Class: PDF::Reader::Font

Inherits:
Object
  • Object
show all
Defined in:
lib/pdf/reader/font.rb

Overview

Represents a single font PDF object and provides some useful methods for extracting info. Mainly used for converting text to UTF-8.

Instance Attribute Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(ohash, obj) ⇒ Font

Returns a new instance of Font.

Signature:

  • (PDF::Reader::ObjectHash, Hash[Symbol, untyped]) -> void



80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
# File 'lib/pdf/reader/font.rb', line 80

def initialize(ohash, obj)
  @ohash = ohash
  @tounicode = nil #: PDF::Reader::CMap | nil
  @descendantfonts = [] #: Array[PDF::Reader::Font]
  @widths = [] #: Array[Numeric]
  @first_char = nil #: Integer?
  @last_char = nil #: Integer?
  @basefont = nil #: Symbol?
  @font_descriptor = nil #: PDF::Reader::FontDescriptor?
  @cid_widths = [] #: Array[Numeric]
  @cid_default_width = 0 #: Numeric
  @encoding = PDF::Reader::Encoding.new(:StandardEncoding) #: PDF::Reader::Encoding
  @cached_widths = {} #: Hash[Integer, Numeric]
  @font_matrix = nil #: Array[Numeric] | nil

  extract_base_info(obj)
  extract_type3_info(obj)
  extract_descriptor(obj)
  extract_descendants(obj)
  @width_calc = build_width_calculator #: widthCalculator
  @utf8_cache = {} #: Hash[Integer, String]
end

Instance Attribute Details

#basefontObject (readonly)

Signature:

  • Symbol?



68
69
70
# File 'lib/pdf/reader/font.rb', line 68

def basefont
  @basefont
end

#cid_default_widthObject (readonly)

Signature:

  • Numeric



77
78
79
# File 'lib/pdf/reader/font.rb', line 77

def cid_default_width
  @cid_default_width
end

#cid_widthsObject (readonly)

Signature:

  • Array[Numeric]



74
75
76
# File 'lib/pdf/reader/font.rb', line 74

def cid_widths
  @cid_widths
end

#descendantfontsObject

Signature:

  • Array[PDF::Reader::Font]



53
54
55
# File 'lib/pdf/reader/font.rb', line 53

def descendantfonts
  @descendantfonts
end

#encodingObject

Signature:

  • PDF::Reader::Encoding



50
51
52
# File 'lib/pdf/reader/font.rb', line 50

def encoding
  @encoding
end

#first_charObject (readonly)

Signature:

  • Integer?



62
63
64
# File 'lib/pdf/reader/font.rb', line 62

def first_char
  @first_char
end

#font_descriptorObject (readonly)

Signature:

  • PDF::Reader::FontDescriptor?



71
72
73
# File 'lib/pdf/reader/font.rb', line 71

def font_descriptor
  @font_descriptor
end

#last_charObject (readonly)

Signature:

  • Integer?



65
66
67
# File 'lib/pdf/reader/font.rb', line 65

def last_char
  @last_char
end

#subtypeObject

Signature:

  • Symbol?



47
48
49
# File 'lib/pdf/reader/font.rb', line 47

def subtype
  @subtype
end

#tounicodeObject

Signature:

  • PDF::Reader::CMap | nil



56
57
58
# File 'lib/pdf/reader/font.rb', line 56

def tounicode
  @tounicode
end

#widthsObject (readonly)

Signature:

  • Array[Numeric]



59
60
61
# File 'lib/pdf/reader/font.rb', line 59

def widths
  @widths
end

Instance Method Details

#glyph_width(code_point) ⇒ Object

looks up the specified codepoint and returns a value that is in (pdf) glyph space, which is 1000 glyph units = 1 text space unit

Signature:

  • (Integer | String) -> Numeric



128
129
130
131
132
133
134
135
# File 'lib/pdf/reader/font.rb', line 128

def glyph_width(code_point)
  if code_point.is_a?(String)
    code_point = unpack_string_to_array_of_ints(code_point, encoding.unpack).first
    raise MalformedPDFError, "code point missing" if code_point.nil?
  end

  @cached_widths[code_point] ||= @width_calc.glyph_width(code_point)
end

#glyph_width_in_text_space(code_point) ⇒ Object

In most cases glyph width is converted into text space with a simple divide by 1000.

However, Type3 fonts provide their own FontMatrix that's used for the transformation.

Signature:

  • (Integer | String) -> Numeric



142
143
144
145
146
147
148
149
150
151
152
# File 'lib/pdf/reader/font.rb', line 142

def glyph_width_in_text_space(code_point)
  glyph_width_in_glyph_space = glyph_width(code_point)

  if @subtype == :Type3
    pt1 = font_matrix_transform(Point::ZERO_ZERO)
    pt2 = font_matrix_transform(Point.new(glyph_width_in_glyph_space, 0))
    (pt2.x - pt1.x).abs.round(2)
  else
    glyph_width_in_glyph_space / 1000.0
  end
end

#to_utf8(params) ⇒ Object

Signature:

  • (Integer | String | Array[Integer | String]) -> String



104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
# File 'lib/pdf/reader/font.rb', line 104

def to_utf8(params)
  if @tounicode
    if params.is_a?(Integer)
      cached = @utf8_cache[params]
      return cached unless cached.nil?
      result = to_utf8_via_cmap(params, @tounicode)
      @utf8_cache[params] = result
      result
    else
      to_utf8_via_cmap(params, @tounicode)
    end
  else
    to_utf8_via_encoding(params)
  end
end

#unpack(data) ⇒ Object

Signature:

  • (String) -> (Array[Integer | Float | String | nil] | nil)



121
122
123
# File 'lib/pdf/reader/font.rb', line 121

def unpack(data)
  data.unpack(encoding.unpack)
end