⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 cairo.c

📁 按照官方的说法:Cairo is a vector graphics library with cross-device output support. 翻译过来
💻 C
📖 第 1 页 / 共 5 页
字号:
/* cairo - a vector graphics library with display and print output * * Copyright © 2002 University of Southern California * Copyright © 2005 Red Hat, Inc. * * 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 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> */#include "cairoint.h"#include "cairo-private.h"#include "cairo-arc-private.h"#include "cairo-path-data-private.h"#define CAIRO_TOLERANCE_MINIMUM	0.0002 /* We're limited by 16 bits of sub-pixel precision */static const cairo_t cairo_nil = {  (unsigned int)-1,		/* ref_count */  CAIRO_STATUS_NO_MEMORY,	/* status */  { 				/* path */    NULL, NULL,			/* op_buf_head, op_buf_tail */    NULL, NULL,			/* arg_buf_head, arg_buf_tail */    { 0, 0 },			/* last_move_point */    { 0, 0 },			/* current point */    FALSE,			/* has_current_point */  },  NULL				/* gstate */};#include <assert.h>/* This has to be updated whenever cairo_status_t is extended.  That's * a bit of a pain, but it should be easy to always catch as long as * one adds a new test case to test a trigger of the new status value. */#define CAIRO_STATUS_LAST_STATUS CAIRO_STATUS_INVALID_DSC_COMMENT/** * _cairo_error: * @status: a status value indicating an error, (eg. not * CAIRO_STATUS_SUCCESS) * * Checks that status is an error status, but does nothing else. * * All assignments of an error status to any user-visible object * within the cairo application should result in a call to * _cairo_error(). * * 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. **/void_cairo_error (cairo_status_t status){    assert (status > CAIRO_STATUS_SUCCESS &&	    status <= CAIRO_STATUS_LAST_STATUS);}/** * _cairo_set_error: * @cr: a cairo context * @status: a status value indicating an error, (eg. not * CAIRO_STATUS_SUCCESS) * * Sets cr->status to @status and calls _cairo_error; * * All assignments of an error status to cr->status should happen * through _cairo_set_error() or else _cairo_error() should be * called immediately after the assignment. * * 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. It also avoids attempting     * to write to read-only data (eg. from a nil cairo_t). */    if (cr->status == CAIRO_STATUS_SUCCESS)	cr->status = status;    _cairo_error (status);}/** * cairo_version: * * Returns the version of the cairo library encoded in a single * integer as per CAIRO_VERSION_ENCODE. The encoding ensures that * later versions compare greater than earlier versions. * * A run-time comparison to check that cairo's version is greater than * or equal to version X.Y.Z could be performed as follows: * * <informalexample><programlisting> * if (cairo_version() >= CAIRO_VERSION_ENCODE(X,Y,Z)) {...} * </programlisting></informalexample> * * See also cairo_version_string() as well as the compile-time * equivalents %CAIRO_VERSION and %CAIRO_VERSION_STRING. * * Return value: the encoded version. **/intcairo_version (void){    return CAIRO_VERSION;}/** * cairo_version_string: * * Returns the version of the cairo library as a human-readable string * of the form "X.Y.Z". * * See also cairo_version() as well as the compile-time equivalents * %CAIRO_VERSION_STRING and %CAIRO_VERSION. * * Return value: a string containing the version. **/const char*cairo_version_string (void){    return CAIRO_VERSION_STRING;}/** * 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 * <literal>cairo_&lt;backend&gt;_surface_create</literal> 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. *  You can use this object normally, but no drawing will *  be done. **/cairo_t *cairo_create (cairo_surface_t *target){    cairo_t *cr;    cr = malloc (sizeof (cairo_t));    if (cr == NULL)	return (cairo_t *) &cairo_nil;    cr->ref_count = 1;    cr->status = CAIRO_STATUS_SUCCESS;    _cairo_path_fixed_init (&cr->path);    if (target == NULL) {	cr->gstate = NULL;	_cairo_set_error (cr, CAIRO_STATUS_NULL_POINTER);	return cr;    }    cr->gstate = _cairo_gstate_create (target);    if (cr->gstate == NULL)	_cairo_set_error (cr, CAIRO_STATUS_NO_MEMORY);    return cr;}/** * 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. * * Return value: the referenced #cairo_t. **/cairo_t *cairo_reference (cairo_t *cr){    if (cr == NULL)	return NULL;    if (cr->ref_count == (unsigned int)-1)	return cr;    assert (cr->ref_count > 0);    cr->ref_count++;    return cr;}/** * 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(). **/voidcairo_destroy (cairo_t *cr){    if (cr == NULL)	return;    if (cr->ref_count == (unsigned int)-1)	return;    assert (cr->ref_count > 0);    cr->ref_count--;    if (cr->ref_count)	return;    while (cr->gstate) {	cairo_gstate_t *tmp = cr->gstate;	cr->gstate = tmp->next;	_cairo_gstate_destroy (tmp);    }    _cairo_path_fixed_fini (&cr->path);    free (cr);}/** * 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. **/voidcairo_save (cairo_t *cr){    cairo_gstate_t *top;    if (cr->status)	return;    top = _cairo_gstate_clone (cr->gstate);    if (top == NULL) {	_cairo_set_error (cr, CAIRO_STATUS_NO_MEMORY);	return;    }    top->next = cr->gstate;    cr->gstate = top;}slim_hidden_def(cairo_save);/** * 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. **/voidcairo_restore (cairo_t *cr){    cairo_gstate_t *top;    if (cr->status)	return;    top = cr->gstate;    cr->gstate = top->next;    _cairo_gstate_destroy (top);    if (cr->gstate == NULL)	_cairo_set_error (cr, CAIRO_STATUS_INVALID_RESTORE);}slim_hidden_def(cairo_restore);/** * 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 */voidcairo_push_group (cairo_t *cr){    cairo_push_group_with_content (cr, CAIRO_CONTENT_COLOR_ALPHA);}slim_hidden_def(cairo_push_group);/** * 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 */voidcairo_push_group_with_content (cairo_t *cr, cairo_content_t content){    cairo_status_t status;    cairo_rectangle_int16_t extents;    cairo_surface_t *group_surface = NULL;    /* Get the extents that we'll use in creating our new group surface */    _cairo_surface_get_extents (_cairo_gstate_get_target (cr->gstate), &extents);    status = _cairo_clip_intersect_to_rectangle (_cairo_gstate_get_clip (cr->gstate), &extents);    if (status != CAIRO_STATUS_SUCCESS)	goto bail;    group_surface = cairo_surface_create_similar (_cairo_gstate_get_target (cr->gstate),						  content,						  extents.width,						  extents.height);    status = cairo_surface_status (group_surface);    if (status)	goto bail;    /* Set device offsets on the new surface so that logically it appears at     * the same location on the parent surface -- when we pop_group this,     * the source pattern will get fixed up for the appropriate target surface     * device offsets, so we want to set our own surface offsets from /that/,     * and not from the device origin. */    cairo_surface_set_device_offset (group_surface,                                     cr->gstate->target->device_transform.x0 - extents.x,                                     cr->gstate->target->device_transform.y0 - extents.y);    /* create a new gstate for the redirect */    cairo_save (cr);    if (cr->status)	goto bail;    _cairo_gstate_redirect_target (cr->gstate, group_surface);bail:    cairo_surface_destroy (group_surface);    if (status)	_cairo_set_error (cr, status);}slim_hidden_def(cairo_push_group_with_content);/** * 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.

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -