Skip to content

Commit

Permalink
Traktor: SVG rasterizer implemented.
Browse files Browse the repository at this point in the history
  • Loading branch information
apistol78 committed Apr 25, 2024
1 parent 366d834 commit f0f66e0
Show file tree
Hide file tree
Showing 17 changed files with 619 additions and 165 deletions.
2 changes: 1 addition & 1 deletion code/Animation/Editor/AnimationBrowsePreview.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -122,7 +122,7 @@ Ref< ui::Bitmap > AnimationBrowsePreview::generate(editor::IEditor* editor, db::
raster.lineTo(e);
}
}
raster.stroke(ls, 2.0f, drawing::Raster::StrokeCap::Round);
raster.stroke(ls, 2.0f, drawing::Raster::StrokeJoin::Round, drawing::Raster::StrokeCap::Round);
raster.submit();

drawing::ScaleFilter scaleFilter(
Expand Down
5 changes: 5 additions & 0 deletions code/Core/Class/BoxedClassFactory.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -134,6 +134,11 @@ void BoxedClassFactory::createClasses(IRuntimeClassRegistrar* registrar) const
classBoxedColor4f->addProperty("green", &BoxedColor4f::setGreen, &BoxedColor4f::getGreen);
classBoxedColor4f->addProperty("blue", &BoxedColor4f::setBlue, &BoxedColor4f::getBlue);
classBoxedColor4f->addProperty("alpha", &BoxedColor4f::setAlpha, &BoxedColor4f::getAlpha);
classBoxedColor4f->addProperty("rgb0", &BoxedColor4f::rgb0);
classBoxedColor4f->addProperty("rgb1", &BoxedColor4f::rgb1);
classBoxedColor4f->addProperty("aaa0", &BoxedColor4f::aaa0);
classBoxedColor4f->addProperty("aaa1", &BoxedColor4f::aaa1);
classBoxedColor4f->addProperty("aaaa", &BoxedColor4f::aaaa);
classBoxedColor4f->addMethod("get", &BoxedColor4f::get);
classBoxedColor4f->addMethod("set", &BoxedColor4f::set);
classBoxedColor4f->addStaticMethod("lerp", &BoxedColor4f::lerp);
Expand Down
10 changes: 10 additions & 0 deletions code/Core/Class/Boxes/BoxedColor4f.h
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,16 @@ class T_DLLCLASS BoxedColor4f : public Boxed

void setAlpha(float alpha) { m_value.setAlpha(Scalar(alpha)); }

Color4f rgb0() const { return m_value.rgb0(); }

Color4f rgb1() const { return m_value.rgb1(); }

Color4f aaa0() const { return m_value.aaa0(); }

Color4f aaa1() const { return m_value.aaa1(); }

Color4f aaaa() const { return m_value.aaaa(); }

inline Color4f add(const BoxedColor4f* v) const { return m_value + v->m_value; }

inline Color4f sub(const BoxedColor4f* v) const { return m_value - v->m_value; }
Expand Down
13 changes: 8 additions & 5 deletions code/Drawing/DrawingClassFactory.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -184,9 +184,9 @@ void Raster_fill(Raster* self, int32_t style0, int32_t style1, int32_t fillRule)
self->fill(style0, style1, (Raster::FillRule)fillRule);
}

void Raster_stroke(Raster* self, int32_t style, float width, int32_t cap)
void Raster_stroke(Raster* self, int32_t style, float width, int32_t join, int32_t cap)
{
self->stroke(style, width, (Raster::StrokeCap)cap);
self->stroke(style, width, (Raster::StrokeJoin)join, (Raster::StrokeCap)cap);
}

}
Expand Down Expand Up @@ -369,9 +369,12 @@ void DrawingClassFactory::createClasses(IRuntimeClassRegistrar* registrar) const
registrar->registerClass(classBlendFunction);

