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 35... | Line 35... | ||
35 | * Carl D. Worth |
35 | * Carl D. Worth |
36 | */ |
36 | */ |
Line 37... | Line 37... | ||
37 | 37 | ||
Line -... | Line 38... | ||
- | 38 | #include "cairoint.h" |
|
38 | #include "cairoint.h" |
39 | |
39 | 40 | #include "cairo-clip-inline.h" |
|
- | 41 | #include "cairo-clip-private.h" |
|
40 | #include "cairo-clip-private.h" |
42 | #include "cairo-error-private.h" |
- | 43 | #include "cairo-list-inline.h" |
|
- | 44 | #include "cairo-gstate-private.h" |
|
Line 41... | Line 45... | ||
41 | #include "cairo-error-private.h" |
45 | #include "cairo-pattern-private.h" |
42 | #include "cairo-gstate-private.h" |
46 | #include "cairo-traps-private.h" |
43 | 47 | ||
44 | #if _XOPEN_SOURCE >= 600 || defined (_ISOC99_SOURCE) |
48 | #if _XOPEN_SOURCE >= 600 || defined (_ISOC99_SOURCE) |
Line 57... | Line 61... | ||
57 | _cairo_gstate_ensure_scaled_font (cairo_gstate_t *gstate); |
61 | _cairo_gstate_ensure_scaled_font (cairo_gstate_t *gstate); |
Line 58... | Line 62... | ||
58 | 62 | ||
59 | static void |
63 | static void |
Line 60... | Line 64... | ||
60 | _cairo_gstate_unset_scaled_font (cairo_gstate_t *gstate); |
64 | _cairo_gstate_unset_scaled_font (cairo_gstate_t *gstate); |
61 | 65 | ||
62 | static cairo_status_t |
66 | static void |
63 | _cairo_gstate_transform_glyphs_to_backend (cairo_gstate_t *gstate, |
67 | _cairo_gstate_transform_glyphs_to_backend (cairo_gstate_t *gstate, |
64 | const cairo_glyph_t *glyphs, |
68 | const cairo_glyph_t *glyphs, |
65 | int num_glyphs, |
69 | int num_glyphs, |
Line 84... | Line 88... | ||
84 | 88 | ||
85 | cairo_status_t |
89 | cairo_status_t |
86 | _cairo_gstate_init (cairo_gstate_t *gstate, |
90 | _cairo_gstate_init (cairo_gstate_t *gstate, |
87 | cairo_surface_t *target) |
91 | cairo_surface_t *target) |
88 | { |
- | |
89 | cairo_status_t status; |
- | |
90 | 92 | { |
|
Line 91... | Line 93... | ||
91 | VG (VALGRIND_MAKE_MEM_UNDEFINED (gstate, sizeof (cairo_gstate_t))); |
93 | VG (VALGRIND_MAKE_MEM_UNDEFINED (gstate, sizeof (cairo_gstate_t))); |
Line 92... | Line 94... | ||
92 | 94 | ||
- | 95 | gstate->next = NULL; |
|
Line 93... | Line 96... | ||
93 | gstate->next = NULL; |
96 | |
94 | 97 | gstate->op = CAIRO_GSTATE_OPERATOR_DEFAULT; |
|
Line 95... | Line 98... | ||
95 | gstate->op = CAIRO_GSTATE_OPERATOR_DEFAULT; |
98 | gstate->opacity = 1.; |
Line 109... | Line 112... | ||
109 | CAIRO_GSTATE_DEFAULT_FONT_SIZE, |
112 | CAIRO_GSTATE_DEFAULT_FONT_SIZE, |
110 | CAIRO_GSTATE_DEFAULT_FONT_SIZE); |
113 | CAIRO_GSTATE_DEFAULT_FONT_SIZE); |
Line 111... | Line 114... | ||
111 | 114 | ||
Line 112... | Line 115... | ||
112 | _cairo_font_options_init_default (&gstate->font_options); |
115 | _cairo_font_options_init_default (&gstate->font_options); |
Line 113... | Line 116... | ||
113 | 116 | ||
114 | _cairo_clip_init (&gstate->clip); |
117 | gstate->clip = NULL; |
115 | 118 | ||
Line 129... | Line 132... | ||
129 | gstate->source = (cairo_pattern_t *) &_cairo_pattern_black.base; |
132 | gstate->source = (cairo_pattern_t *) &_cairo_pattern_black.base; |
Line 130... | Line 133... | ||
130 | 133 | ||
131 | /* Now that the gstate is fully initialized and ready for the eventual |
134 | /* Now that the gstate is fully initialized and ready for the eventual |
132 | * _cairo_gstate_fini(), we can check for errors (and not worry about |
135 | * _cairo_gstate_fini(), we can check for errors (and not worry about |
133 | * the resource deallocation). */ |
136 | * the resource deallocation). */ |
134 | status = target->status; |
- | |
135 | if (unlikely (status)) |
- | |
136 | return status; |
- | |
137 | - | ||
138 | status = gstate->source->status; |
- | |
139 | if (unlikely (status)) |
- | |
140 | return status; |
- | |
141 | - | ||
142 | return CAIRO_STATUS_SUCCESS; |
137 | return target->status; |
Line 143... | Line 138... | ||
143 | } |
138 | } |
144 | 139 | ||
145 | /** |
140 | /** |
Line 155... | Line 150... | ||
155 | cairo_status_t status; |
150 | cairo_status_t status; |
Line 156... | Line 151... | ||
156 | 151 | ||
Line 157... | Line 152... | ||
157 | VG (VALGRIND_MAKE_MEM_UNDEFINED (gstate, sizeof (cairo_gstate_t))); |
152 | VG (VALGRIND_MAKE_MEM_UNDEFINED (gstate, sizeof (cairo_gstate_t))); |
- | 153 | ||
Line 158... | Line 154... | ||
158 | 154 | gstate->op = other->op; |
|
159 | gstate->op = other->op; |
155 | gstate->opacity = other->opacity; |
Line 160... | Line 156... | ||
160 | 156 | ||
Line 174... | Line 170... | ||
174 | 170 | ||
Line 175... | Line 171... | ||
175 | gstate->font_matrix = other->font_matrix; |
171 | gstate->font_matrix = other->font_matrix; |
Line 176... | Line 172... | ||
176 | 172 | ||
Line 177... | Line 173... | ||
177 | _cairo_font_options_init_copy (&gstate->font_options , &other->font_options); |
173 | _cairo_font_options_init_copy (&gstate->font_options , &other->font_options); |
178 | 174 | ||
179 | _cairo_clip_init_copy (&gstate->clip, &other->clip); |
175 | gstate->clip = _cairo_clip_copy (other->clip); |
180 | 176 | ||
Line 211... | Line 207... | ||
211 | gstate->previous_scaled_font = NULL; |
207 | gstate->previous_scaled_font = NULL; |
Line 212... | Line 208... | ||
212 | 208 | ||
213 | cairo_scaled_font_destroy (gstate->scaled_font); |
209 | cairo_scaled_font_destroy (gstate->scaled_font); |
Line 214... | Line 210... | ||
214 | gstate->scaled_font = NULL; |
210 | gstate->scaled_font = NULL; |
Line 215... | Line 211... | ||
215 | 211 | ||
Line 216... | Line 212... | ||
216 | _cairo_clip_reset (&gstate->clip); |
212 | _cairo_clip_destroy (gstate->clip); |
217 | 213 | ||
Line 301... | Line 297... | ||
301 | * @child: the new child target |
297 | * @child: the new child target |
302 | * |
298 | * |
303 | * Redirect @gstate rendering to a "child" target. The original |
299 | * Redirect @gstate rendering to a "child" target. The original |
304 | * "parent" target with which the gstate was created will not be |
300 | * "parent" target with which the gstate was created will not be |
305 | * affected. See _cairo_gstate_get_target(). |
301 | * affected. See _cairo_gstate_get_target(). |
306 | * |
- | |
307 | * Unless the redirected target has the same device offsets as the |
- | |
308 | * original #cairo_t target, the clip will be INVALID after this call, |
- | |
309 | * and the caller should either recreate or reset the clip. |
- | |
310 | **/ |
302 | **/ |
311 | cairo_status_t |
303 | cairo_status_t |
312 | _cairo_gstate_redirect_target (cairo_gstate_t *gstate, cairo_surface_t *child) |
304 | _cairo_gstate_redirect_target (cairo_gstate_t *gstate, cairo_surface_t *child) |
313 | { |
305 | { |
314 | cairo_matrix_t matrix; |
- | |
315 | - | ||
316 | /* If this gstate is already redirected, this is an error; we need a |
306 | /* If this gstate is already redirected, this is an error; we need a |
317 | * new gstate to be able to redirect */ |
307 | * new gstate to be able to redirect */ |
318 | assert (gstate->parent_target == NULL); |
308 | assert (gstate->parent_target == NULL); |
Line 319... | Line 309... | ||
319 | 309 | ||
320 | /* Set up our new parent_target based on our current target; |
310 | /* Set up our new parent_target based on our current target; |
321 | * gstate->parent_target will take the ref that is held by gstate->target |
311 | * gstate->parent_target will take the ref that is held by gstate->target |
322 | */ |
- | |
323 | cairo_surface_destroy (gstate->parent_target); |
312 | */ |
Line 324... | Line 313... | ||
324 | gstate->parent_target = gstate->target; |
313 | gstate->parent_target = gstate->target; |
325 | 314 | ||
326 | /* Now set up our new target; we overwrite gstate->target directly, |
315 | /* Now set up our new target; we overwrite gstate->target directly, |
Line 330... | Line 319... | ||
330 | cairo_list_move (&gstate->device_transform_observer.link, |
319 | cairo_list_move (&gstate->device_transform_observer.link, |
331 | &gstate->target->device_transform_observers); |
320 | &gstate->target->device_transform_observers); |
Line 332... | Line 321... | ||
332 | 321 | ||
333 | /* The clip is in surface backend coordinates for the previous target; |
322 | /* The clip is in surface backend coordinates for the previous target; |
334 | * translate it into the child's backend coordinates. */ |
323 | * translate it into the child's backend coordinates. */ |
- | 324 | _cairo_clip_destroy (gstate->clip); |
|
335 | cairo_matrix_init_translate (&matrix, |
325 | gstate->clip = _cairo_clip_copy_with_translation (gstate->next->clip, |
336 | child->device_transform.x0 - gstate->parent_target->device_transform.x0, |
326 | child->device_transform.x0 - gstate->parent_target->device_transform.x0, |
- | 327 | child->device_transform.y0 - gstate->parent_target->device_transform.y0); |
|
337 | child->device_transform.y0 - gstate->parent_target->device_transform.y0); |
328 | |
338 | _cairo_clip_reset (&gstate->clip); |
- | |
339 | return _cairo_clip_init_copy_transformed (&gstate->clip, |
- | |
340 | &gstate->next->clip, |
- | |
341 | &matrix); |
329 | return CAIRO_STATUS_SUCCESS; |
Line 342... | Line 330... | ||
342 | } |
330 | } |
343 | 331 | ||
344 | /** |
332 | /** |
345 | * _cairo_gstate_is_redirected |
333 | * _cairo_gstate_is_group: |
346 | * @gstate: a #cairo_gstate_t |
334 | * @gstate: a #cairo_gstate_t |
- | 335 | * |
|
347 | * |
336 | * Check if _cairo_gstate_redirect_target has been called on the head |
348 | * This space left intentionally blank. |
337 | * of the stack. |
349 | * |
338 | * |
350 | * Return value: %TRUE if the gstate is redirected to a target |
339 | * Return value: %TRUE if @gstate is redirected to a target different |
351 | * different than the original, %FALSE otherwise. |
340 | * than the previous state in the stack, %FALSE otherwise. |
352 | **/ |
341 | **/ |
353 | cairo_bool_t |
342 | cairo_bool_t |
354 | _cairo_gstate_is_redirected (cairo_gstate_t *gstate) |
343 | _cairo_gstate_is_group (cairo_gstate_t *gstate) |
355 | { |
344 | { |
Line 356... | Line 345... | ||
356 | return (gstate->target != gstate->original_target); |
345 | return gstate->parent_target != NULL; |
357 | } |
346 | } |
358 | 347 | ||
Line 370... | Line 359... | ||
370 | { |
359 | { |
371 | return gstate->target; |
360 | return gstate->target; |
372 | } |
361 | } |
Line 373... | Line 362... | ||
373 | 362 | ||
374 | /** |
- | |
375 | * _cairo_gstate_get_parent_target: |
- | |
376 | * @gstate: a #cairo_gstate_t |
- | |
377 | * |
- | |
378 | * Return the parent surface of the current drawing target surface; |
- | |
379 | * if this particular gstate isn't a redirect gstate, this will return %NULL. |
- | |
380 | **/ |
- | |
381 | cairo_surface_t * |
- | |
382 | _cairo_gstate_get_parent_target (cairo_gstate_t *gstate) |
- | |
383 | { |
- | |
384 | return gstate->parent_target; |
- | |
385 | } |
- | |
386 | - | ||
387 | /** |
363 | /** |
388 | * _cairo_gstate_get_original_target: |
364 | * _cairo_gstate_get_original_target: |
389 | * @gstate: a #cairo_gstate_t |
365 | * @gstate: a #cairo_gstate_t |
390 | * |
366 | * |
391 | * Return the original target with which @gstate was created. This |
367 | * Return the original target with which @gstate was created. This |
Line 406... | Line 382... | ||
406 | * @gstate: a #cairo_gstate_t |
382 | * @gstate: a #cairo_gstate_t |
407 | * |
383 | * |
408 | * This space left intentionally blank. |
384 | * This space left intentionally blank. |
409 | * |
385 | * |
410 | * Return value: a pointer to the gstate's #cairo_clip_t structure. |
386 | * Return value: a pointer to the gstate's #cairo_clip_t structure. |
411 | */ |
387 | **/ |
412 | cairo_clip_t * |
388 | cairo_clip_t * |
413 | _cairo_gstate_get_clip (cairo_gstate_t *gstate) |
389 | _cairo_gstate_get_clip (cairo_gstate_t *gstate) |
414 | { |
390 | { |
415 | return &gstate->clip; |
391 | return gstate->clip; |
416 | } |
392 | } |
Line 417... | Line 393... | ||
417 | 393 | ||
418 | cairo_status_t |
394 | cairo_status_t |
419 | _cairo_gstate_set_source (cairo_gstate_t *gstate, |
395 | _cairo_gstate_set_source (cairo_gstate_t *gstate, |
Line 454... | Line 430... | ||
454 | { |
430 | { |
455 | return gstate->op; |
431 | return gstate->op; |
456 | } |
432 | } |
Line 457... | Line 433... | ||
457 | 433 | ||
- | 434 | cairo_status_t |
|
- | 435 | _cairo_gstate_set_opacity (cairo_gstate_t *gstate, double op) |
|
- | 436 | { |
|
- | 437 | gstate->opacity = op; |
|
- | 438 | ||
- | 439 | return CAIRO_STATUS_SUCCESS; |
|
- | 440 | } |
|
- | 441 | ||
- | 442 | double |
|
- | 443 | _cairo_gstate_get_opacity (cairo_gstate_t *gstate) |
|
- | 444 | { |
|
- | 445 | return gstate->opacity; |
|
- | 446 | } |
|
- | 447 | ||
458 | cairo_status_t |
448 | cairo_status_t |
459 | _cairo_gstate_set_tolerance (cairo_gstate_t *gstate, double tolerance) |
449 | _cairo_gstate_set_tolerance (cairo_gstate_t *gstate, double tolerance) |
460 | { |
450 | { |
Line 461... | Line 451... | ||
461 | gstate->tolerance = tolerance; |
451 | gstate->tolerance = tolerance; |
Line 526... | Line 516... | ||
526 | } |
516 | } |
Line 527... | Line 517... | ||
527 | 517 | ||
528 | cairo_status_t |
518 | cairo_status_t |
529 | _cairo_gstate_set_dash (cairo_gstate_t *gstate, const double *dash, int num_dashes, double offset) |
519 | _cairo_gstate_set_dash (cairo_gstate_t *gstate, const double *dash, int num_dashes, double offset) |
530 | { |
520 | { |
531 | unsigned int i; |
521 | double dash_total, on_total, off_total; |
Line 532... | Line -... | ||
532 | double dash_total; |
- | |
533 | 522 | int i, j; |
|
Line 534... | Line 523... | ||
534 | if (gstate->stroke_style.dash) |
523 | |
Line 535... | Line 524... | ||
535 | free (gstate->stroke_style.dash); |
524 | free (gstate->stroke_style.dash); |
Line 546... | Line 535... | ||
546 | if (unlikely (gstate->stroke_style.dash == NULL)) { |
535 | if (unlikely (gstate->stroke_style.dash == NULL)) { |
547 | gstate->stroke_style.num_dashes = 0; |
536 | gstate->stroke_style.num_dashes = 0; |
548 | return _cairo_error (CAIRO_STATUS_NO_MEMORY); |
537 | return _cairo_error (CAIRO_STATUS_NO_MEMORY); |
549 | } |
538 | } |
Line 550... | Line 539... | ||
550 | 539 | ||
- | 540 | on_total = off_total = dash_total = 0.0; |
|
- | 541 | for (i = j = 0; i < num_dashes; i++) { |
|
- | 542 | if (dash[i] < 0) |
|
Line 551... | Line -... | ||
551 | memcpy (gstate->stroke_style.dash, dash, gstate->stroke_style.num_dashes * sizeof (double)); |
- | |
552 | 543 | return _cairo_error (CAIRO_STATUS_INVALID_DASH); |
|
553 | dash_total = 0.0; |
544 | |
554 | for (i = 0; i < gstate->stroke_style.num_dashes; i++) { |
545 | if (dash[i] == 0 && i > 0 && i < num_dashes - 1) { |
Line -... | Line 546... | ||
- | 546 | if (dash[++i] < 0) |
|
- | 547 | return _cairo_error (CAIRO_STATUS_INVALID_DASH); |
|
- | 548 | ||
555 | if (gstate->stroke_style.dash[i] < 0) |
549 | gstate->stroke_style.dash[j-1] += dash[i]; |
- | 550 | gstate->stroke_style.num_dashes -= 2; |
|
- | 551 | } else |
|
- | 552 | gstate->stroke_style.dash[j++] = dash[i]; |
|
- | 553 | ||
- | 554 | if (dash[i]) { |
|
- | 555 | dash_total += dash[i]; |
|
- | 556 | if ((i & 1) == 0) |
|
- | 557 | on_total += dash[i]; |
|
556 | return _cairo_error (CAIRO_STATUS_INVALID_DASH); |
558 | else |
Line 557... | Line 559... | ||
557 | 559 | off_total += dash[i]; |
|
558 | dash_total += gstate->stroke_style.dash[i]; |
560 | } |
Line 559... | Line 561... | ||
559 | } |
561 | } |
560 | 562 | ||
561 | if (dash_total == 0.0) |
563 | if (dash_total == 0.0) |
562 | return _cairo_error (CAIRO_STATUS_INVALID_DASH); |
564 | return _cairo_error (CAIRO_STATUS_INVALID_DASH); |
- | 565 | ||
- | 566 | /* An odd dash value indicate symmetric repeating, so the total |
|
- | 567 | * is twice as long. */ |
|
- | 568 | if (gstate->stroke_style.num_dashes & 1) { |
|
- | 569 | dash_total *= 2; |
|
- | 570 | on_total += off_total; |
|
- | 571 | } |
|
- | 572 | ||
- | 573 | if (dash_total - on_total < CAIRO_FIXED_ERROR_DOUBLE) { |
|
- | 574 | /* Degenerate dash -> solid line */ |
|
- | 575 | free (gstate->stroke_style.dash); |
|
Line 563... | Line 576... | ||
563 | 576 | gstate->stroke_style.dash = NULL; |
|
564 | /* An odd dash value indicate symmetric repeating, so the total |
577 | gstate->stroke_style.num_dashes = 0; |
565 | * is twice as long. */ |
578 | gstate->stroke_style.dash_offset = 0.0; |
566 | if (gstate->stroke_style.num_dashes & 1) |
579 | return CAIRO_STATUS_SUCCESS; |
Line 799... | Line 812... | ||
799 | cairo_matrix_transform_point (&gstate->ctm, x, y); |
812 | cairo_matrix_transform_point (&gstate->ctm, x, y); |
800 | cairo_matrix_transform_point (&gstate->target->device_transform, x, y); |
813 | cairo_matrix_transform_point (&gstate->target->device_transform, x, y); |
801 | } |
814 | } |
Line 802... | Line 815... | ||
802 | 815 | ||
- | 816 | void |
|
- | 817 | _do_cairo_gstate_user_to_backend_distance (cairo_gstate_t *gstate, double *x, double *y) |
|
- | 818 | { |
|
- | 819 | cairo_matrix_transform_distance (&gstate->ctm, x, y); |
|
- | 820 | cairo_matrix_transform_distance (&gstate->target->device_transform, x, y); |
|
- | 821 | } |
|
- | 822 | ||
803 | void |
823 | void |
804 | _do_cairo_gstate_backend_to_user (cairo_gstate_t *gstate, double *x, double *y) |
824 | _do_cairo_gstate_backend_to_user (cairo_gstate_t *gstate, double *x, double *y) |
805 | { |
825 | { |
806 | cairo_matrix_transform_point (&gstate->target->device_transform_inverse, x, y); |
826 | cairo_matrix_transform_point (&gstate->target->device_transform_inverse, x, y); |
807 | cairo_matrix_transform_point (&gstate->ctm_inverse, x, y); |
827 | cairo_matrix_transform_point (&gstate->ctm_inverse, x, y); |
Line 808... | Line 828... | ||
808 | } |
828 | } |
- | 829 | ||
- | 830 | void |
|
- | 831 | _do_cairo_gstate_backend_to_user_distance (cairo_gstate_t *gstate, double *x, double *y) |
|
- | 832 | { |
|
- | 833 | cairo_matrix_transform_distance (&gstate->target->device_transform_inverse, x, y); |
|
- | 834 | cairo_matrix_transform_distance (&gstate->ctm_inverse, x, y); |
|
- | 835 | } |
|
809 | 836 | ||
810 | void |
837 | void |
811 | _cairo_gstate_backend_to_user_rectangle (cairo_gstate_t *gstate, |
838 | _cairo_gstate_backend_to_user_rectangle (cairo_gstate_t *gstate, |
812 | double *x1, double *y1, |
839 | double *x1, double *y1, |
813 | double *x2, double *y2, |
840 | double *x2, double *y2, |
814 | cairo_bool_t *is_tight) |
841 | cairo_bool_t *is_tight) |
Line -... | Line 842... | ||
- | 842 | { |
|
- | 843 | cairo_matrix_t matrix_inverse; |
|
- | 844 | ||
815 | { |
845 | if (! _cairo_matrix_is_identity (&gstate->target->device_transform_inverse) || |
816 | cairo_matrix_t matrix_inverse; |
846 | ! _cairo_matrix_is_identity (&gstate->ctm_inverse)) |
817 | 847 | { |
|
818 | cairo_matrix_multiply (&matrix_inverse, |
848 | cairo_matrix_multiply (&matrix_inverse, |
819 | &gstate->target->device_transform_inverse, |
849 | &gstate->target->device_transform_inverse, |
820 | &gstate->ctm_inverse); |
850 | &gstate->ctm_inverse); |
Line -... | Line 851... | ||
- | 851 | _cairo_matrix_transform_bounding_box (&matrix_inverse, |
|
- | 852 | x1, y1, x2, y2, is_tight); |
|
- | 853 | } |
|
- | 854 | ||
- | 855 | else |
|
- | 856 | { |
|
- | 857 | if (is_tight) |
|
821 | _cairo_matrix_transform_bounding_box (&matrix_inverse, |
858 | *is_tight = TRUE; |
822 | x1, y1, x2, y2, is_tight); |
859 | } |
823 | } |
860 | } |
824 | 861 | ||
825 | /* XXX: NYI |
862 | /* XXX: NYI |
Line 946... | Line 983... | ||
946 | _cairo_gstate_copy_transformed_pattern (gstate, pattern, |
983 | _cairo_gstate_copy_transformed_pattern (gstate, pattern, |
947 | mask, |
984 | mask, |
948 | &gstate->ctm_inverse); |
985 | &gstate->ctm_inverse); |
949 | } |
986 | } |
Line 950... | Line -... | ||
950 | - | ||
951 | /* We need to take a copy of the clip so that the lower layers may modify it |
- | |
952 | * by, perhaps, intersecting it with the operation extents and other paths. |
- | |
953 | */ |
- | |
954 | #define _gstate_get_clip(G, C) _cairo_clip_init_copy ((C), &(G)->clip) |
- | |
955 | - | ||
956 | static cairo_bool_t |
- | |
957 | _clipped (cairo_gstate_t *gstate) |
- | |
958 | { |
- | |
959 | cairo_rectangle_int_t extents; |
- | |
960 | - | ||
961 | if (gstate->clip.all_clipped) |
- | |
962 | return TRUE; |
- | |
963 | - | ||
964 | /* XXX consider applying a surface clip? */ |
- | |
965 | - | ||
966 | if (gstate->clip.path == NULL) |
- | |
967 | return FALSE; |
- | |
968 | - | ||
969 | if (_cairo_surface_get_extents (gstate->target, &extents)) { |
- | |
970 | if (extents.width == 0 || extents.height == 0) |
- | |
971 | return TRUE; |
- | |
972 | - | ||
973 | if (! _cairo_rectangle_intersect (&extents, |
- | |
974 | &gstate->clip.path->extents)) |
- | |
975 | { |
- | |
976 | return TRUE; |
- | |
977 | } |
- | |
978 | } |
- | |
979 | - | ||
980 | /* perform a simple query to exclude trivial all-clipped cases */ |
- | |
981 | return _cairo_clip_get_region (&gstate->clip, NULL) == CAIRO_INT_STATUS_NOTHING_TO_DO; |
- | |
982 | } |
- | |
983 | 987 | ||
984 | static cairo_operator_t |
988 | static cairo_operator_t |
985 | _reduce_op (cairo_gstate_t *gstate) |
989 | _reduce_op (cairo_gstate_t *gstate) |
986 | { |
990 | { |
987 | cairo_operator_t op; |
991 | cairo_operator_t op; |
Line 1018... | Line 1022... | ||
1018 | } |
1022 | } |
Line 1019... | Line 1023... | ||
1019 | 1023 | ||
1020 | return op; |
1024 | return op; |
Line -... | Line 1025... | ||
- | 1025 | } |
|
- | 1026 | ||
- | 1027 | static cairo_status_t |
|
- | 1028 | _cairo_gstate_get_pattern_status (const cairo_pattern_t *pattern) |
|
- | 1029 | { |
|
- | 1030 | if (unlikely (pattern->type == CAIRO_PATTERN_TYPE_MESH && |
|
- | 1031 | ((const cairo_mesh_pattern_t *) pattern)->current_patch)) |
|
- | 1032 | { |
|
- | 1033 | /* If current patch != NULL, the pattern is under construction |
|
- | 1034 | * and cannot be used as a source */ |
|
- | 1035 | return CAIRO_STATUS_INVALID_MESH_CONSTRUCTION; |
|
- | 1036 | } |
|
- | 1037 | ||
- | 1038 | return pattern->status; |
|
1021 | } |
1039 | } |
1022 | 1040 | ||
1023 | cairo_status_t |
1041 | cairo_status_t |
1024 | _cairo_gstate_paint (cairo_gstate_t *gstate) |
1042 | _cairo_gstate_paint (cairo_gstate_t *gstate) |
1025 | { |
1043 | { |
1026 | cairo_pattern_union_t source_pattern; |
- | |
1027 | const cairo_pattern_t *pattern; |
1044 | cairo_pattern_union_t source_pattern; |
1028 | cairo_clip_t clip; |
1045 | const cairo_pattern_t *pattern; |
Line -... | Line 1046... | ||
- | 1046 | cairo_status_t status; |
|
1029 | cairo_status_t status; |
1047 | cairo_operator_t op; |
1030 | cairo_operator_t op; |
1048 | |
Line 1031... | Line 1049... | ||
1031 | 1049 | status = _cairo_gstate_get_pattern_status (gstate->source); |
|
1032 | if (unlikely (gstate->source->status)) |
1050 | if (unlikely (status)) |
Line 1033... | Line 1051... | ||
1033 | return gstate->source->status; |
1051 | return status; |
1034 | 1052 | ||
Line 1035... | Line 1053... | ||
1035 | if (gstate->op == CAIRO_OPERATOR_DEST) |
1053 | if (gstate->op == CAIRO_OPERATOR_DEST) |
1036 | return CAIRO_STATUS_SUCCESS; |
1054 | return CAIRO_STATUS_SUCCESS; |
1037 | 1055 | ||
1038 | if (_clipped (gstate)) |
1056 | if (_cairo_clip_is_all_clipped (gstate->clip)) |
1039 | return CAIRO_STATUS_SUCCESS; |
1057 | return CAIRO_STATUS_SUCCESS; |
1040 | 1058 | ||
1041 | op = _reduce_op (gstate); |
1059 | op = _reduce_op (gstate); |
Line 1042... | Line 1060... | ||
1042 | if (op == CAIRO_OPERATOR_CLEAR) { |
1060 | if (op == CAIRO_OPERATOR_CLEAR) { |
1043 | pattern = &_cairo_pattern_clear.base; |
1061 | pattern = &_cairo_pattern_clear.base; |
1044 | } else { |
1062 | } else { |
1045 | _cairo_gstate_copy_transformed_source (gstate, &source_pattern.base); |
- | |
1046 | pattern = &source_pattern.base; |
- | |
1047 | } |
- | |
1048 | 1063 | _cairo_gstate_copy_transformed_source (gstate, &source_pattern.base); |
|
Line 1049... | Line 1064... | ||
1049 | status = _cairo_surface_paint (gstate->target, |
1064 | pattern = &source_pattern.base; |
1050 | op, pattern, |
1065 | } |
1051 | _gstate_get_clip (gstate, &clip)); |
1066 | |
1052 | _cairo_clip_fini (&clip); |
1067 | return _cairo_surface_paint (gstate->target, |
1053 | 1068 | op, pattern, |
|
1054 | return status; |
1069 | gstate->clip); |
1055 | } |
1070 | } |
1056 | - | ||
1057 | cairo_status_t |
1071 | |
Line -... | Line 1072... | ||
- | 1072 | cairo_status_t |
|
1058 | _cairo_gstate_mask (cairo_gstate_t *gstate, |
1073 | _cairo_gstate_mask (cairo_gstate_t *gstate, |
1059 | cairo_pattern_t *mask) |
1074 | cairo_pattern_t *mask) |
Line -... | Line 1075... | ||
- | 1075 | { |
|
1060 | { |
1076 | cairo_pattern_union_t source_pattern, mask_pattern; |
1061 | cairo_pattern_union_t source_pattern, mask_pattern; |
1077 | const cairo_pattern_t *source; |
Line 1062... | Line 1078... | ||
1062 | const cairo_pattern_t *source; |
1078 | cairo_operator_t op; |
1063 | cairo_operator_t op; |
1079 | cairo_status_t status; |
Line 1064... | Line 1080... | ||
1064 | cairo_clip_t clip; |
1080 | |
1065 | cairo_status_t status; |
1081 | status = _cairo_gstate_get_pattern_status (mask); |
Line -... | Line 1082... | ||
- | 1082 | if (unlikely (status)) |
|
- | 1083 | return status; |
|
1066 | 1084 | ||
1067 | if (unlikely (mask->status)) |
1085 | status = _cairo_gstate_get_pattern_status (gstate->source); |
Line 1068... | Line 1086... | ||
1068 | return mask->status; |
1086 | if (unlikely (status)) |
1069 | 1087 | return status; |
|
Line 1093... | Line 1111... | ||
1093 | source = &source_pattern.base; |
1111 | source = &source_pattern.base; |
1094 | } |
1112 | } |
1095 | _cairo_gstate_copy_transformed_mask (gstate, &mask_pattern.base, mask); |
1113 | _cairo_gstate_copy_transformed_mask (gstate, &mask_pattern.base, mask); |
Line 1096... | Line 1114... | ||
1096 | 1114 | ||
1097 | if (source->type == CAIRO_PATTERN_TYPE_SOLID && |
1115 | if (source->type == CAIRO_PATTERN_TYPE_SOLID && |
1098 | mask_pattern.type == CAIRO_PATTERN_TYPE_SOLID && |
1116 | mask_pattern.base.type == CAIRO_PATTERN_TYPE_SOLID && |
1099 | _cairo_operator_bounded_by_source (op)) |
1117 | _cairo_operator_bounded_by_source (op)) |
1100 | { |
1118 | { |
1101 | const cairo_solid_pattern_t *solid = (cairo_solid_pattern_t *) source; |
1119 | const cairo_solid_pattern_t *solid = (cairo_solid_pattern_t *) source; |
Line 1115... | Line 1133... | ||
1115 | 1133 | ||
Line 1116... | Line 1134... | ||
1116 | _cairo_pattern_init_solid (&source_pattern.solid, &combined); |
1134 | _cairo_pattern_init_solid (&source_pattern.solid, &combined); |
1117 | 1135 | ||
1118 | status = _cairo_surface_paint (gstate->target, op, |
1136 | status = _cairo_surface_paint (gstate->target, op, |
1119 | &source_pattern.base, |
1137 | &source_pattern.base, |
1120 | _gstate_get_clip (gstate, &clip)); |
1138 | gstate->clip); |
1121 | } |
1139 | } |
1122 | else |
1140 | else |
1123 | { |
1141 | { |
1124 | status = _cairo_surface_mask (gstate->target, op, |
1142 | status = _cairo_surface_mask (gstate->target, op, |
1125 | source, |
1143 | source, |
1126 | &mask_pattern.base, |
1144 | &mask_pattern.base, |
1127 | _gstate_get_clip (gstate, &clip)); |
- | |
Line 1128... | Line 1145... | ||
1128 | } |
1145 | gstate->clip); |
1129 | _cairo_clip_fini (&clip); |
1146 | } |
Line 1130... | Line 1147... | ||
1130 | 1147 | ||
1131 | return status; |
1148 | return status; |
1132 | } |
1149 | } |
1133 | 1150 | ||
1134 | cairo_status_t |
1151 | cairo_status_t |
1135 | _cairo_gstate_stroke (cairo_gstate_t *gstate, cairo_path_fixed_t *path) |
1152 | _cairo_gstate_stroke (cairo_gstate_t *gstate, cairo_path_fixed_t *path) |
1136 | { |
- | |
1137 | cairo_pattern_union_t source_pattern; |
1153 | { |
Line -... | Line 1154... | ||
- | 1154 | cairo_pattern_union_t source_pattern; |
|
1138 | cairo_stroke_style_t style; |
1155 | cairo_stroke_style_t style; |
1139 | double dash[2]; |
1156 | double dash[2]; |
Line 1140... | Line 1157... | ||
1140 | cairo_clip_t clip; |
1157 | cairo_status_t status; |
1141 | cairo_status_t status; |
1158 | |
Line 1142... | Line 1159... | ||
1142 | 1159 | status = _cairo_gstate_get_pattern_status (gstate->source); |
|
1143 | if (unlikely (gstate->source->status)) |
1160 | if (unlikely (status)) |
Line 1144... | Line 1161... | ||
1144 | return gstate->source->status; |
1161 | return status; |
1145 | 1162 | ||
Line -... | Line 1163... | ||
- | 1163 | if (gstate->op == CAIRO_OPERATOR_DEST) |
|
- | 1164 | return CAIRO_STATUS_SUCCESS; |
|
1146 | if (gstate->op == CAIRO_OPERATOR_DEST) |
1165 | |
1147 | return CAIRO_STATUS_SUCCESS; |
1166 | if (gstate->stroke_style.line_width <= 0.0) |
1148 | 1167 | return CAIRO_STATUS_SUCCESS; |
|
1149 | if (gstate->stroke_style.line_width <= 0.0) |
1168 | |
1150 | return CAIRO_STATUS_SUCCESS; |
1169 | if (_cairo_clip_is_all_clipped (gstate->clip)) |
Line 1161... | Line 1180... | ||
1161 | &style.num_dashes); |
1180 | &style.num_dashes); |
1162 | } |
1181 | } |
Line 1163... | Line 1182... | ||
1163 | 1182 | ||
Line 1164... | Line 1183... | ||
1164 | _cairo_gstate_copy_transformed_source (gstate, &source_pattern.base); |
1183 | _cairo_gstate_copy_transformed_source (gstate, &source_pattern.base); |
1165 | 1184 | ||
1166 | status = _cairo_surface_stroke (gstate->target, |
1185 | return _cairo_surface_stroke (gstate->target, |
1167 | gstate->op, |
1186 | gstate->op, |
1168 | &source_pattern.base, |
1187 | &source_pattern.base, |
1169 | path, |
1188 | path, |
1170 | &style, |
1189 | &style, |
1171 | &gstate->ctm, |
1190 | &gstate->ctm, |
1172 | &gstate->ctm_inverse, |
1191 | &gstate->ctm_inverse, |
1173 | gstate->tolerance, |
1192 | gstate->tolerance, |
1174 | gstate->antialias, |
- | |
1175 | _gstate_get_clip (gstate, &clip)); |
- | |
1176 | _cairo_clip_fini (&clip); |
- | |
1177 | 1193 | gstate->antialias, |
|
Line 1178... | Line 1194... | ||
1178 | return status; |
1194 | gstate->clip); |
1179 | } |
1195 | } |
1180 | 1196 | ||
Line 1217... | Line 1233... | ||
1217 | limit.p2.y = limit.p1.y + 2; |
1233 | limit.p2.y = limit.p1.y + 2; |
Line 1218... | Line 1234... | ||
1218 | 1234 | ||
1219 | _cairo_traps_init (&traps); |
1235 | _cairo_traps_init (&traps); |
Line 1220... | Line 1236... | ||
1220 | _cairo_traps_limit (&traps, &limit, 1); |
1236 | _cairo_traps_limit (&traps, &limit, 1); |
1221 | 1237 | ||
1222 | status = _cairo_path_fixed_stroke_to_traps (path, |
1238 | status = _cairo_path_fixed_stroke_polygon_to_traps (path, |
1223 | &gstate->stroke_style, |
1239 | &gstate->stroke_style, |
1224 | &gstate->ctm, |
1240 | &gstate->ctm, |
1225 | &gstate->ctm_inverse, |
1241 | &gstate->ctm_inverse, |
Line 1237... | Line 1253... | ||
1237 | } |
1253 | } |
Line 1238... | Line 1254... | ||
1238 | 1254 | ||
1239 | cairo_status_t |
1255 | cairo_status_t |
1240 | _cairo_gstate_fill (cairo_gstate_t *gstate, cairo_path_fixed_t *path) |
1256 | _cairo_gstate_fill (cairo_gstate_t *gstate, cairo_path_fixed_t *path) |
1241 | { |
- | |
1242 | cairo_clip_t clip; |
1257 | { |
Line -... | Line 1258... | ||
- | 1258 | cairo_status_t status; |
|
1243 | cairo_status_t status; |
1259 | |
1244 | 1260 | status = _cairo_gstate_get_pattern_status (gstate->source); |
|
Line 1245... | Line 1261... | ||
1245 | if (unlikely (gstate->source->status)) |
1261 | if (unlikely (status)) |
1246 | return gstate->source->status; |
1262 | return status; |
Line 1247... | Line 1263... | ||
1247 | 1263 | ||
1248 | if (gstate->op == CAIRO_OPERATOR_DEST) |
1264 | if (gstate->op == CAIRO_OPERATOR_DEST) |
Line -... | Line 1265... | ||
- | 1265 | return CAIRO_STATUS_SUCCESS; |
|
- | 1266 | ||
1249 | return CAIRO_STATUS_SUCCESS; |
1267 | if (_cairo_clip_is_all_clipped (gstate->clip)) |
1250 | 1268 | return CAIRO_STATUS_SUCCESS; |
|
1251 | if (_clipped (gstate)) |
1269 | |
Line 1252... | Line 1270... | ||
1252 | return CAIRO_STATUS_SUCCESS; |
1270 | assert (gstate->opacity == 1.0); |
1253 | 1271 | ||
1254 | if (_cairo_path_fixed_fill_is_empty (path)) { |
1272 | if (_cairo_path_fixed_fill_is_empty (path)) { |
1255 | if (_cairo_operator_bounded_by_mask (gstate->op)) |
1273 | if (_cairo_operator_bounded_by_mask (gstate->op)) |
1256 | return CAIRO_STATUS_SUCCESS; |
1274 | return CAIRO_STATUS_SUCCESS; |
1257 | 1275 | ||
1258 | status = _cairo_surface_paint (gstate->target, |
1276 | status = _cairo_surface_paint (gstate->target, |
1259 | CAIRO_OPERATOR_CLEAR, |
1277 | CAIRO_OPERATOR_CLEAR, |
1260 | &_cairo_pattern_clear.base, |
1278 | &_cairo_pattern_clear.base, |
Line 1281... | Line 1299... | ||
1281 | box.p1.y <= _cairo_fixed_from_int (extents.y) && |
1299 | box.p1.y <= _cairo_fixed_from_int (extents.y) && |
1282 | box.p2.x >= _cairo_fixed_from_int (extents.x + extents.width) && |
1300 | box.p2.x >= _cairo_fixed_from_int (extents.x + extents.width) && |
1283 | box.p2.y >= _cairo_fixed_from_int (extents.y + extents.height)) |
1301 | box.p2.y >= _cairo_fixed_from_int (extents.y + extents.height)) |
1284 | { |
1302 | { |
1285 | status = _cairo_surface_paint (gstate->target, op, pattern, |
1303 | status = _cairo_surface_paint (gstate->target, op, pattern, |
1286 | _gstate_get_clip (gstate, &clip)); |
1304 | gstate->clip); |
1287 | } |
1305 | } |
1288 | else |
1306 | else |
1289 | { |
1307 | { |
1290 | status = _cairo_surface_fill (gstate->target, op, pattern, |
1308 | status = _cairo_surface_fill (gstate->target, op, pattern, |
1291 | path, |
1309 | path, |
1292 | gstate->fill_rule, |
1310 | gstate->fill_rule, |
1293 | gstate->tolerance, |
1311 | gstate->tolerance, |
1294 | gstate->antialias, |
1312 | gstate->antialias, |
1295 | _gstate_get_clip (gstate, &clip)); |
1313 | gstate->clip); |
1296 | } |
1314 | } |
1297 | } |
1315 | } |
Line 1298... | Line -... | ||
1298 | - | ||
1299 | _cairo_clip_fini (&clip); |
- | |
1300 | 1316 | ||
1301 | return status; |
1317 | return status; |
Line 1302... | Line 1318... | ||
1302 | } |
1318 | } |
1303 | 1319 | ||
Line 1318... | Line 1334... | ||
1318 | cairo_bool_t |
1334 | cairo_bool_t |
1319 | _cairo_gstate_in_clip (cairo_gstate_t *gstate, |
1335 | _cairo_gstate_in_clip (cairo_gstate_t *gstate, |
1320 | double x, |
1336 | double x, |
1321 | double y) |
1337 | double y) |
1322 | { |
1338 | { |
1323 | cairo_clip_path_t *clip_path; |
1339 | cairo_clip_t *clip = gstate->clip; |
- | 1340 | int i; |
|
Line 1324... | Line 1341... | ||
1324 | 1341 | ||
1325 | if (gstate->clip.all_clipped) |
1342 | if (_cairo_clip_is_all_clipped (clip)) |
Line 1326... | Line -... | ||
1326 | return FALSE; |
- | |
1327 | 1343 | return FALSE; |
|
1328 | clip_path = gstate->clip.path; |
1344 | |
Line 1329... | Line 1345... | ||
1329 | if (clip_path == NULL) |
1345 | if (clip == NULL) |
Line 1330... | Line 1346... | ||
1330 | return TRUE; |
1346 | return TRUE; |
1331 | 1347 | ||
1332 | _cairo_gstate_user_to_backend (gstate, &x, &y); |
1348 | _cairo_gstate_user_to_backend (gstate, &x, &y); |
1333 | 1349 | ||
1334 | if (x < clip_path->extents.x || |
1350 | if (x < clip->extents.x || |
1335 | x >= clip_path->extents.x + clip_path->extents.width || |
1351 | x >= clip->extents.x + clip->extents.width || |
1336 | y < clip_path->extents.y || |
1352 | y < clip->extents.y || |
Line -... | Line 1353... | ||
- | 1353 | y >= clip->extents.y + clip->extents.height) |
|
- | 1354 | { |
|
- | 1355 | return FALSE; |
|
- | 1356 | } |
|
- | 1357 | ||
- | 1358 | if (clip->num_boxes) { |
|
- | 1359 | int fx, fy; |
|
- | 1360 | ||
- | 1361 | fx = _cairo_fixed_from_double (x); |
|
- | 1362 | fy = _cairo_fixed_from_double (y); |
|
- | 1363 | for (i = 0; i < clip->num_boxes; i++) { |
|
- | 1364 | if (fx >= clip->boxes[i].p1.x && fx <= clip->boxes[i].p2.x && |
|
- | 1365 | fy >= clip->boxes[i].p1.y && fy <= clip->boxes[i].p2.y) |
|
- | 1366 | break; |
|
- | 1367 | } |
|
- | 1368 | if (i == clip->num_boxes) |
|
1337 | y >= clip_path->extents.y + clip_path->extents.height) |
1369 | return FALSE; |
1338 | { |
1370 | } |
1339 | return FALSE; |
1371 | |
1340 | } |
1372 | if (clip->path) { |
1341 | 1373 | cairo_clip_path_t *clip_path = clip->path; |
|
1342 | do { |
1374 | do { |
1343 | if (! _cairo_path_fixed_in_fill (&clip_path->path, |
1375 | if (! _cairo_path_fixed_in_fill (&clip_path->path, |
- | 1376 | clip_path->fill_rule, |
|
Line 1344... | Line 1377... | ||
1344 | clip_path->fill_rule, |
1377 | clip_path->tolerance, |
1345 | clip_path->tolerance, |
1378 | x, y)) |
Line 1346... | Line 1379... | ||
1346 | x, y)) |
1379 | return FALSE; |
Line 1363... | Line 1396... | ||
1363 | cairo_surface_show_page (gstate->target); |
1396 | cairo_surface_show_page (gstate->target); |
1364 | return cairo_surface_status (gstate->target); |
1397 | return cairo_surface_status (gstate->target); |
1365 | } |
1398 | } |
Line 1366... | Line 1399... | ||
1366 | 1399 | ||
1367 | static void |
1400 | static void |
1368 | _cairo_gstate_traps_extents_to_user_rectangle (cairo_gstate_t *gstate, |
1401 | _cairo_gstate_extents_to_user_rectangle (cairo_gstate_t *gstate, |
1369 | cairo_traps_t *traps, |
1402 | const cairo_box_t *extents, |
1370 | double *x1, double *y1, |
1403 | double *x1, double *y1, |
1371 | double *x2, double *y2) |
1404 | double *x2, double *y2) |
1372 | { |
- | |
1373 | cairo_box_t extents; |
- | |
1374 | - | ||
1375 | if (traps->num_traps == 0) { |
- | |
1376 | /* no traps, so we actually won't draw anything */ |
- | |
1377 | if (x1) |
- | |
1378 | *x1 = 0.0; |
- | |
1379 | if (y1) |
- | |
1380 | *y1 = 0.0; |
- | |
1381 | if (x2) |
- | |
1382 | *x2 = 0.0; |
- | |
1383 | if (y2) |
- | |
1384 | *y2 = 0.0; |
- | |
1385 | } else { |
1405 | { |
Line 1386... | Line -... | ||
1386 | double px1, py1, px2, py2; |
- | |
1387 | - | ||
1388 | _cairo_traps_extents (traps, &extents); |
1406 | double px1, py1, px2, py2; |
1389 | 1407 | ||
1390 | px1 = _cairo_fixed_to_double (extents.p1.x); |
1408 | px1 = _cairo_fixed_to_double (extents->p1.x); |
1391 | py1 = _cairo_fixed_to_double (extents.p1.y); |
1409 | py1 = _cairo_fixed_to_double (extents->p1.y); |
Line 1392... | Line 1410... | ||
1392 | px2 = _cairo_fixed_to_double (extents.p2.x); |
1410 | px2 = _cairo_fixed_to_double (extents->p2.x); |
1393 | py2 = _cairo_fixed_to_double (extents.p2.y); |
1411 | py2 = _cairo_fixed_to_double (extents->p2.y); |
1394 | 1412 | ||
1395 | _cairo_gstate_backend_to_user_rectangle (gstate, |
1413 | _cairo_gstate_backend_to_user_rectangle (gstate, |
Line 1402... | Line 1420... | ||
1402 | if (x2) |
1420 | if (x2) |
1403 | *x2 = px2; |
1421 | *x2 = px2; |
1404 | if (y2) |
1422 | if (y2) |
1405 | *y2 = py2; |
1423 | *y2 = py2; |
1406 | } |
1424 | } |
1407 | } |
- | |
Line 1408... | Line 1425... | ||
1408 | 1425 | ||
1409 | cairo_status_t |
1426 | cairo_status_t |
1410 | _cairo_gstate_stroke_extents (cairo_gstate_t *gstate, |
1427 | _cairo_gstate_stroke_extents (cairo_gstate_t *gstate, |
1411 | cairo_path_fixed_t *path, |
1428 | cairo_path_fixed_t *path, |
1412 | double *x1, double *y1, |
1429 | double *x1, double *y1, |
1413 | double *x2, double *y2) |
1430 | double *x2, double *y2) |
1414 | { |
1431 | { |
1415 | cairo_status_t status; |
1432 | cairo_int_status_t status; |
- | 1433 | cairo_box_t extents; |
|
Line 1416... | Line -... | ||
1416 | cairo_traps_t traps; |
- | |
1417 | 1434 | cairo_bool_t empty; |
|
1418 | if (gstate->stroke_style.line_width <= 0.0) { |
1435 | |
1419 | if (x1) |
1436 | if (x1) |
1420 | *x1 = 0.0; |
1437 | *x1 = 0.0; |
1421 | if (y1) |
1438 | if (y1) |
1422 | *y1 = 0.0; |
1439 | *y1 = 0.0; |
1423 | if (x2) |
1440 | if (x2) |
1424 | *x2 = 0.0; |
1441 | *x2 = 0.0; |
- | 1442 | if (y2) |
|
- | 1443 | *y2 = 0.0; |
|
1425 | if (y2) |
1444 | |
- | 1445 | if (gstate->stroke_style.line_width <= 0.0) |
|
- | 1446 | return CAIRO_STATUS_SUCCESS; |
|
- | 1447 | ||
- | 1448 | status = CAIRO_INT_STATUS_UNSUPPORTED; |
|
- | 1449 | if (_cairo_path_fixed_stroke_is_rectilinear (path)) { |
|
- | 1450 | cairo_boxes_t boxes; |
|
- | 1451 | ||
- | 1452 | _cairo_boxes_init (&boxes); |
|
- | 1453 | status = _cairo_path_fixed_stroke_rectilinear_to_boxes (path, |
|
- | 1454 | &gstate->stroke_style, |
|
- | 1455 | &gstate->ctm, |
|
- | 1456 | gstate->antialias, |
|
- | 1457 | &boxes); |
|
- | 1458 | empty = boxes.num_boxes == 0; |
|
- | 1459 | if (! empty) |
|
1426 | *y2 = 0.0; |
1460 | _cairo_boxes_extents (&boxes, &extents); |
Line -... | Line 1461... | ||
- | 1461 | _cairo_boxes_fini (&boxes); |
|
1427 | return CAIRO_STATUS_SUCCESS; |
1462 | } |
Line -... | Line 1463... | ||
- | 1463 | ||
1428 | } |
1464 | if (status == CAIRO_INT_STATUS_UNSUPPORTED) { |
1429 | 1465 | cairo_polygon_t polygon; |
|
1430 | _cairo_traps_init (&traps); |
1466 | |
1431 | 1467 | _cairo_polygon_init (&polygon, NULL, 0); |
|
1432 | status = _cairo_path_fixed_stroke_to_traps (path, |
1468 | status = _cairo_path_fixed_stroke_to_polygon (path, |
1433 | &gstate->stroke_style, |
1469 | &gstate->stroke_style, |
- | 1470 | &gstate->ctm, |
|
- | 1471 | &gstate->ctm_inverse, |
|
1434 | &gstate->ctm, |
1472 | gstate->tolerance, |
- | 1473 | &polygon); |
|
- | 1474 | empty = polygon.num_edges == 0; |
|
- | 1475 | if (! empty) |
|
1435 | &gstate->ctm_inverse, |
1476 | extents = polygon.extents; |
1436 | gstate->tolerance, |
1477 | _cairo_polygon_fini (&polygon); |
1437 | &traps); |
1478 | } |
Line 1438... | Line -... | ||
1438 | if (likely (status == CAIRO_STATUS_SUCCESS)) { |
- | |
1439 | _cairo_gstate_traps_extents_to_user_rectangle (gstate, &traps, |
- | |
1440 | x1, y1, x2, y2); |
1479 | if (! empty) { |
1441 | } |
1480 | _cairo_gstate_extents_to_user_rectangle (gstate, &extents, |
Line 1442... | Line 1481... | ||
1442 | 1481 | x1, y1, x2, y2); |
|
1443 | _cairo_traps_fini (&traps); |
1482 | } |
1444 | 1483 | ||
1445 | return status; |
1484 | return status; |
1446 | } |
1485 | } |
1447 | 1486 | ||
1448 | cairo_status_t |
1487 | cairo_status_t |
1449 | _cairo_gstate_fill_extents (cairo_gstate_t *gstate, |
1488 | _cairo_gstate_fill_extents (cairo_gstate_t *gstate, |
- | 1489 | cairo_path_fixed_t *path, |
|
Line 1450... | Line -... | ||
1450 | cairo_path_fixed_t *path, |
- | |
1451 | double *x1, double *y1, |
1490 | double *x1, double *y1, |
1452 | double *x2, double *y2) |
1491 | double *x2, double *y2) |
1453 | { |
1492 | { |
1454 | cairo_status_t status; |
1493 | cairo_status_t status; |
1455 | cairo_traps_t traps; |
1494 | cairo_box_t extents; |
1456 | 1495 | cairo_bool_t empty; |
|
1457 | if (path->is_empty_fill) { |
1496 | |
1458 | if (x1) |
1497 | if (x1) |
- | 1498 | *x1 = 0.0; |
|
- | 1499 | if (y1) |
|
1459 | *x1 = 0.0; |
1500 | *y1 = 0.0; |
- | 1501 | if (x2) |
|
- | 1502 | *x2 = 0.0; |
|
- | 1503 | if (y2) |
|
- | 1504 | *y2 = 0.0; |
|
- | 1505 | ||
- | 1506 | if (_cairo_path_fixed_fill_is_empty (path)) |
|
- | 1507 | return CAIRO_STATUS_SUCCESS; |
|
- | 1508 | ||
- | 1509 | if (_cairo_path_fixed_fill_is_rectilinear (path)) { |
|
- | 1510 | cairo_boxes_t boxes; |
|
- | 1511 | ||
- | 1512 | _cairo_boxes_init (&boxes); |
|
- | 1513 | status = _cairo_path_fixed_fill_rectilinear_to_boxes (path, |
|
- | 1514 | gstate->fill_rule, |
|
1460 | if (y1) |
1515 | gstate->antialias, |
- | 1516 | &boxes); |
|
Line 1461... | Line 1517... | ||
1461 | *y1 = 0.0; |
1517 | empty = boxes.num_boxes == 0; |
Line 1462... | Line 1518... | ||
1462 | if (x2) |
1518 | if (! empty) |
1463 | *x2 = 0.0; |
1519 | _cairo_boxes_extents (&boxes, &extents); |
1464 | if (y2) |
1520 | |
1465 | *y2 = 0.0; |
1521 | _cairo_boxes_fini (&boxes); |
1466 | return CAIRO_STATUS_SUCCESS; |
1522 | } else { |
- | 1523 | cairo_traps_t traps; |
|
1467 | } |
1524 | |
1468 | - | ||
1469 | _cairo_traps_init (&traps); |
- | |
Line 1470... | Line 1525... | ||
1470 | 1525 | _cairo_traps_init (&traps); |
|
- | 1526 | ||
- | 1527 | status = _cairo_path_fixed_fill_to_traps (path, |
|
- | 1528 | gstate->fill_rule, |
|
- | 1529 | gstate->tolerance, |
|
- | 1530 | &traps); |
|
- | 1531 | empty = traps.num_traps == 0; |
|
Line 1471... | Line 1532... | ||
1471 | status = _cairo_path_fixed_fill_to_traps (path, |
1532 | if (! empty) |
1472 | gstate->fill_rule, |
1533 | _cairo_traps_extents (&traps, &extents); |
Line 1473... | Line 1534... | ||
1473 | gstate->tolerance, |
1534 | |
1474 | &traps); |
1535 | _cairo_traps_fini (&traps); |
1475 | if (likely (status == CAIRO_STATUS_SUCCESS)) { |
1536 | } |
1476 | _cairo_gstate_traps_extents_to_user_rectangle (gstate, &traps, |
1537 | |
- | 1538 | if (! empty) { |
|
Line 1477... | Line 1539... | ||
1477 | x1, y1, x2, y2); |
1539 | _cairo_gstate_extents_to_user_rectangle (gstate, &extents, |
1478 | } |
1540 | x1, y1, x2, y2); |
Line 1479... | Line 1541... | ||
1479 | 1541 | } |
|
1480 | _cairo_traps_fini (&traps); |
1542 | |
1481 | 1543 | return status; |
|
- | 1544 | } |
|
1482 | return status; |
1545 | |
- | 1546 | cairo_status_t |
|
1483 | } |
1547 | _cairo_gstate_reset_clip (cairo_gstate_t *gstate) |
- | 1548 | { |
|
1484 | 1549 | _cairo_clip_destroy (gstate->clip); |
|
- | 1550 | gstate->clip = NULL; |
|
- | 1551 | ||
1485 | cairo_status_t |
1552 | return CAIRO_STATUS_SUCCESS; |
Line 1486... | Line 1553... | ||
1486 | _cairo_gstate_reset_clip (cairo_gstate_t *gstate) |
1553 | } |
1487 | { |
1554 | |
1488 | _cairo_clip_reset (&gstate->clip); |
1555 | cairo_status_t |
1489 | 1556 | _cairo_gstate_clip (cairo_gstate_t *gstate, cairo_path_fixed_t *path) |
|
1490 | return CAIRO_STATUS_SUCCESS; |
- | |
1491 | } |
1557 | { |
Line 1492... | Line 1558... | ||
1492 | 1558 | gstate->clip = |
|
Line 1493... | Line -... | ||
1493 | cairo_status_t |
- | |
1494 | _cairo_gstate_clip (cairo_gstate_t *gstate, cairo_path_fixed_t *path) |
1559 | _cairo_clip_intersect_path (gstate->clip, |
1495 | { |
1560 | path, |
1496 | return _cairo_clip_clip (&gstate->clip, |
- | |
1497 | path, gstate->fill_rule, |
1561 | gstate->fill_rule, |
1498 | gstate->tolerance, gstate->antialias); |
1562 | gstate->tolerance, |
1499 | } |
1563 | gstate->antialias); |
Line 1500... | Line 1564... | ||
1500 | 1564 | /* XXX */ |
|
1501 | static cairo_bool_t |
1565 | return CAIRO_STATUS_SUCCESS; |
Line 1553... | Line 1617... | ||
1553 | } |
1617 | } |
Line 1554... | Line 1618... | ||
1554 | 1618 | ||
1555 | cairo_rectangle_list_t* |
1619 | cairo_rectangle_list_t* |
1556 | _cairo_gstate_copy_clip_rectangle_list (cairo_gstate_t *gstate) |
1620 | _cairo_gstate_copy_clip_rectangle_list (cairo_gstate_t *gstate) |
1557 | { |
- | |
1558 | cairo_clip_t clip; |
1621 | { |
1559 | cairo_rectangle_int_t extents; |
1622 | cairo_rectangle_int_t extents; |
1560 | cairo_rectangle_list_t *list; |
- | |
1561 | 1623 | cairo_rectangle_list_t *list; |
|
Line 1562... | Line 1624... | ||
1562 | _cairo_clip_init_copy (&clip, &gstate->clip); |
1624 | cairo_clip_t *clip; |
1563 | 1625 | ||
- | 1626 | if (_cairo_surface_get_extents (gstate->target, &extents)) |
|
- | 1627 | clip = _cairo_clip_copy_intersect_rectangle (gstate->clip, &extents); |
|
Line 1564... | Line 1628... | ||
1564 | if (_cairo_surface_get_extents (gstate->target, &extents)) |
1628 | else |
- | 1629 | clip = gstate->clip; |
|
- | 1630 | ||
1565 | _cairo_clip_rectangle (&clip, &extents); |
1631 | list = _cairo_clip_copy_rectangle_list (clip, gstate); |
Line 1566... | Line 1632... | ||
1566 | 1632 | ||
1567 | list = _cairo_clip_copy_rectangle_list (&clip, gstate); |
1633 | if (clip != gstate->clip) |
Line 1568... | Line 1634... | ||
1568 | _cairo_clip_fini (&clip); |
1634 | _cairo_clip_destroy (clip); |
Line 1582... | Line 1648... | ||
1582 | gstate->previous_scaled_font = gstate->scaled_font; |
1648 | gstate->previous_scaled_font = gstate->scaled_font; |
1583 | gstate->scaled_font = NULL; |
1649 | gstate->scaled_font = NULL; |
1584 | } |
1650 | } |
Line 1585... | Line 1651... | ||
1585 | 1651 | ||
1586 | cairo_status_t |
- | |
1587 | _cairo_gstate_select_font_face (cairo_gstate_t *gstate, |
- | |
1588 | const char *family, |
- | |
1589 | cairo_font_slant_t slant, |
- | |
1590 | cairo_font_weight_t weight) |
- | |
1591 | { |
- | |
1592 | cairo_font_face_t *font_face; |
- | |
1593 | cairo_status_t status; |
- | |
1594 | - | ||
1595 | font_face = cairo_toy_font_face_create (family, slant, weight); |
- | |
1596 | if (font_face->status) |
- | |
1597 | return font_face->status; |
- | |
1598 | - | ||
1599 | status = _cairo_gstate_set_font_face (gstate, font_face); |
- | |
1600 | cairo_font_face_destroy (font_face); |
- | |
1601 | - | ||
1602 | return status; |
- | |
1603 | } |
- | |
1604 | - | ||
1605 | cairo_status_t |
1652 | cairo_status_t |
1606 | _cairo_gstate_set_font_size (cairo_gstate_t *gstate, |
1653 | _cairo_gstate_set_font_size (cairo_gstate_t *gstate, |
1607 | double size) |
1654 | double size) |
1608 | { |
1655 | { |
Line 1618... | Line 1665... | ||
1618 | const cairo_matrix_t *matrix) |
1665 | const cairo_matrix_t *matrix) |
1619 | { |
1666 | { |
1620 | if (memcmp (matrix, &gstate->font_matrix, sizeof (cairo_matrix_t)) == 0) |
1667 | if (memcmp (matrix, &gstate->font_matrix, sizeof (cairo_matrix_t)) == 0) |
1621 | return CAIRO_STATUS_SUCCESS; |
1668 | return CAIRO_STATUS_SUCCESS; |
Line 1622... | Line -... | ||
1622 | - | ||
1623 | if (! _cairo_matrix_is_invertible (matrix)) |
- | |
1624 | return _cairo_error (CAIRO_STATUS_INVALID_MATRIX); |
- | |
1625 | 1669 | ||
Line 1626... | Line 1670... | ||
1626 | _cairo_gstate_unset_scaled_font (gstate); |
1670 | _cairo_gstate_unset_scaled_font (gstate); |
Line 1627... | Line 1671... | ||
1627 | 1671 | ||
Line 1826... | Line 1870... | ||
1826 | 1870 | ||
1827 | return cairo_scaled_font_status (gstate->scaled_font); |
1871 | return cairo_scaled_font_status (gstate->scaled_font); |
Line 1828... | Line 1872... | ||
1828 | } |
1872 | } |
1829 | - | ||
1830 | cairo_status_t |
- | |
1831 | _cairo_gstate_text_to_glyphs (cairo_gstate_t *gstate, |
- | |
1832 | double x, |
- | |
1833 | double y, |
- | |
1834 | const char *utf8, |
- | |
1835 | int utf8_len, |
- | |
1836 | cairo_glyph_t **glyphs, |
- | |
1837 | int *num_glyphs, |
- | |
1838 | cairo_text_cluster_t **clusters, |
- | |
1839 | int *num_clusters, |
- | |
1840 | cairo_text_cluster_flags_t *cluster_flags) |
- | |
1841 | { |
- | |
1842 | cairo_status_t status; |
- | |
1843 | - | ||
1844 | status = _cairo_gstate_ensure_scaled_font (gstate); |
- | |
1845 | if (unlikely (status)) |
- | |
1846 | return status; |
- | |
1847 | - | ||
1848 | return cairo_scaled_font_text_to_glyphs (gstate->scaled_font, x, y, |
- | |
1849 | utf8, utf8_len, |
- | |
1850 | glyphs, num_glyphs, |
- | |
1851 | clusters, num_clusters, |
- | |
1852 | cluster_flags); |
- | |
1853 | } |
- | |
1854 | 1873 | ||
1855 | cairo_status_t |
1874 | cairo_status_t |
1856 | _cairo_gstate_set_font_face (cairo_gstate_t *gstate, |
1875 | _cairo_gstate_set_font_face (cairo_gstate_t *gstate, |
1857 | cairo_font_face_t *font_face) |
1876 | cairo_font_face_t *font_face) |
1858 | { |
1877 | { |
Line 1889... | Line 1908... | ||
1889 | return cairo_scaled_font_status (gstate->scaled_font); |
1908 | return cairo_scaled_font_status (gstate->scaled_font); |
1890 | } |
1909 | } |
Line 1891... | Line 1910... | ||
1891 | 1910 | ||
1892 | cairo_status_t |
1911 | cairo_status_t |
1893 | _cairo_gstate_show_text_glyphs (cairo_gstate_t *gstate, |
- | |
1894 | const char *utf8, |
- | |
1895 | int utf8_len, |
1912 | _cairo_gstate_show_text_glyphs (cairo_gstate_t *gstate, |
1896 | const cairo_glyph_t *glyphs, |
1913 | const cairo_glyph_t *glyphs, |
1897 | int num_glyphs, |
- | |
1898 | const cairo_text_cluster_t *clusters, |
- | |
1899 | int num_clusters, |
1914 | int num_glyphs, |
1900 | cairo_text_cluster_flags_t cluster_flags) |
1915 | cairo_glyph_text_info_t *info) |
1901 | { |
- | |
1902 | cairo_pattern_union_t source_pattern; |
- | |
1903 | const cairo_pattern_t *pattern; |
1916 | { |
1904 | cairo_glyph_t stack_transformed_glyphs[CAIRO_STACK_ARRAY_LENGTH (cairo_glyph_t)]; |
- | |
1905 | cairo_glyph_t *transformed_glyphs; |
1917 | cairo_glyph_t stack_transformed_glyphs[CAIRO_STACK_ARRAY_LENGTH (cairo_glyph_t)]; |
- | 1918 | cairo_text_cluster_t stack_transformed_clusters[CAIRO_STACK_ARRAY_LENGTH (cairo_text_cluster_t)]; |
|
- | 1919 | cairo_pattern_union_t source_pattern; |
|
- | 1920 | cairo_glyph_t *transformed_glyphs; |
|
1906 | cairo_text_cluster_t stack_transformed_clusters[CAIRO_STACK_ARRAY_LENGTH (cairo_text_cluster_t)]; |
1921 | const cairo_pattern_t *pattern; |
1907 | cairo_text_cluster_t *transformed_clusters; |
1922 | cairo_text_cluster_t *transformed_clusters; |
1908 | cairo_operator_t op; |
1923 | cairo_operator_t op; |
1909 | cairo_status_t status; |
- | |
Line -... | Line 1924... | ||
- | 1924 | cairo_status_t status; |
|
1910 | cairo_clip_t clip; |
1925 | |
1911 | 1926 | status = _cairo_gstate_get_pattern_status (gstate->source); |
|
Line 1912... | Line 1927... | ||
1912 | if (unlikely (gstate->source->status)) |
1927 | if (unlikely (status)) |
1913 | return gstate->source->status; |
1928 | return status; |
Line 1914... | Line 1929... | ||
1914 | 1929 | ||
1915 | if (gstate->op == CAIRO_OPERATOR_DEST) |
1930 | if (gstate->op == CAIRO_OPERATOR_DEST) |
Line 1916... | Line 1931... | ||
1916 | return CAIRO_STATUS_SUCCESS; |
1931 | return CAIRO_STATUS_SUCCESS; |
1917 | 1932 | ||
1918 | if (_clipped (gstate)) |
1933 | if (_cairo_clip_is_all_clipped (gstate->clip)) |
Line 1925... | Line 1940... | ||
1925 | transformed_glyphs = stack_transformed_glyphs; |
1940 | transformed_glyphs = stack_transformed_glyphs; |
1926 | transformed_clusters = stack_transformed_clusters; |
1941 | transformed_clusters = stack_transformed_clusters; |
Line 1927... | Line 1942... | ||
1927 | 1942 | ||
1928 | if (num_glyphs > ARRAY_LENGTH (stack_transformed_glyphs)) { |
1943 | if (num_glyphs > ARRAY_LENGTH (stack_transformed_glyphs)) { |
1929 | transformed_glyphs = cairo_glyph_allocate (num_glyphs); |
1944 | transformed_glyphs = cairo_glyph_allocate (num_glyphs); |
1930 | if (unlikely (transformed_glyphs == NULL)) { |
1945 | if (unlikely (transformed_glyphs == NULL)) |
1931 | status = _cairo_error (CAIRO_STATUS_NO_MEMORY); |
- | |
1932 | goto CLEANUP_GLYPHS; |
- | |
1933 | } |
1946 | return _cairo_error (CAIRO_STATUS_NO_MEMORY); |
Line 1934... | Line -... | ||
1934 | } |
- | |
1935 | 1947 | } |
|
1936 | /* Just in case */ |
- | |
1937 | if (!clusters) |
- | |
1938 | num_clusters = 0; |
1948 | |
1939 | 1949 | if (info != NULL) { |
|
1940 | if (num_clusters > ARRAY_LENGTH (stack_transformed_clusters)) { |
1950 | if (info->num_clusters > ARRAY_LENGTH (stack_transformed_clusters)) { |
1941 | transformed_clusters = cairo_text_cluster_allocate (num_clusters); |
1951 | transformed_clusters = cairo_text_cluster_allocate (info->num_clusters); |
1942 | if (unlikely (transformed_clusters == NULL)) { |
1952 | if (unlikely (transformed_clusters == NULL)) { |
1943 | status = _cairo_error (CAIRO_STATUS_NO_MEMORY); |
1953 | status = _cairo_error (CAIRO_STATUS_NO_MEMORY); |
1944 | goto CLEANUP_GLYPHS; |
1954 | goto CLEANUP_GLYPHS; |
Line 1945... | Line 1955... | ||
1945 | } |
1955 | } |
1946 | } |
1956 | } |
1947 | 1957 | ||
1948 | status = _cairo_gstate_transform_glyphs_to_backend (gstate, |
1958 | _cairo_gstate_transform_glyphs_to_backend (gstate, |
1949 | glyphs, num_glyphs, |
1959 | glyphs, num_glyphs, |
1950 | clusters, |
1960 | info->clusters, |
1951 | num_clusters, |
1961 | info->num_clusters, |
1952 | cluster_flags, |
1962 | info->cluster_flags, |
- | 1963 | transformed_glyphs, |
|
- | 1964 | &num_glyphs, |
|
- | 1965 | transformed_clusters); |
|
- | 1966 | } else { |
|
- | 1967 | _cairo_gstate_transform_glyphs_to_backend (gstate, |
|
- | 1968 | glyphs, num_glyphs, |
|
- | 1969 | NULL, 0, 0, |
|
- | 1970 | transformed_glyphs, |
|
Line 1953... | Line 1971... | ||
1953 | transformed_glyphs, |
1971 | &num_glyphs, |
1954 | &num_glyphs, |
1972 | NULL); |
Line 1955... | Line 1973... | ||
1955 | transformed_clusters); |
1973 | } |
1956 | 1974 | ||
1957 | if (status || num_glyphs == 0) |
1975 | if (num_glyphs == 0) |
Line 1976... | Line 1994... | ||
1976 | * |
1994 | * |
1977 | * Needless to say, do this only if show_text_glyphs is not available. */ |
1995 | * Needless to say, do this only if show_text_glyphs is not available. */ |
1978 | if (cairo_surface_has_show_text_glyphs (gstate->target) || |
1996 | if (cairo_surface_has_show_text_glyphs (gstate->target) || |
1979 | _cairo_scaled_font_get_max_scale (gstate->scaled_font) <= 10240) |
1997 | _cairo_scaled_font_get_max_scale (gstate->scaled_font) <= 10240) |
1980 | { |
1998 | { |
- | 1999 | if (info != NULL) { |
|
1981 | status = _cairo_surface_show_text_glyphs (gstate->target, op, pattern, |
2000 | status = _cairo_surface_show_text_glyphs (gstate->target, op, pattern, |
1982 | utf8, utf8_len, |
2001 | info->utf8, info->utf8_len, |
1983 | transformed_glyphs, num_glyphs, |
2002 | transformed_glyphs, num_glyphs, |
1984 | transformed_clusters, num_clusters, |
2003 | transformed_clusters, info->num_clusters, |
1985 | cluster_flags, |
2004 | info->cluster_flags, |
1986 | gstate->scaled_font, |
2005 | gstate->scaled_font, |
1987 | _gstate_get_clip (gstate, &clip)); |
2006 | gstate->clip); |
- | 2007 | } else { |
|
- | 2008 | status = _cairo_surface_show_text_glyphs (gstate->target, op, pattern, |
|
- | 2009 | NULL, 0, |
|
- | 2010 | transformed_glyphs, num_glyphs, |
|
- | 2011 | NULL, 0, 0, |
|
- | 2012 | gstate->scaled_font, |
|
- | 2013 | gstate->clip); |
|
- | 2014 | } |
|
1988 | } |
2015 | } |
1989 | else |
2016 | else |
1990 | { |
2017 | { |
1991 | cairo_path_fixed_t path; |
2018 | cairo_path_fixed_t path; |
Line 2000... | Line 2027... | ||
2000 | status = _cairo_surface_fill (gstate->target, op, pattern, |
2027 | status = _cairo_surface_fill (gstate->target, op, pattern, |
2001 | &path, |
2028 | &path, |
2002 | CAIRO_FILL_RULE_WINDING, |
2029 | CAIRO_FILL_RULE_WINDING, |
2003 | gstate->tolerance, |
2030 | gstate->tolerance, |
2004 | gstate->scaled_font->options.antialias, |
2031 | gstate->scaled_font->options.antialias, |
2005 | _gstate_get_clip (gstate, &clip)); |
2032 | gstate->clip); |
2006 | } |
2033 | } |
Line 2007... | Line 2034... | ||
2007 | 2034 | ||
2008 | _cairo_path_fixed_fini (&path); |
2035 | _cairo_path_fixed_fini (&path); |
Line 2009... | Line -... | ||
2009 | } |
- | |
2010 | - | ||
2011 | _cairo_clip_fini (&clip); |
2036 | } |
2012 | 2037 | ||
2013 | CLEANUP_GLYPHS: |
2038 | CLEANUP_GLYPHS: |
2014 | if (transformed_glyphs != stack_transformed_glyphs) |
2039 | if (transformed_glyphs != stack_transformed_glyphs) |
2015 | cairo_glyph_free (transformed_glyphs); |
2040 | cairo_glyph_free (transformed_glyphs); |
Line 2023... | Line 2048... | ||
2023 | _cairo_gstate_glyph_path (cairo_gstate_t *gstate, |
2048 | _cairo_gstate_glyph_path (cairo_gstate_t *gstate, |
2024 | const cairo_glyph_t *glyphs, |
2049 | const cairo_glyph_t *glyphs, |
2025 | int num_glyphs, |
2050 | int num_glyphs, |
2026 | cairo_path_fixed_t *path) |
2051 | cairo_path_fixed_t *path) |
2027 | { |
2052 | { |
2028 | cairo_status_t status; |
- | |
2029 | cairo_glyph_t *transformed_glyphs; |
- | |
2030 | cairo_glyph_t stack_transformed_glyphs[CAIRO_STACK_ARRAY_LENGTH (cairo_glyph_t)]; |
2053 | cairo_glyph_t stack_transformed_glyphs[CAIRO_STACK_ARRAY_LENGTH (cairo_glyph_t)]; |
- | 2054 | cairo_glyph_t *transformed_glyphs; |
|
- | 2055 | cairo_status_t status; |
|
Line 2031... | Line 2056... | ||
2031 | 2056 | ||
2032 | status = _cairo_gstate_ensure_scaled_font (gstate); |
2057 | status = _cairo_gstate_ensure_scaled_font (gstate); |
2033 | if (unlikely (status)) |
2058 | if (unlikely (status)) |
Line 2039... | Line 2064... | ||
2039 | transformed_glyphs = cairo_glyph_allocate (num_glyphs); |
2064 | transformed_glyphs = cairo_glyph_allocate (num_glyphs); |
2040 | if (unlikely (transformed_glyphs == NULL)) |
2065 | if (unlikely (transformed_glyphs == NULL)) |
2041 | return _cairo_error (CAIRO_STATUS_NO_MEMORY); |
2066 | return _cairo_error (CAIRO_STATUS_NO_MEMORY); |
2042 | } |
2067 | } |
Line 2043... | Line 2068... | ||
2043 | 2068 | ||
2044 | status = _cairo_gstate_transform_glyphs_to_backend (gstate, |
2069 | _cairo_gstate_transform_glyphs_to_backend (gstate, |
2045 | glyphs, num_glyphs, |
2070 | glyphs, num_glyphs, |
2046 | NULL, 0, 0, |
2071 | NULL, 0, 0, |
2047 | transformed_glyphs, |
2072 | transformed_glyphs, |
2048 | NULL, NULL); |
- | |
2049 | if (unlikely (status)) |
- | |
Line 2050... | Line 2073... | ||
2050 | goto CLEANUP_GLYPHS; |
2073 | &num_glyphs, NULL); |
2051 | 2074 | ||
2052 | status = _cairo_scaled_font_glyph_path (gstate->scaled_font, |
2075 | status = _cairo_scaled_font_glyph_path (gstate->scaled_font, |
Line 2053... | Line -... | ||
2053 | transformed_glyphs, num_glyphs, |
- | |
2054 | path); |
2076 | transformed_glyphs, num_glyphs, |
2055 | 2077 | path); |
|
Line 2056... | Line 2078... | ||
2056 | CLEANUP_GLYPHS: |
2078 | |
2057 | if (transformed_glyphs != stack_transformed_glyphs) |
2079 | if (transformed_glyphs != stack_transformed_glyphs) |
Line 2091... | Line 2113... | ||
2091 | * The result of the transformation is placed in @transformed_glyphs. |
2113 | * The result of the transformation is placed in @transformed_glyphs. |
2092 | * |
2114 | * |
2093 | * This also uses information from the scaled font and the surface to |
2115 | * This also uses information from the scaled font and the surface to |
2094 | * cull/drop glyphs that will not be visible. |
2116 | * cull/drop glyphs that will not be visible. |
2095 | **/ |
2117 | **/ |
2096 | static cairo_status_t |
2118 | static void |
2097 | _cairo_gstate_transform_glyphs_to_backend (cairo_gstate_t *gstate, |
2119 | _cairo_gstate_transform_glyphs_to_backend (cairo_gstate_t *gstate, |
2098 | const cairo_glyph_t *glyphs, |
2120 | const cairo_glyph_t *glyphs, |
2099 | int num_glyphs, |
2121 | int num_glyphs, |
2100 | const cairo_text_cluster_t *clusters, |
2122 | const cairo_text_cluster_t *clusters, |
2101 | int num_clusters, |
2123 | int num_clusters, |
2102 | cairo_text_cluster_flags_t cluster_flags, |
2124 | cairo_text_cluster_flags_t cluster_flags, |
2103 | cairo_glyph_t *transformed_glyphs, |
2125 | cairo_glyph_t *transformed_glyphs, |
2104 | int *num_transformed_glyphs, |
2126 | int *num_transformed_glyphs, |
2105 | cairo_text_cluster_t *transformed_clusters) |
2127 | cairo_text_cluster_t *transformed_clusters) |
2106 | { |
2128 | { |
2107 | int i, j, k; |
2129 | cairo_rectangle_int_t surface_extents; |
2108 | cairo_matrix_t *ctm = &gstate->ctm; |
2130 | cairo_matrix_t *ctm = &gstate->ctm; |
2109 | cairo_matrix_t *font_matrix = &gstate->font_matrix; |
2131 | cairo_matrix_t *font_matrix = &gstate->font_matrix; |
2110 | cairo_matrix_t *device_transform = &gstate->target->device_transform; |
2132 | cairo_matrix_t *device_transform = &gstate->target->device_transform; |
2111 | cairo_bool_t drop = FALSE; |
2133 | cairo_bool_t drop = FALSE; |
2112 | double x1 = 0, x2 = 0, y1 = 0, y2 = 0; |
2134 | double x1 = 0, x2 = 0, y1 = 0, y2 = 0; |
2113 | - | ||
2114 | if (num_transformed_glyphs != NULL) { |
2135 | int i, j, k; |
2115 | cairo_rectangle_int_t surface_extents; |
- | |
Line 2116... | Line 2136... | ||
2116 | 2136 | ||
2117 | drop = TRUE; |
2137 | drop = TRUE; |
2118 | if (! _cairo_gstate_int_clip_extents (gstate, &surface_extents)) { |
2138 | if (! _cairo_gstate_int_clip_extents (gstate, &surface_extents)) { |
2119 | drop = FALSE; /* unbounded surface */ |
2139 | drop = FALSE; /* unbounded surface */ |
2120 | } else { |
2140 | } else { |
2121 | double scale10 = 10 * _cairo_scaled_font_get_max_scale (gstate->scaled_font); |
2141 | double scale10 = 10 * _cairo_scaled_font_get_max_scale (gstate->scaled_font); |
2122 | if (surface_extents.width == 0 || surface_extents.height == 0) { |
2142 | if (surface_extents.width == 0 || surface_extents.height == 0) { |
2123 | /* No visible area. Don't draw anything */ |
2143 | /* No visible area. Don't draw anything */ |
2124 | *num_transformed_glyphs = 0; |
2144 | *num_transformed_glyphs = 0; |
2125 | return CAIRO_STATUS_SUCCESS; |
2145 | return; |
2126 | } |
2146 | } |
2127 | /* XXX We currently drop any glyphs that has its position outside |
2147 | /* XXX We currently drop any glyphs that has its position outside |
2128 | * of the surface boundaries by a safety margin depending on the |
2148 | * of the surface boundaries by a safety margin depending on the |
2129 | * font scale. This however can fail in extreme cases where the |
2149 | * font scale. This however can fail in extreme cases where the |
Line 2138... | Line 2158... | ||
2138 | y2 = surface_extents.y + (int) surface_extents.height + scale10; |
2158 | y2 = surface_extents.y + (int) surface_extents.height + scale10; |
2139 | } |
2159 | } |
Line 2140... | Line 2160... | ||
2140 | 2160 | ||
2141 | if (!drop) |
2161 | if (!drop) |
2142 | *num_transformed_glyphs = num_glyphs; |
- | |
2143 | } else |
- | |
Line 2144... | Line 2162... | ||
2144 | num_transformed_glyphs = &j; |
2162 | *num_transformed_glyphs = num_glyphs; |
Line 2145... | Line 2163... | ||
2145 | 2163 | ||
2146 | #define KEEP_GLYPH(glyph) (x1 <= glyph.x && glyph.x <= x2 && y1 <= glyph.y && glyph.y <= y2) |
2164 | #define KEEP_GLYPH(glyph) (x1 <= glyph.x && glyph.x <= x2 && y1 <= glyph.y && glyph.y <= y2) |
Line 2151... | Line 2169... | ||
2151 | font_matrix->x0 == 0 && font_matrix->y0 == 0) |
2169 | font_matrix->x0 == 0 && font_matrix->y0 == 0) |
2152 | { |
2170 | { |
2153 | if (! drop) { |
2171 | if (! drop) { |
2154 | memcpy (transformed_glyphs, glyphs, |
2172 | memcpy (transformed_glyphs, glyphs, |
2155 | num_glyphs * sizeof (cairo_glyph_t)); |
2173 | num_glyphs * sizeof (cairo_glyph_t)); |
- | 2174 | memcpy (transformed_clusters, clusters, |
|
- | 2175 | num_clusters * sizeof (cairo_text_cluster_t)); |
|
2156 | j = num_glyphs; |
2176 | j = num_glyphs; |
2157 | } else if (num_clusters == 0) { |
2177 | } else if (num_clusters == 0) { |
2158 | for (i = 0; i < num_glyphs; i++) { |
2178 | for (i = 0; i < num_glyphs; i++) { |
2159 | transformed_glyphs[j].index = glyphs[i].index; |
2179 | transformed_glyphs[j].index = glyphs[i].index; |
2160 | transformed_glyphs[j].x = glyphs[i].x; |
2180 | transformed_glyphs[j].x = glyphs[i].x; |
Line 2206... | Line 2226... | ||
2206 | transformed_glyphs[j].x = glyphs[i].x + tx; |
2226 | transformed_glyphs[j].x = glyphs[i].x + tx; |
2207 | transformed_glyphs[j].y = glyphs[i].y + ty; |
2227 | transformed_glyphs[j].y = glyphs[i].y + ty; |
2208 | if (!drop || KEEP_GLYPH (transformed_glyphs[j])) |
2228 | if (!drop || KEEP_GLYPH (transformed_glyphs[j])) |
2209 | j++; |
2229 | j++; |
2210 | } |
2230 | } |
- | 2231 | memcpy (transformed_clusters, clusters, |
|
- | 2232 | num_clusters * sizeof (cairo_text_cluster_t)); |
|
2211 | } else { |
2233 | } else { |
2212 | const cairo_glyph_t *cur_glyph; |
2234 | const cairo_glyph_t *cur_glyph; |
Line 2213... | Line 2235... | ||
2213 | 2235 | ||
2214 | if (cluster_flags & CAIRO_TEXT_CLUSTER_FLAG_BACKWARD) |
2236 | if (cluster_flags & CAIRO_TEXT_CLUSTER_FLAG_BACKWARD) |
Line 2259... | Line 2281... | ||
2259 | &transformed_glyphs[j].x, |
2281 | &transformed_glyphs[j].x, |
2260 | &transformed_glyphs[j].y); |
2282 | &transformed_glyphs[j].y); |
2261 | if (! drop || KEEP_GLYPH (transformed_glyphs[j])) |
2283 | if (! drop || KEEP_GLYPH (transformed_glyphs[j])) |
2262 | j++; |
2284 | j++; |
2263 | } |
2285 | } |
- | 2286 | memcpy (transformed_clusters, clusters, |
|
- | 2287 | num_clusters * sizeof (cairo_text_cluster_t)); |
|
2264 | } else { |
2288 | } else { |
2265 | const cairo_glyph_t *cur_glyph; |
2289 | const cairo_glyph_t *cur_glyph; |
Line 2266... | Line 2290... | ||
2266 | 2290 | ||
2267 | if (cluster_flags & CAIRO_TEXT_CLUSTER_FLAG_BACKWARD) |
2291 | if (cluster_flags & CAIRO_TEXT_CLUSTER_FLAG_BACKWARD) |
Line 2302... | Line 2326... | ||
2302 | tmp = transformed_glyphs[i]; |
2326 | tmp = transformed_glyphs[i]; |
2303 | transformed_glyphs[i] = transformed_glyphs[j]; |
2327 | transformed_glyphs[i] = transformed_glyphs[j]; |
2304 | transformed_glyphs[j] = tmp; |
2328 | transformed_glyphs[j] = tmp; |
2305 | } |
2329 | } |
2306 | } |
2330 | } |
2307 | - | ||
2308 | return CAIRO_STATUS_SUCCESS; |
- | |
2309 | }>>>>>>>>>>=>=>=>=>>=>=>>>=>=>>>=>=>=>=>=>>>> |
2331 | }>>>>>>>>>>=>=>=>=>>=>=>=>=>>>>=>=>>>=>=>=>=>=>>>>>>> |