Permalink
Browse files

Merge branch 'more_performance_work' of git://github.com/alexdowad/prawn

  • Loading branch information...
bradediger committed Aug 23, 2012
2 parents 121dba0 + ad37380 commit 6680efc54d771052e0f8e4364948d1e538cdbeaa
Showing with 51 additions and 31 deletions.
  1. +19 −7 lib/prawn/core/text/formatted/line_wrap.rb
  2. +4 −2 lib/prawn/font/afm.rb
  3. +28 −22 lib/prawn/text/formatted/fragment.rb
@@ -71,6 +71,9 @@ def is_next_string_newline?
def apply_font_settings_and_add_fragment_to_line(fragment)
result = nil
@arranger.apply_font_settings do
+ # if font has changed from Unicode to non-Unicode, or vice versa, the characters used for soft hyphens
+ # and zero-width spaces will be different
+ set_soft_hyphen_and_zero_width_space
result = add_fragment_to_line(fragment)
end
result
@@ -141,11 +144,11 @@ def hyphen
end
def soft_hyphen
- @document.font.normalize_encoding(Prawn::Text::SHY)
+ @soft_hyphen
end
def zero_width_space
- @document.font.unicode? ? Prawn::Text::ZWSP : ""
+ @zero_width_space
end
def line_empty?
@@ -168,6 +171,14 @@ def initialize_line(options)
@line_full = false
end
+ def set_soft_hyphen_and_zero_width_space
+ # this is done once per fragment, after the font settings for the fragment are applied --
+ # it could actually be skipped if the font hasn't changed
+ font = @document.font
+ @soft_hyphen = font.normalize_encoding(Prawn::Text::SHY)
+ @zero_width_space = font.unicode? ? Prawn::Text::ZWSP : ""
+ end
+
def fragment_finished(fragment)
if fragment == "\n"
@newline_encountered = true
@@ -234,20 +245,21 @@ def wrap_by_char(segment)
# this conditional is only necessary for Ruby 1.8 compatibility
# String#unicode_characters is a helper which iterates over UTF-8 characters
# under Ruby 1.9, it is implemented simply by aliasing #each_char
- if @document.font.unicode?
+ font = @document.font
+ if font.unicode?
segment.unicode_characters do |char|
- break unless append_char(char)
+ break unless append_char(char,font)
end
else
segment.each_char do |char|
- break unless append_char(char)
+ break unless append_char(char,font)
end
end
end
- def append_char(char)
+ def append_char(char,font)
# kerning doesn't make sense in the context of a single character
- char_width = @document.width_of(char)
+ char_width = font.compute_width_of(char)
if @accumulated_width + char_width <= @width
@accumulated_width += char_width
View
@@ -41,6 +41,8 @@ def initialize(document, name, options={}) #:nodoc:
super
+ @@winansi ||= Prawn::Encoding::WinAnsi.new
+
@attributes = {}
@glyph_widths = {}
@bounding_boxes = {}
@@ -86,8 +88,8 @@ def has_kerning_data?
# string. Changes the encoding in-place, so the argument itself
# is replaced with a string in WinAnsi encoding.
#
- def normalize_encoding(text)
- enc = Prawn::Encoding::WinAnsi.new
+ def normalize_encoding(text)
+ enc = @@winansi
text.unpack("U*").collect { |i| enc[i] }.pack("C*")
rescue ArgumentError
raise Prawn::Errors::IncompatibleStringEncoding,
@@ -15,34 +15,20 @@ module Formatted
#
class Fragment
- attr_reader :format_state
+ attr_reader :format_state, :text
attr_writer :width
attr_accessor :line_height, :descender, :ascender
attr_accessor :word_spacing, :left, :baseline
def initialize(text, format_state, document)
- @text = text
@format_state = format_state
@document = document
@word_spacing = 0
- end
- def text
- string = strip_zero_width_spaces(@text)
- if exclude_trailing_white_space?
- string = string.rstrip
- string = process_soft_hyphens(string)
- end
- case direction
- when :rtl
- if ruby_18 { true }
- string.scan(/./mu).reverse.join
- else
- string.reverse
- end
- else
- string
- end
+ # keep the original value of "text", so we can reinitialize @text if formatting parameters
+ # like text direction are changed
+ @original_text = text
+ @text = process_text(@original_text)
end
def width
@@ -127,16 +113,19 @@ def direction
end
def default_direction=(direction)
- @format_state[:direction] = direction unless @format_state[:direction]
+ unless @format_state[:direction]
+ @format_state[:direction] = direction
+ @text = process_text(@original_text)
+ end
end
def include_trailing_white_space!
@format_state.delete(:exclude_trailing_white_space)
+ @text = process_text(@original_text)
end
def space_count
- string = exclude_trailing_white_space? ? @text.rstrip : @text
- string.count(" ")
+ @text.count(" ")
end
def callback_objects
@@ -212,6 +201,23 @@ def absolute_bottom_right
private
+ def process_text(text)
+ string = strip_zero_width_spaces(text)
+ if exclude_trailing_white_space?
+ string = process_soft_hyphens(string.rstrip)
+ end
+ case direction
+ when :rtl
+ if ruby_18 { true }
+ string.scan(/./mu).reverse.join
+ else
+ string.reverse
+ end
+ else
+ string
+ end
+ end
+
def exclude_trailing_white_space?
@format_state[:exclude_trailing_white_space]
end

0 comments on commit 6680efc

Please sign in to comment.