prune 0.0.4

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 (78) hide show
  1. data/CHANGELOG.ja.txt +16 -0
  2. data/CHANGELOG.txt +16 -0
  3. data/MIT-LICENSE.ja.txt +24 -0
  4. data/MIT-LICENSE.txt +20 -0
  5. data/Manifest.txt +77 -0
  6. data/PostInstall.txt +4 -0
  7. data/README.ja.rdoc +39 -0
  8. data/README.rdoc +39 -0
  9. data/Rakefile +28 -0
  10. data/demo/english_fonts.rb +66 -0
  11. data/demo/japanese_encodings_euc_jp.rb +27 -0
  12. data/demo/japanese_encodings_shift_jis.rb +27 -0
  13. data/demo/japanese_fonts.rb +54 -0
  14. data/demo/tables.rb +52 -0
  15. data/demo/text_decoration.rb +55 -0
  16. data/lib/prune.rb +90 -0
  17. data/lib/prune/constants.rb +39 -0
  18. data/lib/prune/document.rb +101 -0
  19. data/lib/prune/elements/base.rb +55 -0
  20. data/lib/prune/elements/catalog.rb +51 -0
  21. data/lib/prune/elements/font.rb +38 -0
  22. data/lib/prune/elements/font_descriptor.rb +38 -0
  23. data/lib/prune/elements/info.rb +44 -0
  24. data/lib/prune/elements/outlines.rb +19 -0
  25. data/lib/prune/elements/page.rb +115 -0
  26. data/lib/prune/elements/pages.rb +29 -0
  27. data/lib/prune/elements/procedure_sets.rb +22 -0
  28. data/lib/prune/elements/stream.rb +34 -0
  29. data/lib/prune/errors.rb +73 -0
  30. data/lib/prune/fonts/base.rb +92 -0
  31. data/lib/prune/fonts/base_en.rb +38 -0
  32. data/lib/prune/fonts/base_ja.rb +129 -0
  33. data/lib/prune/fonts/en/courier.rb +37 -0
  34. data/lib/prune/fonts/en/helvetica.rb +168 -0
  35. data/lib/prune/fonts/en/symbol.rb +60 -0
  36. data/lib/prune/fonts/en/times_roman.rb +168 -0
  37. data/lib/prune/fonts/en/zapf_dingbats.rb +60 -0
  38. data/lib/prune/fonts/ja/ms_gothic.rb +55 -0
  39. data/lib/prune/fonts/ja/ms_mincho.rb +55 -0
  40. data/lib/prune/fonts/ja/ms_p_gothic.rb +55 -0
  41. data/lib/prune/fonts/ja/ms_p_mincho.rb +55 -0
  42. data/lib/prune/fonts/ja/ms_pr_gothic.rb +55 -0
  43. data/lib/prune/fonts/ja/ms_ui_gothic.rb +55 -0
  44. data/lib/prune/functions.rb +18 -0
  45. data/lib/prune/p_objects/aliases.rb +37 -0
  46. data/lib/prune/p_objects/base.rb +45 -0
  47. data/lib/prune/p_objects/p_array.rb +62 -0
  48. data/lib/prune/p_objects/p_dictionary.rb +83 -0
  49. data/lib/prune/p_objects/p_hexadecimal_string.rb +27 -0
  50. data/lib/prune/p_objects/p_literal_string.rb +25 -0
  51. data/lib/prune/p_objects/p_name.rb +45 -0
  52. data/lib/prune/p_objects/p_stream.rb +29 -0
  53. data/lib/prune/parsers/base.rb +13 -0
  54. data/lib/prune/parsers/document/page/table/tr_parser.rb +77 -0
  55. data/lib/prune/parsers/document/page/table_parser.rb +32 -0
  56. data/lib/prune/parsers/document/page_parser.rb +91 -0
  57. data/lib/prune/parsers/document/property_parser.rb +45 -0
  58. data/lib/prune/parsers/document_parser.rb +26 -0
  59. data/lib/prune/shapes/base.rb +52 -0
  60. data/lib/prune/shapes/line.rb +55 -0
  61. data/lib/prune/shapes/rectangle.rb +64 -0
  62. data/lib/prune/shapes/text_box.rb +223 -0
  63. data/prune.gemspec +37 -0
  64. data/script/console +10 -0
  65. data/script/console.cmd +1 -0
  66. data/script/destroy +14 -0
  67. data/script/destroy.cmd +1 -0
  68. data/script/generate +14 -0
  69. data/script/generate.cmd +1 -0
  70. data/spec/prune/p_objects/p_array_spec.rb +46 -0
  71. data/spec/prune/p_objects/p_dictionary_spec.rb +61 -0
  72. data/spec/prune/p_objects/p_stream_spec.rb +29 -0
  73. data/spec/prune_spec.rb +38 -0
  74. data/spec/spec.opts +1 -0
  75. data/spec/spec_helper.rb +11 -0
  76. data/tasks/prune.rake +38 -0
  77. data/tasks/rspec.rake +21 -0
  78. metadata +181 -0
