/work/workdir/UnpackedTarball/cairo/src/cairo-mesh-pattern-rasterizer.c
Line | Count | Source (jump to first uncovered line) |
1 | | /* -*- Mode: c; tab-width: 8; c-basic-offset: 4; indent-tabs-mode: t; -*- */ |
2 | | /* cairo - a vector graphics library with display and print output |
3 | | * |
4 | | * Copyright 2009 Andrea Canciani |
5 | | * |
6 | | * This library is free software; you can redistribute it and/or |
7 | | * modify it either under the terms of the GNU Lesser General Public |
8 | | * License version 2.1 as published by the Free Software Foundation |
9 | | * (the "LGPL") or, at your option, under the terms of the Mozilla |
10 | | * Public License Version 1.1 (the "MPL"). If you do not alter this |
11 | | * notice, a recipient may use your version of this file under either |
12 | | * the MPL or the LGPL. |
13 | | * |
14 | | * You should have received a copy of the LGPL along with this library |
15 | | * in the file COPYING-LGPL-2.1; if not, write to the Free Software |
16 | | * Foundation, Inc., 51 Franklin Street, Suite 500, Boston, MA 02110-1335, USA |
17 | | * You should have received a copy of the MPL along with this library |
18 | | * in the file COPYING-MPL-1.1 |
19 | | * |
20 | | * The contents of this file are subject to the Mozilla Public License |
21 | | * Version 1.1 (the "License"); you may not use this file except in |
22 | | * compliance with the License. You may obtain a copy of the License at |
23 | | * http://www.mozilla.org/MPL/ |
24 | | * |
25 | | * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY |
26 | | * OF ANY KIND, either express or implied. See the LGPL or the MPL for |
27 | | * the specific language governing rights and limitations. |
28 | | * |
29 | | * The Original Code is the cairo graphics library. |
30 | | * |
31 | | * The Initial Developer of the Original Code is Andrea Canciani. |
32 | | * |
33 | | * Contributor(s): |
34 | | * Andrea Canciani <ranma42@gmail.com> |
35 | | */ |
36 | | |
37 | | #include "cairoint.h" |
38 | | |
39 | | #include "cairo-array-private.h" |
40 | | #include "cairo-pattern-private.h" |
41 | | |
42 | | /* |
43 | | * Rasterizer for mesh patterns. |
44 | | * |
45 | | * This implementation is based on techniques derived from several |
46 | | * papers (available from ACM): |
47 | | * |
48 | | * - Lien, Shantz and Pratt "Adaptive Forward Differencing for |
49 | | * Rendering Curves and Surfaces" (discussion of the AFD technique, |
50 | | * bound of 1/sqrt(2) on step length without proof) |
51 | | * |
52 | | * - Popescu and Rosen, "Forward rasterization" (description of |
53 | | * forward rasterization, proof of the previous bound) |
54 | | * |
55 | | * - Klassen, "Integer Forward Differencing of Cubic Polynomials: |
56 | | * Analysis and Algorithms" |
57 | | * |
58 | | * - Klassen, "Exact Integer Hybrid Subdivision and Forward |
59 | | * Differencing of Cubics" (improving the bound on the minimum |
60 | | * number of steps) |
61 | | * |
62 | | * - Chang, Shantz and Rocchetti, "Rendering Cubic Curves and Surfaces |
63 | | * with Integer Adaptive Forward Differencing" (analysis of forward |
64 | | * differencing applied to Bezier patches) |
65 | | * |
66 | | * Notes: |
67 | | * - Poor performance expected in degenerate cases |
68 | | * |
69 | | * - Patches mostly outside the drawing area are drawn completely (and |
70 | | * clipped), wasting time |
71 | | * |
72 | | * - Both previous problems are greatly reduced by splitting until a |
73 | | * reasonably small size and clipping the new tiles: execution time |
74 | | * is quadratic in the convex-hull diameter instead than linear to |
75 | | * the painted area. Splitting the tiles doesn't change the painted |
76 | | * area but (usually) reduces the bounding box area (bbox area can |
77 | | * remain the same after splitting, but cannot grow) |
78 | | * |
79 | | * - The initial implementation used adaptive forward differencing, |
80 | | * but simple forward differencing scored better in benchmarks |
81 | | * |
82 | | * Idea: |
83 | | * |
84 | | * We do a sampling over the cubic patch with step du and dv (in the |
85 | | * two parameters) that guarantees that any point of our sampling will |
86 | | * be at most at 1/sqrt(2) from its adjacent points. In formulae |
87 | | * (assuming B is the patch): |
88 | | * |
89 | | * |B(u,v) - B(u+du,v)| < 1/sqrt(2) |
90 | | * |B(u,v) - B(u,v+dv)| < 1/sqrt(2) |
91 | | * |
92 | | * This means that every pixel covered by the patch will contain at |
93 | | * least one of the samples, thus forward rasterization can be |
94 | | * performed. Sketch of proof (from Popescu and Rosen): |
95 | | * |
96 | | * Let's take the P pixel we're interested into. If we assume it to be |
97 | | * square, its boundaries define 9 regions on the plane: |
98 | | * |
99 | | * 1|2|3 |
100 | | * -+-+- |
101 | | * 8|P|4 |
102 | | * -+-+- |
103 | | * 7|6|5 |
104 | | * |
105 | | * Let's check that the pixel P will contain at least one point |
106 | | * assuming that it is covered by the patch. |
107 | | * |
108 | | * Since the pixel is covered by the patch, its center will belong to |
109 | | * (at least) one of the quads: |
110 | | * |
111 | | * {(B(u,v), B(u+du,v), B(u,v+dv), B(u+du,v+dv)) for u,v in [0,1]} |
112 | | * |
113 | | * If P doesn't contain any of the corners of the quad: |
114 | | * |
115 | | * - if one of the corners is in 1,3,5 or 7, other two of them have to |
116 | | * be in 2,4,6 or 8, thus if the last corner is not in P, the length |
117 | | * of one of the edges will be > 1/sqrt(2) |
118 | | * |
119 | | * - if none of the corners is in 1,3,5 or 7, all of them are in 2,4,6 |
120 | | * and/or 8. If they are all in different regions, they can't |
121 | | * satisfy the distance constraint. If two of them are in the same |
122 | | * region (let's say 2), no point is in 6 and again it is impossible |
123 | | * to have the center of P in the quad respecting the distance |
124 | | * constraint (both these assertions can be checked by continuity |
125 | | * considering the length of the edges of a quad with the vertices |
126 | | * on the edges of P) |
127 | | * |
128 | | * Each of the cases led to a contradiction, so P contains at least |
129 | | * one of the corners of the quad. |
130 | | */ |
131 | | |
132 | | /* |
133 | | * Make sure that errors are less than 1 in fixed point math if you |
134 | | * change these values. |
135 | | * |
136 | | * The error is amplified by about steps^3/4 times. |
137 | | * The rasterizer always uses a number of steps that is a power of 2. |
138 | | * |
139 | | * 256 is the maximum allowed number of steps (to have error < 1) |
140 | | * using 8.24 for the differences. |
141 | | */ |
142 | 0 | #define STEPS_MAX_V 256.0 |
143 | 0 | #define STEPS_MAX_U 256.0 |
144 | | |
145 | | /* |
146 | | * If the patch/curve is only partially visible, split it to a finer |
147 | | * resolution to get higher chances to clip (part of) it. |
148 | | * |
149 | | * These values have not been computed, but simply obtained |
150 | | * empirically (by benchmarking some patches). They should never be |
151 | | * greater than STEPS_MAX_V (or STEPS_MAX_U), but they can be as small |
152 | | * as 1 (depending on how much you want to spend time in splitting the |
153 | | * patch/curve when trying to save some rasterization time). |
154 | | */ |
155 | 0 | #define STEPS_CLIP_V 64.0 |
156 | 0 | #define STEPS_CLIP_U 64.0 |
157 | | |
158 | | |
159 | | /* Utils */ |
160 | | static inline double |
161 | | sqlen (cairo_point_double_t p0, cairo_point_double_t p1) |
162 | 0 | { |
163 | 0 | cairo_point_double_t delta; |
164 | |
|
165 | 0 | delta.x = p0.x - p1.x; |
166 | 0 | delta.y = p0.y - p1.y; |
167 | |
|
168 | 0 | return delta.x * delta.x + delta.y * delta.y; |
169 | 0 | } |
170 | | |
171 | | static inline int16_t |
172 | | _color_delta_to_shifted_short (int32_t from, int32_t to, int shift) |
173 | 0 | { |
174 | 0 | int32_t delta = to - from; |
175 | | |
176 | | /* We need to round toward zero, because otherwise adding the |
177 | | * delta 2^shift times can overflow */ |
178 | 0 | if (delta >= 0) |
179 | 0 | return delta >> shift; |
180 | 0 | else |
181 | 0 | return -((-delta) >> shift); |
182 | 0 | } |
183 | | |
184 | | /* |
185 | | * Convert a number of steps to the equivalent shift. |
186 | | * |
187 | | * Input: the square of the minimum number of steps |
188 | | * |
189 | | * Output: the smallest integer x such that 2^x > steps |
190 | | */ |
191 | | static inline int |
192 | | sqsteps2shift (double steps_sq) |
193 | 0 | { |
194 | 0 | int r; |
195 | 0 | frexp (MAX (1.0, steps_sq), &r); |
196 | 0 | return (r + 1) >> 1; |
197 | 0 | } |
198 | | |
199 | | /* |
200 | | * FD functions |
201 | | * |
202 | | * A Bezier curve is defined (with respect to a parameter t in |
203 | | * [0,1]) from its nodes (x,y,z,w) like this: |
204 | | * |
205 | | * B(t) = x(1-t)^3 + 3yt(1-t)^2 + 3zt^2(1-t) + wt^3 |
206 | | * |
207 | | * To efficiently evaluate a Bezier curve, the rasterizer uses forward |
208 | | * differences. Given x, y, z, w (the 4 nodes of the Bezier curve), it |
209 | | * is possible to convert them to forward differences form and walk |
210 | | * over the curve using fd_init (), fd_down () and fd_fwd (). |
211 | | * |
212 | | * f[0] is always the value of the Bezier curve for "current" t. |
213 | | */ |
214 | | |
215 | | /* |
216 | | * Initialize the coefficient for forward differences. |
217 | | * |
218 | | * Input: x,y,z,w are the 4 nodes of the Bezier curve |
219 | | * |
220 | | * Output: f[i] is the i-th difference of the curve |
221 | | * |
222 | | * f[0] is the value of the curve for t==0, i.e. f[0]==x. |
223 | | * |
224 | | * The initial step is 1; this means that each step increases t by 1 |
225 | | * (so fd_init () immediately followed by fd_fwd (f) n times makes |
226 | | * f[0] be the value of the curve for t==n). |
227 | | */ |
228 | | static inline void |
229 | | fd_init (double x, double y, double z, double w, double f[4]) |
230 | 0 | { |
231 | 0 | f[0] = x; |
232 | 0 | f[1] = w - x; |
233 | 0 | f[2] = 6. * (w - 2. * z + y); |
234 | 0 | f[3] = 6. * (w - 3. * z + 3. * y - x); |
235 | 0 | } |
236 | | |
237 | | /* |
238 | | * Halve the step of the coefficients for forward differences. |
239 | | * |
240 | | * Input: f[i] is the i-th difference of the curve |
241 | | * |
242 | | * Output: f[i] is the i-th difference of the curve with half the |
243 | | * original step |
244 | | * |
245 | | * f[0] is not affected, so the current t is not changed. |
246 | | * |
247 | | * The other coefficients are changed so that the step is half the |
248 | | * original step. This means that doing fd_fwd (f) n times with the |
249 | | * input f results in the same f[0] as doing fd_fwd (f) 2n times with |
250 | | * the output f. |
251 | | */ |
252 | | static inline void |
253 | | fd_down (double f[4]) |
254 | 0 | { |
255 | 0 | f[3] *= 0.125; |
256 | 0 | f[2] = f[2] * 0.25 - f[3]; |
257 | 0 | f[1] = (f[1] - f[2]) * 0.5; |
258 | 0 | } |
259 | | |
260 | | /* |
261 | | * Perform one step of forward differences along the curve. |
262 | | * |
263 | | * Input: f[i] is the i-th difference of the curve |
264 | | * |
265 | | * Output: f[i] is the i-th difference of the curve after one step |
266 | | */ |
267 | | static inline void |
268 | | fd_fwd (double f[4]) |
269 | 0 | { |
270 | 0 | f[0] += f[1]; |
271 | 0 | f[1] += f[2]; |
272 | 0 | f[2] += f[3]; |
273 | 0 | } |
274 | | |
275 | | /* |
276 | | * Transform to integer forward differences. |
277 | | * |
278 | | * Input: d[n] is the n-th difference (in double precision) |
279 | | * |
280 | | * Output: i[n] is the n-th difference (in fixed point precision) |
281 | | * |
282 | | * i[0] is 9.23 fixed point, other differences are 4.28 fixed point. |
283 | | */ |
284 | | static inline void |
285 | | fd_fixed (double d[4], int32_t i[4]) |
286 | 0 | { |
287 | 0 | i[0] = _cairo_fixed_16_16_from_double (256 * 2 * d[0]); |
288 | 0 | i[1] = _cairo_fixed_16_16_from_double (256 * 16 * d[1]); |
289 | 0 | i[2] = _cairo_fixed_16_16_from_double (256 * 16 * d[2]); |
290 | 0 | i[3] = _cairo_fixed_16_16_from_double (256 * 16 * d[3]); |
291 | 0 | } |
292 | | |
293 | | /* |
294 | | * Perform one step of integer forward differences along the curve. |
295 | | * |
296 | | * Input: f[n] is the n-th difference |
297 | | * |
298 | | * Output: f[n] is the n-th difference |
299 | | * |
300 | | * f[0] is 9.23 fixed point, other differences are 4.28 fixed point. |
301 | | */ |
302 | | static inline void |
303 | | fd_fixed_fwd (int32_t f[4]) |
304 | 0 | { |
305 | 0 | f[0] += (f[1] >> 5) + ((f[1] >> 4) & 1); |
306 | 0 | f[1] += f[2]; |
307 | 0 | f[2] += f[3]; |
308 | 0 | } |
309 | | |
310 | | /* |
311 | | * Compute the minimum number of steps that guarantee that walking |
312 | | * over a curve will leave no holes. |
313 | | * |
314 | | * Input: p[0..3] the nodes of the Bezier curve |
315 | | * |
316 | | * Returns: the square of the number of steps |
317 | | * |
318 | | * Idea: |
319 | | * |
320 | | * We want to make sure that at every step we move by less than |
321 | | * 1/sqrt(2). |
322 | | * |
323 | | * The derivative of the cubic Bezier with nodes (p0, p1, p2, p3) is |
324 | | * the quadratic Bezier with nodes (p1-p0, p2-p1, p3-p2) scaled by 3, |
325 | | * so (since a Bezier curve is always bounded by its convex hull), we |
326 | | * can say that: |
327 | | * |
328 | | * max(|B'(t)|) <= 3 max (|p1-p0|, |p2-p1|, |p3-p2|) |
329 | | * |
330 | | * We can improve this by noticing that a quadratic Bezier (a,b,c) is |
331 | | * bounded by the quad (a,lerp(a,b,t),lerp(b,c,t),c) for any t, so |
332 | | * (substituting the previous values, using t=0.5 and simplifying): |
333 | | * |
334 | | * max(|B'(t)|) <= 3 max (|p1-p0|, |p2-p0|/2, |p3-p1|/2, |p3-p2|) |
335 | | * |
336 | | * So, to guarantee a maximum step length of 1/sqrt(2) we must do: |
337 | | * |
338 | | * 3 max (|p1-p0|, |p2-p0|/2, |p3-p1|/2, |p3-p2|) sqrt(2) steps |
339 | | */ |
340 | | static inline double |
341 | | bezier_steps_sq (cairo_point_double_t p[4]) |
342 | 0 | { |
343 | 0 | double tmp = sqlen (p[0], p[1]); |
344 | 0 | tmp = MAX (tmp, sqlen (p[2], p[3])); |
345 | 0 | tmp = MAX (tmp, sqlen (p[0], p[2]) * .25); |
346 | 0 | tmp = MAX (tmp, sqlen (p[1], p[3]) * .25); |
347 | 0 | return 18.0 * tmp; |
348 | 0 | } |
349 | | |
350 | | /* |
351 | | * Split a 1D Bezier cubic using de Casteljau's algorithm. |
352 | | * |
353 | | * Input: x,y,z,w the nodes of the Bezier curve |
354 | | * |
355 | | * Output: x0,y0,z0,w0 and x1,y1,z1,w1 are respectively the nodes of |
356 | | * the first half and of the second half of the curve |
357 | | * |
358 | | * The output control nodes have to be distinct. |
359 | | */ |
360 | | static inline void |
361 | | split_bezier_1D (double x, double y, double z, double w, |
362 | | double *x0, double *y0, double *z0, double *w0, |
363 | | double *x1, double *y1, double *z1, double *w1) |
364 | 0 | { |
365 | 0 | double tmp; |
366 | |
|
367 | 0 | *x0 = x; |
368 | 0 | *w1 = w; |
369 | |
|
370 | 0 | tmp = 0.5 * (y + z); |
371 | 0 | *y0 = 0.5 * (x + y); |
372 | 0 | *z1 = 0.5 * (z + w); |
373 | |
|
374 | 0 | *z0 = 0.5 * (*y0 + tmp); |
375 | 0 | *y1 = 0.5 * (tmp + *z1); |
376 | |
|
377 | 0 | *w0 = *x1 = 0.5 * (*z0 + *y1); |
378 | 0 | } |
379 | | |
380 | | /* |
381 | | * Split a Bezier curve using de Casteljau's algorithm. |
382 | | * |
383 | | * Input: p[0..3] the nodes of the Bezier curve |
384 | | * |
385 | | * Output: fst_half[0..3] and snd_half[0..3] are respectively the |
386 | | * nodes of the first and of the second half of the curve |
387 | | * |
388 | | * fst_half and snd_half must be different, but they can be the same as |
389 | | * nodes. |
390 | | */ |
391 | | static void |
392 | | split_bezier (cairo_point_double_t p[4], |
393 | | cairo_point_double_t fst_half[4], |
394 | | cairo_point_double_t snd_half[4]) |
395 | 0 | { |
396 | 0 | split_bezier_1D (p[0].x, p[1].x, p[2].x, p[3].x, |
397 | 0 | &fst_half[0].x, &fst_half[1].x, &fst_half[2].x, &fst_half[3].x, |
398 | 0 | &snd_half[0].x, &snd_half[1].x, &snd_half[2].x, &snd_half[3].x); |
399 | |
|
400 | 0 | split_bezier_1D (p[0].y, p[1].y, p[2].y, p[3].y, |
401 | 0 | &fst_half[0].y, &fst_half[1].y, &fst_half[2].y, &fst_half[3].y, |
402 | 0 | &snd_half[0].y, &snd_half[1].y, &snd_half[2].y, &snd_half[3].y); |
403 | 0 | } |
404 | | |
405 | | |
406 | | typedef enum _intersection { |
407 | | INSIDE = -1, /* the interval is entirely contained in the reference interval */ |
408 | | OUTSIDE = 0, /* the interval has no intersection with the reference interval */ |
409 | | PARTIAL = 1 /* the interval intersects the reference interval (but is not fully inside it) */ |
410 | | } intersection_t; |
411 | | |
412 | | /* |
413 | | * Check if an interval if inside another. |
414 | | * |
415 | | * Input: a,b are the extrema of the first interval |
416 | | * c,d are the extrema of the second interval |
417 | | * |
418 | | * Returns: INSIDE iff [a,b) intersection [c,d) = [a,b) |
419 | | * OUTSIDE iff [a,b) intersection [c,d) = {} |
420 | | * PARTIAL otherwise |
421 | | * |
422 | | * The function assumes a < b and c < d |
423 | | * |
424 | | * Note: Bitwise-anding the results along each component gives the |
425 | | * expected result for [a,b) x [A,B) intersection [c,d) x [C,D). |
426 | | */ |
427 | | static inline int |
428 | | intersect_interval (double a, double b, double c, double d) |
429 | 0 | { |
430 | 0 | if (c <= a && b <= d) |
431 | 0 | return INSIDE; |
432 | 0 | else if (a >= d || b <= c) |
433 | 0 | return OUTSIDE; |
434 | 0 | else |
435 | 0 | return PARTIAL; |
436 | 0 | } |
437 | | |
438 | | /* |
439 | | * Set the color of a pixel. |
440 | | * |
441 | | * Input: data is the base pointer of the image |
442 | | * width, height are the dimensions of the image |
443 | | * stride is the stride in bytes between adjacent rows |
444 | | * x, y are the coordinates of the pixel to be colored |
445 | | * r,g,b,a are the color components of the color to be set |
446 | | * |
447 | | * Output: the (x,y) pixel in data has the (r,g,b,a) color |
448 | | * |
449 | | * The input color components are not premultiplied, but the data |
450 | | * stored in the image is assumed to be in CAIRO_FORMAT_ARGB32 (8 bpc, |
451 | | * premultiplied). |
452 | | * |
453 | | * If the pixel to be set is outside the image, this function does |
454 | | * nothing. |
455 | | */ |
456 | | static inline void |
457 | | draw_pixel (unsigned char *data, int width, int height, int stride, |
458 | | int x, int y, uint16_t r, uint16_t g, uint16_t b, uint16_t a) |
459 | 0 | { |
460 | 0 | if (likely (0 <= x && 0 <= y && x < width && y < height)) { |
461 | 0 | uint32_t tr, tg, tb, ta; |
462 | | |
463 | | /* Premultiply and round */ |
464 | 0 | ta = a; |
465 | 0 | tr = r * ta + 0x8000; |
466 | 0 | tg = g * ta + 0x8000; |
467 | 0 | tb = b * ta + 0x8000; |
468 | |
|
469 | 0 | tr += tr >> 16; |
470 | 0 | tg += tg >> 16; |
471 | 0 | tb += tb >> 16; |
472 | |
|
473 | 0 | *((uint32_t*) (data + y*(ptrdiff_t)stride + 4*x)) = ((ta << 16) & 0xff000000) | |
474 | 0 | ((tr >> 8) & 0xff0000) | ((tg >> 16) & 0xff00) | (tb >> 24); |
475 | 0 | } |
476 | 0 | } |
477 | | |
478 | | /* |
479 | | * Forward-rasterize a cubic curve using forward differences. |
480 | | * |
481 | | * Input: data is the base pointer of the image |
482 | | * width, height are the dimensions of the image |
483 | | * stride is the stride in bytes between adjacent rows |
484 | | * ushift is log2(n) if n is the number of desired steps |
485 | | * dxu[i], dyu[i] are the x,y forward differences of the curve |
486 | | * r0,g0,b0,a0 are the color components of the start point |
487 | | * r3,g3,b3,a3 are the color components of the end point |
488 | | * |
489 | | * Output: data will be changed to have the requested curve drawn in |
490 | | * the specified colors |
491 | | * |
492 | | * The input color components are not premultiplied, but the data |
493 | | * stored in the image is assumed to be in CAIRO_FORMAT_ARGB32 (8 bpc, |
494 | | * premultiplied). |
495 | | * |
496 | | * The function draws n+1 pixels, that is from the point at step 0 to |
497 | | * the point at step n, both included. This is the discrete equivalent |
498 | | * to drawing the curve for values of the interpolation parameter in |
499 | | * [0,1] (including both extremes). |
500 | | */ |
501 | | static inline void |
502 | | rasterize_bezier_curve (unsigned char *data, int width, int height, int stride, |
503 | | int ushift, double dxu[4], double dyu[4], |
504 | | uint16_t r0, uint16_t g0, uint16_t b0, uint16_t a0, |
505 | | uint16_t r3, uint16_t g3, uint16_t b3, uint16_t a3) |
506 | 0 | { |
507 | 0 | int32_t xu[4], yu[4]; |
508 | 0 | int x0, y0, u, usteps = 1 << ushift; |
509 | |
|
510 | 0 | uint16_t r = r0, g = g0, b = b0, a = a0; |
511 | 0 | int16_t dr = _color_delta_to_shifted_short (r0, r3, ushift); |
512 | 0 | int16_t dg = _color_delta_to_shifted_short (g0, g3, ushift); |
513 | 0 | int16_t db = _color_delta_to_shifted_short (b0, b3, ushift); |
514 | 0 | int16_t da = _color_delta_to_shifted_short (a0, a3, ushift); |
515 | |
|
516 | 0 | fd_fixed (dxu, xu); |
517 | 0 | fd_fixed (dyu, yu); |
518 | | |
519 | | /* |
520 | | * Use (dxu[0],dyu[0]) as origin for the forward differences. |
521 | | * |
522 | | * This makes it possible to handle much larger coordinates (the |
523 | | * ones that can be represented as cairo_fixed_t) |
524 | | */ |
525 | 0 | x0 = _cairo_fixed_from_double (dxu[0]); |
526 | 0 | y0 = _cairo_fixed_from_double (dyu[0]); |
527 | 0 | xu[0] = 0; |
528 | 0 | yu[0] = 0; |
529 | |
|
530 | 0 | for (u = 0; u <= usteps; ++u) { |
531 | | /* |
532 | | * This rasterizer assumes that pixels are integer aligned |
533 | | * squares, so a generic (x,y) point belongs to the pixel with |
534 | | * top-left coordinates (floor(x), floor(y)) |
535 | | */ |
536 | |
|
537 | 0 | int x = _cairo_fixed_integer_floor (x0 + (xu[0] >> 15) + ((xu[0] >> 14) & 1)); |
538 | 0 | int y = _cairo_fixed_integer_floor (y0 + (yu[0] >> 15) + ((yu[0] >> 14) & 1)); |
539 | |
|
540 | 0 | draw_pixel (data, width, height, stride, x, y, r, g, b, a); |
541 | |
|
542 | 0 | fd_fixed_fwd (xu); |
543 | 0 | fd_fixed_fwd (yu); |
544 | 0 | r += dr; |
545 | 0 | g += dg; |
546 | 0 | b += db; |
547 | 0 | a += da; |
548 | 0 | } |
549 | 0 | } |
550 | | |
551 | | /* |
552 | | * Clip, split and rasterize a Bezier curve. |
553 | | * |
554 | | * Input: data is the base pointer of the image |
555 | | * width, height are the dimensions of the image |
556 | | * stride is the stride in bytes between adjacent rows |
557 | | * p[i] is the i-th node of the Bezier curve |
558 | | * c0[i] is the i-th color component at the start point |
559 | | * c3[i] is the i-th color component at the end point |
560 | | * |
561 | | * Output: data will be changed to have the requested curve drawn in |
562 | | * the specified colors |
563 | | * |
564 | | * The input color components are not premultiplied, but the data |
565 | | * stored in the image is assumed to be in CAIRO_FORMAT_ARGB32 (8 bpc, |
566 | | * premultiplied). |
567 | | * |
568 | | * The color components are red, green, blue and alpha, in this order. |
569 | | * |
570 | | * The function guarantees that it will draw the curve with a step |
571 | | * small enough to never have a distance above 1/sqrt(2) between two |
572 | | * consecutive points (which is needed to ensure that no hole can |
573 | | * appear when using this function to rasterize a patch). |
574 | | */ |
575 | | static void |
576 | | draw_bezier_curve (unsigned char *data, int width, int height, int stride, |
577 | | cairo_point_double_t p[4], double c0[4], double c3[4]) |
578 | 0 | { |
579 | 0 | double top, bottom, left, right, steps_sq; |
580 | 0 | int i, v; |
581 | |
|
582 | 0 | top = bottom = p[0].y; |
583 | 0 | for (i = 1; i < 4; ++i) { |
584 | 0 | top = MIN (top, p[i].y); |
585 | 0 | bottom = MAX (bottom, p[i].y); |
586 | 0 | } |
587 | | |
588 | | /* Check visibility */ |
589 | 0 | v = intersect_interval (top, bottom, 0, height); |
590 | 0 | if (v == OUTSIDE) |
591 | 0 | return; |
592 | | |
593 | 0 | left = right = p[0].x; |
594 | 0 | for (i = 1; i < 4; ++i) { |
595 | 0 | left = MIN (left, p[i].x); |
596 | 0 | right = MAX (right, p[i].x); |
597 | 0 | } |
598 | |
|
599 | 0 | v &= intersect_interval (left, right, 0, width); |
600 | 0 | if (v == OUTSIDE) |
601 | 0 | return; |
602 | | |
603 | 0 | steps_sq = bezier_steps_sq (p); |
604 | 0 | if (steps_sq >= (v == INSIDE ? STEPS_MAX_U * STEPS_MAX_U : STEPS_CLIP_U * STEPS_CLIP_U)) { |
605 | | /* |
606 | | * The number of steps is greater than the threshold. This |
607 | | * means that either the error would become too big if we |
608 | | * directly rasterized it or that we can probably save some |
609 | | * time by splitting the curve and clipping part of it |
610 | | */ |
611 | 0 | cairo_point_double_t first[4], second[4]; |
612 | 0 | double midc[4]; |
613 | 0 | split_bezier (p, first, second); |
614 | 0 | midc[0] = (c0[0] + c3[0]) * 0.5; |
615 | 0 | midc[1] = (c0[1] + c3[1]) * 0.5; |
616 | 0 | midc[2] = (c0[2] + c3[2]) * 0.5; |
617 | 0 | midc[3] = (c0[3] + c3[3]) * 0.5; |
618 | 0 | draw_bezier_curve (data, width, height, stride, first, c0, midc); |
619 | 0 | draw_bezier_curve (data, width, height, stride, second, midc, c3); |
620 | 0 | } else { |
621 | 0 | double xu[4], yu[4]; |
622 | 0 | int ushift = sqsteps2shift (steps_sq), k; |
623 | |
|
624 | 0 | fd_init (p[0].x, p[1].x, p[2].x, p[3].x, xu); |
625 | 0 | fd_init (p[0].y, p[1].y, p[2].y, p[3].y, yu); |
626 | |
|
627 | 0 | for (k = 0; k < ushift; ++k) { |
628 | 0 | fd_down (xu); |
629 | 0 | fd_down (yu); |
630 | 0 | } |
631 | |
|
632 | 0 | rasterize_bezier_curve (data, width, height, stride, ushift, |
633 | 0 | xu, yu, |
634 | 0 | _cairo_color_double_to_short (c0[0]), |
635 | 0 | _cairo_color_double_to_short (c0[1]), |
636 | 0 | _cairo_color_double_to_short (c0[2]), |
637 | 0 | _cairo_color_double_to_short (c0[3]), |
638 | 0 | _cairo_color_double_to_short (c3[0]), |
639 | 0 | _cairo_color_double_to_short (c3[1]), |
640 | 0 | _cairo_color_double_to_short (c3[2]), |
641 | 0 | _cairo_color_double_to_short (c3[3])); |
642 | | |
643 | | /* Draw the end point, to make sure that we didn't leave it |
644 | | * out because of rounding */ |
645 | 0 | draw_pixel (data, width, height, stride, |
646 | 0 | _cairo_fixed_integer_floor (_cairo_fixed_from_double (p[3].x)), |
647 | 0 | _cairo_fixed_integer_floor (_cairo_fixed_from_double (p[3].y)), |
648 | 0 | _cairo_color_double_to_short (c3[0]), |
649 | 0 | _cairo_color_double_to_short (c3[1]), |
650 | 0 | _cairo_color_double_to_short (c3[2]), |
651 | 0 | _cairo_color_double_to_short (c3[3])); |
652 | 0 | } |
653 | 0 | } |
654 | | |
655 | | /* |
656 | | * Forward-rasterize a cubic Bezier patch using forward differences. |
657 | | * |
658 | | * Input: data is the base pointer of the image |
659 | | * width, height are the dimensions of the image |
660 | | * stride is the stride in bytes between adjacent rows |
661 | | * vshift is log2(n) if n is the number of desired steps |
662 | | * p[i][j], p[i][j] are the the nodes of the Bezier patch |
663 | | * col[i][j] is the j-th color component of the i-th corner |
664 | | * |
665 | | * Output: data will be changed to have the requested patch drawn in |
666 | | * the specified colors |
667 | | * |
668 | | * The nodes of the patch are as follows: |
669 | | * |
670 | | * u\v 0 - > 1 |
671 | | * 0 p00 p01 p02 p03 |
672 | | * | p10 p11 p12 p13 |
673 | | * v p20 p21 p22 p23 |
674 | | * 1 p30 p31 p32 p33 |
675 | | * |
676 | | * i.e. u varies along the first component (rows), v varies along the |
677 | | * second one (columns). |
678 | | * |
679 | | * The color components are red, green, blue and alpha, in this order. |
680 | | * c[0..3] are the colors in p00, p30, p03, p33 respectively |
681 | | * |
682 | | * The input color components are not premultiplied, but the data |
683 | | * stored in the image is assumed to be in CAIRO_FORMAT_ARGB32 (8 bpc, |
684 | | * premultiplied). |
685 | | * |
686 | | * If the patch folds over itself, the part with the highest v |
687 | | * parameter is considered above. If both have the same v, the one |
688 | | * with the highest u parameter is above. |
689 | | * |
690 | | * The function draws n+1 curves, that is from the curve at step 0 to |
691 | | * the curve at step n, both included. This is the discrete equivalent |
692 | | * to drawing the patch for values of the interpolation parameter in |
693 | | * [0,1] (including both extremes). |
694 | | */ |
695 | | static inline void |
696 | | rasterize_bezier_patch (unsigned char *data, int width, int height, int stride, int vshift, |
697 | | cairo_point_double_t p[4][4], double col[4][4]) |
698 | 0 | { |
699 | 0 | double pv[4][2][4], cstart[4], cend[4], dcstart[4], dcend[4]; |
700 | 0 | int v, i, k; |
701 | |
|
702 | 0 | v = 1 << vshift; |
703 | | |
704 | | /* |
705 | | * pv[i][0] is the function (represented using forward |
706 | | * differences) mapping v to the x coordinate of the i-th node of |
707 | | * the Bezier curve with parameter u. |
708 | | * (Likewise p[i][0] gives the y coordinate). |
709 | | * |
710 | | * This means that (pv[0][0][0],pv[0][1][0]), |
711 | | * (pv[1][0][0],pv[1][1][0]), (pv[2][0][0],pv[2][1][0]) and |
712 | | * (pv[3][0][0],pv[3][1][0]) are the nodes of the Bezier curve for |
713 | | * the "current" v value (see the FD comments for more details). |
714 | | */ |
715 | 0 | for (i = 0; i < 4; ++i) { |
716 | 0 | fd_init (p[i][0].x, p[i][1].x, p[i][2].x, p[i][3].x, pv[i][0]); |
717 | 0 | fd_init (p[i][0].y, p[i][1].y, p[i][2].y, p[i][3].y, pv[i][1]); |
718 | 0 | for (k = 0; k < vshift; ++k) { |
719 | 0 | fd_down (pv[i][0]); |
720 | 0 | fd_down (pv[i][1]); |
721 | 0 | } |
722 | 0 | } |
723 | |
|
724 | 0 | for (i = 0; i < 4; ++i) { |
725 | 0 | cstart[i] = col[0][i]; |
726 | 0 | cend[i] = col[1][i]; |
727 | 0 | dcstart[i] = (col[2][i] - col[0][i]) / v; |
728 | 0 | dcend[i] = (col[3][i] - col[1][i]) / v; |
729 | 0 | } |
730 | |
|
731 | 0 | v++; |
732 | 0 | while (v--) { |
733 | 0 | cairo_point_double_t nodes[4]; |
734 | 0 | for (i = 0; i < 4; ++i) { |
735 | 0 | nodes[i].x = pv[i][0][0]; |
736 | 0 | nodes[i].y = pv[i][1][0]; |
737 | 0 | } |
738 | |
|
739 | 0 | draw_bezier_curve (data, width, height, stride, nodes, cstart, cend); |
740 | |
|
741 | 0 | for (i = 0; i < 4; ++i) { |
742 | 0 | fd_fwd (pv[i][0]); |
743 | 0 | fd_fwd (pv[i][1]); |
744 | 0 | cstart[i] += dcstart[i]; |
745 | 0 | cend[i] += dcend[i]; |
746 | 0 | } |
747 | 0 | } |
748 | 0 | } |
749 | | |
750 | | /* |
751 | | * Clip, split and rasterize a Bezier cubic patch. |
752 | | * |
753 | | * Input: data is the base pointer of the image |
754 | | * width, height are the dimensions of the image |
755 | | * stride is the stride in bytes between adjacent rows |
756 | | * p[i][j], p[i][j] are the nodes of the patch |
757 | | * col[i][j] is the j-th color component of the i-th corner |
758 | | * |
759 | | * Output: data will be changed to have the requested patch drawn in |
760 | | * the specified colors |
761 | | * |
762 | | * The nodes of the patch are as follows: |
763 | | * |
764 | | * u\v 0 - > 1 |
765 | | * 0 p00 p01 p02 p03 |
766 | | * | p10 p11 p12 p13 |
767 | | * v p20 p21 p22 p23 |
768 | | * 1 p30 p31 p32 p33 |
769 | | * |
770 | | * i.e. u varies along the first component (rows), v varies along the |
771 | | * second one (columns). |
772 | | * |
773 | | * The color components are red, green, blue and alpha, in this order. |
774 | | * c[0..3] are the colors in p00, p30, p03, p33 respectively |
775 | | * |
776 | | * The input color components are not premultiplied, but the data |
777 | | * stored in the image is assumed to be in CAIRO_FORMAT_ARGB32 (8 bpc, |
778 | | * premultiplied). |
779 | | * |
780 | | * If the patch folds over itself, the part with the highest v |
781 | | * parameter is considered above. If both have the same v, the one |
782 | | * with the highest u parameter is above. |
783 | | * |
784 | | * The function guarantees that it will draw the patch with a step |
785 | | * small enough to never have a distance above 1/sqrt(2) between two |
786 | | * adjacent points (which guarantees that no hole can appear). |
787 | | * |
788 | | * This function can be used to rasterize a tile of PDF type 7 |
789 | | * shadings (see http://www.adobe.com/devnet/pdf/pdf_reference.html). |
790 | | */ |
791 | | static void |
792 | | draw_bezier_patch (unsigned char *data, int width, int height, int stride, |
793 | | cairo_point_double_t p[4][4], double c[4][4]) |
794 | 0 | { |
795 | 0 | double top, bottom, left, right, steps_sq; |
796 | 0 | int i, j, v; |
797 | |
|
798 | 0 | top = bottom = p[0][0].y; |
799 | 0 | for (i = 0; i < 4; ++i) { |
800 | 0 | for (j= 0; j < 4; ++j) { |
801 | 0 | top = MIN (top, p[i][j].y); |
802 | 0 | bottom = MAX (bottom, p[i][j].y); |
803 | 0 | } |
804 | 0 | } |
805 | |
|
806 | 0 | v = intersect_interval (top, bottom, 0, height); |
807 | 0 | if (v == OUTSIDE) |
808 | 0 | return; |
809 | | |
810 | 0 | left = right = p[0][0].x; |
811 | 0 | for (i = 0; i < 4; ++i) { |
812 | 0 | for (j= 0; j < 4; ++j) { |
813 | 0 | left = MIN (left, p[i][j].x); |
814 | 0 | right = MAX (right, p[i][j].x); |
815 | 0 | } |
816 | 0 | } |
817 | |
|
818 | 0 | v &= intersect_interval (left, right, 0, width); |
819 | 0 | if (v == OUTSIDE) |
820 | 0 | return; |
821 | | |
822 | 0 | steps_sq = 0; |
823 | 0 | for (i = 0; i < 4; ++i) |
824 | 0 | steps_sq = MAX (steps_sq, bezier_steps_sq (p[i])); |
825 | |
|
826 | 0 | if (steps_sq >= (v == INSIDE ? STEPS_MAX_V * STEPS_MAX_V : STEPS_CLIP_V * STEPS_CLIP_V)) { |
827 | | /* The number of steps is greater than the threshold. This |
828 | | * means that either the error would become too big if we |
829 | | * directly rasterized it or that we can probably save some |
830 | | * time by splitting the curve and clipping part of it. The |
831 | | * patch is only split in the v direction to guarantee that |
832 | | * rasterizing each part will overwrite parts with low v with |
833 | | * overlapping parts with higher v. */ |
834 | |
|
835 | 0 | cairo_point_double_t first[4][4], second[4][4]; |
836 | 0 | double subc[4][4]; |
837 | |
|
838 | 0 | for (i = 0; i < 4; ++i) |
839 | 0 | split_bezier (p[i], first[i], second[i]); |
840 | |
|
841 | 0 | for (i = 0; i < 4; ++i) { |
842 | 0 | subc[0][i] = c[0][i]; |
843 | 0 | subc[1][i] = c[1][i]; |
844 | 0 | subc[2][i] = 0.5 * (c[0][i] + c[2][i]); |
845 | 0 | subc[3][i] = 0.5 * (c[1][i] + c[3][i]); |
846 | 0 | } |
847 | |
|
848 | 0 | draw_bezier_patch (data, width, height, stride, first, subc); |
849 | |
|
850 | 0 | for (i = 0; i < 4; ++i) { |
851 | 0 | subc[0][i] = subc[2][i]; |
852 | 0 | subc[1][i] = subc[3][i]; |
853 | 0 | subc[2][i] = c[2][i]; |
854 | 0 | subc[3][i] = c[3][i]; |
855 | 0 | } |
856 | 0 | draw_bezier_patch (data, width, height, stride, second, subc); |
857 | 0 | } else { |
858 | 0 | rasterize_bezier_patch (data, width, height, stride, sqsteps2shift (steps_sq), p, c); |
859 | 0 | } |
860 | 0 | } |
861 | | |
862 | | /* |
863 | | * Draw a tensor product shading pattern. |
864 | | * |
865 | | * Input: mesh is the mesh pattern |
866 | | * data is the base pointer of the image |
867 | | * width, height are the dimensions of the image |
868 | | * stride is the stride in bytes between adjacent rows |
869 | | * |
870 | | * Output: data will be changed to have the pattern drawn on it |
871 | | * |
872 | | * data is assumed to be clear and its content is assumed to be in |
873 | | * CAIRO_FORMAT_ARGB32 (8 bpc, premultiplied). |
874 | | * |
875 | | * This function can be used to rasterize a PDF type 7 shading (see |
876 | | * http://www.adobe.com/devnet/pdf/pdf_reference.html). |
877 | | */ |
878 | | void |
879 | | _cairo_mesh_pattern_rasterize (const cairo_mesh_pattern_t *mesh, |
880 | | void *data, |
881 | | int width, |
882 | | int height, |
883 | | int stride, |
884 | | double x_offset, |
885 | | double y_offset) |
886 | 0 | { |
887 | 0 | cairo_point_double_t nodes[4][4]; |
888 | 0 | double colors[4][4]; |
889 | 0 | cairo_matrix_t p2u; |
890 | 0 | unsigned int i, j, k, n; |
891 | 0 | cairo_status_t status; |
892 | 0 | const cairo_mesh_patch_t *patch; |
893 | 0 | const cairo_color_t *c; |
894 | |
|
895 | 0 | assert (mesh->base.status == CAIRO_STATUS_SUCCESS); |
896 | 0 | assert (mesh->current_patch == NULL); |
897 | | |
898 | 0 | p2u = mesh->base.matrix; |
899 | 0 | status = cairo_matrix_invert (&p2u); |
900 | 0 | assert (status == CAIRO_STATUS_SUCCESS); |
901 | | |
902 | 0 | n = _cairo_array_num_elements (&mesh->patches); |
903 | 0 | patch = _cairo_array_index_const (&mesh->patches, 0); |
904 | 0 | for (i = 0; i < n; i++) { |
905 | 0 | for (j = 0; j < 4; j++) { |
906 | 0 | for (k = 0; k < 4; k++) { |
907 | 0 | nodes[j][k] = patch->points[j][k]; |
908 | 0 | cairo_matrix_transform_point (&p2u, &nodes[j][k].x, &nodes[j][k].y); |
909 | 0 | nodes[j][k].x += x_offset; |
910 | 0 | nodes[j][k].y += y_offset; |
911 | 0 | } |
912 | 0 | } |
913 | |
|
914 | 0 | c = &patch->colors[0]; |
915 | 0 | colors[0][0] = c->red; |
916 | 0 | colors[0][1] = c->green; |
917 | 0 | colors[0][2] = c->blue; |
918 | 0 | colors[0][3] = c->alpha; |
919 | |
|
920 | 0 | c = &patch->colors[3]; |
921 | 0 | colors[1][0] = c->red; |
922 | 0 | colors[1][1] = c->green; |
923 | 0 | colors[1][2] = c->blue; |
924 | 0 | colors[1][3] = c->alpha; |
925 | |
|
926 | 0 | c = &patch->colors[1]; |
927 | 0 | colors[2][0] = c->red; |
928 | 0 | colors[2][1] = c->green; |
929 | 0 | colors[2][2] = c->blue; |
930 | 0 | colors[2][3] = c->alpha; |
931 | |
|
932 | 0 | c = &patch->colors[2]; |
933 | 0 | colors[3][0] = c->red; |
934 | 0 | colors[3][1] = c->green; |
935 | 0 | colors[3][2] = c->blue; |
936 | 0 | colors[3][3] = c->alpha; |
937 | |
|
938 | 0 | draw_bezier_patch (data, width, height, stride, nodes, colors); |
939 | 0 | patch++; |
940 | 0 | } |
941 | 0 | } |