mirror of
https://github.com/RGBCube/serenity
synced 2025-07-26 07:47:37 +00:00
LibPDF: Turn Glyph into a class
Glyph was a simple structure, but even now it's become more complex that it was initially. Turning it into a class hides some of that complexity, and make sit easier to understand to external eyes. While doing this I also decided to remove the float + bool combo for keeping track of the glyph's width, and replaced it with an Optional instead.
This commit is contained in:
parent
c084943457
commit
11a9bfd4b6
3 changed files with 27 additions and 18 deletions
|
@ -102,10 +102,10 @@ PDFErrorOr<NonnullRefPtr<CFF>> CFF::create(ReadonlyBytes const& cff_bytes, RefPt
|
||||||
|
|
||||||
// Adjust glyphs' widths as they are deltas from nominalWidthX
|
// Adjust glyphs' widths as they are deltas from nominalWidthX
|
||||||
for (auto& glyph : glyphs) {
|
for (auto& glyph : glyphs) {
|
||||||
if (!glyph.width_specified)
|
if (!glyph.has_width())
|
||||||
glyph.width = float(defaultWidthX);
|
glyph.set_width(float(defaultWidthX));
|
||||||
else
|
else
|
||||||
glyph.width += float(nominalWidthX);
|
glyph.set_width(glyph.width() + float(nominalWidthX));
|
||||||
}
|
}
|
||||||
|
|
||||||
for (size_t i = 0; i < glyphs.size(); i++) {
|
for (size_t i = 0; i < glyphs.size(); i++) {
|
||||||
|
|
|
@ -71,17 +71,16 @@ Gfx::Path Type1FontProgram::build_char(DeprecatedFlyString const& char_name, flo
|
||||||
if (!maybe_glyph.has_value())
|
if (!maybe_glyph.has_value())
|
||||||
return {};
|
return {};
|
||||||
|
|
||||||
auto& glyph = maybe_glyph.value();
|
auto const& glyph = maybe_glyph.value();
|
||||||
auto transform = Gfx::AffineTransform()
|
auto transform = Gfx::AffineTransform()
|
||||||
.translate(subpixel_offset.to_float_point())
|
.translate(subpixel_offset.to_float_point())
|
||||||
.multiply(glyph_transform_to_device_space(glyph, width));
|
.multiply(glyph_transform_to_device_space(glyph, width));
|
||||||
|
|
||||||
// Translate such that the top-left point is at [0, 0].
|
// Translate such that the top-left point is at [0, 0].
|
||||||
auto bounding_box = glyph.path.bounding_box();
|
auto bounding_box = glyph.path().bounding_box();
|
||||||
Gfx::FloatPoint translation(-bounding_box.x(), -(bounding_box.y() + bounding_box.height()));
|
Gfx::FloatPoint translation(-bounding_box.x(), -(bounding_box.y() + bounding_box.height()));
|
||||||
transform.translate(translation);
|
transform.translate(translation);
|
||||||
|
return glyph.path().copy_transformed(transform);
|
||||||
return glyph.path.copy_transformed(transform);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Gfx::FloatPoint Type1FontProgram::glyph_translation(DeprecatedFlyString const& char_name, float width) const
|
Gfx::FloatPoint Type1FontProgram::glyph_translation(DeprecatedFlyString const& char_name, float width) const
|
||||||
|
@ -94,7 +93,7 @@ Gfx::FloatPoint Type1FontProgram::glyph_translation(DeprecatedFlyString const& c
|
||||||
auto transform = glyph_transform_to_device_space(glyph, width);
|
auto transform = glyph_transform_to_device_space(glyph, width);
|
||||||
|
|
||||||
// Undo the translation we applied earlier.
|
// Undo the translation we applied earlier.
|
||||||
auto bounding_box = glyph.path.bounding_box();
|
auto bounding_box = glyph.path().bounding_box();
|
||||||
Gfx::FloatPoint translation(bounding_box.x(), bounding_box.y() + bounding_box.height());
|
Gfx::FloatPoint translation(bounding_box.x(), bounding_box.y() + bounding_box.height());
|
||||||
|
|
||||||
return transform.map(translation);
|
return transform.map(translation);
|
||||||
|
@ -102,7 +101,7 @@ Gfx::FloatPoint Type1FontProgram::glyph_translation(DeprecatedFlyString const& c
|
||||||
|
|
||||||
Gfx::AffineTransform Type1FontProgram::glyph_transform_to_device_space(Glyph const& glyph, float width) const
|
Gfx::AffineTransform Type1FontProgram::glyph_transform_to_device_space(Glyph const& glyph, float width) const
|
||||||
{
|
{
|
||||||
auto scale = width / (m_font_matrix.a() * glyph.width + m_font_matrix.e());
|
auto scale = width / (m_font_matrix.a() * glyph.width() + m_font_matrix.e());
|
||||||
auto transform = m_font_matrix;
|
auto transform = m_font_matrix;
|
||||||
|
|
||||||
// Convert character space to device space.
|
// Convert character space to device space.
|
||||||
|
@ -132,7 +131,7 @@ PDFErrorOr<Type1FontProgram::Glyph> Type1FontProgram::parse_glyph(ReadonlyBytes
|
||||||
return value;
|
return value;
|
||||||
};
|
};
|
||||||
|
|
||||||
auto& path = state.glyph.path;
|
auto& path = state.glyph.path();
|
||||||
auto& point = state.point;
|
auto& point = state.point;
|
||||||
|
|
||||||
// Core operations: move to, line to, curve to
|
// Core operations: move to, line to, curve to
|
||||||
|
@ -214,8 +213,7 @@ PDFErrorOr<Type1FontProgram::Glyph> Type1FontProgram::parse_glyph(ReadonlyBytes
|
||||||
auto maybe_read_width = [&](EvenOrOdd required_argument_count) {
|
auto maybe_read_width = [&](EvenOrOdd required_argument_count) {
|
||||||
if (!is_type2 || !is_first_command || state.sp % 2 != required_argument_count)
|
if (!is_type2 || !is_first_command || state.sp % 2 != required_argument_count)
|
||||||
return;
|
return;
|
||||||
state.glyph.width = pop_front();
|
state.glyph.set_width(pop_front());
|
||||||
state.glyph.width_specified = true;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
// Parse the stream of parameters and commands that make up a glyph outline.
|
// Parse the stream of parameters and commands that make up a glyph outline.
|
||||||
|
@ -434,8 +432,7 @@ PDFErrorOr<Type1FontProgram::Glyph> Type1FontProgram::parse_glyph(ReadonlyBytes
|
||||||
auto wx = pop();
|
auto wx = pop();
|
||||||
auto sbx = pop();
|
auto sbx = pop();
|
||||||
|
|
||||||
state.glyph.width = wx;
|
state.glyph.set_width(wx);
|
||||||
state.glyph.width_specified = true;
|
|
||||||
state.point = { sbx, 0.0f };
|
state.point = { sbx, 0.0f };
|
||||||
state.sp = 0;
|
state.sp = 0;
|
||||||
break;
|
break;
|
||||||
|
|
|
@ -25,10 +25,22 @@ public:
|
||||||
RefPtr<Encoding> encoding() const { return m_encoding; }
|
RefPtr<Encoding> encoding() const { return m_encoding; }
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
struct Glyph {
|
class Glyph {
|
||||||
Gfx::Path path;
|
|
||||||
float width { 0 };
|
public:
|
||||||
bool width_specified { false };
|
bool has_width() const { return m_width.has_value(); }
|
||||||
|
float width() const { return m_width.value(); }
|
||||||
|
void set_width(float width)
|
||||||
|
{
|
||||||
|
m_width = width;
|
||||||
|
}
|
||||||
|
|
||||||
|
Gfx::Path& path() { return m_path; }
|
||||||
|
Gfx::Path const& path() const { return m_path; }
|
||||||
|
|
||||||
|
private:
|
||||||
|
Gfx::Path m_path;
|
||||||
|
Optional<float> m_width;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct GlyphParserState {
|
struct GlyphParserState {
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue