Commit graph

213 commits

Author SHA1 Message Date
Joe Petrus
2632f6ae65 LibGfx: Abort draw_circle_arc_intersecting with 0 radius
In testing a particular website (https://www.icpms.com), WebContent
was crashing with infinite recursion in draw_circle_arc_intersecting.
Presumably, radius must be > 0 to paint something, so this trivial
patch simply returns if radius <= 0. The website in question no longer
crashes WebContent.
2022-03-11 10:54:06 +01:00
Vrins
3b22fd9a9f LibGfx: Add support for TextAlignment::TopCenter / BottomCenter
Now supports TextAlignment::TopCenter and TextAlignment::BottomCenter
for the Painter::draw_text.

Also patched this in Spreadsheet/CellTypeDialog.cpp
2022-03-08 22:09:52 +01:00
Andreas Kling
9fa78b1a05 LibGfx: Don't mix up red/blue channels when blitting RGBA8888 bitmap
This makes CanvasRenderingContext2D.putImageData() actually paint the
right colors into the canvas.
2022-03-06 00:15:12 +01:00
Andreas Kling
a6a8ba80fc LibGfx: Rename Color::from_rgba() => Color::from_argb()
This matches the rename of RGBA32 to ARGB32. It also makes more sense
when you see it used with 32-bit hexadecimal literals:

Before:
    Color::from_rgba(0xaarrggbb)

After:
    Color::from_argb(0xaarrggbb)
2022-03-04 23:40:21 +01:00
Andreas Kling
5ace66a903 LibGfx: Rename RGBA32 => ARGB32
The ARGB32 typedef is used for 32-bit #AARRGGBB quadruplets. As such,
the name RGBA32 was misleading, so let's call it ARGB32 instead.

Since endianness is a thing, let's not encode any assumptions about byte
order in the name of this type. ARGB32 is basically a "machine word"
of color.
2022-03-04 23:40:21 +01:00
Linus Groh
c5c026890e LibGfx: Add basic variation selector and regional indicator support :^)
I'm sure there's a spec for this somewhere, but this is a first working
approximation.

Closes #3315.
2022-02-23 21:53:30 +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
Steven Schmoll
d345a3689f LibGfx: Support color blending in Painter::draw_bitmap
This method is commonly used by bitmap text rendering. Adding support
for color blending enables support in the browser for text opacity using
their color property.
2022-02-14 12:49:19 +01: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
Maciej
8542d1da5a LibGfx: Always scale emojis to fit font height 2022-01-22 00:26:23 +00:00
Filiph Sandström
c4b78bee45 LibGfx: Remove VERIFY in draw_rect_with_thickness
draw_line with thickness already supports scaling so that verify isn't
needed anymore. This fixes a scaling chrash introduced in 8a1d77f.
2022-01-01 20:30:09 +00:00
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
Gal Horowitz
aa180c821d LibGFX: Draw the ends of lines with non-standard thickness
Lines are drawn using squares the size of the thickness, so if the
length of the line was not a multiple of the thickness, the end of the
line was not drawn correctly.
2021-10-02 20:54:47 +02: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
thankyouverycool
ae59d8a728 LibGfx: Paint replacement character, 0xFFFD, for unknown glyphs
Note: most systems now use a font's .notdef character for unknown
glyphs (commonly the tofu box) and reserve 0xFFFD for encoding
errors. Until Serenity supports tofu, 0xFFFD is a preferable, if
deprecated, alternative to '?' to reduce ambiguity.
2021-09-19 00:58:59 +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
Ali Mohammad Pur
e2cd558101 LibGfx: Start a very basic anti-aliased Painter implementation
This can currently draw AA lines (and by proxy, AA paths), and passes
all its output through a 2D affine transform to an underlying
Gfx::Painter.
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
Sam Atkins
6c992e5dce LibGfx: Don't try to paint 0px-wide lines
In some cases, we were infinite-looping when asked to paint something
with a thickness of '0', so now every Painter method that takes a
thickness, does a check for a thickness <= 0 and bails early. After all,
you can't draw something that's 0px wide. :^)
2021-09-16 22:30:33 +02:00
Mustafa Quraish
0f749681a9 Everywhere: Use my fancy new serenityos.org email :^) 2021-09-13 20:51:50 +00:00
David Isaksson
242acfcbae LibGfx: Apply translation and scale to Painter::draw_triangle() 2021-09-11 19:16:29 +02:00
Tobias Christiansen
de0791b0a1 LibGfx: Increase bit-width of variables used in do_draw_scaled_bitmap
To avoid expensive floating point operations the values are put in the
upper half of an integer which is then used for calculations.
When the src_rect is sufficiently large (when, say, PixelPaint is zoomed
in x100), the precision provided by this strategy with regular
32-bit-long ints  is no longer enough.
This patch changes the used types to i64, which are 64 bits wide and the
shifting is increased to 32 bits.
On the 32-bit-arch a i64 doesn't fit in a single register anymore but
it's probably okay to trust the compiler to do clever stuff around this
issue.
2021-09-11 00:09:33 +02:00
sin-ack
1999b66f38 LibGfx: Intersect the bounding box with the main rect in draw_text
Without this, the bounding rect for the text as generated by TextLayout
can go beyond the bounds of the user-supplied drawing rect and cause the
text to overlap because of the line_rect.intersect(rect) a few lines
below.
2021-09-04 16:48:27 +02:00
Idan Horowitz
1a19d2c2df LibGfx: Stop using a Utf8View that points to a temporary String 2021-09-04 16:13:30 +02:00
Idan Horowitz
72b21343ad LibGfx: Convert line text into a Utf8View before finding its direction
We were accidentally calling TextDirection::get_text_direction with a
String instead of a UtfView, which meant each byte was treated as a
codepoint, resulting in incorrect identification of text direction.
2021-09-04 16:13:30 +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
Andreas Kling
2432c5264b LibGfx: Remove ancient unused NO_FPU macros 2021-08-18 11:35:51 +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
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
Andreas Kling
9f601fcbcf LibTTF+LibGfx: Improve vertical alignment of glyphs
Before this patch, some glyphs had a weird off-by-1 vertical position
which looked really jarring at small font sizes.

