Skip to content
Newer
Older
100644 249 lines (215 sloc) 6.31 KB
9b1ec2b commit changes from draw branch
Tony Cook authored
1 #include "imager.h"
2 #include "imrender.h"
3 #include "imageri.h"
4
5 int
6 i_compose_mask(i_img *out, i_img *src, i_img *mask,
8d14daa @tonycoz switch to using size_t and i_img_dim strictly
authored
7 i_img_dim out_left, i_img_dim out_top,
8 i_img_dim src_left, i_img_dim src_top,
9 i_img_dim mask_left, i_img_dim mask_top,
10 i_img_dim width, i_img_dim height,
9b1ec2b commit changes from draw branch
Tony Cook authored
11 int combine,
12 double opacity) {
13 i_render r;
8d14daa @tonycoz switch to using size_t and i_img_dim strictly
authored
14 i_img_dim dy;
9b1ec2b commit changes from draw branch
Tony Cook authored
15 i_fill_combine_f combinef_8;
16 i_fill_combinef_f combinef_double;
17 int channel_zero = 0;
18
8d14daa @tonycoz switch to using size_t and i_img_dim strictly
authored
19 mm_log((1, "i_compose_mask(out %p, src %p, mask %p, out(" i_DFp "), "
20 "src(" i_DFp "), mask(" i_DFp "), size(" i_DFp "),"
21 " combine %d opacity %f\n", out, src,
22 mask, i_DFcp(out_left, out_top), i_DFcp(src_left, src_top),
23 i_DFcp(mask_left, mask_top), i_DFcp(width, height),
24 combine, opacity));
618a328 @tonycoz test coverage and fix pass for compose()
authored
25
9b1ec2b commit changes from draw branch
Tony Cook authored
26 i_clear_error();
27 if (out_left >= out->xsize
28 || out_top >= out->ysize
29 || src_left >= src->xsize
30 || src_top >= src->ysize
31 || width <= 0
32 || height <= 0
33 || out_left + width <= 0
34 || out_top + height <= 0
35 || src_left + width <= 0
36 || src_top + height <= 0
37 || mask_left >= mask->xsize
38 || mask_top >= mask->ysize
39 || mask_left + width <= 0
40 || mask_top + height <= 0)
41 return 0;
42
43 if (out_left < 0) {
44 width = out_left + width;
618a328 @tonycoz test coverage and fix pass for compose()
authored
45 src_left -= out_left;
46 mask_left -= out_left;
9b1ec2b commit changes from draw branch
Tony Cook authored
47 out_left = 0;
48 }
49 if (out_left + width > out->xsize)
50 width = out->xsize - out_left;
51
52 if (out_top < 0) {
53 height = out_top + height;
618a328 @tonycoz test coverage and fix pass for compose()
authored
54 mask_top -= out_top;
55 src_top -= out_top;
9b1ec2b commit changes from draw branch
Tony Cook authored
56 out_top = 0;
57 }
58 if (out_top + height > out->ysize)
59 height = out->ysize - out_top;
60
61 if (src_left < 0) {
62 width = src_left + width;
618a328 @tonycoz test coverage and fix pass for compose()
authored
63 out_left -= src_left;
64 mask_left -= src_left;
9b1ec2b commit changes from draw branch
Tony Cook authored
65 src_left = 0;
66 }
67 if (src_left + width > src->xsize)
68 width = src->xsize - src_left;
69
70 if (src_top < 0) {
71 height = src_top + height;
618a328 @tonycoz test coverage and fix pass for compose()
authored
72 out_top -= src_top;
73 mask_top -= src_top;
9b1ec2b commit changes from draw branch
Tony Cook authored
74 src_top = 0;
75 }
76 if (src_top + height > src->ysize)
618a328 @tonycoz test coverage and fix pass for compose()
authored
77 height = src->ysize - src_top;
9b1ec2b commit changes from draw branch
Tony Cook authored
78
79 if (mask_left < 0) {
80 width = mask_left + width;
618a328 @tonycoz test coverage and fix pass for compose()
authored
81 out_left -= mask_left;
82 src_left -= mask_left;
9b1ec2b commit changes from draw branch
Tony Cook authored
83 mask_left = 0;
84 }
85 if (mask_left + width > mask->xsize)
86 width = mask->xsize - mask_left;
87
88 if (mask_top < 0) {
618a328 @tonycoz test coverage and fix pass for compose()
authored
89 height = mask_top + height;
90 src_top -= mask_top;
91 out_top -= mask_top;
9b1ec2b commit changes from draw branch
Tony Cook authored
92 mask_top = 0;
93 }
94 if (mask_top + height > mask->ysize)
618a328 @tonycoz test coverage and fix pass for compose()
authored
95 height = mask->ysize - mask_top;
9b1ec2b commit changes from draw branch
Tony Cook authored
96
97 if (opacity > 1.0)
98 opacity = 1.0;
618a328 @tonycoz test coverage and fix pass for compose()
authored
99 else if (opacity <= 0) {
100 i_push_error(0, "opacity must be positive");
9b1ec2b commit changes from draw branch
Tony Cook authored
101 return 0;
618a328 @tonycoz test coverage and fix pass for compose()
authored
102 }
103
8d14daa @tonycoz switch to using size_t and i_img_dim strictly
authored
104 mm_log((1, "after adjustments: (out(" i_DFp "), src(" i_DFp "),"
105 " mask(" i_DFp "), size(" i_DFp ")\n",
106 i_DFcp(out_left, out_top), i_DFcp(src_left, src_top),
107 i_DFcp(mask_left, mask_top), i_DFcp(width, height)));
9b1ec2b commit changes from draw branch
Tony Cook authored
108
109 i_get_combine(combine, &combinef_8, &combinef_double);
110
111 i_render_init(&r, out, width);
112 #code out->bits <= 8 && src->bits<= 8 && mask->bits <= 8
113 IM_COLOR *src_line = mymalloc(sizeof(IM_COLOR) * width);
114 IM_SAMPLE_T *mask_line = mymalloc(sizeof(IM_SAMPLE_T) * width);
115 int adapt_channels = out->channels;
116
117 if (adapt_channels == 1 || adapt_channels == 3)
118 ++adapt_channels;
119
120 for (dy = 0; dy < height; ++dy) {
121 IM_GLIN(src, src_left, src_left + width, src_top + dy, src_line);
122 IM_ADAPT_COLORS(adapt_channels, src->channels, src_line, width);
123 IM_GSAMP(mask, mask_left, mask_left + width, mask_top + dy,
124 mask_line, &channel_zero, 1);
125 if (opacity < 1.0) {
8d14daa @tonycoz switch to using size_t and i_img_dim strictly
authored
126 i_img_dim i;
9b1ec2b commit changes from draw branch
Tony Cook authored
127 IM_SAMPLE_T *maskp = mask_line;
128 for (i = 0; i < width; ++i) {
129 *maskp = IM_ROUND(*maskp * opacity);
130 ++maskp;
131 }
132 }
133 IM_RENDER_LINE(&r, out_left, out_top+dy, width, mask_line, src_line,
134 IM_SUFFIX(combinef));
135 }
136 myfree(src_line);
137 myfree(mask_line);
138
139 #/code
140 i_render_done(&r);
141
142 return 1;
143 }
144
145 int
146 i_compose(i_img *out, i_img *src,
8d14daa @tonycoz switch to using size_t and i_img_dim strictly
authored
147 i_img_dim out_left, i_img_dim out_top,
148 i_img_dim src_left, i_img_dim src_top,
149 i_img_dim width, i_img_dim height,
9b1ec2b commit changes from draw branch
Tony Cook authored
150 int combine,
151 double opacity) {
152 i_render r;
8d14daa @tonycoz switch to using size_t and i_img_dim strictly
authored
153 i_img_dim dy;
9b1ec2b commit changes from draw branch
Tony Cook authored
154 i_fill_combine_f combinef_8;
155 i_fill_combinef_f combinef_double;
156
8d14daa @tonycoz switch to using size_t and i_img_dim strictly
authored
157 mm_log((1, "i_compose(out %p, src %p, out(" i_DFp "), src(" i_DFp "), "
158 "size(" i_DFp "), combine %d opacity %f\n", out, src,
159 i_DFcp(out_left, out_top), i_DFcp(src_left, src_top),
160 i_DFcp(width, height), combine, opacity));
618a328 @tonycoz test coverage and fix pass for compose()
authored
161
9b1ec2b commit changes from draw branch
Tony Cook authored
162 i_clear_error();
163 if (out_left >= out->xsize
164 || out_top >= out->ysize
165 || src_left >= src->xsize
166 || src_top >= src->ysize
167 || width <= 0
168 || height <= 0
169 || out_left + width <= 0
170 || out_top + height <= 0
171 || src_left + width <= 0
172 || src_top + height <= 0)
173 return 0;
174
175 if (out_left < 0) {
176 width = out_left + width;
618a328 @tonycoz test coverage and fix pass for compose()
authored
177 src_left -= out_left;
9b1ec2b commit changes from draw branch
Tony Cook authored
178 out_left = 0;
179 }
180 if (out_left + width > out->xsize)
181 width = out->xsize - out_left;
182
183 if (out_top < 0) {
184 height = out_top + height;
618a328 @tonycoz test coverage and fix pass for compose()
authored
185 src_top -= out_top;
9b1ec2b commit changes from draw branch
Tony Cook authored
186 out_top = 0;
187 }
188 if (out_top + height > out->ysize)
189 height = out->ysize - out_top;
190
191 if (src_left < 0) {
192 width = src_left + width;
618a328 @tonycoz test coverage and fix pass for compose()
authored
193 out_left -= src_left;
9b1ec2b commit changes from draw branch
Tony Cook authored
194 src_left = 0;
195 }
196 if (src_left + width > src->xsize)
197 width = src->xsize - src_left;
198
199 if (src_top < 0) {
200 height = src_top + height;
618a328 @tonycoz test coverage and fix pass for compose()
authored
201 out_top -= src_top;
9b1ec2b commit changes from draw branch
Tony Cook authored
202 src_top = 0;
203 }
204 if (src_top + height > src->ysize)
618a328 @tonycoz test coverage and fix pass for compose()
authored
205 height = src->ysize - src_top;
9b1ec2b commit changes from draw branch
Tony Cook authored
206
207 if (opacity > 1.0)
208 opacity = 1.0;
618a328 @tonycoz test coverage and fix pass for compose()
authored
209 else if (opacity <= 0) {
210 i_push_error(0, "opacity must be positive");
9b1ec2b commit changes from draw branch
Tony Cook authored
211 return 0;
618a328 @tonycoz test coverage and fix pass for compose()
authored
212 }
9b1ec2b commit changes from draw branch
Tony Cook authored
213
214 i_get_combine(combine, &combinef_8, &combinef_double);
215
216 i_render_init(&r, out, width);
217 #code out->bits <= 8 && src->bits <= 8
218 IM_COLOR *src_line = mymalloc(sizeof(IM_COLOR) * width);
219 IM_SAMPLE_T *mask_line = NULL;
220 int adapt_channels = out->channels;
221
222 if (opacity != 1.0) {
8d14daa @tonycoz switch to using size_t and i_img_dim strictly
authored
223 i_img_dim i;
9b1ec2b commit changes from draw branch
Tony Cook authored
224 IM_SAMPLE_T mask_value = IM_ROUND(opacity * IM_SAMPLE_MAX);
225 mask_line = mymalloc(sizeof(IM_SAMPLE_T) * width);
226
227 for (i = 0; i < width; ++i)
228 mask_line[i] = mask_value;
229 }
230
231 if (adapt_channels == 1 || adapt_channels == 3)
232 ++adapt_channels;
233
234 for (dy = 0; dy < height; ++dy) {
235 IM_GLIN(src, src_left, src_left + width, src_top + dy, src_line);
236 IM_ADAPT_COLORS(adapt_channels, src->channels, src_line, width);
237 IM_RENDER_LINE(&r, out_left, out_top+dy, width, mask_line, src_line,
238 IM_SUFFIX(combinef));
239 }
240 myfree(src_line);
241 if (mask_line)
242 myfree(mask_line);
243
244 #/code
245 i_render_done(&r);
246
247 return 1;
248 }
Something went wrong with that request. Please try again.