зеркало из https://github.com/mozilla/pjs.git
b=374462, update cairo to 1.4.2, r=stuart
This commit is contained in:
Родитель
7a656c0720
Коммит
724852819d
|
@ -7248,7 +7248,6 @@ if test "$MOZ_SVG" -o "$MOZ_ENABLE_CANVAS" -o "$MOZ_ENABLE_CAIRO_GFX" ; then
|
|||
fi
|
||||
if test "$MOZ_WIDGET_TOOLKIT" = "mac" -o "$MOZ_WIDGET_TOOLKIT" = "cocoa"; then
|
||||
QUARTZ_SURFACE_FEATURE="#define CAIRO_HAS_QUARTZ_SURFACE 1"
|
||||
NQUARTZ_SURFACE_FEATURE="#define CAIRO_HAS_NQUARTZ_SURFACE 1"
|
||||
ATSUI_FONT_FEATURE="#define CAIRO_HAS_ATSUI_FONT 1"
|
||||
fi
|
||||
if test "$MOZ_WIDGET_TOOLKIT" = "windows"; then
|
||||
|
|
|
@ -7,10 +7,20 @@ http://www.cairographics.org/.
|
|||
|
||||
VERSIONS:
|
||||
|
||||
cairo (1.3.12 tagged snapshot)
|
||||
cairo (1.4.2)
|
||||
glitz 0.5.2 (cvs - 2006-01-10)
|
||||
|
||||
***** NOTE FOR VISUAL C++ 6.0 *****
|
||||
|
||||
VC6 is not supported. Please upgrade to VC8.
|
||||
|
||||
==== Patches ====
|
||||
|
||||
All patches in the cairo tree are surrounded by "MOZILLA_CAIRO_NOT_DEFINED" (which should NOT be defined).
|
||||
|
||||
Some specific things:
|
||||
|
||||
max-font-size.patch: Clamp freetype font size to 1000 to avoid overflow issues
|
||||
|
||||
fbcompose-bandaid.patch: Disable "optimized" code in non-MMX case due to bugs
|
||||
|
||||
|
|
|
@ -129,11 +129,6 @@ endif
|
|||
ifneq (,$(filter mac cocoa,$(MOZ_WIDGET_TOOLKIT)))
|
||||
CSRCS += cairo-quartz-surface.c cairo-atsui-font.c
|
||||
EXPORTS += cairo-quartz.h cairo-atsui.h
|
||||
|
||||
ifdef MOZ_ENABLE_CAIRO_GFX
|
||||
CSRCS += cairo-nquartz-surface.c
|
||||
EXPORTS += cairo-nquartz.h
|
||||
endif
|
||||
endif
|
||||
|
||||
ifeq ($(MOZ_WIDGET_TOOLKIT),beos)
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
/* $Id: cairo-analysis-surface-private.h,v 1.4 2007/04/03 18:59:47 vladimir%pobox.com Exp $
|
||||
/* $Id: cairo-analysis-surface-private.h,v 1.5 2007/04/04 01:09:15 vladimir%pobox.com Exp $
|
||||
*
|
||||
* Copyright © 2005 Keith Packard
|
||||
*
|
||||
|
|
|
@ -82,6 +82,9 @@ struct _cairo_atsui_font {
|
|||
ATSUStyle style;
|
||||
ATSUStyle unscaled_style;
|
||||
ATSUFontID fontID;
|
||||
|
||||
Fixed size;
|
||||
CGAffineTransform font_matrix;
|
||||
};
|
||||
|
||||
struct _cairo_atsui_font_face {
|
||||
|
@ -146,47 +149,6 @@ cairo_atsui_font_face_create_for_atsu_font_id (ATSUFontID font_id)
|
|||
return &font_face->base;
|
||||
}
|
||||
|
||||
static CGContextRef
|
||||
CGBitmapContextCreateWithCairoImageSurface (const cairo_image_surface_t * surface)
|
||||
{
|
||||
CGContextRef contextRef;
|
||||
CGColorSpaceRef colorSpace;
|
||||
int bits_per_comp, alpha;
|
||||
|
||||
/* Create a CGBitmapContext for the dest surface for drawing into */
|
||||
if (surface->depth == 1) {
|
||||
colorSpace = CGColorSpaceCreateDeviceGray ();
|
||||
bits_per_comp = 1;
|
||||
alpha = kCGImageAlphaNone;
|
||||
} else if (surface->depth == 8) {
|
||||
colorSpace = CGColorSpaceCreateDeviceGray ();
|
||||
bits_per_comp = 8;
|
||||
alpha = kCGImageAlphaNone;
|
||||
} else if (surface->depth == 24) {
|
||||
colorSpace = CGColorSpaceCreateDeviceRGB ();
|
||||
bits_per_comp = 8;
|
||||
alpha = kCGImageAlphaNoneSkipFirst | CG_BITMAP_BYTE_ORDER_FLAG;
|
||||
} else if (surface->depth == 32) {
|
||||
colorSpace = CGColorSpaceCreateDeviceRGB ();
|
||||
bits_per_comp = 8;
|
||||
alpha = kCGImageAlphaPremultipliedFirst | CG_BITMAP_BYTE_ORDER_FLAG;
|
||||
} else {
|
||||
/* not reached */
|
||||
return NULL;
|
||||
}
|
||||
|
||||
contextRef = CGBitmapContextCreate (surface->data,
|
||||
surface->width,
|
||||
surface->height,
|
||||
bits_per_comp,
|
||||
surface->stride,
|
||||
colorSpace,
|
||||
alpha);
|
||||
CGColorSpaceRelease (colorSpace);
|
||||
|
||||
return contextRef;
|
||||
}
|
||||
|
||||
static CGAffineTransform
|
||||
CGAffineTransformMakeWithCairoFontScale(const cairo_matrix_t *scale)
|
||||
{
|
||||
|
@ -195,29 +157,19 @@ CGAffineTransformMakeWithCairoFontScale(const cairo_matrix_t *scale)
|
|||
0, 0);
|
||||
}
|
||||
|
||||
static CGAffineTransform
|
||||
CGAffineTransformMakeWithCairoScaleFactors(const cairo_matrix_t *scale)
|
||||
{
|
||||
double xscale = 1.0;
|
||||
double yscale = 1.0;
|
||||
_cairo_matrix_compute_scale_factors(scale, &xscale, &yscale, 1);
|
||||
return CGAffineTransformMake(xscale, 0,
|
||||
0, yscale,
|
||||
0, 0);
|
||||
}
|
||||
|
||||
static ATSUStyle
|
||||
CreateSizedCopyOfStyle(ATSUStyle inStyle, const cairo_matrix_t *scale)
|
||||
CreateSizedCopyOfStyle(ATSUStyle inStyle,
|
||||
const Fixed *theSize,
|
||||
const CGAffineTransform *theTransform)
|
||||
{
|
||||
ATSUStyle style;
|
||||
OSStatus err;
|
||||
|
||||
/* Set the style's size */
|
||||
Fixed theSize = FloatToFixed(1.0);
|
||||
CGAffineTransform theTransform = CGAffineTransformMakeWithCairoScaleFactors(scale);
|
||||
const ATSUAttributeTag theFontStyleTags[] = { kATSUSizeTag, kATSUFontMatrixTag };
|
||||
const ByteCount theFontStyleSizes[] = { sizeof(Fixed), sizeof(CGAffineTransform) };
|
||||
ATSUAttributeValuePtr theFontStyleValues[] = { &theSize, &theTransform };
|
||||
const ATSUAttributeTag theFontStyleTags[] = { kATSUSizeTag,
|
||||
kATSUFontMatrixTag };
|
||||
const ByteCount theFontStyleSizes[] = { sizeof(Fixed),
|
||||
sizeof(CGAffineTransform) };
|
||||
ATSUAttributeValuePtr theFontStyleValues[] = { (Fixed *)theSize,
|
||||
(CGAffineTransform *)theTransform };
|
||||
|
||||
err = ATSUCreateAndCopyStyle(inStyle, &style);
|
||||
|
||||
|
@ -273,6 +225,8 @@ _cairo_atsui_font_create_scaled (cairo_font_face_t *font_face,
|
|||
cairo_atsui_font_t *font = NULL;
|
||||
OSStatus err;
|
||||
cairo_status_t status;
|
||||
double xscale = 1.0;
|
||||
double yscale = 1.0;
|
||||
|
||||
font = malloc(sizeof(cairo_atsui_font_t));
|
||||
if (font == NULL)
|
||||
|
@ -281,7 +235,14 @@ _cairo_atsui_font_create_scaled (cairo_font_face_t *font_face,
|
|||
_cairo_scaled_font_init(&font->base, font_face, font_matrix, ctm, options,
|
||||
&cairo_atsui_scaled_font_backend);
|
||||
|
||||
font->style = CreateSizedCopyOfStyle(style, &font->base.scale);
|
||||
_cairo_matrix_compute_scale_factors (&font->base.scale,
|
||||
&xscale, &yscale, 1);
|
||||
font->font_matrix = CGAffineTransformMake (1., 0.,
|
||||
0., yscale/xscale,
|
||||
0., 0.);
|
||||
font->size = FloatToFixed (xscale);
|
||||
|
||||
font->style = CreateSizedCopyOfStyle (style, &font->size, &font->font_matrix);
|
||||
|
||||
{
|
||||
Fixed theSize = FloatToFixed(1.0);
|
||||
|
@ -480,11 +441,19 @@ OSStatus _close_path_for_metrics(void *callback_data)
|
|||
return noErr;
|
||||
}
|
||||
|
||||
static GlyphID
|
||||
_cairo_atsui_scaled_glyph_index (cairo_scaled_glyph_t *scaled_glyph) {
|
||||
unsigned long index = _cairo_scaled_glyph_index (scaled_glyph);
|
||||
if (index > 0xffff)
|
||||
return kATSDeletedGlyphcode;
|
||||
return index;
|
||||
}
|
||||
|
||||
static cairo_status_t
|
||||
_cairo_atsui_font_init_glyph_metrics (cairo_atsui_font_t *scaled_font,
|
||||
cairo_scaled_glyph_t *scaled_glyph)
|
||||
{
|
||||
cairo_text_extents_t extents;
|
||||
cairo_text_extents_t extents = {0, 0, 0, 0, 0, 0};
|
||||
OSStatus err, callback_err;
|
||||
ATSGlyphScreenMetrics metricsH;
|
||||
static ATSCubicMoveToUPP moveProc = NULL;
|
||||
|
@ -492,10 +461,17 @@ _cairo_atsui_font_init_glyph_metrics (cairo_atsui_font_t *scaled_font,
|
|||
static ATSCubicCurveToUPP curveProc = NULL;
|
||||
static ATSCubicClosePathUPP closePathProc = NULL;
|
||||
CGMutablePathRef path;
|
||||
GlyphID theGlyph = _cairo_scaled_glyph_index (scaled_glyph);
|
||||
GlyphID theGlyph = _cairo_atsui_scaled_glyph_index (scaled_glyph);
|
||||
double xscale, yscale;
|
||||
CGRect rect;
|
||||
|
||||
if (theGlyph == kATSDeletedGlyphcode) {
|
||||
_cairo_scaled_glyph_set_metrics (scaled_glyph,
|
||||
&scaled_font->base,
|
||||
&extents);
|
||||
return CAIRO_STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
/* We calculate the advance from the screen metrics. We
|
||||
* could probably take this from the glyph path.
|
||||
*/
|
||||
|
@ -503,7 +479,7 @@ _cairo_atsui_font_init_glyph_metrics (cairo_atsui_font_t *scaled_font,
|
|||
1, &theGlyph, 0, false,
|
||||
false, &metricsH);
|
||||
if (err != noErr)
|
||||
return CAIRO_INT_STATUS_UNSUPPORTED;
|
||||
return CAIRO_STATUS_NO_MEMORY;
|
||||
|
||||
/* Scale down to font units.*/
|
||||
_cairo_matrix_compute_scale_factors (&scaled_font->base.scale,
|
||||
|
@ -532,11 +508,8 @@ _cairo_atsui_font_init_glyph_metrics (cairo_atsui_font_t *scaled_font,
|
|||
(void *)path, &callback_err);
|
||||
|
||||
if (err != noErr) {
|
||||
/* This could potentially happen for bitmap fonts, where
|
||||
* no paths are available.
|
||||
*/
|
||||
CGPathRelease (path);
|
||||
return CAIRO_INT_STATUS_UNSUPPORTED;
|
||||
return CAIRO_STATUS_NO_MEMORY;
|
||||
}
|
||||
|
||||
rect = CGPathGetBoundingBox (path);
|
||||
|
@ -636,6 +609,7 @@ _cairo_atsui_scaled_font_init_glyph_path (cairo_atsui_font_t *scaled_font,
|
|||
static ATSCubicLineToUPP lineProc = NULL;
|
||||
static ATSCubicCurveToUPP curveProc = NULL;
|
||||
static ATSCubicClosePathUPP closePathProc = NULL;
|
||||
GlyphID theGlyph = _cairo_atsui_scaled_glyph_index (scaled_glyph);
|
||||
OSStatus err;
|
||||
cairo_atsui_scaled_path_t scaled_path;
|
||||
cairo_matrix_t *font_to_device = &scaled_font->base.scale;
|
||||
|
@ -643,6 +617,17 @@ _cairo_atsui_scaled_font_init_glyph_path (cairo_atsui_font_t *scaled_font,
|
|||
double xscale;
|
||||
double yscale;
|
||||
|
||||
scaled_path.path = _cairo_path_fixed_create ();
|
||||
if (!scaled_path.path)
|
||||
return CAIRO_STATUS_NO_MEMORY;
|
||||
|
||||
if (theGlyph == kATSDeletedGlyphcode) {
|
||||
_cairo_scaled_glyph_set_path (scaled_glyph, &scaled_font->base,
|
||||
scaled_path.path);
|
||||
|
||||
return CAIRO_STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
/* extract the rotation/shear component of the scale matrix. */
|
||||
_cairo_matrix_compute_scale_factors (font_to_device, &xscale, &yscale, 1);
|
||||
cairo_matrix_init (&unscaled_font_to_device,
|
||||
|
@ -653,9 +638,6 @@ _cairo_atsui_scaled_font_init_glyph_path (cairo_atsui_font_t *scaled_font,
|
|||
cairo_matrix_scale (&unscaled_font_to_device, 1.0/xscale, 1.0/yscale);
|
||||
|
||||
scaled_path.scale = &unscaled_font_to_device;
|
||||
scaled_path.path = _cairo_path_fixed_create ();
|
||||
if (!scaled_path.path)
|
||||
return CAIRO_STATUS_NO_MEMORY;
|
||||
|
||||
if (moveProc == NULL) {
|
||||
moveProc = NewATSCubicMoveToUPP(_move_to);
|
||||
|
@ -665,7 +647,7 @@ _cairo_atsui_scaled_font_init_glyph_path (cairo_atsui_font_t *scaled_font,
|
|||
}
|
||||
|
||||
err = ATSUGlyphGetCubicPaths(scaled_font->style,
|
||||
_cairo_scaled_glyph_index (scaled_glyph),
|
||||
theGlyph,
|
||||
moveProc,
|
||||
lineProc,
|
||||
curveProc,
|
||||
|
@ -691,7 +673,7 @@ _cairo_atsui_scaled_font_init_glyph_surface (cairo_atsui_font_t *scaled_font,
|
|||
cairo_scaled_font_t base = scaled_font->base;
|
||||
cairo_font_extents_t extents = base.extents;
|
||||
|
||||
GlyphID theGlyph = _cairo_scaled_glyph_index (scaled_glyph);
|
||||
GlyphID theGlyph = _cairo_atsui_scaled_glyph_index (scaled_glyph);
|
||||
ATSGlyphScreenMetrics metricsH;
|
||||
double left, bottom, width, height;
|
||||
double xscale, yscale;
|
||||
|
@ -699,6 +681,16 @@ _cairo_atsui_scaled_font_init_glyph_surface (cairo_atsui_font_t *scaled_font,
|
|||
CGAffineTransform transform;
|
||||
|
||||
|
||||
if (theGlyph == kATSDeletedGlyphcode) {
|
||||
surface = (cairo_image_surface_t *)cairo_image_surface_create (CAIRO_FORMAT_A8, 2, 2);
|
||||
if (!surface)
|
||||
return CAIRO_STATUS_NO_MEMORY;
|
||||
_cairo_scaled_glyph_set_surface (scaled_glyph,
|
||||
&base,
|
||||
surface);
|
||||
return CAIRO_STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
/* Compute a box to contain the glyph mask. The vertical
|
||||
* sizes come from the font extents; extra pixels are
|
||||
* added to account for fractional sizes.
|
||||
|
@ -754,10 +746,23 @@ _cairo_atsui_scaled_font_init_glyph_surface (cairo_atsui_font_t *scaled_font,
|
|||
if (!surface)
|
||||
return CAIRO_STATUS_NO_MEMORY;
|
||||
|
||||
drawingContext = CGBitmapContextCreateWithCairoImageSurface (surface);
|
||||
/* Create a CGBitmapContext for the dest surface for drawing into */
|
||||
{
|
||||
CGColorSpaceRef colorSpace = CGColorSpaceCreateDeviceGray ();
|
||||
|
||||
drawingContext = CGBitmapContextCreate (surface->data,
|
||||
surface->width,
|
||||
surface->height,
|
||||
8,
|
||||
surface->stride,
|
||||
colorSpace,
|
||||
kCGImageAlphaNone);
|
||||
CGColorSpaceRelease (colorSpace);
|
||||
}
|
||||
|
||||
if (!drawingContext) {
|
||||
cairo_surface_destroy ((cairo_surface_t *)surface);
|
||||
return CAIRO_INT_STATUS_UNSUPPORTED;
|
||||
return CAIRO_STATUS_NO_MEMORY;
|
||||
}
|
||||
|
||||
atsFont = FMGetATSFontRefFromFont (scaled_font->fontID);
|
||||
|
@ -839,6 +844,9 @@ _cairo_atsui_font_text_to_glyphs (void *abstract_font,
|
|||
cairo_atsui_font_t *font = abstract_font;
|
||||
ItemCount glyphCount;
|
||||
int i;
|
||||
CGPoint point;
|
||||
double xscale, yscale;
|
||||
CGAffineTransform device_to_user_scale;
|
||||
|
||||
status = _cairo_utf8_to_utf16 ((unsigned char *)utf8, -1, &utf16, &n16);
|
||||
if (status)
|
||||
|
@ -865,9 +873,18 @@ _cairo_atsui_font_text_to_glyphs (void *abstract_font,
|
|||
return CAIRO_STATUS_NO_MEMORY;
|
||||
}
|
||||
|
||||
_cairo_matrix_compute_scale_factors (&font->base.ctm, &xscale, &yscale, 1);
|
||||
device_to_user_scale =
|
||||
CGAffineTransformInvert (CGAffineTransformMake (xscale, 0,
|
||||
0, yscale,
|
||||
0, 0));
|
||||
for (i = 0; i < *num_glyphs; i++) {
|
||||
(*glyphs)[i].index = layoutRecords[i].glyphID;
|
||||
(*glyphs)[i].x = x + FixedToFloat(layoutRecords[i].realPos);
|
||||
/* ATSLayoutRecord.realPos is in device units, convert to user units */
|
||||
point = CGPointMake (FixedToFloat (layoutRecords[i].realPos), 0);
|
||||
point = CGPointApplyAffineTransform (point, device_to_user_scale);
|
||||
|
||||
(*glyphs)[i].x = x + point.x;
|
||||
(*glyphs)[i].y = y;
|
||||
}
|
||||
|
||||
|
@ -881,158 +898,6 @@ _cairo_atsui_font_text_to_glyphs (void *abstract_font,
|
|||
return CAIRO_STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
static cairo_int_status_t
|
||||
_cairo_atsui_font_old_show_glyphs (void *abstract_font,
|
||||
cairo_operator_t op,
|
||||
cairo_pattern_t *pattern,
|
||||
cairo_surface_t *generic_surface,
|
||||
int source_x,
|
||||
int source_y,
|
||||
int dest_x,
|
||||
int dest_y,
|
||||
unsigned int width,
|
||||
unsigned int height,
|
||||
cairo_glyph_t *glyphs,
|
||||
int num_glyphs)
|
||||
{
|
||||
cairo_atsui_font_t *font = abstract_font;
|
||||
CGContextRef drawingContext;
|
||||
cairo_image_surface_t *destImageSurface;
|
||||
int i;
|
||||
void *extra = NULL;
|
||||
cairo_bool_t can_draw_directly;
|
||||
cairo_rectangle_int16_t rect;
|
||||
cairo_quartz_surface_t *surface = (cairo_quartz_surface_t *)generic_surface;
|
||||
|
||||
ATSFontRef atsFont;
|
||||
CGFontRef cgFont;
|
||||
CGAffineTransform textTransform;
|
||||
|
||||
if (!_cairo_surface_is_quartz (generic_surface))
|
||||
return CAIRO_INT_STATUS_UNSUPPORTED;
|
||||
|
||||
/* Check if we can draw directly to the destination surface */
|
||||
can_draw_directly = _cairo_pattern_is_opaque_solid (pattern) &&
|
||||
op == CAIRO_OPERATOR_OVER;
|
||||
|
||||
if (!can_draw_directly) {
|
||||
rect.x = dest_x;
|
||||
rect.y = dest_y;
|
||||
rect.width = width;
|
||||
rect.height = height;
|
||||
|
||||
_cairo_surface_acquire_dest_image(generic_surface,
|
||||
&rect,
|
||||
&destImageSurface,
|
||||
&rect,
|
||||
&extra);
|
||||
|
||||
drawingContext = CGBitmapContextCreateWithCairoImageSurface (destImageSurface);
|
||||
if (!drawingContext)
|
||||
return CAIRO_INT_STATUS_UNSUPPORTED;
|
||||
|
||||
CGContextTranslateCTM(drawingContext, 0, destImageSurface->height);
|
||||
CGContextScaleCTM(drawingContext, 1.0f, -1.0f);
|
||||
} else {
|
||||
drawingContext = ((cairo_quartz_surface_t *)generic_surface)->context;
|
||||
CGContextSaveGState (drawingContext);
|
||||
}
|
||||
|
||||
atsFont = FMGetATSFontRefFromFont(font->fontID);
|
||||
cgFont = CGFontCreateWithPlatformFont(&atsFont);
|
||||
|
||||
CGContextSetFont(drawingContext, cgFont);
|
||||
|
||||
if (font->base.options.antialias == CAIRO_ANTIALIAS_NONE) {
|
||||
CGContextSetShouldAntialias (drawingContext, false);
|
||||
}
|
||||
|
||||
textTransform = CGAffineTransformMakeWithCairoFontScale(&font->base.scale);
|
||||
textTransform = CGAffineTransformScale(textTransform, 1.0f, -1.0f);
|
||||
|
||||
CGContextSetFontSize(drawingContext, 1.0);
|
||||
CGContextSetTextMatrix(drawingContext, textTransform);
|
||||
|
||||
if (pattern->type == CAIRO_PATTERN_TYPE_SOLID &&
|
||||
_cairo_pattern_is_opaque_solid(pattern))
|
||||
{
|
||||
cairo_solid_pattern_t *solid = (cairo_solid_pattern_t *)pattern;
|
||||
CGContextSetRGBFillColor(drawingContext,
|
||||
solid->color.red,
|
||||
solid->color.green,
|
||||
solid->color.blue, 1.0f);
|
||||
} else {
|
||||
CGContextSetRGBFillColor(drawingContext, 0.0f, 0.0f, 0.0f, 0.0f);
|
||||
}
|
||||
|
||||
if (surface->clip_region) {
|
||||
pixman_box16_t *boxes = pixman_region_rects (surface->clip_region);
|
||||
int num_boxes = pixman_region_num_rects (surface->clip_region);
|
||||
CGRect stack_rects[10];
|
||||
CGRect *rects;
|
||||
int i;
|
||||
|
||||
/* XXX: Return-value of malloc needs to be checked for
|
||||
* NULL. Can someone fix this who is more familiar with
|
||||
* the cleanup needed in this function?
|
||||
*/
|
||||
if (num_boxes > 10)
|
||||
rects = malloc (sizeof (CGRect) * num_boxes);
|
||||
else
|
||||
rects = stack_rects;
|
||||
|
||||
for (i = 0; i < num_boxes; i++) {
|
||||
rects[i].origin.x = boxes[i].x1;
|
||||
rects[i].origin.y = boxes[i].y1;
|
||||
rects[i].size.width = boxes[i].x2 - boxes[i].x1;
|
||||
rects[i].size.height = boxes[i].y2 - boxes[i].y1;
|
||||
}
|
||||
|
||||
CGContextClipToRects (drawingContext, rects, num_boxes);
|
||||
|
||||
if (rects != stack_rects)
|
||||
free(rects);
|
||||
}
|
||||
|
||||
/* 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++) {
|
||||
CGGlyph theGlyph = glyphs[i].index;
|
||||
|
||||
/* round glyph locations to the nearest pixel */
|
||||
/* XXX: FRAGILE: We're ignoring device_transform scaling here. A bug? */
|
||||
CGContextShowGlyphsAtPoint(drawingContext,
|
||||
_cairo_lround (glyphs[i].x),
|
||||
_cairo_lround (glyphs[i].y),
|
||||
&theGlyph, 1);
|
||||
}
|
||||
|
||||
if (!can_draw_directly) {
|
||||
CGContextRelease(drawingContext);
|
||||
|
||||
_cairo_surface_release_dest_image(generic_surface,
|
||||
&rect,
|
||||
destImageSurface,
|
||||
&rect,
|
||||
extra);
|
||||
} else {
|
||||
CGContextRestoreGState (drawingContext);
|
||||
}
|
||||
|
||||
return CAIRO_STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
cairo_bool_t
|
||||
_cairo_scaled_font_is_atsui (cairo_scaled_font_t *sfont)
|
||||
{
|
||||
return (sfont->backend == &cairo_atsui_scaled_font_backend);
|
||||
}
|
||||
|
||||
ATSUStyle
|
||||
_cairo_atsui_scaled_font_get_atsu_style (cairo_scaled_font_t *sfont)
|
||||
{
|
||||
|
@ -1049,6 +914,30 @@ _cairo_atsui_scaled_font_get_atsu_font_id (cairo_scaled_font_t *sfont)
|
|||
return afont->fontID;
|
||||
}
|
||||
|
||||
static cairo_int_status_t
|
||||
_cairo_atsui_load_truetype_table (void *abstract_font,
|
||||
unsigned long tag,
|
||||
long offset,
|
||||
unsigned char *buffer,
|
||||
unsigned long *length)
|
||||
{
|
||||
cairo_atsui_font_t *scaled_font = abstract_font;
|
||||
ATSFontRef atsFont;
|
||||
OSStatus err;
|
||||
|
||||
atsFont = FMGetATSFontRefFromFont (scaled_font->fontID);
|
||||
err = ATSFontGetTable ( atsFont, tag,
|
||||
(ByteOffset) offset,
|
||||
(ByteCount) *length,
|
||||
buffer,
|
||||
length);
|
||||
if (err != noErr) {
|
||||
return CAIRO_INT_STATUS_UNSUPPORTED;
|
||||
}
|
||||
|
||||
return CAIRO_STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
const cairo_scaled_font_backend_t cairo_atsui_scaled_font_backend = {
|
||||
CAIRO_FONT_TYPE_ATSUI,
|
||||
_cairo_atsui_font_create_toy,
|
||||
|
@ -1056,6 +945,8 @@ const cairo_scaled_font_backend_t cairo_atsui_scaled_font_backend = {
|
|||
_cairo_atsui_font_scaled_glyph_init,
|
||||
_cairo_atsui_font_text_to_glyphs,
|
||||
NULL, /* ucs4_to_index */
|
||||
_cairo_atsui_font_old_show_glyphs,
|
||||
NULL, /* show_glyphs */
|
||||
_cairo_atsui_load_truetype_table,
|
||||
NULL, /* map_glyphs_to_unicode */
|
||||
};
|
||||
|
||||
|
|
|
@ -121,7 +121,7 @@ typedef struct _cairo_bo_event {
|
|||
#define SKIP_ELT_TO_EVENT(elt) SKIP_LIST_ELT_TO_DATA (cairo_bo_event_t, (elt))
|
||||
|
||||
typedef struct _cairo_bo_event_queue {
|
||||
skip_list_t intersection_queue;
|
||||
cairo_skip_list_t intersection_queue;
|
||||
|
||||
cairo_bo_event_t *startstop_events;
|
||||
cairo_bo_event_t **sorted_startstop_event_ptrs;
|
||||
|
@ -129,9 +129,9 @@ typedef struct _cairo_bo_event_queue {
|
|||
unsigned num_startstop_events;
|
||||
} cairo_bo_event_queue_t;
|
||||
|
||||
/* This structure extends skip_list_t, which must come first. */
|
||||
/* This structure extends cairo_skip_list_t, which must come first. */
|
||||
typedef struct _cairo_bo_sweep_line {
|
||||
skip_list_t active_edges;
|
||||
cairo_skip_list_t active_edges;
|
||||
cairo_bo_edge_t *head;
|
||||
cairo_bo_edge_t *tail;
|
||||
int32_t current_y;
|
||||
|
@ -697,7 +697,7 @@ _cairo_bo_event_queue_insert (cairo_bo_event_queue_t *queue,
|
|||
cairo_bo_event_t *event)
|
||||
{
|
||||
/* Don't insert if there's already an equivalent intersection event in the queue. */
|
||||
skip_list_insert (&queue->intersection_queue, event,
|
||||
_cairo_skip_list_insert (&queue->intersection_queue, event,
|
||||
event->type == CAIRO_BO_EVENT_TYPE_INTERSECTION);
|
||||
}
|
||||
|
||||
|
@ -706,7 +706,7 @@ _cairo_bo_event_queue_delete (cairo_bo_event_queue_t *queue,
|
|||
cairo_bo_event_t *event)
|
||||
{
|
||||
if (CAIRO_BO_EVENT_TYPE_INTERSECTION == event->type)
|
||||
skip_list_delete_given ( &queue->intersection_queue, &event->elt );
|
||||
_cairo_skip_list_delete_given ( &queue->intersection_queue, &event->elt );
|
||||
}
|
||||
|
||||
static cairo_bo_event_t *
|
||||
|
@ -740,7 +740,7 @@ _cairo_bo_event_queue_init (cairo_bo_event_queue_t *event_queue,
|
|||
|
||||
memset (event_queue, 0, sizeof(*event_queue));
|
||||
|
||||
skip_list_init (&event_queue->intersection_queue,
|
||||
_cairo_skip_list_init (&event_queue->intersection_queue,
|
||||
cairo_bo_event_compare_abstract,
|
||||
sizeof (cairo_bo_event_t));
|
||||
if (0 == num_edges)
|
||||
|
@ -789,7 +789,7 @@ _cairo_bo_event_queue_init (cairo_bo_event_queue_t *event_queue,
|
|||
static void
|
||||
_cairo_bo_event_queue_fini (cairo_bo_event_queue_t *event_queue)
|
||||
{
|
||||
skip_list_fini (&event_queue->intersection_queue);
|
||||
_cairo_skip_list_fini (&event_queue->intersection_queue);
|
||||
if (event_queue->startstop_events)
|
||||
free (event_queue->startstop_events);
|
||||
if (event_queue->sorted_startstop_event_ptrs)
|
||||
|
@ -834,7 +834,7 @@ _cairo_bo_event_queue_insert_if_intersect_below_current_y (cairo_bo_event_queue_
|
|||
static void
|
||||
_cairo_bo_sweep_line_init (cairo_bo_sweep_line_t *sweep_line)
|
||||
{
|
||||
skip_list_init (&sweep_line->active_edges,
|
||||
_cairo_skip_list_init (&sweep_line->active_edges,
|
||||
_sweep_line_elt_compare,
|
||||
sizeof (sweep_line_elt_t));
|
||||
sweep_line->head = NULL;
|
||||
|
@ -845,7 +845,7 @@ _cairo_bo_sweep_line_init (cairo_bo_sweep_line_t *sweep_line)
|
|||
static void
|
||||
_cairo_bo_sweep_line_fini (cairo_bo_sweep_line_t *sweep_line)
|
||||
{
|
||||
skip_list_fini (&sweep_line->active_edges);
|
||||
_cairo_skip_list_fini (&sweep_line->active_edges);
|
||||
}
|
||||
|
||||
static void
|
||||
|
@ -856,7 +856,7 @@ _cairo_bo_sweep_line_insert (cairo_bo_sweep_line_t *sweep_line,
|
|||
sweep_line_elt_t *sweep_line_elt;
|
||||
cairo_bo_edge_t **prev_of_next, **next_of_prev;
|
||||
|
||||
sweep_line_elt = skip_list_insert (&sweep_line->active_edges, &edge,
|
||||
sweep_line_elt = _cairo_skip_list_insert (&sweep_line->active_edges, &edge,
|
||||
1 /* unique inserts*/);
|
||||
|
||||
next_elt = sweep_line_elt->elt.next[0];
|
||||
|
@ -884,7 +884,7 @@ _cairo_bo_sweep_line_delete (cairo_bo_sweep_line_t *sweep_line,
|
|||
{
|
||||
cairo_bo_edge_t **left_next, **right_prev;
|
||||
|
||||
skip_list_delete_given (&sweep_line->active_edges, &edge->sweep_line_elt->elt);
|
||||
_cairo_skip_list_delete_given (&sweep_line->active_edges, &edge->sweep_line_elt->elt);
|
||||
|
||||
left_next = &sweep_line->head;
|
||||
if (edge->prev)
|
||||
|
@ -975,7 +975,7 @@ _cairo_bo_event_queue_print (cairo_bo_event_queue_t *event_queue)
|
|||
{
|
||||
skip_elt_t *elt;
|
||||
/* XXX: fixme to print the start/stop array too. */
|
||||
skip_list_t *queue = &event_queue->intersection_queue;
|
||||
cairo_skip_list_t *queue = &event_queue->intersection_queue;
|
||||
cairo_bo_event_t *event;
|
||||
|
||||
printf ("Event queue:\n");
|
||||
|
@ -1767,7 +1767,7 @@ int
|
|||
main (void)
|
||||
{
|
||||
char random_name[] = "random-XX";
|
||||
static cairo_bo_edge_t random_edges[MAX_RANDOM], *edge;
|
||||
cairo_bo_edge_t random_edges[MAX_RANDOM], *edge;
|
||||
unsigned int i, num_random;
|
||||
test_t *test;
|
||||
|
||||
|
|
|
@ -31,6 +31,7 @@
|
|||
*
|
||||
* Contributor(s):
|
||||
* Adrian Johnson <ajohnson@redneon.com>
|
||||
* Eugeniy Meshcheryakov <eugen@debian.org>
|
||||
*/
|
||||
|
||||
#include "cairoint.h"
|
||||
|
@ -81,6 +82,13 @@ typedef struct _cff_dict_operator {
|
|||
int operand_offset;
|
||||
} cff_dict_operator_t;
|
||||
|
||||
typedef struct _cff_charset {
|
||||
cairo_bool_t is_builtin;
|
||||
const uint16_t *sids;
|
||||
const unsigned char *data;
|
||||
int length;
|
||||
} cff_charset_t;
|
||||
|
||||
typedef struct _cairo_cff_font {
|
||||
|
||||
cairo_scaled_font_subset_t *scaled_font_subset;
|
||||
|
@ -100,11 +108,14 @@ typedef struct _cairo_cff_font {
|
|||
cairo_array_t global_sub_index;
|
||||
cairo_array_t local_sub_index;
|
||||
int num_glyphs;
|
||||
cff_charset_t charset;
|
||||
int charset_offset;
|
||||
|
||||
/* Subsetted Font Data */
|
||||
char *subset_font_name;
|
||||
cairo_array_t charstrings_subset_index;
|
||||
cairo_array_t strings_subset_index;
|
||||
cairo_array_t charset_subset;
|
||||
cairo_array_t output;
|
||||
|
||||
/* Subset Metrics */
|
||||
|
@ -114,34 +125,6 @@ typedef struct _cairo_cff_font {
|
|||
|
||||
} cairo_cff_font_t;
|
||||
|
||||
#ifdef WORDS_BIGENDIAN
|
||||
|
||||
#define cpu_to_be16(v) (v)
|
||||
#define be16_to_cpu(v) (v)
|
||||
#define cpu_to_be32(v) (v)
|
||||
|
||||
#else
|
||||
|
||||
static inline uint16_t
|
||||
cpu_to_be16(uint16_t v)
|
||||
{
|
||||
return (v << 8) | (v >> 8);
|
||||
}
|
||||
|
||||
static inline uint16_t
|
||||
be16_to_cpu(uint16_t v)
|
||||
{
|
||||
return cpu_to_be16 (v);
|
||||
}
|
||||
|
||||
static inline uint32_t
|
||||
cpu_to_be32(uint32_t v)
|
||||
{
|
||||
return (cpu_to_be16 (v) << 16) | cpu_to_be16 (v >> 16);
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
/* Encoded integer using maximum sized encoding. This is required for
|
||||
* operands that are later modified after encoding. */
|
||||
static unsigned char *
|
||||
|
@ -505,20 +488,6 @@ fail:
|
|||
return status;
|
||||
}
|
||||
|
||||
static void
|
||||
cff_dict_remove (cairo_hash_table_t *dict, unsigned short operator)
|
||||
{
|
||||
cff_dict_operator_t key, *op;
|
||||
|
||||
_cairo_dict_init_key (&key, operator);
|
||||
if (_cairo_hash_table_lookup (dict, &key.base,
|
||||
(cairo_hash_entry_t **) &op))
|
||||
{
|
||||
free (op->operand);
|
||||
_cairo_hash_table_remove (dict, (cairo_hash_entry_t *) op);
|
||||
}
|
||||
}
|
||||
|
||||
static unsigned char *
|
||||
cff_dict_get_operands (cairo_hash_table_t *dict,
|
||||
unsigned short operator,
|
||||
|
@ -742,12 +711,19 @@ cairo_cff_font_read_top_dict (cairo_cff_font_t *font)
|
|||
decode_integer (operand, &offset);
|
||||
cairo_cff_font_read_private_dict (font, font->data + offset, size);
|
||||
|
||||
cff_dict_remove (font->top_dict, CHARSET_OP);
|
||||
operand = cff_dict_get_operands (font->top_dict, CHARSET_OP, &size);
|
||||
if (!operand)
|
||||
font->charset_offset = 0;
|
||||
else {
|
||||
decode_integer (operand, &offset);
|
||||
font->charset_offset = offset;
|
||||
}
|
||||
|
||||
/* Use maximum sized encoding to reserve space for later modification. */
|
||||
end_buf = encode_integer_max (buf, 0);
|
||||
cff_dict_set_operands (font->top_dict, CHARSTRINGS_OP, buf, end_buf - buf);
|
||||
cff_dict_set_operands (font->top_dict, ENCODING_OP, buf, end_buf - buf);
|
||||
cff_dict_set_operands (font->top_dict, CHARSET_OP, buf, end_buf - buf);
|
||||
/* Private has two operands - size and offset */
|
||||
end_buf = encode_integer_max (end_buf, 0);
|
||||
cff_dict_set_operands (font->top_dict, PRIVATE_OP, buf, end_buf - buf);
|
||||
|
@ -770,6 +746,138 @@ cairo_cff_font_read_global_subroutines (cairo_cff_font_t *font)
|
|||
return cff_index_read (&font->global_sub_index, &font->current_ptr, font->data_end);
|
||||
}
|
||||
|
||||
static cairo_int_status_t
|
||||
cff_charset_read_data (cff_charset_t *charset, const unsigned char *data,
|
||||
const unsigned char *data_end, int num_glyphs)
|
||||
{
|
||||
const unsigned char *p = data;
|
||||
|
||||
num_glyphs -= 1; /* do not count .notdef */
|
||||
|
||||
if (p + 1 > data_end)
|
||||
return CAIRO_INT_STATUS_UNSUPPORTED;
|
||||
|
||||
switch (*p++) {
|
||||
case 0:
|
||||
if (p + num_glyphs*2 > data_end)
|
||||
return CAIRO_INT_STATUS_UNSUPPORTED;
|
||||
charset->is_builtin = FALSE;
|
||||
charset->data = data;
|
||||
charset->length = num_glyphs * 2 + 1;
|
||||
break;
|
||||
case 1:
|
||||
while (num_glyphs > 0) {
|
||||
if (p + 3 > data_end)
|
||||
return CAIRO_INT_STATUS_UNSUPPORTED;
|
||||
num_glyphs -= p[2] + 1;
|
||||
p += 3;
|
||||
}
|
||||
if (num_glyphs < 0)
|
||||
return CAIRO_INT_STATUS_UNSUPPORTED;
|
||||
charset->is_builtin = FALSE;
|
||||
charset->data = data;
|
||||
charset->length = p - data;
|
||||
break;
|
||||
case 2:
|
||||
while (num_glyphs > 0) {
|
||||
if (p + 4 > data_end)
|
||||
return CAIRO_INT_STATUS_UNSUPPORTED;
|
||||
num_glyphs -= be16_to_cpu(*(uint16_t *)(p + 2)) + 1;
|
||||
p += 4;
|
||||
}
|
||||
if (num_glyphs < 0)
|
||||
return CAIRO_INT_STATUS_UNSUPPORTED;
|
||||
charset->is_builtin = FALSE;
|
||||
charset->data = data;
|
||||
charset->length = p - data;
|
||||
break;
|
||||
default:
|
||||
return CAIRO_INT_STATUS_UNSUPPORTED;
|
||||
}
|
||||
|
||||
return CAIRO_STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
static const uint16_t ISOAdobe_charset[] = {
|
||||
1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16,
|
||||
17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30,
|
||||
31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44,
|
||||
45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58,
|
||||
59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72,
|
||||
73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86,
|
||||
87, 88, 89, 90, 91, 92, 93, 94, 95, 96, 97, 98, 99, 100,
|
||||
101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111,
|
||||
112, 113, 114, 115, 116, 117, 118, 119, 120, 121, 122,
|
||||
123, 124, 125, 126, 127, 128, 129, 130, 131, 132, 133,
|
||||
134, 135, 136, 137, 138, 139, 140, 141, 142, 143, 144,
|
||||
145, 146, 147, 148, 149, 150, 151, 152, 153, 154, 155,
|
||||
156, 157, 158, 159, 160, 161, 162, 163, 164, 165, 166,
|
||||
167, 168, 169, 170, 171, 172, 173, 174, 175, 176, 177,
|
||||
178, 179, 180, 181, 182, 183, 184, 185, 186, 187, 188,
|
||||
189, 190, 191, 192, 193, 194, 195, 196, 197, 198, 199,
|
||||
200, 201, 202, 203, 204, 205, 206, 207, 208, 209, 210,
|
||||
211, 212, 213, 214, 215, 216, 217, 218, 219, 220, 221,
|
||||
222, 223, 224, 225, 226, 227, 228,
|
||||
};
|
||||
|
||||
static const uint16_t Expert_charset[] = {
|
||||
1, 229, 230, 231, 232, 233, 234, 235, 236, 237, 238, 13,
|
||||
14, 15, 99, 239, 240, 241, 242, 243, 244, 245, 246, 247,
|
||||
248, 27, 28, 249, 250, 251, 252, 253, 254, 255, 256, 257,
|
||||
258, 259, 260, 261, 262, 263, 264, 265, 266, 109, 110,
|
||||
267, 268, 269, 270, 271, 272, 273, 274, 275, 276, 277,
|
||||
278, 279, 280, 281, 282, 283, 284, 285, 286, 287, 288,
|
||||
289, 290, 291, 292, 293, 294, 295, 296, 297, 298, 299,
|
||||
300, 301, 302, 303, 304, 305, 306, 307, 308, 309, 310,
|
||||
311, 312, 313, 314, 315, 316, 317, 318, 158, 155, 163,
|
||||
319, 320, 321, 322, 323, 324, 325, 326, 150, 164, 169,
|
||||
327, 328, 329, 330, 331, 332, 333, 334, 335, 336, 337,
|
||||
338, 339, 340, 341, 342, 343, 344, 345, 346, 347, 348,
|
||||
349, 350, 351, 352, 353, 354, 355, 356, 357, 358, 359,
|
||||
360, 361, 362, 363, 364, 365, 366, 367, 368, 369, 370,
|
||||
371, 372, 373, 374, 375, 376, 377, 378,
|
||||
};
|
||||
|
||||
static const uint16_t ExpertSubset_charset[] = {
|
||||
1, 231, 232, 235, 236, 237, 238, 13, 14, 15, 99, 239, 240,
|
||||
241, 242, 243, 244, 245, 246, 247, 248, 27, 28, 249, 250,
|
||||
251, 253, 254, 255, 256, 257, 258, 259, 260, 261, 262,
|
||||
263, 264, 265, 266, 109, 110, 267, 268, 269, 270, 272,
|
||||
300, 301, 302, 305, 314, 315, 158, 155, 163, 320, 321,
|
||||
322, 323, 324, 325, 326, 150, 164, 169, 327, 328, 329,
|
||||
330, 331, 332, 333, 334, 335, 336, 337, 338, 339, 340,
|
||||
341, 342, 343, 344, 345, 346,
|
||||
};
|
||||
|
||||
static cairo_int_status_t
|
||||
cairo_cff_font_read_charset (cairo_cff_font_t *font)
|
||||
{
|
||||
switch (font->charset_offset) {
|
||||
case 0:
|
||||
/* ISOAdobe charset */
|
||||
font->charset.is_builtin = TRUE;
|
||||
font->charset.sids = ISOAdobe_charset;
|
||||
font->charset.length = sizeof (ISOAdobe_charset);
|
||||
return CAIRO_STATUS_SUCCESS;
|
||||
case 1:
|
||||
/* Expert charset */
|
||||
font->charset.is_builtin = TRUE;
|
||||
font->charset.sids = Expert_charset;
|
||||
font->charset.length = sizeof (Expert_charset);
|
||||
return CAIRO_STATUS_SUCCESS;
|
||||
case 2:
|
||||
/* ExpertSubset charset */;
|
||||
font->charset.is_builtin = TRUE;
|
||||
font->charset.sids = ExpertSubset_charset;
|
||||
font->charset.length = sizeof (ExpertSubset_charset);
|
||||
return CAIRO_STATUS_SUCCESS;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
return cff_charset_read_data (&font->charset, font->data + (unsigned)font->charset_offset,
|
||||
font->data_end, font->num_glyphs);
|
||||
}
|
||||
|
||||
typedef cairo_int_status_t
|
||||
(*font_read_t) (cairo_cff_font_t *font);
|
||||
|
||||
|
@ -779,6 +887,8 @@ static const font_read_t font_read_funcs[] = {
|
|||
cairo_cff_font_read_top_dict,
|
||||
cairo_cff_font_read_strings,
|
||||
cairo_cff_font_read_global_subroutines,
|
||||
/* non-contiguous */
|
||||
cairo_cff_font_read_charset,
|
||||
};
|
||||
|
||||
static cairo_int_status_t
|
||||
|
@ -898,6 +1008,80 @@ cairo_cff_font_subset_charstrings (cairo_cff_font_t *font)
|
|||
return CAIRO_STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
static uint16_t
|
||||
cff_sid_from_gid (const cff_charset_t *charset, int gid)
|
||||
{
|
||||
const uint16_t *sids;
|
||||
const unsigned char *p;
|
||||
int prev_glyph;
|
||||
|
||||
if (charset->is_builtin) {
|
||||
if (gid - 1 < charset->length / 2)
|
||||
return charset->sids[gid - 1];
|
||||
}
|
||||
else {
|
||||
/* no need to check sizes here, this was done during reading */
|
||||
switch (charset->data[0]) {
|
||||
case 0:
|
||||
sids = (const uint16_t *)(charset->data + 1);
|
||||
return be16_to_cpu(sids[gid - 1]);
|
||||
case 1:
|
||||
prev_glyph = 1;
|
||||
for (p = charset->data + 1; p < charset->data + charset->length; p += 3) {
|
||||
if (gid <= prev_glyph + p[2]) {
|
||||
uint16_t sid = be16_to_cpu(*(const uint16_t *)p);
|
||||
return sid + gid - prev_glyph;
|
||||
}
|
||||
prev_glyph += p[2] + 1;
|
||||
}
|
||||
break;
|
||||
case 2:
|
||||
prev_glyph = 1;
|
||||
for (p = charset->data + 1; p < charset->data + charset->length; p += 4) {
|
||||
uint16_t nLeft = be16_to_cpu(*(const uint16_t *)(p + 2));
|
||||
if (gid <= prev_glyph + nLeft) {
|
||||
uint16_t sid = be16_to_cpu(*(const uint16_t *)p);
|
||||
return sid + gid - prev_glyph;
|
||||
}
|
||||
prev_glyph += nLeft + 1;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static cairo_status_t
|
||||
cairo_cff_font_subset_charset (cairo_cff_font_t *font)
|
||||
{
|
||||
unsigned int i;
|
||||
|
||||
for (i = 0; i < font->scaled_font_subset->num_glyphs; i++) {
|
||||
int gid = font->scaled_font_subset->glyphs[i];
|
||||
uint16_t original_sid = cff_sid_from_gid(&font->charset, gid);
|
||||
uint16_t new_sid;
|
||||
cff_index_element_t *element;
|
||||
cairo_status_t status;
|
||||
|
||||
if (original_sid >= NUM_STD_STRINGS) {
|
||||
element = _cairo_array_index (&font->strings_index, original_sid - NUM_STD_STRINGS);
|
||||
new_sid = NUM_STD_STRINGS + _cairo_array_num_elements (&font->strings_subset_index);
|
||||
status = cff_index_append (&font->strings_subset_index, element->data, element->length);
|
||||
if (status)
|
||||
return status;
|
||||
}
|
||||
else
|
||||
new_sid = original_sid;
|
||||
|
||||
status = _cairo_array_append(&font->charset_subset, &new_sid);
|
||||
if (status)
|
||||
return status;
|
||||
}
|
||||
return CAIRO_STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
static cairo_status_t
|
||||
cairo_cff_font_subset_font (cairo_cff_font_t *font)
|
||||
{
|
||||
|
@ -910,6 +1094,10 @@ cairo_cff_font_subset_font (cairo_cff_font_t *font)
|
|||
return status;
|
||||
|
||||
status = cairo_cff_font_subset_charstrings (font);
|
||||
if (status)
|
||||
return status;
|
||||
|
||||
status = cairo_cff_font_subset_charset (font);
|
||||
|
||||
return status;
|
||||
}
|
||||
|
@ -1038,6 +1226,27 @@ cairo_cff_font_write_encoding (cairo_cff_font_t *font)
|
|||
return _cairo_array_append_multiple (&font->output, buf, 4);
|
||||
}
|
||||
|
||||
static cairo_status_t
|
||||
cairo_cff_font_write_charset (cairo_cff_font_t *font)
|
||||
{
|
||||
unsigned char format = 0;
|
||||
unsigned int i;
|
||||
cairo_status_t status;
|
||||
|
||||
cairo_cff_font_set_topdict_operator_to_cur_pos (font, CHARSET_OP);
|
||||
status = _cairo_array_append (&font->output, &format);
|
||||
if (status)
|
||||
return status;
|
||||
|
||||
for (i = 0; i < (unsigned)_cairo_array_num_elements(&font->charset_subset); i++) {
|
||||
uint16_t sid = cpu_to_be16(*(uint16_t *)_cairo_array_index(&font->charset_subset, i));
|
||||
status = _cairo_array_append_multiple (&font->output, &sid, sizeof(sid));
|
||||
if (status)
|
||||
return status;
|
||||
}
|
||||
return CAIRO_STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
static cairo_status_t
|
||||
cairo_cff_font_write_charstrings (cairo_cff_font_t *font)
|
||||
{
|
||||
|
@ -1098,6 +1307,7 @@ static const font_write_t font_write_funcs[] = {
|
|||
cairo_cff_font_write_strings,
|
||||
cairo_cff_font_write_global_subrs,
|
||||
cairo_cff_font_write_encoding,
|
||||
cairo_cff_font_write_charset,
|
||||
cairo_cff_font_write_charstrings,
|
||||
cairo_cff_font_write_private_dict_and_local_sub,
|
||||
};
|
||||
|
@ -1345,6 +1555,7 @@ _cairo_cff_font_create (cairo_scaled_font_subset_t *scaled_font_subset,
|
|||
cff_index_init (&font->local_sub_index);
|
||||
cff_index_init (&font->charstrings_subset_index);
|
||||
cff_index_init (&font->strings_subset_index);
|
||||
_cairo_array_init (&font->charset_subset, sizeof(uint16_t));
|
||||
|
||||
free (name);
|
||||
*font_return = font;
|
||||
|
@ -1383,6 +1594,7 @@ cairo_cff_font_destroy (cairo_cff_font_t *font)
|
|||
cff_index_fini (&font->local_sub_index);
|
||||
cff_index_fini (&font->charstrings_subset_index);
|
||||
cff_index_fini (&font->strings_subset_index);
|
||||
_cairo_array_fini (&font->charset_subset);
|
||||
free (font);
|
||||
}
|
||||
|
||||
|
|
|
@ -48,7 +48,10 @@ _cairo_clip_path_destroy (cairo_clip_path_t *clip_path);
|
|||
void
|
||||
_cairo_clip_init (cairo_clip_t *clip, cairo_surface_t *target)
|
||||
{
|
||||
if (target)
|
||||
clip->mode = _cairo_surface_get_clip_mode (target);
|
||||
else
|
||||
clip->mode = CAIRO_CLIP_MODE_MASK;
|
||||
|
||||
clip->surface = NULL;
|
||||
clip->surface_rect.x = 0;
|
||||
|
|
|
@ -95,7 +95,8 @@ _cairo_color_init_rgb (cairo_color_t *color,
|
|||
* then special-casing the result of an input value of 1.0 so that it
|
||||
* maps to 65535 instead of 65536.
|
||||
*/
|
||||
static inline uint16_t _color_to_short (double d)
|
||||
uint16_t
|
||||
_cairo_color_double_to_short (double d)
|
||||
{
|
||||
uint32_t i;
|
||||
i = (uint32_t) (d * 65536);
|
||||
|
@ -106,10 +107,10 @@ static inline uint16_t _color_to_short (double d)
|
|||
static void
|
||||
_cairo_color_compute_shorts (cairo_color_t *color)
|
||||
{
|
||||
color->red_short = _color_to_short (color->red * color->alpha);
|
||||
color->green_short = _color_to_short (color->green * color->alpha);
|
||||
color->blue_short = _color_to_short (color->blue * color->alpha);
|
||||
color->alpha_short = _color_to_short (color->alpha);
|
||||
color->red_short = _cairo_color_double_to_short (color->red * color->alpha);
|
||||
color->green_short = _cairo_color_double_to_short (color->green * color->alpha);
|
||||
color->blue_short = _cairo_color_double_to_short (color->blue * color->alpha);
|
||||
color->alpha_short = _cairo_color_double_to_short (color->alpha);
|
||||
}
|
||||
|
||||
void
|
||||
|
|
|
@ -52,9 +52,9 @@
|
|||
|
||||
|
||||
/*
|
||||
* Rectangle works fine.
|
||||
* Rectangle causes problems (see bugs 361377, 359553, 359243 in Gnome BTS).
|
||||
*/
|
||||
#define DFB_RECTANGLES 1
|
||||
#define DFB_RECTANGLES 0
|
||||
|
||||
/*
|
||||
* Composite works fine.
|
||||
|
|
|
@ -48,5 +48,8 @@ cairo_directfb_surface_create (IDirectFB *dfb,IDirectFBSurface *surface);
|
|||
|
||||
CAIRO_END_DECLS
|
||||
|
||||
#else /*CAIRO_HAS_DIRECTFB_SURFACE*/
|
||||
# error Cairo was not compiled with support for the directfb backend
|
||||
#endif /*CAIRO_HAS_DIRECTFB_SURFACE*/
|
||||
|
||||
#endif /*CAIRO_DIRECTFB_H*/
|
||||
|
|
|
@ -52,10 +52,10 @@
|
|||
#endif
|
||||
|
||||
#define CAIRO_VERSION_MAJOR 1
|
||||
#define CAIRO_VERSION_MINOR 3
|
||||
#define CAIRO_VERSION_MICRO 12
|
||||
#define CAIRO_VERSION_MINOR 4
|
||||
#define CAIRO_VERSION_MICRO 2
|
||||
|
||||
#define CAIRO_VERSION_STRING "1.3.12"
|
||||
#define CAIRO_VERSION_STRING "1.4.2"
|
||||
|
||||
@PS_SURFACE_FEATURE@
|
||||
|
||||
|
@ -67,8 +67,6 @@
|
|||
|
||||
@QUARTZ_SURFACE_FEATURE@
|
||||
|
||||
@NQUARTZ_SURFACE_FEATURE@
|
||||
|
||||
@XCB_SURFACE_FEATURE@
|
||||
|
||||
@WIN32_SURFACE_FEATURE@
|
||||
|
|
|
@ -1,3 +1,4 @@
|
|||
/* -*- Mode: c; c-basic-offset: 4; indent-tabs-mode: t; tab-width: 8; -*- */
|
||||
/* cairo - a vector graphics library with display and print output
|
||||
*
|
||||
* Copyright © 2002 University of Southern California
|
||||
|
@ -65,32 +66,40 @@ _cairo_font_face_init (cairo_font_face_t *font_face,
|
|||
_cairo_user_data_array_init (&font_face->user_data);
|
||||
}
|
||||
|
||||
/* This mutex protects both cairo_toy_font_hash_table as well as
|
||||
reference count manipulations for all cairo_font_face_t. */
|
||||
CAIRO_MUTEX_DECLARE (_cairo_font_face_mutex);
|
||||
|
||||
/**
|
||||
* cairo_font_face_reference:
|
||||
* @font_face: a #cairo_font_face_t, (may be NULL in which case this
|
||||
* @font_face: a #cairo_font_face_t, (may be %NULL in which case this
|
||||
* function does nothing).
|
||||
*
|
||||
* Increases the reference count on @font_face by one. This prevents
|
||||
* @font_face from being destroyed until a matching call to
|
||||
* cairo_font_face_destroy() is made.
|
||||
*
|
||||
* The number of references to a #cairo_font_face_t can be get using
|
||||
* cairo_font_face_get_reference_count().
|
||||
*
|
||||
* Return value: the referenced #cairo_font_face_t.
|
||||
**/
|
||||
cairo_font_face_t *
|
||||
cairo_font_face_reference (cairo_font_face_t *font_face)
|
||||
{
|
||||
if (font_face == NULL)
|
||||
return NULL;
|
||||
|
||||
if (font_face->ref_count == CAIRO_REF_COUNT_INVALID)
|
||||
if (font_face == NULL || font_face->ref_count == CAIRO_REF_COUNT_INVALID)
|
||||
return font_face;
|
||||
|
||||
CAIRO_MUTEX_LOCK (_cairo_font_face_mutex);
|
||||
|
||||
/* We would normally assert (font_face->ref_count >0) here but we
|
||||
* can't get away with that due to the zombie case as documented
|
||||
* in _cairo_ft_font_face_destroy. */
|
||||
|
||||
font_face->ref_count++;
|
||||
|
||||
CAIRO_MUTEX_UNLOCK (_cairo_font_face_mutex);
|
||||
|
||||
return font_face;
|
||||
}
|
||||
slim_hidden_def (cairo_font_face_reference);
|
||||
|
@ -106,16 +115,19 @@ slim_hidden_def (cairo_font_face_reference);
|
|||
void
|
||||
cairo_font_face_destroy (cairo_font_face_t *font_face)
|
||||
{
|
||||
if (font_face == NULL)
|
||||
if (font_face == NULL || font_face->ref_count == CAIRO_REF_COUNT_INVALID)
|
||||
return;
|
||||
|
||||
if (font_face->ref_count == CAIRO_REF_COUNT_INVALID)
|
||||
return;
|
||||
CAIRO_MUTEX_LOCK (_cairo_font_face_mutex);
|
||||
|
||||
assert (font_face->ref_count > 0);
|
||||
|
||||
if (--(font_face->ref_count) > 0)
|
||||
if (--(font_face->ref_count) > 0) {
|
||||
CAIRO_MUTEX_UNLOCK (_cairo_font_face_mutex);
|
||||
return;
|
||||
}
|
||||
|
||||
CAIRO_MUTEX_UNLOCK (_cairo_font_face_mutex);
|
||||
|
||||
font_face->backend->destroy (font_face);
|
||||
|
||||
|
@ -134,7 +146,7 @@ slim_hidden_def (cairo_font_face_destroy);
|
|||
|
||||
/**
|
||||
* cairo_font_face_get_type:
|
||||
* @font_face: a #cairo_font_face_t
|
||||
* @font_face: a font face
|
||||
*
|
||||
* This function returns the type of the backend used to create
|
||||
* a font face. See #cairo_font_type_t for available types.
|
||||
|
@ -149,6 +161,26 @@ cairo_font_face_get_type (cairo_font_face_t *font_face)
|
|||
return font_face->backend->type;
|
||||
}
|
||||
|
||||
/**
|
||||
* cairo_font_face_get_reference_count:
|
||||
* @font_face: a #cairo_font_face_t
|
||||
*
|
||||
* Returns the current reference count of @font_face.
|
||||
*
|
||||
* Return value: the current reference count of @font_face. If the
|
||||
* object is a nil object, 0 will be returned.
|
||||
*
|
||||
* Since: 1.4
|
||||
**/
|
||||
unsigned int
|
||||
cairo_font_face_get_reference_count (cairo_font_face_t *font_face)
|
||||
{
|
||||
if (font_face == NULL || font_face->ref_count == CAIRO_REF_COUNT_INVALID)
|
||||
return 0;
|
||||
|
||||
return font_face->ref_count;
|
||||
}
|
||||
|
||||
/**
|
||||
* cairo_font_face_status:
|
||||
* @font_face: a #cairo_font_face_t
|
||||
|
@ -226,16 +258,16 @@ _cairo_toy_font_face_keys_equal (const void *key_a,
|
|||
* our cache and mapping from cairo_font_face_t => cairo_scaled_font_t
|
||||
* works. Once the corresponding cairo_font_face_t objects fall out of
|
||||
* downstream caches, we don't need them in this hash table anymore.
|
||||
*
|
||||
* Modifications to this hash table are protected by
|
||||
* _cairo_font_face_mutex.
|
||||
*/
|
||||
|
||||
static cairo_hash_table_t *cairo_toy_font_face_hash_table = NULL;
|
||||
|
||||
CAIRO_MUTEX_DECLARE (cairo_toy_font_face_hash_table_mutex);
|
||||
|
||||
static cairo_hash_table_t *
|
||||
_cairo_toy_font_face_hash_table_lock (void)
|
||||
{
|
||||
CAIRO_MUTEX_LOCK (cairo_toy_font_face_hash_table_mutex);
|
||||
CAIRO_MUTEX_LOCK (_cairo_font_face_mutex);
|
||||
|
||||
if (cairo_toy_font_face_hash_table == NULL)
|
||||
{
|
||||
|
@ -243,7 +275,7 @@ _cairo_toy_font_face_hash_table_lock (void)
|
|||
_cairo_hash_table_create (_cairo_toy_font_face_keys_equal);
|
||||
|
||||
if (cairo_toy_font_face_hash_table == NULL) {
|
||||
CAIRO_MUTEX_UNLOCK (cairo_toy_font_face_hash_table_mutex);
|
||||
CAIRO_MUTEX_UNLOCK (_cairo_font_face_mutex);
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
|
@ -254,7 +286,7 @@ _cairo_toy_font_face_hash_table_lock (void)
|
|||
static void
|
||||
_cairo_toy_font_face_hash_table_unlock (void)
|
||||
{
|
||||
CAIRO_MUTEX_UNLOCK (cairo_toy_font_face_hash_table_mutex);
|
||||
CAIRO_MUTEX_UNLOCK (_cairo_font_face_mutex);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -363,8 +395,11 @@ _cairo_toy_font_face_create (const char *family,
|
|||
&key.base.hash_entry,
|
||||
(cairo_hash_entry_t **) &font_face))
|
||||
{
|
||||
/* We increment the reference count here manually to avoid
|
||||
double-locking. */
|
||||
font_face->base.ref_count++;
|
||||
_cairo_toy_font_face_hash_table_unlock ();
|
||||
return cairo_font_face_reference (&font_face->base);
|
||||
return &font_face->base;
|
||||
}
|
||||
|
||||
/* Otherwise create it and insert into hash table. */
|
||||
|
@ -471,8 +506,11 @@ _cairo_font_reset_static_data (void)
|
|||
{
|
||||
_cairo_scaled_font_map_destroy ();
|
||||
|
||||
CAIRO_MUTEX_LOCK (cairo_toy_font_face_hash_table_mutex);
|
||||
/* We manually acquire the lock rather than calling
|
||||
* cairo_toy_font_face_hash_table_lock simply to avoid
|
||||
* creating the table only to destroy it again. */
|
||||
CAIRO_MUTEX_LOCK (_cairo_font_face_mutex);
|
||||
_cairo_hash_table_destroy (cairo_toy_font_face_hash_table);
|
||||
cairo_toy_font_face_hash_table = NULL;
|
||||
CAIRO_MUTEX_UNLOCK (cairo_toy_font_face_hash_table_mutex);
|
||||
CAIRO_MUTEX_UNLOCK (_cairo_font_face_mutex);
|
||||
}
|
||||
|
|
|
@ -62,9 +62,11 @@
|
|||
*/
|
||||
#define MAX_OPEN_FACES 10
|
||||
|
||||
#ifndef MOZILLA_CAIRO_NOT_DEFINED
|
||||
/* This is the maximum font size we allow to be passed to FT_Set_Char_Size
|
||||
*/
|
||||
#define MAX_FONT_SIZE 1000
|
||||
#endif /* !MOZILLA_CAIRO_NOT_DEFINED */
|
||||
|
||||
/*
|
||||
* The simple 2x2 matrix is converted into separate scale and shape
|
||||
|
@ -104,7 +106,8 @@ struct _cairo_ft_unscaled_font {
|
|||
cairo_matrix_t current_shape;
|
||||
FT_Matrix Current_Shape;
|
||||
|
||||
int lock; /* count of how many times this font has been locked */
|
||||
cairo_mutex_t mutex;
|
||||
int lock_count;
|
||||
|
||||
cairo_ft_font_face_t *faces; /* Linked list of faces for this font */
|
||||
};
|
||||
|
@ -153,7 +156,7 @@ typedef struct _cairo_ft_unscaled_font_map {
|
|||
|
||||
static cairo_ft_unscaled_font_map_t *cairo_ft_unscaled_font_map = NULL;
|
||||
|
||||
CAIRO_MUTEX_DECLARE(cairo_ft_unscaled_font_map_mutex);
|
||||
CAIRO_MUTEX_DECLARE(_cairo_ft_unscaled_font_map_mutex);
|
||||
|
||||
static void
|
||||
_font_map_release_face_lock_held (cairo_ft_unscaled_font_map_t *font_map,
|
||||
|
@ -211,7 +214,7 @@ _cairo_ft_unscaled_font_map_destroy (void)
|
|||
cairo_ft_unscaled_font_t *unscaled;
|
||||
cairo_ft_unscaled_font_map_t *font_map;
|
||||
|
||||
CAIRO_MUTEX_LOCK (cairo_ft_unscaled_font_map_mutex);
|
||||
CAIRO_MUTEX_LOCK (_cairo_ft_unscaled_font_map_mutex);
|
||||
|
||||
if (cairo_ft_unscaled_font_map) {
|
||||
font_map = cairo_ft_unscaled_font_map;
|
||||
|
@ -244,20 +247,20 @@ _cairo_ft_unscaled_font_map_destroy (void)
|
|||
cairo_ft_unscaled_font_map = NULL;
|
||||
}
|
||||
|
||||
CAIRO_MUTEX_UNLOCK (cairo_ft_unscaled_font_map_mutex);
|
||||
CAIRO_MUTEX_UNLOCK (_cairo_ft_unscaled_font_map_mutex);
|
||||
}
|
||||
|
||||
static cairo_ft_unscaled_font_map_t *
|
||||
_cairo_ft_unscaled_font_map_lock (void)
|
||||
{
|
||||
CAIRO_MUTEX_LOCK (cairo_ft_unscaled_font_map_mutex);
|
||||
CAIRO_MUTEX_LOCK (_cairo_ft_unscaled_font_map_mutex);
|
||||
|
||||
if (cairo_ft_unscaled_font_map == NULL)
|
||||
{
|
||||
_cairo_ft_unscaled_font_map_create ();
|
||||
|
||||
if (cairo_ft_unscaled_font_map == NULL) {
|
||||
CAIRO_MUTEX_UNLOCK (cairo_ft_unscaled_font_map_mutex);
|
||||
CAIRO_MUTEX_UNLOCK (_cairo_ft_unscaled_font_map_mutex);
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
|
@ -268,7 +271,7 @@ _cairo_ft_unscaled_font_map_lock (void)
|
|||
static void
|
||||
_cairo_ft_unscaled_font_map_unlock (void)
|
||||
{
|
||||
CAIRO_MUTEX_UNLOCK (cairo_ft_unscaled_font_map_mutex);
|
||||
CAIRO_MUTEX_UNLOCK (_cairo_ft_unscaled_font_map_mutex);
|
||||
}
|
||||
|
||||
static void
|
||||
|
@ -337,7 +340,8 @@ _cairo_ft_unscaled_font_init (cairo_ft_unscaled_font_t *unscaled,
|
|||
}
|
||||
|
||||
unscaled->have_scale = FALSE;
|
||||
unscaled->lock = 0;
|
||||
CAIRO_MUTEX_INIT (&unscaled->mutex);
|
||||
unscaled->lock_count = 0;
|
||||
|
||||
unscaled->faces = NULL;
|
||||
|
||||
|
@ -370,6 +374,8 @@ _cairo_ft_unscaled_font_fini (cairo_ft_unscaled_font_t *unscaled)
|
|||
free (unscaled->filename);
|
||||
unscaled->filename = NULL;
|
||||
}
|
||||
|
||||
CAIRO_MUTEX_FINI (&unscaled->mutex);
|
||||
}
|
||||
|
||||
static int
|
||||
|
@ -501,7 +507,7 @@ _has_unlocked_face (void *entry)
|
|||
{
|
||||
cairo_ft_unscaled_font_t *unscaled = entry;
|
||||
|
||||
return (unscaled->lock == 0 && unscaled->face);
|
||||
return (unscaled->lock_count == 0 && unscaled->face);
|
||||
}
|
||||
|
||||
/* Ensures that an unscaled font has a face object. If we exceed
|
||||
|
@ -516,16 +522,18 @@ _cairo_ft_unscaled_font_lock_face (cairo_ft_unscaled_font_t *unscaled)
|
|||
cairo_ft_unscaled_font_map_t *font_map;
|
||||
FT_Face face = NULL;
|
||||
|
||||
if (unscaled->face) {
|
||||
unscaled->lock++;
|
||||
CAIRO_MUTEX_LOCK (unscaled->mutex);
|
||||
unscaled->lock_count++;
|
||||
|
||||
if (unscaled->face)
|
||||
return unscaled->face;
|
||||
}
|
||||
|
||||
/* If this unscaled font was created from an FT_Face then we just
|
||||
* returned it above. */
|
||||
assert (!unscaled->from_face);
|
||||
|
||||
font_map = _cairo_ft_unscaled_font_map_lock ();
|
||||
{
|
||||
assert (font_map != NULL);
|
||||
|
||||
while (font_map->num_open_faces >= MAX_OPEN_FACES)
|
||||
|
@ -539,21 +547,22 @@ _cairo_ft_unscaled_font_lock_face (cairo_ft_unscaled_font_t *unscaled)
|
|||
|
||||
_font_map_release_face_lock_held (font_map, entry);
|
||||
}
|
||||
}
|
||||
_cairo_ft_unscaled_font_map_unlock ();
|
||||
|
||||
if (FT_New_Face (font_map->ft_library,
|
||||
unscaled->filename,
|
||||
unscaled->id,
|
||||
&face) != FT_Err_Ok)
|
||||
goto FAIL;
|
||||
{
|
||||
CAIRO_MUTEX_UNLOCK (unscaled->mutex);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
unscaled->face = face;
|
||||
unscaled->lock++;
|
||||
|
||||
font_map->num_open_faces++;
|
||||
|
||||
FAIL:
|
||||
_cairo_ft_unscaled_font_map_unlock ();
|
||||
|
||||
return face;
|
||||
}
|
||||
slim_hidden_def (cairo_ft_scaled_font_lock_face);
|
||||
|
@ -563,9 +572,11 @@ slim_hidden_def (cairo_ft_scaled_font_lock_face);
|
|||
void
|
||||
_cairo_ft_unscaled_font_unlock_face (cairo_ft_unscaled_font_t *unscaled)
|
||||
{
|
||||
assert (unscaled->lock > 0);
|
||||
assert (unscaled->lock_count > 0);
|
||||
|
||||
unscaled->lock--;
|
||||
unscaled->lock_count--;
|
||||
|
||||
CAIRO_MUTEX_UNLOCK (unscaled->mutex);
|
||||
}
|
||||
slim_hidden_def (cairo_ft_scaled_font_unlock_face);
|
||||
|
||||
|
@ -647,6 +658,7 @@ _cairo_ft_unscaled_font_set_scale (cairo_ft_unscaled_font_t *unscaled,
|
|||
FT_Set_Transform(unscaled->face, &mat, NULL);
|
||||
|
||||
if ((unscaled->face->face_flags & FT_FACE_FLAG_SCALABLE) != 0) {
|
||||
#ifndef MOZILLA_CAIRO_NOT_DEFINED
|
||||
double x_scale = sf.x_scale;
|
||||
double y_scale = sf.y_scale;
|
||||
if (x_scale > MAX_FONT_SIZE) {
|
||||
|
@ -656,10 +668,16 @@ _cairo_ft_unscaled_font_set_scale (cairo_ft_unscaled_font_t *unscaled,
|
|||
y_scale = MAX_FONT_SIZE;
|
||||
}
|
||||
|
||||
error = FT_Set_Char_Size (unscaled->face,
|
||||
sf.x_scale * 64.0,
|
||||
sf.y_scale * 64.0,
|
||||
0, 0);
|
||||
#else
|
||||
error = FT_Set_Char_Size (unscaled->face,
|
||||
x_scale * 64.0,
|
||||
y_scale * 64.0,
|
||||
0, 0);
|
||||
#endif /* MOZCAIRO */
|
||||
assert (error == 0);
|
||||
} else {
|
||||
double min_distance = DBL_MAX;
|
||||
|
@ -1501,6 +1519,8 @@ _cairo_ft_scaled_font_create (cairo_ft_unscaled_font_t *unscaled,
|
|||
|
||||
_cairo_scaled_font_set_metrics (&scaled_font->base, &fs_metrics);
|
||||
|
||||
_cairo_ft_unscaled_font_unlock_face (unscaled);
|
||||
|
||||
return &scaled_font->base;
|
||||
}
|
||||
|
||||
|
@ -1780,10 +1800,13 @@ _cairo_ft_scaled_glyph_init (void *abstract_font,
|
|||
cairo_bool_t vertical_layout = FALSE;
|
||||
cairo_status_t status = CAIRO_STATUS_SUCCESS;
|
||||
|
||||
face = cairo_ft_scaled_font_lock_face (abstract_font);
|
||||
face = _cairo_ft_unscaled_font_lock_face (unscaled);
|
||||
if (!face)
|
||||
return CAIRO_STATUS_NO_MEMORY;
|
||||
|
||||
_cairo_ft_unscaled_font_set_scale (scaled_font->unscaled,
|
||||
&scaled_font->base.scale);
|
||||
|
||||
/* Ignore global advance unconditionally */
|
||||
load_flags |= FT_LOAD_IGNORE_GLOBAL_ADVANCE_WIDTH;
|
||||
|
||||
|
@ -1823,6 +1846,8 @@ _cairo_ft_scaled_glyph_init (void *abstract_font,
|
|||
_cairo_ft_scaled_glyph_vertical_layout_bearing_fix (scaled_font, glyph);
|
||||
|
||||
if (info & CAIRO_SCALED_GLYPH_INFO_METRICS) {
|
||||
|
||||
cairo_bool_t hint_metrics = scaled_font->base.options.hint_metrics != CAIRO_HINT_METRICS_OFF;
|
||||
/*
|
||||
* Compute font-space metrics
|
||||
*/
|
||||
|
@ -1848,8 +1873,7 @@ _cairo_ft_scaled_glyph_init (void *abstract_font,
|
|||
* FreeType, then we need to do the metric hinting ourselves.
|
||||
*/
|
||||
|
||||
if ((scaled_font->base.options.hint_metrics != CAIRO_HINT_METRICS_OFF) &&
|
||||
(load_flags & FT_LOAD_NO_HINTING))
|
||||
if (hint_metrics && (load_flags & FT_LOAD_NO_HINTING))
|
||||
{
|
||||
FT_Pos x1, x2;
|
||||
FT_Pos y1, y2;
|
||||
|
@ -1896,14 +1920,20 @@ _cairo_ft_scaled_glyph_init (void *abstract_font,
|
|||
fs_metrics.x_bearing = DOUBLE_FROM_26_6 (metrics->horiBearingX) * x_factor;
|
||||
fs_metrics.y_bearing = DOUBLE_FROM_26_6 (-metrics->horiBearingY) * y_factor;
|
||||
|
||||
if (hint_metrics || glyph->format != FT_GLYPH_FORMAT_OUTLINE)
|
||||
fs_metrics.x_advance = DOUBLE_FROM_26_6 (metrics->horiAdvance) * x_factor;
|
||||
else
|
||||
fs_metrics.x_advance = DOUBLE_FROM_16_16 (glyph->linearHoriAdvance) * x_factor;
|
||||
fs_metrics.y_advance = 0 * y_factor;
|
||||
} else {
|
||||
fs_metrics.x_bearing = DOUBLE_FROM_26_6 (metrics->vertBearingX) * x_factor;
|
||||
fs_metrics.y_bearing = DOUBLE_FROM_26_6 (metrics->vertBearingY) * y_factor;
|
||||
|
||||
fs_metrics.x_advance = 0 * x_factor;
|
||||
if (hint_metrics || glyph->format != FT_GLYPH_FORMAT_OUTLINE)
|
||||
fs_metrics.y_advance = DOUBLE_FROM_26_6 (metrics->vertAdvance) * y_factor;
|
||||
else
|
||||
fs_metrics.y_advance = DOUBLE_FROM_26_6 (glyph->linearVertAdvance) * y_factor;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1946,7 +1976,7 @@ _cairo_ft_scaled_glyph_init (void *abstract_font,
|
|||
load_flags | FT_LOAD_NO_BITMAP);
|
||||
|
||||
if (error) {
|
||||
cairo_ft_scaled_font_unlock_face (abstract_font);
|
||||
_cairo_ft_unscaled_font_unlock_face (unscaled);
|
||||
return CAIRO_STATUS_NO_MEMORY;
|
||||
}
|
||||
#if HAVE_FT_GLYPHSLOT_EMBOLDEN
|
||||
|
@ -1974,7 +2004,7 @@ _cairo_ft_scaled_glyph_init (void *abstract_font,
|
|||
path);
|
||||
}
|
||||
FAIL:
|
||||
cairo_ft_scaled_font_unlock_face (abstract_font);
|
||||
_cairo_ft_unscaled_font_unlock_face (unscaled);
|
||||
|
||||
return status;
|
||||
}
|
||||
|
@ -2026,6 +2056,38 @@ _cairo_ft_load_truetype_table (void *abstract_font,
|
|||
return status;
|
||||
}
|
||||
|
||||
static void
|
||||
_cairo_ft_map_glyphs_to_unicode (void *abstract_font,
|
||||
cairo_scaled_font_subset_t *font_subset)
|
||||
{
|
||||
cairo_ft_scaled_font_t *scaled_font = abstract_font;
|
||||
cairo_ft_unscaled_font_t *unscaled = scaled_font->unscaled;
|
||||
FT_Face face;
|
||||
FT_UInt glyph;
|
||||
unsigned long charcode;
|
||||
unsigned int i;
|
||||
int count;
|
||||
|
||||
face = _cairo_ft_unscaled_font_lock_face (unscaled);
|
||||
if (!face)
|
||||
return;
|
||||
|
||||
count = font_subset->num_glyphs;
|
||||
charcode = FT_Get_First_Char( face, &glyph);
|
||||
while (glyph != 0 && count > 0)
|
||||
{
|
||||
for (i = 0; i < font_subset->num_glyphs; i++) {
|
||||
if (font_subset->glyphs[i] == glyph) {
|
||||
font_subset->to_unicode[i] = charcode;
|
||||
count--;
|
||||
break;
|
||||
}
|
||||
}
|
||||
charcode = FT_Get_Next_Char(face, charcode, &glyph);
|
||||
}
|
||||
_cairo_ft_unscaled_font_unlock_face (unscaled);
|
||||
}
|
||||
|
||||
const cairo_scaled_font_backend_t cairo_ft_scaled_font_backend = {
|
||||
CAIRO_FONT_TYPE_FT,
|
||||
_cairo_ft_scaled_font_create_toy,
|
||||
|
@ -2035,6 +2097,7 @@ const cairo_scaled_font_backend_t cairo_ft_scaled_font_backend = {
|
|||
_cairo_ft_ucs4_to_index,
|
||||
NULL, /* show_glyphs */
|
||||
_cairo_ft_load_truetype_table,
|
||||
_cairo_ft_map_glyphs_to_unicode,
|
||||
};
|
||||
|
||||
/* cairo_ft_font_face_t */
|
||||
|
@ -2392,13 +2455,14 @@ cairo_ft_font_face_create_for_ft_face (FT_Face face,
|
|||
* of times.
|
||||
*
|
||||
* You must be careful when using this function in a library or in a
|
||||
* threaded application, because other threads may lock faces that
|
||||
* share the same #FT_Face object. For this reason, you must call
|
||||
* cairo_ft_lock() before locking any face objects, and
|
||||
* cairo_ft_unlock() after you are done. (These functions are not yet
|
||||
* implemented, so this function cannot be currently safely used in a
|
||||
* threaded application.)
|
||||
|
||||
* threaded application, because freetype's design makes it unsafe to
|
||||
* call freetype functions simultaneously from multiple threads, (even
|
||||
* if using distinct FT_Face objects). Because of this, application
|
||||
* code that acquires an FT_Face object with this call must add it's
|
||||
* own locking to protect any use of that object, (and which also must
|
||||
* protect any other calls into cairo as almost any cairo function
|
||||
* might result in a call into the freetype library).
|
||||
*
|
||||
* Return value: The #FT_Face object for @font, scaled appropriately,
|
||||
* or %NULL if @scaled_font is in an error state (see
|
||||
* cairo_scaled_font_status()) or there is insufficient memory.
|
||||
|
@ -2421,6 +2485,14 @@ cairo_ft_scaled_font_lock_face (cairo_scaled_font_t *abstract_font)
|
|||
_cairo_ft_unscaled_font_set_scale (scaled_font->unscaled,
|
||||
&scaled_font->base.scale);
|
||||
|
||||
/* NOTE: We deliberately release the unscaled font's mutex here,
|
||||
* so that we are not holding a lock across two separate calls to
|
||||
* cairo function, (which would give the application some
|
||||
* opportunity for creating deadlock. This is obviously unsafe,
|
||||
* but as documented, the user must add manual locking when using
|
||||
* this function. */
|
||||
CAIRO_MUTEX_UNLOCK (scaled_font->unscaled->mutex);
|
||||
|
||||
return face;
|
||||
}
|
||||
|
||||
|
@ -2441,6 +2513,12 @@ cairo_ft_scaled_font_unlock_face (cairo_scaled_font_t *abstract_font)
|
|||
if (scaled_font->base.status)
|
||||
return;
|
||||
|
||||
/* NOTE: We released the unscaled font's mutex at the end of
|
||||
* cairo_ft_scaled_font_lock_face, so we have to acquire it again
|
||||
* as _cairo_ft_unscaled_font_unlock_face expects it to be held
|
||||
* when we call into it. */
|
||||
CAIRO_MUTEX_LOCK (scaled_font->unscaled->mutex);
|
||||
|
||||
_cairo_ft_unscaled_font_unlock_face (scaled_font->unscaled);
|
||||
}
|
||||
|
||||
|
|
|
@ -594,7 +594,7 @@ _cairo_glitz_pattern_acquire_surface (cairo_pattern_t *pattern,
|
|||
unsigned int *pixels;
|
||||
unsigned int i, n_base_params;
|
||||
glitz_buffer_t *buffer;
|
||||
static glitz_pixel_format_t format = {
|
||||
static const glitz_pixel_format_t format = {
|
||||
GLITZ_FOURCC_RGB,
|
||||
{
|
||||
32,
|
||||
|
@ -686,12 +686,12 @@ _cairo_glitz_pattern_acquire_surface (cairo_pattern_t *pattern,
|
|||
{
|
||||
cairo_radial_pattern_t *grad = (cairo_radial_pattern_t *) pattern;
|
||||
|
||||
params[0] = grad->gradient.inner.x;
|
||||
params[1] = grad->gradient.inner.y;
|
||||
params[2] = grad->gradient.inner.radius;
|
||||
params[3] = grad->gradient.outer.x;
|
||||
params[4] = grad->gradient.outer.y;
|
||||
params[5] = grad->gradient.outer.radius;
|
||||
params[0] = grad->gradient.c1.x;
|
||||
params[1] = grad->gradient.c1.y;
|
||||
params[2] = grad->gradient.c1.radius;
|
||||
params[3] = grad->gradient.c2.x;
|
||||
params[4] = grad->gradient.c2.y;
|
||||
params[5] = grad->gradient.c2.radius;
|
||||
attr->filter = GLITZ_FILTER_RADIAL_GRADIENT;
|
||||
}
|
||||
|
||||
|
@ -976,7 +976,7 @@ _cairo_glitz_surface_fill_rectangles (void *abstract_dst,
|
|||
(glitz_rectangle_t *) rects, n_rects);
|
||||
} break;
|
||||
case CAIRO_OPERATOR_CLEAR: {
|
||||
static glitz_color_t glitz_color = { 0, 0, 0, 0 };
|
||||
static const glitz_color_t glitz_color = { 0, 0, 0, 0 };
|
||||
|
||||
glitz_set_rectangles (dst->surface, &glitz_color,
|
||||
(glitz_rectangle_t *) rects, n_rects);
|
||||
|
@ -1095,7 +1095,7 @@ _cairo_glitz_surface_composite_trapezoids (cairo_operator_t op,
|
|||
|
||||
if (op == CAIRO_OPERATOR_ADD || n_traps <= 1)
|
||||
{
|
||||
static glitz_color_t clear_black = { 0, 0, 0, 0 };
|
||||
static const glitz_color_t clear_black = { 0, 0, 0, 0 };
|
||||
glitz_color_t color;
|
||||
glitz_geometry_format_t format;
|
||||
int n_trap_added;
|
||||
|
@ -1941,7 +1941,7 @@ _cairo_glitz_surface_old_show_glyphs (cairo_scaled_font_t *scaled_font,
|
|||
int i, cached_glyphs = 0;
|
||||
int remaining_glyps = num_glyphs;
|
||||
glitz_float_t x1, y1, x2, y2;
|
||||
static glitz_vertex_format_t format = {
|
||||
static const glitz_vertex_format_t format = {
|
||||
GLITZ_PRIMITIVE_QUADS,
|
||||
GLITZ_DATA_TYPE_FLOAT,
|
||||
sizeof (glitz_float_t) * 4,
|
||||
|
|
|
@ -42,16 +42,9 @@
|
|||
#include "cairo-clip-private.h"
|
||||
#include "cairo-gstate-private.h"
|
||||
|
||||
static cairo_status_t
|
||||
_cairo_gstate_init (cairo_gstate_t *gstate,
|
||||
cairo_surface_t *target);
|
||||
|
||||
static cairo_status_t
|
||||
_cairo_gstate_init_copy (cairo_gstate_t *gstate, cairo_gstate_t *other);
|
||||
|
||||
static void
|
||||
_cairo_gstate_fini (cairo_gstate_t *gstate);
|
||||
|
||||
static cairo_status_t
|
||||
_cairo_gstate_ensure_font_face (cairo_gstate_t *gstate);
|
||||
|
||||
|
@ -67,40 +60,7 @@ _cairo_gstate_transform_glyphs_to_backend (cairo_gstate_t *gstate,
|
|||
int num_glyphs,
|
||||
cairo_glyph_t *transformed_glyphs);
|
||||
|
||||
/**
|
||||
* _cairo_gstate_create:
|
||||
* @target: a #cairo_surface_t, not NULL
|
||||
*
|
||||
* Create a new #cairo_gstate_t to draw to target with all graphics
|
||||
* state parameters set to defaults. gstate->next will be set to NULL
|
||||
* and may be used by the caller to chain #cairo_gstate_t objects
|
||||
* together.
|
||||
*
|
||||
* Return value: a new #cairo_gstate_t or NULL if there is
|
||||
* insufficient memory.
|
||||
**/
|
||||
cairo_gstate_t *
|
||||
_cairo_gstate_create (cairo_surface_t *target)
|
||||
{
|
||||
cairo_status_t status;
|
||||
cairo_gstate_t *gstate;
|
||||
|
||||
assert (target != NULL);
|
||||
|
||||
gstate = malloc (sizeof (cairo_gstate_t));
|
||||
if (gstate == NULL)
|
||||
return NULL;
|
||||
|
||||
status = _cairo_gstate_init (gstate, target);
|
||||
if (status) {
|
||||
free (gstate);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return gstate;
|
||||
}
|
||||
|
||||
static cairo_status_t
|
||||
cairo_status_t
|
||||
_cairo_gstate_init (cairo_gstate_t *gstate,
|
||||
cairo_surface_t *target)
|
||||
{
|
||||
|
@ -189,7 +149,7 @@ _cairo_gstate_init_copy (cairo_gstate_t *gstate, cairo_gstate_t *other)
|
|||
return CAIRO_STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
static void
|
||||
void
|
||||
_cairo_gstate_fini (cairo_gstate_t *gstate)
|
||||
{
|
||||
_cairo_stroke_style_fini (&gstate->stroke_style);
|
||||
|
@ -722,7 +682,7 @@ _cairo_gstate_backend_to_user_rectangle (cairo_gstate_t *gstate,
|
|||
|
||||
cairo_matrix_multiply (&matrix_inverse, &gstate->ctm_inverse,
|
||||
&gstate->target->device_transform_inverse);
|
||||
cairo_matrix_transform_bounding_box (&matrix_inverse,
|
||||
_cairo_matrix_transform_bounding_box (&matrix_inverse,
|
||||
x1, y1, x2, y2, is_tight);
|
||||
}
|
||||
|
||||
|
@ -955,6 +915,11 @@ _cairo_gstate_in_stroke (cairo_gstate_t *gstate,
|
|||
cairo_status_t status = CAIRO_STATUS_SUCCESS;
|
||||
cairo_traps_t traps;
|
||||
|
||||
if (gstate->stroke_style.line_width <= 0.0) {
|
||||
*inside_ret = FALSE;
|
||||
return CAIRO_STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
_cairo_gstate_user_to_backend (gstate, &x, &y);
|
||||
|
||||
_cairo_traps_init (&traps);
|
||||
|
@ -1073,11 +1038,22 @@ _cairo_gstate_traps_extents_to_user_rectangle (cairo_gstate_t *gstate,
|
|||
|
||||
if (extents.p1.x >= extents.p2.x || extents.p1.y >= extents.p2.y) {
|
||||
/* no traps, so we actually won't draw anything */
|
||||
*x1 = *y1 = *x2 = *y2 = 0;
|
||||
if (x1)
|
||||
*x1 = 0.0;
|
||||
if (y1)
|
||||
*y1 = 0.0;
|
||||
if (x2)
|
||||
*x2 = 0.0;
|
||||
if (y2)
|
||||
*y2 = 0.0;
|
||||
} else {
|
||||
if (x1)
|
||||
*x1 = _cairo_fixed_to_double (extents.p1.x);
|
||||
if (y1)
|
||||
*y1 = _cairo_fixed_to_double (extents.p1.y);
|
||||
if (x2)
|
||||
*x2 = _cairo_fixed_to_double (extents.p2.x);
|
||||
if (y2)
|
||||
*y2 = _cairo_fixed_to_double (extents.p2.y);
|
||||
|
||||
_cairo_gstate_backend_to_user_rectangle (gstate, x1, y1, x2, y2, NULL);
|
||||
|
@ -1093,6 +1069,18 @@ _cairo_gstate_stroke_extents (cairo_gstate_t *gstate,
|
|||
cairo_status_t status;
|
||||
cairo_traps_t traps;
|
||||
|
||||
if (gstate->stroke_style.line_width <= 0.0) {
|
||||
if (x1)
|
||||
*x1 = 0.0;
|
||||
if (y1)
|
||||
*y1 = 0.0;
|
||||
if (x2)
|
||||
*x2 = 0.0;
|
||||
if (y2)
|
||||
*y2 = 0.0;
|
||||
return CAIRO_STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
_cairo_traps_init (&traps);
|
||||
|
||||
status = _cairo_path_fixed_stroke_to_traps (path,
|
||||
|
@ -1166,9 +1154,13 @@ _cairo_gstate_clip_extents (cairo_gstate_t *gstate,
|
|||
if (status)
|
||||
return status;
|
||||
|
||||
if (x1)
|
||||
*x1 = extents.x;
|
||||
if (y1)
|
||||
*y1 = extents.y;
|
||||
if (x2)
|
||||
*x2 = extents.x + extents.width;
|
||||
if (y2)
|
||||
*y2 = extents.y + extents.height;
|
||||
|
||||
_cairo_gstate_backend_to_user_rectangle (gstate, x1, y1, x2, y2, NULL);
|
||||
|
@ -1271,6 +1263,21 @@ _cairo_gstate_get_font_face (cairo_gstate_t *gstate,
|
|||
return CAIRO_STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
cairo_status_t
|
||||
_cairo_gstate_get_scaled_font (cairo_gstate_t *gstate,
|
||||
cairo_scaled_font_t **scaled_font)
|
||||
{
|
||||
cairo_status_t status;
|
||||
|
||||
status = _cairo_gstate_ensure_scaled_font (gstate);
|
||||
if (status)
|
||||
return status;
|
||||
|
||||
*scaled_font = gstate->scaled_font;
|
||||
|
||||
return CAIRO_STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
/*
|
||||
* Like everything else in this file, fonts involve Too Many Coordinate Spaces;
|
||||
* it is easy to get confused about what's going on.
|
||||
|
|
|
@ -1116,6 +1116,7 @@ _cairo_image_surface_clone (cairo_image_surface_t *surface,
|
|||
cairo_image_surface_create (format,
|
||||
surface->width, surface->height);
|
||||
|
||||
/* Use _cairo_surface_composite directly */
|
||||
cr = cairo_create (&clone->base);
|
||||
cairo_surface_get_device_offset (&surface->base, &x, &y);
|
||||
cairo_set_source_surface (cr, &surface->base, x, y);
|
||||
|
|
|
@ -356,7 +356,7 @@ cairo_matrix_transform_point (const cairo_matrix_t *matrix, double *x, double *y
|
|||
slim_hidden_def(cairo_matrix_transform_point);
|
||||
|
||||
void
|
||||
cairo_matrix_transform_bounding_box (const cairo_matrix_t *matrix,
|
||||
_cairo_matrix_transform_bounding_box (const cairo_matrix_t *matrix,
|
||||
double *x1, double *y1,
|
||||
double *x2, double *y2,
|
||||
cairo_bool_t *is_tight)
|
||||
|
@ -417,7 +417,6 @@ cairo_matrix_transform_bounding_box (const cairo_matrix_t *matrix,
|
|||
quad_x[2] == quad_x[0] && quad_y[2] == quad_y[3]);
|
||||
}
|
||||
}
|
||||
slim_hidden_def(cairo_matrix_transform_bounding_box);
|
||||
|
||||
static void
|
||||
_cairo_matrix_scalar_multiply (cairo_matrix_t *matrix, double scalar)
|
||||
|
|
Разница между файлами не показана из-за своего большого размера
Загрузить разницу
|
@ -1,80 +0,0 @@
|
|||
/* cairo - a vector graphics library with display and print output
|
||||
*
|
||||
* Copyright © 2006 Mozilla Corporation
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it either under the terms of the GNU Lesser General Public
|
||||
* License version 2.1 as published by the Free Software Foundation
|
||||
* (the "LGPL") or, at your option, under the terms of the Mozilla
|
||||
* Public License Version 1.1 (the "MPL"). If you do not alter this
|
||||
* notice, a recipient may use your version of this file under either
|
||||
* the MPL or the LGPL.
|
||||
*
|
||||
* You should have received a copy of the LGPL along with this library
|
||||
* in the file COPYING-LGPL-2.1; if not, write to the Free Software
|
||||
* Foundation, Inc., 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 Mozilla Corporation.
|
||||
*
|
||||
* Contributor(s):
|
||||
* Vladimir Vukicevic <vladimir@mozilla.com>
|
||||
*/
|
||||
|
||||
#ifndef CAIRO_NQUARTZ_H
|
||||
#define CAIRO_NQUARTZ_H
|
||||
|
||||
#include <cairo.h>
|
||||
|
||||
#if CAIRO_HAS_NQUARTZ_SURFACE
|
||||
|
||||
#include <Carbon/Carbon.h>
|
||||
|
||||
#include <AGL/agl.h>
|
||||
|
||||
CAIRO_BEGIN_DECLS
|
||||
|
||||
cairo_public cairo_surface_t *
|
||||
cairo_nquartz_surface_create (cairo_format_t format,
|
||||
unsigned int width,
|
||||
unsigned int height);
|
||||
|
||||
#ifdef CAIRO_NQUARTZ_SUPPORT_AGL
|
||||
cairo_public cairo_surface_t *
|
||||
cairo_nquartz_surface_create_for_agl_context (AGLContext aglContext,
|
||||
unsigned int width,
|
||||
unsigned int height,
|
||||
cairo_bool_t y_grows_down);
|
||||
#endif
|
||||
|
||||
cairo_public cairo_surface_t *
|
||||
cairo_nquartz_surface_create_for_cg_context (CGContextRef cgContext,
|
||||
unsigned int width,
|
||||
unsigned int height,
|
||||
cairo_bool_t y_grows_down);
|
||||
|
||||
cairo_public cairo_bool_t
|
||||
cairo_surface_is_nquartz (cairo_surface_t *surf);
|
||||
|
||||
cairo_public CGContextRef
|
||||
cairo_nquartz_surface_get_cg_context (cairo_surface_t *surf);
|
||||
|
||||
CAIRO_END_DECLS
|
||||
|
||||
#else /* CAIRO_HAS_NQUARTZ_SURFACE */
|
||||
# error Cairo was not compiled with support for the nquartz backend
|
||||
#endif /* CAIRO_HAS_NQUARTZ_SURFACE */
|
||||
|
||||
#endif /* CAIRO_NQUARTZ_H */
|
|
@ -69,11 +69,11 @@
|
|||
static int cairo_os2_initialization_count = 0;
|
||||
|
||||
/* The mutex semaphores Cairo uses all around: */
|
||||
HMTX cairo_toy_font_face_hash_table_mutex = 0;
|
||||
HMTX cairo_scaled_font_map_mutex = 0;
|
||||
HMTX _cairo_scaled_font_map_mutex = 0;
|
||||
HMTX _global_image_glyph_cache_mutex = 0;
|
||||
HMTX _cairo_font_face_mutex = 0;
|
||||
#ifdef CAIRO_HAS_FT_FONT
|
||||
HMTX cairo_ft_unscaled_font_map_mutex = 0;
|
||||
HMTX _cairo_ft_unscaled_font_map_mutex = 0;
|
||||
#endif
|
||||
|
||||
static void inline
|
||||
|
@ -106,13 +106,13 @@ cairo_os2_init (void)
|
|||
/* Create the mutex semaphores we'll use! */
|
||||
|
||||
/* cairo-font.c: */
|
||||
DosCreateMutexSem (NULL, &cairo_toy_font_face_hash_table_mutex, 0, FALSE);
|
||||
DosCreateMutexSem (NULL, &cairo_scaled_font_map_mutex, 0, FALSE);
|
||||
DosCreateMutexSem (NULL, &_cairo_scaled_font_map_mutex, 0, FALSE);
|
||||
DosCreateMutexSem (NULL, &_global_image_glyph_cache_mutex, 0, FALSE);
|
||||
DosCreateMutexSem (NULL, &_cairo_font_face_mutex, 0, FALSE);
|
||||
|
||||
#ifdef CAIRO_HAS_FT_FONT
|
||||
/* cairo-ft-font.c: */
|
||||
DosCreateMutexSem (NULL, &cairo_ft_unscaled_font_map_mutex, 0, FALSE);
|
||||
DosCreateMutexSem (NULL, &_cairo_ft_unscaled_font_map_mutex, 0, FALSE);
|
||||
#endif
|
||||
|
||||
/* Initialize FontConfig */
|
||||
|
@ -139,24 +139,24 @@ cairo_os2_fini (void)
|
|||
|
||||
/* Destroy the mutex semaphores we've created! */
|
||||
/* cairo-font.c: */
|
||||
if (cairo_toy_font_face_hash_table_mutex) {
|
||||
DosCloseMutexSem (cairo_toy_font_face_hash_table_mutex);
|
||||
cairo_toy_font_face_hash_table_mutex = 0;
|
||||
}
|
||||
if (cairo_scaled_font_map_mutex) {
|
||||
DosCloseMutexSem (cairo_scaled_font_map_mutex);
|
||||
cairo_scaled_font_map_mutex = 0;
|
||||
if (_cairo_scaled_font_map_mutex) {
|
||||
DosCloseMutexSem (_cairo_scaled_font_map_mutex);
|
||||
_cairo_scaled_font_map_mutex = 0;
|
||||
}
|
||||
if (_global_image_glyph_cache_mutex) {
|
||||
DosCloseMutexSem (_global_image_glyph_cache_mutex);
|
||||
_global_image_glyph_cache_mutex = 0;
|
||||
}
|
||||
if (_cairo_font_face_mutex) {
|
||||
DosCloseMutexSem (_cairo_font_face_mutex);
|
||||
_cairo_font_face_mutex = 0;
|
||||
}
|
||||
|
||||
#ifdef CAIRO_HAS_FT_FONT
|
||||
/* cairo-ft-font.c: */
|
||||
if (cairo_ft_unscaled_font_map_mutex) {
|
||||
DosCloseMutexSem (cairo_ft_unscaled_font_map_mutex);
|
||||
cairo_ft_unscaled_font_map_mutex = 0;
|
||||
if (_cairo_ft_unscaled_font_map_mutex) {
|
||||
DosCloseMutexSem (_cairo_ft_unscaled_font_map_mutex);
|
||||
_cairo_ft_unscaled_font_map_mutex = 0;
|
||||
}
|
||||
#endif
|
||||
|
||||
|
|
|
@ -194,6 +194,8 @@ cairo_os2_surface_set_manual_window_refresh (cairo_surface_t *surface,
|
|||
cairo_public cairo_bool_t
|
||||
cairo_os2_surface_get_manual_window_refresh (cairo_surface_t *surface);
|
||||
|
||||
#else /* CAIRO_HAS_OS2_SURFACE */
|
||||
# error Cairo was not compiled with support for the OS/2 backend
|
||||
#endif /* CAIRO_HAS_OS2_SURFACE */
|
||||
|
||||
CAIRO_END_DECLS
|
||||
|
|
|
@ -224,6 +224,10 @@ _cairo_dtostr (char *buffer, size_t size, double d)
|
|||
char *p;
|
||||
int decimal_len;
|
||||
|
||||
/* Omit the minus sign from negative zero. */
|
||||
if (d == 0.0)
|
||||
d = 0.0;
|
||||
|
||||
snprintf (buffer, size, "%f", d);
|
||||
|
||||
locale_data = localeconv ();
|
||||
|
|
|
@ -70,6 +70,7 @@ typedef struct _cairo_paginated_surface {
|
|||
* fallbacks. */
|
||||
cairo_surface_t *meta;
|
||||
|
||||
int page_num;
|
||||
cairo_bool_t page_is_blank;
|
||||
|
||||
} cairo_paginated_surface_t;
|
||||
|
@ -122,6 +123,7 @@ _cairo_paginated_surface_create (cairo_surface_t *target,
|
|||
if (cairo_surface_status (surface->meta))
|
||||
goto FAIL_CLEANUP_SURFACE;
|
||||
|
||||
surface->page_num = 1;
|
||||
surface->page_is_blank = TRUE;
|
||||
|
||||
return &surface->base;
|
||||
|
@ -155,12 +157,22 @@ static cairo_status_t
|
|||
_cairo_paginated_surface_finish (void *abstract_surface)
|
||||
{
|
||||
cairo_paginated_surface_t *surface = abstract_surface;
|
||||
cairo_status_t status = CAIRO_STATUS_SUCCESS;
|
||||
|
||||
cairo_surface_destroy (surface->meta);
|
||||
if (surface->page_is_blank == FALSE || surface->page_num == 1)
|
||||
status = _cairo_paginated_surface_show_page (abstract_surface);
|
||||
|
||||
if (status == CAIRO_STATUS_SUCCESS)
|
||||
cairo_surface_finish (surface->target);
|
||||
|
||||
if (status == CAIRO_STATUS_SUCCESS)
|
||||
cairo_surface_finish (surface->meta);
|
||||
|
||||
cairo_surface_destroy (surface->target);
|
||||
|
||||
return CAIRO_STATUS_SUCCESS;
|
||||
cairo_surface_destroy (surface->meta);
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
static cairo_surface_t *
|
||||
|
@ -288,6 +300,8 @@ _cairo_paginated_surface_copy_page (void *abstract_surface)
|
|||
|
||||
_paint_page (surface);
|
||||
|
||||
surface->page_num++;
|
||||
|
||||
/* XXX: It might make sense to add some suport here for calling
|
||||
* _cairo_surface_copy_page on the target surface. It would be an
|
||||
* optimization for the output, (so that PostScript could include
|
||||
|
@ -296,9 +310,7 @@ _cairo_paginated_surface_copy_page (void *abstract_surface)
|
|||
* show_page and we implement the copying by simply not destroying
|
||||
* the meta-surface. */
|
||||
|
||||
_cairo_surface_show_page (surface->target);
|
||||
|
||||
return CAIRO_STATUS_SUCCESS;
|
||||
return _cairo_surface_show_page (surface->target);
|
||||
}
|
||||
|
||||
static cairo_int_status_t
|
||||
|
@ -322,6 +334,7 @@ _cairo_paginated_surface_show_page (void *abstract_surface)
|
|||
if (cairo_surface_status (surface->meta))
|
||||
return cairo_surface_status (surface->meta);
|
||||
|
||||
surface->page_num++;
|
||||
surface->page_is_blank = TRUE;
|
||||
|
||||
return CAIRO_STATUS_SUCCESS;
|
||||
|
@ -442,6 +455,7 @@ _cairo_paginated_surface_show_glyphs (void *abstract_surface,
|
|||
cairo_scaled_font_t *scaled_font)
|
||||
{
|
||||
cairo_paginated_surface_t *surface = abstract_surface;
|
||||
cairo_int_status_t status;
|
||||
|
||||
/* Optimize away erasing of nothing. */
|
||||
if (surface->page_is_blank && op == CAIRO_OPERATOR_CLEAR)
|
||||
|
@ -449,9 +463,23 @@ _cairo_paginated_surface_show_glyphs (void *abstract_surface,
|
|||
|
||||
surface->page_is_blank = FALSE;
|
||||
|
||||
return _cairo_surface_show_glyphs (surface->meta, op, source,
|
||||
/* Since this is a "wrapping" surface, we're calling back into
|
||||
* _cairo_surface_show_glyphs from within a call to the same.
|
||||
* Since _cairo_surface_show_glyphs acquires a mutex, we release
|
||||
* and re-acquire the mutex around this nested call.
|
||||
*
|
||||
* Yes, this is ugly, but we consider it pragmatic as compared to
|
||||
* adding locking code to all 18 surface-backend-specific
|
||||
* show_glyphs functions, (which would get less testing and likely
|
||||
* lead to bugs).
|
||||
*/
|
||||
CAIRO_MUTEX_UNLOCK (scaled_font->mutex);
|
||||
status = _cairo_surface_show_glyphs (surface->meta, op, source,
|
||||
glyphs, num_glyphs,
|
||||
scaled_font);
|
||||
CAIRO_MUTEX_LOCK (scaled_font->mutex);
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
static cairo_surface_t *
|
||||
|
|
|
@ -35,6 +35,7 @@
|
|||
*/
|
||||
|
||||
#include "cairoint.h"
|
||||
#include "cairo-path-fixed-private.h"
|
||||
|
||||
typedef struct cairo_filler {
|
||||
double tolerance;
|
||||
|
@ -169,6 +170,10 @@ _cairo_filler_close_path (void *closure)
|
|||
return CAIRO_STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
static cairo_int_status_t
|
||||
_cairo_path_fixed_fill_rectangle (cairo_path_fixed_t *path,
|
||||
cairo_traps_t *traps);
|
||||
|
||||
cairo_status_t
|
||||
_cairo_path_fixed_fill_to_traps (cairo_path_fixed_t *path,
|
||||
cairo_fill_rule_t fill_rule,
|
||||
|
@ -178,6 +183,12 @@ _cairo_path_fixed_fill_to_traps (cairo_path_fixed_t *path,
|
|||
cairo_status_t status = CAIRO_STATUS_SUCCESS;
|
||||
cairo_filler_t filler;
|
||||
|
||||
/* Before we do anything else, we use a special-case filler for
|
||||
* a device-axis aligned rectangle if possible. */
|
||||
status = _cairo_path_fixed_fill_rectangle (path, traps);
|
||||
if (status != CAIRO_INT_STATUS_UNSUPPORTED)
|
||||
return status;
|
||||
|
||||
_cairo_filler_init (&filler, tolerance, traps);
|
||||
|
||||
status = _cairo_path_fixed_interpret (path,
|
||||
|
@ -205,3 +216,84 @@ BAIL:
|
|||
|
||||
return status;
|
||||
}
|
||||
|
||||
/* This special-case filler supports only a path that describes a
|
||||
* device-axis aligned rectangle. It exists to avoid the overhead of
|
||||
* the general tessellator when drawing very common rectangles.
|
||||
*
|
||||
* If the path described anything but a device-axis aligned rectangle,
|
||||
* this function will return CAIRO_INT_STATUS_UNSUPPORTED.
|
||||
*/
|
||||
static cairo_int_status_t
|
||||
_cairo_path_fixed_fill_rectangle (cairo_path_fixed_t *path,
|
||||
cairo_traps_t *traps)
|
||||
{
|
||||
cairo_path_buf_t *buf = path->buf_head;
|
||||
int final;
|
||||
|
||||
/* Ensure the path has the operators we expect for a rectangular path.
|
||||
*/
|
||||
if (buf == NULL || buf->num_ops < 5)
|
||||
return CAIRO_INT_STATUS_UNSUPPORTED;
|
||||
|
||||
if (buf->op[0] != CAIRO_PATH_OP_MOVE_TO ||
|
||||
buf->op[1] != CAIRO_PATH_OP_LINE_TO ||
|
||||
buf->op[2] != CAIRO_PATH_OP_LINE_TO ||
|
||||
buf->op[3] != CAIRO_PATH_OP_LINE_TO)
|
||||
{
|
||||
return CAIRO_INT_STATUS_UNSUPPORTED;
|
||||
}
|
||||
|
||||
/* Now, there are choices. The rectangle might end with a LINE_TO
|
||||
* (to the original point), but this isn't required. If it
|
||||
* doesn't, then it must end with a CLOSE_PATH. */
|
||||
if (buf->op[4] == CAIRO_PATH_OP_LINE_TO) {
|
||||
if (buf->points[4].x != buf->points[0].x ||
|
||||
buf->points[4].y != buf->points[0].y)
|
||||
{
|
||||
return CAIRO_INT_STATUS_UNSUPPORTED;
|
||||
}
|
||||
} else if (buf->op[4] != CAIRO_PATH_OP_CLOSE_PATH) {
|
||||
return CAIRO_INT_STATUS_UNSUPPORTED;
|
||||
}
|
||||
|
||||
/* Finally, a trailing CLOSE_PATH or MOVE_TO after the rectangle
|
||||
* is fine. But anything more than that means we must return
|
||||
* unsupported. */
|
||||
final = 5;
|
||||
if (final < buf->num_ops &&
|
||||
buf->op[final] == CAIRO_PATH_OP_CLOSE_PATH)
|
||||
{
|
||||
final++;
|
||||
}
|
||||
if (final < buf->num_ops &&
|
||||
buf->op[final] == CAIRO_PATH_OP_MOVE_TO)
|
||||
{
|
||||
final++;
|
||||
}
|
||||
if (final < buf->num_ops)
|
||||
return CAIRO_INT_STATUS_UNSUPPORTED;
|
||||
|
||||
/* Now that we've verified the operators, we must ensure that the
|
||||
* path coordinates are consistent with a rectangle. There are two
|
||||
* choices here. */
|
||||
if (buf->points[0].y == buf->points[1].y &&
|
||||
buf->points[1].x == buf->points[2].x &&
|
||||
buf->points[2].y == buf->points[3].y &&
|
||||
buf->points[3].x == buf->points[0].x)
|
||||
{
|
||||
return _cairo_traps_tessellate_convex_quad (traps,
|
||||
buf->points);
|
||||
}
|
||||
|
||||
if (buf->points[0].x == buf->points[1].x &&
|
||||
buf->points[1].y == buf->points[2].y &&
|
||||
buf->points[2].x == buf->points[3].x &&
|
||||
buf->points[3].y == buf->points[0].y)
|
||||
{
|
||||
return _cairo_traps_tessellate_convex_quad (traps,
|
||||
buf->points);
|
||||
}
|
||||
|
||||
return CAIRO_INT_STATUS_UNSUPPORTED;
|
||||
}
|
||||
|
|
|
@ -42,34 +42,30 @@ typedef enum cairo_path_op {
|
|||
CAIRO_PATH_OP_CURVE_TO = 2,
|
||||
CAIRO_PATH_OP_CLOSE_PATH = 3
|
||||
} __attribute__ ((packed)) cairo_path_op_t; /* Don't want 32 bits if we can avoid it. */
|
||||
/* XXX Shall we just not use char instead of hoping for __attribute__ working? */
|
||||
|
||||
#define CAIRO_PATH_BUF_SIZE 64
|
||||
/* make cairo_path_fixed fit a 512 bytes. about 50 items */
|
||||
#define CAIRO_PATH_BUF_SIZE ((512 - 12 * sizeof (void*)) \
|
||||
/ (sizeof (cairo_point_t) + sizeof (cairo_path_op_t)))
|
||||
|
||||
typedef struct _cairo_path_op_buf {
|
||||
typedef struct _cairo_path_buf {
|
||||
struct _cairo_path_buf *next, *prev;
|
||||
int num_ops;
|
||||
cairo_path_op_t op[CAIRO_PATH_BUF_SIZE];
|
||||
|
||||
struct _cairo_path_op_buf *next, *prev;
|
||||
} cairo_path_op_buf_t;
|
||||
|
||||
typedef struct _cairo_path_arg_buf {
|
||||
int num_points;
|
||||
|
||||
cairo_path_op_t op[CAIRO_PATH_BUF_SIZE];
|
||||
cairo_point_t points[CAIRO_PATH_BUF_SIZE];
|
||||
|
||||
struct _cairo_path_arg_buf *next, *prev;
|
||||
} cairo_path_arg_buf_t;
|
||||
} cairo_path_buf_t;
|
||||
|
||||
struct _cairo_path_fixed {
|
||||
cairo_path_op_buf_t *op_buf_head;
|
||||
cairo_path_op_buf_t *op_buf_tail;
|
||||
|
||||
cairo_path_arg_buf_t *arg_buf_head;
|
||||
cairo_path_arg_buf_t *arg_buf_tail;
|
||||
|
||||
cairo_point_t last_move_point;
|
||||
cairo_point_t current_point;
|
||||
unsigned int has_current_point : 1;
|
||||
unsigned int has_curve_to : 1;
|
||||
|
||||
cairo_path_buf_t *buf_tail;
|
||||
cairo_path_buf_t buf_head[1];
|
||||
};
|
||||
|
||||
#endif /* CAIRO_PATH_FIXED_PRIVATE_H */
|
||||
|
|
|
@ -48,42 +48,33 @@ _cairo_path_fixed_add (cairo_path_fixed_t *path,
|
|||
int num_points);
|
||||
|
||||
static void
|
||||
_cairo_path_fixed_add_op_buf (cairo_path_fixed_t *path,
|
||||
cairo_path_op_buf_t *op_buf);
|
||||
_cairo_path_fixed_add_buf (cairo_path_fixed_t *path,
|
||||
cairo_path_buf_t *buf);
|
||||
|
||||
static cairo_path_buf_t *
|
||||
_cairo_path_buf_create (void);
|
||||
|
||||
static void
|
||||
_cairo_path_fixed_add_arg_buf (cairo_path_fixed_t *path,
|
||||
cairo_path_arg_buf_t *arg_buf);
|
||||
|
||||
static cairo_path_op_buf_t *
|
||||
_cairo_path_op_buf_create (void);
|
||||
_cairo_path_buf_destroy (cairo_path_buf_t *buf);
|
||||
|
||||
static void
|
||||
_cairo_path_op_buf_destroy (cairo_path_op_buf_t *op_buf);
|
||||
|
||||
static void
|
||||
_cairo_path_op_buf_add_op (cairo_path_op_buf_t *op_buf,
|
||||
_cairo_path_buf_add_op (cairo_path_buf_t *buf,
|
||||
cairo_path_op_t op);
|
||||
|
||||
static cairo_path_arg_buf_t *
|
||||
_cairo_path_arg_buf_create (void);
|
||||
|
||||
static void
|
||||
_cairo_path_arg_buf_destroy (cairo_path_arg_buf_t *arg_buf);
|
||||
|
||||
static void
|
||||
_cairo_path_arg_buf_add_points (cairo_path_arg_buf_t *arg_buf,
|
||||
_cairo_path_buf_add_points (cairo_path_buf_t *buf,
|
||||
cairo_point_t *points,
|
||||
int num_points);
|
||||
|
||||
void
|
||||
_cairo_path_fixed_init (cairo_path_fixed_t *path)
|
||||
{
|
||||
path->op_buf_head = NULL;
|
||||
path->op_buf_tail = NULL;
|
||||
path->buf_head->next = NULL;
|
||||
path->buf_head->prev = NULL;
|
||||
path->buf_tail = path->buf_head;
|
||||
|
||||
path->arg_buf_head = NULL;
|
||||
path->arg_buf_tail = NULL;
|
||||
path->buf_head->num_ops = 0;
|
||||
path->buf_head->num_points = 0;
|
||||
|
||||
path->current_point.x = 0;
|
||||
path->current_point.y = 0;
|
||||
|
@ -96,8 +87,7 @@ cairo_status_t
|
|||
_cairo_path_fixed_init_copy (cairo_path_fixed_t *path,
|
||||
cairo_path_fixed_t *other)
|
||||
{
|
||||
cairo_path_op_buf_t *op_buf, *other_op_buf;
|
||||
cairo_path_arg_buf_t *arg_buf, *other_arg_buf;
|
||||
cairo_path_buf_t *buf, *other_buf;
|
||||
|
||||
_cairo_path_fixed_init (path);
|
||||
path->current_point = other->current_point;
|
||||
|
@ -105,30 +95,23 @@ _cairo_path_fixed_init_copy (cairo_path_fixed_t *path,
|
|||
path->has_curve_to = other->has_curve_to;
|
||||
path->last_move_point = other->last_move_point;
|
||||
|
||||
for (other_op_buf = other->op_buf_head;
|
||||
other_op_buf;
|
||||
other_op_buf = other_op_buf->next)
|
||||
path->buf_head->num_ops = other->buf_head->num_ops;
|
||||
path->buf_head->num_points = other->buf_head->num_points;
|
||||
memcpy (path->buf_head->op, other->buf_head->op,
|
||||
other->buf_head->num_ops * sizeof (other->buf_head->op[0]));
|
||||
memcpy (path->buf_head->points, other->buf_head->points,
|
||||
other->buf_head->num_points * sizeof (other->buf_head->points[0]));
|
||||
for (other_buf = other->buf_head->next;
|
||||
other_buf;
|
||||
other_buf = other_buf->next)
|
||||
{
|
||||
op_buf = _cairo_path_op_buf_create ();
|
||||
if (op_buf == NULL) {
|
||||
buf = _cairo_path_buf_create ();
|
||||
if (buf == NULL) {
|
||||
_cairo_path_fixed_fini (path);
|
||||
return CAIRO_STATUS_NO_MEMORY;
|
||||
}
|
||||
memcpy (op_buf, other_op_buf, sizeof (cairo_path_op_buf_t));
|
||||
_cairo_path_fixed_add_op_buf (path, op_buf);
|
||||
}
|
||||
|
||||
for (other_arg_buf = other->arg_buf_head;
|
||||
other_arg_buf;
|
||||
other_arg_buf = other_arg_buf->next)
|
||||
{
|
||||
arg_buf = _cairo_path_arg_buf_create ();
|
||||
if (arg_buf == NULL) {
|
||||
_cairo_path_fixed_fini (path);
|
||||
return CAIRO_STATUS_NO_MEMORY;
|
||||
}
|
||||
memcpy (arg_buf, other_arg_buf, sizeof (cairo_path_arg_buf_t));
|
||||
_cairo_path_fixed_add_arg_buf (path, arg_buf);
|
||||
memcpy (buf, other_buf, sizeof (cairo_path_buf_t));
|
||||
_cairo_path_fixed_add_buf (path, buf);
|
||||
}
|
||||
|
||||
return CAIRO_STATUS_SUCCESS;
|
||||
|
@ -148,22 +131,19 @@ _cairo_path_fixed_create (void)
|
|||
void
|
||||
_cairo_path_fixed_fini (cairo_path_fixed_t *path)
|
||||
{
|
||||
cairo_path_op_buf_t *op_buf;
|
||||
cairo_path_arg_buf_t *arg_buf;
|
||||
cairo_path_buf_t *buf;
|
||||
|
||||
while (path->op_buf_head) {
|
||||
op_buf = path->op_buf_head;
|
||||
path->op_buf_head = op_buf->next;
|
||||
_cairo_path_op_buf_destroy (op_buf);
|
||||
buf = path->buf_head->next;
|
||||
while (buf) {
|
||||
cairo_path_buf_t *this = buf;
|
||||
buf = buf->next;
|
||||
_cairo_path_buf_destroy (this);
|
||||
}
|
||||
path->op_buf_tail = NULL;
|
||||
|
||||
while (path->arg_buf_head) {
|
||||
arg_buf = path->arg_buf_head;
|
||||
path->arg_buf_head = arg_buf->next;
|
||||
_cairo_path_arg_buf_destroy (arg_buf);
|
||||
}
|
||||
path->arg_buf_tail = NULL;
|
||||
path->buf_head->next = NULL;
|
||||
path->buf_head->prev = NULL;
|
||||
path->buf_tail = path->buf_head;
|
||||
path->buf_head->num_ops = 0;
|
||||
path->buf_head->num_points = 0;
|
||||
|
||||
path->has_current_point = FALSE;
|
||||
path->has_curve_to = FALSE;
|
||||
|
@ -189,11 +169,11 @@ _cairo_path_fixed_move_to (cairo_path_fixed_t *path,
|
|||
|
||||
/* If the previous op was also a MOVE_TO, then just change its
|
||||
* point rather than adding a new op. */
|
||||
if (path->op_buf_tail && path->op_buf_tail->num_ops &&
|
||||
path->op_buf_tail->op[path->op_buf_tail->num_ops - 1] == CAIRO_PATH_OP_MOVE_TO)
|
||||
if (path->buf_tail && path->buf_tail->num_ops &&
|
||||
path->buf_tail->op[path->buf_tail->num_ops - 1] == CAIRO_PATH_OP_MOVE_TO)
|
||||
{
|
||||
cairo_point_t *last_move_to_point;
|
||||
last_move_to_point = &path->arg_buf_tail->points[path->arg_buf_tail->num_points - 1];
|
||||
last_move_to_point = &path->buf_tail->points[path->buf_tail->num_points - 1];
|
||||
*last_move_to_point = point;
|
||||
} else {
|
||||
status = _cairo_path_fixed_add (path, CAIRO_PATH_OP_MOVE_TO, &point, 1);
|
||||
|
@ -376,133 +356,77 @@ _cairo_path_fixed_add (cairo_path_fixed_t *path,
|
|||
cairo_point_t *points,
|
||||
int num_points)
|
||||
{
|
||||
if (path->op_buf_tail == NULL ||
|
||||
path->op_buf_tail->num_ops + 1 > CAIRO_PATH_BUF_SIZE)
|
||||
if (path->buf_tail->num_ops + 1 > CAIRO_PATH_BUF_SIZE ||
|
||||
path->buf_tail->num_points + num_points > CAIRO_PATH_BUF_SIZE)
|
||||
{
|
||||
cairo_path_op_buf_t *op_buf;
|
||||
cairo_path_buf_t *buf;
|
||||
|
||||
op_buf = _cairo_path_op_buf_create ();
|
||||
if (op_buf == NULL)
|
||||
buf = _cairo_path_buf_create ();
|
||||
if (buf == NULL)
|
||||
return CAIRO_STATUS_NO_MEMORY;
|
||||
|
||||
_cairo_path_fixed_add_op_buf (path, op_buf);
|
||||
_cairo_path_fixed_add_buf (path, buf);
|
||||
}
|
||||
|
||||
_cairo_path_op_buf_add_op (path->op_buf_tail, op);
|
||||
|
||||
if (path->arg_buf_tail == NULL ||
|
||||
path->arg_buf_tail->num_points + num_points > CAIRO_PATH_BUF_SIZE)
|
||||
{
|
||||
cairo_path_arg_buf_t *arg_buf;
|
||||
|
||||
arg_buf = _cairo_path_arg_buf_create ();
|
||||
|
||||
if (arg_buf == NULL)
|
||||
return CAIRO_STATUS_NO_MEMORY;
|
||||
|
||||
_cairo_path_fixed_add_arg_buf (path, arg_buf);
|
||||
}
|
||||
|
||||
_cairo_path_arg_buf_add_points (path->arg_buf_tail, points, num_points);
|
||||
_cairo_path_buf_add_op (path->buf_tail, op);
|
||||
_cairo_path_buf_add_points (path->buf_tail, points, num_points);
|
||||
|
||||
return CAIRO_STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
static void
|
||||
_cairo_path_fixed_add_op_buf (cairo_path_fixed_t *path,
|
||||
cairo_path_op_buf_t *op_buf)
|
||||
_cairo_path_fixed_add_buf (cairo_path_fixed_t *path,
|
||||
cairo_path_buf_t *buf)
|
||||
{
|
||||
op_buf->next = NULL;
|
||||
op_buf->prev = path->op_buf_tail;
|
||||
buf->next = NULL;
|
||||
buf->prev = path->buf_tail;
|
||||
|
||||
if (path->op_buf_tail) {
|
||||
path->op_buf_tail->next = op_buf;
|
||||
} else {
|
||||
path->op_buf_head = op_buf;
|
||||
path->buf_tail->next = buf;
|
||||
path->buf_tail = buf;
|
||||
}
|
||||
|
||||
path->op_buf_tail = op_buf;
|
||||
static cairo_path_buf_t *
|
||||
_cairo_path_buf_create (void)
|
||||
{
|
||||
cairo_path_buf_t *buf;
|
||||
|
||||
buf = malloc (sizeof (cairo_path_buf_t));
|
||||
|
||||
if (buf) {
|
||||
buf->next = NULL;
|
||||
buf->prev = NULL;
|
||||
buf->num_ops = 0;
|
||||
buf->num_points = 0;
|
||||
}
|
||||
|
||||
return buf;
|
||||
}
|
||||
|
||||
static void
|
||||
_cairo_path_fixed_add_arg_buf (cairo_path_fixed_t *path,
|
||||
cairo_path_arg_buf_t *arg_buf)
|
||||
_cairo_path_buf_destroy (cairo_path_buf_t *buf)
|
||||
{
|
||||
arg_buf->next = NULL;
|
||||
arg_buf->prev = path->arg_buf_tail;
|
||||
|
||||
if (path->arg_buf_tail) {
|
||||
path->arg_buf_tail->next = arg_buf;
|
||||
} else {
|
||||
path->arg_buf_head = arg_buf;
|
||||
}
|
||||
|
||||
path->arg_buf_tail = arg_buf;
|
||||
}
|
||||
|
||||
static cairo_path_op_buf_t *
|
||||
_cairo_path_op_buf_create (void)
|
||||
{
|
||||
cairo_path_op_buf_t *op_buf;
|
||||
|
||||
op_buf = malloc (sizeof (cairo_path_op_buf_t));
|
||||
|
||||
if (op_buf) {
|
||||
op_buf->num_ops = 0;
|
||||
op_buf->next = NULL;
|
||||
}
|
||||
|
||||
return op_buf;
|
||||
free (buf);
|
||||
}
|
||||
|
||||
static void
|
||||
_cairo_path_op_buf_destroy (cairo_path_op_buf_t *op_buf)
|
||||
{
|
||||
free (op_buf);
|
||||
}
|
||||
|
||||
static void
|
||||
_cairo_path_op_buf_add_op (cairo_path_op_buf_t *op_buf,
|
||||
_cairo_path_buf_add_op (cairo_path_buf_t *buf,
|
||||
cairo_path_op_t op)
|
||||
{
|
||||
op_buf->op[op_buf->num_ops++] = op;
|
||||
}
|
||||
|
||||
static cairo_path_arg_buf_t *
|
||||
_cairo_path_arg_buf_create (void)
|
||||
{
|
||||
cairo_path_arg_buf_t *arg_buf;
|
||||
|
||||
arg_buf = malloc (sizeof (cairo_path_arg_buf_t));
|
||||
|
||||
if (arg_buf) {
|
||||
arg_buf->num_points = 0;
|
||||
arg_buf->next = NULL;
|
||||
}
|
||||
|
||||
return arg_buf;
|
||||
buf->op[buf->num_ops++] = op;
|
||||
}
|
||||
|
||||
static void
|
||||
_cairo_path_arg_buf_destroy (cairo_path_arg_buf_t *arg_buf)
|
||||
{
|
||||
free (arg_buf);
|
||||
}
|
||||
|
||||
static void
|
||||
_cairo_path_arg_buf_add_points (cairo_path_arg_buf_t *arg_buf,
|
||||
_cairo_path_buf_add_points (cairo_path_buf_t *buf,
|
||||
cairo_point_t *points,
|
||||
int num_points)
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i=0; i < num_points; i++) {
|
||||
arg_buf->points[arg_buf->num_points++] = points[i];
|
||||
buf->points[buf->num_points++] = points[i];
|
||||
}
|
||||
}
|
||||
|
||||
#define CAIRO_PATH_OP_MAX_ARGS 3
|
||||
|
||||
static int const num_args[] =
|
||||
{
|
||||
1, /* cairo_path_move_to */
|
||||
|
@ -521,61 +445,43 @@ _cairo_path_fixed_interpret (cairo_path_fixed_t *path,
|
|||
void *closure)
|
||||
{
|
||||
cairo_status_t status;
|
||||
int i, arg;
|
||||
cairo_path_op_buf_t *op_buf;
|
||||
cairo_path_buf_t *buf;
|
||||
cairo_path_op_t op;
|
||||
cairo_path_arg_buf_t *arg_buf = path->arg_buf_head;
|
||||
int buf_i = 0;
|
||||
cairo_point_t point[CAIRO_PATH_OP_MAX_ARGS];
|
||||
cairo_bool_t forward = (dir == CAIRO_DIRECTION_FORWARD);
|
||||
int step = forward ? 1 : -1;
|
||||
|
||||
for (op_buf = forward ? path->op_buf_head : path->op_buf_tail;
|
||||
op_buf;
|
||||
op_buf = forward ? op_buf->next : op_buf->prev)
|
||||
for (buf = forward ? path->buf_head : path->buf_tail;
|
||||
buf;
|
||||
buf = forward ? buf->next : buf->prev)
|
||||
{
|
||||
int start, stop;
|
||||
cairo_point_t *points;
|
||||
int start, stop, i;
|
||||
if (forward) {
|
||||
start = 0;
|
||||
stop = op_buf->num_ops;
|
||||
stop = buf->num_ops;
|
||||
points = buf->points;
|
||||
} else {
|
||||
start = op_buf->num_ops - 1;
|
||||
start = buf->num_ops - 1;
|
||||
stop = -1;
|
||||
points = buf->points + buf->num_points;
|
||||
}
|
||||
|
||||
for (i=start; i != stop; i += step) {
|
||||
op = op_buf->op[i];
|
||||
op = buf->op[i];
|
||||
|
||||
if (! forward) {
|
||||
if (buf_i == 0) {
|
||||
arg_buf = arg_buf->prev;
|
||||
buf_i = arg_buf->num_points;
|
||||
}
|
||||
buf_i -= num_args[op];
|
||||
}
|
||||
|
||||
for (arg = 0; arg < num_args[op]; arg++) {
|
||||
point[arg] = arg_buf->points[buf_i];
|
||||
buf_i++;
|
||||
if (buf_i >= arg_buf->num_points) {
|
||||
arg_buf = arg_buf->next;
|
||||
buf_i = 0;
|
||||
}
|
||||
}
|
||||
|
||||
if (! forward) {
|
||||
buf_i -= num_args[op];
|
||||
points -= num_args[op];
|
||||
}
|
||||
|
||||
switch (op) {
|
||||
case CAIRO_PATH_OP_MOVE_TO:
|
||||
status = (*move_to) (closure, &point[0]);
|
||||
status = (*move_to) (closure, &points[0]);
|
||||
break;
|
||||
case CAIRO_PATH_OP_LINE_TO:
|
||||
status = (*line_to) (closure, &point[0]);
|
||||
status = (*line_to) (closure, &points[0]);
|
||||
break;
|
||||
case CAIRO_PATH_OP_CURVE_TO:
|
||||
status = (*curve_to) (closure, &point[0], &point[1], &point[2]);
|
||||
status = (*curve_to) (closure, &points[0], &points[1], &points[2]);
|
||||
break;
|
||||
case CAIRO_PATH_OP_CLOSE_PATH:
|
||||
default:
|
||||
|
@ -584,6 +490,11 @@ _cairo_path_fixed_interpret (cairo_path_fixed_t *path,
|
|||
}
|
||||
if (status)
|
||||
return status;
|
||||
|
||||
if (forward) {
|
||||
points += num_args[op];
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -597,31 +508,31 @@ _cairo_path_fixed_offset_and_scale (cairo_path_fixed_t *path,
|
|||
cairo_fixed_t scalex,
|
||||
cairo_fixed_t scaley)
|
||||
{
|
||||
cairo_path_arg_buf_t *arg_buf = path->arg_buf_head;
|
||||
cairo_path_buf_t *buf = path->buf_head;
|
||||
int i;
|
||||
cairo_int64_t i64temp;
|
||||
cairo_fixed_t fixedtemp;
|
||||
|
||||
while (arg_buf) {
|
||||
for (i = 0; i < arg_buf->num_points; i++) {
|
||||
while (buf) {
|
||||
for (i = 0; i < buf->num_points; i++) {
|
||||
if (scalex == CAIRO_FIXED_ONE) {
|
||||
arg_buf->points[i].x += offx;
|
||||
buf->points[i].x += offx;
|
||||
} else {
|
||||
fixedtemp = arg_buf->points[i].x + offx;
|
||||
fixedtemp = buf->points[i].x + offx;
|
||||
i64temp = _cairo_int32x32_64_mul (fixedtemp, scalex);
|
||||
arg_buf->points[i].x = _cairo_int64_to_int32(_cairo_int64_rsl (i64temp, 16));
|
||||
buf->points[i].x = _cairo_int64_to_int32(_cairo_int64_rsl (i64temp, 16));
|
||||
}
|
||||
|
||||
if (scaley == CAIRO_FIXED_ONE) {
|
||||
arg_buf->points[i].y += offy;
|
||||
buf->points[i].y += offy;
|
||||
} else {
|
||||
fixedtemp = arg_buf->points[i].y + offy;
|
||||
fixedtemp = buf->points[i].y + offy;
|
||||
i64temp = _cairo_int32x32_64_mul (fixedtemp, scaley);
|
||||
arg_buf->points[i].y = _cairo_int64_to_int32(_cairo_int64_rsl (i64temp, 16));
|
||||
buf->points[i].y = _cairo_int64_to_int32(_cairo_int64_rsl (i64temp, 16));
|
||||
}
|
||||
}
|
||||
|
||||
arg_buf = arg_buf->next;
|
||||
buf = buf->next;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -51,7 +51,7 @@ typedef struct cairo_stroker {
|
|||
cairo_point_t current_point;
|
||||
cairo_point_t first_point;
|
||||
|
||||
cairo_bool_t has_sub_path;
|
||||
cairo_bool_t has_initial_sub_path;
|
||||
|
||||
cairo_bool_t has_current_face;
|
||||
cairo_stroke_face_t current_face;
|
||||
|
@ -61,7 +61,8 @@ typedef struct cairo_stroker {
|
|||
|
||||
cairo_bool_t dashed;
|
||||
unsigned int dash_index;
|
||||
int dash_on;
|
||||
cairo_bool_t dash_on;
|
||||
cairo_bool_t dash_starts_on;
|
||||
double dash_remain;
|
||||
} cairo_stroker_t;
|
||||
|
||||
|
@ -114,7 +115,7 @@ static void
|
|||
_cairo_stroker_start_dash (cairo_stroker_t *stroker)
|
||||
{
|
||||
double offset;
|
||||
int on = 1;
|
||||
cairo_bool_t on = TRUE;
|
||||
unsigned int i = 0;
|
||||
|
||||
offset = stroker->style->dash_offset;
|
||||
|
@ -124,13 +125,13 @@ _cairo_stroker_start_dash (cairo_stroker_t *stroker)
|
|||
segment shrinks to zero it will be skipped over. */
|
||||
while (offset > 0.0 && offset >= stroker->style->dash[i]) {
|
||||
offset -= stroker->style->dash[i];
|
||||
on = 1-on;
|
||||
on = !on;
|
||||
if (++i == stroker->style->num_dashes)
|
||||
i = 0;
|
||||
}
|
||||
stroker->dashed = TRUE;
|
||||
stroker->dash_index = i;
|
||||
stroker->dash_on = on;
|
||||
stroker->dash_on = stroker->dash_starts_on = on;
|
||||
stroker->dash_remain = stroker->style->dash[i] - offset;
|
||||
}
|
||||
|
||||
|
@ -142,7 +143,7 @@ _cairo_stroker_step_dash (cairo_stroker_t *stroker, double step)
|
|||
stroker->dash_index++;
|
||||
if (stroker->dash_index == stroker->style->num_dashes)
|
||||
stroker->dash_index = 0;
|
||||
stroker->dash_on = 1-stroker->dash_on;
|
||||
stroker->dash_on = !stroker->dash_on;
|
||||
stroker->dash_remain = stroker->style->dash[stroker->dash_index];
|
||||
}
|
||||
}
|
||||
|
@ -167,7 +168,7 @@ _cairo_stroker_init (cairo_stroker_t *stroker,
|
|||
|
||||
stroker->has_current_face = FALSE;
|
||||
stroker->has_first_face = FALSE;
|
||||
stroker->has_sub_path = FALSE;
|
||||
stroker->has_initial_sub_path = FALSE;
|
||||
|
||||
if (stroker->style->dash)
|
||||
_cairo_stroker_start_dash (stroker);
|
||||
|
@ -466,17 +467,25 @@ _cairo_stroker_add_caps (cairo_stroker_t *stroker)
|
|||
{
|
||||
cairo_status_t status;
|
||||
/* check for a degenerative sub_path */
|
||||
if (stroker->has_sub_path
|
||||
if (stroker->has_initial_sub_path
|
||||
&& !stroker->has_first_face
|
||||
&& !stroker->has_current_face
|
||||
&& stroker->style->line_cap == CAIRO_LINE_JOIN_ROUND)
|
||||
{
|
||||
/* pick an arbitrary slope to use */
|
||||
cairo_slope_t slope = {1, 0};
|
||||
_compute_face (&stroker->first_point, &slope, stroker, &stroker->first_face);
|
||||
cairo_stroke_face_t face;
|
||||
|
||||
stroker->has_first_face = stroker->has_current_face = TRUE;
|
||||
stroker->current_face = stroker->first_face;
|
||||
/* arbitrarily choose first_point
|
||||
* first_point and current_point should be the same */
|
||||
_compute_face (&stroker->first_point, &slope, stroker, &face);
|
||||
|
||||
status = _cairo_stroker_add_leading_cap (stroker, &face);
|
||||
if (status)
|
||||
return status;
|
||||
status = _cairo_stroker_add_trailing_cap (stroker, &face);
|
||||
if (status)
|
||||
return status;
|
||||
}
|
||||
|
||||
if (stroker->has_first_face) {
|
||||
|
@ -594,6 +603,7 @@ _cairo_stroker_move_to (void *closure, cairo_point_t *point)
|
|||
cairo_status_t status;
|
||||
cairo_stroker_t *stroker = closure;
|
||||
|
||||
/* Cap the start and end of the previous sub path as needed */
|
||||
status = _cairo_stroker_add_caps (stroker);
|
||||
if (status)
|
||||
return status;
|
||||
|
@ -603,7 +613,7 @@ _cairo_stroker_move_to (void *closure, cairo_point_t *point)
|
|||
|
||||
stroker->has_first_face = FALSE;
|
||||
stroker->has_current_face = FALSE;
|
||||
stroker->has_sub_path = FALSE;
|
||||
stroker->has_initial_sub_path = FALSE;
|
||||
|
||||
return CAIRO_STATUS_SUCCESS;
|
||||
}
|
||||
|
@ -628,7 +638,7 @@ _cairo_stroker_line_to (void *closure, cairo_point_t *point)
|
|||
cairo_point_t *p2 = point;
|
||||
cairo_slope_t slope;
|
||||
|
||||
stroker->has_sub_path = TRUE;
|
||||
stroker->has_initial_sub_path = TRUE;
|
||||
|
||||
if (p1->x == p2->x && p1->y == p2->y)
|
||||
return CAIRO_STATUS_SUCCESS;
|
||||
|
@ -640,15 +650,15 @@ _cairo_stroker_line_to (void *closure, cairo_point_t *point)
|
|||
return status;
|
||||
|
||||
if (stroker->has_current_face) {
|
||||
/* Join with final face from previous segment */
|
||||
status = _cairo_stroker_join (stroker, &stroker->current_face, &start);
|
||||
if (status)
|
||||
return status;
|
||||
} else {
|
||||
if (!stroker->has_first_face) {
|
||||
} else if (!stroker->has_first_face) {
|
||||
/* Save sub path's first face in case needed for closing join */
|
||||
stroker->first_face = start;
|
||||
stroker->has_first_face = TRUE;
|
||||
}
|
||||
}
|
||||
stroker->current_face = end;
|
||||
stroker->has_current_face = TRUE;
|
||||
|
||||
|
@ -665,17 +675,16 @@ _cairo_stroker_line_to_dashed (void *closure, cairo_point_t *point)
|
|||
{
|
||||
cairo_status_t status = CAIRO_STATUS_SUCCESS;
|
||||
cairo_stroker_t *stroker = closure;
|
||||
double mag, remain, tmp;
|
||||
double mag, remain, step_length = 0;
|
||||
double dx, dy;
|
||||
double dx2, dy2;
|
||||
cairo_point_t fd1, fd2;
|
||||
cairo_bool_t first = TRUE;
|
||||
cairo_stroke_face_t sub_start, sub_end;
|
||||
cairo_point_t *p1 = &stroker->current_point;
|
||||
cairo_point_t *p2 = point;
|
||||
cairo_slope_t slope;
|
||||
|
||||
stroker->has_sub_path = stroker->dash_on;
|
||||
stroker->has_initial_sub_path = stroker->dash_starts_on;
|
||||
|
||||
if (p1->x == p2->x && p1->y == p2->y)
|
||||
return CAIRO_STATUS_SUCCESS;
|
||||
|
@ -691,86 +700,71 @@ _cairo_stroker_line_to_dashed (void *closure, cairo_point_t *point)
|
|||
remain = mag;
|
||||
fd1 = *p1;
|
||||
while (remain) {
|
||||
tmp = stroker->dash_remain;
|
||||
if (tmp > remain)
|
||||
tmp = remain;
|
||||
remain -= tmp;
|
||||
step_length = MIN (stroker->dash_remain, remain);
|
||||
remain -= step_length;
|
||||
dx2 = dx * (mag - remain)/mag;
|
||||
dy2 = dy * (mag - remain)/mag;
|
||||
cairo_matrix_transform_distance (stroker->ctm, &dx2, &dy2);
|
||||
fd2.x = _cairo_fixed_from_double (dx2);
|
||||
fd2.y = _cairo_fixed_from_double (dy2);
|
||||
fd2.x += p1->x;
|
||||
fd2.y += p1->y;
|
||||
/*
|
||||
* XXX simplify this case analysis
|
||||
*/
|
||||
fd2.x = _cairo_fixed_from_double (dx2) + p1->x;
|
||||
fd2.y = _cairo_fixed_from_double (dy2) + p1->y;
|
||||
|
||||
if (stroker->dash_on) {
|
||||
status = _cairo_stroker_add_sub_edge (stroker, &fd1, &fd2, &slope, &sub_start, &sub_end);
|
||||
if (status)
|
||||
return status;
|
||||
if (!first) {
|
||||
/*
|
||||
* Not first dash in this segment, cap start
|
||||
*/
|
||||
status = _cairo_stroker_add_leading_cap (stroker, &sub_start);
|
||||
if (status)
|
||||
return status;
|
||||
} else {
|
||||
/*
|
||||
* First in this segment, join to any current_face, else
|
||||
* if at start of sub-path, mark position, else
|
||||
* cap
|
||||
*/
|
||||
|
||||
if (stroker->has_current_face) {
|
||||
/* Join with final face from previous segment */
|
||||
status = _cairo_stroker_join (stroker, &stroker->current_face, &sub_start);
|
||||
stroker->has_current_face = FALSE;
|
||||
if (status)
|
||||
return status;
|
||||
} else {
|
||||
if (!stroker->has_first_face) {
|
||||
} else if (!stroker->has_first_face && stroker->dash_starts_on) {
|
||||
/* Save sub path's first face in case needed for closing join */
|
||||
stroker->first_face = sub_start;
|
||||
stroker->has_first_face = TRUE;
|
||||
} else {
|
||||
/* Cap dash start if not connecting to a previous segment */
|
||||
status = _cairo_stroker_add_leading_cap (stroker, &sub_start);
|
||||
if (status)
|
||||
return status;
|
||||
}
|
||||
}
|
||||
stroker->has_sub_path = TRUE;
|
||||
}
|
||||
|
||||
if (remain) {
|
||||
/*
|
||||
* Cap if not at end of segment
|
||||
*/
|
||||
/* Cap dash end if not at end of segment */
|
||||
status = _cairo_stroker_add_trailing_cap (stroker, &sub_end);
|
||||
if (status)
|
||||
return status;
|
||||
} else {
|
||||
/*
|
||||
* Mark previous line face and fix up next time
|
||||
* through
|
||||
*/
|
||||
stroker->current_face = sub_end;
|
||||
stroker->has_current_face = TRUE;
|
||||
}
|
||||
} else {
|
||||
/*
|
||||
* If starting with off dash, check previous face
|
||||
* and cap if necessary
|
||||
*/
|
||||
if (first) {
|
||||
if (stroker->has_current_face) {
|
||||
/* Cap final face from previous segment */
|
||||
status = _cairo_stroker_add_trailing_cap (stroker, &stroker->current_face);
|
||||
if (status)
|
||||
return status;
|
||||
}
|
||||
}
|
||||
if (!remain)
|
||||
stroker->has_current_face = FALSE;
|
||||
}
|
||||
_cairo_stroker_step_dash (stroker, tmp);
|
||||
}
|
||||
_cairo_stroker_step_dash (stroker, step_length);
|
||||
fd1 = fd2;
|
||||
first = FALSE;
|
||||
}
|
||||
|
||||
if (stroker->dash_on && !stroker->has_current_face) {
|
||||
/* This segment ends on a transition to dash_on, compute a new face
|
||||
* and add cap for the begining of the next dash_on step.
|
||||
*
|
||||
* Note: this will create a degenerate cap if this is not the last line
|
||||
* in the path. Whether this behaviour is desirable or not is debatable.
|
||||
* On one side these degnerate caps can not be reproduced with regular path stroking.
|
||||
* On the other side Acroread 7 also produces the degenerate caps. */
|
||||
_compute_face (point, &slope, stroker, &stroker->current_face);
|
||||
stroker->has_current_face = TRUE;
|
||||
status = _cairo_stroker_add_leading_cap (stroker, &stroker->current_face);
|
||||
if (status)
|
||||
return status;
|
||||
}
|
||||
|
||||
stroker->current_point = *point;
|
||||
|
@ -807,12 +801,10 @@ _cairo_stroker_curve_to (void *closure,
|
|||
status = _cairo_stroker_join (stroker, &stroker->current_face, &start);
|
||||
if (status)
|
||||
return status;
|
||||
} else {
|
||||
if (!stroker->has_first_face) {
|
||||
} else if (!stroker->has_first_face) {
|
||||
stroker->first_face = start;
|
||||
stroker->has_first_face = TRUE;
|
||||
}
|
||||
}
|
||||
stroker->current_face = end;
|
||||
stroker->has_current_face = TRUE;
|
||||
|
||||
|
@ -928,16 +920,18 @@ _cairo_stroker_close_path (void *closure)
|
|||
return status;
|
||||
|
||||
if (stroker->has_first_face && stroker->has_current_face) {
|
||||
/* Join first and final faces of sub path */
|
||||
status = _cairo_stroker_join (stroker, &stroker->current_face, &stroker->first_face);
|
||||
if (status)
|
||||
return status;
|
||||
} else {
|
||||
/* Cap the start and end of the sub path as needed */
|
||||
status = _cairo_stroker_add_caps (stroker);
|
||||
if (status)
|
||||
return status;
|
||||
}
|
||||
|
||||
stroker->has_sub_path = FALSE;
|
||||
stroker->has_initial_sub_path = FALSE;
|
||||
stroker->has_first_face = FALSE;
|
||||
stroker->has_current_face = FALSE;
|
||||
|
||||
|
@ -996,6 +990,7 @@ _cairo_path_fixed_stroke_to_traps (cairo_path_fixed_t *path,
|
|||
if (status)
|
||||
goto BAIL;
|
||||
|
||||
/* Cap the start and end of the final sub path as needed */
|
||||
status = _cairo_stroker_add_caps (&stroker);
|
||||
|
||||
BAIL:
|
||||
|
@ -1287,16 +1282,17 @@ _cairo_path_fixed_stroke_rectilinear (cairo_path_fixed_t *path,
|
|||
NULL,
|
||||
_cairo_rectilinear_stroker_close_path,
|
||||
&rectilinear_stroker);
|
||||
if (status) {
|
||||
_cairo_traps_fini (traps);
|
||||
return status;
|
||||
}
|
||||
if (status)
|
||||
goto BAIL;
|
||||
|
||||
status = _cairo_rectilinear_stroker_emit_segments (&rectilinear_stroker);
|
||||
if (status)
|
||||
return status;
|
||||
|
||||
BAIL:
|
||||
|
||||
_cairo_rectilinear_stroker_fini (&rectilinear_stroker);
|
||||
|
||||
return CAIRO_STATUS_SUCCESS;
|
||||
if (status)
|
||||
_cairo_traps_fini (traps);
|
||||
|
||||
return status;
|
||||
}
|
||||
|
|
|
@ -465,19 +465,19 @@ _cairo_path_append_to_context (const cairo_path_t *path,
|
|||
p = &path->data[i];
|
||||
switch (p->header.type) {
|
||||
case CAIRO_PATH_MOVE_TO:
|
||||
if (p->header.length != 2)
|
||||
if (p->header.length < 2)
|
||||
return CAIRO_STATUS_INVALID_PATH_DATA;
|
||||
cairo_move_to (cr,
|
||||
p[1].point.x, p[1].point.y);
|
||||
break;
|
||||
case CAIRO_PATH_LINE_TO:
|
||||
if (p->header.length != 2)
|
||||
if (p->header.length < 2)
|
||||
return CAIRO_STATUS_INVALID_PATH_DATA;
|
||||
cairo_line_to (cr,
|
||||
p[1].point.x, p[1].point.y);
|
||||
break;
|
||||
case CAIRO_PATH_CURVE_TO:
|
||||
if (p->header.length != 4)
|
||||
if (p->header.length < 4)
|
||||
return CAIRO_STATUS_INVALID_PATH_DATA;
|
||||
cairo_curve_to (cr,
|
||||
p[1].point.x, p[1].point.y,
|
||||
|
@ -485,7 +485,7 @@ _cairo_path_append_to_context (const cairo_path_t *path,
|
|||
p[3].point.x, p[3].point.y);
|
||||
break;
|
||||
case CAIRO_PATH_CLOSE_PATH:
|
||||
if (p->header.length != 1)
|
||||
if (p->header.length < 1)
|
||||
return CAIRO_STATUS_INVALID_PATH_DATA;
|
||||
cairo_close_path (cr);
|
||||
break;
|
||||
|
|
|
@ -34,6 +34,7 @@ const cairo_solid_pattern_t cairo_pattern_nil = {
|
|||
{ CAIRO_PATTERN_TYPE_SOLID, /* type */
|
||||
CAIRO_REF_COUNT_INVALID, /* ref_count */
|
||||
CAIRO_STATUS_NO_MEMORY, /* status */
|
||||
{ 0, 0, 0, NULL }, /* user_data */
|
||||
{ 1., 0., 0., 1., 0., 0., }, /* matrix */
|
||||
CAIRO_FILTER_DEFAULT, /* filter */
|
||||
CAIRO_EXTEND_GRADIENT_DEFAULT }, /* extend */
|
||||
|
@ -43,6 +44,7 @@ static const cairo_solid_pattern_t cairo_pattern_nil_null_pointer = {
|
|||
{ CAIRO_PATTERN_TYPE_SOLID, /* type */
|
||||
CAIRO_REF_COUNT_INVALID, /* ref_count */
|
||||
CAIRO_STATUS_NULL_POINTER,/* status */
|
||||
{ 0, 0, 0, NULL }, /* user_data */
|
||||
{ 1., 0., 0., 1., 0., 0., }, /* matrix */
|
||||
CAIRO_FILTER_DEFAULT, /* filter */
|
||||
CAIRO_EXTEND_GRADIENT_DEFAULT }, /* extend */
|
||||
|
@ -84,6 +86,8 @@ _cairo_pattern_init (cairo_pattern_t *pattern, cairo_pattern_type_t type)
|
|||
pattern->ref_count = 1;
|
||||
pattern->status = CAIRO_STATUS_SUCCESS;
|
||||
|
||||
_cairo_user_data_array_init (&pattern->user_data);
|
||||
|
||||
if (type == CAIRO_PATTERN_TYPE_SURFACE)
|
||||
pattern->extend = CAIRO_EXTEND_SURFACE_DEFAULT;
|
||||
else
|
||||
|
@ -113,11 +117,15 @@ _cairo_gradient_pattern_init_copy (cairo_gradient_pattern_t *pattern,
|
|||
*dst = *src;
|
||||
}
|
||||
|
||||
if (other->n_stops)
|
||||
if (other->stops == other->stops_embedded)
|
||||
pattern->stops = pattern->stops_embedded;
|
||||
else if (other->stops)
|
||||
{
|
||||
pattern->stops = malloc (other->n_stops *
|
||||
pattern->stops = malloc (other->stops_size *
|
||||
sizeof (pixman_gradient_stop_t));
|
||||
if (pattern->stops == NULL) {
|
||||
pattern->stops_size = 0;
|
||||
pattern->n_stops = 0;
|
||||
_cairo_pattern_set_error (&pattern->base, CAIRO_STATUS_NO_MEMORY);
|
||||
return;
|
||||
}
|
||||
|
@ -165,6 +173,8 @@ _cairo_pattern_init_copy (cairo_pattern_t *pattern,
|
|||
void
|
||||
_cairo_pattern_fini (cairo_pattern_t *pattern)
|
||||
{
|
||||
_cairo_user_data_array_fini (&pattern->user_data);
|
||||
|
||||
switch (pattern->type) {
|
||||
case CAIRO_PATTERN_TYPE_SOLID:
|
||||
break;
|
||||
|
@ -179,7 +189,7 @@ _cairo_pattern_fini (cairo_pattern_t *pattern)
|
|||
cairo_gradient_pattern_t *gradient =
|
||||
(cairo_gradient_pattern_t *) pattern;
|
||||
|
||||
if (gradient->stops)
|
||||
if (gradient->stops && gradient->stops != gradient->stops_embedded)
|
||||
free (gradient->stops);
|
||||
} break;
|
||||
}
|
||||
|
@ -215,8 +225,9 @@ _cairo_pattern_init_gradient (cairo_gradient_pattern_t *pattern,
|
|||
{
|
||||
_cairo_pattern_init (&pattern->base, type);
|
||||
|
||||
pattern->stops = NULL;
|
||||
pattern->n_stops = 0;
|
||||
pattern->stops_size = 0;
|
||||
pattern->stops = NULL;
|
||||
}
|
||||
|
||||
void
|
||||
|
@ -238,12 +249,12 @@ _cairo_pattern_init_radial (cairo_radial_pattern_t *pattern,
|
|||
{
|
||||
_cairo_pattern_init_gradient (&pattern->base, CAIRO_PATTERN_TYPE_RADIAL);
|
||||
|
||||
pattern->gradient.inner.x = _cairo_fixed_from_double (cx0);
|
||||
pattern->gradient.inner.y = _cairo_fixed_from_double (cy0);
|
||||
pattern->gradient.inner.radius = _cairo_fixed_from_double (fabs (radius0));
|
||||
pattern->gradient.outer.x = _cairo_fixed_from_double (cx1);
|
||||
pattern->gradient.outer.y = _cairo_fixed_from_double (cy1);
|
||||
pattern->gradient.outer.radius = _cairo_fixed_from_double (fabs (radius1));
|
||||
pattern->gradient.c1.x = _cairo_fixed_from_double (cx0);
|
||||
pattern->gradient.c1.y = _cairo_fixed_from_double (cy0);
|
||||
pattern->gradient.c1.radius = _cairo_fixed_from_double (fabs (radius0));
|
||||
pattern->gradient.c2.x = _cairo_fixed_from_double (cx1);
|
||||
pattern->gradient.c2.y = _cairo_fixed_from_double (cy1);
|
||||
pattern->gradient.c2.radius = _cairo_fixed_from_double (fabs (radius1));
|
||||
}
|
||||
|
||||
cairo_pattern_t *
|
||||
|
@ -490,15 +501,15 @@ cairo_pattern_create_radial (double cx0, double cy0, double radius0,
|
|||
* @pattern from being destroyed until a matching call to
|
||||
* cairo_pattern_destroy() is made.
|
||||
*
|
||||
* The number of references to a #cairo_pattern_t can be get using
|
||||
* cairo_pattern_get_reference_count().
|
||||
*
|
||||
* Return value: the referenced #cairo_pattern_t.
|
||||
**/
|
||||
cairo_pattern_t *
|
||||
cairo_pattern_reference (cairo_pattern_t *pattern)
|
||||
{
|
||||
if (pattern == NULL)
|
||||
return NULL;
|
||||
|
||||
if (pattern->ref_count == CAIRO_REF_COUNT_INVALID)
|
||||
if (pattern == NULL || pattern->ref_count == CAIRO_REF_COUNT_INVALID)
|
||||
return pattern;
|
||||
|
||||
assert (pattern->ref_count > 0);
|
||||
|
@ -555,10 +566,7 @@ slim_hidden_def (cairo_pattern_status);
|
|||
void
|
||||
cairo_pattern_destroy (cairo_pattern_t *pattern)
|
||||
{
|
||||
if (pattern == NULL)
|
||||
return;
|
||||
|
||||
if (pattern->ref_count == CAIRO_REF_COUNT_INVALID)
|
||||
if (pattern == NULL || pattern->ref_count == CAIRO_REF_COUNT_INVALID)
|
||||
return;
|
||||
|
||||
assert (pattern->ref_count > 0);
|
||||
|
@ -572,6 +580,116 @@ cairo_pattern_destroy (cairo_pattern_t *pattern)
|
|||
}
|
||||
slim_hidden_def (cairo_pattern_destroy);
|
||||
|
||||
/**
|
||||
* cairo_pattern_get_reference_count:
|
||||
* @pattern: a #cairo_pattern_t
|
||||
*
|
||||
* Returns the current reference count of @pattern.
|
||||
*
|
||||
* Return value: the current reference count of @pattern. If the
|
||||
* object is a nil object, 0 will be returned.
|
||||
*
|
||||
* Since: 1.4
|
||||
**/
|
||||
unsigned int
|
||||
cairo_pattern_get_reference_count (cairo_pattern_t *pattern)
|
||||
{
|
||||
if (pattern == NULL || pattern->ref_count == CAIRO_REF_COUNT_INVALID)
|
||||
return 0;
|
||||
|
||||
return pattern->ref_count;
|
||||
}
|
||||
|
||||
/**
|
||||
* cairo_pattern_get_user_data:
|
||||
* @pattern: a #cairo_pattern_t
|
||||
* @key: the address of the #cairo_user_data_key_t the user data was
|
||||
* attached to
|
||||
*
|
||||
* Return user data previously attached to @pattern using the
|
||||
* specified key. If no user data has been attached with the given
|
||||
* key this function returns %NULL.
|
||||
*
|
||||
* Return value: the user data previously attached or %NULL.
|
||||
*
|
||||
* Since: 1.4
|
||||
**/
|
||||
void *
|
||||
cairo_pattern_get_user_data (cairo_pattern_t *pattern,
|
||||
const cairo_user_data_key_t *key)
|
||||
{
|
||||
return _cairo_user_data_array_get_data (&pattern->user_data,
|
||||
key);
|
||||
}
|
||||
|
||||
/**
|
||||
* cairo_pattern_set_user_data:
|
||||
* @pattern: a #cairo_pattern_t
|
||||
* @key: the address of a #cairo_user_data_key_t to attach the user data to
|
||||
* @user_data: the user data to attach to the #cairo_pattern_t
|
||||
* @destroy: a #cairo_destroy_func_t which will be called when the
|
||||
* #cairo_t is destroyed or when new user data is attached using the
|
||||
* same key.
|
||||
*
|
||||
* Attach user data to @pattern. To remove user data from a surface,
|
||||
* call this function with the key that was used to set it and %NULL
|
||||
* for @data.
|
||||
*
|
||||
* Return value: %CAIRO_STATUS_SUCCESS or %CAIRO_STATUS_NO_MEMORY if a
|
||||
* slot could not be allocated for the user data.
|
||||
*
|
||||
* Since: 1.4
|
||||
**/
|
||||
cairo_status_t
|
||||
cairo_pattern_set_user_data (cairo_pattern_t *pattern,
|
||||
const cairo_user_data_key_t *key,
|
||||
void *user_data,
|
||||
cairo_destroy_func_t destroy)
|
||||
{
|
||||
if (pattern->ref_count == CAIRO_REF_COUNT_INVALID)
|
||||
return CAIRO_STATUS_NO_MEMORY;
|
||||
|
||||
return _cairo_user_data_array_set_data (&pattern->user_data,
|
||||
key, user_data, destroy);
|
||||
}
|
||||
|
||||
/* make room for at least one more color stop */
|
||||
static cairo_status_t
|
||||
_cairo_pattern_gradient_grow (cairo_gradient_pattern_t *pattern)
|
||||
{
|
||||
pixman_gradient_stop_t *new_stops;
|
||||
int old_size = pattern->stops_size;
|
||||
int embedded_size = sizeof (pattern->stops_embedded) / sizeof (pattern->stops_embedded[0]);
|
||||
int new_size = 2 * MAX (old_size, 4);
|
||||
|
||||
/* we have a local buffer at pattern->stops_embedded. try to fulfill the request
|
||||
* from there. */
|
||||
if (old_size < embedded_size) {
|
||||
pattern->stops = pattern->stops_embedded;
|
||||
pattern->stops_size = embedded_size;
|
||||
return CAIRO_STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
assert (pattern->n_stops <= pattern->stops_size);
|
||||
|
||||
if (pattern->stops == pattern->stops_embedded) {
|
||||
new_stops = malloc (new_size * sizeof (pixman_gradient_stop_t));
|
||||
if (new_stops)
|
||||
memcpy (new_stops, pattern->stops, old_size * sizeof (pixman_gradient_stop_t));
|
||||
} else {
|
||||
new_stops = realloc (pattern->stops, new_size * sizeof (pixman_gradient_stop_t));
|
||||
}
|
||||
|
||||
if (new_stops == NULL) {
|
||||
return CAIRO_STATUS_NO_MEMORY;
|
||||
}
|
||||
|
||||
pattern->stops = new_stops;
|
||||
pattern->stops_size = new_size;
|
||||
|
||||
return CAIRO_STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
static void
|
||||
_cairo_pattern_add_color_stop (cairo_gradient_pattern_t *pattern,
|
||||
double offset,
|
||||
|
@ -580,38 +698,38 @@ _cairo_pattern_add_color_stop (cairo_gradient_pattern_t *pattern,
|
|||
double blue,
|
||||
double alpha)
|
||||
{
|
||||
pixman_gradient_stop_t *new_stops;
|
||||
pixman_gradient_stop_t *stops;
|
||||
cairo_fixed_t x;
|
||||
unsigned int i;
|
||||
|
||||
new_stops = realloc (pattern->stops, (pattern->n_stops + 1) *
|
||||
sizeof (pixman_gradient_stop_t));
|
||||
if (new_stops == NULL)
|
||||
{
|
||||
if (pattern->n_stops >= pattern->stops_size) {
|
||||
cairo_status_t status = _cairo_pattern_gradient_grow (pattern);
|
||||
if (status) {
|
||||
_cairo_pattern_set_error (&pattern->base, CAIRO_STATUS_NO_MEMORY);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
pattern->stops = new_stops;
|
||||
stops = pattern->stops;
|
||||
|
||||
x = _cairo_fixed_from_double (offset);
|
||||
for (i = 0; i < pattern->n_stops; i++)
|
||||
{
|
||||
if (x < new_stops[i].x)
|
||||
if (x < stops[i].x)
|
||||
{
|
||||
memmove (&new_stops[i + 1], &new_stops[i],
|
||||
memmove (&stops[i + 1], &stops[i],
|
||||
sizeof (pixman_gradient_stop_t) * (pattern->n_stops - i));
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
new_stops[i].x = x;
|
||||
stops[i].x = x;
|
||||
|
||||
new_stops[i].color.red = red * 65535.0;
|
||||
new_stops[i].color.green = green * 65535.0;
|
||||
new_stops[i].color.blue = blue * 65535.0;
|
||||
new_stops[i].color.alpha = alpha * 65535.0;
|
||||
stops[i].color.red = _cairo_color_double_to_short (red);
|
||||
stops[i].color.green = _cairo_color_double_to_short (green);
|
||||
stops[i].color.blue = _cairo_color_double_to_short (blue);
|
||||
stops[i].color.alpha = _cairo_color_double_to_short (alpha);
|
||||
|
||||
pattern->n_stops++;
|
||||
}
|
||||
|
@ -767,6 +885,15 @@ cairo_pattern_get_matrix (cairo_pattern_t *pattern, cairo_matrix_t *matrix)
|
|||
*matrix = pattern->matrix;
|
||||
}
|
||||
|
||||
/**
|
||||
* cairo_pattern_set_filter:
|
||||
* @pattern: a #cairo_pattern_t
|
||||
* @filter: a #cairo_filter_t describing the filter to use for resizing
|
||||
* the pattern
|
||||
*
|
||||
* Sets the filter to be used for resizing when using this pattern.
|
||||
* See #cairo_filter_t for details on each filter.
|
||||
**/
|
||||
void
|
||||
cairo_pattern_set_filter (cairo_pattern_t *pattern, cairo_filter_t filter)
|
||||
{
|
||||
|
@ -776,6 +903,15 @@ cairo_pattern_set_filter (cairo_pattern_t *pattern, cairo_filter_t filter)
|
|||
pattern->filter = filter;
|
||||
}
|
||||
|
||||
/**
|
||||
* cairo_pattern_get_filter:
|
||||
* @pattern: a #cairo_pattern_t
|
||||
*
|
||||
* Gets the current filter for a pattern. See #cairo_filter_t
|
||||
* for details on each filter.
|
||||
*
|
||||
* Return value: the current filter used for resizing the pattern.
|
||||
**/
|
||||
cairo_filter_t
|
||||
cairo_pattern_get_filter (cairo_pattern_t *pattern)
|
||||
{
|
||||
|
@ -1144,6 +1280,63 @@ _cairo_pattern_acquire_surface_for_surface (cairo_surface_pattern_t *pattern,
|
|||
ty = 0;
|
||||
}
|
||||
|
||||
/* XXX: Hack:
|
||||
*
|
||||
* The way we currently support CAIRO_EXTEND_REFLECT is to create
|
||||
* an image twice bigger on each side, and create a pattern of four
|
||||
* images such that the new image, when repeated, has the same effect
|
||||
* of reflecting the original pattern.
|
||||
*
|
||||
* This is because the reflect support in pixman is broken and we
|
||||
* pass repeat instead of reflect to pixman. See
|
||||
* _cairo_image_surface_set_attributes() for that.
|
||||
*/
|
||||
if (attr->extend == CAIRO_EXTEND_REFLECT) {
|
||||
cairo_t *cr;
|
||||
int w,h;
|
||||
|
||||
cairo_rectangle_int16_t extents;
|
||||
status = _cairo_surface_get_extents (pattern->surface, &extents);
|
||||
if (status)
|
||||
return status;
|
||||
|
||||
attr->extend = CAIRO_EXTEND_REPEAT;
|
||||
|
||||
x = extents.x;
|
||||
y = extents.y;
|
||||
w = 2 * extents.width;
|
||||
h = 2 * extents.height;
|
||||
|
||||
*out = cairo_surface_create_similar (dst, dst->content, w, h);
|
||||
if (!*out)
|
||||
return CAIRO_STATUS_NO_MEMORY;
|
||||
|
||||
(*out)->device_transform = pattern->surface->device_transform;
|
||||
(*out)->device_transform_inverse = pattern->surface->device_transform_inverse;
|
||||
|
||||
cr = cairo_create (*out);
|
||||
|
||||
cairo_set_source_surface (cr, pattern->surface, -x, -y);
|
||||
cairo_paint (cr);
|
||||
|
||||
cairo_scale (cr, -1, +1);
|
||||
cairo_set_source_surface (cr, pattern->surface, x-w, -y);
|
||||
cairo_paint (cr);
|
||||
|
||||
cairo_scale (cr, +1, -1);
|
||||
cairo_set_source_surface (cr, pattern->surface, x-w, y-h);
|
||||
cairo_paint (cr);
|
||||
|
||||
cairo_scale (cr, -1, +1);
|
||||
cairo_set_source_surface (cr, pattern->surface, -x, y-h);
|
||||
cairo_paint (cr);
|
||||
|
||||
status = cairo_status (cr);
|
||||
cairo_destroy (cr);
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
if (_cairo_surface_is_image (dst))
|
||||
{
|
||||
cairo_image_surface_t *image;
|
||||
|
@ -1159,10 +1352,16 @@ _cairo_pattern_acquire_surface_for_surface (cairo_surface_pattern_t *pattern,
|
|||
}
|
||||
else
|
||||
{
|
||||
/* If we're repeating, we just play it safe and clone the entire surface. */
|
||||
if (attr->extend == CAIRO_EXTEND_REPEAT) {
|
||||
cairo_rectangle_int16_t extents;
|
||||
status = _cairo_surface_get_extents (pattern->surface, &extents);
|
||||
if (status)
|
||||
return status;
|
||||
|
||||
/* If we're repeating, we just play it safe and clone the entire surface. */
|
||||
/* If requested width and height are -1, clone the entire surface.
|
||||
* This is relied on in the svg backend. */
|
||||
if (attr->extend == CAIRO_EXTEND_REPEAT ||
|
||||
(width == (unsigned int) -1 && height == (unsigned int) -1)) {
|
||||
x = extents.x;
|
||||
y = extents.y;
|
||||
width = extents.width;
|
||||
|
@ -1179,13 +1378,19 @@ _cairo_pattern_acquire_surface_for_surface (cairo_surface_pattern_t *pattern,
|
|||
double y2 = y + height;
|
||||
cairo_bool_t is_tight;
|
||||
|
||||
cairo_matrix_transform_bounding_box (&attr->matrix,
|
||||
_cairo_matrix_transform_bounding_box (&attr->matrix,
|
||||
&x1, &y1, &x2, &y2,
|
||||
&is_tight);
|
||||
x = floor (x1);
|
||||
y = floor (y1);
|
||||
width = ceil (x2) - x;
|
||||
height = ceil (y2) - y;
|
||||
|
||||
/* The transform_bounding_box call may have resulted
|
||||
* in a region larger than the surface, but we never
|
||||
* want to clone more than the surface itself, (we
|
||||
* know we're not repeating at this point due to the
|
||||
* above. */
|
||||
x = MAX (0, floor (x1));
|
||||
y = MAX (0, floor (y1));
|
||||
width = MIN (extents.width, ceil (x2)) - x;
|
||||
height = MIN (extents.height, ceil (y2)) - y;
|
||||
}
|
||||
x += tx;
|
||||
y += ty;
|
||||
|
@ -1193,6 +1398,29 @@ _cairo_pattern_acquire_surface_for_surface (cairo_surface_pattern_t *pattern,
|
|||
|
||||
status = _cairo_surface_clone_similar (dst, pattern->surface,
|
||||
x, y, width, height, out);
|
||||
|
||||
if (status == CAIRO_INT_STATUS_UNSUPPORTED) {
|
||||
|
||||
cairo_t *cr;
|
||||
|
||||
*out = cairo_surface_create_similar (dst, dst->content,
|
||||
width, height);
|
||||
if (!*out)
|
||||
return CAIRO_STATUS_NO_MEMORY;
|
||||
|
||||
(*out)->device_transform = pattern->surface->device_transform;
|
||||
(*out)->device_transform_inverse = pattern->surface->device_transform_inverse;
|
||||
|
||||
/* XXX Use _cairo_surface_composite directly */
|
||||
cr = cairo_create (*out);
|
||||
|
||||
cairo_set_operator (cr, CAIRO_OPERATOR_SOURCE);
|
||||
cairo_set_source_surface (cr, pattern->surface, -x, -y);
|
||||
cairo_paint (cr);
|
||||
|
||||
status = cairo_status (cr);
|
||||
cairo_destroy (cr);
|
||||
}
|
||||
}
|
||||
|
||||
return status;
|
||||
|
@ -1256,10 +1484,10 @@ _cairo_pattern_acquire_surface (cairo_pattern_t *pattern,
|
|||
cairo_color_t color;
|
||||
|
||||
_cairo_color_init_rgba (&color,
|
||||
src->stops->color.red / 65536.0,
|
||||
src->stops->color.green / 65536.0,
|
||||
src->stops->color.blue / 65536.0,
|
||||
src->stops->color.alpha / 65536.0);
|
||||
src->stops->color.red / 65535.0,
|
||||
src->stops->color.green / 65535.0,
|
||||
src->stops->color.blue / 65535.0,
|
||||
src->stops->color.alpha / 65535.0);
|
||||
|
||||
_cairo_pattern_init_solid (&solid, &color);
|
||||
}
|
||||
|
@ -1451,6 +1679,7 @@ _cairo_pattern_get_extents (cairo_pattern_t *pattern,
|
|||
imatrix = pattern->matrix;
|
||||
cairo_matrix_invert (&imatrix);
|
||||
|
||||
/* XXX Use _cairo_matrix_transform_bounding_box here */
|
||||
for (sy = 0; sy <= 1; sy++) {
|
||||
for (sx = 0; sx <= 1; sx++) {
|
||||
x = surface_extents.x + sx * surface_extents.width;
|
||||
|
@ -1569,6 +1798,7 @@ cairo_pattern_get_surface (cairo_pattern_t *pattern,
|
|||
* cairo_pattern_get_color_stop_rgba
|
||||
* @pattern: a #cairo_pattern_t
|
||||
* @index: index of the stop to return data for
|
||||
* @offset: return value for the offset of the stop, or %NULL
|
||||
* @red: return value for red component of color, or %NULL
|
||||
* @green: return value for green component of color, or %NULL
|
||||
* @blue: return value for blue component of color, or %NULL
|
||||
|
@ -1685,12 +1915,12 @@ cairo_pattern_get_linear_points (cairo_pattern_t *pattern,
|
|||
/**
|
||||
* cairo_pattern_get_radial_circles
|
||||
* @pattern: a #cairo_pattern_t
|
||||
* @x0: return value for the x coordinate of the center of the first (inner) circle, or %NULL
|
||||
* @y0: return value for the y coordinate of the center of the first (inner) circle, or %NULL
|
||||
* @r0: return value for the radius of the first (inner) circle, or %NULL
|
||||
* @x1: return value for the x coordinate of the center of the second (outer) circle, or %NULL
|
||||
* @y1: return value for the y coordinate of the center of the second (outer) circle, or %NULL
|
||||
* @r1: return value for the radius of the second (outer) circle, or %NULL
|
||||
* @x0: return value for the x coordinate of the center of the first circle, or %NULL
|
||||
* @y0: return value for the y coordinate of the center of the first circle, or %NULL
|
||||
* @r0: return value for the radius of the first circle, or %NULL
|
||||
* @x1: return value for the x coordinate of the center of the second circle, or %NULL
|
||||
* @y1: return value for the y coordinate of the center of the second circle, or %NULL
|
||||
* @r1: return value for the radius of the second circle, or %NULL
|
||||
*
|
||||
* Gets the gradient endpoint circles for a radial gradient, each
|
||||
* specified as a center coordinate and a radius.
|
||||
|
@ -1712,17 +1942,17 @@ cairo_pattern_get_radial_circles (cairo_pattern_t *pattern,
|
|||
return CAIRO_STATUS_PATTERN_TYPE_MISMATCH;
|
||||
|
||||
if (x0)
|
||||
*x0 = _cairo_fixed_to_double (radial->gradient.inner.x);
|
||||
*x0 = _cairo_fixed_to_double (radial->gradient.c1.x);
|
||||
if (y0)
|
||||
*y0 = _cairo_fixed_to_double (radial->gradient.inner.y);
|
||||
*y0 = _cairo_fixed_to_double (radial->gradient.c1.y);
|
||||
if (r0)
|
||||
*r0 = _cairo_fixed_to_double (radial->gradient.inner.radius);
|
||||
*r0 = _cairo_fixed_to_double (radial->gradient.c1.radius);
|
||||
if (x1)
|
||||
*x1 = _cairo_fixed_to_double (radial->gradient.outer.x);
|
||||
*x1 = _cairo_fixed_to_double (radial->gradient.c2.x);
|
||||
if (y1)
|
||||
*y1 = _cairo_fixed_to_double (radial->gradient.outer.y);
|
||||
*y1 = _cairo_fixed_to_double (radial->gradient.c2.y);
|
||||
if (r1)
|
||||
*r1 = _cairo_fixed_to_double (radial->gradient.outer.radius);
|
||||
*r1 = _cairo_fixed_to_double (radial->gradient.c2.radius);
|
||||
|
||||
return CAIRO_STATUS_SUCCESS;
|
||||
}
|
||||
|
|
|
@ -277,7 +277,8 @@ _cairo_pdf_surface_create_for_stream_internal (cairo_output_stream_t *output,
|
|||
_cairo_array_init (&surface->streams, sizeof (cairo_pdf_resource_t));
|
||||
_cairo_array_init (&surface->alphas, sizeof (double));
|
||||
|
||||
surface->font_subsets = _cairo_scaled_font_subsets_create (PDF_SURFACE_MAX_GLYPHS_PER_FONT);
|
||||
surface->font_subsets = _cairo_scaled_font_subsets_create (PDF_SURFACE_MAX_GLYPHS_PER_FONT,
|
||||
PDF_SURFACE_MAX_GLYPHS_PER_FONT);
|
||||
if (! surface->font_subsets) {
|
||||
_cairo_error (CAIRO_STATUS_NO_MEMORY);
|
||||
free (surface);
|
||||
|
@ -379,7 +380,9 @@ cairo_pdf_surface_create (const char *filename,
|
|||
status = _cairo_output_stream_get_status (output);
|
||||
if (status) {
|
||||
_cairo_error (status);
|
||||
return (cairo_surface_t*) &_cairo_surface_nil;
|
||||
return (status == CAIRO_STATUS_WRITE_ERROR) ?
|
||||
(cairo_surface_t*) &_cairo_surface_nil_write_error :
|
||||
(cairo_surface_t*) &_cairo_surface_nil;
|
||||
}
|
||||
|
||||
return _cairo_pdf_surface_create_for_stream_internal (output,
|
||||
|
@ -654,7 +657,7 @@ compress_dup (const void *data, unsigned long data_size,
|
|||
* no SMask object will be emitted and *id_ret will be set to 0.
|
||||
*/
|
||||
static cairo_status_t
|
||||
emit_smask (cairo_pdf_surface_t *surface,
|
||||
_cairo_pdf_surface_emit_smask (cairo_pdf_surface_t *surface,
|
||||
cairo_image_surface_t *image,
|
||||
cairo_pdf_resource_t *stream_ret)
|
||||
{
|
||||
|
@ -725,7 +728,7 @@ emit_smask (cairo_pdf_surface_t *surface,
|
|||
/* Emit image data into the given surface, providing a resource that
|
||||
* can be used to reference the data in image_ret. */
|
||||
static cairo_status_t
|
||||
emit_image (cairo_pdf_surface_t *surface,
|
||||
_cairo_pdf_surface_emit_image (cairo_pdf_surface_t *surface,
|
||||
cairo_image_surface_t *image,
|
||||
cairo_pdf_resource_t *image_ret)
|
||||
{
|
||||
|
@ -744,7 +747,7 @@ emit_image (cairo_pdf_surface_t *surface,
|
|||
|
||||
/* These are the only image formats we currently support, (which
|
||||
* makes things a lot simpler here). This is enforced through
|
||||
* _analyze_operation which only accept source surfaces of
|
||||
* _cairo_pdf_surface_analyze_operation which only accept source surfaces of
|
||||
* CONTENT_COLOR or CONTENT_COLOR_ALPHA.
|
||||
*/
|
||||
assert (image->format == CAIRO_FORMAT_RGB24 || image->format == CAIRO_FORMAT_ARGB32);
|
||||
|
@ -794,7 +797,7 @@ emit_image (cairo_pdf_surface_t *surface,
|
|||
|
||||
need_smask = FALSE;
|
||||
if (image->format == CAIRO_FORMAT_ARGB32) {
|
||||
status = emit_smask (surface, image, &smask);
|
||||
status = _cairo_pdf_surface_emit_smask (surface, image, &smask);
|
||||
if (status)
|
||||
goto CLEANUP_COMPRESSED;
|
||||
|
||||
|
@ -838,7 +841,7 @@ emit_image (cairo_pdf_surface_t *surface,
|
|||
}
|
||||
|
||||
static cairo_status_t
|
||||
emit_solid_pattern (cairo_pdf_surface_t *surface,
|
||||
_cairo_pdf_surface_emit_solid_pattern (cairo_pdf_surface_t *surface,
|
||||
cairo_solid_pattern_t *pattern)
|
||||
{
|
||||
cairo_pdf_resource_t alpha;
|
||||
|
@ -863,77 +866,80 @@ emit_solid_pattern (cairo_pdf_surface_t *surface,
|
|||
}
|
||||
|
||||
static cairo_status_t
|
||||
emit_surface_pattern (cairo_pdf_surface_t *surface,
|
||||
_cairo_pdf_surface_emit_surface_pattern (cairo_pdf_surface_t *surface,
|
||||
cairo_surface_pattern_t *pattern)
|
||||
{
|
||||
cairo_pdf_resource_t stream;
|
||||
cairo_surface_t *pat_surface;
|
||||
cairo_surface_attributes_t pat_attr;
|
||||
cairo_image_surface_t *image;
|
||||
void *image_extra;
|
||||
cairo_status_t status = CAIRO_STATUS_SUCCESS;
|
||||
cairo_pdf_resource_t alpha, image_resource = {0}; /* squelch bogus compiler warning */
|
||||
cairo_matrix_t cairo_p2d, pdf_p2d;
|
||||
cairo_extend_t extend = cairo_pattern_get_extend (&pattern->base);
|
||||
int xstep, ystep;
|
||||
double xstep, ystep;
|
||||
cairo_rectangle_int16_t surface_extents;
|
||||
|
||||
/* XXX: Should do something clever here for PDF source surfaces ? */
|
||||
|
||||
_cairo_pdf_surface_pause_content_stream (surface);
|
||||
|
||||
status = _cairo_surface_acquire_source_image (pattern->surface, &image, &image_extra);
|
||||
status = _cairo_pattern_acquire_surface ((cairo_pattern_t *)pattern,
|
||||
(cairo_surface_t *)surface,
|
||||
0, 0, -1, -1,
|
||||
&pat_surface, &pat_attr);
|
||||
if (status)
|
||||
return status;
|
||||
|
||||
status = emit_image (surface, image, &image_resource);
|
||||
status = _cairo_surface_acquire_source_image (pat_surface, &image, &image_extra);
|
||||
if (status)
|
||||
goto BAIL2;
|
||||
|
||||
status = _cairo_pdf_surface_emit_image (surface, image, &image_resource);
|
||||
if (status)
|
||||
goto BAIL;
|
||||
|
||||
_cairo_surface_get_extents (&surface->base, &surface_extents);
|
||||
|
||||
switch (extend) {
|
||||
/* We implement EXTEND_PAD like EXTEND_NONE for now */
|
||||
case CAIRO_EXTEND_PAD:
|
||||
case CAIRO_EXTEND_NONE:
|
||||
{
|
||||
/* In PDF, (as far as I can tell), all patterns are
|
||||
/* In PS/PDF, (as far as I can tell), all patterns are
|
||||
* repeating. So we support cairo's EXTEND_NONE semantics
|
||||
* by setting the repeat step size to a size large enough
|
||||
* to guarantee that no more than a single occurrence will
|
||||
* be visible.
|
||||
*
|
||||
* First, map the pattern's extents through the inverse
|
||||
* pattern matrix to compute the device-space bounds of
|
||||
* the desired single occurrence. Then consider the bounds
|
||||
* of (the union of this rectangle with the target surface
|
||||
* extents). If the repeat size is larger than the
|
||||
* diagonal of the bounds of the union, then it is
|
||||
* guaranteed to never repeat visibly.
|
||||
* First, map the surface extents into pattern space (since
|
||||
* xstep and ystep are in pattern space). Then use an upper
|
||||
* bound on the length of the diagonal of the pattern image
|
||||
* and the surface as repeat size. This guarantees to never
|
||||
* repeat visibly.
|
||||
*/
|
||||
double x1 = 0.0, y1 = 0.0;
|
||||
double x2 = image->width, y2 = image->height;
|
||||
cairo_matrix_t surface_to_device = pattern->base.matrix;
|
||||
cairo_matrix_invert (&surface_to_device);
|
||||
cairo_matrix_transform_bounding_box (&surface_to_device,
|
||||
double x2 = surface->width, y2 = surface->height;
|
||||
_cairo_matrix_transform_bounding_box (&pattern->base.matrix,
|
||||
&x1, &y1, &x2, &y2,
|
||||
NULL);
|
||||
|
||||
/* Rather than computing precise bounds of the union, just
|
||||
* add the surface extents unconditionally. We only
|
||||
* required an answer that's large enough, we don't really
|
||||
* care if it's not as tight as possible.*/
|
||||
x1 = MAX (fabs(x1), fabs(x2)) + surface_extents.width;
|
||||
y1 = MAX (fabs(y1), fabs(y2)) + surface_extents.height;
|
||||
/* Similarly, don't bother computing the square root to
|
||||
* determine the length of the final diagonal. */
|
||||
xstep = _cairo_lround (ceil (x1 * y1));
|
||||
ystep = _cairo_lround (ceil (x1 * y1));
|
||||
xstep = ystep = ceil ((x2 - x1) + (y2 - y1) +
|
||||
image->width + image->height);
|
||||
}
|
||||
break;
|
||||
case CAIRO_EXTEND_REPEAT:
|
||||
case CAIRO_EXTEND_REFLECT:
|
||||
xstep = image->width;
|
||||
ystep = image->height;
|
||||
break;
|
||||
/* All the rest should have been analyzed away, so this case
|
||||
* should be unreachable. */
|
||||
case CAIRO_EXTEND_REFLECT:
|
||||
case CAIRO_EXTEND_PAD:
|
||||
/* All the rest (if any) should have been analyzed away, so this
|
||||
* case should be unreachable. */
|
||||
default:
|
||||
ASSERT_NOT_REACHED;
|
||||
xstep = 0;
|
||||
|
@ -980,8 +986,8 @@ emit_surface_pattern (cairo_pdf_surface_t *surface,
|
|||
stream = _cairo_pdf_surface_open_stream (surface,
|
||||
FALSE,
|
||||
" /BBox [0 0 %d %d]\r\n"
|
||||
" /XStep %d\r\n"
|
||||
" /YStep %d\r\n"
|
||||
" /XStep %f\r\n"
|
||||
" /YStep %f\r\n"
|
||||
" /PatternType 1\r\n"
|
||||
" /TilingType 1\r\n"
|
||||
" /PaintType 1\r\n"
|
||||
|
@ -1016,7 +1022,9 @@ emit_surface_pattern (cairo_pdf_surface_t *surface,
|
|||
stream.id, stream.id, alpha.id);
|
||||
|
||||
BAIL:
|
||||
_cairo_surface_release_source_image (pattern->surface, image, image_extra);
|
||||
_cairo_surface_release_source_image (pat_surface, image, image_extra);
|
||||
BAIL2:
|
||||
_cairo_pattern_release_surface ((cairo_pattern_t *)pattern, pat_surface, &pat_attr);
|
||||
|
||||
return status;
|
||||
}
|
||||
|
@ -1028,7 +1036,7 @@ typedef struct _cairo_pdf_color_stop {
|
|||
} cairo_pdf_color_stop_t;
|
||||
|
||||
static cairo_pdf_resource_t
|
||||
emit_linear_colorgradient (cairo_pdf_surface_t *surface,
|
||||
_cairo_pdf_surface_emit_linear_colorgradient (cairo_pdf_surface_t *surface,
|
||||
cairo_pdf_color_stop_t *stop1,
|
||||
cairo_pdf_color_stop_t *stop2)
|
||||
{
|
||||
|
@ -1057,7 +1065,7 @@ emit_linear_colorgradient (cairo_pdf_surface_t *surface,
|
|||
}
|
||||
|
||||
static cairo_pdf_resource_t
|
||||
emit_stitched_colorgradient (cairo_pdf_surface_t *surface,
|
||||
_cairo_pdf_surface_emit_stitched_colorgradient (cairo_pdf_surface_t *surface,
|
||||
unsigned int n_stops,
|
||||
cairo_pdf_color_stop_t stops[])
|
||||
{
|
||||
|
@ -1066,7 +1074,7 @@ emit_stitched_colorgradient (cairo_pdf_surface_t *surface,
|
|||
|
||||
/* emit linear gradients between pairs of subsequent stops... */
|
||||
for (i = 0; i < n_stops-1; i++) {
|
||||
stops[i].gradient = emit_linear_colorgradient (surface,
|
||||
stops[i].gradient = _cairo_pdf_surface_emit_linear_colorgradient (surface,
|
||||
&stops[i],
|
||||
&stops[i+1]);
|
||||
}
|
||||
|
@ -1119,7 +1127,7 @@ emit_stitched_colorgradient (cairo_pdf_surface_t *surface,
|
|||
#define COLOR_STOP_EPSILON 1e-6
|
||||
|
||||
static cairo_pdf_resource_t
|
||||
emit_pattern_stops (cairo_pdf_surface_t *surface, cairo_gradient_pattern_t *pattern)
|
||||
_cairo_pdf_surface_emit_pattern_stops (cairo_pdf_surface_t *surface, cairo_gradient_pattern_t *pattern)
|
||||
{
|
||||
cairo_pdf_resource_t function;
|
||||
cairo_pdf_color_stop_t *allstops, *stops;
|
||||
|
@ -1162,11 +1170,11 @@ emit_pattern_stops (cairo_pdf_surface_t *surface, cairo_gradient_pattern_t *patt
|
|||
|
||||
if (n_stops == 2) {
|
||||
/* no need for stitched function */
|
||||
function = emit_linear_colorgradient (surface, &stops[0], &stops[1]);
|
||||
function = _cairo_pdf_surface_emit_linear_colorgradient (surface, &stops[0], &stops[1]);
|
||||
} else {
|
||||
/* multiple stops: stitch. XXX possible optimization: regulary spaced
|
||||
* stops do not require stitching. XXX */
|
||||
function = emit_stitched_colorgradient (surface,
|
||||
function = _cairo_pdf_surface_emit_stitched_colorgradient (surface,
|
||||
n_stops,
|
||||
stops);
|
||||
}
|
||||
|
@ -1177,7 +1185,7 @@ emit_pattern_stops (cairo_pdf_surface_t *surface, cairo_gradient_pattern_t *patt
|
|||
}
|
||||
|
||||
static cairo_status_t
|
||||
emit_linear_pattern (cairo_pdf_surface_t *surface, cairo_linear_pattern_t *pattern)
|
||||
_cairo_pdf_surface_emit_linear_pattern (cairo_pdf_surface_t *surface, cairo_linear_pattern_t *pattern)
|
||||
{
|
||||
cairo_pdf_resource_t function, pattern_resource, alpha;
|
||||
double x0, y0, x1, y1;
|
||||
|
@ -1185,7 +1193,7 @@ emit_linear_pattern (cairo_pdf_surface_t *surface, cairo_linear_pattern_t *patte
|
|||
|
||||
_cairo_pdf_surface_pause_content_stream (surface);
|
||||
|
||||
function = emit_pattern_stops (surface, &pattern->base);
|
||||
function = _cairo_pdf_surface_emit_pattern_stops (surface, &pattern->base);
|
||||
if (function.id == 0)
|
||||
return CAIRO_STATUS_NO_MEMORY;
|
||||
|
||||
|
@ -1240,7 +1248,7 @@ emit_linear_pattern (cairo_pdf_surface_t *surface, cairo_linear_pattern_t *patte
|
|||
}
|
||||
|
||||
static cairo_status_t
|
||||
emit_radial_pattern (cairo_pdf_surface_t *surface, cairo_radial_pattern_t *pattern)
|
||||
_cairo_pdf_surface_emit_radial_pattern (cairo_pdf_surface_t *surface, cairo_radial_pattern_t *pattern)
|
||||
{
|
||||
cairo_pdf_resource_t function, pattern_resource, alpha;
|
||||
double x0, y0, x1, y1, r0, r1;
|
||||
|
@ -1248,20 +1256,20 @@ emit_radial_pattern (cairo_pdf_surface_t *surface, cairo_radial_pattern_t *patte
|
|||
|
||||
_cairo_pdf_surface_pause_content_stream (surface);
|
||||
|
||||
function = emit_pattern_stops (surface, &pattern->base);
|
||||
function = _cairo_pdf_surface_emit_pattern_stops (surface, &pattern->base);
|
||||
if (function.id == 0)
|
||||
return CAIRO_STATUS_NO_MEMORY;
|
||||
|
||||
p2u = pattern->base.base.matrix;
|
||||
cairo_matrix_invert (&p2u);
|
||||
|
||||
x0 = _cairo_fixed_to_double (pattern->gradient.inner.x);
|
||||
y0 = _cairo_fixed_to_double (pattern->gradient.inner.y);
|
||||
r0 = _cairo_fixed_to_double (pattern->gradient.inner.radius);
|
||||
x0 = _cairo_fixed_to_double (pattern->gradient.c1.x);
|
||||
y0 = _cairo_fixed_to_double (pattern->gradient.c1.y);
|
||||
r0 = _cairo_fixed_to_double (pattern->gradient.c1.radius);
|
||||
cairo_matrix_transform_point (&p2u, &x0, &y0);
|
||||
x1 = _cairo_fixed_to_double (pattern->gradient.outer.x);
|
||||
y1 = _cairo_fixed_to_double (pattern->gradient.outer.y);
|
||||
r1 = _cairo_fixed_to_double (pattern->gradient.outer.radius);
|
||||
x1 = _cairo_fixed_to_double (pattern->gradient.c2.x);
|
||||
y1 = _cairo_fixed_to_double (pattern->gradient.c2.y);
|
||||
r1 = _cairo_fixed_to_double (pattern->gradient.c2.radius);
|
||||
cairo_matrix_transform_point (&p2u, &x1, &y1);
|
||||
|
||||
/* FIXME: This is surely crack, but how should you scale a radius
|
||||
|
@ -1316,20 +1324,20 @@ emit_radial_pattern (cairo_pdf_surface_t *surface, cairo_radial_pattern_t *patte
|
|||
}
|
||||
|
||||
static cairo_status_t
|
||||
emit_pattern (cairo_pdf_surface_t *surface, cairo_pattern_t *pattern)
|
||||
_cairo_pdf_surface_emit_pattern (cairo_pdf_surface_t *surface, cairo_pattern_t *pattern)
|
||||
{
|
||||
switch (pattern->type) {
|
||||
case CAIRO_PATTERN_TYPE_SOLID:
|
||||
return emit_solid_pattern (surface, (cairo_solid_pattern_t *) pattern);
|
||||
return _cairo_pdf_surface_emit_solid_pattern (surface, (cairo_solid_pattern_t *) pattern);
|
||||
|
||||
case CAIRO_PATTERN_TYPE_SURFACE:
|
||||
return emit_surface_pattern (surface, (cairo_surface_pattern_t *) pattern);
|
||||
return _cairo_pdf_surface_emit_surface_pattern (surface, (cairo_surface_pattern_t *) pattern);
|
||||
|
||||
case CAIRO_PATTERN_TYPE_LINEAR:
|
||||
return emit_linear_pattern (surface, (cairo_linear_pattern_t *) pattern);
|
||||
return _cairo_pdf_surface_emit_linear_pattern (surface, (cairo_linear_pattern_t *) pattern);
|
||||
|
||||
case CAIRO_PATTERN_TYPE_RADIAL:
|
||||
return emit_radial_pattern (surface, (cairo_radial_pattern_t *) pattern);
|
||||
return _cairo_pdf_surface_emit_radial_pattern (surface, (cairo_radial_pattern_t *) pattern);
|
||||
|
||||
}
|
||||
|
||||
|
@ -1630,11 +1638,90 @@ _cairo_pdf_surface_write_pages (cairo_pdf_surface_t *surface)
|
|||
"endobj\r\n");
|
||||
}
|
||||
|
||||
static cairo_pdf_resource_t
|
||||
_cairo_pdf_surface_emit_toUnicode_stream (cairo_pdf_surface_t *surface,
|
||||
cairo_scaled_font_subset_t *font_subset)
|
||||
{
|
||||
const cairo_scaled_font_backend_t *backend;
|
||||
cairo_pdf_resource_t stream;
|
||||
unsigned int i;
|
||||
|
||||
if (font_subset->to_unicode == NULL) {
|
||||
stream.id = 0;
|
||||
return stream;
|
||||
}
|
||||
|
||||
if (_cairo_truetype_create_glyph_to_unicode_map (font_subset) != CAIRO_STATUS_SUCCESS) {
|
||||
backend = font_subset->scaled_font->backend;
|
||||
if (backend->map_glyphs_to_unicode == NULL) {
|
||||
stream.id = 0;
|
||||
return stream;
|
||||
}
|
||||
backend->map_glyphs_to_unicode (font_subset->scaled_font, font_subset);
|
||||
}
|
||||
|
||||
stream = _cairo_pdf_surface_open_stream (surface, FALSE, NULL);
|
||||
_cairo_output_stream_printf (surface->output,
|
||||
"/CIDInit /ProcSet findresource begin\r\n"
|
||||
"12 dict begin\r\n"
|
||||
"begincmap\r\n"
|
||||
"/CIDSystemInfo\r\n"
|
||||
"<< /Registry (Cairo)\r\n"
|
||||
" /Ordering (ToUnicode-%d-%d)\r\n"
|
||||
" /Supplement 0\r\n"
|
||||
">> def\r\n"
|
||||
"/CMapName /Cairo-ToUnicode-%d-%d def\r\n"
|
||||
"/CMapType 2 def\r\n"
|
||||
"1 begincodespacerange\r\n"
|
||||
"<00> <ff>\r\n"
|
||||
"endcodespacerange\r\n",
|
||||
font_subset->font_id,
|
||||
font_subset->subset_id,
|
||||
font_subset->font_id,
|
||||
font_subset->subset_id);
|
||||
|
||||
/* The CMap specification has a limit of 100 characters per beginbfchar operator */
|
||||
_cairo_output_stream_printf (surface->output,
|
||||
"%d beginbfchar\r\n",
|
||||
font_subset->num_glyphs > 100 ? 100 : font_subset->num_glyphs);
|
||||
for (i = 0; i < font_subset->num_glyphs; i++) {
|
||||
if (i != 0 && i % 100 == 0) {
|
||||
_cairo_output_stream_printf (surface->output,
|
||||
"endbfchar\r\n"
|
||||
"%d beginbfchar\r\n",
|
||||
font_subset->num_glyphs - i > 100 ? 100 : font_subset->num_glyphs - i);
|
||||
}
|
||||
_cairo_output_stream_printf (surface->output,
|
||||
"<%02x> <%04x>\r\n",
|
||||
i, font_subset->to_unicode[i]);
|
||||
}
|
||||
_cairo_output_stream_printf (surface->output,
|
||||
"endbfchar\r\n");
|
||||
|
||||
if (font_subset->num_glyphs < 256) {
|
||||
_cairo_output_stream_printf (surface->output,
|
||||
"1 beginnotdefrange\r\n"
|
||||
"<%02x> <ff> 0\r\n"
|
||||
"endnotdefrange\r\n",
|
||||
font_subset->num_glyphs);
|
||||
}
|
||||
|
||||
_cairo_output_stream_printf (surface->output,
|
||||
"endcmap\r\n"
|
||||
"CMapName currentdict /CMap defineresource pop\r\n"
|
||||
"end\r\n"
|
||||
"end\r\n");
|
||||
|
||||
_cairo_pdf_surface_close_stream (surface);
|
||||
|
||||
return stream;
|
||||
}
|
||||
|
||||
static cairo_status_t
|
||||
_cairo_pdf_surface_emit_cff_font_subset (cairo_pdf_surface_t *surface,
|
||||
cairo_scaled_font_subset_t *font_subset)
|
||||
{
|
||||
cairo_pdf_resource_t stream, descriptor, subset_resource;
|
||||
cairo_pdf_resource_t stream, descriptor, subset_resource, to_unicode_stream;
|
||||
cairo_status_t status;
|
||||
cairo_pdf_font_t font;
|
||||
cairo_cff_subset_t subset;
|
||||
|
@ -1672,6 +1759,8 @@ _cairo_pdf_surface_emit_cff_font_subset (cairo_pdf_surface_t *surface,
|
|||
"endobj\r\n");
|
||||
free (compressed);
|
||||
|
||||
to_unicode_stream = _cairo_pdf_surface_emit_toUnicode_stream (surface, font_subset);
|
||||
|
||||
descriptor = _cairo_pdf_surface_new_object (surface);
|
||||
_cairo_output_stream_printf (surface->output,
|
||||
"%d 0 obj\r\n"
|
||||
|
@ -1710,7 +1799,7 @@ _cairo_pdf_surface_emit_cff_font_subset (cairo_pdf_surface_t *surface,
|
|||
" /Widths [",
|
||||
subset_resource.id,
|
||||
subset.base_font,
|
||||
font_subset->num_glyphs,
|
||||
font_subset->num_glyphs - 1,
|
||||
descriptor.id);
|
||||
|
||||
for (i = 0; i < font_subset->num_glyphs; i++)
|
||||
|
@ -1719,7 +1808,14 @@ _cairo_pdf_surface_emit_cff_font_subset (cairo_pdf_surface_t *surface,
|
|||
subset.widths[i]);
|
||||
|
||||
_cairo_output_stream_printf (surface->output,
|
||||
" ]\r\n"
|
||||
" ]\r\n");
|
||||
|
||||
if (to_unicode_stream.id != 0)
|
||||
_cairo_output_stream_printf (surface->output,
|
||||
" /ToUnicode %d 0 R\r\n",
|
||||
to_unicode_stream.id);
|
||||
|
||||
_cairo_output_stream_printf (surface->output,
|
||||
">>\r\n"
|
||||
"endobj\r\n");
|
||||
|
||||
|
@ -1738,7 +1834,7 @@ _cairo_pdf_surface_emit_type1_font (cairo_pdf_surface_t *surface,
|
|||
cairo_scaled_font_subset_t *font_subset,
|
||||
cairo_type1_subset_t *subset)
|
||||
{
|
||||
cairo_pdf_resource_t stream, descriptor, subset_resource;
|
||||
cairo_pdf_resource_t stream, descriptor, subset_resource, to_unicode_stream;
|
||||
cairo_pdf_font_t font;
|
||||
unsigned long length, compressed_length;
|
||||
char *compressed;
|
||||
|
@ -1772,6 +1868,8 @@ _cairo_pdf_surface_emit_type1_font (cairo_pdf_surface_t *surface,
|
|||
"endobj\r\n");
|
||||
free (compressed);
|
||||
|
||||
to_unicode_stream = _cairo_pdf_surface_emit_toUnicode_stream (surface, font_subset);
|
||||
|
||||
descriptor = _cairo_pdf_surface_new_object (surface);
|
||||
_cairo_output_stream_printf (surface->output,
|
||||
"%d 0 obj\r\n"
|
||||
|
@ -1819,7 +1917,14 @@ _cairo_pdf_surface_emit_type1_font (cairo_pdf_surface_t *surface,
|
|||
subset->widths[i]);
|
||||
|
||||
_cairo_output_stream_printf (surface->output,
|
||||
" ]\r\n"
|
||||
" ]\r\n");
|
||||
|
||||
if (to_unicode_stream.id != 0)
|
||||
_cairo_output_stream_printf (surface->output,
|
||||
" /ToUnicode %d 0 R\r\n",
|
||||
to_unicode_stream.id);
|
||||
|
||||
_cairo_output_stream_printf (surface->output,
|
||||
">>\r\n"
|
||||
"endobj\r\n");
|
||||
|
||||
|
@ -1873,11 +1978,13 @@ _cairo_pdf_surface_emit_type1_fallback_font (cairo_pdf_surface_t *surface,
|
|||
return status;
|
||||
}
|
||||
|
||||
#define PDF_UNITS_PER_EM 1000
|
||||
|
||||
static cairo_status_t
|
||||
_cairo_pdf_surface_emit_truetype_font_subset (cairo_pdf_surface_t *surface,
|
||||
cairo_scaled_font_subset_t *font_subset)
|
||||
{
|
||||
cairo_pdf_resource_t stream, descriptor, subset_resource;
|
||||
cairo_pdf_resource_t stream, descriptor, encoding, subset_resource, to_unicode_stream;
|
||||
cairo_status_t status;
|
||||
cairo_pdf_font_t font;
|
||||
cairo_truetype_subset_t subset;
|
||||
|
@ -1914,17 +2021,19 @@ _cairo_pdf_surface_emit_truetype_font_subset (cairo_pdf_surface_t *surface,
|
|||
"endobj\r\n");
|
||||
free (compressed);
|
||||
|
||||
to_unicode_stream = _cairo_pdf_surface_emit_toUnicode_stream (surface, font_subset);
|
||||
|
||||
descriptor = _cairo_pdf_surface_new_object (surface);
|
||||
_cairo_output_stream_printf (surface->output,
|
||||
"%d 0 obj\r\n"
|
||||
"<< /Type /FontDescriptor\r\n"
|
||||
" /FontName /7%s\r\n"
|
||||
" /FontName /%s\r\n"
|
||||
" /Flags 4\r\n"
|
||||
" /FontBBox [ %ld %ld %ld %ld ]\r\n"
|
||||
" /ItalicAngle 0\r\n"
|
||||
" /Ascent %ld\r\n"
|
||||
" /Descent %ld\r\n"
|
||||
" /CapHeight 500\r\n"
|
||||
" /CapHeight %ld\r\n"
|
||||
" /StemV 80\r\n"
|
||||
" /StemH 80\r\n"
|
||||
" /FontFile2 %u 0 R\r\n"
|
||||
|
@ -1932,14 +2041,30 @@ _cairo_pdf_surface_emit_truetype_font_subset (cairo_pdf_surface_t *surface,
|
|||
"endobj\r\n",
|
||||
descriptor.id,
|
||||
subset.base_font,
|
||||
subset.x_min,
|
||||
subset.y_min,
|
||||
subset.x_max,
|
||||
subset.y_max,
|
||||
subset.ascent,
|
||||
subset.descent,
|
||||
(long)(subset.x_min*PDF_UNITS_PER_EM),
|
||||
(long)(subset.y_min*PDF_UNITS_PER_EM),
|
||||
(long)(subset.x_max*PDF_UNITS_PER_EM),
|
||||
(long)(subset.y_max*PDF_UNITS_PER_EM),
|
||||
(long)(subset.ascent*PDF_UNITS_PER_EM),
|
||||
(long)(subset.descent*PDF_UNITS_PER_EM),
|
||||
(long)(subset.y_max*PDF_UNITS_PER_EM),
|
||||
stream.id);
|
||||
|
||||
encoding = _cairo_pdf_surface_new_object (surface);
|
||||
_cairo_output_stream_printf (surface->output,
|
||||
"%d 0 obj\r\n"
|
||||
"<< /Type /Encoding\r\n"
|
||||
" /Differences [0 ",
|
||||
encoding.id);
|
||||
|
||||
for (i = 0; i < font_subset->num_glyphs; i++)
|
||||
_cairo_output_stream_printf (surface->output, "/g%d ", i);
|
||||
|
||||
_cairo_output_stream_printf (surface->output,
|
||||
" ]\r\n"
|
||||
">>\r\n"
|
||||
"endobj\r\n");
|
||||
|
||||
subset_resource = _cairo_pdf_surface_new_object (surface);
|
||||
_cairo_output_stream_printf (surface->output,
|
||||
"%d 0 obj\r\n"
|
||||
|
@ -1949,19 +2074,28 @@ _cairo_pdf_surface_emit_truetype_font_subset (cairo_pdf_surface_t *surface,
|
|||
" /FirstChar 0\r\n"
|
||||
" /LastChar %d\r\n"
|
||||
" /FontDescriptor %d 0 R\r\n"
|
||||
" /Encoding %d 0 R\r\n"
|
||||
" /Widths [",
|
||||
subset_resource.id,
|
||||
subset.base_font,
|
||||
font_subset->num_glyphs - 1,
|
||||
descriptor.id);
|
||||
descriptor.id,
|
||||
encoding.id);
|
||||
|
||||
for (i = 0; i < font_subset->num_glyphs; i++)
|
||||
_cairo_output_stream_printf (surface->output,
|
||||
" %d",
|
||||
subset.widths[i]);
|
||||
" %ld",
|
||||
(long)(subset.widths[i]*PDF_UNITS_PER_EM));
|
||||
|
||||
_cairo_output_stream_printf (surface->output,
|
||||
" ]\r\n");
|
||||
|
||||
if (to_unicode_stream.id != 0)
|
||||
_cairo_output_stream_printf (surface->output,
|
||||
" /ToUnicode %d 0 R\r\n",
|
||||
to_unicode_stream.id);
|
||||
|
||||
_cairo_output_stream_printf (surface->output,
|
||||
" ]\r\n"
|
||||
">>\r\n"
|
||||
"endobj\r\n");
|
||||
|
||||
|
@ -2025,13 +2159,16 @@ static cairo_int_status_t
|
|||
_cairo_pdf_surface_emit_bitmap_glyph (cairo_pdf_surface_t *surface,
|
||||
cairo_scaled_font_t *scaled_font,
|
||||
unsigned long glyph_index,
|
||||
cairo_pdf_resource_t *glyph_ret)
|
||||
cairo_pdf_resource_t *glyph_ret,
|
||||
cairo_box_t *bbox,
|
||||
double *width)
|
||||
{
|
||||
cairo_scaled_glyph_t *scaled_glyph;
|
||||
cairo_status_t status;
|
||||
cairo_image_surface_t *image;
|
||||
unsigned char *row, *byte;
|
||||
int rows, cols;
|
||||
double x_advance, y_advance;
|
||||
|
||||
status = _cairo_scaled_glyph_lookup (scaled_font,
|
||||
glyph_index,
|
||||
|
@ -2041,6 +2178,12 @@ _cairo_pdf_surface_emit_bitmap_glyph (cairo_pdf_surface_t *surface,
|
|||
if (status)
|
||||
return status;
|
||||
|
||||
x_advance = scaled_glyph->metrics.x_advance;
|
||||
y_advance = scaled_glyph->metrics.y_advance;
|
||||
cairo_matrix_transform_distance (&scaled_font->ctm, &x_advance, &y_advance);
|
||||
*bbox = scaled_glyph->bbox;
|
||||
*width = x_advance;
|
||||
|
||||
image = scaled_glyph->surface;
|
||||
if (image->format != CAIRO_FORMAT_A1) {
|
||||
image = _cairo_image_surface_clone (image, CAIRO_FORMAT_A1);
|
||||
|
@ -2048,17 +2191,18 @@ _cairo_pdf_surface_emit_bitmap_glyph (cairo_pdf_surface_t *surface,
|
|||
return cairo_surface_status (&image->base);
|
||||
}
|
||||
|
||||
*glyph_ret = _cairo_pdf_surface_open_stream (surface, FALSE, NULL);
|
||||
*glyph_ret = _cairo_pdf_surface_open_stream (surface, TRUE, NULL);
|
||||
|
||||
_cairo_output_stream_printf (surface->output,
|
||||
"0 0 %f %f %f %f d1\r\n",
|
||||
"%f 0 %f %f %f %f d1\r\n",
|
||||
x_advance,
|
||||
_cairo_fixed_to_double (scaled_glyph->bbox.p1.x),
|
||||
- _cairo_fixed_to_double (scaled_glyph->bbox.p2.y),
|
||||
_cairo_fixed_to_double (scaled_glyph->bbox.p2.y),
|
||||
_cairo_fixed_to_double (scaled_glyph->bbox.p2.x),
|
||||
- _cairo_fixed_to_double (scaled_glyph->bbox.p1.y));
|
||||
_cairo_fixed_to_double (scaled_glyph->bbox.p1.y));
|
||||
|
||||
_cairo_output_stream_printf (surface->output,
|
||||
"%f 0.0 0.0 %f %f %f cm\r\n",
|
||||
"%f 0 0 %f %f %f cm\r\n",
|
||||
_cairo_fixed_to_double (scaled_glyph->bbox.p2.x) - _cairo_fixed_to_double (scaled_glyph->bbox.p1.x),
|
||||
_cairo_fixed_to_double (scaled_glyph->bbox.p1.y) - _cairo_fixed_to_double (scaled_glyph->bbox.p2.y),
|
||||
_cairo_fixed_to_double (scaled_glyph->bbox.p1.x),
|
||||
|
@ -2097,7 +2241,9 @@ static void
|
|||
_cairo_pdf_surface_emit_glyph (cairo_pdf_surface_t *surface,
|
||||
cairo_scaled_font_t *scaled_font,
|
||||
unsigned long glyph_index,
|
||||
cairo_pdf_resource_t *glyph_ret)
|
||||
cairo_pdf_resource_t *glyph_ret,
|
||||
cairo_box_t *bbox,
|
||||
double *width)
|
||||
{
|
||||
cairo_status_t status;
|
||||
|
||||
|
@ -2109,7 +2255,9 @@ _cairo_pdf_surface_emit_glyph (cairo_pdf_surface_t *surface,
|
|||
status = _cairo_pdf_surface_emit_bitmap_glyph (surface,
|
||||
scaled_font,
|
||||
glyph_index,
|
||||
glyph_ret);
|
||||
glyph_ret,
|
||||
bbox,
|
||||
width);
|
||||
|
||||
if (status)
|
||||
_cairo_surface_set_error (&surface->base, status);
|
||||
|
@ -2119,10 +2267,13 @@ static cairo_status_t
|
|||
_cairo_pdf_surface_emit_type3_font_subset (cairo_pdf_surface_t *surface,
|
||||
cairo_scaled_font_subset_t *font_subset)
|
||||
{
|
||||
cairo_pdf_resource_t *glyphs, encoding, char_procs, subset_resource;
|
||||
cairo_pdf_resource_t *glyphs, encoding, char_procs, subset_resource, to_unicode_stream;
|
||||
cairo_pdf_font_t font;
|
||||
cairo_matrix_t matrix;
|
||||
double *widths;
|
||||
unsigned int i;
|
||||
cairo_box_t font_bbox = {{0,0},{0,0}};
|
||||
cairo_box_t bbox = {{0,0},{0,0}};
|
||||
|
||||
glyphs = malloc (font_subset->num_glyphs * sizeof (cairo_pdf_resource_t));
|
||||
if (glyphs == NULL) {
|
||||
|
@ -2130,11 +2281,35 @@ _cairo_pdf_surface_emit_type3_font_subset (cairo_pdf_surface_t *surface,
|
|||
return CAIRO_STATUS_NO_MEMORY;
|
||||
}
|
||||
|
||||
widths = malloc (font_subset->num_glyphs * sizeof (double));
|
||||
if (widths == NULL) {
|
||||
free (glyphs);
|
||||
_cairo_surface_set_error (&surface->base, CAIRO_STATUS_NO_MEMORY);
|
||||
return CAIRO_STATUS_NO_MEMORY;
|
||||
}
|
||||
|
||||
for (i = 0; i < font_subset->num_glyphs; i++) {
|
||||
_cairo_pdf_surface_emit_glyph (surface,
|
||||
font_subset->scaled_font,
|
||||
font_subset->glyphs[i],
|
||||
&glyphs[i]);
|
||||
&glyphs[i],
|
||||
&bbox,
|
||||
&widths[i]);
|
||||
if (i == 0) {
|
||||
font_bbox.p1.x = bbox.p1.x;
|
||||
font_bbox.p1.y = bbox.p1.y;
|
||||
font_bbox.p2.x = bbox.p2.x;
|
||||
font_bbox.p2.y = bbox.p2.y;
|
||||
} else {
|
||||
if (bbox.p1.x < font_bbox.p1.x)
|
||||
font_bbox.p1.x = bbox.p1.x;
|
||||
if (bbox.p1.y < font_bbox.p1.y)
|
||||
font_bbox.p1.y = bbox.p1.y;
|
||||
if (bbox.p2.x > font_bbox.p2.x)
|
||||
font_bbox.p2.x = bbox.p2.x;
|
||||
if (bbox.p2.y > font_bbox.p2.y)
|
||||
font_bbox.p2.y = bbox.p2.y;
|
||||
}
|
||||
}
|
||||
|
||||
encoding = _cairo_pdf_surface_new_object (surface);
|
||||
|
@ -2164,6 +2339,8 @@ _cairo_pdf_surface_emit_type3_font_subset (cairo_pdf_surface_t *surface,
|
|||
|
||||
free (glyphs);
|
||||
|
||||
to_unicode_stream = _cairo_pdf_surface_emit_toUnicode_stream (surface, font_subset);
|
||||
|
||||
subset_resource = _cairo_pdf_surface_new_object (surface);
|
||||
matrix = font_subset->scaled_font->scale;
|
||||
cairo_matrix_invert (&matrix);
|
||||
|
@ -2171,13 +2348,17 @@ _cairo_pdf_surface_emit_type3_font_subset (cairo_pdf_surface_t *surface,
|
|||
"%d 0 obj\r\n"
|
||||
"<< /Type /Font\r\n"
|
||||
" /Subtype /Type3\r\n"
|
||||
" /FontBBox [0 0 0 0]\r\n"
|
||||
" /FontBBox [%f %f %f %f]\r\n"
|
||||
" /FontMatrix [ %f %f %f %f 0 0 ]\r\n"
|
||||
" /Encoding %d 0 R\r\n"
|
||||
" /CharProcs %d 0 R\r\n"
|
||||
" /FirstChar 0\r\n"
|
||||
" /LastChar %d\r\n",
|
||||
subset_resource.id,
|
||||
_cairo_fixed_to_double (font_bbox.p1.x),
|
||||
_cairo_fixed_to_double (font_bbox.p1.y),
|
||||
_cairo_fixed_to_double (font_bbox.p2.x),
|
||||
_cairo_fixed_to_double (font_bbox.p2.y),
|
||||
matrix.xx,
|
||||
matrix.yx,
|
||||
-matrix.xy,
|
||||
|
@ -2189,9 +2370,15 @@ _cairo_pdf_surface_emit_type3_font_subset (cairo_pdf_surface_t *surface,
|
|||
_cairo_output_stream_printf (surface->output,
|
||||
" /Widths [");
|
||||
for (i = 0; i < font_subset->num_glyphs; i++)
|
||||
_cairo_output_stream_printf (surface->output, " 0");
|
||||
_cairo_output_stream_printf (surface->output, " %f", widths[i]);
|
||||
_cairo_output_stream_printf (surface->output,
|
||||
"]\r\n");
|
||||
free (widths);
|
||||
|
||||
if (to_unicode_stream.id != 0)
|
||||
_cairo_output_stream_printf (surface->output,
|
||||
" /ToUnicode %d 0 R\r\n",
|
||||
to_unicode_stream.id);
|
||||
|
||||
_cairo_output_stream_printf (surface->output,
|
||||
">>\r\n"
|
||||
|
@ -2206,7 +2393,7 @@ _cairo_pdf_surface_emit_type3_font_subset (cairo_pdf_surface_t *surface,
|
|||
}
|
||||
|
||||
static void
|
||||
_cairo_pdf_surface_emit_font_subset (cairo_scaled_font_subset_t *font_subset,
|
||||
_cairo_pdf_surface_emit_unscaled_font_subset (cairo_scaled_font_subset_t *font_subset,
|
||||
void *closure)
|
||||
{
|
||||
cairo_pdf_surface_t *surface = closure;
|
||||
|
@ -2229,6 +2416,14 @@ _cairo_pdf_surface_emit_font_subset (cairo_scaled_font_subset_t *font_subset,
|
|||
status = _cairo_pdf_surface_emit_type1_fallback_font (surface, font_subset);
|
||||
if (status != CAIRO_INT_STATUS_UNSUPPORTED)
|
||||
return;
|
||||
}
|
||||
|
||||
static void
|
||||
_cairo_pdf_surface_emit_scaled_font_subset (cairo_scaled_font_subset_t *font_subset,
|
||||
void *closure)
|
||||
{
|
||||
cairo_pdf_surface_t *surface = closure;
|
||||
cairo_status_t status;
|
||||
|
||||
status = _cairo_pdf_surface_emit_type3_font_subset (surface, font_subset);
|
||||
if (status != CAIRO_INT_STATUS_UNSUPPORTED)
|
||||
|
@ -2240,8 +2435,11 @@ _cairo_pdf_surface_emit_font_subsets (cairo_pdf_surface_t *surface)
|
|||
{
|
||||
cairo_status_t status;
|
||||
|
||||
status = _cairo_scaled_font_subsets_foreach (surface->font_subsets,
|
||||
_cairo_pdf_surface_emit_font_subset,
|
||||
status = _cairo_scaled_font_subsets_foreach_unscaled (surface->font_subsets,
|
||||
_cairo_pdf_surface_emit_unscaled_font_subset,
|
||||
surface);
|
||||
status = _cairo_scaled_font_subsets_foreach_scaled (surface->font_subsets,
|
||||
_cairo_pdf_surface_emit_scaled_font_subset,
|
||||
surface);
|
||||
_cairo_scaled_font_subsets_destroy (surface->font_subsets);
|
||||
surface->font_subsets = NULL;
|
||||
|
@ -2252,114 +2450,6 @@ _cairo_pdf_surface_emit_font_subsets (cairo_pdf_surface_t *surface)
|
|||
return CAIRO_STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
#if 0
|
||||
static cairo_status_t
|
||||
_cairo_pdf_surface_write_fonts (cairo_pdf_surface_t *surface)
|
||||
{
|
||||
cairo_font_subset_t *font;
|
||||
cairo_pdf_resource_t font_resource;
|
||||
int num_fonts, i, j;
|
||||
const char *data;
|
||||
char *compressed;
|
||||
unsigned long data_size, compressed_size;
|
||||
cairo_pdf_resource_t stream, descriptor;
|
||||
cairo_status_t status = CAIRO_STATUS_SUCCESS;
|
||||
|
||||
num_fonts = _cairo_array_num_elements (&surface->fonts);
|
||||
for (i = 0; i < num_fonts; i++) {
|
||||
_cairo_array_copy_element (&surface->fonts, i, &font);
|
||||
|
||||
status = _cairo_font_subset_generate (font, &data, &data_size);
|
||||
if (status)
|
||||
goto fail;
|
||||
|
||||
compressed = compress_dup (data, data_size, &compressed_size);
|
||||
if (compressed == NULL) {
|
||||
status = CAIRO_STATUS_NO_MEMORY;
|
||||
goto fail;
|
||||
}
|
||||
|
||||
stream = _cairo_pdf_surface_new_object (surface);
|
||||
_cairo_output_stream_printf (surface->output,
|
||||
"%d 0 obj\r\n"
|
||||
"<< /Filter /FlateDecode\r\n"
|
||||
" /Length %lu\r\n"
|
||||
" /Length1 %lu\r\n"
|
||||
">>\r\n"
|
||||
"stream\r\n",
|
||||
stream.id,
|
||||
compressed_size,
|
||||
data_size);
|
||||
_cairo_output_stream_write (surface->output, compressed, compressed_size);
|
||||
_cairo_output_stream_printf (surface->output,
|
||||
"\r\n"
|
||||
"endstream\r\n"
|
||||
"endobj\r\n");
|
||||
free (compressed);
|
||||
|
||||
descriptor = _cairo_pdf_surface_new_object (surface);
|
||||
_cairo_output_stream_printf (surface->output,
|
||||
"%d 0 obj\r\n"
|
||||
"<< /Type /FontDescriptor\r\n"
|
||||
" /FontName /7%s\r\n"
|
||||
" /Flags 4\r\n"
|
||||
" /FontBBox [ %ld %ld %ld %ld ]\r\n"
|
||||
" /ItalicAngle 0\r\n"
|
||||
" /Ascent %ld\r\n"
|
||||
" /Descent %ld\r\n"
|
||||
" /CapHeight 500\r\n"
|
||||
" /StemV 80\r\n"
|
||||
" /StemH 80\r\n"
|
||||
" /FontFile2 %u 0 R\r\n"
|
||||
">>\r\n"
|
||||
"endobj\r\n",
|
||||
descriptor.id,
|
||||
font->base_font,
|
||||
font->x_min,
|
||||
font->y_min,
|
||||
font->x_max,
|
||||
font->y_max,
|
||||
font->ascent,
|
||||
font->descent,
|
||||
stream.id);
|
||||
|
||||
font_resource.id = font->font_id;
|
||||
_cairo_pdf_surface_update_object (surface, font_resource);
|
||||
_cairo_output_stream_printf (surface->output,
|
||||
"%d 0 obj\r\n"
|
||||
"<< /Type /Font\r\n"
|
||||
" /Subtype /TrueType\r\n"
|
||||
" /BaseFont /%s\r\n"
|
||||
" /FirstChar 0\r\n"
|
||||
" /LastChar %d\r\n"
|
||||
" /FontDescriptor %d 0 R\r\n"
|
||||
" /Widths ",
|
||||
font->font_id,
|
||||
font->base_font,
|
||||
font->num_glyphs,
|
||||
descriptor.id);
|
||||
|
||||
_cairo_output_stream_printf (surface->output,
|
||||
"[");
|
||||
|
||||
for (j = 0; j < font->num_glyphs; j++)
|
||||
_cairo_output_stream_printf (surface->output,
|
||||
" %d",
|
||||
font->widths[j]);
|
||||
|
||||
_cairo_output_stream_printf (surface->output,
|
||||
" ]\r\n"
|
||||
">>\r\n"
|
||||
"endobj\r\n");
|
||||
|
||||
fail:
|
||||
_cairo_font_subset_destroy (font);
|
||||
}
|
||||
|
||||
return status;
|
||||
}
|
||||
#endif
|
||||
|
||||
static cairo_pdf_resource_t
|
||||
_cairo_pdf_surface_write_catalog (cairo_pdf_surface_t *surface)
|
||||
{
|
||||
|
@ -2444,9 +2534,12 @@ _cairo_pdf_surface_write_page (cairo_pdf_surface_t *surface)
|
|||
stream.id);
|
||||
}
|
||||
_cairo_output_stream_printf (surface->output,
|
||||
" ]\r\n");
|
||||
|
||||
_cairo_output_stream_printf (surface->output,
|
||||
" ]\r\n"
|
||||
" /Group <<\r\n"
|
||||
" /Type /Group\r\n"
|
||||
" /S /Transparency\r\n"
|
||||
" /CS /DeviceRGB\r\n"
|
||||
" >>\r\n"
|
||||
">>\r\n"
|
||||
"endobj\r\n");
|
||||
|
||||
|
@ -2478,10 +2571,11 @@ _surface_pattern_supported (cairo_surface_pattern_t *pattern)
|
|||
switch (extend) {
|
||||
case CAIRO_EXTEND_NONE:
|
||||
case CAIRO_EXTEND_REPEAT:
|
||||
return TRUE;
|
||||
case CAIRO_EXTEND_REFLECT:
|
||||
/* There's no point returning FALSE for EXTEND_PAD, as the image
|
||||
* surface does not currently implement it either */
|
||||
case CAIRO_EXTEND_PAD:
|
||||
return FALSE;
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
ASSERT_NOT_REACHED;
|
||||
|
@ -2521,7 +2615,7 @@ _cairo_pdf_test_force_fallbacks (void)
|
|||
}
|
||||
|
||||
static cairo_int_status_t
|
||||
_operation_supported (cairo_pdf_surface_t *surface,
|
||||
__cairo_pdf_surface_operation_supported (cairo_pdf_surface_t *surface,
|
||||
cairo_operator_t op,
|
||||
cairo_pattern_t *pattern)
|
||||
{
|
||||
|
@ -2540,11 +2634,11 @@ _operation_supported (cairo_pdf_surface_t *surface,
|
|||
}
|
||||
|
||||
static cairo_int_status_t
|
||||
_analyze_operation (cairo_pdf_surface_t *surface,
|
||||
_cairo_pdf_surface_analyze_operation (cairo_pdf_surface_t *surface,
|
||||
cairo_operator_t op,
|
||||
cairo_pattern_t *pattern)
|
||||
{
|
||||
if (_operation_supported (surface, op, pattern))
|
||||
if (__cairo_pdf_surface_operation_supported (surface, op, pattern))
|
||||
return CAIRO_STATUS_SUCCESS;
|
||||
else
|
||||
return CAIRO_INT_STATUS_UNSUPPORTED;
|
||||
|
@ -2559,7 +2653,7 @@ _cairo_pdf_surface_paint (void *abstract_surface,
|
|||
cairo_status_t status;
|
||||
|
||||
if (surface->paginated_mode == CAIRO_PAGINATED_MODE_ANALYZE)
|
||||
return _analyze_operation (surface, op, source);
|
||||
return _cairo_pdf_surface_analyze_operation (surface, op, source);
|
||||
|
||||
/* XXX: It would be nice to be able to assert this condition
|
||||
* here. But, we actually allow one 'cheat' that is used when
|
||||
|
@ -2568,10 +2662,10 @@ _cairo_pdf_surface_paint (void *abstract_surface,
|
|||
* possible only because there is nothing between the fallback
|
||||
* images and the paper, nor is anything painted above. */
|
||||
/*
|
||||
assert (_operation_supported (op, source));
|
||||
assert (__cairo_pdf_surface_operation_supported (op, source));
|
||||
*/
|
||||
|
||||
status = emit_pattern (surface, source);
|
||||
status = _cairo_pdf_surface_emit_pattern (surface, source);
|
||||
if (status)
|
||||
return status;
|
||||
|
||||
|
@ -2680,11 +2774,11 @@ _cairo_pdf_surface_stroke (void *abstract_surface,
|
|||
cairo_status_t status;
|
||||
|
||||
if (surface->paginated_mode == CAIRO_PAGINATED_MODE_ANALYZE)
|
||||
return _analyze_operation (surface, op, source);
|
||||
return _cairo_pdf_surface_analyze_operation (surface, op, source);
|
||||
|
||||
assert (_operation_supported (surface, op, source));
|
||||
assert (__cairo_pdf_surface_operation_supported (surface, op, source));
|
||||
|
||||
status = emit_pattern (surface, source);
|
||||
status = _cairo_pdf_surface_emit_pattern (surface, source);
|
||||
if (status)
|
||||
return status;
|
||||
|
||||
|
@ -2729,11 +2823,11 @@ _cairo_pdf_surface_fill (void *abstract_surface,
|
|||
pdf_path_info_t info;
|
||||
|
||||
if (surface->paginated_mode == CAIRO_PAGINATED_MODE_ANALYZE)
|
||||
return _analyze_operation (surface, op, source);
|
||||
return _cairo_pdf_surface_analyze_operation (surface, op, source);
|
||||
|
||||
assert (_operation_supported (surface, op, source));
|
||||
assert (__cairo_pdf_surface_operation_supported (surface, op, source));
|
||||
|
||||
status = emit_pattern (surface, source);
|
||||
status = _cairo_pdf_surface_emit_pattern (surface, source);
|
||||
if (status)
|
||||
return status;
|
||||
|
||||
|
@ -2782,11 +2876,11 @@ _cairo_pdf_surface_show_glyphs (void *abstract_surface,
|
|||
int i;
|
||||
|
||||
if (surface->paginated_mode == CAIRO_PAGINATED_MODE_ANALYZE)
|
||||
return _analyze_operation (surface, op, source);
|
||||
return _cairo_pdf_surface_analyze_operation (surface, op, source);
|
||||
|
||||
assert (_operation_supported (surface, op, source));
|
||||
assert (__cairo_pdf_surface_operation_supported (surface, op, source));
|
||||
|
||||
status = emit_pattern (surface, source);
|
||||
status = _cairo_pdf_surface_emit_pattern (surface, source);
|
||||
if (status)
|
||||
return status;
|
||||
|
||||
|
@ -2826,7 +2920,7 @@ _cairo_pdf_surface_show_glyphs (void *abstract_surface,
|
|||
_cairo_output_stream_printf (surface->output,
|
||||
"%f %f Td <%02x> Tj\r\n",
|
||||
(glyphs[i].x - glyphs[i-1].x)/scaled_font->scale.xx,
|
||||
(glyphs[i].y - glyphs[i-1].y)/scaled_font->scale.yy,
|
||||
(glyphs[i].y - glyphs[i-1].y)/-scaled_font->scale.yy,
|
||||
subset_glyph_index);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -40,7 +40,7 @@
|
|||
/* private functions */
|
||||
|
||||
static cairo_status_t
|
||||
_cairo_polygon_grow_by (cairo_polygon_t *polygon, int additional);
|
||||
_cairo_polygon_grow (cairo_polygon_t *polygon);
|
||||
|
||||
void
|
||||
_cairo_polygon_init (cairo_polygon_t *polygon)
|
||||
|
@ -50,42 +50,55 @@ _cairo_polygon_init (cairo_polygon_t *polygon)
|
|||
polygon->edges_size = 0;
|
||||
polygon->edges = NULL;
|
||||
|
||||
polygon->has_current_point = 0;
|
||||
polygon->has_current_point = FALSE;
|
||||
}
|
||||
|
||||
void
|
||||
_cairo_polygon_fini (cairo_polygon_t *polygon)
|
||||
{
|
||||
if (polygon->edges_size) {
|
||||
if (polygon->edges && polygon->edges != polygon->edges_embedded)
|
||||
free (polygon->edges);
|
||||
|
||||
polygon->edges = NULL;
|
||||
polygon->edges_size = 0;
|
||||
polygon->num_edges = 0;
|
||||
|
||||
polygon->has_current_point = FALSE;
|
||||
}
|
||||
|
||||
polygon->has_current_point = 0;
|
||||
}
|
||||
|
||||
/* make room for at least one more edge */
|
||||
static cairo_status_t
|
||||
_cairo_polygon_grow_by (cairo_polygon_t *polygon, int additional)
|
||||
_cairo_polygon_grow (cairo_polygon_t *polygon)
|
||||
{
|
||||
cairo_edge_t *new_edges;
|
||||
int old_size = polygon->edges_size;
|
||||
int new_size = polygon->num_edges + additional;
|
||||
int embedded_size = sizeof (polygon->edges_embedded) / sizeof (polygon->edges_embedded[0]);
|
||||
int new_size = 2 * MAX (old_size, 16);
|
||||
|
||||
if (new_size <= polygon->edges_size) {
|
||||
/* we have a local buffer at polygon->edges_embedded. try to fulfill the request
|
||||
* from there. */
|
||||
if (old_size < embedded_size) {
|
||||
polygon->edges = polygon->edges_embedded;
|
||||
polygon->edges_size = embedded_size;
|
||||
return CAIRO_STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
polygon->edges_size = new_size;
|
||||
new_edges = realloc (polygon->edges, polygon->edges_size * sizeof (cairo_edge_t));
|
||||
assert (polygon->num_edges <= polygon->edges_size);
|
||||
|
||||
if (polygon->edges == polygon->edges_embedded) {
|
||||
new_edges = malloc (new_size * sizeof (cairo_edge_t));
|
||||
if (new_edges)
|
||||
memcpy (new_edges, polygon->edges, old_size * sizeof (cairo_edge_t));
|
||||
} else {
|
||||
new_edges = realloc (polygon->edges, new_size * sizeof (cairo_edge_t));
|
||||
}
|
||||
|
||||
if (new_edges == NULL) {
|
||||
polygon->edges_size = old_size;
|
||||
return CAIRO_STATUS_NO_MEMORY;
|
||||
}
|
||||
|
||||
polygon->edges = new_edges;
|
||||
polygon->edges_size = new_size;
|
||||
|
||||
return CAIRO_STATUS_SUCCESS;
|
||||
}
|
||||
|
@ -102,8 +115,7 @@ _cairo_polygon_add_edge (cairo_polygon_t *polygon, cairo_point_t *p1, cairo_poin
|
|||
}
|
||||
|
||||
if (polygon->num_edges >= polygon->edges_size) {
|
||||
int additional = polygon->edges_size ? polygon->edges_size : 16;
|
||||
status = _cairo_polygon_grow_by (polygon, additional);
|
||||
status = _cairo_polygon_grow (polygon);
|
||||
if (status) {
|
||||
return status;
|
||||
}
|
||||
|
@ -134,7 +146,7 @@ _cairo_polygon_move_to (cairo_polygon_t *polygon, cairo_point_t *point)
|
|||
if (! polygon->has_current_point)
|
||||
polygon->first_point = *point;
|
||||
polygon->current_point = *point;
|
||||
polygon->has_current_point = 1;
|
||||
polygon->has_current_point = TRUE;
|
||||
|
||||
return CAIRO_STATUS_SUCCESS;
|
||||
}
|
||||
|
@ -165,7 +177,7 @@ _cairo_polygon_close (cairo_polygon_t *polygon)
|
|||
if (status)
|
||||
return status;
|
||||
|
||||
polygon->has_current_point = 0;
|
||||
polygon->has_current_point = FALSE;
|
||||
}
|
||||
|
||||
return CAIRO_STATUS_SUCCESS;
|
||||
|
|
|
@ -44,9 +44,12 @@ struct _cairo {
|
|||
|
||||
cairo_status_t status;
|
||||
|
||||
cairo_path_fixed_t path;
|
||||
cairo_user_data_array_t user_data;
|
||||
|
||||
cairo_gstate_t *gstate;
|
||||
cairo_gstate_t gstate_tail[1];
|
||||
|
||||
cairo_path_fixed_t path[1];
|
||||
};
|
||||
|
||||
#endif /* CAIRO_PRIVATE_H */
|
||||
|
|
|
@ -484,18 +484,18 @@ _cairo_ps_surface_emit_truetype_font_subset (cairo_ps_surface_t *surface,
|
|||
|
||||
/* FIXME: Figure out how subset->x_max etc maps to the /FontBBox */
|
||||
|
||||
for (i = 1; i < font_subset->num_glyphs; i++)
|
||||
for (i = 0; i < font_subset->num_glyphs; i++)
|
||||
_cairo_output_stream_printf (surface->final_stream,
|
||||
"Encoding %d /g%d put\n", i, i);
|
||||
|
||||
_cairo_output_stream_printf (surface->final_stream,
|
||||
"/CharStrings %d dict dup begin\n"
|
||||
"/.notdef 0 def\n",
|
||||
font_subset->num_glyphs);
|
||||
font_subset->num_glyphs + 1);
|
||||
|
||||
for (i = 1; i < font_subset->num_glyphs; i++)
|
||||
for (i = 0; i < font_subset->num_glyphs; i++)
|
||||
_cairo_output_stream_printf (surface->final_stream,
|
||||
"/g%d %d def\n", i, i);
|
||||
"/g%d %d def\n", i, i + 1);
|
||||
|
||||
_cairo_output_stream_printf (surface->final_stream,
|
||||
"end readonly def\n");
|
||||
|
@ -709,7 +709,7 @@ _cairo_ps_surface_emit_type3_font_subset (cairo_ps_surface_t *surface,
|
|||
|
||||
|
||||
static void
|
||||
_cairo_ps_surface_emit_font_subset (cairo_scaled_font_subset_t *font_subset,
|
||||
_cairo_ps_surface_emit_unscaled_font_subset (cairo_scaled_font_subset_t *font_subset,
|
||||
void *closure)
|
||||
{
|
||||
cairo_ps_surface_t *surface = closure;
|
||||
|
@ -728,6 +728,14 @@ _cairo_ps_surface_emit_font_subset (cairo_scaled_font_subset_t *font_subset,
|
|||
status = _cairo_ps_surface_emit_type1_font_fallback (surface, font_subset);
|
||||
if (status != CAIRO_INT_STATUS_UNSUPPORTED)
|
||||
return;
|
||||
}
|
||||
|
||||
static void
|
||||
_cairo_ps_surface_emit_scaled_font_subset (cairo_scaled_font_subset_t *font_subset,
|
||||
void *closure)
|
||||
{
|
||||
cairo_ps_surface_t *surface = closure;
|
||||
cairo_status_t status;
|
||||
|
||||
status = _cairo_ps_surface_emit_type3_font_subset (surface, font_subset);
|
||||
if (status != CAIRO_INT_STATUS_UNSUPPORTED)
|
||||
|
@ -742,8 +750,11 @@ _cairo_ps_surface_emit_font_subsets (cairo_ps_surface_t *surface)
|
|||
_cairo_output_stream_printf (surface->final_stream,
|
||||
"%% _cairo_ps_surface_emit_font_subsets\n");
|
||||
|
||||
status = _cairo_scaled_font_subsets_foreach (surface->font_subsets,
|
||||
_cairo_ps_surface_emit_font_subset,
|
||||
status = _cairo_scaled_font_subsets_foreach_unscaled (surface->font_subsets,
|
||||
_cairo_ps_surface_emit_unscaled_font_subset,
|
||||
surface);
|
||||
status = _cairo_scaled_font_subsets_foreach_scaled (surface->font_subsets,
|
||||
_cairo_ps_surface_emit_scaled_font_subset,
|
||||
surface);
|
||||
_cairo_scaled_font_subsets_destroy (surface->font_subsets);
|
||||
surface->font_subsets = NULL;
|
||||
|
@ -798,7 +809,8 @@ _cairo_ps_surface_create_for_stream_internal (cairo_output_stream_t *stream,
|
|||
if (status)
|
||||
goto CLEANUP_TMPFILE;
|
||||
|
||||
surface->font_subsets = _cairo_scaled_font_subsets_create (PS_SURFACE_MAX_GLYPHS_PER_FONT);
|
||||
surface->font_subsets = _cairo_scaled_font_subsets_create (PS_SURFACE_MAX_GLYPHS_PER_FONT,
|
||||
PS_SURFACE_MAX_GLYPHS_PER_FONT);
|
||||
if (! surface->font_subsets)
|
||||
goto CLEANUP_OUTPUT_STREAM;
|
||||
|
||||
|
@ -868,7 +880,9 @@ cairo_ps_surface_create (const char *filename,
|
|||
status = _cairo_output_stream_get_status (stream);
|
||||
if (status) {
|
||||
_cairo_error (status);
|
||||
return (cairo_surface_t*) &_cairo_surface_nil;
|
||||
return (status == CAIRO_STATUS_WRITE_ERROR) ?
|
||||
(cairo_surface_t*) &_cairo_surface_nil_write_error :
|
||||
(cairo_surface_t*) &_cairo_surface_nil;
|
||||
}
|
||||
|
||||
return _cairo_ps_surface_create_for_stream_internal (stream,
|
||||
|
@ -1323,9 +1337,37 @@ color_is_gray (cairo_color_t *color)
|
|||
static cairo_bool_t
|
||||
surface_pattern_supported (const cairo_surface_pattern_t *pattern)
|
||||
{
|
||||
if (pattern->surface->backend->acquire_source_image != NULL)
|
||||
return TRUE;
|
||||
cairo_extend_t extend;
|
||||
|
||||
if (pattern->surface->backend->acquire_source_image == NULL)
|
||||
return FALSE;
|
||||
|
||||
/* Does an ALPHA-only source surface even make sense? Maybe, but I
|
||||
* don't think it's worth the extra code to support it. */
|
||||
|
||||
/* XXX: Need to write this function here...
|
||||
content = cairo_surface_get_content (pattern->surface);
|
||||
if (content == CAIRO_CONTENT_ALPHA)
|
||||
return FALSE;
|
||||
*/
|
||||
|
||||
/* Cast away the const, trusting get_extend not to muck with it.
|
||||
* And I really wish I had a way to cast away just the const, and
|
||||
* not potentially coerce this pointer to an incorrect type at the
|
||||
* same time. :-(
|
||||
*/
|
||||
extend = cairo_pattern_get_extend ((cairo_pattern_t*)&pattern->base);
|
||||
switch (extend) {
|
||||
case CAIRO_EXTEND_NONE:
|
||||
case CAIRO_EXTEND_REPEAT:
|
||||
case CAIRO_EXTEND_REFLECT:
|
||||
/* There's no point returning FALSE for EXTEND_PAD, as the image
|
||||
* surface does not currently implement it either */
|
||||
case CAIRO_EXTEND_PAD:
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
ASSERT_NOT_REACHED;
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
|
@ -1362,7 +1404,7 @@ _cairo_ps_test_force_fallbacks (void)
|
|||
}
|
||||
|
||||
static cairo_int_status_t
|
||||
operation_supported (cairo_ps_surface_t *surface,
|
||||
_cairo_ps_surface_operation_supported (cairo_ps_surface_t *surface,
|
||||
cairo_operator_t op,
|
||||
const cairo_pattern_t *pattern)
|
||||
{
|
||||
|
@ -1382,11 +1424,11 @@ operation_supported (cairo_ps_surface_t *surface,
|
|||
}
|
||||
|
||||
static cairo_int_status_t
|
||||
_analyze_operation (cairo_ps_surface_t *surface,
|
||||
_cairo_ps_surface_analyze_operation (cairo_ps_surface_t *surface,
|
||||
cairo_operator_t op,
|
||||
const cairo_pattern_t *pattern)
|
||||
{
|
||||
if (operation_supported (surface, op, pattern))
|
||||
if (_cairo_ps_surface_operation_supported (surface, op, pattern))
|
||||
return CAIRO_STATUS_SUCCESS;
|
||||
else
|
||||
return CAIRO_INT_STATUS_UNSUPPORTED;
|
||||
|
@ -1516,9 +1558,8 @@ _string_array_stream_create (cairo_output_stream_t *output)
|
|||
* surface we can render natively in PS. */
|
||||
|
||||
static cairo_status_t
|
||||
emit_image (cairo_ps_surface_t *surface,
|
||||
_cairo_ps_surface_emit_image (cairo_ps_surface_t *surface,
|
||||
cairo_image_surface_t *image,
|
||||
cairo_matrix_t *matrix,
|
||||
const char *name)
|
||||
{
|
||||
cairo_status_t status;
|
||||
|
@ -1627,17 +1668,14 @@ emit_image (cairo_ps_surface_t *surface,
|
|||
" /%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"
|
||||
" /ImageMatrix [ 1 0 0 1 0 0 ]\n"
|
||||
" >>\n"
|
||||
" image\n"
|
||||
"} def\n",
|
||||
name,
|
||||
opaque_image->width,
|
||||
opaque_image->height,
|
||||
name, name, name, name, name, name, name,
|
||||
matrix->xx, matrix->yx,
|
||||
matrix->xy, matrix->yy,
|
||||
0.0, 0.0);
|
||||
name, name, name, name, name, name, name);
|
||||
|
||||
status = CAIRO_STATUS_SUCCESS;
|
||||
|
||||
|
@ -1652,7 +1690,7 @@ emit_image (cairo_ps_surface_t *surface,
|
|||
}
|
||||
|
||||
static void
|
||||
emit_solid_pattern (cairo_ps_surface_t *surface,
|
||||
_cairo_ps_surface_emit_solid_pattern (cairo_ps_surface_t *surface,
|
||||
cairo_solid_pattern_t *pattern)
|
||||
{
|
||||
if (color_is_gray (&pattern->color))
|
||||
|
@ -1668,12 +1706,13 @@ emit_solid_pattern (cairo_ps_surface_t *surface,
|
|||
}
|
||||
|
||||
static void
|
||||
emit_surface_pattern (cairo_ps_surface_t *surface,
|
||||
_cairo_ps_surface_emit_surface_pattern (cairo_ps_surface_t *surface,
|
||||
cairo_surface_pattern_t *pattern)
|
||||
{
|
||||
double bbox_width, bbox_height;
|
||||
int xstep, ystep;
|
||||
double xstep, ystep;
|
||||
cairo_matrix_t inverse = pattern->base.matrix;
|
||||
|
||||
cairo_matrix_invert (&inverse);
|
||||
|
||||
if (_cairo_surface_is_meta (pattern->surface)) {
|
||||
|
@ -1694,32 +1733,49 @@ emit_surface_pattern (cairo_ps_surface_t *surface,
|
|||
&image_extra);
|
||||
assert (status == CAIRO_STATUS_SUCCESS);
|
||||
|
||||
emit_image (surface, image, &pattern->base.matrix, "MyPattern");
|
||||
_cairo_ps_surface_emit_image (surface, image, "MyPattern");
|
||||
|
||||
bbox_width = image->width;
|
||||
bbox_height = image->height;
|
||||
cairo_matrix_transform_distance (&inverse,
|
||||
&bbox_width, &bbox_height);
|
||||
|
||||
/* In PostScript, (as far as I can tell), all patterns are
|
||||
* repeating. So we support cairo's EXTEND_NONE semantics by
|
||||
* setting the repeat step size to the larger of the image size
|
||||
* and the extents of the destination surface. That way we
|
||||
* guarantee the pattern will not repeat.
|
||||
*/
|
||||
switch (pattern->base.extend) {
|
||||
/* We implement EXTEND_PAD like EXTEND_NONE for now */
|
||||
case CAIRO_EXTEND_PAD:
|
||||
case CAIRO_EXTEND_NONE:
|
||||
xstep = MAX (image->width, surface->width);
|
||||
ystep = MAX (image->height, surface->height);
|
||||
{
|
||||
/* In PS/PDF, (as far as I can tell), all patterns are
|
||||
* repeating. So we support cairo's EXTEND_NONE semantics
|
||||
* by setting the repeat step size to a size large enough
|
||||
* to guarantee that no more than a single occurrence will
|
||||
* be visible.
|
||||
*
|
||||
* First, map the surface extents into pattern space (since
|
||||
* xstep and ystep are in pattern space). Then use an upper
|
||||
* bound on the length of the diagonal of the pattern image
|
||||
* and the surface as repeat size. This guarantees to never
|
||||
* repeat visibly.
|
||||
*/
|
||||
double x1 = 0.0, y1 = 0.0;
|
||||
double x2 = surface->width, y2 = surface->height;
|
||||
_cairo_matrix_transform_bounding_box (&pattern->base.matrix,
|
||||
&x1, &y1, &x2, &y2,
|
||||
NULL);
|
||||
|
||||
/* Rather than computing precise bounds of the union, just
|
||||
* add the surface extents unconditionally. We only
|
||||
* required an answer that's large enough, we don't really
|
||||
* care if it's not as tight as possible.*/
|
||||
xstep = ystep = ceil ((x2 - x1) + (y2 - y1) +
|
||||
image->width + image->height);
|
||||
break;
|
||||
}
|
||||
case CAIRO_EXTEND_REPEAT:
|
||||
case CAIRO_EXTEND_REFLECT:
|
||||
xstep = image->width;
|
||||
ystep = image->height;
|
||||
break;
|
||||
/* All the rest should have been analyzed away, so these cases
|
||||
* should be unreachable. */
|
||||
case CAIRO_EXTEND_REFLECT:
|
||||
case CAIRO_EXTEND_PAD:
|
||||
/* All the rest (if any) should have been analyzed away, so these
|
||||
* cases should be unreachable. */
|
||||
default:
|
||||
ASSERT_NOT_REACHED;
|
||||
xstep = 0;
|
||||
|
@ -1734,37 +1790,39 @@ emit_surface_pattern (cairo_ps_surface_t *surface,
|
|||
" /PaintType 1\n"
|
||||
" /TilingType 1\n");
|
||||
_cairo_output_stream_printf (surface->stream,
|
||||
" /BBox [0 0 %d %d]\n",
|
||||
(int) bbox_width, (int) bbox_height);
|
||||
" /BBox [0 0 %f %f]\n",
|
||||
bbox_width, bbox_height);
|
||||
_cairo_output_stream_printf (surface->stream,
|
||||
" /XStep %d /YStep %d\n",
|
||||
" /XStep %f /YStep %f\n",
|
||||
xstep, ystep);
|
||||
_cairo_output_stream_printf (surface->stream,
|
||||
" /PaintProc { MyPattern } bind\n"
|
||||
">>\n");
|
||||
_cairo_output_stream_printf (surface->stream,
|
||||
"[ 1 0 0 1 %f %f ]\n",
|
||||
"[ %f %f %f %f %f %f ]\n",
|
||||
inverse.xx, inverse.yx,
|
||||
inverse.xy, inverse.yy,
|
||||
inverse.x0, inverse.y0);
|
||||
_cairo_output_stream_printf (surface->stream,
|
||||
"makepattern setpattern\n");
|
||||
}
|
||||
|
||||
static void
|
||||
emit_linear_pattern (cairo_ps_surface_t *surface,
|
||||
_cairo_ps_surface_emit_linear_pattern (cairo_ps_surface_t *surface,
|
||||
cairo_linear_pattern_t *pattern)
|
||||
{
|
||||
/* XXX: NYI */
|
||||
}
|
||||
|
||||
static void
|
||||
emit_radial_pattern (cairo_ps_surface_t *surface,
|
||||
_cairo_ps_surface_emit_radial_pattern (cairo_ps_surface_t *surface,
|
||||
cairo_radial_pattern_t *pattern)
|
||||
{
|
||||
/* XXX: NYI */
|
||||
}
|
||||
|
||||
static void
|
||||
emit_pattern (cairo_ps_surface_t *surface, cairo_pattern_t *pattern)
|
||||
_cairo_ps_surface_emit_pattern (cairo_ps_surface_t *surface, cairo_pattern_t *pattern)
|
||||
{
|
||||
/* FIXME: We should keep track of what pattern is currently set in
|
||||
* the postscript file and only emit code if we're setting a
|
||||
|
@ -1772,19 +1830,19 @@ emit_pattern (cairo_ps_surface_t *surface, cairo_pattern_t *pattern)
|
|||
|
||||
switch (pattern->type) {
|
||||
case CAIRO_PATTERN_TYPE_SOLID:
|
||||
emit_solid_pattern (surface, (cairo_solid_pattern_t *) pattern);
|
||||
_cairo_ps_surface_emit_solid_pattern (surface, (cairo_solid_pattern_t *) pattern);
|
||||
break;
|
||||
|
||||
case CAIRO_PATTERN_TYPE_SURFACE:
|
||||
emit_surface_pattern (surface, (cairo_surface_pattern_t *) pattern);
|
||||
_cairo_ps_surface_emit_surface_pattern (surface, (cairo_surface_pattern_t *) pattern);
|
||||
break;
|
||||
|
||||
case CAIRO_PATTERN_TYPE_LINEAR:
|
||||
emit_linear_pattern (surface, (cairo_linear_pattern_t *) pattern);
|
||||
_cairo_ps_surface_emit_linear_pattern (surface, (cairo_linear_pattern_t *) pattern);
|
||||
break;
|
||||
|
||||
case CAIRO_PATTERN_TYPE_RADIAL:
|
||||
emit_radial_pattern (surface, (cairo_radial_pattern_t *) pattern);
|
||||
_cairo_ps_surface_emit_radial_pattern (surface, (cairo_radial_pattern_t *) pattern);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
@ -1874,7 +1932,7 @@ _cairo_ps_surface_paint (void *abstract_surface,
|
|||
cairo_rectangle_int16_t extents, pattern_extents;
|
||||
|
||||
if (surface->paginated_mode == CAIRO_PAGINATED_MODE_ANALYZE)
|
||||
return _analyze_operation (surface, op, source);
|
||||
return _cairo_ps_surface_analyze_operation (surface, op, source);
|
||||
|
||||
/* XXX: It would be nice to be able to assert this condition
|
||||
* here. But, we actually allow one 'cheat' that is used when
|
||||
|
@ -1883,7 +1941,7 @@ _cairo_ps_surface_paint (void *abstract_surface,
|
|||
* possible only because there is nothing between the fallback
|
||||
* images and the paper, nor is anything painted above. */
|
||||
/*
|
||||
assert (_operation_supported (op, source));
|
||||
assert (__cairo_ps_surface_operation_supported (op, source));
|
||||
*/
|
||||
|
||||
_cairo_output_stream_printf (stream,
|
||||
|
@ -1893,7 +1951,7 @@ _cairo_ps_surface_paint (void *abstract_surface,
|
|||
_cairo_pattern_get_extents (source, &pattern_extents);
|
||||
_cairo_rectangle_intersect (&extents, &pattern_extents);
|
||||
|
||||
emit_pattern (surface, source);
|
||||
_cairo_ps_surface_emit_pattern (surface, source);
|
||||
|
||||
_cairo_output_stream_printf (stream, "%d %d M\n",
|
||||
extents.x, extents.y);
|
||||
|
@ -1961,9 +2019,9 @@ _cairo_ps_surface_stroke (void *abstract_surface,
|
|||
double dash_offset = style->dash_offset;
|
||||
|
||||
if (surface->paginated_mode == CAIRO_PAGINATED_MODE_ANALYZE)
|
||||
return _analyze_operation (surface, op, source);
|
||||
return _cairo_ps_surface_analyze_operation (surface, op, source);
|
||||
|
||||
assert (operation_supported (surface, op, source));
|
||||
assert (_cairo_ps_surface_operation_supported (surface, op, source));
|
||||
|
||||
|
||||
_cairo_output_stream_printf (stream,
|
||||
|
@ -2032,7 +2090,7 @@ _cairo_ps_surface_stroke (void *abstract_surface,
|
|||
}
|
||||
}
|
||||
|
||||
emit_pattern (surface, source);
|
||||
_cairo_ps_surface_emit_pattern (surface, source);
|
||||
|
||||
_cairo_output_stream_printf (stream,
|
||||
"gsave\n");
|
||||
|
@ -2092,14 +2150,14 @@ _cairo_ps_surface_fill (void *abstract_surface,
|
|||
const char *ps_operator;
|
||||
|
||||
if (surface->paginated_mode == CAIRO_PAGINATED_MODE_ANALYZE)
|
||||
return _analyze_operation (surface, op, source);
|
||||
return _cairo_ps_surface_analyze_operation (surface, op, source);
|
||||
|
||||
assert (operation_supported (surface, op, source));
|
||||
assert (_cairo_ps_surface_operation_supported (surface, op, source));
|
||||
|
||||
_cairo_output_stream_printf (stream,
|
||||
"%% _cairo_ps_surface_fill\n");
|
||||
|
||||
emit_pattern (surface, source);
|
||||
_cairo_ps_surface_emit_pattern (surface, source);
|
||||
|
||||
/* We're filling not stroking, so we pass CAIRO_LINE_CAP_ROUND. */
|
||||
status = _cairo_ps_surface_emit_path (surface, stream, path,
|
||||
|
@ -2150,9 +2208,9 @@ _cairo_ps_surface_show_glyphs (void *abstract_surface,
|
|||
cairo_output_stream_t *word_wrap;
|
||||
|
||||
if (surface->paginated_mode == CAIRO_PAGINATED_MODE_ANALYZE)
|
||||
return _analyze_operation (surface, op, source);
|
||||
return _cairo_ps_surface_analyze_operation (surface, op, source);
|
||||
|
||||
assert (operation_supported (surface, op, source));
|
||||
assert (_cairo_ps_surface_operation_supported (surface, op, source));
|
||||
|
||||
_cairo_output_stream_printf (stream,
|
||||
"%% _cairo_ps_surface_show_glyphs\n");
|
||||
|
@ -2162,7 +2220,7 @@ _cairo_ps_surface_show_glyphs (void *abstract_surface,
|
|||
|
||||
num_glyphs_unsigned = num_glyphs;
|
||||
|
||||
emit_pattern (surface, source);
|
||||
_cairo_ps_surface_emit_pattern (surface, source);
|
||||
glyph_ids = malloc (num_glyphs_unsigned*sizeof (cairo_ps_glyph_id_t));
|
||||
if (glyph_ids == NULL)
|
||||
return CAIRO_STATUS_NO_MEMORY;
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
/* cairo - a vector graphics library with display and print output
|
||||
*
|
||||
* Copyright © 2004 Calum Robinson
|
||||
* Copyright (C) 2006,2007 Mozilla Corporation
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it either under the terms of the GNU Lesser General Public
|
||||
|
@ -31,36 +32,43 @@
|
|||
*
|
||||
* Contributor(s):
|
||||
* Calum Robinson <calumr@mac.com>
|
||||
* Vladimir Vukicevic <vladimir@mozilla.com>
|
||||
*/
|
||||
|
||||
#ifndef CAIRO_QUARTZ_PRIVATE_H
|
||||
#define CAIRO_QUARTZ_PRIVATE_H
|
||||
|
||||
#include <cairoint.h>
|
||||
|
||||
#ifdef CAIRO_HAS_QUARTZ_SURFACE
|
||||
#include <cairo-quartz.h>
|
||||
|
||||
typedef struct cairo_quartz_surface {
|
||||
cairo_surface_t base;
|
||||
|
||||
CGContextRef context;
|
||||
void *imageData;
|
||||
|
||||
cairo_bool_t y_grows_down;
|
||||
CGContextRef cgContext;
|
||||
CGAffineTransform cgContextBaseCTM;
|
||||
|
||||
cairo_rectangle_int16_t extents;
|
||||
|
||||
pixman_region16_t *clip_region;
|
||||
/* These are stored while drawing operations are in place, set up
|
||||
* by quartz_setup_source() and quartz_finish_source()
|
||||
*/
|
||||
CGAffineTransform imageTransform;
|
||||
CGImageRef sourceImage;
|
||||
CGShadingRef sourceShading;
|
||||
CGPatternRef sourcePattern;
|
||||
} cairo_quartz_surface_t;
|
||||
#endif /* CAIRO_HAS_QUARTZ_SURFACE */
|
||||
|
||||
cairo_bool_t
|
||||
_cairo_surface_is_quartz (cairo_surface_t *surface);
|
||||
|
||||
cairo_bool_t
|
||||
_cairo_scaled_font_is_atsui (cairo_scaled_font_t *sfont);
|
||||
|
||||
#if CAIRO_HAS_ATSUI_FONT
|
||||
ATSUStyle
|
||||
_cairo_atsui_scaled_font_get_atsu_style (cairo_scaled_font_t *sfont);
|
||||
|
||||
ATSUFontID
|
||||
_cairo_atsui_scaled_font_get_atsu_font_id (cairo_scaled_font_t *sfont);
|
||||
#endif /* CAIRO_HAS_ATSUI_FONT */
|
||||
|
||||
#endif /* CAIRO_QUARTZ_PRIVATE_H */
|
||||
|
|
Разница между файлами не показана из-за своего большого размера
Загрузить разницу
|
@ -1,6 +1,6 @@
|
|||
/* cairo - a vector graphics library with display and print output
|
||||
*
|
||||
* Copyright © 2002 University of Southern California
|
||||
* Copyright © 2006, 2007 Mozilla Corporation
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it either under the terms of the GNU Lesser General Public
|
||||
|
@ -27,11 +27,10 @@
|
|||
*
|
||||
* The Original Code is the cairo graphics library.
|
||||
*
|
||||
* The Initial Developer of the Original Code is University of Southern
|
||||
* California.
|
||||
* The Initial Developer of the Original Code is Mozilla Corporation.
|
||||
*
|
||||
* Contributor(s):
|
||||
* Carl D. Worth <cworth@cworth.org>
|
||||
* Vladimir Vukicevic <vladimir@mozilla.com>
|
||||
*/
|
||||
|
||||
#ifndef CAIRO_QUARTZ_H
|
||||
|
@ -46,10 +45,17 @@
|
|||
CAIRO_BEGIN_DECLS
|
||||
|
||||
cairo_public cairo_surface_t *
|
||||
cairo_quartz_surface_create (CGContextRef context,
|
||||
int width,
|
||||
int height,
|
||||
cairo_bool_t y_grows_down);
|
||||
cairo_quartz_surface_create (cairo_format_t format,
|
||||
unsigned int width,
|
||||
unsigned int height);
|
||||
|
||||
cairo_public cairo_surface_t *
|
||||
cairo_quartz_surface_create_for_cg_context (CGContextRef cgContext,
|
||||
unsigned int width,
|
||||
unsigned int height);
|
||||
|
||||
cairo_public CGContextRef
|
||||
cairo_quartz_surface_get_cg_context (cairo_surface_t *surface);
|
||||
|
||||
CAIRO_END_DECLS
|
||||
|
||||
|
|
|
@ -35,6 +35,7 @@
|
|||
#define cairo_fill_preserve _moz_cairo_fill_preserve
|
||||
#define cairo_font_extents _moz_cairo_font_extents
|
||||
#define cairo_font_face_destroy _moz_cairo_font_face_destroy
|
||||
#define cairo_font_face_get_reference_count _moz_cairo_font_face_get_reference_count
|
||||
#define cairo_font_face_get_type _moz_cairo_font_face_get_type
|
||||
#define cairo_font_face_get_user_data _moz_cairo_font_face_get_user_data
|
||||
#define cairo_font_face_reference _moz_cairo_font_face_reference
|
||||
|
@ -75,9 +76,12 @@
|
|||
#define cairo_get_matrix _moz_cairo_get_matrix
|
||||
#define cairo_get_miter_limit _moz_cairo_get_miter_limit
|
||||
#define cairo_get_operator _moz_cairo_get_operator
|
||||
#define cairo_get_reference_count _moz_cairo_get_reference_count
|
||||
#define cairo_get_scaled_font _moz_cairo_get_scaled_font
|
||||
#define cairo_get_source _moz_cairo_get_source
|
||||
#define cairo_get_target _moz_cairo_get_target
|
||||
#define cairo_get_tolerance _moz_cairo_get_tolerance
|
||||
#define cairo_get_user_data _moz_cairo_get_user_data
|
||||
#define cairo_glitz_surface_create _moz_cairo_glitz_surface_create
|
||||
#define cairo_glyph_extents _moz_cairo_glyph_extents
|
||||
#define cairo_glyph_path _moz_cairo_glyph_path
|
||||
|
@ -105,17 +109,12 @@
|
|||
#define cairo_matrix_multiply _moz_cairo_matrix_multiply
|
||||
#define cairo_matrix_rotate _moz_cairo_matrix_rotate
|
||||
#define cairo_matrix_scale _moz_cairo_matrix_scale
|
||||
#define cairo_matrix_transform_bounding_box _moz_cairo_matrix_transform_bounding_box
|
||||
#define cairo_matrix_transform_distance _moz_cairo_matrix_transform_distance
|
||||
#define cairo_matrix_transform_point _moz_cairo_matrix_transform_point
|
||||
#define cairo_matrix_translate _moz_cairo_matrix_translate
|
||||
#define cairo_move_to _moz_cairo_move_to
|
||||
#define cairo_new_path _moz_cairo_new_path
|
||||
#define cairo_new_sub_path _moz_cairo_new_sub_path
|
||||
#define cairo_nquartz_surface_create _moz_cairo_nquartz_surface_create
|
||||
#define cairo_nquartz_surface_create_for_agl_context _moz_cairo_nquartz_surface_create_for_agl_context
|
||||
#define cairo_nquartz_surface_create_for_cg_context _moz_cairo_nquartz_surface_create_for_cg_context
|
||||
#define cairo_nquartz_surface_get_cg_context _moz_cairo_nquartz_surface_get_cg_context
|
||||
#define cairo_os2_fini _moz_cairo_os2_fini
|
||||
#define cairo_os2_init _moz_cairo_os2_init
|
||||
#define cairo_os2_surface_create _moz_cairo_os2_surface_create
|
||||
|
@ -142,13 +141,16 @@
|
|||
#define cairo_pattern_get_linear_points _moz_cairo_pattern_get_linear_points
|
||||
#define cairo_pattern_get_matrix _moz_cairo_pattern_get_matrix
|
||||
#define cairo_pattern_get_radial_circles _moz_cairo_pattern_get_radial_circles
|
||||
#define cairo_pattern_get_reference_count _moz_cairo_pattern_get_reference_count
|
||||
#define cairo_pattern_get_rgba _moz_cairo_pattern_get_rgba
|
||||
#define cairo_pattern_get_surface _moz_cairo_pattern_get_surface
|
||||
#define cairo_pattern_get_type _moz_cairo_pattern_get_type
|
||||
#define cairo_pattern_get_user_data _moz_cairo_pattern_get_user_data
|
||||
#define cairo_pattern_reference _moz_cairo_pattern_reference
|
||||
#define cairo_pattern_set_extend _moz_cairo_pattern_set_extend
|
||||
#define cairo_pattern_set_filter _moz_cairo_pattern_set_filter
|
||||
#define cairo_pattern_set_matrix _moz_cairo_pattern_set_matrix
|
||||
#define cairo_pattern_set_user_data _moz_cairo_pattern_set_user_data
|
||||
#define cairo_pattern_status _moz_cairo_pattern_status
|
||||
#define cairo_pdf_surface_create _moz_cairo_pdf_surface_create
|
||||
#define cairo_pdf_surface_create_for_stream _moz_cairo_pdf_surface_create_for_stream
|
||||
|
@ -164,6 +166,8 @@
|
|||
#define cairo_push_group _moz_cairo_push_group
|
||||
#define cairo_push_group_with_content _moz_cairo_push_group_with_content
|
||||
#define cairo_quartz_surface_create _moz_cairo_quartz_surface_create
|
||||
#define cairo_quartz_surface_create_for_cg_context _moz_cairo_quartz_surface_create_for_cg_context
|
||||
#define cairo_quartz_surface_get_cg_context _moz_cairo_quartz_surface_get_cg_context
|
||||
#define cairo_rectangle _moz_cairo_rectangle
|
||||
#define cairo_rectangle_list_destroy _moz_cairo_rectangle_list_destroy
|
||||
#define cairo_reference _moz_cairo_reference
|
||||
|
@ -182,9 +186,12 @@
|
|||
#define cairo_scaled_font_get_font_face _moz_cairo_scaled_font_get_font_face
|
||||
#define cairo_scaled_font_get_font_matrix _moz_cairo_scaled_font_get_font_matrix
|
||||
#define cairo_scaled_font_get_font_options _moz_cairo_scaled_font_get_font_options
|
||||
#define cairo_scaled_font_get_reference_count _moz_cairo_scaled_font_get_reference_count
|
||||
#define cairo_scaled_font_get_type _moz_cairo_scaled_font_get_type
|
||||
#define cairo_scaled_font_get_user_data _moz_cairo_scaled_font_get_user_data
|
||||
#define cairo_scaled_font_glyph_extents _moz_cairo_scaled_font_glyph_extents
|
||||
#define cairo_scaled_font_reference _moz_cairo_scaled_font_reference
|
||||
#define cairo_scaled_font_set_user_data _moz_cairo_scaled_font_set_user_data
|
||||
#define cairo_scaled_font_status _moz_cairo_scaled_font_status
|
||||
#define cairo_scaled_font_text_extents _moz_cairo_scaled_font_text_extents
|
||||
#define cairo_select_font_face _moz_cairo_select_font_face
|
||||
|
@ -207,6 +214,7 @@
|
|||
#define cairo_set_source_rgba _moz_cairo_set_source_rgba
|
||||
#define cairo_set_source_surface _moz_cairo_set_source_surface
|
||||
#define cairo_set_tolerance _moz_cairo_set_tolerance
|
||||
#define cairo_set_user_data _moz_cairo_set_user_data
|
||||
#define cairo_show_glyphs _moz_cairo_show_glyphs
|
||||
#define cairo_show_page _moz_cairo_show_page
|
||||
#define cairo_show_text _moz_cairo_show_text
|
||||
|
@ -226,7 +234,6 @@
|
|||
#define cairo_surface_get_reference_count _moz_cairo_surface_get_reference_count
|
||||
#define cairo_surface_get_type _moz_cairo_surface_get_type
|
||||
#define cairo_surface_get_user_data _moz_cairo_surface_get_user_data
|
||||
#define cairo_surface_is_nquartz _moz_cairo_surface_is_nquartz
|
||||
#define cairo_surface_mark_dirty _moz_cairo_surface_mark_dirty
|
||||
#define cairo_surface_mark_dirty_rectangle _moz_cairo_surface_mark_dirty_rectangle
|
||||
#define cairo_surface_reference _moz_cairo_surface_reference
|
||||
|
|
|
@ -41,23 +41,17 @@
|
|||
|
||||
typedef struct _cairo_scaled_font_subsets cairo_scaled_font_subsets_t;
|
||||
|
||||
typedef struct _cairo_scaled_font_subset {
|
||||
cairo_scaled_font_t *scaled_font;
|
||||
unsigned int font_id;
|
||||
unsigned int subset_id;
|
||||
|
||||
/* Index of glyphs array is subset_glyph_index.
|
||||
* Value of glyphs array is scaled_font_glyph_index.
|
||||
*/
|
||||
unsigned long *glyphs;
|
||||
unsigned int num_glyphs;
|
||||
} cairo_scaled_font_subset_t;
|
||||
|
||||
/**
|
||||
* _cairo_scaled_font_subsets_create:
|
||||
* @max_glyphs_per_subset: the maximum number of glyphs that should
|
||||
* appear in any subset. A value of 0 indicates that there is no limit
|
||||
* to the number of glyphs per subset.
|
||||
*
|
||||
* @max_glyphs_per_unscaled_subset: the maximum number of glyphs that
|
||||
* should appear in any unscaled subset. A value of 0 indicates that
|
||||
* no unscaled subset will be created. All glyphs will mapped to
|
||||
* scaled subsets.
|
||||
*
|
||||
* @max_glyphs_per_scaled_subset: the maximum number of glyphs that
|
||||
* should appear in any scaled subset. A value of 0 indicates that
|
||||
* no scaled subset will be created.
|
||||
*
|
||||
* Create a new #cairo_scaled_font_subsets_t object which can be used
|
||||
* to create subsets of any number of cairo_scaled_font_t
|
||||
|
@ -66,12 +60,16 @@ typedef struct _cairo_scaled_font_subset {
|
|||
* subsets with glyph indices packed into the range
|
||||
* [0 .. max_glyphs_per_subset).
|
||||
*
|
||||
* @max_glyphs_per_unscaled_subset and @max_glyphs_per_scaled_subset
|
||||
* cannot both be 0.
|
||||
*
|
||||
* Return value: a pointer to the newly creates font subsets. The
|
||||
* caller owns this object and should call
|
||||
* _cairo_scaled_font_subsets_destroy() when done with it.
|
||||
**/
|
||||
cairo_private cairo_scaled_font_subsets_t *
|
||||
_cairo_scaled_font_subsets_create (int max_glyphs_per_subset);
|
||||
_cairo_scaled_font_subsets_create (int max_glyphs_unscaled_per_subset,
|
||||
int max_glyphs_scaled_per_subset);
|
||||
|
||||
/**
|
||||
* _cairo_scaled_font_subsets_destroy:
|
||||
|
@ -150,7 +148,7 @@ typedef void
|
|||
* @font_subset_callback: a function to be called for each font subset
|
||||
* @closure: closure data for the callback function
|
||||
*
|
||||
* Iterate over each unique font subset as created by calls to
|
||||
* Iterate over each unique scaled font subset as created by calls to
|
||||
* _cairo_scaled_font_subsets_map_glyph(). A subset is determined by
|
||||
* unique pairs of (font_id, subset_id) as returned by
|
||||
* _cairo_scaled_font_subsets_map_glyph().
|
||||
|
@ -175,7 +173,42 @@ typedef void
|
|||
* CAIRO_STATUS_NO_MEMORY.
|
||||
**/
|
||||
cairo_private cairo_status_t
|
||||
_cairo_scaled_font_subsets_foreach (cairo_scaled_font_subsets_t *font_subsets,
|
||||
_cairo_scaled_font_subsets_foreach_scaled (cairo_scaled_font_subsets_t *font_subsets,
|
||||
cairo_scaled_font_subset_callback_func_t font_subset_callback,
|
||||
void *closure);
|
||||
|
||||
/**
|
||||
* _cairo_scaled_font_subsets_foreach_unscaled:
|
||||
* @font_subsets: a #cairo_scaled_font_subsets_t
|
||||
* @font_subset_callback: a function to be called for each font subset
|
||||
* @closure: closure data for the callback function
|
||||
*
|
||||
* Iterate over each unique unscaled font subset as created by calls to
|
||||
* _cairo_scaled_font_subsets_map_glyph(). A subset is determined by
|
||||
* unique pairs of (font_id, subset_id) as returned by
|
||||
* _cairo_scaled_font_subsets_map_glyph().
|
||||
*
|
||||
* For each subset, @font_subset_callback will be called and will be
|
||||
* provided with both a #cairo_scaled_font_subset_t object containing
|
||||
* all the glyphs in the subset as well as the value of @closure.
|
||||
*
|
||||
* The #cairo_scaled_font_subset_t object contains the scaled_font,
|
||||
* the font_id, and the subset_id corresponding to all glyphs
|
||||
* belonging to the subset. In addition, it contains an array providing
|
||||
* a mapping between subset glyph indices and the original scaled font
|
||||
* glyph indices.
|
||||
*
|
||||
* The index of the array corresponds to subset_glyph_index values
|
||||
* returned by _cairo_scaled_font_subsets_map_glyph() while the
|
||||
* values of the array correspond to the scaled_font_glyph_index
|
||||
* values passed as input to the same function.
|
||||
*
|
||||
* Return value: CAIRO_STATUS_SUCCESS if successful, or a non-zero
|
||||
* value indicating an error. Possible errors include
|
||||
* CAIRO_STATUS_NO_MEMORY.
|
||||
**/
|
||||
cairo_private cairo_status_t
|
||||
_cairo_scaled_font_subsets_foreach_unscaled (cairo_scaled_font_subsets_t *font_subsets,
|
||||
cairo_scaled_font_subset_callback_func_t font_subset_callback,
|
||||
void *closure);
|
||||
|
||||
|
@ -222,9 +255,9 @@ _cairo_cff_subset_fini (cairo_cff_subset_t *cff_subset);
|
|||
|
||||
typedef struct _cairo_truetype_subset {
|
||||
char *base_font;
|
||||
int *widths;
|
||||
long x_min, y_min, x_max, y_max;
|
||||
long ascent, descent;
|
||||
double *widths;
|
||||
double x_min, y_min, x_max, y_max;
|
||||
double ascent, descent;
|
||||
char *data;
|
||||
unsigned long data_length;
|
||||
unsigned long *string_offsets;
|
||||
|
@ -361,4 +394,21 @@ _cairo_type1_fallback_init_hex (cairo_type1_subset_t *type_subset,
|
|||
cairo_private void
|
||||
_cairo_type1_fallback_fini (cairo_type1_subset_t *subset);
|
||||
|
||||
/**
|
||||
* _cairo_truetype_create_glyph_to_unicode_map:
|
||||
* @font_subset: the #cairo_scaled_font_subset_t to initialize from
|
||||
*
|
||||
* If possible (depending on the format of the underlying
|
||||
* cairo_scaled_font_t and the font backend in use) assign
|
||||
* the unicode character of each glyph in font_subset to
|
||||
* fontsubset->to_unicode.
|
||||
*
|
||||
* Return value: CAIRO_STATUS_SUCCESS if successful,
|
||||
* CAIRO_INT_STATUS_UNSUPPORTED if the unicode encoding of
|
||||
* the glyphs is not available. Possible errors include
|
||||
* CAIRO_STATUS_NO_MEMORY.
|
||||
**/
|
||||
cairo_private cairo_int_status_t
|
||||
_cairo_truetype_create_glyph_to_unicode_map (cairo_scaled_font_subset_t *font_subset);
|
||||
|
||||
#endif /* CAIRO_SCALED_FONT_SUBSETS_PRIVATE_H */
|
||||
|
|
|
@ -43,16 +43,21 @@
|
|||
#include "cairo-scaled-font-subsets-private.h"
|
||||
|
||||
struct _cairo_scaled_font_subsets {
|
||||
int max_glyphs_per_subset_limit;
|
||||
int max_glyphs_per_subset_used;
|
||||
int num_sub_fonts;
|
||||
int max_glyphs_per_unscaled_subset_limit;
|
||||
int max_glyphs_per_unscaled_subset_used;
|
||||
cairo_hash_table_t *unscaled_sub_fonts;
|
||||
|
||||
cairo_hash_table_t *sub_fonts;
|
||||
int max_glyphs_per_scaled_subset_limit;
|
||||
int max_glyphs_per_scaled_subset_used;
|
||||
cairo_hash_table_t *scaled_sub_fonts;
|
||||
|
||||
int num_sub_fonts;
|
||||
};
|
||||
|
||||
typedef struct _cairo_sub_font {
|
||||
cairo_hash_entry_t base;
|
||||
|
||||
cairo_bool_t is_scaled;
|
||||
cairo_scaled_font_subsets_t *parent;
|
||||
cairo_scaled_font_t *scaled_font;
|
||||
unsigned int font_id;
|
||||
|
@ -163,22 +168,34 @@ _cairo_sub_fonts_equal (const void *key_a, const void *key_b)
|
|||
const cairo_sub_font_t *sub_font_a = key_a;
|
||||
const cairo_sub_font_t *sub_font_b = key_b;
|
||||
|
||||
if (sub_font_a->is_scaled)
|
||||
return sub_font_a->scaled_font == sub_font_b->scaled_font;
|
||||
else
|
||||
return sub_font_a->scaled_font->font_face == sub_font_b->scaled_font->font_face;
|
||||
}
|
||||
|
||||
static void
|
||||
_cairo_sub_font_init_key (cairo_sub_font_t *sub_font,
|
||||
cairo_scaled_font_t *scaled_font)
|
||||
{
|
||||
if (sub_font->is_scaled)
|
||||
{
|
||||
sub_font->base.hash = (unsigned long) scaled_font;
|
||||
sub_font->scaled_font = scaled_font;
|
||||
}
|
||||
else
|
||||
{
|
||||
sub_font->base.hash = (unsigned long) scaled_font->font_face;
|
||||
sub_font->scaled_font = scaled_font;
|
||||
}
|
||||
}
|
||||
|
||||
static cairo_sub_font_t *
|
||||
_cairo_sub_font_create (cairo_scaled_font_subsets_t *parent,
|
||||
cairo_scaled_font_t *scaled_font,
|
||||
unsigned int font_id,
|
||||
int max_glyphs_per_subset)
|
||||
int max_glyphs_per_subset,
|
||||
cairo_bool_t is_scaled)
|
||||
{
|
||||
cairo_sub_font_t *sub_font;
|
||||
|
||||
|
@ -186,6 +203,7 @@ _cairo_sub_font_create (cairo_scaled_font_subsets_t *parent,
|
|||
if (sub_font == NULL)
|
||||
return NULL;
|
||||
|
||||
sub_font->is_scaled = is_scaled;
|
||||
_cairo_sub_font_init_key (sub_font, scaled_font);
|
||||
|
||||
sub_font->parent = parent;
|
||||
|
@ -226,6 +244,27 @@ _cairo_sub_font_pluck (void *entry, void *closure)
|
|||
_cairo_sub_font_destroy (sub_font);
|
||||
}
|
||||
|
||||
static cairo_status_t
|
||||
_cairo_sub_font_lookup_glyph (cairo_sub_font_t *sub_font,
|
||||
unsigned long scaled_font_glyph_index,
|
||||
unsigned int *subset_id,
|
||||
unsigned int *subset_glyph_index)
|
||||
{
|
||||
cairo_sub_font_glyph_t key, *sub_font_glyph;
|
||||
|
||||
_cairo_sub_font_glyph_init_key (&key, scaled_font_glyph_index);
|
||||
if (_cairo_hash_table_lookup (sub_font->sub_font_glyphs, &key.base,
|
||||
(cairo_hash_entry_t **) &sub_font_glyph))
|
||||
{
|
||||
*subset_id = sub_font_glyph->subset_id;
|
||||
*subset_glyph_index = sub_font_glyph->subset_glyph_index;
|
||||
|
||||
return CAIRO_STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
return CAIRO_STATUS_NULL_POINTER;
|
||||
}
|
||||
|
||||
static cairo_status_t
|
||||
_cairo_sub_font_map_glyph (cairo_sub_font_t *sub_font,
|
||||
unsigned long scaled_font_glyph_index,
|
||||
|
@ -239,8 +278,7 @@ _cairo_sub_font_map_glyph (cairo_sub_font_t *sub_font,
|
|||
if (! _cairo_hash_table_lookup (sub_font->sub_font_glyphs, &key.base,
|
||||
(cairo_hash_entry_t **) &sub_font_glyph))
|
||||
{
|
||||
if (sub_font->max_glyphs_per_subset &&
|
||||
sub_font->num_glyphs_in_current_subset == sub_font->max_glyphs_per_subset)
|
||||
if (sub_font->num_glyphs_in_current_subset == sub_font->max_glyphs_per_subset)
|
||||
{
|
||||
sub_font->current_subset++;
|
||||
sub_font->num_glyphs_in_current_subset = 0;
|
||||
|
@ -252,8 +290,16 @@ _cairo_sub_font_map_glyph (cairo_sub_font_t *sub_font,
|
|||
if (sub_font_glyph == NULL)
|
||||
return CAIRO_STATUS_NO_MEMORY;
|
||||
|
||||
if (sub_font->num_glyphs_in_current_subset > sub_font->parent->max_glyphs_per_subset_used)
|
||||
sub_font->parent->max_glyphs_per_subset_used = sub_font->num_glyphs_in_current_subset;
|
||||
if (sub_font->is_scaled)
|
||||
{
|
||||
if (sub_font->num_glyphs_in_current_subset > sub_font->parent->max_glyphs_per_scaled_subset_used)
|
||||
sub_font->parent->max_glyphs_per_scaled_subset_used = sub_font->num_glyphs_in_current_subset;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (sub_font->num_glyphs_in_current_subset > sub_font->parent->max_glyphs_per_unscaled_subset_used)
|
||||
sub_font->parent->max_glyphs_per_unscaled_subset_used = sub_font->num_glyphs_in_current_subset;
|
||||
}
|
||||
|
||||
status = _cairo_hash_table_insert (sub_font->sub_font_glyphs, &sub_font_glyph->base);
|
||||
if (status)
|
||||
|
@ -273,6 +319,7 @@ _cairo_sub_font_collect (void *entry, void *closure)
|
|||
cairo_sub_font_collection_t *collection = closure;
|
||||
cairo_scaled_font_subset_t subset;
|
||||
int i;
|
||||
unsigned int j;
|
||||
|
||||
for (i = 0; i <= sub_font->current_subset; i++) {
|
||||
collection->subset_id = i;
|
||||
|
@ -291,14 +338,26 @@ _cairo_sub_font_collect (void *entry, void *closure)
|
|||
subset.subset_id = i;
|
||||
subset.glyphs = collection->glyphs;
|
||||
subset.num_glyphs = collection->num_glyphs;
|
||||
|
||||
/* No need to check for out of memory here. If to_unicode is NULL, the PDF
|
||||
* surface does not emit an ToUnicode stream */
|
||||
subset.to_unicode = malloc (collection->num_glyphs*sizeof(unsigned long));
|
||||
if (subset.to_unicode) {
|
||||
for (j = 0; j < collection->num_glyphs; j++) {
|
||||
/* default unicode character required when mapping fails */
|
||||
subset.to_unicode[j] = 0xfffd;
|
||||
}
|
||||
}
|
||||
(collection->font_subset_callback) (&subset,
|
||||
collection->font_subset_callback_closure);
|
||||
|
||||
if (subset.to_unicode != NULL)
|
||||
free (subset.to_unicode);
|
||||
}
|
||||
}
|
||||
|
||||
cairo_scaled_font_subsets_t *
|
||||
_cairo_scaled_font_subsets_create (int max_glyphs_per_subset)
|
||||
_cairo_scaled_font_subsets_create (int max_glyphs_per_unscaled_subset,
|
||||
int max_glyphs_per_scaled_subset)
|
||||
{
|
||||
cairo_scaled_font_subsets_t *subsets;
|
||||
|
||||
|
@ -306,12 +365,23 @@ _cairo_scaled_font_subsets_create (int max_glyphs_per_subset)
|
|||
if (subsets == NULL)
|
||||
return NULL;
|
||||
|
||||
subsets->max_glyphs_per_subset_limit = max_glyphs_per_subset;
|
||||
subsets->max_glyphs_per_subset_used = 0;
|
||||
subsets->max_glyphs_per_unscaled_subset_limit = max_glyphs_per_unscaled_subset;
|
||||
subsets->max_glyphs_per_unscaled_subset_used = 0;
|
||||
|
||||
subsets->max_glyphs_per_scaled_subset_limit = max_glyphs_per_scaled_subset;
|
||||
subsets->max_glyphs_per_scaled_subset_used = 0;
|
||||
|
||||
subsets->num_sub_fonts = 0;
|
||||
|
||||
subsets->sub_fonts = _cairo_hash_table_create (_cairo_sub_fonts_equal);
|
||||
if (! subsets->sub_fonts) {
|
||||
subsets->unscaled_sub_fonts = _cairo_hash_table_create (_cairo_sub_fonts_equal);
|
||||
if (! subsets->unscaled_sub_fonts) {
|
||||
free (subsets);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
subsets->scaled_sub_fonts = _cairo_hash_table_create (_cairo_sub_fonts_equal);
|
||||
if (! subsets->scaled_sub_fonts) {
|
||||
free (subsets->unscaled_sub_fonts);
|
||||
free (subsets);
|
||||
return NULL;
|
||||
}
|
||||
|
@ -322,8 +392,11 @@ _cairo_scaled_font_subsets_create (int max_glyphs_per_subset)
|
|||
void
|
||||
_cairo_scaled_font_subsets_destroy (cairo_scaled_font_subsets_t *subsets)
|
||||
{
|
||||
_cairo_hash_table_foreach (subsets->sub_fonts, _cairo_sub_font_pluck, subsets->sub_fonts);
|
||||
_cairo_hash_table_destroy (subsets->sub_fonts);
|
||||
_cairo_hash_table_foreach (subsets->scaled_sub_fonts, _cairo_sub_font_pluck, subsets->scaled_sub_fonts);
|
||||
_cairo_hash_table_destroy (subsets->scaled_sub_fonts);
|
||||
|
||||
_cairo_hash_table_foreach (subsets->unscaled_sub_fonts, _cairo_sub_font_pluck, subsets->unscaled_sub_fonts);
|
||||
_cairo_hash_table_destroy (subsets->unscaled_sub_fonts);
|
||||
free (subsets);
|
||||
}
|
||||
|
||||
|
@ -336,38 +409,106 @@ _cairo_scaled_font_subsets_map_glyph (cairo_scaled_font_subsets_t *subsets,
|
|||
unsigned int *subset_glyph_index)
|
||||
{
|
||||
cairo_sub_font_t key, *sub_font;
|
||||
cairo_scaled_glyph_t *scaled_glyph;
|
||||
cairo_status_t status;
|
||||
|
||||
/* Lookup glyph in unscaled subsets */
|
||||
if (subsets->max_glyphs_per_unscaled_subset_limit > 0) {
|
||||
key.is_scaled = FALSE;
|
||||
_cairo_sub_font_init_key (&key, scaled_font);
|
||||
if (! _cairo_hash_table_lookup (subsets->sub_fonts, &key.base,
|
||||
if (_cairo_hash_table_lookup (subsets->unscaled_sub_fonts, &key.base,
|
||||
(cairo_hash_entry_t **) &sub_font))
|
||||
{
|
||||
status = _cairo_sub_font_lookup_glyph (sub_font, scaled_font_glyph_index,
|
||||
subset_id, subset_glyph_index);
|
||||
if (status == CAIRO_STATUS_SUCCESS) {
|
||||
*font_id = sub_font->font_id;
|
||||
return CAIRO_STATUS_SUCCESS;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* Lookup glyph in scaled subsets */
|
||||
if (subsets->max_glyphs_per_scaled_subset_limit > 0) {
|
||||
key.is_scaled = TRUE;
|
||||
_cairo_sub_font_init_key (&key, scaled_font);
|
||||
if (_cairo_hash_table_lookup (subsets->scaled_sub_fonts, &key.base,
|
||||
(cairo_hash_entry_t **) &sub_font))
|
||||
{
|
||||
status = _cairo_sub_font_lookup_glyph (sub_font, scaled_font_glyph_index,
|
||||
subset_id, subset_glyph_index);
|
||||
if (status == CAIRO_STATUS_SUCCESS) {
|
||||
*font_id = sub_font->font_id;
|
||||
return CAIRO_STATUS_SUCCESS;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* Glyph not found. Determine whether the glyph is outline or
|
||||
* bitmap and add to the appropriate subset */
|
||||
status = _cairo_scaled_glyph_lookup (scaled_font,
|
||||
scaled_font_glyph_index,
|
||||
CAIRO_SCALED_GLYPH_INFO_PATH,
|
||||
&scaled_glyph);
|
||||
if (status == 0 && subsets->max_glyphs_per_unscaled_subset_limit > 0) {
|
||||
/* Path available. Add to unscaled subset. */
|
||||
key.is_scaled = FALSE;
|
||||
_cairo_sub_font_init_key (&key, scaled_font);
|
||||
if (! _cairo_hash_table_lookup (subsets->unscaled_sub_fonts, &key.base,
|
||||
(cairo_hash_entry_t **) &sub_font))
|
||||
{
|
||||
sub_font = _cairo_sub_font_create (subsets, scaled_font,
|
||||
subsets->num_sub_fonts++,
|
||||
subsets->max_glyphs_per_subset_limit);
|
||||
subsets->max_glyphs_per_unscaled_subset_limit,
|
||||
FALSE);
|
||||
if (sub_font == NULL)
|
||||
return CAIRO_STATUS_NO_MEMORY;
|
||||
|
||||
status = _cairo_hash_table_insert (subsets->sub_fonts,
|
||||
status = _cairo_hash_table_insert (subsets->unscaled_sub_fonts,
|
||||
&sub_font->base);
|
||||
if (status)
|
||||
return status;
|
||||
}
|
||||
} else if (subsets->max_glyphs_per_scaled_subset_limit > 0) {
|
||||
/* No path available. Add to scaled subset. */
|
||||
key.is_scaled = TRUE;
|
||||
_cairo_sub_font_init_key (&key, scaled_font);
|
||||
if (! _cairo_hash_table_lookup (subsets->scaled_sub_fonts, &key.base,
|
||||
(cairo_hash_entry_t **) &sub_font))
|
||||
{
|
||||
sub_font = _cairo_sub_font_create (subsets, scaled_font,
|
||||
subsets->num_sub_fonts++,
|
||||
subsets->max_glyphs_per_scaled_subset_limit,
|
||||
TRUE);
|
||||
if (sub_font == NULL)
|
||||
return CAIRO_STATUS_NO_MEMORY;
|
||||
|
||||
status = _cairo_hash_table_insert (subsets->scaled_sub_fonts,
|
||||
&sub_font->base);
|
||||
if (status)
|
||||
return status;
|
||||
}
|
||||
} else {
|
||||
return CAIRO_INT_STATUS_UNSUPPORTED;
|
||||
}
|
||||
*font_id = sub_font->font_id;
|
||||
|
||||
return _cairo_sub_font_map_glyph (sub_font, scaled_font_glyph_index,
|
||||
subset_id, subset_glyph_index);
|
||||
}
|
||||
|
||||
cairo_private cairo_status_t
|
||||
_cairo_scaled_font_subsets_foreach (cairo_scaled_font_subsets_t *font_subsets,
|
||||
static cairo_status_t
|
||||
_cairo_scaled_font_subsets_foreach_internal (cairo_scaled_font_subsets_t *font_subsets,
|
||||
cairo_scaled_font_subset_callback_func_t font_subset_callback,
|
||||
void *closure)
|
||||
void *closure,
|
||||
cairo_bool_t is_scaled)
|
||||
{
|
||||
cairo_sub_font_collection_t collection;
|
||||
|
||||
collection.glyphs_size = font_subsets->max_glyphs_per_subset_used;
|
||||
if (is_scaled)
|
||||
collection.glyphs_size = font_subsets->max_glyphs_per_scaled_subset_used;
|
||||
else
|
||||
collection.glyphs_size = font_subsets->max_glyphs_per_unscaled_subset_used;
|
||||
collection.glyphs = malloc (collection.glyphs_size * sizeof(unsigned long));
|
||||
if (collection.glyphs == NULL)
|
||||
return CAIRO_STATUS_NO_MEMORY;
|
||||
|
@ -375,10 +516,36 @@ _cairo_scaled_font_subsets_foreach (cairo_scaled_font_subsets_t *font_subsets,
|
|||
collection.font_subset_callback = font_subset_callback;
|
||||
collection.font_subset_callback_closure = closure;
|
||||
|
||||
_cairo_hash_table_foreach (font_subsets->sub_fonts,
|
||||
if (is_scaled)
|
||||
_cairo_hash_table_foreach (font_subsets->scaled_sub_fonts,
|
||||
_cairo_sub_font_collect, &collection);
|
||||
else
|
||||
_cairo_hash_table_foreach (font_subsets->unscaled_sub_fonts,
|
||||
_cairo_sub_font_collect, &collection);
|
||||
|
||||
free (collection.glyphs);
|
||||
|
||||
return CAIRO_STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
cairo_private cairo_status_t
|
||||
_cairo_scaled_font_subsets_foreach_scaled (cairo_scaled_font_subsets_t *font_subsets,
|
||||
cairo_scaled_font_subset_callback_func_t font_subset_callback,
|
||||
void *closure)
|
||||
{
|
||||
return _cairo_scaled_font_subsets_foreach_internal (font_subsets,
|
||||
font_subset_callback,
|
||||
closure,
|
||||
TRUE);
|
||||
}
|
||||
|
||||
cairo_private cairo_status_t
|
||||
_cairo_scaled_font_subsets_foreach_unscaled (cairo_scaled_font_subsets_t *font_subsets,
|
||||
cairo_scaled_font_subset_callback_func_t font_subset_callback,
|
||||
void *closure)
|
||||
{
|
||||
return _cairo_scaled_font_subsets_foreach_internal (font_subsets,
|
||||
font_subset_callback,
|
||||
closure,
|
||||
FALSE);
|
||||
}
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
/* $Id: cairo-scaled-font.c,v 1.15 2007/04/03 19:21:53 vladimir%pobox.com Exp $
|
||||
*
|
||||
/* -*- Mode: c; c-basic-offset: 4; indent-tabs-mode: t; tab-width: 8; -*- */
|
||||
/*
|
||||
* Copyright © 2005 Keith Packard
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
|
@ -71,10 +71,11 @@ _cairo_scaled_glyph_destroy (void *abstract_glyph)
|
|||
free (scaled_glyph);
|
||||
}
|
||||
|
||||
static const cairo_scaled_font_t _cairo_scaled_font_nil = {
|
||||
const cairo_scaled_font_t _cairo_scaled_font_nil = {
|
||||
{ 0 }, /* hash_entry */
|
||||
CAIRO_STATUS_NO_MEMORY, /* status */
|
||||
CAIRO_REF_COUNT_INVALID, /* ref_count */
|
||||
{ 0, 0, 0, NULL }, /* user_data */
|
||||
NULL, /* font_face */
|
||||
{ 1., 0., 0., 1., 0, 0}, /* font_matrix */
|
||||
{ 1., 0., 0., 1., 0, 0}, /* ctm */
|
||||
|
@ -84,6 +85,7 @@ static const cairo_scaled_font_t _cairo_scaled_font_nil = {
|
|||
CAIRO_HINT_METRICS_DEFAULT} ,
|
||||
{ 1., 0., 0., 1., 0, 0}, /* scale */
|
||||
{ 0., 0., 0., 0., 0. }, /* extents */
|
||||
CAIRO_MUTEX_NIL_INITIALIZER,/* mutex */
|
||||
NULL, /* glyphs */
|
||||
NULL, /* surface_backend */
|
||||
NULL, /* surface_private */
|
||||
|
@ -183,7 +185,7 @@ typedef struct _cairo_scaled_font_map {
|
|||
|
||||
static cairo_scaled_font_map_t *cairo_scaled_font_map = NULL;
|
||||
|
||||
CAIRO_MUTEX_DECLARE (cairo_scaled_font_map_mutex);
|
||||
CAIRO_MUTEX_DECLARE (_cairo_scaled_font_map_mutex);
|
||||
|
||||
static int
|
||||
_cairo_scaled_font_keys_equal (const void *abstract_key_a, const void *abstract_key_b);
|
||||
|
@ -191,7 +193,7 @@ _cairo_scaled_font_keys_equal (const void *abstract_key_a, const void *abstract_
|
|||
static cairo_scaled_font_map_t *
|
||||
_cairo_scaled_font_map_lock (void)
|
||||
{
|
||||
CAIRO_MUTEX_LOCK (cairo_scaled_font_map_mutex);
|
||||
CAIRO_MUTEX_LOCK (_cairo_scaled_font_map_mutex);
|
||||
|
||||
if (cairo_scaled_font_map == NULL) {
|
||||
cairo_scaled_font_map = malloc (sizeof (cairo_scaled_font_map_t));
|
||||
|
@ -212,14 +214,14 @@ _cairo_scaled_font_map_lock (void)
|
|||
CLEANUP_SCALED_FONT_MAP:
|
||||
free (cairo_scaled_font_map);
|
||||
CLEANUP_MUTEX_LOCK:
|
||||
CAIRO_MUTEX_UNLOCK (cairo_scaled_font_map_mutex);
|
||||
CAIRO_MUTEX_UNLOCK (_cairo_scaled_font_map_mutex);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static void
|
||||
_cairo_scaled_font_map_unlock (void)
|
||||
{
|
||||
CAIRO_MUTEX_UNLOCK (cairo_scaled_font_map_mutex);
|
||||
CAIRO_MUTEX_UNLOCK (_cairo_scaled_font_map_mutex);
|
||||
}
|
||||
|
||||
void
|
||||
|
@ -229,7 +231,7 @@ _cairo_scaled_font_map_destroy (void)
|
|||
cairo_scaled_font_map_t *font_map;
|
||||
cairo_scaled_font_t *scaled_font;
|
||||
|
||||
CAIRO_MUTEX_LOCK (cairo_scaled_font_map_mutex);
|
||||
CAIRO_MUTEX_LOCK (_cairo_scaled_font_map_mutex);
|
||||
|
||||
font_map = cairo_scaled_font_map;
|
||||
if (font_map == NULL) {
|
||||
|
@ -254,7 +256,7 @@ _cairo_scaled_font_map_destroy (void)
|
|||
cairo_scaled_font_map = NULL;
|
||||
|
||||
CLEANUP_MUTEX_LOCK:
|
||||
CAIRO_MUTEX_UNLOCK (cairo_scaled_font_map_mutex);
|
||||
CAIRO_MUTEX_UNLOCK (_cairo_scaled_font_map_mutex);
|
||||
}
|
||||
|
||||
/* Fowler / Noll / Vo (FNV) Hash (http://www.isthe.com/chongo/tech/comp/fnv/)
|
||||
|
@ -352,6 +354,8 @@ _cairo_scaled_font_init (cairo_scaled_font_t *scaled_font,
|
|||
{
|
||||
scaled_font->ref_count = 1;
|
||||
|
||||
_cairo_user_data_array_init (&scaled_font->user_data);
|
||||
|
||||
_cairo_scaled_font_init_key (scaled_font, font_face,
|
||||
font_matrix, ctm, options);
|
||||
|
||||
|
@ -361,6 +365,7 @@ _cairo_scaled_font_init (cairo_scaled_font_t *scaled_font,
|
|||
&scaled_font->font_matrix,
|
||||
&scaled_font->ctm);
|
||||
|
||||
CAIRO_MUTEX_INIT (&scaled_font->mutex);
|
||||
scaled_font->glyphs = _cairo_cache_create (_cairo_scaled_glyph_keys_equal,
|
||||
_cairo_scaled_glyph_destroy,
|
||||
max_glyphs_cached_per_font);
|
||||
|
@ -385,6 +390,15 @@ _cairo_scaled_font_thaw_cache (cairo_scaled_font_t *scaled_font)
|
|||
_cairo_cache_thaw (scaled_font->glyphs);
|
||||
}
|
||||
|
||||
void
|
||||
_cairo_scaled_font_reset_cache (cairo_scaled_font_t *scaled_font)
|
||||
{
|
||||
_cairo_cache_destroy (scaled_font->glyphs);
|
||||
scaled_font->glyphs = _cairo_cache_create (_cairo_scaled_glyph_keys_equal,
|
||||
_cairo_scaled_glyph_destroy,
|
||||
max_glyphs_cached_per_font);
|
||||
}
|
||||
|
||||
void
|
||||
_cairo_scaled_font_set_metrics (cairo_scaled_font_t *scaled_font,
|
||||
cairo_font_extents_t *fs_metrics)
|
||||
|
@ -416,12 +430,15 @@ _cairo_scaled_font_fini (cairo_scaled_font_t *scaled_font)
|
|||
if (scaled_font->glyphs != NULL)
|
||||
_cairo_cache_destroy (scaled_font->glyphs);
|
||||
|
||||
CAIRO_MUTEX_FINI (&scaled_font->mutex);
|
||||
|
||||
if (scaled_font->surface_backend != NULL &&
|
||||
scaled_font->surface_backend->scaled_font_fini != NULL)
|
||||
scaled_font->surface_backend->scaled_font_fini (scaled_font);
|
||||
|
||||
scaled_font->backend->fini (scaled_font);
|
||||
|
||||
_cairo_user_data_array_fini (&scaled_font->user_data);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -459,7 +476,7 @@ cairo_scaled_font_create (cairo_font_face_t *font_face,
|
|||
|
||||
font_map = _cairo_scaled_font_map_lock ();
|
||||
if (font_map == NULL)
|
||||
goto UNWIND;
|
||||
return NULL;
|
||||
|
||||
_cairo_scaled_font_init_key (&key, font_face,
|
||||
font_matrix, ctm, options);
|
||||
|
@ -467,70 +484,6 @@ cairo_scaled_font_create (cairo_font_face_t *font_face,
|
|||
/* Return existing scaled_font if it exists in the hash table. */
|
||||
if (_cairo_hash_table_lookup (font_map->hash_table, &key.hash_entry,
|
||||
(cairo_hash_entry_t**) &scaled_font))
|
||||
{
|
||||
_cairo_scaled_font_map_unlock ();
|
||||
return cairo_scaled_font_reference (scaled_font);
|
||||
}
|
||||
|
||||
/* Otherwise create it and insert it into the hash table. */
|
||||
status = font_face->backend->scaled_font_create (font_face, font_matrix,
|
||||
ctm, options, &scaled_font);
|
||||
if (status)
|
||||
goto UNWIND_FONT_MAP_LOCK;
|
||||
|
||||
status = _cairo_hash_table_insert (font_map->hash_table,
|
||||
&scaled_font->hash_entry);
|
||||
if (status)
|
||||
goto UNWIND_SCALED_FONT_CREATE;
|
||||
|
||||
_cairo_scaled_font_map_unlock ();
|
||||
|
||||
return scaled_font;
|
||||
|
||||
UNWIND_SCALED_FONT_CREATE:
|
||||
/* We can't call _cairo_scaled_font_destroy here since it expects
|
||||
* that the font has already been successfully inserted into the
|
||||
* hash table. */
|
||||
_cairo_scaled_font_fini (scaled_font);
|
||||
free (scaled_font);
|
||||
UNWIND_FONT_MAP_LOCK:
|
||||
_cairo_scaled_font_map_unlock ();
|
||||
UNWIND:
|
||||
return NULL;
|
||||
}
|
||||
slim_hidden_def (cairo_scaled_font_create);
|
||||
|
||||
/**
|
||||
* cairo_scaled_font_reference:
|
||||
* @scaled_font: a #cairo_scaled_font_t, (may be NULL in which case
|
||||
* this function does nothing)
|
||||
*
|
||||
* Increases the reference count on @scaled_font by one. This prevents
|
||||
* @scaled_font from being destroyed until a matching call to
|
||||
* cairo_scaled_font_destroy() is made.
|
||||
*
|
||||
* Returns: the referenced #cairo_scaled_font_t
|
||||
**/
|
||||
cairo_scaled_font_t *
|
||||
cairo_scaled_font_reference (cairo_scaled_font_t *scaled_font)
|
||||
{
|
||||
cairo_scaled_font_map_t *font_map;
|
||||
|
||||
if (scaled_font == NULL)
|
||||
return NULL;
|
||||
|
||||
if (scaled_font->ref_count == CAIRO_REF_COUNT_INVALID)
|
||||
return scaled_font;
|
||||
|
||||
/* We would normally assert (scaled_font->ref_count > 0) here, but
|
||||
* we are using ref_count == 0 as a legitimate case for the
|
||||
* holdovers array. See below. */
|
||||
|
||||
/* cairo_scaled_font_t objects are cached and shared between
|
||||
* threads. This works because these objects are immutable. Except
|
||||
* that the reference count is mutable, so we have to do locking
|
||||
* around any modification of the reference count. */
|
||||
font_map = _cairo_scaled_font_map_lock ();
|
||||
{
|
||||
/* If the original reference count is 0, then this font must have
|
||||
* been found in font_map->holdovers, (which means this caching is
|
||||
|
@ -550,8 +503,64 @@ cairo_scaled_font_reference (cairo_scaled_font_t *scaled_font)
|
|||
(font_map->num_holdovers - i) * sizeof (cairo_scaled_font_t*));
|
||||
}
|
||||
|
||||
/* We increment the reference count manually here, (rather
|
||||
* than calling into cairo_scaled_font_reference), since we
|
||||
* must modify the reference count while our lock is still
|
||||
* held. */
|
||||
scaled_font->ref_count++;
|
||||
_cairo_scaled_font_map_unlock ();
|
||||
} else {
|
||||
/* Otherwise create it and insert it into the hash table. */
|
||||
status = font_face->backend->scaled_font_create (font_face, font_matrix,
|
||||
ctm, options, &scaled_font);
|
||||
if (status) {
|
||||
_cairo_scaled_font_map_unlock ();
|
||||
return NULL;
|
||||
}
|
||||
|
||||
status = _cairo_hash_table_insert (font_map->hash_table,
|
||||
&scaled_font->hash_entry);
|
||||
_cairo_scaled_font_map_unlock ();
|
||||
|
||||
if (status) {
|
||||
/* We can't call _cairo_scaled_font_destroy here since it expects
|
||||
* that the font has already been successfully inserted into the
|
||||
* hash table. */
|
||||
_cairo_scaled_font_fini (scaled_font);
|
||||
free (scaled_font);
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
|
||||
return scaled_font;
|
||||
}
|
||||
slim_hidden_def (cairo_scaled_font_create);
|
||||
|
||||
/**
|
||||
* cairo_scaled_font_reference:
|
||||
* @scaled_font: a #cairo_scaled_font_t, (may be NULL in which case
|
||||
* this function does nothing)
|
||||
*
|
||||
* Increases the reference count on @scaled_font by one. This prevents
|
||||
* @scaled_font from being destroyed until a matching call to
|
||||
* cairo_scaled_font_destroy() is made.
|
||||
*
|
||||
* The number of references to a #cairo_scaled_font_t can be get using
|
||||
* cairo_scaled_font_get_reference_count().
|
||||
*
|
||||
* Returns: the referenced #cairo_scaled_font_t
|
||||
**/
|
||||
cairo_scaled_font_t *
|
||||
cairo_scaled_font_reference (cairo_scaled_font_t *scaled_font)
|
||||
{
|
||||
if (scaled_font == NULL || scaled_font->ref_count == CAIRO_REF_COUNT_INVALID)
|
||||
return scaled_font;
|
||||
|
||||
_cairo_scaled_font_map_lock ();
|
||||
{
|
||||
assert (scaled_font->ref_count > 0);
|
||||
|
||||
scaled_font->ref_count++;
|
||||
}
|
||||
_cairo_scaled_font_map_unlock ();
|
||||
|
||||
|
@ -571,17 +580,11 @@ void
|
|||
cairo_scaled_font_destroy (cairo_scaled_font_t *scaled_font)
|
||||
{
|
||||
cairo_scaled_font_map_t *font_map;
|
||||
cairo_scaled_font_t *lru = NULL;
|
||||
|
||||
if (scaled_font == NULL)
|
||||
if (scaled_font == NULL || scaled_font->ref_count == CAIRO_REF_COUNT_INVALID)
|
||||
return;
|
||||
|
||||
if (scaled_font->ref_count == CAIRO_REF_COUNT_INVALID)
|
||||
return;
|
||||
|
||||
/* cairo_scaled_font_t objects are cached and shared between
|
||||
* threads. This works because these objects are immutable. Except
|
||||
* that the reference count is mutable, so we have to do locking
|
||||
* around any modification of the reference count. */
|
||||
font_map = _cairo_scaled_font_map_lock ();
|
||||
{
|
||||
assert (font_map != NULL);
|
||||
|
@ -595,17 +598,13 @@ cairo_scaled_font_destroy (cairo_scaled_font_t *scaled_font)
|
|||
* soon. To make room for it, we do actually destroy the
|
||||
* least-recently-used holdover.
|
||||
*/
|
||||
if (font_map->num_holdovers == CAIRO_SCALED_FONT_MAX_HOLDOVERS) {
|
||||
cairo_scaled_font_t *lru;
|
||||
|
||||
if (font_map->num_holdovers == CAIRO_SCALED_FONT_MAX_HOLDOVERS)
|
||||
{
|
||||
lru = font_map->holdovers[0];
|
||||
assert (lru->ref_count == 0);
|
||||
|
||||
_cairo_hash_table_remove (font_map->hash_table, &lru->hash_entry);
|
||||
|
||||
_cairo_scaled_font_fini (lru);
|
||||
free (lru);
|
||||
|
||||
font_map->num_holdovers--;
|
||||
memmove (&font_map->holdovers[0],
|
||||
&font_map->holdovers[1],
|
||||
|
@ -617,9 +616,93 @@ cairo_scaled_font_destroy (cairo_scaled_font_t *scaled_font)
|
|||
}
|
||||
}
|
||||
_cairo_scaled_font_map_unlock ();
|
||||
|
||||
/* If we pulled an item from the holdovers array, (while the font
|
||||
* map lock was held, of course), then there is no way that anyone
|
||||
* else could have acquired a reference to it. So we can now
|
||||
* safely call fini on it without any lock held. This is desirable
|
||||
* as we never want to call into any backend function with a lock
|
||||
* held. */
|
||||
if (lru) {
|
||||
_cairo_scaled_font_fini (lru);
|
||||
free (lru);
|
||||
}
|
||||
}
|
||||
slim_hidden_def (cairo_scaled_font_destroy);
|
||||
|
||||
/**
|
||||
* cairo_scaled_font_get_reference_count:
|
||||
* @scaled_font: a #cairo_scaled_font_t
|
||||
*
|
||||
* Returns the current reference count of @scaled_font.
|
||||
*
|
||||
* Return value: the current reference count of @scaled_font. If the
|
||||
* object is a nil object, 0 will be returned.
|
||||
*
|
||||
* Since: 1.4
|
||||
**/
|
||||
unsigned int
|
||||
cairo_scaled_font_get_reference_count (cairo_scaled_font_t *scaled_font)
|
||||
{
|
||||
if (scaled_font == NULL || scaled_font->ref_count == CAIRO_REF_COUNT_INVALID)
|
||||
return 0;
|
||||
|
||||
return scaled_font->ref_count;
|
||||
}
|
||||
|
||||
/**
|
||||
* cairo_scaled_font_get_user_data:
|
||||
* @scaled_font: a #cairo_scaled_font_t
|
||||
* @key: the address of the #cairo_user_data_key_t the user data was
|
||||
* attached to
|
||||
*
|
||||
* Return user data previously attached to @scaled_font using the
|
||||
* specified key. If no user data has been attached with the given
|
||||
* key this function returns %NULL.
|
||||
*
|
||||
* Return value: the user data previously attached or %NULL.
|
||||
*
|
||||
* Since: 1.4
|
||||
**/
|
||||
void *
|
||||
cairo_scaled_font_get_user_data (cairo_scaled_font_t *scaled_font,
|
||||
const cairo_user_data_key_t *key)
|
||||
{
|
||||
return _cairo_user_data_array_get_data (&scaled_font->user_data,
|
||||
key);
|
||||
}
|
||||
|
||||
/**
|
||||
* cairo_scaled_font_set_user_data:
|
||||
* @scaled_font: a #cairo_scaled_font_t
|
||||
* @key: the address of a #cairo_user_data_key_t to attach the user data to
|
||||
* @user_data: the user data to attach to the #cairo_scaled_font_t
|
||||
* @destroy: a #cairo_destroy_func_t which will be called when the
|
||||
* #cairo_t is destroyed or when new user data is attached using the
|
||||
* same key.
|
||||
*
|
||||
* Attach user data to @scaled_font. To remove user data from a surface,
|
||||
* call this function with the key that was used to set it and %NULL
|
||||
* for @data.
|
||||
*
|
||||
* Return value: %CAIRO_STATUS_SUCCESS or %CAIRO_STATUS_NO_MEMORY if a
|
||||
* slot could not be allocated for the user data.
|
||||
*
|
||||
* Since: 1.4
|
||||
**/
|
||||
cairo_status_t
|
||||
cairo_scaled_font_set_user_data (cairo_scaled_font_t *scaled_font,
|
||||
const cairo_user_data_key_t *key,
|
||||
void *user_data,
|
||||
cairo_destroy_func_t destroy)
|
||||
{
|
||||
if (scaled_font->ref_count == CAIRO_REF_COUNT_INVALID)
|
||||
return CAIRO_STATUS_NO_MEMORY;
|
||||
|
||||
return _cairo_user_data_array_set_data (&scaled_font->user_data,
|
||||
key, user_data, destroy);
|
||||
}
|
||||
|
||||
/* Public font API follows. */
|
||||
|
||||
/**
|
||||
|
@ -711,6 +794,8 @@ cairo_scaled_font_glyph_extents (cairo_scaled_font_t *scaled_font,
|
|||
if (scaled_font->status)
|
||||
return;
|
||||
|
||||
CAIRO_MUTEX_LOCK (scaled_font->mutex);
|
||||
|
||||
for (i = 0; i < num_glyphs; i++) {
|
||||
double left, top, right, bottom;
|
||||
|
||||
|
@ -720,7 +805,7 @@ cairo_scaled_font_glyph_extents (cairo_scaled_font_t *scaled_font,
|
|||
&scaled_glyph);
|
||||
if (status) {
|
||||
_cairo_scaled_font_set_error (scaled_font, status);
|
||||
return;
|
||||
goto UNLOCK;
|
||||
}
|
||||
|
||||
/* "Ink" extents should skip "invisible" glyphs */
|
||||
|
@ -774,6 +859,9 @@ cairo_scaled_font_glyph_extents (cairo_scaled_font_t *scaled_font,
|
|||
extents->x_advance = 0.0;
|
||||
extents->y_advance = 0.0;
|
||||
}
|
||||
|
||||
UNLOCK:
|
||||
CAIRO_MUTEX_UNLOCK (scaled_font->mutex);
|
||||
}
|
||||
slim_hidden_def (cairo_scaled_font_glyph_extents);
|
||||
|
||||
|
@ -796,24 +884,26 @@ _cairo_scaled_font_text_to_glyphs (cairo_scaled_font_t *scaled_font,
|
|||
return CAIRO_STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
CAIRO_MUTEX_LOCK (scaled_font->mutex);
|
||||
|
||||
if (scaled_font->backend->text_to_glyphs) {
|
||||
status = scaled_font->backend->text_to_glyphs (scaled_font,
|
||||
x, y, utf8,
|
||||
glyphs, num_glyphs);
|
||||
|
||||
if (status != CAIRO_INT_STATUS_UNSUPPORTED)
|
||||
return status;
|
||||
goto DONE;
|
||||
}
|
||||
|
||||
status = _cairo_utf8_to_ucs4 ((unsigned char*)utf8, -1, &ucs4, num_glyphs);
|
||||
if (status)
|
||||
return status;
|
||||
goto DONE;
|
||||
|
||||
*glyphs = (cairo_glyph_t *) malloc ((*num_glyphs) * (sizeof (cairo_glyph_t)));
|
||||
|
||||
if (*glyphs == NULL) {
|
||||
status = CAIRO_STATUS_NO_MEMORY;
|
||||
goto FAIL;
|
||||
goto DONE;
|
||||
}
|
||||
|
||||
for (i = 0; i < *num_glyphs; i++) {
|
||||
|
@ -829,14 +919,17 @@ _cairo_scaled_font_text_to_glyphs (cairo_scaled_font_t *scaled_font,
|
|||
if (status) {
|
||||
free (*glyphs);
|
||||
*glyphs = NULL;
|
||||
goto FAIL;
|
||||
goto DONE;
|
||||
}
|
||||
|
||||
x += scaled_glyph->metrics.x_advance;
|
||||
y += scaled_glyph->metrics.y_advance;
|
||||
}
|
||||
|
||||
FAIL:
|
||||
DONE:
|
||||
CAIRO_MUTEX_UNLOCK (scaled_font->mutex);
|
||||
|
||||
if (ucs4)
|
||||
free (ucs4);
|
||||
|
||||
return status;
|
||||
|
@ -1338,6 +1431,8 @@ _cairo_scaled_glyph_set_path (cairo_scaled_glyph_t *scaled_glyph,
|
|||
* If the desired info is not available, (for example, when trying to
|
||||
* get INFO_PATH with a bitmapped font), this function will return
|
||||
* CAIRO_INT_STATUS_UNSUPPORTED.
|
||||
*
|
||||
* NOTE: This function must be called with scaled_font->mutex held.
|
||||
**/
|
||||
cairo_int_status_t
|
||||
_cairo_scaled_glyph_lookup (cairo_scaled_font_t *scaled_font,
|
||||
|
@ -1353,8 +1448,6 @@ _cairo_scaled_glyph_lookup (cairo_scaled_font_t *scaled_font,
|
|||
if (scaled_font->status)
|
||||
return scaled_font->status;
|
||||
|
||||
CAIRO_MUTEX_LOCK (cairo_scaled_font_map_mutex);
|
||||
|
||||
key.hash = index;
|
||||
/*
|
||||
* Check cache for glyph
|
||||
|
@ -1425,8 +1518,6 @@ _cairo_scaled_glyph_lookup (cairo_scaled_font_t *scaled_font,
|
|||
*scaled_glyph_ret = scaled_glyph;
|
||||
}
|
||||
|
||||
CAIRO_MUTEX_UNLOCK (cairo_scaled_font_map_mutex);
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
|
|
|
@ -34,7 +34,7 @@
|
|||
* a skip_elt_t, (which will be allocated with variable size).
|
||||
*
|
||||
* The caller must also pass the size of the structure to
|
||||
* skip_list_init.
|
||||
* _cairo_skip_list_init.
|
||||
*/
|
||||
typedef struct _skip_elt {
|
||||
int prev_index;
|
||||
|
@ -45,16 +45,16 @@ typedef struct _skip_elt {
|
|||
#define SKIP_LIST_ELT_TO_DATA(type, elt) ((type *) ((char *) (elt) - (sizeof (type) - sizeof (skip_elt_t))))
|
||||
|
||||
typedef int
|
||||
(*skip_list_compare_t) (void *list, void *a, void *b);
|
||||
(*cairo_skip_list_compare_t) (void *list, void *a, void *b);
|
||||
|
||||
typedef struct _skip_list {
|
||||
skip_list_compare_t compare;
|
||||
cairo_skip_list_compare_t compare;
|
||||
size_t elt_size;
|
||||
size_t data_size;
|
||||
skip_elt_t *chains[MAX_LEVEL];
|
||||
skip_elt_t *freelists[MAX_LEVEL];
|
||||
int max_level;
|
||||
} skip_list_t;
|
||||
} cairo_skip_list_t;
|
||||
|
||||
/* Initialize a new skip list. The compare function accepts a pointer
|
||||
* to the list as well as pointers to two elements. The function must
|
||||
|
@ -65,8 +65,8 @@ typedef struct _skip_list {
|
|||
* list elements must have as its final member a skip_elt_t
|
||||
*/
|
||||
cairo_private void
|
||||
skip_list_init (skip_list_t *list,
|
||||
skip_list_compare_t compare,
|
||||
_cairo_skip_list_init (cairo_skip_list_t *list,
|
||||
cairo_skip_list_compare_t compare,
|
||||
size_t elt_size);
|
||||
|
||||
|
||||
|
@ -74,7 +74,7 @@ skip_list_init (skip_list_t *list,
|
|||
* in it. (XXX: currently this simply deletes all elements.)
|
||||
*/
|
||||
cairo_private void
|
||||
skip_list_fini (skip_list_t *list);
|
||||
_cairo_skip_list_fini (cairo_skip_list_t *list);
|
||||
|
||||
/* Insert a new element into the list at the correct sort order as
|
||||
* determined by compare. If unique is true, then duplicate elements
|
||||
|
@ -82,18 +82,18 @@ skip_list_fini (skip_list_t *list);
|
|||
* Otherwise data will be copied (elt_size bytes from <data> via
|
||||
* memcpy) and the new element is returned. */
|
||||
cairo_private void *
|
||||
skip_list_insert (skip_list_t *list, void *data, int unique);
|
||||
_cairo_skip_list_insert (cairo_skip_list_t *list, void *data, int unique);
|
||||
|
||||
/* Find an element which compare considers equal to <data> */
|
||||
cairo_private void *
|
||||
skip_list_find (skip_list_t *list, void *data);
|
||||
_cairo_skip_list_find (cairo_skip_list_t *list, void *data);
|
||||
|
||||
/* Delete an element which compare considers equal to <data> */
|
||||
cairo_private void
|
||||
skip_list_delete (skip_list_t *list, void *data);
|
||||
_cairo_skip_list_delete (cairo_skip_list_t *list, void *data);
|
||||
|
||||
/* Delete the given element from the list. */
|
||||
cairo_private void
|
||||
skip_list_delete_given (skip_list_t *list, skip_elt_t *given);
|
||||
_cairo_skip_list_delete_given (cairo_skip_list_t *list, skip_elt_t *given);
|
||||
|
||||
#endif
|
||||
|
|
|
@ -34,7 +34,7 @@
|
|||
|
||||
/* Four 256 element lookup tables back to back implementing a linear
|
||||
* feedback shift register of degree 32. */
|
||||
static unsigned const lfsr_lut[1024] = {
|
||||
static unsigned const _cairo_lfsr_random_lut[1024] = {
|
||||
0x00000000, 0x9a795537, 0xae8bff59, 0x34f2aa6e, 0xc76eab85, 0x5d17feb2,
|
||||
0x69e554dc, 0xf39c01eb, 0x14a4023d, 0x8edd570a, 0xba2ffd64, 0x2056a853,
|
||||
0xd3caa9b8, 0x49b3fc8f, 0x7d4156e1, 0xe73803d6, 0x2948047a, 0xb331514d,
|
||||
|
@ -207,24 +207,25 @@ static unsigned const lfsr_lut[1024] = {
|
|||
0xeaa6b0df, 0x6a98c0b4, 0x184c1316, 0x9872637d, 0x8249a6f7, 0x0277d69c,
|
||||
0xb63e2de3, 0x36005d88, 0x2c3b9802, 0xac05e869};
|
||||
|
||||
static unsigned _cairo_lfsr_random_state = 0x12345678;
|
||||
|
||||
static unsigned
|
||||
lfsr_random(void)
|
||||
{
|
||||
static unsigned state = 0x12345678;
|
||||
unsigned next;
|
||||
next = lfsr_lut[((state>> 0) & 0xFF) + 0*256];
|
||||
next ^= lfsr_lut[((state>> 8) & 0xFF) + 1*256];
|
||||
next ^= lfsr_lut[((state>>16) & 0xFF) + 2*256];
|
||||
next ^= lfsr_lut[((state>>24) & 0xFF) + 3*256];
|
||||
return state = next;
|
||||
next = _cairo_lfsr_random_lut[((_cairo_lfsr_random_state>> 0) & 0xFF) + 0*256];
|
||||
next ^= _cairo_lfsr_random_lut[((_cairo_lfsr_random_state>> 8) & 0xFF) + 1*256];
|
||||
next ^= _cairo_lfsr_random_lut[((_cairo_lfsr_random_state>>16) & 0xFF) + 2*256];
|
||||
next ^= _cairo_lfsr_random_lut[((_cairo_lfsr_random_state>>24) & 0xFF) + 3*256];
|
||||
return _cairo_lfsr_random_state = next;
|
||||
}
|
||||
|
||||
/*
|
||||
* Initialize an empty skip list
|
||||
*/
|
||||
void
|
||||
skip_list_init (skip_list_t *list,
|
||||
skip_list_compare_t compare,
|
||||
_cairo_skip_list_init (cairo_skip_list_t *list,
|
||||
cairo_skip_list_compare_t compare,
|
||||
size_t elt_size)
|
||||
{
|
||||
int i;
|
||||
|
@ -242,13 +243,13 @@ skip_list_init (skip_list_t *list,
|
|||
}
|
||||
|
||||
void
|
||||
skip_list_fini (skip_list_t *list)
|
||||
_cairo_skip_list_fini (cairo_skip_list_t *list)
|
||||
{
|
||||
skip_elt_t *elt;
|
||||
int i;
|
||||
|
||||
while ((elt = list->chains[0])) {
|
||||
skip_list_delete_given (list, elt);
|
||||
_cairo_skip_list_delete_given (list, elt);
|
||||
}
|
||||
for (i=0; i<MAX_LEVEL; i++) {
|
||||
elt = list->freelists[i];
|
||||
|
@ -283,7 +284,7 @@ random_level (void)
|
|||
}
|
||||
|
||||
static void *
|
||||
alloc_node_for_level (skip_list_t *list, unsigned level)
|
||||
alloc_node_for_level (cairo_skip_list_t *list, unsigned level)
|
||||
{
|
||||
if (list->freelists[level-1]) {
|
||||
skip_elt_t *elt = list->freelists[level-1];
|
||||
|
@ -294,7 +295,7 @@ alloc_node_for_level (skip_list_t *list, unsigned level)
|
|||
}
|
||||
|
||||
static void
|
||||
free_elt (skip_list_t *list, skip_elt_t *elt)
|
||||
free_elt (cairo_skip_list_t *list, skip_elt_t *elt)
|
||||
{
|
||||
elt->prev = list->freelists[elt->prev_index];
|
||||
list->freelists[elt->prev_index] = elt;
|
||||
|
@ -304,7 +305,7 @@ free_elt (skip_list_t *list, skip_elt_t *elt)
|
|||
* Insert 'data' into the list
|
||||
*/
|
||||
void *
|
||||
skip_list_insert (skip_list_t *list, void *data, int unique)
|
||||
_cairo_skip_list_insert (cairo_skip_list_t *list, void *data, int unique)
|
||||
{
|
||||
skip_elt_t **update[MAX_LEVEL];
|
||||
skip_elt_t *prev[MAX_LEVEL];
|
||||
|
@ -369,7 +370,7 @@ skip_list_insert (skip_list_t *list, void *data, int unique)
|
|||
}
|
||||
|
||||
void *
|
||||
skip_list_find (skip_list_t *list, void *data)
|
||||
_cairo_skip_list_find (cairo_skip_list_t *list, void *data)
|
||||
{
|
||||
int i;
|
||||
skip_elt_t **next = list->chains;
|
||||
|
@ -394,7 +395,7 @@ skip_list_find (skip_list_t *list, void *data)
|
|||
}
|
||||
|
||||
void
|
||||
skip_list_delete (skip_list_t *list, void *data)
|
||||
_cairo_skip_list_delete (cairo_skip_list_t *list, void *data)
|
||||
{
|
||||
skip_elt_t **update[MAX_LEVEL], *prev[MAX_LEVEL];
|
||||
skip_elt_t *elt, **next;
|
||||
|
@ -430,7 +431,7 @@ skip_list_delete (skip_list_t *list, void *data)
|
|||
}
|
||||
|
||||
void
|
||||
skip_list_delete_given (skip_list_t *list, skip_elt_t *given)
|
||||
_cairo_skip_list_delete_given (cairo_skip_list_t *list, skip_elt_t *given)
|
||||
{
|
||||
skip_elt_t **update[MAX_LEVEL], *prev[MAX_LEVEL];
|
||||
skip_elt_t *elt, **next;
|
||||
|
|
|
@ -51,7 +51,7 @@ _cairo_slope_init (cairo_slope_t *slope, cairo_point_t *a, cairo_point_t *b)
|
|||
difference between a and b is less than PI.
|
||||
|
||||
< 0 => a less positive than b
|
||||
== 0 => a equal to be
|
||||
== 0 => a equal to b
|
||||
> 0 => a more positive than b
|
||||
*/
|
||||
int
|
||||
|
@ -67,6 +67,12 @@ _cairo_slope_compare (cairo_slope_t *a, cairo_slope_t *b)
|
|||
if (diff < 0)
|
||||
return -1;
|
||||
|
||||
/* special-case zero vectors. the intended logic here is:
|
||||
* zero vectors all compare equal, and more positive than any
|
||||
* non-zero vector.
|
||||
*/
|
||||
if (a->dx == 0 && a->dy == 0 && b->dx == 0 && b->dy ==0)
|
||||
return 0;
|
||||
if (a->dx == 0 && a->dy == 0)
|
||||
return 1;
|
||||
if (b->dx == 0 && b->dy ==0)
|
||||
|
|
|
@ -37,7 +37,7 @@
|
|||
#include "cairoint.h"
|
||||
|
||||
static cairo_status_t
|
||||
_cairo_spline_grow_by (cairo_spline_t *spline, int additional);
|
||||
_cairo_spline_grow (cairo_spline_t *spline);
|
||||
|
||||
static cairo_status_t
|
||||
_cairo_spline_add_point (cairo_spline_t *spline, cairo_point_t *point);
|
||||
|
@ -90,31 +90,47 @@ _cairo_spline_init (cairo_spline_t *spline,
|
|||
void
|
||||
_cairo_spline_fini (cairo_spline_t *spline)
|
||||
{
|
||||
spline->num_points = 0;
|
||||
spline->points_size = 0;
|
||||
if (spline->points && spline->points != spline->points_embedded)
|
||||
free (spline->points);
|
||||
|
||||
spline->points = NULL;
|
||||
spline->points_size = 0;
|
||||
spline->num_points = 0;
|
||||
}
|
||||
|
||||
/* make room for at least one more point */
|
||||
static cairo_status_t
|
||||
_cairo_spline_grow_by (cairo_spline_t *spline, int additional)
|
||||
_cairo_spline_grow (cairo_spline_t *spline)
|
||||
{
|
||||
cairo_point_t *new_points;
|
||||
int old_size = spline->points_size;
|
||||
int new_size = spline->num_points + additional;
|
||||
int embedded_size = sizeof (spline->points_embedded) / sizeof (spline->points_embedded[0]);
|
||||
int new_size = 2 * MAX (old_size, 16);
|
||||
|
||||
if (new_size <= spline->points_size)
|
||||
/* we have a local buffer at spline->points_embedded. try to fulfill the request
|
||||
* from there. */
|
||||
if (old_size < embedded_size) {
|
||||
spline->points = spline->points_embedded;
|
||||
spline->points_size = embedded_size;
|
||||
return CAIRO_STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
spline->points_size = new_size;
|
||||
new_points = realloc (spline->points, spline->points_size * sizeof (cairo_point_t));
|
||||
assert (spline->num_points <= spline->points_size);
|
||||
|
||||
if (spline->points == spline->points_embedded) {
|
||||
new_points = malloc (new_size * sizeof (cairo_point_t));
|
||||
if (new_points)
|
||||
memcpy (new_points, spline->points, old_size * sizeof (cairo_point_t));
|
||||
} else {
|
||||
new_points = realloc (spline->points, new_size * sizeof (cairo_point_t));
|
||||
}
|
||||
|
||||
if (new_points == NULL) {
|
||||
spline->points_size = old_size;
|
||||
return CAIRO_STATUS_NO_MEMORY;
|
||||
}
|
||||
|
||||
spline->points = new_points;
|
||||
spline->points_size = new_size;
|
||||
|
||||
return CAIRO_STATUS_SUCCESS;
|
||||
}
|
||||
|
@ -132,8 +148,7 @@ _cairo_spline_add_point (cairo_spline_t *spline, cairo_point_t *point)
|
|||
}
|
||||
|
||||
if (spline->num_points >= spline->points_size) {
|
||||
int additional = spline->points_size ? spline->points_size : 32;
|
||||
status = _cairo_spline_grow_by (spline, additional);
|
||||
status = _cairo_spline_grow (spline);
|
||||
if (status)
|
||||
return status;
|
||||
}
|
||||
|
|
|
@ -41,107 +41,45 @@
|
|||
#include "cairo-surface-fallback-private.h"
|
||||
#include "cairo-clip-private.h"
|
||||
|
||||
const cairo_surface_t _cairo_surface_nil = {
|
||||
&cairo_image_surface_backend, /* backend */
|
||||
CAIRO_SURFACE_TYPE_IMAGE,
|
||||
CAIRO_CONTENT_COLOR,
|
||||
CAIRO_REF_COUNT_INVALID, /* ref_count */
|
||||
CAIRO_STATUS_NO_MEMORY, /* status */
|
||||
FALSE, /* finished */
|
||||
{ 0, /* size */
|
||||
0, /* num_elements */
|
||||
0, /* element_size */
|
||||
NULL, /* elements */
|
||||
}, /* user_data */
|
||||
{ 1.0, 0.0,
|
||||
0.0, 1.0,
|
||||
0.0, 0.0
|
||||
}, /* device_transform */
|
||||
{ 1.0, 0.0,
|
||||
0.0, 1.0,
|
||||
0.0, 0.0
|
||||
}, /* device_transform_inverse */
|
||||
0.0, /* x_fallback_resolution */
|
||||
0.0, /* y_fallback_resolution */
|
||||
NULL, /* clip */
|
||||
0, /* next_clip_serial */
|
||||
0, /* current_clip_serial */
|
||||
FALSE, /* is_snapshot */
|
||||
FALSE, /* has_font_options */
|
||||
{ CAIRO_ANTIALIAS_DEFAULT,
|
||||
CAIRO_SUBPIXEL_ORDER_DEFAULT,
|
||||
CAIRO_HINT_STYLE_DEFAULT,
|
||||
CAIRO_HINT_METRICS_DEFAULT
|
||||
} /* font_options */
|
||||
};
|
||||
#define DEFINE_NIL_SURFACE(status, name) \
|
||||
const cairo_surface_t name = { \
|
||||
&cairo_image_surface_backend, /* backend */ \
|
||||
CAIRO_SURFACE_TYPE_IMAGE, \
|
||||
CAIRO_CONTENT_COLOR, \
|
||||
CAIRO_REF_COUNT_INVALID, /* ref_count */ \
|
||||
status, /* status */ \
|
||||
FALSE, /* finished */ \
|
||||
{ 0, /* size */ \
|
||||
0, /* num_elements */ \
|
||||
0, /* element_size */ \
|
||||
NULL, /* elements */ \
|
||||
}, /* user_data */ \
|
||||
{ 1.0, 0.0, \
|
||||
0.0, 1.0, \
|
||||
0.0, 0.0 \
|
||||
}, /* device_transform */ \
|
||||
{ 1.0, 0.0, \
|
||||
0.0, 1.0, \
|
||||
0.0, 0.0 \
|
||||
}, /* device_transform_inverse */ \
|
||||
0.0, /* x_fallback_resolution */ \
|
||||
0.0, /* y_fallback_resolution */ \
|
||||
NULL, /* clip */ \
|
||||
0, /* next_clip_serial */ \
|
||||
0, /* current_clip_serial */ \
|
||||
FALSE, /* is_snapshot */ \
|
||||
FALSE, /* has_font_options */ \
|
||||
{ CAIRO_ANTIALIAS_DEFAULT, \
|
||||
CAIRO_SUBPIXEL_ORDER_DEFAULT, \
|
||||
CAIRO_HINT_STYLE_DEFAULT, \
|
||||
CAIRO_HINT_METRICS_DEFAULT \
|
||||
} /* font_options */ \
|
||||
}
|
||||
|
||||
const cairo_surface_t _cairo_surface_nil_file_not_found = {
|
||||
&cairo_image_surface_backend, /* backend */
|
||||
CAIRO_SURFACE_TYPE_IMAGE,
|
||||
CAIRO_CONTENT_COLOR,
|
||||
CAIRO_REF_COUNT_INVALID, /* ref_count */
|
||||
CAIRO_STATUS_FILE_NOT_FOUND, /* status */
|
||||
FALSE, /* finished */
|
||||
{ 0, /* size */
|
||||
0, /* num_elements */
|
||||
0, /* element_size */
|
||||
NULL, /* elements */
|
||||
}, /* user_data */
|
||||
{ 1.0, 0.0,
|
||||
0.0, 1.0,
|
||||
0.0, 0.0
|
||||
}, /* device_transform */
|
||||
{ 1.0, 0.0,
|
||||
0.0, 1.0,
|
||||
0.0, 0.0
|
||||
}, /* device_transform_inverse */
|
||||
0.0, /* x_fallback_resolution */
|
||||
0.0, /* y_fallback_resolution */
|
||||
NULL, /* clip */
|
||||
0, /* next_clip_serial */
|
||||
0, /* current_clip_serial */
|
||||
FALSE, /* is_snapshot */
|
||||
FALSE, /* has_font_options */
|
||||
{ CAIRO_ANTIALIAS_DEFAULT,
|
||||
CAIRO_SUBPIXEL_ORDER_DEFAULT,
|
||||
CAIRO_HINT_STYLE_DEFAULT,
|
||||
CAIRO_HINT_METRICS_DEFAULT
|
||||
} /* font_options */
|
||||
};
|
||||
|
||||
const cairo_surface_t _cairo_surface_nil_read_error = {
|
||||
&cairo_image_surface_backend, /* backend */
|
||||
CAIRO_SURFACE_TYPE_IMAGE,
|
||||
CAIRO_CONTENT_COLOR,
|
||||
CAIRO_REF_COUNT_INVALID, /* ref_count */
|
||||
CAIRO_STATUS_READ_ERROR, /* status */
|
||||
FALSE, /* finished */
|
||||
{ 0, /* size */
|
||||
0, /* num_elements */
|
||||
0, /* element_size */
|
||||
NULL, /* elements */
|
||||
}, /* user_data */
|
||||
{ 1.0, 0.0,
|
||||
0.0, 1.0,
|
||||
0.0, 0.0
|
||||
}, /* device_transform */
|
||||
{ 1.0, 0.0,
|
||||
0.0, 1.0,
|
||||
0.0, 0.0
|
||||
}, /* device_transform_inverse */
|
||||
0.0, /* x_fallback_resolution */
|
||||
0.0, /* y_fallback_resolution */
|
||||
NULL, /* clip */
|
||||
0, /* next_clip_serial */
|
||||
0, /* current_clip_serial */
|
||||
FALSE, /* is_snapshot */
|
||||
FALSE, /* has_font_options */
|
||||
{ CAIRO_ANTIALIAS_DEFAULT,
|
||||
CAIRO_SUBPIXEL_ORDER_DEFAULT,
|
||||
CAIRO_HINT_STYLE_DEFAULT,
|
||||
CAIRO_HINT_METRICS_DEFAULT
|
||||
} /* font_options */
|
||||
};
|
||||
DEFINE_NIL_SURFACE(CAIRO_STATUS_NO_MEMORY, _cairo_surface_nil);
|
||||
DEFINE_NIL_SURFACE(CAIRO_STATUS_FILE_NOT_FOUND, _cairo_surface_nil_file_not_found);
|
||||
DEFINE_NIL_SURFACE(CAIRO_STATUS_READ_ERROR, _cairo_surface_nil_read_error);
|
||||
DEFINE_NIL_SURFACE(CAIRO_STATUS_WRITE_ERROR, _cairo_surface_nil_write_error);
|
||||
|
||||
static void
|
||||
_cairo_surface_copy_pattern_for_destination (const cairo_pattern_t *pattern,
|
||||
|
@ -203,10 +141,12 @@ slim_hidden_def (cairo_surface_get_type);
|
|||
* cairo_surface_get_content:
|
||||
* @surface: a #cairo_surface_t
|
||||
*
|
||||
* Return value: The content type of @surface which indicates whether
|
||||
* the surface contains color and/or alpha information. See
|
||||
* This function returns the content type of @surface which indicates
|
||||
* whether the surface contains color and/or alpha information. See
|
||||
* #cairo_content_t.
|
||||
*
|
||||
* Return value: The content type of @surface.
|
||||
*
|
||||
* Since: 1.2
|
||||
**/
|
||||
cairo_content_t
|
||||
|
@ -281,12 +221,23 @@ _cairo_surface_create_similar_scratch (cairo_surface_t *other,
|
|||
if (other->status)
|
||||
return (cairo_surface_t*) &_cairo_surface_nil;
|
||||
|
||||
if (other->backend->create_similar)
|
||||
if (other->backend->create_similar) {
|
||||
surface = other->backend->create_similar (other, content, width, height);
|
||||
/* It's not an error if the backend didn't create a valid
|
||||
* surface---it may just not be supported. */
|
||||
if (surface && surface->status) {
|
||||
cairo_surface_destroy (surface);
|
||||
surface = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
if (!surface)
|
||||
if (surface == NULL)
|
||||
surface = cairo_image_surface_create (format, width, height);
|
||||
|
||||
/* If any error occurred, then return the nil surface we received. */
|
||||
if (surface->status)
|
||||
return surface;
|
||||
|
||||
cairo_surface_get_font_options (other, &options);
|
||||
_cairo_surface_set_font_options (surface, &options);
|
||||
|
||||
|
@ -402,15 +353,15 @@ _cairo_surface_get_clip_mode (cairo_surface_t *surface)
|
|||
* @surface from being destroyed until a matching call to
|
||||
* cairo_surface_destroy() is made.
|
||||
*
|
||||
* The number of references to a #cairo_surface_t can be get using
|
||||
* cairo_surface_get_reference_count().
|
||||
*
|
||||
* Return value: the referenced #cairo_surface_t.
|
||||
**/
|
||||
cairo_surface_t *
|
||||
cairo_surface_reference (cairo_surface_t *surface)
|
||||
{
|
||||
if (surface == NULL)
|
||||
return NULL;
|
||||
|
||||
if (surface->ref_count == CAIRO_REF_COUNT_INVALID)
|
||||
if (surface == NULL || surface->ref_count == CAIRO_REF_COUNT_INVALID)
|
||||
return surface;
|
||||
|
||||
assert (surface->ref_count > 0);
|
||||
|
@ -432,10 +383,7 @@ slim_hidden_def (cairo_surface_reference);
|
|||
void
|
||||
cairo_surface_destroy (cairo_surface_t *surface)
|
||||
{
|
||||
if (surface == NULL)
|
||||
return;
|
||||
|
||||
if (surface->ref_count == CAIRO_REF_COUNT_INVALID)
|
||||
if (surface == NULL || surface->ref_count == CAIRO_REF_COUNT_INVALID)
|
||||
return;
|
||||
|
||||
assert (surface->ref_count > 0);
|
||||
|
@ -444,6 +392,7 @@ cairo_surface_destroy (cairo_surface_t *surface)
|
|||
if (surface->ref_count)
|
||||
return;
|
||||
|
||||
if (! surface->finished)
|
||||
cairo_surface_finish (surface);
|
||||
|
||||
_cairo_user_data_array_fini (&surface->user_data);
|
||||
|
@ -452,6 +401,26 @@ cairo_surface_destroy (cairo_surface_t *surface)
|
|||
}
|
||||
slim_hidden_def(cairo_surface_destroy);
|
||||
|
||||
/**
|
||||
* cairo_surface_get_reference_count:
|
||||
* @surface: a #cairo_surface_t
|
||||
*
|
||||
* Returns the current reference count of @surface.
|
||||
*
|
||||
* Return value: the current reference count of @surface. If the
|
||||
* object is a nil object, 0 will be returned.
|
||||
*
|
||||
* Since: 1.4
|
||||
**/
|
||||
unsigned int
|
||||
cairo_surface_get_reference_count (cairo_surface_t *surface)
|
||||
{
|
||||
if (surface == NULL || surface->ref_count == CAIRO_REF_COUNT_INVALID)
|
||||
return 0;
|
||||
|
||||
return surface->ref_count;
|
||||
}
|
||||
|
||||
/**
|
||||
* cairo_surface_finish:
|
||||
* @surface: the #cairo_surface_t to finish
|
||||
|
@ -475,6 +444,12 @@ cairo_surface_finish (cairo_surface_t *surface)
|
|||
{
|
||||
cairo_status_t status;
|
||||
|
||||
if (surface == NULL)
|
||||
return;
|
||||
|
||||
if (surface->ref_count == CAIRO_REF_COUNT_INVALID)
|
||||
return;
|
||||
|
||||
if (surface->finished) {
|
||||
_cairo_surface_set_error (surface, CAIRO_STATUS_SURFACE_FINISHED);
|
||||
return;
|
||||
|
@ -815,7 +790,9 @@ cairo_surface_get_device_offset (cairo_surface_t *surface,
|
|||
double *x_offset,
|
||||
double *y_offset)
|
||||
{
|
||||
if (x_offset)
|
||||
*x_offset = surface->device_transform.x0;
|
||||
if (y_offset)
|
||||
*y_offset = surface->device_transform.y0;
|
||||
}
|
||||
slim_hidden_def (cairo_surface_get_device_offset);
|
||||
|
@ -1024,7 +1001,7 @@ _cairo_surface_clone_similar (cairo_surface_t *surface,
|
|||
|
||||
status = surface->backend->clone_similar (surface, src, src_x, src_y,
|
||||
width, height, clone_out);
|
||||
if (status == CAIRO_STATUS_SUCCESS)
|
||||
if (status == CAIRO_STATUS_SUCCESS && *clone_out != src)
|
||||
(*clone_out)->device_transform = src->device_transform;
|
||||
|
||||
if (status != CAIRO_INT_STATUS_UNSUPPORTED)
|
||||
|
@ -1036,8 +1013,10 @@ _cairo_surface_clone_similar (cairo_surface_t *surface,
|
|||
|
||||
status = surface->backend->clone_similar (surface, &image->base, src_x,
|
||||
src_y, width, height, clone_out);
|
||||
if (status == CAIRO_STATUS_SUCCESS)
|
||||
if (status == CAIRO_STATUS_SUCCESS && *clone_out != src) {
|
||||
(*clone_out)->device_transform = src->device_transform;
|
||||
(*clone_out)->device_transform_inverse = src->device_transform_inverse;
|
||||
}
|
||||
|
||||
/* If the above failed point, we could implement a full fallback
|
||||
* using acquire_dest_image, but that's going to be very
|
||||
|
@ -1276,12 +1255,6 @@ _cairo_surface_paint (cairo_surface_t *surface,
|
|||
|
||||
assert (! surface->is_snapshot);
|
||||
|
||||
if (source->type == CAIRO_PATTERN_TYPE_SURFACE &&
|
||||
(source->extend == CAIRO_EXTEND_REFLECT || source->extend == CAIRO_EXTEND_PAD))
|
||||
{
|
||||
return CAIRO_STATUS_NO_MEMORY;
|
||||
}
|
||||
|
||||
_cairo_surface_copy_pattern_for_destination (source, surface, &dev_source.base);
|
||||
|
||||
if (surface->backend->paint) {
|
||||
|
@ -1310,12 +1283,6 @@ _cairo_surface_mask (cairo_surface_t *surface,
|
|||
|
||||
assert (! surface->is_snapshot);
|
||||
|
||||
if (source->type == CAIRO_PATTERN_TYPE_SURFACE &&
|
||||
(source->extend == CAIRO_EXTEND_REFLECT || source->extend == CAIRO_EXTEND_PAD))
|
||||
{
|
||||
return CAIRO_STATUS_NO_MEMORY;
|
||||
}
|
||||
|
||||
_cairo_surface_copy_pattern_for_destination (source, surface, &dev_source.base);
|
||||
_cairo_surface_copy_pattern_for_destination (mask, surface, &dev_mask.base);
|
||||
|
||||
|
@ -1354,12 +1321,6 @@ _cairo_surface_stroke (cairo_surface_t *surface,
|
|||
|
||||
assert (! surface->is_snapshot);
|
||||
|
||||
if (source->type == CAIRO_PATTERN_TYPE_SURFACE &&
|
||||
(source->extend == CAIRO_EXTEND_REFLECT || source->extend == CAIRO_EXTEND_PAD))
|
||||
{
|
||||
return CAIRO_STATUS_NO_MEMORY;
|
||||
}
|
||||
|
||||
_cairo_surface_copy_pattern_for_destination (source, surface, &dev_source.base);
|
||||
|
||||
if (surface->backend->stroke) {
|
||||
|
@ -1399,12 +1360,6 @@ _cairo_surface_fill (cairo_surface_t *surface,
|
|||
|
||||
assert (! surface->is_snapshot);
|
||||
|
||||
if (source->type == CAIRO_PATTERN_TYPE_SURFACE &&
|
||||
(source->extend == CAIRO_EXTEND_REFLECT || source->extend == CAIRO_EXTEND_PAD))
|
||||
{
|
||||
return CAIRO_STATUS_NO_MEMORY;
|
||||
}
|
||||
|
||||
_cairo_surface_copy_pattern_for_destination (source, surface, &dev_source.base);
|
||||
|
||||
if (surface->backend->fill) {
|
||||
|
@ -1806,12 +1761,6 @@ _cairo_surface_show_glyphs (cairo_surface_t *surface,
|
|||
|
||||
assert (! surface->is_snapshot);
|
||||
|
||||
if (source->type == CAIRO_PATTERN_TYPE_SURFACE &&
|
||||
(source->extend == CAIRO_EXTEND_REFLECT || source->extend == CAIRO_EXTEND_PAD))
|
||||
{
|
||||
return CAIRO_STATUS_NO_MEMORY;
|
||||
}
|
||||
|
||||
if (!num_glyphs)
|
||||
return CAIRO_STATUS_SUCCESS;
|
||||
|
||||
|
@ -1839,19 +1788,22 @@ _cairo_surface_show_glyphs (cairo_surface_t *surface,
|
|||
cairo_font_options_destroy (font_options);
|
||||
}
|
||||
|
||||
if (surface->backend->show_glyphs) {
|
||||
CAIRO_MUTEX_LOCK (dev_scaled_font->mutex);
|
||||
|
||||
status = CAIRO_INT_STATUS_UNSUPPORTED;
|
||||
|
||||
if (surface->backend->show_glyphs)
|
||||
status = surface->backend->show_glyphs (surface, op, &dev_source.base,
|
||||
glyphs, num_glyphs,
|
||||
dev_scaled_font);
|
||||
if (status != CAIRO_INT_STATUS_UNSUPPORTED)
|
||||
goto FINISH;
|
||||
}
|
||||
|
||||
if (status == CAIRO_INT_STATUS_UNSUPPORTED)
|
||||
status = _cairo_surface_fallback_show_glyphs (surface, op, &dev_source.base,
|
||||
glyphs, num_glyphs,
|
||||
dev_scaled_font);
|
||||
|
||||
FINISH:
|
||||
CAIRO_MUTEX_UNLOCK (dev_scaled_font->mutex);
|
||||
|
||||
if (dev_scaled_font != scaled_font)
|
||||
cairo_scaled_font_destroy (dev_scaled_font);
|
||||
|
||||
|
@ -2137,17 +2089,5 @@ _cairo_surface_copy_pattern_for_destination (const cairo_pattern_t *pattern,
|
|||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* cairo_surface_get_reference_count
|
||||
* @surface: the #cairo_surface_t to fetch the reference count for
|
||||
*
|
||||
* Returns the number of references to this surface that are held.
|
||||
*/
|
||||
unsigned int
|
||||
cairo_surface_get_reference_count (cairo_surface_t *surface)
|
||||
{
|
||||
return surface->ref_count;
|
||||
}
|
||||
|
||||
/* LocalWords: rasterized
|
||||
*/
|
||||
|
|
|
@ -240,7 +240,9 @@ cairo_svg_surface_create (const char *filename,
|
|||
status = _cairo_output_stream_get_status (stream);
|
||||
if (status) {
|
||||
_cairo_error (status);
|
||||
return (cairo_surface_t *) &_cairo_surface_nil;
|
||||
return (status == CAIRO_STATUS_WRITE_ERROR) ?
|
||||
(cairo_surface_t *) &_cairo_surface_nil_write_error :
|
||||
(cairo_surface_t *) &_cairo_surface_nil;
|
||||
}
|
||||
|
||||
return _cairo_svg_surface_create_for_stream_internal (stream, width, height, CAIRO_SVG_VERSION_1_1);
|
||||
|
@ -475,7 +477,7 @@ _cairo_svg_surface_show_page (void *abstract_surface)
|
|||
}
|
||||
|
||||
static void
|
||||
emit_transform (cairo_output_stream_t *output,
|
||||
_cairo_svg_surface_emit_transform (cairo_output_stream_t *output,
|
||||
char const *attribute_str,
|
||||
char const *trailer,
|
||||
cairo_matrix_t *matrix)
|
||||
|
@ -563,7 +565,7 @@ _cairo_svg_path_close_path (void *closure)
|
|||
}
|
||||
|
||||
static cairo_status_t
|
||||
emit_path (cairo_output_stream_t *output,
|
||||
_cairo_svg_surface_emit_path (cairo_output_stream_t *output,
|
||||
cairo_path_fixed_t *path,
|
||||
cairo_matrix_t *ctm_inverse)
|
||||
{
|
||||
|
@ -606,7 +608,7 @@ _cairo_svg_document_emit_outline_glyph_data (cairo_svg_document_t *document,
|
|||
_cairo_output_stream_printf (document->xml_node_glyphs,
|
||||
"<path style=\"stroke: none;\" ");
|
||||
|
||||
status = emit_path (document->xml_node_glyphs, scaled_glyph->path, NULL);
|
||||
status = _cairo_svg_surface_emit_path (document->xml_node_glyphs, scaled_glyph->path, NULL);
|
||||
|
||||
_cairo_output_stream_printf (document->xml_node_glyphs,
|
||||
"/>\n");
|
||||
|
@ -642,7 +644,7 @@ _cairo_svg_document_emit_bitmap_glyph_data (cairo_svg_document_t *document,
|
|||
}
|
||||
|
||||
_cairo_output_stream_printf (document->xml_node_glyphs, "<g");
|
||||
emit_transform (document->xml_node_glyphs, " transform", ">/n", &image->base.device_transform);
|
||||
_cairo_svg_surface_emit_transform (document->xml_node_glyphs, " transform", ">/n", &image->base.device_transform);
|
||||
|
||||
for (y = 0, row = image->data, rows = image->height; rows; row += image->stride, rows--, y++) {
|
||||
for (x = 0, byte = row, cols = (image->width + 7) / 8; cols; byte++, cols--) {
|
||||
|
@ -674,7 +676,7 @@ _cairo_svg_document_emit_glyph (cairo_svg_document_t *document,
|
|||
cairo_status_t status;
|
||||
|
||||
_cairo_output_stream_printf (document->xml_node_glyphs,
|
||||
"<symbol id=\"glyph%d-%d\">\n",
|
||||
"<symbol overflow=\"visible\" id=\"glyph%d-%d\">\n",
|
||||
font_id,
|
||||
subset_glyph_index);
|
||||
|
||||
|
@ -707,7 +709,7 @@ _cairo_svg_document_emit_font_subset (cairo_scaled_font_subset_t *font_subset,
|
|||
static void
|
||||
_cairo_svg_document_emit_font_subsets (cairo_svg_document_t *document)
|
||||
{
|
||||
_cairo_scaled_font_subsets_foreach (document->font_subsets,
|
||||
_cairo_scaled_font_subsets_foreach_scaled (document->font_subsets,
|
||||
_cairo_svg_document_emit_font_subset,
|
||||
document);
|
||||
_cairo_scaled_font_subsets_destroy (document->font_subsets);
|
||||
|
@ -735,7 +737,7 @@ _cairo_svg_test_force_fallbacks (void)
|
|||
}
|
||||
|
||||
static cairo_int_status_t
|
||||
_operation_supported (cairo_svg_surface_t *surface,
|
||||
__cairo_svg_surface_operation_supported (cairo_svg_surface_t *surface,
|
||||
cairo_operator_t op,
|
||||
const cairo_pattern_t *pattern)
|
||||
{
|
||||
|
@ -752,11 +754,11 @@ _operation_supported (cairo_svg_surface_t *surface,
|
|||
}
|
||||
|
||||
static cairo_int_status_t
|
||||
_analyze_operation (cairo_svg_surface_t *surface,
|
||||
_cairo_svg_surface_analyze_operation (cairo_svg_surface_t *surface,
|
||||
cairo_operator_t op,
|
||||
const cairo_pattern_t *pattern)
|
||||
{
|
||||
if (_operation_supported (surface, op, pattern))
|
||||
if (__cairo_svg_surface_operation_supported (surface, op, pattern))
|
||||
return CAIRO_STATUS_SUCCESS;
|
||||
else
|
||||
return CAIRO_INT_STATUS_UNSUPPORTED;
|
||||
|
@ -799,7 +801,7 @@ _cairo_svg_surface_finish (void *abstract_surface)
|
|||
}
|
||||
|
||||
static void
|
||||
emit_alpha_filter (cairo_svg_document_t *document)
|
||||
_cairo_svg_surface_emit_alpha_filter (cairo_svg_document_t *document)
|
||||
{
|
||||
if (document->alpha_filter)
|
||||
return;
|
||||
|
@ -914,19 +916,27 @@ _cairo_surface_base64_encode (cairo_surface_t *surface,
|
|||
}
|
||||
|
||||
static cairo_status_t
|
||||
emit_composite_image_pattern (cairo_output_stream_t *output,
|
||||
_cairo_svg_surface_emit_composite_image_pattern (cairo_output_stream_t *output,
|
||||
cairo_svg_surface_t *svg_surface,
|
||||
cairo_surface_pattern_t *pattern,
|
||||
int pattern_id,
|
||||
const char *extra_attributes)
|
||||
{
|
||||
cairo_image_surface_t *image;
|
||||
cairo_surface_t *surface;
|
||||
cairo_surface_attributes_t surface_attr;
|
||||
cairo_rectangle_int16_t extents;
|
||||
cairo_status_t status;
|
||||
cairo_matrix_t p2u;
|
||||
void *image_extra;
|
||||
|
||||
status = _cairo_surface_acquire_source_image (pattern->surface,
|
||||
&image, &image_extra);
|
||||
status = _cairo_pattern_acquire_surface ((cairo_pattern_t *)pattern,
|
||||
(cairo_surface_t *)svg_surface,
|
||||
0, 0, (unsigned int)-1, (unsigned int)-1,
|
||||
&surface, &surface_attr);
|
||||
if (status)
|
||||
return status;
|
||||
|
||||
status = _cairo_surface_get_extents (surface, &extents);
|
||||
|
||||
if (status)
|
||||
return status;
|
||||
|
||||
|
@ -939,36 +949,37 @@ emit_composite_image_pattern (cairo_output_stream_t *output,
|
|||
"patternUnits=\"userSpaceOnUse\" "
|
||||
"width=\"%d\" height=\"%d\"",
|
||||
pattern_id,
|
||||
image->width, image->height);
|
||||
emit_transform (output, " patternTransform", ">\n", &p2u);
|
||||
extents.width, extents.height);
|
||||
_cairo_svg_surface_emit_transform (output, " patternTransform", ">\n", &p2u);
|
||||
}
|
||||
|
||||
_cairo_output_stream_printf (output,
|
||||
" <image width=\"%d\" height=\"%d\"",
|
||||
image->width, image->height);
|
||||
extents.width, extents.height);
|
||||
|
||||
if (pattern_id == invalid_pattern_id)
|
||||
emit_transform (output, " transform", "", &p2u);
|
||||
_cairo_svg_surface_emit_transform (output, " transform", "", &p2u);
|
||||
|
||||
if (extra_attributes)
|
||||
_cairo_output_stream_printf (output, " %s", extra_attributes);
|
||||
|
||||
_cairo_output_stream_printf (output, " xlink:href=\"");
|
||||
|
||||
status = _cairo_surface_base64_encode (pattern->surface, output);
|
||||
status = _cairo_surface_base64_encode (surface, output);
|
||||
|
||||
_cairo_output_stream_printf (output, "\"/>\n");
|
||||
|
||||
if (pattern_id != invalid_pattern_id)
|
||||
_cairo_output_stream_printf (output, "</pattern>\n");
|
||||
|
||||
_cairo_surface_release_source_image (pattern->surface, image, image_extra);
|
||||
_cairo_pattern_release_surface ((cairo_pattern_t *)pattern,
|
||||
surface, &surface_attr);
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
static int
|
||||
emit_meta_surface (cairo_svg_document_t *document,
|
||||
_cairo_svg_surface_emit_meta_surface (cairo_svg_document_t *document,
|
||||
cairo_meta_surface_t *surface)
|
||||
{
|
||||
cairo_surface_t *paginated_surface;
|
||||
|
@ -1010,7 +1021,7 @@ emit_meta_surface (cairo_svg_document_t *document,
|
|||
_cairo_array_append (&document->meta_snapshots, &new_snapshot);
|
||||
|
||||
if (meta->content == CAIRO_CONTENT_ALPHA) {
|
||||
emit_alpha_filter (document);
|
||||
_cairo_svg_surface_emit_alpha_filter (document);
|
||||
_cairo_output_stream_printf (document->xml_node_defs,
|
||||
"<g id=\"surface%d\" "
|
||||
"clip-path=\"url(#clip%d)\" "
|
||||
|
@ -1055,7 +1066,7 @@ emit_meta_surface (cairo_svg_document_t *document,
|
|||
}
|
||||
|
||||
static cairo_status_t
|
||||
emit_composite_meta_pattern (cairo_output_stream_t *output,
|
||||
_cairo_svg_surface_emit_composite_meta_pattern (cairo_output_stream_t *output,
|
||||
cairo_svg_surface_t *surface,
|
||||
cairo_surface_pattern_t *pattern,
|
||||
int pattern_id,
|
||||
|
@ -1068,7 +1079,7 @@ emit_composite_meta_pattern (cairo_output_stream_t *output,
|
|||
|
||||
meta_surface = (cairo_meta_surface_t *) pattern->surface;
|
||||
|
||||
id = emit_meta_surface (document, meta_surface);
|
||||
id = _cairo_svg_surface_emit_meta_surface (document, meta_surface);
|
||||
|
||||
p2u = pattern->base.matrix;
|
||||
cairo_matrix_invert (&p2u);
|
||||
|
@ -1081,7 +1092,7 @@ emit_composite_meta_pattern (cairo_output_stream_t *output,
|
|||
pattern_id,
|
||||
meta_surface->width_pixels,
|
||||
meta_surface->height_pixels);
|
||||
emit_transform (output, " patternTransform", ">\n", &p2u);
|
||||
_cairo_svg_surface_emit_transform (output, " patternTransform", ">\n", &p2u);
|
||||
}
|
||||
|
||||
_cairo_output_stream_printf (output,
|
||||
|
@ -1089,7 +1100,7 @@ emit_composite_meta_pattern (cairo_output_stream_t *output,
|
|||
id);
|
||||
|
||||
if (pattern_id == invalid_pattern_id)
|
||||
emit_transform (output, " transform", "", &p2u);
|
||||
_cairo_svg_surface_emit_transform (output, " transform", "", &p2u);
|
||||
|
||||
if (extra_attributes)
|
||||
_cairo_output_stream_printf (output, " %s", extra_attributes);
|
||||
|
@ -1103,7 +1114,7 @@ emit_composite_meta_pattern (cairo_output_stream_t *output,
|
|||
}
|
||||
|
||||
static cairo_status_t
|
||||
emit_composite_pattern (cairo_output_stream_t *output,
|
||||
_cairo_svg_surface_emit_composite_pattern (cairo_output_stream_t *output,
|
||||
cairo_svg_surface_t *surface,
|
||||
cairo_surface_pattern_t *pattern,
|
||||
int pattern_id,
|
||||
|
@ -1111,16 +1122,16 @@ emit_composite_pattern (cairo_output_stream_t *output,
|
|||
{
|
||||
|
||||
if (_cairo_surface_is_meta (pattern->surface)) {
|
||||
return emit_composite_meta_pattern (output, surface, pattern,
|
||||
return _cairo_svg_surface_emit_composite_meta_pattern (output, surface, pattern,
|
||||
pattern_id, extra_attributes);
|
||||
}
|
||||
|
||||
return emit_composite_image_pattern (output, surface, pattern,
|
||||
return _cairo_svg_surface_emit_composite_image_pattern (output, surface, pattern,
|
||||
pattern_id, extra_attributes);
|
||||
}
|
||||
|
||||
static void
|
||||
emit_operator (cairo_output_stream_t *output,
|
||||
_cairo_svg_surface_emit_operator (cairo_output_stream_t *output,
|
||||
cairo_svg_surface_t *surface,
|
||||
cairo_operator_t op)
|
||||
{
|
||||
|
@ -1142,7 +1153,7 @@ emit_operator (cairo_output_stream_t *output,
|
|||
}
|
||||
|
||||
static void
|
||||
emit_solid_pattern (cairo_svg_surface_t *surface,
|
||||
_cairo_svg_surface_emit_solid_pattern (cairo_svg_surface_t *surface,
|
||||
cairo_solid_pattern_t *pattern,
|
||||
cairo_output_stream_t *style,
|
||||
cairo_bool_t is_stroke)
|
||||
|
@ -1158,7 +1169,7 @@ emit_solid_pattern (cairo_svg_surface_t *surface,
|
|||
}
|
||||
|
||||
static void
|
||||
emit_surface_pattern (cairo_svg_surface_t *surface,
|
||||
_cairo_svg_surface_emit_surface_pattern (cairo_svg_surface_t *surface,
|
||||
cairo_surface_pattern_t *pattern,
|
||||
cairo_output_stream_t *style,
|
||||
cairo_bool_t is_stroke)
|
||||
|
@ -1167,7 +1178,7 @@ emit_surface_pattern (cairo_svg_surface_t *surface,
|
|||
int pattern_id;
|
||||
|
||||
pattern_id = document->pattern_id++;
|
||||
emit_composite_pattern (document->xml_node_defs, surface, pattern,
|
||||
_cairo_svg_surface_emit_composite_pattern (document->xml_node_defs, surface, pattern,
|
||||
pattern_id, NULL);
|
||||
|
||||
_cairo_output_stream_printf (style,
|
||||
|
@ -1177,30 +1188,169 @@ emit_surface_pattern (cairo_svg_surface_t *surface,
|
|||
}
|
||||
|
||||
static void
|
||||
emit_pattern_stops (cairo_output_stream_t *output,
|
||||
_cairo_svg_surface_emit_pattern_stops (cairo_output_stream_t *output,
|
||||
cairo_gradient_pattern_t const *pattern,
|
||||
double start_offset)
|
||||
double start_offset,
|
||||
cairo_bool_t reverse_stops,
|
||||
cairo_bool_t emulate_reflect)
|
||||
{
|
||||
pixman_gradient_stop_t *stops;
|
||||
double offset;
|
||||
unsigned int n_stops;
|
||||
unsigned int i;
|
||||
|
||||
if (pattern->n_stops < 1)
|
||||
return;
|
||||
|
||||
if (pattern->n_stops == 1) {
|
||||
_cairo_output_stream_printf (output,
|
||||
"<stop offset=\"%f\" style=\""
|
||||
"stop-color: rgb(%f%%,%f%%,%f%%); "
|
||||
"stop-opacity: %f;\"/>\n",
|
||||
_cairo_fixed_to_double (pattern->stops[0].x),
|
||||
pattern->stops[0].color.red / 655.35,
|
||||
pattern->stops[0].color.green / 655.35,
|
||||
pattern->stops[0].color.blue / 655.35,
|
||||
pattern->stops[0].color.alpha / 65535.0);
|
||||
return;
|
||||
}
|
||||
|
||||
if (emulate_reflect || reverse_stops) {
|
||||
n_stops = emulate_reflect ? pattern->n_stops * 2 - 2: pattern->n_stops;
|
||||
stops = malloc (sizeof (pixman_gradient_stop_t) * n_stops);
|
||||
|
||||
for (i = 0; i < pattern->n_stops; i++) {
|
||||
if (reverse_stops) {
|
||||
stops[i] = pattern->stops[pattern->n_stops - i - 1];
|
||||
stops[i].x = _cairo_fixed_from_double (1.0 - _cairo_fixed_to_double (stops[i].x));
|
||||
} else
|
||||
stops[i] = pattern->stops[i];
|
||||
if (emulate_reflect) {
|
||||
stops[i].x /= 2;
|
||||
if (i > 0 && i < (pattern->n_stops - 1)) {
|
||||
if (reverse_stops) {
|
||||
stops[i + pattern->n_stops - 1] = pattern->stops[i];
|
||||
stops[i + pattern->n_stops - 1].x =
|
||||
_cairo_fixed_from_double (0.5 + 0.5
|
||||
* _cairo_fixed_to_double (stops[i + pattern->n_stops - 1].x));
|
||||
} else {
|
||||
stops[i + pattern->n_stops - 1] = pattern->stops[pattern->n_stops - i - 1];
|
||||
stops[i + pattern->n_stops - 1].x =
|
||||
_cairo_fixed_from_double (1 - 0.5
|
||||
* _cairo_fixed_to_double (stops [i + pattern->n_stops - 1].x));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
n_stops = pattern->n_stops;
|
||||
stops = pattern->stops;
|
||||
}
|
||||
|
||||
if (start_offset >= 0.0)
|
||||
for (i = 0; i < n_stops; i++) {
|
||||
offset = start_offset + (1 - start_offset ) *
|
||||
_cairo_fixed_to_double (pattern->stops[i].x);
|
||||
_cairo_fixed_to_double (stops[i].x);
|
||||
_cairo_output_stream_printf (output,
|
||||
"<stop offset=\"%f\" style=\""
|
||||
"stop-color: rgb(%f%%,%f%%,%f%%); "
|
||||
"stop-opacity: %f;\"/>\n",
|
||||
offset,
|
||||
pattern->stops[i].color.red / 655.35,
|
||||
pattern->stops[i].color.green / 655.35,
|
||||
pattern->stops[i].color.blue / 655.35,
|
||||
pattern->stops[i].color.alpha / 65535.0);
|
||||
stops[i].color.red / 655.35,
|
||||
stops[i].color.green / 655.35,
|
||||
stops[i].color.blue / 655.35,
|
||||
stops[i].color.alpha / 65535.0);
|
||||
}
|
||||
else {
|
||||
cairo_bool_t found = FALSE;
|
||||
unsigned int offset_index;
|
||||
pixman_color_t offset_color_start, offset_color_stop;
|
||||
|
||||
for (i = 0; i < n_stops; i++) {
|
||||
if (_cairo_fixed_to_double (stops[i].x) >= -start_offset) {
|
||||
if (i > 0) {
|
||||
if (stops[i].x != stops[i-1].x) {
|
||||
double x0, x1;
|
||||
pixman_color_t *color0, *color1;
|
||||
|
||||
x0 = _cairo_fixed_to_double (stops[i-1].x);
|
||||
x1 = _cairo_fixed_to_double (stops[i].x);
|
||||
color0 = &stops[i-1].color;
|
||||
color1 = &stops[i].color;
|
||||
offset_color_start.red = color0->red + (color1->red - color0->red)
|
||||
* (-start_offset - x0) / (x1 - x0);
|
||||
offset_color_start.green = color0->green + (color1->green - color0->green)
|
||||
* (-start_offset - x0) / (x1 - x0);
|
||||
offset_color_start.blue = color0->blue + (color1->blue - color0->blue)
|
||||
* (-start_offset - x0) / (x1 - x0);
|
||||
offset_color_start.alpha = color0->alpha + (color1->alpha - color0->alpha)
|
||||
* (-start_offset - x0) / (x1 - x0);
|
||||
offset_color_stop = offset_color_start;
|
||||
} else {
|
||||
offset_color_stop = stops[i-1].color;
|
||||
offset_color_start = stops[i].color;
|
||||
}
|
||||
} else
|
||||
offset_color_stop = offset_color_start = stops[i].color;
|
||||
offset_index = i;
|
||||
found = TRUE;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (!found) {
|
||||
offset_index = n_stops - 1;
|
||||
offset_color_stop = offset_color_start = stops[offset_index].color;
|
||||
}
|
||||
|
||||
_cairo_output_stream_printf (output,
|
||||
"<stop offset=\"0\" style=\""
|
||||
"stop-color: rgb(%f%%,%f%%,%f%%); "
|
||||
"stop-opacity: %f;\"/>\n",
|
||||
offset_color_start.red / 655.35,
|
||||
offset_color_start.green / 655.35,
|
||||
offset_color_start.blue / 655.35,
|
||||
offset_color_start.alpha / 65535.0);
|
||||
for (i = offset_index; i < n_stops; i++) {
|
||||
_cairo_output_stream_printf (output,
|
||||
"<stop offset=\"%f\" style=\""
|
||||
"stop-color: rgb(%f%%,%f%%,%f%%); "
|
||||
"stop-opacity: %f;\"/>\n",
|
||||
_cairo_fixed_to_double (stops[i].x) + start_offset,
|
||||
stops[i].color.red / 655.35,
|
||||
stops[i].color.green / 655.35,
|
||||
stops[i].color.blue / 655.35,
|
||||
stops[i].color.alpha / 65535.0);
|
||||
}
|
||||
for (i = 0; i < offset_index; i++) {
|
||||
_cairo_output_stream_printf (output,
|
||||
"<stop offset=\"%f\" style=\""
|
||||
"stop-color: rgb(%f%%,%f%%,%f%%); "
|
||||
"stop-opacity: %f;\"/>\n",
|
||||
1.0 + _cairo_fixed_to_double (stops[i].x) + start_offset,
|
||||
stops[i].color.red / 655.35,
|
||||
stops[i].color.green / 655.35,
|
||||
stops[i].color.blue / 655.35,
|
||||
stops[i].color.alpha / 65535.0);
|
||||
}
|
||||
|
||||
_cairo_output_stream_printf (output,
|
||||
"<stop offset=\"1\" style=\""
|
||||
"stop-color: rgb(%f%%,%f%%,%f%%); "
|
||||
"stop-opacity: %f;\"/>\n",
|
||||
offset_color_stop.red / 655.35,
|
||||
offset_color_stop.green / 655.35,
|
||||
offset_color_stop.blue / 655.35,
|
||||
offset_color_stop.alpha / 65535.0);
|
||||
|
||||
}
|
||||
|
||||
if (reverse_stops || emulate_reflect)
|
||||
free (stops);
|
||||
}
|
||||
|
||||
static void
|
||||
emit_pattern_extend (cairo_output_stream_t *output,
|
||||
_cairo_svg_surface_emit_pattern_extend (cairo_output_stream_t *output,
|
||||
cairo_pattern_t *pattern)
|
||||
{
|
||||
switch (pattern->extend) {
|
||||
|
@ -1211,15 +1361,13 @@ emit_pattern_extend (cairo_output_stream_t *output,
|
|||
_cairo_output_stream_printf (output, "spreadMethod=\"reflect\" ");
|
||||
break;
|
||||
case CAIRO_EXTEND_NONE:
|
||||
break;
|
||||
case CAIRO_EXTEND_PAD:
|
||||
/* FIXME not implemented */
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
emit_linear_pattern (cairo_svg_surface_t *surface,
|
||||
_cairo_svg_surface_emit_linear_pattern (cairo_svg_surface_t *surface,
|
||||
cairo_linear_pattern_t *pattern,
|
||||
cairo_output_stream_t *style,
|
||||
cairo_bool_t is_stroke)
|
||||
|
@ -1240,12 +1388,12 @@ emit_linear_pattern (cairo_svg_surface_t *surface,
|
|||
document->linear_pattern_id,
|
||||
x0, y0, x1, y1);
|
||||
|
||||
emit_pattern_extend (document->xml_node_defs, &pattern->base.base),
|
||||
_cairo_svg_surface_emit_pattern_extend (document->xml_node_defs, &pattern->base.base),
|
||||
p2u = pattern->base.base.matrix;
|
||||
cairo_matrix_invert (&p2u);
|
||||
emit_transform (document->xml_node_defs, "gradientTransform", ">\n", &p2u);
|
||||
_cairo_svg_surface_emit_transform (document->xml_node_defs, "gradientTransform", ">\n", &p2u);
|
||||
|
||||
emit_pattern_stops (document->xml_node_defs ,&pattern->base, 0.0);
|
||||
_cairo_svg_surface_emit_pattern_stops (document->xml_node_defs ,&pattern->base, 0.0, FALSE, FALSE);
|
||||
|
||||
_cairo_output_stream_printf (document->xml_node_defs,
|
||||
"</linearGradient>\n");
|
||||
|
@ -1259,31 +1407,122 @@ emit_linear_pattern (cairo_svg_surface_t *surface,
|
|||
}
|
||||
|
||||
static void
|
||||
emit_radial_pattern (cairo_svg_surface_t *surface,
|
||||
_cairo_svg_surface_emit_radial_pattern (cairo_svg_surface_t *surface,
|
||||
cairo_radial_pattern_t *pattern,
|
||||
cairo_output_stream_t *style,
|
||||
cairo_bool_t is_stroke)
|
||||
{
|
||||
cairo_svg_document_t *document = surface->document;
|
||||
cairo_matrix_t p2u;
|
||||
cairo_extend_t extend;
|
||||
double x0, y0, x1, y1, r0, r1;
|
||||
double fx, fy;
|
||||
cairo_bool_t reverse_stops;
|
||||
pixman_circle_t *c0, *c1;
|
||||
|
||||
x0 = _cairo_fixed_to_double (pattern->gradient.inner.x);
|
||||
y0 = _cairo_fixed_to_double (pattern->gradient.inner.y);
|
||||
r0 = _cairo_fixed_to_double (pattern->gradient.inner.radius);
|
||||
x1 = _cairo_fixed_to_double (pattern->gradient.outer.x);
|
||||
y1 = _cairo_fixed_to_double (pattern->gradient.outer.y);
|
||||
r1 = _cairo_fixed_to_double (pattern->gradient.outer.radius);
|
||||
extend = pattern->base.base.extend;
|
||||
|
||||
if (pattern->gradient.c1.radius < pattern->gradient.c2.radius) {
|
||||
c0 = &pattern->gradient.c1;
|
||||
c1 = &pattern->gradient.c2;
|
||||
reverse_stops = FALSE;
|
||||
} else {
|
||||
c0 = &pattern->gradient.c2;
|
||||
c1 = &pattern->gradient.c1;
|
||||
reverse_stops = TRUE;
|
||||
}
|
||||
|
||||
x0 = _cairo_fixed_to_double (c0->x);
|
||||
y0 = _cairo_fixed_to_double (c0->y);
|
||||
r0 = _cairo_fixed_to_double (c0->radius);
|
||||
x1 = _cairo_fixed_to_double (c1->x);
|
||||
y1 = _cairo_fixed_to_double (c1->y);
|
||||
r1 = _cairo_fixed_to_double (c1->radius);
|
||||
|
||||
p2u = pattern->base.base.matrix;
|
||||
cairo_matrix_invert (&p2u);
|
||||
|
||||
if (pattern->gradient.c1.radius == pattern->gradient.c2.radius) {
|
||||
_cairo_output_stream_printf (document->xml_node_defs,
|
||||
"<radialGradient id=\"radial%d\" "
|
||||
"gradientUnits=\"userSpaceOnUse\" "
|
||||
"cx=\"%f\" cy=\"%f\" "
|
||||
"fx=\"%f\" fy=\"%f\" r=\"%f\" ",
|
||||
document->radial_pattern_id,
|
||||
x1, y1,
|
||||
x1, y1, r1);
|
||||
|
||||
_cairo_svg_surface_emit_transform (document->xml_node_defs, "gradientTransform", ">\n", &p2u);
|
||||
|
||||
if (extend == CAIRO_EXTEND_NONE ||
|
||||
pattern->base.n_stops < 1)
|
||||
_cairo_output_stream_printf (document->xml_node_defs,
|
||||
"<stop offset=\"0\" style=\""
|
||||
"stop-color: rgb(0%%,0%%,0%%); "
|
||||
"stop-opacity: 0;\"/>\n");
|
||||
else {
|
||||
_cairo_output_stream_printf (document->xml_node_defs,
|
||||
"<stop offset=\"0\" style=\""
|
||||
"stop-color: rgb(%f%%,%f%%,%f%%); "
|
||||
"stop-opacity: %f;\"/>\n",
|
||||
pattern->base.stops[0].color.red / 655.35,
|
||||
pattern->base.stops[0].color.green / 655.35,
|
||||
pattern->base.stops[0].color.blue / 655.35,
|
||||
pattern->base.stops[0].color.alpha / 65535.0);
|
||||
if (pattern->base.n_stops > 1)
|
||||
_cairo_output_stream_printf (document->xml_node_defs,
|
||||
"<stop offset=\"0\" style=\""
|
||||
"stop-color: rgb(%f%%,%f%%,%f%%); "
|
||||
"stop-opacity: %f;\"/>\n",
|
||||
pattern->base.stops[1].color.red / 655.35,
|
||||
pattern->base.stops[1].color.green / 655.35,
|
||||
pattern->base.stops[1].color.blue / 655.35,
|
||||
pattern->base.stops[1].color.alpha / 65535.0);
|
||||
}
|
||||
|
||||
} else {
|
||||
double offset, r, x, y;
|
||||
cairo_bool_t emulate_reflect = FALSE;
|
||||
|
||||
/* SVG doesn't have a start radius, so computing now SVG focal coordinates
|
||||
* and emulating start radius by translating color stops.
|
||||
* FIXME: We also need to emulate cairo behaviour inside start circle when
|
||||
* extend != CAIRO_EXTEND_NONE.
|
||||
* FIXME: Handle radius1 <= radius0 */
|
||||
fx = (r1 * x0 - r0 * x1) / (r1 - r0);
|
||||
fy = (r1 * y0 - r0 * y1) / (r1 - r0);
|
||||
|
||||
/* SVG doesn't support the inner circle and use instead a gradient focal.
|
||||
* That means we need to emulate the cairo behaviour by processing the
|
||||
* cairo gradient stops.
|
||||
* The CAIRO_EXTENT_NONE and CAIRO_EXTENT_PAD modes are quite easy to handle,
|
||||
* it's just a matter of stop position translation and calculation of
|
||||
* the corresponding SVG radial gradient focal.
|
||||
* The CAIRO_EXTENT_REFLECT and CAIRO_EXTEND_REPEAT modes require to compute a new
|
||||
* radial gradient, with an new outer circle, equal to r1 - r0 in the CAIRO_EXTEND_REPEAT
|
||||
* case, and 2 * (r1 - r0) in the CAIRO_EXTENT_REFLECT case, and a new gradient stop
|
||||
* list that maps to the original cairo stop list.
|
||||
*/
|
||||
if ((extend == CAIRO_EXTEND_REFLECT
|
||||
|| extend == CAIRO_EXTEND_REPEAT)
|
||||
&& r0 > 0.0) {
|
||||
double r_org = r1;
|
||||
|
||||
if (extend == CAIRO_EXTEND_REFLECT) {
|
||||
r1 = 2 * r1 - r0;
|
||||
emulate_reflect = TRUE;
|
||||
}
|
||||
|
||||
offset = fmod (r1, r1 - r0) / (r1 - r0) - 1.0;
|
||||
r = r1 - r0;
|
||||
|
||||
/* New position of outer circle. */
|
||||
x = r * (x1 - fx) / r_org + fx;
|
||||
y = r * (y1 - fy) / r_org + fy;
|
||||
|
||||
x1 = x;
|
||||
y1 = y;
|
||||
r1 = r;
|
||||
r0 = 0.0;
|
||||
} else {
|
||||
offset = r0 / r1;
|
||||
}
|
||||
|
||||
_cairo_output_stream_printf (document->xml_node_defs,
|
||||
"<radialGradient id=\"radial%d\" "
|
||||
"gradientUnits=\"userSpaceOnUse\" "
|
||||
|
@ -1293,12 +1532,35 @@ emit_radial_pattern (cairo_svg_surface_t *surface,
|
|||
x1, y1,
|
||||
fx, fy, r1);
|
||||
|
||||
emit_pattern_extend (document->xml_node_defs, &pattern->base.base),
|
||||
p2u = pattern->base.base.matrix;
|
||||
cairo_matrix_invert (&p2u);
|
||||
emit_transform (document->xml_node_defs, "gradientTransform", ">\n", &p2u);
|
||||
if (emulate_reflect)
|
||||
_cairo_output_stream_printf (document->xml_node_defs, "spreadMethod=\"repeat\" ");
|
||||
else
|
||||
_cairo_svg_surface_emit_pattern_extend (document->xml_node_defs, &pattern->base.base);
|
||||
_cairo_svg_surface_emit_transform (document->xml_node_defs, "gradientTransform", ">\n", &p2u);
|
||||
|
||||
emit_pattern_stops (document->xml_node_defs, &pattern->base, r0 / r1);
|
||||
/* To support cairo's EXTEND_NONE, (for which SVG has no similar
|
||||
* notion), we add transparent color stops on either end of the
|
||||
* user-provided stops. */
|
||||
if (extend == CAIRO_EXTEND_NONE) {
|
||||
_cairo_output_stream_printf (document->xml_node_defs,
|
||||
"<stop offset=\"0\" style=\""
|
||||
"stop-color: rgb(0%%,0%%,0%%); "
|
||||
"stop-opacity: 0;\"/>\n");
|
||||
if (r0 != 0.0)
|
||||
_cairo_output_stream_printf (document->xml_node_defs,
|
||||
"<stop offset=\"%f\" style=\""
|
||||
"stop-color: rgb(0%%,0%%,0%%); "
|
||||
"stop-opacity: 0;\"/>\n",
|
||||
r0 / r1);
|
||||
}
|
||||
_cairo_svg_surface_emit_pattern_stops (document->xml_node_defs, &pattern->base, offset,
|
||||
reverse_stops, emulate_reflect);
|
||||
if (pattern->base.base.extend == CAIRO_EXTEND_NONE)
|
||||
_cairo_output_stream_printf (document->xml_node_defs,
|
||||
"<stop offset=\"1.0\" style=\""
|
||||
"stop-color: rgb(0%%,0%%,0%%); "
|
||||
"stop-opacity: 0;\"/>\n");
|
||||
}
|
||||
|
||||
_cairo_output_stream_printf (document->xml_node_defs,
|
||||
"</radialGradient>\n");
|
||||
|
@ -1312,24 +1574,24 @@ emit_radial_pattern (cairo_svg_surface_t *surface,
|
|||
}
|
||||
|
||||
static void
|
||||
emit_pattern (cairo_svg_surface_t *surface, cairo_pattern_t *pattern,
|
||||
_cairo_svg_surface_emit_pattern (cairo_svg_surface_t *surface, cairo_pattern_t *pattern,
|
||||
cairo_output_stream_t *output, cairo_bool_t is_stroke)
|
||||
{
|
||||
switch (pattern->type) {
|
||||
case CAIRO_PATTERN_TYPE_SOLID:
|
||||
emit_solid_pattern (surface, (cairo_solid_pattern_t *) pattern, output, is_stroke);
|
||||
_cairo_svg_surface_emit_solid_pattern (surface, (cairo_solid_pattern_t *) pattern, output, is_stroke);
|
||||
break;
|
||||
|
||||
case CAIRO_PATTERN_TYPE_SURFACE:
|
||||
emit_surface_pattern (surface, (cairo_surface_pattern_t *) pattern, output, is_stroke);
|
||||
_cairo_svg_surface_emit_surface_pattern (surface, (cairo_surface_pattern_t *) pattern, output, is_stroke);
|
||||
break;
|
||||
|
||||
case CAIRO_PATTERN_TYPE_LINEAR:
|
||||
emit_linear_pattern (surface, (cairo_linear_pattern_t *) pattern, output, is_stroke);
|
||||
_cairo_svg_surface_emit_linear_pattern (surface, (cairo_linear_pattern_t *) pattern, output, is_stroke);
|
||||
break;
|
||||
|
||||
case CAIRO_PATTERN_TYPE_RADIAL:
|
||||
emit_radial_pattern (surface, (cairo_radial_pattern_t *) pattern, output, is_stroke);
|
||||
_cairo_svg_surface_emit_radial_pattern (surface, (cairo_radial_pattern_t *) pattern, output, is_stroke);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
@ -1347,20 +1609,20 @@ _cairo_svg_surface_fill (void *abstract_surface,
|
|||
cairo_status_t status;
|
||||
|
||||
if (surface->paginated_mode == CAIRO_PAGINATED_MODE_ANALYZE)
|
||||
return _analyze_operation (surface, op, source);
|
||||
return _cairo_svg_surface_analyze_operation (surface, op, source);
|
||||
|
||||
assert (_operation_supported (surface, op, source));
|
||||
assert (__cairo_svg_surface_operation_supported (surface, op, source));
|
||||
|
||||
_cairo_output_stream_printf (surface->xml_node,
|
||||
"<path style=\"stroke: none; "
|
||||
"fill-rule: %s; ",
|
||||
fill_rule == CAIRO_FILL_RULE_EVEN_ODD ?
|
||||
"evenodd" : "nonzero");
|
||||
emit_operator (surface->xml_node, surface, op);
|
||||
emit_pattern (surface, source, surface->xml_node, FALSE);
|
||||
_cairo_svg_surface_emit_operator (surface->xml_node, surface, op);
|
||||
_cairo_svg_surface_emit_pattern (surface, source, surface->xml_node, FALSE);
|
||||
_cairo_output_stream_printf (surface->xml_node, "\" ");
|
||||
|
||||
status = emit_path (surface->xml_node, path, NULL);
|
||||
status = _cairo_svg_surface_emit_path (surface->xml_node, path, NULL);
|
||||
|
||||
_cairo_output_stream_printf (surface->xml_node, "/>\n");
|
||||
|
||||
|
@ -1387,7 +1649,7 @@ _cairo_svg_surface_get_extents (void *abstract_surface,
|
|||
}
|
||||
|
||||
static cairo_status_t
|
||||
emit_paint (cairo_output_stream_t *output,
|
||||
_cairo_svg_surface_emit_paint (cairo_output_stream_t *output,
|
||||
cairo_svg_surface_t *surface,
|
||||
cairo_operator_t op,
|
||||
cairo_pattern_t *source,
|
||||
|
@ -1395,7 +1657,7 @@ emit_paint (cairo_output_stream_t *output,
|
|||
{
|
||||
if (source->type == CAIRO_PATTERN_TYPE_SURFACE &&
|
||||
source->extend == CAIRO_EXTEND_NONE)
|
||||
return emit_composite_pattern (output,
|
||||
return _cairo_svg_surface_emit_composite_pattern (output,
|
||||
surface,
|
||||
(cairo_surface_pattern_t *) source,
|
||||
invalid_pattern_id,
|
||||
|
@ -1406,8 +1668,8 @@ emit_paint (cairo_output_stream_t *output,
|
|||
"width=\"%f\" height=\"%f\" "
|
||||
"style=\"",
|
||||
surface->width, surface->height);
|
||||
emit_operator (output, surface, op);
|
||||
emit_pattern (surface, source, output, FALSE);
|
||||
_cairo_svg_surface_emit_operator (output, surface, op);
|
||||
_cairo_svg_surface_emit_pattern (surface, source, output, FALSE);
|
||||
_cairo_output_stream_printf (output, " stroke: none;\"");
|
||||
|
||||
if (extra_attributes)
|
||||
|
@ -1427,7 +1689,7 @@ _cairo_svg_surface_paint (void *abstract_surface,
|
|||
cairo_svg_surface_t *surface = abstract_surface;
|
||||
|
||||
if (surface->paginated_mode == CAIRO_PAGINATED_MODE_ANALYZE)
|
||||
return _analyze_operation (surface, op, source);
|
||||
return _cairo_svg_surface_analyze_operation (surface, op, source);
|
||||
|
||||
/* XXX: It would be nice to be able to assert this condition
|
||||
* here. But, we actually allow one 'cheat' that is used when
|
||||
|
@ -1436,7 +1698,7 @@ _cairo_svg_surface_paint (void *abstract_surface,
|
|||
* possible only because there is nothing between the fallback
|
||||
* images and the paper, nor is anything painted above. */
|
||||
/*
|
||||
assert (_operation_supported (surface, op, source));
|
||||
assert (__cairo_svg_surface_operation_supported (surface, op, source));
|
||||
*/
|
||||
|
||||
/* Emulation of clear and source operators, when no clipping region
|
||||
|
@ -1467,7 +1729,7 @@ _cairo_svg_surface_paint (void *abstract_surface,
|
|||
}
|
||||
}
|
||||
|
||||
emit_paint (surface->xml_node, surface, op, source, NULL);
|
||||
_cairo_svg_surface_emit_paint (surface->xml_node, surface, op, source, NULL);
|
||||
|
||||
return CAIRO_STATUS_SUCCESS;
|
||||
}
|
||||
|
@ -1484,13 +1746,13 @@ _cairo_svg_surface_mask (void *abstract_surface,
|
|||
char buffer[64];
|
||||
|
||||
if (surface->paginated_mode == CAIRO_PAGINATED_MODE_ANALYZE)
|
||||
return _analyze_operation (surface, op, source);
|
||||
return _cairo_svg_surface_analyze_operation (surface, op, source);
|
||||
|
||||
assert (_operation_supported (surface, op, source));
|
||||
assert (__cairo_svg_surface_operation_supported (surface, op, source));
|
||||
|
||||
emit_alpha_filter (document);
|
||||
_cairo_svg_surface_emit_alpha_filter (document);
|
||||
|
||||
/* emit_paint() will output a pattern definition to
|
||||
/* _cairo_svg_surface_emit_paint() will output a pattern definition to
|
||||
* document->xml_node_defs so we need to write the mask element to
|
||||
* a temporary stream and then copy that to xml_node_defs. */
|
||||
mask_stream = _cairo_memory_stream_create ();
|
||||
|
@ -1498,7 +1760,7 @@ _cairo_svg_surface_mask (void *abstract_surface,
|
|||
"<mask id=\"mask%d\">\n"
|
||||
" <g filter=\"url(#alpha)\">\n",
|
||||
document->mask_id);
|
||||
emit_paint (mask_stream, surface, op, mask, NULL);
|
||||
_cairo_svg_surface_emit_paint (mask_stream, surface, op, mask, NULL);
|
||||
_cairo_output_stream_printf (mask_stream,
|
||||
" </g>\n"
|
||||
"</mask>\n");
|
||||
|
@ -1507,7 +1769,7 @@ _cairo_svg_surface_mask (void *abstract_surface,
|
|||
|
||||
snprintf (buffer, sizeof buffer, "mask=\"url(#mask%d);\"",
|
||||
document->mask_id);
|
||||
emit_paint (surface->xml_node, surface, op, source, buffer);
|
||||
_cairo_svg_surface_emit_paint (surface->xml_node, surface, op, source, buffer);
|
||||
|
||||
document->mask_id++;
|
||||
|
||||
|
@ -1531,9 +1793,9 @@ _cairo_svg_surface_stroke (void *abstract_dst,
|
|||
unsigned int i;
|
||||
|
||||
if (surface->paginated_mode == CAIRO_PAGINATED_MODE_ANALYZE)
|
||||
return _analyze_operation (surface, op, source);
|
||||
return _cairo_svg_surface_analyze_operation (surface, op, source);
|
||||
|
||||
assert (_operation_supported (surface, op, source));
|
||||
assert (__cairo_svg_surface_operation_supported (surface, op, source));
|
||||
|
||||
switch (stroke_style->line_cap) {
|
||||
case CAIRO_LINE_CAP_BUTT:
|
||||
|
@ -1572,8 +1834,8 @@ _cairo_svg_surface_stroke (void *abstract_dst,
|
|||
line_cap,
|
||||
line_join);
|
||||
|
||||
emit_pattern (surface, source, surface->xml_node, TRUE);
|
||||
emit_operator (surface->xml_node, surface, op);
|
||||
_cairo_svg_surface_emit_pattern (surface, source, surface->xml_node, TRUE);
|
||||
_cairo_svg_surface_emit_operator (surface->xml_node, surface, op);
|
||||
|
||||
if (stroke_style->num_dashes > 0) {
|
||||
_cairo_output_stream_printf (surface->xml_node, "stroke-dasharray: ");
|
||||
|
@ -1596,9 +1858,9 @@ _cairo_svg_surface_stroke (void *abstract_dst,
|
|||
"stroke-miterlimit: %f;\" ",
|
||||
stroke_style->miter_limit);
|
||||
|
||||
status = emit_path (surface->xml_node, path, ctm_inverse);
|
||||
status = _cairo_svg_surface_emit_path (surface->xml_node, path, ctm_inverse);
|
||||
|
||||
emit_transform (surface->xml_node, " transform", "/>\n", ctm);
|
||||
_cairo_svg_surface_emit_transform (surface->xml_node, " transform", "/>\n", ctm);
|
||||
|
||||
return status;
|
||||
}
|
||||
|
@ -1619,9 +1881,9 @@ _cairo_svg_surface_show_glyphs (void *abstract_surface,
|
|||
int i;
|
||||
|
||||
if (surface->paginated_mode == CAIRO_PAGINATED_MODE_ANALYZE)
|
||||
return _analyze_operation (surface, op, pattern);
|
||||
return _cairo_svg_surface_analyze_operation (surface, op, pattern);
|
||||
|
||||
assert (_operation_supported (surface, op, pattern));
|
||||
assert (__cairo_svg_surface_operation_supported (surface, op, pattern));
|
||||
|
||||
if (num_glyphs <= 0)
|
||||
return CAIRO_STATUS_SUCCESS;
|
||||
|
@ -1633,7 +1895,7 @@ _cairo_svg_surface_show_glyphs (void *abstract_surface,
|
|||
goto FALLBACK;
|
||||
|
||||
_cairo_output_stream_printf (surface->xml_node, "<g style=\"");
|
||||
emit_pattern (surface, pattern, surface->xml_node, FALSE);
|
||||
_cairo_svg_surface_emit_pattern (surface, pattern, surface->xml_node, FALSE);
|
||||
_cairo_output_stream_printf (surface->xml_node, "\">\n");
|
||||
|
||||
for (i = 0; i < num_glyphs; i++) {
|
||||
|
@ -1698,7 +1960,7 @@ _cairo_svg_surface_intersect_clip_path (void *dst,
|
|||
"<clipPath id=\"clip%d\">\n"
|
||||
" <path ",
|
||||
document->clip_id);
|
||||
status = emit_path (document->xml_node_defs, path, NULL);
|
||||
status = _cairo_svg_surface_emit_path (document->xml_node_defs, path, NULL);
|
||||
_cairo_output_stream_printf (document->xml_node_defs,
|
||||
"/>\n"
|
||||
"</clipPath>\n");
|
||||
|
@ -1772,7 +2034,7 @@ _cairo_svg_document_create (cairo_output_stream_t *output_stream,
|
|||
}
|
||||
|
||||
/* The use of defs for font glyphs imposes no per-subset limit. */
|
||||
document->font_subsets = _cairo_scaled_font_subsets_create (0);
|
||||
document->font_subsets = _cairo_scaled_font_subsets_create (0, INT_MAX);
|
||||
if (document->font_subsets == NULL) {
|
||||
_cairo_error (CAIRO_STATUS_NO_MEMORY);
|
||||
free (document);
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
/*
|
||||
* Copyright © 2002 Keith Packard
|
||||
* Copyright © 2007 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
|
||||
|
@ -40,7 +41,7 @@
|
|||
/* private functions */
|
||||
|
||||
static cairo_status_t
|
||||
_cairo_traps_grow_by (cairo_traps_t *traps, int additional);
|
||||
_cairo_traps_grow (cairo_traps_t *traps);
|
||||
|
||||
static cairo_status_t
|
||||
_cairo_traps_add_trap (cairo_traps_t *traps, cairo_fixed_t top, cairo_fixed_t bottom,
|
||||
|
@ -49,18 +50,6 @@ _cairo_traps_add_trap (cairo_traps_t *traps, cairo_fixed_t top, cairo_fixed_t bo
|
|||
static int
|
||||
_compare_point_fixed_by_y (const void *av, const void *bv);
|
||||
|
||||
static int
|
||||
_compare_cairo_edge_by_top (const void *av, const void *bv);
|
||||
|
||||
static int
|
||||
_compare_cairo_edge_by_slope (const void *av, const void *bv);
|
||||
|
||||
static cairo_fixed_16_16_t
|
||||
_compute_x (cairo_line_t *line, cairo_fixed_t y);
|
||||
|
||||
static int
|
||||
_line_segs_intersect_ceil (cairo_line_t *left, cairo_line_t *right, cairo_fixed_t *y_ret);
|
||||
|
||||
void
|
||||
_cairo_traps_init (cairo_traps_t *traps)
|
||||
{
|
||||
|
@ -70,20 +59,20 @@ _cairo_traps_init (cairo_traps_t *traps)
|
|||
|
||||
traps->traps_size = 0;
|
||||
traps->traps = NULL;
|
||||
traps->extents.p1.x = traps->extents.p1.y = INT16_MAX << 16;
|
||||
traps->extents.p2.x = traps->extents.p2.y = INT16_MIN << 16;
|
||||
traps->extents.p1.x = traps->extents.p1.y = INT32_MAX;
|
||||
traps->extents.p2.x = traps->extents.p2.y = INT32_MIN;
|
||||
}
|
||||
|
||||
void
|
||||
_cairo_traps_fini (cairo_traps_t *traps)
|
||||
{
|
||||
if (traps->traps_size) {
|
||||
if (traps->traps && traps->traps != traps->traps_embedded)
|
||||
free (traps->traps);
|
||||
|
||||
traps->traps = NULL;
|
||||
traps->traps_size = 0;
|
||||
traps->num_traps = 0;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* _cairo_traps_init_box:
|
||||
|
@ -100,7 +89,7 @@ _cairo_traps_init_box (cairo_traps_t *traps,
|
|||
{
|
||||
_cairo_traps_init (traps);
|
||||
|
||||
traps->status = _cairo_traps_grow_by (traps, 1);
|
||||
traps->status = _cairo_traps_grow (traps);
|
||||
if (traps->status)
|
||||
return traps->status;
|
||||
|
||||
|
@ -134,8 +123,7 @@ _cairo_traps_add_trap (cairo_traps_t *traps, cairo_fixed_t top, cairo_fixed_t bo
|
|||
}
|
||||
|
||||
if (traps->num_traps >= traps->traps_size) {
|
||||
int inc = traps->traps_size ? traps->traps_size : 32;
|
||||
traps->status = _cairo_traps_grow_by (traps, inc);
|
||||
traps->status = _cairo_traps_grow (traps);
|
||||
if (traps->status)
|
||||
return traps->status;
|
||||
}
|
||||
|
@ -193,29 +181,43 @@ _cairo_traps_add_trap_from_points (cairo_traps_t *traps, cairo_fixed_t top, cair
|
|||
return _cairo_traps_add_trap (traps, top, bottom, &left, &right);
|
||||
}
|
||||
|
||||
/* make room for at least one more trap */
|
||||
static cairo_status_t
|
||||
_cairo_traps_grow_by (cairo_traps_t *traps, int additional)
|
||||
_cairo_traps_grow (cairo_traps_t *traps)
|
||||
{
|
||||
cairo_trapezoid_t *new_traps;
|
||||
int old_size = traps->traps_size;
|
||||
int new_size = traps->num_traps + additional;
|
||||
int embedded_size = sizeof (traps->traps_embedded) / sizeof (traps->traps_embedded[0]);
|
||||
int new_size = 2 * MAX (old_size, 16);
|
||||
|
||||
/* we have a local buffer at traps->traps_embedded. try to fulfill the request
|
||||
* from there. */
|
||||
if (old_size < embedded_size) {
|
||||
traps->traps = traps->traps_embedded;
|
||||
traps->traps_size = embedded_size;
|
||||
return traps->status;
|
||||
}
|
||||
|
||||
assert (traps->num_traps <= traps->traps_size);
|
||||
|
||||
if (traps->status)
|
||||
return traps->status;
|
||||
|
||||
if (new_size <= traps->traps_size)
|
||||
return traps->status;
|
||||
|
||||
traps->traps_size = new_size;
|
||||
new_traps = realloc (traps->traps, traps->traps_size * sizeof (cairo_trapezoid_t));
|
||||
if (traps->traps == traps->traps_embedded) {
|
||||
new_traps = malloc (new_size * sizeof (cairo_trapezoid_t));
|
||||
if (new_traps)
|
||||
memcpy (new_traps, traps->traps, old_size * sizeof (cairo_trapezoid_t));
|
||||
} else {
|
||||
new_traps = realloc (traps->traps, new_size * sizeof (cairo_trapezoid_t));
|
||||
}
|
||||
|
||||
if (new_traps == NULL) {
|
||||
traps->traps_size = old_size;
|
||||
traps->status = CAIRO_STATUS_NO_MEMORY;
|
||||
return traps->status;
|
||||
}
|
||||
|
||||
traps->traps = new_traps;
|
||||
traps->traps_size = new_size;
|
||||
|
||||
return traps->status;
|
||||
}
|
||||
|
@ -309,57 +311,20 @@ _cairo_trapezoid_array_translate_and_scale (cairo_trapezoid_t *offset_traps,
|
|||
}
|
||||
}
|
||||
|
||||
/* A triangle is simply a degenerate case of a convex
|
||||
* quadrilateral. We would not benefit from having any distinct
|
||||
* implementation of triangle vs. quadrilateral tessellation here. */
|
||||
cairo_status_t
|
||||
_cairo_traps_tessellate_triangle (cairo_traps_t *traps, cairo_point_t t[3])
|
||||
{
|
||||
cairo_line_t line;
|
||||
cairo_fixed_16_16_t intersect;
|
||||
cairo_point_t tsort[3];
|
||||
cairo_point_t quad[4];
|
||||
|
||||
memcpy (tsort, t, 3 * sizeof (cairo_point_t));
|
||||
qsort (tsort, 3, sizeof (cairo_point_t), _compare_point_fixed_by_y);
|
||||
quad[0] = t[0];
|
||||
quad[1] = t[0];
|
||||
quad[2] = t[1];
|
||||
quad[3] = t[2];
|
||||
|
||||
/* horizontal top edge requires special handling */
|
||||
if (tsort[0].y == tsort[1].y) {
|
||||
if (tsort[0].x < tsort[1].x)
|
||||
_cairo_traps_add_trap_from_points (traps,
|
||||
tsort[1].y, tsort[2].y,
|
||||
tsort[0], tsort[2],
|
||||
tsort[1], tsort[2]);
|
||||
else
|
||||
_cairo_traps_add_trap_from_points (traps,
|
||||
tsort[1].y, tsort[2].y,
|
||||
tsort[1], tsort[2],
|
||||
tsort[0], tsort[2]);
|
||||
return traps->status;
|
||||
}
|
||||
|
||||
line.p1 = tsort[0];
|
||||
line.p2 = tsort[1];
|
||||
|
||||
intersect = _compute_x (&line, tsort[2].y);
|
||||
|
||||
if (intersect < tsort[2].x) {
|
||||
_cairo_traps_add_trap_from_points (traps,
|
||||
tsort[0].y, tsort[1].y,
|
||||
tsort[0], tsort[1],
|
||||
tsort[0], tsort[2]);
|
||||
_cairo_traps_add_trap_from_points (traps,
|
||||
tsort[1].y, tsort[2].y,
|
||||
tsort[1], tsort[2],
|
||||
tsort[0], tsort[2]);
|
||||
} else {
|
||||
_cairo_traps_add_trap_from_points (traps,
|
||||
tsort[0].y, tsort[1].y,
|
||||
tsort[0], tsort[2],
|
||||
tsort[0], tsort[1]);
|
||||
_cairo_traps_add_trap_from_points (traps,
|
||||
tsort[1].y, tsort[2].y,
|
||||
tsort[0], tsort[2],
|
||||
tsort[1], tsort[2]);
|
||||
}
|
||||
|
||||
return traps->status;
|
||||
return _cairo_traps_tessellate_convex_quad (traps, quad);
|
||||
}
|
||||
|
||||
cairo_status_t
|
||||
|
@ -367,6 +332,8 @@ _cairo_traps_tessellate_convex_quad (cairo_traps_t *traps, cairo_point_t q[4])
|
|||
{
|
||||
int a, b, c, d;
|
||||
int i;
|
||||
cairo_slope_t ab, ad;
|
||||
cairo_bool_t b_left_of_d;
|
||||
|
||||
/* Choose a as a point with minimal y */
|
||||
a = 0;
|
||||
|
@ -386,24 +353,50 @@ _cairo_traps_tessellate_convex_quad (cairo_traps_t *traps, cairo_point_t q[4])
|
|||
}
|
||||
|
||||
/* Without freedom left to choose anything else, we have four
|
||||
* cases to tessellate which we can distinguish by comparing c.y
|
||||
* to d.y and then by comparing b.x to d.x. And then for any of
|
||||
* these cases there is a trivial way to emit three
|
||||
* trapezoids. The 4 cases and their trapezoids are described and
|
||||
* implemented below:
|
||||
*/
|
||||
if (q[c].y < q[d].y) {
|
||||
if (q[b].x < q[d].x) {
|
||||
/* c.y < d.y && b.x < d.x
|
||||
* cases to tessellate.
|
||||
*
|
||||
* First, we have to determine the Y-axis sort of the four
|
||||
* vertices, (either abcd or abdc). After that we need to detemine
|
||||
* which edges will be "left" and which will be "right" in the
|
||||
* resulting trapezoids. This can be determined by computing a
|
||||
* slope comparison of ab and ad to determine if b is left of d or
|
||||
* not.
|
||||
*
|
||||
* Note that "left of" here is in the sense of which edges should
|
||||
* be the left vs. right edges of the trapezoid. In particular, b
|
||||
* left of d does *not* mean that b.x is less than d.x.
|
||||
*
|
||||
* This should hopefully be made clear in the lame ASCII art
|
||||
* below. Since the same slope comparison is used in all cases, we
|
||||
* compute it before testing for the Y-value sort. */
|
||||
|
||||
/* Note: If a == b then the ab slope doesn't give us any
|
||||
* information. In that case, we can replace it with the ac (or
|
||||
* equivalenly the bc) slope which gives us exactly the same
|
||||
* information we need. At worst the names of the identifiers ab
|
||||
* and b_left_of_d are inaccurate in this case, (would be ac, and
|
||||
* c_left_of_d). */
|
||||
if (q[a].x == q[b].x && q[a].y == q[b].y)
|
||||
_cairo_slope_init (&ab, &q[a], &q[c]);
|
||||
else
|
||||
_cairo_slope_init (&ab, &q[a], &q[b]);
|
||||
|
||||
_cairo_slope_init (&ad, &q[a], &q[d]);
|
||||
|
||||
b_left_of_d = (_cairo_slope_compare (&ab, &ad) > 0);
|
||||
|
||||
if (q[c].y <= q[d].y) {
|
||||
if (b_left_of_d) {
|
||||
/* Y-sort is abcd and b is left of d, (slope(ab) > slope (ad))
|
||||
*
|
||||
* top bot left right
|
||||
* a
|
||||
* / | a.y b.y ab ad
|
||||
* b |
|
||||
* | | b.y c.y bc ad
|
||||
* c |
|
||||
* \ | c.y d.y cd ad
|
||||
* d
|
||||
* _a a a
|
||||
* / / /| |\ a.y b.y ab ad
|
||||
* b / b | b \
|
||||
* / / | | \ \ b.y c.y bc ad
|
||||
* c / c | c \
|
||||
* | / \| \ \ c.y d.y cd ad
|
||||
* d d d
|
||||
*/
|
||||
_cairo_traps_add_trap_from_points (traps,
|
||||
q[a].y, q[b].y,
|
||||
|
@ -415,15 +408,15 @@ _cairo_traps_tessellate_convex_quad (cairo_traps_t *traps, cairo_point_t q[4])
|
|||
q[c].y, q[d].y,
|
||||
q[c], q[d], q[a], q[d]);
|
||||
} else {
|
||||
/* c.y < d.y && b.x >= d.x
|
||||
/* Y-sort is abcd and b is right of d, (slope(ab) <= slope (ad))
|
||||
*
|
||||
* a
|
||||
* | \ a.y b.y ad ab
|
||||
* | b
|
||||
* | | b.y c.y ad bc
|
||||
* | c
|
||||
* | / c.y d.y ad cd
|
||||
* d
|
||||
* a a a_
|
||||
* /| |\ \ \ a.y b.y ad ab
|
||||
* / b | b \ b
|
||||
* / / | | \ \ b.y c.y ad bc
|
||||
* / c | c \ c
|
||||
* / / |/ \ | c.y d.y ad cd
|
||||
* d d d
|
||||
*/
|
||||
_cairo_traps_add_trap_from_points (traps,
|
||||
q[a].y, q[b].y,
|
||||
|
@ -436,16 +429,16 @@ _cairo_traps_tessellate_convex_quad (cairo_traps_t *traps, cairo_point_t q[4])
|
|||
q[a], q[d], q[c], q[d]);
|
||||
}
|
||||
} else {
|
||||
if (q[b].x < q[d].x) {
|
||||
/* c.y >= d.y && b.x < d.x
|
||||
if (b_left_of_d) {
|
||||
/* Y-sort is abdc and b is left of d, (slope (ab) > slope (ad))
|
||||
*
|
||||
* a
|
||||
* / \ a.y b.y ab ad
|
||||
* b \
|
||||
* \ \ b.y d.y bc ad
|
||||
* \ d
|
||||
* \ / d.y c.y bc dc
|
||||
* c
|
||||
* a a a
|
||||
* // / \ |\ a.y b.y ab ad
|
||||
* /b/ b \ b \
|
||||
* / / \ \ \ \ b.y d.y bc ad
|
||||
* /d/ \ d \ d
|
||||
* // \ / \| d.y c.y bc dc
|
||||
* c c c
|
||||
*/
|
||||
_cairo_traps_add_trap_from_points (traps,
|
||||
q[a].y, q[b].y,
|
||||
|
@ -457,15 +450,15 @@ _cairo_traps_tessellate_convex_quad (cairo_traps_t *traps, cairo_point_t q[4])
|
|||
q[d].y, q[c].y,
|
||||
q[b], q[c], q[d], q[c]);
|
||||
} else {
|
||||
/* c.y >= d.y && b.x >= d.x
|
||||
/* Y-sort is abdc and b is right of d, (slope (ab) <= slope (ad))
|
||||
*
|
||||
* a
|
||||
* / \ a.y b.y ad ab
|
||||
* / b
|
||||
* / / b.y d.y ad bc
|
||||
* d /
|
||||
* \ / d.y c.y dc bc
|
||||
* c
|
||||
* a a a
|
||||
* /| / \ \\ a.y b.y ad ab
|
||||
* / b / b \b\
|
||||
* / / / / \ \ b.y d.y ad bc
|
||||
* d / d / \d\
|
||||
* |/ \ / \\ d.y c.y dc bc
|
||||
* c c c
|
||||
*/
|
||||
_cairo_traps_add_trap_from_points (traps,
|
||||
q[a].y, q[b].y,
|
||||
|
@ -482,400 +475,6 @@ _cairo_traps_tessellate_convex_quad (cairo_traps_t *traps, cairo_point_t q[4])
|
|||
return traps->status;
|
||||
}
|
||||
|
||||
static int
|
||||
_compare_cairo_edge_by_top (const void *av, const void *bv)
|
||||
{
|
||||
const cairo_edge_t *a = av, *b = bv;
|
||||
|
||||
return a->edge.p1.y - b->edge.p1.y;
|
||||
}
|
||||
|
||||
/* Return value is:
|
||||
> 0 if a is "clockwise" from b, (in a mathematical, not a graphical sense)
|
||||
== 0 if slope (a) == slope (b)
|
||||
< 0 if a is "counter-clockwise" from b
|
||||
*/
|
||||
static int
|
||||
_compare_cairo_edge_by_slope (const void *av, const void *bv)
|
||||
{
|
||||
const cairo_edge_t *a = av, *b = bv;
|
||||
cairo_fixed_32_32_t d;
|
||||
|
||||
cairo_fixed_48_16_t a_dx = a->edge.p2.x - a->edge.p1.x;
|
||||
cairo_fixed_48_16_t a_dy = a->edge.p2.y - a->edge.p1.y;
|
||||
cairo_fixed_48_16_t b_dx = b->edge.p2.x - b->edge.p1.x;
|
||||
cairo_fixed_48_16_t b_dy = b->edge.p2.y - b->edge.p1.y;
|
||||
|
||||
d = b_dy * a_dx - a_dy * b_dx;
|
||||
|
||||
if (d > 0)
|
||||
return 1;
|
||||
else if (d == 0)
|
||||
return 0;
|
||||
else
|
||||
return -1;
|
||||
}
|
||||
|
||||
static int
|
||||
_compare_cairo_edge_by_current_x_slope (const void *av, const void *bv)
|
||||
{
|
||||
const cairo_edge_t *a = av, *b = bv;
|
||||
int ret;
|
||||
|
||||
ret = a->current_x - b->current_x;
|
||||
if (ret == 0)
|
||||
ret = _compare_cairo_edge_by_slope (a, b);
|
||||
return ret;
|
||||
}
|
||||
|
||||
/* XXX: Both _compute_x and _compute_inverse_slope will divide by zero
|
||||
for horizontal lines. Now, we "know" that when we are tessellating
|
||||
polygons that the polygon data structure discards all horizontal
|
||||
edges, but there's nothing here to guarantee that. I suggest the
|
||||
following:
|
||||
|
||||
A) Move all of the polygon tessellation code out of xrtraps.c and
|
||||
into xrpoly.c, (in order to be in the same module as the code
|
||||
discarding horizontal lines).
|
||||
|
||||
OR
|
||||
|
||||
B) Re-implement the line intersection in a way that avoids all
|
||||
division by zero. Here's one approach. The only disadvantage
|
||||
might be that that there are not meaningful names for all of the
|
||||
sub-computations -- just a bunch of determinants. I haven't
|
||||
looked at complexity, (both are probably similar and it probably
|
||||
doesn't matter much anyway).
|
||||
*/
|
||||
|
||||
/* XXX: Keith's new intersection code is much cleaner, and uses
|
||||
* sufficient precision for correctly sorting intersections according
|
||||
* to the analysis in Hobby's paper.
|
||||
*
|
||||
* But, when we enable this code, some things are failing, (eg. the
|
||||
* stars in test/fill_rule get filled wrong). This could indicate a
|
||||
* bug in one of tree places:
|
||||
*
|
||||
* 1) The new intersection code in this file
|
||||
*
|
||||
* 2) cairo_wideint.c (which is only exercised here)
|
||||
*
|
||||
* 3) In the current tessellator, (where the old intersection
|
||||
* code, with its mystic increments could be masking the bug).
|
||||
*
|
||||
* It will likely be easier to revisit this when the new tessellation
|
||||
* code is in place. So, for now, we'll simply disable the new
|
||||
* intersection code.
|
||||
*/
|
||||
|
||||
#define CAIRO_TRAPS_USE_NEW_INTERSECTION_CODE 0
|
||||
|
||||
#if CAIRO_TRAPS_USE_NEW_INTERSECTION_CODE
|
||||
static const cairo_fixed_32_32_t
|
||||
_det16_32 (cairo_fixed_16_16_t a,
|
||||
cairo_fixed_16_16_t b,
|
||||
cairo_fixed_16_16_t c,
|
||||
cairo_fixed_16_16_t d)
|
||||
{
|
||||
return _cairo_int64_sub (_cairo_int32x32_64_mul (a, d),
|
||||
_cairo_int32x32_64_mul (b, c));
|
||||
}
|
||||
|
||||
static const cairo_fixed_64_64_t
|
||||
_det32_64 (cairo_fixed_32_32_t a,
|
||||
cairo_fixed_32_32_t b,
|
||||
cairo_fixed_32_32_t c,
|
||||
cairo_fixed_32_32_t d)
|
||||
{
|
||||
return _cairo_int128_sub (_cairo_int64x64_128_mul (a, d),
|
||||
_cairo_int64x64_128_mul (b, c));
|
||||
}
|
||||
|
||||
static const cairo_fixed_32_32_t
|
||||
_fixed_16_16_to_fixed_32_32 (cairo_fixed_16_16_t a)
|
||||
{
|
||||
return _cairo_int64_lsl (_cairo_int32_to_int64 (a), 16);
|
||||
}
|
||||
|
||||
static int
|
||||
_line_segs_intersect_ceil (cairo_line_t *l1, cairo_line_t *l2, cairo_fixed_t *y_intersection)
|
||||
{
|
||||
cairo_fixed_16_16_t dx1, dx2, dy1, dy2;
|
||||
cairo_fixed_32_32_t den_det;
|
||||
cairo_fixed_32_32_t l1_det, l2_det;
|
||||
cairo_fixed_64_64_t num_det;
|
||||
cairo_fixed_32_32_t intersect_32_32;
|
||||
cairo_fixed_48_16_t intersect_48_16;
|
||||
cairo_fixed_16_16_t intersect_16_16;
|
||||
cairo_quorem128_t qr;
|
||||
|
||||
dx1 = l1->p1.x - l1->p2.x;
|
||||
dy1 = l1->p1.y - l1->p2.y;
|
||||
dx2 = l2->p1.x - l2->p2.x;
|
||||
dy2 = l2->p1.y - l2->p2.y;
|
||||
den_det = _det16_32 (dx1, dy1,
|
||||
dx2, dy2);
|
||||
|
||||
if (_cairo_int64_eq (den_det, _cairo_int32_to_int64(0)))
|
||||
return 0;
|
||||
|
||||
l1_det = _det16_32 (l1->p1.x, l1->p1.y,
|
||||
l1->p2.x, l1->p2.y);
|
||||
l2_det = _det16_32 (l2->p1.x, l2->p1.y,
|
||||
l2->p2.x, l2->p2.y);
|
||||
|
||||
num_det = _det32_64 (l1_det, _fixed_16_16_to_fixed_32_32 (dy1),
|
||||
l2_det, _fixed_16_16_to_fixed_32_32 (dy2));
|
||||
|
||||
/*
|
||||
* Ok, this one is a bit tricky in fixed point, the denominator
|
||||
* needs to be left with 32-bits of fraction so that the
|
||||
* result of the divide ends up with 32-bits of fraction (64 - 32 = 32)
|
||||
*/
|
||||
qr = _cairo_int128_divrem (num_det, _cairo_int64_to_int128 (den_det));
|
||||
|
||||
intersect_32_32 = _cairo_int128_to_int64 (qr.quo);
|
||||
|
||||
/*
|
||||
* Find the ceiling of the quotient -- divrem returns
|
||||
* the quotient truncated towards zero, so if the
|
||||
* quotient should be positive (num_den and den_det have same sign)
|
||||
* bump the quotient up by one.
|
||||
*/
|
||||
|
||||
if (_cairo_int128_ne (qr.rem, _cairo_int32_to_int128 (0)) &&
|
||||
(_cairo_int128_ge (num_det, _cairo_int32_to_int128 (0)) ==
|
||||
_cairo_int64_ge (den_det, _cairo_int32_to_int64 (0))))
|
||||
{
|
||||
intersect_32_32 = _cairo_int64_add (intersect_32_32,
|
||||
_cairo_int32_to_int64 (1));
|
||||
}
|
||||
|
||||
/*
|
||||
* Now convert from 32.32 to 48.16 and take the ceiling;
|
||||
* this requires adding in 15 1 bits and shifting the result
|
||||
*/
|
||||
|
||||
intersect_32_32 = _cairo_int64_add (intersect_32_32,
|
||||
_cairo_int32_to_int64 ((1 << 16) - 1));
|
||||
intersect_48_16 = _cairo_int64_rsa (intersect_32_32, 16);
|
||||
|
||||
/*
|
||||
* And drop the top bits
|
||||
*/
|
||||
intersect_16_16 = _cairo_int64_to_int32 (intersect_48_16);
|
||||
|
||||
*y_intersection = intersect_16_16;
|
||||
|
||||
return 1;
|
||||
}
|
||||
#endif /* CAIRO_TRAPS_USE_NEW_INTERSECTION_CODE */
|
||||
|
||||
static cairo_fixed_16_16_t
|
||||
_compute_x (cairo_line_t *line, cairo_fixed_t y)
|
||||
{
|
||||
cairo_fixed_16_16_t dx = line->p2.x - line->p1.x;
|
||||
cairo_fixed_32_32_t ex = (cairo_fixed_48_16_t) (y - line->p1.y) * (cairo_fixed_48_16_t) dx;
|
||||
cairo_fixed_16_16_t dy = line->p2.y - line->p1.y;
|
||||
|
||||
return line->p1.x + (ex / dy);
|
||||
}
|
||||
|
||||
#if ! CAIRO_TRAPS_USE_NEW_INTERSECTION_CODE
|
||||
static double
|
||||
_compute_inverse_slope (cairo_line_t *l)
|
||||
{
|
||||
return (_cairo_fixed_to_double (l->p2.x - l->p1.x) /
|
||||
_cairo_fixed_to_double (l->p2.y - l->p1.y));
|
||||
}
|
||||
|
||||
static double
|
||||
_compute_x_intercept (cairo_line_t *l, double inverse_slope)
|
||||
{
|
||||
return _cairo_fixed_to_double (l->p1.x) - inverse_slope * _cairo_fixed_to_double (l->p1.y);
|
||||
}
|
||||
|
||||
static int
|
||||
_line_segs_intersect_ceil (cairo_line_t *l1, cairo_line_t *l2, cairo_fixed_t *y_ret)
|
||||
{
|
||||
/*
|
||||
* x = m1y + b1
|
||||
* x = m2y + b2
|
||||
* m1y + b1 = m2y + b2
|
||||
* y * (m1 - m2) = b2 - b1
|
||||
* y = (b2 - b1) / (m1 - m2)
|
||||
*/
|
||||
cairo_fixed_16_16_t y_intersect;
|
||||
double m1 = _compute_inverse_slope (l1);
|
||||
double b1 = _compute_x_intercept (l1, m1);
|
||||
double m2 = _compute_inverse_slope (l2);
|
||||
double b2 = _compute_x_intercept (l2, m2);
|
||||
|
||||
if (m1 == m2)
|
||||
return 0;
|
||||
|
||||
y_intersect = _cairo_fixed_from_double ((b2 - b1) / (m1 - m2));
|
||||
|
||||
if (m1 < m2) {
|
||||
cairo_line_t *t;
|
||||
t = l1;
|
||||
l1 = l2;
|
||||
l2 = t;
|
||||
}
|
||||
|
||||
/* Assuming 56 bits of floating point precision, the intersection
|
||||
is accurate within one sub-pixel coordinate. We must ensure
|
||||
that we return a value that is at or after the intersection. At
|
||||
most, we must increment once. */
|
||||
if (_compute_x (l2, y_intersect) > _compute_x (l1, y_intersect))
|
||||
y_intersect++;
|
||||
/* XXX: Hmm... Keith's error calculations said we'd at most be off
|
||||
by one sub-pixel. But, I found that the paint-fill-BE-01.svg
|
||||
test from the W3C SVG conformance suite definitely requires two
|
||||
increments.
|
||||
|
||||
It could be that we need one to overcome the error, and another
|
||||
to round up.
|
||||
|
||||
It would be nice to be sure this code is correct, (but we can't
|
||||
do the while loop as it will work for way to long on
|
||||
exceedingly distant intersections with large errors that we
|
||||
really don't care about anyway as they will be ignored by the
|
||||
calling function.
|
||||
*/
|
||||
if (_compute_x (l2, y_intersect) > _compute_x (l1, y_intersect))
|
||||
y_intersect++;
|
||||
/* XXX: hmm... now I found "intersection_killer" inside xrspline.c
|
||||
that requires 3 increments. Clearly, we haven't characterized
|
||||
this completely yet. */
|
||||
if (_compute_x (l2, y_intersect) > _compute_x (l1, y_intersect))
|
||||
y_intersect++;
|
||||
/* I think I've found the answer to our problems. The insight is
|
||||
that everytime we round we are changing the slopes of the
|
||||
relevant lines, so we may be introducing new intersections that
|
||||
we miss, so everything breaks apart. John Hobby wrote a paper
|
||||
on how to fix this:
|
||||
|
||||
[Hobby93c] John D. Hobby, Practical Segment Intersection with
|
||||
Finite Precision Output, Computation Geometry Theory and
|
||||
Applications, 13(4), 1999.
|
||||
|
||||
Available online (2003-08017):
|
||||
|
||||
http://cm.bell-labs.com/cm/cs/doc/93/2-27.ps.gz
|
||||
|
||||
Now we just need to go off and implement that.
|
||||
*/
|
||||
|
||||
*y_ret = y_intersect;
|
||||
|
||||
return 1;
|
||||
}
|
||||
#endif /* CAIRO_TRAPS_USE_NEW_INTERSECTION_CODE */
|
||||
|
||||
/* The algorithm here is pretty simple:
|
||||
|
||||
inactive = [edges]
|
||||
y = min_p1_y (inactive)
|
||||
|
||||
while (num_active || num_inactive) {
|
||||
active = all edges containing y
|
||||
|
||||
next_y = min ( min_p2_y (active), min_p1_y (inactive), min_intersection (active) )
|
||||
|
||||
fill_traps (active, y, next_y, fill_rule)
|
||||
|
||||
y = next_y
|
||||
}
|
||||
|
||||
The invariants that hold during fill_traps are:
|
||||
|
||||
All edges in active contain both y and next_y
|
||||
No edges in active intersect within y and next_y
|
||||
|
||||
These invariants mean that fill_traps is as simple as sorting the
|
||||
active edges, forming a trapezoid between each adjacent pair. Then,
|
||||
either the even-odd or winding rule is used to determine whether to
|
||||
emit each of these trapezoids.
|
||||
|
||||
Warning: This function obliterates the edges of the polygon provided.
|
||||
*/
|
||||
cairo_status_t
|
||||
_cairo_traps_tessellate_polygon (cairo_traps_t *traps,
|
||||
cairo_polygon_t *poly,
|
||||
cairo_fill_rule_t fill_rule)
|
||||
{
|
||||
int i, active, inactive;
|
||||
cairo_fixed_t y, y_next, intersect;
|
||||
int in_out, num_edges = poly->num_edges;
|
||||
cairo_edge_t *edges = poly->edges;
|
||||
|
||||
if (num_edges == 0)
|
||||
return CAIRO_STATUS_SUCCESS;
|
||||
|
||||
qsort (edges, num_edges, sizeof (cairo_edge_t), _compare_cairo_edge_by_top);
|
||||
|
||||
y = edges[0].edge.p1.y;
|
||||
active = 0;
|
||||
inactive = 0;
|
||||
while (active < num_edges) {
|
||||
while (inactive < num_edges && edges[inactive].edge.p1.y <= y)
|
||||
inactive++;
|
||||
|
||||
for (i = active; i < inactive; i++)
|
||||
edges[i].current_x = _compute_x (&edges[i].edge, y);
|
||||
|
||||
qsort (&edges[active], inactive - active,
|
||||
sizeof (cairo_edge_t), _compare_cairo_edge_by_current_x_slope);
|
||||
|
||||
/* find next inflection point */
|
||||
y_next = edges[active].edge.p2.y;
|
||||
|
||||
for (i = active; i < inactive; i++) {
|
||||
if (edges[i].edge.p2.y < y_next)
|
||||
y_next = edges[i].edge.p2.y;
|
||||
/* check intersect */
|
||||
if (i != inactive - 1 && edges[i].current_x != edges[i+1].current_x)
|
||||
if (_line_segs_intersect_ceil (&edges[i].edge, &edges[i+1].edge,
|
||||
&intersect))
|
||||
if (intersect > y && intersect < y_next)
|
||||
y_next = intersect;
|
||||
}
|
||||
/* check next inactive point */
|
||||
if (inactive < num_edges && edges[inactive].edge.p1.y < y_next)
|
||||
y_next = edges[inactive].edge.p1.y;
|
||||
|
||||
/* walk the active edges generating trapezoids */
|
||||
in_out = 0;
|
||||
for (i = active; i < inactive - 1; i++) {
|
||||
if (fill_rule == CAIRO_FILL_RULE_WINDING) {
|
||||
if (edges[i].clockWise)
|
||||
in_out++;
|
||||
else
|
||||
in_out--;
|
||||
if (in_out == 0)
|
||||
continue;
|
||||
} else {
|
||||
in_out++;
|
||||
if ((in_out & 1) == 0)
|
||||
continue;
|
||||
}
|
||||
_cairo_traps_add_trap (traps, y, y_next, &edges[i].edge, &edges[i+1].edge);
|
||||
}
|
||||
|
||||
/* delete inactive edges */
|
||||
for (i = active; i < inactive; i++) {
|
||||
if (edges[i].edge.p2.y <= y_next) {
|
||||
memmove (&edges[active+1], &edges[active], (i - active) * sizeof (cairo_edge_t));
|
||||
active++;
|
||||
}
|
||||
}
|
||||
|
||||
y = y_next;
|
||||
}
|
||||
return traps->status;
|
||||
}
|
||||
|
||||
static cairo_bool_t
|
||||
_cairo_trap_contains (cairo_trapezoid_t *t, cairo_point_t *pt)
|
||||
{
|
||||
|
|
|
@ -62,9 +62,33 @@
|
|||
#define TT_TAG_loca MAKE_TT_TAG('l','o','c','a')
|
||||
#define TT_TAG_maxp MAKE_TT_TAG('m','a','x','p')
|
||||
#define TT_TAG_name MAKE_TT_TAG('n','a','m','e')
|
||||
#define TT_TAG_post MAKE_TT_TAG('p','o','s','t')
|
||||
#define TT_TAG_prep MAKE_TT_TAG('p','r','e','p')
|
||||
|
||||
/* All tt_* structs are big-endian */
|
||||
typedef struct _tt_cmap_index {
|
||||
uint16_t platform;
|
||||
uint16_t encoding;
|
||||
uint32_t offset;
|
||||
} tt_cmap_index_t;
|
||||
|
||||
typedef struct _tt_cmap {
|
||||
uint16_t version;
|
||||
uint16_t num_tables;
|
||||
tt_cmap_index_t index[1];
|
||||
} tt_cmap_t;
|
||||
|
||||
typedef struct _segment_map {
|
||||
uint16_t format;
|
||||
uint16_t length;
|
||||
uint16_t version;
|
||||
uint16_t segCountX2;
|
||||
uint16_t searchRange;
|
||||
uint16_t entrySelector;
|
||||
uint16_t rangeShift;
|
||||
uint16_t endCount[1];
|
||||
} tt_segment_map_t;
|
||||
|
||||
typedef struct _tt_head {
|
||||
int16_t version_1;
|
||||
int16_t version_2;
|
||||
|
|
|
@ -56,6 +56,7 @@ typedef struct _cairo_truetype_font {
|
|||
int *widths;
|
||||
long x_min, y_min, x_max, y_max;
|
||||
long ascent, descent;
|
||||
int units_per_em;
|
||||
} base;
|
||||
|
||||
subset_glyph_t *glyphs;
|
||||
|
@ -79,41 +80,6 @@ cairo_truetype_font_use_glyph (cairo_truetype_font_t *font, int glyph);
|
|||
#define SFNT_VERSION 0x00010000
|
||||
#define SFNT_STRING_MAX_LENGTH 65535
|
||||
|
||||
#ifdef WORDS_BIGENDIAN
|
||||
|
||||
#define cpu_to_be16(v) (v)
|
||||
#define be16_to_cpu(v) (v)
|
||||
#define cpu_to_be32(v) (v)
|
||||
#define be32_to_cpu(v) (v)
|
||||
|
||||
#else
|
||||
|
||||
static inline uint16_t
|
||||
cpu_to_be16(uint16_t v)
|
||||
{
|
||||
return (v << 8) | (v >> 8);
|
||||
}
|
||||
|
||||
static inline uint16_t
|
||||
be16_to_cpu(uint16_t v)
|
||||
{
|
||||
return cpu_to_be16 (v);
|
||||
}
|
||||
|
||||
static inline uint32_t
|
||||
cpu_to_be32(uint32_t v)
|
||||
{
|
||||
return (cpu_to_be16 (v) << 16) | cpu_to_be16 (v >> 16);
|
||||
}
|
||||
|
||||
static inline uint32_t
|
||||
be32_to_cpu(uint32_t v)
|
||||
{
|
||||
return cpu_to_be32 (v);
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
static cairo_status_t
|
||||
_cairo_truetype_font_create (cairo_scaled_font_subset_t *scaled_font_subset,
|
||||
cairo_truetype_font_t **font_return)
|
||||
|
@ -200,6 +166,9 @@ _cairo_truetype_font_create (cairo_scaled_font_subset_t *scaled_font_subset,
|
|||
font->base.y_max = (int16_t) be16_to_cpu (head.y_max);
|
||||
font->base.ascent = (int16_t) be16_to_cpu (hhea.ascender);
|
||||
font->base.descent = (int16_t) be16_to_cpu (hhea.descender);
|
||||
font->base.units_per_em = (int16_t) be16_to_cpu (head.units_per_em);
|
||||
if (font->base.units_per_em == 0)
|
||||
font->base.units_per_em = 2048;
|
||||
|
||||
/* Extract the font name from the name table. At present this
|
||||
* just looks for the Mac platform/Roman encoded font name. It
|
||||
|
@ -371,22 +340,45 @@ cairo_truetype_font_write_cmap_table (cairo_truetype_font_t *font,
|
|||
{
|
||||
unsigned int i;
|
||||
|
||||
cairo_truetype_font_write_be16 (font, 0);
|
||||
cairo_truetype_font_write_be16 (font, 1);
|
||||
cairo_truetype_font_write_be16 (font, 0); /* Table version */
|
||||
cairo_truetype_font_write_be16 (font, 2); /* Num tables */
|
||||
|
||||
cairo_truetype_font_write_be16 (font, 1);
|
||||
cairo_truetype_font_write_be16 (font, 0);
|
||||
cairo_truetype_font_write_be32 (font, 12);
|
||||
cairo_truetype_font_write_be16 (font, 3); /* Platform */
|
||||
cairo_truetype_font_write_be16 (font, 0); /* Encoding */
|
||||
cairo_truetype_font_write_be32 (font, 20); /* Offset to start of table */
|
||||
|
||||
cairo_truetype_font_write_be16 (font, 1); /* Platform */
|
||||
cairo_truetype_font_write_be16 (font, 0); /* Encoding */
|
||||
cairo_truetype_font_write_be32 (font, 52); /* Offset to start of table */
|
||||
|
||||
/* Output a format 4 encoding table. */
|
||||
|
||||
cairo_truetype_font_write_be16 (font, 4); /* Format */
|
||||
cairo_truetype_font_write_be16 (font, 32); /* Length */
|
||||
cairo_truetype_font_write_be16 (font, 0); /* Version */
|
||||
cairo_truetype_font_write_be16 (font, 4); /* 2*segcount */
|
||||
cairo_truetype_font_write_be16 (font, 4); /* searchrange */
|
||||
cairo_truetype_font_write_be16 (font, 1); /* entry selector */
|
||||
cairo_truetype_font_write_be16 (font, 0); /* rangeshift */
|
||||
cairo_truetype_font_write_be16 (font, 0xf000 + font->base.num_glyphs - 2); /* end count[0] */
|
||||
cairo_truetype_font_write_be16 (font, 0xffff); /* end count[1] */
|
||||
cairo_truetype_font_write_be16 (font, 0); /* reserved */
|
||||
cairo_truetype_font_write_be16 (font, 0xf000); /* startCode[0] */
|
||||
cairo_truetype_font_write_be16 (font, 0xffff); /* startCode[1] */
|
||||
cairo_truetype_font_write_be16 (font, 0x1001); /* delta[0] */
|
||||
cairo_truetype_font_write_be16 (font, 1); /* delta[1] */
|
||||
cairo_truetype_font_write_be16 (font, 0); /* rangeOffset[0] */
|
||||
cairo_truetype_font_write_be16 (font, 0); /* rangeOffset[1] */
|
||||
|
||||
/* Output a format 6 encoding table. */
|
||||
|
||||
cairo_truetype_font_write_be16 (font, 6);
|
||||
cairo_truetype_font_write_be16 (font, 10 + 2 * (font->base.num_glyphs - 1));
|
||||
cairo_truetype_font_write_be16 (font, 0);
|
||||
cairo_truetype_font_write_be16 (font, 1); /* First glyph */
|
||||
cairo_truetype_font_write_be16 (font, font->base.num_glyphs - 1);
|
||||
for (i = 1; i < font->base.num_glyphs; i++)
|
||||
cairo_truetype_font_write_be16 (font, i);
|
||||
cairo_truetype_font_write_be16 (font, 0); /* First character */
|
||||
cairo_truetype_font_write_be16 (font, font->base.num_glyphs);
|
||||
for (i = 0; i < font->base.num_glyphs; i++)
|
||||
cairo_truetype_font_write_be16 (font, i + 1);
|
||||
|
||||
return font->status;
|
||||
}
|
||||
|
@ -532,6 +524,9 @@ cairo_truetype_font_write_head_table (cairo_truetype_font_t *font,
|
|||
font->status = cairo_truetype_font_allocate_write_buffer (font, size, &buffer);
|
||||
font->backend->load_truetype_table( font->scaled_font_subset->scaled_font,
|
||||
tag, 0, buffer, &size);
|
||||
/* set checkSumAdjustment to 0 for table checksum calcualtion */
|
||||
*(uint32_t *)(buffer + 8) = 0;
|
||||
|
||||
return font->status;
|
||||
}
|
||||
|
||||
|
@ -640,28 +635,65 @@ cairo_truetype_font_write_maxp_table (cairo_truetype_font_t *font,
|
|||
return font->status;
|
||||
}
|
||||
|
||||
static int
|
||||
cairo_truetype_font_write_post_table (cairo_truetype_font_t *font,
|
||||
unsigned long tag)
|
||||
{
|
||||
char buf[10];
|
||||
int n;
|
||||
unsigned i;
|
||||
|
||||
cairo_truetype_font_write_be32 (font, 0x00020000);
|
||||
cairo_truetype_font_write_be32 (font, 0);
|
||||
cairo_truetype_font_write_be16 (font, 0);
|
||||
cairo_truetype_font_write_be16 (font, 1);
|
||||
cairo_truetype_font_write_be32 (font, 0);
|
||||
cairo_truetype_font_write_be32 (font, 0);
|
||||
cairo_truetype_font_write_be32 (font, 0);
|
||||
cairo_truetype_font_write_be32 (font, 0);
|
||||
cairo_truetype_font_write_be32 (font, 0);
|
||||
cairo_truetype_font_write_be16 (font, font->base.num_glyphs);
|
||||
cairo_truetype_font_write_be16 (font, 0);
|
||||
for (i = 1; i < font->base.num_glyphs; i++)
|
||||
cairo_truetype_font_write_be16 (font, i + 257);
|
||||
|
||||
for (i = 1; i < font->base.num_glyphs; i++) {
|
||||
n = snprintf(buf + 1, 9, "g%d", i - 1);
|
||||
buf[0] = n;
|
||||
cairo_truetype_font_write (font, buf, n + 1);
|
||||
}
|
||||
|
||||
return font->status;
|
||||
}
|
||||
|
||||
typedef struct table table_t;
|
||||
struct table {
|
||||
unsigned long tag;
|
||||
int (*write) (cairo_truetype_font_t *font, unsigned long tag);
|
||||
int pos; /* position in the font directory */
|
||||
};
|
||||
|
||||
static const table_t truetype_tables[] = {
|
||||
/* As we write out the glyf table we remap composite glyphs.
|
||||
* Remapping composite glyphs will reference the sub glyphs the
|
||||
* composite glyph is made up of. That needs to be done first so
|
||||
* we have all the glyphs in the subset before going further. */
|
||||
{ TT_TAG_glyf, cairo_truetype_font_write_glyf_table },
|
||||
{ TT_TAG_cmap, cairo_truetype_font_write_cmap_table },
|
||||
{ TT_TAG_cvt, cairo_truetype_font_write_generic_table },
|
||||
{ TT_TAG_fpgm, cairo_truetype_font_write_generic_table },
|
||||
{ TT_TAG_head, cairo_truetype_font_write_head_table },
|
||||
{ TT_TAG_hhea, cairo_truetype_font_write_hhea_table },
|
||||
{ TT_TAG_hmtx, cairo_truetype_font_write_hmtx_table },
|
||||
{ TT_TAG_loca, cairo_truetype_font_write_loca_table },
|
||||
{ TT_TAG_maxp, cairo_truetype_font_write_maxp_table },
|
||||
{ TT_TAG_name, cairo_truetype_font_write_generic_table },
|
||||
{ TT_TAG_prep, cairo_truetype_font_write_generic_table },
|
||||
* we have all the glyphs in the subset before going further.
|
||||
*
|
||||
* The third column in this table is the order in which the
|
||||
* directory entries will appear in the table directory.
|
||||
* The table directory must be sorted in tag order. */
|
||||
{ TT_TAG_glyf, cairo_truetype_font_write_glyf_table, 3 },
|
||||
{ TT_TAG_cmap, cairo_truetype_font_write_cmap_table, 0 },
|
||||
{ TT_TAG_cvt, cairo_truetype_font_write_generic_table, 1 },
|
||||
{ TT_TAG_fpgm, cairo_truetype_font_write_generic_table, 2 },
|
||||
{ TT_TAG_head, cairo_truetype_font_write_head_table, 4 },
|
||||
{ TT_TAG_hhea, cairo_truetype_font_write_hhea_table, 5 },
|
||||
{ TT_TAG_hmtx, cairo_truetype_font_write_hmtx_table, 6 },
|
||||
{ TT_TAG_loca, cairo_truetype_font_write_loca_table, 7 },
|
||||
{ TT_TAG_maxp, cairo_truetype_font_write_maxp_table, 8 },
|
||||
{ TT_TAG_name, cairo_truetype_font_write_generic_table, 9 },
|
||||
{ TT_TAG_post, cairo_truetype_font_write_post_table, 10 },
|
||||
{ TT_TAG_prep, cairo_truetype_font_write_generic_table, 11 },
|
||||
};
|
||||
|
||||
static cairo_status_t
|
||||
|
@ -716,7 +748,7 @@ cairo_truetype_font_calculate_checksum (cairo_truetype_font_t *font,
|
|||
p = (uint32_t *) (data + start);
|
||||
padded_end = (uint32_t *) (data + ((end + 3) & ~3));
|
||||
while (p < padded_end)
|
||||
checksum += *p++;
|
||||
checksum += be32_to_cpu(*p++);
|
||||
|
||||
return checksum;
|
||||
}
|
||||
|
@ -761,7 +793,7 @@ cairo_truetype_font_generate (cairo_truetype_font_t *font,
|
|||
|
||||
end = _cairo_array_num_elements (&font->output);
|
||||
next = cairo_truetype_font_align_output (font);
|
||||
cairo_truetype_font_update_entry (font, i, truetype_tables[i].tag,
|
||||
cairo_truetype_font_update_entry (font, truetype_tables[i].pos, truetype_tables[i].tag,
|
||||
start, end);
|
||||
cairo_truetype_font_check_boundary (font, next);
|
||||
start = next;
|
||||
|
@ -813,6 +845,10 @@ _cairo_truetype_subset_init (cairo_truetype_subset_t *truetype_subset,
|
|||
if (status)
|
||||
return status;
|
||||
|
||||
/* Add the notdef glyph. This is required at glyph index 0
|
||||
* in the subsetted font. */
|
||||
cairo_truetype_font_use_glyph (font, 0);
|
||||
|
||||
for (i = 0; i < font->scaled_font_subset->num_glyphs; i++) {
|
||||
parent_glyph = font->scaled_font_subset->glyphs[i];
|
||||
cairo_truetype_font_use_glyph (font, parent_glyph);
|
||||
|
@ -827,18 +863,23 @@ _cairo_truetype_subset_init (cairo_truetype_subset_t *truetype_subset,
|
|||
if (truetype_subset->base_font == NULL)
|
||||
goto fail1;
|
||||
|
||||
truetype_subset->widths = calloc (sizeof (int), font->base.num_glyphs);
|
||||
/* The widths array returned must contain only widths for
|
||||
* the glyphs in font_subset. The notdef glyph at index 0
|
||||
* and any subglyphs appended after font_subset->num_glyphs
|
||||
* are omitted. */
|
||||
truetype_subset->widths = calloc (sizeof (double),
|
||||
font->scaled_font_subset->num_glyphs);
|
||||
if (truetype_subset->widths == NULL)
|
||||
goto fail2;
|
||||
for (i = 0; i < font->base.num_glyphs; i++)
|
||||
truetype_subset->widths[i] = font->base.widths[i];
|
||||
for (i = 0; i < font->scaled_font_subset->num_glyphs; i++)
|
||||
truetype_subset->widths[i] = (double)font->base.widths[i + 1]/font->base.units_per_em;
|
||||
|
||||
truetype_subset->x_min = font->base.x_min;
|
||||
truetype_subset->y_min = font->base.y_min;
|
||||
truetype_subset->x_max = font->base.x_max;
|
||||
truetype_subset->y_max = font->base.y_max;
|
||||
truetype_subset->ascent = font->base.ascent;
|
||||
truetype_subset->descent = font->base.descent;
|
||||
truetype_subset->x_min = (double)font->base.x_min/font->base.units_per_em;
|
||||
truetype_subset->y_min = (double)font->base.y_min/font->base.units_per_em;
|
||||
truetype_subset->x_max = (double)font->base.x_max/font->base.units_per_em;
|
||||
truetype_subset->y_max = (double)font->base.y_max/font->base.units_per_em;
|
||||
truetype_subset->ascent = (double)font->base.ascent/font->base.units_per_em;
|
||||
truetype_subset->descent = (double)font->base.descent/font->base.units_per_em;
|
||||
|
||||
truetype_subset->data = malloc (length);
|
||||
if (truetype_subset->data == NULL)
|
||||
|
@ -880,3 +921,145 @@ _cairo_truetype_subset_fini (cairo_truetype_subset_t *subset)
|
|||
free (subset->string_offsets);
|
||||
}
|
||||
|
||||
static cairo_int_status_t
|
||||
_cairo_truetype_map_glyphs_to_unicode (cairo_scaled_font_subset_t *font_subset,
|
||||
unsigned long table_offset)
|
||||
{
|
||||
cairo_status_t status = CAIRO_INT_STATUS_UNSUPPORTED;
|
||||
const cairo_scaled_font_backend_t *backend;
|
||||
tt_segment_map_t *map;
|
||||
char buf[4];
|
||||
unsigned int num_segments, i, j;
|
||||
unsigned long size;
|
||||
uint16_t *start_code;
|
||||
uint16_t *end_code;
|
||||
uint16_t *delta;
|
||||
uint16_t *range_offset;
|
||||
uint16_t *glyph_array;
|
||||
uint16_t g_id, c;
|
||||
|
||||
backend = font_subset->scaled_font->backend;
|
||||
size = 4;
|
||||
if (backend->load_truetype_table (font_subset->scaled_font,
|
||||
TT_TAG_cmap, table_offset,
|
||||
(unsigned char *) &buf,
|
||||
&size) != CAIRO_STATUS_SUCCESS) {
|
||||
return CAIRO_INT_STATUS_UNSUPPORTED;
|
||||
}
|
||||
|
||||
/* All table formats have the same first two words */
|
||||
map = (tt_segment_map_t *) buf;
|
||||
if (be16_to_cpu (map->format) != 4)
|
||||
return CAIRO_INT_STATUS_UNSUPPORTED;
|
||||
|
||||
size = be16_to_cpu (map->length);
|
||||
map = malloc (size);
|
||||
if (map == NULL)
|
||||
return CAIRO_STATUS_NO_MEMORY;
|
||||
if (backend->load_truetype_table (font_subset->scaled_font,
|
||||
TT_TAG_cmap, table_offset,
|
||||
(unsigned char *) map,
|
||||
&size) != CAIRO_STATUS_SUCCESS) {
|
||||
goto fail;
|
||||
}
|
||||
|
||||
num_segments = be16_to_cpu (map->segCountX2)/2;
|
||||
end_code = map->endCount;
|
||||
start_code = &(end_code[num_segments + 1]);
|
||||
delta = &(start_code[num_segments]);
|
||||
range_offset = &(delta[num_segments]);
|
||||
glyph_array = &(range_offset[num_segments]);
|
||||
|
||||
i = 0;
|
||||
while (i < font_subset->num_glyphs) {
|
||||
g_id = (uint16_t) font_subset->glyphs[i];
|
||||
|
||||
/* search for glyph in segments
|
||||
* with rangeOffset=0 */
|
||||
for (j = 0; j < num_segments; j++) {
|
||||
c = g_id - be16_to_cpu (delta[j]);
|
||||
if (range_offset[j] == 0 &&
|
||||
c >= be16_to_cpu (start_code[j]) &&
|
||||
c <= be16_to_cpu (end_code[j]))
|
||||
{
|
||||
font_subset->to_unicode[i] = c;
|
||||
goto next_glyph;
|
||||
}
|
||||
}
|
||||
|
||||
/* search for glyph in segments with rangeOffset=1 */
|
||||
for (j = 0; j < num_segments; j++) {
|
||||
if (range_offset[j] != 0) {
|
||||
uint16_t *glyph_ids = &range_offset[j] + be16_to_cpu (range_offset[j])/2;
|
||||
int range_size = be16_to_cpu (end_code[j]) - be16_to_cpu (start_code[j]) + 1;
|
||||
uint16_t g_id_be = cpu_to_be16 (g_id);
|
||||
int k;
|
||||
|
||||
for (k = 0; k < range_size; k++) {
|
||||
if (glyph_ids[k] == g_id_be) {
|
||||
font_subset->to_unicode[i] = be16_to_cpu (start_code[j]) + k;
|
||||
goto next_glyph;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
next_glyph:
|
||||
i++;
|
||||
}
|
||||
status = CAIRO_STATUS_SUCCESS;
|
||||
fail:
|
||||
free (map);
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
cairo_int_status_t
|
||||
_cairo_truetype_create_glyph_to_unicode_map (cairo_scaled_font_subset_t *font_subset)
|
||||
{
|
||||
cairo_status_t status = CAIRO_INT_STATUS_UNSUPPORTED;
|
||||
const cairo_scaled_font_backend_t *backend;
|
||||
tt_cmap_t *cmap;
|
||||
char buf[4];
|
||||
int num_tables, i;
|
||||
unsigned long size;
|
||||
|
||||
backend = font_subset->scaled_font->backend;
|
||||
if (!backend->load_truetype_table)
|
||||
return CAIRO_INT_STATUS_UNSUPPORTED;
|
||||
|
||||
size = 4;
|
||||
if (backend->load_truetype_table (font_subset->scaled_font,
|
||||
TT_TAG_cmap, 0, (unsigned char *) &buf,
|
||||
&size) != CAIRO_STATUS_SUCCESS)
|
||||
return CAIRO_INT_STATUS_UNSUPPORTED;
|
||||
|
||||
cmap = (tt_cmap_t *) buf;
|
||||
num_tables = be16_to_cpu (cmap->num_tables);
|
||||
size = 4 + num_tables*sizeof(tt_cmap_index_t);
|
||||
cmap = malloc (size);
|
||||
if (cmap == NULL)
|
||||
return CAIRO_STATUS_NO_MEMORY;
|
||||
if (backend->load_truetype_table (font_subset->scaled_font,
|
||||
TT_TAG_cmap, 0, (unsigned char *) cmap,
|
||||
&size) != CAIRO_STATUS_SUCCESS) {
|
||||
status = CAIRO_INT_STATUS_UNSUPPORTED;
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
/* Find a table with Unicode mapping */
|
||||
for (i = 0; i < num_tables; i++) {
|
||||
if (be16_to_cpu (cmap->index[i].platform) == 3 &&
|
||||
be16_to_cpu (cmap->index[i].encoding) == 1) {
|
||||
status = _cairo_truetype_map_glyphs_to_unicode (font_subset,
|
||||
be32_to_cpu (cmap->index[i].offset));
|
||||
if (status != CAIRO_INT_STATUS_UNSUPPORTED)
|
||||
goto cleanup;
|
||||
}
|
||||
}
|
||||
|
||||
cleanup:
|
||||
free (cmap);
|
||||
|
||||
return status;
|
||||
}
|
||||
|
|
|
@ -34,6 +34,7 @@
|
|||
*/
|
||||
|
||||
#include "cairoint.h"
|
||||
#include "cairo-type1-private.h"
|
||||
#include "cairo-scaled-font-subsets-private.h"
|
||||
#include "cairo-path-fixed-private.h"
|
||||
#include "cairo-output-stream-private.h"
|
||||
|
@ -116,11 +117,6 @@ fail:
|
|||
return CAIRO_STATUS_NO_MEMORY;
|
||||
}
|
||||
|
||||
/* Magic constants for the type1 eexec encryption */
|
||||
static const unsigned short encrypt_c1 = 52845, encrypt_c2 = 22719;
|
||||
static const unsigned short private_dict_key = 55665;
|
||||
static const unsigned short charstring_key = 4330;
|
||||
|
||||
/* Charstring commands. If the high byte is 0 the command is encoded
|
||||
* with a single byte. */
|
||||
#define CHARSTRING_sbw 0x0c07
|
||||
|
@ -301,13 +297,13 @@ charstring_encrypt (cairo_array_t *data)
|
|||
unsigned char *d, *end;
|
||||
uint16_t c, p, r;
|
||||
|
||||
r = charstring_key;
|
||||
r = CAIRO_TYPE1_CHARSTRING_KEY;
|
||||
d = (unsigned char *) _cairo_array_index (data, 0);
|
||||
end = d + _cairo_array_num_elements (data);
|
||||
while (d < end) {
|
||||
p = *d;
|
||||
c = p ^ (r >> 8);
|
||||
r = (c + r) * encrypt_c1 + encrypt_c2;
|
||||
r = (c + r) * CAIRO_TYPE1_ENCRYPT_C1 + CAIRO_TYPE1_ENCRYPT_C2;
|
||||
*d++ = c;
|
||||
}
|
||||
}
|
||||
|
@ -534,7 +530,7 @@ cairo_type1_write_stream_encrypted (void *closure,
|
|||
while (in < end) {
|
||||
p = *in++;
|
||||
c = p ^ (font->eexec_key >> 8);
|
||||
font->eexec_key = (c + font->eexec_key) * encrypt_c1 + encrypt_c2;
|
||||
font->eexec_key = (c + font->eexec_key) * CAIRO_TYPE1_ENCRYPT_C1 + CAIRO_TYPE1_ENCRYPT_C2;
|
||||
|
||||
if (font->hex_encode) {
|
||||
digits[0] = hex_digits[c >> 4];
|
||||
|
@ -564,7 +560,7 @@ cairo_type1_font_write_private_dict (cairo_type1_font_t *font,
|
|||
cairo_int_status_t status;
|
||||
cairo_output_stream_t *encrypted_output;
|
||||
|
||||
font->eexec_key = private_dict_key;
|
||||
font->eexec_key = CAIRO_TYPE1_PRIVATE_DICT_KEY;
|
||||
font->hex_column = 0;
|
||||
encrypted_output = _cairo_output_stream_create (
|
||||
cairo_type1_write_stream_encrypted,
|
||||
|
@ -680,8 +676,9 @@ static void
|
|||
cairo_type1_font_destroy (cairo_type1_font_t *font)
|
||||
{
|
||||
free (font->widths);
|
||||
_cairo_array_fini (&font->contents);
|
||||
cairo_scaled_font_destroy (font->type1_scaled_font);
|
||||
_cairo_array_fini (&font->contents);
|
||||
_cairo_output_stream_destroy (font->output);
|
||||
free (font);
|
||||
}
|
||||
|
||||
|
|
|
@ -34,6 +34,7 @@
|
|||
*/
|
||||
|
||||
#include "cairoint.h"
|
||||
#include "cairo-type1-private.h"
|
||||
#include "cairo-scaled-font-subsets-private.h"
|
||||
#include "cairo-output-stream-private.h"
|
||||
|
||||
|
@ -107,6 +108,7 @@ _cairo_type1_font_subset_create (cairo_unscaled_font_t *unscaled_font,
|
|||
cairo_bool_t hex_encode)
|
||||
{
|
||||
cairo_ft_unscaled_font_t *ft_unscaled_font;
|
||||
cairo_status_t status;
|
||||
FT_Face face;
|
||||
PS_FontInfoRec font_info;
|
||||
cairo_type1_font_subset_t *font;
|
||||
|
@ -116,12 +118,16 @@ _cairo_type1_font_subset_create (cairo_unscaled_font_t *unscaled_font,
|
|||
|
||||
face = _cairo_ft_unscaled_font_lock_face (ft_unscaled_font);
|
||||
|
||||
if (FT_Get_PS_Font_Info(face, &font_info) != 0)
|
||||
return CAIRO_INT_STATUS_UNSUPPORTED;
|
||||
if (FT_Get_PS_Font_Info(face, &font_info) != 0) {
|
||||
status = CAIRO_INT_STATUS_UNSUPPORTED;
|
||||
goto fail1;
|
||||
}
|
||||
|
||||
font = calloc (sizeof (cairo_type1_font_subset_t), 1);
|
||||
if (font == NULL)
|
||||
return CAIRO_STATUS_NO_MEMORY;
|
||||
if (font == NULL) {
|
||||
status = CAIRO_STATUS_NO_MEMORY;
|
||||
goto fail1;
|
||||
}
|
||||
|
||||
font->base.unscaled_font = _cairo_unscaled_font_reference (unscaled_font);
|
||||
font->base.num_glyphs = face->num_glyphs;
|
||||
|
@ -132,8 +138,10 @@ _cairo_type1_font_subset_create (cairo_unscaled_font_t *unscaled_font,
|
|||
font->base.ascent = face->ascender;
|
||||
font->base.descent = face->descender;
|
||||
font->base.base_font = strdup (face->family_name);
|
||||
if (font->base.base_font == NULL)
|
||||
goto fail1;
|
||||
if (font->base.base_font == NULL) {
|
||||
status = CAIRO_STATUS_NO_MEMORY;
|
||||
goto fail2;
|
||||
}
|
||||
|
||||
for (i = 0, j = 0; font->base.base_font[j]; j++) {
|
||||
if (font->base.base_font[j] == ' ')
|
||||
|
@ -143,8 +151,10 @@ _cairo_type1_font_subset_create (cairo_unscaled_font_t *unscaled_font,
|
|||
font->base.base_font[i] = '\0';
|
||||
|
||||
font->glyphs = calloc (face->num_glyphs, sizeof font->glyphs[0]);
|
||||
if (font->glyphs == NULL)
|
||||
goto fail2;
|
||||
if (font->glyphs == NULL) {
|
||||
status = CAIRO_STATUS_NO_MEMORY;
|
||||
goto fail3;
|
||||
}
|
||||
|
||||
font->hex_encode = hex_encode;
|
||||
font->num_glyphs = 0;
|
||||
|
@ -159,12 +169,15 @@ _cairo_type1_font_subset_create (cairo_unscaled_font_t *unscaled_font,
|
|||
|
||||
return CAIRO_STATUS_SUCCESS;
|
||||
|
||||
fail2:
|
||||
fail3:
|
||||
free (font->base.base_font);
|
||||
fail1:
|
||||
fail2:
|
||||
_cairo_unscaled_font_destroy (unscaled_font);
|
||||
free (font);
|
||||
fail1:
|
||||
_cairo_ft_unscaled_font_unlock_face (ft_unscaled_font);
|
||||
|
||||
return CAIRO_STATUS_NO_MEMORY;
|
||||
return status;
|
||||
}
|
||||
|
||||
static int
|
||||
|
@ -179,11 +192,6 @@ cairo_type1_font_subset_use_glyph (cairo_type1_font_subset_t *font, int glyph)
|
|||
return font->glyphs[glyph].subset_index;
|
||||
}
|
||||
|
||||
/* Magic constants for the type1 eexec encryption */
|
||||
static const unsigned short c1 = 52845, c2 = 22719;
|
||||
static const unsigned short private_dict_key = 55665;
|
||||
static const unsigned short charstring_key = 4330;
|
||||
|
||||
static cairo_bool_t
|
||||
is_ps_delimiter(int c)
|
||||
{
|
||||
|
@ -325,7 +333,7 @@ cairo_type1_font_subset_write_encrypted (cairo_type1_font_subset_t *font,
|
|||
while (in < end) {
|
||||
p = *in++;
|
||||
c = p ^ (font->eexec_key >> 8);
|
||||
font->eexec_key = (c + font->eexec_key) * c1 + c2;
|
||||
font->eexec_key = (c + font->eexec_key) * CAIRO_TYPE1_ENCRYPT_C1 + CAIRO_TYPE1_ENCRYPT_C2;
|
||||
|
||||
if (font->hex_encode) {
|
||||
digits[0] = hex_digits[c >> 4];
|
||||
|
@ -349,7 +357,7 @@ cairo_type1_font_subset_write_encrypted (cairo_type1_font_subset_t *font,
|
|||
static cairo_status_t
|
||||
cairo_type1_font_subset_decrypt_eexec_segment (cairo_type1_font_subset_t *font)
|
||||
{
|
||||
unsigned short r = private_dict_key;
|
||||
unsigned short r = CAIRO_TYPE1_PRIVATE_DICT_KEY;
|
||||
unsigned char *in, *end;
|
||||
char *out;
|
||||
int c, p;
|
||||
|
@ -372,7 +380,7 @@ cairo_type1_font_subset_decrypt_eexec_segment (cairo_type1_font_subset_t *font)
|
|||
c = *in++;
|
||||
}
|
||||
p = c ^ (r >> 8);
|
||||
r = (c + r) * c1 + c2;
|
||||
r = (c + r) * CAIRO_TYPE1_ENCRYPT_C1 + CAIRO_TYPE1_ENCRYPT_C2;
|
||||
|
||||
*out++ = p;
|
||||
}
|
||||
|
@ -452,13 +460,13 @@ cairo_type1_font_subset_get_glyph_names_and_widths (cairo_type1_font_subset_t *f
|
|||
static void
|
||||
cairo_type1_font_subset_decrypt_charstring (const unsigned char *in, int size, unsigned char *out)
|
||||
{
|
||||
unsigned short r = charstring_key;
|
||||
unsigned short r = CAIRO_TYPE1_CHARSTRING_KEY;
|
||||
int c, p, i;
|
||||
|
||||
for (i = 0; i < size; i++) {
|
||||
c = *in++;
|
||||
p = c ^ (r >> 8);
|
||||
r = (c + r) * c1 + c2;
|
||||
r = (c + r) * CAIRO_TYPE1_ENCRYPT_C1 + CAIRO_TYPE1_ENCRYPT_C2;
|
||||
*out++ = p;
|
||||
}
|
||||
}
|
||||
|
@ -1004,7 +1012,7 @@ cairo_type1_font_subset_write (cairo_type1_font_subset_t *font,
|
|||
return font->status = CAIRO_INT_STATUS_UNSUPPORTED;
|
||||
}
|
||||
|
||||
font->eexec_key = private_dict_key;
|
||||
font->eexec_key = CAIRO_TYPE1_PRIVATE_DICT_KEY;
|
||||
font->hex_column = 0;
|
||||
|
||||
cairo_type1_font_subset_write_private_dict (font, name);
|
||||
|
|
|
@ -693,7 +693,7 @@ _cairo_win32_scaled_font_set_metrics (cairo_win32_scaled_font_t *scaled_font)
|
|||
if (!hdc)
|
||||
return CAIRO_STATUS_NO_MEMORY;
|
||||
|
||||
if (scaled_font->preserve_axes) {
|
||||
if (scaled_font->preserve_axes || scaled_font->base.options.hint_metrics == CAIRO_HINT_METRICS_OFF) {
|
||||
/* For 90-degree rotations (including 0), we get the metrics
|
||||
* from the GDI in logical space, then convert back to font space
|
||||
*/
|
||||
|
@ -723,7 +723,7 @@ _cairo_win32_scaled_font_set_metrics (cairo_win32_scaled_font_t *scaled_font)
|
|||
_cairo_win32_scaled_font_done_unscaled_font (&scaled_font->base);
|
||||
|
||||
extents.ascent = (double)metrics.tmAscent / scaled_font->em_square;
|
||||
extents.descent = metrics.tmDescent * scaled_font->em_square;
|
||||
extents.descent = (double)metrics.tmDescent / scaled_font->em_square;
|
||||
extents.height = (double)(metrics.tmHeight + metrics.tmExternalLeading) / scaled_font->em_square;
|
||||
extents.max_x_advance = (double)(metrics.tmMaxCharWidth) / scaled_font->em_square;
|
||||
extents.max_y_advance = 0;
|
||||
|
@ -1281,6 +1281,20 @@ _cairo_win32_scaled_font_load_truetype_table (void *abstract_font,
|
|||
return status;
|
||||
}
|
||||
|
||||
static void
|
||||
_cairo_win32_scaled_font_map_glyphs_to_unicode (void *abstract_font,
|
||||
cairo_scaled_font_subset_t *font_subset)
|
||||
{
|
||||
cairo_win32_scaled_font_t *scaled_font = abstract_font;
|
||||
unsigned int i;
|
||||
|
||||
if (scaled_font->glyph_indexing)
|
||||
return;
|
||||
|
||||
for (i = 0; i < font_subset->num_glyphs; i++)
|
||||
font_subset->to_unicode[i] = font_subset->glyphs[i];
|
||||
}
|
||||
|
||||
static void
|
||||
_cairo_win32_transform_FIXED_to_fixed (cairo_matrix_t *matrix,
|
||||
FIXED Fx, FIXED Fy,
|
||||
|
@ -1467,6 +1481,7 @@ const cairo_scaled_font_backend_t cairo_win32_scaled_font_backend = {
|
|||
NULL, /* ucs4_to_index */
|
||||
_cairo_win32_scaled_font_show_glyphs,
|
||||
_cairo_win32_scaled_font_load_truetype_table,
|
||||
_cairo_win32_scaled_font_map_glyphs_to_unicode,
|
||||
};
|
||||
|
||||
/* cairo_win32_font_face_t */
|
||||
|
@ -1649,7 +1664,7 @@ cairo_win32_scaled_font_select_font (cairo_scaled_font_t *scaled_font,
|
|||
|
||||
/**
|
||||
* cairo_win32_scaled_font_done_font:
|
||||
* @scaled_font: A #cairo_scaled_font_t from the Win32 font backend.
|
||||
* @scaled_font: A scaled font from the Win32 font backend.
|
||||
*
|
||||
* Releases any resources allocated by cairo_win32_scaled_font_select_font()
|
||||
**/
|
||||
|
@ -1660,7 +1675,7 @@ cairo_win32_scaled_font_done_font (cairo_scaled_font_t *scaled_font)
|
|||
|
||||
/**
|
||||
* cairo_win32_scaled_font_get_metrics_factor:
|
||||
* @scaled_font: a #cairo_scaled_font_t from the Win32 font backend
|
||||
* @scaled_font: a scaled font from the Win32 font backend
|
||||
*
|
||||
* Gets a scale factor between logical coordinates in the coordinate
|
||||
* space used by cairo_win32_scaled_font_select_font() (that is, the
|
||||
|
@ -1676,6 +1691,16 @@ cairo_win32_scaled_font_get_metrics_factor (cairo_scaled_font_t *scaled_font)
|
|||
return 1. / ((cairo_win32_scaled_font_t *)scaled_font)->logical_scale;
|
||||
}
|
||||
|
||||
/**
|
||||
* cairo_win32_scaled_font_get_logical_to_device:
|
||||
* @scaled_font: a scaled font from the Win32 font backend
|
||||
* @logical_to_device: matrix to return
|
||||
*
|
||||
* Gets the transformation mapping the logical space used by @scaled_font
|
||||
* to device space.
|
||||
*
|
||||
* Since: 1.4
|
||||
**/
|
||||
void
|
||||
cairo_win32_scaled_font_get_logical_to_device (cairo_scaled_font_t *scaled_font,
|
||||
cairo_matrix_t *logical_to_device)
|
||||
|
@ -1684,6 +1709,16 @@ cairo_win32_scaled_font_get_logical_to_device (cairo_scaled_font_t *scaled_font,
|
|||
*logical_to_device = win_font->logical_to_device;
|
||||
}
|
||||
|
||||
/**
|
||||
* cairo_win32_scaled_font_get_device_to_logical:
|
||||
* @scaled_font: a scaled font from the Win32 font backend
|
||||
* @device_to_logical: matrix to return
|
||||
*
|
||||
* Gets the transformation mapping device space to the logical space
|
||||
* used by @scaled_font.
|
||||
*
|
||||
* Since: 1.4
|
||||
**/
|
||||
void
|
||||
cairo_win32_scaled_font_get_device_to_logical (cairo_scaled_font_t *scaled_font,
|
||||
cairo_matrix_t *device_to_logical)
|
||||
|
|
|
@ -46,7 +46,11 @@
|
|||
#define SB_NONE 0
|
||||
#endif
|
||||
|
||||
#if MOZILLA_CAIRO_NOT_DEFINED
|
||||
#define WIN32_FONT_LOGICAL_SCALE 32
|
||||
#else
|
||||
#define WIN32_FONT_LOGICAL_SCALE 1
|
||||
#endif
|
||||
|
||||
typedef struct _cairo_win32_surface {
|
||||
cairo_surface_t base;
|
||||
|
|
|
@ -1487,6 +1487,7 @@ _cairo_win32_surface_show_glyphs (void *surface,
|
|||
int num_glyphs,
|
||||
cairo_scaled_font_t *scaled_font)
|
||||
{
|
||||
#if CAIRO_HAS_WIN32_FONT
|
||||
cairo_win32_surface_t *dst = surface;
|
||||
|
||||
WORD glyph_buf_stack[STACK_GLYPH_SIZE];
|
||||
|
@ -1580,8 +1581,8 @@ _cairo_win32_surface_show_glyphs (void *surface,
|
|||
next_logical_x = _cairo_lround (next_user_x);
|
||||
next_logical_y = _cairo_lround (next_user_y);
|
||||
|
||||
dxy_buf[j] = _cairo_lround ((next_logical_x - logical_x) * WIN32_FONT_LOGICAL_SCALE);
|
||||
dxy_buf[j+1] = _cairo_lround ((next_logical_y - logical_y) * WIN32_FONT_LOGICAL_SCALE);
|
||||
dxy_buf[j] = _cairo_lround (next_logical_x - logical_x);
|
||||
dxy_buf[j+1] = _cairo_lround (next_logical_y - logical_y);
|
||||
|
||||
logical_x = next_logical_x;
|
||||
logical_y = next_logical_y;
|
||||
|
@ -1607,6 +1608,9 @@ _cairo_win32_surface_show_glyphs (void *surface,
|
|||
free(dxy_buf);
|
||||
}
|
||||
return (win_result) ? CAIRO_STATUS_SUCCESS : CAIRO_INT_STATUS_UNSUPPORTED;
|
||||
#else
|
||||
return CAIRO_INT_STATUS_UNSUPPORTED;
|
||||
#endif
|
||||
}
|
||||
|
||||
#undef STACK_GLYPH_SIZE
|
||||
|
@ -1728,6 +1732,7 @@ cairo_win32_surface_create_with_dib (cairo_format_t format,
|
|||
|
||||
/**
|
||||
* cairo_win32_surface_create_with_ddb:
|
||||
* @hdc: the DC to create a surface for
|
||||
* @format: format of pixels in the surface to create
|
||||
* @width: width of the surface, in pixels
|
||||
* @height: height of the surface, in pixels
|
||||
|
@ -1890,9 +1895,11 @@ static const cairo_surface_backend_t cairo_win32_surface_backend = {
|
|||
*/
|
||||
#if !defined(HAVE_PTHREAD_H)
|
||||
|
||||
CRITICAL_SECTION cairo_toy_font_face_hash_table_mutex;
|
||||
CRITICAL_SECTION cairo_scaled_font_map_mutex;
|
||||
CRITICAL_SECTION cairo_ft_unscaled_font_map_mutex;
|
||||
CRITICAL_SECTION _cairo_scaled_font_map_mutex;
|
||||
#ifdef CAIRO_HAS_FT_FONT
|
||||
CRITICAL_SECTION _cairo_ft_unscaled_font_map_mutex;
|
||||
#endif
|
||||
CRITICAL_SECTION _cairo_font_face_mutex;
|
||||
|
||||
static int _cairo_win32_initialized = 0;
|
||||
|
||||
|
@ -1902,9 +1909,11 @@ _cairo_win32_initialize (void) {
|
|||
return;
|
||||
|
||||
/* every 'mutex' from CAIRO_MUTEX_DECALRE needs to be initialized here */
|
||||
InitializeCriticalSection (&cairo_toy_font_face_hash_table_mutex);
|
||||
InitializeCriticalSection (&cairo_scaled_font_map_mutex);
|
||||
InitializeCriticalSection (&cairo_ft_unscaled_font_map_mutex);
|
||||
InitializeCriticalSection (&_cairo_scaled_font_map_mutex);
|
||||
#ifdef CAIRO_HAS_FT_FONT
|
||||
InitializeCriticalSection (&_cairo_ft_unscaled_font_map_mutex);
|
||||
#endif
|
||||
InitializeCriticalSection (&_cairo_font_face_mutex);
|
||||
|
||||
_cairo_win32_initialized = 1;
|
||||
}
|
||||
|
@ -1921,9 +1930,11 @@ DllMain (HINSTANCE hinstDLL,
|
|||
_cairo_win32_initialize();
|
||||
break;
|
||||
case DLL_PROCESS_DETACH:
|
||||
DeleteCriticalSection (&cairo_toy_font_face_hash_table_mutex);
|
||||
DeleteCriticalSection (&cairo_scaled_font_map_mutex);
|
||||
DeleteCriticalSection (&cairo_ft_unscaled_font_map_mutex);
|
||||
DeleteCriticalSection (&_cairo_scaled_font_map_mutex);
|
||||
#ifdef CAIRO_HAS_FT_FONT
|
||||
DeleteCriticalSection (&_cairo_ft_unscaled_font_map_mutex);
|
||||
#endif
|
||||
DeleteCriticalSection (&_cairo_font_face_mutex);
|
||||
break;
|
||||
}
|
||||
return TRUE;
|
||||
|
|
|
@ -1289,10 +1289,9 @@ _create_a8_picture (cairo_xcb_surface_t *surface,
|
|||
= _CAIRO_FORMAT_TO_XRENDER_FORMAT (surface->dpy, CAIRO_FORMAT_A8);
|
||||
xcb_rectangle_t rect = { 0, 0, width, height };
|
||||
|
||||
xcb_create_pixmap (surface->dpy, pixmap, surface->drawable,
|
||||
xcb_create_pixmap (surface->dpy, 8, pixmap, surface->drawable,
|
||||
width <= 0 ? 1 : width,
|
||||
height <= 0 ? 1 : height,
|
||||
8);
|
||||
height <= 0 ? 1 : height);
|
||||
xcb_render_create_picture (surface->dpy, picture, pixmap, format->id, mask, values);
|
||||
xcb_render_fill_rectangles (surface->dpy, XCB_RENDER_PICT_OP_SRC, picture, *color, 1, &rect);
|
||||
xcb_free_pixmap (surface->dpy, pixmap);
|
||||
|
|
|
@ -37,6 +37,14 @@
|
|||
#include "cairo-xlib.h"
|
||||
|
||||
typedef struct _cairo_xlib_screen_info cairo_xlib_screen_info_t;
|
||||
typedef struct _cairo_xlib_hook cairo_xlib_hook_t;
|
||||
|
||||
struct _cairo_xlib_hook {
|
||||
cairo_xlib_hook_t *next;
|
||||
void (*func) (Display *display, void *data);
|
||||
void *data;
|
||||
void *key;
|
||||
};
|
||||
|
||||
struct _cairo_xlib_screen_info {
|
||||
cairo_xlib_screen_info_t *next;
|
||||
|
@ -46,18 +54,24 @@ struct _cairo_xlib_screen_info {
|
|||
cairo_bool_t has_render;
|
||||
|
||||
cairo_font_options_t font_options;
|
||||
|
||||
cairo_xlib_hook_t *close_display_hooks;
|
||||
};
|
||||
|
||||
cairo_private cairo_xlib_screen_info_t *
|
||||
_cairo_xlib_screen_info_get (Display *display, Screen *screen);
|
||||
|
||||
cairo_private cairo_bool_t
|
||||
_cairo_xlib_add_close_display_hook (Display *display, void (*func) (Display *, void *), void *data, void *key);
|
||||
cairo_private void
|
||||
_cairo_xlib_remove_close_display_hook (Display *display, void *key);
|
||||
|
||||
#if CAIRO_HAS_XLIB_XRENDER_SURFACE
|
||||
|
||||
#include "cairo-xlib-xrender.h"
|
||||
#if 0
|
||||
#ifdef MOZILLA_CAIRO_NOT_DEFINED
|
||||
slim_hidden_proto (cairo_xlib_surface_create_with_xrender_format);
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
||||
#endif /* CAIRO_XLIB_PRIVATE_H */
|
||||
|
|
|
@ -247,31 +247,36 @@ CAIRO_MUTEX_DECLARE(_xlib_screen_mutex);
|
|||
|
||||
static cairo_xlib_screen_info_t *_cairo_xlib_screen_list = NULL;
|
||||
|
||||
/* XXX: From this function we should also run through and cleanup
|
||||
* anything else that still has a pointer to this Display*. For
|
||||
* example, we should clean up any Xlib-specific glyph caches. */
|
||||
static int
|
||||
_cairo_xlib_close_display (Display *dpy, XExtCodes *codes)
|
||||
{
|
||||
cairo_xlib_screen_info_t *info, *prev;
|
||||
cairo_xlib_screen_info_t *info, **prev, *next;
|
||||
|
||||
/*
|
||||
* Unhook from the global list
|
||||
*/
|
||||
CAIRO_MUTEX_LOCK (_xlib_screen_mutex);
|
||||
|
||||
prev = NULL;
|
||||
for (info = _cairo_xlib_screen_list; info; info = info->next) {
|
||||
prev = &_cairo_xlib_screen_list;
|
||||
for (info = _cairo_xlib_screen_list; info; info = next) {
|
||||
next = info->next;
|
||||
if (info->display == dpy) {
|
||||
if (prev)
|
||||
prev->next = info->next;
|
||||
else
|
||||
_cairo_xlib_screen_list = info->next;
|
||||
*prev = next;
|
||||
/* call all registered shutdown routines */
|
||||
while (info->close_display_hooks) {
|
||||
cairo_xlib_hook_t *hook = info->close_display_hooks;
|
||||
info->close_display_hooks = hook->next;
|
||||
|
||||
hook->func (dpy, hook->data);
|
||||
|
||||
free (hook);
|
||||
}
|
||||
free (info);
|
||||
break;
|
||||
} else {
|
||||
prev = &info->next;
|
||||
}
|
||||
prev = info;
|
||||
}
|
||||
*prev = NULL;
|
||||
CAIRO_MUTEX_UNLOCK (_xlib_screen_mutex);
|
||||
|
||||
/* Return value in accordance with requirements of
|
||||
|
@ -291,6 +296,11 @@ _cairo_xlib_screen_info_reset (void)
|
|||
|
||||
for (info = _cairo_xlib_screen_list; info; info = next) {
|
||||
next = info->next;
|
||||
while (info->close_display_hooks) {
|
||||
cairo_xlib_hook_t *hook = info->close_display_hooks;
|
||||
info->close_display_hooks = hook->next;
|
||||
free (hook);
|
||||
}
|
||||
free (info);
|
||||
}
|
||||
|
||||
|
@ -300,8 +310,8 @@ _cairo_xlib_screen_info_reset (void)
|
|||
|
||||
}
|
||||
|
||||
cairo_xlib_screen_info_t *
|
||||
_cairo_xlib_screen_info_get (Display *dpy, Screen *screen)
|
||||
static cairo_xlib_screen_info_t *
|
||||
_cairo_xlib_screen_info_get_unlocked (Display *dpy, Screen *screen)
|
||||
{
|
||||
cairo_xlib_screen_info_t *info;
|
||||
cairo_xlib_screen_info_t **prev;
|
||||
|
@ -309,26 +319,15 @@ _cairo_xlib_screen_info_get (Display *dpy, Screen *screen)
|
|||
XExtCodes *codes;
|
||||
cairo_bool_t seen_display = FALSE;
|
||||
|
||||
/* There is an apparent deadlock between this mutex and the
|
||||
* mutex for the display, but it's actually safe. For the
|
||||
* app to call XCloseDisplay() while any other thread is
|
||||
* inside this function would be an error in the logic
|
||||
* app, and the CloseDisplay hook is the only other place we
|
||||
* acquire this mutex.
|
||||
*/
|
||||
CAIRO_MUTEX_LOCK (_xlib_screen_mutex);
|
||||
|
||||
for (prev = &_cairo_xlib_screen_list; (info = *prev); prev = &(*prev)->next)
|
||||
{
|
||||
if (info->display == dpy) {
|
||||
seen_display = TRUE;
|
||||
if (info->screen == screen)
|
||||
{
|
||||
if (info->screen == screen || screen == NULL) {
|
||||
/*
|
||||
* MRU the list
|
||||
*/
|
||||
if (prev != &_cairo_xlib_screen_list)
|
||||
{
|
||||
if (prev != &_cairo_xlib_screen_list) {
|
||||
*prev = info->next;
|
||||
info->next = _cairo_xlib_screen_list;
|
||||
_cairo_xlib_screen_list = info;
|
||||
|
@ -339,18 +338,17 @@ _cairo_xlib_screen_info_get (Display *dpy, Screen *screen)
|
|||
}
|
||||
|
||||
if (info)
|
||||
goto out;
|
||||
return info;
|
||||
|
||||
info = malloc (sizeof (cairo_xlib_screen_info_t));
|
||||
if (!info)
|
||||
goto out;
|
||||
return NULL;
|
||||
|
||||
if (!seen_display) {
|
||||
codes = XAddExtension (dpy);
|
||||
if (!codes) {
|
||||
free (info);
|
||||
info = NULL;
|
||||
goto out;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
XESetCloseDisplay (dpy, codes->extension, _cairo_xlib_close_display);
|
||||
|
@ -361,24 +359,110 @@ _cairo_xlib_screen_info_get (Display *dpy, Screen *screen)
|
|||
info->has_render = (XRenderQueryExtension (dpy, &event_base, &error_base) &&
|
||||
(XRenderFindVisualFormat (dpy, DefaultVisual (dpy, DefaultScreen (dpy))) != 0));
|
||||
|
||||
info->close_display_hooks = NULL;
|
||||
|
||||
_cairo_xlib_init_screen_font_options (info);
|
||||
|
||||
info->next = _cairo_xlib_screen_list;
|
||||
_cairo_xlib_screen_list = info;
|
||||
|
||||
out:
|
||||
return info;
|
||||
}
|
||||
cairo_xlib_screen_info_t *
|
||||
_cairo_xlib_screen_info_get (Display *dpy, Screen *screen)
|
||||
{
|
||||
cairo_xlib_screen_info_t *info;
|
||||
|
||||
/* There is an apparent deadlock between this mutex and the
|
||||
* mutex for the display, but it's actually safe. For the
|
||||
* app to call XCloseDisplay() while any other thread is
|
||||
* inside this function would be an error in the logic
|
||||
* app, and the CloseDisplay hook is the only other place we
|
||||
* acquire this mutex.
|
||||
*/
|
||||
CAIRO_MUTEX_LOCK (_xlib_screen_mutex);
|
||||
|
||||
info = _cairo_xlib_screen_info_get_unlocked (dpy, screen);
|
||||
|
||||
CAIRO_MUTEX_UNLOCK (_xlib_screen_mutex);
|
||||
|
||||
return info;
|
||||
}
|
||||
|
||||
cairo_bool_t
|
||||
_cairo_xlib_add_close_display_hook (Display *dpy, void (*func) (Display *, void *), void *data, void *key)
|
||||
{
|
||||
cairo_xlib_screen_info_t *info;
|
||||
cairo_xlib_hook_t *hook;
|
||||
cairo_xlib_hook_t **prev;
|
||||
cairo_bool_t success = FALSE;
|
||||
|
||||
CAIRO_MUTEX_LOCK (_xlib_screen_mutex);
|
||||
|
||||
info = _cairo_xlib_screen_info_get_unlocked (dpy, NULL);
|
||||
if (!info)
|
||||
goto unlock;
|
||||
|
||||
for (prev = &info->close_display_hooks; (hook = *prev); prev = &hook->next)
|
||||
{
|
||||
if (hook->key == key) {
|
||||
/*
|
||||
* MRU the list
|
||||
*/
|
||||
if (prev != &info->close_display_hooks) {
|
||||
*prev = hook->next;
|
||||
hook->next = info->close_display_hooks;
|
||||
info->close_display_hooks = hook;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (!hook) {
|
||||
hook = malloc (sizeof (cairo_xlib_hook_t));
|
||||
if (!hook)
|
||||
goto unlock;
|
||||
hook->func = func;
|
||||
hook->data = data;
|
||||
hook->key = key;
|
||||
hook->next = info->close_display_hooks;
|
||||
info->close_display_hooks = hook;
|
||||
}
|
||||
|
||||
success = TRUE;
|
||||
unlock:
|
||||
CAIRO_MUTEX_UNLOCK (_xlib_screen_mutex);
|
||||
return success;
|
||||
}
|
||||
|
||||
void
|
||||
_cairo_xlib_remove_close_display_hook (Display *dpy, void *key)
|
||||
{
|
||||
cairo_xlib_screen_info_t *info;
|
||||
cairo_xlib_hook_t *hook;
|
||||
cairo_xlib_hook_t **prev;
|
||||
|
||||
CAIRO_MUTEX_LOCK (_xlib_screen_mutex);
|
||||
|
||||
info = _cairo_xlib_screen_info_get_unlocked (dpy, NULL);
|
||||
if (!info)
|
||||
goto unlock;
|
||||
|
||||
for (prev = &info->close_display_hooks; (hook = *prev); prev = &hook->next)
|
||||
{
|
||||
if (hook->key == key) {
|
||||
*prev = hook->next;
|
||||
free (hook);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
unlock:
|
||||
CAIRO_MUTEX_UNLOCK (_xlib_screen_mutex);
|
||||
}
|
||||
|
||||
void
|
||||
_cairo_xlib_screen_reset_static_data (void)
|
||||
{
|
||||
_cairo_xlib_screen_info_reset ();
|
||||
|
||||
#if HAVE_XRMFINALIZE
|
||||
XrmFinalize ();
|
||||
#endif
|
||||
|
||||
}
|
||||
|
|
|
@ -610,24 +610,27 @@ _get_image_surface (cairo_xlib_surface_t *surface,
|
|||
_swap_ximage_to_native (ximage);
|
||||
|
||||
/*
|
||||
* Compute the pixel format masks from either a visual or a
|
||||
* XRenderFormat, failing we assume the drawable is an
|
||||
* alpha-only pixmap as it could only have been created
|
||||
* that way through the cairo_xlib_surface_create_for_bitmap
|
||||
* function.
|
||||
* Compute the pixel format masks from either a XrenderFormat or
|
||||
* else from a visual; failing that we assume the drawable is an
|
||||
* alpha-only pixmap as it could only have been created that way
|
||||
* through the cairo_xlib_surface_create_for_bitmap function.
|
||||
*/
|
||||
if (surface->visual) {
|
||||
if (surface->xrender_format) {
|
||||
masks.bpp = ximage->bits_per_pixel;
|
||||
masks.red_mask = (unsigned long) surface->xrender_format->direct.redMask
|
||||
<< surface->xrender_format->direct.red;
|
||||
masks.green_mask = (unsigned long) surface->xrender_format->direct.greenMask
|
||||
<< surface->xrender_format->direct.green;
|
||||
masks.blue_mask = (unsigned long) surface->xrender_format->direct.blueMask
|
||||
<< surface->xrender_format->direct.blue;
|
||||
masks.alpha_mask = (unsigned long) surface->xrender_format->direct.alphaMask
|
||||
<< surface->xrender_format->direct.alpha;
|
||||
} else if (surface->visual) {
|
||||
masks.bpp = ximage->bits_per_pixel;
|
||||
masks.alpha_mask = 0;
|
||||
masks.red_mask = surface->visual->red_mask;
|
||||
masks.green_mask = surface->visual->green_mask;
|
||||
masks.blue_mask = surface->visual->blue_mask;
|
||||
} else if (surface->xrender_format) {
|
||||
masks.bpp = ximage->bits_per_pixel;
|
||||
masks.red_mask = (unsigned long)surface->xrender_format->direct.redMask << surface->xrender_format->direct.red;
|
||||
masks.green_mask = (unsigned long)surface->xrender_format->direct.greenMask << surface->xrender_format->direct.green;
|
||||
masks.blue_mask = (unsigned long)surface->xrender_format->direct.blueMask << surface->xrender_format->direct.blue;
|
||||
masks.alpha_mask = (unsigned long)surface->xrender_format->direct.alphaMask << surface->xrender_format->direct.alpha;
|
||||
} else {
|
||||
masks.bpp = ximage->bits_per_pixel;
|
||||
masks.red_mask = 0;
|
||||
|
@ -2019,7 +2022,7 @@ cairo_xlib_surface_create_with_xrender_format (Display *dpy,
|
|||
return _cairo_xlib_surface_create_internal (dpy, drawable, screen,
|
||||
NULL, format, width, height, 0);
|
||||
}
|
||||
#if 0
|
||||
#ifdef MOZILLA_CAIRO_NOT_DEFINED
|
||||
slim_hidden_def (cairo_xlib_surface_create_with_xrender_format);
|
||||
#endif
|
||||
|
||||
|
@ -2270,6 +2273,24 @@ typedef struct _cairo_xlib_surface_font_private {
|
|||
XRenderPictFormat *xrender_format;
|
||||
} cairo_xlib_surface_font_private_t;
|
||||
|
||||
static void
|
||||
_cairo_xlib_surface_remove_scaled_font (Display *dpy,
|
||||
void *data)
|
||||
{
|
||||
cairo_scaled_font_t *scaled_font = data;
|
||||
cairo_xlib_surface_font_private_t *font_private = scaled_font->surface_private;
|
||||
|
||||
_cairo_scaled_font_reset_cache (scaled_font);
|
||||
|
||||
/* separate function to avoid deadlock if we tried to remove the
|
||||
* close display hook ala _cairo_xlib_surface_scaled_font_fini() */
|
||||
if (font_private) {
|
||||
XRenderFreeGlyphSet (font_private->dpy, font_private->glyphset);
|
||||
free (font_private);
|
||||
scaled_font->surface_private = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
static cairo_status_t
|
||||
_cairo_xlib_surface_font_init (Display *dpy,
|
||||
cairo_scaled_font_t *scaled_font,
|
||||
|
@ -2277,6 +2298,11 @@ _cairo_xlib_surface_font_init (Display *dpy,
|
|||
{
|
||||
cairo_xlib_surface_font_private_t *font_private;
|
||||
|
||||
if (!_cairo_xlib_add_close_display_hook (dpy,
|
||||
_cairo_xlib_surface_remove_scaled_font,
|
||||
scaled_font, scaled_font))
|
||||
return CAIRO_STATUS_NO_MEMORY;
|
||||
|
||||
font_private = malloc (sizeof (cairo_xlib_surface_font_private_t));
|
||||
if (!font_private)
|
||||
return CAIRO_STATUS_NO_MEMORY;
|
||||
|
@ -2287,6 +2313,7 @@ _cairo_xlib_surface_font_init (Display *dpy,
|
|||
font_private->glyphset = XRenderCreateGlyphSet (dpy, font_private->xrender_format);
|
||||
scaled_font->surface_private = font_private;
|
||||
scaled_font->surface_backend = &cairo_xlib_surface_backend;
|
||||
|
||||
return CAIRO_STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
|
@ -2296,6 +2323,7 @@ _cairo_xlib_surface_scaled_font_fini (cairo_scaled_font_t *scaled_font)
|
|||
cairo_xlib_surface_font_private_t *font_private = scaled_font->surface_private;
|
||||
|
||||
if (font_private) {
|
||||
_cairo_xlib_remove_close_display_hook (font_private->dpy, scaled_font);
|
||||
XRenderFreeGlyphSet (font_private->dpy, font_private->glyphset);
|
||||
free (font_private);
|
||||
}
|
||||
|
|
|
@ -47,15 +47,18 @@
|
|||
static const cairo_t cairo_nil = {
|
||||
CAIRO_REF_COUNT_INVALID, /* ref_count */
|
||||
CAIRO_STATUS_NO_MEMORY, /* status */
|
||||
{ /* path */
|
||||
NULL, NULL, /* op_buf_head, op_buf_tail */
|
||||
NULL, NULL, /* arg_buf_head, arg_buf_tail */
|
||||
{ 0, 0, 0, NULL }, /* user_data */
|
||||
NULL, /* gstate */
|
||||
{{ /* gstate_tail */
|
||||
0
|
||||
}},
|
||||
{{ /* path */
|
||||
{ 0, 0 }, /* last_move_point */
|
||||
{ 0, 0 }, /* current point */
|
||||
FALSE, /* has_current_point */
|
||||
FALSE /* has_curve_to */
|
||||
},
|
||||
NULL /* gstate */
|
||||
FALSE, /* has_curve_to */
|
||||
NULL, {{0}} /* buf_tail, buf_head */
|
||||
}}
|
||||
};
|
||||
|
||||
#include <assert.h>
|
||||
|
@ -195,18 +198,17 @@ cairo_create (cairo_surface_t *target)
|
|||
|
||||
cr->status = CAIRO_STATUS_SUCCESS;
|
||||
|
||||
_cairo_path_fixed_init (&cr->path);
|
||||
_cairo_user_data_array_init (&cr->user_data);
|
||||
|
||||
cr->gstate = cr->gstate_tail;
|
||||
_cairo_gstate_init (cr->gstate, target);
|
||||
|
||||
_cairo_path_fixed_init (cr->path);
|
||||
|
||||
if (target == NULL) {
|
||||
cr->gstate = NULL;
|
||||
_cairo_set_error (cr, CAIRO_STATUS_NULL_POINTER);
|
||||
return cr;
|
||||
}
|
||||
|
||||
cr->gstate = _cairo_gstate_create (target);
|
||||
if (cr->gstate == NULL)
|
||||
_cairo_set_error (cr, CAIRO_STATUS_NO_MEMORY);
|
||||
|
||||
return cr;
|
||||
}
|
||||
slim_hidden_def (cairo_create);
|
||||
|
@ -219,15 +221,15 @@ slim_hidden_def (cairo_create);
|
|||
* @cr from being destroyed until a matching call to cairo_destroy()
|
||||
* is made.
|
||||
*
|
||||
* The number of references to a #cairo_t can be get using
|
||||
* cairo_get_reference_count().
|
||||
*
|
||||
* Return value: the referenced #cairo_t.
|
||||
**/
|
||||
cairo_t *
|
||||
cairo_reference (cairo_t *cr)
|
||||
{
|
||||
if (cr == NULL)
|
||||
return NULL;
|
||||
|
||||
if (cr->ref_count == CAIRO_REF_COUNT_INVALID)
|
||||
if (cr == NULL || cr->ref_count == CAIRO_REF_COUNT_INVALID)
|
||||
return cr;
|
||||
|
||||
assert (cr->ref_count > 0);
|
||||
|
@ -248,10 +250,7 @@ cairo_reference (cairo_t *cr)
|
|||
void
|
||||
cairo_destroy (cairo_t *cr)
|
||||
{
|
||||
if (cr == NULL)
|
||||
return;
|
||||
|
||||
if (cr->ref_count == CAIRO_REF_COUNT_INVALID)
|
||||
if (cr == NULL || cr->ref_count == CAIRO_REF_COUNT_INVALID)
|
||||
return;
|
||||
|
||||
assert (cr->ref_count > 0);
|
||||
|
@ -260,19 +259,96 @@ cairo_destroy (cairo_t *cr)
|
|||
if (cr->ref_count)
|
||||
return;
|
||||
|
||||
while (cr->gstate) {
|
||||
while (cr->gstate != cr->gstate_tail) {
|
||||
cairo_gstate_t *tmp = cr->gstate;
|
||||
cr->gstate = tmp->next;
|
||||
|
||||
_cairo_gstate_destroy (tmp);
|
||||
}
|
||||
|
||||
_cairo_path_fixed_fini (&cr->path);
|
||||
_cairo_gstate_fini (cr->gstate);
|
||||
|
||||
_cairo_path_fixed_fini (cr->path);
|
||||
|
||||
_cairo_user_data_array_fini (&cr->user_data);
|
||||
|
||||
free (cr);
|
||||
}
|
||||
slim_hidden_def (cairo_destroy);
|
||||
|
||||
/**
|
||||
* cairo_get_user_data:
|
||||
* @cr: a #cairo_t
|
||||
* @key: the address of the #cairo_user_data_key_t the user data was
|
||||
* attached to
|
||||
*
|
||||
* Return user data previously attached to @cr using the specified
|
||||
* key. If no user data has been attached with the given key this
|
||||
* function returns %NULL.
|
||||
*
|
||||
* Return value: the user data previously attached or %NULL.
|
||||
*
|
||||
* Since: 1.4
|
||||
**/
|
||||
void *
|
||||
cairo_get_user_data (cairo_t *cr,
|
||||
const cairo_user_data_key_t *key)
|
||||
{
|
||||
return _cairo_user_data_array_get_data (&cr->user_data,
|
||||
key);
|
||||
}
|
||||
|
||||
/**
|
||||
* cairo_set_user_data:
|
||||
* @cr: a #cairo_t
|
||||
* @key: the address of a #cairo_user_data_key_t to attach the user data to
|
||||
* @user_data: the user data to attach to the #cairo_t
|
||||
* @destroy: a #cairo_destroy_func_t which will be called when the
|
||||
* #cairo_t is destroyed or when new user data is attached using the
|
||||
* same key.
|
||||
*
|
||||
* Attach user data to @cr. To remove user data from a surface,
|
||||
* call this function with the key that was used to set it and %NULL
|
||||
* for @data.
|
||||
*
|
||||
* Return value: %CAIRO_STATUS_SUCCESS or %CAIRO_STATUS_NO_MEMORY if a
|
||||
* slot could not be allocated for the user data.
|
||||
*
|
||||
* Since: 1.4
|
||||
**/
|
||||
cairo_status_t
|
||||
cairo_set_user_data (cairo_t *cr,
|
||||
const cairo_user_data_key_t *key,
|
||||
void *user_data,
|
||||
cairo_destroy_func_t destroy)
|
||||
{
|
||||
if (cr->ref_count == CAIRO_REF_COUNT_INVALID)
|
||||
return CAIRO_STATUS_NO_MEMORY;
|
||||
|
||||
return _cairo_user_data_array_set_data (&cr->user_data,
|
||||
key, user_data, destroy);
|
||||
}
|
||||
|
||||
/**
|
||||
* cairo_get_reference_count:
|
||||
* @cr: a #cairo_t
|
||||
*
|
||||
* Returns the current reference count of @cr.
|
||||
*
|
||||
* Return value: the current reference count of @cr. If the
|
||||
* object is a nil object, 0 will be returned.
|
||||
*
|
||||
* Since: 1.4
|
||||
**/
|
||||
unsigned int
|
||||
cairo_get_reference_count (cairo_t *cr)
|
||||
{
|
||||
if (cr == NULL || cr->ref_count == CAIRO_REF_COUNT_INVALID)
|
||||
return 0;
|
||||
|
||||
return cr->ref_count;
|
||||
}
|
||||
|
||||
/**
|
||||
* cairo_save:
|
||||
* @cr: a #cairo_t
|
||||
|
@ -325,13 +401,15 @@ cairo_restore (cairo_t *cr)
|
|||
if (cr->status)
|
||||
return;
|
||||
|
||||
if (cr->gstate == cr->gstate_tail) {
|
||||
_cairo_set_error (cr, CAIRO_STATUS_INVALID_RESTORE);
|
||||
return;
|
||||
}
|
||||
|
||||
top = cr->gstate;
|
||||
cr->gstate = top->next;
|
||||
|
||||
_cairo_gstate_destroy (top);
|
||||
|
||||
if (cr->gstate == NULL)
|
||||
_cairo_set_error (cr, CAIRO_STATUS_INVALID_RESTORE);
|
||||
}
|
||||
slim_hidden_def(cairo_restore);
|
||||
|
||||
|
@ -855,8 +933,8 @@ cairo_set_line_width (cairo_t *cr, double width)
|
|||
|
||||
/**
|
||||
* cairo_set_line_cap:
|
||||
* @cr: a cairo context, as a #cairo_t
|
||||
* @line_cap: a line cap style, as a #cairo_line_cap_t
|
||||
* @cr: a cairo context
|
||||
* @line_cap: a line cap style
|
||||
*
|
||||
* Sets the current line cap style within the cairo context. See
|
||||
* #cairo_line_cap_t for details about how the available line cap
|
||||
|
@ -880,8 +958,8 @@ cairo_set_line_cap (cairo_t *cr, cairo_line_cap_t line_cap)
|
|||
|
||||
/**
|
||||
* cairo_set_line_join:
|
||||
* @cr: a cairo context, as a #cairo_t
|
||||
* @line_join: a line joint style, as a #cairo_line_join_t
|
||||
* @cr: a cairo context
|
||||
* @line_join: a line joint style
|
||||
*
|
||||
* Sets the current line join style within the cairo context. See
|
||||
* #cairo_line_join_t for details about how the available line join
|
||||
|
@ -954,11 +1032,13 @@ cairo_set_dash (cairo_t *cr,
|
|||
* cairo_get_dash_count:
|
||||
* @cr: a #cairo_t
|
||||
*
|
||||
* Returns the length of the dash array in @cr (0 if dashing is not
|
||||
* currently in effect).
|
||||
* This function returns the length of the dash array in @cr (0 if dashing
|
||||
* is not currently in effect).
|
||||
*
|
||||
* See also cairo_set_dash() and cairo_get_dash().
|
||||
*
|
||||
* Return value: the length of the dash array, or 0 if no dash array set.
|
||||
*
|
||||
* Since: 1.4
|
||||
*/
|
||||
int
|
||||
|
@ -993,6 +1073,25 @@ cairo_get_dash (cairo_t *cr,
|
|||
*offset = cr->gstate->stroke_style.dash_offset;
|
||||
}
|
||||
|
||||
/**
|
||||
* cairo_set_miter_limit:
|
||||
* @cr: a cairo context
|
||||
* @limit: miter limit to set
|
||||
*
|
||||
* Sets the current miter limit within the cairo context.
|
||||
*
|
||||
* If the current line join style is set to %CAIRO_LINE_JOIN_MITER
|
||||
* (see cairo_set_line_join()), the miter limit is used to determine
|
||||
* whether the lines should be joined with a bevel instead of a miter.
|
||||
* Cairo divides the length of the miter by the line width.
|
||||
* If the result is greater than the miter limit, the style is
|
||||
* converted to a bevel.
|
||||
*
|
||||
* As with the other stroke parameters, the current line miter limit is
|
||||
* examined by cairo_stroke(), cairo_stroke_extents(), and
|
||||
* cairo_stroke_to_path(), but does not have any effect during path
|
||||
* construction.
|
||||
**/
|
||||
void
|
||||
cairo_set_miter_limit (cairo_t *cr, double limit)
|
||||
{
|
||||
|
@ -1048,6 +1147,7 @@ cairo_scale (cairo_t *cr, double sx, double sy)
|
|||
if (cr->status)
|
||||
_cairo_set_error (cr, cr->status);
|
||||
}
|
||||
slim_hidden_def (cairo_scale);
|
||||
|
||||
/**
|
||||
* cairo_rotate:
|
||||
|
@ -1232,7 +1332,7 @@ cairo_new_path (cairo_t *cr)
|
|||
if (cr->status)
|
||||
return;
|
||||
|
||||
_cairo_path_fixed_fini (&cr->path);
|
||||
_cairo_path_fixed_fini (cr->path);
|
||||
}
|
||||
slim_hidden_def(cairo_new_path);
|
||||
|
||||
|
@ -1257,7 +1357,7 @@ cairo_move_to (cairo_t *cr, double x, double y)
|
|||
x_fixed = _cairo_fixed_from_double (x);
|
||||
y_fixed = _cairo_fixed_from_double (y);
|
||||
|
||||
cr->status = _cairo_path_fixed_move_to (&cr->path, x_fixed, y_fixed);
|
||||
cr->status = _cairo_path_fixed_move_to (cr->path, x_fixed, y_fixed);
|
||||
if (cr->status)
|
||||
_cairo_set_error (cr, cr->status);
|
||||
}
|
||||
|
@ -1287,7 +1387,7 @@ cairo_new_sub_path (cairo_t *cr)
|
|||
if (cr->status)
|
||||
return;
|
||||
|
||||
_cairo_path_fixed_new_sub_path (&cr->path);
|
||||
_cairo_path_fixed_new_sub_path (cr->path);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -1315,7 +1415,7 @@ cairo_line_to (cairo_t *cr, double x, double y)
|
|||
x_fixed = _cairo_fixed_from_double (x);
|
||||
y_fixed = _cairo_fixed_from_double (y);
|
||||
|
||||
cr->status = _cairo_path_fixed_line_to (&cr->path, x_fixed, y_fixed);
|
||||
cr->status = _cairo_path_fixed_line_to (cr->path, x_fixed, y_fixed);
|
||||
if (cr->status)
|
||||
_cairo_set_error (cr, cr->status);
|
||||
}
|
||||
|
@ -1366,7 +1466,7 @@ cairo_curve_to (cairo_t *cr,
|
|||
x3_fixed = _cairo_fixed_from_double (x3);
|
||||
y3_fixed = _cairo_fixed_from_double (y3);
|
||||
|
||||
cr->status = _cairo_path_fixed_curve_to (&cr->path,
|
||||
cr->status = _cairo_path_fixed_curve_to (cr->path,
|
||||
x1_fixed, y1_fixed,
|
||||
x2_fixed, y2_fixed,
|
||||
x3_fixed, y3_fixed);
|
||||
|
@ -1532,7 +1632,7 @@ cairo_rel_move_to (cairo_t *cr, double dx, double dy)
|
|||
dx_fixed = _cairo_fixed_from_double (dx);
|
||||
dy_fixed = _cairo_fixed_from_double (dy);
|
||||
|
||||
cr->status = _cairo_path_fixed_rel_move_to (&cr->path, dx_fixed, dy_fixed);
|
||||
cr->status = _cairo_path_fixed_rel_move_to (cr->path, dx_fixed, dy_fixed);
|
||||
if (cr->status)
|
||||
_cairo_set_error (cr, cr->status);
|
||||
}
|
||||
|
@ -1567,7 +1667,7 @@ cairo_rel_line_to (cairo_t *cr, double dx, double dy)
|
|||
dx_fixed = _cairo_fixed_from_double (dx);
|
||||
dy_fixed = _cairo_fixed_from_double (dy);
|
||||
|
||||
cr->status = _cairo_path_fixed_rel_line_to (&cr->path, dx_fixed, dy_fixed);
|
||||
cr->status = _cairo_path_fixed_rel_line_to (cr->path, dx_fixed, dy_fixed);
|
||||
if (cr->status)
|
||||
_cairo_set_error (cr, cr->status);
|
||||
}
|
||||
|
@ -1625,7 +1725,7 @@ cairo_rel_curve_to (cairo_t *cr,
|
|||
dx3_fixed = _cairo_fixed_from_double (dx3);
|
||||
dy3_fixed = _cairo_fixed_from_double (dy3);
|
||||
|
||||
cr->status = _cairo_path_fixed_rel_curve_to (&cr->path,
|
||||
cr->status = _cairo_path_fixed_rel_curve_to (cr->path,
|
||||
dx1_fixed, dy1_fixed,
|
||||
dx2_fixed, dy2_fixed,
|
||||
dx3_fixed, dy3_fixed);
|
||||
|
@ -1713,7 +1813,7 @@ cairo_close_path (cairo_t *cr)
|
|||
if (cr->status)
|
||||
return;
|
||||
|
||||
cr->status = _cairo_path_fixed_close_path (&cr->path);
|
||||
cr->status = _cairo_path_fixed_close_path (cr->path);
|
||||
if (cr->status)
|
||||
_cairo_set_error (cr, cr->status);
|
||||
}
|
||||
|
@ -1903,7 +2003,7 @@ cairo_stroke_preserve (cairo_t *cr)
|
|||
if (cr->status)
|
||||
return;
|
||||
|
||||
cr->status = _cairo_gstate_stroke (cr->gstate, &cr->path);
|
||||
cr->status = _cairo_gstate_stroke (cr->gstate, cr->path);
|
||||
if (cr->status)
|
||||
_cairo_set_error (cr, cr->status);
|
||||
}
|
||||
|
@ -1944,7 +2044,7 @@ cairo_fill_preserve (cairo_t *cr)
|
|||
if (cr->status)
|
||||
return;
|
||||
|
||||
cr->status = _cairo_gstate_fill (cr->gstate, &cr->path);
|
||||
cr->status = _cairo_gstate_fill (cr->gstate, cr->path);
|
||||
if (cr->status)
|
||||
_cairo_set_error (cr, cr->status);
|
||||
}
|
||||
|
@ -2014,7 +2114,7 @@ cairo_in_stroke (cairo_t *cr, double x, double y)
|
|||
return 0;
|
||||
|
||||
cr->status = _cairo_gstate_in_stroke (cr->gstate,
|
||||
&cr->path,
|
||||
cr->path,
|
||||
x, y, &inside);
|
||||
if (cr->status)
|
||||
return 0;
|
||||
|
@ -2046,7 +2146,7 @@ cairo_in_fill (cairo_t *cr, double x, double y)
|
|||
return 0;
|
||||
|
||||
cr->status = _cairo_gstate_in_fill (cr->gstate,
|
||||
&cr->path,
|
||||
cr->path,
|
||||
x, y, &inside);
|
||||
if (cr->status) {
|
||||
_cairo_set_error (cr, cr->status);
|
||||
|
@ -2082,7 +2182,7 @@ cairo_stroke_extents (cairo_t *cr,
|
|||
return;
|
||||
|
||||
cr->status = _cairo_gstate_stroke_extents (cr->gstate,
|
||||
&cr->path,
|
||||
cr->path,
|
||||
x1, y1, x2, y2);
|
||||
if (cr->status)
|
||||
_cairo_set_error (cr, cr->status);
|
||||
|
@ -2112,7 +2212,7 @@ cairo_fill_extents (cairo_t *cr,
|
|||
return;
|
||||
|
||||
cr->status = _cairo_gstate_fill_extents (cr->gstate,
|
||||
&cr->path,
|
||||
cr->path,
|
||||
x1, y1, x2, y2);
|
||||
if (cr->status)
|
||||
_cairo_set_error (cr, cr->status);
|
||||
|
@ -2176,7 +2276,7 @@ cairo_clip_preserve (cairo_t *cr)
|
|||
if (cr->status)
|
||||
return;
|
||||
|
||||
cr->status = _cairo_gstate_clip (cr->gstate, &cr->path);
|
||||
cr->status = _cairo_gstate_clip (cr->gstate, cr->path);
|
||||
if (cr->status)
|
||||
_cairo_set_error (cr, cr->status);
|
||||
}
|
||||
|
@ -2251,8 +2351,9 @@ _cairo_rectangle_list_create_in_error (cairo_status_t status)
|
|||
|
||||
/**
|
||||
* cairo_copy_clip_rectangle_list:
|
||||
* @cr: a cairo context
|
||||
*
|
||||
* Returns the current clip region as a list of rectangles in user coordinates.
|
||||
* Gets the current clip region as a list of rectangles in user coordinates.
|
||||
* Never returns %NULL.
|
||||
*
|
||||
* The status in the list may be CAIRO_STATUS_CLIP_NOT_REPRESENTABLE to
|
||||
|
@ -2263,6 +2364,8 @@ _cairo_rectangle_list_create_in_error (cairo_status_t status)
|
|||
* The caller must always call cairo_rectangle_list_destroy on the result of
|
||||
* this function.
|
||||
*
|
||||
* Returns: the current clip region as a list of rectangles in user coordinates.
|
||||
*
|
||||
* Since: 1.4
|
||||
**/
|
||||
cairo_rectangle_list_t *
|
||||
|
@ -2303,34 +2406,6 @@ cairo_select_font_face (cairo_t *cr,
|
|||
_cairo_set_error (cr, cr->status);
|
||||
}
|
||||
|
||||
/**
|
||||
* cairo_get_font_face:
|
||||
* @cr: a #cairo_t
|
||||
*
|
||||
* Gets the current font face for a #cairo_t.
|
||||
*
|
||||
* Return value: the current font object. Can return %NULL
|
||||
* on out-of-memory or if the context is already in
|
||||
* an error state. This object is owned by cairo. To keep
|
||||
* a reference to it, you must call cairo_font_face_reference().
|
||||
**/
|
||||
cairo_font_face_t *
|
||||
cairo_get_font_face (cairo_t *cr)
|
||||
{
|
||||
cairo_font_face_t *font_face;
|
||||
|
||||
if (cr->status)
|
||||
return (cairo_font_face_t*) &_cairo_font_face_nil;
|
||||
|
||||
cr->status = _cairo_gstate_get_font_face (cr->gstate, &font_face);
|
||||
if (cr->status) {
|
||||
_cairo_set_error (cr, cr->status);
|
||||
return (cairo_font_face_t*) &_cairo_font_face_nil;
|
||||
}
|
||||
|
||||
return font_face;
|
||||
}
|
||||
|
||||
/**
|
||||
* cairo_font_extents:
|
||||
* @cr: a #cairo_t
|
||||
|
@ -2372,6 +2447,41 @@ cairo_set_font_face (cairo_t *cr,
|
|||
_cairo_set_error (cr, cr->status);
|
||||
}
|
||||
|
||||
/**
|
||||
* cairo_get_font_face:
|
||||
* @cr: a #cairo_t
|
||||
*
|
||||
* Gets the current font face for a #cairo_t.
|
||||
*
|
||||
* Return value: the current font face. This object is owned by
|
||||
* cairo. To keep a reference to it, you must call
|
||||
* cairo_font_face_reference.
|
||||
*
|
||||
* This function never returns %NULL. If memory cannot be allocated, a
|
||||
* special "nil" #cairo_font_face_t object will be returned on which
|
||||
* cairo_font_face_status() returns %CAIRO_STATUS_NO_MEMORY. Using
|
||||
* this nil object will cause its error state to propagate to other
|
||||
* objects it is passed to, (for example, calling
|
||||
* cairo_set_font_face() with a nil font will trigger an error that
|
||||
* will shutdown the cairo_t object).
|
||||
**/
|
||||
cairo_font_face_t *
|
||||
cairo_get_font_face (cairo_t *cr)
|
||||
{
|
||||
cairo_font_face_t *font_face;
|
||||
|
||||
if (cr->status)
|
||||
return (cairo_font_face_t*) &_cairo_font_face_nil;
|
||||
|
||||
cr->status = _cairo_gstate_get_font_face (cr->gstate, &font_face);
|
||||
if (cr->status) {
|
||||
_cairo_set_error (cr, cr->status);
|
||||
return (cairo_font_face_t*) &_cairo_font_face_nil;
|
||||
}
|
||||
|
||||
return font_face;
|
||||
}
|
||||
|
||||
/**
|
||||
* cairo_set_font_size:
|
||||
* @cr: a #cairo_t
|
||||
|
@ -2516,6 +2626,43 @@ BAIL:
|
|||
_cairo_set_error (cr, cr->status);
|
||||
}
|
||||
|
||||
/**
|
||||
* cairo_get_scaled_font:
|
||||
* @cr: a #cairo_t
|
||||
*
|
||||
* Gets the current scaled font for a #cairo_t.
|
||||
*
|
||||
* Return value: the current scaled font. This object is owned by
|
||||
* cairo. To keep a reference to it, you must call
|
||||
* cairo_scaled_font_reference().
|
||||
*
|
||||
* This function never returns %NULL. If memory cannot be allocated, a
|
||||
* special "nil" #cairo_scaled_font_t object will be returned on which
|
||||
* cairo_scaled_font_status() returns %CAIRO_STATUS_NO_MEMORY. Using
|
||||
* this nil object will cause its error state to propagate to other
|
||||
* objects it is passed to, (for example, calling
|
||||
* cairo_set_scaled_font() with a nil font will trigger an error that
|
||||
* will shutdown the cairo_t object).
|
||||
*
|
||||
* Since: 1.4
|
||||
**/
|
||||
cairo_scaled_font_t *
|
||||
cairo_get_scaled_font (cairo_t *cr)
|
||||
{
|
||||
cairo_scaled_font_t *scaled_font;
|
||||
|
||||
if (cr->status)
|
||||
return (cairo_scaled_font_t *)&_cairo_scaled_font_nil;
|
||||
|
||||
cr->status = _cairo_gstate_get_scaled_font (cr->gstate, &scaled_font);
|
||||
if (cr->status) {
|
||||
_cairo_set_error (cr, cr->status);
|
||||
return (cairo_scaled_font_t *)&_cairo_scaled_font_nil;
|
||||
}
|
||||
|
||||
return scaled_font;
|
||||
}
|
||||
|
||||
/**
|
||||
* cairo_text_extents:
|
||||
* @cr: a #cairo_t
|
||||
|
@ -2635,9 +2782,9 @@ cairo_glyph_extents (cairo_t *cr,
|
|||
*
|
||||
* NOTE: The cairo_show_text() function call is part of what the cairo
|
||||
* designers call the "toy" text API. It is convenient for short demos
|
||||
* and simple programs, but it is not expected to be adequate for the
|
||||
* most serious of text-using applications. See cairo_show_glyphs()
|
||||
* for the "real" text display API in cairo.
|
||||
* and simple programs, but it is not expected to be adequate for
|
||||
* serious text-using applications. See cairo_show_glyphs() for the
|
||||
* "real" text display API in cairo.
|
||||
**/
|
||||
void
|
||||
cairo_show_text (cairo_t *cr, const char *utf8)
|
||||
|
@ -2687,6 +2834,16 @@ cairo_show_text (cairo_t *cr, const char *utf8)
|
|||
_cairo_set_error (cr, cr->status);
|
||||
}
|
||||
|
||||
/**
|
||||
* cairo_show_glyphs:
|
||||
* @cr: a cairo context
|
||||
* @glyphs: array of glyphs to show
|
||||
* @num_glyphs: number of glyphs to show
|
||||
*
|
||||
* A drawing operator that generates the shape from an array of glyphs,
|
||||
* rendered according to the current font_face, font_size
|
||||
* (font_matrix), and font_options.
|
||||
**/
|
||||
void
|
||||
cairo_show_glyphs (cairo_t *cr, const cairo_glyph_t *glyphs, int num_glyphs)
|
||||
{
|
||||
|
@ -2701,10 +2858,35 @@ cairo_show_glyphs (cairo_t *cr, const cairo_glyph_t *glyphs, int num_glyphs)
|
|||
_cairo_set_error (cr, cr->status);
|
||||
}
|
||||
|
||||
/**
|
||||
* cairo_text_path:
|
||||
* @cr: a cairo context
|
||||
* @utf8: a string of text encoded in UTF-8
|
||||
*
|
||||
* Adds closed paths for text to the current path. The generated
|
||||
* path if filled, achieves an effect similar to that of
|
||||
* cairo_show_text().
|
||||
*
|
||||
* Text conversion and positioning is done similar to cairo_show_text().
|
||||
*
|
||||
* Like cairo_show_text(), After this call the current point is
|
||||
* moved to the origin of where the next glyph would be placed in
|
||||
* this same progression. That is, the current point will be at
|
||||
* the origin of the final glyph offset by its advance values.
|
||||
* This allows for chaining multiple calls to to cairo_text_path()
|
||||
* without having to set current point in between.
|
||||
*
|
||||
* NOTE: The cairo_text_path() function call is part of what the cairo
|
||||
* designers call the "toy" text API. It is convenient for short demos
|
||||
* and simple programs, but it is not expected to be adequate for
|
||||
* serious text-using applications. See cairo_glyph_path() for the
|
||||
* "real" text path API in cairo.
|
||||
**/
|
||||
void
|
||||
cairo_text_path (cairo_t *cr, const char *utf8)
|
||||
{
|
||||
cairo_glyph_t *glyphs = NULL;
|
||||
cairo_text_extents_t extents;
|
||||
cairo_glyph_t *glyphs = NULL, *last_glyph;
|
||||
int num_glyphs;
|
||||
double x, y;
|
||||
|
||||
|
@ -2717,16 +2899,32 @@ cairo_text_path (cairo_t *cr, const char *utf8)
|
|||
x, y,
|
||||
&glyphs, &num_glyphs);
|
||||
|
||||
if (cr->status) {
|
||||
if (glyphs)
|
||||
free (glyphs);
|
||||
_cairo_set_error (cr, cr->status);
|
||||
if (cr->status)
|
||||
goto BAIL;
|
||||
|
||||
if (num_glyphs == 0)
|
||||
return;
|
||||
}
|
||||
|
||||
cr->status = _cairo_gstate_glyph_path (cr->gstate,
|
||||
glyphs, num_glyphs,
|
||||
&cr->path);
|
||||
cr->path);
|
||||
|
||||
if (cr->status)
|
||||
goto BAIL;
|
||||
|
||||
last_glyph = &glyphs[num_glyphs - 1];
|
||||
cr->status = _cairo_gstate_glyph_extents (cr->gstate,
|
||||
last_glyph, 1,
|
||||
&extents);
|
||||
|
||||
if (cr->status)
|
||||
goto BAIL;
|
||||
|
||||
x = last_glyph->x + extents.x_advance;
|
||||
y = last_glyph->y + extents.y_advance;
|
||||
cairo_move_to (cr, x, y);
|
||||
|
||||
BAIL:
|
||||
if (glyphs)
|
||||
free (glyphs);
|
||||
|
||||
|
@ -2734,6 +2932,16 @@ cairo_text_path (cairo_t *cr, const char *utf8)
|
|||
_cairo_set_error (cr, cr->status);
|
||||
}
|
||||
|
||||
/**
|
||||
* cairo_glyph_path:
|
||||
* @cr: a cairo context
|
||||
* @glyphs: array of glyphs to show
|
||||
* @num_glyphs: number of glyphs to show
|
||||
*
|
||||
* Adds closed paths for the glyphs to the current path. The generated
|
||||
* path if filled, achieves an effect similar to that of
|
||||
* cairo_show_glyphs().
|
||||
**/
|
||||
void
|
||||
cairo_glyph_path (cairo_t *cr, const cairo_glyph_t *glyphs, int num_glyphs)
|
||||
{
|
||||
|
@ -2742,7 +2950,7 @@ cairo_glyph_path (cairo_t *cr, const cairo_glyph_t *glyphs, int num_glyphs)
|
|||
|
||||
cr->status = _cairo_gstate_glyph_path (cr->gstate,
|
||||
glyphs, num_glyphs,
|
||||
&cr->path);
|
||||
cr->path);
|
||||
if (cr->status)
|
||||
_cairo_set_error (cr, cr->status);
|
||||
}
|
||||
|
@ -2818,7 +3026,7 @@ cairo_get_current_point (cairo_t *cr, double *x_ret, double *y_ret)
|
|||
cairo_fixed_t x_fixed, y_fixed;
|
||||
double x, y;
|
||||
|
||||
status = _cairo_path_fixed_get_current_point (&cr->path, &x_fixed, &y_fixed);
|
||||
status = _cairo_path_fixed_get_current_point (cr->path, &x_fixed, &y_fixed);
|
||||
if (status == CAIRO_STATUS_NO_CURRENT_POINT) {
|
||||
x = 0.0;
|
||||
y = 0.0;
|
||||
|
@ -2853,10 +3061,12 @@ cairo_get_fill_rule (cairo_t *cr)
|
|||
* cairo_get_line_width:
|
||||
* @cr: a cairo context
|
||||
*
|
||||
* Return value: the current line width value exactly as set by
|
||||
* This function returns the current line width value exactly as set by
|
||||
* cairo_set_line_width(). Note that the value is unchanged even if
|
||||
* the CTM has changed between the calls to cairo_set_line_width() and
|
||||
* cairo_get_line_width().
|
||||
*
|
||||
* Return value: the current line width.
|
||||
**/
|
||||
double
|
||||
cairo_get_line_width (cairo_t *cr)
|
||||
|
@ -3008,7 +3218,7 @@ cairo_copy_path (cairo_t *cr)
|
|||
if (cr->status)
|
||||
return _cairo_path_create_in_error (cr->status);
|
||||
|
||||
return _cairo_path_create (&cr->path, cr->gstate);
|
||||
return _cairo_path_create (cr->path, cr->gstate);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -3050,7 +3260,7 @@ cairo_copy_path_flat (cairo_t *cr)
|
|||
if (cr->status)
|
||||
return _cairo_path_create_in_error (cr->status);
|
||||
|
||||
return _cairo_path_create_flat (&cr->path, cr->gstate);
|
||||
return _cairo_path_create_flat (cr->path, cr->gstate);
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -72,7 +72,7 @@ cairo_version_string (void);
|
|||
* /<!-- -->* do something *<!-- -->/
|
||||
* }
|
||||
* </programlisting></informalexample>
|
||||
*/
|
||||
**/
|
||||
typedef int cairo_bool_t;
|
||||
|
||||
/**
|
||||
|
@ -80,6 +80,13 @@ typedef int cairo_bool_t;
|
|||
*
|
||||
* A #cairo_t contains the current state of the rendering device,
|
||||
* including coordinates of yet to be drawn shapes.
|
||||
*
|
||||
* Cairo contexts, as #cairo_t objects are named, are central to
|
||||
* cairo and all drawing with cairo is always done to a #cairo_t
|
||||
* object.
|
||||
*
|
||||
* Memory management of #cairo_t is done with
|
||||
* cairo_reference() and cairo_destroy().
|
||||
**/
|
||||
typedef struct _cairo cairo_t;
|
||||
|
||||
|
@ -88,13 +95,17 @@ typedef struct _cairo cairo_t;
|
|||
*
|
||||
* A #cairo_surface_t represents an image, either as the destination
|
||||
* of a drawing operation or as source when drawing onto another
|
||||
* surface. There are different subtypes of cairo_surface_t for
|
||||
* surface. To draw to a #cairo_surface_t, create a cairo context
|
||||
* with the surface as the target, using cairo_create().
|
||||
*
|
||||
* There are different subtypes of #cairo_surface_t for
|
||||
* different drawing backends; for example, cairo_image_surface_create()
|
||||
* creates a bitmap image in memory.
|
||||
* The type of a surface can be queried with cairo_surface_get_type().
|
||||
*
|
||||
* Memory management of #cairo_surface_t is done with
|
||||
* cairo_surface_reference() and cairo_surface_destroy().
|
||||
*/
|
||||
**/
|
||||
typedef struct _cairo_surface cairo_surface_t;
|
||||
|
||||
/**
|
||||
|
@ -120,6 +131,25 @@ typedef struct _cairo_matrix {
|
|||
double x0; double y0;
|
||||
} cairo_matrix_t;
|
||||
|
||||
/**
|
||||
* cairo_pattern_t:
|
||||
*
|
||||
* A #cairo_pattern_t represents a source when drawing onto a
|
||||
* surface. There are different subtypes of #cairo_pattern_t,
|
||||
* for different types of sources; for example,
|
||||
* cairo_pattern_create_rgb() creates a pattern for a solid
|
||||
* opaque color.
|
||||
*
|
||||
* Other than various cairo_pattern_create_<emphasis>type</emphasis>
|
||||
* functions, some of the pattern types can be implicitly created
|
||||
* using vairous cairo_set_source_<emphasis>type</emphasis> functions;
|
||||
* for example cairo_set_source_rgb().
|
||||
*
|
||||
* The type of a pattern can be queried with cairo_pattern_get_type().
|
||||
*
|
||||
* Memory management of #cairo_pattern_t is done with
|
||||
* cairo_pattern_reference() and cairo_pattern_destroy().
|
||||
**/
|
||||
typedef struct _cairo_pattern cairo_pattern_t;
|
||||
|
||||
/**
|
||||
|
@ -129,7 +159,7 @@ typedef struct _cairo_pattern cairo_pattern_t;
|
|||
* #cairo_destroy_func_t the type of function which is called when a
|
||||
* data element is destroyed. It is passed the pointer to the data
|
||||
* element and should free any memory and resources allocated for it.
|
||||
*/
|
||||
**/
|
||||
typedef void (*cairo_destroy_func_t) (void *data);
|
||||
|
||||
/**
|
||||
|
@ -141,7 +171,7 @@ typedef void (*cairo_destroy_func_t) (void *data);
|
|||
* and there is no need to initialize the object; only the unique
|
||||
* address of a #cairo_data_key_t object is used. Typically, you
|
||||
* would just use the address of a static #cairo_data_key_t object.
|
||||
*/
|
||||
**/
|
||||
typedef struct _cairo_user_data_key {
|
||||
int unused;
|
||||
} cairo_user_data_key_t;
|
||||
|
@ -219,7 +249,7 @@ typedef enum _cairo_status {
|
|||
* Note: The large values here are designed to keep cairo_content_t
|
||||
* values distinct from cairo_format_t values so that the
|
||||
* implementation can detect the error if users confuse the two types.
|
||||
*/
|
||||
**/
|
||||
typedef enum _cairo_content {
|
||||
CAIRO_CONTENT_COLOR = 0x1000,
|
||||
CAIRO_CONTENT_ALPHA = 0x2000,
|
||||
|
@ -241,7 +271,7 @@ typedef enum _cairo_content {
|
|||
* CAIRO_STATUS_WRITE_ERROR otherwise.
|
||||
*
|
||||
* Returns: the status code of the write operation
|
||||
*/
|
||||
**/
|
||||
typedef cairo_status_t (*cairo_write_func_t) (void *closure,
|
||||
const unsigned char *data,
|
||||
unsigned int length);
|
||||
|
@ -261,7 +291,7 @@ typedef cairo_status_t (*cairo_write_func_t) (void *closure,
|
|||
* CAIRO_STATUS_READ_ERROR otherwise.
|
||||
*
|
||||
* Returns: the status code of the read operation
|
||||
*/
|
||||
**/
|
||||
typedef cairo_status_t (*cairo_read_func_t) (void *closure,
|
||||
unsigned char *data,
|
||||
unsigned int length);
|
||||
|
@ -276,6 +306,19 @@ cairo_reference (cairo_t *cr);
|
|||
cairo_public void
|
||||
cairo_destroy (cairo_t *cr);
|
||||
|
||||
cairo_public unsigned int
|
||||
cairo_get_reference_count (cairo_t *cr);
|
||||
|
||||
cairo_public void *
|
||||
cairo_get_user_data (cairo_t *cr,
|
||||
const cairo_user_data_key_t *key);
|
||||
|
||||
cairo_public cairo_status_t
|
||||
cairo_set_user_data (cairo_t *cr,
|
||||
const cairo_user_data_key_t *key,
|
||||
void *user_data,
|
||||
cairo_destroy_func_t destroy);
|
||||
|
||||
cairo_public void
|
||||
cairo_save (cairo_t *cr);
|
||||
|
||||
|
@ -402,7 +445,7 @@ cairo_set_line_width (cairo_t *cr, double width);
|
|||
* @CAIRO_LINE_CAP_ROUND: use a round ending, the center of the circle is the end point
|
||||
* @CAIRO_LINE_CAP_SQUARE: use squared ending, the center of the square is the end point
|
||||
*
|
||||
* enumeration for style of line-endings
|
||||
* Specifies how to render the endpoint of a line when stroking.
|
||||
**/
|
||||
typedef enum _cairo_line_cap {
|
||||
CAIRO_LINE_CAP_BUTT,
|
||||
|
@ -413,6 +456,17 @@ typedef enum _cairo_line_cap {
|
|||
cairo_public void
|
||||
cairo_set_line_cap (cairo_t *cr, cairo_line_cap_t line_cap);
|
||||
|
||||
/**
|
||||
* cairo_line_join_t
|
||||
* @CAIRO_LINE_JOIN_MITER: use a sharp (angled) corner, see
|
||||
* cairo_set_miter_limit()
|
||||
* @CAIRO_LINE_JOIN_ROUND: use a rounded join, the center of the circle is the
|
||||
* joint point
|
||||
* @CAIRO_LINE_JOIN_BEVEL: use a cut-off join, the join is cut off at half
|
||||
* the line width from the joint point
|
||||
*
|
||||
* Specifies how to render the junction of two lines when stroking.
|
||||
**/
|
||||
typedef enum _cairo_line_join {
|
||||
CAIRO_LINE_JOIN_MITER,
|
||||
CAIRO_LINE_JOIN_ROUND,
|
||||
|
@ -598,23 +652,30 @@ cairo_clip_extents (cairo_t *cr,
|
|||
|
||||
/**
|
||||
* cairo_rectangle_t:
|
||||
* @x: X coordinate of the left side of the rectangle
|
||||
* @y: Y coordinate of the the top side of the rectangle
|
||||
* @width: width of the rectangle
|
||||
* @height: height of the rectangle
|
||||
*
|
||||
* A data structure for holding a rectangle.
|
||||
*
|
||||
* Since: 1.4
|
||||
*/
|
||||
**/
|
||||
typedef struct _cairo_rectangle {
|
||||
double x, y, width, height;
|
||||
} cairo_rectangle_t;
|
||||
|
||||
/**
|
||||
* cairo_rectangle_list_t:
|
||||
* @status: Error status of the rectangle list
|
||||
* @rectangles: Array containing the rectangles
|
||||
* @num_rectangles: Number of rectangles in this list
|
||||
*
|
||||
* A data structure for holding a dynamically allocated
|
||||
* array of rectangles.
|
||||
*
|
||||
* Since: 1.4
|
||||
*/
|
||||
**/
|
||||
typedef struct _cairo_rectangle_list {
|
||||
cairo_status_t status;
|
||||
cairo_rectangle_t *rectangles;
|
||||
|
@ -636,7 +697,14 @@ cairo_rectangle_list_destroy (cairo_rectangle_list_t *rectangle_list);
|
|||
* resolution. A cairo_scaled_font_t is most useful for low-level font
|
||||
* usage where a library or application wants to cache a reference
|
||||
* to a scaled font to speed up the computation of metrics.
|
||||
*/
|
||||
*
|
||||
* There are various types of scaled fonts, depending on the
|
||||
* <firstterm>font backend</firstterm> they use. The type of a
|
||||
* scaled font can be queried using cairo_scaled_font_get_type().
|
||||
*
|
||||
* Memory management of #cairo_scaled_font_t is done with
|
||||
* cairo_scaled_font_reference() and cairo_scaled_font_destroy().
|
||||
**/
|
||||
typedef struct _cairo_scaled_font cairo_scaled_font_t;
|
||||
|
||||
/**
|
||||
|
@ -648,7 +716,14 @@ typedef struct _cairo_scaled_font cairo_scaled_font_t;
|
|||
* directions) . A font face can be set on a #cairo_t by using
|
||||
* cairo_set_font_face(); the size and font matrix are set with
|
||||
* cairo_set_font_size() and cairo_set_font_matrix().
|
||||
*/
|
||||
*
|
||||
* There are various types of font faces, depending on the
|
||||
* <firstterm>font backend</firstterm> they use. The type of a
|
||||
* font face can be queried using cairo_font_face_get_type().
|
||||
*
|
||||
* Memory management of #cairo_font_face_t is done with
|
||||
* cairo_font_face_reference() and cairo_font_face_destroy().
|
||||
**/
|
||||
typedef struct _cairo_font_face cairo_font_face_t;
|
||||
|
||||
/**
|
||||
|
@ -707,7 +782,7 @@ typedef struct {
|
|||
* doubled. They will change slightly due to hinting (so you can't
|
||||
* assume that metrics are independent of the transformation matrix),
|
||||
* but otherwise will remain unchanged.
|
||||
*/
|
||||
**/
|
||||
typedef struct {
|
||||
double x_bearing;
|
||||
double y_bearing;
|
||||
|
@ -757,7 +832,7 @@ typedef struct {
|
|||
* not be doubled. They will change slightly due to hinting (so you
|
||||
* can't assume that metrics are independent of the transformation
|
||||
* matrix), but otherwise will remain unchanged.
|
||||
*/
|
||||
**/
|
||||
typedef struct {
|
||||
double ascent;
|
||||
double descent;
|
||||
|
@ -766,12 +841,27 @@ typedef struct {
|
|||
double max_y_advance;
|
||||
} cairo_font_extents_t;
|
||||
|
||||
/**
|
||||
* cairo_font_slant_t:
|
||||
* @CAIRO_FONT_SLANT_NORMAL: Upright font style
|
||||
* @CAIRO_FONT_SLANT_ITALIC: Italic font style
|
||||
* @CAIRO_FONT_SLANT_OBLIQUE: Oblique font style
|
||||
*
|
||||
* Specifies variants of a font face based on their slant.
|
||||
**/
|
||||
typedef enum _cairo_font_slant {
|
||||
CAIRO_FONT_SLANT_NORMAL,
|
||||
CAIRO_FONT_SLANT_ITALIC,
|
||||
CAIRO_FONT_SLANT_OBLIQUE
|
||||
} cairo_font_slant_t;
|
||||
|
||||
/**
|
||||
* cairo_font_weight_t:
|
||||
* @CAIRO_FONT_WEIGHT_NORMAL: Normal font weight
|
||||
* @CAIRO_FONT_WEIGHT_BOLD: Bold font weight
|
||||
*
|
||||
* Specifies variants of a font face based on their weight.
|
||||
**/
|
||||
typedef enum _cairo_font_weight {
|
||||
CAIRO_FONT_WEIGHT_NORMAL,
|
||||
CAIRO_FONT_WEIGHT_BOLD
|
||||
|
@ -823,7 +913,7 @@ typedef enum _cairo_subpixel_order {
|
|||
* styles are supported by all font backends.
|
||||
*
|
||||
* New entries may be added in future versions.
|
||||
*/
|
||||
**/
|
||||
typedef enum _cairo_hint_style {
|
||||
CAIRO_HINT_STYLE_DEFAULT,
|
||||
CAIRO_HINT_STYLE_NONE,
|
||||
|
@ -844,13 +934,33 @@ typedef enum _cairo_hint_style {
|
|||
* device space. Doing this improves the consistency of
|
||||
* letter and line spacing, however it also means that text
|
||||
* will be laid out differently at different zoom factors.
|
||||
*/
|
||||
**/
|
||||
typedef enum _cairo_hint_metrics {
|
||||
CAIRO_HINT_METRICS_DEFAULT,
|
||||
CAIRO_HINT_METRICS_OFF,
|
||||
CAIRO_HINT_METRICS_ON
|
||||
} cairo_hint_metrics_t;
|
||||
|
||||
/**
|
||||
* cairo_font_options_t:
|
||||
*
|
||||
* An opaque structure holding all options that are used when
|
||||
* rendering fonts.
|
||||
*
|
||||
* Individual features of a #cairo_font_options_t can be set or
|
||||
* accessed using functions named
|
||||
* cairo_font_options_set_<emphasis>feature_name</emphasis> and
|
||||
* cairo_font_options_get_<emphasis>feature_name</emphasis>, like
|
||||
* cairo_font_options_set_antialias() and
|
||||
* cairo_font_options_get_antialias().
|
||||
*
|
||||
* New features may be added to a #cairo_font_options_t in the
|
||||
* future. For this reason, cairo_font_options_copy(),
|
||||
* cairo_font_options_equal(), cairo_font_options_merge(), and
|
||||
* cairo_font_options_hash() should be used to copy, check
|
||||
* for equality, merge, or compute a hash value of
|
||||
* #cairo_font_options_t objects.
|
||||
**/
|
||||
typedef struct _cairo_font_options cairo_font_options_t;
|
||||
|
||||
cairo_public cairo_font_options_t *
|
||||
|
@ -927,25 +1037,30 @@ cairo_public void
|
|||
cairo_get_font_options (cairo_t *cr,
|
||||
cairo_font_options_t *options);
|
||||
|
||||
cairo_public void
|
||||
cairo_set_font_face (cairo_t *cr, cairo_font_face_t *font_face);
|
||||
|
||||
cairo_public cairo_font_face_t *
|
||||
cairo_get_font_face (cairo_t *cr);
|
||||
|
||||
cairo_public void
|
||||
cairo_set_scaled_font (cairo_t *cr,
|
||||
const cairo_scaled_font_t *scaled_font);
|
||||
|
||||
cairo_public cairo_scaled_font_t *
|
||||
cairo_get_scaled_font (cairo_t *cr);
|
||||
|
||||
cairo_public void
|
||||
cairo_show_text (cairo_t *cr, const char *utf8);
|
||||
|
||||
cairo_public void
|
||||
cairo_show_glyphs (cairo_t *cr, const cairo_glyph_t *glyphs, int num_glyphs);
|
||||
|
||||
cairo_public cairo_font_face_t *
|
||||
cairo_get_font_face (cairo_t *cr);
|
||||
cairo_public void
|
||||
cairo_text_path (cairo_t *cr, const char *utf8);
|
||||
|
||||
cairo_public void
|
||||
cairo_font_extents (cairo_t *cr,
|
||||
cairo_font_extents_t *extents);
|
||||
|
||||
cairo_public void
|
||||
cairo_set_font_face (cairo_t *cr, cairo_font_face_t *font_face);
|
||||
cairo_glyph_path (cairo_t *cr, const cairo_glyph_t *glyphs, int num_glyphs);
|
||||
|
||||
cairo_public void
|
||||
cairo_text_extents (cairo_t *cr,
|
||||
|
@ -959,10 +1074,8 @@ cairo_glyph_extents (cairo_t *cr,
|
|||
cairo_text_extents_t *extents);
|
||||
|
||||
cairo_public void
|
||||
cairo_text_path (cairo_t *cr, const char *utf8);
|
||||
|
||||
cairo_public void
|
||||
cairo_glyph_path (cairo_t *cr, const cairo_glyph_t *glyphs, int num_glyphs);
|
||||
cairo_font_extents (cairo_t *cr,
|
||||
cairo_font_extents_t *extents);
|
||||
|
||||
/* Generic identifier for a font style */
|
||||
|
||||
|
@ -972,6 +1085,9 @@ cairo_font_face_reference (cairo_font_face_t *font_face);
|
|||
cairo_public void
|
||||
cairo_font_face_destroy (cairo_font_face_t *font_face);
|
||||
|
||||
cairo_public unsigned int
|
||||
cairo_font_face_get_reference_count (cairo_font_face_t *font_face);
|
||||
|
||||
cairo_public cairo_status_t
|
||||
cairo_font_face_status (cairo_font_face_t *font_face);
|
||||
|
||||
|
@ -1010,7 +1126,7 @@ cairo_font_face_status (cairo_font_face_t *font_face);
|
|||
* New entries may be added in future versions.
|
||||
*
|
||||
* Since: 1.2
|
||||
*/
|
||||
**/
|
||||
typedef enum _cairo_font_type {
|
||||
CAIRO_FONT_TYPE_TOY,
|
||||
CAIRO_FONT_TYPE_FT,
|
||||
|
@ -1045,12 +1161,25 @@ cairo_scaled_font_reference (cairo_scaled_font_t *scaled_font);
|
|||
cairo_public void
|
||||
cairo_scaled_font_destroy (cairo_scaled_font_t *scaled_font);
|
||||
|
||||
cairo_public unsigned int
|
||||
cairo_scaled_font_get_reference_count (cairo_scaled_font_t *scaled_font);
|
||||
|
||||
cairo_public cairo_status_t
|
||||
cairo_scaled_font_status (cairo_scaled_font_t *scaled_font);
|
||||
|
||||
cairo_public cairo_font_type_t
|
||||
cairo_scaled_font_get_type (cairo_scaled_font_t *scaled_font);
|
||||
|
||||
cairo_public void *
|
||||
cairo_scaled_font_get_user_data (cairo_scaled_font_t *scaled_font,
|
||||
const cairo_user_data_key_t *key);
|
||||
|
||||
cairo_public cairo_status_t
|
||||
cairo_scaled_font_set_user_data (cairo_scaled_font_t *scaled_font,
|
||||
const cairo_user_data_key_t *key,
|
||||
void *user_data,
|
||||
cairo_destroy_func_t destroy);
|
||||
|
||||
cairo_public void
|
||||
cairo_scaled_font_extents (cairo_scaled_font_t *scaled_font,
|
||||
cairo_font_extents_t *extents);
|
||||
|
@ -1128,6 +1257,17 @@ cairo_get_target (cairo_t *cr);
|
|||
cairo_public cairo_surface_t *
|
||||
cairo_get_group_target (cairo_t *cr);
|
||||
|
||||
/**
|
||||
* cairo_path_data_type_t:
|
||||
* @CAIRO_PATH_MOVE_TO: A move-to operation
|
||||
* @CAIRO_PATH_LINE_TO: A line-to operation
|
||||
* @CAIRO_PATH_CURVE_TO: A curve-to operation
|
||||
* @CAIRO_PATH_CLOSE_PATH: A close-path operation
|
||||
*
|
||||
* #cairo_path_data_t is used to describe the type of one portion
|
||||
* of a path when represented as a #cairo_path_t.
|
||||
* See #cairo_path_data_t for details.
|
||||
**/
|
||||
typedef enum _cairo_path_data_type {
|
||||
CAIRO_PATH_MOVE_TO,
|
||||
CAIRO_PATH_LINE_TO,
|
||||
|
@ -1149,8 +1289,7 @@ typedef enum _cairo_path_data_type {
|
|||
* the array, (one header followed by 0 or more points). The length
|
||||
* value of the header is the number of array elements for the current
|
||||
* portion including the header, (ie. length == 1 + # of points), and
|
||||
* where the number of points for each element type must be as
|
||||
* follows:
|
||||
* where the number of points for each element type is as follows:
|
||||
*
|
||||
* <programlisting>
|
||||
* %CAIRO_PATH_MOVE_TO: 1 point
|
||||
|
@ -1193,6 +1332,14 @@ typedef enum _cairo_path_data_type {
|
|||
* }
|
||||
* cairo_path_destroy (path);
|
||||
* </programlisting></informalexample>
|
||||
*
|
||||
* As of cairo 1.4, cairo does not mind if there are more elements in
|
||||
* a portion of the path than needed. Such elements can be used by
|
||||
* users of the cairo API to hold extra values in the path data
|
||||
* structure. For this reason, it is recommended that applications
|
||||
* always use <literal>data->header.length</literal> to
|
||||
* iterate over the path data, instead of hardcoding the number of
|
||||
* elements for each element type.
|
||||
**/
|
||||
typedef union _cairo_path_data_t cairo_path_data_t;
|
||||
union _cairo_path_data_t {
|
||||
|
@ -1268,12 +1415,12 @@ cairo_surface_finish (cairo_surface_t *surface);
|
|||
cairo_public void
|
||||
cairo_surface_destroy (cairo_surface_t *surface);
|
||||
|
||||
cairo_public cairo_status_t
|
||||
cairo_surface_status (cairo_surface_t *surface);
|
||||
|
||||
cairo_public unsigned int
|
||||
cairo_surface_get_reference_count (cairo_surface_t *surface);
|
||||
|
||||
cairo_public cairo_status_t
|
||||
cairo_surface_status (cairo_surface_t *surface);
|
||||
|
||||
/**
|
||||
* cairo_surface_type_t
|
||||
* @CAIRO_SURFACE_TYPE_IMAGE: The surface is of type image
|
||||
|
@ -1311,7 +1458,7 @@ cairo_surface_get_reference_count (cairo_surface_t *surface);
|
|||
* New entries may be added in future versions.
|
||||
*
|
||||
* Since: 1.2
|
||||
*/
|
||||
**/
|
||||
typedef enum _cairo_surface_type {
|
||||
CAIRO_SURFACE_TYPE_IMAGE,
|
||||
CAIRO_SURFACE_TYPE_PDF,
|
||||
|
@ -1324,7 +1471,6 @@ typedef enum _cairo_surface_type {
|
|||
CAIRO_SURFACE_TYPE_BEOS,
|
||||
CAIRO_SURFACE_TYPE_DIRECTFB,
|
||||
CAIRO_SURFACE_TYPE_SVG,
|
||||
CAIRO_SURFACE_TYPE_NQUARTZ,
|
||||
CAIRO_SURFACE_TYPE_OS2
|
||||
} cairo_surface_type_t;
|
||||
|
||||
|
@ -1417,7 +1563,7 @@ cairo_surface_set_fallback_resolution (cairo_surface_t *surface,
|
|||
* image data.
|
||||
*
|
||||
* New entries may be added in future versions.
|
||||
*/
|
||||
**/
|
||||
typedef enum _cairo_format {
|
||||
CAIRO_FORMAT_ARGB32,
|
||||
CAIRO_FORMAT_RGB24,
|
||||
|
@ -1493,9 +1639,22 @@ cairo_pattern_reference (cairo_pattern_t *pattern);
|
|||
cairo_public void
|
||||
cairo_pattern_destroy (cairo_pattern_t *pattern);
|
||||
|
||||
cairo_public unsigned int
|
||||
cairo_pattern_get_reference_count (cairo_pattern_t *pattern);
|
||||
|
||||
cairo_public cairo_status_t
|
||||
cairo_pattern_status (cairo_pattern_t *pattern);
|
||||
|
||||
cairo_public void *
|
||||
cairo_pattern_get_user_data (cairo_pattern_t *pattern,
|
||||
const cairo_user_data_key_t *key);
|
||||
|
||||
cairo_public cairo_status_t
|
||||
cairo_pattern_set_user_data (cairo_pattern_t *pattern,
|
||||
const cairo_user_data_key_t *key,
|
||||
void *user_data,
|
||||
cairo_destroy_func_t destroy);
|
||||
|
||||
/**
|
||||
* cairo_pattern_type_t
|
||||
* @CAIRO_PATTERN_TYPE_SOLID: The pattern is a solid (uniform)
|
||||
|
@ -1525,7 +1684,7 @@ cairo_pattern_status (cairo_pattern_t *pattern);
|
|||
* New entries may be added in future versions.
|
||||
*
|
||||
* Since: 1.2
|
||||
*/
|
||||
**/
|
||||
typedef enum _cairo_pattern_type {
|
||||
CAIRO_PATTERN_TYPE_SOLID,
|
||||
CAIRO_PATTERN_TYPE_SURFACE,
|
||||
|
@ -1570,7 +1729,7 @@ cairo_pattern_get_matrix (cairo_pattern_t *pattern,
|
|||
* of a pattern will be drawn.
|
||||
*
|
||||
* New entries may be added in future versions.
|
||||
*/
|
||||
**/
|
||||
typedef enum _cairo_extend {
|
||||
CAIRO_EXTEND_NONE,
|
||||
CAIRO_EXTEND_REPEAT,
|
||||
|
@ -1677,12 +1836,6 @@ cairo_public void
|
|||
cairo_matrix_transform_point (const cairo_matrix_t *matrix,
|
||||
double *x, double *y);
|
||||
|
||||
cairo_public void
|
||||
cairo_matrix_transform_bounding_box (const cairo_matrix_t *matrix,
|
||||
double *x1, double *y1,
|
||||
double *x2, double *y2,
|
||||
cairo_bool_t *is_tight);
|
||||
|
||||
/* Functions to be used while debugging (not intended for use in production code) */
|
||||
cairo_public void
|
||||
cairo_debug_reset_static_data (void);
|
||||
|
|
|
@ -73,7 +73,7 @@
|
|||
|
||||
CAIRO_BEGIN_DECLS
|
||||
|
||||
#if __GNUC__ >= 3 && defined(__ELF__)
|
||||
#if __GNUC__ >= 3 && defined(__ELF__) && !defined(__sun)
|
||||
# define slim_hidden_proto(name) slim_hidden_proto1(name, slim_hidden_int_name(name))
|
||||
# define slim_hidden_def(name) slim_hidden_def1(name, slim_hidden_int_name(name))
|
||||
# define slim_hidden_int_name(name) INT_##name
|
||||
|
@ -102,7 +102,7 @@ CAIRO_BEGIN_DECLS
|
|||
#endif
|
||||
|
||||
/* slim_internal.h */
|
||||
#if (__GNUC__ > 3 || (__GNUC__ == 3 && __GNUC_MINOR__ >= 3)) && defined(__ELF__)
|
||||
#if (__GNUC__ > 3 || (__GNUC__ == 3 && __GNUC_MINOR__ >= 3)) && defined(__ELF__) && !defined(__sun)
|
||||
#define cairo_private __attribute__((__visibility__("hidden")))
|
||||
#elif defined(__SUNPRO_C) && (__SUNPRO_C >= 0x550)
|
||||
#define cairo_private __hidden
|
||||
|
@ -134,13 +134,20 @@ CAIRO_BEGIN_DECLS
|
|||
#define __attribute__(x)
|
||||
#endif
|
||||
|
||||
#if 0
|
||||
#if MOZILLA_CAIRO_NOT_DEFINED
|
||||
#if HAVE_PTHREAD_H
|
||||
# include <pthread.h>
|
||||
# define CAIRO_MUTEX_DECLARE(name) static pthread_mutex_t name = PTHREAD_MUTEX_INITIALIZER
|
||||
# define CAIRO_MUTEX_DECLARE_GLOBAL(name) pthread_mutex_t name = PTHREAD_MUTEX_INITIALIZER
|
||||
# define CAIRO_MUTEX_LOCK(name) pthread_mutex_lock (&name)
|
||||
# define CAIRO_MUTEX_UNLOCK(name) pthread_mutex_unlock (&name)
|
||||
typedef pthread_mutex_t cairo_mutex_t;
|
||||
#define CAIRO_MUTEX_INIT(mutex) do { \
|
||||
pthread_mutex_t tmp_mutex = PTHREAD_MUTEX_INITIALIZER; \
|
||||
memcpy (mutex, &tmp_mutex, sizeof (tmp_mutex)); \
|
||||
} while (0)
|
||||
# define CAIRO_MUTEX_FINI(mutex) pthread_mutex_destroy (mutex)
|
||||
# define CAIRO_MUTEX_NIL_INITIALIZER PTHREAD_MUTEX_INITIALIZER
|
||||
#endif
|
||||
|
||||
#if !defined(CAIRO_MUTEX_DECLARE) && defined CAIRO_HAS_WIN32_SURFACE
|
||||
|
@ -160,6 +167,10 @@ CAIRO_BEGIN_DECLS
|
|||
# define CAIRO_MUTEX_DECLARE_GLOBAL(name) extern LPCRITICAL_SECTION name;
|
||||
# define CAIRO_MUTEX_LOCK(name) EnterCriticalSection (&name)
|
||||
# define CAIRO_MUTEX_UNLOCK(name) LeaveCriticalSection (&name)
|
||||
typedef CRITICAL_SECTION cairo_mutex_t;
|
||||
# define CAIRO_MUTEX_INIT(mutex) InitializeCriticalSection (mutex)
|
||||
# define CAIRO_MUTEX_FINI(mutex) DeleteCriticalSection (mutex)
|
||||
# define CAIRO_MUTEX_NIL_INITIALIZER { 0 }
|
||||
#endif
|
||||
|
||||
#if defined(__OS2__) && !defined(CAIRO_MUTEX_DECLARE)
|
||||
|
@ -171,6 +182,10 @@ CAIRO_BEGIN_DECLS
|
|||
# define CAIRO_MUTEX_DECLARE_GLOBAL(name) extern HMTX name
|
||||
# define CAIRO_MUTEX_LOCK(name) DosRequestMutexSem(name, SEM_INDEFINITE_WAIT)
|
||||
# define CAIRO_MUTEX_UNLOCK(name) DosReleaseMutexSem(name)
|
||||
typedef HMTX cairo_mutex_t;
|
||||
# define CAIRO_MUTEX_INIT(mutex) DosCreateMutexSem (NULL, mutex, 0L, FALSE)
|
||||
# define CAIRO_MUTEX_FINI(mutex) DosCloseMutexSem (*(mutex))
|
||||
# define CAIRO_MUTEX_NIL_INITIALIZER 0
|
||||
#endif
|
||||
|
||||
#if !defined(CAIRO_MUTEX_DECLARE) && defined CAIRO_HAS_BEOS_SURFACE
|
||||
|
@ -181,14 +196,29 @@ cairo_private void _cairo_beos_unlock(void*);
|
|||
# define CAIRO_MUTEX_DECLARE_GLOBAL(name) extern void* name;
|
||||
# define CAIRO_MUTEX_LOCK(name) _cairo_beos_lock (&name)
|
||||
# define CAIRO_MUTEX_UNLOCK(name) _cairo_beos_unlock (&name)
|
||||
# error "XXX: Someone who understands BeOS needs to add definitions for" \
|
||||
" cairo_mutex_t, CAIRO_MUTEX_INIT, and CAIRO_MUTEX_FINI," \
|
||||
" to cairoint.h"
|
||||
typedef ??? cairo_mutex_t;
|
||||
# define CAIRO_MUTEX_INIT(mutex) ???
|
||||
# define CAIRO_MUTEX_FINI(mutex) ???
|
||||
# define CAIRO_MUTEX_NIL_INITIALIZER {}
|
||||
#endif
|
||||
#endif
|
||||
#endif /* MOZILLA_CAIRO_NOT_REACHED */
|
||||
|
||||
#ifndef CAIRO_MUTEX_DECLARE
|
||||
#if MOZILLA_CAIRO_NOT_DEFINED
|
||||
# error "No mutex declarations. Cairo will not work with multiple threads." \
|
||||
"(Remove this #error directive to acknowledge & accept this limitation)."
|
||||
#endif
|
||||
typedef void *cairo_mutex_t;
|
||||
# define CAIRO_MUTEX_DECLARE(name)
|
||||
# define CAIRO_MUTEX_DECLARE_GLOBAL(name)
|
||||
# define CAIRO_MUTEX_LOCK(name)
|
||||
# define CAIRO_MUTEX_UNLOCK(name)
|
||||
#define CAIRO_MUTEX_INIT(mutex) (*(mutex) = 0)
|
||||
#define CAIRO_MUTEX_FINI(mutex)
|
||||
#define CAIRO_MUTEX_NIL_INITIALIZER 0
|
||||
#endif
|
||||
|
||||
#undef MIN
|
||||
|
@ -209,6 +239,18 @@ cairo_private void _cairo_beos_unlock(void*);
|
|||
#define M_PI 3.14159265358979323846
|
||||
#endif
|
||||
|
||||
#ifndef MOZILLA_CAIRO_NOT_DEFINED
|
||||
#ifndef INT32_MAX
|
||||
# ifdef INT_MAX
|
||||
# define INT32_MAX INT_MAX
|
||||
# define INT32_MIN INT_MIN
|
||||
# else
|
||||
# define INT32_MAX 2147483647
|
||||
# define INT32_MIN (-2147483647 - 1)
|
||||
# endif
|
||||
#endif
|
||||
#endif
|
||||
|
||||
/* Size in bytes of buffer to use off the stack per functions.
|
||||
* Mostly used by text functions. For larger allocations, they'll
|
||||
* malloc(). */
|
||||
|
@ -250,6 +292,41 @@ typedef cairo_fixed_16_16_t cairo_fixed_t;
|
|||
#define CAIRO_BITSWAP8_IF_LITTLE_ENDIAN(c) CAIRO_BITSWAP8(c)
|
||||
#endif
|
||||
|
||||
#ifdef WORDS_BIGENDIAN
|
||||
|
||||
#define cpu_to_be16(v) (v)
|
||||
#define be16_to_cpu(v) (v)
|
||||
#define cpu_to_be32(v) (v)
|
||||
#define be32_to_cpu(v) (v)
|
||||
|
||||
#else
|
||||
|
||||
static inline uint16_t
|
||||
cpu_to_be16(uint16_t v)
|
||||
{
|
||||
return (v << 8) | (v >> 8);
|
||||
}
|
||||
|
||||
static inline uint16_t
|
||||
be16_to_cpu(uint16_t v)
|
||||
{
|
||||
return cpu_to_be16 (v);
|
||||
}
|
||||
|
||||
static inline uint32_t
|
||||
cpu_to_be32(uint32_t v)
|
||||
{
|
||||
return (cpu_to_be16 (v) << 16) | cpu_to_be16 (v >> 16);
|
||||
}
|
||||
|
||||
static inline uint32_t
|
||||
be32_to_cpu(uint32_t v)
|
||||
{
|
||||
return cpu_to_be32 (v);
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
#include "cairo-hash-private.h"
|
||||
#include "cairo-cache-private.h"
|
||||
|
||||
|
@ -364,15 +441,14 @@ typedef struct _cairo_edge {
|
|||
} cairo_edge_t;
|
||||
|
||||
typedef struct _cairo_polygon {
|
||||
cairo_point_t first_point;
|
||||
cairo_point_t current_point;
|
||||
cairo_bool_t has_current_point;
|
||||
|
||||
int num_edges;
|
||||
int edges_size;
|
||||
cairo_edge_t *edges;
|
||||
|
||||
cairo_point_t first_point;
|
||||
cairo_point_t current_point;
|
||||
int has_current_point;
|
||||
|
||||
int closed;
|
||||
cairo_edge_t edges_embedded[8];
|
||||
} cairo_polygon_t;
|
||||
|
||||
typedef struct _cairo_spline {
|
||||
|
@ -384,6 +460,7 @@ typedef struct _cairo_spline {
|
|||
int num_points;
|
||||
int points_size;
|
||||
cairo_point_t *points;
|
||||
cairo_point_t points_embedded[8];
|
||||
} cairo_spline_t;
|
||||
|
||||
typedef struct _cairo_pen_vertex {
|
||||
|
@ -523,12 +600,43 @@ typedef struct _cairo_scaled_glyph {
|
|||
#define _cairo_scaled_glyph_set_index(g,i) ((g)->cache_entry.hash = (i))
|
||||
|
||||
struct _cairo_scaled_font {
|
||||
/* For most cairo objects, the rule for multiple threads is that
|
||||
* the user is responsible for any locking if the same object is
|
||||
* manipulated from multiple threads simultaneously.
|
||||
*
|
||||
* However, with the caching that cairo does for scaled fonts, a
|
||||
* user can easily end up with the same cairo_scaled_font object
|
||||
* being manipulated from multiple threads without the user ever
|
||||
* being aware of this, (and in fact, unable to control it).
|
||||
*
|
||||
* So, as a special exception, the cairo implementation takes care
|
||||
* of all locking needed for cairo_scaled_font_t. Most of what is
|
||||
* in the scaled font is immutable, (which is what allows for the
|
||||
* sharing in the first place). The things that are modified and
|
||||
* the locks protecting them are as follows:
|
||||
*
|
||||
* 1. The reference count (scaled_font->ref_count)
|
||||
*
|
||||
* Modifications to the reference count are protected by the
|
||||
* _cairo_scaled_font_map_mutex. This is because the reference
|
||||
* count of a scaled font is intimately related with the font
|
||||
* map itself, (and the magic holdovers array).
|
||||
*
|
||||
* 2. The cache of glyphs (scaled_font->glyphs)
|
||||
* 3. The backend private data (scaled_font->surface_backend,
|
||||
* scaled_font->surface_private)
|
||||
*
|
||||
* Modifications to these fields are protected with locks on
|
||||
* scaled_font->mutex in the generic scaled_font code.
|
||||
*/
|
||||
|
||||
/* must be first to be stored in a hash table */
|
||||
cairo_hash_entry_t hash_entry;
|
||||
|
||||
/* useful bits for _cairo_scaled_font_nil */
|
||||
cairo_status_t status;
|
||||
unsigned int ref_count;
|
||||
cairo_user_data_array_t user_data;
|
||||
|
||||
/* hash key members */
|
||||
cairo_font_face_t *font_face; /* may be NULL */
|
||||
|
@ -539,6 +647,10 @@ struct _cairo_scaled_font {
|
|||
/* "live" scaled_font members */
|
||||
cairo_matrix_t scale; /* font space => device space */
|
||||
cairo_font_extents_t extents; /* user space */
|
||||
|
||||
/* The mutex protects modification to all subsequent fields. */
|
||||
cairo_mutex_t mutex;
|
||||
|
||||
cairo_cache_t *glyphs; /* glyph index -> cairo_scaled_glyph_t */
|
||||
|
||||
/*
|
||||
|
@ -598,6 +710,19 @@ typedef enum _cairo_scaled_glyph_info {
|
|||
CAIRO_SCALED_GLYPH_INFO_PATH = (1 << 2)
|
||||
} cairo_scaled_glyph_info_t;
|
||||
|
||||
typedef struct _cairo_scaled_font_subset {
|
||||
cairo_scaled_font_t *scaled_font;
|
||||
unsigned int font_id;
|
||||
unsigned int subset_id;
|
||||
|
||||
/* Index of glyphs array is subset_glyph_index.
|
||||
* Value of glyphs array is scaled_font_glyph_index.
|
||||
*/
|
||||
unsigned long *glyphs;
|
||||
unsigned long *to_unicode;
|
||||
unsigned int num_glyphs;
|
||||
} cairo_scaled_font_subset_t;
|
||||
|
||||
struct _cairo_scaled_font_backend {
|
||||
cairo_font_type_t type;
|
||||
|
||||
|
@ -651,6 +776,11 @@ struct _cairo_scaled_font_backend {
|
|||
long offset,
|
||||
unsigned char *buffer,
|
||||
unsigned long *length);
|
||||
|
||||
void
|
||||
(*map_glyphs_to_unicode)(void *scaled_font,
|
||||
cairo_scaled_font_subset_t *font_subset);
|
||||
|
||||
};
|
||||
|
||||
struct _cairo_font_face_backend {
|
||||
|
@ -1045,6 +1175,8 @@ struct _cairo_pattern {
|
|||
cairo_pattern_type_t type;
|
||||
unsigned int ref_count;
|
||||
cairo_status_t status;
|
||||
cairo_user_data_array_t user_data;
|
||||
|
||||
cairo_matrix_t matrix;
|
||||
cairo_filter_t filter;
|
||||
cairo_extend_t extend;
|
||||
|
@ -1066,8 +1198,10 @@ typedef struct _cairo_surface_pattern {
|
|||
typedef struct _cairo_gradient_pattern {
|
||||
cairo_pattern_t base;
|
||||
|
||||
pixman_gradient_stop_t *stops;
|
||||
unsigned int n_stops;
|
||||
unsigned int stops_size;
|
||||
pixman_gradient_stop_t *stops;
|
||||
pixman_gradient_stop_t stops_embedded[2];
|
||||
} cairo_gradient_pattern_t;
|
||||
|
||||
typedef struct _cairo_linear_pattern {
|
||||
|
@ -1110,10 +1244,12 @@ typedef struct _cairo_surface_attributes {
|
|||
typedef struct _cairo_traps {
|
||||
cairo_status_t status;
|
||||
|
||||
cairo_trapezoid_t *traps;
|
||||
cairo_box_t extents;
|
||||
|
||||
int num_traps;
|
||||
int traps_size;
|
||||
cairo_box_t extents;
|
||||
cairo_trapezoid_t *traps;
|
||||
cairo_trapezoid_t traps_embedded[1];
|
||||
} cairo_traps_t;
|
||||
|
||||
#define CAIRO_FONT_SLANT_DEFAULT CAIRO_FONT_SLANT_NORMAL
|
||||
|
@ -1196,15 +1332,19 @@ cairo_private int
|
|||
_cairo_fixed_integer_ceil (cairo_fixed_t f);
|
||||
|
||||
/* cairo_gstate.c */
|
||||
cairo_private cairo_gstate_t *
|
||||
_cairo_gstate_create (cairo_surface_t *target);
|
||||
cairo_private cairo_status_t
|
||||
_cairo_gstate_init (cairo_gstate_t *gstate,
|
||||
cairo_surface_t *target);
|
||||
|
||||
cairo_private void
|
||||
_cairo_gstate_destroy (cairo_gstate_t *gstate);
|
||||
_cairo_gstate_fini (cairo_gstate_t *gstate);
|
||||
|
||||
cairo_private cairo_gstate_t *
|
||||
_cairo_gstate_clone (cairo_gstate_t *gstate);
|
||||
|
||||
cairo_private void
|
||||
_cairo_gstate_destroy (cairo_gstate_t *gstate);
|
||||
|
||||
cairo_private cairo_bool_t
|
||||
_cairo_gstate_is_redirected (cairo_gstate_t *gstate);
|
||||
|
||||
|
@ -1420,6 +1560,10 @@ cairo_private cairo_status_t
|
|||
_cairo_gstate_get_font_face (cairo_gstate_t *gstate,
|
||||
cairo_font_face_t **font_face);
|
||||
|
||||
cairo_private cairo_status_t
|
||||
_cairo_gstate_get_scaled_font (cairo_gstate_t *gstate,
|
||||
cairo_scaled_font_t **scaled_font);
|
||||
|
||||
cairo_private cairo_status_t
|
||||
_cairo_gstate_get_font_extents (cairo_gstate_t *gstate,
|
||||
cairo_font_extents_t *extents);
|
||||
|
@ -1467,6 +1611,9 @@ _cairo_stock_color (cairo_stock_t stock);
|
|||
#define CAIRO_COLOR_BLACK _cairo_stock_color (CAIRO_STOCK_BLACK)
|
||||
#define CAIRO_COLOR_TRANSPARENT _cairo_stock_color (CAIRO_STOCK_TRANSPARENT)
|
||||
|
||||
cairo_private uint16_t
|
||||
_cairo_color_double_to_short (double d);
|
||||
|
||||
cairo_private void
|
||||
_cairo_color_init (cairo_color_t *color);
|
||||
|
||||
|
@ -1505,11 +1652,15 @@ _cairo_scaled_font_freeze_cache (cairo_scaled_font_t *scaled_font);
|
|||
cairo_private void
|
||||
_cairo_scaled_font_thaw_cache (cairo_scaled_font_t *scaled_font);
|
||||
|
||||
cairo_private void
|
||||
_cairo_scaled_font_reset_cache (cairo_scaled_font_t *scaled_font);
|
||||
|
||||
cairo_private void
|
||||
_cairo_scaled_font_set_error (cairo_scaled_font_t *scaled_font,
|
||||
cairo_status_t status);
|
||||
|
||||
extern const cairo_private cairo_font_face_t _cairo_font_face_nil;
|
||||
extern const cairo_private cairo_scaled_font_t _cairo_scaled_font_nil;
|
||||
|
||||
cairo_private void
|
||||
_cairo_font_face_init (cairo_font_face_t *font_face,
|
||||
|
@ -1760,6 +1911,7 @@ _cairo_stroke_style_fini (cairo_stroke_style_t *style);
|
|||
|
||||
extern const cairo_private cairo_surface_t _cairo_surface_nil;
|
||||
extern const cairo_private cairo_surface_t _cairo_surface_nil_read_error;
|
||||
extern const cairo_private cairo_surface_t _cairo_surface_nil_write_error;
|
||||
extern const cairo_private cairo_surface_t _cairo_surface_nil_file_not_found;
|
||||
|
||||
cairo_private void
|
||||
|
@ -2185,6 +2337,12 @@ _cairo_matrix_get_affine (const cairo_matrix_t *matrix,
|
|||
double *xy, double *yy,
|
||||
double *x0, double *y0);
|
||||
|
||||
cairo_private void
|
||||
_cairo_matrix_transform_bounding_box (const cairo_matrix_t *matrix,
|
||||
double *x1, double *y1,
|
||||
double *x2, double *y2,
|
||||
cairo_bool_t *is_tight);
|
||||
|
||||
cairo_private void
|
||||
_cairo_matrix_compute_determinant (const cairo_matrix_t *matrix, double *det);
|
||||
|
||||
|
@ -2420,7 +2578,6 @@ slim_hidden_proto (cairo_matrix_multiply);
|
|||
slim_hidden_proto (cairo_matrix_scale);
|
||||
slim_hidden_proto (cairo_matrix_transform_distance);
|
||||
slim_hidden_proto (cairo_matrix_transform_point);
|
||||
slim_hidden_proto (cairo_matrix_transform_bounding_box);
|
||||
slim_hidden_proto (cairo_matrix_translate);
|
||||
slim_hidden_proto (cairo_move_to);
|
||||
slim_hidden_proto (cairo_new_path);
|
||||
|
@ -2441,6 +2598,7 @@ slim_hidden_proto (cairo_push_group_with_content);
|
|||
slim_hidden_proto (cairo_rel_line_to);
|
||||
slim_hidden_proto (cairo_restore);
|
||||
slim_hidden_proto (cairo_save);
|
||||
slim_hidden_proto (cairo_scale);
|
||||
slim_hidden_proto (cairo_scaled_font_create);
|
||||
slim_hidden_proto (cairo_scaled_font_destroy);
|
||||
slim_hidden_proto (cairo_scaled_font_extents);
|
||||
|
@ -2467,9 +2625,14 @@ slim_hidden_proto (cairo_surface_reference);
|
|||
slim_hidden_proto (cairo_surface_set_device_offset);
|
||||
slim_hidden_proto (cairo_surface_set_fallback_resolution);
|
||||
slim_hidden_proto (cairo_surface_status);
|
||||
slim_hidden_proto (cairo_surface_write_to_png_stream);
|
||||
slim_hidden_proto (cairo_version_string);
|
||||
|
||||
#if CAIRO_HAS_PNG_FUNCTIONS
|
||||
|
||||
slim_hidden_proto (cairo_surface_write_to_png_stream);
|
||||
|
||||
#endif
|
||||
|
||||
CAIRO_END_DECLS
|
||||
|
||||
#endif
|
||||
|
|
|
@ -64,10 +64,10 @@ typedef struct _test_fallback_surface {
|
|||
|
||||
const cairo_private cairo_surface_backend_t test_fallback_surface_backend;
|
||||
|
||||
slim_hidden_proto (_test_fallback_surface_create);
|
||||
slim_hidden_proto (_cairo_test_fallback_surface_create);
|
||||
|
||||
cairo_surface_t *
|
||||
_test_fallback_surface_create (cairo_content_t content,
|
||||
_cairo_test_fallback_surface_create (cairo_content_t content,
|
||||
int width,
|
||||
int height)
|
||||
{
|
||||
|
@ -91,7 +91,7 @@ _test_fallback_surface_create (cairo_content_t content,
|
|||
|
||||
return &surface->base;
|
||||
}
|
||||
slim_hidden_def (_test_fallback_surface_create);
|
||||
slim_hidden_def (_cairo_test_fallback_surface_create);
|
||||
|
||||
static cairo_surface_t *
|
||||
_test_fallback_surface_create_similar (void *abstract_surface,
|
||||
|
@ -101,7 +101,7 @@ _test_fallback_surface_create_similar (void *abstract_surface,
|
|||
{
|
||||
assert (CAIRO_CONTENT_VALID (content));
|
||||
|
||||
return _test_fallback_surface_create (content,
|
||||
return _cairo_test_fallback_surface_create (content,
|
||||
width, height);
|
||||
}
|
||||
|
||||
|
|
|
@ -41,7 +41,7 @@
|
|||
CAIRO_BEGIN_DECLS
|
||||
|
||||
cairo_surface_t *
|
||||
_test_fallback_surface_create (cairo_content_t content,
|
||||
_cairo_test_fallback_surface_create (cairo_content_t content,
|
||||
int width,
|
||||
int height);
|
||||
|
||||
|
|
|
@ -68,7 +68,7 @@ static cairo_int_status_t
|
|||
_test_meta_surface_show_page (void *abstract_surface);
|
||||
|
||||
cairo_surface_t *
|
||||
_test_meta_surface_create (cairo_content_t content,
|
||||
_cairo_test_meta_surface_create (cairo_content_t content,
|
||||
int width,
|
||||
int height)
|
||||
{
|
||||
|
@ -252,12 +252,27 @@ _test_meta_surface_show_glyphs (void *abstract_surface,
|
|||
cairo_scaled_font_t *scaled_font)
|
||||
{
|
||||
test_meta_surface_t *surface = abstract_surface;
|
||||
cairo_int_status_t status;
|
||||
|
||||
surface->image_reflects_meta = FALSE;
|
||||
|
||||
return _cairo_surface_show_glyphs (surface->meta, op, source,
|
||||
/* Since this is a "wrapping" surface, we're calling back into
|
||||
* _cairo_surface_show_glyphs from within a call to the same.
|
||||
* Since _cairo_surface_show_glyphs acquires a mutex, we release
|
||||
* and re-acquire the mutex around this nested call.
|
||||
*
|
||||
* Yes, this is ugly, but we consider it pragmatic as compared to
|
||||
* adding locking code to all 18 surface-backend-specific
|
||||
* show_glyphs functions, (which would get less testing and likely
|
||||
* lead to bugs).
|
||||
*/
|
||||
CAIRO_MUTEX_UNLOCK (scaled_font->mutex);
|
||||
status = _cairo_surface_show_glyphs (surface->meta, op, source,
|
||||
glyphs, num_glyphs,
|
||||
scaled_font);
|
||||
CAIRO_MUTEX_LOCK (scaled_font->mutex);
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
static cairo_surface_t *
|
||||
|
|
|
@ -41,7 +41,7 @@
|
|||
CAIRO_BEGIN_DECLS
|
||||
|
||||
cairo_surface_t *
|
||||
_test_meta_surface_create (cairo_content_t content,
|
||||
_cairo_test_meta_surface_create (cairo_content_t content,
|
||||
int width,
|
||||
int height);
|
||||
|
||||
|
|
|
@ -61,7 +61,7 @@ static const cairo_surface_backend_t test_paginated_surface_backend;
|
|||
static const cairo_paginated_surface_backend_t test_paginated_surface_paginated_backend;
|
||||
|
||||
cairo_surface_t *
|
||||
_test_paginated_surface_create_for_data (unsigned char *data,
|
||||
_cairo_test_paginated_surface_create_for_data (unsigned char *data,
|
||||
cairo_content_t content,
|
||||
int width,
|
||||
int height,
|
||||
|
@ -233,12 +233,27 @@ _test_paginated_surface_show_glyphs (void *abstract_surface,
|
|||
cairo_scaled_font_t *scaled_font)
|
||||
{
|
||||
test_paginated_surface_t *surface = abstract_surface;
|
||||
cairo_int_status_t status;
|
||||
|
||||
if (surface->paginated_mode == CAIRO_PAGINATED_MODE_ANALYZE)
|
||||
return CAIRO_STATUS_SUCCESS;
|
||||
|
||||
return _cairo_surface_show_glyphs (surface->target, op, source,
|
||||
/* Since this is a "wrapping" surface, we're calling back into
|
||||
* _cairo_surface_show_glyphs from within a call to the same.
|
||||
* Since _cairo_surface_show_glyphs acquires a mutex, we release
|
||||
* and re-acquire the mutex around this nested call.
|
||||
*
|
||||
* Yes, this is ugly, but we consider it pragmatic as compared to
|
||||
* adding locking code to all 18 surface-backend-specific
|
||||
* show_glyphs functions, (which would get less testing and likely
|
||||
* lead to bugs).
|
||||
*/
|
||||
CAIRO_MUTEX_UNLOCK (scaled_font->mutex);
|
||||
status = _cairo_surface_show_glyphs (surface->target, op, source,
|
||||
glyphs, num_glyphs, scaled_font);
|
||||
CAIRO_MUTEX_LOCK (scaled_font->mutex);
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
static void
|
||||
|
|
|
@ -41,7 +41,7 @@
|
|||
CAIRO_BEGIN_DECLS
|
||||
|
||||
cairo_surface_t *
|
||||
_test_paginated_surface_create_for_data (unsigned char *data,
|
||||
_cairo_test_paginated_surface_create_for_data (unsigned char *data,
|
||||
cairo_content_t content,
|
||||
int width,
|
||||
int height,
|
||||
|
|
|
@ -28,7 +28,9 @@
|
|||
#endif
|
||||
#include "pixman-xserver-compat.h"
|
||||
#include "fbpict.h"
|
||||
#ifndef MOZILLA_CAIRO_NOT_DEFINED
|
||||
#include "fbmmx.h"
|
||||
#endif /* MOZCAIRO */
|
||||
|
||||
#ifdef RENDER
|
||||
|
||||
|
@ -38,6 +40,7 @@
|
|||
#define _USE_MATH_DEFINES
|
||||
#endif
|
||||
|
||||
#include <assert.h>
|
||||
#include <math.h>
|
||||
|
||||
#ifndef M_PI
|
||||
|
@ -2740,12 +2743,13 @@ typedef struct
|
|||
CARD32 right_rb;
|
||||
int32_t left_x;
|
||||
int32_t right_x;
|
||||
int32_t width_x;
|
||||
int32_t stepper;
|
||||
|
||||
pixman_gradient_stop_t *stops;
|
||||
int num_stops;
|
||||
unsigned int spread;
|
||||
|
||||
int need_reset;
|
||||
} GradientWalker;
|
||||
|
||||
static void
|
||||
|
@ -2757,13 +2761,14 @@ _gradient_walker_init (GradientWalker *walker,
|
|||
walker->stops = pGradient->gradient.stops;
|
||||
walker->left_x = 0;
|
||||
walker->right_x = 0x10000;
|
||||
walker->width_x = 0; /* will force a reset */
|
||||
walker->stepper = 0;
|
||||
walker->left_ag = 0;
|
||||
walker->left_rb = 0;
|
||||
walker->right_ag = 0;
|
||||
walker->right_rb = 0;
|
||||
walker->spread = spread;
|
||||
|
||||
walker->need_reset = TRUE;
|
||||
}
|
||||
|
||||
static void
|
||||
|
@ -2853,13 +2858,15 @@ _gradient_walker_reset (GradientWalker *walker,
|
|||
pixman_color_t *tmp_c;
|
||||
int32_t tmp_x;
|
||||
|
||||
tmp_x = 0x20000 - right_x;
|
||||
right_x = 0x20000 - left_x;
|
||||
tmp_x = 0x10000 - right_x;
|
||||
right_x = 0x10000 - left_x;
|
||||
left_x = tmp_x;
|
||||
|
||||
tmp_c = right_c;
|
||||
right_c = left_c;
|
||||
left_c = tmp_c;
|
||||
|
||||
x = 0x10000 - x;
|
||||
}
|
||||
left_x += (pos - x);
|
||||
right_x += (pos - x);
|
||||
|
@ -2893,27 +2900,28 @@ _gradient_walker_reset (GradientWalker *walker,
|
|||
|
||||
walker->left_x = left_x;
|
||||
walker->right_x = right_x;
|
||||
walker->width_x = right_x - left_x;
|
||||
walker->left_ag = ((left_c->alpha >> 8) << 16) | (left_c->green >> 8);
|
||||
walker->left_rb = ((left_c->red & 0xff00) << 8) | (left_c->blue >> 8);
|
||||
walker->right_ag = ((right_c->alpha >> 8) << 16) | (right_c->green >> 8);
|
||||
walker->right_rb = ((right_c->red & 0xff00) << 8) | (right_c->blue >> 8);
|
||||
|
||||
if ( walker->width_x == 0 ||
|
||||
if ( walker->left_x == walker->right_x ||
|
||||
( walker->left_ag == walker->right_ag &&
|
||||
walker->left_rb == walker->right_rb ) )
|
||||
{
|
||||
walker->width_x = 1;
|
||||
walker->stepper = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
walker->stepper = ((1 << 24) + walker->width_x/2)/walker->width_x;
|
||||
int32_t width = right_x - left_x;
|
||||
walker->stepper = ((1 << 24) + width/2)/width;
|
||||
}
|
||||
|
||||
walker->need_reset = FALSE;
|
||||
}
|
||||
|
||||
#define GRADIENT_WALKER_NEED_RESET(w,x) \
|
||||
( (x) < (w)->left_x || (x) - (w)->left_x >= (w)->width_x )
|
||||
( (w)->need_reset || (x) < (w)->left_x || (x) >= (w)->right_x)
|
||||
|
||||
/* the following assumes that GRADIENT_WALKER_NEED_RESET(w,x) is FALSE */
|
||||
static CARD32
|
||||
|
@ -2948,8 +2956,6 @@ _gradient_walker_pixel (GradientWalker *walker,
|
|||
return (color | (t1 & 0xff00ff) | (t2 & 0xff00));
|
||||
}
|
||||
|
||||
|
||||
|
||||
static void fbFetchSourcePict(PicturePtr pict, int x, int y, int width, CARD32 *buffer, CARD32 *mask, CARD32 maskBits)
|
||||
{
|
||||
SourcePictPtr pGradient = pict->pSourcePict;
|
||||
|
@ -3081,13 +3087,128 @@ static void fbFetchSourcePict(PicturePtr pict, int x, int y, int width, CARD32 *
|
|||
}
|
||||
}
|
||||
} else {
|
||||
|
||||
/*
|
||||
* In the radial gradient problem we are given two circles (c₁,r₁) and
|
||||
* (c₂,r₂) that define the gradient itself. Then, for any point p, we
|
||||
* must compute the value(s) of t within [0.0, 1.0] representing the
|
||||
* circle(s) that would color the point.
|
||||
*
|
||||
* There are potentially two values of t since the point p can be
|
||||
* colored by both sides of the circle, (which happens whenever one
|
||||
* circle is not entirely contained within the other).
|
||||
*
|
||||
* If we solve for a value of t that is outside of [0.0, 1.0] then we
|
||||
* use the extend mode (NONE, REPEAT, REFLECT, or PAD) to map to a
|
||||
* value within [0.0, 1.0].
|
||||
*
|
||||
* Here is an illustration of the problem:
|
||||
*
|
||||
* p₂
|
||||
* p •
|
||||
* • ╲
|
||||
* · ╲r₂
|
||||
* p₁ · ╲
|
||||
* • θ╲
|
||||
* ╲ ╌╌•
|
||||
* ╲r₁ · c₂
|
||||
* θ╲ ·
|
||||
* ╌╌•
|
||||
* c₁
|
||||
*
|
||||
* Given (c₁,r₁), (c₂,r₂) and p, we must find an angle θ such that two
|
||||
* points p₁ and p₂ on the two circles are collinear with p. Then, the
|
||||
* desired value of t is the ratio of the length of p₁p to the length
|
||||
* of p₁p₂.
|
||||
*
|
||||
* So, we have six unknown values: (p₁x, p₁y), (p₂x, p₂y), θ and t.
|
||||
* We can also write six equations that constrain the problem:
|
||||
*
|
||||
* Point p₁ is a distance r₁ from c₁ at an angle of θ:
|
||||
*
|
||||
* 1. p₁x = c₁x + r₁·cos θ
|
||||
* 2. p₁y = c₁y + r₁·sin θ
|
||||
*
|
||||
* Point p₂ is a distance r₂ from c₂ at an angle of θ:
|
||||
*
|
||||
* 3. p₂x = c₂x + r2·cos θ
|
||||
* 4. p₂y = c₂y + r2·sin θ
|
||||
*
|
||||
* Point p lies at a fraction t along the line segment p₁p₂:
|
||||
*
|
||||
* 5. px = t·p₂x + (1-t)·p₁x
|
||||
* 6. py = t·p₂y + (1-t)·p₁y
|
||||
*
|
||||
* To solve, first subtitute 1-4 into 5 and 6:
|
||||
*
|
||||
* px = t·(c₂x + r₂·cos θ) + (1-t)·(c₁x + r₁·cos θ)
|
||||
* py = t·(c₂y + r₂·sin θ) + (1-t)·(c₁y + r₁·sin θ)
|
||||
*
|
||||
* Then solve each for cos θ and sin θ expressed as a function of t:
|
||||
*
|
||||
* cos θ = (-(c₂x - c₁x)·t + (px - c₁x)) / ((r₂-r₁)·t + r₁)
|
||||
* sin θ = (-(c₂y - c₁y)·t + (py - c₁y)) / ((r₂-r₁)·t + r₁)
|
||||
*
|
||||
* To simplify this a bit, we define new variables for several of the
|
||||
* common terms as shown below:
|
||||
*
|
||||
* p₂
|
||||
* p •
|
||||
* • ╲
|
||||
* · ┆ ╲r₂
|
||||
* p₁ · ┆ ╲
|
||||
* • pdy┆ ╲
|
||||
* ╲ ┆ •c₂
|
||||
* ╲r₁ ┆ · ┆
|
||||
* ╲ ·┆ ┆cdy
|
||||
* •╌╌╌╌┴╌╌╌╌╌╌╌┘
|
||||
* c₁ pdx cdx
|
||||
*
|
||||
* cdx = (c₂x - c₁x)
|
||||
* cdy = (c₂y - c₁y)
|
||||
* dr = r₂-r₁
|
||||
* pdx = px - c₁x
|
||||
* pdy = py - c₁y
|
||||
*
|
||||
* Note that cdx, cdy, and dr do not depend on point p at all, so can
|
||||
* be pre-computed for the entire gradient. The simplifed equations
|
||||
* are now:
|
||||
*
|
||||
* cos θ = (-cdx·t + pdx) / (dr·t + r₁)
|
||||
* sin θ = (-cdy·t + pdy) / (dr·t + r₁)
|
||||
*
|
||||
* Finally, to get a single function of t and eliminate the last
|
||||
* unknown θ, we use the identity sin²θ + cos²θ = 1. First, square
|
||||
* each equation, (we knew a quadratic was coming since it must be
|
||||
* possible to obtain two solutions in some cases):
|
||||
*
|
||||
* cos²θ = (cdx²t² - 2·cdx·pdx·t + pdx²) / (dr²·t² + 2·r₁·dr·t + r₁²)
|
||||
* sin²θ = (cdy²t² - 2·cdy·pdy·t + pdy²) / (dr²·t² + 2·r₁·dr·t + r₁²)
|
||||
*
|
||||
* Then add both together, set the result equal to 1, and express as a
|
||||
* standard quadratic equation in t of the form At² + Bt + C = 0
|
||||
*
|
||||
* (cdx² + cdy² - dr²)·t² - 2·(cdx·pdx + cdy·pdy + r₁·dr)·t + (pdx² + pdy² - r₁²) = 0
|
||||
*
|
||||
* In other words:
|
||||
*
|
||||
* A = cdx² + cdy² - dr²
|
||||
* B = -2·(pdx·cdx + pdy·cdy + r₁·dr)
|
||||
* C = pdx² + pdy² - r₁²
|
||||
*
|
||||
* And again, notice that A does not depend on p, so can be
|
||||
* precomputed. From here we just use the quadratic formula to solve
|
||||
* for t:
|
||||
*
|
||||
* t = (-2·B ± ⎷(B² - 4·A·C)) / 2·A
|
||||
*/
|
||||
/* radial or conical */
|
||||
Bool projective = FALSE;
|
||||
double cx = 1.;
|
||||
double cy = 0.;
|
||||
double cz = 0.;
|
||||
double rx = x;
|
||||
double ry = y;
|
||||
double rx = x + 0.5;
|
||||
double ry = y + 0.5;
|
||||
double rz = 1.;
|
||||
|
||||
if (pict->transform) {
|
||||
|
@ -3109,23 +3230,36 @@ static void fbFetchSourcePict(PicturePtr pict, int x, int y, int width, CARD32 *
|
|||
}
|
||||
|
||||
if (pGradient->type == SourcePictTypeRadial) {
|
||||
pixman_radial_gradient_image_t *radial;
|
||||
radial = &pGradient->radial;
|
||||
if (!projective) {
|
||||
rx -= pGradient->radial.fx;
|
||||
ry -= pGradient->radial.fy;
|
||||
|
||||
while (buffer < end) {
|
||||
double b, c, det, s;
|
||||
|
||||
if (!mask || *mask++ & maskBits)
|
||||
{
|
||||
double pdx, pdy;
|
||||
double B, C;
|
||||
double det;
|
||||
double c1x = xFixedToDouble (radial->c1.x);
|
||||
double c1y = xFixedToDouble (radial->c1.y);
|
||||
double r1 = xFixedToDouble (radial->c1.radius);
|
||||
xFixed_48_16 t;
|
||||
|
||||
b = 2*(rx*pGradient->radial.dx + ry*pGradient->radial.dy);
|
||||
c = -(rx*rx + ry*ry);
|
||||
det = (b * b) - (4 * pGradient->radial.a * c);
|
||||
s = (-b + sqrt(det))/(2. * pGradient->radial.a);
|
||||
pdx = rx - c1x;
|
||||
pdy = ry - c1y;
|
||||
|
||||
t = (xFixed_48_16)((s*pGradient->radial.m + pGradient->radial.b)*65536);
|
||||
B = -2 * ( pdx * radial->cdx
|
||||
+ pdy * radial->cdy
|
||||
+ r1 * radial->dr);
|
||||
C = (pdx * pdx + pdy * pdy - r1 * r1);
|
||||
|
||||
det = (B * B) - (4 * radial->A * C);
|
||||
if (det < 0.0)
|
||||
det = 0.0;
|
||||
|
||||
if (radial->A < 0)
|
||||
t = (xFixed_48_16) ((- B - sqrt(det)) / (2.0 * radial->A) * 65536);
|
||||
else
|
||||
t = (xFixed_48_16) ((- B + sqrt(det)) / (2.0 * radial->A) * 65536);
|
||||
|
||||
*buffer = _gradient_walker_pixel (&walker, t);
|
||||
}
|
||||
|
@ -3134,35 +3268,12 @@ static void fbFetchSourcePict(PicturePtr pict, int x, int y, int width, CARD32 *
|
|||
ry += cy;
|
||||
}
|
||||
} else {
|
||||
while (buffer < end) {
|
||||
double x, y;
|
||||
double b, c, det, s;
|
||||
|
||||
if (!mask || *mask++ & maskBits)
|
||||
{
|
||||
xFixed_48_16 t;
|
||||
|
||||
if (rz != 0) {
|
||||
x = rx/rz;
|
||||
y = ry/rz;
|
||||
} else {
|
||||
x = y = 0.;
|
||||
}
|
||||
x -= pGradient->radial.fx;
|
||||
y -= pGradient->radial.fy;
|
||||
b = 2*(x*pGradient->radial.dx + y*pGradient->radial.dy);
|
||||
c = -(x*x + y*y);
|
||||
det = (b * b) - (4 * pGradient->radial.a * c);
|
||||
s = (-b + sqrt(det))/(2. * pGradient->radial.a);
|
||||
t = (xFixed_48_16)((s*pGradient->radial.m + pGradient->radial.b)*65536);
|
||||
|
||||
*buffer = _gradient_walker_pixel (&walker, t);
|
||||
}
|
||||
++buffer;
|
||||
rx += cx;
|
||||
ry += cy;
|
||||
rz += cz;
|
||||
}
|
||||
/* In cairo, we don't have projective transformed
|
||||
* radial gradients---so I'm not going to bother
|
||||
* implementing something untested and broken
|
||||
* here. Instead, someone trying to get this code into
|
||||
* shape for use in the X server can fix this here. */
|
||||
assert (0);
|
||||
}
|
||||
} else /* SourcePictTypeConical */ {
|
||||
double a = pGradient->conical.angle/(180.*65536);
|
||||
|
@ -3927,6 +4038,7 @@ fbCompositeRect (const FbComposeData *data, CARD32 *scanline_buffer)
|
|||
if (!compose)
|
||||
return;
|
||||
|
||||
#ifndef MOZILLA_CAIRO_NOT_DEFINED
|
||||
/* XXX: The non-MMX version of some of the fbCompose functions
|
||||
* overwrite the source or mask data (ones that use
|
||||
* fbCombineMaskC, fbCombineMaskAlphaC, or fbCombineMaskValueC
|
||||
|
@ -3944,6 +4056,7 @@ fbCompositeRect (const FbComposeData *data, CARD32 *scanline_buffer)
|
|||
srcClass = SourcePictClassUnknown;
|
||||
maskClass = SourcePictClassUnknown;
|
||||
}
|
||||
#endif /* MOZCAIRO */
|
||||
|
||||
for (i = 0; i < data->height; ++i) {
|
||||
/* fill first half of scanline with source */
|
||||
|
|
|
@ -157,6 +157,11 @@ static const MMXData c =
|
|||
#define MC(x) c.mmx_##x
|
||||
#endif
|
||||
|
||||
/* cast to void* in the middle to shut gcc up warning about
|
||||
* "dereferencing type-punned pointers".
|
||||
*/
|
||||
#define M64(x) (*(__m64*)(void*)(&x))
|
||||
|
||||
static __inline__ __m64
|
||||
shift (__m64 v, int s)
|
||||
{
|
||||
|
@ -1467,8 +1472,6 @@ fbCompositeSrc_8888x0565mmx (pixman_operator_t op,
|
|||
fbComposeGetStart (pDst, xDst, yDst, CARD16, dstStride, dstLine, 1);
|
||||
fbComposeGetStart (pSrc, xSrc, ySrc, CARD32, srcStride, srcLine, 1);
|
||||
|
||||
assert (pSrc->pDrawable == pMask->pDrawable);
|
||||
|
||||
while (height--)
|
||||
{
|
||||
dst = dstLine;
|
||||
|
@ -1497,38 +1500,15 @@ fbCompositeSrc_8888x0565mmx (pixman_operator_t op,
|
|||
|
||||
while (w >= 4)
|
||||
{
|
||||
CARD32 s0, s1, s2, s3;
|
||||
unsigned char a0, a1, a2, a3;
|
||||
__m64 vsrc0, vsrc1, vsrc2, vsrc3;
|
||||
|
||||
s0 = *src;
|
||||
s1 = *(src + 1);
|
||||
s2 = *(src + 2);
|
||||
s3 = *(src + 3);
|
||||
|
||||
a0 = (s0 >> 24);
|
||||
a1 = (s1 >> 24);
|
||||
a2 = (s2 >> 24);
|
||||
a3 = (s3 >> 24);
|
||||
|
||||
vsrc0 = load8888(s0);
|
||||
vsrc1 = load8888(s1);
|
||||
vsrc2 = load8888(s2);
|
||||
vsrc3 = load8888(s3);
|
||||
|
||||
if ((a0 & a1 & a2 & a3) == 0xFF)
|
||||
{
|
||||
__m64 vdest;
|
||||
vdest = pack565(vsrc0, _mm_setzero_si64(), 0);
|
||||
vdest = pack565(vsrc1, vdest, 1);
|
||||
vdest = pack565(vsrc2, vdest, 2);
|
||||
vdest = pack565(vsrc3, vdest, 3);
|
||||
|
||||
*(__m64 *)dst = vdest;
|
||||
}
|
||||
else if (a0 | a1 | a2 | a3)
|
||||
{
|
||||
__m64 vdest = *(__m64 *)dst;
|
||||
vsrc0 = load8888(*(src + 0));
|
||||
vsrc1 = load8888(*(src + 1));
|
||||
vsrc2 = load8888(*(src + 2));
|
||||
vsrc3 = load8888(*(src + 3));
|
||||
|
||||
vdest = *(__m64 *)dst;
|
||||
|
||||
vdest = pack565(over(vsrc0, expand_alpha(vsrc0), expand565(vdest, 0)), vdest, 0);
|
||||
vdest = pack565(over(vsrc1, expand_alpha(vsrc1), expand565(vdest, 1)), vdest, 1);
|
||||
|
@ -1536,7 +1516,6 @@ fbCompositeSrc_8888x0565mmx (pixman_operator_t op,
|
|||
vdest = pack565(over(vsrc3, expand_alpha(vsrc3), expand565(vdest, 3)), vdest, 3);
|
||||
|
||||
*(__m64 *)dst = vdest;
|
||||
}
|
||||
|
||||
w -= 4;
|
||||
dst += 4;
|
||||
|
@ -1617,7 +1596,7 @@ fbCompositeSolidMask_nx8x8888mmx (pixman_operator_t op,
|
|||
|
||||
if (m)
|
||||
{
|
||||
__m64 vdest = in_over(vsrc, vsrca, expand_alpha_rev (*(__m64*)(&m)), load8888(*dst));
|
||||
__m64 vdest = in_over(vsrc, vsrca, expand_alpha_rev (M64(m)), load8888(*dst));
|
||||
*dst = store8888(vdest);
|
||||
}
|
||||
|
||||
|
@ -1645,8 +1624,8 @@ fbCompositeSolidMask_nx8x8888mmx (pixman_operator_t op,
|
|||
|
||||
vdest = *(__m64 *)dst;
|
||||
|
||||
dest0 = in_over(vsrc, vsrca, expand_alpha_rev (*(__m64*)(&m0)), expand8888(vdest, 0));
|
||||
dest1 = in_over(vsrc, vsrca, expand_alpha_rev (*(__m64*)(&m1)), expand8888(vdest, 1));
|
||||
dest0 = in_over(vsrc, vsrca, expand_alpha_rev (M64(m0)), expand8888(vdest, 0));
|
||||
dest1 = in_over(vsrc, vsrca, expand_alpha_rev (M64(m1)), expand8888(vdest, 1));
|
||||
|
||||
*(__m64 *)dst = pack8888(dest0, dest1);
|
||||
}
|
||||
|
@ -1665,7 +1644,7 @@ fbCompositeSolidMask_nx8x8888mmx (pixman_operator_t op,
|
|||
if (m)
|
||||
{
|
||||
__m64 vdest = load8888(*dst);
|
||||
vdest = in_over(vsrc, vsrca, expand_alpha_rev (*(__m64*)(&m)), vdest);
|
||||
vdest = in_over(vsrc, vsrca, expand_alpha_rev (M64(m)), vdest);
|
||||
*dst = store8888(vdest);
|
||||
}
|
||||
|
||||
|
@ -1735,7 +1714,7 @@ fbCompositeSolidMaskSrc_nx8x8888mmx (pixman_operator_t op,
|
|||
|
||||
if (m)
|
||||
{
|
||||
__m64 vdest = in(vsrc, expand_alpha_rev (*(__m64*)(&m)));
|
||||
__m64 vdest = in(vsrc, expand_alpha_rev (M64(m)));
|
||||
*dst = store8888(vdest);
|
||||
}
|
||||
else
|
||||
|
@ -1767,8 +1746,8 @@ fbCompositeSolidMaskSrc_nx8x8888mmx (pixman_operator_t op,
|
|||
|
||||
vdest = *(__m64 *)dst;
|
||||
|
||||
dest0 = in(vsrc, expand_alpha_rev (*(__m64*)(&m0)));
|
||||
dest1 = in(vsrc, expand_alpha_rev (*(__m64*)(&m1)));
|
||||
dest0 = in(vsrc, expand_alpha_rev (M64(m0)));
|
||||
dest1 = in(vsrc, expand_alpha_rev (M64(m1)));
|
||||
|
||||
*(__m64 *)dst = pack8888(dest0, dest1);
|
||||
}
|
||||
|
@ -1791,7 +1770,7 @@ fbCompositeSolidMaskSrc_nx8x8888mmx (pixman_operator_t op,
|
|||
if (m)
|
||||
{
|
||||
__m64 vdest = load8888(*dst);
|
||||
vdest = in(vsrc, expand_alpha_rev (*(__m64*)(&m)));
|
||||
vdest = in(vsrc, expand_alpha_rev (M64(m)));
|
||||
*dst = store8888(vdest);
|
||||
}
|
||||
else
|
||||
|
@ -1846,7 +1825,7 @@ fbCompositeSolidMask_nx8x0565mmx (pixman_operator_t op,
|
|||
vsrca = expand_alpha (vsrc);
|
||||
|
||||
vsrc16 = pack565(vsrc, _mm_setzero_si64(), 0);
|
||||
src16 = *(ullong*)(&vsrc16);
|
||||
src16 = *(ullong*)(void*)(&vsrc16);
|
||||
|
||||
srcsrcsrcsrc = (ullong)src16 << 48 | (ullong)src16 << 32 |
|
||||
(ullong)src16 << 16 | (ullong)src16;
|
||||
|
@ -1868,7 +1847,7 @@ fbCompositeSolidMask_nx8x0565mmx (pixman_operator_t op,
|
|||
if (m)
|
||||
{
|
||||
__m64 vd = _mm_cvtsi32_si64 (*dst);
|
||||
__m64 vdest = in_over(vsrc, vsrca, expand_alpha_rev (*(__m64*)(&m)), expand565(vd, 0));
|
||||
__m64 vdest = in_over(vsrc, vsrca, expand_alpha_rev (M64(m)), expand565(vd, 0));
|
||||
*dst = _mm_cvtsi64_si32 (pack565(vdest, _mm_setzero_si64(), 0));
|
||||
}
|
||||
|
||||
|
@ -1898,13 +1877,13 @@ fbCompositeSolidMask_nx8x0565mmx (pixman_operator_t op,
|
|||
|
||||
vdest = *(__m64 *)dst;
|
||||
|
||||
vm0 = *(__m64*)(&m0);
|
||||
vm0 = M64(m0);
|
||||
vdest = pack565(in_over(vsrc, vsrca, expand_alpha_rev(vm0), expand565(vdest, 0)), vdest, 0);
|
||||
vm1 = *(__m64*)(&m1);
|
||||
vm1 = M64(m1);
|
||||
vdest = pack565(in_over(vsrc, vsrca, expand_alpha_rev(vm1), expand565(vdest, 1)), vdest, 1);
|
||||
vm2 = *(__m64*)(&m2);
|
||||
vm2 = M64(m2);
|
||||
vdest = pack565(in_over(vsrc, vsrca, expand_alpha_rev(vm2), expand565(vdest, 2)), vdest, 2);
|
||||
vm3 = *(__m64*)(&m3);
|
||||
vm3 = M64(m3);
|
||||
vdest = pack565(in_over(vsrc, vsrca, expand_alpha_rev(vm3), expand565(vdest, 3)), vdest, 3);
|
||||
|
||||
*(__m64 *)dst = vdest;
|
||||
|
@ -1924,7 +1903,7 @@ fbCompositeSolidMask_nx8x0565mmx (pixman_operator_t op,
|
|||
if (m)
|
||||
{
|
||||
__m64 vd = _mm_cvtsi32_si64 (*dst);
|
||||
__m64 vdest = in_over(vsrc, vsrca, expand_alpha_rev (*(__m64*)(&m)), expand565(vd, 0));
|
||||
__m64 vdest = in_over(vsrc, vsrca, expand_alpha_rev (M64(m)), expand565(vd, 0));
|
||||
*dst = _mm_cvtsi64_si32 (pack565(vdest, _mm_setzero_si64(), 0));
|
||||
}
|
||||
|
||||
|
@ -2655,7 +2634,7 @@ fbSolidFillmmx (FbPixels *pDraw,
|
|||
}
|
||||
|
||||
fill = ((ullong)xor << 32) | xor;
|
||||
vfill = *(__m64*)&fill;
|
||||
vfill = M64(fill);
|
||||
|
||||
while (height--)
|
||||
{
|
||||
|
|
|
@ -2123,7 +2123,9 @@ static unsigned int detectCPUFeatures(void) {
|
|||
features |= SSE;
|
||||
if (result & (1 << 26))
|
||||
features |= SSE2;
|
||||
if ((result & MMX) && !(result & SSE) && (strcmp(vendor, "AuthenticAMD") == 0)) {
|
||||
if ((features & MMX) && !(features & SSE) &&
|
||||
(strcmp(vendor, "AuthenticAMD") == 0 ||
|
||||
strcmp(vendor, "Geode by NSC") == 0)) {
|
||||
/* check for AMD MMX extensions */
|
||||
#ifdef __GNUC__
|
||||
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* $Id: fbtrap.c,v 1.14 2007/04/03 18:59:49 vladimir%pobox.com Exp $
|
||||
* $Id: fbtrap.c,v 1.15 2007/04/04 01:09:16 vladimir%pobox.com Exp $
|
||||
*
|
||||
* Copyright © 2004 Keith Packard
|
||||
*
|
||||
|
|
|
@ -247,7 +247,6 @@ pixman_image_create_radial_gradient (const pixman_radial_gradient_t *gradient,
|
|||
{
|
||||
pixman_radial_gradient_image_t *radial;
|
||||
pixman_image_t *image;
|
||||
double x;
|
||||
|
||||
if (n_stops < 2)
|
||||
return NULL;
|
||||
|
@ -270,19 +269,14 @@ pixman_image_create_radial_gradient (const pixman_radial_gradient_t *gradient,
|
|||
memcpy (radial->stops, stops, sizeof (pixman_gradient_stop_t) * n_stops);
|
||||
|
||||
radial->type = SourcePictTypeRadial;
|
||||
x = (double) gradient->inner.radius / (double) gradient->outer.radius;
|
||||
radial->dx = (gradient->outer.x - gradient->inner.x);
|
||||
radial->dy = (gradient->outer.y - gradient->inner.y);
|
||||
radial->fx = (gradient->inner.x) - x * radial->dx;
|
||||
radial->fy = (gradient->inner.y) - x * radial->dy;
|
||||
radial->m = 1. / (1 + x);
|
||||
radial->b = -x * radial->m;
|
||||
radial->dx /= 65536.;
|
||||
radial->dy /= 65536.;
|
||||
radial->fx /= 65536.;
|
||||
radial->fy /= 65536.;
|
||||
x = gradient->outer.radius / 65536.;
|
||||
radial->a = x * x - radial->dx * radial->dx - radial->dy * radial->dy;
|
||||
radial->c1 = gradient->c1;
|
||||
radial->c2 = gradient->c2;
|
||||
radial->cdx = xFixedToDouble (gradient->c2.x - gradient->c1.x);
|
||||
radial->cdy = xFixedToDouble (gradient->c2.y - gradient->c1.y);
|
||||
radial->dr = xFixedToDouble (gradient->c2.radius - gradient->c1.radius);
|
||||
radial->A = ( radial->cdx * radial->cdx
|
||||
+ radial->cdy * radial->cdy
|
||||
- radial->dr * radial->dr);
|
||||
|
||||
image->pSourcePict = (pixman_source_image_t *) radial;
|
||||
|
||||
|
|
|
@ -101,13 +101,12 @@ typedef struct _pixman_radial_gradient_image {
|
|||
int stopRange;
|
||||
uint32_t *colorTable;
|
||||
int colorTableSize;
|
||||
double fx;
|
||||
double fy;
|
||||
double dx;
|
||||
double dy;
|
||||
double a;
|
||||
double m;
|
||||
double b;
|
||||
pixman_circle_t c1;
|
||||
pixman_circle_t c2;
|
||||
double cdx;
|
||||
double cdy;
|
||||
double dr;
|
||||
double A;
|
||||
} pixman_radial_gradient_image_t;
|
||||
|
||||
typedef struct _pixman_conical_gradient_image {
|
||||
|
|
|
@ -1026,6 +1026,7 @@ typedef xFixed_16_16 xFixed;
|
|||
#define IntToxFixed(i) ((xFixed) (i) << XFIXED_BITS)
|
||||
#define xFixedE ((xFixed) 1)
|
||||
#define xFixed1 (IntToxFixed(1))
|
||||
#define xFixedToDouble(f) (double) ((f) / (double) xFixed1)
|
||||
#define xFixed1MinusE (xFixed1 - xFixedE)
|
||||
#define xFixedFrac(f) ((f) & xFixed1MinusE)
|
||||
#define xFixedFloor(f) ((f) & ~xFixed1MinusE)
|
||||
|
|
|
@ -1,80 +1,80 @@
|
|||
#define pixman_add_trapezoids _moz_cairo_pixman_add_trapezoids
|
||||
#define pixman_color_to_pixel _moz_cairo_pixman_color_to_pixel
|
||||
#define composeFunctions _moz_cairo_pixman_compose_functions
|
||||
#define fbComposeSetupMMX _moz_cairo_pixman_compose_setup_mmx
|
||||
#define pixman_composite _moz_cairo_pixman_composite
|
||||
#define fbCompositeCopyAreammx _moz_cairo_pixman_composite_copy_area_mmx
|
||||
#define fbCompositeSolidMask_nx8888x0565Cmmx _moz_cairo_pixman_composite_solid_mask_nx8888x0565Cmmx
|
||||
#define fbCompositeSolidMask_nx8888x8888Cmmx _moz_cairo_pixman_composite_solid_mask_nx8888x8888Cmmx
|
||||
#define fbCompositeSolidMask_nx8x0565mmx _moz_cairo_pixman_composite_solid_mask_nx8x0565mmx
|
||||
#define fbCompositeSolidMask_nx8x8888mmx _moz_cairo_pixman_composite_solid_mask_nx8x8888mmx
|
||||
#define fbCompositeSolidMaskSrc_nx8x8888mmx _moz_cairo_pixman_composite_solid_mask_src_nx8x8888mmx
|
||||
#define fbCompositeSolid_nx0565mmx _moz_cairo_pixman_composite_solid_nx0565mmx
|
||||
#define fbCompositeSolid_nx8888mmx _moz_cairo_pixman_composite_solid_nx8888mmx
|
||||
#define fbCompositeSrc_8888RevNPx0565mmx _moz_cairo_pixman_composite_src_8888RevNPx0565mmx
|
||||
#define fbCompositeSrc_8888RevNPx8888mmx _moz_cairo_pixman_composite_src_8888RevNPx8888_mmx
|
||||
#define fbCompositeSrc_8888x0565mmx _moz_cairo_pixman_composite_src_8888x0565mmx
|
||||
#define fbCompositeSrc_8888x8888mmx _moz_cairo_pixman_composite_src_8888x8888mmx
|
||||
#define fbCompositeSrc_8888x8x8888mmx _moz_cairo_pixman_composite_src_8888x8x8888mmx
|
||||
#define fbCompositeSrcAdd_8000x8000mmx _moz_cairo_pixman_composite_src_add_8000x8000mmx
|
||||
#define fbCompositeSrcAdd_8888x8888mmx _moz_cairo_pixman_composite_src_add_8888x8888mmx
|
||||
#define fbCompositeSrc_x888x8x8888mmx _moz_cairo_pixman_composite_src_x888x8x8888mmx
|
||||
#define pixman_composite_trapezoids _moz_cairo_pixman_composite_trapezoids
|
||||
#define pixman_composite_tri_fan _moz_cairo_pixman_composite_tri_fan
|
||||
#define pixman_composite_tri_strip _moz_cairo_pixman_composite_tri_strip
|
||||
#define pixman_composite_triangles _moz_cairo_pixman_composite_triangles
|
||||
#define fbCopyAreammx _moz_cairo_pixman_copy_area_mmx
|
||||
#define pixman_fill_rectangle _moz_cairo_pixman_fill_rectangle
|
||||
#define pixman_fill_rectangles _moz_cairo_pixman_fill_rectangles
|
||||
#define pixman_format_create _moz_cairo_pixman_format_create
|
||||
#define pixman_format_create_masks _moz_cairo_pixman_format_create_masks
|
||||
#define pixman_format_destroy _moz_cairo_pixman_format_destroy
|
||||
#define pixman_format_get_masks _moz_cairo_pixman_format_get_masks
|
||||
#define pixman_format_init _moz_cairo_pixman_format_init
|
||||
#define pixman_add_trapezoids _cairo_pixman_add_trapezoids
|
||||
#define pixman_color_to_pixel _cairo_pixman_color_to_pixel
|
||||
#define composeFunctions _cairo_pixman_compose_functions
|
||||
#define fbComposeSetupMMX _cairo_pixman_compose_setup_mmx
|
||||
#define pixman_composite _cairo_pixman_composite
|
||||
#define fbCompositeCopyAreammx _cairo_pixman_composite_copy_area_mmx
|
||||
#define fbCompositeSolidMask_nx8888x0565Cmmx _cairo_pixman_composite_solid_mask_nx8888x0565Cmmx
|
||||
#define fbCompositeSolidMask_nx8888x8888Cmmx _cairo_pixman_composite_solid_mask_nx8888x8888Cmmx
|
||||
#define fbCompositeSolidMask_nx8x0565mmx _cairo_pixman_composite_solid_mask_nx8x0565mmx
|
||||
#define fbCompositeSolidMask_nx8x8888mmx _cairo_pixman_composite_solid_mask_nx8x8888mmx
|
||||
#define fbCompositeSolidMaskSrc_nx8x8888mmx _cairo_pixman_composite_solid_mask_src_nx8x8888mmx
|
||||
#define fbCompositeSolid_nx0565mmx _cairo_pixman_composite_solid_nx0565mmx
|
||||
#define fbCompositeSolid_nx8888mmx _cairo_pixman_composite_solid_nx8888mmx
|
||||
#define fbCompositeSrc_8888RevNPx0565mmx _cairo_pixman_composite_src_8888RevNPx0565mmx
|
||||
#define fbCompositeSrc_8888RevNPx8888mmx _cairo_pixman_composite_src_8888RevNPx8888_mmx
|
||||
#define fbCompositeSrc_8888x0565mmx _cairo_pixman_composite_src_8888x0565mmx
|
||||
#define fbCompositeSrc_8888x8888mmx _cairo_pixman_composite_src_8888x8888mmx
|
||||
#define fbCompositeSrc_8888x8x8888mmx _cairo_pixman_composite_src_8888x8x8888mmx
|
||||
#define fbCompositeSrcAdd_8000x8000mmx _cairo_pixman_composite_src_add_8000x8000mmx
|
||||
#define fbCompositeSrcAdd_8888x8888mmx _cairo_pixman_composite_src_add_8888x8888mmx
|
||||
#define fbCompositeSrc_x888x8x8888mmx _cairo_pixman_composite_src_x888x8x8888mmx
|
||||
#define pixman_composite_trapezoids _cairo_pixman_composite_trapezoids
|
||||
#define pixman_composite_tri_fan _cairo_pixman_composite_tri_fan
|
||||
#define pixman_composite_tri_strip _cairo_pixman_composite_tri_strip
|
||||
#define pixman_composite_triangles _cairo_pixman_composite_triangles
|
||||
#define fbCopyAreammx _cairo_pixman_copy_area_mmx
|
||||
#define pixman_fill_rectangle _cairo_pixman_fill_rectangle
|
||||
#define pixman_fill_rectangles _cairo_pixman_fill_rectangles
|
||||
#define pixman_format_create _cairo_pixman_format_create
|
||||
#define pixman_format_create_masks _cairo_pixman_format_create_masks
|
||||
#define pixman_format_destroy _cairo_pixman_format_destroy
|
||||
#define pixman_format_get_masks _cairo_pixman_format_get_masks
|
||||
#define pixman_format_init _cairo_pixman_format_init
|
||||
#if defined(USE_MMX) && !defined(__amd64__) && !defined(__x86_64__)
|
||||
#define fbHaveMMX _moz_cairo_pixman_have_mmx
|
||||
#define fbHaveMMX _cairo_pixman_have_mmx
|
||||
#endif
|
||||
#define pixman_image_create _moz_cairo_pixman_image_create
|
||||
#define pixman_image_create_for_data _moz_cairo_pixman_image_create_for_data
|
||||
#define pixman_image_destroy _moz_cairo_pixman_image_destroy
|
||||
#define pixman_image_get_data _moz_cairo_pixman_image_get_data
|
||||
#define pixman_image_get_depth _moz_cairo_pixman_image_get_depth
|
||||
#define pixman_image_get_format _moz_cairo_pixman_image_get_format
|
||||
#define pixman_image_get_height _moz_cairo_pixman_image_get_height
|
||||
#define pixman_image_get_stride _moz_cairo_pixman_image_get_stride
|
||||
#define pixman_image_get_width _moz_cairo_pixman_image_get_width
|
||||
#define pixman_image_set_clip_region _moz_cairo_pixman_image_set_clip_region
|
||||
#define pixman_image_set_component_alpha _moz_cairo_pixman_image_set_component_alpha
|
||||
#define pixman_image_set_filter _moz_cairo_pixman_image_set_filter
|
||||
#define pixman_image_set_repeat _moz_cairo_pixman_image_set_repeat
|
||||
#define pixman_image_set_transform _moz_cairo_pixman_image_set_transform
|
||||
#define pixman_image_create_linear_gradient _moz_cairo_pixman_image_create_linear_gradient
|
||||
#define pixman_image_create_radial_gradient _moz_cairo_pixman_image_create_radial_gradient
|
||||
#define miIsSolidAlpha _moz_cairo_pixman_is_solid_alpha
|
||||
#define pixman_pixel_to_color _moz_cairo_pixman_pixel_to_color
|
||||
#define pixman_region_append _moz_cairo_pixman_region_append
|
||||
#define pixman_region_contains_point _moz_cairo_pixman_region_contains_point
|
||||
#define pixman_region_contains_rectangle _moz_cairo_pixman_region_contains_rectangle
|
||||
#define pixman_region_copy _moz_cairo_pixman_region_copy
|
||||
#define pixman_region_create _moz_cairo_pixman_region_create
|
||||
#define pixman_region_create_simple _moz_cairo_pixman_region_create_simple
|
||||
#define pixman_region_destroy _moz_cairo_pixman_region_destroy
|
||||
#define pixman_region_empty _moz_cairo_pixman_region_empty
|
||||
#define pixman_region_extents _moz_cairo_pixman_region_extents
|
||||
#define pixman_region_intersect _moz_cairo_pixman_region_intersect
|
||||
#define pixman_region_inverse _moz_cairo_pixman_region_inverse
|
||||
#define pixman_region_not_empty _moz_cairo_pixman_region_not_empty
|
||||
#define pixman_region_num_rects _moz_cairo_pixman_region_num_rects
|
||||
#define pixman_region_rects _moz_cairo_pixman_region_rects
|
||||
#define pixman_region_reset _moz_cairo_pixman_region_reset
|
||||
#define pixman_region_subtract _moz_cairo_pixman_region_subtract
|
||||
#define pixman_region_translate _moz_cairo_pixman_region_translate
|
||||
#define pixman_region_union _moz_cairo_pixman_region_union
|
||||
#define pixman_region_union_rect _moz_cairo_pixman_region_union_rect
|
||||
#define pixman_region_validate _moz_cairo_pixman_region_validate
|
||||
#define RenderEdgeInit _moz_cairo_pixman_render_edge_init
|
||||
#define RenderEdgeStep _moz_cairo_pixman_render_edge_step
|
||||
#define RenderLineFixedEdgeInit _moz_cairo_pixman_render_line_fixed_edge_init
|
||||
#define RenderSampleCeilY _moz_cairo_pixman_render_sample_ceil_y
|
||||
#define RenderSampleFloorY _moz_cairo_pixman_render_sample_floor_y
|
||||
#define fbSolidFillmmx _moz_cairo_pixman_solid_fill_mmx
|
||||
#define pixman_image_create _cairo_pixman_image_create
|
||||
#define pixman_image_create_for_data _cairo_pixman_image_create_for_data
|
||||
#define pixman_image_destroy _cairo_pixman_image_destroy
|
||||
#define pixman_image_get_data _cairo_pixman_image_get_data
|
||||
#define pixman_image_get_depth _cairo_pixman_image_get_depth
|
||||
#define pixman_image_get_format _cairo_pixman_image_get_format
|
||||
#define pixman_image_get_height _cairo_pixman_image_get_height
|
||||
#define pixman_image_get_stride _cairo_pixman_image_get_stride
|
||||
#define pixman_image_get_width _cairo_pixman_image_get_width
|
||||
#define pixman_image_set_clip_region _cairo_pixman_image_set_clip_region
|
||||
#define pixman_image_set_component_alpha _cairo_pixman_image_set_component_alpha
|
||||
#define pixman_image_set_filter _cairo_pixman_image_set_filter
|
||||
#define pixman_image_set_repeat _cairo_pixman_image_set_repeat
|
||||
#define pixman_image_set_transform _cairo_pixman_image_set_transform
|
||||
#define pixman_image_create_linear_gradient _cairo_pixman_image_create_linear_gradient
|
||||
#define pixman_image_create_radial_gradient _cairo_pixman_image_create_radial_gradient
|
||||
#define miIsSolidAlpha _cairo_pixman_is_solid_alpha
|
||||
#define pixman_pixel_to_color _cairo_pixman_pixel_to_color
|
||||
#define pixman_region_append _cairo_pixman_region_append
|
||||
#define pixman_region_contains_point _cairo_pixman_region_contains_point
|
||||
#define pixman_region_contains_rectangle _cairo_pixman_region_contains_rectangle
|
||||
#define pixman_region_copy _cairo_pixman_region_copy
|
||||
#define pixman_region_create _cairo_pixman_region_create
|
||||
#define pixman_region_create_simple _cairo_pixman_region_create_simple
|
||||
#define pixman_region_destroy _cairo_pixman_region_destroy
|
||||
#define pixman_region_empty _cairo_pixman_region_empty
|
||||
#define pixman_region_extents _cairo_pixman_region_extents
|
||||
#define pixman_region_intersect _cairo_pixman_region_intersect
|
||||
#define pixman_region_inverse _cairo_pixman_region_inverse
|
||||
#define pixman_region_not_empty _cairo_pixman_region_not_empty
|
||||
#define pixman_region_num_rects _cairo_pixman_region_num_rects
|
||||
#define pixman_region_rects _cairo_pixman_region_rects
|
||||
#define pixman_region_reset _cairo_pixman_region_reset
|
||||
#define pixman_region_subtract _cairo_pixman_region_subtract
|
||||
#define pixman_region_translate _cairo_pixman_region_translate
|
||||
#define pixman_region_union _cairo_pixman_region_union
|
||||
#define pixman_region_union_rect _cairo_pixman_region_union_rect
|
||||
#define pixman_region_validate _cairo_pixman_region_validate
|
||||
#define RenderEdgeInit _cairo_pixman_render_edge_init
|
||||
#define RenderEdgeStep _cairo_pixman_render_edge_step
|
||||
#define RenderLineFixedEdgeInit _cairo_pixman_render_line_fixed_edge_init
|
||||
#define RenderSampleCeilY _cairo_pixman_render_sample_ceil_y
|
||||
#define RenderSampleFloorY _cairo_pixman_render_sample_floor_y
|
||||
#define fbSolidFillmmx _cairo_pixman_solid_fill_mmx
|
||||
|
|
|
@ -99,7 +99,7 @@ SOFTWARE.
|
|||
|
||||
#include "pixman-remap.h"
|
||||
|
||||
#if (__GNUC__ > 3 || (__GNUC__ == 3 && __GNUC_MINOR__ >= 3)) && defined(__ELF__)
|
||||
#if (__GNUC__ > 3 || (__GNUC__ == 3 && __GNUC_MINOR__ >= 3)) && defined(__ELF__) && !defined(__sun__)
|
||||
#define pixman_private __attribute__((__visibility__("hidden")))
|
||||
#elif defined(__SUNPRO_C) && (__SUNPRO_C >= 0x550)
|
||||
#define pixman_private __hidden
|
||||
|
@ -364,8 +364,8 @@ typedef struct pixman_linear_gradient {
|
|||
} pixman_linear_gradient_t;
|
||||
|
||||
typedef struct pixman_radial_gradient {
|
||||
pixman_circle_t inner;
|
||||
pixman_circle_t outer;
|
||||
pixman_circle_t c1;
|
||||
pixman_circle_t c2;
|
||||
} pixman_radial_gradient_t;
|
||||
|
||||
typedef enum {
|
||||
|
|
|
@ -1,106 +0,0 @@
|
|||
/* slim - Shared Library Interface Macros
|
||||
*
|
||||
* Copyright © 2003 Richard Henderson
|
||||
*
|
||||
* 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 Richard Henderson
|
||||
* not be used in advertising or publicity pertaining to distribution
|
||||
* of the software without specific, written prior permission.
|
||||
* Richard Henderson makes no representations about the suitability of this
|
||||
* software for any purpose. It is provided "as is" without express
|
||||
* or implied warranty.
|
||||
*
|
||||
* RICHARD HENDERSON DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
|
||||
* INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN
|
||||
* NO EVENT SHALL RICHARD HENDERSON 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: Richard Henderson <rth@twiddle.net>
|
||||
*/
|
||||
|
||||
#ifndef _SLIM_INTERNAL_H_
|
||||
#define _SLIM_INTERNAL_H_ 1
|
||||
|
||||
/* XXX THIS DOCUMENTATION IS BLOODY WRONG. SOMEONE DID NOT ACTUALLY
|
||||
CONSULT WITH THE COMPILERS THEY CLAIMED TO SUPPORT */
|
||||
/* This macro marks a symbol as STV_HIDDEN, which prevents it from being
|
||||
added to the dynamic symbol table of the shared library. This prevents
|
||||
users of the library from knowingly or unknowingly accessing library
|
||||
internals that may change in future releases. It also allows the
|
||||
compiler to generate slightly more efficient code in some cases.
|
||||
|
||||
The macro should be placed either immediately before the return type in
|
||||
a function declaration:
|
||||
|
||||
pixman_private int
|
||||
somefunction(void);
|
||||
|
||||
or after a data name,
|
||||
XXX THIS IS WRONG. YOU CAN NOT DO THIS WITH THE COMPILERS THAT
|
||||
THIS PACKAGE CLAIMS TO SUPPORT.
|
||||
extern int somedata pixman_private;
|
||||
|
||||
The ELF visibility attribute did not exist before gcc 3.3. */
|
||||
/* ??? Not marked with "slim" because that makes it look too much
|
||||
like the function name instead of just an attribute. */
|
||||
|
||||
#if (__GNUC__ > 3 || (__GNUC__ == 3 && __GNUC_MINOR__ >= 3)) && defined(__ELF__)
|
||||
#define pixman_private __attribute__((__visibility__("hidden")))
|
||||
#elif defined(__SUNPRO_C) && (__SUNPRO_C >= 0x550)
|
||||
#define pixman_private __hidden
|
||||
#else /* not gcc >= 3.3 and not Sun Studio >= 8 */
|
||||
#define pixman_private
|
||||
#endif
|
||||
|
||||
/* The following macros are used for PLT bypassing. First of all,
|
||||
you need to have the function prototyped somewhere, say in foo.h:
|
||||
|
||||
int foo (int __bar);
|
||||
|
||||
If calls to foo within libfoo.so should always go to foo defined
|
||||
in libfoo.so, then in fooint.h you add:
|
||||
|
||||
slim_hidden_proto (foo)
|
||||
|
||||
and after the foo function definition:
|
||||
|
||||
int foo (int __bar)
|
||||
{
|
||||
return __bar;
|
||||
}
|
||||
slim_hidden_def (foo);
|
||||
|
||||
This works by arranging for the C symbol "foo" to be renamed to
|
||||
"INT_foo" at the assembly level, which is marked pixman_private.
|
||||
We then create another symbol at the same address (an alias) with
|
||||
the C symbol "EXT_foo", which is renamed to "foo" at the assembly
|
||||
level. */
|
||||
|
||||
#if __GNUC__ >= 3 && defined(__ELF__)
|
||||
# define slim_hidden_proto(name) slim_hidden_proto1(name, slim_hidden_int_name(name))
|
||||
# define slim_hidden_def(name) slim_hidden_def1(name, slim_hidden_int_name(name))
|
||||
# define slim_hidden_int_name(name) INT_##name
|
||||
# define slim_hidden_proto1(name, internal) \
|
||||
extern __typeof (name) name \
|
||||
__asm__ (slim_hidden_asmname (internal)) \
|
||||
pixman_private;
|
||||
# define slim_hidden_def1(name, internal) \
|
||||
extern __typeof (name) EXT_##name __asm__(slim_hidden_asmname(name)) \
|
||||
__attribute__((__alias__(slim_hidden_asmname(internal))))
|
||||
# define slim_hidden_ulp slim_hidden_ulp1(__USER_LABEL_PREFIX__)
|
||||
# define slim_hidden_ulp1(x) slim_hidden_ulp2(x)
|
||||
# define slim_hidden_ulp2(x) #x
|
||||
# define slim_hidden_asmname(name) slim_hidden_asmname1(name)
|
||||
# define slim_hidden_asmname1(name) slim_hidden_ulp #name
|
||||
#else
|
||||
# define slim_hidden_proto(name)
|
||||
# define slim_hidden_def(name)
|
||||
#endif
|
||||
|
||||
#endif /* _SLIM_INTERNAL_H_ */
|
|
@ -150,7 +150,7 @@ nsThebesDeviceContext::SetDPI()
|
|||
if (mPrintingSurface &&
|
||||
(mPrintingSurface->GetType() == gfxASurface::SurfaceTypePDF ||
|
||||
mPrintingSurface->GetType() == gfxASurface::SurfaceTypePS ||
|
||||
mPrintingSurface->GetType() == gfxASurface::SurfaceTypeQuartz2)) {
|
||||
mPrintingSurface->GetType() == gfxASurface::SurfaceTypeQuartz)) {
|
||||
dpi = 72;
|
||||
dotsArePixels = PR_FALSE;
|
||||
} else {
|
||||
|
@ -700,7 +700,7 @@ nsThebesDeviceContext::CalcPrintingSize()
|
|||
#endif
|
||||
|
||||
#ifdef XP_MACOSX
|
||||
case gfxASurface::SurfaceTypeQuartz2:
|
||||
case gfxASurface::SurfaceTypeQuartz:
|
||||
inPoints = PR_TRUE; // this is really only true when we're printing
|
||||
size = reinterpret_cast<gfxQuartzSurface*>(mPrintingSurface.get())->GetSize();
|
||||
break;
|
||||
|
|
|
@ -81,7 +81,6 @@ public:
|
|||
SurfaceTypeBeOS,
|
||||
SurfaceTypeDirectFB,
|
||||
SurfaceTypeSVG,
|
||||
SurfaceTypeQuartz2,
|
||||
SurfaceTypeOS2
|
||||
} gfxSurfaceType;
|
||||
|
||||
|
|
|
@ -46,7 +46,7 @@
|
|||
class THEBES_API gfxQuartzSurface : public gfxASurface {
|
||||
public:
|
||||
gfxQuartzSurface(const gfxSize& size, gfxImageFormat format);
|
||||
gfxQuartzSurface(CGContextRef context, PRBool y_grows_down, const gfxSize& size);
|
||||
gfxQuartzSurface(CGContextRef context, const gfxSize& size);
|
||||
gfxQuartzSurface(cairo_surface_t *csurf);
|
||||
|
||||
virtual ~gfxQuartzSurface();
|
||||
|
|
|
@ -50,7 +50,7 @@
|
|||
#include "gfxXlibSurface.h"
|
||||
#endif
|
||||
|
||||
#ifdef CAIRO_HAS_NQUARTZ_SURFACE
|
||||
#ifdef CAIRO_HAS_QUARTZ_SURFACE
|
||||
#include "gfxQuartzSurface.h"
|
||||
#endif
|
||||
|
||||
|
@ -139,8 +139,8 @@ gfxASurface::Wrap (cairo_surface_t *csurf)
|
|||
result = new gfxXlibSurface(csurf);
|
||||
}
|
||||
#endif
|
||||
#ifdef CAIRO_HAS_NQUARTZ_SURFACE
|
||||
else if (stype == CAIRO_SURFACE_TYPE_NQUARTZ) {
|
||||
#ifdef CAIRO_HAS_QUARTZ_SURFACE
|
||||
else if (stype == CAIRO_SURFACE_TYPE_QUARTZ) {
|
||||
result = new gfxQuartzSurface(csurf);
|
||||
}
|
||||
#endif
|
||||
|
|
|
@ -108,12 +108,60 @@ gfxMatrix::Transform(const gfxRect& rect) const
|
|||
gfxRect
|
||||
gfxMatrix::TransformBounds(const gfxRect& rect) const
|
||||
{
|
||||
double x0 = rect.pos.x;
|
||||
double y0 = rect.pos.y;
|
||||
double x1 = rect.pos.x + rect.size.width;
|
||||
double y1 = rect.pos.y + rect.size.height;
|
||||
/* Code taken from cairo-matrix.c, _cairo_matrix_transform_bounding_box isn't public */
|
||||
int i;
|
||||
double quad_x[4], quad_y[4];
|
||||
double min_x, max_x;
|
||||
double min_y, max_y;
|
||||
|
||||
cairo_matrix_transform_bounding_box(CONST_CAIRO_MATRIX(this), &x0, &y0, &x1, &y1, NULL);
|
||||
quad_x[0] = rect.pos.x;
|
||||
quad_y[0] = rect.pos.y;
|
||||
cairo_matrix_transform_point (CONST_CAIRO_MATRIX(this), &quad_x[0], &quad_y[0]);
|
||||
|
||||
return gfxRect(x0, y0, x1 - x0, y1 - y0);
|
||||
quad_x[1] = rect.pos.x + rect.size.width;
|
||||
quad_y[1] = rect.pos.y;
|
||||
cairo_matrix_transform_point (CONST_CAIRO_MATRIX(this), &quad_x[1], &quad_y[1]);
|
||||
|
||||
quad_x[2] = rect.pos.x;
|
||||
quad_y[2] = rect.pos.y + rect.size.height;
|
||||
cairo_matrix_transform_point (CONST_CAIRO_MATRIX(this), &quad_x[2], &quad_y[2]);
|
||||
|
||||
quad_x[3] = rect.pos.x + rect.size.width;
|
||||
quad_y[3] = rect.pos.y + rect.size.height;
|
||||
cairo_matrix_transform_point (CONST_CAIRO_MATRIX(this), &quad_x[3], &quad_y[3]);
|
||||
|
||||
min_x = max_x = quad_x[0];
|
||||
min_y = max_y = quad_y[0];
|
||||
|
||||
for (i = 1; i < 4; i++) {
|
||||
if (quad_x[i] < min_x)
|
||||
min_x = quad_x[i];
|
||||
if (quad_x[i] > max_x)
|
||||
max_x = quad_x[i];
|
||||
|
||||
if (quad_y[i] < min_y)
|
||||
min_y = quad_y[i];
|
||||
if (quad_y[i] > max_y)
|
||||
max_y = quad_y[i];
|
||||
}
|
||||
|
||||
// we don't compute this now
|
||||
#if 0
|
||||
if (is_tight) {
|
||||
/* it's tight if and only if the four corner points form an axis-aligned
|
||||
rectangle.
|
||||
And that's true if and only if we can derive corners 0 and 3 from
|
||||
corners 1 and 2 in one of two straightforward ways...
|
||||
We could use a tolerance here but for now we'll fall back to FALSE in the case
|
||||
of floating point error.
|
||||
*/
|
||||
*is_tight =
|
||||
(quad_x[1] == quad_x[0] && quad_y[1] == quad_y[3] &&
|
||||
quad_x[2] == quad_x[3] && quad_y[2] == quad_y[0]) ||
|
||||
(quad_x[1] == quad_x[3] && quad_y[1] == quad_y[0] &&
|
||||
quad_x[2] == quad_x[0] && quad_y[2] == quad_y[3]);
|
||||
}
|
||||
#endif
|
||||
|
||||
return gfxRect(min_x, min_y, max_x - min_x, max_y - min_y);
|
||||
}
|
||||
|
|
|
@ -37,7 +37,7 @@
|
|||
|
||||
#include "gfxQuartzPDFSurface.h"
|
||||
|
||||
#include "cairo-nquartz.h"
|
||||
#include "cairo-quartz.h"
|
||||
|
||||
gfxQuartzPDFSurface::gfxQuartzPDFSurface(const char *filename, gfxSize aSizeInPoints)
|
||||
{
|
||||
|
@ -50,7 +50,7 @@ gfxQuartzPDFSurface::gfxQuartzPDFSurface(const char *filename, gfxSize aSizeInPo
|
|||
CFRelease(file);
|
||||
CFRelease(fileURL);
|
||||
|
||||
Init(cairo_nquartz_surface_create_for_cg_context(mCGContext, aSizeInPoints.width, aSizeInPoints.height, PR_FALSE));
|
||||
Init(cairo_quartz_surface_create_for_cg_context(mCGContext, aSizeInPoints.width, aSizeInPoints.height));
|
||||
}
|
||||
|
||||
gfxQuartzPDFSurface::~gfxQuartzPDFSurface()
|
||||
|
|
|
@ -37,15 +37,15 @@
|
|||
|
||||
#include "gfxQuartzSurface.h"
|
||||
|
||||
#include "cairo-nquartz.h"
|
||||
#include "cairo-quartz.h"
|
||||
|
||||
gfxQuartzSurface::gfxQuartzSurface(const gfxSize& size, gfxImageFormat format)
|
||||
: mSize(size)
|
||||
{
|
||||
cairo_surface_t *surf = cairo_nquartz_surface_create
|
||||
cairo_surface_t *surf = cairo_quartz_surface_create
|
||||
((cairo_format_t) format, floor(size.width), floor(size.height));
|
||||
|
||||
mCGContext = cairo_nquartz_surface_get_cg_context (surf);
|
||||
mCGContext = cairo_quartz_surface_get_cg_context (surf);
|
||||
|
||||
CGContextRetain(mCGContext);
|
||||
|
||||
|
@ -53,15 +53,13 @@ gfxQuartzSurface::gfxQuartzSurface(const gfxSize& size, gfxImageFormat format)
|
|||
}
|
||||
|
||||
gfxQuartzSurface::gfxQuartzSurface(CGContextRef context,
|
||||
PRBool y_grows_down,
|
||||
const gfxSize& size)
|
||||
: mCGContext(context), mSize(size)
|
||||
{
|
||||
cairo_surface_t *surf =
|
||||
cairo_nquartz_surface_create_for_cg_context(context,
|
||||
cairo_quartz_surface_create_for_cg_context(context,
|
||||
floor(size.width),
|
||||
floor(size.height),
|
||||
y_grows_down);
|
||||
floor(size.height));
|
||||
|
||||
CGContextRetain(mCGContext);
|
||||
|
||||
|
@ -71,7 +69,7 @@ gfxQuartzSurface::gfxQuartzSurface(CGContextRef context,
|
|||
gfxQuartzSurface::gfxQuartzSurface(cairo_surface_t *csurf) :
|
||||
mSize(-1.0, -1.0)
|
||||
{
|
||||
mCGContext = cairo_nquartz_surface_get_cg_context (csurf);
|
||||
mCGContext = cairo_quartz_surface_get_cg_context (csurf);
|
||||
CGContextRetain (mCGContext);
|
||||
|
||||
Init(csurf, PR_TRUE);
|
||||
|
|
|
@ -2154,7 +2154,7 @@ NSEvent* globalDragEvent = nil;
|
|||
|
||||
NSRect bounds = [self bounds];
|
||||
nsRefPtr<gfxQuartzSurface> targetSurface =
|
||||
new gfxQuartzSurface(cgContext, PR_TRUE, gfxSize(bounds.size.width, bounds.size.height));
|
||||
new gfxQuartzSurface(cgContext, gfxSize(bounds.size.width, bounds.size.height));
|
||||
|
||||
#ifdef DEBUG_UPDATE
|
||||
fprintf (stderr, "---- Update[%p][%p] [%f %f %f %f] cgc: %p\n gecko bounds: [%d %d %d %d]\n",
|
||||
|
|
|
@ -268,10 +268,13 @@ NS_IMETHODIMP nsDeviceContextSpecX::GetSurfaceForPrinter(gfxASurface **surface)
|
|||
|
||||
nsRefPtr<gfxASurface> newSurface;
|
||||
|
||||
if (context)
|
||||
newSurface = new gfxQuartzSurface(context, PR_FALSE, gfxSize(width, height));
|
||||
else
|
||||
if (context) {
|
||||
CGContextTranslateCTM(context, 0.0, height);
|
||||
CGContextScaleCTM(context, 1.0, -1.0);
|
||||
newSurface = new gfxQuartzSurface(context, gfxSize(width, height));
|
||||
} else {
|
||||
newSurface = new gfxQuartzSurface(gfxSize((PRInt32)width, (PRInt32)height), gfxASurface::ImageFormatARGB32);
|
||||
}
|
||||
|
||||
if (!newSurface)
|
||||
return NS_ERROR_FAILURE;
|
||||
|
|
|
@ -322,8 +322,8 @@ nsNativeThemeCocoa::DrawWidgetBackground(nsIRenderingContext* aContext, nsIFrame
|
|||
|
||||
double offsetX = 0.0, offsetY = 0.0;
|
||||
nsRefPtr<gfxASurface> thebesSurface = thebesCtx->CurrentSurface(&offsetX, &offsetY);
|
||||
if (thebesSurface->GetType() != gfxASurface::SurfaceTypeQuartz2) {
|
||||
fprintf(stderr, "Expected surface of type Quartz2, got %d\n",
|
||||
if (thebesSurface->GetType() != gfxASurface::SurfaceTypeQuartz) {
|
||||
fprintf(stderr, "Expected surface of type Quartz, got %d\n",
|
||||
thebesSurface->GetType());
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
|
|
Загрузка…
Ссылка в новой задаче