From e1cf868e6ed86db217deab2c7feb0de4170cb6aa Mon Sep 17 00:00:00 2001 From: MacDue Date: Sun, 9 Jul 2023 20:27:40 +0100 Subject: [PATCH] LibGfx: Use AntiAliasingPainter::fill_path() for drawing font glyphs Using the general AA painter fill_path() is indistinguishable from the previous rasterizer, so this switch simply allows us to share more code. --- Userland/Libraries/LibGfx/CMakeLists.txt | 1 - .../Libraries/LibGfx/Font/OpenType/Glyf.cpp | 15 ++- .../Libraries/LibGfx/Font/OpenType/Glyf.h | 17 +-- .../Libraries/LibGfx/Font/PathRasterizer.cpp | 124 ------------------ .../Libraries/LibGfx/Font/PathRasterizer.h | 28 ---- .../Libraries/LibPDF/Fonts/PS1FontProgram.cpp | 1 - .../LibPDF/Fonts/Type1FontProgram.cpp | 13 +- 7 files changed, 28 insertions(+), 171 deletions(-) delete mode 100644 Userland/Libraries/LibGfx/Font/PathRasterizer.cpp delete mode 100644 Userland/Libraries/LibGfx/Font/PathRasterizer.h diff --git a/Userland/Libraries/LibGfx/CMakeLists.txt b/Userland/Libraries/LibGfx/CMakeLists.txt index 0208e347c0..31370ff69e 100644 --- a/Userland/Libraries/LibGfx/CMakeLists.txt +++ b/Userland/Libraries/LibGfx/CMakeLists.txt @@ -21,7 +21,6 @@ set(SOURCES Font/OpenType/Font.cpp Font/OpenType/Glyf.cpp Font/OpenType/Hinting/Opcodes.cpp - Font/PathRasterizer.cpp Font/ScaledFont.cpp Font/Typeface.cpp Font/WOFF/Font.cpp diff --git a/Userland/Libraries/LibGfx/Font/OpenType/Glyf.cpp b/Userland/Libraries/LibGfx/Font/OpenType/Glyf.cpp index 27728c9cc5..81296b25fb 100644 --- a/Userland/Libraries/LibGfx/Font/OpenType/Glyf.cpp +++ b/Userland/Libraries/LibGfx/Font/OpenType/Glyf.cpp @@ -4,7 +4,9 @@ * SPDX-License-Identifier: BSD-2-Clause */ +#include #include +#include #include #include @@ -258,7 +260,7 @@ ReadonlyBytes Glyf::Glyph::program() const return m_slice.slice(instructions_start + 2, num_instructions); } -void Glyf::Glyph::rasterize_impl(Gfx::PathRasterizer& rasterizer, Gfx::AffineTransform const& transform) const +void Glyf::Glyph::rasterize_impl(Gfx::Painter& painter, Gfx::AffineTransform const& transform) const { // Get offset for flags, x, and y. u16 num_points = be_u16(m_slice.offset_pointer((m_num_contours - 1) * 2)) + 1; @@ -332,20 +334,23 @@ void Glyf::Glyph::rasterize_impl(Gfx::PathRasterizer& rasterizer, Gfx::AffineTra } } - rasterizer.draw_path(path); + constexpr auto base_color = Color::White; + Gfx::AntiAliasingPainter aa_painter { painter }; + aa_painter.fill_path(path, base_color); } RefPtr Glyf::Glyph::rasterize_simple(i16 font_ascender, i16 font_descender, float x_scale, float y_scale, Gfx::GlyphSubpixelOffset subpixel_offset) const { u32 width = (u32)(ceilf((m_xmax - m_xmin) * x_scale)) + 2; u32 height = (u32)(ceilf((font_ascender - font_descender) * y_scale)) + 2; - Gfx::PathRasterizer rasterizer(Gfx::IntSize(width, height)); + auto bitmap = Gfx::Bitmap::create(Gfx::BitmapFormat::BGRA8888, { width, height }).release_value_but_fixme_should_propagate_errors(); auto affine = Gfx::AffineTransform() .translate(subpixel_offset.to_float_point()) .scale(x_scale, -y_scale) .translate(-m_xmin, -font_ascender); - rasterize_impl(rasterizer, affine); - return rasterizer.accumulate(); + Gfx::Painter painter { bitmap }; + rasterize_impl(painter, affine); + return bitmap; } Optional Glyf::glyph(u32 offset) const diff --git a/Userland/Libraries/LibGfx/Font/OpenType/Glyf.h b/Userland/Libraries/LibGfx/Font/OpenType/Glyf.h index 037bbbe8cf..b099e5e2a9 100644 --- a/Userland/Libraries/LibGfx/Font/OpenType/Glyf.h +++ b/Userland/Libraries/LibGfx/Font/OpenType/Glyf.h @@ -13,7 +13,7 @@ #include #include #include -#include +#include #include namespace OpenType { @@ -97,11 +97,11 @@ public: u32 m_offset { 0 }; }; - void rasterize_impl(Gfx::PathRasterizer&, Gfx::AffineTransform const&) const; + void rasterize_impl(Gfx::Painter&, Gfx::AffineTransform const&) const; RefPtr rasterize_simple(i16 ascender, i16 descender, float x_scale, float y_scale, Gfx::GlyphSubpixelOffset) const; template - void rasterize_composite_loop(Gfx::PathRasterizer& rasterizer, Gfx::AffineTransform const& transform, GlyphCb glyph_callback) const + void rasterize_composite_loop(Gfx::Painter& painter, Gfx::AffineTransform const& transform, GlyphCb glyph_callback) const { ComponentIterator component_iterator(m_slice); @@ -118,9 +118,9 @@ public: continue; if (glyph->m_type == Type::Simple) { - glyph->rasterize_impl(rasterizer, affine_here); + glyph->rasterize_impl(painter, affine_here); } else { - glyph->rasterize_composite_loop(rasterizer, transform, glyph_callback); + glyph->rasterize_composite_loop(painter, transform, glyph_callback); } } } @@ -130,15 +130,16 @@ public: { u32 width = (u32)(ceilf((m_xmax - m_xmin) * x_scale)) + 1; u32 height = (u32)(ceilf((font_ascender - font_descender) * y_scale)) + 1; - Gfx::PathRasterizer rasterizer(Gfx::IntSize(width, height)); + auto bitmap = Gfx::Bitmap::create(Gfx::BitmapFormat::BGRA8888, { width, height }).release_value_but_fixme_should_propagate_errors(); auto affine = Gfx::AffineTransform() .translate(subpixel_offset.to_float_point()) .scale(x_scale, -y_scale) .translate(-m_xmin, -font_ascender); - rasterize_composite_loop(rasterizer, affine, glyph_callback); + Gfx::Painter painter { bitmap }; + rasterize_composite_loop(painter, affine, glyph_callback); - return rasterizer.accumulate(); + return bitmap; } Type m_type { Type::Composite }; diff --git a/Userland/Libraries/LibGfx/Font/PathRasterizer.cpp b/Userland/Libraries/LibGfx/Font/PathRasterizer.cpp deleted file mode 100644 index 420e77be0a..0000000000 --- a/Userland/Libraries/LibGfx/Font/PathRasterizer.cpp +++ /dev/null @@ -1,124 +0,0 @@ -/* - * Copyright (c) 2020, Srimanta Barua - * Copyright (c) 2023, Jelle Raaijmakers - * - * SPDX-License-Identifier: BSD-2-Clause - */ - -#include - -namespace Gfx { - -PathRasterizer::PathRasterizer(Gfx::IntSize size) - : m_size(size) -{ - m_data.resize(m_size.area()); - for (int i = 0; i < m_size.area(); i++) - m_data[i] = 0.f; -} - -void PathRasterizer::draw_path(Gfx::Path& path) -{ - for (auto& line : path.split_lines()) - draw_line(line.a(), line.b()); -} - -RefPtr PathRasterizer::accumulate() -{ - auto bitmap_or_error = Gfx::Bitmap::create(Gfx::BitmapFormat::BGRA8888, m_size); - if (bitmap_or_error.is_error()) - return {}; - auto bitmap = bitmap_or_error.release_value_but_fixme_should_propagate_errors(); - Color base_color = Color::from_rgb(0xffffff); - for (int y = 0; y < m_size.height(); y++) { - float accumulator = 0.f; - for (int x = 0; x < m_size.width(); x++) { - accumulator += m_data[y * m_size.width() + x]; - float value = AK::min(AK::abs(accumulator), 1.f); - u8 alpha = value * 255.f; - bitmap->set_pixel(x, y, base_color.with_alpha(alpha)); - } - } - return bitmap; -} - -void PathRasterizer::draw_line(Gfx::FloatPoint p0, Gfx::FloatPoint p1) -{ - // FIXME: Shift x and y according to dy/dx - if (p0.x() < 0.f) - p0.set_x(roundf(p0.x())); - if (p0.y() < 0.f) - p0.set_y(roundf(p0.y())); - if (p1.x() < 0.f) - p1.set_x(roundf(p1.x())); - if (p1.y() < 0.f) - p1.set_y(roundf(p1.y())); - - if (p0.x() < 0.f || p0.y() < 0.f || p0.x() > m_size.width() || p0.y() > m_size.height()) { - dbgln("!P0({},{})", p0.x(), p0.y()); - return; - } - - if (p1.x() < 0.f || p1.y() < 0.f || p1.x() > m_size.width() || p1.y() > m_size.height()) { - dbgln("!P1({},{})", p1.x(), p1.y()); - return; - } - - // If we're on the same Y, there's no need to draw - if (p0.y() == p1.y()) - return; - - float direction = -1.f; - if (p1.y() < p0.y()) { - direction = 1.f; - AK::swap(p0, p1); - } - - float const dxdy = (p1.x() - p0.x()) / (p1.y() - p0.y()); - float const dydx = AK::abs(1.f / dxdy); - - u32 y0 = floorf(p0.y()); - u32 y1 = ceilf(p1.y()); - float x_cur = p0.x(); - - for (u32 y = y0; y < y1; y++) { - u32 line_offset = m_size.width() * y; - - float dy = AK::min(y + 1.f, p1.y()) - AK::max(static_cast(y), p0.y()); - float directed_dy = dy * direction; - float x_next = x_cur + dy * dxdy; - x_next = AK::max(x_next, 0.f); - float x0 = x_cur; - float x1 = x_next; - if (x1 < x0) { - x1 = x_cur; - x0 = x_next; - } - float x0_floor = floorf(x0); - float x1_ceil = ceilf(x1); - u32 x0_floor_i = x0_floor; - - if (x1_ceil <= x0_floor + 1.f) { - // If x0 and x1 are within the same pixel, then area to the right is (1 - (mid(x0, x1) - x0_floor)) * dy - float area = .5f * (x0 + x1) - x0_floor; - m_data[line_offset + x0_floor_i] += directed_dy * (1.f - area); - if (x0_floor_i + 1 < static_cast(m_size.width())) - m_data[line_offset + x0_floor_i + 1] += directed_dy * area; - } else { - float x0_right = 1.f - (x0 - x0_floor); - u32 x1_floor_i = floorf(x1); - float area_upto_here = .5f * x0_right * x0_right * dydx; - m_data[line_offset + x0_floor_i] += direction * area_upto_here; - for (u32 x = x0_floor_i + 1; x < x1_floor_i; x++) { - m_data[line_offset + x] += direction * dydx; - area_upto_here += dydx; - } - float remaining_area = dy - area_upto_here; - m_data[line_offset + x1_floor_i] += direction * remaining_area; - } - - x_cur = x_next; - } -} - -} diff --git a/Userland/Libraries/LibGfx/Font/PathRasterizer.h b/Userland/Libraries/LibGfx/Font/PathRasterizer.h deleted file mode 100644 index 90020da3ef..0000000000 --- a/Userland/Libraries/LibGfx/Font/PathRasterizer.h +++ /dev/null @@ -1,28 +0,0 @@ -/* - * Copyright (c) 2020, Srimanta Barua - * - * SPDX-License-Identifier: BSD-2-Clause - */ - -#pragma once - -#include -#include -#include - -namespace Gfx { - -class PathRasterizer { -public: - PathRasterizer(Gfx::IntSize); - void draw_path(Gfx::Path&); - RefPtr accumulate(); - -private: - void draw_line(Gfx::FloatPoint, Gfx::FloatPoint); - - Gfx::IntSize m_size; - Vector m_data; -}; - -} diff --git a/Userland/Libraries/LibPDF/Fonts/PS1FontProgram.cpp b/Userland/Libraries/LibPDF/Fonts/PS1FontProgram.cpp index 01d9f55abb..a4a5000ef3 100644 --- a/Userland/Libraries/LibPDF/Fonts/PS1FontProgram.cpp +++ b/Userland/Libraries/LibPDF/Fonts/PS1FontProgram.cpp @@ -4,7 +4,6 @@ * SPDX-License-Identifier: BSD-2-Clause */ -#include #include #include #include diff --git a/Userland/Libraries/LibPDF/Fonts/Type1FontProgram.cpp b/Userland/Libraries/LibPDF/Fonts/Type1FontProgram.cpp index 94a8a53a9a..0ee99a015e 100644 --- a/Userland/Libraries/LibPDF/Fonts/Type1FontProgram.cpp +++ b/Userland/Libraries/LibPDF/Fonts/Type1FontProgram.cpp @@ -4,7 +4,8 @@ * SPDX-License-Identifier: BSD-2-Clause */ -#include +#include +#include #include namespace PDF { @@ -54,15 +55,19 @@ enum ExtendedCommand { RefPtr Type1FontProgram::rasterize_glyph(DeprecatedFlyString const& char_name, float width, Gfx::GlyphSubpixelOffset subpixel_offset) { + constexpr auto base_color = Color::White; auto path = build_char(char_name, width, subpixel_offset); auto bounding_box = path.bounding_box().size(); u32 w = (u32)ceilf(bounding_box.width()) + 2; u32 h = (u32)ceilf(bounding_box.height()) + 2; - Gfx::PathRasterizer rasterizer(Gfx::IntSize(w, h)); - rasterizer.draw_path(path); - return rasterizer.accumulate(); + auto bitmap = Gfx::Bitmap::create(Gfx::BitmapFormat::BGRA8888, { w, h }).release_value_but_fixme_should_propagate_errors(); + Gfx::Painter painter { bitmap }; + Gfx::AntiAliasingPainter aa_painter { painter }; + + aa_painter.fill_path(path, base_color); + return bitmap; } Gfx::Path Type1FontProgram::build_char(DeprecatedFlyString const& char_name, float width, Gfx::GlyphSubpixelOffset subpixel_offset)