rtf 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
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,142 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ require 'rubygems'
4
+ require 'test/unit'
5
+ require 'rtf'
6
+
7
+ include RTF
8
+
9
+ # Information class unit test class.
10
+ class CharacterStyleTest < Test::Unit::TestCase
11
+ def test_basics
12
+ style = CharacterStyle.new
13
+
14
+ assert(style.is_character_style? == true)
15
+ assert(style.is_document_style? == false)
16
+ assert(style.is_paragraph_style? == false)
17
+ assert(style.is_table_style? == false)
18
+
19
+ assert(style.prefix(nil, nil) == nil)
20
+ assert(style.suffix(nil, nil) == nil)
21
+
22
+ assert(style.background == nil)
23
+ assert(style.bold == false)
24
+ assert(style.capitalise == false)
25
+ assert(style.flow == CharacterStyle::LEFT_TO_RIGHT)
26
+ assert(style.font == nil)
27
+ assert(style.font_size == nil)
28
+ assert(style.foreground == nil)
29
+ assert(style.hidden == false)
30
+ assert(style.italic == false)
31
+ assert(style.strike == false)
32
+ assert(style.subscript == false)
33
+ assert(style.superscript == false)
34
+ assert(style.underline == false)
35
+ end
36
+
37
+ def test_mutators
38
+ style = CharacterStyle.new
39
+
40
+ style.background = Colour.new(100, 100, 100)
41
+ assert(style.background == Colour.new(100, 100, 100))
42
+
43
+ style.bold = true
44
+ assert(style.bold)
45
+
46
+ style.capitalise = true
47
+ assert(style.capitalize)
48
+
49
+ style.flow = CharacterStyle::RIGHT_TO_LEFT
50
+ assert(style.flow == CharacterStyle::RIGHT_TO_LEFT)
51
+
52
+ style.font = Font.new(Font::ROMAN, 'Arial')
53
+ assert(style.font == Font.new(Font::ROMAN, 'Arial'))
54
+
55
+ style.font_size = 38
56
+ assert(style.font_size == 38)
57
+
58
+ style.foreground = Colour.new(250, 200, 150)
59
+ assert(style.foreground == Colour.new(250, 200, 150))
60
+
61
+ style.hidden = true
62
+ assert(style.hidden)
63
+
64
+ style.italic = true
65
+ assert(style.italic)
66
+
67
+ style.strike = true
68
+ assert(style.strike)
69
+
70
+ style.subscript = true
71
+ assert(style.subscript)
72
+
73
+ style.superscript = true
74
+ assert(style.superscript)
75
+
76
+ style.underline = true
77
+ assert(style.underline)
78
+ end
79
+
80
+ def test_prefix
81
+ fonts = FontTable.new(Font.new(Font::ROMAN, 'Arial'))
82
+ colours = ColourTable.new(Colour.new(100, 100, 100))
83
+ style = CharacterStyle.new
84
+
85
+ style.background = colours[0]
86
+ assert(style.prefix(fonts, colours) == '\cb1')
87
+
88
+ style.background = nil
89
+ style.bold = true
90
+ assert(style.prefix(nil, nil) == '\b')
91
+
92
+ style.bold = false
93
+ style.capitalise = true
94
+ assert(style.prefix(nil, nil) == '\caps')
95
+
96
+ style.capitalize = false
97
+ style.flow = CharacterStyle::RIGHT_TO_LEFT
98
+ assert(style.prefix(nil, nil) == '\rtlch')
99
+
100
+ style.flow = nil
101
+ style.font = fonts[0]
102
+ assert(style.prefix(fonts, colours) == '\f0')
103
+
104
+ style.font = nil
105
+ style.font_size = 40
106
+ assert(style.prefix(nil, nil) == '\fs40')
107
+
108
+ style.font_size = nil
109
+ style.foreground = colours[0]
110
+ assert(style.prefix(fonts, colours) == '\cf1')
111
+
112
+ style.foreground = nil
113
+ style.hidden = true
114
+ assert(style.prefix(nil, nil) == '\v')
115
+
116
+ style.hidden = false
117
+ style.italic = true
118
+ assert(style.prefix(nil, nil) == '\i')
119
+
120
+ style.italic = false
121
+ style.strike = true
122
+ assert(style.prefix(nil, nil) == '\strike')
123
+
124
+ style.strike = false
125
+ style.subscript = true
126
+ assert(style.prefix(nil, nil) == '\sub')
127
+
128
+ style.subscript = false
129
+ style.superscript = true
130
+ assert(style.prefix(fonts, colours) == '\super')
131
+
132
+ style.superscript = false
133
+ style.underline = true
134
+ assert(style.prefix(fonts, colours) == '\ul')
135
+
136
+ style.flow = CharacterStyle::RIGHT_TO_LEFT
137
+ style.background = colours[0]
138
+ style.font_size = 18
139
+ style.subscript = true
140
+ assert(style.prefix(fonts, colours) == '\ul\sub\cb1\fs18\rtlch')
141
+ end
142
+ end