[haiku-commits] haiku: hrev52122 - src/add-ons/decorators/BeDecorator

  • From: waddlesplash <waddlesplash@xxxxxxxxx>
  • To: haiku-commits@xxxxxxxxxxxxx
  • Date: Thu, 19 Jul 2018 10:01:53 -0400 (EDT)

hrev52122 adds 1 changeset to branch 'master'
old head: d8d6c65576e72e28bdc912c600546f6db93e3c4f
new head: 31234326741231bb8d36456ce9dbdccec7ce0e3b
overview: 
https://git.haiku-os.org/haiku/log/?qt=range&q=312343267412+%5Ed8d6c65576e7

----------------------------------------------------------------------------

312343267412: 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

                                     [ John Scipione <jscipione@xxxxxxxxx> ]

----------------------------------------------------------------------------

Revision:    hrev52122
Commit:      31234326741231bb8d36456ce9dbdccec7ce0e3b
URL:         https://git.haiku-os.org/haiku/commit/?id=312343267412
Author:      John Scipione <jscipione@xxxxxxxxx>
Date:        Sun Jul  1 10:03:21 2018 UTC
Committer:   waddlesplash <waddlesplash@xxxxxxxxx>
Commit-Date: Thu Jul 19 14:01:51 2018 UTC

----------------------------------------------------------------------------

2 files changed, 524 insertions(+), 75 deletions(-)
.../decorators/BeDecorator/BeDecorator.cpp       | 590 ++++++++++++++++---
src/add-ons/decorators/BeDecorator/BeDecorator.h |   9 +

----------------------------------------------------------------------------

diff --git a/src/add-ons/decorators/BeDecorator/BeDecorator.cpp 
b/src/add-ons/decorators/BeDecorator/BeDecorator.cpp
index 7423a2bfb1..2c83627e54 100644
--- a/src/add-ons/decorators/BeDecorator/BeDecorator.cpp
+++ b/src/add-ons/decorators/BeDecorator/BeDecorator.cpp
@@ -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);
 
-                       break;
-               }
+                       if (!tab->closePressed) {
+                               // undraw bottom left and top right corners
+                               
sBitmapDrawingEngine->StrokePoint(rect.LeftBottom(),
+                                       buttonColor);
+                               
sBitmapDrawingEngine->StrokePoint(rect.RightTop(),
+                                       buttonColor);
+                       }
 
-               case COMPONENT_ZOOM_BUTTON:
-               {
-                       sBitmapDrawingEngine->FillRect(rect, 
B_TRANSPARENT_COLOR);
-                               // init the background
+                       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);
 
-                       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);
+                               break;
+                       }
 
-                       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);
+                       // 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);
 
-                       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);
+                       break;
+               }
 
+               case COMPONENT_ZOOM_BUTTON:
+               {
+                       // 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);
 
-                       // big rect
+                       // fill the background
+                       sBitmapDrawingEngine->FillRect(rect, buttonColor);
 
-                       BRect zoomRect = rect;
-                       zoomRect.left += floorf(width * 3.0f / 14.0f);
-                       zoomRect.top += floorf(height * 3.0f / 14.0f);
+                       // big rect
+                       BRect bigRect(rect);
+                       bigRect.left += floorf(width * 3.0f / 14.0f);
+                       bigRect.top += floorf(height * 3.0f / 14.0f);
 
-                       _DrawBlendedRect(sBitmapDrawingEngine, zoomRect, 
tab->zoomPressed,
-                               buttonColorLight2, buttonColorLight1, 
buttonColor,
-                               buttonColorShadow1);
+                       // small rect
+                       BRect smallRect(rect);
+                       smallRect.right -= floorf(width * 5.0f / 14.0f);
+                       smallRect.bottom -= floorf(height * 5.0f / 14.0f);
 
-                       _DrawBevelRect(sBitmapDrawingEngine, zoomRect, 
tab->zoomPressed,
+                       // draw big rect bevel
+                       _DrawBevelRect(sBitmapDrawingEngine, bigRect, 
tab->zoomPressed,
                                buttonColorLight2, buttonColorShadow2);
 
-                       // small rect
+                       if (!tab->zoomPressed) {
+                               // undraw bottom left and top right corners
+                               
sBitmapDrawingEngine->StrokePoint(bigRect.LeftBottom(),
+                                       buttonColor);
+                               
sBitmapDrawingEngine->StrokePoint(bigRect.RightTop(),
+                                       buttonColor);
+                       }
 
-                       zoomRect = rect;
-                       zoomRect.right -= floorf(width * 5.0f / 14.0f);
-                       zoomRect.bottom -= floorf(height * 5.0f / 14.0f);
+                       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);
 
-                       _DrawBlendedRect(sBitmapDrawingEngine, zoomRect, 
tab->zoomPressed,
-                               buttonColorLight2, buttonColorLight1, 
buttonColor,
-                               buttonColorShadow1);
+                               break;
+                       }
 
-                       _DrawBevelRect(sBitmapDrawingEngine, zoomRect, 
tab->zoomPressed,
+                       // 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);
 
-                       // 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(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)
diff --git a/src/add-ons/decorators/BeDecorator/BeDecorator.h 
b/src/add-ons/decorators/BeDecorator/BeDecorator.h
index 7ffe242a65..e128c24168 100644
--- a/src/add-ons/decorators/BeDecorator/BeDecorator.h
+++ b/src/add-ons/decorators/BeDecorator/BeDecorator.h
@@ -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;
 };
 
 


Other related posts:

  • » [haiku-commits] haiku: hrev52122 - src/add-ons/decorators/BeDecorator - waddlesplash