Merge branch 'cairo-origin' into analysis-surface

With the string-array-stream stuff that this merge picks up, the
analysis-surface branch is now passing all of the test suite again.
This commit is contained in:
Carl Worth 2006-04-04 14:58:52 -07:00
commit 66ed9811cc
65 changed files with 1962 additions and 472 deletions

1
.gitignore vendored
View file

@ -1,3 +1,4 @@
ChangeLog
Makefile
Makefile.in
aclocal.m4

View file

@ -16,7 +16,7 @@ This final step may require temporary root access (eg. with sudo) if
you don't have write permission to the directory in which cairo will
be installed.
NOTE: If you are working with source from CVS rather than from a tar
NOTE: If you are working with source from git/cvs rather than from a tar
file, then you should use ./autogen.sh in place of ./configure
anywhere it is mentioned in these instructions.

View file

@ -11,6 +11,21 @@ EXTRA_DIST = \
COPYING-LGPL-2.1 \
COPYING-MPL-1.1 \
cairo.pc.in
MAINTAINERCLEANFILES = \
$(srcdir)/INSTALL \
$(srcdir)/aclocal.m4 \
$(srcdir)/autoscan.log \
$(srcdir)/compile \
$(srcdir)/config.guess \
$(srcdir)/config.h.in \
$(srcdir)/config.sub \
$(srcdir)/configure.scan \
$(srcdir)/depcomp \
$(srcdir)/install-sh \
$(srcdir)/ltmain.sh \
$(srcdir)/missing \
$(srcdir)/mkinstalldirs \
`find "$(srcdir)" -type f -name Makefile.in -print`
pkgconfigdir = $(libdir)/pkgconfig
pkgconfig_DATA = cairo.pc
@ -20,6 +35,30 @@ check-valgrind: all
DISTCHECK_CONFIGURE_FLAGS=--enable-gtk-doc
# Creating ChangeLog from git log:
MAINTAINERCLEANFILES += ChangeLog
EXTRA_DIST += ChangeLog
ChangeLog: $(srcdir)/ChangeLog
$(srcdir)/ChangeLog:
@if test -d "$(srcdir)/.git"; then \
(cd "$(srcdir)" && \
./missing --run git-log) | fmt --split-only > $@.tmp \
&& mv -f $@.tmp $@ \
|| ($(RM) $@.tmp; \
echo Failed to generate ChangeLog, your ChangeLog may be outdated >&2; \
(test -f $@ || echo git-log is required to generate this file >> $@)); \
else \
test -f $@ || \
(echo A git checkout and git-log is required to generate ChangeLog >&2 && \
echo A git checkout and git-log is required to generate this file >> $@); \
fi
.PHONY: ChangeLog $(srcdir)/ChangeLog
# Some custom targets to make it easier to release things.
# Use either:
# make release-check
@ -82,7 +121,7 @@ release-verify-newer:
@echo -n "Checking that no $(VERSION) release already exists..."
@ssh $(RELEASE_UPLOAD_HOST) test ! -e $(RELEASE_UPLOAD_DIR)/$(tar_file) \
|| (echo "Ouch." && echo "Found: $(RELEASE_UPLOAD_HOST):$(RELEASE_UPLOAD_DIR)/$(tar_file)" \
&& echo "Are you sure you have an updated CVS checkout?" \
&& echo "Are you sure you have an updated checkout?" \
&& echo "This should never happen." \
&& false)
@echo "Good."
@ -104,9 +143,9 @@ release-upload: release-check $(tar_file) $(sha1_file) $(gpg_file)
scp $(tar_file) $(sha1_file) $(gpg_file) $(RELEASE_UPLOAD_HOST):$(RELEASE_UPLOAD_DIR)
mv $(tar_file) $(sha1_file) $(gpg_file) releases
ssh $(RELEASE_UPLOAD_HOST) "rm -f $(RELEASE_UPLOAD_DIR)/LATEST-$(PACKAGE)-[0-9]* && ln -s $(tar_file) $(RELEASE_UPLOAD_DIR)/LATEST-$(PACKAGE)-$(VERSION)"
$(CVS) tag RELEASE_$(CAIRO_VERSION_MAJOR)_$(CAIRO_VERSION_MINOR)_$(CAIRO_VERSION_MICRO)
git tag -s $(CAIRO_VERSION_MAJOR).$(CAIRO_VERSION_MINOR).$(CAIRO_VERSION_MICRO)
release-publish: release-upload releases/$(sha1_file)
release-publish-message: releases/$(sha1_file)
@echo ""
@echo "Please send an announcement to $(RELEASE_ANNOUNCE_LIST)"
@echo "including the following:"
@ -133,6 +172,8 @@ release-publish: release-upload releases/$(sha1_file)
@echo "Last but not least, do not forget to bump up the micro"
@echo "version component to the next (odd) number and commit."
release-publish: release-upload release-publish-message
# XXX: Depending on all here is rather overkill. We don't really need
# the library built in order to create the documentation.
docs-publish: all

View file

@ -1,12 +1,7 @@
Here are the steps to follow to create a new cairo release:
1) Ensure that there are no local, uncommitted modifications. The best
thing to do here may be to begin with a fresh checkout from CVS:
cvs -d cairographics.org:/cvs/cairo co cairo
But it's probably good enough if "cvs -q update -Ad" generates no
output.
1) Ensure that there are no local, uncommitted modifications.
It's probably good enough if "git diff" doesn't output anything.
2) Verify that the code passes "make distcheck"
@ -32,7 +27,10 @@ Here are the steps to follow to create a new cairo release:
previous release tag:
find src/ -name '*.h' -not -name '*-private.h' -not -name 'cairoint.h' | \
xargs cvs diff -r RELEASE_X_Y_Z
xargs git diff X.Y.Z --
Note that for older releases made under CVS, the tag name is
RELEASE_X_Y_Z instead.
4) Increment cairo_version_{minor|micro} and LT_{CURRENT|VERSION|AGE}
in configure.in:
@ -55,9 +53,8 @@ Here are the steps to follow to create a new cairo release:
5) Commit the changes to NEWS and configure.in
Don't forget to fill out the ChangeLog just like with any
other commit. It's especially important to mention the new
version number in the ChangeLog.
It's especially important to mention the new version number in your
commit log.
6) Run "make release-publish" which will perform the following steps
for you:
@ -71,8 +68,13 @@ Here are the steps to follow to create a new cairo release:
* scp the three files to appear on http://cairographics.org/releases
* Place local copies of the three files in the releases directory
* Create a LATEST-package-version file (after deleting any old one)
* Tag the entire source tree with a tag of the form RELEASE_X_Y_Z
* Tag the entire source tree with a tag of the form X.Y.Z, and sign
the tag with your GPG key (asks for your GPG password, and you
may need to set GIT_COMMITTER_NAME and GIT_COMMITTER_EMAIL to match
your public-key's setting or this fails.)
* Provide some text for the release announcement (see below).
If for some reason you lost this message, "make release-publish-message"
prints it for you.
7) Increment cairo_version_micro to the next larger (odd) number in
configure, and commit.

View file

@ -1,7 +1,7 @@
AC_PREREQ(2.54)
# cairo package version number, (as distinct from shared library version)
# An odd micro number indicates in-progress development, (eg. from CVS)
# An odd micro number indicates in-progress development, (eg. from git/cvs)
# An even micro number indicates a released version.
m4_define(cairo_version_major, 1)
m4_define(cairo_version_minor, 1)
@ -810,6 +810,6 @@ if test x"$use_beos" = "xyes" ; then
echo "$WARNING_MESSAGE" | sed 's/@BACKEND@/BeOS/'
fi
if test x"$use_directfb" == "xyes" ; then
if test x"$use_directfb" = "xyes" ; then
echo "$WARNING_MESSAGE" | sed 's/@BACKEND@/DirectFB/'
fi

View file

