1
Fork 0
mirror of https://github.com/RGBCube/serenity synced 2025-05-16 19:35:08 +00:00
Commit graph

228 commits

Author SHA1 Message Date
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
Andreas Kling
a396bb0c0b LibGfx: Remove indexed palette formats from Bitmap and Painter
Nobody was actually using these formats anymore, and this simplifies
and shrinks the code. :^)
2023-10-12 07:39:05 +02:00
MacDue
3e6ca1085c LibGfx: Add apply_alpha option to Painter::blit_filtered() 2023-07-30 09:31:43 +02:00
MacDue
0ef0ad04e1 LibGfx: Take filter by reference in Painter::blit_filtered()
This allows reusing the filter rather than moving it into blit_filtered.
2023-07-30 09:31:43 +02:00
MacDue
dcb7c299bf LibGfx: Use stroke_to_fill() for Painter::stroke_path() 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
Timothy Flynn
c911781c21 Everywhere: Remove needless trailing semi-colons after functions
This is a new option in clang-format-16.
2023-07-08 10:32:56 +01:00
Andreas Kling
57404bae1f LibGfx: Return early from Painter::draw_line() if clip rect is empty 2023-06-26 20:28:42 +02:00
MacDue
0bb0f2e4fb LibGfx: Apply opacity in Painter::draw_scaled_bitmap_with_transform() 2023-06-18 20:31:11 +02:00
Jelle Raaijmakers
5d0da8c096 LibGfx: Optimize Painter::blit_filtered()
For some reason, we were decoding the source color twice for every pixel
in the inner-most loop of `blit_filtered`. This makes sure we only
decode the source color once, and rearranges the code to improve
readability.

For my synthetic font rendering benchmark, this improves glyph rendering
performance by ~9%.
2023-06-01 12:23:24 +02:00
Andi Gallo
62c7fcd836 LibGfx: Multiply alpha channels for vector fonts, when necessary
When the background color has an alpha < 255, we can't copy over the
pixel alpha.
2023-06-01 09:22:41 +02:00
MacDue
6685656d2d LibGfx: Fix winding order of segments on elliptical arcs
for_each_line_segment_on_elliptical_arc() flips the start/end points
for negative theta deltas. When doing this we have to make sure the
line segments emitted swap the start/end points back, so that the
(correct) winding order can be calculated from them.

This makes nonzero fills not totally broken for a lot of SVGs.
2023-06-01 06:25:00 +02:00
Jelle Raaijmakers
5339b54b5d LibGfx: Improve glyph rendering speed for vector fonts
The glyph bitmap is a grayscale image that is multiplied with the
requested color provided to `Gfx::Painter::draw_glyph()` to get the
final glyph bitmap that can be blitted.

Using `Gfx::Color::multiply()` is unnecessary however: by simply taking
the destination color and copying over the glyph bitmap's alpha value,
we can prevent four multiplications and divisions per pixel.

In an artifical benchmark I wrote, this improved glyph rendering
performance by ~9%.
2023-06-01 06:18:57 +02:00
Jelle Raaijmakers
a02b28e6c8 LibGfx: Get rid of Gfx::Rect<float> area workaround in Painter
We can now trust `Gfx::Rect<T>` to correctly calculate rectangle
intersections when `T = float`.
2023-05-23 12:35:42 +02:00
Jelle Raaijmakers
f391ccfe53 LibGfx+Everywhere: Change Gfx::Rect to be endpoint exclusive
Previously, calling `.right()` on a `Gfx::Rect` would return the last
column's coordinate still inside the rectangle, or `left + width - 1`.
This is called 'endpoint inclusive' and does not make a lot of sense for
`Gfx::Rect<float>` where a rectangle of width 5 at position (0, 0) would
return 4 as its right side. This same problem exists for `.bottom()`.

This changes `Gfx::Rect` to be endpoint exclusive, which gives us the
nice property that `width = right - left` and `height = bottom - top`.
It enables us to treat `Gfx::Rect<int>` and `Gfx::Rect<float>` exactly
the same.

All users of `Gfx::Rect` have been updated accordingly.
2023-05-23 12:35:42 +02:00
Sam Atkins
ff70418ffc Revert "LibGfx: Add NearestFractional scaling type to painter"
This reverts commit df30440117.

This scaling type is now unused, and has issues with painting outside of
the Painter's clip-rect.
2023-05-22 01:38:41 +02:00
Jelle Raaijmakers
5031603cdc LibGfx: Remove clip check in Painter::do_draw_scaled_bitmap
We were performing a check whether source pixels would fall into a
clipped rect too early. Since we already clamp the resulting source
coordinates to the clipped rect, we can just remove this code.
2023-05-19 18:36:36 +02:00
Jelle Raaijmakers
6242d8e023 LibGfx: Implement box sampling image scaling
Box sampling is a scaling algorithm that averages all the pixels that
form the source for the target pixel. For example, if you would resize a
9x9 image to 3x3, each target pixel would encompass a 3x3 pixel area in
the source image.

