common fill: add fill-rule interface.

Fill rule is used to select how paths are filled.

For both fill rules, wheter or not a point is included in the fill is determined by taking a ray
from that point to infinity and looking at intersections with the path. The ray can be in any
direction, as long as it doens't pass through the end point of a segment or have a tricky
intersection such as intersecting tangent to the path.

@API Addtions:

enum class TVG_EXPORT FillRule { Winding = 0, EvenOdd };
Result Fill::rule(FillRule r) noexcept;
FillRule Fill::rule() const noexcept;

@Examples:

shape->rule(FillRule::EvenOdd);

@issue: 97
This commit is contained in:
Hermet Park 2020-10-20 19:36:26 +09:00 committed by Hermet Park
parent 380450c95b
commit 04aa038339
4 changed files with 21 additions and 1 deletions

View file

@ -56,6 +56,7 @@ enum class TVG_EXPORT PathCommand { Close = 0, MoveTo, LineTo, CubicTo };
enum class TVG_EXPORT StrokeCap { Square = 0, Round, Butt }; enum class TVG_EXPORT StrokeCap { Square = 0, Round, Butt };
enum class TVG_EXPORT StrokeJoin { Bevel = 0, Round, Miter }; enum class TVG_EXPORT StrokeJoin { Bevel = 0, Round, Miter };
enum class TVG_EXPORT FillSpread { Pad = 0, Reflect, Repeat }; enum class TVG_EXPORT FillSpread { Pad = 0, Reflect, Repeat };
enum class TVG_EXPORT FillRule { Winding = 0, EvenOdd };
enum class TVG_EXPORT CompositeMethod { None = 0, ClipPath }; enum class TVG_EXPORT CompositeMethod { None = 0, ClipPath };
enum class TVG_EXPORT CanvasEngine { Sw = (1 << 1), Gl = (1 << 2)}; enum class TVG_EXPORT CanvasEngine { Sw = (1 << 1), Gl = (1 << 2)};
@ -239,12 +240,14 @@ public:
//Fill //Fill
Result fill(uint8_t r, uint8_t g, uint8_t b, uint8_t a) noexcept; Result fill(uint8_t r, uint8_t g, uint8_t b, uint8_t a) noexcept;
Result fill(std::unique_ptr<Fill> f) noexcept; Result fill(std::unique_ptr<Fill> f) noexcept;
Result fill(FillRule r) noexcept;
//Getters //Getters
uint32_t pathCommands(const PathCommand** cmds) const noexcept; uint32_t pathCommands(const PathCommand** cmds) const noexcept;
uint32_t pathCoords(const Point** pts) const noexcept; uint32_t pathCoords(const Point** pts) const noexcept;
Result fill(uint8_t* r, uint8_t* g, uint8_t* b, uint8_t* a) const noexcept; Result fill(uint8_t* r, uint8_t* g, uint8_t* b, uint8_t* a) const noexcept;
const Fill* fill() const noexcept; const Fill* fill() const noexcept;
FillRule fillRule() const noexcept;
float strokeWidth() const noexcept; float strokeWidth() const noexcept;
Result strokeColor(uint8_t* r, uint8_t* g, uint8_t* b, uint8_t* a) const noexcept; Result strokeColor(uint8_t* r, uint8_t* g, uint8_t* b, uint8_t* a) const noexcept;

View file

@ -88,4 +88,4 @@ FillSpread Fill::spread() const noexcept
Fill* Fill::duplicate() const noexcept Fill* Fill::duplicate() const noexcept
{ {
return pImpl->duplicate(); return pImpl->duplicate();
} }

View file

@ -384,3 +384,17 @@ StrokeJoin Shape::strokeJoin() const noexcept
return pImpl->stroke->join; return pImpl->stroke->join;
} }
Result Shape::fill(FillRule r) noexcept
{
pImpl->rule = r;
return Result::Success;
}
FillRule Shape::fillRule() const noexcept
{
return pImpl->rule;
}

View file

@ -196,6 +196,7 @@ struct Shape::Impl
Fill *fill = nullptr; Fill *fill = nullptr;
ShapeStroke *stroke = nullptr; ShapeStroke *stroke = nullptr;
uint8_t color[4] = {0, 0, 0, 0}; //r, g, b, a uint8_t color[4] = {0, 0, 0, 0}; //r, g, b, a
FillRule rule = FillRule::Winding;
void *edata = nullptr; //engine data void *edata = nullptr; //engine data
Shape *shape = nullptr; Shape *shape = nullptr;
uint32_t flag = RenderUpdateFlag::None; uint32_t flag = RenderUpdateFlag::None;
@ -329,6 +330,7 @@ struct Shape::Impl
if (!ret) return nullptr; if (!ret) return nullptr;
auto dup = ret.get()->pImpl; auto dup = ret.get()->pImpl;
dup->rule = rule;
//Color //Color
memcpy(dup->color, color, sizeof(color)); memcpy(dup->color, color, sizeof(color));
@ -346,6 +348,7 @@ struct Shape::Impl
dup->flag |= RenderUpdateFlag::Stroke; dup->flag |= RenderUpdateFlag::Stroke;
} }
//Fill
if (fill) { if (fill) {
dup->fill = fill->duplicate(); dup->fill = fill->duplicate();
dup->flag |= RenderUpdateFlag::Gradient; dup->flag |= RenderUpdateFlag::Gradient;