giga-fast-kit 0.0.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (75) hide show
  1. checksums.yaml +7 -0
  2. data/giga-fast-kit.gemspec +12 -0
  3. data/prawn-2.5.0/COPYING +2 -0
  4. data/prawn-2.5.0/GPLv2 +339 -0
  5. data/prawn-2.5.0/GPLv3 +674 -0
  6. data/prawn-2.5.0/LICENSE +56 -0
  7. data/prawn-2.5.0/data/fonts/Courier-Bold.afm +342 -0
  8. data/prawn-2.5.0/data/fonts/Courier-BoldOblique.afm +342 -0
  9. data/prawn-2.5.0/data/fonts/Courier-Oblique.afm +342 -0
  10. data/prawn-2.5.0/data/fonts/Courier.afm +342 -0
  11. data/prawn-2.5.0/data/fonts/Helvetica-Bold.afm +2827 -0
  12. data/prawn-2.5.0/data/fonts/Helvetica-BoldOblique.afm +2827 -0
  13. data/prawn-2.5.0/data/fonts/Helvetica-Oblique.afm +3051 -0
  14. data/prawn-2.5.0/data/fonts/Helvetica.afm +3051 -0
  15. data/prawn-2.5.0/data/fonts/MustRead.html +19 -0
  16. data/prawn-2.5.0/data/fonts/Symbol.afm +213 -0
  17. data/prawn-2.5.0/data/fonts/Times-Bold.afm +2588 -0
  18. data/prawn-2.5.0/data/fonts/Times-BoldItalic.afm +2384 -0
  19. data/prawn-2.5.0/data/fonts/Times-Italic.afm +2667 -0
  20. data/prawn-2.5.0/data/fonts/Times-Roman.afm +2419 -0
  21. data/prawn-2.5.0/data/fonts/ZapfDingbats.afm +225 -0
  22. data/prawn-2.5.0/lib/prawn/document/bounding_box.rb +625 -0
  23. data/prawn-2.5.0/lib/prawn/document/column_box.rb +177 -0
  24. data/prawn-2.5.0/lib/prawn/document/internals.rb +76 -0
  25. data/prawn-2.5.0/lib/prawn/document/span.rb +65 -0
  26. data/prawn-2.5.0/lib/prawn/document.rb +846 -0
  27. data/prawn-2.5.0/lib/prawn/encoding.rb +85 -0
  28. data/prawn-2.5.0/lib/prawn/errors.rb +73 -0
  29. data/prawn-2.5.0/lib/prawn/font.rb +567 -0
  30. data/prawn-2.5.0/lib/prawn/font_metric_cache.rb +50 -0
  31. data/prawn-2.5.0/lib/prawn/fonts/afm.rb +332 -0
  32. data/prawn-2.5.0/lib/prawn/fonts/dfont.rb +42 -0
  33. data/prawn-2.5.0/lib/prawn/fonts/otf.rb +14 -0
  34. data/prawn-2.5.0/lib/prawn/fonts/to_unicode_cmap.rb +151 -0
  35. data/prawn-2.5.0/lib/prawn/fonts/ttc.rb +41 -0
  36. data/prawn-2.5.0/lib/prawn/fonts/ttf.rb +615 -0
  37. data/prawn-2.5.0/lib/prawn/fonts.rb +14 -0
  38. data/prawn-2.5.0/lib/prawn/graphics/blend_mode.rb +62 -0
  39. data/prawn-2.5.0/lib/prawn/graphics/cap_style.rb +44 -0
  40. data/prawn-2.5.0/lib/prawn/graphics/color.rb +257 -0
  41. data/prawn-2.5.0/lib/prawn/graphics/dash.rb +123 -0
  42. data/prawn-2.5.0/lib/prawn/graphics/join_style.rb +60 -0
  43. data/prawn-2.5.0/lib/prawn/graphics/patterns.rb +389 -0
  44. data/prawn-2.5.0/lib/prawn/graphics/transformation.rb +172 -0
  45. data/prawn-2.5.0/lib/prawn/graphics/transparency.rb +79 -0
  46. data/prawn-2.5.0/lib/prawn/graphics.rb +791 -0
  47. data/prawn-2.5.0/lib/prawn/grid.rb +449 -0
  48. data/prawn-2.5.0/lib/prawn/image_handler.rb +61 -0
  49. data/prawn-2.5.0/lib/prawn/images/image.rb +48 -0
  50. data/prawn-2.5.0/lib/prawn/images/jpg.rb +121 -0
  51. data/prawn-2.5.0/lib/prawn/images/png.rb +383 -0
  52. data/prawn-2.5.0/lib/prawn/images.rb +195 -0
  53. data/prawn-2.5.0/lib/prawn/measurement_extensions.rb +82 -0
  54. data/prawn-2.5.0/lib/prawn/measurements.rb +129 -0
  55. data/prawn-2.5.0/lib/prawn/outline.rb +316 -0
  56. data/prawn-2.5.0/lib/prawn/repeater.rb +140 -0
  57. data/prawn-2.5.0/lib/prawn/security/arcfour.rb +54 -0
  58. data/prawn-2.5.0/lib/prawn/security.rb +308 -0
  59. data/prawn-2.5.0/lib/prawn/soft_mask.rb +105 -0
  60. data/prawn-2.5.0/lib/prawn/stamp.rb +147 -0
  61. data/prawn-2.5.0/lib/prawn/text/box.rb +192 -0
  62. data/prawn-2.5.0/lib/prawn/text/formatted/arranger.rb +396 -0
  63. data/prawn-2.5.0/lib/prawn/text/formatted/box.rb +725 -0
  64. data/prawn-2.5.0/lib/prawn/text/formatted/fragment.rb +373 -0
  65. data/prawn-2.5.0/lib/prawn/text/formatted/line_wrap.rb +335 -0
  66. data/prawn-2.5.0/lib/prawn/text/formatted/parser.rb +284 -0
  67. data/prawn-2.5.0/lib/prawn/text/formatted/wrap.rb +166 -0
  68. data/prawn-2.5.0/lib/prawn/text/formatted.rb +82 -0
  69. data/prawn-2.5.0/lib/prawn/text.rb +701 -0
  70. data/prawn-2.5.0/lib/prawn/transformation_stack.rb +63 -0
  71. data/prawn-2.5.0/lib/prawn/utilities.rb +34 -0
  72. data/prawn-2.5.0/lib/prawn/version.rb +6 -0
  73. data/prawn-2.5.0/lib/prawn/view.rb +116 -0
  74. data/prawn-2.5.0/lib/prawn.rb +83 -0
  75. metadata +114 -0
