diff options
author | Matthew Olsson <matthewcolsson@gmail.com> | 2021-05-28 11:55:51 -0700 |
---|---|---|
committer | Ali Mohammad Pur <Ali.mpfard@gmail.com> | 2021-06-12 22:45:01 +0430 |
commit | 449ef14895d9e47028a1fa3d8a9426d2ecc8197f (patch) | |
tree | e7de229c1d7b14d9fc35f9871ad0e75b1ba6eedb | |
parent | c142dadbe8d00221da414f77f3f30a311373ec34 (diff) | |
download | serenity-449ef14895d9e47028a1fa3d8a9426d2ecc8197f.zip |
LibPDF: Avoid calculating rendering matrix for every glyph
-rw-r--r-- | Userland/Libraries/LibPDF/Renderer.cpp | 46 | ||||
-rw-r--r-- | Userland/Libraries/LibPDF/Renderer.h | 9 |
2 files changed, 32 insertions, 23 deletions
diff --git a/Userland/Libraries/LibPDF/Renderer.cpp b/Userland/Libraries/LibPDF/Renderer.cpp index efaa2c3cb1..55e65605fa 100644 --- a/Userland/Libraries/LibPDF/Renderer.cpp +++ b/Userland/Libraries/LibPDF/Renderer.cpp @@ -33,15 +33,16 @@ Renderer::Renderer(RefPtr<Document> document, const Page& page, RefPtr<Gfx::Bitm { auto media_box = m_page.media_box; - m_userspace_matrix.translate(media_box.lower_left_x, media_box.lower_left_y); + Gfx::AffineTransform userspace_matrix; + userspace_matrix.translate(media_box.lower_left_x, media_box.lower_left_y); float width = media_box.upper_right_x - media_box.lower_left_x; float height = media_box.upper_right_y - media_box.lower_left_y; float scale_x = static_cast<float>(bitmap->width()) / width; float scale_y = static_cast<float>(bitmap->height()) / height; - m_userspace_matrix.scale(scale_x, scale_y); + userspace_matrix.scale(scale_x, scale_y); - m_graphics_state_stack.append(GraphicsState { m_userspace_matrix }); + m_graphics_state_stack.append(GraphicsState { userspace_matrix }); m_bitmap->fill(Gfx::Color::NamedColor::White); } @@ -317,13 +318,9 @@ RENDERER_HANDLER(text_set_font) font_variant = "Regular"; } - auto specified_font_size = args[1].to_float(); - // FIXME: This scaling should occur when drawing the glyph rather than selecting the font. - // This should be removed when the painter supports arbitrary bitmap scaling. - specified_font_size *= state().ctm.x_scale(); + text_state().font_size = args[1].to_float(); + text_state().font_variant = font_variant; - text_state().font = Gfx::FontDatabase::the().get("Liberation Serif", font_variant, static_cast<int>(specified_font_size)); - VERIFY(text_state().font); m_text_rendering_matrix_is_dirty = true; } @@ -525,19 +522,24 @@ void Renderer::set_graphics_state_from_dict(NonnullRefPtr<DictObject> dict) void Renderer::show_text(const String& string, float shift) { auto utf = Utf8View(string); - auto& font = text_state().font; - for (auto code_point : utf) { - // FIXME: Don't calculate this matrix for every character - auto& text_rendering_matrix = calculate_text_rendering_matrix(); + auto& text_rendering_matrix = calculate_text_rendering_matrix(); + + auto font_size = static_cast<int>(text_rendering_matrix.x_scale() * text_state().font_size); + auto font = Gfx::FontDatabase::the().get(text_state().font_family, text_state().font_variant, font_size); + VERIFY(font); + + auto glyph_position = text_rendering_matrix.map(Gfx::FloatPoint { 0.0f, 0.0f }); + // Reverse the Y axis + glyph_position.set_y(static_cast<float>(m_bitmap->height()) - glyph_position.y()); + // Account for the reversed font baseline + glyph_position.set_y(glyph_position.y() - static_cast<float>(font->baseline())); - auto text_position = text_rendering_matrix.map(Gfx::FloatPoint { 0.0f, 0.0f }); - text_position.set_y(static_cast<float>(m_bitmap->height()) - text_position.y()); - text_position.set_y(text_position.y() - static_cast<float>(font->baseline())); + auto original_position = glyph_position; - // FIXME: For some reason, the space character in LiberationSerif is drawn as an exclamation point + for (auto code_point : utf) { if (code_point != 0x20) - m_painter.draw_glyph(text_position.to_type<int>(), code_point, *text_state().font, state().paint_color); + m_painter.draw_glyph(glyph_position.to_type<int>(), code_point, *font, state().paint_color); auto glyph_width = static_cast<float>(font->glyph_width(code_point)); auto tx = (glyph_width - shift / 1000.0f); @@ -548,9 +550,13 @@ void Renderer::show_text(const String& string, float shift) tx *= text_state().horizontal_scaling; - m_text_rendering_matrix_is_dirty = true; - m_text_matrix = Gfx::AffineTransform(1, 0, 0, 1, tx, 0).multiply(m_text_matrix); + glyph_position += { tx, 0.0f }; } + + // Update text matrix + auto delta_x = glyph_position.x() - original_position.x(); + m_text_rendering_matrix_is_dirty = true; + m_text_matrix = Gfx::AffineTransform(1, 0, 0, 1, delta_x, 0).multiply(m_text_matrix); } RefPtr<ColorSpace> Renderer::get_color_space(const Value& value) diff --git a/Userland/Libraries/LibPDF/Renderer.h b/Userland/Libraries/LibPDF/Renderer.h index b1f61eae4f..3bb67261c2 100644 --- a/Userland/Libraries/LibPDF/Renderer.h +++ b/Userland/Libraries/LibPDF/Renderer.h @@ -55,7 +55,9 @@ struct TextState { float word_spacing { 5.0f }; float horizontal_scaling { 1.0f }; float leading { 0.0f }; - RefPtr<Gfx::Font> font; + FlyString font_family { "Liberation Serif" }; + String font_variant { "Regular" }; + float font_size { 12.0f }; TextRenderingMode rendering_mode { TextRenderingMode::Fill }; float rise { 0.0f }; bool knockout { true }; @@ -122,7 +124,6 @@ private: Vector<GraphicsState> m_graphics_state_stack; Gfx::AffineTransform m_text_matrix; Gfx::AffineTransform m_text_line_matrix; - Gfx::AffineTransform m_userspace_matrix; bool m_text_rendering_matrix_is_dirty { true }; Gfx::AffineTransform m_text_rendering_matrix; @@ -231,7 +232,9 @@ struct Formatter<PDF::TextState> : Formatter<StringView> { builder.appendff(" word_spacing={}\n", state.word_spacing); builder.appendff(" horizontal_scaling={}\n", state.horizontal_scaling); builder.appendff(" leading={}\n", state.leading); - builder.appendff(" font={}\n", state.font ? state.font->name() : "<null>"); + builder.appendff(" font_family={}\n", state.font_family); + builder.appendff(" font_variant={}\n", state.font_variant); + builder.appendff(" font_size={}\n", state.font_size); builder.appendff(" rendering_mode={}\n", state.rendering_mode); builder.appendff(" rise={}\n", state.rise); builder.appendff(" knockout={}\n", state.knockout); |