1
Fork 0
mirror of https://github.com/RGBCube/serenity synced 2025-07-27 06:27:45 +00:00

LibGfx+LibTTF: Allow Painter to draw TTF glyphs

This commit is contained in:
Stephan Unverwerth 2021-01-02 18:22:22 +01:00 committed by Andreas Kling
parent 0f41f5d9ba
commit 85158dc0ad
5 changed files with 66 additions and 14 deletions

View file

@ -75,18 +75,27 @@ public:
{
}
Glyph(RefPtr<Bitmap> bitmap)
Glyph(RefPtr<Bitmap> bitmap, int left_bearing, int advance, int ascent)
: m_bitmap(bitmap)
, m_left_bearing(left_bearing)
, m_advance(advance)
, m_ascent(ascent)
{
}
bool is_glyph_bitmap() const { return !m_bitmap; }
GlyphBitmap glyph_bitmap() const { return m_glyph_bitmap; }
RefPtr<Bitmap> bitmap() const { return m_bitmap; }
int left_bearing() const { return m_left_bearing; }
int advance() const { return m_advance; }
int ascent() const { return m_ascent; }
private:
GlyphBitmap m_glyph_bitmap;
RefPtr<Bitmap> m_bitmap;
int m_left_bearing;
int m_advance;
int m_ascent;
};
class Font : public RefCounted<Font> {

View file

@ -900,7 +900,16 @@ FLATTEN void Painter::draw_glyph(const IntPoint& point, u32 code_point, Color co
FLATTEN void Painter::draw_glyph(const IntPoint& point, u32 code_point, const Font& font, Color color)
{
draw_bitmap(point, font.glyph(code_point).glyph_bitmap(), color);
auto glyph = font.glyph(code_point);
if (glyph.is_glyph_bitmap()) {
draw_bitmap(point, glyph.glyph_bitmap(), color);
} else {
auto top_left = point + IntPoint(glyph.left_bearing(), font.x_height() - glyph.ascent());
blit_filtered(top_left, *glyph.bitmap(), glyph.bitmap()->rect(), [color](Color pixel) -> Color {
return pixel.multiply(color);
});
}
}
void Painter::draw_emoji(const IntPoint& point, const Gfx::Bitmap& emoji, const Font& font)

View file

@ -5,4 +5,4 @@ set(SOURCES
)
serenity_lib(LibTTF ttf)
target_link_libraries(LibGfx LibM LibCore)
target_link_libraries(LibTTF LibM LibCore)

View file

@ -481,6 +481,35 @@ String Font::variant() const
return m_name.subfamily_name();
}
u16 Font::weight() const
{
// FIXME: This is pretty naive, read weight from the actual font table(s)
auto variant_name = variant();
if (variant_name == "Thin")
return 100;
if (variant_name == "Extra Light")
return 200;
if (variant_name == "Light")
return 300;
if (variant_name == "Regular")
return 400;
if (variant_name == "Medium")
return 500;
if (variant_name == "Semi Bold")
return 600;
if (variant_name == "Bold")
return 700;
if (variant_name == "Extra Bold")
return 800;
if (variant_name == "Black")
return 900;
if (variant_name == "Extra Black")
return 950;
return 400;
}
int ScaledFont::width(const StringView& string) const
{
Utf8View utf8 { string };
@ -524,7 +553,8 @@ Gfx::Glyph ScaledFont::glyph(u32 code_point) const
{
auto id = glyph_id_for_codepoint(code_point);
auto bitmap = raster_glyph(id);
return Gfx::Glyph(bitmap);
auto metrics = glyph_metrics(id);
return Gfx::Glyph(bitmap, metrics.left_side_bearing, metrics.advance_width, metrics.ascender);
}
u8 ScaledFont::glyph_width(size_t code_point) const

View file

@ -123,6 +123,8 @@ class ScaledFont : public Gfx::Font {
public:
ScaledFont(RefPtr<TTF::Font> font, float point_width, float point_height, unsigned dpi_x = DEFAULT_DPI, unsigned dpi_y = DEFAULT_DPI)
: m_font(font)
, m_point_width(point_width)
, m_point_height(point_height)
{
float units_per_em = m_font->units_per_em();
m_x_scale = (point_width * dpi_x) / (POINTS_PER_INCH * units_per_em);
@ -135,18 +137,18 @@ public:
// Gfx::Font implementation
virtual NonnullRefPtr<Font> clone() const override { return *this; } /* TODO */
virtual u8 presentation_size() const override { return (u8)m_y_scale; }
virtual u16 weight() const override { return 400; } /* TODO */
virtual u8 presentation_size() const override { return m_point_height; }
virtual u16 weight() const override { return m_font->weight(); }
virtual Gfx::Glyph glyph(u32 code_point) const override;
virtual u8 glyph_width(size_t ch) const override;
virtual int glyph_or_emoji_width(u32 code_point) const override;
virtual u8 glyph_height() const override { return m_y_scale; } /* TODO */
virtual int x_height() const override { return m_y_scale; } /* TODO */
virtual u8 glyph_height() const override { return m_point_height; } /* TODO */
virtual int x_height() const override { return m_point_height; } /* TODO */
virtual u8 min_glyph_width() const override { return 1; } /* TODO */
virtual u8 max_glyph_width() const override { return m_x_scale; } /* TODO */
virtual u8 max_glyph_width() const override { return m_point_height; } /* TODO */
virtual u8 glyph_fixed_width() const override;
virtual u8 baseline() const override { return m_y_scale; } /* TODO */
virtual u8 mean_line() const override { return m_y_scale; } /* TODO */
virtual u8 baseline() const override { return m_point_height; } /* TODO */
virtual u8 mean_line() const override { return m_point_height; } /* TODO */
virtual int width(const StringView&) const override;
virtual int width(const Utf8View&) const override;
virtual int width(const Utf32View&) const override;
@ -161,8 +163,10 @@ public:
private:
RefPtr<TTF::Font> m_font;
float m_x_scale { 0.0 };
float m_y_scale { 0.0 };
float m_x_scale { 0.0f };
float m_y_scale { 0.0f };
float m_point_width { 0.0f };
float m_point_height { 0.0f };
mutable AK::HashMap<u32, RefPtr<Gfx::Bitmap>> m_cached_glyph_bitmaps;
};