Rev 1892 | Go to most recent revision | Show entire file | Regard whitespace | Details | Blame | Last modification | View Log | RSS feed
Rev 1892 | Rev 3959 | ||
---|---|---|---|
Line 37... | Line 37... | ||
37 | * 2002-07-15: Converted from XRenderCompositeDoublePoly to #cairo_trap_t. Carl D. Worth |
37 | * 2002-07-15: Converted from XRenderCompositeDoublePoly to #cairo_trap_t. Carl D. Worth |
38 | */ |
38 | */ |
Line 39... | Line 39... | ||
39 | 39 | ||
Line -... | Line 40... | ||
- | 40 | #include "cairoint.h" |
|
40 | #include "cairoint.h" |
41 | |
41 | 42 | #include "cairo-box-inline.h" |
|
42 | #include "cairo-boxes-private.h" |
43 | #include "cairo-boxes-private.h" |
43 | #include "cairo-error-private.h" |
44 | #include "cairo-error-private.h" |
- | 45 | #include "cairo-region-private.h" |
|
- | 46 | #include "cairo-slope-private.h" |
|
Line 44... | Line 47... | ||
44 | #include "cairo-region-private.h" |
47 | #include "cairo-traps-private.h" |
Line 45... | Line 48... | ||
45 | #include "cairo-slope-private.h" |
48 | #include "cairo-spans-private.h" |
46 | 49 | ||
Line 69... | Line 72... | ||
69 | void |
72 | void |
70 | _cairo_traps_limit (cairo_traps_t *traps, |
73 | _cairo_traps_limit (cairo_traps_t *traps, |
71 | const cairo_box_t *limits, |
74 | const cairo_box_t *limits, |
72 | int num_limits) |
75 | int num_limits) |
73 | { |
76 | { |
- | 77 | int i; |
|
- | 78 | ||
74 | traps->limits = limits; |
79 | traps->limits = limits; |
75 | traps->num_limits = num_limits; |
80 | traps->num_limits = num_limits; |
- | 81 | ||
- | 82 | traps->bounds = limits[0]; |
|
- | 83 | for (i = 1; i < num_limits; i++) |
|
- | 84 | _cairo_box_add_box (&traps->bounds, &limits[i]); |
|
- | 85 | } |
|
- | 86 | ||
- | 87 | void |
|
- | 88 | _cairo_traps_init_with_clip (cairo_traps_t *traps, |
|
- | 89 | const cairo_clip_t *clip) |
|
- | 90 | { |
|
- | 91 | _cairo_traps_init (traps); |
|
- | 92 | if (clip) |
|
- | 93 | _cairo_traps_limit (traps, clip->boxes, clip->num_boxes); |
|
76 | } |
94 | } |
Line 77... | Line 95... | ||
77 | 95 | ||
78 | void |
96 | void |
79 | _cairo_traps_clear (cairo_traps_t *traps) |
97 | _cairo_traps_clear (cairo_traps_t *traps) |
Line 145... | Line 163... | ||
145 | trap->bottom = bottom; |
163 | trap->bottom = bottom; |
146 | trap->left = *left; |
164 | trap->left = *left; |
147 | trap->right = *right; |
165 | trap->right = *right; |
148 | } |
166 | } |
Line -... | Line 167... | ||
- | 167 | ||
- | 168 | static void |
|
- | 169 | _cairo_traps_add_clipped_trap (cairo_traps_t *traps, |
|
- | 170 | cairo_fixed_t _top, cairo_fixed_t _bottom, |
|
- | 171 | cairo_line_t *_left, cairo_line_t *_right) |
|
- | 172 | { |
|
- | 173 | /* Note: With the goofy trapezoid specification, (where an |
|
- | 174 | * arbitrary two points on the lines can specified for the left |
|
- | 175 | * and right edges), these limit checks would not work in |
|
- | 176 | * general. For example, one can imagine a trapezoid entirely |
|
- | 177 | * within the limits, but with two points used to specify the left |
|
- | 178 | * edge entirely to the right of the limits. Fortunately, for our |
|
- | 179 | * purposes, cairo will never generate such a crazy |
|
- | 180 | * trapezoid. Instead, cairo always uses for its points the |
|
- | 181 | * extreme positions of the edge that are visible on at least some |
|
- | 182 | * trapezoid. With this constraint, it's impossible for both |
|
- | 183 | * points to be outside the limits while the relevant edge is |
|
- | 184 | * entirely inside the limits. |
|
- | 185 | */ |
|
- | 186 | if (traps->num_limits) { |
|
- | 187 | const cairo_box_t *b = &traps->bounds; |
|
- | 188 | cairo_fixed_t top = _top, bottom = _bottom; |
|
- | 189 | cairo_line_t left = *_left, right = *_right; |
|
- | 190 | ||
- | 191 | /* Trivially reject if trapezoid is entirely to the right or |
|
- | 192 | * to the left of the limits. */ |
|
- | 193 | if (left.p1.x >= b->p2.x && left.p2.x >= b->p2.x) |
|
- | 194 | return; |
|
- | 195 | ||
- | 196 | if (right.p1.x <= b->p1.x && right.p2.x <= b->p1.x) |
|
- | 197 | return; |
|
- | 198 | ||
- | 199 | /* And reject if the trapezoid is entirely above or below */ |
|
- | 200 | if (top >= b->p2.y || bottom <= b->p1.y) |
|
- | 201 | return; |
|
- | 202 | ||
- | 203 | /* Otherwise, clip the trapezoid to the limits. We only clip |
|
- | 204 | * where an edge is entirely outside the limits. If we wanted |
|
- | 205 | * to be more clever, we could handle cases where a trapezoid |
|
- | 206 | * edge intersects the edge of the limits, but that would |
|
- | 207 | * require slicing this trapezoid into multiple trapezoids, |
|
- | 208 | * and I'm not sure the effort would be worth it. */ |
|
- | 209 | if (top < b->p1.y) |
|
- | 210 | top = b->p1.y; |
|
- | 211 | ||
- | 212 | if (bottom > b->p2.y) |
|
- | 213 | bottom = b->p2.y; |
|
- | 214 | ||
- | 215 | if (left.p1.x <= b->p1.x && left.p2.x <= b->p1.x) |
|
- | 216 | left.p1.x = left.p2.x = b->p1.x; |
|
- | 217 | ||
- | 218 | if (right.p1.x >= b->p2.x && right.p2.x >= b->p2.x) |
|
- | 219 | right.p1.x = right.p2.x = b->p2.x; |
|
- | 220 | ||
- | 221 | /* Trivial discards for empty trapezoids that are likely to |
|
- | 222 | * be produced by our tessellators (most notably convex_quad |
|
- | 223 | * when given a simple rectangle). |
|
- | 224 | */ |
|
- | 225 | if (top >= bottom) |
|
- | 226 | return; |
|
- | 227 | ||
- | 228 | /* cheap colinearity check */ |
|
- | 229 | if (right.p1.x <= left.p1.x && right.p1.y == left.p1.y && |
|
- | 230 | right.p2.x <= left.p2.x && right.p2.y == left.p2.y) |
|
- | 231 | return; |
|
- | 232 | ||
- | 233 | _cairo_traps_add_trap (traps, top, bottom, &left, &right); |
|
- | 234 | } else |
|
- | 235 | _cairo_traps_add_trap (traps, _top, _bottom, _left, _right); |
|
- | 236 | } |
|
- | 237 | ||
- | 238 | static int |
|
- | 239 | _compare_point_fixed_by_y (const void *av, const void *bv) |
|
- | 240 | { |
|
- | 241 | const cairo_point_t *a = av, *b = bv; |
|
- | 242 | int ret = a->y - b->y; |
|
- | 243 | if (ret == 0) |
|
- | 244 | ret = a->x - b->x; |
|
- | 245 | return ret; |
|
- | 246 | } |
|
- | 247 | ||
- | 248 | void |
|
- | 249 | _cairo_traps_tessellate_convex_quad (cairo_traps_t *traps, |
|
- | 250 | const cairo_point_t q[4]) |
|
- | 251 | { |
|
- | 252 | int a, b, c, d; |
|
- | 253 | int i; |
|
- | 254 | cairo_slope_t ab, ad; |
|
- | 255 | cairo_bool_t b_left_of_d; |
|
- | 256 | cairo_line_t left; |
|
- | 257 | cairo_line_t right; |
|
- | 258 | ||
- | 259 | /* Choose a as a point with minimal y */ |
|
- | 260 | a = 0; |
|
- | 261 | for (i = 1; i < 4; i++) |
|
- | 262 | if (_compare_point_fixed_by_y (&q[i], &q[a]) < 0) |
|
- | 263 | a = i; |
|
- | 264 | ||
- | 265 | /* b and d are adjacent to a, while c is opposite */ |
|
- | 266 | b = (a + 1) % 4; |
|
- | 267 | c = (a + 2) % 4; |
|
- | 268 | d = (a + 3) % 4; |
|
- | 269 | ||
- | 270 | /* Choose between b and d so that b.y is less than d.y */ |
|
- | 271 | if (_compare_point_fixed_by_y (&q[d], &q[b]) < 0) { |
|
- | 272 | b = (a + 3) % 4; |
|
- | 273 | d = (a + 1) % 4; |
|
- | 274 | } |
|
- | 275 | ||
- | 276 | /* Without freedom left to choose anything else, we have four |
|
- | 277 | * cases to tessellate. |
|
- | 278 | * |
|
- | 279 | * First, we have to determine the Y-axis sort of the four |
|
- | 280 | * vertices, (either abcd or abdc). After that we need to detemine |
|
- | 281 | * which edges will be "left" and which will be "right" in the |
|
- | 282 | * resulting trapezoids. This can be determined by computing a |
|
- | 283 | * slope comparison of ab and ad to determine if b is left of d or |
|
- | 284 | * not. |
|
- | 285 | * |
|
- | 286 | * Note that "left of" here is in the sense of which edges should |
|
- | 287 | * be the left vs. right edges of the trapezoid. In particular, b |
|
- | 288 | * left of d does *not* mean that b.x is less than d.x. |
|
- | 289 | * |
|
- | 290 | * This should hopefully be made clear in the lame ASCII art |
|
- | 291 | * below. Since the same slope comparison is used in all cases, we |
|
- | 292 | * compute it before testing for the Y-value sort. */ |
|
- | 293 | ||
- | 294 | /* Note: If a == b then the ab slope doesn't give us any |
|
- | 295 | * information. In that case, we can replace it with the ac (or |
|
- | 296 | * equivalenly the bc) slope which gives us exactly the same |
|
- | 297 | * information we need. At worst the names of the identifiers ab |
|
- | 298 | * and b_left_of_d are inaccurate in this case, (would be ac, and |
|
- | 299 | * c_left_of_d). */ |
|
- | 300 | if (q[a].x == q[b].x && q[a].y == q[b].y) |
|
- | 301 | _cairo_slope_init (&ab, &q[a], &q[c]); |
|
- | 302 | else |
|
- | 303 | _cairo_slope_init (&ab, &q[a], &q[b]); |
|
- | 304 | ||
- | 305 | _cairo_slope_init (&ad, &q[a], &q[d]); |
|
- | 306 | ||
- | 307 | b_left_of_d = _cairo_slope_compare (&ab, &ad) > 0; |
|
- | 308 | ||
- | 309 | if (q[c].y <= q[d].y) { |
|
- | 310 | if (b_left_of_d) { |
|
- | 311 | /* Y-sort is abcd and b is left of d, (slope(ab) > slope (ad)) |
|
- | 312 | * |
|
- | 313 | * top bot left right |
|
- | 314 | * _a a a |
|
- | 315 | * / / /| |\ a.y b.y ab ad |
|
- | 316 | * b / b | b \ |
|
- | 317 | * / / | | \ \ b.y c.y bc ad |
|
- | 318 | * c / c | c \ |
|
- | 319 | * | / \| \ \ c.y d.y cd ad |
|
- | 320 | * d d d |
|
- | 321 | */ |
|
- | 322 | left.p1 = q[a]; left.p2 = q[b]; |
|
- | 323 | right.p1 = q[a]; right.p2 = q[d]; |
|
- | 324 | _cairo_traps_add_clipped_trap (traps, q[a].y, q[b].y, &left, &right); |
|
- | 325 | left.p1 = q[b]; left.p2 = q[c]; |
|
- | 326 | _cairo_traps_add_clipped_trap (traps, q[b].y, q[c].y, &left, &right); |
|
- | 327 | left.p1 = q[c]; left.p2 = q[d]; |
|
- | 328 | _cairo_traps_add_clipped_trap (traps, q[c].y, q[d].y, &left, &right); |
|
- | 329 | } else { |
|
- | 330 | /* Y-sort is abcd and b is right of d, (slope(ab) <= slope (ad)) |
|
- | 331 | * |
|
- | 332 | * a a a_ |
|
- | 333 | * /| |\ \ \ a.y b.y ad ab |
|
- | 334 | * / b | b \ b |
|
- | 335 | * / / | | \ \ b.y c.y ad bc |
|
- | 336 | * / c | c \ c |
|
- | 337 | * / / |/ \ | c.y d.y ad cd |
|
- | 338 | * d d d |
|
- | 339 | */ |
|
- | 340 | left.p1 = q[a]; left.p2 = q[d]; |
|
- | 341 | right.p1 = q[a]; right.p2 = q[b]; |
|
- | 342 | _cairo_traps_add_clipped_trap (traps, q[a].y, q[b].y, &left, &right); |
|
- | 343 | right.p1 = q[b]; right.p2 = q[c]; |
|
- | 344 | _cairo_traps_add_clipped_trap (traps, q[b].y, q[c].y, &left, &right); |
|
- | 345 | right.p1 = q[c]; right.p2 = q[d]; |
|
- | 346 | _cairo_traps_add_clipped_trap (traps, q[c].y, q[d].y, &left, &right); |
|
- | 347 | } |
|
- | 348 | } else { |
|
- | 349 | if (b_left_of_d) { |
|
- | 350 | /* Y-sort is abdc and b is left of d, (slope (ab) > slope (ad)) |
|
- | 351 | * |
|
- | 352 | * a a a |
|
- | 353 | * // / \ |\ a.y b.y ab ad |
|
- | 354 | * /b/ b \ b \ |
|
- | 355 | * / / \ \ \ \ b.y d.y bc ad |
|
- | 356 | * /d/ \ d \ d |
|
- | 357 | * // \ / \| d.y c.y bc dc |
|
- | 358 | * c c c |
|
- | 359 | */ |
|
- | 360 | left.p1 = q[a]; left.p2 = q[b]; |
|
- | 361 | right.p1 = q[a]; right.p2 = q[d]; |
|
- | 362 | _cairo_traps_add_clipped_trap (traps, q[a].y, q[b].y, &left, &right); |
|
- | 363 | left.p1 = q[b]; left.p2 = q[c]; |
|
- | 364 | _cairo_traps_add_clipped_trap (traps, q[b].y, q[d].y, &left, &right); |
|
- | 365 | right.p1 = q[d]; right.p2 = q[c]; |
|
- | 366 | _cairo_traps_add_clipped_trap (traps, q[d].y, q[c].y, &left, &right); |
|
- | 367 | } else { |
|
- | 368 | /* Y-sort is abdc and b is right of d, (slope (ab) <= slope (ad)) |
|
- | 369 | * |
|
- | 370 | * a a a |
|
- | 371 | * /| / \ \\ a.y b.y ad ab |
|
- | 372 | * / b / b \b\ |
|
- | 373 | * / / / / \ \ b.y d.y ad bc |
|
- | 374 | * d / d / \d\ |
|
- | 375 | * |/ \ / \\ d.y c.y dc bc |
|
- | 376 | * c c c |
|
- | 377 | */ |
|
- | 378 | left.p1 = q[a]; left.p2 = q[d]; |
|
- | 379 | right.p1 = q[a]; right.p2 = q[b]; |
|
- | 380 | _cairo_traps_add_clipped_trap (traps, q[a].y, q[b].y, &left, &right); |
|
- | 381 | right.p1 = q[b]; right.p2 = q[c]; |
|
- | 382 | _cairo_traps_add_clipped_trap (traps, q[b].y, q[d].y, &left, &right); |
|
- | 383 | left.p1 = q[d]; left.p2 = q[c]; |
|
- | 384 | _cairo_traps_add_clipped_trap (traps, q[d].y, q[c].y, &left, &right); |
|
- | 385 | } |
|
- | 386 | } |
|
- | 387 | } |
|
- | 388 | ||
- | 389 | /* A triangle is simply a degenerate case of a convex |
|
- | 390 | * quadrilateral. We would not benefit from having any distinct |
|
- | 391 | * implementation of triangle vs. quadrilateral tessellation here. */ |
|
- | 392 | void |
|
- | 393 | _cairo_traps_tessellate_triangle (cairo_traps_t *traps, |
|
- | 394 | const cairo_point_t t[3]) |
|
- | 395 | { |
|
- | 396 | cairo_point_t quad[4]; |
|
- | 397 | ||
- | 398 | quad[0] = t[0]; |
|
- | 399 | quad[1] = t[0]; |
|
- | 400 | quad[2] = t[1]; |
|
- | 401 | quad[3] = t[2]; |
|
- | 402 | ||
- | 403 | _cairo_traps_tessellate_convex_quad (traps, quad); |
|
- | 404 | } |
|
- | 405 | ||
149 | 406 | ||
150 | /** |
407 | /** |
151 | * _cairo_traps_init_box: |
408 | * _cairo_traps_init_boxes: |
152 | * @traps: a #cairo_traps_t |
409 | * @traps: a #cairo_traps_t |
153 | * @box: an array box that will each be converted to a single trapezoid |
410 | * @box: an array box that will each be converted to a single trapezoid |
154 | * to store in @traps. |
411 | * to store in @traps. |
155 | * |
412 | * |
Line 227... | Line 484... | ||
227 | 484 | ||
228 | if (traps->num_limits) { |
485 | if (traps->num_limits) { |
229 | cairo_bool_t reversed; |
486 | cairo_bool_t reversed; |
Line -... | Line 487... | ||
- | 487 | int n; |
|
- | 488 | ||
- | 489 | if (top >= traps->bounds.p2.y || bottom <= traps->bounds.p1.y) |
|
230 | int n; |
490 | return CAIRO_STATUS_SUCCESS; |
231 | 491 | ||
232 | /* support counter-clockwise winding for rectangular tessellation */ |
492 | /* support counter-clockwise winding for rectangular tessellation */ |
233 | reversed = top_left->x > bottom_right->x; |
493 | reversed = top_left->x > bottom_right->x; |
234 | if (reversed) { |
494 | if (reversed) { |
235 | right.p1.x = right.p2.x = top_left->x; |
495 | right.p1.x = right.p2.x = top_left->x; |
Line -... | Line 496... | ||
- | 496 | left.p1.x = left.p2.x = bottom_right->x; |
|
- | 497 | } |
|
- | 498 | ||
236 | left.p1.x = left.p2.x = bottom_right->x; |
499 | if (left.p1.x >= traps->bounds.p2.x || right.p1.x <= traps->bounds.p1.x) |
237 | } |
500 | return CAIRO_STATUS_SUCCESS; |
238 | 501 | ||
239 | for (n = 0; n < traps->num_limits; n++) { |
502 | for (n = 0; n < traps->num_limits; n++) { |
Line 483... | Line 746... | ||
483 | extents->p2.x = x; |
746 | extents->p2.x = x; |
484 | } |
747 | } |
485 | } |
748 | } |
486 | } |
749 | } |
Line -... | Line 750... | ||
- | 750 | ||
- | 751 | static cairo_bool_t |
|
- | 752 | _mono_edge_is_vertical (const cairo_line_t *line) |
|
- | 753 | { |
|
- | 754 | return _cairo_fixed_integer_round_down (line->p1.x) == _cairo_fixed_integer_round_down (line->p2.x); |
|
- | 755 | } |
|
- | 756 | ||
- | 757 | static cairo_bool_t |
|
- | 758 | _traps_are_pixel_aligned (cairo_traps_t *traps, |
|
- | 759 | cairo_antialias_t antialias) |
|
- | 760 | { |
|
- | 761 | int i; |
|
- | 762 | ||
- | 763 | if (antialias == CAIRO_ANTIALIAS_NONE) { |
|
- | 764 | for (i = 0; i < traps->num_traps; i++) { |
|
- | 765 | if (! _mono_edge_is_vertical (&traps->traps[i].left) || |
|
- | 766 | ! _mono_edge_is_vertical (&traps->traps[i].right)) |
|
- | 767 | { |
|
- | 768 | traps->maybe_region = FALSE; |
|
- | 769 | return FALSE; |
|
- | 770 | } |
|
- | 771 | } |
|
- | 772 | } else { |
|
- | 773 | for (i = 0; i < traps->num_traps; i++) { |
|
- | 774 | if (traps->traps[i].left.p1.x != traps->traps[i].left.p2.x || |
|
- | 775 | traps->traps[i].right.p1.x != traps->traps[i].right.p2.x || |
|
- | 776 | ! _cairo_fixed_is_integer (traps->traps[i].top) || |
|
- | 777 | ! _cairo_fixed_is_integer (traps->traps[i].bottom) || |
|
- | 778 | ! _cairo_fixed_is_integer (traps->traps[i].left.p1.x) || |
|
- | 779 | ! _cairo_fixed_is_integer (traps->traps[i].right.p1.x)) |
|
- | 780 | { |
|
- | 781 | traps->maybe_region = FALSE; |
|
- | 782 | return FALSE; |
|
- | 783 | } |
|
- | 784 | } |
|
- | 785 | } |
|
- | 786 | ||
- | 787 | return TRUE; |
|
Line 487... | Line 788... | ||
487 | 788 | } |
|
488 | 789 | ||
489 | /** |
790 | /** |
490 | * _cairo_traps_extract_region: |
791 | * _cairo_traps_extract_region: |
Line 500... | Line 801... | ||
500 | * Return value: %CAIRO_STATUS_SUCCESS, %CAIRO_INT_STATUS_UNSUPPORTED |
801 | * Return value: %CAIRO_STATUS_SUCCESS, %CAIRO_INT_STATUS_UNSUPPORTED |
501 | * or %CAIRO_STATUS_NO_MEMORY |
802 | * or %CAIRO_STATUS_NO_MEMORY |
502 | **/ |
803 | **/ |
503 | cairo_int_status_t |
804 | cairo_int_status_t |
504 | _cairo_traps_extract_region (cairo_traps_t *traps, |
805 | _cairo_traps_extract_region (cairo_traps_t *traps, |
- | 806 | cairo_antialias_t antialias, |
|
505 | cairo_region_t **region) |
807 | cairo_region_t **region) |
506 | { |
808 | { |
507 | cairo_rectangle_int_t stack_rects[CAIRO_STACK_ARRAY_LENGTH (cairo_rectangle_int_t)]; |
809 | cairo_rectangle_int_t stack_rects[CAIRO_STACK_ARRAY_LENGTH (cairo_rectangle_int_t)]; |
508 | cairo_rectangle_int_t *rects = stack_rects; |
810 | cairo_rectangle_int_t *rects = stack_rects; |
509 | cairo_int_status_t status; |
811 | cairo_int_status_t status; |
510 | int i, rect_count; |
812 | int i, rect_count; |
Line 511... | Line 813... | ||
511 | 813 | ||
512 | /* we only treat this a hint... */ |
814 | /* we only treat this a hint... */ |
513 | if (! traps->maybe_region) |
815 | if (antialias != CAIRO_ANTIALIAS_NONE && ! traps->maybe_region) |
Line 514... | Line -... | ||
514 | return CAIRO_INT_STATUS_UNSUPPORTED; |
- | |
515 | - | ||
516 | for (i = 0; i < traps->num_traps; i++) { |
- | |
517 | if (traps->traps[i].left.p1.x != traps->traps[i].left.p2.x || |
- | |
518 | traps->traps[i].right.p1.x != traps->traps[i].right.p2.x || |
- | |
519 | ! _cairo_fixed_is_integer (traps->traps[i].top) || |
- | |
520 | ! _cairo_fixed_is_integer (traps->traps[i].bottom) || |
816 | return CAIRO_INT_STATUS_UNSUPPORTED; |
521 | ! _cairo_fixed_is_integer (traps->traps[i].left.p1.x) || |
- | |
522 | ! _cairo_fixed_is_integer (traps->traps[i].right.p1.x)) |
817 | |
523 | { |
818 | if (! _traps_are_pixel_aligned (traps, antialias)) { |
524 | traps->maybe_region = FALSE; |
819 | traps->maybe_region = FALSE; |
525 | return CAIRO_INT_STATUS_UNSUPPORTED; |
- | |
Line 526... | Line 820... | ||
526 | } |
820 | return CAIRO_INT_STATUS_UNSUPPORTED; |
527 | } |
821 | } |
Line 528... | Line 822... | ||
528 | 822 | ||
529 | if (traps->num_traps > ARRAY_LENGTH (stack_rects)) { |
823 | if (traps->num_traps > ARRAY_LENGTH (stack_rects)) { |
530 | rects = _cairo_malloc_ab (traps->num_traps, sizeof (cairo_rectangle_int_t)); |
824 | rects = _cairo_malloc_ab (traps->num_traps, sizeof (cairo_rectangle_int_t)); |
Line 531... | Line 825... | ||
531 | 825 | ||
532 | if (unlikely (rects == NULL)) |
826 | if (unlikely (rects == NULL)) |
533 | return _cairo_error (CAIRO_STATUS_NO_MEMORY); |
- | |
534 | } |
827 | return _cairo_error (CAIRO_STATUS_NO_MEMORY); |
535 | - | ||
536 | rect_count = 0; |
- | |
Line -... | Line 828... | ||
- | 828 | } |
|
- | 829 | ||
- | 830 | rect_count = 0; |
|
- | 831 | for (i = 0; i < traps->num_traps; i++) { |
|
- | 832 | int x1, y1, x2, y2; |
|
- | 833 | ||
- | 834 | if (antialias == CAIRO_ANTIALIAS_NONE) { |
|
- | 835 | x1 = _cairo_fixed_integer_round_down (traps->traps[i].left.p1.x); |
|
- | 836 | y1 = _cairo_fixed_integer_round_down (traps->traps[i].top); |
|
- | 837 | x2 = _cairo_fixed_integer_round_down (traps->traps[i].right.p1.x); |
|
- | 838 | y2 = _cairo_fixed_integer_round_down (traps->traps[i].bottom); |
|
- | 839 | } else { |
|
- | 840 | x1 = _cairo_fixed_integer_part (traps->traps[i].left.p1.x); |
|
537 | for (i = 0; i < traps->num_traps; i++) { |
841 | y1 = _cairo_fixed_integer_part (traps->traps[i].top); |
538 | int x1 = _cairo_fixed_integer_part (traps->traps[i].left.p1.x); |
842 | x2 = _cairo_fixed_integer_part (traps->traps[i].right.p1.x); |
539 | int y1 = _cairo_fixed_integer_part (traps->traps[i].top); |
843 | y2 = _cairo_fixed_integer_part (traps->traps[i].bottom); |
540 | int x2 = _cairo_fixed_integer_part (traps->traps[i].right.p1.x); |
844 | } |
541 | int y2 = _cairo_fixed_integer_part (traps->traps[i].bottom); |
- | |
542 | 845 | ||
543 | rects[rect_count].x = x1; |
846 | if (x2 > x1 && y2 > y1) { |
- | 847 | rects[rect_count].x = x1; |
|
- | 848 | rects[rect_count].y = y1; |
|
Line 544... | Line 849... | ||
544 | rects[rect_count].y = y1; |
849 | rects[rect_count].width = x2 - x1; |
545 | rects[rect_count].width = x2 - x1; |
850 | rects[rect_count].height = y2 - y1; |
Line 546... | Line 851... | ||
546 | rects[rect_count].height = y2 - y1; |
851 | rect_count++; |
547 | 852 | } |
|
Line 548... | Line 853... | ||
548 | rect_count++; |
853 | } |
549 | } |
854 | |
Line -... | Line 855... | ||
- | 855 | ||
- | 856 | *region = cairo_region_create_rectangles (rects, rect_count); |
|
- | 857 | status = (*region)->status; |
|
- | 858 | ||
- | 859 | if (rects != stack_rects) |
|
- | 860 | free (rects); |
|
- | 861 | ||
- | 862 | return status; |
|
- | 863 | } |
|
- | 864 | ||
- | 865 | cairo_bool_t |
|
- | 866 | _cairo_traps_to_boxes (cairo_traps_t *traps, |
|
- | 867 | cairo_antialias_t antialias, |
|
- | 868 | cairo_boxes_t *boxes) |
|
- | 869 | { |
|
- | 870 | int i; |
|
- | 871 | ||
- | 872 | for (i = 0; i < traps->num_traps; i++) { |
|
- | 873 | if (traps->traps[i].left.p1.x != traps->traps[i].left.p2.x || |
|
- | 874 | traps->traps[i].right.p1.x != traps->traps[i].right.p2.x) |
|
- | 875 | return FALSE; |
|
- | 876 | } |
|
- | 877 | ||
- | 878 | _cairo_boxes_init (boxes); |
|
- | 879 | ||
- | 880 | boxes->num_boxes = traps->num_traps; |
|
- | 881 | boxes->chunks.base = (cairo_box_t *) traps->traps; |
|
- | 882 | boxes->chunks.count = traps->num_traps; |
|
- | 883 | boxes->chunks.size = traps->num_traps; |
|
- | 884 | ||
- | 885 | if (antialias != CAIRO_ANTIALIAS_NONE) { |
|
- | 886 | for (i = 0; i < traps->num_traps; i++) { |
|
- | 887 | /* Note the traps and boxes alias so we need to take the local copies first. */ |
|
- | 888 | cairo_fixed_t x1 = traps->traps[i].left.p1.x; |
|
- | 889 | cairo_fixed_t x2 = traps->traps[i].right.p1.x; |
|
- | 890 | cairo_fixed_t y1 = traps->traps[i].top; |
|
- | 891 | cairo_fixed_t y2 = traps->traps[i].bottom; |
|
- | 892 | ||
- | 893 | boxes->chunks.base[i].p1.x = x1; |
|
- | 894 | boxes->chunks.base[i].p1.y = y1; |
|
- | 895 | boxes->chunks.base[i].p2.x = x2; |
|
- | 896 | boxes->chunks.base[i].p2.y = y2; |
|
- | 897 | ||
- | 898 | if (boxes->is_pixel_aligned) { |
|
- | 899 | boxes->is_pixel_aligned = |
|
- | 900 | _cairo_fixed_is_integer (x1) && _cairo_fixed_is_integer (y1) && |
|
- | 901 | _cairo_fixed_is_integer (x2) && _cairo_fixed_is_integer (y2); |
|
- | 902 | } |
|
- | 903 | } |
|
- | 904 | } else { |
|
- | 905 | boxes->is_pixel_aligned = TRUE; |
|
- | 906 | ||
- | 907 | for (i = 0; i < traps->num_traps; i++) { |
|
- | 908 | /* Note the traps and boxes alias so we need to take the local copies first. */ |
|
- | 909 | cairo_fixed_t x1 = traps->traps[i].left.p1.x; |
|
- | 910 | cairo_fixed_t x2 = traps->traps[i].right.p1.x; |
|
- | 911 | cairo_fixed_t y1 = traps->traps[i].top; |
|
- | 912 | cairo_fixed_t y2 = traps->traps[i].bottom; |
|
- | 913 | ||
- | 914 | /* round down here to match Pixman's behavior when using traps. */ |
|
550 | 915 | boxes->chunks.base[i].p1.x = _cairo_fixed_round_down (x1); |
|
551 | *region = cairo_region_create_rectangles (rects, rect_count); |
916 | boxes->chunks.base[i].p1.y = _cairo_fixed_round_down (y1); |
552 | status = (*region)->status; |
917 | boxes->chunks.base[i].p2.x = _cairo_fixed_round_down (x2); |
553 | 918 | boxes->chunks.base[i].p2.y = _cairo_fixed_round_down (y2); |
|
554 | if (rects != stack_rects) |
919 | } |
Line 601... | Line 966... | ||
601 | if (unlikely (status)) return status; |
966 | if (unlikely (status)) return status; |
602 | } |
967 | } |
Line 603... | Line 968... | ||
603 | 968 | ||
604 | return CAIRO_STATUS_SUCCESS; |
969 | return CAIRO_STATUS_SUCCESS; |
- | 970 | } |
|
- | 971 | ||
- | 972 | void |
|
- | 973 | _cairo_debug_print_traps (FILE *file, const cairo_traps_t *traps) |
|
- | 974 | { |
|
- | 975 | cairo_box_t extents; |
|
- | 976 | int n; |
|
- | 977 | ||
- | 978 | #if 0 |
|
- | 979 | if (traps->has_limits) { |
|
- | 980 | printf ("%s: limits=(%d, %d, %d, %d)\n", |
|
- | 981 | filename, |
|
- | 982 | traps->limits.p1.x, traps->limits.p1.y, |
|
- | 983 | traps->limits.p2.x, traps->limits.p2.y); |
|
- | 984 | } |
|
- | 985 | #endif |
|
- | 986 | ||
- | 987 | _cairo_traps_extents (traps, &extents); |
|
- | 988 | fprintf (file, "extents=(%d, %d, %d, %d)\n", |
|
- | 989 | extents.p1.x, extents.p1.y, |
|
- | 990 | extents.p2.x, extents.p2.y); |
|
- | 991 | ||
- | 992 | for (n = 0; n < traps->num_traps; n++) { |
|
- | 993 | fprintf (file, "%d %d L:(%d, %d), (%d, %d) R:(%d, %d), (%d, %d)\n", |
|
- | 994 | traps->traps[n].top, |
|
- | 995 | traps->traps[n].bottom, |
|
- | 996 | traps->traps[n].left.p1.x, |
|
- | 997 | traps->traps[n].left.p1.y, |
|
- | 998 | traps->traps[n].left.p2.x, |
|
- | 999 | traps->traps[n].left.p2.y, |
|
- | 1000 | traps->traps[n].right.p1.x, |
|
- | 1001 | traps->traps[n].right.p1.y, |
|
- | 1002 | traps->traps[n].right.p2.x, |
|
- | 1003 | traps->traps[n].right.p2.y); |
|
- | 1004 | } |
|
- | 1005 | } |
|
- | 1006 | ||
- | 1007 | struct cairo_trap_renderer { |
|
- | 1008 | cairo_span_renderer_t base; |
|
- | 1009 | cairo_traps_t *traps; |
|
- | 1010 | }; |
|
- | 1011 | ||
- | 1012 | static cairo_status_t |
|
- | 1013 | span_to_traps (void *abstract_renderer, int y, int h, |
|
- | 1014 | const cairo_half_open_span_t *spans, unsigned num_spans) |
|
- | 1015 | { |
|
- | 1016 | struct cairo_trap_renderer *r = abstract_renderer; |
|
- | 1017 | cairo_fixed_t top, bot; |
|
- | 1018 | ||
- | 1019 | if (num_spans == 0) |
|
- | 1020 | return CAIRO_STATUS_SUCCESS; |
|
- | 1021 | ||
- | 1022 | top = _cairo_fixed_from_int (y); |
|
- | 1023 | bot = _cairo_fixed_from_int (y + h); |
|
- | 1024 | do { |
|
- | 1025 | if (spans[0].coverage) { |
|
- | 1026 | cairo_fixed_t x0 = _cairo_fixed_from_int(spans[0].x); |
|
- | 1027 | cairo_fixed_t x1 = _cairo_fixed_from_int(spans[1].x); |
|
- | 1028 | cairo_line_t left = { { x0, top }, { x0, bot } }, |
|
- | 1029 | right = { { x1, top }, { x1, bot } }; |
|
- | 1030 | _cairo_traps_add_trap (r->traps, top, bot, &left, &right); |
|
- | 1031 | } |
|
- | 1032 | spans++; |
|
- | 1033 | } while (--num_spans > 1); |
|
- | 1034 | ||
- | 1035 | return CAIRO_STATUS_SUCCESS; |
|
- | 1036 | } |
|
- | 1037 | ||
- | 1038 | cairo_int_status_t |
|
- | 1039 | _cairo_rasterise_polygon_to_traps (cairo_polygon_t *polygon, |
|
- | 1040 | cairo_fill_rule_t fill_rule, |
|
- | 1041 | cairo_antialias_t antialias, |
|
- | 1042 | cairo_traps_t *traps) |
|
- | 1043 | { |
|
- | 1044 | struct cairo_trap_renderer renderer; |
|
- | 1045 | cairo_scan_converter_t *converter; |
|
- | 1046 | cairo_int_status_t status; |
|
- | 1047 | cairo_rectangle_int_t r; |
|
- | 1048 | ||
- | 1049 | TRACE ((stderr, "%s: fill_rule=%d, antialias=%d\n", |
|
- | 1050 | __FUNCTION__, fill_rule, antialias)); |
|
- | 1051 | assert(antialias == CAIRO_ANTIALIAS_NONE); |
|
- | 1052 | ||
- | 1053 | renderer.traps = traps; |
|
- | 1054 | renderer.base.render_rows = span_to_traps; |
|
- | 1055 | ||
- | 1056 | _cairo_box_round_to_rectangle (&polygon->extents, &r); |
|
- | 1057 | converter = _cairo_mono_scan_converter_create (r.x, r.y, |
|
- | 1058 | r.x + r.width, |
|
- | 1059 | r.y + r.height, |
|
- | 1060 | fill_rule); |
|
- | 1061 | status = _cairo_mono_scan_converter_add_polygon (converter, polygon); |
|
- | 1062 | if (likely (status == CAIRO_INT_STATUS_SUCCESS)) |
|
- | 1063 | status = converter->generate (converter, &renderer.base); |
|
- | 1064 | converter->destroy (converter); |
|
- | 1065 | return status; |