thinreports 0.6.0.pre3

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 (146) hide show
  1. data/.yardopts +1 -0
  2. data/README.rdoc +100 -0
  3. data/Rakefile +10 -0
  4. data/doc/yardoc_templates/default/layout/html/footer.erb +10 -0
  5. data/lib/thinreports.rb +11 -0
  6. data/lib/thinreports/core.rb +20 -0
  7. data/lib/thinreports/core/errors.rb +58 -0
  8. data/lib/thinreports/core/events.rb +71 -0
  9. data/lib/thinreports/core/ext.rb +5 -0
  10. data/lib/thinreports/core/ext/array.rb +19 -0
  11. data/lib/thinreports/core/ext/hash.rb +19 -0
  12. data/lib/thinreports/core/ext/object.rb +25 -0
  13. data/lib/thinreports/core/format.rb +14 -0
  14. data/lib/thinreports/core/format/base.rb +93 -0
  15. data/lib/thinreports/core/format/builder.rb +65 -0
  16. data/lib/thinreports/core/ordered_hash.rb +39 -0
  17. data/lib/thinreports/core/page.rb +91 -0
  18. data/lib/thinreports/core/shape.rb +53 -0
  19. data/lib/thinreports/core/shape/base.rb +16 -0
  20. data/lib/thinreports/core/shape/base/interface.rb +38 -0
  21. data/lib/thinreports/core/shape/base/internal.rb +60 -0
  22. data/lib/thinreports/core/shape/basic.rb +15 -0
  23. data/lib/thinreports/core/shape/basic/format.rb +26 -0
  24. data/lib/thinreports/core/shape/basic/interface.rb +57 -0
  25. data/lib/thinreports/core/shape/basic/internal.rb +29 -0
  26. data/lib/thinreports/core/shape/list.rb +25 -0
  27. data/lib/thinreports/core/shape/list/configuration.rb +33 -0
  28. data/lib/thinreports/core/shape/list/events.rb +30 -0
  29. data/lib/thinreports/core/shape/list/format.rb +72 -0
  30. data/lib/thinreports/core/shape/list/manager.rb +209 -0
  31. data/lib/thinreports/core/shape/list/page.rb +118 -0
  32. data/lib/thinreports/core/shape/list/page_state.rb +40 -0
  33. data/lib/thinreports/core/shape/list/section_format.rb +32 -0
  34. data/lib/thinreports/core/shape/list/section_interface.rb +48 -0
  35. data/lib/thinreports/core/shape/list/section_internal.rb +29 -0
  36. data/lib/thinreports/core/shape/list/store.rb +34 -0
  37. data/lib/thinreports/core/shape/manager.rb +14 -0
  38. data/lib/thinreports/core/shape/manager/format.rb +28 -0
  39. data/lib/thinreports/core/shape/manager/internal.rb +87 -0
  40. data/lib/thinreports/core/shape/manager/target.rb +85 -0
  41. data/lib/thinreports/core/shape/tblock.rb +16 -0
  42. data/lib/thinreports/core/shape/tblock/format.rb +36 -0
  43. data/lib/thinreports/core/shape/tblock/formatter.rb +32 -0
  44. data/lib/thinreports/core/shape/tblock/formatter/basic.rb +38 -0
  45. data/lib/thinreports/core/shape/tblock/formatter/datetime.rb +21 -0
  46. data/lib/thinreports/core/shape/tblock/formatter/number.rb +49 -0
  47. data/lib/thinreports/core/shape/tblock/formatter/padding.rb +43 -0
  48. data/lib/thinreports/core/shape/tblock/interface.rb +52 -0
  49. data/lib/thinreports/core/shape/tblock/internal.rb +70 -0
  50. data/lib/thinreports/core/shape/text.rb +15 -0
  51. data/lib/thinreports/core/shape/text/format.rb +25 -0
  52. data/lib/thinreports/core/shape/text/interface.rb +16 -0
  53. data/lib/thinreports/core/shape/text/internal.rb +17 -0
  54. data/lib/thinreports/core/utils.rb +48 -0
  55. data/lib/thinreports/generator.rb +30 -0
  56. data/lib/thinreports/generator/base.rb +49 -0
  57. data/lib/thinreports/generator/pdf.rb +63 -0
  58. data/lib/thinreports/generator/pdf/document.rb +171 -0
  59. data/lib/thinreports/generator/pdf/document/draw_shape.rb +74 -0
  60. data/lib/thinreports/generator/pdf/document/font.rb +59 -0
  61. data/lib/thinreports/generator/pdf/document/graphics.rb +42 -0
  62. data/lib/thinreports/generator/pdf/document/graphics/attributes.rb +92 -0
  63. data/lib/thinreports/generator/pdf/document/graphics/basic.rb +132 -0
  64. data/lib/thinreports/generator/pdf/document/graphics/image.rb +51 -0
  65. data/lib/thinreports/generator/pdf/document/graphics/text.rb +130 -0
  66. data/lib/thinreports/generator/pdf/document/parse_color.rb +51 -0
  67. data/lib/thinreports/generator/pdf/document/parse_svg.rb +102 -0
  68. data/lib/thinreports/generator/pdf/drawer.rb +16 -0
  69. data/lib/thinreports/generator/pdf/drawer/base.rb +56 -0
  70. data/lib/thinreports/generator/pdf/drawer/list.rb +39 -0
  71. data/lib/thinreports/generator/pdf/drawer/list_section.rb +46 -0
  72. data/lib/thinreports/generator/pdf/drawer/page.rb +101 -0
  73. data/lib/thinreports/generator/pdf/prawn_ext.rb +36 -0
  74. data/lib/thinreports/generator/pxd.rb +75 -0
  75. data/lib/thinreports/generator/pxd/helper.rb +33 -0
  76. data/lib/thinreports/generator/pxd/list_renderer.rb +58 -0
  77. data/lib/thinreports/generator/pxd/page_renderer.rb +75 -0
  78. data/lib/thinreports/layout.rb +17 -0
  79. data/lib/thinreports/layout/base.rb +78 -0
  80. data/lib/thinreports/layout/configuration.rb +27 -0
  81. data/lib/thinreports/layout/format.rb +77 -0
  82. data/lib/thinreports/layout/version.rb +43 -0
  83. data/lib/thinreports/report.rb +31 -0
  84. data/lib/thinreports/report/base.rb +160 -0
  85. data/lib/thinreports/report/events.rb +32 -0
  86. data/lib/thinreports/report/internal.rb +131 -0
  87. data/resources/fonts/IPA_Font_License_Agreement_v1.0.txt +117 -0
  88. data/resources/fonts/ipag.ttf +0 -0
  89. data/resources/fonts/ipagp.ttf +0 -0
  90. data/resources/fonts/ipam.ttf +0 -0
  91. data/resources/fonts/ipamp.ttf +0 -0
  92. data/tasks/clean.rake +6 -0
  93. data/tasks/doc.rake +13 -0
  94. data/tasks/test.rake +18 -0
  95. data/test/unit/core/ext/array_spec.rb +29 -0
  96. data/test/unit/core/ext/hash_spec.rb +29 -0
  97. data/test/unit/core/ext/object_spec.rb +30 -0
  98. data/test/unit/core/format/test_base.rb +148 -0
  99. data/test/unit/core/format/test_builder.rb +114 -0
  100. data/test/unit/core/ordered_hash_spec.rb +51 -0
  101. data/test/unit/core/shape/base/test_interface.rb +52 -0
  102. data/test/unit/core/shape/base/test_internal.rb +109 -0
  103. data/test/unit/core/shape/basic/test_format.rb +59 -0
  104. data/test/unit/core/shape/basic/test_interface.rb +70 -0
  105. data/test/unit/core/shape/basic/test_internal.rb +42 -0
  106. data/test/unit/core/shape/list/test_configuration.rb +52 -0
  107. data/test/unit/core/shape/list/test_events.rb +28 -0
  108. data/test/unit/core/shape/list/test_format.rb +71 -0
  109. data/test/unit/core/shape/list/test_page.rb +10 -0
  110. data/test/unit/core/shape/list/test_page_state.rb +31 -0
  111. data/test/unit/core/shape/list/test_section_format.rb +46 -0
  112. data/test/unit/core/shape/list/test_section_interface.rb +52 -0
  113. data/test/unit/core/shape/list/test_section_internal.rb +30 -0
  114. data/test/unit/core/shape/list/test_store.rb +41 -0
  115. data/test/unit/core/shape/manager/test_format.rb +40 -0
  116. data/test/unit/core/shape/manager/test_internal.rb +137 -0
  117. data/test/unit/core/shape/manager/test_target.rb +109 -0
  118. data/test/unit/core/shape/tblock/formatter/test_basic.rb +24 -0
  119. data/test/unit/core/shape/tblock/formatter/test_datetime.rb +47 -0
  120. data/test/unit/core/shape/tblock/formatter/test_number.rb +76 -0
  121. data/test/unit/core/shape/tblock/formatter/test_padding.rb +72 -0
  122. data/test/unit/core/shape/tblock/test_format.rb +125 -0
  123. data/test/unit/core/shape/tblock/test_formatter.rb +28 -0
  124. data/test/unit/core/shape/tblock/test_interface.rb +40 -0
  125. data/test/unit/core/shape/tblock/test_internal.rb +139 -0
  126. data/test/unit/core/shape/text/test_format.rb +73 -0
  127. data/test/unit/core/shape/text/test_internal.rb +21 -0
  128. data/test/unit/core/test_events.rb +91 -0
  129. data/test/unit/core/test_shape.rb +35 -0
  130. data/test/unit/core/utils_spec.rb +56 -0
  131. data/test/unit/generator/pdf/document/graphics/test_attributes.rb +103 -0
  132. data/test/unit/generator/pdf/document/test_font.rb +54 -0
  133. data/test/unit/generator/pdf/document/test_graphics.rb +43 -0
  134. data/test/unit/generator/pdf/document/test_parse_color.rb +30 -0
  135. data/test/unit/generator/test_base.rb +51 -0
  136. data/test/unit/helper.rb +37 -0
  137. data/test/unit/layout/test_base.rb +92 -0
  138. data/test/unit/layout/test_configuration.rb +46 -0
  139. data/test/unit/layout/test_format.rb +104 -0
  140. data/test/unit/layout/test_version.rb +62 -0
  141. data/test/unit/report/test_base.rb +187 -0
  142. data/test/unit/report/test_events.rb +22 -0
  143. data/test/unit/report/test_internal.rb +234 -0
  144. data/test/unit/test_layout.rb +12 -0
  145. data/test/unit/test_report.rb +30 -0
  146. metadata +218 -0
