Commit Graph

46 Commits

Author SHA1 Message Date
MacDue
d7e2894e57 LibGfx: Output an SVG compatible string from Path::to_byte_string()
This is much more useful than the previous format, as you can now just
paste the path into a site like https://svg-path-visualizer.netlify.app/
to debug issues.
2024-03-19 09:55:55 -04:00
MacDue
8057542dea LibGfx: Simplify path storage and tidy up APIs
Rather than make path segments virtual and refcounted let's store
`Gfx::Path`s as a list of `FloatPoints` and a separate list of commands.

This reduces the size of paths, for example, a `MoveTo` goes from 24
bytes to 9 bytes (one point + a single byte command), and removes a
layer of indirection when accessing segments. A nice little bonus is
transforming a path can now be done by applying the transform to all
points in the path (without looking at the commands).

Alongside this there's been a few minor API changes:

- `path.segments()` has been removed
  * All current uses could be replaced by a new `path.is_empty()` API
  * There's also now an iterator for looping over `Gfx::Path` segments
- `path.add_path(other_path)` has been removed
  * This was a duplicate of `path.append_path(other_path)`
- `path.ensure_subpath(point)` has been removed
  * Had one use and is equivalent to an `is_empty()` check + `move_to()`
- `path.close()` and `path.close_all_subpaths()` assume an implicit
  `moveto 0,0` if there's no `moveto` at the start of a path (for
  consistency with `path.segmentize_path()`).

Only the last point could change behaviour (though in LibWeb/SVGs all
paths start with a `moveto` as per the spec, it's only possible to
construct a path without a starting `moveto` via LibGfx APIs).
2024-03-18 07:09:37 +01:00
MacDue
e9e1ee11d4 LibGfx: Decrease flatness a little in Path::stroke_to_fill()
Noticed larger stroke widths were looking a little 'low poly', this
looks a little nicer.

(Minor LibWeb test changes)
2024-01-21 19:23:31 +01:00
MacDue
13a4fb0325 LibGfx: Increase bezier splitting tolerance to 0.5
No noticeable difference a bit faster. This is still arbitrary and
should be somehow derived from the curve.
2024-01-08 09:26:43 +01:00
MacDue
d327104910 LibGfx: Add Path::place_text_along(text, font)
This method returns a new path with the input text placed along the edge
of the original path.
2023-12-19 21:29:03 +01:00
Ali Mohammad Pur
5e1499d104 Everywhere: Rename {Deprecated => Byte}String
This commit un-deprecates DeprecatedString, and repurposes it as a byte
string.
As the null state has already been removed, there are no other
particularly hairy blockers in repurposing this type as a byte string
(what it _really_ is).

This commit is auto-generated:
  $ xs=$(ack -l \bDeprecatedString\b\|deprecated_string AK Userland \
    Meta Ports Ladybird Tests Kernel)
  $ perl -pie 's/\bDeprecatedString\b/ByteString/g;
    s/deprecated_string/byte_string/g' $xs
  $ clang-format --style=file -i \
    $(git diff --name-only | grep \.cpp\|\.h)
  $ gn format $(git ls-files '*.gn' '*.gni')
2023-12-17 18:25:10 +03:30
Aliaksandr Kalenik
df57d7ca68 LibGfx+LibWeb: Update for_each_glyph_position to use font cascade list
This change updates function that builds list of glyphs to use font
cascade list to find font for each code point.
2023-12-10 17:32:04 +01:00
Nicolas Ramz
b3cbe0fdb9 LibGfx/Path: Round numerator in elliptical_arc_to
This avoids rounding problems which made Ladybird crash with some SVGs
on macOS/Clang.
2023-11-19 22:33:48 +01:00
MacDue
f3c8e88e5e LibGfx: Use BoundingBox helper in Gfx::Path 2023-11-14 10:13:10 +01:00
Aliaksandr Kalenik
efdbd8238e LibGfx: Decouple glyph positions calculation from draw_text_run()
This change separates a part of the `draw_text_run()` function, which
is responsible for calculating the positions for glyphs that need to be
painted, into a separate function called `get_glyph_run()`.

It is a part of the preparation for text run painting using OpenGL,
where we can't immediately blit glyph bitmaps but instead need to
prepare a sequence of quads for them in advance.
2023-11-06 09:53:11 +01:00
MacDue
50d33f79fa LibGfx: Allow extracting paths from fonts and add Gfx::Path::text()
This updates fonts so rather than rastering directly to a bitmap, you
can extract paths for glyphs. This is then used to implement a
Gfx::Path::text("some text", font) API, that if given a vector font
appends the path of the text to your Gfx::Path. This then allows
arbitrary manipulation of the text (rotation, skewing, etc), paving the
way for Word Art in Serenity.
2023-11-05 02:46:46 +01:00
Gabriel Nava
9a61041941 LibWeb: Add CanvasPath arcTo support
Adds initial CanvasPath arcTo support for 2D rendering contexts
https://html.spec.whatwg.org/multipage/canvas.html#dom-context-2d-arcto
2023-09-17 17:22:52 +02:00
MacDue
a9b4e876d0 LibGfx: Only attempt to paint strokes with a width > 0 2023-07-16 18:52:38 +02:00
MacDue
1bc7b0320e LibGfx: Approximate elliptical arcs with cubic beziers
Unlike all other primitives elliptical arcs are non-trivial to
manipulate, it's tricky to correctly apply a Gfx::AffineTransform to
them. Prior to this change, Path::copy_transformed() was still
incorrectly applying transforms such as flips and skews to arcs.

