Skip to content

Commit

Permalink
[Vector] Modified all path generators to take an agg::path_storage pa…
Browse files Browse the repository at this point in the history
…rameter
  • Loading branch information
paul-manias authored Apr 3, 2024
1 parent 02ad6a4 commit a819c74
Show file tree
Hide file tree
Showing 12 changed files with 127 additions and 128 deletions.
2 changes: 1 addition & 1 deletion src/vector/paths.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -256,7 +256,7 @@ void gen_vector_path(extVector *Vector)
if ((Vector->Dirty & RC::BASE_PATH) != RC::NIL) {
Vector->BasePath.free_all();

Vector->GeneratePath(Vector);
Vector->GeneratePath(Vector, Vector->BasePath);

if ((Vector->Morph) and (Vector->Morph->Class->BaseClassID IS ID_VECTOR)) {
if ((Vector->Class->ClassID IS ID_VECTORTEXT) and ((Vector->MorphFlags & VMF::STRETCH) IS VMF::NIL)) {
Expand Down
4 changes: 2 additions & 2 deletions src/vector/vector.h
Original file line number Diff line number Diff line change
Expand Up @@ -380,7 +380,7 @@ class extVector : public objVector {
agg::trans_affine Transform;
CSTRING FilterString, StrokeString, FillString;
STRING ID;
void (*GeneratePath)(extVector *);
void (*GeneratePath)(extVector *, agg::path_storage &);
agg::rasterizer_scanline_aa<> *StrokeRaster;
agg::rasterizer_scanline_aa<> *FillRaster;
std::vector<FeedbackSubscription> *FeedbackSubscriptions;
Expand Down Expand Up @@ -573,7 +573,7 @@ extern void apply_transition(objVectorTransition *, DOUBLE, agg::trans_affine &)
extern void apply_transition_xy(objVectorTransition *, DOUBLE, DOUBLE *, DOUBLE *);
extern void calc_aspectratio(CSTRING, ARF, DOUBLE, DOUBLE, DOUBLE, DOUBLE, DOUBLE *X, DOUBLE *Y, DOUBLE *, DOUBLE *);
extern void calc_full_boundary(extVector *, TClipRectangle<DOUBLE> &, bool IncludeSiblings = true, bool IncludeTransforms = true, bool IncludeStrokes = false);
extern void convert_to_aggpath(extVectorPath *, std::vector<PathCommand> &, agg::path_storage *);
extern void convert_to_aggpath(extVectorPath *, std::vector<PathCommand> &, agg::path_storage &);
extern void debug_tree(extVector *, LONG &);
extern void gen_vector_path(extVector *);
extern void gen_vector_tree(extVector *);
Expand Down
2 changes: 1 addition & 1 deletion src/vector/vector_functions.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -478,7 +478,7 @@ ERR vecGeneratePath(CSTRING Sequence, APTR *Path)
if ((error = read_path(paths, Sequence)) IS ERR::Okay) {
auto vector = new_simplevector();
if (vector) {
convert_to_aggpath(NULL, paths, &vector->mPath);
convert_to_aggpath(NULL, paths, vector->mPath);
*Path = vector;
}
else error = ERR::AllocMemory;
Expand Down
22 changes: 11 additions & 11 deletions src/vector/vectors/ellipse.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ class extVectorEllipse : public extVector {

//********************************************************************************************************************

static void generate_ellipse(extVectorEllipse *Vector)
static void generate_ellipse(extVectorEllipse *Vector, agg::path_storage &Path)
{
DOUBLE cx = Vector->eCX, cy = Vector->eCY;
DOUBLE rx = Vector->eRadiusX, ry = Vector->eRadiusY;
Expand All @@ -43,12 +43,12 @@ static void generate_ellipse(extVectorEllipse *Vector)
// is not good enough to make this viable at the current time.
// Top -> right -> bottom -> left -> top

Vector->BasePath.move_to(cx, cy-ry);
Vector->BasePath.arc_to(rx, ry, 0 /* angle */, 0 /* large */, 1 /* sweep */, cx+rx, cy);
Vector->BasePath.arc_to(rx, ry, 0, 0, 1, cx, cy+ry);
Vector->BasePath.arc_to(rx, ry, 0, 0, 1, cx-rx, cy);
Vector->BasePath.arc_to(rx, ry, 0, 0, 1, cx, cy-ry);
Vector->BasePath.close_polygon();
Path.move_to(cx, cy-ry);
Path.arc_to(rx, ry, 0 /* angle */, 0 /* large */, 1 /* sweep */, cx+rx, cy);
Path.arc_to(rx, ry, 0, 0, 1, cx, cy+ry);
Path.arc_to(rx, ry, 0, 0, 1, cx-rx, cy);
Path.arc_to(rx, ry, 0, 0, 1, cx, cy-ry);
Path.close_polygon();
#else
ULONG vertices;
if (Vector->eVertices >= 3) vertices = Vector->eVertices;
Expand All @@ -69,10 +69,10 @@ static void generate_ellipse(extVectorEllipse *Vector)
//if (m_cw) angle = 2.0 * agg::pi - angle;
DOUBLE x = cx + cos(angle) * rx;
DOUBLE y = cy + sin(angle) * ry;
if (v == 0) Vector->BasePath.move_to(x, y);
else Vector->BasePath.line_to(x, y);
if (v == 0) Path.move_to(x, y);
else Path.line_to(x, y);
}
Vector->BasePath.close_polygon();
Path.close_polygon();
#endif

Vector->Bounds = { cx - rx, cy - ry, cx + rx, cy + ry };
Expand Down Expand Up @@ -116,7 +116,7 @@ static ERR ELLIPSE_MoveToPoint(extVectorEllipse *Self, struct acMoveToPoint *Arg

static ERR ELLIPSE_NewObject(extVectorEllipse *Self, APTR Void)
{
Self->GeneratePath = (void (*)(extVector *))&generate_ellipse;
Self->GeneratePath = (void (*)(extVector *, agg::path_storage &))&generate_ellipse;
return ERR::Okay;
}

Expand Down
59 changes: 29 additions & 30 deletions src/vector/vectors/path.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -11,160 +11,159 @@ VectorPath provides support for parsing SVG styled path strings.

//********************************************************************************************************************

static void generate_path(extVectorPath *Vector)
static void generate_path(extVectorPath *Vector, agg::path_storage &Path)
{
// TODO: We may be able to drop our internal PathCommand type in favour of agg:path_storage (and
// extend it if necessary).
convert_to_aggpath(Vector, Vector->Commands, &Vector->BasePath);
Vector->Bounds = get_bounds(Vector->BasePath);
convert_to_aggpath(Vector, Vector->Commands, Path);
Vector->Bounds = get_bounds(Path);
}

//********************************************************************************************************************

void convert_to_aggpath(extVectorPath *Vector, std::vector<PathCommand> &Paths, agg::path_storage *BasePath)
void convert_to_aggpath(extVectorPath *Vector, std::vector<PathCommand> &Paths, agg::path_storage &BasePath)
{
PathCommand dummy = { PE::NIL, 0, 0, 0, 0, 0 };
PathCommand &lp = dummy;

bool lp_curved = false;
auto bp = BasePath;

for (size_t i=0; i < Paths.size(); i++) {
auto path = Paths[i];
switch (path.Type) {
case PE::Move:
path.AbsX = path.X;
path.AbsY = path.Y;
bp->move_to(path.AbsX, path.AbsY);
BasePath.move_to(path.AbsX, path.AbsY);
lp_curved = false;
break;

case PE::MoveRel:
path.AbsX = path.X + lp.AbsX;
path.AbsY = path.Y + lp.AbsY;
bp->move_to(path.AbsX, path.AbsY);
BasePath.move_to(path.AbsX, path.AbsY);
lp_curved = false;
break;

case PE::Line:
path.AbsX = path.X;
path.AbsY = path.Y;
bp->line_to(path.AbsX, path.AbsY);
BasePath.line_to(path.AbsX, path.AbsY);
lp_curved = false;
break;

case PE::LineRel:
path.AbsX = path.X + lp.AbsX;
path.AbsY = path.Y + lp.AbsY;
bp->line_to(path.AbsX, path.AbsY);
BasePath.line_to(path.AbsX, path.AbsY);
lp_curved = false;
break;

case PE::HLine:
path.AbsX = path.X;
path.AbsY = lp.AbsY;
bp->line_to(path.AbsX, path.AbsY);
BasePath.line_to(path.AbsX, path.AbsY);
lp_curved = false;
break;

case PE::HLineRel:
path.AbsX = path.X + lp.AbsX;
path.AbsY = lp.AbsY;
bp->line_to(path.AbsX, path.AbsY);
BasePath.line_to(path.AbsX, path.AbsY);
lp_curved = false;
break;

case PE::VLine:
path.AbsX = lp.AbsX;
path.AbsY = path.Y;
bp->line_to(path.AbsX, path.AbsY);
BasePath.line_to(path.AbsX, path.AbsY);
lp_curved = false;
break;

case PE::VLineRel:
path.AbsX = lp.AbsX;
path.AbsY = path.Y + lp.AbsY;
bp->line_to(path.AbsX, path.AbsY);
BasePath.line_to(path.AbsX, path.AbsY);
lp_curved = false;
break;

case PE::Curve: // curve4()
path.AbsX = path.X;
path.AbsY = path.Y;
bp->curve4(path.X2, path.Y2, path.X3, path.Y3, path.AbsX, path.AbsY);
BasePath.curve4(path.X2, path.Y2, path.X3, path.Y3, path.AbsX, path.AbsY);
lp_curved = true;
break;

case PE::CurveRel:
path.AbsX = lp.AbsX + path.X;
path.AbsY = lp.AbsY + path.Y;
bp->curve4(path.X2+lp.AbsX, path.Y2+lp.AbsY, path.X3+lp.AbsX, path.Y3+lp.AbsY, path.AbsX, path.AbsY);
BasePath.curve4(path.X2+lp.AbsX, path.Y2+lp.AbsY, path.X3+lp.AbsX, path.Y3+lp.AbsY, path.AbsX, path.AbsY);
lp_curved = true;
break;

case PE::Smooth:
case PE::Smooth:
// Simplified curve3/4 with one control inherited from the previous vertex
path.AbsX = path.X;
path.AbsY = path.Y;
if (!lp_curved) bp->curve3(path.X2, path.Y2, path.AbsX, path.AbsY);
else bp->curve4(path.X2, path.Y2, path.AbsX, path.AbsY);
if (!lp_curved) BasePath.curve3(path.X2, path.Y2, path.AbsX, path.AbsY);
else BasePath.curve4(path.X2, path.Y2, path.AbsX, path.AbsY);
lp_curved = true;
break;

case PE::SmoothRel:
path.AbsX = lp.AbsX + path.X;
path.AbsY = lp.AbsY + path.Y;
if (!lp_curved) bp->curve3(path.X2+lp.AbsX, path.Y2+lp.AbsY, path.AbsX, path.AbsY);
else bp->curve4(path.X2+lp.AbsX, path.Y2+lp.AbsY, path.AbsX, path.AbsY);
if (!lp_curved) BasePath.curve3(path.X2+lp.AbsX, path.Y2+lp.AbsY, path.AbsX, path.AbsY);
else BasePath.curve4(path.X2+lp.AbsX, path.Y2+lp.AbsY, path.AbsX, path.AbsY);
lp_curved = true;
break;

case PE::QuadCurve:
path.AbsX = path.X;
path.AbsY = path.Y;
bp->curve3(path.X2, path.Y2, path.AbsX, path.AbsY);
BasePath.curve3(path.X2, path.Y2, path.AbsX, path.AbsY);
lp_curved = true;
break;

case PE::QuadCurveRel:
path.AbsX = lp.AbsX + path.X;
path.AbsY = lp.AbsY + path.Y;
bp->curve3(path.X2+lp.AbsX, path.Y2+lp.AbsY, path.AbsX, path.AbsY);
BasePath.curve3(path.X2+lp.AbsX, path.Y2+lp.AbsY, path.AbsX, path.AbsY);
lp_curved = true;
break;

case PE::QuadSmooth: // Inherits a control from previous vertex
path.AbsX = path.X;
path.AbsY = path.Y;
bp->curve4(path.X2, path.Y2, path.AbsX, path.AbsY);
BasePath.curve4(path.X2, path.Y2, path.AbsX, path.AbsY);
lp_curved = true;
break;

case PE::QuadSmoothRel: // Inherits a control from previous vertex
path.AbsX = lp.AbsX + path.X;
path.AbsY = lp.AbsY + path.Y;
bp->curve4(path.X2+lp.AbsX, path.Y2+lp.AbsY, path.AbsX, path.AbsY);
BasePath.curve4(path.X2+lp.AbsX, path.Y2+lp.AbsY, path.AbsX, path.AbsY);
lp_curved = true;
break;

case PE::Arc:
path.AbsX = path.X;
path.AbsY = path.Y;
bp->arc_to(path.X2, path.Y2, path.Angle, path.LargeArc, path.Sweep, path.AbsX, path.AbsY);
BasePath.arc_to(path.X2, path.Y2, path.Angle, path.LargeArc, path.Sweep, path.AbsX, path.AbsY);
lp_curved = true;
break;

case PE::ArcRel:
path.AbsX = lp.AbsX + path.X;
path.AbsY = lp.AbsY + path.Y;
bp->arc_to(path.X2+lp.AbsX, path.Y2+lp.AbsY, path.Angle, path.LargeArc, path.Sweep, path.AbsX, path.AbsY);
BasePath.arc_to(path.X2+lp.AbsX, path.Y2+lp.AbsY, path.Angle, path.LargeArc, path.Sweep, path.AbsX, path.AbsY);
lp_curved = true;
break;

case PE::ClosePath:
path.AbsX = lp.AbsX; // Inherit the previous AbsX/Y values
path.AbsY = lp.AbsY;
bp->close_polygon();
BasePath.close_polygon();
break;

default:
Expand Down Expand Up @@ -212,7 +211,7 @@ static ERR VECTORPATH_Init(extVectorPath *Self, APTR Void)
static ERR VECTORPATH_NewObject(extVectorPath *Self, APTR Void)
{
new(&Self->Commands) std::vector<PathCommand>;
Self->GeneratePath = (void (*)(extVector *))&generate_path;
Self->GeneratePath = (void (*)(extVector *, agg::path_storage &))&generate_path;
return ERR::Okay;
}

Expand Down Expand Up @@ -406,10 +405,10 @@ static ERR VECTORPATH_SetCommandList(extVectorPath *Self, struct vpSetCommandLis
Commands: Direct pointer to the PathCommand array.
Read the Commands field to obtain a direct pointer to the PathCommand array. This will allow the control points of
the path to be modified directly, but it is not possible to resize the path. After making changes to the path, call
the path to be modified directly, but it is not possible to resize the path. After making changes to the path, call
#Flush() to register the changes for the next redraw.
This field can also be written at any time with a new array of PathCommand structures. Doing so will clear the
This field can also be written at any time with a new array of PathCommand structures. Doing so will clear the
existing path, if any.
*********************************************************************************************************************/
Expand Down
10 changes: 5 additions & 5 deletions src/vector/vectors/polygon.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ TODO: Add a SetPoint(DOUBLE X, DOUBLE Y) method for modifying existing points.

#define MAX_POINTS 1024 * 16 // Maximum of 16k points per polygon object.

static void generate_polygon(extVectorPoly *Vector)
static void generate_polygon(extVectorPoly *Vector, agg::path_storage &Path)
{
auto view_width = get_parent_width(Vector);
auto view_height = get_parent_height(Vector);
Expand All @@ -30,7 +30,7 @@ static void generate_polygon(extVectorPoly *Vector)
DOUBLE y = Vector->Points[0].Y;
if (Vector->Points[0].XScaled) x *= view_width;
if (Vector->Points[0].YScaled) y *= view_height;
Vector->BasePath.move_to(x, y);
Path.move_to(x, y);

DOUBLE min_x = x, max_x = x, min_y = y, max_y = y;

Expand All @@ -44,10 +44,10 @@ static void generate_polygon(extVectorPoly *Vector)
if (y < min_y) min_y = y;
if (x > max_x) max_x = x;
if (y > max_y) max_y = y;
Vector->BasePath.line_to(x, y);
Path.line_to(x, y);
}

if ((Vector->TotalPoints > 2) and (Vector->Closed)) Vector->BasePath.close_polygon();
if ((Vector->TotalPoints > 2) and (Vector->Closed)) Path.close_polygon();

Vector->Bounds = { min_x, min_y, max_x, max_y };
}
Expand Down Expand Up @@ -197,7 +197,7 @@ static ERR POLYGON_MoveToPoint(extVectorPoly *Self, struct acMoveToPoint *Args)

static ERR POLYGON_NewObject(extVectorPoly *Self, APTR Void)
{
Self->GeneratePath = (void (*)(extVector *))&generate_polygon;
Self->GeneratePath = (void (*)(extVector *, agg::path_storage &))&generate_polygon;
Self->Closed = TRUE;
Self->TotalPoints = 2;
if (AllocMemory(sizeof(VectorPoint) * Self->TotalPoints, MEM::DATA, &Self->Points) != ERR::Okay) return ERR::AllocMemory;
Expand Down
Loading

0 comments on commit a819c74

Please sign in to comment.