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. :^)
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.
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.
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)
This is achieved by simplifying the logic in TextLayout. We get rid
of all the various ways that the layout bounding rect can get cropped.
Then we make sure to use the right pixel metrics.
Finally we use the font's own line gap metrics instead of hard-coding 4.
The end result is that text painted with vector fonts now gets pretty
reasonable vertical alignment in most cases.
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.
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>()`.
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.
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.
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 :^)
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.
Doesn't use them in libc headers so that those don't have to pull in
AK/Platform.h.
AK_COMPILER_GCC is set _only_ for gcc, not for clang too. (__GNUC__ is
defined in clang builds as well.) Using AK_COMPILER_GCC simplifies
things some.
AK_COMPILER_CLANG isn't as much of a win, other than that it's
consistent with AK_COMPILER_GCC.
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.
In some artificial full screen blitting profiling, I've seen `memcpy`
take up about 4% fewer samples each time I measure. It seems like
`fast_u32_copy` is not as fast as it'd like to believe.
Our bilinear scaling logic worked well for upscaling, but during
downscaling the bitmap was often shifted one pixel to the bottom right.
This is a common problem, described here in more detail:
https://bartwronski.com/2021/02/15/bilinear-down-upsampling-pixel-grids-and-that-half-pixel-offset/
Fix it by calculating coordinate shift values that align the pixel's
boundaries between the source and target pixels before selecting the
source pixels to interpolate.
This is a reimplementation of draw_triangle that manages without
floating point arithmetic.
It's most important property, compared to the previous implementation is
that rotating the same triangle 90 degrees won't drastically change the
appearance of that triangle. (it did before)
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.
The added precision of doubles is most likely not needed here and floats
are usually cheaper than doubles, so lets always stick to them.
This also simplifies some calls to sin+cos to AK:sincos and a call to
atan(1/x) to atan2(1,x) to avoid a division.