@@ -0,0 +1,192 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative 'formatted/box'
4
+
5
+ module Prawn
6
+ module Text # rubocop: disable Style/Documentation
7
+ # @group Stable API
8
+
9
+ # Draws the requested text into a box.
10
+ #
11
+ # When the text overflows the rectangle, you shrink to fit, or truncate the
12
+ # text. Text boxes are independent of the document y position.
13
+ #
14
+ # #### Encoding
15
+ #
16
+ # Note that strings passed to this function should be encoded as UTF-8. If
17
+ # you get unexpected characters appearing in your rendered document, check
18
+ # this.
19
+ #
20
+ # If the current font is a built-in one, although the string must be encoded
21
+ # as UTF-8, only characters that are available in WinAnsi are allowed.
22
+ #
23
+ # If an empty box is rendered to your PDF instead of the character you
24
+ # wanted it usually means the current font doesn't include that character.
25
+ #
26
+ # @param string [String]
27
+ # @param options [Hash{Symbol => any}]
28
+ # @option options :kerning [Boolean] (value of document.default_kerning?)
29
+ # Whether or not to use kerning (if it is available with the current
30
+ # font).
31
+ # @option options :size [Number] (current font size)
32
+ # The font size to use.
33
+ # @option options :character_spacing [Number] (0)
34
+ # The amount of space to add to or remove from the default character
35
+ # spacing.
36
+ # @option options :disable_wrap_by_char [Boolean] (false)
37
+ # Whether or not to prevent mid-word breaks when text does not fit in box.
38
+ # @option options :mode [Symbol] (:fill)
39
+ # The text rendering mode. See documentation for
40
+ # {Prawn::Document#text_rendering_mode} for a list of valid options.
41
+ # @option option :style [Symbol] (current style)
42
+ # The style to use. The requested style must be part of the current font
43
+ # family.
44
+ # @option option :at [Array(Number, Number)] (bounds top left corner)
45
+ # The upper left corner of the box.
46
+ # @option options :width [Number] (bounds.right - at[0])
47
+ # The width of the box.
48
+ # @option options :height [Number] (default_height())
49
+ # The height of the box.
50
+ # @option options :direction [:ltr, :rtl] (value of document.text_direction)
51
+ # Direction of the text (left-to-right or right-to-left).
52
+ # @option options :fallback_fonts [Array<String>]
53
+ # An array of font names. Each name must be the name of an AFM font or the
54
+ # name that was used to register a family of external fonts (see
55
+ # {Prawn::Document#font_families}). If present, then each glyph will be
56
+ # rendered using the first font that includes the glyph, starting with the
57
+ # current font and then moving through `:fallback_fonts`.
58
+ # @option options :align [:left, :center, :right, :justify]
59
+ # (:left if direction is :ltr, :right if direction is :rtl)
60
+ # Alignment within the bounding box.
61
+ # @option options :valign [:top, :center, :bottom] (:top)
62
+ # Vertical alignment within the bounding box.
63
+ # @option options :rotate [Number]
64
+ # The angle to rotate the text.
65
+ # @option options :rotate_around
66
+ # [:center, :upper_left, :upper_right, :lower_right, :lower_left]
67
+ # (:upper_left)
68
+ # The point around which to rotate the text.
69
+ # @option options :leading [Number] (value of document.default_leading)
70
+ # Additional space between lines.
71
+ # @option options :single_line [Boolean] (false)
72
+ # If true, then only the first line will be drawn.
73
+ # @option options :overflow [:truncate, :shrink_to_fit, :expand] (:truncate)
74
+ # This controls the behavior when the amount of text exceeds the available
75
+ # space.
76
+ # @option options :min_font_size [Number] (5)
77
+ # The minimum font size to use when `:overflow` is set to `:shrink_to_fit`
78
+ # (that is the font size will not be reduced to less than this value, even
79
+ # if it means that some text will be cut off).
80
+ # @return [String] Any text that did not print under the current settings.
81
+ # @raise [Prawn::Errors::CannotFit]
82
+ # If not wide enough to print any text.
83
+ def text_box(string, options = {})
84
+ options = options.dup
85
+ options[:document] = self
86
+
87
+ box =
88
+ if options[:inline_format]
89
+ p = options.delete(:inline_format)
90
+ p = [] unless p.is_a?(Array)
91
+ array = text_formatter.format(string, *p)
92
+ Text::Formatted::Box.new(array, options)
93
+ else
94
+ Text::Box.new(string, options)
95
+ end
96
+
97
+ box.render
98
+ end
99
+
100
+ # @group Experimental API
101
+
102
+ # Text box.
103
+ #
104
+ # Generally, one would use the {Prawn::Text#text_box} convenience method.
105
+ # However, using {Prawn::Text::Box#initialize Box.new} in conjunction with
106
+ # `render(dry_run: true)` enables one to do calculations prior to placing
107
+ # text on the page, or to determine how much vertical space was consumed by
108
+ # the printed text.
109
+ class Box < Prawn::Text::Formatted::Box
110
+ # @param string [String]
111
+ # @param options [Hash{Symbol => any}]
112
+ # @option options :document [Prawn::Document] Owning document.
113
+ # @option options :kerning [Boolean] (value of document.default_kerning?)
114
+ # Whether or not to use kerning (if it is available with the current
115
+ # font).
116
+ # @option options :size [Number] (current font size)
117
+ # The font size to use.
118
+ # @option options :character_spacing [Number] (0)
119
+ # The amount of space to add to or remove from the default character
120
+ # spacing.
121
+ # @option options :disable_wrap_by_char [Boolean] (false)
122
+ # Whether or not to prevent mid-word breaks when text does not fit in box.
123
+ # @option options :mode [Symbol] (:fill)
124
+ # The text rendering mode. See documentation for
125
+ # {Prawn::Document#text_rendering_mode} for a list of valid options.
126
+ # @option option :style [Symbol] (current style)
127
+ # The style to use. The requested style must be part of the current font
128
+ # family.
129
+ # @option option :at [Array(Number, Number)] (bounds top left corner)
130
+ # The upper left corner of the box.
131
+ # @option options :width [Number] (bounds.right - at[0])
132
+ # The width of the box.
133
+ # @option options :height [Number] (default_height())
134
+ # The height of the box.
135
+ # @option options :direction [:ltr, :rtl] (value of document.text_direction)
136
+ # Direction of the text (left-to-right or right-to-left).
137
+ # @option options :fallback_fonts [Array<String>]
138
+ # An array of font names. Each name must be the name of an AFM font or the
139
+ # name that was used to register a family of external fonts (see
140
+ # {Prawn::Document#font_families}). If present, then each glyph will be
141
+ # rendered using the first font that includes the glyph, starting with the
142
+ # current font and then moving through `:fallback_fonts`.
143
+ # @option options :align [:left, :center, :right, :justify]
144
+ # (:left if direction is :ltr, :right if direction is :rtl)
145
+ # Alignment within the bounding box.
146
+ # @option options :valign [:top, :center, :bottom] (:top)
147
+ # Vertical alignment within the bounding box.
148
+ # @option options :rotate [Number]
149
+ # The angle to rotate the text.
150
+ # @option options :rotate_around
151
+ # [:center, :upper_left, :upper_right, :lower_right, :lower_left]
152
+ # (:upper_left)
153
+ # The point around which to rotate the text.
154
+ # @option options :leading [Number] (value of document.default_leading)
155
+ # Additional space between lines.
156
+ # @option options :single_line [Boolean] (false)
157
+ # If true, then only the first line will be drawn.
158
+ # @option options :overflow [:truncate, :shrink_to_fit, :expand] (:truncate)
159
+ # This controls the behavior when the amount of text exceeds the available
160
+ # space.
161
+ # @option options :min_font_size [Number] (5)
162
+ # The minimum font size to use when `:overflow` is set to `:shrink_to_fit`
163
+ # (that is the font size will not be reduced to less than this value, even
164
+ # if it means that some text will be cut off).
165
+ def initialize(string, options = {})
166
+ super([{ text: string }], options)
167
+ end
168
+
169
+ # Render text to the document based on the settings defined in
170
+ # constructor.
171
+ #
172
+ # In order to facilitate look-ahead calculations, this method accepts
173
+ # a `dry_run: true` option. If provided, then everything is executed as if
174
+ # rendering, with the exception that nothing is drawn on the page. Useful
175
+ # for look-ahead computations of height, unprinted text, etc.
176
+ #
177
+ # @param flags [Hash{Symbol => any}]
178
+ # @option flags :dry_run [Boolean] (false)
179
+ # Do not draw the text. Everything else is done.
180
+ # @return [String]
181
+ # Any text that did not print under the current settings.
182
+ # @raise [Prawn::Text::Formatted::Arranger::BadFontFamily]
183
+ # If no font family is defined for the current font.
184
+ # @raise [Prawn::Errors::CannotFit]
185
+ # If not wide enough to print any text.
186
+ def render(flags = {})
187
+ leftover = super(flags)
188
+ leftover.map { |hash| hash[:text] }.join
189
+ end
190
+ end
191
+ end
192
+ end
@@ -0,0 +1,396 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Prawn
4
+ module Text
5
+ module Formatted
6
+ # D data structure for 2-stage processing of lines of formatted text.
7
+ # @private
8
+ class Arranger
9
+ # You're getting this because you're trying to get some information from
10
+ # the arranger before it finished processing text.
11
+ class NotFinalized < StandardError
12
+ # @private
13
+ DEFAULT_MESSAGE = 'Lines must be finalized'
14
+
15
+ # @private
16
+ MESSAGE_WITH_METHOD = 'Lines must be finalized before calling #%<method>s'
17
+
18
+ def initialize(message = DEFAULT_MESSAGE, method: nil)
19
+ if method && message == DEFAULT_MESSAGE
20
+ super(format(MESSAGE_WITH_METHOD, method: method))
21
+ else
22
+ super(message)
23
+ end
24
+ end
25
+ end
26
+
27
+ # You're getting this because a font doesn't have a family name.
28
+ class BadFontFamily < StandardError
29
+ def initialize(message = 'Bad font family')
30
+ super
31
+ end
32
+ end
33
+
34
+ attr_reader :max_line_height
35
+ attr_reader :max_descender
36
+ attr_reader :max_ascender
37
+ attr_reader :finalized
38
+ attr_accessor :consumed
39
+
40
+ # The following present only for testing purposes
41
+ attr_reader :unconsumed
42
+ attr_reader :fragments
43
+ attr_reader :current_format_state
44
+
45
+ def initialize(document, options = {})
46
+ @document = document
47
+ @fragments = []
48
+ @unconsumed = []
49
+ @kerning = options[:kerning]
50
+ end
51
+
52
+ # Number of spaces in the text.
53
+ #
54
+ # @return [Integer]
55
+ # @raise [NotFinalized]
56
+ def space_count
57
+ unless finalized
58
+ raise NotFinalized.new(method: 'space_count')
59
+ end
60
+
61
+ @fragments.reduce(0) do |sum, fragment|
62
+ sum + fragment.space_count
63
+ end
64
+ end
65
+
66
+ # Line width.
67
+ #
68
+ # @return [Number]
69
+ # @raise [NotFinalized]
70
+ def line_width
71
+ unless finalized
72
+ raise raise NotFinalized.new(method: 'line_width')
73
+ end
74
+
75
+ @fragments.reduce(0) do |sum, fragment|
76
+ sum + fragment.width
77
+ end
78
+ end
79
+
80
+ # Line text.
81
+ #
82
+ # @return [String]
83
+ # @raise [NotFinalized]
84
+ def line
85
+ unless finalized
86
+ raise NotFinalized.new(method: 'line')
87
+ end
88
+
89
+ @fragments.map { |fragment|
90
+ begin
91
+ fragment.text.dup.encode(::Encoding::UTF_8)
92
+ rescue ::Encoding::InvalidByteSequenceError, ::Encoding::UndefinedConversionError
93
+ fragment.text.dup.force_encoding(::Encoding::UTF_8)
94
+ end
95
+ }.join
96
+ end
97
+
98
+ # Finish laying out current line.
99
+ #
100
+ # @return [void]
101
+ def finalize_line
102
+ @finalized = true
103
+
104
+ omit_trailing_whitespace_from_line_width
105
+ @fragments = []
106
+ @consumed.each do |hash|
107
+ text = hash[:text]
108
+ format_state = hash.dup
109
+ format_state.delete(:text)
110
+ fragment = Prawn::Text::Formatted::Fragment.new(
111
+ text,
112
+ format_state,
113
+ @document,
114
+ )
115
+ @fragments << fragment
116
+ self.fragment_measurements = fragment
117
+ self.line_measurement_maximums = fragment
118
+ end
119
+ end
120
+
121
+ # Set new fragment array.
122
+ #
123
+ # @param array [Array<Hash>]
124
+ # @return [void]
125
+ def format_array=(array)
126
+ initialize_line
127
+ @unconsumed = []
128
+ array.each do |hash|
129
+ hash[:text].scan(/[^\n]+|\n/) do |line|
130
+ @unconsumed << hash.merge(text: line)
131
+ end
132
+ end
133
+ end
134
+
135
+ # Prepare for new line layout.
136
+ #
137
+ # @return [void]
138
+ def initialize_line
139
+ @finalized = false
140
+ @max_line_height = 0
141
+ @max_descender = 0
142
+ @max_ascender = 0
143
+
144
+ @consumed = []
145
+ @fragments = []
146
+ end
147
+
148
+ # Were all fragments processed?
149
+ #
150
+ # @return [Boolean]
151
+ def finished?
152
+ @unconsumed.empty?
153
+ end
154
+
155
+ # Get the next unprocessed string.
156
+ #
157
+ # @return [String, nil]
158
+ # @raise [NotFinalized]
159
+ def next_string
160
+ if finalized
161
+ raise NotFinalized.new(method: 'next_string')
162
+ end
163
+
164
+ next_unconsumed_hash = @unconsumed.shift
165
+
166
+ if next_unconsumed_hash
167
+ @consumed << next_unconsumed_hash.dup
168
+ @current_format_state = next_unconsumed_hash.dup
169
+ @current_format_state.delete(:text)
170
+
171
+ next_unconsumed_hash[:text]
172
+ end
173
+ end
174
+
175
+ # Get the next unprocessed string keeping it in the queue.
176
+ #
177
+ # @return [String, nil]
178
+ def preview_next_string
179
+ next_unconsumed_hash = @unconsumed.first
180
+
181
+ if next_unconsumed_hash
182
+ next_unconsumed_hash[:text]
183
+ end
184
+ end
185
+
186
+ # Apply color and font settings.
187
+ #
188
+ # @param fragment [Prawn::Text::Formatted::Fragment]
189
+ # @yield
190
+ # @return [void]
191
+ def apply_color_and_font_settings(fragment, &block)
192
+ if fragment.color
193
+ original_fill_color = @document.fill_color
194
+ original_stroke_color = @document.stroke_color
195
+ @document.fill_color(*fragment.color)
196
+ @document.stroke_color(*fragment.color)
197
+ apply_font_settings(fragment, &block)
198
+ @document.stroke_color = original_stroke_color
199
+ @document.fill_color = original_fill_color
200
+ else
201
+ apply_font_settings(fragment, &block)
202
+ end
203
+ end
204
+
205
+ # Apply font settings.
206
+ #
207
+ # @param fragment [Prawn::Text::Formatted::Fragment]
208
+ # @yield
209
+ # @return [void]
210
+ def apply_font_settings(fragment = nil, &block)
211
+ if fragment.nil?
212
+ font = current_format_state[:font]
213
+ size = current_format_state[:size]
214
+ character_spacing = current_format_state[:character_spacing] ||
215
+ @document.character_spacing
216
+ styles = current_format_state[:styles]
217
+ else
218
+ font = fragment.font
219
+ size = fragment.size
220
+ character_spacing = fragment.character_spacing
221
+ styles = fragment.styles
222
+ end
223
+ font_style = font_style(styles)
224
+
225
+ @document.character_spacing(character_spacing) do
226
+ if font || font_style != :normal
227
+ raise BadFontFamily unless @document.font.family
228
+
229
+ @document.font(
230
+ font || @document.font.family, style: font_style,
231
+ ) do
232
+ apply_font_size(size, styles, &block)
233
+ end
234
+ else
235
+ apply_font_size(size, styles, &block)
236
+ end
237
+ end
238
+ end
239
+
240
+ # Update last fragment's text.
241
+ #
242
+ # @param printed [String]
243
+ # @param unprinted [String]
244
+ # @param normalized_soft_hyphen [Boolean]
245
+ # @return [void]
246
+ def update_last_string(printed, unprinted, normalized_soft_hyphen = nil)
247
+ return if printed.nil?
248
+
249
+ if printed.empty?
250
+ @consumed.pop
251
+ else
252
+ @consumed.last[:text] = printed
253
+ if normalized_soft_hyphen
254
+ @consumed.last[:normalized_soft_hyphen] = normalized_soft_hyphen
255
+ end
256
+ end
257
+
258
+ unless unprinted.empty?
259
+ @unconsumed.unshift(@current_format_state.merge(text: unprinted))
260
+ end
261
+
262
+ load_previous_format_state if printed.empty?
263
+ end
264
+
265
+ # Get the next fragment.
266
+ #
267
+ # @return [Prawn::Text::Formatted::Fragment]
268
+ # @raise [NotFinalized]
269
+ def retrieve_fragment
270
+ unless finalized
271
+ raise NotFinalized, 'Lines must be finalized before fragments can be retrieved'
272
+ end
273
+
274
+ @fragments.shift
275
+ end
276
+
277
+ # Repack remaining fragments.
278
+ #
279
+ # @return [void]
280
+ def repack_unretrieved
281
+ new_unconsumed = []
282
+ # rubocop: disable Lint/AssignmentInCondition
283
+ while fragment = retrieve_fragment
284
+ # rubocop: enable Lint/AssignmentInCondition
285
+ fragment.include_trailing_white_space!
286
+ new_unconsumed << fragment.format_state.merge(text: fragment.text)
287
+ end
288
+ @unconsumed = new_unconsumed.concat(@unconsumed)
289
+ end
290
+
291
+ # Get font variant from fragment styles.
292
+ #
293
+ # @param styles [Array<Symbol>]
294
+ # @return [Symbol]
295
+ def font_style(styles)
296
+ styles = Array(styles)
297
+ if styles.include?(:bold) && styles.include?(:italic)
298
+ :bold_italic
299
+ elsif styles.include?(:bold)
300
+ :bold
301
+ elsif styles.include?(:italic)
302
+ :italic
303
+ else
304
+ :normal
305
+ end
306
+ end
307
+
308
+ private
309
+
310
+ def load_previous_format_state
311
+ if @consumed.empty?
312
+ @current_format_state = {}
313
+ else
314
+ hash = @consumed.last
315
+ @current_format_state = hash.dup
316
+ @current_format_state.delete(:text)
317
+ end
318
+ end
319
+
320
+ def apply_font_size(size, styles, &block)
321
+ if subscript?(styles) || superscript?(styles)
322
+ relative_size = 0.583
323
+ size =
324
+ if size.nil?
325
+ @document.font_size * relative_size
326
+ else
327
+ size * relative_size
328
+ end
329
+ end
330
+ if size.nil?
331
+ yield
332
+ else
333
+ @document.font_size(size, &block)
334
+ end
335
+ end
336
+
337
+ def subscript?(styles)
338
+ if styles.nil? then false
339
+ else
340
+ styles.include?(:subscript)
341
+ end
342
+ end
343
+
344
+ def superscript?(styles)
345
+ if styles.nil? then false
346
+ else
347
+ styles.include?(:superscript)
348
+ end
349
+ end
350
+
351
+ def omit_trailing_whitespace_from_line_width
352
+ @consumed.reverse_each do |hash|
353
+ if hash[:text] == "\n"
354
+ break
355
+ elsif hash[:text].strip.empty? && @consumed.length > 1
356
+ # this entire fragment is trailing white space
357
+ hash[:exclude_trailing_white_space] = true
358
+ else
359
+ # this fragment contains the first non-white space we have
360
+ # encountered since the end of the line
361
+ hash[:exclude_trailing_white_space] = true
362
+ break
363
+ end
364
+ end
365
+ end
366
+
367
+ def fragment_measurements=(fragment)
368
+ apply_font_settings(fragment) do
369
+ fragment.width = @document.width_of(
370
+ fragment.text,
371
+ kerning: @kerning,
372
+ )
373
+ fragment.line_height = @document.font.height
374
+ fragment.descender = @document.font.descender
375
+ fragment.ascender = @document.font.ascender
376
+ end
377
+ end
378
+
379
+ def line_measurement_maximums=(fragment)
380
+ @max_line_height = [
381
+ defined?(@max_line_height) && @max_line_height,
382
+ fragment.line_height,
383
+ ].compact.max
384
+ @max_descender = [
385
+ defined?(@max_descender) && @max_descender,
386
+ fragment.descender,
387
+ ].compact.max
388
+ @max_ascender = [
389
+ defined?(@max_ascender) && @max_ascender,
390
+ fragment.ascender,
391
+ ].compact.max
392
+ end
393
+ end
394
+ end
395
+ end
396
+ end