prep 0.2.2
Sign up to get free protection for your applications and to get access to all the features.
- data/.document +5 -0
- data/.rspec +1 -0
- data/Gemfile +15 -0
- data/Gemfile.lock +30 -0
- data/LICENSE.txt +20 -0
- data/README.rdoc +24 -0
- data/Rakefile +51 -0
- data/VERSION +1 -0
- data/bin/prep-helper +48 -0
- data/bin/prep-test +51 -0
- data/examples/generate_group_sample.rb +4 -0
- data/examples/generate_sample.rb +4 -0
- data/examples/generate_sample2.rb +19 -0
- data/examples/generate_sample3.rb +20 -0
- data/examples/generate_sample4.rb +31 -0
- data/examples/generate_sample5.rb +74 -0
- data/examples/generate_sample6.rb +40 -0
- data/examples/generate_sample_dataset.rb +9 -0
- data/examples/group_sample.yml +121 -0
- data/examples/sample.yml +90 -0
- data/examples/sample2.yml +164 -0
- data/examples/sample3.yml +206 -0
- data/examples/sample5.yml +116 -0
- data/examples/sample6.yml +127 -0
- data/lib/core/color.rb +47 -0
- data/lib/core/drawable.rb +163 -0
- data/lib/core/group.rb +193 -0
- data/lib/core/label.rb +125 -0
- data/lib/core/line.rb +95 -0
- data/lib/core/loop.rb +584 -0
- data/lib/core/page.rb +87 -0
- data/lib/core/page_ext.rb +14 -0
- data/lib/core/point.rb +26 -0
- data/lib/core/prep.rb +351 -0
- data/lib/core/rectangle.rb +137 -0
- data/lib/core/region.rb +54 -0
- data/lib/mm2pixcel.rb +5 -0
- data/lib/prep.rb +175 -0
- data/prep.gemspec +108 -0
- data/spec/component_spec.rb +5 -0
- data/spec/prep_spec.rb +7 -0
- data/spec/spec_helper.rb +12 -0
- metadata +197 -0
@@ -0,0 +1,116 @@
|
|
1
|
+
page:
|
2
|
+
size: a4
|
3
|
+
orientation: portrait
|
4
|
+
content:
|
5
|
+
type: group
|
6
|
+
out_table:
|
7
|
+
type: loop
|
8
|
+
x: 0
|
9
|
+
y: 0
|
10
|
+
direction: vertical
|
11
|
+
page_break: true
|
12
|
+
gap: 2
|
13
|
+
header: out_table_header
|
14
|
+
iterator: out_table_content
|
15
|
+
footer: out_table_footer
|
16
|
+
|
17
|
+
# 外側のテーブル定義
|
18
|
+
out_table_content:
|
19
|
+
type: group
|
20
|
+
inner_table:
|
21
|
+
type: loop
|
22
|
+
x: 0
|
23
|
+
y: 0
|
24
|
+
direction: vertical
|
25
|
+
page_break: false
|
26
|
+
gap: 1
|
27
|
+
header: inner_table_header
|
28
|
+
iterator: inner_table_content
|
29
|
+
footer: inner_table_footer
|
30
|
+
out_table_header:
|
31
|
+
type: group
|
32
|
+
out_table_header_label:
|
33
|
+
type: label
|
34
|
+
label: 外側のテーブルヘッダ
|
35
|
+
region:
|
36
|
+
x: 0
|
37
|
+
y: 0
|
38
|
+
width: 100
|
39
|
+
height: 10
|
40
|
+
out_table_header_rect:
|
41
|
+
type: rectangle
|
42
|
+
region:
|
43
|
+
x: 0
|
44
|
+
y: 0
|
45
|
+
width: 100
|
46
|
+
height: 10
|
47
|
+
out_table_footer:
|
48
|
+
type: group
|
49
|
+
out_table_footer_label:
|
50
|
+
type: label
|
51
|
+
label: 外側のテーブルフッタ
|
52
|
+
region:
|
53
|
+
x: 0
|
54
|
+
y: 0
|
55
|
+
width: 100
|
56
|
+
height: 10
|
57
|
+
out_table_footer_rect:
|
58
|
+
type: rectangle
|
59
|
+
region:
|
60
|
+
x: 0
|
61
|
+
y: 0
|
62
|
+
width: 100
|
63
|
+
height: 10
|
64
|
+
|
65
|
+
# 内側のテーブル定義
|
66
|
+
inner_table_header:
|
67
|
+
type: group
|
68
|
+
inner_table_header_label:
|
69
|
+
type: label
|
70
|
+
label: 内側のテーブルヘッダ
|
71
|
+
region:
|
72
|
+
x: 0
|
73
|
+
y: 0
|
74
|
+
width: 100
|
75
|
+
height: 10
|
76
|
+
inner_table_header_rect:
|
77
|
+
type: rectangle
|
78
|
+
region:
|
79
|
+
x: 0
|
80
|
+
y: 0
|
81
|
+
width: 100
|
82
|
+
height: 10
|
83
|
+
inner_table_content:
|
84
|
+
type: group
|
85
|
+
inner_table_content_column01_label:
|
86
|
+
type: label
|
87
|
+
label: 値1
|
88
|
+
region:
|
89
|
+
x: 0
|
90
|
+
y: 0
|
91
|
+
width: 200
|
92
|
+
height: 10
|
93
|
+
inner_table_content_column01_rect:
|
94
|
+
type: rectangle
|
95
|
+
region:
|
96
|
+
x: 0
|
97
|
+
y: 0
|
98
|
+
width: 200
|
99
|
+
height: 10
|
100
|
+
inner_table_footer:
|
101
|
+
type: group
|
102
|
+
inner_table_footer_label:
|
103
|
+
type: label
|
104
|
+
label: 内側のテーブルフッタ
|
105
|
+
region:
|
106
|
+
x: 0
|
107
|
+
y: 0
|
108
|
+
width: 100
|
109
|
+
height: 10
|
110
|
+
inner_table_footer_rect:
|
111
|
+
type: rectangle
|
112
|
+
region:
|
113
|
+
x: 0
|
114
|
+
y: 0
|
115
|
+
width: 100
|
116
|
+
height: 10
|
@@ -0,0 +1,127 @@
|
|
1
|
+
page:
|
2
|
+
size: a4
|
3
|
+
orientation: portrait
|
4
|
+
margin:
|
5
|
+
top: 10
|
6
|
+
left: 10
|
7
|
+
bottom: 10
|
8
|
+
right: 10
|
9
|
+
content:
|
10
|
+
type: group
|
11
|
+
out_table:
|
12
|
+
type: loop
|
13
|
+
x: 0
|
14
|
+
y: 0
|
15
|
+
direction: vertical
|
16
|
+
page_break: false
|
17
|
+
gap: 0
|
18
|
+
header: out_table_header
|
19
|
+
iterator: out_table_content
|
20
|
+
footer: out_table_footer
|
21
|
+
|
22
|
+
# 外側のテーブル定義
|
23
|
+
out_table_content:
|
24
|
+
type: group
|
25
|
+
inner_table:
|
26
|
+
type: loop
|
27
|
+
x: 0
|
28
|
+
y: 0
|
29
|
+
direction: horizontal
|
30
|
+
page_break: false
|
31
|
+
gap: 0
|
32
|
+
header: inner_table_header
|
33
|
+
iterator: inner_table_content
|
34
|
+
footer: inner_table_footer
|
35
|
+
out_table_header:
|
36
|
+
type: group
|
37
|
+
out_table_header_label:
|
38
|
+
type: label
|
39
|
+
label: 外側のテーブルヘッダ
|
40
|
+
align: center
|
41
|
+
expand: true
|
42
|
+
region:
|
43
|
+
x: 0
|
44
|
+
y: 0
|
45
|
+
width: 30
|
46
|
+
height: 10
|
47
|
+
out_table_header_rect:
|
48
|
+
type: rectangle
|
49
|
+
expand: true
|
50
|
+
region:
|
51
|
+
x: 0
|
52
|
+
y: 0
|
53
|
+
width: 30
|
54
|
+
height: 10
|
55
|
+
out_table_footer:
|
56
|
+
type: group
|
57
|
+
out_table_footer_label:
|
58
|
+
type: label
|
59
|
+
label: 外側のテーブルフッタ
|
60
|
+
align: center
|
61
|
+
expand: true
|
62
|
+
region:
|
63
|
+
x: 0
|
64
|
+
y: 0
|
65
|
+
width: 30
|
66
|
+
height: 10
|
67
|
+
out_table_header_rect:
|
68
|
+
type: rectangle
|
69
|
+
expand: true
|
70
|
+
region:
|
71
|
+
x: 0
|
72
|
+
y: 0
|
73
|
+
width: 30
|
74
|
+
height: 10
|
75
|
+
|
76
|
+
# 内側のテーブル定義
|
77
|
+
inner_table_content:
|
78
|
+
type: group
|
79
|
+
inner_table_content_column01_label:
|
80
|
+
type: label
|
81
|
+
label: 値1
|
82
|
+
region:
|
83
|
+
x: 0
|
84
|
+
y: 0
|
85
|
+
width: 30
|
86
|
+
height: 10
|
87
|
+
inner_table_content_column01_rect:
|
88
|
+
type: rectangle
|
89
|
+
region:
|
90
|
+
x: 0
|
91
|
+
y: 0
|
92
|
+
width: 30
|
93
|
+
height: 10
|
94
|
+
inner_table_header:
|
95
|
+
type: group
|
96
|
+
inner_table_header_title:
|
97
|
+
type: label
|
98
|
+
label: 内側のテーブルヘッダ
|
99
|
+
region:
|
100
|
+
x: 0
|
101
|
+
y: 0
|
102
|
+
width: 30
|
103
|
+
height: 10
|
104
|
+
inner_table_header_column01_rect:
|
105
|
+
type: rectangle
|
106
|
+
region:
|
107
|
+
x: 0
|
108
|
+
y: 0
|
109
|
+
width: 30
|
110
|
+
height: 10
|
111
|
+
inner_table_footer:
|
112
|
+
type: group
|
113
|
+
inner_table_footer_column01_label:
|
114
|
+
type: label
|
115
|
+
label: 内側のテーブルフッタ
|
116
|
+
region:
|
117
|
+
x: 0
|
118
|
+
y: 0
|
119
|
+
width: 30
|
120
|
+
height: 10
|
121
|
+
inner_table_footer_column01_rect:
|
122
|
+
type: rectangle
|
123
|
+
region:
|
124
|
+
x: 0
|
125
|
+
y: 0
|
126
|
+
width: 30
|
127
|
+
height: 10
|
data/lib/core/color.rb
ADDED
@@ -0,0 +1,47 @@
|
|
1
|
+
# Color クラスのソースファイル
|
2
|
+
# Author:: maki-tetsu
|
3
|
+
# Date:: 2011/03/11
|
4
|
+
# Copyright:: Copyright (c) 2011 maki-tetsu
|
5
|
+
|
6
|
+
module PREP # nodoc
|
7
|
+
module Core # nodoc
|
8
|
+
class Color
|
9
|
+
attr_reader :red, :green, :blue
|
10
|
+
|
11
|
+
def initialize(red, green, blue)
|
12
|
+
self.red = red
|
13
|
+
self.green = green
|
14
|
+
self.blue = blue
|
15
|
+
end
|
16
|
+
|
17
|
+
# 全ての色設定が 255 の場合は白として扱う
|
18
|
+
def white?
|
19
|
+
return red == 1.0 && green == 1.0 && blue == 1.0
|
20
|
+
end
|
21
|
+
|
22
|
+
def red=(red)
|
23
|
+
if red >= 0.0 && red <= 1.0
|
24
|
+
@red = red
|
25
|
+
else
|
26
|
+
raise "Color red must be include range 0..1."
|
27
|
+
end
|
28
|
+
end
|
29
|
+
|
30
|
+
def green=(green)
|
31
|
+
if green >= 0.0 && green <= 1.0
|
32
|
+
@green = green
|
33
|
+
else
|
34
|
+
raise "Color green must be include range 0..1."
|
35
|
+
end
|
36
|
+
end
|
37
|
+
|
38
|
+
def blue=(blue)
|
39
|
+
if blue >= 0.0 && blue <= 1.0
|
40
|
+
@blue = blue
|
41
|
+
else
|
42
|
+
raise "Color blue must be include range 0..1."
|
43
|
+
end
|
44
|
+
end
|
45
|
+
end
|
46
|
+
end
|
47
|
+
end
|
@@ -0,0 +1,163 @@
|
|
1
|
+
# Drawable クラスのソースファイル
|
2
|
+
# Author:: maki-tetsu
|
3
|
+
# Date:: 2011/03/11
|
4
|
+
# Copyright:: Copyright (c) 2011 maki-tetsu
|
5
|
+
|
6
|
+
module PREP # nodoc
|
7
|
+
module Core # nodoc
|
8
|
+
# 描画機能が実装されていない場合に発行される例外クラス
|
9
|
+
class NotImplementedError < StandardError; end
|
10
|
+
# 再描画時に元の場所まで戻ったときにその時のリージョンセットを伴って戻る例外
|
11
|
+
class ReRenderJump < StandardError
|
12
|
+
attr_reader :region
|
13
|
+
|
14
|
+
def initialize(region)
|
15
|
+
@region = region
|
16
|
+
end
|
17
|
+
end
|
18
|
+
|
19
|
+
# 構成要素を表現する基底クラス
|
20
|
+
#
|
21
|
+
# Label, Line, Rectangle などの描画構成要素の基底クラス.
|
22
|
+
# 描画に必要となる基本的な機能が実装されている.
|
23
|
+
class Drawable
|
24
|
+
attr_reader :identifier, :layer
|
25
|
+
|
26
|
+
# 初期化
|
27
|
+
def initialize(identifier, layer = 1)
|
28
|
+
STDERR.puts("Initializing #{self.class}: #{identifier}") if ENV['DEBUG']
|
29
|
+
@identifier = identifier
|
30
|
+
@layer = layer.to_i
|
31
|
+
end
|
32
|
+
|
33
|
+
# 描画領域計算
|
34
|
+
def calculate_region(prep, region, values, stop_on_drawable = nil)
|
35
|
+
raise NotImplementedError.new
|
36
|
+
end
|
37
|
+
|
38
|
+
# 比較メソッド
|
39
|
+
def <=>(other)
|
40
|
+
unless Drawable === other
|
41
|
+
raise ArgumentError.new
|
42
|
+
end
|
43
|
+
return @layer <=> other.layer
|
44
|
+
end
|
45
|
+
|
46
|
+
# 描画処理の呼び出し
|
47
|
+
#
|
48
|
+
# 継承先で実装されるべきメソッド
|
49
|
+
# 引数として描画可能領域を表現するリージョンインスタンス、
|
50
|
+
# および、関連する値のハッシュが渡されます。
|
51
|
+
# 描画対象は Prep#current_page から取得します。
|
52
|
+
def draw(prep, region, values, stop_on_drawable = nil)
|
53
|
+
raise NotImplementedError.new
|
54
|
+
end
|
55
|
+
|
56
|
+
# ハッシュに対して再帰的にキーが文字列の場合にシンボルに置換
|
57
|
+
def key_string_to_symbol(hash)
|
58
|
+
if Hash === hash
|
59
|
+
ret_hash = hash.keys.inject({ }) do |h, key|
|
60
|
+
case hash[key]
|
61
|
+
when Hash
|
62
|
+
h[key.to_sym] = key_string_to_symbol(hash[key])
|
63
|
+
else
|
64
|
+
h[key.to_sym] = hash[key]
|
65
|
+
end
|
66
|
+
|
67
|
+
next h
|
68
|
+
end
|
69
|
+
return ret_hash
|
70
|
+
else
|
71
|
+
raise "Argument not Hash."
|
72
|
+
end
|
73
|
+
end
|
74
|
+
|
75
|
+
# 座標変換
|
76
|
+
#
|
77
|
+
# 実際に PDF 上に配置する際の座標に変換
|
78
|
+
# 絶対補正座標と相対座標の組みで渡されて
|
79
|
+
# x, y のリストで返却される
|
80
|
+
def calculate_pos(page, region, x, y)
|
81
|
+
# 絶対座標変換
|
82
|
+
x = region.x + x
|
83
|
+
y = region.y + y
|
84
|
+
# Y 座標反転
|
85
|
+
return x, page.get_height - y
|
86
|
+
end
|
87
|
+
|
88
|
+
# 領域計算前後で現在位置を保持して戻すためのブロック付きメソッド
|
89
|
+
#
|
90
|
+
# Prep インスタンスと必要に応じて元ループの方向を示す
|
91
|
+
# 元ループの方向と内部のページ遷移方向が異なる場合のみページを元に戻す
|
92
|
+
# 親の方向が指定されない場合は無条件にページを戻す
|
93
|
+
def rewind_current_page(prep, parent_direction = nil)
|
94
|
+
# 領域計算中にページ移動が発生した場合に戻すために保持
|
95
|
+
current_page_x, current_page_y = prep.page_pos_x, prep.page_pos_y
|
96
|
+
begin
|
97
|
+
values = yield
|
98
|
+
rescue ReRenderJump => e
|
99
|
+
# ページの移動方向を確認
|
100
|
+
# 設定ファイルの構成によっては両方に遷移する可能性があるがそれはエラーとする
|
101
|
+
horizontal_page_move = prep.page_pos_x - current_page_x
|
102
|
+
vertical_page_move = prep.page_pos_y - current_page_y
|
103
|
+
if horizontal_page_move < 0 # 左方向の遷移を検出したのでエラー
|
104
|
+
raise "Page move to left error!"
|
105
|
+
end
|
106
|
+
if vertical_page_move < 0 # 上方向の遷移を検出したのでエラー
|
107
|
+
raise "Page move to up error!"
|
108
|
+
end
|
109
|
+
if horizontal_page_move != 0 && vertical_page_move != 0
|
110
|
+
# 水平、垂直両方向への遷移を検出したのでエラー
|
111
|
+
raise "Page move is too difficult!!(Please wait...)"
|
112
|
+
end
|
113
|
+
if parent_direction.nil?
|
114
|
+
if horizontal_page_move != 0 || vertical_page_move != 0
|
115
|
+
# 方向指定がない場合は戻す
|
116
|
+
prep.current_page = { :x => current_page_x, :y => current_page_y }
|
117
|
+
puts "Rewind page index to [#{current_page_x}:#{current_page_y}]" if ENV["DEBUG"]
|
118
|
+
end
|
119
|
+
elsif parent_direction == Loop::DIRECTIONS[:horizontal] && vertical_page_move > 0
|
120
|
+
# 方向指定と異なる方向の場合は戻す(ループは水平、ページは垂直)
|
121
|
+
prep.current_page = { :x => current_page_x, :y => current_page_y }
|
122
|
+
puts "Rewind page index to [#{current_page_x}:#{current_page_y}]" if ENV["DEBUG"]
|
123
|
+
elsif parent_direction == Loop::DIRECTIONS[:vertical] && horizontal_page_move > 0
|
124
|
+
# 方向指定と異なる方向の場合は戻す(ループは垂直、ページは水平)
|
125
|
+
prep.current_page = { :x => current_page_x, :y => current_page_y }
|
126
|
+
puts "Rewind page index to [#{current_page_x}:#{current_page_y}]" if ENV["DEBUG"]
|
127
|
+
end
|
128
|
+
raise e
|
129
|
+
end
|
130
|
+
# 現在のページ番号を元に戻す
|
131
|
+
horizontal_page_move = prep.page_pos_x - current_page_x
|
132
|
+
vertical_page_move = prep.page_pos_y - current_page_y
|
133
|
+
if horizontal_page_move < 0 # 左方向の遷移を検出したのでエラー
|
134
|
+
raise "Page move to left error!"
|
135
|
+
end
|
136
|
+
if vertical_page_move < 0 # 上方向の遷移を検出したのでエラー
|
137
|
+
raise "Page move to up error!"
|
138
|
+
end
|
139
|
+
if horizontal_page_move != 0 && vertical_page_move != 0
|
140
|
+
# 水平、垂直両方向への遷移を検出したのでエラー
|
141
|
+
raise "Page move is too difficult!!(Please wait...)"
|
142
|
+
end
|
143
|
+
if parent_direction.nil?
|
144
|
+
if horizontal_page_move != 0 || vertical_page_move != 0
|
145
|
+
# 方向指定がない場合は戻す
|
146
|
+
prep.current_page = { :x => current_page_x, :y => current_page_y }
|
147
|
+
puts "Rewind page index to [#{current_page_x}:#{current_page_y}]" if ENV["DEBUG"]
|
148
|
+
end
|
149
|
+
elsif parent_direction == Loop::DIRECTIONS[:horizontal] && vertical_page_move > 0
|
150
|
+
# 方向指定と異なる方向の場合は戻す(ループは水平、ページは垂直)
|
151
|
+
prep.current_page = { :x => current_page_x, :y => current_page_y }
|
152
|
+
puts "Rewind page index to [#{current_page_x}:#{current_page_y}]" if ENV["DEBUG"]
|
153
|
+
elsif parent_direction == Loop::DIRECTIONS[:vertical] && horizontal_page_move > 0
|
154
|
+
# 方向指定と異なる方向の場合は戻す(ループは垂直、ページは水平)
|
155
|
+
prep.current_page = { :x => current_page_x, :y => current_page_y }
|
156
|
+
puts "Rewind page index to [#{current_page_x}:#{current_page_y}]" if ENV["DEBUG"]
|
157
|
+
end
|
158
|
+
|
159
|
+
return values
|
160
|
+
end
|
161
|
+
end
|
162
|
+
end
|
163
|
+
end
|