mirror of
https://github.com/RGBCube/serenity
synced 2025-07-26 12:17:35 +00:00
LibPDF: Implement initial support for Type0 truetype fonts
Disclaimers, similar to what's on #23202 (and most of the prerequisites mentioned there are needed for this too): * Only supports the `Identity-H` type0 cmap at the moment * Doesn't support vertical text yet * Only supports the `Identity` CIDToGIDMap at the moment (this one is a truetype-only thing)
This commit is contained in:
parent
76a439124d
commit
f4a59246f5
1 changed files with 44 additions and 10 deletions
|
@ -4,6 +4,7 @@
|
||||||
* SPDX-License-Identifier: BSD-2-Clause
|
* SPDX-License-Identifier: BSD-2-Clause
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
#include <LibGfx/Font/OpenType/Font.h>
|
||||||
#include <LibGfx/Font/ScaledFont.h>
|
#include <LibGfx/Font/ScaledFont.h>
|
||||||
#include <LibPDF/CommonNames.h>
|
#include <LibPDF/CommonNames.h>
|
||||||
#include <LibPDF/Fonts/CFF.h>
|
#include <LibPDF/Fonts/CFF.h>
|
||||||
|
@ -113,6 +114,14 @@ public:
|
||||||
static PDFErrorOr<NonnullOwnPtr<CIDFontType2>> create(Document*, NonnullRefPtr<DictObject> const& descendant, float font_size);
|
static PDFErrorOr<NonnullOwnPtr<CIDFontType2>> create(Document*, NonnullRefPtr<DictObject> const& descendant, float font_size);
|
||||||
|
|
||||||
virtual PDFErrorOr<void> draw_glyph(Gfx::Painter&, Gfx::FloatPoint, float width, u32 cid, Renderer const&) override;
|
virtual PDFErrorOr<void> draw_glyph(Gfx::Painter&, Gfx::FloatPoint, float width, u32 cid, Renderer const&) override;
|
||||||
|
|
||||||
|
private:
|
||||||
|
CIDFontType2(RefPtr<Gfx::Font> font)
|
||||||
|
: m_font(move(font))
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
RefPtr<Gfx::Font> m_font;
|
||||||
};
|
};
|
||||||
|
|
||||||
PDFErrorOr<NonnullOwnPtr<CIDFontType2>> CIDFontType2::create(Document* document, NonnullRefPtr<DictObject> const& descendant, float font_size)
|
PDFErrorOr<NonnullOwnPtr<CIDFontType2>> CIDFontType2::create(Document* document, NonnullRefPtr<DictObject> const& descendant, float font_size)
|
||||||
|
@ -128,22 +137,31 @@ PDFErrorOr<NonnullOwnPtr<CIDFontType2>> CIDFontType2::create(Document* document,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
class IdentityCIDToGIDMap : public OpenType::CharCodeToGlyphIndex {
|
||||||
|
public:
|
||||||
|
virtual u32 glyph_id_for_code_point(u32 char_code) const override
|
||||||
|
{
|
||||||
|
return char_code;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
RefPtr<Gfx::Font> font;
|
RefPtr<Gfx::Font> font;
|
||||||
if (descriptor->contains(CommonNames::FontFile2)) {
|
if (descriptor->contains(CommonNames::FontFile2)) {
|
||||||
auto font_file_stream = TRY(descriptor->get_stream(document, CommonNames::FontFile2));
|
auto font_file_stream = TRY(descriptor->get_stream(document, CommonNames::FontFile2));
|
||||||
float point_size = (font_size * POINTS_PER_INCH) / DEFAULT_DPI;
|
float point_size = (font_size * POINTS_PER_INCH) / DEFAULT_DPI;
|
||||||
// FIXME: Load font_file_stream->bytes() as TTF data, similar to TrueTypeFont::initialize().
|
auto ttf_font = TRY(OpenType::Font::try_load_from_externally_owned_memory(font_file_stream->bytes(), 0, make<IdentityCIDToGIDMap>()));
|
||||||
// Unfortunately, TTF data in Type0 CIDFontType2 fonts don't contain the "cmap" table
|
font = adopt_ref(*new Gfx::ScaledFont(*ttf_font, point_size, point_size));
|
||||||
// that's mandatory per TTF spec and the PDF stores that mapping in CIDToGIDMap instead.
|
|
||||||
// OpenType::Font::try_load currently rejects TTF data without "cmap" data.
|
|
||||||
(void)font_file_stream;
|
|
||||||
(void)point_size;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return TRY(adopt_nonnull_own_or_enomem(new (nothrow) CIDFontType2()));
|
if (!font) {
|
||||||
|
// FIXME: Should we use a fallback font? How common is this for type 0 fonts?
|
||||||
|
return Error::malformed_error("CIDFontType2: missing FontFile2");
|
||||||
|
}
|
||||||
|
|
||||||
|
return TRY(adopt_nonnull_own_or_enomem(new (nothrow) CIDFontType2(move(font))));
|
||||||
}
|
}
|
||||||
|
|
||||||
PDFErrorOr<void> CIDFontType2::draw_glyph(Gfx::Painter&, Gfx::FloatPoint, float, u32, Renderer const&)
|
PDFErrorOr<void> CIDFontType2::draw_glyph(Gfx::Painter& painter, Gfx::FloatPoint point, float width, u32 char_code, Renderer const& renderer)
|
||||||
{
|
{
|
||||||
// ISO 32000 (PDF 2.0) 9.7.4.2 Glyph selection in CIDFonts
|
// ISO 32000 (PDF 2.0) 9.7.4.2 Glyph selection in CIDFonts
|
||||||
// "For Type 2, the CIDFont program is actually a TrueType font program, which has no native notion of CIDs.
|
// "For Type 2, the CIDFont program is actually a TrueType font program, which has no native notion of CIDs.
|
||||||
|
@ -157,8 +175,24 @@ PDFErrorOr<void> CIDFontType2::draw_glyph(Gfx::Painter&, Gfx::FloatPoint, float,
|
||||||
// that maps CIDs to the glyph indices for the appropriate glyph descriptions in that font program.
|
// that maps CIDs to the glyph indices for the appropriate glyph descriptions in that font program.
|
||||||
// * If the TrueType font program is not embedded but is referenced by name, and the Type 2 CIDFont dictionary
|
// * If the TrueType font program is not embedded but is referenced by name, and the Type 2 CIDFont dictionary
|
||||||
// contains a CIDToGIDMap entry, the CIDToGIDMap entry shall be ignored, since it is not meaningful
|
// contains a CIDToGIDMap entry, the CIDToGIDMap entry shall be ignored, since it is not meaningful
|
||||||
/// to refer to glyph indices in an external font program."
|
// to refer to glyph indices in an external font program."
|
||||||
return Error::rendering_unsupported_error("Type0 font CIDFontType2 not implemented yet");
|
|
||||||
|
// FIXME: We don't support non-embedded type0 truetype fonts yet.
|
||||||
|
|
||||||
|
auto style = renderer.state().paint_style;
|
||||||
|
|
||||||
|
// Undo shift in Glyf::Glyph::append_simple_path() via OpenType::Font::rasterize_glyph().
|
||||||
|
auto position = point.translated(0, -m_font->pixel_metrics().ascent);
|
||||||
|
|
||||||
|
if (style.has<Color>()) {
|
||||||
|
painter.draw_glyph(position, char_code, *m_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(position, char_code, *m_font, sample(Gfx::IntPoint(position.x(), position.y())));
|
||||||
|
});
|
||||||
|
}
|
||||||
|
return {};
|
||||||
}
|
}
|
||||||
|
|
||||||
Type0Font::Type0Font() = default;
|
Type0Font::Type0Font() = default;
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue