Skip to content

Commit e04179c

Browse files
committed
LibPDF: Move text rendering strategy selection into SimpleFont
Seems a little neater. This excludes Type0Fonts for now, but it looks like not much of the implementation would be shared. No behaviour change intended.
1 parent e694768 commit e04179c

File tree

5 files changed

+46
-38
lines changed

5 files changed

+46
-38
lines changed

Userland/Libraries/LibPDF/Fonts/PDFFont.h

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -36,10 +36,6 @@ class PDFFont : public RefCounted<PDFFont> {
3636

3737
virtual void set_font_size(float font_size) = 0;
3838
virtual PDFErrorOr<Gfx::FloatPoint> draw_string(Gfx::Painter&, Gfx::FloatPoint, ByteString const&, Renderer const&) = 0;
39-
virtual PDFErrorOr<Gfx::FloatPoint> append_text_path(Gfx::Path&, Gfx::FloatPoint, ByteString const&, Renderer const&)
40-
{
41-
return Error { Error::Type::RenderingUnsupported, "append_text_path not implemented for font" };
42-
}
4339

4440
virtual WritingMode writing_mode() const { return WritingMode::Horizontal; }
4541

Userland/Libraries/LibPDF/Fonts/SimpleFont.cpp

Lines changed: 30 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -100,6 +100,36 @@ PDFErrorOr<Gfx::FloatPoint> SimpleFont::append_text_path(Gfx::Path& path, Gfx::F
100100
}
101101

102102
PDFErrorOr<Gfx::FloatPoint> SimpleFont::draw_string(Gfx::Painter& painter, Gfx::FloatPoint position, ByteString const& string, Renderer const& renderer)
103+
{
104+
auto const& text_rendering_matrix = renderer.calculate_text_rendering_matrix();
105+
// Fast path: Use cached bitmap glyphs.
106+
if (text_rendering_matrix.is_identity_or_translation_or_scale(Gfx::AffineTransform::AllowNegativeScaling::Yes))
107+
return draw_axis_aligned_glyphs(painter, position, string, renderer);
108+
// Slow path: Create a Gfx::Path for the string, transform it, then draw it. This handles arbitrary transforms.
109+
if (auto end_position = draw_transformed_glyphs(painter, position, string, renderer); !end_position.is_error())
110+
return end_position;
111+
// Fallback to axis aligned glyphs in case `append_path` is unimplemented. This won't look correct.
112+
return draw_axis_aligned_glyphs(painter, position, string, renderer);
113+
}
114+
115+
PDFErrorOr<Gfx::FloatPoint> SimpleFont::draw_transformed_glyphs(Gfx::Painter& painter, Gfx::FloatPoint position, ByteString const& string, Renderer const& renderer)
116+
{
117+
Gfx::Path text_path;
118+
Gfx::AntiAliasingPainter aa_painter(painter);
119+
auto horizontal_scaling = renderer.text_state().horizontal_scaling;
120+
auto text_rendering_matrix = renderer.calculate_text_rendering_matrix();
121+
auto end_position = TRY(append_text_path(text_path, position, string, renderer));
122+
// FIXME: This is a bit janky, but the font is already scaled by `m_text_rendering_matrix.x_scale() / horizontal_scaling`,
123+
// which is included in `m_text_rendering_matrix`. So, we must scale it by the reciprocal. Also, the y-axis is flipped.
124+
text_path.transform(text_rendering_matrix.multiply(
125+
Gfx::AffineTransform {}
126+
.set_scale(1 / text_rendering_matrix.x_scale() * horizontal_scaling,
127+
-1 / text_rendering_matrix.x_scale() * horizontal_scaling)));
128+
Renderer::fill_path_with_style(aa_painter, text_path, renderer.state().paint_style, renderer.state().paint_alpha_constant);
129+
return end_position;
130+
}
131+
132+
PDFErrorOr<Gfx::FloatPoint> SimpleFont::draw_axis_aligned_glyphs(Gfx::Painter& painter, Gfx::FloatPoint position, ByteString const& string, Renderer const& renderer)
103133
{
104134
auto horizontal_scaling = renderer.text_state().horizontal_scaling;
105135
auto const& text_rendering_matrix = renderer.calculate_text_rendering_matrix();
@@ -110,5 +140,4 @@ PDFErrorOr<Gfx::FloatPoint> SimpleFont::draw_string(Gfx::Painter& painter, Gfx::
110140
return draw_glyph(painter, glyph_render_position, glyph_width, char_code, renderer);
111141
});
112142
}
113-
114143
}

