Class: Prawn::Font::TTF

Inherits:
Prawn::Font show all
Defined in:
lib/prawn/font/ttf.rb

Direct Known Subclasses

DFont

Instance Attribute Summary collapse

Attributes inherited from Prawn::Font

#family, #name, #options

Instance Method Summary collapse

Methods inherited from Prawn::Font

#add_to_current_page, #ascender, #descender, #height, #height_at, #identifier_for, #inspect, #line_gap, load, #normalize_encoding!

Constructor Details

#initialize(document, name, options = {}) ⇒ TTF

Returns a new instance of TTF.


9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
# File 'lib/prawn/font/ttf.rb', line 9

def initialize(document, name, options={})
  super

  @ttf              = read_ttf_file
  @subsets          = TTFunk::SubsetCollection.new(@ttf)

  @attributes       = {}
  @bounding_boxes   = {} 
  @char_widths      = {}   
  @has_kerning_data = @ttf.kerning.exists? && @ttf.kerning.tables.any?

  @ascender         = Integer(@ttf.ascent * scale_factor)
  @descender        = Integer(@ttf.descent * scale_factor)
  @line_gap         = Integer(@ttf.line_gap * scale_factor)
end

Instance Attribute Details

#subsetsObject (readonly)

Returns the value of attribute subsets


7
8
9
# File 'lib/prawn/font/ttf.rb', line 7

def subsets
  @subsets
end

#ttfObject (readonly)

Returns the value of attribute ttf


7
8
9
# File 'lib/prawn/font/ttf.rb', line 7

def ttf
  @ttf
end

Instance Method Details

#basenameObject


91
92
93
# File 'lib/prawn/font/ttf.rb', line 91

def basename
  @basename ||= @ttf.name.postscript_name
end

#bboxObject


44
45
46
# File 'lib/prawn/font/ttf.rb', line 44

def bbox
  @bbox ||= @ttf.bbox.map { |i| Integer(i * scale_factor) }
end

#cap_heightObject


111
112
113
114
115
116
# File 'lib/prawn/font/ttf.rb', line 111

def cap_height
  @cap_height ||= begin
    height = @ttf.os2.exists? && @ttf.os2.cap_height || 0
    height == 0 ? ascender : height
  end
end

#compute_width_of(string, options = {}) ⇒ Object

string must be UTF8-encoded.


27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
# File 'lib/prawn/font/ttf.rb', line 27

def compute_width_of(string, options={})
  scale = (options[:size] || size) / 1000.0
  if options[:kerning]
    kern(string).inject(0) do |s,r|
      if r.is_a?(Numeric)
        s - r
      else 
        r.inject(s) { |s2, u| s2 + character_width_by_code(u) }
      end
    end * scale
  else
    string.unpack("U*").inject(0) do |s,r|
      s + character_width_by_code(r)
    end * scale
  end
end

#encode_text(text, options = {}) ⇒ Object

Perform any changes to the string that need to happen before it is rendered to the canvas. Returns an array of subset “chunks”, where the even-numbered indices are the font subset number, and the following entry element is either a string or an array (for kerned text).

The text parameter must be UTF8-encoded.


60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
# File 'lib/prawn/font/ttf.rb', line 60

def encode_text(text,options={})
  text = text.chomp

  if options[:kerning]
    last_subset = nil
    kern(text).inject([]) do |result, element| 
      if element.is_a?(Numeric)
        result.last[1] = [result.last[1]] unless result.last[1].is_a?(Array)
        result.last[1] << element
        result
      else
        encoded = @subsets.encode(element)

        if encoded.first[0] == last_subset
          result.last[1] << encoded.first[1]
          encoded.shift
        end

        if encoded.any?
          last_subset = encoded.last[0]
          result + encoded
        else
          result
        end
      end
    end
  else
    @subsets.encode(text.unpack("U*"))
  end
end

#family_classObject


124
125
126
# File 'lib/prawn/font/ttf.rb', line 124

def family_class
  @family_class ||= (@ttf.os2.exists? && @ttf.os2.family_class || 0) >> 8
end

#has_kerning_data?Boolean

Returns:

  • (Boolean)

48
49
50
# File 'lib/prawn/font/ttf.rb', line 48

def has_kerning_data?
  @has_kerning_data 
end

#italic_angleObject


100
101
102
103
104
105
106
107
108
109
# File 'lib/prawn/font/ttf.rb', line 100

def italic_angle
  @italic_angle ||= if @ttf.postscript.exists?
    raw = @ttf.postscript.italic_angle
    hi, low = raw >> 16, raw & 0xFF
    hi = -((hi ^ 0xFFFF) + 1) if hi & 0x8000 != 0
    "#{hi}.#{low}".to_f
  else
    0
  end
end

#normalize_encoding(text) ⇒ Object


147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
# File 'lib/prawn/font/ttf.rb', line 147

def normalize_encoding(text)
  if text.respond_to?(:encode)
    # if we're running under a M17n aware VM, ensure the string provided is
    # UTF-8 (by converting it if necessary)
    begin
      text.encode("UTF-8")
    rescue
      raise Prawn::Errors::IncompatibleStringEncoding, "Encoding " +
      "#{text.encoding} can not be transparently converted to UTF-8. " +
      "Please ensure the encoding of the string you are attempting " +
      "to use is set correctly"
    end
  else
    # on a non M17N aware VM, use unpack as a hackish way to verify the
    # string is valid utf-8. I thought it was better than loading iconv
    # though.
    begin
      text.unpack("U*")
      return text.dup
    rescue
      raise Prawn::Errors::IncompatibleStringEncoding, "The string you " +
        "are attempting to render is not encoded in valid UTF-8."
    end
  end
end

#pdf_flagsObject


136
137
138
139
140
141
142
143
144
145
# File 'lib/prawn/font/ttf.rb', line 136

def pdf_flags
  @flags ||= begin
    flags = 0
    flags |= 0x0001 if @ttf.postscript.fixed_pitch?
    flags |= 0x0002 if serif?
    flags |= 0x0008 if script?
    flags |= 0x0040 if italic_angle != 0
    flags |= 0x0004 # assume the font contains at least some non-latin characters
  end
end

#script?Boolean

Returns:

  • (Boolean)

132
133
134
# File 'lib/prawn/font/ttf.rb', line 132

def script?
  @script ||= family_class == 10
end

#serif?Boolean

Returns:

  • (Boolean)

128
129
130
# File 'lib/prawn/font/ttf.rb', line 128

def serif?
  @serif ||= [1,2,3,4,5,7].include?(family_class)
end

#stemVObject

not sure how to compute this for true-type fonts…


96
97
98
# File 'lib/prawn/font/ttf.rb', line 96

def stemV
  0
end

#x_heightObject


118
119
120
121
122
# File 'lib/prawn/font/ttf.rb', line 118

def x_height
  # FIXME: seems like if os2 table doesn't exist, we could
  # just find the height of the lower-case 'x' glyph?
  @ttf.os2.exists? && @ttf.os2.x_height || 0
end