2
* Copyright � 2002 University of Southern California
4
* Permission to use, copy, modify, distribute, and sell this software
5
* and its documentation for any purpose is hereby granted without
6
* fee, provided that the above copyright notice appear in all copies
7
* and that both that copyright notice and this permission notice
8
* appear in supporting documentation, and that the name of the
9
* University of Southern California not be used in advertising or
10
* publicity pertaining to distribution of the software without
11
* specific, written prior permission. The University of Southern
12
* California makes no representations about the suitability of this
13
* software for any purpose. It is provided "as is" without express
14
* or implied warranty.
16
* THE UNIVERSITY OF SOUTHERN CALIFORNIA DISCLAIMS ALL WARRANTIES WITH
17
* REGARD TO THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF
18
* MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL THE UNIVERSITY OF
19
* SOUTHERN CALIFORNIA BE LIABLE FOR ANY SPECIAL, INDIRECT OR
20
* CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS
21
* OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT,
22
* NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
23
* CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
25
* Author: Carl D. Worth <cworth@isi.edu>
34
_cairo_gstate_clip_and_composite_trapezoids (cairo_gstate_t *gstate,
36
cairo_operator_t operator,
38
cairo_traps_t *traps);
41
_cairo_gstate_create ()
43
cairo_gstate_t *gstate;
45
gstate = malloc (sizeof (cairo_gstate_t));
48
_cairo_gstate_init (gstate);
54
_cairo_gstate_init (cairo_gstate_t *gstate)
56
gstate->operator = CAIRO_GSTATE_OPERATOR_DEFAULT;
58
gstate->tolerance = CAIRO_GSTATE_TOLERANCE_DEFAULT;
60
gstate->line_width = CAIRO_GSTATE_LINE_WIDTH_DEFAULT;
61
gstate->line_cap = CAIRO_GSTATE_LINE_CAP_DEFAULT;
62
gstate->line_join = CAIRO_GSTATE_LINE_JOIN_DEFAULT;
63
gstate->miter_limit = CAIRO_GSTATE_MITER_LIMIT_DEFAULT;
65
gstate->fill_rule = CAIRO_GSTATE_FILL_RULE_DEFAULT;
68
gstate->num_dashes = 0;
69
gstate->dash_offset = 0.0;
71
gstate->font = _cairo_font_create (CAIRO_FONT_FAMILY_DEFAULT,
72
CAIRO_FONT_SLANT_DEFAULT,
73
CAIRO_FONT_WEIGHT_DEFAULT);
75
gstate->surface = NULL;
77
gstate->clip.region = NULL;
78
gstate->clip.surface = NULL;
80
gstate->pattern = _cairo_pattern_create_solid (1.0, 1.0, 1.0);
81
gstate->pattern_offset.x = 0.0;
82
gstate->pattern_offset.y = 0.0;
85
gstate->pixels_per_inch = CAIRO_GSTATE_PIXELS_PER_INCH_DEFAULT;
86
_cairo_gstate_default_matrix (gstate);
88
_cairo_path_init (&gstate->path);
90
_cairo_pen_init_empty (&gstate->pen_regular);
96
_cairo_gstate_init_copy (cairo_gstate_t *gstate, cairo_gstate_t *other)
98
cairo_status_t status;
101
/* Copy all members, but don't smash the next pointer */
106
/* Now fix up pointer data that needs to be cloned/referenced */
108
gstate->dash = malloc (other->num_dashes * sizeof (double));
109
if (gstate->dash == NULL)
110
return CAIRO_STATUS_NO_MEMORY;
111
memcpy (gstate->dash, other->dash, other->num_dashes * sizeof (double));
115
gstate->font = _cairo_font_copy (other->font);
117
status = CAIRO_STATUS_NO_MEMORY;
122
if (other->clip.region)
124
gstate->clip.region = pixman_region_create ();
125
pixman_region_copy (gstate->clip.region, other->clip.region);
128
cairo_surface_reference (gstate->surface);
129
cairo_surface_reference (gstate->clip.surface);
131
cairo_pattern_reference (gstate->pattern);
133
status = _cairo_path_init_copy (&gstate->path, &other->path);
137
status = _cairo_pen_init_copy (&gstate->pen_regular, &other->pen_regular);
144
_cairo_path_fini (&gstate->path);
146
cairo_font_destroy (gstate->font);
155
_cairo_gstate_fini (cairo_gstate_t *gstate)
157
cairo_font_destroy (gstate->font);
160
cairo_surface_destroy (gstate->surface);
161
gstate->surface = NULL;
163
if (gstate->clip.surface)
164
cairo_surface_destroy (gstate->clip.surface);
165
gstate->clip.surface = NULL;
167
if (gstate->clip.region)
168
pixman_region_destroy (gstate->clip.region);
169
gstate->clip.region = NULL;
171
cairo_pattern_destroy (gstate->pattern);
173
_cairo_matrix_fini (&gstate->ctm);
174
_cairo_matrix_fini (&gstate->ctm_inverse);
176
_cairo_path_fini (&gstate->path);
178
_cairo_pen_fini (&gstate->pen_regular);
187
_cairo_gstate_destroy (cairo_gstate_t *gstate)
189
_cairo_gstate_fini (gstate);
194
_cairo_gstate_clone (cairo_gstate_t *gstate)
196
cairo_status_t status;
197
cairo_gstate_t *clone;
199
clone = malloc (sizeof (cairo_gstate_t));
201
status = _cairo_gstate_init_copy (clone, gstate);
213
_cairo_gstate_copy (cairo_gstate_t *dest, cairo_gstate_t *src)
215
cairo_status_t status;
216
cairo_gstate_t *next;
218
/* Preserve next pointer over fini/init */
220
_cairo_gstate_fini (dest);
221
status = _cairo_gstate_init_copy (dest, src);
227
/* Push rendering off to an off-screen group. */
228
/* XXX: Rethinking this API
230
_cairo_gstate_begin_group (cairo_gstate_t *gstate)
234
unsigned int width, height;
236
gstate->parent_surface = gstate->surface;
238
width = _cairo_surface_get_width (gstate->surface);
239
height = _cairo_surface_get_height (gstate->surface);
241
pix = XCreatePixmap (gstate->dpy,
242
_cairo_surface_get_drawable (gstate->surface),
244
_cairo_surface_get_depth (gstate->surface));
246
return CAIRO_STATUS_NO_MEMORY;
248
gstate->surface = cairo_surface_create (gstate->dpy);
249
if (gstate->surface == NULL)
250
return CAIRO_STATUS_NO_MEMORY;
252
_cairo_surface_set_drawableWH (gstate->surface, pix, width, height);
254
_cairo_color_init (&clear);
255
_cairo_color_set_alpha (&clear, 0);
257
status = _cairo_surface_fill_rectangle (gstate->surface,
261
_cairo_surface_get_width (gstate->surface),
262
_cairo_surface_get_height (gstate->surface));
266
return CAIRO_STATUS_SUCCESS;
270
/* Complete the current offscreen group, composing its contents onto the parent surface. */
271
/* XXX: Rethinking this API
273
_cairo_gstate_end_group (cairo_gstate_t *gstate)
276
cairo_color_t mask_color;
277
cairo_surface_t mask;
279
if (gstate->parent_surface == NULL)
280
return CAIRO_STATUS_INVALID_POP_GROUP;
282
_cairo_surface_init (&mask, gstate->dpy);
283
_cairo_color_init (&mask_color);
284
_cairo_color_set_alpha (&mask_color, gstate->alpha);
286
_cairo_surface_set_solid_color (&mask, &mask_color);
288
* XXX: This could be made much more efficient by using
289
_cairo_surface_get_damaged_width/Height if cairo_surface_t actually kept
290
track of such informaton. *
291
_cairo_surface_composite (gstate->operator,
294
gstate->parent_surface,
298
_cairo_surface_get_width (gstate->surface),
299
_cairo_surface_get_height (gstate->surface));
301
_cairo_surface_fini (&mask);
303
pix = _cairo_surface_get_drawable (gstate->surface);
304
XFreePixmap (gstate->dpy, pix);
306
cairo_surface_destroy (gstate->surface);
307
gstate->surface = gstate->parent_surface;
308
gstate->parent_surface = NULL;
310
return CAIRO_STATUS_SUCCESS;
315
_cairo_gstate_set_target_surface (cairo_gstate_t *gstate, cairo_surface_t *surface)
320
cairo_surface_destroy (gstate->surface);
322
gstate->surface = surface;
324
/* Sometimes the user wants to return to having no target surface,
325
* (just like after cairo_create). This can be useful for forcing
326
* the old surface to be destroyed. */
328
return CAIRO_STATUS_SUCCESS;
330
cairo_surface_reference (gstate->surface);
332
scale = _cairo_surface_pixels_per_inch (surface) / gstate->pixels_per_inch;
333
_cairo_gstate_scale (gstate, scale, scale);
334
gstate->pixels_per_inch = _cairo_surface_pixels_per_inch (surface);
336
return CAIRO_STATUS_SUCCESS;
339
/* XXX: Need to decide the memory mangement semantics of this
340
function. Should it reference the surface again? */
342
_cairo_gstate_current_target_surface (cairo_gstate_t *gstate)
347
/* XXX: Do we want this?
349
_cairo_surface_reference (gstate->surface);
352
return gstate->surface;
356
_cairo_gstate_set_pattern (cairo_gstate_t *gstate, cairo_pattern_t *pattern)
359
return CAIRO_STATUS_NULL_POINTER;
362
cairo_pattern_destroy (gstate->pattern);
364
gstate->pattern = pattern;
365
cairo_pattern_reference (pattern);
367
return CAIRO_STATUS_SUCCESS;
371
_cairo_gstate_current_pattern (cairo_gstate_t *gstate)
376
/* XXX: Do we want this?
377
cairo_pattern_reference (gstate->pattern);
380
return gstate->pattern;
384
_cairo_gstate_set_operator (cairo_gstate_t *gstate, cairo_operator_t operator)
386
gstate->operator = operator;
388
return CAIRO_STATUS_SUCCESS;
392
_cairo_gstate_current_operator (cairo_gstate_t *gstate)
394
return gstate->operator;
398
_cairo_gstate_set_rgb_color (cairo_gstate_t *gstate, double red, double green, double blue)
400
cairo_pattern_destroy (gstate->pattern);
402
gstate->pattern = _cairo_pattern_create_solid (red, green, blue);
403
gstate->pattern_offset.x = 0.0;
404
gstate->pattern_offset.y = 0.0;
406
return CAIRO_STATUS_SUCCESS;
410
_cairo_gstate_current_rgb_color (cairo_gstate_t *gstate, double *red, double *green, double *blue)
412
return _cairo_pattern_get_rgb (gstate->pattern, red, green, blue);
416
_cairo_gstate_set_tolerance (cairo_gstate_t *gstate, double tolerance)
418
gstate->tolerance = tolerance;
420
return CAIRO_STATUS_SUCCESS;
424
_cairo_gstate_current_tolerance (cairo_gstate_t *gstate)
426
return gstate->tolerance;
430
_cairo_gstate_set_alpha (cairo_gstate_t *gstate, double alpha)
432
gstate->alpha = alpha;
434
return CAIRO_STATUS_SUCCESS;
438
_cairo_gstate_current_alpha (cairo_gstate_t *gstate)
440
return gstate->alpha;
444
_cairo_gstate_set_fill_rule (cairo_gstate_t *gstate, cairo_fill_rule_t fill_rule)
446
gstate->fill_rule = fill_rule;
448
return CAIRO_STATUS_SUCCESS;
452
_cairo_gstate_current_fill_rule (cairo_gstate_t *gstate)
454
return gstate->fill_rule;
458
_cairo_gstate_set_line_width (cairo_gstate_t *gstate, double width)
460
gstate->line_width = width;
462
return CAIRO_STATUS_SUCCESS;
466
_cairo_gstate_current_line_width (cairo_gstate_t *gstate)
468
return gstate->line_width;
472
_cairo_gstate_set_line_cap (cairo_gstate_t *gstate, cairo_line_cap_t line_cap)
474
gstate->line_cap = line_cap;
476
return CAIRO_STATUS_SUCCESS;
480
_cairo_gstate_current_line_cap (cairo_gstate_t *gstate)
482
return gstate->line_cap;
486
_cairo_gstate_set_line_join (cairo_gstate_t *gstate, cairo_line_join_t line_join)
488
gstate->line_join = line_join;
490
return CAIRO_STATUS_SUCCESS;
494
_cairo_gstate_current_line_join (cairo_gstate_t *gstate)
496
return gstate->line_join;
500
_cairo_gstate_set_dash (cairo_gstate_t *gstate, double *dash, int num_dashes, double offset)
507
gstate->num_dashes = num_dashes;
508
if (gstate->num_dashes) {
509
gstate->dash = malloc (gstate->num_dashes * sizeof (double));
510
if (gstate->dash == NULL) {
511
gstate->num_dashes = 0;
512
return CAIRO_STATUS_NO_MEMORY;
516
memcpy (gstate->dash, dash, gstate->num_dashes * sizeof (double));
517
gstate->dash_offset = offset;
519
return CAIRO_STATUS_SUCCESS;
523
_cairo_gstate_set_miter_limit (cairo_gstate_t *gstate, double limit)
525
gstate->miter_limit = limit;
527
return CAIRO_STATUS_SUCCESS;
531
_cairo_gstate_current_miter_limit (cairo_gstate_t *gstate)
533
return gstate->miter_limit;
537
_cairo_gstate_current_matrix (cairo_gstate_t *gstate, cairo_matrix_t *matrix)
539
cairo_matrix_copy (matrix, &gstate->ctm);
543
_cairo_gstate_translate (cairo_gstate_t *gstate, double tx, double ty)
547
_cairo_matrix_set_translate (&tmp, tx, ty);
548
cairo_matrix_multiply (&gstate->ctm, &tmp, &gstate->ctm);
550
_cairo_matrix_set_translate (&tmp, -tx, -ty);
551
cairo_matrix_multiply (&gstate->ctm_inverse, &gstate->ctm_inverse, &tmp);
553
return CAIRO_STATUS_SUCCESS;
557
_cairo_gstate_scale (cairo_gstate_t *gstate, double sx, double sy)
561
if (sx == 0 || sy == 0)
562
return CAIRO_STATUS_INVALID_MATRIX;
564
_cairo_matrix_set_scale (&tmp, sx, sy);
565
cairo_matrix_multiply (&gstate->ctm, &tmp, &gstate->ctm);
567
_cairo_matrix_set_scale (&tmp, 1/sx, 1/sy);
568
cairo_matrix_multiply (&gstate->ctm_inverse, &gstate->ctm_inverse, &tmp);
570
return CAIRO_STATUS_SUCCESS;
574
_cairo_gstate_rotate (cairo_gstate_t *gstate, double angle)
578
_cairo_matrix_set_rotate (&tmp, angle);
579
cairo_matrix_multiply (&gstate->ctm, &tmp, &gstate->ctm);
581
_cairo_matrix_set_rotate (&tmp, -angle);
582
cairo_matrix_multiply (&gstate->ctm_inverse, &gstate->ctm_inverse, &tmp);
584
return CAIRO_STATUS_SUCCESS;
588
_cairo_gstate_concat_matrix (cairo_gstate_t *gstate,
589
cairo_matrix_t *matrix)
593
cairo_matrix_copy (&tmp, matrix);
594
cairo_matrix_multiply (&gstate->ctm, &tmp, &gstate->ctm);
596
cairo_matrix_invert (&tmp);
597
cairo_matrix_multiply (&gstate->ctm_inverse, &gstate->ctm_inverse, &tmp);
599
return CAIRO_STATUS_SUCCESS;
603
_cairo_gstate_set_matrix (cairo_gstate_t *gstate,
604
cairo_matrix_t *matrix)
606
cairo_status_t status;
608
cairo_matrix_copy (&gstate->ctm, matrix);
610
cairo_matrix_copy (&gstate->ctm_inverse, matrix);
611
status = cairo_matrix_invert (&gstate->ctm_inverse);
615
return CAIRO_STATUS_SUCCESS;
619
_cairo_gstate_default_matrix (cairo_gstate_t *gstate)
621
int scale = gstate->pixels_per_inch / CAIRO_GSTATE_PIXELS_PER_INCH_DEFAULT + 0.5;
625
cairo_matrix_set_identity (&gstate->ctm);
626
cairo_matrix_scale (&gstate->ctm, scale, scale);
627
cairo_matrix_copy (&gstate->ctm_inverse, &gstate->ctm);
628
cairo_matrix_invert (&gstate->ctm_inverse);
630
return CAIRO_STATUS_SUCCESS;
634
_cairo_gstate_identity_matrix (cairo_gstate_t *gstate)
636
cairo_matrix_set_identity (&gstate->ctm);
637
cairo_matrix_set_identity (&gstate->ctm_inverse);
639
return CAIRO_STATUS_SUCCESS;
643
_cairo_gstate_transform_point (cairo_gstate_t *gstate, double *x, double *y)
645
cairo_matrix_transform_point (&gstate->ctm, x, y);
647
return CAIRO_STATUS_SUCCESS;
651
_cairo_gstate_transform_distance (cairo_gstate_t *gstate, double *dx, double *dy)
653
cairo_matrix_transform_distance (&gstate->ctm, dx, dy);
655
return CAIRO_STATUS_SUCCESS;
659
_cairo_gstate_inverse_transform_point (cairo_gstate_t *gstate, double *x, double *y)
661
cairo_matrix_transform_point (&gstate->ctm_inverse, x, y);
663
return CAIRO_STATUS_SUCCESS;
667
_cairo_gstate_inverse_transform_distance (cairo_gstate_t *gstate, double *dx, double *dy)
669
cairo_matrix_transform_distance (&gstate->ctm_inverse, dx, dy);
671
return CAIRO_STATUS_SUCCESS;
675
_cairo_gstate_new_path (cairo_gstate_t *gstate)
677
_cairo_path_fini (&gstate->path);
679
return CAIRO_STATUS_SUCCESS;
683
_cairo_gstate_move_to (cairo_gstate_t *gstate, double x, double y)
687
cairo_matrix_transform_point (&gstate->ctm, &x, &y);
689
point.x = _cairo_fixed_from_double (x);
690
point.y = _cairo_fixed_from_double (y);
692
return _cairo_path_move_to (&gstate->path, &point);
696
_cairo_gstate_line_to (cairo_gstate_t *gstate, double x, double y)
700
cairo_matrix_transform_point (&gstate->ctm, &x, &y);
702
point.x = _cairo_fixed_from_double (x);
703
point.y = _cairo_fixed_from_double (y);
705
return _cairo_path_line_to (&gstate->path, &point);
709
_cairo_gstate_curve_to (cairo_gstate_t *gstate,
710
double x0, double y0,
711
double x1, double y1,
712
double x2, double y2)
714
cairo_point_t p0, p1, p2;
716
cairo_matrix_transform_point (&gstate->ctm, &x0, &y0);
717
cairo_matrix_transform_point (&gstate->ctm, &x1, &y1);
718
cairo_matrix_transform_point (&gstate->ctm, &x2, &y2);
720
p0.x = _cairo_fixed_from_double (x0);
721
p0.y = _cairo_fixed_from_double (y0);
723
p1.x = _cairo_fixed_from_double (x1);
724
p1.y = _cairo_fixed_from_double (y1);
726
p2.x = _cairo_fixed_from_double (x2);
727
p2.y = _cairo_fixed_from_double (y2);
729
return _cairo_path_curve_to (&gstate->path, &p0, &p1, &p2);
732
/* Spline deviation from the circle in radius would be given by:
734
error = sqrt (x**2 + y**2) - 1
736
A simpler error function to work with is:
740
From "Good approximation of circles by curvature-continuous Bezier
741
curves", Tor Dokken and Morten Daehlen, Computer Aided Geometric
742
Design 8 (1990) 22-41, we learn:
744
abs (max(e)) = 4/27 * sin**6(angle/4) / cos**2(angle/4)
747
abs (error) =~ 1/2 * e
749
Of course, this error value applies only for the particular spline
750
approximation that is used in _cairo_gstate_arc_segment.
753
_arc_error_normalized (double angle)
755
return 2.0/27.0 * pow (sin (angle / 4), 6) / pow (cos (angle / 4), 2);
759
_arc_max_angle_for_tolerance_normalized (double tolerance)
764
/* Use table lookup to reduce search time in most cases. */
769
{ M_PI / 1.0, 0.0185185185185185036127 },
770
{ M_PI / 2.0, 0.000272567143730179811158 },
771
{ M_PI / 3.0, 2.38647043651461047433e-05 },
772
{ M_PI / 4.0, 4.2455377443222443279e-06 },
773
{ M_PI / 5.0, 1.11281001494389081528e-06 },
774
{ M_PI / 6.0, 3.72662000942734705475e-07 },
775
{ M_PI / 7.0, 1.47783685574284411325e-07 },
776
{ M_PI / 8.0, 6.63240432022601149057e-08 },
777
{ M_PI / 9.0, 3.2715520137536980553e-08 },
778
{ M_PI / 10.0, 1.73863223499021216974e-08 },
779
{ M_PI / 11.0, 9.81410988043554039085e-09 },
781
int table_size = (sizeof (table) / sizeof (table[0]));
783
for (i = 0; i < table_size; i++)
784
if (table[i].error < tolerance)
785
return table[i].angle;
790
error = _arc_error_normalized (angle);
791
} while (error > tolerance);
797
_cairo_gstate_arc_segments_needed (cairo_gstate_t *gstate,
804
_cairo_matrix_compute_eigen_values (&gstate->ctm, &l1, &l2);
813
max_angle = _arc_max_angle_for_tolerance_normalized (gstate->tolerance / (radius * lmax));
815
return (int) ceil (angle / max_angle);
818
/* We want to draw a single spline approximating a circular arc radius
819
R from angle A to angle B. Since we want a symmetric spline that
820
matches the endpoints of the arc in position and slope, we know
821
that the spline control points must be:
823
(R * cos(A), R * sin(A))
824
(R * cos(A) - h * sin(A), R * sin(A) + h * cos (A))
825
(R * cos(B) + h * sin(B), R * sin(B) - h * cos (B))
826
(R * cos(B), R * sin(B))
830
"Approximation of circular arcs by cubic poynomials", Michael
831
Goldapp, Computer Aided Geometric Design 8 (1991) 227-238, provides
832
various values of h along with error analysis for each.
834
From that paper, a very practical value of h is:
836
h = 4/3 * tan(angle/4)
838
This value does not give the spline with minimal error, but it does
839
provide a very good approximation, (6th-order convergence), and the
840
error expression is quite simple, (see the comment for
841
_arc_error_normalized).
843
static cairo_status_t
844
_cairo_gstate_arc_segment (cairo_gstate_t *gstate,
845
double xc, double yc,
847
double angle_A, double angle_B)
849
cairo_status_t status;
850
double r_sin_A, r_cos_A;
851
double r_sin_B, r_cos_B;
854
r_sin_A = radius * sin (angle_A);
855
r_cos_A = radius * cos (angle_A);
856
r_sin_B = radius * sin (angle_B);
857
r_cos_B = radius * cos (angle_B);
859
h = 4.0/3.0 * tan ((angle_B - angle_A) / 4.0);
861
status = _cairo_gstate_curve_to (gstate,
862
xc + r_cos_A - h * r_sin_A, yc + r_sin_A + h * r_cos_A,
863
xc + r_cos_B + h * r_sin_B, yc + r_sin_B - h * r_cos_B,
864
xc + r_cos_B, yc + r_sin_B);
868
return CAIRO_STATUS_SUCCESS;
871
static cairo_status_t
872
_cairo_gstate_arc_dir (cairo_gstate_t *gstate,
873
double xc, double yc,
877
cairo_direction_t dir)
879
cairo_status_t status;
881
while (angle_max - angle_min > 4 * M_PI)
882
angle_max -= 2 * M_PI;
884
/* Recurse if drawing arc larger than pi */
885
if (angle_max - angle_min > M_PI) {
886
/* XXX: Something tells me this block could be condensed. */
887
if (dir == CAIRO_DIRECTION_FORWARD) {
888
status = _cairo_gstate_arc_dir (gstate, xc, yc, radius,
889
angle_min, angle_min + M_PI, dir);
893
status = _cairo_gstate_arc_dir (gstate, xc, yc, radius,
894
angle_min + M_PI, angle_max, dir);
898
status = _cairo_gstate_arc_dir (gstate, xc, yc, radius,
899
angle_min + M_PI, angle_max, dir);
903
status = _cairo_gstate_arc_dir (gstate, xc, yc, radius,
904
angle_min, angle_min + M_PI, dir);
910
double angle, angle_step;
912
segments = _cairo_gstate_arc_segments_needed (gstate,
913
angle_max - angle_min,
915
angle_step = (angle_max - angle_min) / (double) segments;
917
if (dir == CAIRO_DIRECTION_FORWARD) {
921
angle_step = - angle_step;
924
for (i = 0; i < segments; i++, angle += angle_step) {
925
_cairo_gstate_arc_segment (gstate,
934
return CAIRO_STATUS_SUCCESS;
938
_cairo_gstate_arc (cairo_gstate_t *gstate,
939
double xc, double yc,
941
double angle1, double angle2)
943
cairo_status_t status;
946
return CAIRO_STATUS_SUCCESS;
948
while (angle2 < angle1)
951
status = _cairo_gstate_line_to (gstate,
952
xc + radius * cos (angle1),
953
yc + radius * sin (angle1));
957
status = _cairo_gstate_arc_dir (gstate, xc, yc, radius,
958
angle1, angle2, CAIRO_DIRECTION_FORWARD);
962
return CAIRO_STATUS_SUCCESS;
966
_cairo_gstate_arc_negative (cairo_gstate_t *gstate,
967
double xc, double yc,
969
double angle1, double angle2)
971
cairo_status_t status;
974
return CAIRO_STATUS_SUCCESS;
976
while (angle2 > angle1)
979
status = _cairo_gstate_line_to (gstate,
980
xc + radius * cos (angle1),
981
yc + radius * sin (angle1));
985
status = _cairo_gstate_arc_dir (gstate, xc, yc, radius,
986
angle2, angle1, CAIRO_DIRECTION_REVERSE);
990
return CAIRO_STATUS_SUCCESS;
995
_cairo_gstate_arc_to (cairo_gstate_t *gstate,
996
double x1, double y1,
997
double x2, double y2,
1005
_cairo_gstate_rel_move_to (cairo_gstate_t *gstate, double dx, double dy)
1007
cairo_distance_t distance;
1009
cairo_matrix_transform_distance (&gstate->ctm, &dx, &dy);
1011
distance.dx = _cairo_fixed_from_double (dx);
1012
distance.dy = _cairo_fixed_from_double (dy);
1014
return _cairo_path_rel_move_to (&gstate->path, &distance);
1018
_cairo_gstate_rel_line_to (cairo_gstate_t *gstate, double dx, double dy)
1020
cairo_distance_t distance;
1022
cairo_matrix_transform_distance (&gstate->ctm, &dx, &dy);
1024
distance.dx = _cairo_fixed_from_double (dx);
1025
distance.dy = _cairo_fixed_from_double (dy);
1027
return _cairo_path_rel_line_to (&gstate->path, &distance);
1031
_cairo_gstate_rel_curve_to (cairo_gstate_t *gstate,
1032
double dx0, double dy0,
1033
double dx1, double dy1,
1034
double dx2, double dy2)
1036
cairo_distance_t distance[3];
1038
cairo_matrix_transform_distance (&gstate->ctm, &dx0, &dy0);
1039
cairo_matrix_transform_distance (&gstate->ctm, &dx1, &dy1);
1040
cairo_matrix_transform_distance (&gstate->ctm, &dx2, &dy2);
1042
distance[0].dx = _cairo_fixed_from_double (dx0);
1043
distance[0].dy = _cairo_fixed_from_double (dy0);
1045
distance[1].dx = _cairo_fixed_from_double (dx1);
1046
distance[1].dy = _cairo_fixed_from_double (dy1);
1048
distance[2].dx = _cairo_fixed_from_double (dx2);
1049
distance[2].dy = _cairo_fixed_from_double (dy2);
1051
return _cairo_path_rel_curve_to (&gstate->path,
1059
_cairo_gstate_stroke_path (cairo_gstate_t *gstate)
1061
cairo_status_t status;
1063
_cairo_pen_init (&gstate);
1064
return CAIRO_STATUS_SUCCESS;
1069
_cairo_gstate_close_path (cairo_gstate_t *gstate)
1071
return _cairo_path_close_path (&gstate->path);
1075
_cairo_gstate_current_point (cairo_gstate_t *gstate, double *x_ret, double *y_ret)
1077
cairo_status_t status;
1078
cairo_point_t point;
1081
status = _cairo_path_current_point (&gstate->path, &point);
1082
if (status == CAIRO_STATUS_NO_CURRENT_POINT) {
1086
x = _cairo_fixed_to_double (point.x);
1087
y = _cairo_fixed_to_double (point.y);
1088
cairo_matrix_transform_point (&gstate->ctm_inverse, &x, &y);
1094
return CAIRO_STATUS_SUCCESS;
1097
typedef struct gstate_path_interpreter {
1098
cairo_matrix_t ctm_inverse;
1100
cairo_point_t current_point;
1102
cairo_move_to_func_t *move_to;
1103
cairo_line_to_func_t *line_to;
1104
cairo_curve_to_func_t *curve_to;
1105
cairo_close_path_func_t *close_path;
1110
static cairo_status_t
1111
_gpi_move_to (void *closure, cairo_point_t *point)
1113
gpi_t *gpi = closure;
1116
x = _cairo_fixed_to_double (point->x);
1117
y = _cairo_fixed_to_double (point->y);
1119
cairo_matrix_transform_point (&gpi->ctm_inverse, &x, &y);
1121
gpi->move_to (gpi->closure, x, y);
1122
gpi->current_point = *point;
1124
return CAIRO_STATUS_SUCCESS;
1127
static cairo_status_t
1128
_gpi_line_to (void *closure, cairo_point_t *point)
1130
gpi_t *gpi = closure;
1133
x = _cairo_fixed_to_double (point->x);
1134
y = _cairo_fixed_to_double (point->y);
1136
cairo_matrix_transform_point (&gpi->ctm_inverse, &x, &y);
1138
gpi->line_to (gpi->closure, x, y);
1139
gpi->current_point = *point;
1141
return CAIRO_STATUS_SUCCESS;
1144
static cairo_status_t
1145
_gpi_curve_to (void *closure,
1150
gpi_t *gpi = closure;
1151
cairo_status_t status;
1152
cairo_spline_t spline;
1153
double x1, y1, x2, y2, x3, y3;
1155
if (gpi->curve_to) {
1156
x1 = _cairo_fixed_to_double (p1->x);
1157
y1 = _cairo_fixed_to_double (p1->y);
1158
cairo_matrix_transform_point (&gpi->ctm_inverse, &x1, &y1);
1160
x2 = _cairo_fixed_to_double (p2->x);
1161
y2 = _cairo_fixed_to_double (p2->y);
1162
cairo_matrix_transform_point (&gpi->ctm_inverse, &x2, &y2);
1164
x3 = _cairo_fixed_to_double (p3->x);
1165
y3 = _cairo_fixed_to_double (p3->y);
1166
cairo_matrix_transform_point (&gpi->ctm_inverse, &x3, &y3);
1168
gpi->curve_to (gpi->closure, x1, y1, x2, y2, x3, y3);
1170
cairo_point_t *p0 = &gpi->current_point;
1174
status = _cairo_spline_init (&spline, p0, p1, p2, p3);
1175
if (status == CAIRO_INT_STATUS_DEGENERATE)
1176
return CAIRO_STATUS_SUCCESS;
1178
status = _cairo_spline_decompose (&spline, gpi->tolerance);
1182
for (i=1; i < spline.num_points; i++) {
1183
x = _cairo_fixed_to_double (spline.points[i].x);
1184
y = _cairo_fixed_to_double (spline.points[i].y);
1186
cairo_matrix_transform_point (&gpi->ctm_inverse, &x, &y);
1188
gpi->line_to (gpi->closure, x, y);
1192
gpi->current_point = *p3;
1194
return CAIRO_STATUS_SUCCESS;
1197
static cairo_status_t
1198
_gpi_close_path (void *closure)
1200
gpi_t *gpi = closure;
1202
gpi->close_path (gpi->closure);
1204
gpi->current_point.x = 0;
1205
gpi->current_point.y = 0;
1207
return CAIRO_STATUS_SUCCESS;
1210
/* It's OK for curve_path to be NULL. In that case, all curves in the
1211
path will be decomposed into one or more calls to the line_to
1212
function, (according to the current tolerance). */
1214
_cairo_gstate_interpret_path (cairo_gstate_t *gstate,
1215
cairo_move_to_func_t *move_to,
1216
cairo_line_to_func_t *line_to,
1217
cairo_curve_to_func_t *curve_to,
1218
cairo_close_path_func_t *close_path,
1224
/* Anything we want from gstate must be copied. We must not retain
1225
pointers into gstate. */
1226
_cairo_path_init_copy (&path, &gstate->path);
1228
cairo_matrix_copy (&gpi.ctm_inverse, &gstate->ctm_inverse);
1229
gpi.tolerance = gstate->tolerance;
1231
gpi.move_to = move_to;
1232
gpi.line_to = line_to;
1233
gpi.curve_to = curve_to;
1234
gpi.close_path = close_path;
1235
gpi.closure = closure;
1237
gpi.current_point.x = 0;
1238
gpi.current_point.y = 0;
1240
return _cairo_path_interpret (&path,
1241
CAIRO_DIRECTION_FORWARD,
1249
/* This function modifies the pattern and the state of the pattern surface it
1250
may contain. The pattern surface will be restored to its orignal state
1251
when the pattern is destroyed. The appropriate way is to pass a copy of
1252
the original pattern to this function just before the pattern should be
1253
used and destroy the copy when done. */
1254
static cairo_status_t
1255
_cairo_gstate_create_pattern (cairo_gstate_t *gstate,
1256
cairo_pattern_t *pattern,
1257
cairo_box_t *extents)
1259
cairo_int_status_t status;
1261
if (gstate->surface == NULL) {
1262
_cairo_pattern_fini (pattern);
1263
return CAIRO_STATUS_NO_TARGET_SURFACE;
1266
if (pattern->type == CAIRO_PATTERN_LINEAR ||
1267
pattern->type == CAIRO_PATTERN_RADIAL) {
1268
if (pattern->n_stops < 2) {
1269
pattern->type = CAIRO_PATTERN_SOLID;
1271
if (pattern->n_stops)
1272
pattern->color = pattern->stops->color;
1276
_cairo_pattern_set_alpha (pattern, gstate->alpha);
1277
_cairo_pattern_transform (pattern, &gstate->ctm_inverse);
1279
_cairo_pattern_set_source_offset (pattern,
1280
gstate->pattern_offset.x,
1281
gstate->pattern_offset.y);
1283
status = _cairo_surface_create_pattern (gstate->surface, pattern, extents);
1285
_cairo_pattern_fini (pattern);
1289
if (pattern->type == CAIRO_PATTERN_SURFACE)
1290
_cairo_pattern_prepare_surface (pattern);
1292
return CAIRO_STATUS_SUCCESS;
1296
_cairo_gstate_stroke (cairo_gstate_t *gstate)
1298
cairo_status_t status;
1299
cairo_traps_t traps;
1301
if (gstate->line_width <= 0.0)
1302
return CAIRO_STATUS_SUCCESS;
1304
_cairo_pen_init (&gstate->pen_regular, gstate->line_width / 2.0, gstate);
1306
_cairo_traps_init (&traps);
1308
status = _cairo_path_stroke_to_traps (&gstate->path, gstate, &traps);
1310
_cairo_traps_fini (&traps);
1314
_cairo_gstate_clip_and_composite_trapezoids (gstate,
1320
_cairo_traps_fini (&traps);
1322
_cairo_gstate_new_path (gstate);
1324
return CAIRO_STATUS_SUCCESS;
1328
_cairo_gstate_in_stroke (cairo_gstate_t *gstate,
1333
cairo_status_t status = CAIRO_STATUS_SUCCESS;
1334
cairo_traps_t traps;
1336
cairo_matrix_transform_point (&gstate->ctm, &x, &y);
1338
_cairo_pen_init (&gstate->pen_regular, gstate->line_width / 2.0, gstate);
1340
_cairo_traps_init (&traps);
1342
status = _cairo_path_stroke_to_traps (&gstate->path, gstate, &traps);
1346
*inside_ret = _cairo_traps_contain (&traps, x, y);
1349
_cairo_traps_fini (&traps);
1354
/* Warning: This call modifies the coordinates of traps */
1355
static cairo_status_t
1356
_cairo_gstate_clip_and_composite_trapezoids (cairo_gstate_t *gstate,
1357
cairo_pattern_t *src,
1358
cairo_operator_t operator,
1359
cairo_surface_t *dst,
1360
cairo_traps_t *traps)
1362
cairo_status_t status;
1363
cairo_pattern_t pattern;
1364
cairo_box_t extents;
1366
if (traps->num_traps == 0)
1367
return CAIRO_STATUS_SUCCESS;
1369
if (gstate->clip.surface) {
1370
cairo_fixed_t xoff, yoff;
1371
cairo_trapezoid_t *t;
1373
cairo_surface_t *intermediate;
1374
cairo_color_t empty_color;
1376
_cairo_color_init (&empty_color);
1377
_cairo_color_set_alpha (&empty_color, 0.);
1378
intermediate = _cairo_surface_create_similar_solid (gstate->clip.surface,
1381
gstate->clip.height,
1383
if (intermediate == NULL) {
1384
status = CAIRO_STATUS_NO_MEMORY;
1388
/* Ugh. The cairo_composite/(Render) interface doesn't allow
1389
an offset for the trapezoids. Need to manually shift all
1390
the coordinates to align with the offset origin of the clip
1392
xoff = _cairo_fixed_from_double (gstate->clip.x);
1393
yoff = _cairo_fixed_from_double (gstate->clip.y);
1394
for (i=0, t=traps->traps; i < traps->num_traps; i++, t++) {
1397
t->left.p1.x -= xoff;
1398
t->left.p1.y -= yoff;
1399
t->left.p2.x -= xoff;
1400
t->left.p2.y -= yoff;
1401
t->right.p1.x -= xoff;
1402
t->right.p1.y -= yoff;
1403
t->right.p2.x -= xoff;
1404
t->right.p2.y -= yoff;
1407
_cairo_pattern_init_solid (&pattern, 1.0, 1.0, 1.0);
1408
_cairo_pattern_set_alpha (&pattern, 1.0);
1410
_cairo_traps_extents (traps, &extents);
1411
status = _cairo_gstate_create_pattern (gstate, &pattern, &extents);
1415
status = _cairo_surface_composite_trapezoids (CAIRO_OPERATOR_ADD,
1416
pattern.source, intermediate,
1423
status = _cairo_surface_composite (CAIRO_OPERATOR_IN,
1424
gstate->clip.surface,
1428
gstate->clip.width, gstate->clip.height);
1432
_cairo_pattern_fini (&pattern);
1434
_cairo_pattern_init_copy (&pattern, src);
1436
extents.p1.x = _cairo_fixed_from_int (gstate->clip.x);
1437
extents.p1.y = _cairo_fixed_from_int (gstate->clip.y);
1439
_cairo_fixed_from_int (gstate->clip.x + gstate->clip.width);
1441
_cairo_fixed_from_int (gstate->clip.y + gstate->clip.height);
1442
status = _cairo_gstate_create_pattern (gstate, &pattern, &extents);
1446
status = _cairo_surface_composite (operator,
1447
pattern.source, intermediate, dst,
1453
gstate->clip.height);
1456
cairo_surface_destroy (intermediate);
1458
_cairo_pattern_fini (&pattern);
1467
if (traps->traps[0].left.p1.y < traps->traps[0].left.p2.y) {
1468
xoff = _cairo_fixed_to_double (traps->traps[0].left.p1.x);
1469
yoff = _cairo_fixed_to_double (traps->traps[0].left.p1.y);
1471
xoff = _cairo_fixed_to_double (traps->traps[0].left.p2.x);
1472
yoff = _cairo_fixed_to_double (traps->traps[0].left.p2.y);
1475
_cairo_pattern_init_copy (&pattern, src);
1477
_cairo_traps_extents (traps, &extents);
1478
status = _cairo_gstate_create_pattern (gstate, &pattern, &extents);
1482
status = _cairo_surface_composite_trapezoids (gstate->operator,
1483
pattern.source, dst,
1484
xoff - pattern.source_offset.x,
1485
yoff - pattern.source_offset.y,
1489
_cairo_pattern_fini (&pattern);
1495
return CAIRO_STATUS_SUCCESS;
1499
_cairo_gstate_fill (cairo_gstate_t *gstate)
1501
cairo_status_t status;
1502
cairo_traps_t traps;
1504
_cairo_traps_init (&traps);
1506
status = _cairo_path_fill_to_traps (&gstate->path, gstate, &traps);
1508
_cairo_traps_fini (&traps);
1512
_cairo_gstate_clip_and_composite_trapezoids (gstate,
1518
_cairo_traps_fini (&traps);
1520
_cairo_gstate_new_path (gstate);
1522
return CAIRO_STATUS_SUCCESS;
1526
_cairo_gstate_in_fill (cairo_gstate_t *gstate,
1531
cairo_status_t status = CAIRO_STATUS_SUCCESS;
1532
cairo_traps_t traps;
1534
cairo_matrix_transform_point (&gstate->ctm, &x, &y);
1536
_cairo_traps_init (&traps);
1538
status = _cairo_path_fill_to_traps (&gstate->path, gstate, &traps);
1542
*inside_ret = _cairo_traps_contain (&traps, x, y);
1545
_cairo_traps_fini (&traps);
1551
_cairo_gstate_copy_page (cairo_gstate_t *gstate)
1553
if (gstate->surface == NULL)
1554
return CAIRO_STATUS_NO_TARGET_SURFACE;
1556
return _cairo_surface_copy_page (gstate->surface);
1560
_cairo_gstate_show_page (cairo_gstate_t *gstate)
1562
if (gstate->surface == NULL)
1563
return CAIRO_STATUS_NO_TARGET_SURFACE;
1565
return _cairo_surface_show_page (gstate->surface);
1569
_cairo_gstate_stroke_extents (cairo_gstate_t *gstate,
1570
double *x1, double *y1,
1571
double *x2, double *y2)
1573
cairo_status_t status;
1574
cairo_traps_t traps;
1575
cairo_box_t extents;
1577
_cairo_traps_init (&traps);
1579
status = _cairo_path_stroke_to_traps (&gstate->path, gstate, &traps);
1583
_cairo_traps_extents (&traps, &extents);
1585
*x1 = _cairo_fixed_to_double (extents.p1.x);
1586
*y1 = _cairo_fixed_to_double (extents.p1.y);
1587
*x2 = _cairo_fixed_to_double (extents.p2.x);
1588
*y2 = _cairo_fixed_to_double (extents.p2.y);
1590
cairo_matrix_transform_point (&gstate->ctm_inverse, x1, y1);
1591
cairo_matrix_transform_point (&gstate->ctm_inverse, x2, y2);
1594
_cairo_traps_fini (&traps);
1600
_cairo_gstate_fill_extents (cairo_gstate_t *gstate,
1601
double *x1, double *y1,
1602
double *x2, double *y2)
1604
cairo_status_t status;
1605
cairo_traps_t traps;
1606
cairo_box_t extents;
1608
_cairo_traps_init (&traps);
1610
status = _cairo_path_fill_to_traps (&gstate->path, gstate, &traps);
1614
_cairo_traps_extents (&traps, &extents);
1616
*x1 = _cairo_fixed_to_double (extents.p1.x);
1617
*y1 = _cairo_fixed_to_double (extents.p1.y);
1618
*x2 = _cairo_fixed_to_double (extents.p2.x);
1619
*y2 = _cairo_fixed_to_double (extents.p2.y);
1621
cairo_matrix_transform_point (&gstate->ctm_inverse, x1, y1);
1622
cairo_matrix_transform_point (&gstate->ctm_inverse, x2, y2);
1625
_cairo_traps_fini (&traps);
1631
_cairo_gstate_init_clip (cairo_gstate_t *gstate)
1633
/* destroy any existing clip-region artifacts */
1634
if (gstate->clip.surface)
1635
cairo_surface_destroy (gstate->clip.surface);
1636
gstate->clip.surface = NULL;
1638
if (gstate->clip.region)
1639
pixman_region_destroy (gstate->clip.region);
1640
gstate->clip.region = NULL;
1642
/* reset the surface's clip to the whole surface */
1643
_cairo_surface_set_clip_region (gstate->surface,
1644
gstate->clip.region);
1646
return CAIRO_STATUS_SUCCESS;
1650
extract_transformed_rectangle(cairo_matrix_t *mat,
1652
pixman_box16_t *box)
1654
#define CAIRO_FIXED_IS_INTEGER(x) (((x) & 0xFFFF) == 0)
1655
#define CAIRO_FIXED_INTEGER_PART(x) ((x) >> 16)
1657
double a, b, c, d, tx, ty;
1660
st = cairo_matrix_get_affine (mat, &a, &b, &c, &d, &tx, &ty);
1661
if (!(st == CAIRO_STATUS_SUCCESS && b == 0. && c == 0.))
1664
if (tr->num_traps == 1
1665
&& tr->traps[0].left.p1.x == tr->traps[0].left.p2.x
1666
&& tr->traps[0].right.p1.x == tr->traps[0].right.p2.x
1667
&& tr->traps[0].left.p1.y == tr->traps[0].right.p1.y
1668
&& tr->traps[0].left.p2.y == tr->traps[0].right.p2.y
1669
&& CAIRO_FIXED_IS_INTEGER(tr->traps[0].left.p1.x)
1670
&& CAIRO_FIXED_IS_INTEGER(tr->traps[0].left.p1.y)
1671
&& CAIRO_FIXED_IS_INTEGER(tr->traps[0].left.p2.x)
1672
&& CAIRO_FIXED_IS_INTEGER(tr->traps[0].left.p2.y)
1673
&& CAIRO_FIXED_IS_INTEGER(tr->traps[0].right.p1.x)
1674
&& CAIRO_FIXED_IS_INTEGER(tr->traps[0].right.p1.y)
1675
&& CAIRO_FIXED_IS_INTEGER(tr->traps[0].right.p2.x)
1676
&& CAIRO_FIXED_IS_INTEGER(tr->traps[0].right.p2.y)) {
1678
box->x1 = (short) CAIRO_FIXED_INTEGER_PART(tr->traps[0].left.p1.x);
1679
box->x2 = (short) CAIRO_FIXED_INTEGER_PART(tr->traps[0].right.p1.x);
1680
box->y1 = (short) CAIRO_FIXED_INTEGER_PART(tr->traps[0].left.p1.y);
1681
box->y2 = (short) CAIRO_FIXED_INTEGER_PART(tr->traps[0].left.p2.y);
1686
#undef CAIRO_FIXED_IS_INTEGER
1687
#undef CAIRO_FIXED_INTEGER_PART
1691
_cairo_gstate_clip (cairo_gstate_t *gstate)
1693
cairo_status_t status;
1694
cairo_pattern_t pattern;
1695
cairo_traps_t traps;
1696
cairo_color_t white_color;
1699
/* Fill the clip region as traps. */
1701
_cairo_traps_init (&traps);
1702
status = _cairo_path_fill_to_traps (&gstate->path, gstate, &traps);
1704
_cairo_traps_fini (&traps);
1708
/* Check to see if we can represent these traps as a PixRegion. */
1710
if (extract_transformed_rectangle (&gstate->ctm, &traps, &box)) {
1712
pixman_region16_t *rect = NULL;
1713
pixman_region16_t *intersection = NULL;
1715
status = CAIRO_STATUS_SUCCESS;
1716
rect = pixman_region_create_simple (&box);
1719
status = CAIRO_STATUS_NO_MEMORY;
1723
if (gstate->clip.region == NULL) {
1724
gstate->clip.region = rect;
1726
intersection = pixman_region_create();
1727
if (pixman_region_intersect (intersection,
1728
gstate->clip.region, rect)
1729
== PIXMAN_REGION_STATUS_SUCCESS) {
1730
pixman_region_destroy (gstate->clip.region);
1731
gstate->clip.region = intersection;
1733
status = CAIRO_STATUS_NO_MEMORY;
1735
pixman_region_destroy (rect);
1739
status = _cairo_surface_set_clip_region (gstate->surface,
1740
gstate->clip.region);
1743
if (status != CAIRO_INT_STATUS_UNSUPPORTED) {
1744
_cairo_traps_fini (&traps);
1749
/* Otherwise represent the clip as a mask surface. */
1751
_cairo_color_init (&white_color);
1753
if (gstate->clip.surface == NULL) {
1754
double x1, y1, x2, y2;
1755
_cairo_path_bounds (&gstate->path,
1756
&x1, &y1, &x2, &y2);
1757
gstate->clip.x = floor (x1);
1758
gstate->clip.y = floor (y1);
1759
gstate->clip.width = ceil (x2 - gstate->clip.x);
1760
gstate->clip.height = ceil (y2 - gstate->clip.y);
1761
gstate->clip.surface =
1762
_cairo_surface_create_similar_solid (gstate->surface,
1765
gstate->clip.height,
1767
if (gstate->clip.surface == NULL)
1768
return CAIRO_STATUS_NO_MEMORY;
1771
_cairo_pattern_init_solid (&pattern, 1.0, 1.0, 1.0);
1772
_cairo_pattern_set_alpha (&pattern, 1.0);
1774
_cairo_gstate_clip_and_composite_trapezoids (gstate,
1777
gstate->clip.surface,
1780
_cairo_pattern_fini (&pattern);
1782
_cairo_traps_fini (&traps);
1788
_cairo_gstate_show_surface (cairo_gstate_t *gstate,
1789
cairo_surface_t *surface,
1793
cairo_status_t status;
1794
cairo_matrix_t user_to_image, image_to_user;
1795
cairo_matrix_t image_to_device, device_to_image;
1796
double device_x, device_y;
1797
double device_width, device_height;
1798
cairo_pattern_t pattern;
1799
cairo_box_t extents;
1801
cairo_surface_get_matrix (surface, &user_to_image);
1802
cairo_matrix_multiply (&device_to_image, &gstate->ctm_inverse, &user_to_image);
1803
cairo_surface_set_matrix (surface, &device_to_image);
1805
image_to_user = user_to_image;
1806
cairo_matrix_invert (&image_to_user);
1807
cairo_matrix_multiply (&image_to_device, &image_to_user, &gstate->ctm);
1809
_cairo_gstate_current_point (gstate, &device_x, &device_y);
1810
device_width = width;
1811
device_height = height;
1812
_cairo_matrix_transform_bounding_box (&image_to_device,
1813
&device_x, &device_y,
1814
&device_width, &device_height);
1816
_cairo_pattern_init (&pattern);
1818
if ((gstate->pattern->type != CAIRO_PATTERN_SOLID) ||
1819
(gstate->alpha != 1.0)) {
1820
/* I'm allowing any type of pattern for the mask right now.
1821
Maybe this is bad. Will allow for some cool effects though. */
1822
_cairo_pattern_init_copy (&pattern, gstate->pattern);
1823
extents.p1.x = _cairo_fixed_from_double (device_x);
1824
extents.p1.y = _cairo_fixed_from_double (device_y);
1825
extents.p2.x = _cairo_fixed_from_double (device_x + device_width);
1826
extents.p2.y = _cairo_fixed_from_double (device_y + device_height);
1827
status = _cairo_gstate_create_pattern (gstate, &pattern, &extents);
1832
/* XXX: The rendered size is sometimes 1 or 2 pixels short from
1833
what I expect. Need to fix this. */
1834
status = _cairo_surface_composite (gstate->operator,
1835
surface, pattern.source, gstate->surface,
1842
_cairo_pattern_fini (&pattern);
1844
/* restore the matrix originally in the surface */
1845
cairo_surface_set_matrix (surface, &user_to_image);
1850
return CAIRO_STATUS_SUCCESS;
1854
_cairo_gstate_select_font (cairo_gstate_t *gstate,
1856
cairo_font_slant_t slant,
1857
cairo_font_weight_t weight)
1859
if (gstate->font != NULL)
1860
cairo_font_destroy (gstate->font);
1862
gstate->font = _cairo_font_create (family, slant, weight);
1864
return CAIRO_STATUS_SUCCESS;
1868
_cairo_gstate_scale_font (cairo_gstate_t *gstate,
1871
return _cairo_font_scale (gstate->font, scale);
1875
_cairo_gstate_transform_font (cairo_gstate_t *gstate,
1876
cairo_matrix_t *matrix)
1878
return _cairo_font_transform (gstate->font, matrix);
1882
_cairo_gstate_current_font (cairo_gstate_t *gstate,
1883
cairo_font_t **font)
1885
*font = gstate->font;
1887
return CAIRO_STATUS_SUCCESS;
1891
_cairo_gstate_current_font_extents (cairo_gstate_t *gstate,
1892
cairo_font_extents_t *extents)
1894
cairo_int_status_t status;
1895
cairo_matrix_t saved_font_matrix;
1897
cairo_matrix_copy (&saved_font_matrix, &gstate->font->matrix);
1898
cairo_matrix_multiply (&gstate->font->matrix, &gstate->ctm, &gstate->font->matrix);
1900
status = _cairo_font_font_extents (gstate->font, extents);
1902
cairo_matrix_copy (&gstate->font->matrix, &saved_font_matrix);
1909
_cairo_gstate_set_font (cairo_gstate_t *gstate,
1912
if (gstate->font != NULL)
1913
cairo_font_destroy (gstate->font);
1914
gstate->font = font;
1915
cairo_font_reference (gstate->font);
1916
return CAIRO_STATUS_SUCCESS;
1920
_cairo_gstate_text_extents (cairo_gstate_t *gstate,
1921
const unsigned char *utf8,
1922
cairo_text_extents_t *extents)
1924
cairo_matrix_t saved_font_matrix;
1925
cairo_status_t status;
1926
double scale_x, scale_y;
1928
cairo_matrix_copy (&saved_font_matrix, &gstate->font->matrix);
1929
_cairo_matrix_compute_scale_factors (&gstate->ctm, &scale_x, &scale_y);
1930
cairo_matrix_scale (&gstate->font->matrix, scale_x, scale_y);
1932
status = _cairo_font_text_extents (gstate->font,
1935
cairo_matrix_copy (&gstate->font->matrix, &saved_font_matrix);
1937
extents->x_bearing /= scale_x;
1938
extents->y_bearing /= scale_y;
1939
extents->width /= scale_x;
1940
extents->height /= scale_y;
1941
extents->x_advance /= scale_x;
1942
extents->y_advance /= scale_y;
1948
_cairo_gstate_glyph_extents (cairo_gstate_t *gstate,
1949
cairo_glyph_t *glyphs,
1951
cairo_text_extents_t *extents)
1953
cairo_status_t status;
1954
cairo_matrix_t saved_font_matrix;
1955
double scale_x, scale_y;
1957
cairo_matrix_copy (&saved_font_matrix, &gstate->font->matrix);
1958
_cairo_matrix_compute_scale_factors (&gstate->ctm, &scale_x, &scale_y);
1959
cairo_matrix_scale (&gstate->font->matrix, scale_x, scale_y);
1961
status = _cairo_font_glyph_extents (gstate->font,
1965
cairo_matrix_copy (&gstate->font->matrix, &saved_font_matrix);
1967
extents->x_bearing /= scale_x;
1968
extents->y_bearing /= scale_y;
1969
extents->width /= scale_x;
1970
extents->height /= scale_y;
1971
extents->x_advance /= scale_x;
1972
extents->y_advance /= scale_y;
1978
_cairo_gstate_show_text (cairo_gstate_t *gstate,
1979
const unsigned char *utf8)
1981
cairo_status_t status;
1982
cairo_point_t point;
1984
cairo_matrix_t saved_font_matrix;
1985
cairo_pattern_t pattern;
1986
cairo_text_extents_t text_extents;
1987
cairo_box_t extents;
1989
status = _cairo_path_current_point (&gstate->path, &point);
1990
if (status == CAIRO_STATUS_NO_CURRENT_POINT) {
1993
cairo_matrix_transform_point (&gstate->ctm, &x, &y);
1995
x = _cairo_fixed_to_double (point.x);
1996
y = _cairo_fixed_to_double (point.y);
1999
cairo_matrix_copy (&saved_font_matrix, &gstate->font->matrix);
2000
cairo_matrix_multiply (&gstate->font->matrix, &gstate->ctm, &gstate->font->matrix);
2002
_cairo_pattern_init_copy (&pattern, gstate->pattern);
2004
status = _cairo_gstate_text_extents (gstate, utf8, &text_extents);
2008
extents.p1.x = _cairo_fixed_from_double (x);
2009
extents.p1.y = _cairo_fixed_from_double (y);
2010
extents.p2.x = _cairo_fixed_from_double (x + text_extents.width);
2011
extents.p2.y = _cairo_fixed_from_double (y + text_extents.height);
2012
status = _cairo_gstate_create_pattern (gstate, &pattern, &extents);
2016
status = _cairo_font_show_text (gstate->font,
2017
gstate->operator, pattern.source,
2018
gstate->surface, x, y, utf8);
2020
cairo_matrix_copy (&gstate->font->matrix, &saved_font_matrix);
2022
_cairo_pattern_fini (&pattern);
2028
_cairo_gstate_show_glyphs (cairo_gstate_t *gstate,
2029
cairo_glyph_t *glyphs,
2032
cairo_status_t status;
2033
cairo_matrix_t saved_font_matrix;
2035
cairo_glyph_t *transformed_glyphs = NULL;
2036
cairo_pattern_t pattern;
2037
cairo_text_extents_t text_extents;
2038
cairo_box_t extents;
2040
transformed_glyphs = malloc (num_glyphs * sizeof(cairo_glyph_t));
2041
if (transformed_glyphs == NULL)
2042
return CAIRO_STATUS_NO_MEMORY;
2044
for (i = 0; i < num_glyphs; ++i)
2046
transformed_glyphs[i] = glyphs[i];
2047
cairo_matrix_transform_point (&gstate->ctm,
2048
&(transformed_glyphs[i].x),
2049
&(transformed_glyphs[i].y));
2052
cairo_matrix_copy (&saved_font_matrix, &gstate->font->matrix);
2053
cairo_matrix_multiply (&gstate->font->matrix, &gstate->ctm, &gstate->font->matrix);
2055
_cairo_pattern_init_copy (&pattern, gstate->pattern);
2056
_cairo_gstate_glyph_extents (gstate, transformed_glyphs, num_glyphs,
2061
extents.p1.x = _cairo_fixed_from_double (transformed_glyphs[0].x);
2062
extents.p1.y = _cairo_fixed_from_double (transformed_glyphs[0].y);
2063
extents.p2.x = _cairo_fixed_from_double (transformed_glyphs[0].x +
2064
text_extents.width);
2065
extents.p2.y = _cairo_fixed_from_double (transformed_glyphs[0].y +
2066
text_extents.height);
2067
status = _cairo_gstate_create_pattern (gstate, &pattern, &extents);
2071
status = _cairo_font_show_glyphs (gstate->font,
2072
gstate->operator, pattern.source,
2074
transformed_glyphs, num_glyphs);
2076
cairo_matrix_copy (&gstate->font->matrix, &saved_font_matrix);
2078
_cairo_pattern_fini (&pattern);
2080
free (transformed_glyphs);
2087
_cairo_gstate_text_path (cairo_gstate_t *gstate,
2088
const unsigned char *utf8)
2090
cairo_status_t status;
2091
cairo_matrix_t saved_font_matrix;
2092
cairo_point_t point;
2095
status = _cairo_path_current_point (&gstate->path, &point);
2096
if (status == CAIRO_STATUS_NO_CURRENT_POINT) {
2099
cairo_matrix_transform_point (&gstate->ctm, &x, &y);
2101
x = _cairo_fixed_to_double (point.x);
2102
y = _cairo_fixed_to_double (point.y);
2105
cairo_matrix_copy (&saved_font_matrix, &gstate->font->matrix);
2106
cairo_matrix_multiply (&gstate->font->matrix, &gstate->ctm, &gstate->font->matrix);
2108
status = _cairo_font_text_path (gstate->font,
2113
cairo_matrix_copy (&gstate->font->matrix, &saved_font_matrix);
2120
_cairo_gstate_glyph_path (cairo_gstate_t *gstate,
2121
cairo_glyph_t *glyphs,
2124
cairo_status_t status;
2126
cairo_glyph_t *transformed_glyphs = NULL;
2127
cairo_matrix_t saved_font_matrix;
2129
transformed_glyphs = malloc (num_glyphs * sizeof(cairo_glyph_t));
2130
if (transformed_glyphs == NULL)
2131
return CAIRO_STATUS_NO_MEMORY;
2133
for (i = 0; i < num_glyphs; ++i)
2135
transformed_glyphs[i] = glyphs[i];
2136
cairo_matrix_transform_point (&gstate->ctm,
2137
&(transformed_glyphs[i].x),
2138
&(transformed_glyphs[i].y));
2141
cairo_matrix_copy (&saved_font_matrix, &gstate->font->matrix);
2142
cairo_matrix_multiply (&gstate->font->matrix, &gstate->ctm, &gstate->font->matrix);
2144
status = _cairo_font_glyph_path (gstate->font,
2145
transformed_glyphs, num_glyphs,
2148
cairo_matrix_copy (&gstate->font->matrix, &saved_font_matrix);
2150
free (transformed_glyphs);