Class: HexaPDF::Layout::TextShaper

Inherits:
Object
  • Object
show all
Defined in:
lib/hexapdf/layout/text_shaper.rb

Overview

This class is used to perform text shaping, i.e. changing the position of glyphs (e.g. for kerning) or substituting one or more glyphs for other glyphs (e.g. for ligatures).

The class contains two shaping engines: A very limited custom one and one based on HarfBuzz. Which one is used for shaping can be selected via the Style#shaping_engine property.

The custom implementation is always used for Type1 fonts and supports kerning and ligature substitution. It also supports the ‘kern’ table for TrueType fonts if HarfBuzz is not used.

For complex scripts or the need of special font features it is recommended to use the shaping engine based on HarfBuzz, even though it is slightly slower. For it to work the harfbuzz-ruby gem needs to be installed. OpenType features can be activated and deactivated using Style#font_features.

Instance Method Summary collapse

Instance Method Details

#shape_text(text_fragment) ⇒ Object

Shapes the given text fragment. Returns either the in-place modified fragment or, for complex shaping, an array of fragments.

The style properties Style#shaping_engine, Style#font_features, Style#font_script, Style#language and Style#direction are used for shaping.



127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
# File 'lib/hexapdf/layout/text_shaper.rb', line 127

def shape_text(text_fragment)
  font = text_fragment.style.font
  if text_fragment.style.shaping_engine == :harfbuzz && font.font_type == :TrueType
    unless HARFBUZZ_AVAILABLE
      raise HexaPDF::Error, "Shaping engine harfbuzz required but the needed Rubygem " \
        "harfbuzz-ruby is not available"
    end
    return harfbuzz_shape_text(text_fragment)
  end

  if text_fragment.style.font_features[:liga] && font.wrapped_font.features.include?(:liga)
    if font.font_type == :Type1
      process_type1_ligatures(text_fragment)
    end
    text_fragment.clear_cache
  end
  if text_fragment.style.font_features[:kern] && font.wrapped_font.features.include?(:kern)
    case font.font_type
    when :TrueType
      process_true_type_kerning(text_fragment)
    when :Type1
      process_type1_kerning(text_fragment)
    end
    text_fragment.clear_cache
  end

  text_fragment
end