* 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
This commit is contained in:
Michael Lotz 2008-06-13 13:48:33 +00:00
parent 33d85b510b
commit e13a79e005
2 changed files with 201 additions and 67 deletions

View File

@ -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 <WindowPrivate.h>
#include <Autolock.h>
#include <Rect.h>
#include <View.h>
#include <new>
#include <stdio.h>
//#define DEBUG_DECORATOR
#ifdef DEBUG_DECORATOR
# include <stdio.h>
# 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;
}

View File

@ -14,7 +14,7 @@
#include <Region.h>
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