From e13a79e00573fcfda5f745b5882897cfe718e320 Mon Sep 17 00:00:00 2001 From: Michael Lotz Date: Fri, 13 Jun 2008 13:48:33 +0000 Subject: [PATCH] * Cache the close and zoom buttons in a blit-ready bitmap so the buttons don't need to be drawn each time an update occurs (switching focus/non-focus or pressed state, involving many graphics card blits and state updates in the drawing subsystem). * Provide a shared list of already present bitmaps. All the default decorators now use the new _GetBitmapForButton static method to get a rendered bitmap of the button for the given size and state (focus, pressed). If a matching bitmap exists it is returned, otherwise a new one is created on demand using a shared BitmapDrawingEngine. * Cache the colors of the tab and frame for both focus and non-focus states to avoid always looking them up. * Added a todo that these bitmaps and the BitmapDrawingEngine are never freed. They should be freed on app_server quit, but as there are only like 12 of them anyway I didn't really bother. * Some cleanup. This should reduce the waste of cycles for just drawing the default decorator buttons quite a bit. Probably the whole tab should be pre-rendered though to also safe the text rendering of the title. git-svn-id: file:///srv/svn/repos/haiku/haiku/trunk@25952 a95241bf-73f2-0310-859d-f6bbb57e9c96 --- src/servers/app/DefaultDecorator.cpp | 247 ++++++++++++++++++++------- src/servers/app/DefaultDecorator.h | 21 ++- 2 files changed, 201 insertions(+), 67 deletions(-) diff --git a/src/servers/app/DefaultDecorator.cpp b/src/servers/app/DefaultDecorator.cpp index c76a6854e6..863ed0daae 100644 --- a/src/servers/app/DefaultDecorator.cpp +++ b/src/servers/app/DefaultDecorator.cpp @@ -12,22 +12,25 @@ #include "DefaultDecorator.h" +#include "BitmapDrawingEngine.h" #include "DesktopSettings.h" #include "DrawingEngine.h" #include "DrawState.h" #include "FontManager.h" #include "PatternHandler.h" +#include "ServerBitmap.h" #include +#include #include #include +#include #include //#define DEBUG_DECORATOR #ifdef DEBUG_DECORATOR -# include # define STRACE(x) printf x #else # define STRACE(x) ; @@ -89,13 +92,27 @@ DefaultDecorator::DefaultDecorator(DesktopSettings& settings, BRect rect, { DefaultDecorator::SetLook(settings, look); + // common colors to both focus and non focus state fFrameColors[0] = (rgb_color){ 152, 152, 152, 255 }; fFrameColors[1] = (rgb_color){ 255, 255, 255, 255 }; - fFrameColors[2] = (rgb_color){ 216, 216, 216, 255 }; - fFrameColors[3] = (rgb_color){ 136, 136, 136, 255 }; fFrameColors[4] = (rgb_color){ 152, 152, 152, 255 }; fFrameColors[5] = (rgb_color){ 96, 96, 96, 255 }; + // state based colors + fFocusFrameColors[0] = (rgb_color){ 216, 216, 216, 255 }; + fFocusFrameColors[1] = (rgb_color){ 136, 136, 136, 255 }; + fNonFocusFrameColors[0] = (rgb_color){ 232, 232, 232, 255 }; + fNonFocusFrameColors[1] = (rgb_color){ 148, 148, 148, 255 }; + + fFocusTabColor = UIColor(B_WINDOW_TAB_COLOR); + fFocusTextColor = UIColor(B_WINDOW_TEXT_COLOR); + fNonFocusTabColor = UIColor(B_WINDOW_INACTIVE_TAB_COLOR); + fNonFocusTextColor = UIColor(B_WINDOW_INACTIVE_TEXT_COLOR); + + fCloseBitmaps[0] = fCloseBitmaps[1] = fCloseBitmaps[2] = fCloseBitmaps[3] + = fZoomBitmaps[0] = fZoomBitmaps[1] = fZoomBitmaps[2] = fZoomBitmaps[3] + = NULL; + // Set appropriate colors based on the current focus value. In this case, each decorator // defaults to not having the focus. _SetFocus(); @@ -435,7 +452,7 @@ DefaultDecorator::Draw(BRect update) _DrawTab(update); } -// Draw + void DefaultDecorator::Draw() { @@ -447,7 +464,7 @@ DefaultDecorator::Draw() _DrawTab(fTabRect); } -// GetSizeLimits + void DefaultDecorator::GetSizeLimits(int32* minWidth, int32* minHeight, int32* maxWidth, int32* maxHeight) const @@ -458,7 +475,7 @@ DefaultDecorator::GetSizeLimits(int32* minWidth, int32* minHeight, *minHeight = (int32)roundf(max_c(*minHeight, fResizeRect.Height() - fBorderWidth)); } -// GetFootprint + void DefaultDecorator::GetFootprint(BRegion *region) { @@ -712,7 +729,7 @@ DefaultDecorator::_DoLayout() } } -// _DrawFrame + void DefaultDecorator::_DrawFrame(BRect invalid) { @@ -903,7 +920,7 @@ DefaultDecorator::_DrawFrame(BRect invalid) } } -// _DrawTab + void DefaultDecorator::_DrawTab(BRect invalid) { @@ -964,16 +981,28 @@ DefaultDecorator::_DrawTab(BRect invalid) _DrawZoom(fZoomRect); } -// _DrawClose + void -DefaultDecorator::_DrawClose(BRect r) +DefaultDecorator::_DrawClose(BRect rect) { - STRACE(("_DrawClose(%f,%f,%f,%f)\n", r.left, r.top, r.right, r.bottom)); - // Just like DrawZoom, but for a close button - _DrawBlendedRect(r, GetClose()); + STRACE(("_DrawClose(%f,%f,%f,%f)\n", rect.left, rect.top, rect.right, + rect.bottom)); + + int32 index = (fButtonFocus ? 0 : 1) + (GetClose() ? 0 : 2); + ServerBitmap *bitmap = fCloseBitmaps[index]; + if (bitmap == NULL) { + bitmap = _GetBitmapForButton(DEC_CLOSE, GetClose(), fButtonFocus, + rect.IntegerWidth(), rect.IntegerHeight(), this); + fCloseBitmaps[index] = bitmap; + } + + if (bitmap == NULL) + return; + + fDrawingEngine->DrawBitmap(bitmap, rect.OffsetToCopy(0, 0), rect); } -// _DrawTitle + void DefaultDecorator::_DrawTitle(BRect r) { @@ -1008,23 +1037,23 @@ DefaultDecorator::_DrawTitle(BRect r) // _DrawZoom void -DefaultDecorator::_DrawZoom(BRect r) +DefaultDecorator::_DrawZoom(BRect rect) { - STRACE(("_DrawZoom(%f,%f,%f,%f)\n", r.left, r.top, r.right, r.bottom)); + STRACE(("_DrawZoom(%f,%f,%f,%f)\n", rect.left, rect.top, rect.right, + rect.bottom)); - float inset = floorf(r.Width() / 4.0); + int32 index = (fButtonFocus ? 0 : 1) + (GetZoom() ? 0 : 2); + ServerBitmap *bitmap = fZoomBitmaps[index]; + if (bitmap == NULL) { + bitmap = _GetBitmapForButton(DEC_ZOOM, GetZoom(), fButtonFocus, + rect.IntegerWidth(), rect.IntegerHeight(), this); + fZoomBitmaps[index] = bitmap; + } - BRect zr(r); - zr.left += inset; - zr.top += inset; - _DrawBlendedRect(zr, GetZoom()); + if (bitmap == NULL) + return; - inset = floorf(r.Width() / 2.1); - - zr = r; - zr.right -= inset; - zr.bottom -= inset; - _DrawBlendedRect(zr, GetZoom()); + fDrawingEngine->DrawBitmap(bitmap, rect.OffsetToCopy(0, 0), rect); } // _SetFocus @@ -1037,21 +1066,17 @@ DefaultDecorator::_SetFocus() if (IsFocus() || ((fLook == B_FLOATING_WINDOW_LOOK || fLook == kLeftTitledWindowLook) && (fFlags & B_AVOID_FOCUS) != 0)) { - fTabColor = UIColor(B_WINDOW_TAB_COLOR); - fTextColor = UIColor(B_WINDOW_TEXT_COLOR); - fButtonHighColor = tint_color(fTabColor, B_LIGHTEN_2_TINT); - fButtonLowColor = tint_color(fTabColor, B_DARKEN_1_TINT); - - fFrameColors[2] = (rgb_color){ 216, 216, 216, 255 }; - fFrameColors[3] = (rgb_color){ 136, 136, 136, 255 }; + fTabColor = fFocusTabColor; + fTextColor = fFocusTextColor; + fFrameColors[2] = fFocusFrameColors[0]; + fFrameColors[3] = fFocusFrameColors[1]; + fButtonFocus = true; } else { - fTabColor = UIColor(B_WINDOW_INACTIVE_TAB_COLOR); - fTextColor = UIColor(B_WINDOW_INACTIVE_TEXT_COLOR); - fButtonHighColor = tint_color(fTabColor, B_LIGHTEN_2_TINT); - fButtonLowColor = tint_color(fTabColor, B_DARKEN_1_TINT); - - fFrameColors[2] = (rgb_color){ 232, 232, 232, 255 }; - fFrameColors[3] = (rgb_color){ 148, 148, 148, 255 }; + fTabColor = fNonFocusTabColor; + fTextColor = fNonFocusTextColor; + fFrameColors[2] = fNonFocusFrameColors[0]; + fFrameColors[3] = fNonFocusFrameColors[1]; + fButtonFocus = false; } fTabColorLight = tint_color(fTabColor, @@ -1060,7 +1085,7 @@ DefaultDecorator::_SetFocus() B_DARKEN_2_TINT); } -// _SetColors + void DefaultDecorator::_SetColors() { @@ -1073,48 +1098,49 @@ DefaultDecorator::_SetColors() \param down The rectangle should be drawn recessed or not */ void -DefaultDecorator::_DrawBlendedRect(BRect r, bool down) +DefaultDecorator::_DrawBlendedRect(DrawingEngine *engine, BRect rect, + bool down, bool focus) { // Actually just draws a blended square - int32 w = r.IntegerWidth(); - int32 h = r.IntegerHeight(); - - rgb_color tempColor; - rgb_color halfColor, startColor, endColor; - float rstep, gstep, bstep; - - int steps = w < h ? w : h; + int32 width = rect.IntegerWidth(); + int32 height = rect.IntegerHeight(); + int32 steps = width < height ? width : height; + rgb_color startColor, endColor; + rgb_color tabColor = focus ? fFocusTabColor : fNonFocusTabColor; if (down) { - startColor = fButtonLowColor; - endColor = fButtonHighColor; + startColor = tint_color(tabColor, B_DARKEN_1_TINT); + endColor = tint_color(tabColor, B_LIGHTEN_2_TINT);; } else { - startColor = fButtonHighColor; - endColor = fButtonLowColor; + startColor = tint_color(tabColor, B_LIGHTEN_2_TINT); + endColor = tint_color(tabColor, B_DARKEN_1_TINT); } - halfColor = make_blend_color(startColor, endColor, 0.5); + rgb_color halfColor = make_blend_color(startColor, endColor, 0.5); - rstep = float(startColor.red - halfColor.red) / steps; - gstep = float(startColor.green - halfColor.green) / steps; - bstep = float(startColor.blue - halfColor.blue) / steps; + float rstep = float(startColor.red - halfColor.red) / steps; + float gstep = float(startColor.green - halfColor.green) / steps; + float bstep = float(startColor.blue - halfColor.blue) / steps; + rgb_color tempColor; for (int32 i = 0; i <= steps; i++) { tempColor.red = uint8(startColor.red - (i * rstep)); tempColor.green = uint8(startColor.green - (i * gstep)); tempColor.blue = uint8(startColor.blue - (i * bstep)); - fDrawingEngine->StrokeLine(BPoint(r.left, r.top + i), - BPoint(r.left + i, r.top), tempColor); + engine->StrokeLine(BPoint(rect.left, rect.top + i), + BPoint(rect.left + i, rect.top), tempColor); tempColor.red = uint8(halfColor.red - (i * rstep)); tempColor.green = uint8(halfColor.green - (i * gstep)); tempColor.blue = uint8(halfColor.blue - (i * bstep)); - fDrawingEngine->StrokeLine(BPoint(r.left + steps, r.top + i), - BPoint(r.left + i, r.top + steps), tempColor); + engine->StrokeLine(BPoint(rect.left + steps, rect.top + i), + BPoint(rect.left + i, rect.top + steps), tempColor); } - fDrawingEngine->StrokeRect(r, fFrameColors[3]); + + engine->StrokeRect(rect, + focus ? fFocusFrameColors[1] : fNonFocusFrameColors[1]); } // _GetButtonSizeAndOffset @@ -1187,3 +1213,96 @@ DefaultDecorator::_LayoutTabItems(const BRect& tabRect) fDrawState.Font().TruncateString(&fTruncatedTitle, B_TRUNCATE_END, size); fTruncatedTitleLength = fTruncatedTitle.Length(); } + + +ServerBitmap * +DefaultDecorator::_GetBitmapForButton(int32 item, bool down, bool focus, + int32 width, int32 height, DefaultDecorator *object) +{ + // TODO: the list of shared bitmaps is never freed + struct decorator_bitmap { + int32 item; + bool down; + bool focus; + int32 width; + int32 height; + UtilityBitmap * bitmap; + decorator_bitmap * next; + }; + + static BLocker sBitmapListLock("decorator lock", true); + static decorator_bitmap *sBitmapList = NULL; + BAutolock locker(sBitmapListLock); + + // search our list for a matching bitmap + decorator_bitmap *current = sBitmapList; + while (current) { + if (current->item == item && current->down == down + && current->focus == focus && current->width == width + && current->height == height) { + return current->bitmap; + } + + current = current->next; + } + + static BitmapDrawingEngine *sBitmapDrawingEngine = NULL; + + // didn't find any bitmap, create a new one + if (sBitmapDrawingEngine == NULL) + sBitmapDrawingEngine = new(std::nothrow) BitmapDrawingEngine(); + if (sBitmapDrawingEngine == NULL + || sBitmapDrawingEngine->SetSize(width, height) != B_OK) + return NULL; + + BRect rect(0, 0, width - 1, height - 1); + sBitmapDrawingEngine->FillRect(rect, + focus ? object->fFocusTabColor : object->fNonFocusTabColor); + + STRACE(("DefaultDecorator creating bitmap for %s %sfocus %s at size %ldx%ld\n", + item == DEC_CLOSE ? "close" : "zoom", focus ? "" : "non-", + down ? "down" : "up", width, height)); + switch (item) { + case DEC_CLOSE: + object->_DrawBlendedRect(sBitmapDrawingEngine, rect, down, focus); + break; + + case DEC_ZOOM: + { + float inset = floorf(width / 4.0); + BRect zoomRect(rect); + zoomRect.left += inset; + zoomRect.top += inset; + object->_DrawBlendedRect(sBitmapDrawingEngine, zoomRect, down, focus); + + inset = floorf(width / 2.1); + zoomRect = rect; + zoomRect.right -= inset; + zoomRect.bottom -= inset; + object->_DrawBlendedRect(sBitmapDrawingEngine, zoomRect, down, focus); + break; + } + } + + UtilityBitmap *bitmap = sBitmapDrawingEngine->ExportToBitmap(width, height, + B_RGB32); + if (bitmap == NULL) + return NULL; + + // bitmap ready, put it into the list + decorator_bitmap *entry = new(std::nothrow) decorator_bitmap; + if (entry == NULL) { + delete bitmap; + return NULL; + } + + entry->item = item; + entry->down = down; + entry->focus = focus; + entry->width = width; + entry->height = height; + entry->bitmap = bitmap; + entry->next = sBitmapList; + sBitmapList = entry; + return bitmap; +} diff --git a/src/servers/app/DefaultDecorator.h b/src/servers/app/DefaultDecorator.h index 0e6c659013..07e0140862 100644 --- a/src/servers/app/DefaultDecorator.h +++ b/src/servers/app/DefaultDecorator.h @@ -14,7 +14,7 @@ #include class Desktop; - +class ServerBitmap; class DefaultDecorator: public Decorator { public: @@ -68,20 +68,35 @@ class DefaultDecorator: public Decorator { virtual void _SetColors(); private: - void _DrawBlendedRect(BRect r, bool down); + void _DrawBlendedRect(DrawingEngine *engine, + BRect rect, bool down, bool focus); void _GetButtonSizeAndOffset(const BRect& tabRect, float* offset, float* size, float* inset) const; void _LayoutTabItems(const BRect& tabRect); +static ServerBitmap * _GetBitmapForButton(int32 item, bool down, + bool focus, int32 width, int32 height, + DefaultDecorator *object); + rgb_color fButtonHighColor; rgb_color fButtonLowColor; - rgb_color fTextColor; rgb_color fTabColor; + rgb_color fFocusTabColor; + rgb_color fNonFocusTabColor; + rgb_color fTextColor; + rgb_color fFocusTextColor; + rgb_color fNonFocusTextColor; rgb_color fTabColorLight; rgb_color fTabColorShadow; rgb_color fFrameColors[6]; + rgb_color fFocusFrameColors[2]; + rgb_color fNonFocusFrameColors[2]; + + bool fButtonFocus; + ServerBitmap * fCloseBitmaps[4]; + ServerBitmap * fZoomBitmaps[4]; // Individual rects for handling window frame // rendering the proper way