StrokeGeometry.h header

#include <ew/app/StrokeGeometry.h>

Namespace ew::app

StrokeBounds struct

struct ew::app::StrokeBounds

The axis-aligned extent of a set of points.

Members

double ew::app::script::StrokeBounds::minX = 0.0

The smallest x of any point.

double ew::app::script::StrokeBounds::minY = 0.0

The smallest y of any point.

double ew::app::script::StrokeBounds::maxX = 0.0

The largest x of any point.

double ew::app::script::StrokeBounds::maxY = 0.0

The largest y of any point.

bool ew::app::script::StrokeBounds::valid = false

Whether any point contributed. False leaves the four edges at zero, so a caller cannot mistake an empty stroke's bounds for a point at the origin.

double ew::app::script::StrokeBounds::width() const

The extent's width.

double ew::app::script::StrokeBounds::height() const

The extent's height.

double ew::app::script::StrokeBounds::centerX() const

The x midway between the edges.

double ew::app::script::StrokeBounds::centerY() const

The y midway between the edges.

bool ew::app::script::StrokeBounds::operator==(const StrokeBounds &other) const =default

Value equality over all fields.

StrokeTransform struct

struct ew::app::StrokeTransform

An affine transform of glyph-box coordinates, as the six numbers of a 2x3 matrix.

One transform type serves both jobs that need one: the named ew::core::conlang::GlyphTransform a variant is derived by, and the free move/scale/rotate/skew a canvas selection is dragged through. Keeping them the same type means a variant and a hand edit cannot disagree about what "flip" means – which is exactly the confusion the axis-naming in GlyphTransform exists to stop.

Members

double ew::app::script::StrokeTransform::a = 1.0

Row 0, column 0 – the x scale.

double ew::app::script::StrokeTransform::b = 0.0

Row 1, column 0 – the y shear.

double ew::app::script::StrokeTransform::c = 0.0

Row 0, column 1 – the x shear.

double ew::app::script::StrokeTransform::d = 1.0

Row 1, column 1 – the y scale.

double ew::app::script::StrokeTransform::e = 0.0

Row 0, column 2 – the x translation.

double ew::app::script::StrokeTransform::f = 0.0

Row 1, column 2 – the y translation.

bool ew::app::script::StrokeTransform::operator==(const StrokeTransform &other) const =default

Value equality over all six coefficients.

Functions

ew::core::conlang::StrokePoint ew::app::script::apply(const StrokeTransform &transform, const ew::core::conlang::StrokePoint &point)

point moved by transform, keeping its pressure and corner flag – geometry moves, authored intent does not.

StrokeTransform ew::app::script::combined(const StrokeTransform &first, const StrokeTransform &second)

first followed by second (second applied to first's output).

StrokeTransform ew::app::script::glyphTransformMatrix(ew::core::conlang::GlyphTransform transform)

The transform realizing transform about the centre of the unit glyph box.

The axis each enumerator names is defined on ew::core::conlang::GlyphTransform and is honoured here exactly: MirrorY flips across the HORIZONTAL axis (y is negated, so the parts keep their left-to-right order) and MirrorX flips across the VERTICAL axis (x is negated, so the order reverses). Getting these the wrong way round makes a script that inverts meaning by flipping read backwards instead.

ew::core::conlang::Stroke ew::app::script::joined(const ew::core::conlang::Stroke &first, const ew::core::conlang::Stroke &second)

first and second as one stroke, second's points following first's.

When the two ends being joined coincide, the duplicate point is dropped – two points at the same place are a zero-length segment that every later operation has to special-case.

ew::core::conlang::Stroke ew::app::script::resampled(const ew::core::conlang::Stroke &stroke, double spacing)

stroke resampled so its points sit spacing apart along its length, interpolating pressure between the originals.

A freehand capture arrives as however many samples the pointer happened to emit – dense where the hand slowed, sparse where it moved fast – which makes every later operation depend on how quickly the user drew. Resampling makes the point density a property of the SHAPE.

A point the author marked a corner is always kept, and kept exactly: it is a statement about the letterform, not a sample, and moving it to the nearest even interval would round off the very feature it records.

ew::core::conlang::Stroke ew::app::script::reversed(const ew::core::conlang::Stroke &stroke)

stroke with its points in the opposite order, so it is drawn from the other end.

StrokeTransform ew::app::script::rotation(double degrees, double originX, double originY)

A transform that rotates degrees clockwise about (originX, originY).

StrokeTransform ew::app::script::scaling(double sx, double sy, double originX, double originY)

A transform that scales by (sx, sy) about (originX, originY).

ew::core::conlang::Stroke ew::app::script::simplified(const ew::core::conlang::Stroke &stroke, double tolerance)

stroke with the points that contribute less than tolerance to its shape removed (Ramer-Douglas-Peucker).

The endpoints and every corner point survive regardless of tolerance. Dropping a corner would silently discard an authored angle, and a simplify that can destroy intent is one the user cannot safely reach for.

StrokeTransform ew::app::script::skewing(double degreesX, double degreesY, double originX, double originY)

A transform that skews by degreesX along x and degreesY along y, about the given origin.

std::vector< ew::core::conlang::StrokePoint > ew::app::script::smoothedPolyline(const ew::core::conlang::Stroke &stroke, int samplesPerSegment)

stroke's smoothing curve evaluated into a dense polyline, samplesPerSegment points per original segment.

The stored stroke keeps the author's points; this is the RENDERING of them, which is why it returns a polyline rather than a modified stroke – writing the smoothed points back would let each save round the letterform a little further.

std::pair< ew::core::conlang::Stroke, ew::core::conlang::Stroke > ew::app::script::split(const ew::core::conlang::Stroke &stroke, qsizetype index)

stroke cut at index into the part up to and including that point and the part from it onward, so the point is shared and the drawing does not gain a gap.

An index outside the interior returns the whole stroke and an empty one: there is nothing to cut off an end.

StrokeBounds ew::app::script::strokeBounds(const ew::core::conlang::Stroke &stroke)

The extent of stroke's points.

double ew::app::script::strokeLength(const ew::core::conlang::Stroke &stroke)

The length of stroke's polyline, following its points in order (and closing it when the stroke is closed).

StrokeBounds ew::app::script::strokesBounds(const std::vector< ew::core::conlang::Stroke > &strokes)

The extent of every point of strokes – a whole glyph's bounds.

ew::core::conlang::Stroke ew::app::script::transformed(const ew::core::conlang::Stroke &stroke, const StrokeTransform &transform)

stroke with every point moved by transform.

StrokeTransform ew::app::script::translation(double dx, double dy)

A transform that moves by (dx, dy).