Commit graph

199 commits

Author SHA1 Message Date
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
Andreas Kling
381dcca2f6 Revert "LibGfx: Add directional floating-point scaling to Painter"
This reverts commit ff76a5b8d2.
2021-05-03 16:37:05 +02:00
Andreas Kling
f43adb816e Revert "LibGfx: Re-add missing bounds-checks to Painter::draw_rect"
This reverts commit 4cf5514672.
2021-05-03 16:36:57 +02:00
Matthew Olsson
4cf5514672 LibGfx: Re-add missing bounds-checks to Painter::draw_rect
This commit adds a draw_physical_line method, which is the exact same
as draw_line, except it's parameters are already transformed and
scaled. This is used by both draw_line and draw_rect, as a slight
optimization to save some work. It also fixed draw_rect not checking
whether it should draw the lines before drawing them.
2021-05-03 08:19:39 +02:00
Matthew Olsson
ff76a5b8d2 LibGfx: Add directional floating-point scaling to Painter
This allows the painter to be scaled separately in both directions, and
not just in integer intervals. This is crucial for proper SVG viewBox
support.

Most bitmap-related things verify the scale to be one as of now.
2021-05-02 22:48:06 +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
Gunnar Beutner
6cf59b6ae9 Everywhere: Turn #if *_DEBUG into dbgln_if/if constexpr 2021-05-01 21:25:06 +02:00
Idan Horowitz
115b445dab LibGfx: Add basic support for bidirectional text rendering
This adds a *very* simplified version of the UNICODE BIDIRECTIONAL
ALGORITHM (https://www.unicode.org/reports/tr9/), that can render most
bidirectional text but also produces awkward results in a large amount
of edge cases, and as such, this should probably be replaced with a
fully spec compliant implementation at some point.
2021-04-29 10:36:23 +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
AnotherTest
cb04a441cf LibGfx: Un-recursive-ify the Bezier and Elliptic curve implementations 2021-04-15 17:50:16 +02:00
Idan Horowitz
b7c3f046f7 LibGfx: initialize winding number to 1 for NonZero winding rules
Since we first check the winding number and only then update it, fills
for "Rectangle-like" (made up of 2 parallel segments) paths would draw
nothing when filled by NonZero winding rules. (Fix by alimpfard)
2021-04-14 23:01:23 +02:00
Andreas Kling
d4d8d9ea0b LibGfx: Make sure draw_ui_text() paints underlines with text color
We shouldn't hard-code black here, then we won't respect the system
theme colors. :^)
2021-04-11 01:11:56 +02:00