7#include "bezier_point.hpp"
8#include "bezier_curve.hpp"
10#include "../utility/utility.hpp"
11#include "../geometry/module.hpp"
12#include "../image/module.hpp"
13#include "../macros.hpp"
16hi_export_module(hikogui.graphic_path);
18namespace hi {
inline namespace v1 {
73 if (
color != firstColor) {
90 for (hilet& point :
points) {
123 [[nodiscard]] std::vector<bezier_point>::const_iterator endContour(
ssize_t contourNr)
const noexcept
142 [[nodiscard]] std::vector<bezier_point> getbezier_pointsOfContour(
ssize_t contourNr)
const noexcept
149 [[nodiscard]] std::vector<bezier_curve> getBeziersOfContour(
ssize_t contourNr)
const noexcept
152 auto last = endContour(contourNr);
154 if (num_points < 3) {
163 [[nodiscard]] std::vector<bezier_curve> getBeziers() const noexcept
167 std::vector<bezier_curve> r;
170 hilet beziers = getBeziersOfContour(contourNr);
171 r.
insert(r.
end(), beziers.begin(), beziers.end());
176 [[nodiscard]] std::pair<graphic_path, color> getLayer(
ssize_t layerNr)
const noexcept
180 auto path = graphic_path{};
182 hilet
begin = beginLayer(layerNr);
183 hilet
end = endLayer(layerNr);
185 path.addContour(
beginContour(contourNr), endContour(contourNr));
188 return {path, getColorOfLayer(layerNr)};
191 [[nodiscard]] color getColorOfLayer(
ssize_t layerNr)
const noexcept
196 void setColorOfLayer(
ssize_t layerNr, color fill_color)
noexcept
272 if (prev_i->second != i->second) {
273 tmp.push_back(*prev_i);
278 tmp.push_back(*prev_i);
301 points.emplace_back(position, bezier_point::Type::Anchor);
313 points.emplace_back(lastPosition + direction, bezier_point::Type::Anchor);
316 void lineTo(point2 position)
noexcept
320 points.emplace_back(position, bezier_point::Type::Anchor);
323 void lineRelativeTo(
vector2 direction)
noexcept
330 void quadraticCurveTo(point2 controlPosition, point2 position)
noexcept
334 points.emplace_back(controlPosition, bezier_point::Type::QuadraticControl);
335 points.emplace_back(position, bezier_point::Type::Anchor);
347 points.emplace_back(p + controlDirection, bezier_point::Type::QuadraticControl);
348 points.emplace_back(p + direction, bezier_point::Type::Anchor);
351 void cubicCurveTo(point2 controlPosition1, point2 controlPosition2, point2 position)
noexcept
355 points.emplace_back(controlPosition1, bezier_point::Type::CubicControl1);
356 points.emplace_back(controlPosition2, bezier_point::Type::CubicControl2);
357 points.emplace_back(position, bezier_point::Type::Anchor);
370 points.emplace_back(p + controlDirection1, bezier_point::Type::CubicControl1);
371 points.emplace_back(p + controlDirection2, bezier_point::Type::CubicControl2);
372 points.emplace_back(p + direction, bezier_point::Type::Anchor);
386 void arcTo(
float radius, point2 position)
noexcept
390 hilet r = std::abs(radius);
393 hilet Pm = midpoint(P1, P2);
401 hilet C = Pm + normal(Vm2) *
std::cos(alpha) * radius;
407 hilet q1 = squared_hypot(VC1);
408 hilet q2 = q1 + dot(VC1, VC2);
409 hilet k2 = (4.0f / 3.0f) * (
std::sqrt(2.0f * q1 * q2) - q2) / cross(VC1, VC2);
412 hilet C1 = point2{(C.x() + VC1.x()) - k2 * VC1.y(), (C.y() + VC1.y()) + k2 * VC1.x()};
413 hilet C2 = point2{(C.x() + VC2.x()) + k2 * VC2.y(), (C.y() + VC2.y()) - k2 * VC2.x()};
415 cubicCurveTo(C1, C2, P2);
427 hilet bl_radius = std::abs(corners.left_bottom());
428 hilet br_radius = std::abs(corners.right_bottom());
429 hilet tl_radius = std::abs(corners.left_top());
430 hilet tr_radius = std::abs(corners.right_top());
437 hilet blc1 = blc +
vector2{0.0f, bl_radius};
438 hilet blc2 = blc +
vector2{bl_radius, 0.0f};
439 hilet brc1 = brc + vector2{-br_radius, 0.0f};
440 hilet brc2 = brc + vector2{0.0f, br_radius};
441 hilet tlc1 = tlc + vector2{tl_radius, 0.0f};
442 hilet tlc2 = tlc + vector2{0.0f, -tl_radius};
443 hilet trc1 = trc + vector2{0.0f, -tr_radius};
444 hilet trc2 = trc + vector2{-tr_radius, 0.0f};
447 if (corners.left_bottom() > 0.0) {
448 arcTo(bl_radius, blc2);
449 }
else if (corners.left_bottom() < 0.0) {
454 if (corners.right_bottom() > 0.0) {
455 arcTo(br_radius, brc2);
456 }
else if (corners.right_bottom() < 0.0) {
461 if (corners.left_top() > 0.0) {
462 arcTo(tl_radius, tlc2);
463 }
else if (corners.left_top() < 0.0) {
468 if (corners.right_top() > 0.0) {
469 arcTo(tr_radius, trc2);
470 }
else if (corners.right_top() < 0.0) {
485 moveTo(point2{position.x(), position.y() - radius});
486 arcTo(radius, point2{position.x() + radius, position.y()});
487 arcTo(radius, point2{position.x(), position.y() + radius});
488 arcTo(radius, point2{position.x() - radius, position.y()});
489 arcTo(radius, point2{position.x(), position.y() - radius});
500 for (hilet& curve : contour) {
502 switch (curve.type) {
503 case bezier_curve::Type::Linear:
504 points.emplace_back(curve.P2, bezier_point::Type::Anchor);
506 case bezier_curve::Type::Quadratic:
507 points.emplace_back(curve.C1, bezier_point::Type::QuadraticControl);
508 points.emplace_back(curve.P2, bezier_point::Type::Anchor);
510 case bezier_curve::Type::Cubic:
511 points.emplace_back(curve.C1, bezier_point::Type::CubicControl1);
512 points.emplace_back(curve.C2, bezier_point::Type::CubicControl2);
513 points.emplace_back(curve.P2, bezier_point::Type::Anchor);
527 std::vector<bezier_point>::const_iterator
const&
begin,
528 std::vector<bezier_point>::const_iterator
const&
end)
noexcept
558 float tolerance = 0.05f) noexcept
576 float strokeWidth = 1.0f,
578 float tolerance = 0.05f) const noexcept
585 float starboardOffset = strokeWidth / 2;
586 float portOffset = -starboardOffset;
589 hilet baseContour = getBeziersOfContour(i);
592 r.addContour(starboardContour);
595 r.addContour(portContour);
609 if (bbox.width() <= 0.0 || bbox.height() <= 0.0) {
613 hilet scale =
std::min(max_size.width() / bbox.width(), max_size.height() / bbox.height());
614 bbox =
scale2(scale) * bbox;
616 hilet offset = (point2{} - get<0>(bbox)) + (extent - bbox.size()) * 0.5;
624 hi_assert(!rhs.isContourOpen());
629 hilet pointOffset = ssize(
points);
633 for (hilet & [ x, fill_color ] : rhs.layerEndContours) {
638 for (hilet x : rhs.contourEndPoints) {
642 points.insert(
points.end(), rhs.points.begin(), rhs.points.end());
646 [[nodiscard]]
friend graphic_path operator+(graphic_path lhs, graphic_path
const& rhs)
noexcept
651 friend graphic_path operator*(transformer2
auto const& lhs, graphic_path
const& rhs)
noexcept
654 for (
auto& point : rhs_.points) {
669 hi_assert(not mask.hasLayers());
670 hi_assert(not mask.isContourOpen());
675 hilet curves = mask.getBeziers();
676 fill(mask_image, curves);
688 hi_assert(mask.hasLayers() and not mask.isLayerOpen());
690 for (
int layerNr = 0; layerNr < mask.numberOfLayers(); layerNr++) {
691 hilet[layer, fill_color] = mask.getLayer(layerNr);
703 fill(dst, path.getBeziers());
@ end
Start from the end of the file.
Definition seek_whence.hpp:17
@ begin
Start from the beginning of the file.
Definition seek_whence.hpp:15
line_join_style
The way two lines should be joined.
Definition line_join_style.hpp:19
@ miter
The outer edge of both lines are extended until they meet to form a sharp corner.
Definition line_join_style.hpp:30
geometry/margins.hpp
Definition lookahead_iterator.hpp:5
The HikoGUI API version 1.
Definition lookahead_iterator.hpp:6
hi_export void composit(pixmap_span< sfloat_rgba16 > dst, hi::color color, graphic_path const &mask) noexcept
Composit color onto the destination image where the mask is solid.
Definition graphic_path.hpp:667
std::ptrdiff_t ssize_t
Signed size/index into an array.
Definition misc.hpp:33
constexpr void fill(pixmap_span< uint8_t > image, std::vector< bezier_curve > const &curves) noexcept
Fill a linear gray scale image by filling a curve with anti-aliasing.
Definition bezier_curve.hpp:667
constexpr std::vector< bezier_curve > makeContourFromPoints(std::vector< bezier_point >::const_iterator begin, std::vector< bezier_point >::const_iterator end) noexcept
Make a contour of Bezier curves from a list of points.
Definition bezier_curve.hpp:523
unit< si_length_tag, double, std::ratio< 254, 720 '000 >::type > points
Points: 1/72 inch.
Definition units.hpp:180
constexpr std::vector< bezier_curve > makeInverseContour(std::vector< bezier_curve > const &contour) noexcept
Inverse a contour.
Definition bezier_curve.hpp:587
constexpr std::vector< bezier_curve > makeParallelContour(std::vector< bezier_curve > const &contour, float offset, hi::line_join_style line_join_style, float tolerance) noexcept
Definition bezier_curve.hpp:609
This is a RGBA floating point color.
Definition color.hpp:45
Class which represents an axis-aligned rectangle.
Definition aarectangle.hpp:29
The 4 radii of the corners of a quad or rectangle.
Definition corner_radii.hpp:19
A high-level geometric extent.
Definition extent2.hpp:29
constexpr float & width() noexcept
Access the x-as-width element from the extent.
Definition extent2.hpp:104
constexpr float & height() noexcept
Access the y-as-height element from the extent.
Definition extent2.hpp:115
A rectangle / parallelogram in 3D space.
Definition rectangle.hpp:21
Definition translate2.hpp:14
A high-level geometric vector Part of the high-level vector, point, mat and color types.
Definition vector2.hpp:19
A path is a vector graphics object.
Definition graphic_path.hpp:26
void addContour(std::vector< bezier_point >::const_iterator const &begin, std::vector< bezier_point >::const_iterator const &end) noexcept
Curve with the given bezier curve.
Definition graphic_path.hpp:526
void addRectangle(aarectangle rectangle, corner_radii corners=corner_radii{0.0f, 0.0f, 0.0f, 0.0f}) noexcept
Draw a rectangle.
Definition graphic_path.hpp:423
void clear() noexcept
Clear the path.
Definition graphic_path.hpp:41
void addStroke(graphic_path const &path, color strokeColor, float strokeWidth, hi::line_join_style line_join_style=line_join_style::miter, float tolerance=0.05f) noexcept
Stroke a path and close layer.
Definition graphic_path.hpp:553
std::vector< bezier_point > points
A set of all bezier points describing all bezier curves, contours and layers.
Definition graphic_path.hpp:29
void optimizeLayers() noexcept
Optimize layers.
Definition graphic_path.hpp:260
void closeLayer(color fill_color) noexcept
Close current contour.
Definition graphic_path.hpp:249
std::vector< bezier_point >::const_iterator beginContour(ssize_t contourNr) const noexcept
Return an iterator to the start point of a contour.
Definition graphic_path.hpp:116
void addContour(std::vector< bezier_curve > const &contour) noexcept
Contour with the given bezier curves.
Definition graphic_path.hpp:496
void addContour(std::vector< bezier_point > const &contour) noexcept
Curve with the given bezier curve.
Definition graphic_path.hpp:538
aarectangle boundingBox() const noexcept
Calculate bounding box.
Definition graphic_path.hpp:82
graphic_path toStroke(float strokeWidth=1.0f, line_join_style line_join_style=line_join_style::miter, float tolerance=0.05f) const noexcept
Convert path to stroke-path.
Definition graphic_path.hpp:575
bool allLayersHaveSameColor() const noexcept
Check if all layers have the same color.
Definition graphic_path.hpp:64
ssize_t numberOfLayers() const noexcept
Return the number of closed layers.
Definition graphic_path.hpp:57
void cubicCurveRelativeTo(vector2 controlDirection1, vector2 controlDirection2, vector2 direction) noexcept
Draw curve from the current position to the new direction.
Definition graphic_path.hpp:365
ssize_t numberOfContours() const noexcept
Return the number of closed contours.
Definition graphic_path.hpp:50
std::vector< std::pair< ssize_t, color > > layerEndContours
An color and index into.
Definition graphic_path.hpp:37
void arcTo(float radius, point2 position) noexcept
Draw an circular arc.
Definition graphic_path.hpp:386
void closeContour() noexcept
Close current contour.
Definition graphic_path.hpp:217
void addPath(graphic_path const &path, color fill_color) noexcept
Add path and close layer.
Definition graphic_path.hpp:545
void addCircle(point2 position, float radius) noexcept
Draw a circle.
Definition graphic_path.hpp:481
void moveTo(point2 position) noexcept
Start a new contour at position.
Definition graphic_path.hpp:298
point2 currentPosition() const noexcept
Get the currentPosition of the open contour.
Definition graphic_path.hpp:286
bool hasLayers() const noexcept
This path has layers.
Definition graphic_path.hpp:226
std::vector< ssize_t > contourEndPoints
An index into.
Definition graphic_path.hpp:33
bool isContourOpen() const noexcept
Return true if there is an open contour.
Definition graphic_path.hpp:203
void quadraticCurveRelativeTo(vector2 controlDirection, vector2 direction) noexcept
Draw curve from the current position to the new direction.
Definition graphic_path.hpp:342
bool isLayerOpen() const noexcept
Return true if there is an open layer.
Definition graphic_path.hpp:233
void moveRelativeTo(vector2 direction) noexcept
Start a new contour relative to current position.
Definition graphic_path.hpp:307
graphic_path centerScale(extent2 extent, float padding=0.0) const noexcept
Center and scale a path inside the extent with padding.
Definition graphic_path.hpp:603
void tryRemoveLayers() noexcept
Try to move the layers in a path.
Definition graphic_path.hpp:101
A non-owning 2D pixel-based image.
Definition pixmap_span.hpp:34
A 2D pixel-based image.
Definition pixmap.hpp:38