Commit graph

72 commits

Author SHA1 Message Date
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
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
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
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
MacDue
63b11030f0 Everywhere: Use ReadonlySpan<T> instead of Span<T const> 2023-02-08 19:15:45 +00:00
MacDue
285bd7a37a LibGfx: Stop passing color stop spans by const reference
No idea why I did this, possibly because these were once vectors?
Anyway, the const reference is pointless here.
2023-01-29 13:49:35 +00:00
Aliaksandr Kalenik
ee4ba7617c LibWeb: Fix clip of hidden overflow when translated boxes are involved
There is a problem with current approach where overflow clip rectange is
calculated by aggregating intersection of absolute padding boxes of
boxes in containing block chain that resulting rectangle doesn't
respect transform properties.

To solve this problem `PaintableBox` is changed to store clip rectangle
saved from painter because it does respect transform properties of all
previously applied clip rectangles.
2023-01-25 10:44:58 +01:00
MacDue
f3c0987afe LibGfx: Add Painter::fill_rect(rect, paint_style)
The usual fill_rect()... but with style :^)
2023-01-22 18:15:52 +01:00
MacDue
223cedc896 LibGfx: Update fill_path() to support taking a PaintStyle
This means fill_path() now paints the scanlines its self rather than
calling draw_line() which easily allows each pixel along the scanline
to have a different color.
2023-01-22 18:15:52 +01:00
MacDue
c8c065b6b0 LibWeb+LibGfx: Migrate (most of) the CSS gradient painting to LibGfx
This moves the CSS gradient painting to the painter creating:

 - Painter::fill_rect_with_linear_gradient()
 - Painter::fill_rect_with_conic_gradient()
 - Painter::fill_rect_with_radial_gradient()

This has a few benefits:
 - The gradients can now easily respect the painter scale
 - The Painter::fill_pixels() escape hatch can be removed
 - We can remove the old fixed color stop gradient code
    - The old functions are  now just a shim
 - Anywhere can now easily use this gradient painting code!

This only leaves the color stop resolution in LibWeb (which is fine).
Just means in LibGfx you have to actually specify color stop positions.

(Also while here add a small optimization to avoid generating
excessively long gradient lines)
2023-01-10 10:25:58 +01:00
MacDue
a1726b1ba5 LibGfx: Avoid rounding/truncating glyph positions till blitting
This keeps some overloads that accept ints to avoid adding calls to
.to_type<float>() all over the place.
2023-01-05 12:09:35 +01:00
MacDue
ca01017f32 LibGfx: Add Painter::fill_pixels()
This function fills a region of pixels with the result of a callback
function. This is an alternative to a for loop that repeatedly calls
Painter::set_pixel(), which can get very expensive due to the clipping
checks set_pixel() does each call.
2022-12-25 15:35:31 +01:00
FrHun
df30440117 LibGfx: Add NearestFractional scaling type to painter
This is useful for cases where you want to avoid scaling artifacts.
2022-12-23 12:16:46 +00:00
Sam Atkins
83f31cb4a7 LibGfx: Add int overloads for (AntiAliasing)Painter float methods
Without this change, the upcoming LibWeb pixel types will require a
silly doubled conversion in some places.

eg: `some_rect.to_type<int>().to_type<float>()`

