Anforderungen  |   Konzepte  |   Entwurf  |   Entwicklung  |   Qualitätssicherung  |   Lebenszyklus  |   Steuerung
 
 
 
 


Quelle  cairo.c   Sprache: C

 
/* -*- Mode: c; c-basic-offset: 4; indent-tabs-mode: t; tab-width: 8; -*- */
/* cairo - a vector graphics library with display and print output
 *
 * Copyright © 2002 University of Southern California
 * Copyright © 2005 Red Hat, Inc.
 * Copyright © 2011 Intel Corporation
 *
 * This library is free software; you can redistribute it and/or
 * modify it either under the terms of the GNU Lesser General Public
 * License version 2.1 as published by the Free Software Foundation
 * (the "LGPL") or, at your option, under the terms of the Mozilla
 * Public License Version 1.1 (the "MPL"). If you do not alter this
 * notice, a recipient may use your version of this file under either
 * the MPL or the LGPL.
 *
 * You should have received a copy of the LGPL along with this library
 * in the file COPYING-LGPL-2.1; if not, write to the Free Software
 * Foundation, Inc., 51 Franklin Street, Suite 500, Boston, MA 02110-1335, USA
 * You should have received a copy of the MPL along with this library
 * in the file COPYING-MPL-1.1
 *
 * The contents of this file are subject to the Mozilla Public License
 * Version 1.1 (the "License"); you may not use this file except in
 * compliance with the License. You may obtain a copy of the License at
 * http://www.mozilla.org/MPL/
 *
 * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY
 * OF ANY KIND, either express or implied. See the LGPL or the MPL for
 * the specific language governing rights and limitations.
 *
 * The Original Code is the cairo graphics library.
 *
 * The Initial Developer of the Original Code is University of Southern
 * California.
 *
 * Contributor(s):
 * Carl D. Worth <cworth@cworth.org>
 * Chris Wilson <chris@chris-wilson.co.uk>
 */


#include "cairoint.h"
#include "cairo-private.h"

#include "cairo-backend-private.h"
#include "cairo-error-private.h"
#include "cairo-path-private.h"
#include "cairo-pattern-private.h"
#include "cairo-surface-private.h"
#include "cairo-surface-backend-private.h"

#include <assert.h>

/**
 * SECTION:cairo
 * @Title: cairo_t
 * @Short_Description: The cairo drawing context
 * @See_Also: #cairo_surface_t
 *
 * #cairo_t is the main object used when drawing with cairo. To
 * draw with cairo, you create a #cairo_t, set the target surface,
 * and drawing options for the #cairo_t, create shapes with
 * functions like cairo_move_to() and cairo_line_to(), and then
 * draw shapes with cairo_stroke() or cairo_fill().
 *
 * #cairo_t<!-- -->'s can be pushed to a stack via cairo_save().
 * They may then safely be changed, without losing the current state.
 * Use cairo_restore() to restore to the saved state.
 **/


/**
 * SECTION:cairo-text
 * @Title: text
 * @Short_Description: Rendering text and glyphs
 * @See_Also: #cairo_font_face_t, #cairo_scaled_font_t, cairo_text_path(),
 *            cairo_glyph_path()
 *
 * The functions with <emphasis>text</emphasis> in their name form cairo's
 * <firstterm>toy</firstterm> text API.  The toy API takes UTF-8 encoded
 * text and is limited in its functionality to rendering simple
 * left-to-right text with no advanced features.  That means for example
 * that most complex scripts like Hebrew, Arabic, and Indic scripts are
 * out of question.  No kerning or correct positioning of diacritical marks
 * either.  The font selection is pretty limited too and doesn't handle the
 * case that the selected font does not cover the characters in the text.
 * This set of functions are really that, a toy text API, for testing and
 * demonstration purposes.  Any serious application should avoid them.
 *
 * The functions with <emphasis>glyphs</emphasis> in their name form cairo's
 * <firstterm>low-level</firstterm> text API.  The low-level API relies on
 * the user to convert text to a set of glyph indexes and positions.  This
 * is a very hard problem and is best handled by external libraries, like
 * the pangocairo that is part of the Pango text layout and rendering library.
 * Pango is available from <ulink
 * url="http://www.pango.org/">http://www.pango.org/</ulink>.
 **/


/**
 * SECTION:cairo-transforms
 * @Title: Transformations
 * @Short_Description: Manipulating the current transformation matrix
 * @See_Also: #cairo_matrix_t
 *
 * The current transformation matrix, <firstterm>ctm</firstterm>, is a
 * two-dimensional affine transformation that maps all coordinates and other
 * drawing instruments from the <firstterm>user space</firstterm> into the
 * surface's canonical coordinate system, also known as the <firstterm>device
 * space</firstterm>.
 **/


