pdf-writer 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.
- data/ChangeLog +44 -0
- data/LICENCE +118 -0
- data/README +32 -0
- data/bin/loader +54 -0
- data/bin/manual +22 -0
- data/bin/manual.bat +2 -0
- data/demo/chunkybacon.rb +28 -0
- data/demo/code.rb +63 -0
- data/demo/colornames.rb +843 -0
- data/demo/demo.rb +65 -0
- data/demo/gettysburg.rb +58 -0
- data/demo/hello.rb +18 -0
- data/demo/individual-i.rb +81 -0
- data/demo/pac.rb +62 -0
- data/demo/pagenumber.rb +67 -0
- data/demo/qr-language.rb +573 -0
- data/demo/qr-library.rb +371 -0
- data/images/chunkybacon.jpg +0 -0
- data/images/chunkybacon.png +0 -0
- data/images/pdfwriter-icon.jpg +0 -0
- data/images/pdfwriter-small.jpg +0 -0
- data/lib/pdf/charts.rb +13 -0
- data/lib/pdf/charts/stddev.rb +431 -0
- data/lib/pdf/grid.rb +135 -0
- data/lib/pdf/math.rb +108 -0
- data/lib/pdf/quickref.rb +330 -0
- data/lib/pdf/simpletable.rb +946 -0
- data/lib/pdf/techbook.rb +890 -0
- data/lib/pdf/writer.rb +2661 -0
- data/lib/pdf/writer/arc4.rb +63 -0
- data/lib/pdf/writer/fontmetrics.rb +201 -0
- data/lib/pdf/writer/fonts/Courier-Bold.afm +342 -0
- data/lib/pdf/writer/fonts/Courier-BoldOblique.afm +342 -0
- data/lib/pdf/writer/fonts/Courier-Oblique.afm +342 -0
- data/lib/pdf/writer/fonts/Courier.afm +342 -0
- data/lib/pdf/writer/fonts/Helvetica-Bold.afm +2827 -0
- data/lib/pdf/writer/fonts/Helvetica-BoldOblique.afm +2827 -0
- data/lib/pdf/writer/fonts/Helvetica-Oblique.afm +3051 -0
- data/lib/pdf/writer/fonts/Helvetica.afm +3051 -0
- data/lib/pdf/writer/fonts/MustRead.html +1 -0
- data/lib/pdf/writer/fonts/Symbol.afm +213 -0
- data/lib/pdf/writer/fonts/Times-Bold.afm +2588 -0
- data/lib/pdf/writer/fonts/Times-BoldItalic.afm +2384 -0
- data/lib/pdf/writer/fonts/Times-Italic.afm +2667 -0
- data/lib/pdf/writer/fonts/Times-Roman.afm +2419 -0
- data/lib/pdf/writer/fonts/ZapfDingbats.afm +225 -0
- data/lib/pdf/writer/graphics.rb +727 -0
- data/lib/pdf/writer/graphics/imageinfo.rb +365 -0
- data/lib/pdf/writer/lang.rb +43 -0
- data/lib/pdf/writer/lang/en.rb +77 -0
- data/lib/pdf/writer/object.rb +23 -0
- data/lib/pdf/writer/object/action.rb +40 -0
- data/lib/pdf/writer/object/annotation.rb +42 -0
- data/lib/pdf/writer/object/catalog.rb +39 -0
- data/lib/pdf/writer/object/contents.rb +68 -0
- data/lib/pdf/writer/object/destination.rb +40 -0
- data/lib/pdf/writer/object/encryption.rb +53 -0
- data/lib/pdf/writer/object/font.rb +76 -0
- data/lib/pdf/writer/object/fontdescriptor.rb +34 -0
- data/lib/pdf/writer/object/fontencoding.rb +39 -0
- data/lib/pdf/writer/object/image.rb +168 -0
- data/lib/pdf/writer/object/info.rb +55 -0
- data/lib/pdf/writer/object/outline.rb +30 -0
- data/lib/pdf/writer/object/outlines.rb +30 -0
- data/lib/pdf/writer/object/page.rb +195 -0
- data/lib/pdf/writer/object/pages.rb +115 -0
- data/lib/pdf/writer/object/procset.rb +46 -0
- data/lib/pdf/writer/object/viewerpreferences.rb +74 -0
- data/lib/pdf/writer/ohash.rb +58 -0
- data/lib/pdf/writer/oreader.rb +25 -0
- data/lib/pdf/writer/state.rb +48 -0
- data/lib/pdf/writer/strokestyle.rb +138 -0
- data/manual.pwd +5151 -0
- metadata +147 -0
@@ -0,0 +1,115 @@
|
|
1
|
+
#--
|
2
|
+
# PDF::Writer for Ruby.
|
3
|
+
# http://rubyforge.org/projects/ruby-pdf/
|
4
|
+
# Copyright 2003 - 2005 Austin Ziegler.
|
5
|
+
#
|
6
|
+
# Licensed under a MIT-style licence. See LICENCE in the main distribution
|
7
|
+
# for full licensing information.
|
8
|
+
#
|
9
|
+
# $Id: pages.rb,v 1.2 2005/05/16 03:59:21 austin Exp $
|
10
|
+
#++
|
11
|
+
# object which is a parent to the pages in the document
|
12
|
+
class PDF::Writer::Object::Pages < PDF::Writer::Object
|
13
|
+
def initialize(parent)
|
14
|
+
super(parent)
|
15
|
+
|
16
|
+
@parent.catalog.pages = self
|
17
|
+
|
18
|
+
@pages = []
|
19
|
+
@procset = nil
|
20
|
+
@media_box = nil
|
21
|
+
@fonts = []
|
22
|
+
@xObjects = []
|
23
|
+
@bleed_box = nil
|
24
|
+
@trim_box = nil
|
25
|
+
end
|
26
|
+
|
27
|
+
def size
|
28
|
+
@pages.size
|
29
|
+
end
|
30
|
+
|
31
|
+
def first_page
|
32
|
+
@pages[0]
|
33
|
+
end
|
34
|
+
|
35
|
+
# Add the page ID to the end of the page list.
|
36
|
+
def <<(p)
|
37
|
+
if p.kind_of?(PDF::Writer::Object::Page)
|
38
|
+
@pages << p
|
39
|
+
elsif p.kind_of?(PDF::Writer::Object::Font)
|
40
|
+
@fonts << p
|
41
|
+
elsif p.kind_of?(PDF::Writer::External)
|
42
|
+
@xObjects << p
|
43
|
+
else
|
44
|
+
raise ArgumentError, PDF::Message[:req_FPXO]
|
45
|
+
end
|
46
|
+
end
|
47
|
+
|
48
|
+
# Add a page to the page list. If p is just a Page, then it will be
|
49
|
+
# added to the page list. Otherwise, it will be treated as a Hash with
|
50
|
+
# keys :page, :pos, and :rpage. :page is the Page to be added to the
|
51
|
+
# list; :pos is :before or :after; :rpage is the Page to which the
|
52
|
+
# new Page will be added relative to.
|
53
|
+
def add(p)
|
54
|
+
if p.kind_of?(PDF::Writer::Object::Page)
|
55
|
+
@pages << p
|
56
|
+
elsif p.kind_of?(PDF::Writer::FontMetrics)
|
57
|
+
@fonts << p
|
58
|
+
elsif p.kind_of?(PDF::Writer::External)
|
59
|
+
@xObjects << p
|
60
|
+
elsif p.kind_of?(Hash)
|
61
|
+
# Find a match.
|
62
|
+
i = @pages.index(p[:rpage])
|
63
|
+
unless i.nil?
|
64
|
+
# There is a match; insert the page.
|
65
|
+
case p[:pos]
|
66
|
+
when :before
|
67
|
+
@pages[i, 0] = p[:page]
|
68
|
+
when :after
|
69
|
+
@pages[i + 1, 0] = p[:page]
|
70
|
+
else
|
71
|
+
raise ArgumentError, PDF::Message[:invalid_pos]
|
72
|
+
end
|
73
|
+
end
|
74
|
+
else
|
75
|
+
raise ArgumentError, PDF::Message[:req_FPXOH]
|
76
|
+
end
|
77
|
+
end
|
78
|
+
|
79
|
+
attr_accessor :procset
|
80
|
+
# Each of the following should be an array of 4 numbers, the x and y
|
81
|
+
# coordinates of the lower left and upper right bounds of the box.
|
82
|
+
attr_accessor :media_box
|
83
|
+
attr_accessor :bleed_box
|
84
|
+
attr_accessor :trim_box
|
85
|
+
|
86
|
+
def to_s
|
87
|
+
unless @pages.empty?
|
88
|
+
res = "\n#{@oid} 0 obj\n<< /Type /Pages\n/Kids ["
|
89
|
+
@pages.uniq! # uniqify the data...
|
90
|
+
@pages.each { |p| res << "#{p.oid} 0 R\n" }
|
91
|
+
res << "]\n/Count #{@pages.size}"
|
92
|
+
unless @fonts.empty? and @procset.nil?
|
93
|
+
res << "\n/Resources <<"
|
94
|
+
res << "\n/ProcSet #{@procset.oid} 0 R" unless @procset.nil?
|
95
|
+
unless @fonts.empty?
|
96
|
+
res << "\n/Font << "
|
97
|
+
@fonts.each { |f| res << "\n/F#{f.font_id} #{f.oid} 0 R" }
|
98
|
+
res << " >>"
|
99
|
+
end
|
100
|
+
unless @xObjects.empty?
|
101
|
+
res << "\n/XObject << "
|
102
|
+
@xObjects.each { |x| res << "\n/#{x.label} #{x.oid} 0 R" }
|
103
|
+
res << " >>"
|
104
|
+
end
|
105
|
+
res << "\n>>"
|
106
|
+
res << "\n/MediaBox [#{@media_box.join(' ')}]" unless @media_box.nil? or @media_box.empty?
|
107
|
+
res << "\n/BleedBox [#{@bleed_box.join(' ')}]" unless @bleed_box.nil? or @bleed_box.empty?
|
108
|
+
res << "\n/TrimBox [#{@trim_box.join(' ')}]" unless @trim_box.nil? or @trim_box.empty?
|
109
|
+
end
|
110
|
+
res << "\n >>\nendobj"
|
111
|
+
else
|
112
|
+
"\n#{@oid} 0 obj\n<< /Type /Pages\n/Count 0\n>>\nendobj"
|
113
|
+
end
|
114
|
+
end
|
115
|
+
end
|
@@ -0,0 +1,46 @@
|
|
1
|
+
#--
|
2
|
+
# PDF::Writer for Ruby.
|
3
|
+
# http://rubyforge.org/projects/ruby-pdf/
|
4
|
+
# Copyright 2003 - 2005 Austin Ziegler.
|
5
|
+
#
|
6
|
+
# Licensed under a MIT-style licence. See LICENCE in the main distribution
|
7
|
+
# for full licensing information.
|
8
|
+
#
|
9
|
+
# $Id: procset.rb,v 1.2 2005/05/16 03:59:21 austin Exp $
|
10
|
+
#++
|
11
|
+
# The document Procedure Set. Not necessary in PDF 1.4 or later, but
|
12
|
+
# producing applications are recommended to provide the /ProcSet /Resource
|
13
|
+
# in any case for older viewers. Viewing applications are *not*
|
14
|
+
# recommended to rely on this information being correct.
|
15
|
+
#
|
16
|
+
# These procedure sets are used only when the content stream is printed to
|
17
|
+
# a PostScript output device; the names identify PostScript procedure sets
|
18
|
+
# that must be sent to the device to interpret the PDF operators in the
|
19
|
+
# content stream. Each element of this array must be one of the following
|
20
|
+
# predefined names: 'PDF', 'Text', 'ImageB', 'ImageC', and 'ImageI'. See
|
21
|
+
# also Appendix H note 102.
|
22
|
+
class PDF::Writer::Object::Procset < PDF::Writer::Object
|
23
|
+
def initialize(parent)
|
24
|
+
super
|
25
|
+
|
26
|
+
@info = ["PDF", "Text"]
|
27
|
+
@parent.pages.procset = self
|
28
|
+
@parent.procset = self
|
29
|
+
end
|
30
|
+
|
31
|
+
# This is to add new items to the procset list, despite the fact that
|
32
|
+
# this is considered obselete, the items are required for printing to
|
33
|
+
# some PostsCript printers.
|
34
|
+
#
|
35
|
+
# +p+ may be 'ImageB', 'ImageC', or 'ImageI'.
|
36
|
+
def <<(p)
|
37
|
+
@info << p
|
38
|
+
end
|
39
|
+
|
40
|
+
def to_s
|
41
|
+
info = @info.uniq
|
42
|
+
res = "\n#{@oid} 0 obj\n["
|
43
|
+
@info.each { |k| res << "/#{k} " }
|
44
|
+
res << "]\nendobj"
|
45
|
+
end
|
46
|
+
end
|
@@ -0,0 +1,74 @@
|
|
1
|
+
#--
|
2
|
+
# PDF::Writer for Ruby.
|
3
|
+
# http://rubyforge.org/projects/ruby-pdf/
|
4
|
+
# Copyright 2003 - 2005 Austin Ziegler.
|
5
|
+
#
|
6
|
+
# Licensed under a MIT-style licence. See LICENCE in the main distribution
|
7
|
+
# for full licensing information.
|
8
|
+
#
|
9
|
+
# $Id: viewerpreferences.rb,v 1.2 2005/05/16 03:59:21 austin Exp $
|
10
|
+
#++
|
11
|
+
# Set the viewer preferences.
|
12
|
+
#
|
13
|
+
# HideToolbar:: boolean (Optional) A flag specifying whether to hide the
|
14
|
+
# viewer application? tool bars when the document is
|
15
|
+
# active. Default value: false.
|
16
|
+
# HideMenubar:: boolean (Optional) A flag specifying whether to hide the
|
17
|
+
# viewer application? menu bar when the document is
|
18
|
+
# active. Default value: false.
|
19
|
+
# HideWindowUI:: boolean (Optional) A flag specifying whether to hide
|
20
|
+
# user interface elements in the document? window (such as
|
21
|
+
# scroll bars and navigation controls), leaving only the
|
22
|
+
# document? contents displayed. Default value: false.
|
23
|
+
# FitWindow:: boolean (Optional) A flag specifying whether to resize
|
24
|
+
# the document? window to fit the size of the first
|
25
|
+
# displayed page. Default value: false.
|
26
|
+
# CenterWindow:: boolean (Optional) A flag specifying whether to position
|
27
|
+
# the document? window in the center of the screen.
|
28
|
+
# Default value: false.
|
29
|
+
# NonFullScreenPageMode:: name (Optional) The document? page mode,
|
30
|
+
# specifying how to display the document on
|
31
|
+
# exiting full-screen mode. This entry is
|
32
|
+
# meaningful only if the value of the PageMode
|
33
|
+
# entry in the catalog dictionary is FullScreen;
|
34
|
+
# it is ignored otherwise. Default value: UseNone.
|
35
|
+
# Direction:: name (Optional; PDF 1.3) The predominant reading
|
36
|
+
# order for text: L2R Left to right R2L Right to
|
37
|
+
# left (including vertical writing systems such as
|
38
|
+
# Chinese, Japanese, and Korean) This entry has no
|
39
|
+
# direct effect on the document? contents or page
|
40
|
+
# numbering, but can be used to determine the
|
41
|
+
# relative positioning of pages when displayed
|
42
|
+
# side by side or printed n-up. Default value:
|
43
|
+
# L2R.
|
44
|
+
#
|
45
|
+
# NonFullScreenPageMode Names
|
46
|
+
# UseNone:: Neither document outline nor thumbnail images visible
|
47
|
+
# UseOutlines:: Document outline visible
|
48
|
+
# UseThumbs:: Thumbnail images visible
|
49
|
+
#
|
50
|
+
# Note that boolean values are represented by the values 'true' and
|
51
|
+
# 'false'. Also note that I have not done much testing on changing these
|
52
|
+
# values and am not sure how responsive the various viewers and browsers
|
53
|
+
# are to them (and setting the direction would be fairly meaningless as
|
54
|
+
# none of these character sets are avaliable yet.
|
55
|
+
class PDF::Writer::Object::ViewerPreferences < PDF::Writer::Object
|
56
|
+
Preferences = %w{HideToolbar HideMenubar HideWindowUI FitWindow CenterWindow NonFullScreenPageMode Direction}
|
57
|
+
|
58
|
+
def initialize(parent)
|
59
|
+
super(parent)
|
60
|
+
end
|
61
|
+
|
62
|
+
Preferences.each do |s|
|
63
|
+
attr_accessor s.downcase.intern
|
64
|
+
end
|
65
|
+
|
66
|
+
def to_s
|
67
|
+
res = "\n#{@id} 0 obj\n<< "
|
68
|
+
Preferences.each do |s|
|
69
|
+
v = __send__("#{s.downcase}".intern)
|
70
|
+
res << "\n/#{s} /#{v}" unless v.nil?
|
71
|
+
end
|
72
|
+
res << "\n>>\n"
|
73
|
+
end
|
74
|
+
end
|
@@ -0,0 +1,58 @@
|
|
1
|
+
#--
|
2
|
+
# PDF::Writer for Ruby.
|
3
|
+
# http://rubyforge.org/projects/ruby-pdf/
|
4
|
+
# Copyright 2003 - 2005 Austin Ziegler.
|
5
|
+
#
|
6
|
+
# Licensed under a MIT-style licence. See LICENCE in the main distribution
|
7
|
+
# for full licensing information.
|
8
|
+
#
|
9
|
+
# $Id: ohash.rb,v 1.2 2005/05/16 03:59:21 austin Exp $
|
10
|
+
#++
|
11
|
+
# Based on [ruby-talk:20551]. Updated to (hopefully) be 1.8 friendly.
|
12
|
+
class PDF::Writer::OHash < Hash
|
13
|
+
alias_method :store, :[]=
|
14
|
+
alias_method :each_pair, :each
|
15
|
+
|
16
|
+
def initialize(*args)
|
17
|
+
@keys = []
|
18
|
+
super
|
19
|
+
end
|
20
|
+
|
21
|
+
def []=(key, val)
|
22
|
+
@keys << key unless has_key?(key)
|
23
|
+
super
|
24
|
+
end
|
25
|
+
|
26
|
+
def delete(key)
|
27
|
+
@keys.delete(key) if has_key?(key)
|
28
|
+
super
|
29
|
+
end
|
30
|
+
|
31
|
+
def each
|
32
|
+
@keys.each { |k| yield k, self[k] }
|
33
|
+
end
|
34
|
+
|
35
|
+
def each_key
|
36
|
+
@keys.each { |k| yield k }
|
37
|
+
end
|
38
|
+
|
39
|
+
def each_value
|
40
|
+
@keys.each { |k| yield self[k] }
|
41
|
+
end
|
42
|
+
|
43
|
+
def first
|
44
|
+
self[@keys[0]]
|
45
|
+
end
|
46
|
+
|
47
|
+
def last
|
48
|
+
self[@keys[-1]]
|
49
|
+
end
|
50
|
+
|
51
|
+
def first?(item)
|
52
|
+
self[@keys[0]] == item
|
53
|
+
end
|
54
|
+
|
55
|
+
def last?(item)
|
56
|
+
self[@keys[-1]] == item
|
57
|
+
end
|
58
|
+
end
|
@@ -0,0 +1,25 @@
|
|
1
|
+
#--
|
2
|
+
# PDF::Writer for Ruby.
|
3
|
+
# http://rubyforge.org/projects/ruby-pdf/
|
4
|
+
# Copyright 2003 - 2005 Austin Ziegler.
|
5
|
+
#
|
6
|
+
# Licensed under a MIT-style licence. See LICENCE in the main distribution
|
7
|
+
# for full licensing information.
|
8
|
+
#
|
9
|
+
# $Id: oreader.rb,v 1.2 2005/05/16 03:59:21 austin Exp $
|
10
|
+
#++
|
11
|
+
module PDF::Writer::OffsetReader
|
12
|
+
def read_o(length = 1, offset = nil)
|
13
|
+
@offset ||= 0
|
14
|
+
@offset = offset if offset
|
15
|
+
ret = self[@offset, length]
|
16
|
+
@offset += length
|
17
|
+
ret
|
18
|
+
end
|
19
|
+
def offset
|
20
|
+
@offset
|
21
|
+
end
|
22
|
+
def offset=(o)
|
23
|
+
@offset = o || 0
|
24
|
+
end
|
25
|
+
end
|
@@ -0,0 +1,48 @@
|
|
1
|
+
#--
|
2
|
+
# PDF::Writer for Ruby.
|
3
|
+
# http://rubyforge.org/projects/ruby-pdf/
|
4
|
+
# Copyright 2003 - 2005 Austin Ziegler.
|
5
|
+
#
|
6
|
+
# Licensed under a MIT-style licence. See LICENCE in the main distribution
|
7
|
+
# for full licensing information.
|
8
|
+
#
|
9
|
+
# $Id: state.rb,v 1.2 2005/05/16 03:59:21 austin Exp $
|
10
|
+
#++
|
11
|
+
class PDF::Writer
|
12
|
+
class State
|
13
|
+
attr_accessor :fill_color
|
14
|
+
attr_accessor :stroke_color
|
15
|
+
attr_accessor :text_render_style
|
16
|
+
attr_accessor :stroke_style
|
17
|
+
|
18
|
+
def initialize(vals = {})
|
19
|
+
@fill_color = vals[:fill_color]
|
20
|
+
@stroke_color = vals[:stroke_color]
|
21
|
+
@text_render_style = vals[:text_render_style]
|
22
|
+
@stroke_style = vals[:stroke_style]
|
23
|
+
|
24
|
+
yield self if block_given?
|
25
|
+
end
|
26
|
+
|
27
|
+
def blank?
|
28
|
+
@fill_color.nil? and @stroke_color.nil? and @stroke_style.nil?
|
29
|
+
end
|
30
|
+
end
|
31
|
+
|
32
|
+
class StateStack < ::Array
|
33
|
+
alias_method :__push__, :push
|
34
|
+
# alias_method :__pop__, :pop
|
35
|
+
|
36
|
+
def push(obj)
|
37
|
+
return self if obj.nil?
|
38
|
+
raise TypeError unless obj.kind_of?(PDF::Writer::State)
|
39
|
+
return self if obj.blank?
|
40
|
+
__push__(obj)
|
41
|
+
end
|
42
|
+
|
43
|
+
# def pop
|
44
|
+
# ret = __pop__
|
45
|
+
# ret
|
46
|
+
# end
|
47
|
+
end
|
48
|
+
end
|
@@ -0,0 +1,138 @@
|
|
1
|
+
#--
|
2
|
+
# PDF::Writer for Ruby.
|
3
|
+
# http://rubyforge.org/projects/ruby-pdf/
|
4
|
+
# Copyright 2003 - 2005 Austin Ziegler.
|
5
|
+
#
|
6
|
+
# Licensed under a MIT-style licence. See LICENCE in the main distribution
|
7
|
+
# for full licensing information.
|
8
|
+
#
|
9
|
+
# $Id: strokestyle.rb,v 1.5 2005/06/02 21:20:35 austin Exp $
|
10
|
+
#++
|
11
|
+
# A class that represents a style with which lines will be drawn.
|
12
|
+
class PDF::Writer::StrokeStyle
|
13
|
+
LINE_CAPS = { :butt => 0, :round => 1, :square => 2 }
|
14
|
+
LINE_JOINS = { :miter => 0, :round => 1, :bevel => 2 }
|
15
|
+
SOLID_LINE = { :pattern => [], :phase => 0 }
|
16
|
+
|
17
|
+
def initialize(width = 1, options = {})
|
18
|
+
@width = width
|
19
|
+
@cap = options[:cap]
|
20
|
+
@join = options[:join]
|
21
|
+
@dash = options[:dash]
|
22
|
+
@miter_limit = options[:miter_limit]
|
23
|
+
|
24
|
+
yield self if block_given?
|
25
|
+
end
|
26
|
+
|
27
|
+
DEFAULT = self.new(1, :cap => :butt, :join => :miter, :dash => SOLID_LINE)
|
28
|
+
|
29
|
+
# The thickness of the line in PDF units.
|
30
|
+
attr_accessor :width
|
31
|
+
# The type of cap to put on the line.
|
32
|
+
#
|
33
|
+
# <tt>:butt</tt>:: The stroke is squared off at the endpoint of the
|
34
|
+
# path. There is no projection beyond the end of the
|
35
|
+
# path.
|
36
|
+
# <tt>:round</tt>:: A semicircular arc with a diameter equal to the
|
37
|
+
# line width is drawn around the endpoint and filled
|
38
|
+
# in.
|
39
|
+
# <tt>:square</tt>:: The stroke continues beyond the endpoint of the
|
40
|
+
# path for a distance equal to half the line width
|
41
|
+
# and is squared off.
|
42
|
+
# +nil+:: Keeps the current line cap.
|
43
|
+
attr_accessor :cap
|
44
|
+
def cap=(c) #:nodoc:
|
45
|
+
if c.nil? or LINE_CAPS.include?(c)
|
46
|
+
@cap = c
|
47
|
+
else
|
48
|
+
raise ArgumentError, "Line cap styles must be nil (none), butt, round, or square."
|
49
|
+
end
|
50
|
+
end
|
51
|
+
# How two lines join together.
|
52
|
+
#
|
53
|
+
# <tt>:miter</tt>:: The outer edges of the strokes for the two
|
54
|
+
# segments are extended until they meet at an angle,
|
55
|
+
# as in a picture frame. If the segments meet at too
|
56
|
+
# sharp an angle (as defined by the #miter_limit), a
|
57
|
+
# bevel join is used instead.
|
58
|
+
# <tt>:round</tt>:: An arc of a circle with a diameter equal to the
|
59
|
+
# line width is drawn around the point where the two
|
60
|
+
# segments meet, connecting the outer edges of the
|
61
|
+
# strokes for the two segments. This pie-slice
|
62
|
+
# shaped figure is filled in, producing a rounded
|
63
|
+
# corner.
|
64
|
+
# <tt>:bevel</tt>:: The two segments are finished with butt caps and
|
65
|
+
# the the resulting notch beyond the ends of the
|
66
|
+
# segments is filled with a triangle, forming a
|
67
|
+
# flattened edge on the join.
|
68
|
+
# +nil+:: Keeps the current line join.
|
69
|
+
attr_accessor :join
|
70
|
+
def join=(j) #:nodoc:
|
71
|
+
if j.nil? or LINE_JOINS.include?(j)
|
72
|
+
@join = j
|
73
|
+
else
|
74
|
+
raise ArgumentError, "Line join styles must be nil (none), miter, round, or bevel."
|
75
|
+
end
|
76
|
+
end
|
77
|
+
# When two line segments meet and <tt>:miter</tt> joins have been
|
78
|
+
# specified, the miter may extend far beyond the thickness of the line
|
79
|
+
# stroking the path. #miter_limit imposes a maximum ratio miter length
|
80
|
+
# to line width at which point the join will be converted from a miter
|
81
|
+
# to a bevel. Adobe points out that the ratio is directly related to the
|
82
|
+
# angle between the segments in user space. With [p] representing the
|
83
|
+
# angle at which the segments meet:
|
84
|
+
#
|
85
|
+
# miter_length / line_width == 1 / (sin ([p] / 2))
|
86
|
+
#
|
87
|
+
# A miter limit of 1.414 converts miters to bevels for [p] less than 90
|
88
|
+
# degrees, a limit of 2.0 converts them for [p] less than 60 degrees,
|
89
|
+
# and a limit of 10.0 converts them for [p] less than approximately 11.5
|
90
|
+
# degrees.
|
91
|
+
attr_accessor :miter_limit
|
92
|
+
# Controls the pattern of dashes and gaps used to stroke paths. This
|
93
|
+
# value must either be +nil+, or a hash with the following values:
|
94
|
+
#
|
95
|
+
# <tt>:pattern</tt>:: An array of numbers specifying the lengths (in PDF
|
96
|
+
# userspace units) of alternating dashes and gaps.
|
97
|
+
# The array is processed cyclically, so that a
|
98
|
+
# <tt>:pattern</tt> of [3] represents three units
|
99
|
+
# on, three units off, and a <tt>:pattern</tt> of
|
100
|
+
# [2, 1] represents two units on, one unit off.
|
101
|
+
#
|
102
|
+
# # - represents on, _ represents off
|
103
|
+
# ---___---___--- # pattern [3]
|
104
|
+
# --_--_--_--_--_ # pattern [2, 1]
|
105
|
+
#
|
106
|
+
# <tt>:phase</tt>:: The offset in the <tt>:pattern</tt> where the
|
107
|
+
# drawing of the stroke begins. Using a
|
108
|
+
# <tt>:phase</tt> of 1, the <tt>:pattern</tt> [3]
|
109
|
+
# will start offset by one phase, for two units on,
|
110
|
+
# three units off, three units on.
|
111
|
+
#
|
112
|
+
# --___---___---_ # pattern [3], phase 1
|
113
|
+
# -_--_--_--_--_- # pattern [2, 1], phase 1
|
114
|
+
#
|
115
|
+
# The constant SOLID_LINE may be used to restore line drawing to a solid
|
116
|
+
# line; this corresponds to an empty pattern with zero phase ([] 0).
|
117
|
+
#
|
118
|
+
# Dashed lines wrap around curves and corners just as solid stroked
|
119
|
+
# lines do, with normal cap and join handling with no consideration of
|
120
|
+
# the dash pattern. A path with several subpaths treats each subpath
|
121
|
+
# independently; the complete dash pattern is restarted at the beginning
|
122
|
+
# of each subpath.
|
123
|
+
attr_accessor :dash
|
124
|
+
|
125
|
+
def render(debug = false)
|
126
|
+
s = ""
|
127
|
+
s << "#{width} w" if @width > 0
|
128
|
+
s << " #{LINE_CAPS[@cap]} J" if @cap
|
129
|
+
s << " #{LINE_JOINS[@join]} j" if @join
|
130
|
+
s << " #{@miter_limit} M" if @miter_limit
|
131
|
+
if @dash
|
132
|
+
s << " ["
|
133
|
+
@dash[:pattern].each { |len| s << " #{len}" }
|
134
|
+
s << " ] #{@dash[:phase] or 0} d"
|
135
|
+
end
|
136
|
+
s
|
137
|
+
end
|
138
|
+
end
|