With these overloads, we can get away with `some_rect.to_type<int>()`.
2022-12-08 12:46:03 +00:00
MacDue
27fae78335 Meta+Userland: Pass Gfx::IntSize by value
Just two ints like Gfx::IntPoint.
2022-12-07 11:48:27 +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
MacDue
7be0b27dd3 Meta+Userland: Pass Gfx::IntPoint by value
This is just two ints or 8 bytes or the size of the reference on
x86_64 or AArch64.
2022-12-07 11:48:27 +01:00
MacDue
bbc149ebb9 Meta+Userland: Pass Gfx::Color by value
Gfx::Color is always 4 bytes (it's just a wrapper over u32) it's less
work just to pass the color directly.

This also updates IPCCompiler to prevent from generating
Gfx::Color const &, which makes replacement easier.
2022-12-07 11:48:27 +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
lanmonster
2b7aa4a971 LibGfx+LibGUI: Use constant for line spacing instead of magic number 2022-11-30 07:57:21 +01:00
jack gleeson
4bf587811f PixelPaint+LibGfx: Allow resizing images and layers
This PR adds resize ability to PixelPaint as per issue 11862.
The previous behaviour was to always rescale the canvas when
resizing an image. This adds a checkbox to toggle between
rescaling, and resizing which blits the existing canvas to
the top left of the new, resized canvas.

As part of this, a new ScalingMode is added to
LibGfx - None.
2022-11-02 10:59:18 +00:00
Andreas Kling
a494bd24f1 LibGfx: Add a way to get the Painter's current 2D translation 2022-10-02 21:14:02 +02:00
Andreas Kling
b52165c5d7 LibWeb+LibGfx: Move the blit image through 2D transfrom to Gfx::Painter
Even though this code is obnoxiously slow, it still belongs in LibGfx
and should not be hidden away in LibWeb's CanvasRenderingContext2D.
2022-09-24 13:00:53 +02:00
MacDue
60356c8dde LibGfx: Support getting a bitmap for a region of painter
This will be needed so we can apply filter effects to the backdrop
of an element in LibWeb.

This now also allows getting a crop of a bitmap in a different format
than the source bitmap. This is for if the painter's bitmap does not
have an alpha channel, but you want to ensure the cropped bitmap does.
2022-09-16 10:50:48 +01:00
FrHun
b3d1fa4c54 LibGUI: Add drawing triangle from coordinate list 2022-06-20 12:40:51 +01:00
Karol Kosek
3d7838c5fb LibGfx: Implement SmoothPixels scaling mode
If you wanted to upscale an image, you had two options:
- use Nearest Neighbor: it's probably a good choice. The image stays
  sharp.. unless you aren't using integer scales.
- use Bilinear blending, but this on the other hand, doesn't handle
  upscaling well. It just blurs everything.

But what if we could take the best of both of them and make the image
sharp on integers and just blur it a little when needed?

Well, there's Smooth Pixels!

This mode is similar to the Bilinear Blend, with the main difference
is that the blend ratio is multiplied by the current scale, so the blur
on corners can be only 1px wide.

From my testing this mode doesn't handles downscaling as good as the
Bilinear blending though.
2022-06-16 14:26:55 +01:00
MacDue
81a3ec0692 LibGfx: Add Painter::get_pixel()
This is required to do some painting tricks in LibWeb, this has to be
added to the painter so it can apply the paint translation first.
2022-06-16 10:28:07 +01:00
Simon Wanner
206d6ece55 LibGfx: Move other font-related files to LibGfx/Font/ 2022-04-09 23:48:18 +02:00
Andreas Kling
7850628ff1 LibGfx: Add Painter::draw_text_run(), a simplified text painting API
This API does:
    - Take a Utf8View
    - Take the starting point on the baseline as its input coordinate

This API does not:
    - Align the text
    - Wrap the text
    - Elide too-long text into "..."
2022-03-30 00:57:15 +02:00
MacDue
3c0e17f29f LibGfx: Support scaling in AntiAliasingPainter::draw_circle()
Previously the painter would crash if scaling was enabled.
2022-03-26 18:24:11 +00:00
MacDue
51e54ab1ba LibGfx: AntiAliasingPainter::draw_circle/fill_rect_with_rounded_corners
Follows the efficient algorithm from this paper:
https://cs.uwaterloo.ca/research/tr/1984/CS-84-38.pdf

Can be extended ellipses in future.
2022-03-18 11:31:33 +01:00
Lenny Maiorani
9c56a83b76 Libraries: Use default constructors/destructors in LibGfx
https://isocpp.github.io/CppCoreGuidelines/CppCoreGuidelines#cother-other-default-operation-rules

"The compiler is more likely to get the default semantics right and
you cannot implement these functions better than the compiler."
2022-03-17 17:23:49 +00:00
Linus Groh
cab032f1ee LibGfx+LibGUI: Support multi code point emojis in text painting :^)
This necessitates switching from passing a single code point to the
callback to passing a non-const Utf8CodePointIterator instead.

Note that the text selection mechanisms in LibGUI and LibWeb don't
handle this properly yet; they still assume that each code point
renders as one glyph. Similarly, width calculations for text widths
don't either, so a single such an emoji will require space for more
than one glyph.

