CanvasTools.h header
#include <ew/app/CanvasTools.h>
Namespace ew::app
BezierNode struct
struct ew::app::BezierNode
One node of a Bezier pen path.
The pen is the one drawing tool whose gesture carries more than a position: a click places a corner and a drag pulls a handle out of it, and the curve leaving the node follows that handle. Modelled here rather than in the widget so the curve a given run of gestures produces can be checked without a window.
Members
ew::core::conlang::StrokePoint ew::app::script::BezierNode::anchor
Where the path passes through.
ew::core::conlang::StrokePoint ew::app::script::BezierNode::handle
The handle dragged out of the anchor, shaping the curve that LEAVES it. Equal to the anchor for a corner, which is what a click with no drag gives.
bool ew::app::script::BezierNode::operator==(const BezierNode &other) const =default
Value equality over all fields.
CanvasView struct
struct ew::app::CanvasView
Where the glyph box sits within the canvas widget, in pixels.
The one place pointer positions and model coordinates meet. Kept as data rather than as widget state so the mapping – including what a grab radius in pixels means once the user has zoomed in – can be checked directly.
Members
double ew::app::script::CanvasView::originX = 0.0
The widget x of the glyph box's left edge.
double ew::app::script::CanvasView::originY = 0.0
The widget y of the glyph box's top edge.
double ew::app::script::CanvasView::width = 1.0
How many pixels across the box spans.
double ew::app::script::CanvasView::height = 1.0
How many pixels down it spans.
bool ew::app::script::CanvasView::operator==(const CanvasView &other) const =default
Value equality over all fields.
PixelPoint struct
struct ew::app::PixelPoint
A position in widget pixels.
Members
double ew::app::script::PixelPoint::x = 0.0
Pixels from the widget's left edge.
double ew::app::script::PixelPoint::y = 0.0
Pixels from its top edge.
bool ew::app::script::PixelPoint::operator==(const PixelPoint &other) const =default
Value equality over all fields.
ToolOptions struct
struct ew::app::ToolOptions
The settings the shape tools read, all live on the canvas's options row.
Members
int ew::app::script::ToolOptions::sides = 5
Vertices for the polygon, spikes for the star.
double ew::app::script::ToolOptions::innerRatio = 0.5
A star's inner radius as a fraction of its outer one.
double ew::app::script::ToolOptions::cornerRadius = 0.1
A rounded rectangle's corner radius, in glyph-box units.
int ew::app::script::ToolOptions::segments = 24
How many points a curve, arc or ellipse is flattened into. More is smoother and heavier to edit; this is the trade the user makes by eye, so it is a setting rather than a constant.
bool ew::app::script::ToolOptions::constrainSquare = false
Whether the shape is constrained to a square aspect – what holding Shift does.
bool ew::app::script::ToolOptions::fromCentre = false
Whether the drag starts at the shape's centre rather than at one corner of its box.
bool ew::app::script::ToolOptions::operator==(const ToolOptions &other) const =default
Value equality over all fields.
Enumerations
enum class CanvasTool { Freehand, Line, Rectangle, RoundedRectangle, Ellipse, Circle, Polygon, Star, Arc, Bezier, Polyline, Eraser, Select, Lasso, Edit }
Which tool the pointer drives on the glyph canvas.
One enum covering drawing, selection and point editing, because the canvas has exactly one pointer and a tool is what it currently means. Every DRAWING entry ends up in ew::app::script::StrokeShapes, so each produces the same editable primitive.
Functions
ew::core::conlang::Stroke ew::app::script::bezierStroke(const std::vector< BezierNode > &nodes, bool closed, int segments)
The stroke nodes describe, each span a cubic between consecutive anchors.
The handle leaving a node and the one arriving at the next are mirror images about that next anchor, which is what makes a pen path smooth THROUGH a node rather than kinked at it. closed runs a final span from the last anchor back to the first. segments points per span.
std::optional< CanvasTool > ew::app::script::canvasToolFromToken(QStringView token)
Parses a canvas tool from its token; std::nullopt if unrecognized.
CanvasView ew::app::script::fittedView(double widgetWidth, double widgetHeight, double boxAspect, double margin)
The view that centres a box of boxAspect (width over height) in a widget widgetWidth by widgetHeight, leaving margin pixels clear on every side.
The aspect is honoured rather than stretched: a tall narrow script drawn into a square would be designed at proportions it will never be read at.
ew::core::conlang::StrokePoint ew::app::script::glyphPoint(const CanvasView &view, double pixelX, double pixelY, double pressure)
The glyph-box coordinate the widget position (pixelX, pixelY) names, carrying pressure.
double ew::app::script::grabRadius(const CanvasView &view)
The grab radius to use in view, in glyph-box units.
Derived FROM the view rather than fixed in model units, so the handle is the same reachable size on screen at every zoom: a constant in glyph units would be an unusable 50-odd pixels once the user zoomed in to work on a detail, grabbing the neighbouring point instead of the intended one.
bool ew::app::script::isClickTool(CanvasTool tool)
Whether tool builds a stroke from a run of separate clicks, finished deliberately.
bool ew::app::script::isDragTool(CanvasTool tool)
Whether tool builds a stroke from one press-drag-release.
bool ew::app::script::isDrawTool(CanvasTool tool)
Whether tool produces strokes at all (as opposed to selecting or editing existing ones).
CanvasView ew::app::script::panned(const CanvasView &view, double dxPixels, double dyPixels)
view moved by (dxPixels, dyPixels).
double ew::app::script::pixelsToGlyphUnits(const CanvasView &view, double pixels)
pixels expressed in glyph-box units under view.
ew::core::conlang::Stroke ew::app::script::strokeForClicks(CanvasTool tool, const std::vector< ew::core::conlang::StrokePoint > &points, const ToolOptions &options)
The stroke the clicked or sampled points make with tool.
Freehand keeps every sample and curves through them; the polyline keeps them as corners. Both are the same primitive afterwards – the difference is only what the user meant by placing them.
ew::core::conlang::Stroke ew::app::script::strokeForDrag(CanvasTool tool, const ew::core::conlang::StrokePoint &start, const ew::core::conlang::StrokePoint ¤t, const ToolOptions &options)
The stroke a drag from start to current makes with tool.
Returns an empty stroke for a tool that is not driven by a drag, so a caller that asks the wrong question gets nothing rather than a shape the user did not draw.
QString ew::app::script::toToken(CanvasTool tool)
The stable serialization token for tool (e.g. "freehand").
PixelPoint ew::app::script::widgetPoint(const CanvasView &view, const ew::core::conlang::StrokePoint &point)
The widget position point sits at.
CanvasView ew::app::script::zoomedAbout(const CanvasView &view, double factor, double pixelX, double pixelY)
view scaled by factor about the widget position (pixelX, pixelY).
About the POINTER, not the centre: zooming toward the cursor is what lets a user work into a detail without also having to pan back to it after every step.
Constants
double ew::app::script::kMinimumGrabPixels = 14.0
The fewest pixels a click may miss a point by and still grab it.
The prototype used four, and a near miss then registered as a click on empty canvas and added a stray point – its single most-reported bug. Fourteen is the figure the brief asks for.