зеркало из https://github.com/mozilla/gecko-dev.git
b=364742, Update cairo to git 473ae3aa95, r=stuart
This commit is contained in:
Родитель
4243a33bb0
Коммит
83f4546038
|
@ -1,9 +1,4 @@
|
|||
Snapshots of cairo and glitz for mozilla usage. A git branch
|
||||
of this version of cairo is available at
|
||||
|
||||
vladimir@git.cairographics.org:~vladimir/cairo
|
||||
|
||||
in the 'mozilla-tree-cairo' branch.
|
||||
Snapshots of cairo and glitz for mozilla usage.
|
||||
|
||||
We only include the relevant parts of each release (generally, src/*.[ch]),
|
||||
as we have Makefile.in's that integrate into the Mozilla build system. For
|
||||
|
@ -12,7 +7,7 @@ http://www.cairographics.org/.
|
|||
|
||||
VERSIONS:
|
||||
|
||||
cairo 1.3.1 (cvs - 2006-07-13)
|
||||
cairo (git 473ae3aa9510b750f54cbf889180e3c4784da1b7)
|
||||
glitz 0.5.2 (cvs - 2006-01-10)
|
||||
|
||||
***** NOTE FOR VISUAL C++ 6.0 *****
|
||||
|
|
|
@ -63,6 +63,7 @@ CSRCS = \
|
|||
cairo-analysis-surface.c \
|
||||
cairo-arc.c \
|
||||
cairo-array.c \
|
||||
cairo-bentley-ottmann.c \
|
||||
cairo-cache.c \
|
||||
cairo-clip.c \
|
||||
cairo-color.c \
|
||||
|
@ -70,6 +71,7 @@ CSRCS = \
|
|||
cairo-fixed.c \
|
||||
cairo-font.c \
|
||||
cairo-font-options.c \
|
||||
cairo-freelist.c \
|
||||
cairo-gstate.c \
|
||||
cairo-hash.c \
|
||||
cairo-hull.c \
|
||||
|
@ -82,8 +84,8 @@ CSRCS = \
|
|||
cairo-paginated-surface.c \
|
||||
cairo-path.c \
|
||||
cairo-path-bounds.c \
|
||||
cairo-path-data.c \
|
||||
cairo-path-fill.c \
|
||||
cairo-path-fixed.c \
|
||||
cairo-path-stroke.c \
|
||||
cairo-pattern.c \
|
||||
cairo-pen.c \
|
||||
|
@ -92,6 +94,7 @@ CSRCS = \
|
|||
cairo-region.c \
|
||||
cairo-scaled-font.c \
|
||||
cairo-scaled-font-subsets.c \
|
||||
cairo-skiplist.c \
|
||||
cairo-slope.c \
|
||||
cairo-spline.c \
|
||||
cairo-stroke-style.c \
|
||||
|
|
|
@ -154,7 +154,7 @@ static cairo_int_status_t
|
|||
_cairo_analysis_surface_show_glyphs (void *abstract_surface,
|
||||
cairo_operator_t op,
|
||||
cairo_pattern_t *source,
|
||||
const cairo_glyph_t *glyphs,
|
||||
cairo_glyph_t *glyphs,
|
||||
int num_glyphs,
|
||||
cairo_scaled_font_t *scaled_font)
|
||||
{
|
||||
|
|
|
@ -363,28 +363,30 @@ _cairo_atsui_font_init_glyph_metrics (cairo_atsui_font_t *font,
|
|||
cairo_text_extents_t extents;
|
||||
OSStatus err;
|
||||
GlyphID theGlyph = _cairo_scaled_glyph_index (scaled_glyph);
|
||||
ATSGlyphIdealMetrics metricsH, metricsV;
|
||||
ATSUStyle style;
|
||||
ATSGlyphScreenMetrics metricsH, metricsV;
|
||||
ATSUStyle style,style1;
|
||||
ATSUVerticalCharacterType verticalType = kATSUStronglyVertical;
|
||||
const ATSUAttributeTag theTag[] = { kATSUVerticalCharacterTag };
|
||||
const ByteCount theSizes[] = { sizeof(verticalType) };
|
||||
ATSUAttributeValuePtr theValues[] = { &verticalType };
|
||||
double xscale;
|
||||
double yscale;
|
||||
|
||||
ATSUCreateAndCopyStyle(font->unscaled_style, &style);
|
||||
_cairo_matrix_compute_scale_factors(&font->base.scale, &xscale, &yscale, 1);
|
||||
|
||||
err = ATSUGlyphGetIdealMetrics(style,
|
||||
1, &theGlyph, 0, &metricsH);
|
||||
ATSUCreateAndCopyStyle(font->style, &style);
|
||||
|
||||
err = ATSUGlyphGetScreenMetrics(style,
|
||||
1, &theGlyph, 0, false, false, &metricsH);
|
||||
err = ATSUSetAttributes(style, 1, theTag, theSizes, theValues);
|
||||
err = ATSUGlyphGetIdealMetrics(style,
|
||||
1, &theGlyph, 0, &metricsV);
|
||||
err = ATSUGlyphGetScreenMetrics(style,
|
||||
1, &theGlyph, 0, false, false, &metricsV);
|
||||
|
||||
extents.x_bearing = metricsH.sideBearing.x;
|
||||
extents.y_bearing = metricsV.advance.y;
|
||||
extents.width =
|
||||
metricsH.advance.x - metricsH.sideBearing.x - metricsH.otherSideBearing.x;
|
||||
extents.height =
|
||||
-metricsV.advance.y - metricsV.sideBearing.y - metricsV.otherSideBearing.y;
|
||||
extents.x_advance = metricsH.advance.x;
|
||||
extents.width = metricsH.width/xscale;
|
||||
extents.height = metricsH.height/yscale;
|
||||
extents.x_bearing = metricsH.sideBearing.x/xscale;
|
||||
extents.y_bearing = metricsV.sideBearing.y/yscale - extents.height;
|
||||
extents.x_advance = metricsH.deviceAdvance.x/xscale;
|
||||
extents.y_advance = 0;
|
||||
|
||||
_cairo_scaled_glyph_set_metrics (scaled_glyph,
|
||||
|
@ -578,7 +580,7 @@ _cairo_atsui_font_old_show_glyphs (void *abstract_font,
|
|||
int dest_y,
|
||||
unsigned int width,
|
||||
unsigned int height,
|
||||
const cairo_glyph_t *glyphs,
|
||||
cairo_glyph_t *glyphs,
|
||||
int num_glyphs)
|
||||
{
|
||||
cairo_atsui_font_t *font = abstract_font;
|
||||
|
@ -656,6 +658,10 @@ _cairo_atsui_font_old_show_glyphs (void *abstract_font,
|
|||
|
||||
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);
|
||||
|
||||
|
@ -718,9 +724,11 @@ _cairo_atsui_font_old_show_glyphs (void *abstract_font,
|
|||
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,
|
||||
glyphs[i].x,
|
||||
glyphs[i].y,
|
||||
_cairo_lround (glyphs[i].x),
|
||||
_cairo_lround (glyphs[i].y),
|
||||
&theGlyph, 1);
|
||||
}
|
||||
|
||||
|
|
Разница между файлами не показана из-за своего большого размера
Загрузить разницу
|
@ -101,17 +101,17 @@ _cairo_beos_surface_create_internal (BView* view,
|
|||
bool owns_bitmap_view = false);
|
||||
|
||||
static BRect
|
||||
_cairo_rect_to_brect (const cairo_rectangle_fixed_t* rect)
|
||||
_cairo_rect_to_brect (const cairo_rectangle_int16_t* rect)
|
||||
{
|
||||
// A BRect is one pixel wider than you'd think
|
||||
return BRect(rect->x, rect->y, rect->x + rect->width - 1,
|
||||
rect->y + rect->height - 1);
|
||||
}
|
||||
|
||||
static cairo_rectangle_fixed_t
|
||||
static cairo_rectangle_int16_t
|
||||
_brect_to_cairo_rect (const BRect& rect)
|
||||
{
|
||||
cairo_rectangle_fixed_t retval;
|
||||
cairo_rectangle_int16_t retval;
|
||||
retval.x = int(rect.left + 0.5);
|
||||
retval.y = int(rect.top + 0.5);
|
||||
retval.width = rect.IntegerWidth() + 1;
|
||||
|
@ -550,9 +550,9 @@ _cairo_beos_surface_release_source_image (void *abstract_surfac
|
|||
|
||||
static cairo_status_t
|
||||
_cairo_beos_surface_acquire_dest_image (void *abstract_surface,
|
||||
cairo_rectangle_fixed_t *interest_rect,
|
||||
cairo_rectangle_int16_t *interest_rect,
|
||||
cairo_image_surface_t **image_out,
|
||||
cairo_rectangle_fixed_t *image_rect,
|
||||
cairo_rectangle_int16_t *image_rect,
|
||||
void **image_extra)
|
||||
{
|
||||
cairo_beos_surface_t *surface = reinterpret_cast<cairo_beos_surface_t*>(
|
||||
|
@ -615,9 +615,9 @@ _cairo_beos_surface_acquire_dest_image (void *abstract_surface,
|
|||
|
||||
static void
|
||||
_cairo_beos_surface_release_dest_image (void *abstract_surface,
|
||||
cairo_rectangle_fixed_t *intersect_rect,
|
||||
cairo_rectangle_int16_t *intersect_rect,
|
||||
cairo_image_surface_t *image,
|
||||
cairo_rectangle_fixed_t *image_rect,
|
||||
cairo_rectangle_int16_t *image_rect,
|
||||
void *image_extra)
|
||||
{
|
||||
fprintf(stderr, "Fallback drawing\n");
|
||||
|
@ -768,7 +768,7 @@ _cairo_beos_surface_composite (cairo_operator_t op,
|
|||
|
||||
static void
|
||||
_cairo_beos_surface_fill_rectangle (cairo_beos_surface_t *surface,
|
||||
cairo_rectangle_fixed_t *rect)
|
||||
cairo_rectangle_int16_t *rect)
|
||||
{
|
||||
BRect brect(_cairo_rect_to_brect(rect));
|
||||
surface->view->FillRect(brect);
|
||||
|
@ -778,7 +778,7 @@ static cairo_int_status_t
|
|||
_cairo_beos_surface_fill_rectangles (void *abstract_surface,
|
||||
cairo_operator_t op,
|
||||
const cairo_color_t *color,
|
||||
cairo_rectangle_fixed_t *rects,
|
||||
cairo_rectangle_int16_t *rects,
|
||||
int num_rects)
|
||||
{
|
||||
fprintf(stderr, "Drawing %i rectangles\n", num_rects);
|
||||
|
@ -863,7 +863,7 @@ _cairo_beos_surface_set_clip_region (void *abstract_surface,
|
|||
|
||||
static cairo_int_status_t
|
||||
_cairo_beos_surface_get_extents (void *abstract_surface,
|
||||
cairo_rectangle_fixed_t *rectangle)
|
||||
cairo_rectangle_int16_t *rectangle)
|
||||
{
|
||||
cairo_beos_surface_t *surface = reinterpret_cast<cairo_beos_surface_t*>(
|
||||
abstract_surface);
|
||||
|
|
|
@ -563,7 +563,12 @@ _cairo_clip_init_deep_copy (cairo_clip_t *clip,
|
|||
}
|
||||
|
||||
if (other->surface) {
|
||||
_cairo_surface_clone_similar (target, other->surface, &clip->surface);
|
||||
_cairo_surface_clone_similar (target, other->surface,
|
||||
other->surface_rect.x,
|
||||
other->surface_rect.y,
|
||||
other->surface_rect.width,
|
||||
other->surface_rect.height,
|
||||
&clip->surface);
|
||||
clip->surface_rect = other->surface_rect;
|
||||
}
|
||||
|
||||
|
@ -649,6 +654,16 @@ _cairo_clip_copy_rectangles (cairo_clip_t *clip, cairo_gstate_t *gstate)
|
|||
return list;
|
||||
}
|
||||
|
||||
/**
|
||||
* cairo_rectangle_list_destroy:
|
||||
* @rectangle_list: a rectangle list, as obtained from cairo_copy_clip_rectangles()
|
||||
*
|
||||
* Unconditionally frees @rectangle_list and all associated
|
||||
* references. After this call, the @rectangle_list pointer must not
|
||||
* be dereferenced.
|
||||
*
|
||||
* Since: 1.4
|
||||
**/
|
||||
void
|
||||
cairo_rectangle_list_destroy (cairo_rectangle_list_t *rectangle_list)
|
||||
{
|
||||
|
|
|
@ -89,19 +89,27 @@ _cairo_color_init_rgb (cairo_color_t *color,
|
|||
_cairo_color_init_rgba (color, red, green, blue, 1.0);
|
||||
}
|
||||
|
||||
/* We multiply colors by (0x10000 - epsilon), such that we get a uniform
|
||||
* range even for 0xffff. In other words, (1.0 - epsilon) would convert
|
||||
* to 0xffff, not 0xfffe.
|
||||
/* Convert a double in [0.0, 1.0] to an integer in [0, 65535]
|
||||
* The conversion is designed to divide the input range into 65536
|
||||
* equally-sized regions. This is achieved by multiplying by 65536 and
|
||||
* then special-casing the result of an input value of 1.0 so that it
|
||||
* maps to 65535 instead of 65536.
|
||||
*/
|
||||
#define CAIRO_COLOR_ONE_MINUS_EPSILON (65536.0 - 1e-5)
|
||||
static inline uint16_t _color_to_short (double d)
|
||||
{
|
||||
uint32_t i;
|
||||
i = (uint32_t) (d * 65536);
|
||||
i -= (i >> 16);
|
||||
return i;
|
||||
}
|
||||
|
||||
static void
|
||||
_cairo_color_compute_shorts (cairo_color_t *color)
|
||||
{
|
||||
color->red_short = color->red * color->alpha * CAIRO_COLOR_ONE_MINUS_EPSILON;
|
||||
color->green_short = color->green * color->alpha * CAIRO_COLOR_ONE_MINUS_EPSILON;
|
||||
color->blue_short = color->blue * color->alpha * CAIRO_COLOR_ONE_MINUS_EPSILON;
|
||||
color->alpha_short = color->alpha * CAIRO_COLOR_ONE_MINUS_EPSILON;
|
||||
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);
|
||||
}
|
||||
|
||||
void
|
||||
|
|
|
@ -548,6 +548,10 @@ _cairo_directfb_surface_release_dest_image (void *abstract_surf
|
|||
static cairo_status_t
|
||||
_cairo_directfb_surface_clone_similar (void *abstract_surface,
|
||||
cairo_surface_t *src,
|
||||
int src_x,
|
||||
int src_y,
|
||||
int width,
|
||||
int height,
|
||||
cairo_surface_t **clone_out)
|
||||
{
|
||||
cairo_directfb_surface_t *surface = abstract_surface;
|
||||
|
@ -583,19 +587,23 @@ _cairo_directfb_surface_clone_similar (void *abstract_surface,
|
|||
cairo_surface_destroy ((cairo_surface_t *)clone);
|
||||
return CAIRO_STATUS_NO_MEMORY;
|
||||
}
|
||||
|
||||
dst += pitch * src_y;
|
||||
src += image_src->stride * src_y;
|
||||
|
||||
if (image_src->format == CAIRO_FORMAT_A1) {
|
||||
/* A1 -> A8 */
|
||||
for (i = 0; i < image_src->height; i++) {
|
||||
for (j = 0; j < image_src->width; j++)
|
||||
for (i = 0; i < height; i++) {
|
||||
for (j = src_x; j < src_x + width; j++)
|
||||
dst[j] = (src[j>>3] & (1 << (j&7))) ? 0xff : 0x00;
|
||||
dst += pitch;
|
||||
src += image_src->stride;
|
||||
}
|
||||
}
|
||||
else {
|
||||
for (i = 0; i < image_src->height; i++) {
|
||||
direct_memcpy( dst, src, image_src->stride );
|
||||
else {
|
||||
/* A8 -> A8 */
|
||||
for (i = 0; i < height; i++) {
|
||||
direct_memcpy( dst+src_x, src+src_x, sizeof(*dst)*width );
|
||||
dst += pitch;
|
||||
src += image_src->stride;
|
||||
}
|
||||
|
@ -881,10 +889,10 @@ _cairo_directfb_surface_composite (cairo_operator_t op,
|
|||
TRANSFORM_POINT (m, sr.x, sr.y, x1, y1);
|
||||
TRANSFORM_POINT (m, sr.x+sr.w, sr.y+sr.h, x2, y2);
|
||||
|
||||
dr.x = floor (x1+.5);
|
||||
dr.y = floor (y1+.5);
|
||||
dr.w = floor (x2-x1+.5);
|
||||
dr.h = floor (y2-y1+.5);
|
||||
dr.x = _cairo_lround (x1);
|
||||
dr.y = _cairo_lround (y1);
|
||||
dr.w = _cairo_lround (x2-x1);
|
||||
dr.h = _cairo_lround (y2-y1);
|
||||
|
||||
D_DEBUG_AT (Cairo_DirectFB, "Running StretchBlit().\n");
|
||||
|
||||
|
@ -1275,8 +1283,8 @@ _directfb_acquire_font_cache (cairo_directfb_surface_t *surface,
|
|||
return CAIRO_INT_STATUS_UNSUPPORTED;
|
||||
}
|
||||
|
||||
points[n].x = floor (glyphs[i].x + img->base.device_transform.x0 + .5);
|
||||
points[n].y = floor (glyphs[i].y + img->base.device_transform.y0 + .5);
|
||||
points[n].x = _cairo_lround (glyphs[i].x + img->base.device_transform.x0);
|
||||
points[n].y = _cairo_lround (glyphs[i].y + img->base.device_transform.y0);
|
||||
|
||||
if (points[n].x >= surface->width ||
|
||||
points[n].y >= surface->height ||
|
||||
|
@ -1442,7 +1450,7 @@ static cairo_int_status_t
|
|||
_cairo_directfb_surface_show_glyphs ( void *abstract_dst,
|
||||
cairo_operator_t op,
|
||||
cairo_pattern_t *pattern,
|
||||
const cairo_glyph_t *glyphs,
|
||||
cairo_glyph_t *glyphs,
|
||||
int num_glyphs,
|
||||
cairo_scaled_font_t *scaled_font)
|
||||
{
|
||||
|
|
|
@ -53,9 +53,9 @@
|
|||
|
||||
#define CAIRO_VERSION_MAJOR 1
|
||||
#define CAIRO_VERSION_MINOR 3
|
||||
#define CAIRO_VERSION_MICRO 1
|
||||
#define CAIRO_VERSION_MICRO 8
|
||||
|
||||
#define CAIRO_VERSION_STRING "1.3.1"
|
||||
#define CAIRO_VERSION_STRING "1.3.8"
|
||||
|
||||
@PS_SURFACE_FEATURE@
|
||||
|
||||
|
|
|
@ -42,10 +42,56 @@ _cairo_fixed_from_int (int i)
|
|||
return i << 16;
|
||||
}
|
||||
|
||||
/* This is the "magic number" approach to converting a double into fixed
|
||||
* point as described here:
|
||||
*
|
||||
* http://www.stereopsis.com/sree/fpu2006.html (an overview)
|
||||
* http://www.d6.com/users/checker/pdfs/gdmfp.pdf (in detail)
|
||||
*
|
||||
* The basic idea is to add a large enough number to the double that the
|
||||
* literal floating point is moved up to the extent that it forces the
|
||||
* double's value to be shifted down to the bottom of the mantissa (to make
|
||||
* room for the large number being added in). Since the mantissa is, at a
|
||||
* given moment in time, a fixed point integer itself, one can convert a
|
||||
* float to various fixed point representations by moving around the point
|
||||
* of a floating point number through arithmetic operations. This behavior
|
||||
* is reliable on most modern platforms as it is mandated by the IEEE-754
|
||||
* standard for floating point arithmetic.
|
||||
*
|
||||
* For our purposes, a "magic number" must be carefully selected that is
|
||||
* both large enough to produce the desired point-shifting effect, and also
|
||||
* has no lower bits in its representation that would interfere with our
|
||||
* value at the bottom of the mantissa. The magic number is calculated as
|
||||
* follows:
|
||||
*
|
||||
* (2 ^ (MANTISSA_SIZE - FRACTIONAL_SIZE)) * 1.5
|
||||
*
|
||||
* where in our case:
|
||||
* - MANTISSA_SIZE for 64-bit doubles is 52
|
||||
* - FRACTIONAL_SIZE for 16.16 fixed point is 16
|
||||
*
|
||||
* Although this approach provides a very large speedup of this function
|
||||
* on a wide-array of systems, it does come with two caveats:
|
||||
*
|
||||
* 1) It uses banker's rounding as opposed to arithmetic rounding.
|
||||
* 2) It doesn't function properly if the FPU is in single-precision
|
||||
* mode.
|
||||
*/
|
||||
#define CAIRO_MAGIC_NUMBER_FIXED_16_16 (103079215104.0)
|
||||
cairo_fixed_t
|
||||
_cairo_fixed_from_double (double d)
|
||||
{
|
||||
return (cairo_fixed_t) floor (d * 65536 + 0.5);
|
||||
union {
|
||||
double d;
|
||||
int32_t i[2];
|
||||
} u;
|
||||
|
||||
u.d = d + CAIRO_MAGIC_NUMBER_FIXED_16_16;
|
||||
#ifdef FLOAT_WORDS_BIGENDIAN
|
||||
return u.i[1];
|
||||
#else
|
||||
return u.i[0];
|
||||
#endif
|
||||
}
|
||||
|
||||
cairo_fixed_t
|
||||
|
|
|
@ -0,0 +1,73 @@
|
|||
/*
|
||||
* Copyright © 2006 Joonas Pihlaja
|
||||
*
|
||||
* 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 the copyright holders not be used in advertising or
|
||||
* publicity pertaining to distribution of the software without specific,
|
||||
* written prior permission. The copyright holders make no representations
|
||||
* about the suitability of this software for any purpose. It is provided "as
|
||||
* is" without express or implied warranty.
|
||||
*
|
||||
* THE COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
|
||||
* INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
|
||||
* EVENT SHALL THE COPYRIGHT HOLDERS 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.
|
||||
*/
|
||||
#ifndef CAIRO_FREELIST_H
|
||||
#define CAIRO_FREELIST_H
|
||||
|
||||
#include "cairoint.h"
|
||||
#include <stddef.h>
|
||||
|
||||
/* Opaque implementation types. */
|
||||
struct _cairo_freelist;
|
||||
struct _cairo_freelist_node;
|
||||
typedef struct _cairo_freelist cairo_freelist_t;
|
||||
typedef struct _cairo_freelist_node cairo_freelist_node_t;
|
||||
|
||||
struct _cairo_freelist_node {
|
||||
cairo_freelist_node_t *next;
|
||||
};
|
||||
|
||||
struct _cairo_freelist {
|
||||
cairo_freelist_node_t *first_free_node;
|
||||
unsigned nodesize;
|
||||
};
|
||||
|
||||
|
||||
/* Initialise a freelist that will be responsible for allocating
|
||||
* nodes of size nodesize. */
|
||||
cairo_private void
|
||||
_cairo_freelist_init (cairo_freelist_t *freelist, unsigned nodesize);
|
||||
|
||||
/* Deallocate any nodes in the freelist. */
|
||||
cairo_private void
|
||||
_cairo_freelist_fini (cairo_freelist_t *freelist);
|
||||
|
||||
/* Allocate a new node from the freelist. If the freelist contains no
|
||||
* nodes, a new one will be allocated using malloc(). The caller is
|
||||
* responsible for calling _cairo_freelist_free() or free() on the
|
||||
* returned node. Returns NULL on memory allocation error. */
|
||||
cairo_private void *
|
||||
_cairo_freelist_alloc (cairo_freelist_t *freelist);
|
||||
|
||||
/* Allocate a new node from the freelist. If the freelist contains no
|
||||
* nodes, a new one will be allocated using calloc(). The caller is
|
||||
* responsible for calling _cairo_freelist_free() or free() on the
|
||||
* returned node. Returns NULL on memory allocation error. */
|
||||
cairo_private void *
|
||||
_cairo_freelist_calloc (cairo_freelist_t *freelist);
|
||||
|
||||
/* Return a node to the freelist. This does not deallocate the memory,
|
||||
* but makes it available for later reuse by
|
||||
* _cairo_freelist_alloc(). */
|
||||
cairo_private void
|
||||
_cairo_freelist_free (cairo_freelist_t *freelist, void *node);
|
||||
|
||||
#endif /* CAIRO_FREELIST_H */
|
|
@ -0,0 +1,72 @@
|
|||
/*
|
||||
* Copyright © 2006 Joonas Pihlaja
|
||||
*
|
||||
* 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 the copyright holders not be used in advertising or
|
||||
* publicity pertaining to distribution of the software without specific,
|
||||
* written prior permission. The copyright holders make no representations
|
||||
* about the suitability of this software for any purpose. It is provided "as
|
||||
* is" without express or implied warranty.
|
||||
*
|
||||
* THE COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
|
||||
* INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
|
||||
* EVENT SHALL THE COPYRIGHT HOLDERS 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.
|
||||
*/
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include "cairo-freelist-private.h"
|
||||
|
||||
void
|
||||
_cairo_freelist_init (cairo_freelist_t *freelist, unsigned nodesize)
|
||||
{
|
||||
memset (freelist, 0, sizeof(cairo_freelist_t));
|
||||
freelist->nodesize = nodesize;
|
||||
}
|
||||
|
||||
void
|
||||
_cairo_freelist_fini (cairo_freelist_t *freelist)
|
||||
{
|
||||
cairo_freelist_node_t *node = freelist->first_free_node;
|
||||
while (node) {
|
||||
cairo_freelist_node_t *next = node->next;
|
||||
free (node);
|
||||
node = next;
|
||||
}
|
||||
}
|
||||
|
||||
void *
|
||||
_cairo_freelist_alloc (cairo_freelist_t *freelist)
|
||||
{
|
||||
if (freelist->first_free_node) {
|
||||
cairo_freelist_node_t *node = freelist->first_free_node;
|
||||
freelist->first_free_node = node->next;
|
||||
return (void*)node;
|
||||
}
|
||||
return malloc (freelist->nodesize);
|
||||
}
|
||||
|
||||
void *
|
||||
_cairo_freelist_calloc (cairo_freelist_t *freelist)
|
||||
{
|
||||
void *node = _cairo_freelist_alloc (freelist);
|
||||
if (node)
|
||||
memset (node, 0, freelist->nodesize);
|
||||
return node;
|
||||
}
|
||||
|
||||
void
|
||||
_cairo_freelist_free (cairo_freelist_t *freelist, void *voidnode)
|
||||
{
|
||||
cairo_freelist_node_t *node = voidnode;
|
||||
if (node) {
|
||||
node->next = freelist->first_free_node;
|
||||
freelist->first_free_node = node;
|
||||
}
|
||||
}
|
|
@ -1191,8 +1191,8 @@ _transform_glyph_bitmap (cairo_matrix_t * shape,
|
|||
cairo_surface_destroy (&old_image->base);
|
||||
|
||||
cairo_surface_set_device_offset (&(*surface)->base,
|
||||
- floor (origin_x + 0.5),
|
||||
- floor (origin_y + 0.5));
|
||||
- _cairo_lround (origin_x),
|
||||
- _cairo_lround (origin_y));
|
||||
return status;
|
||||
}
|
||||
|
||||
|
@ -1216,8 +1216,8 @@ const cairo_scaled_font_backend_t cairo_ft_scaled_font_backend;
|
|||
/* The load flags passed to FT_Load_Glyph control aspects like hinting and
|
||||
* antialiasing. Here we compute them from the fields of a FcPattern.
|
||||
*/
|
||||
static cairo_ft_options_t
|
||||
_get_pattern_ft_options (FcPattern *pattern)
|
||||
static void
|
||||
_get_pattern_ft_options (FcPattern *pattern, cairo_ft_options_t *ret)
|
||||
{
|
||||
FcBool antialias, vertical_layout, hinting, autohint, bitmap, embolden;
|
||||
cairo_ft_options_t ft_options;
|
||||
|
@ -1341,7 +1341,7 @@ _get_pattern_ft_options (FcPattern *pattern)
|
|||
if (embolden)
|
||||
ft_options.extra_flags |= CAIRO_FT_OPTIONS_EMBOLDEN;
|
||||
|
||||
return ft_options;
|
||||
*ret = ft_options;
|
||||
}
|
||||
|
||||
static void
|
||||
|
@ -1581,7 +1581,7 @@ _cairo_ft_scaled_font_create_toy (cairo_toy_font_face_t *toy_face,
|
|||
if (!unscaled)
|
||||
goto FREE_RESOLVED;
|
||||
|
||||
ft_options = _get_pattern_ft_options (resolved);
|
||||
_get_pattern_ft_options (resolved, &ft_options);
|
||||
|
||||
new_font = _cairo_ft_scaled_font_create (unscaled,
|
||||
&toy_face->base,
|
||||
|
@ -1996,23 +1996,6 @@ _cairo_ft_ucs4_to_index (void *abstract_font,
|
|||
return index;
|
||||
}
|
||||
|
||||
static cairo_int_status_t
|
||||
_cairo_ft_show_glyphs (void *abstract_font,
|
||||
cairo_operator_t op,
|
||||
cairo_pattern_t *pattern,
|
||||
cairo_surface_t *surface,
|
||||
int source_x,
|
||||
int source_y,
|
||||
int dest_x,
|
||||
int dest_y,
|
||||
unsigned int width,
|
||||
unsigned int height,
|
||||
const cairo_glyph_t *glyphs,
|
||||
int num_glyphs)
|
||||
{
|
||||
return CAIRO_INT_STATUS_UNSUPPORTED;
|
||||
}
|
||||
|
||||
static cairo_int_status_t
|
||||
_cairo_ft_load_truetype_table (void *abstract_font,
|
||||
unsigned long tag,
|
||||
|
@ -2050,7 +2033,7 @@ const cairo_scaled_font_backend_t cairo_ft_scaled_font_backend = {
|
|||
_cairo_ft_scaled_glyph_init,
|
||||
NULL, /* text_to_glyphs */
|
||||
_cairo_ft_ucs4_to_index,
|
||||
_cairo_ft_show_glyphs,
|
||||
NULL, /* show_glyphs */
|
||||
_cairo_ft_load_truetype_table,
|
||||
};
|
||||
|
||||
|
@ -2154,7 +2137,7 @@ static const cairo_font_face_backend_t _cairo_ft_font_face_backend = {
|
|||
|
||||
static cairo_font_face_t *
|
||||
_cairo_ft_font_face_create (cairo_ft_unscaled_font_t *unscaled,
|
||||
cairo_ft_options_t ft_options)
|
||||
cairo_ft_options_t *ft_options)
|
||||
{
|
||||
cairo_ft_font_face_t *font_face;
|
||||
|
||||
|
@ -2163,9 +2146,9 @@ _cairo_ft_font_face_create (cairo_ft_unscaled_font_t *unscaled,
|
|||
font_face;
|
||||
font_face = font_face->next)
|
||||
{
|
||||
if (font_face->ft_options.load_flags == ft_options.load_flags &&
|
||||
font_face->ft_options.extra_flags == ft_options.extra_flags &&
|
||||
cairo_font_options_equal (&font_face->ft_options.base, &ft_options.base))
|
||||
if (font_face->ft_options.load_flags == ft_options->load_flags &&
|
||||
font_face->ft_options.extra_flags == ft_options->extra_flags &&
|
||||
cairo_font_options_equal (&font_face->ft_options.base, &ft_options->base))
|
||||
return cairo_font_face_reference (&font_face->base);
|
||||
}
|
||||
|
||||
|
@ -2177,7 +2160,7 @@ _cairo_ft_font_face_create (cairo_ft_unscaled_font_t *unscaled,
|
|||
font_face->unscaled = unscaled;
|
||||
_cairo_unscaled_font_reference (&unscaled->base);
|
||||
|
||||
font_face->ft_options = ft_options;
|
||||
font_face->ft_options = *ft_options;
|
||||
|
||||
font_face->next = unscaled->faces;
|
||||
unscaled->faces = font_face;
|
||||
|
@ -2316,6 +2299,7 @@ cairo_ft_font_face_create_for_pattern (FcPattern *pattern)
|
|||
{
|
||||
cairo_ft_unscaled_font_t *unscaled;
|
||||
cairo_font_face_t *font_face;
|
||||
cairo_ft_options_t ft_options;
|
||||
|
||||
unscaled = _cairo_ft_unscaled_font_create_for_pattern (pattern);
|
||||
if (unscaled == NULL) {
|
||||
|
@ -2323,8 +2307,8 @@ cairo_ft_font_face_create_for_pattern (FcPattern *pattern)
|
|||
return (cairo_font_face_t *)&_cairo_font_face_nil;
|
||||
}
|
||||
|
||||
font_face = _cairo_ft_font_face_create (unscaled,
|
||||
_get_pattern_ft_options (pattern));
|
||||
_get_pattern_ft_options (pattern, &ft_options);
|
||||
font_face = _cairo_ft_font_face_create (unscaled, &ft_options);
|
||||
_cairo_unscaled_font_destroy (&unscaled->base);
|
||||
|
||||
if (font_face)
|
||||
|
@ -2379,7 +2363,7 @@ cairo_ft_font_face_create_for_ft_face (FT_Face face,
|
|||
ft_options.extra_flags = 0;
|
||||
_cairo_font_options_init_default (&ft_options.base);
|
||||
|
||||
font_face = _cairo_ft_font_face_create (unscaled, ft_options);
|
||||
font_face = _cairo_ft_font_face_create (unscaled, &ft_options);
|
||||
_cairo_unscaled_font_destroy (&unscaled->base);
|
||||
|
||||
if (font_face) {
|
||||
|
|
|
@ -0,0 +1,41 @@
|
|||
/* Cairo - a vector graphics library with display and print output
|
||||
*
|
||||
* Copyright © 2005 Red Hat, Inc.
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it either under the terms of the GNU Lesser General Public
|
||||
* License version 2.1 as published by the Free Software Foundation
|
||||
* (the "LGPL") or, at your option, under the terms of the Mozilla
|
||||
* Public License Version 1.1 (the "MPL"). If you do not alter this
|
||||
* notice, a recipient may use your version of this file under either
|
||||
* the MPL or the LGPL.
|
||||
*
|
||||
* You should have received a copy of the LGPL along with this library
|
||||
* in the file COPYING-LGPL-2.1; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
* You should have received a copy of the MPL along with this library
|
||||
* in the file COPYING-MPL-1.1
|
||||
*
|
||||
* The contents of this file are subject to the Mozilla Public License
|
||||
* Version 1.1 (the "License"); you may not use this file except in
|
||||
* compliance with the License. You may obtain a copy of the License at
|
||||
* http://www.mozilla.org/MPL/
|
||||
*
|
||||
* This software is distributed on an "AS IS" basis, WITHOUT WARRANTY
|
||||
* OF ANY KIND, either express or implied. See the LGPL or the MPL for
|
||||
* the specific language governing rights and limitations.
|
||||
*
|
||||
* The Original Code is the cairo graphics library.
|
||||
*
|
||||
* The Initial Developer of the Original Code is Red Hat, Inc.
|
||||
*/
|
||||
|
||||
#ifndef CAIRO_GLITZ_PRIVATE_H
|
||||
#define CAIRO_GLITZ_PRIVATE_H
|
||||
|
||||
#include "cairoint.h"
|
||||
#include "cairo-glitz.h"
|
||||
|
||||
slim_hidden_proto (cairo_glitz_surface_create);
|
||||
|
||||
#endif /* CAIRO_GLITZ_PRIVATE_H */
|
|
@ -26,6 +26,7 @@
|
|||
|
||||
#include "cairoint.h"
|
||||
#include "cairo-glitz.h"
|
||||
#include "cairo-glitz-private.h"
|
||||
|
||||
typedef struct _cairo_glitz_surface {
|
||||
cairo_surface_t base;
|
||||
|
@ -207,8 +208,9 @@ _cairo_glitz_surface_get_image (cairo_glitz_surface_t *surface,
|
|||
}
|
||||
|
||||
/* clear out the glitz clip; the clip affects glitz_get_pixels */
|
||||
glitz_surface_set_clip_region (surface->surface,
|
||||
0, 0, NULL, 0);
|
||||
if (surface->clip)
|
||||
glitz_surface_set_clip_region (surface->surface,
|
||||
0, 0, NULL, 0);
|
||||
|
||||
glitz_get_pixels (surface->surface,
|
||||
x1, y1,
|
||||
|
@ -219,8 +221,14 @@ _cairo_glitz_surface_get_image (cairo_glitz_surface_t *surface,
|
|||
glitz_buffer_destroy (buffer);
|
||||
|
||||
/* restore the clip, if any */
|
||||
surface->base.current_clip_serial = 0;
|
||||
_cairo_surface_set_clip (&surface->base, surface->base.clip);
|
||||
if (surface->clip) {
|
||||
glitz_box_t *box;
|
||||
int n;
|
||||
|
||||
box = (glitz_box_t *) pixman_region_rects (surface->clip);
|
||||
n = pixman_region_num_rects (surface->clip);
|
||||
glitz_surface_set_clip_region (surface->surface, 0, 0, box, n);
|
||||
}
|
||||
|
||||
image = (cairo_image_surface_t *)
|
||||
_cairo_image_surface_create_with_masks (pixels,
|
||||
|
@ -243,8 +251,12 @@ _cairo_glitz_surface_get_image (cairo_glitz_surface_t *surface,
|
|||
static cairo_status_t
|
||||
_cairo_glitz_surface_set_image (void *abstract_surface,
|
||||
cairo_image_surface_t *image,
|
||||
int x_dst,
|
||||
int y_dst)
|
||||
int src_x,
|
||||
int src_y,
|
||||
int width,
|
||||
int height,
|
||||
int x_dst,
|
||||
int y_dst)
|
||||
{
|
||||
cairo_glitz_surface_t *surface = abstract_surface;
|
||||
glitz_buffer_t *buffer;
|
||||
|
@ -264,8 +276,8 @@ _cairo_glitz_surface_set_image (void *abstract_surface,
|
|||
pf.masks.red_mask = rm;
|
||||
pf.masks.green_mask = gm;
|
||||
pf.masks.blue_mask = bm;
|
||||
pf.xoffset = 0;
|
||||
pf.skip_lines = 0;
|
||||
pf.xoffset = src_x;
|
||||
pf.skip_lines = src_y;
|
||||
|
||||
/* check for negative stride */
|
||||
if (image->stride < 0)
|
||||
|
@ -287,7 +299,7 @@ _cairo_glitz_surface_set_image (void *abstract_surface,
|
|||
|
||||
glitz_set_pixels (surface->surface,
|
||||
x_dst, y_dst,
|
||||
image->width, image->height,
|
||||
width, height,
|
||||
&pf,
|
||||
buffer);
|
||||
|
||||
|
@ -347,7 +359,8 @@ _cairo_glitz_surface_release_dest_image (void *abstract_surfa
|
|||
{
|
||||
cairo_glitz_surface_t *surface = abstract_surface;
|
||||
|
||||
_cairo_glitz_surface_set_image (surface, image,
|
||||
_cairo_glitz_surface_set_image (surface, image, 0, 0,
|
||||
image->width, image->height,
|
||||
image_rect->x, image_rect->y);
|
||||
|
||||
cairo_surface_destroy (&image->base);
|
||||
|
@ -356,6 +369,10 @@ _cairo_glitz_surface_release_dest_image (void *abstract_surfa
|
|||
static cairo_status_t
|
||||
_cairo_glitz_surface_clone_similar (void *abstract_surface,
|
||||
cairo_surface_t *src,
|
||||
int src_x,
|
||||
int src_y,
|
||||
int width,
|
||||
int height,
|
||||
cairo_surface_t **clone_out)
|
||||
{
|
||||
cairo_glitz_surface_t *surface = abstract_surface;
|
||||
|
@ -374,6 +391,8 @@ _cairo_glitz_surface_clone_similar (void *abstract_surface,
|
|||
{
|
||||
cairo_image_surface_t *image_src = (cairo_image_surface_t *) src;
|
||||
cairo_content_t content;
|
||||
cairo_rectangle_int16_t image_extent;
|
||||
cairo_rectangle_int16_t extent;
|
||||
|
||||
content = _cairo_content_from_format (image_src->format);
|
||||
|
||||
|
@ -384,7 +403,21 @@ _cairo_glitz_surface_clone_similar (void *abstract_surface,
|
|||
if (clone->base.status)
|
||||
return CAIRO_STATUS_NO_MEMORY;
|
||||
|
||||
_cairo_glitz_surface_set_image (clone, image_src, 0, 0);
|
||||
image_extent.x = 0;
|
||||
image_extent.y = 0;
|
||||
image_extent.width = image_src->width;
|
||||
image_extent.height = image_src->height;
|
||||
extent.x = src_x;
|
||||
extent.y = src_y;
|
||||
extent.width = width;
|
||||
extent.height = height;
|
||||
|
||||
_cairo_rectangle_intersect(&extent, &image_extent);
|
||||
|
||||
_cairo_glitz_surface_set_image (clone, image_src,
|
||||
extent.x, extent.y,
|
||||
extent.width, extent.height,
|
||||
extent.x, extent.y);
|
||||
|
||||
*clone_out = &clone->base;
|
||||
|
||||
|
@ -1183,7 +1216,9 @@ _cairo_glitz_surface_composite_trapezoids (cairo_operator_t op,
|
|||
return CAIRO_STATUS_NO_MEMORY;
|
||||
}
|
||||
|
||||
_cairo_glitz_surface_set_image (mask, image, 0, 0);
|
||||
_cairo_glitz_surface_set_image (mask, image, 0, 0, width, height, 0, 0);
|
||||
|
||||
cairo_surface_destroy(&image->base);
|
||||
}
|
||||
|
||||
_cairo_glitz_surface_set_attributes (src, &attributes);
|
||||
|
@ -1665,10 +1700,14 @@ _cairo_glitz_surface_font_init (cairo_glitz_surface_t *surface,
|
|||
drawable = glitz_surface_get_drawable (surface->surface);
|
||||
|
||||
switch (format) {
|
||||
case CAIRO_FORMAT_A1:
|
||||
case CAIRO_FORMAT_A8:
|
||||
surface_format =
|
||||
glitz_find_standard_format (drawable, GLITZ_STANDARD_A8);
|
||||
break;
|
||||
case CAIRO_FORMAT_RGB24:
|
||||
ASSERT_NOT_REACHED;
|
||||
break;
|
||||
case CAIRO_FORMAT_ARGB32:
|
||||
surface_format =
|
||||
glitz_find_standard_format (drawable, GLITZ_STANDARD_ARGB32);
|
||||
|
@ -1870,7 +1909,7 @@ _cairo_glitz_surface_old_show_glyphs (cairo_scaled_font_t *scaled_font,
|
|||
int dst_y,
|
||||
unsigned int width,
|
||||
unsigned int height,
|
||||
const cairo_glyph_t *glyphs,
|
||||
cairo_glyph_t *glyphs,
|
||||
int num_glyphs)
|
||||
{
|
||||
cairo_glitz_surface_attributes_t attributes;
|
||||
|
@ -1941,6 +1980,8 @@ _cairo_glitz_surface_old_show_glyphs (cairo_scaled_font_t *scaled_font,
|
|||
if (!buffer)
|
||||
goto FAIL2;
|
||||
|
||||
_cairo_scaled_font_freeze_cache (scaled_font);
|
||||
|
||||
for (i = 0; i < num_glyphs; i++)
|
||||
{
|
||||
status = _cairo_scaled_glyph_lookup (scaled_font,
|
||||
|
@ -1953,6 +1994,17 @@ _cairo_glitz_surface_old_show_glyphs (cairo_scaled_font_t *scaled_font,
|
|||
goto UNLOCK;
|
||||
}
|
||||
|
||||
glyph_private = scaled_glyphs[i]->surface_private;
|
||||
if (!glyph_private || !glyph_private->area)
|
||||
{
|
||||
status = _cairo_glitz_surface_add_glyph (dst,
|
||||
scaled_font,
|
||||
scaled_glyphs[i]);
|
||||
if (status != CAIRO_STATUS_SUCCESS) {
|
||||
num_glyphs = i;
|
||||
goto UNLOCK;
|
||||
}
|
||||
}
|
||||
glyph_private = scaled_glyphs[i]->surface_private;
|
||||
if (glyph_private && glyph_private->area)
|
||||
{
|
||||
|
@ -1963,8 +2015,8 @@ _cairo_glitz_surface_old_show_glyphs (cairo_scaled_font_t *scaled_font,
|
|||
x_offset = scaled_glyphs[i]->surface->base.device_transform.x0;
|
||||
y_offset = scaled_glyphs[i]->surface->base.device_transform.y0;
|
||||
|
||||
x1 = floor (glyphs[i].x + 0.5) + x_offset;
|
||||
y1 = floor (glyphs[i].y + 0.5) + y_offset;
|
||||
x1 = _cairo_lround (glyphs[i].x) + x_offset;
|
||||
y1 = _cairo_lround (glyphs[i].y) + y_offset;
|
||||
x2 = x1 + glyph_private->area->width;
|
||||
y2 = y1 + glyph_private->area->height;
|
||||
|
||||
|
@ -1988,42 +2040,18 @@ _cairo_glitz_surface_old_show_glyphs (cairo_scaled_font_t *scaled_font,
|
|||
glyph_private = scaled_glyphs[i]->surface_private;
|
||||
if (!glyph_private || !glyph_private->area)
|
||||
{
|
||||
status = _cairo_glitz_surface_add_glyph (dst,
|
||||
scaled_font,
|
||||
scaled_glyphs[i]);
|
||||
if (status)
|
||||
goto UNLOCK;
|
||||
int glyph_width, glyph_height;
|
||||
|
||||
glyph_private = scaled_glyphs[i]->surface_private;
|
||||
}
|
||||
|
||||
x_offset = scaled_glyphs[i]->surface->base.device_transform.x0;
|
||||
y_offset = scaled_glyphs[i]->surface->base.device_transform.y0;
|
||||
|
||||
x1 = floor (glyphs[i].x + 0.5) + x_offset;
|
||||
y1 = floor (glyphs[i].y + 0.5) + y_offset;
|
||||
|
||||
if (glyph_private->area)
|
||||
{
|
||||
if (glyph_private->area->width)
|
||||
{
|
||||
x2 = x1 + glyph_private->area->width;
|
||||
y2 = y1 + glyph_private->area->height;
|
||||
|
||||
WRITE_BOX (vertices, x1, y1, x2, y2,
|
||||
&glyph_private->p1, &glyph_private->p2);
|
||||
|
||||
glyph_private->locked = TRUE;
|
||||
|
||||
cached_glyphs++;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
image = &scaled_glyphs[i]->surface->base;
|
||||
glyph_width = scaled_glyphs[i]->surface->width;
|
||||
glyph_height = scaled_glyphs[i]->surface->height;
|
||||
status =
|
||||
_cairo_glitz_surface_clone_similar (abstract_surface,
|
||||
image,
|
||||
0,
|
||||
0,
|
||||
glyph_width,
|
||||
glyph_height,
|
||||
(cairo_surface_t **)
|
||||
&clone);
|
||||
if (status)
|
||||
|
@ -2037,8 +2065,8 @@ _cairo_glitz_surface_old_show_glyphs (cairo_scaled_font_t *scaled_font,
|
|||
src_y + attributes.base.y_offset + y1,
|
||||
0, 0,
|
||||
x1, y1,
|
||||
scaled_glyphs[i]->surface->width,
|
||||
scaled_glyphs[i]->surface->height);
|
||||
glyph_width,
|
||||
glyph_height);
|
||||
|
||||
cairo_surface_destroy (&clone->base);
|
||||
|
||||
|
@ -2081,6 +2109,8 @@ _cairo_glitz_surface_old_show_glyphs (cairo_scaled_font_t *scaled_font,
|
|||
}
|
||||
|
||||
UNLOCK:
|
||||
_cairo_scaled_font_thaw_cache (scaled_font);
|
||||
|
||||
if (cached_glyphs)
|
||||
{
|
||||
for (i = 0; i < num_glyphs; i++)
|
||||
|
@ -2196,3 +2226,4 @@ cairo_glitz_surface_create (glitz_surface_t *surface)
|
|||
|
||||
return (cairo_surface_t *) crsurface;
|
||||
}
|
||||
slim_hidden_def (cairo_glitz_surface_create);
|
||||
|
|
|
@ -61,6 +61,12 @@ _cairo_gstate_ensure_scaled_font (cairo_gstate_t *gstate);
|
|||
static void
|
||||
_cairo_gstate_unset_scaled_font (cairo_gstate_t *gstate);
|
||||
|
||||
static void
|
||||
_cairo_gstate_transform_glyphs_to_backend (cairo_gstate_t *gstate,
|
||||
const cairo_glyph_t *glyphs,
|
||||
int num_glyphs,
|
||||
cairo_glyph_t *transformed_glyphs);
|
||||
|
||||
/**
|
||||
* _cairo_gstate_create:
|
||||
* @target: a #cairo_surface_t, not NULL
|
||||
|
@ -712,17 +718,12 @@ _cairo_gstate_backend_to_user_rectangle (cairo_gstate_t *gstate,
|
|||
double *x2, double *y2,
|
||||
cairo_bool_t *is_tight)
|
||||
{
|
||||
double width = *x2 - *x1;
|
||||
double height = *y2 - *y1;
|
||||
cairo_matrix_t matrix_inverse;
|
||||
|
||||
cairo_matrix_multiply (&matrix_inverse, &gstate->ctm_inverse,
|
||||
&gstate->target->device_transform_inverse);
|
||||
cairo_matrix_transform_bounding_box (
|
||||
&matrix_inverse, x1, y1, &width, &height, is_tight);
|
||||
|
||||
*x2 = *x1 + width;
|
||||
*y2 = *y1 + height;
|
||||
cairo_matrix_transform_bounding_box (&matrix_inverse,
|
||||
x1, y1, x2, y2, is_tight);
|
||||
}
|
||||
|
||||
/* XXX: NYI
|
||||
|
@ -1117,7 +1118,6 @@ _cairo_gstate_fill_extents (cairo_gstate_t *gstate,
|
|||
{
|
||||
cairo_status_t status;
|
||||
cairo_traps_t traps;
|
||||
cairo_box_t extents;
|
||||
|
||||
_cairo_traps_init (&traps);
|
||||
|
||||
|
@ -1447,7 +1447,7 @@ _cairo_gstate_set_font_face (cairo_gstate_t *gstate,
|
|||
|
||||
cairo_status_t
|
||||
_cairo_gstate_glyph_extents (cairo_gstate_t *gstate,
|
||||
cairo_glyph_t *glyphs,
|
||||
const cairo_glyph_t *glyphs,
|
||||
int num_glyphs,
|
||||
cairo_text_extents_t *extents)
|
||||
{
|
||||
|
@ -1464,6 +1464,7 @@ _cairo_gstate_glyph_extents (cairo_gstate_t *gstate,
|
|||
return CAIRO_STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
#define STACK_GLYPHS_LEN ((int) (CAIRO_STACK_BUFFER_SIZE / sizeof (cairo_glyph_t)))
|
||||
cairo_status_t
|
||||
_cairo_gstate_show_glyphs (cairo_gstate_t *gstate,
|
||||
const cairo_glyph_t *glyphs,
|
||||
|
@ -1472,7 +1473,8 @@ _cairo_gstate_show_glyphs (cairo_gstate_t *gstate,
|
|||
cairo_status_t status;
|
||||
cairo_pattern_union_t source_pattern;
|
||||
cairo_glyph_t *transformed_glyphs;
|
||||
int i;
|
||||
cairo_glyph_t stack_transformed_glyphs[STACK_GLYPHS_LEN];
|
||||
|
||||
|
||||
if (gstate->source->status)
|
||||
return gstate->source->status;
|
||||
|
@ -1485,20 +1487,17 @@ _cairo_gstate_show_glyphs (cairo_gstate_t *gstate,
|
|||
if (status)
|
||||
return status;
|
||||
|
||||
transformed_glyphs = malloc (num_glyphs * sizeof(cairo_glyph_t));
|
||||
if (transformed_glyphs == NULL)
|
||||
return CAIRO_STATUS_NO_MEMORY;
|
||||
|
||||
for (i = 0; i < num_glyphs; ++i)
|
||||
{
|
||||
transformed_glyphs[i].index = glyphs[i].index;
|
||||
transformed_glyphs[i].x = glyphs[i].x + gstate->font_matrix.x0;
|
||||
transformed_glyphs[i].y = glyphs[i].y + gstate->font_matrix.y0;
|
||||
_cairo_gstate_user_to_backend (gstate,
|
||||
&transformed_glyphs[i].x,
|
||||
&transformed_glyphs[i].y);
|
||||
if (num_glyphs <= STACK_GLYPHS_LEN) {
|
||||
transformed_glyphs = stack_transformed_glyphs;
|
||||
} else {
|
||||
transformed_glyphs = malloc (num_glyphs * sizeof(cairo_glyph_t));
|
||||
if (transformed_glyphs == NULL)
|
||||
return CAIRO_STATUS_NO_MEMORY;
|
||||
}
|
||||
|
||||
_cairo_gstate_transform_glyphs_to_backend (gstate, glyphs, num_glyphs,
|
||||
transformed_glyphs);
|
||||
|
||||
_cairo_gstate_copy_transformed_source (gstate, &source_pattern.base);
|
||||
|
||||
status = _cairo_surface_show_glyphs (gstate->target,
|
||||
|
@ -1509,46 +1508,47 @@ _cairo_gstate_show_glyphs (cairo_gstate_t *gstate,
|
|||
gstate->scaled_font);
|
||||
|
||||
_cairo_pattern_fini (&source_pattern.base);
|
||||
free (transformed_glyphs);
|
||||
|
||||
if (transformed_glyphs != stack_transformed_glyphs)
|
||||
free (transformed_glyphs);
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
cairo_status_t
|
||||
_cairo_gstate_glyph_path (cairo_gstate_t *gstate,
|
||||
cairo_glyph_t *glyphs,
|
||||
int num_glyphs,
|
||||
cairo_path_fixed_t *path)
|
||||
_cairo_gstate_glyph_path (cairo_gstate_t *gstate,
|
||||
const cairo_glyph_t *glyphs,
|
||||
int num_glyphs,
|
||||
cairo_path_fixed_t *path)
|
||||
{
|
||||
cairo_status_t status;
|
||||
int i;
|
||||
cairo_glyph_t *transformed_glyphs = NULL;
|
||||
cairo_glyph_t *transformed_glyphs;
|
||||
cairo_glyph_t stack_transformed_glyphs[STACK_GLYPHS_LEN];
|
||||
|
||||
status = _cairo_gstate_ensure_scaled_font (gstate);
|
||||
if (status)
|
||||
return status;
|
||||
|
||||
transformed_glyphs = malloc (num_glyphs * sizeof(cairo_glyph_t));
|
||||
if (num_glyphs < STACK_GLYPHS_LEN)
|
||||
transformed_glyphs = stack_transformed_glyphs;
|
||||
else
|
||||
transformed_glyphs = malloc (num_glyphs * sizeof(cairo_glyph_t));
|
||||
if (transformed_glyphs == NULL)
|
||||
return CAIRO_STATUS_NO_MEMORY;
|
||||
|
||||
for (i = 0; i < num_glyphs; ++i)
|
||||
{
|
||||
transformed_glyphs[i].index = glyphs[i].index;
|
||||
transformed_glyphs[i].x = glyphs[i].x + gstate->font_matrix.x0;
|
||||
transformed_glyphs[i].y = glyphs[i].y + gstate->font_matrix.y0;
|
||||
_cairo_gstate_user_to_backend (gstate,
|
||||
&(transformed_glyphs[i].x),
|
||||
&(transformed_glyphs[i].y));
|
||||
}
|
||||
_cairo_gstate_transform_glyphs_to_backend (gstate, glyphs, num_glyphs,
|
||||
transformed_glyphs);
|
||||
|
||||
status = _cairo_scaled_font_glyph_path (gstate->scaled_font,
|
||||
transformed_glyphs, num_glyphs,
|
||||
path);
|
||||
|
||||
free (transformed_glyphs);
|
||||
if (transformed_glyphs != stack_transformed_glyphs)
|
||||
free (transformed_glyphs);
|
||||
|
||||
return status;
|
||||
}
|
||||
#undef STACK_GLYPHS_LEN
|
||||
|
||||
cairo_status_t
|
||||
_cairo_gstate_set_antialias (cairo_gstate_t *gstate,
|
||||
|
@ -1564,3 +1564,66 @@ _cairo_gstate_get_antialias (cairo_gstate_t *gstate)
|
|||
{
|
||||
return gstate->antialias;
|
||||
}
|
||||
|
||||
/**
|
||||
* _cairo_gstate_transform_glyphs_to_backend:
|
||||
* @gstate: a #cairo_gstate_t
|
||||
* @glyphs: the array of #cairo_glyph_t objects to be transformed
|
||||
* @num_glyphs: the number of elements in @glyphs
|
||||
* @transformed_glyphs: a pre-allocated array of at least @num_glyphs
|
||||
* #cairo_glyph_t objects
|
||||
*
|
||||
* Transform an array of glyphs to backend space by first adding the offset
|
||||
* of the font matrix, then transforming from user space to backend space.
|
||||
* The result of the transformation is placed in @transformed_glyphs.
|
||||
**/
|
||||
static void
|
||||
_cairo_gstate_transform_glyphs_to_backend (cairo_gstate_t *gstate,
|
||||
const cairo_glyph_t *glyphs,
|
||||
int num_glyphs,
|
||||
cairo_glyph_t *transformed_glyphs)
|
||||
{
|
||||
int i;
|
||||
cairo_matrix_t *ctm = &gstate->ctm;
|
||||
cairo_matrix_t *device_transform = &gstate->target->device_transform;
|
||||
|
||||
if (_cairo_matrix_is_identity (ctm) &&
|
||||
_cairo_matrix_is_identity (device_transform) &&
|
||||
gstate->font_matrix.x0 == 0 && gstate->font_matrix.y0 == 0)
|
||||
{
|
||||
memcpy (transformed_glyphs, glyphs, num_glyphs * sizeof (cairo_glyph_t));
|
||||
}
|
||||
else if (_cairo_matrix_is_translation (ctm) &&
|
||||
_cairo_matrix_is_translation (device_transform))
|
||||
{
|
||||
double tx = gstate->font_matrix.x0 + ctm->x0 + device_transform->x0;
|
||||
double ty = gstate->font_matrix.y0 + ctm->y0 + device_transform->y0;
|
||||
|
||||
for (i = 0; i < num_glyphs; i++)
|
||||
{
|
||||
transformed_glyphs[i].index = glyphs[i].index;
|
||||
transformed_glyphs[i].x = glyphs[i].x + tx;
|
||||
transformed_glyphs[i].y = glyphs[i].y + ty;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
cairo_matrix_t aggregate_transform;
|
||||
|
||||
cairo_matrix_init_translate (&aggregate_transform,
|
||||
gstate->font_matrix.x0,
|
||||
gstate->font_matrix.y0);
|
||||
cairo_matrix_multiply (&aggregate_transform,
|
||||
&aggregate_transform, ctm);
|
||||
cairo_matrix_multiply (&aggregate_transform,
|
||||
&aggregate_transform, device_transform);
|
||||
|
||||
for (i = 0; i < num_glyphs; i++)
|
||||
{
|
||||
transformed_glyphs[i] = glyphs[i];
|
||||
cairo_matrix_transform_point (&aggregate_transform,
|
||||
&transformed_glyphs[i].x,
|
||||
&transformed_glyphs[i].y);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -36,6 +36,52 @@
|
|||
|
||||
#include "cairoint.h"
|
||||
|
||||
const cairo_image_surface_t _cairo_image_surface_nil_invalid_format = {
|
||||
{
|
||||
&cairo_image_surface_backend, /* backend */
|
||||
CAIRO_SURFACE_TYPE_IMAGE,
|
||||
CAIRO_CONTENT_COLOR,
|
||||
CAIRO_REF_COUNT_INVALID, /* ref_count */
|
||||
CAIRO_STATUS_INVALID_FORMAT, /* 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 */
|
||||
}, /* base */
|
||||
CAIRO_FORMAT_ARGB32, /* format */
|
||||
NULL, /* data */
|
||||
FALSE, /* owns_data */
|
||||
FALSE, /* has_clip */
|
||||
0, /* width */
|
||||
0, /* height */
|
||||
0, /* stride */
|
||||
0, /* depth */
|
||||
NULL /* pixman_image */
|
||||
};
|
||||
|
||||
|
||||
static int
|
||||
_cairo_format_bpp (cairo_format_t format)
|
||||
{
|
||||
|
@ -248,8 +294,10 @@ cairo_image_surface_create (cairo_format_t format,
|
|||
pixman_format_t *pixman_format;
|
||||
pixman_image_t *pixman_image;
|
||||
|
||||
if (! CAIRO_FORMAT_VALID (format))
|
||||
return (cairo_surface_t*) &_cairo_surface_nil;
|
||||
if (! CAIRO_FORMAT_VALID (format)) {
|
||||
_cairo_error (CAIRO_STATUS_INVALID_FORMAT);
|
||||
return (cairo_surface_t*) &_cairo_image_surface_nil_invalid_format;
|
||||
}
|
||||
|
||||
pixman_format = _create_pixman_format (format);
|
||||
if (pixman_format == NULL) {
|
||||
|
@ -617,6 +665,10 @@ _cairo_image_surface_release_dest_image (void *abstract_surfa
|
|||
static cairo_status_t
|
||||
_cairo_image_surface_clone_similar (void *abstract_surface,
|
||||
cairo_surface_t *src,
|
||||
int src_x,
|
||||
int src_y,
|
||||
int width,
|
||||
int height,
|
||||
cairo_surface_t **clone_out)
|
||||
{
|
||||
cairo_image_surface_t *surface = abstract_surface;
|
||||
|
|
|
@ -357,35 +357,30 @@ slim_hidden_def(cairo_matrix_transform_point);
|
|||
|
||||
void
|
||||
cairo_matrix_transform_bounding_box (const cairo_matrix_t *matrix,
|
||||
double *x, double *y,
|
||||
double *width, double *height,
|
||||
double *x1, double *y1,
|
||||
double *x2, double *y2,
|
||||
cairo_bool_t *is_tight)
|
||||
{
|
||||
int i;
|
||||
double quad_x[4], quad_y[4];
|
||||
double dx1, dy1;
|
||||
double dx2, dy2;
|
||||
double min_x, max_x;
|
||||
double min_y, max_y;
|
||||
|
||||
quad_x[0] = *x;
|
||||
quad_y[0] = *y;
|
||||
quad_x[0] = *x1;
|
||||
quad_y[0] = *y1;
|
||||
cairo_matrix_transform_point (matrix, &quad_x[0], &quad_y[0]);
|
||||
|
||||
dx1 = *width;
|
||||
dy1 = 0;
|
||||
cairo_matrix_transform_distance (matrix, &dx1, &dy1);
|
||||
quad_x[1] = quad_x[0] + dx1;
|
||||
quad_y[1] = quad_y[0] + dy1;
|
||||
quad_x[1] = *x2;
|
||||
quad_y[1] = *y1;
|
||||
cairo_matrix_transform_point (matrix, &quad_x[1], &quad_y[1]);
|
||||
|
||||
dx2 = 0;
|
||||
dy2 = *height;
|
||||
cairo_matrix_transform_distance (matrix, &dx2, &dy2);
|
||||
quad_x[2] = quad_x[0] + dx2;
|
||||
quad_y[2] = quad_y[0] + dy2;
|
||||
quad_x[2] = *x1;
|
||||
quad_y[2] = *y2;
|
||||
cairo_matrix_transform_point (matrix, &quad_x[2], &quad_y[2]);
|
||||
|
||||
quad_x[3] = quad_x[0] + dx1 + dx2;
|
||||
quad_y[3] = quad_y[0] + dy1 + dy2;
|
||||
quad_x[3] = *x2;
|
||||
quad_y[3] = *y2;
|
||||
cairo_matrix_transform_point (matrix, &quad_x[3], &quad_y[3]);
|
||||
|
||||
min_x = max_x = quad_x[0];
|
||||
min_y = max_y = quad_y[0];
|
||||
|
@ -402,10 +397,10 @@ cairo_matrix_transform_bounding_box (const cairo_matrix_t *matrix,
|
|||
max_y = quad_y[i];
|
||||
}
|
||||
|
||||
*x = min_x;
|
||||
*y = min_y;
|
||||
*width = max_x - min_x;
|
||||
*height = max_y - min_y;
|
||||
*x1 = min_x;
|
||||
*y1 = min_y;
|
||||
*x2 = max_x;
|
||||
*y2 = max_y;
|
||||
|
||||
if (is_tight) {
|
||||
/* it's tight if and only if the four corner points form an axis-aligned
|
||||
|
@ -555,31 +550,34 @@ _cairo_matrix_is_identity (const cairo_matrix_t *matrix)
|
|||
}
|
||||
|
||||
cairo_bool_t
|
||||
_cairo_matrix_is_integer_translation(const cairo_matrix_t *m,
|
||||
int *itx, int *ity)
|
||||
_cairo_matrix_is_translation (const cairo_matrix_t *matrix)
|
||||
{
|
||||
cairo_bool_t is_integer_translation;
|
||||
cairo_fixed_t x0_fixed, y0_fixed;
|
||||
return (matrix->xx == 1.0 && matrix->yx == 0.0 &&
|
||||
matrix->xy == 0.0 && matrix->yy == 1.0);
|
||||
}
|
||||
|
||||
x0_fixed = _cairo_fixed_from_double (m->x0);
|
||||
y0_fixed = _cairo_fixed_from_double (m->y0);
|
||||
cairo_bool_t
|
||||
_cairo_matrix_is_integer_translation (const cairo_matrix_t *matrix,
|
||||
int *itx, int *ity)
|
||||
{
|
||||
if (_cairo_matrix_is_translation (matrix))
|
||||
{
|
||||
cairo_fixed_t x0_fixed = _cairo_fixed_from_double (matrix->x0);
|
||||
cairo_fixed_t y0_fixed = _cairo_fixed_from_double (matrix->y0);
|
||||
|
||||
is_integer_translation = ((m->xx == 1.0) &&
|
||||
(m->yx == 0.0) &&
|
||||
(m->xy == 0.0) &&
|
||||
(m->yy == 1.0) &&
|
||||
(_cairo_fixed_is_integer(x0_fixed)) &&
|
||||
(_cairo_fixed_is_integer(y0_fixed)));
|
||||
if (_cairo_fixed_is_integer (x0_fixed) &&
|
||||
_cairo_fixed_is_integer (y0_fixed))
|
||||
{
|
||||
if (itx)
|
||||
*itx = _cairo_fixed_integer_part (x0_fixed);
|
||||
if (ity)
|
||||
*ity = _cairo_fixed_integer_part (y0_fixed);
|
||||
|
||||
if (! is_integer_translation)
|
||||
return FALSE;
|
||||
return TRUE;
|
||||
}
|
||||
}
|
||||
|
||||
if (itx)
|
||||
*itx = _cairo_fixed_integer_part(x0_fixed);
|
||||
if (ity)
|
||||
*ity = _cairo_fixed_integer_part(y0_fixed);
|
||||
|
||||
return TRUE;
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -728,15 +726,26 @@ void
|
|||
_cairo_matrix_to_pixman_matrix (const cairo_matrix_t *matrix,
|
||||
pixman_transform_t *pixman_transform)
|
||||
{
|
||||
pixman_transform->matrix[0][0] = _cairo_fixed_from_double (matrix->xx);
|
||||
pixman_transform->matrix[0][1] = _cairo_fixed_from_double (matrix->xy);
|
||||
pixman_transform->matrix[0][2] = _cairo_fixed_from_double (matrix->x0);
|
||||
static const pixman_transform_t pixman_identity_transform = {{
|
||||
{1 << 16, 0, 0},
|
||||
{ 0, 1 << 16, 0},
|
||||
{ 0, 0, 1 << 16}
|
||||
}};
|
||||
|
||||
pixman_transform->matrix[1][0] = _cairo_fixed_from_double (matrix->yx);
|
||||
pixman_transform->matrix[1][1] = _cairo_fixed_from_double (matrix->yy);
|
||||
pixman_transform->matrix[1][2] = _cairo_fixed_from_double (matrix->y0);
|
||||
if (_cairo_matrix_is_identity (matrix)) {
|
||||
*pixman_transform = pixman_identity_transform;
|
||||
}
|
||||
else {
|
||||
pixman_transform->matrix[0][0] = _cairo_fixed_from_double (matrix->xx);
|
||||
pixman_transform->matrix[0][1] = _cairo_fixed_from_double (matrix->xy);
|
||||
pixman_transform->matrix[0][2] = _cairo_fixed_from_double (matrix->x0);
|
||||
|
||||
pixman_transform->matrix[2][0] = 0;
|
||||
pixman_transform->matrix[2][1] = 0;
|
||||
pixman_transform->matrix[2][2] = _cairo_fixed_from_double (1);
|
||||
pixman_transform->matrix[1][0] = _cairo_fixed_from_double (matrix->yx);
|
||||
pixman_transform->matrix[1][1] = _cairo_fixed_from_double (matrix->yy);
|
||||
pixman_transform->matrix[1][2] = _cairo_fixed_from_double (matrix->y0);
|
||||
|
||||
pixman_transform->matrix[2][0] = 0;
|
||||
pixman_transform->matrix[2][1] = 0;
|
||||
pixman_transform->matrix[2][2] = 1 << 16;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -416,7 +416,7 @@ static cairo_int_status_t
|
|||
_cairo_meta_surface_show_glyphs (void *abstract_surface,
|
||||
cairo_operator_t op,
|
||||
cairo_pattern_t *source,
|
||||
const cairo_glyph_t *glyphs,
|
||||
cairo_glyph_t *glyphs,
|
||||
int num_glyphs,
|
||||
cairo_scaled_font_t *scaled_font)
|
||||
{
|
||||
|
|
|
@ -498,7 +498,8 @@ SurfacePatternDrawFunc (void *info, CGContextRef context)
|
|||
|
||||
cairo_surface_t *new_surf = NULL;
|
||||
|
||||
_cairo_surface_clone_similar (dummy, pat_surf, &new_surf);
|
||||
_cairo_surface_clone_similar (dummy, pat_surf, rect.x, rect.y,
|
||||
rect.width, rect.height, &new_surf);
|
||||
|
||||
cairo_surface_destroy(dummy);
|
||||
|
||||
|
@ -1063,6 +1064,10 @@ _cairo_nquartz_surface_create_similar (void *abstract_surface,
|
|||
static cairo_status_t
|
||||
_cairo_nquartz_surface_clone_similar (void *abstract_surface,
|
||||
cairo_surface_t *src,
|
||||
int src_x,
|
||||
int src_y,
|
||||
int width,
|
||||
int height,
|
||||
cairo_surface_t **clone_out)
|
||||
{
|
||||
cairo_nquartz_surface_t *surface = (cairo_nquartz_surface_t *) abstract_surface;
|
||||
|
@ -1142,7 +1147,7 @@ _cairo_nquartz_surface_clone_similar (void *abstract_surface,
|
|||
nquartz_image_to_png (quartz_image, NULL);
|
||||
|
||||
CGContextDrawImage (new_surface->cgContext,
|
||||
CGRectMake (0, 0, CGImageGetWidth (quartz_image), CGImageGetHeight (quartz_image)),
|
||||
CGRectMake (src_x, src_y, width, height),
|
||||
quartz_image);
|
||||
CGImageRelease (quartz_image);
|
||||
|
||||
|
@ -1341,7 +1346,7 @@ static cairo_int_status_t
|
|||
_cairo_nquartz_surface_show_glyphs (void *abstract_surface,
|
||||
cairo_operator_t op,
|
||||
cairo_pattern_t *source,
|
||||
const cairo_glyph_t *glyphs,
|
||||
cairo_glyph_t *glyphs,
|
||||
int num_glyphs,
|
||||
cairo_scaled_font_t *scaled_font)
|
||||
{
|
||||
|
|
|
@ -437,7 +437,7 @@ static cairo_int_status_t
|
|||
_cairo_paginated_surface_show_glyphs (void *abstract_surface,
|
||||
cairo_operator_t op,
|
||||
cairo_pattern_t *source,
|
||||
const cairo_glyph_t *glyphs,
|
||||
cairo_glyph_t *glyphs,
|
||||
int num_glyphs,
|
||||
cairo_scaled_font_t *scaled_font)
|
||||
{
|
||||
|
|
|
@ -1,481 +0,0 @@
|
|||
/* cairo - a vector graphics library with display and print output
|
||||
*
|
||||
* Copyright © 2005 Red Hat, Inc.
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it either under the terms of the GNU Lesser General Public
|
||||
* License version 2.1 as published by the Free Software Foundation
|
||||
* (the "LGPL") or, at your option, under the terms of the Mozilla
|
||||
* Public License Version 1.1 (the "MPL"). If you do not alter this
|
||||
* notice, a recipient may use your version of this file under either
|
||||
* the MPL or the LGPL.
|
||||
*
|
||||
* You should have received a copy of the LGPL along with this library
|
||||
* in the file COPYING-LGPL-2.1; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
* You should have received a copy of the MPL along with this library
|
||||
* in the file COPYING-MPL-1.1
|
||||
*
|
||||
* The contents of this file are subject to the Mozilla Public License
|
||||
* Version 1.1 (the "License"); you may not use this file except in
|
||||
* compliance with the License. You may obtain a copy of the License at
|
||||
* http://www.mozilla.org/MPL/
|
||||
*
|
||||
* This software is distributed on an "AS IS" basis, WITHOUT WARRANTY
|
||||
* OF ANY KIND, either express or implied. See the LGPL or the MPL for
|
||||
* the specific language governing rights and limitations.
|
||||
*
|
||||
* The Original Code is the cairo graphics library.
|
||||
*
|
||||
* The Initial Developer of the Original Code is Red Hat, Inc.
|
||||
*
|
||||
* Contributor(s):
|
||||
* Carl D. Worth <cworth@redhat.com>
|
||||
*/
|
||||
|
||||
#include "cairo-path-data-private.h"
|
||||
#include "cairo-path-fixed-private.h"
|
||||
#include "cairo-gstate-private.h"
|
||||
|
||||
const cairo_path_t _cairo_path_nil = { CAIRO_STATUS_NO_MEMORY, NULL, 0 };
|
||||
|
||||
/* Closure for path interpretation. */
|
||||
typedef struct cairo_path_data_count {
|
||||
int count;
|
||||
double tolerance;
|
||||
cairo_point_t current_point;
|
||||
} cpdc_t;
|
||||
|
||||
static cairo_status_t
|
||||
_cpdc_move_to (void *closure, cairo_point_t *point)
|
||||
{
|
||||
cpdc_t *cpdc = closure;
|
||||
|
||||
cpdc->count += 2;
|
||||
|
||||
cpdc->current_point = *point;
|
||||
|
||||
return CAIRO_STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
static cairo_status_t
|
||||
_cpdc_line_to (void *closure, cairo_point_t *point)
|
||||
{
|
||||
cpdc_t *cpdc = closure;
|
||||
|
||||
cpdc->count += 2;
|
||||
|
||||
cpdc->current_point = *point;
|
||||
|
||||
return CAIRO_STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
static cairo_status_t
|
||||
_cpdc_curve_to (void *closure,
|
||||
cairo_point_t *p1,
|
||||
cairo_point_t *p2,
|
||||
cairo_point_t *p3)
|
||||
{
|
||||
cpdc_t *cpdc = closure;
|
||||
|
||||
cpdc->count += 4;
|
||||
|
||||
cpdc->current_point = *p3;
|
||||
|
||||
return CAIRO_STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
static cairo_status_t
|
||||
_cpdc_curve_to_flatten (void *closure,
|
||||
cairo_point_t *p1,
|
||||
cairo_point_t *p2,
|
||||
cairo_point_t *p3)
|
||||
{
|
||||
cpdc_t *cpdc = closure;
|
||||
cairo_status_t status;
|
||||
cairo_spline_t spline;
|
||||
int i;
|
||||
|
||||
cairo_point_t *p0 = &cpdc->current_point;
|
||||
|
||||
status = _cairo_spline_init (&spline, p0, p1, p2, p3);
|
||||
if (status == CAIRO_INT_STATUS_DEGENERATE)
|
||||
return CAIRO_STATUS_SUCCESS;
|
||||
|
||||
status = _cairo_spline_decompose (&spline, cpdc->tolerance);
|
||||
if (status)
|
||||
goto out;
|
||||
|
||||
for (i=1; i < spline.num_points; i++)
|
||||
_cpdc_line_to (cpdc, &spline.points[i]);
|
||||
|
||||
cpdc->current_point = *p3;
|
||||
|
||||
status = CAIRO_STATUS_SUCCESS;
|
||||
|
||||
out:
|
||||
_cairo_spline_fini (&spline);
|
||||
return status;
|
||||
}
|
||||
|
||||
static cairo_status_t
|
||||
_cpdc_close_path (void *closure)
|
||||
{
|
||||
cpdc_t *cpdc = closure;
|
||||
|
||||
cpdc->count += 1;
|
||||
|
||||
return CAIRO_STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
static int
|
||||
_cairo_path_data_count (cairo_path_t *path,
|
||||
cairo_path_fixed_t *path_fixed,
|
||||
double tolerance,
|
||||
cairo_bool_t flatten)
|
||||
{
|
||||
cpdc_t cpdc;
|
||||
|
||||
cpdc.count = 0;
|
||||
cpdc.tolerance = tolerance;
|
||||
cpdc.current_point.x = 0;
|
||||
cpdc.current_point.y = 0;
|
||||
|
||||
_cairo_path_fixed_interpret (path_fixed,
|
||||
CAIRO_DIRECTION_FORWARD,
|
||||
_cpdc_move_to,
|
||||
_cpdc_line_to,
|
||||
flatten ?
|
||||
_cpdc_curve_to_flatten :
|
||||
_cpdc_curve_to,
|
||||
_cpdc_close_path,
|
||||
&cpdc);
|
||||
|
||||
return cpdc.count;
|
||||
}
|
||||
|
||||
/* Closure for path interpretation. */
|
||||
typedef struct cairo_path_data_populate {
|
||||
cairo_path_data_t *data;
|
||||
cairo_gstate_t *gstate;
|
||||
cairo_point_t current_point;
|
||||
} cpdp_t;
|
||||
|
||||
static cairo_status_t
|
||||
_cpdp_move_to (void *closure, cairo_point_t *point)
|
||||
{
|
||||
cpdp_t *cpdp = closure;
|
||||
cairo_path_data_t *data = cpdp->data;
|
||||
double x, y;
|
||||
|
||||
x = _cairo_fixed_to_double (point->x);
|
||||
y = _cairo_fixed_to_double (point->y);
|
||||
|
||||
_cairo_gstate_backend_to_user (cpdp->gstate, &x, &y);
|
||||
|
||||
data->header.type = CAIRO_PATH_MOVE_TO;
|
||||
data->header.length = 2;
|
||||
|
||||
/* We index from 1 to leave room for data->header */
|
||||
data[1].point.x = x;
|
||||
data[1].point.y = y;
|
||||
|
||||
cpdp->data += data->header.length;
|
||||
|
||||
cpdp->current_point = *point;
|
||||
|
||||
return CAIRO_STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
static cairo_status_t
|
||||
_cpdp_line_to (void *closure, cairo_point_t *point)
|
||||
{
|
||||
cpdp_t *cpdp = closure;
|
||||
cairo_path_data_t *data = cpdp->data;
|
||||
double x, y;
|
||||
|
||||
x = _cairo_fixed_to_double (point->x);
|
||||
y = _cairo_fixed_to_double (point->y);
|
||||
|
||||
_cairo_gstate_backend_to_user (cpdp->gstate, &x, &y);
|
||||
|
||||
data->header.type = CAIRO_PATH_LINE_TO;
|
||||
data->header.length = 2;
|
||||
|
||||
/* We index from 1 to leave room for data->header */
|
||||
data[1].point.x = x;
|
||||
data[1].point.y = y;
|
||||
|
||||
cpdp->data += data->header.length;
|
||||
|
||||
cpdp->current_point = *point;
|
||||
|
||||
return CAIRO_STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
static cairo_status_t
|
||||
_cpdp_curve_to (void *closure,
|
||||
cairo_point_t *p1,
|
||||
cairo_point_t *p2,
|
||||
cairo_point_t *p3)
|
||||
{
|
||||
cpdp_t *cpdp = closure;
|
||||
cairo_path_data_t *data = cpdp->data;
|
||||
double x1, y1;
|
||||
double x2, y2;
|
||||
double x3, y3;
|
||||
|
||||
x1 = _cairo_fixed_to_double (p1->x);
|
||||
y1 = _cairo_fixed_to_double (p1->y);
|
||||
_cairo_gstate_backend_to_user (cpdp->gstate, &x1, &y1);
|
||||
|
||||
x2 = _cairo_fixed_to_double (p2->x);
|
||||
y2 = _cairo_fixed_to_double (p2->y);
|
||||
_cairo_gstate_backend_to_user (cpdp->gstate, &x2, &y2);
|
||||
|
||||
x3 = _cairo_fixed_to_double (p3->x);
|
||||
y3 = _cairo_fixed_to_double (p3->y);
|
||||
_cairo_gstate_backend_to_user (cpdp->gstate, &x3, &y3);
|
||||
|
||||
data->header.type = CAIRO_PATH_CURVE_TO;
|
||||
data->header.length = 4;
|
||||
|
||||
/* We index from 1 to leave room for data->header */
|
||||
data[1].point.x = x1;
|
||||
data[1].point.y = y1;
|
||||
|
||||
data[2].point.x = x2;
|
||||
data[2].point.y = y2;
|
||||
|
||||
data[3].point.x = x3;
|
||||
data[3].point.y = y3;
|
||||
|
||||
cpdp->data += data->header.length;
|
||||
|
||||
cpdp->current_point = *p3;
|
||||
|
||||
return CAIRO_STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
static cairo_status_t
|
||||
_cpdp_curve_to_flatten (void *closure,
|
||||
cairo_point_t *p1,
|
||||
cairo_point_t *p2,
|
||||
cairo_point_t *p3)
|
||||
{
|
||||
cpdp_t *cpdp = closure;
|
||||
cairo_status_t status;
|
||||
cairo_spline_t spline;
|
||||
int i;
|
||||
|
||||
cairo_point_t *p0 = &cpdp->current_point;
|
||||
|
||||
status = _cairo_spline_init (&spline, p0, p1, p2, p3);
|
||||
if (status == CAIRO_INT_STATUS_DEGENERATE)
|
||||
return CAIRO_STATUS_SUCCESS;
|
||||
|
||||
status = _cairo_spline_decompose (&spline, cpdp->gstate->tolerance);
|
||||
if (status)
|
||||
goto out;
|
||||
|
||||
for (i=1; i < spline.num_points; i++)
|
||||
_cpdp_line_to (cpdp, &spline.points[i]);
|
||||
|
||||
cpdp->current_point = *p3;
|
||||
|
||||
status = CAIRO_STATUS_SUCCESS;
|
||||
|
||||
out:
|
||||
_cairo_spline_fini (&spline);
|
||||
return status;
|
||||
}
|
||||
|
||||
static cairo_status_t
|
||||
_cpdp_close_path (void *closure)
|
||||
{
|
||||
cpdp_t *cpdp = closure;
|
||||
cairo_path_data_t *data = cpdp->data;
|
||||
|
||||
data->header.type = CAIRO_PATH_CLOSE_PATH;
|
||||
data->header.length = 1;
|
||||
|
||||
cpdp->data += data->header.length;
|
||||
|
||||
return CAIRO_STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
static void
|
||||
_cairo_path_data_populate (cairo_path_t *path,
|
||||
cairo_path_fixed_t *path_fixed,
|
||||
cairo_gstate_t *gstate,
|
||||
cairo_bool_t flatten)
|
||||
{
|
||||
cpdp_t cpdp;
|
||||
|
||||
cpdp.data = path->data;
|
||||
cpdp.gstate = gstate;
|
||||
cpdp.current_point.x = 0;
|
||||
cpdp.current_point.y = 0;
|
||||
|
||||
_cairo_path_fixed_interpret (path_fixed,
|
||||
CAIRO_DIRECTION_FORWARD,
|
||||
_cpdp_move_to,
|
||||
_cpdp_line_to,
|
||||
flatten ?
|
||||
_cpdp_curve_to_flatten :
|
||||
_cpdp_curve_to,
|
||||
_cpdp_close_path,
|
||||
&cpdp);
|
||||
|
||||
/* Sanity check the count */
|
||||
assert (cpdp.data - path->data == path->num_data);
|
||||
}
|
||||
|
||||
static cairo_path_t *
|
||||
_cairo_path_data_create_real (cairo_path_fixed_t *path_fixed,
|
||||
cairo_gstate_t *gstate,
|
||||
cairo_bool_t flatten)
|
||||
{
|
||||
cairo_path_t *path;
|
||||
|
||||
path = malloc (sizeof (cairo_path_t));
|
||||
if (path == NULL)
|
||||
return (cairo_path_t*) &_cairo_path_nil;
|
||||
|
||||
path->num_data = _cairo_path_data_count (path, path_fixed,
|
||||
gstate->tolerance, flatten);
|
||||
|
||||
path->data = malloc (path->num_data * sizeof (cairo_path_data_t));
|
||||
if (path->data == NULL) {
|
||||
free (path);
|
||||
return (cairo_path_t*) &_cairo_path_nil;
|
||||
}
|
||||
|
||||
path->status = CAIRO_STATUS_SUCCESS;
|
||||
|
||||
_cairo_path_data_populate (path, path_fixed,
|
||||
gstate, flatten);
|
||||
|
||||
return path;
|
||||
}
|
||||
|
||||
/**
|
||||
* cairo_path_destroy:
|
||||
* @path: a path previously returned by either cairo_copy_path() or
|
||||
* cairo_copy_path_flat().
|
||||
*
|
||||
* Immediately releases all memory associated with @path. After a call
|
||||
* to cairo_path_destroy() the @path pointer is no longer valid and
|
||||
* should not be used further.
|
||||
*
|
||||
* NOTE: cairo_path_destroy function should only be called with a
|
||||
* pointer to a #cairo_path_t returned by a cairo function. Any path
|
||||
* that is created manually (ie. outside of cairo) should be destroyed
|
||||
* manually as well.
|
||||
**/
|
||||
void
|
||||
cairo_path_destroy (cairo_path_t *path)
|
||||
{
|
||||
if (path == NULL || path == &_cairo_path_nil)
|
||||
return;
|
||||
|
||||
free (path->data);
|
||||
path->num_data = 0;
|
||||
free (path);
|
||||
}
|
||||
|
||||
/**
|
||||
* _cairo_path_data_create:
|
||||
* @path: a fixed-point, device-space path to be converted and copied
|
||||
* @gstate: the current graphics state
|
||||
*
|
||||
* Creates a user-space #cairo_path_t copy of the given device-space
|
||||
* @path. The @gstate parameter provides the inverse CTM for the
|
||||
* conversion.
|
||||
*
|
||||
* Return value: the new copy of the path. If there is insufficient
|
||||
* memory a pointer to a special static cairo_path_nil will be
|
||||
* returned instead with status==CAIRO_STATUS_NO_MEMORY and
|
||||
* data==NULL.
|
||||
**/
|
||||
cairo_path_t *
|
||||
_cairo_path_data_create (cairo_path_fixed_t *path,
|
||||
cairo_gstate_t *gstate)
|
||||
{
|
||||
return _cairo_path_data_create_real (path, gstate, FALSE);
|
||||
}
|
||||
|
||||
/**
|
||||
* _cairo_path_data_create_flat:
|
||||
* @path: a fixed-point, device-space path to be flattened, converted and copied
|
||||
* @gstate: the current graphics state
|
||||
*
|
||||
* Creates a flattened, user-space #cairo_path_t copy of the given
|
||||
* device-space @path. The @gstate parameter provide the inverse CTM
|
||||
* for the conversion, as well as the tolerance value to control the
|
||||
* accuracy of the flattening.
|
||||
*
|
||||
* Return value: the flattened copy of the path. If there is insufficient
|
||||
* memory a pointer to a special static cairo_path_nil will be
|
||||
* returned instead with status==CAIRO_STATUS_NO_MEMORY and
|
||||
* data==NULL.
|
||||
**/
|
||||
cairo_path_t *
|
||||
_cairo_path_data_create_flat (cairo_path_fixed_t *path,
|
||||
cairo_gstate_t *gstate)
|
||||
{
|
||||
return _cairo_path_data_create_real (path, gstate, TRUE);
|
||||
}
|
||||
|
||||
/**
|
||||
* _cairo_path_data_append_to_context:
|
||||
* @path: the path data to be appended
|
||||
* @cr: a cairo context
|
||||
*
|
||||
* Append @path to the current path within @cr.
|
||||
*
|
||||
* Return value: CAIRO_STATUS_INVALID_PATH_DATA if the data in @path
|
||||
* is invalid, and CAIRO_STATUS_SUCCESS otherwise.
|
||||
**/
|
||||
cairo_status_t
|
||||
_cairo_path_data_append_to_context (cairo_path_t *path,
|
||||
cairo_t *cr)
|
||||
{
|
||||
int i;
|
||||
cairo_path_data_t *p;
|
||||
|
||||
for (i=0; i < path->num_data; i += path->data[i].header.length) {
|
||||
p = &path->data[i];
|
||||
switch (p->header.type) {
|
||||
case CAIRO_PATH_MOVE_TO:
|
||||
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)
|
||||
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)
|
||||
return CAIRO_STATUS_INVALID_PATH_DATA;
|
||||
cairo_curve_to (cr,
|
||||
p[1].point.x, p[1].point.y,
|
||||
p[2].point.x, p[2].point.y,
|
||||
p[3].point.x, p[3].point.y);
|
||||
break;
|
||||
case CAIRO_PATH_CLOSE_PATH:
|
||||
if (p->header.length != 1)
|
||||
return CAIRO_STATUS_INVALID_PATH_DATA;
|
||||
cairo_close_path (cr);
|
||||
break;
|
||||
default:
|
||||
return CAIRO_STATUS_INVALID_PATH_DATA;
|
||||
}
|
||||
}
|
||||
|
||||
return CAIRO_STATUS_SUCCESS;
|
||||
}
|
|
@ -194,9 +194,9 @@ _cairo_path_fixed_fill_to_traps (cairo_path_fixed_t *path,
|
|||
if (status)
|
||||
goto BAIL;
|
||||
|
||||
status = _cairo_traps_tessellate_polygon (filler.traps,
|
||||
&filler.polygon,
|
||||
fill_rule);
|
||||
status = _cairo_bentley_ottmann_tessellate_polygon (filler.traps,
|
||||
&filler.polygon,
|
||||
fill_rule);
|
||||
if (status)
|
||||
goto BAIL;
|
||||
|
||||
|
|
|
@ -0,0 +1,639 @@
|
|||
/* cairo - a vector graphics library with display and print output
|
||||
*
|
||||
* Copyright © 2002 University of Southern California
|
||||
* Copyright © 2005 Red Hat, Inc.
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it either under the terms of the GNU Lesser General Public
|
||||
* License version 2.1 as published by the Free Software Foundation
|
||||
* (the "LGPL") or, at your option, under the terms of the Mozilla
|
||||
* Public License Version 1.1 (the "MPL"). If you do not alter this
|
||||
* notice, a recipient may use your version of this file under either
|
||||
* the MPL or the LGPL.
|
||||
*
|
||||
* You should have received a copy of the LGPL along with this library
|
||||
* in the file COPYING-LGPL-2.1; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
* You should have received a copy of the MPL along with this library
|
||||
* in the file COPYING-MPL-1.1
|
||||
*
|
||||
* The contents of this file are subject to the Mozilla Public License
|
||||
* Version 1.1 (the "License"); you may not use this file except in
|
||||
* compliance with the License. You may obtain a copy of the License at
|
||||
* http://www.mozilla.org/MPL/
|
||||
*
|
||||
* This software is distributed on an "AS IS" basis, WITHOUT WARRANTY
|
||||
* OF ANY KIND, either express or implied. See the LGPL or the MPL for
|
||||
* the specific language governing rights and limitations.
|
||||
*
|
||||
* The Original Code is the cairo graphics library.
|
||||
*
|
||||
* The Initial Developer of the Original Code is University of Southern
|
||||
* California.
|
||||
*
|
||||
* Contributor(s):
|
||||
* Carl D. Worth <cworth@cworth.org>
|
||||
*/
|
||||
|
||||
#include <stdlib.h>
|
||||
#include "cairoint.h"
|
||||
|
||||
#include "cairo-path-fixed-private.h"
|
||||
|
||||
/* private functions */
|
||||
static cairo_status_t
|
||||
_cairo_path_fixed_add (cairo_path_fixed_t *path,
|
||||
cairo_path_op_t op,
|
||||
cairo_point_t *points,
|
||||
int num_points);
|
||||
|
||||
static void
|
||||
_cairo_path_fixed_add_op_buf (cairo_path_fixed_t *path,
|
||||
cairo_path_op_buf_t *op_buf);
|
||||
|
||||
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);
|
||||
|
||||
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_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_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->arg_buf_head = NULL;
|
||||
path->arg_buf_tail = NULL;
|
||||
|
||||
path->current_point.x = 0;
|
||||
path->current_point.y = 0;
|
||||
path->has_current_point = FALSE;
|
||||
path->last_move_point = path->current_point;
|
||||
}
|
||||
|
||||
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_fixed_init (path);
|
||||
path->current_point = other->current_point;
|
||||
path->has_current_point = other->has_current_point;
|
||||
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)
|
||||
{
|
||||
op_buf = _cairo_path_op_buf_create ();
|
||||
if (op_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);
|
||||
}
|
||||
|
||||
return CAIRO_STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
cairo_path_fixed_t *
|
||||
_cairo_path_fixed_create (void)
|
||||
{
|
||||
cairo_path_fixed_t *path = malloc (sizeof (cairo_path_fixed_t));
|
||||
|
||||
if (!path)
|
||||
return NULL;
|
||||
_cairo_path_fixed_init (path);
|
||||
return path;
|
||||
}
|
||||
|
||||
void
|
||||
_cairo_path_fixed_fini (cairo_path_fixed_t *path)
|
||||
{
|
||||
cairo_path_op_buf_t *op_buf;
|
||||
cairo_path_arg_buf_t *arg_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);
|
||||
}
|
||||
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->has_current_point = FALSE;
|
||||
}
|
||||
|
||||
void
|
||||
_cairo_path_fixed_destroy (cairo_path_fixed_t *path)
|
||||
{
|
||||
_cairo_path_fixed_fini (path);
|
||||
free (path);
|
||||
}
|
||||
|
||||
cairo_status_t
|
||||
_cairo_path_fixed_move_to (cairo_path_fixed_t *path,
|
||||
cairo_fixed_t x,
|
||||
cairo_fixed_t y)
|
||||
{
|
||||
cairo_status_t status;
|
||||
cairo_point_t point;
|
||||
|
||||
point.x = x;
|
||||
point.y = y;
|
||||
|
||||
status = _cairo_path_fixed_add (path, CAIRO_PATH_OP_MOVE_TO, &point, 1);
|
||||
if (status)
|
||||
return status;
|
||||
|
||||
path->current_point = point;
|
||||
path->has_current_point = TRUE;
|
||||
path->last_move_point = path->current_point;
|
||||
|
||||
return CAIRO_STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
void
|
||||
_cairo_path_fixed_new_sub_path (cairo_path_fixed_t *path)
|
||||
{
|
||||
path->has_current_point = FALSE;
|
||||
}
|
||||
|
||||
cairo_status_t
|
||||
_cairo_path_fixed_rel_move_to (cairo_path_fixed_t *path,
|
||||
cairo_fixed_t dx,
|
||||
cairo_fixed_t dy)
|
||||
{
|
||||
cairo_fixed_t x, y;
|
||||
|
||||
if (! path->has_current_point)
|
||||
return CAIRO_STATUS_NO_CURRENT_POINT;
|
||||
|
||||
x = path->current_point.x + dx;
|
||||
y = path->current_point.y + dy;
|
||||
|
||||
return _cairo_path_fixed_move_to (path, x, y);
|
||||
}
|
||||
|
||||
cairo_status_t
|
||||
_cairo_path_fixed_line_to (cairo_path_fixed_t *path,
|
||||
cairo_fixed_t x,
|
||||
cairo_fixed_t y)
|
||||
{
|
||||
cairo_status_t status;
|
||||
cairo_point_t point;
|
||||
|
||||
point.x = x;
|
||||
point.y = y;
|
||||
|
||||
/* When there is not yet a current point, the line_to operation
|
||||
* becomes a move_to instead. Note: We have to do this by
|
||||
* explicitly calling into _cairo_path_fixed_line_to to ensure
|
||||
* that the last_move_point state is updated properly.
|
||||
*/
|
||||
if (! path->has_current_point)
|
||||
status = _cairo_path_fixed_move_to (path, point.x, point.y);
|
||||
else
|
||||
status = _cairo_path_fixed_add (path, CAIRO_PATH_OP_LINE_TO, &point, 1);
|
||||
|
||||
if (status)
|
||||
return status;
|
||||
|
||||
path->current_point = point;
|
||||
path->has_current_point = TRUE;
|
||||
|
||||
return CAIRO_STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
cairo_status_t
|
||||
_cairo_path_fixed_rel_line_to (cairo_path_fixed_t *path,
|
||||
cairo_fixed_t dx,
|
||||
cairo_fixed_t dy)
|
||||
{
|
||||
cairo_fixed_t x, y;
|
||||
|
||||
if (! path->has_current_point)
|
||||
return CAIRO_STATUS_NO_CURRENT_POINT;
|
||||
|
||||
x = path->current_point.x + dx;
|
||||
y = path->current_point.y + dy;
|
||||
|
||||
return _cairo_path_fixed_line_to (path, x, y);
|
||||
}
|
||||
|
||||
cairo_status_t
|
||||
_cairo_path_fixed_curve_to (cairo_path_fixed_t *path,
|
||||
cairo_fixed_t x0, cairo_fixed_t y0,
|
||||
cairo_fixed_t x1, cairo_fixed_t y1,
|
||||
cairo_fixed_t x2, cairo_fixed_t y2)
|
||||
{
|
||||
cairo_status_t status;
|
||||
cairo_point_t point[3];
|
||||
|
||||
point[0].x = x0; point[0].y = y0;
|
||||
point[1].x = x1; point[1].y = y1;
|
||||
point[2].x = x2; point[2].y = y2;
|
||||
|
||||
if (! path->has_current_point) {
|
||||
status = _cairo_path_fixed_add (path, CAIRO_PATH_OP_MOVE_TO,
|
||||
&point[0], 1);
|
||||
if (status)
|
||||
return status;
|
||||
}
|
||||
|
||||
status = _cairo_path_fixed_add (path, CAIRO_PATH_OP_CURVE_TO, point, 3);
|
||||
if (status)
|
||||
return status;
|
||||
|
||||
path->current_point = point[2];
|
||||
path->has_current_point = TRUE;
|
||||
|
||||
return CAIRO_STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
cairo_status_t
|
||||
_cairo_path_fixed_rel_curve_to (cairo_path_fixed_t *path,
|
||||
cairo_fixed_t dx0, cairo_fixed_t dy0,
|
||||
cairo_fixed_t dx1, cairo_fixed_t dy1,
|
||||
cairo_fixed_t dx2, cairo_fixed_t dy2)
|
||||
{
|
||||
cairo_fixed_t x0, y0;
|
||||
cairo_fixed_t x1, y1;
|
||||
cairo_fixed_t x2, y2;
|
||||
|
||||
if (! path->has_current_point)
|
||||
return CAIRO_STATUS_NO_CURRENT_POINT;
|
||||
|
||||
x0 = path->current_point.x + dx0;
|
||||
y0 = path->current_point.y + dy0;
|
||||
|
||||
x1 = path->current_point.x + dx1;
|
||||
y1 = path->current_point.y + dy1;
|
||||
|
||||
x2 = path->current_point.x + dx2;
|
||||
y2 = path->current_point.y + dy2;
|
||||
|
||||
return _cairo_path_fixed_curve_to (path,
|
||||
x0, y0,
|
||||
x1, y1,
|
||||
x2, y2);
|
||||
}
|
||||
|
||||
cairo_status_t
|
||||
_cairo_path_fixed_close_path (cairo_path_fixed_t *path)
|
||||
{
|
||||
cairo_status_t status;
|
||||
|
||||
if (! path->has_current_point)
|
||||
return CAIRO_STATUS_SUCCESS;
|
||||
|
||||
status = _cairo_path_fixed_add (path, CAIRO_PATH_OP_CLOSE_PATH, NULL, 0);
|
||||
if (status)
|
||||
return status;
|
||||
|
||||
status = _cairo_path_fixed_move_to (path,
|
||||
path->last_move_point.x,
|
||||
path->last_move_point.y);
|
||||
if (status)
|
||||
return status;
|
||||
|
||||
return CAIRO_STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
cairo_status_t
|
||||
_cairo_path_fixed_get_current_point (cairo_path_fixed_t *path,
|
||||
cairo_fixed_t *x,
|
||||
cairo_fixed_t *y)
|
||||
{
|
||||
if (! path->has_current_point)
|
||||
return CAIRO_STATUS_NO_CURRENT_POINT;
|
||||
|
||||
*x = path->current_point.x;
|
||||
*y = path->current_point.y;
|
||||
|
||||
return CAIRO_STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
static cairo_status_t
|
||||
_cairo_path_fixed_add (cairo_path_fixed_t *path,
|
||||
cairo_path_op_t op,
|
||||
cairo_point_t *points,
|
||||
int num_points)
|
||||
{
|
||||
if (path->op_buf_tail == NULL ||
|
||||
path->op_buf_tail->num_ops + 1 > CAIRO_PATH_BUF_SIZE)
|
||||
{
|
||||
cairo_path_op_buf_t *op_buf;
|
||||
|
||||
op_buf = _cairo_path_op_buf_create ();
|
||||
if (op_buf == NULL)
|
||||
return CAIRO_STATUS_NO_MEMORY;
|
||||
|
||||
_cairo_path_fixed_add_op_buf (path, op_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);
|
||||
|
||||
return CAIRO_STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
static void
|
||||
_cairo_path_fixed_add_op_buf (cairo_path_fixed_t *path,
|
||||
cairo_path_op_buf_t *op_buf)
|
||||
{
|
||||
op_buf->next = NULL;
|
||||
op_buf->prev = path->op_buf_tail;
|
||||
|
||||
if (path->op_buf_tail) {
|
||||
path->op_buf_tail->next = op_buf;
|
||||
} else {
|
||||
path->op_buf_head = op_buf;
|
||||
}
|
||||
|
||||
path->op_buf_tail = op_buf;
|
||||
}
|
||||
|
||||
static void
|
||||
_cairo_path_fixed_add_arg_buf (cairo_path_fixed_t *path,
|
||||
cairo_path_arg_buf_t *arg_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;
|
||||
}
|
||||
|
||||
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_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;
|
||||
}
|
||||
|
||||
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_point_t *points,
|
||||
int num_points)
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i=0; i < num_points; i++) {
|
||||
arg_buf->points[arg_buf->num_points++] = points[i];
|
||||
}
|
||||
}
|
||||
|
||||
#define CAIRO_PATH_OP_MAX_ARGS 3
|
||||
|
||||
static int const num_args[] =
|
||||
{
|
||||
1, /* cairo_path_move_to */
|
||||
1, /* cairo_path_op_line_to */
|
||||
3, /* cairo_path_op_curve_to */
|
||||
0, /* cairo_path_op_close_path */
|
||||
};
|
||||
|
||||
cairo_status_t
|
||||
_cairo_path_fixed_interpret (cairo_path_fixed_t *path,
|
||||
cairo_direction_t dir,
|
||||
cairo_path_fixed_move_to_func_t *move_to,
|
||||
cairo_path_fixed_line_to_func_t *line_to,
|
||||
cairo_path_fixed_curve_to_func_t *curve_to,
|
||||
cairo_path_fixed_close_path_func_t *close_path,
|
||||
void *closure)
|
||||
{
|
||||
cairo_status_t status;
|
||||
int i, arg;
|
||||
cairo_path_op_buf_t *op_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)
|
||||
{
|
||||
int start, stop;
|
||||
if (forward) {
|
||||
start = 0;
|
||||
stop = op_buf->num_ops;
|
||||
} else {
|
||||
start = op_buf->num_ops - 1;
|
||||
stop = -1;
|
||||
}
|
||||
|
||||
for (i=start; i != stop; i += step) {
|
||||
op = 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];
|
||||
}
|
||||
|
||||
switch (op) {
|
||||
case CAIRO_PATH_OP_MOVE_TO:
|
||||
status = (*move_to) (closure, &point[0]);
|
||||
break;
|
||||
case CAIRO_PATH_OP_LINE_TO:
|
||||
status = (*line_to) (closure, &point[0]);
|
||||
break;
|
||||
case CAIRO_PATH_OP_CURVE_TO:
|
||||
status = (*curve_to) (closure, &point[0], &point[1], &point[2]);
|
||||
break;
|
||||
case CAIRO_PATH_OP_CLOSE_PATH:
|
||||
default:
|
||||
status = (*close_path) (closure);
|
||||
break;
|
||||
}
|
||||
if (status)
|
||||
return status;
|
||||
}
|
||||
}
|
||||
|
||||
return CAIRO_STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
static void
|
||||
_cairo_path_fixed_offset_and_scale (cairo_path_fixed_t *path,
|
||||
cairo_fixed_t offx,
|
||||
cairo_fixed_t offy,
|
||||
cairo_fixed_t scalex,
|
||||
cairo_fixed_t scaley)
|
||||
{
|
||||
cairo_path_arg_buf_t *arg_buf = path->arg_buf_head;
|
||||
int i;
|
||||
cairo_int64_t i64temp;
|
||||
cairo_fixed_t fixedtemp;
|
||||
|
||||
while (arg_buf) {
|
||||
for (i = 0; i < arg_buf->num_points; i++) {
|
||||
if (scalex == CAIRO_FIXED_ONE) {
|
||||
arg_buf->points[i].x += offx;
|
||||
} else {
|
||||
fixedtemp = arg_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));
|
||||
}
|
||||
|
||||
if (scaley == CAIRO_FIXED_ONE) {
|
||||
arg_buf->points[i].y += offy;
|
||||
} else {
|
||||
fixedtemp = arg_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));
|
||||
}
|
||||
}
|
||||
|
||||
arg_buf = arg_buf->next;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* _cairo_path_fixed_device_transform:
|
||||
* @path: a #cairo_path_fixed_t to be transformed
|
||||
* @device_transform: a matrix with only scaling/translation (no rotation or shear)
|
||||
*
|
||||
* Transform the fixed-point path according to the scaling and
|
||||
* translation of the given matrix. This function assert()s that the
|
||||
* given matrix has no rotation or shear elements, (that is, xy and yx
|
||||
* are 0.0).
|
||||
**/
|
||||
void
|
||||
_cairo_path_fixed_device_transform (cairo_path_fixed_t *path,
|
||||
cairo_matrix_t *device_transform)
|
||||
{
|
||||
assert (device_transform->yx == 0.0 && device_transform->xy == 0.0);
|
||||
/* XXX: FRAGILE: I'm not really sure whether we're doing the
|
||||
* "right" thing here if there is both scaling and translation in
|
||||
* the matrix. But for now, the internals guarantee that we won't
|
||||
* really ever have both going on. */
|
||||
_cairo_path_fixed_offset_and_scale (path,
|
||||
_cairo_fixed_from_double (device_transform->x0),
|
||||
_cairo_fixed_from_double (device_transform->y0),
|
||||
_cairo_fixed_from_double (device_transform->xx),
|
||||
_cairo_fixed_from_double (device_transform->yy));
|
||||
}
|
|
@ -1,6 +1,7 @@
|
|||
/* cairo - a vector graphics library with display and print output
|
||||
*
|
||||
* Copyright © 2005 Red Hat, Inc.
|
||||
* Copyright © 2006 Red Hat, Inc.
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it either under the terms of the GNU Lesser General Public
|
||||
|
@ -33,23 +34,26 @@
|
|||
* Carl D. Worth <cworth@redhat.com>
|
||||
*/
|
||||
|
||||
#ifndef CAIRO_PATH_DATA_PRIVATE_H
|
||||
#define CAIRO_PATH_DATA_PRIVATE_H
|
||||
#ifndef CAIRO_PATH_PRIVATE_H
|
||||
#define CAIRO_PATH_PRIVATE_H
|
||||
|
||||
#include "cairoint.h"
|
||||
|
||||
extern const cairo_private cairo_path_t _cairo_path_nil;
|
||||
|
||||
cairo_private cairo_path_t *
|
||||
_cairo_path_data_create (cairo_path_fixed_t *path,
|
||||
_cairo_path_create (cairo_path_fixed_t *path,
|
||||
cairo_gstate_t *gstate);
|
||||
|
||||
cairo_private cairo_path_t *
|
||||
_cairo_path_create_flat (cairo_path_fixed_t *path,
|
||||
cairo_gstate_t *gstate);
|
||||
|
||||
cairo_private cairo_path_t *
|
||||
_cairo_path_data_create_flat (cairo_path_fixed_t *path,
|
||||
cairo_gstate_t *gstate);
|
||||
_cairo_path_create_in_error (cairo_status_t status);
|
||||
|
||||
cairo_private cairo_status_t
|
||||
_cairo_path_data_append_to_context (cairo_path_t *path,
|
||||
cairo_t *cr);
|
||||
_cairo_path_append_to_context (const cairo_path_t *path,
|
||||
cairo_t *cr);
|
||||
|
||||
#endif /* CAIRO_PATH_DATA_PRIVATE_H */
|
|
@ -201,7 +201,6 @@ _cairo_stroker_face_clockwise (cairo_stroke_face_t *in, cairo_stroke_face_t *out
|
|||
static cairo_status_t
|
||||
_cairo_stroker_join (cairo_stroker_t *stroker, cairo_stroke_face_t *in, cairo_stroke_face_t *out)
|
||||
{
|
||||
cairo_status_t status;
|
||||
int clockwise = _cairo_stroker_face_clockwise (out, in);
|
||||
cairo_point_t *inpt, *outpt;
|
||||
|
||||
|
@ -296,8 +295,8 @@ _cairo_stroker_join (cairo_stroker_t *stroker, cairo_stroke_face_t *in, cairo_st
|
|||
double x1, y1, x2, y2;
|
||||
double mx, my;
|
||||
double dx1, dx2, dy1, dy2;
|
||||
cairo_polygon_t polygon;
|
||||
cairo_point_t outer;
|
||||
cairo_point_t quad[4];
|
||||
|
||||
/*
|
||||
* we've got the points already transformed to device
|
||||
|
@ -339,18 +338,13 @@ _cairo_stroker_join (cairo_stroker_t *stroker, cairo_stroke_face_t *in, cairo_st
|
|||
*/
|
||||
outer.x = _cairo_fixed_from_double (mx);
|
||||
outer.y = _cairo_fixed_from_double (my);
|
||||
_cairo_polygon_init (&polygon);
|
||||
_cairo_polygon_move_to (&polygon, &in->point);
|
||||
_cairo_polygon_line_to (&polygon, inpt);
|
||||
_cairo_polygon_line_to (&polygon, &outer);
|
||||
_cairo_polygon_line_to (&polygon, outpt);
|
||||
_cairo_polygon_close (&polygon);
|
||||
status = _cairo_traps_tessellate_polygon (stroker->traps,
|
||||
&polygon,
|
||||
CAIRO_FILL_RULE_WINDING);
|
||||
_cairo_polygon_fini (&polygon);
|
||||
|
||||
return status;
|
||||
quad[0] = in->point;
|
||||
quad[1] = *inpt;
|
||||
quad[2] = outer;
|
||||
quad[3] = *outpt;
|
||||
|
||||
return _cairo_traps_tessellate_convex_quad (stroker->traps, quad);
|
||||
}
|
||||
/* fall through ... */
|
||||
}
|
||||
|
@ -424,7 +418,7 @@ _cairo_stroker_add_cap (cairo_stroker_t *stroker, cairo_stroke_face_t *f)
|
|||
_cairo_polygon_line_to (&polygon, &f->ccw);
|
||||
_cairo_polygon_close (&polygon);
|
||||
|
||||
status = _cairo_traps_tessellate_polygon (stroker->traps, &polygon, CAIRO_FILL_RULE_WINDING);
|
||||
status = _cairo_bentley_ottmann_tessellate_polygon (stroker->traps, &polygon, CAIRO_FILL_RULE_WINDING);
|
||||
_cairo_polygon_fini (&polygon);
|
||||
|
||||
return status;
|
||||
|
@ -573,8 +567,7 @@ _cairo_stroker_add_sub_edge (cairo_stroker_t *stroker, cairo_point_t *p1, cairo_
|
|||
cairo_slope_t *slope, cairo_stroke_face_t *start,
|
||||
cairo_stroke_face_t *end)
|
||||
{
|
||||
cairo_status_t status;
|
||||
cairo_polygon_t polygon;
|
||||
cairo_point_t rectangle[4];
|
||||
|
||||
_compute_face (p1, slope, stroker, start);
|
||||
|
||||
|
@ -586,30 +579,12 @@ _cairo_stroker_add_sub_edge (cairo_stroker_t *stroker, cairo_point_t *p1, cairo_
|
|||
if (p1->x == p2->x && p1->y == p2->y)
|
||||
return CAIRO_STATUS_SUCCESS;
|
||||
|
||||
/* XXX: I should really check the return value of the
|
||||
move_to/line_to functions here to catch out of memory
|
||||
conditions. But since that would be ugly, I'd prefer to add a
|
||||
status flag to the polygon object that I could check only once
|
||||
at then end of this sequence, (like we do with cairo_t
|
||||
already). */
|
||||
_cairo_polygon_init (&polygon);
|
||||
_cairo_polygon_move_to (&polygon, &start->cw);
|
||||
_cairo_polygon_line_to (&polygon, &start->ccw);
|
||||
_cairo_polygon_line_to (&polygon, &end->ccw);
|
||||
_cairo_polygon_line_to (&polygon, &end->cw);
|
||||
_cairo_polygon_close (&polygon);
|
||||
rectangle[0] = start->cw;
|
||||
rectangle[1] = start->ccw;
|
||||
rectangle[2] = end->ccw;
|
||||
rectangle[3] = end->cw;
|
||||
|
||||
/* XXX: We can't use tessellate_rectangle as the matrix may have
|
||||
skewed this into a non-rectangular shape. Perhaps it would be
|
||||
worth checking the matrix for skew so that the common case
|
||||
could use the faster tessellate_rectangle rather than
|
||||
tessellate_polygon? */
|
||||
status = _cairo_traps_tessellate_polygon (stroker->traps,
|
||||
&polygon, CAIRO_FILL_RULE_WINDING);
|
||||
|
||||
_cairo_polygon_fini (&polygon);
|
||||
|
||||
return status;
|
||||
return _cairo_traps_tessellate_convex_quad (stroker->traps, rectangle);
|
||||
}
|
||||
|
||||
static cairo_status_t
|
||||
|
|
Разница между файлами не показана из-за своего большого размера
Загрузить разницу
|
@ -48,40 +48,6 @@ static const cairo_solid_pattern_t cairo_pattern_nil_null_pointer = {
|
|||
CAIRO_EXTEND_GRADIENT_DEFAULT }, /* extend */
|
||||
};
|
||||
|
||||
static const cairo_solid_pattern_t cairo_pattern_nil_file_not_found = {
|
||||
{ CAIRO_PATTERN_TYPE_SOLID, /* type */
|
||||
CAIRO_REF_COUNT_INVALID, /* ref_count */
|
||||
CAIRO_STATUS_FILE_NOT_FOUND, /* status */
|
||||
{ 1., 0., 0., 1., 0., 0., }, /* matrix */
|
||||
CAIRO_FILTER_DEFAULT, /* filter */
|
||||
CAIRO_EXTEND_GRADIENT_DEFAULT }, /* extend */
|
||||
};
|
||||
|
||||
static const cairo_solid_pattern_t cairo_pattern_nil_read_error = {
|
||||
{ CAIRO_PATTERN_TYPE_SOLID, /* type */
|
||||
CAIRO_REF_COUNT_INVALID, /* ref_count */
|
||||
CAIRO_STATUS_READ_ERROR, /* status */
|
||||
{ 1., 0., 0., 1., 0., 0., }, /* matrix */
|
||||
CAIRO_FILTER_DEFAULT, /* filter */
|
||||
CAIRO_EXTEND_GRADIENT_DEFAULT }, /* extend */
|
||||
};
|
||||
|
||||
static const cairo_pattern_t *
|
||||
_cairo_pattern_nil_for_status (cairo_status_t status)
|
||||
{
|
||||
/* A switch statement would be more natural here, but we're
|
||||
* avoiding that to prevent a "false positive" warning from
|
||||
* -Wswitch-enum, (and I don't want to maintain a list of all
|
||||
* status values here). */
|
||||
if (status == CAIRO_STATUS_NULL_POINTER)
|
||||
return &cairo_pattern_nil_null_pointer.base;
|
||||
if (status == CAIRO_STATUS_FILE_NOT_FOUND)
|
||||
return &cairo_pattern_nil_file_not_found.base;
|
||||
if (status == CAIRO_STATUS_READ_ERROR)
|
||||
return &cairo_pattern_nil_read_error.base;
|
||||
return &cairo_pattern_nil.base;
|
||||
}
|
||||
|
||||
/**
|
||||
* _cairo_pattern_set_error:
|
||||
* @pattern: a pattern
|
||||
|
@ -294,6 +260,20 @@ _cairo_pattern_create_solid (const cairo_color_t *color)
|
|||
return &pattern->base;
|
||||
}
|
||||
|
||||
static const cairo_pattern_t *
|
||||
_cairo_pattern_create_in_error (cairo_status_t status)
|
||||
{
|
||||
cairo_pattern_t *pattern;
|
||||
|
||||
pattern = _cairo_pattern_create_solid (_cairo_stock_color (CAIRO_STOCK_BLACK));
|
||||
if (cairo_pattern_status (pattern))
|
||||
return pattern;
|
||||
|
||||
_cairo_pattern_set_error (pattern, status);
|
||||
|
||||
return pattern;
|
||||
}
|
||||
|
||||
/**
|
||||
* cairo_pattern_create_rgb:
|
||||
* @red: red component of the color
|
||||
|
@ -398,10 +378,10 @@ cairo_pattern_create_for_surface (cairo_surface_t *surface)
|
|||
cairo_surface_pattern_t *pattern;
|
||||
|
||||
if (surface == NULL)
|
||||
return (cairo_pattern_t*) _cairo_pattern_nil_for_status (CAIRO_STATUS_NULL_POINTER);
|
||||
return (cairo_pattern_t*) &cairo_pattern_nil_null_pointer;
|
||||
|
||||
if (surface->status)
|
||||
return (cairo_pattern_t*) _cairo_pattern_nil_for_status (surface->status);
|
||||
return (cairo_pattern_t*) _cairo_pattern_create_in_error (surface->status);
|
||||
|
||||
pattern = malloc (sizeof (cairo_surface_pattern_t));
|
||||
if (pattern == NULL) {
|
||||
|
@ -562,6 +542,7 @@ cairo_pattern_status (cairo_pattern_t *pattern)
|
|||
{
|
||||
return pattern->status;
|
||||
}
|
||||
slim_hidden_def (cairo_pattern_status);
|
||||
|
||||
/**
|
||||
* cairo_pattern_destroy:
|
||||
|
@ -1024,7 +1005,8 @@ _cairo_pattern_acquire_surface_for_gradient (cairo_gradient_pattern_t *pattern,
|
|||
|
||||
pixman_image_destroy (pixman_image);
|
||||
|
||||
status = _cairo_surface_clone_similar (dst, &image->base, out);
|
||||
status = _cairo_surface_clone_similar (dst, &image->base,
|
||||
0, 0, width, height, out);
|
||||
|
||||
cairo_surface_destroy (&image->base);
|
||||
|
||||
|
@ -1144,6 +1126,24 @@ _cairo_pattern_acquire_surface_for_surface (cairo_surface_pattern_t *pattern,
|
|||
|
||||
attr->acquired = FALSE;
|
||||
|
||||
attr->extend = pattern->base.extend;
|
||||
attr->filter = pattern->base.filter;
|
||||
if (_cairo_matrix_is_integer_translation (&pattern->base.matrix,
|
||||
&tx, &ty))
|
||||
{
|
||||
cairo_matrix_init_identity (&attr->matrix);
|
||||
attr->x_offset = tx;
|
||||
attr->y_offset = ty;
|
||||
attr->filter = CAIRO_FILTER_NEAREST;
|
||||
}
|
||||
else
|
||||
{
|
||||
attr->matrix = pattern->base.matrix;
|
||||
attr->x_offset = attr->y_offset = 0;
|
||||
tx = 0;
|
||||
ty = 0;
|
||||
}
|
||||
|
||||
if (_cairo_surface_is_image (dst))
|
||||
{
|
||||
cairo_image_surface_t *image;
|
||||
|
@ -1159,23 +1159,40 @@ _cairo_pattern_acquire_surface_for_surface (cairo_surface_pattern_t *pattern,
|
|||
}
|
||||
else
|
||||
{
|
||||
status = _cairo_surface_clone_similar (dst, pattern->surface, out);
|
||||
}
|
||||
/* 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);
|
||||
x = extents.x;
|
||||
y = extents.y;
|
||||
width = extents.width;
|
||||
height = extents.height;
|
||||
} else {
|
||||
/* Otherwise, we first transform the rectangle to the
|
||||
* coordinate space of the source surface so that we can
|
||||
* clone only that portion of the surface that will be
|
||||
* read. */
|
||||
if (! _cairo_matrix_is_identity (&attr->matrix)) {
|
||||
double x1 = x;
|
||||
double y1 = y;
|
||||
double x2 = x + width;
|
||||
double y2 = y + height;
|
||||
cairo_bool_t is_tight;
|
||||
|
||||
attr->extend = pattern->base.extend;
|
||||
attr->filter = pattern->base.filter;
|
||||
if (_cairo_matrix_is_integer_translation (&pattern->base.matrix,
|
||||
&tx, &ty))
|
||||
{
|
||||
cairo_matrix_init_identity (&attr->matrix);
|
||||
attr->x_offset = tx;
|
||||
attr->y_offset = ty;
|
||||
attr->filter = CAIRO_FILTER_NEAREST;
|
||||
}
|
||||
else
|
||||
{
|
||||
attr->matrix = pattern->base.matrix;
|
||||
attr->x_offset = attr->y_offset = 0;
|
||||
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;
|
||||
}
|
||||
x += tx;
|
||||
y += ty;
|
||||
}
|
||||
|
||||
status = _cairo_surface_clone_similar (dst, pattern->surface,
|
||||
x, y, width, height, out);
|
||||
}
|
||||
|
||||
return status;
|
||||
|
@ -1580,7 +1597,7 @@ cairo_pattern_get_color_stop_rgba (cairo_pattern_t *pattern,
|
|||
pattern->type != CAIRO_PATTERN_TYPE_RADIAL)
|
||||
return CAIRO_STATUS_PATTERN_TYPE_MISMATCH;
|
||||
|
||||
if (index < 0 || index >= gradient->n_stops)
|
||||
if (index < 0 || (unsigned int) index >= gradient->n_stops)
|
||||
return CAIRO_STATUS_INVALID_INDEX;
|
||||
|
||||
if (offset)
|
||||
|
|
|
@ -880,7 +880,7 @@ emit_surface_pattern (cairo_pdf_surface_t *surface,
|
|||
xstep = image->width;
|
||||
ystep = image->height;
|
||||
break;
|
||||
/* All the reset should have been analyzed away, so this case
|
||||
/* All the rest should have been analyzed away, so this case
|
||||
* should be unreachable. */
|
||||
case CAIRO_EXTEND_REFLECT:
|
||||
case CAIRO_EXTEND_PAD:
|
||||
|
@ -1473,11 +1473,13 @@ _cairo_pdf_surface_write_info (cairo_pdf_surface_t *surface)
|
|||
info = _cairo_pdf_surface_new_object (surface);
|
||||
_cairo_output_stream_printf (surface->output,
|
||||
"%d 0 obj\r\n"
|
||||
"<< /Creator (cairographics.org)\r\n"
|
||||
" /Producer (cairographics.org)\r\n"
|
||||
"<< /Creator (cairo %s (http://cairographics.org))\r\n"
|
||||
" /Producer (cairo %s (http://cairographics.org))\r\n"
|
||||
">>\r\n"
|
||||
"endobj\r\n",
|
||||
info.id);
|
||||
info.id,
|
||||
cairo_version_string (),
|
||||
cairo_version_string ());
|
||||
|
||||
return info;
|
||||
}
|
||||
|
@ -1577,6 +1579,109 @@ _cairo_pdf_surface_write_pages (cairo_pdf_surface_t *surface)
|
|||
"endobj\r\n");
|
||||
}
|
||||
|
||||
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_status_t status;
|
||||
cairo_pdf_font_t font;
|
||||
cairo_cff_subset_t subset;
|
||||
unsigned long compressed_length;
|
||||
char *compressed;
|
||||
unsigned int i;
|
||||
char name[64];
|
||||
|
||||
snprintf (name, sizeof name, "CairoFont-%d-%d",
|
||||
font_subset->font_id, font_subset->subset_id);
|
||||
status = _cairo_cff_subset_init (&subset, name, font_subset);
|
||||
if (status)
|
||||
return status;
|
||||
|
||||
compressed = compress_dup (subset.data, subset.data_length, &compressed_length);
|
||||
if (compressed == NULL) {
|
||||
_cairo_cff_subset_fini (&subset);
|
||||
return CAIRO_STATUS_NO_MEMORY;
|
||||
}
|
||||
|
||||
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"
|
||||
" /Subtype /Type1C\r\n"
|
||||
">>\r\n"
|
||||
"stream\r\n",
|
||||
stream.id,
|
||||
compressed_length);
|
||||
_cairo_output_stream_write (surface->output, compressed, compressed_length);
|
||||
_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 /%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"
|
||||
" /FontFile3 %u 0 R\r\n"
|
||||
">>\r\n"
|
||||
"endobj\r\n",
|
||||
descriptor.id,
|
||||
subset.base_font,
|
||||
subset.x_min,
|
||||
subset.y_min,
|
||||
subset.x_max,
|
||||
subset.y_max,
|
||||
subset.ascent,
|
||||
subset.descent,
|
||||
stream.id);
|
||||
|
||||
subset_resource = _cairo_pdf_surface_new_object (surface);
|
||||
_cairo_output_stream_printf (surface->output,
|
||||
"%d 0 obj\r\n"
|
||||
"<< /Type /Font\r\n"
|
||||
" /Subtype /Type1\r\n"
|
||||
" /BaseFont /%s\r\n"
|
||||
" /FirstChar 0\r\n"
|
||||
" /LastChar %d\r\n"
|
||||
" /FontDescriptor %d 0 R\r\n"
|
||||
" /Widths [",
|
||||
subset_resource.id,
|
||||
subset.base_font,
|
||||
font_subset->num_glyphs,
|
||||
descriptor.id);
|
||||
|
||||
for (i = 0; i < font_subset->num_glyphs; i++)
|
||||
_cairo_output_stream_printf (surface->output,
|
||||
" %d",
|
||||
subset.widths[i]);
|
||||
|
||||
_cairo_output_stream_printf (surface->output,
|
||||
" ]\r\n"
|
||||
">>\r\n"
|
||||
"endobj\r\n");
|
||||
|
||||
font.font_id = font_subset->font_id;
|
||||
font.subset_id = font_subset->subset_id;
|
||||
font.subset_resource = subset_resource;
|
||||
_cairo_array_append (&surface->fonts, &font);
|
||||
|
||||
_cairo_cff_subset_fini (&subset);
|
||||
|
||||
return CAIRO_STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
static cairo_status_t
|
||||
_cairo_pdf_surface_emit_type1_font (cairo_pdf_surface_t *surface,
|
||||
cairo_scaled_font_subset_t *font_subset,
|
||||
|
@ -1707,7 +1812,7 @@ _cairo_pdf_surface_emit_type1_fallback_font (cairo_pdf_surface_t *surface,
|
|||
|
||||
snprintf (name, sizeof name, "CairoFont-%d-%d",
|
||||
font_subset->font_id, font_subset->subset_id);
|
||||
status = _cairo_type1_fallback_init (&subset, name, font_subset);
|
||||
status = _cairo_type1_fallback_init_binary (&subset, name, font_subset);
|
||||
if (status)
|
||||
return status;
|
||||
|
||||
|
@ -2057,6 +2162,10 @@ _cairo_pdf_surface_emit_font_subset (cairo_scaled_font_subset_t *font_subset,
|
|||
cairo_pdf_surface_t *surface = closure;
|
||||
cairo_status_t status;
|
||||
|
||||
status = _cairo_pdf_surface_emit_cff_font_subset (surface, font_subset);
|
||||
if (status != CAIRO_INT_STATUS_UNSUPPORTED)
|
||||
return;
|
||||
|
||||
#if CAIRO_HAS_FT_FONT
|
||||
status = _cairo_pdf_surface_emit_type1_font_subset (surface, font_subset);
|
||||
if (status != CAIRO_INT_STATUS_UNSUPPORTED)
|
||||
|
@ -2537,6 +2646,11 @@ _cairo_pdf_surface_stroke (void *abstract_surface,
|
|||
info.output = surface->output;
|
||||
info.ctm_inverse = ctm_inverse;
|
||||
|
||||
_cairo_output_stream_printf (surface->output,
|
||||
"q %f %f %f %f %f %f cm\r\n",
|
||||
ctm->xx, ctm->yx, ctm->xy, ctm->yy,
|
||||
ctm->x0, ctm->y0);
|
||||
|
||||
status = _cairo_path_fixed_interpret (path,
|
||||
CAIRO_DIRECTION_FORWARD,
|
||||
_cairo_pdf_path_move_to,
|
||||
|
@ -2545,11 +2659,6 @@ _cairo_pdf_surface_stroke (void *abstract_surface,
|
|||
_cairo_pdf_path_close_path,
|
||||
&info);
|
||||
|
||||
_cairo_output_stream_printf (surface->output,
|
||||
"q %f %f %f %f %f %f cm\r\n",
|
||||
ctm->xx, ctm->yx, ctm->xy, ctm->yy,
|
||||
ctm->x0, ctm->y0);
|
||||
|
||||
_cairo_output_stream_printf (surface->output, "S Q\r\n");
|
||||
|
||||
return status;
|
||||
|
@ -2611,7 +2720,7 @@ static cairo_int_status_t
|
|||
_cairo_pdf_surface_show_glyphs (void *abstract_surface,
|
||||
cairo_operator_t op,
|
||||
cairo_pattern_t *source,
|
||||
const cairo_glyph_t *glyphs,
|
||||
cairo_glyph_t *glyphs,
|
||||
int num_glyphs,
|
||||
cairo_scaled_font_t *scaled_font)
|
||||
{
|
||||
|
|
|
@ -270,7 +270,12 @@ _cairo_pen_vertices_needed (double tolerance,
|
|||
/* number of vertices must be even */
|
||||
if (num_vertices % 2)
|
||||
num_vertices++;
|
||||
|
||||
/* And we must always have at least 4 vertices. */
|
||||
if (num_vertices < 4)
|
||||
num_vertices = 4;
|
||||
}
|
||||
|
||||
return num_vertices;
|
||||
}
|
||||
|
||||
|
@ -315,6 +320,8 @@ _cairo_pen_find_active_cw_vertex_index (cairo_pen_t *pen,
|
|||
break;
|
||||
}
|
||||
|
||||
assert (i < pen->num_vertices);
|
||||
|
||||
*active = i;
|
||||
|
||||
return CAIRO_STATUS_SUCCESS;
|
||||
|
@ -441,7 +448,7 @@ _cairo_pen_stroke_spline (cairo_pen_t *pen,
|
|||
return status;
|
||||
|
||||
_cairo_polygon_close (&polygon);
|
||||
_cairo_traps_tessellate_polygon (traps, &polygon, CAIRO_FILL_RULE_WINDING);
|
||||
_cairo_bentley_ottmann_tessellate_polygon (traps, &polygon, CAIRO_FILL_RULE_WINDING);
|
||||
_cairo_polygon_fini (&polygon);
|
||||
|
||||
return CAIRO_STATUS_SUCCESS;
|
||||
|
|
|
@ -82,4 +82,8 @@
|
|||
#include "cairo-rename.h"
|
||||
#endif
|
||||
|
||||
#ifdef IS_BIG_ENDIAN
|
||||
#define FLOAT_WORDS_BIGENDIAN
|
||||
#endif
|
||||
|
||||
#endif /* CAIRO_PLATFORM_H */
|
||||
|
|
|
@ -289,7 +289,7 @@ cairo_surface_write_to_png_stream (cairo_surface_t *surface,
|
|||
}
|
||||
slim_hidden_def (cairo_surface_write_to_png_stream);
|
||||
|
||||
static INLINE int
|
||||
static inline int
|
||||
multiply_alpha (int alpha, int color)
|
||||
{
|
||||
int temp = (alpha * color) + 0x80;
|
||||
|
|
|
@ -331,10 +331,11 @@ _cairo_ps_surface_emit_header (cairo_ps_surface_t *surface)
|
|||
|
||||
_cairo_output_stream_printf (surface->final_stream,
|
||||
"%%!PS-Adobe-3.0\n"
|
||||
"%%%%Creator: cairo (http://cairographics.org)\n"
|
||||
"%%%%Creator: cairo %s (http://cairographics.org)\n"
|
||||
"%%%%CreationDate: %s"
|
||||
"%%%%Pages: %d\n"
|
||||
"%%%%BoundingBox: %d %d %d %d\n",
|
||||
cairo_version_string (),
|
||||
ctime (&now),
|
||||
surface->num_pages,
|
||||
0, 0,
|
||||
|
@ -367,6 +368,9 @@ _cairo_ps_surface_emit_header (cairo_ps_surface_t *surface)
|
|||
"/P{closepath}bind def\n"
|
||||
"/R{setrgbcolor}bind def\n"
|
||||
"/S{show}bind def\n"
|
||||
"/xS{xshow}bind def\n"
|
||||
"/yS{yshow}bind def\n"
|
||||
"/xyS{xyshow}bind def\n"
|
||||
"%%%%EndProlog\n");
|
||||
|
||||
num_comments = _cairo_array_num_elements (&surface->dsc_setup_comments);
|
||||
|
@ -430,14 +434,14 @@ _cairo_ps_surface_emit_type1_font_fallback (cairo_ps_surface_t *surface,
|
|||
|
||||
snprintf (name, sizeof name, "CairoFont-%d-%d",
|
||||
font_subset->font_id, font_subset->subset_id);
|
||||
status = _cairo_type1_fallback_init (&subset, name, font_subset);
|
||||
status = _cairo_type1_fallback_init_hex (&subset, name, font_subset);
|
||||
if (status)
|
||||
return status;
|
||||
|
||||
/* FIXME: Figure out document structure convention for fonts */
|
||||
|
||||
_cairo_output_stream_printf (surface->final_stream,
|
||||
"%% _cairo_ps_surface_emit_type1_font_subset\n");
|
||||
"%% _cairo_ps_surface_emit_type1_font_fallback\n");
|
||||
|
||||
length = subset.header_length + subset.data_length + subset.trailer_length;
|
||||
_cairo_output_stream_write (surface->final_stream, subset.data, length);
|
||||
|
@ -1666,55 +1670,84 @@ emit_solid_pattern (cairo_ps_surface_t *surface,
|
|||
|
||||
static void
|
||||
emit_surface_pattern (cairo_ps_surface_t *surface,
|
||||
cairo_surface_pattern_t *pattern,
|
||||
double x, double y)
|
||||
cairo_surface_pattern_t *pattern)
|
||||
{
|
||||
cairo_rectangle_int16_t extents;
|
||||
double bbox_width, bbox_height;
|
||||
int xstep, ystep;
|
||||
cairo_matrix_t inverse = pattern->base.matrix;
|
||||
cairo_matrix_invert (&inverse);
|
||||
|
||||
if (_cairo_surface_is_meta (pattern->surface)) {
|
||||
_cairo_output_stream_printf (surface->stream, "/MyPattern {\n");
|
||||
_cairo_meta_surface_replay (pattern->surface, &surface->base);
|
||||
extents.width = surface->width;
|
||||
extents.height = surface->height;
|
||||
bbox_width = surface->width;
|
||||
bbox_height = surface->height;
|
||||
xstep = surface->width;
|
||||
ystep = surface->height;
|
||||
_cairo_output_stream_printf (surface->stream, "} bind def\n");
|
||||
} else {
|
||||
cairo_image_surface_t *image;
|
||||
void *image_extra;
|
||||
cairo_status_t status;
|
||||
cairo_matrix_t inverse = pattern->base.matrix;
|
||||
|
||||
cairo_matrix_invert (&inverse);
|
||||
|
||||
status = _cairo_surface_acquire_source_image (pattern->surface,
|
||||
&image,
|
||||
&image_extra);
|
||||
assert (status == CAIRO_STATUS_SUCCESS);
|
||||
|
||||
_cairo_pattern_get_extents (&pattern->base, &extents);
|
||||
|
||||
emit_image (surface, image, &pattern->base.matrix, "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) {
|
||||
case CAIRO_EXTEND_NONE:
|
||||
xstep = MAX (image->width, surface->width);
|
||||
ystep = MAX (image->height, surface->height);
|
||||
break;
|
||||
case CAIRO_EXTEND_REPEAT:
|
||||
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:
|
||||
default:
|
||||
ASSERT_NOT_REACHED;
|
||||
xstep = 0;
|
||||
ystep = 0;
|
||||
}
|
||||
|
||||
_cairo_surface_release_source_image (pattern->surface, image,
|
||||
image_extra);
|
||||
}
|
||||
_cairo_output_stream_printf (surface->stream,
|
||||
"%f %f translate\n",
|
||||
x, y);
|
||||
_cairo_output_stream_printf (surface->stream,
|
||||
"<< /PatternType 1\n"
|
||||
" /PaintType 1\n"
|
||||
" /TilingType 1\n");
|
||||
_cairo_output_stream_printf (surface->stream,
|
||||
" /BBox [0 0 %d %d]\n",
|
||||
extents.width, extents.height);
|
||||
(int) bbox_width, (int) bbox_height);
|
||||
_cairo_output_stream_printf (surface->stream,
|
||||
" /XStep %d /YStep %d\n",
|
||||
extents.width, extents.height);
|
||||
xstep, ystep);
|
||||
_cairo_output_stream_printf (surface->stream,
|
||||
" /PaintProc { MyPattern } bind\n"
|
||||
">> matrix makepattern setpattern\n");
|
||||
">>\n");
|
||||
_cairo_output_stream_printf (surface->stream,
|
||||
"-%f -%f translate\n",
|
||||
x, y);
|
||||
"[ 1 0 0 1 %f %f ]\n",
|
||||
inverse.x0, inverse.y0);
|
||||
_cairo_output_stream_printf (surface->stream,
|
||||
"makepattern setpattern\n");
|
||||
}
|
||||
|
||||
static void
|
||||
|
@ -1732,8 +1765,7 @@ emit_radial_pattern (cairo_ps_surface_t *surface,
|
|||
}
|
||||
|
||||
static void
|
||||
emit_pattern (cairo_ps_surface_t *surface, cairo_pattern_t *pattern,
|
||||
double x, double y)
|
||||
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
|
||||
|
@ -1745,7 +1777,7 @@ emit_pattern (cairo_ps_surface_t *surface, cairo_pattern_t *pattern,
|
|||
break;
|
||||
|
||||
case CAIRO_PATTERN_TYPE_SURFACE:
|
||||
emit_surface_pattern (surface, (cairo_surface_pattern_t *) pattern, x, y);
|
||||
emit_surface_pattern (surface, (cairo_surface_pattern_t *) pattern);
|
||||
break;
|
||||
|
||||
case CAIRO_PATTERN_TYPE_LINEAR:
|
||||
|
@ -1840,7 +1872,7 @@ _cairo_ps_surface_paint (void *abstract_surface,
|
|||
{
|
||||
cairo_ps_surface_t *surface = abstract_surface;
|
||||
cairo_output_stream_t *stream = surface->stream;
|
||||
cairo_rectangle_int16_t extents;
|
||||
cairo_rectangle_int16_t extents, pattern_extents;
|
||||
|
||||
if (surface->paginated_mode == CAIRO_PAGINATED_MODE_ANALYZE)
|
||||
return _analyze_operation (surface, op, source);
|
||||
|
@ -1858,9 +1890,11 @@ _cairo_ps_surface_paint (void *abstract_surface,
|
|||
_cairo_output_stream_printf (stream,
|
||||
"%% _cairo_ps_surface_paint\n");
|
||||
|
||||
_cairo_pattern_get_extents (source, &extents);
|
||||
_cairo_surface_get_extents (&surface->base, &extents);
|
||||
_cairo_pattern_get_extents (source, &pattern_extents);
|
||||
_cairo_rectangle_intersect (&extents, &pattern_extents);
|
||||
|
||||
emit_pattern (surface, source, extents.x, extents.y);
|
||||
emit_pattern (surface, source);
|
||||
|
||||
_cairo_output_stream_printf (stream, "%d %d M\n",
|
||||
extents.x, extents.y);
|
||||
|
@ -1999,7 +2033,7 @@ _cairo_ps_surface_stroke (void *abstract_surface,
|
|||
}
|
||||
}
|
||||
|
||||
emit_pattern (surface, source, 0, 0);
|
||||
emit_pattern (surface, source);
|
||||
|
||||
_cairo_output_stream_printf (stream,
|
||||
"gsave\n");
|
||||
|
@ -2066,7 +2100,7 @@ _cairo_ps_surface_fill (void *abstract_surface,
|
|||
_cairo_output_stream_printf (stream,
|
||||
"%% _cairo_ps_surface_fill\n");
|
||||
|
||||
emit_pattern (surface, source, 0, 0);
|
||||
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,
|
||||
|
@ -2089,20 +2123,32 @@ _cairo_ps_surface_fill (void *abstract_surface,
|
|||
return status;
|
||||
}
|
||||
|
||||
/* This size keeps the length of the hex encoded string of glyphs
|
||||
* within 80 columns. */
|
||||
#define MAX_GLYPHS_PER_SHOW 36
|
||||
|
||||
typedef struct _cairo_ps_glyph_id {
|
||||
unsigned int subset_id;
|
||||
unsigned int glyph_id;
|
||||
} cairo_ps_glyph_id_t;
|
||||
|
||||
static cairo_int_status_t
|
||||
_cairo_ps_surface_show_glyphs (void *abstract_surface,
|
||||
cairo_operator_t op,
|
||||
cairo_pattern_t *source,
|
||||
const cairo_glyph_t *glyphs,
|
||||
cairo_glyph_t *glyphs,
|
||||
int num_glyphs,
|
||||
cairo_scaled_font_t *scaled_font)
|
||||
{
|
||||
cairo_ps_surface_t *surface = abstract_surface;
|
||||
cairo_output_stream_t *stream = surface->stream;
|
||||
unsigned int current_subset_id = -1;
|
||||
unsigned int font_id, subset_id, subset_glyph_index;
|
||||
unsigned int font_id;
|
||||
cairo_ps_glyph_id_t *glyph_ids;
|
||||
cairo_status_t status;
|
||||
int i;
|
||||
unsigned int num_glyphs_unsigned, i, j, last, end;
|
||||
cairo_bool_t vertical, horizontal;
|
||||
cairo_output_stream_t *word_wrap;
|
||||
|
||||
if (surface->paginated_mode == CAIRO_PAGINATED_MODE_ANALYZE)
|
||||
return _analyze_operation (surface, op, source);
|
||||
|
@ -2112,37 +2158,117 @@ _cairo_ps_surface_show_glyphs (void *abstract_surface,
|
|||
_cairo_output_stream_printf (stream,
|
||||
"%% _cairo_ps_surface_show_glyphs\n");
|
||||
|
||||
if (num_glyphs)
|
||||
emit_pattern (surface, source, 0, 0);
|
||||
if (num_glyphs <= 0)
|
||||
return CAIRO_STATUS_SUCCESS;
|
||||
|
||||
for (i = 0; i < num_glyphs; i++) {
|
||||
status = _cairo_scaled_font_subsets_map_glyph (surface->font_subsets,
|
||||
scaled_font, glyphs[i].index,
|
||||
&font_id, &subset_id, &subset_glyph_index);
|
||||
if (status)
|
||||
return status;
|
||||
num_glyphs_unsigned = num_glyphs;
|
||||
|
||||
if (subset_id != current_subset_id) {
|
||||
_cairo_output_stream_printf (surface->stream,
|
||||
"/CairoFont-%d-%d findfont\n"
|
||||
"[ %f %f %f %f 0 0 ] makefont\n"
|
||||
"setfont\n",
|
||||
font_id,
|
||||
subset_id,
|
||||
scaled_font->scale.xx,
|
||||
scaled_font->scale.yx,
|
||||
-scaled_font->scale.xy,
|
||||
-scaled_font->scale.yy);
|
||||
current_subset_id = subset_id;
|
||||
}
|
||||
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;
|
||||
|
||||
_cairo_output_stream_printf (surface->stream,
|
||||
"%f %f M <%02x> S\n",
|
||||
glyphs[i].x, glyphs[i].y,
|
||||
subset_glyph_index);
|
||||
for (i = 0; i < num_glyphs_unsigned; i++) {
|
||||
status = _cairo_scaled_font_subsets_map_glyph (surface->font_subsets,
|
||||
scaled_font, glyphs[i].index,
|
||||
&font_id,
|
||||
&(glyph_ids[i].subset_id),
|
||||
&(glyph_ids[i].glyph_id));
|
||||
if (status)
|
||||
goto fail;
|
||||
}
|
||||
|
||||
return _cairo_output_stream_get_status (surface->stream);
|
||||
i = 0;
|
||||
while (i < num_glyphs_unsigned) {
|
||||
if (glyph_ids[i].subset_id != current_subset_id) {
|
||||
_cairo_output_stream_printf (surface->stream,
|
||||
"/CairoFont-%d-%d findfont\n"
|
||||
"[ %f %f %f %f 0 0 ] makefont\n"
|
||||
"setfont\n",
|
||||
font_id,
|
||||
glyph_ids[i].subset_id,
|
||||
scaled_font->scale.xx,
|
||||
scaled_font->scale.yx,
|
||||
-scaled_font->scale.xy,
|
||||
-scaled_font->scale.yy);
|
||||
current_subset_id = glyph_ids[i].subset_id;
|
||||
}
|
||||
|
||||
if (i == 0)
|
||||
_cairo_output_stream_printf (stream,
|
||||
"%f %f M\n",
|
||||
glyphs[i].x,
|
||||
glyphs[i].y);
|
||||
|
||||
horizontal = TRUE;
|
||||
vertical = TRUE;
|
||||
end = num_glyphs_unsigned;
|
||||
if (end - i > MAX_GLYPHS_PER_SHOW)
|
||||
end = i + MAX_GLYPHS_PER_SHOW;
|
||||
last = end - 1;
|
||||
for (j = i; j < end - 1; j++) {
|
||||
if ((glyphs[j].y != glyphs[j + 1].y))
|
||||
horizontal = FALSE;
|
||||
if ((glyphs[j].x != glyphs[j + 1].x))
|
||||
vertical = FALSE;
|
||||
if (glyph_ids[j].subset_id != glyph_ids[j + 1].subset_id) {
|
||||
last = j;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (i == last) {
|
||||
_cairo_output_stream_printf (surface->stream, "<%02x> S\n", glyph_ids[i].glyph_id);
|
||||
} else {
|
||||
word_wrap = _word_wrap_stream_create (surface->stream, 79);
|
||||
_cairo_output_stream_printf (word_wrap, "<");
|
||||
for (j = i; j < last+1; j++)
|
||||
_cairo_output_stream_printf (word_wrap, "%02x", glyph_ids[j].glyph_id);
|
||||
_cairo_output_stream_printf (word_wrap, ">\n[");
|
||||
|
||||
if (horizontal) {
|
||||
for (j = i; j < last+1; j++) {
|
||||
if (j == num_glyphs_unsigned - 1)
|
||||
_cairo_output_stream_printf (word_wrap, "0 ");
|
||||
else
|
||||
_cairo_output_stream_printf (word_wrap,
|
||||
"%f ", glyphs[j + 1].x - glyphs[j].x);
|
||||
}
|
||||
_cairo_output_stream_printf (word_wrap, "] xS\n");
|
||||
} else if (vertical) {
|
||||
for (j = i; j < last+1; j++) {
|
||||
if (j == num_glyphs_unsigned - 1)
|
||||
_cairo_output_stream_printf (word_wrap, "0 ");
|
||||
else
|
||||
_cairo_output_stream_printf (word_wrap,
|
||||
"%f ", glyphs[j + 1].y - glyphs[j].y);
|
||||
}
|
||||
_cairo_output_stream_printf (word_wrap, "] yS\n");
|
||||
} else {
|
||||
for (j = i; j < last+1; j++) {
|
||||
if (j == num_glyphs_unsigned - 1)
|
||||
_cairo_output_stream_printf (word_wrap, "0 ");
|
||||
else
|
||||
_cairo_output_stream_printf (word_wrap,
|
||||
"%f %f ",
|
||||
glyphs[j + 1].x - glyphs[j].x,
|
||||
glyphs[j + 1].y - glyphs[j].y);
|
||||
}
|
||||
_cairo_output_stream_printf (word_wrap, "] xyS\n");
|
||||
}
|
||||
|
||||
status = _cairo_output_stream_destroy (word_wrap);
|
||||
if (status)
|
||||
goto fail;
|
||||
}
|
||||
i = last + 1;
|
||||
}
|
||||
|
||||
status = _cairo_output_stream_get_status (surface->stream);
|
||||
fail:
|
||||
free (glyph_ids);
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
static void
|
||||
|
|
|
@ -55,11 +55,9 @@ _cairo_quartz_surface_acquire_source_image(void *abstract_surface,
|
|||
{
|
||||
cairo_quartz_surface_t *surface = abstract_surface;
|
||||
|
||||
#if 0
|
||||
if (CGBitmapContextGetBitmapInfo (surface->context) != 0) {
|
||||
/* XXX: We can create an image out of the bitmap here */
|
||||
}
|
||||
#endif
|
||||
|
||||
return CAIRO_INT_STATUS_UNSUPPORTED;
|
||||
}
|
||||
|
@ -249,19 +247,11 @@ cairo_surface_t *cairo_quartz_surface_create(CGContextRef context,
|
|||
surface->clip_region = NULL;
|
||||
surface->y_grows_down = y_grows_down;
|
||||
|
||||
#if 0
|
||||
/* 10.3 or later */
|
||||
clip_box = CGContextGetClipBoundingBox (context);
|
||||
surface->extents.x = clip_box.origin.x;
|
||||
surface->extents.y = clip_box.origin.y;
|
||||
surface->extents.width = clip_box.size.width;
|
||||
surface->extents.height = clip_box.size.height;
|
||||
#else
|
||||
surface->extents.x = 0;
|
||||
surface->extents.y = 0;
|
||||
surface->extents.width = width;
|
||||
surface->extents.height = height;
|
||||
#endif
|
||||
|
||||
return (cairo_surface_t *) surface;
|
||||
}
|
||||
|
|
|
@ -105,6 +105,7 @@
|
|||
#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
|
||||
|
@ -154,8 +155,6 @@
|
|||
#define cairo_pdf_surface_set_size _moz_cairo_pdf_surface_set_size
|
||||
#define cairo_pop_group _moz_cairo_pop_group
|
||||
#define cairo_pop_group_to_source _moz_cairo_pop_group_to_source
|
||||
#define cairo_profile_surface_create _moz_cairo_profile_surface_create
|
||||
#define cairo_profile_surface_get_profile_data _moz_cairo_profile_surface_get_profile_data
|
||||
#define cairo_ps_surface_create _moz_cairo_ps_surface_create
|
||||
#define cairo_ps_surface_create_for_stream _moz_cairo_ps_surface_create_for_stream
|
||||
#define cairo_ps_surface_dsc_begin_page_setup _moz_cairo_ps_surface_dsc_begin_page_setup
|
||||
|
@ -227,7 +226,6 @@
|
|||
#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_is_profile _moz_cairo_surface_is_profile
|
||||
#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
|
||||
|
|
|
@ -179,6 +179,46 @@ _cairo_scaled_font_subsets_foreach (cairo_scaled_font_subsets_t *font_subsets,
|
|||
cairo_scaled_font_subset_callback_func_t font_subset_callback,
|
||||
void *closure);
|
||||
|
||||
typedef struct _cairo_cff_subset {
|
||||
char *base_font;
|
||||
int *widths;
|
||||
long x_min, y_min, x_max, y_max;
|
||||
long ascent, descent;
|
||||
char *data;
|
||||
unsigned long data_length;
|
||||
} cairo_cff_subset_t;
|
||||
|
||||
/**
|
||||
* _cairo_cff_subset_init:
|
||||
* @cff_subset: a #cairo_cff_subset_t to initialize
|
||||
* @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) generate a
|
||||
* cff file corresponding to @font_subset and initialize
|
||||
* @cff_subset with information about the subset and the cff
|
||||
* data.
|
||||
*
|
||||
* Return value: CAIRO_STATUS_SUCCESS if successful,
|
||||
* CAIRO_INT_STATUS_UNSUPPORTED if the font can't be subset as a
|
||||
* cff file, or an non-zero value indicating an error. Possible
|
||||
* errors include CAIRO_STATUS_NO_MEMORY.
|
||||
**/
|
||||
cairo_private cairo_status_t
|
||||
_cairo_cff_subset_init (cairo_cff_subset_t *cff_subset,
|
||||
const char *name,
|
||||
cairo_scaled_font_subset_t *font_subset);
|
||||
|
||||
/**
|
||||
* _cairo_cff_subset_fini:
|
||||
* @cff_subset: a #cairo_cff_subset_t
|
||||
*
|
||||
* Free all resources associated with @cff_subset. After this
|
||||
* call, @cff_subset should not be used again without a
|
||||
* subsequent call to _cairo_cff_subset_init() again first.
|
||||
**/
|
||||
cairo_private void
|
||||
_cairo_cff_subset_fini (cairo_cff_subset_t *cff_subset);
|
||||
|
||||
typedef struct _cairo_truetype_subset {
|
||||
char *base_font;
|
||||
|
@ -269,14 +309,15 @@ cairo_private void
|
|||
_cairo_type1_subset_fini (cairo_type1_subset_t *subset);
|
||||
|
||||
/**
|
||||
* _cairo_type1_fallback_init:
|
||||
* _cairo_type1_fallback_init_binary:
|
||||
* @type1_subset: a #cairo_type1_subset_t to initialize
|
||||
* @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) generate a type1
|
||||
* file corresponding to @font_subset and initialize @type1_subset
|
||||
* with information about the subset and the type1 data.
|
||||
* with information about the subset and the type1 data. The encrypted
|
||||
* part of the font is binary encoded.
|
||||
*
|
||||
* Return value: CAIRO_STATUS_SUCCESS if successful,
|
||||
* CAIRO_INT_STATUS_UNSUPPORTED if the font can't be subset as a type1
|
||||
|
@ -284,9 +325,30 @@ _cairo_type1_subset_fini (cairo_type1_subset_t *subset);
|
|||
* include CAIRO_STATUS_NO_MEMORY.
|
||||
**/
|
||||
cairo_private cairo_status_t
|
||||
_cairo_type1_fallback_init (cairo_type1_subset_t *type_subset,
|
||||
const char *name,
|
||||
cairo_scaled_font_subset_t *font_subset);
|
||||
_cairo_type1_fallback_init_binary (cairo_type1_subset_t *type_subset,
|
||||
const char *name,
|
||||
cairo_scaled_font_subset_t *font_subset);
|
||||
|
||||
/**
|
||||
* _cairo_type1_fallback_init_hexencode:
|
||||
* @type1_subset: a #cairo_type1_subset_t to initialize
|
||||
* @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) generate a type1
|
||||
* file corresponding to @font_subset and initialize @type1_subset
|
||||
* with information about the subset and the type1 data. The encrypted
|
||||
* part of the font is hex encoded.
|
||||
*
|
||||
* Return value: CAIRO_STATUS_SUCCESS if successful,
|
||||
* CAIRO_INT_STATUS_UNSUPPORTED if the font can't be subset as a type1
|
||||
* file, or an non-zero value indicating an error. Possible errors
|
||||
* include CAIRO_STATUS_NO_MEMORY.
|
||||
**/
|
||||
cairo_private cairo_status_t
|
||||
_cairo_type1_fallback_init_hex (cairo_type1_subset_t *type_subset,
|
||||
const char *name,
|
||||
cairo_scaled_font_subset_t *font_subset);
|
||||
|
||||
/**
|
||||
* _cairo_type1_fallback_fini:
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
/* $Id: cairo-scaled-font.c,v 1.11 2006/09/26 22:21:55 vladimir%pobox.com Exp $
|
||||
/* $Id: cairo-scaled-font.c,v 1.12 2006/12/23 01:15:53 vladimir%pobox.com Exp $
|
||||
*
|
||||
* Copyright © 2005 Keith Packard
|
||||
*
|
||||
|
@ -698,7 +698,7 @@ cairo_scaled_font_text_extents (cairo_scaled_font_t *scaled_font,
|
|||
**/
|
||||
void
|
||||
cairo_scaled_font_glyph_extents (cairo_scaled_font_t *scaled_font,
|
||||
cairo_glyph_t *glyphs,
|
||||
const cairo_glyph_t *glyphs,
|
||||
int num_glyphs,
|
||||
cairo_text_extents_t *extents)
|
||||
{
|
||||
|
@ -834,7 +834,7 @@ _cairo_scaled_font_glyph_device_extents (cairo_scaled_font_t *scaled_font,
|
|||
cairo_status_t status = CAIRO_STATUS_SUCCESS;
|
||||
int i;
|
||||
int min_x = INT16_MAX, max_x = INT16_MIN;
|
||||
int min_y = INT16_MAX, max_y = INT16_MAX;
|
||||
int min_y = INT16_MAX, max_y = INT16_MIN;
|
||||
|
||||
if (scaled_font->status)
|
||||
return scaled_font->status;
|
||||
|
@ -855,8 +855,8 @@ _cairo_scaled_font_glyph_device_extents (cairo_scaled_font_t *scaled_font,
|
|||
}
|
||||
|
||||
/* glyph images are snapped to pixel locations */
|
||||
x = (int) floor (glyphs[i].x + 0.5);
|
||||
y = (int) floor (glyphs[i].y + 0.5);
|
||||
x = _cairo_lround (glyphs[i].x);
|
||||
y = _cairo_lround (glyphs[i].y);
|
||||
|
||||
left = x + _cairo_fixed_integer_floor(scaled_glyph->bbox.p1.x);
|
||||
top = y + _cairo_fixed_integer_floor (scaled_glyph->bbox.p1.y);
|
||||
|
@ -891,7 +891,7 @@ _cairo_scaled_font_show_glyphs (cairo_scaled_font_t *scaled_font,
|
|||
int dest_y,
|
||||
unsigned int width,
|
||||
unsigned int height,
|
||||
const cairo_glyph_t *glyphs,
|
||||
cairo_glyph_t *glyphs,
|
||||
int num_glyphs)
|
||||
{
|
||||
cairo_status_t status;
|
||||
|
@ -964,12 +964,10 @@ _cairo_scaled_font_show_glyphs (cairo_scaled_font_t *scaled_font,
|
|||
|
||||
/* round glyph locations to the nearest pixel */
|
||||
/* XXX: FRAGILE: We're ignoring device_transform scaling here. A bug? */
|
||||
x = (int) floor (glyphs[i].x +
|
||||
glyph_surface->base.device_transform.x0 +
|
||||
0.5);
|
||||
y = (int) floor (glyphs[i].y +
|
||||
glyph_surface->base.device_transform.y0 +
|
||||
0.5);
|
||||
x = _cairo_lround (glyphs[i].x +
|
||||
glyph_surface->base.device_transform.x0);
|
||||
y = _cairo_lround (glyphs[i].y +
|
||||
glyph_surface->base.device_transform.y0);
|
||||
|
||||
_cairo_pattern_init_for_surface (&glyph_pattern, &glyph_surface->base);
|
||||
|
||||
|
@ -1213,6 +1211,7 @@ _cairo_scaled_glyph_set_metrics (cairo_scaled_glyph_t *scaled_glyph,
|
|||
double hm, wm;
|
||||
double min_user_x = 0.0, max_user_x = 0.0, min_user_y = 0.0, max_user_y = 0.0;
|
||||
double min_device_x = 0.0, max_device_x = 0.0, min_device_y = 0.0, max_device_y = 0.0;
|
||||
double device_x_advance, device_y_advance;
|
||||
|
||||
for (hm = 0.0; hm <= 1.0; hm += 1.0)
|
||||
for (wm = 0.0; wm <= 1.0; wm += 1.0) {
|
||||
|
@ -1261,10 +1260,19 @@ _cairo_scaled_glyph_set_metrics (cairo_scaled_glyph_t *scaled_glyph,
|
|||
&scaled_glyph->metrics.x_advance,
|
||||
&scaled_glyph->metrics.y_advance);
|
||||
|
||||
device_x_advance = fs_metrics->x_advance;
|
||||
device_y_advance = fs_metrics->y_advance;
|
||||
cairo_matrix_transform_distance (&scaled_font->scale,
|
||||
&device_x_advance,
|
||||
&device_y_advance);
|
||||
|
||||
scaled_glyph->bbox.p1.x = _cairo_fixed_from_double (min_device_x);
|
||||
scaled_glyph->bbox.p1.y = _cairo_fixed_from_double (min_device_y);
|
||||
scaled_glyph->bbox.p2.x = _cairo_fixed_from_double (max_device_x);
|
||||
scaled_glyph->bbox.p2.y = _cairo_fixed_from_double (max_device_y);
|
||||
|
||||
scaled_glyph->x_advance = _cairo_lround (device_x_advance);
|
||||
scaled_glyph->y_advance = _cairo_lround (device_y_advance);
|
||||
}
|
||||
|
||||
void
|
||||
|
|
|
@ -0,0 +1,99 @@
|
|||
/*
|
||||
* Copyright © 2006 Keith Packard
|
||||
* Copyright © 2006 Carl Worth
|
||||
*
|
||||
* 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 the copyright holders not be used in advertising or
|
||||
* publicity pertaining to distribution of the software without specific,
|
||||
* written prior permission. The copyright holders make no representations
|
||||
* about the suitability of this software for any purpose. It is provided "as
|
||||
* is" without express or implied warranty.
|
||||
*
|
||||
* THE COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
|
||||
* INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
|
||||
* EVENT SHALL THE COPYRIGHT HOLDERS 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.
|
||||
*/
|
||||
|
||||
#ifndef SKIPLIST_H
|
||||
#define SKIPLIST_H
|
||||
|
||||
#include "cairoint.h"
|
||||
|
||||
#define MAX_LEVEL 31
|
||||
|
||||
/*
|
||||
* Skip list element. In order to use the skip list, the caller must
|
||||
* generate a structure for list elements that has as its final member
|
||||
* 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.
|
||||
*/
|
||||
typedef struct _skip_elt {
|
||||
int prev_index;
|
||||
struct _skip_elt *prev;
|
||||
struct _skip_elt *next[1];
|
||||
} skip_elt_t;
|
||||
|
||||
#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);
|
||||
|
||||
typedef struct _skip_list {
|
||||
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;
|
||||
|
||||
/* Initialize a new skip list. The compare function accepts a pointer
|
||||
* to the list as well as pointers to two elements. The function must
|
||||
* return a value greater than zero, zero, or less then 0 if the first
|
||||
* element is considered respectively greater than, equal to, or less
|
||||
* than the second element. The size of each object, (as computed by
|
||||
* sizeof) is passed for elt_size. Note that the structure used for
|
||||
* 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,
|
||||
size_t elt_size);
|
||||
|
||||
|
||||
/* Deallocate resources associated with a skip list and all elements
|
||||
* in it. (XXX: currently this simply deletes all elements.)
|
||||
*/
|
||||
cairo_private void
|
||||
skip_list_fini (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
|
||||
* are ignored and the already inserted element is returned.
|
||||
* 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);
|
||||
|
||||
/* Find an element which compare considers equal to <data> */
|
||||
cairo_private void *
|
||||
skip_list_find (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);
|
||||
|
||||
/* Delete the given element from the list. */
|
||||
cairo_private void
|
||||
skip_list_delete_given (skip_list_t *list, skip_elt_t *given);
|
||||
|
||||
#endif
|
|
@ -0,0 +1,469 @@
|
|||
/*
|
||||
* Copyright © 2006 Keith Packard
|
||||
* Copyright © 2006 Carl Worth
|
||||
*
|
||||
* 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 the copyright holders not be used in advertising or
|
||||
* publicity pertaining to distribution of the software without specific,
|
||||
* written prior permission. The copyright holders make no representations
|
||||
* about the suitability of this software for any purpose. It is provided "as
|
||||
* is" without express or implied warranty.
|
||||
*
|
||||
* THE COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
|
||||
* INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
|
||||
* EVENT SHALL THE COPYRIGHT HOLDERS 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.
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <stddef.h>
|
||||
#include <string.h>
|
||||
#include <assert.h>
|
||||
|
||||
#include "cairo-skiplist-private.h"
|
||||
|
||||
#define ELT_DATA(elt) (void *) ((char*) (elt) - list->data_size)
|
||||
#define NEXT_TO_ELT(next) (skip_elt_t *) ((char *) (next) - offsetof (skip_elt_t, next))
|
||||
|
||||
/* Four 256 element lookup tables back to back implementing a linear
|
||||
* feedback shift register of degree 32. */
|
||||
static unsigned const lfsr_lut[1024] = {
|
||||
0x00000000, 0x9a795537, 0xae8bff59, 0x34f2aa6e, 0xc76eab85, 0x5d17feb2,
|
||||
0x69e554dc, 0xf39c01eb, 0x14a4023d, 0x8edd570a, 0xba2ffd64, 0x2056a853,
|
||||
0xd3caa9b8, 0x49b3fc8f, 0x7d4156e1, 0xe73803d6, 0x2948047a, 0xb331514d,
|
||||
0x87c3fb23, 0x1dbaae14, 0xee26afff, 0x745ffac8, 0x40ad50a6, 0xdad40591,
|
||||
0x3dec0647, 0xa7955370, 0x9367f91e, 0x091eac29, 0xfa82adc2, 0x60fbf8f5,
|
||||
0x5409529b, 0xce7007ac, 0x529008f4, 0xc8e95dc3, 0xfc1bf7ad, 0x6662a29a,
|
||||
0x95fea371, 0x0f87f646, 0x3b755c28, 0xa10c091f, 0x46340ac9, 0xdc4d5ffe,
|
||||
0xe8bff590, 0x72c6a0a7, 0x815aa14c, 0x1b23f47b, 0x2fd15e15, 0xb5a80b22,
|
||||
0x7bd80c8e, 0xe1a159b9, 0xd553f3d7, 0x4f2aa6e0, 0xbcb6a70b, 0x26cff23c,
|
||||
0x123d5852, 0x88440d65, 0x6f7c0eb3, 0xf5055b84, 0xc1f7f1ea, 0x5b8ea4dd,
|
||||
0xa812a536, 0x326bf001, 0x06995a6f, 0x9ce00f58, 0xa52011e8, 0x3f5944df,
|
||||
0x0babeeb1, 0x91d2bb86, 0x624eba6d, 0xf837ef5a, 0xccc54534, 0x56bc1003,
|
||||
0xb18413d5, 0x2bfd46e2, 0x1f0fec8c, 0x8576b9bb, 0x76eab850, 0xec93ed67,
|
||||
0xd8614709, 0x4218123e, 0x8c681592, 0x161140a5, 0x22e3eacb, 0xb89abffc,
|
||||
0x4b06be17, 0xd17feb20, 0xe58d414e, 0x7ff41479, 0x98cc17af, 0x02b54298,
|
||||
0x3647e8f6, 0xac3ebdc1, 0x5fa2bc2a, 0xc5dbe91d, 0xf1294373, 0x6b501644,
|
||||
0xf7b0191c, 0x6dc94c2b, 0x593be645, 0xc342b372, 0x30deb299, 0xaaa7e7ae,
|
||||
0x9e554dc0, 0x042c18f7, 0xe3141b21, 0x796d4e16, 0x4d9fe478, 0xd7e6b14f,
|
||||
0x247ab0a4, 0xbe03e593, 0x8af14ffd, 0x10881aca, 0xdef81d66, 0x44814851,
|
||||
0x7073e23f, 0xea0ab708, 0x1996b6e3, 0x83efe3d4, 0xb71d49ba, 0x2d641c8d,
|
||||
0xca5c1f5b, 0x50254a6c, 0x64d7e002, 0xfeaeb535, 0x0d32b4de, 0x974be1e9,
|
||||
0xa3b94b87, 0x39c01eb0, 0xd03976e7, 0x4a4023d0, 0x7eb289be, 0xe4cbdc89,
|
||||
0x1757dd62, 0x8d2e8855, 0xb9dc223b, 0x23a5770c, 0xc49d74da, 0x5ee421ed,
|
||||
0x6a168b83, 0xf06fdeb4, 0x03f3df5f, 0x998a8a68, 0xad782006, 0x37017531,
|
||||
0xf971729d, 0x630827aa, 0x57fa8dc4, 0xcd83d8f3, 0x3e1fd918, 0xa4668c2f,
|
||||
0x90942641, 0x0aed7376, 0xedd570a0, 0x77ac2597, 0x435e8ff9, 0xd927dace,
|
||||
0x2abbdb25, 0xb0c28e12, 0x8430247c, 0x1e49714b, 0x82a97e13, 0x18d02b24,
|
||||
0x2c22814a, 0xb65bd47d, 0x45c7d596, 0xdfbe80a1, 0xeb4c2acf, 0x71357ff8,
|
||||
0x960d7c2e, 0x0c742919, 0x38868377, 0xa2ffd640, 0x5163d7ab, 0xcb1a829c,
|
||||
0xffe828f2, 0x65917dc5, 0xabe17a69, 0x31982f5e, 0x056a8530, 0x9f13d007,
|
||||
0x6c8fd1ec, 0xf6f684db, 0xc2042eb5, 0x587d7b82, 0xbf457854, 0x253c2d63,
|
||||
0x11ce870d, 0x8bb7d23a, 0x782bd3d1, 0xe25286e6, 0xd6a02c88, 0x4cd979bf,
|
||||
0x7519670f, 0xef603238, 0xdb929856, 0x41ebcd61, 0xb277cc8a, 0x280e99bd,
|
||||
0x1cfc33d3, 0x868566e4, 0x61bd6532, 0xfbc43005, 0xcf369a6b, 0x554fcf5c,
|
||||
0xa6d3ceb7, 0x3caa9b80, 0x085831ee, 0x922164d9, 0x5c516375, 0xc6283642,
|
||||
0xf2da9c2c, 0x68a3c91b, 0x9b3fc8f0, 0x01469dc7, 0x35b437a9, 0xafcd629e,
|
||||
0x48f56148, 0xd28c347f, 0xe67e9e11, 0x7c07cb26, 0x8f9bcacd, 0x15e29ffa,
|
||||
0x21103594, 0xbb6960a3, 0x27896ffb, 0xbdf03acc, 0x890290a2, 0x137bc595,
|
||||
0xe0e7c47e, 0x7a9e9149, 0x4e6c3b27, 0xd4156e10, 0x332d6dc6, 0xa95438f1,
|
||||
0x9da6929f, 0x07dfc7a8, 0xf443c643, 0x6e3a9374, 0x5ac8391a, 0xc0b16c2d,
|
||||
0x0ec16b81, 0x94b83eb6, 0xa04a94d8, 0x3a33c1ef, 0xc9afc004, 0x53d69533,
|
||||
0x67243f5d, 0xfd5d6a6a, 0x1a6569bc, 0x801c3c8b, 0xb4ee96e5, 0x2e97c3d2,
|
||||
0xdd0bc239, 0x4772970e, 0x73803d60, 0xe9f96857, 0x00000000, 0x3a0bb8f9,
|
||||
0x741771f2, 0x4e1cc90b, 0xe82ee3e4, 0xd2255b1d, 0x9c399216, 0xa6322aef,
|
||||
0x4a2492ff, 0x702f2a06, 0x3e33e30d, 0x04385bf4, 0xa20a711b, 0x9801c9e2,
|
||||
0xd61d00e9, 0xec16b810, 0x944925fe, 0xae429d07, 0xe05e540c, 0xda55ecf5,
|
||||
0x7c67c61a, 0x466c7ee3, 0x0870b7e8, 0x327b0f11, 0xde6db701, 0xe4660ff8,
|
||||
0xaa7ac6f3, 0x90717e0a, 0x364354e5, 0x0c48ec1c, 0x42542517, 0x785f9dee,
|
||||
0xb2eb1ecb, 0x88e0a632, 0xc6fc6f39, 0xfcf7d7c0, 0x5ac5fd2f, 0x60ce45d6,
|
||||
0x2ed28cdd, 0x14d93424, 0xf8cf8c34, 0xc2c434cd, 0x8cd8fdc6, 0xb6d3453f,
|
||||
0x10e16fd0, 0x2aead729, 0x64f61e22, 0x5efda6db, 0x26a23b35, 0x1ca983cc,
|
||||
0x52b54ac7, 0x68bef23e, 0xce8cd8d1, 0xf4876028, 0xba9ba923, 0x809011da,
|
||||
0x6c86a9ca, 0x568d1133, 0x1891d838, 0x229a60c1, 0x84a84a2e, 0xbea3f2d7,
|
||||
0xf0bf3bdc, 0xcab48325, 0xffaf68a1, 0xc5a4d058, 0x8bb81953, 0xb1b3a1aa,
|
||||
0x17818b45, 0x2d8a33bc, 0x6396fab7, 0x599d424e, 0xb58bfa5e, 0x8f8042a7,
|
||||
0xc19c8bac, 0xfb973355, 0x5da519ba, 0x67aea143, 0x29b26848, 0x13b9d0b1,
|
||||
0x6be64d5f, 0x51edf5a6, 0x1ff13cad, 0x25fa8454, 0x83c8aebb, 0xb9c31642,
|
||||
0xf7dfdf49, 0xcdd467b0, 0x21c2dfa0, 0x1bc96759, 0x55d5ae52, 0x6fde16ab,
|
||||
0xc9ec3c44, 0xf3e784bd, 0xbdfb4db6, 0x87f0f54f, 0x4d44766a, 0x774fce93,
|
||||
0x39530798, 0x0358bf61, 0xa56a958e, 0x9f612d77, 0xd17de47c, 0xeb765c85,
|
||||
0x0760e495, 0x3d6b5c6c, 0x73779567, 0x497c2d9e, 0xef4e0771, 0xd545bf88,
|
||||
0x9b597683, 0xa152ce7a, 0xd90d5394, 0xe306eb6d, 0xad1a2266, 0x97119a9f,
|
||||
0x3123b070, 0x0b280889, 0x4534c182, 0x7f3f797b, 0x9329c16b, 0xa9227992,
|
||||
0xe73eb099, 0xdd350860, 0x7b07228f, 0x410c9a76, 0x0f10537d, 0x351beb84,
|
||||
0x65278475, 0x5f2c3c8c, 0x1130f587, 0x2b3b4d7e, 0x8d096791, 0xb702df68,
|
||||
0xf91e1663, 0xc315ae9a, 0x2f03168a, 0x1508ae73, 0x5b146778, 0x611fdf81,
|
||||
0xc72df56e, 0xfd264d97, 0xb33a849c, 0x89313c65, 0xf16ea18b, 0xcb651972,
|
||||
0x8579d079, 0xbf726880, 0x1940426f, 0x234bfa96, 0x6d57339d, 0x575c8b64,
|
||||
0xbb4a3374, 0x81418b8d, 0xcf5d4286, 0xf556fa7f, 0x5364d090, 0x696f6869,
|
||||
0x2773a162, 0x1d78199b, 0xd7cc9abe, 0xedc72247, 0xa3dbeb4c, 0x99d053b5,
|
||||
0x3fe2795a, 0x05e9c1a3, 0x4bf508a8, 0x71feb051, 0x9de80841, 0xa7e3b0b8,
|
||||
0xe9ff79b3, 0xd3f4c14a, 0x75c6eba5, 0x4fcd535c, 0x01d19a57, 0x3bda22ae,
|
||||
0x4385bf40, 0x798e07b9, 0x3792ceb2, 0x0d99764b, 0xabab5ca4, 0x91a0e45d,
|
||||
0xdfbc2d56, 0xe5b795af, 0x09a12dbf, 0x33aa9546, 0x7db65c4d, 0x47bde4b4,
|
||||
0xe18fce5b, 0xdb8476a2, 0x9598bfa9, 0xaf930750, 0x9a88ecd4, 0xa083542d,
|
||||
0xee9f9d26, 0xd49425df, 0x72a60f30, 0x48adb7c9, 0x06b17ec2, 0x3cbac63b,
|
||||
0xd0ac7e2b, 0xeaa7c6d2, 0xa4bb0fd9, 0x9eb0b720, 0x38829dcf, 0x02892536,
|
||||
0x4c95ec3d, 0x769e54c4, 0x0ec1c92a, 0x34ca71d3, 0x7ad6b8d8, 0x40dd0021,
|
||||
0xe6ef2ace, 0xdce49237, 0x92f85b3c, 0xa8f3e3c5, 0x44e55bd5, 0x7eeee32c,
|
||||
0x30f22a27, 0x0af992de, 0xaccbb831, 0x96c000c8, 0xd8dcc9c3, 0xe2d7713a,
|
||||
0x2863f21f, 0x12684ae6, 0x5c7483ed, 0x667f3b14, 0xc04d11fb, 0xfa46a902,
|
||||
0xb45a6009, 0x8e51d8f0, 0x624760e0, 0x584cd819, 0x16501112, 0x2c5ba9eb,
|
||||
0x8a698304, 0xb0623bfd, 0xfe7ef2f6, 0xc4754a0f, 0xbc2ad7e1, 0x86216f18,
|
||||
0xc83da613, 0xf2361eea, 0x54043405, 0x6e0f8cfc, 0x201345f7, 0x1a18fd0e,
|
||||
0xf60e451e, 0xcc05fde7, 0x821934ec, 0xb8128c15, 0x1e20a6fa, 0x242b1e03,
|
||||
0x6a37d708, 0x503c6ff1, 0x00000000, 0xca4f08ea, 0x0ee744e3, 0xc4a84c09,
|
||||
0x1dce89c6, 0xd781812c, 0x1329cd25, 0xd966c5cf, 0x3b9d138c, 0xf1d21b66,
|
||||
0x357a576f, 0xff355f85, 0x26539a4a, 0xec1c92a0, 0x28b4dea9, 0xe2fbd643,
|
||||
0x773a2718, 0xbd752ff2, 0x79dd63fb, 0xb3926b11, 0x6af4aede, 0xa0bba634,
|
||||
0x6413ea3d, 0xae5ce2d7, 0x4ca73494, 0x86e83c7e, 0x42407077, 0x880f789d,
|
||||
0x5169bd52, 0x9b26b5b8, 0x5f8ef9b1, 0x95c1f15b, 0xee744e30, 0x243b46da,
|
||||
0xe0930ad3, 0x2adc0239, 0xf3bac7f6, 0x39f5cf1c, 0xfd5d8315, 0x37128bff,
|
||||
0xd5e95dbc, 0x1fa65556, 0xdb0e195f, 0x114111b5, 0xc827d47a, 0x0268dc90,
|
||||
0xc6c09099, 0x0c8f9873, 0x994e6928, 0x530161c2, 0x97a92dcb, 0x5de62521,
|
||||
0x8480e0ee, 0x4ecfe804, 0x8a67a40d, 0x4028ace7, 0xa2d37aa4, 0x689c724e,
|
||||
0xac343e47, 0x667b36ad, 0xbf1df362, 0x7552fb88, 0xb1fab781, 0x7bb5bf6b,
|
||||
0x4691c957, 0x8cdec1bd, 0x48768db4, 0x8239855e, 0x5b5f4091, 0x9110487b,
|
||||
0x55b80472, 0x9ff70c98, 0x7d0cdadb, 0xb743d231, 0x73eb9e38, 0xb9a496d2,
|
||||
0x60c2531d, 0xaa8d5bf7, 0x6e2517fe, 0xa46a1f14, 0x31abee4f, 0xfbe4e6a5,
|
||||
0x3f4caaac, 0xf503a246, 0x2c656789, 0xe62a6f63, 0x2282236a, 0xe8cd2b80,
|
||||
0x0a36fdc3, 0xc079f529, 0x04d1b920, 0xce9eb1ca, 0x17f87405, 0xddb77cef,
|
||||
0x191f30e6, 0xd350380c, 0xa8e58767, 0x62aa8f8d, 0xa602c384, 0x6c4dcb6e,
|
||||
0xb52b0ea1, 0x7f64064b, 0xbbcc4a42, 0x718342a8, 0x937894eb, 0x59379c01,
|
||||
0x9d9fd008, 0x57d0d8e2, 0x8eb61d2d, 0x44f915c7, 0x805159ce, 0x4a1e5124,
|
||||
0xdfdfa07f, 0x1590a895, 0xd138e49c, 0x1b77ec76, 0xc21129b9, 0x085e2153,
|
||||
0xccf66d5a, 0x06b965b0, 0xe442b3f3, 0x2e0dbb19, 0xeaa5f710, 0x20eafffa,
|
||||
0xf98c3a35, 0x33c332df, 0xf76b7ed6, 0x3d24763c, 0x8d2392ae, 0x476c9a44,
|
||||
0x83c4d64d, 0x498bdea7, 0x90ed1b68, 0x5aa21382, 0x9e0a5f8b, 0x54455761,
|
||||
0xb6be8122, 0x7cf189c8, 0xb859c5c1, 0x7216cd2b, 0xab7008e4, 0x613f000e,
|
||||
0xa5974c07, 0x6fd844ed, 0xfa19b5b6, 0x3056bd5c, 0xf4fef155, 0x3eb1f9bf,
|
||||
0xe7d73c70, 0x2d98349a, 0xe9307893, 0x237f7079, 0xc184a63a, 0x0bcbaed0,
|
||||
0xcf63e2d9, 0x052cea33, 0xdc4a2ffc, 0x16052716, 0xd2ad6b1f, 0x18e263f5,
|
||||
0x6357dc9e, 0xa918d474, 0x6db0987d, 0xa7ff9097, 0x7e995558, 0xb4d65db2,
|
||||
0x707e11bb, 0xba311951, 0x58cacf12, 0x9285c7f8, 0x562d8bf1, 0x9c62831b,
|
||||
0x450446d4, 0x8f4b4e3e, 0x4be30237, 0x81ac0add, 0x146dfb86, 0xde22f36c,
|
||||
0x1a8abf65, 0xd0c5b78f, 0x09a37240, 0xc3ec7aaa, 0x074436a3, 0xcd0b3e49,
|
||||
0x2ff0e80a, 0xe5bfe0e0, 0x2117ace9, 0xeb58a403, 0x323e61cc, 0xf8716926,
|
||||
0x3cd9252f, 0xf6962dc5, 0xcbb25bf9, 0x01fd5313, 0xc5551f1a, 0x0f1a17f0,
|
||||
0xd67cd23f, 0x1c33dad5, 0xd89b96dc, 0x12d49e36, 0xf02f4875, 0x3a60409f,
|
||||
0xfec80c96, 0x3487047c, 0xede1c1b3, 0x27aec959, 0xe3068550, 0x29498dba,
|
||||
0xbc887ce1, 0x76c7740b, 0xb26f3802, 0x782030e8, 0xa146f527, 0x6b09fdcd,
|
||||
0xafa1b1c4, 0x65eeb92e, 0x87156f6d, 0x4d5a6787, 0x89f22b8e, 0x43bd2364,
|
||||
0x9adbe6ab, 0x5094ee41, 0x943ca248, 0x5e73aaa2, 0x25c615c9, 0xef891d23,
|
||||
0x2b21512a, 0xe16e59c0, 0x38089c0f, 0xf24794e5, 0x36efd8ec, 0xfca0d006,
|
||||
0x1e5b0645, 0xd4140eaf, 0x10bc42a6, 0xdaf34a4c, 0x03958f83, 0xc9da8769,
|
||||
0x0d72cb60, 0xc73dc38a, 0x52fc32d1, 0x98b33a3b, 0x5c1b7632, 0x96547ed8,
|
||||
0x4f32bb17, 0x857db3fd, 0x41d5fff4, 0x8b9af71e, 0x6961215d, 0xa32e29b7,
|
||||
0x678665be, 0xadc96d54, 0x74afa89b, 0xbee0a071, 0x7a48ec78, 0xb007e492,
|
||||
0x00000000, 0x803e706b, 0x9a05b5e1, 0x1a3bc58a, 0xae723ef5, 0x2e4c4e9e,
|
||||
0x34778b14, 0xb449fb7f, 0xc69d28dd, 0x46a358b6, 0x5c989d3c, 0xdca6ed57,
|
||||
0x68ef1628, 0xe8d16643, 0xf2eaa3c9, 0x72d4d3a2, 0x1743048d, 0x977d74e6,
|
||||
0x8d46b16c, 0x0d78c107, 0xb9313a78, 0x390f4a13, 0x23348f99, 0xa30afff2,
|
||||
0xd1de2c50, 0x51e05c3b, 0x4bdb99b1, 0xcbe5e9da, 0x7fac12a5, 0xff9262ce,
|
||||
0xe5a9a744, 0x6597d72f, 0x2e86091a, 0xaeb87971, 0xb483bcfb, 0x34bdcc90,
|
||||
0x80f437ef, 0x00ca4784, 0x1af1820e, 0x9acff265, 0xe81b21c7, 0x682551ac,
|
||||
0x721e9426, 0xf220e44d, 0x46691f32, 0xc6576f59, 0xdc6caad3, 0x5c52dab8,
|
||||
0x39c50d97, 0xb9fb7dfc, 0xa3c0b876, 0x23fec81d, 0x97b73362, 0x17894309,
|
||||
0x0db28683, 0x8d8cf6e8, 0xff58254a, 0x7f665521, 0x655d90ab, 0xe563e0c0,
|
||||
0x512a1bbf, 0xd1146bd4, 0xcb2fae5e, 0x4b11de35, 0x5d0c1234, 0xdd32625f,
|
||||
0xc709a7d5, 0x4737d7be, 0xf37e2cc1, 0x73405caa, 0x697b9920, 0xe945e94b,
|
||||
0x9b913ae9, 0x1baf4a82, 0x01948f08, 0x81aaff63, 0x35e3041c, 0xb5dd7477,
|
||||
0xafe6b1fd, 0x2fd8c196, 0x4a4f16b9, 0xca7166d2, 0xd04aa358, 0x5074d333,
|
||||
0xe43d284c, 0x64035827, 0x7e389dad, 0xfe06edc6, 0x8cd23e64, 0x0cec4e0f,
|
||||
0x16d78b85, 0x96e9fbee, 0x22a00091, 0xa29e70fa, 0xb8a5b570, 0x389bc51b,
|
||||
0x738a1b2e, 0xf3b46b45, 0xe98faecf, 0x69b1dea4, 0xddf825db, 0x5dc655b0,
|
||||
0x47fd903a, 0xc7c3e051, 0xb51733f3, 0x35294398, 0x2f128612, 0xaf2cf679,
|
||||
0x1b650d06, 0x9b5b7d6d, 0x8160b8e7, 0x015ec88c, 0x64c91fa3, 0xe4f76fc8,
|
||||
0xfeccaa42, 0x7ef2da29, 0xcabb2156, 0x4a85513d, 0x50be94b7, 0xd080e4dc,
|
||||
0xa254377e, 0x226a4715, 0x3851829f, 0xb86ff2f4, 0x0c26098b, 0x8c1879e0,
|
||||
0x9623bc6a, 0x161dcc01, 0xba182468, 0x3a265403, 0x201d9189, 0xa023e1e2,
|
||||
0x146a1a9d, 0x94546af6, 0x8e6faf7c, 0x0e51df17, 0x7c850cb5, 0xfcbb7cde,
|
||||
0xe680b954, 0x66bec93f, 0xd2f73240, 0x52c9422b, 0x48f287a1, 0xc8ccf7ca,
|
||||
0xad5b20e5, 0x2d65508e, 0x375e9504, 0xb760e56f, 0x03291e10, 0x83176e7b,
|
||||
0x992cabf1, 0x1912db9a, 0x6bc60838, 0xebf87853, 0xf1c3bdd9, 0x71fdcdb2,
|
||||
0xc5b436cd, 0x458a46a6, 0x5fb1832c, 0xdf8ff347, 0x949e2d72, 0x14a05d19,
|
||||
0x0e9b9893, 0x8ea5e8f8, 0x3aec1387, 0xbad263ec, 0xa0e9a666, 0x20d7d60d,
|
||||
0x520305af, 0xd23d75c4, 0xc806b04e, 0x4838c025, 0xfc713b5a, 0x7c4f4b31,
|
||||
0x66748ebb, 0xe64afed0, 0x83dd29ff, 0x03e35994, 0x19d89c1e, 0x99e6ec75,
|
||||
0x2daf170a, 0xad916761, 0xb7aaa2eb, 0x3794d280, 0x45400122, 0xc57e7149,
|
||||
0xdf45b4c3, 0x5f7bc4a8, 0xeb323fd7, 0x6b0c4fbc, 0x71378a36, 0xf109fa5d,
|
||||
0xe714365c, 0x672a4637, 0x7d1183bd, 0xfd2ff3d6, 0x496608a9, 0xc95878c2,
|
||||
0xd363bd48, 0x535dcd23, 0x21891e81, 0xa1b76eea, 0xbb8cab60, 0x3bb2db0b,
|
||||
0x8ffb2074, 0x0fc5501f, 0x15fe9595, 0x95c0e5fe, 0xf05732d1, 0x706942ba,
|
||||
0x6a528730, 0xea6cf75b, 0x5e250c24, 0xde1b7c4f, 0xc420b9c5, 0x441ec9ae,
|
||||
0x36ca1a0c, 0xb6f46a67, 0xaccfafed, 0x2cf1df86, 0x98b824f9, 0x18865492,
|
||||
0x02bd9118, 0x8283e173, 0xc9923f46, 0x49ac4f2d, 0x53978aa7, 0xd3a9facc,
|
||||
0x67e001b3, 0xe7de71d8, 0xfde5b452, 0x7ddbc439, 0x0f0f179b, 0x8f3167f0,
|
||||
0x950aa27a, 0x1534d211, 0xa17d296e, 0x21435905, 0x3b789c8f, 0xbb46ece4,
|
||||
0xded13bcb, 0x5eef4ba0, 0x44d48e2a, 0xc4eafe41, 0x70a3053e, 0xf09d7555,
|
||||
0xeaa6b0df, 0x6a98c0b4, 0x184c1316, 0x9872637d, 0x8249a6f7, 0x0277d69c,
|
||||
0xb63e2de3, 0x36005d88, 0x2c3b9802, 0xac05e869};
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
/*
|
||||
* Initialize an empty skip list
|
||||
*/
|
||||
void
|
||||
skip_list_init (skip_list_t *list,
|
||||
skip_list_compare_t compare,
|
||||
size_t elt_size)
|
||||
{
|
||||
int i;
|
||||
|
||||
list->compare = compare;
|
||||
list->elt_size = elt_size;
|
||||
list->data_size = elt_size - sizeof (skip_elt_t);
|
||||
|
||||
for (i = 0; i < MAX_LEVEL; i++) {
|
||||
list->chains[i] = NULL;
|
||||
list->freelists[i] = NULL;
|
||||
}
|
||||
|
||||
list->max_level = 0;
|
||||
}
|
||||
|
||||
void
|
||||
skip_list_fini (skip_list_t *list)
|
||||
{
|
||||
skip_elt_t *elt;
|
||||
int i;
|
||||
|
||||
while ((elt = list->chains[0])) {
|
||||
skip_list_delete_given (list, elt);
|
||||
}
|
||||
for (i=0; i<MAX_LEVEL; i++) {
|
||||
elt = list->freelists[i];
|
||||
while (elt) {
|
||||
skip_elt_t *nextfree = elt->prev;
|
||||
free (ELT_DATA(elt));
|
||||
elt = nextfree;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Generate a random level number, distributed
|
||||
* so that each level is 1/4 as likely as the one before
|
||||
*
|
||||
* Note that level numbers run 1 <= level <= MAX_LEVEL
|
||||
*/
|
||||
static int
|
||||
random_level (void)
|
||||
{
|
||||
/* tricky bit -- each bit is '1' 75% of the time */
|
||||
long int bits = lfsr_random() | lfsr_random();
|
||||
int level = 0;
|
||||
|
||||
while (++level < MAX_LEVEL)
|
||||
{
|
||||
if (bits & 1)
|
||||
break;
|
||||
bits >>= 1;
|
||||
}
|
||||
return level;
|
||||
}
|
||||
|
||||
static void *
|
||||
alloc_node_for_level (skip_list_t *list, unsigned level)
|
||||
{
|
||||
if (list->freelists[level-1]) {
|
||||
skip_elt_t *elt = list->freelists[level-1];
|
||||
list->freelists[level-1] = elt->prev;
|
||||
return ELT_DATA(elt);
|
||||
}
|
||||
return malloc (list->elt_size + (level-1) * sizeof (skip_elt_t *));
|
||||
}
|
||||
|
||||
static void
|
||||
free_elt (skip_list_t *list, skip_elt_t *elt)
|
||||
{
|
||||
elt->prev = list->freelists[elt->prev_index];
|
||||
list->freelists[elt->prev_index] = elt;
|
||||
}
|
||||
|
||||
/*
|
||||
* Insert 'data' into the list
|
||||
*/
|
||||
void *
|
||||
skip_list_insert (skip_list_t *list, void *data, int unique)
|
||||
{
|
||||
skip_elt_t **update[MAX_LEVEL];
|
||||
skip_elt_t *prev[MAX_LEVEL];
|
||||
char *data_and_elt;
|
||||
skip_elt_t *elt, **next;
|
||||
int i, level, prev_index;
|
||||
|
||||
/*
|
||||
* Find links along each chain
|
||||
*/
|
||||
next = list->chains;
|
||||
for (i = list->max_level; --i >= 0; )
|
||||
{
|
||||
for (; (elt = next[i]); next = elt->next)
|
||||
{
|
||||
int cmp = list->compare (list, ELT_DATA(elt), data);
|
||||
if (unique && 0 == cmp)
|
||||
return ELT_DATA(elt);
|
||||
if (cmp > 0)
|
||||
break;
|
||||
}
|
||||
update[i] = next;
|
||||
if (next != list->chains)
|
||||
prev[i] = NEXT_TO_ELT (next);
|
||||
else
|
||||
prev[i] = NULL;
|
||||
}
|
||||
level = random_level ();
|
||||
prev_index = level - 1;
|
||||
|
||||
/*
|
||||
* Create new list element
|
||||
*/
|
||||
if (level > list->max_level)
|
||||
{
|
||||
level = list->max_level + 1;
|
||||
prev_index = level - 1;
|
||||
prev[prev_index] = NULL;
|
||||
update[list->max_level] = list->chains;
|
||||
list->max_level = level;
|
||||
}
|
||||
|
||||
data_and_elt = alloc_node_for_level (list, level);
|
||||
memcpy (data_and_elt, data, list->data_size);
|
||||
elt = (skip_elt_t *) (data_and_elt + list->data_size);
|
||||
|
||||
elt->prev_index = prev_index;
|
||||
elt->prev = prev[prev_index];
|
||||
|
||||
/*
|
||||
* Insert into all chains
|
||||
*/
|
||||
for (i = 0; i < level; i++)
|
||||
{
|
||||
elt->next[i] = update[i][i];
|
||||
if (elt->next[i] && elt->next[i]->prev_index == i)
|
||||
elt->next[i]->prev = elt;
|
||||
update[i][i] = elt;
|
||||
}
|
||||
|
||||
return data_and_elt;
|
||||
}
|
||||
|
||||
void *
|
||||
skip_list_find (skip_list_t *list, void *data)
|
||||
{
|
||||
int i;
|
||||
skip_elt_t **next = list->chains;
|
||||
skip_elt_t *elt;
|
||||
|
||||
/*
|
||||
* Walk chain pointers one level at a time
|
||||
*/
|
||||
for (i = list->max_level; --i >= 0;)
|
||||
while (next[i] && list->compare (list, data, ELT_DATA(next[i])) > 0)
|
||||
{
|
||||
next = next[i]->next;
|
||||
}
|
||||
/*
|
||||
* Here we are
|
||||
*/
|
||||
elt = next[0];
|
||||
if (elt && list->compare (list, data, ELT_DATA (elt)) == 0)
|
||||
return ELT_DATA (elt);
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
void
|
||||
skip_list_delete (skip_list_t *list, void *data)
|
||||
{
|
||||
skip_elt_t **update[MAX_LEVEL], *prev[MAX_LEVEL];
|
||||
skip_elt_t *elt, **next;
|
||||
int i;
|
||||
|
||||
/*
|
||||
* Find links along each chain
|
||||
*/
|
||||
next = list->chains;
|
||||
for (i = list->max_level; --i >= 0; )
|
||||
{
|
||||
for (; (elt = next[i]); next = elt->next)
|
||||
{
|
||||
if (list->compare (list, ELT_DATA (elt), data) >= 0)
|
||||
break;
|
||||
}
|
||||
update[i] = &next[i];
|
||||
if (next == list->chains)
|
||||
prev[i] = NULL;
|
||||
else
|
||||
prev[i] = NEXT_TO_ELT (next);
|
||||
}
|
||||
elt = next[0];
|
||||
assert (list->compare (list, ELT_DATA (elt), data) == 0);
|
||||
for (i = 0; i < list->max_level && *update[i] == elt; i++) {
|
||||
*update[i] = elt->next[i];
|
||||
if (elt->next[i] && elt->next[i]->prev_index == i)
|
||||
elt->next[i]->prev = prev[i];
|
||||
}
|
||||
while (list->max_level > 0 && list->chains[list->max_level - 1] == NULL)
|
||||
list->max_level--;
|
||||
free_elt (list, elt);
|
||||
}
|
||||
|
||||
void
|
||||
skip_list_delete_given (skip_list_t *list, skip_elt_t *given)
|
||||
{
|
||||
skip_elt_t **update[MAX_LEVEL], *prev[MAX_LEVEL];
|
||||
skip_elt_t *elt, **next;
|
||||
int i;
|
||||
|
||||
/*
|
||||
* Find links along each chain
|
||||
*/
|
||||
if (given->prev)
|
||||
next = given->prev->next;
|
||||
else
|
||||
next = list->chains;
|
||||
for (i = given->prev_index + 1; --i >= 0; )
|
||||
{
|
||||
for (; (elt = next[i]); next = elt->next)
|
||||
{
|
||||
if (elt == given)
|
||||
break;
|
||||
}
|
||||
update[i] = &next[i];
|
||||
if (next == list->chains)
|
||||
prev[i] = NULL;
|
||||
else
|
||||
prev[i] = NEXT_TO_ELT (next);
|
||||
}
|
||||
elt = next[0];
|
||||
assert (elt == given);
|
||||
for (i = 0; i < (given->prev_index + 1) && *update[i] == elt; i++) {
|
||||
*update[i] = elt->next[i];
|
||||
if (elt->next[i] && elt->next[i]->prev_index == i)
|
||||
elt->next[i]->prev = prev[i];
|
||||
}
|
||||
while (list->max_level > 0 && list->chains[list->max_level - 1] == NULL)
|
||||
list->max_level--;
|
||||
free_elt (list, elt);
|
||||
}
|
|
@ -74,7 +74,7 @@ cairo_private cairo_status_t
|
|||
_cairo_surface_fallback_show_glyphs (cairo_surface_t *surface,
|
||||
cairo_operator_t op,
|
||||
cairo_pattern_t *source,
|
||||
const cairo_glyph_t *glyphs,
|
||||
cairo_glyph_t *glyphs,
|
||||
int num_glyphs,
|
||||
cairo_scaled_font_t *scaled_font);
|
||||
|
||||
|
|
|
@ -548,10 +548,6 @@ _clip_and_composite_trapezoids (cairo_pattern_t *src,
|
|||
* _cairo_surface_fill_rectangles() or to drawing with a
|
||||
* clip region, then we have an additional region to clear.
|
||||
*/
|
||||
status = _cairo_surface_get_extents (dst, &extents);
|
||||
if (status)
|
||||
return status;
|
||||
|
||||
clear_region = _cairo_region_create_from_rectangle (&extents);
|
||||
if (clear_region == NULL)
|
||||
return CAIRO_STATUS_NO_MEMORY;
|
||||
|
@ -843,7 +839,7 @@ _cairo_surface_fallback_fill (cairo_surface_t *surface,
|
|||
|
||||
typedef struct {
|
||||
cairo_scaled_font_t *font;
|
||||
const cairo_glyph_t *glyphs;
|
||||
cairo_glyph_t *glyphs;
|
||||
int num_glyphs;
|
||||
} cairo_show_glyphs_info_t;
|
||||
|
||||
|
@ -911,7 +907,7 @@ cairo_status_t
|
|||
_cairo_surface_fallback_show_glyphs (cairo_surface_t *surface,
|
||||
cairo_operator_t op,
|
||||
cairo_pattern_t *source,
|
||||
const cairo_glyph_t *glyphs,
|
||||
cairo_glyph_t *glyphs,
|
||||
int num_glyphs,
|
||||
cairo_scaled_font_t *scaled_font)
|
||||
{
|
||||
|
|
|
@ -987,6 +987,10 @@ _cairo_surface_release_dest_image (cairo_surface_t *surface,
|
|||
* _cairo_surface_clone_similar:
|
||||
* @surface: a #cairo_surface_t
|
||||
* @src: the source image
|
||||
* @src_x: extent for the rectangle in src we actually care about
|
||||
* @src_y: extent for the rectangle in src we actually care about
|
||||
* @width: extent for the rectangle in src we actually care about
|
||||
* @height: extent for the rectangle in src we actually care about
|
||||
* @clone_out: location to store a surface compatible with @surface
|
||||
* and with contents identical to @src. The caller must call
|
||||
* cairo_surface_destroy() on the result.
|
||||
|
@ -1002,6 +1006,10 @@ _cairo_surface_release_dest_image (cairo_surface_t *surface,
|
|||
cairo_status_t
|
||||
_cairo_surface_clone_similar (cairo_surface_t *surface,
|
||||
cairo_surface_t *src,
|
||||
int src_x,
|
||||
int src_y,
|
||||
int width,
|
||||
int height,
|
||||
cairo_surface_t **clone_out)
|
||||
{
|
||||
cairo_status_t status;
|
||||
|
@ -1014,7 +1022,8 @@ _cairo_surface_clone_similar (cairo_surface_t *surface,
|
|||
if (surface->backend->clone_similar == NULL)
|
||||
return CAIRO_INT_STATUS_UNSUPPORTED;
|
||||
|
||||
status = surface->backend->clone_similar (surface, src, clone_out);
|
||||
status = surface->backend->clone_similar (surface, src, src_x, src_y,
|
||||
width, height, clone_out);
|
||||
if (status == CAIRO_STATUS_SUCCESS)
|
||||
(*clone_out)->device_transform = src->device_transform;
|
||||
|
||||
|
@ -1025,7 +1034,8 @@ _cairo_surface_clone_similar (cairo_surface_t *surface,
|
|||
if (status != CAIRO_STATUS_SUCCESS)
|
||||
return status;
|
||||
|
||||
status = surface->backend->clone_similar (surface, &image->base, clone_out);
|
||||
status = surface->backend->clone_similar (surface, &image->base, src_x,
|
||||
src_y, width, height, clone_out);
|
||||
if (status == CAIRO_STATUS_SUCCESS)
|
||||
(*clone_out)->device_transform = src->device_transform;
|
||||
|
||||
|
@ -1785,7 +1795,7 @@ cairo_status_t
|
|||
_cairo_surface_show_glyphs (cairo_surface_t *surface,
|
||||
cairo_operator_t op,
|
||||
cairo_pattern_t *source,
|
||||
const cairo_glyph_t *glyphs,
|
||||
cairo_glyph_t *glyphs,
|
||||
int num_glyphs,
|
||||
cairo_scaled_font_t *scaled_font)
|
||||
{
|
||||
|
@ -1863,7 +1873,7 @@ _cairo_surface_old_show_glyphs (cairo_scaled_font_t *scaled_font,
|
|||
int dest_y,
|
||||
unsigned int width,
|
||||
unsigned int height,
|
||||
const cairo_glyph_t *glyphs,
|
||||
cairo_glyph_t *glyphs,
|
||||
int num_glyphs)
|
||||
{
|
||||
cairo_status_t status;
|
||||
|
|
|
@ -49,6 +49,7 @@
|
|||
|
||||
typedef struct cairo_svg_document cairo_svg_document_t;
|
||||
typedef struct cairo_svg_surface cairo_svg_surface_t;
|
||||
typedef struct cairo_svg_page cairo_svg_page_t;
|
||||
|
||||
static const int invalid_pattern_id = -1;
|
||||
|
||||
|
@ -60,6 +61,12 @@ static const cairo_svg_version_t _cairo_svg_versions[] =
|
|||
|
||||
#define CAIRO_SVG_VERSION_LAST ((int)(sizeof (_cairo_svg_versions) / sizeof (_cairo_svg_versions[0])))
|
||||
|
||||
static cairo_bool_t
|
||||
_cairo_svg_version_has_page_set_support (cairo_svg_version_t version)
|
||||
{
|
||||
return version > CAIRO_SVG_VERSION_1_1;
|
||||
}
|
||||
|
||||
static const char * _cairo_svg_version_strings[CAIRO_SVG_VERSION_LAST] =
|
||||
{
|
||||
"SVG 1.1",
|
||||
|
@ -72,6 +79,13 @@ static const char * _cairo_svg_internal_version_strings[CAIRO_SVG_VERSION_LAST]
|
|||
"1.2"
|
||||
};
|
||||
|
||||
struct cairo_svg_page {
|
||||
unsigned int surface_id;
|
||||
unsigned int clip_id;
|
||||
unsigned int clip_level;
|
||||
cairo_output_stream_t *xml_node;
|
||||
};
|
||||
|
||||
struct cairo_svg_document {
|
||||
cairo_output_stream_t *output_stream;
|
||||
unsigned long refcount;
|
||||
|
@ -114,6 +128,7 @@ struct cairo_svg_surface {
|
|||
cairo_svg_document_t *document;
|
||||
|
||||
cairo_output_stream_t *xml_node;
|
||||
cairo_array_t page_set;
|
||||
|
||||
unsigned int clip_level;
|
||||
unsigned int base_clip;
|
||||
|
@ -370,6 +385,7 @@ _cairo_svg_surface_create_for_document (cairo_svg_document_t *document,
|
|||
width, height);
|
||||
|
||||
surface->xml_node = _cairo_memory_stream_create ();
|
||||
_cairo_array_init (&surface->page_set, sizeof (cairo_svg_page_t));
|
||||
|
||||
if (content == CAIRO_CONTENT_COLOR) {
|
||||
_cairo_output_stream_printf (surface->xml_node,
|
||||
|
@ -412,6 +428,52 @@ _cairo_svg_surface_create_for_stream_internal (cairo_output_stream_t *stream,
|
|||
return surface;
|
||||
}
|
||||
|
||||
static cairo_svg_page_t *
|
||||
_cairo_svg_surface_store_page (cairo_svg_surface_t *surface)
|
||||
{
|
||||
unsigned int i;
|
||||
cairo_svg_page_t page;
|
||||
|
||||
page.surface_id = surface->id;
|
||||
page.clip_id = surface->base_clip;
|
||||
page.clip_level = surface->clip_level;
|
||||
page.xml_node = surface->xml_node;
|
||||
|
||||
surface->xml_node = _cairo_memory_stream_create ();
|
||||
surface->clip_level = 0;
|
||||
|
||||
for (i = 0; i < page.clip_level; i++)
|
||||
_cairo_output_stream_printf (page.xml_node, "</g>\n");
|
||||
|
||||
_cairo_array_append (&surface->page_set, &page);
|
||||
|
||||
return _cairo_array_index (&surface->page_set, surface->page_set.num_elements - 1);
|
||||
}
|
||||
|
||||
static cairo_int_status_t
|
||||
_cairo_svg_surface_copy_page (void *abstract_surface)
|
||||
{
|
||||
cairo_svg_surface_t *surface = abstract_surface;
|
||||
cairo_svg_page_t *page;
|
||||
|
||||
page = _cairo_svg_surface_store_page (surface);
|
||||
|
||||
_cairo_memory_stream_copy (page->xml_node, surface->xml_node);
|
||||
surface->clip_level = page->clip_level;
|
||||
|
||||
return CAIRO_STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
static cairo_int_status_t
|
||||
_cairo_svg_surface_show_page (void *abstract_surface)
|
||||
{
|
||||
cairo_svg_surface_t *surface = abstract_surface;
|
||||
|
||||
_cairo_svg_surface_store_page (surface);
|
||||
|
||||
return CAIRO_STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
static void
|
||||
emit_transform (cairo_output_stream_t *output,
|
||||
char const *attribute_str,
|
||||
|
@ -716,6 +778,8 @@ _cairo_svg_surface_finish (void *abstract_surface)
|
|||
cairo_status_t status;
|
||||
cairo_svg_surface_t *surface = abstract_surface;
|
||||
cairo_svg_document_t *document = surface->document;
|
||||
cairo_svg_page_t *page;
|
||||
unsigned int i;
|
||||
|
||||
if (_cairo_paginated_surface_get_target (document->owner) == &surface->base)
|
||||
status = _cairo_svg_document_finish (document);
|
||||
|
@ -724,6 +788,12 @@ _cairo_svg_surface_finish (void *abstract_surface)
|
|||
|
||||
_cairo_output_stream_destroy (surface->xml_node);
|
||||
|
||||
for (i = 0; i < surface->page_set.num_elements; i++) {
|
||||
page = _cairo_array_index (&surface->page_set, i);
|
||||
_cairo_output_stream_destroy (page->xml_node);
|
||||
}
|
||||
_cairo_array_fini (&surface->page_set);
|
||||
|
||||
_cairo_svg_document_destroy (document);
|
||||
|
||||
return status;
|
||||
|
@ -902,80 +972,86 @@ static int
|
|||
emit_meta_surface (cairo_svg_document_t *document,
|
||||
cairo_meta_surface_t *surface)
|
||||
{
|
||||
cairo_surface_t *paginated_surface;
|
||||
cairo_surface_t *svg_surface;
|
||||
cairo_meta_snapshot_t new_snapshot;
|
||||
cairo_array_t *page_set;
|
||||
|
||||
cairo_output_stream_t *contents;
|
||||
cairo_meta_surface_t *meta;
|
||||
cairo_meta_snapshot_t *snapshot;
|
||||
unsigned int num_elements;
|
||||
unsigned int i, id;
|
||||
|
||||
/* search in already emitted meta snapshots */
|
||||
num_elements = document->meta_snapshots.num_elements;
|
||||
for (i = 0; i < num_elements; i++) {
|
||||
snapshot = _cairo_array_index (&document->meta_snapshots, i);
|
||||
meta = snapshot->meta;
|
||||
if (meta->commands.num_elements == surface->commands.num_elements &&
|
||||
_cairo_array_index (&meta->commands, 0) == _cairo_array_index (&surface->commands, 0)) {
|
||||
id = snapshot->id;
|
||||
break;
|
||||
return snapshot->id;
|
||||
}
|
||||
}
|
||||
|
||||
if (i >= num_elements) {
|
||||
cairo_surface_t *paginated_surface;
|
||||
cairo_surface_t *svg_surface;
|
||||
cairo_meta_snapshot_t new_snapshot;
|
||||
meta = (cairo_meta_surface_t *) _cairo_surface_snapshot ((cairo_surface_t *)surface);
|
||||
paginated_surface = _cairo_svg_surface_create_for_document (document,
|
||||
meta->content,
|
||||
meta->width_pixels,
|
||||
meta->height_pixels);
|
||||
svg_surface = _cairo_paginated_surface_get_target (paginated_surface);
|
||||
cairo_surface_set_fallback_resolution (paginated_surface,
|
||||
document->owner->x_fallback_resolution,
|
||||
document->owner->y_fallback_resolution);
|
||||
_cairo_meta_surface_replay ((cairo_surface_t *)meta, paginated_surface);
|
||||
_cairo_surface_show_page (paginated_surface);
|
||||
|
||||
meta = (cairo_meta_surface_t *) _cairo_surface_snapshot ((cairo_surface_t *)surface);
|
||||
paginated_surface = _cairo_svg_surface_create_for_document (document,
|
||||
meta->content,
|
||||
meta->width_pixels,
|
||||
meta->height_pixels);
|
||||
svg_surface = _cairo_paginated_surface_get_target (paginated_surface);
|
||||
cairo_surface_set_fallback_resolution (paginated_surface,
|
||||
document->owner->x_fallback_resolution,
|
||||
document->owner->y_fallback_resolution);
|
||||
_cairo_meta_surface_replay ((cairo_surface_t *)meta, paginated_surface);
|
||||
_cairo_surface_show_page (paginated_surface);
|
||||
new_snapshot.meta = meta;
|
||||
new_snapshot.id = ((cairo_svg_surface_t *) svg_surface)->id;
|
||||
_cairo_array_append (&document->meta_snapshots, &new_snapshot);
|
||||
|
||||
new_snapshot.meta = meta;
|
||||
new_snapshot.id = ((cairo_svg_surface_t *) svg_surface)->id;
|
||||
_cairo_array_append (&document->meta_snapshots, &new_snapshot);
|
||||
|
||||
if (meta->content == CAIRO_CONTENT_ALPHA) {
|
||||
emit_alpha_filter (document);
|
||||
_cairo_output_stream_printf (document->xml_node_defs,
|
||||
"<g id=\"surface%d\" "
|
||||
"clip-path=\"url(#clip%d)\" "
|
||||
"filter=\"url(#alpha)\">\n",
|
||||
((cairo_svg_surface_t *) svg_surface)->id,
|
||||
((cairo_svg_surface_t *) svg_surface)->base_clip);
|
||||
} else {
|
||||
_cairo_output_stream_printf (document->xml_node_defs,
|
||||
"<g id=\"surface%d\" "
|
||||
"clip-path=\"url(#clip%d)\">\n",
|
||||
((cairo_svg_surface_t *) svg_surface)->id,
|
||||
((cairo_svg_surface_t *) svg_surface)->base_clip);
|
||||
}
|
||||
|
||||
contents = ((cairo_svg_surface_t *) svg_surface)->xml_node;
|
||||
_cairo_memory_stream_copy (contents, document->xml_node_defs);
|
||||
|
||||
for (i = 0; i < ((cairo_svg_surface_t *) svg_surface)->clip_level; i++)
|
||||
_cairo_output_stream_printf (document->xml_node_defs, "</g>\n");
|
||||
|
||||
_cairo_output_stream_printf (document->xml_node_defs, "</g>\n");
|
||||
|
||||
id = new_snapshot.id;
|
||||
|
||||
cairo_surface_destroy (paginated_surface);
|
||||
|
||||
/* FIXME: cairo_paginated_surface doesn't take a ref to the
|
||||
* passed in target surface so we can't call destroy here.
|
||||
* cairo_paginated_surface should be fixed, but for now just
|
||||
* work around it. */
|
||||
|
||||
/* cairo_surface_destroy (svg_surface); */
|
||||
if (meta->content == CAIRO_CONTENT_ALPHA) {
|
||||
emit_alpha_filter (document);
|
||||
_cairo_output_stream_printf (document->xml_node_defs,
|
||||
"<g id=\"surface%d\" "
|
||||
"clip-path=\"url(#clip%d)\" "
|
||||
"filter=\"url(#alpha)\">\n",
|
||||
((cairo_svg_surface_t *) svg_surface)->id,
|
||||
((cairo_svg_surface_t *) svg_surface)->base_clip);
|
||||
} else {
|
||||
_cairo_output_stream_printf (document->xml_node_defs,
|
||||
"<g id=\"surface%d\" "
|
||||
"clip-path=\"url(#clip%d)\">\n",
|
||||
((cairo_svg_surface_t *) svg_surface)->id,
|
||||
((cairo_svg_surface_t *) svg_surface)->base_clip);
|
||||
}
|
||||
|
||||
contents = ((cairo_svg_surface_t *) svg_surface)->xml_node;
|
||||
page_set = &((cairo_svg_surface_t *) svg_surface)->page_set;
|
||||
|
||||
if (_cairo_memory_stream_length (contents) > 0)
|
||||
_cairo_svg_surface_store_page ((cairo_svg_surface_t *) svg_surface);
|
||||
|
||||
if (page_set->num_elements > 0) {
|
||||
cairo_svg_page_t *page;
|
||||
|
||||
page = _cairo_array_index (page_set, page_set->num_elements - 1);
|
||||
_cairo_memory_stream_copy (page->xml_node, document->xml_node_defs);
|
||||
}
|
||||
|
||||
_cairo_output_stream_printf (document->xml_node_defs, "</g>\n");
|
||||
|
||||
id = new_snapshot.id;
|
||||
|
||||
cairo_surface_destroy (paginated_surface);
|
||||
|
||||
/* FIXME: cairo_paginated_surface doesn't take a ref to the
|
||||
* passed in target surface so we can't call destroy here.
|
||||
* cairo_paginated_surface should be fixed, but for now just
|
||||
* work around it. */
|
||||
|
||||
/* cairo_surface_destroy (svg_surface); */
|
||||
|
||||
return id;
|
||||
}
|
||||
|
||||
|
@ -1532,7 +1608,7 @@ static cairo_int_status_t
|
|||
_cairo_svg_surface_show_glyphs (void *abstract_surface,
|
||||
cairo_operator_t op,
|
||||
cairo_pattern_t *pattern,
|
||||
const cairo_glyph_t *glyphs,
|
||||
cairo_glyph_t *glyphs,
|
||||
int num_glyphs,
|
||||
cairo_scaled_font_t *scaled_font)
|
||||
{
|
||||
|
@ -1664,8 +1740,8 @@ static const cairo_surface_backend_t cairo_svg_surface_backend = {
|
|||
NULL, /* _cairo_svg_surface_composite, */
|
||||
NULL, /* _cairo_svg_surface_fill_rectangles, */
|
||||
NULL, /* _cairo_svg_surface_composite_trapezoids,*/
|
||||
NULL, /* copy_page */
|
||||
NULL, /* show_page */
|
||||
_cairo_svg_surface_copy_page,
|
||||
_cairo_svg_surface_show_page,
|
||||
NULL, /* set_clip_region */
|
||||
_cairo_svg_surface_intersect_clip_path,
|
||||
_cairo_svg_surface_get_extents,
|
||||
|
@ -1759,6 +1835,7 @@ _cairo_svg_document_finish (cairo_svg_document_t *document)
|
|||
cairo_output_stream_t *output = document->output_stream;
|
||||
cairo_meta_snapshot_t *snapshot;
|
||||
cairo_svg_surface_t *surface;
|
||||
cairo_svg_page_t *page;
|
||||
unsigned int i;
|
||||
|
||||
if (document->finished)
|
||||
|
@ -1788,17 +1865,36 @@ _cairo_svg_document_finish (cairo_svg_document_t *document)
|
|||
}
|
||||
|
||||
surface = (cairo_svg_surface_t *) _cairo_paginated_surface_get_target (document->owner);
|
||||
_cairo_output_stream_printf (output,
|
||||
"<g id=\"surface%d\" "
|
||||
"clip-path=\"url(#clip%d)\">\n",
|
||||
surface->id,
|
||||
surface->base_clip);
|
||||
_cairo_memory_stream_copy (surface->xml_node, output);
|
||||
if (_cairo_memory_stream_length (surface->xml_node) > 0)
|
||||
_cairo_svg_surface_store_page (surface);
|
||||
|
||||
for (i = 0; i < surface->clip_level; i++)
|
||||
if (surface->page_set.num_elements > 1 &&
|
||||
_cairo_svg_version_has_page_set_support (document->svg_version)) {
|
||||
_cairo_output_stream_printf (output, "<pageSet>\n");
|
||||
for (i = 0; i < surface->page_set.num_elements; i++) {
|
||||
page = _cairo_array_index (&surface->page_set, i);
|
||||
_cairo_output_stream_printf (output, "<page>\n");
|
||||
_cairo_output_stream_printf (output,
|
||||
"<g id=\"surface%d\" "
|
||||
"clip-path=\"url(#clip%d)\">\n",
|
||||
page->surface_id,
|
||||
page->clip_id);
|
||||
_cairo_memory_stream_copy (page->xml_node, output);
|
||||
_cairo_output_stream_printf (output, "</g>\n</page>\n");
|
||||
}
|
||||
_cairo_output_stream_printf (output, "</pageSet>\n");
|
||||
} else if (surface->page_set.num_elements > 0) {
|
||||
page = _cairo_array_index (&surface->page_set, surface->page_set.num_elements - 1);
|
||||
_cairo_output_stream_printf (output,
|
||||
"<g id=\"surface%d\" "
|
||||
"clip-path=\"url(#clip%d)\">\n",
|
||||
page->surface_id,
|
||||
page->clip_id);
|
||||
_cairo_memory_stream_copy (page->xml_node, output);
|
||||
_cairo_output_stream_printf (output, "</g>\n");
|
||||
}
|
||||
|
||||
_cairo_output_stream_printf (output, "</g>\n</svg>\n");
|
||||
_cairo_output_stream_printf (output, "</svg>\n");
|
||||
|
||||
_cairo_output_stream_destroy (document->xml_node_glyphs);
|
||||
_cairo_output_stream_destroy (document->xml_node_defs);
|
||||
|
|
|
@ -46,7 +46,7 @@ CAIRO_BEGIN_DECLS
|
|||
* #cairo_svg_version_t is used to describe the version number of the SVG
|
||||
* specification that a generated SVG file will conform to.
|
||||
*/
|
||||
typedef enum {
|
||||
typedef enum _cairo_svg_version {
|
||||
CAIRO_SVG_VERSION_1_1,
|
||||
CAIRO_SVG_VERSION_1_2
|
||||
} cairo_svg_version_t;
|
||||
|
|
|
@ -46,11 +46,6 @@ static cairo_status_t
|
|||
_cairo_traps_add_trap (cairo_traps_t *traps, cairo_fixed_t top, cairo_fixed_t bottom,
|
||||
cairo_line_t *left, cairo_line_t *right);
|
||||
|
||||
static cairo_status_t
|
||||
_cairo_traps_add_trap_from_points (cairo_traps_t *traps, cairo_fixed_t top, cairo_fixed_t bottom,
|
||||
cairo_point_t left_p1, cairo_point_t left_p2,
|
||||
cairo_point_t right_p1, cairo_point_t right_p2);
|
||||
|
||||
static int
|
||||
_compare_point_fixed_by_y (const void *av, const void *bv);
|
||||
|
||||
|
@ -69,6 +64,8 @@ _line_segs_intersect_ceil (cairo_line_t *left, cairo_line_t *right, cairo_fixed_
|
|||
void
|
||||
_cairo_traps_init (cairo_traps_t *traps)
|
||||
{
|
||||
traps->status = CAIRO_STATUS_SUCCESS;
|
||||
|
||||
traps->num_traps = 0;
|
||||
|
||||
traps->traps_size = 0;
|
||||
|
@ -101,13 +98,11 @@ cairo_status_t
|
|||
_cairo_traps_init_box (cairo_traps_t *traps,
|
||||
cairo_box_t *box)
|
||||
{
|
||||
cairo_status_t status;
|
||||
|
||||
_cairo_traps_init (traps);
|
||||
|
||||
status = _cairo_traps_grow_by (traps, 1);
|
||||
if (status)
|
||||
return status;
|
||||
traps->status = _cairo_traps_grow_by (traps, 1);
|
||||
if (traps->status)
|
||||
return traps->status;
|
||||
|
||||
traps->num_traps = 1;
|
||||
|
||||
|
@ -122,25 +117,27 @@ _cairo_traps_init_box (cairo_traps_t *traps,
|
|||
|
||||
traps->extents = *box;
|
||||
|
||||
return CAIRO_STATUS_SUCCESS;
|
||||
return traps->status;
|
||||
}
|
||||
|
||||
static cairo_status_t
|
||||
_cairo_traps_add_trap (cairo_traps_t *traps, cairo_fixed_t top, cairo_fixed_t bottom,
|
||||
cairo_line_t *left, cairo_line_t *right)
|
||||
{
|
||||
cairo_status_t status;
|
||||
cairo_trapezoid_t *trap;
|
||||
|
||||
if (traps->status)
|
||||
return traps->status;
|
||||
|
||||
if (top == bottom) {
|
||||
return CAIRO_STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
if (traps->num_traps >= traps->traps_size) {
|
||||
int inc = traps->traps_size ? traps->traps_size : 32;
|
||||
status = _cairo_traps_grow_by (traps, inc);
|
||||
if (status)
|
||||
return status;
|
||||
traps->status = _cairo_traps_grow_by (traps, inc);
|
||||
if (traps->status)
|
||||
return traps->status;
|
||||
}
|
||||
|
||||
trap = &traps->traps[traps->num_traps];
|
||||
|
@ -173,10 +170,10 @@ _cairo_traps_add_trap (cairo_traps_t *traps, cairo_fixed_t top, cairo_fixed_t bo
|
|||
|
||||
traps->num_traps++;
|
||||
|
||||
return CAIRO_STATUS_SUCCESS;
|
||||
return traps->status;
|
||||
}
|
||||
|
||||
static cairo_status_t
|
||||
cairo_status_t
|
||||
_cairo_traps_add_trap_from_points (cairo_traps_t *traps, cairo_fixed_t top, cairo_fixed_t bottom,
|
||||
cairo_point_t left_p1, cairo_point_t left_p2,
|
||||
cairo_point_t right_p1, cairo_point_t right_p2)
|
||||
|
@ -184,6 +181,9 @@ _cairo_traps_add_trap_from_points (cairo_traps_t *traps, cairo_fixed_t top, cair
|
|||
cairo_line_t left;
|
||||
cairo_line_t right;
|
||||
|
||||
if (traps->status)
|
||||
return traps->status;
|
||||
|
||||
left.p1 = left_p1;
|
||||
left.p2 = left_p2;
|
||||
|
||||
|
@ -200,21 +200,24 @@ _cairo_traps_grow_by (cairo_traps_t *traps, int additional)
|
|||
int old_size = traps->traps_size;
|
||||
int new_size = traps->num_traps + additional;
|
||||
|
||||
if (new_size <= traps->traps_size) {
|
||||
return CAIRO_STATUS_SUCCESS;
|
||||
}
|
||||
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 (new_traps == NULL) {
|
||||
traps->traps_size = old_size;
|
||||
return CAIRO_STATUS_NO_MEMORY;
|
||||
traps->status = CAIRO_STATUS_NO_MEMORY;
|
||||
return traps->status;
|
||||
}
|
||||
|
||||
traps->traps = new_traps;
|
||||
|
||||
return CAIRO_STATUS_SUCCESS;
|
||||
return traps->status;
|
||||
}
|
||||
|
||||
static int
|
||||
|
@ -309,7 +312,6 @@ _cairo_trapezoid_array_translate_and_scale (cairo_trapezoid_t *offset_traps,
|
|||
cairo_status_t
|
||||
_cairo_traps_tessellate_triangle (cairo_traps_t *traps, cairo_point_t t[3])
|
||||
{
|
||||
cairo_status_t status;
|
||||
cairo_line_t line;
|
||||
cairo_fixed_16_16_t intersect;
|
||||
cairo_point_t tsort[3];
|
||||
|
@ -320,16 +322,16 @@ _cairo_traps_tessellate_triangle (cairo_traps_t *traps, cairo_point_t t[3])
|
|||
/* horizontal top edge requires special handling */
|
||||
if (tsort[0].y == tsort[1].y) {
|
||||
if (tsort[0].x < tsort[1].x)
|
||||
status = _cairo_traps_add_trap_from_points (traps,
|
||||
tsort[1].y, tsort[2].y,
|
||||
tsort[0], tsort[2],
|
||||
tsort[1], tsort[2]);
|
||||
_cairo_traps_add_trap_from_points (traps,
|
||||
tsort[1].y, tsort[2].y,
|
||||
tsort[0], tsort[2],
|
||||
tsort[1], tsort[2]);
|
||||
else
|
||||
status = _cairo_traps_add_trap_from_points (traps,
|
||||
tsort[1].y, tsort[2].y,
|
||||
tsort[1], tsort[2],
|
||||
tsort[0], tsort[2]);
|
||||
return status;
|
||||
_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];
|
||||
|
@ -338,73 +340,146 @@ _cairo_traps_tessellate_triangle (cairo_traps_t *traps, cairo_point_t t[3])
|
|||
intersect = _compute_x (&line, tsort[2].y);
|
||||
|
||||
if (intersect < tsort[2].x) {
|
||||
status = _cairo_traps_add_trap_from_points (traps,
|
||||
tsort[0].y, tsort[1].y,
|
||||
tsort[0], tsort[1],
|
||||
tsort[0], tsort[2]);
|
||||
if (status)
|
||||
return status;
|
||||
status = _cairo_traps_add_trap_from_points (traps,
|
||||
tsort[1].y, tsort[2].y,
|
||||
tsort[1], tsort[2],
|
||||
tsort[0], tsort[2]);
|
||||
if (status)
|
||||
return status;
|
||||
_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 {
|
||||
status = _cairo_traps_add_trap_from_points (traps,
|
||||
tsort[0].y, tsort[1].y,
|
||||
tsort[0], tsort[2],
|
||||
tsort[0], tsort[1]);
|
||||
if (status)
|
||||
return status;
|
||||
status = _cairo_traps_add_trap_from_points (traps,
|
||||
tsort[1].y, tsort[2].y,
|
||||
tsort[0], tsort[2],
|
||||
tsort[1], tsort[2]);
|
||||
if (status)
|
||||
return status;
|
||||
_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 CAIRO_STATUS_SUCCESS;
|
||||
return traps->status;
|
||||
}
|
||||
|
||||
/* Warning: This function reorders the elements of the array provided. */
|
||||
cairo_status_t
|
||||
_cairo_traps_tessellate_rectangle (cairo_traps_t *traps, cairo_point_t q[4])
|
||||
_cairo_traps_tessellate_convex_quad (cairo_traps_t *traps, cairo_point_t q[4])
|
||||
{
|
||||
cairo_status_t status;
|
||||
int a, b, c, d;
|
||||
int i;
|
||||
|
||||
qsort (q, 4, sizeof (cairo_point_t), _compare_point_fixed_by_y);
|
||||
/* Choose a as a point with minimal y */
|
||||
a = 0;
|
||||
for (i = 1; i < 4; i++)
|
||||
if (_compare_point_fixed_by_y (&q[i], &q[a]) < 0)
|
||||
a = i;
|
||||
|
||||
if (q[1].x > q[2].x) {
|
||||
status = _cairo_traps_add_trap_from_points (traps,
|
||||
q[0].y, q[1].y, q[0], q[2], q[0], q[1]);
|
||||
if (status)
|
||||
return status;
|
||||
status = _cairo_traps_add_trap_from_points (traps,
|
||||
q[1].y, q[2].y, q[0], q[2], q[1], q[3]);
|
||||
if (status)
|
||||
return status;
|
||||
status = _cairo_traps_add_trap_from_points (traps,
|
||||
q[2].y, q[3].y, q[2], q[3], q[1], q[3]);
|
||||
if (status)
|
||||
return status;
|
||||
} else {
|
||||
status = _cairo_traps_add_trap_from_points (traps,
|
||||
q[0].y, q[1].y, q[0], q[1], q[0], q[2]);
|
||||
if (status)
|
||||
return status;
|
||||
status = _cairo_traps_add_trap_from_points (traps,
|
||||
q[1].y, q[2].y, q[1], q[3], q[0], q[2]);
|
||||
if (status)
|
||||
return status;
|
||||
status = _cairo_traps_add_trap_from_points (traps,
|
||||
q[2].y, q[3].y, q[1], q[3], q[2], q[3]);
|
||||
if (status)
|
||||
return status;
|
||||
/* b and d are adjacent to a, while c is opposite */
|
||||
b = (a + 1) % 4;
|
||||
c = (a + 2) % 4;
|
||||
d = (a + 3) % 4;
|
||||
|
||||
/* Choose between b and d so that b.y is less than d.y */
|
||||
if (_compare_point_fixed_by_y (&q[d], &q[b]) < 0) {
|
||||
b = (a + 3) % 4;
|
||||
d = (a + 1) % 4;
|
||||
}
|
||||
|
||||
return CAIRO_STATUS_SUCCESS;
|
||||
/* 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
|
||||
*
|
||||
* 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
|
||||
*/
|
||||
_cairo_traps_add_trap_from_points (traps,
|
||||
q[a].y, q[b].y,
|
||||
q[a], q[b], q[a], q[d]);
|
||||
_cairo_traps_add_trap_from_points (traps,
|
||||
q[b].y, q[c].y,
|
||||
q[b], q[c], q[a], q[d]);
|
||||
_cairo_traps_add_trap_from_points (traps,
|
||||
q[c].y, q[d].y,
|
||||
q[c], q[d], q[a], q[d]);
|
||||
} else {
|
||||
/* c.y < d.y && b.x >= d.x
|
||||
*
|
||||
* a
|
||||
* | \ a.y b.y ad ab
|
||||
* | b
|
||||
* | | b.y c.y ad bc
|
||||
* | c
|
||||
* | / c.y d.y ad cd
|
||||
* d
|
||||
*/
|
||||
_cairo_traps_add_trap_from_points (traps,
|
||||
q[a].y, q[b].y,
|
||||
q[a], q[d], q[a], q[b]);
|
||||
_cairo_traps_add_trap_from_points (traps,
|
||||
q[b].y, q[c].y,
|
||||
q[a], q[d], q[b], q[c]);
|
||||
_cairo_traps_add_trap_from_points (traps,
|
||||
q[c].y, q[d].y,
|
||||
q[a], q[d], q[c], q[d]);
|
||||
}
|
||||
} else {
|
||||
if (q[b].x < q[d].x) {
|
||||
/* c.y >= d.y && b.x < d.x
|
||||
*
|
||||
* a
|
||||
* / \ a.y b.y ab ad
|
||||
* b \
|
||||
* \ \ b.y d.y bc ad
|
||||
* \ d
|
||||
* \ / d.y c.y bc dc
|
||||
* c
|
||||
*/
|
||||
_cairo_traps_add_trap_from_points (traps,
|
||||
q[a].y, q[b].y,
|
||||
q[a], q[b], q[a], q[d]);
|
||||
_cairo_traps_add_trap_from_points (traps,
|
||||
q[b].y, q[d].y,
|
||||
q[b], q[c], q[a], q[d]);
|
||||
_cairo_traps_add_trap_from_points (traps,
|
||||
q[d].y, q[c].y,
|
||||
q[b], q[c], q[d], q[c]);
|
||||
} else {
|
||||
/* c.y >= d.y && b.x >= d.x
|
||||
*
|
||||
* a
|
||||
* / \ a.y b.y ad ab
|
||||
* / b
|
||||
* / / b.y d.y ad bc
|
||||
* d /
|
||||
* \ / d.y c.y dc bc
|
||||
* c
|
||||
*/
|
||||
_cairo_traps_add_trap_from_points (traps,
|
||||
q[a].y, q[b].y,
|
||||
q[a], q[d], q[a], q[b]);
|
||||
_cairo_traps_add_trap_from_points (traps,
|
||||
q[b].y, q[d].y,
|
||||
q[a], q[d], q[b], q[c]);
|
||||
_cairo_traps_add_trap_from_points (traps,
|
||||
q[d].y, q[c].y,
|
||||
q[d], q[c], q[b], q[c]);
|
||||
}
|
||||
}
|
||||
|
||||
return traps->status;
|
||||
}
|
||||
|
||||
static int
|
||||
|
@ -730,7 +805,6 @@ _cairo_traps_tessellate_polygon (cairo_traps_t *traps,
|
|||
cairo_polygon_t *poly,
|
||||
cairo_fill_rule_t fill_rule)
|
||||
{
|
||||
cairo_status_t status;
|
||||
int i, active, inactive;
|
||||
cairo_fixed_t y, y_next, intersect;
|
||||
int in_out, num_edges = poly->num_edges;
|
||||
|
@ -786,9 +860,7 @@ _cairo_traps_tessellate_polygon (cairo_traps_t *traps,
|
|||
if ((in_out & 1) == 0)
|
||||
continue;
|
||||
}
|
||||
status = _cairo_traps_add_trap (traps, y, y_next, &edges[i].edge, &edges[i+1].edge);
|
||||
if (status)
|
||||
return status;
|
||||
_cairo_traps_add_trap (traps, y, y_next, &edges[i].edge, &edges[i+1].edge);
|
||||
}
|
||||
|
||||
/* delete inactive edges */
|
||||
|
@ -801,7 +873,7 @@ _cairo_traps_tessellate_polygon (cairo_traps_t *traps,
|
|||
|
||||
y = y_next;
|
||||
}
|
||||
return CAIRO_STATUS_SUCCESS;
|
||||
return traps->status;
|
||||
}
|
||||
|
||||
static cairo_bool_t
|
||||
|
|
|
@ -51,6 +51,7 @@
|
|||
*/
|
||||
|
||||
#define MAKE_TT_TAG(a, b, c, d) (a<<24 | b<<16 | c<<8 | d)
|
||||
#define TT_TAG_CFF MAKE_TT_TAG('C','F','F',' ')
|
||||
#define TT_TAG_cmap MAKE_TT_TAG('c','m','a','p')
|
||||
#define TT_TAG_cvt MAKE_TT_TAG('c','v','t',' ')
|
||||
#define TT_TAG_fpgm MAKE_TT_TAG('f','p','g','m')
|
||||
|
|
|
@ -194,12 +194,12 @@ _cairo_truetype_font_create (cairo_scaled_font_subset_t *scaled_font_subset,
|
|||
goto fail3;
|
||||
|
||||
font->base.num_glyphs = 0;
|
||||
font->base.x_min = be16_to_cpu (head.x_min);
|
||||
font->base.y_min = be16_to_cpu (head.y_min);
|
||||
font->base.x_max = be16_to_cpu (head.x_max);
|
||||
font->base.y_max = be16_to_cpu (head.y_max);
|
||||
font->base.ascent = be16_to_cpu (hhea.ascender);
|
||||
font->base.descent = be16_to_cpu (hhea.descender);
|
||||
font->base.x_min = (int16_t) be16_to_cpu (head.x_min);
|
||||
font->base.y_min = (int16_t) be16_to_cpu (head.y_min);
|
||||
font->base.x_max = (int16_t) be16_to_cpu (head.x_max);
|
||||
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);
|
||||
|
||||
/* Extract the font name from the name table. At present this
|
||||
* just looks for the Mac platform/Roman encoded font name. It
|
||||
|
@ -591,10 +591,9 @@ cairo_truetype_font_write_hmtx_table (cairo_truetype_font_t *font,
|
|||
}
|
||||
font->backend->load_truetype_table (font->scaled_font_subset->scaled_font,
|
||||
TT_TAG_hmtx,
|
||||
(num_hmetrics - 1) * long_entry_size +
|
||||
(font->glyphs[i].parent_index - num_hmetrics)
|
||||
* short_entry_size,
|
||||
(unsigned char *) (p+1), &short_entry_size);
|
||||
num_hmetrics * long_entry_size +
|
||||
(font->glyphs[i].parent_index - num_hmetrics) * short_entry_size,
|
||||
(unsigned char *) (p + 1), &short_entry_size);
|
||||
}
|
||||
font->base.widths[i] = be16_to_cpu (p[0]);
|
||||
}
|
||||
|
|
|
@ -64,7 +64,8 @@ typedef struct _cairo_type1_font {
|
|||
|
||||
static cairo_status_t
|
||||
cairo_type1_font_create (cairo_scaled_font_subset_t *scaled_font_subset,
|
||||
cairo_type1_font_t **subset_return)
|
||||
cairo_type1_font_t **subset_return,
|
||||
cairo_bool_t hex_encode)
|
||||
{
|
||||
cairo_type1_font_t *font;
|
||||
cairo_font_face_t *font_face;
|
||||
|
@ -84,6 +85,7 @@ cairo_type1_font_create (cairo_scaled_font_subset_t *scaled_font_subset,
|
|||
}
|
||||
|
||||
font->scaled_font_subset = scaled_font_subset;
|
||||
font->hex_encode = hex_encode;
|
||||
|
||||
font_face = cairo_scaled_font_get_font_face (scaled_font_subset->scaled_font);
|
||||
|
||||
|
@ -98,12 +100,20 @@ cairo_type1_font_create (cairo_scaled_font_subset_t *scaled_font_subset,
|
|||
&font_matrix,
|
||||
&ctm,
|
||||
&font_options);
|
||||
if (font->type1_scaled_font == NULL)
|
||||
goto fail;
|
||||
|
||||
_cairo_array_init (&font->contents, sizeof (unsigned char));
|
||||
|
||||
*subset_return = font;
|
||||
|
||||
return CAIRO_STATUS_SUCCESS;
|
||||
|
||||
fail:
|
||||
free (font->widths);
|
||||
free (font);
|
||||
|
||||
return CAIRO_STATUS_NO_MEMORY;
|
||||
}
|
||||
|
||||
/* Magic constants for the type1 eexec encryption */
|
||||
|
@ -378,14 +388,19 @@ cairo_type1_font_create_charstring (cairo_type1_font_t *font,
|
|||
path_info.data = data;
|
||||
path_info.current_x = (int) scaled_glyph->metrics.x_bearing;
|
||||
path_info.current_y = (int) scaled_glyph->metrics.y_bearing;
|
||||
_cairo_path_fixed_interpret (scaled_glyph->path,
|
||||
CAIRO_DIRECTION_FORWARD,
|
||||
_charstring_move_to,
|
||||
_charstring_line_to,
|
||||
_charstring_curve_to,
|
||||
_charstring_close_path,
|
||||
&path_info);
|
||||
status = _cairo_path_fixed_interpret (scaled_glyph->path,
|
||||
CAIRO_DIRECTION_FORWARD,
|
||||
_charstring_move_to,
|
||||
_charstring_line_to,
|
||||
_charstring_curve_to,
|
||||
_charstring_close_path,
|
||||
&path_info);
|
||||
if (status)
|
||||
return status;
|
||||
|
||||
status = _cairo_array_grow_by (data, 1);
|
||||
if (status)
|
||||
return status;
|
||||
charstring_encode_command (path_info.data, CHARSTRING_endchar);
|
||||
|
||||
return CAIRO_STATUS_SUCCESS;
|
||||
|
@ -395,7 +410,7 @@ static cairo_int_status_t
|
|||
cairo_type1_font_write_charstrings (cairo_type1_font_t *font,
|
||||
cairo_output_stream_t *encrypted_output)
|
||||
{
|
||||
cairo_status_t status = CAIRO_STATUS_SUCCESS;
|
||||
cairo_status_t status;
|
||||
unsigned char zeros[] = { 0, 0, 0, 0 };
|
||||
cairo_array_t data;
|
||||
unsigned int i;
|
||||
|
@ -413,7 +428,9 @@ cairo_type1_font_write_charstrings (cairo_type1_font_t *font,
|
|||
for (i = 0; i < font->scaled_font_subset->num_glyphs; i++) {
|
||||
_cairo_array_truncate (&data, 0);
|
||||
/* four "random" bytes required by encryption algorithm */
|
||||
_cairo_array_append_multiple (&data, zeros, 4);
|
||||
status = _cairo_array_append_multiple (&data, zeros, 4);
|
||||
if (status)
|
||||
goto fail;
|
||||
status = cairo_type1_font_create_charstring (font, i,
|
||||
font->scaled_font_subset->glyphs[i],
|
||||
&data);
|
||||
|
@ -432,8 +449,12 @@ cairo_type1_font_write_charstrings (cairo_type1_font_t *font,
|
|||
|
||||
_cairo_array_truncate (&data, 0);
|
||||
/* four "random" bytes required by encryption algorithm */
|
||||
_cairo_array_append_multiple (&data, zeros, 4);
|
||||
create_notdef_charstring (&data);
|
||||
status = _cairo_array_append_multiple (&data, zeros, 4);
|
||||
if (status)
|
||||
goto fail;
|
||||
status = create_notdef_charstring (&data);
|
||||
if (status)
|
||||
goto fail;
|
||||
charstring_encrypt (&data);
|
||||
length = _cairo_array_num_elements (&data);
|
||||
_cairo_output_stream_printf (encrypted_output, "/.notdef %d RD ", length);
|
||||
|
@ -447,7 +468,7 @@ fail:
|
|||
return status;
|
||||
}
|
||||
|
||||
static cairo_status_t
|
||||
static void
|
||||
cairo_type1_font_write_header (cairo_type1_font_t *font,
|
||||
const char *name)
|
||||
{
|
||||
|
@ -495,8 +516,6 @@ cairo_type1_font_write_header (cairo_type1_font_t *font,
|
|||
"readonly def\n"
|
||||
"currentdict end\n"
|
||||
"currentfile eexec\n");
|
||||
|
||||
return CAIRO_STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
static cairo_status_t
|
||||
|
@ -546,14 +565,15 @@ cairo_type1_font_write_private_dict (cairo_type1_font_t *font,
|
|||
cairo_output_stream_t *encrypted_output;
|
||||
|
||||
font->eexec_key = private_dict_key;
|
||||
font->hex_encode = TRUE;
|
||||
font->hex_column = 0;
|
||||
encrypted_output = _cairo_output_stream_create (
|
||||
cairo_type1_write_stream_encrypted,
|
||||
NULL,
|
||||
font);
|
||||
if (encrypted_output == NULL)
|
||||
if (encrypted_output == NULL) {
|
||||
status = CAIRO_STATUS_NO_MEMORY;
|
||||
goto fail;
|
||||
}
|
||||
|
||||
/* Note: the first four spaces at the start of this private dict
|
||||
* are the four "random" bytes of plaintext required by the
|
||||
|
@ -589,7 +609,7 @@ cairo_type1_font_write_private_dict (cairo_type1_font_t *font,
|
|||
return status;
|
||||
}
|
||||
|
||||
static cairo_status_t
|
||||
static void
|
||||
cairo_type1_font_write_trailer(cairo_type1_font_t *font)
|
||||
{
|
||||
int i;
|
||||
|
@ -600,8 +620,6 @@ cairo_type1_font_write_trailer(cairo_type1_font_t *font)
|
|||
_cairo_output_stream_write (font->output, zeros, sizeof zeros);
|
||||
|
||||
_cairo_output_stream_printf (font->output, "cleartomark\n");
|
||||
|
||||
return CAIRO_STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
static cairo_status_t
|
||||
|
@ -667,17 +685,18 @@ cairo_type1_font_destroy (cairo_type1_font_t *font)
|
|||
free (font);
|
||||
}
|
||||
|
||||
cairo_status_t
|
||||
_cairo_type1_fallback_init (cairo_type1_subset_t *type1_subset,
|
||||
const char *name,
|
||||
cairo_scaled_font_subset_t *scaled_font_subset)
|
||||
static cairo_status_t
|
||||
_cairo_type1_fallback_init_internal (cairo_type1_subset_t *type1_subset,
|
||||
const char *name,
|
||||
cairo_scaled_font_subset_t *scaled_font_subset,
|
||||
cairo_bool_t hex_encode)
|
||||
{
|
||||
cairo_type1_font_t *font;
|
||||
cairo_status_t status;
|
||||
unsigned long length;
|
||||
unsigned int i, len;
|
||||
|
||||
status = cairo_type1_font_create (scaled_font_subset, &font);
|
||||
status = cairo_type1_font_create (scaled_font_subset, &font, hex_encode);
|
||||
if (status)
|
||||
return status;
|
||||
|
||||
|
@ -686,12 +705,16 @@ _cairo_type1_fallback_init (cairo_type1_subset_t *type1_subset,
|
|||
goto fail1;
|
||||
|
||||
type1_subset->base_font = strdup (name);
|
||||
if (type1_subset->base_font == NULL)
|
||||
if (type1_subset->base_font == NULL) {
|
||||
status = CAIRO_STATUS_NO_MEMORY;
|
||||
goto fail1;
|
||||
}
|
||||
|
||||
type1_subset->widths = calloc (sizeof (int), font->scaled_font_subset->num_glyphs);
|
||||
if (type1_subset->widths == NULL)
|
||||
if (type1_subset->widths == NULL) {
|
||||
status = CAIRO_STATUS_NO_MEMORY;
|
||||
goto fail2;
|
||||
}
|
||||
for (i = 0; i < font->scaled_font_subset->num_glyphs; i++)
|
||||
type1_subset->widths[i] = font->widths[i];
|
||||
|
||||
|
@ -705,9 +728,10 @@ _cairo_type1_fallback_init (cairo_type1_subset_t *type1_subset,
|
|||
length = font->header_size + font->data_size +
|
||||
font->trailer_size;
|
||||
type1_subset->data = malloc (length);
|
||||
if (type1_subset->data == NULL)
|
||||
if (type1_subset->data == NULL) {
|
||||
status = CAIRO_STATUS_NO_MEMORY;
|
||||
goto fail3;
|
||||
|
||||
}
|
||||
memcpy (type1_subset->data,
|
||||
_cairo_array_index (&font->contents, 0), length);
|
||||
|
||||
|
@ -737,6 +761,26 @@ _cairo_type1_fallback_init (cairo_type1_subset_t *type1_subset,
|
|||
return status;
|
||||
}
|
||||
|
||||
cairo_status_t
|
||||
_cairo_type1_fallback_init_binary (cairo_type1_subset_t *type1_subset,
|
||||
const char *name,
|
||||
cairo_scaled_font_subset_t *scaled_font_subset)
|
||||
{
|
||||
return _cairo_type1_fallback_init_internal (type1_subset,
|
||||
name,
|
||||
scaled_font_subset, FALSE);
|
||||
}
|
||||
|
||||
cairo_status_t
|
||||
_cairo_type1_fallback_init_hex (cairo_type1_subset_t *type1_subset,
|
||||
const char *name,
|
||||
cairo_scaled_font_subset_t *scaled_font_subset)
|
||||
{
|
||||
return _cairo_type1_fallback_init_internal (type1_subset,
|
||||
name,
|
||||
scaled_font_subset, TRUE);
|
||||
}
|
||||
|
||||
void
|
||||
_cairo_type1_fallback_fini (cairo_type1_subset_t *subset)
|
||||
{
|
||||
|
|
|
@ -280,7 +280,7 @@ cairo_type1_font_subset_write_header (cairo_type1_font_subset_t *font,
|
|||
_cairo_output_stream_printf (font->output,
|
||||
"/Encoding 256 array\n"
|
||||
"0 1 255 {1 index exch /.notdef put} for\n");
|
||||
for (i = 0; i < font->base.num_glyphs; i++) {
|
||||
for (i = 1; i < font->base.num_glyphs; i++) {
|
||||
if (font->glyphs[i].subset_index < 0)
|
||||
continue;
|
||||
_cairo_output_stream_printf (font->output,
|
||||
|
@ -1008,6 +1008,9 @@ _cairo_type1_subset_init (cairo_type1_subset_t *type1_subset,
|
|||
if (!_cairo_scaled_font_is_ft (scaled_font_subset->scaled_font))
|
||||
return CAIRO_INT_STATUS_UNSUPPORTED;
|
||||
|
||||
if (_cairo_ft_scaled_font_is_vertical (scaled_font_subset->scaled_font))
|
||||
return CAIRO_INT_STATUS_UNSUPPORTED;
|
||||
|
||||
unscaled_font = _cairo_ft_scaled_font_get_unscaled_font (scaled_font_subset->scaled_font);
|
||||
|
||||
status = _cairo_type1_font_subset_create (unscaled_font, &font, hex_encode);
|
||||
|
|
|
@ -218,7 +218,7 @@ cairo_uint128_t I _cairo_uint128_negate (cairo_uint128_t a);
|
|||
#define _cairo_uint128_negative(a) (_cairo_uint64_negative(a.hi))
|
||||
cairo_uint128_t I _cairo_uint128_not (cairo_uint128_t a);
|
||||
|
||||
#define _cairo_uint128_to_int128_(i) (i)
|
||||
#define _cairo_uint128_to_int128(i) (i)
|
||||
#define _cairo_int128_to_uint128(i) (i)
|
||||
|
||||
cairo_int128_t I _cairo_int32_to_int128 (int32_t i);
|
||||
|
@ -298,6 +298,14 @@ _cairo_uint128_divrem (cairo_uint128_t num, cairo_uint128_t den);
|
|||
cairo_quorem128_t I
|
||||
_cairo_int128_divrem (cairo_int128_t num, cairo_int128_t den);
|
||||
|
||||
cairo_uquorem64_t I
|
||||
_cairo_uint_96by64_32x64_divrem (cairo_uint128_t num,
|
||||
cairo_uint64_t den);
|
||||
|
||||
cairo_quorem64_t I
|
||||
_cairo_int_96by64_32x64_divrem (cairo_int128_t num,
|
||||
cairo_int64_t den);
|
||||
|
||||
#define _cairo_uint128_le(a,b) (!_cairo_uint128_gt(a,b))
|
||||
#define _cairo_uint128_ne(a,b) (!_cairo_uint128_eq(a,b))
|
||||
#define _cairo_uint128_ge(a,b) (!_cairo_uint128_lt(a,b))
|
||||
|
|
|
@ -71,7 +71,7 @@ _cairo_int32_to_int64 (int32_t i)
|
|||
return q;
|
||||
}
|
||||
|
||||
static const cairo_uint64_t
|
||||
static cairo_uint64_t
|
||||
_cairo_uint32s_to_uint64 (uint32_t h, uint32_t l)
|
||||
{
|
||||
cairo_uint64_t q;
|
||||
|
@ -407,7 +407,7 @@ _cairo_uint128_sub (cairo_uint128_t a, cairo_uint128_t b)
|
|||
#define uint64_lo32(i) ((i).lo)
|
||||
#define uint64_hi32(i) ((i).hi)
|
||||
|
||||
static const cairo_uint64_t
|
||||
static cairo_uint64_t
|
||||
uint64_lo (cairo_uint64_t i)
|
||||
{
|
||||
cairo_uint64_t s;
|
||||
|
@ -417,7 +417,7 @@ uint64_lo (cairo_uint64_t i)
|
|||
return s;
|
||||
}
|
||||
|
||||
static const cairo_uint64_t
|
||||
static cairo_uint64_t
|
||||
uint64_hi (cairo_uint64_t i)
|
||||
{
|
||||
cairo_uint64_t s;
|
||||
|
@ -427,7 +427,7 @@ uint64_hi (cairo_uint64_t i)
|
|||
return s;
|
||||
}
|
||||
|
||||
static const cairo_uint64_t
|
||||
static cairo_uint64_t
|
||||
uint64_shift32 (cairo_uint64_t i)
|
||||
{
|
||||
cairo_uint64_t s;
|
||||
|
@ -656,3 +656,155 @@ _cairo_int128_divrem (cairo_int128_t num, cairo_int128_t den)
|
|||
qr.quo = uqr.quo;
|
||||
return qr;
|
||||
}
|
||||
|
||||
/**
|
||||
* _cairo_uint_96by64_32x64_divrem:
|
||||
*
|
||||
* Compute a 32 bit quotient and 64 bit remainder of a 96 bit unsigned
|
||||
* dividend and 64 bit divisor. If the quotient doesn't fit into 32
|
||||
* bits then the returned remainder is equal to the divisor, and the
|
||||
* qoutient is the largest representable 64 bit integer. It is an
|
||||
* error to call this function with the high 32 bits of @num being
|
||||
* non-zero. */
|
||||
cairo_uquorem64_t
|
||||
_cairo_uint_96by64_32x64_divrem (cairo_uint128_t num,
|
||||
cairo_uint64_t den)
|
||||
{
|
||||
cairo_uquorem64_t result;
|
||||
cairo_uint64_t B = _cairo_uint32s_to_uint64 (1, 0);
|
||||
|
||||
/* These are the high 64 bits of the *96* bit numerator. We're
|
||||
* going to represent the numerator as xB + y, where x is a 64,
|
||||
* and y is a 32 bit number. */
|
||||
cairo_uint64_t x = _cairo_uint128_to_uint64 (_cairo_uint128_rsl(num, 32));
|
||||
|
||||
/* Initialise the result to indicate overflow. */
|
||||
result.quo = _cairo_uint32s_to_uint64 (-1U, -1U);
|
||||
result.rem = den;
|
||||
|
||||
/* Don't bother if the quotient is going to overflow. */
|
||||
if (_cairo_uint64_ge (x, den)) {
|
||||
return /* overflow */ result;
|
||||
}
|
||||
|
||||
if (_cairo_uint64_lt (x, B)) {
|
||||
/* When the final quotient is known to fit in 32 bits, then
|
||||
* num < 2^64 if and only if den < 2^32. */
|
||||
return _cairo_uint64_divrem (_cairo_uint128_to_uint64 (num), den);
|
||||
}
|
||||
else {
|
||||
/* Denominator is >= 2^32. the numerator is >= 2^64, and the
|
||||
* division won't overflow: need two divrems. Write the
|
||||
* numerator and denominator as
|
||||
*
|
||||
* num = xB + y x : 64 bits, y : 32 bits
|
||||
* den = uB + v u, v : 32 bits
|
||||
*/
|
||||
uint32_t y = _cairo_uint128_to_uint32 (num);
|
||||
uint32_t u = uint64_hi32 (den);
|
||||
uint32_t v = _cairo_uint64_to_uint32 (den);
|
||||
|
||||
/* Compute a lower bound approximate quotient of num/den
|
||||
* from x/(u+1). Then we have
|
||||
*
|
||||
* x = q(u+1) + r ; q : 32 bits, r <= u : 32 bits.
|
||||
*
|
||||
* xB + y = q(u+1)B + (rB+y)
|
||||
* = q(uB + B + v - v) + (rB+y)
|
||||
* = q(uB + v) + qB - qv + (rB+y)
|
||||
* = q(uB + v) + q(B-v) + (rB+y)
|
||||
*
|
||||
* The true quotient of num/den then is q plus the
|
||||
* contribution of q(B-v) + (rB+y). The main contribution
|
||||
* comes from the term q(B-v), with the term (rB+y) only
|
||||
* contributing at most one part.
|
||||
*
|
||||
* The term q(B-v) must fit into 64 bits, since q fits into 32
|
||||
* bits on account of being a lower bound to the true
|
||||
* quotient, and as B-v <= 2^32, we may safely use a single
|
||||
* 64/64 bit division to find its contribution. */
|
||||
|
||||
cairo_uquorem64_t quorem;
|
||||
cairo_uint64_t remainder; /* will contain final remainder */
|
||||
uint32_t quotient; /* will contain final quotient. */
|
||||
uint32_t q;
|
||||
uint32_t r;
|
||||
|
||||
/* Approximate quotient by dividing the high 64 bits of num by
|
||||
* u+1. Watch out for overflow of u+1. */
|
||||
if (u+1) {
|
||||
quorem = _cairo_uint64_divrem (x, _cairo_uint32_to_uint64 (u+1));
|
||||
q = _cairo_uint64_to_uint32 (quorem.quo);
|
||||
r = _cairo_uint64_to_uint32 (quorem.rem);
|
||||
}
|
||||
else {
|
||||
q = uint64_hi32 (x);
|
||||
r = _cairo_uint64_to_uint32 (x);
|
||||
}
|
||||
quotient = q;
|
||||
|
||||
/* Add the main term's contribution to quotient. Note B-v =
|
||||
* -v as an uint32 (unless v = 0) */
|
||||
if (v)
|
||||
quorem = _cairo_uint64_divrem (_cairo_uint32x32_64_mul (q, -v), den);
|
||||
else
|
||||
quorem = _cairo_uint64_divrem (_cairo_uint32s_to_uint64 (q, 0), den);
|
||||
quotient += _cairo_uint64_to_uint32 (quorem.quo);
|
||||
|
||||
/* Add the contribution of the subterm and start computing the
|
||||
* true remainder. */
|
||||
remainder = _cairo_uint32s_to_uint64 (r, y);
|
||||
if (_cairo_uint64_ge (remainder, den)) {
|
||||
remainder = _cairo_uint64_sub (remainder, den);
|
||||
quotient++;
|
||||
}
|
||||
|
||||
/* Add the contribution of the main term's remainder. The
|
||||
* funky test here checks that remainder + main_rem >= den,
|
||||
* taking into account overflow of the addition. */
|
||||
remainder = _cairo_uint64_add (remainder, quorem.rem);
|
||||
if (_cairo_uint64_ge (remainder, den) ||
|
||||
_cairo_uint64_lt (remainder, quorem.rem))
|
||||
{
|
||||
remainder = _cairo_uint64_sub (remainder, den);
|
||||
quotient++;
|
||||
}
|
||||
|
||||
result.quo = _cairo_uint32_to_uint64 (quotient);
|
||||
result.rem = remainder;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
cairo_quorem64_t
|
||||
_cairo_int_96by64_32x64_divrem (cairo_int128_t num, cairo_int64_t den)
|
||||
{
|
||||
int num_neg = _cairo_int128_negative (num);
|
||||
int den_neg = _cairo_int64_negative (den);
|
||||
cairo_int64_t nonneg_den = den;
|
||||
cairo_uquorem64_t uqr;
|
||||
cairo_quorem64_t qr;
|
||||
|
||||
if (num_neg)
|
||||
num = _cairo_int128_negate (num);
|
||||
if (den_neg)
|
||||
nonneg_den = _cairo_int64_negate (den);
|
||||
|
||||
uqr = _cairo_uint_96by64_32x64_divrem (num, nonneg_den);
|
||||
if (_cairo_uint64_eq (uqr.rem, nonneg_den)) {
|
||||
/* bail on overflow. */
|
||||
qr.quo = _cairo_uint32s_to_uint64 (0x7FFFFFFF, -1U);;
|
||||
qr.rem = den;
|
||||
return qr;
|
||||
}
|
||||
|
||||
if (num_neg)
|
||||
qr.rem = _cairo_int64_negate (uqr.rem);
|
||||
else
|
||||
qr.rem = uqr.rem;
|
||||
if (num_neg != den_neg)
|
||||
qr.quo = _cairo_int64_negate (uqr.quo);
|
||||
else
|
||||
qr.quo = uqr.quo;
|
||||
return qr;
|
||||
}
|
||||
|
|
|
@ -1,304 +0,0 @@
|
|||
/* cairo - a vector graphics library with display and print output
|
||||
*
|
||||
* Copyright © 2004 Keith Packard
|
||||
*
|
||||
* 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 Keith Packard
|
||||
*
|
||||
* Contributor(s):
|
||||
* Keith R. Packard <keithp@keithp.com>
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef CAIRO_WIDEINT_H
|
||||
#define CAIRO_WIDEINT_H
|
||||
|
||||
#if HAVE_STDINT_H
|
||||
# include <stdint.h>
|
||||
#elif HAVE_INTTYPES_H
|
||||
# include <inttypes.h>
|
||||
#elif HAVE_SYS_INT_TYPES_H
|
||||
# include <sys/int_types.h>
|
||||
#elif defined(_MSC_VER)
|
||||
typedef __int8 int8_t;
|
||||
typedef unsigned __int8 uint8_t;
|
||||
typedef __int16 int16_t;
|
||||
typedef unsigned __int16 uint16_t;
|
||||
typedef __int32 int32_t;
|
||||
typedef unsigned __int32 uint32_t;
|
||||
typedef __int64 int64_t;
|
||||
typedef unsigned __int64 uint64_t;
|
||||
# ifndef HAVE_UINT64_T
|
||||
# define HAVE_UINT64_T 1
|
||||
# endif
|
||||
#else
|
||||
#error Cannot find definitions for fixed-width integral types (uint8_t, uint32_t, etc.)
|
||||
#endif
|
||||
|
||||
/*
|
||||
* 64-bit datatypes. Two separate implementations, one using
|
||||
* built-in 64-bit signed/unsigned types another implemented
|
||||
* as a pair of 32-bit ints
|
||||
*/
|
||||
|
||||
#define I cairo_private
|
||||
|
||||
#if !HAVE_UINT64_T
|
||||
|
||||
typedef struct _cairo_uint64 {
|
||||
uint32_t lo, hi;
|
||||
} cairo_uint64_t, cairo_int64_t;
|
||||
|
||||
cairo_uint64_t I _cairo_uint32_to_uint64 (uint32_t i);
|
||||
#define _cairo_uint64_to_uint32(a) ((a).lo)
|
||||
cairo_uint64_t I _cairo_uint64_add (cairo_uint64_t a, cairo_uint64_t b);
|
||||
cairo_uint64_t I _cairo_uint64_sub (cairo_uint64_t a, cairo_uint64_t b);
|
||||
cairo_uint64_t I _cairo_uint64_mul (cairo_uint64_t a, cairo_uint64_t b);
|
||||
cairo_uint64_t I _cairo_uint32x32_64_mul (uint32_t a, uint32_t b);
|
||||
cairo_uint64_t I _cairo_uint64_lsl (cairo_uint64_t a, int shift);
|
||||
cairo_uint64_t I _cairo_uint64_rsl (cairo_uint64_t a, int shift);
|
||||
cairo_uint64_t I _cairo_uint64_rsa (cairo_uint64_t a, int shift);
|
||||
int I _cairo_uint64_lt (cairo_uint64_t a, cairo_uint64_t b);
|
||||
int I _cairo_uint64_eq (cairo_uint64_t a, cairo_uint64_t b);
|
||||
cairo_uint64_t I _cairo_uint64_negate (cairo_uint64_t a);
|
||||
#define _cairo_uint64_negative(a) (((int32_t) ((a).hi)) < 0)
|
||||
cairo_uint64_t I _cairo_uint64_not (cairo_uint64_t a);
|
||||
|
||||
#define _cairo_uint64_to_int64(i) (i)
|
||||
#define _cairo_int64_to_uint64(i) (i)
|
||||
|
||||
cairo_int64_t I _cairo_int32_to_int64(int32_t i);
|
||||
#define _cairo_int64_to_int32(a) ((int32_t) _cairo_uint64_to_uint32(a))
|
||||
#define _cairo_int64_add(a,b) _cairo_uint64_add (a,b)
|
||||
#define _cairo_int64_sub(a,b) _cairo_uint64_sub (a,b)
|
||||
#define _cairo_int64_mul(a,b) _cairo_uint64_mul (a,b)
|
||||
cairo_int64_t I _cairo_int32x32_64_mul (int32_t a, int32_t b);
|
||||
int I _cairo_int64_lt (cairo_uint64_t a, cairo_uint64_t b);
|
||||
#define _cairo_int64_eq(a,b) _cairo_uint64_eq (a,b)
|
||||
#define _cairo_int64_lsl(a,b) _cairo_uint64_lsl (a,b)
|
||||
#define _cairo_int64_rsl(a,b) _cairo_uint64_rsl (a,b)
|
||||
#define _cairo_int64_rsa(a,b) _cairo_uint64_rsa (a,b)
|
||||
#define _cairo_int64_negate(a) _cairo_uint64_negate(a)
|
||||
#define _cairo_int64_negative(a) (((int32_t) ((a).hi)) < 0)
|
||||
#define _cairo_int64_not(a) _cairo_uint64_not(a)
|
||||
|
||||
#else
|
||||
|
||||
typedef uint64_t cairo_uint64_t;
|
||||
typedef int64_t cairo_int64_t;
|
||||
|
||||
#define _cairo_uint32_to_uint64(i) ((uint64_t) (i))
|
||||
#define _cairo_uint64_to_uint32(i) ((uint32_t) (i))
|
||||
#define _cairo_uint64_add(a,b) ((a) + (b))
|
||||
#define _cairo_uint64_sub(a,b) ((a) - (b))
|
||||
#define _cairo_uint64_mul(a,b) ((a) * (b))
|
||||
#define _cairo_uint32x32_64_mul(a,b) ((uint64_t) (a) * (b))
|
||||
#define _cairo_uint64_lsl(a,b) ((a) << (b))
|
||||
#define _cairo_uint64_rsl(a,b) ((uint64_t) (a) >> (b))
|
||||
#define _cairo_uint64_rsa(a,b) ((uint64_t) ((int64_t) (a) >> (b)))
|
||||
#define _cairo_uint64_lt(a,b) ((a) < (b))
|
||||
#define _cairo_uint64_eq(a,b) ((a) == (b))
|
||||
#define _cairo_uint64_negate(a) ((uint64_t) -((int64_t) (a)))
|
||||
#define _cairo_uint64_negative(a) ((int64_t) (a) < 0)
|
||||
#define _cairo_uint64_not(a) (~(a))
|
||||
|
||||
#define _cairo_uint64_to_int64(i) ((int64_t) (i))
|
||||
#define _cairo_int64_to_uint64(i) ((uint64_t) (i))
|
||||
|
||||
#define _cairo_int32_to_int64(i) ((int64_t) (i))
|
||||
#define _cairo_int64_to_int32(i) ((int32_t) (i))
|
||||
#define _cairo_int64_add(a,b) ((a) + (b))
|
||||
#define _cairo_int64_sub(a,b) ((a) - (b))
|
||||
#define _cairo_int64_mul(a,b) ((a) * (b))
|
||||
#define _cairo_int32x32_64_mul(a,b) ((int64_t) (a) * (b))
|
||||
#define _cairo_int64_lt(a,b) ((a) < (b))
|
||||
#define _cairo_int64_eq(a,b) ((a) == (b))
|
||||
#define _cairo_int64_lsl(a,b) ((a) << (b))
|
||||
#define _cairo_int64_rsl(a,b) ((int64_t) ((uint64_t) (a) >> (b)))
|
||||
#define _cairo_int64_rsa(a,b) ((int64_t) (a) >> (b))
|
||||
#define _cairo_int64_negate(a) (-(a))
|
||||
#define _cairo_int64_negative(a) ((a) < 0)
|
||||
#define _cairo_int64_not(a) (~(a))
|
||||
|
||||
#endif
|
||||
|
||||
/*
|
||||
* 64-bit comparisions derived from lt or eq
|
||||
*/
|
||||
#define _cairo_uint64_le(a,b) (!_cairo_uint64_gt(a,b))
|
||||
#define _cairo_uint64_ne(a,b) (!_cairo_uint64_eq(a,b))
|
||||
#define _cairo_uint64_ge(a,b) (!_cairo_uint64_lt(a,b))
|
||||
#define _cairo_uint64_gt(a,b) _cairo_uint64_lt(b,a)
|
||||
|
||||
#define _cairo_int64_le(a,b) (!_cairo_int64_gt(a,b))
|
||||
#define _cairo_int64_ne(a,b) (!_cairo_int64_eq(a,b))
|
||||
#define _cairo_int64_ge(a,b) (!_cairo_int64_lt(a,b))
|
||||
#define _cairo_int64_gt(a,b) _cairo_int64_lt(b,a)
|
||||
|
||||
/*
|
||||
* As the C implementation always computes both, create
|
||||
* a function which returns both for the 'native' type as well
|
||||
*/
|
||||
|
||||
typedef struct _cairo_uquorem64 {
|
||||
cairo_uint64_t quo;
|
||||
cairo_uint64_t rem;
|
||||
} cairo_uquorem64_t;
|
||||
|
||||
typedef struct _cairo_quorem64 {
|
||||
cairo_int64_t quo;
|
||||
cairo_int64_t rem;
|
||||
} cairo_quorem64_t;
|
||||
|
||||
cairo_uquorem64_t I
|
||||
_cairo_uint64_divrem (cairo_uint64_t num, cairo_uint64_t den);
|
||||
|
||||
cairo_quorem64_t I
|
||||
_cairo_int64_divrem (cairo_int64_t num, cairo_int64_t den);
|
||||
|
||||
/*
|
||||
* 128-bit datatypes. Again, provide two implementations in
|
||||
* case the machine has a native 128-bit datatype. GCC supports int128_t
|
||||
* on ia64
|
||||
*/
|
||||
|
||||
#if !HAVE_UINT128_T
|
||||
|
||||
typedef struct cairo_uint128 {
|
||||
cairo_uint64_t lo, hi;
|
||||
} cairo_uint128_t, cairo_int128_t;
|
||||
|
||||
cairo_uint128_t I _cairo_uint32_to_uint128 (uint32_t i);
|
||||
cairo_uint128_t I _cairo_uint64_to_uint128 (cairo_uint64_t i);
|
||||
#define _cairo_uint128_to_uint64(a) ((a).lo)
|
||||
#define _cairo_uint128_to_uint32(a) _cairo_uint64_to_uint32(_cairo_uint128_to_uint64(a))
|
||||
cairo_uint128_t I _cairo_uint128_add (cairo_uint128_t a, cairo_uint128_t b);
|
||||
cairo_uint128_t I _cairo_uint128_sub (cairo_uint128_t a, cairo_uint128_t b);
|
||||
cairo_uint128_t I _cairo_uint128_mul (cairo_uint128_t a, cairo_uint128_t b);
|
||||
cairo_uint128_t I _cairo_uint64x64_128_mul (cairo_uint64_t a, cairo_uint64_t b);
|
||||
cairo_uint128_t I _cairo_uint128_lsl (cairo_uint128_t a, int shift);
|
||||
cairo_uint128_t I _cairo_uint128_rsl (cairo_uint128_t a, int shift);
|
||||
cairo_uint128_t I _cairo_uint128_rsa (cairo_uint128_t a, int shift);
|
||||
int I _cairo_uint128_lt (cairo_uint128_t a, cairo_uint128_t b);
|
||||
int I _cairo_uint128_eq (cairo_uint128_t a, cairo_uint128_t b);
|
||||
cairo_uint128_t I _cairo_uint128_negate (cairo_uint128_t a);
|
||||
#define _cairo_uint128_negative(a) (_cairo_uint64_negative(a.hi))
|
||||
cairo_uint128_t I _cairo_uint128_not (cairo_uint128_t a);
|
||||
|
||||
#define _cairo_uint128_to_int128_(i) (i)
|
||||
#define _cairo_int128_to_uint128(i) (i)
|
||||
|
||||
cairo_int128_t I _cairo_int32_to_int128 (int32_t i);
|
||||
cairo_int128_t I _cairo_int64_to_int128 (cairo_int64_t i);
|
||||
#define _cairo_int128_to_int64(a) ((cairo_int64_t) (a).lo)
|
||||
#define _cairo_int128_to_int32(a) _cairo_int64_to_int32(_cairo_int128_to_int64(a))
|
||||
#define _cairo_int128_add(a,b) _cairo_uint128_add(a,b)
|
||||
#define _cairo_int128_sub(a,b) _cairo_uint128_sub(a,b)
|
||||
#define _cairo_int128_mul(a,b) _cairo_uint128_mul(a,b)
|
||||
cairo_int128_t I _cairo_int64x64_128_mul (cairo_int64_t a, cairo_int64_t b);
|
||||
#define _cairo_int128_lsl(a,b) _cairo_uint128_lsl(a,b)
|
||||
#define _cairo_int128_rsl(a,b) _cairo_uint128_rsl(a,b)
|
||||
#define _cairo_int128_rsa(a,b) _cairo_uint128_rsa(a,b)
|
||||
int I _cairo_int128_lt (cairo_int128_t a, cairo_int128_t b);
|
||||
#define _cairo_int128_eq(a,b) _cairo_uint128_eq (a,b)
|
||||
#define _cairo_int128_negate(a) _cairo_uint128_negate(a)
|
||||
#define _cairo_int128_negative(a) (_cairo_uint128_negative(a))
|
||||
#define _cairo_int128_not(a) _cairo_uint128_not(a)
|
||||
|
||||
#else /* !HAVE_UINT128_T */
|
||||
|
||||
typedef uint128_t cairo_uint128_t;
|
||||
typedef int128_t cairo_int128_t;
|
||||
|
||||
#define _cairo_uint32_to_uint128(i) ((uint128_t) (i))
|
||||
#define _cairo_uint64_to_uint128(i) ((uint128_t) (i))
|
||||
#define _cairo_uint128_to_uint64(i) ((uint64_t) (i))
|
||||
#define _cairo_uint128_to_uint32(i) ((uint32_t) (i))
|
||||
#define _cairo_uint128_add(a,b) ((a) + (b))
|
||||
#define _cairo_uint128_sub(a,b) ((a) - (b))
|
||||
#define _cairo_uint128_mul(a,b) ((a) * (b))
|
||||
#define _cairo_uint64x64_128_mul(a,b) ((uint128_t) (a) * (b))
|
||||
#define _cairo_uint128_lsl(a,b) ((a) << (b))
|
||||
#define _cairo_uint128_rsl(a,b) ((uint128_t) (a) >> (b))
|
||||
#define _cairo_uint128_rsa(a,b) ((uint128_t) ((int128_t) (a) >> (b)))
|
||||
#define _cairo_uint128_lt(a,b) ((a) < (b))
|
||||
#define _cairo_uint128_eq(a,b) ((a) == (b))
|
||||
#define _cairo_uint128_negate(a) ((uint128_t) -((int128_t) (a)))
|
||||
#define _cairo_uint128_negative(a) ((int128_t) (a) < 0)
|
||||
#define _cairo_uint128_not(a) (~(a))
|
||||
|
||||
#define _cairo_uint128_to_int128(i) ((int128_t) (i))
|
||||
#define _cairo_int128_to_uint128(i) ((uint128_t) (i))
|
||||
|
||||
#define _cairo_int32_to_int128(i) ((int128_t) (i))
|
||||
#define _cairo_int64_to_int128(i) ((int128_t) (i))
|
||||
#define _cairo_int128_to_int64(i) ((int64_t) (i))
|
||||
#define _cairo_int128_to_int32(i) ((int32_t) (i))
|
||||
#define _cairo_int128_add(a,b) ((a) + (b))
|
||||
#define _cairo_int128_sub(a,b) ((a) - (b))
|
||||
#define _cairo_int128_mul(a,b) ((a) * (b))
|
||||
#define _cairo_int64x64_128_mul(a,b) ((int128_t) (a) * (b))
|
||||
#define _cairo_int128_lt(a,b) ((a) < (b))
|
||||
#define _cairo_int128_eq(a,b) ((a) == (b))
|
||||
#define _cairo_int128_lsl(a,b) ((a) << (b))
|
||||
#define _cairo_int128_rsl(a,b) ((int128_t) ((uint128_t) (a) >> (b)))
|
||||
#define _cairo_int128_rsa(a,b) ((int128_t) (a) >> (b))
|
||||
#define _cairo_int128_negate(a) (-(a))
|
||||
#define _cairo_int128_negative(a) ((a) < 0)
|
||||
#define _cairo_int128_not(a) (~(a))
|
||||
|
||||
#endif /* HAVE_UINT128_T */
|
||||
|
||||
typedef struct _cairo_uquorem128 {
|
||||
cairo_uint128_t quo;
|
||||
cairo_uint128_t rem;
|
||||
} cairo_uquorem128_t;
|
||||
|
||||
typedef struct _cairo_quorem128 {
|
||||
cairo_int128_t quo;
|
||||
cairo_int128_t rem;
|
||||
} cairo_quorem128_t;
|
||||
|
||||
cairo_uquorem128_t I
|
||||
_cairo_uint128_divrem (cairo_uint128_t num, cairo_uint128_t den);
|
||||
|
||||
cairo_quorem128_t I
|
||||
_cairo_int128_divrem (cairo_int128_t num, cairo_int128_t den);
|
||||
|
||||
#define _cairo_uint128_le(a,b) (!_cairo_uint128_gt(a,b))
|
||||
#define _cairo_uint128_ne(a,b) (!_cairo_uint128_eq(a,b))
|
||||
#define _cairo_uint128_ge(a,b) (!_cairo_uint128_lt(a,b))
|
||||
#define _cairo_uint128_gt(a,b) _cairo_uint128_lt(b,a)
|
||||
|
||||
#define _cairo_int128_le(a,b) (!_cairo_int128_gt(a,b))
|
||||
#define _cairo_int128_ne(a,b) (!_cairo_int128_eq(a,b))
|
||||
#define _cairo_int128_ge(a,b) (!_cairo_int128_lt(a,b))
|
||||
#define _cairo_int128_gt(a,b) _cairo_int128_lt(b,a)
|
||||
|
||||
#undef I
|
||||
|
||||
#endif /* CAIRO_WIDEINT_H */
|
|
@ -151,7 +151,8 @@ _compute_transform (cairo_win32_scaled_font_t *scaled_font,
|
|||
scaled_font->y_scale = - scaled_font->y_scale;
|
||||
|
||||
scaled_font->logical_scale = WIN32_FONT_LOGICAL_SCALE * scaled_font->y_scale;
|
||||
scaled_font->logical_size = WIN32_FONT_LOGICAL_SCALE * floor (scaled_font->y_scale + 0.5);
|
||||
scaled_font->logical_size = WIN32_FONT_LOGICAL_SCALE *
|
||||
_cairo_lround (scaled_font->y_scale);
|
||||
}
|
||||
|
||||
/* The font matrix has x and y "scale" components which we extract and
|
||||
|
@ -165,7 +166,8 @@ _compute_transform (cairo_win32_scaled_font_t *scaled_font,
|
|||
&scaled_font->x_scale, &scaled_font->y_scale,
|
||||
TRUE); /* XXX: Handle vertical text */
|
||||
|
||||
scaled_font->logical_size = floor (WIN32_FONT_LOGICAL_SCALE * scaled_font->y_scale + 0.5);
|
||||
scaled_font->logical_size = _cairo_lround (WIN32_FONT_LOGICAL_SCALE *
|
||||
scaled_font->y_scale);
|
||||
scaled_font->logical_scale = WIN32_FONT_LOGICAL_SCALE * scaled_font->y_scale;
|
||||
}
|
||||
|
||||
|
@ -864,8 +866,8 @@ _cairo_win32_scaled_font_glyph_bbox (void *abstract_font,
|
|||
glyph_index_option = 0;
|
||||
|
||||
for (i = 0; i < num_glyphs; i++) {
|
||||
int x = floor (0.5 + glyphs[i].x);
|
||||
int y = floor (0.5 + glyphs[i].y);
|
||||
int x = _cairo_lround (glyphs[i].x);
|
||||
int y = _cairo_lround (glyphs[i].y);
|
||||
|
||||
GetGlyphOutlineW (hdc, glyphs[i].index, GGO_METRICS | glyph_index_option,
|
||||
&metrics, 0, NULL, &matrix);
|
||||
|
@ -966,8 +968,8 @@ _add_glyph (cairo_glyph_state_t *state,
|
|||
|
||||
cairo_matrix_transform_point (&state->scaled_font->device_to_logical, &user_x, &user_y);
|
||||
|
||||
logical_x = floor (user_x + 0.5);
|
||||
logical_y = floor (user_y + 0.5);
|
||||
logical_x = _cairo_lround (user_x);
|
||||
logical_y = _cairo_lround (user_y);
|
||||
|
||||
if (state->glyphs.num_elements > 0) {
|
||||
int dx;
|
||||
|
@ -1149,7 +1151,7 @@ _cairo_win32_scaled_font_show_glyphs (void *abstract_font,
|
|||
int dest_y,
|
||||
unsigned int width,
|
||||
unsigned int height,
|
||||
const cairo_glyph_t *glyphs,
|
||||
cairo_glyph_t *glyphs,
|
||||
int num_glyphs)
|
||||
{
|
||||
cairo_win32_scaled_font_t *scaled_font = abstract_font;
|
||||
|
|
|
@ -106,6 +106,6 @@ cairo_bool_t
|
|||
_cairo_surface_is_win32 (cairo_surface_t *surface);
|
||||
|
||||
void
|
||||
_cairo_win32_initialize ();
|
||||
_cairo_win32_initialize (void);
|
||||
|
||||
#endif /* CAIRO_WIN32_PRIVATE_H */
|
||||
|
|
|
@ -1473,7 +1473,7 @@ static cairo_int_status_t
|
|||
_cairo_win32_surface_show_glyphs (void *surface,
|
||||
cairo_operator_t op,
|
||||
cairo_pattern_t *source,
|
||||
const cairo_glyph_t *glyphs,
|
||||
cairo_glyph_t *glyphs,
|
||||
int num_glyphs,
|
||||
cairo_scaled_font_t *scaled_font)
|
||||
{
|
||||
|
@ -1481,19 +1481,21 @@ _cairo_win32_surface_show_glyphs (void *surface,
|
|||
|
||||
WORD glyph_buf_stack[STACK_GLYPH_SIZE];
|
||||
WORD *glyph_buf = glyph_buf_stack;
|
||||
int dx_buf_stack[STACK_GLYPH_SIZE];
|
||||
int *dx_buf = dx_buf_stack;
|
||||
int dxy_buf_stack[2 * STACK_GLYPH_SIZE];
|
||||
int *dxy_buf = dxy_buf_stack;
|
||||
|
||||
BOOL win_result = 0;
|
||||
int i;
|
||||
double last_y = glyphs[0].y;
|
||||
int i, j;
|
||||
|
||||
cairo_solid_pattern_t *solid_pattern;
|
||||
COLORREF color;
|
||||
int output_count = 0;
|
||||
|
||||
cairo_matrix_t device_to_logical;
|
||||
|
||||
int start_x, start_y;
|
||||
double user_x, user_y;
|
||||
int logical_x, logical_y;
|
||||
|
||||
/* We can only handle win32 fonts */
|
||||
if (cairo_scaled_font_get_type (scaled_font) != CAIRO_FONT_TYPE_WIN32)
|
||||
return CAIRO_INT_STATUS_UNSUPPORTED;
|
||||
|
@ -1531,58 +1533,68 @@ _cairo_win32_surface_show_glyphs (void *surface,
|
|||
|
||||
if (num_glyphs > STACK_GLYPH_SIZE) {
|
||||
glyph_buf = (WORD *)malloc(num_glyphs * sizeof(WORD));
|
||||
dx_buf = (int *)malloc(num_glyphs * sizeof(int));
|
||||
dxy_buf = (int *)malloc(num_glyphs * 2 * sizeof(int));
|
||||
}
|
||||
|
||||
for (i = 0; i < num_glyphs; ++i) {
|
||||
output_count++;
|
||||
/* It is vital that dx values for dxy_buf are calculated from the delta of
|
||||
* _logical_ x coordinates (not user x coordinates) or else the sum of all
|
||||
* previous dx values may start to diverge from the current glyph's x
|
||||
* coordinate due to accumulated rounding error. As a result strings could
|
||||
* be painted shorter or longer than expected. */
|
||||
|
||||
glyph_buf[i] = (WORD) glyphs[i].index;
|
||||
if (i == num_glyphs - 1)
|
||||
dx_buf[i] = 0;
|
||||
else
|
||||
dx_buf[i] = (int) floor(((glyphs[i+1].x - glyphs[i].x) * WIN32_FONT_LOGICAL_SCALE) + 0.5);
|
||||
user_x = glyphs[0].x;
|
||||
user_y = glyphs[0].y;
|
||||
|
||||
if (i == num_glyphs - 1 || glyphs[i].y != glyphs[i+1].y) {
|
||||
const int offset = (i - output_count) + 1;
|
||||
double user_x = glyphs[offset].x;
|
||||
double user_y = last_y;
|
||||
int logical_x, logical_y;
|
||||
cairo_matrix_transform_point(&device_to_logical,
|
||||
&user_x, &user_y);
|
||||
|
||||
cairo_matrix_transform_point(&device_to_logical,
|
||||
&user_x, &user_y);
|
||||
logical_x = _cairo_lround (user_x);
|
||||
logical_y = _cairo_lround (user_y);
|
||||
|
||||
logical_x = (int) floor(user_x + 0.5);
|
||||
logical_y = (int) floor(user_y + 0.5);
|
||||
start_x = logical_x;
|
||||
start_y = logical_y;
|
||||
|
||||
win_result = ExtTextOutW(dst->dc,
|
||||
logical_x,
|
||||
logical_y,
|
||||
ETO_GLYPH_INDEX,
|
||||
NULL,
|
||||
glyph_buf + offset,
|
||||
output_count,
|
||||
dx_buf + offset);
|
||||
if (!win_result) {
|
||||
_cairo_win32_print_gdi_error("_cairo_win32_surface_show_glyphs(ExtTextOutW failed)");
|
||||
goto FAIL;
|
||||
}
|
||||
for (i = 0, j = 0; i < num_glyphs; ++i, j = 2 * i) {
|
||||
glyph_buf[i] = (WORD) glyphs[i].index;
|
||||
if (i == num_glyphs - 1) {
|
||||
dxy_buf[j] = 0;
|
||||
dxy_buf[j+1] = 0;
|
||||
} else {
|
||||
double next_user_x = glyphs[i+1].x;
|
||||
double next_user_y = glyphs[i+1].y;
|
||||
int next_logical_x, next_logical_y;
|
||||
|
||||
output_count = 0;
|
||||
cairo_matrix_transform_point(&device_to_logical,
|
||||
&next_user_x, &next_user_y);
|
||||
|
||||
if (i < num_glyphs - 1)
|
||||
last_y = glyphs[i+1].y;
|
||||
} else {
|
||||
last_y = glyphs[i].y;
|
||||
}
|
||||
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 ((logical_y - start_y) * WIN32_FONT_LOGICAL_SCALE);
|
||||
|
||||
logical_x = next_logical_x;
|
||||
logical_y = next_logical_y;
|
||||
}
|
||||
}
|
||||
|
||||
win_result = ExtTextOutW(dst->dc,
|
||||
start_x,
|
||||
start_y,
|
||||
ETO_GLYPH_INDEX | ETO_PDY,
|
||||
NULL,
|
||||
glyph_buf,
|
||||
num_glyphs,
|
||||
dxy_buf);
|
||||
if (!win_result) {
|
||||
_cairo_win32_print_gdi_error("_cairo_win32_surface_show_glyphs(ExtTextOutW failed)");
|
||||
}
|
||||
|
||||
FAIL:
|
||||
RestoreDC(dst->dc, -1);
|
||||
|
||||
if (glyph_buf != glyph_buf_stack) {
|
||||
free(glyph_buf);
|
||||
free(dx_buf);
|
||||
free(dxy_buf);
|
||||
}
|
||||
return (win_result) ? CAIRO_STATUS_SUCCESS : CAIRO_INT_STATUS_UNSUPPORTED;
|
||||
}
|
||||
|
|
|
@ -40,6 +40,16 @@
|
|||
|
||||
#if CAIRO_HAS_WIN32_SURFACE
|
||||
|
||||
#define WIN32_LEAN_AND_MEAN
|
||||
/* We require Windows 2000 features. Although we don't use them here, things
|
||||
* should still work if this header file ends up being the one to include
|
||||
* windows.h into a source file, so: */
|
||||
#if !defined(WINVER) || (WINVER < 0x0500)
|
||||
# define WINVER 0x0500
|
||||
#endif
|
||||
#if !defined(_WIN32_WINNT) || (_WIN32_WINNT < 0x0500)
|
||||
# define _WIN32_WINNT 0x0500
|
||||
#endif
|
||||
#include <windows.h>
|
||||
|
||||
CAIRO_BEGIN_DECLS
|
||||
|
|
Разница между файлами не показана из-за своего большого размера
Загрузить разницу
|
@ -41,16 +41,16 @@
|
|||
|
||||
#if CAIRO_HAS_XCB_SURFACE
|
||||
|
||||
#include <X11/XCB/xcb.h>
|
||||
#include <X11/XCB/render.h>
|
||||
#include <xcb/xcb.h>
|
||||
#include <xcb/render.h>
|
||||
|
||||
CAIRO_BEGIN_DECLS
|
||||
|
||||
cairo_public cairo_surface_t *
|
||||
cairo_xcb_surface_create_with_xrender_format (XCBConnection *c,
|
||||
XCBDRAWABLE drawable,
|
||||
XCBSCREEN *screen,
|
||||
XCBRenderPICTFORMINFO *format,
|
||||
cairo_xcb_surface_create_with_xrender_format (xcb_connection_t *c,
|
||||
xcb_drawable_t drawable,
|
||||
xcb_screen_t *screen,
|
||||
xcb_render_pictforminfo_t *format,
|
||||
int width,
|
||||
int height);
|
||||
|
||||
|
|
|
@ -41,21 +41,21 @@
|
|||
|
||||
#if CAIRO_HAS_XCB_SURFACE
|
||||
|
||||
#include <X11/XCB/xcb.h>
|
||||
#include <xcb/xcb.h>
|
||||
|
||||
CAIRO_BEGIN_DECLS
|
||||
|
||||
cairo_public cairo_surface_t *
|
||||
cairo_xcb_surface_create (XCBConnection *c,
|
||||
XCBDRAWABLE drawable,
|
||||
XCBVISUALTYPE *visual,
|
||||
cairo_xcb_surface_create (xcb_connection_t *c,
|
||||
xcb_drawable_t drawable,
|
||||
xcb_visualtype_t *visual,
|
||||
int width,
|
||||
int height);
|
||||
|
||||
cairo_public cairo_surface_t *
|
||||
cairo_xcb_surface_create_for_bitmap (XCBConnection *c,
|
||||
XCBPIXMAP bitmap,
|
||||
XCBSCREEN *screen,
|
||||
cairo_xcb_surface_create_for_bitmap (xcb_connection_t *c,
|
||||
xcb_pixmap_t bitmap,
|
||||
xcb_screen_t *screen,
|
||||
int width,
|
||||
int height);
|
||||
|
||||
|
|
|
@ -54,6 +54,7 @@ _cairo_xlib_screen_info_get (Display *display, Screen *screen);
|
|||
#if CAIRO_HAS_XLIB_XRENDER_SURFACE
|
||||
|
||||
#include "cairo-xlib-xrender.h"
|
||||
slim_hidden_proto (cairo_xlib_surface_create_with_xrender_format);
|
||||
|
||||
#endif
|
||||
|
||||
|
|
|
@ -33,6 +33,7 @@
|
|||
*
|
||||
* Contributor(s):
|
||||
* Carl D. Worth <cworth@cworth.org>
|
||||
* Behdad Esfahbod <behdad@behdad.org>
|
||||
*/
|
||||
|
||||
#include "cairoint.h"
|
||||
|
@ -69,7 +70,7 @@ static cairo_int_status_t
|
|||
_cairo_xlib_surface_show_glyphs (void *abstract_dst,
|
||||
cairo_operator_t op,
|
||||
cairo_pattern_t *src_pattern,
|
||||
const cairo_glyph_t *glyphs,
|
||||
cairo_glyph_t *glyphs,
|
||||
int num_glyphs,
|
||||
cairo_scaled_font_t *scaled_font);
|
||||
|
||||
|
@ -744,6 +745,10 @@ _cairo_xlib_surface_ensure_gc (cairo_xlib_surface_t *surface)
|
|||
static cairo_status_t
|
||||
_draw_image_surface (cairo_xlib_surface_t *surface,
|
||||
cairo_image_surface_t *image,
|
||||
int src_x,
|
||||
int src_y,
|
||||
int width,
|
||||
int height,
|
||||
int dst_x,
|
||||
int dst_y)
|
||||
{
|
||||
|
@ -774,8 +779,8 @@ _draw_image_surface (cairo_xlib_surface_t *surface,
|
|||
|
||||
_cairo_xlib_surface_ensure_gc (surface);
|
||||
XPutImage(surface->dpy, surface->drawable, surface->gc,
|
||||
&ximage, 0, 0, dst_x, dst_y,
|
||||
image->width, image->height);
|
||||
&ximage, src_x, src_y, dst_x, dst_y,
|
||||
width, height);
|
||||
|
||||
return CAIRO_STATUS_SUCCESS;
|
||||
|
||||
|
@ -839,7 +844,8 @@ _cairo_xlib_surface_release_dest_image (void *abstract_surfac
|
|||
cairo_xlib_surface_t *surface = abstract_surface;
|
||||
|
||||
/* ignore errors */
|
||||
_draw_image_surface (surface, image, image_rect->x, image_rect->y);
|
||||
_draw_image_surface (surface, image, 0, 0, image->width, image->height,
|
||||
image_rect->x, image_rect->y);
|
||||
|
||||
cairo_surface_destroy (&image->base);
|
||||
}
|
||||
|
@ -859,6 +865,10 @@ _cairo_xlib_surface_same_screen (cairo_xlib_surface_t *dst,
|
|||
static cairo_status_t
|
||||
_cairo_xlib_surface_clone_similar (void *abstract_surface,
|
||||
cairo_surface_t *src,
|
||||
int src_x,
|
||||
int src_y,
|
||||
int width,
|
||||
int height,
|
||||
cairo_surface_t **clone_out)
|
||||
{
|
||||
cairo_xlib_surface_t *surface = abstract_surface;
|
||||
|
@ -884,7 +894,8 @@ _cairo_xlib_surface_clone_similar (void *abstract_surface,
|
|||
if (clone->base.status)
|
||||
return CAIRO_STATUS_NO_MEMORY;
|
||||
|
||||
_draw_image_surface (clone, image_src, 0, 0);
|
||||
_draw_image_surface (clone, image_src, src_x, src_y,
|
||||
width, height, src_x, src_y);
|
||||
|
||||
*clone_out = &clone->base;
|
||||
|
||||
|
@ -2008,6 +2019,7 @@ cairo_xlib_surface_create_with_xrender_format (Display *dpy,
|
|||
return _cairo_xlib_surface_create_internal (dpy, drawable, screen,
|
||||
NULL, format, width, height, 0);
|
||||
}
|
||||
slim_hidden_def (cairo_xlib_surface_create_with_xrender_format);
|
||||
|
||||
/**
|
||||
* cairo_xlib_surface_set_size:
|
||||
|
@ -2397,12 +2409,12 @@ _cairo_xlib_surface_add_glyph (Display *dpy,
|
|||
*/
|
||||
|
||||
/* XXX: FRAGILE: We're ignore device_transform scaling here. A bug? */
|
||||
glyph_info.x = - (int) floor(glyph_surface->base.device_transform.x0 + 0.5);
|
||||
glyph_info.y = - (int) floor(glyph_surface->base.device_transform.y0 + 0.5);
|
||||
glyph_info.x = - _cairo_lround (glyph_surface->base.device_transform.x0);
|
||||
glyph_info.y = - _cairo_lround (glyph_surface->base.device_transform.y0);
|
||||
glyph_info.width = glyph_surface->width;
|
||||
glyph_info.height = glyph_surface->height;
|
||||
glyph_info.xOff = 0;
|
||||
glyph_info.yOff = 0;
|
||||
glyph_info.xOff = scaled_glyph->x_advance;
|
||||
glyph_info.yOff = scaled_glyph->y_advance;
|
||||
|
||||
data = glyph_surface->data;
|
||||
|
||||
|
@ -2485,200 +2497,301 @@ _cairo_xlib_surface_add_glyph (Display *dpy,
|
|||
return status;
|
||||
}
|
||||
|
||||
#define N_STACK_BUF 1024
|
||||
typedef void (*cairo_xrender_composite_text_func_t)
|
||||
(Display *dpy,
|
||||
int op,
|
||||
Picture src,
|
||||
Picture dst,
|
||||
_Xconst XRenderPictFormat *maskFormat,
|
||||
int xSrc,
|
||||
int ySrc,
|
||||
int xDst,
|
||||
int yDst,
|
||||
_Xconst XGlyphElt8 *elts,
|
||||
int nelt);
|
||||
|
||||
/* Build a struct of the same size of cairo_glyph_t that can be used both as
|
||||
* an input glyph with double coordinates, and as "working" glyph with
|
||||
* integer from-current-point offsets. */
|
||||
typedef struct {
|
||||
unsigned long index;
|
||||
union {
|
||||
struct {
|
||||
double x;
|
||||
double y;
|
||||
} d;
|
||||
struct {
|
||||
int x;
|
||||
int y;
|
||||
} i;
|
||||
} p;
|
||||
} cairo_xlib_glyph_t;
|
||||
|
||||
#define GLYPH_INDEX_SKIP ((unsigned long) -1)
|
||||
#define STACK_ELTS_LEN ((int) (CAIRO_STACK_BUFFER_SIZE / sizeof (XGlyphElt8)))
|
||||
|
||||
static cairo_status_t
|
||||
_cairo_xlib_surface_show_glyphs8 (cairo_xlib_surface_t *dst,
|
||||
cairo_operator_t op,
|
||||
cairo_xlib_surface_t *src,
|
||||
int src_x_offset, int src_y_offset,
|
||||
const cairo_glyph_t *glyphs,
|
||||
int num_glyphs,
|
||||
cairo_scaled_font_t *scaled_font)
|
||||
_cairo_xlib_surface_emit_glyphs_chunk (cairo_xlib_surface_t *dst,
|
||||
cairo_xlib_glyph_t *glyphs,
|
||||
int num_glyphs,
|
||||
int width,
|
||||
int num_elts,
|
||||
cairo_scaled_font_t *scaled_font,
|
||||
cairo_operator_t op,
|
||||
cairo_xlib_surface_t *src,
|
||||
cairo_surface_attributes_t *attributes)
|
||||
{
|
||||
cairo_xlib_surface_font_private_t *font_private = scaled_font->surface_private;
|
||||
XGlyphElt8 *elts = NULL;
|
||||
XGlyphElt8 stack_elts [N_STACK_BUF];
|
||||
/* Which XRenderCompositeText function to use */
|
||||
cairo_xrender_composite_text_func_t composite_text_func;
|
||||
int size;
|
||||
|
||||
char *chars = NULL;
|
||||
char stack_chars [N_STACK_BUF];
|
||||
/* Element buffer stuff */
|
||||
XGlyphElt8 *elts;
|
||||
XGlyphElt8 stack_elts[STACK_ELTS_LEN];
|
||||
|
||||
/* Reuse the input glyph array for output char generation */
|
||||
char *char8 = (char *) glyphs;
|
||||
unsigned short *char16 = (unsigned short *) glyphs;
|
||||
unsigned int *char32 = (unsigned int *) glyphs;
|
||||
|
||||
int i;
|
||||
int thisX, thisY;
|
||||
int lastX = 0, lastY = 0;
|
||||
int nelt; /* Element index */
|
||||
int n; /* Num output glyphs in current element */
|
||||
int j; /* Num output glyphs so far */
|
||||
|
||||
/* Acquire arrays of suitable sizes. */
|
||||
if (num_glyphs < N_STACK_BUF) {
|
||||
elts = stack_elts;
|
||||
chars = stack_chars;
|
||||
cairo_xlib_surface_font_private_t *font_private = scaled_font->surface_private;
|
||||
|
||||
switch (width) {
|
||||
case 1:
|
||||
/* don't cast the 8-variant, to catch possible mismatches */
|
||||
composite_text_func = XRenderCompositeText8;
|
||||
size = sizeof (char);
|
||||
break;
|
||||
case 2:
|
||||
composite_text_func = (cairo_xrender_composite_text_func_t) XRenderCompositeText16;
|
||||
size = sizeof (unsigned short);
|
||||
break;
|
||||
default:
|
||||
case 4:
|
||||
composite_text_func = (cairo_xrender_composite_text_func_t) XRenderCompositeText32;
|
||||
size = sizeof (unsigned int);
|
||||
}
|
||||
|
||||
/* Allocate element array */
|
||||
if (num_elts <= STACK_ELTS_LEN) {
|
||||
elts = stack_elts;
|
||||
} else {
|
||||
elts = malloc (num_glyphs * sizeof (XGlyphElt8) +
|
||||
num_glyphs * sizeof (unsigned char));
|
||||
if (elts == NULL)
|
||||
return CAIRO_STATUS_NO_MEMORY;
|
||||
|
||||
chars = (char *) (elts + num_glyphs);
|
||||
elts = malloc (num_elts * sizeof (XGlyphElt8));
|
||||
if (elts == NULL)
|
||||
return CAIRO_STATUS_NO_MEMORY;
|
||||
}
|
||||
|
||||
for (i = 0; i < num_glyphs; ++i) {
|
||||
chars[i] = glyphs[i].index;
|
||||
elts[i].chars = &(chars[i]);
|
||||
elts[i].nchars = 1;
|
||||
elts[i].glyphset = font_private->glyphset;
|
||||
thisX = (int) floor (glyphs[i].x + 0.5);
|
||||
thisY = (int) floor (glyphs[i].y + 0.5);
|
||||
elts[i].xOff = thisX - lastX;
|
||||
elts[i].yOff = thisY - lastY;
|
||||
lastX = thisX;
|
||||
lastY = thisY;
|
||||
/* Fill them in */
|
||||
nelt = 0;
|
||||
n = 0;
|
||||
j = 0;
|
||||
for (i = 0; i < num_glyphs; i++) {
|
||||
|
||||
/* Skip glyphs marked so */
|
||||
if (glyphs[i].index == GLYPH_INDEX_SKIP)
|
||||
continue;
|
||||
|
||||
/* Start a new element for first output glyph, and for glyphs with
|
||||
* unexpected position */
|
||||
if (!j || glyphs[i].p.i.x || glyphs[i].p.i.y) {
|
||||
if (j) {
|
||||
elts[nelt].nchars = n;
|
||||
nelt++;
|
||||
n = 0;
|
||||
}
|
||||
elts[nelt].chars = char8 + size * j;
|
||||
elts[nelt].glyphset = font_private->glyphset;
|
||||
elts[nelt].xOff = glyphs[i].p.i.x;
|
||||
elts[nelt].yOff = glyphs[i].p.i.y;
|
||||
}
|
||||
|
||||
switch (width) {
|
||||
case 1: char8 [j] = (char) glyphs[i].index; break;
|
||||
case 2: char16[j] = (unsigned short) glyphs[i].index; break;
|
||||
default:
|
||||
case 4: char32[j] = (unsigned int) glyphs[i].index; break;
|
||||
}
|
||||
|
||||
n++;
|
||||
j++;
|
||||
}
|
||||
|
||||
XRenderCompositeText8 (dst->dpy,
|
||||
_render_operator (op),
|
||||
src->src_picture,
|
||||
dst->dst_picture,
|
||||
font_private->xrender_format,
|
||||
src_x_offset + elts[0].xOff, src_y_offset + elts[0].yOff,
|
||||
elts[0].xOff, elts[0].yOff,
|
||||
elts, num_glyphs);
|
||||
if (n) {
|
||||
elts[nelt].nchars = n;
|
||||
nelt++;
|
||||
n = 0;
|
||||
}
|
||||
|
||||
composite_text_func (dst->dpy,
|
||||
_render_operator (op),
|
||||
src->src_picture,
|
||||
dst->dst_picture,
|
||||
font_private->xrender_format,
|
||||
attributes->x_offset + elts[0].xOff,
|
||||
attributes->y_offset + elts[0].yOff,
|
||||
elts[0].xOff, elts[0].yOff,
|
||||
(XGlyphElt8 *) elts, nelt);
|
||||
|
||||
if (elts != stack_elts)
|
||||
free (elts);
|
||||
free (elts);
|
||||
|
||||
return CAIRO_STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
static cairo_status_t
|
||||
_cairo_xlib_surface_show_glyphs16 (cairo_xlib_surface_t *dst,
|
||||
cairo_operator_t op,
|
||||
cairo_xlib_surface_t *src,
|
||||
int src_x_offset, int src_y_offset,
|
||||
const cairo_glyph_t *glyphs,
|
||||
int num_glyphs,
|
||||
cairo_scaled_font_t *scaled_font)
|
||||
{
|
||||
cairo_xlib_surface_font_private_t *font_private = scaled_font->surface_private;
|
||||
XGlyphElt16 *elts = NULL;
|
||||
XGlyphElt16 stack_elts [N_STACK_BUF];
|
||||
|
||||
unsigned short *chars = NULL;
|
||||
unsigned short stack_chars [N_STACK_BUF];
|
||||
|
||||
int i;
|
||||
int thisX, thisY;
|
||||
int lastX = 0, lastY = 0;
|
||||
|
||||
/* Acquire arrays of suitable sizes. */
|
||||
if (num_glyphs < N_STACK_BUF) {
|
||||
elts = stack_elts;
|
||||
chars = stack_chars;
|
||||
} else {
|
||||
elts = malloc (num_glyphs * sizeof (XGlyphElt16) +
|
||||
num_glyphs * sizeof (unsigned short));
|
||||
if (elts == NULL)
|
||||
return CAIRO_STATUS_NO_MEMORY;
|
||||
|
||||
chars = (unsigned short *) (elts + num_glyphs);
|
||||
}
|
||||
|
||||
for (i = 0; i < num_glyphs; ++i) {
|
||||
chars[i] = glyphs[i].index;
|
||||
elts[i].chars = &(chars[i]);
|
||||
elts[i].nchars = 1;
|
||||
elts[i].glyphset = font_private->glyphset;
|
||||
thisX = (int) floor (glyphs[i].x + 0.5);
|
||||
thisY = (int) floor (glyphs[i].y + 0.5);
|
||||
elts[i].xOff = thisX - lastX;
|
||||
elts[i].yOff = thisY - lastY;
|
||||
lastX = thisX;
|
||||
lastY = thisY;
|
||||
}
|
||||
|
||||
XRenderCompositeText16 (dst->dpy,
|
||||
_render_operator (op),
|
||||
src->src_picture,
|
||||
dst->dst_picture,
|
||||
font_private->xrender_format,
|
||||
src_x_offset + elts[0].xOff, src_y_offset + elts[0].yOff,
|
||||
elts[0].xOff, elts[0].yOff,
|
||||
elts, num_glyphs);
|
||||
|
||||
if (elts != stack_elts)
|
||||
free (elts);
|
||||
|
||||
return CAIRO_STATUS_SUCCESS;
|
||||
}
|
||||
#undef STACK_ELTS_LEN
|
||||
|
||||
static cairo_status_t
|
||||
_cairo_xlib_surface_show_glyphs32 (cairo_xlib_surface_t *dst,
|
||||
cairo_operator_t op,
|
||||
cairo_xlib_surface_t *src,
|
||||
int src_x_offset, int src_y_offset,
|
||||
const cairo_glyph_t *glyphs,
|
||||
int num_glyphs,
|
||||
cairo_scaled_font_t *scaled_font)
|
||||
_cairo_xlib_surface_emit_glyphs (cairo_xlib_surface_t *dst,
|
||||
cairo_xlib_glyph_t *glyphs,
|
||||
int num_glyphs,
|
||||
cairo_scaled_font_t *scaled_font,
|
||||
cairo_operator_t op,
|
||||
cairo_xlib_surface_t *src,
|
||||
cairo_surface_attributes_t *attributes)
|
||||
{
|
||||
cairo_xlib_surface_font_private_t *font_private = scaled_font->surface_private;
|
||||
XGlyphElt32 *elts = NULL;
|
||||
XGlyphElt32 stack_elts [N_STACK_BUF];
|
||||
|
||||
unsigned int *chars = NULL;
|
||||
unsigned int stack_chars [N_STACK_BUF];
|
||||
|
||||
int i;
|
||||
int thisX, thisY;
|
||||
int lastX = 0, lastY = 0;
|
||||
cairo_status_t status = CAIRO_STATUS_SUCCESS;
|
||||
cairo_scaled_glyph_t *scaled_glyph;
|
||||
cairo_fixed_t x = 0, y = 0;
|
||||
|
||||
/* Acquire arrays of suitable sizes. */
|
||||
if (num_glyphs < N_STACK_BUF) {
|
||||
elts = stack_elts;
|
||||
chars = stack_chars;
|
||||
} else {
|
||||
elts = malloc (num_glyphs * sizeof (XGlyphElt32) +
|
||||
num_glyphs * sizeof (unsigned int));
|
||||
if (elts == NULL)
|
||||
return CAIRO_STATUS_NO_MEMORY;
|
||||
unsigned long max_index = 0;
|
||||
int width = 1;
|
||||
int num_elts = 0;
|
||||
int num_out_glyphs = 0;
|
||||
|
||||
chars = (unsigned int *) (elts + num_glyphs);
|
||||
int max_request_size = XMaxRequestSize (dst->dpy)
|
||||
- MAX (sz_xRenderCompositeGlyphs8Req,
|
||||
MAX(sz_xRenderCompositeGlyphs16Req,
|
||||
sz_xRenderCompositeGlyphs32Req));
|
||||
int request_size = 0;
|
||||
|
||||
_cairo_xlib_surface_ensure_dst_picture (dst);
|
||||
|
||||
for (i = 0; i < num_glyphs; i++) {
|
||||
int this_x, this_y;
|
||||
int old_width;
|
||||
|
||||
status = _cairo_scaled_glyph_lookup (scaled_font,
|
||||
glyphs[i].index,
|
||||
CAIRO_SCALED_GLYPH_INFO_SURFACE |
|
||||
CAIRO_SCALED_GLYPH_INFO_METRICS,
|
||||
&scaled_glyph);
|
||||
if (status != CAIRO_STATUS_SUCCESS)
|
||||
return status;
|
||||
|
||||
this_x = _cairo_lround (glyphs[i].p.d.x);
|
||||
this_y = _cairo_lround (glyphs[i].p.d.y);
|
||||
|
||||
/* Glyph skipping:
|
||||
*
|
||||
* We skip any initial size-zero glyphs to avoid an X server bug (present
|
||||
* in at least Xorg 7.1 without EXA) which stops rendering glyphs after
|
||||
* the first zero-size glyph. However, we don't skip all size-zero
|
||||
* glyphs, since that will force a new element at every space. We
|
||||
* skip initial size-zero glyphs and hope that it's enough. Since
|
||||
* Xft never exposed that bug, this assumptation should be correct.
|
||||
*
|
||||
* We also skip any glyph that hav troublesome coordinates. We want
|
||||
* to make sure that (glyph2.x - (glyph1.x + glyph1.width)) fits in
|
||||
* a signed 16bit integer, otherwise it will overflow in the render
|
||||
* protocol.
|
||||
* To ensure this, we'll make sure that (glyph2.x - glyph1.x) fits in
|
||||
* a signed 15bit integer. The trivial option would be to allow
|
||||
* coordinates -8192..8192, but that's kinda dull. It probably will
|
||||
* take a decade or so to get monitors 8192x4096 or something. A
|
||||
* negative value of -8192 on the other hand, is absolutely useless.
|
||||
* Note that we do want to allow some negative positions. The glyph
|
||||
* may start off the screen but part of it make it to the screen.
|
||||
* Anyway, we will allow positions in the range -1024..15359. That
|
||||
* will buy us a few more years before this stops working.
|
||||
*/
|
||||
if ((!num_out_glyphs && !(scaled_glyph->surface->width && scaled_glyph->surface->height)) ||
|
||||
(((this_x+1024)|(this_y+1024))&~0x3fffu)) {
|
||||
glyphs[i].index = GLYPH_INDEX_SKIP;
|
||||
continue;
|
||||
}
|
||||
|
||||
old_width = width;
|
||||
|
||||
/* Update max glyph index */
|
||||
if (glyphs[i].index > max_index) {
|
||||
max_index = glyphs[i].index;
|
||||
if (max_index >= 65536)
|
||||
width = 4;
|
||||
else if (max_index >= 256)
|
||||
width = 2;
|
||||
if (width != old_width)
|
||||
request_size += (width - old_width) * num_out_glyphs;
|
||||
}
|
||||
|
||||
/* If we will pass the max request size by adding this glyph,
|
||||
* flush current glyphs. Note that we account for a
|
||||
* possible element being added below. */
|
||||
if (request_size + width > max_request_size - sz_xGlyphElt) {
|
||||
status = _cairo_xlib_surface_emit_glyphs_chunk (dst, glyphs, i,
|
||||
old_width, num_elts,
|
||||
scaled_font, op, src, attributes);
|
||||
if (status != CAIRO_STATUS_SUCCESS)
|
||||
return status;
|
||||
|
||||
glyphs += i;
|
||||
num_glyphs -= i;
|
||||
i = 0;
|
||||
max_index = glyphs[i].index;
|
||||
width = max_index < 256 ? 1 : max_index < 65536 ? 2 : 4;
|
||||
request_size = 0;
|
||||
num_elts = 0;
|
||||
num_out_glyphs = 0;
|
||||
x = y = 0;
|
||||
|
||||
}
|
||||
|
||||
/* Convert absolute glyph position to relative-to-current-point
|
||||
* position */
|
||||
glyphs[i].p.i.x = this_x - x;
|
||||
glyphs[i].p.i.y = this_y - y;
|
||||
|
||||
/* Start a new element for the first glyph, or for any glyph that
|
||||
* has unexpected position */
|
||||
if (!num_out_glyphs || glyphs[i].p.i.x || glyphs[i].p.i.y) {
|
||||
num_elts++;
|
||||
request_size += sz_xGlyphElt;
|
||||
}
|
||||
|
||||
/* Send unsent glyphs to the server */
|
||||
if (scaled_glyph->surface_private == NULL) {
|
||||
_cairo_xlib_surface_add_glyph (dst->dpy, scaled_font, scaled_glyph);
|
||||
scaled_glyph->surface_private = (void *) 1;
|
||||
}
|
||||
|
||||
/* adjust current-position */
|
||||
x = this_x + scaled_glyph->x_advance;
|
||||
y = this_y + scaled_glyph->y_advance;
|
||||
|
||||
num_out_glyphs++;
|
||||
request_size += width;
|
||||
}
|
||||
|
||||
for (i = 0; i < num_glyphs; ++i) {
|
||||
chars[i] = glyphs[i].index;
|
||||
elts[i].chars = &(chars[i]);
|
||||
elts[i].nchars = 1;
|
||||
elts[i].glyphset = font_private->glyphset;
|
||||
thisX = (int) floor (glyphs[i].x + 0.5);
|
||||
thisY = (int) floor (glyphs[i].y + 0.5);
|
||||
elts[i].xOff = thisX - lastX;
|
||||
elts[i].yOff = thisY - lastY;
|
||||
lastX = thisX;
|
||||
lastY = thisY;
|
||||
}
|
||||
if (num_elts)
|
||||
status = _cairo_xlib_surface_emit_glyphs_chunk (dst, glyphs, num_glyphs,
|
||||
width, num_elts,
|
||||
scaled_font, op, src, attributes);
|
||||
|
||||
XRenderCompositeText32 (dst->dpy,
|
||||
_render_operator (op),
|
||||
src->src_picture,
|
||||
dst->dst_picture,
|
||||
font_private->xrender_format,
|
||||
src_x_offset + elts[0].xOff, src_y_offset + elts[0].yOff,
|
||||
elts[0].xOff, elts[0].yOff,
|
||||
elts, num_glyphs);
|
||||
|
||||
if (elts != stack_elts)
|
||||
free (elts);
|
||||
|
||||
return CAIRO_STATUS_SUCCESS;
|
||||
return status;
|
||||
}
|
||||
|
||||
typedef cairo_status_t (*cairo_xlib_surface_show_glyphs_func_t)
|
||||
(cairo_xlib_surface_t *, cairo_operator_t, cairo_xlib_surface_t *, int, int,
|
||||
const cairo_glyph_t *, int, cairo_scaled_font_t *);
|
||||
#undef GLYPH_INDEX_SKIP
|
||||
|
||||
static cairo_int_status_t
|
||||
_cairo_xlib_surface_show_glyphs (void *abstract_dst,
|
||||
cairo_operator_t op,
|
||||
cairo_pattern_t *src_pattern,
|
||||
const cairo_glyph_t *glyphs,
|
||||
cairo_glyph_t *glyphs,
|
||||
int num_glyphs,
|
||||
cairo_scaled_font_t *scaled_font)
|
||||
{
|
||||
|
@ -2689,17 +2802,8 @@ _cairo_xlib_surface_show_glyphs (void *abstract_dst,
|
|||
cairo_surface_attributes_t attributes;
|
||||
cairo_xlib_surface_t *src = NULL;
|
||||
|
||||
cairo_glyph_t *output_glyphs;
|
||||
const cairo_glyph_t *glyphs_chunk;
|
||||
int glyphs_remaining, chunk_size, max_chunk_size;
|
||||
cairo_scaled_glyph_t *scaled_glyph;
|
||||
cairo_xlib_surface_font_private_t *font_private;
|
||||
|
||||
int i, o;
|
||||
unsigned long max_index = 0;
|
||||
|
||||
cairo_xlib_surface_show_glyphs_func_t show_glyphs_func;
|
||||
|
||||
cairo_pattern_union_t solid_pattern;
|
||||
|
||||
if (!CAIRO_SURFACE_RENDER_HAS_COMPOSITE_TEXT (dst) || !dst->xrender_format)
|
||||
|
@ -2739,13 +2843,6 @@ _cairo_xlib_surface_show_glyphs (void *abstract_dst,
|
|||
(font_private != NULL && font_private->dpy != dst->dpy))
|
||||
return CAIRO_INT_STATUS_UNSUPPORTED;
|
||||
|
||||
/* We make a copy of the glyphs so that we can elide any size-zero
|
||||
* glyphs to workaround an X server bug, (present in at least Xorg
|
||||
* 7.1 without EXA). */
|
||||
output_glyphs = malloc (num_glyphs * sizeof (cairo_glyph_t));
|
||||
if (output_glyphs == NULL)
|
||||
return CAIRO_STATUS_NO_MEMORY;
|
||||
|
||||
/* After passing all those tests, we're now committed to rendering
|
||||
* these glyphs or to fail trying. We first upload any glyphs to
|
||||
* the X server that it doesn't have already, then we draw
|
||||
|
@ -2803,60 +2900,11 @@ _cairo_xlib_surface_show_glyphs (void *abstract_dst,
|
|||
if (status)
|
||||
goto BAIL;
|
||||
|
||||
/* Send all unsent glyphs to the server, and count the max of the glyph indices */
|
||||
for (i = 0, o = 0; i < num_glyphs; i++) {
|
||||
if (glyphs[i].index > max_index)
|
||||
max_index = glyphs[i].index;
|
||||
status = _cairo_scaled_glyph_lookup (scaled_font,
|
||||
glyphs[i].index,
|
||||
CAIRO_SCALED_GLYPH_INFO_SURFACE,
|
||||
&scaled_glyph);
|
||||
if (status != CAIRO_STATUS_SUCCESS)
|
||||
goto BAIL;
|
||||
/* Don't put any size-zero glyphs into output_glyphs to avoid
|
||||
* an X server bug which stops rendering glyphs after the
|
||||
* first size-zero glyph. */
|
||||
if (scaled_glyph->surface->width && scaled_glyph->surface->height) {
|
||||
output_glyphs[o++] = glyphs[i];
|
||||
if (scaled_glyph->surface_private == NULL) {
|
||||
_cairo_xlib_surface_add_glyph (dst->dpy, scaled_font, scaled_glyph);
|
||||
scaled_glyph->surface_private = (void *) 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
num_glyphs = o;
|
||||
|
||||
_cairo_xlib_surface_ensure_dst_picture (dst);
|
||||
|
||||
max_chunk_size = XMaxRequestSize (dst->dpy);
|
||||
if (max_index < 256) {
|
||||
max_chunk_size -= sz_xRenderCompositeGlyphs8Req;
|
||||
show_glyphs_func = _cairo_xlib_surface_show_glyphs8;
|
||||
} else if (max_index < 65536) {
|
||||
max_chunk_size -= sz_xRenderCompositeGlyphs16Req;
|
||||
show_glyphs_func = _cairo_xlib_surface_show_glyphs16;
|
||||
} else {
|
||||
max_chunk_size -= sz_xRenderCompositeGlyphs32Req;
|
||||
show_glyphs_func = _cairo_xlib_surface_show_glyphs32;
|
||||
}
|
||||
max_chunk_size /= sz_xGlyphElt;
|
||||
|
||||
for (glyphs_remaining = num_glyphs, glyphs_chunk = output_glyphs;
|
||||
glyphs_remaining;
|
||||
glyphs_remaining -= chunk_size, glyphs_chunk += chunk_size)
|
||||
{
|
||||
chunk_size = MIN (glyphs_remaining, max_chunk_size);
|
||||
|
||||
status = show_glyphs_func (dst, op, src,
|
||||
attributes.x_offset, attributes.y_offset,
|
||||
glyphs_chunk, chunk_size, scaled_font);
|
||||
if (status != CAIRO_STATUS_SUCCESS)
|
||||
break;
|
||||
}
|
||||
_cairo_xlib_surface_emit_glyphs (dst, (cairo_xlib_glyph_t *) glyphs, num_glyphs,
|
||||
scaled_font, op, src, &attributes);
|
||||
|
||||
BAIL:
|
||||
_cairo_scaled_font_thaw_cache (scaled_font);
|
||||
free (output_glyphs);
|
||||
|
||||
if (src)
|
||||
_cairo_pattern_release_surface (src_pattern, &src->base, &attributes);
|
||||
|
|
|
@ -40,7 +40,7 @@
|
|||
#include "cairo-private.h"
|
||||
|
||||
#include "cairo-arc-private.h"
|
||||
#include "cairo-path-data-private.h"
|
||||
#include "cairo-path-private.h"
|
||||
|
||||
#define CAIRO_TOLERANCE_MINIMUM 0.0002 /* We're limited by 16 bits of sub-pixel precision */
|
||||
|
||||
|
@ -156,6 +156,7 @@ cairo_version_string (void)
|
|||
{
|
||||
return CAIRO_VERSION_STRING;
|
||||
}
|
||||
slim_hidden_def (cairo_version_string);
|
||||
|
||||
/**
|
||||
* cairo_create:
|
||||
|
@ -2007,18 +2008,21 @@ cairo_show_page (cairo_t *cr)
|
|||
* @x: X coordinate of the point to test
|
||||
* @y: Y coordinate of the point to test
|
||||
*
|
||||
* Tests whether the given point is on the area stroked by doing a
|
||||
* cairo_stroke() operation on @cr given the current path and stroking
|
||||
* parameters.
|
||||
* Tests whether the given point is inside the area that would be
|
||||
* affected by a cairo_stroke() operation given the current path and
|
||||
* stroking parameters.
|
||||
*
|
||||
* See cairo_stroke, cairo_set_line_width(), cairo_set_line_join(),
|
||||
* See cairo_stroke(), cairo_set_line_width(), cairo_set_line_join(),
|
||||
* cairo_set_line_cap(), cairo_set_dash(), and
|
||||
* cairo_stroke_preserve().
|
||||
*
|
||||
* Return value: A non-zero value if the point is inside, or zero if
|
||||
* outside.
|
||||
**/
|
||||
cairo_bool_t
|
||||
cairo_in_stroke (cairo_t *cr, double x, double y)
|
||||
{
|
||||
int inside;
|
||||
cairo_bool_t inside;
|
||||
|
||||
if (cr->status)
|
||||
return 0;
|
||||
|
@ -2038,16 +2042,19 @@ cairo_in_stroke (cairo_t *cr, double x, double y)
|
|||
* @x: X coordinate of the point to test
|
||||
* @y: Y coordinate of the point to test
|
||||
*
|
||||
* Tests whether the given point is on the area filled by doing a
|
||||
* cairo_stroke() operation on @cr given the current path and filling
|
||||
* parameters.
|
||||
* Tests whether the given point is inside the area that would be
|
||||
* affected by a cairo_fill() operation given the current path and
|
||||
* filling parameters.
|
||||
*
|
||||
* See cairo_fill(), cairo_set_fill_rule() and cairo_fill_preserve().
|
||||
*
|
||||
* Return value: A non-zero value if the point is inside, or zero if
|
||||
* outside.
|
||||
**/
|
||||
cairo_bool_t
|
||||
cairo_in_fill (cairo_t *cr, double x, double y)
|
||||
{
|
||||
int inside;
|
||||
cairo_bool_t inside;
|
||||
|
||||
if (cr->status)
|
||||
return 0;
|
||||
|
@ -2071,10 +2078,15 @@ cairo_in_fill (cairo_t *cr, double x, double y)
|
|||
* @x2: right of the resulting extents
|
||||
* @y2: bottom of the resulting extents
|
||||
*
|
||||
* Computes a bounding box in user coordinates covering all area that will
|
||||
* be stroked by the current path with the current stroking parameters. If
|
||||
* the current path is empty, returns an empty rectangle. Surface dimensions
|
||||
* and clipping are not taken into account.
|
||||
* Computes a bounding box in user coordinates covering the area that
|
||||
* would be affected by a cairo_stroke() operation operation given the
|
||||
* current path and stroke parameters. If the current path is empty,
|
||||
* returns an empty rectangle (0,0, 0,0). Surface dimensions and
|
||||
* clipping are not taken into account.
|
||||
*
|
||||
* See cairo_stroke(), cairo_set_line_width(), cairo_set_line_join(),
|
||||
* cairo_set_line_cap(), cairo_set_dash(), and
|
||||
* cairo_stroke_preserve().
|
||||
**/
|
||||
void
|
||||
cairo_stroke_extents (cairo_t *cr,
|
||||
|
@ -2098,10 +2110,13 @@ cairo_stroke_extents (cairo_t *cr,
|
|||
* @x2: right of the resulting extents
|
||||
* @y2: bottom of the resulting extents
|
||||
*
|
||||
* Computes a bounding box in user coordinates covering all area that will
|
||||
* be filled by the current path. If the current path is empty, returns an
|
||||
* empty rectangle. Surface dimensions and clipping are not taken into
|
||||
* account.
|
||||
* Computes a bounding box in user coordinates covering the area that
|
||||
* would be affected by a cairo_fill() operation given the current path
|
||||
* and fill parameters. If the current path is empty, returns an empty
|
||||
* rectangle (0,0, 0,0). Surface dimensions and clipping are not taken
|
||||
* into account.
|
||||
*
|
||||
* See cairo_fill(), cairo_set_fill_rule() and cairo_fill_preserve().
|
||||
**/
|
||||
void
|
||||
cairo_fill_extents (cairo_t *cr,
|
||||
|
@ -2218,6 +2233,8 @@ cairo_reset_clip (cairo_t *cr)
|
|||
*
|
||||
* Computes a bounding box in user coordinates covering the area inside the
|
||||
* current clip.
|
||||
*
|
||||
* Since: 1.4
|
||||
**/
|
||||
void
|
||||
cairo_clip_extents (cairo_t *cr,
|
||||
|
@ -2233,7 +2250,7 @@ cairo_clip_extents (cairo_t *cr,
|
|||
}
|
||||
|
||||
static cairo_rectangle_list_t *
|
||||
_cairo_rectangle_list_create_for_status (cairo_status_t status)
|
||||
_cairo_rectangle_list_create_in_error (cairo_status_t status)
|
||||
{
|
||||
cairo_rectangle_list_t *list;
|
||||
|
||||
|
@ -2259,12 +2276,14 @@ _cairo_rectangle_list_create_for_status (cairo_status_t status)
|
|||
*
|
||||
* The caller must always call cairo_rectangle_list_destroy on the result of
|
||||
* this function.
|
||||
*
|
||||
* Since: 1.4
|
||||
**/
|
||||
cairo_rectangle_list_t *
|
||||
cairo_copy_clip_rectangles (cairo_t *cr)
|
||||
{
|
||||
if (cr->status)
|
||||
return _cairo_rectangle_list_create_for_status (cr->status);
|
||||
return _cairo_rectangle_list_create_in_error (cr->status);
|
||||
|
||||
return _cairo_gstate_copy_clip_rectangles (cr->gstate);
|
||||
}
|
||||
|
@ -2594,7 +2613,7 @@ cairo_text_extents (cairo_t *cr,
|
|||
**/
|
||||
void
|
||||
cairo_glyph_extents (cairo_t *cr,
|
||||
cairo_glyph_t *glyphs,
|
||||
const cairo_glyph_t *glyphs,
|
||||
int num_glyphs,
|
||||
cairo_text_extents_t *extents)
|
||||
{
|
||||
|
@ -2730,7 +2749,7 @@ cairo_text_path (cairo_t *cr, const char *utf8)
|
|||
}
|
||||
|
||||
void
|
||||
cairo_glyph_path (cairo_t *cr, cairo_glyph_t *glyphs, int num_glyphs)
|
||||
cairo_glyph_path (cairo_t *cr, const cairo_glyph_t *glyphs, int num_glyphs)
|
||||
{
|
||||
if (cr->status)
|
||||
return;
|
||||
|
@ -2981,8 +3000,12 @@ cairo_get_group_target (cairo_t *cr)
|
|||
* conditions hold:
|
||||
*
|
||||
* <orderedlist>
|
||||
* <listitem>If there is insufficient memory to copy the path.</listitem>
|
||||
* <listitem>If @cr is already in an error state.</listitem>
|
||||
* <listitem>If there is insufficient memory to copy the path. In this
|
||||
* case <literal>path->status</literal> will be set to
|
||||
* %CAIRO_STATUS_NO_MEMORY.</listitem>
|
||||
* <listitem>If @cr is already in an error state. In this case
|
||||
* <literal>path->status</literal> will contain the same status that
|
||||
* would be returned by cairo_status().</listitem>
|
||||
* </orderedlist>
|
||||
*
|
||||
* In either case, <literal>path->status</literal> will be set to
|
||||
|
@ -2997,9 +3020,9 @@ cairo_path_t *
|
|||
cairo_copy_path (cairo_t *cr)
|
||||
{
|
||||
if (cr->status)
|
||||
return (cairo_path_t*) &_cairo_path_nil;
|
||||
return _cairo_path_create_in_error (cr->status);
|
||||
|
||||
return _cairo_path_data_create (&cr->path, cr->gstate);
|
||||
return _cairo_path_create (&cr->path, cr->gstate);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -3039,9 +3062,9 @@ cairo_path_t *
|
|||
cairo_copy_path_flat (cairo_t *cr)
|
||||
{
|
||||
if (cr->status)
|
||||
return (cairo_path_t*) &_cairo_path_nil;
|
||||
else
|
||||
return _cairo_path_data_create_flat (&cr->path, cr->gstate);
|
||||
return _cairo_path_create_in_error (cr->status);
|
||||
|
||||
return _cairo_path_create_flat (&cr->path, cr->gstate);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -3057,8 +3080,8 @@ cairo_copy_path_flat (cairo_t *cr)
|
|||
* initialized to %CAIRO_STATUS_SUCCESS.
|
||||
**/
|
||||
void
|
||||
cairo_append_path (cairo_t *cr,
|
||||
cairo_path_t *path)
|
||||
cairo_append_path (cairo_t *cr,
|
||||
const cairo_path_t *path)
|
||||
{
|
||||
if (cr->status)
|
||||
return;
|
||||
|
@ -3082,7 +3105,7 @@ cairo_append_path (cairo_t *cr,
|
|||
return;
|
||||
}
|
||||
|
||||
cr->status = _cairo_path_data_append_to_context (path, cr);
|
||||
cr->status = _cairo_path_append_to_context (path, cr);
|
||||
if (cr->status)
|
||||
_cairo_set_error (cr, cr->status);
|
||||
}
|
||||
|
@ -3173,3 +3196,214 @@ _cairo_restrict_value (double *value, double min, double max)
|
|||
else if (*value > max)
|
||||
*value = max;
|
||||
}
|
||||
|
||||
/* This function is identical to the C99 function lround(), except that it
|
||||
* performs arithmetic rounding (instead of away-from-zero rounding) and
|
||||
* has a valid input range of (INT_MIN, INT_MAX] instead of
|
||||
* [INT_MIN, INT_MAX]. It is much faster on both x86 and FPU-less systems
|
||||
* than other commonly used methods for rounding (lround, round, rint, lrint
|
||||
* or float (d + 0.5)).
|
||||
*
|
||||
* The reason why this function is much faster on x86 than other
|
||||
* methods is due to the fact that it avoids the fldcw instruction.
|
||||
* This instruction incurs a large performance penalty on modern Intel
|
||||
* processors due to how it prevents efficient instruction pipelining.
|
||||
*
|
||||
* The reason why this function is much faster on FPU-less systems is for
|
||||
* an entirely different reason. All common rounding methods involve multiple
|
||||
* floating-point operations. Each one of these operations has to be
|
||||
* emulated in software, which adds up to be a large performance penalty.
|
||||
* This function doesn't perform any floating-point calculations, and thus
|
||||
* avoids this penalty.
|
||||
*/
|
||||
int
|
||||
_cairo_lround (double d)
|
||||
{
|
||||
uint32_t top, shift_amount, output;
|
||||
union {
|
||||
double d;
|
||||
uint64_t ui64;
|
||||
uint32_t ui32[2];
|
||||
} u;
|
||||
|
||||
u.d = d;
|
||||
|
||||
/* If the integer word order doesn't match the float word order, we swap
|
||||
* the words of the input double. This is needed because we will be
|
||||
* treating the whole double as a 64-bit unsigned integer. Notice that we
|
||||
* use WORDS_BIGENDIAN to detect the integer word order, which isn't
|
||||
* exactly correct because WORDS_BIGENDIAN refers to byte order, not word
|
||||
* order. Thus, we are making the assumption that the byte order is the
|
||||
* same as the integer word order which, on the modern machines that we
|
||||
* care about, is OK.
|
||||
*/
|
||||
#if ( defined(FLOAT_WORDS_BIGENDIAN) && !defined(WORDS_BIGENDIAN)) || \
|
||||
(!defined(FLOAT_WORDS_BIGENDIAN) && defined(WORDS_BIGENDIAN))
|
||||
{
|
||||
uint32_t temp = u.ui32[0];
|
||||
u.ui32[0] = u.ui32[1];
|
||||
u.ui32[1] = temp;
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef WORDS_BIGENDIAN
|
||||
#define MSW (0) /* Most Significant Word */
|
||||
#define LSW (1) /* Least Significant Word */
|
||||
#else
|
||||
#define MSW (1)
|
||||
#define LSW (0)
|
||||
#endif
|
||||
|
||||
/* By shifting the most significant word of the input double to the
|
||||
* right 20 places, we get the very "top" of the double where the exponent
|
||||
* and sign bit lie.
|
||||
*/
|
||||
top = u.ui32[MSW] >> 20;
|
||||
|
||||
/* Here, we calculate how much we have to shift the mantissa to normalize
|
||||
* it to an integer value. We extract the exponent "top" by masking out the
|
||||
* sign bit, then we calculate the shift amount by subtracting the exponent
|
||||
* from the bias. Notice that the correct bias for 64-bit doubles is
|
||||
* actually 1075, but we use 1053 instead for two reasons:
|
||||
*
|
||||
* 1) To perform rounding later on, we will first need the target
|
||||
* value in a 31.1 fixed-point format. Thus, the bias needs to be one
|
||||
* less: (1075 - 1: 1074).
|
||||
*
|
||||
* 2) To avoid shifting the mantissa as a full 64-bit integer (which is
|
||||
* costly on certain architectures), we break the shift into two parts.
|
||||
* First, the upper and lower parts of the mantissa are shifted
|
||||
* individually by a constant amount that all valid inputs will require
|
||||
* at the very least. This amount is chosen to be 21, because this will
|
||||
* allow the two parts of the mantissa to later be combined into a
|
||||
* single 32-bit representation, on which the remainder of the shift
|
||||
* will be performed. Thus, we decrease the bias by an additional 21:
|
||||
* (1074 - 21: 1053).
|
||||
*/
|
||||
shift_amount = 1053 - (top & 0x7FF);
|
||||
|
||||
/* We are done with the exponent portion in "top", so here we shift it off
|
||||
* the end.
|
||||
*/
|
||||
top >>= 11;
|
||||
|
||||
/* Before we perform any operations on the mantissa, we need to OR in
|
||||
* the implicit 1 at the top (see the IEEE-754 spec). We needn't mask
|
||||
* off the sign bit nor the exponent bits because these higher bits won't
|
||||
* make a bit of difference in the rest of our calculations.
|
||||
*/
|
||||
u.ui32[MSW] |= 0x100000;
|
||||
|
||||
/* If the input double is negative, we have to decrease the mantissa
|
||||
* by a hair. This is an important part of performing arithmetic rounding,
|
||||
* as negative numbers must round towards positive infinity in the
|
||||
* halfwase case of -x.5. Since "top" contains only the sign bit at this
|
||||
* point, we can just decrease the mantissa by the value of "top".
|
||||
*/
|
||||
u.ui64 -= top;
|
||||
|
||||
/* By decrementing "top", we create a bitmask with a value of either
|
||||
* 0x0 (if the input was negative) or 0xFFFFFFFF (if the input was positive
|
||||
* and thus the unsigned subtraction underflowed) that we'll use later.
|
||||
*/
|
||||
top--;
|
||||
|
||||
/* Here, we shift the mantissa by the constant value as described above.
|
||||
* We can emulate a 64-bit shift right by 21 through shifting the top 32
|
||||
* bits left 11 places and ORing in the bottom 32 bits shifted 21 places
|
||||
* to the right. Both parts of the mantissa are now packed into a single
|
||||
* 32-bit integer. Although we severely truncate the lower part in the
|
||||
* process, we still have enough significant bits to perform the conversion
|
||||
* without error (for all valid inputs).
|
||||
*/
|
||||
output = (u.ui32[MSW] << 11) | (u.ui32[LSW] >> 21);
|
||||
|
||||
/* Next, we perform the shift that converts the X.Y fixed-point number
|
||||
* currently found in "output" to the desired 31.1 fixed-point format
|
||||
* needed for the following rounding step. It is important to consider
|
||||
* all possible values for "shift_amount" at this point:
|
||||
*
|
||||
* - {shift_amount < 0} Since shift_amount is an unsigned integer, it
|
||||
* really can't have a value less than zero. But, if the shift_amount
|
||||
* calculation above caused underflow (which would happen with
|
||||
* input > INT_MAX or input <= INT_MIN) then shift_amount will now be
|
||||
* a very large number, and so this shift will result in complete
|
||||
* garbage. But that's OK, as the input was out of our range, so our
|
||||
* output is undefined.
|
||||
*
|
||||
* - {shift_amount > 31} If the magnitude of the input was very small
|
||||
* (i.e. |input| << 1.0), shift_amount will have a value greater than
|
||||
* 31. Thus, this shift will also result in garbage. After performing
|
||||
* the shift, we will zero-out "output" if this is the case.
|
||||
*
|
||||
* - {0 <= shift_amount < 32} In this case, the shift will properly convert
|
||||
* the mantissa into a 31.1 fixed-point number.
|
||||
*/
|
||||
output >>= shift_amount;
|
||||
|
||||
/* This is where we perform rounding with the 31.1 fixed-point number.
|
||||
* Since what we're after is arithmetic rounding, we simply add the single
|
||||
* fractional bit into the integer part of "output", and just keep the
|
||||
* integer part.
|
||||
*/
|
||||
output = (output >> 1) + (output & 1);
|
||||
|
||||
/* Here, we zero-out the result if the magnitude if the input was very small
|
||||
* (as explained in the section above). Notice that all input out of the
|
||||
* valid range is also caught by this condition, which means we produce 0
|
||||
* for all invalid input, which is a nice side effect.
|
||||
*
|
||||
* The most straightforward way to do this would be:
|
||||
*
|
||||
* if (shift_amount > 31)
|
||||
* output = 0;
|
||||
*
|
||||
* But we can use a little trick to avoid the potential branch. The
|
||||
* expression (shift_amount > 31) will be either 1 or 0, which when
|
||||
* decremented will be either 0x0 or 0xFFFFFFFF (unsigned underflow),
|
||||
* which can be used to conditionally mask away all the bits in "output"
|
||||
* (in the 0x0 case), effectively zeroing it out. Certain, compilers would
|
||||
* have done this for us automatically.
|
||||
*/
|
||||
output &= ((shift_amount > 31) - 1);
|
||||
|
||||
/* If the input double was a negative number, then we have to negate our
|
||||
* output. The most straightforward way to do this would be:
|
||||
*
|
||||
* if (!top)
|
||||
* output = -output;
|
||||
*
|
||||
* as "top" at this point is either 0x0 (if the input was negative) or
|
||||
* 0xFFFFFFFF (if the input was positive). But, we can use a trick to
|
||||
* avoid the branch. Observe that the following snippet of code has the
|
||||
* same effect as the reference snippet above:
|
||||
*
|
||||
* if (!top)
|
||||
* output = 0 - output;
|
||||
* else
|
||||
* output = output - 0;
|
||||
*
|
||||
* Armed with the bitmask found in "top", we can condense the two statements
|
||||
* into the following:
|
||||
*
|
||||
* output = (output & top) - (output & ~top);
|
||||
*
|
||||
* where, in the case that the input double was negative, "top" will be 0,
|
||||
* and the statement will be equivalent to:
|
||||
*
|
||||
* output = (0) - (output);
|
||||
*
|
||||
* and if the input double was positive, "top" will be 0xFFFFFFFF, and the
|
||||
* statement will be equivalent to:
|
||||
*
|
||||
* output = (output) - (0);
|
||||
*
|
||||
* Which, as pointed out earlier, is equivalent to the original reference
|
||||
* snippet.
|
||||
*/
|
||||
output = (output & top) - (output & ~top);
|
||||
|
||||
return output;
|
||||
#undef MSW
|
||||
#undef LSW
|
||||
}
|
||||
|
|
|
@ -169,7 +169,7 @@ typedef struct _cairo_user_data_key {
|
|||
* @CAIRO_STATUS_FILE_NOT_FOUND: file not found
|
||||
* @CAIRO_STATUS_INVALID_DASH: invalid value for a dash setting
|
||||
* @CAIRO_STATUS_INVALID_DSC_COMMENT: invalid value for a DSC comment (Since 1.2)
|
||||
* @CAIRO_STATUS_INVALID_INDEX: invalid index passed to getter
|
||||
* @CAIRO_STATUS_INVALID_INDEX: invalid index passed to getter (Since 1.4)
|
||||
* @CAIRO_STATUS_CLIP_NOT_REPRESENTABLE: clip region not representable in desired format (Since 1.4)
|
||||
*
|
||||
* #cairo_status_t is used to indicate errors that can occur when
|
||||
|
@ -600,6 +600,8 @@ cairo_clip_extents (cairo_t *cr,
|
|||
* cairo_rectangle_t:
|
||||
*
|
||||
* A data structure for holding a rectangle.
|
||||
*
|
||||
* Since: 1.4
|
||||
*/
|
||||
typedef struct _cairo_rectangle {
|
||||
double x, y, width, height;
|
||||
|
@ -610,6 +612,8 @@ typedef struct _cairo_rectangle {
|
|||
*
|
||||
* A data structure for holding a dynamically allocated
|
||||
* array of rectangles.
|
||||
*
|
||||
* Since: 1.4
|
||||
*/
|
||||
typedef struct _cairo_rectangle_list {
|
||||
cairo_status_t status;
|
||||
|
@ -950,7 +954,7 @@ cairo_text_extents (cairo_t *cr,
|
|||
|
||||
cairo_public void
|
||||
cairo_glyph_extents (cairo_t *cr,
|
||||
cairo_glyph_t *glyphs,
|
||||
const cairo_glyph_t *glyphs,
|
||||
int num_glyphs,
|
||||
cairo_text_extents_t *extents);
|
||||
|
||||
|
@ -958,7 +962,7 @@ cairo_public void
|
|||
cairo_text_path (cairo_t *cr, const char *utf8);
|
||||
|
||||
cairo_public void
|
||||
cairo_glyph_path (cairo_t *cr, cairo_glyph_t *glyphs, int num_glyphs);
|
||||
cairo_glyph_path (cairo_t *cr, const cairo_glyph_t *glyphs, int num_glyphs);
|
||||
|
||||
/* Generic identifier for a font style */
|
||||
|
||||
|
@ -1058,7 +1062,7 @@ cairo_scaled_font_text_extents (cairo_scaled_font_t *scaled_font,
|
|||
|
||||
cairo_public void
|
||||
cairo_scaled_font_glyph_extents (cairo_scaled_font_t *scaled_font,
|
||||
cairo_glyph_t *glyphs,
|
||||
const cairo_glyph_t *glyphs,
|
||||
int num_glyphs,
|
||||
cairo_text_extents_t *extents);
|
||||
|
||||
|
@ -1233,8 +1237,8 @@ cairo_public cairo_path_t *
|
|||
cairo_copy_path_flat (cairo_t *cr);
|
||||
|
||||
cairo_public void
|
||||
cairo_append_path (cairo_t *cr,
|
||||
cairo_path_t *path);
|
||||
cairo_append_path (cairo_t *cr,
|
||||
const cairo_path_t *path);
|
||||
|
||||
cairo_public void
|
||||
cairo_path_destroy (cairo_path_t *path);
|
||||
|
@ -1672,9 +1676,9 @@ cairo_matrix_transform_point (const cairo_matrix_t *matrix,
|
|||
|
||||
cairo_public void
|
||||
cairo_matrix_transform_bounding_box (const cairo_matrix_t *matrix,
|
||||
double *x, double *y,
|
||||
double *width, double *height,
|
||||
cairo_bool_t *is_tight);
|
||||
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
|
||||
|
|
|
@ -67,6 +67,7 @@
|
|||
|
||||
#ifdef _MSC_VER
|
||||
#define snprintf _snprintf
|
||||
#undef inline
|
||||
#define inline __inline
|
||||
#endif
|
||||
|
||||
|
@ -89,8 +90,8 @@ CAIRO_BEGIN_DECLS
|
|||
# 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)
|
||||
# define slim_hidden_proto(name) int _cairo_dummy_prototype(void)
|
||||
# define slim_hidden_def(name) int _cairo_dummy_prototype(void)
|
||||
#endif
|
||||
|
||||
#if __GNUC__ > 2 || (__GNUC__ == 2 && __GNUC_MINOR__ > 4)
|
||||
|
@ -133,12 +134,6 @@ CAIRO_BEGIN_DECLS
|
|||
#define __attribute__(x)
|
||||
#endif
|
||||
|
||||
#if defined(__GNUC__)
|
||||
#define INLINE __inline__
|
||||
#else
|
||||
#define INLINE
|
||||
#endif
|
||||
|
||||
#if 0
|
||||
#if HAVE_PTHREAD_H
|
||||
# include <pthread.h>
|
||||
|
@ -149,11 +144,15 @@ CAIRO_BEGIN_DECLS
|
|||
#endif
|
||||
|
||||
#if !defined(CAIRO_MUTEX_DECLARE) && defined CAIRO_HAS_WIN32_SURFACE
|
||||
# ifndef WIN32_LEAN_AND_MEAN
|
||||
# define WIN32_LEAN_AND_MEAN
|
||||
# define WIN32_LEAN_AND_MEAN
|
||||
/* We require Windows 2000 features. Although we don't use them here, things
|
||||
* should still work if this header file ends up being the one to include
|
||||
* windows.h into a source file, so: */
|
||||
# if !defined(WINVER) || (WINVER < 0x0500)
|
||||
# define WINVER 0x0500
|
||||
# endif
|
||||
# ifndef WINVER
|
||||
# define WINVER 0xFFFFF /* use newest and greatest */
|
||||
# if !defined(_WIN32_WINNT) || (_WIN32_WINNT < 0x0500)
|
||||
# define _WIN32_WINNT 0x0500
|
||||
# endif
|
||||
# include <windows.h>
|
||||
/* the real initialization must take place in DllMain */
|
||||
|
@ -210,6 +209,13 @@ cairo_private void _cairo_beos_unlock(void*);
|
|||
#define M_PI 3.14159265358979323846
|
||||
#endif
|
||||
|
||||
/* Size in bytes of buffer to use off the stack per functions.
|
||||
* Mostly used by text functions. For larger allocations, they'll
|
||||
* malloc(). */
|
||||
#ifndef CAIRO_STACK_BUFFER_SIZE
|
||||
#define CAIRO_STACK_BUFFER_SIZE (512 * sizeof (int))
|
||||
#endif
|
||||
|
||||
#define ASSERT_NOT_REACHED \
|
||||
do { \
|
||||
static const int NOT_REACHED = 0; \
|
||||
|
@ -506,6 +512,8 @@ typedef struct _cairo_scaled_glyph {
|
|||
cairo_scaled_font_t *scaled_font; /* font the glyph lives in */
|
||||
cairo_text_extents_t metrics; /* user-space metrics */
|
||||
cairo_box_t bbox; /* device-space bounds */
|
||||
int16_t x_advance; /* device-space rounded X advance */
|
||||
int16_t y_advance; /* device-space rounded Y advance */
|
||||
cairo_image_surface_t *surface; /* device-space image */
|
||||
cairo_path_fixed_t *path; /* device-space outline */
|
||||
void *surface_private; /* for the surface backend */
|
||||
|
@ -634,7 +642,7 @@ struct _cairo_scaled_font_backend {
|
|||
int dest_y,
|
||||
unsigned int width,
|
||||
unsigned int height,
|
||||
const cairo_glyph_t *glyphs,
|
||||
cairo_glyph_t *glyphs,
|
||||
int num_glyphs);
|
||||
|
||||
cairo_int_status_t
|
||||
|
@ -727,9 +735,23 @@ struct _cairo_surface_backend {
|
|||
cairo_rectangle_int16_t *image_rect,
|
||||
void *image_extra);
|
||||
|
||||
/* Create a new surface (@clone_out) with the following
|
||||
* characteristics:
|
||||
*
|
||||
* 1. It is as compatible as possible with @surface (in terms of
|
||||
* efficiency)
|
||||
*
|
||||
* 2. It has the same size as @src
|
||||
*
|
||||
* 3. It has the same contents as @src within the given rectangle.
|
||||
*/
|
||||
cairo_status_t
|
||||
(*clone_similar) (void *surface,
|
||||
cairo_surface_t *src,
|
||||
int src_x,
|
||||
int src_y,
|
||||
int width,
|
||||
int height,
|
||||
cairo_surface_t **clone_out);
|
||||
|
||||
/* XXX: dst should be the first argument for consistency */
|
||||
|
@ -843,7 +865,7 @@ struct _cairo_surface_backend {
|
|||
int dest_y,
|
||||
unsigned int width,
|
||||
unsigned int height,
|
||||
const cairo_glyph_t *glyphs,
|
||||
cairo_glyph_t *glyphs,
|
||||
int num_glyphs);
|
||||
|
||||
void
|
||||
|
@ -905,7 +927,7 @@ struct _cairo_surface_backend {
|
|||
(*show_glyphs) (void *surface,
|
||||
cairo_operator_t op,
|
||||
cairo_pattern_t *source,
|
||||
const cairo_glyph_t *glyphs,
|
||||
cairo_glyph_t *glyphs,
|
||||
int num_glyphs,
|
||||
cairo_scaled_font_t *scaled_font);
|
||||
|
||||
|
@ -1086,6 +1108,8 @@ typedef struct _cairo_surface_attributes {
|
|||
} cairo_surface_attributes_t;
|
||||
|
||||
typedef struct _cairo_traps {
|
||||
cairo_status_t status;
|
||||
|
||||
cairo_trapezoid_t *traps;
|
||||
int num_traps;
|
||||
int traps_size;
|
||||
|
@ -1141,6 +1165,9 @@ typedef struct _cairo_stroke_face {
|
|||
cairo_private void
|
||||
_cairo_restrict_value (double *value, double min, double max);
|
||||
|
||||
cairo_private int
|
||||
_cairo_lround (double d);
|
||||
|
||||
/* cairo_fixed.c */
|
||||
cairo_private cairo_fixed_t
|
||||
_cairo_fixed_from_int (int i);
|
||||
|
@ -1411,7 +1438,7 @@ _cairo_gstate_text_to_glyphs (cairo_gstate_t *font,
|
|||
|
||||
cairo_private cairo_status_t
|
||||
_cairo_gstate_glyph_extents (cairo_gstate_t *gstate,
|
||||
cairo_glyph_t *glyphs,
|
||||
const cairo_glyph_t *glyphs,
|
||||
int num_glyphs,
|
||||
cairo_text_extents_t *extents);
|
||||
|
||||
|
@ -1421,10 +1448,10 @@ _cairo_gstate_show_glyphs (cairo_gstate_t *gstate,
|
|||
int num_glyphs);
|
||||
|
||||
cairo_private cairo_status_t
|
||||
_cairo_gstate_glyph_path (cairo_gstate_t *gstate,
|
||||
cairo_glyph_t *glyphs,
|
||||
int num_glyphs,
|
||||
cairo_path_fixed_t *path);
|
||||
_cairo_gstate_glyph_path (cairo_gstate_t *gstate,
|
||||
const cairo_glyph_t *glyphs,
|
||||
int num_glyphs,
|
||||
cairo_path_fixed_t *path);
|
||||
|
||||
cairo_private cairo_bool_t
|
||||
_cairo_operator_bounded_by_mask (cairo_operator_t op);
|
||||
|
@ -1667,12 +1694,6 @@ _cairo_scaled_font_text_to_glyphs (cairo_scaled_font_t *scaled_font,
|
|||
cairo_glyph_t **glyphs,
|
||||
int *num_glyphs);
|
||||
|
||||
cairo_private cairo_status_t
|
||||
_cairo_scaled_font_glyph_extents (cairo_scaled_font_t *scaled_font,
|
||||
cairo_glyph_t *glyphs,
|
||||
int num_glyphs,
|
||||
cairo_text_extents_t *extents);
|
||||
|
||||
cairo_private cairo_status_t
|
||||
_cairo_scaled_font_glyph_device_extents (cairo_scaled_font_t *scaled_font,
|
||||
const cairo_glyph_t *glyphs,
|
||||
|
@ -1690,7 +1711,7 @@ _cairo_scaled_font_show_glyphs (cairo_scaled_font_t *scaled_font,
|
|||
int dest_y,
|
||||
unsigned int width,
|
||||
unsigned int height,
|
||||
const cairo_glyph_t *glyphs,
|
||||
cairo_glyph_t *glyphs,
|
||||
int num_glyphs);
|
||||
|
||||
cairo_private cairo_status_t
|
||||
|
@ -1841,7 +1862,7 @@ cairo_private cairo_status_t
|
|||
_cairo_surface_show_glyphs (cairo_surface_t *surface,
|
||||
cairo_operator_t op,
|
||||
cairo_pattern_t *source,
|
||||
const cairo_glyph_t *glyphs,
|
||||
cairo_glyph_t *glyphs,
|
||||
int num_glyphs,
|
||||
cairo_scaled_font_t *scaled_font);
|
||||
|
||||
|
@ -1892,6 +1913,10 @@ _cairo_surface_release_dest_image (cairo_surface_t *surface,
|
|||
cairo_private cairo_status_t
|
||||
_cairo_surface_clone_similar (cairo_surface_t *surface,
|
||||
cairo_surface_t *src,
|
||||
int src_x,
|
||||
int src_y,
|
||||
int width,
|
||||
int height,
|
||||
cairo_surface_t **clone_out);
|
||||
|
||||
cairo_private cairo_surface_t *
|
||||
|
@ -1936,7 +1961,7 @@ _cairo_surface_old_show_glyphs (cairo_scaled_font_t *scaled_font,
|
|||
int dest_y,
|
||||
unsigned int width,
|
||||
unsigned int height,
|
||||
const cairo_glyph_t *glyphs,
|
||||
cairo_glyph_t *glyphs,
|
||||
int num_glyphs);
|
||||
|
||||
cairo_private cairo_status_t
|
||||
|
@ -2160,12 +2185,6 @@ _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 *x, double *y,
|
||||
double *width, double *height,
|
||||
cairo_bool_t *is_tight);
|
||||
|
||||
cairo_private void
|
||||
_cairo_matrix_compute_determinant (const cairo_matrix_t *matrix, double *det);
|
||||
|
||||
|
@ -2176,6 +2195,9 @@ _cairo_matrix_compute_scale_factors (const cairo_matrix_t *matrix,
|
|||
cairo_private cairo_bool_t
|
||||
_cairo_matrix_is_identity (const cairo_matrix_t *matrix);
|
||||
|
||||
cairo_private cairo_bool_t
|
||||
_cairo_matrix_is_translation (const cairo_matrix_t *matrix);
|
||||
|
||||
cairo_private cairo_bool_t
|
||||
_cairo_matrix_is_integer_translation(const cairo_matrix_t *matrix,
|
||||
int *itx, int *ity);
|
||||
|
@ -2205,13 +2227,23 @@ cairo_private cairo_status_t
|
|||
_cairo_traps_tessellate_triangle (cairo_traps_t *traps, cairo_point_t t[3]);
|
||||
|
||||
cairo_private cairo_status_t
|
||||
_cairo_traps_tessellate_rectangle (cairo_traps_t *traps, cairo_point_t q[4]);
|
||||
_cairo_traps_tessellate_convex_quad (cairo_traps_t *traps, cairo_point_t q[4]);
|
||||
|
||||
cairo_private cairo_status_t
|
||||
_cairo_traps_tessellate_polygon (cairo_traps_t *traps,
|
||||
cairo_polygon_t *poly,
|
||||
cairo_fill_rule_t fill_rule);
|
||||
|
||||
cairo_private cairo_status_t
|
||||
_cairo_traps_add_trap_from_points (cairo_traps_t *traps, cairo_fixed_t top, cairo_fixed_t bottom,
|
||||
cairo_point_t left_p1, cairo_point_t left_p2,
|
||||
cairo_point_t right_p1, cairo_point_t right_p2);
|
||||
|
||||
cairo_private cairo_status_t
|
||||
_cairo_bentley_ottmann_tessellate_polygon (cairo_traps_t *traps,
|
||||
cairo_polygon_t *polygon,
|
||||
cairo_fill_rule_t fill_rule);
|
||||
|
||||
cairo_private int
|
||||
_cairo_traps_contain (cairo_traps_t *traps, double x, double y);
|
||||
|
||||
|
@ -2401,6 +2433,7 @@ slim_hidden_proto (cairo_pattern_get_extend);
|
|||
slim_hidden_proto (cairo_pattern_get_type);
|
||||
slim_hidden_proto (cairo_pattern_reference);
|
||||
slim_hidden_proto (cairo_pattern_set_matrix);
|
||||
slim_hidden_proto (cairo_pattern_status);
|
||||
slim_hidden_proto (cairo_pop_group);
|
||||
slim_hidden_proto (cairo_pop_group_to_source);
|
||||
slim_hidden_proto (cairo_push_group);
|
||||
|
@ -2435,6 +2468,7 @@ 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);
|
||||
|
||||
CAIRO_END_DECLS
|
||||
|
||||
|
|
|
@ -247,7 +247,7 @@ static cairo_int_status_t
|
|||
_test_meta_surface_show_glyphs (void *abstract_surface,
|
||||
cairo_operator_t op,
|
||||
cairo_pattern_t *source,
|
||||
const cairo_glyph_t *glyphs,
|
||||
cairo_glyph_t *glyphs,
|
||||
int num_glyphs,
|
||||
cairo_scaled_font_t *scaled_font)
|
||||
{
|
||||
|
|
|
@ -228,7 +228,7 @@ static cairo_int_status_t
|
|||
_test_paginated_surface_show_glyphs (void *abstract_surface,
|
||||
cairo_operator_t op,
|
||||
cairo_pattern_t *source,
|
||||
const cairo_glyph_t *glyphs,
|
||||
cairo_glyph_t *glyphs,
|
||||
int num_glyphs,
|
||||
cairo_scaled_font_t *scaled_font)
|
||||
{
|
||||
|
|
|
@ -2732,78 +2732,231 @@ static void fbFetch(PicturePtr pict, int x, int y, int width, CARD32 *buffer, CA
|
|||
#define DIV(a,b) ((((a) < 0) == ((b) < 0)) ? (a) / (b) :\
|
||||
((a) - (b) + 1 - (((b) < 0) << 1)) / (b))
|
||||
|
||||
static CARD32
|
||||
xRenderColorMultToCard32 (pixman_color_t *c)
|
||||
typedef struct
|
||||
{
|
||||
return
|
||||
((((uint32_t) c->red * c->alpha) >> 24) << 16) |
|
||||
((((uint32_t) c->green * c->alpha) >> 24) << 8) |
|
||||
((((uint32_t) c->blue * c->alpha) >> 24) << 0) |
|
||||
((((uint32_t) c->alpha ) >> 8) << 24);
|
||||
CARD32 left_ag;
|
||||
CARD32 left_rb;
|
||||
CARD32 right_ag;
|
||||
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;
|
||||
} GradientWalker;
|
||||
|
||||
static void
|
||||
_gradient_walker_init (GradientWalker *walker,
|
||||
SourcePictPtr pGradient,
|
||||
unsigned int spread)
|
||||
{
|
||||
walker->num_stops = pGradient->gradient.nstops;
|
||||
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;
|
||||
}
|
||||
|
||||
static CARD32 gradientPixel(const SourcePictPtr pGradient, xFixed_48_16 pos, unsigned int spread)
|
||||
static void
|
||||
_gradient_walker_reset (GradientWalker *walker,
|
||||
xFixed_32_32 pos)
|
||||
{
|
||||
int ipos = (pos * pGradient->gradient.stopRange - 1) >> 16;
|
||||
int32_t x, left_x, right_x;
|
||||
pixman_color_t *left_c, *right_c;
|
||||
int n, count = walker->num_stops;
|
||||
pixman_gradient_stop_t *stops = walker->stops;
|
||||
|
||||
/* calculate the actual offset. */
|
||||
if (ipos < 0 || ipos >= pGradient->gradient.stopRange)
|
||||
static const pixman_color_t transparent_black = { 0, 0, 0, 0 };
|
||||
|
||||
switch (walker->spread)
|
||||
{
|
||||
if (pGradient->type == SourcePictTypeConical || spread == RepeatNormal)
|
||||
{
|
||||
ipos = ipos % pGradient->gradient.stopRange;
|
||||
ipos = ipos < 0 ? pGradient->gradient.stopRange + ipos : ipos;
|
||||
|
||||
case RepeatNormal:
|
||||
x = (int32_t)pos & 0xFFFF;
|
||||
for (n = 0; n < count; n++)
|
||||
if (x < stops[n].x)
|
||||
break;
|
||||
if (n == 0) {
|
||||
left_x = stops[count-1].x - 0x10000;
|
||||
left_c = &stops[count-1].color;
|
||||
} else {
|
||||
left_x = stops[n-1].x;
|
||||
left_c = &stops[n-1].color;
|
||||
}
|
||||
else if (spread == RepeatReflect)
|
||||
{
|
||||
const int limit = pGradient->gradient.stopRange * 2 - 1;
|
||||
|
||||
ipos = ipos % limit;
|
||||
ipos = ipos < 0 ? limit + ipos : ipos;
|
||||
ipos = ipos >= pGradient->gradient.stopRange ? limit - ipos : ipos;
|
||||
if (n == count) {
|
||||
right_x = stops[0].x + 0x10000;
|
||||
right_c = &stops[0].color;
|
||||
} else {
|
||||
right_x = stops[n].x;
|
||||
right_c = &stops[n].color;
|
||||
}
|
||||
left_x += (pos - x);
|
||||
right_x += (pos - x);
|
||||
break;
|
||||
|
||||
case RepeatPad:
|
||||
for (n = 0; n < count; n++)
|
||||
if (pos < stops[n].x)
|
||||
break;
|
||||
|
||||
if (n == 0) {
|
||||
left_x = INT_MIN;
|
||||
left_c = &stops[0].color;
|
||||
} else {
|
||||
left_x = stops[n-1].x;
|
||||
left_c = &stops[n-1].color;
|
||||
}
|
||||
else if (spread == RepeatPad)
|
||||
{
|
||||
if (ipos < 0)
|
||||
ipos = 0;
|
||||
else
|
||||
ipos = pGradient->gradient.stopRange - 1;
|
||||
|
||||
if (n == count) {
|
||||
right_x = INT_MAX;
|
||||
right_c = &stops[n-1].color;
|
||||
} else {
|
||||
right_x = stops[n].x;
|
||||
right_c = &stops[n].color;
|
||||
}
|
||||
else /* RepeatNone */
|
||||
break;
|
||||
|
||||
case RepeatReflect:
|
||||
x = (int32_t)pos & 0xFFFF;
|
||||
if ((int32_t)pos & 0x10000)
|
||||
x = 0x10000 - x;
|
||||
for (n = 0; n < count; n++)
|
||||
if (x < stops[n].x)
|
||||
break;
|
||||
|
||||
if (n == 0) {
|
||||
left_x = -stops[0].x;
|
||||
left_c = &stops[0].color;
|
||||
} else {
|
||||
left_x = stops[n-1].x;
|
||||
left_c = &stops[n-1].color;
|
||||
}
|
||||
|
||||
if (n == count) {
|
||||
right_x = 0x20000 - stops[n-1].x;
|
||||
right_c = &stops[n-1].color;
|
||||
} else {
|
||||
right_x = stops[n].x;
|
||||
right_c = &stops[n].color;
|
||||
}
|
||||
|
||||
if ((int32_t)pos & 0x10000) {
|
||||
pixman_color_t *tmp_c;
|
||||
int32_t tmp_x;
|
||||
|
||||
tmp_x = 0x20000 - right_x;
|
||||
right_x = 0x20000 - left_x;
|
||||
left_x = tmp_x;
|
||||
|
||||
tmp_c = right_c;
|
||||
right_c = left_c;
|
||||
left_c = tmp_c;
|
||||
}
|
||||
left_x += (pos - x);
|
||||
right_x += (pos - x);
|
||||
break;
|
||||
|
||||
default: /* RepeatNone */
|
||||
for (n = 0; n < count; n++)
|
||||
if (pos < stops[n].x)
|
||||
break;
|
||||
|
||||
if (n == 0)
|
||||
{
|
||||
return 0;
|
||||
left_x = INT_MIN;
|
||||
right_x = stops[0].x;
|
||||
left_c = right_c = (pixman_color_t*) &transparent_black;
|
||||
}
|
||||
else if (n == count)
|
||||
{
|
||||
left_x = stops[n-1].x;
|
||||
right_x = INT_MAX;
|
||||
left_c = right_c = (pixman_color_t*) &transparent_black;
|
||||
}
|
||||
else
|
||||
{
|
||||
left_x = stops[n-1].x;
|
||||
right_x = stops[n].x;
|
||||
left_c = &stops[n-1].color;
|
||||
right_c = &stops[n].color;
|
||||
}
|
||||
}
|
||||
|
||||
if (pGradient->gradient.colorTableSize)
|
||||
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 ||
|
||||
( walker->left_ag == walker->right_ag &&
|
||||
walker->left_rb == walker->right_rb ) )
|
||||
{
|
||||
return pGradient->gradient.colorTable[ipos];
|
||||
walker->width_x = 1;
|
||||
walker->stepper = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
int i;
|
||||
|
||||
if (ipos <= pGradient->gradient.stops->x)
|
||||
return xRenderColorMultToCard32 (&pGradient->gradient.stops->color);
|
||||
|
||||
for (i = 1; i < pGradient->gradient.nstops; i++)
|
||||
{
|
||||
if (pGradient->gradient.stops[i].x >= ipos)
|
||||
return PictureGradientColor (&pGradient->gradient.stops[i - 1],
|
||||
&pGradient->gradient.stops[i],
|
||||
ipos);
|
||||
}
|
||||
|
||||
return xRenderColorMultToCard32 (&pGradient->gradient.stops[--i].color);
|
||||
walker->stepper = ((1 << 24) + walker->width_x/2)/walker->width_x;
|
||||
}
|
||||
}
|
||||
|
||||
#define GRADIENT_WALKER_NEED_RESET(w,x) \
|
||||
( (x) < (w)->left_x || (x) - (w)->left_x >= (w)->width_x )
|
||||
|
||||
/* the following assumes that GRADIENT_WALKER_NEED_RESET(w,x) is FALSE */
|
||||
static CARD32
|
||||
_gradient_walker_pixel (GradientWalker *walker,
|
||||
xFixed_32_32 x)
|
||||
{
|
||||
int dist, idist;
|
||||
uint32_t t1, t2, a, color;
|
||||
|
||||
if (GRADIENT_WALKER_NEED_RESET (walker, x))
|
||||
_gradient_walker_reset (walker, x);
|
||||
|
||||
dist = ((int)(x - walker->left_x)*walker->stepper) >> 16;
|
||||
idist = 256 - dist;
|
||||
|
||||
/* combined INTERPOLATE and premultiply */
|
||||
t1 = walker->left_rb*idist + walker->right_rb*dist;
|
||||
t1 = (t1 >> 8) & 0xff00ff;
|
||||
|
||||
t2 = walker->left_ag*idist + walker->right_ag*dist;
|
||||
t2 &= 0xff00ff00;
|
||||
|
||||
color = t2 & 0xff000000;
|
||||
a = t2 >> 24;
|
||||
|
||||
t1 = t1*a + 0x800080;
|
||||
t1 = (t1 + ((t1 >> 8) & 0xff00ff)) >> 8;
|
||||
|
||||
t2 = (t2 >> 8)*a + 0x800080;
|
||||
t2 = (t2 + ((t2 >> 8) & 0xff00ff));
|
||||
|
||||
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;
|
||||
CARD32 *end = buffer + width;
|
||||
SourcePictPtr pGradient = pict->pSourcePict;
|
||||
GradientWalker walker;
|
||||
CARD32 *end = buffer + width;
|
||||
|
||||
_gradient_walker_init (&walker, pGradient, pict->repeat);
|
||||
|
||||
if (pGradient->type == SourcePictTypeSolidFill) {
|
||||
register CARD32 color = pGradient->solidFill.color;
|
||||
|
@ -2854,20 +3007,29 @@ static void fbFetchSourcePict(PicturePtr pict, int x, int y, int width, CARD32 *
|
|||
{
|
||||
register CARD32 color;
|
||||
|
||||
color = gradientPixel (pGradient, t, pict->repeat);
|
||||
color = _gradient_walker_pixel( &walker, t );
|
||||
while (buffer < end)
|
||||
*buffer++ = color;
|
||||
}
|
||||
else
|
||||
{
|
||||
while (buffer < end) {
|
||||
if (!mask || *mask++ & maskBits)
|
||||
{
|
||||
*buffer = gradientPixel (pGradient, t, pict->repeat);
|
||||
}
|
||||
++buffer;
|
||||
t += inc;
|
||||
}
|
||||
if (!mask) {
|
||||
while (buffer < end)
|
||||
{
|
||||
*buffer = _gradient_walker_pixel (&walker, t);
|
||||
buffer += 1;
|
||||
t += inc;
|
||||
}
|
||||
} else {
|
||||
while (buffer < end) {
|
||||
if (*mask++ & maskBits)
|
||||
{
|
||||
*buffer = _gradient_walker_pixel (&walker, t);
|
||||
}
|
||||
buffer += 1;
|
||||
t += inc;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
else /* projective transformation */
|
||||
|
@ -2891,31 +3053,31 @@ static void fbFetchSourcePict(PicturePtr pict, int x, int y, int width, CARD32 *
|
|||
t = ((a * x + b * y) >> 16) + off;
|
||||
}
|
||||
|
||||
color = gradientPixel (pGradient, t, pict->repeat);
|
||||
color = _gradient_walker_pixel( &walker, t );
|
||||
while (buffer < end)
|
||||
*buffer++ = color;
|
||||
}
|
||||
else
|
||||
{
|
||||
while (buffer < end)
|
||||
{
|
||||
if (!mask || *mask++ & maskBits)
|
||||
{
|
||||
if (v.vector[2] == 0) {
|
||||
t = 0;
|
||||
} else {
|
||||
xFixed_48_16 x, y;
|
||||
x = ((xFixed_48_16)v.vector[0] << 16) / v.vector[2];
|
||||
y = ((xFixed_48_16)v.vector[1] << 16) / v.vector[2];
|
||||
t = ((a*x + b*y) >> 16) + off;
|
||||
}
|
||||
*buffer = gradientPixel(pGradient, t, pict->repeat);
|
||||
}
|
||||
++buffer;
|
||||
v.vector[0] += unit.vector[0];
|
||||
v.vector[1] += unit.vector[1];
|
||||
v.vector[2] += unit.vector[2];
|
||||
}
|
||||
while (buffer < end)
|
||||
{
|
||||
if (!mask || *mask++ & maskBits)
|
||||
{
|
||||
if (v.vector[2] == 0) {
|
||||
t = 0;
|
||||
} else {
|
||||
xFixed_48_16 x, y;
|
||||
x = ((xFixed_48_16)v.vector[0] << 16) / v.vector[2];
|
||||
y = ((xFixed_48_16)v.vector[1] << 16) / v.vector[2];
|
||||
t = ((a*x + b*y) >> 16) + off;
|
||||
}
|
||||
*buffer = _gradient_walker_pixel (&walker, t);
|
||||
}
|
||||
++buffer;
|
||||
v.vector[0] += unit.vector[0];
|
||||
v.vector[1] += unit.vector[1];
|
||||
v.vector[2] += unit.vector[2];
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
|
@ -2952,19 +3114,22 @@ static void fbFetchSourcePict(PicturePtr pict, int x, int y, int width, CARD32 *
|
|||
ry -= pGradient->radial.fy;
|
||||
|
||||
while (buffer < end) {
|
||||
double b, c, det, s;
|
||||
double b, c, det, s;
|
||||
|
||||
if (!mask || *mask++ & maskBits)
|
||||
{
|
||||
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);
|
||||
*buffer = gradientPixel(pGradient,
|
||||
(xFixed_48_16)((s*pGradient->radial.m + pGradient->radial.b)*65536),
|
||||
pict->repeat);
|
||||
}
|
||||
++buffer;
|
||||
if (!mask || *mask++ & maskBits)
|
||||
{
|
||||
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);
|
||||
|
||||
t = (xFixed_48_16)((s*pGradient->radial.m + pGradient->radial.b)*65536);
|
||||
|
||||
*buffer = _gradient_walker_pixel (&walker, t);
|
||||
}
|
||||
++buffer;
|
||||
rx += cx;
|
||||
ry += cy;
|
||||
}
|
||||
|
@ -2973,25 +3138,27 @@ static void fbFetchSourcePict(PicturePtr pict, int x, int y, int width, CARD32 *
|
|||
double x, y;
|
||||
double b, c, det, s;
|
||||
|
||||
if (!mask || *mask++ & maskBits)
|
||||
{
|
||||
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);
|
||||
*buffer = gradientPixel(pGradient,
|
||||
(xFixed_48_16)((s*pGradient->radial.m + pGradient->radial.b)*65536),
|
||||
pict->repeat);
|
||||
}
|
||||
++buffer;
|
||||
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;
|
||||
|
@ -3006,37 +3173,41 @@ static void fbFetchSourcePict(PicturePtr pict, int x, int y, int width, CARD32 *
|
|||
while (buffer < end) {
|
||||
double angle;
|
||||
|
||||
if (!mask || *mask++ & maskBits)
|
||||
{
|
||||
angle = atan2(ry, rx) + a;
|
||||
if (!mask || *mask++ & maskBits)
|
||||
{
|
||||
xFixed_48_16 t;
|
||||
|
||||
*buffer = gradientPixel(pGradient, (xFixed_48_16) (angle * (65536. / (2*M_PI))),
|
||||
pict->repeat);
|
||||
}
|
||||
angle = atan2(ry, rx) + a;
|
||||
t = (xFixed_48_16) (angle * (65536. / (2*M_PI)));
|
||||
|
||||
*buffer = _gradient_walker_pixel (&walker, t);
|
||||
}
|
||||
++buffer;
|
||||
rx += cx;
|
||||
ry += cy;
|
||||
}
|
||||
} else {
|
||||
|
||||
while (buffer < end) {
|
||||
double x, y;
|
||||
double angle;
|
||||
double angle;
|
||||
|
||||
if (!mask || *mask++ & maskBits)
|
||||
{
|
||||
if (rz != 0) {
|
||||
x = rx/rz;
|
||||
y = ry/rz;
|
||||
} else {
|
||||
x = y = 0.;
|
||||
}
|
||||
x -= pGradient->conical.center.x/65536.;
|
||||
y -= pGradient->conical.center.y/65536.;
|
||||
angle = atan2(y, x) + a;
|
||||
*buffer = gradientPixel(pGradient, (xFixed_48_16) (angle * (65536. / (2*M_PI))),
|
||||
pict->repeat);
|
||||
}
|
||||
if (!mask || *mask++ & maskBits)
|
||||
{
|
||||
xFixed_48_16 t;
|
||||
|
||||
if (rz != 0) {
|
||||
x = rx/rz;
|
||||
y = ry/rz;
|
||||
} else {
|
||||
x = y = 0.;
|
||||
}
|
||||
x -= pGradient->conical.center.x/65536.;
|
||||
y -= pGradient->conical.center.y/65536.;
|
||||
angle = atan2(y, x) + a;
|
||||
t = (xFixed_48_16) (angle * (65536. / (2*M_PI)));
|
||||
|
||||
*buffer = _gradient_walker_pixel (&walker, t);
|
||||
}
|
||||
++buffer;
|
||||
rx += cx;
|
||||
ry += cy;
|
||||
|
|
|
@ -602,18 +602,18 @@ nsThebesRenderingContext::DrawRect(nscoord aX, nscoord aY, nscoord aWidth, nscoo
|
|||
}
|
||||
|
||||
|
||||
/* Clamp r to (0,0) (32766,32766);
|
||||
/* Clamp r to (0,0) (16384,16384);
|
||||
* these are to be device coordinates.
|
||||
*
|
||||
* Returns PR_FALSE if the rectangle is completely out of bounds, PR_TRUE otherwise.
|
||||
*/
|
||||
#define CAIRO_COORD_MAX (16384.0)
|
||||
|
||||
static PRBool
|
||||
ConditionRect(gfxRect& r) {
|
||||
const double COORD_MAX = 32766.0;
|
||||
|
||||
// if either x or y is way out of bounds;
|
||||
// note that we don't handle negative w/h here
|
||||
if (r.pos.x > COORD_MAX || r.pos.y > COORD_MAX)
|
||||
if (r.pos.x > CAIRO_COORD_MAX || r.pos.y > CAIRO_COORD_MAX)
|
||||
return PR_FALSE;
|
||||
|
||||
if (r.pos.x < 0.0) {
|
||||
|
@ -621,8 +621,8 @@ ConditionRect(gfxRect& r) {
|
|||
r.pos.x = 0.0;
|
||||
}
|
||||
|
||||
if (r.pos.x + r.size.width > COORD_MAX) {
|
||||
r.size.width = COORD_MAX - r.pos.x;
|
||||
if (r.pos.x + r.size.width > CAIRO_COORD_MAX) {
|
||||
r.size.width = CAIRO_COORD_MAX - r.pos.x;
|
||||
}
|
||||
|
||||
if (r.pos.y < 0.0) {
|
||||
|
@ -630,8 +630,8 @@ ConditionRect(gfxRect& r) {
|
|||
r.pos.y = 0.0;
|
||||
}
|
||||
|
||||
if (r.pos.y + r.size.height > COORD_MAX) {
|
||||
r.size.height = COORD_MAX - r.pos.y;
|
||||
if (r.pos.y + r.size.height > CAIRO_COORD_MAX) {
|
||||
r.size.height = CAIRO_COORD_MAX - r.pos.y;
|
||||
}
|
||||
return PR_TRUE;
|
||||
}
|
||||
|
@ -644,7 +644,7 @@ nsThebesRenderingContext::FillRect(const nsRect& aRect)
|
|||
gfxRect r(GFX_RECT_FROM_TWIPS_RECT(aRect));
|
||||
|
||||
/* Clamp coordinates to work around a design bug in cairo */
|
||||
nscoord bigval = (nscoord)(32766*mP2T);
|
||||
nscoord bigval = (nscoord)(CAIRO_COORD_MAX*mP2T);
|
||||
if (aRect.width > bigval ||
|
||||
aRect.height > bigval ||
|
||||
aRect.x < -bigval ||
|
||||
|
@ -661,6 +661,9 @@ nsThebesRenderingContext::FillRect(const nsRect& aRect)
|
|||
|
||||
mThebes->IdentityMatrix();
|
||||
mThebes->NewPath();
|
||||
|
||||
PR_LOG(gThebesGFXLog, PR_LOG_DEBUG, ("## %p nsTRC::FillRect conditioned to [%f,%f,%f,%f]\n", this, r.pos.x, r.pos.y, r.size.width, r.size.height));
|
||||
|
||||
mThebes->Rectangle(r, PR_TRUE);
|
||||
mThebes->Fill();
|
||||
mThebes->SetMatrix(mat);
|
||||
|
@ -668,6 +671,8 @@ nsThebesRenderingContext::FillRect(const nsRect& aRect)
|
|||
return NS_OK;
|
||||
}
|
||||
|
||||
PR_LOG(gThebesGFXLog, PR_LOG_DEBUG, ("## %p nsTRC::FillRect raw [%f,%f,%f,%f]\n", this, r.pos.x, r.pos.y, r.size.width, r.size.height));
|
||||
|
||||
mThebes->NewPath();
|
||||
mThebes->Rectangle(r, PR_TRUE);
|
||||
mThebes->Fill();
|
||||
|
|
|
@ -245,14 +245,14 @@ public:
|
|||
}
|
||||
|
||||
gfxRect TransformBounds(const gfxRect& rect) const {
|
||||
double x = rect.pos.x;
|
||||
double y = rect.pos.y;
|
||||
double width = rect.size.width;
|
||||
double height = rect.size.height;
|
||||
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;
|
||||
|
||||
cairo_matrix_transform_bounding_box (&mat, &x, &y, &width, &height, NULL);
|
||||
cairo_matrix_transform_bounding_box (&mat, &x0, &y0, &x1, &y1, NULL);
|
||||
|
||||
return gfxRect(x, y, width, height);
|
||||
return gfxRect(x0, y0, x1 - x0, y1 - y0);
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
Загрузка…
Ссылка в новой задаче