@@ -0,0 +1,38 @@
1
+ # -*- coding:utf-8 -*-
2
+
3
+ module Prune
4
+ module Elements
5
+ class Font < Base
6
+ # Initialize.
7
+ def initialize(document, options)
8
+ super(document)
9
+ # Set dictionary.
10
+ @content = pd(pn(:Type) => pn(:Font))
11
+ @content.update(options)
12
+ # Register element to document.
13
+ register
14
+ end
15
+
16
+ # Get name of the font.
17
+ def name
18
+ @content[pn(:Name)]
19
+ end
20
+
21
+ # Set name of the font.
22
+ def name=(name)
23
+ @content[pn(:Name)] = name
24
+ end
25
+
26
+ # Set base font.
27
+ def base_font=(base_font)
28
+ @content[pn(:BaseFont)] = base_font
29
+ end
30
+
31
+ # Get encoding of the font.
32
+ def encoding
33
+ @content[pn(:Encoding)]
34
+ end
35
+ end
36
+ end
37
+ end
38
+
@@ -0,0 +1,38 @@
1
+ # -*- coding:utf-8 -*-
2
+
3
+ module Prune
4
+ module Elements
5
+ class FontDescriptor < Base
6
+ # Initialize.
7
+ def initialize(document, options)
8
+ super(document)
9
+ # Set dictionary.
10
+ @content = pd(pn(:Type) => pn(:FontDescriptor))
11
+ @content.update(options)
12
+ # Register element to document.
13
+ register
14
+ end
15
+
16
+ # Set font name.
17
+ def font_name=(name)
18
+ @content[pn(:FontName)] = name
19
+ end
20
+
21
+ # Set italic angle.
22
+ def italic_angle=(angle)
23
+ @content[pn(:ItalicAngle)] = angle
24
+ end
25
+
26
+ # Set flags.
27
+ def flags=(flags)
28
+ @content[pn(:Flags)] = flags
29
+ end
30
+
31
+ # Set stem v.
32
+ def stem_v=(stem_v)
33
+ @content[pn(:StemV)] = stem_v
34
+ end
35
+ end
36
+ end
37
+ end
38
+
@@ -0,0 +1,44 @@
1
+ # -*- coding:utf-8 -*-
2
+ require "date"
3
+
4
+ module Prune
5
+ module Elements
6
+ class Info < Base
7
+ # Initialize.
8
+ def initialize(document)
9
+ super(document)
10
+ date = DateTime.now
11
+ creation_date = date.strftime("D:%Y%m%d%H%M%S")
12
+ creation_date << date.zone.sub(/:/, "'") + "'"
13
+ creator = "#{APPLICATION}-#{VERSION}"
14
+ # Set dictionary.
15
+ @content = pd(
16
+ pn(:CreationDate) => pl(creation_date),
17
+ pn(:ModDate) => pl(creation_date),
18
+ pn(:Author) => pl("UNKNOWN"),
19
+ pn(:Title) => pl("UNKNOWN"),
20
+ pn(:Creator) => pl(creator),
21
+ pn(:Producer) => pl(creator),
22
+ pn(:Trapped) => pn(:False))
23
+ # Register element to document.
24
+ register
25
+ end
26
+
27
+ # Set title of the document.
28
+ def title=(title)
29
+ @content[pn(:Title)] = pl(title)
30
+ end
31
+
32
+ # Set subject of the document.
33
+ def subject=(subject)
34
+ @content[pn(:Subject)] = pl(subject)
35
+ end
36
+
37
+ # Set author of the document.
38
+ def author=(author)
39
+ @content[pn(:Author)] = pl(author)
40
+ end
41
+ end
42
+ end
43
+ end
44
+
@@ -0,0 +1,19 @@
1
+ # -*- coding:utf-8 -*-
2
+
3
+ module Prune
4
+ module Elements
5
+ class Outlines < Base
6
+ # Initialize.
7
+ def initialize(document)
8
+ super(document)
9
+ # Set dictionary.
10
+ @content = pd(
11
+ pn(:Type) => pn(:Outlines),
12
+ pn(:Count) => 0)
13
+ # Register element to document.
14
+ register
15
+ end
16
+ end
17
+ end
18
+ end
19
+
@@ -0,0 +1,115 @@
1
+ # -*- coding:utf-8 -*-
2
+
3
+ module Prune
4
+ module Elements
5
+ class Page < Base
6
+ attr_reader :default_font
7
+ attr_accessor :shape_ids
8
+ attr_accessor :shapes
9
+ attr_accessor :x
10
+ attr_accessor :y
11
+ attr_accessor :current_font
12
+ attr_accessor :margin_left
13
+ attr_accessor :margin_right
14
+ attr_accessor :margin_top
15
+ attr_accessor :margin_bottom
16
+
17
+ FONT_OPTIONS = [
18
+ :name, # Font name.
19
+ :size, # Font size.
20
+ :bold, # Bold(boolean).
21
+ :italic, # Italic(boolean).
22
+ :mode, # Font color mode.
23
+ :fill_color, # Color inside font.
24
+ :stroke_color, # Color around font.
25
+ ] unless const_defined?(:FONT_OPTIONS)
26
+
27
+ # Initialize.
28
+ def initialize(document, media_box, options = {})
29
+ super(document)
30
+ # Set stream.
31
+ @stream = Stream.new(@document)
32
+
33
+ # Set dictionary.
34
+ @media_box = media_box
35
+ @content = pd(
36
+ pn(:Type) => pn(:Page),
37
+ pn(:Parent) => @document.pages.reference,
38
+ pn(:MediaBox) => pa(*@media_box),
39
+ pn(:Contents) => @stream.reference,
40
+ pn(:Resources) => pd(
41
+ pn(:ProcSet) => @document.proc_set.reference))
42
+
43
+ # Set page margin by option in millimeters(default 10mm).
44
+ %w[top left right bottom].each do |position|
45
+ value = options["margin_#{position}".to_sym] || 10.0
46
+ value = mm_to_pt(value)
47
+ instance_variable_set("@margin_#{position}", value)
48
+ end
49
+
50
+ # Set initial position.
51
+ @x = @margin_left
52
+ @y = @media_box[3] - @margin_top
53
+
54
+ # Set page default font.
55
+ initialize_font(options)
56
+ # Initialize page shapes.
57
+ @shape_ids = []
58
+ @shapes = {}
59
+ # Register element to document.
60
+ register
61
+ end
62
+
63
+ # Get stream object.
64
+ def stream
65
+ @stream.stream
66
+ end
67
+
68
+ # Get width of the page(pt).
69
+ def width
70
+ @media_box[2] - @margin_left - @margin_right
71
+ end
72
+
73
+ # Get height of the page(pt).
74
+ def height
75
+ @media_box[3] - @margin_top - @margin_bottom
76
+ end
77
+
78
+ # Set font to use.
79
+ def set_font(key, font)
80
+ # Add :Font key to content hash unless there is no key
81
+ unless @content[pn(:Resources)].has_key?(pn(:Font))
82
+ @content[pn(:Resources)].update(pn(:Font) => pd)
83
+ end
84
+ # Add font symbol to :Font hash
85
+ unless @content[pn(:Resources)][pn(:Font)].has_key?(key)
86
+ @content[pn(:Resources)][pn(:Font)].update(key => font.reference)
87
+ end
88
+ end
89
+
90
+ private
91
+ # Initialize font.
92
+ def initialize_font(options)
93
+ @current_font = {}
94
+ @default_font = {
95
+ :name => nil,
96
+ :size => 12,
97
+ :bold => false,
98
+ :italic => false,
99
+ :mode => :fill,
100
+ :fill_color => "#000000",
101
+ :stroke_color => "#000000"}
102
+ # Set default and current font from options.
103
+ if options.key?(:font)
104
+ FONT_OPTIONS.each do |sym|
105
+ if options[:font].key?(sym)
106
+ @default_font[sym] = options[:font][sym]
107
+ @current_font[sym] = @default_font[sym]
108
+ end
109
+ end
110
+ end
111
+ end
112
+ end
113
+ end
114
+ end
115
+
@@ -0,0 +1,29 @@
1
+ # -*- coding:utf-8 -*-
2
+
3
+ module Prune
4
+ module Elements
5
+ class Pages < Base
6
+ # Initialize.
7
+ def initialize(document)
8
+ super(document)
9
+ @content = pd(
10
+ pn(:Type) => pn(:Pages),
11
+ pn(:Kids) => pa,
12
+ pn(:Count) => 0)
13
+ register
14
+ end
15
+
16
+ # Determine emptyness of pages.
17
+ def empty?
18
+ @content[pn(:Kids)].empty?
19
+ end
20
+
21
+ # Add page.
22
+ def <<(page)
23
+ @content[pn(:Kids)] << page.reference
24
+ @content[pn(:Count)] += 1
25
+ end
26
+ end
27
+ end
28
+ end
29
+
@@ -0,0 +1,22 @@
1
+ # -*- coding:utf-8 -*-
2
+
3
+ module Prune
4
+ module Elements
5
+ class ProcedureSets < Base
6
+ # Initialize.
7
+ def initialize(document)
8
+ super(document)
9
+ # Set dictionary.
10
+ @content = pa(
11
+ pn(:PDF),
12
+ pn(:Text),
13
+ pn(:ImageB),
14
+ pn(:ImageC),
15
+ pn(:ImageI))
16
+ # Register element to document.
17
+ register
18
+ end
19
+ end
20
+ end
21
+ end
22
+
@@ -0,0 +1,34 @@
1
+ # -*- coding:utf-8 -*-
2
+
3
+ module Prune
4
+ module Elements
5
+ class Stream < Base
6
+ attr_reader :stream
7
+
8
+ # Initialize.
9
+ def initialize(document)
10
+ super(document)
11
+ # Set dictionary.
12
+ @content = pd(pn(:Length) => 0)
13
+ # Set stream.
14
+ @stream = ps
15
+ # Register element to document.
16
+ register
17
+ end
18
+
19
+ # Convert stream to String.
20
+ def to_s
21
+ # Update length of the stream.
22
+ @content[pn(:Length)] = @stream.length
23
+ # Convert to String.
24
+ out = []
25
+ out << "#{@element_id} #{@revision} obj"
26
+ out << @content.to_s
27
+ out << @stream.to_s
28
+ out << "endobj"
29
+ return out.join(LF)
30
+ end
31
+ end
32
+ end
33
+ end
34
+
@@ -0,0 +1,73 @@
1
+ # -*- coding:utf-8 -*-
2
+ module Prune
3
+ module Errors
4
+ #===========================================================================
5
+ # Errors for PObjects
6
+ #===========================================================================
7
+ # PDictionary can update with only PDictionary.
8
+ class PDictionaryTypeError < StandardError;end
9
+ # PDictionary key should be PName.
10
+ class PDictionaryKeyError < StandardError;end
11
+ # PHexadecimalString's content should be a String.
12
+ class PHexadecimalStringTypeError < StandardError;end
13
+ # PHexadeciamlString's content should consist of /[0-9A-F]+/.
14
+ class PHexadecimalStringContentError < StandardError;end
15
+ # PLiteralString's content should be a String.
16
+ class PLiteralStringTypeError < StandardError;end
17
+ # PName's content should be a String or a Symbol.
18
+ class PNameTypeError < StandardError;end
19
+ # PStream's content should be a String.
20
+ class PStreamTypeError < StandardError;end
21
+
22
+ #===========================================================================
23
+ # Errors for Elements
24
+ #===========================================================================
25
+ class ElementNotRegisteredError < StandardError; end
26
+
27
+ #===========================================================================
28
+ # Errors for Fonts
29
+ #===========================================================================
30
+ # Wrong options for font.
31
+ class FontOptionError < StandardError;end
32
+ # Wrong flags for font descriptor.
33
+ class FontDescriptorFlagError < StandardError;end
34
+ # Ascii font used for non-ascii string.
35
+ class NonAsciiStringError < StandardError;end
36
+
37
+ #===========================================================================
38
+ # Errors for Shapes
39
+ #===========================================================================
40
+ class DuplicateIdError < StandardError;end
41
+ # Color format error.
42
+ class ColorFormatError < StandardError;end
43
+ # Line argument error.
44
+ class LineArgumentError < StandardError;end
45
+ # Line style error.
46
+ class LineStyleError < StandardError;end
47
+ # Rectangle argument error.
48
+ class RectangleArgumentError < StandardError;end
49
+ # Rectangle style error.
50
+ class RectangleStyleError < StandardError;end
51
+ # Unexisting font.
52
+ class UnexistingFontError < StandardError;end
53
+ # Font not Specified.
54
+ class FontNotSpecifiedError < StandardError;end
55
+ # Font mode error.
56
+ class FontModeError < StandardError;end
57
+ # Text align should be :left, :center, or :right.
58
+ class TextAlignError < StandardError;end
59
+
60
+ #===========================================================================
61
+ # Errors for Document
62
+ #===========================================================================
63
+ # Document has no pages.
64
+ class DocumentEmptyError < StandardError; end
65
+
66
+ #===========================================================================
67
+ # Errors for Parsers
68
+ #===========================================================================
69
+ # Invalid PDF version.
70
+ class PdfVersionError < StandardError;end
71
+ end
72
+ end
73
+
@@ -0,0 +1,92 @@
1
+ # -*- coding:utf-8 -*-
2
+
3
+ module Prune
4
+ module Fonts
5
+ class Base
6
+ include Errors
7
+ include PObjects
8
+ include Elements
9
+
10
+ class << self
11
+ # Check bold flag.
12
+ def bold?(options)
13
+ raise FontOptionError unless
14
+ [true, false, nil].include?(options[:bold])
15
+ options[:bold] || false
16
+ end
17
+
18
+ # Check italic flag.
19
+ def italic?(options)
20
+ raise FontOptionError unless
21
+ [true, false, nil].include?(options[:italic])
22
+ options[:italic] || false
23
+ end
24
+
25
+ # Get font name.
26
+ def font_name
27
+ class_name = self.to_s.gsub(/\A.*::/, "")
28
+ class_name.gsub(/\A(.)/){$1.downcase}.gsub(/([A-Z])/){"_#{$1.downcase}"}
29
+ end
30
+ end
31
+
32
+ attr_reader :font_name
33
+
34
+ # Initialize.
35
+ def initialize(document)
36
+ @document = document
37
+ @main_element = nil
38
+ @font_name = self.class.font_name
39
+ end
40
+
41
+ # Get reference of the font.
42
+ def reference
43
+ @main_element.reference
44
+ end
45
+
46
+ # Get name of the font.
47
+ def name
48
+ @main_element.name
49
+ end
50
+
51
+ # Get encoding of the font.
52
+ def encoding
53
+ @main_element.encoding
54
+ end
55
+
56
+ # Get font symbol.
57
+ def font_sym
58
+ @font_name.to_sym
59
+ end
60
+
61
+ private
62
+ # Check bold flags.
63
+ def bold?(options)
64
+ self.class.bold?(options)
65
+ end
66
+
67
+ # Check italic flags.
68
+ def italic?(options)
69
+ self.class.italic?(options)
70
+ end
71
+
72
+ # Calculate flags.
73
+ def calculate_flags(options = {})
74
+ raise FontDescriptorFlagError unless options.values.all?{|value|
75
+ [true, false].include?(value)
76
+ }
77
+ flags = 0b00000000000000000000000000000000
78
+ flags |= 0b00000000000000000000000000000001 if options[:fixed_pitch]
79
+ flags |= 0b00000000000000000000000000000010 if options[:serif]
80
+ flags |= 0b00000000000000000000000000000100 if options[:symbolic]
81
+ flags |= 0b00000000000000000000000000001000 if options[:script]
82
+ flags |= 0b00000000000000000000000000100000 if options[:non_symbolic]
83
+ flags |= 0b00000000000000000000000001000000 if options[:italic]
84
+ flags |= 0b00000000000000010000000000000000 if options[:all_cap]
85
+ flags |= 0b00000000000000100000000000000000 if options[:small_cap]
86
+ flags |= 0b00000000000001000000000000000000 if options[:force_bold]
87
+ flags
88
+ end
89
+ end
90
+ end
91
+ end
92
+