auto classRaster = new AutoRuntimeClass< Raster >();
classRaster->addConstant("Butt", Any::fromInt32((int32_t)Raster::StrokeCap::Butt));
classRaster->addConstant("Square", Any::fromInt32((int32_t)Raster::StrokeCap::Square));
classRaster->addConstant("Round", Any::fromInt32((int32_t)Raster::StrokeCap::Round));
classRaster->addConstant("JoinMiter", Any::fromInt32((int32_t)Raster::StrokeJoin::Miter));
classRaster->addConstant("JoinRound", Any::fromInt32((int32_t)Raster::StrokeJoin::Round));
classRaster->addConstant("JoinBevel", Any::fromInt32((int32_t)Raster::StrokeJoin::Bevel));
classRaster->addConstant("CapButt", Any::fromInt32((int32_t)Raster::StrokeCap::Butt));
classRaster->addConstant("CapSquare", Any::fromInt32((int32_t)Raster::StrokeCap::Square));
classRaster->addConstant("CapRound", Any::fromInt32((int32_t)Raster::StrokeCap::Round));
classRaster->addConstant("OddEven", Any::fromInt32((int32_t)Raster::FillRule::OddEven));
classRaster->addConstant("NonZero", Any::fromInt32((int32_t)Raster::FillRule::NonZero));
classRaster->addConstructor();
Expand Down
137 changes: 93 additions & 44 deletions code/Drawing/Raster.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -75,7 +75,7 @@ class IRasterImpl : public IRefCount

virtual void fill(int32_t style0, int32_t style1, Raster::FillRule fillRule) = 0;

virtual void stroke(int32_t style, float width, Raster::StrokeCap cap) = 0;
virtual void stroke(int32_t style, float width, Raster::StrokeJoin join, Raster::StrokeCap cap) = 0;

virtual void submit() = 0;
};
Expand Down Expand Up @@ -431,10 +431,11 @@ template < typename pixfmt_type, typename color_type >
class RasterImpl : public RefCountImpl< IRasterImpl >
{
public:
RasterImpl(Image* image)
explicit RasterImpl(Image* image)
: m_rbuffer((agg::int8u*)image->getData(), image->getWidth(), image->getHeight(), image->getWidth() * image->getPixelFormat().getByteSize())
, m_pf(m_rbuffer)
, m_renderer(m_pf)
// , m_closed(false)
{
}

Expand Down Expand Up @@ -470,96 +471,132 @@ class RasterImpl : public RefCountImpl< IRasterImpl >

virtual void clear() override final
{
m_path.remove_all();
m_paths.resize(0);
m_current = nullptr;
}

virtual void moveTo(float x, float y) override final
{
m_path.move_to(x, y);
current().move_to(x, y);
}

virtual void lineTo(float x, float y) override final
{
m_path.line_to(x, y);
current().line_to(x, y);
}

virtual void quadricTo(float x1, float y1, float x, float y) override final
{
m_path.curve3(x1, y1, x, y);
current().curve3(x1, y1, x, y);
}

virtual void quadricTo(float x, float y) override final
{
m_path.curve3(x, y);
current().curve3(x, y);
}

virtual void cubicTo(float x1, float y1, float x2, float y2, float x, float y) override final
{
m_path.curve4(x1, y1, x2, y2, x, y);
current().curve4(x1, y1, x2, y2, x, y);
}

virtual void cubicTo(float x2, float y2, float x, float y) override final
{
m_path.curve4(x2, y2, x, y);
current().curve4(x2, y2, x, y);
}

virtual void close() override final
{
m_path.close_polygon();
m_current->second = true;
m_current = nullptr;
}

virtual void rect(float x, float y, float width, float height, float radius) override final
{
agg::rounded_rect r(x, y, x + width, y + height, radius);
r.normalize_radius();
m_path.concat_path(r);
current().concat_path(r);
}

virtual void circle(float x, float y, float radius) override final
{
agg::ellipse e(x, y, radius, radius);
m_path.concat_path(e);
current().concat_path(e);
}

virtual void fill(int32_t style0, int32_t style1, Raster::FillRule fillRule) override final
{
agg::conv_curve< agg::path_storage > curve(m_path);
for (auto& path : m_paths)
{
agg::path_storage p = path.first;
p.align_all_paths();

if (fillRule == Raster::FillRule::NonZero)
m_rasterizer.filling_rule(agg::fill_non_zero);
else // Raster::FillRule::OddEven
m_rasterizer.filling_rule(agg::fill_even_odd);
agg::conv_curve< agg::path_storage > curve(p);

m_rasterizer.styles(style0, style1);
m_rasterizer.add_path(curve);
if (fillRule == Raster::FillRule::NonZero)
m_rasterizer.filling_rule(agg::fill_non_zero);
else // Raster::FillRule::OddEven
m_rasterizer.filling_rule(agg::fill_even_odd);

m_rasterizer.styles(style0, style1);
m_rasterizer.add_path(curve);
}
}

virtual void stroke(int32_t style, float width, Raster::StrokeCap cap) override final
virtual void stroke(int32_t style, float width, Raster::StrokeJoin join, Raster::StrokeCap cap) override final
{
agg::conv_stroke< agg::path_storage > outline(m_path);
outline.width(width);

switch (cap)
for (auto& path : m_paths)
{
case Raster::StrokeCap::Butt:
outline.line_cap(agg::butt_cap);
break;

case Raster::StrokeCap::Square:
outline.line_cap(agg::square_cap);
break;

case Raster::StrokeCap::Round:
outline.line_cap(agg::round_cap);
break;
agg::path_storage p = path.first;
p.align_all_paths();

if (path.second)
p.close_polygon();

agg::conv_curve< agg::path_storage > curve(p);
agg::conv_stroke< agg::conv_curve< agg::path_storage > > outline(curve);
outline.width(width);

switch (join)
{
case Raster::StrokeJoin::Miter:
outline.line_join(agg::miter_join);
break;

case Raster::StrokeJoin::Round:
outline.line_join(agg::round_join);
break;

case Raster::StrokeJoin::Bevel:
outline.line_join(agg::bevel_join);
break;

default:
break;
}

switch (cap)
{
case Raster::StrokeCap::Butt:
outline.line_cap(agg::butt_cap);
break;

case Raster::StrokeCap::Square:
outline.line_cap(agg::square_cap);
break;

case Raster::StrokeCap::Round:
outline.line_cap(agg::round_cap);
break;

default:
break;
}

default:
break;
m_rasterizer.filling_rule(agg::fill_non_zero);
m_rasterizer.styles(-1, style);
m_rasterizer.add_path(outline);
}

m_rasterizer.filling_rule(agg::fill_non_zero);
m_rasterizer.styles(-1, style);
m_rasterizer.add_path(outline);
}

virtual void submit() override final
Expand Down Expand Up @@ -587,7 +624,19 @@ class RasterImpl : public RefCountImpl< IRasterImpl >
pixfmt_type m_pf;
agg::renderer_base< pixfmt_type > m_renderer;
agg::rasterizer_compound_aa<> m_rasterizer;
agg::path_storage m_path;
AlignedVector< std::pair< agg::path_storage, bool > > m_paths;
std::pair< agg::path_storage, bool >* m_current = nullptr;

agg::path_storage& current()
{
if (!m_current)
{
m_paths.push_back();
m_current = &m_paths.back();
m_current->second = false;
}
return m_current->first;
}
};