It also doesn't work in LibVT's TerminalWidget, where each code point
is handled and rendered separately, so LibGfx never gets a chance to
check if subsequent code points could result in a combined emoji.
2022-02-23 21:53:30 +00:00
Tobias Christiansen
0277118cb4 LibGfx: Add Painter::draw_triangle_wave()
This patch adds support for drawing triangular waves.
For now those can only be horizontal, but as they are intended for
underlining text, it's an okay way to handle this.
2022-01-23 15:48:27 +03:30
Hendiadyoin1
9e7c16d0a4 LibGfx: Load default font lazily
This is required when trying to use a Painter from lagom, due to
/res/font not being present
2021-11-29 23:17:05 +03:30
Andreas Kling
8b1108e485 Everywhere: Pass AK::StringView by value 2021-11-11 01:27:46 +01:00
Sam Atkins
1c807410cd LibGfx: Add optional bilinear filtering to draw_scaled_bitmap()
The algorithm is quite simple: You grab a 2x2 area of pixels around the
point you want from the source bitmap, and then linearly interpolate
between them based on how far they are from that point.

This works well when scaling up images, and moderately well when scaling
down - small details may get skipped over. The way GPUs solve this is
with mipmaps, which is not something I want to get into right now. (And
increases the memory usage per bitmap by 50%.)

I have not focused on performance, but this does reuse much of the
existing fixed-point calculation, and uses constexpr so that the
performance for nearest-neighbor should be the same as it was
previously.
2021-09-20 22:18:20 +02: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
Ali Mohammad Pur
02d949cfb6 LibGfx: Switch Painter.{h,cpp} to use east-const 2021-09-18 02:12:38 +04:30
Andreas Kling
32b9d80ee5 LibGfx: Make Painter::fill_path() take Path by const reference
Taking a mutable reference here made the API look very strange.
2021-09-17 13:41:03 +02:00
Mustafa Quraish
9ed32582e2 LibGfx/Painter: Add draw_rect_with_thickness method
Previously there was no way to draw rectangles with any specific
thickness, like we can do with ellises, for instance. This method
is just a simple wrapper around `draw_line()` several times. At
least for now, we don't need to do anything sophisticated since
this will only be used by PixelPaint.`
2021-09-04 03:30:03 +02:00
Tobias Christiansen
61a1122c2d LibGfx: Add alternate_color to draw_line
This alternate_color can be used when drawing dashed lines to have two
alternating Colors.
2021-08-07 02:52:47 +04:30
sin-ack
4c9c85ac01 Userland: Make TextWrapping::Wrap opt-in
This was breaking many places which didn't expect text to wrap. Now,
the only place where text currently wraps is in GUI::Label.
2021-07-27 22:05:20 +02:00
sin-ack
e11940fd01 Userland: Move text wrapping/elision into the new TextLayout :^)
This class now contains all the fun bits about laying out text in a
rect. It will handle line wrapping at a certain width, cutting off lines
that don't fit the given rect, and handling text elision.
Painter::draw_text now internally uses this.

Future work here would be not laying out text twice (once actually
preparing the lines to be rendered and once to get the bounding box),
and possibly adding left elision if necessary.

Additionally, this commit makes the Utf32View versions of
Painter::draw_text convert to Utf8View internally. The intention is to
completely remove those versions, but they're kept at the moment to keep
the scope of this PR small.
2021-07-26 21:14:39 +04:30
Timothy Flynn
4903186cc5 LibGfx: Add helper for painting a rounded rect with equal corner radii 2021-06-04 19:11:45 +02:00
Tobias Christiansen
8b63c2a10e LibGfx: Add Painter::draw_circle_arc_intersecting()
This adds a function to draw a circle specified by a center point (
relative to the given Rect) and a radius. The circle arc is only drawn
inside the specified Rect as to allow for circle arc segments.
Technically this was already possible using draw_elliptical_arc(), but
the algorithm is quite involved and lead to wonky arcs when trying to
draw circle arc segments.
2021-05-20 22:08:02 +02:00
Tobias Christiansen
819e0e0440 LibGfx: Add Painter::fill_rect_with_rounded_corners()
This paints a rectangle with rounded corners each specified by a
radius.
2021-05-20 22:08:02 +02:00
Andreas Kling
381dcca2f6 Revert "LibGfx: Add directional floating-point scaling to Painter"
This reverts commit ff76a5b8d2.
2021-05-03 16:37:05 +02:00