rrtf 0.1.2 → 1.0.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.
Files changed (137) hide show
  1. checksums.yaml +4 -4
  2. data/.byebug_history +6 -3
  3. data/CHANGELOG.md +24 -0
  4. data/README.md +194 -84
  5. data/documentation/RRTF.html +5 -5
  6. data/documentation/RRTF/AnonymousStyle.html +792 -0
  7. data/documentation/RRTF/BorderFormatting.html +821 -0
  8. data/documentation/RRTF/BorderStyle.html +493 -0
  9. data/documentation/RRTF/CharacterFormatting.html +293 -162
  10. data/documentation/RRTF/CharacterStyle.html +53 -109
  11. data/documentation/RRTF/Colour.html +61 -1
  12. data/documentation/RRTF/ColourTable.html +52 -52
  13. data/documentation/RRTF/CommandNode.html +367 -971
  14. data/documentation/RRTF/ContainerNode.html +44 -44
  15. data/documentation/RRTF/Converters.html +1 -1
  16. data/documentation/RRTF/Converters/HTML.html +1 -1
  17. data/documentation/RRTF/Converters/HTML/Helpers.html +1 -1
  18. data/documentation/RRTF/Converters/HTML/Node.html +1 -1
  19. data/documentation/RRTF/Converters/HTML/NodeSet.html +1 -1
  20. data/documentation/RRTF/Document.html +267 -255
  21. data/documentation/RRTF/DocumentFormatting.html +833 -0
  22. data/documentation/RRTF/DocumentProperties.html +444 -0
  23. data/documentation/RRTF/Font.html +1 -1
  24. data/documentation/RRTF/FontTable.html +1 -1
  25. data/documentation/RRTF/FooterNode.html +16 -16
  26. data/documentation/RRTF/GeometryNode.html +774 -0
  27. data/documentation/RRTF/GeometryProperties.html +1014 -0
  28. data/documentation/RRTF/HeaderNode.html +16 -16
  29. data/documentation/RRTF/ImageNode.html +705 -492
  30. data/documentation/RRTF/Information.html +1 -1
  31. data/documentation/RRTF/LinkNode.html +10 -10
  32. data/documentation/RRTF/ListLevel.html +1 -1
  33. data/documentation/RRTF/ListLevelNode.html +37 -37
  34. data/documentation/RRTF/ListMarker.html +1 -1
  35. data/documentation/RRTF/ListNode.html +19 -19
  36. data/documentation/RRTF/ListTable.html +1 -1
  37. data/documentation/RRTF/ListTemplate.html +1 -1
  38. data/documentation/RRTF/ListTextNode.html +14 -14
  39. data/documentation/RRTF/Node.html +26 -26
  40. data/documentation/RRTF/Page.html +129 -0
  41. data/documentation/RRTF/Page/Margin.html +1158 -0
  42. data/documentation/RRTF/Page/Size.html +946 -0
  43. data/documentation/RRTF/PageFormatting.html +954 -0
  44. data/documentation/RRTF/ParagraphFormatting.html +338 -56
  45. data/documentation/RRTF/ParagraphNode.html +10 -10
  46. data/documentation/RRTF/ParagraphStyle.html +72 -111
  47. data/documentation/RRTF/PositionFormatting.html +780 -0
  48. data/documentation/RRTF/PositionStyle.html +424 -0
  49. data/documentation/RRTF/Properties.html +243 -0
  50. data/documentation/RRTF/RTFError.html +21 -10
  51. data/documentation/RRTF/ShadingFormatting.html +712 -0
  52. data/documentation/RRTF/ShadingStyle.html +424 -0
  53. data/documentation/RRTF/Style.html +284 -697
  54. data/documentation/RRTF/Stylesheet.html +36 -3
  55. data/documentation/RRTF/TableCellNode.html +131 -131
  56. data/documentation/RRTF/TableNode.html +82 -82
  57. data/documentation/RRTF/TableRowNode.html +53 -53
  58. data/documentation/RRTF/TextNode.html +46 -46
  59. data/documentation/RRTF/Utilities.html +837 -17
  60. data/documentation/_index.html +139 -6
  61. data/documentation/class_list.html +1 -1
  62. data/documentation/file.README.html +218 -87
  63. data/documentation/index.html +218 -87
  64. data/documentation/method_list.html +631 -391
  65. data/documentation/top-level-namespace.html +1 -1
  66. data/examples/01.rtf +947 -20
  67. data/examples/01_everything.rb +176 -0
  68. data/examples/02.rtf +13 -0
  69. data/examples/02_basic_paragraph.rb +10 -0
  70. data/examples/03.rtf +20 -0
  71. data/examples/03_paragraph_inline_style.rb +14 -0
  72. data/examples/04.rtf +21 -0
  73. data/examples/04_paragraph_with_character_style.rb +18 -0
  74. data/examples/05.rtf +21 -0
  75. data/examples/05_hyperlinks.rb +21 -0
  76. data/examples/06.rtf +21 -0
  77. data/examples/06_basic_list.rb +21 -0
  78. data/examples/07.rtf +28 -0
  79. data/examples/07_nested_list.rb +27 -0
  80. data/examples/08.rtf +807 -0
  81. data/examples/08_images.rb +17 -0
  82. data/examples/09.rtf +84 -0
  83. data/examples/09_shapes.rb +56 -0
  84. data/examples/10.rtf +34 -0
  85. data/examples/10_stylesheet.rb +18 -0
  86. data/examples/resources/images/redshirt.png +0 -0
  87. data/examples/resources/images/redshirts.jpg +0 -0
  88. data/examples/resources/json/redshirt_styles.json +72 -8
  89. data/examples/~$01.rtf +0 -0
  90. data/lib/rrtf.rb +4 -16
  91. data/lib/rrtf/colour.rb +8 -0
  92. data/lib/rrtf/formatting.rb +988 -0
  93. data/lib/rrtf/node.rb +17 -1851
  94. data/lib/rrtf/node/command_node.rb +242 -0
  95. data/lib/rrtf/node/container_node.rb +75 -0
  96. data/lib/rrtf/node/document.rb +339 -0
  97. data/lib/rrtf/node/footer_node.rb +47 -0
  98. data/lib/rrtf/node/geometry_node.rb +65 -0
  99. data/lib/rrtf/node/header_node.rb +47 -0
  100. data/lib/rrtf/node/image_node.rb +175 -0
  101. data/lib/rrtf/node/link_node.rb +10 -0
  102. data/lib/rrtf/node/list_level_node.rb +44 -0
  103. data/lib/rrtf/node/list_node.rb +30 -0
  104. data/lib/rrtf/node/list_text_node.rb +22 -0
  105. data/lib/rrtf/node/node.rb +53 -0
  106. data/lib/rrtf/node/paragraph_node.rb +11 -0
  107. data/lib/rrtf/node/table_cell_node.rb +233 -0
  108. data/lib/rrtf/node/table_node.rb +136 -0
  109. data/lib/rrtf/node/table_row_node.rb +92 -0
  110. data/lib/rrtf/node/text_node.rb +76 -0
  111. data/lib/rrtf/page.rb +7 -0
  112. data/lib/rrtf/page/margin.rb +98 -0
  113. data/lib/rrtf/page/size.rb +98 -0
  114. data/lib/rrtf/properties.rb +3 -0
  115. data/lib/rrtf/properties/document_properties.rb +34 -0
  116. data/lib/rrtf/properties/geometry_properties.rb +380 -0
  117. data/lib/rrtf/properties/properties.rb +13 -0
  118. data/lib/rrtf/style.rb +4 -5
  119. data/lib/rrtf/style/anonymous_style.rb +73 -0
  120. data/lib/rrtf/style/border_style.rb +27 -0
  121. data/lib/rrtf/style/character_style.rb +1 -7
  122. data/lib/rrtf/style/paragraph_style.rb +0 -6
  123. data/lib/rrtf/style/position_style.rb +26 -0
  124. data/lib/rrtf/style/shading_style.rb +26 -0
  125. data/lib/rrtf/style/style.rb +60 -101
  126. data/lib/rrtf/utilities.rb +138 -0
  127. data/lib/rrtf/version.rb +1 -1
  128. data/rrtf.gemspec +1 -0
  129. metadata +85 -10
  130. data/examples/01_mac_libreoffice5_2_3_3.png +0 -0
  131. data/examples/01_mac_pages6_2.png +0 -0
  132. data/examples/01_mac_textedit1_12.png +0 -0
  133. data/examples/01_mac_word15_36.png +0 -0
  134. data/examples/01_styles_and_paragraphs.rb +0 -32
  135. data/lib/rrtf/paper.rb +0 -53
  136. data/lib/rrtf/style/document_style.rb +0 -116
  137. data/lib/rrtf/style/formatting.rb +0 -320
