* completed my changes to DrawState handling, the current DrawingState

of the active ViewLayer is now always mirrored in the Painter instance
  of a ServerWindow, so that it doesn't need to be synced on every drawing
  command, this was previously incomplete for font handling
* removed the DrawState parameter from all the DrawingEngine functions
* adjusted ServerWindow and ServerPicture accordingly
* made sure that string related functions used by non-drawing related
  parts (ServerApp, Decorator) don't interfere with the current drawing
  state
* moved AS_SYNC handling from _DispatchViewMessage to _DispatchMessage,
  it is actually a window message and doesn't require fCurrentLayer to
  be valid
* fixed bug #1300, fCurrentLayer was not updated when a ViewLayer was
  deleted by client request which happened to be fCurrentLayer (I am now
  handling it so that the parent becomes the current layer, could be
  wrong)
* AGGTextRenderer is no longer using it's own scanline, which should save
  a few bytes RAM, the Painter already had such an object
* StringWidth() in AGGTextRenderer is now taking the escapement_delta into
  account
* Painter::StrokeLine() doesn't need to check the clipping as much, since
  that is already done in DrawingEngine
* if a ServerWindow message is not handled because fCurrentLayer is NULL,
  a reply is sent in case the messages needs it (client window could
  freeze otherwise, waiting for the reply for ever)
* removed unused AS_SET_FONT and AS_SET_FONT_SIZE
* added automatic RGBColor -> rgb_color conversion to RGBColor.h
* minor cleanup for 80 char/line limit



git-svn-id: file:///srv/svn/repos/haiku/haiku/trunk@21685 a95241bf-73f2-0310-859d-f6bbb57e9c96
This commit is contained in:
Stephan Aßmus 2007-07-22 19:48:27 +00:00
parent d069bd6917
commit 38287e02af
16 changed files with 303 additions and 272 deletions

View File

@ -212,8 +212,6 @@ enum {
AS_FILL_TRIANGLE,
AS_DRAW_STRING,
AS_SET_FONT,
AS_SET_FONT_SIZE,
AS_SYNC,

View File

@ -639,8 +639,9 @@ DefaultDecorator::_DoLayout()
fMinTabSize += offset + size;
// fMaxTabSize contains fMinWidth + the width required for the title
fMaxTabSize = fDrawingEngine ? ceilf(fDrawingEngine->StringWidth(Title(), strlen(Title()),
&fDrawState)) : 0.0;
fMaxTabSize = fDrawingEngine ?
ceilf(fDrawingEngine->StringWidth(Title(), strlen(Title()),
fDrawState.Font())) : 0.0;
if (fMaxTabSize > 0.0)
fMaxTabSize += fTextOffset;
fMaxTabSize += fMinTabSize;
@ -967,8 +968,9 @@ DefaultDecorator::_DrawTitle(BRect r)
{
STRACE(("_DrawTitle(%f,%f,%f,%f)\n", r.left, r.top, r.right, r.bottom));
fDrawState.SetHighColor(fTextColor);
fDrawState.SetLowColor(fTabColor);
fDrawingEngine->SetHighColor(fTextColor.GetColor32());
fDrawingEngine->SetLowColor(fTabColor.GetColor32());
fDrawingEngine->SetFont(fDrawState.Font());
// figure out position of text
font_height fontHeight;
@ -987,7 +989,8 @@ DefaultDecorator::_DrawTitle(BRect r)
: fTabRect.bottom - fTextOffset;
}
fDrawingEngine->DrawString(fTruncatedTitle.String(), fTruncatedTitleLength, titlePos, &fDrawState);
fDrawingEngine->DrawString(fTruncatedTitle.String(), fTruncatedTitleLength,
titlePos);
}
// _DrawZoom

View File

@ -200,8 +200,6 @@ string_for_message_code(uint32 code, BString& string)
case AS_FILL_TRIANGLE: string = "AS_FILL_TRIANGLE"; break;
case AS_DRAW_STRING: string = "AS_DRAW_STRING"; break;
case AS_SET_FONT: string = "AS_SET_FONT"; break;
case AS_SET_FONT_SIZE: string = "AS_SET_FONT_SIZE"; break;
case AS_SYNC: string = "AS_SYNC"; break;

View File

@ -53,6 +53,10 @@ class RGBColor {
bool operator==(const RGBColor& color) const;
bool operator!=(const rgb_color& color) const;
bool operator!=(const RGBColor& color) const;
// conversion to rgb_color
operator rgb_color() const
{ return fColor32; }
bool IsTransparentMagic() const;

View File

@ -1401,7 +1401,8 @@ ServerApp::_DispatchMessage(int32 code, BPrivate::LinkReceiver& link)
int32 lengthArray[numStrings];
char *stringArray[numStrings];
for (int32 i = 0; i < numStrings; i++) {
// This version of ReadString allocates the strings, we free them below
// This version of ReadString allocates the strings, we free
// them below
link.ReadString(&stringArray[i], (size_t *)&lengthArray[i]);
}
@ -1415,13 +1416,14 @@ ServerApp::_DispatchMessage(int32 code, BPrivate::LinkReceiver& link)
if (!stringArray[i] || lengthArray[i] <= 0)
widthArray[i] = 0.0;
else {
widthArray[i] = fDesktop->GetDrawingEngine()->StringWidth(stringArray[i], lengthArray[i], font);
// NOTE: The line below will return the exact same thing. However,
// the line above uses the AGG rendering backend, for which glyph caching
// actually works. It is about 20 times faster!
// TODO: I've disabled the AGG version for now, as it produces a dead lock
// (font use), that I am currently too lazy to investigate...
// widthArray[i] = font.StringWidth(stringArray[i], lengthArray[i]);
widthArray[i] = fDesktop->GetDrawingEngine()->
StringWidth(stringArray[i], lengthArray[i], font);
// NOTE: The line below will return the exact same thing.
// However, the line above uses the AGG rendering backend,
// for which glyph caching actually works. It is about
// 20 times faster!
// widthArray[i] = font.StringWidth(stringArray[i],
// lengthArray[i]);
}
}

View File

