prawn 0.13.0 → 2.4.0
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.
- checksums.yaml +5 -5
- checksums.yaml.gz.sig +0 -0
- data/.yardopts +10 -0
- data/GPLv2 +20 -21
- data/Gemfile +3 -16
- data/Rakefile +17 -39
- data/lib/prawn/document/bounding_box.rb +85 -42
- data/lib/prawn/document/column_box.rb +21 -11
- data/lib/prawn/document/internals.rb +40 -147
- data/lib/prawn/document/span.rb +25 -17
- data/lib/prawn/document.rb +286 -245
- data/lib/prawn/encoding.rb +68 -101
- data/lib/prawn/errors.rb +47 -43
- data/lib/prawn/font.rb +204 -155
- data/lib/prawn/font_metric_cache.rb +25 -21
- data/lib/prawn/fonts/afm.rb +292 -0
- data/lib/prawn/{font → fonts}/dfont.rb +7 -13
- data/lib/prawn/fonts/otf.rb +11 -0
- data/lib/prawn/fonts/ttc.rb +36 -0
- data/lib/prawn/{font → fonts}/ttf.rb +142 -80
- data/lib/prawn/graphics/blend_mode.rb +65 -0
- data/lib/prawn/graphics/cap_style.rb +6 -5
- data/lib/prawn/graphics/color.rb +47 -44
- data/lib/prawn/graphics/dash.rb +30 -13
- data/lib/prawn/graphics/join_style.rb +13 -6
- data/lib/prawn/graphics/patterns.rb +221 -90
- data/lib/prawn/graphics/transformation.rb +21 -12
- data/lib/prawn/graphics/transparency.rb +21 -17
- data/lib/prawn/graphics.rb +155 -128
- data/lib/prawn/{layout/grid.rb → grid.rb} +110 -47
- data/lib/prawn/image_handler.rb +16 -2
- data/lib/prawn/images/image.rb +4 -2
- data/lib/prawn/images/jpg.rb +39 -30
- data/lib/prawn/images/png.rb +132 -169
- data/lib/prawn/images.rb +70 -62
- data/lib/prawn/measurement_extensions.rb +15 -10
- data/lib/prawn/measurements.rb +22 -23
- data/lib/prawn/outline.rb +301 -13
- data/lib/prawn/repeater.rb +19 -17
- data/lib/prawn/security/arcfour.rb +54 -0
- data/lib/prawn/security.rb +108 -86
- data/lib/prawn/soft_mask.rb +40 -41
- data/lib/prawn/stamp.rb +29 -12
- data/lib/prawn/text/box.rb +27 -29
- data/lib/prawn/text/formatted/arranger.rb +110 -67
- data/lib/prawn/text/formatted/box.rb +233 -165
- data/lib/prawn/text/formatted/fragment.rb +27 -27
- data/lib/prawn/text/formatted/line_wrap.rb +137 -97
- data/lib/prawn/text/formatted/parser.rb +149 -127
- data/lib/prawn/text/formatted/wrap.rb +57 -37
- data/lib/prawn/text/formatted.rb +6 -4
- data/lib/prawn/text.rb +105 -73
- data/lib/prawn/transformation_stack.rb +44 -0
- data/lib/prawn/utilities.rb +11 -21
- data/lib/prawn/version.rb +5 -0
- data/lib/prawn/view.rb +101 -0
- data/lib/prawn.rb +42 -68
- data/{data/images/fractal.jpg → manual/absolute_position.pdf} +0 -0
- data/manual/basic_concepts/adding_pages.rb +9 -10
- data/manual/basic_concepts/basic_concepts.rb +33 -24
- data/manual/basic_concepts/creation.rb +10 -11
- data/manual/basic_concepts/cursor.rb +9 -10
- data/manual/basic_concepts/measurement.rb +10 -11
- data/manual/basic_concepts/origin.rb +8 -9
- data/manual/basic_concepts/other_cursor_helpers.rb +17 -18
- data/manual/basic_concepts/view.rb +48 -0
- data/manual/bounding_box/bounding_box.rb +31 -29
- data/manual/bounding_box/bounds.rb +17 -18
- data/manual/bounding_box/canvas.rb +8 -9
- data/manual/bounding_box/creation.rb +8 -9
- data/manual/bounding_box/indentation.rb +22 -23
- data/manual/bounding_box/nesting.rb +32 -25
- data/manual/bounding_box/russian_boxes.rb +19 -19
- data/manual/bounding_box/stretchy.rb +18 -20
- data/manual/contents.rb +35 -0
- data/manual/cover.rb +43 -0
- data/manual/document_and_page_options/background.rb +16 -14
- data/manual/document_and_page_options/document_and_page_options.rb +26 -23
- data/manual/document_and_page_options/metadata.rb +21 -19
- data/manual/document_and_page_options/page_margins.rb +20 -22
- data/manual/document_and_page_options/page_size.rb +15 -15
- data/manual/document_and_page_options/print_scaling.rb +23 -0
- data/manual/example_helper.rb +5 -408
- data/manual/graphics/blend_mode.rb +52 -0
- data/manual/graphics/circle_and_ellipse.rb +8 -9
- data/manual/graphics/color.rb +11 -13
- data/manual/graphics/common_lines.rb +13 -12
- data/manual/graphics/fill_and_stroke.rb +10 -11
- data/manual/graphics/fill_rules.rb +13 -12
- data/manual/graphics/gradients.rb +28 -22
- data/manual/graphics/graphics.rb +52 -46
- data/manual/graphics/helper.rb +20 -10
- data/manual/graphics/line_width.rb +13 -12
- data/manual/graphics/lines_and_curves.rb +13 -14
- data/manual/graphics/polygon.rb +10 -12
- data/manual/graphics/rectangle.rb +7 -8
- data/manual/graphics/rotate.rb +9 -12
- data/manual/graphics/scale.rb +19 -18
- data/manual/graphics/soft_masks.rb +5 -7
- data/manual/graphics/stroke_cap.rb +10 -11
- data/manual/graphics/stroke_dash.rb +16 -17
- data/manual/graphics/stroke_join.rb +10 -11
- data/manual/graphics/translate.rb +13 -13
- data/manual/graphics/transparency.rb +11 -13
- data/manual/{manual/how_to_read_this_manual.rb → how_to_read_this_manual.rb} +23 -25
- data/manual/images/absolute_position.rb +9 -10
- data/manual/images/fit.rb +9 -10
- data/manual/images/horizontal.rb +13 -14
- data/manual/images/images.rb +31 -30
- data/manual/images/plain_image.rb +6 -7
- data/manual/images/scale.rb +12 -13
- data/manual/images/vertical.rb +19 -17
- data/manual/images/width_and_height.rb +13 -14
- data/manual/layout/boxes.rb +14 -15
- data/manual/layout/content.rb +12 -13
- data/manual/layout/layout.rb +19 -20
- data/manual/layout/simple_grid.rb +8 -9
- data/manual/outline/add_subsection_to.rb +26 -27
- data/manual/outline/insert_section_after.rb +19 -20
- data/manual/outline/outline.rb +23 -22
- data/manual/outline/sections_and_pages.rb +24 -25
- data/manual/repeatable_content/alternate_page_numbering.rb +36 -0
- data/manual/repeatable_content/page_numbering.rb +20 -19
- data/manual/repeatable_content/repeatable_content.rb +26 -22
- data/manual/repeatable_content/repeater.rb +18 -19
- data/manual/repeatable_content/stamp.rb +18 -19
- data/manual/security/encryption.rb +8 -11
- data/manual/security/permissions.rb +20 -15
- data/manual/security/security.rb +20 -20
- data/manual/table.rb +16 -0
- data/manual/text/alignment.rb +17 -18
- data/manual/text/color.rb +13 -13
- data/manual/text/column_box.rb +10 -12
- data/manual/text/fallback_fonts.rb +29 -25
- data/manual/text/font.rb +17 -18
- data/manual/text/font_size.rb +21 -22
- data/manual/text/font_style.rb +12 -10
- data/manual/text/formatted_callbacks.rb +36 -26
- data/manual/text/formatted_text.rb +41 -34
- data/manual/text/free_flowing_text.rb +28 -29
- data/manual/text/inline.rb +23 -26
- data/manual/text/kerning_and_character_spacing.rb +20 -21
- data/manual/text/leading.rb +10 -11
- data/manual/text/line_wrapping.rb +40 -21
- data/manual/text/paragraph_indentation.rb +17 -12
- data/manual/text/positioned_text.rb +19 -20
- data/manual/text/registering_families.rb +33 -30
- data/manual/text/rendering_and_color.rb +11 -12
- data/manual/text/right_to_left_text.rb +31 -20
- data/manual/text/rotation.rb +36 -27
- data/manual/text/single_usage.rb +13 -14
- data/manual/text/text.rb +62 -62
- data/manual/text/text_box_excess.rb +22 -19
- data/manual/text/text_box_extensions.rb +21 -18
- data/manual/text/text_box_overflow.rb +28 -21
- data/manual/text/utf8.rb +16 -17
- data/manual/text/win_ansi_charset.rb +29 -26
- data/prawn.gemspec +45 -43
- data/spec/extensions/encoding_helpers.rb +4 -3
- data/spec/prawn/document/bounding_box_spec.rb +550 -0
- data/spec/prawn/document/column_box_spec.rb +75 -0
- data/spec/prawn/document/security_spec.rb +176 -0
- data/spec/prawn/document_annotations_spec.rb +76 -0
- data/spec/prawn/document_destinations_spec.rb +15 -0
- data/spec/prawn/document_grid_spec.rb +99 -0
- data/spec/prawn/document_reference_spec.rb +27 -0
- data/spec/prawn/document_span_spec.rb +44 -0
- data/spec/prawn/document_spec.rb +805 -0
- data/spec/prawn/font_metric_cache_spec.rb +54 -0
- data/spec/prawn/font_spec.rb +544 -0
- data/spec/prawn/graphics/blend_mode_spec.rb +63 -0
- data/spec/prawn/graphics/transparency_spec.rb +81 -0
- data/spec/prawn/graphics_spec.rb +872 -0
- data/spec/prawn/graphics_stroke_styles_spec.rb +229 -0
- data/spec/prawn/image_handler_spec.rb +53 -0
- data/spec/prawn/images/jpg_spec.rb +20 -0
- data/spec/prawn/images/png_spec.rb +283 -0
- data/spec/prawn/images_spec.rb +229 -0
- data/spec/prawn/measurements_extensions_spec.rb +24 -0
- data/spec/prawn/outline_spec.rb +512 -0
- data/spec/prawn/repeater_spec.rb +166 -0
- data/spec/prawn/soft_mask_spec.rb +74 -0
- data/spec/prawn/stamp_spec.rb +173 -0
- data/spec/prawn/text/box_spec.rb +1110 -0
- data/spec/prawn/text/formatted/arranger_spec.rb +466 -0
- data/spec/prawn/text/formatted/box_spec.rb +849 -0
- data/spec/prawn/text/formatted/fragment_spec.rb +343 -0
- data/spec/prawn/text/formatted/line_wrap_spec.rb +495 -0
- data/spec/prawn/text/formatted/parser_spec.rb +697 -0
- data/spec/prawn/text_draw_text_spec.rb +150 -0
- data/spec/prawn/text_rendering_mode_spec.rb +48 -0
- data/spec/prawn/text_spacing_spec.rb +95 -0
- data/spec/prawn/text_spec.rb +603 -0
- data/spec/prawn/text_with_inline_formatting_spec.rb +35 -0
- data/spec/prawn/transformation_stack_spec.rb +66 -0
- data/spec/prawn/view_spec.rb +63 -0
- data/spec/prawn_manual_spec.rb +35 -0
- data/spec/spec_helper.rb +22 -21
- data.tar.gz.sig +0 -0
- metadata +168 -307
- metadata.gz.sig +0 -0
- data/README.md +0 -109
- data/data/encodings/win_ansi.txt +0 -29
- data/data/images/16bit.alpha +0 -0
- data/data/images/16bit.dat +0 -0
- data/data/images/16bit.png +0 -0
- data/data/images/arrow.png +0 -0
- data/data/images/arrow2.png +0 -0
- data/data/images/barcode_issue.png +0 -0
- data/data/images/dice.alpha +0 -0
- data/data/images/dice.dat +0 -0
- data/data/images/dice.png +0 -0
- data/data/images/dice_interlaced.png +0 -0
- data/data/images/indexed_color.dat +0 -0
- data/data/images/indexed_color.png +0 -0
- data/data/images/letterhead.jpg +0 -0
- data/data/images/page_white_text.alpha +0 -0
- data/data/images/page_white_text.dat +0 -0
- data/data/images/page_white_text.png +0 -0
- data/data/images/pigs.jpg +0 -0
- data/data/images/prawn.png +0 -0
- data/data/images/ruport.png +0 -0
- data/data/images/ruport_data.dat +0 -0
- data/data/images/ruport_transparent.png +0 -0
- data/data/images/ruport_type0.png +0 -0
- data/data/images/stef.jpg +0 -0
- data/data/images/tru256.bmp +0 -0
- data/data/images/web-links.dat +0 -1
- data/data/images/web-links.png +0 -0
- data/data/pdfs/complex_template.pdf +0 -0
- data/data/pdfs/contains_ttf_font.pdf +0 -0
- data/data/pdfs/encrypted.pdf +0 -0
- data/data/pdfs/form.pdf +1 -819
- data/data/pdfs/hexagon.pdf +0 -61
- data/data/pdfs/indirect_reference.pdf +0 -86
- data/data/pdfs/multipage_template.pdf +0 -127
- data/data/pdfs/nested_pages.pdf +0 -118
- data/data/pdfs/page_without_mediabox.pdf +0 -193
- data/data/pdfs/resources_as_indirect_object.pdf +0 -83
- data/data/pdfs/two_hexagons.pdf +0 -90
- data/data/pdfs/version_1_6.pdf +0 -61
- data/data/shift_jis_text.txt +0 -1
- data/lib/pdf/core/annotations.rb +0 -60
- data/lib/pdf/core/byte_string.rb +0 -9
- data/lib/pdf/core/destinations.rb +0 -90
- data/lib/pdf/core/document_state.rb +0 -78
- data/lib/pdf/core/filter_list.rb +0 -51
- data/lib/pdf/core/filters.rb +0 -36
- data/lib/pdf/core/graphics_state.rb +0 -68
- data/lib/pdf/core/literal_string.rb +0 -16
- data/lib/pdf/core/name_tree.rb +0 -177
- data/lib/pdf/core/object_store.rb +0 -320
- data/lib/pdf/core/outline.rb +0 -315
- data/lib/pdf/core/page.rb +0 -212
- data/lib/pdf/core/page_geometry.rb +0 -126
- data/lib/pdf/core/pdf_object.rb +0 -124
- data/lib/pdf/core/reference.rb +0 -103
- data/lib/pdf/core/stream.rb +0 -98
- data/lib/pdf/core/text.rb +0 -275
- data/lib/pdf/core.rb +0 -35
- data/lib/prawn/compatibility.rb +0 -91
- data/lib/prawn/document/graphics_state.rb +0 -73
- data/lib/prawn/document/snapshot.rb +0 -89
- data/lib/prawn/font/afm.rb +0 -203
- data/lib/prawn/layout.rb +0 -20
- data/lib/prawn/table/cell/image.rb +0 -70
- data/lib/prawn/table/cell/in_table.rb +0 -27
- data/lib/prawn/table/cell/span_dummy.rb +0 -92
- data/lib/prawn/table/cell/subtable.rb +0 -65
- data/lib/prawn/table/cell/text.rb +0 -153
- data/lib/prawn/table/cell.rb +0 -770
- data/lib/prawn/table/cells.rb +0 -295
- data/lib/prawn/table.rb +0 -643
- data/manual/example_file.rb +0 -116
- data/manual/example_package.rb +0 -53
- data/manual/example_section.rb +0 -46
- data/manual/manual/cover.rb +0 -35
- data/manual/manual/foreword.rb +0 -85
- data/manual/manual/manual.rb +0 -35
- data/manual/syntax_highlight.rb +0 -52
- data/manual/table/basic_block.rb +0 -53
- data/manual/table/before_rendering_page.rb +0 -26
- data/manual/table/cell_border_lines.rb +0 -24
- data/manual/table/cell_borders_and_bg.rb +0 -31
- data/manual/table/cell_dimensions.rb +0 -30
- data/manual/table/cell_text.rb +0 -38
- data/manual/table/column_widths.rb +0 -30
- data/manual/table/content_and_subtables.rb +0 -39
- data/manual/table/creation.rb +0 -27
- data/manual/table/filtering.rb +0 -36
- data/manual/table/flow_and_header.rb +0 -17
- data/manual/table/image_cells.rb +0 -33
- data/manual/table/position.rb +0 -29
- data/manual/table/row_colors.rb +0 -20
- data/manual/table/span.rb +0 -30
- data/manual/table/style.rb +0 -22
- data/manual/table/table.rb +0 -52
- data/manual/table/width.rb +0 -27
- data/manual/templates/full_template.rb +0 -25
- data/manual/templates/page_template.rb +0 -48
- data/manual/templates/templates.rb +0 -27
- data/manual/text/group.rb +0 -29
- data/spec/acceptance/png.rb +0 -23
- data/spec/annotations_spec.rb +0 -74
- data/spec/bounding_box_spec.rb +0 -493
- data/spec/cell_spec.rb +0 -628
- data/spec/column_box_spec.rb +0 -33
- data/spec/destinations_spec.rb +0 -15
- data/spec/document_spec.rb +0 -761
- data/spec/extensions/mocha.rb +0 -44
- data/spec/filters_spec.rb +0 -34
- data/spec/font_metric_cache_spec.rb +0 -52
- data/spec/font_spec.rb +0 -464
- data/spec/formatted_text_arranger_spec.rb +0 -421
- data/spec/formatted_text_box_spec.rb +0 -650
- data/spec/formatted_text_fragment_spec.rb +0 -298
- data/spec/graphics_spec.rb +0 -651
- data/spec/grid_spec.rb +0 -85
- data/spec/image_handler_spec.rb +0 -42
- data/spec/images_spec.rb +0 -157
- data/spec/inline_formatted_text_parser_spec.rb +0 -564
- data/spec/jpg_spec.rb +0 -25
- data/spec/line_wrap_spec.rb +0 -333
- data/spec/measurement_units_spec.rb +0 -23
- data/spec/name_tree_spec.rb +0 -112
- data/spec/object_store_spec.rb +0 -170
- data/spec/outline_spec.rb +0 -448
- data/spec/pdf_object_spec.rb +0 -172
- data/spec/png_spec.rb +0 -240
- data/spec/reference_spec.rb +0 -82
- data/spec/repeater_spec.rb +0 -158
- data/spec/security_spec.rb +0 -158
- data/spec/snapshot_spec.rb +0 -186
- data/spec/soft_mask_spec.rb +0 -117
- data/spec/span_spec.rb +0 -44
- data/spec/stamp_spec.rb +0 -158
- data/spec/stream_spec.rb +0 -58
- data/spec/stroke_styles_spec.rb +0 -211
- data/spec/table/span_dummy_spec.rb +0 -17
- data/spec/table_spec.rb +0 -1355
- data/spec/template_spec.rb +0 -351
- data/spec/text_at_spec.rb +0 -130
- data/spec/text_box_spec.rb +0 -1030
- data/spec/text_rendering_mode_spec.rb +0 -45
- data/spec/text_spacing_spec.rb +0 -93
- data/spec/text_spec.rb +0 -425
- data/spec/text_with_inline_formatting_spec.rb +0 -35
- data/spec/transparency_spec.rb +0 -89
@@ -1,4 +1,4 @@
|
|
1
|
-
#
|
1
|
+
# frozen_string_literal: true
|
2
2
|
|
3
3
|
# prawn/font/ttf.rb : Implements AFM font support for Prawn
|
4
4
|
#
|
@@ -11,43 +11,68 @@ require 'ttfunk'
|
|
11
11
|
require 'ttfunk/subset_collection'
|
12
12
|
|
13
13
|
module Prawn
|
14
|
-
|
14
|
+
module Fonts
|
15
|
+
# @private
|
15
16
|
class TTF < Font
|
17
|
+
class Error < StandardError
|
18
|
+
DEFAULT_MESSAGE = 'TTF font error'
|
19
|
+
MESSAGE_WITH_FONT = 'TTF font error in font %<font>s'
|
20
|
+
|
21
|
+
def initialize(message = DEFAULT_MESSAGE, font: nil)
|
22
|
+
if font && message == DEFAULT_MESSAGE
|
23
|
+
super format(MESSAGE_WITH_FONT, font: font)
|
24
|
+
else
|
25
|
+
super message
|
26
|
+
end
|
27
|
+
end
|
28
|
+
end
|
29
|
+
|
30
|
+
class NoUnicodeCMap < Error
|
31
|
+
DEFAULT_MESSAGE = 'No unicode cmap found in font'
|
32
|
+
MESSAGE_WITH_FONT = 'No unicode cmap found in font %<font>s'
|
33
|
+
end
|
34
|
+
|
35
|
+
class NoPostscriptName < Error
|
36
|
+
DEFAULT_MESSAGE = 'Can not detect a postscript name'
|
37
|
+
MESSAGE_WITH_FONT = 'Can not detect a postscript name in font %<font>s'
|
38
|
+
end
|
39
|
+
|
16
40
|
attr_reader :ttf, :subsets
|
17
41
|
|
18
42
|
def unicode?
|
19
43
|
true
|
20
44
|
end
|
21
45
|
|
22
|
-
def initialize(document, name, options={})
|
46
|
+
def initialize(document, name, options = {})
|
23
47
|
super
|
24
48
|
|
25
|
-
@ttf
|
26
|
-
@subsets
|
49
|
+
@ttf = read_ttf_file
|
50
|
+
@subsets = TTFunk::SubsetCollection.new(@ttf)
|
51
|
+
@italic_angle = nil
|
27
52
|
|
28
|
-
@attributes
|
29
|
-
@bounding_boxes
|
30
|
-
@char_widths
|
53
|
+
@attributes = {}
|
54
|
+
@bounding_boxes = {}
|
55
|
+
@char_widths = {}
|
31
56
|
@has_kerning_data = @ttf.kerning.exists? && @ttf.kerning.tables.any?
|
32
57
|
|
33
|
-
@ascender
|
34
|
-
@descender
|
35
|
-
@line_gap
|
58
|
+
@ascender = Integer(@ttf.ascent * scale_factor)
|
59
|
+
@descender = Integer(@ttf.descent * scale_factor)
|
60
|
+
@line_gap = Integer(@ttf.line_gap * scale_factor)
|
36
61
|
end
|
37
62
|
|
38
63
|
# NOTE: +string+ must be UTF8-encoded.
|
39
|
-
def compute_width_of(string, options={}) #:nodoc:
|
64
|
+
def compute_width_of(string, options = {}) #:nodoc:
|
40
65
|
scale = (options[:size] || size) / 1000.0
|
41
66
|
if options[:kerning]
|
42
|
-
kern(string).
|
67
|
+
kern(string).reduce(0) do |s, r|
|
43
68
|
if r.is_a?(Numeric)
|
44
69
|
s - r
|
45
70
|
else
|
46
|
-
r.
|
71
|
+
r.reduce(s) { |a, e| a + character_width_by_code(e) }
|
47
72
|
end
|
48
73
|
end * scale
|
49
74
|
else
|
50
|
-
string.codepoints.
|
75
|
+
string.codepoints.reduce(0) do |s, r|
|
51
76
|
s + character_width_by_code(r)
|
52
77
|
end * scale
|
53
78
|
end
|
@@ -60,9 +85,12 @@ module Prawn
|
|
60
85
|
end
|
61
86
|
|
62
87
|
# Returns true if the font has kerning data, false otherwise
|
88
|
+
#
|
89
|
+
# rubocop: disable Naming/PredicateName
|
63
90
|
def has_kerning_data?
|
64
91
|
@has_kerning_data
|
65
92
|
end
|
93
|
+
# rubocop: enable Naming/PredicateName
|
66
94
|
|
67
95
|
# Perform any changes to the string that need to happen
|
68
96
|
# before it is rendered to the canvas. Returns an array of
|
@@ -72,14 +100,16 @@ module Prawn
|
|
72
100
|
#
|
73
101
|
# The +text+ parameter must be UTF8-encoded.
|
74
102
|
#
|
75
|
-
def encode_text(text,options={})
|
103
|
+
def encode_text(text, options = {})
|
76
104
|
text = text.chomp
|
77
105
|
|
78
106
|
if options[:kerning]
|
79
107
|
last_subset = nil
|
80
|
-
kern(text).
|
108
|
+
kern(text).reduce([]) do |result, element|
|
81
109
|
if element.is_a?(Numeric)
|
82
|
-
|
110
|
+
unless result.last[1].is_a?(Array)
|
111
|
+
result.last[1] = [result.last[1]]
|
112
|
+
end
|
83
113
|
result.last[1] << element
|
84
114
|
result
|
85
115
|
else
|
@@ -99,7 +129,7 @@ module Prawn
|
|
99
129
|
end
|
100
130
|
end
|
101
131
|
else
|
102
|
-
@subsets.encode(text.unpack(
|
132
|
+
@subsets.encode(text.unpack('U*'))
|
103
133
|
end
|
104
134
|
end
|
105
135
|
|
@@ -108,26 +138,32 @@ module Prawn
|
|
108
138
|
end
|
109
139
|
|
110
140
|
# not sure how to compute this for true-type fonts...
|
111
|
-
def
|
141
|
+
def stem_v
|
112
142
|
0
|
113
143
|
end
|
114
144
|
|
115
145
|
def italic_angle
|
116
|
-
@italic_angle
|
146
|
+
return @italic_angle if @italic_angle
|
147
|
+
|
148
|
+
if @ttf.postscript.exists?
|
117
149
|
raw = @ttf.postscript.italic_angle
|
118
|
-
hi
|
150
|
+
hi = raw >> 16
|
151
|
+
low = raw & 0xFF
|
119
152
|
hi = -((hi ^ 0xFFFF) + 1) if hi & 0x8000 != 0
|
120
|
-
"#{hi}.#{low}".to_f
|
153
|
+
@italic_angle = "#{hi}.#{low}".to_f
|
121
154
|
else
|
122
|
-
0
|
155
|
+
@italic_angle = 0
|
123
156
|
end
|
157
|
+
|
158
|
+
@italic_angle
|
124
159
|
end
|
125
160
|
|
126
161
|
def cap_height
|
127
|
-
@cap_height ||=
|
128
|
-
|
129
|
-
|
130
|
-
|
162
|
+
@cap_height ||=
|
163
|
+
begin
|
164
|
+
height = @ttf.os2.exists? && @ttf.os2.cap_height || 0
|
165
|
+
height.zero? ? @ascender : height
|
166
|
+
end
|
131
167
|
end
|
132
168
|
|
133
169
|
def x_height
|
@@ -141,7 +177,7 @@ module Prawn
|
|
141
177
|
end
|
142
178
|
|
143
179
|
def serif?
|
144
|
-
@serif ||= [1,2,3,4,5,7].include?(family_class)
|
180
|
+
@serif ||= [1, 2, 3, 4, 5, 7].include?(family_class)
|
145
181
|
end
|
146
182
|
|
147
183
|
def script?
|
@@ -149,35 +185,47 @@ module Prawn
|
|
149
185
|
end
|
150
186
|
|
151
187
|
def pdf_flags
|
152
|
-
@
|
153
|
-
|
154
|
-
|
155
|
-
|
156
|
-
|
157
|
-
|
158
|
-
|
159
|
-
|
188
|
+
@pdf_flags ||=
|
189
|
+
begin
|
190
|
+
flags = 0
|
191
|
+
flags |= 0x0001 if @ttf.postscript.fixed_pitch?
|
192
|
+
flags |= 0x0002 if serif?
|
193
|
+
flags |= 0x0008 if script?
|
194
|
+
flags |= 0x0040 if italic_angle != 0
|
195
|
+
# Assume the font contains at least some non-latin characters
|
196
|
+
flags | 0x0004
|
197
|
+
end
|
160
198
|
end
|
161
199
|
|
162
200
|
def normalize_encoding(text)
|
163
|
-
text.
|
201
|
+
text.encode(::Encoding::UTF_8)
|
202
|
+
rescue StandardError => e
|
203
|
+
puts e
|
204
|
+
raise Prawn::Errors::IncompatibleStringEncoding,
|
205
|
+
"Encoding #{text.encoding} can not be transparently converted to UTF-8. " \
|
206
|
+
'Please ensure the encoding of the string you are attempting ' \
|
207
|
+
'to use is set correctly'
|
208
|
+
end
|
209
|
+
|
210
|
+
def to_utf8(text)
|
211
|
+
text.encode('UTF-8')
|
164
212
|
end
|
165
213
|
|
166
214
|
def glyph_present?(char)
|
167
215
|
code = char.codepoints.first
|
168
|
-
cmap[code]
|
216
|
+
cmap[code].positive?
|
169
217
|
end
|
170
218
|
|
171
219
|
# Returns the number of characters in +str+ (a UTF-8-encoded string).
|
172
220
|
#
|
173
221
|
def character_count(str)
|
174
|
-
str.
|
222
|
+
str.length
|
175
223
|
end
|
176
224
|
|
177
225
|
private
|
178
226
|
|
179
227
|
def cmap
|
180
|
-
@cmap ||= @ttf.cmap.unicode.first
|
228
|
+
(@cmap ||= @ttf.cmap.unicode.first) || raise(NoUnicodeCMap.new(font: name))
|
181
229
|
end
|
182
230
|
|
183
231
|
# +string+ must be UTF8-encoded.
|
@@ -203,12 +251,12 @@ module Prawn
|
|
203
251
|
end
|
204
252
|
|
205
253
|
def kern_pairs_table
|
206
|
-
@
|
207
|
-
|
208
|
-
|
209
|
-
|
210
|
-
|
211
|
-
|
254
|
+
@kern_pairs_table ||=
|
255
|
+
if has_kerning_data?
|
256
|
+
@ttf.kerning.tables.first.pairs
|
257
|
+
else
|
258
|
+
{}
|
259
|
+
end
|
212
260
|
end
|
213
261
|
|
214
262
|
def hmtx
|
@@ -226,16 +274,16 @@ module Prawn
|
|
226
274
|
end
|
227
275
|
|
228
276
|
def scale_factor
|
229
|
-
@
|
277
|
+
@scale_factor ||= 1000.0 / @ttf.header.units_per_em
|
230
278
|
end
|
231
279
|
|
232
280
|
def register(subset)
|
233
|
-
temp_name = @ttf.name.postscript_name.
|
234
|
-
ref = @document.ref!(:
|
281
|
+
temp_name = @ttf.name.postscript_name.delete("\0").to_sym
|
282
|
+
ref = @document.ref!(Type: :Font, BaseFont: temp_name)
|
235
283
|
|
236
284
|
# Embed the font metrics in the document after everything has been
|
237
285
|
# drawn, just before the document is emitted.
|
238
|
-
@document.before_render { |
|
286
|
+
@document.renderer.before_render { |_doc| embed(ref, subset) }
|
239
287
|
|
240
288
|
ref
|
241
289
|
end
|
@@ -250,29 +298,32 @@ module Prawn
|
|
250
298
|
|
251
299
|
# empirically, it looks like Adobe Reader will not display fonts
|
252
300
|
# if their font name is more than 33 bytes long. Strange. But true.
|
253
|
-
basename = font.name.postscript_name[0, 33].
|
301
|
+
basename = font.name.postscript_name[0, 33].delete("\0")
|
254
302
|
|
255
|
-
raise
|
303
|
+
raise NoPostscriptName.new(font: font) if basename.nil?
|
256
304
|
|
257
|
-
fontfile = @document.ref!(:
|
305
|
+
fontfile = @document.ref!(Length1: font_content.size)
|
258
306
|
fontfile.stream << font_content
|
259
307
|
fontfile.stream.compress!
|
260
308
|
|
261
|
-
descriptor = @document.ref!(
|
262
|
-
|
263
|
-
|
264
|
-
|
265
|
-
|
266
|
-
|
267
|
-
|
268
|
-
|
269
|
-
|
270
|
-
|
271
|
-
|
309
|
+
descriptor = @document.ref!(
|
310
|
+
Type: :FontDescriptor,
|
311
|
+
FontName: basename.to_sym,
|
312
|
+
FontFile2: fontfile,
|
313
|
+
FontBBox: bbox,
|
314
|
+
Flags: pdf_flags,
|
315
|
+
StemV: stem_v,
|
316
|
+
ItalicAngle: italic_angle,
|
317
|
+
Ascent: @ascender,
|
318
|
+
Descent: @descender,
|
319
|
+
CapHeight: cap_height,
|
320
|
+
XHeight: x_height
|
321
|
+
)
|
272
322
|
|
273
323
|
hmtx = font.horizontal_metrics
|
274
|
-
widths = font.cmap.tables.first.code_map.map
|
275
|
-
Integer(hmtx.widths[gid] * scale_factor)
|
324
|
+
widths = font.cmap.tables.first.code_map.map do |gid|
|
325
|
+
Integer(hmtx.widths[gid] * scale_factor)
|
326
|
+
end[32..-1]
|
276
327
|
|
277
328
|
# It would be nice to have Encoding set for the macroman subsets,
|
278
329
|
# and only do a ToUnicode cmap for non-encoded unicode subsets.
|
@@ -287,15 +338,24 @@ module Prawn
|
|
287
338
|
map = @subsets[subset].to_unicode_map
|
288
339
|
|
289
340
|
ranges = [[]]
|
290
|
-
map.keys.sort.
|
341
|
+
map.keys.sort.reduce('') do |_s, code|
|
291
342
|
ranges << [] if ranges.last.length >= 100
|
292
343
|
unicode = map[code]
|
293
|
-
ranges.last <<
|
344
|
+
ranges.last << format(
|
345
|
+
'<%<code>02x><%<unicode>04x>',
|
346
|
+
code: code,
|
347
|
+
unicode: unicode
|
348
|
+
)
|
294
349
|
end
|
295
350
|
|
296
|
-
range_blocks =
|
297
|
-
|
298
|
-
|
351
|
+
range_blocks =
|
352
|
+
ranges.reduce(+'') do |s, list|
|
353
|
+
s << format(
|
354
|
+
"%<lenght>d beginbfchar\n%<list>s\nendbfchar\n",
|
355
|
+
lenght: list.length,
|
356
|
+
list: list.join("\n")
|
357
|
+
)
|
358
|
+
end
|
299
359
|
|
300
360
|
to_unicode_cmap = UNICODE_CMAP_TEMPLATE % range_blocks.strip
|
301
361
|
|
@@ -303,16 +363,18 @@ module Prawn
|
|
303
363
|
cmap << to_unicode_cmap
|
304
364
|
cmap.stream.compress!
|
305
365
|
|
306
|
-
reference.data.update(
|
307
|
-
|
308
|
-
|
309
|
-
|
310
|
-
|
311
|
-
|
312
|
-
|
366
|
+
reference.data.update(
|
367
|
+
Subtype: :TrueType,
|
368
|
+
BaseFont: basename.to_sym,
|
369
|
+
FontDescriptor: descriptor,
|
370
|
+
FirstChar: 32,
|
371
|
+
LastChar: 255,
|
372
|
+
Widths: @document.ref!(widths),
|
373
|
+
ToUnicode: cmap
|
374
|
+
)
|
313
375
|
end
|
314
376
|
|
315
|
-
UNICODE_CMAP_TEMPLATE = <<-STR.strip.gsub(/^\s*/,
|
377
|
+
UNICODE_CMAP_TEMPLATE = <<-STR.strip.gsub(/^\s*/, '')
|
316
378
|
/CIDInit /ProcSet findresource begin
|
317
379
|
12 dict begin
|
318
380
|
begincmap
|
@@ -0,0 +1,65 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
# blend_mode.rb : Implements blend modes
|
4
|
+
#
|
5
|
+
# Contributed by John Ford. October, 2015
|
6
|
+
#
|
7
|
+
# This is free software. Please see the LICENSE and COPYING files for details.
|
8
|
+
#
|
9
|
+
|
10
|
+
module Prawn
|
11
|
+
module Graphics
|
12
|
+
# The Prawn::BlendMode module is used to change the way
|
13
|
+
# two layers are blended together.
|
14
|
+
#
|
15
|
+
# Passing an array of blend modes is allowed. PDF viewers should
|
16
|
+
# blend layers based on the first recognized blend mode.
|
17
|
+
#
|
18
|
+
# Valid blend modes in v1.4 of the PDF spec include :Normal, :Multiply,
|
19
|
+
# :Screen, :Overlay, :Darken, :Lighten, :ColorDodge, :ColorBurn, :HardLight,
|
20
|
+
# :SoftLight, :Difference, :Exclusion, :Hue, :Saturation, :Color, and
|
21
|
+
# :Luminosity.
|
22
|
+
#
|
23
|
+
# Example:
|
24
|
+
# pdf.fill_color('0000ff')
|
25
|
+
# pdf.fill_rectangle([x, y+25], 50, 50)
|
26
|
+
# pdf.blend_mode(:Multiply) do
|
27
|
+
# pdf.fill_color('ff0000')
|
28
|
+
# pdf.fill_circle([x, y], 25)
|
29
|
+
# end
|
30
|
+
#
|
31
|
+
module BlendMode
|
32
|
+
# @group Stable API
|
33
|
+
|
34
|
+
def blend_mode(blend_mode = :Normal)
|
35
|
+
renderer.min_version(1.4)
|
36
|
+
|
37
|
+
save_graphics_state if block_given?
|
38
|
+
renderer.add_content "/#{blend_mode_dictionary_name(blend_mode)} gs"
|
39
|
+
if block_given?
|
40
|
+
yield
|
41
|
+
restore_graphics_state
|
42
|
+
end
|
43
|
+
end
|
44
|
+
|
45
|
+
private
|
46
|
+
|
47
|
+
def blend_mode_dictionary_registry
|
48
|
+
@blend_mode_dictionary_registry ||= {}
|
49
|
+
end
|
50
|
+
|
51
|
+
def blend_mode_dictionary_name(blend_mode)
|
52
|
+
key = Array(blend_mode).join('')
|
53
|
+
dictionary_name = "BM#{key}"
|
54
|
+
|
55
|
+
dictionary = blend_mode_dictionary_registry[dictionary_name] ||= ref!(
|
56
|
+
Type: :ExtGState,
|
57
|
+
BM: blend_mode
|
58
|
+
)
|
59
|
+
|
60
|
+
page.ext_gstates[dictionary_name] = dictionary
|
61
|
+
dictionary_name
|
62
|
+
end
|
63
|
+
end
|
64
|
+
end
|
65
|
+
end
|
@@ -1,4 +1,4 @@
|
|
1
|
-
#
|
1
|
+
# frozen_string_literal: true
|
2
2
|
|
3
3
|
# cap_style.rb : Implements stroke cap styling
|
4
4
|
#
|
@@ -9,8 +9,9 @@
|
|
9
9
|
module Prawn
|
10
10
|
module Graphics
|
11
11
|
module CapStyle
|
12
|
+
# @group Stable API
|
12
13
|
|
13
|
-
CAP_STYLES = { :
|
14
|
+
CAP_STYLES = { butt: 0, round: 1, projecting_square: 2 }.freeze
|
14
15
|
|
15
16
|
# Sets the cap style for stroked lines and curves
|
16
17
|
#
|
@@ -18,7 +19,7 @@ module Prawn
|
|
18
19
|
#
|
19
20
|
# NOTE: If this method is never called, :butt will be used by default.
|
20
21
|
#
|
21
|
-
def cap_style(style=nil)
|
22
|
+
def cap_style(style = nil)
|
22
23
|
return current_cap_style || :butt if style.nil?
|
23
24
|
|
24
25
|
self.current_cap_style = style
|
@@ -26,7 +27,7 @@ module Prawn
|
|
26
27
|
write_stroke_cap_style
|
27
28
|
end
|
28
29
|
|
29
|
-
|
30
|
+
alias cap_style= cap_style
|
30
31
|
|
31
32
|
private
|
32
33
|
|
@@ -39,7 +40,7 @@ module Prawn
|
|
39
40
|
end
|
40
41
|
|
41
42
|
def write_stroke_cap_style
|
42
|
-
add_content "#{CAP_STYLES[current_cap_style]} J"
|
43
|
+
renderer.add_content "#{CAP_STYLES[current_cap_style]} J"
|
43
44
|
end
|
44
45
|
end
|
45
46
|
end
|
data/lib/prawn/graphics/color.rb
CHANGED
@@ -1,4 +1,4 @@
|
|
1
|
-
#
|
1
|
+
# frozen_string_literal: true
|
2
2
|
|
3
3
|
# color.rb : Implements color handling
|
4
4
|
#
|
@@ -9,6 +9,7 @@
|
|
9
9
|
module Prawn
|
10
10
|
module Graphics
|
11
11
|
module Color
|
12
|
+
# @group Stable API
|
12
13
|
|
13
14
|
# Sets or returns the fill color.
|
14
15
|
#
|
@@ -26,11 +27,12 @@ module Prawn
|
|
26
27
|
#
|
27
28
|
def fill_color(*color)
|
28
29
|
return current_fill_color if color.empty?
|
30
|
+
|
29
31
|
self.current_fill_color = process_color(*color)
|
30
32
|
set_fill_color
|
31
33
|
end
|
32
34
|
|
33
|
-
|
35
|
+
alias fill_color= fill_color
|
34
36
|
|
35
37
|
# Sets or returns the line stroking color.
|
36
38
|
#
|
@@ -48,12 +50,13 @@ module Prawn
|
|
48
50
|
#
|
49
51
|
def stroke_color(*color)
|
50
52
|
return current_stroke_color if color.empty?
|
53
|
+
|
51
54
|
color = process_color(*color)
|
52
55
|
self.current_stroke_color = color
|
53
56
|
set_stroke_color(color)
|
54
57
|
end
|
55
58
|
|
56
|
-
|
59
|
+
alias stroke_color= stroke_color
|
57
60
|
|
58
61
|
module_function
|
59
62
|
|
@@ -64,7 +67,7 @@ module Prawn
|
|
64
67
|
# => "ff7808"
|
65
68
|
#
|
66
69
|
def rgb2hex(rgb)
|
67
|
-
rgb.map { |e|
|
70
|
+
rgb.map { |e| format '%<value>02x', value: e }.join
|
68
71
|
end
|
69
72
|
|
70
73
|
# Converts hex string into RGB value array:
|
@@ -73,14 +76,16 @@ module Prawn
|
|
73
76
|
# => [255, 120, 8]
|
74
77
|
#
|
75
78
|
def hex2rgb(hex)
|
76
|
-
r
|
77
|
-
|
79
|
+
r = hex[0..1]
|
80
|
+
g = hex[2..3]
|
81
|
+
b = hex[4..5]
|
82
|
+
[r, g, b].map { |e| e.to_i(16) }
|
78
83
|
end
|
79
84
|
|
80
85
|
private
|
81
86
|
|
82
87
|
def process_color(*color)
|
83
|
-
case
|
88
|
+
case color.size
|
84
89
|
when 1
|
85
90
|
color[0]
|
86
91
|
when 4
|
@@ -93,7 +98,11 @@ module Prawn
|
|
93
98
|
def color_type(color)
|
94
99
|
case color
|
95
100
|
when String
|
96
|
-
|
101
|
+
if /\A\h{6}\z/.match?(color)
|
102
|
+
:RGB
|
103
|
+
else
|
104
|
+
raise ArgumentError, "Unknown type of color: #{color.inspect}"
|
105
|
+
end
|
97
106
|
when Array
|
98
107
|
case color.length
|
99
108
|
when 3
|
@@ -109,16 +118,16 @@ module Prawn
|
|
109
118
|
def normalize_color(color)
|
110
119
|
case color_type(color)
|
111
120
|
when :RGB
|
112
|
-
r,g,b = hex2rgb(color)
|
121
|
+
r, g, b = hex2rgb(color)
|
113
122
|
[r / 255.0, g / 255.0, b / 255.0]
|
114
123
|
when :CMYK
|
115
|
-
c,m,y,k = *color
|
124
|
+
c, m, y, k = *color
|
116
125
|
[c / 100.0, m / 100.0, y / 100.0, k / 100.0]
|
117
126
|
end
|
118
127
|
end
|
119
128
|
|
120
129
|
def color_to_s(color)
|
121
|
-
normalize_color(color)
|
130
|
+
PDF::Core.real_params normalize_color(color)
|
122
131
|
end
|
123
132
|
|
124
133
|
def color_space(color)
|
@@ -130,42 +139,48 @@ module Prawn
|
|
130
139
|
end
|
131
140
|
end
|
132
141
|
|
133
|
-
COLOR_SPACES = [
|
142
|
+
COLOR_SPACES = %i[DeviceRGB DeviceCMYK Pattern].freeze
|
134
143
|
|
135
144
|
def set_color_space(type, color_space)
|
136
145
|
# don't set the same color space again
|
137
|
-
|
146
|
+
if current_color_space(type) == color_space &&
|
147
|
+
!state.page.in_stamp_stream?
|
148
|
+
return
|
149
|
+
end
|
150
|
+
|
138
151
|
set_current_color_space(color_space, type)
|
139
152
|
|
140
153
|
unless COLOR_SPACES.include?(color_space)
|
141
154
|
raise ArgumentError, "unknown color space: '#{color_space}'"
|
142
155
|
end
|
143
156
|
|
144
|
-
operator =
|
145
|
-
|
146
|
-
|
147
|
-
|
148
|
-
|
149
|
-
|
150
|
-
|
151
|
-
|
157
|
+
operator =
|
158
|
+
case type
|
159
|
+
when :fill
|
160
|
+
'cs'
|
161
|
+
when :stroke
|
162
|
+
'CS'
|
163
|
+
else
|
164
|
+
raise ArgumentError, "unknown type '#{type}'"
|
165
|
+
end
|
152
166
|
|
153
|
-
add_content "/#{color_space} #{operator}"
|
167
|
+
renderer.add_content "/#{color_space} #{operator}"
|
154
168
|
end
|
155
169
|
|
156
170
|
def set_color(type, color, options = {})
|
157
|
-
operator =
|
158
|
-
|
159
|
-
|
160
|
-
|
161
|
-
|
162
|
-
|
163
|
-
|
164
|
-
|
171
|
+
operator =
|
172
|
+
case type
|
173
|
+
when :fill
|
174
|
+
'scn'
|
175
|
+
when :stroke
|
176
|
+
'SCN'
|
177
|
+
else
|
178
|
+
raise ArgumentError, "unknown type '#{type}'"
|
179
|
+
end
|
165
180
|
|
166
181
|
if options[:pattern]
|
167
182
|
set_color_space type, :Pattern
|
168
|
-
add_content "/#{color} #{operator}"
|
183
|
+
renderer.add_content "/#{color} #{operator}"
|
169
184
|
else
|
170
185
|
set_color_space type, color_space(color)
|
171
186
|
color = color_to_s(color)
|
@@ -186,8 +201,6 @@ module Prawn
|
|
186
201
|
set_stroke_color
|
187
202
|
end
|
188
203
|
|
189
|
-
private
|
190
|
-
|
191
204
|
def current_color_space(type)
|
192
205
|
graphic_state.color_space[type]
|
193
206
|
end
|
@@ -213,19 +226,9 @@ module Prawn
|
|
213
226
|
graphic_state.stroke_color = color
|
214
227
|
end
|
215
228
|
|
216
|
-
def write_fill_color
|
217
|
-
write_color(current_fill_color, 'scn')
|
218
|
-
end
|
219
|
-
|
220
|
-
def write_stroke_color
|
221
|
-
write_color(current_fill_color, 'SCN')
|
222
|
-
end
|
223
|
-
|
224
229
|
def write_color(color, operator)
|
225
|
-
add_content "#{color} #{operator}"
|
230
|
+
renderer.add_content "#{color} #{operator}"
|
226
231
|
end
|
227
|
-
|
228
232
|
end
|
229
233
|
end
|
230
234
|
end
|
231
|
-
|