Class: Prawn::Font::Metrics::TTF

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

Overview

:nodoc:

Instance Attribute Summary collapse

Instance Method Summary collapse

Methods inherited from Prawn::Font::Metrics

[], data, #font_height, #string_height

Methods included from Wrapping

#naive_wrap

Constructor Details

#initialize(font) ⇒ TTF

Returns a new instance of TTF.



255
256
257
258
259
260
261
262
# File 'lib/prawn/font/metrics.rb', line 255

def initialize(font)
  @ttf = ::Font::TTF::File.open(font,"rb")
  @attributes       = {}
  @glyph_widths     = {}
  @bounding_boxes   = {} 
  @char_widths      = {}   
  @has_kerning_data = !kern_pairs_table.empty?    
end

Instance Attribute Details

#ttfObject

Returns the value of attribute ttf.



253
254
255
# File 'lib/prawn/font/metrics.rb', line 253

def ttf
  @ttf
end

Instance Method Details

#ascenderObject



345
346
347
# File 'lib/prawn/font/metrics.rb', line 345

def ascender
  Integer(@ttf.get_table(:hhea).ascender * scale_factor)
end

#basenameObject



357
358
359
360
361
362
363
364
365
# File 'lib/prawn/font/metrics.rb', line 357

def basename
  return @basename if @basename
  ps_name = ::Font::TTF::Table::Name::NameRecord::POSTSCRIPT_NAME

  @ttf.get_table(:name).name_records.each do |rec|
    @basename = rec.utf8_str.to_sym if rec.name_id == ps_name            
  end
  @basename
end

#bboxObject



338
339
340
341
342
343
# File 'lib/prawn/font/metrics.rb', line 338

def bbox
  head = @ttf.get_table(:head)
  [:x_min, :y_min, :x_max, :y_max].map do |atr| 
    Integer(head.send(atr)) * scale_factor
  end
end

#cmapObject



264
265
266
# File 'lib/prawn/font/metrics.rb', line 264

def cmap
  @cmap ||= enc_table.charmaps
end

#convert_text(text, options) ⇒ Object



411
412
413
414
415
416
417
418
419
420
421
422
# File 'lib/prawn/font/metrics.rb', line 411

def convert_text(text,options)
  text = text.chomp
  if options[:kerning] 
    kern(text)         
  else     
   unicode_codepoints = text.unpack("U*")
    glyph_codes = unicode_codepoints.map { |u| 
      enc_table.get_glyph_id_for_unicode(u)
    }
    text = glyph_codes.pack("n*")
  end
end

#descenderObject



349
350
351
# File 'lib/prawn/font/metrics.rb', line 349

def descender
  Integer(@ttf.get_table(:hhea).descender * scale_factor)
end

#enc_tableObject



367
368
369
370
371
# File 'lib/prawn/font/metrics.rb', line 367

def enc_table
  @enc_table ||= @ttf.get_table(:cmap).encoding_tables.find do |t|
    t.class == ::Font::TTF::Table::Cmap::EncodingTable4
  end
end

#glyph_widthsObject



322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
# File 'lib/prawn/font/metrics.rb', line 322

def glyph_widths
  glyphs = cmap.values.uniq.sort
  first_glyph = glyphs.shift
  widths = [first_glyph, [Integer(hmtx[first_glyph][0] * scale_factor)]]
  prev_glyph = first_glyph
  glyphs.each do |glyph|
    unless glyph == prev_glyph + 1
      widths << glyph
      widths << []
    end
    widths.last << Integer(hmtx[glyph][0] * scale_factor )
    prev_glyph = glyph
  end
  widths
end

#has_kerning_data?Boolean

Returns:

  • (Boolean)


403
404
405
# File 'lib/prawn/font/metrics.rb', line 403

def has_kerning_data?
  @has_kerning_data 
end

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

TODO: NASTY.



286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
# File 'lib/prawn/font/metrics.rb', line 286

def kern(string,options={})   
  a = []
  
  string.unpack("U*").each do |r|
    if a.last.is_a? Array
      if kern = kern_pairs_table[[cmap[a.last.last], cmap[r]]] 
        kern *= scale_factor
        a << kern << [r]
      else
        a.last << r
      end
    else
      a << [r]
    end
    a
  end
  
  a.map { |r| 
    if options[:skip_conversion]
      r.is_a?(Array) ? r.pack("U*") : r
    else
      i = r.is_a?(Array) ? r.pack("U*") : r 
      x = if i.is_a?(String)
        unicode_codepoints = i.unpack("U*")
        glyph_codes = unicode_codepoints.map { |u| 
          enc_table.get_glyph_id_for_unicode(u)
        }
        glyph_codes.pack("n*")
      else
        i
      end
      x.is_a?(Numeric) ? -x : x 
    end
  }
end

#kern_pairs_tableObject



386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
# File 'lib/prawn/font/metrics.rb', line 386

def kern_pairs_table
  return @kern_pairs_table if @kern_pairs_table
  
  table = @ttf.get_table(:kern).subtables.find { |s| 
    s.is_a? ::Font::TTF::Table::Kern::KerningSubtable0 }
  
  if table
    @kern_pairs_table = table.kerning_pairs.inject({}) do |h,p|
      h[[p.left, p.right]] = p.value; h
    end
  else
    @kern_pairs_table = {}
  end               
rescue ::Font::TTF::TableMissing
  @kern_pairs_table = {}
end

#line_gapObject



353
354
355
# File 'lib/prawn/font/metrics.rb', line 353

def line_gap
  Integer(@ttf.get_table(:hhea).line_gap * scale_factor)   
end

#string_width(string, font_size, options = {}) ⇒ Object



268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
# File 'lib/prawn/font/metrics.rb', line 268

def string_width(string, font_size, options = {})
  scale = font_size / 1000.0
  if options[:kerning]
    kern(string,:skip_conversion => true).inject(0) do |s,r|
      if r.is_a? String  
        s + string_width(r, font_size, :kerning => false)
      else 
        s + r * scale
      end
    end
  else
    string.unpack("U*").inject(0) do |s,r|
      s + character_width_by_code(r)
    end * scale
  end
end

#to_unicode_cmapObject

TODO: instead of creating a map that contains every glyph in the font,

only include the glyphs that were used


375
376
377
378
379
380
381
382
383
384
# File 'lib/prawn/font/metrics.rb', line 375

def to_unicode_cmap
  return @to_unicode if @to_unicode
  @to_unicode = Prawn::Font::CMap.new
  unicode_for_glyph = cmap.invert
  glyphs = unicode_for_glyph.keys.uniq.sort
  glyphs.each do |glyph|
    @to_unicode[unicode_for_glyph[glyph]] = glyph
  end
  @to_unicode
end

#type0?Boolean

Returns:

  • (Boolean)


407
408
409
# File 'lib/prawn/font/metrics.rb', line 407

def type0?
  true
end