@@ -0,0 +1,51 @@
1
+ # coding: utf-8
2
+
3
+ module ThinReports
4
+ module Generator
5
+
6
+ # @private
7
+ module Pdf::ParseColor
8
+ # @param [String] color
9
+ # @return [String]
10
+ def parse_color(color)
11
+ color = color.downcase
12
+
13
+ unless color =~ /^#?[\da-f]{6}$/
14
+ find_color_from_name(color)
15
+ else
16
+ color.delete('#')
17
+ end
18
+ end
19
+
20
+ private
21
+
22
+ # Supported only SAFE COLORS.
23
+ SUPPORTED_COLOR_NAMES = {
24
+ 'red' => 'ff0000',
25
+ 'yellow' => 'fff000',
26
+ 'lime' => '00ff00',
27
+ 'aqua' => '00ffff',
28
+ 'blue' => '0000ff',
29
+ 'fuchsia' => 'ff00ff',
30
+ 'maroon' => '800000',
31
+ 'olive' => '808000',
32
+ 'green' => '008800',
33
+ 'teal' => '008080',
34
+ 'navy' => '000080',
35
+ 'purple' => '800080',
36
+ 'black' => '000000',
37
+ 'gray' => '808080',
38
+ 'silver' => 'c0c0c0',
39
+ 'white' => 'ffffff'
40
+ }
41
+
42
+ def find_color_from_name(name)
43
+ unless color = SUPPORTED_COLOR_NAMES[name]
44
+ raise ThinReports::Errors::UnsupportedColorName, name
45
+ end
46
+ color
47
+ end
48
+ end
49
+
50
+ end
51
+ end
@@ -0,0 +1,102 @@
1
+ # coding: utf-8
2
+
3
+ require 'rexml/document'
4
+
5
+ module ThinReports
6
+ module Generator
7
+
8
+ # @private
9
+ module Pdf::ParseSVG
10
+ # @param [String] source
11
+ # @param [String] base_path
12
+ def parse_svg(source, base_path)
13
+ svg = REXML::Document.new(clean_svg(source))
14
+
15
+ svg.elements[base_path].each do |elm|
16
+ case elm.attributes['class']
17
+ when 's-text' then draw_svg_text(elm)
18
+ when 's-image' then draw_svg_image(elm)
19
+ when 's-rect' then draw_svg_rect(elm)
20
+ when 's-ellipse' then draw_svg_ellipse(elm)
21
+ when 's-line' then draw_svg_line(elm)
22
+ end
23
+ end
24
+ svg = nil
25
+ end
26
+
27
+ private
28
+
29
+ # @param [String] source
30
+ # @return [String]
31
+ def clean_svg(source)
32
+ source.gsub(/<%.+?%>/, '')
33
+ end
34
+
35
+ # @param [REXML::Element] elm
36
+ # @param [Array<String>] keys
37
+ # @return [Array<String>]
38
+ def element_attributes_values_at(elm, *keys)
39
+ attrs = elm.attributes
40
+ keys.inject([]) do |values, key|
41
+ values << attrs[key]
42
+ end
43
+ end
44
+
45
+ # @param [REXML::Element] svg_elm
46
+ def draw_svg_rect(elm)
47
+ x, y, w, h = element_attributes_values_at(elm, 'x', 'y', 'width', 'height')
48
+ attributes = common_graphic_attrs(elm.attributes) do |attrs|
49
+ attrs[:radius] = elm.attributes['rx']
50
+ end
51
+ rect(x, y, w, h, attributes)
52
+ end
53
+
54
+ # @see #draw_svg_rect
55
+ def draw_svg_ellipse(elm)
56
+ x, y, rx, ry = element_attributes_values_at(elm, 'cx', 'cy', 'rx', 'ry')
57
+ ellipse(x, y, rx, ry,
58
+ common_graphic_attrs(elm.attributes))
59
+ end
60
+
61
+ # @see #draw_svg_rect
62
+ def draw_svg_line(elm)
63
+ x1, y1, x2, y2 = element_attributes_values_at(elm, 'x1', 'y1', 'x2', 'y2')
64
+ line(x1, y1, x2, y2,
65
+ common_graphic_attrs(elm.attributes))
66
+ end
67
+
68
+ # @see #draw_svg_rect
69
+ def draw_svg_text(elm)
70
+ x, y, w, h = element_attributes_values_at(elm, 'x-left', 'x-top',
71
+ 'x-width', 'x-height')
72
+ content = []
73
+ elm.each_element('text') do |text_elm|
74
+ content << text_elm.text
75
+ end
76
+ text(content.join("\n"), x, y, w, h, svg_text_attrs(elm.attributes))
77
+ end
78
+
79
+ # @see #draw_svg_rect
80
+ def draw_svg_image(elm)
81
+ x, y, w, h = element_attributes_values_at(elm, 'x', 'y', 'width', 'height')
82
+ base64image(extract_base64_string(elm.attributes['xlink:href']),
83
+ x, y, w, h)
84
+ end
85
+
86
+ # @param [Hash] attributes
87
+ # @return [Hash]
88
+ def svg_text_attrs(attributes)
89
+ common_text_attrs(attributes) do |attrs|
90
+ # Set the :line_height option.
91
+ if height = attributes['x-line-height']
92
+ attrs[:line_height] = height unless height == 'normal'
93
+ end
94
+ # Set the :valign option.
95
+ attrs[:valign] = text_valign(attributes['x-valign'])
96
+ end
97
+ end
98
+
99
+ end
100
+
101
+ end
102
+ end
@@ -0,0 +1,16 @@
1
+ # coding: utf-8
2
+
3
+ module ThinReports
4
+ module Generator
5
+
6
+ # @private
7
+ module Pdf::Drawer
8
+ end
9
+
10
+ end
11
+ end
12
+
13
+ require 'thinreports/generator/pdf/drawer/base'
14
+ require 'thinreports/generator/pdf/drawer/page'
15
+ require 'thinreports/generator/pdf/drawer/list'
16
+ require 'thinreports/generator/pdf/drawer/list_section'
@@ -0,0 +1,56 @@
1
+ # coding: utf-8
2
+
3
+ module ThinReports
4
+ module Generator
5
+
6
+ # @abstract
7
+ # @private
8
+ class Pdf::Drawer::Base
9
+ # @param [ThinReports::Generator::Pdf::Document] pdf
10
+ # @param [ThinReports::Core::Shape::Manager::Format] format
11
+ def initialize(pdf, format)
12
+ @pdf = pdf
13
+ @format = format
14
+ @stamps = []
15
+ @draw_at = nil
16
+ end
17
+
18
+ # @abstract
19
+ def draw
20
+ raise NotImplementedError
21
+ end
22
+
23
+ private
24
+
25
+ # @param [ThinReports::Core::Shape::Base::Internal] shape
26
+ # @return [String]
27
+ def pdf_stamp_id(shape)
28
+ "#{@format.identifier}#{shape_stamp_id(shape)}"
29
+ end
30
+
31
+ # @see #pdf_stamp_id
32
+ def shape_stamp_id(shape)
33
+ id = shape.id.dup
34
+ id << shape.attrs.values_at('fill', 'stroke').join unless shape.attrs.empty?
35
+ id.gsub(/#/, '')
36
+ end
37
+
38
+ # @overload pdf_stamp('stamp_id')
39
+ # @param [String] shape
40
+ # @overload pdf_stamp(shape)
41
+ # @param [ThinReports::Core::Shape::Base::Internal] shape
42
+ def pdf_stamp(shape)
43
+ unless shape.is_a?(::String)
44
+ shape = pdf_stamp_id(shape)
45
+ end
46
+ @pdf.stamp(shape, @draw_at)
47
+ end
48
+
49
+ # @param [ThinReports::Core::Shape::Base::Internal] shape
50
+ def create_pdf_stamp(shape, &block)
51
+ @pdf.create_stamp(pdf_stamp_id(shape), &block)
52
+ end
53
+ end
54
+
55
+ end
56
+ end
@@ -0,0 +1,39 @@
1
+ # coding: utf-8
2
+
3
+ module ThinReports
4
+ module Generator
5
+
6
+ # @private
7
+ class Pdf::Drawer::List < Pdf::Drawer::Base
8
+ # @param (see Pdf::Drawer::Base#initialize)
9
+ def initialize(pdf, format)
10
+ super
11
+ @sections = {}
12
+ end
13
+
14
+ # @param [ThinReports::Core::Shape::List::PageState] list
15
+ def draw(list)
16
+ draw_section(list.header) if list.header
17
+ list.rows.each do |row|
18
+ draw_section(row)
19
+ end
20
+ end
21
+
22
+ private
23
+
24
+ # @param [ThinReports::Core::Shape::List::SectionInterface] section
25
+ def draw_section(section)
26
+ internal = section.internal
27
+ drawer(internal).draw(section.manager, internal.relative_position)
28
+ end
29
+
30
+ # @param [ThinReports::Core::Shape::List::SectionInternal] section
31
+ # @return [ThinReports::Generator::Pdf::Drawer::ListSection]
32
+ def drawer(section)
33
+ @sections[section.section_name] ||=
34
+ Pdf::Drawer::ListSection.new(@pdf, section)
35
+ end
36
+ end
37
+
38
+ end
39
+ end
@@ -0,0 +1,46 @@
1
+ # coding: utf-8
2
+
3
+ module ThinReports
4
+ module Generator
5
+
6
+ # @private
7
+ class Pdf::Drawer::ListSection < Pdf::Drawer::Page
8
+ # @param pdf (see Pdf::Drawer::Page#initialize)
9
+ # @param section [ThinReports::Core::Shape::List::SectionInternal] section
10
+ def initialize(pdf, section)
11
+ super(pdf, section.format)
12
+ @section = section
13
+ @stamp_created = false
14
+ end
15
+
16
+ # @param [ThinReports::Core::Shape::Manager::Internal] manager
17
+ # @param [Array<Numeric>] at
18
+ def draw(manager, at)
19
+ @draw_at = at
20
+ draw_section
21
+ super(manager)
22
+ end
23
+
24
+ private
25
+
26
+ def draw_section
27
+ id = @format.identifier.to_s
28
+
29
+ unless @stamp_created
30
+ @pdf.create_stamp(id) do
31
+ @pdf.parse_svg('<svg xmlns:xlink="http://www.w3.org/1999/xlink">' +
32
+ "#{@format.layout}</svg>", '/svg')
33
+ end
34
+ @stamp_created = true
35
+ end
36
+ pdf_stamp(id)
37
+ end
38
+
39
+ # @see ThinReports::Generator::Pdf::Drawer::Page#draw_tblock_shape
40
+ def draw_tblock_shape(shape)
41
+ @pdf.translate(*@draw_at) { super }
42
+ end
43
+ end
44
+
45
+ end
46
+ end
@@ -0,0 +1,101 @@
1
+ # coding: utf-8
2
+
3
+ module ThinReports
4
+ module Generator
5
+
6
+ # @private
7
+ class Pdf::Drawer::Page < Pdf::Drawer::Base
8
+ # @param see Pdf::Drawer::Base#initialize)
9
+ def initialize(pdf, format)
10
+ super
11
+ @lists = {}
12
+ end
13
+
14
+ # @param [ThinReports::Core::Shape::Manager::Internal] manager
15
+ def draw(manager)
16
+ manager.format.shapes.each_key do |id|
17
+ if shape = manager.final_shape(id)
18
+ draw_shape(shape.internal)
19
+ end
20
+ end
21
+ end
22
+
23
+ private
24
+
25
+ # @param [ThinReports::Core::Shape::Base::Internal] shape
26
+ def draw_shape(shape)
27
+ case
28
+ when shape.type_of?(:tblock)
29
+ draw_tblock_shape(shape)
30
+ when shape.type_of?(:list)
31
+ draw_list_shape(shape)
32
+ else
33
+ id = shape_stamp_id(shape)
34
+ unless @stamps.include?(id)
35
+ create_basic_shape_stamp(shape)
36
+ @stamps << id
37
+ end
38
+ pdf_stamp(shape)
39
+ end
40
+ end
41
+
42
+ # @see #draw_shape
43
+ def draw_list_shape(shape)
44
+ drawer = @lists[shape.id] ||= Pdf::Drawer::List.new(@pdf, shape.format)
45
+ drawer.draw(shape)
46
+ end
47
+
48
+ # @see #draw_shape
49
+ def draw_tblock_shape(shape)
50
+ @pdf.draw_shape_tblock(shape)
51
+ end
52
+
53
+ # @param [ThinReports::Core::Shape::Base::Internal] shape
54
+ def create_basic_shape_stamp(shape)
55
+ case
56
+ when shape.type_of?(:text) then create_text_stamp(shape)
57
+ when shape.type_of?(:image) then create_image_stamp(shape)
58
+ when shape.type_of?(:ellipse) then create_ellipse_stamp(shape)
59
+ when shape.type_of?(:rect) then create_rect_stamp(shape)
60
+ when shape.type_of?(:line) then create_line_stamp(shape)
61
+ end
62
+ end
63
+
64
+ # @see #create_basic_shape_stamp
65
+ def create_image_stamp(shape)
66
+ create_pdf_stamp(shape) do
67
+ @pdf.draw_shape_image(shape)
68
+ end
69
+ end
70
+
71
+ # @see #create_basic_shape_stamp
72
+ def create_rect_stamp(shape)
73
+ create_pdf_stamp(shape) do
74
+ @pdf.draw_shape_rect(shape)
75
+ end
76
+ end
77
+
78
+ # @see #create_basic_shape_stamp
79
+ def create_ellipse_stamp(shape)
80
+ create_pdf_stamp(shape) do
81
+ @pdf.draw_shape_ellipse(shape)
82
+ end
83
+ end
84
+
85
+ # @see #create_basic_shape_stamp
86
+ def create_line_stamp(shape)
87
+ create_pdf_stamp(shape) do
88
+ @pdf.draw_shape_line(shape)
89
+ end
90
+ end
91
+
92
+ # @see #create_basic_shape_stamp
93
+ def create_text_stamp(shape)
94
+ create_pdf_stamp(shape) do
95
+ @pdf.draw_shape_text(shape)
96
+ end
97
+ end
98
+ end
99
+
100
+ end
101
+ end
@@ -0,0 +1,36 @@
1
+ # coding: utf-8
2
+
3
+ # @private
4
+ module Prawn
5
+ # Patch for issue {https://github.com/sandal/prawn/issues/245 #245}.
6
+ # @private
7
+ class Font::TTF
8
+ def character_width_by_code(code)
9
+ return 0 unless cmap[code]
10
+ return 0.0 if code == 10
11
+ @char_widths[code] ||= Integer(hmtx.widths[cmap[code]] * scale_factor)
12
+ end
13
+ end
14
+
15
+ # @private
16
+ class Document
17
+ # Create around alias.
18
+ alias_method :original_width_of, :width_of
19
+
20
+ # For Ruby 1.8
21
+ ruby_18 do
22
+ def width_of(string, options={})
23
+ str_length = in_utf8 { string.split(//).size }
24
+ font.compute_width_of(string, options) + character_spacing * (str_length - 1)
25
+ end
26
+ end
27
+
28
+ # For Ruby 1.9
29
+ ruby_19 do
30
+ def width_of(string, options={})
31
+ font.compute_width_of(string, options) + character_spacing * (string.length - 1)
32
+ end
33
+ end
34
+ end
35
+
36
+ end