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 31... | Line 31... | ||
31 | * Chris Wilson |
31 | * Chris Wilson |
32 | */ |
32 | */ |
Line 33... | Line 33... | ||
33 | 33 | ||
Line -... | Line 34... | ||
- | 34 | #include "cairoint.h" |
|
34 | #include "cairoint.h" |
35 | |
35 | 36 | #include "cairo-box-inline.h" |
|
Line 36... | Line 37... | ||
36 | #include "cairo-boxes-private.h" |
37 | #include "cairo-boxes-private.h" |
37 | #include "cairo-error-private.h" |
38 | #include "cairo-error-private.h" |
Line 51... | Line 52... | ||
51 | 52 | ||
52 | boxes->is_pixel_aligned = TRUE; |
53 | boxes->is_pixel_aligned = TRUE; |
Line 53... | Line 54... | ||
53 | } |
54 | } |
- | 55 | ||
- | 56 | void |
|
- | 57 | _cairo_boxes_init_from_rectangle (cairo_boxes_t *boxes, |
|
- | 58 | int x, int y, int w, int h) |
|
- | 59 | { |
|
- | 60 | _cairo_boxes_init (boxes); |
|
- | 61 | ||
- | 62 | _cairo_box_from_integers (&boxes->chunks.base[0], x, y, w, h); |
|
- | 63 | boxes->num_boxes = 1; |
|
- | 64 | } |
|
- | 65 | ||
- | 66 | void |
|
- | 67 | _cairo_boxes_init_with_clip (cairo_boxes_t *boxes, |
|
- | 68 | cairo_clip_t *clip) |
|
- | 69 | { |
|
- | 70 | _cairo_boxes_init (boxes); |
|
- | 71 | if (clip) |
|
- | 72 | _cairo_boxes_limit (boxes, clip->boxes, clip->num_boxes); |
|
- | 73 | } |
|
54 | 74 | ||
55 | void |
75 | void |
56 | _cairo_boxes_init_for_array (cairo_boxes_t *boxes, |
76 | _cairo_boxes_init_for_array (cairo_boxes_t *boxes, |
57 | cairo_box_t *array, |
77 | cairo_box_t *array, |
58 | int num_boxes) |
78 | int num_boxes) |
Line 143... | Line 163... | ||
143 | } |
163 | } |
Line 144... | Line 164... | ||
144 | 164 | ||
145 | chunk->base[chunk->count++] = *box; |
165 | chunk->base[chunk->count++] = *box; |
Line 146... | Line 166... | ||
146 | boxes->num_boxes++; |
166 | boxes->num_boxes++; |
147 | 167 | ||
148 | if (boxes->is_pixel_aligned) { |
- | |
149 | boxes->is_pixel_aligned = |
- | |
150 | _cairo_fixed_is_integer (box->p1.x) && |
- | |
151 | _cairo_fixed_is_integer (box->p1.y) && |
- | |
152 | _cairo_fixed_is_integer (box->p2.x) && |
- | |
153 | _cairo_fixed_is_integer (box->p2.y); |
168 | if (boxes->is_pixel_aligned) |
Line 154... | Line 169... | ||
154 | } |
169 | boxes->is_pixel_aligned = _cairo_box_is_pixel_aligned (box); |
155 | } |
170 | } |
- | 171 | ||
156 | 172 | cairo_status_t |
|
157 | cairo_status_t |
173 | _cairo_boxes_add (cairo_boxes_t *boxes, |
- | 174 | cairo_antialias_t antialias, |
|
- | 175 | const cairo_box_t *box) |
|
- | 176 | { |
|
- | 177 | cairo_box_t b; |
|
- | 178 | ||
- | 179 | if (antialias == CAIRO_ANTIALIAS_NONE) { |
|
- | 180 | b.p1.x = _cairo_fixed_round_down (box->p1.x); |
|
- | 181 | b.p1.y = _cairo_fixed_round_down (box->p1.y); |
|
- | 182 | b.p2.x = _cairo_fixed_round_down (box->p2.x); |
|
- | 183 | b.p2.y = _cairo_fixed_round_down (box->p2.y); |
|
158 | _cairo_boxes_add (cairo_boxes_t *boxes, |
184 | box = &b; |
159 | const cairo_box_t *box) |
185 | } |
Line 160... | Line 186... | ||
160 | { |
186 | |
161 | if (box->p1.y == box->p2.y) |
187 | if (box->p1.y == box->p2.y) |
Line 239... | Line 265... | ||
239 | return boxes->status; |
265 | return boxes->status; |
240 | } |
266 | } |
Line 241... | Line 267... | ||
241 | 267 | ||
242 | void |
268 | void |
243 | _cairo_boxes_extents (const cairo_boxes_t *boxes, |
269 | _cairo_boxes_extents (const cairo_boxes_t *boxes, |
244 | cairo_rectangle_int_t *extents) |
270 | cairo_box_t *box) |
245 | { |
271 | { |
246 | const struct _cairo_boxes_chunk *chunk; |
272 | const struct _cairo_boxes_chunk *chunk; |
247 | cairo_box_t box; |
273 | cairo_box_t b; |
Line 248... | Line 274... | ||
248 | int i; |
274 | int i; |
249 | 275 | ||
- | 276 | if (boxes->num_boxes == 0) { |
|
- | 277 | box->p1.x = box->p1.y = box->p2.x = box->p2.y = 0; |
|
Line -... | Line 278... | ||
- | 278 | return; |
|
250 | box.p1.y = box.p1.x = INT_MAX; |
279 | } |
251 | box.p2.y = box.p2.x = INT_MIN; |
- | |
252 | 280 | ||
253 | for (chunk = &boxes->chunks; chunk != NULL; chunk = chunk->next) { |
281 | b = boxes->chunks.base[0]; |
254 | const cairo_box_t *b = chunk->base; |
282 | for (chunk = &boxes->chunks; chunk != NULL; chunk = chunk->next) { |
Line 255... | Line 283... | ||
255 | for (i = 0; i < chunk->count; i++) { |
283 | for (i = 0; i < chunk->count; i++) { |
256 | if (b[i].p1.x < box.p1.x) |
284 | if (chunk->base[i].p1.x < b.p1.x) |
Line 257... | Line 285... | ||
257 | box.p1.x = b[i].p1.x; |
285 | b.p1.x = chunk->base[i].p1.x; |
258 | 286 | ||
Line 259... | Line 287... | ||
259 | if (b[i].p1.y < box.p1.y) |
287 | if (chunk->base[i].p1.y < b.p1.y) |
260 | box.p1.y = b[i].p1.y; |
288 | b.p1.y = chunk->base[i].p1.y; |
261 | 289 | ||
262 | if (b[i].p2.x > box.p2.x) |
290 | if (chunk->base[i].p2.x > b.p2.x) |
263 | box.p2.x = b[i].p2.x; |
- | |
264 | 291 | b.p2.x = chunk->base[i].p2.x; |
|
265 | if (b[i].p2.y > box.p2.y) |
292 | |
Line 266... | Line 293... | ||
266 | box.p2.y = b[i].p2.y; |
293 | if (chunk->base[i].p2.y > b.p2.y) |
267 | } |
294 | b.p2.y = chunk->base[i].p2.y; |
268 | } |
295 | } |
Line 281... | Line 308... | ||
281 | } |
308 | } |
Line 282... | Line 309... | ||
282 | 309 | ||
283 | boxes->tail = &boxes->chunks; |
310 | boxes->tail = &boxes->chunks; |
284 | boxes->chunks.next = 0; |
311 | boxes->chunks.next = 0; |
- | 312 | boxes->chunks.count = 0; |
|
- | 313 | boxes->chunks.base = boxes->boxes_embedded; |
|
285 | boxes->chunks.count = 0; |
314 | boxes->chunks.size = ARRAY_LENGTH (boxes->boxes_embedded); |
Line 286... | Line 315... | ||
286 | boxes->num_boxes = 0; |
315 | boxes->num_boxes = 0; |
287 | 316 | ||
Line -... | Line 317... | ||
- | 317 | boxes->is_pixel_aligned = TRUE; |
|
- | 318 | } |
|
- | 319 | ||
- | 320 | cairo_box_t * |
|
- | 321 | _cairo_boxes_to_array (const cairo_boxes_t *boxes, |
|
- | 322 | int *num_boxes, |
|
- | 323 | cairo_bool_t force_allocation) |
|
- | 324 | { |
|
- | 325 | const struct _cairo_boxes_chunk *chunk; |
|
- | 326 | cairo_box_t *box; |
|
- | 327 | int i, j; |
|
- | 328 | ||
- | 329 | *num_boxes = boxes->num_boxes; |
|
- | 330 | if (boxes->chunks.next == NULL && ! force_allocation) |
|
- | 331 | return boxes->chunks.base; |
|
- | 332 | ||
- | 333 | box = _cairo_malloc_ab (boxes->num_boxes, sizeof (cairo_box_t)); |
|
- | 334 | if (box == NULL) { |
|
- | 335 | _cairo_error_throw (CAIRO_STATUS_NO_MEMORY); |
|
- | 336 | return NULL; |
|
- | 337 | } |
|
- | 338 | ||
- | 339 | j = 0; |
|
- | 340 | for (chunk = &boxes->chunks; chunk != NULL; chunk = chunk->next) { |
|
- | 341 | for (i = 0; i < chunk->count; i++) |
|
- | 342 | box[j++] = chunk->base[i]; |
|
- | 343 | } |
|
- | 344 | ||
288 | boxes->is_pixel_aligned = TRUE; |
345 | return box; |
289 | } |
346 | } |
290 | 347 | ||
291 | void |
348 | void |
Line 292... | Line 349... | ||
292 | _cairo_boxes_fini (cairo_boxes_t *boxes) |
349 | _cairo_boxes_fini (cairo_boxes_t *boxes) |
293 | { |
350 | { |
294 | struct _cairo_boxes_chunk *chunk, *next; |
351 | struct _cairo_boxes_chunk *chunk, *next; |
295 | 352 | ||
296 | for (chunk = boxes->chunks.next; chunk != NULL; chunk = next) { |
353 | for (chunk = boxes->chunks.next; chunk != NULL; chunk = next) { |
- | 354 | next = chunk->next; |
|
- | 355 | free (chunk); |
|
- | 356 | } |
|
- | 357 | } |
|
- | 358 | ||
- | 359 | cairo_bool_t |
|
- | 360 | _cairo_boxes_for_each_box (cairo_boxes_t *boxes, |
|
- | 361 | cairo_bool_t (*func) (cairo_box_t *box, void *data), |
|
- | 362 | void *data) |
|
- | 363 | { |
|
- | 364 | struct _cairo_boxes_chunk *chunk; |
|
- | 365 | int i; |
|
- | 366 | ||
- | 367 | for (chunk = &boxes->chunks; chunk != NULL; chunk = chunk->next) { |
|
- | 368 | for (i = 0; i < chunk->count; i++) |
|
- | 369 | if (! func (&chunk->base[i], data)) |
|
- | 370 | return FALSE; |
|
- | 371 | } |
|
- | 372 | ||
- | 373 | return TRUE; |
|
- | 374 | } |
|
- | 375 | ||
- | 376 | struct cairo_box_renderer { |
|
- | 377 | cairo_span_renderer_t base; |
|
- | 378 | cairo_boxes_t *boxes; |
|
- | 379 | }; |
|
- | 380 | ||
- | 381 | static cairo_status_t |
|
- | 382 | span_to_boxes (void *abstract_renderer, int y, int h, |
|
- | 383 | const cairo_half_open_span_t *spans, unsigned num_spans) |
|
- | 384 | { |
|
- | 385 | struct cairo_box_renderer *r = abstract_renderer; |
|
- | 386 | cairo_status_t status = CAIRO_STATUS_SUCCESS; |
|
- | 387 | cairo_box_t box; |
|
- | 388 | ||
- | 389 | if (num_spans == 0) |
|
- | 390 | return CAIRO_STATUS_SUCCESS; |
|
- | 391 | ||
- | 392 | box.p1.y = _cairo_fixed_from_int (y); |
|
- | 393 | box.p2.y = _cairo_fixed_from_int (y + h); |
|
- | 394 | do { |
|
- | 395 | if (spans[0].coverage) { |
|
- | 396 | box.p1.x = _cairo_fixed_from_int(spans[0].x); |
|
- | 397 | box.p2.x = _cairo_fixed_from_int(spans[1].x); |
|
- | 398 | status = _cairo_boxes_add (r->boxes, CAIRO_ANTIALIAS_DEFAULT, &box); |
|
- | 399 | } |
|
- | 400 | spans++; |
|
- | 401 | } while (--num_spans > 1 && status == CAIRO_STATUS_SUCCESS); |
|
- | 402 | ||
- | 403 | return status; |
|
- | 404 | } |
|
- | 405 | ||
- | 406 | cairo_status_t |
|
- | 407 | _cairo_rasterise_polygon_to_boxes (cairo_polygon_t *polygon, |
|
- | 408 | cairo_fill_rule_t fill_rule, |
|
- | 409 | cairo_boxes_t *boxes) |
|
- | 410 | { |
|
- | 411 | struct cairo_box_renderer renderer; |
|
- | 412 | cairo_scan_converter_t *converter; |
|
- | 413 | cairo_int_status_t status; |
|
- | 414 | cairo_rectangle_int_t r; |
|
- | 415 | ||
- | 416 | TRACE ((stderr, "%s: fill_rule=%d\n", __FUNCTION__, fill_rule)); |
|
- | 417 | ||
- | 418 | _cairo_box_round_to_rectangle (&polygon->extents, &r); |
|
- | 419 | converter = _cairo_mono_scan_converter_create (r.x, r.y, |
|
- | 420 | r.x + r.width, |
|
- | 421 | r.y + r.height, |
|
- | 422 | fill_rule); |
|
- | 423 | status = _cairo_mono_scan_converter_add_polygon (converter, polygon); |
|
- | 424 | if (unlikely (status)) |
|
- | 425 | goto cleanup_converter; |
|
- | 426 | ||
- | 427 | renderer.boxes = boxes; |
|
- | 428 | renderer.base.render_rows = span_to_boxes; |
|
- | 429 | ||
- | 430 | status = converter->generate (converter, &renderer.base); |
|
- | 431 | cleanup_converter: |
|
- | 432 | converter->destroy (converter); |
|
- | 433 | return status; |
|
- | 434 | } |
|
- | 435 | ||
- | 436 | void |
|
- | 437 | _cairo_debug_print_boxes (FILE *stream, const cairo_boxes_t *boxes) |
|
- | 438 | { |
|
- | 439 | const struct _cairo_boxes_chunk *chunk; |
|
- | 440 | cairo_box_t extents; |
|
- | 441 | int i; |
|
- | 442 | ||
- | 443 | _cairo_boxes_extents (boxes, &extents); |
|
- | 444 | fprintf (stream, "boxes x %d: (%f, %f) x (%f, %f)\n", |
|
- | 445 | boxes->num_boxes, |
|
- | 446 | _cairo_fixed_to_double (extents.p1.x), |
|
- | 447 | _cairo_fixed_to_double (extents.p1.y), |
|
- | 448 | _cairo_fixed_to_double (extents.p2.x), |
|
- | 449 | _cairo_fixed_to_double (extents.p2.y)); |
|
- | 450 | ||
- | 451 | for (chunk = &boxes->chunks; chunk != NULL; chunk = chunk->next) { |
|
- | 452 | for (i = 0; i < chunk->count; i++) { |
|
- | 453 | fprintf (stderr, " box[%d]: (%f, %f), (%f, %f)\n", i, |
|
- | 454 | _cairo_fixed_to_double (chunk->base[i].p1.x), |
|
- | 455 | _cairo_fixed_to_double (chunk->base[i].p1.y), |
|
- | 456 | _cairo_fixed_to_double (chunk->base[i].p2.x), |