зеркало из https://github.com/mozilla/gecko-dev.git
Backed out changeset 20534cf9abf5
This commit is contained in:
Родитель
f477c5b702
Коммит
3651538cb6
|
@ -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, ®ion->rgn))
|
||||
if (! pixman_image_set_clip_region (surface->pixman_image, ®ion->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 (®ion->rgn);
|
||||
pixman_region_init (®ion->rgn);
|
||||
}
|
||||
|
||||
void
|
||||
_cairo_region_init_rect (cairo_region_t *region,
|
||||
cairo_rectangle_int_t *rect)
|
||||
{
|
||||
pixman_region32_init_rect (®ion->rgn,
|
||||
pixman_region_init_rect (®ion->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 (®ion->rgn, pboxes, count))
|
||||
if (!pixman_region_init_rects (®ion->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 (®ion->rgn);
|
||||
pixman_region_fini (®ion->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 (®ion->rgn);
|
||||
return pixman_region_n_rects (®ion->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 (®ion->rgn, &nboxes);
|
||||
pboxes = pixman_region_rectangles (®ion->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 (®ion->rgn);
|
||||
pixman_box16_t *pextents = pixman_region_extents (®ion->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 (®ion->rgn);
|
||||
return (cairo_bool_t) pixman_region_not_empty (®ion->rgn);
|
||||
}
|
||||
|
||||
void
|
||||
_cairo_region_translate (cairo_region_t *region,
|
||||
int x, int y)
|
||||
{
|
||||
pixman_region32_translate (®ion->rgn, x, y);
|
||||
pixman_region_translate (®ion->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 (®ion->rgn, &pbox);
|
||||
return pixman_region_contains_rectangle (®ion->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;
|
||||
}
|
||||
|
|
Некоторые файлы не были показаны из-за слишком большого количества измененных файлов Показать больше
Загрузка…
Ссылка в новой задаче