This patch very closely approximates arcs with cubic beziers (I can not
visually spot any differences), which can then be easily and correctly
transformed in all cases.

Most of the maths here was taken from:
https://mortoray.com/rendering-an-svg-elliptical-arc-as-bezier-curves/
(which came from https://www.joecridge.me/content/pdf/bezier-arcs.pdf,
now a dead link).
2023-07-16 06:22:55 +02:00
MacDue
2a1bf63f9e LibGfx: Use AK::sincos() and AK::Pi<double> in Path::elliptical_arc_to() 2023-07-16 06:22:55 +02:00
MacDue
8d4f90df4e LibGfx: Pass angles as floats to Path::elliptical_arc_to()
These are stored as floats internally and other parameters are
FloatPoints, so taking doubles is a little inconsistent. Doubles are
needed for the endpoint -> center parametrization conversion, but that
does not need exposing in the API.
2023-07-16 06:22:55 +02:00
MacDue
90e836deae LibGfx: Fix elliptical arcs after non orientation preserving transform
That is flipping/reflecting the arc.
2023-07-14 06:51:05 +02:00
MacDue
3d755a57b6 LibGfx: Ensure last subpath is closed by Path::close_all_subpaths() 2023-06-24 19:31:30 +02:00
MacDue
95a07bd4e5 LibGfx: Add Path::stroke_to_fill(thickness)
This function generates a new path, which can be filled to rasterize
a stroke of the original path (at whatever thickness you like). It
does this by convolving a circular pen with the path, so right now
only supports round line caps.

Since filled paths now have good antialiasing, doing this results in
good stroked paths for "free". It also (for free) fixes stroked lines
with an opacity < 1, nice line joins, and is possible to fill with a
paint style (e.g. a gradient or an image).

Algorithm from: https://keithp.com/~keithp/talks/cairo2003.pdf
2023-06-06 09:17:06 +02:00
MacDue
6abc51d9f8 LibGfx: Simplify segmentizing paths
Remove SplitLineSegment and replace it with a FloatLine, nobody was
interested in its extra fields anymore. Also, remove the sorting of
the split segments, this really should not have been done here
anyway, and is not required by the rasterizer anymore. Keeping the
segments in stroke order will also make it possible to generate
stroked path geometry (in future).
2023-06-04 05:40:39 +02:00
Andreas Kling
cc86c07f58 LibGfx: Transform the x axis rotation for elliptical arcs
Without this, copy_transformed() will create paths with bogus elliptical
arcs. This was very noticeable with transformed ellipses in SVG.
2023-04-27 07:24:53 +02:00
MacDue
26e56bdd08 LibGfx: Fix crash due to vector resize in close_all_subpaths()
Since close_all_subpaths() appends while iterating, the vector can
end up being resized and the iterator invalidated. Previously, this
led to a crash/UAF in some cases.
2023-04-09 18:42:45 +02:00
Andreas Kling
8a48246ed1 Everywhere: Stop using NonnullRefPtrVector
This class had slightly confusing semantics and the added weirdness
doesn't seem worth it just so we can say "." instead of "->" when
iterating over a vector of NNRPs.

This patch replaces NonnullRefPtrVector<T> with Vector<NNRP<T>>.
2023-03-06 23:46:35 +01:00
Luke Wilde
1f97adbee8 LibGfx: Add a function that adds two paths together
This will be used by Path2D#addPath in LibWeb.
2023-02-27 20:55:09 +01:00
Andreas Kling
ca44b26b2a LibGfx: Make Gfx::Path const-correct internally (segment list) 2023-02-21 00:54:04 +01:00
Andreas Kling
7c607462a4 LibGfx+LibWeb: Store radii as FloatSize rather than FloatPoint
Radii are sizes, not points. This becomes important when mapping them
through a 2D transform.
2023-02-10 23:33:16 +01:00
MacDue
e011eafd37 Meta+Userland: Pass Gfx::FloatPoint by value
Just a small 8-byte value like Gfx::IntPoint.
2022-12-07 11:48:27 +01:00
Linus Groh
57dc179b1f Everywhere: Rename to_{string => deprecated_string}() where applicable
This will make it easier to support both string types at the same time
while we convert code, and tracking down remaining uses.

