forked from prawnpdf/prawn
/
patterns.rb
137 lines (118 loc) · 4.33 KB
/
patterns.rb
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
# encoding: utf-8
# patterns.rb : Implements axial & radial gradients
#
# Originally implemented by Wojciech Piekutowski. November, 2009
# Copyright September 2012, Alexander Mankuta. All Rights Reserved.
#
# This is free software. Please see the LICENSE and COPYING files for details.
#
module Prawn
module Graphics
module Patterns
# Sets the fill gradient from color1 to color2.
# old arguments: point, width, height, color1, color2, options = {}
# new arguments: from, to, color1, color1
# or from, r1, to, r2, color1, color2
def fill_gradient(*args)
if args[1].is_a?(Array) || args[2].is_a?(Array)
set_gradient(:fill, *args)
else
warn "[DEPRECATION] 'fill_gradient(point, width, height,...)' is deprecated in favor of 'fill_gradient(from, to,...)'. " +
"Old arguments will be removed in release 1.1"
set_gradient :fill, args[0], [args[0].first, args[0].last - args[2]], args[3], args[4]
end
end
# Sets the stroke gradient from color1 to color2.
# old arguments: point, width, height, color1, color2, options = {}
# new arguments: from, to, color1, color2
# or from, r1, to, r2, color1, color2
def stroke_gradient(*args)
if args[1].is_a?(Array) || args[2].is_a?(Array)
set_gradient(:stroke, *args)
else
warn "[DEPRECATION] 'stroke_gradient(point, width, height,...)' is deprecated in favor of 'stroke_gradient(from, to,...)'. " +
"Old arguments will be removed in release 1.1"
set_gradient :stroke, args[0], [args[0].first, args[0].last - args[2]], args[3], args[4]
end
end
private
def set_gradient(type, *grad)
patterns = page.resources[:Pattern] ||= {}
registry_key = gradient_registry_key grad
if patterns["SP#{registry_key}"]
shading = patterns["SP#{registry_key}"]
else
unless shading = gradient_registry[registry_key]
shading = gradient(*grad)
gradient_registry[registry_key] = shading
end
patterns["SP#{registry_key}"] = shading
end
operator = case type
when :fill
'scn'
when :stroke
'SCN'
else
raise ArgumentError, "unknown type '#{type}'"
end
set_color_space type, :Pattern
add_content "/SP#{registry_key} #{operator}"
end
def gradient_registry_key(gradient)
if gradient[1].is_a?(Array) # axial
[
map_to_absolute(gradient[0]),
map_to_absolute(gradient[1]),
gradient[2], gradient[3]
]
else # radial
[
map_to_absolute(gradient[0]),
gradient[1],
map_to_absolute(gradient[2]),
gradient[3],
gradient[4], gradient[5]
]
end.hash
end
def gradient_registry
@gradient_registry ||= {}
end
def gradient(*args)
if args.length != 4 && args.length != 6
raise ArgumentError, "Unknown type of gradient: #{args.inspect}"
end
color1 = normalize_color(args[-2]).dup.freeze
color2 = normalize_color(args[-1]).dup.freeze
if color_type(color1) != color_type(color2)
raise ArgumentError, "Both colors must be of the same color space: #{color1.inspect} and #{color2.inspect}"
end
process_color color1
process_color color2
shader = ref!({
:FunctionType => 2,
:Domain => [0.0, 1.0],
:C0 => color1,
:C1 => color2,
:N => 1.0,
})
shading = ref!({
:ShadingType => args.length == 4 ? 2 : 3, # axial : radial shading
:ColorSpace => color_space(color1),
:Coords => args.length == 4 ?
[0, 0, args[1].first - args[0].first, args[1].last - args[0].last] :
[0, 0, args[1], args[2].first - args[0].first, args[2].last - args[0].last, args[3]],
:Function => shader,
:Extend => [true, true],
})
shading_pattern = ref!({
:PatternType => 2, # shading pattern
:Shading => shading,
:Matrix => [1, 0,
0, 1] + map_to_absolute(args[0]),
})
end
end
end
end