@ -339,6 +339,7 @@ ServerFont::GetTransformedFace(bool rotate, bool shear) const
FT_Set_Transform(face, &smatrix, NULL);
}
// fStyle will be unlocked in PutTransformedFace()
return face;
}
@ -433,7 +434,8 @@ ServerFont::GetEdges(const char charArray[], int32 numChars,
status_t
ServerFont::GetEscapements(const char charArray[], int32 numChars,
escapement_delta delta, BPoint escapementArray[], BPoint offsetArray[]) const
escapement_delta delta, BPoint escapementArray[],
BPoint offsetArray[]) const
{
if (!charArray || numChars <= 0 || !escapementArray)
return B_BAD_DATA;

View File

@ -131,7 +131,7 @@ ShapePainter::Draw(ViewLayer *view, BRect frame, bool filled)
}
view->Window()->GetDrawingEngine()->DrawShape(frame, opCount, opList, ptCount, ptList,
view->CurrentState(), filled);
filled);
}
}
@ -182,7 +182,7 @@ stroke_line(ViewLayer *view, BPoint start, BPoint end)
{
view->ConvertToScreenForDrawing(&start);
view->ConvertToScreenForDrawing(&end);
view->Window()->GetDrawingEngine()->StrokeLine(start, end, view->CurrentState());
view->Window()->GetDrawingEngine()->StrokeLine(start, end);
}
@ -190,7 +190,7 @@ static void
stroke_rect(ViewLayer *view, BRect rect)
{
view->ConvertToScreenForDrawing(&rect);
view->Window()->GetDrawingEngine()->StrokeRect(rect, view->CurrentState());
view->Window()->GetDrawingEngine()->StrokeRect(rect);
}
@ -198,7 +198,7 @@ static void
fill_rect(ViewLayer *view, BRect rect)
{
view->ConvertToScreenForDrawing(&rect);
view->Window()->GetDrawingEngine()->FillRect(rect, view->CurrentState());
view->Window()->GetDrawingEngine()->FillRect(rect);
}
@ -206,7 +206,8 @@ static void
stroke_round_rect(ViewLayer *view, BRect rect, BPoint radii)
{
view->ConvertToScreenForDrawing(&rect);
view->Window()->GetDrawingEngine()->DrawRoundRect(rect, radii.x, radii.y, view->CurrentState(), false);
view->Window()->GetDrawingEngine()->DrawRoundRect(rect, radii.x, radii.y,
false);
}
@ -214,7 +215,8 @@ static void
fill_round_rect(ViewLayer *view, BRect rect, BPoint radii)
{
view->ConvertToScreenForDrawing(&rect);
view->Window()->GetDrawingEngine()->DrawRoundRect(rect, radii.x, radii.y, view->CurrentState(), true);
view->Window()->GetDrawingEngine()->DrawRoundRect(rect, radii.x, radii.y,
true);
}
@ -224,7 +226,7 @@ stroke_bezier(ViewLayer *view, const BPoint *viewPoints)
BPoint points[4];
view->ConvertToScreenForDrawing(points, viewPoints, 4);
view->Window()->GetDrawingEngine()->DrawBezier(points, view->CurrentState(), false);
view->Window()->GetDrawingEngine()->DrawBezier(points, false);
}
@ -234,7 +236,7 @@ fill_bezier(ViewLayer *view, const BPoint *viewPoints)
BPoint points[4];
view->ConvertToScreenForDrawing(points, viewPoints, 4);
view->Window()->GetDrawingEngine()->DrawBezier(points, view->CurrentState(), true);
view->Window()->GetDrawingEngine()->DrawBezier(points, true);
}
@ -245,7 +247,7 @@ stroke_arc(ViewLayer *view, BPoint center, BPoint radii, float startTheta,
BRect rect(center.x - radii.x, center.y - radii.y, center.x + radii.x,
center.y + radii.y);
view->ConvertToScreenForDrawing(&rect);
view->Window()->GetDrawingEngine()->DrawArc(rect, startTheta, arcTheta, view->CurrentState(), false);
view->Window()->GetDrawingEngine()->DrawArc(rect, startTheta, arcTheta, false);
}
@ -256,7 +258,7 @@ fill_arc(ViewLayer *view, BPoint center, BPoint radii, float startTheta,
BRect rect(center.x - radii.x, center.y - radii.y, center.x + radii.x,
center.y + radii.y);
view->ConvertToScreenForDrawing(&rect);
view->Window()->GetDrawingEngine()->DrawArc(rect, startTheta, arcTheta, view->CurrentState(), true);
view->Window()->GetDrawingEngine()->DrawArc(rect, startTheta, arcTheta, true);
}
@ -266,7 +268,7 @@ stroke_ellipse(ViewLayer *view, BPoint center, BPoint radii)
BRect rect(center.x - radii.x, center.y - radii.y, center.x + radii.x,
center.y + radii.y);
view->ConvertToScreenForDrawing(&rect);
view->Window()->GetDrawingEngine()->DrawEllipse(rect, view->CurrentState(), false);
view->Window()->GetDrawingEngine()->DrawEllipse(rect, false);
}
@ -276,7 +278,7 @@ fill_ellipse(ViewLayer *view, BPoint center, BPoint radii)
BRect rect(center.x - radii.x, center.y - radii.y, center.x + radii.x,
center.y + radii.y);
view->ConvertToScreenForDrawing(&rect);
view->Window()->GetDrawingEngine()->DrawEllipse(rect, view->CurrentState(), true);
view->Window()->GetDrawingEngine()->DrawEllipse(rect, true);
}
@ -295,9 +297,8 @@ stroke_polygon(ViewLayer *view, int32 numPoints, const BPoint *viewPoints, bool
BRect polyFrame;
get_polygon_frame(points, numPoints, &polyFrame);
view->Window()->GetDrawingEngine()->DrawPolygon(points, numPoints, polyFrame,
view->CurrentState(), false,
isClosed && numPoints > 2);
view->Window()->GetDrawingEngine()->DrawPolygon(points, numPoints, polyFrame,
false, isClosed && numPoints > 2);
} else {
// avoid constructor/destructor calls by using malloc instead of new []
BPoint *points = (BPoint *)malloc(numPoints * sizeof(BPoint));
@ -310,8 +311,7 @@ stroke_polygon(ViewLayer *view, int32 numPoints, const BPoint *viewPoints, bool
get_polygon_frame(points, numPoints, &polyFrame);
view->Window()->GetDrawingEngine()->DrawPolygon(points, numPoints, polyFrame,
view->CurrentState(), false,
isClosed && numPoints > 2);
false, isClosed && numPoints > 2);
free(points);
}
}
@ -333,7 +333,7 @@ fill_polygon(ViewLayer *view, int32 numPoints, const BPoint *viewPoints)
get_polygon_frame(points, numPoints, &polyFrame);
view->Window()->GetDrawingEngine()->DrawPolygon(points, numPoints, polyFrame,
view->CurrentState(), true, true);
true, true);
} else {
// avoid constructor/destructor calls by using malloc instead of new []
BPoint *points = (BPoint *)malloc(numPoints * sizeof(BPoint));
@ -346,7 +346,7 @@ fill_polygon(ViewLayer *view, int32 numPoints, const BPoint *viewPoints)
get_polygon_frame(points, numPoints, &polyFrame);
view->Window()->GetDrawingEngine()->DrawPolygon(points, numPoints, polyFrame,
view->CurrentState(), true, true);
true, true);
free(points);
}
}
@ -373,13 +373,14 @@ fill_shape(ViewLayer *view, const BShape *shape)
static void
draw_string(ViewLayer *view, const char *string, float deltaSpace, float deltaNonSpace)
draw_string(ViewLayer *view, const char *string, float deltaSpace,
float deltaNonSpace)
{
BPoint location = view->CurrentState()->PenLocation();
escapement_delta delta = {deltaSpace, deltaNonSpace };
view->ConvertToScreenForDrawing(&location);
view->Window()->GetDrawingEngine()->DrawString(string, strlen(string), location,
view->CurrentState(), &delta);
view->Window()->GetDrawingEngine()->DrawString(string, strlen(string),
location, &delta);
// TODO: Update pen location ?
}
@ -399,7 +400,7 @@ draw_pixels(ViewLayer *view, BRect src, BRect dest, int32 width, int32 height,
view->ConvertToScreenForDrawing(&dest);
view->Window()->GetDrawingEngine()->DrawBitmap(&bitmap, src, dest, view->CurrentState());
view->Window()->GetDrawingEngine()->DrawBitmap(&bitmap, src, dest);
}
@ -434,6 +435,11 @@ static void
pop_state(ViewLayer *view)
{
view->PopState();
IntPoint p = view->ScrollingOffset();
p += IntPoint(view->CurrentState()->Origin());
view->Window()->GetDrawingEngine()->SetDrawState(
view->CurrentState(), p.x, p.y);
}
@ -476,6 +482,12 @@ static void
set_pen_location(ViewLayer *view, BPoint pt)
{
view->CurrentState()->SetPenLocation(pt);
// TODO: faster version
IntPoint p = view->ScrollingOffset();
p += IntPoint(view->CurrentState()->Origin());
view->Window()->GetDrawingEngine()->SetDrawState(
view->CurrentState(), p.x, p.y);
}
@ -483,6 +495,7 @@ static void
set_drawing_mode(ViewLayer *view, drawing_mode mode)
{
view->CurrentState()->SetDrawingMode(mode);
view->Window()->GetDrawingEngine()->SetDrawingMode(mode);
}
@ -493,6 +506,7 @@ set_line_mode(ViewLayer *view, cap_mode capMode, join_mode joinMode, float miter
state->SetLineCapMode(capMode);
state->SetLineJoinMode(joinMode);
state->SetMiterLimit(miterLimit);
view->Window()->GetDrawingEngine()->SetStrokeMode(capMode, joinMode, miterLimit);
}
@ -500,6 +514,7 @@ static void
set_pen_size(ViewLayer *view, float size)
{
view->CurrentState()->SetPenSize(size);
view->Window()->GetDrawingEngine()->SetPenSize(size);
}
@ -507,6 +522,7 @@ static void
set_fore_color(ViewLayer *view, rgb_color color)
{
view->CurrentState()->SetHighColor(RGBColor(color));
view->Window()->GetDrawingEngine()->SetHighColor(color);
}
@ -514,13 +530,15 @@ static void
set_back_color(ViewLayer *view, rgb_color color)
{
view->CurrentState()->SetLowColor(RGBColor(color));
view->Window()->GetDrawingEngine()->SetLowColor(color);
}
static void
set_stipple_pattern(ViewLayer *view, pattern p)
{
printf("SetStipplePattern\n");
view->CurrentState()->SetPattern(Pattern(p));
view->Window()->GetDrawingEngine()->SetPattern(p);
}
@ -558,13 +576,17 @@ set_font_size(ViewLayer *view, float size)
ServerFont font;
font.SetSize(size);
view->CurrentState()->SetFont(font, B_FONT_SIZE);
view->Window()->GetDrawingEngine()->SetFont(view->CurrentState()->Font());
}
static void
set_font_rotate(ViewLayer *view, float rotation)
{
printf("SetFontRotate(%.2f)\n", rotation);
ServerFont font;
font.SetRotation(rotation);
view->CurrentState()->SetFont(font, B_FONT_ROTATION);
view->Window()->GetDrawingEngine()->SetFont(view->CurrentState()->Font());
}