One big exception is Value::to_string() in LibJS, where the name is
dictated by the ToString AO.
2022-12-06 08:54:33 +01:00
Linus Groh
6e19ab2bbc AK+Everywhere: Rename String to DeprecatedString
We have a new, improved string type coming up in AK (OOM aware, no null
state), and while it's going to use UTF-8, the name UTF8String is a
mouthful - so let's free up the String name by renaming the existing
class.
Making the old one have an annoying name will hopefully also help with
quick adoption :^)
2022-12-06 08:54:33 +01:00
Sam Atkins
389f1ee6f5 LibGfx: Add method for copying a Path with a transform applied
The Web's CanvasRenderingContext2D needs a way to draw a path with a
transform applied to it, without modifying the original path, so here
it is. :^)
2022-08-14 11:30:40 +02:00
sin-ack
c8585b77d2 Everywhere: Replace single-char StringView op. arguments with chars
This prevents us from needing a sv suffix, and potentially reduces the
need to run generic code for a single character (as contains,
starts_with, ends_with etc. for a char will be just a length and
equality check).

No functional changes.
2022-07-12 23:11:35 +02:00
sin-ack
3f3f45580a Everywhere: Add sv suffix to strings relying on StringView(char const*)
Each of these strings would previously rely on StringView's char const*
constructor overload, which would call __builtin_strlen on the string.
Since we now have operator ""sv, we can replace these with much simpler
versions. This opens the door to being able to remove
StringView(char const*).

No functional changes.
2022-07-12 23:11:35 +02:00
Idan Horowitz
086969277e Everywhere: Run clang-format 2022-04-01 21:24:45 +01:00
Simon Danner
f0a1ab6f84 LibWeb: Keep SVG elliptical arc shape when applying viewbox
When doing viewbox transforms, elliptical always had large arc and
sweep flag set to false. Preserve these flags so they can be set
correctly when applying viewbox transformations.
2022-03-12 15:38:55 +01:00
Ali Mohammad Pur
433725fef2 LibGfx: Implement cubic bezier curves by splitting them to subcurves
This makes them significantly more nicer-looking, and fixes a FIXME :^)
2021-09-18 02:12:38 +04:30
Andreas Kling
c8c3828b59 LibGfx: Avoid invalidation when Path::close() is a no-op
If the path is already closed, calling close() is a no-op, and we don't
need to invalidate the split lines cache.
2021-09-17 13:41:34 +02:00
Andreas Kling
09d13e437b LibGfx: Add Path::cubic_bezier_curve_to()
This is pretty unsophisticated as it will simply add a fixed number of
of line segments approximating the curve. Still better than nothing.
2021-09-15 20:57:43 +02:00
Hendiadyoin1
ed46d52252 Everywhere: Use AK/Math.h if applicable
AK's version should see better inlining behaviors, than the LibM one.
We avoid mixed usage for now though.

Also clean up some stale math includes and improper floatingpoint usage.
2021-07-19 16:34:21 +04:30
Andreas Kling
eb05931ab5 LibGfx: Convert StringBuilder::appendf() => AK::Format 2021-05-07 21:12:09 +02:00
Matthew Olsson
88cfaf7bf0 LibGfx: Unify Rect, Point, and Size
This commit unifies methods and method/param names between the above
classes, as well as adds [[nodiscard]] and ALWAYS_INLINE where
appropriate. It also renamed the various move_by methods to
translate_by, as that more closely matches the transformation
terminology.
2021-05-02 22:48:06 +02:00
Brian Gianforcaro
1682f0b760 Everything: Move to SPDX license identifiers in all files.
SPDX License Identifiers are a more compact / standardized
way of representing file license information.

See: https://spdx.dev/resources/use/#identifiers

This was done with the `ambr` search and replace tool.

 ambr --no-parent-ignore --key-from-file --rep-from-file key.txt rep.txt *
2021-04-22 11:22:27 +02:00
Nicholas-Baron
73dd293ec4 Everywhere: Add -Wdouble-promotion warning
This warning informs of float-to-double conversions. The best solution
seems to be to do math *either* in 32-bit *or* in 64-bit, and only to
cross over when absolutely necessary.
2021-04-16 19:01:54 +02:00
AnotherTest
801daf47f0 LibGfx+LibWeb: Wire up CanvasRenderingContext2D.ellipse()
Note that this is *extremely* naive, and not very good at being correct.
2021-04-15 17:50:16 +02:00
AnotherTest
1ea466661f LibGfx+LibWeb: Move out the EllipticArcTo() logic into Path
At its previous state, the interface allowed invalid "ellipses" to be
specified, instead of doing that, simply use the parameters that SVG
uses :^)
2021-04-15 17:50:16 +02:00
Andreas Kling
5d180d1f99 Everywhere: Rename ASSERT => VERIFY
(...and ASSERT_NOT_REACHED => VERIFY_NOT_REACHED)

Since all of these checks are done in release builds as well,
let's rename them to VERIFY to prevent confusion, as everyone is
used to assertions being compiled out in release.

We can introduce a new ASSERT macro that is specifically for debug
checks, but I'm doing this wholesale conversion first since we've
accumulated thousands of these already, and it's not immediately
obvious which ones are suitable for ASSERT.
2021-02-23 20:56:54 +01:00
Andreas Kling
13d7c09125 Libraries: Move to Userland/Libraries/ 2021-01-12 12:17:46 +01:00