BeDecorator: update close and zoom button gradients

... to better match BeOS.

Up until this point we have drawn buttons with a perfectly smooth
linear gradient that was nicely provided by Stippi. However, BeOS
used a more stylized gradient instead. This commit seeks to
reproduce this stylized gradient on BeDecorator adjusting itself
for larger button sizes.

Consolidate and correct colors. button, light1, light2, and
shadow1 colors are the same on close and zoom buttons. Zoom has
a lighter shadow2 than close button. Try to get as close to the
colors used on BeOS as possible. Added comments indicating the
colors used on BeOS in active and inactive states for future
reference.

light1 color stays grayscale if grayscale, otherwise skews
non-blue. This replicates how BeOS worked.

Fill with window tab color before drawing: lose B_TRANSPARENT.

Undraw the bottom left and top right corners of bitmaps in the
unpressed state. BeOS did not do this (usually), but it should
have as it closes the ring.

Define a bunch of bitmaps and use them as stencils to write into
ServerBitmaps 1 or 2 colors at a time.

Update close and zoom button down states. When the button is
pressed rotate bitmap by 180° by reading the source bitmap in
forwards while writing destination bitmap out backwards. This
allows the dark part to be draw in the top left while the light
parts are drawn in the bottom right. (opposite of unpressed)

Don't draw the parts of the big zoom square that are obscured by
the small square.

private _CreateTemporaryBitmap() method stolen from AlphaMask.cpp
to create temporary ServerBitmaps and zero them out. Store the
pointers on the BeDecorator class and then release them in the
destructor method when the class object is deleted.

Initialize the ServerBitmaps in the ctor and set fCStatus. On
failure set to B_NO_MEMORY and fallback to drawing a linear
gradiant. This will most likely never happen but just in case
it does we want to avoid crashing.

A few 80-line char fixes

