mirror of
https://github.com/SerenityOS/serenity.git
synced 2026-11-07 04:29:30 -10:00
LibPDF: Separate resolving glyph IDs from drawing glyphs
This will make reusing the logic to determine glyph IDs easier. No behaviour change intended.
This commit is contained in:
1 parent
20ac70e1a6
commit
e103b1ec36
5 files changed
+28
-39
No files matched your search
@@ -30,6 +30,7 @@ public:
|
||||
ScaledGlyphMetrics glyph_metrics(u32 glyph_id) const { return m_font->glyph_metrics(glyph_id, m_x_scale, m_y_scale, m_point_width, m_point_height); }
|
||||
RefPtr<Gfx::Bitmap> rasterize_glyph(u32 glyph_id, GlyphSubpixelOffset) const;
|
||||
bool append_glyph_path_to(Gfx::Path&, u32 glyph_id) const;
|
||||
Optional<Glyph> glyph_for_id(u32 id, GlyphSubpixelOffset) const;
|
||||
|
||||
// ^Gfx::Font
|
||||
virtual NonnullRefPtr<Font> clone() const override { return MUST(try_clone()); } // FIXME: clone() should not need to be implemented
|
||||
@@ -80,8 +81,6 @@ public:
|
||||
virtual bool has_color_bitmaps() const override { return m_font->has_color_bitmaps(); }
|
||||
|
||||
private:
|
||||
Optional<Glyph> glyph_for_id(u32 id, GlyphSubpixelOffset) const;
|
||||
|
||||
NonnullRefPtr<VectorFont> m_font;
|
||||
float m_x_scale { 0.0f };
|
||||
float m_y_scale { 0.0f };
|
||||
|
||||
@@ -27,6 +27,7 @@
|
||||
#include <AK/Utf32View.h>
|
||||
#include <AK/Utf8View.h>
|
||||
#include <LibGfx/CharacterBitmap.h>
|
||||
#include <LibGfx/Font/ScaledFont.h>
|
||||
#include <LibGfx/Palette.h>
|
||||
#include <LibGfx/Path.h>
|
||||
#include <LibGfx/Quad.h>
|
||||
@@ -1371,14 +1372,14 @@ FLATTEN void Painter::draw_glyph(FloatPoint point, u32 code_point, Font const& f
|
||||
draw_glyph_internal(point, glyph_position, top_left, glyph, color);
|
||||
}
|
||||
|
||||
FLATTEN void Painter::draw_glyph_with_postscript_name(FloatPoint point, StringView name, Font const& font, Color color)
|
||||
FLATTEN void Painter::draw_glyph_via_glyph_id(FloatPoint point, Gfx::ScaledFont const& font, u32 glyph_id, Color color)
|
||||
{
|
||||
auto left_bearing = font.glyph_left_bearing_for_postscript_name(name);
|
||||
if (!left_bearing.has_value())
|
||||
return;
|
||||
auto top_left = point + FloatPoint(left_bearing.value(), 0);
|
||||
auto top_left = point + Gfx::FloatPoint(font.glyph_metrics(glyph_id).left_side_bearing, 0);
|
||||
auto glyph_position = Gfx::GlyphRasterPosition::get_nearest_fit_for(top_left);
|
||||
auto glyph = font.glyph_for_postscript_name(name, glyph_position.subpixel_offset).value();
|
||||
auto maybe_glyph = font.glyph_for_id(glyph_id, glyph_position.subpixel_offset);
|
||||
if (!maybe_glyph.has_value())
|
||||
return;
|
||||
auto glyph = maybe_glyph.release_value();
|
||||
draw_glyph_internal(point, glyph_position, top_left, glyph, color);
|
||||
}
|
||||
|
||||
|
||||
@@ -114,9 +114,9 @@ public:
|
||||
void draw_glyph_or_emoji(IntPoint, Utf8CodePointIterator&, Font const&, Color);
|
||||
void draw_glyph(FloatPoint, u32, Color);
|
||||
void draw_glyph(FloatPoint, u32, Font const&, Color);
|
||||
void draw_glyph_with_postscript_name(FloatPoint point, StringView name, Font const& font, Color color);
|
||||
void draw_glyph_or_emoji(FloatPoint, u32, Font const&, Color);
|
||||
void draw_glyph_or_emoji(FloatPoint, Utf8CodePointIterator&, Font const&, Color);
|
||||
void draw_glyph_via_glyph_id(FloatPoint, Gfx::ScaledFont const&, u32, Color);
|
||||
void draw_circle_arc_intersecting(IntRect const&, IntPoint, int radius, Color, int thickness);
|
||||
|
||||
// Streamlined text drawing routine that does no wrapping/elision/alignment.
|
||||
|
||||
@@ -62,40 +62,23 @@ NonnullOwnPtr<TrueTypePainter> TrueTypePainter::create(Document* document, Nonnu
|
||||
return adopt_own(*new TrueTypePainter { move(font), move(encoding), encoding_is_mac_roman_or_win_ansi, containing_pdf_font.is_nonsymbolic(), high_byte, is_zapf_dingbats });
|
||||
}
|
||||
|
||||
static void do_draw_glyph(Gfx::Painter& painter, Gfx::FloatPoint point, float width, u32 unicode, Gfx::ScaledFont const& font, ColorOrStyle const& style)
|
||||
static void do_draw_glyph(Gfx::Painter& painter, u32 glyph_id, Gfx::FloatPoint point, float width, Gfx::ScaledFont const& font, ColorOrStyle const& style)
|
||||
{
|
||||
// Undo shift in Glyf::Glyph::append_simple_path() via OpenType::Font::rasterize_glyph().
|
||||
auto position = point.translated(0, -font.pixel_metrics().ascent);
|
||||
|
||||
if (style.has<Color>()) {
|
||||
painter.draw_glyph(position, unicode, font, style.get<Color>());
|
||||
painter.draw_glyph_via_glyph_id(position, font, glyph_id, style.get<Color>());
|
||||
} else {
|
||||
// FIXME: Bounding box and sample point look to be pretty wrong
|
||||
style.get<NonnullRefPtr<Gfx::PaintStyle>>()->paint(Gfx::IntRect(position.x(), position.y(), width, 0), [&](auto sample) {
|
||||
painter.draw_glyph(position, unicode, font, sample(Gfx::IntPoint(position.x(), position.y())));
|
||||
painter.draw_glyph_via_glyph_id(position, font, glyph_id, sample(Gfx::IntPoint(position.x(), position.y())));
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
static void do_draw_glyph_with_postscript_name(Gfx::Painter& painter, Gfx::FloatPoint point, float width, StringView postscript_name, Gfx::ScaledFont const& font, ColorOrStyle const& style)
|
||||
PDFErrorOr<TrueTypePainter::GlyphID> TrueTypePainter::resolve_glyph_id_for_char_code(u8 char_code)
|
||||
{
|
||||
// Undo shift in Glyf::Glyph::append_simple_path() via OpenType::Font::rasterize_glyph().
|
||||
auto position = point.translated(0, -font.pixel_metrics().ascent);
|
||||
|
||||
if (style.has<Color>()) {
|
||||
painter.draw_glyph_with_postscript_name(position, postscript_name, font, style.get<Color>());
|
||||
} else {
|
||||
// FIXME: Bounding box and sample point look to be pretty wrong
|
||||
style.get<NonnullRefPtr<Gfx::PaintStyle>>()->paint(Gfx::IntRect(position.x(), position.y(), width, 0), [&](auto sample) {
|
||||
painter.draw_glyph_with_postscript_name(position, postscript_name, font, sample(Gfx::IntPoint(position.x(), position.y())));
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
PDFErrorOr<void> TrueTypePainter::draw_glyph(Gfx::Painter& painter, Gfx::FloatPoint point, float width, u8 char_code, Renderer const& renderer)
|
||||
{
|
||||
auto style = renderer.state().paint_style;
|
||||
|
||||
// 5.5.5 Character Encoding, Encodings for TrueType Fonts
|
||||
u32 unicode;
|
||||
|
||||
@@ -126,17 +109,13 @@ PDFErrorOr<void> TrueTypePainter::draw_glyph(Gfx::Painter& painter, Gfx::FloatPo
|
||||
// FIXME: Implement (1, 0) subtable support.
|
||||
auto char_name = m_encoding->get_name(char_code);
|
||||
u32 unicode = glyph_name_to_unicode(char_name, m_is_zapf_dingbats).value_or(char_code);
|
||||
if (m_font->contains_glyph(unicode)) {
|
||||
do_draw_glyph(painter, point, width, unicode, *m_font, style);
|
||||
return {};
|
||||
}
|
||||
if (m_font->contains_glyph(unicode))
|
||||
return m_font->glyph_id_for_code_point(unicode);
|
||||
|
||||
// "In either of the cases above, if the glyph name cannot be mapped as specified, the glyph name is looked up
|
||||
// in the font program’s “post” table (if one is present) and the associated glyph description is used."
|
||||
if (m_font->contains_glyph_for_postscript_name(char_name)) {
|
||||
do_draw_glyph_with_postscript_name(painter, point, width, char_name, *m_font, style);
|
||||
return {};
|
||||
}
|
||||
if (m_font->contains_glyph_for_postscript_name(char_name))
|
||||
return m_font->glyph_id_for_postscript_name(char_name);
|
||||
|
||||
return Error::malformed_error("Failed to draw glyph with postscript name");
|
||||
} else if (m_high_byte.has_value()) {
|
||||
@@ -158,7 +137,14 @@ PDFErrorOr<void> TrueTypePainter::draw_glyph(Gfx::Painter& painter, Gfx::FloatPo
|
||||
unicode = glyph_name_to_unicode(char_name, m_is_zapf_dingbats).value_or(char_code);
|
||||
}
|
||||
|
||||
do_draw_glyph(painter, point, width, unicode, *m_font, style);
|
||||
return m_font->glyph_id_for_code_point(unicode);
|
||||
}
|
||||
|
||||
PDFErrorOr<void> TrueTypePainter::draw_glyph(Gfx::Painter& painter, Gfx::FloatPoint point, float width, u8 char_code, Renderer const& renderer)
|
||||
{
|
||||
auto glyph_id = TRY(resolve_glyph_id_for_char_code(char_code));
|
||||
if (glyph_id.has_value())
|
||||
do_draw_glyph(painter, *glyph_id, point, width, m_font, renderer.state().paint_style);
|
||||
return {};
|
||||
}
|
||||
|
||||
|
||||
@@ -23,6 +23,9 @@ public:
|
||||
private:
|
||||
TrueTypePainter(AK::NonnullRefPtr<Gfx::ScaledFont>, NonnullRefPtr<Encoding>, bool encoding_is_mac_roman_or_win_ansi, bool is_nonsymbolic, Optional<u8> high_byte, bool is_zapf_dingbats);
|
||||
|
||||
using GlyphID = Optional<u32>;
|
||||
PDFErrorOr<GlyphID> resolve_glyph_id_for_char_code(u8 char_code);
|
||||
|
||||
NonnullRefPtr<Gfx::ScaledFont> m_font;
|
||||
NonnullRefPtr<Encoding> m_encoding;
|
||||
bool m_encoding_is_mac_roman_or_win_ansi { false };
|
||||
|
||||
Reference in new issue
Block a user