@@ -0,0 +1,13 @@
1
+ module RRTF
2
+ # Parent class from which all properties classes derive.
3
+ # @author Wesley Hileman
4
+ # @abstract
5
+ class Properties
6
+ # Converts a properties object into an RTF sequence. Override in derived
7
+ # classes.
8
+ # @abstract
9
+ def to_rtf
10
+ nil
11
+ end
12
+ end # class Properties
13
+ end # module RRTF
@@ -1,8 +1,7 @@
1
- require 'rrtf/style/formatting'
1
+ require 'rrtf/style/anonymous_style'
2
+ require 'rrtf/style/border_style'
3
+ require 'rrtf/style/position_style'
4
+ require 'rrtf/style/shading_style'
2
5
  require 'rrtf/style/style'
3
6
  require 'rrtf/style/paragraph_style'
4
7
  require 'rrtf/style/character_style'
5
- require 'rrtf/style/document_style'
6
-
7
- module RRTF
8
- end
@@ -0,0 +1,73 @@
1
+ module RRTF
2
+ # Represents an arbitrary style that can be applied to an element within an
3
+ # RTF document (e.g. paragraph, characters, border, table, etc.)
4
+ #
5
+ # @author Wesley Hileman
6
+ # @since 1.0.0
7
+ # @abstract
8
+ class AnonymousStyle
9
+ # Constructor (empty for now).
10
+ def initialize(options = {})
11
+ end
12
+
13
+ # This method retrieves the command prefix text associated with a Style
14
+ # object. This method always returns nil and should be overridden by
15
+ # derived classes as needed.
16
+ # @abstract
17
+ def prefix(document)
18
+ nil
19
+ end
20
+
21
+ # This method retrieves the command suffix text associated with a Style
22
+ # object. This method always returns nil and should be overridden by
23
+ # derived classes as needed.
24
+ # @abstract
25
+ def suffix(document)
26
+ nil
27
+ end
28
+
29
+ # Generates a string containing an RTF sequence that describes the
30
+ # formatting present in the style. Override in derived classes.
31
+ # @abstract
32
+ def rtf_formatting
33
+ nil
34
+ end
35
+
36
+ # Pushes the colour objects present in formatting attributes onto the
37
+ # supplied colour table.
38
+ # @note All colours used in an RTF document must appear in the document's
39
+ # header as a colour table. This method assists in generating that table.
40
+ #
41
+ # @param [ColourTable] colours the table in which the formatting
42
+ # colours will be stored.
43
+ def push_colours(colours)
44
+ colours << foreground_color unless !respond_to?(:foreground_color) || foreground_color.nil?
45
+ colours << background_color unless !respond_to?(:background_color) || background_color.nil?
46
+ colours << underline_color unless !respond_to?(:underline_color) || underline_color.nil?
47
+ colours << highlight_color unless !respond_to?(:highlight_color) || highlight_color.nil?
48
+ colours << color unless !respond_to?(:color) || color.nil?
49
+
50
+ # border
51
+ border.each do |b|
52
+ colours << b.color unless b.color.nil?
53
+ end unless !respond_to?(:border) || border.nil?
54
+
55
+ # shading
56
+ unless !respond_to?(:shading) || shading.nil?
57
+ colours << shading.background_color unless shading.background_color.nil?
58
+ colours << shading.foreground_color unless shading.foreground_color.nil?
59
+ end
60
+ end
61
+
62
+ # Pushes the font objects present in formatting attributes onto the
63
+ # supplied font table.
64
+ # @note All fonts used in an RTF document must appear in the document's
65
+ # header as a font table. This method assists in generating that table.
66
+ #
67
+ # @param [FontTable] fonts the table in which the character formatting
68
+ # fonts will be stored.
69
+ def push_fonts(fonts)
70
+ fonts << font unless font.nil?
71
+ end
72
+ end
73
+ end # module RRTF
@@ -0,0 +1,27 @@
1
+ module RRTF
2
+ # Represents a set of formatting that can be applied to paragraph and table
3
+ # borders
4
+ class BorderStyle < AnonymousStyle
5
+ include BorderFormatting
6
+
7
+ # This is the constructor for the BorderStyle class.
8
+ #
9
+ # @param [Hash] options the character style options.
10
+ # @option options (see AnonymousStyle#initialize)
11
+ # @option options (see BorderFormatting#initialize_border_formatting)
12
+ def initialize(options = {})
13
+ super(options)
14
+ initialize_border_formatting(options)
15
+ end
16
+
17
+ # This method generates a string containing the prefix associated with the
18
+ # style object. Equivalent to {#rtf_formatting} for the BorderStyle class.
19
+ def prefix(document)
20
+ rtf_formatting(document)
21
+ end
22
+
23
+ def rtf_formatting(document)
24
+ border_formatting_to_rtf(document)
25
+ end
26
+ end # class BorderStyle
27
+ end # module RRTF
@@ -15,12 +15,6 @@ module RRTF
15
15
  initialize_character_formatting(options)
