IOM/ColorField: Get rid of useless threads

Generate bitmap in Draw() lazily. Removed liblayout stuff. Support for
Haiku layout methods. Fixed some bugs with selecting red/green/blue
as fixed values (ticket #10574).
This commit is contained in:
Stephan Aßmus
2015-07-19 23:20:11 +02:00
parent 44046ca5cd
commit 0ebc8ac6ef
2 changed files with 380 additions and 435 deletions
@@ -1,9 +1,9 @@
/* /*
* Copyright 2001 Werner Freytag - please read to the LICENSE file * Copyright 2001 Werner Freytag - please read to the LICENSE file
* *
* Copyright 2002-2006, Stephan Aßmus <[email protected]> * Copyright 2002-2006, Stephan Aßmus <[email protected]>
* All rights reserved. * All rights reserved.
* *
*/ */
#include "ColorField.h" #include "ColorField.h"
@@ -11,16 +11,17 @@
#include <stdio.h> #include <stdio.h>
#include <Bitmap.h> #include <Bitmap.h>
#include <ControlLook.h>
#include <LayoutUtils.h>
#include <OS.h> #include <OS.h>
#include <Region.h> #include <Region.h>
#include <Window.h> #include <Window.h>
#include "selected_color_mode.h"
#include "support_ui.h" #include "support_ui.h"
#include "rgb_hsv.h" #include "rgb_hsv.h"
#define round(x) (int)(x+.5) #define round(x) (int)(x +.5)
enum { enum {
MSG_UPDATE = 'Updt', MSG_UPDATE = 'Updt',
@@ -30,105 +31,77 @@ enum {
#define MAX_Y 255 #define MAX_Y 255
// constructor // constructor
ColorField::ColorField(BPoint offset_point, selected_color_mode mode, ColorField::ColorField(BPoint offsetPoint, SelectedColorMode mode,
float fixed_value, orientation orient) float fixedValue, orientation orient, border_style border)
: BControl(BRect(0.0, 0.0, MAX_X + 4.0, MAX_Y + 4.0).OffsetToCopy(offset_point), : BControl(BRect(0.0, 0.0, MAX_X + 4.0, MAX_Y + 4.0)
"ColorField", "", new BMessage(MSG_COLOR_FIELD), .OffsetToCopy(offsetPoint),
B_FOLLOW_LEFT | B_FOLLOW_TOP, "ColorField", "", new BMessage(MSG_COLOR_FIELD),
B_WILL_DRAW | B_FRAME_EVENTS), B_FOLLOW_LEFT | B_FOLLOW_TOP, B_WILL_DRAW | B_FRAME_EVENTS)
fMode(mode),
fFixedValue(fixed_value),
fOrientation(orient),
fMarkerPosition(0.0, 0.0),
fLastMarkerPosition(-1.0, -1.0),
fMouseDown(false),
fUpdateThread(B_ERROR),
fUpdatePort(B_ERROR)
{ {
SetViewColor(B_TRANSPARENT_32_BIT); _Init(mode, fixedValue, orient, border);
FrameResized(Bounds().Width(), Bounds().Height());
}
for (int i = 0; i < 2; ++i) { // constructor
fBgBitmap[i] = new BBitmap(Bounds(), B_RGB32, true); ColorField::ColorField(SelectedColorMode mode, float fixedValue,
orientation orient, border_style border)
fBgBitmap[i]->Lock(); : BControl("ColorField", "", new BMessage(MSG_COLOR_FIELD),
fBgView[i] = new BView(Bounds(), "", B_FOLLOW_NONE, B_WILL_DRAW); B_WILL_DRAW | B_FRAME_EVENTS)
fBgBitmap[i]->AddChild(fBgView[i]); {
fBgView[i]->SetOrigin(2.0, 2.0); _Init(mode, fixedValue, orient, border);
fBgBitmap[i]->Unlock();
}
_DrawBorder();
fUpdatePort = create_port(100, "color field update port");
fUpdateThread = spawn_thread(ColorField::_UpdateThread,
"color field update thread", 10, this);
resume_thread(fUpdateThread);
// Update(3);
} }
// destructor // destructor
ColorField::~ColorField() ColorField::~ColorField()
{ {
if (fUpdatePort >= B_OK) delete fBitmap;
delete_port(fUpdatePort);
if (fUpdateThread >= B_OK)
kill_thread(fUpdateThread);
delete fBgBitmap[0];
delete fBgBitmap[1];
} }
#if LIB_LAYOUT // MinSize
// layoutprefs BSize
minimax ColorField::MinSize()
ColorField::layoutprefs()
{ {
if (fOrientation == B_VERTICAL) { BSize minSize;
mpm.mini.x = 4 + MAX_X / 17; if (fOrientation == B_VERTICAL)
mpm.mini.y = 4 + MAX_Y / 5; minSize = BSize(4 + MAX_X / 17, 4 + MAX_Y / 5);
} else { else
mpm.mini.x = 4 + MAX_X / 5; minSize = BSize(4 + MAX_X / 5, 4 + MAX_Y / 17);
mpm.mini.y = 4 + MAX_Y / 17;
}
mpm.maxi.x = 4 + MAX_X;
mpm.maxi.y = 4 + MAX_Y;
mpm.weight = 1.0; return BLayoutUtils::ComposeSize(ExplicitMinSize(), minSize);
return mpm;
} }
// layout // PreferredSize
BRect BSize
ColorField::layout(BRect frame) ColorField::PreferredSize()
{ {
MoveTo(frame.LeftTop()); return BLayoutUtils::ComposeSize(ExplicitPreferredSize(), MinSize());
}
// reposition marker
fMarkerPosition.x *= (frame.Width() - 4.0) / (Bounds().Width() - 4.0); // MaxSize
fMarkerPosition.y *= (frame.Height() - 4.0) / (Bounds().Height() - 4.0); BSize
ColorField::MaxSize()
ResizeTo(frame.Width(), frame.Height()); {
_DrawBorder(); BSize maxSize(4 + MAX_X, 4 + MAX_Y);
Update(3); return BLayoutUtils::ComposeSize(ExplicitMaxSize(), maxSize);
return Frame(); // return BLayoutUtils::ComposeSize(ExplicitMaxSize(),
// BSize(B_SIZE_UNLIMITED, B_SIZE_UNLIMITED));
} }
#endif // LIB_LAYOUT
// Invoke // Invoke
status_t status_t
ColorField::Invoke(BMessage *msg) ColorField::Invoke(BMessage* message)
{ {
if (!msg) if (message == NULL)
msg = Message(); message = Message();
msg->RemoveName("value"); if (message == NULL)
return BControl::Invoke(message);
message->RemoveName("value");
float v1 = 0; float v1 = 0;
float v2 = 0; float v2 = 0;
switch (fMode) { switch (fMode) {
case R_SELECTED: case R_SELECTED:
case G_SELECTED: case G_SELECTED:
@@ -146,7 +119,7 @@ ColorField::Invoke(BMessage *msg)
v2 = 1.0 - fMarkerPosition.x / Width(); v2 = 1.0 - fMarkerPosition.x / Width();
} }
break; break;
case S_SELECTED: case S_SELECTED:
case V_SELECTED: case V_SELECTED:
v1 = fMarkerPosition.x / Width() * 6.0; v1 = fMarkerPosition.x / Width() * 6.0;
@@ -154,38 +127,73 @@ ColorField::Invoke(BMessage *msg)
break; break;
} }
msg->AddFloat("value", v1); message->AddFloat("value", v1);
msg->AddFloat("value", v2); message->AddFloat("value", v2);
return BControl::Invoke(msg); return BControl::Invoke(message);
} }
// AttachedToWindow // AttachedToWindow
void void
ColorField::AttachedToWindow() ColorField::AttachedToWindow()
{ {
Update(3);
} }
// Draw // Draw
void void
ColorField::Draw(BRect updateRect) ColorField::Draw(BRect updateRect)
{ {
Update(0); if (fBitmapDirty && fBitmap != NULL) {
_FillBitmap(fBitmap, fMode, fFixedValue, fOrientation);
fBitmapDirty = false;
}
BRect bounds = Bounds();
// Frame
if (fBorderStyle == B_FANCY_BORDER) {
rgb_color color = LowColor();
be_control_look->DrawTextControlBorder(this, bounds, updateRect,
color);
BRegion region(bounds);
ConstrainClippingRegion(&region);
}
// Color field fill
if (fBitmap != NULL)
DrawBitmap(fBitmap, bounds.LeftTop());
else {
SetHighColor(255, 0, 0);
FillRect(bounds);
}
// Marker
SetHighColor(0, 0, 0);
StrokeEllipse(fMarkerPosition + bounds.LeftTop(), 5.0, 5.0);
SetHighColor(255.0, 255.0, 255.0);
StrokeEllipse(fMarkerPosition + bounds.LeftTop(), 4.0, 4.0);
}
// FrameResized
void
ColorField::FrameResized(float width, float height)
{
BRect r = _BitmapRect();
_AllocBitmap(r.IntegerWidth() + 1, r.IntegerHeight() + 1);
Invalidate();
} }
// MouseDown // MouseDown
void void
ColorField::MouseDown(BPoint where) ColorField::MouseDown(BPoint where)
{ {
Window()->Activate();
fMouseDown = true; fMouseDown = true;
SetMouseEventMask(B_POINTER_EVENTS, B_SUSPEND_VIEW_FOCUS|B_LOCK_WINDOW_FOCUS ); SetMouseEventMask(B_POINTER_EVENTS,
PositionMarkerAt( where ); B_SUSPEND_VIEW_FOCUS | B_LOCK_WINDOW_FOCUS);
PositionMarkerAt(where);
if (Message()) { if (Message() != NULL) {
BMessage message(*Message()); BMessage message(*Message());
message.AddBool("begin", true); message.AddBool("begin", true);
Invoke(&message); Invoke(&message);
@@ -202,83 +210,36 @@ ColorField::MouseUp(BPoint where)
// MouseMoved // MouseMoved
void void
ColorField::MouseMoved(BPoint where, uint32 code, const BMessage *a_message) ColorField::MouseMoved(BPoint where, uint32 transit,
const BMessage* dragMessage)
{ {
if (a_message || !fMouseDown ) { if (dragMessage != NULL || !fMouseDown ) {
BView::MouseMoved( where, code, a_message); BView::MouseMoved(where, transit, dragMessage);
return; return;
} }
PositionMarkerAt(where); PositionMarkerAt(where);
Invoke(); Invoke();
} }
// Update
void
ColorField::Update(int depth)
{
// depth: 0 = only onscreen redraw, 1 = only cursor 1, 2 = full update part 2, 3 = full
if (depth == 3) {
write_port(fUpdatePort, MSG_UPDATE, NULL, 0);
return;
}
if (depth >= 1) {
fBgBitmap[1]->Lock();
fBgView[1]->DrawBitmap( fBgBitmap[0], BPoint(-2.0, -2.0) );
fBgView[1]->SetHighColor( 0, 0, 0 );
fBgView[1]->StrokeEllipse( fMarkerPosition, 5.0, 5.0 );
fBgView[1]->SetHighColor( 255.0, 255.0, 255.0 );
fBgView[1]->StrokeEllipse( fMarkerPosition, 4.0, 4.0 );
fBgView[1]->Sync();
fBgBitmap[1]->Unlock();
}
if (depth != 0 && depth != 2 && fMarkerPosition != fLastMarkerPosition) {
fBgBitmap[1]->Lock();
DrawBitmap( fBgBitmap[1],
BRect(-3.0, -3.0, 7.0, 7.0).OffsetByCopy(fMarkerPosition),
BRect(-3.0, -3.0, 7.0, 7.0).OffsetByCopy(fMarkerPosition));
DrawBitmap( fBgBitmap[1],
BRect(-3.0, -3.0, 7.0, 7.0).OffsetByCopy(fLastMarkerPosition),
BRect(-3.0, -3.0, 7.0, 7.0).OffsetByCopy(fLastMarkerPosition));
fLastMarkerPosition = fMarkerPosition;
fBgBitmap[1]->Unlock();
} else
DrawBitmap(fBgBitmap[1]);
}
// SetModeAndValue // SetModeAndValue
void void
ColorField::SetModeAndValue(selected_color_mode mode, float fixed_value) ColorField::SetModeAndValue(SelectedColorMode mode, float fixedValue)
{ {
float R(0), G(0), B(0); float R(0), G(0), B(0);
float H(0), S(0), V(0); float H(0), S(0), V(0);
fBgBitmap[0]->Lock();
float width = Width(); float width = Width();
float height = Height(); float height = Height();
switch (fMode) { switch (fMode) {
case R_SELECTED: { case R_SELECTED: {
R = fFixedValue * 255; R = fFixedValue * 255;
G = round(fMarkerPosition.x / width * 255.0); G = round(fMarkerPosition.x / width * 255.0);
B = round(255.0 - fMarkerPosition.y / height * 255.0); B = round(255.0 - fMarkerPosition.y / height * 255.0);
}; break; }; break;
case G_SELECTED: { case G_SELECTED: {
R = round(fMarkerPosition.x / width * 255.0); R = round(fMarkerPosition.x / width * 255.0);
G = fFixedValue * 255; G = fFixedValue * 255;
@@ -314,17 +275,14 @@ ColorField::SetModeAndValue(selected_color_mode mode, float fixed_value)
HSV_to_RGB(H, S, V, R, G, B); HSV_to_RGB(H, S, V, R, G, B);
R *= 255.0; G *= 255.0; B *= 255.0; R *= 255.0; G *= 255.0; B *= 255.0;
} }
rgb_color color = { (uint8)round(R), (uint8)round(G), (uint8)round(B),
255 };
fBgBitmap[0]->Unlock(); rgb_color color = { round(R), round(G), round(B), 255 };
if (fFixedValue != fixed_value || fMode != mode) { if (fFixedValue != fixedValue || fMode != mode) {
fFixedValue = fixed_value; fFixedValue = fixedValue;
fMode = mode; fMode = mode;
Update(3); _Update();
} }
SetMarkerToColor(color); SetMarkerToColor(color);
@@ -332,11 +290,11 @@ ColorField::SetModeAndValue(selected_color_mode mode, float fixed_value)
// SetFixedValue // SetFixedValue
void void
ColorField::SetFixedValue(float fixed_value) ColorField::SetFixedValue(float fixedValue)
{ {
if (fFixedValue != fixed_value) { if (fFixedValue != fixedValue) {
fFixedValue = fixed_value; fFixedValue = fixedValue;
Update(3); _Update();
} }
} }
@@ -345,285 +303,269 @@ void
ColorField::SetMarkerToColor(rgb_color color) ColorField::SetMarkerToColor(rgb_color color)
{ {
float h, s, v; float h, s, v;
RGB_to_HSV( (float)color.red / 255.0, (float)color.green / 255.0, (float)color.blue / 255.0, h, s, v ); RGB_to_HSV(color.red / 255.0, color.green / 255.0, color.blue / 255.0,
h, s, v );
fLastMarkerPosition = fMarkerPosition; fLastMarkerPosition = fMarkerPosition;
float width = Width(); float width = Width();
float height = Height(); float height = Height();
switch (fMode) { switch (fMode) {
case R_SELECTED: { case R_SELECTED:
fMarkerPosition = BPoint(color.green / 255.0 * width, fMarkerPosition = BPoint(color.green / 255.0 * width,
(255.0 - color.blue) / 255.0 * height); (255.0 - color.blue) / 255.0 * height);
} break; break;
case G_SELECTED: {
fMarkerPosition = BPoint(color.red / 255.0 * width,
(255.0 - color.blue) / 255.0 * height);
} break;
case B_SELECTED: { case G_SELECTED:
fMarkerPosition = BPoint(color.red / 255.0 * width, fMarkerPosition = BPoint(color.red / 255.0 * width,
(255.0 - color.green) / 255.0 * height); (255.0 - color.blue) / 255.0 * height);
} break; break;
case H_SELECTED: { case B_SELECTED:
fMarkerPosition = BPoint(color.red / 255.0 * width,
(255.0 - color.green) / 255.0 * height);
break;
case H_SELECTED:
if (fOrientation == B_VERTICAL) if (fOrientation == B_VERTICAL)
fMarkerPosition = BPoint(s * width, height - v * height); fMarkerPosition = BPoint(s * width, height - v * height);
else else
fMarkerPosition = BPoint(width - v * width, s * height); fMarkerPosition = BPoint(width - v * width, s * height);
} break; break;
case S_SELECTED: {
fMarkerPosition = BPoint(h / 6.0 * width, height - v * height);
} break;
case V_SELECTED: { case S_SELECTED:
fMarkerPosition = BPoint(h / 6.0 * width, height - v * height);
break;
case V_SELECTED:
fMarkerPosition = BPoint( h / 6.0 * width, height - s * height); fMarkerPosition = BPoint( h / 6.0 * width, height - s * height);
} break; break;
} }
Update(1); Invalidate();
} }
// PositionMarkerAt // PositionMarkerAt
void void
ColorField::PositionMarkerAt( BPoint where ) ColorField::PositionMarkerAt(BPoint where)
{ {
BRect rect = Bounds().InsetByCopy( 2.0, 2.0 ).OffsetToCopy(0.0, 0.0); BRect rect = _BitmapRect();
where = BPoint(max_c(min_c(where.x - 2.0, rect.right), 0.0), where.ConstrainTo(rect);
max_c(min_c(where.y - 2.0, rect.bottom), 0.0) ); where -= rect.LeftTop();
fLastMarkerPosition = fMarkerPosition; fLastMarkerPosition = fMarkerPosition;
fMarkerPosition = where; fMarkerPosition = where;
Update(1); Invalidate();
} }
// Width // Width
float float
ColorField::Width() const ColorField::Width() const
{ {
return Bounds().IntegerWidth() + 1 - 4; return _BitmapRect().IntegerWidth() + 1;
} }
// Height // Height
float float
ColorField::Height() const ColorField::Height() const
{ {
return Bounds().IntegerHeight() + 1 - 4; return _BitmapRect().IntegerHeight() + 1;
} }
// set_bits // set_bits
void static inline void
set_bits(uint8* bits, uint8 r, uint8 g, uint8 b) set_bits(uint8* bits, uint8 r, uint8 g, uint8 b)
{ {
bits[0] = b; bits[0] = b;
bits[1] = g; bits[1] = g;
bits[2] = r; bits[2] = r;
// bits[3] = 255; bits[3] = 255;
} }
// _UpdateThread // _Init
status_t
ColorField::_UpdateThread(void* data)
{
// initializing
ColorField* colorField = (ColorField *)data;
bool looperLocked = colorField->LockLooper();
BBitmap* bitmap = colorField->fBgBitmap[0];
port_id port = colorField->fUpdatePort;
orientation orient = colorField->fOrientation;
if (looperLocked)
colorField->UnlockLooper();
float h, s, v, r, g, b;
int R, G, B;
// drawing
int32 msg_code;
char msg_buffer;
while (true) {
port_info info;
do {
read_port(port, &msg_code, &msg_buffer, sizeof(msg_buffer));
get_port_info(port, &info);
} while (info.queue_count);
if (colorField->LockLooper()) {
uint colormode = colorField->fMode;
float fixedvalue = colorField->fFixedValue;
int width = (int)colorField->Width();
int height = (int)colorField->Height();
colorField->UnlockLooper();
bitmap->Lock();
//bigtime_t now = system_time();
uint8* bits = (uint8*)bitmap->Bits();
uint32 bpr = bitmap->BytesPerRow();
// offset 2 pixels from top and left
bits += 2 * 4 + 2 * bpr;
switch (colormode) {
case R_SELECTED: {
R = round(fixedvalue * 255);
for (int y = height; y >= 0; y--) {
uint8* bitsHandle = bits;
int B = y / height * 255;
for (int x = 0; x <= width; ++x) {
int G = x / width * 255;
set_bits(bitsHandle, R, G, B);
bitsHandle += 4;
}
bits += bpr;
}
}; break;
case G_SELECTED: {
G = round(fixedvalue * 255);
for (int y = height; y >= 0; y--) {
uint8* bitsHandle = bits;
int B = y / height * 255;
for (int x = 0; x <= width; ++x) {
int R = x / width * 255;
set_bits(bitsHandle, R, G, B);
bitsHandle += 4;
}
bits += bpr;
}
}; break;
case B_SELECTED: {
B = round(fixedvalue * 255);
for (int y = height; y >= 0; y--) {
uint8* bitsHandle = bits;
int G = y / height * 255;
for (int x = 0; x <= width; ++x) {
int R = x / width * 255;
set_bits(bitsHandle, R, G, B);
bitsHandle += 4;
}
bits += bpr;
}
}; break;
case H_SELECTED: {
h = fixedvalue;
if (orient == B_VERTICAL) {
for (int y = 0; y <= height; ++y) {
v = (float)(height - y) / height;
uint8* bitsHandle = bits;
for (int x = 0; x <= width; ++x) {
s = (float)x / width;
HSV_to_RGB( h, s, v, r, g, b );
set_bits(bitsHandle, round(r * 255.0), round(g * 255.0), round(b * 255.0));
bitsHandle += 4;
}
bits += bpr;
}
} else {
for (int y = 0; y <= height; ++y) {
s = (float)y / height;
uint8* bitsHandle = bits;
for (int x = 0; x <= width; ++x) {
v = (float)(width - x) / width;
HSV_to_RGB( h, s, v, r, g, b );
set_bits(bitsHandle, round(r * 255.0), round(g * 255.0), round(b * 255.0));
bitsHandle += 4;
}
bits += bpr;
}
}
}; break;
case S_SELECTED: {
s = fixedvalue;
for (int y = 0; y <= height; ++y) {
v = (float)(height - y) / height;
uint8* bitsHandle = bits;
for (int x = 0; x <= width; ++x) {
h = 6.0 / width * x;
HSV_to_RGB( h, s, v, r, g, b );
set_bits(bitsHandle, round(r * 255.0), round(g * 255.0), round(b * 255.0));
bitsHandle += 4;
}
bits += bpr;
}
}; break;
case V_SELECTED: {
v = fixedvalue;
for (int y = 0; y <= height; ++y) {
s = (float)(height - y) / height;
uint8* bitsHandle = bits;
for (int x = 0; x <= width; ++x) {
h = 6.0 / width * x;
HSV_to_RGB( h, s, v, r, g, b );
set_bits(bitsHandle, round(r * 255.0), round(g * 255.0), round(b * 255.0));
bitsHandle += 4;
}
bits += bpr;
}
}; break;
}
//printf("color field update: %lld\n", system_time() - now);
bitmap->Unlock();
if (colorField->LockLooper()) {
colorField->Update(2);
colorField->UnlockLooper();
}
}
}
return B_OK;
}
// _DrawBorder
void void
ColorField::_DrawBorder() ColorField::_Init(SelectedColorMode mode, float fixedValue,
orientation orient, border_style border)
{ {
bool looperLocked = LockLooper(); fMode = mode;
fFixedValue = fixedValue;
fBgBitmap[1]->Lock(); fOrientation = orient;
fBorderStyle = border;
rgb_color background = ui_color(B_PANEL_BACKGROUND_COLOR); fMarkerPosition = BPoint(0.0, 0.0);
rgb_color shadow = tint_color(background, B_DARKEN_1_TINT); fLastMarkerPosition = BPoint(-1.0, -1.0);
rgb_color darkShadow = tint_color(background, B_DARKEN_3_TINT); fMouseDown = false;
rgb_color light = tint_color(background, B_LIGHTEN_MAX_TINT);
BRect r(fBgView[1]->Bounds()); fBitmap = NULL;
r.OffsetBy(-2.0, -2.0); fBitmapDirty = true;
BRegion region(r);
fBgView[1]->ConstrainClippingRegion(&region);
r = Bounds(); SetViewColor(B_TRANSPARENT_COLOR);
r.OffsetBy(-2.0, -2.0); SetLowColor(ui_color(B_PANEL_BACKGROUND_COLOR));
}
stroke_frame(fBgView[1], r, shadow, shadow, light, light);
r.InsetBy(1.0, 1.0); // _AllocBitmap
stroke_frame(fBgView[1], r, darkShadow, darkShadow, background, background); void
r.InsetBy(1.0, 1.0); ColorField::_AllocBitmap(int32 width, int32 height)
{
region.Set(r); if (width < 2 || height < 2)
fBgView[1]->ConstrainClippingRegion(&region); return;
fBgBitmap[1]->Unlock(); delete fBitmap;
fBitmap = new BBitmap(BRect(0, 0, width - 1, height - 1), 0, B_RGB32);
if (looperLocked)
UnlockLooper(); fBitmapDirty = true;
}
// _Update
void
ColorField::_Update()
{
fBitmapDirty = true;
Invalidate();
}
// _BitmapRect
BRect
ColorField::_BitmapRect() const
{
BRect r = Bounds();
if (fBorderStyle == B_FANCY_BORDER)
r.InsetBy(2, 2);
return r;
}
// _FillBitmap
void
ColorField::_FillBitmap(BBitmap* bitmap, SelectedColorMode mode,
float fixedValue, orientation orient) const
{
int32 width = bitmap->Bounds().IntegerWidth();
int32 height = bitmap->Bounds().IntegerHeight();
uint32 bpr = bitmap->BytesPerRow();
//bigtime_t now = system_time();
uint8* bits = (uint8*)bitmap->Bits();
float r = 0;
float g = 0;
float b = 0;
float h;
float s;
float v;
switch (mode) {
case R_SELECTED:
r = round(fixedValue * 255);
for (int y = height; y >= 0; y--) {
uint8* bitsHandle = bits;
b = y * 255 / height;
for (int32 x = 0; x <= width; x++) {
g = x * 255 / width;
set_bits(bitsHandle, (uint8)r, (uint8)g, (uint8)b);
bitsHandle += 4;
}
bits += bpr;
}
break;
case G_SELECTED:
g = round(fixedValue * 255);
for (int y = height; y >= 0; y--) {
uint8* bitsHandle = bits;
b = y * 255 / height;
for (int x = 0; x <= width; x++) {
r = x * 255 / width;
set_bits(bitsHandle, (uint8)r, (uint8)g, (uint8)b);
bitsHandle += 4;
}
bits += bpr;
}
break;
case B_SELECTED:
b = round(fixedValue * 255);
for (int y = height; y >= 0; y--) {
uint8* bitsHandle = bits;
g = y * 255 / height;
for (int x = 0; x <= width; ++x) {
r = x * 255 / width;
set_bits(bitsHandle, (uint8)r, (uint8)g, (uint8)b);
bitsHandle += 4;
}
bits += bpr;
}
break;
case H_SELECTED:
h = fixedValue;
if (orient == B_VERTICAL) {
for (int y = 0; y <= height; ++y) {
v = (float)(height - y) / height;
uint8* bitsHandle = bits;
for (int x = 0; x <= width; ++x) {
s = (float)x / width;
HSV_to_RGB(h, s, v, r, g, b);
set_bits(bitsHandle,
round(r * 255.0),
round(g * 255.0),
round(b * 255.0));
bitsHandle += 4;
}
bits += bpr;
}
} else {
for (int y = 0; y <= height; ++y) {
s = (float)y / height;
uint8* bitsHandle = bits;
for (int x = 0; x <= width; ++x) {
v = (float)(width - x) / width;
HSV_to_RGB(h, s, v, r, g, b);
set_bits(bitsHandle,
round(r * 255.0),
round(g * 255.0),
round(b * 255.0));
bitsHandle += 4;
}
bits += bpr;
}
}
break;
case S_SELECTED:
s = fixedValue;
for (int y = 0; y <= height; ++y) {
v = (float)(height - y) / height;
uint8* bitsHandle = bits;
for (int x = 0; x <= width; ++x) {
h = 6.0 / width * x;
HSV_to_RGB(h, s, v, r, g, b);
set_bits(bitsHandle,
round(r * 255.0),
round(g * 255.0),
round(b * 255.0));
bitsHandle += 4;
}
bits += bpr;
}
break;
case V_SELECTED:
v = fixedValue;
for (int y = 0; y <= height; ++y) {
s = (float)(height - y) / height;
uint8* bitsHandle = bits;
for (int x = 0; x <= width; ++x) {
h = 6.0 / width * x;
HSV_to_RGB(h, s, v, r, g, b);
set_bits(bitsHandle,
round(r * 255.0),
round(g * 255.0),
round(b * 255.0));
bitsHandle += 4;
}
bits += bpr;
}
break;
}
} }
@@ -1,21 +1,17 @@
/* /*
* Copyright 2001 Werner Freytag - please read to the LICENSE file * Copyright 2001 Werner Freytag - please read to the LICENSE file
* *
* Copyright 2002-2006, Stephan Aßmus <[email protected]> * Copyright 2002-2006, Stephan Aßmus <[email protected]>
* All rights reserved. * All rights reserved.
* *
*/ */
#ifndef _COLOR_FIELD_H #ifndef COLOR_FIELD_H
#define _COLOR_FIELD_H #define COLOR_FIELD_H
#include <Control.h> #include <Control.h>
#if LIB_LAYOUT #include "SelectedColorMode.h"
# include <layout.h>
#endif
#include "selected_color_mode.h"
enum { enum {
MSG_COLOR_FIELD = 'ColF', MSG_COLOR_FIELD = 'ColF',
@@ -23,69 +19,76 @@ enum {
class BBitmap; class BBitmap;
class ColorField : class ColorField : public BControl {
#if LIB_LAYOUT public:
public MView,
#endif
public BControl {
public:
ColorField(BPoint offset_point, ColorField(BPoint offset_point,
selected_color_mode mode, SelectedColorMode mode, float fixedValue,
float fixed_value, orientation orient = B_VERTICAL,
orientation orient = B_VERTICAL); border_style border = B_FANCY_BORDER);
ColorField(SelectedColorMode mode,
float fixedValue,
orientation orient = B_VERTICAL,
border_style border = B_FANCY_BORDER);
virtual ~ColorField(); virtual ~ColorField();
// MView // BControl interface
#if LIB_LAYOUT virtual BSize MinSize();
virtual minimax layoutprefs(); virtual BSize PreferredSize();
virtual BRect layout(BRect frame); virtual BSize MaxSize();
#endif
// BControl virtual status_t Invoke(BMessage* message = NULL);
virtual status_t Invoke(BMessage *msg = NULL);
virtual void AttachedToWindow(); virtual void AttachedToWindow();
virtual void Draw(BRect updateRect); virtual void Draw(BRect updateRect);
virtual void FrameResized(float width, float height);
virtual void MouseDown(BPoint where); virtual void MouseDown(BPoint where);
virtual void MouseUp(BPoint where); virtual void MouseUp(BPoint where);
virtual void MouseMoved(BPoint where, uint32 code, virtual void MouseMoved(BPoint where, uint32 code,
const BMessage* message); const BMessage* dragMessage);
// ColorField // ColorField
void Update(int depth); void SetModeAndValue(SelectedColorMode mode,
float fixedValue);
void SetModeAndValue(selected_color_mode mode, float fixed_value); void SetFixedValue(float fixedValue);
void SetFixedValue(float fixed_value);
float FixedValue() const float FixedValue() const
{ return fFixedValue; } { return fFixedValue; }
void SetMarkerToColor( rgb_color color ); void SetMarkerToColor(rgb_color color);
void PositionMarkerAt( BPoint where ); void PositionMarkerAt(BPoint where);
float Width() const; float Width() const;
float Height() const; float Height() const;
bool IsTracking() const bool IsTracking() const
{ return fMouseDown; } { return fMouseDown; }
private: private:
static status_t _UpdateThread(void* data); void _Init(SelectedColorMode mode,
void _DrawBorder(); float fixedValue, orientation orient,
border_style border);
selected_color_mode fMode; void _AllocBitmap(int32 width, int32 height);
void _Update();
BRect _BitmapRect() const;
void _FillBitmap(BBitmap* bitmap,
SelectedColorMode mode,
float fixedValue, orientation orient) const;
private:
SelectedColorMode fMode;
float fFixedValue; float fFixedValue;
orientation fOrientation; orientation fOrientation;
border_style fBorderStyle;
BPoint fMarkerPosition; BPoint fMarkerPosition;
BPoint fLastMarkerPosition; BPoint fLastMarkerPosition;
bool fMouseDown; bool fMouseDown;
BBitmap* fBgBitmap[2]; BBitmap* fBitmap;
BView* fBgView[2]; bool fBitmapDirty;
thread_id fUpdateThread;
port_id fUpdatePort;
}; };
#endif #endif // COLOR_FIELD_H