Change-Id: Ic81837aa387f05b04dda3e1ff76fdf103c93f8e8
This commit is contained in:
John Scipione
2018-07-19 14:01:51 +00:00
committed by waddlesplash
parent d8d6c65576
commit 3123432674
2 changed files with 528 additions and 79 deletions
@@ -52,6 +52,77 @@ static const float kBorderResizeLength = 22.0;
static const float kResizeKnobSize = 18.0;
static const unsigned char f = 0xff; // way to write 0xff shorter
static const unsigned char kInnerShadowBits[] = {
f, f, f, f, f, f, f, f, f, 0,
f, f, f, f, f, f, 0, f, 0, f,
f, f, f, f, f, 0, f, 0, f, 0,
f, f, f, f, 0, f, 0, 0, 0, 0,
f, f, f, 0, f, 0, 0, 0, 0, 0,
f, f, 0, f, 0, 0, 0, 0, 0, 0,
f, 0, f, 0, 0, 0, 0, 0, 0, 0,
f, f, 0, 0, 0, 0, 0, 0, 0, 0,
f, 0, f, 0, 0, 0, 0, 0, 0, 0,
0, f, 0, 0, 0, 0, 0, 0, 0, 0
};
static const unsigned char kOuterShadowBits[] = {
f, f, f, f, f, f, f, f, f, f,
f, f, f, f, f, f, f, f, f, f,
f, f, f, f, f, f, f, f, f, f,
f, f, f, f, f, f, f, f, f, f,
f, f, f, f, f, f, f, f, f, 0,
f, f, f, f, f, f, f, 0, 0, 0,
f, f, f, f, f, f, 0, f, 0, 0,
f, f, f, f, f, 0, f, 0, 0, 0,
f, f, f, f, f, 0, 0, 0, 0, 0,
f, f, f, f, 0, 0, 0, 0, 0, 0
};
static const unsigned char kBigInnerShadowBits[] = {
f, f, f, f, f, f, f,
f, f, f, f, f, f, 0,
f, f, f, f, f, 0, 0,
f, f, f, f, 0, f, 0,
f, f, f, 0, f, 0, 0,
f, f, 0, f, 0, 0, 0,
f, 0, 0, 0, 0, 0, 0
};
static const unsigned char kBigOuterShadowBits[] = {
f, f, f, f, f, f, f,
f, f, f, f, f, f, 0,
f, f, f, f, f, f, 0,
f, f, f, f, f, f, 0,
f, f, f, f, f, f, 0,
f, f, f, f, f, f, 0,
f, 0, 0, 0, 0, 0, 0
};
static const unsigned char kSmallInnerShadowBits[] = {
f, f, f, 0, 0,
f, f, 0, f, 0,
f, 0, f, 0, 0,
0, f, 0, 0, 0,
0, 0, 0, 0, 0
};
static const unsigned char kSmallOuterShadowBits[] = {
f, f, f, f, f,
f, f, f, f, f,
f, f, f, f, f,
f, f, f, f, 0,
f, f, 0, 0, 0
};
static const unsigned char kGlintBits[] = {
0, f, 0,
f, 0, f,
0, f, f
};
// #pragma mark - BeDecorAddOn
@@ -78,11 +149,24 @@ BeDecorAddOn::_AllocateDecorator(DesktopSettings& settings, BRect rect,
BeDecorator::BeDecorator(DesktopSettings& settings, BRect rect,
Desktop* desktop)
:
SATDecorator(settings, rect, desktop)
SATDecorator(settings, rect, desktop),
fCStatus(B_NO_INIT)
{
STRACE(("BeDecorator:\n"));
STRACE(("\tFrame (%.1f,%.1f,%.1f,%.1f)\n",
rect.left, rect.top, rect.right, rect.bottom));
fCloseBitmap = _CreateTemporaryBitmap(BRect(0, 0, 9, 9));
fBigZoomBitmap = _CreateTemporaryBitmap(BRect(0, 0, 6, 6));
fSmallZoomBitmap = _CreateTemporaryBitmap(BRect(0, 0, 4, 4));
fGlintBitmap = _CreateTemporaryBitmap(BRect(0, 0, 2, 2));
// glint bitmap is used by close and zoom buttons
if (fCloseBitmap == NULL || fBigZoomBitmap == NULL
|| fSmallZoomBitmap == NULL || fGlintBitmap == NULL) {
fCStatus = B_NO_MEMORY;
} else
fCStatus = B_OK;
}
@@ -90,6 +174,18 @@ BeDecorator::~BeDecorator()
{
STRACE(("BeDecorator: ~BeDecorator()\n"));
//delete[] fFrameColors;
if (fCloseBitmap != NULL)
fCloseBitmap->ReleaseReference();
if (fBigZoomBitmap != NULL)
fBigZoomBitmap->ReleaseReference();
if (fSmallZoomBitmap != NULL)
fSmallZoomBitmap->ReleaseReference();
if (fGlintBitmap != NULL)
fGlintBitmap->ReleaseReference();
}
@@ -150,8 +246,10 @@ BeDecorator::GetComponentColors(Component component, uint8 highlight,
case COMPONENT_CLOSE_BUTTON:
case COMPONENT_ZOOM_BUTTON:
if (highlight == HIGHLIGHT_STACK_AND_TILE) {
_colors[COLOR_BUTTON] = tint_color(fFocusTabColor, B_DARKEN_1_TINT);
_colors[COLOR_BUTTON_LIGHT] = tint_color(fFocusTabColorLight, B_DARKEN_1_TINT);
_colors[COLOR_BUTTON] = tint_color(fFocusTabColor,
B_DARKEN_1_TINT);
_colors[COLOR_BUTTON_LIGHT] = tint_color(fFocusTabColorLight,
B_DARKEN_1_TINT);
} else if (tab && tab->buttonFocus) {
_colors[COLOR_BUTTON] = fFocusTabColor;
_colors[COLOR_BUTTON_LIGHT] = fFocusTabColorLight;
@@ -294,7 +392,8 @@ BeDecorator::_DrawFrame(BRect invalid)
}
}
// right
if (invalid.Intersects(fRightBorder.InsetByCopy(0, -fBorderWidth))) {
if (invalid.Intersects(
fRightBorder.InsetByCopy(0, -fBorderWidth))) {
ComponentColors colors;
_GetComponentColors(COMPONENT_RIGHT_BORDER, colors, fTopTab);
@@ -319,7 +418,8 @@ BeDecorator::_DrawFrame(BRect invalid)
fDrawingEngine->StrokeLine(BPoint(r.left + i, r.top + i),
BPoint(r.right - i, r.top + i), colors[i * 2]);
}
if (fTitleBarRect.IsValid() && fTopTab->look != kLeftTitledWindowLook) {
if (fTitleBarRect.IsValid()
&& fTopTab->look != kLeftTitledWindowLook) {
// grey along the bottom of the tab
// (overwrites "white" from frame)
fDrawingEngine->StrokeLine(
@@ -445,18 +545,23 @@ BeDecorator::_DrawFrame(BRect invalid)
case B_MODAL_WINDOW_LOOK:
case kLeftTitledWindowLook:
{
if (!invalid.Intersects(BRect(fRightBorder.right - kBorderResizeLength,
fBottomBorder.bottom - kBorderResizeLength, fRightBorder.right - 1,
fBottomBorder.bottom - 1)))
if (!invalid.Intersects(BRect(fRightBorder.right
- kBorderResizeLength,
fBottomBorder.bottom - kBorderResizeLength,
fRightBorder.right - 1, fBottomBorder.bottom - 1))) {
break;
}
fDrawingEngine->StrokeLine(
BPoint(fRightBorder.left, fBottomBorder.bottom - kBorderResizeLength),
BPoint(fRightBorder.right - 1, fBottomBorder.bottom - kBorderResizeLength),
fDrawingEngine->StrokeLine(BPoint(fRightBorder.left,
fBottomBorder.bottom - kBorderResizeLength),
BPoint(fRightBorder.right - 1,
fBottomBorder.bottom - kBorderResizeLength),
colors[0]);
fDrawingEngine->StrokeLine(
BPoint(fRightBorder.right - kBorderResizeLength, fBottomBorder.top),
BPoint(fRightBorder.right - kBorderResizeLength, fBottomBorder.bottom - 1),
BPoint(fRightBorder.right - kBorderResizeLength,
fBottomBorder.top),
BPoint(fRightBorder.right - kBorderResizeLength,
fBottomBorder.bottom - 1),
colors[0]);
break;
}
@@ -594,8 +699,8 @@ BeDecorator::_DrawTitle(Decorator::Tab* _tab, BRect r)
fDrawingEngine->SetFont(fDrawState.Font());
fDrawingEngine->DrawString(tab->truncatedTitle.String(), tab->truncatedTitleLength,
titlePos);
fDrawingEngine->DrawString(tab->truncatedTitle.String(),
tab->truncatedTitleLength, titlePos);
fDrawingEngine->SetDrawingMode(B_OP_COPY);
}
@@ -775,6 +880,10 @@ ServerBitmap*
BeDecorator::_GetBitmapForButton(Decorator::Tab* tab, Component item,
bool down, int32 width, int32 height)
{
uint8* data;
size_t size;
size_t offset;
// TODO: the list of shared bitmaps is never freed
struct decorator_bitmap {
Component item;
@@ -790,11 +899,38 @@ BeDecorator::_GetBitmapForButton(Decorator::Tab* tab, Component item,
static BLocker sBitmapListLock("decorator lock", true);
static decorator_bitmap* sBitmapList = NULL;
// BeOS R5 colors
// button: active: 255, 203, 0 inactive: 232, 232, 232
// light1: active: 255, 238, 0 inactive: 255, 255, 255
// light2: active: 255, 255, 26 inactive: 255, 255, 255
// shadow1: active: 235, 183, 0 inactive: 211, 211, 211
// shadow2 is a bit lighter on zoom than on close button
ComponentColors colors;
_GetComponentColors(item, colors, tab);
const rgb_color buttonColor(colors[COLOR_BUTTON]);
bool isGrayscale = buttonColor.red == buttonColor.green
&& buttonColor.green == buttonColor.blue;
rgb_color buttonColorLight1(buttonColor);
buttonColorLight1.red = std::min(255, buttonColor.red + 35),
buttonColorLight1.green = std::min(255, buttonColor.green + 35),
buttonColorLight1.blue = std::min(255, buttonColor.blue
+ (isGrayscale ? 35 : 0));
// greyscale color stays grayscale
rgb_color buttonColorLight2(buttonColor);
buttonColorLight2.red = std::min(255, buttonColor.red + 52),
buttonColorLight2.green = std::min(255, buttonColor.green + 52),
buttonColorLight2.blue = std::min(255, buttonColor.blue + 26);
rgb_color buttonColorShadow1(buttonColor);
buttonColorShadow1.red = std::max(0, buttonColor.red - 21),
buttonColorShadow1.green = std::max(0, buttonColor.green - 21),
buttonColorShadow1.blue = std::max(0, buttonColor.blue - 21);
BAutolock locker(sBitmapListLock);
// search our list for a matching bitmap
@@ -817,8 +953,9 @@ BeDecorator::_GetBitmapForButton(Decorator::Tab* tab, Component item,
if (sBitmapDrawingEngine == NULL)
sBitmapDrawingEngine = new(std::nothrow) BitmapDrawingEngine();
if (sBitmapDrawingEngine == NULL
|| sBitmapDrawingEngine->SetSize(width, height) != B_OK)
|| sBitmapDrawingEngine->SetSize(width, height) != B_OK) {
return NULL;
}
BRect rect(0, 0, width - 1, height - 1);
@@ -828,92 +965,375 @@ BeDecorator::_GetBitmapForButton(Decorator::Tab* tab, Component item,
switch (item) {
case COMPONENT_CLOSE_BUTTON:
{
rgb_color buttonColorLight1(buttonColor);
buttonColorLight1.red = std::min(255, buttonColor.red + 32),
buttonColorLight1.green = std::min(255, buttonColor.green + 32),
buttonColorLight1.blue = std::min(255, buttonColor.blue + 32);
rgb_color buttonColorLight2(buttonColor);
buttonColorLight2.red = std::min(255, buttonColor.red + 64),
buttonColorLight2.green = std::min(255, buttonColor.green + 64),
buttonColorLight2.blue = std::min(255, buttonColor.blue + 64);
rgb_color buttonColorShadow1(buttonColor);
buttonColorShadow1.red = std::max(0, buttonColor.red - 36),
buttonColorShadow1.green = std::max(0, buttonColor.green - 36),
buttonColorShadow1.blue = std::max(0, buttonColor.blue - 36);
// BeOS R5 shadow2: active: 183, 131, 0 inactive: 160, 160, 160
rgb_color buttonColorShadow2(buttonColor);
buttonColorShadow2.red = std::max(0, buttonColor.red - 72),
buttonColorShadow2.green = std::max(0, buttonColor.green - 72),
buttonColorShadow2.blue = std::max(0, buttonColor.blue - 72);
_DrawBlendedRect(sBitmapDrawingEngine, rect, tab->closePressed,
buttonColorLight2, buttonColorLight1, buttonColor,
buttonColorShadow1);
// fill the background
sBitmapDrawingEngine->FillRect(rect, buttonColor);
// draw outer bevel
_DrawBevelRect(sBitmapDrawingEngine, rect, tab->closePressed,
buttonColorLight2, buttonColorShadow2);
if (!tab->closePressed) {
// undraw bottom left and top right corners
sBitmapDrawingEngine->StrokePoint(rect.LeftBottom(),
buttonColor);
sBitmapDrawingEngine->StrokePoint(rect.RightTop(),
buttonColor);
}
if (fCStatus != B_OK) {
// If we ran out of memory while initializing bitmaps
// fall back to a linear gradient.
rect.InsetBy(1, 1);
_DrawBlendedRect(sBitmapDrawingEngine, rect, tab->closePressed,
buttonColorLight2, buttonColorLight1, buttonColor,
buttonColorShadow1);
break;
}
// inset by bevel
rect.InsetBy(2, 2);
// fill bg
sBitmapDrawingEngine->FillRect(rect, buttonColorLight1);
// treat background color as transparent
sBitmapDrawingEngine->SetDrawingMode(B_OP_OVER);
sBitmapDrawingEngine->SetLowColor(buttonColorLight1);
if (tab->closePressed) {
// Draw glint in bottom right, then combined inner and outer
// shadow in top left.
// Read the source bitmap in forward while writing the
// destination in reverse to rotate the bitmap by 180°.
data = fGlintBitmap->Bits();
size = sizeof(kGlintBits);
for (size_t i = 0; i < size; i++) {
offset = (size - 1 - i) * 4;
if (kGlintBits[i] == 0) {
// draw glint color
data[offset + 0] = buttonColorLight2.blue;
data[offset + 1] = buttonColorLight2.green;
data[offset + 2] = buttonColorLight2.red;
} else {
// draw background color
data[offset + 0] = buttonColorLight1.blue;
data[offset + 1] = buttonColorLight1.green;
data[offset + 2] = buttonColorLight1.red;
}
}
// glint is 3x3
const BRect rightBottom(BRect(rect.right - 2, rect.bottom - 2,
rect.right, rect.bottom));
sBitmapDrawingEngine->DrawBitmap(fGlintBitmap,
fGlintBitmap->Bounds(), rightBottom);
data = fCloseBitmap->Bits();
size = sizeof(kOuterShadowBits);
for (size_t i = 0; i < size; i++) {
offset = (size - 1 - i) * 4;
if (kOuterShadowBits[i] == 0) {
// draw outer shadow
data[offset + 0] = buttonColorShadow1.blue;
data[offset + 1] = buttonColorShadow1.green;
data[offset + 2] = buttonColorShadow1.red;
} else if (kInnerShadowBits[i] == 0) {
// draw inner shadow
data[offset + 0] = buttonColor.blue;
data[offset + 1] = buttonColor.green;
data[offset + 2] = buttonColor.red;
} else {
// draw background color
data[offset + 0] = buttonColorLight1.blue;
data[offset + 1] = buttonColorLight1.green;
data[offset + 2] = buttonColorLight1.red;
}
}
// shadow is 10x10
const BRect leftTop(rect.left, rect.top,
rect.left + 9, rect.top + 9);
sBitmapDrawingEngine->DrawBitmap(fCloseBitmap,
fCloseBitmap->Bounds(), leftTop);
} else {
// draw glint, then draw combined outer and inner shadows
data = fGlintBitmap->Bits();
size = sizeof(kGlintBits);
for (size_t i = 0; i < size; i++) {
offset = i * 4 + 0;
if (kGlintBits[i] == 0) {
// draw glint color
data[offset + 0] = buttonColorLight2.blue;
data[offset + 1] = buttonColorLight2.green;
data[offset + 2] = buttonColorLight2.red;
} else {
// draw background color
data[offset + 0] = buttonColorLight1.blue;
data[offset + 1] = buttonColorLight1.green;
data[offset + 2] = buttonColorLight1.red;
}
}
// glint is 3x3
const BRect leftTop(rect.left, rect.top,
rect.left + 2, rect.top + 2);
sBitmapDrawingEngine->DrawBitmap(fGlintBitmap,
fGlintBitmap->Bounds(), leftTop);
data = fCloseBitmap->Bits();
size = sizeof(kOuterShadowBits);
for (size_t i = 0; i < size; i++) {
offset = i * 4 + 0;
if (kOuterShadowBits[i] == 0) {
// draw outer shadow
data[offset + 0] = buttonColorShadow1.blue;
data[offset + 1] = buttonColorShadow1.green;
data[offset + 2] = buttonColorShadow1.red;
} else if (kInnerShadowBits[i] == 0) {
// draw inner shadow
data[offset + 0] = buttonColor.blue;
data[offset + 1] = buttonColor.green;
data[offset + 2] = buttonColor.red;
} else {
// draw background color
data[offset + 0] = buttonColorLight1.blue;
data[offset + 1] = buttonColorLight1.green;
data[offset + 2] = buttonColorLight1.red;
}
}
// shadow is 10x10
const BRect rightBottom(BRect(rect.right - 9, rect.bottom - 9,
rect.right, rect.bottom));
sBitmapDrawingEngine->DrawBitmap(fCloseBitmap,
fCloseBitmap->Bounds(), rightBottom);
}
// restore drawing mode
sBitmapDrawingEngine->SetDrawingMode(B_OP_COPY);
break;
}
case COMPONENT_ZOOM_BUTTON:
{
sBitmapDrawingEngine->FillRect(rect, B_TRANSPARENT_COLOR);
// init the background
rgb_color buttonColorLight1(buttonColor);
buttonColorLight1.red = std::min(255, buttonColor.red + 32),
buttonColorLight1.green = std::min(255, buttonColor.green + 32),
buttonColorLight1.blue = std::min(255, buttonColor.blue + 32);
rgb_color buttonColorLight2(buttonColor);
buttonColorLight2.red = std::min(255, buttonColor.red + 64),
buttonColorLight2.green = std::min(255, buttonColor.green + 64),
buttonColorLight2.blue = std::min(255, buttonColor.blue + 64);
rgb_color buttonColorShadow1(buttonColor);
buttonColorShadow1.red = std::max(0, buttonColor.red - 22),
buttonColorShadow1.green = std::max(0, buttonColor.green - 23),
buttonColorShadow1.blue = std::max(0, buttonColor.blue - 5);
// BeOS R5 shadow2: active: 210, 158, 0 inactive: 187, 187, 187
rgb_color buttonColorShadow2(buttonColor);
buttonColorShadow2.red = std::max(0, buttonColor.red - 45),
buttonColorShadow2.green = std::max(0, buttonColor.green - 47),
buttonColorShadow2.blue = std::max(0, buttonColor.blue - 10);
buttonColorShadow2.green = std::max(0, buttonColor.green - 45),
buttonColorShadow2.blue = std::max(0, buttonColor.blue - 45);
// fill the background
sBitmapDrawingEngine->FillRect(rect, buttonColor);
// big rect
BRect zoomRect = rect;
zoomRect.left += floorf(width * 3.0f / 14.0f);
zoomRect.top += floorf(height * 3.0f / 14.0f);
_DrawBlendedRect(sBitmapDrawingEngine, zoomRect, tab->zoomPressed,
buttonColorLight2, buttonColorLight1, buttonColor,
buttonColorShadow1);
_DrawBevelRect(sBitmapDrawingEngine, zoomRect, tab->zoomPressed,
buttonColorLight2, buttonColorShadow2);
BRect bigRect(rect);
bigRect.left += floorf(width * 3.0f / 14.0f);
bigRect.top += floorf(height * 3.0f / 14.0f);
// small rect
BRect smallRect(rect);
smallRect.right -= floorf(width * 5.0f / 14.0f);
smallRect.bottom -= floorf(height * 5.0f / 14.0f);
zoomRect = rect;
zoomRect.right -= floorf(width * 5.0f / 14.0f);
zoomRect.bottom -= floorf(height * 5.0f / 14.0f);
_DrawBlendedRect(sBitmapDrawingEngine, zoomRect, tab->zoomPressed,
buttonColorLight2, buttonColorLight1, buttonColor,
buttonColorShadow1);
_DrawBevelRect(sBitmapDrawingEngine, zoomRect, tab->zoomPressed,
// draw big rect bevel
_DrawBevelRect(sBitmapDrawingEngine, bigRect, tab->zoomPressed,
buttonColorLight2, buttonColorShadow2);
// Fill in the right top and bottom right corners with buttonColor
sBitmapDrawingEngine->StrokeLine(zoomRect.RightTop(),
zoomRect.RightTop(), buttonColor);
sBitmapDrawingEngine->StrokeLine(zoomRect.LeftBottom(),
zoomRect.LeftBottom(), buttonColor);
if (!tab->zoomPressed) {
// undraw bottom left and top right corners
sBitmapDrawingEngine->StrokePoint(bigRect.LeftBottom(),
buttonColor);
sBitmapDrawingEngine->StrokePoint(bigRect.RightTop(),
buttonColor);
}
if (fCStatus != B_OK) {
// If we ran out of memory while initializing bitmaps
// fall back to a linear gradient.
// already drew bigRect bevel, fill with linear gradient
bigRect.InsetBy(1, 1);
_DrawBlendedRect(sBitmapDrawingEngine, bigRect,
tab->zoomPressed, buttonColorLight2, buttonColorLight1,
buttonColor, buttonColorShadow1);
// draw small rect bevel then fill with linear gradient
_DrawBevelRect(sBitmapDrawingEngine, smallRect,
tab->zoomPressed, buttonColorLight2, buttonColorShadow2);
if (!tab->zoomPressed) {
// undraw bottom left and top right corners
sBitmapDrawingEngine->StrokePoint(smallRect.LeftBottom(),
buttonColor);
sBitmapDrawingEngine->StrokePoint(smallRect.RightTop(),
buttonColor);
}
smallRect.InsetBy(1, 1);
_DrawBlendedRect(sBitmapDrawingEngine, smallRect,
tab->zoomPressed, buttonColorLight2, buttonColorLight1,
buttonColor, buttonColorShadow1);
break;
}
// inset past bevel
bigRect.InsetBy(2, 2);
// fill big rect bg
sBitmapDrawingEngine->FillRect(bigRect, buttonColorLight1);
// some elements are covered by the small rect
// so only draw the parts that get shown
if (tab->zoomPressed) {
// draw glint
// Read the source bitmap in forward while writing the
// destination in reverse to rotate the bitmap by 180°.
data = fGlintBitmap->Bits();
size = sizeof(kGlintBits);
for (size_t i = 0; i < sizeof(kGlintBits); i++) {
offset = (size - 1 - i) * 4;
if (kGlintBits[i] == 0) {
// draw glint
data[offset + 0] = buttonColorLight2.blue;
data[offset + 1] = buttonColorLight2.green;
data[offset + 2] = buttonColorLight2.red;
} else {
// draw background color
data[offset + 0] = buttonColorLight1.blue;
data[offset + 1] = buttonColorLight1.green;
data[offset + 2] = buttonColorLight1.red;
}
}
// glint is 3x3
const BRect rightBottom(BRect(bigRect.right - 2,
bigRect.bottom - 2, bigRect.right, bigRect.bottom));
sBitmapDrawingEngine->DrawBitmap(fGlintBitmap,
fGlintBitmap->Bounds(), rightBottom);
} else {
// draw combined inner and outer shadow
data = fBigZoomBitmap->Bits();
size = sizeof(kBigOuterShadowBits);
for (size_t i = 0; i < sizeof(kBigOuterShadowBits); i++) {
offset = i * 4;
if (kBigOuterShadowBits[i] == 0) {
// draw outer shadow
data[offset + 0] = buttonColorShadow1.blue;
data[offset + 1] = buttonColorShadow1.green;
data[offset + 2] = buttonColorShadow1.red;
} else if (kBigInnerShadowBits[i] == 0) {
// draw inner shadow
data[offset + 0] = buttonColor.blue;
data[offset + 1] = buttonColor.green;
data[offset + 2] = buttonColor.red;
} else {
// draw background color
data[offset + 0] = buttonColorLight1.blue;
data[offset + 1] = buttonColorLight1.green;
data[offset + 2] = buttonColorLight1.red;
}
}
// shadow is 7x7
const BRect rightBottom(BRect(bigRect.right - 6,
bigRect.bottom - 6, bigRect.right, bigRect.bottom));
sBitmapDrawingEngine->DrawBitmap(fBigZoomBitmap,
fBigZoomBitmap->Bounds(), rightBottom);
}
sBitmapDrawingEngine->SetDrawingMode(B_OP_COPY);
// draw small rect bevel
_DrawBevelRect(sBitmapDrawingEngine, smallRect, tab->zoomPressed,
buttonColorLight2, buttonColorShadow2);
if (!tab->zoomPressed) {
// undraw bottom left and top right corners
sBitmapDrawingEngine->StrokePoint(smallRect.LeftBottom(),
buttonColor);
sBitmapDrawingEngine->StrokePoint(smallRect.RightTop(),
buttonColor);
}
// inset past bevel
smallRect.InsetBy(2, 2);
// fill small rect bg
sBitmapDrawingEngine->FillRect(smallRect, buttonColorLight1);
// treat background color as transparent
sBitmapDrawingEngine->SetDrawingMode(B_OP_OVER);
sBitmapDrawingEngine->SetLowColor(buttonColorLight1);
// draw small bitmap
data = fSmallZoomBitmap->Bits();
size = sizeof(kSmallOuterShadowBits);
if (tab->zoomPressed) {
// draw combined inner and outer shadow
// Read the source bitmap in forward while writing the
// destination in reverse to rotate the bitmap by 180°.
for (size_t i = 0; i < size; i++) {
offset = (size - 1 - i) * 4;
if (kSmallOuterShadowBits[i] == 0) {
// draw outer shadow
data[offset + 0] = buttonColorShadow1.blue;
data[offset + 1] = buttonColorShadow1.green;
data[offset + 2] = buttonColorShadow1.red;
} else if (kSmallInnerShadowBits[i] == 0) {
// draw inner shadow
data[offset + 0] = buttonColor.blue;
data[offset + 1] = buttonColor.green;
data[offset + 2] = buttonColor.red;
} else {
// draw background color
data[offset + 0] = buttonColorLight1.blue;
data[offset + 1] = buttonColorLight1.green;
data[offset + 2] = buttonColorLight1.red;
}
}
// shadow is 5x5
const BRect smallLeftTop(BRect(smallRect.left,
smallRect.top, smallRect.left + 4, smallRect.top + 4));
sBitmapDrawingEngine->DrawBitmap(fSmallZoomBitmap,
fSmallZoomBitmap->Bounds(), smallLeftTop);
} else {
// draw combined inner and outer shadow
for (size_t i = 0; i < size; i++) {
offset = i * 4;
if (kSmallOuterShadowBits[i] == 0) {
// draw outer shadow
data[offset + 0] = buttonColorShadow1.blue;
data[offset + 1] = buttonColorShadow1.green;
data[offset + 2] = buttonColorShadow1.red;
} else if (kSmallInnerShadowBits[i] == 0) {
// draw inner shadow
data[offset + 0] = buttonColor.blue;
data[offset + 1] = buttonColor.green;
data[offset + 2] = buttonColor.red;
} else {
// draw background color
data[offset + 0] = buttonColorLight1.blue;
data[offset + 1] = buttonColorLight1.green;
data[offset + 2] = buttonColorLight1.red;
}
}
// shadow is 5x5
const BRect smallRightBottom(BRect(smallRect.right - 4,
smallRect.bottom - 4, smallRect.right, smallRect.bottom));
sBitmapDrawingEngine->DrawBitmap(fSmallZoomBitmap,
fSmallZoomBitmap->Bounds(), smallRightBottom);
}
// draw glint last (single pixel)
sBitmapDrawingEngine->StrokePoint(tab->zoomPressed
? smallRect.RightBottom() : smallRect.LeftTop(),
buttonColorLight2);
// restore drawing mode
sBitmapDrawingEngine->SetDrawingMode(B_OP_COPY);
break;
}
@@ -947,6 +1367,26 @@ BeDecorator::_GetBitmapForButton(Decorator::Tab* tab, Component item,
}
ServerBitmap*
BeDecorator::_CreateTemporaryBitmap(BRect bounds) const
{
UtilityBitmap* bitmap = new(std::nothrow) UtilityBitmap(bounds,
B_RGB32, 0);
if (bitmap == NULL)
return NULL;
if (!bitmap->IsValid()) {
delete bitmap;
return NULL;
}
memset(bitmap->Bits(), 0, bitmap->BitsLength());
// background opacity is 0
return bitmap;
}
void
BeDecorator::_GetComponentColors(Component component,
ComponentColors _colors, Decorator::Tab* tab)
@@ -69,9 +69,18 @@ private:
ServerBitmap* _GetBitmapForButton(Decorator::Tab* tab,
Component item, bool down, int32 width,
int32 height);
ServerBitmap* _CreateTemporaryBitmap(BRect bounds) const;
void _GetComponentColors(Component component,
ComponentColors _colors,
Decorator::Tab* tab = NULL);
private:
status_t fCStatus;
ServerBitmap* fCloseBitmap;
ServerBitmap* fBigZoomBitmap;
ServerBitmap* fSmallZoomBitmap;
ServerBitmap* fGlintBitmap;
};