Back to index

lightning-sunbird  0.9+nobinonly
cairo.c
Go to the documentation of this file.
00001 /* cairo - a vector graphics library with display and print output
00002  *
00003  * Copyright © 2002 University of Southern California
00004  * Copyright © 2005 Red Hat, Inc.
00005  *
00006  * This library is free software; you can redistribute it and/or
00007  * modify it either under the terms of the GNU Lesser General Public
00008  * License version 2.1 as published by the Free Software Foundation
00009  * (the "LGPL") or, at your option, under the terms of the Mozilla
00010  * Public License Version 1.1 (the "MPL"). If you do not alter this
00011  * notice, a recipient may use your version of this file under either
00012  * the MPL or the LGPL.
00013  *
00014  * You should have received a copy of the LGPL along with this library
00015  * in the file COPYING-LGPL-2.1; if not, write to the Free Software
00016  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
00017  * You should have received a copy of the MPL along with this library
00018  * in the file COPYING-MPL-1.1
00019  *
00020  * The contents of this file are subject to the Mozilla Public License
00021  * Version 1.1 (the "License"); you may not use this file except in
00022  * compliance with the License. You may obtain a copy of the License at
00023  * http://www.mozilla.org/MPL/
00024  *
00025  * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY
00026  * OF ANY KIND, either express or implied. See the LGPL or the MPL for
00027  * the specific language governing rights and limitations.
00028  *
00029  * The Original Code is the cairo graphics library.
00030  *
00031  * The Initial Developer of the Original Code is University of Southern
00032  * California.
00033  *
00034  * Contributor(s):
00035  *     Carl D. Worth <cworth@cworth.org>
00036  */
00037 
00038 #include "cairoint.h"
00039 #include "cairo-private.h"
00040 
00041 #include "cairo-arc-private.h"
00042 #include "cairo-path-data-private.h"
00043 
00044 #define CAIRO_TOLERANCE_MINIMUM    0.0002 /* We're limited by 16 bits of sub-pixel precision */
00045 
00046 static const cairo_t cairo_nil = {
00047   (unsigned int)-1,         /* ref_count */
00048   CAIRO_STATUS_NO_MEMORY,   /* status */
00049   {                         /* path */
00050     NULL, NULL,                    /* op_buf_head, op_buf_tail */
00051     NULL, NULL,                    /* arg_buf_head, arg_buf_tail */
00052     { 0, 0 },               /* last_move_point */
00053     { 0, 0 },               /* current point */
00054     FALSE,                  /* has_current_point */
00055   },
00056   NULL                      /* gstate */
00057 };
00058 
00059 #include <assert.h>
00060 
00061 /* This has to be updated whenever cairo_status_t is extended.  That's
00062  * a bit of a pain, but it should be easy to always catch as long as
00063  * one adds a new test case to test a trigger of the new status value.
00064  */
00065 #define CAIRO_STATUS_LAST_STATUS CAIRO_STATUS_INVALID_DASH
00066 
00082 void
00083 _cairo_error (cairo_status_t status)
00084 {
00085     assert (status > CAIRO_STATUS_SUCCESS &&
00086            status <= CAIRO_STATUS_LAST_STATUS);
00087 }
00088 
00105 static void
00106 _cairo_set_error (cairo_t *cr, cairo_status_t status)
00107 {
00108     /* Don't overwrite an existing error. This preserves the first
00109      * error, which is the most significant. It also avoids attempting
00110      * to write to read-only data (eg. from a nil cairo_t). */
00111     if (cr->status == CAIRO_STATUS_SUCCESS)
00112        cr->status = status;
00113 
00114     _cairo_error (status);
00115 }
00116 
00136 int
00137 cairo_version (void)
00138 {
00139     return CAIRO_VERSION;
00140 }
00141 
00153 const char*
00154 cairo_version_string (void)
00155 {
00156     return CAIRO_VERSION_STRING;
00157 }
00158 
00182 cairo_t *
00183 cairo_create (cairo_surface_t *target)
00184 {
00185     cairo_t *cr;
00186 
00187     cr = malloc (sizeof (cairo_t));
00188     if (cr == NULL)
00189        return (cairo_t *) &cairo_nil;
00190 
00191     cr->ref_count = 1;
00192 
00193     cr->status = CAIRO_STATUS_SUCCESS;
00194 
00195     _cairo_path_fixed_init (&cr->path);
00196 
00197     if (target == NULL) {
00198        cr->gstate = NULL;
00199        _cairo_set_error (cr, CAIRO_STATUS_NULL_POINTER);
00200        return cr;
00201     }
00202 
00203     cr->gstate = _cairo_gstate_create (target);
00204     if (cr->gstate == NULL)
00205        _cairo_set_error (cr, CAIRO_STATUS_NO_MEMORY);
00206 
00207     return cr;
00208 }
00209 
00220 cairo_t *
00221 cairo_reference (cairo_t *cr)
00222 {
00223     if (cr->ref_count == (unsigned int)-1)
00224        return cr;
00225 
00226     assert (cr->ref_count > 0);
00227     
00228     cr->ref_count++;
00229 
00230     return cr;
00231 }
00232 
00241 void
00242 cairo_destroy (cairo_t *cr)
00243 {
00244     if (cr->ref_count == (unsigned int)-1)
00245        return;
00246 
00247     assert (cr->ref_count > 0);
00248     
00249     cr->ref_count--;
00250     if (cr->ref_count)
00251        return;
00252 
00253     while (cr->gstate) {
00254        cairo_gstate_t *tmp = cr->gstate;
00255        cr->gstate = tmp->next;
00256 
00257        _cairo_gstate_destroy (tmp);
00258     }
00259 
00260     _cairo_path_fixed_fini (&cr->path);
00261 
00262     free (cr);
00263 }
00264 
00281 void
00282 cairo_save (cairo_t *cr)
00283 {
00284     cairo_gstate_t *top;
00285 
00286     if (cr->status)
00287        return;
00288 
00289     top = _cairo_gstate_clone (cr->gstate);
00290 
00291     if (top == NULL) {
00292        _cairo_set_error (cr, CAIRO_STATUS_NO_MEMORY);
00293        return;
00294     }
00295 
00296     top->next = cr->gstate;
00297     cr->gstate = top;
00298 }
00299 slim_hidden_def(cairo_save);
00300 
00309 void
00310 cairo_restore (cairo_t *cr)
00311 {
00312     cairo_gstate_t *top;
00313 
00314     if (cr->status)
00315        return;
00316 
00317     top = cr->gstate;
00318     cr->gstate = top->next;
00319 
00320     _cairo_gstate_destroy (top);
00321 
00322     if (cr->gstate == NULL)
00323        _cairo_set_error (cr, CAIRO_STATUS_INVALID_RESTORE);
00324 }
00325 slim_hidden_def(cairo_restore);
00326 
00327 /* XXX: I want to rethink this API
00328 void
00329 cairo_push_group (cairo_t *cr)
00330 {
00331     if (cr->status)
00332        return;
00333 
00334     cr->status = cairoPush (cr);
00335     if (cr->status)
00336        return;
00337 
00338     cr->status = _cairo_gstate_begin_group (cr->gstate);
00339 }
00340 
00341 void
00342 cairo_pop_group (cairo_t *cr)
00343 {
00344     if (cr->status)
00345        return;
00346 
00347     cr->status = _cairo_gstate_end_group (cr->gstate);
00348     if (cr->status)
00349        return;
00350 
00351     cr->status = cairoPop (cr);
00352 }
00353 */
00354 
00368 void
00369 cairo_set_operator (cairo_t *cr, cairo_operator_t op)
00370 {
00371     if (cr->status)
00372        return;
00373 
00374     cr->status = _cairo_gstate_set_operator (cr->gstate, op);
00375     if (cr->status)
00376        _cairo_set_error (cr, cr->status);
00377 }
00378 
00394 void
00395 cairo_set_source_rgb (cairo_t *cr, double red, double green, double blue)
00396 {
00397     cairo_pattern_t *pattern;
00398 
00399     if (cr->status)
00400        return;
00401 
00402     pattern = cairo_pattern_create_rgb (red, green, blue);
00403     cairo_set_source (cr, pattern);
00404     cairo_pattern_destroy (pattern);
00405 }
00406 
00423 void
00424 cairo_set_source_rgba (cairo_t *cr,
00425                      double red, double green, double blue,
00426                      double alpha)
00427 {
00428     cairo_pattern_t *pattern;
00429 
00430     if (cr->status)
00431        return;
00432 
00433     pattern = cairo_pattern_create_rgba (red, green, blue, alpha);
00434     cairo_set_source (cr, pattern);
00435     cairo_pattern_destroy (pattern);
00436 }
00437 
00461 void
00462 cairo_set_source_surface (cairo_t    *cr,
00463                        cairo_surface_t *surface,
00464                        double         x,
00465                        double         y)
00466 {
00467     cairo_pattern_t *pattern;
00468     cairo_matrix_t matrix;
00469 
00470     if (cr->status)
00471        return;
00472 
00473     pattern = cairo_pattern_create_for_surface (surface);
00474 
00475     cairo_matrix_init_translate (&matrix, -x, -y);
00476     cairo_pattern_set_matrix (pattern, &matrix);
00477 
00478     cairo_set_source (cr, pattern);
00479     cairo_pattern_destroy (pattern);
00480 }
00481 
00501 void
00502 cairo_set_source (cairo_t *cr, cairo_pattern_t *source)
00503 {
00504     if (cr->status)
00505        return;
00506 
00507     if (source == NULL) {
00508        _cairo_set_error (cr, CAIRO_STATUS_NULL_POINTER);
00509        return;
00510     }
00511 
00512     if (source->status) {
00513        _cairo_set_error (cr, source->status);
00514        return;
00515     }
00516 
00517     cr->status = _cairo_gstate_set_source (cr->gstate, source);
00518     if (cr->status)
00519        _cairo_set_error (cr, cr->status);
00520 }
00521 
00532 cairo_pattern_t *
00533 cairo_get_source (cairo_t *cr)
00534 {
00535     if (cr->status)
00536        return (cairo_pattern_t*) &cairo_pattern_nil.base;
00537 
00538     return _cairo_gstate_get_source (cr->gstate);
00539 }
00540 
00554 void
00555 cairo_set_tolerance (cairo_t *cr, double tolerance)
00556 {
00557     if (cr->status)
00558        return;
00559 
00560     _cairo_restrict_value (&tolerance, CAIRO_TOLERANCE_MINIMUM, tolerance);
00561 
00562     cr->status = _cairo_gstate_set_tolerance (cr->gstate, tolerance);
00563     if (cr->status)
00564        _cairo_set_error (cr, cr->status);
00565 }
00566 
00580 void
00581 cairo_set_antialias (cairo_t *cr, cairo_antialias_t antialias)
00582 {
00583     if (cr->status) 
00584        return;
00585 
00586     cr->status = _cairo_gstate_set_antialias (cr->gstate, antialias);
00587     if (cr->status)
00588        _cairo_set_error (cr, cr->status);
00589 }
00590 
00602 void
00603 cairo_set_fill_rule (cairo_t *cr, cairo_fill_rule_t fill_rule)
00604 {
00605     if (cr->status)
00606        return;
00607 
00608     cr->status = _cairo_gstate_set_fill_rule (cr->gstate, fill_rule);
00609     if (cr->status)
00610        _cairo_set_error (cr, cr->status);
00611 }
00612 
00627 void
00628 cairo_set_line_width (cairo_t *cr, double width)
00629 {
00630     if (cr->status)
00631        return;
00632 
00633     _cairo_restrict_value (&width, 0.0, width);
00634 
00635     cr->status = _cairo_gstate_set_line_width (cr->gstate, width);
00636     if (cr->status)
00637        _cairo_set_error (cr, cr->status);
00638 }
00639 
00654 void
00655 cairo_set_line_cap (cairo_t *cr, cairo_line_cap_t line_cap)
00656 {
00657     if (cr->status)
00658        return;
00659 
00660     cr->status = _cairo_gstate_set_line_cap (cr->gstate, line_cap);
00661     if (cr->status)
00662        _cairo_set_error (cr, cr->status);
00663 }
00664 
00679 void
00680 cairo_set_line_join (cairo_t *cr, cairo_line_join_t line_join)
00681 {
00682     if (cr->status)
00683        return;
00684 
00685     cr->status = _cairo_gstate_set_line_join (cr->gstate, line_join);
00686     if (cr->status)
00687        _cairo_set_error (cr, cr->status);
00688 }
00689 
00713 void
00714 cairo_set_dash (cairo_t     *cr,
00715               double *dashes,
00716               int     num_dashes,
00717               double  offset)
00718 {
00719     if (cr->status)
00720        return;
00721 
00722     cr->status = _cairo_gstate_set_dash (cr->gstate,
00723                                     dashes, num_dashes, offset);
00724     if (cr->status)
00725        _cairo_set_error (cr, cr->status);
00726 }
00727 
00728 void
00729 cairo_set_miter_limit (cairo_t *cr, double limit)
00730 {
00731     if (cr->status)
00732        return;
00733 
00734     cr->status = _cairo_gstate_set_miter_limit (cr->gstate, limit);
00735     if (cr->status)
00736        _cairo_set_error (cr, cr->status);
00737 }
00738 
00739 
00752 void
00753 cairo_translate (cairo_t *cr, double tx, double ty)
00754 {
00755     if (cr->status)
00756        return;
00757 
00758     cr->status = _cairo_gstate_translate (cr->gstate, tx, ty);
00759     if (cr->status)
00760        _cairo_set_error (cr, cr->status);
00761 }
00762 
00774 void
00775 cairo_scale (cairo_t *cr, double sx, double sy)
00776 {
00777     if (cr->status)
00778        return;
00779 
00780     cr->status = _cairo_gstate_scale (cr->gstate, sx, sy);
00781     if (cr->status)
00782        _cairo_set_error (cr, cr->status);
00783 }
00784 
00785 
00798 void
00799 cairo_rotate (cairo_t *cr, double angle)
00800 {
00801     if (cr->status)
00802        return;
00803 
00804     cr->status = _cairo_gstate_rotate (cr->gstate, angle);
00805     if (cr->status)
00806        _cairo_set_error (cr, cr->status);
00807 }
00808 
00818 void
00819 cairo_transform (cairo_t          *cr,
00820                const cairo_matrix_t *matrix)
00821 {
00822     if (cr->status)
00823        return;
00824 
00825     cr->status = _cairo_gstate_transform (cr->gstate, matrix);
00826     if (cr->status)
00827        _cairo_set_error (cr, cr->status);
00828 }
00829 
00838 void
00839 cairo_set_matrix (cairo_t          *cr,
00840                 const cairo_matrix_t *matrix)
00841 {
00842     if (cr->status)
00843        return;
00844 
00845     cr->status = _cairo_gstate_set_matrix (cr->gstate, matrix);
00846     if (cr->status)
00847        _cairo_set_error (cr, cr->status);
00848 }
00849 
00859 void
00860 cairo_identity_matrix (cairo_t *cr)
00861 {
00862     if (cr->status)
00863        return;
00864 
00865     cr->status = _cairo_gstate_identity_matrix (cr->gstate);
00866     if (cr->status)
00867        _cairo_set_error (cr, cr->status);
00868 }
00869 
00880 void
00881 cairo_user_to_device (cairo_t *cr, double *x, double *y)
00882 {
00883     if (cr->status)
00884        return;
00885 
00886     cr->status = _cairo_gstate_user_to_device (cr->gstate, x, y);
00887     if (cr->status)
00888        _cairo_set_error (cr, cr->status);
00889 }
00890 
00902 void
00903 cairo_user_to_device_distance (cairo_t *cr, double *dx, double *dy)
00904 {
00905     if (cr->status)
00906        return;
00907 
00908     cr->status = _cairo_gstate_user_to_device_distance (cr->gstate, dx, dy);
00909     if (cr->status)
00910        _cairo_set_error (cr, cr->status);
00911 }
00912 
00923 void
00924 cairo_device_to_user (cairo_t *cr, double *x, double *y)
00925 {
00926     if (cr->status)
00927        return;
00928 
00929     cr->status = _cairo_gstate_device_to_user (cr->gstate, x, y);
00930     if (cr->status)
00931        _cairo_set_error (cr, cr->status);
00932 }
00933 
00945 void
00946 cairo_device_to_user_distance (cairo_t *cr, double *dx, double *dy)
00947 {
00948     if (cr->status)
00949        return;
00950 
00951     cr->status = _cairo_gstate_device_to_user_distance (cr->gstate, dx, dy);
00952     if (cr->status)
00953        _cairo_set_error (cr, cr->status);
00954 }
00955 
00963 void
00964 cairo_new_path (cairo_t *cr)
00965 {
00966     if (cr->status)
00967        return;
00968 
00969     _cairo_path_fixed_fini (&cr->path);
00970 }
00971 slim_hidden_def(cairo_new_path);
00972 
00982 void
00983 cairo_move_to (cairo_t *cr, double x, double y)
00984 {
00985     cairo_fixed_t x_fixed, y_fixed;
00986 
00987     if (cr->status)
00988        return;
00989 
00990     _cairo_gstate_user_to_backend (cr->gstate, &x, &y);
00991     x_fixed = _cairo_fixed_from_double (x);
00992     y_fixed = _cairo_fixed_from_double (y);
00993 
00994     cr->status = _cairo_path_fixed_move_to (&cr->path, x_fixed, y_fixed);
00995     if (cr->status)
00996        _cairo_set_error (cr, cr->status);
00997 }
00998 slim_hidden_def(cairo_move_to);
00999 
01010 void
01011 cairo_line_to (cairo_t *cr, double x, double y)
01012 {
01013     cairo_fixed_t x_fixed, y_fixed;
01014 
01015     if (cr->status)
01016        return;
01017 
01018     _cairo_gstate_user_to_backend (cr->gstate, &x, &y);
01019     x_fixed = _cairo_fixed_from_double (x);
01020     y_fixed = _cairo_fixed_from_double (y);
01021 
01022     cr->status = _cairo_path_fixed_line_to (&cr->path, x_fixed, y_fixed);
01023     if (cr->status)
01024        _cairo_set_error (cr, cr->status);
01025 }
01026 
01042 void
01043 cairo_curve_to (cairo_t *cr,
01044               double x1, double y1,
01045               double x2, double y2,
01046               double x3, double y3)
01047 {
01048     cairo_fixed_t x1_fixed, y1_fixed;
01049     cairo_fixed_t x2_fixed, y2_fixed;
01050     cairo_fixed_t x3_fixed, y3_fixed;
01051        
01052     if (cr->status)
01053        return;
01054 
01055     _cairo_gstate_user_to_backend (cr->gstate, &x1, &y1);
01056     _cairo_gstate_user_to_backend (cr->gstate, &x2, &y2);
01057     _cairo_gstate_user_to_backend (cr->gstate, &x3, &y3);
01058 
01059     x1_fixed = _cairo_fixed_from_double (x1);
01060     y1_fixed = _cairo_fixed_from_double (y1);
01061 
01062     x2_fixed = _cairo_fixed_from_double (x2);
01063     y2_fixed = _cairo_fixed_from_double (y2);
01064 
01065     x3_fixed = _cairo_fixed_from_double (x3);
01066     y3_fixed = _cairo_fixed_from_double (y3);
01067 
01068     cr->status = _cairo_path_fixed_curve_to (&cr->path,
01069                                         x1_fixed, y1_fixed,
01070                                         x2_fixed, y2_fixed,
01071                                         x3_fixed, y3_fixed);
01072     if (cr->status)
01073        _cairo_set_error (cr, cr->status);
01074 }
01075 
01122 void
01123 cairo_arc (cairo_t *cr,
01124           double xc, double yc,
01125           double radius,
01126           double angle1, double angle2)
01127 {
01128     if (cr->status)
01129        return;
01130 
01131     /* Do nothing, successfully, if radius is <= 0 */
01132     if (radius <= 0.0)
01133        return;
01134 
01135     while (angle2 < angle1)
01136        angle2 += 2 * M_PI;
01137 
01138     cairo_line_to (cr,
01139                  xc + radius * cos (angle1),
01140                  yc + radius * sin (angle1));
01141 
01142     _cairo_arc_path (cr, xc, yc, radius,
01143                    angle1, angle2);
01144 }
01145 
01164 void
01165 cairo_arc_negative (cairo_t *cr,
01166                   double xc, double yc,
01167                   double radius,
01168                   double angle1, double angle2)
01169 {
01170     if (cr->status)
01171        return;
01172 
01173     /* Do nothing, successfully, if radius is <= 0 */
01174     if (radius <= 0.0)
01175        return;
01176 
01177     while (angle2 > angle1)
01178        angle2 -= 2 * M_PI;
01179 
01180     cairo_line_to (cr,
01181                  xc + radius * cos (angle1),
01182                  yc + radius * sin (angle1));
01183 
01184      _cairo_arc_path_negative (cr, xc, yc, radius,
01185                             angle1, angle2);
01186 }
01187 
01188 /* XXX: NYI
01189 void
01190 cairo_arc_to (cairo_t *cr,
01191              double x1, double y1,
01192              double x2, double y2,
01193              double radius)
01194 {
01195     if (cr->status)
01196        return;
01197 
01198     cr->status = _cairo_gstate_arc_to (cr->gstate,
01199                                    x1, y1,
01200                                    x2, y2,
01201                                    radius);
01202 }
01203 */
01204 
01217 void
01218 cairo_rel_move_to (cairo_t *cr, double dx, double dy)
01219 {
01220     cairo_fixed_t dx_fixed, dy_fixed;
01221 
01222     if (cr->status) 
01223        return;
01224 
01225     _cairo_gstate_user_to_device_distance (cr->gstate, &dx, &dy);
01226     dx_fixed = _cairo_fixed_from_double (dx);
01227     dy_fixed = _cairo_fixed_from_double (dy);
01228 
01229     cr->status = _cairo_path_fixed_rel_move_to (&cr->path, dx_fixed, dy_fixed);
01230     if (cr->status)
01231        _cairo_set_error (cr, cr->status);
01232 }
01233 
01248 void
01249 cairo_rel_line_to (cairo_t *cr, double dx, double dy)
01250 {
01251     cairo_fixed_t dx_fixed, dy_fixed;
01252 
01253     if (cr->status)
01254        return;
01255 
01256     _cairo_gstate_user_to_device_distance (cr->gstate, &dx, &dy);
01257     dx_fixed = _cairo_fixed_from_double (dx);
01258     dy_fixed = _cairo_fixed_from_double (dy);
01259 
01260     cr->status = _cairo_path_fixed_rel_line_to (&cr->path, dx_fixed, dy_fixed);
01261     if (cr->status)
01262        _cairo_set_error (cr, cr->status);
01263 }
01264 slim_hidden_def(cairo_rel_line_to);
01265 
01288 void
01289 cairo_rel_curve_to (cairo_t *cr,
01290                   double dx1, double dy1,
01291                   double dx2, double dy2,
01292                   double dx3, double dy3)
01293 {
01294     cairo_fixed_t dx1_fixed, dy1_fixed;
01295     cairo_fixed_t dx2_fixed, dy2_fixed;
01296     cairo_fixed_t dx3_fixed, dy3_fixed;
01297 
01298     if (cr->status)
01299        return;
01300 
01301     _cairo_gstate_user_to_device_distance (cr->gstate, &dx1, &dy1);
01302     _cairo_gstate_user_to_device_distance (cr->gstate, &dx2, &dy2);
01303     _cairo_gstate_user_to_device_distance (cr->gstate, &dx3, &dy3);
01304 
01305     dx1_fixed = _cairo_fixed_from_double (dx1);
01306     dy1_fixed = _cairo_fixed_from_double (dy1);
01307 
01308     dx2_fixed = _cairo_fixed_from_double (dx2);
01309     dy2_fixed = _cairo_fixed_from_double (dy2);
01310 
01311     dx3_fixed = _cairo_fixed_from_double (dx3);
01312     dy3_fixed = _cairo_fixed_from_double (dy3);
01313 
01314     cr->status = _cairo_path_fixed_rel_curve_to (&cr->path,
01315                                            dx1_fixed, dy1_fixed,
01316                                            dx2_fixed, dy2_fixed,
01317                                            dx3_fixed, dy3_fixed);
01318     if (cr->status)
01319        _cairo_set_error (cr, cr->status);
01320 }
01321 
01342 void
01343 cairo_rectangle (cairo_t *cr,
01344                double x, double y,
01345                double width, double height)
01346 {
01347     if (cr->status)
01348        return;
01349 
01350     cairo_move_to (cr, x, y);
01351     cairo_rel_line_to (cr, width, 0);
01352     cairo_rel_line_to (cr, 0, height);
01353     cairo_rel_line_to (cr, -width, 0);
01354     cairo_close_path (cr);
01355 }
01356 
01357 /* XXX: NYI
01358 void
01359 cairo_stroke_to_path (cairo_t *cr)
01360 {
01361     if (cr->status)
01362        return;
01363 
01364     cr->status = _cairo_gstate_stroke_path (cr->gstate);
01365     if (cr->status)
01366        _cairo_set_error (cr, cr->status);
01367 }
01368 */
01369 
01384 void
01385 cairo_close_path (cairo_t *cr)
01386 {
01387     if (cr->status)
01388        return;
01389 
01390     cr->status = _cairo_path_fixed_close_path (&cr->path);
01391     if (cr->status)
01392        _cairo_set_error (cr, cr->status);
01393 }
01394 slim_hidden_def(cairo_close_path);
01395 
01403 void
01404 cairo_paint (cairo_t *cr)
01405 {
01406     if (cr->status)
01407        return;
01408 
01409     cr->status = _cairo_gstate_paint (cr->gstate);
01410     if (cr->status)
01411        _cairo_set_error (cr, cr->status);
01412 }
01413 
01424 void
01425 cairo_paint_with_alpha (cairo_t *cr,
01426                      double   alpha)
01427 {
01428     cairo_color_t color;
01429     cairo_pattern_union_t pattern;
01430   
01431     if (cr->status)
01432        return;
01433 
01434     if (CAIRO_ALPHA_IS_OPAQUE (alpha)) {
01435        cairo_paint (cr);
01436        return;
01437     }
01438 
01439     if (CAIRO_ALPHA_IS_ZERO (alpha)) {
01440        return;
01441     }
01442 
01443     _cairo_color_init_rgba (&color, 1., 1., 1., alpha);
01444     _cairo_pattern_init_solid (&pattern.solid, &color);
01445 
01446     cr->status = _cairo_gstate_mask (cr->gstate, &pattern.base);
01447     if (cr->status)
01448        _cairo_set_error (cr, cr->status);
01449 
01450     _cairo_pattern_fini (&pattern.base);
01451 }
01452 
01463 void
01464 cairo_mask (cairo_t         *cr,
01465            cairo_pattern_t *pattern)
01466 {
01467     if (cr->status)
01468        return;
01469 
01470     if (pattern == NULL) {
01471        _cairo_set_error (cr, CAIRO_STATUS_NULL_POINTER);
01472        return;
01473     }
01474     
01475     if (pattern->status) {
01476        _cairo_set_error (cr, pattern->status);
01477        return;
01478     }
01479 
01480     cr->status = _cairo_gstate_mask (cr->gstate, pattern);
01481     if (cr->status)
01482        _cairo_set_error (cr, cr->status);
01483 }
01484 
01497 void
01498 cairo_mask_surface (cairo_t         *cr,
01499                   cairo_surface_t *surface,
01500                   double           surface_x,
01501                   double           surface_y)
01502 {
01503     cairo_pattern_t *pattern;
01504     cairo_matrix_t matrix;
01505 
01506     if (cr->status)
01507        return;
01508 
01509     pattern = cairo_pattern_create_for_surface (surface);
01510 
01511     cairo_matrix_init_translate (&matrix, - surface_x, - surface_y);
01512     cairo_pattern_set_matrix (pattern, &matrix);
01513 
01514     cairo_mask (cr, pattern);
01515     
01516     cairo_pattern_destroy (pattern);
01517 }
01518 
01530 void
01531 cairo_stroke (cairo_t *cr)
01532 {
01533     cairo_stroke_preserve (cr);
01534 
01535     cairo_new_path (cr);
01536 }
01537 
01551 void
01552 cairo_stroke_preserve (cairo_t *cr)
01553 {
01554     if (cr->status)
01555        return;
01556 
01557     cr->status = _cairo_gstate_stroke (cr->gstate, &cr->path);
01558     if (cr->status)
01559        _cairo_set_error (cr, cr->status);
01560 }
01561 slim_hidden_def(cairo_stroke_preserve);
01562 
01573 void
01574 cairo_fill (cairo_t *cr)
01575 {
01576     cairo_fill_preserve (cr);
01577 
01578     cairo_new_path (cr);
01579 }
01580 
01592 void
01593 cairo_fill_preserve (cairo_t *cr)
01594 {
01595     if (cr->status)
01596        return;
01597 
01598     cr->status = _cairo_gstate_fill (cr->gstate, &cr->path);
01599     if (cr->status)
01600        _cairo_set_error (cr, cr->status);
01601 }
01602 slim_hidden_def(cairo_fill_preserve);
01603 
01604 void
01605 cairo_copy_page (cairo_t *cr)
01606 {
01607     if (cr->status)
01608        return;
01609 
01610     cr->status = _cairo_gstate_copy_page (cr->gstate);
01611     if (cr->status)
01612        _cairo_set_error (cr, cr->status);
01613 }
01614 
01615 void
01616 cairo_show_page (cairo_t *cr)
01617 {
01618     if (cr->status)
01619        return;
01620 
01621     cr->status = _cairo_gstate_show_page (cr->gstate);
01622     if (cr->status)
01623        _cairo_set_error (cr, cr->status);
01624 }
01625 
01626 cairo_bool_t
01627 cairo_in_stroke (cairo_t *cr, double x, double y)
01628 {
01629     int inside;
01630 
01631     if (cr->status)
01632        return 0;
01633 
01634     cr->status = _cairo_gstate_in_stroke (cr->gstate,
01635                                      &cr->path,
01636                                      x, y, &inside);
01637     if (cr->status)
01638        return 0;
01639 
01640     return inside;
01641 }
01642 
01643 cairo_bool_t
01644 cairo_in_fill (cairo_t *cr, double x, double y)
01645 {
01646     int inside;
01647 
01648     if (cr->status)
01649        return 0;
01650 
01651     cr->status = _cairo_gstate_in_fill (cr->gstate,
01652                                    &cr->path,
01653                                    x, y, &inside);
01654     if (cr->status) {
01655        _cairo_set_error (cr, cr->status);
01656        return 0;
01657     }
01658 
01659     return inside;
01660 }
01661 
01662 void
01663 cairo_stroke_extents (cairo_t *cr,
01664                       double *x1, double *y1, double *x2, double *y2)
01665 {
01666     if (cr->status)
01667        return;
01668     
01669     cr->status = _cairo_gstate_stroke_extents (cr->gstate,
01670                                           &cr->path,
01671                                           x1, y1, x2, y2);
01672     if (cr->status)
01673        _cairo_set_error (cr, cr->status);
01674 }
01675 
01676 void
01677 cairo_fill_extents (cairo_t *cr,
01678                     double *x1, double *y1, double *x2, double *y2)
01679 {
01680     if (cr->status)
01681        return;
01682     
01683     cr->status = _cairo_gstate_fill_extents (cr->gstate,
01684                                         &cr->path,
01685                                         x1, y1, x2, y2);
01686     if (cr->status)
01687        _cairo_set_error (cr, cr->status);
01688 }
01689 
01712 void
01713 cairo_clip (cairo_t *cr)
01714 {
01715     cairo_clip_preserve (cr);
01716 
01717     cairo_new_path (cr);
01718 }
01719 
01742 void
01743 cairo_clip_preserve (cairo_t *cr)
01744 {
01745     if (cr->status)
01746        return;
01747 
01748     cr->status = _cairo_gstate_clip (cr->gstate, &cr->path);
01749     if (cr->status)
01750        _cairo_set_error (cr, cr->status);
01751 }
01752 slim_hidden_def(cairo_clip_preserve);
01753 
01770 void
01771 cairo_reset_clip (cairo_t *cr)
01772 {
01773     if (cr->status)
01774        return;
01775 
01776     cr->status = _cairo_gstate_reset_clip (cr->gstate);
01777     if (cr->status)
01778        _cairo_set_error (cr, cr->status);
01779 }
01780 
01796 void
01797 cairo_select_font_face (cairo_t              *cr, 
01798                      const char           *family, 
01799                      cairo_font_slant_t    slant, 
01800                      cairo_font_weight_t   weight)
01801 {
01802     if (cr->status)
01803        return;
01804 
01805     cr->status = _cairo_gstate_select_font_face (cr->gstate, family, slant, weight);
01806     if (cr->status)
01807        _cairo_set_error (cr, cr->status);
01808 }
01809 
01821 cairo_font_face_t *
01822 cairo_get_font_face (cairo_t *cr)
01823 {
01824     cairo_font_face_t *font_face;
01825 
01826     if (cr->status)
01827        return (cairo_font_face_t*) &_cairo_font_face_nil;
01828 
01829     cr->status = _cairo_gstate_get_font_face (cr->gstate, &font_face);
01830     if (cr->status) {
01831        _cairo_set_error (cr, cr->status);
01832        return (cairo_font_face_t*) &_cairo_font_face_nil;
01833     }
01834 
01835     return font_face;
01836 }
01837 
01846 void
01847 cairo_font_extents (cairo_t              *cr, 
01848                   cairo_font_extents_t *extents)
01849 {
01850     if (cr->status)
01851        return;
01852 
01853     cr->status = _cairo_gstate_get_font_extents (cr->gstate, extents);
01854     if (cr->status)
01855        _cairo_set_error (cr, cr->status);
01856 }
01857 
01867 void
01868 cairo_set_font_face (cairo_t           *cr,
01869                    cairo_font_face_t *font_face)
01870 {
01871     if (cr->status)
01872        return;
01873 
01874     cr->status = _cairo_gstate_set_font_face (cr->gstate, font_face);  
01875     if (cr->status)
01876        _cairo_set_error (cr, cr->status);
01877 }
01878 
01890 void
01891 cairo_set_font_size (cairo_t *cr, double size)
01892 {
01893     if (cr->status)
01894        return;
01895 
01896     cr->status = _cairo_gstate_set_font_size (cr->gstate, size);
01897     if (cr->status)
01898        _cairo_set_error (cr, cr->status);
01899 }
01900 
01914 void
01915 cairo_set_font_matrix (cairo_t                *cr,
01916                      const cairo_matrix_t *matrix)
01917 {
01918     if (cr->status)
01919        return;
01920 
01921     cr->status = _cairo_gstate_set_font_matrix (cr->gstate, matrix);
01922     if (cr->status)
01923        _cairo_set_error (cr, cr->status);
01924 }
01925 
01934 void
01935 cairo_get_font_matrix (cairo_t *cr, cairo_matrix_t *matrix)
01936 {
01937     _cairo_gstate_get_font_matrix (cr->gstate, matrix);
01938 }
01939 
01951 void
01952 cairo_set_font_options (cairo_t                    *cr,
01953                      const cairo_font_options_t *options)
01954 {
01955     if (cr->status)
01956        return;
01957 
01958     cr->status = _cairo_gstate_set_font_options (cr->gstate, options);
01959     if (cr->status)
01960        _cairo_set_error (cr, cr->status);
01961 }
01962 
01974 void
01975 cairo_get_font_options (cairo_t              *cr,
01976                      cairo_font_options_t *options)
01977 {
01978     _cairo_gstate_get_font_options (cr->gstate, options);
01979 }
01980 
02001 void
02002 cairo_text_extents (cairo_t              *cr,
02003                   const char               *utf8,
02004                   cairo_text_extents_t *extents)
02005 {
02006     cairo_glyph_t *glyphs = NULL;
02007     int num_glyphs;
02008     double x, y;
02009 
02010     if (cr->status)
02011        return;
02012 
02013     if (utf8 == NULL) {
02014        extents->x_bearing = 0.0;
02015        extents->y_bearing = 0.0;
02016        extents->width = 0.0;
02017        extents->height = 0.0;
02018        extents->x_advance = 0.0;
02019        extents->y_advance = 0.0;
02020        return;
02021     }
02022 
02023     cairo_get_current_point (cr, &x, &y);
02024 
02025     cr->status = _cairo_gstate_text_to_glyphs (cr->gstate, utf8,
02026                                           x, y,
02027                                           &glyphs, &num_glyphs);
02028 
02029     if (cr->status) {
02030        if (glyphs)
02031            free (glyphs);
02032        _cairo_set_error (cr, cr->status);
02033        return;
02034     }
02035        
02036     cr->status = _cairo_gstate_glyph_extents (cr->gstate, glyphs, num_glyphs, extents);
02037     if (glyphs)
02038        free (glyphs);
02039 
02040     if (cr->status)
02041        _cairo_set_error (cr, cr->status);
02042 }
02043 
02062 void
02063 cairo_glyph_extents (cairo_t                *cr,
02064                    cairo_glyph_t          *glyphs, 
02065                    int                    num_glyphs,
02066                    cairo_text_extents_t   *extents)
02067 {
02068     if (cr->status)
02069        return;
02070 
02071     cr->status = _cairo_gstate_glyph_extents (cr->gstate, glyphs, num_glyphs,
02072                                          extents);
02073     if (cr->status)
02074        _cairo_set_error (cr, cr->status);
02075 }
02076 
02104 void
02105 cairo_show_text (cairo_t *cr, const char *utf8)
02106 {
02107     cairo_text_extents_t extents;
02108     cairo_glyph_t *glyphs = NULL, *last_glyph;
02109     int num_glyphs;
02110     double x, y;
02111 
02112     if (cr->status)
02113        return;
02114 
02115     if (utf8 == NULL)
02116        return;
02117 
02118     cairo_get_current_point (cr, &x, &y);
02119 
02120     cr->status = _cairo_gstate_text_to_glyphs (cr->gstate, utf8,
02121                                           x, y,
02122                                           &glyphs, &num_glyphs);
02123     if (cr->status)
02124        goto BAIL;
02125 
02126     if (num_glyphs == 0)
02127        return;
02128 
02129     cr->status = _cairo_gstate_show_glyphs (cr->gstate, glyphs, num_glyphs);
02130     if (cr->status)
02131        goto BAIL;
02132 
02133     last_glyph = &glyphs[num_glyphs - 1];
02134     cr->status = _cairo_gstate_glyph_extents (cr->gstate,
02135                                          last_glyph, 1,
02136                                          &extents);
02137     if (cr->status)
02138        goto BAIL;
02139 
02140     x = last_glyph->x + extents.x_advance;
02141     y = last_glyph->y + extents.y_advance;
02142     cairo_move_to (cr, x, y);
02143 
02144  BAIL:
02145     if (glyphs)
02146        free (glyphs);
02147 
02148     if (cr->status)
02149        _cairo_set_error (cr, cr->status);
02150 }
02151 
02152 void
02153 cairo_show_glyphs (cairo_t *cr, cairo_glyph_t *glyphs, int num_glyphs)
02154 {
02155     if (cr->status)
02156        return;
02157 
02158     cr->status = _cairo_gstate_show_glyphs (cr->gstate, glyphs, num_glyphs);
02159     if (cr->status)
02160        _cairo_set_error (cr, cr->status);
02161 }
02162 
02163 void
02164 cairo_text_path  (cairo_t *cr, const char *utf8)
02165 {
02166     cairo_glyph_t *glyphs = NULL;
02167     int num_glyphs;
02168     double x, y;
02169 
02170     if (cr->status)
02171        return;
02172 
02173     cairo_get_current_point (cr, &x, &y);
02174 
02175     cr->status = _cairo_gstate_text_to_glyphs (cr->gstate, utf8,
02176                                           x, y,
02177                                           &glyphs, &num_glyphs);
02178 
02179     if (cr->status) {
02180        if (glyphs)
02181            free (glyphs);
02182        _cairo_set_error (cr, cr->status);
02183        return;
02184     }
02185 
02186     cr->status = _cairo_gstate_glyph_path (cr->gstate,
02187                                       glyphs, num_glyphs,
02188                                       &cr->path);
02189     if (glyphs)
02190        free (glyphs);
02191 
02192     if (cr->status)
02193        _cairo_set_error (cr, cr->status);
02194 }
02195 
02196 void
02197 cairo_glyph_path (cairo_t *cr, cairo_glyph_t *glyphs, int num_glyphs)
02198 {
02199     if (cr->status)
02200        return;
02201 
02202     cr->status = _cairo_gstate_glyph_path (cr->gstate,
02203                                       glyphs, num_glyphs,
02204                                       &cr->path);
02205     if (cr->status)
02206        _cairo_set_error (cr, cr->status);
02207 }
02208 
02217 cairo_operator_t
02218 cairo_get_operator (cairo_t *cr)
02219 {
02220     return _cairo_gstate_get_operator (cr->gstate);
02221 }
02222 
02231 double
02232 cairo_get_tolerance (cairo_t *cr)
02233 {
02234     return _cairo_gstate_get_tolerance (cr->gstate);
02235 }
02236 
02245 cairo_antialias_t
02246 cairo_get_antialias (cairo_t *cr)
02247 {
02248     return _cairo_gstate_get_antialias (cr->gstate);
02249 }
02250 
02272 void
02273 cairo_get_current_point (cairo_t *cr, double *x_ret, double *y_ret)
02274 {
02275     cairo_status_t status;
02276     cairo_fixed_t x_fixed, y_fixed;
02277     double x, y;
02278 
02279     status = _cairo_path_fixed_get_current_point (&cr->path, &x_fixed, &y_fixed);
02280     if (status == CAIRO_STATUS_NO_CURRENT_POINT) {
02281        x = 0.0;
02282        y = 0.0;
02283     } else {
02284        x = _cairo_fixed_to_double (x_fixed);
02285        y = _cairo_fixed_to_double (y_fixed);
02286        _cairo_gstate_backend_to_user (cr->gstate, &x, &y);
02287     }
02288 
02289     if (x_ret)
02290        *x_ret = x;
02291     if (y_ret)
02292        *y_ret = y;
02293 }
02294 slim_hidden_def(cairo_get_current_point);
02295 
02304 cairo_fill_rule_t
02305 cairo_get_fill_rule (cairo_t *cr)
02306 {
02307     return _cairo_gstate_get_fill_rule (cr->gstate);
02308 }
02309 
02318 double
02319 cairo_get_line_width (cairo_t *cr)
02320 {
02321     return _cairo_gstate_get_line_width (cr->gstate);
02322 }
02323 
02332 cairo_line_cap_t
02333 cairo_get_line_cap (cairo_t *cr)
02334 {
02335     return _cairo_gstate_get_line_cap (cr->gstate);
02336 }
02337 
02346 cairo_line_join_t
02347 cairo_get_line_join (cairo_t *cr)
02348 {
02349     return _cairo_gstate_get_line_join (cr->gstate);
02350 }
02351 
02360 double
02361 cairo_get_miter_limit (cairo_t *cr)
02362 {
02363     return _cairo_gstate_get_miter_limit (cr->gstate);
02364 }
02365 
02373 void
02374 cairo_get_matrix (cairo_t *cr, cairo_matrix_t *matrix)
02375 {
02376     _cairo_gstate_get_matrix (cr->gstate, matrix);
02377 }
02378 
02395 cairo_surface_t *
02396 cairo_get_target (cairo_t *cr)
02397 {
02398     if (cr->status)
02399        return (cairo_surface_t*) &_cairo_surface_nil;
02400 
02401     return _cairo_gstate_get_target (cr->gstate);
02402 }
02403 
02434 cairo_path_t *
02435 cairo_copy_path (cairo_t *cr)
02436 {
02437     if (cr->status)
02438        return (cairo_path_t*) &_cairo_path_nil;
02439 
02440     return _cairo_path_data_create (&cr->path, cr->gstate);
02441 }
02442 
02476 cairo_path_t *
02477 cairo_copy_path_flat (cairo_t *cr)
02478 {
02479     if (cr->status)
02480        return (cairo_path_t*) &_cairo_path_nil;
02481     else
02482        return _cairo_path_data_create_flat (&cr->path, cr->gstate);
02483 }
02484 
02497 void
02498 cairo_append_path (cairo_t  *cr,
02499                  cairo_path_t *path)
02500 {
02501     if (cr->status)
02502        return;
02503 
02504     if (path == NULL) {
02505        _cairo_set_error (cr, CAIRO_STATUS_NULL_POINTER);
02506        return;
02507     }
02508 
02509     if (path->status) {
02510        if (path->status <= CAIRO_STATUS_LAST_STATUS)
02511            _cairo_set_error (cr, path->status);
02512        else
02513            _cairo_set_error (cr, CAIRO_STATUS_INVALID_STATUS);
02514        return;
02515     }
02516 
02517     if (path->data == NULL) {
02518        _cairo_set_error (cr, CAIRO_STATUS_NULL_POINTER);
02519        return;
02520     }
02521 
02522     cr->status = _cairo_path_data_append_to_context (path, cr);
02523     if (cr->status)
02524        _cairo_set_error (cr, cr->status);
02525 }
02526 
02535 cairo_status_t
02536 cairo_status (cairo_t *cr)
02537 {
02538     return cr->status;
02539 }
02540 
02549 const char *
02550 cairo_status_to_string (cairo_status_t status)
02551 {
02552     switch (status) {
02553     case CAIRO_STATUS_SUCCESS:
02554        return "success";
02555     case CAIRO_STATUS_NO_MEMORY:
02556        return "out of memory";
02557     case CAIRO_STATUS_INVALID_RESTORE:
02558        return "cairo_restore without matching cairo_save";
02559     case CAIRO_STATUS_INVALID_POP_GROUP:
02560        return "cairo_pop_group without matching cairo_push_group";
02561     case CAIRO_STATUS_NO_CURRENT_POINT:
02562        return "no current point defined";
02563     case CAIRO_STATUS_INVALID_MATRIX:
02564        return "invalid matrix (not invertible)";
02565     case CAIRO_STATUS_INVALID_STATUS:
02566        return "invalid value for an input cairo_status_t";
02567     case CAIRO_STATUS_NULL_POINTER:
02568        return "NULL pointer";
02569     case CAIRO_STATUS_INVALID_STRING:
02570        return "input string not valid UTF-8";
02571     case CAIRO_STATUS_INVALID_PATH_DATA:
02572        return "input path data not valid";
02573     case CAIRO_STATUS_READ_ERROR:
02574        return "error while reading from input stream";
02575     case CAIRO_STATUS_WRITE_ERROR:
02576        return "error while writing to output stream";
02577     case CAIRO_STATUS_SURFACE_FINISHED:
02578        return "the target surface has been finished";
02579     case CAIRO_STATUS_SURFACE_TYPE_MISMATCH:
02580        return "the surface type is not appropriate for the operation";
02581     case CAIRO_STATUS_PATTERN_TYPE_MISMATCH:
02582        return "the pattern type is not appropriate for the operation";
02583     case CAIRO_STATUS_INVALID_CONTENT:
02584        return "invalid value for an input cairo_content_t";
02585     case CAIRO_STATUS_INVALID_FORMAT:
02586        return "invalid value for an input cairo_format_t";
02587     case CAIRO_STATUS_INVALID_VISUAL:
02588        return "invalid value for an input Visual*";
02589     case CAIRO_STATUS_FILE_NOT_FOUND:
02590        return "file not found";
02591     case CAIRO_STATUS_INVALID_DASH:
02592        return "invalid value for a dash setting";
02593     }
02594 
02595     return "<unknown error status>";
02596 }
02597 
02598 void
02599 _cairo_restrict_value (double *value, double min, double max)
02600 {
02601     if (*value < min)
02602        *value = min;
02603     else if (*value > max)
02604        *value = max;
02605 }