prawn 0.13.0 → 2.4.0
Sign up to get free protection for your applications and to get access to all the features.
- 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
|
-
|