Box sampling is a near perfect scaling algorithm for downscaling. When
upscaling with this algorithm, the result is similar to nearest neighbor
or smooth pixels.
2023-05-19 18:36:36 +02:00
Jelle Raaijmakers
31fa449538 LibGfx: Cleanup of Painter::do_draw_scaled_bitmap()
No functional changes.
2023-05-19 18:36:36 +02:00
Andreas Kling
3a670389d6 Revert "LibGfx: Cleanup of Painter::do_draw_scaled_bitmap()"
This reverts commit 4944b16bd5.
2023-05-19 13:33:54 +02:00
Andreas Kling
2d3b7eff15 Revert "LibGfx: Implement box sampling image scaling"
This reverts commit eb418bec32.
2023-05-19 13:33:54 +02:00
Andreas Kling
fb1a151fe3 Revert "LibGfx: Remove clip check in Painter::do_draw_scaled_bitmap"
This reverts commit 2959c2f2eb.
2023-05-19 13:33:50 +02:00
Jelle Raaijmakers
2959c2f2eb LibGfx: Remove clip check in Painter::do_draw_scaled_bitmap
We were performing a check whether source pixels would fall into a
clipped rect too early. Since we already clamp the resulting source
coordinates to the clipped rect, we can just remove this code.
2023-05-19 06:16:14 +02:00
Jelle Raaijmakers
eb418bec32 LibGfx: Implement box sampling image scaling
Box sampling is a scaling algorithm that averages all the pixels that
form the source for the target pixel. For example, if you would resize a
9x9 image to 3x3, each target pixel would encompass a 3x3 pixel area in
the source image.

Box sampling is a near perfect scaling algorithm for downscaling. When
upscaling with this algorithm, the result is similar to nearest neighbor
or smooth pixels.
2023-05-19 06:16:14 +02:00
Jelle Raaijmakers
4944b16bd5 LibGfx: Cleanup of Painter::do_draw_scaled_bitmap()
No functional changes.
2023-05-19 06:16:14 +02:00
MacDue
631fe129e9 LibGfx: Stop assuming the target format is always BGRA8888
...and instead assume it's BGRx8888 or BGRA8888, for now. Always
treating the target as BGRA8888 leads to the alpha channel being
interpreted incorrectly sometimes (as can be seen with WindowServer
overlays).

Fixes #18749
2023-05-15 06:38:22 +02:00
MacDue
9070aaebee LibGfx: VERIFY() error is finite when splitting bezier curves
If this value somehow becomes nan/inf the painter will keep splitting
the path till the process OOMs, a simple crash would be preferable.
2023-05-12 05:37:44 +02:00
Jelle Raaijmakers
8f736be711 LibGfx: Increase tolerance for bezier curves
An oval approximated by quadratic bezier curves ended up with 2048 line
segments when rasterized to a bitmap of around 35 by 35 pixels, which
seems a bit much. :^)

By increasing the tolerance by an order of magnitude, that same oval is
now split up into 512 line segments, which is still more than enough for
a high quality render.
2023-04-19 06:05:10 +02:00
thankyouverycool
55423b4ed0 LibGfx+Userland: Add width_rounded_up() helper 2023-04-15 15:24:50 +02:00
MacDue
790daa4754 LibGfx: Optimize Painter::draw_scaled_bitmap_with_transform()
This now applies clipping to the destination bounding box before
painting, which cuts out a load of clipped computation and allows
using the faster set_physical_pixel() method.

Alongside this it also combines the source_transform and
inverse_transform outside the hot loop (which might cut things down
a little).

The `destination_quad.contains()` check is also removed in favour
of just checking if the mapped point is inside the source rect,
which takes less work to compute than checking the bounding box.

This takes this method down from 98% of the time to 10% of the
time when painting Google Street View (with no obvious issues).
2023-04-12 07:40:22 +02:00
MacDue
98040c508f LibGfx: Handle signed distance field edges better
Small change to treat pixels outside the signed distance field bitmap
as outside the shape.
2023-03-24 09:57:48 +00:00
MacDue
77456d1d0b LibGfx: Implement simple signed distance field rendering
This is mostly a simple grayscale bilinear scale, with an extra step
of computing the distance and alpha with a little smoothing. This
can be used to paint more scalable UI elements/icons from rather
small distance fields. A tiny 16x16 SDF seems to do a decent job
for simple icons.
2023-03-23 08:27:51 +00:00
Tim Ledbetter
5a6b995444 LibGfx: Use premultiplied alpha when scaling images
This commit replaces usages of `Color::interpolate()` with
`Color::mixed_with()` in image scaling functions. The latter
uses premultiplied alpha, which results in more visually
pleasing edges when images are scaled against a transparent
background.

These changes affect the SmoothPixels and BilinearBlend scaling modes
of `Painter::draw_scaled_bitmap()` as well as the `Bitmap::scaled()`
function.