This was caused by glyph bitmaps having different heights from each
other. (Each glyph bitmap was minimally sized to fit only the glyph
itself, and then vertically positioned during the paint phase.
Since this vertical positioning was integer based, subpixel precision
was lost and things ended up looking wonky.)

Fix this by making all glyph bitmaps be the same height so we can blit
them at the same integer y position. We use the typographic ascent from
the OS/2 table to transform the glyph coordinates.

The end result is a huge improvement visually. :^)
2021-07-20 02:48:29 +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
Tom
1021aba226 LibGUI: Dither pattern should be independent from clipping rectangle
The dither pattern needs to be determined relative to the bitmap
itself, not the clipping rectangle.

Fixes #8780
2021-07-15 19:46:42 +02:00
Karol Kosek
871c51dfd3 LibGfx: Don't underline escaped ampersand in menus
Double ampersands (&&) marking in menus is meant to provide a way
to show the ampersand, since using just one would turn it
into a modifier that sets the shortcut for the next character.

Unfortunately, while the first character had a special case to avoid
marking this set, the marking was still calculated
for the second character.

The fix is rather simple: just skip then the following character!

This issue applied only to the visual part of the Menu.
The WindowServer calculation for the shortcut character is working
properly, i.e. ignores escaped ampersands.
2021-07-14 18:25:36 +02:00
Andreas Kling
5439453139 LibGfx: Improve Painter::draw_line() alignment with (thickness > 1)
Thicker lines are drawn by filling rectangles along the path.
Previously these rectangles used the points as their top left corner.
This patch changes it to use the points as the center of the rectangles
which makes the PixelPaint line tool feel a lot more natural. :^)
2021-07-09 22:07:00 +02:00
Daniel Bertalan
f14a4994b0 Everywhere: Don't promote float to double where not needed
The `float => double => float` round trip seen in a couple of places
might pessimize the code. Even if it's truncated to an int in the end,
it's weird not to use the functions with the `f` suffixes when working
with single precision floats.
2021-07-08 10:11:00 +02:00
Andreas Kling
f33edd33cc LibGfx: Small improvements to fill_rect_with_checkerboard()
- Clamp the checkerboard scanline prologue length to the total width
  of the (clipped) rect we're filling.

- Use fast_u32_fill() for the prologue and epilogue as well.
2021-07-07 13:01:20 +02:00
Andreas Kling
e7b8f6fe48 LibGfx: Make Painter::fill_rect_with_checkerboard() faster
We now divide each scanline into prologue, aligned run, and epilogue.
Basically, we draw enough pixels one-by-one until we reach a grid
intersection. Then we draw full grid cell slices using fast memory
fills. Finally we go back to one-by-one for the epilogue.

This is roughly 2.5x faster in a microbenchmark and no longer dominates
the ImageViewer and PixelPaint resizing profiles.
2021-07-06 12:24:51 +02:00
Gunnar Beutner
40f7977508 LibGfx: Fix drawing rounded corners when using display scaling 2021-06-22 23:46:16 +02:00
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
bd2b17a70e LibGfx: Replace ellipse drawing algorithm
The new one is way more naive and not as fancy as the old one, but it
doesn't crash when trying to draw circles.
This algorithm just sweeps the angles required by the call, makes sure
each segment is at most 1 (pixel) long and just uses the standard
parameterization to find the coordinates of each point on the ellipse.
2021-05-23 18:28:27 +02:00
Tobias Christiansen
155d876c44 LibGfx: Support alpha in rendering methods for border-radius
The methods used in displaying border-radius were ignoring alpha.
2021-05-22 00:21:02 +02:00
Linus Groh
d60ebbbba6 Revert "Userland: static vs non-static constexpr variables"
This reverts commit 800ea8ea96.

Booting the system no longer worked after these changes.
2021-05-21 10:30:52 +01:00
Lenny Maiorani
800ea8ea96 Userland: static vs non-static constexpr variables
Problem:
- `static` variables consume memory and sometimes are less
  optimizable.
- `static const` variables can be `constexpr`, usually.
- `static` function-local variables require an initialization check
  every time the function is run.

Solution:
- If a global `static` variable is only used in a single function then
  move it into the function and make it non-`static` and `constexpr`.
- Make all global `static` variables `constexpr` instead of `const`.
- Change function-local `static const[expr]` variables to be just
  `constexpr`.
2021-05-21 10:07:06 +01:00
Linus Groh
9dd3203cc6 LibGfx: Add missing TextAlignment::BottomLeft 2021-05-21 08:04:31 +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
07850ccf51 LibGfx: Fix incorrect origin for checkerboard pattern fills
The checkerboard pattern used in transparency backgrounds was sometimes
misaligned with the grid. This happened because it was incorrectly
anchoring the pattern to the clipped rect instead of the global
grid of the underlying paint target.
2021-05-15 11:21:55 +02:00
Egor Ananyin
782dc348fd LibGfx: Fix clipping in fill_ellipse
fill_ellipse used to clip the bounding box, so instead of drawing a
part of an ellipse it drew a smaller ellipse. This commit fixes this
behaviour.
2021-05-09 16:14:01 +01:00