From 38287e02afe4c0b08ae1c2c3279bb8d3a2e07fc2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Stephan=20A=C3=9Fmus?= Date: Sun, 22 Jul 2007 19:48:27 +0000 Subject: [PATCH] * 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 --- headers/private/app/ServerProtocol.h | 2 - src/servers/app/DefaultDecorator.cpp | 13 +- src/servers/app/ProfileMessageSupport.cpp | 2 - src/servers/app/RGBColor.h | 4 + src/servers/app/ServerApp.cpp | 18 +- src/servers/app/ServerFont.cpp | 4 +- src/servers/app/ServerPicture.cpp | 72 +++++--- src/servers/app/ServerWindow.cpp | 97 +++++----- src/servers/app/ViewLayer.cpp | 12 +- src/servers/app/WindowLayer.h | 1 - src/servers/app/drawing/DrawingEngine.cpp | 168 ++++++++---------- src/servers/app/drawing/DrawingEngine.h | 51 +++--- src/servers/app/drawing/Painter/Painter.cpp | 85 +++++---- src/servers/app/drawing/Painter/Painter.h | 22 ++- .../Painter/font_support/AGGTextRenderer.cpp | 14 +- .../Painter/font_support/AGGTextRenderer.h | 10 +- 16 files changed, 303 insertions(+), 272 deletions(-) diff --git a/headers/private/app/ServerProtocol.h b/headers/private/app/ServerProtocol.h index c50d1fd1d9..f8733bf014 100644 --- a/headers/private/app/ServerProtocol.h +++ b/headers/private/app/ServerProtocol.h @@ -212,8 +212,6 @@ enum { AS_FILL_TRIANGLE, AS_DRAW_STRING, - AS_SET_FONT, - AS_SET_FONT_SIZE, AS_SYNC, diff --git a/src/servers/app/DefaultDecorator.cpp b/src/servers/app/DefaultDecorator.cpp index 517243206a..5b8e28d1c4 100644 --- a/src/servers/app/DefaultDecorator.cpp +++ b/src/servers/app/DefaultDecorator.cpp @@ -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 diff --git a/src/servers/app/ProfileMessageSupport.cpp b/src/servers/app/ProfileMessageSupport.cpp index 4a46ed79d8..d766d55434 100644 --- a/src/servers/app/ProfileMessageSupport.cpp +++ b/src/servers/app/ProfileMessageSupport.cpp @@ -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; diff --git a/src/servers/app/RGBColor.h b/src/servers/app/RGBColor.h index c4ae960043..8d008e5e33 100644 --- a/src/servers/app/RGBColor.h +++ b/src/servers/app/RGBColor.h @@ -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; diff --git a/src/servers/app/ServerApp.cpp b/src/servers/app/ServerApp.cpp index d43e82d0d7..df0960c0d6 100644 --- a/src/servers/app/ServerApp.cpp +++ b/src/servers/app/ServerApp.cpp @@ -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]); } } diff --git a/src/servers/app/ServerFont.cpp b/src/servers/app/ServerFont.cpp index 44202ba3ae..7f176677f5 100644 --- a/src/servers/app/ServerFont.cpp +++ b/src/servers/app/ServerFont.cpp @@ -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; diff --git a/src/servers/app/ServerPicture.cpp b/src/servers/app/ServerPicture.cpp index 888cc8da76..f6d01c9fae 100644 --- a/src/servers/app/ServerPicture.cpp +++ b/src/servers/app/ServerPicture.cpp @@ -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()); } diff --git a/src/servers/app/ServerWindow.cpp b/src/servers/app/ServerWindow.cpp index 9d04491273..64fd8d960c 100644 --- a/src/servers/app/ServerWindow.cpp +++ b/src/servers/app/ServerWindow.cpp @@ -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(&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(&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(&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(&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(&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(&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(®ion); - 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); diff --git a/src/servers/app/ViewLayer.cpp b/src/servers/app/ViewLayer.cpp index 24cb5c4cb4..0a4c76949e 100644 --- a/src/servers/app/ViewLayer.cpp +++ b/src/servers/app/ViewLayer.cpp @@ -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); } diff --git a/src/servers/app/WindowLayer.h b/src/servers/app/WindowLayer.h index 8c0e7773ee..c104b4fc9f 100644 --- a/src/servers/app/WindowLayer.h +++ b/src/servers/app/WindowLayer.h @@ -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; } diff --git a/src/servers/app/drawing/DrawingEngine.cpp b/src/servers/app/drawing/DrawingEngine.cpp index c2185dcecc..dcfe82f449 100644 --- a/src/servers/app/drawing/DrawingEngine.cpp +++ b/src/servers/app/drawing/DrawingEngine.cpp @@ -13,6 +13,7 @@ #include #include +#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 - diff --git a/src/servers/app/drawing/DrawingEngine.h b/src/servers/app/drawing/DrawingEngine.h index 23c830d86b..3070ac18e4 100644 --- a/src/servers/app/drawing/DrawingEngine.h +++ b/src/servers/app/drawing/DrawingEngine.h @@ -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; diff --git a/src/servers/app/drawing/Painter/Painter.cpp b/src/servers/app/drawing/Painter/Painter.cpp index 49153d633a..26731c0b5b 100644 --- a/src/servers/app/drawing/Painter/Painter.cpp +++ b/src/servers/app/drawing/Painter/Painter.cpp @@ -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); } diff --git a/src/servers/app/drawing/Painter/Painter.h b/src/servers/app/drawing/Painter/Painter.h index 808d1483d8..24149f7508 100644 --- a/src/servers/app/drawing/Painter/Painter.h +++ b/src/servers/app/drawing/Painter/Painter.h @@ -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; diff --git a/src/servers/app/drawing/Painter/font_support/AGGTextRenderer.cpp b/src/servers/app/drawing/Painter/font_support/AGGTextRenderer.cpp index 5619e74a1b..08f83a1886 100644 --- a/src/servers/app/drawing/Painter/font_support/AGGTextRenderer.cpp +++ b/src/servers/app/drawing/Painter/font_support/AGGTextRenderer.cpp @@ -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; diff --git a/src/servers/app/drawing/Painter/font_support/AGGTextRenderer.h b/src/servers/app/drawing/Painter/font_support/AGGTextRenderer.h index e26ba8c522..ad5bfa34b5 100644 --- a/src/servers/app/drawing/Painter/font_support/AGGTextRenderer.h +++ b/src/servers/app/drawing/Painter/font_support/AGGTextRenderer.h @@ -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;