Fixes #17153.
2023-03-21 00:29:33 +01:00
MacDue
a425b6f772 LibGfx: Make all fill_path() code member functions and move into .cpp
This makes all the code for fill_path() member functions of the painter,
and moves them into a new FillPathImplementation.cpp. This allows us
to avoid polluting Painter.h with implementation details, and makes
the edit, compile, retry loop much shorter.
2023-03-11 18:34:26 +00:00
MacDue
b1a72d66f6 LibGfx: Speed up fill_path() with per scanline clipping & fast fills
This improves fill_path() performance by adding an API to the painter
that allows painting an entire scanline rather than just a pixel.
With this paths can be clipped a scanline at a time rather than each
pixel, removing a fair amount of checks.

Along with optimized clipping, this can now use a fast_u32_fill() to
paint all but the subpixels of a scanline if a solid color with no
alpha channel is used (which is quite common in SVGs).

This reduces scrolling around on svg.html from 21% in set_pixel() and
19% in fill_path() to just 7.8% in fill_path (with set_pixel()
eliminated). Now fill_path() is far from the slowest code when
scrolling the page.
2023-03-11 18:34:26 +00: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
Andreas Kling
552895da60 LibGfx: Skip old-style emoji lookup for fonts that have color bitmaps
Ultimately, we should find a way to route all emoji access through
the font code, but for now, this patch adds a special case for fonts
that are known to have embedded color bitmaps so we can test them.
2023-03-06 10:52:55 +01:00
Andreas Kling
e8cc1a4373 LibGfx: Prepare the paint code for fonts whose glyphs are color bitmaps
This patch does three things:
- Font::has_color_bitmaps() (true if CBLC and CBDT are present)
- Glyph now knows when its bitmap comes from a color bitmap font
- Painter draws color bitmap glyphs with the appropriate scaling etc
2023-03-06 10:52:55 +01:00
Andreas Kling
508fb7e1e9 Userland: Use Font::pixel_size_rounded_up() in more places 2023-03-04 00:29:38 +01:00
Timothy Flynn
62f2f0a081 LibGfx: Handle multi-code point emoji widths when drawing text runs
This API is used by LibWeb's text painter. Bring it up to date with the
glyph width computations performed in draw_text_line() used by other GUI
applications.
2023-03-02 18:33:44 +01:00
Timothy Flynn
e231f72f61 LibGfx: Render text presentation emoji as text if we have its glyph 2023-02-28 13:22:58 +00:00
Aliaksandr Kalenik
87fa1c5e66 Revert "LibWeb: Fix clip of hidden overflow..."
This reverts commit eb1ef59603c13c43b87c099c43c4d118dc8441f6.

The idea of saving clip box to apply it to handle `overflow: hidden`
turned out to break painting if box is painted before it's containing
block (it is possible if box has negative z-index).
2023-02-24 20:55:40 +01:00
Timothy Flynn
36a495e87e LibGfx: Use non-emoji glyph width API to compute the width of a space 2023-02-24 20:28:23 +01:00
Timothy Flynn
8be43cd3bf LibGfx: Use LibUnicode to filter code points that cannot start an emoji 2023-02-24 19:48:47 +01:00
Timothy Flynn
2bc7c11e8d LibGfx: Consult Unicode data to decode emoji sequences
For example, consider the Pirate Flag emoji, which is the code point
sequence U+1F3F4 U+200D U+2620 U+FE0F. Our current emoji resolution does
not consider U+200D (Zero Width Joiner) as part of an emoji sequence.
Therefore fonts like Katica, which have a glyph for U+1F3F4, will draw
that glyph without checking if we have an emoji bitmap.

This removes some hard-coded code points and consults the UCD's code
point properties for emoji sequence components and variation selectors.
This recognizes the ZWJ code point as part of an emoji sequence.
2023-02-22 10:14:36 +01:00
Timothy Flynn
b823f3d29f LibGfx: Consider multi-code point glyphs when computing text width
Currently, we compute the width of text one code point at a time. This
ignores grapheme clusters (emoji in particular). One effect of this is
when highlighting a multi-code point emoji. We will errantly increase
the highlight rect to the sum of all code point widths, rather than
just the width of the resolved emoji bitmap.
2023-02-22 10:14:36 +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
Andreas Kling
e9078e216d LibGfx: Make sure the Painter clip rect is never larger than the target
The new Painter::set_clip_rect(IntRect) API was able to make the clip
rect larger than the underlying target bitmap. This was not good, as it
could make it possible to draw outside the bitmap memory.

Fixes a crash when viewing https://twinings.co.uk/ in the browser. :^)
2023-02-10 23:33:16 +01:00
Tim Ledbetter
392dac0818 LibGfx: Make checkerboard patterns static when panning
Previously checkerboard patterns were anchored to the top left of the
bitmap they were being drawn into.

This makes the transparency grid in PixelPaint static relative to the
canvas when panning.
2023-02-08 21:53:34 +01:00