16
16
  end
17
17
 
18
- # This method overrides the is_character_style? method inherited from the
19
- # Style class to always return true.
20
- def is_character_style?
21
- true
22
- end
23
-
24
18
  # Converts the stylesheet character style into its RTF representation
25
19
  # (for stylesheet)
26
20
  def to_rtf(document, options = {})
@@ -51,7 +45,7 @@ module RRTF
51
45
  rtf.string
52
46
  end
53
47
 
54
- # This method generates a string containing the prefix associated with a
48
+ # This method generates a string containing the prefix associated with the
55
49
  # style object.
56
50
  def prefix(document)
57
51
  text = StringIO.new
@@ -21,12 +21,6 @@ module RRTF
21
21
  initialize_character_formatting(options)
22
22
  end
23
23
 
24
- # This method overrides the is_paragraph_style? method inherited from the
25
- # Style class to always return true.
26
- def is_paragraph_style?
27
- true
28
- end
29
-
30
24
  # Converts the stylesheet paragraph style into its RTF representation
31
25
  #
32
26
  # ==== Parameters
@@ -0,0 +1,26 @@
1
+ module RRTF
2
+ # Represents a set of formatting that can be applied to position paragraphs.
3
+ class PositionStyle < AnonymousStyle
4
+ include PositionFormatting
5
+
6
+ # This is the constructor for the PositionStyle class.
7
+ #
8
+ # @param [Hash] options the position style options.
9
+ # @option options (see AnonymousStyle#initialize)
10
+ # @option options (see PositionFormatting#initialize_position_formatting)
11
+ def initialize(options = {})
12
+ super(options)
13
+ initialize_position_formatting(options)
14
+ end
15
+
16
+ # This method generates a string containing the prefix associated with the
17
+ # style object. Equivalent to {#rtf_formatting} for the PositionStyle class.
18
+ def prefix(document)
19
+ rtf_formatting(document)
20
+ end
21
+
22
+ def rtf_formatting(document)
23
+ position_formatting_to_rtf(document)
24
+ end
25
+ end # class PositionStyle
26
+ end # module RRTF
@@ -0,0 +1,26 @@
1
+ module RRTF
2
+ # Represents a set of formatting that can be applied to shade paragraphs.
3
+ class ShadingStyle < AnonymousStyle
4
+ include ShadingFormatting
5
+
6
+ # This is the constructor for the ShadingStyle class.
7
+ #
8
+ # @param [Hash] options the shading style options.
9
+ # @option options (see AnonymousStyle#initialize)
10
+ # @option options (see ShadingFormatting#initialize_shading_formatting)
11
+ def initialize(options = {})
12
+ super(options)
13
+ initialize_shading_formatting(options)
14
+ end
15
+
16
+ # This method generates a string containing the prefix associated with the
17
+ # style object. Equivalent to {#rtf_formatting} for the ShadingStyle class.
18
+ def prefix(document)
19
+ rtf_formatting(document)
20
+ end
21
+
22
+ def rtf_formatting(document)
23
+ shading_formatting_to_rtf(document)
24
+ end
25
+ end # class ShadingStyle
26
+ end # module RRTF
@@ -1,101 +1,60 @@
1
- # This is a parent class that all style classes will derive from.
2
- class RRTF::Style
3
- attr_accessor :handle, :name, :priority, :primary, :additive,
4
- :next_style_handle, :auto_update, :based_on_style_handle,
5
- :hidden
6
-
7
- # Constructor for the style class.
8
- #
9
- # @param [Hash] options
10
- # @option options [String] "name" (nil) human-readable name for the style.
11
- # @option options [Integer] "handle" (nil) 16-bit integer that identifies the style in a document.
12
- # @option options [Integer] "next_style_handle" (nil) 16-bit integer that identifies the next style for this style.
13
- # @option options [Integer] "based_on_style_handle" (nil) 16-bit integer that identifies the base style for this style.
14
- # @option options [Integer] "priority" (nil) 16-bit integer that indicates the ordering of the style among other styles in a document.
15
- # @option options [Boolean] "primary" (false) whether or not this style is a primary or "quick" style.
16
- # @option options [Boolean] "additive" (false) whether or not this character style is additive to the current paragraph style.
17
- # @option options [Boolean] "auto_update" (false) whether or not this style should be updated when any node to which the style is applied is updated.
18
- # @option options [Boolean] "hidden" (false) whether or not the style should be hidden.
19
- def initialize(options = {})
20
- # load default options
21
- options = {
22
- "name" => nil,
23
- "handle" => nil,
24
- "priority" => nil,
25
- "primary" => false,
26
- "additive" => false,
27
- "next_style_handle" => nil,
28
- "auto_update" => false,
29
- "based_on_style_handle" => nil,
30
- "hidden" => false
31
- }.merge(options)
32
-
33
- @handle = options.delete("handle")
34
- @name = options.delete("name")
35
- @priority = options.delete("priority")
36
- @flow = options.delete("flow")
37
- @primary = options.delete("primary")
38
- @additive = options.delete("additive")
39
- @next_style_handle = options.delete("next_style_handle")
40
- @auto_update = options.delete("auto_update")
41
- @hidden = options.delete("hidden")
42
- end
43
-
44
- # Constructs an RTF identifier for the style.
45
- # (override in derived classes as needed)
46
- def styledef
47
- nil
48
- end
49
-
50
- def stylename
51
- name
52
- end
53
-
54
- # Constructs the RTF formatting representing the style.
55
- # (override in derived classes as needed)
56
- def to_rtf(document)
57
- nil
58
- end
59
-
60
- # This method retrieves the command prefix text associated with a Style
61
- # object. This method always returns nil and should be overridden by
62
- # derived classes as needed.
63
- def prefix(document)
64
- nil
65
- end
66
-
67
- def rtf_formatting
68
- nil
69
- end
70
-
71
- # This method retrieves the command suffix text associated with a Style
72
- # object. This method always returns nil and should be overridden by
73
- # derived classes as needed.
74
- def suffix(document)
75
- nil
76
- end
77
-
78
- # Used to determine if the style applies to characters. This method always
79
- # returns false and should be overridden by derived classes as needed.
80
- def is_character_style?
81
- false
82
- end
83
-
84
- # Used to determine if the style applies to paragraphs. This method always
85
- # returns false and should be overridden by derived classes as needed.
86
- def is_paragraph_style?
87
- false
88
- end
89
-
90
- # Used to determine if the style applies to documents. This method always
91
- # returns false and should be overridden by derived classes as needed.
92
- def is_document_style?
93
- false
94
- end
95
-
96
- # Used to determine if the style applies to tables. This method always
97
- # returns false and should be overridden by derived classes as needed.
98
- def is_table_style?
99
- false
100
- end
101
- end # End of the style class.
1
+ module RRTF
2
+ # Represents an abstract style that can be applied to elements within a
3
+ # document AND appear in a document's stylesheet (i.e. paragraph, character,
4
+ # table, & section styles).
5
+ # @author Wesley Hileman
6
+ # @author Peter Wood
7
+ # @since legacy
8
+ # @abstract
9
+ class Style < AnonymousStyle
10
+ attr_accessor :handle, :name, :priority, :primary, :additive,
11
+ :next_style_handle, :auto_update, :based_on_style_handle,
12
+ :hidden
13
+
14
+ # Constructor for the style class.
15
+ #
16
+ # @param [Hash] options
17
+ # @option options [String] "name" (nil) human-readable name for the style.
18
+ # @option options [Integer] "handle" (nil) 16-bit integer that identifies the style in a document.
19
+ # @option options [Integer] "next_style_handle" (nil) 16-bit integer that identifies the next style for this style.
20
+ # @option options [Integer] "based_on_style_handle" (nil) 16-bit integer that identifies the base style for this style.
21
+ # @option options [Integer] "priority" (nil) 16-bit integer that indicates the ordering of the style among other styles in a document.
22
+ # @option options [Boolean] "primary" (false) whether or not this style is a primary or "quick" style.
23
+ # @option options [Boolean] "additive" (false) whether or not this character style is additive to the current paragraph style.
24
+ # @option options [Boolean] "auto_update" (false) whether or not this style should be updated when any node to which the style is applied is updated.
25
+ # @option options [Boolean] "hidden" (false) whether or not the style should be hidden.
26
+ def initialize(options = {})
27
+ # load default options
28
+ options = {
29
+ "name" => nil,
30
+ "handle" => nil,
31
+ "priority" => nil,
32
+ "primary" => false,
33
+ "additive" => false,
34
+ "next_style_handle" => nil,
35
+ "auto_update" => false,
36
+ "based_on_style_handle" => nil,
37
+ "hidden" => false
38
+ }.merge(options)
39
+ super(options)
40
+
41
+ @handle = options.delete("handle")
42
+ @name = options.delete("name")
43
+ @priority = options.delete("priority")
44
+ @flow = options.delete("flow")
45
+ @primary = options.delete("primary")
46
+ @additive = options.delete("additive")
47
+ @next_style_handle = options.delete("next_style_handle")
48
+ @auto_update = options.delete("auto_update")
49
+ @hidden = options.delete("hidden")
50
+ end
51
+
52
+ # Constructs the RTF formatting representing the style in a Stylesheet.
53
+ # (override in derived classes as needed).
54
+ # @abstract
55
+ # @since 0.0.1
56
+ def to_rtf(document)
57
+ nil
58
+ end
59
+ end # End of the style class.
60
+ end # module RRTF
@@ -0,0 +1,138 @@
1
+ module RRTF
2
+ class Utilities
3
+ def self.constantize(string)
4
+ string.split('::').inject(Object) {|o,c| o.const_get c}
5
+ end
6
+
7
+ def self.parse_string_with_units(value)
8
+ return nil if value.nil?
9
+ matches = value.match /([+\-]?(\d*\.)?\d+)([a-z\%]*)$/i
10
+ RTFError.fire("Invalid units string '#{value}'.") if matches.nil?
11
+ [matches[1].to_f, matches[3]]
12
+ end
13
+
14
+ def self.num2pt(num, units)
15
+ case units
16
+ when 'in'
17
+ (num * 72.0)
18
+ when 'cm'
19
+ (num * 28.3464567)
20
+ when 'mm'
21
+ (num * 2.83464567)
22
+ when 'pt'
23
+ (num)
24
+ when 'twip'
25
+ (num.to_f / 20.0)
26
+ when 'none'
27
+ (num)
28
+ else
29
+ RTFError.fire("Invalid unit '#{units}'.")
30
+ end # case
31
+ end
32
+
33
+ # Converts a string representing a single value with an optional units
34
+ # suffix into an integer representing the value in twips (twentieth points).
35
+ # Supported unit suffixes are 'in' (inches), 'cm' (centimeters), 'mm'
36
+ # (millimeters), and 'pt' (typographic points).
37
+ # @note The RTF standard requires many values to be specified in twips
38
+ # (twentieth points), hence the need for this method.
39
+ #
40
+ # @param [Integer, String] value the string from which to parse the value (passes integers and nil without modification).
41
+ # @return [Integer] the parsed value in twips.
42
+ # @raise [RTFError] if the string cannot be converted into a value.
43
+ def self.value2twips(value)
44
+ return nil if value.nil?
45
+ return value if value.is_a?(Integer)
46
+
47
+ num, units = parse_string_with_units(value)
48
+ units ||= 'none'
49
+
50
+ (num2pt(num, units) * 20.0).round
51
+ end
52
+
53
+ # Convert to quarter points.
54
+ # @see .value2twips
55
+ def self.value2quarterpt(value)
56
+ return nil if value.nil?
57
+ return value if value.is_a?(Integer)
58
+
59
+ num, units = parse_string_with_units(value)
60
+ units ||= 'none'
61
+
62
+ (num2pt(num, units) * 4.0).round
63
+ end
64
+
65
+ # Convert to half points.
66
+ # @see .value2twips
67
+ def self.value2halfpt(value)
68
+ return nil if value.nil?
69
+ return value if value.is_a?(Integer)
70
+
71
+ num, units = parse_string_with_units(value)
72
+ units ||= 'none'
73
+
74
+ (num2pt(num, units) * 2.0).round
75
+ end
76
+
77
+ # Convert to Microsoft's "English Metric Unit" (EMU).
78
+ # @see .value2twips
79
+ def self.value2emu(value)
80
+ return nil if value.nil?
81
+ return value if value.is_a?(Integer)
82
+
83
+ num, units = parse_string_with_units(value)
84
+ units ||= 'none'
85
+
86
+ # 12700 EMUs per point
87
+ (num2pt(num, units) * 12700.0).round
88
+ end
89
+
90
+ # Convert to frational geometry units (1/65536 of a regular unit).
91
+ def self.value2geomfrac(value)
92
+ return nil if value.nil?
93
+ (value * 65536.0).round
94
+ end
95
+
96
+ # Convert to a Boolean value into a geometry Boolean (0 or 1).
97
+ def self.value2geombool(value)
98
+ return nil if value.nil?
99
+ return value if value.is_a?(Integer)
100
+
101
+ value ? 1 : 0
102
+ end
103
+
104
+ # Converts a string representing a single value with an optional units
105
+ # suffix into an integer representing the value in hundreths of a percent.
106
+ # Supported unit suffixes are '%' (percent).
107
+ #
108
+ # @param [Integer, String] value the string from which to parse the value (passes integers and nil without modification).
109
+ # @return [Integer] the parsed value in hundreths of a percent.
110
+ # @raise [RTFError] if the string cannot be converted into a value.
111
+ def self.value2hunpercent(value)
112
+ return nil if value.nil?
113
+ return value if value.is_a?(Integer)
114
+
115
+ num, units = parse_string_with_units(value)
116
+ units ||= 'none'
117
+
118
+ case units
119
+ when '%'
120
+ (num * 100.0).round
121
+ when 'none'
122
+ (num).round
123
+ else
124
+ RTFError.fire("Invalid unit '#{units}'.")
125
+ end # case
126
+ end
127
+ end # class Utilities
128
+
129
+ class RTFError < StandardError
130
+ def initialize(message=nil)
131
+ super(message == nil ? 'No error message available.' : message)
132
+ end
133
+
134
+ def RTFError.fire(message=nil)
135
+ raise RTFError.new(message)
136
+ end
137
+ end # class RTFError
138
+ end # module RRTF