hrev47005 adds 1 changeset to branch 'master' old head: 98e26ff2422c423dca23e08628b5f723727e5d42 new head: eb431663264ef319e72b492801fb867b5d71910b overview: http://cgit.haiku-os.org/haiku/log/?qt=range&q=eb43166+%5E98e26ff ---------------------------------------------------------------------------- eb43166: app_server & interface kit: support fill rules. * BView gets SetFillRule/FillRule methods. The fill rule is part of the view state. * The B_NONZERO rule is the default. This is what we implemented before. * The B_EVEN_ODD rule is the other common possibility for this, and we need to support it to help WebKit to render properly. [ Adrien Destugues <pulkomandy@xxxxxxxxxxxxx> ] ---------------------------------------------------------------------------- Revision: hrev47005 Commit: eb431663264ef319e72b492801fb867b5d71910b URL: http://cgit.haiku-os.org/haiku/commit/?id=eb43166 Author: Adrien Destugues <pulkomandy@xxxxxxxxxxxxx> Date: Tue Mar 11 16:23:32 2014 UTC ---------------------------------------------------------------------------- 13 files changed, 137 insertions(+), 1 deletion(-) headers/os/interface/InterfaceDefs.h | 8 ++++ headers/os/interface/View.h | 3 ++ headers/private/app/ServerProtocol.h | 4 ++ headers/private/interface/ViewPrivate.h | 6 ++- src/kits/interface/View.cpp | 53 +++++++++++++++++++++++++ src/servers/app/DrawState.cpp | 8 ++++ src/servers/app/DrawState.h | 5 +++ src/servers/app/ProfileMessageSupport.cpp | 2 + src/servers/app/ServerWindow.cpp | 25 ++++++++++++ src/servers/app/drawing/DrawingEngine.cpp | 7 ++++ src/servers/app/drawing/DrawingEngine.h | 1 + src/servers/app/drawing/Painter/Painter.cpp | 14 +++++++ src/servers/app/drawing/Painter/Painter.h | 2 + ---------------------------------------------------------------------------- diff --git a/headers/os/interface/InterfaceDefs.h b/headers/os/interface/InterfaceDefs.h index b1808cd..accef2c 100644 --- a/headers/os/interface/InterfaceDefs.h +++ b/headers/os/interface/InterfaceDefs.h @@ -261,6 +261,14 @@ enum cap_mode { const float B_DEFAULT_MITER_LIMIT = 10.0F; +// Polygon filling rules + +enum { + B_EVEN_ODD = 0, + B_NONZERO +}; + + // Bitmap and overlay constants enum bitmap_tiling { diff --git a/headers/os/interface/View.h b/headers/os/interface/View.h index bda8acd..84a63b0 100644 --- a/headers/os/interface/View.h +++ b/headers/os/interface/View.h @@ -282,6 +282,9 @@ public: cap_mode LineCapMode() const; float LineMiterLimit() const; + void SetFillRule(int32 rule); + int32 FillRule() const; + void SetOrigin(BPoint pt); void SetOrigin(float x, float y); BPoint Origin() const; diff --git a/headers/private/app/ServerProtocol.h b/headers/private/app/ServerProtocol.h index 782a578..e85f774 100644 --- a/headers/private/app/ServerProtocol.h +++ b/headers/private/app/ServerProtocol.h @@ -345,6 +345,10 @@ enum { AS_VIEW_SET_TRANSFORM, AS_VIEW_GET_TRANSFORM, + // Polygon filling rules + AS_VIEW_SET_FILL_RULE, + AS_VIEW_GET_FILL_RULE, + AS_LAST_CODE }; diff --git a/headers/private/interface/ViewPrivate.h b/headers/private/interface/ViewPrivate.h index 4be0f77..a9073d4 100644 --- a/headers/private/interface/ViewPrivate.h +++ b/headers/private/interface/ViewPrivate.h @@ -40,8 +40,9 @@ enum { B_VIEW_VIEW_COLOR_BIT = 0x00010000, B_VIEW_PATTERN_BIT = 0x00020000, B_VIEW_TRANSFORM_BIT = 0x00040000, + B_VIEW_FILL_RULE_BIT = 0x00080000, - B_VIEW_ALL_BITS = 0x0007ffff, + B_VIEW_ALL_BITS = 0x000fffff, // these used for archiving only B_VIEW_RESIZE_BIT = 0x00001000, @@ -123,6 +124,9 @@ class ViewState { cap_mode line_cap; float miter_limit; + // fill rule + int32 fill_rule; + // alpha blending source_alpha alpha_source_mode; alpha_function alpha_function_mode; diff --git a/src/kits/interface/View.cpp b/src/kits/interface/View.cpp index 9aaae85..c7395dd 100644 --- a/src/kits/interface/View.cpp +++ b/src/kits/interface/View.cpp @@ -149,6 +149,7 @@ ViewState::ViewState() line_join = B_MITER_JOIN; line_cap = B_BUTT_CAP; miter_limit = B_DEFAULT_MITER_LIMIT; + fill_rule = B_NONZERO; alpha_source_mode = B_PIXEL_ALPHA; alpha_function_mode = B_ALPHA_OVERLAY; @@ -494,6 +495,10 @@ BView::BView(BMessage* archive) && archive->FindFloat("_lmmiter", &lineMiter) == B_OK) SetLineMode((cap_mode)lineCap, (join_mode)lineJoin, lineMiter); + int16 fillRule; + if (archive->FindInt16("_fillrule", &fillRule) == B_OK) + SetFillRule(fillRule); + int16 alphaBlend; int16 modeBlend; if (archive->FindInt16("_blend", 0, &alphaBlend) == B_OK @@ -617,6 +622,9 @@ BView::Archive(BMessage* data, bool deep) const ret = data->AddFloat("_lmmiter", LineMiterLimit()); } + if (ret == B_OK && (fState->archiving_flags & B_VIEW_FILL_RULE_BIT) != 0) + ret = data->AddInt16("_fillrule", (int16)FillRule()); + if (ret == B_OK && (fState->archiving_flags & B_VIEW_BLENDING_BIT) != 0) { source_alpha alphaSourceMode; alpha_function alphaFunctionMode; @@ -1993,6 +2001,51 @@ BView::LineMiterLimit() const void +BView::SetFillRule(int32 fillRule) +{ + if (fState->IsValid(B_VIEW_FILL_RULE_BIT) && fillRule == fState->fill_rule) + return; + + if (fOwner) { + _CheckLockAndSwitchCurrent(); + + fOwner->fLink->StartMessage(AS_VIEW_SET_FILL_RULE); + fOwner->fLink->Attach<int32>(fillRule); + + fState->valid_flags |= B_VIEW_FILL_RULE_BIT; + } + + fState->fill_rule = fillRule; + + fState->archiving_flags |= B_VIEW_FILL_RULE_BIT; +} + + +int32 +BView::FillRule() const +{ + if (!fState->IsValid(B_VIEW_FILL_RULE_BIT) && fOwner) { + _CheckLockAndSwitchCurrent(); + + fOwner->fLink->StartMessage(AS_VIEW_GET_FILL_RULE); + + int32 code; + if (fOwner->fLink->FlushWithReply(code) == B_OK && code == B_OK) { + + int32 fillRule; + fOwner->fLink->Read<int32>(&fillRule); + + fState->fill_rule = fillRule; + } + + fState->valid_flags |= B_VIEW_FILL_RULE_BIT; + } + + return fState->fill_rule; +} + + +void BView::SetDrawingMode(drawing_mode mode) { if (fState->IsValid(B_VIEW_DRAWING_MODE_BIT) diff --git a/src/servers/app/DrawState.cpp b/src/servers/app/DrawState.cpp index c5b5ca3..6d1dd32 100644 --- a/src/servers/app/DrawState.cpp +++ b/src/servers/app/DrawState.cpp @@ -55,6 +55,7 @@ DrawState::DrawState() fLineCapMode(B_BUTT_CAP), fLineJoinMode(B_MITER_JOIN), fMiterLimit(B_DEFAULT_MITER_LIMIT), + fFillRule(B_NONZERO), fPreviousState(NULL) { fUnscaledFontSize = fFont.Size(); @@ -691,6 +692,13 @@ DrawState::SetMiterLimit(float limit) void +DrawState::SetFillRule(int32 fillRule) +{ + fFillRule = fillRule; +} + + +void DrawState::PrintToStream() const { printf("\t Origin: (%.1f, %.1f)\n", fOrigin.x, fOrigin.y); diff --git a/src/servers/app/DrawState.h b/src/servers/app/DrawState.h index 58ca037..48508ed 100644 --- a/src/servers/app/DrawState.h +++ b/src/servers/app/DrawState.h @@ -144,6 +144,10 @@ public: float MiterLimit() const { return fMiterLimit; } + void SetFillRule(int32 fillRule); + int32 FillRule() const + { return fFillRule; } + // convenience functions void PrintToStream() const; @@ -192,6 +196,7 @@ protected: cap_mode fLineCapMode; join_mode fLineJoinMode; float fMiterLimit; + int32 fFillRule; // "internal", used to calculate the size // of the font (again) when the scale changes float fUnscaledFontSize; diff --git a/src/servers/app/ProfileMessageSupport.cpp b/src/servers/app/ProfileMessageSupport.cpp index 519ebbf..1dbb357 100644 --- a/src/servers/app/ProfileMessageSupport.cpp +++ b/src/servers/app/ProfileMessageSupport.cpp @@ -256,6 +256,8 @@ string_for_message_code(uint32 code, BString& string) CODE(AS_VIEW_SCROLL); CODE(AS_VIEW_SET_LINE_MODE); CODE(AS_VIEW_GET_LINE_MODE); + CODE(AS_VIEW_SET_FILL_RULE); + CODE(AS_VIEW_GET_FILL_RULE); CODE(AS_VIEW_PUSH_STATE); CODE(AS_VIEW_POP_STATE); CODE(AS_VIEW_SET_SCALE); diff --git a/src/servers/app/ServerWindow.cpp b/src/servers/app/ServerWindow.cpp index fdeb467..88d1c02 100644 --- a/src/servers/app/ServerWindow.cpp +++ b/src/servers/app/ServerWindow.cpp @@ -1529,6 +1529,31 @@ fDesktop->LockSingleWindow(); break; } + case AS_VIEW_SET_FILL_RULE: + { + DTRACE(("ServerWindow %s: Message AS_VIEW_SET_FILL_RULE: " + "View: %s\n", Title(), fCurrentView->Name())); + int32 fillRule; + if (link.Read<int32>(&fillRule) != B_OK) + break; + + fCurrentView->CurrentState()->SetFillRule(fillRule); + fWindow->GetDrawingEngine()->SetFillRule(fillRule); + + break; + } + case AS_VIEW_GET_FILL_RULE: + { + DTRACE(("ServerWindow %s: Message AS_VIEW_GET_FILL_RULE: " + "View: %s\n", Title(), fCurrentView->Name())); + int32 fillRule = fCurrentView->CurrentState()->FillRule(); + + fLink.StartMessage(B_OK); + fLink.Attach<int32>(fillRule); + fLink.Flush(); + + break; + } case AS_VIEW_PUSH_STATE: { DTRACE(("ServerWindow %s: Message AS_VIEW_PUSH_STATE: View: " diff --git a/src/servers/app/drawing/DrawingEngine.cpp b/src/servers/app/drawing/DrawingEngine.cpp index 3fdc48f..e37ad03 100644 --- a/src/servers/app/drawing/DrawingEngine.cpp +++ b/src/servers/app/drawing/DrawingEngine.cpp @@ -272,6 +272,13 @@ DrawingEngine::SetStrokeMode(cap_mode lineCap, join_mode joinMode, void +DrawingEngine::SetFillRule(int32 fillRule) +{ + fPainter->SetFillRule(fillRule); +} + + +void DrawingEngine::SetBlendingMode(source_alpha srcAlpha, alpha_function alphaFunc) { fPainter->SetBlendingMode(srcAlpha, alphaFunc); diff --git a/src/servers/app/drawing/DrawingEngine.h b/src/servers/app/drawing/DrawingEngine.h index ce89487..dd15db2 100644 --- a/src/servers/app/drawing/DrawingEngine.h +++ b/src/servers/app/drawing/DrawingEngine.h @@ -76,6 +76,7 @@ public: virtual void SetPenSize(float size); virtual void SetStrokeMode(cap_mode lineCap, join_mode joinMode, float miterLimit); + virtual void SetFillRule(int32 fillRule); virtual void SetPattern(const struct pattern& pattern); virtual void SetDrawingMode(drawing_mode mode); virtual void SetDrawingMode(drawing_mode mode, diff --git a/src/servers/app/drawing/Painter/Painter.cpp b/src/servers/app/drawing/Painter/Painter.cpp index 2300d6c..95d5398 100644 --- a/src/servers/app/drawing/Painter/Painter.cpp +++ b/src/servers/app/drawing/Painter/Painter.cpp @@ -199,6 +199,7 @@ Painter::Painter() fLineCapMode(B_BUTT_CAP), fLineJoinMode(B_MITER_JOIN), fMiterLimit(B_DEFAULT_MITER_LIMIT), + fFillRule(B_NONZERO), fPatternHandler(), fTextRenderer(fSubpixRenderer, fRenderer, fRendererBin, fUnpackedScanline, @@ -423,6 +424,13 @@ Painter::SetStrokeMode(cap_mode lineCap, join_mode joinMode, float miterLimit) } +void +Painter::SetFillRule(int32 fillRule) +{ + fFillRule = fillRule; +} + + // SetPattern void Painter::SetPattern(const pattern& p, bool drawingText) @@ -2827,16 +2835,22 @@ Painter::_RasterizePath(VertexSource& path) const if (fMaskedUnpackedScanline != NULL) { // TODO: we can't do both alpha-masking and subpixel AA. fRasterizer.reset(); + fRasterizer.filling_rule( + fFillRule == B_EVEN_ODD ? agg::fill_even_odd : agg::fill_non_zero); fRasterizer.add_path(path); agg::render_scanlines(fRasterizer, *fMaskedUnpackedScanline, fRenderer); } else if (gSubpixelAntialiasing) { fSubpixRasterizer.reset(); + fSubpixRasterizer.filling_rule( + fFillRule == B_EVEN_ODD ? agg::fill_even_odd : agg::fill_non_zero); fSubpixRasterizer.add_path(path); agg::render_scanlines(fSubpixRasterizer, fSubpixPackedScanline, fSubpixRenderer); } else { fRasterizer.reset(); + fRasterizer.filling_rule( + fFillRule == B_EVEN_ODD ? agg::fill_even_odd : agg::fill_non_zero); fRasterizer.add_path(path); agg::render_scanlines(fRasterizer, fPackedScanline, fRenderer); } diff --git a/src/servers/app/drawing/Painter/Painter.h b/src/servers/app/drawing/Painter/Painter.h index 5042ed9..b2ccc49 100644 --- a/src/servers/app/drawing/Painter/Painter.h +++ b/src/servers/app/drawing/Painter/Painter.h @@ -81,6 +81,7 @@ public: { return fPenSize; } void SetStrokeMode(cap_mode lineCap, join_mode joinMode, float miterLimit); + void SetFillRule(int32 fillRule); void SetPattern(const pattern& p, bool drawingText = false); inline pattern Pattern() const @@ -394,6 +395,7 @@ private: cap_mode fLineCapMode; join_mode fLineJoinMode; float fMiterLimit; + int32 fFillRule; PatternHandler fPatternHandler;