T_IMPLEMENT_RTTI_CLASS(L"traktor.drawing.Raster", Raster, Object)
Expand Down Expand Up @@ -705,9 +754,9 @@ void Raster::fill(int32_t style0, int32_t style1, FillRule fillRule)
m_impl->fill(style0, style1, fillRule);
}

void Raster::stroke(int32_t style, float width, StrokeCap cap)
void Raster::stroke(int32_t style, float width, StrokeJoin join, StrokeCap cap)
{
m_impl->stroke(style, width, cap);
m_impl->stroke(style, width, join, cap);
}

void Raster::submit()
Expand Down
9 changes: 8 additions & 1 deletion code/Drawing/Raster.h
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,13 @@ class T_DLLCLASS Raster : public Object
T_RTTI_CLASS;

public:
enum class StrokeJoin
{
Miter,
Round,
Bevel
};

enum class StrokeCap
{
Butt,
Expand Down Expand Up @@ -112,7 +119,7 @@ class T_DLLCLASS Raster : public Object

void fill(int32_t style0, int32_t style1, FillRule fillRule);

void stroke(int32_t style, float width, StrokeCap cap);
void stroke(int32_t style, float width, StrokeJoin join, StrokeCap cap);

void submit();

Expand Down
2 changes: 1 addition & 1 deletion code/Render/Editor/Shader/ShaderGraphBrowsePreview.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -108,7 +108,7 @@ Ref< ui::Bitmap > ShaderGraphBrowsePreview::generate(editor::IEditor* editor, db
raster.clear();
raster.moveTo(x1, y1);
raster.lineTo(x2, y2);
raster.stroke(edgeStyle, sw, drawing::Raster::StrokeCap::Round);
raster.stroke(edgeStyle, sw, drawing::Raster::StrokeJoin::Round, drawing::Raster::StrokeCap::Round);
}

for (auto node : nodes)
Expand Down
8 changes: 4 additions & 4 deletions code/Spark/Sw/SwDisplayRenderer.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -271,9 +271,9 @@ void SwDisplayRenderer::renderShape(const Dictionary& dictionary, const Matrix33
if (ls >= 0)
{
if (!m_writeMask)
m_raster->stroke(lineStyleBase + ls, lineStyles[ls].getLineWidth() * strokeScale, drawing::Raster::StrokeCap::Square);
m_raster->stroke(lineStyleBase + ls, lineStyles[ls].getLineWidth() * strokeScale, drawing::Raster::StrokeJoin::Round, drawing::Raster::StrokeCap::Square);
else
m_raster->stroke(0, lineStyles[ls].getLineWidth(), drawing::Raster::StrokeCap::Square);
m_raster->stroke(0, lineStyles[ls].getLineWidth(), drawing::Raster::StrokeJoin::Round, drawing::Raster::StrokeCap::Square);
}
}

Expand Down Expand Up @@ -504,9 +504,9 @@ void SwDisplayRenderer::renderCanvas(const Matrix33& transform, const Canvas& ca
if (ls >= 0)
{
if (!m_writeMask)
m_raster->stroke(lineStyleBase + ls, lineStyles[ls].getLineWidth() * strokeScale, drawing::Raster::StrokeCap::Square);
m_raster->stroke(lineStyleBase + ls, lineStyles[ls].getLineWidth() * strokeScale, drawing::Raster::StrokeJoin::Round, drawing::Raster::StrokeCap::Square);
else
m_raster->stroke(0, lineStyles[ls].getLineWidth(), drawing::Raster::StrokeCap::Square);
m_raster->stroke(0, lineStyles[ls].getLineWidth(), drawing::Raster::StrokeJoin::Round, drawing::Raster::StrokeCap::Square);
}
}

Expand Down
14 changes: 13 additions & 1 deletion code/Svg/ClassFactory.cpp
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
/*
* TRAKTOR
* Copyright (c) 2022 Anders Pistol.
* Copyright (c) 2022-2024 Anders Pistol.
*
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
Expand All @@ -14,13 +14,15 @@
#include "Core/Class/Boxes/BoxedRefArray.h"
#include "Core/Class/IRuntimeClassRegistrar.h"
#include "Core/Class/IRuntimeDelegate.h"
#include "Drawing/Image.h"
#include "Svg/ClassFactory.h"
#include "Svg/Document.h"
#include "Svg/Gradient.h"
#include "Svg/IShapeVisitor.h"
#include "Svg/Parser.h"
#include "Svg/Path.h"
#include "Svg/PathShape.h"
#include "Svg/Rasterizer.h"
#include "Svg/Shape.h"
#include "Svg/Style.h"
#include "Xml/Document.h"
Expand Down Expand Up @@ -135,7 +137,12 @@ void ClassFactory::createClasses(IRuntimeClassRegistrar* registrar) const
registrar->registerClass(classDocument);

auto classGradient = new AutoRuntimeClass< Gradient >();
classGradient->addProperty("bounds", &Gradient::setBounds, &Gradient::getBounds);
classGradient->addProperty("transform", &Gradient::setTransform, &Gradient::getTransform);
classGradient->addProperty("stopCount", &Gradient::getStopCount);
classGradient->addMethod("addStop", &Gradient::addStop);
classGradient->addMethod("getStopOffset", &Gradient::getStopOffset);
classGradient->addMethod("getStopColor", &Gradient::getStopColor);
registrar->registerClass(classGradient);

auto classIShapeVisitor = new AutoRuntimeClass< IShapeVisitor >();
Expand Down Expand Up @@ -201,6 +208,11 @@ void ClassFactory::createClasses(IRuntimeClassRegistrar* registrar) const
classStyle->addProperty("stroke", &Style::setStroke, &Style::getStroke);
classStyle->addProperty("opacity", &Style::setOpacity, &Style::getOpacity);
registrar->registerClass(classStyle);

auto classRasterizer = new AutoRuntimeClass< Rasterizer >();
classRasterizer->addConstructor();
classRasterizer->addMethod("raster", &Rasterizer::raster);
registrar->registerClass(classRasterizer);
}

}
Loading

0 comments on commit f0f66e0

Please sign in to comment.