View File

@ -1034,6 +1034,16 @@ fDesktop->LockSingleWindow();
// at the fRedrawRequested member variable in _MessageLooper().
break;
case AS_SYNC:
// the synchronisation works by the fact that the client
// window is waiting for this reply, after having received it,
// client and server queues are in sync (earlier, the client
// may have pushed drawing commands at the server and now it
// knows they have all been carried out)
fLink.StartMessage(B_OK);
fLink.Flush();
break;
case AS_BEGIN_UPDATE:
DTRACE(("ServerWindowo %s: AS_BEGIN_UPDATE\n", Title()));
fWindowLayer->BeginUpdate(fLink);
@ -1161,7 +1171,15 @@ fDesktop->LockSingleWindow();
// and take appropriate actions, then checking for fCurrentLayer->CurrentState()
// is unnecessary
if (fCurrentLayer == NULL || fCurrentLayer->CurrentState() == NULL) {
printf("ServerWindow %s received unexpected code - message offset %ld before top_view attached.\n", Title(), code - B_OK);
BString codeName;
string_for_message_code(code, codeName);
printf("ServerWindow %s received unexpected code - "
"message '%s' before top_view attached.\n",
Title(), codeName.String());
if (link.NeedsReply()) {
fLink.StartMessage(B_ERROR);
fLink.Flush();
}
return;
}
@ -1231,8 +1249,10 @@ ServerWindow::_DispatchViewMessage(int32 code,
fDesktop->EventDispatcher().RemoveListener(EventTarget(),
token);
}
if (fCurrentLayer == view)
_SetCurrentLayer(parent);
delete view;
}
} // else we don't delete the root view
}
break;
}
@ -1251,7 +1271,9 @@ ServerWindow::_DispatchViewMessage(int32 code,
{
DTRACE(("ServerWindow %s: Message AS_LAYER_SET_FONT_STATE: ViewLayer name: %s\n", fTitle, fCurrentLayer->Name()));
fCurrentLayer->CurrentState()->ReadFontFromLink(link);
_UpdateDrawState(fCurrentLayer);
// _UpdateDrawState(fCurrentLayer);
fWindowLayer->GetDrawingEngine()->SetFont(
fCurrentLayer->CurrentState()->Font());
break;
}
case AS_LAYER_GET_STATE:
@ -1466,7 +1488,9 @@ ServerWindow::_DispatchViewMessage(int32 code,
fCurrentLayer->CurrentState()->SetLineJoinMode((join_mode)lineJoin);
fCurrentLayer->CurrentState()->SetMiterLimit(miterLimit);
_UpdateDrawState(fCurrentLayer);
fWindowLayer->GetDrawingEngine()->SetStrokeMode((cap_mode)lineCap,
(join_mode)lineJoin, miterLimit);
// _UpdateDrawState(fCurrentLayer);
break;
}
@ -1606,8 +1630,10 @@ ServerWindow::_DispatchViewMessage(int32 code,
link.Read<int8>(&alphaFunc);
fCurrentLayer->CurrentState()->SetBlendingMode((source_alpha)srcAlpha,
(alpha_function)alphaFunc);
_UpdateDrawState(fCurrentLayer);
(alpha_function)alphaFunc);
//_UpdateDrawState(fCurrentLayer);
fWindowLayer->GetDrawingEngine()->SetBlendingMode((source_alpha)srcAlpha,
(alpha_function)alphaFunc);
break;
}
case AS_LAYER_GET_BLENDING_MODE:
@ -1856,30 +1882,6 @@ ServerWindow::_DispatchViewMessage(int32 code,
fWindowLayer->GetDrawingEngine()->SetPattern(pat);
break;
}
case AS_SET_FONT:
{
DTRACE(("ServerWindow %s: Message AS_SET_FONT\n", Title()));
// TODO: Implement AS_SET_FONT?
// Confusing!! But it works already!
break;
}
case AS_SET_FONT_SIZE:
{
DTRACE(("ServerWindow %s: Message AS_SET_FONT_SIZE\n", Title()));
// TODO: Implement AS_SET_FONT_SIZE?
break;
}
case AS_SYNC:
{
// the synchronisation works by the fact that the client
// window is waiting for this reply, after having received it,
// client and server queues are in sync (earlier, the client
// may have pushed drawing commands at the server and now it
// knows they have all been carried out)
fLink.StartMessage(B_OK);
fLink.Flush();
break;
}
case AS_LAYER_DRAG_IMAGE:
{
// TODO: flesh out AS_LAYER_DRAG_IMAGE
@ -2052,7 +2054,7 @@ ServerWindow::_DispatchViewDrawingMessage(int32 code, BPrivate::LinkReceiver &li
BPoint penPos = p2;
fCurrentLayer->ConvertToScreenForDrawing(&p1);
fCurrentLayer->ConvertToScreenForDrawing(&p2);
drawingEngine->StrokeLine(p1, p2, fCurrentLayer->CurrentState());
drawingEngine->StrokeLine(p1, p2);
// We update the pen here because many DrawingEngine calls which do not update the
// pen position actually call StrokeLine
@ -2086,7 +2088,7 @@ ServerWindow::_DispatchViewDrawingMessage(int32 code, BPrivate::LinkReceiver &li
BRect rect(left,top,right,bottom);
fCurrentLayer->ConvertToScreenForDrawing(&rect);
drawingEngine->StrokeRect(rect, fCurrentLayer->CurrentState());
drawingEngine->StrokeRect(rect);
break;
}
case AS_FILL_RECT:
@ -2097,7 +2099,7 @@ ServerWindow::_DispatchViewDrawingMessage(int32 code, BPrivate::LinkReceiver &li
link.Read<BRect>(&rect);
fCurrentLayer->ConvertToScreenForDrawing(&rect);
drawingEngine->FillRect(rect, fCurrentLayer->CurrentState());
drawingEngine->FillRect(rect);
break;
}
case AS_LAYER_DRAW_BITMAP:
@ -2114,7 +2116,7 @@ ServerWindow::_DispatchViewDrawingMessage(int32 code, BPrivate::LinkReceiver &li
if (bitmap) {
fCurrentLayer->ConvertToScreenForDrawing(&dstRect);
drawingEngine->DrawBitmap(bitmap, srcRect, dstRect, fCurrentLayer->CurrentState());
drawingEngine->DrawBitmap(bitmap, srcRect, dstRect);
}
break;
@ -2132,8 +2134,7 @@ ServerWindow::_DispatchViewDrawingMessage(int32 code, BPrivate::LinkReceiver &li
link.Read<float>(&span);
fCurrentLayer->ConvertToScreenForDrawing(&r);
drawingEngine->DrawArc(r, angle, span, fCurrentLayer->CurrentState(),
code == AS_FILL_ARC);
drawingEngine->DrawArc(r, angle, span, code == AS_FILL_ARC);
break;
}
case AS_STROKE_BEZIER:
@ -2147,8 +2148,7 @@ ServerWindow::_DispatchViewDrawingMessage(int32 code, BPrivate::LinkReceiver &li
fCurrentLayer->ConvertToScreenForDrawing(&pts[i]);
}
drawingEngine->DrawBezier(pts, fCurrentLayer->CurrentState(),
code == AS_FILL_BEZIER);
drawingEngine->DrawBezier(pts, code == AS_FILL_BEZIER);
break;
}
case AS_STROKE_ELLIPSE:
@ -2160,7 +2160,7 @@ ServerWindow::_DispatchViewDrawingMessage(int32 code, BPrivate::LinkReceiver &li
link.Read<BRect>(&rect);
fCurrentLayer->ConvertToScreenForDrawing(&rect);
drawingEngine->DrawEllipse(rect, fCurrentLayer->CurrentState(), code == AS_FILL_ELLIPSE);
drawingEngine->DrawEllipse(rect, code == AS_FILL_ELLIPSE);
break;
}
case AS_STROKE_ROUNDRECT:
@ -2175,7 +2175,7 @@ ServerWindow::_DispatchViewDrawingMessage(int32 code, BPrivate::LinkReceiver &li
link.Read<float>(&yrad);
fCurrentLayer->ConvertToScreenForDrawing(&rect);
drawingEngine->DrawRoundRect(rect, xrad, yrad, fCurrentLayer->CurrentState(), code == AS_FILL_ROUNDRECT);
drawingEngine->DrawRoundRect(rect, xrad, yrad, code == AS_FILL_ROUNDRECT);
break;
}
case AS_STROKE_TRIANGLE:
@ -2194,7 +2194,7 @@ ServerWindow::_DispatchViewDrawingMessage(int32 code, BPrivate::LinkReceiver &li
link.Read<BRect>(&rect);
fCurrentLayer->ConvertToScreenForDrawing(&rect);
drawingEngine->DrawTriangle(pts, rect, fCurrentLayer->CurrentState(), code == AS_FILL_TRIANGLE);
drawingEngine->DrawTriangle(pts, rect, code == AS_FILL_TRIANGLE);
break;
}
case AS_STROKE_POLYGON:
@ -2218,8 +2218,7 @@ ServerWindow::_DispatchViewDrawingMessage(int32 code, BPrivate::LinkReceiver &li
fCurrentLayer->ConvertToScreenForDrawing(&polyFrame);
drawingEngine->DrawPolygon(pointList, pointCount, polyFrame,
fCurrentLayer->CurrentState(), code == AS_FILL_POLYGON,
isClosed && pointCount > 2);
code == AS_FILL_POLYGON, isClosed && pointCount > 2);
}
delete[] pointList;
break;
@ -2246,7 +2245,7 @@ ServerWindow::_DispatchViewDrawingMessage(int32 code, BPrivate::LinkReceiver &li
fCurrentLayer->ConvertToScreenForDrawing(&ptList[i]);
drawingEngine->DrawShape(shapeFrame, opCount, opList, ptCount, ptList,
fCurrentLayer->CurrentState(), code == AS_FILL_SHAPE);
code == AS_FILL_SHAPE);
}
delete[] opList;
@ -2262,7 +2261,7 @@ ServerWindow::_DispatchViewDrawingMessage(int32 code, BPrivate::LinkReceiver &li
break;
fCurrentLayer->ConvertToScreenForDrawing(&region);
drawingEngine->FillRegion(region, fCurrentLayer->CurrentState());
drawingEngine->FillRegion(region);
break;
}
@ -2292,8 +2291,7 @@ ServerWindow::_DispatchViewDrawingMessage(int32 code, BPrivate::LinkReceiver &li
fCurrentLayer->ConvertToScreenForDrawing(&index->pt1);
fCurrentLayer->ConvertToScreenForDrawing(&index->pt2);
}
drawingEngine->StrokeLineArray(lineCount, lineData,
fCurrentLayer->CurrentState());
drawingEngine->StrokeLineArray(lineCount, lineData);
}
break;
}
@ -2311,11 +2309,12 @@ ServerWindow::_DispatchViewDrawingMessage(int32 code, BPrivate::LinkReceiver &li
link.ReadString(&string);
fCurrentLayer->ConvertToScreenForDrawing(&location);
BPoint penLocation = drawingEngine->DrawString(string, length, location,
fCurrentLayer->CurrentState(), &delta);
BPoint penLocation = drawingEngine->DrawString(string, length,
location, &delta);
fCurrentLayer->ConvertFromScreenForDrawing(&penLocation);
fCurrentLayer->CurrentState()->SetPenLocation(penLocation);
// pen location has changed, update DrawingEngine
// TODO: optimize with flags
_UpdateDrawState(fCurrentLayer);

View File

@ -1212,16 +1212,14 @@ ViewLayer::Draw(DrawingEngine* drawingEngine, BRegion* effectiveClipping,
if (rect.IsValid()/* && drawingEngine->Lock()*/) {
drawingEngine->ConstrainClippingRegion(redraw);
DrawState defaultDrawState;
if (fBitmapOptions & B_TILE_BITMAP) {
// tile across entire view
float start = rect.left;
while (rect.top < redraw->Frame().bottom) {
while (rect.left < redraw->Frame().right) {
drawingEngine->DrawBitmap(fViewBitmap, fBitmapSource,
rect, &defaultDrawState);
drawingEngine->DrawBitmap(fViewBitmap,
fBitmapSource, rect);
rect.OffsetBy(rect.Width() + 1, 0.0);
}
rect.OffsetBy(start - rect.left, rect.Height() + 1);
@ -1233,7 +1231,7 @@ ViewLayer::Draw(DrawingEngine* drawingEngine, BRegion* effectiveClipping,
while (rect.left < redraw->Frame().right) {
drawingEngine->DrawBitmap(fViewBitmap, fBitmapSource,
rect, &defaultDrawState);
rect);
rect.OffsetBy(rect.Width() + 1, 0.0);
}
// remove horizontal stripe from clipping
@ -1245,7 +1243,7 @@ ViewLayer::Draw(DrawingEngine* drawingEngine, BRegion* effectiveClipping,
while (rect.top < redraw->Frame().bottom) {
drawingEngine->DrawBitmap(fViewBitmap, fBitmapSource,
rect, &defaultDrawState);
rect);
rect.OffsetBy(0.0, rect.Height() + 1);
}
// remove vertical stripe from clipping
@ -1256,7 +1254,7 @@ ViewLayer::Draw(DrawingEngine* drawingEngine, BRegion* effectiveClipping,
// no tiling at all
drawingEngine->DrawBitmap(fViewBitmap, fBitmapSource,
rect, &defaultDrawState);
rect);
redraw->Exclude(rect);
}

View File

@ -84,7 +84,6 @@ class WindowLayer {
ViewLayer* TopLayer() const { return fTopLayer; }
// TODO: only used for WorkspacesLayer, can go away if we do
// this differently one day
ViewLayer* ViewAt(const BPoint& where);
virtual bool IsOffscreenWindow() const { return false; }

View File

@ -13,6 +13,7 @@
#include <algo.h>
#include <stack.h>
#include "AGGTextRenderer.h"
#include "DrawState.h"
#include "Painter.h"
#include "PNGDump.h"
@ -46,10 +47,10 @@ make_rect_valid(BRect& rect)
// extend_by_stroke_width
static inline void
extend_by_stroke_width(BRect& rect, const DrawState* context)
extend_by_stroke_width(BRect& rect, float penSize)
{
// "- 0.5" because if stroke width == 1, we don't need to extend
float inset = -ceilf(context->PenSize() / 2.0 - 0.5);
float inset = -ceilf(penSize / 2.0 - 0.5);
rect.InsetBy(inset, inset);
}
@ -184,7 +185,7 @@ DrawingEngine::ConstrainClippingRegion(const BRegion* region)
void
DrawingEngine::SetDrawState(const DrawState* state, int32 xOffset, int32 yOffset)
{
fPainter->SetDrawState(state, false, xOffset, yOffset);
fPainter->SetDrawState(state, true, xOffset, yOffset);
}
@ -209,11 +210,24 @@ DrawingEngine::SetPenSize(float size)
}
void
DrawingEngine::SetStrokeMode(cap_mode lineCap, join_mode joinMode,
float miterLimit)
{
fPainter->SetStrokeMode(lineCap, joinMode, miterLimit);
}
void
DrawingEngine::SetBlendingMode(source_alpha srcAlpha, alpha_function alphaFunc)
{
fPainter->SetBlendingMode(srcAlpha, alphaFunc);
}
void
DrawingEngine::SetPattern(const struct pattern& pattern)
{
// TODO: doing it like this prevents an optimization
// for font rendering (special "solid" drawing mode)
fPainter->SetPattern(pattern, false);
}
@ -225,6 +239,13 @@ DrawingEngine::SetDrawingMode(drawing_mode mode)
}
void
DrawingEngine::SetFont(const ServerFont& font)
{
fPainter->SetFont(font);
}
// #pragma mark -
@ -505,8 +526,7 @@ DrawingEngine::InvertRect(BRect r)
// DrawBitmap
void
DrawingEngine::DrawBitmap(ServerBitmap *bitmap,
const BRect &source, const BRect &dest,
const DrawState *d)
const BRect &source, const BRect &dest)
{
CRASH_IF_NOT_LOCKED
@ -514,7 +534,6 @@ DrawingEngine::DrawBitmap(ServerBitmap *bitmap,
if (clipped.IsValid()) {
bool cursorTouched = fGraphicsCard->HideSoftwareCursor(clipped);
// fPainter->SetDrawState(d);
fPainter->DrawBitmap(bitmap, source, dest);
fGraphicsCard->Invalidate(clipped);
@ -526,21 +545,18 @@ DrawingEngine::DrawBitmap(ServerBitmap *bitmap,
// DrawArc
void
DrawingEngine::DrawArc(BRect r, const float &angle,
const float &span, const DrawState *d,
bool filled)
const float &span, bool filled)
{
CRASH_IF_NOT_LOCKED
make_rect_valid(r);
BRect clipped(r);
if (!filled)
extend_by_stroke_width(clipped, d);
extend_by_stroke_width(clipped, fPainter->PenSize());
clipped = fPainter->ClipRect(r);
if (clipped.IsValid()) {
bool cursorTouched = fGraphicsCard->HideSoftwareCursor(clipped);
// fPainter->SetDrawState(d);
float xRadius = r.Width() / 2.0;
float yRadius = r.Height() / 2.0;
BPoint center(r.left + xRadius,
@ -559,14 +575,13 @@ DrawingEngine::DrawArc(BRect r, const float &angle,
// DrawBezier
void
DrawingEngine::DrawBezier(BPoint *pts, const DrawState *d, bool filled)
DrawingEngine::DrawBezier(BPoint *pts, bool filled)
{
CRASH_IF_NOT_LOCKED
// TODO: figure out bounds and hide cursor depending on that
fGraphicsCard->HideSoftwareCursor();
// fPainter->SetDrawState(d);
BRect touched = fPainter->DrawBezier(pts, filled);
fGraphicsCard->Invalidate(touched);
@ -575,7 +590,7 @@ DrawingEngine::DrawBezier(BPoint *pts, const DrawState *d, bool filled)
// DrawEllipse
void
DrawingEngine::DrawEllipse(BRect r, const DrawState *d, bool filled)
DrawingEngine::DrawEllipse(BRect r, bool filled)
{
CRASH_IF_NOT_LOCKED
@ -584,7 +599,7 @@ DrawingEngine::DrawEllipse(BRect r, const DrawState *d, bool filled)
fPainter->AlignEllipseRect(&clipped, filled);
if (!filled)
extend_by_stroke_width(clipped, d);
extend_by_stroke_width(clipped, fPainter->PenSize());
clipped.left = floorf(clipped.left);
clipped.top = floorf(clipped.top);
@ -596,7 +611,6 @@ DrawingEngine::DrawEllipse(BRect r, const DrawState *d, bool filled)
if (clipped.IsValid()) {
bool cursorTouched = fGraphicsCard->HideSoftwareCursor(clipped);
// fPainter->SetDrawState(d);
fPainter->DrawEllipse(r, filled);
fGraphicsCard->Invalidate(clipped);
@ -608,19 +622,17 @@ DrawingEngine::DrawEllipse(BRect r, const DrawState *d, bool filled)
// DrawPolygon
void
DrawingEngine::DrawPolygon(BPoint* ptlist, int32 numpts,
BRect bounds, const DrawState* d,
bool filled, bool closed)
BRect bounds, bool filled, bool closed)
{
CRASH_IF_NOT_LOCKED
make_rect_valid(bounds);
if (!filled)
extend_by_stroke_width(bounds, d);
extend_by_stroke_width(bounds, fPainter->PenSize());
bounds = fPainter->ClipRect(bounds);
if (bounds.IsValid()) {
bool cursorTouched = fGraphicsCard->HideSoftwareCursor(bounds);
// fPainter->SetDrawState(d);
fPainter->DrawPolygon(ptlist, numpts, filled, closed);
fGraphicsCard->Invalidate(bounds);
@ -756,20 +768,19 @@ DrawingEngine::FillRegion(BRegion& r, const RGBColor& color)
// #pragma mark - DrawState
void
DrawingEngine::StrokeRect(BRect r, const DrawState *d)
DrawingEngine::StrokeRect(BRect r)
{
CRASH_IF_NOT_LOCKED
// support invalid rects
make_rect_valid(r);
BRect clipped(r);
extend_by_stroke_width(clipped, d);
extend_by_stroke_width(clipped, fPainter->PenSize());
clipped = fPainter->ClipRect(clipped);
if (clipped.IsValid()) {
bool cursorTouched = fGraphicsCard->HideSoftwareCursor(clipped);
// fPainter->SetDrawState(d);
fPainter->StrokeRect(r);
fGraphicsCard->Invalidate(clipped);
@ -780,7 +791,7 @@ DrawingEngine::StrokeRect(BRect r, const DrawState *d)
void
DrawingEngine::FillRect(BRect r, const DrawState *d)
DrawingEngine::FillRect(BRect r)
{
CRASH_IF_NOT_LOCKED
@ -794,20 +805,20 @@ DrawingEngine::FillRect(BRect r, const DrawState *d)
// try hardware optimized version first
// if the rect is large enough
if ((fAvailableHWAccleration & HW_ACC_FILL_REGION) != 0) {
if (d->GetPattern() == B_SOLID_HIGH
&& (d->GetDrawingMode() == B_OP_COPY
|| d->GetDrawingMode() == B_OP_OVER)) {
if (fPainter->Pattern() == B_SOLID_HIGH
&& (fPainter->DrawingMode() == B_OP_COPY
|| fPainter->DrawingMode() == B_OP_OVER)) {
BRegion region(r);
region.IntersectWith(fPainter->ClippingRegion());
fGraphicsCard->FillRegion(region, d->HighColor(),
fGraphicsCard->FillRegion(region, fPainter->HighColor(),
fSuspendSyncLevel == 0
|| cursorTouched);
doInSoftware = false;
} else if (d->GetPattern() == B_SOLID_LOW
&& d->GetDrawingMode() == B_OP_COPY) {
} else if (fPainter->Pattern() == B_SOLID_LOW
&& fPainter->DrawingMode() == B_OP_COPY) {
BRegion region(r);
region.IntersectWith(fPainter->ClippingRegion());
fGraphicsCard->FillRegion(region, d->LowColor(),
fGraphicsCard->FillRegion(region, fPainter->LowColor(),
fSuspendSyncLevel == 0
|| cursorTouched);
doInSoftware = false;
@ -815,7 +826,6 @@ DrawingEngine::FillRect(BRect r, const DrawState *d)
}
}
if (doInSoftware) {
// fPainter->SetDrawState(d);
fPainter->FillRect(r);
fGraphicsCard->Invalidate(r);
@ -828,7 +838,7 @@ DrawingEngine::FillRect(BRect r, const DrawState *d)
void
DrawingEngine::FillRegion(BRegion& r, const DrawState *d)
DrawingEngine::FillRegion(BRegion& r)
{
CRASH_IF_NOT_LOCKED
@ -839,18 +849,18 @@ DrawingEngine::FillRegion(BRegion& r, const DrawState *d)
bool doInSoftware = true;
// try hardware optimized version first
if ((fAvailableHWAccleration & HW_ACC_FILL_REGION) != 0) {
if (d->GetPattern() == B_SOLID_HIGH
&& (d->GetDrawingMode() == B_OP_COPY
|| d->GetDrawingMode() == B_OP_OVER)) {
if (fPainter->Pattern() == B_SOLID_HIGH
&& (fPainter->DrawingMode() == B_OP_COPY
|| fPainter->DrawingMode() == B_OP_OVER)) {
r.IntersectWith(fPainter->ClippingRegion());
fGraphicsCard->FillRegion(r, d->HighColor(),
fGraphicsCard->FillRegion(r, fPainter->HighColor(),
fSuspendSyncLevel == 0
|| cursorTouched);
doInSoftware = false;
} else if (d->GetPattern() == B_SOLID_LOW
&& d->GetDrawingMode() == B_OP_COPY) {
} else if (fPainter->Pattern() == B_SOLID_LOW
&& fPainter->DrawingMode() == B_OP_COPY) {
r.IntersectWith(fPainter->ClippingRegion());
fGraphicsCard->FillRegion(r, d->LowColor(),
fGraphicsCard->FillRegion(r, fPainter->LowColor(),
fSuspendSyncLevel == 0
|| cursorTouched);
doInSoftware = false;
@ -858,7 +868,6 @@ DrawingEngine::FillRegion(BRegion& r, const DrawState *d)
}
if (doInSoftware) {
// fPainter->SetDrawState(d);
BRect touched = fPainter->FillRect(r.RectAt(0));
@ -877,8 +886,7 @@ DrawingEngine::FillRegion(BRegion& r, const DrawState *d)
void
DrawingEngine::DrawRoundRect(BRect r, float xrad, float yrad,
const DrawState* d, bool filled)
DrawingEngine::DrawRoundRect(BRect r, float xrad, float yrad, bool filled)
{
CRASH_IF_NOT_LOCKED
@ -895,7 +903,6 @@ DrawingEngine::DrawRoundRect(BRect r, float xrad, float yrad,
if (clipped.IsValid()) {
bool cursorTouched = fGraphicsCard->HideSoftwareCursor(clipped);
// fPainter->SetDrawState(d);
BRect touched = filled ? fPainter->FillRoundRect(r, xrad, yrad)
: fPainter->StrokeRoundRect(r, xrad, yrad);
@ -908,8 +915,7 @@ DrawingEngine::DrawRoundRect(BRect r, float xrad, float yrad,
void
DrawingEngine::DrawShape(const BRect& bounds, int32 opCount,
const uint32* opList, int32 ptCount, const BPoint* ptList,
const DrawState* d, bool filled)
const uint32* opList, int32 ptCount, const BPoint* ptList, bool filled)
{
CRASH_IF_NOT_LOCKED
@ -917,7 +923,6 @@ DrawingEngine::DrawShape(const BRect& bounds, int32 opCount,
// shape is drawn on screen, TODO: optimize
fGraphicsCard->HideSoftwareCursor();
// fPainter->SetDrawState(d);
BRect touched = fPainter->DrawShape(opCount, opList,
ptCount, ptList,
filled);
@ -928,19 +933,17 @@ DrawingEngine::DrawShape(const BRect& bounds, int32 opCount,
void
DrawingEngine::DrawTriangle(BPoint* pts, const BRect& bounds,
const DrawState* d, bool filled)
DrawingEngine::DrawTriangle(BPoint* pts, const BRect& bounds, bool filled)
{
CRASH_IF_NOT_LOCKED
BRect clipped(bounds);
if (!filled)
extend_by_stroke_width(clipped, d);
extend_by_stroke_width(clipped, fPainter->PenSize());
clipped = fPainter->ClipRect(clipped);
if (clipped.IsValid()) {
bool cursorTouched = fGraphicsCard->HideSoftwareCursor(clipped);
// fPainter->SetDrawState(d);
if (filled)
fPainter->FillTriangle(pts[0], pts[1], pts[2]);
else
@ -954,18 +957,17 @@ DrawingEngine::DrawTriangle(BPoint* pts, const BRect& bounds,
// StrokeLine
void
DrawingEngine::StrokeLine(const BPoint &start, const BPoint &end, DrawState* context)
DrawingEngine::StrokeLine(const BPoint &start, const BPoint &end)
{
CRASH_IF_NOT_LOCKED
BRect touched(start, end);
make_rect_valid(touched);
extend_by_stroke_width(touched, context);
extend_by_stroke_width(touched, fPainter->PenSize());
touched = fPainter->ClipRect(touched);
if (touched.IsValid()) {
bool cursorTouched = fGraphicsCard->HideSoftwareCursor(touched);
// fPainter->SetDrawState(context);
fPainter->StrokeLine(start, end);
fGraphicsCard->Invalidate(touched);
@ -977,11 +979,11 @@ DrawingEngine::StrokeLine(const BPoint &start, const BPoint &end, DrawState* con
// StrokeLineArray
void
DrawingEngine::StrokeLineArray(int32 numLines,
const LineArrayData *linedata, const DrawState *d)
const LineArrayData *linedata)
{
CRASH_IF_NOT_LOCKED
if (!d || !linedata || numLines <= 0)
if (!linedata || numLines <= 0)
return;
// figure out bounding box for line array
@ -999,13 +1001,14 @@ DrawingEngine::StrokeLineArray(int32 numLines,
max_c(data->pt1.y, data->pt2.y));
touched = touched | box;
}
extend_by_stroke_width(touched, d);
extend_by_stroke_width(touched, fPainter->PenSize());
touched = fPainter->ClipRect(touched);
if (touched.IsValid()) {
bool cursorTouched = fGraphicsCard->HideSoftwareCursor(touched);
data = (const LineArrayData *)&(linedata[0]);
rgb_color oldColor = fPainter->HighColor();
fPainter->SetHighColor(data->color);
fPainter->StrokeLine(data->pt1, data->pt2);
@ -1016,7 +1019,7 @@ DrawingEngine::StrokeLineArray(int32 numLines,
}
// restore correct drawing state highcolor
fPainter->SetHighColor(d->HighColor());
fPainter->SetHighColor(oldColor);
fGraphicsCard->Invalidate(touched);
if (cursorTouched)
@ -1028,22 +1031,14 @@ DrawingEngine::StrokeLineArray(int32 numLines,
BPoint
DrawingEngine::DrawString(const char* string, int32 length,
const BPoint& pt, DrawState* d,
escapement_delta* delta)
const BPoint& pt, escapement_delta* delta)
{
CRASH_IF_NOT_LOCKED
// TODO: use delta
FontLocker locker(d);
FontLocker locker(&fPainter->Font());
BPoint penLocation = pt;
fPainter->SetDrawState(d, true);
// TODO: this will reset the scrolling offsets used for
// pattern drawing again, it is really necessary to change
// the whole graphics state synchronization between DrawState
// and Painter, and remove any individual SetDrawState() calls
// like here
//bigtime_t now = system_time();
// TODO: BoundingBox is quite slow!! Optimizing it will be beneficial.
// Cursiously, the DrawString after it is actually faster!?!
@ -1074,10 +1069,9 @@ DrawingEngine::DrawString(const char* string, int32 length,
// StringWidth
float
DrawingEngine::StringWidth(const char* string, int32 length,
const DrawState* d, escapement_delta* delta)
escapement_delta* delta)
{
// TODO: use delta
FontLocker locker(d);
FontLocker locker(&fPainter->Font());
float width = 0.0;
// NOTE: For now it is enough to block on the
@ -1086,7 +1080,7 @@ DrawingEngine::StringWidth(const char* string, int32 length,
// deadlock in case another thread holds the font
// lock already and then tries to lock the drawing
// engine after it is already locked here (race condition)
width = fPainter->StringWidth(string, length, d);
width = fPainter->StringWidth(string, length, delta);
return width;
}
@ -1095,30 +1089,12 @@ float
DrawingEngine::StringWidth(const char* string, int32 length,
const ServerFont& font, escapement_delta* delta)
{
DrawState d;
d.SetFont(font);
return StringWidth(string, length, &d, delta);
}
FontLocker locker(&font);
// StringHeight
float
DrawingEngine::StringHeight(const char *string, int32 length,
const DrawState *d)
{
FontLocker locker(d);
AGGTextRenderer* renderer = AGGTextRenderer::Default();
renderer->SetFont(font);
float height = 0.0;
// NOTE: For now it is enough to block on the
// font style lock, this already prevents multiple
// threads from executing this code and avoids a
// deadlock in case another thread holds the font
// lock already and then tries to lock the drawing
// engine after it is already locked here (race condition)
fPainter->SetDrawState(d, true);
BPoint dummy1(0.0, 0.0);
BPoint dummy2(0.0, 0.0);
height = fPainter->BoundingBox(string, length, dummy1, &dummy2).Height();
return height;
return renderer->StringWidth(string, length, delta);
}
// #pragma mark -

View File

@ -72,8 +72,13 @@ public:
void SetHighColor(const rgb_color& color);
void SetLowColor(const rgb_color& color);
void SetPenSize(float size);
void SetStrokeMode(cap_mode lineCap, join_mode joinMode,
float miterLimit);
void SetPattern(const struct pattern& pattern);
void SetDrawingMode(drawing_mode mode);
void SetBlendingMode(source_alpha srcAlpha,
alpha_function alphaFunc);
void SetFont(const ServerFont& font);
void SuspendAutoSync();
void Sync();
@ -85,24 +90,18 @@ public:
void InvertRect(BRect r);
void DrawBitmap(ServerBitmap *bitmap,
const BRect &source, const BRect &dest,
const DrawState *d);
const BRect &source, const BRect &dest);
// drawing primitives
void DrawArc(BRect r, const float &angle,
const float &span,
const DrawState *d,
bool filled);
const float &span, bool filled);
void DrawBezier(BPoint *pts, const DrawState *d,
bool filled);
void DrawBezier(BPoint *pts, bool filled);
void DrawEllipse(BRect r, const DrawState *d,
bool filled);
void DrawEllipse(BRect r, bool filled);
void DrawPolygon(BPoint *ptlist, int32 numpts,
BRect bounds, const DrawState *d,
bool filled, bool closed);
BRect bounds, bool filled, bool closed);
// these RGBColor versions are used internally by the server
void StrokePoint(const BPoint& pt,
@ -111,53 +110,49 @@ public:
void FillRect(BRect r, const RGBColor &color);
void FillRegion(BRegion& r, const RGBColor& color);
void StrokeRect(BRect r, const DrawState *d);
void FillRect(BRect r, const DrawState *d);
void StrokeRect(BRect r);
void FillRect(BRect r);
void FillRegion(BRegion& r, const DrawState *d);
void FillRegion(BRegion& r);
void DrawRoundRect(BRect r, float xrad,
float yrad, const DrawState *d,
bool filled);
float yrad, bool filled);
void DrawShape(const BRect& bounds,
int32 opcount, const uint32* oplist,
int32 ptcount, const BPoint* ptlist,
const DrawState* d, bool filled);
bool filled);
void DrawTriangle(BPoint* pts, const BRect& bounds,
const DrawState* d, bool filled);
bool filled);
// this version used by Decorator
void StrokeLine(const BPoint& start,
const BPoint& end, const RGBColor& color);
void StrokeLine(const BPoint& start,
const BPoint& end, DrawState* d);
const BPoint& end);
void StrokeLineArray(int32 numlines,
const LineArrayData* data,
const DrawState* d);
const LineArrayData* data);
// -------- text related calls
// DrawState is NOT const because this call updates the
// pen position in the passed DrawState
// returns the pen position behind the (virtually) drawn
// string
BPoint DrawString(const char* string, int32 length,
const BPoint& pt, DrawState* d,
const BPoint& pt,
escapement_delta* delta = NULL);
float StringWidth(const char* string, int32 length,
const DrawState* d,
escapement_delta* delta = NULL);
// convenience function which is independent of graphics
// state (to be used by Decorator or ServerApp etc)
float StringWidth(const char* string,
int32 length, const ServerFont& font,
escapement_delta* delta = NULL);
float StringHeight(const char* string,
int32 length, const DrawState* d);
private:
BRect _CopyRect(BRect r, int32 xOffset,
int32 yOffset) const;

View File

@ -47,6 +47,7 @@
#define CHECK_CLIPPING if (!fValidClipping) return BRect(0, 0, -1, -1);
#define CHECK_CLIPPING_NO_RETURN if (!fValidClipping) return;
// constructor
@ -82,12 +83,6 @@ Painter::Painter()
{
fPixelFormat.SetDrawingMode(fDrawingMode, fAlphaSrcMode, fAlphaFncMode, false);
// Usually, the drawing engine will lock the font for us when
// needed - unfortunately, it can't know we need it here
fFont.Lock();
_UpdateFont();
fFont.Unlock();
#if ALIASED_DRAWING
fRasterizer.gamma(agg::gamma_threshold(0.5));
#endif
@ -217,13 +212,32 @@ Painter::SetDrawingMode(drawing_mode mode)
}
}
// SetBlendingMode
void
Painter::SetBlendingMode(source_alpha srcAlpha, alpha_function alphaFunc)
{
if (fAlphaSrcMode != srcAlpha || fAlphaFncMode != alphaFunc) {
fAlphaSrcMode = srcAlpha;
fAlphaFncMode = alphaFunc;
if (fDrawingMode == B_OP_ALPHA)
_UpdateDrawingMode();
}
}
// SetPenSize
void
Painter::SetPenSize(float size)
{
if (fPenSize != size) {
fPenSize = size;
}
fPenSize = size;
}
// SetStrokeMode
void
Painter::SetStrokeMode(cap_mode lineCap, join_mode joinMode, float miterLimit)
{
fLineCapMode = lineCap;
fLineJoinMode = joinMode;
fMiterLimit = miterLimit;
}
// SetPattern
@ -258,36 +272,21 @@ void
Painter::SetFont(const ServerFont& font)
{
fFont = font;
_UpdateFont();
}
// #pragma mark - drawing
// StrokeLine
BRect
void
Painter::StrokeLine(BPoint a, BPoint b)
{
CHECK_CLIPPING
CHECK_CLIPPING_NO_RETURN
// "false" means not to do the pixel center offset,
// because it would mess up our optimized versions
_Transform(&a, false);
_Transform(&b, false);
BRect touched(min_c(a.x, b.x), min_c(a.y, b.y),
max_c(a.x, b.x), max_c(a.y, b.y));
// This is supposed to stop right here if we can see
// that we're definitaly outside the clipping reagion.
// Extending by penSize like that is not really correct,
// but fast and only triggers unnecessary calculation
// in a few edge cases
touched.InsetBy(-(fPenSize - 1), -(fPenSize - 1));
if (!touched.Intersects(fClippingRegion->Frame())) {
touched.Set(0.0, 0.0, -1.0, -1.0);
return touched;
}
// first, try an optimized version
if (fPenSize == 1.0
&& (fDrawingMode == B_OP_COPY || fDrawingMode == B_OP_OVER)) {
@ -295,10 +294,8 @@ Painter::StrokeLine(BPoint a, BPoint b)
pattern pat = *fPatternHandler.GetR5Pattern();
if (pat == B_SOLID_HIGH &&
StraightLine(a, b, fPatternHandler.HighColor().GetColor32())) {
return _Clipped(touched);
} else if (pat == B_SOLID_LOW &&
StraightLine(a, b, fPatternHandler.LowColor().GetColor32())) {
return _Clipped(touched);
}
}
@ -317,7 +314,7 @@ Painter::StrokeLine(BPoint a, BPoint b)
fPath.line_to(a.x + 1, a.y + 1);
fPath.line_to(a.x, a.y + 1);
touched = _FillPath(fPath);
_FillPath(fPath);
}
} else {
// do the pixel center offset here
@ -364,10 +361,8 @@ Painter::StrokeLine(BPoint a, BPoint b)
fPath.move_to(a.x, a.y);
fPath.line_to(b.x, b.y);
touched = _StrokePath(fPath);
_StrokePath(fPath);
}
return _Clipped(touched);
}
// StraightLine
@ -987,18 +982,27 @@ Painter::DrawString(const char* utf8String, uint32 length,
BRect bounds(0.0, 0.0, -1.0, -1.0);
// text is not rendered with patterns, but we need to
// make sure that the previous pattern is restored
pattern oldPattern = *fPatternHandler.GetR5Pattern();
SetPattern(B_SOLID_HIGH, true);
// make sure the text renderer is using our font (the global
// instance of the text renderer is used by everyone)
_UpdateFont();
bounds = fTextRenderer->RenderString(utf8String,
length,
&fRenderer,
&fRendererBin,
fUnpackedScanline,
baseLine,
fClippingRegion->Frame(),
false,
&fPenLocation,
delta);
SetPattern(oldPattern);
return _Clipped(bounds);
}
@ -1013,21 +1017,30 @@ Painter::BoundingBox(const char* utf8String, uint32 length,
baseLine.y = roundf(baseLine.y);
}
// make sure the text renderer is using our font (the global
// instance of the text renderer is used by everyone)
_UpdateFont();
static BRect dummy;
return fTextRenderer->RenderString(utf8String,
length,
&fRenderer,
&fRendererBin,
fUnpackedScanline,
baseLine, dummy, true, penLocation,
delta);
}
// StringWidth
float
Painter::StringWidth(const char* utf8String, uint32 length, const DrawState* context)
Painter::StringWidth(const char* utf8String, uint32 length,
const escapement_delta* delta)
{
SetFont(context->Font());
return fTextRenderer->StringWidth(utf8String, length);
// make sure the text renderer is using our font (the global
// instance of the text renderer is used by everyone)
_UpdateFont();
return fTextRenderer->StringWidth(utf8String, length, delta);
}
// #pragma mark -
@ -1133,7 +1146,7 @@ Painter::_Clipped(const BRect& rect) const
// _UpdateFont
void
Painter::_UpdateFont()
Painter::_UpdateFont() const
{
fTextRenderer->SetFont(fFont);
}

View File

@ -65,22 +65,36 @@ class Painter {
inline void SetLowColor(const RGBColor& color)
{ SetLowColor(color.GetColor32()); }
inline rgb_color LowColor() const
{ return fPatternHandler.
LowColor().GetColor32(); }
void SetPenSize(float size);
inline float PenSize() const
{ return fPenSize; }
void SetStrokeMode(cap_mode lineCap,
join_mode joinMode, float miterLimit);
void SetPattern(const pattern& p,
bool drawingText = false);
inline pattern Pattern() const
{ return *fPatternHandler.GetR5Pattern(); }
void SetDrawingMode(drawing_mode mode);
inline drawing_mode DrawingMode() const
{ return fDrawingMode; }
void SetBlendingMode(source_alpha srcAlpha,
alpha_function alphaFunc);
void SetPenLocation(const BPoint& location);
BPoint PenLocation() const
inline BPoint PenLocation() const
{ return fPenLocation; }
void SetFont(const ServerFont& font);
inline const ServerFont& Font() const
{ return fFont; }
// painting functions
// lines
BRect StrokeLine( BPoint a,
void StrokeLine( BPoint a,
BPoint b);
// returns true if the line was either vertical or horizontal
@ -174,7 +188,7 @@ class Painter {
float StringWidth( const char* utf8String,
uint32 length,
const DrawState* context);
const escapement_delta* delta = NULL);
// bitmaps
@ -197,7 +211,7 @@ class Painter {
bool centerOffset = true) const;
BRect _Clipped(const BRect& rect) const;
void _UpdateFont();
void _UpdateFont() const;
void _UpdateLineWidth();
void _UpdateDrawingMode(bool drawingText = false);
void _SetRendererColor(const rgb_color& color) const;

View File

@ -166,6 +166,7 @@ AGGTextRenderer::RenderString(const char* string,
uint32 length,
renderer_type* solidRenderer,
renderer_bin_type* binRenderer,
scanline_unpacked_type& scanline,
const BPoint& baseLine,
const BRect& clippingFrame,
bool dryRun,
@ -295,8 +296,6 @@ AGGTextRenderer::RenderString(const char* string,
case agg::glyph_data_outline: {
fRasterizer.reset();
// TODO: this currently falls into an endless loop - this is a quick fix to keep the
// app_server running - instead of the characters, their bounding boxes will be shown
if (fContour.width() == 0.0) {
fRasterizer.add_path(transformedOutline);
} else {
@ -314,7 +313,8 @@ AGGTextRenderer::RenderString(const char* string,
fRasterizer.add_path(ps);
#endif
agg::render_scanlines(fRasterizer, fScanline, *solidRenderer);
agg::render_scanlines(fRasterizer, scanline,
*solidRenderer);
break;
}
default:
@ -344,7 +344,8 @@ AGGTextRenderer::RenderString(const char* string,
double
AGGTextRenderer::StringWidth(const char* string, uint32 length)
AGGTextRenderer::StringWidth(const char* string, uint32 length,
const escapement_delta* delta)
{
// NOTE: The implementation does not take font rotation (or shear)
// into account. Just like on R5. Should it ever be desirable to
@ -370,6 +371,11 @@ AGGTextRenderer::StringWidth(const char* string, uint32 length)
if (!firstLoop && fKerning)
fFontCache.add_kerning(&width, &y);
width += glyph->advance_x;
if (delta) {
width += is_white_space(charCode) ?
delta->space : delta->nonspace;
}
}
firstLoop = false;

View File

@ -48,6 +48,7 @@ class AGGTextRenderer {
uint32 length,
renderer_type* solidRenderer,
renderer_bin_type* binRenderer,
scanline_unpacked_type& scanline,
const BPoint& baseLine,
const BRect& clippingFrame,
bool dryRun = false,
@ -55,7 +56,8 @@ class AGGTextRenderer {
const escapement_delta* delta = NULL);
double StringWidth(const char* utf8String,
uint32 length);
uint32 length,
const escapement_delta* delta = NULL);
private:
@ -72,10 +74,10 @@ class AGGTextRenderer {
conv_font_curve_type fCurves;
conv_font_contour_type fContour;
scanline_unpacked_type fScanline;
rasterizer_type fRasterizer;
// TODO: both of these are actually in Painter already
// and could be reused by this object
// NOTE: the object has it's own rasterizer object
// since it might be using a different gamma setting
// to support non-anti-aliased text rendering
char* fUnicodeBuffer;
int32 fUnicodeBufferSize;