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.
This commit is contained in:
Adrien Destugues 2014-03-11 17:23:32 +01:00
parent 98e26ff242
commit eb43166326
13 changed files with 137 additions and 1 deletions

View File

@ -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 {

View File

@ -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;

View File

@ -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
};

View File

@ -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;

View File

@ -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;
@ -1992,6 +2000,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)
{

View File

@ -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();
@ -690,6 +691,13 @@ DrawState::SetMiterLimit(float limit)
}
void
DrawState::SetFillRule(int32 fillRule)
{
fFillRule = fillRule;
}
void
DrawState::PrintToStream() const
{

View File

@ -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;

View File

@ -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);

View File

@ -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: "

View File

@ -271,6 +271,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)
{

View File

@ -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,

View File

@ -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);
}

View File

@ -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;