Backed out changeset 20534cf9abf5

This commit is contained in:
Vladimir Vukicevic 2008-07-20 15:35:51 -07:00
Родитель f477c5b702
Коммит 3651538cb6
134 изменённых файлов: 3815 добавлений и 16977 удалений

Просмотреть файл

@ -7,8 +7,9 @@ http://www.cairographics.org/.
VERSIONS:
cairo (1.6.4-348-g96c9e2a)
pixman (pixman-0.11.8-4-g51576cd)
cairo (1.6.4 - 1.6.4)
pixman (0.10.x - pixman-0.10.0-8-g0b207ae)
glitz 0.5.2 (cvs - 2006-01-10)
***** NOTE FOR VISUAL C++ 6.0 *****
@ -18,6 +19,21 @@ VC6 is not supported. Please upgrade to VC8.
Some specific things:
cairo git commit ea6dbfd36f2182fda16cb82bca92007e0f7b8d77 -
[cairo-meta-surface] Save and restore the original clip.
cairo git commit d96fdd58abf8d6c8692dbb08ec54cdd80accba79 -
win32: Fix broken printing of type1 fonts
cairo git commit 547e2f552cff264b943803d3a1ff03d05bde35c0
Fix win32-printing show_glyphs analysis for Type 1 fonts
cairo git commit 158d24412bba99a4f57907d7fd22a86aae6e87af
Make win32-printing surface work with bitmap fonts
cairo git commit d35d6eec24c1b7ab0a49149a51bf65ea8e223203
Fix win32 bitmap font metrics when device scale != 1
max-font-size.patch: Clamp freetype font size to 1000 to avoid overflow issues
win32-logical-font-scale.patch: set CAIRO_WIN32_LOGICAL_FONT_SCALE to 1
@ -26,6 +42,10 @@ nonfatal-assertions.patch: Make assertions non-fatal
buggy-repeat.patch: Unconditionally turn on buggy-repeat handling to bandaid bug 413583.
clip-clone.patch: _cairo_clip_init_deep_copy should pass 0,0 as the
source coordinates to clone from since it wants an exact copy of the
source's clipping surface
==== pixman patches ====
endian.patch: include cairo-platform.h for endian macros

Просмотреть файл

@ -118,7 +118,6 @@ CSRCS = \
cairo-surface-fallback.c \
cairo-traps.c \
cairo-unicode.c \
cairo-user-font.c \
cairo-wideint.c \
$(NULL)
@ -129,7 +128,6 @@ EXPORTS = cairo.h cairo-features.h cairo-platform.h cairo-deprecated.h cairo-ren
PSPDF_BASE_CSRCS = \
cairo-base85-stream.c \
cairo-type1-fallback.c \
cairo-type3-glyph-surface.c \
cairo-truetype-subset.c \
cairo-cff-subset.c \
$(NULL)

Просмотреть файл

@ -42,14 +42,6 @@ _cairo_analysis_surface_create (cairo_surface_t *target,
int width,
int height);
cairo_private void
_cairo_analysis_surface_set_ctm (cairo_surface_t *surface,
cairo_matrix_t *ctm);
cairo_private void
_cairo_analysis_surface_get_ctm (cairo_surface_t *surface,
cairo_matrix_t *ctm);
cairo_private cairo_region_t *
_cairo_analysis_surface_get_supported (cairo_surface_t *surface);
@ -66,8 +58,4 @@ cairo_private void
_cairo_analysis_surface_get_bounding_box (cairo_surface_t *surface,
cairo_box_t *bbox);
cairo_private cairo_surface_t *
_cairo_null_surface_create (cairo_content_t content);
#endif /* CAIRO_ANALYSIS_SURFACE_H */

Просмотреть файл

@ -84,7 +84,7 @@ _cairo_analysis_surface_analyze_meta_surface_pattern (cairo_analysis_surface_t *
old_height = surface->height;
old_clip = surface->current_clip;
status = _cairo_surface_get_extents (surface_pattern->surface, &meta_extents);
if (status && status != CAIRO_INT_STATUS_UNSUPPORTED)
if (status)
return status;
surface->width = meta_extents.width;
@ -140,13 +140,22 @@ _cairo_analysis_surface_add_operation (cairo_analysis_surface_t *surface,
}
}
_cairo_box_from_rectangle (&bbox, rect);
if (surface->has_ctm) {
double x1, y1, x2, y2;
_cairo_matrix_transform_bounding_box_fixed (&surface->ctm, &bbox, NULL);
x1 = rect->x;
y1 = rect->y;
x2 = rect->x + rect->width;
y2 = rect->y + rect->height;
_cairo_matrix_transform_bounding_box (&surface->ctm,
&x1, &y1, &x2, &y2,
NULL);
rect->x = floor (x1);
rect->y = floor (y1);
if (bbox.p1.x == bbox.p2.x || bbox.p1.y == bbox.p2.y) {
x2 = ceil (x2) - rect->x;
y2 = ceil (y2) - rect->y;
if (x2 <= 0 || y2 <= 0) {
/* Even though the operation is not visible we must be
* careful to not allow unsupported operations to be
* replayed to the backend during
@ -162,9 +171,15 @@ _cairo_analysis_surface_add_operation (cairo_analysis_surface_t *surface,
}
}
_cairo_box_round_to_rectangle (&bbox, rect);
rect->width = x2;
rect->height = y2;
}
bbox.p1.x = _cairo_fixed_from_int (rect->x);
bbox.p1.y = _cairo_fixed_from_int (rect->y);
bbox.p2.x = _cairo_fixed_from_int (rect->x + rect->width);
bbox.p2.y = _cairo_fixed_from_int (rect->y + rect->height);
if (surface->first_op) {
surface->first_op = FALSE;
surface->page_bbox = bbox;
@ -238,8 +253,6 @@ _cairo_analysis_surface_finish (void *abstract_surface)
_cairo_region_fini (&surface->supported_region);
_cairo_region_fini (&surface->fallback_region);
cairo_surface_destroy (surface->target);
return CAIRO_STATUS_SUCCESS;
}
@ -306,7 +319,7 @@ _cairo_analysis_surface_paint (void *abstract_surface,
source);
status = _cairo_surface_get_extents (&surface->base, &extents);
if (status && status != CAIRO_INT_STATUS_UNSUPPORTED)
if (status)
return status;
if (_cairo_operator_bounded_by_source (op)) {
@ -364,7 +377,7 @@ _cairo_analysis_surface_mask (void *abstract_surface,
}
status = _cairo_surface_get_extents (&surface->base, &extents);
if (status && status != CAIRO_INT_STATUS_UNSUPPORTED)
if (status)
return status;
if (_cairo_operator_bounded_by_source (op)) {
@ -419,7 +432,7 @@ _cairo_analysis_surface_stroke (void *abstract_surface,
source);
status = _cairo_surface_get_extents (&surface->base, &extents);
if (status && status != CAIRO_INT_STATUS_UNSUPPORTED)
if (status)
return status;
if (_cairo_operator_bounded_by_source (op)) {
@ -498,7 +511,7 @@ _cairo_analysis_surface_fill (void *abstract_surface,
source);
status = _cairo_surface_get_extents (&surface->base, &extents);
if (status && status != CAIRO_INT_STATUS_UNSUPPORTED)
if (status)
return status;
if (_cairo_operator_bounded_by_source (op)) {
@ -556,120 +569,26 @@ _cairo_analysis_surface_show_glyphs (void *abstract_surface,
cairo_pattern_t *source,
cairo_glyph_t *glyphs,
int num_glyphs,
cairo_scaled_font_t *scaled_font,
int *remaining_glyphs)
cairo_scaled_font_t *scaled_font)
{
cairo_analysis_surface_t *surface = abstract_surface;
cairo_status_t status, backend_status;
cairo_rectangle_int_t extents, glyph_extents;
/* Adapted from _cairo_surface_show_glyphs */
if (surface->target->backend->show_glyphs)
backend_status = (*surface->target->backend->show_glyphs) (surface->target, op,
source,
glyphs, num_glyphs,
scaled_font,
remaining_glyphs);
else if (surface->target->backend->show_text_glyphs)
backend_status = surface->target->backend->show_text_glyphs (surface->target, op,
source,
NULL, 0,
glyphs, num_glyphs,
NULL, 0,
FALSE,
scaled_font);
else
if (!surface->target->backend->show_glyphs)
backend_status = CAIRO_INT_STATUS_UNSUPPORTED;
else
backend_status = (*surface->target->backend->show_glyphs) (surface->target, op,
source,
glyphs, num_glyphs,
scaled_font);
if (backend_status == CAIRO_INT_STATUS_ANALYZE_META_SURFACE_PATTERN)
backend_status = _cairo_analysis_surface_analyze_meta_surface_pattern (surface,
source);
status = _cairo_surface_get_extents (&surface->base, &extents);
if (status && status != CAIRO_INT_STATUS_UNSUPPORTED)
return status;
if (_cairo_operator_bounded_by_source (op)) {
cairo_rectangle_int_t source_extents;
status = _cairo_pattern_get_extents (source, &source_extents);
if (status)
return status;
_cairo_rectangle_intersect (&extents, &source_extents);
}
_cairo_rectangle_intersect (&extents, &surface->current_clip);
if (_cairo_operator_bounded_by_mask (op)) {
status = _cairo_scaled_font_glyph_device_extents (scaled_font,
glyphs,
num_glyphs,
&glyph_extents);
if (status)
return status;
_cairo_rectangle_intersect (&extents, &glyph_extents);
}
status = _cairo_analysis_surface_add_operation (surface, &extents, backend_status);
return status;
}
static cairo_bool_t
_cairo_analysis_surface_has_show_text_glyphs (void *abstract_surface)
{
cairo_analysis_surface_t *surface = abstract_surface;
return _cairo_surface_has_show_text_glyphs (surface->target);
}
static cairo_int_status_t
_cairo_analysis_surface_show_text_glyphs (void *abstract_surface,
cairo_operator_t op,
cairo_pattern_t *source,
const char *utf8,
int utf8_len,
cairo_glyph_t *glyphs,
int num_glyphs,
const cairo_text_cluster_t *clusters,
int num_clusters,
cairo_bool_t backward,
cairo_scaled_font_t *scaled_font)
{
cairo_analysis_surface_t *surface = abstract_surface;
cairo_status_t status, backend_status;
cairo_rectangle_int_t extents, glyph_extents;
/* Adapted from _cairo_surface_show_glyphs */
backend_status = CAIRO_INT_STATUS_UNSUPPORTED;
if (surface->target->backend->show_text_glyphs)
backend_status = surface->target->backend->show_text_glyphs (surface->target, op,
source,
utf8, utf8_len,
glyphs, num_glyphs,
clusters, num_clusters,
backward,
scaled_font);
if (backend_status == CAIRO_INT_STATUS_UNSUPPORTED && surface->target->backend->show_glyphs) {
int remaining_glyphs = num_glyphs;
backend_status = surface->target->backend->show_glyphs (surface->target, op,
source,
glyphs, num_glyphs,
scaled_font,
&remaining_glyphs);
glyphs += num_glyphs - remaining_glyphs;
num_glyphs = remaining_glyphs;
if (remaining_glyphs == 0)
backend_status = CAIRO_STATUS_SUCCESS;
}
if (backend_status == CAIRO_INT_STATUS_ANALYZE_META_SURFACE_PATTERN)
backend_status = _cairo_analysis_surface_analyze_meta_surface_pattern (surface,
source);
status = _cairo_surface_get_extents (&surface->base, &extents);
if (status && status != CAIRO_INT_STATUS_UNSUPPORTED)
if (status)
return status;
if (_cairo_operator_bounded_by_source (op)) {
@ -731,9 +650,6 @@ static const cairo_surface_backend_t cairo_analysis_surface_backend = {
NULL, /* is_similar */
NULL, /* reset */
NULL, /* fill_stroke */
NULL, /* create_solid_pattern_surface */
_cairo_analysis_surface_has_show_text_glyphs,
_cairo_analysis_surface_show_text_glyphs
};
cairo_surface_t *
@ -757,54 +673,21 @@ _cairo_analysis_surface_create (cairo_surface_t *target,
cairo_matrix_init_identity (&surface->ctm);
surface->has_ctm = FALSE;
surface->target = cairo_surface_reference (target);
surface->target = target;
surface->first_op = TRUE;
surface->has_supported = FALSE;
surface->has_unsupported = FALSE;
surface->page_bbox.p1.x = 0;
surface->page_bbox.p1.y = 0;
surface->page_bbox.p2.x = 0;
surface->page_bbox.p2.y = 0;
_cairo_region_init (&surface->supported_region);
_cairo_region_init (&surface->fallback_region);
if (width == -1 && height == -1) {
surface->current_clip.x = CAIRO_RECT_INT_MIN;
surface->current_clip.y = CAIRO_RECT_INT_MIN;
surface->current_clip.width = CAIRO_RECT_INT_MAX - CAIRO_RECT_INT_MIN;
surface->current_clip.height = CAIRO_RECT_INT_MAX - CAIRO_RECT_INT_MIN;
} else {
surface->current_clip.x = 0;
surface->current_clip.y = 0;
surface->current_clip.width = width;
surface->current_clip.height = height;
}
surface->current_clip.x = 0;
surface->current_clip.y = 0;
surface->current_clip.width = width;
surface->current_clip.height = height;
return &surface->base;
}
cairo_private void
_cairo_analysis_surface_set_ctm (cairo_surface_t *abstract_surface,
cairo_matrix_t *ctm)
{
cairo_analysis_surface_t *surface = (cairo_analysis_surface_t *) abstract_surface;
surface->ctm = *ctm;
surface->has_ctm = !_cairo_matrix_is_identity (&surface->ctm);
}
cairo_private void
_cairo_analysis_surface_get_ctm (cairo_surface_t *abstract_surface,
cairo_matrix_t *ctm)
{
cairo_analysis_surface_t *surface = (cairo_analysis_surface_t *) abstract_surface;
*ctm = surface->ctm;
}
cairo_region_t *
_cairo_analysis_surface_get_supported (cairo_surface_t *abstract_surface)
{
@ -845,108 +728,3 @@ _cairo_analysis_surface_get_bounding_box (cairo_surface_t *abstract_surface,
*bbox = surface->page_bbox;
}
/* null surface type: a surface that does nothing (has no side effects, yay!) */
static cairo_int_status_t
_return_success (void)
{
return CAIRO_STATUS_SUCCESS;
}
/* These typedefs are just to silence the compiler... */
typedef cairo_int_status_t
(*_set_clip_region_func) (void *surface,
cairo_region_t *region);
typedef cairo_int_status_t
(*_paint_func) (void *surface,
cairo_operator_t op,
cairo_pattern_t *source);
typedef cairo_int_status_t
(*_mask_func) (void *surface,
cairo_operator_t op,
cairo_pattern_t *source,
cairo_pattern_t *mask);
typedef cairo_int_status_t
(*_stroke_func) (void *surface,
cairo_operator_t op,
cairo_pattern_t *source,
cairo_path_fixed_t *path,
cairo_stroke_style_t *style,
cairo_matrix_t *ctm,
cairo_matrix_t *ctm_inverse,
double tolerance,
cairo_antialias_t antialias);
typedef cairo_int_status_t
(*_fill_func) (void *surface,
cairo_operator_t op,
cairo_pattern_t *source,
cairo_path_fixed_t *path,
cairo_fill_rule_t fill_rule,
double tolerance,
cairo_antialias_t antialias);
typedef cairo_int_status_t
(*_show_glyphs_func) (void *surface,
cairo_operator_t op,
cairo_pattern_t *source,
cairo_glyph_t *glyphs,
int num_glyphs,
cairo_scaled_font_t *scaled_font,
int *remaining_glyphs);
static const cairo_surface_backend_t cairo_null_surface_backend = {
CAIRO_INTERNAL_SURFACE_TYPE_NULL,
NULL, /* create_similar */
NULL, /* finish */
NULL, /* acquire_source_image */
NULL, /* release_source_image */
NULL, /* acquire_dest_image */
NULL, /* release_dest_image */
NULL, /* clone_similar */
NULL, /* composite */
NULL, /* fill_rectangles */
NULL, /* composite_trapezoids */
NULL, /* copy_page */
NULL, /* show_page */
(_set_clip_region_func) _return_success, /* set_clip_region */
NULL, /* intersect_clip_path */
NULL, /* get_extents */
NULL, /* old_show_glyphs */
NULL, /* get_font_options */
NULL, /* flush */
NULL, /* mark_dirty_rectangle */
NULL, /* scaled_font_fini */
NULL, /* scaled_glyph_fini */
(_paint_func) _return_success, /* paint */
(_mask_func) _return_success, /* mask */
(_stroke_func) _return_success, /* stroke */
(_fill_func) _return_success, /* fill */
(_show_glyphs_func) _return_success, /* show_glyphs */
NULL, /* snapshot */
NULL, /* is_similar */
NULL, /* reset */
NULL, /* fill_stroke */
NULL, /* create_solid_pattern_surface */
NULL, /* has_show_text_glyphs */
NULL /* show_text_glyphs */
};
cairo_surface_t *
_cairo_null_surface_create (cairo_content_t content)
{
cairo_surface_t *surface;
surface = malloc (sizeof (cairo_surface_t));
if (surface == NULL) {
return _cairo_surface_create_in_error (_cairo_error (CAIRO_STATUS_NO_MEMORY));
}
_cairo_surface_init (surface, &cairo_null_surface_backend, content);
return surface;
}

Просмотреть файл

@ -181,15 +181,13 @@ _cairo_arc_in_direction (cairo_t *cr,
double angle_max,
cairo_direction_t dir)
{
if (cairo_status (cr))
return;
while (angle_max - angle_min > 4 * M_PI)
angle_max -= 2 * M_PI;
/* Recurse if drawing arc larger than pi */
if (angle_max - angle_min > M_PI) {
double angle_mid = angle_min + (angle_max - angle_min) / 2.0;
/* XXX: Something tells me this block could be condensed. */
if (dir == CAIRO_DIRECTION_FORWARD) {
_cairo_arc_in_direction (cr, xc, yc, radius,
angle_min, angle_mid,
@ -207,7 +205,7 @@ _cairo_arc_in_direction (cairo_t *cr,
angle_min, angle_mid,
dir);
}
} else if (angle_max != angle_min) {
} else {
cairo_matrix_t ctm;
int i, segments;
double angle, angle_step;

Просмотреть файл

@ -236,7 +236,7 @@ _cairo_array_copy_element (cairo_array_t *array, int index, void *dst)
* _cairo_array_index (array, _cairo_array_num_elements (array) - 1);
*
* Return value: %CAIRO_STATUS_SUCCESS if successful or
* %CAIRO_STATUS_NO_MEMORY if insufficient memory is available for the
* CAIRO_STATUS_NO_MEMORY if insufficient memory is available for the
* operation.
**/
cairo_status_t
@ -256,7 +256,7 @@ _cairo_array_append (cairo_array_t *array,
* @elements into the array.
*
* Return value: %CAIRO_STATUS_SUCCESS if successful or
* %CAIRO_STATUS_NO_MEMORY if insufficient memory is available for the
* CAIRO_STATUS_NO_MEMORY if insufficient memory is available for the
* operation.
**/
cairo_status_t
@ -287,7 +287,7 @@ _cairo_array_append_multiple (cairo_array_t *array,
* for in the return value of _cairo_array_num_elements().
*
* Return value: %CAIRO_STATUS_SUCCESS if successful or
* %CAIRO_STATUS_NO_MEMORY if insufficient memory is available for the
* CAIRO_STATUS_NO_MEMORY if insufficient memory is available for the
* operation.
**/
cairo_status_t

Просмотреть файл

@ -1,5 +1,4 @@
/* -*- Mode: c; c-basic-offset: 4; indent-tabs-mode: t; tab-width: 8; -*- */
/* cairo - a vector graphics library with display and print output
/* cairo_output_stream.c: Output stream abstraction
*
* Copyright © 2005 Red Hat, Inc
*

Просмотреть файл

@ -508,7 +508,7 @@ det64_128 (cairo_int64_t a,
* result is provided as a coordinate pair of 128-bit integers.
*
* Returns %CAIRO_BO_STATUS_INTERSECTION if there is an intersection or
* %CAIRO_BO_STATUS_PARALLEL if the two lines are exactly parallel.
* CAIRO_BO_STATUS_PARALLEL if the two lines are exactly parallel.
*/
static cairo_bo_status_t
intersect_lines (cairo_bo_edge_t *a,
@ -1214,7 +1214,7 @@ _active_edges_to_traps (cairo_bo_edge_t *head,
int in_out = 0;
cairo_bo_edge_t *edge;
for (edge = head; edge; edge = edge->next) {
for (edge = head; edge && edge->next; edge = edge->next) {
if (fill_rule == CAIRO_FILL_RULE_WINDING) {
if (edge->reversed)
in_out++;
@ -1415,9 +1415,9 @@ update_minmax(cairo_fixed_t *inout_min,
}
cairo_status_t
_cairo_bentley_ottmann_tessellate_polygon (cairo_traps_t *traps,
const cairo_polygon_t *polygon,
cairo_fill_rule_t fill_rule)
_cairo_bentley_ottmann_tessellate_polygon (cairo_traps_t *traps,
cairo_polygon_t *polygon,
cairo_fill_rule_t fill_rule)
{
int intersections;
cairo_status_t status;

Просмотреть файл

@ -36,7 +36,7 @@
#ifndef CAIRO_BEOS_H
#define CAIRO_BEOS_H
#include "cairo.h"
#include <cairo.h>
#if CAIRO_HAS_BEOS_SURFACE

Просмотреть файл

@ -296,7 +296,7 @@ _cairo_cache_shrink_to_accommodate (cairo_cache_t *cache,
* entry_destroy() callback will be called on it).
*
* Return value: %CAIRO_STATUS_SUCCESS if successful or
* %CAIRO_STATUS_NO_MEMORY if insufficient memory is available.
* CAIRO_STATUS_NO_MEMORY if insufficient memory is available.
**/
cairo_status_t
_cairo_cache_insert (cairo_cache_t *cache,

Просмотреть файл

@ -274,13 +274,13 @@ _cairo_clip_combine_to_surface (cairo_clip_t *clip,
int dst_y,
const cairo_rectangle_int_t *extents)
{
cairo_surface_pattern_t pattern;
cairo_pattern_union_t pattern;
cairo_status_t status;
if (clip->all_clipped)
return CAIRO_STATUS_SUCCESS;
_cairo_pattern_init_for_surface (&pattern, clip->surface);
_cairo_pattern_init_for_surface (&pattern.surface, clip->surface);
status = _cairo_surface_composite (op,
&pattern.base,
@ -485,7 +485,8 @@ _cairo_clip_intersect_mask (cairo_clip_t *clip,
CAIRO_CONTENT_ALPHA,
surface_rect.width,
surface_rect.height,
CAIRO_COLOR_TRANSPARENT);
CAIRO_COLOR_TRANSPARENT,
&pattern.base);
if (surface->status) {
_cairo_pattern_fini (&pattern.base);
return surface->status;
@ -629,7 +630,7 @@ _cairo_clip_translate (cairo_clip_t *clip,
_cairo_fixed_to_double (ty));
while (clip_path) {
_cairo_path_fixed_transform (&clip_path->path, &matrix);
_cairo_path_fixed_device_transform (&clip_path->path, &matrix);
clip_path = clip_path->prev;
}
}
@ -677,8 +678,7 @@ _cairo_clip_init_deep_copy (cairo_clip_t *clip,
if (other->surface) {
status = _cairo_surface_clone_similar (target, other->surface,
0,
0,
0, 0,
other->surface_rect.width,
other->surface_rect.height,
&clip->surface);

Просмотреть файл

@ -111,7 +111,7 @@ CAIRO_BEGIN_DECLS
#define __attribute__(x)
#endif
#if (defined(__WIN32__) && !defined(__WINE__)) || defined(_MSC_VER)
#if defined(__WIN32__) || defined(_MSC_VER)
#define snprintf _snprintf
#endif

Просмотреть файл

@ -61,15 +61,15 @@ cairo_debug_reset_static_data (void)
{
CAIRO_MUTEX_INITIALIZE ();
_cairo_font_face_reset_static_data ();
_cairo_font_reset_static_data ();
#if CAIRO_HAS_FT_FONT
_cairo_ft_font_reset_static_data ();
#endif
_cairo_scaled_font_reset_static_data ();
_cairo_pattern_reset_static_data ();
_cairo_scaled_font_reset_static_data ();
CAIRO_MUTEX_FINALIZE ();
}

Просмотреть файл

@ -1,5 +1,4 @@
/* -*- Mode: c; c-basic-offset: 4; indent-tabs-mode: t; tab-width: 8; -*- */
/* cairo - a vector graphics library with display and print output
/* cairo_deflate_stream.c: Output stream abstraction
*
* Copyright © 2006 Adrian Johnson
*

Просмотреть файл

@ -52,6 +52,8 @@
#define CAIRO_FONT_TYPE_ATSUI CAIRO_FONT_TYPE_QUARTZ
#ifndef _CAIROINT_H_
/* Obsolete functions. These definitions exist to coerce the compiler
* into providing a little bit of guidance with its error
* messages. The idea is to help users port their old code without
@ -135,4 +137,6 @@
#define cairo_get_status_string cairo_get_status_string_DEPRECATED_BY_cairo_status_AND_cairo_status_to_string
#define cairo_status_string cairo_status_string_DEPRECATED_BY_cairo_status_AND_cairo_status_to_string
#endif
#endif /* CAIRO_DEPRECATED_H */

Просмотреть файл

@ -1606,8 +1606,7 @@ _cairo_directfb_surface_show_glyphs (void *abstract_dst,
cairo_pattern_t *pattern,
cairo_glyph_t *glyphs,
int num_glyphs,
cairo_scaled_font_t *scaled_font,
int *remaining_glyphs)
cairo_scaled_font_t *scaled_font)
{
cairo_directfb_surface_t *dst = abstract_dst;
cairo_directfb_font_cache_t *cache;

Просмотреть файл

@ -47,7 +47,7 @@
#ifndef CAIRO_DIRECTFB_H
#define CAIRO_DIRECTFB_H
#include "cairo.h"
#include <cairo.h>
#ifdef CAIRO_HAS_DIRECTFB_SURFACE

Просмотреть файл

@ -226,17 +226,6 @@ _cairo_fixed_mul (cairo_fixed_t a, cairo_fixed_t b)
return _cairo_int64_to_int32(_cairo_int64_rsl (temp, CAIRO_FIXED_FRAC_BITS));
}
/* computes a * b / c */
static inline cairo_fixed_t
_cairo_fixed_mul_div (cairo_fixed_t a, cairo_fixed_t b, cairo_fixed_t c)
{
cairo_int64_t ab = _cairo_int32x32_64_mul (a, b);
cairo_int64_t c64 = _cairo_int32_to_int64 (c);
cairo_int64_t quo = _cairo_int64_divrem (ab, c64).quo;
return _cairo_int64_to_int32(quo);
}
#else
# error Please define multiplication and other operands for your fixed-point type size
#endif

Просмотреть файл

@ -63,8 +63,6 @@ _cairo_font_face_set_error (cairo_font_face_t *font_face,
if (status == CAIRO_STATUS_SUCCESS)
return status;
/* Don't overwrite an existing error. This preserves the first
* error, which is the most significant. */
_cairo_status_set_error (&font_face->status, status);
return _cairo_error (status);
@ -134,8 +132,7 @@ cairo_font_face_destroy (cairo_font_face_t *font_face)
if (! _cairo_reference_count_dec_and_test (&font_face->ref_count))
return;
if (font_face->backend->destroy)
font_face->backend->destroy (font_face);
font_face->backend->destroy (font_face);
/* We allow resurrection to deal with some memory management for the
* FreeType backend where cairo_ft_font_face_t and cairo_ft_unscaled_font_t
@ -537,7 +534,7 @@ _cairo_unscaled_font_destroy (cairo_unscaled_font_t *unscaled_font)
}
void
_cairo_font_face_reset_static_data (void)
_cairo_font_reset_static_data (void)
{
_cairo_scaled_font_map_destroy ();

Просмотреть файл

@ -95,6 +95,7 @@ cairo_font_options_create (void)
return options;
}
slim_hidden_def (cairo_font_options_create);
/**
* cairo_font_options_copy:
@ -143,6 +144,7 @@ cairo_font_options_destroy (cairo_font_options_t *options)
free (options);
}
slim_hidden_def (cairo_font_options_destroy);
/**
* cairo_font_options_status:

Просмотреть файл

@ -1,4 +1,3 @@
/* -*- Mode: c; c-basic-offset: 4; indent-tabs-mode: t; tab-width: 8; -*- */
/* cairo - a vector graphics library with display and print output
*
* Copyright © 2000 Keith Packard
@ -92,7 +91,7 @@ typedef struct _cairo_ft_font_face cairo_ft_font_face_t;
struct _cairo_ft_unscaled_font {
cairo_unscaled_font_t base;
cairo_bool_t from_face; /* was the FT_Face provided by user? */
cairo_bool_t from_face; /* from cairo_ft_font_face_create_for_ft_face()? */
FT_Face face; /* provided or cached face */
/* only set if from_face is false */
@ -283,22 +282,17 @@ _cairo_ft_unscaled_font_map_unlock (void)
static void
_cairo_ft_unscaled_font_init_key (cairo_ft_unscaled_font_t *key,
cairo_bool_t from_face,
char *filename,
int id,
FT_Face face)
int id)
{
unsigned long hash;
key->from_face = from_face;
key->filename = filename;
key->id = id;
key->face = face;
/* 1607 is just an arbitrary prime. */
hash = _cairo_hash_string (filename);
/* the constants are just arbitrary primes */
hash += ((unsigned long) id) * 1607;
hash += ((unsigned long) face) * 2137;
key->base.hash_entry.hash = hash;
}
@ -326,7 +320,6 @@ _cairo_ft_unscaled_font_init_key (cairo_ft_unscaled_font_t *key,
**/
static cairo_status_t
_cairo_ft_unscaled_font_init (cairo_ft_unscaled_font_t *unscaled,
cairo_bool_t from_face,
const char *filename,
int id,
FT_Face face)
@ -334,9 +327,11 @@ _cairo_ft_unscaled_font_init (cairo_ft_unscaled_font_t *unscaled,
_cairo_unscaled_font_init (&unscaled->base,
&cairo_ft_unscaled_font_backend);
if (from_face) {
if (face) {
unscaled->from_face = TRUE;
_cairo_ft_unscaled_font_init_key (unscaled, TRUE, NULL, 0, face);
unscaled->face = face;
unscaled->filename = NULL;
unscaled->id = 0;
} else {
char *filename_copy;
@ -346,7 +341,8 @@ _cairo_ft_unscaled_font_init (cairo_ft_unscaled_font_t *unscaled,
filename_copy = strdup (filename);
if (filename_copy == NULL)
return _cairo_error (CAIRO_STATUS_NO_MEMORY);
_cairo_ft_unscaled_font_init_key (unscaled, FALSE, filename_copy, id, NULL);
_cairo_ft_unscaled_font_init_key (unscaled, filename_copy, id);
}
unscaled->have_scale = FALSE;
@ -358,6 +354,12 @@ _cairo_ft_unscaled_font_init (cairo_ft_unscaled_font_t *unscaled,
return CAIRO_STATUS_SUCCESS;
}
cairo_bool_t
_cairo_unscaled_font_is_ft (cairo_unscaled_font_t *unscaled_font)
{
return unscaled_font->backend == &cairo_ft_unscaled_font_backend;
}
/**
* _cairo_ft_unscaled_font_fini:
*
@ -389,41 +391,35 @@ _cairo_ft_unscaled_font_keys_equal (const void *key_a,
const cairo_ft_unscaled_font_t *unscaled_a = key_a;
const cairo_ft_unscaled_font_t *unscaled_b = key_b;
if (unscaled_a->id == unscaled_b->id &&
unscaled_a->from_face == unscaled_b->from_face)
{
if (unscaled_a->from_face)
return unscaled_a->face == unscaled_b->face;
if (unscaled_a->filename == NULL && unscaled_b->filename == NULL)
return TRUE;
else if (unscaled_a->filename == NULL || unscaled_b->filename == NULL)
return FALSE;
else
return (strcmp (unscaled_a->filename, unscaled_b->filename) == 0);
}
return FALSE;
return (strcmp (unscaled_a->filename, unscaled_b->filename) == 0 &&
unscaled_a->id == unscaled_b->id);
}
/* Finds or creates a #cairo_ft_unscaled_font_t for the filename/id from
* pattern. Returns a new reference to the unscaled font.
*/
static cairo_ft_unscaled_font_t *
_cairo_ft_unscaled_font_create_internal (cairo_bool_t from_face,
char *filename,
int id,
FT_Face font_face)
_cairo_ft_unscaled_font_create_for_pattern (FcPattern *pattern)
{
cairo_ft_unscaled_font_t key, *unscaled;
cairo_ft_unscaled_font_map_t *font_map;
cairo_status_t status;
FcChar8 *fc_filename;
char *filename;
int id;
if (FcPatternGetString (pattern, FC_FILE, 0, &fc_filename) != FcResultMatch)
goto UNWIND;
filename = (char *) fc_filename;
if (FcPatternGetInteger (pattern, FC_INDEX, 0, &id) != FcResultMatch)
goto UNWIND;
font_map = _cairo_ft_unscaled_font_map_lock ();
if (font_map == NULL)
goto UNWIND;
_cairo_ft_unscaled_font_init_key (&key, from_face, filename, id, font_face);
_cairo_ft_unscaled_font_init_key (&key, filename, id);
/* Return existing unscaled font if it exists in the hash table. */
if (_cairo_hash_table_lookup (font_map->hash_table, &key.base.hash_entry,
@ -441,7 +437,7 @@ _cairo_ft_unscaled_font_create_internal (cairo_bool_t from_face,
goto UNWIND_FONT_MAP_LOCK;
}
status = _cairo_ft_unscaled_font_init (unscaled, from_face, filename, id, font_face);
status = _cairo_ft_unscaled_font_init (unscaled, filename, id, NULL);
if (status)
goto UNWIND_UNSCALED_MALLOC;
@ -464,66 +460,57 @@ UNWIND:
return NULL;
}
static cairo_ft_unscaled_font_t *
_cairo_ft_unscaled_font_create_for_pattern (FcPattern *pattern)
{
FT_Face font_face = NULL;
char *filename = NULL;
int id = 0;
if (FcPatternGetFTFace (pattern, FC_FT_FACE, 0, &font_face) != FcResultMatch) {
FcChar8 *fc_filename = NULL;
if (FcPatternGetString (pattern, FC_FILE, 0, &fc_filename) != FcResultMatch)
goto UNWIND;
filename = (char *) fc_filename;
if (FcPatternGetInteger (pattern, FC_INDEX, 0, &id) != FcResultMatch)
goto UNWIND;
}
return _cairo_ft_unscaled_font_create_internal (font_face != NULL, filename, id, font_face);
UNWIND:
return NULL;
}
static cairo_ft_unscaled_font_t *
_cairo_ft_unscaled_font_create_from_face (FT_Face face)
{
return _cairo_ft_unscaled_font_create_internal (TRUE, NULL, 0, face);
cairo_status_t status;
cairo_ft_unscaled_font_t *unscaled;
unscaled = malloc (sizeof (cairo_ft_unscaled_font_t));
if (unscaled == NULL) {
_cairo_error_throw (CAIRO_STATUS_NO_MEMORY);
return NULL;
}
status = _cairo_ft_unscaled_font_init (unscaled, NULL, 0, face);
if (status) {
free (unscaled);
return NULL;
}
return unscaled;
}
static void
_cairo_ft_unscaled_font_destroy (void *abstract_font)
{
cairo_ft_unscaled_font_t *unscaled = abstract_font;
cairo_ft_unscaled_font_map_t *font_map;
if (unscaled == NULL)
return;
font_map = _cairo_ft_unscaled_font_map_lock ();
/* All created objects must have been mapped in the font map. */
assert (font_map != NULL);
_cairo_hash_table_remove (font_map->hash_table,
&unscaled->base.hash_entry);
if (unscaled->from_face) {
/* See comments in _ft_font_face_destroy about the "zombie" state
* for a _ft_font_face.
*/
if (unscaled->faces && !unscaled->faces->unscaled)
cairo_font_face_destroy (&unscaled->faces->base);
unscaled->face = NULL;
} else {
cairo_ft_unscaled_font_map_t *font_map;
font_map = _cairo_ft_unscaled_font_map_lock ();
/* All created objects must have been mapped in the font map. */
assert (font_map != NULL);
_cairo_hash_table_remove (font_map->hash_table,
&unscaled->base.hash_entry);
_font_map_release_face_lock_held (font_map, unscaled);
_cairo_ft_unscaled_font_map_unlock ();
}
unscaled->face = NULL;
_cairo_ft_unscaled_font_map_unlock ();
_cairo_ft_unscaled_font_fini (unscaled);
}
@ -592,7 +579,7 @@ _cairo_ft_unscaled_font_lock_face (cairo_ft_unscaled_font_t *unscaled)
return face;
}
slim_hidden_def (cairo_ft_scaled_font_lock_face);
/* Unlock unscaled font locked with _cairo_ft_unscaled_font_lock_face
*/
@ -605,7 +592,7 @@ _cairo_ft_unscaled_font_unlock_face (cairo_ft_unscaled_font_t *unscaled)
CAIRO_MUTEX_UNLOCK (unscaled->mutex);
}
slim_hidden_def (cairo_ft_scaled_font_unlock_face);
static cairo_status_t
_compute_transform (cairo_ft_font_transform_t *sf,
@ -624,7 +611,7 @@ _compute_transform (cairo_ft_font_transform_t *sf,
status = _cairo_matrix_compute_scale_factors (scale,
&x_scale, &y_scale,
1);
/* XXX */ 1);
if (status)
return status;
@ -1287,7 +1274,7 @@ typedef struct _cairo_ft_scaled_font {
cairo_ft_options_t ft_options;
} cairo_ft_scaled_font_t;
const cairo_scaled_font_backend_t _cairo_ft_scaled_font_backend;
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.
@ -1532,7 +1519,7 @@ _cairo_ft_scaled_font_create (cairo_ft_unscaled_font_t *unscaled,
status = _cairo_scaled_font_init (&scaled_font->base,
font_face,
font_matrix, ctm, options,
&_cairo_ft_scaled_font_backend);
&cairo_ft_scaled_font_backend);
if (status) {
_cairo_unscaled_font_destroy (&unscaled->base);
free (scaled_font);
@ -1610,7 +1597,7 @@ _cairo_ft_scaled_font_create (cairo_ft_unscaled_font_t *unscaled,
cairo_bool_t
_cairo_scaled_font_is_ft (cairo_scaled_font_t *scaled_font)
{
return scaled_font->backend == &_cairo_ft_scaled_font_backend;
return scaled_font->backend == &cairo_ft_scaled_font_backend;
}
static cairo_status_t
@ -2182,36 +2169,40 @@ _cairo_ft_load_truetype_table (void *abstract_font,
}
static cairo_int_status_t
_cairo_ft_index_to_ucs4(void *abstract_font,
unsigned long index,
uint32_t *ucs4)
_cairo_ft_map_glyphs_to_unicode (void *abstract_font,
cairo_scaled_font_subset_t *font_subset)
{
cairo_ft_scaled_font_t *scaled_font = abstract_font;
cairo_ft_unscaled_font_t *unscaled = scaled_font->unscaled;
FT_Face face;
FT_ULong charcode;
FT_UInt gindex;
FT_UInt glyph;
unsigned long charcode;
unsigned int i;
int count;
face = _cairo_ft_unscaled_font_lock_face (unscaled);
if (!face)
return _cairo_error (CAIRO_STATUS_NO_MEMORY);
*ucs4 = (uint32_t) -1;
charcode = FT_Get_First_Char(face, &gindex);
while (gindex != 0) {
charcode = FT_Get_Next_Char (face, charcode, &gindex);
if (gindex == index) {
*ucs4 = charcode;
break;
}
count = font_subset->num_glyphs;
charcode = FT_Get_First_Char( face, &glyph);
while (glyph != 0 && count > 0)
{
for (i = 0; i < font_subset->num_glyphs; i++) {
if (font_subset->glyphs[i] == glyph) {
font_subset->to_unicode[i] = charcode;
count--;
break;
}
}
charcode = FT_Get_Next_Char (face, charcode, &glyph);
}
_cairo_ft_unscaled_font_unlock_face (unscaled);
return CAIRO_STATUS_SUCCESS;
}
const cairo_scaled_font_backend_t _cairo_ft_scaled_font_backend = {
const cairo_scaled_font_backend_t cairo_ft_scaled_font_backend = {
CAIRO_FONT_TYPE_FT,
_cairo_ft_scaled_font_create_toy,
_cairo_ft_scaled_font_fini,
@ -2220,7 +2211,7 @@ const cairo_scaled_font_backend_t _cairo_ft_scaled_font_backend = {
_cairo_ft_ucs4_to_index,
NULL, /* show_glyphs */
_cairo_ft_load_truetype_table,
_cairo_ft_index_to_ucs4
_cairo_ft_map_glyphs_to_unicode,
};
/* #cairo_ft_font_face_t */
@ -2301,10 +2292,6 @@ _cairo_ft_font_face_scaled_font_create (void *abstract_face,
* derived from a pattern where the user has called
* cairo_ft_font_options_substitute(), so *just* use those load
* flags and ignore the options.
*
* XXX two points about the above comment:
* 1. I don't see how the comment is relevant here,
* 2. What if the face is coming from FC_FT_FACE of a pattern?
*/
ft_options = font_face->ft_options;
@ -2500,7 +2487,7 @@ cairo_ft_font_options_substitute (const cairo_font_options_t *options,
* cairo_set_font_face() or cairo_scaled_font_create(). The
* #cairo_scaled_font_t returned from cairo_scaled_font_create() is
* also for the FreeType backend and can be used with functions such
* as cairo_ft_scaled_font_lock_face().
* as cairo_ft_font_lock_face().
*
* Font rendering options are represented both here and when you
* call cairo_scaled_font_create(). Font options that have a representation
@ -2508,17 +2495,6 @@ cairo_ft_font_options_substitute (const cairo_font_options_t *options,
* appropriately to reflect the options in a #cairo_font_options_t, call
* cairo_ft_font_options_substitute().
*
* The pattern's FC_FT_FACE element is inspected first and if that is set,
* that will be the FreeType font face associated with the returned cairo
* font face. Otherwise the FC_FILE and FC_INDEX elements of @pattern are
* used to load a font face from file.
*
* If the FC_FT_FACE element of @pattern is set, the user is responsible
* for making sure that the referenced FT_Face remains valid for the life
* time of the returned #cairo_font_face_t. See
* cairo_ft_font_face_create_for_ft_face() for an exmaple of how to couple
* the life time of the FT_Face to that of the cairo font-face.
*
* Return value: a newly created #cairo_font_face_t. Free with
* cairo_font_face_destroy() when you are done using it.
**/
@ -2563,23 +2539,7 @@ cairo_ft_font_face_create_for_pattern (FcPattern *pattern)
* cairo_set_font_face() or cairo_scaled_font_create(). The
* #cairo_scaled_font_t returned from cairo_scaled_font_create() is
* also for the FreeType backend and can be used with functions such
* as cairo_ft_scaled_font_lock_face().
*
* As an example, here is how one might correctly couple the lifetime of
* the FreeType face object to the #cairo_font_face_t:
*
* <informalexample><programlisting>
* static const cairo_user_data_key_t key;
*
* font_face = cairo_ft_font_face_create_for_ft_face (ft_face, 0);
* status = cairo_font_face_set_user_data (font_face, &key,
* ft_face, (cairo_destroy_func_t) FT_Done_Face);
* if (status) {
* cairo_font_face_destroy (font_face);
* FT_Done_Face (ft_face);
* return ERROR;
* }
* </programlisting></informalexample>
* as cairo_ft_font_lock_face().
*
* Return value: a newly created #cairo_font_face_t. Free with
* cairo_font_face_destroy() when you are done using it.
@ -2613,16 +2573,16 @@ cairo_ft_font_face_create_for_ft_face (FT_Face face,
* @scaled_font: A #cairo_scaled_font_t from the FreeType font backend. Such an
* object can be created by calling cairo_scaled_font_create() on a
* FreeType backend font face (see cairo_ft_font_face_create_for_pattern(),
* cairo_ft_font_face_create_for_ft_face()).
* cairo_ft_font_face_create_for_face()).
*
* cairo_ft_scaled_font_lock_face() gets the #FT_Face object from a FreeType
* cairo_ft_font_lock_face() gets the #FT_Face object from a FreeType
* backend font and scales it appropriately for the font. You must
* release the face with cairo_ft_scaled_font_unlock_face()
* release the face with cairo_ft_font_unlock_face()
* when you are done using it. Since the #FT_Face object can be
* shared between multiple #cairo_scaled_font_t objects, you must not
* lock any other font objects until you unlock this one. A count is
* kept of the number of times cairo_ft_scaled_font_lock_face() is
* called. cairo_ft_scaled_font_unlock_face() must be called the same number
* kept of the number of times cairo_ft_font_lock_face() is
* called. cairo_ft_font_unlock_face() must be called the same number
* of times.
*
* You must be careful when using this function in a library or in a
@ -2645,11 +2605,6 @@ cairo_ft_scaled_font_lock_face (cairo_scaled_font_t *abstract_font)
FT_Face face;
cairo_status_t status;
if (! _cairo_scaled_font_is_ft (abstract_font)) {
_cairo_error_throw (CAIRO_STATUS_FONT_TYPE_MISMATCH);
return NULL;
}
if (scaled_font->base.status)
return NULL;
@ -2692,11 +2647,6 @@ cairo_ft_scaled_font_unlock_face (cairo_scaled_font_t *abstract_font)
{
cairo_ft_scaled_font_t *scaled_font = (cairo_ft_scaled_font_t *) abstract_font;
if (! _cairo_scaled_font_is_ft (abstract_font)) {
_cairo_error_throw (CAIRO_STATUS_FONT_TYPE_MISMATCH);
return;
}
if (scaled_font->base.status)
return;

Просмотреть файл

@ -37,8 +37,8 @@
#ifndef CAIRO_FT_PRIVATE_H
#define CAIRO_FT_PRIVATE_H
#include "cairo-ft.h"
#include "cairoint.h"
#include <cairo-ft.h>
#include <cairoint.h>
#if CAIRO_HAS_FT_FONT
@ -46,6 +46,9 @@ CAIRO_BEGIN_DECLS
typedef struct _cairo_ft_unscaled_font cairo_ft_unscaled_font_t;
cairo_private cairo_bool_t
_cairo_unscaled_font_is_ft (cairo_unscaled_font_t *unscaled_font);
cairo_private cairo_bool_t
_cairo_scaled_font_is_ft (cairo_scaled_font_t *scaled_font);
@ -64,6 +67,9 @@ _cairo_ft_unscaled_font_unlock_face (cairo_ft_unscaled_font_t *unscaled);
cairo_private cairo_bool_t
_cairo_ft_scaled_font_is_vertical (cairo_scaled_font_t *scaled_font);
slim_hidden_proto (cairo_ft_scaled_font_lock_face);
slim_hidden_proto (cairo_ft_scaled_font_unlock_face);
CAIRO_END_DECLS
#endif /* CAIRO_HAS_FT_FONT */

Просмотреть файл

@ -37,7 +37,7 @@
#ifndef CAIRO_FT_H
#define CAIRO_FT_H
#include "cairo.h"
#include <cairo.h>
#if CAIRO_HAS_FT_FONT

Просмотреть файл

@ -958,7 +958,7 @@ _cairo_glitz_pattern_acquire_surfaces (cairo_pattern_t *src,
cairo_glitz_surface_attributes_t *mattr)
{
cairo_int_status_t status;
cairo_solid_pattern_t tmp;
cairo_pattern_union_t tmp;
/* If src and mask are both solid, then the mask alpha can be
* combined into src and mask can be ignored. */
@ -977,7 +977,10 @@ _cairo_glitz_pattern_acquire_surfaces (cairo_pattern_t *src,
combined = src_solid->color;
_cairo_color_multiply_alpha (&combined, mask_solid->color.alpha);
_cairo_pattern_init_solid (&tmp, &combined, CAIRO_CONTENT_COLOR_ALPHA);
_cairo_pattern_init_solid (&tmp.solid, &combined,
CAIRO_COLOR_IS_OPAQUE (&combined) ?
CAIRO_CONTENT_COLOR :
CAIRO_CONTENT_COLOR_ALPHA);
mask = NULL;
} else {
@ -1161,7 +1164,8 @@ _cairo_glitz_surface_fill_rectangles (void *abstract_dst,
_cairo_surface_create_similar_solid (&dst->base,
CAIRO_CONTENT_COLOR_ALPHA,
1, 1,
(cairo_color_t *) color);
(cairo_color_t *) color,
NULL);
if (src->base.status)
return src->base.status;

Просмотреть файл

@ -37,7 +37,7 @@
#ifndef CAIRO_GLITZ_H
#define CAIRO_GLITZ_H
#include "cairo.h"
#include <cairo.h>
#if CAIRO_HAS_GLITZ_SURFACE

Просмотреть файл

@ -64,8 +64,7 @@ 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 *num_transformed_glyphs);
cairo_glyph_t *transformed_glyphs);
cairo_status_t
_cairo_gstate_init (cairo_gstate_t *gstate,
@ -204,6 +203,47 @@ _cairo_gstate_fini (cairo_gstate_t *gstate)
gstate->source = NULL;
}
static void
_cairo_gstate_destroy (cairo_gstate_t *gstate)
{
_cairo_gstate_fini (gstate);
free (gstate);
}
/**
* _cairo_gstate_clone:
* @other: a #cairo_gstate_t to be copied, not %NULL.
*
* Create a new #cairo_gstate_t setting all graphics state parameters
* to the same values as contained in @other. gstate->next will be set
* to %NULL and may be used by the caller to chain #cairo_gstate_t
* objects together.
*
* Return value: a new #cairo_gstate_t or %NULL if there is insufficient
* memory.
**/
static cairo_status_t
_cairo_gstate_clone (cairo_gstate_t *other, cairo_gstate_t **out)
{
cairo_status_t status;
cairo_gstate_t *gstate;
assert (other != NULL);
gstate = malloc (sizeof (cairo_gstate_t));
if (gstate == NULL)
return _cairo_error (CAIRO_STATUS_NO_MEMORY);
status = _cairo_gstate_init_copy (gstate, other);
if (status) {
free (gstate);
return status;
}
*out = gstate;
return CAIRO_STATUS_SUCCESS;
}
/**
* _cairo_gstate_save:
* @gstate: input/output gstate pointer
@ -213,25 +253,14 @@ _cairo_gstate_fini (cairo_gstate_t *gstate)
* copy into @gstate. _cairo_gstate_restore() reverses this.
**/
cairo_status_t
_cairo_gstate_save (cairo_gstate_t **gstate, cairo_gstate_t **freelist)
_cairo_gstate_save (cairo_gstate_t **gstate)
{
cairo_gstate_t *top;
cairo_gstate_t *top = NULL;
cairo_status_t status;
top = *freelist;
if (top == NULL) {
top = malloc (sizeof (cairo_gstate_t));
if (top == NULL)
return _cairo_error (CAIRO_STATUS_NO_MEMORY);
} else
*freelist = top->next;
status = _cairo_gstate_init_copy (top, *gstate);
if (status) {
top->next = *freelist;
*freelist = top;
status = _cairo_gstate_clone (*gstate, &top);
if (status)
return status;
}
top->next = *gstate;
*gstate = top;
@ -246,7 +275,7 @@ _cairo_gstate_save (cairo_gstate_t **gstate, cairo_gstate_t **freelist)
* Reverses the effects of one _cairo_gstate_save() call.
**/
cairo_status_t
_cairo_gstate_restore (cairo_gstate_t **gstate, cairo_gstate_t **freelist)
_cairo_gstate_restore (cairo_gstate_t **gstate)
{
cairo_gstate_t *top;
@ -256,9 +285,7 @@ _cairo_gstate_restore (cairo_gstate_t **gstate, cairo_gstate_t **freelist)
*gstate = top->next;
_cairo_gstate_fini (top);
top->next = *freelist;
*freelist = top;
_cairo_gstate_destroy (top);
return CAIRO_STATUS_SUCCESS;
}
@ -1147,21 +1174,6 @@ _cairo_gstate_clip (cairo_gstate_t *gstate, cairo_path_fixed_t *path)
gstate->antialias, gstate->target);
}
static cairo_status_t
_cairo_gstate_int_clip_extents (cairo_gstate_t *gstate,
cairo_rectangle_int_t *extents)
{
cairo_status_t status;
status = _cairo_surface_get_extents (gstate->target, extents);
if (status)
return status;
status = _cairo_clip_intersect_to_rectangle (&gstate->clip, extents);
return status;
}
cairo_status_t
_cairo_gstate_clip_extents (cairo_gstate_t *gstate,
double *x1,
@ -1172,7 +1184,11 @@ _cairo_gstate_clip_extents (cairo_gstate_t *gstate,
cairo_rectangle_int_t extents;
cairo_status_t status;
status = _cairo_gstate_int_clip_extents (gstate, &extents);
status = _cairo_surface_get_extents (gstate->target, &extents);
if (status)
return status;
status = _cairo_clip_intersect_to_rectangle (&gstate->clip, &extents);
if (status)
return status;
@ -1497,21 +1513,10 @@ _cairo_gstate_glyph_extents (cairo_gstate_t *gstate,
return cairo_scaled_font_status (gstate->scaled_font);
}
cairo_bool_t
_cairo_gstate_has_show_text_glyphs (cairo_gstate_t *gstate)
{
return _cairo_surface_has_show_text_glyphs (gstate->target);
}
cairo_status_t
_cairo_gstate_show_text_glyphs (cairo_gstate_t *gstate,
const char *utf8,
int utf8_len,
const cairo_glyph_t *glyphs,
int num_glyphs,
const cairo_text_cluster_t *clusters,
int num_clusters,
cairo_bool_t backward)
_cairo_gstate_show_glyphs (cairo_gstate_t *gstate,
const cairo_glyph_t *glyphs,
int num_glyphs)
{
cairo_status_t status;
cairo_pattern_union_t source_pattern;
@ -1538,57 +1543,18 @@ _cairo_gstate_show_text_glyphs (cairo_gstate_t *gstate,
}
_cairo_gstate_transform_glyphs_to_backend (gstate, glyphs, num_glyphs,
transformed_glyphs, &num_glyphs);
if (!num_glyphs)
goto CLEANUP_GLYPHS;
transformed_glyphs);
status = _cairo_gstate_copy_transformed_source (gstate, &source_pattern.base);
if (status)
goto CLEANUP_GLYPHS;
/* For really huge font sizes, we can just do path;fill instead of
* show_glyphs, as show_glyphs would put excess pressure on the cache,
* and moreover, not all components below us correctly handle huge font
* sizes. I wanted to set the limit at 256. But alas, seems like cairo's
* rasterizer is something like ten times slower than freetype's for huge
* sizes. So, no win just yet. For now, do it for insanely-huge sizes,
* just to make sure we don't make anyone unhappy. When we get a really
* fast rasterizer in cairo, we may want to readjust this.
*
* Needless to say, do this only if show_text_glyphs is not available. */
if (_cairo_gstate_has_show_text_glyphs (gstate) ||
_cairo_scaled_font_get_max_scale (gstate->scaled_font) <= 10240) {
status = _cairo_surface_show_text_glyphs (gstate->target,
gstate->op,
&source_pattern.base,
utf8, utf8_len,
transformed_glyphs, num_glyphs,
clusters, num_clusters,
backward,
gstate->scaled_font);
} else {
cairo_path_fixed_t path;
_cairo_path_fixed_init (&path);
CAIRO_MUTEX_LOCK (gstate->scaled_font->mutex);
status = _cairo_scaled_font_glyph_path (gstate->scaled_font,
transformed_glyphs, num_glyphs,
&path);
CAIRO_MUTEX_UNLOCK (gstate->scaled_font->mutex);
if (status == CAIRO_STATUS_SUCCESS)
status = _cairo_surface_fill (gstate->target,
gstate->op,
&source_pattern.base,
&path,
CAIRO_FILL_RULE_WINDING,
gstate->tolerance,
gstate->scaled_font->options.antialias);
_cairo_path_fixed_fini (&path);
}
status = _cairo_surface_show_glyphs (gstate->target,
gstate->op,
&source_pattern.base,
transformed_glyphs,
num_glyphs,
gstate->scaled_font);
_cairo_pattern_fini (&source_pattern.base);
@ -1621,7 +1587,7 @@ _cairo_gstate_glyph_path (cairo_gstate_t *gstate,
return _cairo_error (CAIRO_STATUS_NO_MEMORY);
_cairo_gstate_transform_glyphs_to_backend (gstate, glyphs, num_glyphs,
transformed_glyphs, NULL);
transformed_glyphs);
CAIRO_MUTEX_LOCK (gstate->scaled_font->mutex);
status = _cairo_scaled_font_glyph_path (gstate->scaled_font,
@ -1657,99 +1623,39 @@ _cairo_gstate_get_antialias (cairo_gstate_t *gstate)
* @num_glyphs: the number of elements in @glyphs
* @transformed_glyphs: a pre-allocated array of at least @num_glyphs
* #cairo_glyph_t objects
* @num_transformed_glyphs: the number of elements in @transformed_glyphs
* after dropping out of bounds glyphs, or %NULL if glyphs shouldn't be
* dropped
*
* 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.
*
* This also uses information from the scaled font and the surface to
* cull/drop glyphs that will not be visible.
**/
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 *num_transformed_glyphs)
cairo_glyph_t *transformed_glyphs)
{
int i, j;
int i;
cairo_matrix_t *ctm = &gstate->ctm;
cairo_matrix_t *font_matrix = &gstate->font_matrix;
cairo_matrix_t *device_transform = &gstate->target->device_transform;
cairo_bool_t drop = FALSE;
double x1 = 0, x2 = 0, y1 = 0, y2 = 0;
if (num_transformed_glyphs != NULL) {
cairo_rectangle_int_t surface_extents;
double scale = _cairo_scaled_font_get_max_scale (gstate->scaled_font);
drop = TRUE;
if (_cairo_gstate_int_clip_extents (gstate, &surface_extents))
drop = FALSE; /* unbounded surface */
else {
if (surface_extents.width == 0 || surface_extents.height == 0) {
/* No visible area. Don't draw anything */
*num_transformed_glyphs = 0;
return;
}
/* XXX We currently drop any glyphs that has its position outside
* of the surface boundaries by a safety margin depending on the
* font scale. This however can fail in extreme cases where the
* font has really long swashes for example... We can correctly
* handle that by looking the glyph up and using its device bbox
* to device if it's going to be visible, but I'm not inclined to
* do that now.
*/
x1 = surface_extents.x - 2*scale;
y1 = surface_extents.y - 2*scale;
x2 = surface_extents.x + surface_extents.width + scale;
y2 = surface_extents.y + surface_extents.height + scale;
}
if (!drop)
*num_transformed_glyphs = num_glyphs;
} else
num_transformed_glyphs = &j;
#define KEEP_GLYPH(glyph) (x1 <= glyph.x && glyph.x <= x2 && y1 <= glyph.y && glyph.y <= y2)
if (_cairo_matrix_is_identity (ctm) &&
_cairo_matrix_is_identity (device_transform) &&
font_matrix->x0 == 0 && font_matrix->y0 == 0)
gstate->font_matrix.x0 == 0 && gstate->font_matrix.y0 == 0)
{
if (!drop)
memcpy (transformed_glyphs, glyphs, num_glyphs * sizeof (cairo_glyph_t));
else {
for (j = 0, i = 0; i < num_glyphs; i++)
{
transformed_glyphs[j].index = glyphs[i].index;
transformed_glyphs[j].x = glyphs[i].x;
transformed_glyphs[j].y = glyphs[i].y;
if (KEEP_GLYPH (transformed_glyphs[j]))
j++;
}
*num_transformed_glyphs = j;
}
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 = font_matrix->x0 + ctm->x0 + device_transform->x0;
double ty = font_matrix->y0 + ctm->y0 + device_transform->y0;
double tx = gstate->font_matrix.x0 + ctm->x0 + device_transform->x0;
double ty = gstate->font_matrix.y0 + ctm->y0 + device_transform->y0;
for (j = 0, i = 0; i < num_glyphs; i++)
for (i = 0; i < num_glyphs; i++)
{
transformed_glyphs[j].index = glyphs[i].index;
transformed_glyphs[j].x = glyphs[i].x + tx;
transformed_glyphs[j].y = glyphs[i].y + ty;
if (!drop || KEEP_GLYPH (transformed_glyphs[j]))
j++;
transformed_glyphs[i].index = glyphs[i].index;
transformed_glyphs[i].x = glyphs[i].x + tx;
transformed_glyphs[i].y = glyphs[i].y + ty;
}
*num_transformed_glyphs = j;
}
else
{
@ -1763,15 +1669,12 @@ _cairo_gstate_transform_glyphs_to_backend (cairo_gstate_t *gstate,
cairo_matrix_multiply (&aggregate_transform,
&aggregate_transform, device_transform);
for (j = 0, i = 0; i < num_glyphs; i++)
for (i = 0; i < num_glyphs; i++)
{
transformed_glyphs[j] = glyphs[i];
transformed_glyphs[i] = glyphs[i];
cairo_matrix_transform_point (&aggregate_transform,
&transformed_glyphs[j].x,
&transformed_glyphs[j].y);
if (!drop || KEEP_GLYPH (transformed_glyphs[j]))
j++;
&transformed_glyphs[i].x,
&transformed_glyphs[i].y);
}
*num_transformed_glyphs = j;
}
}

Просмотреть файл

@ -296,7 +296,7 @@ _cairo_hash_table_lookup_internal (cairo_hash_table_t *hash_table,
* size.
*
* Return value: %CAIRO_STATUS_SUCCESS if successful or
* %CAIRO_STATUS_NO_MEMORY if out of memory.
* CAIRO_STATUS_NO_MEMORY if out of memory.
**/
static cairo_status_t
_cairo_hash_table_resize (cairo_hash_table_t *hash_table)
@ -401,7 +401,7 @@ _cairo_hash_table_lookup (cairo_hash_table_t *hash_table,
*
* Return value: a random live entry or %NULL if there are no entries
* that match the given predicate. In particular, if predicate is
* %NULL, a %NULL return value indicates that the table is empty.
* NULL, a %NULL return value indicates that the table is empty.
**/
void *
_cairo_hash_table_random_entry (cairo_hash_table_t *hash_table,
@ -459,7 +459,7 @@ _cairo_hash_table_random_entry (cairo_hash_table_t *hash_table,
* necessary, use _cairo_hash_table_remove first.
*
* Return value: %CAIRO_STATUS_SUCCESS if successful or
* %CAIRO_STATUS_NO_MEMORY if insufficient memory is available.
* CAIRO_STATUS_NO_MEMORY if insufficient memory is available.
**/
cairo_status_t
_cairo_hash_table_insert (cairo_hash_table_t *hash_table,
@ -504,7 +504,7 @@ _cairo_hash_table_insert (cairo_hash_table_t *hash_table,
* _cairo_hash_table_create).
*
* Return value: %CAIRO_STATUS_SUCCESS if successful or
* %CAIRO_STATUS_NO_MEMORY if out of memory.
* CAIRO_STATUS_NO_MEMORY if out of memory.
**/
void
_cairo_hash_table_remove (cairo_hash_table_t *hash_table,

Просмотреть файл

@ -36,20 +36,22 @@
#include "cairoint.h"
typedef struct cairo_hull {
typedef struct cairo_hull
{
cairo_point_t point;
cairo_slope_t slope;
int discard;
int id;
} cairo_hull_t;
static void
_cairo_hull_init (cairo_hull_t *hull,
cairo_pen_vertex_t *vertices,
int num_vertices)
static cairo_status_t
_cairo_hull_create (cairo_pen_vertex_t *vertices,
int num_vertices,
cairo_hull_t **out)
{
cairo_point_t *p, *extremum, tmp;
int i;
cairo_hull_t *hull;
cairo_point_t *p, *extremum, tmp;
extremum = &vertices[0].point;
for (i = 1; i < num_vertices; i++) {
@ -62,6 +64,10 @@ _cairo_hull_init (cairo_hull_t *hull,
*extremum = vertices[0].point;
vertices[0].point = tmp;
hull = _cairo_malloc_ab (num_vertices, sizeof (cairo_hull_t));
if (hull == NULL)
return _cairo_error (CAIRO_STATUS_NO_MEMORY);
for (i = 0; i < num_vertices; i++) {
hull[i].point = vertices[i].point;
_cairo_slope_init (&hull[i].slope, &hull[0].point, &hull[i].point);
@ -76,6 +82,9 @@ _cairo_hull_init (cairo_hull_t *hull,
if (i != 0 && hull[i].slope.dx == 0 && hull[i].slope.dy == 0)
hull[i].discard = 1;
}
*out = hull;
return CAIRO_STATUS_SUCCESS;
}
static int
@ -187,19 +196,13 @@ _cairo_hull_to_pen (cairo_hull_t *hull, cairo_pen_vertex_t *vertices, int *num_v
cairo_status_t
_cairo_hull_compute (cairo_pen_vertex_t *vertices, int *num_vertices)
{
cairo_hull_t hull_stack[CAIRO_STACK_ARRAY_LENGTH (cairo_hull_t)];
cairo_hull_t *hull;
cairo_status_t status;
cairo_hull_t *hull = NULL;
int num_hull = *num_vertices;
if (num_hull > ARRAY_LENGTH (hull_stack)) {
hull = _cairo_malloc_ab (num_hull, sizeof (cairo_hull_t));
if (hull == NULL)
return _cairo_error (CAIRO_STATUS_NO_MEMORY);
} else {
hull = hull_stack;
}
_cairo_hull_init (hull, vertices, num_hull);
status = _cairo_hull_create (vertices, num_hull, &hull);
if (status)
return status;
qsort (hull + 1, num_hull - 1,
sizeof (cairo_hull_t), _cairo_hull_vertex_compare);
@ -208,8 +211,7 @@ _cairo_hull_compute (cairo_pen_vertex_t *vertices, int *num_vertices)
_cairo_hull_to_pen (hull, vertices, num_vertices);
if (hull != hull_stack)
free (hull);
free (hull);
return CAIRO_STATUS_SUCCESS;
}

Просмотреть файл

@ -124,7 +124,7 @@ _cairo_image_surface_create_for_pixman_image (pixman_image_t *pixman_image,
if (surface == NULL)
return _cairo_surface_create_in_error (_cairo_error (CAIRO_STATUS_NO_MEMORY));
_cairo_surface_init (&surface->base, &_cairo_image_surface_backend,
_cairo_surface_init (&surface->base, &cairo_image_surface_backend,
_cairo_content_from_pixman_format (pixman_format));
surface->pixman_image = pixman_image;
@ -392,8 +392,7 @@ _cairo_image_surface_create_with_content (cairo_content_t content,
* stride = cairo_format_stride_for_width (format, width);
* data = malloc (stride * height);
* surface = cairo_image_surface_create_for_data (data, format,
* width, height,
* stride);
* width, height);
* </programlisting></informalexample>
*
* Return value: the appropriate stride to use given the desired
@ -1193,7 +1192,7 @@ _cairo_image_surface_set_clip_region (void *abstract_surface,
{
cairo_image_surface_t *surface = (cairo_image_surface_t *) abstract_surface;
if (! pixman_image_set_clip_region32 (surface->pixman_image, &region->rgn))
if (! pixman_image_set_clip_region (surface->pixman_image, &region->rgn))
return _cairo_error (CAIRO_STATUS_NO_MEMORY);
surface->has_clip = region != NULL;
@ -1247,10 +1246,10 @@ _cairo_image_surface_reset (void *abstract_surface)
cairo_bool_t
_cairo_surface_is_image (const cairo_surface_t *surface)
{
return surface->backend == &_cairo_image_surface_backend;
return surface->backend == &cairo_image_surface_backend;
}
const cairo_surface_backend_t _cairo_image_surface_backend = {
const cairo_surface_backend_t cairo_image_surface_backend = {
CAIRO_SURFACE_TYPE_IMAGE,
_cairo_image_surface_create_similar,
_cairo_image_surface_finish,

Просмотреть файл

@ -82,7 +82,7 @@ _lzw_buf_init (lzw_buf_t *buf, int size)
/* Increase the buffer size by doubling.
*
* Returns %CAIRO_STATUS_SUCCESS or %CAIRO_STATUS_NO_MEMORY
* Returns %CAIRO_STATUS_SUCCESS or CAIRO_STATUS_NO_MEMORY
*/
static cairo_status_t
_lzw_buf_grow (lzw_buf_t *buf)

Просмотреть файл

@ -423,18 +423,6 @@ _cairo_matrix_transform_bounding_box (const cairo_matrix_t *matrix,
}
}
cairo_private void
_cairo_matrix_transform_bounding_box_fixed (const cairo_matrix_t *matrix,
cairo_box_t *bbox,
cairo_bool_t *is_tight)
{
double x1, y1, x2, y2;
_cairo_box_to_doubles (bbox, &x1, &y1, &x2, &y2);
_cairo_matrix_transform_bounding_box (matrix, &x1, &y1, &x2, &y2, is_tight);
_cairo_box_from_doubles (bbox, &x1, &y1, &x2, &y2);
}
static void
_cairo_matrix_scalar_multiply (cairo_matrix_t *matrix, double scalar)
{
@ -490,10 +478,10 @@ cairo_matrix_invert (cairo_matrix_t *matrix)
_cairo_matrix_compute_determinant (matrix, &det);
if (! ISFINITE (det))
if (det == 0)
return _cairo_error (CAIRO_STATUS_INVALID_MATRIX);
if (det == 0)
if (! ISFINITE (det))
return _cairo_error (CAIRO_STATUS_INVALID_MATRIX);
_cairo_matrix_compute_adjoint (matrix);
@ -510,7 +498,7 @@ _cairo_matrix_is_invertible (const cairo_matrix_t *matrix)
_cairo_matrix_compute_determinant (matrix, &det);
return ISFINITE (det) && det != 0.;
return det != 0. && ISFINITE (det);
}
void
@ -725,10 +713,6 @@ _cairo_matrix_is_integer_translation (const cairo_matrix_t *matrix,
(Note that the minor axis length is at the minimum of the above solution,
which is just sqrt ( f - sqrt(g² + h²) ) given the symmetry of (D)).
For another derivation of the same result, using Singular Value Decomposition,
see doc/tutorial/src/singular.c.
*/
/* determine the length of the major axis of a circle of the given radius

Просмотреть файл

@ -46,7 +46,7 @@ typedef enum {
CAIRO_COMMAND_MASK,
CAIRO_COMMAND_STROKE,
CAIRO_COMMAND_FILL,
CAIRO_COMMAND_SHOW_TEXT_GLYPHS,
CAIRO_COMMAND_SHOW_GLYPHS,
/* Other junk. For most of these, we should be able to assert that
* they never get called except as part of fallbacks for the 5
@ -104,19 +104,14 @@ typedef struct _cairo_command_fill {
cairo_antialias_t antialias;
} cairo_command_fill_t;
typedef struct _cairo_command_show_text_glyphs {
typedef struct _cairo_command_show_glyphs {
cairo_command_header_t header;
cairo_operator_t op;
cairo_pattern_union_t source;
char *utf8;
int utf8_len;
cairo_glyph_t *glyphs;
unsigned int num_glyphs;
cairo_text_cluster_t *clusters;
int num_clusters;
cairo_bool_t backward;
cairo_scaled_font_t *scaled_font;
} cairo_command_show_text_glyphs_t;
} cairo_command_show_glyphs_t;
typedef struct _cairo_command_intersect_clip_path {
cairo_command_header_t header;
@ -135,7 +130,7 @@ typedef union _cairo_command {
cairo_command_mask_t mask;
cairo_command_stroke_t stroke;
cairo_command_fill_t fill;
cairo_command_show_text_glyphs_t show_text_glyphs;
cairo_command_show_glyphs_t show_glyphs;
/* The other junk. */
cairo_command_intersect_clip_path_t intersect_clip_path;
@ -164,10 +159,6 @@ _cairo_meta_surface_create (cairo_content_t content,
int width_pixels,
int height_pixels);
cairo_private cairo_int_status_t
_cairo_meta_surface_get_path (cairo_surface_t *surface,
cairo_path_fixed_t *path);
cairo_private cairo_status_t
_cairo_meta_surface_replay (cairo_surface_t *surface,
cairo_surface_t *target);

Просмотреть файл

@ -39,7 +39,7 @@
/* A meta surface is a surface that records all drawing operations at
* the highest level of the surface backend interface, (that is, the
* level of paint, mask, stroke, fill, and show_text_glyphs). The meta
* level of paint, mask, stroke, fill, and show_glyphs). The meta
* surface can then be "replayed" against any target surface with:
*
* _cairo_meta_surface_replay (meta, target);
@ -157,12 +157,10 @@ _cairo_meta_surface_finish (void *abstract_surface)
free (command);
break;
case CAIRO_COMMAND_SHOW_TEXT_GLYPHS:
_cairo_pattern_fini (&command->show_text_glyphs.source.base);
free (command->show_text_glyphs.utf8);
free (command->show_text_glyphs.glyphs);
free (command->show_text_glyphs.clusters);
cairo_scaled_font_destroy (command->show_text_glyphs.scaled_font);
case CAIRO_COMMAND_SHOW_GLYPHS:
_cairo_pattern_fini (&command->show_glyphs.source.base);
free (command->show_glyphs.glyphs);
cairo_scaled_font_destroy (command->show_glyphs.scaled_font);
free (command);
break;
@ -428,34 +426,23 @@ _cairo_meta_surface_fill (void *abstract_surface,
return status;
}
static cairo_bool_t
_cairo_meta_surface_has_show_text_glyphs (void *abstract_surface)
{
return TRUE;
}
static cairo_int_status_t
_cairo_meta_surface_show_text_glyphs (void *abstract_surface,
cairo_operator_t op,
cairo_pattern_t *source,
const char *utf8,
int utf8_len,
cairo_glyph_t *glyphs,
int num_glyphs,
const cairo_text_cluster_t *clusters,
int num_clusters,
cairo_bool_t backward,
cairo_scaled_font_t *scaled_font)
_cairo_meta_surface_show_glyphs (void *abstract_surface,
cairo_operator_t op,
cairo_pattern_t *source,
cairo_glyph_t *glyphs,
int num_glyphs,
cairo_scaled_font_t *scaled_font)
{
cairo_status_t status;
cairo_meta_surface_t *meta = abstract_surface;
cairo_command_show_text_glyphs_t *command;
cairo_command_show_glyphs_t *command;
command = malloc (sizeof (cairo_command_show_text_glyphs_t));
command = malloc (sizeof (cairo_command_show_glyphs_t));
if (command == NULL)
return _cairo_error (CAIRO_STATUS_NO_MEMORY);
command->header.type = CAIRO_COMMAND_SHOW_TEXT_GLYPHS;
command->header.type = CAIRO_COMMAND_SHOW_GLYPHS;
command->header.region = CAIRO_META_REGION_ALL;
command->op = op;
@ -463,39 +450,14 @@ _cairo_meta_surface_show_text_glyphs (void *abstract_surface,
if (status)
goto CLEANUP_COMMAND;
command->utf8 = NULL;
command->utf8_len = utf8_len;
command->glyphs = NULL;
command->glyphs = _cairo_malloc_ab (num_glyphs, sizeof (cairo_glyph_t));
if (command->glyphs == NULL) {
status = _cairo_error (CAIRO_STATUS_NO_MEMORY);
goto CLEANUP_SOURCE;
}
memcpy (command->glyphs, glyphs, sizeof (cairo_glyph_t) * num_glyphs);
command->num_glyphs = num_glyphs;
command->clusters = NULL;
command->num_clusters = num_clusters;
if (utf8_len) {
command->utf8 = malloc (utf8_len);
if (command->utf8 == NULL) {
status = _cairo_error (CAIRO_STATUS_NO_MEMORY);
goto CLEANUP_ARRAYS;
}
memcpy (command->utf8, utf8, utf8_len);
}
if (num_glyphs) {
command->glyphs = _cairo_malloc_ab (num_glyphs, sizeof (glyphs[0]));
if (command->glyphs == NULL) {
status = _cairo_error (CAIRO_STATUS_NO_MEMORY);
goto CLEANUP_ARRAYS;
}
memcpy (command->glyphs, glyphs, sizeof (glyphs[0]) * num_glyphs);
}
if (num_clusters) {
command->clusters = _cairo_malloc_ab (num_clusters, sizeof (clusters[0]));
if (command->clusters == NULL) {
status = _cairo_error (CAIRO_STATUS_NO_MEMORY);
goto CLEANUP_ARRAYS;
}
memcpy (command->clusters, clusters, sizeof (clusters[0]) * num_clusters);
}
command->backward = backward;
command->scaled_font = cairo_scaled_font_reference (scaled_font);
@ -507,11 +469,8 @@ _cairo_meta_surface_show_text_glyphs (void *abstract_surface,
CLEANUP_SCALED_FONT:
cairo_scaled_font_destroy (command->scaled_font);
CLEANUP_ARRAYS:
free (command->utf8);
free (command->glyphs);
free (command->clusters);
CLEANUP_SOURCE:
_cairo_pattern_fini (&command->source.base);
CLEANUP_COMMAND:
free (command);
@ -526,7 +485,7 @@ _cairo_meta_surface_show_text_glyphs (void *abstract_surface,
* surface-modifying function on the result of this function.
*
* The caller owns the return value and should call
* cairo_surface_destroy() when finished with it. This function will not
* cairo_surface_destroy when finished with it. This function will not
* return %NULL, but will return a nil surface instead.
*
* Return value: The snapshot surface.
@ -611,9 +570,6 @@ _cairo_meta_surface_get_extents (void *abstract_surface,
{
cairo_meta_surface_t *surface = abstract_surface;
if (surface->width_pixels == -1 && surface->height_pixels == -1)
return CAIRO_INT_STATUS_UNSUPPORTED;
rectangle->x = 0;
rectangle->y = 0;
rectangle->width = surface->width_pixels;
@ -662,24 +618,15 @@ static const cairo_surface_backend_t cairo_meta_surface_backend = {
/* Here are the 5 basic drawing operations, (which are in some
* sense the only things that cairo_meta_surface should need to
* implement). However, we implement the more generic show_text_glyphs
* instead of show_glyphs. One or the other is eough. */
* implement). */
_cairo_meta_surface_paint,
_cairo_meta_surface_mask,
_cairo_meta_surface_stroke,
_cairo_meta_surface_fill,
NULL,
_cairo_meta_surface_show_glyphs,
_cairo_meta_surface_snapshot,
NULL, /* is_similar */
NULL, /* reset */
NULL, /* fill_stroke */
NULL, /* create_solid_pattern_surface */
_cairo_meta_surface_has_show_text_glyphs,
_cairo_meta_surface_show_text_glyphs
_cairo_meta_surface_snapshot
};
static cairo_path_fixed_t *
@ -688,7 +635,7 @@ _cairo_command_get_path (cairo_command_t *command)
switch (command->header.type) {
case CAIRO_COMMAND_PAINT:
case CAIRO_COMMAND_MASK:
case CAIRO_COMMAND_SHOW_TEXT_GLYPHS:
case CAIRO_COMMAND_SHOW_GLYPHS:
return NULL;
case CAIRO_COMMAND_STROKE:
return &command->stroke.path;
@ -702,78 +649,6 @@ _cairo_command_get_path (cairo_command_t *command)
return NULL;
}
cairo_int_status_t
_cairo_meta_surface_get_path (cairo_surface_t *surface,
cairo_path_fixed_t *path)
{
cairo_meta_surface_t *meta;
cairo_command_t *command, **elements;
int i, num_elements;
cairo_int_status_t status;
if (surface->status)
return surface->status;
meta = (cairo_meta_surface_t *) surface;
status = CAIRO_STATUS_SUCCESS;
num_elements = meta->commands.num_elements;
elements = _cairo_array_index (&meta->commands, 0);
for (i = meta->replay_start_idx; i < num_elements; i++) {
command = elements[i];
switch (command->header.type) {
case CAIRO_COMMAND_PAINT:
case CAIRO_COMMAND_MASK:
case CAIRO_COMMAND_INTERSECT_CLIP_PATH:
status = CAIRO_INT_STATUS_UNSUPPORTED;
break;
case CAIRO_COMMAND_STROKE:
{
cairo_traps_t traps;
_cairo_traps_init (&traps);
/* XXX call cairo_stroke_to_path() when that is implemented */
status = _cairo_path_fixed_stroke_to_traps (&command->stroke.path,
&command->stroke.style,
&command->stroke.ctm,
&command->stroke.ctm_inverse,
command->stroke.tolerance,
&traps);
if (status == CAIRO_STATUS_SUCCESS)
status = _cairo_traps_path (&traps, path);
_cairo_traps_fini (&traps);
break;
}
case CAIRO_COMMAND_FILL:
{
status = _cairo_path_fixed_append (path, &command->fill.path, CAIRO_DIRECTION_FORWARD);
break;
}
case CAIRO_COMMAND_SHOW_TEXT_GLYPHS:
{
status = _cairo_scaled_font_glyph_path (command->show_text_glyphs.scaled_font,
command->show_text_glyphs.glyphs,
command->show_text_glyphs.num_glyphs,
path);
break;
}
default:
ASSERT_NOT_REACHED;
}
if (status)
break;
}
return _cairo_surface_set_error (surface, status);
}
static cairo_status_t
_cairo_meta_surface_replay_internal (cairo_surface_t *surface,
cairo_surface_t *target,
@ -824,7 +699,7 @@ _cairo_meta_surface_replay_internal (cairo_surface_t *surface,
status = _cairo_path_fixed_init_copy (&path_copy, dev_path);
if (status)
break;
_cairo_path_fixed_transform (&path_copy, device_transform);
_cairo_path_fixed_device_transform (&path_copy, device_transform);
dev_path = &path_copy;
}
@ -923,13 +798,13 @@ _cairo_meta_surface_replay_internal (cairo_surface_t *surface,
command->fill.antialias);
break;
}
case CAIRO_COMMAND_SHOW_TEXT_GLYPHS:
case CAIRO_COMMAND_SHOW_GLYPHS:
{
cairo_glyph_t *glyphs = command->show_text_glyphs.glyphs;
cairo_glyph_t *glyphs = command->show_glyphs.glyphs;
cairo_glyph_t *dev_glyphs;
int i, num_glyphs = command->show_text_glyphs.num_glyphs;
int i, num_glyphs = command->show_glyphs.num_glyphs;
/* show_text_glyphs is special because _cairo_surface_show_text_glyphs is allowed
/* show_glyphs is special because _cairo_surface_show_glyphs is allowed
* to modify the glyph array that's passed in. We must always
* copy the array before handing it to the backend.
*/
@ -950,14 +825,11 @@ _cairo_meta_surface_replay_internal (cairo_surface_t *surface,
memcpy (dev_glyphs, glyphs, sizeof (cairo_glyph_t) * num_glyphs);
}
status = _cairo_surface_show_text_glyphs (target,
command->show_text_glyphs.op,
&command->show_text_glyphs.source.base,
command->show_text_glyphs.utf8, command->show_text_glyphs.utf8_len,
dev_glyphs, num_glyphs,
command->show_text_glyphs.clusters, command->show_text_glyphs.num_clusters,
command->show_text_glyphs.backward,
command->show_text_glyphs.scaled_font);
status = _cairo_surface_show_glyphs (target,
command->show_glyphs.op,
&command->show_glyphs.source.base,
dev_glyphs, num_glyphs,
command->show_glyphs.scaled_font);
free (dev_glyphs);
break;
@ -1015,7 +887,7 @@ _cairo_meta_surface_replay (cairo_surface_t *surface,
/* Replay meta to surface. When the return status of each operation is
* one of %CAIRO_STATUS_SUCCESS, %CAIRO_INT_STATUS_UNSUPPORTED, or
* %CAIRO_INT_STATUS_FLATTEN_TRANSPARENCY the status of each operation
* CAIRO_INT_STATUS_FLATTEN_TRANSPARENCY the status of each operation
* will be stored in the meta surface. Any other status will abort the
* replay and return the status.
*/

Просмотреть файл

@ -38,8 +38,6 @@
#include "cairoint.h"
COMPILE_TIME_ASSERT (CAIRO_STATUS_LAST_STATUS < CAIRO_INT_STATUS_UNSUPPORTED);
COMPILE_TIME_ASSERT (CAIRO_INT_STATUS_LAST_STATUS <= 127);
/**
* cairo_status_to_string:
@ -103,16 +101,6 @@ cairo_status_to_string (cairo_status_t status)
return "error creating or writing to a temporary file";
case CAIRO_STATUS_INVALID_STRIDE:
return "invalid value for stride";
case CAIRO_STATUS_FONT_TYPE_MISMATCH:
return "the font type is not appropriate for the operation";
case CAIRO_STATUS_USER_FONT_IMMUTABLE:
return "the user-font is immutable";
case CAIRO_STATUS_USER_FONT_ERROR:
return "error occurred in a user-font callback function";
case CAIRO_STATUS_NEGATIVE_COUNT:
return "negative number used where it is not allowed";
case CAIRO_STATUS_INVALID_CLUSTERS:
return "input clusters do not represent the accompanying text and glyph arrays";
}
return "<unknown error status>";

Просмотреть файл

@ -1,226 +0,0 @@
/* cairo - a vector graphics library with display and print output
*
* Copyright © 2002 University of Southern California
* Copyright © 2005,2007 Red Hat, Inc.
* Copyright © 2007 Mathias Hasselmann
*
* 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>
* Mathias Hasselmann <mathias.hasselmann@gmx.de>
* Behdad Esfahbod <behdad@behdad.org>
*/
#ifndef CAIRO_MUTEX_IMPL_PRIVATE_H
#define CAIRO_MUTEX_IMPL_PRIVATE_H
#if HAVE_CONFIG_H
#include "config.h"
#endif
#include "cairo-features.h"
CAIRO_BEGIN_DECLS
/* A fully qualified no-operation statement */
#define CAIRO_MUTEX_IMPL_NOOP do {/*no-op*/} while (0)
/* And one that evaluates it's argument once */
#define CAIRO_MUTEX_IMPL_NOOP1(expr) do { if (expr) ; } while (0)
/* Cairo mutex implementation:
*
* Any new mutex implementation needs to do the following:
*
* - Condition on the right header or feature. Headers are
* preferred as eg. you still can use win32 mutex implementation
* on a win32 system even if you do not compile the win32
* surface/backend.
*
* - typedef #cairo_mutex_impl_t to the proper mutex type on your target
* system. Note that you may or may not need to use a pointer,
* depending on what kinds of initialization your mutex
* implementation supports. No trailing semicolon needed.
* You should be able to compile the following snippet (don't try
* running it):
*
* <programlisting>
* cairo_mutex_impl_t _cairo_some_mutex;
* </programlisting>
*
* - #define CAIRO_MUTEX_IMPL_LOCK(mutex) and CAIRO_MUTEX_IMPL_UNLOCK(mutex) to
* proper statement to lock/unlock the mutex object passed in.
* You can (and should) assume that the mutex is already
* initialized, and is-not-already-locked/is-locked,
* respectively. Use the "do { ... } while (0)" idiom if necessary.
* No trailing semicolons are needed (in any macro you define here).
* You should be able to compile the following snippet:
*
* <programlisting>
* cairo_mutex_impl_t _cairo_some_mutex;
*
* if (1)
* CAIRO_MUTEX_IMPL_LOCK (_cairo_some_mutex);
* else
* CAIRO_MUTEX_IMPL_UNLOCK (_cairo_some_mutex);
* </programlisting>
*
* - #define %CAIRO_MUTEX_IMPL_NIL_INITIALIZER to something that can
* initialize the #cairo_mutex_impl_t type you defined. Most of the
* time one of 0, %NULL, or {} works. At this point
* you should be able to compile the following snippet:
*
* <programlisting>
* cairo_mutex_impl_t _cairo_some_mutex = CAIRO_MUTEX_IMPL_NIL_INITIALIZER;
*
* if (1)
* CAIRO_MUTEX_IMPL_LOCK (_cairo_some_mutex);
* else
* CAIRO_MUTEX_IMPL_UNLOCK (_cairo_some_mutex);
* </programlisting>
*
* - If the above code is not enough to initialize a mutex on
* your platform, #define CAIRO_MUTEX_IMPL_INIT(mutex) to statement
* to initialize the mutex (allocate resources, etc). Such that
* you should be able to compile AND RUN the following snippet:
*
* <programlisting>
* cairo_mutex_impl_t _cairo_some_mutex = CAIRO_MUTEX_IMPL_NIL_INITIALIZER;
*
* CAIRO_MUTEX_IMPL_INIT (_cairo_some_mutex);
*
* if (1)
* CAIRO_MUTEX_IMPL_LOCK (_cairo_some_mutex);
* else
* CAIRO_MUTEX_IMPL_UNLOCK (_cairo_some_mutex);
* </programlisting>
*
* - If you define CAIRO_MUTEX_IMPL_INIT(mutex), cairo will use it to
* initialize all static mutex'es. If for any reason that should
* not happen (eg. %CAIRO_MUTEX_IMPL_INIT is just a faster way than
* what cairo does using %CAIRO_MUTEX_IMPL_NIL_INITIALIZER), then
* <programlisting>
* #define CAIRO_MUTEX_IMPL_INITIALIZE() CAIRO_MUTEX_IMPL_NOOP
* </programlisting>
*
* - If your system supports freeing a mutex object (deallocating
* resources, etc), then #define CAIRO_MUTEX_IMPL_FINI(mutex) to do
* that.
*
* - If you define CAIRO_MUTEX_IMPL_FINI(mutex), cairo will use it to
* define a finalizer function to finalize all static mutex'es.
* However, it's up to you to call CAIRO_MUTEX_IMPL_FINALIZE() at
* proper places, eg. when the system is unloading the cairo library.
* So, if for any reason finalizing static mutex'es is not needed
* (eg. you never call CAIRO_MUTEX_IMPL_FINALIZE()), then
* <programlisting>
* #define CAIRO_MUTEX_IMPL_FINALIZE() CAIRO_MUTEX_IMPL_NOOP
* </programlisting>
*
* - That is all. If for any reason you think the above API is
* not enough to implement #cairo_mutex_impl_t on your system, please
* stop and write to the cairo mailing list about it. DO NOT
* poke around cairo-mutex-private.h for possible solutions.
*/
#ifndef CAIRO_MUTEX_TYPE_PRIVATE_H
#error "Do not include cairo-mutex-impl-private.h directly. Include cairo-mutex-type-private.h instead."
#endif
#if CAIRO_NO_MUTEX
/* No mutexes */
typedef int cairo_mutex_impl_t;
# define CAIRO_MUTEX_IMPL_INITIALIZE() CAIRO_MUTEX_IMPL_NOOP
# define CAIRO_MUTEX_IMPL_LOCK(mutex) CAIRO_MUTEX_IMPL_NOOP1(mutex)
# define CAIRO_MUTEX_IMPL_UNLOCK(mutex) CAIRO_MUTEX_IMPL_NOOP1(mutex)
# define CAIRO_MUTEX_IMPL_NIL_INITIALIZER 0
#elif HAVE_PTHREAD_H /*******************************************************/
# include <pthread.h>
typedef pthread_mutex_t cairo_mutex_impl_t;
# define CAIRO_MUTEX_IMPL_LOCK(mutex) pthread_mutex_lock (&(mutex))
# define CAIRO_MUTEX_IMPL_UNLOCK(mutex) pthread_mutex_unlock (&(mutex))
# define CAIRO_MUTEX_IMPL_FINI(mutex) pthread_mutex_destroy (&(mutex))
# define CAIRO_MUTEX_IMPL_FINALIZE() CAIRO_MUTEX_IMPL_NOOP
# define CAIRO_MUTEX_IMPL_NIL_INITIALIZER PTHREAD_MUTEX_INITIALIZER
#elif HAVE_WINDOWS_H /*******************************************************/
# include <windows.h>
typedef CRITICAL_SECTION cairo_mutex_impl_t;
# define CAIRO_MUTEX_IMPL_LOCK(mutex) EnterCriticalSection (&(mutex))
# define CAIRO_MUTEX_IMPL_UNLOCK(mutex) LeaveCriticalSection (&(mutex))
# define CAIRO_MUTEX_IMPL_INIT(mutex) InitializeCriticalSection (&(mutex))
# define CAIRO_MUTEX_IMPL_FINI(mutex) DeleteCriticalSection (&(mutex))
# define CAIRO_MUTEX_IMPL_NIL_INITIALIZER { NULL, 0, 0, NULL, NULL, 0 }
#elif defined __OS2__ /******************************************************/
# define INCL_BASE
# define INCL_PM
# include <os2.h>
typedef HMTX cairo_mutex_impl_t;
# define CAIRO_MUTEX_IMPL_LOCK(mutex) DosRequestMutexSem(mutex, SEM_INDEFINITE_WAIT)
# define CAIRO_MUTEX_IMPL_UNLOCK(mutex) DosReleaseMutexSem(mutex)
# define CAIRO_MUTEX_IMPL_INIT(mutex) DosCreateMutexSem (NULL, &(mutex), 0L, FALSE)
# define CAIRO_MUTEX_IMPL_FINI(mutex) DosCloseMutexSem (mutex)
# define CAIRO_MUTEX_IMPL_NIL_INITIALIZER 0
#elif CAIRO_HAS_BEOS_SURFACE /***********************************************/
typedef BLocker* cairo_mutex_impl_t;
# define CAIRO_MUTEX_IMPL_LOCK(mutex) (mutex)->Lock()
# define CAIRO_MUTEX_IMPL_UNLOCK(mutex) (mutex)->Unlock()
# define CAIRO_MUTEX_IMPL_INIT(mutex) (mutex) = new BLocker()
# define CAIRO_MUTEX_IMPL_FINI(mutex) delete (mutex)
# define CAIRO_MUTEX_IMPL_NIL_INITIALIZER NULL
#else /**********************************************************************/
# error "XXX: No mutex implementation found. Cairo will not work with multiple threads. Define CAIRO_NO_MUTEX to 1 to acknowledge and accept this limitation and compile cairo without thread-safety support."
#endif
CAIRO_END_DECLS
#endif

Просмотреть файл

@ -41,27 +41,136 @@
#ifndef CAIRO_MUTEX_PRIVATE_H
#define CAIRO_MUTEX_PRIVATE_H
#if HAVE_CONFIG_H
#include "config.h"
#endif
#include <cairo-features.h>
#include "cairo-compiler-private.h"
#include "cairo-mutex-type-private.h"
/* Only the following three are mandatory at this point */
#ifndef CAIRO_MUTEX_LOCK
# error "CAIRO_MUTEX_LOCK not defined. Check cairo-mutex-type-private.h."
#endif
#ifndef CAIRO_MUTEX_UNLOCK
# error "CAIRO_MUTEX_UNLOCK not defined. Check cairo-mutex-type-private.h."
#endif
#ifndef CAIRO_MUTEX_NIL_INITIALIZER
# error "CAIRO_MUTEX_NIL_INITIALIZER not defined. Check cairo-mutex-type-private.h."
#endif
CAIRO_BEGIN_DECLS
#if _CAIRO_MUTEX_IMPL_USE_STATIC_INITIALIZER
cairo_private void _cairo_mutex_initialize (void);
#endif
#if _CAIRO_MUTEX_IMPL_USE_STATIC_FINALIZER
cairo_private void _cairo_mutex_finalize (void);
#endif
/* only if using static initializer and/or finalizer define the boolean */
#if _CAIRO_MUTEX_IMPL_USE_STATIC_INITIALIZER || _CAIRO_MUTEX_IMPL_USE_STATIC_FINALIZER
cairo_private extern cairo_bool_t _cairo_mutex_initialized;
#endif
/* Finally, extern the static mutexes and undef */
#define CAIRO_MUTEX_DECLARE(mutex) cairo_private extern cairo_mutex_t mutex
#define CAIRO_MUTEX_DECLARE(mutex) extern cairo_mutex_t mutex
#include "cairo-mutex-list-private.h"
#undef CAIRO_MUTEX_DECLARE
/* make sure implementations don't fool us: we decide these ourself */
#undef _CAIRO_MUTEX_USE_STATIC_INITIALIZER
#undef _CAIRO_MUTEX_USE_STATIC_FINALIZER
#ifdef CAIRO_MUTEX_INIT
/* If %CAIRO_MUTEX_INIT is defined, we may need to initialize all
* static mutex'es. */
# ifndef CAIRO_MUTEX_INITIALIZE
# define CAIRO_MUTEX_INITIALIZE() do { \
if (!_cairo_mutex_initialized) \
_cairo_mutex_initialize (); \
} while(0)
cairo_private void _cairo_mutex_initialize (void);
/* and make sure we implement the above */
# define _CAIRO_MUTEX_USE_STATIC_INITIALIZER 1
# endif /* CAIRO_MUTEX_INITIALIZE */
#else /* no CAIRO_MUTEX_INIT */
/* Otherwise we probably don't need to initialize static mutex'es, */
# ifndef CAIRO_MUTEX_INITIALIZE
# define CAIRO_MUTEX_INITIALIZE() CAIRO_MUTEX_NOOP
# endif /* CAIRO_MUTEX_INITIALIZE */
/* and dynamic ones can be initialized using the static initializer. */
# define CAIRO_MUTEX_INIT(mutex) do { \
cairo_mutex_t _tmp_mutex = CAIRO_MUTEX_NIL_INITIALIZER; \
memcpy (&(mutex), &_tmp_mutex, sizeof (_tmp_mutex)); \
} while (0)
#endif /* CAIRO_MUTEX_INIT */
#ifdef CAIRO_MUTEX_FINI
/* If %CAIRO_MUTEX_FINI is defined, we may need to finalize all
* static mutex'es. */
# ifndef CAIRO_MUTEX_FINALIZE
# define CAIRO_MUTEX_FINALIZE() do { \
if (_cairo_mutex_initialized) \
_cairo_mutex_finalize (); \
} while(0)
cairo_private void _cairo_mutex_finalize (void);
/* and make sure we implement the above */
# define _CAIRO_MUTEX_USE_STATIC_FINALIZER 1
# endif /* CAIRO_MUTEX_FINALIZE */
#else /* no CAIRO_MUTEX_FINI */
/* Otherwise we probably don't need to finalize static mutex'es, */
# ifndef CAIRO_MUTEX_FINALIZE
# define CAIRO_MUTEX_FINALIZE() CAIRO_MUTEX_NOOP
# endif /* CAIRO_MUTEX_FINALIZE */
/* neither do the dynamic ones. */
# define CAIRO_MUTEX_FINI(mutex) CAIRO_MUTEX_NOOP1(mutex)
#endif /* CAIRO_MUTEX_FINI */
#ifndef _CAIRO_MUTEX_USE_STATIC_INITIALIZER
#define _CAIRO_MUTEX_USE_STATIC_INITIALIZER 0
#endif
#ifndef _CAIRO_MUTEX_USE_STATIC_FINALIZER
#define _CAIRO_MUTEX_USE_STATIC_FINALIZER 0
#endif
/* only if using static initializer and/or finalizer define the boolean */
#if _CAIRO_MUTEX_USE_STATIC_INITIALIZER || _CAIRO_MUTEX_USE_STATIC_FINALIZER
cairo_private extern cairo_bool_t _cairo_mutex_initialized;
#endif
CAIRO_END_DECLS
/* Make sure everything we want is defined */
#ifndef CAIRO_MUTEX_INITIALIZE
# error "CAIRO_MUTEX_INITIALIZE not defined"
#endif
#ifndef CAIRO_MUTEX_FINALIZE
# error "CAIRO_MUTEX_FINALIZE not defined"
#endif
#ifndef CAIRO_MUTEX_LOCK
# error "CAIRO_MUTEX_LOCK not defined"
#endif
#ifndef CAIRO_MUTEX_UNLOCK
# error "CAIRO_MUTEX_UNLOCK not defined"
#endif
#ifndef CAIRO_MUTEX_INIT
# error "CAIRO_MUTEX_INIT not defined"
#endif
#ifndef CAIRO_MUTEX_FINI
# error "CAIRO_MUTEX_FINI not defined"
#endif
#ifndef CAIRO_MUTEX_NIL_INITIALIZER
# error "CAIRO_MUTEX_NIL_INITIALIZER not defined"
#endif
#endif

Просмотреть файл

@ -45,144 +45,166 @@
#include "config.h"
#endif
#include "cairo-features.h"
#include <cairo-features.h>
CAIRO_BEGIN_DECLS
/* A fully qualified no-operation statement */
#define CAIRO_MUTEX_NOOP do {/*no-op*/} while (0)
/* And one that evaluates it's argument once */
#define CAIRO_MUTEX_NOOP1(expr) do { if (expr) ; } while (0)
/* Cairo mutex implementation:
*
* Any new mutex implementation needs to do the following:
*
* - Condition on the right header or feature. Headers are
* preferred as eg. you still can use win32 mutex implementation
* on a win32 system even if you do not compile the win32
* surface/backend.
*
* - typedef #cairo_mutex_t to the proper mutex type on your target
* system. Note that you may or may not need to use a pointer,
* depending on what kinds of initialization your mutex
* implementation supports. No trailing semicolon needed.
* You should be able to compile the following snippet (don't try
* running it):
*
* cairo_mutex_t _cairo_some_mutex;
*
* - #define CAIRO_MUTEX_LOCK(mutex) and CAIRO_MUTEX_UNLOCK(mutex) to
* proper statement to lock/unlock the mutex object passed in.
* You can (and should) assume that the mutex is already
* initialized, and is-not-already-locked/is-locked,
* respectively. Use the "do { ... } while (0)" idiom if necessary.
* No trailing semicolons are needed (in any macro you define here).
* You should be able to compile the following snippet:
*
* cairo_mutex_t _cairo_some_mutex;
*
* if (1)
* %CAIRO_MUTEX_LOCK (_cairo_some_mutex);
* else
* %CAIRO_MUTEX_UNLOCK (_cairo_some_mutex);
*
* - #define %CAIRO_MUTEX_NIL_INITIALIZER to something that can
* initialize the #cairo_mutex_t type you defined. Most of the
* time one of 0, %NULL, or {} works. At this point
* you should be able to compile the following snippet:
*
* cairo_mutex_t _cairo_some_mutex = CAIRO_MUTEX_NIL_INITIALIZER;
*
* if (1)
* %CAIRO_MUTEX_LOCK (_cairo_some_mutex);
* else
* %CAIRO_MUTEX_UNLOCK (_cairo_some_mutex);
*
* - If the above code is not enough to initialize a mutex on
* your platform, #define CAIRO_MUTEX_INIT(mutex) to statement
* to initialize the mutex (allocate resources, etc). Such that
* you should be able to compile AND RUN the following snippet:
*
* cairo_mutex_t _cairo_some_mutex = CAIRO_MUTEX_NIL_INITIALIZER;
*
* %CAIRO_MUTEX_INIT (_cairo_some_mutex);
*
* if (1)
* %CAIRO_MUTEX_LOCK (_cairo_some_mutex);
* else
* %CAIRO_MUTEX_UNLOCK (_cairo_some_mutex);
*
* - If you define CAIRO_MUTEX_INIT(mutex), cairo will use it to
* initialize all static mutex'es. If for any reason that should
* not happen (eg. %CAIRO_MUTEX_INIT is just a faster way than
* what cairo does using %CAIRO_MUTEX_NIL_INITIALIZER), then
* #define CAIRO_MUTEX_INITIALIZE() CAIRO_MUTEX_NOOP
*
* - If your system supports freeing a mutex object (deallocating
* resources, etc), then #define CAIRO_MUTEX_FINI(mutex) to do
* that.
*
* - If you define CAIRO_MUTEX_FINI(mutex), cairo will use it to
* define a finalizer function to finalize all static mutex'es.
* However, it's up to you to call CAIRO_MUTEX_FINALIZE() at
* proper places, eg. when the system is unloading the cairo library.
* So, if for any reason finalizing static mutex'es is not needed
* (eg. you never call %CAIRO_MUTEX_FINALIZE), then
* #define CAIRO_MUTEX_FINALIZE() CAIRO_MUTEX_NOOP
*
* - That is all. If for any reason you think the above API is
* not enough to implement #cairo_mutex_t on your system, please
* stop and write to the cairo mailing list about it. DO NOT
* poke around cairo-mutex-private.h for possible solutions.
*/
#if CAIRO_NO_MUTEX
/* No mutexes */
typedef int cairo_mutex_t;
# define CAIRO_MUTEX_INITIALIZE() CAIRO_MUTEX_NOOP
# define CAIRO_MUTEX_LOCK(mutex) CAIRO_MUTEX_NOOP1(mutex)
# define CAIRO_MUTEX_UNLOCK(mutex) CAIRO_MUTEX_NOOP1(mutex)
# define CAIRO_MUTEX_NIL_INITIALIZER 0
#elif HAVE_PTHREAD_H /*******************************************************/
# include <pthread.h>
typedef pthread_mutex_t cairo_mutex_t;
# define CAIRO_MUTEX_LOCK(mutex) pthread_mutex_lock (&(mutex))
# define CAIRO_MUTEX_UNLOCK(mutex) pthread_mutex_unlock (&(mutex))
# define CAIRO_MUTEX_FINI(mutex) pthread_mutex_destroy (&(mutex))
# define CAIRO_MUTEX_FINALIZE() CAIRO_MUTEX_NOOP
# define CAIRO_MUTEX_NIL_INITIALIZER PTHREAD_MUTEX_INITIALIZER
#elif HAVE_WINDOWS_H /*******************************************************/
# include <windows.h>
typedef CRITICAL_SECTION cairo_mutex_t;
# define CAIRO_MUTEX_LOCK(mutex) EnterCriticalSection (&(mutex))
# define CAIRO_MUTEX_UNLOCK(mutex) LeaveCriticalSection (&(mutex))
# define CAIRO_MUTEX_INIT(mutex) InitializeCriticalSection (&(mutex))
# define CAIRO_MUTEX_FINI(mutex) DeleteCriticalSection (&(mutex))
# define CAIRO_MUTEX_NIL_INITIALIZER { NULL, 0, 0, NULL, NULL, 0 }
#elif defined __OS2__ /******************************************************/
# define INCL_BASE
# define INCL_PM
# include <os2.h>
typedef HMTX cairo_mutex_t;
# define CAIRO_MUTEX_LOCK(mutex) DosRequestMutexSem(mutex, SEM_INDEFINITE_WAIT)
# define CAIRO_MUTEX_UNLOCK(mutex) DosReleaseMutexSem(mutex)
# define CAIRO_MUTEX_INIT(mutex) DosCreateMutexSem (NULL, &(mutex), 0L, FALSE)
# define CAIRO_MUTEX_FINI(mutex) DosCloseMutexSem (mutex)
# define CAIRO_MUTEX_NIL_INITIALIZER 0
#elif CAIRO_HAS_BEOS_SURFACE /***********************************************/
typedef BLocker* cairo_mutex_t;
# define CAIRO_MUTEX_LOCK(mutex) (mutex)->Lock()
# define CAIRO_MUTEX_UNLOCK(mutex) (mutex)->Unlock()
# define CAIRO_MUTEX_INIT(mutex) (mutex) = new BLocker()
# define CAIRO_MUTEX_FINI(mutex) delete (mutex)
# define CAIRO_MUTEX_NIL_INITIALIZER NULL
#else /**********************************************************************/
# error "XXX: No mutex implementation found. Cairo will not work with multiple threads. Define CAIRO_NO_MUTEX to 1 to acknowledge and accept this limitation and compile cairo without thread-safety support."
#include "cairo-compiler-private.h"
#include "cairo-mutex-impl-private.h"
/* Only the following three are mandatory at this point */
#ifndef CAIRO_MUTEX_IMPL_LOCK
# error "CAIRO_MUTEX_IMPL_LOCK not defined. Check cairo-mutex-impl-private.h."
#endif
#ifndef CAIRO_MUTEX_IMPL_UNLOCK
# error "CAIRO_MUTEX_IMPL_UNLOCK not defined. Check cairo-mutex-impl-private.h."
#endif
#ifndef CAIRO_MUTEX_IMPL_NIL_INITIALIZER
# error "CAIRO_MUTEX_IMPL_NIL_INITIALIZER not defined. Check cairo-mutex-impl-private.h."
#endif
/* make sure implementations don't fool us: we decide these ourself */
#undef _CAIRO_MUTEX_IMPL_USE_STATIC_INITIALIZER
#undef _CAIRO_MUTEX_IMPL_USE_STATIC_FINALIZER
#ifdef CAIRO_MUTEX_IMPL_INIT
/* If %CAIRO_MUTEX_IMPL_INIT is defined, we may need to initialize all
* static mutex'es. */
# ifndef CAIRO_MUTEX_IMPL_INITIALIZE
# define CAIRO_MUTEX_IMPL_INITIALIZE() do { \
if (!_cairo_mutex_initialized) \
_cairo_mutex_initialize (); \
} while(0)
/* and make sure we implement the above */
# define _CAIRO_MUTEX_IMPL_USE_STATIC_INITIALIZER 1
# endif /* CAIRO_MUTEX_IMPL_INITIALIZE */
#else /* no CAIRO_MUTEX_IMPL_INIT */
/* Otherwise we probably don't need to initialize static mutex'es, */
# ifndef CAIRO_MUTEX_IMPL_INITIALIZE
# define CAIRO_MUTEX_IMPL_INITIALIZE() CAIRO_MUTEX_IMPL_NOOP
# endif /* CAIRO_MUTEX_IMPL_INITIALIZE */
/* and dynamic ones can be initialized using the static initializer. */
# define CAIRO_MUTEX_IMPL_INIT(mutex) do { \
cairo_mutex_t _tmp_mutex = CAIRO_MUTEX_IMPL_NIL_INITIALIZER; \
memcpy (&(mutex), &_tmp_mutex, sizeof (_tmp_mutex)); \
} while (0)
#endif /* CAIRO_MUTEX_IMPL_INIT */
#ifdef CAIRO_MUTEX_IMPL_FINI
/* If %CAIRO_MUTEX_IMPL_FINI is defined, we may need to finalize all
* static mutex'es. */
# ifndef CAIRO_MUTEX_IMPL_FINALIZE
# define CAIRO_MUTEX_IMPL_FINALIZE() do { \
if (_cairo_mutex_initialized) \
_cairo_mutex_finalize (); \
} while(0)
/* and make sure we implement the above */
# define _CAIRO_MUTEX_IMPL_USE_STATIC_FINALIZER 1
# endif /* CAIRO_MUTEX_IMPL_FINALIZE */
#else /* no CAIRO_MUTEX_IMPL_FINI */
/* Otherwise we probably don't need to finalize static mutex'es, */
# ifndef CAIRO_MUTEX_IMPL_FINALIZE
# define CAIRO_MUTEX_IMPL_FINALIZE() CAIRO_MUTEX_IMPL_NOOP
# endif /* CAIRO_MUTEX_IMPL_FINALIZE */
/* neither do the dynamic ones. */
# define CAIRO_MUTEX_IMPL_FINI(mutex) CAIRO_MUTEX_IMPL_NOOP1(mutex)
#endif /* CAIRO_MUTEX_IMPL_FINI */
#ifndef _CAIRO_MUTEX_IMPL_USE_STATIC_INITIALIZER
#define _CAIRO_MUTEX_IMPL_USE_STATIC_INITIALIZER 0
#endif
#ifndef _CAIRO_MUTEX_IMPL_USE_STATIC_FINALIZER
#define _CAIRO_MUTEX_IMPL_USE_STATIC_FINALIZER 0
#endif
/* Make sure everything we want is defined */
#ifndef CAIRO_MUTEX_IMPL_INITIALIZE
# error "CAIRO_MUTEX_IMPL_INITIALIZE not defined"
#endif
#ifndef CAIRO_MUTEX_IMPL_FINALIZE
# error "CAIRO_MUTEX_IMPL_FINALIZE not defined"
#endif
#ifndef CAIRO_MUTEX_IMPL_LOCK
# error "CAIRO_MUTEX_IMPL_LOCK not defined"
#endif
#ifndef CAIRO_MUTEX_IMPL_UNLOCK
# error "CAIRO_MUTEX_IMPL_UNLOCK not defined"
#endif
#ifndef CAIRO_MUTEX_IMPL_INIT
# error "CAIRO_MUTEX_IMPL_INIT not defined"
#endif
#ifndef CAIRO_MUTEX_IMPL_FINI
# error "CAIRO_MUTEX_IMPL_FINI not defined"
#endif
#ifndef CAIRO_MUTEX_IMPL_NIL_INITIALIZER
# error "CAIRO_MUTEX_IMPL_NIL_INITIALIZER not defined"
#endif
/* Public interface. */
/* By default it simply uses the implementation provided.
* But we can provide for debugging features by overriding them */
#ifndef CAIRO_MUTEX_DEBUG
typedef cairo_mutex_impl_t cairo_mutex_t;
#else
# define cairo_mutex_t cairo_mutex_impl_t
#endif
#define CAIRO_MUTEX_INITIALIZE CAIRO_MUTEX_IMPL_INITIALIZE
#define CAIRO_MUTEX_FINALIZE CAIRO_MUTEX_IMPL_FINALIZE
#define CAIRO_MUTEX_LOCK CAIRO_MUTEX_IMPL_LOCK
#define CAIRO_MUTEX_UNLOCK CAIRO_MUTEX_IMPL_UNLOCK
#define CAIRO_MUTEX_INIT CAIRO_MUTEX_IMPL_INIT
#define CAIRO_MUTEX_FINI CAIRO_MUTEX_IMPL_FINI
#define CAIRO_MUTEX_NIL_INITIALIZER CAIRO_MUTEX_IMPL_NIL_INITIALIZER
/* Debugging support */
#ifdef CAIRO_MUTEX_DEBUG
/* TODO add mutex debugging facilities here (eg deadlock detection) */
#endif /* CAIRO_MUTEX_DEBUG */
CAIRO_END_DECLS
#endif

Просмотреть файл

@ -33,27 +33,25 @@
#include "cairoint.h"
#include "cairo-mutex-private.h"
#define CAIRO_MUTEX_DECLARE(mutex) cairo_mutex_t mutex = CAIRO_MUTEX_NIL_INITIALIZER
#include "cairo-mutex-list-private.h"
#undef CAIRO_MUTEX_DECLARE
#if _CAIRO_MUTEX_IMPL_USE_STATIC_INITIALIZER || _CAIRO_MUTEX_IMPL_USE_STATIC_FINALIZER
#if _CAIRO_MUTEX_USE_STATIC_INITIALIZER || _CAIRO_MUTEX_USE_STATIC_FINALIZER
# if _CAIRO_MUTEX_IMPL_USE_STATIC_INITIALIZER
# define _CAIRO_MUTEX_IMPL_INITIALIZED_DEFAULT_VALUE FALSE
# if _CAIRO_MUTEX_USE_STATIC_INITIALIZER
# define _CAIRO_MUTEX_INITIALIZED_DEFAULT_VALUE FALSE
# else
# define _CAIRO_MUTEX_IMPL_INITIALIZED_DEFAULT_VALUE TRUE
# define _CAIRO_MUTEX_INITIALIZED_DEFAULT_VALUE TRUE
# endif
cairo_bool_t _cairo_mutex_initialized = _CAIRO_MUTEX_IMPL_INITIALIZED_DEFAULT_VALUE;
cairo_bool_t _cairo_mutex_initialized = _CAIRO_MUTEX_INITIALIZED_DEFAULT_VALUE;
# undef _CAIRO_MUTEX_IMPL_INITIALIZED_DEFAULT_VALUE
# undef _CAIRO_MUTEX_INITIALIZED_DEFAULT_VALUE
#endif
#if _CAIRO_MUTEX_IMPL_USE_STATIC_INITIALIZER
#if _CAIRO_MUTEX_USE_STATIC_INITIALIZER
void _cairo_mutex_initialize (void)
{
if (_cairo_mutex_initialized)
@ -67,7 +65,7 @@ void _cairo_mutex_initialize (void)
}
#endif
#if _CAIRO_MUTEX_IMPL_USE_STATIC_FINALIZER
#if _CAIRO_MUTEX_USE_STATIC_FINALIZER
void _cairo_mutex_finalize (void)
{
if (!_cairo_mutex_initialized)

Просмотреть файл

@ -49,7 +49,7 @@
# include <os2emx.h>
#endif
#include "cairo-os2.h"
#include <cairo-os2.h>
#include "cairoint.h"
typedef struct _cairo_os2_surface

Просмотреть файл

@ -56,8 +56,8 @@
/*
* Here comes the extra API for the OS/2 platform. Currently it consists
* of two extra functions, the cairo_os2_init() and the
* cairo_os2_fini(). Both of them are called automatically if
* of two extra functions, the cairo_os2_init () and the
* cairo_os2_fini (). Both of them are called automatically if
* Cairo is compiled to be a DLL file, but you have to call them before
* using the Cairo API if you link to Cairo statically!
*
@ -145,10 +145,8 @@ cairo_os2_fini (void)
CAIRO_MUTEX_FINALIZE ();
#if CAIRO_HAS_FT_FONT
# if HAVE_FCFINI
/* Uninitialize FontConfig */
FcFini ();
# endif
#endif
#ifdef __WATCOMC__

Просмотреть файл

@ -38,7 +38,7 @@
#ifndef _CAIRO_OS2_H_
#define _CAIRO_OS2_H_
#include "cairo.h"
#include <cairo.h>
CAIRO_BEGIN_DECLS

Просмотреть файл

@ -157,11 +157,11 @@ _cairo_memory_stream_copy (cairo_output_stream_t *base,
cairo_private int
_cairo_memory_stream_length (cairo_output_stream_t *stream);
/* cairo-base85-stream.c */
/* cairo_base85_stream.c */
cairo_private cairo_output_stream_t *
_cairo_base85_stream_create (cairo_output_stream_t *output);
/* cairo-deflate-stream.c */
/* cairo_deflate_stream.c */
cairo_private cairo_output_stream_t *
_cairo_deflate_stream_create (cairo_output_stream_t *output);

Просмотреть файл

@ -49,7 +49,7 @@
*/
#define SIGNIFICANT_DIGITS_AFTER_DECIMAL 6
/* Numbers printed with %g are assumed to only have %CAIRO_FIXED_FRAC_BITS
/* Numbers printed with %g are assumed to only have CAIRO_FIXED_FRAC_BITS
* bits of precision available after the decimal point.
*
* FIXED_POINT_DECIMAL_DIGITS specifies the minimum number of decimal
@ -58,12 +58,10 @@
*
* The conversion is:
*
* <programlisting>
* FIXED_POINT_DECIMAL_DIGITS = ceil( CAIRO_FIXED_FRAC_BITS * ln(2)/ln(10) )
* </programlisting>
*
* We can replace ceil(x) with (int)(x+1) since x will never be an
* integer for any likely value of %CAIRO_FIXED_FRAC_BITS.
* integer for any likely value of CAIRO_FIXED_FRAC_BITS.
*/
#define FIXED_POINT_DECIMAL_DIGITS ((int)(CAIRO_FIXED_FRAC_BITS*0.301029996 + 1))

Просмотреть файл

@ -67,14 +67,6 @@ struct _cairo_paginated_surface_backend {
cairo_warn cairo_int_status_t
(*set_bounding_box) (void *surface,
cairo_box_t *bbox);
/* Optional. Indicates whether the page requires fallback images.
* Will be called at the end of the ANALYZE phase but before the
* mode is changed to RENDER.
*/
cairo_warn cairo_int_status_t
(*set_fallback_images_required)(void *surface,
cairo_bool_t fallbacks_required);
};
/* A #cairo_paginated_surface_t provides a very convenient wrapper that
@ -88,7 +80,7 @@ struct _cairo_paginated_surface_backend {
* _cairo_paginated_surface_create which takes its own, much simpler,
* #cairo_paginated_surface_backend_t. You are free to return the result
* of _cairo_paginated_surface_create() from your public
* cairo_<foo>_surface_create(). The paginated backend will be careful
* cairo_<foo>_surface_create. The paginated backend will be careful
* to not let the user see that they really got a "wrapped"
* surface. See test-paginated-surface.c for a fairly minimal example
* of a paginated-using surface. That should be a reasonable example
@ -96,29 +88,29 @@ struct _cairo_paginated_surface_backend {
*
* What the paginated surface does is first save all drawing
* operations for a page into a meta-surface. Then when the user calls
* cairo_show_page(), the paginated surface performs the following
* cairo_show_page, the paginated surface performs the following
* sequence of operations (using the backend functions passed to
* cairo_paginated_surface_create()):
* cairo_paginated_surface_create):
*
* 1. Calls start_page() (if not %NULL). At this point, it is appropriate
* 1. Calls start_page (if non %NULL). At this point, it is appropriate
* for the target to emit any page-specific header information into
* its output.
*
* 2. Calls set_paginated_mode() with an argument of %CAIRO_PAGINATED_MODE_ANALYZE
* 2. Calls set_paginated_mode with an argument of CAIRO_PAGINATED_MODE_ANALYZE
*
* 3. Replays the meta-surface to the target surface, (with an
* analysis surface inserted between which watches the return value
* from each operation). This analysis stage is used to decide which
* operations will require fallbacks.
*
* 4. Calls set_bounding_box() to provide the target surface with the
* 4. Calls set_bounding_box to provide the target surface with the
* tight bounding box of the page.
*
* 5. Calls set_paginated_mode() with an argument of %CAIRO_PAGINATED_MODE_RENDER
* 5. Calls set_paginated_mode with an argument of CAIRO_PAGINATED_MODE_RENDER
*
* 6. Replays a subset of the meta-surface operations to the target surface
*
* 7. Calls set_paginated_mode() with an argument of %CAIRO_PAGINATED_MODE_FALLBACK
* 7. Calls set_paginated_mode with an argument of CAIRO_PAGINATED_MODE_FALLBACK
*
* 8. Replays the remaining operations to an image surface, sets an
* appropriate clip on the target, then paints the resulting image

Просмотреть файл

@ -89,7 +89,7 @@ _cairo_paginated_surface_create (cairo_surface_t *target,
* evidence of the paginated wrapper out to the user. */
surface->base.type = cairo_surface_get_type (target);
surface->target = cairo_surface_reference (target);
surface->target = target;
surface->content = content;
surface->width = width;
@ -316,15 +316,6 @@ _paint_page (cairo_paginated_surface_t *surface)
goto FAIL;
}
if (surface->backend->set_fallback_images_required) {
cairo_bool_t has_fallbacks = _cairo_analysis_surface_has_unsupported (analysis);
status = surface->backend->set_fallback_images_required (surface->target,
has_fallbacks);
if (status)
goto FAIL;
}
surface->backend->set_paginated_mode (surface->target, CAIRO_PAGINATED_MODE_RENDER);
/* Finer grained fallbacks are currently only supported for some
@ -604,26 +595,13 @@ _cairo_paginated_surface_fill (void *abstract_surface,
tolerance, antialias);
}
static cairo_bool_t
_cairo_paginated_surface_has_show_text_glyphs (void *abstract_surface)
{
cairo_paginated_surface_t *surface = abstract_surface;
return _cairo_surface_has_show_text_glyphs (surface->target);
}
static cairo_int_status_t
_cairo_paginated_surface_show_text_glyphs (void *abstract_surface,
cairo_operator_t op,
cairo_pattern_t *source,
const char *utf8,
int utf8_len,
cairo_glyph_t *glyphs,
int num_glyphs,
const cairo_text_cluster_t *clusters,
int num_clusters,
cairo_bool_t backward,
cairo_scaled_font_t *scaled_font)
_cairo_paginated_surface_show_glyphs (void *abstract_surface,
cairo_operator_t op,
cairo_pattern_t *source,
cairo_glyph_t *glyphs,
int num_glyphs,
cairo_scaled_font_t *scaled_font)
{
cairo_paginated_surface_t *surface = abstract_surface;
cairo_int_status_t status;
@ -635,8 +613,8 @@ _cairo_paginated_surface_show_text_glyphs (void *abstract_surface,
surface->page_is_blank = FALSE;
/* Since this is a "wrapping" surface, we're calling back into
* _cairo_surface_show_text_glyphs from within a call to the same.
* Since _cairo_surface_show_text_glyphs acquires a mutex, we release
* _cairo_surface_show_glyphs from within a call to the same.
* Since _cairo_surface_show_glyphs acquires a mutex, we release
* and re-acquire the mutex around this nested call.
*
* Yes, this is ugly, but we consider it pragmatic as compared to
@ -645,12 +623,9 @@ _cairo_paginated_surface_show_text_glyphs (void *abstract_surface,
* lead to bugs).
*/
CAIRO_MUTEX_UNLOCK (scaled_font->mutex);
status = _cairo_surface_show_text_glyphs (surface->meta, op, source,
utf8, utf8_len,
glyphs, num_glyphs,
clusters, num_clusters,
backward,
scaled_font);
status = _cairo_surface_show_glyphs (surface->meta, op, source,
glyphs, num_glyphs,
scaled_font);
CAIRO_MUTEX_LOCK (scaled_font->mutex);
return status;
@ -691,12 +666,6 @@ static const cairo_surface_backend_t cairo_paginated_surface_backend = {
_cairo_paginated_surface_mask,
_cairo_paginated_surface_stroke,
_cairo_paginated_surface_fill,
NULL, /* show_glyphs */
_cairo_paginated_surface_snapshot,
NULL, /* is_similar */
NULL, /* reset */
NULL, /* fill_stroke */
NULL, /* create_solid_pattern_surface */
_cairo_paginated_surface_has_show_text_glyphs,
_cairo_paginated_surface_show_text_glyphs
_cairo_paginated_surface_show_glyphs,
_cairo_paginated_surface_snapshot
};

Просмотреть файл

@ -476,7 +476,7 @@ static int const num_args[] =
};
cairo_status_t
_cairo_path_fixed_interpret (const cairo_path_fixed_t *path,
_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,
@ -485,7 +485,7 @@ _cairo_path_fixed_interpret (const cairo_path_fixed_t *path,
void *closure)
{
cairo_status_t status;
const cairo_path_buf_t *buf;
cairo_path_buf_t *buf;
cairo_path_op_t op;
cairo_bool_t forward = (dir == CAIRO_DIRECTION_FORWARD);
int step = forward ? 1 : -1;
@ -541,52 +541,6 @@ _cairo_path_fixed_interpret (const cairo_path_fixed_t *path,
return CAIRO_STATUS_SUCCESS;
}
static cairo_status_t
_append_move_to (void *closure,
cairo_point_t *point)
{
cairo_path_fixed_t *path = (cairo_path_fixed_t *) closure;
return _cairo_path_fixed_move_to (path, point->x, point->y);
}
static cairo_status_t
_append_line_to (void *closure,
cairo_point_t *point)
{
cairo_path_fixed_t *path = (cairo_path_fixed_t *) closure;
return _cairo_path_fixed_line_to (path, point->x, point->y);
}
static cairo_status_t
_append_curve_to (void *closure,
cairo_point_t *p0,
cairo_point_t *p1,
cairo_point_t *p2)
{
cairo_path_fixed_t *path = (cairo_path_fixed_t *) closure;
return _cairo_path_fixed_curve_to (path, p0->x, p0->y, p1->x, p1->y, p2->x, p2->y);
}
static cairo_status_t
_append_close_path (void *closure)
{
cairo_path_fixed_t *path = (cairo_path_fixed_t *) closure;
return _cairo_path_fixed_close_path (path);
}
cairo_private cairo_status_t
_cairo_path_fixed_append (cairo_path_fixed_t *path,
const cairo_path_fixed_t *other,
cairo_direction_t dir)
{
return _cairo_path_fixed_interpret (other, dir,
_append_move_to,
_append_line_to,
_append_curve_to,
_append_close_path,
path);
}
static void
_cairo_path_fixed_offset_and_scale (cairo_path_fixed_t *path,
cairo_fixed_t offx,
@ -612,47 +566,29 @@ _cairo_path_fixed_offset_and_scale (cairo_path_fixed_t *path,
}
}
/**
* _cairo_path_fixed_transform:
* _cairo_path_fixed_device_transform:
* @path: a #cairo_path_fixed_t to be transformed
* @matrix: a #cairo_matrix_t
* @device_transform: a matrix with only scaling/translation (no rotation or shear)
*
* Transform the fixed-point path according to the given matrix.
* There is a fast path for the case where @matrix has 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_transform (cairo_path_fixed_t *path,
cairo_matrix_t *matrix)
_cairo_path_fixed_device_transform (cairo_path_fixed_t *path,
cairo_matrix_t *device_transform)
{
cairo_path_buf_t *buf;
int i;
double dx, dy;
if (matrix->yx == 0.0 && matrix->xy == 0.0) {
/* Fast path for the common case of scale+transform */
_cairo_path_fixed_offset_and_scale (path,
_cairo_fixed_from_double (matrix->x0),
_cairo_fixed_from_double (matrix->y0),
_cairo_fixed_from_double (matrix->xx),
_cairo_fixed_from_double (matrix->yy));
return;
}
buf = &path->buf_head.base;
while (buf) {
for (i = 0; i < buf->num_points; i++) {
dx = _cairo_fixed_to_double (buf->points[i].x);
dy = _cairo_fixed_to_double (buf->points[i].y);
cairo_matrix_transform_point (matrix, &dx, &dy);
buf->points[i].x = _cairo_fixed_from_double (dx);
buf->points[i].y = _cairo_fixed_from_double (dy);
}
buf = buf->next;
}
assert (device_transform->yx == 0.0 && device_transform->xy == 0.0);
/* XXX: Support freeform matrices someday (right now, only translation and scale
* work. */
_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));
}
cairo_bool_t
@ -765,7 +701,7 @@ _cpf_close_path (void *closure)
cairo_status_t
_cairo_path_fixed_interpret_flat (const cairo_path_fixed_t *path,
_cairo_path_fixed_interpret_flat (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,
@ -869,16 +805,14 @@ _cairo_path_fixed_is_box (cairo_path_fixed_t *path,
return FALSE;
}
/*
/**
* Check whether the given path contains a single rectangle
* that is logically equivalent to:
* <informalexample><programlisting>
* cairo_move_to (cr, x, y);
* cairo_rel_line_to (cr, width, 0);
* cairo_rel_line_to (cr, 0, height);
* cairo_rel_line_to (cr, -width, 0);
* cairo_close_path (cr);
* </programlisting></informalexample>
*/
cairo_bool_t
_cairo_path_fixed_is_rectangle (cairo_path_fixed_t *path,

Просмотреть файл

@ -1191,10 +1191,9 @@ typedef struct _cairo_rectilinear_stroker
cairo_point_t current_point;
cairo_point_t first_point;
cairo_bool_t open_sub_path;
int num_segments;
int segments_size;
cairo_line_t *segments;
cairo_line_t segments_embedded[8]; /* common case is a single rectangle */
int segments_size;
int num_segments;
} cairo_rectilinear_stroker_t;
static void
@ -1207,16 +1206,15 @@ _cairo_rectilinear_stroker_init (cairo_rectilinear_stroker_t *stroker,
_cairo_fixed_from_double (stroke_style->line_width / 2.0);
stroker->traps = traps;
stroker->open_sub_path = FALSE;
stroker->segments = stroker->segments_embedded;
stroker->segments_size = ARRAY_LENGTH (stroker->segments_embedded);
stroker->segments = NULL;
stroker->segments_size = 0;
stroker->num_segments = 0;
}
static void
_cairo_rectilinear_stroker_fini (cairo_rectilinear_stroker_t *stroker)
{
if (stroker->segments != stroker->segments_embedded)
free (stroker->segments);
free (stroker->segments);
}
static cairo_status_t
@ -1224,24 +1222,18 @@ _cairo_rectilinear_stroker_add_segment (cairo_rectilinear_stroker_t *stroker,
cairo_point_t *p1,
cairo_point_t *p2)
{
int new_size;
cairo_line_t *new_segments;
if (stroker->num_segments == stroker->segments_size) {
int new_size = stroker->segments_size * 2;
cairo_line_t *new_segments;
if (stroker->segments == stroker->segments_embedded) {
new_segments = _cairo_malloc_ab (new_size, sizeof (cairo_line_t));
if (new_segments == NULL)
return _cairo_error (CAIRO_STATUS_NO_MEMORY);
memcpy (new_segments, stroker->segments,
stroker->num_segments * sizeof (cairo_line_t));
} else {
new_segments = _cairo_realloc_ab (stroker->segments,
new_size, sizeof (cairo_line_t));
if (new_segments == NULL)
return _cairo_error (CAIRO_STATUS_NO_MEMORY);
}
new_size = stroker->segments_size * 2;
/* Common case is one rectangle of exactly 4 segments. */
if (new_size == 0)
new_size = 4;
new_segments = _cairo_realloc_ab (stroker->segments,
new_size, sizeof (cairo_line_t));
if (new_segments == NULL)
return _cairo_error (CAIRO_STATUS_NO_MEMORY);
stroker->segments_size = new_size;
stroker->segments = new_segments;
@ -1398,7 +1390,8 @@ _cairo_rectilinear_stroker_line_to (void *closure,
if (a->x == b->x && a->y == b->y)
return CAIRO_STATUS_SUCCESS;
status = _cairo_rectilinear_stroker_add_segment (stroker, a, b);
status = _cairo_rectilinear_stroker_add_segment (stroker,
a, b);
stroker->current_point = *point;
stroker->open_sub_path = TRUE;

Просмотреть файл

@ -50,7 +50,7 @@ static const cairo_solid_pattern_t _cairo_pattern_nil_null_pointer = {
CAIRO_EXTEND_GRADIENT_DEFAULT }, /* extend */
};
const cairo_solid_pattern_t _cairo_pattern_none = {
const cairo_solid_pattern_t cairo_pattern_none = {
{ CAIRO_PATTERN_TYPE_SOLID, /* type */
CAIRO_REFERENCE_COUNT_INVALID, /* ref_count */
CAIRO_STATUS_SUCCESS, /* status */
@ -63,10 +63,10 @@ const cairo_solid_pattern_t _cairo_pattern_none = {
/**
* _cairo_pattern_set_error:
* @pattern: a pattern
* @status: a status value indicating an error
* @status: a status value indicating an error, (eg. not
* CAIRO_STATUS_SUCCESS)
*
* Atomically sets pattern->status to @status and calls _cairo_error;
* Does nothing if status is %CAIRO_STATUS_SUCCESS.
*
* All assignments of an error status to pattern->status should happen
* through _cairo_pattern_set_error(). Note that due to the nature of
@ -81,9 +81,6 @@ static cairo_status_t
_cairo_pattern_set_error (cairo_pattern_t *pattern,
cairo_status_t status)
{
if (status == CAIRO_STATUS_SUCCESS)
return status;
/* Don't overwrite an existing error. This preserves the first
* error, which is the most significant. */
_cairo_status_set_error (&pattern->status, status);
@ -255,9 +252,6 @@ _cairo_pattern_init_solid (cairo_solid_pattern_t *pattern,
const cairo_color_t *color,
cairo_content_t content)
{
if (content == CAIRO_CONTENT_COLOR_ALPHA && CAIRO_COLOR_IS_OPAQUE (color))
content = CAIRO_CONTENT_COLOR;
_cairo_pattern_init (&pattern->base, CAIRO_PATTERN_TYPE_SOLID);
pattern->color = *color;
pattern->content = content;
@ -364,8 +358,7 @@ _cairo_pattern_reset_solid_pattern_cache (void)
CAIRO_MUTEX_LOCK (_cairo_pattern_solid_pattern_cache_lock);
for (i = 0; i < MIN (ARRAY_LENGTH (solid_pattern_cache.patterns), solid_pattern_cache.size); i++) {
if (solid_pattern_cache.patterns[i])
free (solid_pattern_cache.patterns[i]);
free (solid_pattern_cache.patterns[i]);
solid_pattern_cache.patterns[i] = NULL;
}
solid_pattern_cache.size = 0;
@ -383,7 +376,8 @@ _cairo_pattern_create_in_error (cairo_status_t status)
CAIRO_MUTEX_INITIALIZE ();
pattern = _cairo_pattern_create_solid (CAIRO_COLOR_BLACK, CAIRO_CONTENT_COLOR);
pattern = _cairo_pattern_create_solid (_cairo_stock_color (CAIRO_STOCK_BLACK),
CAIRO_CONTENT_COLOR);
if (pattern->status == CAIRO_STATUS_SUCCESS)
status = _cairo_pattern_set_error (pattern, status);
@ -1370,7 +1364,6 @@ _cairo_pattern_acquire_surface_for_gradient (cairo_gradient_pattern_t *pattern,
#define MAX_SURFACE_CACHE_SIZE 16
static struct {
struct _cairo_pattern_solid_surface_cache{
cairo_content_t content;
cairo_color_t color;
cairo_surface_t *surface;
} cache[MAX_SURFACE_CACHE_SIZE];
@ -1383,10 +1376,10 @@ _cairo_pattern_solid_surface_matches (
const cairo_solid_pattern_t *pattern,
cairo_surface_t *dst)
{
if (cache->content != pattern->content)
if (CAIRO_REFERENCE_COUNT_GET_VALUE (&cache->surface->ref_count) != 1)
return FALSE;
if (CAIRO_REFERENCE_COUNT_GET_VALUE (&cache->surface->ref_count) != 1)
if (! _cairo_color_equal (&cache->color, &pattern->color))
return FALSE;
if (! _cairo_surface_is_similar (cache->surface, dst, pattern->content))
@ -1395,18 +1388,6 @@ _cairo_pattern_solid_surface_matches (
return TRUE;
}
static cairo_bool_t
_cairo_pattern_solid_surface_matches_color (
const struct _cairo_pattern_solid_surface_cache *cache,
const cairo_solid_pattern_t *pattern,
cairo_surface_t *dst)
{
if (! _cairo_color_equal (&cache->color, &pattern->color))
return FALSE;
return _cairo_pattern_solid_surface_matches (cache, pattern, dst);
}
static cairo_int_status_t
_cairo_pattern_acquire_surface_for_solid (cairo_solid_pattern_t *pattern,
cairo_surface_t *dst,
@ -1419,89 +1400,61 @@ _cairo_pattern_acquire_surface_for_solid (cairo_solid_pattern_t *pattern,
{
static int i;
cairo_surface_t *surface, *to_destroy = NULL;
cairo_surface_t *surface;
cairo_status_t status;
CAIRO_MUTEX_LOCK (_cairo_pattern_solid_surface_cache_lock);
/* Check cache first */
if (i < solid_surface_cache.size &&
_cairo_pattern_solid_surface_matches_color (&solid_surface_cache.cache[i],
pattern,
dst))
_cairo_pattern_solid_surface_matches (&solid_surface_cache.cache[i],
pattern,
dst))
{
status = _cairo_surface_reset (solid_surface_cache.cache[i].surface);
if (status)
goto UNLOCK;
goto DONE;
if (! _cairo_surface_reset (solid_surface_cache.cache[i].surface))
goto DONE;
}
for (i = 0 ; i < solid_surface_cache.size; i++) {
if (_cairo_pattern_solid_surface_matches_color (&solid_surface_cache.cache[i],
pattern,
dst))
{
status = _cairo_surface_reset (solid_surface_cache.cache[i].surface);
if (status)
goto UNLOCK;
goto DONE;
}
}
/* Choose a surface to repaint/evict */
surface = NULL;
if (solid_surface_cache.size == MAX_SURFACE_CACHE_SIZE) {
i = rand () % MAX_SURFACE_CACHE_SIZE;
surface = solid_surface_cache.cache[i].surface;
if (_cairo_pattern_solid_surface_matches (&solid_surface_cache.cache[i],
pattern,
pattern,
dst))
{
/* Reuse the surface instead of evicting */
status = _cairo_surface_reset (surface);
if (status)
goto EVICT;
status = _cairo_surface_repaint_solid_pattern_surface (dst, surface, pattern);
if (status)
goto EVICT;
cairo_surface_reference (surface);
}
else
{
EVICT:
surface = NULL;
if (! _cairo_surface_reset (solid_surface_cache.cache[i].surface))
goto DONE;
}
}
if (surface == NULL) {
/* Not cached, need to create new */
surface = _cairo_surface_create_solid_pattern_surface (dst, pattern);
if (surface->status) {
status = surface->status;
goto UNLOCK;
}
if (! _cairo_surface_is_similar (surface, dst, pattern->content)) {
/* in the rare event of a substitute surface being returned (e.g.
* malloc failure) don't cache the fallback surface */
*out = surface;
goto NOCACHE;
}
/* Not cached, need to create new */
surface = _cairo_surface_create_similar_solid (dst,
pattern->content,
1, 1,
&pattern->color,
&pattern->base);
if (surface->status) {
status = surface->status;
goto UNLOCK;
}
if (i == solid_surface_cache.size)
if (! _cairo_surface_is_similar (surface, dst, pattern->content)) {
/* in the rare event of a substitute surface being returned (e.g.
* malloc failure) don't cache the fallback surface */
*out = surface;
goto NOCACHE;
}
/* Cache new */
if (solid_surface_cache.size < MAX_SURFACE_CACHE_SIZE) {
solid_surface_cache.size++;
} else {
i = rand () % MAX_SURFACE_CACHE_SIZE;
/* Evict old */
cairo_surface_destroy (solid_surface_cache.cache[i].surface);
}
to_destroy = solid_surface_cache.cache[i].surface;
solid_surface_cache.cache[i].surface = surface;
solid_surface_cache.cache[i].color = pattern->color;
solid_surface_cache.cache[i].content = pattern->content;
solid_surface_cache.cache[i].surface = surface;
DONE:
*out = cairo_surface_reference (solid_surface_cache.cache[i].surface);
@ -1518,32 +1471,19 @@ NOCACHE:
UNLOCK:
CAIRO_MUTEX_UNLOCK (_cairo_pattern_solid_surface_cache_lock);
if (to_destroy)
cairo_surface_destroy (to_destroy);
return status;
}
static void
_cairo_pattern_reset_solid_surface_cache (void)
{
int i;
CAIRO_MUTEX_LOCK (_cairo_pattern_solid_surface_cache_lock);
/* remove surfaces starting from the end so that solid_surface_cache.cache
* is always in a consistent state when we release the mutex. */
while (solid_surface_cache.size) {
cairo_surface_t *surface;
solid_surface_cache.size--;
surface = solid_surface_cache.cache[solid_surface_cache.size].surface;
solid_surface_cache.cache[solid_surface_cache.size].surface = NULL;
/* release the lock to avoid the possibility of a recursive
* deadlock when the scaled font destroy closure gets called */
CAIRO_MUTEX_UNLOCK (_cairo_pattern_solid_surface_cache_lock);
cairo_surface_destroy (surface);
CAIRO_MUTEX_LOCK (_cairo_pattern_solid_surface_cache_lock);
}
for (i = 0; i < solid_surface_cache.size; i++)
cairo_surface_destroy (solid_surface_cache.cache[i].surface);
solid_surface_cache.size = 0;
CAIRO_MUTEX_UNLOCK (_cairo_pattern_solid_surface_cache_lock);
}
@ -1853,11 +1793,18 @@ _cairo_pattern_acquire_surface (cairo_pattern_t *pattern,
src->stops->color.blue,
src->stops->color.alpha);
_cairo_pattern_init_solid (&solid, &color, CAIRO_CONTENT_COLOR_ALPHA);
_cairo_pattern_init_solid (&solid, &color,
CAIRO_COLOR_IS_OPAQUE (&color) ?
CAIRO_CONTENT_COLOR :
CAIRO_CONTENT_COLOR_ALPHA);
}
else
{
_cairo_pattern_init_solid (&solid, CAIRO_COLOR_TRANSPARENT, CAIRO_CONTENT_ALPHA);
const cairo_color_t *color;
color = _cairo_stock_color (CAIRO_STOCK_TRANSPARENT);
_cairo_pattern_init_solid (&solid, color,
CAIRO_CONTENT_ALPHA);
}
status = _cairo_pattern_acquire_surface_for_solid (&solid, dst,
@ -1960,7 +1907,10 @@ _cairo_pattern_acquire_surfaces (cairo_pattern_t *src,
combined = src_solid->color;
_cairo_color_multiply_alpha (&combined, mask_solid->color.alpha);
_cairo_pattern_init_solid (&src_tmp.solid, &combined, CAIRO_CONTENT_COLOR_ALPHA);
_cairo_pattern_init_solid (&src_tmp.solid, &combined,
CAIRO_COLOR_IS_OPAQUE (&combined) ?
CAIRO_CONTENT_COLOR :
CAIRO_CONTENT_COLOR_ALPHA);
mask = NULL;
}
@ -2078,10 +2028,15 @@ _cairo_pattern_get_extents (cairo_pattern_t *pattern,
* horizontal/vertical linear gradients).
*/
extents->x = CAIRO_RECT_INT_MIN;
extents->y = CAIRO_RECT_INT_MIN;
extents->width = CAIRO_RECT_INT_MIN + CAIRO_RECT_INT_MAX;
extents->height = CAIRO_RECT_INT_MIN + CAIRO_RECT_INT_MAX;
/* XXX: because extents are represented as x, y, w, h we can't
* actually have a rectangle that covers our entire valid
* coordinate space, since we'd need width/height to be 2*INT_MAX.
*/
extents->x = 0;
extents->y = 0;
extents->width = CAIRO_RECT_INT_MAX;
extents->height = CAIRO_RECT_INT_MAX;
return CAIRO_STATUS_SUCCESS;
}

Просмотреть файл

@ -45,51 +45,16 @@
#include "cairo-compiler-private.h"
#include "cairo-types-private.h"
/* The glyph buffer size is based on the expected maximum glyphs in a
* line so that an entire line can be emitted in as one string. If the
* glyphs in a line exceeds this size the only downside is the slight
* overhead of emitting two strings.
*/
#define PDF_GLYPH_BUFFER_SIZE 200
typedef cairo_status_t (*cairo_pdf_operators_use_font_subset_t) (unsigned int font_id,
unsigned int subset_id,
void *closure);
typedef struct _cairo_pdf_glyph {
unsigned int glyph_index;
double x_position;
double x_advance;
} cairo_pdf_glyph_t;
typedef struct _cairo_pdf_operators {
cairo_output_stream_t *stream;
cairo_matrix_t cairo_to_pdf;
cairo_scaled_font_subsets_t *font_subsets;
cairo_pdf_operators_use_font_subset_t use_font_subset;
void *use_font_subset_closure;
cairo_bool_t in_text_object; /* inside BT/ET pair */
/* PDF text state */
cairo_bool_t is_new_text_object; /* text object started but matrix and font not yet selected */
unsigned int font_id;
unsigned int subset_id;
cairo_matrix_t text_matrix; /* PDF text matrix (Tlm in the PDF reference) */
cairo_matrix_t cairo_to_pdftext; /* translate cairo coords to PDF text space */
cairo_matrix_t font_matrix_inverse;
double cur_x; /* Current position in PDF text space (Tm in the PDF reference) */
double cur_y;
int hex_width;
int num_glyphs;
cairo_pdf_glyph_t glyphs[PDF_GLYPH_BUFFER_SIZE];
/* PDF line style */
cairo_bool_t has_line_style;
double line_width;
cairo_line_cap_t line_cap;
cairo_line_join_t line_join;
double miter_limit;
cairo_bool_t has_dashes;
} cairo_pdf_operators_t;
cairo_private void
@ -98,7 +63,7 @@ _cairo_pdf_operators_init (cairo_pdf_operators_t *pdf_operators,
cairo_matrix_t *cairo_to_pdf,
cairo_scaled_font_subsets_t *font_subsets);
cairo_private cairo_status_t
cairo_private void
_cairo_pdf_operators_fini (cairo_pdf_operators_t *pdf_operators);
cairo_private void
@ -115,22 +80,11 @@ cairo_private void
_cairo_pdf_operators_set_cairo_to_pdf_matrix (cairo_pdf_operators_t *pdf_operators,
cairo_matrix_t *cairo_to_pdf);
cairo_private cairo_status_t
_cairo_pdf_operators_flush (cairo_pdf_operators_t *pdf_operators);
cairo_private void
_cairo_pdf_operators_reset (cairo_pdf_operators_t *pdf_operators);
cairo_private cairo_int_status_t
_cairo_pdf_operators_clip (cairo_pdf_operators_t *pdf_operators,
cairo_path_fixed_t *path,
cairo_fill_rule_t fill_rule);
cairo_private cairo_int_status_t
_cairo_pdf_operators_emit_stroke_style (cairo_pdf_operators_t *pdf_operators,
cairo_stroke_style_t *style,
double scale);
cairo_private cairo_int_status_t
_cairo_pdf_operators_stroke (cairo_pdf_operators_t *pdf_operators,
cairo_path_fixed_t *path,
@ -152,15 +106,9 @@ _cairo_pdf_operators_fill_stroke (cairo_pdf_operators_t *pdf_operators,
cairo_matrix_t *ctm_inverse);
cairo_private cairo_int_status_t
_cairo_pdf_operators_show_text_glyphs (cairo_pdf_operators_t *pdf_operators,
const char *utf8,
int utf8_len,
cairo_glyph_t *glyphs,
int num_glyphs,
const cairo_text_cluster_t *clusters,
int num_clusters,
cairo_bool_t backward,
cairo_scaled_font_t *scaled_font);
_cairo_pdf_operators_show_glyphs (cairo_pdf_operators_t *pdf_operators,
cairo_glyph_t *glyphs,
int num_glyphs,
cairo_scaled_font_t *scaled_font);
#endif /* CAIRO_PDF_OPERATORS_H */

Просмотреть файл

@ -47,10 +47,6 @@
#include <ctype.h>
static cairo_status_t
_cairo_pdf_operators_end_text (cairo_pdf_operators_t *pdf_operators);
void
_cairo_pdf_operators_init (cairo_pdf_operators_t *pdf_operators,
cairo_output_stream_t *stream,
@ -62,15 +58,11 @@ _cairo_pdf_operators_init (cairo_pdf_operators_t *pdf_operators,
pdf_operators->font_subsets = font_subsets;
pdf_operators->use_font_subset = NULL;
pdf_operators->use_font_subset_closure = NULL;
pdf_operators->in_text_object = FALSE;
pdf_operators->num_glyphs = 0;
pdf_operators->has_line_style = FALSE;
}
cairo_status_t
void
_cairo_pdf_operators_fini (cairo_pdf_operators_t *pdf_operators)
{
return _cairo_pdf_operators_flush (pdf_operators);
}
void
@ -82,16 +74,11 @@ _cairo_pdf_operators_set_font_subsets_callback (cairo_pdf_operators_t *pdf
pdf_operators->use_font_subset_closure = closure;
}
/* Change the output stream to a different stream.
* _cairo_pdf_operators_flush() should always be called before calling
* this function.
*/
void
_cairo_pdf_operators_set_stream (cairo_pdf_operators_t *pdf_operators,
cairo_output_stream_t *stream)
{
pdf_operators->stream = stream;
pdf_operators->has_line_style = FALSE;
}
void
@ -99,45 +86,6 @@ _cairo_pdf_operators_set_cairo_to_pdf_matrix (cairo_pdf_operators_t *pdf_operato
cairo_matrix_t *cairo_to_pdf)
{
pdf_operators->cairo_to_pdf = *cairo_to_pdf;
pdf_operators->has_line_style = FALSE;
}
/* Finish writing out any pending commands to the stream. This
* function must be called by the surface before emitting anything
* into the PDF stream.
*
* pdf_operators may leave the emitted PDF for some operations
* unfinished in case subsequent operations can be merged. This
* function will finish off any incomplete operation so the stream
* will be in a state where the surface may emit it's own PDF
* operations (eg changing patterns).
*
*/
cairo_status_t
_cairo_pdf_operators_flush (cairo_pdf_operators_t *pdf_operators)
{
cairo_status_t status = CAIRO_STATUS_SUCCESS;
if (pdf_operators->in_text_object)
status = _cairo_pdf_operators_end_text (pdf_operators);
return status;
}
/* Reset the known graphics state of the PDF consumer. ie no
* assumptions will be made about the state. The next time a
* particular graphics state is required (eg line width) the state
* operator is always emitted and then remembered for subsequent
* operatations.
*
* This should be called when starting a new stream or after emitting
* the 'Q' operator (where pdf-operators functions were called inside
* the q/Q pair).
*/
void
_cairo_pdf_operators_reset (cairo_pdf_operators_t *pdf_operators)
{
pdf_operators->has_line_style = FALSE;
}
/* A word wrap stream can be used as a filter to do word wrapping on
@ -530,7 +478,7 @@ _cairo_pdf_line_join (cairo_line_join_t join)
}
}
cairo_int_status_t
static cairo_int_status_t
_cairo_pdf_operators_emit_stroke_style (cairo_pdf_operators_t *pdf_operators,
cairo_stroke_style_t *style,
double scale)
@ -538,7 +486,6 @@ _cairo_pdf_operators_emit_stroke_style (cairo_pdf_operators_t *pdf_operators,
double *dash = style->dash;
int num_dashes = style->num_dashes;
double dash_offset = style->dash_offset;
double line_width = style->line_width * scale;
/* PostScript has "special needs" when it comes to zero-length
* dash segments with butt caps. It apparently (at least
@ -603,26 +550,17 @@ _cairo_pdf_operators_emit_stroke_style (cairo_pdf_operators_t *pdf_operators,
}
}
if (!pdf_operators->has_line_style || pdf_operators->line_width != line_width) {
_cairo_output_stream_printf (pdf_operators->stream,
"%f w\n",
line_width);
pdf_operators->line_width = line_width;
}
_cairo_output_stream_printf (pdf_operators->stream,
"%f w\n",
style->line_width * scale);
if (!pdf_operators->has_line_style || pdf_operators->line_cap != style->line_cap) {
_cairo_output_stream_printf (pdf_operators->stream,
"%d J\n",
_cairo_pdf_line_cap (style->line_cap));
pdf_operators->line_cap = style->line_cap;
}
_cairo_output_stream_printf (pdf_operators->stream,
"%d J\n",
_cairo_pdf_line_cap (style->line_cap));
if (!pdf_operators->has_line_style || pdf_operators->line_join != style->line_join) {
_cairo_output_stream_printf (pdf_operators->stream,
"%d j\n",
_cairo_pdf_line_join (style->line_join));
pdf_operators->line_join = style->line_join;
}
_cairo_output_stream_printf (pdf_operators->stream,
"%d j\n",
_cairo_pdf_line_join (style->line_join));
if (num_dashes) {
int d;
@ -632,21 +570,15 @@ _cairo_pdf_operators_emit_stroke_style (cairo_pdf_operators_t *pdf_operators,
_cairo_output_stream_printf (pdf_operators->stream, " %f", dash[d] * scale);
_cairo_output_stream_printf (pdf_operators->stream, "] %f d\n",
dash_offset * scale);
pdf_operators->has_dashes = TRUE;
} else if (!pdf_operators->has_line_style || pdf_operators->has_dashes) {
} else {
_cairo_output_stream_printf (pdf_operators->stream, "[] 0.0 d\n");
pdf_operators->has_dashes = FALSE;
}
if (dash != style->dash)
free (dash);
if (!pdf_operators->has_line_style || pdf_operators->miter_limit != style->miter_limit) {
_cairo_output_stream_printf (pdf_operators->stream,
"%f M ",
style->miter_limit < 1.0 ? 1.0 : style->miter_limit);
pdf_operators->miter_limit = style->miter_limit;
}
pdf_operators->has_line_style = TRUE;
_cairo_output_stream_printf (pdf_operators->stream,
"%f M ",
style->miter_limit < 1.0 ? 1.0 : style->miter_limit);
return _cairo_output_stream_get_status (pdf_operators->stream);
}
@ -690,9 +622,6 @@ _cairo_pdf_operators_emit_stroke (cairo_pdf_operators_t *pdf_operators,
cairo_bool_t has_ctm = TRUE;
double scale = 1.0;
if (pdf_operators->in_text_object)
status = _cairo_pdf_operators_end_text (pdf_operators);
/* Optimize away the stroke ctm when it does not affect the
* stroke. There are other ctm cases that could be optimized
* however this is the most common.
@ -788,9 +717,6 @@ _cairo_pdf_operators_fill (cairo_pdf_operators_t *pdf_operators,
const char *pdf_operator;
cairo_status_t status;
if (pdf_operators->in_text_object)
status = _cairo_pdf_operators_end_text (pdf_operators);
status = _cairo_pdf_operators_emit_path (pdf_operators,
path,
&pdf_operators->cairo_to_pdf,
@ -847,567 +773,205 @@ _cairo_pdf_operators_fill_stroke (cairo_pdf_operators_t *pdf_operators,
#define GLYPH_POSITION_TOLERANCE 0.001
/* Emit the string of glyphs using the 'Tj' operator. This requires
* that the glyphs are positioned at their natural glyph advances. */
static cairo_status_t
_cairo_pdf_operators_emit_glyph_string (cairo_pdf_operators_t *pdf_operators,
cairo_output_stream_t *stream)
{
int i;
_cairo_output_stream_printf (stream, "<");
for (i = 0; i < pdf_operators->num_glyphs; i++) {
_cairo_output_stream_printf (stream,
"%0*x",
pdf_operators->hex_width,
pdf_operators->glyphs[i].glyph_index);
pdf_operators->cur_x += pdf_operators->glyphs[i].x_advance;
}
_cairo_output_stream_printf (stream, ">Tj\n");
return _cairo_output_stream_get_status (stream);
}
/* Emit the string of glyphs using the 'TJ' operator.
*
* The TJ operator takes an array of strings of glyphs. Each string of
* glyphs is displayed using the glyph advances of each glyph to
* position the glyphs. A relative adjustment to the glyph advance may
* be specified by including the adjustment between two strings. The
* adjustment is in units of text space * -1000.
*/
static cairo_status_t
_cairo_pdf_operators_emit_glyph_string_with_positioning (
cairo_pdf_operators_t *pdf_operators,
cairo_output_stream_t *stream)
{
int i;
_cairo_output_stream_printf (stream, "[<");
for (i = 0; i < pdf_operators->num_glyphs; i++) {
if (pdf_operators->glyphs[i].x_position != pdf_operators->cur_x)
{
double delta = pdf_operators->glyphs[i].x_position - pdf_operators->cur_x;
int rounded_delta;
delta = -1000.0*delta;
/* As the delta is in 1/1000 of a unit of text space,
* rounding to an integer should still provide sufficient
* precision. We round the delta before adding to Tm_x so
* that we keep track of the accumulated rounding error in
* the PDF interpreter and compensate for it when
* calculating subsequent deltas.
*/
rounded_delta = _cairo_lround (delta);
if (rounded_delta != 0) {
_cairo_output_stream_printf (stream,
">%d<",
rounded_delta);
}
/* Convert the rounded delta back to text
* space before adding to the current text
* position. */
delta = rounded_delta/-1000.0;
pdf_operators->cur_x += delta;
}
_cairo_output_stream_printf (stream,
"%0*x",
pdf_operators->hex_width,
pdf_operators->glyphs[i].glyph_index);
pdf_operators->cur_x += pdf_operators->glyphs[i].x_advance;
}
_cairo_output_stream_printf (stream, ">]TJ\n");
return _cairo_output_stream_get_status (stream);
}
static cairo_status_t
_cairo_pdf_operators_flush_glyphs (cairo_pdf_operators_t *pdf_operators)
cairo_int_status_t
_cairo_pdf_operators_show_glyphs (cairo_pdf_operators_t *pdf_operators,
cairo_glyph_t *glyphs,
int num_glyphs,
cairo_scaled_font_t *scaled_font)
{
unsigned int current_subset_id = (unsigned int)-1;
cairo_scaled_font_subsets_glyph_t subset_glyph;
cairo_bool_t diagonal, in_TJ;
cairo_status_t status, status_ignored;
double Tlm_x = 0, Tlm_y = 0;
double Tm_x = 0, y;
int i, hex_width;
cairo_output_stream_t *word_wrap_stream;
cairo_status_t status;
int i;
double x;
if (pdf_operators->num_glyphs == 0)
return 0;
for (i = 0; i < num_glyphs; i++)
cairo_matrix_transform_point (&pdf_operators->cairo_to_pdf, &glyphs[i].x, &glyphs[i].y);
word_wrap_stream = _word_wrap_stream_create (pdf_operators->stream, 72);
status = _cairo_output_stream_get_status (word_wrap_stream);
if (status)
return _cairo_output_stream_destroy (word_wrap_stream);
/* Check if glyph advance used to position every glyph */
x = pdf_operators->cur_x;
for (i = 0; i < pdf_operators->num_glyphs; i++) {
if (fabs(pdf_operators->glyphs[i].x_position - x) > GLYPH_POSITION_TOLERANCE)
break;
x += pdf_operators->glyphs[i].x_advance;
}
if (i == pdf_operators->num_glyphs) {
status = _cairo_pdf_operators_emit_glyph_string (pdf_operators,
word_wrap_stream);
} else {
status = _cairo_pdf_operators_emit_glyph_string_with_positioning (
pdf_operators, word_wrap_stream);
_cairo_output_stream_printf (word_wrap_stream,
"BT\n");
if (scaled_font->scale.xy == 0.0 &&
scaled_font->scale.yx == 0.0)
diagonal = TRUE;
else
diagonal = FALSE;
in_TJ = FALSE;
for (i = 0; i < num_glyphs; i++) {
status = _cairo_scaled_font_subsets_map_glyph (pdf_operators->font_subsets,
scaled_font, glyphs[i].index,
&subset_glyph);
if (status) {
status_ignored = _cairo_output_stream_destroy (word_wrap_stream);
return status;
}
if (subset_glyph.is_composite)
hex_width = 4;
else
hex_width = 2;
if (subset_glyph.is_scaled == FALSE) {
y = 0.0;
cairo_matrix_transform_distance (&scaled_font->scale,
&subset_glyph.x_advance,
&y);
}
if (subset_glyph.subset_id != current_subset_id) {
if (in_TJ) {
_cairo_output_stream_printf (word_wrap_stream, ">] TJ\n");
in_TJ = FALSE;
}
_cairo_output_stream_printf (word_wrap_stream,
"/f-%d-%d 1 Tf\n",
subset_glyph.font_id,
subset_glyph.subset_id);
if (pdf_operators->use_font_subset) {
status = pdf_operators->use_font_subset (subset_glyph.font_id,
subset_glyph.subset_id,
pdf_operators->use_font_subset_closure);
if (status) {
status_ignored = _cairo_output_stream_destroy (word_wrap_stream);
return status;
}
}
}
if (subset_glyph.subset_id != current_subset_id || !diagonal) {
_cairo_output_stream_printf (word_wrap_stream,
"%f %f %f %f %f %f Tm\n",
scaled_font->scale.xx,
-scaled_font->scale.yx,
-scaled_font->scale.xy,
scaled_font->scale.yy,
glyphs[i].x,
glyphs[i].y);
current_subset_id = subset_glyph.subset_id;
Tlm_x = glyphs[i].x;
Tlm_y = glyphs[i].y;
Tm_x = Tlm_x;
}
if (diagonal) {
if (i < num_glyphs - 1 &&
fabs((glyphs[i].y - glyphs[i+1].y)/scaled_font->scale.yy) < GLYPH_POSITION_TOLERANCE &&
fabs((glyphs[i].x - glyphs[i+1].x)/scaled_font->scale.xx) < 10)
{
if (!in_TJ) {
if (i != 0) {
_cairo_output_stream_printf (word_wrap_stream,
"%f %f Td\n",
(glyphs[i].x - Tlm_x)/scaled_font->scale.xx,
(glyphs[i].y - Tlm_y)/scaled_font->scale.yy);
Tlm_x = glyphs[i].x;
Tlm_y = glyphs[i].y;
Tm_x = Tlm_x;
}
_cairo_output_stream_printf (word_wrap_stream,
"[<%0*x",
hex_width,
subset_glyph.subset_glyph_index);
Tm_x += subset_glyph.x_advance;
in_TJ = TRUE;
} else {
if (fabs((glyphs[i].x - Tm_x)/scaled_font->scale.xx) > GLYPH_POSITION_TOLERANCE) {
double delta = glyphs[i].x - Tm_x;
int rounded_delta;
delta = -1000.0*delta/scaled_font->scale.xx;
/* As the delta is in 1/1000 of a unit of text
* space, rounding to an integer should still
* provide sufficient precision. We round the
* delta before adding to Tm_x so that we keep
* track of the accumulated rounding error in
* the PDF interpreter and compensate for it
* when calculating subsequent deltas.
*/
rounded_delta = _cairo_lround (delta);
if (rounded_delta != 0) {
_cairo_output_stream_printf (word_wrap_stream,
"> %d <",
rounded_delta);
}
/* Convert the rounded delta back to cairo
* space before adding to the current text
* position. */
delta = rounded_delta*scaled_font->scale.xx/-1000.0;
Tm_x += delta;
}
_cairo_output_stream_printf (word_wrap_stream,
"%0*x",
hex_width,
subset_glyph.subset_glyph_index);
Tm_x += subset_glyph.x_advance;
}
}
else
{
if (in_TJ) {
if (fabs((glyphs[i].x - Tm_x)/scaled_font->scale.xx) > GLYPH_POSITION_TOLERANCE) {
double delta = glyphs[i].x - Tm_x;
int rounded_delta;
delta = -1000.0*delta/scaled_font->scale.xx;
rounded_delta = _cairo_lround (delta);
if (rounded_delta != 0) {
_cairo_output_stream_printf (word_wrap_stream,
"> %d <",
rounded_delta);
}
delta = rounded_delta*scaled_font->scale.xx/-1000.0;
Tm_x += delta;
}
_cairo_output_stream_printf (word_wrap_stream,
"%0*x>] TJ\n",
hex_width,
subset_glyph.subset_glyph_index);
Tm_x += subset_glyph.x_advance;
in_TJ = FALSE;
} else {
if (i != 0) {
_cairo_output_stream_printf (word_wrap_stream,
"%f %f Td ",
(glyphs[i].x - Tlm_x)/scaled_font->scale.xx,
(glyphs[i].y - Tlm_y)/scaled_font->scale.yy);
Tlm_x = glyphs[i].x;
Tlm_y = glyphs[i].y;
Tm_x = Tlm_x;
}
_cairo_output_stream_printf (word_wrap_stream,
"<%0*x> Tj ",
hex_width,
subset_glyph.subset_glyph_index);
Tm_x += subset_glyph.x_advance;
}
}
} else {
_cairo_output_stream_printf (word_wrap_stream,
"<%0*x> Tj\n",
hex_width,
subset_glyph.subset_glyph_index);
}
}
pdf_operators->num_glyphs = 0;
_cairo_output_stream_printf (word_wrap_stream,
"ET\n");
status = _cairo_output_stream_destroy (word_wrap_stream);
if (status)
return status;
return status;
}
static cairo_status_t
_cairo_pdf_operators_add_glyph (cairo_pdf_operators_t *pdf_operators,
cairo_scaled_font_subsets_glyph_t *glyph,
double x_position)
{
double x, y;
x = glyph->x_advance;
y = glyph->y_advance;
if (glyph->is_scaled)
cairo_matrix_transform_distance (&pdf_operators->font_matrix_inverse, &x, &y);
pdf_operators->glyphs[pdf_operators->num_glyphs].x_position = x_position;
pdf_operators->glyphs[pdf_operators->num_glyphs].glyph_index = glyph->subset_glyph_index;
pdf_operators->glyphs[pdf_operators->num_glyphs].x_advance = x;
pdf_operators->num_glyphs++;
if (pdf_operators->num_glyphs == PDF_GLYPH_BUFFER_SIZE)
return _cairo_pdf_operators_flush_glyphs (pdf_operators);
return CAIRO_STATUS_SUCCESS;
}
/* Use 'Tm' operator to set the PDF text matrix. */
static cairo_status_t
_cairo_pdf_operators_set_text_matrix (cairo_pdf_operators_t *pdf_operators,
cairo_matrix_t *matrix)
{
cairo_matrix_t inverse;
cairo_status_t status;
/* We require the matrix to be invertable. */
inverse = *matrix;
status = cairo_matrix_invert (&inverse);
if (status)
return status;
pdf_operators->text_matrix = *matrix;
pdf_operators->cur_x = 0;
pdf_operators->cur_y = 0;
_cairo_output_stream_printf (pdf_operators->stream,
"%f %f %f %f %f %f Tm\n",
pdf_operators->text_matrix.xx,
pdf_operators->text_matrix.yx,
pdf_operators->text_matrix.xy,
pdf_operators->text_matrix.yy,
pdf_operators->text_matrix.x0,
pdf_operators->text_matrix.y0);
pdf_operators->cairo_to_pdftext = *matrix;
status = cairo_matrix_invert (&pdf_operators->cairo_to_pdftext);
assert (status == CAIRO_STATUS_SUCCESS);
cairo_matrix_multiply (&pdf_operators->cairo_to_pdftext,
&pdf_operators->cairo_to_pdf,
&pdf_operators->cairo_to_pdftext);
return _cairo_output_stream_get_status (pdf_operators->stream);
}
#define TEXT_MATRIX_TOLERANCE 1e-6
/* Set the translation components of the PDF text matrix to x, y. The
* 'Td' operator is used to transform the text matrix.
*/
static cairo_status_t
_cairo_pdf_operators_set_text_position (cairo_pdf_operators_t *pdf_operators,
double x,
double y)
{
cairo_matrix_t translate, inverse;
cairo_status_t status;
/* The Td operator transforms the text_matrix with:
*
* text_matrix' = T x text_matrix
*
* where T is a translation matrix with the translation components
* set to the Td operands tx and ty.
*/
inverse = pdf_operators->text_matrix;
status = cairo_matrix_invert (&inverse);
assert (status == CAIRO_STATUS_SUCCESS);
pdf_operators->text_matrix.x0 = x;
pdf_operators->text_matrix.y0 = y;
cairo_matrix_multiply (&translate, &pdf_operators->text_matrix, &inverse);
if (fabs(translate.x0) < TEXT_MATRIX_TOLERANCE)
translate.x0 = 0.0;
if (fabs(translate.y0) < TEXT_MATRIX_TOLERANCE)
translate.y0 = 0.0;
_cairo_output_stream_printf (pdf_operators->stream,
"%f %f Td\n",
translate.x0,
translate.y0);
pdf_operators->cur_x = 0;
pdf_operators->cur_y = 0;
pdf_operators->cairo_to_pdftext = pdf_operators->text_matrix;
status = cairo_matrix_invert (&pdf_operators->cairo_to_pdftext);
assert (status == CAIRO_STATUS_SUCCESS);
cairo_matrix_multiply (&pdf_operators->cairo_to_pdftext,
&pdf_operators->cairo_to_pdf,
&pdf_operators->cairo_to_pdftext);
return _cairo_output_stream_get_status (pdf_operators->stream);
}
/* Select the font using the 'Tf' operator. The font size is set to 1
* as we use the 'Tm' operator to set the font scale.
*/
static cairo_status_t
_cairo_pdf_operators_set_font_subset (cairo_pdf_operators_t *pdf_operators,
cairo_scaled_font_subsets_glyph_t *subset_glyph)
{
cairo_status_t status;
_cairo_output_stream_printf (pdf_operators->stream,
"/f-%d-%d 1 Tf\n",
subset_glyph->font_id,
subset_glyph->subset_id);
if (pdf_operators->use_font_subset) {
status = pdf_operators->use_font_subset (subset_glyph->font_id,
subset_glyph->subset_id,
pdf_operators->use_font_subset_closure);
if (status)
return status;
}
pdf_operators->font_id = subset_glyph->font_id;
pdf_operators->subset_id = subset_glyph->subset_id;
if (subset_glyph->is_composite)
pdf_operators->hex_width = 4;
else
pdf_operators->hex_width = 2;
return CAIRO_STATUS_SUCCESS;
}
static cairo_status_t
_cairo_pdf_operators_begin_text (cairo_pdf_operators_t *pdf_operators)
{
_cairo_output_stream_printf (pdf_operators->stream, "BT\n");
pdf_operators->in_text_object = TRUE;
pdf_operators->num_glyphs = 0;
return _cairo_output_stream_get_status (pdf_operators->stream);
}
static cairo_status_t
_cairo_pdf_operators_end_text (cairo_pdf_operators_t *pdf_operators)
{
cairo_status_t status;
status = _cairo_pdf_operators_flush_glyphs (pdf_operators);
if (status)
return status;
_cairo_output_stream_printf (pdf_operators->stream, "ET\n");
pdf_operators->in_text_object = FALSE;
return _cairo_output_stream_get_status (pdf_operators->stream);
}
/* Compare the scale components of two matrices. The translation
* components are ignored. */
static cairo_bool_t
_cairo_matrix_scale_equal (cairo_matrix_t *a, cairo_matrix_t *b)
{
return (a->xx == b->xx &&
a->xy == b->xy &&
a->yx == b->yx &&
a->yy == b->yy);
}
static cairo_status_t
_cairo_pdf_operators_begin_actualtext (cairo_pdf_operators_t *pdf_operators,
const char *utf8,
int utf8_len)
{
uint16_t *utf16;
int utf16_len;
cairo_status_t status;
int i;
_cairo_output_stream_printf (pdf_operators->stream, "/Span << /ActualText <feff");
if (utf8_len) {
status = _cairo_utf8_to_utf16 (utf8, utf8_len, &utf16, &utf16_len);
if (status)
return status;
for (i = 0; i < utf16_len; i++) {
_cairo_output_stream_printf (pdf_operators->stream,
"%04x", (int) (utf16[i]));
}
free (utf16);
}
_cairo_output_stream_printf (pdf_operators->stream, "> >> BDC\n");
return _cairo_output_stream_get_status (pdf_operators->stream);
}
static cairo_status_t
_cairo_pdf_operators_end_actualtext (cairo_pdf_operators_t *pdf_operators)
{
_cairo_output_stream_printf (pdf_operators->stream, "EMC\n");
return _cairo_output_stream_get_status (pdf_operators->stream);
}
static cairo_status_t
_cairo_pdf_operators_emit_glyph (cairo_pdf_operators_t *pdf_operators,
cairo_glyph_t *glyph,
cairo_scaled_font_subsets_glyph_t *subset_glyph)
{
double x, y;
cairo_status_t status;
if (pdf_operators->is_new_text_object ||
pdf_operators->font_id != subset_glyph->font_id ||
pdf_operators->subset_id != subset_glyph->subset_id)
{
status = _cairo_pdf_operators_flush_glyphs (pdf_operators);
if (status)
return status;
status = _cairo_pdf_operators_set_font_subset (pdf_operators, subset_glyph);
if (status)
return status;
pdf_operators->is_new_text_object = FALSE;
}
x = glyph->x;
y = glyph->y;
cairo_matrix_transform_point (&pdf_operators->cairo_to_pdftext, &x, &y);
/* The TJ operator for displaying text strings can only set
* the horizontal position of the glyphs. If the y position
* (in text space) changes, use the Td operator to change the
* current position to the next glyph. We also use the Td
* operator to move the current position if the horizontal
* position changes by more than 10 (in text space
* units). This is becauses the horizontal glyph positioning
* in the TJ operator is intended for kerning and there may be
* PDF consumers that do not handle very large position
* adjustments in TJ.
*/
if (fabs(x - pdf_operators->cur_x) > 10 ||
fabs(y - pdf_operators->cur_y) > GLYPH_POSITION_TOLERANCE)
{
status = _cairo_pdf_operators_flush_glyphs (pdf_operators);
if (status)
return status;
x = glyph->x;
y = glyph->y;
cairo_matrix_transform_point (&pdf_operators->cairo_to_pdf, &x, &y);
status = _cairo_pdf_operators_set_text_position (pdf_operators, x, y);
if (status)
return status;
x = 0.0;
y = 0.0;
}
status = _cairo_pdf_operators_add_glyph (pdf_operators,
subset_glyph,
x);
return status;
}
/* A utf8_len of -1 indicates no unicode text. A utf8_len = 0 is an
* empty string.
*/
static cairo_int_status_t
_cairo_pdf_operators_emit_cluster (cairo_pdf_operators_t *pdf_operators,
const char *utf8,
int utf8_len,
cairo_glyph_t *glyphs,
int num_glyphs,
cairo_bool_t backward,
cairo_scaled_font_t *scaled_font)
{
cairo_scaled_font_subsets_glyph_t subset_glyph;
cairo_glyph_t *cur_glyph;
cairo_status_t status;
int i;
/* If the cluster maps 1 glyph to 1 or more unicode characters, we
* first try _map_glyph() with the unicode string to see if it can
* use toUnicode to map our glyph to the unicode. This will fail
* if the glyph is already mapped to a different unicode string.
*
* We also go through this path if no unicode mapping was
* supplied (utf8_len < 0).
*
* Mapping a glyph to a zero length unicode string requires the
* use of ActualText.
*/
if (num_glyphs == 1 && utf8_len != 0) {
status = _cairo_scaled_font_subsets_map_glyph (pdf_operators->font_subsets,
scaled_font,
glyphs->index,
utf8,
utf8_len < 0 ? 0 : utf8_len,
&subset_glyph);
if (status)
return status;
if (subset_glyph.utf8_is_mapped || utf8_len < 0) {
status = _cairo_pdf_operators_emit_glyph (pdf_operators,
glyphs,
&subset_glyph);
return 0;
}
}
/* Fallback to using ActualText to map zero or more glyphs to a
* unicode string. */
_cairo_pdf_operators_flush_glyphs (pdf_operators);
status = _cairo_pdf_operators_begin_actualtext (pdf_operators, utf8, utf8_len);
cur_glyph = glyphs;
for (i = 0; i < num_glyphs; i++) {
status = _cairo_scaled_font_subsets_map_glyph (pdf_operators->font_subsets,
scaled_font,
cur_glyph->index,
NULL, 0,
&subset_glyph);
if (status)
return status;
status = _cairo_pdf_operators_emit_glyph (pdf_operators,
cur_glyph,
&subset_glyph);
if (status)
return status;
if (backward)
cur_glyph--;
else
cur_glyph++;
}
status = _cairo_pdf_operators_flush_glyphs (pdf_operators);
if (status)
return status;
status = _cairo_pdf_operators_end_actualtext (pdf_operators);
return status;
}
cairo_int_status_t
_cairo_pdf_operators_show_text_glyphs (cairo_pdf_operators_t *pdf_operators,
const char *utf8,
int utf8_len,
cairo_glyph_t *glyphs,
int num_glyphs,
const cairo_text_cluster_t *clusters,
int num_clusters,
cairo_bool_t backward,
cairo_scaled_font_t *scaled_font)
{
cairo_status_t status;
int i;
cairo_matrix_t text_matrix, invert_y_axis;
double x, y;
const char *cur_text;
cairo_glyph_t *cur_glyph;
pdf_operators->font_matrix_inverse = scaled_font->font_matrix;
status = cairo_matrix_invert (&pdf_operators->font_matrix_inverse);
if (status == CAIRO_STATUS_INVALID_MATRIX)
return CAIRO_STATUS_SUCCESS;
if (status)
return status;
pdf_operators->is_new_text_object = FALSE;
if (pdf_operators->in_text_object == FALSE) {
_cairo_pdf_operators_begin_text (pdf_operators);
/* Force Tm and Tf to be emitted when starting a new text
* object.*/
pdf_operators->is_new_text_object = TRUE;
}
cairo_matrix_init_scale (&invert_y_axis, 1, -1);
text_matrix = scaled_font->scale;
/* Invert y axis in font space */
cairo_matrix_multiply (&text_matrix, &text_matrix, &invert_y_axis);
/* Invert y axis in device space */
cairo_matrix_multiply (&text_matrix, &invert_y_axis, &text_matrix);
if (pdf_operators->is_new_text_object ||
! _cairo_matrix_scale_equal (&pdf_operators->text_matrix, &text_matrix))
{
_cairo_pdf_operators_flush_glyphs (pdf_operators);
x = glyphs[0].x;
y = glyphs[0].y;
cairo_matrix_transform_point (&pdf_operators->cairo_to_pdf, &x, &y);
text_matrix.x0 = x;
text_matrix.y0 = y;
status = _cairo_pdf_operators_set_text_matrix (pdf_operators, &text_matrix);
if (status == CAIRO_STATUS_INVALID_MATRIX)
return CAIRO_STATUS_SUCCESS;
if (status)
return status;
}
if (num_clusters > 0) {
cur_text = utf8;
if (backward)
cur_glyph = glyphs + num_glyphs;
else
cur_glyph = glyphs;
for (i = 0; i < num_clusters; i++) {
if (backward)
cur_glyph -= clusters[i].num_glyphs;
status = _cairo_pdf_operators_emit_cluster (pdf_operators,
cur_text,
clusters[i].num_bytes,
cur_glyph,
clusters[i].num_glyphs,
backward,
scaled_font);
if (status)
return status;
cur_text += clusters[i].num_bytes;
if (!backward)
cur_glyph += clusters[i].num_glyphs;
}
} else {
for (i = 0; i < num_glyphs; i++) {
status = _cairo_pdf_operators_emit_cluster (pdf_operators,
NULL,
-1, /* no unicode string available */
&glyphs[i],
1,
FALSE,
scaled_font);
if (status)
return status;
}
}
return _cairo_output_stream_get_status (pdf_operators->stream);
}

Просмотреть файл

@ -90,13 +90,8 @@ typedef struct _cairo_pdf_smask_group
cairo_stroke_style_t *style;
cairo_matrix_t ctm;
cairo_matrix_t ctm_inverse;
char *utf8;
int utf8_len;
cairo_glyph_t *glyphs;
int num_glyphs;
cairo_text_cluster_t *clusters;
int num_clusters;
cairo_bool_t backward;
cairo_scaled_font_t *scaled_font;
} cairo_pdf_smask_group_t;
@ -158,13 +153,6 @@ struct _cairo_pdf_surface {
cairo_bool_t force_fallbacks;
cairo_bool_t current_pattern_is_solid_color;
cairo_bool_t current_color_is_stroke;
double current_color_red;
double current_color_green;
double current_color_blue;
double current_color_alpha;
cairo_surface_t *paginated_surface;
};

Просмотреть файл

@ -48,7 +48,6 @@
#include "cairo-paginated-private.h"
#include "cairo-output-stream-private.h"
#include "cairo-meta-surface-private.h"
#include "cairo-type3-glyph-surface-private.h"
#include <time.h>
#include <zlib.h>
@ -282,7 +281,6 @@ _cairo_pdf_surface_create_for_stream_internal (cairo_output_stream_t *output,
surface->force_fallbacks = FALSE;
surface->select_pattern_gstate_saved = FALSE;
surface->current_pattern_is_solid_color = FALSE;
_cairo_pdf_operators_init (&surface->pdf_operators,
surface->output,
@ -303,13 +301,9 @@ _cairo_pdf_surface_create_for_stream_internal (cairo_output_stream_t *output,
CAIRO_CONTENT_COLOR_ALPHA,
width, height,
&cairo_pdf_surface_paginated_backend);
status = surface->paginated_surface->status;
if (status == CAIRO_STATUS_SUCCESS) {
/* paginated keeps the only reference to surface now, drop ours */
cairo_surface_destroy (&surface->base);
if (status == CAIRO_STATUS_SUCCESS)
return surface->paginated_surface;
}
BAIL1:
_cairo_scaled_font_subsets_destroy (surface->font_subsets);
@ -747,12 +741,8 @@ _cairo_pdf_smask_group_destroy (cairo_pdf_smask_group_t *group)
cairo_pattern_destroy (group->source);
if (group->mask)
cairo_pattern_destroy (group->mask);
if (group->utf8)
free (group->utf8);
if (group->glyphs)
free (group->glyphs);
if (group->clusters)
free (group->clusters);
if (group->scaled_font)
cairo_scaled_font_destroy (group->scaled_font);
free (group);
@ -781,23 +771,15 @@ _cairo_pdf_surface_add_pdf_pattern (cairo_pdf_surface_t *surface,
return CAIRO_STATUS_SUCCESS;
}
/* Gradients with zero stops do not produce any output */
if (pattern->type == CAIRO_PATTERN_TYPE_LINEAR ||
pattern->type == CAIRO_PATTERN_TYPE_RADIAL)
{
cairo_gradient_pattern_t *gradient;
gradient = (cairo_gradient_pattern_t *) pattern;
/* Gradients with zero stops do not produce any output */
if (gradient->n_stops == 0)
return CAIRO_INT_STATUS_NOTHING_TO_DO;
/* Gradients with one stop are the same as solid colors */
if (gradient->n_stops == 1) {
pattern_res->id = 0;
gstate_res->id = 0;
return CAIRO_STATUS_SUCCESS;
}
}
pdf_pattern.pattern = cairo_pattern_reference (pattern);
@ -869,8 +851,6 @@ _cairo_pdf_surface_open_stream (cairo_pdf_surface_t *surface,
surface->pdf_stream.self = self;
surface->pdf_stream.length = length;
surface->pdf_stream.compressed = compressed;
surface->current_pattern_is_solid_color = FALSE;
_cairo_pdf_operators_reset (&surface->pdf_operators);
_cairo_output_stream_printf (surface->output,
"%d 0 obj\n"
@ -912,10 +892,6 @@ _cairo_pdf_surface_close_stream (cairo_pdf_surface_t *surface)
if (! surface->pdf_stream.active)
return CAIRO_STATUS_SUCCESS;
status = _cairo_pdf_operators_flush (&surface->pdf_operators);
if (status)
return status;
if (surface->pdf_stream.compressed) {
status = _cairo_output_stream_destroy (surface->output);
surface->output = surface->pdf_stream.old_output;
@ -1006,8 +982,6 @@ _cairo_pdf_surface_open_group (cairo_pdf_surface_t *surface,
assert (surface->group_stream.active == FALSE);
surface->group_stream.active = TRUE;
surface->current_pattern_is_solid_color = FALSE;
_cairo_pdf_operators_reset (&surface->pdf_operators);
surface->group_stream.mem_stream = _cairo_memory_stream_create ();
@ -1059,10 +1033,6 @@ _cairo_pdf_surface_close_group (cairo_pdf_surface_t *surface,
assert (surface->pdf_stream.active == FALSE);
assert (surface->group_stream.active == TRUE);
status = _cairo_pdf_operators_flush (&surface->pdf_operators);
if (status)
return status;
if (surface->compress_content) {
status = _cairo_output_stream_destroy (surface->group_stream.stream);
surface->group_stream.stream = NULL;
@ -1146,10 +1116,6 @@ _cairo_pdf_surface_close_content_stream (cairo_pdf_surface_t *surface)
assert (surface->pdf_stream.active == TRUE);
assert (surface->group_stream.active == FALSE);
status = _cairo_pdf_operators_flush (&surface->pdf_operators);
if (status)
return status;
_cairo_output_stream_printf (surface->output, "Q\n");
status = _cairo_pdf_surface_close_stream (surface);
if (status)
@ -1215,10 +1181,7 @@ _cairo_pdf_surface_finish (void *abstract_surface)
"%%%%EOF\n",
offset);
status2 = _cairo_pdf_operators_fini (&surface->pdf_operators);
/* pdf_operators has already been flushed when the last stream was
* closed so we should never be writing anything here. */
assert(status2 == CAIRO_STATUS_SUCCESS);
_cairo_pdf_operators_fini (&surface->pdf_operators);
/* close any active streams still open due to fatal errors */
status2 = _cairo_pdf_surface_close_stream (surface);
@ -1267,23 +1230,13 @@ _cairo_pdf_surface_finish (void *abstract_surface)
static cairo_int_status_t
_cairo_pdf_surface_start_page (void *abstract_surface)
{
cairo_pdf_surface_t *surface = abstract_surface;
_cairo_pdf_group_resources_clear (&surface->resources);
return CAIRO_STATUS_SUCCESS;
}
static cairo_int_status_t
_cairo_pdf_surface_has_fallback_images (void *abstract_surface,
cairo_bool_t has_fallbacks)
{
cairo_status_t status;
cairo_pdf_surface_t *surface = abstract_surface;
surface->has_fallback_images = has_fallbacks;
status = _cairo_pdf_surface_open_content_stream (surface, has_fallbacks);
surface->has_fallback_images = FALSE;
_cairo_pdf_group_resources_clear (&surface->resources);
status = _cairo_pdf_surface_open_content_stream (surface, TRUE);
if (status)
return status;
@ -1543,7 +1496,7 @@ _cairo_pdf_surface_emit_meta_surface (cairo_pdf_surface_t *surface,
cairo_paginated_mode_t old_paginated_mode;
cairo_clip_t *old_clip;
cairo_rectangle_int_t meta_extents;
cairo_status_t status;
cairo_status_t status, status2;
int alpha = 0;
status = _cairo_surface_get_extents (meta_surface, &meta_extents);
@ -1571,7 +1524,7 @@ _cairo_pdf_surface_emit_meta_surface (cairo_pdf_surface_t *surface,
if (cairo_surface_get_content (meta_surface) == CAIRO_CONTENT_COLOR) {
status = _cairo_pdf_surface_add_alpha (surface, 1.0, &alpha);
if (status)
return status;
goto CLEANUP_GROUP;
_cairo_output_stream_printf (surface->output,
"q /a%d gs 0 0 0 rg 0 0 %f %f re f Q\n",
@ -1584,18 +1537,18 @@ _cairo_pdf_surface_emit_meta_surface (cairo_pdf_surface_t *surface,
CAIRO_META_REGION_NATIVE);
assert (status != CAIRO_INT_STATUS_UNSUPPORTED);
if (status)
return status;
status = _cairo_surface_set_clip (&surface->base, old_clip);
if (status)
return status;
goto CLEANUP_GROUP;
status = _cairo_pdf_surface_close_content_stream (surface);
CLEANUP_GROUP:
_cairo_pdf_surface_set_size_internal (surface,
old_width,
old_height);
surface->paginated_mode = old_paginated_mode;
status2 = _cairo_surface_set_clip (&surface->base, old_clip);
if (status == CAIRO_STATUS_SUCCESS)
status = status2;
return status;
}
@ -2609,73 +2562,29 @@ _cairo_pdf_surface_select_pattern (cairo_pdf_surface_t *surface,
{
cairo_status_t status;
int alpha;
cairo_bool_t is_solid_color = FALSE;
cairo_color_t *solid_color;
if (pattern->type == CAIRO_PATTERN_TYPE_SOLID) {
cairo_solid_pattern_t *solid = (cairo_solid_pattern_t *) pattern;
cairo_solid_pattern_t *solid_pattern = (cairo_solid_pattern_t *) pattern;
is_solid_color = TRUE;
solid_color = &solid->color;
}
status = _cairo_pdf_surface_add_alpha (surface, solid_pattern->color.alpha, &alpha);
if (status)
return status;
if (pattern->type == CAIRO_PATTERN_TYPE_LINEAR ||
pattern->type == CAIRO_PATTERN_TYPE_RADIAL)
{
cairo_gradient_pattern_t *gradient = (cairo_gradient_pattern_t *) pattern;
_cairo_output_stream_printf (surface->output,
"%f %f %f ",
solid_pattern->color.red,
solid_pattern->color.green,
solid_pattern->color.blue);
if (gradient->n_stops == 1) {
is_solid_color = TRUE;
solid_color = &gradient->stops[0].color;
}
}
if (is_stroke)
_cairo_output_stream_printf (surface->output, "RG ");
else
_cairo_output_stream_printf (surface->output, "rg ");
if (is_solid_color) {
if (surface->current_pattern_is_solid_color == FALSE ||
surface->current_color_red != solid_color->red ||
surface->current_color_green != solid_color->green ||
surface->current_color_blue != solid_color->blue ||
surface->current_color_is_stroke != is_stroke)
{
status = _cairo_pdf_operators_flush (&surface->pdf_operators);
if (status)
return status;
_cairo_output_stream_printf (surface->output,
"%f %f %f ",
solid_color->red,
solid_color->green,
solid_color->blue);
if (is_stroke)
_cairo_output_stream_printf (surface->output, "RG ");
else
_cairo_output_stream_printf (surface->output, "rg ");
surface->current_color_red = solid_color->red;
surface->current_color_green = solid_color->green;
surface->current_color_blue = solid_color->blue;
surface->current_color_is_stroke = is_stroke;
}
if (surface->current_pattern_is_solid_color == FALSE ||
surface->current_color_alpha != solid_color->alpha)
{
status = _cairo_pdf_surface_add_alpha (surface, solid_color->alpha, &alpha);
if (status)
return status;
status = _cairo_pdf_operators_flush (&surface->pdf_operators);
if (status)
return status;
_cairo_output_stream_printf (surface->output,
"/a%d gs\n",
alpha);
surface->current_color_alpha = solid_color->alpha;
}
surface->current_pattern_is_solid_color = TRUE;
_cairo_output_stream_printf (surface->output,
"/a%d gs\n",
alpha);
surface->select_pattern_gstate_saved = FALSE;
} else {
status = _cairo_pdf_surface_add_alpha (surface, 1.0, &alpha);
if (status)
@ -2685,10 +2594,6 @@ _cairo_pdf_surface_select_pattern (cairo_pdf_surface_t *surface,
if (status)
return status;
status = _cairo_pdf_operators_flush (&surface->pdf_operators);
if (status)
return status;
/* fill-stroke calls select_pattern twice. Don't save if the
* gstate is already saved. */
if (!surface->select_pattern_gstate_saved)
@ -2707,28 +2612,17 @@ _cairo_pdf_surface_select_pattern (cairo_pdf_surface_t *surface,
"/a%d gs\n",
alpha);
surface->select_pattern_gstate_saved = TRUE;
surface->current_pattern_is_solid_color = FALSE;
}
return _cairo_output_stream_get_status (surface->output);
}
static cairo_int_status_t
static void
_cairo_pdf_surface_unselect_pattern (cairo_pdf_surface_t *surface)
{
cairo_int_status_t status;
if (surface->select_pattern_gstate_saved) {
status = _cairo_pdf_operators_flush (&surface->pdf_operators);
if (status)
return status;
if (surface->select_pattern_gstate_saved)
_cairo_output_stream_printf (surface->output, "Q\n");
_cairo_pdf_operators_reset (&surface->pdf_operators);
}
surface->select_pattern_gstate_saved = FALSE;
return CAIRO_STATUS_SUCCESS;
}
static cairo_int_status_t
@ -2777,17 +2671,9 @@ _cairo_pdf_surface_intersect_clip_path (void *abstract_surface,
cairo_antialias_t antialias)
{
cairo_pdf_surface_t *surface = abstract_surface;
cairo_int_status_t status;
if (path == NULL) {
status = _cairo_pdf_operators_flush (&surface->pdf_operators);
if (status)
return status;
_cairo_output_stream_printf (surface->output, "Q q\n");
surface->current_pattern_is_solid_color = FALSE;
_cairo_pdf_operators_reset (&surface->pdf_operators);
return CAIRO_STATUS_SUCCESS;
}
@ -2857,54 +2743,34 @@ _cairo_pdf_surface_write_pages (cairo_pdf_surface_t *surface)
"endobj\n");
}
static cairo_status_t
_cairo_pdf_surface_emit_unicode_for_glyph (cairo_pdf_surface_t *surface,
const char *utf8)
{
uint16_t *utf16 = NULL;
int utf16_len = 0;
cairo_status_t status;
int i;
if (utf8 && *utf8) {
status = _cairo_utf8_to_utf16 (utf8, -1, &utf16, &utf16_len);
if (status && status != CAIRO_STATUS_INVALID_STRING)
return status;
}
_cairo_output_stream_printf (surface->output, "<");
if (utf16 == NULL || utf16_len == 0) {
/* According to the "ToUnicode Mapping File Tutorial"
* http://www.adobe.com/devnet/acrobat/pdfs/5411.ToUnicode.pdf
*
* Glyphs that do not map to a Unicode code point must be
* mapped to 0xfffd "REPLACEMENT CHARACTER".
*/
_cairo_output_stream_printf (surface->output,
"fffd");
} else {
for (i = 0; i < utf16_len; i++)
_cairo_output_stream_printf (surface->output,
"%04x", (int) (utf16[i]));
}
_cairo_output_stream_printf (surface->output, ">");
if (utf16)
free (utf16);
return CAIRO_STATUS_SUCCESS;
}
static cairo_int_status_t
_cairo_pdf_surface_emit_to_unicode_stream (cairo_pdf_surface_t *surface,
cairo_scaled_font_subset_t *font_subset,
cairo_bool_t is_composite,
cairo_pdf_resource_t *stream)
{
const cairo_scaled_font_backend_t *backend;
unsigned int i, num_bfchar;
cairo_int_status_t status;
stream->id = 0;
if (font_subset->to_unicode == NULL)
return CAIRO_INT_STATUS_UNSUPPORTED;
status = _cairo_truetype_create_glyph_to_unicode_map (font_subset);
if (status) {
if (status != CAIRO_INT_STATUS_UNSUPPORTED)
return status;
backend = font_subset->scaled_font->backend;
if (backend->map_glyphs_to_unicode == NULL)
return CAIRO_INT_STATUS_UNSUPPORTED;
status = backend->map_glyphs_to_unicode (font_subset->scaled_font,
font_subset);
if (status)
return status;
}
status = _cairo_pdf_surface_open_stream (surface,
NULL,
@ -2938,12 +2804,10 @@ _cairo_pdf_surface_emit_to_unicode_stream (cairo_pdf_surface_t *surface,
"endcodespacerange\n");
num_bfchar = font_subset->num_glyphs - 1;
/* The CMap specification has a limit of 100 characters per beginbfchar operator */
_cairo_output_stream_printf (surface->output,
"%d beginbfchar\n",
num_bfchar > 100 ? 100 : num_bfchar);
for (i = 0; i < num_bfchar; i++) {
if (i != 0 && i % 100 == 0) {
_cairo_output_stream_printf (surface->output,
@ -2953,16 +2817,13 @@ _cairo_pdf_surface_emit_to_unicode_stream (cairo_pdf_surface_t *surface,
}
if (is_composite) {
_cairo_output_stream_printf (surface->output,
"<%04x> ",
i + 1);
"<%04x> <%04lx>\n",
i + 1, font_subset->to_unicode[i + 1]);
} else {
_cairo_output_stream_printf (surface->output,
"<%02x> ",
i + 1);
"<%02x> <%04lx>\n",
i + 1, font_subset->to_unicode[i + 1]);
}
_cairo_pdf_surface_emit_unicode_for_glyph (surface, font_subset->utf8[i + 1]);
_cairo_output_stream_printf (surface->output,
"\n");
}
_cairo_output_stream_printf (surface->output,
"endbfchar\n");
@ -3440,18 +3301,71 @@ _cairo_pdf_surface_emit_truetype_font_subset (cairo_pdf_surface_t *surface,
return status;
}
static cairo_status_t
_cairo_pdf_emit_imagemask (cairo_image_surface_t *image,
cairo_output_stream_t *stream)
static cairo_int_status_t
_cairo_pdf_surface_emit_bitmap_glyph (cairo_pdf_surface_t *surface,
cairo_scaled_font_t *scaled_font,
unsigned long glyph_index,
cairo_pdf_resource_t *glyph_ret,
cairo_box_t *bbox,
double *width)
{
unsigned char *byte, output_byte;
int row, col, num_cols;
cairo_scaled_glyph_t *scaled_glyph;
cairo_status_t status;
cairo_image_surface_t *image;
unsigned char *row, *byte;
int rows, cols;
double x_advance, y_advance;
/* The only image type supported by Type 3 fonts are 1-bit image
* masks */
assert (image->format == CAIRO_FORMAT_A1);
status = _cairo_scaled_glyph_lookup (scaled_font,
glyph_index,
CAIRO_SCALED_GLYPH_INFO_METRICS|
CAIRO_SCALED_GLYPH_INFO_SURFACE,
&scaled_glyph);
if (status)
return status;
_cairo_output_stream_printf (stream,
x_advance = scaled_glyph->metrics.x_advance;
y_advance = scaled_glyph->metrics.y_advance;
cairo_matrix_transform_distance (&scaled_font->ctm, &x_advance, &y_advance);
*bbox = scaled_glyph->bbox;
*width = x_advance;
image = scaled_glyph->surface;
if (image->format != CAIRO_FORMAT_A1) {
image = _cairo_image_surface_clone (image, CAIRO_FORMAT_A1);
status = cairo_surface_status (&image->base);
if (status)
return status;
}
status = _cairo_pdf_surface_open_stream (surface,
NULL,
surface->compress_content,
NULL);
if (status) {
if (image != scaled_glyph->surface)
cairo_surface_destroy (&image->base);
return status;
}
*glyph_ret = surface->pdf_stream.self;
_cairo_output_stream_printf (surface->output,
"%f 0 %f %f %f %f d1\n",
x_advance,
_cairo_fixed_to_double (scaled_glyph->bbox.p1.x),
_cairo_fixed_to_double (scaled_glyph->bbox.p2.y),
_cairo_fixed_to_double (scaled_glyph->bbox.p2.x),
_cairo_fixed_to_double (scaled_glyph->bbox.p1.y));
_cairo_output_stream_printf (surface->output,
"%f 0 0 %f %f %f cm\n",
_cairo_fixed_to_double (scaled_glyph->bbox.p2.x) - _cairo_fixed_to_double (scaled_glyph->bbox.p1.x),
_cairo_fixed_to_double (scaled_glyph->bbox.p1.y) - _cairo_fixed_to_double (scaled_glyph->bbox.p2.y),
_cairo_fixed_to_double (scaled_glyph->bbox.p1.x),
_cairo_fixed_to_double (scaled_glyph->bbox.p2.y));
_cairo_output_stream_printf (surface->output,
"BI\n"
"/IM true\n"
"/W %d\n"
@ -3461,23 +3375,23 @@ _cairo_pdf_emit_imagemask (cairo_image_surface_t *image,
image->width,
image->height);
_cairo_output_stream_printf (stream,
_cairo_output_stream_printf (surface->output,
"ID ");
num_cols = (image->width + 7) / 8;
for (row = 0; row < image->height; row++) {
byte = image->data + row * image->stride;
for (col = 0; col < num_cols; col++) {
output_byte = CAIRO_BITSWAP8_IF_LITTLE_ENDIAN (*byte);
_cairo_output_stream_write (stream, &output_byte, 1);
byte++;
for (row = image->data, rows = image->height; rows; row += image->stride, rows--) {
for (byte = row, cols = (image->width + 7) / 8; cols; byte++, cols--) {
unsigned char output_byte = CAIRO_BITSWAP8_IF_LITTLE_ENDIAN (*byte);
_cairo_output_stream_write (surface->output, &output_byte, 1);
}
}
_cairo_output_stream_printf (stream,
_cairo_output_stream_printf (surface->output,
"\nEI\n");
return _cairo_output_stream_get_status (stream);
status = _cairo_pdf_surface_close_stream (surface);
if (image != scaled_glyph->surface)
cairo_surface_destroy (&image->base);
return status;
}
static cairo_status_t
@ -3492,7 +3406,6 @@ _cairo_pdf_surface_emit_type3_font_subset (cairo_pdf_surface_t *surface,
unsigned int i;
cairo_box_t font_bbox = {{0,0},{0,0}};
cairo_box_t bbox = {{0,0},{0,0}};
cairo_surface_t *type3_surface;
if (font_subset->num_glyphs == 0)
return CAIRO_STATUS_SUCCESS;
@ -3513,29 +3426,13 @@ _cairo_pdf_surface_emit_type3_font_subset (cairo_pdf_surface_t *surface,
return _cairo_error (CAIRO_STATUS_NO_MEMORY);
}
type3_surface = _cairo_type3_glyph_surface_create (font_subset->scaled_font,
NULL,
_cairo_pdf_emit_imagemask);
for (i = 0; i < font_subset->num_glyphs; i++) {
status = _cairo_pdf_surface_open_stream (surface,
NULL,
surface->compress_content,
NULL);
glyphs[i] = surface->pdf_stream.self;
if (i == 0) {
status = _cairo_type3_glyph_surface_emit_notdef_glyph (type3_surface,
surface->output,
&bbox,
&widths[i]);
} else {
status = _cairo_type3_glyph_surface_emit_glyph (type3_surface,
surface->output,
font_subset->glyphs[i],
&bbox,
&widths[i]);
}
status = _cairo_pdf_surface_close_stream (surface);
status = _cairo_pdf_surface_emit_bitmap_glyph (surface,
font_subset->scaled_font,
font_subset->glyphs[i],
&glyphs[i],
&bbox,
&widths[i]);
if (status)
break;
@ -3555,7 +3452,6 @@ _cairo_pdf_surface_emit_type3_font_subset (cairo_pdf_surface_t *surface,
font_bbox.p2.y = bbox.p2.y;
}
}
cairo_surface_destroy (type3_surface);
if (status) {
free (glyphs);
free (widths);
@ -3616,16 +3512,20 @@ _cairo_pdf_surface_emit_type3_font_subset (cairo_pdf_surface_t *surface,
"<< /Type /Font\n"
" /Subtype /Type3\n"
" /FontBBox [%f %f %f %f]\n"
" /FontMatrix [ 1 0 0 1 0 0 ]\n"
" /FontMatrix [ %f %f %f %f 0 0 ]\n"
" /Encoding %d 0 R\n"
" /CharProcs %d 0 R\n"
" /FirstChar 0\n"
" /LastChar %d\n",
subset_resource.id,
_cairo_fixed_to_double (font_bbox.p1.x),
- _cairo_fixed_to_double (font_bbox.p2.y),
_cairo_fixed_to_double (font_bbox.p1.y),
_cairo_fixed_to_double (font_bbox.p2.x),
- _cairo_fixed_to_double (font_bbox.p1.y),
_cairo_fixed_to_double (font_bbox.p2.y),
matrix.xx,
matrix.yx,
-matrix.xy,
-matrix.yy,
encoding.id,
char_procs.id,
font_subset->num_glyphs - 1);
@ -3682,7 +3582,6 @@ _cairo_pdf_surface_emit_unscaled_font_subset (cairo_scaled_font_subset_t *font_s
status = _cairo_pdf_surface_emit_type1_fallback_font (surface, font_subset);
if (status != CAIRO_INT_STATUS_UNSUPPORTED)
return status;
}
ASSERT_NOT_REACHED;
@ -3831,9 +3730,7 @@ _cairo_pdf_surface_write_mask_group (cairo_pdf_surface_t *surface,
"0 0 %f %f re f\n",
surface->width, surface->height);
status = _cairo_pdf_surface_unselect_pattern (surface);
if (status)
return status;
_cairo_pdf_surface_unselect_pattern (surface);
}
status = _cairo_pdf_surface_close_group (surface, &mask_group);
@ -3886,9 +3783,7 @@ _cairo_pdf_surface_write_mask_group (cairo_pdf_surface_t *surface,
"0 0 %f %f re f\n",
surface->width, surface->height);
status = _cairo_pdf_surface_unselect_pattern (surface);
if (status)
return status;
_cairo_pdf_surface_unselect_pattern (surface);
}
status = _cairo_pdf_surface_close_group (surface, NULL);
@ -3977,21 +3872,16 @@ _cairo_pdf_surface_write_smask_group (cairo_pdf_surface_t *surface,
&group->ctm_inverse);
break;
case PDF_SHOW_GLYPHS:
status = _cairo_pdf_operators_show_text_glyphs (&surface->pdf_operators,
group->utf8, group->utf8_len,
group->glyphs, group->num_glyphs,
group->clusters, group->num_clusters,
group->backward,
group->scaled_font);
status = _cairo_pdf_operators_show_glyphs (&surface->pdf_operators,
group->glyphs,
group->num_glyphs,
group->scaled_font);
break;
}
if (status)
return status;
status = _cairo_pdf_surface_unselect_pattern (surface);
if (status)
return status;
_cairo_pdf_surface_unselect_pattern (surface);
status = _cairo_pdf_surface_close_group (surface, NULL);
_cairo_pdf_surface_set_size_internal (surface,
@ -4271,19 +4161,8 @@ _cairo_pdf_surface_analyze_operation (cairo_pdf_surface_t *surface,
cairo_surface_pattern_t *surface_pattern = (cairo_surface_pattern_t *) pattern;
if (_cairo_surface_is_meta (surface_pattern->surface)) {
if (_cairo_pattern_is_opaque (pattern)) {
if (_cairo_pattern_is_opaque (pattern))
return CAIRO_INT_STATUS_ANALYZE_META_SURFACE_PATTERN;
} else {
/* FIXME: The analysis surface does not yet have
* the capability to analyze a non opaque meta
* surface and mark it supported if there is
* nothing underneath. For now meta surfaces of
* type CONTENT_COLOR_ALPHA painted with
* OPERATOR_SOURCE will result in a fallback
* image. */
return CAIRO_INT_STATUS_UNSUPPORTED;
}
} else {
return _cairo_pdf_surface_analyze_surface_pattern_transparency (surface,
surface_pattern);
@ -4323,6 +4202,7 @@ _cairo_pdf_surface_start_fallback (cairo_pdf_surface_t *surface)
if (status)
return status;
surface->has_fallback_images = TRUE;
_cairo_pdf_group_resources_clear (&surface->resources);
return _cairo_pdf_surface_open_content_stream (surface, TRUE);
}
@ -4377,10 +4257,6 @@ _cairo_pdf_surface_paint (void *abstract_surface,
if (status)
return status;
status = _cairo_pdf_operators_flush (&surface->pdf_operators);
if (status)
return status;
_cairo_output_stream_printf (surface->output,
"q /s%d gs /x%d Do Q\n",
gstate_res.id,
@ -4394,9 +4270,7 @@ _cairo_pdf_surface_paint (void *abstract_surface,
"0 0 %f %f re f\n",
surface->width, surface->height);
status = _cairo_pdf_surface_unselect_pattern (surface);
if (status)
return status;
_cairo_pdf_surface_unselect_pattern (surface);
}
return _cairo_output_stream_get_status (surface->output);
@ -4459,10 +4333,6 @@ _cairo_pdf_surface_mask (void *abstract_surface,
if (status)
return status;
status = _cairo_pdf_operators_flush (&surface->pdf_operators);
if (status)
return status;
_cairo_output_stream_printf (surface->output,
"q /s%d gs /x%d Do Q\n",
group->group_res.id,
@ -4531,10 +4401,6 @@ _cairo_pdf_surface_stroke (void *abstract_surface,
if (status)
return status;
status = _cairo_pdf_operators_flush (&surface->pdf_operators);
if (status)
return status;
_cairo_output_stream_printf (surface->output,
"q /s%d gs /x%d Do Q\n",
gstate_res.id,
@ -4552,9 +4418,7 @@ _cairo_pdf_surface_stroke (void *abstract_surface,
if (status)
return status;
status = _cairo_pdf_surface_unselect_pattern (surface);
if (status)
return status;
_cairo_pdf_surface_unselect_pattern (surface);
}
return _cairo_output_stream_get_status (surface->output);
@ -4621,10 +4485,6 @@ _cairo_pdf_surface_fill (void *abstract_surface,
if (status)
return status;
status = _cairo_pdf_operators_flush (&surface->pdf_operators);
if (status)
return status;
_cairo_output_stream_printf (surface->output,
"q /s%d gs /x%d Do Q\n",
gstate_res.id,
@ -4640,9 +4500,7 @@ _cairo_pdf_surface_fill (void *abstract_surface,
if (status)
return status;
status = _cairo_pdf_surface_unselect_pattern (surface);
if (status)
return status;
_cairo_pdf_surface_unselect_pattern (surface);
}
return _cairo_output_stream_get_status (surface->output);
@ -4729,31 +4587,18 @@ _cairo_pdf_surface_fill_stroke (void *abstract_surface,
if (status)
return status;
status = _cairo_pdf_surface_unselect_pattern (surface);
if (status)
return status;
_cairo_pdf_surface_unselect_pattern (surface);
return _cairo_output_stream_get_status (surface->output);
}
static cairo_bool_t
_cairo_pdf_surface_has_show_text_glyphs (void *abstract_surface)
{
return TRUE;
}
static cairo_int_status_t
_cairo_pdf_surface_show_text_glyphs (void *abstract_surface,
cairo_operator_t op,
cairo_pattern_t *source,
const char *utf8,
int utf8_len,
cairo_glyph_t *glyphs,
int num_glyphs,
const cairo_text_cluster_t *clusters,
int num_clusters,
cairo_bool_t backward,
cairo_scaled_font_t *scaled_font)
_cairo_pdf_surface_show_glyphs (void *abstract_surface,
cairo_operator_t op,
cairo_pattern_t *source,
cairo_glyph_t *glyphs,
int num_glyphs,
cairo_scaled_font_t *scaled_font)
{
cairo_pdf_surface_t *surface = abstract_surface;
cairo_status_t status;
@ -4781,37 +4626,13 @@ _cairo_pdf_surface_show_text_glyphs (void *abstract_surface,
group->operation = PDF_SHOW_GLYPHS;
group->source = cairo_pattern_reference (source);
group->source_res = pattern_res;
if (utf8_len) {
group->utf8 = malloc(utf8_len);
if (group->utf8) {
_cairo_pdf_smask_group_destroy (group);
return _cairo_error (CAIRO_STATUS_NO_MEMORY);
}
memcpy (group->utf8, utf8, utf8_len);
}
group->utf8_len = utf8_len;
if (num_glyphs) {
group->glyphs = _cairo_malloc_ab (num_glyphs, sizeof (cairo_glyph_t));
if (group->glyphs == NULL) {
_cairo_pdf_smask_group_destroy (group);
return _cairo_error (CAIRO_STATUS_NO_MEMORY);
}
memcpy (group->glyphs, glyphs, sizeof (cairo_glyph_t) * num_glyphs);
group->glyphs = _cairo_malloc_ab (num_glyphs, sizeof (cairo_glyph_t));
if (group->glyphs == NULL) {
_cairo_pdf_smask_group_destroy (group);
return _cairo_error (CAIRO_STATUS_NO_MEMORY);
}
memcpy (group->glyphs, glyphs, sizeof (cairo_glyph_t) * num_glyphs);
group->num_glyphs = num_glyphs;
if (num_clusters) {
group->clusters = _cairo_malloc_ab (num_clusters, sizeof (cairo_text_cluster_t));
if (group->clusters) {
_cairo_pdf_smask_group_destroy (group);
return _cairo_error (CAIRO_STATUS_NO_MEMORY);
}
memcpy (group->clusters, clusters, sizeof (cairo_text_cluster_t) * num_clusters);
}
group->num_clusters = num_clusters;
group->scaled_font = cairo_scaled_font_reference (scaled_font);
status = _cairo_pdf_surface_add_smask_group (surface, group);
if (status) {
@ -4827,10 +4648,6 @@ _cairo_pdf_surface_show_text_glyphs (void *abstract_surface,
if (status)
return status;
status = _cairo_pdf_operators_flush (&surface->pdf_operators);
if (status)
return status;
_cairo_output_stream_printf (surface->output,
"q /s%d gs /x%d Do Q\n",
gstate_res.id,
@ -4840,34 +4657,19 @@ _cairo_pdf_surface_show_text_glyphs (void *abstract_surface,
if (status)
return status;
/* Each call to show_glyphs() with a transclucent pattern must
* be in a separate text object otherwise overlapping text
* from separate calls to show_glyphs will not composite with
* each other. */
if (! _cairo_pattern_is_opaque (source)) {
status = _cairo_pdf_operators_flush (&surface->pdf_operators);
if (status)
return status;
}
status = _cairo_pdf_operators_show_text_glyphs (&surface->pdf_operators,
utf8, utf8_len,
glyphs, num_glyphs,
clusters, num_clusters,
backward,
scaled_font);
status = _cairo_pdf_operators_show_glyphs (&surface->pdf_operators,
glyphs,
num_glyphs,
scaled_font);
if (status)
return status;
status = _cairo_pdf_surface_unselect_pattern (surface);
if (status)
return status;
_cairo_pdf_surface_unselect_pattern (surface);
}
return _cairo_output_stream_get_status (surface->output);
}
static void
_cairo_pdf_surface_set_paginated_mode (void *abstract_surface,
cairo_paginated_mode_t paginated_mode)
@ -4907,20 +4709,15 @@ static const cairo_surface_backend_t cairo_pdf_surface_backend = {
_cairo_pdf_surface_mask,
_cairo_pdf_surface_stroke,
_cairo_pdf_surface_fill,
NULL, /* show_glyphs */
_cairo_pdf_surface_show_glyphs,
NULL, /* snapshot */
NULL, /* is_compatible */
NULL, /* reset */
_cairo_pdf_surface_fill_stroke,
NULL, /* create_solid_pattern_surface */
_cairo_pdf_surface_has_show_text_glyphs,
_cairo_pdf_surface_show_text_glyphs,
};
static const cairo_paginated_surface_backend_t cairo_pdf_surface_paginated_backend = {
_cairo_pdf_surface_start_page,
_cairo_pdf_surface_set_paginated_mode,
NULL, /* set_bounding_box */
_cairo_pdf_surface_has_fallback_images,
_cairo_pdf_surface_set_paginated_mode
};

Просмотреть файл

@ -37,7 +37,7 @@
#ifndef CAIRO_PDF_H
#define CAIRO_PDF_H
#include "cairo.h"
#include <cairo.h>
#if CAIRO_HAS_PDF_SURFACE

Просмотреть файл

@ -45,6 +45,15 @@ _cairo_pen_compute_slopes (cairo_pen_t *pen);
static void
_cairo_pen_stroke_spline_half (cairo_pen_t *pen, cairo_spline_t *spline, cairo_direction_t dir, cairo_polygon_t *polygon);
void
_cairo_pen_init_empty (cairo_pen_t *pen)
{
pen->radius = 0;
pen->tolerance = 0;
pen->vertices = NULL;
pen->num_vertices = 0;
}
cairo_status_t
_cairo_pen_init (cairo_pen_t *pen,
double radius,
@ -69,14 +78,10 @@ _cairo_pen_init (cairo_pen_t *pen,
radius,
ctm);
if (pen->num_vertices > ARRAY_LENGTH (pen->vertices_embedded)) {
pen->vertices = _cairo_malloc_ab (pen->num_vertices,
sizeof (cairo_pen_vertex_t));
if (pen->vertices == NULL)
return _cairo_error (CAIRO_STATUS_NO_MEMORY);
} else {
pen->vertices = pen->vertices_embedded;
}
pen->vertices = _cairo_malloc_ab (pen->num_vertices,
sizeof (cairo_pen_vertex_t));
if (pen->vertices == NULL)
return _cairo_error (CAIRO_STATUS_NO_MEMORY);
/*
* Compute pen coordinates. To generate the right ellipse, compute points around
@ -102,11 +107,10 @@ _cairo_pen_init (cairo_pen_t *pen,
void
_cairo_pen_fini (cairo_pen_t *pen)
{
if (pen->vertices != pen->vertices_embedded)
free (pen->vertices);
free (pen->vertices);
pen->vertices = NULL;
pen->vertices = pen->vertices_embedded;
pen->num_vertices = 0;
_cairo_pen_init_empty (pen);
}
cairo_status_t
@ -114,17 +118,13 @@ _cairo_pen_init_copy (cairo_pen_t *pen, cairo_pen_t *other)
{
*pen = *other;
pen->vertices = pen->vertices_embedded;
if (pen->num_vertices) {
if (pen->num_vertices > ARRAY_LENGTH (pen->vertices_embedded)) {
pen->vertices = _cairo_malloc_ab (pen->num_vertices,
sizeof (cairo_pen_vertex_t));
if (pen->vertices == NULL)
return _cairo_error (CAIRO_STATUS_NO_MEMORY);
}
pen->vertices = _cairo_malloc_ab (pen->num_vertices,
sizeof (cairo_pen_vertex_t));
if (pen->vertices == NULL)
return _cairo_error (CAIRO_STATUS_NO_MEMORY);
memcpy (pen->vertices, other->vertices,
pen->num_vertices * sizeof (cairo_pen_vertex_t));
memcpy (pen->vertices, other->vertices, pen->num_vertices * sizeof (cairo_pen_vertex_t));
}
return CAIRO_STATUS_SUCCESS;
@ -133,35 +133,18 @@ _cairo_pen_init_copy (cairo_pen_t *pen, cairo_pen_t *other)
cairo_status_t
_cairo_pen_add_points (cairo_pen_t *pen, cairo_point_t *point, int num_points)
{
cairo_pen_vertex_t *vertices;
cairo_status_t status;
int num_vertices;
int i;
num_vertices = pen->num_vertices + num_points;
if (num_vertices > ARRAY_LENGTH (pen->vertices_embedded) ||
pen->vertices != pen->vertices_embedded)
{
cairo_pen_vertex_t *vertices;
if (pen->vertices == pen->vertices_embedded) {
vertices = _cairo_malloc_ab (num_vertices,
sizeof (cairo_pen_vertex_t));
if (vertices == NULL)
return _cairo_error (CAIRO_STATUS_NO_MEMORY);
memcpy (vertices, pen->vertices,
pen->num_vertices * sizeof (cairo_pen_vertex_t));
} else {
vertices = _cairo_realloc_ab (pen->vertices,
num_vertices,
sizeof (cairo_pen_vertex_t));
if (vertices == NULL)
return _cairo_error (CAIRO_STATUS_NO_MEMORY);
}
pen->vertices = vertices;
}
vertices = _cairo_realloc_ab (pen->vertices,
num_vertices, sizeof (cairo_pen_vertex_t));
if (vertices == NULL)
return _cairo_error (CAIRO_STATUS_NO_MEMORY);
pen->vertices = vertices;
pen->num_vertices = num_vertices;
/* initialize new vertices */

Просмотреть файл

@ -197,9 +197,6 @@ write_png (cairo_surface_t *surface,
case CAIRO_FORMAT_A1:
depth = 1;
png_color_type = PNG_COLOR_TYPE_GRAY;
#ifndef WORDS_BIGENDIAN
png_set_packswap (png);
#endif
break;
default:
status = _cairo_error (CAIRO_STATUS_INVALID_FORMAT);
@ -277,7 +274,7 @@ stdio_write_func (png_structp png, png_bytep data, png_size_t size)
* Return value: %CAIRO_STATUS_SUCCESS if the PNG file was written
* successfully. Otherwise, %CAIRO_STATUS_NO_MEMORY if memory could not
* be allocated for the operation or
* %CAIRO_STATUS_SURFACE_TYPE_MISMATCH if the surface does not have
* CAIRO_STATUS_SURFACE_TYPE_MISMATCH if the surface does not have
* pixel contents, or %CAIRO_STATUS_WRITE_ERROR if an I/O error occurs
* while attempting to write the file.
**/
@ -344,7 +341,7 @@ stream_write_func (png_structp png, png_bytep data, png_size_t size)
* Return value: %CAIRO_STATUS_SUCCESS if the PNG file was written
* successfully. Otherwise, %CAIRO_STATUS_NO_MEMORY is returned if
* memory could not be allocated for the operation,
* %CAIRO_STATUS_SURFACE_TYPE_MISMATCH if the surface does not have
* CAIRO_STATUS_SURFACE_TYPE_MISMATCH if the surface does not have
* pixel contents.
**/
cairo_status_t
@ -354,12 +351,6 @@ cairo_surface_write_to_png_stream (cairo_surface_t *surface,
{
struct png_write_closure_t png_closure;
if (surface->status)
return surface->status;
if (surface->finished)
return _cairo_error (CAIRO_STATUS_SURFACE_FINISHED);
png_closure.write_func = write_func;
png_closure.closure = closure;
@ -507,37 +498,25 @@ read_png (png_rw_ptr read_func,
if (interlace != PNG_INTERLACE_NONE)
png_set_interlace_handling (png);
png_set_filler (png, 0xff, PNG_FILLER_AFTER);
/* recheck header after setting EXPAND options */
png_read_update_info (png, info);
png_get_IHDR (png, info,
&png_width, &png_height, &depth,
&color_type, &interlace, NULL, NULL);
if (depth != 8 || interlace != PNG_INTERLACE_NONE ||
! (color_type == PNG_COLOR_TYPE_RGB ||
color_type == PNG_COLOR_TYPE_RGB_ALPHA))
{
surface = _cairo_surface_create_in_error (_cairo_error (CAIRO_STATUS_READ_ERROR));
goto BAIL;
}
switch (color_type) {
default:
ASSERT_NOT_REACHED;
/* fall-through just in case ;-) */
case PNG_COLOR_TYPE_GRAY_ALPHA:
case PNG_COLOR_TYPE_RGB_ALPHA:
format = CAIRO_FORMAT_ARGB32;
png_set_read_user_transform_fn (png, premultiply_data);
break;
case PNG_COLOR_TYPE_GRAY:
case PNG_COLOR_TYPE_PALETTE:
case PNG_COLOR_TYPE_RGB:
format = CAIRO_FORMAT_RGB24;
png_set_read_user_transform_fn (png, convert_bytes_to_data);
png_set_filler (png, 0xff, PNG_FILLER_AFTER);
break;
}
png_read_update_info (png, info);
stride = cairo_format_stride_for_width (format, png_width);
if (stride < 0) {
surface = _cairo_surface_create_in_error (_cairo_error (CAIRO_STATUS_INVALID_STRIDE));
@ -618,9 +597,9 @@ stdio_read_func (png_structp png, png_bytep data, png_size_t size)
* surface can be checked for with cairo_surface_status(surface) which
* may return one of the following values:
*
* %CAIRO_STATUS_NO_MEMORY
* %CAIRO_STATUS_FILE_NOT_FOUND
* %CAIRO_STATUS_READ_ERROR
* CAIRO_STATUS_NO_MEMORY
* CAIRO_STATUS_FILE_NOT_FOUND
* CAIRO_STATUS_READ_ERROR
**/
cairo_surface_t *
cairo_image_surface_create_from_png (const char *filename)

Просмотреть файл

@ -48,8 +48,8 @@ _cairo_polygon_init (cairo_polygon_t *polygon)
polygon->num_edges = 0;
polygon->edges = polygon->edges_embedded;
polygon->edges_size = ARRAY_LENGTH (polygon->edges_embedded);
polygon->edges_size = 0;
polygon->edges = NULL;
polygon->has_current_point = FALSE;
}
@ -79,17 +79,26 @@ _cairo_polygon_grow (cairo_polygon_t *polygon)
{
cairo_edge_t *new_edges;
int old_size = polygon->edges_size;
int new_size = 2 * old_size;
int embedded_size = ARRAY_LENGTH (polygon->edges_embedded);
int new_size = 2 * MAX (old_size, 16);
/* we have a local buffer at polygon->edges_embedded. try to fulfill the request
* from there. */
if (old_size < embedded_size) {
polygon->edges = polygon->edges_embedded;
polygon->edges_size = embedded_size;
return CAIRO_STATUS_SUCCESS;
}
assert (polygon->num_edges <= polygon->edges_size);
if (polygon->edges == polygon->edges_embedded) {
new_edges = _cairo_malloc_ab (new_size, sizeof (cairo_edge_t));
if (new_edges != NULL)
if (new_edges)
memcpy (new_edges, polygon->edges, old_size * sizeof (cairo_edge_t));
} else {
new_edges = _cairo_realloc_ab (polygon->edges,
new_size, sizeof (cairo_edge_t));
new_size, sizeof (cairo_edge_t));
}
if (new_edges == NULL)

Просмотреть файл

@ -49,7 +49,6 @@ struct _cairo {
cairo_gstate_t *gstate;
cairo_gstate_t gstate_tail[1];
cairo_gstate_t *gstate_freelist;
cairo_path_fixed_t path[1];
};

Просмотреть файл

@ -69,12 +69,6 @@ typedef struct cairo_ps_surface {
void *image_extra;
cairo_bool_t use_string_datasource;
cairo_bool_t current_pattern_is_solid_color;
double current_color_red;
double current_color_green;
double current_color_blue;
double current_color_alpha;
int num_pages;
cairo_paginated_mode_t paginated_mode;

Просмотреть файл

@ -49,7 +49,6 @@
#include "cairo-paginated-private.h"
#include "cairo-meta-surface-private.h"
#include "cairo-output-stream-private.h"
#include "cairo-type3-glyph-surface-private.h"
#include <stdio.h>
#include <ctype.h>
@ -173,35 +172,24 @@ _cairo_ps_surface_emit_header (cairo_ps_surface_t *surface)
"/n { newpath } bind def\n"
"/W { clip } bind def\n"
"/W* { eoclip } bind def\n"
"/Tf { pop /cairo_font exch def } bind def\n"
"/BT { } bind def\n"
"/ET { } bind def\n"
"/pdfmark where { pop globaldict /?pdfmark /exec load put }\n"
" { globaldict begin /?pdfmark /pop load def /pdfmark\n"
" /cleartomark load def end } ifelse\n"
"/BDC { mark 3 1 roll /BDC pdfmark } bind def\n"
"/EMC { mark /EMC pdfmark } bind def\n"
"/cairo_store_point { /cairo_point_y exch def /cairo_point_x exch def } def\n"
"/Tj { show currentpoint cairo_store_point } bind def\n"
"/Tj { show } bind def\n"
"/TJ {\n"
" {\n"
" dup\n"
" type /stringtype eq\n"
" { show } { -0.001 mul 0 cairo_font_matrix dtransform rmoveto } ifelse\n"
" } forall\n"
" currentpoint cairo_store_point\n"
"} bind def\n"
"/cairo_selectfont { cairo_font_matrix aload pop pop pop 0 0 6 array astore\n"
" cairo_font exch selectfont cairo_point_x cairo_point_y moveto } bind def\n"
"/Tf { pop /cairo_font exch def /cairo_font_matrix where\n"
" { cairo_selectfont } if } bind def\n"
"/Td { matrix translate cairo_font_matrix matrix concatmatrix dup\n"
" /cairo_font_matrix exch def dup 4 get exch 5 get cairo_store_point\n"
" /cairo_font where { cairo_selectfont } if } bind def\n"
"/Tm { 2 copy 8 2 roll 6 array astore /cairo_font_matrix exch def\n"
" cairo_store_point /cairo_font where { cairo_selectfont } if } bind def\n"
"/Td { matrix translate cairo_font_matrix matrix concatmatrix aload\n"
" /cairo_font_matrix exch def 6 2 roll 0 0 6 array astore\n"
" cairo_font exch selectfont moveto } bind def\n"
"/Tm { 6 copy 6 array astore /cairo_font_matrix exch def 6 2 roll 0 0\n"
" 6 array astore cairo_font exch selectfont moveto } bind def\n"
"/g { setgray } bind def\n"
"/rg { setrgbcolor } bind def\n"
"/d1 { setcachedevice } bind def\n");
"/rg { setrgbcolor } bind def\n");
_cairo_output_stream_printf (surface->final_stream,
"%%%%EndProlog\n");
@ -381,49 +369,113 @@ _cairo_ps_surface_emit_truetype_font_subset (cairo_ps_surface_t *surface,
return CAIRO_STATUS_SUCCESS;
}
static cairo_status_t
_cairo_ps_emit_imagemask (cairo_image_surface_t *image,
cairo_output_stream_t *stream)
static cairo_int_status_t
_cairo_ps_surface_emit_bitmap_glyph_data (cairo_ps_surface_t *surface,
cairo_scaled_font_t *scaled_font,
unsigned long glyph_index,
cairo_box_t *bbox)
{
cairo_scaled_glyph_t *scaled_glyph;
cairo_status_t status;
cairo_image_surface_t *image;
unsigned char *row, *byte;
int rows, cols;
double x_advance, y_advance;
/* The only image type supported by Type 3 fonts are 1-bit image
* masks */
assert (image->format == CAIRO_FORMAT_A1);
status = _cairo_scaled_glyph_lookup (scaled_font,
glyph_index,
CAIRO_SCALED_GLYPH_INFO_METRICS|
CAIRO_SCALED_GLYPH_INFO_SURFACE,
&scaled_glyph);
if (status)
return status;
_cairo_output_stream_printf (stream,
*bbox = scaled_glyph->bbox;
x_advance = scaled_glyph->metrics.x_advance;
y_advance = scaled_glyph->metrics.y_advance;
cairo_matrix_transform_distance (&scaled_font->ctm, &x_advance, &y_advance);
image = scaled_glyph->surface;
if (image->format != CAIRO_FORMAT_A1) {
image = _cairo_image_surface_clone (image, CAIRO_FORMAT_A1);
if (cairo_surface_status (&image->base))
return cairo_surface_status (&image->base);
}
_cairo_output_stream_printf (surface->final_stream,
"%f 0 %f %f %f %f setcachedevice\n",
x_advance,
_cairo_fixed_to_double (scaled_glyph->bbox.p1.x),
_cairo_fixed_to_double (scaled_glyph->bbox.p2.y),
_cairo_fixed_to_double (scaled_glyph->bbox.p2.x),
_cairo_fixed_to_double (scaled_glyph->bbox.p1.y));
_cairo_output_stream_printf (surface->final_stream,
"<<\n"
" /ImageType 1\n"
" /Width %d\n"
" /Height %d\n"
" /ImageMatrix [%d 0 0 %d 0 %d]\n"
" /ImageMatrix [%f %f %f %f %f %f]\n"
" /Decode [1 0]\n"
" /BitsPerComponent 1\n",
image->width,
image->height,
image->width,
-image->height,
image->height);
image->base.device_transform.xx,
image->base.device_transform.yx,
image->base.device_transform.xy,
image->base.device_transform.yy,
image->base.device_transform.x0,
image->base.device_transform.y0);
_cairo_output_stream_printf (stream,
_cairo_output_stream_printf (surface->final_stream,
" /DataSource {<");
for (row = image->data, rows = image->height; rows; row += image->stride, rows--) {
for (byte = row, cols = (image->width + 7) / 8; cols; byte++, cols--) {
unsigned char output_byte = CAIRO_BITSWAP8_IF_LITTLE_ENDIAN (*byte);
_cairo_output_stream_printf (stream, "%02x ", output_byte);
_cairo_output_stream_printf (surface->final_stream, "%02x ", output_byte);
}
_cairo_output_stream_printf (stream, "\n ");
_cairo_output_stream_printf (surface->final_stream, "\n ");
}
_cairo_output_stream_printf (stream,
_cairo_output_stream_printf (surface->final_stream,
" >}\n");
_cairo_output_stream_printf (stream,
_cairo_output_stream_printf (surface->final_stream,
">>\n");
_cairo_output_stream_printf (stream,
_cairo_output_stream_printf (surface->final_stream,
"imagemask\n");
return _cairo_output_stream_get_status (stream);
if (image != scaled_glyph->surface)
cairo_surface_destroy (&image->base);
return CAIRO_STATUS_SUCCESS;
}
static cairo_status_t
_cairo_ps_surface_emit_glyph (cairo_ps_surface_t *surface,
cairo_scaled_font_t *scaled_font,
unsigned long scaled_font_glyph_index,
unsigned int subset_glyph_index,
cairo_box_t *bbox)
{
cairo_status_t status = CAIRO_STATUS_SUCCESS;
_cairo_output_stream_printf (surface->final_stream,
"\t\t{ %% %d\n", subset_glyph_index);
if (subset_glyph_index != 0) {
status = _cairo_ps_surface_emit_bitmap_glyph_data (surface,
scaled_font,
scaled_font_glyph_index,
bbox);
}
_cairo_output_stream_printf (surface->final_stream,
"\t\t}\n");
if (status)
status = _cairo_surface_set_error (&surface->base, status);
return status;
}
static cairo_status_t
@ -437,8 +489,6 @@ _cairo_ps_surface_emit_type3_font_subset (cairo_ps_surface_t *surface,
unsigned int i;
cairo_box_t font_bbox = {{0,0},{0,0}};
cairo_box_t bbox = {{0,0},{0,0}};
cairo_surface_t *type3_surface;
double width;
#if DEBUG_PS
_cairo_output_stream_printf (surface->final_stream,
@ -449,13 +499,13 @@ _cairo_ps_surface_emit_type3_font_subset (cairo_ps_surface_t *surface,
_cairo_output_stream_printf (surface->final_stream,
"8 dict begin\n"
"/FontType 3 def\n"
"/FontMatrix [1 0 0 1 0 0] def\n"
"/FontMatrix [%f %f %f %f 0 0] def\n"
"/Encoding 256 array def\n"
"0 1 255 { Encoding exch /.notdef put } for\n");
type3_surface = _cairo_type3_glyph_surface_create (font_subset->scaled_font,
NULL,
_cairo_ps_emit_imagemask);
"0 1 255 { Encoding exch /.notdef put } for\n",
matrix.xx,
matrix.yx,
-matrix.xy,
-matrix.yy);
for (i = 1; i < font_subset->num_glyphs; i++) {
if (font_subset->glyph_names != NULL) {
@ -472,25 +522,13 @@ _cairo_ps_surface_emit_type3_font_subset (cairo_ps_surface_t *surface,
"/Glyphs [\n");
for (i = 0; i < font_subset->num_glyphs; i++) {
_cairo_output_stream_printf (surface->final_stream,
" { %% %d\n", i);
if (i == 0) {
status = _cairo_type3_glyph_surface_emit_notdef_glyph (type3_surface,
surface->final_stream,
&bbox,
&width);
} else {
status = _cairo_type3_glyph_surface_emit_glyph (type3_surface,
surface->final_stream,
font_subset->glyphs[i],
&bbox,
&width);
}
status = _cairo_ps_surface_emit_glyph (surface,
font_subset->scaled_font,
font_subset->glyphs[i], i,
&bbox);
if (status)
return status;
_cairo_output_stream_printf (surface->final_stream,
" }\n");
if (i == 0) {
font_bbox.p1.x = bbox.p1.x;
font_bbox.p1.y = bbox.p1.y;
@ -507,7 +545,6 @@ _cairo_ps_surface_emit_type3_font_subset (cairo_ps_surface_t *surface,
font_bbox.p2.y = bbox.p2.y;
}
}
cairo_surface_destroy (type3_surface);
_cairo_output_stream_printf (surface->final_stream,
"] def\n"
@ -520,9 +557,9 @@ _cairo_ps_surface_emit_type3_font_subset (cairo_ps_surface_t *surface,
"end\n"
"/f-%d-%d exch definefont pop\n",
_cairo_fixed_to_double (font_bbox.p1.x),
- _cairo_fixed_to_double (font_bbox.p2.y),
_cairo_fixed_to_double (font_bbox.p1.y),
_cairo_fixed_to_double (font_bbox.p2.x),
- _cairo_fixed_to_double (font_bbox.p1.y),
_cairo_fixed_to_double (font_bbox.p2.y),
font_subset->font_id,
font_subset->subset_id);
@ -691,7 +728,6 @@ _cairo_ps_surface_create_for_stream_internal (cairo_output_stream_t *stream,
surface->force_fallbacks = FALSE;
surface->content = CAIRO_CONTENT_COLOR_ALPHA;
surface->use_string_datasource = FALSE;
surface->current_pattern_is_solid_color = FALSE;
_cairo_pdf_operators_init (&surface->pdf_operators,
surface->stream,
@ -711,11 +747,8 @@ _cairo_ps_surface_create_for_stream_internal (cairo_output_stream_t *stream,
width, height,
&cairo_ps_surface_paginated_backend);
status = surface->paginated_surface->status;
if (status == CAIRO_STATUS_SUCCESS) {
/* paginated keeps the only reference to surface now, drop ours */
cairo_surface_destroy (&surface->base);
if (status == CAIRO_STATUS_SUCCESS)
return surface->paginated_surface;
}
_cairo_scaled_font_subsets_destroy (surface->font_subsets);
CLEANUP_OUTPUT_STREAM:
@ -1291,30 +1324,19 @@ _cairo_ps_surface_start_page (void *abstract_surface)
return CAIRO_STATUS_SUCCESS;
}
static cairo_int_status_t
static void
_cairo_ps_surface_end_page (cairo_ps_surface_t *surface)
{
cairo_int_status_t status;
status = _cairo_pdf_operators_flush (&surface->pdf_operators);
if (status)
return status;
_cairo_output_stream_printf (surface->stream,
"Q\n");
return CAIRO_STATUS_SUCCESS;
}
static cairo_int_status_t
_cairo_ps_surface_show_page (void *abstract_surface)
{
cairo_ps_surface_t *surface = abstract_surface;
cairo_int_status_t status;
status = _cairo_ps_surface_end_page (surface);
if (status)
return status;
_cairo_ps_surface_end_page (surface);
_cairo_output_stream_printf (surface->stream, "showpage\n");
@ -1696,7 +1718,7 @@ _cairo_ps_surface_flatten_image_transparency (cairo_ps_surface_t *surface,
{
const cairo_color_t *background_color;
cairo_surface_t *opaque;
cairo_surface_pattern_t pattern;
cairo_pattern_union_t pattern;
cairo_status_t status;
if (surface->content == CAIRO_CONTENT_COLOR_ALPHA)
@ -1710,7 +1732,7 @@ _cairo_ps_surface_flatten_image_transparency (cairo_ps_surface_t *surface,
if (opaque->status)
return opaque->status;
_cairo_pattern_init_for_surface (&pattern, &image->base);
_cairo_pattern_init_for_surface (&pattern.surface, &image->base);
status = _cairo_surface_fill_rectangle (opaque,
CAIRO_OPERATOR_SOURCE,
@ -2030,8 +2052,6 @@ _cairo_ps_surface_emit_meta_surface (cairo_ps_surface_t *surface,
old_clip = _cairo_surface_get_clip (&surface->base);
surface->width = meta_extents.width;
surface->height = meta_extents.height;
surface->current_pattern_is_solid_color = FALSE;
_cairo_pdf_operators_reset (&surface->pdf_operators);
cairo_matrix_init (&surface->cairo_to_ps, 1, 0, 0, -1, 0, surface->height);
_cairo_pdf_operators_set_cairo_to_pdf_matrix (&surface->pdf_operators,
&surface->cairo_to_ps);
@ -2055,17 +2075,11 @@ _cairo_ps_surface_emit_meta_surface (cairo_ps_surface_t *surface,
if (status)
return status;
status = _cairo_pdf_operators_flush (&surface->pdf_operators);
if (status)
return status;
_cairo_output_stream_printf (surface->stream,
" Q\n");
surface->content = old_content;
surface->width = old_width;
surface->height = old_height;
surface->current_pattern_is_solid_color = FALSE;
_cairo_pdf_operators_reset (&surface->pdf_operators);
surface->cairo_to_ps = old_cairo_to_ps;
status = _cairo_surface_set_clip (&surface->base, old_clip);
if (status)
@ -2604,19 +2618,6 @@ _cairo_ps_surface_emit_linear_pattern (cairo_ps_surface_t *surface,
if (pattern->base.n_stops == 0)
return CAIRO_INT_STATUS_NOTHING_TO_DO;
if (pattern->base.n_stops == 1) {
cairo_solid_pattern_t solid;
_cairo_pattern_init_solid (&solid,
&pattern->base.stops[0].color,
CAIRO_CONTENT_COLOR_ALPHA);
_cairo_ps_surface_emit_solid_pattern (surface,
&solid);
_cairo_pattern_fini (&solid.base);
return CAIRO_STATUS_SUCCESS;
}
extend = cairo_pattern_get_extend (&pattern->base.base);
pat_to_ps = pattern->base.base.matrix;
@ -2744,19 +2745,6 @@ _cairo_ps_surface_emit_radial_pattern (cairo_ps_surface_t *surface,
if (pattern->base.n_stops == 0)
return CAIRO_INT_STATUS_NOTHING_TO_DO;
if (pattern->base.n_stops == 1) {
cairo_solid_pattern_t solid;
_cairo_pattern_init_solid (&solid,
&pattern->base.stops[0].color,
CAIRO_CONTENT_COLOR_ALPHA);
_cairo_ps_surface_emit_solid_pattern (surface,
&solid);
_cairo_pattern_fini (&solid.base);
return CAIRO_STATUS_SUCCESS;
}
extend = cairo_pattern_get_extend (&pattern->base.base);
pat_to_ps = pattern->base.base.matrix;
@ -2813,41 +2801,13 @@ _cairo_ps_surface_emit_pattern (cairo_ps_surface_t *surface,
cairo_pattern_t *pattern,
cairo_operator_t op)
{
/* FIXME: We should keep track of what pattern is currently set in
* the postscript file and only emit code if we're setting a
* different pattern. */
cairo_status_t status;
if (pattern->type == CAIRO_PATTERN_TYPE_SOLID) {
cairo_solid_pattern_t *solid = (cairo_solid_pattern_t *) pattern;
if (surface->current_pattern_is_solid_color == FALSE ||
surface->current_color_red != solid->color.red ||
surface->current_color_green != solid->color.green ||
surface->current_color_blue != solid->color.blue ||
surface->current_color_alpha != solid->color.alpha)
{
status = _cairo_pdf_operators_flush (&surface->pdf_operators);
if (status)
return status;
_cairo_ps_surface_emit_solid_pattern (surface, (cairo_solid_pattern_t *) pattern);
surface->current_pattern_is_solid_color = TRUE;
surface->current_color_red = solid->color.red;
surface->current_color_green = solid->color.green;
surface->current_color_blue = solid->color.blue;
surface->current_color_alpha = solid->color.alpha;
}
return CAIRO_STATUS_SUCCESS;
}
surface->current_pattern_is_solid_color = FALSE;
status = _cairo_pdf_operators_flush (&surface->pdf_operators);
if (status)
return status;
switch (pattern->type) {
case CAIRO_PATTERN_TYPE_SOLID:
_cairo_ps_surface_emit_solid_pattern (surface, (cairo_solid_pattern_t *) pattern);
break;
@ -2886,7 +2846,6 @@ _cairo_ps_surface_intersect_clip_path (void *abstract_surface,
{
cairo_ps_surface_t *surface = abstract_surface;
cairo_output_stream_t *stream = surface->stream;
cairo_status_t status;
if (surface->paginated_mode == CAIRO_PAGINATED_MODE_ANALYZE)
return CAIRO_STATUS_SUCCESS;
@ -2897,14 +2856,7 @@ _cairo_ps_surface_intersect_clip_path (void *abstract_surface,
#endif
if (path == NULL) {
status = _cairo_pdf_operators_flush (&surface->pdf_operators);
if (status)
return status;
_cairo_output_stream_printf (stream, "Q q\n");
surface->current_pattern_is_solid_color = FALSE;
_cairo_pdf_operators_reset (&surface->pdf_operators);
return CAIRO_STATUS_SUCCESS;
}
@ -2967,10 +2919,6 @@ _cairo_ps_surface_paint (void *abstract_surface,
if (status)
return status;
status = _cairo_pdf_operators_flush (&surface->pdf_operators);
if (status)
return status;
if (source->type == CAIRO_PATTERN_TYPE_SURFACE &&
(source->extend == CAIRO_EXTEND_NONE ||
source->extend == CAIRO_EXTEND_PAD))
@ -3063,10 +3011,6 @@ _cairo_ps_surface_fill (void *abstract_surface,
(source->extend == CAIRO_EXTEND_NONE ||
source->extend == CAIRO_EXTEND_PAD))
{
status = _cairo_pdf_operators_flush (&surface->pdf_operators);
if (status)
return status;
_cairo_output_stream_printf (surface->stream, "q\n");
status = _cairo_pdf_operators_clip (&surface->pdf_operators,
@ -3082,7 +3026,6 @@ _cairo_ps_surface_fill (void *abstract_surface,
return status;
_cairo_output_stream_printf (surface->stream, "Q\n");
_cairo_pdf_operators_reset (&surface->pdf_operators);
} else {
status = _cairo_ps_surface_emit_pattern (surface, source, op);
if (status == CAIRO_INT_STATUS_NOTHING_TO_DO)
@ -3105,8 +3048,7 @@ _cairo_ps_surface_show_glyphs (void *abstract_surface,
cairo_pattern_t *source,
cairo_glyph_t *glyphs,
int num_glyphs,
cairo_scaled_font_t *scaled_font,
int *remaining_glyphs)
cairo_scaled_font_t *scaled_font)
{
cairo_ps_surface_t *surface = abstract_surface;
cairo_status_t status;
@ -3131,12 +3073,10 @@ _cairo_ps_surface_show_glyphs (void *abstract_surface,
if (status)
return status;
return _cairo_pdf_operators_show_text_glyphs (&surface->pdf_operators,
NULL, 0,
glyphs, num_glyphs,
NULL, 0,
FALSE,
scaled_font);
return _cairo_pdf_operators_show_glyphs (&surface->pdf_operators,
glyphs,
num_glyphs,
scaled_font);
}
static void
@ -3210,8 +3150,6 @@ _cairo_ps_surface_set_bounding_box (void *abstract_surface,
if (y2 > surface->bbox_y2)
surface->bbox_y2 = y2;
}
surface->current_pattern_is_solid_color = FALSE;
_cairo_pdf_operators_reset (&surface->pdf_operators);
return _cairo_output_stream_get_status (surface->stream);
}

Просмотреть файл

@ -37,7 +37,7 @@
#ifndef CAIRO_PS_H
#define CAIRO_PS_H
#include "cairo.h"
#include <cairo.h>
#if CAIRO_HAS_PS_SURFACE

Просмотреть файл

@ -127,9 +127,9 @@ struct _cairo_quartz_font_face {
CGFontRef cgFont;
};
/*
* font face backend
*/
/**
** font face backend
**/
static void
_cairo_quartz_font_face_destroy (void *abstract_face)
@ -165,7 +165,7 @@ _cairo_quartz_font_face_scaled_font_create (void *abstract_face,
status = _cairo_scaled_font_init (&font->base,
&font_face->base, font_matrix, ctm, options,
&_cairo_quartz_scaled_font_backend);
&cairo_quartz_scaled_font_backend);
if (status)
goto FINISH;
@ -188,7 +188,6 @@ _cairo_quartz_font_face_scaled_font_create (void *abstract_face,
quartz_CGFontMetrics *m;
m = CGFontGetHMetricsPtr (font_face->cgFont);
/* On OX 10.4, GetHMetricsPtr sometimes returns NULL for unknown reasons */
if (!m) {
status = _cairo_error(CAIRO_STATUS_NULL_POINTER);
goto FINISH;
@ -261,9 +260,9 @@ cairo_quartz_font_face_create_for_cgfont (CGFontRef font)
return &font_face->base;
}
/*
* scaled font backend
*/
/**
** scaled font backend
**/
static cairo_quartz_font_face_t *
_cairo_quartz_scaled_to_face (void *abstract_font)
@ -741,7 +740,7 @@ _cairo_quartz_ucs4_to_index (void *abstract_font,
return glyph;
}
const cairo_scaled_font_backend_t _cairo_quartz_scaled_font_backend = {
const cairo_scaled_font_backend_t cairo_quartz_scaled_font_backend = {
CAIRO_FONT_TYPE_QUARTZ,
_cairo_quartz_font_create_toy,
_cairo_quartz_font_fini,

Просмотреть файл

@ -43,7 +43,6 @@
#include "cairo-quartz-private.h"
#define SURFACE_ERROR_NO_MEMORY (_cairo_surface_create_in_error(_cairo_error(CAIRO_STATUS_NO_MEMORY)))
#define SURFACE_ERROR_TYPE_MISMATCH (_cairo_surface_create_in_error(_cairo_error(CAIRO_STATUS_SURFACE_TYPE_MISMATCH)))
#define SURFACE_ERROR_INVALID_FORMAT (_cairo_surface_create_in_error(_cairo_error(CAIRO_STATUS_INVALID_FORMAT)))
CGImageRef
@ -301,7 +300,7 @@ cairo_quartz_image_surface_create (cairo_surface_t *surface)
unsigned char *data;
if (cairo_surface_get_type(surface) != CAIRO_SURFACE_TYPE_IMAGE)
return SURFACE_ERROR_TYPE_MISMATCH;
return SURFACE_ERROR_NO_MEMORY;
image_surface = (cairo_image_surface_t*) surface;
width = image_surface->width;
@ -338,7 +337,7 @@ cairo_quartz_image_surface_create (cairo_surface_t *surface)
TRUE,
NULL,
DataProviderReleaseCallback,
image_surface);
surface);
if (!image) {
free (qisurf);

Просмотреть файл

@ -36,7 +36,7 @@
#ifndef CAIRO_QUARTZ_IMAGE_H
#define CAIRO_QUARTZ_IMAGE_H
#include "cairo.h"
#include <cairo.h>
#if CAIRO_HAS_QUARTZ_IMAGE_SURFACE

Просмотреть файл

@ -41,7 +41,7 @@
#include "cairoint.h"
#ifdef CAIRO_HAS_QUARTZ_SURFACE
#include "cairo-quartz.h"
#include <cairo-quartz.h>
typedef struct cairo_quartz_surface {
cairo_surface_t base;

Просмотреть файл

@ -695,13 +695,6 @@ CreateRepeatingGradientFunction (cairo_quartz_surface_t *surface,
/* Obtain a CGImageRef from a #cairo_surface_t * */
static void
DataProviderReleaseCallback (void *info, const void *data, size_t size)
{
cairo_surface_t *surface = (cairo_surface_t *) info;
cairo_surface_destroy (surface);
}
static cairo_status_t
_cairo_surface_to_cgimage (cairo_surface_t *target,
cairo_surface_t *source,
@ -744,22 +737,17 @@ _cairo_surface_to_cgimage (cairo_surface_t *target,
if (isurf->width == 0 || isurf->height == 0) {
*image_out = NULL;
} else {
cairo_image_surface_t *isurf_snap = NULL;
isurf_snap = _cairo_surface_snapshot (isurf);
if (isurf_snap == NULL)
return CAIRO_STATUS_NO_MEMORY;
image = _cairo_quartz_create_cgimage (isurf_snap->format,
isurf_snap->width,
isurf_snap->height,
isurf_snap->stride,
isurf_snap->data,
image = _cairo_quartz_create_cgimage (isurf->format,
isurf->width,
isurf->height,
isurf->stride,
isurf->data,
TRUE,
NULL,
DataProviderReleaseCallback,
isurf_snap);
NULL, NULL, NULL);
*image_out = image;
/* Create a copy to ensure that the CGImageRef doesn't depend on the image surface's backing store */
*image_out = CGImageCreateCopy (image);
CGImageRelease (image);
}
if ((cairo_surface_t*) isurf != source)
@ -1887,8 +1875,7 @@ _cairo_quartz_surface_show_glyphs (void *abstract_surface,
cairo_pattern_t *source,
cairo_glyph_t *glyphs,
int num_glyphs,
cairo_scaled_font_t *scaled_font,
int *remaining_glyphs)
cairo_scaled_font_t *scaled_font)
{
CGAffineTransform textTransform, ctm;
#define STATIC_BUF_SIZE 64
@ -2167,7 +2154,7 @@ _cairo_quartz_surface_mask_with_generic (cairo_quartz_surface_t *surface,
cairo_surface_t *gradient_surf = NULL;
cairo_t *gradient_surf_cr = NULL;
cairo_surface_pattern_t surface_pattern;
cairo_pattern_union_t surface_pattern;
cairo_int_status_t status;
/* Render the gradient to a surface */
@ -2184,9 +2171,9 @@ _cairo_quartz_surface_mask_with_generic (cairo_quartz_surface_t *surface,
if (status)
goto BAIL;
_cairo_pattern_init_for_surface (&surface_pattern, gradient_surf);
_cairo_pattern_init_for_surface (&surface_pattern.surface, gradient_surf);
status = _cairo_quartz_surface_mask_with_surface (surface, op, source, &surface_pattern);
status = _cairo_quartz_surface_mask_with_surface (surface, op, source, &surface_pattern.surface);
_cairo_pattern_fini (&surface_pattern.base);

Просмотреть файл

@ -36,7 +36,7 @@
#ifndef CAIRO_QUARTZ_H
#define CAIRO_QUARTZ_H
#include "cairo.h"
#include <cairo.h>
#if CAIRO_HAS_QUARTZ_SURFACE

Просмотреть файл

@ -39,38 +39,6 @@
#include "cairoint.h"
cairo_private void
_cairo_box_from_doubles (cairo_box_t *box,
double *x1, double *y1,
double *x2, double *y2)
{
box->p1.x = _cairo_fixed_from_double (*x1);
box->p1.y = _cairo_fixed_from_double (*y1);
box->p2.x = _cairo_fixed_from_double (*x2);
box->p2.y = _cairo_fixed_from_double (*y2);
}
cairo_private void
_cairo_box_to_doubles (const cairo_box_t *box,
double *x1, double *y1,
double *x2, double *y2)
{
*x1 = _cairo_fixed_to_double (box->p1.x);
*y1 = _cairo_fixed_to_double (box->p1.y);
*x2 = _cairo_fixed_to_double (box->p2.x);
*y2 = _cairo_fixed_to_double (box->p2.y);
}
void
_cairo_box_from_rectangle (cairo_box_t *box,
const cairo_rectangle_int_t *rect)
{
box->p1.x = _cairo_fixed_from_int (rect->x);
box->p1.y = _cairo_fixed_from_int (rect->y);
box->p2.x = _cairo_fixed_from_int (rect->x + rect->width);
box->p2.y = _cairo_fixed_from_int (rect->y + rect->height);
}
/* XXX We currently have a confusing mix of boxes and rectangles as
* exemplified by this function. A #cairo_box_t is a rectangular area
* represented by the coordinates of the upper left and lower right
@ -86,8 +54,7 @@ _cairo_box_from_rectangle (cairo_box_t *box,
*/
void
_cairo_box_round_to_rectangle (const cairo_box_t *box,
cairo_rectangle_int_t *rectangle)
_cairo_box_round_to_rectangle (cairo_box_t *box, cairo_rectangle_int_t *rectangle)
{
rectangle->x = _cairo_fixed_integer_floor (box->p1.x);
rectangle->y = _cairo_fixed_integer_floor (box->p1.y);

Просмотреть файл

@ -44,7 +44,7 @@
/* #cairo_region_t is defined in cairoint.h */
struct _cairo_region {
pixman_region32_t rgn;
pixman_region16_t rgn;
};
cairo_private void

Просмотреть файл

@ -40,14 +40,14 @@
void
_cairo_region_init (cairo_region_t *region)
{
pixman_region32_init (&region->rgn);
pixman_region_init (&region->rgn);
}
void
_cairo_region_init_rect (cairo_region_t *region,
cairo_rectangle_int_t *rect)
{
pixman_region32_init_rect (&region->rgn,
pixman_region_init_rect (&region->rgn,
rect->x, rect->y,
rect->width, rect->height);
}
@ -57,13 +57,13 @@ _cairo_region_init_boxes (cairo_region_t *region,
cairo_box_int_t *boxes,
int count)
{
pixman_box32_t stack_pboxes[CAIRO_STACK_ARRAY_LENGTH (pixman_box32_t)];
pixman_box32_t *pboxes = stack_pboxes;
pixman_box16_t stack_pboxes[CAIRO_STACK_ARRAY_LENGTH (pixman_box16_t)];
pixman_box16_t *pboxes = stack_pboxes;
cairo_int_status_t status = CAIRO_STATUS_SUCCESS;
int i;
if (count > ARRAY_LENGTH(stack_pboxes)) {
pboxes = _cairo_malloc_ab (count, sizeof(pixman_box32_t));
pboxes = _cairo_malloc_ab (count, sizeof(pixman_box16_t));
if (pboxes == NULL)
return _cairo_error (CAIRO_STATUS_NO_MEMORY);
}
@ -75,7 +75,7 @@ _cairo_region_init_boxes (cairo_region_t *region,
pboxes[i].y2 = boxes[i].p2.y;
}
if (!pixman_region32_init_rects (&region->rgn, pboxes, count))
if (!pixman_region_init_rects (&region->rgn, pboxes, count))
status = _cairo_error (CAIRO_STATUS_NO_MEMORY);
if (pboxes != stack_pboxes)
@ -87,13 +87,13 @@ _cairo_region_init_boxes (cairo_region_t *region,
void
_cairo_region_fini (cairo_region_t *region)
{
pixman_region32_fini (&region->rgn);
pixman_region_fini (&region->rgn);
}
cairo_int_status_t
_cairo_region_copy (cairo_region_t *dst, cairo_region_t *src)
{
if (!pixman_region32_copy (&dst->rgn, &src->rgn))
if (!pixman_region_copy (&dst->rgn, &src->rgn))
return _cairo_error (CAIRO_STATUS_NO_MEMORY);
return CAIRO_STATUS_SUCCESS;
@ -102,18 +102,18 @@ _cairo_region_copy (cairo_region_t *dst, cairo_region_t *src)
int
_cairo_region_num_boxes (cairo_region_t *region)
{
return pixman_region32_n_rects (&region->rgn);
return pixman_region_n_rects (&region->rgn);
}
cairo_int_status_t
_cairo_region_get_boxes (cairo_region_t *region, int *num_boxes, cairo_box_int_t **boxes)
{
int nboxes;
pixman_box32_t *pboxes;
pixman_box16_t *pboxes;
cairo_box_int_t *cboxes;
int i;
pboxes = pixman_region32_rectangles (&region->rgn, &nboxes);
pboxes = pixman_region_rectangles (&region->rgn, &nboxes);
if (nboxes == 0) {
*num_boxes = 0;
@ -154,7 +154,7 @@ _cairo_region_boxes_fini (cairo_region_t *region, cairo_box_int_t *boxes)
void
_cairo_region_get_extents (cairo_region_t *region, cairo_rectangle_int_t *extents)
{
pixman_box32_t *pextents = pixman_region32_extents (&region->rgn);
pixman_box16_t *pextents = pixman_region_extents (&region->rgn);
extents->x = pextents->x1;
extents->y = pextents->y1;
@ -165,7 +165,7 @@ _cairo_region_get_extents (cairo_region_t *region, cairo_rectangle_int_t *extent
cairo_int_status_t
_cairo_region_subtract (cairo_region_t *dst, cairo_region_t *a, cairo_region_t *b)
{
if (!pixman_region32_subtract (&dst->rgn, &a->rgn, &b->rgn))
if (!pixman_region_subtract (&dst->rgn, &a->rgn, &b->rgn))
return _cairo_error (CAIRO_STATUS_NO_MEMORY);
return CAIRO_STATUS_SUCCESS;
@ -174,7 +174,7 @@ _cairo_region_subtract (cairo_region_t *dst, cairo_region_t *a, cairo_region_t *
cairo_int_status_t
_cairo_region_intersect (cairo_region_t *dst, cairo_region_t *a, cairo_region_t *b)
{
if (!pixman_region32_intersect (&dst->rgn, &a->rgn, &b->rgn))
if (!pixman_region_intersect (&dst->rgn, &a->rgn, &b->rgn))
return _cairo_error (CAIRO_STATUS_NO_MEMORY);
return CAIRO_STATUS_SUCCESS;
@ -185,7 +185,7 @@ _cairo_region_union_rect (cairo_region_t *dst,
cairo_region_t *src,
cairo_rectangle_int_t *rect)
{
if (!pixman_region32_union_rect (&dst->rgn, &src->rgn,
if (!pixman_region_union_rect (&dst->rgn, &src->rgn,
rect->x, rect->y,
rect->width, rect->height))
return _cairo_error (CAIRO_STATUS_NO_MEMORY);
@ -196,25 +196,25 @@ _cairo_region_union_rect (cairo_region_t *dst,
cairo_bool_t
_cairo_region_not_empty (cairo_region_t *region)
{
return (cairo_bool_t) pixman_region32_not_empty (&region->rgn);
return (cairo_bool_t) pixman_region_not_empty (&region->rgn);
}
void
_cairo_region_translate (cairo_region_t *region,
int x, int y)
{
pixman_region32_translate (&region->rgn, x, y);
pixman_region_translate (&region->rgn, x, y);
}
pixman_region_overlap_t
_cairo_region_contains_rectangle (cairo_region_t *region, cairo_rectangle_int_t *rect)
{
pixman_box32_t pbox;
pixman_box16_t pbox;
pbox.x1 = rect->x;
pbox.y1 = rect->y;
pbox.x2 = rect->x + rect->width;
pbox.y2 = rect->y + rect->height;
return pixman_region32_contains_rectangle (&region->rgn, &pbox);
return pixman_region_contains_rectangle (&region->rgn, &pbox);
}

Просмотреть файл

@ -89,14 +89,9 @@ struct _cairo_scaled_font {
cairo_matrix_t ctm; /* user space => device space */
cairo_font_options_t options;
cairo_bool_t placeholder; /* protected by fontmap mutex */
cairo_bool_t finished;
/* "live" scaled_font members */
cairo_matrix_t scale; /* font space => device space */
cairo_matrix_t scale_inverse; /* device space => font space */
double max_scale; /* maximum x/y expansion of scale */
cairo_font_extents_t extents; /* user space */
/* The mutex protects modification to all subsequent fields. */

Просмотреть файл

@ -46,9 +46,6 @@ typedef struct _cairo_scaled_font_subsets_glyph {
cairo_bool_t is_scaled;
cairo_bool_t is_composite;
double x_advance;
double y_advance;
cairo_bool_t utf8_is_mapped;
uint32_t unicode;
} cairo_scaled_font_subsets_glyph_t;
/**
@ -178,25 +175,17 @@ _cairo_scaled_font_subsets_destroy (cairo_scaled_font_subsets_t *font_subsets);
* @is_scaled: If true, the mapped glyph is from a bitmap font, and separate font
* subset is created for each font scale used. If false, the outline of the mapped glyph
* is available. One font subset for each font face is created.
* @x_advance, @y_advance: When @is_scaled is true, @x_advance and @y_advance contain
* the x and y advance for the mapped glyph in device space.
* When @is_scaled is false, @x_advance and @y_advance contain the x and y advance for
* the the mapped glyph from an unhinted 1 point font.
* @utf8_is_mapped: If true the utf8 string provided to _cairo_scaled_font_subsets_map_glyph()
* is (or already was) the utf8 string mapped to this glyph. If false the glyph is already
* mapped to a different utf8 string.
* @unicode: the unicode character mapped to this glyph by the font backend.
* @x_advance: When @is_scaled is true, @x_advance contains the x_advance for the mapped glyph in device space.
* When @is_scaled is false, @x_advance contains the x_advance for the the mapped glyph from an unhinted 1 point font.
*
* Return value: %CAIRO_STATUS_SUCCESS if successful, or a non-zero
* value indicating an error. Possible errors include
* %CAIRO_STATUS_NO_MEMORY.
* CAIRO_STATUS_NO_MEMORY.
**/
cairo_private cairo_status_t
_cairo_scaled_font_subsets_map_glyph (cairo_scaled_font_subsets_t *font_subsets,
cairo_scaled_font_t *scaled_font,
unsigned long scaled_font_glyph_index,
const char * utf8,
int utf8_len,
cairo_scaled_font_subsets_glyph_t *subset_glyph_ret);
typedef cairo_status_t
@ -231,7 +220,7 @@ typedef cairo_status_t
*
* Return value: %CAIRO_STATUS_SUCCESS if successful, or a non-zero
* value indicating an error. Possible errors include
* %CAIRO_STATUS_NO_MEMORY.
* CAIRO_STATUS_NO_MEMORY.
**/
cairo_private cairo_status_t
_cairo_scaled_font_subsets_foreach_scaled (cairo_scaled_font_subsets_t *font_subsets,
@ -266,7 +255,7 @@ _cairo_scaled_font_subsets_foreach_scaled (cairo_scaled_font_subsets_t *fon
*
* Return value: %CAIRO_STATUS_SUCCESS if successful, or a non-zero
* value indicating an error. Possible errors include
* %CAIRO_STATUS_NO_MEMORY.
* CAIRO_STATUS_NO_MEMORY.
**/
cairo_private cairo_status_t
_cairo_scaled_font_subsets_foreach_unscaled (cairo_scaled_font_subsets_t *font_subsets,
@ -281,7 +270,7 @@ _cairo_scaled_font_subsets_foreach_unscaled (cairo_scaled_font_subsets_t
* in @font_subsets. The array as store in font_subsets->glyph_names.
*
* Return value: %CAIRO_STATUS_SUCCESS if successful,
* %CAIRO_INT_STATUS_UNSUPPORTED if the font backend does not support
* CAIRO_INT_STATUS_UNSUPPORTED if the font backend does not support
* mapping the glyph indices to unicode characters. Possible errors
* include %CAIRO_STATUS_NO_MEMORY.
**/
@ -309,7 +298,7 @@ typedef struct _cairo_cff_subset {
* data.
*
* Return value: %CAIRO_STATUS_SUCCESS if successful,
* %CAIRO_INT_STATUS_UNSUPPORTED if the font can't be subset as a
* 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.
**/
@ -340,7 +329,7 @@ _cairo_cff_subset_fini (cairo_cff_subset_t *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
* 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.
**/
@ -383,7 +372,7 @@ typedef struct _cairo_truetype_subset {
* data.
*
* Return value: %CAIRO_STATUS_SUCCESS if successful,
* %CAIRO_INT_STATUS_UNSUPPORTED if the font can't be subset as a
* CAIRO_INT_STATUS_UNSUPPORTED if the font can't be subset as a
* truetype file, or an non-zero value indicating an error. Possible
* errors include %CAIRO_STATUS_NO_MEMORY.
**/
@ -427,7 +416,7 @@ typedef struct _cairo_type1_subset {
* with information about the subset and the type1 data.
*
* Return value: %CAIRO_STATUS_SUCCESS if successful,
* %CAIRO_INT_STATUS_UNSUPPORTED if the font can't be subset as a type1
* 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.
**/
@ -469,7 +458,7 @@ _cairo_type1_scaled_font_is_type1 (cairo_scaled_font_t *scaled_font);
* 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
* 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.
**/
@ -490,7 +479,7 @@ _cairo_type1_fallback_init_binary (cairo_type1_subset_t *type_subset,
* 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
* 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.
**/
@ -528,7 +517,7 @@ typedef struct _cairo_type2_charstrings {
* with information about the subset.
*
* Return value: %CAIRO_STATUS_SUCCESS if successful,
* %CAIRO_INT_STATUS_UNSUPPORTED if the font can't be subset as a type2
* CAIRO_INT_STATUS_UNSUPPORTED if the font can't be subset as a type2
* charstrings, or an non-zero value indicating an error. Possible errors
* include %CAIRO_STATUS_NO_MEMORY.
**/
@ -557,33 +546,11 @@ _cairo_type2_charstrings_fini (cairo_type2_charstrings_t *charstrings);
* fontsubset->to_unicode.
*
* Return value: %CAIRO_STATUS_SUCCESS if successful,
* %CAIRO_INT_STATUS_UNSUPPORTED if the unicode encoding of
* CAIRO_INT_STATUS_UNSUPPORTED if the unicode encoding of
* the glyphs is not available. Possible errors include
* %CAIRO_STATUS_NO_MEMORY.
* CAIRO_STATUS_NO_MEMORY.
**/
cairo_private cairo_int_status_t
_cairo_truetype_create_glyph_to_unicode_map (cairo_scaled_font_subset_t *font_subset);
/**
* _cairo_truetype_index_to_ucs4:
* @scaled_font: the #cairo_scaled_font_t
* @index: the glyph index
* @ucs4: return value for the unicode value of the glyph
*
* If possible (depending on the format of the underlying
* #cairo_scaled_font_t and the font backend in use) assign
* the unicode character of the glyph to @ucs4.
*
* If mapping glyph indices to unicode is supported but the unicode
* value of the specified glyph is not available, @ucs4 is set to -1.
*
* Return value: %CAIRO_STATUS_SUCCESS if successful,
* %CAIRO_INT_STATUS_UNSUPPORTED if mapping glyph indices to unicode
* is not supported. Possible errors include %CAIRO_STATUS_NO_MEMORY.
**/
cairo_private cairo_int_status_t
_cairo_truetype_index_to_ucs4 (cairo_scaled_font_t *scaled_font,
unsigned long index,
uint32_t *ucs4);
#endif /* CAIRO_SCALED_FONT_SUBSETS_PRIVATE_H */

Просмотреть файл

@ -43,7 +43,6 @@
#define _BSD_SOURCE /* for snprintf(), strdup() */
#include "cairoint.h"
#include "cairo-scaled-font-subsets-private.h"
#include "cairo-user-font-private.h"
#define MAX_GLYPHS_PER_SIMPLE_FONT 256
#define MAX_GLYPHS_PER_COMPOSITE_FONT 65536
@ -54,6 +53,18 @@ typedef enum {
CAIRO_SUBSETS_COMPOSITE
} cairo_subsets_type_t;
struct _cairo_scaled_font_subsets {
cairo_subsets_type_t type;
int max_glyphs_per_unscaled_subset_used;
cairo_hash_table_t *unscaled_sub_fonts;
int max_glyphs_per_scaled_subset_used;
cairo_hash_table_t *scaled_sub_fonts;
int num_sub_fonts;
};
typedef struct _cairo_sub_font {
cairo_hash_entry_t base;
@ -68,42 +79,18 @@ typedef struct _cairo_sub_font {
int max_glyphs_per_subset;
cairo_hash_table_t *sub_font_glyphs;
struct _cairo_sub_font *next;
} cairo_sub_font_t;
struct _cairo_scaled_font_subsets {
cairo_subsets_type_t type;
int max_glyphs_per_unscaled_subset_used;
cairo_hash_table_t *unscaled_sub_fonts;
cairo_sub_font_t *unscaled_sub_fonts_list;
cairo_sub_font_t *unscaled_sub_fonts_list_end;
int max_glyphs_per_scaled_subset_used;
cairo_hash_table_t *scaled_sub_fonts;
cairo_sub_font_t *scaled_sub_fonts_list;
cairo_sub_font_t *scaled_sub_fonts_list_end;
int num_sub_fonts;
};
typedef struct _cairo_sub_font_glyph {
cairo_hash_entry_t base;
unsigned int subset_id;
unsigned int subset_glyph_index;
double x_advance;
double y_advance;
cairo_bool_t is_mapped;
uint32_t unicode;
char *utf8;
int utf8_len;
} cairo_sub_font_glyph_t;
typedef struct _cairo_sub_font_collection {
unsigned long *glyphs; /* scaled_font_glyph_index */
char **utf8;
unsigned int glyphs_size;
unsigned int max_glyph;
unsigned int num_glyphs;
@ -123,8 +110,6 @@ typedef struct _cairo_string_entry {
static cairo_status_t
_cairo_sub_font_map_glyph (cairo_sub_font_t *sub_font,
unsigned long scaled_font_glyph_index,
const char * utf8,
int utf8_len,
cairo_scaled_font_subsets_glyph_t *subset_glyph);
static void
@ -147,8 +132,7 @@ static cairo_sub_font_glyph_t *
_cairo_sub_font_glyph_create (unsigned long scaled_font_glyph_index,
unsigned int subset_id,
unsigned int subset_glyph_index,
double x_advance,
double y_advance)
double x_advance)
{
cairo_sub_font_glyph_t *sub_font_glyph;
@ -162,11 +146,6 @@ _cairo_sub_font_glyph_create (unsigned long scaled_font_glyph_index,
sub_font_glyph->subset_id = subset_id;
sub_font_glyph->subset_glyph_index = subset_glyph_index;
sub_font_glyph->x_advance = x_advance;
sub_font_glyph->y_advance = y_advance;
sub_font_glyph->is_mapped = FALSE;
sub_font_glyph->unicode = -1;
sub_font_glyph->utf8 = NULL;
sub_font_glyph->utf8_len = 0;
return sub_font_glyph;
}
@ -174,9 +153,6 @@ _cairo_sub_font_glyph_create (unsigned long scaled_font_glyph_index,
static void
_cairo_sub_font_glyph_destroy (cairo_sub_font_glyph_t *sub_font_glyph)
{
if (sub_font_glyph->utf8 != NULL)
free (sub_font_glyph->utf8);
free (sub_font_glyph);
}
@ -208,7 +184,6 @@ _cairo_sub_font_glyph_collect (void *entry, void *closure)
assert (subset_glyph_index < collection->glyphs_size);
collection->glyphs[subset_glyph_index] = scaled_font_glyph_index;
collection->utf8[subset_glyph_index] = sub_font_glyph->utf8;
if (subset_glyph_index > collection->max_glyph)
collection->max_glyph = subset_glyph_index;
@ -277,10 +252,9 @@ _cairo_sub_font_create (cairo_scaled_font_subsets_t *parent,
free (sub_font);
return _cairo_error (CAIRO_STATUS_NO_MEMORY);
}
sub_font->next = NULL;
/* Reserve first glyph in subset for the .notdef glyph */
status = _cairo_sub_font_map_glyph (sub_font, 0, NULL, 0, &subset_glyph);
status = _cairo_sub_font_map_glyph (sub_font, 0, &subset_glyph);
if (status) {
_cairo_hash_table_destroy (sub_font->sub_font_glyphs);
free (sub_font);
@ -312,86 +286,9 @@ _cairo_sub_font_pluck (void *entry, void *closure)
_cairo_sub_font_destroy (sub_font);
}
static cairo_status_t
_cairo_sub_font_glyph_lookup_unicode (cairo_sub_font_glyph_t *sub_font_glyph,
cairo_scaled_font_t *scaled_font,
unsigned long scaled_font_glyph_index)
{
uint32_t unicode;
char buf[8];
int len;
cairo_status_t status;
/* Do a reverse lookup on the glyph index. unicode is -1 if the
* index could not be mapped to a unicode character. */
status = _cairo_truetype_index_to_ucs4 (scaled_font, scaled_font_glyph_index, &unicode);
if (status && status != CAIRO_INT_STATUS_UNSUPPORTED)
return status;
if (status == CAIRO_INT_STATUS_UNSUPPORTED)
unicode = -1;
if (unicode == (uint32_t)-1 && scaled_font->backend->index_to_ucs4)
status = scaled_font->backend->index_to_ucs4 (scaled_font, scaled_font_glyph_index, &unicode);
sub_font_glyph->unicode = unicode;
sub_font_glyph->utf8 = NULL;
sub_font_glyph->utf8_len = 0;
if (unicode != (uint32_t)-1) {
len = _cairo_ucs4_to_utf8 (unicode, buf);
if (len > 0) {
sub_font_glyph->utf8 = malloc(len + 1);
memcpy (sub_font_glyph->utf8, buf, len);
sub_font_glyph->utf8[len] = 0;
sub_font_glyph->utf8_len = len;
}
}
return CAIRO_STATUS_SUCCESS;
}
static cairo_bool_t
_cairo_sub_font_glyph_map_to_unicode (cairo_sub_font_glyph_t *sub_font_glyph,
const char *utf8,
int utf8_len)
{
int add_zero_byte = 0;
if (utf8 != NULL && utf8_len != 0) {
if (sub_font_glyph->utf8 != NULL) {
if (utf8_len == sub_font_glyph->utf8_len &&
memcmp (utf8, sub_font_glyph->utf8, utf8_len) == 0)
{
/* Requested utf8 mapping matches the existing mapping */
return TRUE;
}
else
{
/* Requested utf8 mapping does not match the existing mapping */
return FALSE;
}
} else {
/* No existing mapping. Use the requested mapping */
if (sub_font_glyph->utf8[utf8_len - 1] != 0)
add_zero_byte = 1;
sub_font_glyph->utf8 = malloc (utf8_len + add_zero_byte);
memcpy (sub_font_glyph->utf8, utf8, utf8_len);
if (add_zero_byte)
sub_font_glyph->utf8[utf8_len] = 0;
sub_font_glyph->utf8_len = utf8_len;
return TRUE;
}
}
/* No mapping was requested. */
return FALSE;
}
static cairo_bool_t
_cairo_sub_font_lookup_glyph (cairo_sub_font_t *sub_font,
unsigned long scaled_font_glyph_index,
const char * utf8,
int utf8_len,
cairo_scaled_font_subsets_glyph_t *subset_glyph)
{
cairo_sub_font_glyph_t key, *sub_font_glyph;
@ -406,11 +303,8 @@ _cairo_sub_font_lookup_glyph (cairo_sub_font_t *sub_font,
subset_glyph->is_scaled = sub_font->is_scaled;
subset_glyph->is_composite = sub_font->is_composite;
subset_glyph->x_advance = sub_font_glyph->x_advance;
subset_glyph->y_advance = sub_font_glyph->y_advance;
subset_glyph->utf8_is_mapped = _cairo_sub_font_glyph_map_to_unicode (sub_font_glyph, utf8, utf8_len);
subset_glyph->unicode = sub_font_glyph->unicode;
return TRUE;
return TRUE;
}
return FALSE;
@ -419,8 +313,6 @@ _cairo_sub_font_lookup_glyph (cairo_sub_font_t *sub_font,
static cairo_status_t
_cairo_sub_font_map_glyph (cairo_sub_font_t *sub_font,
unsigned long scaled_font_glyph_index,
const char * utf8,
int utf8_len,
cairo_scaled_font_subsets_glyph_t *subset_glyph)
{
cairo_sub_font_glyph_t key, *sub_font_glyph;
@ -438,7 +330,7 @@ _cairo_sub_font_map_glyph (cairo_sub_font_t *sub_font,
sub_font->num_glyphs_in_current_subset = 0;
/* Reserve first glyph in subset for the .notdef glyph */
status = _cairo_sub_font_map_glyph (sub_font, 0, NULL, 0, &tmp_subset_glyph);
status = _cairo_sub_font_map_glyph (sub_font, 0, &tmp_subset_glyph);
if (status)
return status;
}
@ -454,15 +346,10 @@ _cairo_sub_font_map_glyph (cairo_sub_font_t *sub_font,
sub_font_glyph = _cairo_sub_font_glyph_create (scaled_font_glyph_index,
sub_font->current_subset,
sub_font->num_glyphs_in_current_subset,
scaled_glyph->metrics.x_advance,
scaled_glyph->metrics.y_advance);
scaled_glyph->metrics.x_advance);
if (sub_font_glyph == NULL)
return _cairo_error (CAIRO_STATUS_NO_MEMORY);
_cairo_sub_font_glyph_lookup_unicode (sub_font_glyph,
sub_font->scaled_font,
scaled_font_glyph_index);
status = _cairo_hash_table_insert (sub_font->sub_font_glyphs, &sub_font_glyph->base);
if (status) {
_cairo_sub_font_glyph_destroy (sub_font_glyph);
@ -489,8 +376,6 @@ _cairo_sub_font_map_glyph (cairo_sub_font_t *sub_font,
subset_glyph->is_scaled = sub_font->is_scaled;
subset_glyph->is_composite = sub_font->is_composite;
subset_glyph->x_advance = sub_font_glyph->x_advance;
subset_glyph->y_advance = sub_font_glyph->y_advance;
subset_glyph->utf8_is_mapped = FALSE;
return CAIRO_STATUS_SUCCESS;
}
@ -527,7 +412,6 @@ _cairo_sub_font_collect (void *entry, void *closure)
subset.font_id = sub_font->font_id;
subset.subset_id = i;
subset.glyphs = collection->glyphs;
subset.utf8 = collection->utf8;
subset.num_glyphs = collection->num_glyphs;
subset.glyph_names = NULL;
/* No need to check for out of memory here. If to_unicode is NULL, the PDF
@ -577,8 +461,6 @@ _cairo_scaled_font_subsets_create_internal (cairo_subsets_type_t type)
free (subsets);
return NULL;
}
subsets->unscaled_sub_fonts_list = NULL;
subsets->unscaled_sub_fonts_list_end = NULL;
subsets->scaled_sub_fonts = _cairo_hash_table_create (_cairo_sub_fonts_equal);
if (! subsets->scaled_sub_fonts) {
@ -586,8 +468,6 @@ _cairo_scaled_font_subsets_create_internal (cairo_subsets_type_t type)
free (subsets);
return NULL;
}
subsets->scaled_sub_fonts_list = NULL;
subsets->scaled_sub_fonts_list_end = NULL;
return subsets;
}
@ -626,8 +506,6 @@ cairo_status_t
_cairo_scaled_font_subsets_map_glyph (cairo_scaled_font_subsets_t *subsets,
cairo_scaled_font_t *scaled_font,
unsigned long scaled_font_glyph_index,
const char * utf8,
int utf8_len,
cairo_scaled_font_subsets_glyph_t *subset_glyph)
{
cairo_sub_font_t key, *sub_font;
@ -649,7 +527,6 @@ _cairo_scaled_font_subsets_map_glyph (cairo_scaled_font_subsets_t *subsets,
{
if (_cairo_sub_font_lookup_glyph (sub_font,
scaled_font_glyph_index,
utf8, utf8_len,
subset_glyph))
return CAIRO_STATUS_SUCCESS;
}
@ -663,7 +540,6 @@ _cairo_scaled_font_subsets_map_glyph (cairo_scaled_font_subsets_t *subsets,
{
if (_cairo_sub_font_lookup_glyph (sub_font,
scaled_font_glyph_index,
utf8, utf8_len,
subset_glyph))
return CAIRO_STATUS_SUCCESS;
}
@ -688,8 +564,7 @@ _cairo_scaled_font_subsets_map_glyph (cairo_scaled_font_subsets_t *subsets,
return status;
if (status == CAIRO_STATUS_SUCCESS &&
subsets->type != CAIRO_SUBSETS_SCALED &&
! _cairo_font_face_is_user (scaled_font->font_face))
subsets->type != CAIRO_SUBSETS_SCALED)
{
/* Path available. Add to unscaled subset. */
key.is_scaled = FALSE;
@ -736,16 +611,11 @@ _cairo_scaled_font_subsets_map_glyph (cairo_scaled_font_subsets_t *subsets,
status = _cairo_hash_table_insert (subsets->unscaled_sub_fonts,
&sub_font->base);
if (status) {
_cairo_sub_font_destroy (sub_font);
return status;
}
if (!subsets->unscaled_sub_fonts_list)
subsets->unscaled_sub_fonts_list = sub_font;
else
subsets->unscaled_sub_fonts_list_end->next = sub_font;
subsets->unscaled_sub_fonts_list_end = sub_font;
subsets->num_sub_fonts++;
}
} else {
@ -780,18 +650,13 @@ _cairo_scaled_font_subsets_map_glyph (cairo_scaled_font_subsets_t *subsets,
_cairo_sub_font_destroy (sub_font);
return status;
}
if (!subsets->scaled_sub_fonts_list)
subsets->scaled_sub_fonts_list = sub_font;
else
subsets->scaled_sub_fonts_list_end->next = sub_font;
subsets->scaled_sub_fonts_list_end = sub_font;
subsets->num_sub_fonts++;
}
}
return _cairo_sub_font_map_glyph (sub_font,
scaled_font_glyph_index,
utf8, utf8_len,
subset_glyph);
}
@ -802,7 +667,6 @@ _cairo_scaled_font_subsets_foreach_internal (cairo_scaled_font_subsets_t
cairo_bool_t is_scaled)
{
cairo_sub_font_collection_t collection;
cairo_sub_font_t *sub_font;
if (is_scaled)
collection.glyphs_size = font_subsets->max_glyphs_per_scaled_subset_used;
@ -813,30 +677,20 @@ _cairo_scaled_font_subsets_foreach_internal (cairo_scaled_font_subsets_t
return CAIRO_STATUS_SUCCESS;
collection.glyphs = _cairo_malloc_ab (collection.glyphs_size, sizeof(unsigned long));
collection.utf8 = _cairo_malloc_ab (collection.glyphs_size, sizeof(char *));
if (collection.glyphs == NULL || collection.utf8 == NULL) {
if (collection.glyphs != NULL)
free (collection.glyphs);
if (collection.utf8 != NULL)
free (collection.utf8);
if (collection.glyphs == NULL)
return _cairo_error (CAIRO_STATUS_NO_MEMORY);
}
collection.font_subset_callback = font_subset_callback;
collection.font_subset_callback_closure = closure;
collection.status = CAIRO_STATUS_SUCCESS;
if (is_scaled)
sub_font = font_subsets->scaled_sub_fonts_list;
_cairo_hash_table_foreach (font_subsets->scaled_sub_fonts,
_cairo_sub_font_collect, &collection);
else
sub_font = font_subsets->unscaled_sub_fonts_list;
_cairo_hash_table_foreach (font_subsets->unscaled_sub_fonts,
_cairo_sub_font_collect, &collection);
while (sub_font) {
_cairo_sub_font_collect (sub_font, &collection);
sub_font = sub_font->next;
}
free (collection.utf8);
free (collection.glyphs);
return collection.status;
@ -903,14 +757,29 @@ create_string_entry (char *s, cairo_string_entry_t **entry)
cairo_int_status_t
_cairo_scaled_font_subset_create_glyph_names (cairo_scaled_font_subset_t *subset)
{
const cairo_scaled_font_backend_t *backend;
unsigned int i;
cairo_status_t status;
cairo_hash_table_t *names;
cairo_string_entry_t key, *entry;
char buf[30];
char *utf8;
uint16_t *utf16;
int utf16_len;
if (subset->to_unicode == NULL)
return CAIRO_INT_STATUS_UNSUPPORTED;
status = _cairo_truetype_create_glyph_to_unicode_map (subset);
if (status) {
if (status != CAIRO_INT_STATUS_UNSUPPORTED)
return status;
backend = subset->scaled_font->backend;
if (backend->map_glyphs_to_unicode == NULL)
return CAIRO_INT_STATUS_UNSUPPORTED;
status = backend->map_glyphs_to_unicode (subset->scaled_font, subset);
if (status)
return status;
}
names = _cairo_hash_table_create (_cairo_string_equal);
if (names == NULL)
@ -939,17 +808,8 @@ _cairo_scaled_font_subset_create_glyph_names (cairo_scaled_font_subset_t *subset
}
for (i = 1; i < subset->num_glyphs; i++) {
utf8 = subset->utf8[i];
utf16 = NULL;
utf16_len = 0;
if (utf8 && *utf8) {
status = _cairo_utf8_to_utf16 (utf8, -1, &utf16, &utf16_len);
if (status && status != CAIRO_STATUS_INVALID_STRING)
return status; // FIXME
}
if (utf16_len == 1) {
snprintf (buf, sizeof(buf), "uni%04X", (int)(utf16[0]));
if (subset->to_unicode[i] <= 0xffff) {
snprintf (buf, sizeof(buf), "uni%04X", (unsigned int)(subset->to_unicode[i]));
_cairo_string_init_key (&key, buf);
if (_cairo_hash_table_lookup (names, &key.base,
(cairo_hash_entry_t **) &entry)) {
@ -958,8 +818,6 @@ _cairo_scaled_font_subset_create_glyph_names (cairo_scaled_font_subset_t *subset
} else {
snprintf (buf, sizeof(buf), "g%d", i);
}
if (utf16)
free (utf16);
subset->glyph_names[i] = strdup (buf);
if (subset->glyph_names[i] == NULL) {

Просмотреть файл

@ -167,8 +167,6 @@ _cairo_scaled_glyph_fini (cairo_scaled_glyph_t *scaled_glyph)
cairo_surface_destroy (&scaled_glyph->surface->base);
if (scaled_glyph->path != NULL)
_cairo_path_fixed_destroy (scaled_glyph->path);
if (scaled_glyph->meta_surface != NULL)
cairo_surface_destroy (scaled_glyph->meta_surface);
}
static void
@ -192,11 +190,8 @@ static const cairo_scaled_font_t _cairo_scaled_font_nil = {
CAIRO_SUBPIXEL_ORDER_DEFAULT,
CAIRO_HINT_STYLE_DEFAULT,
CAIRO_HINT_METRICS_DEFAULT} ,
FALSE, /* placeholder */
TRUE, /* finished */
{ 1., 0., 0., 1., 0, 0}, /* scale */
{ 1., 0., 0., 1., 0, 0}, /* scale_inverse */
1., /* max_scale */
{ 0., 0., 0., 0., 0. }, /* extents */
CAIRO_MUTEX_NIL_INITIALIZER,/* mutex */
NULL, /* glyphs */
@ -208,10 +203,10 @@ static const cairo_scaled_font_t _cairo_scaled_font_nil = {
/**
* _cairo_scaled_font_set_error:
* @scaled_font: a scaled_font
* @status: a status value indicating an error
* @status: a status value indicating an error, (eg. not
* CAIRO_STATUS_SUCCESS)
*
* Atomically sets scaled_font->status to @status and calls _cairo_error;
* Does nothing if status is %CAIRO_STATUS_SUCCESS.
*
* All assignments of an error status to scaled_font->status should happen
* through _cairo_scaled_font_set_error(). Note that due to the nature of
@ -348,6 +343,7 @@ _cairo_scaled_font_map_unlock (void)
void
_cairo_scaled_font_map_destroy (void)
{
int i;
cairo_scaled_font_map_t *font_map;
cairo_scaled_font_t *scaled_font;
@ -358,23 +354,15 @@ _cairo_scaled_font_map_destroy (void)
goto CLEANUP_MUTEX_LOCK;
}
/* remove scaled_fonts starting from the end so that font_map->holdovers
* is always in a consistent state when we release the mutex. */
while (font_map->num_holdovers) {
scaled_font = font_map->holdovers[font_map->num_holdovers-1];
for (i = 0; i < font_map->num_holdovers; i++) {
scaled_font = font_map->holdovers[i];
/* We should only get here through the reset_static_data path
* and there had better not be any active references at that
* point. */
assert (! CAIRO_REFERENCE_COUNT_HAS_REFERENCE (&scaled_font->ref_count));
_cairo_hash_table_remove (font_map->hash_table,
&scaled_font->hash_entry);
font_map->num_holdovers--;
/* release the lock to avoid the possibility of a recursive
* deadlock when the scaled font destroy closure gets called */
CAIRO_MUTEX_UNLOCK (_cairo_scaled_font_map_mutex);
_cairo_scaled_font_fini (scaled_font);
CAIRO_MUTEX_LOCK (_cairo_scaled_font_map_mutex);
free (scaled_font);
}
@ -387,113 +375,6 @@ _cairo_scaled_font_map_destroy (void)
CAIRO_MUTEX_UNLOCK (_cairo_scaled_font_map_mutex);
}
/* If a scaled font wants to unlock the font map while still being
* created (needed for user-fonts), we need to take extra care not
* ending up with multiple identical scaled fonts being created.
*
* What we do is, we create a fake identical scaled font, and mark
* it as placeholder, lock its mutex, and insert that in the fontmap
* hash table. This makes other code trying to create an identical
* scaled font to just wait and retry.
*
* The reason we have to create a fake scaled font instead of just using
* scaled_font is for lifecycle management: we need to (or rather,
* other code needs to) reference the scaked_font in the hash.
* We can't do that on the input scaled_font as it may be freed by
* font backend upon error.
*/
void
_cairo_scaled_font_register_placeholder_and_unlock_font_map (cairo_scaled_font_t *scaled_font)
{
cairo_status_t status = CAIRO_STATUS_SUCCESS;
cairo_scaled_font_t *placeholder_scaled_font;
placeholder_scaled_font = malloc (sizeof (cairo_scaled_font_t));
if (!placeholder_scaled_font) {
status = CAIRO_STATUS_NO_MEMORY;
goto FREE;
}
/* full initialization is wasteful, but who cares... */
status = _cairo_scaled_font_init (placeholder_scaled_font,
scaled_font->font_face,
&scaled_font->font_matrix,
&scaled_font->ctm,
&scaled_font->options,
NULL);
if (status)
goto FINI;
placeholder_scaled_font->placeholder = TRUE;
CAIRO_MUTEX_LOCK (placeholder_scaled_font->mutex);
status = _cairo_hash_table_insert (cairo_scaled_font_map->hash_table,
&placeholder_scaled_font->hash_entry);
if (status)
goto UNLOCK_KEY;
goto UNLOCK;
UNLOCK_KEY:
CAIRO_MUTEX_UNLOCK (placeholder_scaled_font->mutex);
FINI:
_cairo_scaled_font_fini (placeholder_scaled_font);
FREE:
free (placeholder_scaled_font);
status = _cairo_scaled_font_set_error (scaled_font, status);
UNLOCK:
CAIRO_MUTEX_UNLOCK (_cairo_scaled_font_map_mutex);
}
void
_cairo_scaled_font_unregister_placeholder_and_lock_font_map (cairo_scaled_font_t *scaled_font)
{
cairo_scaled_font_t *placeholder_scaled_font;
cairo_bool_t found;
CAIRO_MUTEX_LOCK (_cairo_scaled_font_map_mutex);
found = _cairo_hash_table_lookup (cairo_scaled_font_map->hash_table,
&scaled_font->hash_entry,
(cairo_hash_entry_t**) &placeholder_scaled_font);
assert (found);
assert (placeholder_scaled_font->placeholder);
_cairo_hash_table_remove (cairo_scaled_font_map->hash_table,
&scaled_font->hash_entry);
CAIRO_MUTEX_UNLOCK (scaled_font->mutex);
CAIRO_MUTEX_UNLOCK (_cairo_scaled_font_map_mutex);
cairo_scaled_font_destroy (placeholder_scaled_font);
CAIRO_MUTEX_LOCK (_cairo_scaled_font_map_mutex);
}
static void
_cairo_scaled_font_placeholder_wait_for_creation_to_finish (cairo_scaled_font_t *scaled_font)
{
/* reference the place holder so it doesn't go away */
cairo_scaled_font_reference (scaled_font);
/* now unlock the fontmap mutex so creation has a chance to finish */
CAIRO_MUTEX_UNLOCK (_cairo_scaled_font_map_mutex);
/* wait on placeholder mutex until we are awaken */
CAIRO_MUTEX_LOCK (scaled_font->mutex);
/* ok, creation done. just clean up and back out */
CAIRO_MUTEX_UNLOCK (scaled_font->mutex);
CAIRO_MUTEX_LOCK (_cairo_scaled_font_map_mutex);
cairo_scaled_font_destroy (scaled_font);
}
/* Fowler / Noll / Vo (FNV) Hash (http://www.isthe.com/chongo/tech/comp/fnv/)
*
* Not necessarily better than a lot of other hashes, but should be OK, and
@ -526,7 +407,6 @@ _cairo_scaled_font_init_key (cairo_scaled_font_t *scaled_font,
uint32_t hash = FNV1_32_INIT;
scaled_font->status = CAIRO_STATUS_SUCCESS;
scaled_font->placeholder = FALSE;
scaled_font->font_face = font_face;
scaled_font->font_matrix = *font_matrix;
scaled_font->ctm = *ctm;
@ -597,8 +477,6 @@ _cairo_scaled_font_init (cairo_scaled_font_t *scaled_font,
&scaled_font->font_matrix,
&scaled_font->ctm);
scaled_font->max_scale = MAX (fabs (scaled_font->scale.xx) + fabs (scaled_font->scale.xy),
fabs (scaled_font->scale.yx) + fabs (scaled_font->scale.yy));
scaled_font->scale_inverse = scaled_font->scale;
status = cairo_matrix_invert (&scaled_font->scale_inverse);
if (status) {
@ -607,9 +485,9 @@ _cairo_scaled_font_init (cairo_scaled_font_t *scaled_font,
* producing an error.
*
* FIXME: If the scale is rank 1, we still go into error mode. But then
* again, that's what we do everywhere in cairo.
* again, that's what we doo everywhere in cairo.
*
* Also, the check for == 0. below may be too harsh...
* Also, the check for == 0. below may bee too harsh...
*/
if (scaled_font->scale.xx == 0. && scaled_font->scale.xy == 0. &&
scaled_font->scale.yx == 0. && scaled_font->scale.yy == 0.)
@ -621,8 +499,6 @@ _cairo_scaled_font_init (cairo_scaled_font_t *scaled_font,
return status;
}
scaled_font->finished = FALSE;
scaled_font->glyphs = _cairo_cache_create (_cairo_scaled_glyph_keys_equal,
_cairo_scaled_glyph_destroy,
MAX_GLYPHS_CACHED_PER_FONT);
@ -675,7 +551,7 @@ _cairo_scaled_font_set_metrics (cairo_scaled_font_t *scaled_font,
status = _cairo_matrix_compute_scale_factors (&scaled_font->font_matrix,
&font_scale_x, &font_scale_y,
1);
/* XXX */ 1);
if (status)
return status;
@ -696,8 +572,6 @@ _cairo_scaled_font_set_metrics (cairo_scaled_font_t *scaled_font,
void
_cairo_scaled_font_fini (cairo_scaled_font_t *scaled_font)
{
scaled_font->finished = TRUE;
if (scaled_font->font_face != NULL)
cairo_font_face_destroy (scaled_font->font_face);
@ -710,8 +584,7 @@ _cairo_scaled_font_fini (cairo_scaled_font_t *scaled_font)
scaled_font->surface_backend->scaled_font_fini != NULL)
scaled_font->surface_backend->scaled_font_fini (scaled_font);
if (scaled_font->backend != NULL && scaled_font->backend->fini != NULL)
scaled_font->backend->fini (scaled_font);
scaled_font->backend->fini (scaled_font);
_cairo_user_data_array_fini (&scaled_font->user_data);
}
@ -764,20 +637,9 @@ cairo_scaled_font_create (cairo_font_face_t *font_face,
_cairo_scaled_font_init_key (&key, font_face,
font_matrix, ctm, options);
while (_cairo_hash_table_lookup (font_map->hash_table, &key.hash_entry,
(cairo_hash_entry_t**) &scaled_font))
{
if (!scaled_font->placeholder)
break;
/* If the scaled font is being created (happens for user-font),
* just wait until it's done, then retry */
_cairo_scaled_font_placeholder_wait_for_creation_to_finish (scaled_font);
}
/* Return existing scaled_font if it exists in the hash table. */
if (scaled_font)
if (_cairo_hash_table_lookup (font_map->hash_table, &key.hash_entry,
(cairo_hash_entry_t**) &scaled_font))
{
/* If the original reference count is 0, then this font must have
* been found in font_map->holdovers, (which means this caching is
@ -931,29 +793,26 @@ slim_hidden_def (cairo_scaled_font_reference);
void
cairo_scaled_font_destroy (cairo_scaled_font_t *scaled_font)
{
cairo_scaled_font_t *lru = NULL;
cairo_scaled_font_map_t *font_map;
cairo_scaled_font_t *lru = NULL;
if (scaled_font == NULL ||
CAIRO_REFERENCE_COUNT_IS_INVALID (&scaled_font->ref_count))
return;
assert (CAIRO_REFERENCE_COUNT_HAS_REFERENCE (&scaled_font->ref_count));
font_map = _cairo_scaled_font_map_lock ();
assert (font_map != NULL);
assert (CAIRO_REFERENCE_COUNT_HAS_REFERENCE (&scaled_font->ref_count));
if (_cairo_reference_count_dec_and_test (&scaled_font->ref_count)) {
if (!scaled_font->placeholder && scaled_font->hash_entry.hash != ZOMBIE) {
if (scaled_font->hash_entry.hash != ZOMBIE) {
/* Rather than immediately destroying this object, we put it into
* the font_map->holdovers array in case it will get used again
* soon (and is why we must hold the lock over the atomic op on
* the reference count). To make room for it, we do actually
* destroy the least-recently-used holdover.
*/
if (font_map->num_holdovers == CAIRO_SCALED_FONT_MAX_HOLDOVERS)
{
lru = font_map->holdovers[0];
@ -971,10 +830,8 @@ cairo_scaled_font_destroy (cairo_scaled_font_t *scaled_font)
font_map->num_holdovers++;
} else
lru = scaled_font;
}
CAIRO_MUTEX_UNLOCK (_cairo_scaled_font_map_mutex);
_cairo_scaled_font_map_unlock ();
/* If we pulled an item from the holdovers array, (while the font
* map lock was held, of course), then there is no way that anyone
@ -1176,21 +1033,6 @@ cairo_scaled_font_glyph_extents (cairo_scaled_font_t *scaled_font,
return;
}
if (num_glyphs == 0)
return;
if (num_glyphs < 0) {
_cairo_error_throw (CAIRO_STATUS_NEGATIVE_COUNT);
/* XXX Can't propagate error */
return;
}
if (glyphs == NULL) {
_cairo_error_throw (CAIRO_STATUS_NULL_POINTER);
/* XXX Can't propagate error */
return;
}
CAIRO_MUTEX_LOCK (scaled_font->mutex);
_cairo_scaled_font_freeze_cache (scaled_font);
@ -1277,26 +1119,20 @@ _cairo_scaled_font_text_to_glyphs (cairo_scaled_font_t *scaled_font,
cairo_status_t status;
cairo_scaled_glyph_t *scaled_glyph;
*num_glyphs = 0;
*glyphs = NULL;
status = scaled_font->status;
if (status)
return status;
if (utf8[0] == '\0')
if (utf8[0] == '\0') {
*num_glyphs = 0;
*glyphs = NULL;
return CAIRO_STATUS_SUCCESS;
}
CAIRO_MUTEX_LOCK (scaled_font->mutex);
_cairo_scaled_font_freeze_cache (scaled_font);
if (scaled_font->backend->text_to_glyphs) {
/* validate input so backend does not have to */
status = _cairo_utf8_to_ucs4 (utf8, -1, NULL, NULL);
if (status)
goto DONE;
status = scaled_font->backend->text_to_glyphs (scaled_font,
x, y, utf8,
glyphs, num_glyphs);
@ -1305,7 +1141,7 @@ _cairo_scaled_font_text_to_glyphs (cairo_scaled_font_t *scaled_font,
goto DONE;
}
status = _cairo_utf8_to_ucs4 (utf8, -1, &ucs4, num_glyphs);
status = _cairo_utf8_to_ucs4 ((unsigned char*)utf8, -1, &ucs4, num_glyphs);
if (status)
goto DONE;
@ -1376,7 +1212,7 @@ _cairo_scaled_font_glyph_device_extents (cairo_scaled_font_t *scaled_font,
if (status)
return _cairo_scaled_font_set_error (scaled_font, status);
/* XXX glyph images are snapped to pixel locations */
/* glyph images are snapped to pixel locations */
x = _cairo_lround (glyphs[i].x);
y = _cairo_lround (glyphs[i].y);
@ -1435,18 +1271,13 @@ _cairo_scaled_font_show_glyphs (cairo_scaled_font_t *scaled_font,
return CAIRO_STATUS_SUCCESS;
if (scaled_font->backend->show_glyphs != NULL) {
int remaining_glyphs = num_glyphs;
status = scaled_font->backend->show_glyphs (scaled_font,
op, pattern,
surface,
source_x, source_y,
dest_x, dest_y,
width, height,
glyphs, num_glyphs, &remaining_glyphs);
glyphs += num_glyphs - remaining_glyphs;
num_glyphs = remaining_glyphs;
if (remaining_glyphs == 0)
status = CAIRO_STATUS_SUCCESS;
glyphs, num_glyphs);
if (status != CAIRO_INT_STATUS_UNSUPPORTED)
return _cairo_scaled_font_set_error (scaled_font, status);
}
@ -1810,7 +1641,7 @@ _cairo_scaled_font_glyph_path (cairo_scaled_font_t *scaled_font,
}
/**
* _cairo_scaled_glyph_set_metrics:
* cairo_scaled_glyph_set_metrics:
* @scaled_glyph: a #cairo_scaled_glyph_t
* @scaled_font: a #cairo_scaled_font_t
* @fs_metrics: a #cairo_text_extents_t in font space
@ -1818,7 +1649,7 @@ _cairo_scaled_font_glyph_path (cairo_scaled_font_t *scaled_font,
* _cairo_scaled_glyph_set_metrics() stores user space metrics
* for the specified glyph given font space metrics. It is
* called by the font backend when initializing a glyph with
* %CAIRO_SCALED_GLYPH_INFO_METRICS.
* CAIRO_SCALED_GLYPH_INFO_METRICS.
**/
void
_cairo_scaled_glyph_set_metrics (cairo_scaled_glyph_t *scaled_glyph,
@ -1913,16 +1744,6 @@ _cairo_scaled_glyph_set_path (cairo_scaled_glyph_t *scaled_glyph,
scaled_glyph->path = path;
}
void
_cairo_scaled_glyph_set_meta_surface (cairo_scaled_glyph_t *scaled_glyph,
cairo_scaled_font_t *scaled_font,
cairo_surface_t *meta_surface)
{
if (scaled_glyph->meta_surface != NULL)
cairo_surface_destroy (meta_surface);
scaled_glyph->meta_surface = meta_surface;
}
/**
* _cairo_scaled_glyph_lookup:
* @scaled_font: a #cairo_scaled_font_t
@ -1942,7 +1763,7 @@ _cairo_scaled_glyph_set_meta_surface (cairo_scaled_glyph_t *scaled_glyph,
*
* If the desired info is not available, (for example, when trying to
* get INFO_PATH with a bitmapped font), this function will return
* %CAIRO_INT_STATUS_UNSUPPORTED.
* CAIRO_INT_STATUS_UNSUPPORTED.
*
* Note: This function must be called with scaled_font->mutex held.
**/
@ -1978,11 +1799,10 @@ _cairo_scaled_glyph_lookup (cairo_scaled_font_t *scaled_font,
}
_cairo_scaled_glyph_set_index(scaled_glyph, index);
scaled_glyph->cache_entry.size = 1; /* We currently don't differentiate on glyph size at all */
scaled_glyph->cache_entry.size = 1; /* XXX */
scaled_glyph->scaled_font = scaled_font;
scaled_glyph->surface = NULL;
scaled_glyph->path = NULL;
scaled_glyph->meta_surface = NULL;
scaled_glyph->surface_private = NULL;
/* ask backend to initialize metrics and shape fields */
@ -2014,38 +1834,11 @@ _cairo_scaled_glyph_lookup (cairo_scaled_font_t *scaled_font,
scaled_glyph->path == NULL))
need_info |= CAIRO_SCALED_GLYPH_INFO_PATH;
if (((info & CAIRO_SCALED_GLYPH_INFO_META_SURFACE) != 0 &&
scaled_glyph->path == NULL))
need_info |= CAIRO_SCALED_GLYPH_INFO_META_SURFACE;
if (need_info) {
status = (*scaled_font->backend->
scaled_glyph_init) (scaled_font, scaled_glyph, need_info);
if (status)
goto CLEANUP;
/* Don't trust the scaled_glyph_init() return value, the font
* backend may not even know about some of the info. For example,
* no backend other than the user-fonts knows about meta-surface
* glyph info. */
if ((info & CAIRO_SCALED_GLYPH_INFO_SURFACE) != 0 &&
scaled_glyph->surface == NULL) {
status = CAIRO_INT_STATUS_UNSUPPORTED;
goto CLEANUP;
}
if ((info & CAIRO_SCALED_GLYPH_INFO_PATH) != 0 &&
scaled_glyph->path == NULL) {
status = CAIRO_INT_STATUS_UNSUPPORTED;
goto CLEANUP;
}
if ((info & CAIRO_SCALED_GLYPH_INFO_META_SURFACE) != 0 &&
scaled_glyph->meta_surface == NULL) {
status = CAIRO_INT_STATUS_UNSUPPORTED;
goto CLEANUP;
}
}
CLEANUP:
@ -2061,13 +1854,6 @@ _cairo_scaled_glyph_lookup (cairo_scaled_font_t *scaled_font,
return status;
}
double
_cairo_scaled_font_get_max_scale (cairo_scaled_font_t *scaled_font)
{
return scaled_font->max_scale;
}
/**
* cairo_scaled_font_get_font_face:
* @scaled_font: a #cairo_scaled_font_t
@ -2134,30 +1920,6 @@ cairo_scaled_font_get_ctm (cairo_scaled_font_t *scaled_font,
}
slim_hidden_def (cairo_scaled_font_get_ctm);
/**
* cairo_scaled_font_get_scale_matrix:
* @scaled_font: a #cairo_scaled_font_t
* @scale_matrix: return value for the matrix
*
* Stores the scale matrix of @scaled_font into @matrix.
* The scale matrix is product of the font matrix and the ctm
* associated with the scaled font, and hence is the matrix mapping from
* font space to device space.
*
* Since: 1.8
**/
void
cairo_scaled_font_get_scale_matrix (cairo_scaled_font_t *scaled_font,
cairo_matrix_t *scale_matrix)
{
if (scaled_font->status) {
cairo_matrix_init_identity (scale_matrix);
return;
}
*scale_matrix = scaled_font->scale;
}
/**
* cairo_scaled_font_get_font_options:
* @scaled_font: a #cairo_scaled_font_t

Просмотреть файл

@ -358,7 +358,7 @@ _clip_and_composite (cairo_clip_t *clip,
cairo_surface_t *dst,
const cairo_rectangle_int_t *extents)
{
cairo_solid_pattern_t solid_pattern;
cairo_pattern_union_t solid_pattern;
cairo_status_t status;
if (_cairo_rectangle_empty (extents))
@ -366,7 +366,7 @@ _clip_and_composite (cairo_clip_t *clip,
return CAIRO_STATUS_SUCCESS;
if (op == CAIRO_OPERATOR_CLEAR) {
_cairo_pattern_init_solid (&solid_pattern, CAIRO_COLOR_WHITE,
_cairo_pattern_init_solid (&solid_pattern.solid, CAIRO_COLOR_WHITE,
CAIRO_CONTENT_COLOR);
src = &solid_pattern.base;
op = CAIRO_OPERATOR_DEST_OUT;
@ -415,14 +415,14 @@ _composite_trap_region (cairo_clip_t *clip,
cairo_rectangle_int_t *extents)
{
cairo_status_t status;
cairo_solid_pattern_t solid_pattern;
cairo_surface_pattern_t mask;
cairo_pattern_union_t solid_pattern;
cairo_pattern_union_t mask;
int num_rects = _cairo_region_num_boxes (trap_region);
unsigned int clip_serial;
cairo_surface_t *clip_surface = clip ? clip->surface : NULL;
if (clip_surface && op == CAIRO_OPERATOR_CLEAR) {
_cairo_pattern_init_solid (&solid_pattern, CAIRO_COLOR_WHITE,
_cairo_pattern_init_solid (&solid_pattern.solid, CAIRO_COLOR_WHITE,
CAIRO_CONTENT_COLOR);
src = &solid_pattern.base;
op = CAIRO_OPERATOR_DEST_OUT;
@ -444,7 +444,7 @@ _composite_trap_region (cairo_clip_t *clip,
}
if (clip_surface)
_cairo_pattern_init_for_surface (&mask, clip_surface);
_cairo_pattern_init_for_surface (&mask.surface, clip_surface);
status = _cairo_surface_composite (op,
src,
@ -487,13 +487,13 @@ _composite_traps_draw_func (void *closure,
const cairo_rectangle_int_t *extents)
{
cairo_composite_traps_info_t *info = closure;
cairo_solid_pattern_t pattern;
cairo_pattern_union_t pattern;
cairo_status_t status;
if (dst_x != 0 || dst_y != 0)
_cairo_traps_translate (info->traps, - dst_x, - dst_y);
_cairo_pattern_init_solid (&pattern, CAIRO_COLOR_WHITE,
_cairo_pattern_init_solid (&pattern.solid, CAIRO_COLOR_WHITE,
CAIRO_CONTENT_COLOR);
if (!src)
src = &pattern.base;
@ -929,7 +929,7 @@ _cairo_surface_old_show_glyphs_draw_func (void *closure
const cairo_rectangle_int_t *extents)
{
cairo_show_glyphs_info_t *glyph_info = closure;
cairo_solid_pattern_t pattern;
cairo_pattern_union_t pattern;
cairo_status_t status;
/* Modifying the glyph array is fine because we know that this function
@ -946,7 +946,7 @@ _cairo_surface_old_show_glyphs_draw_func (void *closure
}
}
_cairo_pattern_init_solid (&pattern, CAIRO_COLOR_WHITE,
_cairo_pattern_init_solid (&pattern.solid, CAIRO_COLOR_WHITE,
CAIRO_CONTENT_COLOR);
if (!src)
src = &pattern.base;
@ -1032,7 +1032,7 @@ _cairo_surface_fallback_snapshot (cairo_surface_t *surface)
{
cairo_surface_t *snapshot;
cairo_status_t status;
cairo_surface_pattern_t pattern;
cairo_pattern_union_t pattern;
cairo_image_surface_t *image;
void *image_extra;
@ -1050,7 +1050,7 @@ _cairo_surface_fallback_snapshot (cairo_surface_t *surface)
return snapshot;
}
_cairo_pattern_init_for_surface (&pattern, &image->base);
_cairo_pattern_init_for_surface (&pattern.surface, &image->base);
status = _cairo_surface_composite (CAIRO_OPERATOR_SOURCE,
&pattern.base,

Просмотреть файл

@ -43,7 +43,7 @@
#define DEFINE_NIL_SURFACE(status, name) \
const cairo_surface_t name = { \
&_cairo_image_surface_backend, /* backend */ \
&cairo_image_surface_backend, /* backend */ \
CAIRO_SURFACE_TYPE_IMAGE, \
CAIRO_CONTENT_COLOR, \
CAIRO_REFERENCE_COUNT_INVALID, /* ref_count */ \
@ -96,11 +96,10 @@ _cairo_surface_copy_pattern_for_destination (const cairo_pattern_t *pattern,
/**
* _cairo_surface_set_error:
* @surface: a surface
* @status: a status value indicating an error
* @status: a status value indicating an error, (eg. not
* CAIRO_STATUS_SUCCESS)
*
* Atomically sets surface->status to @status and calls _cairo_error;
* Does nothing if status is %CAIRO_STATUS_SUCCESS or any of the internal
* status values.
*
* All assignments of an error status to surface->status should happen
* through _cairo_surface_set_error(). Note that due to the nature of
@ -302,7 +301,8 @@ cairo_surface_create_similar (cairo_surface_t *other,
return _cairo_surface_create_similar_solid (other, content,
width, height,
CAIRO_COLOR_TRANSPARENT);
CAIRO_COLOR_TRANSPARENT,
NULL);
}
slim_hidden_def (cairo_surface_create_similar);
@ -311,25 +311,34 @@ _cairo_surface_create_similar_solid (cairo_surface_t *other,
cairo_content_t content,
int width,
int height,
const cairo_color_t *color)
const cairo_color_t *color,
cairo_pattern_t *pattern)
{
cairo_status_t status;
cairo_surface_t *surface;
cairo_solid_pattern_t solid_pattern;
cairo_pattern_t *source;
surface = _cairo_surface_create_similar_scratch (other, content,
width, height);
if (surface->status)
return surface;
_cairo_pattern_init_solid (&solid_pattern, color, content);
if (pattern == NULL) {
source = _cairo_pattern_create_solid (color, content);
if (source->status) {
cairo_surface_destroy (surface);
return _cairo_surface_create_in_error (source->status);
}
} else
source = pattern;
status = _cairo_surface_paint (surface,
color == CAIRO_COLOR_TRANSPARENT ?
CAIRO_OPERATOR_CLEAR : CAIRO_OPERATOR_SOURCE,
&solid_pattern.base);
CAIRO_OPERATOR_CLEAR :
CAIRO_OPERATOR_SOURCE, source);
_cairo_pattern_fini (&solid_pattern.base);
if (source != pattern)
cairo_pattern_destroy (source);
if (status) {
cairo_surface_destroy (surface);
@ -339,43 +348,6 @@ _cairo_surface_create_similar_solid (cairo_surface_t *other,
return surface;
}
cairo_surface_t *
_cairo_surface_create_solid_pattern_surface (cairo_surface_t *other,
cairo_solid_pattern_t *solid_pattern)
{
cairo_surface_t *surface;
if (other->backend->create_solid_pattern_surface) {
surface = other->backend->create_solid_pattern_surface (other, solid_pattern);
if (surface)
return surface;
}
surface = _cairo_surface_create_similar_solid (other,
solid_pattern->content,
1, 1,
&solid_pattern->color);
return surface;
}
cairo_int_status_t
_cairo_surface_repaint_solid_pattern_surface (cairo_surface_t *other,
cairo_surface_t *solid_surface,
cairo_solid_pattern_t *solid_pattern)
{
if (other->backend->create_solid_pattern_surface)
/* Solid pattern surface for this backend are not trivial to make.
* Skip repainting.
*
* This does not work optimally with things like analysis surface that
* are proxies. But returning UNSUPPORTED is *safe* as it only
* disables some caching.
*/
return CAIRO_INT_STATUS_UNSUPPORTED;
return _cairo_surface_paint (solid_surface, CAIRO_OPERATOR_SOURCE, &solid_pattern->base);
}
cairo_clip_mode_t
_cairo_surface_get_clip_mode (cairo_surface_t *surface)
{
@ -445,7 +417,7 @@ cairo_surface_destroy (cairo_surface_t *surface)
slim_hidden_def(cairo_surface_destroy);
/**
* _cairo_surface_reset:
* cairo_surface_reset:
* @surface: a #cairo_surface_t
*
* Resets the surface back to defaults such that it may be reused in lieu
@ -502,10 +474,9 @@ cairo_surface_get_reference_count (cairo_surface_t *surface)
* external resources. For example, for the Xlib backend it means
* that cairo will no longer access the drawable, which can be freed.
* After calling cairo_surface_finish() the only valid operations on a
* surface are getting and setting user, referencing and
* destroying, and flushing and finishing it.
* Further drawing to the surface will not affect the
* surface but will instead trigger a %CAIRO_STATUS_SURFACE_FINISHED
* surface are getting and setting user data and referencing and
* destroying it. Further drawing to the surface will not affect the
* surface but will instead trigger a CAIRO_STATUS_SURFACE_FINISHED
* error.
*
* When the last call to cairo_surface_destroy() decreases the
@ -524,18 +495,28 @@ cairo_surface_finish (cairo_surface_t *surface)
if (CAIRO_REFERENCE_COUNT_IS_INVALID (&surface->ref_count))
return;
if (surface->finished)
if (surface->finished) {
status = _cairo_surface_set_error (surface, CAIRO_STATUS_SURFACE_FINISHED);
return;
cairo_surface_flush (surface);
/* call finish even if in error mode */
if (surface->backend->finish) {
status = surface->backend->finish (surface);
if (status)
status = _cairo_surface_set_error (surface, status);
}
if (surface->backend->finish == NULL) {
surface->finished = TRUE;
return;
}
if (!surface->status && surface->backend->flush) {
status = surface->backend->flush (surface);
if (status) {
status = _cairo_surface_set_error (surface, status);
return;
}
}
status = surface->backend->finish (surface);
if (status)
status = _cairo_surface_set_error (surface, status);
surface->finished = TRUE;
}
slim_hidden_def (cairo_surface_finish);
@ -681,8 +662,10 @@ cairo_surface_flush (cairo_surface_t *surface)
if (surface->status)
return;
if (surface->finished)
if (surface->finished) {
status = _cairo_surface_set_error (surface, CAIRO_STATUS_SURFACE_FINISHED);
return;
}
if (surface->backend->flush) {
status = surface->backend->flush (surface);
@ -690,7 +673,6 @@ cairo_surface_flush (cairo_surface_t *surface)
status = _cairo_surface_set_error (surface, status);
}
}
slim_hidden_def (cairo_surface_flush);
/**
* cairo_surface_mark_dirty:
@ -781,8 +763,11 @@ slim_hidden_def (cairo_surface_mark_dirty_rectangle);
* different backend space, (differing by the fallback resolution
* scale factors), we need a scale factor correction.
*
* Caution: Not all places we use device transform correctly handle
* both a translate and a scale. An audit would be nice.
* Caution: There is no guarantee that a surface with both a
* device_scale and a device_offset will be treated in consistent
* fashion. So, for now, just don't do that. (And we'll need to
* examine this issue in more detail if we were to ever want to export
* support for device scaling.)
**/
void
_cairo_surface_set_device_scale (cairo_surface_t *surface,
@ -803,13 +788,9 @@ _cairo_surface_set_device_scale (cairo_surface_t *surface,
surface->device_transform.xx = sx;
surface->device_transform.yy = sy;
surface->device_transform.xy = 0.0;
surface->device_transform.yx = 0.0;
surface->device_transform_inverse.xx = 1.0 / sx;
surface->device_transform_inverse.yy = 1.0 / sy;
surface->device_transform_inverse.xy = 0.0;
surface->device_transform_inverse.yx = 0.0;
}
/**
@ -933,29 +914,6 @@ cairo_surface_set_fallback_resolution (cairo_surface_t *surface,
}
slim_hidden_def (cairo_surface_set_fallback_resolution);
/**
* cairo_surface_get_fallback_resolution:
* @surface: a #cairo_surface_t
* @x_pixels_per_inch: horizontal pixels per inch
* @y_pixels_per_inch: vertical pixels per inch
*
* This function returns the previous fallback resolution set by
* cairo_surface_set_fallback_resolution(), or default fallback
* resolution if never set.
*
* Since: 1.8
**/
void
cairo_surface_get_fallback_resolution (cairo_surface_t *surface,
double *x_pixels_per_inch,
double *y_pixels_per_inch)
{
if (x_pixels_per_inch)
*x_pixels_per_inch = surface->x_fallback_resolution;
if (y_pixels_per_inch)
*y_pixels_per_inch = surface->y_fallback_resolution;
}
cairo_bool_t
_cairo_surface_has_device_transform (cairo_surface_t *surface)
{
@ -1184,7 +1142,7 @@ _cairo_surface_clone_similar (cairo_surface_t *surface,
* surface-modifying function on the result of this function.
*
* The caller owns the return value and should call
* cairo_surface_destroy() when finished with it. This function will not
* cairo_surface_destroy when finished with it. This function will not
* return %NULL, but will return a nil surface instead.
*
* Return value: The snapshot surface. Note that the return surface
@ -1816,7 +1774,7 @@ _cairo_surface_get_current_clip_serial (cairo_surface_t *surface)
* this function allocates one from the specified surface. As zero is
* reserved for the special no-clipping case, this function will not
* return that except for an in-error surface, (ie. surface->status !=
* %CAIRO_STATUS_SUCCESS).
* CAIRO_STATUS_SUCCESS).
*/
unsigned int
_cairo_surface_allocate_clip_serial (cairo_surface_t *surface)
@ -2108,80 +2066,47 @@ _cairo_surface_set_clip (cairo_surface_t *surface, cairo_clip_t *clip)
* This behavior would have to be changed is we ever exported a public
* variant of this function.
*/
cairo_int_status_t
cairo_status_t
_cairo_surface_get_extents (cairo_surface_t *surface,
cairo_rectangle_int_t *extents)
cairo_rectangle_int_t *rectangle)
{
cairo_int_status_t status = CAIRO_INT_STATUS_UNSUPPORTED;
if (surface->status)
return surface->status;
if (surface->finished)
return _cairo_surface_set_error (surface,CAIRO_STATUS_SURFACE_FINISHED);
if (surface->backend->get_extents) {
status = _cairo_surface_set_error (surface,
surface->backend->get_extents (surface, extents));
}
if (status == CAIRO_INT_STATUS_UNSUPPORTED) {
extents->x = CAIRO_RECT_INT_MIN;
extents->y = CAIRO_RECT_INT_MIN;
extents->width = CAIRO_RECT_INT_MAX - CAIRO_RECT_INT_MIN;
extents->height = CAIRO_RECT_INT_MAX - CAIRO_RECT_INT_MIN;
}
return status;
}
cairo_bool_t
_cairo_surface_has_show_text_glyphs (cairo_surface_t *surface)
{
if (surface->backend->has_show_text_glyphs)
return surface->backend->has_show_text_glyphs (surface);
else
return surface->backend->show_text_glyphs != NULL;
return _cairo_surface_set_error (surface,
surface->backend->get_extents (surface, rectangle));
}
/* Note: the backends may modify the contents of the glyph array as long as
* they do not return %CAIRO_INT_STATUS_UNSUPPORTED. This makes it possible to
* they do not return %CAIRO_STATUS_UNSUPPORTED. This makes it possible to
* avoid copying the array again and again, and edit it in-place.
* Backends are in fact free to use the array as a generic buffer as they
* see fit.
*
* For show_glyphs backend method, and NOT for show_text_glyphs method,
* when they do return UNSUPPORTED, they may adjust remaining_glyphs to notify
* that they have successfully rendered some of the glyphs (from the beginning
* of the array), but not all. If they don't touch remaining_glyphs, it
* defaults to all glyphs.
*
* See commits 5a9642c5746fd677aed35ce620ce90b1029b1a0c and
* 1781e6018c17909311295a9cc74b70500c6b4d0a for the rationale.
*/
cairo_status_t
_cairo_surface_show_text_glyphs (cairo_surface_t *surface,
cairo_operator_t op,
cairo_pattern_t *source,
const char *utf8,
int utf8_len,
cairo_glyph_t *glyphs,
int num_glyphs,
const cairo_text_cluster_t *clusters,
int num_clusters,
cairo_bool_t backward,
cairo_scaled_font_t *scaled_font)
_cairo_surface_show_glyphs (cairo_surface_t *surface,
cairo_operator_t op,
cairo_pattern_t *source,
cairo_glyph_t *glyphs,
int num_glyphs,
cairo_scaled_font_t *scaled_font)
{
cairo_status_t status;
cairo_scaled_font_t *dev_scaled_font = scaled_font;
cairo_pattern_t *dev_source;
cairo_matrix_t font_matrix;
assert (! surface->is_snapshot);
if (surface->status)
return surface->status;
if (!num_glyphs && !utf8_len)
if (!num_glyphs)
return CAIRO_STATUS_SUCCESS;
status = _cairo_surface_copy_pattern_for_destination (source,
@ -2190,20 +2115,24 @@ _cairo_surface_show_text_glyphs (cairo_surface_t *surface,
if (status)
return _cairo_surface_set_error (surface, status);
cairo_scaled_font_get_font_matrix (scaled_font, &font_matrix);
if (_cairo_surface_has_device_transform (surface) &&
! _cairo_matrix_is_integer_translation (&surface->device_transform, NULL, NULL))
{
cairo_font_options_t font_options;
cairo_matrix_t dev_ctm, font_matrix;
cairo_font_options_t *font_options;
cairo_matrix_t dev_ctm;
font_options = cairo_font_options_create ();
cairo_scaled_font_get_font_matrix (scaled_font, &font_matrix);
cairo_scaled_font_get_ctm (scaled_font, &dev_ctm);
cairo_matrix_multiply (&dev_ctm, &dev_ctm, &surface->device_transform);
cairo_scaled_font_get_font_options (scaled_font, &font_options);
cairo_scaled_font_get_font_options (scaled_font, font_options);
dev_scaled_font = cairo_scaled_font_create (cairo_scaled_font_get_font_face (scaled_font),
&font_matrix,
&dev_ctm,
&font_options);
font_options);
cairo_font_options_destroy (font_options);
}
status = cairo_scaled_font_status (dev_scaled_font);
if (status) {
@ -2215,59 +2144,10 @@ _cairo_surface_show_text_glyphs (cairo_surface_t *surface,
status = CAIRO_INT_STATUS_UNSUPPORTED;
/* The logic here is duplicated in _cairo_analysis_surface show_glyphs and
* show_text_glyphs. Keep in synch. */
if (clusters) {
/* A real show_text_glyphs call. Try show_text_glyphs backend
* method first */
if (surface->backend->show_text_glyphs) {
status = surface->backend->show_text_glyphs (surface, op, dev_source,
utf8, utf8_len,
glyphs, num_glyphs,
clusters, num_clusters,
backward,
dev_scaled_font);
}
if (status == CAIRO_INT_STATUS_UNSUPPORTED && surface->backend->show_glyphs) {
int remaining_glyphs = num_glyphs;
status = surface->backend->show_glyphs (surface, op, dev_source,
glyphs, num_glyphs,
dev_scaled_font,
&remaining_glyphs);
glyphs += num_glyphs - remaining_glyphs;
num_glyphs = remaining_glyphs;
if (status == CAIRO_INT_STATUS_UNSUPPORTED && remaining_glyphs == 0)
status = CAIRO_STATUS_SUCCESS;
}
} else {
/* A mere show_glyphs call. Try show_glyphs backend method first */
if (surface->backend->show_glyphs) {
int remaining_glyphs = num_glyphs;
status = surface->backend->show_glyphs (surface, op, dev_source,
glyphs, num_glyphs,
dev_scaled_font,
&remaining_glyphs);
glyphs += num_glyphs - remaining_glyphs;
num_glyphs = remaining_glyphs;
if (status == CAIRO_INT_STATUS_UNSUPPORTED && remaining_glyphs == 0)
status = CAIRO_STATUS_SUCCESS;
} else if (surface->backend->show_text_glyphs) {
/* Intentionally only try show_text_glyphs method for show_glyphs
* calls if backend does not have show_glyphs. If backend has
* both methods implemented, we don't fallback from show_glyphs to
* show_text_glyphs, and hence the backend can assume in its
* show_text_glyphs call that clusters is not NULL (which also
* implies that UTF-8 is not NULL, unless the text is
* zero-length).
*/
status = surface->backend->show_text_glyphs (surface, op, dev_source,
utf8, utf8_len,
glyphs, num_glyphs,
clusters, num_clusters,
backward,
dev_scaled_font);
}
}
if (surface->backend->show_glyphs)
status = surface->backend->show_glyphs (surface, op, dev_source,
glyphs, num_glyphs,
dev_scaled_font);
if (status == CAIRO_INT_STATUS_UNSUPPORTED)
status = _cairo_surface_fallback_show_glyphs (surface, op, dev_source,
@ -2285,8 +2165,8 @@ _cairo_surface_show_text_glyphs (cairo_surface_t *surface,
}
/* XXX: Previously, we had a function named _cairo_surface_show_glyphs
* with not-so-useful semantics. We've now got a
* _cairo_surface_show_text_glyphs with the proper semantics, and its
* with not-so-useful semantics. We've now got a new
* _cairo_surface_show_glyphs with the proper semantics, and its
* fallback still uses this old function (which still needs to be
* cleaned up in terms of both semantics and naming). */
cairo_status_t
@ -2634,11 +2514,6 @@ _cairo_surface_create_in_error (cairo_status_t status)
case CAIRO_STATUS_INVALID_DSC_COMMENT:
case CAIRO_STATUS_INVALID_INDEX:
case CAIRO_STATUS_CLIP_NOT_REPRESENTABLE:
case CAIRO_STATUS_FONT_TYPE_MISMATCH:
case CAIRO_STATUS_USER_FONT_IMMUTABLE:
case CAIRO_STATUS_USER_FONT_ERROR:
case CAIRO_STATUS_NEGATIVE_COUNT:
case CAIRO_STATUS_INVALID_CLUSTERS:
default:
_cairo_error_throw (CAIRO_STATUS_NO_MEMORY);
return (cairo_surface_t *) &_cairo_surface_nil;

Просмотреть файл

@ -384,11 +384,8 @@ _cairo_svg_surface_create_for_document (cairo_svg_document_t *document,
surface->height,
&cairo_svg_surface_paginated_backend);
status = paginated->status;
if (status == CAIRO_STATUS_SUCCESS) {
/* paginated keeps the only reference to surface now, drop ours */
cairo_surface_destroy (&surface->base);
if (status == CAIRO_STATUS_SUCCESS)
return paginated;
}
/* ignore status as we are on the error path */
CLEANUP:
@ -2142,8 +2139,7 @@ _cairo_svg_surface_show_glyphs (void *abstract_surface,
cairo_pattern_t *pattern,
cairo_glyph_t *glyphs,
int num_glyphs,
cairo_scaled_font_t *scaled_font,
int *remaining_glyphs)
cairo_scaled_font_t *scaled_font)
{
cairo_svg_surface_t *surface = abstract_surface;
cairo_svg_document_t *document = surface->document;
@ -2177,7 +2173,6 @@ _cairo_svg_surface_show_glyphs (void *abstract_surface,
for (i = 0; i < num_glyphs; i++) {
status = _cairo_scaled_font_subsets_map_glyph (document->font_subsets,
scaled_font, glyphs[i].index,
NULL, 0,
&subset_glyph);
if (status == CAIRO_INT_STATUS_UNSUPPORTED) {
_cairo_output_stream_printf (surface->xml_node, "</g>\n");
@ -2203,7 +2198,7 @@ _cairo_svg_surface_show_glyphs (void *abstract_surface,
return CAIRO_STATUS_SUCCESS;
FALLBACK:
_cairo_path_fixed_init (&path);
_cairo_path_fixed_init (&path);
status = _cairo_scaled_font_glyph_path (scaled_font,(cairo_glyph_t *) glyphs, num_glyphs, &path);

Просмотреть файл

@ -32,7 +32,7 @@
#ifndef CAIRO_SVG_H
#define CAIRO_SVG_H
#include "cairo.h"
#include <cairo.h>
#if CAIRO_HAS_SVG_SURFACE

Просмотреть файл

@ -557,8 +557,7 @@ _cairo_trap_contains (cairo_trapezoid_t *t, cairo_point_t *pt)
}
cairo_bool_t
_cairo_traps_contain (const cairo_traps_t *traps,
double x, double y)
_cairo_traps_contain (cairo_traps_t *traps, double x, double y)
{
int i;
cairo_point_t point;
@ -575,8 +574,7 @@ _cairo_traps_contain (const cairo_traps_t *traps,
}
void
_cairo_traps_extents (const cairo_traps_t *traps,
cairo_box_t *extents)
_cairo_traps_extents (cairo_traps_t *traps, cairo_box_t *extents)
{
if (traps->num_traps == 0) {
extents->p1.x = extents->p1.y = _cairo_fixed_from_int (0);
@ -600,8 +598,8 @@ _cairo_traps_extents (const cairo_traps_t *traps,
* or %CAIRO_STATUS_NO_MEMORY
**/
cairo_int_status_t
_cairo_traps_extract_region (const cairo_traps_t *traps,
cairo_region_t *region)
_cairo_traps_extract_region (cairo_traps_t *traps,
cairo_region_t *region)
{
cairo_box_int_t stack_boxes[CAIRO_STACK_ARRAY_LENGTH (cairo_box_int_t)];
cairo_box_int_t *boxes = stack_boxes;
@ -657,50 +655,3 @@ _cairo_traps_extract_region (const cairo_traps_t *traps,
return status;
}
/* moves trap points such that they become the actual corners of the trapezoid */
static void
_sanitize_trap (cairo_trapezoid_t *t)
{
cairo_trapezoid_t s = *t;
#define FIX(lr, tb, p) \
if (t->lr.p.y != t->tb) { \
t->lr.p.x = s.lr.p2.x + _cairo_fixed_mul_div (s.lr.p1.x - s.lr.p2.x, s.tb - s.lr.p2.y, s.lr.p1.y - s.lr.p2.y); \
t->lr.p.y = s.tb; \
}
FIX (left, top, p1);
FIX (left, bottom, p2);
FIX (right, top, p1);
FIX (right, bottom, p2);
}
cairo_private cairo_status_t
_cairo_traps_path (const cairo_traps_t *traps,
cairo_path_fixed_t *path)
{
int i;
for (i = 0; i < traps->num_traps; i++) {
cairo_status_t status;
cairo_trapezoid_t trap = traps->traps[i];
if (trap.top == trap.bottom)
continue;
_sanitize_trap (&trap);
status = _cairo_path_fixed_move_to (path, trap.left.p1.x, trap.top);
if (status) return status;
status = _cairo_path_fixed_line_to (path, trap.right.p1.x, trap.top);
if (status) return status;
status = _cairo_path_fixed_line_to (path, trap.right.p2.x, trap.bottom);
if (status) return status;
status = _cairo_path_fixed_line_to (path, trap.left.p2.x, trap.bottom);
if (status) return status;
status = _cairo_path_fixed_close_path (path);
if (status) return status;
}
return CAIRO_STATUS_SUCCESS;
}

Просмотреть файл

@ -1173,27 +1173,25 @@ _cairo_truetype_subset_fini (cairo_truetype_subset_t *subset)
}
static cairo_int_status_t
_cairo_truetype_reverse_cmap (cairo_scaled_font_t *scaled_font,
unsigned long table_offset,
unsigned long index,
uint32_t *ucs4)
_cairo_truetype_map_glyphs_to_unicode (cairo_scaled_font_subset_t *font_subset,
unsigned long table_offset)
{
cairo_status_t status;
const cairo_scaled_font_backend_t *backend;
tt_segment_map_t *map;
char buf[4];
unsigned int num_segments, i;
unsigned int num_segments, i, j;
unsigned long size;
uint16_t *start_code;
uint16_t *end_code;
uint16_t *delta;
uint16_t *range_offset;
uint16_t *glyph_array;
uint16_t c;
uint16_t g_id, c;
backend = scaled_font->backend;
backend = font_subset->scaled_font->backend;
size = 4;
status = backend->load_truetype_table (scaled_font,
status = backend->load_truetype_table (font_subset->scaled_font,
TT_TAG_cmap, table_offset,
(unsigned char *) &buf,
&size);
@ -1210,7 +1208,7 @@ _cairo_truetype_reverse_cmap (cairo_scaled_font_t *scaled_font,
if (map == NULL)
return _cairo_error (CAIRO_STATUS_NO_MEMORY);
status = backend->load_truetype_table (scaled_font,
status = backend->load_truetype_table (font_subset->scaled_font,
TT_TAG_cmap, table_offset,
(unsigned char *) map,
&size);
@ -1224,42 +1222,44 @@ _cairo_truetype_reverse_cmap (cairo_scaled_font_t *scaled_font,
range_offset = &(delta[num_segments]);
glyph_array = &(range_offset[num_segments]);
/* search for glyph in segments
* with rangeOffset=0 */
for (i = 0; i < num_segments; i++) {
c = index - be16_to_cpu (delta[i]);
if (range_offset[i] == 0 &&
c >= be16_to_cpu (start_code[i]) &&
c <= be16_to_cpu (end_code[i]))
{
*ucs4 = c;
goto found;
}
i = 0;
while (i < font_subset->num_glyphs) {
g_id = (uint16_t) font_subset->glyphs[i];
/* search for glyph in segments
* with rangeOffset=0 */
for (j = 0; j < num_segments; j++) {
c = g_id - be16_to_cpu (delta[j]);
if (range_offset[j] == 0 &&
c >= be16_to_cpu (start_code[j]) &&
c <= be16_to_cpu (end_code[j]))
{
font_subset->to_unicode[i] = c;
goto next_glyph;
}
}
/* search for glyph in segments with rangeOffset=1 */
for (j = 0; j < num_segments; j++) {
if (range_offset[j] != 0) {
uint16_t *glyph_ids = &range_offset[j] + be16_to_cpu (range_offset[j])/2;
int range_size = be16_to_cpu (end_code[j]) - be16_to_cpu (start_code[j]) + 1;
uint16_t g_id_be = cpu_to_be16 (g_id);
int k;
for (k = 0; k < range_size; k++) {
if (glyph_ids[k] == g_id_be) {
font_subset->to_unicode[i] = be16_to_cpu (start_code[j]) + k;
goto next_glyph;
}
}
}
}
next_glyph:
i++;
}
/* search for glyph in segments with rangeOffset=1 */
for (i = 0; i < num_segments; i++) {
if (range_offset[i] != 0) {
uint16_t *glyph_ids = &range_offset[i] + be16_to_cpu (range_offset[i])/2;
int range_size = be16_to_cpu (end_code[i]) - be16_to_cpu (start_code[i]) + 1;
uint16_t g_id_be = cpu_to_be16 (index);
int j;
for (j = 0; j < range_size; j++) {
if (glyph_ids[j] == g_id_be) {
*ucs4 = be16_to_cpu (start_code[i]) + j;
goto found;
}
}
}
}
/* glyph not found */
*ucs4 = -1;
found:
status = CAIRO_STATUS_SUCCESS;
fail:
free (map);
@ -1267,9 +1267,7 @@ fail:
}
cairo_int_status_t
_cairo_truetype_index_to_ucs4 (cairo_scaled_font_t *scaled_font,
unsigned long index,
uint32_t *ucs4)
_cairo_truetype_create_glyph_to_unicode_map (cairo_scaled_font_subset_t *font_subset)
{
cairo_status_t status = CAIRO_INT_STATUS_UNSUPPORTED;
const cairo_scaled_font_backend_t *backend;
@ -1278,12 +1276,12 @@ _cairo_truetype_index_to_ucs4 (cairo_scaled_font_t *scaled_font,
int num_tables, i;
unsigned long size;
backend = scaled_font->backend;
backend = font_subset->scaled_font->backend;
if (!backend->load_truetype_table)
return CAIRO_INT_STATUS_UNSUPPORTED;
size = 4;
status = backend->load_truetype_table (scaled_font,
status = backend->load_truetype_table (font_subset->scaled_font,
TT_TAG_cmap, 0,
(unsigned char *) &buf,
&size);
@ -1297,7 +1295,7 @@ _cairo_truetype_index_to_ucs4 (cairo_scaled_font_t *scaled_font,
if (cmap == NULL)
return _cairo_error (CAIRO_STATUS_NO_MEMORY);
status = backend->load_truetype_table (scaled_font,
status = backend->load_truetype_table (font_subset->scaled_font,
TT_TAG_cmap, 0,
(unsigned char *) cmap,
&size);
@ -1308,12 +1306,10 @@ _cairo_truetype_index_to_ucs4 (cairo_scaled_font_t *scaled_font,
for (i = 0; i < num_tables; i++) {
if (be16_to_cpu (cmap->index[i].platform) == 3 &&
be16_to_cpu (cmap->index[i].encoding) == 1) {
status = _cairo_truetype_reverse_cmap (scaled_font,
be32_to_cpu (cmap->index[i].offset),
index,
ucs4);
status = _cairo_truetype_map_glyphs_to_unicode (font_subset,
be32_to_cpu (cmap->index[i].offset));
if (status != CAIRO_INT_STATUS_UNSUPPORTED)
break;
goto cleanup;
}
}

Просмотреть файл

@ -276,47 +276,6 @@ cairo_type1_font_subset_find_segments (cairo_type1_font_subset_t *font)
return CAIRO_STATUS_SUCCESS;
}
/* Search for the definition of key and erase it by overwriting with spaces.
* This function is looks for definitions of the form:
*
* /key1 1234 def
* /key2 [12 34 56] def
*
* ie a key defined as an integer or array of integers.
*
*/
static void
cairo_type1_font_erase_dict_key (cairo_type1_font_subset_t *font,
const char *key)
{
const char *start, *p, *segment_end;
segment_end = font->header_segment + font->header_segment_size;
start = font->header_segment;
do {
start = find_token (start, segment_end, key);
if (start) {
p = start + strlen(key);
/* skip integers or array of integers */
while (p < segment_end &&
(isspace(*p) ||
isdigit(*p) ||
*p == '[' ||
*p == ']'))
{
p++;
}
if (p + 3 < segment_end && memcmp(p, "def", 3) == 0) {
/* erase definition of the key */
memset((char *) start, ' ', p + 3 - start);
}
start += strlen(key);
}
} while (start);
}
static cairo_status_t
cairo_type1_font_subset_write_header (cairo_type1_font_subset_t *font,
const char *name)
@ -324,57 +283,14 @@ cairo_type1_font_subset_write_header (cairo_type1_font_subset_t *font,
const char *start, *end, *segment_end;
unsigned int i;
/* FIXME:
* This function assumes that /FontName always appears
* before /Encoding. This appears to always be the case with Type1
* fonts.
*
* The more recently added code for removing the UniqueID and XUID
* keys can not make any assumptions about the position of the
* keys in the dictionary so it is implemented by overwriting the
* key definition with spaces before we start copying the font to
* the output.
*
* This code should be rewritten to not make any assumptions about
* the order of dictionary keys. This will allow UniqueID to be
* stripped out instead of leaving a bunch of spaces in the
* output.
*/
cairo_type1_font_erase_dict_key (font, "/UniqueID");
cairo_type1_font_erase_dict_key (font, "/XUID");
segment_end = font->header_segment + font->header_segment_size;
/* Type 1 fonts created by Fontforge have some PostScript code at
* the start of the font that skips the font if the printer has a
* cached copy of the font with the same unique id. This breaks
* our subsetted font so we disable it by searching for the
* PostScript operator "known" when used to check for the
* "/UniqueID" dictionary key. We append " pop false " after it to
* pop the result of this check off the stack and replace it with
* "false" to make the PostScript code think "/UniqueID" does not
* exist.
*/
end = font->header_segment;
start = find_token (font->header_segment, segment_end, "/UniqueID");
if (start) {
start += 9;
while (start < segment_end && isspace (*start))
start++;
if (start + 5 < segment_end && memcmp(start, "known", 5) == 0) {
_cairo_output_stream_write (font->output, font->header_segment,
start + 5 - font->header_segment);
_cairo_output_stream_printf (font->output, " pop false ");
end = start + 5;
}
}
start = find_token (end, segment_end, "/FontName");
start = find_token (font->header_segment, segment_end, "/FontName");
if (start == NULL)
return CAIRO_INT_STATUS_UNSUPPORTED;
_cairo_output_stream_write (font->output, end,
start - end);
_cairo_output_stream_write (font->output, font->header_segment,
start - font->header_segment);
_cairo_output_stream_printf (font->output, "/FontName /%s def", name);
@ -466,7 +382,6 @@ cairo_type1_font_subset_decrypt_eexec_segment (cairo_type1_font_subset_t *font)
unsigned char *in, *end;
char *out;
int c, p;
int i;
in = (unsigned char *) font->eexec_segment;
end = (unsigned char *) in + font->eexec_segment_size;
@ -492,23 +407,6 @@ cairo_type1_font_subset_decrypt_eexec_segment (cairo_type1_font_subset_t *font)
}
font->cleartext_end = out;
/* Overwrite random bytes with spaces.
*
* The first 4 bytes of the cleartext are the random bytes
* required by the encryption algorithm. When encrypting the
* cleartext, the first ciphertext byte must not be a white space
* character and the first 4 bytes must not be an ASCII Hex
* character. Some fonts do not check that their randomly chosen
* bytes results in ciphertext that complies with this
* restriction. This may cause problems for some PDF consumers. By
* replacing the random bytes with spaces, the first four bytes of
* ciphertext will always be 0xf9, 0x83, 0xef, 0x00 which complies
* with this restriction. Using spaces also means we don't have to
* skip over the random bytes when parsing the cleartext.
*/
for (i = 0; i < 4 && i < font->eexec_segment_size; i++)
font->cleartext[i] = ' ';
return CAIRO_STATUS_SUCCESS;
}

Просмотреть файл

@ -1,74 +0,0 @@
/* -*- Mode: c; c-basic-offset: 4; indent-tabs-mode: t; tab-width: 8; -*- */
/* cairo - a vector graphics library with display and print output
*
* Copyright © 2008 Adrian Johnson
*
* 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 Adrian Johnson.
*
* Contributor(s):
* Adrian Johnson <ajohnson@redneon.com>
*/
#ifndef CAIRO_TYPE3_GLYPH_SURFACE_PRIVATE_H
#define CAIRO_TYPE3_GLYPH_SURFACE_PRIVATE_H
#include "cairo-surface-private.h"
#include "cairo-pdf-operators-private.h"
typedef cairo_status_t (*cairo_type3_glyph_surface_emit_image_t) (cairo_image_surface_t *image,
cairo_output_stream_t *stream);
typedef struct cairo_type3_glyph_surface {
cairo_surface_t base;
cairo_scaled_font_t *scaled_font;
cairo_output_stream_t *stream;
cairo_pdf_operators_t pdf_operators;
cairo_matrix_t cairo_to_pdf;
cairo_type3_glyph_surface_emit_image_t emit_image;
} cairo_type3_glyph_surface_t;
cairo_private cairo_surface_t *
_cairo_type3_glyph_surface_create (cairo_scaled_font_t *scaled_font,
cairo_output_stream_t *stream,
cairo_type3_glyph_surface_emit_image_t emit_image);
cairo_private cairo_status_t
_cairo_type3_glyph_surface_emit_notdef_glyph (void *abstract_surface,
cairo_output_stream_t *stream,
cairo_box_t *bbox,
double *width);
cairo_private cairo_status_t
_cairo_type3_glyph_surface_emit_glyph (void *abstract_surface,
cairo_output_stream_t *stream,
unsigned long glyph_index,
cairo_box_t *bbox,
double *width);
#endif /* CAIRO_TYPE3_GLYPH_SURFACE_PRIVATE_H */

Просмотреть файл

@ -1,445 +0,0 @@
/* -*- Mode: c; c-basic-offset: 4; indent-tabs-mode: t; tab-width: 8; -*- */
/* cairo - a vector graphics library with display and print output
*
* Copyright © 2008 Adrian Johnson
*
* 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 Adrian Johnson.
*
* Contributor(s):
* Adrian Johnson <ajohnson@redneon.com>
*/
#include "cairoint.h"
#include "cairo-type3-glyph-surface-private.h"
#include "cairo-output-stream-private.h"
#include "cairo-meta-surface-private.h"
static const cairo_surface_backend_t cairo_type3_glyph_surface_backend;
cairo_surface_t *
_cairo_type3_glyph_surface_create (cairo_scaled_font_t *scaled_font,
cairo_output_stream_t *stream,
cairo_type3_glyph_surface_emit_image_t emit_image)
{
cairo_type3_glyph_surface_t *surface;
cairo_matrix_t invert_y_axis;
surface = malloc (sizeof (cairo_type3_glyph_surface_t));
if (surface == NULL)
return _cairo_surface_create_in_error (_cairo_error (CAIRO_STATUS_NO_MEMORY));
_cairo_surface_init (&surface->base, &cairo_type3_glyph_surface_backend,
CAIRO_CONTENT_COLOR_ALPHA);
surface->scaled_font = scaled_font;
surface->stream = stream;
surface->emit_image = emit_image;
/* Setup the transform from the user-font device space to Type 3
* font space. The Type 3 font space is defined by the FontMatrix
* entry in the Type 3 dictionary. In the PDF backend this is an
* identity matrix. */
surface->cairo_to_pdf = scaled_font->scale_inverse;
cairo_matrix_init_scale (&invert_y_axis, 1, -1);
cairo_matrix_multiply (&surface->cairo_to_pdf, &surface->cairo_to_pdf, &invert_y_axis);
_cairo_pdf_operators_init (&surface->pdf_operators,
surface->stream,
&surface->cairo_to_pdf,
NULL);
return &surface->base;
}
static cairo_status_t
_cairo_type3_glyph_surface_emit_image (cairo_type3_glyph_surface_t *surface,
cairo_image_surface_t *image,
cairo_matrix_t *image_matrix)
{
cairo_status_t status;
cairo_image_surface_t *image_mask;
/* The only image type supported by Type 3 fonts are 1-bit image
* masks */
if (image->format == CAIRO_FORMAT_A1) {
image_mask = image;
} else {
image_mask = _cairo_image_surface_clone (image, CAIRO_FORMAT_A1);
status = cairo_surface_status (&image->base);
if (status)
return status;
}
_cairo_output_stream_printf (surface->stream,
"q %f %f %f %f %f %f cm\n",
image_matrix->xx,
image_matrix->xy,
image_matrix->yx,
image_matrix->yy,
image_matrix->x0,
image_matrix->y0);
status = surface->emit_image (image_mask, surface->stream);
_cairo_output_stream_printf (surface->stream,
"Q\n");
if (image_mask != image)
cairo_surface_destroy (&image_mask->base);
return CAIRO_STATUS_SUCCESS;
}
static cairo_status_t
_cairo_type3_glyph_surface_emit_image_pattern (cairo_type3_glyph_surface_t *surface,
cairo_image_surface_t *image,
cairo_matrix_t *pattern_matrix)
{
cairo_matrix_t mat, upside_down;
cairo_status_t status;
if (image->width == 0 || image->height == 0)
return CAIRO_STATUS_SUCCESS;
mat = *pattern_matrix;
/* Get the pattern space to user space matrix */
status = cairo_matrix_invert (&mat);
/* cairo_pattern_set_matrix ensures the matrix is invertible */
assert (status == CAIRO_STATUS_SUCCESS);
/* Make this a pattern space to Type 3 font space matrix */
cairo_matrix_multiply (&mat, &mat, &surface->cairo_to_pdf);
/* PDF images are in a 1 unit by 1 unit image space. Turn the 1 by
* 1 image upside down to convert to flip the Y-axis going from
* cairo to PDF. Then scale the image up to the required size. */
cairo_matrix_scale (&mat, image->width, image->height);
cairo_matrix_init (&upside_down, 1, 0, 0, -1, 0, 1);
cairo_matrix_multiply (&mat, &upside_down, &mat);
return _cairo_type3_glyph_surface_emit_image (surface, image, &mat);
}
static cairo_status_t
_cairo_type3_glyph_surface_finish (void *abstract_surface)
{
cairo_type3_glyph_surface_t *surface = abstract_surface;
return _cairo_pdf_operators_fini (&surface->pdf_operators);
}
static cairo_int_status_t
_cairo_type3_glyph_surface_intersect_clip_path (void *abstract_surface,
cairo_path_fixed_t *path,
cairo_fill_rule_t fill_rule,
double tolerance,
cairo_antialias_t antialias)
{
cairo_type3_glyph_surface_t *surface = abstract_surface;
if (path == NULL) {
_cairo_output_stream_printf (surface->stream, "Q q\n");
return CAIRO_STATUS_SUCCESS;
}
return _cairo_pdf_operators_clip (&surface->pdf_operators,
path,
fill_rule);
}
static cairo_int_status_t
_cairo_type3_glyph_surface_paint (void *abstract_surface,
cairo_operator_t op,
cairo_pattern_t *source)
{
cairo_type3_glyph_surface_t *surface = abstract_surface;
cairo_surface_pattern_t *pattern;
cairo_image_surface_t *image;
void *image_extra;
cairo_status_t status;
if (source->type != CAIRO_PATTERN_TYPE_SURFACE)
return CAIRO_INT_STATUS_IMAGE_FALLBACK;
pattern = (cairo_surface_pattern_t *) source;
status = _cairo_surface_acquire_source_image (pattern->surface, &image, &image_extra);
if (status)
goto fail;
status = _cairo_type3_glyph_surface_emit_image_pattern (surface,
image,
&pattern->base.matrix);
fail:
_cairo_surface_release_source_image (pattern->surface, image, image_extra);
return status;
}
static cairo_int_status_t
_cairo_type3_glyph_surface_mask (void *abstract_surface,
cairo_operator_t op,
cairo_pattern_t *source,
cairo_pattern_t *mask)
{
return _cairo_type3_glyph_surface_paint (abstract_surface, op, mask);
}
static cairo_int_status_t
_cairo_type3_glyph_surface_stroke (void *abstract_surface,
cairo_operator_t op,
cairo_pattern_t *source,
cairo_path_fixed_t *path,
cairo_stroke_style_t *style,
cairo_matrix_t *ctm,
cairo_matrix_t *ctm_inverse,
double tolerance,
cairo_antialias_t antialias)
{
cairo_type3_glyph_surface_t *surface = abstract_surface;
return _cairo_pdf_operators_stroke (&surface->pdf_operators,
path,
style,
ctm,
ctm_inverse);
}
static cairo_int_status_t
_cairo_type3_glyph_surface_fill (void *abstract_surface,
cairo_operator_t op,
cairo_pattern_t *source,
cairo_path_fixed_t *path,
cairo_fill_rule_t fill_rule,
double tolerance,
cairo_antialias_t antialias)
{
cairo_type3_glyph_surface_t *surface = abstract_surface;
cairo_int_status_t status;
status = _cairo_pdf_operators_fill (&surface->pdf_operators,
path,
fill_rule);
return status;
}
static cairo_int_status_t
_cairo_type3_glyph_surface_show_glyphs (void *abstract_surface,
cairo_operator_t op,
cairo_pattern_t *source,
cairo_glyph_t *glyphs,
int num_glyphs,
cairo_scaled_font_t *scaled_font,
int *remaining_glyphs)
{
/* XXX: Some refactoring is required before we can add font
* subsets in the middle of emitting all the subsets. */
return CAIRO_INT_STATUS_IMAGE_FALLBACK;
}
static const cairo_surface_backend_t cairo_type3_glyph_surface_backend = {
CAIRO_INTERNAL_SURFACE_TYPE_TYPE3_GLYPH,
NULL, /* _cairo_type3_glyph_surface_create_similar */
_cairo_type3_glyph_surface_finish,
NULL, /* acquire_source_image */
NULL, /* release_source_image */
NULL, /* acquire_dest_image */
NULL, /* release_dest_image */
NULL, /* clone_similar */
NULL, /* composite */
NULL, /* fill_rectangles */
NULL, /* composite_trapezoids */
NULL, /* cairo_type3_glyph_surface_copy_page */
NULL, /* _cairo_type3_glyph_surface_show_page */
NULL, /* set_clip_region */
_cairo_type3_glyph_surface_intersect_clip_path,
NULL, /* _cairo_type3_glyph_surface_get_extents */
NULL, /* old_show_glyphs */
NULL, /* _cairo_type3_glyph_surface_get_font_options */
NULL, /* flush */
NULL, /* mark_dirty_rectangle */
NULL, /* scaled_font_fini */
NULL, /* scaled_glyph_fini */
_cairo_type3_glyph_surface_paint,
_cairo_type3_glyph_surface_mask,
_cairo_type3_glyph_surface_stroke,
_cairo_type3_glyph_surface_fill,
_cairo_type3_glyph_surface_show_glyphs,
NULL, /* snapshot */
};
static void
_cairo_type3_glyph_surface_set_stream (cairo_type3_glyph_surface_t *surface,
cairo_output_stream_t *stream)
{
surface->stream = stream;
_cairo_pdf_operators_set_stream (&surface->pdf_operators, stream);
}
static cairo_status_t
_cairo_type3_glyph_surface_emit_fallback_image (cairo_type3_glyph_surface_t *surface,
unsigned long glyph_index)
{
cairo_scaled_glyph_t *scaled_glyph;
cairo_status_t status;
cairo_image_surface_t *image;
cairo_matrix_t mat;
double width, height, x, y;
status = _cairo_scaled_glyph_lookup (surface->scaled_font,
glyph_index,
CAIRO_SCALED_GLYPH_INFO_METRICS |
CAIRO_SCALED_GLYPH_INFO_SURFACE,
&scaled_glyph);
if (status)
return status;
image = scaled_glyph->surface;
if (image->width == 0 || image->height == 0)
return CAIRO_STATUS_SUCCESS;
x = _cairo_fixed_to_double (scaled_glyph->bbox.p1.x);
y = _cairo_fixed_to_double (scaled_glyph->bbox.p2.y);
width = _cairo_fixed_to_double (scaled_glyph->bbox.p2.x) -
_cairo_fixed_to_double (scaled_glyph->bbox.p1.x);
height = _cairo_fixed_to_double (scaled_glyph->bbox.p2.y) -
_cairo_fixed_to_double (scaled_glyph->bbox.p1.y);
mat.xx = width;
mat.xy = 0;
mat.yx = 0;
mat.yy = height;
mat.x0 = x;
mat.y0 = y;
cairo_matrix_multiply (&mat, &mat, &surface->scaled_font->scale_inverse);
mat.y0 *= -1;
return _cairo_type3_glyph_surface_emit_image (surface, image, &mat);
}
cairo_status_t
_cairo_type3_glyph_surface_emit_notdef_glyph (void *abstract_surface,
cairo_output_stream_t *stream,
cairo_box_t *bbox,
double *width)
{
bbox->p1.x = 0;
bbox->p1.y = 0;
bbox->p2.x = 0;
bbox->p2.y = 0;
*width = 0.0;
_cairo_output_stream_printf (stream, "0 0 0 0 0 0 d1\n");
return CAIRO_STATUS_SUCCESS;
}
cairo_status_t
_cairo_type3_glyph_surface_emit_glyph (void *abstract_surface,
cairo_output_stream_t *stream,
unsigned long glyph_index,
cairo_box_t *bbox,
double *width)
{
cairo_type3_glyph_surface_t *surface = abstract_surface;
cairo_scaled_glyph_t *scaled_glyph;
cairo_status_t status, status2;
double x_advance, y_advance;
cairo_output_stream_t *mem_stream;
cairo_matrix_t font_matrix_inverse;
_cairo_type3_glyph_surface_set_stream (surface, stream);
status = _cairo_scaled_glyph_lookup (surface->scaled_font,
glyph_index,
CAIRO_SCALED_GLYPH_INFO_METRICS |
CAIRO_SCALED_GLYPH_INFO_META_SURFACE,
&scaled_glyph);
if (status && status != CAIRO_INT_STATUS_UNSUPPORTED)
return status;
if (status == CAIRO_INT_STATUS_UNSUPPORTED) {
status = _cairo_scaled_glyph_lookup (surface->scaled_font,
glyph_index,
CAIRO_SCALED_GLYPH_INFO_METRICS,
&scaled_glyph);
if (status)
return status;
status = CAIRO_INT_STATUS_IMAGE_FALLBACK;
}
x_advance = scaled_glyph->metrics.x_advance;
y_advance = scaled_glyph->metrics.y_advance;
font_matrix_inverse = surface->scaled_font->font_matrix;
status2 = cairo_matrix_invert (&font_matrix_inverse);
/* The invertability of font_matrix is tested in
* pdf_operators_show_glyphs before any glyphs are mappped to the
* subset. */
assert (status2 == CAIRO_STATUS_SUCCESS);
cairo_matrix_transform_distance (&font_matrix_inverse, &x_advance, &y_advance);
*width = x_advance;
*bbox = scaled_glyph->bbox;
_cairo_matrix_transform_bounding_box_fixed (&surface->scaled_font->scale_inverse,
bbox, NULL);
_cairo_output_stream_printf (surface->stream,
"%f 0 %f %f %f %f d1\n",
x_advance,
_cairo_fixed_to_double (bbox->p1.x),
- _cairo_fixed_to_double (bbox->p2.y),
_cairo_fixed_to_double (bbox->p2.x),
- _cairo_fixed_to_double (bbox->p1.y));
if (status == CAIRO_STATUS_SUCCESS) {
mem_stream = _cairo_memory_stream_create ();
_cairo_type3_glyph_surface_set_stream (surface, mem_stream);
_cairo_output_stream_printf (surface->stream, "q\n");
status = _cairo_meta_surface_replay (scaled_glyph->meta_surface,
&surface->base);
_cairo_output_stream_printf (surface->stream, "Q\n");
_cairo_type3_glyph_surface_set_stream (surface, stream);
if (status == CAIRO_STATUS_SUCCESS)
_cairo_memory_stream_copy (mem_stream, stream);
status2 = _cairo_output_stream_destroy (mem_stream);
if (status2)
return status2;
}
if (status == CAIRO_INT_STATUS_IMAGE_FALLBACK)
status = _cairo_type3_glyph_surface_emit_fallback_image (surface, glyph_index);
return status;
}

Просмотреть файл

@ -130,19 +130,16 @@ typedef enum _cairo_paginated_mode {
} cairo_paginated_mode_t;
/* Sure wish C had a real enum type so that this would be distinct
* from #cairo_status_t. Oh well, without that, I'll use this bogus 100
* offset. We want to keep it fit in int8_t as the compiler may choose
* that for #cairo_status_t */
from cairo_status_t. Oh well, without that, I'll use this bogus 1000
offset */
typedef enum _cairo_int_status {
CAIRO_INT_STATUS_UNSUPPORTED = 100,
CAIRO_INT_STATUS_DEGENERATE,
CAIRO_INT_STATUS_DEGENERATE = 1000,
CAIRO_INT_STATUS_UNSUPPORTED,
CAIRO_INT_STATUS_NOTHING_TO_DO,
CAIRO_INT_STATUS_CACHE_EMPTY,
CAIRO_INT_STATUS_FLATTEN_TRANSPARENCY,
CAIRO_INT_STATUS_IMAGE_FALLBACK,
CAIRO_INT_STATUS_ANALYZE_META_SURFACE_PATTERN,
CAIRO_INT_STATUS_LAST_STATUS
CAIRO_INT_STATUS_ANALYZE_META_SURFACE_PATTERN
} cairo_int_status_t;
typedef enum _cairo_internal_surface_type {
@ -151,9 +148,7 @@ typedef enum _cairo_internal_surface_type {
CAIRO_INTERNAL_SURFACE_TYPE_ANALYSIS,
CAIRO_INTERNAL_SURFACE_TYPE_TEST_META,
CAIRO_INTERNAL_SURFACE_TYPE_TEST_FALLBACK,
CAIRO_INTERNAL_SURFACE_TYPE_TEST_PAGINATED,
CAIRO_INTERNAL_SURFACE_TYPE_NULL,
CAIRO_INTERNAL_SURFACE_TYPE_TYPE3_GLYPH
CAIRO_INTERNAL_SURFACE_TYPE_TEST_PAGINATED
} cairo_internal_surface_type_t;
typedef struct _cairo_region cairo_region_t;
@ -212,13 +207,13 @@ struct _cairo_point_int32 {
#if CAIRO_FIXED_BITS == 32 && CAIRO_FIXED_FRAC_BITS >= 16
typedef struct _cairo_rectangle_int16 cairo_rectangle_int_t;
typedef struct _cairo_point_int16 cairo_point_int_t;
#define CAIRO_RECT_INT_MIN (INT16_MIN >> (CAIRO_FIXED_FRAC_BITS - 16))
#define CAIRO_RECT_INT_MAX (INT16_MAX >> (CAIRO_FIXED_FRAC_BITS - 16))
#define CAIRO_RECT_INT_MIN INT16_MIN
#define CAIRO_RECT_INT_MAX INT16_MAX
#elif CAIRO_FIXED_BITS == 32
typedef struct _cairo_rectangle_int32 cairo_rectangle_int_t;
typedef struct _cairo_point_int32 cairo_point_int_t;
#define CAIRO_RECT_INT_MIN (INT32_MIN >> CAIRO_FIXED_FRAC_BITS)
#define CAIRO_RECT_INT_MAX (INT32_MAX >> CAIRO_FIXED_FRAC_BITS)
#define CAIRO_RECT_INT_MIN INT32_MIN
#define CAIRO_RECT_INT_MAX INT32_MAX
#else
#error Not sure how to pick a cairo_rectangle_int_t and cairo_point_int_t for your CAIRO_FIXED_BITS!
#endif
@ -258,7 +253,7 @@ typedef struct _cairo_polygon {
int num_edges;
int edges_size;
cairo_edge_t *edges;
cairo_edge_t edges_embedded[32];
cairo_edge_t edges_embedded[8];
} cairo_polygon_t;
typedef struct _cairo_spline_knots {
@ -273,7 +268,7 @@ typedef struct _cairo_spline {
int num_points;
int points_size;
cairo_point_t *points;
cairo_point_t points_embedded[64];
cairo_point_t points_embedded[8];
} cairo_spline_t;
typedef struct _cairo_pen_vertex {
@ -287,9 +282,8 @@ typedef struct _cairo_pen {
double radius;
double tolerance;
int num_vertices;
cairo_pen_vertex_t *vertices;
cairo_pen_vertex_t vertices_embedded[32];
int num_vertices;
} cairo_pen_t;
typedef struct _cairo_color cairo_color_t;

Просмотреть файл

@ -1,5 +1,4 @@
/* -*- Mode: c; c-basic-offset: 4; indent-tabs-mode: t; tab-width: 8; -*- */
/* cairo - a vector graphics library with display and print output
/* cairo_unicode.c: Unicode conversion routines
*
* The code in this file is derived from GLib's gutf8.c and
* ultimately from libunicode. It is relicensed under the
@ -202,7 +201,7 @@ _utf8_get_char_extended (const unsigned char *p,
* If @len is supplied and the string has an embedded nul
* byte, only the portion before the nul byte is converted.
* @result: location to store a pointer to a newly allocated UTF-32
* string (always native endian), or %NULL. Free with free(). A 0
* string (always native endian). Free with free(). A 0
* word will be written after the last character.
* @items_written: location to store number of 32-bit words
* written. (Not including the trailing 0)
@ -216,21 +215,20 @@ _utf8_get_char_extended (const unsigned char *p,
* an invalid sequence was found.
**/
cairo_status_t
_cairo_utf8_to_ucs4 (const char *str,
int len,
uint32_t **result,
int *items_written)
_cairo_utf8_to_ucs4 (const unsigned char *str,
int len,
uint32_t **result,
int *items_written)
{
uint32_t *str32 = NULL;
int n_chars, i;
const unsigned char *in;
const unsigned char * const ustr = (const unsigned char *) str;
in = ustr;
in = str;
n_chars = 0;
while ((len < 0 || ustr + len - in > 0) && *in)
while ((len < 0 || str + len - in > 0) && *in)
{
uint32_t wc = _utf8_get_char_extended (in, ustr + len - in);
uint32_t wc = _utf8_get_char_extended (in, str + len - in);
if (wc & 0x80000000 || !UNICODE_VALID (wc))
return _cairo_error (CAIRO_STATUS_INVALID_STRING);
@ -241,66 +239,24 @@ _cairo_utf8_to_ucs4 (const char *str,
in = UTF8_NEXT_CHAR (in);
}
if (result) {
str32 = _cairo_malloc_ab (n_chars + 1, sizeof (uint32_t));
if (!str32)
return _cairo_error (CAIRO_STATUS_NO_MEMORY);
str32 = _cairo_malloc_ab (n_chars + 1, sizeof (uint32_t));
if (!str32)
return _cairo_error (CAIRO_STATUS_NO_MEMORY);
in = ustr;
for (i=0; i < n_chars; i++) {
str32[i] = _utf8_get_char (in);
in = UTF8_NEXT_CHAR (in);
}
str32[i] = 0;
*result = str32;
in = str;
for (i=0; i < n_chars; i++) {
str32[i] = _utf8_get_char (in);
in = UTF8_NEXT_CHAR (in);
}
str32[i] = 0;
*result = str32;
if (items_written)
*items_written = n_chars;
return CAIRO_STATUS_SUCCESS;
}
/**
* _cairo_ucs4_to_utf8:
* @unicode: a UCS-4 character
* @utf8: buffer to write utf8 string into. Must have at least 4 bytes
* space available.
*
* Return value: Number of bytes in the utf8 string or 0 if an invalid
* unicode character
**/
int
_cairo_ucs4_to_utf8 (uint32_t unicode,
char *utf8)
{
int bytes;
char *p;
if (unicode < 0x80) {
*utf8 = unicode;
return 1;
} else if (unicode < 0x800) {
bytes = 2;
} else if (unicode < 0x10000) {
bytes = 3;
} else if (unicode < 0x200000) {
bytes = 4;
} else {
return 0;
}
p = utf8 + bytes;
while (p > utf8) {
*--p = 0x80 | (unicode & 0x3f);
unicode >>= 6;
}
*p |= 0xf0 << (4 - bytes);
return bytes;
}
#if CAIRO_HAS_UTF8_TO_UTF16
/**
* _cairo_utf8_to_utf16:
@ -324,20 +280,19 @@ _cairo_ucs4_to_utf8 (uint32_t unicode,
* an invalid sequence was found.
**/
cairo_status_t
_cairo_utf8_to_utf16 (const char *str,
int len,
uint16_t **result,
int *items_written)
_cairo_utf8_to_utf16 (const unsigned char *str,
int len,
uint16_t **result,
int *items_written)
{
uint16_t *str16 = NULL;
int n16, i;
const unsigned char *in;
const unsigned char * const ustr = (const unsigned char *) str;
in = ustr;
in = str;
n16 = 0;
while ((len < 0 || ustr + len - in > 0) && *in) {
uint32_t wc = _utf8_get_char_extended (in, ustr + len - in);
while ((len < 0 || str + len - in > 0) && *in) {
uint32_t wc = _utf8_get_char_extended (in, str + len - in);
if (wc & 0x80000000 || !UNICODE_VALID (wc))
return _cairo_error (CAIRO_STATUS_INVALID_STRING);
@ -356,7 +311,7 @@ _cairo_utf8_to_utf16 (const char *str,
if (!str16)
return _cairo_error (CAIRO_STATUS_NO_MEMORY);
in = ustr;
in = str;
for (i = 0; i < n16;) {
uint32_t wc = _utf8_get_char (in);

Просмотреть файл

@ -1,45 +0,0 @@
/* cairo - a vector graphics library with display and print output
*
* Copyright © 2006, 2008 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):
* Kristian Høgsberg <krh@redhat.com>
* Behdad Esfahbod <behdad@behdad.org>
*/
#ifndef CAIRO_USER_FONT_PRIVATE_H
#define CAIRO_USER_FONT_PRIVATE_H
#include "cairo.h"
cairo_private cairo_bool_t
_cairo_font_face_is_user (cairo_font_face_t *font_face);
#endif /* CAIRO_USER_FONT_PRIVATE_H */

Просмотреть файл

@ -1,688 +0,0 @@
/* cairo - a vector graphics library with display and print output
*
* Copyright © 2006, 2008 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):
* Kristian Høgsberg <krh@redhat.com>
* Behdad Esfahbod <behdad@behdad.org>
*/
#include "cairoint.h"
#include "cairo-user-font-private.h"
#include "cairo-meta-surface-private.h"
#include "cairo-analysis-surface-private.h"
typedef struct _cairo_user_scaled_font_methods {
cairo_user_scaled_font_init_func_t init;
cairo_user_scaled_font_render_glyph_func_t render_glyph;
cairo_user_scaled_font_unicode_to_glyph_func_t unicode_to_glyph;
cairo_user_scaled_font_text_to_glyphs_func_t text_to_glyphs;
} cairo_user_scaled_font_methods_t;
typedef struct _cairo_user_font_face {
cairo_font_face_t base;
/* Set to true after first scaled font is created. At that point,
* the scaled_font_methods cannot change anymore. */
cairo_bool_t immutable;
cairo_user_scaled_font_methods_t scaled_font_methods;
} cairo_user_font_face_t;
typedef struct _cairo_user_scaled_font {
cairo_scaled_font_t base;
cairo_text_extents_t default_glyph_extents;
/* space to compute extents in, and factors to convert back to user space */
cairo_matrix_t extent_scale;
double extent_x_scale;
double extent_y_scale;
/* multiplier for metrics hinting */
double snap_x_scale;
double snap_y_scale;
} cairo_user_scaled_font_t;
/* #cairo_user_scaled_font_t */
static const cairo_scaled_font_backend_t cairo_user_scaled_font_backend;
static cairo_int_status_t
_cairo_user_scaled_glyph_init (void *abstract_font,
cairo_scaled_glyph_t *scaled_glyph,
cairo_scaled_glyph_info_t info)
{
cairo_int_status_t status = CAIRO_STATUS_SUCCESS;
cairo_user_scaled_font_t *scaled_font = abstract_font;
cairo_surface_t *meta_surface = scaled_glyph->meta_surface;
if (!scaled_glyph->meta_surface) {
cairo_user_font_face_t *face =
(cairo_user_font_face_t *) scaled_font->base.font_face;
cairo_text_extents_t extents = scaled_font->default_glyph_extents;
cairo_content_t content = scaled_font->base.options.antialias == CAIRO_ANTIALIAS_SUBPIXEL ?
CAIRO_CONTENT_COLOR_ALPHA :
CAIRO_CONTENT_ALPHA;
cairo_t *cr;
meta_surface = _cairo_meta_surface_create (content, -1, -1);
cr = cairo_create (meta_surface);
cairo_set_matrix (cr, &scaled_font->base.scale);
cairo_set_font_size (cr, 1.0);
cairo_set_font_options (cr, &scaled_font->base.options);
if (face->scaled_font_methods.render_glyph)
status = face->scaled_font_methods.render_glyph ((cairo_scaled_font_t *)scaled_font,
_cairo_scaled_glyph_index(scaled_glyph),
cr, &extents);
else
status = CAIRO_STATUS_USER_FONT_ERROR;
if (status == CAIRO_STATUS_SUCCESS)
status = cairo_status (cr);
cairo_destroy (cr);
if (status) {
cairo_surface_destroy (meta_surface);
return status;
}
_cairo_scaled_glyph_set_meta_surface (scaled_glyph,
&scaled_font->base,
meta_surface);
/* set metrics */
if (extents.width == 0.) {
/* Compute extents.x/y/width/height from meta_surface, in font space */
cairo_box_t bbox;
double x1, y1, x2, y2;
double x_scale, y_scale;
cairo_surface_t *null_surface = _cairo_null_surface_create (cairo_surface_get_content (meta_surface));
cairo_surface_t *analysis_surface = _cairo_analysis_surface_create (null_surface, -1, -1);
cairo_surface_destroy (null_surface);
_cairo_analysis_surface_set_ctm (analysis_surface, &scaled_font->extent_scale);
status = _cairo_meta_surface_replay (meta_surface, analysis_surface);
_cairo_analysis_surface_get_bounding_box (analysis_surface, &bbox);
cairo_surface_destroy (analysis_surface);
_cairo_box_to_doubles (&bbox, &x1, &y1, &x2, &y2);
x_scale = scaled_font->extent_x_scale;
y_scale = scaled_font->extent_y_scale;
extents.x_bearing = x1 * x_scale;
extents.y_bearing = y1 * y_scale;
extents.width = (x2 - x1) * x_scale;
extents.height = (y2 - y1) * y_scale;
}
if (scaled_font->base.options.hint_metrics != CAIRO_HINT_METRICS_OFF) {
extents.x_advance = _cairo_lround (extents.x_advance / scaled_font->snap_x_scale) * scaled_font->snap_x_scale;
extents.y_advance = _cairo_lround (extents.y_advance / scaled_font->snap_y_scale) * scaled_font->snap_y_scale;
}
_cairo_scaled_glyph_set_metrics (scaled_glyph,
&scaled_font->base,
&extents);
}
if (info & CAIRO_SCALED_GLYPH_INFO_SURFACE) {
cairo_surface_t *surface;
cairo_status_t status = CAIRO_STATUS_SUCCESS;
cairo_format_t format;
int width, height;
/* TODO
* extend the glyph cache to support argb glyphs.
* need to figure out the semantics and interaction with subpixel
* rendering first.
*/
width = _cairo_fixed_integer_ceil (scaled_glyph->bbox.p2.x) -
_cairo_fixed_integer_floor (scaled_glyph->bbox.p1.x);
height = _cairo_fixed_integer_ceil (scaled_glyph->bbox.p2.y) -
_cairo_fixed_integer_floor (scaled_glyph->bbox.p1.y);
switch (scaled_font->base.options.antialias) {
default:
case CAIRO_ANTIALIAS_DEFAULT:
case CAIRO_ANTIALIAS_GRAY: format = CAIRO_FORMAT_A8; break;
case CAIRO_ANTIALIAS_NONE: format = CAIRO_FORMAT_A1; break;
case CAIRO_ANTIALIAS_SUBPIXEL: format = CAIRO_FORMAT_ARGB32; break;
}
surface = cairo_image_surface_create (format, width, height);
cairo_surface_set_device_offset (surface,
- _cairo_fixed_integer_floor (scaled_glyph->bbox.p1.x),
- _cairo_fixed_integer_floor (scaled_glyph->bbox.p1.y));
status = _cairo_meta_surface_replay (meta_surface, surface);
if (status) {
cairo_surface_destroy(surface);
return status;
}
_cairo_scaled_glyph_set_surface (scaled_glyph,
&scaled_font->base,
(cairo_image_surface_t *) surface);
}
if (info & CAIRO_SCALED_GLYPH_INFO_PATH) {
cairo_path_fixed_t *path = _cairo_path_fixed_create ();
if (!path)
return _cairo_error (CAIRO_STATUS_NO_MEMORY);
status = _cairo_meta_surface_get_path (meta_surface, path);
if (status) {
_cairo_path_fixed_destroy (path);
return status;
}
_cairo_scaled_glyph_set_path (scaled_glyph,
&scaled_font->base,
path);
}
return status;
}
static unsigned long
_cairo_user_ucs4_to_index (void *abstract_font,
uint32_t ucs4)
{
cairo_user_scaled_font_t *scaled_font = abstract_font;
cairo_user_font_face_t *face =
(cairo_user_font_face_t *) scaled_font->base.font_face;
unsigned long glyph = 0;
if (face->scaled_font_methods.unicode_to_glyph) {
cairo_status_t status;
status = face->scaled_font_methods.unicode_to_glyph (&scaled_font->base,
ucs4, &glyph);
if (status != CAIRO_STATUS_SUCCESS) {
status = _cairo_scaled_font_set_error (&scaled_font->base, status);
glyph = 0;
}
} else {
glyph = ucs4;
}
return glyph;
}
static cairo_int_status_t
_cairo_user_text_to_glyphs (void *abstract_font,
double x,
double y,
const char *utf8,
cairo_glyph_t **glyphs,
int *num_glyphs)
{
cairo_int_status_t status = CAIRO_INT_STATUS_UNSUPPORTED;
cairo_user_scaled_font_t *scaled_font = abstract_font;
cairo_user_font_face_t *face =
(cairo_user_font_face_t *) scaled_font->base.font_face;
if (face->scaled_font_methods.text_to_glyphs) {
int i;
*glyphs = NULL;
*num_glyphs = -1;
/* XXX currently user allocs glyphs array but cairo frees it */
status = face->scaled_font_methods.text_to_glyphs (&scaled_font->base,
utf8, glyphs, num_glyphs);
if (status != CAIRO_STATUS_SUCCESS) {
status = _cairo_scaled_font_set_error (&scaled_font->base, status);
if (*glyphs) {
free (*glyphs);
*glyphs = NULL;
}
return status;
}
if (*num_glyphs < 0)
return CAIRO_INT_STATUS_UNSUPPORTED;
/* Convert from font space to user space and add x,y */
for (i = 0; i < *num_glyphs; i++) {
double gx = (*glyphs)[i].x;
double gy = (*glyphs)[i].y;
cairo_matrix_transform_point (&scaled_font->base.font_matrix,
&gx, &gy);
(*glyphs)[i].x = gx + x;
(*glyphs)[i].y = gy + y;
}
}
return status;
}
static const cairo_scaled_font_backend_t cairo_user_scaled_font_backend = {
CAIRO_FONT_TYPE_USER,
NULL, /* create_toy */
NULL, /* scaled_font_fini */
_cairo_user_scaled_glyph_init,
_cairo_user_text_to_glyphs,
_cairo_user_ucs4_to_index,
NULL, /* show_glyphs */
NULL, /* load_truetype_table */
NULL, /* map_glyphs_to_unicode */
};
/* #cairo_user_font_face_t */
static cairo_status_t
_cairo_user_font_face_scaled_font_create (void *abstract_face,
const cairo_matrix_t *font_matrix,
const cairo_matrix_t *ctm,
const cairo_font_options_t *options,
cairo_scaled_font_t **scaled_font)
{
cairo_status_t status = CAIRO_STATUS_SUCCESS;
cairo_user_font_face_t *font_face = abstract_face;
cairo_user_scaled_font_t *user_scaled_font = NULL;
cairo_font_extents_t font_extents = {1., 0., 1., 1., 0.};
font_face->immutable = TRUE;
user_scaled_font = malloc (sizeof (cairo_user_scaled_font_t));
if (user_scaled_font == NULL)
return CAIRO_STATUS_NO_MEMORY;
status = _cairo_scaled_font_init (&user_scaled_font->base,
&font_face->base,
font_matrix, ctm, options,
&cairo_user_scaled_font_backend);
if (status) {
free (user_scaled_font);
return status;
}
/* XXX metrics hinting? */
/* compute a normalized version of font scale matrix to compute
* extents in. This is to minimize error caused by the cairo_fixed_t
* representation. */
{
double fixed_scale, x_scale, y_scale;
user_scaled_font->extent_scale = user_scaled_font->base.scale_inverse;
status = _cairo_matrix_compute_scale_factors (&user_scaled_font->extent_scale,
&x_scale, &y_scale,
1);
if (status == CAIRO_STATUS_SUCCESS) {
if (x_scale == 0) x_scale = 1.;
if (y_scale == 0) y_scale = 1.;
user_scaled_font->snap_x_scale = x_scale;
user_scaled_font->snap_y_scale = y_scale;
/* since glyphs are pretty much 1.0x1.0, we can reduce error by
* scaling to a larger square. say, 1024.x1024. */
fixed_scale = 1024.;
x_scale /= fixed_scale;
y_scale /= fixed_scale;
cairo_matrix_scale (&user_scaled_font->extent_scale, 1. / x_scale, 1. / y_scale);
user_scaled_font->extent_x_scale = x_scale;
user_scaled_font->extent_y_scale = y_scale;
}
}
if (status == CAIRO_STATUS_SUCCESS && font_face->scaled_font_methods.init != NULL) {
/* Lock the scaled_font mutex such that user doesn't accidentally try
* to use it just yet. */
CAIRO_MUTEX_LOCK (user_scaled_font->base.mutex);
/* Give away fontmap lock such that user-font can use other fonts */
_cairo_scaled_font_register_placeholder_and_unlock_font_map (&user_scaled_font->base);
status = font_face->scaled_font_methods.init (&user_scaled_font->base,
&font_extents);
_cairo_scaled_font_unregister_placeholder_and_lock_font_map (&user_scaled_font->base);
CAIRO_MUTEX_UNLOCK (user_scaled_font->base.mutex);
}
if (status == CAIRO_STATUS_SUCCESS)
status = _cairo_scaled_font_set_metrics (&user_scaled_font->base, &font_extents);
if (status != CAIRO_STATUS_SUCCESS) {
_cairo_scaled_font_fini (&user_scaled_font->base);
free (user_scaled_font);
} else {
user_scaled_font->default_glyph_extents.x_bearing = 0.;
user_scaled_font->default_glyph_extents.y_bearing = -font_extents.ascent;
user_scaled_font->default_glyph_extents.width = 0.;
user_scaled_font->default_glyph_extents.height = font_extents.ascent + font_extents.descent;
user_scaled_font->default_glyph_extents.x_advance = font_extents.max_x_advance;
user_scaled_font->default_glyph_extents.y_advance = 0.;
*scaled_font = &user_scaled_font->base;
}
return status;
}
static const cairo_font_face_backend_t _cairo_user_font_face_backend = {
CAIRO_FONT_TYPE_USER,
NULL, /* destroy */
_cairo_user_font_face_scaled_font_create
};
cairo_bool_t
_cairo_font_face_is_user (cairo_font_face_t *font_face)
{
return font_face->backend == &_cairo_user_font_face_backend;
}
/* Implement the public interface */
/**
* cairo_user_font_face_create:
*
* Creates a new user font-face.
*
* Use the setter functions to associate callbacks with the returned
* user font. The only mandatory callback is render_glyph.
*
* After the font-face is created, the user can attach arbitrary data
* (the actual font data) to it using cairo_font_face_set_user_data()
* and access it from the user-font callbacks by using
* cairo_scaled_font_get_font_face() followed by
* cairo_font_face_get_user_data().
*
* Return value: a newly created #cairo_font_face_t. Free with
* cairo_font_face_destroy() when you are done using it.
*
* Since: 1.8
**/
cairo_font_face_t *
cairo_user_font_face_create (void)
{
cairo_user_font_face_t *font_face;
font_face = malloc (sizeof (cairo_user_font_face_t));
if (!font_face) {
_cairo_error_throw (CAIRO_STATUS_NO_MEMORY);
return (cairo_font_face_t *)&_cairo_font_face_nil;
}
_cairo_font_face_init (&font_face->base, &_cairo_user_font_face_backend);
font_face->immutable = FALSE;
memset (&font_face->scaled_font_methods, 0, sizeof (font_face->scaled_font_methods));
return &font_face->base;
}
/* User-font method setters */
/**
* cairo_user_font_face_set_init_func:
* @font_face: A user font face
* @init_func: The init callback, or %NULL
*
* Sets the scaled-font initialization function of a user-font.
* See #cairo_user_scaled_font_init_func_t for details of how the callback
* works.
*
* The font-face should not be immutable or a %CAIRO_STATUS_USER_FONT_IMMUTABLE
* error will occur. A user font-face is immutable as soon as a scaled-font
* is created from it.
*
* Since: 1.8
**/
void
cairo_user_font_face_set_init_func (cairo_font_face_t *font_face,
cairo_user_scaled_font_init_func_t init_func)
{
cairo_user_font_face_t *user_font_face = (cairo_user_font_face_t *) font_face;
if (! _cairo_font_face_is_user (font_face)) {
if (_cairo_font_face_set_error (font_face, CAIRO_STATUS_FONT_TYPE_MISMATCH))
return;
}
if (user_font_face->immutable) {
if (_cairo_font_face_set_error (font_face, CAIRO_STATUS_USER_FONT_IMMUTABLE))
return;
}
user_font_face->scaled_font_methods.init = init_func;
}
/**
* cairo_user_font_face_set_render_glyph_func:
* @font_face: A user font face
* @render_glyph_func: The render_glyph callback, or %NULL
*
* Sets the glyph rendering function of a user-font.
* See #cairo_user_scaled_font_render_glyph_func_t for details of how the callback
* works.
*
* The font-face should not be immutable or a %CAIRO_STATUS_USER_FONT_IMMUTABLE
* error will occur. A user font-face is immutable as soon as a scaled-font
* is created from it.
*
* The render_glyph callback is the only mandatory callback of a user-font.
* If the callback is %NULL and a glyph is tried to be rendered using
* @font_face, a %CAIRO_STATUS_USER_FONT_ERROR will occur.
*
* Since: 1.8
**/
void
cairo_user_font_face_set_render_glyph_func (cairo_font_face_t *font_face,
cairo_user_scaled_font_render_glyph_func_t render_glyph_func)
{
cairo_user_font_face_t *user_font_face = (cairo_user_font_face_t *) font_face;
if (! _cairo_font_face_is_user (font_face)) {
if (_cairo_font_face_set_error (font_face, CAIRO_STATUS_FONT_TYPE_MISMATCH))
return;
}
if (user_font_face->immutable) {
if (_cairo_font_face_set_error (font_face, CAIRO_STATUS_USER_FONT_IMMUTABLE))
return;
}
user_font_face->scaled_font_methods.render_glyph = render_glyph_func;
}
/**
* cairo_user_font_face_set_text_to_glyphs_func:
* @font_face: A user font face
* @text_to_glyphs_func: The text_to_glyphs callback, or %NULL
*
* Sets th text-to-glyphs conversion function of a user-font.
* See #cairo_user_scaled_font_text_to_glyphs_func_t for details of how the callback
* works.
*
* The font-face should not be immutable or a %CAIRO_STATUS_USER_FONT_IMMUTABLE
* error will occur. A user font-face is immutable as soon as a scaled-font
* is created from it.
*
* Since: 1.8
**/
void
cairo_user_font_face_set_text_to_glyphs_func (cairo_font_face_t *font_face,
cairo_user_scaled_font_text_to_glyphs_func_t text_to_glyphs_func)
{
cairo_user_font_face_t *user_font_face = (cairo_user_font_face_t *) font_face;
if (! _cairo_font_face_is_user (font_face)) {
if (_cairo_font_face_set_error (font_face, CAIRO_STATUS_FONT_TYPE_MISMATCH))
return;
}
if (user_font_face->immutable) {
if (_cairo_font_face_set_error (font_face, CAIRO_STATUS_USER_FONT_IMMUTABLE))
return;
}
user_font_face->scaled_font_methods.text_to_glyphs = text_to_glyphs_func;
}
/**
* cairo_user_font_face_set_unicode_to_glyph_func:
* @font_face: A user font face
* @unicode_to_glyph_func: The unicode_to_glyph callback, or %NULL
*
* Sets the unicode-to-glyph conversion function of a user-font.
* See #cairo_user_scaled_font_unicode_to_glyph_func_t for details of how the callback
* works.
*
* The font-face should not be immutable or a %CAIRO_STATUS_USER_FONT_IMMUTABLE
* error will occur. A user font-face is immutable as soon as a scaled-font
* is created from it.
*
* Since: 1.8
**/
void
cairo_user_font_face_set_unicode_to_glyph_func (cairo_font_face_t *font_face,
cairo_user_scaled_font_unicode_to_glyph_func_t unicode_to_glyph_func)
{
cairo_user_font_face_t *user_font_face = (cairo_user_font_face_t *) font_face;
if (! _cairo_font_face_is_user (font_face)) {
if (_cairo_font_face_set_error (font_face, CAIRO_STATUS_FONT_TYPE_MISMATCH))
return;
}
if (user_font_face->immutable) {
if (_cairo_font_face_set_error (font_face, CAIRO_STATUS_USER_FONT_IMMUTABLE))
return;
}
user_font_face->scaled_font_methods.unicode_to_glyph = unicode_to_glyph_func;
}
/* User-font method getters */
/**
* cairo_user_font_face_get_init_func:
* @font_face: A user font face
*
* Gets the scaled-font initialization function of a user-font.
*
* Return value: The init callback of @font_face
* or %NULL if none set.
*
* Since: 1.8
**/
cairo_user_scaled_font_init_func_t
cairo_user_font_face_get_init_func (cairo_font_face_t *font_face)
{
cairo_user_font_face_t *user_font_face = (cairo_user_font_face_t *) font_face;
if (! _cairo_font_face_is_user (font_face)) {
if (_cairo_font_face_set_error (font_face, CAIRO_STATUS_FONT_TYPE_MISMATCH))
return NULL;
}
return user_font_face->scaled_font_methods.init;
}
/**
* cairo_user_font_face_get_render_glyph_func:
* @font_face: A user font face
*
* Gets the glyph rendering function of a user-font.
*
* Return value: The render_glyph callback of @font_face
* or %NULL if none set.
*
* Since: 1.8
**/
cairo_user_scaled_font_render_glyph_func_t
cairo_user_font_face_get_render_glyph_func (cairo_font_face_t *font_face)
{
cairo_user_font_face_t *user_font_face = (cairo_user_font_face_t *) font_face;
if (! _cairo_font_face_is_user (font_face)) {
if (_cairo_font_face_set_error (font_face, CAIRO_STATUS_FONT_TYPE_MISMATCH))
return NULL;
}
return user_font_face->scaled_font_methods.render_glyph;
}
/**
* cairo_user_font_face_get_text_to_glyphs_func:
* @font_face: A user font face
*
* Gets the text-to-glyphs conversion function of a user-font.
*
* Return value: The text_to_glyphs callback of @font_face
* or %NULL if none set.
*
* Since: 1.8
**/
cairo_user_scaled_font_text_to_glyphs_func_t
cairo_user_font_face_get_text_to_glyphs_func (cairo_font_face_t *font_face)
{
cairo_user_font_face_t *user_font_face = (cairo_user_font_face_t *) font_face;
if (! _cairo_font_face_is_user (font_face)) {
if (_cairo_font_face_set_error (font_face, CAIRO_STATUS_FONT_TYPE_MISMATCH))
return NULL;
}
return user_font_face->scaled_font_methods.text_to_glyphs;
}
/**
* cairo_user_font_face_get_unicode_to_glyph_func:
* @font_face: A user font face
*
* Gets the unicode-to-glyph conversion function of a user-font.
*
* Return value: The unicode_to_glyph callback of @font_face
* or %NULL if none set.
*
* Since: 1.8
**/
cairo_user_scaled_font_unicode_to_glyph_func_t
cairo_user_font_face_get_unicode_to_glyph_func (cairo_font_face_t *font_face)
{
cairo_user_font_face_t *user_font_face = (cairo_user_font_face_t *) font_face;
if (! _cairo_font_face_is_user (font_face)) {
if (_cairo_font_face_set_error (font_face, CAIRO_STATUS_FONT_TYPE_MISMATCH))
return NULL;
}
return user_font_face->scaled_font_methods.unicode_to_glyph;
}

Просмотреть файл

@ -78,22 +78,6 @@
#error Cannot find definitions for fixed-width integral types (uint8_t, uint32_t, etc.)
#endif
#if HAVE_BYTESWAP_H
# include <byteswap.h>
#endif
#ifndef bswap_16
# define bswap_16(p) \
(((((uint16_t)(p)) & 0x00ff) << 8) | \
(((uint16_t)(p)) >> 8));
#endif
#ifndef bswap_32
# define bswap_32(p) \
(((((uint32_t)(p)) & 0x000000ff) << 24) | \
((((uint32_t)(p)) & 0x0000ff00) << 8) | \
((((uint32_t)(p)) & 0x00ff0000) >> 8) | \
((((uint32_t)(p))) >> 24));
#endif
#if !HAVE_UINT64_T

Просмотреть файл

@ -61,7 +61,7 @@
#define CMAP_TAG 0x70616d63
const cairo_scaled_font_backend_t _cairo_win32_scaled_font_backend;
const cairo_scaled_font_backend_t cairo_win32_scaled_font_backend;
typedef struct {
cairo_scaled_font_t base;
@ -322,7 +322,7 @@ _win32_scaled_font_create (LOGFONTW *logfont,
status = _cairo_scaled_font_init (&f->base, font_face,
font_matrix, ctm, options,
&_cairo_win32_scaled_font_backend);
&cairo_win32_scaled_font_backend);
if (status)
goto FAIL;
@ -934,7 +934,7 @@ _cairo_win32_scaled_font_init_glyph_metrics (cairo_win32_scaled_font_t *scaled_f
extents.x_bearing = 0;
extents.y_bearing = scaled_font->base.ctm.yy * (-font_extents.ascent / scaled_font->y_scale);
extents.width = width / (WIN32_FONT_LOGICAL_SCALE * scaled_font->x_scale);
extents.width = width / scaled_font->x_scale;
extents.height = scaled_font->base.ctm.yy * (font_extents.ascent + font_extents.descent) / scaled_font->y_scale;
extents.x_advance = extents.width;
extents.y_advance = 0;
@ -1320,8 +1320,7 @@ _cairo_win32_scaled_font_show_glyphs (void *abstract_font,
unsigned int width,
unsigned int height,
cairo_glyph_t *glyphs,
int num_glyphs,
int *remaining_glyphs)
int num_glyphs)
{
cairo_win32_scaled_font_t *scaled_font = abstract_font;
cairo_win32_surface_t *surface = (cairo_win32_surface_t *)generic_surface;
@ -1436,7 +1435,7 @@ _cairo_win32_scaled_font_load_truetype_table (void *abstract_font,
unsigned long *length)
{
HDC hdc;
cairo_status_t status;
cairo_status_t status = CAIRO_STATUS_SUCCESS;
cairo_win32_scaled_font_t *scaled_font = abstract_font;
hdc = _get_global_font_dc ();
@ -1444,23 +1443,20 @@ _cairo_win32_scaled_font_load_truetype_table (void *abstract_font,
return _cairo_error (CAIRO_STATUS_NO_MEMORY);
tag = (tag&0x000000ff)<<24 | (tag&0x0000ff00)<<8 | (tag&0x00ff0000)>>8 | (tag&0xff000000)>>24;
status = cairo_win32_scaled_font_select_font (&scaled_font->base, hdc);
if (status)
return status;
status = _cairo_win32_scaled_font_select_unscaled_font (&scaled_font->base, hdc);
*length = GetFontData (hdc, tag, offset, buffer, *length);
if (*length == GDI_ERROR)
status = CAIRO_INT_STATUS_UNSUPPORTED;
cairo_win32_scaled_font_done_font (&scaled_font->base);
_cairo_win32_scaled_font_done_unscaled_font (&scaled_font->base);
return status;
}
static cairo_status_t
_cairo_win32_scaled_font_index_to_ucs4 (void *abstract_font,
unsigned long index,
uint32_t *ucs4)
static cairo_int_status_t
_cairo_win32_scaled_font_map_glyphs_to_unicode (void *abstract_font,
cairo_scaled_font_subset_t *font_subset)
{
cairo_win32_scaled_font_t *scaled_font = abstract_font;
GLYPHSET *glyph_set;
@ -1468,7 +1464,7 @@ _cairo_win32_scaled_font_index_to_ucs4 (void *abstract_font,
WORD *glyph_indices = NULL;
HDC hdc = NULL;
int res;
unsigned int i, j, num_glyphs;
unsigned int i, j, k, count, num_glyphs;
cairo_status_t status = CAIRO_STATUS_SUCCESS;
hdc = _get_global_font_dc ();
@ -1482,36 +1478,37 @@ _cairo_win32_scaled_font_index_to_ucs4 (void *abstract_font,
res = GetFontUnicodeRanges(hdc, NULL);
if (res == 0) {
status = _cairo_win32_print_gdi_error (
"_cairo_win32_scaled_font_index_to_ucs4:GetFontUnicodeRanges");
goto exit1;
"_cairo_win32_scaled_font_map_glyphs_to_unicode:GetFontUnicodeRanges");
goto fail1;
}
glyph_set = malloc (res);
if (glyph_set == NULL) {
status = _cairo_error (CAIRO_STATUS_NO_MEMORY);
goto exit1;
goto fail1;
}
res = GetFontUnicodeRanges(hdc, glyph_set);
if (res == 0) {
status = _cairo_win32_print_gdi_error (
"_cairo_win32_scaled_font_index_to_ucs4:GetFontUnicodeRanges");
goto exit1;
"_cairo_win32_scaled_font_map_glyphs_to_unicode:GetFontUnicodeRanges");
goto fail2;
}
for (i = 0; i < glyph_set->cRanges; i++) {
count = font_subset->num_glyphs;
for (i = 0; i < glyph_set->cRanges && count > 0; i++) {
num_glyphs = glyph_set->ranges[i].cGlyphs;
utf16 = _cairo_malloc_ab (num_glyphs + 1, sizeof (uint16_t));
if (utf16 == NULL) {
status = _cairo_error (CAIRO_STATUS_NO_MEMORY);
goto exit1;
goto fail2;
}
glyph_indices = _cairo_malloc_ab (num_glyphs + 1, sizeof (WORD));
if (glyph_indices == NULL) {
status = _cairo_error (CAIRO_STATUS_NO_MEMORY);
goto exit2;
goto fail2;
}
for (j = 0; j < num_glyphs; j++)
@ -1520,30 +1517,33 @@ _cairo_win32_scaled_font_index_to_ucs4 (void *abstract_font,
if (GetGlyphIndicesW (hdc, utf16, num_glyphs, glyph_indices, 0) == GDI_ERROR) {
status = _cairo_win32_print_gdi_error (
"_cairo_win32_scaled_font_index_to_ucs4:GetGlyphIndicesW");
goto exit2;
"_cairo_win32_scaled_font_map_glyphs_to_unicode:GetGlyphIndicesW");
goto fail2;
}
for (j = 0; j < num_glyphs; j++) {
if (glyph_indices[j] == index) {
*ucs4 = utf16[j];
goto exit2;
for (k = 0; k < font_subset->num_glyphs; k++) {
if (font_subset->glyphs[k] == glyph_indices[j]) {
font_subset->to_unicode[k] = utf16[j];
count--;
break;
}
}
}
free (glyph_indices);
glyph_indices = NULL;
free (utf16);
utf16 = NULL;
utf16= NULL;
}
exit2:
fail2:
if (glyph_indices)
free (glyph_indices);
if (utf16)
free (utf16);
free (glyph_set);
exit1:
fail1:
cairo_win32_scaled_font_done_font (&scaled_font->base);
return status;
@ -1775,7 +1775,7 @@ _cairo_win32_scaled_font_init_glyph_path (cairo_win32_scaled_font_t *scaled_font
return status;
}
const cairo_scaled_font_backend_t _cairo_win32_scaled_font_backend = {
const cairo_scaled_font_backend_t cairo_win32_scaled_font_backend = {
CAIRO_FONT_TYPE_WIN32,
_cairo_win32_scaled_font_create_toy,
_cairo_win32_scaled_font_fini,
@ -1784,7 +1784,7 @@ const cairo_scaled_font_backend_t _cairo_win32_scaled_font_backend = {
NULL, /* ucs4_to_index */
_cairo_win32_scaled_font_show_glyphs,
_cairo_win32_scaled_font_load_truetype_table,
_cairo_win32_scaled_font_index_to_ucs4,
_cairo_win32_scaled_font_map_glyphs_to_unicode,
};
/* #cairo_win32_font_face_t */
@ -1939,12 +1939,6 @@ cairo_win32_font_face_create_for_hfont (HFONT font)
return cairo_win32_font_face_create_for_logfontw_hfont (&logfont, font);
}
static cairo_bool_t
_cairo_scaled_font_is_win32 (cairo_scaled_font_t *scaled_font)
{
return scaled_font->backend == &_cairo_win32_scaled_font_backend;
}
/**
* cairo_win32_scaled_font_select_font:
* @scaled_font: A #cairo_scaled_font_t from the Win32 font backend. Such an
@ -1978,10 +1972,6 @@ cairo_win32_scaled_font_select_font (cairo_scaled_font_t *scaled_font,
HFONT old_hfont = NULL;
int old_mode;
if (! _cairo_scaled_font_is_win32 (scaled_font)) {
return _cairo_error (CAIRO_STATUS_FONT_TYPE_MISMATCH);
}
if (scaled_font->status)
return scaled_font->status;
@ -2021,9 +2011,6 @@ cairo_win32_scaled_font_select_font (cairo_scaled_font_t *scaled_font,
void
cairo_win32_scaled_font_done_font (cairo_scaled_font_t *scaled_font)
{
if (! _cairo_scaled_font_is_win32 (scaled_font)) {
_cairo_error_throw (CAIRO_STATUS_FONT_TYPE_MISMATCH);
}
}
/**
@ -2041,10 +2028,6 @@ cairo_win32_scaled_font_done_font (cairo_scaled_font_t *scaled_font)
double
cairo_win32_scaled_font_get_metrics_factor (cairo_scaled_font_t *scaled_font)
{
if (! _cairo_scaled_font_is_win32 (scaled_font)) {
_cairo_error_throw (CAIRO_STATUS_FONT_TYPE_MISMATCH);
return 1.;
}
return 1. / ((cairo_win32_scaled_font_t *)scaled_font)->logical_scale;
}
@ -2063,11 +2046,6 @@ cairo_win32_scaled_font_get_logical_to_device (cairo_scaled_font_t *scaled_font,
cairo_matrix_t *logical_to_device)
{
cairo_win32_scaled_font_t *win_font = (cairo_win32_scaled_font_t *)scaled_font;
if (! _cairo_scaled_font_is_win32 (scaled_font)) {
_cairo_error_throw (CAIRO_STATUS_FONT_TYPE_MISMATCH);
cairo_matrix_init_identity (logical_to_device);
return;
}
*logical_to_device = win_font->logical_to_device;
}
@ -2086,10 +2064,5 @@ cairo_win32_scaled_font_get_device_to_logical (cairo_scaled_font_t *scaled_font,
cairo_matrix_t *device_to_logical)
{
cairo_win32_scaled_font_t *win_font = (cairo_win32_scaled_font_t *)scaled_font;
if (! _cairo_scaled_font_is_win32 (scaled_font)) {
_cairo_error_throw (CAIRO_STATUS_FONT_TYPE_MISMATCH);
cairo_matrix_init_identity (device_to_logical);
return;
}
*device_to_logical = win_font->device_to_logical;
}

Просмотреть файл

@ -494,6 +494,7 @@ _cairo_win32_printing_surface_paint_image_pattern (cairo_win32_surface_t *surf
cairo_image_surface_t *image;
void *image_extra;
cairo_surface_t *opaque_surface;
cairo_pattern_union_t opaque_pattern;
cairo_image_surface_t *opaque_image = NULL;
BITMAPINFO bi;
cairo_matrix_t m;
@ -537,8 +538,6 @@ _cairo_win32_printing_surface_paint_image_pattern (cairo_win32_surface_t *surf
}
if (image->format != CAIRO_FORMAT_RGB24) {
cairo_surface_pattern_t opaque_pattern;
opaque_surface = cairo_image_surface_create (CAIRO_FORMAT_RGB24,
image->width,
image->height);
@ -547,7 +546,7 @@ _cairo_win32_printing_surface_paint_image_pattern (cairo_win32_surface_t *surf
goto FINISH3;
}
_cairo_pattern_init_for_surface (&opaque_pattern, &image->base);
_cairo_pattern_init_for_surface (&opaque_pattern.surface, &image->base);
status = _cairo_surface_fill_rectangle (opaque_surface,
CAIRO_OPERATOR_SOURCE,
@ -1294,8 +1293,7 @@ _cairo_win32_printing_surface_show_glyphs (void *abstract_surfac
cairo_pattern_t *source,
cairo_glyph_t *glyphs,
int num_glyphs,
cairo_scaled_font_t *scaled_font,
int *remaining_glyphs)
cairo_scaled_font_t *scaled_font)
{
cairo_win32_surface_t *surface = abstract_surface;
cairo_status_t status = CAIRO_STATUS_SUCCESS;
@ -1324,26 +1322,20 @@ _cairo_win32_printing_surface_show_glyphs (void *abstract_surfac
* non Windows fonts. ie filled outlines for Type 1 fonts and
* fallback images for bitmap fonts.
*/
if (cairo_scaled_font_get_type (scaled_font) == CAIRO_FONT_TYPE_WIN32) {
if (_cairo_win32_scaled_font_is_bitmap (scaled_font))
return CAIRO_INT_STATUS_UNSUPPORTED;
else
return _cairo_win32_printing_surface_analyze_operation (surface, op, source);
}
if (_cairo_win32_scaled_font_is_bitmap (scaled_font))
return CAIRO_INT_STATUS_UNSUPPORTED;
/* For non win32 fonts we need to check that each glyph has a
* path available. If a path is not available,
* _cairo_scaled_glyph_lookup() will return
* CAIRO_INT_STATUS_UNSUPPORTED and a fallback image will be
* used.
*/
for (i = 0; i < num_glyphs; i++) {
status = _cairo_scaled_glyph_lookup (scaled_font,
glyphs[i].index,
CAIRO_SCALED_GLYPH_INFO_PATH,
&scaled_glyph);
if (status)
return status;
if (!(cairo_scaled_font_get_type (scaled_font) == CAIRO_FONT_TYPE_WIN32 &&
! _cairo_win32_scaled_font_is_type1 (scaled_font) &&
source->type == CAIRO_PATTERN_TYPE_SOLID)) {
for (i = 0; i < num_glyphs; i++) {
status = _cairo_scaled_glyph_lookup (scaled_font,
glyphs[i].index,
CAIRO_SCALED_GLYPH_INFO_PATH,
&scaled_glyph);
if (status)
return status;
}
}
return _cairo_win32_printing_surface_analyze_operation (surface, op, source);
@ -1380,8 +1372,7 @@ _cairo_win32_printing_surface_show_glyphs (void *abstract_surfac
}
status = _cairo_win32_surface_show_glyphs (surface, op,
source, glyphs,
num_glyphs, scaled_font,
remaining_glyphs);
num_glyphs, scaled_font);
if (surface->has_ctm)
cairo_scaled_font_destroy (scaled_font);
@ -1502,14 +1493,11 @@ _cairo_win32_printing_surface_set_paginated_mode (void *abstract_surface,
* associated methods must be used for correct output.
*
* Return value: the newly created surface
*
* Since: 1.6
**/
cairo_surface_t *
cairo_win32_printing_surface_create (HDC hdc)
{
cairo_win32_surface_t *surface;
cairo_surface_t *paginated;
RECT rect;
surface = malloc (sizeof (cairo_win32_surface_t));
@ -1545,16 +1533,11 @@ cairo_win32_printing_surface_create (HDC hdc)
_cairo_surface_init (&surface->base, &cairo_win32_printing_surface_backend,
CAIRO_CONTENT_COLOR_ALPHA);
paginated = _cairo_paginated_surface_create (&surface->base,
CAIRO_CONTENT_COLOR_ALPHA,
surface->extents.width,
surface->extents.height,
&cairo_win32_surface_paginated_backend);
/* paginated keeps the only reference to surface now, drop ours */
cairo_surface_destroy (&surface->base);
return paginated;
return _cairo_paginated_surface_create (&surface->base,
CAIRO_CONTENT_COLOR_ALPHA,
surface->extents.width,
surface->extents.height,
&cairo_win32_surface_paginated_backend);
}
cairo_bool_t

Просмотреть файл

@ -36,8 +36,8 @@
#ifndef CAIRO_WIN32_PRIVATE_H
#define CAIRO_WIN32_PRIVATE_H
#include "cairo-win32.h"
#include "cairoint.h"
#include <cairo-win32.h>
#include <cairoint.h>
#ifndef SHADEBLENDCAPS
#define SHADEBLENDCAPS 120
@ -143,8 +143,7 @@ _cairo_win32_surface_show_glyphs (void *surface,
cairo_pattern_t *source,
cairo_glyph_t *glyphs,
int num_glyphs,
cairo_scaled_font_t *scaled_font,
int *remaining_glyphs);
cairo_scaled_font_t *scaled_font);
cairo_surface_t *
_cairo_win32_surface_create_similar (void *abstract_src,

Просмотреть файл

@ -48,7 +48,6 @@
#include "cairoint.h"
#include "cairo-clip-private.h"
#include "cairo-paginated-private.h"
#include "cairo-win32-private.h"
#include <windows.h>
@ -446,7 +445,7 @@ _cairo_win32_surface_clone_similar (void *abstract_surface,
cairo_content_t src_content;
cairo_surface_t *new_surface;
cairo_status_t status;
cairo_surface_pattern_t pattern;
cairo_pattern_union_t pattern;
src_content = cairo_surface_get_content(src);
new_surface =
@ -455,7 +454,7 @@ _cairo_win32_surface_clone_similar (void *abstract_surface,
if (cairo_surface_status(new_surface))
return cairo_surface_status(new_surface);
_cairo_pattern_init_for_surface (&pattern, src);
_cairo_pattern_init_for_surface (&pattern.surface, src);
status = _cairo_surface_composite (CAIRO_OPERATOR_SOURCE,
&pattern.base,
@ -1556,8 +1555,7 @@ _cairo_win32_surface_show_glyphs (void *surface,
cairo_pattern_t *source,
cairo_glyph_t *glyphs,
int num_glyphs,
cairo_scaled_font_t *scaled_font,
int *remaining_glyphs)
cairo_scaled_font_t *scaled_font)
{
#if CAIRO_HAS_WIN32_FONT
cairo_win32_surface_t *dst = surface;
@ -1707,6 +1705,7 @@ cairo_win32_surface_create (HDC hdc)
{
cairo_win32_surface_t *surface;
int depth;
cairo_format_t format;
RECT rect;
@ -1874,25 +1873,13 @@ cairo_win32_surface_get_dc (cairo_surface_t *surface)
{
cairo_win32_surface_t *winsurf;
if (_cairo_surface_is_win32 (surface)){
winsurf = (cairo_win32_surface_t *) surface;
if (!_cairo_surface_is_win32(surface) &&
!_cairo_surface_is_win32_printing(surface))
return NULL;
return winsurf->dc;
}
winsurf = (cairo_win32_surface_t *) surface;
if (_cairo_surface_is_paginated (surface)) {
cairo_surface_t *target;
target = _cairo_paginated_surface_get_target (surface);
if (_cairo_surface_is_win32_printing (target)) {
winsurf = (cairo_win32_surface_t *) target;
return winsurf->dc;
}
}
return NULL;
return winsurf->dc;
}
/**

Просмотреть файл

@ -37,7 +37,7 @@
#ifndef _CAIRO_WIN32_H_
#define _CAIRO_WIN32_H_
#include "cairo.h"
#include <cairo.h>
#if CAIRO_HAS_WIN32_SURFACE

Просмотреть файл

@ -1627,8 +1627,7 @@ _cairo_xcb_surface_show_glyphs (void *abstract_dst,
cairo_pattern_t *src_pattern,
cairo_glyph_t *glyphs,
int num_glyphs,
cairo_scaled_font_t *scaled_font,
int *remaining_glyphs);
cairo_scaled_font_t *scaled_font);
static cairo_bool_t
_cairo_xcb_surface_is_similar (void *surface_a,
@ -1856,7 +1855,7 @@ _cairo_xcb_screen_from_visual (xcb_connection_t *c, xcb_visualtype_t *visual)
* by the provided visual.
*
* Note: If @drawable is a window, then the function
* cairo_xcb_surface_set_size() must be called whenever the size of the
* cairo_xcb_surface_set_size must be called whenever the size of the
* window changes.
*
* Return value: the newly created surface
@ -1918,7 +1917,7 @@ cairo_xcb_surface_create_for_bitmap (xcb_connection_t *c,
* by the provided picture format.
*
* Note: If @drawable is a Window, then the function
* cairo_xcb_surface_set_size() must be called whenever the size of the
* cairo_xcb_surface_set_size must be called whenever the size of the
* window changes.
*
* Return value: the newly created surface.
@ -2311,8 +2310,7 @@ _cairo_xcb_surface_show_glyphs (void *abstract_dst,
cairo_pattern_t *src_pattern,
cairo_glyph_t *glyphs,
int num_glyphs,
cairo_scaled_font_t *scaled_font,
int *remaining_glyphs)
cairo_scaled_font_t *scaled_font)
{
cairo_int_status_t status = CAIRO_STATUS_SUCCESS;
cairo_xcb_surface_t *dst = abstract_dst;
@ -2332,7 +2330,7 @@ _cairo_xcb_surface_show_glyphs (void *abstract_dst,
cairo_xcb_surface_show_glyphs_func_t show_glyphs_func;
cairo_solid_pattern_t solid_pattern;
cairo_pattern_union_t solid_pattern;
if (!CAIRO_SURFACE_RENDER_HAS_COMPOSITE_TEXT (dst) || dst->xrender_format.id == XCB_NONE)
return CAIRO_INT_STATUS_UNSUPPORTED;
@ -2395,7 +2393,7 @@ _cairo_xcb_surface_show_glyphs (void *abstract_dst,
* so PictOpClear was never used with CompositeText before.
*/
if (op == CAIRO_OPERATOR_CLEAR) {
_cairo_pattern_init_solid (&solid_pattern, CAIRO_COLOR_WHITE,
_cairo_pattern_init_solid (&solid_pattern.solid, CAIRO_COLOR_WHITE,
CAIRO_CONTENT_COLOR);
src_pattern = &solid_pattern.base;
op = CAIRO_OPERATOR_DEST_OUT;

Просмотреть файл

@ -37,7 +37,7 @@
#ifndef CAIRO_XCB_XRENDER_H
#define CAIRO_XCB_XRENDER_H
#include "cairo.h"
#include <cairo.h>
#if CAIRO_HAS_XCB_SURFACE

Просмотреть файл

@ -37,7 +37,7 @@
#ifndef CAIRO_XCB_H
#define CAIRO_XCB_H
#include "cairo.h"
#include <cairo.h>
#if CAIRO_HAS_XCB_SURFACE

Просмотреть файл

@ -289,9 +289,6 @@ _cairo_xlib_display_get (Display *dpy)
display->close_display_hooks = NULL;
display->closed = FALSE;
memset (display->cached_xrender_formats, 0,
sizeof (display->cached_xrender_formats));
display->buggy_repeat = FALSE;
if (strstr (ServerVendor (dpy), "X.Org") != NULL) {
/* When modularized, the X.Org server VendorRelease was
@ -501,35 +498,3 @@ _cairo_xlib_display_notify (cairo_xlib_display_t *display)
}
CAIRO_MUTEX_UNLOCK (display->mutex);
}
XRenderPictFormat *
_cairo_xlib_display_get_xrender_format (cairo_xlib_display_t *display,
cairo_format_t format)
{
XRenderPictFormat *xrender_format;
CAIRO_MUTEX_LOCK (display->mutex);
xrender_format = display->cached_xrender_formats[format];
if (xrender_format == NULL) {
int pict_format;
switch (format) {
case CAIRO_FORMAT_A1:
pict_format = PictStandardA1; break;
case CAIRO_FORMAT_A8:
pict_format = PictStandardA8; break;
case CAIRO_FORMAT_RGB24:
pict_format = PictStandardRGB24; break;
default:
ASSERT_NOT_REACHED;
case CAIRO_FORMAT_ARGB32:
pict_format = PictStandardARGB32; break;
}
xrender_format = XRenderFindStandardFormat (display->display,
pict_format);
display->cached_xrender_formats[format] = xrender_format;
}
CAIRO_MUTEX_UNLOCK (display->mutex);
return xrender_format;
}

Просмотреть файл

@ -34,7 +34,6 @@
#define CAIRO_XLIB_PRIVATE_H
#include "cairo-xlib.h"
#include "cairo-xlib-xrender-private.h"
#include "cairo-compiler-private.h"
#include "cairo-freelist-private.h"
@ -62,8 +61,6 @@ struct _cairo_xlib_display {
Display *display;
cairo_xlib_screen_info_t *screens;
XRenderPictFormat *cached_xrender_formats[CAIRO_FORMAT_A1 + 1];
cairo_xlib_job_t *workqueue;
cairo_freelist_t wq_freelist;
@ -73,24 +70,15 @@ struct _cairo_xlib_display {
unsigned int closed :1;
};
/* size of color cube */
#define CUBE_SIZE 6
/* size of gray ramp */
#define RAMP_SIZE 16
typedef struct _cairo_xlib_visual_info {
VisualID visualid;
struct { uint8_t a, r, g, b; } colors[256];
uint8_t cube_to_pseudocolor[CUBE_SIZE][CUBE_SIZE][CUBE_SIZE];
uint8_t field8_to_cube[256];
int8_t dither8_to_cube[256];
uint8_t gray8_to_pseudocolor[256];
XColor colors[256];
unsigned long rgb333_to_pseudocolor[512];
} cairo_xlib_visual_info_t;
struct _cairo_xlib_screen_info {
cairo_xlib_screen_info_t *next;
cairo_reference_count_t ref_count;
cairo_mutex_t mutex;
cairo_xlib_display_t *display;
Screen *screen;
@ -129,10 +117,6 @@ _cairo_xlib_display_queue_resource (cairo_xlib_display_t *display,
cairo_private void
_cairo_xlib_display_notify (cairo_xlib_display_t *display);
cairo_private XRenderPictFormat *
_cairo_xlib_display_get_xrender_format (cairo_xlib_display_t *display,
cairo_format_t format);
cairo_private cairo_xlib_screen_info_t *
_cairo_xlib_screen_info_get (Display *display, Screen *screen);

Просмотреть файл

@ -111,10 +111,8 @@ get_integer_default (Display *dpy,
v = XGetDefault (dpy, "Xft", option);
if (v) {
#if CAIRO_HAS_FT_FONT
if (FcNameConstant ((FcChar8 *) v, value))
return TRUE;
#endif
i = strtol (v, &e, 0);
if (e != v)
@ -256,23 +254,14 @@ _cairo_xlib_screen_info_reference (cairo_xlib_screen_info_t *info)
void
_cairo_xlib_screen_info_close_display (cairo_xlib_screen_info_t *info)
{
cairo_xlib_visual_info_t **visuals;
int i;
CAIRO_MUTEX_LOCK (info->mutex);
for (i = 0; i < ARRAY_LENGTH (info->gc); i++) {
if (info->gc[i] != NULL) {
XFreeGC (info->display->display, info->gc[i]);
info->gc[i] = NULL;
}
}
visuals = _cairo_array_index (&info->visuals, 0);
for (i = 0; i < _cairo_array_num_elements (&info->visuals); i++)
_cairo_xlib_visual_info_destroy (info->display->display, visuals[i]);
_cairo_array_truncate (&info->visuals, 0);
CAIRO_MUTEX_UNLOCK (info->mutex);
}
void
@ -280,6 +269,8 @@ _cairo_xlib_screen_info_destroy (cairo_xlib_screen_info_t *info)
{
cairo_xlib_screen_info_t **prev;
cairo_xlib_screen_info_t *list;
cairo_xlib_visual_info_t **visuals;
int i;
assert (CAIRO_REFERENCE_COUNT_HAS_REFERENCE (&info->ref_count));
@ -293,6 +284,9 @@ _cairo_xlib_screen_info_destroy (cairo_xlib_screen_info_t *info)
break;
}
}
visuals = _cairo_array_index (&info->visuals, 0);
for (i = 0; i < _cairo_array_num_elements (&info->visuals); i++)
_cairo_xlib_visual_info_destroy (info->display->display, visuals[i]);
CAIRO_MUTEX_UNLOCK (info->display->mutex);
_cairo_xlib_screen_info_close_display (info);
@ -301,8 +295,6 @@ _cairo_xlib_screen_info_destroy (cairo_xlib_screen_info_t *info)
_cairo_array_fini (&info->visuals);
CAIRO_MUTEX_FINI (info->mutex);
free (info);
}
@ -343,7 +335,6 @@ _cairo_xlib_screen_info_get (Display *dpy, Screen *screen)
info = malloc (sizeof (cairo_xlib_screen_info_t));
if (info != NULL) {
CAIRO_REFERENCE_COUNT_INIT (&info->ref_count, 2); /* Add one for display cache */
CAIRO_MUTEX_INIT (info->mutex);
info->display = _cairo_xlib_display_reference (display);
info->screen = screen;
info->has_render = FALSE;
@ -394,19 +385,16 @@ GC
_cairo_xlib_screen_get_gc (cairo_xlib_screen_info_t *info, int depth)
{
GC gc;
cairo_bool_t needs_reset;
depth = depth_to_index (depth);
CAIRO_MUTEX_LOCK (info->mutex);
gc = info->gc[depth];
info->gc[depth] = NULL;
needs_reset = info->gc_needs_clip_reset & (1 << depth);
info->gc_needs_clip_reset &= ~(1 << depth);
CAIRO_MUTEX_UNLOCK (info->mutex);
if (needs_reset)
if (info->gc_needs_clip_reset & (1 << depth)) {
XSetClipMask(info->display->display, gc, None);
info->gc_needs_clip_reset &= ~(1 << depth);
}
return gc;
}
@ -415,25 +403,21 @@ cairo_status_t
_cairo_xlib_screen_put_gc (cairo_xlib_screen_info_t *info, int depth, GC gc, cairo_bool_t reset_clip)
{
cairo_status_t status = CAIRO_STATUS_SUCCESS;
GC oldgc;
depth = depth_to_index (depth);
CAIRO_MUTEX_LOCK (info->mutex);
oldgc = info->gc[depth];
if (info->gc[depth] != NULL) {
status = _cairo_xlib_display_queue_work (info->display,
(cairo_xlib_notify_func) XFreeGC,
info->gc[depth],
NULL);
}
info->gc[depth] = gc;
if (reset_clip)
info->gc_needs_clip_reset |= 1 << depth;
else
info->gc_needs_clip_reset &= ~(1 << depth);
CAIRO_MUTEX_UNLOCK (info->mutex);
if (oldgc != NULL) {
status = _cairo_xlib_display_queue_work (info->display,
(cairo_xlib_notify_func) XFreeGC,
oldgc,
NULL);
}
return status;
}
@ -443,12 +427,11 @@ _cairo_xlib_screen_get_visual_info (cairo_xlib_screen_info_t *info,
Visual *visual,
cairo_xlib_visual_info_t **out)
{
Display *dpy = info->display->display;
cairo_xlib_visual_info_t **visuals, *ret = NULL;
cairo_status_t status;
int i, n_visuals;
CAIRO_MUTEX_LOCK (info->mutex);
CAIRO_MUTEX_LOCK (info->display->mutex);
visuals = _cairo_array_index (&info->visuals, 0);
n_visuals = _cairo_array_num_elements (&info->visuals);
for (i = 0; i < n_visuals; i++) {
@ -457,28 +440,28 @@ _cairo_xlib_screen_get_visual_info (cairo_xlib_screen_info_t *info,
break;
}
}
CAIRO_MUTEX_UNLOCK (info->mutex);
CAIRO_MUTEX_UNLOCK (info->display->mutex);
if (ret != NULL) {
*out = ret;
return CAIRO_STATUS_SUCCESS;
}
status = _cairo_xlib_visual_info_create (dpy,
status = _cairo_xlib_visual_info_create (info->display->display,
XScreenNumberOfScreen (info->screen),
visual->visualid,
&ret);
if (status)
return status;
CAIRO_MUTEX_LOCK (info->mutex);
CAIRO_MUTEX_LOCK (info->display->mutex);
if (n_visuals != _cairo_array_num_elements (&info->visuals)) {
/* check that another thread has not added our visual */
int new_visuals = _cairo_array_num_elements (&info->visuals);
visuals = _cairo_array_index (&info->visuals, 0);
for (i = n_visuals; i < new_visuals; i++) {
if (visuals[i]->visualid == visual->visualid) {
_cairo_xlib_visual_info_destroy (dpy, ret);
_cairo_xlib_visual_info_destroy (info->display->display, ret);
ret = visuals[i];
break;
}
@ -487,10 +470,10 @@ _cairo_xlib_screen_get_visual_info (cairo_xlib_screen_info_t *info,
status = _cairo_array_append (&info->visuals, &ret);
} else
status = _cairo_array_append (&info->visuals, &ret);
CAIRO_MUTEX_UNLOCK (info->mutex);
CAIRO_MUTEX_UNLOCK (info->display->mutex);
if (status) {
_cairo_xlib_visual_info_destroy (dpy, ret);
_cairo_xlib_visual_info_destroy (info->display->display, ret);
return status;
}

Разница между файлами не показана из-за своего большого размера Загрузить разницу

Просмотреть файл

@ -66,16 +66,15 @@ _cairo_xlib_visual_info_create (Display *dpy,
Colormap colormap = DefaultColormap (dpy, screen);
XColor color;
int gray, red, green, blue;
int i, j, distance, min_distance = 0;
XColor colors[256];
unsigned short cube_index_to_short[CUBE_SIZE];
unsigned short ramp_index_to_short[RAMP_SIZE];
unsigned char gray_to_pseudocolor[RAMP_SIZE];
int i, index, distance, min_distance = 0;
for (i = 0; i < CUBE_SIZE; i++)
cube_index_to_short[i] = (0xffff * i + ((CUBE_SIZE-1)>>1)) / (CUBE_SIZE-1);
for (i = 0; i < RAMP_SIZE; i++)
ramp_index_to_short[i] = (0xffff * i + ((RAMP_SIZE-1)>>1)) / (RAMP_SIZE-1);
const unsigned short index5_to_short[5] = {
0x0000, 0x4000, 0x8000, 0xc000, 0xffff
};
const unsigned short index8_to_short[8] = {
0x0000, 0x2492, 0x4924, 0x6db6,
0x9249, 0xb6db, 0xdb6d, 0xffff
};
info = malloc (sizeof (cairo_xlib_visual_info_t));
if (info == NULL)
@ -83,11 +82,12 @@ _cairo_xlib_visual_info_create (Display *dpy,
info->visualid = visualid;
/* Allocate a gray ramp and a color cube.
* Give up as soon as failures start. */
for (gray = 0; gray < RAMP_SIZE; gray++) {
color.red = color.green = color.blue = ramp_index_to_short[gray];
/* Allocate a 16-entry gray ramp and a 5x5x5 color cube. Give up
* as soon as failures start. */
for (gray = 0; gray < 16; gray++) {
color.red = (gray << 12) | (gray << 8) | (gray << 4) | gray;
color.green = (gray << 12) | (gray << 8) | (gray << 4) | gray;
color.blue = (gray << 12) | (gray << 8) | (gray << 4) | gray;
if (! XAllocColor (dpy, colormap, &color))
goto DONE_ALLOCATE;
}
@ -95,12 +95,12 @@ _cairo_xlib_visual_info_create (Display *dpy,
/* XXX: Could do this in a more clever order to have the best
* possible results from early failure. Could also choose a cube
* uniformly distributed in a better space than RGB. */
for (red = 0; red < CUBE_SIZE; red++) {
for (green = 0; green < CUBE_SIZE; green++) {
for (blue = 0; blue < CUBE_SIZE; blue++) {
color.red = cube_index_to_short[red];
color.green = cube_index_to_short[green];
color.blue = cube_index_to_short[blue];
for (red = 0; red < 5; red++) {
for (green = 0; green < 5; green++) {
for (blue = 0; blue < 5; blue++) {
color.red = index5_to_short[red];
color.green = index5_to_short[green];
color.blue = index5_to_short[blue];
color.pixel = 0;
color.flags = 0;
color.pad = 0;
@ -111,68 +111,31 @@ _cairo_xlib_visual_info_create (Display *dpy,
}
DONE_ALLOCATE:
for (i = 0; i < ARRAY_LENGTH (colors); i++)
colors[i].pixel = i;
XQueryColors (dpy, colormap, colors, ARRAY_LENGTH (colors));
for (i = 0; i < ARRAY_LENGTH (info->colors); i++)
info->colors[i].pixel = i;
XQueryColors (dpy, colormap, info->colors, ARRAY_LENGTH (info->colors));
/* Search for nearest colors within allocated colormap. */
for (gray = 0; gray < RAMP_SIZE; gray++) {
for (i = 0; i < 256; i++) {
distance = _color_distance (ramp_index_to_short[gray],
ramp_index_to_short[gray],
ramp_index_to_short[gray],
colors[i].red,
colors[i].green,
colors[i].blue);
if (i == 0 || distance < min_distance) {
gray_to_pseudocolor[gray] = colors[i].pixel;
min_distance = distance;
if (!min_distance)
break;
}
}
}
for (red = 0; red < CUBE_SIZE; red++) {
for (green = 0; green < CUBE_SIZE; green++) {
for (blue = 0; blue < CUBE_SIZE; blue++) {
for (red = 0; red < 8; red++) {
for (green = 0; green < 8; green++) {
for (blue = 0; blue < 8; blue++) {
index = (red << 6) | (green << 3) | (blue);
for (i = 0; i < 256; i++) {
distance = _color_distance (cube_index_to_short[red],
cube_index_to_short[green],
cube_index_to_short[blue],
colors[i].red,
colors[i].green,
colors[i].blue);
distance = _color_distance (index8_to_short[red],
index8_to_short[green],
index8_to_short[blue],
info->colors[i].red,
info->colors[i].green,
info->colors[i].blue);
if (i == 0 || distance < min_distance) {
info->cube_to_pseudocolor[red][green][blue] = colors[i].pixel;
info->rgb333_to_pseudocolor[index] = info->colors[i].pixel;
min_distance = distance;
if (!min_distance)
break;
}
}
}
}
}
for (i = 0, j = 0; i < 256; i++) {
if (j < CUBE_SIZE - 1 && (((i<<8)+i) - (int)cube_index_to_short[j]) > ((int)cube_index_to_short[j+1] - ((i<<8)+i)))
j++;
info->field8_to_cube[i] = j;
info->dither8_to_cube[i] = ((int)i - 128) / (CUBE_SIZE - 1);
}
for (i = 0, j = 0; i < 256; i++) {
if (j < RAMP_SIZE - 1 && (((i<<8)+i) - (int)ramp_index_to_short[j]) > ((int)ramp_index_to_short[j+1] - ((i<<8)+i)))
j++;
info->gray8_to_pseudocolor[i] = gray_to_pseudocolor[j];
}
for (i = 0; i < 256; i++) {
info->colors[i].a = 0xff;
info->colors[i].r = colors[i].red >> 8;
info->colors[i].g = colors[i].green >> 8;
info->colors[i].b = colors[i].blue >> 8;
}
*out = info;
return CAIRO_STATUS_SUCCESS;
}

Некоторые файлы не были показаны из-за слишком большого количества измененных файлов Показать больше