From 0896fce5fb6672058acb2a99990d3a4cd082105c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Stephan=20A=C3=9Fmus?= Date: Wed, 18 Jul 2007 09:35:40 +0000 Subject: [PATCH] * since every window has it's own Painter instance, the drawing state does not need to be "set" (transfered from the "current" view to the painter) for each singly drawing command. Now, painter is synchronized whenever the client changes the drawing state of the current view, or when the current view changes. * the screen offset of the current view has become part of the Painter state, in the PatternHandler. This fixes a bug in which moving or scrolling a view which used patterns for drawing, resulted in visual glitches (seams in the pattern). NOTE: this patch is a bit work in progress, most importantly, it is not complete with regards to text rendering. More specifically, the server applications and other parts of the appserver might set a font on the Painter and this might mess up the synchronization. But this happens on the Desktop's Painter instance (only?), and so it is not a problem. I did observe some drawing bugs with this patch though, so bug reports are welcome, particularily how to reproduce these bugs reliably. git-svn-id: file:///srv/svn/repos/haiku/haiku/trunk@21643 a95241bf-73f2-0310-859d-f6bbb57e9c96 --- src/servers/app/ServerWindow.cpp | 115 +++++++++++++++----- src/servers/app/ServerWindow.h | 3 + src/servers/app/WindowLayer.cpp | 8 ++ src/servers/app/drawing/DrawingEngine.cpp | 104 +++++++++++++----- src/servers/app/drawing/DrawingEngine.h | 11 +- src/servers/app/drawing/Painter/Painter.cpp | 16 ++- src/servers/app/drawing/Painter/Painter.h | 15 ++- 7 files changed, 212 insertions(+), 60 deletions(-) diff --git a/src/servers/app/ServerWindow.cpp b/src/servers/app/ServerWindow.cpp index c4db76efb3..7380b47269 100644 --- a/src/servers/app/ServerWindow.cpp +++ b/src/servers/app/ServerWindow.cpp @@ -407,7 +407,8 @@ fDesktop->LockSingleWindow(); void ServerWindow::NotifyQuitRequested() { - // NOTE: if you do something else, other than sending a port message, PLEASE lock + // NOTE: if you do something else, other than sending a port message, + // PLEASE lock STRACE(("ServerWindow %s: Quit\n", fTitle)); BMessage msg(B_QUIT_REQUESTED); @@ -435,7 +436,8 @@ ServerWindow::NotifyMinimize(bool minimize) void ServerWindow::NotifyZoom() { - // NOTE: if you do something else, other than sending a port message, PLEASE lock + // NOTE: if you do something else, other than sending a port message, + // PLEASE lock BMessage msg(B_ZOOM); SendMessageToClient(&msg); } @@ -465,6 +467,13 @@ ServerWindow::GetInfo(window_info& info) } +void +ServerWindow::ResyncDrawState() +{ + _UpdateDrawState(fCurrentLayer); +} + + /*! Returns the ServerWindow's WindowLayer, if it exists and has been added to the Desktop already. @@ -1194,12 +1203,15 @@ ServerWindow::_DispatchViewMessage(int32 code, fCurrentLayer->CurrentState()->ReadFromLink(link); // TODO: When is this used?!? fCurrentLayer->RebuildClipping(true); + _UpdateDrawState(fCurrentLayer); + break; } case AS_LAYER_SET_FONT_STATE: { DTRACE(("ServerWindow %s: Message AS_LAYER_SET_FONT_STATE: ViewLayer name: %s\n", fTitle, fCurrentLayer->Name())); fCurrentLayer->CurrentState()->ReadFontFromLink(link); + _UpdateDrawState(fCurrentLayer); break; } case AS_LAYER_GET_STATE: @@ -1323,6 +1335,7 @@ ServerWindow::_DispatchViewMessage(int32 code, link.Read(&y); fCurrentLayer->SetDrawingOrigin(BPoint(x, y)); + _UpdateDrawState(fCurrentLayer); break; } case AS_LAYER_GET_ORIGIN: @@ -1382,6 +1395,7 @@ ServerWindow::_DispatchViewMessage(int32 code, uint32 flags; link.Read(&flags); fCurrentLayer->SetFlags(flags); + _UpdateDrawState(fCurrentLayer); STRACE(("ServerWindow %s: Message AS_LAYER_SET_FLAGS: ViewLayer: %s\n", Title(), fCurrentLayer->Name())); break; @@ -1411,7 +1425,9 @@ ServerWindow::_DispatchViewMessage(int32 code, fCurrentLayer->CurrentState()->SetLineCapMode((cap_mode)lineCap); fCurrentLayer->CurrentState()->SetLineJoinMode((join_mode)lineJoin); fCurrentLayer->CurrentState()->SetMiterLimit(miterLimit); - + + _UpdateDrawState(fCurrentLayer); + break; } case AS_LAYER_GET_LINE_MODE: @@ -1430,7 +1446,8 @@ ServerWindow::_DispatchViewMessage(int32 code, DTRACE(("ServerWindow %s: Message AS_LAYER_PUSH_STATE: ViewLayer: %s\n", Title(), fCurrentLayer->Name())); fCurrentLayer->PushState(); - + // TODO: is this necessary? + _UpdateDrawState(fCurrentLayer); break; } case AS_LAYER_POP_STATE: @@ -1438,7 +1455,7 @@ ServerWindow::_DispatchViewMessage(int32 code, DTRACE(("ServerWindow %s: Message AS_LAYER_POP_STATE: ViewLayer: %s\n", Title(), fCurrentLayer->Name())); fCurrentLayer->PopState(); - + _UpdateDrawState(fCurrentLayer); break; } case AS_LAYER_SET_SCALE: @@ -1448,6 +1465,7 @@ ServerWindow::_DispatchViewMessage(int32 code, link.Read(&scale); fCurrentLayer->SetScale(scale); + _UpdateDrawState(fCurrentLayer); break; } case AS_LAYER_GET_SCALE: @@ -1468,6 +1486,8 @@ ServerWindow::_DispatchViewMessage(int32 code, link.Read(&y); fCurrentLayer->CurrentState()->SetPenLocation(BPoint(x, y)); + // TODO: is this necessary? + _UpdateDrawState(fCurrentLayer); break; } case AS_LAYER_GET_PEN_LOC: @@ -1484,8 +1504,10 @@ ServerWindow::_DispatchViewMessage(int32 code, DTRACE(("ServerWindow %s: Message AS_LAYER_SET_PEN_SIZE: ViewLayer: %s\n", Title(), fCurrentLayer->Name())); float penSize; link.Read(&penSize); + fCurrentLayer->CurrentState()->SetPenSize(penSize); - + //_UpdateDrawState(fCurrentLayer); + fWindowLayer->GetDrawingEngine()->SetPenSize(penSize); break; } case AS_LAYER_GET_PEN_SIZE: @@ -1545,7 +1567,7 @@ ServerWindow::_DispatchViewMessage(int32 code, fCurrentLayer->CurrentState()->SetBlendingMode((source_alpha)srcAlpha, (alpha_function)alphaFunc); - + _UpdateDrawState(fCurrentLayer); break; } case AS_LAYER_GET_BLENDING_MODE: @@ -1566,7 +1588,8 @@ ServerWindow::_DispatchViewMessage(int32 code, link.Read(&drawingMode); fCurrentLayer->CurrentState()->SetDrawingMode((drawing_mode)drawingMode); - + //_UpdateDrawState(fCurrentLayer); + fWindowLayer->GetDrawingEngine()->SetDrawingMode((drawing_mode)drawingMode); break; } case AS_LAYER_GET_DRAWING_MODE: @@ -1633,8 +1656,10 @@ ServerWindow::_DispatchViewMessage(int32 code, { DTRACE(("ServerWindow %s: Message AS_LAYER_PRINT_ALIASING: ViewLayer: %s\n", Title(), fCurrentLayer->Name())); bool fontAliasing; - if (link.Read(&fontAliasing) == B_OK) + if (link.Read(&fontAliasing) == B_OK) { fCurrentLayer->CurrentState()->SetForceFontAliasing(fontAliasing); + _UpdateDrawState(fCurrentLayer); + } break; } case AS_LAYER_CLIP_TO_PICTURE: @@ -1782,6 +1807,8 @@ ServerWindow::_DispatchViewMessage(int32 code, link.Read(&c, sizeof(rgb_color)); fCurrentLayer->CurrentState()->SetHighColor(RGBColor(c)); +// _UpdateDrawState(fCurrentLayer); + fWindowLayer->GetDrawingEngine()->SetHighColor(c); break; } case AS_LAYER_SET_LOW_COLOR: @@ -1792,6 +1819,8 @@ ServerWindow::_DispatchViewMessage(int32 code, link.Read(&c, sizeof(rgb_color)); fCurrentLayer->CurrentState()->SetLowColor(RGBColor(c)); +// _UpdateDrawState(fCurrentLayer); + fWindowLayer->GetDrawingEngine()->SetLowColor(c); break; } case AS_LAYER_SET_PATTERN: @@ -1802,6 +1831,8 @@ ServerWindow::_DispatchViewMessage(int32 code, link.Read(&pat, sizeof(pattern)); fCurrentLayer->CurrentState()->SetPattern(Pattern(pat)); +// _UpdateDrawState(fCurrentLayer); + fWindowLayer->GetDrawingEngine()->SetPattern(pat); break; } case AS_SET_FONT: @@ -1819,7 +1850,11 @@ ServerWindow::_DispatchViewMessage(int32 code, } case AS_SYNC: { - // TODO: AS_SYNC is a no-op for now, just to get things working + // 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; @@ -1974,7 +2009,9 @@ ServerWindow::_DispatchViewDrawingMessage(int32 code, BPrivate::LinkReceiver &li } drawingEngine->LockParallelAccess(); - // TODO: avoid setting the region each time + // NOTE: the region is not copied, Painter keeps a pointer, + // that's why you need to use the clipping only for as long + // as you have it locked drawingEngine->ConstrainClippingRegion(&fCurrentDrawingRegion); switch (code) { @@ -2258,6 +2295,8 @@ ServerWindow::_DispatchViewDrawingMessage(int32 code, BPrivate::LinkReceiver &li fCurrentLayer->ConvertFromScreenForDrawing(&penLocation); fCurrentLayer->CurrentState()->SetPenLocation(penLocation); + // TODO: optimize with flags + _UpdateDrawState(fCurrentLayer); free(string); break; @@ -2837,29 +2876,49 @@ ServerWindow::HandleDirectConnection(int32 bufferState, int32 driverState) void ServerWindow::_SetCurrentLayer(ViewLayer* layer) { - if (fCurrentLayer != layer) { - fCurrentLayer = layer; - fCurrentDrawingRegionValid = false; + if (fCurrentLayer == layer) + return; + + fCurrentLayer = layer; + fCurrentDrawingRegionValid = false; + _UpdateDrawState(fCurrentLayer); + #if 0 #if DELAYED_BACKGROUND_CLEARING - if (fCurrentLayer && fCurrentLayer->IsBackgroundDirty() && fWindowLayer->InUpdate()) { - DrawingEngine* drawingEngine = fWindowLayer->GetDrawingEngine(); - if (drawingEngine->LockParallelAccess()) { - - fWindowLayer->GetEffectiveDrawingRegion(fCurrentLayer, fCurrentDrawingRegion); - fCurrentDrawingRegionValid = true; - BRegion dirty(fCurrentDrawingRegion); - - BRegion content; - fWindowLayer->GetContentRegion(&content); - - fCurrentLayer->Draw(drawingEngine, &dirty, &content, false); + if (fCurrentLayer && fCurrentLayer->IsBackgroundDirty() + && fWindowLayer->InUpdate()) { + DrawingEngine* drawingEngine = fWindowLayer->GetDrawingEngine(); + if (drawingEngine->LockParallelAccess()) { - drawingEngine->UnlockParallelAccess(); - } + fWindowLayer->GetEffectiveDrawingRegion(fCurrentLayer, fCurrentDrawingRegion); + fCurrentDrawingRegionValid = true; + BRegion dirty(fCurrentDrawingRegion); + + BRegion content; + fWindowLayer->GetContentRegion(&content); + + fCurrentLayer->Draw(drawingEngine, &dirty, &content, false); + + drawingEngine->UnlockParallelAccess(); } + } #endif #endif // 0 +} + + +void +ServerWindow::_UpdateDrawState(ViewLayer* layer) +{ + // switch the drawing state + // TODO: is it possible to scroll a view while it + // is being drawn? probably not... otherwise the + // "offsets" passed below would need to be updated again + DrawingEngine* drawingEngine = fWindowLayer->GetDrawingEngine(); + if (layer && drawingEngine) { + IntPoint p = layer->ScrollingOffset(); + p += IntPoint(layer->CurrentState()->Origin()); + drawingEngine->SetDrawState(layer->CurrentState(), p.x, p.y); } } diff --git a/src/servers/app/ServerWindow.h b/src/servers/app/ServerWindow.h index 4e3bd379ce..41d53ce94f 100644 --- a/src/servers/app/ServerWindow.h +++ b/src/servers/app/ServerWindow.h @@ -101,6 +101,8 @@ public: void GetInfo(window_info& info); + void ResyncDrawState(); + private: ViewLayer* _CreateLayerTree(BPrivate::LinkReceiver &link, ViewLayer **_parent); @@ -123,6 +125,7 @@ private: status_t _EnableDirectWindowMode(); void _SetCurrentLayer(ViewLayer* view); + void _UpdateDrawState(ViewLayer* view); // TODO: Move me elsewhere status_t PictureToRegion(ServerPicture *picture, diff --git a/src/servers/app/WindowLayer.cpp b/src/servers/app/WindowLayer.cpp index b5a997ded9..cc00e9aa3b 100644 --- a/src/servers/app/WindowLayer.cpp +++ b/src/servers/app/WindowLayer.cpp @@ -1784,6 +1784,14 @@ WindowLayer::_DrawBorder() engine->ConstrainClippingRegion(dirtyBorderRegion); fDecorator->Draw(dirtyBorderRegion->Frame()); +// TODO: remove this once the DrawState stuff is handled +// more cleanly. The reason why this is needed is that +// when the decorator draws strings, a draw state is set +// on the Painter object, and this is were it might get +// out of sync with what the ServerWindow things is the +// current DrawState set on the Painter +fWindow->ResyncDrawState(); + engine->UnlockParallelAccess(); } fRegionPool.Recycle(dirtyBorderRegion); diff --git a/src/servers/app/drawing/DrawingEngine.cpp b/src/servers/app/drawing/DrawingEngine.cpp index 7ef304e959..c2185dcecc 100644 --- a/src/servers/app/drawing/DrawingEngine.cpp +++ b/src/servers/app/drawing/DrawingEngine.cpp @@ -1,5 +1,5 @@ /* - * Copyright 2001-2005, Haiku, Inc. + * Copyright 2001-2007, Haiku, Inc. * Distributed under the terms of the MIT License. * * Authors: @@ -181,6 +181,53 @@ DrawingEngine::ConstrainClippingRegion(const BRegion* region) } +void +DrawingEngine::SetDrawState(const DrawState* state, int32 xOffset, int32 yOffset) +{ + fPainter->SetDrawState(state, false, xOffset, yOffset); +} + + +void +DrawingEngine::SetHighColor(const rgb_color& color) +{ + fPainter->SetHighColor(color); +} + + +void +DrawingEngine::SetLowColor(const rgb_color& color) +{ + fPainter->SetLowColor(color); +} + + +void +DrawingEngine::SetPenSize(float size) +{ + fPainter->SetPenSize(size); +} + + +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); +} + + +void +DrawingEngine::SetDrawingMode(drawing_mode mode) +{ + fPainter->SetDrawingMode(mode); +} + + +// #pragma mark - + + void DrawingEngine::SuspendAutoSync() { @@ -467,7 +514,7 @@ DrawingEngine::DrawBitmap(ServerBitmap *bitmap, if (clipped.IsValid()) { bool cursorTouched = fGraphicsCard->HideSoftwareCursor(clipped); - fPainter->SetDrawState(d); +// fPainter->SetDrawState(d); fPainter->DrawBitmap(bitmap, source, dest); fGraphicsCard->Invalidate(clipped); @@ -492,7 +539,7 @@ DrawingEngine::DrawArc(BRect r, const float &angle, if (clipped.IsValid()) { bool cursorTouched = fGraphicsCard->HideSoftwareCursor(clipped); - fPainter->SetDrawState(d); +// fPainter->SetDrawState(d); float xRadius = r.Width() / 2.0; float yRadius = r.Height() / 2.0; @@ -519,7 +566,7 @@ DrawingEngine::DrawBezier(BPoint *pts, const DrawState *d, bool filled) // TODO: figure out bounds and hide cursor depending on that fGraphicsCard->HideSoftwareCursor(); - fPainter->SetDrawState(d); +// fPainter->SetDrawState(d); BRect touched = fPainter->DrawBezier(pts, filled); fGraphicsCard->Invalidate(touched); @@ -549,7 +596,7 @@ DrawingEngine::DrawEllipse(BRect r, const DrawState *d, bool filled) if (clipped.IsValid()) { bool cursorTouched = fGraphicsCard->HideSoftwareCursor(clipped); - fPainter->SetDrawState(d); +// fPainter->SetDrawState(d); fPainter->DrawEllipse(r, filled); fGraphicsCard->Invalidate(clipped); @@ -573,7 +620,7 @@ DrawingEngine::DrawPolygon(BPoint* ptlist, int32 numpts, if (bounds.IsValid()) { bool cursorTouched = fGraphicsCard->HideSoftwareCursor(bounds); - fPainter->SetDrawState(d); +// fPainter->SetDrawState(d); fPainter->DrawPolygon(ptlist, numpts, filled, closed); fGraphicsCard->Invalidate(bounds); @@ -606,10 +653,15 @@ DrawingEngine::StrokeLine(const BPoint &start, const BPoint &end, bool cursorTouched = fGraphicsCard->HideSoftwareCursor(touched); if (!fPainter->StraightLine(start, end, color.GetColor32())) { - DrawState context; - context.SetHighColor(color); - context.SetDrawingMode(B_OP_OVER); - StrokeLine(start, end, &context); + // TODO: all this is quite expensive, but it is currently + // used only for the "gradient" decorator tab buttons + rgb_color previousColor = fPainter->HighColor(); + drawing_mode previousMode = fPainter->DrawingMode(); + fPainter->SetHighColor(color); + fPainter->SetDrawingMode(B_OP_OVER); + fPainter->StrokeLine(start, end); + fPainter->SetHighColor(previousColor); + fPainter->SetDrawingMode(previousMode); } else { fGraphicsCard->Invalidate(touched); } @@ -717,7 +769,7 @@ DrawingEngine::StrokeRect(BRect r, const DrawState *d) bool cursorTouched = fGraphicsCard->HideSoftwareCursor(clipped); - fPainter->SetDrawState(d); +// fPainter->SetDrawState(d); fPainter->StrokeRect(r); fGraphicsCard->Invalidate(clipped); @@ -763,7 +815,7 @@ DrawingEngine::FillRect(BRect r, const DrawState *d) } } if (doInSoftware) { - fPainter->SetDrawState(d); +// fPainter->SetDrawState(d); fPainter->FillRect(r); fGraphicsCard->Invalidate(r); @@ -806,7 +858,7 @@ DrawingEngine::FillRegion(BRegion& r, const DrawState *d) } if (doInSoftware) { - fPainter->SetDrawState(d); +// fPainter->SetDrawState(d); BRect touched = fPainter->FillRect(r.RectAt(0)); @@ -843,7 +895,7 @@ DrawingEngine::DrawRoundRect(BRect r, float xrad, float yrad, if (clipped.IsValid()) { bool cursorTouched = fGraphicsCard->HideSoftwareCursor(clipped); - fPainter->SetDrawState(d); +// fPainter->SetDrawState(d); BRect touched = filled ? fPainter->FillRoundRect(r, xrad, yrad) : fPainter->StrokeRoundRect(r, xrad, yrad); @@ -865,7 +917,7 @@ DrawingEngine::DrawShape(const BRect& bounds, int32 opCount, // shape is drawn on screen, TODO: optimize fGraphicsCard->HideSoftwareCursor(); - fPainter->SetDrawState(d); +// fPainter->SetDrawState(d); BRect touched = fPainter->DrawShape(opCount, opList, ptCount, ptList, filled); @@ -888,7 +940,7 @@ DrawingEngine::DrawTriangle(BPoint* pts, const BRect& bounds, if (clipped.IsValid()) { bool cursorTouched = fGraphicsCard->HideSoftwareCursor(clipped); - fPainter->SetDrawState(d); +// fPainter->SetDrawState(d); if (filled) fPainter->FillTriangle(pts[0], pts[1], pts[2]); else @@ -913,7 +965,7 @@ DrawingEngine::StrokeLine(const BPoint &start, const BPoint &end, DrawState* con if (touched.IsValid()) { bool cursorTouched = fGraphicsCard->HideSoftwareCursor(touched); - fPainter->SetDrawState(context); +// fPainter->SetDrawState(context); fPainter->StrokeLine(start, end); fGraphicsCard->Invalidate(touched); @@ -954,15 +1006,7 @@ DrawingEngine::StrokeLineArray(int32 numLines, data = (const LineArrayData *)&(linedata[0]); - DrawState context; - context.SetDrawingMode(d->GetDrawingMode()); - context.SetLowColor(d->LowColor()); - context.SetHighColor(data->color); - context.SetPenSize(d->PenSize()); - // pen size is already correctly scaled - - fPainter->SetDrawState(&context); - + fPainter->SetHighColor(data->color); fPainter->StrokeLine(data->pt1, data->pt2); for (int32 i = 1; i < numLines; i++) { @@ -971,6 +1015,9 @@ DrawingEngine::StrokeLineArray(int32 numLines, fPainter->StrokeLine(data->pt1, data->pt2); } + // restore correct drawing state highcolor + fPainter->SetHighColor(d->HighColor()); + fGraphicsCard->Invalidate(touched); if (cursorTouched) fGraphicsCard->ShowSoftwareCursor(); @@ -992,6 +1039,11 @@ DrawingEngine::DrawString(const char* string, int32 length, 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!?! diff --git a/src/servers/app/drawing/DrawingEngine.h b/src/servers/app/drawing/DrawingEngine.h index cbfe14a48a..23c830d86b 100644 --- a/src/servers/app/drawing/DrawingEngine.h +++ b/src/servers/app/drawing/DrawingEngine.h @@ -1,5 +1,5 @@ /* - * Copyright 2001-2005, Haiku, Inc. + * Copyright 2001-2007, Haiku, Inc. * Distributed under the terms of the MIT License. * * Authors: @@ -66,6 +66,15 @@ public: // will remove any clipping (drawing allowed everywhere) void ConstrainClippingRegion(const BRegion* region); + void SetDrawState(const DrawState* state, + int32 xOffset = 0, int32 yOffset = 0); + + void SetHighColor(const rgb_color& color); + void SetLowColor(const rgb_color& color); + void SetPenSize(float size); + void SetPattern(const struct pattern& pattern); + void SetDrawingMode(drawing_mode mode); + void SuspendAutoSync(); void Sync(); diff --git a/src/servers/app/drawing/Painter/Painter.cpp b/src/servers/app/drawing/Painter/Painter.cpp index 9990a6311e..9d3bb57756 100644 --- a/src/servers/app/drawing/Painter/Painter.cpp +++ b/src/servers/app/drawing/Painter/Painter.cpp @@ -1,5 +1,5 @@ /* - * Copyright 2005-2006, Stephan Aßmus . All rights reserved. + * Copyright 2005-2007, Stephan Aßmus . All rights reserved. * Distributed under the terms of the MIT License. * * API to the Anti-Grain Geometry based "Painter" drawing backend. Manages @@ -183,7 +183,8 @@ Painter::DetachFromBuffer() // SetDrawState void -Painter::SetDrawState(const DrawState* data, bool updateFont) +Painter::SetDrawState(const DrawState* data, bool updateFont, + int32 xOffset, int32 yOffset) { // NOTE: The custom clipping in "data" is ignored, because it has already been // taken into account elsewhere @@ -211,6 +212,7 @@ Painter::SetDrawState(const DrawState* data, bool updateFont) fAlphaSrcMode = data->AlphaSrcMode(); fAlphaFncMode = data->AlphaFncMode(); fPatternHandler->SetPattern(data->GetPattern()); + fPatternHandler->SetOffsets(xOffset, yOffset); fLineCapMode = data->LineCapMode(); fLineJoinMode = data->LineJoinMode(); fMiterLimit = data->MiterLimit(); @@ -258,6 +260,16 @@ Painter::SetLowColor(const rgb_color& color) _SetRendererColor(color); } +// SetDrawingMode +void +Painter::SetDrawingMode(drawing_mode mode) +{ + if (fDrawingMode != mode) { + fDrawingMode = mode; + _UpdateDrawingMode(); + } +} + // SetPenSize void Painter::SetPenSize(float size) diff --git a/src/servers/app/drawing/Painter/Painter.h b/src/servers/app/drawing/Painter/Painter.h index 490e3365f0..eaf1bffb13 100644 --- a/src/servers/app/drawing/Painter/Painter.h +++ b/src/servers/app/drawing/Painter/Painter.h @@ -1,5 +1,5 @@ /* - * Copyright 2005-2006, Stephan Aßmus . All rights reserved. + * Copyright 2005-2007, Stephan Aßmus . All rights reserved. * Distributed under the terms of the MIT License. * * API to the Anti-Grain Geometry based "Painter" drawing backend. Manages @@ -10,6 +10,7 @@ #define PAINTER_H #include "FontManager.h" +#include "PatternHandler.h" #include "RGBColor.h" #include "ServerFont.h" @@ -26,7 +27,6 @@ class AGGTextRenderer; class BBitmap; class BRegion; class DrawState; -class PatternHandler; class RenderingBuffer; class ServerBitmap; class ServerFont; @@ -65,13 +65,19 @@ class Painter { { return fClippingRegion; } void SetDrawState(const DrawState* data, - bool updateFont = false); + bool updateFont = false, + int32 xOffset = 0, + int32 yOffset = 0); // object settings void SetHighColor(const rgb_color& color); inline void SetHighColor(uint8 r, uint8 g, uint8 b, uint8 a = 255); inline void SetHighColor(const RGBColor& color) { SetHighColor(color.GetColor32()); } + inline rgb_color HighColor() const + { return fPatternHandler-> + HighColor().GetColor32(); } + void SetLowColor(const rgb_color& color); inline void SetLowColor(uint8 r, uint8 g, uint8 b, uint8 a = 255); inline void SetLowColor(const RGBColor& color) @@ -80,6 +86,9 @@ class Painter { void SetPenSize(float size); void SetPattern(const pattern& p, bool drawingText = false); + void SetDrawingMode(drawing_mode mode); + inline drawing_mode DrawingMode() const + { return fDrawingMode; } void SetPenLocation(const BPoint& location); BPoint PenLocation() const