From 5b8deb11d0bc2a40b4e5a3b1eb8ce4339bcd6782 Mon Sep 17 00:00:00 2001 From: David Warring Date: Sun, 15 Dec 2024 10:22:51 +1300 Subject: [PATCH] Add cmap() method --- docs/Font/FreeType/Face.md | 6 ++++++ lib/Font/FreeType/Face.rakumod | 32 +++++++++++++++++++++++++++++++- t/00-basic.t | 4 +++- 3 files changed, 40 insertions(+), 2 deletions(-) diff --git a/docs/Font/FreeType/Face.md b/docs/Font/FreeType/Face.md index 5748a09..837b11e 100644 --- a/docs/Font/FreeType/Face.md +++ b/docs/Font/FreeType/Face.md @@ -92,6 +92,12 @@ Returns an array of Font::FreeType::BitMap::Size objects which detail sizes. Eac Resolution the bitmaps were designed for, in pixels per em. Only available with Freetype 2.1.5 or newer. +### cmap + + say $face.cmap.head(3).raku; # e.g. (3 => " ", 4 => "!", 5 => "\"") + +Iterates the fonts character map, returning character mappings from glyphs-indexes to characters. Any glyphs that don't have character mapping are ommitted. It is also possible for a single glyph-index to map to multiple characters. + ### glyph-images(str) Returns an array of [Font::FreeType::GlyphImage](https://pdf-raku.github.io/Font-FreeType-raku/Font/FreeType/GlyphImage) objects for the Unicode string. diff --git a/lib/Font/FreeType/Face.rakumod b/lib/Font/FreeType/Face.rakumod index 36f0de9..f99128a 100644 --- a/lib/Font/FreeType/Face.rakumod +++ b/lib/Font/FreeType/Face.rakumod @@ -320,6 +320,28 @@ method glyph-images(Str $text, Int :$flags = $!load-flags) { my Font::FreeType::GlyphImage @ = self.forall-char-images({$_}, $text.ords, :$flags); } +method cmap(::?CLASS:D $face:) { + class PairsIteration does Iterator does Iterable { + has Font::FreeType::Face:D $.face is required; + has FT_Face $!raw = $!face.raw; + has FT_UInt $!gid; + has FT_ULong $!char-code = $!raw.FT_Get_First_Char($!gid); + + method pull-one { + if $!gid { + my $rv := $!gid => $!char-code.chr; + $!char-code = $!raw.FT_Get_Next_Char( $!char-code, $!gid); + $rv; + } + else { + IterationEnd; + } + } + method iterator { self } + } + PairsIteration.new: :$face; +} + method set-char-size(Numeric $width, Numeric $height = $width, UInt $horiz-res = 0, UInt $vert-res = 0) { $!lock.protect: sub () is hidden-from-backtrace { my FT_F26Dot6 $w = ($width * Dot6).round; @@ -568,6 +590,15 @@ detail sizes. Each object has the following available methods: Only available with Freetype 2.1.5 or newer. =end item +=head3 cmap + + say $face.cmap.head(3).raku; # e.g. (3 => " ", 4 => "!", 5 => "\"") + +Iterates the fonts character map, returning character mappings from +glyphs-indexes to characters. Any glyphs that don't have character +mapping are ommitted. It is also possible for a single glyph-index to +map to multiple characters. + =head3 glyph-images(str) Returns an array of L objects for the Unicode string. @@ -580,7 +611,6 @@ For example, to load particular glyphs (character images): say $bitmap.Str; }` - =head3 forall-chars($text, &code) $face.forall-chars: "Raku", -> Font::FreeType::Glyph $glyph { ... } diff --git a/t/00-basic.t b/t/00-basic.t index ec08244..b2546ff 100644 --- a/t/00-basic.t +++ b/t/00-basic.t @@ -28,7 +28,7 @@ lives-ok({ cglobal($FT-WRAPPER-LIB, "ft6_glyph_outline", Pointer) }, 'wrapper sy my Font::FreeType::Face $face; lives-ok {$face = $freetype.face('t/fonts/DejaVuSans.ttf') }, 'face creation from filename'; -is-deeply $face.file, 't/fonts/DejaVuSans.ttf'.IO; +is-deeply $face.file, 't/fonts/DejaVuSans.ttf'.IO, 'face file'; is $face.font-format, 'TrueType', 'font format'; is $face.num-faces, 1, 'num-faces'; is $face.family-name, 'DejaVu Sans', 'face family name'; @@ -43,6 +43,8 @@ is $face.units-per-EM, 2048, '.units-per-EM'; is $face.ascender, 1901, '.ascender'; is $face.descender, -483, '.ascender'; +is-deeply $face.cmap.head(3), (3 => " ", 4 => "!", 5 => "\""); + lives-ok {$face = $freetype.face('t/fonts/DejaVuSans.ttf'.IO) }, 'face creation from IO path'; is $face.font-format, 'TrueType', 'font format';