Userland/Libraries/LibPDF/Fonts/SimpleFont.h

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,12 +14,12 @@ namespace PDF {
1414
class SimpleFont : public PDFFont {
1515
public:
1616
PDFErrorOr<Gfx::FloatPoint> draw_string(Gfx::Painter&, Gfx::FloatPoint, ByteString const&, Renderer const&) override;
17-
PDFErrorOr<Gfx::FloatPoint> append_text_path(Gfx::Path&, Gfx::FloatPoint, ByteString const&, Renderer const&) override;
1817

1918
protected:
2019
PDFErrorOr<void> initialize(Document* document, NonnullRefPtr<DictObject> const& dict, float font_size) override;
2120
virtual Optional<float> get_glyph_width(u8 char_code) const = 0;
2221
virtual PDFErrorOr<void> draw_glyph(Gfx::Painter& painter, Gfx::FloatPoint point, float width, u8 char_code, Renderer const&) = 0;
22+
2323
virtual PDFErrorOr<void> append_glyph_path(Gfx::Path&, Gfx::FloatPoint, u8, Renderer const&)
2424
{
2525
return Error { Error::Type::RenderingUnsupported, "append_glyph_path not implemented for font" };
@@ -34,6 +34,10 @@ class SimpleFont : public PDFFont {
3434
template<typename Callback>
3535
PDFErrorOr<Gfx::FloatPoint> for_each_glyph_position(Gfx::FloatPoint, ByteString const&, Renderer const&, Callback callback);
3636

37+
PDFErrorOr<Gfx::FloatPoint> append_text_path(Gfx::Path&, Gfx::FloatPoint, ByteString const&, Renderer const&);
38+
PDFErrorOr<Gfx::FloatPoint> draw_transformed_glyphs(Gfx::Painter&, Gfx::FloatPoint, ByteString const&, Renderer const&);
39+
PDFErrorOr<Gfx::FloatPoint> draw_axis_aligned_glyphs(Gfx::Painter&, Gfx::FloatPoint, ByteString const&, Renderer const&);
40+
3741
RefPtr<Encoding> m_encoding;
3842
RefPtr<StreamObject> m_to_unicode;
3943
HashMap<u8, u16> m_widths;

Userland/Libraries/LibPDF/Renderer.cpp

Lines changed: 2 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -451,20 +451,11 @@ void Renderer::stroke_current_path()
451451
}
452452
}
453453

454-
static void do_fill_path(Gfx::AntiAliasingPainter& painter, Gfx::Path const& path, ColorOrStyle const& style, float paint_style_opacity = 1.0f, Gfx::WindingRule winding_rule = Gfx::WindingRule::Nonzero)
455-
{
456-
if (auto* paint_style = style.get_pointer<NonnullRefPtr<Gfx::PaintStyle>>()) {
457-
painter.fill_path(path, *paint_style, paint_style_opacity, winding_rule);
458-
} else {
459-
painter.fill_path(path, style.get<Color>(), winding_rule);
460-
}
461-
}
462-
463454
void Renderer::fill_current_path(Gfx::WindingRule winding_rule)
464455
{
465456
auto path_end = m_current_path.end();
466457
m_current_path.close_all_subpaths();
467-
do_fill_path(anti_aliasing_painter(), m_current_path, state().paint_style, state().paint_alpha_constant, winding_rule);
458+
fill_path_with_style(anti_aliasing_painter(), m_current_path, state().paint_style, state().paint_alpha_constant, winding_rule);
468459
// .close_all_subpaths() only adds to the end of the path, so we can .trim() the path to remove any changes.
469460
m_current_path.trim(path_end);
470461
}
@@ -1380,28 +1371,7 @@ PDFErrorOr<void> Renderer::show_text(ByteString const& string)
13801371
return Error::rendering_unsupported_error("Can't draw text because an invalid font was in use");
13811372

13821373
auto start_position = Gfx::FloatPoint { 0.0f, 0.0f };
1383-
auto end_position = start_position;
1384-
1385-
if (m_text_rendering_matrix.is_identity_or_translation_or_scale(Gfx::AffineTransform::AllowNegativeScaling::No)) {
1386-
// Fast path: Use cached bitmap glyphs.
1387-
end_position = TRY(text_state().font->draw_string(painter(), start_position, string, *this));
1388-
} else {
1389-
Gfx::Path text_path;
1390-
// Slow path: Create a Gfx::Path for the string, transform it, then draw it. This handles arbitrary transforms.
1391-
if (auto maybe_end = text_state().font->append_text_path(text_path, start_position, string, *this); !maybe_end.is_error()) {
1392-
end_position = maybe_end.release_value();
1393-
// FIXME: This is a bit janky, but the font is already scaled by `m_text_rendering_matrix.x_scale() / horizontal_scaling`,
1394-
// which is included in `m_text_rendering_matrix`. So, we must scale it by the reciprocal. Also, the y-axis is flipped.
1395-
text_path.transform(m_text_rendering_matrix.multiply(
1396-
Gfx::AffineTransform {}
1397-
.set_scale(1 / m_text_rendering_matrix.x_scale() * text_state().horizontal_scaling,
1398-
-1 / m_text_rendering_matrix.x_scale() * text_state().horizontal_scaling)));
1399-
do_fill_path(anti_aliasing_painter(), text_path, state().paint_style, state().paint_alpha_constant);
1400-
} else {
1401-
// Fallback to the fast path in case `append_path` is unimplemented.
1402-
end_position = TRY(text_state().font->draw_string(painter(), start_position, string, *this));
1403-
}
1404-
}
1374+
auto end_position = TRY(text_state().font->draw_string(painter(), start_position, string, *this));
14051375

14061376
// Update text matrix.
14071377
auto delta = end_position - start_position;

Userland/Libraries/LibPDF/Renderer.h

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -179,6 +179,15 @@ class Renderer {
179179

180180
bool show_hidden_text() const { return m_rendering_preferences.show_hidden_text; }
181181

182+
static void fill_path_with_style(Gfx::AntiAliasingPainter& painter, Gfx::Path const& path, ColorOrStyle const& style, float paint_style_opacity = 1.0f, Gfx::WindingRule winding_rule = Gfx::WindingRule::Nonzero)
183+
{
184+
if (auto* paint_style = style.get_pointer<NonnullRefPtr<Gfx::PaintStyle>>()) {
185+
painter.fill_path(path, *paint_style, paint_style_opacity, winding_rule);
186+
} else {
187+
painter.fill_path(path, style.get<Color>(), winding_rule);
188+
}
189+
}
190+
182191
private:
183192
Renderer(RefPtr<Document>, Page const&, RefPtr<Gfx::Bitmap>, Color background_color, RenderingPreferences);
184193

0 commit comments

Comments
 (0)