/**
 * SECTION:cairo-tag
 * @Title: Tags and Links
 * @Short_Description: Hyperlinks and document structure
 * @See_Also: #cairo_pdf_surface_t
 *
 * The tag functions provide the ability to specify hyperlinks and
 * document logical structure on supported backends. The following tags are supported:
 * * [Link][link] - Create a hyperlink
 * * [Destinations][dest] - Create a hyperlink destination
 * * [Document Structure Tags][doc-struct] - Create PDF Document Structure
 *
 * # Link Tags # {#link}
 * A hyperlink is specified by enclosing the hyperlink text with the %CAIRO_TAG_LINK tag.
 *
 * For example:
 * <informalexample><programlisting>
 * cairo_tag_begin (cr, CAIRO_TAG_LINK, "uri='https://cairographics.org'");
 * cairo_move_to (cr, 50, 50);
 * cairo_show_text (cr, "This is a link to the cairo website.");
 * cairo_tag_end (cr, CAIRO_TAG_LINK);
 * </programlisting></informalexample>
 *
 * The PDF backend uses one or more rectangles to define the clickable
 * area of the link.  By default cairo will use the extents of the
 * drawing operations enclosed by the begin/end link tags to define the
 * clickable area. In some cases, such as a link split across two
 * lines, the default rectangle is undesirable.
 *
 * @rect: [optional] The "rect" attribute allows the application to
 * specify one or more rectangles that form the clickable region.  The
 * value of this attribute is an array of floats. Each rectangle is
 * specified by four elements in the array: x, y, width, height. The
 * array size must be a multiple of four.
 *
 * An example of creating a link with user specified clickable region:
 * <informalexample><programlisting>
 * struct text {
 *     const char *s;
 *     double x, y;
 * };
 * const struct text text1 = { "This link is split", 450, 70 };
 * const struct text text2 = { "across two lines", 50, 70 };
 * cairo_text_extents_t text1_extents;
 * cairo_text_extents_t text2_extents;
 * char attribs[100];
 *
 * cairo_text_extents (cr, text1.s, &text1_extents);
 * cairo_text_extents (cr, text2.s, &text2_extents);
 * sprintf (attribs,
 *          "rect=[%f %f %f %f %f %f %f %f] uri='https://cairographics.org'",
 *          text1_extents.x_bearing + text1.x,
 *          text1_extents.y_bearing + text1.y,
 *          text1_extents.width,
 *          text1_extents.height,
 *          text2_extents.x_bearing + text2.x,
 *          text2_extents.y_bearing + text2.y,
 *          text2_extents.width,
 *          text2_extents.height);
 *
 * cairo_tag_begin (cr, CAIRO_TAG_LINK, attribs);
 * cairo_move_to (cr, text1.x, text1.y);
 * cairo_show_text (cr, text1.s);
 * cairo_move_to (cr, text2.x, text2.y);
 * cairo_show_text (cr, text2.s);
 * cairo_tag_end (cr, CAIRO_TAG_LINK);
 * </programlisting></informalexample>
 *
 * There are three types of links. Each type has its own attributes as detailed below.
 * * [Internal Links][internal-link] - A link to a location in the same document
 * * [URI Links][uri-link] - A link to a Uniform resource identifier
 * * [File Links][file-link] - A link to a location in another document
 *
 * ## Internal Links ## {#internal-link}
 * An internal link is a link to a location in the same document. The destination
 * is specified with either:
 *
 * @dest: a UTF-8 string specifying the destination in the PDF file to link
 * to. Destinations are created with the %CAIRO_TAG_DEST tag.
 *
 * or the two attributes:
 *
 * @page: An integer specifying the page number in the PDF file to link to.
 *
 * @pos: [optional] An array of two floats specifying the x,y position
 * on the page.
 *
 * An example of the link attributes to link to a page and x,y position:
 * <programlisting>
 * "page=3 pos=[3.1 6.2]"
 * </programlisting>
 *
 * ## URI Links ## {#uri-link}
 * A URI link is a link to a Uniform Resource Identifier ([RFC 2396](http://tools.ietf.org/html/rfc2396)).
 *
 * A URI is specified with the following attribute:
 *
 * @uri: An ASCII string specifying the URI.
 *
 * An example of the link attributes to the cairo website:
 * <programlisting>
 * "uri='https://cairographics.org'"
 * </programlisting>
 *
 * ## File Links ## {#file-link}
 * A file link is a link a location in another PDF file.
 *
 * The file attribute (required) specifies the name of the PDF file:
 *
 * @file: File name of PDF file to link to.
 *
 * The position is specified by either:
 *
 *  @dest: a UTF-8 string specifying the named destination in the PDF file.
 *
 * or
 *
 *  @page: An integer specifying the page number in the PDF file.
 *
 *  @pos: [optional] An array of two floats specifying the x,y
 *  position on the page. Position coordinates in external files are in PDF
 *  coordinates (0,0 at bottom left).
 *
 * An example of the link attributes to PDF file:
 * <programlisting>
 * "file='document.pdf' page=16 pos=[25 40]"
 * </programlisting>
 *
 * # Destination Tags # {#dest}
 *
 * A destination is specified by enclosing the destination drawing
 * operations with the %CAIRO_TAG_DEST tag.
 *
 * @name: [required] A UTF-8 string specifying the name of this destination.
 *
 * @x: [optional] A float specifying the x coordinate of destination
 *                 position on this page. If not specified the default
 *                 x coordinate is the left side of the extents of the
 *                 operations enclosed by the %CAIRO_TAG_DEST begin/end tags. If
 *                 no operations are enclosed, the x coordidate is 0.
 *
 * @y: [optional] A float specifying the y coordinate of destination
 *                 position on this page. If not specified the default
 *                 y coordinate is the top of the extents of the
 *                 operations enclosed by the %CAIRO_TAG_DEST begin/end tags. If
 *                 no operations are enclosed, the y coordidate is 0.
 *
 * @internal: A boolean that if true, the destination name may be
 *            omitted from PDF where possible. In this case, links
 *            refer directly to the page and position instead of via
 *            the named destination table. Note that if this
 *            destination is referenced by another PDF (see [File Links][file-link]),
 *            this attribute must be false. Default is false.
 *
 * <informalexample><programlisting>
 * /* Create a hyperlink */
 * cairo_tag_begin (cr, CAIRO_TAG_LINK, "dest='mydest' internal");
 * cairo_move_to (cr, 50, 50);
 * cairo_show_text (cr, "This is a hyperlink.");
 * cairo_tag_end (cr, CAIRO_TAG_LINK);
 *
 * /* Create a destination */
 * cairo_tag_begin (cr, CAIRO_TAG_DEST, "name='mydest'");
 * cairo_move_to (cr, 50, 250);
 * cairo_show_text (cr, "This paragraph is the destination of the above link.");
 * cairo_tag_end (cr, CAIRO_TAG_DEST);
 * </programlisting></informalexample>
 *
 * # Document Structure (PDF) # {#doc-struct}
 *
 * The document structure tags provide a means of specifying structural information
 * such as headers, paragraphs, tables, and figures. The inclusion of structural information facilitates:
 * * Extraction of text and graphics for copy and paste
 * * Reflow of text and graphics in the viewer
 * * Processing text eg searching and indexing
 * * Conversion to other formats
 * * Accessability support
 *
 * The list of structure types is specified in section 14.8.4 of the
 * [PDF Reference](http://www.adobe.com/content/dam/Adobe/en/devnet/acrobat/pdfs/PDF32000_2008.pdf).
 *
 * Note the PDF "Link" structure tag is the same as the cairo %CAIRO_TAG_LINK tag.
 *
 * The following example creates a document structure for a document containing two section, each with
 * a header and a paragraph.
 *
 * <informalexample><programlisting>
 * cairo_tag_begin (cr, "Document", NULL);
 *
 * cairo_tag_begin (cr, "Sect", NULL);
 * cairo_tag_begin (cr, "H1", NULL);
 * cairo_show_text (cr, "Heading 1");
 * cairo_tag_end (cr, "H1");
 *
 * cairo_tag_begin (cr, "P", NULL);
 * cairo_show_text (cr, "Paragraph 1");
 * cairo_tag_end (cr, "P");
 * cairo_tag_end (cr, "Sect");
 *
 * cairo_tag_begin (cr, "Sect", NULL);
 * cairo_tag_begin (cr, "H1", NULL);
 * cairo_show_text (cr, "Heading 2");
 * cairo_tag_end (cr, "H1");
 *
 * cairo_tag_begin (cr, "P", NULL);
 * cairo_show_text (cr, "Paragraph 2");
 * cairo_tag_end (cr, "P");
 * cairo_tag_end (cr, "Sect");
 *
 * cairo_tag_end (cr, "Document");
 * </programlisting></informalexample>
 *
 **/


#define DEFINE_NIL_CONTEXT(status)     \
    {         \
 CAIRO_REFERENCE_COUNT_INVALID, /* ref_count */ \
 status,    /* status */ \
 { 0, 0, 0, NULL },  /* user_data */ \
 NULL        \
    }

static const cairo_t _cairo_nil[] = {
    DEFINE_NIL_CONTEXT (CAIRO_STATUS_NO_MEMORY),
    DEFINE_NIL_CONTEXT (CAIRO_STATUS_INVALID_RESTORE),
    DEFINE_NIL_CONTEXT (CAIRO_STATUS_INVALID_POP_GROUP),
    DEFINE_NIL_CONTEXT (CAIRO_STATUS_NO_CURRENT_POINT),
    DEFINE_NIL_CONTEXT (CAIRO_STATUS_INVALID_MATRIX),
    DEFINE_NIL_CONTEXT (CAIRO_STATUS_INVALID_STATUS),
    DEFINE_NIL_CONTEXT (CAIRO_STATUS_NULL_POINTER),
    DEFINE_NIL_CONTEXT (CAIRO_STATUS_INVALID_STRING),
    DEFINE_NIL_CONTEXT (CAIRO_STATUS_INVALID_PATH_DATA),
    DEFINE_NIL_CONTEXT (CAIRO_STATUS_READ_ERROR),
    DEFINE_NIL_CONTEXT (CAIRO_STATUS_WRITE_ERROR),
    DEFINE_NIL_CONTEXT (CAIRO_STATUS_SURFACE_FINISHED),
    DEFINE_NIL_CONTEXT (CAIRO_STATUS_SURFACE_TYPE_MISMATCH),
    DEFINE_NIL_CONTEXT (CAIRO_STATUS_PATTERN_TYPE_MISMATCH),
    DEFINE_NIL_CONTEXT (CAIRO_STATUS_INVALID_CONTENT),
    DEFINE_NIL_CONTEXT (CAIRO_STATUS_INVALID_FORMAT),
    DEFINE_NIL_CONTEXT (CAIRO_STATUS_INVALID_VISUAL),
    DEFINE_NIL_CONTEXT (CAIRO_STATUS_FILE_NOT_FOUND),
    DEFINE_NIL_CONTEXT (CAIRO_STATUS_INVALID_DASH),
    DEFINE_NIL_CONTEXT (CAIRO_STATUS_INVALID_DSC_COMMENT),
    DEFINE_NIL_CONTEXT (CAIRO_STATUS_INVALID_INDEX),
    DEFINE_NIL_CONTEXT (CAIRO_STATUS_CLIP_NOT_REPRESENTABLE),
    DEFINE_NIL_CONTEXT (CAIRO_STATUS_TEMP_FILE_ERROR),
    DEFINE_NIL_CONTEXT (CAIRO_STATUS_INVALID_STRIDE),
    DEFINE_NIL_CONTEXT (CAIRO_STATUS_FONT_TYPE_MISMATCH),
    DEFINE_NIL_CONTEXT (CAIRO_STATUS_USER_FONT_IMMUTABLE),
    DEFINE_NIL_CONTEXT (CAIRO_STATUS_USER_FONT_ERROR),
    DEFINE_NIL_CONTEXT (CAIRO_STATUS_NEGATIVE_COUNT),
    DEFINE_NIL_CONTEXT (CAIRO_STATUS_INVALID_CLUSTERS),
    DEFINE_NIL_CONTEXT (CAIRO_STATUS_INVALID_SLANT),
    DEFINE_NIL_CONTEXT (CAIRO_STATUS_INVALID_WEIGHT),
    DEFINE_NIL_CONTEXT (CAIRO_STATUS_INVALID_SIZE),
    DEFINE_NIL_CONTEXT (CAIRO_STATUS_USER_FONT_NOT_IMPLEMENTED),
    DEFINE_NIL_CONTEXT (CAIRO_STATUS_DEVICE_TYPE_MISMATCH),
    DEFINE_NIL_CONTEXT (CAIRO_STATUS_DEVICE_ERROR),
    DEFINE_NIL_CONTEXT (CAIRO_STATUS_INVALID_MESH_CONSTRUCTION),
    DEFINE_NIL_CONTEXT (CAIRO_STATUS_DEVICE_FINISHED),
    DEFINE_NIL_CONTEXT (CAIRO_STATUS_JBIG2_GLOBAL_MISSING),
    DEFINE_NIL_CONTEXT (CAIRO_STATUS_PNG_ERROR),
    DEFINE_NIL_CONTEXT (CAIRO_STATUS_FREETYPE_ERROR),
    DEFINE_NIL_CONTEXT (CAIRO_STATUS_WIN32_GDI_ERROR),
    DEFINE_NIL_CONTEXT (CAIRO_STATUS_TAG_ERROR),
    DEFINE_NIL_CONTEXT (CAIRO_STATUS_DWRITE_ERROR),
    DEFINE_NIL_CONTEXT (CAIRO_STATUS_SVG_FONT_ERROR)
};
COMPILE_TIME_ASSERT (ARRAY_LENGTH (_cairo_nil) == CAIRO_STATUS_LAST_STATUS - 1);

/**
 * _cairo_set_error:
 * @cr: a cairo context
 * @status: a status value indicating an error
 *
 * Atomically sets cr->status to @status and calls _cairo_error;
 * Does nothing if status is %CAIRO_STATUS_SUCCESS.
 *
 * All assignments of an error status to cr->status should happen
 * through _cairo_set_error(). Note that due to the nature of the atomic
 * operation, it is not safe to call this function on the nil objects.
 *
 * The purpose of this function is to allow the user to set a
 * breakpoint in _cairo_error() to generate a stack trace for when the
 * user causes cairo to detect an error.
 **/

static void
_cairo_set_error (cairo_t *cr, cairo_status_t status)
{
    /* Don't overwrite an existing error. This preserves the first
     * error, which is the most significant. */

    _cairo_status_set_error (&cr->status, _cairo_error (status));
}

cairo_t *
_cairo_create_in_error (cairo_status_t status)
{
    cairo_t *cr;

    assert (status != CAIRO_STATUS_SUCCESS);

    cr = (cairo_t *) &_cairo_nil[status - CAIRO_STATUS_NO_MEMORY];
    assert (status == cr->status);

    return cr;
}

/**
 * cairo_create:
 * @target: target surface for the context
 *
 * Creates a new #cairo_t with all graphics state parameters set to
 * default values and with @target as a target surface. The target
 * surface should be constructed with a backend-specific function such
 * as cairo_image_surface_create() (or any other
 * <function>cairo_<emphasis>backend</emphasis>_surface_create(<!-- -->)</function>
 * variant).
 *
 * This function references @target, so you can immediately
 * call cairo_surface_destroy() on it if you don't need to
 * maintain a separate reference to it.
 *
 * Return value: a newly allocated #cairo_t with a reference
 *  count of 1. The initial reference count should be released
 *  with cairo_destroy() when you are done using the #cairo_t.
 *  This function never returns %NULL. If memory cannot be
 *  allocated, a special #cairo_t object will be returned on
 *  which cairo_status() returns %CAIRO_STATUS_NO_MEMORY. If
 *  you attempt to target a surface which does not support
 *  writing (such as #cairo_mime_surface_t) then a
 *  %CAIRO_STATUS_WRITE_ERROR will be raised.  You can use this
 *  object normally, but no drawing will be done.
 *
 * Since: 1.0
 **/

cairo_t *
cairo_create (cairo_surface_t *target)
{
    if (unlikely (target == NULL))
 return _cairo_create_in_error (_cairo_error (CAIRO_STATUS_NULL_POINTER));
    if (unlikely (target->status))
 return _cairo_create_in_error (target->status);
    if (unlikely (target->finished))
 return _cairo_create_in_error (_cairo_error (CAIRO_STATUS_SURFACE_FINISHED));

    if (target->backend->create_context == NULL)
 return _cairo_create_in_error (_cairo_error (CAIRO_STATUS_WRITE_ERROR));

    return target->backend->create_context (target);

}

void
_cairo_init (cairo_t *cr,
      const cairo_backend_t *backend)
{
    CAIRO_REFERENCE_COUNT_INIT (&cr->ref_count, 1);
    cr->status = CAIRO_STATUS_SUCCESS;
    _cairo_user_data_array_init (&cr->user_data);

    cr->backend = backend;
}

/**
 * cairo_reference:
 * @cr: a #cairo_t
 *
 * Increases the reference count on @cr by one. This prevents
 * @cr from being destroyed until a matching call to cairo_destroy()
 * is made.
 *
 * Use cairo_get_reference_count() to get the number of references to
 * a #cairo_t.
 *
 * Return value: the referenced #cairo_t.
 *
 * Since: 1.0
 **/

cairo_t *
cairo_reference (cairo_t *cr)
{
    if (cr == NULL || CAIRO_REFERENCE_COUNT_IS_INVALID (&cr->ref_count))
 return cr;

    assert (CAIRO_REFERENCE_COUNT_HAS_REFERENCE (&cr->ref_count));

    _cairo_reference_count_inc (&cr->ref_count);

    return cr;
}

void
_cairo_fini (cairo_t *cr)
{
    _cairo_user_data_array_fini (&cr->user_data);
}

/**
 * cairo_destroy:
 * @cr: a #cairo_t
 *
 * Decreases the reference count on @cr by one. If the result
 * is zero, then @cr and all associated resources are freed.
 * See cairo_reference().
 *
 * Since: 1.0
 **/

void
cairo_destroy (cairo_t *cr)
{
    if (cr == NULL || CAIRO_REFERENCE_COUNT_IS_INVALID (&cr->ref_count))
 return;

    assert (CAIRO_REFERENCE_COUNT_HAS_REFERENCE (&cr->ref_count));

    if (! _cairo_reference_count_dec_and_test (&cr->ref_count))
 return;

    cr->backend->destroy (cr);
}

/**
 * cairo_get_user_data:
 * @cr: a #cairo_t
 * @key: the address of the #cairo_user_data_key_t the user data was
 * attached to
 *
 * Return user data previously attached to @cr using the specified
 * key.  If no user data has been attached with the given key this
 * function returns %NULL.
 *
 * Return value: the user data previously attached or %NULL.
 *
 * Since: 1.4
 **/

void *
cairo_get_user_data (cairo_t    *cr,
       const cairo_user_data_key_t *key)
{
    return _cairo_user_data_array_get_data (&cr->user_data, key);
}

/**
 * cairo_set_user_data:
 * @cr: a #cairo_t
 * @key: the address of a #cairo_user_data_key_t to attach the user data to
 * @user_data: the user data to attach to the #cairo_t
 * @destroy: a #cairo_destroy_func_t which will be called when the
 * #cairo_t is destroyed or when new user data is attached using the
 * same key.
 *
 * Attach user data to @cr.  To remove user data from a surface,
 * call this function with the key that was used to set it and %NULL
 * for @data.
 *
 * Return value: %CAIRO_STATUS_SUCCESS or %CAIRO_STATUS_NO_MEMORY if a
 * slot could not be allocated for the user data.
 *
 * Since: 1.4
 **/

cairo_status_t
cairo_set_user_data (cairo_t    *cr,
       const cairo_user_data_key_t *key,
       void    *user_data,
       cairo_destroy_func_t  destroy)
{
    if (CAIRO_REFERENCE_COUNT_IS_INVALID (&cr->ref_count))
 return cr->status;

    return _cairo_user_data_array_set_data (&cr->user_data,
         key, user_data, destroy);
}

/**
 * cairo_get_reference_count:
 * @cr: a #cairo_t
 *
 * Returns the current reference count of @cr.
 *
 * Return value: the current reference count of @cr.  If the
 * object is a nil object, 0 will be returned.
 *
 * Since: 1.4
 **/

unsigned int
cairo_get_reference_count (cairo_t *cr)
{
    if (cr == NULL || CAIRO_REFERENCE_COUNT_IS_INVALID (&cr->ref_count))
 return 0;

    return CAIRO_REFERENCE_COUNT_GET_VALUE (&cr->ref_count);
}

/**
 * cairo_save:
 * @cr: a #cairo_t
 *
 * Makes a copy of the current state of @cr and saves it
 * on an internal stack of saved states for @cr. When
 * cairo_restore() is called, @cr will be restored to
 * the saved state. Multiple calls to cairo_save() and
 * cairo_restore() can be nested; each call to cairo_restore()
 * restores the state from the matching paired cairo_save().
 *
 * It isn't necessary to clear all saved states before
 * a #cairo_t is freed. If the reference count of a #cairo_t
 * drops to zero in response to a call to cairo_destroy(),
 * any saved states will be freed along with the #cairo_t.
 *
 * Since: 1.0
 **/

void
cairo_save (cairo_t *cr)
{
    cairo_status_t status;

    if (unlikely (cr->status))
 return;

    status = cr->backend->save (cr);
    if (unlikely (status))
 _cairo_set_error (cr, status);
}

/**
 * cairo_restore:
 * @cr: a #cairo_t
 *
 * Restores @cr to the state saved by a preceding call to
 * cairo_save() and removes that state from the stack of
 * saved states.
 *
 * Since: 1.0
 **/

void
cairo_restore (cairo_t *cr)
{
    cairo_status_t status;

    if (unlikely (cr->status))
 return;

    status = cr->backend->restore (cr);
    if (unlikely (status))
 _cairo_set_error (cr, status);
}

/**
 * cairo_push_group:
 * @cr: a cairo context
 *
 * Temporarily redirects drawing to an intermediate surface known as a
 * group. The redirection lasts until the group is completed by a call
 * to cairo_pop_group() or cairo_pop_group_to_source(). These calls
 * provide the result of any drawing to the group as a pattern,
 * (either as an explicit object, or set as the source pattern).
 *
 * This group functionality can be convenient for performing
 * intermediate compositing. One common use of a group is to render
 * objects as opaque within the group, (so that they occlude each
 * other), and then blend the result with translucence onto the
 * destination.
 *
 * Groups can be nested arbitrarily deep by making balanced calls to
 * cairo_push_group()/cairo_pop_group(). Each call pushes/pops the new
 * target group onto/from a stack.
 *
 * The cairo_push_group() function calls cairo_save() so that any
 * changes to the graphics state will not be visible outside the
 * group, (the pop_group functions call cairo_restore()).
 *
 * By default the intermediate group will have a content type of
 * %CAIRO_CONTENT_COLOR_ALPHA. Other content types can be chosen for
 * the group by using cairo_push_group_with_content() instead.
 *
 * As an example, here is how one might fill and stroke a path with
 * translucence, but without any portion of the fill being visible
 * under the stroke:
 *
 * <informalexample><programlisting>
 * cairo_push_group (cr);
 * cairo_set_source (cr, fill_pattern);
 * cairo_fill_preserve (cr);
 * cairo_set_source (cr, stroke_pattern);
 * cairo_stroke (cr);
 * cairo_pop_group_to_source (cr);
 * cairo_paint_with_alpha (cr, alpha);
 * </programlisting></informalexample>
 *
 * Since: 1.2
 **/

void
cairo_push_group (cairo_t *cr)
{
    cairo_push_group_with_content (cr, CAIRO_CONTENT_COLOR_ALPHA);
}

/**
 * cairo_push_group_with_content:
 * @cr: a cairo context
 * @content: a #cairo_content_t indicating the type of group that
 *           will be created
 *
 * Temporarily redirects drawing to an intermediate surface known as a
 * group. The redirection lasts until the group is completed by a call
 * to cairo_pop_group() or cairo_pop_group_to_source(). These calls
 * provide the result of any drawing to the group as a pattern,
 * (either as an explicit object, or set as the source pattern).
 *
 * The group will have a content type of @content. The ability to
 * control this content type is the only distinction between this
 * function and cairo_push_group() which you should see for a more
 * detailed description of group rendering.
 *
 * Since: 1.2
 **/

void
cairo_push_group_with_content (cairo_t *cr, cairo_content_t content)
{
    cairo_status_t status;

    if (unlikely (cr->status))
 return;

    status = cr->backend->push_group (cr, content);
    if (unlikely (status))
 _cairo_set_error (cr, status);
}

/**
 * cairo_pop_group:
 * @cr: a cairo context
 *
 * Terminates the redirection begun by a call to cairo_push_group() or
 * cairo_push_group_with_content() and returns a new pattern
 * containing the results of all drawing operations performed to the
 * group.
 *
 * The cairo_pop_group() function calls cairo_restore(), (balancing a
 * call to cairo_save() by the push_group function), so that any
 * changes to the graphics state will not be visible outside the
 * group.
 *
 * Return value: a newly created (surface) pattern containing the
 * results of all drawing operations performed to the group. The
 * caller owns the returned object and should call
 * cairo_pattern_destroy() when finished with it.
 *
 * Since: 1.2
 **/

cairo_pattern_t *
cairo_pop_group (cairo_t *cr)
{
    cairo_pattern_t *group_pattern;

    if (unlikely (cr->status))
 return _cairo_pattern_create_in_error (cr->status);

    group_pattern = cr->backend->pop_group (cr);
    if (unlikely (group_pattern->status))
 _cairo_set_error (cr, group_pattern->status);

    return group_pattern;
}

/**
 * cairo_pop_group_to_source:
 * @cr: a cairo context
 *
 * Terminates the redirection begun by a call to cairo_push_group() or
 * cairo_push_group_with_content() and installs the resulting pattern
 * as the source pattern in the given cairo context.
 *
 * The behavior of this function is equivalent to the sequence of
 * operations:
 *
 * <informalexample><programlisting>
 * cairo_pattern_t *group = cairo_pop_group (cr);
 * cairo_set_source (cr, group);
 * cairo_pattern_destroy (group);
 * </programlisting></informalexample>
 *
 * but is more convenient as their is no need for a variable to store
 * the short-lived pointer to the pattern.
 *
 * The cairo_pop_group() function calls cairo_restore(), (balancing a
 * call to cairo_save() by the push_group function), so that any
 * changes to the graphics state will not be visible outside the
 * group.
 *
 * Since: 1.2
 **/

void
cairo_pop_group_to_source (cairo_t *cr)
{
    cairo_pattern_t *group_pattern;

    group_pattern = cairo_pop_group (cr);
    cairo_set_source (cr, group_pattern);
    cairo_pattern_destroy (group_pattern);
}

/**
 * cairo_set_operator:
 * @cr: a #cairo_t
 * @op: a compositing operator, specified as a #cairo_operator_t
 *
 * Sets the compositing operator to be used for all drawing
 * operations. See #cairo_operator_t for details on the semantics of
 * each available compositing operator.
 *
 * The default operator is %CAIRO_OPERATOR_OVER.
 *
 * Since: 1.0
 **/

void
cairo_set_operator (cairo_t *cr, cairo_operator_t op)
{
    cairo_status_t status;

    if (unlikely (cr->status))
 return;

    status = cr->backend->set_operator (cr, op);
    if (unlikely (status))
 _cairo_set_error (cr, status);
}


#if 0
/*
 * cairo_set_opacity:
 * @cr: a #cairo_t
 * @opacity: the level of opacity to use when compositing
 *
 * Sets the compositing opacity to be used for all drawing
 * operations. The effect is to fade out the operations
 * using the alpha value.
 *
 * The default opacity is 1.
 */

void
cairo_set_opacity (cairo_t *cr, double opacity)
{
    cairo_status_t status;

    if (unlikely (cr->status))
 return;

    status = cr->backend->set_opacity (cr, opacity);
    if (unlikely (status))
 _cairo_set_error (cr, status);
}
#endif

/**
 * cairo_set_source_rgb:
 * @cr: a cairo context
 * @red: red component of color
 * @green: green component of color
 * @blue: blue component of color
 *
 * Sets the source pattern within @cr to an opaque color. This opaque
 * color will then be used for any subsequent drawing operation until
 * a new source pattern is set.
 *
 * The color components are floating point numbers in the range 0 to
 * 1. If the values passed in are outside that range, they will be
 * clamped.
 *
 * The default source pattern is opaque black, (that is, it is
 * equivalent to cairo_set_source_rgb(cr, 0.0, 0.0, 0.0)).
 *
 * Since: 1.0
 **/

void
cairo_set_source_rgb (cairo_t *cr, double red, double green, double blue)
{
    cairo_status_t status;

    if (unlikely (cr->status))
 return;

    status = cr->backend->set_source_rgba (cr, red, green, blue, 1.);
    if (unlikely (status))
 _cairo_set_error (cr, status);
}

/**
 * cairo_set_source_rgba:
 * @cr: a cairo context
 * @red: red component of color
 * @green: green component of color
 * @blue: blue component of color
 * @alpha: alpha component of color
 *
 * Sets the source pattern within @cr to a translucent color. This
 * color will then be used for any subsequent drawing operation until
 * a new source pattern is set.
 *
 * The color and alpha components are floating point numbers in the
 * range 0 to 1. If the values passed in are outside that range, they
 * will be clamped.
 *
 * Note that the color and alpha values are not premultiplied.
 *
 * The default source pattern is opaque black, (that is, it is
 * equivalent to cairo_set_source_rgba(cr, 0.0, 0.0, 0.0, 1.0)).
 *
 * Since: 1.0
 **/

void
cairo_set_source_rgba (cairo_t *cr,
         double red, double green, double blue,
         double alpha)
{
    cairo_status_t status;

    if (unlikely (cr->status))
 return;

    status = cr->backend->set_source_rgba (cr, red, green, blue, alpha);
    if (unlikely (status))
 _cairo_set_error (cr, status);
}

/**
 * cairo_set_source_surface:
 * @cr: a cairo context
 * @surface: a surface to be used to set the source pattern
 * @x: User-space X coordinate for surface origin
 * @y: User-space Y coordinate for surface origin
 *
 * This is a convenience function for creating a pattern from @surface
 * and setting it as the source in @cr with cairo_set_source().
 *
 * The @x and @y parameters give the user-space coordinate at which
 * the surface origin should appear. (The surface origin is its
 * upper-left corner before any transformation has been applied.) The
 * @x and @y parameters are negated and then set as translation values
 * in the pattern matrix.
 *
 * Other than the initial translation pattern matrix, as described
 * above, all other pattern attributes, (such as its extend mode), are
 * set to the default values as in cairo_pattern_create_for_surface().
 * The resulting pattern can be queried with cairo_get_source() so
 * that these attributes can be modified if desired, (eg. to create a
 * repeating pattern with cairo_pattern_set_extend()).
 *
 * Since: 1.0
 **/

void
cairo_set_source_surface (cairo_t   *cr,
     cairo_surface_t *surface,
     double    x,
     double    y)
{
    cairo_status_t status;

    if (unlikely (cr->status))
 return;

    if (unlikely (surface == NULL)) {
 _cairo_set_error (cr, CAIRO_STATUS_NULL_POINTER);
 return;
    }

    status = cr->backend->set_source_surface (cr, surface, x, y);
    if (unlikely (status))
 _cairo_set_error (cr, status);
}

/**
 * cairo_set_source:
 * @cr: a cairo context
 * @source: a #cairo_pattern_t to be used as the source for
 * subsequent drawing operations.
 *
 * Sets the source pattern within @cr to @source. This pattern
 * will then be used for any subsequent drawing operation until a new
 * source pattern is set.
 *
 * Note: The pattern's transformation matrix will be locked to the
 * user space in effect at the time of cairo_set_source(). This means
 * that further modifications of the current transformation matrix
 * will not affect the source pattern. See cairo_pattern_set_matrix().
 *
 * The default source pattern is a solid pattern that is opaque black,
 * (that is, it is equivalent to cairo_set_source_rgb(cr, 0.0, 0.0,
 * 0.0)).
 *
 * Since: 1.0
 **/

void
cairo_set_source (cairo_t *cr, cairo_pattern_t *source)
{
    cairo_status_t status;

    if (unlikely (cr->status))
 return;

    if (unlikely (source == NULL)) {
 _cairo_set_error (cr, CAIRO_STATUS_NULL_POINTER);
 return;
    }

    if (unlikely (source->status)) {
 _cairo_set_error (cr, source->status);
 return;
    }

    status = cr->backend->set_source (cr, source);
    if (unlikely (status))
 _cairo_set_error (cr, status);
}

/**
 * cairo_get_source:
 * @cr: a cairo context
 *
 * Gets the current source pattern for @cr.
 *
 * Return value: the current source pattern. This object is owned by
 * cairo. To keep a reference to it, you must call
 * cairo_pattern_reference().
 *
 * Since: 1.0
 **/

cairo_pattern_t *
cairo_get_source (cairo_t *cr)
{
    if (unlikely (cr->status))
 return _cairo_pattern_create_in_error (cr->status);

    return cr->backend->get_source (cr);
}

/**
 * cairo_set_tolerance:
 * @cr: a #cairo_t
 * @tolerance: the tolerance, in device units (typically pixels)
 *
 * Sets the tolerance used when converting paths into trapezoids.
 * Curved segments of the path will be subdivided until the maximum
 * deviation between the original path and the polygonal approximation
 * is less than @tolerance. The default value is 0.1. A larger
 * value will give better performance, a smaller value, better
 * appearance. (Reducing the value from the default value of 0.1
 * is unlikely to improve appearance significantly.)  The accuracy of paths
 * within Cairo is limited by the precision of its internal arithmetic, and
 * the prescribed @tolerance is restricted to the smallest
 * representable internal value.
 *
 * Since: 1.0
 **/

void
cairo_set_tolerance (cairo_t *cr, double tolerance)
{
    cairo_status_t status;

    if (unlikely (cr->status))
 return;

    status = cr->backend->set_tolerance (cr, tolerance);
    if (unlikely (status))
 _cairo_set_error (cr, status);
}

/**
 * cairo_set_antialias:
 * @cr: a #cairo_t
 * @antialias: the new antialiasing mode
 *
 * Set the antialiasing mode of the rasterizer used for drawing shapes.
 * This value is a hint, and a particular backend may or may not support
 * a particular value.  At the current time, no backend supports
 * %CAIRO_ANTIALIAS_SUBPIXEL when drawing shapes.
 *
 * Note that this option does not affect text rendering, instead see
 * cairo_font_options_set_antialias().
 *
 * Since: 1.0
 **/

void
cairo_set_antialias (cairo_t *cr, cairo_antialias_t antialias)
{
    cairo_status_t status;

    if (unlikely (cr->status))
 return;

    status = cr->backend->set_antialias (cr, antialias);
    if (unlikely (status))
 _cairo_set_error (cr, status);
}

/**
 * cairo_set_fill_rule:
 * @cr: a #cairo_t
 * @fill_rule: a fill rule, specified as a #cairo_fill_rule_t
 *
 * Set the current fill rule within the cairo context. The fill rule
 * is used to determine which regions are inside or outside a complex
 * (potentially self-intersecting) path. The current fill rule affects
 * both cairo_fill() and cairo_clip(). See #cairo_fill_rule_t for details
 * on the semantics of each available fill rule.
 *
 * The default fill rule is %CAIRO_FILL_RULE_WINDING.
 *
 * Since: 1.0
 **/

void
cairo_set_fill_rule (cairo_t *cr, cairo_fill_rule_t fill_rule)
{
    cairo_status_t status;

    if (unlikely (cr->status))
 return;

    status = cr->backend->set_fill_rule (cr, fill_rule);
    if (unlikely (status))
 _cairo_set_error (cr, status);
}

/**
 * cairo_set_line_width:
 * @cr: a #cairo_t
 * @width: a line width
 *
 * Sets the current line width within the cairo context. The line
 * width value specifies the diameter of a pen that is circular in
 * user space, (though device-space pen may be an ellipse in general
 * due to scaling/shear/rotation of the CTM).
 *
 * Note: When the description above refers to user space and CTM it
 * refers to the user space and CTM in effect at the time of the
 * stroking operation, not the user space and CTM in effect at the
 * time of the call to cairo_set_line_width(). The simplest usage
 * makes both of these spaces identical. That is, if there is no
 * change to the CTM between a call to cairo_set_line_width() and the
 * stroking operation, then one can just pass user-space values to
 * cairo_set_line_width() and ignore this note.
 *
 * As with the other stroke parameters, the current line width is
 * examined by cairo_stroke(), and cairo_stroke_extents(), but does not have
 * any effect during path construction.
 *
 * The default line width value is 2.0.
 *
 * Since: 1.0
 **/

void
cairo_set_line_width (cairo_t *cr, double width)
{
    cairo_status_t status;

    if (unlikely (cr->status))
 return;

    if (width < 0.)
 width = 0.;

    status = cr->backend->set_line_width (cr, width);
    if (unlikely (status))
 _cairo_set_error (cr, status);
}

/**
 * cairo_set_hairline:
 * @cr: a #cairo_t
 * @set_hairline: whether or not to set hairline mode
 *
 * Sets lines within the cairo context to be hairlines.
 * Hairlines are logically zero-width lines that are drawn at the
 * thinnest renderable width possible in the current context.
 *
 * On surfaces with native hairline support, the native hairline
 * functionality will be used. Surfaces that support hairlines include:
 * - pdf/ps: Encoded as 0-width line.
 * - win32_printing: Rendered with PS_COSMETIC pen.
 * - svg: Encoded as 1px non-scaling-stroke.
 * - script: Encoded with set-hairline function.
 *
 * Cairo will always render hairlines at 1 device unit wide, even if
 * an anisotropic scaling was applied to the stroke width. In the wild,
 * handling of this situation is not well-defined. Some PDF, PS, and SVG
 * renderers match Cairo's output, but some very popular implementations
 * (Acrobat, Chrome, rsvg) will scale the hairline unevenly.
 * As such, best practice is to reset any anisotropic scaling before calling
 * cairo_stroke(). See https://cairographics.org/cookbook/ellipses/
 * for an example.
 *
 * Since: 1.18
 **/

void
cairo_set_hairline (cairo_t *cr, cairo_bool_t set_hairline)
{
    cairo_status_t status;

    if (unlikely (cr->status))
 return;

    status = cr->backend->set_hairline (cr, set_hairline);
    if (unlikely (status))
 _cairo_set_error (cr, status);
}

/**
 * cairo_set_line_cap:
 * @cr: a cairo context
 * @line_cap: a line cap style
 *
 * Sets the current line cap style within the cairo context. See
 * #cairo_line_cap_t for details about how the available line cap
 * styles are drawn.
 *
 * As with the other stroke parameters, the current line cap style is
 * examined by cairo_stroke(), and cairo_stroke_extents(), but does not have
 * any effect during path construction.
 *
 * The default line cap style is %CAIRO_LINE_CAP_BUTT.
 *
 * Since: 1.0
 **/

void
cairo_set_line_cap (cairo_t *cr, cairo_line_cap_t line_cap)
{
    cairo_status_t status;

    if (unlikely (cr->status))
 return;

    status = cr->backend->set_line_cap (cr, line_cap);
    if (unlikely (status))
 _cairo_set_error (cr, status);
}

/**
 * cairo_set_line_join:
 * @cr: a cairo context
 * @line_join: a line join style
 *
 * Sets the current line join style within the cairo context. See
 * #cairo_line_join_t for details about how the available line join
 * styles are drawn.
 *
 * As with the other stroke parameters, the current line join style is
 * examined by cairo_stroke(), and cairo_stroke_extents(), but does not have
 * any effect during path construction.
 *
 * The default line join style is %CAIRO_LINE_JOIN_MITER.
 *
 * Since: 1.0
 **/

void
cairo_set_line_join (cairo_t *cr, cairo_line_join_t line_join)
{
    cairo_status_t status;

    if (unlikely (cr->status))
 return;

    status = cr->backend->set_line_join (cr, line_join);
    if (unlikely (status))
 _cairo_set_error (cr, status);
}

/**
 * cairo_set_dash:
 * @cr: a cairo context
 * @dashes: an array specifying alternate lengths of on and off stroke portions
 * @num_dashes: the length of the dashes array
 * @offset: an offset into the dash pattern at which the stroke should start
 *
 * Sets the dash pattern to be used by cairo_stroke(). A dash pattern
 * is specified by @dashes, an array of positive values. Each value
 * provides the length of alternate "on" and "off" portions of the
 * stroke. The @offset specifies an offset into the pattern at which
 * the stroke begins.
 *
 * Each "on" segment will have caps applied as if the segment were a
 * separate sub-path. In particular, it is valid to use an "on" length
 * of 0.0 with %CAIRO_LINE_CAP_ROUND or %CAIRO_LINE_CAP_SQUARE in order
 * to distributed dots or squares along a path.
 *
 * Note: The length values are in user-space units as evaluated at the
 * time of stroking. This is not necessarily the same as the user
 * space at the time of cairo_set_dash().
 *
 * If @num_dashes is 0 dashing is disabled.
 *
 * If @num_dashes is 1 a symmetric pattern is assumed with alternating
 * on and off portions of the size specified by the single value in
 * @dashes.
 *
 * If any value in @dashes is negative, or if all values are 0, then
 * @cr will be put into an error state with a status of
 * %CAIRO_STATUS_INVALID_DASH.
 *
 * Since: 1.0
 **/

void
cairo_set_dash (cairo_t      *cr,
  const double *dashes,
  int       num_dashes,
  double       offset)
{
    cairo_status_t status;

    if (unlikely (cr->status))
 return;

    status = cr->backend->set_dash (cr, dashes, num_dashes, offset);
    if (unlikely (status))
 _cairo_set_error (cr, status);
}

/**
 * cairo_get_dash_count:
 * @cr: a #cairo_t
 *
 * This function returns the length of the dash array in @cr (0 if dashing
 * is not currently in effect).
 *
 * See also cairo_set_dash() and cairo_get_dash().
 *
 * Return value: the length of the dash array, or 0 if no dash array set.
 *
 * Since: 1.4
 **/

int
cairo_get_dash_count (cairo_t *cr)
{
    int num_dashes;

    if (unlikely (cr->status))
 return 0;

    cr->backend->get_dash (cr, NULL, &num_dashes, NULL);

    return num_dashes;
}

/**
 * cairo_get_dash:
 * @cr: a #cairo_t
 * @dashes: return value for the dash array, or %NULL
 * @offset: return value for the current dash offset, or %NULL
 *
 * Gets the current dash array.  If not %NULL, @dashes should be big
 * enough to hold at least the number of values returned by
 * cairo_get_dash_count().
 *
 * Since: 1.4
 **/

void
cairo_get_dash (cairo_t *cr,
  double  *dashes,
  double  *offset)
{
    if (unlikely (cr->status))
 return;

    cr->backend->get_dash (cr, dashes, NULL, offset);
}

/**
 * cairo_set_miter_limit:
 * @cr: a cairo context
 * @limit: miter limit to set
 *
 * Sets the current miter limit within the cairo context.
 *
 * If the current line join style is set to %CAIRO_LINE_JOIN_MITER
 * (see cairo_set_line_join()), the miter limit is used to determine
 * whether the lines should be joined with a bevel instead of a miter.
 * Cairo divides the length of the miter by the line width.
 * If the result is greater than the miter limit, the style is
 * converted to a bevel.
 *
 * As with the other stroke parameters, the current line miter limit is
 * examined by cairo_stroke(), and cairo_stroke_extents(), but does not have
 * any effect during path construction.
 *
 * The default miter limit value is 10.0, which will convert joins
 * with interior angles less than 11 degrees to bevels instead of
 * miters. For reference, a miter limit of 2.0 makes the miter cutoff
 * at 60 degrees, and a miter limit of 1.414 makes the cutoff at 90
 * degrees.
 *
 * A miter limit for a desired angle can be computed as: miter limit =
 * 1/sin(angle/2)
 *
 * Since: 1.0
 **/

void
cairo_set_miter_limit (cairo_t *cr, double limit)
{
    cairo_status_t status;

    if (unlikely (cr->status))
 return;

    status = cr->backend->set_miter_limit (cr, limit);
    if (unlikely (status))
 _cairo_set_error (cr, status);
}

/**
 * cairo_translate:
 * @cr: a cairo context
 * @tx: amount to translate in the X direction
 * @ty: amount to translate in the Y direction
 *
 * Modifies the current transformation matrix (CTM) by translating the
 * user-space origin by (@tx, @ty). This offset is interpreted as a
 * user-space coordinate according to the CTM in place before the new
 * call to cairo_translate(). In other words, the translation of the
 * user-space origin takes place after any existing transformation.
 *
 * Since: 1.0
 **/

void
cairo_translate (cairo_t *cr, double tx, double ty)
{
    cairo_status_t status;

    if (unlikely (cr->status))
 return;

    status = cr->backend->translate (cr, tx, ty);
    if (unlikely (status))
 _cairo_set_error (cr, status);
}

/**
 * cairo_scale:
 * @cr: a cairo context
 * @sx: scale factor for the X dimension
 * @sy: scale factor for the Y dimension
 *
 * Modifies the current transformation matrix (CTM) by scaling the X
 * and Y user-space axes by @sx and @sy respectively. The scaling of
 * the axes takes place after any existing transformation of user
 * space.
 *
 * Since: 1.0
 **/

void
cairo_scale (cairo_t *cr, double sx, double sy)
{
    cairo_status_t status;

    if (unlikely (cr->status))
 return;

    status = cr->backend->scale (cr, sx, sy);
    if (unlikely (status))
 _cairo_set_error (cr, status);
}

/**
 * cairo_rotate:
 * @cr: a cairo context
 * @angle: angle (in radians) by which the user-space axes will be
 * rotated
 *
 * Modifies the current transformation matrix (CTM) by rotating the
 * user-space axes by @angle radians. The rotation of the axes takes
 * places after any existing transformation of user space. The
 * rotation direction for positive angles is from the positive X axis
 * toward the positive Y axis.
 *
 * Since: 1.0
 **/

void
cairo_rotate (cairo_t *cr, double angle)
{
    cairo_status_t status;

    if (unlikely (cr->status))
 return;

    status = cr->backend->rotate (cr, angle);
    if (unlikely (status))
 _cairo_set_error (cr, status);
}

/**
 * cairo_transform:
 * @cr: a cairo context
 * @matrix: a transformation to be applied to the user-space axes
 *
 * Modifies the current transformation matrix (CTM) by applying
 * @matrix as an additional transformation. The new transformation of
 * user space takes place after any existing transformation.
 *
 * Since: 1.0
 **/

void
cairo_transform (cairo_t       *cr,
   const cairo_matrix_t *matrix)
{
    cairo_status_t status;

    if (unlikely (cr->status))
 return;

    status = cr->backend->transform (cr, matrix);
    if (unlikely (status))
 _cairo_set_error (cr, status);
}

/**
 * cairo_set_matrix:
 * @cr: a cairo context
 * @matrix: a transformation matrix from user space to device space
 *
 * Modifies the current transformation matrix (CTM) by setting it
 * equal to @matrix.
 *
 * Since: 1.0
 **/

void
cairo_set_matrix (cairo_t        *cr,
    const cairo_matrix_t *matrix)
{
    cairo_status_t status;

    if (unlikely (cr->status))
 return;

    status = cr->backend->set_matrix (cr, matrix);
    if (unlikely (status))
 _cairo_set_error (cr, status);
}

/**
 * cairo_identity_matrix:
 * @cr: a cairo context
 *
 * Resets the current transformation matrix (CTM) by setting it equal
 * to the identity matrix. That is, the user-space and device-space
 * axes will be aligned and one user-space unit will transform to one
 * device-space unit.
 *
 * Since: 1.0
 **/

void
cairo_identity_matrix (cairo_t *cr)
{
    cairo_status_t status;

    if (unlikely (cr->status))
 return;

    status = cr->backend->set_identity_matrix (cr);
    if (unlikely (status))
 _cairo_set_error (cr, status);
}

/**
 * cairo_user_to_device:
 * @cr: a cairo context
 * @x: X value of coordinate (in/out parameter)
 * @y: Y value of coordinate (in/out parameter)
 *
 * Transform a coordinate from user space to device space by
 * multiplying the given point by the current transformation matrix
 * (CTM).
 *
 * Since: 1.0
 **/

void
cairo_user_to_device (cairo_t *cr, double *x, double *y)
{
    if (unlikely (cr->status))
 return;

    cr->backend->user_to_device (cr, x, y);
}

/**
 * cairo_user_to_device_distance:
 * @cr: a cairo context
 * @dx: X component of a distance vector (in/out parameter)
 * @dy: Y component of a distance vector (in/out parameter)
 *
 * Transform a distance vector from user space to device space. This
 * function is similar to cairo_user_to_device() except that the
 * translation components of the CTM will be ignored when transforming
 * (@dx,@dy).
 *
 * Since: 1.0
 **/

void
cairo_user_to_device_distance (cairo_t *cr, double *dx, double *dy)
{
    if (unlikely (cr->status))
 return;

    cr->backend->user_to_device_distance (cr, dx, dy);
}

/**
 * cairo_device_to_user:
 * @cr: a cairo
 * @x: X value of coordinate (in/out parameter)
 * @y: Y value of coordinate (in/out parameter)
 *
 * Transform a coordinate from device space to user space by
 * multiplying the given point by the inverse of the current
 * transformation matrix (CTM).
 *
 * Since: 1.0
 **/

void
cairo_device_to_user (cairo_t *cr, double *x, double *y)
{
    if (unlikely (cr->status))
 return;

    cr->backend->device_to_user (cr, x, y);
}

/**
 * cairo_device_to_user_distance:
 * @cr: a cairo context
 * @dx: X component of a distance vector (in/out parameter)
 * @dy: Y component of a distance vector (in/out parameter)
 *
 * Transform a distance vector from device space to user space. This
 * function is similar to cairo_device_to_user() except that the
 * translation components of the inverse CTM will be ignored when
 * transforming (@dx,@dy).
 *
 * Since: 1.0
 **/

void
cairo_device_to_user_distance (cairo_t *cr, double *dx, double *dy)
{
    if (unlikely (cr->status))
 return;

    cr->backend->device_to_user_distance (cr, dx, dy);
}

/**
 * cairo_new_path:
 * @cr: a cairo context
 *
 * Clears the current path. After this call there will be no path and
 * no current point.
 *
 * Since: 1.0
 **/

void
cairo_new_path (cairo_t *cr)
{
    cairo_status_t status;

    if (unlikely (cr->status))
 return;

    status = cr->backend->new_path (cr);
    if (unlikely (status))
 _cairo_set_error (cr, status);
}

/**
 * cairo_new_sub_path:
 * @cr: a cairo context
 *
 * Begin a new sub-path. Note that the existing path is not
 * affected. After this call there will be no current point.
 *
 * In many cases, this call is not needed since new sub-paths are
 * frequently started with cairo_move_to().
 *
 * A call to cairo_new_sub_path() is particularly useful when
 * beginning a new sub-path with one of the cairo_arc() calls. This
 * makes things easier as it is no longer necessary to manually
 * compute the arc's initial coordinates for a call to
 * cairo_move_to().
 *
 * Since: 1.2
 **/

void
cairo_new_sub_path (cairo_t *cr)
{
    cairo_status_t status;

    if (unlikely (cr->status))
 return;

    status = cr->backend->new_sub_path (cr);
    if (unlikely (status))
 _cairo_set_error (cr, status);
}

/**
 * cairo_move_to:
 * @cr: a cairo context
 * @x: the X coordinate of the new position
 * @y: the Y coordinate of the new position
 *
 * Begin a new sub-path. After this call the current point will be (@x,
 * @y).
 *
 * Since: 1.0
 **/

void
cairo_move_to (cairo_t *cr, double x, double y)
{
    cairo_status_t status;

    if (unlikely (cr->status))
 return;

    status = cr->backend->move_to (cr, x, y);
    if (unlikely (status))
 _cairo_set_error (cr, status);
}

/**
 * cairo_line_to:
 * @cr: a cairo context
 * @x: the X coordinate of the end of the new line
 * @y: the Y coordinate of the end of the new line
 *
 * Adds a line to the path from the current point to position (@x, @y)
 * in user-space coordinates. After this call the current point
 * will be (@x, @y).
 *
 * If there is no current point before the call to cairo_line_to()
 * this function will behave as cairo_move_to(@cr, @x, @y).
 *
 * Since: 1.0
 **/

void
cairo_line_to (cairo_t *cr, double x, double y)
{
    cairo_status_t status;

    if (unlikely (cr->status))
 return;

    status = cr->backend->line_to (cr, x, y);
    if (unlikely (status))
 _cairo_set_error (cr, status);
}

/**
 * cairo_curve_to:
 * @cr: a cairo context
 * @x1: the X coordinate of the first control point
 * @y1: the Y coordinate of the first control point
 * @x2: the X coordinate of the second control point
 * @y2: the Y coordinate of the second control point
 * @x3: the X coordinate of the end of the curve
 * @y3: the Y coordinate of the end of the curve
 *
 * Adds a cubic Bézier spline to the path from the current point to
 * position (@x3, @y3) in user-space coordinates, using (@x1, @y1) and
 * (@x2, @y2) as the control points. After this call the current point
 * will be (@x3, @y3).
 *
 * If there is no current point before the call to cairo_curve_to()
 * this function will behave as if preceded by a call to
 * cairo_move_to(@cr, @x1, @y1).
 *
 * Since: 1.0
 **/

void
cairo_curve_to (cairo_t *cr,
  double x1, double y1,
  double x2, double y2,
  double x3, double y3)
{
    cairo_status_t status;

    if (unlikely (cr->status))
 return;

    status = cr->backend->curve_to (cr,
        x1, y1,
        x2, y2,
        x3, y3);
    if (unlikely (status))
 _cairo_set_error (cr, status);
}

/**
 * cairo_arc:
 * @cr: a cairo context
 * @xc: X position of the center of the arc
 * @yc: Y position of the center of the arc
 * @radius: the radius of the arc
 * @angle1: the start angle, in radians
 * @angle2: the end angle, in radians
 *
 * Adds a circular arc of the given @radius to the current path.  The
 * arc is centered at (@xc, @yc), begins at @angle1 and proceeds in
 * the direction of increasing angles to end at @angle2. If @angle2 is
 * less than @angle1 it will be progressively increased by
 * <literal>2*M_PI</literal> until it is greater than @angle1.
 *
 * If there is a current point, an initial line segment will be added
 * to the path to connect the current point to the beginning of the
 * arc. If this initial line is undesired, it can be avoided by
 * calling cairo_new_sub_path() before calling cairo_arc().
 *
 * Angles are measured in radians. An angle of 0.0 is in the direction
 * of the positive X axis (in user space). An angle of
 * <literal>M_PI/2.0</literal> radians (90 degrees) is in the
 * direction of the positive Y axis (in user space). Angles increase
 * in the direction from the positive X axis toward the positive Y
 * axis. So with the default transformation matrix, angles increase in
 * a clockwise direction.
 *
 * (To convert from degrees to radians, use <literal>degrees * (M_PI /
 * 180.)</literal>.)
 *
 * This function gives the arc in the direction of increasing angles;
 * see cairo_arc_negative() to get the arc in the direction of
 * decreasing angles.
 *
 * The arc is circular in user space. To achieve an elliptical arc,
 * you can scale the current transformation matrix by different
 * amounts in the X and Y directions. For example, to draw an ellipse
 * in the box given by @x, @y, @width, @height:
 *
 * <informalexample><programlisting>
 * cairo_save (cr);
 * cairo_translate (cr, x + width / 2., y + height / 2.);
 * cairo_scale (cr, width / 2., height / 2.);
 * cairo_arc (cr, 0., 0., 1., 0., 2 * M_PI);
 * cairo_restore (cr);
 * </programlisting></informalexample>
 *
 * Since: 1.0
 **/

void
cairo_arc (cairo_t *cr,
    double xc, double yc,
    double radius,
    double angle1, double angle2)
{
    cairo_status_t status;

    if (unlikely (cr->status))
 return;

    if (angle2 < angle1) {
 /* increase angle2 by multiples of full circle until it
 * satisfies angle2 >= angle1 */

 angle2 = fmod (angle2 - angle1, 2 * M_PI);
 if (angle2 < 0)
     angle2 += 2 * M_PI;
 angle2 += angle1;
    }

    status = cr->backend->arc (cr, xc, yc, radius, angle1, angle2, TRUE);
    if (unlikely (status))
 _cairo_set_error (cr, status);
}

/**
 * cairo_arc_negative:
 * @cr: a cairo context
 * @xc: X position of the center of the arc
 * @yc: Y position of the center of the arc
 * @radius: the radius of the arc
 * @angle1: the start angle, in radians
 * @angle2: the end angle, in radians
 *
 * Adds a circular arc of the given @radius to the current path.  The
 * arc is centered at (@xc, @yc), begins at @angle1 and proceeds in
 * the direction of decreasing angles to end at @angle2. If @angle2 is
 * greater than @angle1 it will be progressively decreased by
 * <literal>2*M_PI</literal> until it is less than @angle1.
 *
 * See cairo_arc() for more details. This function differs only in the
 * direction of the arc between the two angles.
 *
 * Since: 1.0
 **/

void
cairo_arc_negative (cairo_t *cr,
      double xc, double yc,
      double radius,
      double angle1, double angle2)
{
    cairo_status_t status;

    if (unlikely (cr->status))
 return;

    if (angle2 > angle1) {
 /* decrease angle2 by multiples of full circle until it
 * satisfies angle2 <= angle1 */

 angle2 = fmod (angle2 - angle1, 2 * M_PI);
 if (angle2 > 0)
     angle2 -= 2 * M_PI;
 angle2 += angle1;
    }

    status = cr->backend->arc (cr, xc, yc, radius, angle1, angle2, FALSE);
    if (unlikely (status))
 _cairo_set_error (cr, status);
}

/* XXX: NYI
void
cairo_arc_to (cairo_t *cr,
      double x1, double y1,
      double x2, double y2,
      double radius)
{
    cairo_status_t status;

    if (unlikely (cr->status))
return;

    status = cr->backend->arc_to (cr, x1, y1, x2, y2, radius);
    if (unlikely (status))
_cairo_set_error (cr, status);
}

void
cairo_rel_arc_to (cairo_t *cr,
      double dx1, double dy1,
      double dx2, double dy2,
      double radius)
{
    cairo_status_t status;

    if (unlikely (cr->status))
return;

    status = cr->backend->rel_arc_to (cr, dx1, dy1, dx2, dy2, radius);
    if (unlikely (status))
_cairo_set_error (cr, status);
}
*/


/**
 * cairo_rel_move_to:
 * @cr: a cairo context
 * @dx: the X offset
 * @dy: the Y offset
 *
 * Begin a new sub-path. After this call the current point will offset
 * by (@x, @y).
 *
 * Given a current point of (x, y), cairo_rel_move_to(@cr, @dx, @dy)
 * is logically equivalent to cairo_move_to(@cr, x + @dx, y + @dy).
 *
 * It is an error to call this function with no current point. Doing
 * so will cause @cr to shutdown with a status of
 * %CAIRO_STATUS_NO_CURRENT_POINT.
 *
 * Since: 1.0
 **/

void
cairo_rel_move_to (cairo_t *cr, double dx, double dy)
{
    cairo_status_t status;

    if (unlikely (cr->status))
 return;

    status = cr->backend->rel_move_to (cr, dx, dy);
    if (unlikely (status))
 _cairo_set_error (cr, status);
}

/**
 * cairo_rel_line_to:
 * @cr: a cairo context
 * @dx: the X offset to the end of the new line
 * @dy: the Y offset to the end of the new line
 *
 * Relative-coordinate version of cairo_line_to(). Adds a line to the
 * path from the current point to a point that is offset from the
 * current point by (@dx, @dy) in user space. After this call the
 * current point will be offset by (@dx, @dy).
 *
 * Given a current point of (x, y), cairo_rel_line_to(@cr, @dx, @dy)
 * is logically equivalent to cairo_line_to(@cr, x + @dx, y + @dy).
 *
 * It is an error to call this function with no current point. Doing
 * so will cause @cr to shutdown with a status of
 * %CAIRO_STATUS_NO_CURRENT_POINT.
 *
 * Since: 1.0
 **/

void
cairo_rel_line_to (cairo_t *cr, double dx, double dy)
{
    cairo_status_t status;

    if (unlikely (cr->status))
 return;

    status = cr->backend->rel_line_to (cr, dx, dy);
    if (unlikely (status))
 _cairo_set_error (cr, status);
}

/**
 * cairo_rel_curve_to:
 * @cr: a cairo context
 * @dx1: the X offset to the first control point
 * @dy1: the Y offset to the first control point
 * @dx2: the X offset to the second control point
 * @dy2: the Y offset to the second control point
 * @dx3: the X offset to the end of the curve
 * @dy3: the Y offset to the end of the curve
 *
 * Relative-coordinate version of cairo_curve_to(). All offsets are
 * relative to the current point. Adds a cubic Bézier spline to the
 * path from the current point to a point offset from the current
 * point by (@dx3, @dy3), using points offset by (@dx1, @dy1) and
 * (@dx2, @dy2) as the control points. After this call the current
 * point will be offset by (@dx3, @dy3).
 *
 * Given a current point of (x, y), cairo_rel_curve_to(@cr, @dx1,
 * @dy1, @dx2, @dy2, @dx3, @dy3) is logically equivalent to
 * cairo_curve_to(@cr, x+@dx1, y+@dy1, x+@dx2, y+@dy2, x+@dx3, y+@dy3).
 *
 * It is an error to call this function with no current point. Doing
 * so will cause @cr to shutdown with a status of
 * %CAIRO_STATUS_NO_CURRENT_POINT.
 *
 * Since: 1.0
 **/

void
cairo_rel_curve_to (cairo_t *cr,
      double dx1, double dy1,
      double dx2, double dy2,
      double dx3, double dy3)
{
    cairo_status_t status;

    if (unlikely (cr->status))
 return;

    status = cr->backend->rel_curve_to (cr,
     dx1, dy1,
     dx2, dy2,
     dx3, dy3);
    if (unlikely (status))
 _cairo_set_error (cr, status);
}

/**
 * cairo_rectangle:
 * @cr: a cairo context
 * @x: the X coordinate of the top left corner of the rectangle
 * @y: the Y coordinate to the top left corner of the rectangle
 * @width: the width of the rectangle
 * @height: the height of the rectangle
 *
 * Adds a closed sub-path rectangle of the given size to the current
 * path at position (@x, @y) in user-space coordinates.
 *
 * This function is logically equivalent to:
 * <informalexample><programlisting>
 * cairo_move_to (cr, x, y);
 * cairo_rel_line_to (cr, width, 0);
 * cairo_rel_line_to (cr, 0, height);
 * cairo_rel_line_to (cr, -width, 0);
 * cairo_close_path (cr);
 * </programlisting></informalexample>
 *
 * Since: 1.0
 **/

void
cairo_rectangle (cairo_t *cr,
   double x, double y,
   double width, double height)
{
    cairo_status_t status;

    if (unlikely (cr->status))
 return;

    status = cr->backend->rectangle (cr, x, y, width, height);
    if (unlikely (status))
 _cairo_set_error (cr, status);
}

#if 0
/* XXX: NYI */
void
cairo_stroke_to_path (cairo_t *cr)
{
    cairo_status_t status;

    if (unlikely (cr->status))
 return;

    /* The code in _cairo_recording_surface_get_path has a poorman's stroke_to_path */

    status = _cairo_gstate_stroke_path (cr->gstate);
    if (unlikely (status))
 _cairo_set_error (cr, status);
}
#endif

/**
 * cairo_close_path:
 * @cr: a cairo context
 *
 * Adds a line segment to the path from the current point to the
 * beginning of the current sub-path, (the most recent point passed to
 * cairo_move_to()), and closes this sub-path. After this call the
 * current point will be at the joined endpoint of the sub-path.
 *
 * The behavior of cairo_close_path() is distinct from simply calling
 * cairo_line_to() with the equivalent coordinate in the case of
 * stroking. When a closed sub-path is stroked, there are no caps on
 * the ends of the sub-path. Instead, there is a line join connecting
 * the final and initial segments of the sub-path.
 *
 * If there is no current point before the call to cairo_close_path(),
 * this function will have no effect.
 *
 * Note: As of cairo version 1.2.4 any call to cairo_close_path() will
 * place an explicit MOVE_TO element into the path immediately after
 * the CLOSE_PATH element, (which can be seen in cairo_copy_path() for
 * example). This can simplify path processing in some cases as it may
 * not be necessary to save the "last move_to point" during processing
 * as the MOVE_TO immediately after the CLOSE_PATH will provide that
 * point.
 *
 * Since: 1.0
 **/

void
cairo_close_path (cairo_t *cr)
{
    cairo_status_t status;

    if (unlikely (cr->status))
 return;

    status = cr->backend->close_path (cr);
    if (unlikely (status))
 _cairo_set_error (cr, status);
}

/**
 * cairo_path_extents:
 * @cr: a cairo context
 * @x1: left of the resulting extents
 * @y1: top of the resulting extents
 * @x2: right of the resulting extents
 * @y2: bottom of the resulting extents
 *
 * Computes a bounding box in user-space coordinates covering the
 * points on the current path. If the current path is empty, returns
 * an empty rectangle ((0,0), (0,0)). Stroke parameters, fill rule,
 * surface dimensions and clipping are not taken into account.
 *
 * Contrast with cairo_fill_extents() and cairo_stroke_extents() which
--> --------------------

--> maximum size reached

--> --------------------

Messung V0.5
C=97 H=100 G=98

¤ Dauer der Verarbeitung: 0.12 Sekunden  (vorverarbeitet)  ¤

*© Formatika GbR, Deutschland






Wurzel

Suchen

Beweissystem der NASA

Beweissystem Isabelle

NIST Cobol Testsuite

Cephes Mathematical Library

Wiener Entwicklungsmethode

Haftungshinweis

Die Informationen auf dieser Webseite wurden nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit, noch Qualität der bereit gestellten Informationen zugesichert.

Bemerkung:

Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.






                                                                                                                                                                                                                                                                                                                                                                                                     


Neuigkeiten

     Aktuelles
     Motto des Tages

Software

     Produkte
     Quellcodebibliothek

Aktivitäten

     Artikel über Sicherheit
     Anleitung zur Aktivierung von SSL

Muße

     Gedichte
     Musik
     Bilder

Jenseits des Üblichen ....

Besucherstatistik

Besucherstatistik

Monitoring

Montastic status badge