@ -33,10 +33,18 @@
#include "pixregionint.h"
#ifdef _MSC_VER
#define _USE_MATH_DEFINES
#endif
#include <math.h>
// #define PIXMAN_CONVOLUTION
// #define PIXMAN_INDEXED_FORMATS
#ifndef M_PI
#define M_PI 3.14159265358979323846
#endif
/* #define PIXMAN_CONVOLUTION */
/* #define PIXMAN_INDEXED_FORMATS */
static Bool
PictureTransformPoint3d (pixman_transform_t *transform,

View file

@ -1,6 +1,4 @@
/*
* $Id: fbedge.c,v 1.3 2005-08-02 01:01:24 vektor Exp $
*
* Copyright © 2004 Keith Packard
*
* Permission to use, copy, modify, distribute, and sell this software and its

View file

@ -1,6 +1,4 @@
/*
* $Id: fbedgeimp.h,v 1.2 2005-01-21 18:38:42 cworth Exp $
*
* Copyright © 2004 Keith Packard
*
* Permission to use, copy, modify, distribute, and sell this software and its

View file

@ -1,6 +1,4 @@
/*
* $Id: fbpict.c,v 1.8 2006-01-21 17:39:11 biesi Exp $
*
* Copyright © 2000 SuSE, Inc.
*
* Permission to use, copy, modify, distribute, and sell this software and its
@ -1151,7 +1149,7 @@ fbCompositeTrans_0888xnx0888(pixman_operator_t op,
setupPackedReader(ws,wt,isrc,wsrc,workingSource);
/* get to word aligned */
switch(!(long)dst&3)
switch(~(long)dst&3)
{
case 1:
readPackedSource(rs);
@ -1227,7 +1225,7 @@ fbCompositeTrans_0888xnx0888(pixman_operator_t op,
srcLine += srcStride;
w = width*3;
/* get to word aligned */
switch(!(long)src&3)
switch(~(long)src&3)
{
case 1:
rd=alphamaskCombine24(*src++, *dst)>>8;

View file

@ -1,6 +1,4 @@
/*
* $Id: fbpict.h,v 1.2 2005-09-12 12:55:11 otaylor Exp $
*
* Copyright © 2000 Keith Packard
* 2005 Lars Knoll & Zack Rusin, Trolltech
*

View file

@ -1,6 +1,4 @@
/*
* $Id: icpixels.c,v 1.9 2005-06-25 03:13:19 jrmuizel Exp $
*
* Copyright © 1998 Keith Packard
*
* Permission to use, copy, modify, distribute, and sell this software and its

View file

@ -1,6 +1,4 @@
/*
* $Id: ictrap.c,v 1.27 2005-08-28 02:32:57 vektor Exp $
*
* Copyright © 2002 Keith Packard
*
* Permission to use, copy, modify, distribute, and sell this software and its

View file

@ -72,8 +72,8 @@ typedef pixman_triangle_t xTriangle;
#define FB_SHIFT IC_SHIFT
#define FB_MASK IC_MASK
#define FB_ALLONES IC_ALLONES
#define FbMaskBits IcMaskBits
*/
//#define FbMaskBits IcMaskBits
/* XXX: We changed some function and field names which makes for some
* ugly hacks... */

View file

@ -54,8 +54,6 @@ ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
SOFTWARE.
******************************************************************/
/* $Id: pixman.h,v 1.25 2006-01-05 00:26:10 cworth Exp $ */
/* libic.h */
/*

View file

@ -60,7 +60,7 @@ SOFTWARE.
#endif
#undef assert
#ifdef DEBUG
#ifdef DEBUG_PIXREGION
#define assert(expr) {if (!(expr)) \
FatalError("Assertion failed file %s, line %d: expr\n", \
__FILE__, __LINE__); }
@ -208,7 +208,7 @@ if (((numRects) < ((reg)->data->size >> 1)) && ((reg)->data->size > 50)) \
}
#ifdef DEBUG
#ifdef DEBUG_PIXREGION
int
pixman_region16_print(rgn)
pixman_region16_t * rgn;
@ -302,7 +302,7 @@ pixman_region16_valid(reg)
}
}
#endif /* DEBUG */
#endif /* DEBUG_PIXREGION */
/* Create a new empty region */

View file

@ -44,8 +44,6 @@ ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
SOFTWARE.
******************************************************************/
/* $Id: pixregionint.h,v 1.7 2004-04-16 15:32:53 cworth Exp $ */
#ifndef _PIXREGIONINT_H_
#define _PIXREGIONINT_H_

View file

@ -1,6 +1,4 @@
/*
* $Id: renderedge.c,v 1.2 2005-01-21 18:26:28 cworth Exp $
*
* Copyright © 2004 Keith Packard
*
* Permission to use, copy, modify, distribute, and sell this software and its

View file

@ -1,6 +1,4 @@
/*
* $Id: renderedge.h,v 1.3 2005-02-21 21:29:22 cworth Exp $
*
* Copyright © 2004 Keith Packard
*
* Permission to use, copy, modify, distribute, and sell this software and its

View file

@ -56,6 +56,11 @@ libcairo_beos_sources =
if CAIRO_HAS_BEOS_SURFACE
libcairo_beos_headers = cairo-beos.h
libcairo_beos_sources += cairo-beos-surface.cpp
noinst_LTLIBRARIES = libcairo_beos.la
libcairo_beos_la_SOURCES = $(libcairo_beos_sources)
# BeOS system headers trigger this warning
libcairo_beos_la_CXXFLAGS = -Wno-multichar
endif
if CAIRO_HAS_GLITZ_SURFACE
@ -129,6 +134,7 @@ libcairo_la_SOURCES = \
cairo-arc.c \
cairo-arc-private.h \
cairo-array.c \
cairo-base85-stream.c \
cairo-cache.c \
cairo-cache-private.h \
cairo-clip.c \
@ -145,6 +151,7 @@ libcairo_la_SOURCES = \
cairo-hash-private.h \
cairo-hull.c \
cairo-image-surface.c \
cairo-lzw.c \
cairo-matrix.c \
cairo-path.c \
cairo-path-bounds.c \
@ -193,15 +200,12 @@ libcairo_la_SOURCES = \
cairoint.h
libcairo_la_LDFLAGS = -version-info @VERSION_INFO@ -no-undefined $(export_symbols)
# this -Wno-multichar line is really just for the beos surface, because the
# system headers trigger this warning.
libcairo_la_CXXFLAGS = -Wno-multichar
INCLUDES = -I$(srcdir) -I$(top_srcdir)/pixman/src $(CAIRO_CFLAGS)
libcairo_la_LIBADD = $(top_builddir)/pixman/src/libpixman.la $(CAIRO_LIBS)
libcairo_la_LIBADD = $(top_builddir)/pixman/src/libpixman.la $(CAIRO_LIBS) $(noinst_LTLIBRARIES)
libcairo_la_DEPENDENCIES = $(cairo_def_dependency) $(top_builddir)/pixman/src/libpixman.la
libcairo_la_DEPENDENCIES = $(cairo_def_dependency) $(top_builddir)/pixman/src/libpixman.la $(noinst_LTLIBRARIES)
EXTRA_DIST = \
cairo.def

View file

@ -176,6 +176,7 @@ _cairo_analysis_surface_show_glyphs (void *abstract_surface,
}
static const cairo_surface_backend_t cairo_analysis_surface_backend = {
CAIRO_INTERNAL_SURFACE_TYPE_ANALYSIS,
NULL, /* create_similar */
NULL, /* finish_surface */
NULL, /* acquire_source_image */

View file

@ -40,6 +40,16 @@
#include "cairo.h"
#include "cairo-quartz-private.h"
/*
* FixedToFloat/FloatToFixed are 10.3+ SDK items - include definitions
* here so we can use older SDKs.
*/
#ifndef FixedToFloat
#define fixed1 ((Fixed) 0x00010000L)
#define FixedToFloat(a) ((float)(a) / fixed1)
#define FloatToFixed(a) ((Fixed)((float)(a) * fixed1))
#endif
typedef struct _cairo_atsui_font_face cairo_atsui_font_face_t;
typedef struct _cairo_atsui_font cairo_atsui_font_t;
@ -133,7 +143,7 @@ CreateSizedCopyOfStyle(ATSUStyle inStyle, const cairo_matrix_t *scale)
ATSUStyle style;
OSStatus err;
// Set the style's size
/* Set the style's size */
CGAffineTransform theTransform =
CGAffineTransformMakeWithCairoFontScale(scale);
Fixed theSize =
@ -175,7 +185,7 @@ _cairo_atsui_font_set_metrics (cairo_atsui_font_t *font)
extents.height = metrics.capHeight;
extents.max_x_advance = metrics.maxAdvanceWidth;
// The FT backend doesn't handle max_y_advance either, so we'll ignore it for now.
/* The FT backend doesn't handle max_y_advance either, so we'll ignore it for now. */
extents.max_y_advance = 0.0;
_cairo_scaled_font_set_metrics (&font->base, &extents);
@ -276,7 +286,7 @@ _cairo_atsui_font_create_toy(cairo_toy_font_face_t *toy_face,
kFontNoLanguageCode, &fontID);
if (err != noErr) {
// couldn't get the font - remap css names and try again
/* couldn't get the font - remap css names and try again */
if (!strcmp(family, "serif"))
family = "Times";
@ -288,7 +298,7 @@ _cairo_atsui_font_create_toy(cairo_toy_font_face_t *toy_face,
family = "Gadget";
else if (!strcmp(family, "monospace"))
family = "Courier";
else // anything else - return error instead?
else /* anything else - return error instead? */
family = "Courier";
err = ATSUFindFontFromName(family, strlen(family),
@ -505,7 +515,7 @@ _cairo_atsui_font_text_to_glyphs (void *abstract_font,
err = ATSUSetTextPointerLocation(textLayout, utf16, 0, n16, n16);
// Set the style for all of the text
/* Set the style for all of the text */
err = ATSUSetRunStyle(textLayout,
font->style, kATSUFromTextBeginning, kATSUToTextEnd);
@ -566,7 +576,7 @@ _cairo_atsui_font_old_show_glyphs (void *abstract_font,
&rect,
&extra);
// Create a CGBitmapContext for the dest surface for drawing into
/* Create a CGBitmapContext for the dest surface for drawing into */
colorSpace = CGColorSpaceCreateDeviceRGB();
myBitmapContext = CGBitmapContextCreate(destImageSurface->data,
@ -592,7 +602,7 @@ _cairo_atsui_font_old_show_glyphs (void *abstract_font,
CGContextSetFontSize(myBitmapContext, 1.0);
CGContextSetTextMatrix(myBitmapContext, textTransform);
if (pattern->type == CAIRO_PATTERN_SOLID &&
if (pattern->type == CAIRO_PATTERN_TYPE_SOLID &&
_cairo_pattern_is_opaque_solid(pattern))
{
cairo_solid_pattern_t *solid = (cairo_solid_pattern_t *)pattern;
@ -634,11 +644,12 @@ _cairo_atsui_font_old_show_glyphs (void *abstract_font,
/* XXX: Need to get the text clipped */
}
// TODO - bold and italic text
//
// We could draw the text using ATSUI and get bold, italics
// etc. for free, but ATSUI does a lot of text layout work
// that we don't really need...
/* TODO - bold and italic text
*
* We could draw the text using ATSUI and get bold, italics
* etc. for free, but ATSUI does a lot of text layout work
* that we don't really need...
*/
for (i = 0; i < num_glyphs; i++) {
@ -664,6 +675,7 @@ _cairo_atsui_font_old_show_glyphs (void *abstract_font,
}
const cairo_scaled_font_backend_t cairo_atsui_scaled_font_backend = {
CAIRO_FONT_TYPE_ATSUI,
_cairo_atsui_font_create_toy,
_cairo_atsui_font_fini,
_cairo_atsui_font_scaled_glyph_init,

130
src/cairo-base85-stream.c Normal file
View file

@ -0,0 +1,130 @@
/* cairo_output_stream.c: Output stream abstraction
*
* 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 cairo_output_stream.c as distributed with the
* cairo graphics library.
*
* The Initial Developer of the Original Code is Red Hat, Inc.
*
* Author(s):
* Kristian Høgsberg <krh@redhat.com>
*/
#include "cairoint.h"
typedef struct _cairo_base85_stream {
cairo_output_stream_t *output;
unsigned char four_tuple[4];
int pending;
} cairo_base85_stream_t;
static void
_expand_four_tuple_to_five (unsigned char four_tuple[4],
unsigned char five_tuple[5],
cairo_bool_t *all_zero)
{
uint32_t value;
int digit, i;
value = four_tuple[0] << 24 | four_tuple[1] << 16 | four_tuple[2] << 8 | four_tuple[3];
if (all_zero)
*all_zero = TRUE;
for (i = 0; i < 5; i++) {
digit = value % 85;
if (digit != 0 && all_zero)
*all_zero = FALSE;
five_tuple[4-i] = digit + 33;
value = value / 85;
}
}
static cairo_status_t
_cairo_base85_stream_write_data (void *closure,
const unsigned char *data,
unsigned int length)
{
cairo_base85_stream_t *stream = closure;
const unsigned char *ptr = data;
unsigned char five_tuple[5];
cairo_bool_t is_zero;
while (length) {
stream->four_tuple[stream->pending++] = *ptr++;
length--;
if (stream->pending == 4) {
_expand_four_tuple_to_five (stream->four_tuple, five_tuple, &is_zero);
if (is_zero)
_cairo_output_stream_write (stream->output, "z", 1);
else
_cairo_output_stream_write (stream->output, five_tuple, 5);
stream->pending = 0;
}
}
return _cairo_output_stream_get_status (stream->output);
}
static cairo_status_t
_cairo_base85_stream_close (void *closure)
{
cairo_status_t status;
cairo_base85_stream_t *stream = closure;
unsigned char five_tuple[5];
if (stream->pending) {
memset (stream->four_tuple + stream->pending, 0, 4 - stream->pending);
_expand_four_tuple_to_five (stream->four_tuple, five_tuple, NULL);
_cairo_output_stream_write (stream->output, five_tuple, stream->pending + 1);
}
/* Mark end of base85 data */
_cairo_output_stream_printf (stream->output, "~>");
status = _cairo_output_stream_get_status (stream->output);
free (stream);
return status;
}
cairo_output_stream_t *
_cairo_base85_stream_create (cairo_output_stream_t *output)
{
cairo_base85_stream_t *stream;
stream = malloc (sizeof (cairo_base85_stream_t));
if (stream == NULL)
return (cairo_output_stream_t *) &cairo_output_stream_nil;
stream->output = output;
stream->pending = 0;
return _cairo_output_stream_create (_cairo_base85_stream_write_data,
_cairo_base85_stream_close,
stream);
}

View file

@ -70,6 +70,9 @@ struct cairo_beos_surface_t {
BBitmap* bitmap;
// If true, surface and view should be deleted when this surface is
// destroyed
bool owns_bitmap_view;
};
class AutoLockView {
@ -92,6 +95,11 @@ class AutoLockView {
bool mOK;
};
static cairo_surface_t *
_cairo_beos_surface_create_internal (BView* view,
BBitmap* bmp,
bool owns_bitmap_view = false);
static BRect
_cairo_rect_to_brect (const cairo_rectangle_t* rect)
{
@ -359,6 +367,7 @@ _cairo_image_surface_to_bitmap (cairo_image_surface_t* surface)
return data;
}
default:
assert(0);
return NULL;
}
}
@ -414,10 +423,76 @@ _cairo_op_to_be_op (cairo_operator_t cairo_op,
};
}
static cairo_surface_t *
_cairo_beos_surface_create_similar (void *abstract_surface,
cairo_content_t content,
int width,
int height)
{
fprintf(stderr, "Creating similar\n");
cairo_beos_surface_t *surface = reinterpret_cast<cairo_beos_surface_t*>(
abstract_surface);
if (width <= 0)
width = 1;
if (height <= 0)
height = 1;
BRect rect(0.0, 0.0, width - 1, height - 1);
BBitmap* bmp;
switch (content) {
case CAIRO_CONTENT_ALPHA:
// Can't support this natively
return _cairo_image_surface_create_with_content(content, width,
height);
case CAIRO_CONTENT_COLOR_ALPHA:
bmp = new BBitmap(rect, B_RGBA32, true);
break;
case CAIRO_CONTENT_COLOR:
// Match the color depth
if (surface->bitmap) {
color_space space = surface->bitmap->ColorSpace();
// No alpha was requested -> make sure not to return
// a surface with alpha
if (space == B_RGBA32)
space = B_RGB32;
if (space == B_RGBA15)
space = B_RGB15;
bmp = new BBitmap(rect, space, true);
} else {
BScreen scr(surface->view->Window());
color_space space = B_RGB32;
if (scr.IsValid())
space = scr.ColorSpace();
bmp = new BBitmap(rect, space, true);
}
break;
default:
assert(0);
return NULL;
};
BView* view = new BView(rect, "Cairo bitmap view", B_FOLLOW_ALL_SIDES, 0);
bmp->AddChild(view);
return _cairo_beos_surface_create_internal(view, bmp, true);
}
static cairo_status_t
_cairo_beos_surface_finish (void *abstract_surface)
{
// Nothing to do
cairo_beos_surface_t *surface = reinterpret_cast<cairo_beos_surface_t*>(
abstract_surface);
if (surface->owns_bitmap_view) {
if (surface->bitmap)
surface->bitmap->RemoveChild(surface->view);
delete surface->view;
delete surface->bitmap;
surface->view = NULL;
surface->bitmap = NULL;
}
return CAIRO_STATUS_SUCCESS;
}
@ -549,13 +624,12 @@ _cairo_beos_surface_release_dest_image (void *abstract_surface,
cairo_beos_surface_t *surface = reinterpret_cast<cairo_beos_surface_t*>(
abstract_surface);
AutoLockView locker(surface->view);
if (!locker)
return;
BBitmap* bitmap_to_draw = _cairo_image_surface_to_bitmap(image);
surface->view->PushState();
surface->view->SetDrawingMode(B_OP_COPY);
@ -570,18 +644,18 @@ _cairo_beos_surface_release_dest_image (void *abstract_surface,
}
static cairo_int_status_t
_cairo_beos_composite (cairo_operator_t op,
cairo_pattern_t *src,
cairo_pattern_t *mask,
void *dst,
int src_x,
int src_y,
int mask_x,
int mask_y,
int dst_x,
int dst_y,
unsigned int width,
unsigned int height)
_cairo_beos_surface_composite (cairo_operator_t op,
cairo_pattern_t *src,
cairo_pattern_t *mask,
void *dst,
int src_x,
int src_y,
int mask_x,
int mask_y,
int dst_x,
int dst_y,
unsigned int width,
unsigned int height)
{
cairo_beos_surface_t *surface = reinterpret_cast<cairo_beos_surface_t*>(
dst);
@ -598,7 +672,7 @@ _cairo_beos_composite (cairo_operator_t op,
return CAIRO_INT_STATUS_UNSUPPORTED;
// XXX should eventually support the others
if (src->type != CAIRO_PATTERN_SURFACE ||
if (src->type != CAIRO_PATTERN_TYPE_SURFACE ||
src->extend != CAIRO_EXTEND_NONE)
{
return CAIRO_INT_STATUS_UNSUPPORTED;
@ -617,63 +691,95 @@ _cairo_beos_composite (cairo_operator_t op,
cairo_surface_t* src_surface = reinterpret_cast<cairo_surface_pattern_t*>(src)->
surface;
if (_cairo_surface_is_image(src_surface)) {
fprintf(stderr, "Composite\n");
// Draw it on screen.
// Get a bitmap
BBitmap* bmp = NULL;
bool free_bmp = false;
if (_cairo_surface_is_image(src_surface)) {
cairo_image_surface_t* img_surface =
reinterpret_cast<cairo_image_surface_t*>(src_surface);
BBitmap* bmp = _cairo_image_surface_to_bitmap(img_surface);
surface->view->PushState();
// If our image rect is only a subrect of the desired size, and we
// aren't using B_OP_ALPHA, then we need to fill the rect first.
if (mode == B_OP_COPY && !bmp->Bounds().Contains(srcRect)) {
rgb_color black = { 0, 0, 0, 0 };
surface->view->SetDrawingMode(mode);
surface->view->SetHighColor(black);
surface->view->FillRect(dstRect);
}
if (mode == B_OP_ALPHA && img_surface->format != CAIRO_FORMAT_ARGB32) {
mode = B_OP_COPY;
}
surface->view->SetDrawingMode(mode);
if (surface->bitmap && surface->bitmap->ColorSpace() == B_RGBA32)
surface->view->SetBlendingMode(B_PIXEL_ALPHA, B_ALPHA_COMPOSITE);
else
surface->view->SetBlendingMode(B_PIXEL_ALPHA, B_ALPHA_OVERLAY);
surface->view->DrawBitmap(bmp, srcRect, dstRect);
surface->view->PopState();
delete bmp;
return CAIRO_INT_STATUS_SUCCESS;
bmp = _cairo_image_surface_to_bitmap(img_surface);
free_bmp = true;
} else if (src_surface->backend == surface->base.backend) {
cairo_beos_surface_t *beos_surface =
reinterpret_cast<cairo_beos_surface_t*>(src_surface);
if (beos_surface->bitmap) {
AutoLockView locker(beos_surface->view);
if (locker)
beos_surface->view->Sync();
bmp = beos_surface->bitmap;
} else {
_cairo_beos_view_to_bitmap(surface->view, &bmp);
free_bmp = true;
}
}
return CAIRO_INT_STATUS_UNSUPPORTED;
if (!bmp)
return CAIRO_INT_STATUS_UNSUPPORTED;
// So, BeOS seems to screw up painting an opaque bitmap onto a
// translucent one (it makes them partly transparent). Just return
// unsupported.
if (bmp->ColorSpace() == B_RGB32 && surface->bitmap &&
surface->bitmap->ColorSpace() == B_RGBA32 &&
(mode == B_OP_COPY || mode == B_OP_ALPHA))
{
if (free_bmp)
delete bmp;
return CAIRO_INT_STATUS_UNSUPPORTED;
}
fprintf(stderr, "Composite\n");
// Draw it on screen.
surface->view->PushState();
// If our image rect is only a subrect of the desired size, and we
// aren't using B_OP_ALPHA, then we need to fill the rect first.
if (mode == B_OP_COPY && !bmp->Bounds().Contains(srcRect)) {
rgb_color black = { 0, 0, 0, 0 };
surface->view->SetDrawingMode(mode);
surface->view->SetHighColor(black);
surface->view->FillRect(dstRect);
}
if (mode == B_OP_ALPHA && bmp->ColorSpace() == B_RGB32) {
mode = B_OP_COPY;
}
surface->view->SetDrawingMode(mode);
if (surface->bitmap && surface->bitmap->ColorSpace() == B_RGBA32)
surface->view->SetBlendingMode(B_PIXEL_ALPHA, B_ALPHA_COMPOSITE);
else
surface->view->SetBlendingMode(B_PIXEL_ALPHA, B_ALPHA_OVERLAY);
surface->view->DrawBitmap(bmp, srcRect, dstRect);
surface->view->PopState();
if (free_bmp)
delete bmp;
return CAIRO_INT_STATUS_SUCCESS;
}
static void
_cairo_beos_fill_rectangle (cairo_beos_surface_t *surface,
cairo_rectangle_t *rect)
_cairo_beos_surface_fill_rectangle (cairo_beos_surface_t *surface,
cairo_rectangle_t *rect)
{
BRect brect(_cairo_rect_to_brect(rect));
surface->view->FillRect(brect);
}
static cairo_int_status_t
_cairo_beos_fill_rectangles (void *abstract_surface,
cairo_operator_t op,
const cairo_color_t *color,
cairo_rectangle_t *rects,
int num_rects)
_cairo_beos_surface_fill_rectangles (void *abstract_surface,
cairo_operator_t op,
const cairo_color_t *color,
cairo_rectangle_t *rects,
int num_rects)
{
fprintf(stderr, "Drawing %i rectangles\n", num_rects);
cairo_beos_surface_t *surface = reinterpret_cast<cairo_beos_surface_t*>(
@ -716,7 +822,7 @@ _cairo_beos_fill_rectangles (void *abstract_surface,
surface->view->SetBlendingMode(B_CONSTANT_ALPHA, B_ALPHA_OVERLAY);
for (int i = 0; i < num_rects; ++i) {
_cairo_beos_fill_rectangle(surface, &rects[i]);
_cairo_beos_surface_fill_rectangle(surface, &rects[i]);
}
surface->view->PopState();
@ -777,15 +883,16 @@ _cairo_beos_surface_get_extents (void *abstract_surface,
}
static const struct _cairo_surface_backend cairo_beos_surface_backend = {
NULL, /* create_similar */
CAIRO_SURFACE_TYPE_BEOS,
_cairo_beos_surface_create_similar,
_cairo_beos_surface_finish,
_cairo_beos_surface_acquire_source_image,
_cairo_beos_surface_release_source_image,
_cairo_beos_surface_acquire_dest_image,
_cairo_beos_surface_release_dest_image,
NULL, /* clone_similar */
_cairo_beos_composite, /* composite */
_cairo_beos_fill_rectangles,
_cairo_beos_surface_composite, /* composite */
_cairo_beos_surface_fill_rectangles,
NULL, /* composite_trapezoids */
NULL, /* copy_page */
NULL, /* show_page */
@ -806,6 +913,28 @@ static const struct _cairo_surface_backend cairo_beos_surface_backend = {
NULL /* show_glyphs */
};
static cairo_surface_t *
_cairo_beos_surface_create_internal (BView* view,
BBitmap* bmp,
bool owns_bitmap_view)
{
// Must use malloc, because cairo code will use free() on the surface
cairo_beos_surface_t *surface = static_cast<cairo_beos_surface_t*>(
malloc(sizeof(cairo_beos_surface_t)));
if (surface == NULL) {
_cairo_error (CAIRO_STATUS_NO_MEMORY);
return const_cast<cairo_surface_t*>(&_cairo_surface_nil);
}
_cairo_surface_init(&surface->base, &cairo_beos_surface_backend);
surface->view = view;
surface->bitmap = bmp;
surface->owns_bitmap_view = owns_bitmap_view;
return (cairo_surface_t *) surface;
}
/**
* cairo_beos_surface_create:
* @view: The view to draw on
@ -842,20 +971,7 @@ cairo_surface_t *
cairo_beos_surface_create_for_bitmap (BView* view,
BBitmap* bmp)
{
// Must use malloc, because cairo code will use free() on the surface
cairo_beos_surface_t *surface = static_cast<cairo_beos_surface_t*>(
malloc(sizeof(cairo_beos_surface_t)));
if (surface == NULL) {
_cairo_error (CAIRO_STATUS_NO_MEMORY);
return const_cast<cairo_surface_t*>(&_cairo_surface_nil);
}
_cairo_surface_init(&surface->base, &cairo_beos_surface_backend);
surface->view = view;
surface->bitmap = bmp;
return (cairo_surface_t *) surface;
return _cairo_beos_surface_create_internal(view, bmp);
}
// ---------------------------------------------------------------------------

View file

@ -88,7 +88,7 @@ typedef struct _cairo_cache_entry {
} cairo_cache_entry_t;
typedef cairo_bool_t
(*cairo_cache_keys_equal_func_t) (void *key_a, void *key_b);
(*cairo_cache_keys_equal_func_t) (const void *key_a, const void *key_b);
typedef void
(*cairo_cache_callback_func_t) (void *entry,

View file

@ -248,8 +248,10 @@ _cairo_clip_intersect_path (cairo_clip_t *clip,
return CAIRO_STATUS_NO_MEMORY;
status = _cairo_path_fixed_init_copy (&clip_path->path, path);
if (status)
if (status) {
free (clip_path);
return status;
}
clip_path->ref_count = 1;
clip_path->fill_rule = fill_rule;

View file

@ -150,7 +150,7 @@ static inline int cairo_to_directfb_format(cairo_format_t format ) {
return DSPF_A1;
default:
{
//assert(0);
/*assert(0);*/
return DSPF_UNKNOWN;
}
}
@ -483,9 +483,9 @@ _cairo_directfb_surface_composite (cairo_operator_t op,
if( _dfb_set_operator(op,surface->buffer) == DFB_UNSUPPORTED )
return CAIRO_INT_STATUS_UNSUPPORTED;
if (src_pattern->type == CAIRO_PATTERN_SOLID ) {
if (src_pattern->type == CAIRO_PATTERN_TYPE_SOLID ) {
} else if (src_pattern->type != CAIRO_PATTERN_SURFACE ||
} else if (src_pattern->type != CAIRO_PATTERN_TYPE_SURFACE ||
src_pattern->extend != CAIRO_EXTEND_NONE) {
return CAIRO_INT_STATUS_UNSUPPORTED;
}
@ -494,7 +494,7 @@ _cairo_directfb_surface_composite (cairo_operator_t op,
/* FIXME: When we fully support RENDER style 4-channel
* masks we need to check r/g/b != 1.0.
*/
if (mask_pattern->type != CAIRO_PATTERN_SOLID)
if (mask_pattern->type != CAIRO_PATTERN_TYPE_SOLID)
return CAIRO_INT_STATUS_UNSUPPORTED;
alpha = ((cairo_solid_pattern_t *)mask_pattern)->color.alpha_short >> 8;
@ -662,6 +662,7 @@ _cairo_directfb_surface_scaled_glyph_fini (cairo_scaled_glyph_t *scaled_glyph,
static const cairo_surface_backend_t cairo_directfb_surface_backend = {
CAIRO_SURFACE_TYPE_DIRECTFB,
_cairo_directfb_surface_create_similar,
_cairo_directfb_surface_finish,
_cairo_directfb_surface_acquire_source_image,

View file

@ -130,6 +130,12 @@ cairo_font_face_destroy (cairo_font_face_t *font_face)
free (font_face);
}
/**
* cairo_font_face_get_type:
* @font_face: a #cairo_font_face_t
*
* Return value: The type of @font_face. See #cairo_font_type_t.
**/
cairo_font_type_t
cairo_font_face_get_type (cairo_font_face_t *font_face)
{
@ -204,8 +210,8 @@ cairo_font_face_set_user_data (cairo_font_face_t *font_face,
static const cairo_font_face_backend_t _cairo_toy_font_face_backend;
static int
_cairo_toy_font_face_keys_equal (void *key_a,
void *key_b);
_cairo_toy_font_face_keys_equal (const void *key_a,
const void *key_b);
/* We maintain a hash table from family/weight/slant =>
* cairo_font_face_t for cairo_toy_font_t. The primary purpose of
@ -306,11 +312,11 @@ _cairo_toy_font_face_fini (cairo_toy_font_face_t *font_face)
}
static int
_cairo_toy_font_face_keys_equal (void *key_a,
void *key_b)
_cairo_toy_font_face_keys_equal (const void *key_a,
const void *key_b)
{
cairo_toy_font_face_t *face_a = key_a;
cairo_toy_font_face_t *face_b = key_b;
const cairo_toy_font_face_t *face_a = key_a;
const cairo_toy_font_face_t *face_b = key_b;
return (strcmp (face_a->family, face_b->family) == 0 &&
face_a->slant == face_b->slant &&

View file

@ -103,8 +103,8 @@ struct _cairo_ft_unscaled_font {
};
static int
_cairo_ft_unscaled_font_keys_equal (void *key_a,
void *key_b);
_cairo_ft_unscaled_font_keys_equal (const void *key_a,
const void *key_b);
static void
_cairo_ft_unscaled_font_fini (cairo_ft_unscaled_font_t *unscaled);
@ -365,11 +365,11 @@ _cairo_ft_unscaled_font_fini (cairo_ft_unscaled_font_t *unscaled)
}
static int
_cairo_ft_unscaled_font_keys_equal (void *key_a,
void *key_b)
_cairo_ft_unscaled_font_keys_equal (const void *key_a,
const void *key_b)
{
cairo_ft_unscaled_font_t *unscaled_a = key_a;
cairo_ft_unscaled_font_t *unscaled_b = key_b;
const cairo_ft_unscaled_font_t *unscaled_a = key_a;
const cairo_ft_unscaled_font_t *unscaled_b = key_b;
return (strcmp (unscaled_a->filename, unscaled_b->filename) == 0 &&
unscaled_a->id == unscaled_b->id);
@ -1901,6 +1901,7 @@ _cairo_ft_show_glyphs (void *abstract_font,
}
const cairo_scaled_font_backend_t cairo_ft_scaled_font_backend = {
CAIRO_FONT_TYPE_FT,
_cairo_ft_scaled_font_create_toy,
_cairo_ft_scaled_font_fini,
_cairo_ft_scaled_glyph_init,

View file

@ -551,8 +551,8 @@ _cairo_glitz_pattern_acquire_surface (cairo_pattern_t *pattern,
attr->acquired = FALSE;
switch (pattern->type) {
case CAIRO_PATTERN_LINEAR:
case CAIRO_PATTERN_RADIAL: {
case CAIRO_PATTERN_TYPE_LINEAR:
case CAIRO_PATTERN_TYPE_RADIAL: {
cairo_gradient_pattern_t *gradient =
(cairo_gradient_pattern_t *) pattern;
char *data;
@ -587,7 +587,7 @@ _cairo_glitz_pattern_acquire_surface (cairo_pattern_t *pattern,
if (!CAIRO_GLITZ_FEATURE_OK (dst->surface, FRAGMENT_PROGRAM))
break;
if (pattern->type == CAIRO_PATTERN_RADIAL)
if (pattern->type == CAIRO_PATTERN_TYPE_RADIAL)
n_base_params = 6;
else
n_base_params = 4;
@ -639,7 +639,7 @@ _cairo_glitz_pattern_acquire_surface (cairo_pattern_t *pattern,
glitz_buffer_destroy (buffer);
if (pattern->type == CAIRO_PATTERN_LINEAR)
if (pattern->type == CAIRO_PATTERN_TYPE_LINEAR)
{
cairo_linear_pattern_t *grad = (cairo_linear_pattern_t *) pattern;
@ -776,8 +776,8 @@ _cairo_glitz_pattern_acquire_surfaces (cairo_pattern_t *src,
* information in mask, so this will need to change when we
* support RENDER-style 4-channel masks. */
if (src->type == CAIRO_PATTERN_SOLID &&
mask->type == CAIRO_PATTERN_SOLID)
if (src->type == CAIRO_PATTERN_TYPE_SOLID &&
mask->type == CAIRO_PATTERN_TYPE_SOLID)
{
cairo_color_t combined;
cairo_solid_pattern_t *src_solid = (cairo_solid_pattern_t *) src;
@ -1018,7 +1018,7 @@ _cairo_glitz_surface_composite_trapezoids (cairo_operator_t op,
if (_glitz_ensure_target (dst->surface))
return CAIRO_INT_STATUS_UNSUPPORTED;
if (pattern->type == CAIRO_PATTERN_SURFACE)
if (pattern->type == CAIRO_PATTERN_TYPE_SURFACE)
{
_cairo_pattern_init_copy (&tmp_src_pattern.base, pattern);
@ -2121,6 +2121,7 @@ _cairo_glitz_surface_flush (void *abstract_surface)
}
static const cairo_surface_backend_t cairo_glitz_surface_backend = {
CAIRO_SURFACE_TYPE_GLITZ,
_cairo_glitz_surface_create_similar,
_cairo_glitz_surface_finish,
_cairo_glitz_surface_acquire_source_image,

View file

@ -85,7 +85,7 @@ typedef struct _cairo_hash_entry {
} cairo_hash_entry_t;
typedef cairo_bool_t
(*cairo_hash_keys_equal_func_t) (void *key_a, void *key_b);
(*cairo_hash_keys_equal_func_t) (const void *key_a, const void *key_b);
typedef cairo_bool_t
(*cairo_hash_predicate_func_t) (void *entry);

View file

@ -903,6 +903,7 @@ _cairo_surface_is_image (const cairo_surface_t *surface)
}
const cairo_surface_backend_t cairo_image_surface_backend = {
CAIRO_SURFACE_TYPE_IMAGE,
_cairo_image_surface_create_similar,
_cairo_image_surface_finish,
_cairo_image_surface_acquire_source_image,

400
src/cairo-lzw.c Normal file
View file

@ -0,0 +1,400 @@
/* cairo - a vector graphics library with display and print output
*
* Copyright © 2006 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"
typedef struct _lzw_buf {
cairo_status_t status;
unsigned char *data;
int data_size;
int num_data;
uint32_t pending;
int pending_bits;
} lzw_buf_t;
/* An lzw_buf_t is a simple, growable chunk of memory for holding
* variable-size objects of up to 16 bits each.
*
* Initialize an lzw_buf_t to the given size in bytes.
*
* To store objects into the lzw_buf_t, call _lzw_buf_store_bits and
* when finished, call _lzw_buf_store_pending, (which flushes out the
* last few bits that hadn't yet made a complete byte yet).
*
* Instead of returning failure from any functions, lzw_buf_t provides
* a status value that the caller can query, (and should query at
* least once when done with the object). The status value will be
* either CAIRO_STATUS_SUCCESS or CAIRO_STATUS_NO_MEMORY;
*/
static void
_lzw_buf_init (lzw_buf_t *buf, int size)
{
if (size == 0)
size = 16;
buf->status = CAIRO_STATUS_SUCCESS;
buf->data = malloc (size);
if (buf->data == NULL) {
buf->data_size = 0;
buf->status = CAIRO_STATUS_NO_MEMORY;
return;
}
buf->data_size = size;
buf->num_data = 0;
buf->pending = 0;
buf->pending_bits = 0;
}
/* Increase the buffer size by doubling.
*
* Returns CAIRO_STATUS_SUCCESS or CAIRO_STATUS_NO_MEMORY
*/
static cairo_status_t
_lzw_buf_grow (lzw_buf_t *buf)
{
int new_size = buf->data_size * 2;
unsigned char *new_data;
if (buf->status)
return buf->status;
new_data = realloc (buf->data, new_size);
if (new_data == NULL) {
free (buf->data);
buf->data_size = 0;
buf->status = CAIRO_STATUS_NO_MEMORY;
return buf->status;
}
buf->data = new_data;
buf->data_size = new_size;
return CAIRO_STATUS_SUCCESS;
}
/* Store the lowest num_bits bits of values into buf.
*
* NOTE: The bits of value above size_in_bits must be 0, (so don't lie
* about the size).
*
* See also _lzw_buf_store_pending which must be called after the last
* call to _lzw_buf_store_bits.
*
* Sets buf->status to either CAIRO_STATUS_SUCCESS or CAIRO_STATUS_NO_MEMORY.
*/
static void
_lzw_buf_store_bits (lzw_buf_t *buf, uint16_t value, int num_bits)
{
cairo_status_t status;
assert (value <= (1 << num_bits) - 1);
if (buf->status)
return;
buf->pending = (buf->pending << num_bits) | value;
buf->pending_bits += num_bits;
while (buf->pending_bits >= 8) {
if (buf->num_data >= buf->data_size) {
status = _lzw_buf_grow (buf);
if (status)
return;
}
buf->data[buf->num_data++] = buf->pending >> (buf->pending_bits - 8);
buf->pending_bits -= 8;
}
}
/* Store the last remaining pending bits into the buffer.
*
* NOTE: This function must be called after the last call to
* _lzw_buf_store_bits.
*
* Sets buf->status to either CAIRO_STATUS_SUCCESS or CAIRO_STATUS_NO_MEMORY.
*/
static void
_lzw_buf_store_pending (lzw_buf_t *buf)
{
cairo_status_t status;
if (buf->status)
return;
if (buf->pending_bits == 0)
return;
assert (buf->pending_bits < 8);
if (buf->num_data >= buf->data_size) {
status = _lzw_buf_grow (buf);
if (status)
return;
}
buf->data[buf->num_data++] = buf->pending << (8 - buf->pending_bits);
buf->pending_bits = 0;
}
/* LZW defines a few magic code values */
#define LZW_CODE_CLEAR_TABLE 256
#define LZW_CODE_EOD 257
#define LZW_CODE_FIRST 258
/* We pack three separate values into a symbol as follows:
*
* 12 bits (31 down to 20): CODE: code value used to represent this symbol
* 12 bits (19 down to 8): PREV: previous code value in chain
* 8 bits ( 7 down to 0): NEXT: next byte value in chain
*/
typedef uint32_t lzw_symbol_t;
#define LZW_SYMBOL_SET(sym, prev, next) ((sym) = ((prev) << 8)|(next))
#define LZW_SYMBOL_SET_CODE(sym, code, prev, next) ((sym) = ((code << 20)|(prev) << 8)|(next))
#define LZW_SYMBOL_GET_CODE(sym) (((sym) >> 20))
#define LZW_SYMBOL_GET_PREV(sym) (((sym) >> 8) & 0x7ff)
#define LZW_SYMBOL_GET_BYTE(sym) (((sym) >> 0) & 0x0ff)
/* The PREV+NEXT fields can be seen as the key used to fetch values
* from the hash table, while the code is the value fetched.
*/
#define LZW_SYMBOL_KEY_MASK 0x000fffff
/* Since code values are only stored starting with 258 we can safely
* use a zero value to represent free slots in the hash table. */
#define LZW_SYMBOL_FREE 0x00000000
/* These really aren't very free for modifying. First, the PostScript
* specification sets the 9-12 bit range. Second, the encoding of
* lzw_symbol_t above also relies on 2 of LZW_BITS_MAX plus one byte
* fitting within 32 bits.
*
* But other than that, the LZW compression scheme could function with
* more bits per code.
*/
#define LZW_BITS_MIN 9
#define LZW_BITS_MAX 12
#define LZW_BITS_BOUNDARY(bits) ((1<<(bits))-1)
#define LZW_MAX_SYMBOLS (1<<LZW_BITS_MAX)
#define LZW_SYMBOL_TABLE_SIZE 9013
#define LZW_SYMBOL_MOD1 LZW_SYMBOL_TABLE_SIZE
#define LZW_SYMBOL_MOD2 9011
typedef struct _lzw_symbol_table {
lzw_symbol_t table[LZW_SYMBOL_TABLE_SIZE];
} lzw_symbol_table_t;
/* Initialize the hash table to entirely empty */
static void
_lzw_symbol_table_init (lzw_symbol_table_t *table)
{
memset (table->table, 0, LZW_SYMBOL_TABLE_SIZE * sizeof (lzw_symbol_t));
}
/* Lookup a symbol in the symbol table. The PREV and NEXT fields of
* symbol form the key for the lookup.
*
* If succesful, then this function returns TRUE and slot_ret will be
* left pointing at the result that will have the CODE field of
* interest.
*
* If the lookup fails, then this function returns FALSE and slot_ret
* will be pointing at the location in the table to which a new CODE
* value should be stored along with PREV and NEXT.
*/
static cairo_bool_t
_lzw_symbol_table_lookup (lzw_symbol_table_t *table,
lzw_symbol_t symbol,
lzw_symbol_t **slot_ret)
{
/* The algorithm here is identical to that in cairo-hash.c. We
* copy it here to allow for a rather more efficient
* implementation due to several circumstances that do not apply
* to the more general case:
*
* 1) We have a known bound on the total number of symbols, so we
* have a fixed-size table without any copying when growing
*
* 2) We never delete any entries, so we don't need to
* support/check for DEAD entries during lookup.
*
* 3) The object fits in 32 bits so we store each object in its
* entirety within the table rather than storing objects
* externally and putting pointers in the table, (which here
* would just double the storage requirements and have negative
* impacts on memory locality).
*/
int i, idx, step, hash = symbol & LZW_SYMBOL_KEY_MASK;
lzw_symbol_t candidate;
idx = hash % LZW_SYMBOL_MOD1;
step = 0;
*slot_ret = NULL;
for (i = 0; i < LZW_SYMBOL_TABLE_SIZE; i++)
{
candidate = table->table[idx];
if (candidate == LZW_SYMBOL_FREE)
{
*slot_ret = &table->table[idx];
return FALSE;
}
else /* candidate is LIVE */
{
if ((candidate & LZW_SYMBOL_KEY_MASK) ==
(symbol & LZW_SYMBOL_KEY_MASK))
{
*slot_ret = &table->table[idx];
return TRUE;
}
}
if (step == 0) {
step = hash % LZW_SYMBOL_MOD2;
if (step == 0)
step = 1;
}
idx += step;
if (idx >= LZW_SYMBOL_TABLE_SIZE)
idx -= LZW_SYMBOL_TABLE_SIZE;
}
return FALSE;
}
/* Compress a bytestream using the LZW algorithm.
*
* This is an original implementation based on reading the
* specification of the LZWDecode filter in the PostScript Language
* Reference. The free parameters in the LZW algorithm are set to the
* values mandated by PostScript, (symbols encoded with widths from 9
* to 12 bits).
*
* This function returns a pointer to a newly allocated buffer holding
* the compressed data, or NULL if an out-of-memory situation
* occurs.
*
* Notice that any one of the _lzw_buf functions called here could
* trigger an out-of-memory condition. But lzw_buf_t uses cairo's
* shutdown-on-error idiom, so it's safe to continue to call into
* lzw_buf without having to check for errors, (until a final check at
* the end).
*/
cairo_public unsigned char *
_cairo_lzw_compress (unsigned char *data, unsigned long *size_in_out)
{
int bytes_remaining = *size_in_out;
lzw_buf_t buf;
lzw_symbol_table_t table;
lzw_symbol_t symbol, *slot;
int code_next = LZW_CODE_FIRST;
int code_bits = LZW_BITS_MIN;
int prev, next;
if (*size_in_out == 0)
return NULL;
_lzw_buf_init (&buf, *size_in_out);
_lzw_symbol_table_init (&table);
/* The LZW header is a clear table code. */
_lzw_buf_store_bits (&buf, LZW_CODE_CLEAR_TABLE, code_bits);
while (1) {
/* Find the longest existing code in the symbol table that
* matches the current input, if any. */
prev = *data++;
bytes_remaining--;
if (bytes_remaining) {
do
{
next = *data++;
bytes_remaining--;
LZW_SYMBOL_SET (symbol, prev, next);
if (_lzw_symbol_table_lookup (&table, symbol, &slot))
prev = LZW_SYMBOL_GET_CODE (*slot);
} while (bytes_remaining && *slot != LZW_SYMBOL_FREE);
if (*slot == LZW_SYMBOL_FREE) {
data--;
bytes_remaining++;
}
}
/* Write the code into the output. This is either a byte read
* directly from the input, or a code from the last successful
* lookup. */
_lzw_buf_store_bits (&buf, prev, code_bits);
if (bytes_remaining == 0)
break;
LZW_SYMBOL_SET_CODE (*slot, code_next++, prev, next);
if (code_next > LZW_BITS_BOUNDARY(code_bits))
{
code_bits++;
if (code_bits > LZW_BITS_MAX) {
_lzw_symbol_table_init (&table);
_lzw_buf_store_bits (&buf, LZW_CODE_CLEAR_TABLE, code_bits - 1);
code_bits = LZW_BITS_MIN;
code_next = LZW_CODE_FIRST;
}
}
}
/* The LZW footer is an end-of-data code. */
_lzw_buf_store_bits (&buf, LZW_CODE_EOD, code_bits);
_lzw_buf_store_pending (&buf);
/* See if we ever ran out of memory while writing to buf. */
if (buf.status == CAIRO_STATUS_NO_MEMORY) {
*size_in_out = 0;
return NULL;
}
assert (buf.status == CAIRO_STATUS_SUCCESS);
*size_in_out = buf.num_data;
return buf.data;
}

View file

@ -53,7 +53,7 @@ typedef enum {
* fallbacks should never get triggered). So the plan is to
* eliminate as many of these as possible. */
CAIRO_COMMAND_INTERSECT_CLIP_PATH,
CAIRO_COMMAND_INTERSECT_CLIP_PATH
} cairo_command_type_t;

View file

@ -557,6 +557,7 @@ _cairo_surface_is_meta (const cairo_surface_t *surface)
}
static const cairo_surface_backend_t cairo_meta_surface_backend = {
CAIRO_INTERNAL_SURFACE_TYPE_META,
_cairo_meta_surface_create_similar,
_cairo_meta_surface_finish,
_cairo_meta_surface_acquire_source_image,

View file

@ -45,53 +45,88 @@
struct _cairo_output_stream {
cairo_write_func_t write_data;
cairo_close_func_t close_func;
void *closure;
cairo_bool_t owns_closure_is_file;
unsigned long position;
cairo_status_t status;
cairo_bool_t closed;
};
const cairo_output_stream_t cairo_output_stream_nil = {
NULL, /* write_data */
NULL, /* close_func */
NULL, /* closure */
0, /* position */
CAIRO_STATUS_NO_MEMORY,
FALSE /* closed */
};
static const cairo_output_stream_t cairo_output_stream_nil_write_error = {
NULL, /* write_data */
NULL, /* close_func */
NULL, /* closure */
0, /* position */
CAIRO_STATUS_WRITE_ERROR,
FALSE /* closed */
};
cairo_output_stream_t *
_cairo_output_stream_create (cairo_write_func_t write_data,
cairo_close_func_t close_func,
void *closure)
{
cairo_output_stream_t *stream;
stream = malloc (sizeof (cairo_output_stream_t));
if (stream == NULL)
return NULL;
return (cairo_output_stream_t *) &cairo_output_stream_nil;
stream->write_data = write_data;
stream->close_func = close_func;
stream->closure = closure;
stream->owns_closure_is_file = FALSE;
stream->position = 0;
stream->status = CAIRO_STATUS_SUCCESS;
stream->closed = FALSE;
return stream;
}
void
_cairo_output_stream_close (cairo_output_stream_t *stream)
{
cairo_status_t status;
if (stream->closed)
return;
if (stream->close_func) {
status = stream->close_func (stream->closure);
if (status)
stream->status = status;
}
stream->closed = TRUE;
}
void
_cairo_output_stream_destroy (cairo_output_stream_t *stream)
{
if (stream->owns_closure_is_file) {
FILE *file = stream->closure;
fflush (file);
fclose (file);
}
_cairo_output_stream_close (stream);
free (stream);
}
cairo_status_t
void
_cairo_output_stream_write (cairo_output_stream_t *stream,
const void *data, size_t length)
{
if (length == 0)
return CAIRO_STATUS_SUCCESS;
return;
if (stream->status)
return;
stream->status = stream->write_data (stream->closure, data, length);
stream->position += length;
return stream->status;
}
void
@ -103,6 +138,9 @@ _cairo_output_stream_write_hex_string (cairo_output_stream_t *stream,
char buffer[2];
int i, column;
if (stream->status)
return;
for (i = 0, column = 0; i < length; i++, column++) {
if (column == 38) {
_cairo_output_stream_write (stream, "\n", 1);
@ -175,8 +213,7 @@ enum {
* formatting. This functionality is only for internal use and we
* only implement the formats we actually use.
*/
cairo_status_t
void
_cairo_output_stream_vprintf (cairo_output_stream_t *stream,
const char *fmt, va_list ap)
{
@ -185,6 +222,9 @@ _cairo_output_stream_vprintf (cairo_output_stream_t *stream,
const char *f;
int length_modifier;
if (stream->status)
return;
f = fmt;
p = buffer;
while (*f != '\0') {
@ -247,24 +287,19 @@ _cairo_output_stream_vprintf (cairo_output_stream_t *stream,
}
_cairo_output_stream_write (stream, buffer, p - buffer);
return stream->status;
}
cairo_status_t
void
_cairo_output_stream_printf (cairo_output_stream_t *stream,
const char *fmt, ...)
{
va_list ap;
cairo_status_t status;
va_start (ap, fmt);
status = _cairo_output_stream_vprintf (stream, fmt, ap);
_cairo_output_stream_vprintf (stream, fmt, ap);
va_end (ap);
return status;
}
long
@ -286,28 +321,33 @@ _cairo_output_stream_get_status (cairo_output_stream_t *stream)
static cairo_status_t
stdio_write (void *closure, const unsigned char *data, unsigned int length)
{
FILE *fp = closure;
FILE *file = closure;
if (fwrite (data, 1, length, fp) == length)
return CAIRO_STATUS_SUCCESS;
if (fwrite (data, 1, length, file) != length)
return CAIRO_STATUS_WRITE_ERROR;
return CAIRO_STATUS_WRITE_ERROR;
return CAIRO_STATUS_SUCCESS;
}
static cairo_status_t
stdio_close (void *closure)
{
FILE *file = closure;
fflush (file);
fclose (file);
return CAIRO_STATUS_SUCCESS;
}
cairo_output_stream_t *
_cairo_output_stream_create_for_file (const char *filename)
{
FILE *fp;
cairo_output_stream_t *stream;
FILE *file;
fp = fopen (filename, "wb");
if (fp == NULL)
return NULL;
file = fopen (filename, "wb");
if (file == NULL)
return (cairo_output_stream_t *) &cairo_output_stream_nil_write_error;
stream = _cairo_output_stream_create (stdio_write, fp);
if (stream == NULL)
fclose (fp);
stream->owns_closure_is_file = TRUE;
return stream;
return _cairo_output_stream_create (stdio_write, stdio_close, file);
}

View file

@ -102,6 +102,24 @@ const cairo_private cairo_surface_backend_t cairo_paginated_surface_backend;
static cairo_int_status_t
_cairo_paginated_surface_show_page (void *abstract_surface);
/* XXX: This would seem the natural thing to do here. But currently,
* PDF and PS surfaces do not yet work as source surfaces. So instead,
* we don't implement create_similar for the paginate_surface which
* means that any create_similar() call on a paginated_surfacae will
* result in a new image surface. */
#if 0
static cairo_surface_t *
_cairo_paginated_surface_create_similar (void *abstract_surface,
cairo_content_t content,
int width,
int height)
{
cairo_paginated_surface_t *surface = abstract_surface;
return cairo_surface_create_similar (surface->target, content,
width, height);
}
#endif
cairo_surface_t *
_cairo_paginated_surface_create (cairo_surface_t *target,
cairo_content_t content,
@ -117,6 +135,10 @@ _cairo_paginated_surface_create (cairo_surface_t *target,
_cairo_surface_init (&surface->base, &cairo_paginated_surface_backend);
/* Override surface->base.type with target's type so we don't leak
* evidence of the paginated wrapper out to the user. */
surface->base.type = cairo_surface_get_type (target);
surface->content = content;
surface->width = width;
surface->height = height;
@ -412,7 +434,8 @@ _cairo_paginated_surface_snapshot (void *abstract_other)
}
const cairo_surface_backend_t cairo_paginated_surface_backend = {
NULL, /* create_similar */
CAIRO_INTERNAL_SURFACE_TYPE_PAGINATED,
NULL, /* create_similar --- see note for _cairo_paginated_surface_create_similar */
_cairo_paginated_surface_finish,
_cairo_paginated_surface_acquire_source_image,
_cairo_paginated_surface_release_source_image,

View file

@ -524,6 +524,18 @@ cairo_pattern_reference (cairo_pattern_t *pattern)
return pattern;
}
/**
* cairo_pattern_get_type:
* @pattern: a #cairo_pattern_t
*
* Return value: The type of @pattern. See #cairo_pattern_type_t.
**/
cairo_pattern_type_t
cairo_pattern_get_type (cairo_pattern_t *pattern)
{
return pattern->type;
}
/**
* cairo_pattern_status:
* @pattern: a #cairo_pattern_t

View file

@ -340,11 +340,13 @@ cairo_pdf_surface_create_for_stream (cairo_write_func_t write,
double width_in_points,
double height_in_points)
{
cairo_status_t status;
cairo_output_stream_t *stream;
stream = _cairo_output_stream_create (write, closure);
if (stream == NULL) {
_cairo_error (CAIRO_STATUS_NO_MEMORY);
stream = _cairo_output_stream_create (write, NULL, closure);
status = _cairo_output_stream_get_status (stream);
if (status) {
_cairo_error (status);
return (cairo_surface_t*) &_cairo_surface_nil;
}
@ -375,11 +377,13 @@ cairo_pdf_surface_create (const char *filename,
double width_in_points,
double height_in_points)
{
cairo_status_t status;
cairo_output_stream_t *stream;
stream = _cairo_output_stream_create_for_file (filename);
if (stream == NULL) {
_cairo_error (CAIRO_STATUS_NO_MEMORY);
status = _cairo_output_stream_get_status (stream);
if (status) {
_cairo_error (status);
return (cairo_surface_t*) &_cairo_surface_nil;
}
@ -663,8 +667,10 @@ emit_image_rgb_data (cairo_pdf_document_t *document,
opaque = cairo_image_surface_create (CAIRO_FORMAT_RGB24,
image->width,
image->height);
if (opaque->status)
if (opaque->status) {
free (rgb);
return 0;
}
_cairo_pattern_init_for_surface (&pattern.surface, &image->base);
@ -1666,6 +1672,7 @@ _cairo_pdf_surface_get_font_options (void *abstract_surface,
}
static const cairo_surface_backend_t cairo_pdf_surface_backend = {
CAIRO_SURFACE_TYPE_PDF,
_cairo_pdf_surface_create_similar,
_cairo_pdf_surface_finish,
NULL, /* acquire_source_image */

View file

@ -51,8 +51,6 @@
*
* - Add document structure convention comments where appropriate.
*
* - Fix image compression.
*
* - Create a set of procs to use... specifically a trapezoid proc.
*/
@ -108,11 +106,9 @@ _cairo_ps_surface_emit_header (cairo_ps_surface_t *surface)
surface->width,
surface->height);
/* The "/FlateDecode filter" currently used is a feature of
* LanguageLevel 3 */
_cairo_output_stream_printf (surface->stream,
"%%%%DocumentData: Binary\n"
"%%%%LanguageLevel: 3\n"
"%%%%DocumentData: Clean7Bit\n"
"%%%%LanguageLevel: 2\n"
"%%%%Orientation: Portrait\n"
"%%%%EndComments\n");
}
@ -191,11 +187,13 @@ cairo_ps_surface_create (const char *filename,
double width_in_points,
double height_in_points)
{
cairo_status_t status;
cairo_output_stream_t *stream;
stream = _cairo_output_stream_create_for_file (filename);
if (stream == NULL) {
_cairo_error (CAIRO_STATUS_NO_MEMORY);
status = _cairo_output_stream_get_status (stream);
if (status) {
_cairo_error (status);
return (cairo_surface_t*) &_cairo_surface_nil;
}
@ -229,11 +227,13 @@ cairo_ps_surface_create_for_stream (cairo_write_func_t write_func,
double width_in_points,
double height_in_points)
{
cairo_status_t status;
cairo_output_stream_t *stream;
stream = _cairo_output_stream_create (write_func, closure);
if (stream == NULL) {
_cairo_error (CAIRO_STATUS_NO_MEMORY);
stream = _cairo_output_stream_create (write_func, NULL, closure);
status = _cairo_output_stream_get_status (stream);
if (status) {
_cairo_error (status);
return (cairo_surface_t*) &_cairo_surface_nil;
}
@ -665,26 +665,107 @@ pattern_operation_analyze (cairo_operator_t op,
return CAIRO_INT_STATUS_UNSUPPORTED;
}
/* The "standard" implementation limit for PostScript string sizes is
* 65535 characters (see PostScript Language Reference, Appendix
* B). We go one short of that because we sometimes need two
* characters in a string to represent a single ASCII85 byte, (for the
* escape sequences "\\", "\(", and "\)") and we must not split these
* across two strings. So we'd be in trouble if we went right to the
* limit and one of these escape sequences just happened to land at
* the end.
*/
#define STRING_ARRAY_MAX_STRING_SIZE (65535-1)
#define STRING_ARRAY_MAX_COLUMN 72
typedef struct _string_array_stream {
cairo_output_stream_t *output;
int column;
int string_size;
} string_array_stream_t;
static cairo_status_t
_string_array_stream_write (void *closure,
const unsigned char *data,
unsigned int length)
{
string_array_stream_t *stream = closure;
unsigned char c;
const unsigned char backslash = '\\';
if (length == 0)
return CAIRO_STATUS_SUCCESS;
while (length--) {
if (stream->string_size == 0) {
_cairo_output_stream_printf (stream->output, "(");
stream->column++;
}
c = *data++;
switch (c) {
case '\\':
case '(':
case ')':
_cairo_output_stream_write (stream->output, &backslash, 1);
stream->column++;
stream->string_size++;
break;
}
_cairo_output_stream_write (stream->output, &c, 1);
stream->column++;
stream->string_size++;
if (stream->string_size >= STRING_ARRAY_MAX_STRING_SIZE) {
_cairo_output_stream_printf (stream->output, ")\n");
stream->string_size = 0;
stream->column = 0;
}
if (stream->column >= STRING_ARRAY_MAX_COLUMN) {
_cairo_output_stream_printf (stream->output, "\n ");
stream->string_size += 2;
stream->column = 1;
}
}
return _cairo_output_stream_get_status (stream->output);
}
static cairo_status_t
_string_array_stream_close (void *closure)
{
cairo_status_t status;
string_array_stream_t *stream = closure;
_cairo_output_stream_printf (stream->output, ")\n");
status = _cairo_output_stream_get_status (stream->output);
free (stream);
return status;
}
static cairo_output_stream_t *
_string_array_stream_create (cairo_output_stream_t *output)
{
string_array_stream_t *stream;
stream = malloc (sizeof (string_array_stream_t));
if (stream == NULL)
return (cairo_output_stream_t *) &cairo_output_stream_nil;
stream->output = output;
stream->column = 0;
stream->string_size = 0;
return _cairo_output_stream_create (_string_array_stream_write,
_string_array_stream_close,
stream);
}
/* PS Output - this section handles output of the parts of the meta
* surface we can render natively in PS. */
static void *
compress_dup (const void *data, unsigned long data_size,
unsigned long *compressed_size)
{
void *compressed;
/* Bound calculation taken from zlib. */
*compressed_size = data_size + (data_size >> 12) + (data_size >> 14) + 11;
compressed = malloc (*compressed_size);
if (compressed == NULL)
return NULL;
compress (compressed, compressed_size, data, data_size);
return compressed;
}
static cairo_status_t
emit_image (cairo_ps_surface_t *surface,
cairo_image_surface_t *image,
@ -699,6 +780,7 @@ emit_image (cairo_ps_surface_t *surface,
cairo_pattern_union_t pattern;
cairo_matrix_t d2i;
int x, y, i;
cairo_output_stream_t *base85_stream, *string_array_stream;
/* PostScript can not represent the alpha channel, so we blend the
current image over a white RGB surface to eliminate it. */
@ -756,56 +838,64 @@ emit_image (cairo_ps_surface_t *surface,
}
}
compressed = compress_dup (rgb, rgb_size, &compressed_size);
/* XXX: Should fix cairo-lzw to provide a stream-based interface
* instead. */
compressed_size = rgb_size;
compressed = _cairo_lzw_compress (rgb, &compressed_size);
if (compressed == NULL) {
status = CAIRO_STATUS_NO_MEMORY;
goto bail2;
}
/* First emit the image data as a base85-encoded string which will
* be used as the data source for the image operator later. */
_cairo_output_stream_printf (surface->stream,
"/%sData [\n", name);
string_array_stream = _string_array_stream_create (surface->stream);
base85_stream = _cairo_base85_stream_create (string_array_stream);
_cairo_output_stream_write (base85_stream, compressed, compressed_size);
_cairo_output_stream_destroy (base85_stream);
_cairo_output_stream_destroy (string_array_stream);
_cairo_output_stream_printf (surface->stream,
"] def\n");
_cairo_output_stream_printf (surface->stream,
"/%sDataIndex 0 def\n", name);
/* matrix transforms from user space to image space. We need to
* transform from device space to image space to compensate for
* postscripts coordinate system. */
cairo_matrix_init (&d2i, 1, 0, 0, 1, 0, 0);
cairo_matrix_multiply (&d2i, &d2i, matrix);
#if 1
/* Construct a string holding the entire image (!) */
_cairo_output_stream_printf (surface->stream, "/%sString %d string def\n",
name, (int) rgb_size);
_cairo_output_stream_printf (surface->stream,
"currentfile %sString readstring\n", name);
#else
/* Construct a reusable stream decoder holding the image */
_cairo_output_stream_printf (surface->stream, "/%sString <<\n", name);
/* intent = image data */
_cairo_output_stream_printf (surface->stream, "\t/Intent 0\n");
#endif
/* Compressed image data */
_cairo_output_stream_write (surface->stream, rgb, rgb_size);
_cairo_output_stream_printf (surface->stream,
"\n");
_cairo_output_stream_printf (surface->stream, "/%s {\n", name);
_cairo_output_stream_printf (surface->stream,
"/DeviceRGB setcolorspace\n"
"<<\n"
"/%s {\n"
" /DeviceRGB setcolorspace\n"
" <<\n"
" /ImageType 1\n"
" /Width %d\n"
" /Height %d\n"
" /BitsPerComponent 8\n"
" /Decode [ 0 1 0 1 0 1 ]\n"
" /DataSource %sString\n"
" /DataSource {\n"
" %sData %sDataIndex get\n"
" /%sDataIndex %sDataIndex 1 add def\n"
" %sDataIndex %sData length 1 sub gt { /%sDataIndex 0 def } if\n"
" } /ASCII85Decode filter /LZWDecode filter\n"
" /ImageMatrix [ %f %f %f %f %f %f ]\n"
">>\n"
"image\n",
" >>\n"
" image\n"
"} def\n",
name,
opaque_image->width,
opaque_image->height,
name,
name, name, name, name, name, name, name,
d2i.xx, d2i.yx,
d2i.xy, d2i.yy,
d2i.x0, d2i.y0);
_cairo_output_stream_printf (surface->stream, "} bind def\n");
status = CAIRO_STATUS_SUCCESS;
@ -862,17 +952,18 @@ emit_surface_pattern (cairo_ps_surface_t *surface,
image_extra);
}
_cairo_output_stream_printf (surface->stream,
"<< /PatternType 1 /PaintType 1 /TilingType 1\n");
"<< /PatternType 1\n"
" /PaintType 1\n"
" /TilingType 1\n");
_cairo_output_stream_printf (surface->stream,
"/BBox [0 0 %d %d]\n",
" /BBox [0 0 %d %d]\n",
extents.width, extents.height);
_cairo_output_stream_printf (surface->stream,
"/XStep %d /YStep %d\n",
" /XStep %d /YStep %d\n",
extents.width, extents.height);
_cairo_output_stream_printf (surface->stream,
"/PaintProc { begin MyPattern\n");
_cairo_output_stream_printf (surface->stream,
" end } bind >> matrix makepattern setpattern\n");
" /PaintProc { MyPattern } bind\n"
">> matrix makepattern setpattern\n");
}
static void
@ -1375,6 +1466,7 @@ _cairo_ps_surface_show_glyphs (void *abstract_surface,
}
static const cairo_surface_backend_t cairo_ps_surface_backend = {
CAIRO_SURFACE_TYPE_PS,
NULL, /* create_similar */
_cairo_ps_surface_finish,
NULL, /* acquire_source_image */

View file

@ -73,10 +73,11 @@ _cairo_quartz_surface_acquire_source_image(void *abstract_surface,
UInt32 imageDataSize, rowBytes;
CGDataProviderRef dataProvider;
// We keep a cached (cairo_image_surface_t *) in the cairo_quartz_surface_t
// struct. If the window is ever drawn to without going through Cairo, then
// we would need to refetch the pixel data from the window into the cached
// image surface.
/* We keep a cached (cairo_image_surface_t *) in the cairo_quartz_surface_t
* struct. If the window is ever drawn to without going through Cairo, then
* we would need to refetch the pixel data from the window into the cached
* image surface.
*/
if (surface->image) {
cairo_surface_reference(&surface->image->base);
@ -257,7 +258,7 @@ cairo_surface_t *cairo_quartz_surface_create(CGContextRef context,
surface->clip_region = NULL;
surface->flipped = flipped;
// Set up the image surface which Cairo draws into and we blit to & from.
/* Set up the image surface which Cairo draws into and we blit to & from. */
void *foo;
_cairo_quartz_surface_acquire_source_image(surface, &surface->image, &foo);

View file

@ -39,10 +39,10 @@
#include "cairoint.h"
static cairo_bool_t
_cairo_scaled_glyph_keys_equal (void *abstract_key_a, void *abstract_key_b)
_cairo_scaled_glyph_keys_equal (const void *abstract_key_a, const void *abstract_key_b)
{
cairo_scaled_glyph_t *key_a = abstract_key_a;
cairo_scaled_glyph_t *key_b = abstract_key_b;
const cairo_scaled_glyph_t *key_a = abstract_key_a;
const cairo_scaled_glyph_t *key_b = abstract_key_b;
return (_cairo_scaled_glyph_index (key_a) ==
_cairo_scaled_glyph_index (key_b));
@ -118,6 +118,18 @@ _cairo_scaled_font_set_error (cairo_scaled_font_t *scaled_font,
_cairo_error (status);
}
/**
* cairo_scaled_font_get_type:
* @scaled_font: a #cairo_scaled_font_t
*
* Return value: The type of @scaled_font. See #cairo_font_type_t.
**/
cairo_font_type_t
cairo_scaled_font_get_type (cairo_scaled_font_t *scaled_font)
{
return scaled_font->backend->type;
}
/**
* cairo_scaled_font_status:
* @scaled_font: a #cairo_scaled_font_t
@ -168,7 +180,7 @@ static cairo_scaled_font_map_t *cairo_scaled_font_map = NULL;
CAIRO_MUTEX_DECLARE (cairo_scaled_font_map_mutex);
static int
_cairo_scaled_font_keys_equal (void *abstract_key_a, void *abstract_key_b);
_cairo_scaled_font_keys_equal (const void *abstract_key_a, const void *abstract_key_b);
static cairo_scaled_font_map_t *
_cairo_scaled_font_map_lock (void)
@ -286,10 +298,10 @@ _cairo_scaled_font_init_key (cairo_scaled_font_t *scaled_font,
}
static cairo_bool_t
_cairo_scaled_font_keys_equal (void *abstract_key_a, void *abstract_key_b)
_cairo_scaled_font_keys_equal (const void *abstract_key_a, const void *abstract_key_b)
{
cairo_scaled_font_t *key_a = abstract_key_a;
cairo_scaled_font_t *key_b = abstract_key_b;
const cairo_scaled_font_t *key_a = abstract_key_a;
const cairo_scaled_font_t *key_b = abstract_key_b;
return (key_a->font_face == key_b->font_face &&
memcmp ((unsigned char *)(&key_a->font_matrix.xx),

View file

@ -549,6 +549,9 @@ _clip_and_composite_trapezoids (cairo_pattern_t *src,
return status;
clear_region = _cairo_region_create_from_rectangle (&extents);
if (clear_region == NULL)
return CAIRO_STATUS_NO_MEMORY;
status = _cairo_clip_intersect_to_region (clip, clear_region);
if (status)
return status;

View file

@ -43,6 +43,7 @@
const cairo_surface_t _cairo_surface_nil = {
&cairo_image_surface_backend, /* backend */
CAIRO_SURFACE_TYPE_IMAGE,
-1, /* ref_count */
CAIRO_STATUS_NO_MEMORY, /* status */
FALSE, /* finished */
@ -59,6 +60,7 @@ const cairo_surface_t _cairo_surface_nil = {
const cairo_surface_t _cairo_surface_nil_file_not_found = {
&cairo_image_surface_backend, /* backend */
CAIRO_SURFACE_TYPE_IMAGE,
-1, /* ref_count */
CAIRO_STATUS_FILE_NOT_FOUND, /* status */
FALSE, /* finished */
@ -75,6 +77,7 @@ const cairo_surface_t _cairo_surface_nil_file_not_found = {
const cairo_surface_t _cairo_surface_nil_read_error = {
&cairo_image_surface_backend, /* backend */
CAIRO_SURFACE_TYPE_IMAGE,
-1, /* ref_count */
CAIRO_STATUS_READ_ERROR, /* status */
FALSE, /* finished */
@ -118,6 +121,22 @@ _cairo_surface_set_error (cairo_surface_t *surface,
_cairo_error (status);
}
/**
* cairo_surface_get_type:
* @surface: a #cairo_surface_t
*
* Return value: The type of @surface. See #cairo_surface_type_t.
**/
cairo_surface_type_t
cairo_surface_get_type (cairo_surface_t *surface)
{
/* We don't use surface->backend->type here so that some of the
* special "wrapper" surfaces such as cairo_paginated_surface_t
* can override surface->type with the type of the "child"
* surface. */
return surface->type;
}
/**
* cairo_surface_status:
* @surface: a #cairo_surface_t
@ -141,6 +160,8 @@ _cairo_surface_init (cairo_surface_t *surface,
const cairo_surface_backend_t *backend)
{
surface->backend = backend;
surface->type = backend->type;
surface->ref_count = 1;
surface->status = CAIRO_STATUS_SUCCESS;
@ -503,6 +524,10 @@ cairo_surface_mark_dirty (cairo_surface_t *surface)
* Like cairo_surface_mark_dirty(), but drawing has been done only to
* the specified rectangle, so that cairo can retain cached contents
* for other parts of the surface.
*
* Any cached clip set on the surface will be reset by this function,
* to make sure that future cairo calls have the clip set that they
* expect.
*/
void
cairo_surface_mark_dirty_rectangle (cairo_surface_t *surface,
@ -521,6 +546,13 @@ cairo_surface_mark_dirty_rectangle (cairo_surface_t *surface,
return;
}
/* Always reset the clip here, to avoid having external calls to
* clip manipulation functions of the underlying device clip result
* in a desync between the cairo clip and the backend clip, due to
* the clip caching.
*/
surface->current_clip_serial = -1;
if (surface->backend->mark_dirty_rectangle) {
cairo_status_t status;
@ -1330,6 +1362,12 @@ _cairo_surface_set_clip (cairo_surface_t *surface, cairo_clip_t *clip)
if (!surface)
return CAIRO_STATUS_NULL_POINTER;
if (surface->status)
return surface->status;
if (surface->finished)
return CAIRO_STATUS_SURFACE_FINISHED;
if (clip) {
serial = clip->serial;
if (serial == 0)
@ -1337,7 +1375,7 @@ _cairo_surface_set_clip (cairo_surface_t *surface, cairo_clip_t *clip)
}
surface->clip = clip;
if (serial == _cairo_surface_get_current_clip_serial (surface))
return CAIRO_STATUS_SUCCESS;

View file

@ -88,8 +88,12 @@ struct cairo_svg_surface {
cairo_svg_document_t *document;
xmlNodePtr xml_node;
xmlNodePtr xml_root_node;
unsigned int clip_level;
cairo_bool_t modified;
unsigned int previous_id;
};
static cairo_svg_document_t *
@ -139,11 +143,15 @@ cairo_svg_surface_create_for_stream (cairo_write_func_t write,
double width,
double height)
{
cairo_status_t status;
cairo_output_stream_t *stream;
stream = _cairo_output_stream_create (write, closure);
if (stream == NULL)
return NULL;
stream = _cairo_output_stream_create (write, NULL, closure);
status = _cairo_output_stream_get_status (stream);
if (status) {
_cairo_error (status);
return (cairo_surface_t *) &cairo_surface_nil;
}
return _cairo_svg_surface_create_for_stream_internal (stream, width, height);
}
@ -153,11 +161,15 @@ cairo_svg_surface_create (const char *filename,
double width,
double height)
{
cairo_status_t status;
cairo_output_stream_t *stream;
stream = _cairo_output_stream_create_for_file (filename);
if (stream == NULL)
return NULL;
status = _cairo_output_stream_get_status (stream);
if (status) {
_cairo_error (status);
return (cairo_surface_t *) &cairo_surface_nil;
}
return _cairo_svg_surface_create_for_stream_internal (stream, width, height);
}
@ -209,15 +221,16 @@ _cairo_svg_surface_create_for_document (cairo_svg_document_t *document,
_cairo_dtostr (buffer, sizeof buffer, height);
xmlSetProp (clip_rect, CC2XML ("height"), C2XML (buffer));
surface->xml_node = xmlNewChild (surface->id == 0 ?
document->xml_node_main :
document->xml_node_defs,
NULL, CC2XML ("g"), NULL);
surface->xml_node = xmlNewNode (NULL, CC2XML ("g"));
surface->xml_root_node = surface->xml_node;
snprintf (buffer, sizeof buffer, "surface%d", surface->id);
xmlSetProp (surface->xml_node, CC2XML ("id"), C2XML (buffer));
snprintf (buffer, sizeof buffer, "url(#clip%d)", clip_id);
xmlSetProp (surface->xml_node, CC2XML ("clip-path"), C2XML (buffer));
surface->modified = TRUE;
surface->previous_id = surface->id;
return &surface->base;
}
@ -240,14 +253,19 @@ _cairo_svg_surface_finish (void *abstract_surface)
cairo_status_t status;
cairo_svg_surface_t *surface = abstract_surface;
cairo_svg_document_t *document = surface->document;
if (document->owner == &surface->base)
if (document->owner == &surface->base) {
xmlAddChild (document->xml_node_main, xmlCopyNode (surface->xml_root_node, 1));
status = _cairo_svg_document_finish (document);
else
} else
status = CAIRO_STATUS_SUCCESS;
_cairo_svg_document_destroy (document);
xmlFreeNode (surface->xml_root_node);
surface->xml_node = NULL;
return status;
}
@ -263,22 +281,22 @@ emit_transform (xmlNodePtr node,
xmlBufferCat (matrix_buffer, CC2XML ("matrix("));
_cairo_dtostr (buffer, sizeof buffer, matrix->xx);
xmlBufferCat (matrix_buffer, C2XML (buffer));
xmlBufferCat (matrix_buffer, ",");
xmlBufferCat (matrix_buffer, CC2XML (","));
_cairo_dtostr (buffer, sizeof buffer, matrix->yx);
xmlBufferCat (matrix_buffer, C2XML (buffer));
xmlBufferCat (matrix_buffer, ",");
xmlBufferCat (matrix_buffer, CC2XML (","));
_cairo_dtostr (buffer, sizeof buffer, matrix->xy);
xmlBufferCat (matrix_buffer, C2XML (buffer));
xmlBufferCat (matrix_buffer, ",");
xmlBufferCat (matrix_buffer, CC2XML (","));
_cairo_dtostr (buffer, sizeof buffer, matrix->yy);
xmlBufferCat (matrix_buffer, C2XML (buffer));
xmlBufferCat (matrix_buffer, ",");
xmlBufferCat (matrix_buffer, CC2XML (","));
_cairo_dtostr (buffer, sizeof buffer, matrix->x0);
xmlBufferCat (matrix_buffer, C2XML (buffer));
xmlBufferCat (matrix_buffer, ",");
xmlBufferCat (matrix_buffer, CC2XML(","));
_cairo_dtostr (buffer, sizeof buffer, matrix->y0);
xmlBufferCat (matrix_buffer, C2XML (buffer));
xmlBufferCat (matrix_buffer, ")");
xmlBufferCat (matrix_buffer, CC2XML (")"));
xmlSetProp (node, CC2XML (attribute_str), C2XML (xmlBufferContent (matrix_buffer)));
xmlBufferFree (matrix_buffer);
}
@ -292,7 +310,7 @@ typedef struct {
unsigned int trailing;
} base64_write_closure_t;
static unsigned char const *base64_table =
static char const *base64_table =
"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
static cairo_status_t
@ -325,7 +343,7 @@ base64_write_func (void *closure,
info->count++;
if (info->count >= 18) {
info->count = 0;
xmlBufferCat (info->buffer, "\r\n");
xmlBufferCat (info->buffer, CC2XML ("\r\n"));
}
dst[0] = base64_table[src[0] >> 2];
dst[1] = base64_table[(src[0] & 0x03) << 4 | src[1] >> 4];
@ -450,16 +468,16 @@ emit_composite_svg_pattern (xmlNodePtr node,
cairo_bool_t is_pattern)
{
cairo_svg_surface_t *surface = (cairo_svg_surface_t *) pattern->surface;
cairo_svg_document_t *document = surface->document;
cairo_matrix_t p2u;
xmlNodePtr child;
char buffer[CAIRO_SVG_DTOSTR_BUFFER_LEN];
/* FIXME: self copy is not supported yet */
if (surface->id == 0)
return NULL;
if (surface->modified)
xmlAddChild (document->xml_node_defs, xmlCopyNode (surface->xml_root_node, 1));
child = xmlNewChild (node, NULL, CC2XML("use"), NULL);
snprintf (buffer, sizeof buffer, "#surface%d", surface->id);
snprintf (buffer, sizeof buffer, "#surface%d", surface->previous_id);
xmlSetProp (child, CC2XML ("xlink:href"), C2XML (buffer));
if (!is_pattern) {
@ -473,6 +491,14 @@ emit_composite_svg_pattern (xmlNodePtr node,
if (height != NULL)
*height = surface->height;
if (surface->modified) {
surface->modified = FALSE;
surface->previous_id = surface->id;
surface->id = document->surface_id++;
snprintf (buffer, sizeof buffer, "surface%d", surface->id);
xmlSetProp (surface->xml_root_node, CC2XML ("id"), C2XML (buffer));
}
return child;
}
@ -762,19 +788,19 @@ emit_pattern (cairo_svg_surface_t *surface, cairo_pattern_t *pattern,
xmlBufferPtr style, int is_stroke)
{
switch (pattern->type) {
case CAIRO_PATTERN_SOLID:
case CAIRO_PATTERN_TYPE_SOLID:
emit_solid_pattern (surface, (cairo_solid_pattern_t *) pattern, style, is_stroke);
break;
case CAIRO_PATTERN_SURFACE:
case CAIRO_PATTERN_TYPE_SURFACE:
emit_surface_pattern (surface, (cairo_surface_pattern_t *) pattern, style, is_stroke);
break;
case CAIRO_PATTERN_LINEAR:
case CAIRO_PATTERN_TYPE_LINEAR:
emit_linear_pattern (surface, (cairo_linear_pattern_t *) pattern, style, is_stroke);
break;
case CAIRO_PATTERN_RADIAL:
case CAIRO_PATTERN_TYPE_RADIAL:
emit_radial_pattern (surface, (cairo_radial_pattern_t *) pattern, style, is_stroke);
break;
}
@ -898,9 +924,9 @@ _cairo_svg_surface_fill (void *abstract_surface,
style = xmlBufferCreate ();
emit_pattern (surface, source, style, 0);
xmlBufferCat (style, " stroke: none;");
xmlBufferCat (style, " fill-rule: ");
xmlBufferCat (style, fill_rule == CAIRO_FILL_RULE_EVEN_ODD ? "evenodd;" : "nonzero;");
xmlBufferCat (style, CC2XML (" stroke: none;"));
xmlBufferCat (style, CC2XML (" fill-rule: "));
xmlBufferCat (style, fill_rule == CAIRO_FILL_RULE_EVEN_ODD ? CC2XML("evenodd;") : CC2XML ("nonzero;"));
status = _cairo_path_fixed_interpret (path,
CAIRO_DIRECTION_FORWARD,
@ -918,6 +944,7 @@ _cairo_svg_surface_fill (void *abstract_surface,
xmlBufferFree (info.path);
xmlBufferFree (style);
surface->modified = TRUE;
return status;
}
@ -950,14 +977,14 @@ emit_paint (xmlNodePtr node,
xmlBufferPtr style;
char buffer[CAIRO_SVG_DTOSTR_BUFFER_LEN];
if (source->type == CAIRO_PATTERN_SURFACE)
if (source->type == CAIRO_PATTERN_TYPE_SURFACE)
return emit_composite_pattern (node,
(cairo_surface_pattern_t *) source,
NULL, NULL, FALSE);
style = xmlBufferCreate ();
emit_pattern (surface, source, style, 0);
xmlBufferCat (style, " stroke: none;");
xmlBufferCat (style, CC2XML (" stroke: none;"));
child = xmlNewChild (node, NULL, CC2XML ("rect"), NULL);
xmlSetProp (child, CC2XML ("x"), CC2XML ("0"));
@ -980,8 +1007,10 @@ _cairo_svg_surface_paint (void *abstract_surface,
cairo_pattern_t *source)
{
cairo_svg_surface_t *surface = abstract_surface;
emit_paint (surface->xml_node, surface, op, source);
surface->modified = TRUE;
return CAIRO_STATUS_SUCCESS;
}
@ -1010,6 +1039,7 @@ _cairo_svg_surface_mask (void *abstract_surface,
document->mask_id++;
surface->modified = TRUE;
return CAIRO_STATUS_SUCCESS;
}
@ -1076,21 +1106,21 @@ _cairo_svg_surface_stroke (void *abstract_dst,
xmlBufferCat (style, CC2XML (" stroke-dasharray: "));
for (i = 0; i < stroke_style->num_dashes; i++) {
if (i != 0)
xmlBufferCat (style, ",");
xmlBufferCat (style, CC2XML (","));
/* FIXME: Is is really what we want ? */
rx = ry = stroke_style->dash[i];
cairo_matrix_transform_distance (ctm, &rx, &ry);
_cairo_dtostr (buffer, sizeof buffer, sqrt ((rx * rx + ry * ry) / 2.0));
xmlBufferCat (style, C2XML (buffer));
}
xmlBufferCat (style, ";");
xmlBufferCat (style, CC2XML (";"));
if (stroke_style->dash_offset != 0.0) {
xmlBufferCat (style, CC2XML (" stroke-dashoffset: "));
rx = ry = stroke_style->dash_offset;
cairo_matrix_transform_distance (ctm, &rx, &ry);
_cairo_dtostr (buffer, sizeof buffer, sqrt ((rx * rx + ry * ry) / 2.0));
xmlBufferCat (style, C2XML (buffer));
xmlBufferCat (style, ";");
xmlBufferCat (style, CC2XML (";"));
}
}
@ -1115,6 +1145,7 @@ _cairo_svg_surface_stroke (void *abstract_dst,
xmlBufferFree (info.path);
xmlBufferFree (style);
surface->modified = TRUE;
return status;
}
@ -1126,6 +1157,7 @@ _cairo_svg_surface_show_glyphs (void *abstract_surface,
int num_glyphs,
cairo_scaled_font_t *scaled_font)
{
cairo_svg_surface_t *surface = abstract_surface;
cairo_path_fixed_t path;
cairo_status_t status;
@ -1149,6 +1181,7 @@ _cairo_svg_surface_show_glyphs (void *abstract_surface,
_cairo_path_fixed_fini (&path);
surface->modified = TRUE;
return status;
}
@ -1167,10 +1200,8 @@ _cairo_svg_surface_intersect_clip_path (void *dst,
char buffer[CAIRO_SVG_DTOSTR_BUFFER_LEN];
if (path == NULL) {
while (surface->clip_level > 0) {
surface->xml_node = surface->xml_node->parent;
surface->clip_level--;
}
surface->xml_node = surface->xml_root_node;
surface->clip_level = 0;
return CAIRO_STATUS_SUCCESS;
}
@ -1221,6 +1252,7 @@ _cairo_svg_surface_get_font_options (void *abstract_surface,
static const cairo_surface_backend_t cairo_svg_surface_backend = {
CAIRO_SURFACE_TYPE_SVG,
_cairo_svg_surface_create_similar,
_cairo_svg_surface_finish,
NULL, /* acquire_source_image */
@ -1318,21 +1350,34 @@ _cairo_svg_document_destroy (cairo_svg_document_t *document)
free (document);
}
static int
_cairo_svg_document_write (cairo_output_stream_t *output_stream,
const char * buffer,
int len)
{
if (_cairo_output_stream_write (output_stream, buffer, len) != CAIRO_STATUS_SUCCESS)
return -1;
return len;
}
static cairo_status_t
_cairo_svg_document_finish (cairo_svg_document_t *document)
{
cairo_status_t status;
cairo_output_stream_t *output = document->output_stream;
xmlChar *xml_buffer;
int xml_buffer_size;
xmlOutputBufferPtr xml_output_buffer;
if (document->finished)
return CAIRO_STATUS_SUCCESS;
/* FIXME: Dumping xml tree in memory is silly. */
xmlDocDumpFormatMemoryEnc (document->xml_doc, &xml_buffer, &xml_buffer_size, "UTF-8", 1);
_cairo_output_stream_write (document->output_stream, xml_buffer, xml_buffer_size);
xmlFree(xml_buffer);
xml_output_buffer = xmlOutputBufferCreateIO ((xmlOutputWriteCallback) _cairo_svg_document_write,
(xmlOutputCloseCallback) NULL,
(void *) document->output_stream,
NULL);
xmlSaveFormatFileTo (xml_output_buffer, document->xml_doc, "UTF-8", 1);
xmlFreeDoc (document->xml_doc);
status = _cairo_output_stream_get_status (output);

View file

@ -1,5 +1,4 @@
/*
* $Id: cairo-wideint.c,v 1.6 2005-07-30 19:57:54 keithp Exp $
/* cairo - a vector graphics library with display and print output
*
* Copyright © 2004 Keith Packard
*

View file

@ -1,5 +1,4 @@
/*
* $Id: cairo-wideint.h,v 1.12 2005-08-05 14:48:19 cworth Exp $
/* cairo - a vector graphics library with display and print output
*
* Copyright © 2004 Keith Packard
*

View file

@ -1159,7 +1159,7 @@ _cairo_win32_scaled_font_show_glyphs (void *abstract_font,
cairo_surface_pattern_t mask;
RECT r;
tmp_surface = (cairo_win32_surface_t *)_cairo_win32_surface_create_dib (CAIRO_FORMAT_ARGB32, width, height);
tmp_surface = (cairo_win32_surface_t *)cairo_win32_surface_create_with_dib (CAIRO_FORMAT_ARGB32, width, height);
if (tmp_surface->base.status)
return CAIRO_STATUS_NO_MEMORY;
@ -1355,6 +1355,7 @@ CLEANUP_FONT:
}
const cairo_scaled_font_backend_t cairo_win32_scaled_font_backend = {
CAIRO_FONT_TYPE_WIN32,
_cairo_win32_scaled_font_create_toy,
_cairo_win32_scaled_font_fini,
_cairo_win32_scaled_font_glyph_init,

View file

@ -62,19 +62,14 @@ typedef struct _cairo_win32_surface {
cairo_rectangle_t clip_rect;
int set_clip;
HRGN saved_clip;
cairo_rectangle_t extents;
} cairo_win32_surface_t;
cairo_status_t
_cairo_win32_print_gdi_error (const char *context);
cairo_surface_t *
_cairo_win32_surface_create_dib (cairo_format_t format,
int width,
int height);
cairo_bool_t
_cairo_surface_is_win32 (cairo_surface_t *surface);

View file

@ -31,6 +31,8 @@
*
* Contributor(s):
* Owen Taylor <otaylor@redhat.com>
* Stuart Parmenter <stuart@mozilla.com>
* Vladimir Vukicevic <vladimir@pobox.com>
*/
#include <stdio.h>
@ -274,9 +276,14 @@ _cairo_win32_surface_create_for_dc (HDC original_dc,
surface->clip_rect.width = width;
surface->clip_rect.height = height;
surface->set_clip = 0;
surface->saved_clip = NULL;
surface->saved_clip = CreateRectRgn (0, 0, 0, 0);
if (GetClipRgn (surface->dc, surface->saved_clip) == 0) {
DeleteObject(surface->saved_clip);
surface->saved_clip = NULL;
}
surface->extents = surface->clip_rect;
_cairo_surface_init (&surface->base, &cairo_win32_surface_backend);
return (cairo_surface_t *)surface;
@ -311,27 +318,6 @@ _cairo_win32_surface_create_similar (void *abstract_src,
return _cairo_win32_surface_create_for_dc (src->dc, format, width, height);
}
/**
* _cairo_win32_surface_create_dib:
* @format: format of pixels in the surface to create
* @width: width of the surface, in pixels
* @height: height of the surface, in pixels
*
* Creates a device-independent-bitmap surface not associated with
* any particular existing surface or device context. The created
* bitmap will be unititialized.
*
* Return value: the newly created surface, or %NULL if it couldn't
* be created (probably because of lack of memory)
**/
cairo_surface_t *
_cairo_win32_surface_create_dib (cairo_format_t format,
int width,
int height)
{
return _cairo_win32_surface_create_for_dc (NULL, format, width, height);
}
static cairo_status_t
_cairo_win32_surface_finish (void *abstract_surface)
{
@ -340,9 +326,8 @@ _cairo_win32_surface_finish (void *abstract_surface)
if (surface->image)
cairo_surface_destroy (surface->image);
if (surface->saved_clip) {
if (surface->saved_clip)
DeleteObject (surface->saved_clip);
}
/* If we created the Bitmap and DC, destroy them */
if (surface->bitmap) {
@ -379,8 +364,18 @@ _cairo_win32_surface_get_subimage (cairo_win32_surface_t *surface,
width, height,
surface->dc,
x, y,
SRCCOPY))
goto FAIL;
SRCCOPY)) {
/* If we fail to BitBlt here, most likely the source is a printer.
* You can't reliably get bits from a printer DC, so just fill in
* the surface as white (common case for printing).
*/
RECT r;
r.left = r.top = 0;
r.right = width;
r.bottom = height;
FillRect(local->dc, &r, (HBRUSH)GetStockObject(WHITE_BRUSH));
}
*local_out = local;
@ -403,7 +398,7 @@ _cairo_win32_surface_acquire_source_image (void *abstract_sur
cairo_win32_surface_t *surface = abstract_surface;
cairo_win32_surface_t *local = NULL;
cairo_status_t status;
if (surface->image) {
*image_out = (cairo_image_surface_t *)surface->image;
*image_extra = NULL;
@ -446,7 +441,7 @@ _cairo_win32_surface_acquire_dest_image (void *abstract_surfa
cairo_status_t status;
RECT clip_box;
int x1, y1, x2, y2;
if (surface->image) {
image_rect->x = 0;
image_rect->y = 0;
@ -461,12 +456,12 @@ _cairo_win32_surface_acquire_dest_image (void *abstract_surfa
if (GetClipBox (surface->dc, &clip_box) == ERROR)
return _cairo_win32_print_gdi_error ("_cairo_win3_surface_acquire_dest_image");
x1 = clip_box.left;
x2 = clip_box.right;
y1 = clip_box.top;
y2 = clip_box.bottom;
if (interest_rect->x > x1)
x1 = interest_rect->x;
if (interest_rect->y > y1)
@ -595,6 +590,8 @@ _composite_alpha_blend (cairo_win32_surface_t *dst,
if (alpha_blend == NULL)
return CAIRO_INT_STATUS_UNSUPPORTED;
if (GetDeviceCaps(dst->dc, SHADEBLENDCAPS) == SB_NONE)
return CAIRO_INT_STATUS_UNSUPPORTED;
blend_function.BlendOp = AC_SRC_OVER;
blend_function.BlendFlags = 0;
@ -634,7 +631,7 @@ _cairo_win32_surface_composite (cairo_operator_t op,
int integer_transform;
int itx, ity;
if (pattern->type != CAIRO_PATTERN_SURFACE ||
if (pattern->type != CAIRO_PATTERN_TYPE_SURFACE ||
pattern->extend != CAIRO_EXTEND_NONE)
return CAIRO_INT_STATUS_UNSUPPORTED;
@ -642,7 +639,7 @@ _cairo_win32_surface_composite (cairo_operator_t op,
/* FIXME: When we fully support RENDER style 4-channel
* masks we need to check r/g/b != 1.0.
*/
if (mask_pattern->type != CAIRO_PATTERN_SOLID)
if (mask_pattern->type != CAIRO_PATTERN_TYPE_SOLID)
return CAIRO_INT_STATUS_UNSUPPORTED;
alpha = ((cairo_solid_pattern_t *)mask_pattern)->color.alpha_short >> 8;
@ -660,6 +657,33 @@ _cairo_win32_surface_composite (cairo_operator_t op,
if (!integer_transform)
return CAIRO_INT_STATUS_UNSUPPORTED;
/* Fix up src coordinates; the src coords and size must be within the
* bounds of the source surface.
* XXX the region not covered should be appropriately rendered!
* - for OVER/SOURCE with RGB24 source -> opaque black
* - for SOURCE with ARGB32 source -> 100% transparent black
*/
src_x += itx;
src_y += ity;
if (src_x < 0) {
width += src_x;
dst_x -= src_x;
src_x = 0;
}
if (src_y < 0) {
height += src_y;
dst_y -= src_y;
src_y = 0;
}
if (src_x + width > src->extents.width)
width = src->extents.width - src_x;
if (src_y + height > src->extents.height)
height = src->extents.height - src_y;
if (alpha == 255 &&
src->format == dst->format &&
(op == CAIRO_OPERATOR_SOURCE ||
@ -669,7 +693,7 @@ _cairo_win32_surface_composite (cairo_operator_t op,
dst_x, dst_y,
width, height,
src->dc,
src_x + itx, src_y + ity,
src_x, src_y,
SRCCOPY))
return _cairo_win32_print_gdi_error ("_cairo_win32_surface_composite");
@ -681,7 +705,7 @@ _cairo_win32_surface_composite (cairo_operator_t op,
op == CAIRO_OPERATOR_OVER) {
return _composite_alpha_blend (dst, src, alpha,
src_x + itx, src_y + ity,
src_x, src_y,
dst_x, dst_y, width, height);
}
@ -855,19 +879,9 @@ _cairo_win32_surface_set_clip_region (void *abstract_surface,
if (region == NULL) {
/* Clear any clip set by cairo, return to the original */
if (surface->set_clip) {
if (SelectClipRgn (surface->dc, surface->saved_clip) == ERROR)
return _cairo_win32_print_gdi_error ("_cairo_win32_surface_set_clip_region");
if (SelectClipRgn (surface->dc, surface->saved_clip) == ERROR)
return _cairo_win32_print_gdi_error ("_cairo_win32_surface_set_clip_region (reset)");
if (surface->saved_clip) {
DeleteObject (surface->saved_clip);
surface->saved_clip = NULL;
}
surface->set_clip = 0;
}
return CAIRO_STATUS_SUCCESS;
} else {
@ -910,36 +924,16 @@ _cairo_win32_surface_set_clip_region (void *abstract_surface,
if (!gdi_region)
return CAIRO_STATUS_NO_MEMORY;
if (surface->set_clip) {
/* Combine the new region with the original clip */
if (surface->saved_clip) {
if (CombineRgn (gdi_region, gdi_region, surface->saved_clip, RGN_AND) == ERROR)
goto FAIL;
}
/* Combine the new region with the original clip */
if (SelectClipRgn (surface->dc, gdi_region) == ERROR)
if (surface->saved_clip) {
if (CombineRgn (gdi_region, gdi_region, surface->saved_clip, RGN_AND) == ERROR)
goto FAIL;
} else {
/* Save the the current region */
surface->saved_clip = CreateRectRgn (0, 0, 0, 0);
if (!surface->saved_clip) {
goto FAIL; }
/* This function has no error return! */
if (GetClipRgn (surface->dc, surface->saved_clip) == 0) { /* No clip */
DeleteObject (surface->saved_clip);
surface->saved_clip = NULL;
}
if (ExtSelectClipRgn (surface->dc, gdi_region, RGN_AND) == ERROR)
goto FAIL;
surface->set_clip = 1;
}
if (SelectClipRgn (surface->dc, gdi_region) == ERROR)
goto FAIL;
DeleteObject (gdi_region);
return CAIRO_STATUS_SUCCESS;
@ -955,15 +949,8 @@ _cairo_win32_surface_get_extents (void *abstract_surface,
cairo_rectangle_t *rectangle)
{
cairo_win32_surface_t *surface = abstract_surface;
RECT clip_box;
if (GetClipBox (surface->dc, &clip_box) == ERROR)
return _cairo_win32_print_gdi_error ("_cairo_win3_surface_acquire_dest_image");
rectangle->x = clip_box.left;
rectangle->y = clip_box.top;
rectangle->width = clip_box.right - clip_box.left;
rectangle->height = clip_box.bottom - clip_box.top;
*rectangle = surface->extents;
return CAIRO_STATUS_SUCCESS;
}
@ -974,11 +961,25 @@ _cairo_win32_surface_flush (void *abstract_surface)
return _cairo_surface_reset_clip (abstract_surface);
}
/**
* cairo_win32_surface_create:
* @hdc: the DC to create a surface for
*
* Creates a cairo surface that targets the given DC. The DC will be
* queried for its initial clip extents, and this will be used as the
* size of the cairo surface. Also, if the DC is a raster DC, it will
* be queried for its pixel format and the cairo surface format will
* be set appropriately.
*
* Return value: the newly created surface
**/
cairo_surface_t *
cairo_win32_surface_create (HDC hdc)
{
cairo_win32_surface_t *surface;
RECT rect;
int depth;
cairo_format_t format;
/* Try to figure out the drawing bounds for the Device context
*/
@ -988,7 +989,28 @@ cairo_win32_surface_create (HDC hdc)
_cairo_error (CAIRO_STATUS_NO_MEMORY);
return &_cairo_surface_nil;
}
if (GetDeviceCaps(hdc, TECHNOLOGY) == DT_RASDISPLAY) {
depth = GetDeviceCaps(hdc, BITSPIXEL);
if (depth == 32)
format = CAIRO_FORMAT_ARGB32;
else if (depth == 24)
format = CAIRO_FORMAT_RGB24;
else if (depth == 16)
format = CAIRO_FORMAT_RGB24;
else if (depth == 8)
format = CAIRO_FORMAT_A8;
else if (depth == 1)
format = CAIRO_FORMAT_A1;
else {
_cairo_win32_print_gdi_error("cairo_win32_surface_create(bad BITSPIXEL)");
_cairo_error (CAIRO_STATUS_NO_MEMORY);
return &_cairo_surface_nil;
}
} else {
format = CAIRO_FORMAT_RGB24;
}
surface = malloc (sizeof (cairo_win32_surface_t));
if (surface == NULL) {
_cairo_error (CAIRO_STATUS_NO_MEMORY);
@ -996,7 +1018,7 @@ cairo_win32_surface_create (HDC hdc)
}
surface->image = NULL;
surface->format = CAIRO_FORMAT_RGB24;
surface->format = format;
surface->dc = hdc;
surface->bitmap = NULL;
@ -1007,14 +1029,47 @@ cairo_win32_surface_create (HDC hdc)
surface->clip_rect.width = rect.right - rect.left;
surface->clip_rect.height = rect.bottom - rect.top;
surface->set_clip = 0;
surface->saved_clip = NULL;
if (surface->clip_rect.width == 0 ||
surface->clip_rect.height == 0)
{
surface->saved_clip = NULL;
} else {
surface->saved_clip = CreateRectRgn (0, 0, 0, 0);
if (GetClipRgn (hdc, surface->saved_clip) == 0) {
DeleteObject(surface->saved_clip);
surface->saved_clip = NULL;
}
}
surface->extents = surface->clip_rect;
_cairo_surface_init (&surface->base, &cairo_win32_surface_backend);
return (cairo_surface_t *)surface;
}
/**
* cairo_win32_surface_create_with_dib:
* @format: format of pixels in the surface to create
* @width: width of the surface, in pixels
* @height: height of the surface, in pixels
*
* Creates a device-independent-bitmap surface not associated with
* any particular existing surface or device context. The created
* bitmap will be unititialized.
*
* Return value: the newly created surface
*
**/
cairo_surface_t *
cairo_win32_surface_create_with_dib (cairo_format_t format,
int width,
int height)
{
return _cairo_win32_surface_create_for_dc (NULL, format, width, height);
}
/**
* _cairo_surface_is_win32:
* @surface: a #cairo_surface_t
@ -1029,7 +1084,33 @@ _cairo_surface_is_win32 (cairo_surface_t *surface)
return surface->backend == &cairo_win32_surface_backend;
}
/**
* cairo_win32_surface_get_dc
* @surface: a #cairo_surface_t
*
* Returns the HDC associated with this surface, or NULL if none.
* Also returns NULL if the surface is not a win32 surface.
*
* Return value: HDC or NULL if no HDC available.
**/
HDC
cairo_win32_surface_get_dc (cairo_surface_t *surface)
{
cairo_win32_surface_t *winsurf;
if (surface == NULL)
return NULL;
if (!_cairo_surface_is_win32(surface))
return NULL;
winsurf = (cairo_win32_surface_t *) surface;
return winsurf->dc;
}
static const cairo_surface_backend_t cairo_win32_surface_backend = {
CAIRO_SURFACE_TYPE_WIN32,
_cairo_win32_surface_create_similar,
_cairo_win32_surface_finish,
_cairo_win32_surface_acquire_source_image,

View file

@ -47,6 +47,14 @@ CAIRO_BEGIN_DECLS
cairo_public cairo_surface_t *
cairo_win32_surface_create (HDC hdc);
cairo_public cairo_surface_t *
cairo_win32_surface_create_with_dib (cairo_format_t format,
int width,
int height);
cairo_public HDC
cairo_win32_surface_get_dc (cairo_surface_t *surface);
cairo_public cairo_font_face_t *
cairo_win32_font_face_create_for_logfontw (LOGFONTW *logfont);

View file

@ -1025,6 +1025,7 @@ _cairo_xcb_surface_get_extents (void *abstract_surface,
}
static const cairo_surface_backend_t cairo_xcb_surface_backend = {
CAIRO_SURFACE_TYPE_XCB,
_cairo_xcb_surface_create_similar,
_cairo_xcb_surface_finish,
_cairo_xcb_surface_acquire_source_image,

View file

@ -41,6 +41,7 @@
#include "cairo-xlib-test.h"
#include "cairo-xlib-private.h"
#include <X11/extensions/Xrender.h>
#include <X11/extensions/renderproto.h>
/* Xlib doesn't define a typedef, so define one ourselves */
typedef int (*cairo_xlib_error_func_t) (Display *display,
@ -1675,6 +1676,7 @@ _cairo_xlib_surface_scaled_glyph_fini (cairo_scaled_glyph_t *scaled_glyph,
cairo_scaled_font_t *scaled_font);
static const cairo_surface_backend_t cairo_xlib_surface_backend = {
CAIRO_SURFACE_TYPE_XLIB,
_cairo_xlib_surface_create_similar,
_cairo_xlib_surface_finish,
_cairo_xlib_surface_acquire_source_image,
@ -2403,6 +2405,8 @@ _cairo_xlib_surface_old_show_glyphs (cairo_scaled_font_t *scaled_font,
cairo_int_status_t status;
cairo_xlib_surface_t *self = abstract_surface;
cairo_xlib_surface_t *src;
const cairo_glyph_t *glyphs_chunk;
int glyphs_remaining, chunk_size, max_chunk_size;
composite_operation_t operation;
cairo_scaled_glyph_t *scaled_glyph;
cairo_xlib_surface_font_private_t *font_private;
@ -2457,23 +2461,41 @@ _cairo_xlib_surface_old_show_glyphs (cairo_scaled_font_t *scaled_font,
}
_cairo_xlib_surface_ensure_dst_picture (self);
/* Call the appropriate sub-function. */
max_chunk_size = XMaxRequestSize (self->dpy);
if (max_index < 256)
status = _cairo_xlib_surface_old_show_glyphs8 (scaled_font, op, src, self,
source_x + attributes.x_offset - dest_x,
source_y + attributes.y_offset - dest_y,
glyphs, num_glyphs);
max_chunk_size -= sz_xRenderCompositeGlyphs8Req;
else if (max_index < 65536)
status = _cairo_xlib_surface_old_show_glyphs16 (scaled_font, op, src, self,
source_x + attributes.x_offset - dest_x,
source_y + attributes.y_offset - dest_y,
glyphs, num_glyphs);
else
status = _cairo_xlib_surface_old_show_glyphs32 (scaled_font, op, src, self,
source_x + attributes.x_offset - dest_x,
source_y + attributes.y_offset - dest_y,
glyphs, num_glyphs);
max_chunk_size -= sz_xRenderCompositeGlyphs16Req;
else
max_chunk_size -= sz_xRenderCompositeGlyphs32Req;
max_chunk_size /= sz_xGlyphElt;
for (glyphs_remaining = num_glyphs, glyphs_chunk = glyphs;
glyphs_remaining;
glyphs_remaining -= chunk_size, glyphs_chunk += chunk_size)
{
chunk_size = MIN (glyphs_remaining, max_chunk_size);
/* Call the appropriate sub-function. */
if (max_index < 256)
status = _cairo_xlib_surface_old_show_glyphs8 (scaled_font, op, src, self,
source_x + attributes.x_offset - dest_x,
source_y + attributes.y_offset - dest_y,
glyphs_chunk, chunk_size);
else if (max_index < 65536)
status = _cairo_xlib_surface_old_show_glyphs16 (scaled_font, op, src, self,
source_x + attributes.x_offset - dest_x,
source_y + attributes.y_offset - dest_y,
glyphs_chunk, chunk_size);
else
status = _cairo_xlib_surface_old_show_glyphs32 (scaled_font, op, src, self,
source_x + attributes.x_offset - dest_x,
source_y + attributes.y_offset - dest_y,
glyphs_chunk, chunk_size);
if (status != CAIRO_STATUS_SUCCESS)
break;
}
if (status == CAIRO_STATUS_SUCCESS && !_cairo_operator_bounded_by_mask (op)) {
cairo_rectangle_t extents;

View file

@ -2155,6 +2155,9 @@ cairo_show_glyphs (cairo_t *cr, cairo_glyph_t *glyphs, int num_glyphs)
if (cr->status)
return;
if (num_glyphs == 0)
return;
cr->status = _cairo_gstate_show_glyphs (cr->gstate, glyphs, num_glyphs);
if (cr->status)
_cairo_set_error (cr, cr->status);

View file

@ -184,6 +184,10 @@ cairo_private void _cairo_beos_unlock(void*);
#define TRUE 1
#endif
#ifndef M_PI
#define M_PI 3.14159265358979323846
#endif
#define ASSERT_NOT_REACHED \
do { \
static const int NOT_REACHED = 0; \
@ -256,6 +260,15 @@ typedef enum cairo_int_status {
CAIRO_INT_STATUS_CACHE_EMPTY
} cairo_int_status_t;
typedef enum cairo_internal_surface_type {
CAIRO_INTERNAL_SURFACE_TYPE_META = 0x1000,
CAIRO_INTERNAL_SURFACE_TYPE_PAGINATED,
CAIRO_INTERNAL_SURFACE_TYPE_ANALYSIS,
CAIRO_INTERNAL_SURFACE_TYPE_TEST_META,
CAIRO_INTERNAL_SURFACE_TYPE_TEST_FALLBACK,
CAIRO_INTERNAL_SURFACE_TYPE_TEST_PAGINATED
} cairo_internal_surface_type_t;
typedef enum cairo_direction {
CAIRO_DIRECTION_FORWARD,
CAIRO_DIRECTION_REVERSE
@ -509,6 +522,8 @@ typedef enum _cairo_scaled_glyph_info {
} cairo_scaled_glyph_info_t;
struct _cairo_scaled_font_backend {
cairo_font_type_t type;
cairo_status_t
(*create_toy) (cairo_toy_font_face_t *toy_face,
const cairo_matrix_t *font_matrix,
@ -602,6 +617,8 @@ typedef struct _cairo_stroke_style {
} cairo_stroke_style_t;
struct _cairo_surface_backend {
cairo_surface_type_t type;
cairo_surface_t *
(*create_similar) (void *surface,
cairo_content_t content,
@ -832,6 +849,11 @@ typedef struct _cairo_format_masks {
struct _cairo_surface {
const cairo_surface_backend_t *backend;
/* We allow surfaces to override the backend->type by shoving something
* else into surface->type. This is for "wrapper" surfaces that want to
* hide their internal type from the user-level API. */
cairo_surface_type_t type;
unsigned int ref_count;
cairo_status_t status;
cairo_bool_t finished;
@ -2103,14 +2125,37 @@ _cairo_utf8_to_utf16 (const unsigned char *str,
typedef struct _cairo_output_stream cairo_output_stream_t;
extern const cairo_private cairo_output_stream_t cairo_output_stream_nil;
/* We already have the following declared in cairo.h:
typedef cairo_status_t (*cairo_write_func_t) (void *closure,
const unsigned char *data,
unsigned int length);
*/
typedef cairo_status_t (*cairo_close_func_t) (void *closure);
/* This function never returns NULL. If an error occurs (NO_MEMORY)
* while trying to create the output stream this function returns a
* valid pointer to a nil output stream.
*
* Note that even with a nil surface, the close_func callback will be
* called by a call to _cairo_output_stream_close or
* _cairo_output_stream_destroy.
*/
cairo_private cairo_output_stream_t *
_cairo_output_stream_create (cairo_write_func_t write_func,
cairo_close_func_t close_func,
void *closure);
cairo_private void
_cairo_output_stream_close (cairo_output_stream_t *stream);
cairo_private void
_cairo_output_stream_destroy (cairo_output_stream_t *stream);
cairo_private cairo_status_t
cairo_private void
_cairo_output_stream_write (cairo_output_stream_t *stream,
const void *data, size_t length);
@ -2119,11 +2164,14 @@ _cairo_output_stream_write_hex_string (cairo_output_stream_t *stream,
const char *data,
size_t length);
cairo_private cairo_status_t
cairo_private unsigned char *
_cairo_lzw_compress (unsigned char *data, unsigned long *data_size_in_out);
cairo_private void
_cairo_output_stream_vprintf (cairo_output_stream_t *stream,
const char *fmt, va_list ap);
cairo_private cairo_status_t
cairo_private void
_cairo_output_stream_printf (cairo_output_stream_t *stream,
const char *fmt, ...) CAIRO_PRINTF_FORMAT(2, 3);
@ -2133,9 +2181,21 @@ _cairo_output_stream_get_position (cairo_output_stream_t *status);
cairo_private cairo_status_t
_cairo_output_stream_get_status (cairo_output_stream_t *stream);
/* This function never returns NULL. If an error occurs (NO_MEMORY or
* WRITE_ERROR) while trying to create the output stream this function
* returns a valid pointer to a nil output stream.
*
* NOTE: Even if a nil surface is returned, the caller should still
* call _cairo_output_stream_destroy (or _cairo_output_stream_close at
* least) in order to ensure that everything is properly cleaned up.
*/
cairo_private cairo_output_stream_t *
_cairo_output_stream_create_for_file (const char *filename);
/* cairo_base85_stream.c */
cairo_output_stream_t *
_cairo_base85_stream_create (cairo_output_stream_t *output);
cairo_private void
_cairo_error (cairo_status_t status);
@ -2143,7 +2203,6 @@ cairo_private int
_cairo_dtostr (char *buffer, size_t size, double d);
/* Avoid unnecessary PLT entries. */
slim_hidden_proto(cairo_get_current_point)
slim_hidden_proto(cairo_fill_preserve)
slim_hidden_proto(cairo_clip_preserve)

View file

@ -175,6 +175,7 @@ _test_fallback_surface_get_extents (void *abstract_surface,
}
const cairo_surface_backend_t test_fallback_surface_backend = {
CAIRO_INTERNAL_SURFACE_TYPE_TEST_FALLBACK,
_test_fallback_surface_create_similar,
_test_fallback_surface_finish,
_test_fallback_surface_acquire_source_image,

View file

@ -296,6 +296,7 @@ _test_meta_surface_snapshot (void *abstract_other)
}
const cairo_surface_backend_t test_meta_surface_backend = {
CAIRO_INTERNAL_SURFACE_TYPE_TEST_META,
NULL, /* create_similar */
_test_meta_surface_finish,
_test_meta_surface_acquire_source_image,

3
test/.gitignore vendored
View file

@ -24,6 +24,7 @@ fill-and-stroke
fill-rule
filter-nearest-offset
ft-font-create-for-ft-face
font-face-get-type
get-and-set
gradient-alpha
imagediff
@ -43,6 +44,7 @@ operator-source
paint
paint-with-alpha
path-data
pattern-get-type
pdf2png
png-flatten
svg2png
@ -59,6 +61,7 @@ select-font-no-show-text
self-copy
self-intersecting
set-source
show-glyphs-many
show-text-current-point
source-clip
source-surface-scale-paint

View file

@ -20,6 +20,7 @@ extend-reflect \
fill-and-stroke \
fill-rule \
filter-nearest-offset \
font-face-get-type \
get-and-set \
gradient-alpha \
leaky-polygon \
@ -35,6 +36,7 @@ operator-source \
paint \
paint-with-alpha \
path-data \
pattern-get-type \
pixman-rotate \
rectangle-rounding-error \
scale-source-surface-paint \
@ -42,6 +44,7 @@ select-font-no-show-text \
self-copy \
self-intersecting \
set-source \
show-glyphs-many \
show-text-current-point \
source-clip \
source-surface-scale-paint \
@ -299,6 +302,7 @@ dash_offset_negative_LDADD = $(LDADDS)
extend_reflect_LDADD = $(LDADDS)
fill_and_stroke_LDADD = $(LDADDS)
fill_rule_LDADD = $(LDADDS)
font_face_get_type_LDADD = $(LDADDS)
filter_nearest_offset_LDADD = $(LDADDS)
ft_font_create_for_ft_face_LDADD = $(LDADDS)
get_and_set_LDADD = $(LDADDS)
@ -317,6 +321,7 @@ operator_source_LDADD = $(LDADDS)
paint_LDADD = $(LDADDS)
paint_with_alpha_LDADD = $(LDADDS)
path_data_LDADD = $(LDADDS)
pattern_get_type_LDADD = $(LDADDS)
svg_surface_LDADD = $(LDADDS)
svg_clip_LDADD = $(LDADDS)
pixman_rotate_LDADD = $(LDADDS)
@ -327,6 +332,7 @@ select_font_no_show_text_LDADD = $(LDADDS)
self_copy_LDADD = $(LDADDS)
self_intersecting_LDADD = $(LDADDS)
set_source_LDADD = $(LDADDS)
show_glyphs_many_LDADD = $(LDADDS)
show_text_current_point_LDADD = $(LDADDS)
source_clip_LDADD = $(LDADDS)
source_surface_scale_paint_LDADD = $(LDADDS)

View file

@ -47,6 +47,21 @@
#include "write-png.h"
#include "xmalloc.h"
/* This is copied from cairoint.h. That makes it painful to keep in
* sync, but the slim stuff makes cairoint.h "hard" to include when
* not actually building the cairo library itself. Fortunately, since
* we're checking all these values, we do have a safeguard for keeping
* them in sync.
*/
typedef enum cairo_internal_surface_type {
CAIRO_INTERNAL_SURFACE_TYPE_META = 0x1000,
CAIRO_INTERNAL_SURFACE_TYPE_PAGINATED,
CAIRO_INTERNAL_SURFACE_TYPE_ANALYSIS,
CAIRO_INTERNAL_SURFACE_TYPE_TEST_META,
CAIRO_INTERNAL_SURFACE_TYPE_TEST_FALLBACK,
CAIRO_INTERNAL_SURFACE_TYPE_TEST_PAGINATED
} cairo_internal_surface_type_t;
#ifdef _MSC_VER
#define vsnprintf _vsnprintf
#define access _access
@ -163,6 +178,7 @@ typedef void
typedef struct _cairo_test_target
{
const char *name;
cairo_surface_type_t expected_type;
cairo_content_t content;
cairo_test_create_target_surface_t create_target_surface;
cairo_test_write_to_png_t write_to_png;
@ -1387,6 +1403,13 @@ cairo_test_for_target (cairo_test_t *test,
goto UNWIND_STRINGS;
}
if (cairo_surface_get_type (surface) != target->expected_type) {
cairo_test_log ("Error: Created surface is of type %d (expected %d)\n",
cairo_surface_get_type (surface), target->expected_type);
ret = CAIRO_TEST_FAILURE;
goto UNWIND_SURFACE;
}
cr = cairo_create (surface);
/* Clear to transparent (or black) depending on whether the target
@ -1418,6 +1441,7 @@ cairo_test_for_target (cairo_test_t *test,
/* Skip image check for tests with no image (width,height == 0,0) */
if (test->width != 0 && test->height != 0) {
int pixels_changed;
xunlink (png_name);
(target->write_to_png) (surface, png_name);
if (target->content == CAIRO_TEST_CONTENT_COLOR_ALPHA_FLATTENED)
pixels_changed = image_diff_flattened (png_name, ref_name, diff_name);
@ -1436,6 +1460,7 @@ cairo_test_for_target (cairo_test_t *test,
UNWIND_CAIRO:
cairo_destroy (cr);
UNWIND_SURFACE:
cairo_surface_destroy (surface);
cairo_debug_reset_static_data ();
@ -1461,102 +1486,128 @@ cairo_test_expecting (cairo_test_t *test, cairo_test_draw_function_t draw,
cairo_test_target_t **targets_to_test;
cairo_test_target_t targets[] =
{
{ "image", CAIRO_CONTENT_COLOR_ALPHA,
{ "image", CAIRO_SURFACE_TYPE_IMAGE, CAIRO_CONTENT_COLOR_ALPHA,
create_image_surface, cairo_surface_write_to_png, NULL},
{ "image", CAIRO_CONTENT_COLOR,
{ "image", CAIRO_SURFACE_TYPE_IMAGE, CAIRO_CONTENT_COLOR,
create_image_surface, cairo_surface_write_to_png, NULL},
#ifdef CAIRO_HAS_TEST_SURFACES
{ "test-fallback", CAIRO_CONTENT_COLOR_ALPHA,
{ "test-fallback", CAIRO_INTERNAL_SURFACE_TYPE_TEST_FALLBACK,
CAIRO_CONTENT_COLOR_ALPHA,
create_test_fallback_surface, cairo_surface_write_to_png, NULL },
{ "test-fallback", CAIRO_CONTENT_COLOR,
{ "test-fallback", CAIRO_INTERNAL_SURFACE_TYPE_TEST_FALLBACK,
CAIRO_CONTENT_COLOR,
create_test_fallback_surface, cairo_surface_write_to_png, NULL },
{ "test-meta", CAIRO_CONTENT_COLOR_ALPHA,
{ "test-meta", CAIRO_INTERNAL_SURFACE_TYPE_TEST_META,
CAIRO_CONTENT_COLOR_ALPHA,
create_test_meta_surface, cairo_surface_write_to_png, NULL },
{ "test-meta", CAIRO_CONTENT_COLOR,
{ "test-meta", CAIRO_INTERNAL_SURFACE_TYPE_TEST_META,
CAIRO_CONTENT_COLOR,
create_test_meta_surface, cairo_surface_write_to_png, NULL },
{ "test-paginated", CAIRO_CONTENT_COLOR_ALPHA,
{ "test-paginated", CAIRO_SURFACE_TYPE_IMAGE,
CAIRO_CONTENT_COLOR_ALPHA,
create_test_paginated_surface,
test_paginated_write_to_png,
cleanup_test_paginated },
{ "test-paginated", CAIRO_CONTENT_COLOR,
{ "test-paginated", CAIRO_SURFACE_TYPE_IMAGE,
CAIRO_CONTENT_COLOR,
create_test_paginated_surface,
test_paginated_write_to_png,
cleanup_test_paginated },
#endif
#ifdef CAIRO_HAS_GLITZ_SURFACE
#if CAIRO_CAN_TEST_GLITZ_GLX_SURFACE
{ "glitz-glx", CAIRO_CONTENT_COLOR_ALPHA,
{ "glitz-glx", CAIRO_SURFACE_TYPE_GLITZ,CAIRO_CONTENT_COLOR_ALPHA,
create_cairo_glitz_glx_surface, cairo_surface_write_to_png,
cleanup_cairo_glitz_glx },
{ "glitz-glx", CAIRO_CONTENT_COLOR,
{ "glitz-glx", CAIRO_SURFACE_TYPE_GLITZ, CAIRO_CONTENT_COLOR,
create_cairo_glitz_glx_surface, cairo_surface_write_to_png,
cleanup_cairo_glitz_glx },
#endif
#if CAIRO_CAN_TEST_GLITZ_AGL_SURFACE
{ "glitz-agl", CAIRO_CONTENT_COLOR_ALPHA,
{ "glitz-agl", CAIRO_SURFACE_TYPE_GLITZ, CAIRO_CONTENT_COLOR_ALPHA,
create_cairo_glitz_agl_surface, cairo_surface_write_to_png,
cleanup_cairo_glitz_agl },
{ "glitz-agl", CAIRO_CONTENT_COLOR,
{ "glitz-agl", CAIRO_SURFACE_TYPE_GLITZ, CAIRO_CONTENT_COLOR,
create_cairo_glitz_agl_surface, cairo_surface_write_to_png,
cleanup_cairo_glitz_agl },
#endif
#if CAIRO_CAN_TEST_GLITZ_WGL_SURFACE
{ "glitz-wgl", CAIRO_CONTENT_COLOR_ALPHA,
{ "glitz-wgl", CAIRO_SURFACE_TYPE_GLITZ, CAIRO_CONTENT_COLOR_ALPHA,
create_cairo_glitz_wgl_surface, cairo_surface_write_to_png,
cleanup_cairo_glitz_wgl },
{ "glitz-wgl", CAIRO_CONTENT_COLOR,
{ "glitz-wgl", CAIRO_SURFACE_TYPE_GLITZ, CAIRO_CONTENT_COLOR,
create_cairo_glitz_wgl_surface, cairo_surface_write_to_png,
cleanup_cairo_glitz_wgl },
#endif
#endif /* CAIRO_HAS_GLITZ_SURFACE */
#if 0 && CAIRO_HAS_QUARTZ_SURFACE
{ "quartz", CAIRO_CONTENT_COLOR,
{ "quartz", CAIRO_SURFACE_TYPE_QUARTZ, CAIRO_CONTENT_COLOR,
create_quartz_surface, cairo_surface_write_to_png,
cleanup_quartz },
#endif
#if CAIRO_HAS_WIN32_SURFACE
{ "win32", CAIRO_CONTENT_COLOR,
{ "win32", CAIRO_SURFACE_TYPE_WIN32, CAIRO_CONTENT_COLOR,
create_win32_surface, cairo_surface_write_to_png, cleanup_win32 },
#endif
#if CAIRO_HAS_XCB_SURFACE
{ "xcb", CAIRO_CONTENT_COLOR_ALPHA,
{ "xcb", CAIRO_SURFACE_TYPE_XCB, CAIRO_CONTENT_COLOR_ALPHA,
create_xcb_surface, cairo_surface_write_to_png, cleanup_xcb},
#endif
#if CAIRO_HAS_XLIB_SURFACE
{ "xlib", CAIRO_CONTENT_COLOR_ALPHA,
{ "xlib", CAIRO_SURFACE_TYPE_XLIB, CAIRO_CONTENT_COLOR_ALPHA,
create_xlib_surface, cairo_surface_write_to_png, cleanup_xlib},
{ "xlib", CAIRO_CONTENT_COLOR,
{ "xlib", CAIRO_SURFACE_TYPE_XLIB, CAIRO_CONTENT_COLOR,
create_xlib_surface, cairo_surface_write_to_png, cleanup_xlib},
#endif
#if CAIRO_HAS_PS_SURFACE
{ "ps", CAIRO_TEST_CONTENT_COLOR_ALPHA_FLATTENED,
{ "ps", CAIRO_SURFACE_TYPE_PS,
CAIRO_TEST_CONTENT_COLOR_ALPHA_FLATTENED,
create_ps_surface, ps_surface_write_to_png, cleanup_ps },
{ "ps", CAIRO_CONTENT_COLOR,
/* XXX: We expect type image here only due to a limitation in
* the current PS/meta-surface code. A PS surface is
* "naturally" COLOR_ALPHA, so the COLOR-only variant goes
* through create_similar in create_ps_surface which results
* in the similar surface being used as a source. We do not yet
* have source support for PS/meta-surfaces, so the
* create_similar path for all paginated surfaces currently
* returns an image surface.*/
{ "ps", CAIRO_SURFACE_TYPE_IMAGE, CAIRO_CONTENT_COLOR,
create_ps_surface, ps_surface_write_to_png, cleanup_ps },
#endif
#if CAIRO_HAS_PDF_SURFACE && CAIRO_CAN_TEST_PDF_SURFACE
{ "pdf", CAIRO_TEST_CONTENT_COLOR_ALPHA_FLATTENED,
{ "pdf", CAIRO_SURFACE_TYPE_PDF,
CAIRO_TEST_CONTENT_COLOR_ALPHA_FLATTENED,
create_pdf_surface, pdf_surface_write_to_png, cleanup_pdf },
{ "pdf", CAIRO_CONTENT_COLOR,
/* XXX: We expect type image here only due to a limitation in
* the current PDF/meta-surface code. A PDF surface is
* "naturally" COLOR_ALPHA, so the COLOR-only variant goes
* through create_similar in create_pdf_surface which results
* in the similar surface being used as a source. We do not yet
* have source support for PDF/meta-surfaces, so the
* create_similar path for all paginated surfaces currently
* returns an image surface.*/
{ "pdf", CAIRO_SURFACE_TYPE_IMAGE, CAIRO_CONTENT_COLOR,
create_pdf_surface, pdf_surface_write_to_png, cleanup_pdf },
#endif
#if CAIRO_HAS_SVG_SURFACE && CAIRO_CAN_TEST_SVG_SURFACE
{ "svg", CAIRO_CONTENT_COLOR_ALPHA,
{ "svg", CAIRO_SURFACE_TYPE_SVG, CAIRO_CONTENT_COLOR_ALPHA,
create_svg_surface, svg_surface_write_to_png, cleanup_svg },
#endif
#if CAIRO_HAS_BEOS_SURFACE
{ "beos", CAIRO_CONTENT_COLOR,
{ "beos", CAIRO_SURFACE_TYPE_BEOS, CAIRO_CONTENT_COLOR,
create_beos_surface, cairo_surface_write_to_png, cleanup_beos},
{ "beos_bitmap", CAIRO_CONTENT_COLOR,
{ "beos_bitmap", CAIRO_SURFACE_TYPE_BEOS, CAIRO_CONTENT_COLOR,
create_beos_bitmap_surface, cairo_surface_write_to_png, cleanup_beos_bitmap},
{ "beos_bitmap", CAIRO_CONTENT_COLOR_ALPHA,
{ "beos_bitmap", CAIRO_SURFACE_TYPE_BEOS, CAIRO_CONTENT_COLOR_ALPHA,
create_beos_bitmap_surface, cairo_surface_write_to_png, cleanup_beos_bitmap},
#endif
#if CAIRO_HAS_DIRECTFB_SURFACE
{ "directfb", CAIRO_CONTENT_COLOR,
{ "directfb", CAIRO_SURFACE_TYPE_DIRECTFB, CAIRO_CONTENT_COLOR,
create_directfb_surface, cairo_surface_write_to_png, cleanup_directfb},
{ "directfb_bitmap", CAIRO_CONTENT_COLOR_ALPHA,
{ "directfb_bitmap", CAIRO_SURFACE_TYPE_DIRECTFB, CAIRO_CONTENT_COLOR_ALPHA,
create_directfb_bitmap_surface, cairo_surface_write_to_png,cleanup_directfb},
#endif
};

64
test/font-face-get-type.c Normal file
View file

@ -0,0 +1,64 @@
/*
* Copyright © 2006 Red Hat, Inc.
*
* Permission to use, copy, modify, distribute, and sell this software
* and its documentation for any purpose is hereby granted without
* fee, provided that the above copyright notice appear in all copies
* and that both that copyright notice and this permission notice
* appear in supporting documentation, and that the name of
* Red Hat, Inc. not be used in advertising or publicity pertaining to
* distribution of the software without specific, written prior
* permission. Red Hat, Inc. makes no representations about the
* suitability of this software for any purpose. It is provided "as
* is" without express or implied warranty.
*
* RED HAT, INC. DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS
* SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND
* FITNESS, IN NO EVENT SHALL RED HAT, INC. BE LIABLE FOR ANY SPECIAL,
* INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER
* RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
* OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR
* IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*
* Author: Carl D. Worth <cworth@cworth.org>
*/
#include "cairo-test.h"
int
main (void)
{
cairo_surface_t *surface;
cairo_t *cr;
cairo_font_face_t *font_face;
cairo_test_init ("font-face-get-type");
cairo_test_log ("Creating cairo context and obtaining a font face\n");
surface = cairo_image_surface_create (CAIRO_FORMAT_ARGB32, 1, 1);
cr = cairo_create (surface);
cairo_select_font_face (cr, "Bitstream Vera Sans",
CAIRO_FONT_SLANT_NORMAL,
CAIRO_FONT_WEIGHT_NORMAL);
font_face = cairo_get_font_face (cr);
cairo_test_log ("Testing return value of cairo_font_face_get_type\n");
if (cairo_font_face_get_type (font_face) != CAIRO_FONT_TYPE_TOY) {
cairo_test_log ("Unexpected value %d from cairo_font_face_get_type (expected %d)\n",
cairo_font_face_get_type (font_face), CAIRO_FONT_TYPE_TOY);
return CAIRO_TEST_FAILURE;
}
cairo_destroy (cr);
cairo_surface_destroy (surface);
return CAIRO_TEST_SUCCESS;
}

View file

@ -64,6 +64,13 @@ draw (cairo_t *cr, int width, int height)
font_face = cairo_ft_font_face_create_for_pattern (resolved);
if (cairo_font_face_get_type (font_face) != CAIRO_FONT_TYPE_FT) {
cairo_test_log ("Unexpected value from cairo_font_face_get_type: %d (expected %d)\n",
cairo_font_face_get_type (font_face), CAIRO_FONT_TYPE_FT);
cairo_font_face_destroy (font_face);
return CAIRO_TEST_FAILURE;
}
cairo_matrix_init_identity (&font_matrix);
cairo_get_matrix (cr, &ctm);
@ -82,6 +89,13 @@ draw (cairo_t *cr, int width, int height)
FcPatternDestroy (pattern);
FcPatternDestroy (resolved);
if (cairo_scaled_font_get_type (scaled_font) != CAIRO_FONT_TYPE_FT) {
cairo_test_log ("Unexpected value from cairo_scaled_font_get_type: %d (expected %d)\n",
cairo_scaled_font_get_type (scaled_font), CAIRO_FONT_TYPE_FT);
cairo_scaled_font_destroy (scaled_font);
return CAIRO_TEST_FAILURE;
}
if (!ft_face) {
cairo_test_log ("Failed to get an ft_face with cairo_ft_scaled_font_lock_face\n");
cairo_scaled_font_destroy (scaled_font);

74
test/pattern-get-type.c Normal file
View file

@ -0,0 +1,74 @@
/*
* Copyright © 2006 Red Hat, Inc.
*
* Permission to use, copy, modify, distribute, and sell this software
* and its documentation for any purpose is hereby granted without
* fee, provided that the above copyright notice appear in all copies
* and that both that copyright notice and this permission notice
* appear in supporting documentation, and that the name of
* Red Hat, Inc. not be used in advertising or publicity pertaining to
* distribution of the software without specific, written prior
* permission. Red Hat, Inc. makes no representations about the
* suitability of this software for any purpose. It is provided "as
* is" without express or implied warranty.
*
* RED HAT, INC. DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS
* SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND
* FITNESS, IN NO EVENT SHALL RED HAT, INC. BE LIABLE FOR ANY SPECIAL,
* INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER
* RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
* OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR
* IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*
* Author: Carl D. Worth <cworth@cworth.org>
*/
#include "cairo-test.h"
int
main (void)
{
cairo_surface_t *surface;
cairo_pattern_t *solid_rgb, *solid_rgba, *surface_pattern, *linear, *radial;
cairo_test_init ("pattern-get-type");
cairo_test_log ("Creating patterns of all types\n");
solid_rgb = cairo_pattern_create_rgb (0.0, 0.1, 0.2);
solid_rgba = cairo_pattern_create_rgba (0.3, 0.4, 0.5, 0.6);
surface = cairo_image_surface_create (CAIRO_FORMAT_ARGB32,
1, 1);
surface_pattern = cairo_pattern_create_for_surface (surface);
linear = cairo_pattern_create_linear (0.0, 0.0, 10.0, 10.0);
radial = cairo_pattern_create_radial (10.0, 10.0, 0.1,
10.0, 10.0, 1.0);
cairo_test_log ("Verifying return values of cairo_pattern_get_type\n");
if (cairo_pattern_get_type (solid_rgb) != CAIRO_PATTERN_TYPE_SOLID)
return CAIRO_TEST_FAILURE;
if (cairo_pattern_get_type (solid_rgba) != CAIRO_PATTERN_TYPE_SOLID)
return CAIRO_TEST_FAILURE;
if (cairo_pattern_get_type (surface_pattern) != CAIRO_PATTERN_TYPE_SURFACE)
return CAIRO_TEST_FAILURE;
if (cairo_pattern_get_type (linear) != CAIRO_PATTERN_TYPE_LINEAR)
return CAIRO_TEST_FAILURE;
if (cairo_pattern_get_type (radial) != CAIRO_PATTERN_TYPE_RADIAL)
return CAIRO_TEST_FAILURE;
cairo_test_log ("Cleaning up\n");
cairo_pattern_destroy (solid_rgb);
cairo_pattern_destroy (solid_rgba);
cairo_pattern_destroy (surface_pattern);
cairo_surface_destroy (surface);
cairo_pattern_destroy (linear);
cairo_pattern_destroy (radial);
return CAIRO_TEST_SUCCESS;
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 118 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 115 B

127
test/show-glyphs-many.c Normal file
View file

@ -0,0 +1,127 @@
/*
* Copyright © 2006 Red Hat, Inc.
*
* Permission to use, copy, modify, distribute, and sell this software
* and its documentation for any purpose is hereby granted without
* fee, provided that the above copyright notice appear in all copies
* and that both that copyright notice and this permission notice
* appear in supporting documentation, and that the name of
* Red Hat, Inc. not be used in advertising or publicity pertaining to
* distribution of the software without specific, written prior
* permission. Red Hat, Inc. makes no representations about the
* suitability of this software for any purpose. It is provided "as
* is" without express or implied warranty.
*
* RED HAT, INC. DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS
* SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND
* FITNESS, IN NO EVENT SHALL RED HAT, INC. BE LIABLE FOR ANY SPECIAL,
* INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER
* RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
* OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR
* IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*
* Author: Carl D. Worth <cworth@cworth.org>
*/
#include "cairo-test.h"
#include <string.h>
/* Bug history
*
* 2006-01-07 Jon Hellan <hellan@acm.org>
*
* Jon opened the following bug report:
*
* _XError from XRenderCompositeText8
* https://bugs.freedesktop.org/show_bug.cgi?id=5528
*
* 2006-03-02 Carl Worth <cworth@cworth.org>
*
* I wrote this test case to demonstrate the bug.
*
* Approach:
*
* Draw 65535 glyphs white-on-white all on top of each other.
*
* Rationale:
*
* The number 65535 comes from the original bug report.
*
* I would use cairo_show_text with a long string of 'x's say,
* but then the surface would need to be enormous to contain
* them. A smaller surface could be used, but I fear that at some
* point the off-surface glyph drawing would be optimized away
* and not exercise the bug.
*
* So, to keep the surface size under control, I use
* cairo_show_glyphs which allows me to place the glyphs all on
* top of each other. But, since cairo doesn't provide any
* character-to-glyphs mapping, I can't get a reliable glyph
* index (for character 'x' for example). So I just "guess" a
* glyph index and use white-on-white drawing to ignore the
* result. (I don't care what's drawn---I just want to ensure
* that things don't crash.)
*
* Status: I replicated bug. The largest value of NUM_GLYPHS for
* which I saw success is 21842.
*/
#define TEXT_SIZE 12
#define NUM_GLYPHS 65535
/* This is the index into the font for what glyph we'll draw. Since we
* don't guarantee we'll get any particular font, we can't relibably
* get any particular glyph. But we don't care what we draw anyway,
* (see discussion of white-on-white drawing above). For what it's
* worth, this appears to be giving me 'M' with Bitstream Vera
* Sans Mono. */
#define GLYPH_INDEX 48
cairo_test_t test = {
"show-glyphs-many",
"Test that cairo_show_glyps works when handed 'many' glyphs",
9, 11
};
static cairo_test_status_t
draw (cairo_t *cr, int width, int height)
{
cairo_glyph_t glyphs[NUM_GLYPHS];
cairo_font_options_t *font_options;
int i;
/* Initialize our giant array of glyphs. */
for (i=0; i < NUM_GLYPHS; i++) {
glyphs[i].index = GLYPH_INDEX;
glyphs[i].x = 1.0;
glyphs[i].y = height - 1;
}
/* Paint white background. */
cairo_set_source_rgb (cr, 1.0, 1.0, 1.0); /* white */
cairo_paint (cr);
cairo_select_font_face (cr, "Bitstream Vera Sans Mono",
CAIRO_FONT_SLANT_NORMAL,
CAIRO_FONT_WEIGHT_NORMAL);
cairo_set_font_size (cr, TEXT_SIZE);
font_options = cairo_font_options_create ();
cairo_font_options_set_hint_style (font_options, CAIRO_HINT_STYLE_NONE);
cairo_font_options_set_antialias (font_options, CAIRO_ANTIALIAS_GRAY);
cairo_set_font_options (cr, font_options);
cairo_font_options_destroy (font_options);
cairo_show_glyphs (cr, glyphs, NUM_GLYPHS);
return CAIRO_TEST_SUCCESS;
}
int
main (void)
{
return cairo_test (&test, draw);
}