panmind-rtf 0.3.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (48) hide show
  1. data/CHANGES +8 -0
  2. data/LICENSE +20 -0
  3. data/README +186 -0
  4. data/Rakefile +48 -0
  5. data/VERSION.yml +5 -0
  6. data/examples/example01.rb +51 -0
  7. data/examples/example02.rb +45 -0
  8. data/examples/example03.rb +66 -0
  9. data/examples/example03.rtf +164 -0
  10. data/examples/example04.rb +50 -0
  11. data/examples/rubyrtf.bmp +0 -0
  12. data/examples/rubyrtf.jpg +0 -0
  13. data/examples/rubyrtf.png +0 -0
  14. data/lib/rtf.rb +34 -0
  15. data/lib/rtf/colour.rb +173 -0
  16. data/lib/rtf/font.rb +173 -0
  17. data/lib/rtf/information.rb +111 -0
  18. data/lib/rtf/node.rb +1680 -0
  19. data/lib/rtf/paper.rb +55 -0
  20. data/lib/rtf/style.rb +305 -0
  21. data/test/character_style_test.rb +136 -0
  22. data/test/colour_table_test.rb +93 -0
  23. data/test/colour_test.rb +116 -0
  24. data/test/command_node_test.rb +219 -0
  25. data/test/container_node_test.rb +64 -0
  26. data/test/document_style_test.rb +79 -0
  27. data/test/document_test.rb +106 -0
  28. data/test/fixtures/bitmap1.bmp +0 -0
  29. data/test/fixtures/bitmap2.bmp +0 -0
  30. data/test/fixtures/jpeg1.jpg +0 -0
  31. data/test/fixtures/jpeg2.jpg +0 -0
  32. data/test/fixtures/png1.png +0 -0
  33. data/test/fixtures/png2.png +0 -0
  34. data/test/font_table_test.rb +91 -0
  35. data/test/font_test.rb +48 -0
  36. data/test/footer_node_test.rb +30 -0
  37. data/test/header_node_test.rb +30 -0
  38. data/test/image_node_test.rb +125 -0
  39. data/test/information_test.rb +127 -0
  40. data/test/node_test.rb +25 -0
  41. data/test/paragraph_style_test.rb +81 -0
  42. data/test/style_test.rb +16 -0
  43. data/test/table_cell_node_test.rb +89 -0
  44. data/test/table_node_test.rb +83 -0
  45. data/test/table_row_node_test.rb +59 -0
  46. data/test/test_helper.rb +13 -0
  47. data/test/text_node_test.rb +50 -0
  48. metadata +133 -0
data/lib/rtf/paper.rb ADDED
@@ -0,0 +1,55 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ module RTF
4
+ # This class represents a definition for a paper size and provides a set
5
+ # of class constants for common paper sizes. An instance of the Paper class
6
+ # is considered immutable after creation.
7
+ class Paper
8
+ # Attribute accessor.
9
+ attr_reader :name, :width, :height
10
+
11
+
12
+ # This is the constructor for the Paper class. All dimension parameters
13
+ # to this method are in twips.
14
+ #
15
+ # ==== Parameters
16
+ # name:: The name for the paper object.
17
+ # width:: The width of the paper in portrait mode.
18
+ # height:: The height of the paper in portrait mode.
19
+ def initialize(name, width, height)
20
+ @name = name
21
+ @width = width
22
+ @height = height
23
+ end
24
+
25
+ # Definition of an international paper constant.
26
+ A0 = Paper.new('A0', 47685, 67416)
27
+
28
+ # Definition of an international paper constant.
29
+ A1 = Paper.new('A1', 33680, 47685)
30
+
31
+ # Definition of an international paper constant.
32
+ A2 = Paper.new('A2', 23814, 33680)
33
+
34
+ # Definition of an international paper constant.
35
+ A3 = Paper.new('A3', 16840, 23814)
36
+
37
+ # Definition of an international paper constant.
38
+ A4 = Paper.new('A4', 11907, 16840)
39
+
40
+ # Definition of an international paper constant.
41
+ A5 = Paper.new('A5', 8392, 11907)
42
+
43
+ # Definition of a US paper constant.
44
+ LETTER = Paper.new('Letter', 12247, 15819)
45
+
46
+ # Definition of a US paper constant.
47
+ LEGAL = Paper.new('Legal', 12247, 20185)
48
+
49
+ # Definition of a US paper constant.
50
+ EXECUTIVE = Paper.new('Executive', 10773, 14402)
51
+
52
+ # Definition of a US paper constant.
53
+ LEDGER_TABLOID = Paper.new('Ledger/Tabloid', 15819, 24494)
54
+ end # End of the Paper class.
55
+ end # End of the RTF module.
data/lib/rtf/style.rb ADDED
@@ -0,0 +1,305 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ require 'stringio'
4
+
5
+ module RTF
6
+ # This is a parent class that all style classes will derive from.
7
+ class Style
8
+ # A definition for a character flow setting.
9
+ LEFT_TO_RIGHT = :rtl
10
+
11
+ # A definition for a character flow setting.
12
+ RIGHT_TO_LEFT = :ltr
13
+
14
+ # This method retrieves the command prefix text associated with a Style
15
+ # object. This method always returns nil and should be overridden by
16
+ # derived classes as needed.
17
+ #
18
+ # ==== Parameters
19
+ # fonts:: A reference to the document fonts table. May be nil if no
20
+ # fonts are used.
21
+ # colours:: A reference to the document colour table. May be nil if no
22
+ # colours are used.
23
+ def prefix(fonts, colours)
24
+ nil
25
+ end
26
+
27
+ # This method retrieves the command suffix text associated with a Style
28
+ # object. This method always returns nil and should be overridden by
29
+ # derived classes as needed.
30
+ #
31
+ # ==== Parameters
32
+ # fonts:: A reference to the document fonts table. May be nil if no
33
+ # fonts are used.
34
+ # colours:: A reference to the document colour table. May be nil if no
35
+ # colours are used.
36
+ def suffix(fonts, colours)
37
+ nil
38
+ end
39
+
40
+ # Used to determine if the style applies to characters. This method always
41
+ # returns false and should be overridden by derived classes as needed.
42
+ def is_character_style?
43
+ false
44
+ end
45
+
46
+ # Used to determine if the style applies to paragraphs. This method always
47
+ # returns false and should be overridden by derived classes as needed.
48
+ def is_paragraph_style?
49
+ false
50
+ end
51
+
52
+ # Used to determine if the style applies to documents. This method always
53
+ # returns false and should be overridden by derived classes as needed.
54
+ def is_document_style?
55
+ false
56
+ end
57
+
58
+ # Used to determine if the style applies to tables. This method always
59
+ # returns false and should be overridden by derived classes as needed.
60
+ def is_table_style?
61
+ false
62
+ end
63
+ end # End of the style class.
64
+
65
+
66
+ # This class represents a character style for an RTF document.
67
+ class CharacterStyle < Style
68
+ # Attribute accessor.
69
+ attr_reader :bold, :italic, :underline, :superscript, :capitalise,
70
+ :strike, :subscript, :hidden, :foreground, :background,
71
+ :flow, :font, :font_size
72
+
73
+ # Attribute mutator.
74
+ attr_writer :bold, :italic, :underline, :superscript, :capitalise,
75
+ :strike, :subscript, :hidden, :foreground, :background,
76
+ :flow, :font, :font_size
77
+
78
+ # This is the constructor for the CharacterStyle class.
79
+ #
80
+ # ==== Exceptions
81
+ # RTFError:: Generate if the parent style specified is not an instance
82
+ # of the CharacterStyle class.
83
+ def initialize
84
+ @bold = false
85
+ @italic = false
86
+ @underline = false
87
+ @superscript = false
88
+ @capitalise = false
89
+ @strike = false
90
+ @subscript = false
91
+ @hidden = false
92
+ @foreground = nil
93
+ @background = nil
94
+ @font = nil
95
+ @font_size = nil
96
+ @flow = LEFT_TO_RIGHT
97
+ end
98
+
99
+ # This method overrides the is_character_style? method inherited from the
100
+ # Style class to always return true.
101
+ def is_character_style?
102
+ true
103
+ end
104
+
105
+ # This method generates a string containing the prefix associated with a
106
+ # style object.
107
+ #
108
+ # ==== Parameters
109
+ # fonts:: A reference to a FontTable containing any fonts used by the
110
+ # style (may be nil if no fonts used).
111
+ # colours:: A reference to a ColourTable containing any colours used by
112
+ # the style (may be nil if no colours used).
113
+ def prefix(fonts, colours)
114
+ text = StringIO.new
115
+
116
+ text << '\b' if @bold
117
+ text << '\i' if @italic
118
+ text << '\ul' if @underline
119
+ text << '\super' if @superscript
120
+ text << '\caps' if @capitalise
121
+ text << '\strike' if @strike
122
+ text << '\sub' if @subscript
123
+ text << '\v' if @hidden
124
+ text << "\\cf#{colours.index(@foreground)}" if @foreground != nil
125
+ text << "\\cb#{colours.index(@background)}" if @background != nil
126
+ text << "\\f#{fonts.index(@font)}" if @font != nil
127
+ text << "\\fs#{@font_size.to_i}" if @font_size != nil
128
+ text << '\rtlch' if @flow == RIGHT_TO_LEFT
129
+
130
+ text.string.length > 0 ? text.string : nil
131
+ end
132
+
133
+ alias :capitalize :capitalise
134
+ alias :capitalize= :capitalise=
135
+ end # End of the CharacterStyle class.
136
+
137
+
138
+ # This class represents a styling for a paragraph within an RTF document.
139
+ class ParagraphStyle < Style
140
+ # A definition for a paragraph justification setting.
141
+ LEFT_JUSTIFY = :ql
142
+
143
+ # A definition for a paragraph justification setting.
144
+ RIGHT_JUSTIFY = :qr
145
+
146
+ # A definition for a paragraph justification setting.
147
+ CENTER_JUSTIFY = :qc
148
+
149
+ # A definition for a paragraph justification setting.
150
+ CENTRE_JUSTIFY = :qc
151
+
152
+ # A definition for a paragraph justification setting.
153
+ FULL_JUSTIFY = :qj
154
+
155
+ # Attribute accessor.
156
+ attr_reader :justification, :left_indent, :right_indent,
157
+ :first_line_indent, :space_before, :space_after,
158
+ :line_spacing, :flow
159
+
160
+ # Attribute mutator.
161
+ attr_writer :justification, :left_indent, :right_indent,
162
+ :first_line_indent, :space_before, :space_after,
163
+ :line_spacing, :flow
164
+
165
+ # This is a constructor for the ParagraphStyle class.
166
+ #
167
+ # ==== Parameters
168
+ # base:: A reference to base object that the new style will inherit its
169
+ # initial properties from. Defaults to nil.
170
+ def initialize(base=nil)
171
+ @justification = base == nil ? LEFT_JUSTIFY : base.justification
172
+ @left_indent = base == nil ? nil : base.left_indent
173
+ @right_indent = base == nil ? nil : base.right_indent
174
+ @first_line_indent = base == nil ? nil : base.first_line_indent
175
+ @space_before = base == nil ? nil : base.space_before
176
+ @space_after = base == nil ? nil : base.space_after
177
+ @line_spacing = base == nil ? nil : base.line_spacing
178
+ @flow = base == nil ? LEFT_TO_RIGHT : base.flow
179
+ end
180
+
181
+ # This method overrides the is_paragraph_style? method inherited from the
182
+ # Style class to always return true.
183
+ def is_paragraph_style?
184
+ true
185
+ end
186
+
187
+ # This method generates a string containing the prefix associated with a
188
+ # style object.
189
+ #
190
+ # ==== Parameters
191
+ # fonts:: A reference to a FontTable containing any fonts used by the
192
+ # style (may be nil if no fonts used).
193
+ # colours:: A reference to a ColourTable containing any colours used by
194
+ # the style (may be nil if no colours used).
195
+ def prefix(fonts, colours)
196
+ text = StringIO.new
197
+
198
+ text << "\\#{@justification.id2name}"
199
+ text << "\\li#{@left_indent}" if @left_indent != nil
200
+ text << "\\ri#{@right_indent}" if @right_indent != nil
201
+ text << "\\fi#{@first_line_indent}" if @first_line_indent != nil
202
+ text << "\\sb#{@space_before}" if @space_before != nil
203
+ text << "\\sa#{@space_after}" if @space_after != nil
204
+ text << "\\sl#{@line_spacing}" if @line_spacing != nil
205
+ text << '\rtlpar' if @flow == RIGHT_TO_LEFT
206
+
207
+ text.string.length > 0 ? text.string : nil
208
+ end
209
+ end # End of the ParagraphStyle class.
210
+
211
+
212
+ # This class represents styling attributes that are to be applied at the
213
+ # document level.
214
+ class DocumentStyle < Style
215
+ # Definition for a document orientation setting.
216
+ PORTRAIT = :portrait
217
+
218
+ # Definition for a document orientation setting.
219
+ LANDSCAPE = :landscape
220
+
221
+ # Definition for a default margin setting.
222
+ DEFAULT_LEFT_MARGIN = 1800
223
+
224
+ # Definition for a default margin setting.
225
+ DEFAULT_RIGHT_MARGIN = 1800
226
+
227
+ # Definition for a default margin setting.
228
+ DEFAULT_TOP_MARGIN = 1440
229
+
230
+ # Definition for a default margin setting.
231
+ DEFAULT_BOTTOM_MARGIN = 1440
232
+
233
+ # Attribute accessor.
234
+ attr_reader :paper, :left_margin, :right_margin, :top_margin,
235
+ :bottom_margin, :gutter, :orientation
236
+
237
+ # Attribute mutator.
238
+ attr_writer :paper, :left_margin, :right_margin, :top_margin,
239
+ :bottom_margin, :gutter, :orientation
240
+
241
+ # This is a constructor for the DocumentStyle class. This creates a
242
+ # document style with a default paper setting of A4 and portrait
243
+ # orientation (all other attributes are nil).
244
+ def initialize
245
+ @paper = Paper::A4
246
+ @left_margin = DEFAULT_LEFT_MARGIN
247
+ @right_margin = DEFAULT_RIGHT_MARGIN
248
+ @top_margin = DEFAULT_TOP_MARGIN
249
+ @bottom_margin = DEFAULT_BOTTOM_MARGIN
250
+ @gutter = nil
251
+ @orientation = PORTRAIT
252
+ end
253
+
254
+ # This method overrides the is_document_style? method inherited from the
255
+ # Style class to always return true.
256
+ def is_document_style?
257
+ true
258
+ end
259
+
260
+ # This method generates a string containing the prefix associated with a
261
+ # style object.
262
+ #
263
+ # ==== Parameters
264
+ # document:: A reference to the document using the style.
265
+ def prefix(fonts=nil, colours=nil)
266
+ text = StringIO.new
267
+
268
+ if orientation == LANDSCAPE
269
+ text << "\\paperw#{@paper.height}" if @paper != nil
270
+ text << "\\paperh#{@paper.width}" if @paper != nil
271
+ else
272
+ text << "\\paperw#{@paper.width}" if @paper != nil
273
+ text << "\\paperh#{@paper.height}" if @paper != nil
274
+ end
275
+ text << "\\margl#{@left_margin}" if @left_margin != nil
276
+ text << "\\margr#{@right_margin}" if @right_margin != nil
277
+ text << "\\margt#{@top_margin}" if @top_margin != nil
278
+ text << "\\margb#{@bottom_margin}" if @bottom_margin != nil
279
+ text << "\\gutter#{@gutter}" if @gutter != nil
280
+ text << '\sectd\lndscpsxn' if @orientation == LANDSCAPE
281
+
282
+ text.string
283
+ end
284
+
285
+ # This method fetches the width of the available work area space for a
286
+ # DocumentStyle object.
287
+ def body_width
288
+ if orientation == PORTRAIT
289
+ @paper.width - (@left_margin + @right_margin)
290
+ else
291
+ @paper.height - (@left_margin + @right_margin)
292
+ end
293
+ end
294
+
295
+ # This method fetches the height of the available work area space for a
296
+ # DocumentStyle object.
297
+ def body_height
298
+ if orientation == PORTRAIT
299
+ @paper.height - (@top_margin + @bottom_margin)
300
+ else
301
+ @paper.width - (@top_margin + @bottom_margin)
302
+ end
303
+ end
304
+ end # End of the DocumentStyle class.
305
+ end # End of the RTF module.
@@ -0,0 +1,136 @@
1
+ require 'test_helper'
2
+
3
+ # Information class unit test class.
4
+ class CharacterStyleTest < Test::Unit::TestCase
5
+ def test_basics
6
+ style = CharacterStyle.new
7
+
8
+ assert(style.is_character_style? == true)
9
+ assert(style.is_document_style? == false)
10
+ assert(style.is_paragraph_style? == false)
11
+ assert(style.is_table_style? == false)
12
+
13
+ assert(style.prefix(nil, nil) == nil)
14
+ assert(style.suffix(nil, nil) == nil)
15
+
16
+ assert(style.background == nil)
17
+ assert(style.bold == false)
18
+ assert(style.capitalise == false)
19
+ assert(style.flow == CharacterStyle::LEFT_TO_RIGHT)
20
+ assert(style.font == nil)
21
+ assert(style.font_size == nil)
22
+ assert(style.foreground == nil)
23
+ assert(style.hidden == false)
24
+ assert(style.italic == false)
25
+ assert(style.strike == false)
26
+ assert(style.subscript == false)
27
+ assert(style.superscript == false)
28
+ assert(style.underline == false)
29
+ end
30
+
31
+ def test_mutators
32
+ style = CharacterStyle.new
33
+
34
+ style.background = Colour.new(100, 100, 100)
35
+ assert(style.background == Colour.new(100, 100, 100))
36
+
37
+ style.bold = true
38
+ assert(style.bold)
39
+
40
+ style.capitalise = true
41
+ assert(style.capitalize)
42
+
43
+ style.flow = CharacterStyle::RIGHT_TO_LEFT
44
+ assert(style.flow == CharacterStyle::RIGHT_TO_LEFT)
45
+
46
+ style.font = Font.new(Font::ROMAN, 'Arial')
47
+ assert(style.font == Font.new(Font::ROMAN, 'Arial'))
48
+
49
+ style.font_size = 38
50
+ assert(style.font_size == 38)
51
+
52
+ style.foreground = Colour.new(250, 200, 150)
53
+ assert(style.foreground == Colour.new(250, 200, 150))
54
+
55
+ style.hidden = true
56
+ assert(style.hidden)
57
+
58
+ style.italic = true
59
+ assert(style.italic)
60
+
61
+ style.strike = true
62
+ assert(style.strike)
63
+
64
+ style.subscript = true
65
+ assert(style.subscript)
66
+
67
+ style.superscript = true
68
+ assert(style.superscript)
69
+
70
+ style.underline = true
71
+ assert(style.underline)
72
+ end
73
+
74
+ def test_prefix
75
+ fonts = FontTable.new(Font.new(Font::ROMAN, 'Arial'))
76
+ colours = ColourTable.new(Colour.new(100, 100, 100))
77
+ style = CharacterStyle.new
78
+
79
+ style.background = colours[0]
80
+ assert(style.prefix(fonts, colours) == '\cb1')
81
+
82
+ style.background = nil
83
+ style.bold = true
84
+ assert(style.prefix(nil, nil) == '\b')
85
+
86
+ style.bold = false
87
+ style.capitalise = true
88
+ assert(style.prefix(nil, nil) == '\caps')
89
+
90
+ style.capitalize = false
91
+ style.flow = CharacterStyle::RIGHT_TO_LEFT
92
+ assert(style.prefix(nil, nil) == '\rtlch')
93
+
94
+ style.flow = nil
95
+ style.font = fonts[0]
96
+ assert(style.prefix(fonts, colours) == '\f0')
97
+
98
+ style.font = nil
99
+ style.font_size = 40
100
+ assert(style.prefix(nil, nil) == '\fs40')
101
+
102
+ style.font_size = nil
103
+ style.foreground = colours[0]
104
+ assert(style.prefix(fonts, colours) == '\cf1')
105
+
106
+ style.foreground = nil
107
+ style.hidden = true
108
+ assert(style.prefix(nil, nil) == '\v')
109
+
110
+ style.hidden = false
111
+ style.italic = true
112
+ assert(style.prefix(nil, nil) == '\i')
113
+
114
+ style.italic = false
115
+ style.strike = true
116
+ assert(style.prefix(nil, nil) == '\strike')
117
+
118
+ style.strike = false
119
+ style.subscript = true
120
+ assert(style.prefix(nil, nil) == '\sub')
121
+
122
+ style.subscript = false
123
+ style.superscript = true
124
+ assert(style.prefix(fonts, colours) == '\super')
125
+
126
+ style.superscript = false
127
+ style.underline = true
128
+ assert(style.prefix(fonts, colours) == '\ul')
129
+
130
+ style.flow = CharacterStyle::RIGHT_TO_LEFT
131
+ style.background = colours[0]
132
+ style.font_size = 18
133
+ style.subscript = true
134
+ assert(style.prefix(fonts, colours) == '\ul\sub\cb1\fs18\rtlch')
135
+ end
136
+ end