b=354388, Update cairo to cairo 2006-09-26 trunk, r=me

This commit is contained in:
vladimir%pobox.com 2006-09-26 22:21:56 +00:00
Родитель fe0ff2999b
Коммит aa06e7a53f
85 изменённых файлов: 6594 добавлений и 5460 удалений

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

@ -1,312 +0,0 @@
Index: gfx/cairo/cairo/src/cairo.h
===================================================================
RCS file: /home/rocallahan/mozilla-cvs-mirror/mozilla/gfx/cairo/cairo/src/cairo.h,v
retrieving revision 1.9
diff -u -t -p -1 -2 -r1.9 cairo.h
--- gfx/cairo/cairo/src/cairo.h 10 Feb 2006 02:20:34 -0000 1.9
+++ gfx/cairo/cairo/src/cairo.h 21 Feb 2006 23:17:08 -0000
@@ -1129,24 +1129,42 @@ cairo_public cairo_path_t *
cairo_copy_path (cairo_t *cr);
cairo_public cairo_path_t *
cairo_copy_path_flat (cairo_t *cr);
cairo_public void
cairo_append_path (cairo_t *cr,
cairo_path_t *path);
cairo_public void
cairo_path_destroy (cairo_path_t *path);
+/**
+ * cairo_clip_rect_t:
+ *
+ * A data structure for holding clip rectangles.
+ */
+typedef struct _cairo_clip_rect {
+ double x, y, width, height;
+} cairo_clip_rect_t;
+
+cairo_public cairo_bool_t
+cairo_has_clip (cairo_t *cr);
+
+cairo_public cairo_bool_t
+cairo_extract_clip_rectangles (cairo_t *cr,
+ int max_rectangles,
+ cairo_clip_rect_t *rectangles_out,
+ int *num_rectangles_out);
+
/* Error status queries */
cairo_public cairo_status_t
cairo_status (cairo_t *cr);
cairo_public const char *
cairo_status_to_string (cairo_status_t status);
/* Surface manipulation */
cairo_public cairo_surface_t *
cairo_surface_create_similar (cairo_surface_t *other,
Index: gfx/cairo/cairo/src/cairoint.h
===================================================================
RCS file: /home/rocallahan/mozilla-cvs-mirror/mozilla/gfx/cairo/cairo/src/cairoint.h,v
retrieving revision 1.19
diff -u -t -p -1 -2 -r1.19 cairoint.h
--- gfx/cairo/cairo/src/cairoint.h 10 Feb 2006 02:51:12 -0000 1.19
+++ gfx/cairo/cairo/src/cairoint.h 21 Feb 2006 23:18:00 -0000
@@ -1229,24 +1229,33 @@ cairo_private cairo_status_t
_cairo_gstate_in_fill (cairo_gstate_t *gstate,
cairo_path_fixed_t *path,
double x,
double y,
cairo_bool_t *inside_ret);
cairo_private cairo_status_t
_cairo_gstate_clip (cairo_gstate_t *gstate, cairo_path_fixed_t *path);
cairo_private cairo_status_t
_cairo_gstate_reset_clip (cairo_gstate_t *gstate);
+cairo_private cairo_bool_t
+_cairo_gstate_has_clip (cairo_gstate_t *gstate);
+
+cairo_private cairo_bool_t
+_cairo_gstate_extract_clip_rectangles (cairo_gstate_t *gstate,
+ int max_rectangles,
+ cairo_clip_rect_t *rectangles_out,
+ int *num_rectangles_out);
+
cairo_private cairo_status_t
_cairo_gstate_show_surface (cairo_gstate_t *gstate,
cairo_surface_t *surface,
double x,
double y,
double width,
double height);
cairo_private cairo_status_t
_cairo_gstate_select_font_face (cairo_gstate_t *gstate,
const char *family,
cairo_font_slant_t slant,
Index: gfx/cairo/cairo/src/cairo-clip-private.h
===================================================================
RCS file: /home/rocallahan/mozilla-cvs-mirror/mozilla/gfx/cairo/cairo/src/cairo-clip-private.h,v
retrieving revision 1.2
diff -u -t -p -1 -2 -r1.2 cairo-clip-private.h
--- gfx/cairo/cairo/src/cairo-clip-private.h 10 Jan 2006 22:56:38 -0000 1.2
+++ gfx/cairo/cairo/src/cairo-clip-private.h 7 Feb 2006 22:44:42 -0000
@@ -105,13 +105,22 @@ _cairo_clip_intersect_to_rectangle (cair
cairo_private cairo_status_t
_cairo_clip_intersect_to_region (cairo_clip_t *clip,
pixman_region16_t *region);
cairo_private cairo_status_t
_cairo_clip_combine_to_surface (cairo_clip_t *clip,
cairo_operator_t op,
cairo_surface_t *dst,
int dst_x,
int dst_y,
const cairo_rectangle_t *extents);
+cairo_private cairo_bool_t
+_cairo_clip_has_clip (cairo_clip_t *clip);
+
+cairo_private cairo_bool_t
+_cairo_clip_extract_rectangles (cairo_clip_t *clip,
+ int max_rectangles,
+ cairo_clip_rect_t *rectangles_out,
+ int *num_rectangles_out);
+
#endif /* CAIRO_CLIP_PRIVATE_H */
Index: gfx/cairo/cairo/src/cairo-clip.c
===================================================================
RCS file: /home/rocallahan/mozilla-cvs-mirror/mozilla/gfx/cairo/cairo/src/cairo-clip.c,v
retrieving revision 1.3
diff -u -t -p -1 -2 -r1.3 cairo-clip.c
--- gfx/cairo/cairo/src/cairo-clip.c 10 Jan 2006 22:56:38 -0000 1.3
+++ gfx/cairo/cairo/src/cairo-clip.c 21 Feb 2006 23:19:34 -0000
@@ -450,12 +450,62 @@ _cairo_clip_clip (cairo_clip_t *cl
status = _cairo_clip_intersect_region (clip, &traps, target);
if (status != CAIRO_INT_STATUS_UNSUPPORTED)
goto bail;
status = _cairo_clip_intersect_mask (clip, &traps, antialias, target);
bail:
_cairo_traps_fini (&traps);
return status;
}
+
+cairo_bool_t
+_cairo_clip_has_clip (cairo_clip_t *clip)
+{
+ return clip->region != NULL || clip->surface != NULL || clip->path != NULL;
+}
+
+static cairo_bool_t
+_cairo_region_to_clip_rectangles (pixman_region16_t *region,
+ int max_rectangles,
+ cairo_clip_rect_t *rectangles_out,
+ int *num_rectangles_out)
+{
+ int n_boxes, i;
+ pixman_box16_t *boxes;
+
+ /* no region -> we can't represent it as rectangles */
+ if (region == NULL)
+ return FALSE;
+
+ n_boxes = pixman_region_num_rects (region);
+ *num_rectangles_out = n_boxes;
+ if (n_boxes > max_rectangles)
+ return FALSE;
+
+ boxes = pixman_region_rects (region);
+
+ for (i = 0; i < n_boxes; i++) {
+ rectangles_out[i].x = boxes[i].x1;
+ rectangles_out[i].y = boxes[i].y1;
+ rectangles_out[i].width = boxes[i].x2 - boxes[i].x1;
+ rectangles_out[i].height = boxes[i].y2 - boxes[i].y1;
+ }
+
+ return TRUE;
+}
+
+cairo_bool_t
+_cairo_clip_extract_rectangles (cairo_clip_t *clip,
+ int max_rectangles,
+ cairo_clip_rect_t *rectangles_out,
+ int *num_rectangles_out)
+{
+ /* can't handle paths or surfaces for now */
+ if (clip->path != NULL || clip->surface != NULL)
+ return FALSE;
+
+ return _cairo_region_to_clip_rectangles (clip->region,
+ max_rectangles, rectangles_out, num_rectangles_out);
+}
Index: gfx/cairo/cairo/src/cairo-gstate.c
===================================================================
RCS file: /home/rocallahan/mozilla-cvs-mirror/mozilla/gfx/cairo/cairo/src/cairo-gstate.c,v
retrieving revision 1.4
diff -u -t -p -1 -2 -r1.4 cairo-gstate.c
--- gfx/cairo/cairo/src/cairo-gstate.c 10 Jan 2006 22:56:38 -0000 1.4
+++ gfx/cairo/cairo/src/cairo-gstate.c 21 Feb 2006 23:18:13 -0000
@@ -1174,24 +1174,42 @@ _cairo_gstate_reset_clip (cairo_gstate_t
{
return _cairo_clip_reset (&gstate->clip);
}
cairo_status_t
_cairo_gstate_clip (cairo_gstate_t *gstate, cairo_path_fixed_t *path)
{
return _cairo_clip_clip (&gstate->clip,
path, gstate->fill_rule, gstate->tolerance,
gstate->antialias, gstate->target);
}
+cairo_bool_t
+_cairo_gstate_has_clip (cairo_gstate_t *gstate)
+{
+ return _cairo_clip_has_clip (&gstate->clip);
+}
+
+cairo_bool_t
+_cairo_gstate_extract_clip_rectangles (cairo_gstate_t *gstate,
+ int max_rectangles,
+ cairo_clip_rect_t *rectangles_out,
+ int *num_rectangles_out)
+{
+ return _cairo_clip_extract_rectangles (&gstate->clip,
+ max_rectangles,
+ rectangles_out,
+ num_rectangles_out);
+}
+
static void
_cairo_gstate_unset_scaled_font (cairo_gstate_t *gstate)
{
if (gstate->scaled_font) {
cairo_scaled_font_destroy (gstate->scaled_font);
gstate->scaled_font = NULL;
}
}
cairo_status_t
_cairo_gstate_select_font_face (cairo_gstate_t *gstate,
const char *family,
Index: gfx/cairo/cairo/src/cairo.c
===================================================================
RCS file: /home/rocallahan/mozilla-cvs-mirror/mozilla/gfx/cairo/cairo/src/cairo.c,v
retrieving revision 1.11
diff -u -t -p -1 -2 -r1.11 cairo.c
--- gfx/cairo/cairo/src/cairo.c 10 Feb 2006 02:56:14 -0000 1.11
+++ gfx/cairo/cairo/src/cairo.c 21 Feb 2006 23:17:34 -0000
@@ -2575,24 +2575,63 @@ cairo_get_group_target (cairo_t *cr)
* with it.
**/
cairo_path_t *
cairo_copy_path (cairo_t *cr)
{
if (cr->status)
return (cairo_path_t*) &_cairo_path_nil;
return _cairo_path_data_create (&cr->path, cr->gstate);
}
/**
+ * cairo_has_clip
+ * @cr: a cairo context
+ *
+ * Returns TRUE if the cairo context has any clipping active, otherwise
+ * FALSE.
+ */
+cairo_bool_t
+cairo_has_clip (cairo_t *cr)
+{
+ if (cr->status)
+ return FALSE;
+ return _cairo_gstate_has_clip (cr->gstate);
+}
+
+/**
+ * cairo_extract_clip_rectangles
+ * @cr: a cairo context
+ * @max_rectangles: the maximum number of rectangles to be returned
+ * @rectangles_out: the output buffer for the rectangles
+ * @num_rectangles_out: the number of rectangles returned
+ *
+ * If the current clip can be expressed as the union of at most
+ * 'max_rectangles' device-coordinate rectangles, then we fill in the array
+ * with the rectangles, and return True. Otherwise we return False. When there
+ * is no clipping active, we return False.
+ */
+cairo_bool_t
+cairo_extract_clip_rectangles (cairo_t *cr,
+ int max_rectangles,
+ cairo_clip_rect_t *rectangles_out,
+ int *num_rectangles_out)
+{
+ if (cr->status)
+ return FALSE;
+ return _cairo_gstate_extract_clip_rectangles (cr->gstate, max_rectangles,
+ rectangles_out, num_rectangles_out);
+}
+
+/**
* cairo_copy_path_flat:
* @cr: a cairo context
*
* Gets a flattened copy of the current path and returns it to the
* user as a #cairo_path_t. See #cairo_path_data_t for hints on
* how to iterate over the returned data structure.
*
* This function is like cairo_copy_path() except that any curves
* in the path will be approximated with piecewise-linear
* approximations, (accurate to within the current tolerance
* value). That is, the result is guaranteed to not have any elements
* of type %CAIRO_PATH_CURVE_TO which will instead be replaced by a

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

@ -1,245 +0,0 @@
Index: src/cairo-debug.c
===================================================================
--- src/cairo-debug.c.orig
+++ src/cairo-debug.c
@@ -35,6 +35,8 @@
#include "cairoint.h"
+#include "cairo-clip-private.h"
+
/**
* cairo_debug_reset_static_data:
*
@@ -70,3 +72,192 @@ cairo_debug_reset_static_data (void)
#endif
}
+/*
+ * clip dumper
+ */
+void
+cairo_debug_dump_clip (struct _cairo_clip *clip,
+ FILE *fp)
+{
+ fprintf (fp, "clip %p: %s ", (clip->mode == CAIRO_CLIP_MODE_PATH ? "PATH" :
+ clip->mode == CAIRO_CLIP_MODE_REGION ? "REGION" :
+ clip->mode == CAIRO_CLIP_MODE_MASK ? "MASK" :
+ "INVALID?!"));
+ if (clip->mode == CAIRO_CLIP_MODE_PATH) {
+ fprintf (fp, "\n=== clip path ===\n");
+ } else if (clip->mode == CAIRO_CLIP_MODE_REGION) {
+ if (!clip->region) {
+ fprintf (fp, "region = NULL");
+ } else if (pixman_region_num_rects (clip->region) == 1) {
+ pixman_box16_t *rects = pixman_region_rects (clip->region);
+ fprintf (fp, "region [%d %d %d %d]",
+ rects[0].x1, rects[0].y1,
+ rects[0].x2, rects[0].y2);
+ } else {
+ pixman_box16_t *rects = pixman_region_rects (clip->region);
+ int i, nr = pixman_region_num_rects(clip->region);
+ fprintf (fp, "region (%d rects)\n", nr);
+ for (i = 0; i < nr; i++) {
+ fprintf (fp, "rect %d: [%d %d %d %d]", i,
+ rects[nr].x1, rects[nr].y1,
+ rects[nr].x2, rects[nr].y2);
+ }
+ }
+ } else if (clip->mode == CAIRO_CLIP_MODE_MASK) {
+ fprintf (fp, "mask, surface: %p rect: [%d %d %d %d]", clip->surface,
+ clip->surface_rect.x, clip->surface_rect.y, clip->surface_rect.width, clip->surface_rect.height);
+ }
+
+ fprintf (fp, "\n");
+}
+
+/*
+ * path dumper
+ */
+
+typedef struct _cairo_debug_path_dump_closure {
+ unsigned int op_count;
+ FILE *fp;
+} cairo_debug_path_dump_closure_t;
+
+static cairo_status_t
+_cairo_debug_path_move_to (void *closure,
+ cairo_point_t *point)
+{
+ cairo_debug_path_dump_closure_t *fdc =
+ (cairo_debug_path_dump_closure_t*) closure;
+ fprintf (fdc->fp, "%d: moveto (%f, %f)\n",
+ fdc->op_count++,
+ _cairo_fixed_to_double(point->x),
+ _cairo_fixed_to_double(point->y));
+ return CAIRO_STATUS_SUCCESS;
+}
+
+static cairo_status_t
+_cairo_debug_path_line_to (void *closure,
+ cairo_point_t *point)
+{
+ cairo_debug_path_dump_closure_t *fdc =
+ (cairo_debug_path_dump_closure_t*) closure;
+ fprintf (fdc->fp, "%d: lineto (%f, %f)\n",
+ fdc->op_count++,
+ _cairo_fixed_to_double(point->x),
+ _cairo_fixed_to_double(point->y));
+ return CAIRO_STATUS_SUCCESS;
+}
+
+static cairo_status_t
+_cairo_debug_path_curve_to (void *closure,
+ cairo_point_t *p0,
+ cairo_point_t *p1,
+ cairo_point_t *p2)
+{
+ cairo_debug_path_dump_closure_t *fdc =
+ (cairo_debug_path_dump_closure_t*) closure;
+ fprintf (fdc->fp, "%d: curveto (%f, %f) (%f, %f) (%f, %f)\n",
+ fdc->op_count++,
+ _cairo_fixed_to_double(p0->x),
+ _cairo_fixed_to_double(p0->y),
+ _cairo_fixed_to_double(p1->x),
+ _cairo_fixed_to_double(p1->y),
+ _cairo_fixed_to_double(p2->x),
+ _cairo_fixed_to_double(p2->y));
+ return CAIRO_STATUS_SUCCESS;
+}
+
+static cairo_status_t
+_cairo_debug_path_close_path (void *closure)
+{
+ cairo_debug_path_dump_closure_t *fdc =
+ (cairo_debug_path_dump_closure_t*) closure;
+ fprintf (fdc->fp, "%d: close\n",
+ fdc->op_count++);
+ return CAIRO_STATUS_SUCCESS;
+}
+
+/**
+ * cairo_debug_dump_path
+ * @path: a #cairo_path_fixed_t
+ * @fp: the file pointer where to dump the given path
+ *
+ * Dumps @path in human-readable form to @fp.
+ */
+void
+cairo_debug_dump_path (cairo_path_fixed_t *path,
+ FILE *fp)
+{
+ cairo_debug_path_dump_closure_t fdc;
+ fdc.fp = fp;
+ fdc.op_count = 0;
+
+ fprintf (fp, "=== path %p ===\n", path);
+ _cairo_path_fixed_interpret (path,
+ CAIRO_DIRECTION_FORWARD,
+ _cairo_debug_path_move_to,
+ _cairo_debug_path_line_to,
+ _cairo_debug_path_curve_to,
+ _cairo_debug_path_close_path,
+ &fdc);
+ fprintf (fp, "======================\n");
+}
+
+/*
+ * traps dumping
+ */
+
+/**
+ * cairo_debug_dump_traps
+ * @traps: a #cairo_traps_t
+ * @fp: the file pointer where to dump the traps
+ *
+ * Dumps @traps in human-readable form to @fp.
+ */
+void
+cairo_debug_dump_traps (cairo_traps_t *traps,
+ FILE *fp)
+{
+ fprintf (fp, "=== traps %p ===\n", traps);
+ fprintf (fp, "extents: (%f, %f) (%f, %f)\n",
+ _cairo_fixed_to_double (traps->extents.p1.x),
+ _cairo_fixed_to_double (traps->extents.p1.y),
+ _cairo_fixed_to_double (traps->extents.p2.x),
+ _cairo_fixed_to_double (traps->extents.p2.y));
+
+ cairo_debug_dump_trapezoid_array (traps->traps,
+ traps->num_traps,
+ fp);
+
+ fprintf (fp, "=======================\n");
+}
+
+/**
+ * cairo_debug_dump_trapezoid_array
+ * @traps: a #cairo_trapezoid_t pointer
+ * @num_traps: the number of trapezoids in @traps
+ * @fp: the file pointer where to dump the traps
+ *
+ * Dumps num_traps in the @traps array in human-readable form to @fp.
+ */
+void
+cairo_debug_dump_trapezoid_array (cairo_trapezoid_t *traps,
+ int num_traps,
+ FILE *fp)
+{
+ int i;
+
+ for (i = 0; i < num_traps; i++) {
+ fprintf (fp, "% 3d: t: %f b: %f l: (%f,%f)->(%f,%f) r: (%f,%f)->(%f,%f)\n",
+ i,
+ _cairo_fixed_to_double (traps[i].top),
+ _cairo_fixed_to_double (traps[i].bottom),
+ _cairo_fixed_to_double (traps[i].left.p1.x),
+ _cairo_fixed_to_double (traps[i].left.p1.y),
+ _cairo_fixed_to_double (traps[i].left.p2.x),
+ _cairo_fixed_to_double (traps[i].left.p2.y),
+ _cairo_fixed_to_double (traps[i].right.p1.x),
+ _cairo_fixed_to_double (traps[i].right.p1.y),
+ _cairo_fixed_to_double (traps[i].right.p2.x),
+ _cairo_fixed_to_double (traps[i].right.p2.y));
+ }
+}
+
Index: src/cairo-debug.h
===================================================================
--- src/cairo-debug.h.orig
+++ src/cairo-debug.h
@@ -37,12 +37,34 @@
#define CAIRO_DEBUG_H
#include <cairo-features.h>
+#include <stdio.h>
CAIRO_BEGIN_DECLS
+struct _cairo_path_fixed;
+struct _cairo_traps;
+struct _cairo_trapezoid;
+struct _cairo_clip;
+
void
cairo_debug_reset_static_data (void);
+void
+cairo_debug_dump_clip (struct _cairo_clip *clip,
+ FILE *fp);
+void
+cairo_debug_dump_path (struct _cairo_path_fixed *path,
+ FILE *fp);
+
+void
+cairo_debug_dump_traps (struct _cairo_traps *traps,
+ FILE *fp);
+
+void
+cairo_debug_dump_trapezoid_array (struct _cairo_trapezoid *traps,
+ int num_traps,
+ FILE *fp);
+
CAIRO_END_DECLS
#endif /* CAIRO_H */

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

@ -102,7 +102,7 @@ CSRCS = \
cairo-wideint.c \
$(NULL)
EXPORTS = cairo.h cairo-features.h cairo-platform.h cairo-rename.h
EXPORTS = cairo.h cairo-features.h cairo-platform.h cairo-deprecated.h cairo-rename.h
ifeq ($(MOZ_WIDGET_TOOLKIT),windows)
@ -132,11 +132,12 @@ EXPORTS += cairo-beos.h
endif
ifeq ($(MOZ_WIDGET_TOOLKIT),gtk2)
CSRCS += cairo-font-subset.c \
cairo-base85-stream.c \
CSRCS += cairo-base85-stream.c \
cairo-pdf-surface.c \
cairo-ps-surface.c \
cairo-type1-subset.c
cairo-type1-subset.c \
cairo-type1-fallback.c \
cairo-truetype-subset.c
EXPORTS += cairo-ps.h cairo-pdf.h
endif
@ -172,3 +173,9 @@ FORCE_STATIC_LIB = 1
FORCE_USE_PIC = 1
include $(topsrcdir)/config/rules.mk
DEFINES += -DPACKAGE_VERSION="\"moz\"" -DPACKAGE_BUGREPORT="\"http://bugzilla.mozilla.org/\""
ifeq ($(MOZ_WIDGET_TOOLKIT),windows)
DEFINES += -DCAIRO_WIN32_STATIC_BUILD
endif

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

@ -231,7 +231,7 @@ _cairo_arc_in_direction (cairo_t *cr,
}
/**
* _cairo_arc_path_negative:
* _cairo_arc_path
* @cr: a cairo context
* @xc: X position of the center of the arc
* @yc: Y position of the center of the arc
@ -266,7 +266,7 @@ _cairo_arc_path (cairo_t *cr,
* @angle2: the end angle, in radians
* @ctm: the current transformation matrix
* @tolerance: the current tolerance value
* @path: the path onto which th earc will be appended
* @path: the path onto which the arc will be appended
*
* Compute a path for the given arc (defined in the negative
* direction) and append it onto the current path within @cr. The arc

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

@ -159,7 +159,7 @@ _cairo_array_grow_by (cairo_array_t *array, int additional)
* beyond @num_elements are simply "forgotten".
**/
void
_cairo_array_truncate (cairo_array_t *array, int num_elements)
_cairo_array_truncate (cairo_array_t *array, unsigned int num_elements)
{
assert (! array->is_snapshot);
@ -187,7 +187,7 @@ _cairo_array_truncate (cairo_array_t *array, int num_elements)
* ... use values[i] here ...
**/
void *
_cairo_array_index (cairo_array_t *array, int index)
_cairo_array_index (cairo_array_t *array, unsigned int index)
{
/* We allow an index of 0 for the no-elements case.
* This makes for cleaner calling code which will often look like:
@ -203,7 +203,7 @@ _cairo_array_index (cairo_array_t *array, int index)
if (index == 0 && array->num_elements == 0)
return NULL;
assert (0 <= index && index < array->num_elements);
assert (index < array->num_elements);
return (void *) &(*array->elements)[index * array->element_size];
}
@ -287,7 +287,7 @@ _cairo_array_append_multiple (cairo_array_t *array,
**/
cairo_status_t
_cairo_array_allocate (cairo_array_t *array,
int num_elements,
unsigned int num_elements,
void **elements)
{
cairo_status_t status;
@ -318,6 +318,18 @@ _cairo_array_num_elements (cairo_array_t *array)
return array->num_elements;
}
/**
* _cairo_array_size:
*
* Return value: The number of elements for which there is currently
* space allocated in array.
**/
int
_cairo_array_size (cairo_array_t *array)
{
return array->size;
}
/* cairo_user_data_array_t */
typedef struct {

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

@ -227,22 +227,30 @@ _cairo_atsui_font_create_scaled (cairo_font_face_t *font_face,
font->style = CreateSizedCopyOfStyle(style, &font->base.scale);
Fixed theSize = FloatToFixed(1.0);
const ATSUAttributeTag theFontStyleTags[] = { kATSUSizeTag };
const ByteCount theFontStyleSizes[] = { sizeof(Fixed) };
ATSUAttributeValuePtr theFontStyleValues[] = { &theSize };
err = ATSUSetAttributes(style,
sizeof(theFontStyleTags) /
sizeof(ATSUAttributeTag), theFontStyleTags,
theFontStyleSizes, theFontStyleValues);
{
Fixed theSize = FloatToFixed(1.0);
const ATSUAttributeTag theFontStyleTags[] = { kATSUSizeTag };
const ByteCount theFontStyleSizes[] = { sizeof(Fixed) };
ATSUAttributeValuePtr theFontStyleValues[] = { &theSize };
err = ATSUSetAttributes(style,
sizeof(theFontStyleTags) /
sizeof(ATSUAttributeTag), theFontStyleTags,
theFontStyleSizes, theFontStyleValues);
if (err != noErr) {
status = CAIRO_STATUS_NO_MEMORY;
goto FAIL;
}
}
font->unscaled_style = style;
font->fontID = font_id;
*font_out = &font->base;
status = _cairo_atsui_font_set_metrics (font);
FAIL:
if (status) {
cairo_scaled_font_destroy (&font->base);
return status;
@ -318,15 +326,17 @@ _cairo_atsui_font_create_toy(cairo_toy_font_face_t *toy_face,
kFontNoLanguageCode, &fontID);
}
ATSUAttributeTag styleTags[] =
{ kATSUQDItalicTag, kATSUQDBoldfaceTag, kATSUFontTag };
ATSUAttributeValuePtr styleValues[] = { &isItalic, &isBold, &fontID };
ByteCount styleSizes[] =
{ sizeof(Boolean), sizeof(Boolean), sizeof(ATSUFontID) };
{
ATSUAttributeTag styleTags[] =
{ kATSUQDItalicTag, kATSUQDBoldfaceTag, kATSUFontTag };
ATSUAttributeValuePtr styleValues[] = { &isItalic, &isBold, &fontID };
ByteCount styleSizes[] =
{ sizeof(Boolean), sizeof(Boolean), sizeof(ATSUFontID) };
err = ATSUSetAttributes(style,
sizeof(styleTags) / sizeof(styleTags[0]),
styleTags, styleSizes, styleValues);
err = ATSUSetAttributes(style,
sizeof(styleTags) / sizeof(styleTags[0]),
styleTags, styleSizes, styleValues);
}
return _cairo_atsui_font_create_scaled (&toy_face->base, fontID, style,
font_matrix, ctm, options, font_out);
@ -580,6 +590,10 @@ _cairo_atsui_font_old_show_glyphs (void *abstract_font,
cairo_bool_t can_draw_directly;
cairo_rectangle_int16_t rect;
ATSFontRef atsFont;
CGFontRef cgFont;
CGAffineTransform textTransform;
/* Check if we can draw directly to the destination surface */
can_draw_directly = _cairo_surface_is_quartz (generic_surface) &&
_cairo_pattern_is_opaque_solid (pattern) &&
@ -637,14 +651,12 @@ _cairo_atsui_font_old_show_glyphs (void *abstract_font,
CGContextSaveGState (drawingContext);
}
ATSFontRef atsFont = FMGetATSFontRefFromFont(font->fontID);
CGFontRef cgFont = CGFontCreateWithPlatformFont(&atsFont);
atsFont = FMGetATSFontRefFromFont(font->fontID);
cgFont = CGFontCreateWithPlatformFont(&atsFont);
CGContextSetFont(drawingContext, cgFont);
CGAffineTransform textTransform =
CGAffineTransformMakeWithCairoFontScale(&font->base.scale);
textTransform = CGAffineTransformMakeWithCairoFontScale(&font->base.scale);
textTransform = CGAffineTransformScale(textTransform, 1.0f, -1.0f);
CGContextSetFontSize(drawingContext, 1.0);

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

@ -38,6 +38,8 @@
#include "cairo-path-fixed-private.h"
extern cairo_private const cairo_rectangle_list_t _cairo_rectangles_nil;
struct _cairo_clip_path {
unsigned int ref_count;
cairo_path_fixed_t path;
@ -124,13 +126,7 @@ _cairo_clip_translate (cairo_clip_t *clip,
cairo_fixed_t tx,
cairo_fixed_t ty);
cairo_private cairo_bool_t
_cairo_clip_has_clip (cairo_clip_t *clip);
cairo_private cairo_bool_t
_cairo_clip_extract_rectangles (cairo_clip_t *clip,
int max_rectangles,
cairo_clip_rect_t *rectangles_out,
int *num_rectangles_out);
cairo_private cairo_rectangle_list_t*
_cairo_clip_copy_rectangles (cairo_clip_t *clip, cairo_gstate_t *gstate);
#endif /* CAIRO_CLIP_PRIVATE_H */

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

@ -118,6 +118,39 @@ _cairo_clip_reset (cairo_clip_t *clip)
return CAIRO_STATUS_SUCCESS;
}
static cairo_status_t
_cairo_clip_path_intersect_to_rectangle (cairo_clip_path_t *clip_path,
cairo_rectangle_int16_t *rectangle)
{
while (clip_path) {
cairo_status_t status;
cairo_traps_t traps;
cairo_box_t extents;
cairo_rectangle_int16_t extents_rect;
_cairo_traps_init (&traps);
status = _cairo_path_fixed_fill_to_traps (&clip_path->path,
clip_path->fill_rule,
clip_path->tolerance,
&traps);
if (status) {
_cairo_traps_fini (&traps);
return status;
}
_cairo_traps_extents (&traps, &extents);
_cairo_box_round_to_rectangle (&extents, &extents_rect);
_cairo_rectangle_intersect (rectangle, &extents_rect);
_cairo_traps_fini (&traps);
clip_path = clip_path->prev;
}
return CAIRO_STATUS_SUCCESS;
}
cairo_status_t
_cairo_clip_intersect_to_rectangle (cairo_clip_t *clip,
cairo_rectangle_int16_t *rectangle)
@ -126,7 +159,12 @@ _cairo_clip_intersect_to_rectangle (cairo_clip_t *clip,
return CAIRO_STATUS_SUCCESS;
if (clip->path) {
/* Intersect path extents here. */
cairo_status_t status;
status = _cairo_clip_path_intersect_to_rectangle (clip->path,
rectangle);
if (status)
return status;
}
if (clip->region) {
@ -535,52 +573,89 @@ _cairo_clip_init_deep_copy (cairo_clip_t *clip,
}
}
cairo_bool_t
_cairo_clip_has_clip (cairo_clip_t *clip)
{
return clip->region != NULL || clip->surface != NULL || clip->path != NULL;
}
const cairo_rectangle_list_t _cairo_rectangles_nil =
{ CAIRO_STATUS_NO_MEMORY, NULL, 0 };
static const cairo_rectangle_list_t _cairo_rectangles_not_representable =
{ CAIRO_STATUS_CLIP_NOT_REPRESENTABLE, NULL, 0 };
static cairo_bool_t
_cairo_region_to_clip_rectangles (pixman_region16_t *region,
int max_rectangles,
cairo_clip_rect_t *rectangles_out,
int *num_rectangles_out)
_cairo_clip_rect_to_user (cairo_gstate_t *gstate,
double x, double y, double width, double height,
cairo_rectangle_t *rectangle)
{
int n_boxes, i;
pixman_box16_t *boxes;
double x2 = x + width;
double y2 = y + height;
cairo_bool_t is_tight;
/* no region -> we can't represent it as rectangles */
if (region == NULL)
return FALSE;
_cairo_gstate_backend_to_user_rectangle (gstate, &x, &y, &x2, &y2, &is_tight);
rectangle->x = x;
rectangle->y = y;
rectangle->width = x2 - x;
rectangle->height = y2 - y;
return is_tight;
}
n_boxes = pixman_region_num_rects (region);
*num_rectangles_out = n_boxes;
if (n_boxes > max_rectangles)
return FALSE;
cairo_private cairo_rectangle_list_t*
_cairo_clip_copy_rectangles (cairo_clip_t *clip, cairo_gstate_t *gstate)
{
cairo_rectangle_list_t *list;
cairo_rectangle_t *rectangles;
int n_boxes;
boxes = pixman_region_rects (region);
for (i = 0; i < n_boxes; i++) {
rectangles_out[i].x = boxes[i].x1;
rectangles_out[i].y = boxes[i].y1;
rectangles_out[i].width = boxes[i].x2 - boxes[i].x1;
rectangles_out[i].height = boxes[i].y2 - boxes[i].y1;
if (clip->path || clip->surface)
return (cairo_rectangle_list_t*) &_cairo_rectangles_not_representable;
n_boxes = clip->region ? pixman_region_num_rects (clip->region) : 1;
rectangles = malloc (sizeof (cairo_rectangle_t)*n_boxes);
if (rectangles == NULL)
return (cairo_rectangle_list_t*) &_cairo_rectangles_nil;
if (clip->region) {
pixman_box16_t *boxes;
int i;
boxes = pixman_region_rects (clip->region);
for (i = 0; i < n_boxes; ++i) {
if (!_cairo_clip_rect_to_user(gstate, boxes[i].x1, boxes[i].y1,
boxes[i].x2 - boxes[i].x1,
boxes[i].y2 - boxes[i].y1,
&rectangles[i])) {
free (rectangles);
return (cairo_rectangle_list_t*)
&_cairo_rectangles_not_representable;
}
}
} else {
cairo_rectangle_int16_t extents;
_cairo_surface_get_extents (_cairo_gstate_get_target (gstate), &extents);
if (!_cairo_clip_rect_to_user(gstate, extents.x, extents.y,
extents.width, extents.height,
rectangles)) {
free (rectangles);
return (cairo_rectangle_list_t*)
&_cairo_rectangles_not_representable;
}
}
return TRUE;
list = malloc (sizeof (cairo_rectangle_list_t));
if (list == NULL) {
free (rectangles);
return (cairo_rectangle_list_t*) &_cairo_rectangles_nil;
}
list->status = CAIRO_STATUS_SUCCESS;
list->rectangles = rectangles;
list->num_rectangles = n_boxes;
return list;
}
cairo_bool_t
_cairo_clip_extract_rectangles (cairo_clip_t *clip,
int max_rectangles,
cairo_clip_rect_t *rectangles_out,
int *num_rectangles_out)
void
cairo_rectangle_list_destroy (cairo_rectangle_list_t *rectangle_list)
{
/* can't handle paths or surfaces for now */
if (clip->path != NULL || clip->surface != NULL)
return FALSE;
return _cairo_region_to_clip_rectangles (clip->region,
max_rectangles, rectangles_out, num_rectangles_out);
if (rectangle_list == NULL || rectangle_list == &_cairo_rectangles_nil ||
rectangle_list == &_cairo_rectangles_not_representable)
return;
free (rectangle_list->rectangles);
free (rectangle_list);
}

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

@ -0,0 +1,139 @@
/* cairo - a vector graphics library with display and print output
*
* Copyright © 2006 Red Hat, Inc.
*
* This library is free software; you can redistribute it and/or
* modify it either under the terms of the GNU Lesser General Public
* License version 2.1 as published by the Free Software Foundation
* (the "LGPL") or, at your option, under the terms of the Mozilla
* Public License Version 1.1 (the "MPL"). If you do not alter this
* notice, a recipient may use your version of this file under either
* the MPL or the LGPL.
*
* You should have received a copy of the LGPL along with this library
* in the file COPYING-LGPL-2.1; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
* You should have received a copy of the MPL along with this library
* in the file COPYING-MPL-1.1
*
* The contents of this file are subject to the Mozilla Public License
* Version 1.1 (the "License"); you may not use this file except in
* compliance with the License. You may obtain a copy of the License at
* http://www.mozilla.org/MPL/
*
* This software is distributed on an "AS IS" basis, WITHOUT WARRANTY
* OF ANY KIND, either express or implied. See the LGPL or the MPL for
* the specific language governing rights and limitations.
*
* The Original Code is the cairo graphics library.
*
* The Initial Developer of the Original Code is Red Hat, Inc.
*
* Contributor(s):
* Carl D. Worth <cworth@cworth.org>
*/
#ifndef CAIRO_DEPRECATED_H
#define CAIRO_DEPRECATED_H
/* The CAIRO_FORMAT_RGB16_565 value was added in cairo 1.2.0 as part
* of fixing cairo's xlib backend to work with X servers advertising a
* 16-bit, 565 visual. But as it turned out, adding this format to
* #cairo_format_t was not necessary, and was a mistake, (cairo's xlib
* backend can work fine with 16-bit visuals in the same way it works
* with BGR visuals without any BGR formats in
* #cairo_format_t).
*
* Additionally, the support for the RGB16_565 format was never
* completely implemented. So while this format value is currently
* deprecated, it may eventually acquire complete support in the future.
*/
#define CAIRO_FORMAT_RGB16_565 4
#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
* having to dig through lots of documentation.
*
* The first set of REPLACED_BY functions is for functions whose names
* have just been changed. So fixing these up is mechanical, (and
* automated by means of the cairo/util/cairo-api-update script.
*
* The second set of DEPRECATED_BY functions is for functions where
* the replacement is used in a different way, (ie. different
* arguments, multiple functions instead of one, etc). Fixing these up
* will require a bit more work on the user's part, (and hopefully we
* can get cairo-api-update to find these and print some guiding
* information).
*/
#define cairo_current_font_extents cairo_current_font_extents_REPLACED_BY_cairo_font_extents
#define cairo_get_font_extents cairo_get_font_extents_REPLACED_BY_cairo_font_extents
#define cairo_current_operator cairo_current_operator_REPLACED_BY_cairo_get_operator
#define cairo_current_tolerance cairo_current_tolerance_REPLACED_BY_cairo_get_tolerance
#define cairo_current_point cairo_current_point_REPLACED_BY_cairo_get_current_point
#define cairo_current_fill_rule cairo_current_fill_rule_REPLACED_BY_cairo_get_fill_rule
#define cairo_current_line_width cairo_current_line_width_REPLACED_BY_cairo_get_line_width
#define cairo_current_line_cap cairo_current_line_cap_REPLACED_BY_cairo_get_line_cap
#define cairo_current_line_join cairo_current_line_join_REPLACED_BY_cairo_get_line_join
#define cairo_current_miter_limit cairo_current_miter_limit_REPLACED_BY_cairo_get_miter_limit
#define cairo_current_matrix cairo_current_matrix_REPLACED_BY_cairo_get_matrix
#define cairo_current_target_surface cairo_current_target_surface_REPLACED_BY_cairo_get_target
#define cairo_get_status cairo_get_status_REPLACED_BY_cairo_status
#define cairo_concat_matrix cairo_concat_matrix_REPLACED_BY_cairo_transform
#define cairo_scale_font cairo_scale_font_REPLACED_BY_cairo_set_font_size
#define cairo_select_font cairo_select_font_REPLACED_BY_cairo_select_font_face
#define cairo_transform_font cairo_transform_font_REPLACED_BY_cairo_set_font_matrix
#define cairo_transform_point cairo_transform_point_REPLACED_BY_cairo_user_to_device
#define cairo_transform_distance cairo_transform_distance_REPLACED_BY_cairo_user_to_device_distance
#define cairo_inverse_transform_point cairo_inverse_transform_point_REPLACED_BY_cairo_device_to_user
#define cairo_inverse_transform_distance cairo_inverse_transform_distance_REPLACED_BY_cairo_device_to_user_distance
#define cairo_init_clip cairo_init_clip_REPLACED_BY_cairo_reset_clip
#define cairo_surface_create_for_image cairo_surface_create_for_image_REPLACED_BY_cairo_image_surface_create_for_data
#define cairo_default_matrix cairo_default_matrix_REPLACED_BY_cairo_identity_matrix
#define cairo_matrix_set_affine cairo_matrix_set_affine_REPLACED_BY_cairo_matrix_init
#define cairo_matrix_set_identity cairo_matrix_set_identity_REPLACED_BY_cairo_matrix_init_identity
#define cairo_pattern_add_color_stop cairo_pattern_add_color_stop_REPLACED_BY_cairo_pattern_add_color_stop_rgba
#define cairo_set_rgb_color cairo_set_rgb_color_REPLACED_BY_cairo_set_source_rgb
#define cairo_set_pattern cairo_set_pattern_REPLACED_BY_cairo_set_source
#define cairo_xlib_surface_create_for_pixmap_with_visual cairo_xlib_surface_create_for_pixmap_with_visual_REPLACED_BY_cairo_xlib_surface_create
#define cairo_xlib_surface_create_for_window_with_visual cairo_xlib_surface_create_for_window_with_visual_REPLACED_BY_cairo_xlib_surface_create
#define cairo_xcb_surface_create_for_pixmap_with_visual cairo_xcb_surface_create_for_pixmap_with_visual_REPLACED_BY_cairo_xcb_surface_create
#define cairo_xcb_surface_create_for_window_with_visual cairo_xcb_surface_create_for_window_with_visual_REPLACED_BY_cairo_xcb_surface_create
#define cairo_ps_surface_set_dpi cairo_ps_surface_set_dpi_REPLACED_BY_cairo_surface_set_fallback_resolution
#define cairo_pdf_surface_set_dpi cairo_pdf_surface_set_dpi_REPLACED_BY_cairo_surface_set_fallback_resolution
#define cairo_svg_surface_set_dpi cairo_svg_surface_set_dpi_REPLACED_BY_cairo_surface_set_fallback_resolution
#define cairo_current_path cairo_current_path_DEPRECATED_BY_cairo_copy_path
#define cairo_current_path_flat cairo_current_path_flat_DEPRECATED_BY_cairo_copy_path_flat
#define cairo_get_path cairo_get_path_DEPRECATED_BY_cairo_copy_path
#define cairo_get_path_flat cairo_get_path_flat_DEPRECATED_BY_cairo_get_path_flat
#define cairo_set_alpha cairo_set_alpha_DEPRECATED_BY_cairo_set_source_rgba_OR_cairo_paint_with_alpha
#define cairo_show_surface cairo_show_surface_DEPRECATED_BY_cairo_set_source_surface_AND_cairo_paint
#define cairo_copy cairo_copy_DEPRECATED_BY_cairo_create_AND_MANY_INDIVIDUAL_FUNCTIONS
#define cairo_surface_set_repeat cairo_surface_set_repeat_DEPRECATED_BY_cairo_pattern_set_extend
#define cairo_surface_set_matrix cairo_surface_set_matrix_DEPRECATED_BY_cairo_pattern_set_matrix
#define cairo_surface_get_matrix cairo_surface_get_matrix_DEPRECATED_BY_cairo_pattern_get_matrix
#define cairo_surface_set_filter cairo_surface_set_filter_DEPRECATED_BY_cairo_pattern_set_filter
#define cairo_surface_get_filter cairo_surface_get_filter_DEPRECATED_BY_cairo_pattern_get_filter
#define cairo_matrix_create cairo_matrix_create_DEPRECATED_BY_cairo_matrix_t
#define cairo_matrix_destroy cairo_matrix_destroy_DEPRECATED_BY_cairo_matrix_t
#define cairo_matrix_copy cairo_matrix_copy_DEPRECATED_BY_cairo_matrix_t
#define cairo_matrix_get_affine cairo_matrix_get_affine_DEPRECATED_BY_cairo_matrix_t
#define cairo_set_target_surface cairo_set_target_surface_DEPRECATED_BY_cairo_create
#define cairo_set_target_glitz cairo_set_target_glitz_DEPRECATED_BY_cairo_glitz_surface_create
#define cairo_set_target_image cairo_set_target_image_DEPRECATED_BY_cairo_image_surface_create_for_data
#define cairo_set_target_pdf cairo_set_target_pdf_DEPRECATED_BY_cairo_pdf_surface_create
#define cairo_set_target_png cairo_set_target_png_DEPRECATED_BY_cairo_surface_write_to_png
#define cairo_set_target_ps cairo_set_target_ps_DEPRECATED_BY_cairo_ps_surface_create
#define cairo_set_target_quartz cairo_set_target_quartz_DEPRECATED_BY_cairo_quartz_surface_create
#define cairo_set_target_win32 cairo_set_target_win32_DEPRECATED_BY_cairo_win32_surface_create
#define cairo_set_target_xcb cairo_set_target_xcb_DEPRECATED_BY_cairo_xcb_surface_create
#define cairo_set_target_drawable cairo_set_target_drawable_DEPRECATED_BY_cairo_xlib_surface_create
#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 */

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

@ -38,6 +38,7 @@
#include <stdio.h>
#include <stdlib.h>
#include <math.h>
#include <assert.h>
#include <directfb.h>
@ -50,15 +51,20 @@
#include "cairoint.h"
/*
* Rectangle works fine.
*/
#define DFB_RECTANGLES 1
/*
* Composite works fine.
*/
#define DFB_COMPOSITE 1
#define DFB_COMPOSITE 1
/*
* CompositeTrapezoids works (without antialiasing).
*/
#define DFB_COMPOSITE_TRAPEZOIDS 1
#define DFB_COMPOSITE_TRAPEZOIDS 0
/*
* ShowGlyphs works fine.
@ -73,31 +79,24 @@ D_DEBUG_DOMAIN (Cairo_DirectFB, "Cairo/DirectFB", "Cairo DirectFB backend");
typedef struct _cairo_directfb_surface {
cairo_surface_t base;
cairo_format_t format;
IDirectFB *dfb;
IDirectFBSurface *surface;
IDirectFBSurface *buffer;
int owner;
IDirectFBSurface *dfbsurface;
/* color buffer */
cairo_surface_t *color;
DFBRegion *clips;
int n_clips;
cairo_surface_t *buffer_image;
DFBRegion *dirty_region;
int width;
int height;
bool local;
} cairo_directfb_surface_t;
typedef struct _cairo_directfb_font_cache {
IDirectFB *dfb;
IDirectFBSurface *buffer;
IDirectFBSurface *dfbsurface;
int width;
int height;
@ -132,17 +131,17 @@ static cairo_surface_backend_t cairo_directfb_surface_backend;
reg.x2 = cli->x2;\
if (reg.y2 > cli->y2)\
reg.y2 = cli->y2;\
(surface)->buffer->SetClip ((surface)->buffer, &reg);\
(surface)->dfbsurface->SetClip ((surface)->dfbsurface, &reg);\
}\
else {\
(surface)->buffer->SetClip ((surface)->buffer,\
(surface)->dfbsurface->SetClip ((surface)->dfbsurface,\
&(surface)->clips[k]);\
}\
func;\
}\
}\
else {\
(surface)->buffer->SetClip ((surface)->buffer, clip);\
(surface)->dfbsurface->SetClip ((surface)->dfbsurface, clip);\
func;\
}\
}
@ -325,78 +324,77 @@ _directfb_buffer_surface_create (IDirectFB *dfb,
static cairo_status_t
_directfb_acquire_surface (cairo_directfb_surface_t *surface,
DFBSurfaceLockFlags lock_flags)
cairo_rectangle_int16_t *intrest_rec,
cairo_image_surface_t **image_out,
cairo_rectangle_int16_t *image_rect_out,
void **image_extra,
DFBSurfaceLockFlags lock_flags)
{
if (!surface->local) {
int width, height;
surface->surface->GetSize (surface->surface, &width, &height);
void *data;
int pitch;
IDirectFBSurface *buffer;
DFBRectangle source_rect;
cairo_format_t cairo_format;
cairo_format = surface->format;
if (surface->width != width || surface->height != height) {
DFBSurfacePixelFormat format;
if (surface->buffer_image) {
cairo_surface_destroy (surface->buffer_image);
surface->buffer_image = NULL;
}
if (surface->buffer)
surface->buffer->Release (surface->buffer);
surface->surface->GetPixelFormat (surface->surface, &format);
surface->format = directfb_to_cairo_format (format);
if (surface->format == -1) {
D_DEBUG_AT (Cairo_DirectFB, "%s buffer for surface.\n",
surface->buffer ? "Reallocating" : "Allocating");
surface->buffer = _directfb_buffer_surface_create (surface->dfb,
DSPF_ARGB, width, height);
if (!surface->buffer)
return CAIRO_STATUS_NO_MEMORY;
surface->buffer->Blit (surface->buffer,
surface->surface, NULL, 0, 0);
surface->format = CAIRO_FORMAT_ARGB32;
}
else {
surface->surface->AddRef (surface->surface);
surface->buffer = surface->surface;
}
surface->width = width;
surface->height = height;
if (surface->format == -1) {
if( intrest_rec ) {
source_rect.x = intrest_rec->x;
source_rect.y = intrest_rec->y;
source_rect.w = intrest_rec->width;
source_rect.h = intrest_rec->height;
}else {
source_rect.x=0;
source_rect.y=0;
surface->dfbsurface->GetSize (surface->dfbsurface,&source_rect.w, &source_rect.h);
}
D_DEBUG_AT (Cairo_DirectFB, "%s buffer for surface.\n",
surface->dfbsurface ? "Reallocating" : "Allocating");
cairo_format = directfb_to_cairo_format(DSPF_ARGB);
buffer = _directfb_buffer_surface_create (surface->dfb,DSPF_ARGB,source_rect.w,source_rect.h);
if (!buffer)
goto ERROR;
*image_extra = buffer;
buffer->SetBlittingFlags (buffer,DSBLIT_BLEND_ALPHACHANNEL | DSBLIT_COLORIZE);
buffer->Blit (buffer,surface->dfbsurface,&source_rect,0,0);
} else {
/*might be a subsurface get the offset*/
surface->dfbsurface->GetVisibleRectangle (surface->dfbsurface,&source_rect);
buffer = surface->dfbsurface;
*image_extra = buffer;
}
if (lock_flags) {
void *data;
int pitch;
DFBResult ret;
ret = surface->buffer->Lock (surface->buffer,
lock_flags, &data, &pitch);
if (ret) {
DirectFBError ("IDirectFBSurface::Lock()", ret);
return CAIRO_STATUS_NO_MEMORY;
}
if( buffer->Lock (buffer,lock_flags, &data, &pitch) )
goto ERROR;
if (!surface->buffer_image) {
surface->buffer_image = cairo_image_surface_create_for_data (data,
surface->format, surface->width,
surface->height, pitch);
if (!surface->buffer_image) {
surface->buffer->Unlock (surface->buffer);
return CAIRO_STATUS_NO_MEMORY;
}
}
else {
cairo_surface_reference (surface->buffer_image);
}
*image_out = (cairo_image_surface_t *)cairo_image_surface_create_for_data (data,
cairo_format,source_rect.w,source_rect.h, pitch);
if (*image_out == NULL )
goto ERROR;
if (image_rect_out) {
image_rect_out->x = source_rect.x;
image_rect_out->y = source_rect.y;
image_rect_out->width = source_rect.w;
image_rect_out->height = source_rect.h;
}else {
/*lock for read*/
cairo_surface_t *sur = &((*image_out)->base);
/*might be a subsurface*/
if( buffer == surface->dfbsurface )
cairo_surface_set_device_offset (sur,source_rect.x,source_rect.y);
}
return CAIRO_STATUS_SUCCESS;
return CAIRO_STATUS_SUCCESS;
ERROR:
*image_extra = NULL;
if( buffer ) {
buffer->Unlock (buffer);
if( buffer != surface->dfbsurface)
buffer->Release(buffer);
}
return CAIRO_STATUS_NO_MEMORY;
}
@ -415,33 +413,30 @@ _cairo_directfb_surface_create_similar (void *abstract_src,
"%s( src=%p, content=0x%x, width=%d, height=%d).\n",
__FUNCTION__, source, content, width, height);
width = (width <= 0) ? 1 : width;
height = (height<= 0) ? 1 : height;
format = _cairo_format_from_content (content);
surface = calloc (1, sizeof(cairo_directfb_surface_t));
if (!surface)
return NULL;
surface->surface = _directfb_buffer_surface_create (source->dfb,
surface->dfbsurface = _directfb_buffer_surface_create (source->dfb,
cairo_to_directfb_format (format),
MAX (width, 8), MAX (height, 8) );
if (!surface->surface) {
width, height);
assert(surface->dfbsurface);
surface->owner = TRUE;
if (!surface->dfbsurface) {
assert(0);
free (surface);
return NULL;
}
_cairo_surface_init (&surface->base, &cairo_directfb_surface_backend,content);
source->dfb->AddRef (source->dfb);
surface->dfb = source->dfb;
surface->surface->AddRef (surface->surface);
surface->buffer = surface->surface;
surface->format = format;
surface->width = width;
surface->height = height;
surface->local = true;
return &surface->base;
}
@ -453,11 +448,6 @@ _cairo_directfb_surface_finish (void *data)
D_DEBUG_AT (Cairo_DirectFB,
"%s( surface=%p ).\n", __FUNCTION__, surface);
if (surface->buffer_image) {
cairo_surface_destroy (surface->buffer_image);
surface->buffer_image = NULL;
}
if (surface->clips) {
free (surface->clips);
surface->clips = NULL;
@ -469,18 +459,13 @@ _cairo_directfb_surface_finish (void *data)
surface->color = NULL;
}
if (surface->buffer) {
surface->buffer->Release (surface->buffer);
surface->buffer = NULL;
}
if (surface->surface) {
surface->surface->Release (surface->surface);
surface->surface = NULL;
if (surface->dfbsurface) {
if( surface->owner )
surface->dfbsurface->Release (surface->dfbsurface);
surface->dfbsurface = NULL;
}
if (surface->dfb) {
surface->dfb->Release (surface->dfb);
surface->dfb = NULL;
}
@ -493,22 +478,9 @@ _cairo_directfb_surface_acquire_source_image (void *abstract_s
void **image_extra)
{
cairo_directfb_surface_t *surface = abstract_surface;
cairo_status_t ret;
D_DEBUG_AT (Cairo_DirectFB,
"%s( surface=%p ).\n", __FUNCTION__, surface);
ret = _directfb_acquire_surface (surface, DSLF_READ);
if (ret)
return ret;
if (image_out)
*image_out = (cairo_image_surface_t *)surface->buffer_image;
if (image_extra)
*image_extra = surface;
return CAIRO_STATUS_SUCCESS;
return _directfb_acquire_surface (surface,NULL,image_out,NULL,image_extra,DSLF_READ);
}
static void
@ -517,11 +489,16 @@ _cairo_directfb_surface_release_source_image (void *abstract_su
void *image_extra)
{
cairo_directfb_surface_t *surface = abstract_surface;
IDirectFBSurface *buffer = image_extra;
D_DEBUG_AT (Cairo_DirectFB,
"%s( surface=%p ).\n", __FUNCTION__, surface);
surface->buffer->Unlock (surface->buffer);
buffer->Unlock (buffer);
if (surface->dfbsurface != buffer) {
buffer->Release (buffer);
}
cairo_surface_destroy (&image->base);
}
static cairo_status_t
@ -532,29 +509,12 @@ _cairo_directfb_surface_acquire_dest_image (void *abstract_sur
void **image_extra)
{
cairo_directfb_surface_t *surface = abstract_surface;
cairo_status_t ret;
D_DEBUG_AT (Cairo_DirectFB,
"%s( surface=%p ).\n", __FUNCTION__, surface);
ret = _directfb_acquire_surface (surface, DSLF_READ | DSLF_WRITE);
if (ret)
return ret;
if (image_out)
*image_out = (cairo_image_surface_t *)surface->buffer_image;
if (image_rect_out) {
image_rect_out->x = 0;
image_rect_out->y = 0;
image_rect_out->width = surface->width;
image_rect_out->height = surface->height;
}
if (image_extra)
*image_extra = interest_rect;
return CAIRO_STATUS_SUCCESS;
return _directfb_acquire_surface (surface,interest_rect,image_out,image_rect_out,image_extra,
DSLF_READ | DSLF_WRITE);
}
static void
@ -565,11 +525,24 @@ _cairo_directfb_surface_release_dest_image (void *abstract_surf
void *image_extra)
{
cairo_directfb_surface_t *surface = abstract_surface;
IDirectFBSurface *buffer = image_extra;
D_DEBUG_AT (Cairo_DirectFB,
"%s( surface=%p ).\n", __FUNCTION__, surface);
surface->buffer->Unlock (surface->buffer);
buffer->Unlock (buffer);
if (surface->dfbsurface != buffer) {
DFBRegion region = { x1:interest_rect->x, y1:interest_rect->y,
x2:interest_rect->x+interest_rect->width-1,
y2:interest_rect->y+interest_rect->height-1 };
surface->dfbsurface->SetClip (surface->dfbsurface, &region);
//surface->dfbsurface->SetBlittingFlags (surface->dfbsurface,
// DSBLIT_BLEND_ALPHACHANNEL | DSBLIT_COLORIZE);
surface->dfbsurface->Blit (surface->dfbsurface,buffer,NULL,
image_rect->x,image_rect->y);
buffer->Release (buffer);
}
cairo_surface_destroy (&image->base);
}
static cairo_status_t
@ -603,7 +576,7 @@ _cairo_directfb_surface_clone_similar (void *abstract_surface,
if (!clone)
return CAIRO_STATUS_NO_MEMORY;
ret = clone->buffer->Lock (clone->buffer,
ret = clone->dfbsurface->Lock (clone->dfbsurface,
DSLF_WRITE, (void *)&dst, &pitch);
if (ret) {
DirectFBError ("IDirectFBSurface::Lock()", ret);
@ -628,7 +601,7 @@ _cairo_directfb_surface_clone_similar (void *abstract_surface,
}
}
clone->buffer->Unlock (clone->buffer);
clone->dfbsurface->Unlock (clone->dfbsurface);
*clone_out = &clone->base;
@ -701,10 +674,6 @@ _directfb_prepare_composite (cairo_directfb_surface_t *dst,
color.a = color.r = color.g = color.b = 0xff;
}
ret = _directfb_acquire_surface (dst, 0);
if (ret)
return ret;
if (src_pattern->type == CAIRO_PATTERN_TYPE_SOLID) {
cairo_solid_pattern_t *pattern = (cairo_solid_pattern_t *)src_pattern;
@ -716,12 +685,12 @@ _directfb_prepare_composite (cairo_directfb_surface_t *dst,
}
src = (cairo_directfb_surface_t *)dst->color;
src->buffer->SetColor (src->buffer,
src->dfbsurface->SetColor (src->dfbsurface,
pattern->color.red_short >> 8,
pattern->color.green_short >> 8,
pattern->color.blue_short >> 8,
pattern->color.alpha_short >> 8);
src->buffer->FillRectangle (src->buffer, 0, 0, 1, 1);
src->dfbsurface->FillRectangle (src->dfbsurface, 0, 0, 1, 1);
cairo_matrix_init_identity (&src_attr.matrix);
src_attr.matrix = src_pattern->matrix;
@ -736,12 +705,6 @@ _directfb_prepare_composite (cairo_directfb_surface_t *dst,
(cairo_surface_t **)&src, &src_attr);
if (ret)
return ret;
ret = _directfb_acquire_surface (src, 0);
if (ret) {
_cairo_pattern_release_surface (src_pattern, &src->base, &src_attr);
return ret;
}
}
if (color.a != 0xff)
@ -749,15 +712,15 @@ _directfb_prepare_composite (cairo_directfb_surface_t *dst,
if (color.r != 0xff || color.g != 0xff || color.b != 0xff)
flags |= DSBLIT_COLORIZE;
dst->buffer->SetBlittingFlags (dst->buffer, flags);
dst->dfbsurface->SetBlittingFlags (dst->dfbsurface, flags);
if (flags & (DSBLIT_BLEND_COLORALPHA | DSBLIT_BLEND_ALPHACHANNEL)) {
dst->buffer->SetSrcBlendFunction (dst->buffer, sblend);
dst->buffer->SetDstBlendFunction (dst->buffer, dblend);
dst->dfbsurface->SetSrcBlendFunction (dst->dfbsurface, sblend);
dst->dfbsurface->SetDstBlendFunction (dst->dfbsurface, dblend);
}
if (flags & (DSBLIT_BLEND_COLORALPHA | DSBLIT_COLORIZE))
dst->buffer->SetColor (dst->buffer, color.r, color.g, color.b, color.a);
dst->dfbsurface->SetColor (dst->dfbsurface, color.r, color.g, color.b, color.a);
*ret_src = src;
*ret_src_attr = src_attr;
@ -822,8 +785,8 @@ _cairo_directfb_surface_composite (cairo_operator_t op,
D_DEBUG_AT (Cairo_DirectFB, "Running Blit().\n");
RUN_CLIPPED( dst, NULL,
dst->buffer->Blit (dst->buffer,
src->buffer, &sr, dst_x, dst_y));
dst->dfbsurface->Blit (dst->dfbsurface,
src->dfbsurface, &sr, dst_x, dst_y));
ret = CAIRO_STATUS_SUCCESS;
}
else if (src_attr.extend == CAIRO_EXTEND_REPEAT) {
@ -837,8 +800,8 @@ _cairo_directfb_surface_composite (cairo_operator_t op,
D_DEBUG_AT (Cairo_DirectFB, "Running TileBlit().\n");
RUN_CLIPPED( dst, &clip,
dst->buffer->TileBlit (dst->buffer,
src->buffer, &sr, dst_x, dst_y));
dst->dfbsurface->TileBlit (dst->dfbsurface,
src->dfbsurface, &sr, dst_x, dst_y));
ret = CAIRO_STATUS_SUCCESS;
}
}
@ -852,7 +815,7 @@ _cairo_directfb_surface_composite (cairo_operator_t op,
*/
src_x = src_y = 0;
dst->buffer->GetAccelerationMask (dst->buffer, src->buffer, &accel);
dst->dfbsurface->GetAccelerationMask (dst->dfbsurface, src->dfbsurface, &accel);
if (m->xy != 0.0 || m->yx != 0.0) {
if (accel & DFXL_TEXTRIANGLES) {
@ -898,8 +861,8 @@ _cairo_directfb_surface_composite (cairo_operator_t op,
D_DEBUG_AT (Cairo_DirectFB, "Running TextureTriangles().\n");
RUN_CLIPPED (dst, NULL,
dst->buffer->TextureTriangles (dst->buffer,
src->buffer, v, NULL, 4, DTTF_FAN));
dst->dfbsurface->TextureTriangles (dst->dfbsurface,
src->dfbsurface, v, NULL, 4, DTTF_FAN));
ret = CAIRO_STATUS_SUCCESS;
}
}
@ -926,8 +889,8 @@ _cairo_directfb_surface_composite (cairo_operator_t op,
D_DEBUG_AT (Cairo_DirectFB, "Running StretchBlit().\n");
RUN_CLIPPED (dst, NULL,
dst->buffer->StretchBlit (dst->buffer,
src->buffer, &sr, &dr));
dst->dfbsurface->StretchBlit (dst->dfbsurface,
src->dfbsurface, &sr, &dr));
ret = CAIRO_STATUS_SUCCESS;
}
}
@ -939,6 +902,7 @@ _cairo_directfb_surface_composite (cairo_operator_t op,
}
#endif /* DFB_COMPOSITE */
#if DFB_RECTANGLES
static cairo_int_status_t
_cairo_directfb_surface_fill_rectangles (void *abstract_surface,
cairo_operator_t op,
@ -947,7 +911,6 @@ _cairo_directfb_surface_fill_rectangles (void *abstract_surface,
int n_rects)
{
cairo_directfb_surface_t *dst = abstract_surface;
cairo_status_t ret;
DFBSurfaceDrawingFlags flags;
DFBSurfaceBlendFunction sblend;
DFBSurfaceBlendFunction dblend;
@ -961,17 +924,13 @@ _cairo_directfb_surface_fill_rectangles (void *abstract_surface,
if (_directfb_get_operator (op, &flags, NULL, &sblend, &dblend))
return CAIRO_INT_STATUS_UNSUPPORTED;
ret = _directfb_acquire_surface (dst, 0);
if (ret)
return ret;
dst->buffer->SetDrawingFlags (dst->buffer, flags);
dst->dfbsurface->SetDrawingFlags (dst->dfbsurface, flags);
if (flags & DSDRAW_BLEND) {
dst->buffer->SetSrcBlendFunction (dst->buffer, sblend);
dst->buffer->SetDstBlendFunction (dst->buffer, dblend);
dst->dfbsurface->SetSrcBlendFunction (dst->dfbsurface, sblend);
dst->dfbsurface->SetDstBlendFunction (dst->dfbsurface, dblend);
}
dst->buffer->SetColor (dst->buffer, color->red_short >> 8,
dst->dfbsurface->SetColor (dst->dfbsurface, color->red_short >> 8,
color->green_short >> 8,
color->blue_short >> 8,
color->alpha_short >> 8 );
@ -984,10 +943,11 @@ _cairo_directfb_surface_fill_rectangles (void *abstract_surface,
}
RUN_CLIPPED (dst, NULL,
dst->buffer->FillRectangles (dst->buffer, r, n_rects));
dst->dfbsurface->FillRectangles (dst->dfbsurface, r, n_rects));
return CAIRO_STATUS_SUCCESS;
}
#endif
#if DFB_COMPOSITE_TRAPEZOIDS
static cairo_int_status_t
@ -1028,7 +988,7 @@ _cairo_directfb_surface_composite_trapezoids (cairo_operator_t op,
if (ret)
return ret;
dst->buffer->GetAccelerationMask (dst->buffer, src->buffer, &accel);
dst->dfbsurface->GetAccelerationMask (dst->dfbsurface, src->dfbsurface, &accel);
ret = CAIRO_INT_STATUS_UNSUPPORTED;
@ -1118,7 +1078,7 @@ _cairo_directfb_surface_composite_trapezoids (cairo_operator_t op,
D_DEBUG_AT (Cairo_DirectFB, "Running TextureTriangles().\n");
RUN_CLIPPED (dst, NULL,
dst->buffer->TextureTriangles (dst->buffer, src->buffer,
dst->dfbsurface->TextureTriangles (dst->dfbsurface, src->dfbsurface,
vertex, NULL, n, DTTF_LIST));
ret = CAIRO_STATUS_SUCCESS;
@ -1146,7 +1106,8 @@ _cairo_directfb_surface_set_clip_region (void *abstract_surface,
int i;
if (surface->n_clips != n_boxes) {
free (surface->clips);
if( surface->clips )
free (surface->clips);
surface->clips = malloc (n_boxes * sizeof(DFBRegion));
if (!surface->clips) {
@ -1202,25 +1163,24 @@ _cairo_directfb_surface_mark_dirty_rectangle (void *abstract_surface,
int width,
int height)
{
#if 0
cairo_directfb_surface_t *surface = abstract_surface;
D_DEBUG_AT (Cairo_DirectFB,
"%s( surface=%p, x=%d, y=%d, width=%d, height=%d ).\n",
__FUNCTION__, surface, x, y, width, height);
if (surface->surface != surface->buffer) {
DFBRegion region = { x1:x, y1:y, x2:x+width-1, y2:y+height-1 };
surface->buffer->SetClip (surface->buffer, &region);
surface->buffer->SetBlittingFlags (surface->buffer, DSBLIT_NOFX);
surface->buffer->Blit (surface->buffer, surface->surface, NULL, 0, 0);
}
if( !surface->dirty_region )
surface->dirty_region = malloc(sizeof(DFBRegion));
if (!dirty_region)
return CAIRO_STATUS_NO_MEMORY;
#endif
return CAIRO_STATUS_SUCCESS;
}
static cairo_status_t
_cairo_directfb_surface_flush (void *abstract_surface)
{
#if 0
cairo_directfb_surface_t *surface = abstract_surface;
D_DEBUG_AT (Cairo_DirectFB,
@ -1231,7 +1191,7 @@ _cairo_directfb_surface_flush (void *abstract_surface)
surface->surface->SetBlittingFlags (surface->surface, DSBLIT_NOFX);
surface->surface->Blit (surface->surface, surface->buffer, NULL, 0, 0);
}
#endif
return CAIRO_STATUS_SUCCESS;
}
@ -1245,13 +1205,13 @@ _directfb_allocate_font_cache (IDirectFB *dfb, int width, int height)
if (!cache)
return NULL;
cache->buffer = _directfb_buffer_surface_create( dfb, DSPF_A8, width, height);
if (!cache->buffer) {
cache->dfbsurface = _directfb_buffer_surface_create( dfb, DSPF_A8, width, height);
if (!cache->dfbsurface) {
free (cache);
return NULL;
}
dfb->AddRef (dfb);
//dfb->AddRef (dfb);
cache->dfb = dfb;
cache->width = width;
@ -1263,8 +1223,7 @@ _directfb_allocate_font_cache (IDirectFB *dfb, int width, int height)
static void
_directfb_destroy_font_cache (cairo_directfb_font_cache_t *cache)
{
cache->buffer->Release (cache->buffer);
cache->dfb->Release (cache->dfb);
cache->dfbsurface->Release (cache->dfbsurface);
free (cache);
}
@ -1386,8 +1345,8 @@ _directfb_acquire_font_cache (cairo_directfb_surface_t *surface,
if (!new_cache)
return CAIRO_STATUS_NO_MEMORY;
new_cache->buffer->Blit (new_cache->buffer,
cache->buffer, NULL, 0, 0);
new_cache->dfbsurface->Blit (new_cache->dfbsurface,
cache->dfbsurface, NULL, 0, 0);
_directfb_destroy_font_cache (cache);
scaled_font->surface_private = cache = new_cache;
@ -1409,7 +1368,7 @@ _directfb_acquire_font_cache (cairo_directfb_surface_t *surface,
unsigned char *data;
int pitch;
if (cache->buffer->Lock (cache->buffer,
if (cache->dfbsurface->Lock (cache->dfbsurface,
DSLF_WRITE, (void *)&data, &pitch))
return CAIRO_STATUS_NO_MEMORY;
@ -1437,7 +1396,7 @@ _directfb_acquire_font_cache (cairo_directfb_surface_t *surface,
}
}
cache->buffer->Unlock (cache->buffer);
cache->dfbsurface->Unlock (cache->dfbsurface);
}
cache->x = x;
@ -1509,10 +1468,6 @@ _cairo_directfb_surface_show_glyphs ( void *abstract_dst,
sblend == DSBF_DESTALPHA || sblend == DSBF_INVDESTALPHA)
return CAIRO_INT_STATUS_UNSUPPORTED;
ret = _directfb_acquire_surface (dst, 0);
if (ret)
return ret;
ret = _directfb_acquire_font_cache (dst, scaled_font, glyphs, num_glyphs,
&cache, &rects[0], &points[0], &num);
if (ret) {
@ -1536,16 +1491,16 @@ _cairo_directfb_surface_show_glyphs ( void *abstract_dst,
dblend = DSBF_INVSRCALPHA;
}
dst->buffer->SetBlittingFlags (dst->buffer, flags);
dst->buffer->SetSrcBlendFunction (dst->buffer, sblend);
dst->buffer->SetDstBlendFunction (dst->buffer, dblend);
dst->buffer->SetColor (dst->buffer, color.r, color.g, color.b, color.a);
dst->dfbsurface->SetBlittingFlags (dst->dfbsurface, flags);
dst->dfbsurface->SetSrcBlendFunction (dst->dfbsurface, sblend);
dst->dfbsurface->SetDstBlendFunction (dst->dfbsurface, dblend);
dst->dfbsurface->SetColor (dst->dfbsurface, color.r, color.g, color.b, color.a);
D_DEBUG_AT (Cairo_DirectFB, "Running BatchBlit().\n");
RUN_CLIPPED (dst, NULL,
dst->buffer->BatchBlit (dst->buffer,
cache->buffer, rects, points, num));
dst->dfbsurface->BatchBlit (dst->dfbsurface,
cache->dfbsurface, rects, points, num));
return CAIRO_STATUS_SUCCESS;
}
@ -1566,7 +1521,11 @@ static cairo_surface_backend_t cairo_directfb_surface_backend = {
#else
NULL,/*composite*/
#endif
#if DFB_RECTANGLES
_cairo_directfb_surface_fill_rectangles,/*fill_rectangles*/
#else
NULL,/*fill_rectangles*/
#endif
#if DFB_COMPOSITE_TRAPEZOIDS
_cairo_directfb_surface_composite_trapezoids,/*composite_trapezoids*/
#else
@ -1642,27 +1601,23 @@ cairo_directfb_surface_create (IDirectFB *dfb, IDirectFBSurface *dfbsurface)
{
DFBSurfacePixelFormat format;
cairo_directfb_surface_t *surface;
assert(dfb);
assert(dfb);
cairo_directfb_surface_backend_init (dfb);
surface = calloc (1, sizeof(cairo_directfb_surface_t));
if (!surface)
if (!surface)
return NULL;
dfbsurface->GetPixelFormat (dfbsurface, &format);
_cairo_surface_init (&surface->base, &cairo_directfb_surface_backend,
_directfb_format_to_content(format));
dfb->AddRef (dfb);
surface->owner = FALSE;
surface->dfb = dfb;
dfbsurface->AddRef (dfbsurface);
surface->surface = dfbsurface;
if (_directfb_acquire_surface (surface, 0)) {
cairo_surface_destroy ((cairo_surface_t *)surface);
return NULL;
}
surface->dfbsurface = dfbsurface;
dfbsurface->GetSize (dfbsurface,&surface->width, &surface->height);
surface->format = directfb_to_cairo_format(format);
return &surface->base;
}

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

@ -43,7 +43,8 @@
CAIRO_BEGIN_DECLS
cairo_surface_t * cairo_directfb_surface_create (IDirectFB *dfb,IDirectFBSurface *surface);
cairo_public cairo_surface_t *
cairo_directfb_surface_create (IDirectFB *dfb,IDirectFBSurface *surface);
CAIRO_END_DECLS

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

@ -95,6 +95,7 @@ cairo_font_options_create (void)
return options;
}
slim_hidden_def (cairo_font_options_create);
/**
* cairo_font_options_copy:
@ -137,6 +138,7 @@ cairo_font_options_destroy (cairo_font_options_t *options)
free (options);
}
slim_hidden_def (cairo_font_options_destroy);
/**
* cairo_font_options_status:
@ -182,6 +184,7 @@ cairo_font_options_merge (cairo_font_options_t *options,
if (other->hint_metrics != CAIRO_HINT_METRICS_DEFAULT)
options->hint_metrics = other->hint_metrics;
}
slim_hidden_def (cairo_font_options_merge);
/**
* cairo_font_options_equal:
@ -201,6 +204,7 @@ cairo_font_options_equal (const cairo_font_options_t *options,
options->hint_style == other->hint_style &&
options->hint_metrics == other->hint_metrics);
}
slim_hidden_def (cairo_font_options_equal);
/**
* cairo_font_options_hash:
@ -222,6 +226,7 @@ cairo_font_options_hash (const cairo_font_options_t *options)
(options->hint_style << 8) |
(options->hint_metrics << 16));
}
slim_hidden_def (cairo_font_options_hash);
/**
* cairo_font_options_set_antialias:
@ -240,6 +245,7 @@ cairo_font_options_set_antialias (cairo_font_options_t *options,
options->antialias = antialias;
}
slim_hidden_def (cairo_font_options_set_antialias);
/**
* cairo_font_options_get_antialias:
@ -275,6 +281,7 @@ cairo_font_options_set_subpixel_order (cairo_font_options_t *options,
options->subpixel_order = subpixel_order;
}
slim_hidden_def (cairo_font_options_set_subpixel_order);
/**
* cairo_font_options_get_subpixel_order:
@ -310,6 +317,7 @@ cairo_font_options_set_hint_style (cairo_font_options_t *options,
options->hint_style = hint_style;
}
slim_hidden_def (cairo_font_options_set_hint_style);
/**
* cairo_font_options_get_hint_style:
@ -345,6 +353,7 @@ cairo_font_options_set_hint_metrics (cairo_font_options_t *options,
options->hint_metrics = hint_metrics;
}
slim_hidden_def (cairo_font_options_set_hint_metrics);
/**
* cairo_font_options_get_hint_metrics:

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

@ -1,812 +0,0 @@
/* cairo - a vector graphics library with display and print output
*
* Copyright © 2004 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>
*/
#include "cairoint.h"
#include "cairo-scaled-font-subsets-private.h"
/* XXX: Eventually, we need to handle other font backends */
#include "cairo-ft-private.h"
#include <ft2build.h>
#include FT_FREETYPE_H
#include FT_OUTLINE_H
#include FT_TRUETYPE_TAGS_H
#include FT_TRUETYPE_TABLES_H
typedef struct ft_subset_glyph ft_subset_glyph_t;
struct ft_subset_glyph {
int parent_index;
unsigned long location;
};
typedef struct _cairo_ft_font {
cairo_scaled_font_subset_t *scaled_font_subset;
struct {
cairo_unscaled_font_t *unscaled_font;
unsigned int font_id;
char *base_font;
int num_glyphs;
int *widths;
long x_min, y_min, x_max, y_max;
long ascent, descent;
} base;
ft_subset_glyph_t *glyphs;
FT_Face face;
int checksum_index;
cairo_array_t output;
int *parent_to_subset;
cairo_status_t status;
} cairo_pdf_ft_font_t;
static int
cairo_pdf_ft_font_use_glyph (cairo_pdf_ft_font_t *font, int glyph);
#define ARRAY_LENGTH(a) ( (sizeof (a)) / (sizeof ((a)[0])) )
#define SFNT_VERSION 0x00010000
#ifdef WORDS_BIGENDIAN
#define cpu_to_be16(v) (v)
#define be16_to_cpu(v) (v)
#define cpu_to_be32(v) (v)
#define be32_to_cpu(v) (v)
#else
static inline unsigned short
cpu_to_be16(unsigned short v)
{
return (v << 8) | (v >> 8);
}
static inline unsigned short
be16_to_cpu(unsigned short v)
{
return cpu_to_be16 (v);
}
static inline unsigned long
cpu_to_be32(unsigned long v)
{
return (cpu_to_be16 (v) << 16) | cpu_to_be16 (v >> 16);
}
static inline unsigned long
be32_to_cpu(unsigned long v)
{
return cpu_to_be32 (v);
}
#endif
static cairo_status_t
_cairo_pdf_ft_font_create (cairo_scaled_font_subset_t *scaled_font_subset,
cairo_pdf_ft_font_t **font_return)
{
cairo_unscaled_font_t *unscaled_font;
cairo_ft_unscaled_font_t *ft_unscaled_font;
cairo_status_t status = CAIRO_STATUS_NO_MEMORY;
cairo_pdf_ft_font_t *font;
FT_Face face;
unsigned long size;
int i, j;
/* XXX: Need to fix this to work with a general cairo_unscaled_font_t. */
if (!_cairo_scaled_font_is_ft (scaled_font_subset->scaled_font))
return CAIRO_INT_STATUS_UNSUPPORTED;
if (_cairo_ft_scaled_font_is_vertical (scaled_font_subset->scaled_font))
return CAIRO_INT_STATUS_UNSUPPORTED;
unscaled_font = _cairo_ft_scaled_font_get_unscaled_font (scaled_font_subset->scaled_font);
ft_unscaled_font = (cairo_ft_unscaled_font_t *) unscaled_font;
face = _cairo_ft_unscaled_font_lock_face (ft_unscaled_font);
if (face == NULL)
/* Assume out of memory */
return CAIRO_STATUS_NO_MEMORY;
/* We currently only support freetype truetype fonts. */
size = 0;
if (!FT_IS_SFNT (face) ||
FT_Load_Sfnt_Table (face, TTAG_glyf, 0, NULL, &size) != 0)
return CAIRO_INT_STATUS_UNSUPPORTED;
font = malloc (sizeof (cairo_pdf_ft_font_t));
if (font == NULL)
return CAIRO_STATUS_NO_MEMORY;
font->scaled_font_subset = scaled_font_subset;
font->base.unscaled_font = _cairo_unscaled_font_reference (unscaled_font);
_cairo_array_init (&font->output, sizeof (char));
if (_cairo_array_grow_by (&font->output, 4096) != CAIRO_STATUS_SUCCESS)
goto fail1;
font->glyphs = calloc (face->num_glyphs + 1, sizeof (ft_subset_glyph_t));
if (font->glyphs == NULL)
goto fail2;
font->parent_to_subset = calloc (face->num_glyphs, sizeof (int));
if (font->parent_to_subset == NULL)
goto fail3;
font->base.num_glyphs = 0;
font->base.x_min = face->bbox.xMin;
font->base.y_min = face->bbox.yMin;
font->base.x_max = face->bbox.xMax;
font->base.y_max = face->bbox.yMax;
font->base.ascent = face->ascender;
font->base.descent = face->descender;
font->base.base_font = strdup (face->family_name);
if (font->base.base_font == NULL)
goto fail4;
for (i = 0, j = 0; font->base.base_font[j]; j++) {
if (font->base.base_font[j] == ' ')
continue;
font->base.base_font[i++] = font->base.base_font[j];
}
font->base.base_font[i] = '\0';
font->base.widths = calloc (face->num_glyphs, sizeof (int));
if (font->base.widths == NULL)
goto fail5;
_cairo_ft_unscaled_font_unlock_face (ft_unscaled_font);
font->status = CAIRO_STATUS_SUCCESS;
*font_return = font;
return CAIRO_STATUS_SUCCESS;
fail5:
free (font->base.base_font);
fail4:
free (font->parent_to_subset);
fail3:
free (font->glyphs);
fail2:
_cairo_array_fini (&font->output);
fail1:
free (font);
return status;
}
static void
cairo_pdf_ft_font_destroy (cairo_pdf_ft_font_t *font)
{
_cairo_unscaled_font_destroy (font->base.unscaled_font);
free (font->base.base_font);
free (font->parent_to_subset);
free (font->glyphs);
_cairo_array_fini (&font->output);
free (font);
}
static cairo_status_t
cairo_pdf_ft_font_allocate_write_buffer (cairo_pdf_ft_font_t *font,
size_t length,
unsigned char **buffer)
{
cairo_status_t status;
status = _cairo_array_allocate (&font->output, length, (void **) buffer);
if (status)
return status;
return CAIRO_STATUS_SUCCESS;
}
static cairo_status_t
cairo_pdf_ft_font_write (cairo_pdf_ft_font_t *font,
const void *data, size_t length)
{
cairo_status_t status;
status = _cairo_array_append_multiple (&font->output, data, length);
if (status)
return status;
return CAIRO_STATUS_SUCCESS;
}
static void
cairo_pdf_ft_font_write_be16 (cairo_pdf_ft_font_t *font,
unsigned short value)
{
unsigned short be16_value;
be16_value = cpu_to_be16 (value);
cairo_pdf_ft_font_write (font, &be16_value, sizeof be16_value);
}
static void
cairo_pdf_ft_font_write_be32 (cairo_pdf_ft_font_t *font, unsigned long value)
{
unsigned long be32_value;
be32_value = cpu_to_be32 (value);
cairo_pdf_ft_font_write (font, &be32_value, sizeof be32_value);
}
static unsigned long
cairo_pdf_ft_font_align_output (cairo_pdf_ft_font_t *font)
{
int length, aligned, pad;
unsigned char *ignored;
length = _cairo_array_num_elements (&font->output);
aligned = (length + 3) & ~3;
pad = aligned - length;
if (pad)
cairo_pdf_ft_font_allocate_write_buffer (font, pad, &ignored);
return aligned;
}
static int
cairo_pdf_ft_font_write_cmap_table (cairo_pdf_ft_font_t *font, unsigned long tag)
{
int i;
cairo_pdf_ft_font_write_be16 (font, 0);
cairo_pdf_ft_font_write_be16 (font, 1);
cairo_pdf_ft_font_write_be16 (font, 1);
cairo_pdf_ft_font_write_be16 (font, 0);
cairo_pdf_ft_font_write_be32 (font, 12);
/* Output a format 6 encoding table. */
cairo_pdf_ft_font_write_be16 (font, 6);
cairo_pdf_ft_font_write_be16 (font, 10 + 2 * (font->base.num_glyphs - 1));
cairo_pdf_ft_font_write_be16 (font, 0);
cairo_pdf_ft_font_write_be16 (font, 1); /* First glyph */
cairo_pdf_ft_font_write_be16 (font, font->base.num_glyphs - 1);
for (i = 1; i < font->base.num_glyphs; i++)
cairo_pdf_ft_font_write_be16 (font, i);
return font->status;
}
static int
cairo_pdf_ft_font_write_generic_table (cairo_pdf_ft_font_t *font,
unsigned long tag)
{
cairo_status_t status;
unsigned char *buffer;
unsigned long size;
size = 0;
FT_Load_Sfnt_Table (font->face, tag, 0, NULL, &size);
status = cairo_pdf_ft_font_allocate_write_buffer (font, size, &buffer);
/* XXX: Need to check status here. */
FT_Load_Sfnt_Table (font->face, tag, 0, buffer, &size);
return 0;
}
typedef struct composite_glyph composite_glyph_t;
struct composite_glyph {
unsigned short flags;
unsigned short index;
unsigned short args[7]; /* 1 to 7 arguments depending on value of flags */
};
typedef struct glyph_data glyph_data_t;
struct glyph_data {
short num_contours;
char data[8];
composite_glyph_t glyph;
};
/* composite_glyph_t flags */
#define ARG_1_AND_2_ARE_WORDS 0x0001
#define WE_HAVE_A_SCALE 0x0008
#define MORE_COMPONENTS 0x0020
#define WE_HAVE_AN_X_AND_Y_SCALE 0x0040
#define WE_HAVE_A_TWO_BY_TWO 0x0080
static void
cairo_pdf_ft_font_remap_composite_glyph (cairo_pdf_ft_font_t *font,
unsigned char *buffer)
{
glyph_data_t *glyph_data;
composite_glyph_t *composite_glyph;
int num_args;
int has_more_components;
unsigned short flags;
unsigned short index;
glyph_data = (glyph_data_t *) buffer;
if ((short)be16_to_cpu (glyph_data->num_contours) >= 0)
return;
composite_glyph = &glyph_data->glyph;
do {
flags = be16_to_cpu (composite_glyph->flags);
has_more_components = flags & MORE_COMPONENTS;
index = cairo_pdf_ft_font_use_glyph (font, be16_to_cpu (composite_glyph->index));
composite_glyph->index = cpu_to_be16 (index);
num_args = 1;
if (flags & ARG_1_AND_2_ARE_WORDS)
num_args += 1;
if (flags & WE_HAVE_A_SCALE)
num_args += 1;
else if (flags & WE_HAVE_AN_X_AND_Y_SCALE)
num_args += 2;
else if (flags & WE_HAVE_A_TWO_BY_TWO)
num_args += 3;
composite_glyph = (composite_glyph_t *) &(composite_glyph->args[num_args]);
} while (has_more_components);
}
static int
cairo_pdf_ft_font_write_glyf_table (cairo_pdf_ft_font_t *font,
unsigned long tag)
{
cairo_status_t status;
unsigned long start_offset, index, size;
TT_Header *header;
unsigned long begin, end;
unsigned char *buffer;
int i;
union {
unsigned char *bytes;
unsigned short *short_offsets;
unsigned long *long_offsets;
} u;
header = FT_Get_Sfnt_Table (font->face, ft_sfnt_head);
if (header->Index_To_Loc_Format == 0)
size = sizeof (short) * (font->face->num_glyphs + 1);
else
size = sizeof (long) * (font->face->num_glyphs + 1);
u.bytes = malloc (size);
if (u.bytes == NULL) {
font->status = CAIRO_STATUS_NO_MEMORY;
return font->status;
}
FT_Load_Sfnt_Table (font->face, TTAG_loca, 0, u.bytes, &size);
start_offset = _cairo_array_num_elements (&font->output);
for (i = 0; i < font->base.num_glyphs; i++) {
index = font->glyphs[i].parent_index;
if (header->Index_To_Loc_Format == 0) {
begin = be16_to_cpu (u.short_offsets[index]) * 2;
end = be16_to_cpu (u.short_offsets[index + 1]) * 2;
}
else {
begin = be32_to_cpu (u.long_offsets[index]);
end = be32_to_cpu (u.long_offsets[index + 1]);
}
size = end - begin;
font->glyphs[i].location =
cairo_pdf_ft_font_align_output (font) - start_offset;
status = cairo_pdf_ft_font_allocate_write_buffer (font, size, &buffer);
if (status)
break;
if (size != 0) {
FT_Load_Sfnt_Table (font->face, TTAG_glyf, begin, buffer, &size);
cairo_pdf_ft_font_remap_composite_glyph (font, buffer);
}
}
font->glyphs[i].location =
cairo_pdf_ft_font_align_output (font) - start_offset;
free (u.bytes);
return font->status;
}
static int
cairo_pdf_ft_font_write_head_table (cairo_pdf_ft_font_t *font,
unsigned long tag)
{
TT_Header *head;
head = FT_Get_Sfnt_Table (font->face, ft_sfnt_head);
cairo_pdf_ft_font_write_be32 (font, head->Table_Version);
cairo_pdf_ft_font_write_be32 (font, head->Font_Revision);
font->checksum_index = _cairo_array_num_elements (&font->output);
cairo_pdf_ft_font_write_be32 (font, 0);
cairo_pdf_ft_font_write_be32 (font, head->Magic_Number);
cairo_pdf_ft_font_write_be16 (font, head->Flags);
cairo_pdf_ft_font_write_be16 (font, head->Units_Per_EM);
cairo_pdf_ft_font_write_be32 (font, head->Created[0]);
cairo_pdf_ft_font_write_be32 (font, head->Created[1]);
cairo_pdf_ft_font_write_be32 (font, head->Modified[0]);
cairo_pdf_ft_font_write_be32 (font, head->Modified[1]);
cairo_pdf_ft_font_write_be16 (font, head->xMin);
cairo_pdf_ft_font_write_be16 (font, head->yMin);
cairo_pdf_ft_font_write_be16 (font, head->xMax);
cairo_pdf_ft_font_write_be16 (font, head->yMax);
cairo_pdf_ft_font_write_be16 (font, head->Mac_Style);
cairo_pdf_ft_font_write_be16 (font, head->Lowest_Rec_PPEM);
cairo_pdf_ft_font_write_be16 (font, head->Font_Direction);
cairo_pdf_ft_font_write_be16 (font, head->Index_To_Loc_Format);
cairo_pdf_ft_font_write_be16 (font, head->Glyph_Data_Format);
return font->status;
}
static int cairo_pdf_ft_font_write_hhea_table (cairo_pdf_ft_font_t *font, unsigned long tag)
{
TT_HoriHeader *hhea;
hhea = FT_Get_Sfnt_Table (font->face, ft_sfnt_hhea);
cairo_pdf_ft_font_write_be32 (font, hhea->Version);
cairo_pdf_ft_font_write_be16 (font, hhea->Ascender);
cairo_pdf_ft_font_write_be16 (font, hhea->Descender);
cairo_pdf_ft_font_write_be16 (font, hhea->Line_Gap);
cairo_pdf_ft_font_write_be16 (font, hhea->advance_Width_Max);
cairo_pdf_ft_font_write_be16 (font, hhea->min_Left_Side_Bearing);
cairo_pdf_ft_font_write_be16 (font, hhea->min_Right_Side_Bearing);
cairo_pdf_ft_font_write_be16 (font, hhea->xMax_Extent);
cairo_pdf_ft_font_write_be16 (font, hhea->caret_Slope_Rise);
cairo_pdf_ft_font_write_be16 (font, hhea->caret_Slope_Run);
cairo_pdf_ft_font_write_be16 (font, hhea->caret_Offset);
cairo_pdf_ft_font_write_be16 (font, 0);
cairo_pdf_ft_font_write_be16 (font, 0);
cairo_pdf_ft_font_write_be16 (font, 0);
cairo_pdf_ft_font_write_be16 (font, 0);
cairo_pdf_ft_font_write_be16 (font, hhea->metric_Data_Format);
cairo_pdf_ft_font_write_be16 (font, font->base.num_glyphs);
return font->status;
}
static int
cairo_pdf_ft_font_write_hmtx_table (cairo_pdf_ft_font_t *font,
unsigned long tag)
{
cairo_status_t status;
unsigned long entry_size;
short *p;
int i;
for (i = 0; i < font->base.num_glyphs; i++) {
entry_size = 2 * sizeof (short);
status = cairo_pdf_ft_font_allocate_write_buffer (font, entry_size,
(unsigned char **) &p);
/* XXX: Need to check status here. */
FT_Load_Sfnt_Table (font->face, TTAG_hmtx,
font->glyphs[i].parent_index * entry_size,
(FT_Byte *) p, &entry_size);
font->base.widths[i] = be16_to_cpu (p[0]);
}
return font->status;
}
static int
cairo_pdf_ft_font_write_loca_table (cairo_pdf_ft_font_t *font,
unsigned long tag)
{
int i;
TT_Header *header;
header = FT_Get_Sfnt_Table (font->face, ft_sfnt_head);
if (header->Index_To_Loc_Format == 0) {
for (i = 0; i < font->base.num_glyphs + 1; i++)
cairo_pdf_ft_font_write_be16 (font, font->glyphs[i].location / 2);
}
else {
for (i = 0; i < font->base.num_glyphs + 1; i++)
cairo_pdf_ft_font_write_be32 (font, font->glyphs[i].location);
}
return font->status;
}
static int
cairo_pdf_ft_font_write_maxp_table (cairo_pdf_ft_font_t *font,
unsigned long tag)
{
TT_MaxProfile *maxp;
maxp = FT_Get_Sfnt_Table (font->face, ft_sfnt_maxp);
cairo_pdf_ft_font_write_be32 (font, maxp->version);
cairo_pdf_ft_font_write_be16 (font, font->base.num_glyphs);
cairo_pdf_ft_font_write_be16 (font, maxp->maxPoints);
cairo_pdf_ft_font_write_be16 (font, maxp->maxContours);
cairo_pdf_ft_font_write_be16 (font, maxp->maxCompositePoints);
cairo_pdf_ft_font_write_be16 (font, maxp->maxCompositeContours);
cairo_pdf_ft_font_write_be16 (font, maxp->maxZones);
cairo_pdf_ft_font_write_be16 (font, maxp->maxTwilightPoints);
cairo_pdf_ft_font_write_be16 (font, maxp->maxStorage);
cairo_pdf_ft_font_write_be16 (font, maxp->maxFunctionDefs);
cairo_pdf_ft_font_write_be16 (font, maxp->maxInstructionDefs);
cairo_pdf_ft_font_write_be16 (font, maxp->maxStackElements);
cairo_pdf_ft_font_write_be16 (font, maxp->maxSizeOfInstructions);
cairo_pdf_ft_font_write_be16 (font, maxp->maxComponentElements);
cairo_pdf_ft_font_write_be16 (font, maxp->maxComponentDepth);
return font->status;
}
typedef struct table table_t;
struct table {
unsigned long tag;
int (*write) (cairo_pdf_ft_font_t *font, unsigned long tag);
};
static const table_t truetype_tables[] = {
/* As we write out the glyf table we remap composite glyphs.
* Remapping composite glyphs will reference the sub glyphs the
* composite glyph is made up of. That needs to be done first so
* we have all the glyphs in the subset before going further. */
{ TTAG_glyf, cairo_pdf_ft_font_write_glyf_table },
{ TTAG_cmap, cairo_pdf_ft_font_write_cmap_table },
{ TTAG_cvt, cairo_pdf_ft_font_write_generic_table },
{ TTAG_fpgm, cairo_pdf_ft_font_write_generic_table },
{ TTAG_head, cairo_pdf_ft_font_write_head_table },
{ TTAG_hhea, cairo_pdf_ft_font_write_hhea_table },
{ TTAG_hmtx, cairo_pdf_ft_font_write_hmtx_table },
{ TTAG_loca, cairo_pdf_ft_font_write_loca_table },
{ TTAG_maxp, cairo_pdf_ft_font_write_maxp_table },
{ TTAG_name, cairo_pdf_ft_font_write_generic_table },
{ TTAG_prep, cairo_pdf_ft_font_write_generic_table },
};
static cairo_status_t
cairo_pdf_ft_font_write_offset_table (cairo_pdf_ft_font_t *font)
{
cairo_status_t status;
unsigned char *table_buffer;
size_t table_buffer_length;
unsigned short search_range, entry_selector, range_shift;
int num_tables;
num_tables = ARRAY_LENGTH (truetype_tables);
search_range = 1;
entry_selector = 0;
while (search_range * 2 <= num_tables) {
search_range *= 2;
entry_selector++;
}
search_range *= 16;
range_shift = num_tables * 16 - search_range;
cairo_pdf_ft_font_write_be32 (font, SFNT_VERSION);
cairo_pdf_ft_font_write_be16 (font, num_tables);
cairo_pdf_ft_font_write_be16 (font, search_range);
cairo_pdf_ft_font_write_be16 (font, entry_selector);
cairo_pdf_ft_font_write_be16 (font, range_shift);
/* XXX: Why are we allocating a table here and then ignoring the
* returned buffer? This should result in garbage in the output
* file, correct? Is this just unfinished code? -cworth. */
table_buffer_length = ARRAY_LENGTH (truetype_tables) * 16;
status = cairo_pdf_ft_font_allocate_write_buffer (font, table_buffer_length,
&table_buffer);
if (status)
return status;
return font->status;
}
static unsigned long
cairo_pdf_ft_font_calculate_checksum (cairo_pdf_ft_font_t *font,
unsigned long start, unsigned long end)
{
unsigned long *padded_end;
unsigned long *p;
unsigned long checksum;
char *data;
checksum = 0;
data = _cairo_array_index (&font->output, 0);
p = (unsigned long *) (data + start);
padded_end = (unsigned long *) (data + ((end + 3) & ~3));
while (p < padded_end)
checksum += *p++;
return checksum;
}
static void
cairo_pdf_ft_font_update_entry (cairo_pdf_ft_font_t *font, int index, unsigned long tag,
unsigned long start, unsigned long end)
{
unsigned long *entry;
entry = _cairo_array_index (&font->output, 12 + 16 * index);
entry[0] = cpu_to_be32 (tag);
entry[1] = cpu_to_be32 (cairo_pdf_ft_font_calculate_checksum (font, start, end));
entry[2] = cpu_to_be32 (start);
entry[3] = cpu_to_be32 (end - start);
}
static cairo_status_t
cairo_pdf_ft_font_generate (void *abstract_font,
const char **data, unsigned long *length)
{
cairo_ft_unscaled_font_t *ft_unscaled_font;
cairo_pdf_ft_font_t *font = abstract_font;
unsigned long start, end, next, checksum, *checksum_location;
int i;
/* XXX: It would be cleaner to do something besides this cast
* here. Perhaps cairo_pdf_ft_font_t should just have the
* cairo_ft_unscaled_font_t rather than having the generic
* cairo_unscaled_font_t in the base class? */
ft_unscaled_font = (cairo_ft_unscaled_font_t *) font->base.unscaled_font;
font->face = _cairo_ft_unscaled_font_lock_face (ft_unscaled_font);
if (cairo_pdf_ft_font_write_offset_table (font))
goto fail;
start = cairo_pdf_ft_font_align_output (font);
end = start;
end = 0;
for (i = 0; i < ARRAY_LENGTH (truetype_tables); i++) {
if (truetype_tables[i].write (font, truetype_tables[i].tag))
goto fail;
end = _cairo_array_num_elements (&font->output);
next = cairo_pdf_ft_font_align_output (font);
cairo_pdf_ft_font_update_entry (font, i, truetype_tables[i].tag,
start, end);
start = next;
}
checksum =
0xb1b0afba - cairo_pdf_ft_font_calculate_checksum (font, 0, end);
checksum_location = _cairo_array_index (&font->output, font->checksum_index);
*checksum_location = cpu_to_be32 (checksum);
*data = _cairo_array_index (&font->output, 0);
*length = _cairo_array_num_elements (&font->output);
fail:
_cairo_ft_unscaled_font_unlock_face (ft_unscaled_font);
font->face = NULL;
return font->status;
}
static int
cairo_pdf_ft_font_use_glyph (cairo_pdf_ft_font_t *font, int glyph)
{
if (font->parent_to_subset[glyph] == 0) {
font->parent_to_subset[glyph] = font->base.num_glyphs;
font->glyphs[font->base.num_glyphs].parent_index = glyph;
font->base.num_glyphs++;
}
return font->parent_to_subset[glyph];
}
cairo_status_t
_cairo_truetype_subset_init (cairo_truetype_subset_t *truetype_subset,
cairo_scaled_font_subset_t *font_subset)
{
cairo_pdf_ft_font_t *font;
cairo_status_t status;
const char *data = NULL; /* squelch bogus compiler warning */
unsigned long parent_glyph, length = 0; /* squelch bogus compiler warning */
int i;
status = _cairo_pdf_ft_font_create (font_subset, &font);
if (status)
return status;
for (i = 0; i < font->scaled_font_subset->num_glyphs; i++) {
parent_glyph = font->scaled_font_subset->glyphs[i];
cairo_pdf_ft_font_use_glyph (font, parent_glyph);
}
status = cairo_pdf_ft_font_generate (font, &data, &length);
if (status)
goto fail1;
truetype_subset->base_font = strdup (font->base.base_font);
if (truetype_subset->base_font == NULL)
goto fail1;
truetype_subset->widths = calloc (sizeof (int), font->base.num_glyphs);
if (truetype_subset->widths == NULL)
goto fail2;
for (i = 0; i < font->base.num_glyphs; i++)
truetype_subset->widths[i] = font->base.widths[i];
truetype_subset->x_min = font->base.x_min;
truetype_subset->y_min = font->base.y_min;
truetype_subset->x_max = font->base.x_max;
truetype_subset->y_max = font->base.y_max;
truetype_subset->ascent = font->base.ascent;
truetype_subset->descent = font->base.descent;
truetype_subset->data = malloc (length);
if (truetype_subset->data == NULL)
goto fail3;
memcpy (truetype_subset->data, data, length);
truetype_subset->data_length = length;
cairo_pdf_ft_font_destroy (font);
return CAIRO_STATUS_SUCCESS;
fail3:
free (truetype_subset->widths);
fail2:
free (truetype_subset->base_font);
fail1:
cairo_pdf_ft_font_destroy (font);
return status;
}
void
_cairo_truetype_subset_fini (cairo_truetype_subset_t *subset)
{
free (subset->base_font);
free (subset->widths);
free (subset->data);
}

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

@ -49,7 +49,7 @@ static const cairo_font_face_backend_t _cairo_toy_font_face_backend;
const cairo_font_face_t _cairo_font_face_nil = {
{ 0 }, /* hash_entry */
CAIRO_STATUS_NO_MEMORY, /* status */
-1, /* ref_count */
CAIRO_REF_COUNT_INVALID, /* ref_count */
{ 0, 0, 0, NULL }, /* user_data */
&_cairo_toy_font_face_backend
};
@ -82,7 +82,7 @@ cairo_font_face_reference (cairo_font_face_t *font_face)
if (font_face == NULL)
return NULL;
if (font_face->ref_count == (unsigned int)-1)
if (font_face->ref_count == CAIRO_REF_COUNT_INVALID)
return font_face;
/* We would normally assert (font_face->ref_count >0) here but we
@ -93,6 +93,7 @@ cairo_font_face_reference (cairo_font_face_t *font_face)
return font_face;
}
slim_hidden_def (cairo_font_face_reference);
/**
* cairo_font_face_destroy:
@ -108,7 +109,7 @@ cairo_font_face_destroy (cairo_font_face_t *font_face)
if (font_face == NULL)
return;
if (font_face->ref_count == (unsigned int)-1)
if (font_face->ref_count == CAIRO_REF_COUNT_INVALID)
return;
assert (font_face->ref_count > 0);
@ -129,12 +130,16 @@ cairo_font_face_destroy (cairo_font_face_t *font_face)
free (font_face);
}
slim_hidden_def (cairo_font_face_destroy);
/**
* cairo_font_face_get_type:
* @font_face: a #cairo_font_face_t
*
* Return value: The type of @font_face. See #cairo_font_type_t.
* This function returns the type of the backend used to create
* a font face. See #cairo_font_type_t for available types.
*
* Return value: The type of @font_face.
*
* Since: 1.2
**/
@ -202,7 +207,7 @@ cairo_font_face_set_user_data (cairo_font_face_t *font_face,
void *user_data,
cairo_destroy_func_t destroy)
{
if (font_face->ref_count == -1)
if (font_face->ref_count == CAIRO_REF_COUNT_INVALID)
return CAIRO_STATUS_NO_MEMORY;
return _cairo_user_data_array_set_data (&font_face->user_data,

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

@ -48,6 +48,7 @@
#include FT_FREETYPE_H
#include FT_OUTLINE_H
#include FT_IMAGE_H
#include FT_TRUETYPE_TABLES_H
#if HAVE_FT_GLYPHSLOT_EMBOLDEN
#include FT_SYNTHESIS_H
#endif
@ -97,6 +98,7 @@ struct _cairo_ft_unscaled_font {
double y_scale; /* Extracted Y scale factor */
cairo_bool_t have_shape; /* true if the current scale has a non-scale component*/
cairo_matrix_t current_shape;
FT_Matrix Current_Shape;
int lock; /* count of how many times this font has been locked */
@ -550,6 +552,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
*/
@ -560,6 +563,7 @@ _cairo_ft_unscaled_font_unlock_face (cairo_ft_unscaled_font_t *unscaled)
unscaled->lock--;
}
slim_hidden_def (cairo_ft_scaled_font_unlock_face);
static void
_compute_transform (cairo_ft_font_transform_t *sf,
@ -601,7 +605,6 @@ _cairo_ft_unscaled_font_set_scale (cairo_ft_unscaled_font_t *unscaled,
{
cairo_ft_font_transform_t sf;
FT_Matrix mat;
FT_UInt pixel_width, pixel_height;
FT_Error error;
assert (unscaled->face != NULL);
@ -631,6 +634,7 @@ _cairo_ft_unscaled_font_set_scale (cairo_ft_unscaled_font_t *unscaled,
mat.xy != 0x00000 ||
mat.yy != 0x10000);
unscaled->Current_Shape = mat;
cairo_matrix_init (&unscaled->current_shape,
sf.shape[0][0], sf.shape[0][1],
sf.shape[1][0], sf.shape[1][1],
@ -639,19 +643,16 @@ _cairo_ft_unscaled_font_set_scale (cairo_ft_unscaled_font_t *unscaled,
FT_Set_Transform(unscaled->face, &mat, NULL);
if ((unscaled->face->face_flags & FT_FACE_FLAG_SCALABLE) != 0) {
pixel_width = sf.x_scale;
pixel_height = sf.y_scale;
error = FT_Set_Char_Size (unscaled->face,
sf.x_scale * 64.0,
sf.y_scale * 64.0,
0, 0);
assert (error == 0);
} else {
double min_distance = DBL_MAX;
int i;
int best_i = 0;
pixel_width = pixel_height = 0;
for (i = 0; i < unscaled->face->num_fixed_sizes; i++) {
#if HAVE_FT_BITMAP_SIZE_Y_PPEM
double size = unscaled->face->available_sizes[i].y_ppem / 64.;
@ -675,9 +676,8 @@ _cairo_ft_unscaled_font_set_scale (cairo_ft_unscaled_font_t *unscaled,
error = FT_Set_Pixel_Sizes (unscaled->face,
unscaled->face->available_sizes[best_i].width,
unscaled->face->available_sizes[best_i].height);
assert (error == 0);
}
assert (error == 0);
}
/* Empirically-derived subpixel filtering values thanks to Keith
@ -978,6 +978,7 @@ _render_glyph_outline (FT_Face face,
switch (font_options->subpixel_order) {
case CAIRO_SUBPIXEL_ORDER_RGB:
case CAIRO_SUBPIXEL_ORDER_BGR:
case CAIRO_SUBPIXEL_ORDER_DEFAULT:
default:
matrix.xx *= 3;
hmul = 3;
@ -1231,6 +1232,8 @@ _get_pattern_ft_options (FcPattern *pattern)
antialias = FcTrue;
if (antialias) {
cairo_subpixel_order_t subpixel_order;
if (!bitmap)
ft_options.load_flags |= FT_LOAD_NO_BITMAP;
@ -1245,25 +1248,28 @@ _get_pattern_ft_options (FcPattern *pattern)
switch (rgba) {
case FC_RGBA_RGB:
ft_options.base.subpixel_order = CAIRO_SUBPIXEL_ORDER_RGB;
subpixel_order = CAIRO_SUBPIXEL_ORDER_RGB;
break;
case FC_RGBA_BGR:
ft_options.base.subpixel_order = CAIRO_SUBPIXEL_ORDER_BGR;
subpixel_order = CAIRO_SUBPIXEL_ORDER_BGR;
break;
case FC_RGBA_VRGB:
ft_options.base.subpixel_order = CAIRO_SUBPIXEL_ORDER_VRGB;
subpixel_order = CAIRO_SUBPIXEL_ORDER_VRGB;
break;
case FC_RGBA_VBGR:
ft_options.base.subpixel_order = CAIRO_SUBPIXEL_ORDER_VBGR;
subpixel_order = CAIRO_SUBPIXEL_ORDER_VBGR;
break;
case FC_RGBA_UNKNOWN:
case FC_RGBA_NONE:
default:
subpixel_order = CAIRO_SUBPIXEL_ORDER_DEFAULT;
break;
}
if (ft_options.base.subpixel_order != CAIRO_SUBPIXEL_ORDER_DEFAULT)
if (subpixel_order != CAIRO_SUBPIXEL_ORDER_DEFAULT) {
ft_options.base.subpixel_order = subpixel_order;
ft_options.base.antialias = CAIRO_ANTIALIAS_SUBPIXEL;
}
#ifdef FC_HINT_STYLE
if (FcPatternGetInteger (pattern,
@ -1458,7 +1464,7 @@ _cairo_ft_scaled_font_create (cairo_ft_unscaled_font_t *unscaled,
fs_metrics.ascent = DOUBLE_FROM_26_6(metrics->ascender) * y_factor;
fs_metrics.descent = DOUBLE_FROM_26_6(- metrics->descender) * y_factor;
fs_metrics.height = DOUBLE_FROM_26_6(metrics->height) * y_factor;
if (!(scaled_font->ft_options.load_flags & FT_LOAD_VERTICAL_LAYOUT)) {
if (!_cairo_ft_scaled_font_is_vertical (&scaled_font->base)) {
fs_metrics.max_x_advance = DOUBLE_FROM_26_6(metrics->max_advance) * x_factor;
fs_metrics.max_y_advance = 0;
} else {
@ -1471,7 +1477,7 @@ _cairo_ft_scaled_font_create (cairo_ft_unscaled_font_t *unscaled,
fs_metrics.ascent = face->ascender / scale;
fs_metrics.descent = - face->descender / scale;
fs_metrics.height = face->height / scale;
if (!(scaled_font->ft_options.load_flags & FT_LOAD_VERTICAL_LAYOUT)) {
if (!_cairo_ft_scaled_font_is_vertical (&scaled_font->base)) {
fs_metrics.max_x_advance = face->max_advance_width / scale;
fs_metrics.max_y_advance = 0;
} else {
@ -1726,16 +1732,21 @@ _decompose_glyph_outline (FT_Face face,
* Translate glyph to match its metrics.
*/
static void
_cairo_ft_scaled_glyph_vertical_layout_bearing_fix (FT_GlyphSlot glyph)
_cairo_ft_scaled_glyph_vertical_layout_bearing_fix (void *abstract_font,
FT_GlyphSlot glyph)
{
FT_Pos x = glyph->metrics.vertBearingX - glyph->metrics.horiBearingX;
FT_Pos y = -glyph->metrics.vertBearingY - glyph->metrics.horiBearingY;
cairo_ft_scaled_font_t *scaled_font = abstract_font;
FT_Vector vector;
if (glyph->format == FT_GLYPH_FORMAT_OUTLINE)
FT_Outline_Translate(&glyph->outline, x, y);
else if (glyph->format == FT_GLYPH_FORMAT_BITMAP) {
glyph->bitmap_left += x / 64;
glyph->bitmap_top += y / 64;
vector.x = glyph->metrics.vertBearingX - glyph->metrics.horiBearingX;
vector.y = -glyph->metrics.vertBearingY - glyph->metrics.horiBearingY;
if (glyph->format == FT_GLYPH_FORMAT_OUTLINE) {
FT_Vector_Transform (&vector, &scaled_font->unscaled->Current_Shape);
FT_Outline_Translate(&glyph->outline, vector.x, vector.y);
} else if (glyph->format == FT_GLYPH_FORMAT_BITMAP) {
glyph->bitmap_left += vector.x / 64;
glyph->bitmap_top += vector.y / 64;
}
}
@ -1796,7 +1807,7 @@ _cairo_ft_scaled_glyph_init (void *abstract_font,
#endif
if (vertical_layout)
_cairo_ft_scaled_glyph_vertical_layout_bearing_fix (glyph);
_cairo_ft_scaled_glyph_vertical_layout_bearing_fix (scaled_font, glyph);
if (info & CAIRO_SCALED_GLYPH_INFO_METRICS) {
/*
@ -1815,8 +1826,7 @@ _cairo_ft_scaled_glyph_init (void *abstract_font,
y_factor = 1 / unscaled->y_scale;
/*
* Note: the font's coordinate system is upside down from ours, so the
* Y coordinates of the bearing and advance need to be negated.
* Note: Y coordinates of the horizontal bearing need to be negated.
*
* Scale metrics back to glyph space from the scaled glyph space returned
* by FreeType
@ -1934,7 +1944,7 @@ _cairo_ft_scaled_glyph_init (void *abstract_font,
FT_GlyphSlot_Embolden (glyph);
#endif
if (vertical_layout)
_cairo_ft_scaled_glyph_vertical_layout_bearing_fix (glyph);
_cairo_ft_scaled_glyph_vertical_layout_bearing_fix (scaled_font, glyph);
}
if (glyph->format == FT_GLYPH_FORMAT_OUTLINE)
@ -1990,6 +2000,36 @@ _cairo_ft_show_glyphs (void *abstract_font,
return CAIRO_INT_STATUS_UNSUPPORTED;
}
static cairo_int_status_t
_cairo_ft_load_truetype_table (void *abstract_font,
unsigned long tag,
long offset,
unsigned char *buffer,
unsigned long *length)
{
cairo_ft_scaled_font_t *scaled_font = abstract_font;
cairo_ft_unscaled_font_t *unscaled = scaled_font->unscaled;
FT_Face face;
cairo_status_t status = CAIRO_INT_STATUS_UNSUPPORTED;
if (_cairo_ft_scaled_font_is_vertical (&scaled_font->base))
return CAIRO_INT_STATUS_UNSUPPORTED;
#if HAVE_FT_LOAD_SFNT_TABLE
face = _cairo_ft_unscaled_font_lock_face (unscaled);
if (!face)
return CAIRO_STATUS_NO_MEMORY;
if (FT_IS_SFNT (face) &&
FT_Load_Sfnt_Table (face, tag, offset, buffer, length) == 0)
status = CAIRO_STATUS_SUCCESS;
_cairo_ft_unscaled_font_unlock_face (unscaled);
#endif
return status;
}
const cairo_scaled_font_backend_t cairo_ft_scaled_font_backend = {
CAIRO_FONT_TYPE_FT,
_cairo_ft_scaled_font_create_toy,
@ -1998,6 +2038,7 @@ const cairo_scaled_font_backend_t cairo_ft_scaled_font_backend = {
NULL, /* text_to_glyphs */
_cairo_ft_ucs4_to_index,
_cairo_ft_show_glyphs,
_cairo_ft_load_truetype_table,
};
/* cairo_ft_font_face_t */
@ -2157,6 +2198,10 @@ cairo_ft_font_options_substitute (const cairo_font_options_t *options,
if (FcPatternGet (pattern, FC_ANTIALIAS, 0, &v) == FcResultNoMatch)
{
FcPatternAddBool (pattern, FC_ANTIALIAS, options->antialias != CAIRO_ANTIALIAS_NONE);
if (options->antialias != CAIRO_ANTIALIAS_SUBPIXEL) {
FcPatternDel (pattern, FC_RGBA);
FcPatternAddInteger (pattern, FC_RGBA, FC_RGBA_NONE);
}
}
}
@ -2204,6 +2249,9 @@ cairo_ft_font_options_substitute (const cairo_font_options_t *options,
int hint_style;
switch (options->hint_style) {
case CAIRO_HINT_STYLE_NONE:
hint_style = FC_HINT_NONE;
break;
case CAIRO_HINT_STYLE_SLIGHT:
hint_style = FC_HINT_SLIGHT;
break;
@ -2211,6 +2259,7 @@ cairo_ft_font_options_substitute (const cairo_font_options_t *options,
hint_style = FC_HINT_MEDIUM;
break;
case CAIRO_HINT_STYLE_FULL:
case CAIRO_HINT_STYLE_DEFAULT:
default:
hint_style = FC_HINT_FULL;
break;
@ -2221,6 +2270,7 @@ cairo_ft_font_options_substitute (const cairo_font_options_t *options,
#endif
}
}
slim_hidden_def (cairo_ft_font_options_substitute);
/**
* cairo_ft_font_face_create_for_pattern:

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

@ -64,11 +64,14 @@ _cairo_ft_unscaled_font_lock_face (cairo_ft_unscaled_font_t *unscaled);
cairo_private void
_cairo_ft_unscaled_font_unlock_face (cairo_ft_unscaled_font_t *unscaled);
cairo_bool_t
cairo_private cairo_bool_t
_cairo_ft_scaled_font_is_vertical (cairo_scaled_font_t *scaled_font);
slim_hidden_proto (cairo_ft_font_options_substitute);
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 */
#endif /* CAIRO_FT_PRIVATE_H */

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

@ -492,9 +492,9 @@ _cairo_gstate_get_line_join (cairo_gstate_t *gstate)
}
cairo_status_t
_cairo_gstate_set_dash (cairo_gstate_t *gstate, double *dash, int num_dashes, double offset)
_cairo_gstate_set_dash (cairo_gstate_t *gstate, const double *dash, int num_dashes, double offset)
{
int i;
unsigned int i;
double dash_total;
if (gstate->stroke_style.dash)
@ -706,6 +706,25 @@ _cairo_gstate_backend_to_user (cairo_gstate_t *gstate, double *x, double *y)
cairo_matrix_transform_point (&gstate->ctm_inverse, x, y);
}
void
_cairo_gstate_backend_to_user_rectangle (cairo_gstate_t *gstate,
double *x1, double *y1,
double *x2, double *y2,
cairo_bool_t *is_tight)
{
double width = *x2 - *x1;
double height = *y2 - *y1;
cairo_matrix_t matrix_inverse;
cairo_matrix_multiply (&matrix_inverse, &gstate->ctm_inverse,
&gstate->target->device_transform_inverse);
_cairo_matrix_transform_bounding_box (
&matrix_inverse, x1, y1, &width, &height, is_tight);
*x2 = *x1 + width;
*y2 = *y1 + height;
}
/* XXX: NYI
cairo_status_t
_cairo_gstate_stroke_to_path (cairo_gstate_t *gstate)
@ -1041,6 +1060,29 @@ _cairo_gstate_show_page (cairo_gstate_t *gstate)
return status;
}
static void
_cairo_gstate_traps_extents_to_user_rectangle (cairo_gstate_t *gstate,
cairo_traps_t *traps,
double *x1, double *y1,
double *x2, double *y2)
{
cairo_box_t extents;
_cairo_traps_extents (traps, &extents);
if (extents.p1.x >= extents.p2.x || extents.p1.y >= extents.p2.y) {
/* no traps, so we actually won't draw anything */
*x1 = *y1 = *x2 = *y2 = 0;
} else {
*x1 = _cairo_fixed_to_double (extents.p1.x);
*y1 = _cairo_fixed_to_double (extents.p1.y);
*x2 = _cairo_fixed_to_double (extents.p2.x);
*y2 = _cairo_fixed_to_double (extents.p2.y);
_cairo_gstate_backend_to_user_rectangle (gstate, x1, y1, x2, y2, NULL);
}
}
cairo_status_t
_cairo_gstate_stroke_extents (cairo_gstate_t *gstate,
cairo_path_fixed_t *path,
@ -1049,7 +1091,6 @@ _cairo_gstate_stroke_extents (cairo_gstate_t *gstate,
{
cairo_status_t status;
cairo_traps_t traps;
cairo_box_t extents;
_cairo_traps_init (&traps);
@ -1059,20 +1100,10 @@ _cairo_gstate_stroke_extents (cairo_gstate_t *gstate,
&gstate->ctm_inverse,
gstate->tolerance,
&traps);
if (status)
goto BAIL;
if (status == CAIRO_STATUS_SUCCESS) {
_cairo_gstate_traps_extents_to_user_rectangle(gstate, &traps, x1, y1, x2, y2);
}
_cairo_traps_extents (&traps, &extents);
*x1 = _cairo_fixed_to_double (extents.p1.x);
*y1 = _cairo_fixed_to_double (extents.p1.y);
*x2 = _cairo_fixed_to_double (extents.p2.x);
*y2 = _cairo_fixed_to_double (extents.p2.y);
_cairo_gstate_backend_to_user (gstate, x1, y1);
_cairo_gstate_backend_to_user (gstate, x2, y2);
BAIL:
_cairo_traps_fini (&traps);
return status;
@ -1094,20 +1125,10 @@ _cairo_gstate_fill_extents (cairo_gstate_t *gstate,
gstate->fill_rule,
gstate->tolerance,
&traps);
if (status)
goto BAIL;
if (status == CAIRO_STATUS_SUCCESS) {
_cairo_gstate_traps_extents_to_user_rectangle(gstate, &traps, x1, y1, x2, y2);
}
_cairo_traps_extents (&traps, &extents);
*x1 = _cairo_fixed_to_double (extents.p1.x);
*y1 = _cairo_fixed_to_double (extents.p1.y);
*x2 = _cairo_fixed_to_double (extents.p2.x);
*y2 = _cairo_fixed_to_double (extents.p2.y);
_cairo_gstate_backend_to_user (gstate, x1, y1);
_cairo_gstate_backend_to_user (gstate, x2, y2);
BAIL:
_cairo_traps_fini (&traps);
return status;
@ -1127,6 +1148,40 @@ _cairo_gstate_clip (cairo_gstate_t *gstate, cairo_path_fixed_t *path)
gstate->antialias, gstate->target);
}
cairo_status_t
_cairo_gstate_clip_extents (cairo_gstate_t *gstate,
double *x1,
double *y1,
double *x2,
double *y2)
{
cairo_rectangle_int16_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);
if (status)
return status;
*x1 = extents.x;
*y1 = extents.y;
*x2 = extents.x + extents.width;
*y2 = extents.y + extents.height;
_cairo_gstate_backend_to_user_rectangle (gstate, x1, y1, x2, y2, NULL);
return CAIRO_STATUS_SUCCESS;
}
cairo_rectangle_list_t*
_cairo_gstate_copy_clip_rectangles (cairo_gstate_t *gstate)
{
return _cairo_clip_copy_rectangles (&gstate->clip, gstate);
}
static void
_cairo_gstate_unset_scaled_font (cairo_gstate_t *gstate)
{
@ -1411,7 +1466,7 @@ _cairo_gstate_glyph_extents (cairo_gstate_t *gstate,
cairo_status_t
_cairo_gstate_show_glyphs (cairo_gstate_t *gstate,
cairo_glyph_t *glyphs,
const cairo_glyph_t *glyphs,
int num_glyphs)
{
cairo_status_t status;
@ -1436,10 +1491,12 @@ _cairo_gstate_show_glyphs (cairo_gstate_t *gstate,
for (i = 0; i < num_glyphs; ++i)
{
transformed_glyphs[i] = glyphs[i];
_cairo_gstate_user_to_device (gstate,
&transformed_glyphs[i].x,
&transformed_glyphs[i].y);
transformed_glyphs[i].index = glyphs[i].index;
transformed_glyphs[i].x = glyphs[i].x + gstate->font_matrix.x0;
transformed_glyphs[i].y = glyphs[i].y + gstate->font_matrix.y0;
_cairo_gstate_user_to_backend (gstate,
&transformed_glyphs[i].x,
&transformed_glyphs[i].y);
}
_cairo_gstate_copy_transformed_source (gstate, &source_pattern.base);
@ -1477,7 +1534,9 @@ _cairo_gstate_glyph_path (cairo_gstate_t *gstate,
for (i = 0; i < num_glyphs; ++i)
{
transformed_glyphs[i] = glyphs[i];
transformed_glyphs[i].index = glyphs[i].index;
transformed_glyphs[i].x = glyphs[i].x + gstate->font_matrix.x0;
transformed_glyphs[i].y = glyphs[i].y + gstate->font_matrix.y0;
_cairo_gstate_user_to_backend (gstate,
&(transformed_glyphs[i].x),
&(transformed_glyphs[i].y));
@ -1505,21 +1564,3 @@ _cairo_gstate_get_antialias (cairo_gstate_t *gstate)
{
return gstate->antialias;
}
cairo_bool_t
_cairo_gstate_has_clip (cairo_gstate_t *gstate)
{
return _cairo_clip_has_clip (&gstate->clip);
}
cairo_bool_t
_cairo_gstate_extract_clip_rectangles (cairo_gstate_t *gstate,
int max_rectangles,
cairo_clip_rect_t *rectangles_out,
int *num_rectangles_out)
{
return _cairo_clip_extract_rectangles (&gstate->clip,
max_rectangles,
rectangles_out,
num_rectangles_out);
}

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

@ -115,7 +115,7 @@ static const cairo_hash_table_arrangement_t hash_table_arrangements [] = {
{ 268435456, 590559793, 590559791 }
};
#define NUM_HASH_TABLE_ARRANGEMENTS (sizeof(hash_table_arrangements)/sizeof(hash_table_arrangements[0]))
#define NUM_HASH_TABLE_ARRANGEMENTS ((int)(sizeof(hash_table_arrangements)/sizeof(hash_table_arrangements[0])))
struct _cairo_hash_table {
cairo_hash_keys_equal_func_t keys_equal;

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

@ -44,8 +44,6 @@ _cairo_format_bpp (cairo_format_t format)
return 1;
case CAIRO_FORMAT_A8:
return 8;
case CAIRO_FORMAT_RGB16_565:
return 16;
case CAIRO_FORMAT_RGB24:
case CAIRO_FORMAT_ARGB32:
return 32;
@ -90,22 +88,33 @@ _cairo_image_surface_create_for_pixman_image (pixman_image_t *pixman_image,
static cairo_format_t
_cairo_format_from_pixman_format (pixman_format_t *pixman_format)
{
int bpp, am, rm, gm, bm;
unsigned int bpp, am, rm, gm, bm;
pixman_format_get_masks (pixman_format, &bpp, &am, &rm, &gm, &bm);
/* See definition of cairo_internal_format_t for an explanation of
* the CAIRO_INTERNAL_FORMAT values used here. */
switch (bpp) {
case 32:
if (am == 0xff000000 &&
rm == 0x00ff0000 &&
gm == 0x0000ff00 &&
bm == 0x000000ff)
return CAIRO_FORMAT_ARGB32;
if (am == 0x0 &&
rm == 0x00ff0000 &&
gm == 0x0000ff00 &&
bm == 0x000000ff)
return CAIRO_FORMAT_RGB24;
if (am == 0xff000000) {
if (rm == 0x00ff0000 &&
gm == 0x0000ff00 &&
bm == 0x000000ff)
return CAIRO_FORMAT_ARGB32;
if (rm == 0x000000ff &&
gm == 0x0000ff00 &&
bm == 0x00ff0000)
return CAIRO_INTERNAL_FORMAT_ABGR32;
} else if (am == 0x0) {
if (rm == 0x00ff0000 &&
gm == 0x0000ff00 &&
bm == 0x000000ff)
return CAIRO_FORMAT_RGB24;
if (rm == 0x000000ff &&
gm == 0x0000ff00 &&
bm == 0x00ff0000)
return CAIRO_INTERNAL_FORMAT_BGR24;
}
break;
case 16:
if (am == 0x0 &&
@ -131,13 +140,13 @@ _cairo_format_from_pixman_format (pixman_format_t *pixman_format)
}
fprintf (stderr,
"Error: Cairo does not yet support the requested image format:\n"
"Error: Cairo " PACKAGE_VERSION " does not yet support the requested image format:\n"
"\tDepth: %d\n"
"\tAlpha mask: 0x%08x\n"
"\tRed mask: 0x%08x\n"
"\tGreen mask: 0x%08x\n"
"\tBlue mask: 0x%08x\n"
"Please file an enhacement request (quoting the above) at:\n"
"Please file an enhancement request (quoting the above) at:\n"
PACKAGE_BUGREPORT "\n",
bpp, am, rm, gm, bm);
@ -145,6 +154,10 @@ _cairo_format_from_pixman_format (pixman_format_t *pixman_format)
return (cairo_format_t) -1;
}
/* XXX: This function really should be eliminated. We don't really
* want to advertise a cairo image surface that supports any possible
* format. A minimal step would be to replace this function with one
* that accepts a cairo_internal_format_t rather than mask values. */
cairo_surface_t *
_cairo_image_surface_create_with_masks (unsigned char *data,
cairo_format_masks_t *format,
@ -196,9 +209,6 @@ _create_pixman_format (cairo_format_t format)
case CAIRO_FORMAT_A8:
return pixman_format_create (PIXMAN_FORMAT_NAME_A8);
break;
case CAIRO_FORMAT_RGB16_565:
return pixman_format_create (PIXMAN_FORMAT_NAME_RGB16_565);
break;
case CAIRO_FORMAT_RGB24:
return pixman_format_create (PIXMAN_FORMAT_NAME_RGB24);
break;
@ -260,6 +270,7 @@ cairo_image_surface_create (cairo_format_t format,
return surface;
}
slim_hidden_def (cairo_image_surface_create);
cairo_surface_t *
_cairo_image_surface_create_with_content (cairo_content_t content,
@ -339,6 +350,7 @@ cairo_image_surface_create_for_data (unsigned char *data,
return surface;
}
slim_hidden_def (cairo_image_surface_create_for_data);
cairo_surface_t *
_cairo_image_surface_create_for_data_with_content (unsigned char *data,
@ -400,6 +412,8 @@ cairo_image_surface_get_format (cairo_surface_t *surface)
return 0;
}
assert (CAIRO_FORMAT_VALID (image_surface->format));
return image_surface->format;
}
@ -423,6 +437,7 @@ cairo_image_surface_get_width (cairo_surface_t *surface)
return image_surface->width;
}
slim_hidden_def (cairo_image_surface_get_width);
/**
* cairo_image_surface_get_height:
@ -444,6 +459,7 @@ cairo_image_surface_get_height (cairo_surface_t *surface)
return image_surface->height;
}
slim_hidden_def (cairo_image_surface_get_height);
/**
* cairo_image_surface_get_stride:
@ -491,11 +507,20 @@ _cairo_format_from_content (cairo_content_t content)
cairo_content_t
_cairo_content_from_format (cairo_format_t format)
{
switch (format) {
/* XXX: Use an int to avoid the warnings from mixed cairo_format_t
* and cairo_internal_format_t values. The warnings are extremely
* valuable since mixing enums can lead to subtle bugs. It's just
* that cairo_internal_format_t is an interim approach to getting
* bug #7294 fixed so we can release cairo 1.2.2 . */
int f = format;
switch (f) {
case CAIRO_FORMAT_ARGB32:
case CAIRO_INTERNAL_FORMAT_ABGR32:
return CAIRO_CONTENT_COLOR_ALPHA;
case CAIRO_FORMAT_RGB24:
case CAIRO_FORMAT_RGB16_565:
case CAIRO_INTERNAL_FORMAT_BGR24:
return CAIRO_CONTENT_COLOR;
case CAIRO_FORMAT_A8:
case CAIRO_FORMAT_A1:
@ -639,6 +664,12 @@ _cairo_image_surface_set_filter (cairo_image_surface_t *surface, cairo_filter_t
case CAIRO_FILTER_BILINEAR:
pixman_filter = PIXMAN_FILTER_BILINEAR;
break;
case CAIRO_FILTER_GAUSSIAN:
/* XXX: The GAUSSIAN value has no implementation in cairo
* whatsoever, so it was really a mistake to have it in the
* API. We could fix this by officially deprecating it, or
* else inventing semantics and providing an actual
* implementation for it. */
default:
pixman_filter = PIXMAN_FILTER_BEST;
}
@ -895,6 +926,9 @@ _cairo_image_surface_composite_trapezoids (cairo_operator_t op,
mask_stride = (width + 31)/8;
mask_bpp = 1;
break;
case CAIRO_ANTIALIAS_GRAY:
case CAIRO_ANTIALIAS_SUBPIXEL:
case CAIRO_ANTIALIAS_DEFAULT:
default:
format = pixman_format_create (PIXMAN_FORMAT_NAME_A8);
mask_stride = (width + 3) & ~3;
@ -1015,3 +1049,29 @@ const cairo_surface_backend_t cairo_image_surface_backend = {
_cairo_image_surface_get_extents,
NULL /* old_show_glyphs */
};
/* A convenience function for when one needs to coerce an image
* surface to an alternate format. */
cairo_image_surface_t *
_cairo_image_surface_clone (cairo_image_surface_t *surface,
cairo_format_t format)
{
cairo_image_surface_t *clone;
cairo_t *cr;
double x, y;
clone = (cairo_image_surface_t *)
cairo_image_surface_create (format,
surface->width, surface->height);
cr = cairo_create (&clone->base);
cairo_surface_get_device_offset (&surface->base, &x, &y);
cairo_set_source_surface (cr, &surface->base, x, y);
cairo_set_operator (cr, CAIRO_OPERATOR_SOURCE);
cairo_paint (cr);
cairo_destroy (cr);
cairo_surface_set_device_offset (&clone->base, x, y);
return clone;
}

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

@ -43,7 +43,7 @@ typedef struct _lzw_buf {
int data_size;
int num_data;
uint32_t pending;
int pending_bits;
unsigned int pending_bits;
} lzw_buf_t;
/* An lzw_buf_t is a simple, growable chunk of memory for holding
@ -67,6 +67,10 @@ _lzw_buf_init (lzw_buf_t *buf, int size)
size = 16;
buf->status = CAIRO_STATUS_SUCCESS;
buf->data_size = size;
buf->num_data = 0;
buf->pending = 0;
buf->pending_bits = 0;
buf->data = malloc (size);
if (buf->data == NULL) {
@ -74,11 +78,6 @@ _lzw_buf_init (lzw_buf_t *buf, int size)
buf->status = CAIRO_STATUS_NO_MEMORY;
return;
}
buf->data_size = size;
buf->num_data = 0;
buf->pending = 0;
buf->pending_bits = 0;
}
/* Increase the buffer size by doubling.

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

@ -170,6 +170,7 @@ cairo_matrix_translate (cairo_matrix_t *matrix, double tx, double ty)
cairo_matrix_multiply (matrix, &tmp, matrix);
}
slim_hidden_def (cairo_matrix_translate);
/**
* cairo_matrix_init_scale:
@ -357,7 +358,8 @@ slim_hidden_def(cairo_matrix_transform_point);
void
_cairo_matrix_transform_bounding_box (const cairo_matrix_t *matrix,
double *x, double *y,
double *width, double *height)
double *width, double *height,
cairo_bool_t *is_tight)
{
int i;
double quad_x[4], quad_y[4];
@ -404,6 +406,21 @@ _cairo_matrix_transform_bounding_box (const cairo_matrix_t *matrix,
*y = min_y;
*width = max_x - min_x;
*height = max_y - min_y;
if (is_tight) {
/* it's tight if and only if the four corner points form an axis-aligned
rectangle.
And that's true if and only if we can derive corners 0 and 3 from
corners 1 and 2 in one of two straightforward ways...
We could use a tolerance here but for now we'll fall back to FALSE in the case
of floating point error.
*/
*is_tight =
(quad_x[1] == quad_x[0] && quad_y[1] == quad_y[3] &&
quad_x[2] == quad_x[3] && quad_y[2] == quad_y[0]) ||
(quad_x[1] == quad_x[3] && quad_y[1] == quad_y[0] &&
quad_x[2] == quad_x[0] && quad_y[2] == quad_y[3]);
}
}
static void

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

@ -97,7 +97,7 @@ typedef struct _cairo_command_show_glyphs {
cairo_operator_t op;
cairo_pattern_union_t source;
cairo_glyph_t *glyphs;
int num_glyphs;
unsigned int num_glyphs;
cairo_scaled_font_t *scaled_font;
} cairo_command_show_glyphs_t;

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

@ -615,6 +615,26 @@ static const cairo_surface_backend_t cairo_meta_surface_backend = {
_cairo_meta_surface_snapshot
};
static cairo_path_fixed_t *
_cairo_command_get_path (cairo_command_t *command)
{
switch (command->type) {
case CAIRO_COMMAND_PAINT:
case CAIRO_COMMAND_MASK:
case CAIRO_COMMAND_SHOW_GLYPHS:
return NULL;
case CAIRO_COMMAND_STROKE:
return &command->stroke.path;
case CAIRO_COMMAND_FILL:
return &command->fill.path;
case CAIRO_COMMAND_INTERSECT_CLIP_PATH:
return command->intersect_clip_path.path_pointer;
}
ASSERT_NOT_REACHED;
return NULL;
}
cairo_status_t
_cairo_meta_surface_replay (cairo_surface_t *surface,
cairo_surface_t *target)
@ -624,6 +644,9 @@ _cairo_meta_surface_replay (cairo_surface_t *surface,
int i, num_elements;
cairo_int_status_t status;
cairo_clip_t clip;
cairo_bool_t has_device_transform = _cairo_surface_has_device_transform (target);
cairo_matrix_t *device_transform = &target->device_transform;
cairo_path_fixed_t path_copy, *dev_path;
meta = (cairo_meta_surface_t *) surface;
status = CAIRO_STATUS_SUCCESS;
@ -634,89 +657,118 @@ _cairo_meta_surface_replay (cairo_surface_t *surface,
elements = _cairo_array_index (&meta->commands, 0);
for (i = meta->replay_start_idx; i < num_elements; i++) {
command = elements[i];
switch (command->type) {
case CAIRO_COMMAND_PAINT:
/* For all commands except intersect_clip_path, we have to
* ensure the current clip gets set on the surface. */
if (command->type != CAIRO_COMMAND_INTERSECT_CLIP_PATH) {
status = _cairo_surface_set_clip (target, &clip);
if (status)
break;
}
dev_path = _cairo_command_get_path (command);
if (dev_path && has_device_transform) {
_cairo_path_fixed_init_copy (&path_copy, dev_path);
_cairo_path_fixed_device_transform (&path_copy, device_transform);
dev_path = &path_copy;
}
switch (command->type) {
case CAIRO_COMMAND_PAINT:
status = _cairo_surface_paint (target,
command->paint.op,
&command->paint.source.base);
break;
case CAIRO_COMMAND_MASK:
status = _cairo_surface_set_clip (target, &clip);
if (status)
break;
status = _cairo_surface_mask (target,
command->mask.op,
&command->mask.source.base,
&command->mask.mask.base);
break;
case CAIRO_COMMAND_STROKE:
status = _cairo_surface_set_clip (target, &clip);
if (status)
break;
{
cairo_matrix_t dev_ctm = command->stroke.ctm;
cairo_matrix_t dev_ctm_inverse = command->stroke.ctm_inverse;
cairo_matrix_t tmp;
if (has_device_transform) {
cairo_matrix_multiply (&dev_ctm, &dev_ctm, device_transform);
tmp = surface->device_transform;
status = cairo_matrix_invert (&tmp);
assert (status == CAIRO_STATUS_SUCCESS);
cairo_matrix_multiply (&dev_ctm_inverse, &tmp, &dev_ctm_inverse);
}
status = _cairo_surface_stroke (target,
command->stroke.op,
&command->stroke.source.base,
&command->stroke.path,
dev_path,
&command->stroke.style,
&command->stroke.ctm,
&command->stroke.ctm_inverse,
&dev_ctm,
&dev_ctm_inverse,
command->stroke.tolerance,
command->stroke.antialias);
break;
}
case CAIRO_COMMAND_FILL:
status = _cairo_surface_set_clip (target, &clip);
if (status)
break;
status = _cairo_surface_fill (target,
command->fill.op,
&command->fill.source.base,
&command->fill.path,
dev_path,
command->fill.fill_rule,
command->fill.tolerance,
command->fill.antialias);
break;
case CAIRO_COMMAND_SHOW_GLYPHS:
status = _cairo_surface_set_clip (target, &clip);
if (status)
break;
{
cairo_glyph_t *glyphs = command->show_glyphs.glyphs;
cairo_glyph_t *dev_glyphs = glyphs;
int i, num_glyphs = command->show_glyphs.num_glyphs;
if (has_device_transform) {
dev_glyphs = malloc (sizeof (cairo_glyph_t) * num_glyphs);
if (dev_glyphs == NULL) {
status = CAIRO_STATUS_NO_MEMORY;
break;
}
for (i = 0; i < num_glyphs; i++) {
dev_glyphs[i] = glyphs[i];
cairo_matrix_transform_point (device_transform,
&dev_glyphs[i].x,
&dev_glyphs[i].y);
}
}
status = _cairo_surface_show_glyphs (target,
command->show_glyphs.op,
&command->show_glyphs.source.base,
command->show_glyphs.glyphs,
command->show_glyphs.num_glyphs,
dev_glyphs, num_glyphs,
command->show_glyphs.scaled_font);
break;
if (dev_glyphs != glyphs)
free (dev_glyphs);
break;
}
case CAIRO_COMMAND_INTERSECT_CLIP_PATH:
/* XXX Meta surface clipping is broken and requires some
* cairo-gstate.c rewriting. Work around it for now. */
if (command->intersect_clip_path.path_pointer == NULL)
if (dev_path == NULL)
status = _cairo_clip_reset (&clip);
else
status = _cairo_clip_clip (&clip,
command->intersect_clip_path.path_pointer,
status = _cairo_clip_clip (&clip, dev_path,
command->intersect_clip_path.fill_rule,
command->intersect_clip_path.tolerance,
command->intersect_clip_path.antialias,
target);
break;
default:
ASSERT_NOT_REACHED;
}
if (dev_path == &path_copy)
_cairo_path_fixed_fini (&path_copy);
if (status)
break;
}

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

@ -31,7 +31,7 @@
* The Initial Developer of the Original Code is Mozilla Corporation.
*
* Contributor(s):
* Vladimir Vukicevic <vladimir@mozilla.com>
* Vladimir Vukicevic <vladimir@mozilla.com>
*/
#include <Carbon/Carbon.h>
@ -50,28 +50,28 @@
#undef NQUARTZ_DEBUG
#ifdef NQUARTZ_DEBUG
#define ND(_x) fprintf _x
#define ND(_x) fprintf _x
#else
#define ND(_x) do {} while(0)
#define ND(_x) do {} while(0)
#endif
/* This method is private, but it exists. Its params are are exposed
* as args to the NS* method, but not as CG.
*/
enum PrivateCGCompositeMode {
kPrivateCGCompositeClear = 0,
kPrivateCGCompositeCopy = 1,
kPrivateCGCompositeSourceOver = 2,
kPrivateCGCompositeSourceIn = 3,
kPrivateCGCompositeSourceOut = 4,
kPrivateCGCompositeSourceAtop = 5,
kPrivateCGCompositeDestinationOver = 6,
kPrivateCGCompositeDestinationIn = 7,
kPrivateCGCompositeDestinationOut = 8,
kPrivateCGCompositeDestinationAtop = 9,
kPrivateCGCompositeXOR = 10,
kPrivateCGCompositePlusDarker = 11, // (max (0, (1-d) + (1-s)))
kPrivateCGCompositePlusLighter = 12, // (min (1, s + d))
kPrivateCGCompositeClear = 0,
kPrivateCGCompositeCopy = 1,
kPrivateCGCompositeSourceOver = 2,
kPrivateCGCompositeSourceIn = 3,
kPrivateCGCompositeSourceOut = 4,
kPrivateCGCompositeSourceAtop = 5,
kPrivateCGCompositeDestinationOver = 6,
kPrivateCGCompositeDestinationIn = 7,
kPrivateCGCompositeDestinationOut = 8,
kPrivateCGCompositeDestinationAtop = 9,
kPrivateCGCompositeXOR = 10,
kPrivateCGCompositePlusDarker = 11, // (max (0, (1-d) + (1-s)))
kPrivateCGCompositePlusLighter = 12, // (min (1, s + d))
};
typedef enum PrivateCGCompositeMode PrivateCGCompositeMode;
CG_EXTERN void CGContextSetCompositeOperation (CGContextRef, PrivateCGCompositeMode);
@ -683,8 +683,8 @@ _cairo_nquartz_setup_source (cairo_nquartz_surface_t *surface,
// pattern (which may be stack allocated)
CGContextSaveGState(surface->cgContext);
CGColorSpaceRef patternSpace = CGColorSpaceCreatePattern(NULL);
CGContextSetFillColorSpace (surface->cgContext, patternSpace);
CGColorSpaceRef patternSpace = CGColorSpaceCreatePattern(NULL);
CGContextSetFillColorSpace (surface->cgContext, patternSpace);
CGContextSetFillPattern (surface->cgContext, pattern, &patternAlpha);
CGColorSpaceRelease (patternSpace);
@ -732,7 +732,7 @@ static void
ImageDataReleaseFunc(void *info, const void *data, size_t size)
{
if (data != NULL) {
free((void *) data);
free((void *) data);
}
}
@ -941,7 +941,7 @@ _cairo_nquartz_surface_acquire_dest_image (void *abstract_surface,
status = _cairo_nquartz_get_image (surface, image_out, &data);
if (status)
return status;
return status;
*image_extra = data;
@ -1521,7 +1521,7 @@ _cairo_nquartz_surface_create_internal (CGContextRef cgContext,
/* Init the base surface */
surface = malloc(sizeof(cairo_nquartz_surface_t));
if (surface == NULL) {
_cairo_error (CAIRO_STATUS_NO_MEMORY);
_cairo_error (CAIRO_STATUS_NO_MEMORY);
return NULL;
}
@ -1578,7 +1578,7 @@ cairo_nquartz_surface_create_for_agl_context (AGLContext aglContext,
if (!surf) {
CGContextRelease (cgc);
// create_internal will have set an error
return (cairo_surface_t*) &_cairo_surface_nil;
return (cairo_surface_t*) &_cairo_surface_nil;
}
return (cairo_surface_t *) surf;
@ -1600,7 +1600,7 @@ cairo_nquartz_surface_create_for_cg_context (CGContextRef cgContext,
if (!surf) {
CGContextRelease (cgContext);
// create_internal will have set an error
return (cairo_surface_t*) &_cairo_surface_nil;
return (cairo_surface_t*) &_cairo_surface_nil;
}
return (cairo_surface_t *) surf;
@ -1643,17 +1643,17 @@ cairo_nquartz_surface_create (cairo_format_t format,
* quantities.
*/
_cairo_error (CAIRO_STATUS_INVALID_FORMAT);
return (cairo_surface_t*) &_cairo_surface_nil;
return (cairo_surface_t*) &_cairo_surface_nil;
} else {
_cairo_error (CAIRO_STATUS_INVALID_FORMAT);
return (cairo_surface_t*) &_cairo_surface_nil;
return (cairo_surface_t*) &_cairo_surface_nil;
}
imageData = malloc (height * stride);
if (!imageData) {
CGColorSpaceRelease (cgColorspace);
_cairo_error (CAIRO_STATUS_NO_MEMORY);
return (cairo_surface_t*) &_cairo_surface_nil;
return (cairo_surface_t*) &_cairo_surface_nil;
}
cgc = CGBitmapContextCreate (imageData,
@ -1666,7 +1666,7 @@ cairo_nquartz_surface_create (cairo_format_t format,
CGColorSpaceRelease (cgColorspace);
if (!cgc) {
_cairo_error (CAIRO_STATUS_NO_MEMORY);
_cairo_error (CAIRO_STATUS_NO_MEMORY);
return (cairo_surface_t*) &_cairo_surface_nil;
}
@ -1675,7 +1675,7 @@ cairo_nquartz_surface_create (cairo_format_t format,
if (!surf) {
CGContextRelease (cgc);
// create_internal will have set an error
return (cairo_surface_t*) &_cairo_surface_nil;
return (cairo_surface_t*) &_cairo_surface_nil;
}
surf->imageData = imageData;
@ -1714,34 +1714,34 @@ void ExportCGImageToPNGFile(CGImageRef inImageRef, char* dest)
// create the data reference
result = QTNewDataReferenceFromFullPathCFString(inPath, kQTNativeDefaultPathStyle,
0, &dataRef, &dataRefType);
0, &dataRef, &dataRefType);
if (NULL != dataRef && noErr == result) {
// get the PNG exporter
result = OpenADefaultComponent(GraphicsExporterComponentType, kQTFileTypePNG,
&grex);
// get the PNG exporter
result = OpenADefaultComponent(GraphicsExporterComponentType, kQTFileTypePNG,
&grex);
if (grex) {
// tell the exporter where to find its source image
result = GraphicsExportSetInputCGImage(grex, inImageRef);
if (grex) {
// tell the exporter where to find its source image
result = GraphicsExportSetInputCGImage(grex, inImageRef);
if (noErr == result) {
// tell the exporter where to save the exporter image
result = GraphicsExportSetOutputDataReference(grex, dataRef,
dataRefType);
if (noErr == result) {
// tell the exporter where to save the exporter image
result = GraphicsExportSetOutputDataReference(grex, dataRef,
dataRefType);
if (noErr == result) {
// write the PNG file
result = GraphicsExportDoExport(grex, &sizeWritten);
}
}
if (noErr == result) {
// write the PNG file
result = GraphicsExportDoExport(grex, &sizeWritten);
}
}
// remember to close the component
CloseComponent(grex);
}
// remember to close the component
CloseComponent(grex);
}
// remember to dispose of the data reference handle
DisposeHandle(dataRef);
// remember to dispose of the data reference handle
DisposeHandle(dataRef);
}
}
#endif

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

@ -46,29 +46,29 @@
CAIRO_BEGIN_DECLS
cairo_surface_t *
cairo_public cairo_surface_t *
cairo_nquartz_surface_create (cairo_format_t format,
unsigned int width,
unsigned int height);
#ifdef CAIRO_NQUARTZ_SUPPORT_AGL
cairo_surface_t *
cairo_public cairo_surface_t *
cairo_nquartz_surface_create_for_agl_context (AGLContext aglContext,
unsigned int width,
unsigned int height,
cairo_bool_t y_grows_down);
#endif
cairo_surface_t *
cairo_public cairo_surface_t *
cairo_nquartz_surface_create_for_cg_context (CGContextRef cgContext,
unsigned int width,
unsigned int height,
cairo_bool_t y_grows_down);
cairo_bool_t
cairo_public cairo_bool_t
cairo_surface_is_nquartz (cairo_surface_t *surf);
CGContextRef
cairo_public CGContextRef
cairo_nquartz_surface_get_cg_context (cairo_surface_t *surf);
CAIRO_END_DECLS

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

@ -1,6 +1,7 @@
/* vim: set sw=4 sts=4 et cin: */
/* cairo - a vector graphics library with display and print output
*
* Copyright © 2004 Red Hat, Inc
* Copyright (c) 2005-2006 netlabs.org
*
* This library is free software; you can redistribute it and/or
* modify it either under the terms of the GNU Lesser General Public
@ -27,41 +28,50 @@
*
* The Original Code is the cairo graphics library.
*
* The Initial Developer of the Original Code is Red Hat, Inc.
* The Initial Developer of the Original Code is
* Doodle <doodle@scenergy.dfmk.hu>
*
* Contributor(s):
* Kristian Høgsberg <krh@redhat.com>
* Peter Weilbacher <mozilla@Weilbacher.org>
*/
#include "cairoint.h"
#ifndef CAIRO_OS2_PRIVATE_H
#define CAIRO_OS2_PRIVATE_H
#ifndef CAIRO_FONT_SUBSET_PRIVATE_H
#define CAIRO_FONT_SUBSET_PRIVATE_H
#define INCL_DOS
#define INCL_DOSSEMAPHORES
#define INCL_DOSERRORS
#define INCL_WIN
#define INCL_GPI
#ifdef __WATCOMC__
# include <os2.h>
#else
# include <os2emx.h>
#endif
typedef struct cairo_font_subset_backend cairo_font_subset_backend_t;
typedef struct cairo_font_subset cairo_font_subset_t;
struct cairo_font_subset {
cairo_font_subset_backend_t *backend;
cairo_unscaled_font_t *unscaled_font;
unsigned int font_id;
char *base_font;
int num_glyphs;
int *widths;
long x_min, y_min, x_max, y_max;
long ascent, descent;
};
#include <cairo-os2.h>
#include <cairoint.h>
cairo_private int
_cairo_font_subset_use_glyph (cairo_font_subset_t *font, int glyph);
typedef struct _cairo_os2_surface
{
cairo_surface_t base;
cairo_private cairo_status_t
_cairo_font_subset_generate (cairo_font_subset_t *font,
const char **data, unsigned long *length);
/* Mutex semaphore to protect private fields from concurrent access */
HMTX hmtx_use_private_fields;
/* Private fields: */
HPS hps_client_window;
HWND hwnd_client_window;
BITMAPINFO2 bitmap_info;
unsigned char *pixels;
cairo_image_surface_t *image_surface;
int pixel_array_lend_count;
HEV hev_pixel_array_came_back;
cairo_private void
_cairo_font_subset_destroy (cairo_font_subset_t *font);
RECTL rcl_dirty_area;
cairo_bool_t dirty_area_present;
cairo_private cairo_font_subset_t *
_cairo_font_subset_create (cairo_unscaled_font_t *unscaled_font);
/* General flags: */
cairo_bool_t blit_as_changes;
} cairo_os2_surface_t;
#endif /* CAIRO_FONT_SUBSET_PRIVATE_H */
#endif /* CAIRO_OS2_PRIVATE_H */

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

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

@ -0,0 +1,201 @@
/* vim: set sw=4 sts=4 et cin: */
/* cairo - a vector graphics library with display and print output
*
* Copyright (c) 2005-2006 netlabs.org
*
* 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
* Doodle <doodle@scenergy.dfmk.hu>
*
* Contributor(s):
* Peter Weilbacher <mozilla@Weilbacher.org>
*/
#ifndef _CAIRO_OS2_H_
#define _CAIRO_OS2_H_
#include <cairo.h>
CAIRO_BEGIN_DECLS
/* The OS/2 Specific Cairo API */
/* cairo_os2_init () : */
/* */
/* Initializes the Cairo library. This function is automatically */
/* called if Cairo was compiled to be a DLL (however it's not a */
/* problem if it's called multiple times), but if you link to */
/* Cairo statically, you have to call it once to set up Cairo's */
/* internal structures and mutexes. */
cairo_public void
cairo_os2_init (void);
/* cairo_os2_fini () : */
/* */
/* Uninitializes the Cairo library. This function is automatically */
/* called if Cairo was compiled to be a DLL (however it's not a */
/* problem if it's called multiple times), but if you link to */
/* Cairo statically, you have to call it once to shut down Cairo, */
/* to let it free all the resources it has allocated. */
cairo_public void
cairo_os2_fini (void);
#if CAIRO_HAS_OS2_SURFACE
/* cairo_os2_surface_create () : */
/* */
/* Create a Cairo surface which is bounded to a given presentation */
/* space (HPS). The surface will be created to have the given */
/* size. */
/* By default: Every change to the surface will be made visible */
/* immediately by blitting it into the window. This */
/* can be changed with the */
/* cairo_os2_surface_set_manual_window_refresh () API. */
/* Note that the surface will contain garbage when created, so the */
/* pixels have to be initialized by hand first. You can use the */
/* Cairo functions to fill it with black, or use the */
/* cairo_surface_mark_dirty () API to fill the surface with pixels */
/* from the window/HPS. */
cairo_public cairo_surface_t *
cairo_os2_surface_create (HPS hps_client_window,
int width,
int height);
/* cairo_os2_surface_set_hwnd () : */
/* */
/* Sets window handle for surface. If Cairo wants to blit into the */
/* window because it's set that it should blit as the surface */
/* changes (see cairo_os2_surface_set_manual_window_refresh () API),*/
/* then there are two ways it can choose: */
/* If it knows the HWND of the surface, then it invalidates that */
/* area, so the application will get a WM_PAINT message and it can */
/* call cairo_os2_surface_refresh_window () to redraw that area. */
/* Otherwise cairo itself will use the HPS it got at surface */
/* creation time, and blit the pixels itself. */
/* It's also a solution, but experience shows that if this happens */
/* from a non-PM thread, then it can screw up PM internals. */
/* */
/* So, best solution is to set the HWND for the surface after the */
/* surface creation, so every blit will be done from application's */
/* message processing loop, which is the safest way to do. */
cairo_public void
cairo_os2_surface_set_hwnd (cairo_surface_t *surface,
HWND hwnd_client_window);
/* cairo_os2_surface_set_size () : */
/* */
/* When the client window is resized, call this API so the */
/* underlaying surface will also be resized. This function will */
/* reallocate everything, so you'll have to redraw everything in */
/* the surface after this call. */
/* The surface will contain garbage after the resizing, just like */
/* after cairo_os2_surface_create (), so all those notes also apply */
/* here, please read that! */
/* */
/* The timeout value is in milliseconds, and tells how much the */
/* function should wait on other parts of the program to release */
/* the buffers. It is necessary, because it can be that Cairo is */
/* just drawing something into the surface while we want to */
/* destroy and recreate it. */
/* Returns CAIRO_STATUS_SUCCESS if the surface could be resized, */
/* or returns other error code if */
/* - the surface is not a real OS/2 Surface */
/* - there is not enough memory to resize the surface */
/* - waiting for all the buffers to be released timed out */
cairo_public int
cairo_os2_surface_set_size (cairo_surface_t *surface,
int new_width,
int new_height,
int timeout);
/* cairo_os2_surface_refresh_window () : */
/* */
/* This function can be used to force a repaint of a given area */
/* of the client window. Most of the time it is called from the */
/* WM_PAINT processing of the window proc. However, it can be */
/* called anytime if a given part of the window has to be updated. */
/* */
/* The function expects a HPS of the window, and a RECTL to tell */
/* which part of the window should be redrawn. */
/* The returned values of WinBeginPaint () is just perfect here, */
/* but you can also get the HPS by using the WinGetPS () function, */
/* and you can assemble your own update rect by hand. */
/* If the hps_begin_paint parameter is NULL, the function will use */
/* the HPS you passed in to cairo_os2_surface_create (). If the */
/* prcl_begin_paint_rect parameter is NULL, the function will query */
/* the current window size and repaint the whole window. */
/* */
/* Cairo/2 assumes that if you told the HWND to the surface using */
/* the cairo_os2_surface_set_hwnd () API, then this function will */
/* be called by the application every time it gets a WM_PAINT for */
/* that HWND. If the HWND is told to the surface, Cairo uses this */
/* function to handle dirty areas too, so you were warned. :) */
cairo_public void
cairo_os2_surface_refresh_window (cairo_surface_t *surface,
HPS hps_begin_paint,
PRECTL prcl_begin_paint_rect);
/* cairo_os2_surface_set_manual_window_refresh () : */
/* */
/* This API can tell Cairo if it should show every change to this */
/* surface immediately in the window, or if it should be cached */
/* and will only be visible if the user calls the */
/* cairo_os2_surface_refresh_window () API explicitly. */
/* If the HWND was not told to Cairo, then it will use the HPS to */
/* blit the graphics. Otherwise it will invalidate the given */
/* window region so the user will get WM_PAINT to redraw that area */
/* of the window. */
/* */
/* So, if you're only interested in displaying the final result */
/* after several drawing operations, you might get better */
/* performance if you put the surface into a manual refresh mode */
/* by passing a true value to cairo_os2_surface_set_manual_refresh()*/
/* and then calling cairo_os2_surface_refresh() whenever desired. */
cairo_public void
cairo_os2_surface_set_manual_window_refresh (cairo_surface_t *surface,
cairo_bool_t manual_refresh);
/* cairo_os2_surface_get_manual_window_refresh () : */
/* */
/* This API can return the current mode of the surface. It is */
/* TRUE by default. */
cairo_public cairo_bool_t
cairo_os2_surface_get_manual_window_refresh (cairo_surface_t *surface);
#endif /* CAIRO_HAS_OS2_SURFACE */
CAIRO_END_DECLS
#endif /* _CAIRO_OS2_H_ */

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

@ -60,7 +60,7 @@ _cairo_output_stream_init (cairo_output_stream_t *stream,
cairo_output_stream_write_func_t write_func,
cairo_output_stream_close_func_t close_func);
cairo_private void
cairo_private cairo_status_t
_cairo_output_stream_fini (cairo_output_stream_t *stream);
@ -86,10 +86,16 @@ _cairo_output_stream_create (cairo_write_func_t write_func,
cairo_close_func_t close_func,
void *closure);
cairo_private void
/* Returns the final status value associated with this object, just
* before its last gasp. This final status value will capture any
* status failure returned by the stream's close_func as well. */
cairo_private cairo_status_t
_cairo_output_stream_close (cairo_output_stream_t *stream);
cairo_private void
/* Returns the final status value associated with this object, just
* before its last gasp. This final status value will capture any
* status failure returned by the stream's close_func as well. */
cairo_private cairo_status_t
_cairo_output_stream_destroy (cairo_output_stream_t *stream);
cairo_private void

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

@ -57,13 +57,12 @@ _cairo_output_stream_init (cairo_output_stream_t *stream,
stream->closed = FALSE;
}
cairo_private void
cairo_private cairo_status_t
_cairo_output_stream_fini (cairo_output_stream_t *stream)
{
_cairo_output_stream_close (stream);
return _cairo_output_stream_close (stream);
}
const cairo_output_stream_t cairo_output_stream_nil = {
NULL, /* write_func */
NULL, /* close_func */
@ -130,37 +129,44 @@ _cairo_output_stream_create (cairo_write_func_t write_func,
return &stream->base;
}
void
cairo_status_t
_cairo_output_stream_close (cairo_output_stream_t *stream)
{
cairo_status_t status;
if (stream->closed)
return;
return stream->status;
if (stream == &cairo_output_stream_nil ||
stream == &cairo_output_stream_nil_write_error)
{
return;
return stream->status;
}
if (stream->close_func) {
status = stream->close_func (stream);
if (status)
/* Don't overwrite a pre-existing status failure. */
if (stream->status == CAIRO_STATUS_SUCCESS)
stream->status = status;
}
stream->closed = TRUE;
return stream->status;
}
void
cairo_status_t
_cairo_output_stream_destroy (cairo_output_stream_t *stream)
{
if (stream == NULL)
return;
cairo_status_t status;
_cairo_output_stream_fini (stream);
if (stream == NULL)
return CAIRO_STATUS_NULL_POINTER;
status = _cairo_output_stream_fini (stream);
free (stream);
return status;
}
void
@ -184,7 +190,7 @@ _cairo_output_stream_write_hex_string (cairo_output_stream_t *stream,
{
const char hex_chars[] = "0123456789abcdef";
char buffer[2];
int i, column;
unsigned int i, column;
if (stream->status)
return;
@ -459,8 +465,10 @@ _cairo_output_stream_create_for_filename (const char *filename)
return (cairo_output_stream_t *) &cairo_output_stream_nil_write_error;
stream = malloc (sizeof *stream);
if (stream == NULL)
if (stream == NULL) {
fclose (file);
return (cairo_output_stream_t *) &cairo_output_stream_nil;
}
_cairo_output_stream_init (&stream->base, stdio_write, stdio_close);
stream->file = file;

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

@ -163,6 +163,25 @@ _cairo_paginated_surface_finish (void *abstract_surface)
return CAIRO_STATUS_SUCCESS;
}
static cairo_surface_t *
_cairo_paginated_surface_create_image_surface (void *abstract_surface,
int width,
int height)
{
cairo_paginated_surface_t *surface = abstract_surface;
cairo_surface_t *image;
cairo_font_options_t options;
image = _cairo_image_surface_create_with_content (surface->content,
width,
height);
cairo_surface_get_font_options (&surface->base, &options);
_cairo_surface_set_font_options (image, &options);
return image;
}
static cairo_status_t
_cairo_paginated_surface_acquire_source_image (void *abstract_surface,
cairo_image_surface_t **image_out,
@ -174,9 +193,9 @@ _cairo_paginated_surface_acquire_source_image (void *abstract_surface,
_cairo_surface_get_extents (surface->target, &extents);
image = _cairo_image_surface_create_with_content (surface->content,
extents.width,
extents.height);
image = _cairo_paginated_surface_create_image_surface (surface,
extents.width,
extents.height);
_cairo_meta_surface_replay (surface->meta, image);
@ -221,9 +240,9 @@ _paint_page (cairo_paginated_surface_t *surface)
double y_scale = surface->base.y_fallback_resolution / 72.0;
cairo_matrix_t matrix;
image = _cairo_image_surface_create_with_content (surface->content,
surface->width * x_scale,
surface->height * y_scale);
image = _cairo_paginated_surface_create_image_surface (surface,
surface->width * x_scale,
surface->height * y_scale);
_cairo_surface_set_device_scale (image, x_scale, y_scale);
_cairo_meta_surface_replay (surface->meta, image);
@ -460,9 +479,9 @@ _cairo_paginated_surface_snapshot (void *abstract_other)
_cairo_surface_get_extents (other->target, &extents);
surface = _cairo_image_surface_create_with_content (other->content,
extents.width,
extents.height);
surface = _cairo_paginated_surface_create_image_surface (other,
extents.width,
extents.height);
_cairo_meta_surface_replay (other->meta, surface);

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

@ -125,9 +125,6 @@ _cpdc_close_path (void *closure)
cpdc->count += 1;
cpdc->current_point.x = 0;
cpdc->current_point.y = 0;
return CAIRO_STATUS_SUCCESS;
}
@ -304,9 +301,6 @@ _cpdp_close_path (void *closure)
cpdp->data += data->header.length;
cpdp->current_point.x = 0;
cpdp->current_point.y = 0;
return CAIRO_STATUS_SUCCESS;
}

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

@ -59,7 +59,7 @@ typedef struct cairo_stroker {
cairo_stroke_face_t first_face;
cairo_bool_t dashed;
int dash_index;
unsigned int dash_index;
int dash_on;
double dash_remain;
} cairo_stroker_t;
@ -114,7 +114,7 @@ _cairo_stroker_start_dash (cairo_stroker_t *stroker)
{
double offset;
int on = 1;
int i = 0;
unsigned int i = 0;
offset = stroker->style->dash_offset;
@ -699,6 +699,8 @@ _cairo_stroker_line_to_dashed (void *closure, cairo_point_t *point)
cairo_point_t *p2 = point;
cairo_slope_t slope;
stroker->has_sub_path = stroker->dash_on;
if (p1->x == p2->x && p1->y == p2->y)
return CAIRO_STATUS_SUCCESS;
@ -758,6 +760,7 @@ _cairo_stroker_line_to_dashed (void *closure, cairo_point_t *point)
return status;
}
}
stroker->has_sub_path = TRUE;
}
if (remain) {
/*

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

@ -228,8 +228,13 @@ _cairo_path_fixed_line_to (cairo_path_fixed_t *path,
point.x = x;
point.y = y;
/* When there is not yet a current point, the line_to operation
* becomes a move_to instead. Note: We have to do this by
* explicitly calling into _cairo_path_fixed_line_to to ensure
* that the last_move_point state is updated properly.
*/
if (! path->has_current_point)
status = _cairo_path_fixed_add (path, CAIRO_PATH_OP_MOVE_TO, &point, 1);
status = _cairo_path_fixed_move_to (path, point.x, point.y);
else
status = _cairo_path_fixed_add (path, CAIRO_PATH_OP_LINE_TO, &point, 1);
@ -328,9 +333,11 @@ _cairo_path_fixed_close_path (cairo_path_fixed_t *path)
if (status)
return status;
path->current_point.x = path->last_move_point.x;
path->current_point.y = path->last_move_point.y;
path->has_current_point = TRUE;
status = _cairo_path_fixed_move_to (path,
path->last_move_point.x,
path->last_move_point.y);
if (status)
return status;
return CAIRO_STATUS_SUCCESS;
}

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

@ -1,3 +1,4 @@
/* -*- Mode: c; c-basic-offset: 4; indent-tabs-mode: t; tab-width: 8; -*- */
/* cairo - a vector graphics library with display and print output
*
* Copyright © 2004 David Reveman
@ -31,7 +32,7 @@
const cairo_solid_pattern_t cairo_pattern_nil = {
{ CAIRO_PATTERN_TYPE_SOLID, /* type */
(unsigned int)-1, /* ref_count */
CAIRO_REF_COUNT_INVALID, /* ref_count */
CAIRO_STATUS_NO_MEMORY, /* status */
{ 1., 0., 0., 1., 0., 0., }, /* matrix */
CAIRO_FILTER_DEFAULT, /* filter */
@ -40,7 +41,7 @@ const cairo_solid_pattern_t cairo_pattern_nil = {
static const cairo_solid_pattern_t cairo_pattern_nil_null_pointer = {
{ CAIRO_PATTERN_TYPE_SOLID, /* type */
(unsigned int)-1, /* ref_count */
CAIRO_REF_COUNT_INVALID, /* ref_count */
CAIRO_STATUS_NULL_POINTER,/* status */
{ 1., 0., 0., 1., 0., 0., }, /* matrix */
CAIRO_FILTER_DEFAULT, /* filter */
@ -49,7 +50,7 @@ static const cairo_solid_pattern_t cairo_pattern_nil_null_pointer = {
static const cairo_solid_pattern_t cairo_pattern_nil_file_not_found = {
{ CAIRO_PATTERN_TYPE_SOLID, /* type */
(unsigned int)-1, /* ref_count */
CAIRO_REF_COUNT_INVALID, /* ref_count */
CAIRO_STATUS_FILE_NOT_FOUND, /* status */
{ 1., 0., 0., 1., 0., 0., }, /* matrix */
CAIRO_FILTER_DEFAULT, /* filter */
@ -58,7 +59,7 @@ static const cairo_solid_pattern_t cairo_pattern_nil_file_not_found = {
static const cairo_solid_pattern_t cairo_pattern_nil_read_error = {
{ CAIRO_PATTERN_TYPE_SOLID, /* type */
(unsigned int)-1, /* ref_count */
CAIRO_REF_COUNT_INVALID, /* ref_count */
CAIRO_STATUS_READ_ERROR, /* status */
{ 1., 0., 0., 1., 0., 0., }, /* matrix */
CAIRO_FILTER_DEFAULT, /* filter */
@ -68,17 +69,17 @@ static const cairo_solid_pattern_t cairo_pattern_nil_read_error = {
static const cairo_pattern_t *
_cairo_pattern_nil_for_status (cairo_status_t status)
{
switch (status) {
case CAIRO_STATUS_NULL_POINTER:
/* A switch statement would be more natural here, but we're
* avoiding that to prevent a "false positive" warning from
* -Wswitch-enum, (and I don't want to maintain a list of all
* status values here). */
if (status == CAIRO_STATUS_NULL_POINTER)
return &cairo_pattern_nil_null_pointer.base;
case CAIRO_STATUS_FILE_NOT_FOUND:
if (status == CAIRO_STATUS_FILE_NOT_FOUND)
return &cairo_pattern_nil_file_not_found.base;
case CAIRO_STATUS_READ_ERROR:
if (status == CAIRO_STATUS_READ_ERROR)
return &cairo_pattern_nil_read_error.base;
default:
case CAIRO_STATUS_NO_MEMORY:
return &cairo_pattern_nil.base;
}
return &cairo_pattern_nil.base;
}
/**
@ -331,6 +332,7 @@ cairo_pattern_create_rgb (double red, double green, double blue)
return pattern;
}
slim_hidden_def (cairo_pattern_create_rgb);
/**
* cairo_pattern_create_rgba:
@ -373,6 +375,7 @@ cairo_pattern_create_rgba (double red, double green, double blue,
return pattern;
}
slim_hidden_def (cairo_pattern_create_rgba);
/**
* cairo_pattern_create_for_surface:
@ -410,6 +413,7 @@ cairo_pattern_create_for_surface (cairo_surface_t *surface)
return &pattern->base;
}
slim_hidden_def (cairo_pattern_create_for_surface);
/**
* cairo_pattern_create_linear:
@ -457,10 +461,10 @@ cairo_pattern_create_linear (double x0, double y0, double x1, double y1)
* cairo_pattern_create_radial:
* @cx0: x coordinate for the center of the start circle
* @cy0: y coordinate for the center of the start circle
* @radius0: radius of the start cirle
* @radius0: radius of the start circle
* @cx1: x coordinate for the center of the end circle
* @cy1: y coordinate for the center of the end circle
* @radius1: radius of the end cirle
* @radius1: radius of the end circle
*
* Creates a new radial gradient cairo_pattern_t between the two
* circles defined by (x0, y0, c0) and (x1, y1, c0). Before using the
@ -514,7 +518,7 @@ cairo_pattern_reference (cairo_pattern_t *pattern)
if (pattern == NULL)
return NULL;
if (pattern->ref_count == (unsigned int)-1)
if (pattern->ref_count == CAIRO_REF_COUNT_INVALID)
return pattern;
assert (pattern->ref_count > 0);
@ -523,12 +527,16 @@ cairo_pattern_reference (cairo_pattern_t *pattern)
return pattern;
}
slim_hidden_def (cairo_pattern_reference);
/**
* cairo_pattern_get_type:
* @pattern: a #cairo_pattern_t
*
* Return value: The type of @pattern. See #cairo_pattern_type_t.
* This function returns the type a pattern.
* See #cairo_pattern_type_t for available types.
*
* Return value: The type of @pattern.
*
* Since: 1.2
**/
@ -537,6 +545,7 @@ cairo_pattern_get_type (cairo_pattern_t *pattern)
{
return pattern->type;
}
slim_hidden_def (cairo_pattern_get_type);
/**
* cairo_pattern_status:
@ -568,7 +577,7 @@ cairo_pattern_destroy (cairo_pattern_t *pattern)
if (pattern == NULL)
return;
if (pattern->ref_count == (unsigned int)-1)
if (pattern->ref_count == CAIRO_REF_COUNT_INVALID)
return;
assert (pattern->ref_count > 0);
@ -580,6 +589,7 @@ cairo_pattern_destroy (cairo_pattern_t *pattern)
_cairo_pattern_fini (pattern);
free (pattern);
}
slim_hidden_def (cairo_pattern_destroy);
static void
_cairo_pattern_add_color_stop (cairo_gradient_pattern_t *pattern,
@ -591,7 +601,7 @@ _cairo_pattern_add_color_stop (cairo_gradient_pattern_t *pattern,
{
pixman_gradient_stop_t *new_stops;
cairo_fixed_t x;
int i;
unsigned int i;
new_stops = realloc (pattern->stops, (pattern->n_stops + 1) *
sizeof (pixman_gradient_stop_t));
@ -761,6 +771,7 @@ cairo_pattern_set_matrix (cairo_pattern_t *pattern,
pattern->matrix = *matrix;
}
slim_hidden_def (cairo_pattern_set_matrix);
/**
* cairo_pattern_get_matrix:
@ -824,6 +835,7 @@ cairo_pattern_get_extend (cairo_pattern_t *pattern)
{
return pattern->extend;
}
slim_hidden_def (cairo_pattern_get_extend);
void
_cairo_pattern_transform (cairo_pattern_t *pattern,
@ -1079,7 +1091,7 @@ _cairo_pattern_is_opaque_solid (const cairo_pattern_t *pattern)
static cairo_bool_t
_gradient_is_opaque (const cairo_gradient_pattern_t *gradient)
{
int i;
unsigned int i;
for (i = 0; i < gradient->n_stops; i++)
if (! CAIRO_ALPHA_IS_OPAQUE (gradient->stops[i].color.alpha))
@ -1466,67 +1478,234 @@ _cairo_pattern_get_extents (cairo_pattern_t *pattern,
}
/**
* cairo_pattern_get_solid_color
* cairo_pattern_get_rgba
* @pattern: a #cairo_pattern_t
* @r, @g, @b, @a: a double to return a color value in. must not be NULL.
* @red: return value for red component of color, or %NULL
* @green: return value for green component of color, or %NULL
* @blue: return value for blue component of color, or %NULL
* @alpha: return value for alpha component of color, or %NULL
*
* Gets the solid color for a solid color pattern.
*
* Return value: CAIRO_STATUS_SUCCESS, or
* CAIRO_STATUS_PATTERN_TYPE_MISMATCH if the pattern is not a solid
* Return value: %CAIRO_STATUS_SUCCESS, or
* %CAIRO_STATUS_PATTERN_TYPE_MISMATCH if the pattern is not a solid
* color pattern.
*
* Since: 1.4
**/
cairo_status_t
cairo_pattern_get_solid_color (cairo_pattern_t *pattern,
double *r, double *g, double *b, double *a)
cairo_pattern_get_rgba (cairo_pattern_t *pattern,
double *red, double *green,
double *blue, double *alpha)
{
cairo_solid_pattern_t *solid = (cairo_solid_pattern_t*) pattern;
assert(r && g && b && a);
double r0, g0, b0, a0;
if (pattern->type != CAIRO_PATTERN_TYPE_SOLID)
return CAIRO_STATUS_PATTERN_TYPE_MISMATCH;
return CAIRO_STATUS_PATTERN_TYPE_MISMATCH;
_cairo_color_get_rgba (&solid->color, r, g, b, a);
_cairo_color_get_rgba (&solid->color, &r0, &g0, &b0, &a0);
if (red)
*red = r0;
if (green)
*green = g0;
if (blue)
*blue = b0;
if (alpha)
*alpha = a0;
return CAIRO_STATUS_SUCCESS;
}
/**
* cairo_pattern_get_color_stop
* cairo_pattern_get_surface
* @pattern: a #cairo_pattern_t
* @stop_index: a number from 0 to 1 minus the number of color stops
* @offset: a double representing the color stop offset
* @r, @g, @b, @a: a double to return a color value in. must not be NULL.
* @surface: return value for surface of pattern, or %NULL
*
* Gets the surface of a surface pattern. The reference returned in
* @surface is owned by the pattern; the caller should call
* cairo_surface_reference() if the surface is to be retained.
*
* Gets the color stop from a gradient pattern. The caller should
* keep increasing stop_index until this function returns CAIRO_STATUS_INVALID_INDEX
* Return value: %CAIRO_STATUS_SUCCESS, or
* %CAIRO_STATUS_PATTERN_TYPE_MISMATCH if the pattern is not a surface
* pattern.
*
* Return value: CAIRO_STATUS_SUCCESS, or CAIRO_STATUS_INVALID_INDEX if there
* is no stop at the given index. If the pattern is not a gradient pattern,
* CAIRO_STATUS_PATTERN_TYPE_MISMATCH is returned.
* Since: 1.4
**/
cairo_status_t
cairo_pattern_get_color_stop (cairo_pattern_t *pattern,
int stop_index, double *offset,
double *r, double *g, double *b, double *a)
cairo_pattern_get_surface (cairo_pattern_t *pattern,
cairo_surface_t **surface)
{
cairo_gradient_pattern_t *gradient = (cairo_gradient_pattern_t*) pattern;
cairo_surface_pattern_t *spat = (cairo_surface_pattern_t*) pattern;
assert(offset && r && g && b && a);
if (pattern->type != CAIRO_PATTERN_TYPE_SURFACE)
return CAIRO_STATUS_PATTERN_TYPE_MISMATCH;
if (pattern->type != CAIRO_PATTERN_TYPE_LINEAR ||
pattern->type != CAIRO_PATTERN_TYPE_RADIAL)
return CAIRO_STATUS_PATTERN_TYPE_MISMATCH;
if (stop_index < 0 || stop_index >= gradient->n_stops)
return CAIRO_STATUS_INVALID_INDEX;
*offset = _cairo_fixed_to_double(gradient->stops[stop_index].x);
*r = gradient->stops[stop_index].color.red / (double) 0xffff;
*g = gradient->stops[stop_index].color.green / (double) 0xffff;
*b = gradient->stops[stop_index].color.blue / (double) 0xffff;
*a = gradient->stops[stop_index].color.alpha / (double) 0xffff;
if (surface)
*surface = spat->surface;
return CAIRO_STATUS_SUCCESS;
}
/**
* cairo_pattern_get_color_stop_rgba
* @pattern: a #cairo_pattern_t
* @index: index of the stop to return data for
* @red: return value for red component of color, or %NULL
* @green: return value for green component of color, or %NULL
* @blue: return value for blue component of color, or %NULL
* @alpha: return value for alpha component of color, or %NULL
*
* Gets the color and offset information at the given @index for a
* gradient pattern. Values of @index are 0 to 1 less than the number
* returned by cairo_pattern_get_color_stop_count().
*
* Return value: %CAIRO_STATUS_SUCCESS, or %CAIRO_STATUS_INVALID_INDEX
* if @index is not valid for the given pattern. If the pattern is
* not a gradient pattern, %CAIRO_STATUS_PATTERN_TYPE_MISMATCH is
* returned.
*
* Since: 1.4
**/
cairo_status_t
cairo_pattern_get_color_stop_rgba (cairo_pattern_t *pattern,
int index, double *offset,
double *red, double *green,
double *blue, double *alpha)
{
cairo_gradient_pattern_t *gradient = (cairo_gradient_pattern_t*) pattern;
if (pattern->type != CAIRO_PATTERN_TYPE_LINEAR &&
pattern->type != CAIRO_PATTERN_TYPE_RADIAL)
return CAIRO_STATUS_PATTERN_TYPE_MISMATCH;
if (index < 0 || index >= gradient->n_stops)
return CAIRO_STATUS_INVALID_INDEX;
if (offset)
*offset = _cairo_fixed_to_double(gradient->stops[index].x);
if (red)
*red = gradient->stops[index].color.red / (double) 0xffff;
if (green)
*green = gradient->stops[index].color.green / (double) 0xffff;
if (blue)
*blue = gradient->stops[index].color.blue / (double) 0xffff;
if (alpha)
*alpha = gradient->stops[index].color.alpha / (double) 0xffff;
return CAIRO_STATUS_SUCCESS;
}
/**
* cairo_pattern_get_color_stop_count
* @pattern: a #cairo_pattern_t
* @count: return value for the number of color stops, or %NULL
*
* Gets the number of color stops specified in the given gradient
* pattern.
*
* Return value: %CAIRO_STATUS_SUCCESS, or
* %CAIRO_STATUS_PATTERN_TYPE_MISMATCH if @pattern is not a gradient
* pattern.
*
* Since: 1.4
*/
cairo_status_t
cairo_pattern_get_color_stop_count (cairo_pattern_t *pattern,
int *count)
{
cairo_gradient_pattern_t *gradient = (cairo_gradient_pattern_t*) pattern;
if (pattern->type != CAIRO_PATTERN_TYPE_LINEAR &&
pattern->type != CAIRO_PATTERN_TYPE_RADIAL)
return CAIRO_STATUS_PATTERN_TYPE_MISMATCH;
if (count)
*count = gradient->n_stops;
return CAIRO_STATUS_SUCCESS;
}
/**
* cairo_pattern_get_linear_points
* @pattern: a #cairo_pattern_t
* @x0: return value for the x coordinate of the first point, or %NULL
* @y0: return value for the y coordinate of the first point, or %NULL
* @x1: return value for the x coordinate of the second point, or %NULL
* @y1: return value for the y coordinate of the second point, or %NULL
*
* Gets the gradient endpoints for a linear gradient.
*
* Return value: %CAIRO_STATUS_SUCCESS, or
* %CAIRO_STATUS_PATTERN_TYPE_MISMATCH if @pattern is not a linear
* gradient pattern.
*
* Since: 1.4
**/
cairo_status_t
cairo_pattern_get_linear_points (cairo_pattern_t *pattern,
double *x0, double *y0,
double *x1, double *y1)
{
cairo_linear_pattern_t *linear = (cairo_linear_pattern_t*) pattern;
if (pattern->type != CAIRO_PATTERN_TYPE_LINEAR)
return CAIRO_STATUS_PATTERN_TYPE_MISMATCH;
if (x0)
*x0 = _cairo_fixed_to_double (linear->gradient.p1.x);
if (y0)
*y0 = _cairo_fixed_to_double (linear->gradient.p1.y);
if (x1)
*x1 = _cairo_fixed_to_double (linear->gradient.p2.x);
if (y1)
*y1 = _cairo_fixed_to_double (linear->gradient.p2.y);
return CAIRO_STATUS_SUCCESS;
}
/**
* cairo_pattern_get_radial_circles
* @pattern: a #cairo_pattern_t
* @x0: return value for the x coordinate of the center of the first (inner) circle, or %NULL
* @y0: return value for the y coordinate of the center of the first (inner) circle, or %NULL
* @r0: return value for the radius of the first (inner) circle, or %NULL
* @x1: return value for the x coordinate of the center of the second (outer) circle, or %NULL
* @y1: return value for the y coordinate of the center of the second (outer) circle, or %NULL
* @r1: return value for the radius of the second (outer) circle, or %NULL
*
* Gets the gradient endpoint circles for a radial gradient, each
* specified as a center coordinate and a radius.
*
* Return value: %CAIRO_STATUS_SUCCESS, or
* %CAIRO_STATUS_PATTERN_TYPE_MISMATCH if @pattern is not a radial
* gradient pattern.
*
* Since: 1.4
**/
cairo_status_t
cairo_pattern_get_radial_circles (cairo_pattern_t *pattern,
double *x0, double *y0, double *r0,
double *x1, double *y1, double *r1)
{
cairo_radial_pattern_t *radial = (cairo_radial_pattern_t*) pattern;
if (pattern->type != CAIRO_PATTERN_TYPE_RADIAL)
return CAIRO_STATUS_PATTERN_TYPE_MISMATCH;
if (x0)
*x0 = _cairo_fixed_to_double (radial->gradient.inner.x);
if (y0)
*y0 = _cairo_fixed_to_double (radial->gradient.inner.y);
if (r0)
*r0 = _cairo_fixed_to_double (radial->gradient.inner.radius);
if (x1)
*x1 = _cairo_fixed_to_double (radial->gradient.outer.x);
if (y1)
*y1 = _cairo_fixed_to_double (radial->gradient.outer.y);
if (r1)
*r1 = _cairo_fixed_to_double (radial->gradient.outer.radius);
return CAIRO_STATUS_SUCCESS;
}

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

@ -40,7 +40,6 @@
#include "cairo-pdf.h"
#include "cairo-pdf-test.h"
#include "cairo-scaled-font-subsets-private.h"
#include "cairo-ft-private.h"
#include "cairo-paginated-surface-private.h"
#include "cairo-path-fixed-private.h"
#include "cairo-output-stream-private.h"
@ -296,6 +295,8 @@ _cairo_pdf_surface_create_for_stream_internal (cairo_output_stream_t *output,
/* Document header */
_cairo_output_stream_printf (surface->output,
"%%PDF-1.4\r\n");
_cairo_output_stream_printf (surface->output,
"%%%c%c%c%c\r\n", 181, 237, 174, 251);
return _cairo_paginated_surface_create (&surface->base,
CAIRO_CONTENT_COLOR_ALPHA,
@ -453,19 +454,6 @@ _cairo_pdf_surface_clear (cairo_pdf_surface_t *surface)
_cairo_array_truncate (&surface->streams, 0);
}
static cairo_surface_t *
_cairo_pdf_surface_create_similar (void *abstract_src,
cairo_content_t content,
int width,
int height)
{
cairo_format_t format = _cairo_format_from_content (content);
/* Just return an image for now, until PDF surface can be used
* as source. */
return cairo_image_surface_create (format, width, height);
}
static cairo_pdf_resource_t
_cairo_pdf_surface_open_stream (cairo_pdf_surface_t *surface,
const char *fmt,
@ -558,8 +546,7 @@ _cairo_pdf_surface_finish (void *abstract_surface)
"%%%%EOF\r\n",
offset);
status = _cairo_output_stream_get_status (surface->output);
_cairo_output_stream_destroy (surface->output);
status = _cairo_output_stream_destroy (surface->output);
_cairo_array_fini (&surface->objects);
_cairo_array_fini (&surface->pages);
@ -893,8 +880,12 @@ emit_surface_pattern (cairo_pdf_surface_t *surface,
xstep = image->width;
ystep = image->height;
break;
/* All the reset should have been analyzed away, so this case
* should be unreachable. */
case CAIRO_EXTEND_REFLECT:
case CAIRO_EXTEND_PAD:
default:
ASSERT_NOT_REACHED; /* all others should be analyzed away */
ASSERT_NOT_REACHED;
xstep = 0;
ystep = 0;
}
@ -1081,8 +1072,7 @@ emit_pattern_stops (cairo_pdf_surface_t *surface, cairo_gradient_pattern_t *patt
{
cairo_pdf_resource_t function;
cairo_pdf_color_stop_t *allstops, *stops;
unsigned int n_stops;
unsigned int i;
unsigned int i, n_stops;
function = _cairo_pdf_surface_new_object (surface);
@ -1472,6 +1462,7 @@ _cairo_pdf_surface_get_font_options (void *abstract_surface,
cairo_font_options_set_hint_style (options, CAIRO_HINT_STYLE_NONE);
cairo_font_options_set_hint_metrics (options, CAIRO_HINT_METRICS_OFF);
cairo_font_options_set_antialias (options, CAIRO_ANTIALIAS_GRAY);
}
static cairo_pdf_resource_t
@ -1587,31 +1578,22 @@ _cairo_pdf_surface_write_pages (cairo_pdf_surface_t *surface)
}
static cairo_status_t
_cairo_pdf_surface_emit_type1_font_subset (cairo_pdf_surface_t *surface,
cairo_scaled_font_subset_t *font_subset)
_cairo_pdf_surface_emit_type1_font (cairo_pdf_surface_t *surface,
cairo_scaled_font_subset_t *font_subset,
cairo_type1_subset_t *subset)
{
cairo_pdf_resource_t stream, descriptor, subset_resource;
cairo_status_t status;
cairo_pdf_font_t font;
cairo_type1_subset_t subset;
unsigned long length, compressed_length;
char *compressed;
int i;
char name[64];
unsigned int i;
snprintf (name, sizeof name, "CairoFont-%d-%d",
font_subset->font_id, font_subset->subset_id);
status = _cairo_type1_subset_init (&subset, name, font_subset);
if (status)
return status;
/* We ignore the zero-trailer and set Length3 to 0. */
length = subset.header_length + subset.data_length;
compressed = compress_dup (subset.data, length, &compressed_length);
if (compressed == NULL) {
_cairo_type1_subset_fini (&subset);
length = subset->header_length + subset->data_length;
compressed = compress_dup (subset->data, length, &compressed_length);
if (compressed == NULL)
return CAIRO_STATUS_NO_MEMORY;
}
stream = _cairo_pdf_surface_new_object (surface);
_cairo_output_stream_printf (surface->output,
@ -1625,8 +1607,8 @@ _cairo_pdf_surface_emit_type1_font_subset (cairo_pdf_surface_t *surface,
"stream\r\n",
stream.id,
compressed_length,
subset.header_length,
subset.data_length);
subset->header_length,
subset->data_length);
_cairo_output_stream_write (surface->output, compressed, compressed_length);
_cairo_output_stream_printf (surface->output,
"\r\n"
@ -1651,13 +1633,13 @@ _cairo_pdf_surface_emit_type1_font_subset (cairo_pdf_surface_t *surface,
">>\r\n"
"endobj\r\n",
descriptor.id,
subset.base_font,
subset.x_min,
subset.y_min,
subset.x_max,
subset.y_max,
subset.ascent,
subset.descent,
subset->base_font,
subset->x_min,
subset->y_min,
subset->x_max,
subset->y_max,
subset->ascent,
subset->descent,
stream.id);
subset_resource = _cairo_pdf_surface_new_object (surface);
@ -1671,14 +1653,14 @@ _cairo_pdf_surface_emit_type1_font_subset (cairo_pdf_surface_t *surface,
" /FontDescriptor %d 0 R\r\n"
" /Widths [",
subset_resource.id,
subset.base_font,
font_subset->num_glyphs,
subset->base_font,
font_subset->num_glyphs - 1,
descriptor.id);
for (i = 0; i < font_subset->num_glyphs; i++)
_cairo_output_stream_printf (surface->output,
" %d",
subset.widths[i]);
subset->widths[i]);
_cairo_output_stream_printf (surface->output,
" ]\r\n"
@ -1690,11 +1672,51 @@ _cairo_pdf_surface_emit_type1_font_subset (cairo_pdf_surface_t *surface,
font.subset_resource = subset_resource;
_cairo_array_append (&surface->fonts, &font);
_cairo_type1_subset_fini (&subset);
return CAIRO_STATUS_SUCCESS;
}
#if CAIRO_HAS_FT_FONT
static cairo_status_t
_cairo_pdf_surface_emit_type1_font_subset (cairo_pdf_surface_t *surface,
cairo_scaled_font_subset_t *font_subset)
{
cairo_status_t status;
cairo_type1_subset_t subset;
char name[64];
snprintf (name, sizeof name, "CairoFont-%d-%d",
font_subset->font_id, font_subset->subset_id);
status = _cairo_type1_subset_init (&subset, name, font_subset, FALSE);
if (status)
return status;
status = _cairo_pdf_surface_emit_type1_font (surface, font_subset, &subset);
_cairo_type1_subset_fini (&subset);
return status;
}
#endif
static cairo_status_t
_cairo_pdf_surface_emit_type1_fallback_font (cairo_pdf_surface_t *surface,
cairo_scaled_font_subset_t *font_subset)
{
cairo_status_t status;
cairo_type1_subset_t subset;
char name[64];
snprintf (name, sizeof name, "CairoFont-%d-%d",
font_subset->font_id, font_subset->subset_id);
status = _cairo_type1_fallback_init (&subset, name, font_subset);
if (status)
return status;
status = _cairo_pdf_surface_emit_type1_font (surface, font_subset, &subset);
_cairo_type1_fallback_fini (&subset);
return status;
}
static cairo_status_t
_cairo_pdf_surface_emit_truetype_font_subset (cairo_pdf_surface_t *surface,
cairo_scaled_font_subset_t *font_subset)
@ -1705,7 +1727,7 @@ _cairo_pdf_surface_emit_truetype_font_subset (cairo_pdf_surface_t *surface,
cairo_truetype_subset_t subset;
unsigned long compressed_length;
char *compressed;
int i;
unsigned int i;
status = _cairo_truetype_subset_init (&subset, font_subset);
if (status)
@ -1774,7 +1796,7 @@ _cairo_pdf_surface_emit_truetype_font_subset (cairo_pdf_surface_t *surface,
" /Widths [",
subset_resource.id,
subset.base_font,
font_subset->num_glyphs,
font_subset->num_glyphs - 1,
descriptor.id);
for (i = 0; i < font_subset->num_glyphs; i++)
@ -1864,7 +1886,11 @@ _cairo_pdf_surface_emit_bitmap_glyph (cairo_pdf_surface_t *surface,
return status;
image = scaled_glyph->surface;
assert (image->format == CAIRO_FORMAT_A1);
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);
}
*glyph_ret = _cairo_pdf_surface_open_stream (surface, NULL);
@ -1906,6 +1932,9 @@ _cairo_pdf_surface_emit_bitmap_glyph (cairo_pdf_surface_t *surface,
_cairo_pdf_surface_close_stream (surface);
if (image != scaled_glyph->surface)
cairo_surface_destroy (&image->base);
return CAIRO_STATUS_SUCCESS;
}
@ -1938,7 +1967,7 @@ _cairo_pdf_surface_emit_type3_font_subset (cairo_pdf_surface_t *surface,
cairo_pdf_resource_t *glyphs, encoding, char_procs, subset_resource;
cairo_pdf_font_t font;
cairo_matrix_t matrix;
int i;
unsigned int i;
glyphs = malloc (font_subset->num_glyphs * sizeof (cairo_pdf_resource_t));
if (glyphs == NULL) {
@ -1978,6 +2007,8 @@ _cairo_pdf_surface_emit_type3_font_subset (cairo_pdf_surface_t *surface,
">>\r\n"
"endobj\r\n");
free (glyphs);
subset_resource = _cairo_pdf_surface_new_object (surface);
matrix = font_subset->scaled_font->scale;
cairo_matrix_invert (&matrix);
@ -2026,14 +2057,20 @@ _cairo_pdf_surface_emit_font_subset (cairo_scaled_font_subset_t *font_subset,
cairo_pdf_surface_t *surface = closure;
cairo_status_t status;
#if CAIRO_HAS_FT_FONT
status = _cairo_pdf_surface_emit_type1_font_subset (surface, font_subset);
if (status != CAIRO_INT_STATUS_UNSUPPORTED)
return;
#endif
status = _cairo_pdf_surface_emit_truetype_font_subset (surface, font_subset);
if (status != CAIRO_INT_STATUS_UNSUPPORTED)
return;
status = _cairo_pdf_surface_emit_type1_fallback_font (surface, font_subset);
if (status != CAIRO_INT_STATUS_UNSUPPORTED)
return;
status = _cairo_pdf_surface_emit_type3_font_subset (surface, font_subset);
if (status != CAIRO_INT_STATUS_UNSUPPORTED)
return;
@ -2451,12 +2488,14 @@ _cairo_pdf_surface_emit_stroke_style (cairo_pdf_surface_t *surface,
_cairo_pdf_line_join (style->line_join));
if (style->num_dashes) {
int d;
unsigned int d;
_cairo_output_stream_printf (surface->output, "[");
for (d = 0; d < style->num_dashes; d++)
_cairo_output_stream_printf (surface->output, " %f", style->dash[d]);
_cairo_output_stream_printf (surface->output, "] %f d\r\n",
style->dash_offset);
} else {
_cairo_output_stream_printf (surface->output, "[] 0.0 d\r\n");
}
_cairo_output_stream_printf (surface->output,
@ -2577,7 +2616,7 @@ _cairo_pdf_surface_show_glyphs (void *abstract_surface,
cairo_scaled_font_t *scaled_font)
{
cairo_pdf_surface_t *surface = abstract_surface;
int current_subset_id = -1;
unsigned int current_subset_id = (unsigned int)-1;
unsigned int font_id, subset_id, subset_glyph_index;
cairo_status_t status;
int i;
@ -2636,7 +2675,7 @@ _cairo_pdf_surface_set_paginated_mode (void *abstract_surface,
static const cairo_surface_backend_t cairo_pdf_surface_backend = {
CAIRO_SURFACE_TYPE_PDF,
_cairo_pdf_surface_create_similar,
NULL, /* create_similar */
_cairo_pdf_surface_finish,
NULL, /* acquire_source_image */
NULL, /* release_source_image */

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

@ -54,7 +54,7 @@ cairo_pdf_surface_create_for_stream (cairo_write_func_t write_func,
double width_in_points,
double height_in_points);
void
cairo_public void
cairo_pdf_surface_set_size (cairo_surface_t *surface,
double width_in_points,
double height_in_points);

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

@ -47,7 +47,7 @@
#define CVISIBILITY_HIDDEN
#endif
// In libxul builds we don't ever want to export cairo symbols
/* In libxul builds we don't ever want to export cairo symbols */
#define cairo_public extern CVISIBILITY_HIDDEN
#define CCALLBACK
#define CCALLBACK_DECL

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

@ -35,15 +35,15 @@
* Kristian Høgsberg <krh@redhat.com>
*/
#include <png.h>
#include <errno.h>
#include "cairoint.h"
#include <png.h>
/* Unpremultiplies data and converts native endian ARGB => RGBA bytes */
static void
unpremultiply_data (png_structp png, png_row_infop row_info, png_bytep data)
{
int i;
unsigned int i;
for (i = 0; i < row_info->rowbytes; i += 4) {
uint8_t *b = &data[i];
@ -67,7 +67,7 @@ unpremultiply_data (png_structp png, png_row_infop row_info, png_bytep data)
static void
convert_data_to_bytes (png_structp png, png_row_infop row_info, png_bytep data)
{
int i;
unsigned int i;
for (i = 0; i < row_info->rowbytes; i += 4) {
uint8_t *b = &data[i];
@ -88,7 +88,7 @@ write_png (cairo_surface_t *surface,
void *closure)
{
int i;
cairo_status_t status = CAIRO_STATUS_SUCCESS;
volatile cairo_status_t status = CAIRO_STATUS_SUCCESS;
cairo_image_surface_t *image;
void *image_extra;
png_struct *png;
@ -287,6 +287,7 @@ cairo_surface_write_to_png_stream (cairo_surface_t *surface,
return write_png (surface, stream_write_func, &png_closure);
}
slim_hidden_def (cairo_surface_write_to_png_stream);
static INLINE int
multiply_alpha (int alpha, int color)
@ -301,7 +302,7 @@ premultiply_data (png_structp png,
png_row_infop row_info,
png_bytep data)
{
int i;
unsigned int i;
for (i = 0; i < row_info->rowbytes; i += 4) {
uint8_t *base = &data[i];
@ -332,7 +333,7 @@ read_png (png_rw_ptr read_func,
{
cairo_surface_t *surface = (cairo_surface_t*) &_cairo_surface_nil;
png_byte *data = NULL;
int i;
unsigned int i;
png_struct *png = NULL;
png_info *info;
png_uint_32 png_width, png_height, stride;

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

@ -43,9 +43,9 @@
#include "cairo-scaled-font-subsets-private.h"
#include "cairo-paginated-surface-private.h"
#include "cairo-meta-surface-private.h"
#include "cairo-ft-private.h"
#include "cairo-output-stream-private.h"
#include <ctype.h>
#include <time.h>
#include <zlib.h>
@ -313,6 +313,8 @@ _cairo_ps_surface_emit_path (cairo_ps_surface_t *surface,
_cairo_ps_surface_path_close_path,
&path_info);
if (status == CAIRO_STATUS_SUCCESS)
status = _cairo_output_stream_get_status (word_wrap);
_cairo_output_stream_destroy (word_wrap);
return status;
@ -385,6 +387,7 @@ _cairo_ps_surface_emit_header (cairo_ps_surface_t *surface)
}
}
#if CAIRO_HAS_FT_FONT
static cairo_status_t
_cairo_ps_surface_emit_type1_font_subset (cairo_ps_surface_t *surface,
cairo_scaled_font_subset_t *font_subset)
@ -398,7 +401,7 @@ _cairo_ps_surface_emit_type1_font_subset (cairo_ps_surface_t *surface,
snprintf (name, sizeof name, "CairoFont-%d-%d",
font_subset->font_id, font_subset->subset_id);
status = _cairo_type1_subset_init (&subset, name, font_subset);
status = _cairo_type1_subset_init (&subset, name, font_subset, TRUE);
if (status)
return status;
@ -414,6 +417,35 @@ _cairo_ps_surface_emit_type1_font_subset (cairo_ps_surface_t *surface,
return CAIRO_STATUS_SUCCESS;
}
#endif
static cairo_status_t
_cairo_ps_surface_emit_type1_font_fallback (cairo_ps_surface_t *surface,
cairo_scaled_font_subset_t *font_subset)
{
cairo_type1_subset_t subset;
cairo_status_t status;
int length;
char name[64];
snprintf (name, sizeof name, "CairoFont-%d-%d",
font_subset->font_id, font_subset->subset_id);
status = _cairo_type1_fallback_init (&subset, name, font_subset);
if (status)
return status;
/* FIXME: Figure out document structure convention for fonts */
_cairo_output_stream_printf (surface->final_stream,
"%% _cairo_ps_surface_emit_type1_font_subset\n");
length = subset.header_length + subset.data_length + subset.trailer_length;
_cairo_output_stream_write (surface->final_stream, subset.data, length);
_cairo_type1_fallback_fini (&subset);
return CAIRO_STATUS_SUCCESS;
}
static cairo_status_t
_cairo_ps_surface_emit_truetype_font_subset (cairo_ps_surface_t *surface,
@ -423,7 +455,7 @@ _cairo_ps_surface_emit_truetype_font_subset (cairo_ps_surface_t *surface,
{
cairo_truetype_subset_t subset;
cairo_status_t status;
int i;
unsigned int i, begin, end;
status = _cairo_truetype_subset_init (&subset, font_subset);
if (status)
@ -464,17 +496,27 @@ _cairo_ps_surface_emit_truetype_font_subset (cairo_ps_surface_t *surface,
_cairo_output_stream_printf (surface->final_stream,
"end readonly def\n");
/* FIXME: We need to break up fonts bigger than 64k so we don't
* exceed string size limitation. At glyph boundaries. Stupid
* postscript. */
_cairo_output_stream_printf (surface->final_stream,
"/sfnts [<");
_cairo_output_stream_write_hex_string (surface->final_stream,
subset.data, subset.data_length);
"/sfnts [\n");
begin = 0;
end = 0;
for (i = 0; i < subset.num_string_offsets; i++) {
end = subset.string_offsets[i];
_cairo_output_stream_printf (surface->final_stream,"<");
_cairo_output_stream_write_hex_string (surface->final_stream,
subset.data + begin, end - begin);
_cairo_output_stream_printf (surface->final_stream,"00>\n");
begin = end;
}
if (subset.data_length > end) {
_cairo_output_stream_printf (surface->final_stream,"<");
_cairo_output_stream_write_hex_string (surface->final_stream,
subset.data + end, subset.data_length - end);
_cairo_output_stream_printf (surface->final_stream,"00>\n");
}
_cairo_output_stream_printf (surface->final_stream,
">] def\n"
"] def\n"
"FontName currentdict end definefont pop\n");
_cairo_truetype_subset_fini (&subset);
@ -535,7 +577,11 @@ _cairo_ps_surface_emit_bitmap_glyph_data (cairo_ps_surface_t *surface,
&scaled_glyph);
image = scaled_glyph->surface;
assert (image->format == CAIRO_FORMAT_A1);
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,
"0 0 %f %f %f %f setcachedevice\n",
@ -554,12 +600,12 @@ _cairo_ps_surface_emit_bitmap_glyph_data (cairo_ps_surface_t *surface,
" /BitsPerComponent 1\n",
image->width,
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);
image->base.device_transform_inverse.xx,
image->base.device_transform_inverse.yx,
image->base.device_transform_inverse.xy,
image->base.device_transform_inverse.yy,
image->base.device_transform_inverse.x0,
image->base.device_transform_inverse.y0);
_cairo_output_stream_printf (surface->final_stream,
" /DataSource {<");
@ -579,6 +625,9 @@ _cairo_ps_surface_emit_bitmap_glyph_data (cairo_ps_surface_t *surface,
_cairo_output_stream_printf (surface->final_stream,
"imagemask\n");
if (image != scaled_glyph->surface)
cairo_surface_destroy (&image->base);
return CAIRO_STATUS_SUCCESS;
}
@ -615,7 +664,7 @@ _cairo_ps_surface_emit_type3_font_subset (cairo_ps_surface_t *surface,
{
cairo_matrix_t matrix;
int i;
unsigned int i;
_cairo_output_stream_printf (surface->final_stream,
"%% _cairo_ps_surface_emit_type3_font_subset\n");
@ -663,14 +712,20 @@ _cairo_ps_surface_emit_font_subset (cairo_scaled_font_subset_t *font_subset,
cairo_ps_surface_t *surface = closure;
cairo_status_t status;
#if CAIRO_HAS_FT_FONT
status = _cairo_ps_surface_emit_type1_font_subset (surface, font_subset);
if (status != CAIRO_INT_STATUS_UNSUPPORTED)
return;
#endif
status = _cairo_ps_surface_emit_truetype_font_subset (surface, font_subset);
if (status != CAIRO_INT_STATUS_UNSUPPORTED)
return;
status = _cairo_ps_surface_emit_type1_font_fallback (surface, font_subset);
if (status != CAIRO_INT_STATUS_UNSUPPORTED)
return;
status = _cairo_ps_surface_emit_type3_font_subset (surface, font_subset);
if (status != CAIRO_INT_STATUS_UNSUPPORTED)
return;
@ -1126,19 +1181,6 @@ cairo_ps_surface_dsc_begin_page_setup (cairo_surface_t *surface)
}
}
static cairo_surface_t *
_cairo_ps_surface_create_similar (void *abstract_src,
cairo_content_t content,
int width,
int height)
{
cairo_format_t format = _cairo_format_from_content (content);
/* Just return an image for now, until PS surface can be used
* as source. */
return cairo_image_surface_create (format, width, height);
}
static cairo_status_t
_cairo_ps_surface_finish (void *abstract_surface)
{
@ -1474,7 +1516,7 @@ static cairo_status_t
emit_image (cairo_ps_surface_t *surface,
cairo_image_surface_t *image,
cairo_matrix_t *matrix,
char *name)
const char *name)
{
cairo_status_t status;
unsigned char *rgb, *compressed;
@ -1788,6 +1830,7 @@ _cairo_ps_surface_get_font_options (void *abstract_surface,
cairo_font_options_set_hint_style (options, CAIRO_HINT_STYLE_NONE);
cairo_font_options_set_hint_metrics (options, CAIRO_HINT_METRICS_OFF);
cairo_font_options_set_antialias (options, CAIRO_ANTIALIAS_GRAY);
}
static cairo_int_status_t
@ -2056,7 +2099,7 @@ _cairo_ps_surface_show_glyphs (void *abstract_surface,
{
cairo_ps_surface_t *surface = abstract_surface;
cairo_output_stream_t *stream = surface->stream;
int current_subset_id = -1;
unsigned int current_subset_id = -1;
unsigned int font_id, subset_id, subset_glyph_index;
cairo_status_t status;
int i;
@ -2113,7 +2156,7 @@ _cairo_ps_surface_set_paginated_mode (void *abstract_surface,
static const cairo_surface_backend_t cairo_ps_surface_backend = {
CAIRO_SURFACE_TYPE_PS,
_cairo_ps_surface_create_similar,
NULL, /* create_similar */
_cairo_ps_surface_finish,
NULL, /* acquire_source_image */
NULL, /* release_source_image */

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

@ -44,15 +44,11 @@ typedef struct cairo_quartz_surface {
CGContextRef context;
cairo_bool_t flipped;
cairo_bool_t y_grows_down;
int width;
int height;
cairo_rectangle_int16_t extents;
cairo_image_surface_t *image;
pixman_region16_t *clip_region;
CGImageRef cgImage;
pixman_region16_t *clip_region;
} cairo_quartz_surface_t;
cairo_bool_t

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

@ -37,28 +37,14 @@
#include "cairo-private.h"
#include "cairo-quartz-private.h"
static void
ImageDataReleaseFunc(void *info, const void *data, size_t size)
{
if (data != NULL) {
free((void *) data);
}
}
static cairo_status_t
_cairo_quartz_surface_finish(void *abstract_surface)
{
cairo_quartz_surface_t *surface = abstract_surface;
if (surface->image)
cairo_surface_destroy(&surface->image->base);
if (surface->clip_region)
pixman_region_destroy (surface->clip_region);
if (surface->cgImage)
CGImageRelease(surface->cgImage);
if (surface->clip_region)
pixman_region_destroy (surface->clip_region);
return CAIRO_STATUS_SUCCESS;
}
@ -67,117 +53,127 @@ _cairo_quartz_surface_acquire_source_image(void *abstract_surface,
cairo_image_surface_t **image_out,
void **image_extra)
{
cairo_quartz_surface_t *surface = abstract_surface;
CGColorSpaceRef colorSpace;
void *imageData;
UInt32 imageDataSize, rowBytes;
CGDataProviderRef dataProvider;
cairo_quartz_surface_t *surface = abstract_surface;
/* We keep a cached (cairo_image_surface_t *) in the cairo_quartz_surface_t
* struct. If the window is ever drawn to without going through Cairo, then
* we would need to refetch the pixel data from the window into the cached
* image surface.
*/
if (surface->image) {
cairo_surface_reference(&surface->image->base);
if (CGBitmapContextGetBitmapInfo (surface->context) != 0) {
/* XXX: We can create an image out of the bitmap here */
}
*image_out = surface->image;
return CAIRO_STATUS_SUCCESS;
}
colorSpace = CGColorSpaceCreateDeviceRGB();
rowBytes = surface->width * 4;
imageDataSize = rowBytes * surface->height;
imageData = malloc(imageDataSize);
dataProvider =
CGDataProviderCreateWithData(NULL, imageData, imageDataSize,
ImageDataReleaseFunc);
surface->cgImage = CGImageCreate(surface->width,
surface->height,
8,
32,
rowBytes,
colorSpace,
kCGImageAlphaPremultipliedFirst,
dataProvider,
NULL,
false, kCGRenderingIntentDefault);
CGColorSpaceRelease(colorSpace);
CGDataProviderRelease(dataProvider);
surface->image = (cairo_image_surface_t *)
cairo_image_surface_create_for_data(imageData,
CAIRO_FORMAT_ARGB32,
surface->width,
surface->height, rowBytes);
if (surface->image->base.status) {
if (surface->cgImage)
CGImageRelease(surface->cgImage);
return CAIRO_STATUS_NO_MEMORY;
}
*image_out = surface->image;
*image_extra = NULL;
return CAIRO_STATUS_SUCCESS;
return CAIRO_INT_STATUS_UNSUPPORTED;
}
static cairo_status_t
_cairo_quartz_surface_acquire_dest_image(void *abstract_surface,
cairo_rectangle_int16_t * interest_rect,
cairo_image_surface_t **
image_out,
cairo_rectangle_int16_t * image_rect,
void **image_extra)
_cairo_quartz_surface_acquire_dest_image(void *abstract_surface,
cairo_rectangle_int16_t *interest_rect,
cairo_image_surface_t **image_out,
cairo_rectangle_int16_t *image_rect,
void **image_extra)
{
cairo_quartz_surface_t *surface = abstract_surface;
cairo_surface_t *image_surface;
unsigned char *data;
int x1, y1, x2, y2;
image_rect->x = 0;
image_rect->y = 0;
image_rect->width = surface->image->width;
image_rect->height = surface->image->height;
x1 = surface->extents.x;
x2 = surface->extents.x + surface->extents.width;
y1 = surface->extents.y;
y2 = surface->extents.y + surface->extents.height;
*image_out = surface->image;
if (image_extra)
if (interest_rect->x > x1)
x1 = interest_rect->x;
if (interest_rect->y > y1)
y1 = interest_rect->y;
if (interest_rect->x + interest_rect->width < x2)
x2 = interest_rect->x + interest_rect->width;
if (interest_rect->y + interest_rect->height < y2)
y2 = interest_rect->y + interest_rect->height;
if (x1 >= x2 || y1 >= y2) {
*image_out = NULL;
*image_extra = NULL;
return CAIRO_STATUS_SUCCESS;
}
image_rect->x = x1;
image_rect->y = y1;
image_rect->width = x2 - x1;
image_rect->height = y2 - y1;
data = calloc (image_rect->width * image_rect->height * 4, 1);
image_surface = cairo_image_surface_create_for_data (data,
CAIRO_FORMAT_ARGB32,
image_rect->width,
image_rect->height,
image_rect->width * 4);
*image_out = (cairo_image_surface_t *)image_surface;
*image_extra = data;
return CAIRO_STATUS_SUCCESS;
return CAIRO_INT_STATUS_UNSUPPORTED;
}
static CGImageRef
create_image_from_surface (cairo_image_surface_t *image_surface, void *data)
{
CGImageRef image;
CGColorSpaceRef color_space;
CGDataProviderRef data_provider;
int width, height;
width = cairo_image_surface_get_width ((cairo_surface_t *)image_surface);
height = cairo_image_surface_get_height ((cairo_surface_t *)image_surface);
color_space = CGColorSpaceCreateDeviceRGB();
data_provider = CGDataProviderCreateWithData (NULL, data,
width * height * 4, NULL);
image = CGImageCreate (width, height,
8, 32,
width * 4,
color_space,
kCGImageAlphaPremultipliedFirst,
data_provider,
NULL,
FALSE, kCGRenderingIntentDefault);
CGColorSpaceRelease (color_space);
CGDataProviderRelease (data_provider);
return image;
}
static void
_cairo_quartz_surface_release_dest_image(void *abstract_surface,
cairo_rectangle_int16_t *
intersect_rect,
cairo_image_surface_t * image,
cairo_rectangle_int16_t * image_rect,
void *image_extra)
_cairo_quartz_surface_release_dest_image(void *abstract_surface,
cairo_rectangle_int16_t *intersect_rect,
cairo_image_surface_t *image,
cairo_rectangle_int16_t *image_rect,
void *image_extra)
{
cairo_quartz_surface_t *surface = abstract_surface;
CGImageRef image_ref;
CGRect rect;
if (surface->image == image) {
CGRect rect;
image_ref = create_image_from_surface (image, image_extra);
rect = CGRectMake(0, 0, surface->width, surface->height);
rect = CGRectMake (image_rect->x, image_rect->y, image_rect->width, image_rect->height);
if (surface->flipped) {
CGContextSaveGState (surface->context);
CGContextTranslateCTM (surface->context, 0, surface->height);
CGContextScaleCTM (surface->context, 1, -1);
}
CGContextDrawImage(surface->context, rect, surface->cgImage);
if (surface->flipped)
CGContextRestoreGState (surface->context);
memset(surface->image->data, 0, surface->width * surface->height * 4);
if (surface->y_grows_down) {
CGContextSaveGState (surface->context);
CGContextTranslateCTM (surface->context, 0, image_rect->height + 2 * image_rect->y);
CGContextScaleCTM (surface->context, 1, -1);
}
CGContextDrawImage(surface->context, rect, image_ref);
CFRelease (image_ref);
if (surface->y_grows_down) {
CGContextRestoreGState (surface->context);
}
cairo_surface_destroy ((cairo_surface_t *)image);
free (image_extra);
}
static cairo_int_status_t
@ -185,33 +181,26 @@ _cairo_quartz_surface_set_clip_region(void *abstract_surface,
pixman_region16_t * region)
{
cairo_quartz_surface_t *surface = abstract_surface;
unsigned int serial;
serial = _cairo_surface_allocate_clip_serial (&surface->image->base);
if (surface->clip_region)
pixman_region_destroy (surface->clip_region);
if (surface->clip_region)
pixman_region_destroy (surface->clip_region);
if (region) {
surface->clip_region = pixman_region_create ();
pixman_region_copy (surface->clip_region, region);
} else
surface->clip_region = NULL;
return _cairo_surface_set_clip_region(&surface->image->base,
region, serial);
if (region) {
surface->clip_region = pixman_region_create ();
pixman_region_copy (surface->clip_region, region);
} else
surface->clip_region = NULL;
return CAIRO_STATUS_SUCCESS;
}
static cairo_int_status_t
_cairo_quartz_surface_get_extents (void *abstract_surface,
cairo_rectangle_int16_t * rectangle)
_cairo_quartz_surface_get_extents (void *abstract_surface,
cairo_rectangle_int16_t *rectangle)
{
cairo_quartz_surface_t *surface = abstract_surface;
rectangle->x = 0;
rectangle->y = 0;
rectangle->width = surface->width;
rectangle->height = surface->height;
*rectangle = surface->extents;
return CAIRO_STATUS_SUCCESS;
}
@ -236,12 +225,13 @@ static const struct _cairo_surface_backend cairo_quartz_surface_backend = {
NULL /* old_show_glyphs */
};
cairo_surface_t *cairo_quartz_surface_create(CGContextRef context,
cairo_bool_t flipped,
int width, int height)
int width,
int height,
cairo_bool_t y_grows_down)
{
cairo_quartz_surface_t *surface;
CGRect clip_box;
surface = malloc(sizeof(cairo_quartz_surface_t));
if (surface == NULL) {
@ -249,20 +239,19 @@ cairo_surface_t *cairo_quartz_surface_create(CGContextRef context,
return (cairo_surface_t*) &_cairo_surface_nil;
}
/* XXX: The content value here might be totally wrong. */
_cairo_surface_init(&surface->base, &cairo_quartz_surface_backend,
CAIRO_CONTENT_COLOR_ALPHA);
CAIRO_CONTENT_COLOR_ALPHA);
surface->context = context;
surface->width = width;
surface->height = height;
surface->image = NULL;
surface->cgImage = NULL;
surface->clip_region = NULL;
surface->flipped = flipped;
surface->clip_region = NULL;
surface->y_grows_down = y_grows_down;
/* Set up the image surface which Cairo draws into and we blit to & from. */
void *foo;
_cairo_quartz_surface_acquire_source_image(surface, &surface->image, &foo);
clip_box = CGContextGetClipBoundingBox (context);
surface->extents.x = clip_box.origin.x;
surface->extents.y = clip_box.origin.y;
surface->extents.width = clip_box.size.width;
surface->extents.height = clip_box.size.height;
return (cairo_surface_t *) surface;
}

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

@ -1,3 +1,8 @@
#define _cairo_pdf_test_force_fallbacks _moz__cairo_pdf_test_force_fallbacks
#define _cairo_ps_test_force_fallbacks _moz__cairo_ps_test_force_fallbacks
#define _cairo_scaled_font_test_set_max_glyphs_cached_per_font _moz__cairo_scaled_font_test_set_max_glyphs_cached_per_font
#define _cairo_svg_test_force_fallbacks _moz__cairo_svg_test_force_fallbacks
#define _cairo_xlib_test_disable_render _moz__cairo_xlib_test_disable_render
#define cairo_append_path _moz_cairo_append_path
#define cairo_arc _moz_cairo_arc
#define cairo_arc_negative _moz_cairo_arc_negative
@ -6,8 +11,10 @@
#define cairo_beos_surface_create _moz_cairo_beos_surface_create
#define cairo_beos_surface_create_for_bitmap _moz_cairo_beos_surface_create_for_bitmap
#define cairo_clip _moz_cairo_clip
#define cairo_clip_extents _moz_cairo_clip_extents
#define cairo_clip_preserve _moz_cairo_clip_preserve
#define cairo_close_path _moz_cairo_close_path
#define cairo_copy_clip_rectangles _moz_cairo_copy_clip_rectangles
#define cairo_copy_page _moz_cairo_copy_page
#define cairo_copy_path _moz_cairo_copy_path
#define cairo_copy_path_flat _moz_cairo_copy_path_flat
@ -22,7 +29,7 @@
#define cairo_destroy _moz_cairo_destroy
#define cairo_device_to_user _moz_cairo_device_to_user
#define cairo_device_to_user_distance _moz_cairo_device_to_user_distance
#define cairo_extract_clip_rectangles _moz_cairo_extract_clip_rectangles
#define cairo_directfb_surface_create _moz_cairo_directfb_surface_create
#define cairo_fill _moz_cairo_fill
#define cairo_fill_extents _moz_cairo_fill_extents
#define cairo_fill_preserve _moz_cairo_fill_preserve
@ -55,6 +62,8 @@
#define cairo_ft_scaled_font_unlock_face _moz_cairo_ft_scaled_font_unlock_face
#define cairo_get_antialias _moz_cairo_get_antialias
#define cairo_get_current_point _moz_cairo_get_current_point
#define cairo_get_dash _moz_cairo_get_dash
#define cairo_get_dash_count _moz_cairo_get_dash_count
#define cairo_get_fill_rule _moz_cairo_get_fill_rule
#define cairo_get_font_face _moz_cairo_get_font_face
#define cairo_get_font_matrix _moz_cairo_get_font_matrix
@ -72,7 +81,6 @@
#define cairo_glitz_surface_create _moz_cairo_glitz_surface_create
#define cairo_glyph_extents _moz_cairo_glyph_extents
#define cairo_glyph_path _moz_cairo_glyph_path
#define cairo_has_clip _moz_cairo_has_clip
#define cairo_identity_matrix _moz_cairo_identity_matrix
#define cairo_image_surface_create _moz_cairo_image_surface_create
#define cairo_image_surface_create_for_data _moz_cairo_image_surface_create_for_data
@ -103,6 +111,18 @@
#define cairo_move_to _moz_cairo_move_to
#define cairo_new_path _moz_cairo_new_path
#define cairo_new_sub_path _moz_cairo_new_sub_path
#define cairo_nquartz_surface_create _moz_cairo_nquartz_surface_create
#define cairo_nquartz_surface_create_for_agl_context _moz_cairo_nquartz_surface_create_for_agl_context
#define cairo_nquartz_surface_create_for_cg_context _moz_cairo_nquartz_surface_create_for_cg_context
#define cairo_nquartz_surface_get_cg_context _moz_cairo_nquartz_surface_get_cg_context
#define cairo_os2_fini _moz_cairo_os2_fini
#define cairo_os2_init _moz_cairo_os2_init
#define cairo_os2_surface_create _moz_cairo_os2_surface_create
#define cairo_os2_surface_get_manual_window_refresh _moz_cairo_os2_surface_get_manual_window_refresh
#define cairo_os2_surface_refresh_window _moz_cairo_os2_surface_refresh_window
#define cairo_os2_surface_set_hwnd _moz_cairo_os2_surface_set_hwnd
#define cairo_os2_surface_set_manual_window_refresh _moz_cairo_os2_surface_set_manual_window_refresh
#define cairo_os2_surface_set_size _moz_cairo_os2_surface_set_size
#define cairo_paint _moz_cairo_paint
#define cairo_paint_with_alpha _moz_cairo_paint_with_alpha
#define cairo_path_destroy _moz_cairo_path_destroy
@ -114,9 +134,15 @@
#define cairo_pattern_create_rgb _moz_cairo_pattern_create_rgb
#define cairo_pattern_create_rgba _moz_cairo_pattern_create_rgba
#define cairo_pattern_destroy _moz_cairo_pattern_destroy
#define cairo_pattern_get_color_stop_count _moz_cairo_pattern_get_color_stop_count
#define cairo_pattern_get_color_stop_rgba _moz_cairo_pattern_get_color_stop_rgba
#define cairo_pattern_get_extend _moz_cairo_pattern_get_extend
#define cairo_pattern_get_filter _moz_cairo_pattern_get_filter
#define cairo_pattern_get_linear_points _moz_cairo_pattern_get_linear_points
#define cairo_pattern_get_matrix _moz_cairo_pattern_get_matrix
#define cairo_pattern_get_radial_circles _moz_cairo_pattern_get_radial_circles
#define cairo_pattern_get_rgba _moz_cairo_pattern_get_rgba
#define cairo_pattern_get_surface _moz_cairo_pattern_get_surface
#define cairo_pattern_get_type _moz_cairo_pattern_get_type
#define cairo_pattern_reference _moz_cairo_pattern_reference
#define cairo_pattern_set_extend _moz_cairo_pattern_set_extend
@ -125,6 +151,7 @@
#define cairo_pattern_status _moz_cairo_pattern_status
#define cairo_pdf_surface_create _moz_cairo_pdf_surface_create
#define cairo_pdf_surface_create_for_stream _moz_cairo_pdf_surface_create_for_stream
#define cairo_pdf_surface_set_size _moz_cairo_pdf_surface_set_size
#define cairo_pop_group _moz_cairo_pop_group
#define cairo_pop_group_to_source _moz_cairo_pop_group_to_source
#define cairo_profile_surface_create _moz_cairo_profile_surface_create
@ -139,6 +166,7 @@
#define cairo_push_group_with_content _moz_cairo_push_group_with_content
#define cairo_quartz_surface_create _moz_cairo_quartz_surface_create
#define cairo_rectangle _moz_cairo_rectangle
#define cairo_rectangle_list_destroy _moz_cairo_rectangle_list_destroy
#define cairo_reference _moz_cairo_reference
#define cairo_rel_curve_to _moz_cairo_rel_curve_to
#define cairo_rel_line_to _moz_cairo_rel_line_to
@ -198,6 +226,7 @@
#define cairo_surface_get_font_options _moz_cairo_surface_get_font_options
#define cairo_surface_get_type _moz_cairo_surface_get_type
#define cairo_surface_get_user_data _moz_cairo_surface_get_user_data
#define cairo_surface_is_nquartz _moz_cairo_surface_is_nquartz
#define cairo_surface_is_profile _moz_cairo_surface_is_profile
#define cairo_surface_mark_dirty _moz_cairo_surface_mark_dirty
#define cairo_surface_mark_dirty_rectangle _moz_cairo_surface_mark_dirty_rectangle

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

@ -50,7 +50,7 @@ typedef struct _cairo_scaled_font_subset {
* Value of glyphs array is scaled_font_glyph_index.
*/
unsigned long *glyphs;
int num_glyphs;
unsigned int num_glyphs;
} cairo_scaled_font_subset_t;
/**
@ -187,6 +187,8 @@ typedef struct _cairo_truetype_subset {
long ascent, descent;
char *data;
unsigned long data_length;
unsigned long *string_offsets;
unsigned long num_string_offsets;
} cairo_truetype_subset_t;
/**
@ -237,6 +239,7 @@ typedef struct _cairo_type1_subset {
* _cairo_type1_subset_init:
* @type1_subset: a #cairo_type1_subset_t to initialize
* @font_subset: the #cairo_scaled_font_subset_t to initialize from
* @hex_encode: if true the encrypted portion of the font is hex encoded
*
* If possible (depending on the format of the underlying
* cairo_scaled_font_t and the font backend in use) generate a type1
@ -251,7 +254,8 @@ typedef struct _cairo_type1_subset {
cairo_private cairo_status_t
_cairo_type1_subset_init (cairo_type1_subset_t *type_subset,
const char *name,
cairo_scaled_font_subset_t *font_subset);
cairo_scaled_font_subset_t *font_subset,
cairo_bool_t hex_encode);
/**
* _cairo_type1_subset_fini:
@ -264,4 +268,35 @@ _cairo_type1_subset_init (cairo_type1_subset_t *type_subset,
cairo_private void
_cairo_type1_subset_fini (cairo_type1_subset_t *subset);
/**
* _cairo_type1_fallback_init:
* @type1_subset: a #cairo_type1_subset_t to initialize
* @font_subset: the #cairo_scaled_font_subset_t to initialize from
*
* If possible (depending on the format of the underlying
* cairo_scaled_font_t and the font backend in use) generate a type1
* file corresponding to @font_subset and initialize @type1_subset
* with information about the subset and the type1 data.
*
* Return value: CAIRO_STATUS_SUCCESS if successful,
* CAIRO_INT_STATUS_UNSUPPORTED if the font can't be subset as a type1
* file, or an non-zero value indicating an error. Possible errors
* include CAIRO_STATUS_NO_MEMORY.
**/
cairo_private cairo_status_t
_cairo_type1_fallback_init (cairo_type1_subset_t *type_subset,
const char *name,
cairo_scaled_font_subset_t *font_subset);
/**
* _cairo_type1_fallback_fini:
* @type1_subset: a #cairo_type1_subset_t
*
* Free all resources associated with @type1_subset. After this call,
* @type1_subset should not be used again without a subsequent call to
* _cairo_truetype_type1_init() again first.
**/
cairo_private void
_cairo_type1_fallback_fini (cairo_type1_subset_t *subset);
#endif /* CAIRO_SCALED_FONT_SUBSETS_PRIVATE_H */

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

@ -73,9 +73,9 @@ typedef struct _cairo_sub_font_glyph {
typedef struct _cairo_sub_font_collection {
unsigned long *glyphs; /* scaled_font_glyph_index */
int glyphs_size;
int max_glyph;
int num_glyphs;
unsigned int glyphs_size;
unsigned int max_glyph;
unsigned int num_glyphs;
unsigned int subset_id;

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

@ -1,4 +1,4 @@
/* $Id: cairo-scaled-font.c,v 1.10 2006/07/13 20:19:37 vladimir%pobox.com Exp $
/* $Id: cairo-scaled-font.c,v 1.11 2006/09/26 22:21:55 vladimir%pobox.com Exp $
*
* Copyright © 2005 Keith Packard
*
@ -74,7 +74,7 @@ _cairo_scaled_glyph_destroy (void *abstract_glyph)
static const cairo_scaled_font_t _cairo_scaled_font_nil = {
{ 0 }, /* hash_entry */
CAIRO_STATUS_NO_MEMORY, /* status */
-1, /* ref_count */
CAIRO_REF_COUNT_INVALID, /* ref_count */
NULL, /* font_face */
{ 1., 0., 0., 1., 0, 0}, /* font_matrix */
{ 1., 0., 0., 1., 0, 0}, /* ctm */
@ -123,7 +123,10 @@ _cairo_scaled_font_set_error (cairo_scaled_font_t *scaled_font,
* cairo_scaled_font_get_type:
* @scaled_font: a #cairo_scaled_font_t
*
* Return value: The type of @scaled_font. See #cairo_font_type_t.
* This function returns the type of the backend used to create
* a scaled font. See #cairo_font_type_t for available types.
*
* Return value: The type of @scaled_font.
*
* Since: 1.2
**/
@ -223,13 +226,15 @@ void
_cairo_scaled_font_map_destroy (void)
{
int i;
cairo_scaled_font_map_t *font_map = cairo_scaled_font_map;
cairo_scaled_font_map_t *font_map;
cairo_scaled_font_t *scaled_font;
if (font_map == NULL)
return;
CAIRO_MUTEX_LOCK (cairo_scaled_font_map_mutex);
CAIRO_MUTEX_UNLOCK (cairo_scaled_font_map_mutex);
font_map = cairo_scaled_font_map;
if (font_map == NULL) {
goto CLEANUP_MUTEX_LOCK;
}
for (i = 0; i < font_map->num_holdovers; i++) {
scaled_font = font_map->holdovers[i];
@ -247,6 +252,9 @@ _cairo_scaled_font_map_destroy (void)
free (cairo_scaled_font_map);
cairo_scaled_font_map = NULL;
CLEANUP_MUTEX_LOCK:
CAIRO_MUTEX_UNLOCK (cairo_scaled_font_map_mutex);
}
/* Fowler / Noll / Vo (FNV) Hash (http://www.isthe.com/chongo/tech/comp/fnv/)
@ -490,6 +498,7 @@ UNWIND_FONT_MAP_LOCK:
UNWIND:
return NULL;
}
slim_hidden_def (cairo_scaled_font_create);
/**
* cairo_scaled_font_reference:
@ -510,7 +519,7 @@ cairo_scaled_font_reference (cairo_scaled_font_t *scaled_font)
if (scaled_font == NULL)
return NULL;
if (scaled_font->ref_count == (unsigned int)-1)
if (scaled_font->ref_count == CAIRO_REF_COUNT_INVALID)
return scaled_font;
/* We would normally assert (scaled_font->ref_count > 0) here, but
@ -548,6 +557,7 @@ cairo_scaled_font_reference (cairo_scaled_font_t *scaled_font)
return scaled_font;
}
slim_hidden_def (cairo_scaled_font_reference);
/**
* cairo_scaled_font_destroy:
@ -565,7 +575,7 @@ cairo_scaled_font_destroy (cairo_scaled_font_t *scaled_font)
if (scaled_font == NULL)
return;
if (scaled_font->ref_count == (unsigned int)-1)
if (scaled_font->ref_count == CAIRO_REF_COUNT_INVALID)
return;
/* cairo_scaled_font_t objects are cached and shared between
@ -608,6 +618,7 @@ cairo_scaled_font_destroy (cairo_scaled_font_t *scaled_font)
}
_cairo_scaled_font_map_unlock ();
}
slim_hidden_def (cairo_scaled_font_destroy);
/* Public font API follows. */
@ -624,6 +635,7 @@ cairo_scaled_font_extents (cairo_scaled_font_t *scaled_font,
{
*extents = scaled_font->extents;
}
slim_hidden_def (cairo_scaled_font_extents);
/**
* cairo_scaled_font_text_extents:
@ -749,6 +761,7 @@ cairo_scaled_font_glyph_extents (cairo_scaled_font_t *scaled_font,
extents->x_advance = x_pos - glyphs[0].x;
extents->y_advance = y_pos - glyphs[0].y;
}
slim_hidden_def (cairo_scaled_font_glyph_extents);
cairo_status_t
_cairo_scaled_font_text_to_glyphs (cairo_scaled_font_t *scaled_font,
@ -758,7 +771,7 @@ _cairo_scaled_font_text_to_glyphs (cairo_scaled_font_t *scaled_font,
cairo_glyph_t **glyphs,
int *num_glyphs)
{
size_t i;
int i;
uint32_t *ucs4 = NULL;
cairo_status_t status = CAIRO_STATUS_SUCCESS;
cairo_scaled_glyph_t *scaled_glyph;
@ -1049,6 +1062,74 @@ _scaled_glyph_path_close_path (void *abstract_closure)
return _cairo_path_fixed_close_path (closure->path);
}
/**
* _trace_mask_to_path:
* @bitmap: An alpha mask (either CAIRO_FORMAT_A1 or _A8)
* @path: An initialized path to hold the result
*
* Given a mask surface, (an alpha image), fill out the provided path
* so that when filled it would result in something that approximates
* the mask.
*
* Note: The current tracing code here is extremely primitive. It
* operates only on an A1 surface, (converting an A8 surface to A1 if
* necessary), and performs the tracing by drawing a little square
* around each pixel that is on in the mask. We do not pretend that
* this is a high-quality result. But we are leaving it up to somone
* who cares enough about getting a better result to implement
* something more sophisticated.
**/
static cairo_status_t
_trace_mask_to_path (cairo_image_surface_t *mask,
cairo_path_fixed_t *path)
{
cairo_image_surface_t *a1_mask;
unsigned char *row, *byte_ptr, byte;
int rows, cols, bytes_per_row;
int x, y, bit;
double xoff, yoff;
if (mask->format == CAIRO_FORMAT_A1)
a1_mask = mask;
else
a1_mask = _cairo_image_surface_clone (mask, CAIRO_FORMAT_A1);
if (cairo_surface_status (&a1_mask->base))
return cairo_surface_status (&a1_mask->base);
cairo_surface_get_device_offset (&mask->base, &xoff, &yoff);
bytes_per_row = (a1_mask->width + 7) / 8;
for (y = 0, row = a1_mask->data, rows = a1_mask->height; rows; row += a1_mask->stride, rows--, y++) {
for (x = 0, byte_ptr = row, cols = (a1_mask->width + 7) / 8; cols; byte_ptr++, cols--) {
byte = CAIRO_BITSWAP8_IF_LITTLE_ENDIAN (*byte_ptr);
for (bit = 7; bit >= 0 && x < a1_mask->width; bit--, x++) {
if (byte & (1 << bit)) {
_cairo_path_fixed_move_to (path,
_cairo_fixed_from_int (x + xoff),
_cairo_fixed_from_int (y + yoff));
_cairo_path_fixed_rel_line_to (path,
_cairo_fixed_from_int (1),
_cairo_fixed_from_int (0));
_cairo_path_fixed_rel_line_to (path,
_cairo_fixed_from_int (0),
_cairo_fixed_from_int (1));
_cairo_path_fixed_rel_line_to (path,
_cairo_fixed_from_int (-1),
_cairo_fixed_from_int (0));
_cairo_path_fixed_close_path (path);
}
}
}
}
if (a1_mask != mask)
cairo_surface_destroy (&a1_mask->base);
return CAIRO_STATUS_SUCCESS;
}
cairo_status_t
_cairo_scaled_font_glyph_path (cairo_scaled_font_t *scaled_font,
const cairo_glyph_t *glyphs,
@ -1058,6 +1139,7 @@ _cairo_scaled_font_glyph_path (cairo_scaled_font_t *scaled_font,
cairo_status_t status;
int i;
cairo_scaled_glyph_path_closure_t closure;
cairo_path_fixed_t *glyph_path;
if (scaled_font->status)
return scaled_font->status;
@ -1070,19 +1152,42 @@ _cairo_scaled_font_glyph_path (cairo_scaled_font_t *scaled_font,
glyphs[i].index,
CAIRO_SCALED_GLYPH_INFO_PATH,
&scaled_glyph);
if (status)
if (status == CAIRO_STATUS_SUCCESS)
glyph_path = scaled_glyph->path;
else if (status != CAIRO_INT_STATUS_UNSUPPORTED)
return status;
/* If the font is incapable of providing a path, then we'll
* have to trace our own from a surface. */
if (status == CAIRO_INT_STATUS_UNSUPPORTED) {
status = _cairo_scaled_glyph_lookup (scaled_font,
glyphs[i].index,
CAIRO_SCALED_GLYPH_INFO_SURFACE,
&scaled_glyph);
glyph_path = _cairo_path_fixed_create ();
if (glyph_path == NULL)
return CAIRO_STATUS_NO_MEMORY;
status = _trace_mask_to_path (scaled_glyph->surface, glyph_path);
if (status) {
_cairo_path_fixed_destroy (glyph_path);
return status;
}
}
closure.offset.x = _cairo_fixed_from_double (glyphs[i].x);
closure.offset.y = _cairo_fixed_from_double (glyphs[i].y);
status = _cairo_path_fixed_interpret (scaled_glyph->path,
status = _cairo_path_fixed_interpret (glyph_path,
CAIRO_DIRECTION_FORWARD,
_scaled_glyph_path_move_to,
_scaled_glyph_path_line_to,
_scaled_glyph_path_curve_to,
_scaled_glyph_path_close_path,
&closure);
if (glyph_path != scaled_glyph->path)
_cairo_path_fixed_destroy (glyph_path);
}
return CAIRO_STATUS_SUCCESS;
@ -1152,9 +1257,9 @@ _cairo_scaled_glyph_set_metrics (cairo_scaled_glyph_t *scaled_glyph,
scaled_glyph->metrics.x_advance = fs_metrics->x_advance;
scaled_glyph->metrics.y_advance = fs_metrics->y_advance;
cairo_matrix_transform_point (&scaled_font->font_matrix,
&scaled_glyph->metrics.x_advance,
&scaled_glyph->metrics.y_advance);
cairo_matrix_transform_distance (&scaled_font->font_matrix,
&scaled_glyph->metrics.x_advance,
&scaled_glyph->metrics.y_advance);
scaled_glyph->bbox.p1.x = _cairo_fixed_from_double (min_device_x);
scaled_glyph->bbox.p1.y = _cairo_fixed_from_double (min_device_y);
@ -1298,6 +1403,8 @@ _cairo_scaled_glyph_lookup (cairo_scaled_font_t *scaled_font,
* cairo_scaled_font_get_font_face:
* @scaled_font: a #cairo_scaled_font_t
*
* Gets the font face that this scaled font was created for.
*
* Return value: The #cairo_font_face_t with which @scaled_font was
* created.
*
@ -1311,6 +1418,7 @@ cairo_scaled_font_get_font_face (cairo_scaled_font_t *scaled_font)
return scaled_font->font_face;
}
slim_hidden_def (cairo_scaled_font_get_font_face);
/**
* cairo_scaled_font_get_font_matrix:
@ -1333,6 +1441,7 @@ cairo_scaled_font_get_font_matrix (cairo_scaled_font_t *scaled_font,
*font_matrix = scaled_font->font_matrix;
}
slim_hidden_def (cairo_scaled_font_get_font_matrix);
/**
* cairo_scaled_font_get_ctm:
@ -1354,6 +1463,7 @@ cairo_scaled_font_get_ctm (cairo_scaled_font_t *scaled_font,
*ctm = scaled_font->ctm;
}
slim_hidden_def (cairo_scaled_font_get_ctm);
/**
* cairo_scaled_font_get_font_options:
@ -1376,3 +1486,4 @@ cairo_scaled_font_get_font_options (cairo_scaled_font_t *scaled_font,
_cairo_font_options_init_copy (options, &scaled_font->options);
}
slim_hidden_def (cairo_scaled_font_get_font_options);

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

@ -45,7 +45,7 @@ const cairo_surface_t _cairo_surface_nil = {
&cairo_image_surface_backend, /* backend */
CAIRO_SURFACE_TYPE_IMAGE,
CAIRO_CONTENT_COLOR,
-1, /* ref_count */
CAIRO_REF_COUNT_INVALID, /* ref_count */
CAIRO_STATUS_NO_MEMORY, /* status */
FALSE, /* finished */
{ 0, /* size */
@ -63,15 +63,23 @@ const cairo_surface_t _cairo_surface_nil = {
}, /* device_transform_inverse */
0.0, /* x_fallback_resolution */
0.0, /* y_fallback_resolution */
NULL, /* clip */
0, /* next_clip_serial */
0 /* current_clip_serial */
0, /* current_clip_serial */
FALSE, /* is_snapshot */
FALSE, /* has_font_options */
{ CAIRO_ANTIALIAS_DEFAULT,
CAIRO_SUBPIXEL_ORDER_DEFAULT,
CAIRO_HINT_STYLE_DEFAULT,
CAIRO_HINT_METRICS_DEFAULT
} /* font_options */
};
const cairo_surface_t _cairo_surface_nil_file_not_found = {
&cairo_image_surface_backend, /* backend */
CAIRO_SURFACE_TYPE_IMAGE,
CAIRO_CONTENT_COLOR,
-1, /* ref_count */
CAIRO_REF_COUNT_INVALID, /* ref_count */
CAIRO_STATUS_FILE_NOT_FOUND, /* status */
FALSE, /* finished */
{ 0, /* size */
@ -89,15 +97,23 @@ const cairo_surface_t _cairo_surface_nil_file_not_found = {
}, /* device_transform_inverse */
0.0, /* x_fallback_resolution */
0.0, /* y_fallback_resolution */
NULL, /* clip */
0, /* next_clip_serial */
0 /* current_clip_serial */
0, /* current_clip_serial */
FALSE, /* is_snapshot */
FALSE, /* has_font_options */
{ CAIRO_ANTIALIAS_DEFAULT,
CAIRO_SUBPIXEL_ORDER_DEFAULT,
CAIRO_HINT_STYLE_DEFAULT,
CAIRO_HINT_METRICS_DEFAULT
} /* font_options */
};
const cairo_surface_t _cairo_surface_nil_read_error = {
&cairo_image_surface_backend, /* backend */
CAIRO_SURFACE_TYPE_IMAGE,
CAIRO_CONTENT_COLOR,
-1, /* ref_count */
CAIRO_REF_COUNT_INVALID, /* ref_count */
CAIRO_STATUS_READ_ERROR, /* status */
FALSE, /* finished */
{ 0, /* size */
@ -115,8 +131,16 @@ const cairo_surface_t _cairo_surface_nil_read_error = {
}, /* device_transform_inverse */
0.0, /* x_fallback_resolution */
0.0, /* y_fallback_resolution */
NULL, /* clip */
0, /* next_clip_serial */
0 /* current_clip_serial */
0, /* current_clip_serial */
FALSE, /* is_snapshot */
FALSE, /* has_font_options */
{ CAIRO_ANTIALIAS_DEFAULT,
CAIRO_SUBPIXEL_ORDER_DEFAULT,
CAIRO_HINT_STYLE_DEFAULT,
CAIRO_HINT_METRICS_DEFAULT
} /* font_options */
};
static void
@ -157,7 +181,10 @@ _cairo_surface_set_error (cairo_surface_t *surface,
* cairo_surface_get_type:
* @surface: a #cairo_surface_t
*
* Return value: The type of @surface. See #cairo_surface_type_t.
* This function returns the type of the backend used to create
* a surface. See #cairo_surface_type_t for available types.
*
* Return value: The type of @surface.
*
* Since: 1.2
**/
@ -170,6 +197,7 @@ cairo_surface_get_type (cairo_surface_t *surface)
* surface. */
return surface->type;
}
slim_hidden_def (cairo_surface_get_type);
/**
* cairo_surface_get_content:
@ -205,6 +233,7 @@ cairo_surface_status (cairo_surface_t *surface)
{
return surface->status;
}
slim_hidden_def (cairo_surface_status);
void
_cairo_surface_init (cairo_surface_t *surface,
@ -234,6 +263,8 @@ _cairo_surface_init (cairo_surface_t *surface,
surface->current_clip_serial = 0;
surface->is_snapshot = FALSE;
surface->has_font_options = FALSE;
}
cairo_surface_t *
@ -242,15 +273,28 @@ _cairo_surface_create_similar_scratch (cairo_surface_t *other,
int width,
int height)
{
cairo_surface_t *surface = NULL;
cairo_font_options_t options;
cairo_format_t format = _cairo_format_from_content (content);
if (other->status)
return (cairo_surface_t*) &_cairo_surface_nil;
if (other->backend->create_similar)
return other->backend->create_similar (other, content, width, height);
else
return cairo_image_surface_create (format, width, height);
surface = other->backend->create_similar (other, content, width, height);
if (!surface)
surface = cairo_image_surface_create (format, width, height);
cairo_surface_get_font_options (other, &options);
_cairo_surface_set_font_options (surface, &options);
cairo_surface_set_fallback_resolution (surface,
other->x_fallback_resolution,
other->y_fallback_resolution);
return surface;
}
/**
@ -261,9 +305,12 @@ _cairo_surface_create_similar_scratch (cairo_surface_t *other,
* @height: height of the new surface (in device-space units)
*
* Create a new surface that is as compatible as possible with an
* existing surface. The new surface will use the same backend as
* @other unless that is not possible for some reason. The type of the
* returned surface may be examined with cairo_surface_get_type().
* existing surface. For example the new surface will have the same
* fallback resolution and font options as @other. Generally, the new
* surface will also use the same backend as @other, unless that is
* not possible for some reason. The type of the returned surface may
* be examined with cairo_surface_get_type().
*
* Initially the surface contents are all 0 (transparent if contents
* have transparency, black otherwise.)
*
@ -293,6 +340,7 @@ cairo_surface_create_similar (cairo_surface_t *other,
width, height,
CAIRO_COLOR_TRANSPARENT);
}
slim_hidden_def (cairo_surface_create_similar);
cairo_surface_t *
_cairo_surface_create_similar_solid (cairo_surface_t *other,
@ -362,7 +410,7 @@ cairo_surface_reference (cairo_surface_t *surface)
if (surface == NULL)
return NULL;
if (surface->ref_count == (unsigned int)-1)
if (surface->ref_count == CAIRO_REF_COUNT_INVALID)
return surface;
assert (surface->ref_count > 0);
@ -371,6 +419,7 @@ cairo_surface_reference (cairo_surface_t *surface)
return surface;
}
slim_hidden_def (cairo_surface_reference);
/**
* cairo_surface_destroy:
@ -386,7 +435,7 @@ cairo_surface_destroy (cairo_surface_t *surface)
if (surface == NULL)
return;
if (surface->ref_count == (unsigned int)-1)
if (surface->ref_count == CAIRO_REF_COUNT_INVALID)
return;
assert (surface->ref_count > 0);
@ -452,6 +501,7 @@ cairo_surface_finish (cairo_surface_t *surface)
surface->finished = TRUE;
}
slim_hidden_def (cairo_surface_finish);
/**
* cairo_surface_get_user_data:
@ -495,13 +545,40 @@ cairo_surface_set_user_data (cairo_surface_t *surface,
void *user_data,
cairo_destroy_func_t destroy)
{
if (surface->ref_count == -1)
if (surface->ref_count == CAIRO_REF_COUNT_INVALID)
return CAIRO_STATUS_NO_MEMORY;
return _cairo_user_data_array_set_data (&surface->user_data,
key, user_data, destroy);
}
/**
* _cairo_surface_set_font_options:
* @surface: a #cairo_surface_t
* @options: a #cairo_font_options_t object that contains the
* options to use for this surface instead of backend's default
* font options.
*
* Sets the default font rendering options for the surface.
* This is useful to correctly propagate default font options when
* falling back to an image surface in a backend implementation.
* This affects the options returned in cairo_surface_get_font_options().
*
* If @options is %NULL the surface options are reset to those of
* the backend default.
**/
void
_cairo_surface_set_font_options (cairo_surface_t *surface,
cairo_font_options_t *options)
{
if (options) {
surface->has_font_options = TRUE;
_cairo_font_options_init_copy (&surface->font_options, options);
} else {
surface->has_font_options = FALSE;
}
}
/**
* cairo_surface_get_font_options:
* @surface: a #cairo_surface_t
@ -518,12 +595,19 @@ void
cairo_surface_get_font_options (cairo_surface_t *surface,
cairo_font_options_t *options)
{
if (!surface->finished && surface->backend->get_font_options) {
surface->backend->get_font_options (surface, options);
} else {
_cairo_font_options_init_default (options);
if (!surface->has_font_options) {
surface->has_font_options = TRUE;
if (!surface->finished && surface->backend->get_font_options) {
surface->backend->get_font_options (surface, &surface->font_options);
} else {
_cairo_font_options_init_default (&surface->font_options);
}
}
_cairo_font_options_init_copy (options, &surface->font_options);
}
slim_hidden_def (cairo_surface_get_font_options);
/**
* cairo_surface_flush:
@ -630,6 +714,7 @@ cairo_surface_mark_dirty_rectangle (cairo_surface_t *surface,
_cairo_surface_set_error (surface, status);
}
}
slim_hidden_def (cairo_surface_mark_dirty_rectangle);
/**
* _cairo_surface_set_device_scale:
@ -712,6 +797,7 @@ cairo_surface_set_device_offset (cairo_surface_t *surface,
surface->device_transform_inverse.x0 = - x_offset;
surface->device_transform_inverse.y0 = - y_offset;
}
slim_hidden_def (cairo_surface_set_device_offset);
/**
* cairo_surface_get_device_offset:
@ -732,6 +818,7 @@ cairo_surface_get_device_offset (cairo_surface_t *surface,
*x_offset = surface->device_transform.x0;
*y_offset = surface->device_transform.y0;
}
slim_hidden_def (cairo_surface_get_device_offset);
/**
* cairo_surface_set_fallback_resolution:
@ -771,6 +858,7 @@ cairo_surface_set_fallback_resolution (cairo_surface_t *surface,
surface->x_fallback_resolution = x_pixels_per_inch;
surface->y_fallback_resolution = y_pixels_per_inch;
}
slim_hidden_def (cairo_surface_set_fallback_resolution);
cairo_bool_t
_cairo_surface_has_device_transform (cairo_surface_t *surface)
@ -1702,9 +1790,9 @@ _cairo_surface_show_glyphs (cairo_surface_t *surface,
cairo_scaled_font_t *scaled_font)
{
cairo_status_t status;
cairo_glyph_t *dev_glyphs = (cairo_glyph_t*) glyphs;
cairo_scaled_font_t *dev_scaled_font = scaled_font;
cairo_pattern_union_t dev_source;
cairo_matrix_t font_matrix;
assert (! surface->is_snapshot);
@ -1718,60 +1806,44 @@ _cairo_surface_show_glyphs (cairo_surface_t *surface,
surface,
&dev_source.base);
if (_cairo_surface_has_device_transform (surface))
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))
{
int i;
cairo_font_options_t *font_options;
cairo_matrix_t dev_ctm;
dev_glyphs = malloc (sizeof(cairo_glyph_t) * num_glyphs);
if (!dev_glyphs)
return CAIRO_STATUS_NO_MEMORY;
font_options = cairo_font_options_create ();
for (i = 0; i < num_glyphs; i++) {
dev_glyphs[i].index = glyphs[i].index;
dev_glyphs[i].x = glyphs[i].x;
dev_glyphs[i].y = glyphs[i].y;
cairo_matrix_transform_point (&surface->device_transform,
&dev_glyphs[i].x,
&dev_glyphs[i].y);
}
if (! _cairo_matrix_is_integer_translation (&surface->device_transform, NULL, NULL)) {
cairo_font_options_t *font_options;
cairo_matrix_t font_matrix, 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);
dev_scaled_font = cairo_scaled_font_create (cairo_scaled_font_get_font_face (scaled_font),
&font_matrix,
&dev_ctm,
font_options);
cairo_font_options_destroy (font_options);
}
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);
dev_scaled_font = cairo_scaled_font_create (cairo_scaled_font_get_font_face (scaled_font),
&font_matrix,
&dev_ctm,
font_options);
cairo_font_options_destroy (font_options);
}
if (surface->backend->show_glyphs) {
status = surface->backend->show_glyphs (surface, op, &dev_source.base,
dev_glyphs, num_glyphs,
glyphs, num_glyphs,
dev_scaled_font);
if (status != CAIRO_INT_STATUS_UNSUPPORTED)
goto FINISH;
}
status = _cairo_surface_fallback_show_glyphs (surface, op, &dev_source.base,
dev_glyphs, num_glyphs,
glyphs, num_glyphs,
dev_scaled_font);
FINISH:
if (dev_glyphs != glyphs)
free (dev_glyphs);
if (dev_scaled_font != scaled_font)
cairo_scaled_font_destroy (dev_scaled_font);
_cairo_pattern_fini (&dev_source.base);
return status;
}

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

@ -42,7 +42,6 @@
#include "cairo-svg.h"
#include "cairo-svg-test.h"
#include "cairo-path-fixed-private.h"
#include "cairo-ft-private.h"
#include "cairo-meta-surface-private.h"
#include "cairo-paginated-surface-private.h"
#include "cairo-scaled-font-subsets-private.h"
@ -290,7 +289,7 @@ cairo_svg_surface_restrict_to_version (cairo_surface_t *abstract_surface,
return;
}
if (version >= 0 && version < CAIRO_SVG_VERSION_LAST)
if (version < CAIRO_SVG_VERSION_LAST)
surface->document->svg_version = version;
}
@ -330,7 +329,7 @@ cairo_svg_get_versions (cairo_svg_version_t const **versions,
const char *
cairo_svg_version_to_string (cairo_svg_version_t version)
{
if (version < 0 || version >= CAIRO_SVG_VERSION_LAST)
if (version >= CAIRO_SVG_VERSION_LAST)
return NULL;
return _cairo_svg_version_strings[version];
@ -574,7 +573,11 @@ _cairo_svg_document_emit_bitmap_glyph_data (cairo_svg_document_t *document,
return status;
image = scaled_glyph->surface;
assert (image->format == CAIRO_FORMAT_A1);
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 (document->xml_node_glyphs, "<g");
emit_transform (document->xml_node_glyphs, " transform", ">/n", &image->base.device_transform);
@ -593,6 +596,10 @@ _cairo_svg_document_emit_bitmap_glyph_data (cairo_svg_document_t *document,
}
}
_cairo_output_stream_printf (document->xml_node_glyphs, "</g>\n");
if (image != scaled_glyph->surface)
cairo_surface_destroy (&image->base);
return CAIRO_STATUS_SUCCESS;
}
@ -626,7 +633,7 @@ _cairo_svg_document_emit_font_subset (cairo_scaled_font_subset_t *font_subset,
void *closure)
{
cairo_svg_document_t *document = closure;
int i;
unsigned int i;
for (i = 0; i < font_subset->num_glyphs; i++) {
_cairo_svg_document_emit_glyph (document,
@ -898,7 +905,7 @@ emit_meta_surface (cairo_svg_document_t *document,
cairo_output_stream_t *contents;
cairo_meta_surface_t *meta;
cairo_meta_snapshot_t *snapshot;
int num_elements;
unsigned int num_elements;
unsigned int i, id;
num_elements = document->meta_snapshots.num_elements;
@ -1100,7 +1107,7 @@ emit_pattern_stops (cairo_output_stream_t *output,
double start_offset)
{
double offset;
int i;
unsigned int i;
for (i = 0; i < pattern->n_stops; i++) {
offset = start_offset + (1 - start_offset ) *
@ -1602,7 +1609,7 @@ _cairo_svg_surface_intersect_clip_path (void *dst,
cairo_svg_surface_t *surface = dst;
cairo_svg_document_t *document = surface->document;
cairo_status_t status;
int i;
unsigned int i;
if (path == NULL) {
for (i = 0; i < surface->clip_level; i++)
@ -1638,10 +1645,11 @@ static void
_cairo_svg_surface_get_font_options (void *abstract_surface,
cairo_font_options_t *options)
{
_cairo_font_options_init_default (options);
_cairo_font_options_init_default (options);
cairo_font_options_set_hint_style (options, CAIRO_HINT_STYLE_NONE);
cairo_font_options_set_hint_metrics (options, CAIRO_HINT_METRICS_OFF);
cairo_font_options_set_hint_style (options, CAIRO_HINT_STYLE_NONE);
cairo_font_options_set_hint_metrics (options, CAIRO_HINT_METRICS_OFF);
cairo_font_options_set_antialias (options, CAIRO_ANTIALIAS_GRAY);
}
static const cairo_surface_backend_t cairo_svg_surface_backend = {
@ -1795,8 +1803,7 @@ _cairo_svg_document_finish (cairo_svg_document_t *document)
_cairo_output_stream_destroy (document->xml_node_glyphs);
_cairo_output_stream_destroy (document->xml_node_defs);
status = _cairo_output_stream_get_status (output);
_cairo_output_stream_destroy (output);
status = _cairo_output_stream_destroy (output);
for (i = 0; i < document->meta_snapshots.num_elements; i++) {
snapshot = _cairo_array_index (&document->meta_snapshots, i);

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

@ -0,0 +1,170 @@
/* cairo - a vector graphics library with display and print output
*
* Copyright © 2006 Red Hat, Inc
*
* This library is free software; you can redistribute it and/or
* modify it either under the terms of the GNU Lesser General Public
* License version 2.1 as published by the Free Software Foundation
* (the "LGPL") or, at your option, under the terms of the Mozilla
* Public License Version 1.1 (the "MPL"). If you do not alter this
* notice, a recipient may use your version of this file under either
* the MPL or the LGPL.
*
* You should have received a copy of the LGPL along with this library
* in the file COPYING-LGPL-2.1; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
* You should have received a copy of the MPL along with this library
* in the file COPYING-MPL-1.1
*
* The contents of this file are subject to the Mozilla Public License
* Version 1.1 (the "License"); you may not use this file except in
* compliance with the License. You may obtain a copy of the License at
* http://www.mozilla.org/MPL/
*
* This software is distributed on an "AS IS" basis, WITHOUT WARRANTY
* OF ANY KIND, either express or implied. See the LGPL or the MPL for
* the specific language governing rights and limitations.
*
* The Original Code is the cairo graphics library.
*
* The Initial Developer of the Original Code is Red Hat, Inc.
*
* Contributor(s):
* Kristian Høgsberg <krh@redhat.com>
* Adrian Johnson <ajohnson@redneon.com>
*/
#ifndef CAIRO_TRUETYPE_SUBSET_PRIVATE_H
#define CAIRO_TRUETYPE_SUBSET_PRIVATE_H
#include "cairoint.h"
/* The structs defined here should strictly follow the TrueType
* specification and not be padded. We use only 16-bit integer
* in their definition to guarantee that. The fields of type
* "FIXED" in the TT spec are broken into two *_1 and *_2 16-bit
* parts, and 64-bit members are broken into four.
*
* The test truetype-tables in the test suite makes sure that
* these tables have the right size. Please update that test
* if you add new tables/structs that should be packed.
*/
#define MAKE_TT_TAG(a, b, c, d) (a<<24 | b<<16 | c<<8 | d)
#define TT_TAG_cmap MAKE_TT_TAG('c','m','a','p')
#define TT_TAG_cvt MAKE_TT_TAG('c','v','t',' ')
#define TT_TAG_fpgm MAKE_TT_TAG('f','p','g','m')
#define TT_TAG_glyf MAKE_TT_TAG('g','l','y','f')
#define TT_TAG_head MAKE_TT_TAG('h','e','a','d')
#define TT_TAG_hhea MAKE_TT_TAG('h','h','e','a')
#define TT_TAG_hmtx MAKE_TT_TAG('h','m','t','x')
#define TT_TAG_loca MAKE_TT_TAG('l','o','c','a')
#define TT_TAG_maxp MAKE_TT_TAG('m','a','x','p')
#define TT_TAG_name MAKE_TT_TAG('n','a','m','e')
#define TT_TAG_prep MAKE_TT_TAG('p','r','e','p')
/* All tt_* structs are big-endian */
typedef struct _tt_head {
int16_t version_1;
int16_t version_2;
int16_t revision_1;
int16_t revision_2;
uint16_t checksum_1;
uint16_t checksum_2;
uint16_t magic_1;
uint16_t magic_2;
uint16_t flags;
uint16_t units_per_em;
int16_t created_1;
int16_t created_2;
int16_t created_3;
int16_t created_4;
int16_t modified_1;
int16_t modified_2;
int16_t modified_3;
int16_t modified_4;
int16_t x_min; /* FWORD */
int16_t y_min; /* FWORD */
int16_t x_max; /* FWORD */
int16_t y_max; /* FWORD */
uint16_t mac_style;
uint16_t lowest_rec_pppem;
int16_t font_direction_hint;
int16_t index_to_loc_format;
int16_t glyph_data_format;
} tt_head_t;
typedef struct _tt_hhea {
int16_t version_1;
int16_t version_2;
int16_t ascender; /* FWORD */
int16_t descender; /* FWORD */
int16_t line_gap; /* FWORD */
uint16_t advance_max_width; /* UFWORD */
int16_t min_left_side_bearing; /* FWORD */
int16_t min_right_side_bearing; /* FWORD */
int16_t x_max_extent; /* FWORD */
int16_t caret_slope_rise;
int16_t caret_slope_run;
int16_t reserved[5];
int16_t metric_data_format;
uint16_t num_hmetrics;
} tt_hhea_t;
typedef struct _tt_maxp {
int16_t version_1;
int16_t version_2;
uint16_t num_glyphs;
uint16_t max_points;
uint16_t max_contours;
uint16_t max_composite_points;
uint16_t max_composite_contours;
uint16_t max_zones;
uint16_t max_twilight_points;
uint16_t max_storage;
uint16_t max_function_defs;
uint16_t max_instruction_defs;
uint16_t max_stack_elements;
uint16_t max_size_of_instructions;
uint16_t max_component_elements;
uint16_t max_component_depth;
} tt_maxp_t;
typedef struct _tt_name_record {
uint16_t platform;
uint16_t encoding;
uint16_t language;
uint16_t name;
uint16_t length;
uint16_t offset;
} tt_name_record_t;
typedef struct _tt_name {
uint16_t format;
uint16_t num_records;
uint16_t strings_offset;
tt_name_record_t records[1];
} tt_name_t;
/* composite_glyph_t flags */
#define TT_ARG_1_AND_2_ARE_WORDS 0x0001
#define TT_WE_HAVE_A_SCALE 0x0008
#define TT_MORE_COMPONENTS 0x0020
#define TT_WE_HAVE_AN_X_AND_Y_SCALE 0x0040
#define TT_WE_HAVE_A_TWO_BY_TWO 0x0080
typedef struct _tt_composite_glyph {
uint16_t flags;
uint16_t index;
uint16_t args[7]; /* 1 to 7 arguments depending on value of flags */
} tt_composite_glyph_t;
typedef struct _tt_glyph_data {
int16_t num_contours;
int8_t data[8];
tt_composite_glyph_t glyph;
} tt_glyph_data_t;
#endif /* CAIRO_TRUETYPE_SUBSET_PRIVATE_H */

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

@ -0,0 +1,883 @@
/* cairo - a vector graphics library with display and print output
*
* Copyright © 2004 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>
* Adrian Johnson <ajohnson@redneon.com>
*/
#include <string.h>
#include "cairoint.h"
#include "cairo-scaled-font-subsets-private.h"
#include "cairo-truetype-subset-private.h"
typedef struct subset_glyph subset_glyph_t;
struct subset_glyph {
int parent_index;
unsigned long location;
};
typedef struct _cairo_truetype_font {
cairo_scaled_font_subset_t *scaled_font_subset;
struct {
char *base_font;
unsigned int num_glyphs;
int *widths;
long x_min, y_min, x_max, y_max;
long ascent, descent;
} base;
subset_glyph_t *glyphs;
const cairo_scaled_font_backend_t *backend;
int num_glyphs_in_face;
int checksum_index;
cairo_array_t output;
cairo_array_t string_offsets;
unsigned long last_offset;
unsigned long last_boundary;
int *parent_to_subset;
cairo_status_t status;
} cairo_truetype_font_t;
static int
cairo_truetype_font_use_glyph (cairo_truetype_font_t *font, int glyph);
#define ARRAY_LENGTH(a) ( (sizeof (a)) / (sizeof ((a)[0])) )
#define SFNT_VERSION 0x00010000
#define SFNT_STRING_MAX_LENGTH 65535
#ifdef WORDS_BIGENDIAN
#define cpu_to_be16(v) (v)
#define be16_to_cpu(v) (v)
#define cpu_to_be32(v) (v)
#define be32_to_cpu(v) (v)
#else
static inline uint16_t
cpu_to_be16(uint16_t v)
{
return (v << 8) | (v >> 8);
}
static inline uint16_t
be16_to_cpu(uint16_t v)
{
return cpu_to_be16 (v);
}
static inline uint32_t
cpu_to_be32(uint32_t v)
{
return (cpu_to_be16 (v) << 16) | cpu_to_be16 (v >> 16);
}
static inline uint32_t
be32_to_cpu(uint32_t v)
{
return cpu_to_be32 (v);
}
#endif
static cairo_status_t
_cairo_truetype_font_create (cairo_scaled_font_subset_t *scaled_font_subset,
cairo_truetype_font_t **font_return)
{
cairo_status_t status = CAIRO_STATUS_NO_MEMORY;
cairo_truetype_font_t *font;
const cairo_scaled_font_backend_t *backend;
tt_head_t head;
tt_hhea_t hhea;
tt_maxp_t maxp;
tt_name_t *name;
tt_name_record_t *record;
unsigned long size;
int i, j;
backend = scaled_font_subset->scaled_font->backend;
if (!backend->load_truetype_table)
return CAIRO_INT_STATUS_UNSUPPORTED;
/* FIXME: We should either support subsetting vertical fonts, or fail on
* vertical. Currently font_options_t doesn't have vertical flag, but
* it should be added in the future. For now, the freetype backend
* returns UNSUPPORTED in load_truetype_table if the font is vertical.
*
* if (cairo_font_options_get_vertical_layout (scaled_font_subset->scaled_font))
* return CAIRO_INT_STATUS_UNSUPPORTED;
*/
size = sizeof (tt_head_t);
if (backend->load_truetype_table (scaled_font_subset->scaled_font,
TT_TAG_head, 0, (unsigned char *) &head,
&size) != CAIRO_STATUS_SUCCESS)
return CAIRO_INT_STATUS_UNSUPPORTED;
size = sizeof (tt_maxp_t);
if (backend->load_truetype_table (scaled_font_subset->scaled_font,
TT_TAG_maxp, 0, (unsigned char *) &maxp,
&size) != CAIRO_STATUS_SUCCESS)
return CAIRO_INT_STATUS_UNSUPPORTED;
size = sizeof (tt_hhea_t);
if (backend->load_truetype_table (scaled_font_subset->scaled_font,
TT_TAG_hhea, 0, (unsigned char *) &hhea,
&size) != CAIRO_STATUS_SUCCESS)
return CAIRO_INT_STATUS_UNSUPPORTED;
size = 0;
if (backend->load_truetype_table (scaled_font_subset->scaled_font,
TT_TAG_name, 0, NULL,
&size) != CAIRO_STATUS_SUCCESS)
return CAIRO_INT_STATUS_UNSUPPORTED;
name = malloc(size);
if (name == NULL)
return CAIRO_STATUS_NO_MEMORY;
backend->load_truetype_table (scaled_font_subset->scaled_font,
TT_TAG_name, 0, (unsigned char *) name,
&size);
font = malloc (sizeof (cairo_truetype_font_t));
if (font == NULL)
goto fail0;
font->backend = backend;
font->num_glyphs_in_face = be16_to_cpu (maxp.num_glyphs);
font->scaled_font_subset = scaled_font_subset;
font->last_offset = 0;
font->last_boundary = 0;
_cairo_array_init (&font->output, sizeof (char));
if (_cairo_array_grow_by (&font->output, 4096) != CAIRO_STATUS_SUCCESS)
goto fail1;
font->glyphs = calloc (font->num_glyphs_in_face + 1, sizeof (subset_glyph_t));
if (font->glyphs == NULL)
goto fail2;
font->parent_to_subset = calloc (font->num_glyphs_in_face, sizeof (int));
if (font->parent_to_subset == NULL)
goto fail3;
font->base.num_glyphs = 0;
font->base.x_min = be16_to_cpu (head.x_min);
font->base.y_min = be16_to_cpu (head.y_min);
font->base.x_max = be16_to_cpu (head.x_max);
font->base.y_max = be16_to_cpu (head.y_max);
font->base.ascent = be16_to_cpu (hhea.ascender);
font->base.descent = be16_to_cpu (hhea.descender);
/* Extract the font name from the name table. At present this
* just looks for the Mac platform/Roman encoded font name. It
* should be extended to use any suitable font name in the
* name table. If the mac/roman font name is not found a
* CairoFont-x-y name is created.
*/
font->base.base_font = NULL;
for (i = 0; i < be16_to_cpu(name->num_records); i++) {
record = &(name->records[i]);
if ((be16_to_cpu (record->platform) == 1) &&
(be16_to_cpu (record->encoding) == 0) &&
(be16_to_cpu (record->name) == 4)) {
font->base.base_font = malloc (be16_to_cpu(record->length) + 1);
if (font->base.base_font) {
strncpy(font->base.base_font,
((char*)name) + be16_to_cpu (name->strings_offset) + be16_to_cpu (record->offset),
be16_to_cpu (record->length));
font->base.base_font[be16_to_cpu (record->length)] = 0;
}
break;
}
}
free (name);
name = NULL;
if (font->base.base_font == NULL) {
font->base.base_font = malloc (30);
if (font->base.base_font == NULL)
goto fail4;
snprintf(font->base.base_font, 30, "CairoFont-%u-%u",
scaled_font_subset->font_id,
scaled_font_subset->subset_id);
}
for (i = 0, j = 0; font->base.base_font[j]; j++) {
if (font->base.base_font[j] == ' ')
continue;
font->base.base_font[i++] = font->base.base_font[j];
}
font->base.base_font[i] = '\0';
font->base.widths = calloc (font->num_glyphs_in_face, sizeof (int));
if (font->base.widths == NULL)
goto fail5;
_cairo_array_init (&font->string_offsets, sizeof (unsigned long));
if (_cairo_array_grow_by (&font->string_offsets, 10) != CAIRO_STATUS_SUCCESS)
goto fail6;
font->status = CAIRO_STATUS_SUCCESS;
*font_return = font;
return CAIRO_STATUS_SUCCESS;
fail6:
free (font->base.widths);
fail5:
free (font->base.base_font);
fail4:
free (font->parent_to_subset);
fail3:
free (font->glyphs);
fail2:
_cairo_array_fini (&font->output);
fail1:
free (font);
fail0:
if (name)
free (name);
return status;
}
static void
cairo_truetype_font_destroy (cairo_truetype_font_t *font)
{
_cairo_array_fini (&font->string_offsets);
free (font->base.widths);
free (font->base.base_font);
free (font->parent_to_subset);
free (font->glyphs);
_cairo_array_fini (&font->output);
free (font);
}
static cairo_status_t
cairo_truetype_font_allocate_write_buffer (cairo_truetype_font_t *font,
size_t length,
unsigned char **buffer)
{
cairo_status_t status;
status = _cairo_array_allocate (&font->output, length, (void **) buffer);
if (status)
return status;
return CAIRO_STATUS_SUCCESS;
}
static cairo_status_t
cairo_truetype_font_write (cairo_truetype_font_t *font,
const void *data,
size_t length)
{
cairo_status_t status;
status = _cairo_array_append_multiple (&font->output, data, length);
if (status)
return status;
return CAIRO_STATUS_SUCCESS;
}
static void
cairo_truetype_font_write_be16 (cairo_truetype_font_t *font,
uint16_t value)
{
uint16_t be16_value;
be16_value = cpu_to_be16 (value);
cairo_truetype_font_write (font, &be16_value, sizeof be16_value);
}
static void
cairo_truetype_font_write_be32 (cairo_truetype_font_t *font,
uint32_t value)
{
uint32_t be32_value;
be32_value = cpu_to_be32 (value);
cairo_truetype_font_write (font, &be32_value, sizeof be32_value);
}
static unsigned long
cairo_truetype_font_align_output (cairo_truetype_font_t *font)
{
int length, aligned, pad;
unsigned char *padding;
length = _cairo_array_num_elements (&font->output);
aligned = (length + 3) & ~3;
pad = aligned - length;
if (pad) {
cairo_truetype_font_allocate_write_buffer (font, pad, &padding);
memset (padding, 0, pad);
}
return aligned;
}
static void
cairo_truetype_font_check_boundary (cairo_truetype_font_t *font,
unsigned long boundary)
{
if (boundary - font->last_offset > SFNT_STRING_MAX_LENGTH)
{
_cairo_array_append(&font->string_offsets, &font->last_boundary);
font->last_offset = font->last_boundary;
}
font->last_boundary = boundary;
}
static int
cairo_truetype_font_write_cmap_table (cairo_truetype_font_t *font,
unsigned long tag)
{
unsigned int i;
cairo_truetype_font_write_be16 (font, 0);
cairo_truetype_font_write_be16 (font, 1);
cairo_truetype_font_write_be16 (font, 1);
cairo_truetype_font_write_be16 (font, 0);
cairo_truetype_font_write_be32 (font, 12);
/* Output a format 6 encoding table. */
cairo_truetype_font_write_be16 (font, 6);
cairo_truetype_font_write_be16 (font, 10 + 2 * (font->base.num_glyphs - 1));
cairo_truetype_font_write_be16 (font, 0);
cairo_truetype_font_write_be16 (font, 1); /* First glyph */
cairo_truetype_font_write_be16 (font, font->base.num_glyphs - 1);
for (i = 1; i < font->base.num_glyphs; i++)
cairo_truetype_font_write_be16 (font, i);
return font->status;
}
static int
cairo_truetype_font_write_generic_table (cairo_truetype_font_t *font,
unsigned long tag)
{
cairo_status_t status;
unsigned char *buffer;
unsigned long size;
size = 0;
if (font->backend->load_truetype_table( font->scaled_font_subset->scaled_font,
tag, 0, NULL, &size) != CAIRO_STATUS_SUCCESS) {
font->status = CAIRO_INT_STATUS_UNSUPPORTED;
return font->status;
}
status = cairo_truetype_font_allocate_write_buffer (font, size, &buffer);
/* XXX: Need to check status here. */
font->backend->load_truetype_table (font->scaled_font_subset->scaled_font,
tag, 0, buffer, &size);
return 0;
}
static void
cairo_truetype_font_remap_composite_glyph (cairo_truetype_font_t *font,
unsigned char *buffer)
{
tt_glyph_data_t *glyph_data;
tt_composite_glyph_t *composite_glyph;
int num_args;
int has_more_components;
unsigned short flags;
unsigned short index;
glyph_data = (tt_glyph_data_t *) buffer;
if ((int16_t)be16_to_cpu (glyph_data->num_contours) >= 0)
return;
composite_glyph = &glyph_data->glyph;
do {
flags = be16_to_cpu (composite_glyph->flags);
has_more_components = flags & TT_MORE_COMPONENTS;
index = cairo_truetype_font_use_glyph (font, be16_to_cpu (composite_glyph->index));
composite_glyph->index = cpu_to_be16 (index);
num_args = 1;
if (flags & TT_ARG_1_AND_2_ARE_WORDS)
num_args += 1;
if (flags & TT_WE_HAVE_A_SCALE)
num_args += 1;
else if (flags & TT_WE_HAVE_AN_X_AND_Y_SCALE)
num_args += 2;
else if (flags & TT_WE_HAVE_A_TWO_BY_TWO)
num_args += 3;
composite_glyph = (tt_composite_glyph_t *) &(composite_glyph->args[num_args]);
} while (has_more_components);
}
static int
cairo_truetype_font_write_glyf_table (cairo_truetype_font_t *font,
unsigned long tag)
{
cairo_status_t status;
unsigned long start_offset, index, size, next;
tt_head_t header;
unsigned long begin, end;
unsigned char *buffer;
unsigned int i;
union {
unsigned char *bytes;
uint16_t *short_offsets;
uint32_t *long_offsets;
} u;
size = sizeof (tt_head_t);
font->backend->load_truetype_table (font->scaled_font_subset->scaled_font,
TT_TAG_head, 0, (unsigned char*) &header, &size);
if (be16_to_cpu (header.index_to_loc_format) == 0)
size = sizeof (int16_t) * (font->num_glyphs_in_face + 1);
else
size = sizeof (int32_t) * (font->num_glyphs_in_face + 1);
u.bytes = malloc (size);
if (u.bytes == NULL) {
font->status = CAIRO_STATUS_NO_MEMORY;
return font->status;
}
if (font->backend->load_truetype_table (font->scaled_font_subset->scaled_font,
TT_TAG_loca, 0, u.bytes, &size) != CAIRO_STATUS_SUCCESS) {
font->status = CAIRO_INT_STATUS_UNSUPPORTED;
return font->status;
}
start_offset = _cairo_array_num_elements (&font->output);
for (i = 0; i < font->base.num_glyphs; i++) {
index = font->glyphs[i].parent_index;
if (be16_to_cpu (header.index_to_loc_format) == 0) {
begin = be16_to_cpu (u.short_offsets[index]) * 2;
end = be16_to_cpu (u.short_offsets[index + 1]) * 2;
}
else {
begin = be32_to_cpu (u.long_offsets[index]);
end = be32_to_cpu (u.long_offsets[index + 1]);
}
size = end - begin;
next = cairo_truetype_font_align_output (font);
cairo_truetype_font_check_boundary (font, next);
font->glyphs[i].location = next - start_offset;
status = cairo_truetype_font_allocate_write_buffer (font, size, &buffer);
if (status)
break;
if (size != 0) {
font->backend->load_truetype_table (font->scaled_font_subset->scaled_font,
TT_TAG_glyf, begin, buffer, &size);
cairo_truetype_font_remap_composite_glyph (font, buffer);
}
}
font->glyphs[i].location =
cairo_truetype_font_align_output (font) - start_offset;
free (u.bytes);
return font->status;
}
static int
cairo_truetype_font_write_head_table (cairo_truetype_font_t *font,
unsigned long tag)
{
unsigned char *buffer;
unsigned long size;
size = 0;
font->backend->load_truetype_table (font->scaled_font_subset->scaled_font,
tag, 0, NULL, &size);
font->checksum_index = _cairo_array_num_elements (&font->output) + 8;
font->status = cairo_truetype_font_allocate_write_buffer (font, size, &buffer);
font->backend->load_truetype_table( font->scaled_font_subset->scaled_font,
tag, 0, buffer, &size);
return font->status;
}
static int cairo_truetype_font_write_hhea_table (cairo_truetype_font_t *font, unsigned long tag)
{
tt_hhea_t *hhea;
unsigned long size;
size = sizeof (tt_hhea_t);
font->status = cairo_truetype_font_allocate_write_buffer (font, size, (unsigned char **) &hhea);
font->backend->load_truetype_table (font->scaled_font_subset->scaled_font,
tag, 0, (unsigned char *) hhea, &size);
hhea->num_hmetrics = cpu_to_be16 ((uint16_t)(font->base.num_glyphs));
return font->status;
}
static int
cairo_truetype_font_write_hmtx_table (cairo_truetype_font_t *font,
unsigned long tag)
{
cairo_status_t status;
unsigned long size;
unsigned long long_entry_size;
unsigned long short_entry_size;
short *p;
unsigned int i;
tt_hhea_t hhea;
int num_hmetrics;
size = sizeof (tt_hhea_t);
font->backend->load_truetype_table (font->scaled_font_subset->scaled_font,
TT_TAG_hhea, 0, (unsigned char*) &hhea, &size);
num_hmetrics = be16_to_cpu(hhea.num_hmetrics);
for (i = 0; i < font->base.num_glyphs; i++) {
long_entry_size = 2 * sizeof (int16_t);
short_entry_size = sizeof (int16_t);
status = cairo_truetype_font_allocate_write_buffer (font, long_entry_size,
(unsigned char **) &p);
if (font->glyphs[i].parent_index < num_hmetrics) {
if (font->backend->load_truetype_table (font->scaled_font_subset->scaled_font,
TT_TAG_hmtx,
font->glyphs[i].parent_index * long_entry_size,
(unsigned char *) p, &long_entry_size) != CAIRO_STATUS_SUCCESS) {
font->status = CAIRO_INT_STATUS_UNSUPPORTED;
return font->status;
}
}
else
{
if (font->backend->load_truetype_table (font->scaled_font_subset->scaled_font,
TT_TAG_hmtx,
(num_hmetrics - 1) * long_entry_size,
(unsigned char *) p, &short_entry_size) != CAIRO_STATUS_SUCCESS) {
font->status = CAIRO_INT_STATUS_UNSUPPORTED;
return font->status;
}
font->backend->load_truetype_table (font->scaled_font_subset->scaled_font,
TT_TAG_hmtx,
(num_hmetrics - 1) * long_entry_size +
(font->glyphs[i].parent_index - num_hmetrics)
* short_entry_size,
(unsigned char *) (p+1), &short_entry_size);
}
font->base.widths[i] = be16_to_cpu (p[0]);
}
return font->status;
}
static int
cairo_truetype_font_write_loca_table (cairo_truetype_font_t *font,
unsigned long tag)
{
unsigned int i;
tt_head_t header;
unsigned long size;
size = sizeof(tt_head_t);
font->backend->load_truetype_table (font->scaled_font_subset->scaled_font,
TT_TAG_head, 0, (unsigned char*) &header, &size);
if (be16_to_cpu (header.index_to_loc_format) == 0)
{
for (i = 0; i < font->base.num_glyphs + 1; i++)
cairo_truetype_font_write_be16 (font, font->glyphs[i].location / 2);
} else {
for (i = 0; i < font->base.num_glyphs + 1; i++)
cairo_truetype_font_write_be32 (font, font->glyphs[i].location);
}
return font->status;
}
static int
cairo_truetype_font_write_maxp_table (cairo_truetype_font_t *font,
unsigned long tag)
{
tt_maxp_t *maxp;
unsigned long size;
size = sizeof (tt_maxp_t);
font->status = cairo_truetype_font_allocate_write_buffer (font, size, (unsigned char **) &maxp);
font->backend->load_truetype_table (font->scaled_font_subset->scaled_font,
tag, 0, (unsigned char *) maxp, &size);
maxp->num_glyphs = cpu_to_be16 (font->base.num_glyphs);
return font->status;
}
typedef struct table table_t;
struct table {
unsigned long tag;
int (*write) (cairo_truetype_font_t *font, unsigned long tag);
};
static const table_t truetype_tables[] = {
/* As we write out the glyf table we remap composite glyphs.
* Remapping composite glyphs will reference the sub glyphs the
* composite glyph is made up of. That needs to be done first so
* we have all the glyphs in the subset before going further. */
{ TT_TAG_glyf, cairo_truetype_font_write_glyf_table },
{ TT_TAG_cmap, cairo_truetype_font_write_cmap_table },
{ TT_TAG_cvt, cairo_truetype_font_write_generic_table },
{ TT_TAG_fpgm, cairo_truetype_font_write_generic_table },
{ TT_TAG_head, cairo_truetype_font_write_head_table },
{ TT_TAG_hhea, cairo_truetype_font_write_hhea_table },
{ TT_TAG_hmtx, cairo_truetype_font_write_hmtx_table },
{ TT_TAG_loca, cairo_truetype_font_write_loca_table },
{ TT_TAG_maxp, cairo_truetype_font_write_maxp_table },
{ TT_TAG_name, cairo_truetype_font_write_generic_table },
{ TT_TAG_prep, cairo_truetype_font_write_generic_table },
};
static cairo_status_t
cairo_truetype_font_write_offset_table (cairo_truetype_font_t *font)
{
cairo_status_t status;
unsigned char *table_buffer;
size_t table_buffer_length;
unsigned short search_range, entry_selector, range_shift;
int num_tables;
num_tables = ARRAY_LENGTH (truetype_tables);
search_range = 1;
entry_selector = 0;
while (search_range * 2 <= num_tables) {
search_range *= 2;
entry_selector++;
}
search_range *= 16;
range_shift = num_tables * 16 - search_range;
cairo_truetype_font_write_be32 (font, SFNT_VERSION);
cairo_truetype_font_write_be16 (font, num_tables);
cairo_truetype_font_write_be16 (font, search_range);
cairo_truetype_font_write_be16 (font, entry_selector);
cairo_truetype_font_write_be16 (font, range_shift);
/* Allocate space for the table directory. Each directory entry
* will be filled in by cairo_truetype_font_update_entry() after
* the table is written. */
table_buffer_length = ARRAY_LENGTH (truetype_tables) * 16;
status = cairo_truetype_font_allocate_write_buffer (font, table_buffer_length,
&table_buffer);
if (status)
return status;
return font->status;
}
static uint32_t
cairo_truetype_font_calculate_checksum (cairo_truetype_font_t *font,
unsigned long start,
unsigned long end)
{
uint32_t *padded_end;
uint32_t *p;
uint32_t checksum;
char *data;
checksum = 0;
data = _cairo_array_index (&font->output, 0);
p = (uint32_t *) (data + start);
padded_end = (uint32_t *) (data + ((end + 3) & ~3));
while (p < padded_end)
checksum += *p++;
return checksum;
}
static void
cairo_truetype_font_update_entry (cairo_truetype_font_t *font,
int index,
unsigned long tag,
unsigned long start,
unsigned long end)
{
uint32_t *entry;
entry = _cairo_array_index (&font->output, 12 + 16 * index);
entry[0] = cpu_to_be32 ((uint32_t)tag);
entry[1] = cpu_to_be32 (cairo_truetype_font_calculate_checksum (font, start, end));
entry[2] = cpu_to_be32 ((uint32_t)start);
entry[3] = cpu_to_be32 ((uint32_t)(end - start));
}
static cairo_status_t
cairo_truetype_font_generate (cairo_truetype_font_t *font,
const char **data,
unsigned long *length,
const unsigned long **string_offsets,
unsigned long *num_strings)
{
unsigned long start, end, next;
uint32_t checksum, *checksum_location;
unsigned int i;
if (cairo_truetype_font_write_offset_table (font))
goto fail;
start = cairo_truetype_font_align_output (font);
end = start;
end = 0;
for (i = 0; i < ARRAY_LENGTH (truetype_tables); i++) {
if (truetype_tables[i].write (font, truetype_tables[i].tag))
goto fail;
end = _cairo_array_num_elements (&font->output);
next = cairo_truetype_font_align_output (font);
cairo_truetype_font_update_entry (font, i, truetype_tables[i].tag,
start, end);
cairo_truetype_font_check_boundary (font, next);
start = next;
}
checksum =
0xb1b0afba - cairo_truetype_font_calculate_checksum (font, 0, end);
checksum_location = _cairo_array_index (&font->output, font->checksum_index);
*checksum_location = cpu_to_be32 (checksum);
*data = _cairo_array_index (&font->output, 0);
*length = _cairo_array_num_elements (&font->output);
*num_strings = _cairo_array_num_elements (&font->string_offsets);
if (*num_strings != 0)
*string_offsets = _cairo_array_index (&font->string_offsets, 0);
else
*string_offsets = NULL;
fail:
return font->status;
}
static int
cairo_truetype_font_use_glyph (cairo_truetype_font_t *font, int glyph)
{
if (font->parent_to_subset[glyph] == 0) {
font->parent_to_subset[glyph] = font->base.num_glyphs;
font->glyphs[font->base.num_glyphs].parent_index = glyph;
font->base.num_glyphs++;
}
return font->parent_to_subset[glyph];
}
cairo_status_t
_cairo_truetype_subset_init (cairo_truetype_subset_t *truetype_subset,
cairo_scaled_font_subset_t *font_subset)
{
cairo_truetype_font_t *font;
cairo_status_t status;
const char *data = NULL; /* squelch bogus compiler warning */
unsigned long length = 0; /* squelch bogus compiler warning */
unsigned long parent_glyph, offsets_length;
unsigned int i;
const unsigned long *string_offsets = NULL;
unsigned long num_strings = 0;
status = _cairo_truetype_font_create (font_subset, &font);
if (status)
return status;
for (i = 0; i < font->scaled_font_subset->num_glyphs; i++) {
parent_glyph = font->scaled_font_subset->glyphs[i];
cairo_truetype_font_use_glyph (font, parent_glyph);
}
status = cairo_truetype_font_generate (font, &data, &length,
&string_offsets, &num_strings);
if (status)
goto fail1;
truetype_subset->base_font = strdup (font->base.base_font);
if (truetype_subset->base_font == NULL)
goto fail1;
truetype_subset->widths = calloc (sizeof (int), font->base.num_glyphs);
if (truetype_subset->widths == NULL)
goto fail2;
for (i = 0; i < font->base.num_glyphs; i++)
truetype_subset->widths[i] = font->base.widths[i];
truetype_subset->x_min = font->base.x_min;
truetype_subset->y_min = font->base.y_min;
truetype_subset->x_max = font->base.x_max;
truetype_subset->y_max = font->base.y_max;
truetype_subset->ascent = font->base.ascent;
truetype_subset->descent = font->base.descent;
truetype_subset->data = malloc (length);
if (truetype_subset->data == NULL)
goto fail3;
memcpy (truetype_subset->data, data, length);
truetype_subset->data_length = length;
offsets_length = num_strings * sizeof (unsigned long);
truetype_subset->string_offsets = malloc (offsets_length);
if (truetype_subset->string_offsets == NULL)
goto fail4;
memcpy (truetype_subset->string_offsets, string_offsets, offsets_length);
truetype_subset->num_string_offsets = num_strings;
cairo_truetype_font_destroy (font);
return CAIRO_STATUS_SUCCESS;
fail4:
free (truetype_subset->data);
fail3:
free (truetype_subset->widths);
fail2:
free (truetype_subset->base_font);
fail1:
cairo_truetype_font_destroy (font);
return status;
}
void
_cairo_truetype_subset_fini (cairo_truetype_subset_t *subset)
{
free (subset->base_font);
free (subset->widths);
free (subset->data);
free (subset->string_offsets);
}

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

@ -0,0 +1,746 @@
/* cairo - a vector graphics library with display and print output
*
* Copyright © 2006 Red Hat, Inc
*
* This library is free software; you can redistribute it and/or
* modify it either under the terms of the GNU Lesser General Public
* License version 2.1 as published by the Free Software Foundation
* (the "LGPL") or, at your option, under the terms of the Mozilla
* Public License Version 1.1 (the "MPL"). If you do not alter this
* notice, a recipient may use your version of this file under either
* the MPL or the LGPL.
*
* You should have received a copy of the LGPL along with this library
* in the file COPYING-LGPL-2.1; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
* You should have received a copy of the MPL along with this library
* in the file COPYING-MPL-1.1
*
* The contents of this file are subject to the Mozilla Public License
* Version 1.1 (the "License"); you may not use this file except in
* compliance with the License. You may obtain a copy of the License at
* http://www.mozilla.org/MPL/
*
* This software is distributed on an "AS IS" basis, WITHOUT WARRANTY
* OF ANY KIND, either express or implied. See the LGPL or the MPL for
* the specific language governing rights and limitations.
*
* The Original Code is the cairo graphics library.
*
* The Initial Developer of the Original Code is Red Hat, Inc.
*
* Contributor(s):
* Adrian Johnson <ajohnson@redneon.com>
*/
#include "cairoint.h"
#include "cairo-scaled-font-subsets-private.h"
#include "cairo-path-fixed-private.h"
#include "cairo-output-stream-private.h"
typedef struct _cairo_type1_font {
int *widths;
cairo_scaled_font_subset_t *scaled_font_subset;
cairo_scaled_font_t *type1_scaled_font;
cairo_array_t contents;
double x_min, y_min, x_max, y_max;
const char *data;
unsigned long header_size;
unsigned long data_size;
unsigned long trailer_size;
int bbox_position;
int bbox_max_chars;
cairo_output_stream_t *output;
unsigned short eexec_key;
cairo_bool_t hex_encode;
int hex_column;
} cairo_type1_font_t;
static cairo_status_t
cairo_type1_font_create (cairo_scaled_font_subset_t *scaled_font_subset,
cairo_type1_font_t **subset_return)
{
cairo_type1_font_t *font;
cairo_font_face_t *font_face;
cairo_matrix_t font_matrix;
cairo_matrix_t ctm;
cairo_font_options_t font_options;
font = calloc (1, sizeof (cairo_type1_font_t));
if (font == NULL)
return CAIRO_STATUS_NO_MEMORY;
font->widths = calloc (scaled_font_subset->num_glyphs,
sizeof (int));
if (font->widths == NULL) {
free (font);
return CAIRO_STATUS_NO_MEMORY;
}
font->scaled_font_subset = scaled_font_subset;
font_face = cairo_scaled_font_get_font_face (scaled_font_subset->scaled_font);
cairo_matrix_init_scale (&font_matrix, 1000, 1000);
cairo_matrix_init_identity (&ctm);
_cairo_font_options_init_default (&font_options);
cairo_font_options_set_hint_style (&font_options, CAIRO_HINT_STYLE_NONE);
cairo_font_options_set_hint_metrics (&font_options, CAIRO_HINT_METRICS_OFF);
font->type1_scaled_font = cairo_scaled_font_create (font_face,
&font_matrix,
&ctm,
&font_options);
_cairo_array_init (&font->contents, sizeof (unsigned char));
*subset_return = font;
return CAIRO_STATUS_SUCCESS;
}
/* Magic constants for the type1 eexec encryption */
static const unsigned short encrypt_c1 = 52845, encrypt_c2 = 22719;
static const unsigned short private_dict_key = 55665;
static const unsigned short charstring_key = 4330;
/* Charstring commands. If the high byte is 0 the command is encoded
* with a single byte. */
#define CHARSTRING_sbw 0x0c07
#define CHARSTRING_rmoveto 0x0015
#define CHARSTRING_rlineto 0x0005
#define CHARSTRING_rcurveto 0x0008
#define CHARSTRING_closepath 0x0009
#define CHARSTRING_endchar 0x000e
/* Before calling this function, the caller must allocate sufficient
* space in data (see _cairo_array_grow_by). The maxium number of
* bytes that will be used is 2.
*/
static void
charstring_encode_command (cairo_array_t *data, int command)
{
cairo_status_t status;
int orig_size;
unsigned char buf[5];
unsigned char *p = buf;
if (command & 0xff00)
*p++ = command >> 8;
*p++ = command & 0x00ff;
/* Ensure the array doesn't grow, which allows this function to
* have no possibility of failure. */
orig_size = _cairo_array_size (data);
status = _cairo_array_append_multiple (data, buf, p - buf);
assert (status == CAIRO_STATUS_SUCCESS);
assert (_cairo_array_size (data) == orig_size);
}
/* Before calling this function, the caller must allocate sufficient
* space in data (see _cairo_array_grow_by). The maxium number of
* bytes that will be used is 5.
*/
static void
charstring_encode_integer (cairo_array_t *data, int i)
{
cairo_status_t status;
int orig_size;
unsigned char buf[10];
unsigned char *p = buf;
if (i >= -107 && i <= 107) {
*p++ = i + 139;
} else if (i >= 108 && i <= 1131) {
i -= 108;
*p++ = (i >> 8)+ 247;
*p++ = i & 0xff;
} else if (i >= -1131 && i <= -108) {
i = -i - 108;
*p++ = (i >> 8)+ 251;
*p++ = i & 0xff;
} else {
*p++ = 0xff;
*p++ = i >> 24;
*p++ = (i >> 16) & 0xff;
*p++ = (i >> 8) & 0xff;
*p++ = i & 0xff;
}
/* Ensure the array doesn't grow, which allows this function to
* have no possibility of failure. */
orig_size = _cairo_array_size (data);
status = _cairo_array_append_multiple (data, buf, p - buf);
assert (status == CAIRO_STATUS_SUCCESS);
assert (_cairo_array_size (data) == orig_size);
}
typedef struct _ps_path_info {
cairo_array_t *data;
int current_x, current_y;
} t1_path_info_t;
static cairo_status_t
_charstring_move_to (void *closure,
cairo_point_t *point)
{
t1_path_info_t *path_info = (t1_path_info_t *) closure;
int dx, dy;
cairo_status_t status;
status = _cairo_array_grow_by (path_info->data, 12);
if (status)
return status;
dx = _cairo_fixed_integer_part (point->x) - path_info->current_x;
dy = _cairo_fixed_integer_part (point->y) - path_info->current_y;
charstring_encode_integer (path_info->data, dx);
charstring_encode_integer (path_info->data, dy);
path_info->current_x += dx;
path_info->current_y += dy;
charstring_encode_command (path_info->data, CHARSTRING_rmoveto);
return CAIRO_STATUS_SUCCESS;
}
static cairo_status_t
_charstring_line_to (void *closure,
cairo_point_t *point)
{
t1_path_info_t *path_info = (t1_path_info_t *) closure;
int dx, dy;
cairo_status_t status;
status = _cairo_array_grow_by (path_info->data, 12);
if (status)
return status;
dx = _cairo_fixed_integer_part (point->x) - path_info->current_x;
dy = _cairo_fixed_integer_part (point->y) - path_info->current_y;
charstring_encode_integer (path_info->data, dx);
charstring_encode_integer (path_info->data, dy);
path_info->current_x += dx;
path_info->current_y += dy;
charstring_encode_command (path_info->data, CHARSTRING_rlineto);
return CAIRO_STATUS_SUCCESS;
}
static cairo_status_t
_charstring_curve_to (void *closure,
cairo_point_t *point1,
cairo_point_t *point2,
cairo_point_t *point3)
{
t1_path_info_t *path_info = (t1_path_info_t *) closure;
int dx1, dy1, dx2, dy2, dx3, dy3;
cairo_status_t status;
status = _cairo_array_grow_by (path_info->data, 32);
if (status)
return status;
dx1 = _cairo_fixed_integer_part (point1->x) - path_info->current_x;
dy1 = _cairo_fixed_integer_part (point1->y) - path_info->current_y;
dx2 = _cairo_fixed_integer_part (point2->x) - path_info->current_x - dx1;
dy2 = _cairo_fixed_integer_part (point2->y) - path_info->current_y - dy1;
dx3 = _cairo_fixed_integer_part (point3->x) - path_info->current_x - dx1 - dx2;
dy3 = _cairo_fixed_integer_part (point3->y) - path_info->current_y - dy1 - dy2;
charstring_encode_integer (path_info->data, dx1);
charstring_encode_integer (path_info->data, dy1);
charstring_encode_integer (path_info->data, dx2);
charstring_encode_integer (path_info->data, dy2);
charstring_encode_integer (path_info->data, dx3);
charstring_encode_integer (path_info->data, dy3);
path_info->current_x += dx1 + dx2 + dx3;
path_info->current_y += dy1 + dy2 + dy3;
charstring_encode_command (path_info->data, CHARSTRING_rcurveto);
return CAIRO_STATUS_SUCCESS;
}
static cairo_status_t
_charstring_close_path (void *closure)
{
cairo_status_t status;
t1_path_info_t *path_info = (t1_path_info_t *) closure;
status = _cairo_array_grow_by (path_info->data, 2);
if (status)
return status;
charstring_encode_command (path_info->data, CHARSTRING_closepath);
return CAIRO_STATUS_SUCCESS;
}
static void
charstring_encrypt (cairo_array_t *data)
{
unsigned char *d, *end;
uint16_t c, p, r;
r = charstring_key;
d = (unsigned char *) _cairo_array_index (data, 0);
end = d + _cairo_array_num_elements (data);
while (d < end) {
p = *d;
c = p ^ (r >> 8);
r = (c + r) * encrypt_c1 + encrypt_c2;
*d++ = c;
}
}
static cairo_int_status_t
create_notdef_charstring (cairo_array_t *data)
{
cairo_status_t status;
/* We're passing constants below, so we know the 0 values will
* only use 1 byte each, and the 500 values will use 2 bytes
* each. Then 2 more for each of the commands is 10 total. */
status = _cairo_array_grow_by (data, 10);
if (status)
return status;
charstring_encode_integer (data, 0);
charstring_encode_integer (data, 0);
/* The width and height is arbitrary. */
charstring_encode_integer (data, 500);
charstring_encode_integer (data, 500);
charstring_encode_command (data, CHARSTRING_sbw);
charstring_encode_command (data, CHARSTRING_endchar);
return CAIRO_STATUS_SUCCESS;
}
static cairo_int_status_t
cairo_type1_font_create_charstring (cairo_type1_font_t *font,
int subset_index,
int glyph_index,
cairo_array_t *data)
{
cairo_int_status_t status;
cairo_scaled_glyph_t *scaled_glyph;
t1_path_info_t path_info;
cairo_text_extents_t *metrics;
/* This call may return CAIRO_INT_STATUS_UNSUPPORTED for bitmap fonts. */
status = _cairo_scaled_glyph_lookup (font->type1_scaled_font,
glyph_index,
CAIRO_SCALED_GLYPH_INFO_METRICS|
CAIRO_SCALED_GLYPH_INFO_PATH,
&scaled_glyph);
if (status)
return status;
metrics = &scaled_glyph->metrics;
if (subset_index == 0) {
font->x_min = metrics->x_bearing;
font->y_min = metrics->y_bearing;
font->x_max = metrics->x_bearing + metrics->width;
font->y_max = metrics->y_bearing + metrics->height;
} else {
if (metrics->x_bearing < font->x_min)
font->x_min = metrics->x_bearing;
if (metrics->y_bearing < font->y_min)
font->y_min = metrics->y_bearing;
if (metrics->x_bearing + metrics->width > font->x_max)
font->x_max = metrics->x_bearing + metrics->width;
if (metrics->y_bearing + metrics->height > font->y_max)
font->y_max = metrics->y_bearing + metrics->height;
}
font->widths[subset_index] = metrics->width;
status = _cairo_array_grow_by (data, 30);
if (status)
return status;
charstring_encode_integer (data, (int) scaled_glyph->metrics.x_bearing);
charstring_encode_integer (data, (int) scaled_glyph->metrics.y_bearing);
charstring_encode_integer (data, (int) scaled_glyph->metrics.width);
charstring_encode_integer (data, (int) scaled_glyph->metrics.height);
charstring_encode_command (data, CHARSTRING_sbw);
path_info.data = data;
path_info.current_x = (int) scaled_glyph->metrics.x_bearing;
path_info.current_y = (int) scaled_glyph->metrics.y_bearing;
_cairo_path_fixed_interpret (scaled_glyph->path,
CAIRO_DIRECTION_FORWARD,
_charstring_move_to,
_charstring_line_to,
_charstring_curve_to,
_charstring_close_path,
&path_info);
charstring_encode_command (path_info.data, CHARSTRING_endchar);
return CAIRO_STATUS_SUCCESS;
}
static cairo_int_status_t
cairo_type1_font_write_charstrings (cairo_type1_font_t *font,
cairo_output_stream_t *encrypted_output)
{
cairo_status_t status = CAIRO_STATUS_SUCCESS;
unsigned char zeros[] = { 0, 0, 0, 0 };
cairo_array_t data;
unsigned int i;
int length;
_cairo_array_init (&data, sizeof (unsigned char));
status = _cairo_array_grow_by (&data, 1024);
if (status)
goto fail;
_cairo_output_stream_printf (encrypted_output,
"2 index /CharStrings %d dict dup begin\n",
font->scaled_font_subset->num_glyphs + 1);
for (i = 0; i < font->scaled_font_subset->num_glyphs; i++) {
_cairo_array_truncate (&data, 0);
/* four "random" bytes required by encryption algorithm */
_cairo_array_append_multiple (&data, zeros, 4);
status = cairo_type1_font_create_charstring (font, i,
font->scaled_font_subset->glyphs[i],
&data);
if (status)
goto fail;
charstring_encrypt (&data);
length = _cairo_array_num_elements (&data);
_cairo_output_stream_printf (encrypted_output, "/g%d %d RD ", i, length);
_cairo_output_stream_write (encrypted_output,
_cairo_array_index (&data, 0),
length);
_cairo_output_stream_printf (encrypted_output, " ND\n");
}
/* All type 1 fonts must have a /.notdef charstring */
_cairo_array_truncate (&data, 0);
/* four "random" bytes required by encryption algorithm */
_cairo_array_append_multiple (&data, zeros, 4);
create_notdef_charstring (&data);
charstring_encrypt (&data);
length = _cairo_array_num_elements (&data);
_cairo_output_stream_printf (encrypted_output, "/.notdef %d RD ", length);
_cairo_output_stream_write (encrypted_output,
_cairo_array_index (&data, 0),
length);
_cairo_output_stream_printf (encrypted_output, " ND\n");
fail:
_cairo_array_fini (&data);
return status;
}
static cairo_status_t
cairo_type1_font_write_header (cairo_type1_font_t *font,
const char *name)
{
cairo_matrix_t matrix;
unsigned int i;
const char spaces[50] = " ";
matrix = font->type1_scaled_font->scale;
matrix.xy = -matrix.xy;
matrix.yy = -matrix.yy;
cairo_matrix_invert (&matrix);
_cairo_output_stream_printf (font->output,
"%%!FontType1-1.1 %s 1.0\n"
"11 dict begin\n"
"/FontName /%s def\n"
"/PaintType 0 def\n"
"/FontType 1 def\n"
"/FontMatrix [%f %f %f %f 0 0] readonly def\n",
name,
name,
matrix.xx,
matrix.yx,
matrix.xy,
matrix.yy);
/* We don't know the bbox values until after the charstrings have
* been generated. Reserve some space and fill in the bbox
* later. */
/* Worst case for four signed ints with spaces between each number */
font->bbox_max_chars = 50;
_cairo_output_stream_printf (font->output, "/FontBBox {");
font->bbox_position = _cairo_output_stream_get_position (font->output);
_cairo_output_stream_write (font->output, spaces, font->bbox_max_chars);
_cairo_output_stream_printf (font->output,
"} readonly def\n"
"/Encoding 256 array\n"
"0 1 255 {1 index exch /.notdef put} for\n");
for (i = 0; i < font->scaled_font_subset->num_glyphs; i++)
_cairo_output_stream_printf (font->output, "dup %d /g%d put\n", i, i);
_cairo_output_stream_printf (font->output,
"readonly def\n"
"currentdict end\n"
"currentfile eexec\n");
return CAIRO_STATUS_SUCCESS;
}
static cairo_status_t
cairo_type1_write_stream_encrypted (void *closure,
const unsigned char *data,
unsigned int length)
{
const unsigned char *in, *end;
uint16_t c, p;
static const char hex_digits[16] = "0123456789abcdef";
char digits[3];
cairo_type1_font_t *font = closure;
in = (const unsigned char *) data;
end = (const unsigned char *) data + length;
while (in < end) {
p = *in++;
c = p ^ (font->eexec_key >> 8);
font->eexec_key = (c + font->eexec_key) * encrypt_c1 + encrypt_c2;
if (font->hex_encode) {
digits[0] = hex_digits[c >> 4];
digits[1] = hex_digits[c & 0x0f];
digits[2] = '\n';
font->hex_column += 2;
if (font->hex_column == 78) {
_cairo_output_stream_write (font->output, digits, 3);
font->hex_column = 0;
} else {
_cairo_output_stream_write (font->output, digits, 2);
}
} else {
digits[0] = c;
_cairo_output_stream_write (font->output, digits, 1);
}
}
return CAIRO_STATUS_SUCCESS;
}
static cairo_int_status_t
cairo_type1_font_write_private_dict (cairo_type1_font_t *font,
const char *name)
{
cairo_int_status_t status;
cairo_output_stream_t *encrypted_output;
font->eexec_key = private_dict_key;
font->hex_encode = TRUE;
font->hex_column = 0;
encrypted_output = _cairo_output_stream_create (
cairo_type1_write_stream_encrypted,
NULL,
font);
if (encrypted_output == NULL)
goto fail;
/* Note: the first four spaces at the start of this private dict
* are the four "random" bytes of plaintext required by the
* encryption algorithm */
_cairo_output_stream_printf (encrypted_output,
" dup /Private 9 dict dup begin\n"
"/RD {string currentfile exch readstring pop}"
" executeonly def\n"
"/ND {noaccess def} executeonly def\n"
"/NP {noaccess put} executeonly def\n"
"/BlueValues [] def\n"
"/MinFeature {16 16} def\n"
"/lenIV 4 def\n"
"/password 5839 def\n");
status = cairo_type1_font_write_charstrings (font, encrypted_output);
if (status)
goto fail;
_cairo_output_stream_printf (encrypted_output,
"end\n"
"end\n"
"readonly put\n"
"noaccess put\n"
"dup /FontName get exch definefont pop\n"
"mark currentfile closefile\n");
if (status == CAIRO_STATUS_SUCCESS)
status = _cairo_output_stream_get_status (encrypted_output);
fail:
_cairo_output_stream_destroy (encrypted_output);
return status;
}
static cairo_status_t
cairo_type1_font_write_trailer(cairo_type1_font_t *font)
{
int i;
static const char zeros[65] =
"0000000000000000000000000000000000000000000000000000000000000000\n";
for (i = 0; i < 8; i++)
_cairo_output_stream_write (font->output, zeros, sizeof zeros);
_cairo_output_stream_printf (font->output, "cleartomark\n");
return CAIRO_STATUS_SUCCESS;
}
static cairo_status_t
cairo_type1_write_stream (void *closure,
const unsigned char *data,
unsigned int length)
{
cairo_type1_font_t *font = closure;
return _cairo_array_append_multiple (&font->contents, data, length);
}
static cairo_int_status_t
cairo_type1_font_write (cairo_type1_font_t *font,
const char *name)
{
cairo_int_status_t status;
cairo_type1_font_write_header (font, name);
font->header_size = _cairo_output_stream_get_position (font->output);
status = cairo_type1_font_write_private_dict (font, name);
if (status)
return status;
font->data_size = _cairo_output_stream_get_position (font->output) -
font->header_size;
cairo_type1_font_write_trailer (font);
font->trailer_size =
_cairo_output_stream_get_position (font->output) -
font->header_size - font->data_size;
return CAIRO_STATUS_SUCCESS;
}
static cairo_int_status_t
cairo_type1_font_generate (cairo_type1_font_t *font, const char *name)
{
cairo_int_status_t status;
status = _cairo_array_grow_by (&font->contents, 4096);
if (status)
return status;
font->output = _cairo_output_stream_create (cairo_type1_write_stream, NULL, font);
status = cairo_type1_font_write (font, name);
if (status)
return status;
font->data = _cairo_array_index (&font->contents, 0);
return CAIRO_STATUS_SUCCESS;
}
static void
cairo_type1_font_destroy (cairo_type1_font_t *font)
{
free (font->widths);
_cairo_array_fini (&font->contents);
cairo_scaled_font_destroy (font->type1_scaled_font);
free (font);
}
cairo_status_t
_cairo_type1_fallback_init (cairo_type1_subset_t *type1_subset,
const char *name,
cairo_scaled_font_subset_t *scaled_font_subset)
{
cairo_type1_font_t *font;
cairo_status_t status;
unsigned long length;
unsigned int i, len;
status = cairo_type1_font_create (scaled_font_subset, &font);
if (status)
return status;
status = cairo_type1_font_generate (font, name);
if (status)
goto fail1;
type1_subset->base_font = strdup (name);
if (type1_subset->base_font == NULL)
goto fail1;
type1_subset->widths = calloc (sizeof (int), font->scaled_font_subset->num_glyphs);
if (type1_subset->widths == NULL)
goto fail2;
for (i = 0; i < font->scaled_font_subset->num_glyphs; i++)
type1_subset->widths[i] = font->widths[i];
type1_subset->x_min = (int) font->x_min;
type1_subset->y_min = (int) font->y_min;
type1_subset->x_max = (int) font->x_max;
type1_subset->y_max = (int) font->y_max;
type1_subset->ascent = (int) font->y_max;
type1_subset->descent = (int) font->y_min;
length = font->header_size + font->data_size +
font->trailer_size;
type1_subset->data = malloc (length);
if (type1_subset->data == NULL)
goto fail3;
memcpy (type1_subset->data,
_cairo_array_index (&font->contents, 0), length);
len = snprintf(type1_subset->data + font->bbox_position,
font->bbox_max_chars,
"%d %d %d %d",
(int)type1_subset->x_min,
(int)type1_subset->y_min,
(int)type1_subset->x_max,
(int)type1_subset->y_max);
type1_subset->data[font->bbox_position + len] = ' ';
type1_subset->header_length = font->header_size;
type1_subset->data_length = font->data_size;
type1_subset->trailer_length = font->trailer_size;
cairo_type1_font_destroy (font);
return CAIRO_STATUS_SUCCESS;
fail3:
free (type1_subset->widths);
fail2:
free (type1_subset->base_font);
fail1:
cairo_type1_font_destroy (font);
return status;
}
void
_cairo_type1_fallback_fini (cairo_type1_subset_t *subset)
{
free (subset->base_font);
free (subset->widths);
free (subset->data);
}

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

@ -53,7 +53,7 @@ typedef struct _cairo_type1_font_subset {
cairo_unscaled_font_t *unscaled_font;
unsigned int font_id;
char *base_font;
int num_glyphs;
unsigned int num_glyphs;
long x_min, y_min, x_max, y_max;
long ascent, descent;
@ -103,7 +103,8 @@ typedef struct _cairo_type1_font_subset {
static cairo_status_t
_cairo_type1_font_subset_create (cairo_unscaled_font_t *unscaled_font,
cairo_type1_font_subset_t **subset_return)
cairo_type1_font_subset_t **subset_return,
cairo_bool_t hex_encode)
{
cairo_ft_unscaled_font_t *ft_unscaled_font;
FT_Face face;
@ -145,6 +146,7 @@ _cairo_type1_font_subset_create (cairo_unscaled_font_t *unscaled_font,
if (font->glyphs == NULL)
goto fail2;
font->hex_encode = hex_encode;
font->num_glyphs = 0;
for (i = 0; i < face->num_glyphs; i++)
font->glyphs[i].subset_index = -1;
@ -185,7 +187,7 @@ static const unsigned short charstring_key = 4330;
static cairo_bool_t
is_ps_delimiter(int c)
{
const static char delimiters[] = "()[]{}<>/% \t\r\n";
static const char delimiters[] = "()[]{}<>/% \t\r\n";
return strchr (delimiters, c) != NULL;
}
@ -252,7 +254,7 @@ cairo_type1_font_subset_write_header (cairo_type1_font_subset_t *font,
const char *name)
{
const char *start, *end, *segment_end;
int i;
unsigned int i;
segment_end = font->header_segment + font->header_segment_size;
@ -399,7 +401,7 @@ static int
cairo_type1_font_subset_lookup_glyph (cairo_type1_font_subset_t *font,
const char *glyph_name, int length)
{
int i;
unsigned int i;
for (i = 0; i < font->base.num_glyphs; i++) {
if (font->glyphs[i].name &&
@ -414,7 +416,7 @@ cairo_type1_font_subset_lookup_glyph (cairo_type1_font_subset_t *font,
static cairo_status_t
cairo_type1_font_subset_get_glyph_names_and_widths (cairo_type1_font_subset_t *font)
{
int i;
unsigned int i;
char buffer[256];
FT_Error error;
@ -481,45 +483,86 @@ cairo_type1_font_subset_decode_integer (const unsigned char *p, int *integer)
}
static const char *ps_standard_encoding[256] = {
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0 */
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 16 */
"space", "exclam", "quotedbl", "numbersign", /* 32 */
"dollar", "percent", "ampersand", "quoteright",
"parenleft", "parenright", "asterisk", "plus",
"comma", "hyphen", "period", "slash",
"zero", "one", "two", "three", /* 48 */
"four", "five", "six", "seven", "eight",
"nine", "colon", "semicolon", "less",
"equal", "greater", "question", "at",
"A", "B", "C", "D", "E", "F", "G", "H", /* 64 */
"I", "J", "K", "L", "M", "N", "O", "P",
"Q", "R", "S", "T", "U", "V", "W", "X", /* 80 */
"Y", "Z", "bracketleft", "backslash",
"bracketright", "asciicircum", "underscore", "quoteleft",
"a", "b", "c", "d", "e", "f", "g", "h", /* 96 */
"i", "j", "k", "l", "m", "n", "o", "p",
"q", "r", "s", "t", "u", "v", "w", "x", /* 112 */
"y", "z", "braceleft", "bar",
"braceright", "asciitilde", 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 128 */
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 144 */
"exclamdown", "cent", "sterling", "fraction",
"yen", "florin", "section", "currency",
"quotesingle", "quotedblleft", "guillemotleft", "guilsinglleft",
"guilsinglright", "fi", "fl", NULL,
"endash", "dagger", "daggerdbl", "periodcentered", /* 160 */
NULL, "paragraph", "bullet", "quotesinglbase",
"quotedblbase", "quotedblright", "guillemotright", "ellipsis",
"perthousand", NULL, "questiondown", NULL,
"grave", "acute", "circumflex", "tilde", /* 176 */
"macron", "breve", "dotaccent", "dieresis",
NULL, "ring", "cedilla", NULL,
"hungarumlaut", "ogonek", "caron", "emdash",
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 192 */
"AE", 0, "ordfeminine", 0, 0, 0, 0, "Lslash", /* 208 */
"Oslash", "OE", "ordmasculine", 0, 0, 0, 0, 0,
"ae", 0, 0, 0, "dotlessi", 0, 0, "lslash", /* 224 */
"oslash", "oe", "germandbls", 0, 0, 0, 0
/* 0 */
NULL, NULL, NULL, NULL,
NULL, NULL, NULL, NULL,
NULL, NULL, NULL, NULL,
NULL, NULL, NULL, NULL,
/* 16 */
NULL, NULL, NULL, NULL,
NULL, NULL, NULL, NULL,
NULL, NULL, NULL, NULL,
NULL, NULL, NULL, NULL,
/* 32 */
"space", "exclam", "quotedbl", "numbersign",
"dollar", "percent", "ampersand", "quoteright",
"parenleft", "parenright", "asterisk", "plus",
"comma", "hyphen", "period", "slash",
/* 48 */
"zero", "one", "two", "three",
"four", "five", "six", "seven",
"eight", "nine", "colon", "semicolon",
"less", "equal", "greater", "question",
/* 64 */
"at", "A", "B", "C",
"D", "E", "F", "G",
"H", "I", "J", "K",
"L", "M", "N", "O",
/* 80 */
"P", "Q", "R", "S",
"T", "U", "V", "W",
"X", "Y", "Z", "bracketleft",
"backslash", "bracketright", "asciicircum", "underscore",
/* 96 */
"quoteleft", "a", "b", "c",
"d", "e", "f", "g",
"h", "i", "j", "k",
"l", "m", "n", "o",
/* 112 */
"p", "q", "r", "s",
"t", "u", "v", "w",
"x", "y", "z", "braceleft",
"bar", "braceright", "asciitilde", NULL,
/* 128 */
NULL, NULL, NULL, NULL,
NULL, NULL, NULL, NULL,
NULL, NULL, NULL, NULL,
NULL, NULL, NULL, NULL,
/* 144 */
NULL, NULL, NULL, NULL,
NULL, NULL, NULL, NULL,
NULL, NULL, NULL, NULL,
NULL, NULL, NULL, NULL,
/* 160 */
NULL, "exclamdown", "cent", "sterling",
"fraction", "yen", "florin", "section",
"currency", "quotesingle", "quotedblleft", "guillemotleft",
"guilsinglleft","guilsinglright","fi", "fl",
/* 176 */
NULL, "endash", "dagger", "daggerdbl",
"periodcentered",NULL, "paragraph", "bullet",
"quotesinglbase","quotedblbase","quotedblright","guillemotright",
"ellipsis", "perthousand", NULL, "questiondown",
/* 192 */
NULL, "grave", "acute", "circumflex",
"tilde", "macron", "breve", "dotaccent",
"dieresis", NULL, "ring", "cedilla",
NULL, "hungarumlaut", "ogonek", "caron",
/* 208 */
"emdash", NULL, NULL, NULL,
NULL, NULL, NULL, NULL,
NULL, NULL, NULL, NULL,
NULL, NULL, NULL, NULL,
/* 224 */
NULL, "AE", NULL, "ordfeminine",
NULL, NULL, NULL, NULL,
"Lslash", "Oslash", "OE", "ordmasculine",
NULL, NULL, NULL, NULL,
/* 240 */
NULL, "ae", NULL, NULL,
NULL, "dotlessi", NULL, NULL,
"lslash", "oslash", "oe", "germandbls",
NULL, NULL, NULL, NULL
};
static void
@ -859,7 +902,6 @@ cairo_type1_font_subset_write (cairo_type1_font_subset_t *font,
}
font->eexec_key = private_dict_key;
font->hex_encode = TRUE;
font->hex_column = 0;
cairo_type1_font_subset_write_private_dict (font, name);
@ -929,7 +971,7 @@ static void
cairo_type1_font_subset_destroy (void *abstract_font)
{
cairo_type1_font_subset_t *font = abstract_font;
int i;
unsigned int i;
/* If the subset generation failed, some of the pointers below may
* be NULL depending on at which point the error occurred. */
@ -953,12 +995,13 @@ cairo_type1_font_subset_destroy (void *abstract_font)
cairo_status_t
_cairo_type1_subset_init (cairo_type1_subset_t *type1_subset,
const char *name,
cairo_scaled_font_subset_t *scaled_font_subset)
cairo_scaled_font_subset_t *scaled_font_subset,
cairo_bool_t hex_encode)
{
cairo_type1_font_subset_t *font;
cairo_status_t status;
unsigned long parent_glyph, length;
int i;
unsigned int i;
cairo_unscaled_font_t *unscaled_font;
/* XXX: Need to fix this to work with a general cairo_unscaled_font_t. */
@ -967,7 +1010,7 @@ _cairo_type1_subset_init (cairo_type1_subset_t *type1_subset,
unscaled_font = _cairo_ft_scaled_font_get_unscaled_font (scaled_font_subset->scaled_font);
status = _cairo_type1_font_subset_create (unscaled_font, &font);
status = _cairo_type1_font_subset_create (unscaled_font, &font, hex_encode);
if (status)
return status;
@ -1038,4 +1081,3 @@ _cairo_type1_subset_fini (cairo_type1_subset_t *subset)
free (subset->widths);
free (subset->data);
}

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

@ -50,6 +50,8 @@
#define TT_PRIM_CSPLINE 3
#endif
#define OPENTYPE_CFF_TAG 0x20464643
const cairo_scaled_font_backend_t cairo_win32_scaled_font_backend;
typedef struct {
@ -97,6 +99,8 @@ typedef struct {
HFONT scaled_hfont;
HFONT unscaled_hfont;
cairo_bool_t glyph_indexing;
cairo_bool_t delete_scaled_hfont;
} cairo_win32_scaled_font_t;
@ -233,6 +237,8 @@ _win32_scaled_font_create (LOGFONTW *logfont,
cairo_matrix_t scale;
cairo_status_t status;
_cairo_win32_initialize ();
f = malloc (sizeof(cairo_win32_scaled_font_t));
if (f == NULL)
return NULL;
@ -464,6 +470,8 @@ _cairo_win32_scaled_font_create_toy (cairo_toy_font_face_t *toy_face,
int face_name_len;
cairo_status_t status;
_cairo_win32_initialize ();
status = _cairo_utf8_to_utf16 (toy_face->family, -1,
&face_name, &face_name_len);
if (status)
@ -720,6 +728,12 @@ _cairo_win32_scaled_font_set_metrics (cairo_win32_scaled_font_t *scaled_font)
}
if ((metrics.tmPitchAndFamily & TMPF_TRUETYPE) ||
(GetFontData (hdc, OPENTYPE_CFF_TAG, 0, NULL, 0) != GDI_ERROR))
scaled_font->glyph_indexing = TRUE;
else
scaled_font->glyph_indexing = FALSE;
_cairo_scaled_font_set_metrics (&scaled_font->base, &extents);
return CAIRO_STATUS_SUCCESS;
@ -734,12 +748,18 @@ _cairo_win32_scaled_font_init_glyph_metrics (cairo_win32_scaled_font_t *scaled_f
cairo_status_t status;
cairo_text_extents_t extents;
HDC hdc;
UINT glyph_index_option;
hdc = _get_global_font_dc ();
if (!hdc)
return CAIRO_STATUS_NO_MEMORY;
if (scaled_font->preserve_axes) {
if (scaled_font->glyph_indexing)
glyph_index_option = GGO_GLYPH_INDEX;
else
glyph_index_option = 0;
if (scaled_font->preserve_axes && scaled_font->base.options.hint_style != CAIRO_HINT_METRICS_OFF) {
/* If we aren't rotating / skewing the axes, then we get the metrics
* from the GDI in device space and convert to font space.
*/
@ -747,7 +767,7 @@ _cairo_win32_scaled_font_init_glyph_metrics (cairo_win32_scaled_font_t *scaled_f
if (status)
return status;
if (GetGlyphOutlineW (hdc, _cairo_scaled_glyph_index (scaled_glyph),
GGO_METRICS | GGO_GLYPH_INDEX,
GGO_METRICS | glyph_index_option,
&metrics, 0, NULL, &matrix) == GDI_ERROR) {
status = _cairo_win32_print_gdi_error ("_cairo_win32_scaled_font_init_glyph_metrics:GetGlyphOutlineW");
memset (&metrics, 0, sizeof (GLYPHMETRICS));
@ -786,7 +806,7 @@ _cairo_win32_scaled_font_init_glyph_metrics (cairo_win32_scaled_font_t *scaled_f
*/
status = _cairo_win32_scaled_font_select_unscaled_font (&scaled_font->base, hdc);
if (GetGlyphOutlineW (hdc, _cairo_scaled_glyph_index (scaled_glyph),
GGO_METRICS | GGO_GLYPH_INDEX,
GGO_METRICS | glyph_index_option,
&metrics, 0, NULL, &matrix) == GDI_ERROR) {
status = _cairo_win32_print_gdi_error ("_cairo_win32_scaled_font_init_glyph_metrics:GetGlyphOutlineW");
memset (&metrics, 0, sizeof (GLYPHMETRICS));
@ -829,6 +849,7 @@ _cairo_win32_scaled_font_glyph_bbox (void *abstract_font,
GLYPHMETRICS metrics;
cairo_status_t status;
int i;
UINT glyph_index_option;
if (!hdc)
return CAIRO_STATUS_NO_MEMORY;
@ -837,11 +858,16 @@ _cairo_win32_scaled_font_glyph_bbox (void *abstract_font,
if (status)
return status;
if (scaled_font->glyph_indexing)
glyph_index_option = GGO_GLYPH_INDEX;
else
glyph_index_option = 0;
for (i = 0; i < num_glyphs; i++) {
int x = floor (0.5 + glyphs[i].x);
int y = floor (0.5 + glyphs[i].y);
GetGlyphOutlineW (hdc, glyphs[i].index, GGO_METRICS | GGO_GLYPH_INDEX,
GetGlyphOutlineW (hdc, glyphs[i].index, GGO_METRICS | glyph_index_option,
&metrics, 0, NULL, &matrix);
if (i == 0 || x1 > x + metrics.gmptGlyphOrigin.x)
@ -897,16 +923,22 @@ _flush_glyphs (cairo_glyph_state_t *state)
int dx = 0;
WCHAR * elements;
int * dx_elements;
UINT glyph_index_option;
status = _cairo_array_append (&state->dx, &dx);
if (status)
return status;
if (state->scaled_font->glyph_indexing)
glyph_index_option = ETO_GLYPH_INDEX;
else
glyph_index_option = 0;
elements = _cairo_array_index (&state->glyphs, 0);
dx_elements = _cairo_array_index (&state->dx, 0);
if (!ExtTextOutW (state->hdc,
state->start_x, state->last_y,
ETO_GLYPH_INDEX,
glyph_index_option,
NULL,
elements,
state->glyphs.num_elements,
@ -1079,7 +1111,7 @@ _compute_a8_mask (cairo_win32_surface_t *mask_surface)
return &image8->base;
}
static cairo_status_t
static cairo_int_status_t
_cairo_win32_scaled_font_glyph_init (void *abstract_font,
cairo_scaled_glyph_t *scaled_glyph,
cairo_scaled_glyph_info_t info)
@ -1220,10 +1252,45 @@ _cairo_win32_scaled_font_show_glyphs (void *abstract_font,
}
}
static cairo_fixed_t
_cairo_fixed_from_FIXED (FIXED f)
static cairo_int_status_t
_cairo_win32_scaled_font_load_truetype_table (void *abstract_font,
unsigned long tag,
long offset,
unsigned char *buffer,
unsigned long *length)
{
return *((cairo_fixed_t *)&f);
HDC hdc;
cairo_status_t status = CAIRO_STATUS_SUCCESS;
cairo_win32_scaled_font_t *scaled_font = abstract_font;
hdc = _get_global_font_dc ();
if (!hdc)
return CAIRO_STATUS_NO_MEMORY;
tag = (tag&0x000000ff)<<24 | (tag&0x0000ff00)<<8 | (tag&0x00ff0000)>>8 | (tag&0xff000000)>>24;
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_unscaled_font (&scaled_font->base);
return status;
}
static void
_cairo_win32_transform_FIXED_to_fixed (cairo_matrix_t *matrix,
FIXED Fx, FIXED Fy,
cairo_fixed_t *fx, cairo_fixed_t *fy)
{
double x, y;
x = _cairo_fixed_to_double (*((cairo_fixed_t *)&Fx));
y = _cairo_fixed_to_double (*((cairo_fixed_t *)&Fy));
cairo_matrix_transform_point (matrix, &x, &y);
*fx = _cairo_fixed_from_double (x);
*fy = _cairo_fixed_from_double (y);
}
static cairo_status_t
@ -1237,6 +1304,9 @@ _cairo_win32_scaled_font_init_glyph_path (cairo_win32_scaled_font_t *scaled_font
DWORD bytesGlyph;
unsigned char *buffer, *ptr;
cairo_path_fixed_t *path;
cairo_matrix_t transform;
cairo_fixed_t x, y;
UINT glyph_index_option;
hdc = _get_global_font_dc ();
if (!hdc)
@ -1246,12 +1316,24 @@ _cairo_win32_scaled_font_init_glyph_path (cairo_win32_scaled_font_t *scaled_font
if (!path)
return CAIRO_STATUS_NO_MEMORY;
status = cairo_win32_scaled_font_select_font (&scaled_font->base, hdc);
if (scaled_font->base.options.hint_style == CAIRO_HINT_STYLE_NONE) {
status = _cairo_win32_scaled_font_select_unscaled_font (&scaled_font->base, hdc);
transform = scaled_font->base.scale;
cairo_matrix_scale (&transform, 1.0/scaled_font->em_square, 1.0/scaled_font->em_square);
} else {
status = cairo_win32_scaled_font_select_font (&scaled_font->base, hdc);
cairo_matrix_init_identity(&transform);
}
if (status)
goto CLEANUP_PATH;
if (scaled_font->glyph_indexing)
glyph_index_option = GGO_GLYPH_INDEX;
else
glyph_index_option = 0;
bytesGlyph = GetGlyphOutlineW (hdc, _cairo_scaled_glyph_index (scaled_glyph),
GGO_NATIVE | GGO_GLYPH_INDEX,
GGO_NATIVE | glyph_index_option,
&metrics, 0, NULL, &matrix);
if (bytesGlyph == GDI_ERROR) {
@ -1267,7 +1349,7 @@ _cairo_win32_scaled_font_init_glyph_path (cairo_win32_scaled_font_t *scaled_font
}
if (GetGlyphOutlineW (hdc, _cairo_scaled_glyph_index (scaled_glyph),
GGO_NATIVE | GGO_GLYPH_INDEX,
GGO_NATIVE | glyph_index_option,
&metrics, bytesGlyph, buffer, &matrix) == GDI_ERROR) {
status = _cairo_win32_print_gdi_error ("_cairo_win32_scaled_font_glyph_path");
free (buffer);
@ -1280,9 +1362,11 @@ _cairo_win32_scaled_font_init_glyph_path (cairo_win32_scaled_font_t *scaled_font
ptr += sizeof (TTPOLYGONHEADER);
_cairo_path_fixed_move_to (path,
_cairo_fixed_from_FIXED (header->pfxStart.x),
_cairo_fixed_from_FIXED (header->pfxStart.y));
_cairo_win32_transform_FIXED_to_fixed (&transform,
header->pfxStart.x,
header->pfxStart.y,
&x, &y);
_cairo_path_fixed_move_to (path, x, y);
while (ptr < endPoly) {
TTPOLYCURVE *curve = (TTPOLYCURVE *)ptr;
@ -1291,26 +1375,36 @@ _cairo_win32_scaled_font_init_glyph_path (cairo_win32_scaled_font_t *scaled_font
switch (curve->wType) {
case TT_PRIM_LINE:
for (i = 0; i < curve->cpfx; i++) {
_cairo_path_fixed_line_to (path,
_cairo_fixed_from_FIXED (points[i].x),
_cairo_fixed_from_FIXED (points[i].y));
_cairo_win32_transform_FIXED_to_fixed (&transform,
points[i].x,
points[i].y,
&x, &y);
_cairo_path_fixed_line_to (path, x, y);
}
break;
case TT_PRIM_QSPLINE:
for (i = 0; i < curve->cpfx - 1; i++) {
cairo_fixed_t p1x, p1y, p2x, p2y, cx, cy, c1x, c1y, c2x, c2y;
_cairo_path_fixed_get_current_point (path, &p1x, &p1y);
cx = _cairo_fixed_from_FIXED (points[i].x);
cy = _cairo_fixed_from_FIXED (points[i].y);
_cairo_win32_transform_FIXED_to_fixed (&transform,
points[i].x,
points[i].y,
&cx, &cy);
if (i + 1 == curve->cpfx - 1) {
p2x = _cairo_fixed_from_FIXED (points[i + 1].x);
p2y = _cairo_fixed_from_FIXED (points[i + 1].y);
_cairo_win32_transform_FIXED_to_fixed (&transform,
points[i + 1].x,
points[i + 1].y,
&p2x, &p2y);
} else {
/* records with more than one curve use interpolation for
control points, per http://support.microsoft.com/kb/q87115/ */
p2x = (cx + _cairo_fixed_from_FIXED (points[i + 1].x)) / 2;
p2y = (cy + _cairo_fixed_from_FIXED (points[i + 1].y)) / 2;
_cairo_win32_transform_FIXED_to_fixed (&transform,
points[i + 1].x,
points[i + 1].y,
&x, &y);
p2x = (cx + x) / 2;
p2y = (cy + y) / 2;
}
c1x = 2 * cx / 3 + p1x / 3;
@ -1323,13 +1417,20 @@ _cairo_win32_scaled_font_init_glyph_path (cairo_win32_scaled_font_t *scaled_font
break;
case TT_PRIM_CSPLINE:
for (i = 0; i < curve->cpfx - 2; i += 2) {
_cairo_path_fixed_curve_to (path,
_cairo_fixed_from_FIXED (points[i].x),
_cairo_fixed_from_FIXED (points[i].y),
_cairo_fixed_from_FIXED (points[i + 1].x),
_cairo_fixed_from_FIXED (points[i + 1].y),
_cairo_fixed_from_FIXED (points[i + 2].x),
_cairo_fixed_from_FIXED (points[i + 2].y));
cairo_fixed_t x1, y1, x2, y2;
_cairo_win32_transform_FIXED_to_fixed (&transform,
points[i].x,
points[i].y,
&x, &y);
_cairo_win32_transform_FIXED_to_fixed (&transform,
points[i + 1].x,
points[i + 1].y,
&x1, &y1);
_cairo_win32_transform_FIXED_to_fixed (&transform,
points[i + 2].x,
points[i + 2].y,
&x2, &y2);
_cairo_path_fixed_curve_to (path, x, y, x1, y1, x2, y2);
}
break;
}
@ -1363,6 +1464,7 @@ const cairo_scaled_font_backend_t cairo_win32_scaled_font_backend = {
_cairo_win32_scaled_font_text_to_glyphs,
NULL, /* ucs4_to_index */
_cairo_win32_scaled_font_show_glyphs,
_cairo_win32_scaled_font_load_truetype_table,
};
/* cairo_win32_font_face_t */
@ -1391,6 +1493,8 @@ _cairo_win32_font_face_scaled_font_create (void *abstract_face,
{
cairo_win32_font_face_t *font_face = abstract_face;
_cairo_win32_initialize ();
*font = _win32_scaled_font_create (&font_face->logfont,
font_face->hfont,
&font_face->base,
@ -1428,6 +1532,8 @@ cairo_win32_font_face_create_for_logfontw (LOGFONTW *logfont)
{
cairo_win32_font_face_t *font_face;
_cairo_win32_initialize ();
font_face = malloc (sizeof (cairo_win32_font_face_t));
if (!font_face) {
_cairo_error (CAIRO_STATUS_NO_MEMORY);
@ -1461,6 +1567,8 @@ cairo_win32_font_face_create_for_hfont (HFONT font)
{
cairo_win32_font_face_t *font_face;
_cairo_win32_initialize ();
font_face = malloc (sizeof (cairo_win32_font_face_t));
if (!font_face) {
_cairo_error (CAIRO_STATUS_NO_MEMORY);
@ -1563,9 +1671,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_get_type (scaled_font) != CAIRO_FONT_TYPE_WIN32)
return 1.0;
return 1. / ((cairo_win32_scaled_font_t *)scaled_font)->logical_scale;
}
@ -1574,9 +1679,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_get_type (scaled_font) != CAIRO_FONT_TYPE_WIN32)
return;
*logical_to_device = win_font->logical_to_device;
}
@ -1585,8 +1687,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_get_type (scaled_font) != CAIRO_FONT_TYPE_WIN32)
return;
*device_to_logical = win_font->device_to_logical;
}

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

@ -102,4 +102,7 @@ _cairo_win32_print_gdi_error (const char *context);
cairo_bool_t
_cairo_surface_is_win32 (cairo_surface_t *surface);
void
_cairo_win32_initialize ();
#endif /* CAIRO_WIN32_PRIVATE_H */

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

@ -1,4 +1,4 @@
/* -*- Mode: c; c-basic-offset: 4; indent-tabs-mode: t; tab-width: 8; -*- */
/* -*- Mode: c; tab-width: 8; c-basic-offset: 4; indent-tabs-mode: t; -*- */
/* Cairo - a vector graphics library with display and print output
*
* Copyright © 2005 Red Hat, Inc.
@ -49,6 +49,9 @@
#define SB_NONE 0x00000000
#endif
#define PELS_72DPI (72. / 0.0254)
#define NIL_SURFACE ((cairo_surface_t*)&_cairo_surface_nil)
static const cairo_surface_backend_t cairo_win32_surface_backend;
/**
@ -104,7 +107,7 @@ _cairo_win32_flags_for_dc (HDC dc)
*/
flags |= CAIRO_WIN32_SURFACE_CAN_BITBLT;
flags |= CAIRO_WIN32_SURFACE_CAN_ALPHABLEND;
/*flags |= CAIRO_WIN32_SURFACE_CAN_STRETCHBLT;*/
flags |= CAIRO_WIN32_SURFACE_CAN_STRETCHBLT;
} else {
int cap;
@ -115,10 +118,8 @@ _cairo_win32_flags_for_dc (HDC dc)
cap = GetDeviceCaps(dc, RASTERCAPS);
if (cap & RC_BITBLT)
flags |= CAIRO_WIN32_SURFACE_CAN_BITBLT;
/*
if (cap & RC_STRETCHBLT)
flags |= CAIRO_WIN32_SURFACE_CAN_STRETCHBLT;
*/
}
return flags;
@ -176,8 +177,8 @@ _create_dc_and_bitmap (cairo_win32_surface_t *surface,
bitmap_info->bmiHeader.biWidth = width == 0 ? 1 : width;
bitmap_info->bmiHeader.biHeight = height == 0 ? -1 : - height; /* top-down */
bitmap_info->bmiHeader.biSizeImage = 0;
bitmap_info->bmiHeader.biXPelsPerMeter = 72. / 0.0254; /* unused here */
bitmap_info->bmiHeader.biYPelsPerMeter = 72. / 0.0254; /* unused here */
bitmap_info->bmiHeader.biXPelsPerMeter = PELS_72DPI; /* unused here */
bitmap_info->bmiHeader.biYPelsPerMeter = PELS_72DPI; /* unused here */
bitmap_info->bmiHeader.biPlanes = 1;
switch (format) {
@ -185,6 +186,8 @@ _create_dc_and_bitmap (cairo_win32_surface_t *surface,
* break if we do, especially if we don't set up an image
* fallback. It could be a bug with using a 24bpp pixman image
* (and creating one with masks). So treat them like 32bpp.
* NOTE: This causes problems when using BitBlt/AlphaBlend/etc!
* see end of file.
*/
case CAIRO_FORMAT_RGB24:
case CAIRO_FORMAT_ARGB32:
@ -308,10 +311,12 @@ _cairo_win32_surface_create_for_dc (HDC original_dc,
char *bits;
int rowstride;
_cairo_win32_initialize ();
surface = malloc (sizeof (cairo_win32_surface_t));
if (surface == NULL) {
_cairo_error (CAIRO_STATUS_NO_MEMORY);
return &_cairo_surface_nil;
return NIL_SURFACE;
}
status = _create_dc_and_bitmap (surface, original_dc, format,
@ -358,10 +363,10 @@ _cairo_win32_surface_create_for_dc (HDC original_dc,
if (status == CAIRO_STATUS_NO_MEMORY) {
_cairo_error (CAIRO_STATUS_NO_MEMORY);
return &_cairo_surface_nil;
return NIL_SURFACE;
} else {
_cairo_error (status);
return &_cairo_surface_nil;
return NIL_SURFACE;
}
}
@ -441,7 +446,7 @@ _cairo_win32_surface_get_subimage (cairo_win32_surface_t *surface,
cairo_win32_surface_t **local_out)
{
cairo_win32_surface_t *local;
cairo_status_t status;
cairo_int_status_t status;
cairo_content_t content = _cairo_content_from_format (surface->format);
local =
@ -450,13 +455,22 @@ _cairo_win32_surface_get_subimage (cairo_win32_surface_t *surface,
if (local->base.status)
return CAIRO_STATUS_NO_MEMORY;
if (!BitBlt (local->dc,
0, 0,
width, height,
surface->dc,
x, y,
SRCCOPY)) {
/* If we fail to BitBlt here, most likely the source is a printer.
status = CAIRO_INT_STATUS_UNSUPPORTED;
if ((local->flags & CAIRO_WIN32_SURFACE_CAN_BITBLT) &&
BitBlt (local->dc,
0, 0,
width, height,
surface->dc,
x, y,
SRCCOPY))
{
status = CAIRO_STATUS_SUCCESS;
}
if (status) {
/* If we failed here, most likely the source or dest doesn't
* support BitBlt/AlphaBlend (e.g. a printer).
* You can't reliably get bits from a printer DC, so just fill in
* the surface as white (common case for printing).
*/
@ -471,14 +485,6 @@ _cairo_win32_surface_get_subimage (cairo_win32_surface_t *surface,
*local_out = local;
return CAIRO_STATUS_SUCCESS;
FAIL:
status = _cairo_win32_print_gdi_error ("_cairo_win32_surface_get_subimage");
if (local)
cairo_surface_destroy (&local->base);
return status;
}
static cairo_status_t
@ -690,10 +696,21 @@ _composite_alpha_blend (cairo_win32_surface_t *dst,
if (!(dst->flags & CAIRO_WIN32_SURFACE_CAN_ALPHABLEND))
return CAIRO_INT_STATUS_UNSUPPORTED;
if (src->format == CAIRO_FORMAT_RGB24 && dst->format == CAIRO_FORMAT_ARGB32)
{
/* Both of these are represented as 32bpp internally, and AlphaBlend
* DOES NOT throw away source alpha is AC_SRC_ALPHA is not specified,
* it just multiplies it by the SourceConstantAlpha, along with the
* R G B components.
* XXX there has to be a way to do this!
*/
return CAIRO_INT_STATUS_UNSUPPORTED;
}
blend_function.BlendOp = AC_SRC_OVER;
blend_function.BlendFlags = 0;
blend_function.SourceConstantAlpha = alpha;
blend_function.AlphaFormat = src->format == CAIRO_FORMAT_ARGB32 ? AC_SRC_ALPHA : 0;
blend_function.AlphaFormat = (src->format == CAIRO_FORMAT_ARGB32) ? AC_SRC_ALPHA : 0;
/*oldstretchmode = SetStretchBltMode(dst->dc, HALFTONE);*/
if (!alpha_blend (dst->dc,
@ -730,11 +747,19 @@ _cairo_win32_surface_composite (cairo_operator_t op,
int itx, ity;
double scalex, scaley;
cairo_fixed_t x0_fixed, y0_fixed;
int orig_dst_x = dst_x, orig_dst_y = dst_y;
int real_src_width, real_src_height;
int src_width, src_height;
int dst_width, dst_height;
cairo_bool_t needs_alpha, needs_scale;
cairo_image_surface_t *src_image = NULL;
#if 0
fprintf (stderr, "composite: %d %p %p %p [%d %d] [%d %d] [%d %d] %dx%d\n",
op, pattern, mask_pattern, abstract_dst, src_x, src_y, mask_x, mask_y, dst_x, dst_y, width, height);
#endif
/* If the destination can't do any of these, then
* we may as well give up, since this is what we'll
@ -769,8 +794,20 @@ _cairo_win32_surface_composite (cairo_operator_t op,
src_surface_pattern = (cairo_surface_pattern_t *)pattern;
src = (cairo_win32_surface_t *)src_surface_pattern->surface;
if (src->base.backend != dst->base.backend)
/* Disable this StretchDIBits optimization for now */
#if 0
if (src->base.type == CAIRO_SURFACE_TYPE_IMAGE) {
src_image = (cairo_image_surface_t*) src;
if (src_image->format != CAIRO_FORMAT_RGB24 ||
alpha != 255 ||
src_image->stride != (src_image->width * 4))
return CAIRO_INT_STATUS_UNSUPPORTED;
} else
#endif
if (src->base.backend != dst->base.backend) {
return CAIRO_INT_STATUS_UNSUPPORTED;
}
#if 0
fprintf (stderr, "Before check: (%d %d) [%d %d] -> [%d %d %d %d] {mat %f %f %f %f}\n",
@ -793,7 +830,7 @@ _cairo_win32_surface_composite (cairo_operator_t op,
{
return CAIRO_INT_STATUS_UNSUPPORTED;
}
itx = _cairo_fixed_integer_part(x0_fixed);
ity = _cairo_fixed_integer_part(y0_fixed);
@ -803,105 +840,67 @@ _cairo_win32_surface_composite (cairo_operator_t op,
src_x += itx;
src_y += ity;
#if 0
if (scalex != 1.0 || scaley != 1.0) {
/* we already know that the destination is an integer rectangle;
* we need to see if the source is also.
*/
cairo_fixed_t sx0 = _cairo_fixed_from_double(src_x * scalex);
cairo_fixed_t sy0 = _cairo_fixed_from_double(src_y * scaley);
cairo_fixed_t sw = _cairo_fixed_from_double((src->extents.width - src_x) * scalex);
cairo_fixed_t sh = _cairo_fixed_from_double((src->extents.height - src_y) * scaley);
fprintf (stderr, "sx0 sy0 sw sh: %f %f %f %f\n",
_cairo_fixed_to_double(sx0), _cairo_fixed_to_double(sy0),
_cairo_fixed_to_double(sw), _cairo_fixed_to_double(sh));
if (!_cairo_fixed_is_integer(sw) ||
!_cairo_fixed_is_integer(sh) ||
!_cairo_fixed_is_integer(sx0) ||
!_cairo_fixed_is_integer(sy0))
{
return CAIRO_INT_STATUS_UNSUPPORTED;
}
}
#endif
if (scalex <= 0.0 || scaley <= 0.0)
return CAIRO_STATUS_SUCCESS;
#if 0
fprintf (stderr, "Before fixup: (%d %d) src: [%d %d] -> dst: [%d %d %d %d] itsc {%d %d %f %f}\n",
src->extents.width, src->extents.height,
src_x, src_y,
dst_x, dst_y, width, height,
itx, ity, scalex, scaley);
#endif
if (scalex != 1.0 || scaley != 1.0)
return CAIRO_INT_STATUS_UNSUPPORTED;
/* Fix up src coordinates; the src coords and size must be within the
* bounds of the source surface.
* XXX the region not covered should be appropriately rendered!
* - for OVER/SOURCE with RGB24 source -> opaque black
* - for SOURCE with ARGB32 source -> 100% transparent black
/* If the src coordinates are outside of the source surface bounds,
* we have to fix them up, because this is an error for the GDI
* functions.
* XXX Make sure to correctly clear out the unpainted region.
*/
src_x *= scalex;
src_y *= scaley;
if (src_x < 0) {
width += src_x / scalex;
dst_x -= src_x / scalex;
width += src_x;
dst_x -= src_x;
src_x = 0;
}
if (src_y < 0) {
height += src_y / scaley;
dst_y -= src_y / scaley;
height += src_y;
dst_y -= src_y;
src_y = 0;
}
if (src_x + width > (src->extents.width / scalex))
dst_width = (src->extents.width / scalex) - src_x;
if (src_x + width > src->extents.width)
dst_width = src->extents.width - src_x;
else
dst_width = width;
if (src_y + height > (src->extents.height / scaley))
dst_height = (src->extents.height / scaley) - src_y;
if (src_y + height > src->extents.height)
dst_height = src->extents.height - src_y;
else
dst_height = height;
/* If we're scaling up an iamge, we may have
* less than 1 pixel's worth of width/height map
* into 1 row in the destination. If this is the case,
* we need to clip to the destination's width/height,
* and then figure out the next source/dest width/height combo
* where there is an integer match.
*
* For now, just let cairo scale that case. THIS IS NOT IDEAL,
* as the scaling algorithms aren't identical!
src_width = dst_width;
src_height = dst_height;
/*
* Figure out what action to take.
* XXX handle SOURCE with alpha != 255
*/
if (!_cairo_fixed_is_integer(_cairo_fixed_from_double(dst_width * scalex)) ||
!_cairo_fixed_is_integer(_cairo_fixed_from_double(dst_height * scaley)))
return CAIRO_INT_STATUS_UNSUPPORTED;
src_width = dst_width * scalex;
src_height = dst_height * scaley;
if (alpha == 255 &&
(op == CAIRO_OPERATOR_SOURCE ||
(src->format == CAIRO_FORMAT_RGB24 && op == CAIRO_OPERATOR_OVER)))
(dst->format == src->format) &&
((op == CAIRO_OPERATOR_SOURCE && (dst->format == CAIRO_FORMAT_ARGB32 ||
dst->format == CAIRO_FORMAT_RGB24)) ||
(op == CAIRO_OPERATOR_OVER && dst->format == CAIRO_FORMAT_RGB24)))
{
needs_alpha = FALSE;
} else if ((src->format == CAIRO_FORMAT_RGB24 || src->format == CAIRO_FORMAT_ARGB32) &&
(dst->format == CAIRO_FORMAT_RGB24 || dst->format == CAIRO_FORMAT_ARGB32) &&
op == CAIRO_OPERATOR_OVER)
} else if ((op == CAIRO_OPERATOR_OVER || op == CAIRO_OPERATOR_SOURCE) &&
(src->format == CAIRO_FORMAT_RGB24 || src->format == CAIRO_FORMAT_ARGB32) &&
(dst->format == CAIRO_FORMAT_RGB24 || dst->format == CAIRO_FORMAT_ARGB32))
{
needs_alpha = TRUE;
} else {
return CAIRO_INT_STATUS_UNSUPPORTED;
}
if (scalex == 1.0 && scaley == 1.0) {
needs_scale = FALSE;
} else {
/* Should never be reached until we turn StretchBlt back on */
needs_scale = TRUE;
}
@ -912,8 +911,32 @@ _cairo_win32_surface_composite (cairo_operator_t op,
fflush (stderr);
#endif
/* Then do BitBlt, StretchBlt, AlphaBlend, or MaskBlt */
if (!needs_alpha) {
/* Then do BitBlt, StretchDIBits, StretchBlt, AlphaBlend, or MaskBlt */
if (src_image) {
BITMAPINFO bi;
bi.bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
bi.bmiHeader.biWidth = src_image->width;
bi.bmiHeader.biHeight = src_image->height;
bi.bmiHeader.biSizeImage = 0;
bi.bmiHeader.biXPelsPerMeter = PELS_72DPI;
bi.bmiHeader.biYPelsPerMeter = PELS_72DPI;
bi.bmiHeader.biPlanes = 1;
bi.bmiHeader.biBitCount = 32;
bi.bmiHeader.biCompression = BI_RGB;
bi.bmiHeader.biClrUsed = 0;
bi.bmiHeader.biClrImportant = 0;
if (!StretchDIBits (dst->dc,
dst_x, dst_y, dst_width, dst_height,
src_x, src_y, src_width, src_height,
src_image->data,
&bi,
DIB_RGB_COLORS,
SRCCOPY))
return _cairo_win32_print_gdi_error ("_cairo_win32_surface_composite(StretchDIBits)");
return CAIRO_STATUS_SUCCESS;
} else if (!needs_alpha) {
/* BitBlt or StretchBlt? */
if (!needs_scale && (dst->flags & CAIRO_WIN32_SURFACE_CAN_BITBLT)) {
if (!BitBlt (dst->dc,
@ -922,15 +945,14 @@ _cairo_win32_surface_composite (cairo_operator_t op,
src->dc,
src_x, src_y,
SRCCOPY))
return _cairo_win32_print_gdi_error ("_cairo_win32_surface_composite");
return _cairo_win32_print_gdi_error ("_cairo_win32_surface_composite(BitBlt)");
return CAIRO_STATUS_SUCCESS;
} else if (dst->flags & CAIRO_WIN32_SURFACE_CAN_STRETCHBLT) {
/* StretchBlt? */
/* XXX check if we want HALFTONE, based on the src filter */
int oldmode = SetStretchBltMode(dst->dc, HALFTONE);
BOOL success;
int oldmode = SetStretchBltMode(dst->dc, HALFTONE);
success = StretchBlt(dst->dc,
dst_x, dst_y,
dst_width, dst_height,
@ -944,11 +966,11 @@ _cairo_win32_surface_composite (cairo_operator_t op,
_cairo_win32_print_gdi_error ("StretchBlt");
return CAIRO_INT_STATUS_UNSUPPORTED;
}
return CAIRO_STATUS_SUCCESS;
}
} else if (needs_alpha && !needs_scale) {
return _composite_alpha_blend (dst, src, alpha,
return _composite_alpha_blend (dst, src, alpha,
src_x, src_y, src_width, src_height,
dst_x, dst_y, dst_width, dst_height);
}
@ -1348,13 +1370,15 @@ cairo_win32_surface_create (HDC hdc)
int depth;
cairo_format_t format;
_cairo_win32_initialize ();
/* Try to figure out the drawing bounds for the Device context
*/
if (GetClipBox (hdc, &rect) == ERROR) {
_cairo_win32_print_gdi_error ("cairo_win32_surface_create");
/* XXX: Can we make a more reasonable guess at the error cause here? */
_cairo_error (CAIRO_STATUS_NO_MEMORY);
return &_cairo_surface_nil;
return NIL_SURFACE;
}
if (GetDeviceCaps(hdc, TECHNOLOGY) == DT_RASDISPLAY) {
@ -1372,7 +1396,7 @@ cairo_win32_surface_create (HDC hdc)
else {
_cairo_win32_print_gdi_error("cairo_win32_surface_create(bad BITSPIXEL)");
_cairo_error (CAIRO_STATUS_NO_MEMORY);
return &_cairo_surface_nil;
return NIL_SURFACE;
}
} else {
format = CAIRO_FORMAT_RGB24;
@ -1381,7 +1405,7 @@ cairo_win32_surface_create (HDC hdc)
surface = malloc (sizeof (cairo_win32_surface_t));
if (surface == NULL) {
_cairo_error (CAIRO_STATUS_NO_MEMORY);
return &_cairo_surface_nil;
return NIL_SURFACE;
}
surface->image = NULL;
@ -1398,15 +1422,15 @@ cairo_win32_surface_create (HDC hdc)
surface->clip_rect.height = rect.bottom - rect.top;
if (surface->clip_rect.width == 0 ||
surface->clip_rect.height == 0)
surface->clip_rect.height == 0)
{
surface->saved_clip = NULL;
surface->saved_clip = NULL;
} else {
surface->saved_clip = CreateRectRgn (0, 0, 0, 0);
if (GetClipRgn (hdc, surface->saved_clip) == 0) {
DeleteObject(surface->saved_clip);
surface->saved_clip = NULL;
}
surface->saved_clip = CreateRectRgn (0, 0, 0, 0);
if (GetClipRgn (hdc, surface->saved_clip) == 0) {
DeleteObject(surface->saved_clip);
surface->saved_clip = NULL;
}
}
surface->extents = surface->clip_rect;
@ -1435,17 +1459,31 @@ cairo_win32_surface_create (HDC hdc)
**/
cairo_surface_t *
cairo_win32_surface_create_with_dib (cairo_format_t format,
int width,
int height)
int width,
int height)
{
return _cairo_win32_surface_create_for_dc (NULL, format, width, height);
}
/**
* cairo_win32_surface_create_with_ddb:
* @format: format of pixels in the surface to create
* @width: width of the surface, in pixels
* @height: height of the surface, in pixels
*
* Creates a device-independent-bitmap surface not associated with
* any particular existing surface or device context. The created
* bitmap will be unititialized.
*
* Return value: the newly created surface
*
* Since: 1.4
**/
cairo_surface_t *
cairo_win32_surface_create_with_ddb (HDC hdc,
cairo_format_t format,
int width,
int height)
cairo_format_t format,
int width,
int height)
{
cairo_win32_surface_t *new_surf;
HBITMAP ddb;
@ -1536,8 +1574,10 @@ cairo_win32_surface_get_dc (cairo_surface_t *surface)
* as the DIB of the Win32 surface. If the passed-in win32 surface
* is not a DIB surface, NULL is returned.
*
* Return value: a #cairo_surface_t (reference owned by the win32 cairo_surface_t),
* Return value: a #cairo_surface_t (owned by the win32 cairo_surface_t),
* or NULL if the win32 surface is not a DIB.
*
* Since: 1.4
*/
cairo_surface_t *
cairo_win32_surface_get_image (cairo_surface_t *surface)
@ -1581,18 +1621,34 @@ static const cairo_surface_backend_t cairo_win32_surface_backend = {
NULL /* snapshot */
};
#if 0
/*
* Without pthread, on win32 we need to initialize all the 'mutex'es
* before use. It is guaranteed that DllMain will get called single
* threaded before any other function.
* Initializing more than finally needed should not matter much.
*/
#ifndef HAVE_PTHREAD_H
#if !defined(HAVE_PTHREAD_H)
CRITICAL_SECTION cairo_toy_font_face_hash_table_mutex;
CRITICAL_SECTION cairo_scaled_font_map_mutex;
CRITICAL_SECTION cairo_ft_unscaled_font_map_mutex;
static int _cairo_win32_initialized = 0;
void
_cairo_win32_initialize () {
if (_cairo_win32_initialized)
return;
/* every 'mutex' from CAIRO_MUTEX_DECALRE needs to be initialized here */
InitializeCriticalSection (&cairo_toy_font_face_hash_table_mutex);
InitializeCriticalSection (&cairo_scaled_font_map_mutex);
InitializeCriticalSection (&cairo_ft_unscaled_font_map_mutex);
_cairo_win32_initialized = 1;
}
#if !defined(CAIRO_WIN32_STATIC_BUILD)
BOOL WINAPI
DllMain (HINSTANCE hinstDLL,
DWORD fdwReason,
@ -1601,10 +1657,7 @@ DllMain (HINSTANCE hinstDLL,
switch (fdwReason)
{
case DLL_PROCESS_ATTACH:
/* every 'mutex' from CAIRO_MUTEX_DECALRE needs to be initialized here */
InitializeCriticalSection (&cairo_toy_font_face_hash_table_mutex);
InitializeCriticalSection (&cairo_scaled_font_map_mutex);
InitializeCriticalSection (&cairo_ft_unscaled_font_map_mutex);
_cairo_win32_initialize();
break;
case DLL_PROCESS_DETACH:
DeleteCriticalSection (&cairo_toy_font_face_hash_table_mutex);
@ -1616,3 +1669,17 @@ DllMain (HINSTANCE hinstDLL,
}
#endif
#endif
/* Notes:
*
* Win32 alpha-understanding functions
*
* BitBlt - will copy full 32 bits from a 32bpp DIB to result
* (so it's safe to use for ARGB32->ARGB32 SOURCE blits)
* (but not safe going RGB24->ARGB32, if RGB24 is also represented
* as a 32bpp DIB, since the alpha isn't discarded!)
*
* AlphaBlend - if both the source and dest have alpha, even if AC_SRC_ALPHA isn't set,
* it will still copy over the src alpha, because the SCA value (255) will be
* multiplied by all the src components.
*/

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

@ -37,35 +37,10 @@
#include "cairoint.h"
#include "cairo-xcb.h"
#include "cairo-xcb-xrender.h"
#include <X11/XCB/xcb_renderutil.h>
#define AllPlanes ((unsigned long)~0L)
static XCBRenderPICTFORMAT
format_from_visual(XCBConnection *c, XCBVISUALID visual)
{
static const XCBRenderPICTFORMAT nil = { 0 };
XCBRenderQueryPictFormatsRep *r;
XCBRenderPICTSCREENIter si;
XCBRenderPICTDEPTHIter di;
XCBRenderPICTVISUALIter vi;
r = XCBRenderQueryPictFormatsReply(c, XCBRenderQueryPictFormats(c), 0);
if(!r)
return nil;
for(si = XCBRenderQueryPictFormatsScreensIter(r); si.rem; XCBRenderPICTSCREENNext(&si))
for(di = XCBRenderPICTSCREENDepthsIter(si.data); di.rem; XCBRenderPICTDEPTHNext(&di))
for(vi = XCBRenderPICTDEPTHVisualsIter(di.data); vi.rem; XCBRenderPICTVISUALNext(&vi))
if(vi.data->visual.id == visual.id)
{
XCBRenderPICTFORMAT ret = vi.data->format;
free(r);
return ret;
}
return nil;
}
static cairo_content_t
_xcb_render_format_to_content (XCBRenderPICTFORMINFO *xrender_format)
{
@ -92,95 +67,6 @@ _xcb_render_format_to_content (XCBRenderPICTFORMINFO *xrender_format)
}
/* XXX: Why is this ridiculously complex compared to the equivalent
* function in cairo-xlib-surface.c */
static XCBRenderPICTFORMINFO
_format_from_cairo(XCBConnection *c, cairo_format_t fmt)
{
XCBRenderPICTFORMINFO ret = {{ 0 }};
struct tmpl_t {
XCBRenderDIRECTFORMAT direct;
CARD8 depth;
};
static const struct tmpl_t templates[] = {
/* CAIRO_FORMAT_ARGB32 */
{
{
16, 0xff,
8, 0xff,
0, 0xff,
24, 0xff
},
32
},
/* CAIRO_FORMAT_RGB24 */
{
{
16, 0xff,
8, 0xff,
0, 0xff,
0, 0x00
},
24
},
/* CAIRO_FORMAT_A8 */
{
{
0, 0x00,
0, 0x00,
0, 0x00,
0, 0xff
},
8
},
/* CAIRO_FORMAT_A1 */
{
{
0, 0x00,
0, 0x00,
0, 0x00,
0, 0x01
},
1
},
};
const struct tmpl_t *tmpl;
XCBRenderQueryPictFormatsRep *r;
XCBRenderPICTFORMINFOIter fi;
if(fmt < 0 || fmt >= (sizeof(templates) / sizeof(*templates)))
return ret;
tmpl = templates + fmt;
r = XCBRenderQueryPictFormatsReply(c, XCBRenderQueryPictFormats(c), 0);
if(!r)
return ret;
for(fi = XCBRenderQueryPictFormatsFormatsIter(r); fi.rem; XCBRenderPICTFORMINFONext(&fi))
{
const XCBRenderDIRECTFORMAT *t, *f;
if(fi.data->type != XCBRenderPictTypeDirect)
continue;
if(fi.data->depth != tmpl->depth)
continue;
t = &tmpl->direct;
f = &fi.data->direct;
if(t->red_mask && (t->red_mask != f->red_mask || t->red_shift != f->red_shift))
continue;
if(t->green_mask && (t->green_mask != f->green_mask || t->green_shift != f->green_shift))
continue;
if(t->blue_mask && (t->blue_mask != f->blue_mask || t->blue_shift != f->blue_shift))
continue;
if(t->alpha_mask && (t->alpha_mask != f->alpha_mask || t->alpha_shift != f->alpha_shift))
continue;
ret = *fi.data;
}
free(r);
return ret;
}
/*
* Instead of taking two round trips for each blending request,
* assume that if a particular drawable fails GetImage that it will
@ -209,6 +95,9 @@ typedef struct cairo_xcb_surface {
int height;
int depth;
XCBRECTANGLE *clip_rects;
int num_clip_rects;
XCBRenderPICTURE picture;
XCBRenderPICTFORMINFO format;
int has_format;
@ -265,7 +154,7 @@ _cairo_xcb_surface_create_similar (void *abstract_src,
XCBDRAWABLE d;
cairo_xcb_surface_t *surface;
cairo_format_t format = _cairo_format_from_content (content);
XCBRenderPICTFORMINFO xrender_format = _format_from_cairo (dpy, format);
XCBRenderPICTFORMINFO *xrender_format;
/* As a good first approximation, if the display doesn't have COMPOSITE,
* we're better off using image surfaces for all temporary operations
@ -280,9 +169,11 @@ _cairo_xcb_surface_create_similar (void *abstract_src,
width <= 0 ? 1 : width,
height <= 0 ? 1 : height);
xrender_format = XCBRenderUtilFindStandardFormat (XCBRenderUtilQueryFormats (dpy), format);
/* XXX: what to do if xrender_format is null? */
surface = (cairo_xcb_surface_t *)
cairo_xcb_surface_create_with_xrender_format (dpy, d, src->screen,
&xrender_format,
xrender_format,
width, height);
if (surface->base.status) {
_cairo_error (CAIRO_STATUS_NO_MEMORY);
@ -307,6 +198,8 @@ _cairo_xcb_surface_finish (void *abstract_surface)
if (surface->gc.xid)
XCBFreeGC (surface->dpy, surface->gc);
free (surface->clip_rects);
surface->dpy = NULL;
return CAIRO_STATUS_SUCCESS;
@ -565,6 +458,26 @@ _get_image_surface (cairo_xcb_surface_t *surface,
return CAIRO_STATUS_NO_MEMORY;
}
static void
_cairo_xcb_surface_set_picture_clip_rects (cairo_xcb_surface_t *surface)
{
if (surface->num_clip_rects)
XCBRenderSetPictureClipRectangles (surface->dpy, surface->picture,
0, 0,
surface->num_clip_rects,
surface->clip_rects);
}
static void
_cairo_xcb_surface_set_gc_clip_rects (cairo_xcb_surface_t *surface)
{
if (surface->num_clip_rects)
XCBSetClipRectangles(surface->dpy, XCBClipOrderingYXSorted, surface->gc,
0, 0,
surface->num_clip_rects,
surface->clip_rects );
}
static void
_cairo_xcb_surface_ensure_gc (cairo_xcb_surface_t *surface)
{
@ -573,6 +486,7 @@ _cairo_xcb_surface_ensure_gc (cairo_xcb_surface_t *surface)
surface->gc = XCBGCONTEXTNew(surface->dpy);
XCBCreateGC (surface->dpy, surface->gc, surface->drawable, 0, 0);
_cairo_xcb_surface_set_gc_clip_rects(surface);
}
static cairo_status_t
@ -1000,7 +914,8 @@ _cairo_xcb_surface_composite_trapezoids (cairo_operator_t op,
cairo_int_status_t status;
int render_reference_x, render_reference_y;
int render_src_x, render_src_y;
XCBRenderPICTFORMINFO render_format;
int cairo_format;
XCBRenderPICTFORMINFO *render_format;
if (!CAIRO_SURFACE_RENDER_HAS_TRAPEZOIDS (dst))
return CAIRO_INT_STATUS_UNSUPPORTED;
@ -1025,30 +940,94 @@ _cairo_xcb_surface_composite_trapezoids (cairo_operator_t op,
switch (antialias) {
case CAIRO_ANTIALIAS_NONE:
render_format = _format_from_cairo (dst->dpy, CAIRO_FORMAT_A1);
cairo_format = CAIRO_FORMAT_A1;
break;
default:
render_format = _format_from_cairo (dst->dpy, CAIRO_FORMAT_A8);
cairo_format = CAIRO_FORMAT_A8;
break;
}
render_format = XCBRenderUtilFindStandardFormat (XCBRenderUtilQueryFormats (dst->dpy), cairo_format);
/* XXX: what to do if render_format is null? */
/* XXX: The XTrapezoid cast is evil and needs to go away somehow. */
/* XXX: _format_from_cairo is slow. should cache something. */
status = _cairo_xcb_surface_set_attributes (src, &attributes);
if (status == CAIRO_STATUS_SUCCESS)
XCBRenderTrapezoids (dst->dpy,
_render_operator (op),
src->picture, dst->picture,
render_format.id,
render_format->id,
render_src_x + attributes.x_offset,
render_src_y + attributes.y_offset,
num_traps, (XCBRenderTRAP *) traps);
num_traps, (XCBRenderTRAPEZOID *) traps);
_cairo_pattern_release_surface (pattern, &src->base, &attributes);
return status;
}
static cairo_int_status_t
_cairo_xcb_surface_set_clip_region (void *abstract_surface,
pixman_region16_t *region)
{
cairo_xcb_surface_t *surface = abstract_surface;
if (surface->clip_rects) {
free (surface->clip_rects);
surface->clip_rects = NULL;
}
surface->num_clip_rects = 0;
if (region == NULL) {
if (surface->gc.xid) {
CARD32 mask = XCBGCClipMask;
CARD32 pa[] = { XCBNone };
XCBChangeGC (surface->dpy, surface->gc, mask, pa);
}
if (surface->has_format && surface->picture.xid) {
CARD32 mask = XCBRenderCPClipMask;
CARD32 pa[] = { XCBNone };
XCBRenderChangePicture (surface->dpy, surface->picture, mask, pa);
}
} else {
pixman_box16_t *boxes;
XCBRECTANGLE *rects = NULL;
int n_boxes, i;
n_boxes = pixman_region_num_rects (region);
if (n_boxes > 0) {
rects = malloc (sizeof(XCBRECTANGLE) * n_boxes);
if (rects == NULL)
return CAIRO_STATUS_NO_MEMORY;
} else {
rects = NULL;
}
boxes = pixman_region_rects (region);
for (i = 0; i < n_boxes; i++) {
rects[i].x = boxes[i].x1;
rects[i].y = boxes[i].y1;
rects[i].width = boxes[i].x2 - boxes[i].x1;
rects[i].height = boxes[i].y2 - boxes[i].y1;
}
surface->clip_rects = rects;
surface->num_clip_rects = n_boxes;
if (surface->gc.xid)
_cairo_xcb_surface_set_gc_clip_rects (surface);
if (surface->picture.xid)
_cairo_xcb_surface_set_picture_clip_rects (surface);
}
return CAIRO_STATUS_SUCCESS;
}
static cairo_int_status_t
_cairo_xcb_surface_get_extents (void *abstract_surface,
cairo_rectangle_int16_t *rectangle)
@ -1078,7 +1057,7 @@ static const cairo_surface_backend_t cairo_xcb_surface_backend = {
_cairo_xcb_surface_composite_trapezoids,
NULL, /* copy_page */
NULL, /* show_page */
NULL, /* _cairo_xcb_surface_set_clip_region */
_cairo_xcb_surface_set_clip_region,
NULL, /* intersect_clip_path */
_cairo_xcb_surface_get_extents,
NULL, /* old_show_glyphs */
@ -1103,26 +1082,6 @@ _cairo_surface_is_xcb (cairo_surface_t *surface)
return surface->backend == &cairo_xcb_surface_backend;
}
static void
query_render_version (XCBConnection *c, cairo_xcb_surface_t *surface)
{
XCBRenderQueryVersionRep *r;
surface->render_major = -1;
surface->render_minor = -1;
if (!XCBRenderInit(c))
return;
r = XCBRenderQueryVersionReply(c, XCBRenderQueryVersion(c, 0, 6), 0);
if (!r)
return;
surface->render_major = r->major_version;
surface->render_minor = r->minor_version;
free(r);
}
static cairo_surface_t *
_cairo_xcb_surface_create_internal (XCBConnection *dpy,
XCBDRAWABLE drawable,
@ -1134,6 +1093,7 @@ _cairo_xcb_surface_create_internal (XCBConnection *dpy,
int depth)
{
cairo_xcb_surface_t *surface;
const XCBRenderQueryVersionRep *r;
surface = malloc (sizeof (cairo_xcb_surface_t));
if (surface == NULL) {
@ -1163,6 +1123,9 @@ _cairo_xcb_surface_create_internal (XCBConnection *dpy,
surface->height = height;
surface->depth = depth;
surface->clip_rects = NULL;
surface->num_clip_rects = 0;
if (format) {
surface->depth = format->depth;
} else if (visual) {
@ -1189,30 +1152,40 @@ _cairo_xcb_surface_create_internal (XCBConnection *dpy,
;
}
query_render_version(dpy, surface);
surface->render_major = -1;
surface->render_minor = -1;
r = XCBRenderUtilQueryVersion(dpy);
if (r) {
surface->render_major = r->major_version;
surface->render_minor = r->minor_version;
}
surface->picture.xid = 0;
if (CAIRO_SURFACE_RENDER_HAS_CREATE_PICTURE (surface))
{
XCBRenderPICTFORMAT pict_format = {0};
XCBRenderPICTFORMINFO format_info;
static const XCBRenderPICTFORMAT nil = { 0 };
const XCBRenderPICTFORMAT *pict_format = &nil;
surface->picture = XCBRenderPICTURENew(dpy);
if (!format) {
if (visual) {
pict_format = format_from_visual (dpy, visual->visual_id);
} else if (depth == 1) {
format_info = _format_from_cairo (dpy, CAIRO_FORMAT_A1);
pict_format = format_info.id;
}
XCBRenderCreatePicture (dpy, surface->picture, drawable,
pict_format, 0, NULL);
} else {
XCBRenderCreatePicture (dpy, surface->picture, drawable,
format->id, 0, NULL);
if (format) {
pict_format = &format->id;
} else if (visual) {
XCBRenderPICTVISUAL *pict_visual;
pict_visual = XCBRenderUtilFindVisualFormat (XCBRenderUtilQueryFormats (dpy), visual->visual_id);
if (pict_visual)
pict_format = &pict_visual->format;
} else if (depth == 1) {
XCBRenderPICTFORMINFO *format_info;
format_info = XCBRenderUtilFindStandardFormat (XCBRenderUtilQueryFormats (dpy), CAIRO_FORMAT_A1);
if (format_info)
pict_format = &format_info->id;
}
/* XXX: if pict_format is nil, should we still call CreatePicture? */
surface->picture = XCBRenderPICTURENew(dpy);
XCBRenderCreatePicture (dpy, surface->picture, drawable,
*pict_format, 0, NULL);
}
return (cairo_surface_t *) surface;

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

@ -51,4 +51,10 @@ struct _cairo_xlib_screen_info {
cairo_private cairo_xlib_screen_info_t *
_cairo_xlib_screen_info_get (Display *display, Screen *screen);
#if CAIRO_HAS_XLIB_XRENDER_SURFACE
#include "cairo-xlib-xrender.h"
#endif
#endif /* CAIRO_XLIB_PRIVATE_H */

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

@ -219,10 +219,11 @@ _cairo_xlib_surface_create_similar_with_format (void *abstract_src,
/* As a good first approximation, if the display doesn't have even
* the most elementary RENDER operation, then we're better off
* using image surfaces for all temporary operations
* using image surfaces for all temporary operations, so return NULL
* and let the fallback code happen.
*/
if (!CAIRO_SURFACE_RENDER_HAS_COMPOSITE(src)) {
return cairo_image_surface_create (format, width, height);
return NULL;
}
pix = XCreatePixmap (dpy, RootWindowOfScreen (src->screen),
@ -747,7 +748,7 @@ _draw_image_surface (cairo_xlib_surface_t *surface,
int dst_y)
{
XImage ximage;
int bpp, alpha, red, green, blue;
unsigned int bpp, alpha, red, green, blue;
int native_byte_order = _native_byte_order_lsb () ? LSBFirst : MSBFirst;
pixman_format_get_masks (pixman_image_get_format (image->pixman_image),
@ -874,6 +875,9 @@ _cairo_xlib_surface_clone_similar (void *abstract_surface,
} else if (_cairo_surface_is_image (src)) {
cairo_image_surface_t *image_src = (cairo_image_surface_t *)src;
if (! CAIRO_FORMAT_VALID (image_src->format))
return CAIRO_INT_STATUS_UNSUPPORTED;
clone = (cairo_xlib_surface_t *)
_cairo_xlib_surface_create_similar_with_format (surface, image_src->format,
image_src->width, image_src->height);
@ -934,7 +938,7 @@ static cairo_status_t
_cairo_xlib_surface_set_filter (cairo_xlib_surface_t *surface,
cairo_filter_t filter)
{
char *render_filter;
const char *render_filter;
if (!surface->src_picture)
return CAIRO_STATUS_SUCCESS;
@ -963,13 +967,19 @@ _cairo_xlib_surface_set_filter (cairo_xlib_surface_t *surface,
case CAIRO_FILTER_BILINEAR:
render_filter = FilterBilinear;
break;
case CAIRO_FILTER_GAUSSIAN:
/* XXX: The GAUSSIAN value has no implementation in cairo
* whatsoever, so it was really a mistake to have it in the
* API. We could fix this by officially deprecating it, or
* else inventing semantics and providing an actual
* implementation for it. */
default:
render_filter = FilterBest;
break;
}
XRenderSetPictureFilter (surface->dpy, surface->src_picture,
render_filter, NULL, 0);
(char *) render_filter, NULL, 0);
return CAIRO_STATUS_SUCCESS;
}
@ -1372,6 +1382,7 @@ _cairo_xlib_surface_composite (cairo_operator_t op,
dst_x, dst_y, width, height);
break;
case DO_UNSUPPORTED:
default:
ASSERT_NOT_REACHED;
}
@ -1561,6 +1572,9 @@ _cairo_xlib_surface_composite_trapezoids (cairo_operator_t op,
case CAIRO_ANTIALIAS_NONE:
pict_format = XRenderFindStandardFormat (dst->dpy, PictStandardA1);
break;
case CAIRO_ANTIALIAS_GRAY:
case CAIRO_ANTIALIAS_SUBPIXEL:
case CAIRO_ANTIALIAS_DEFAULT:
default:
pict_format = XRenderFindStandardFormat (dst->dpy, PictStandardA8);
break;
@ -2423,7 +2437,7 @@ _cairo_xlib_surface_add_glyph (Display *dpy,
break;
case CAIRO_FORMAT_ARGB32:
if (_native_byte_order_lsb() != (ImageByteOrder (dpy) == LSBFirst)) {
int c = glyph_surface->stride * glyph_surface->height;
unsigned int c = glyph_surface->stride * glyph_surface->height;
unsigned char *d;
unsigned char *new, *n;
@ -2434,7 +2448,7 @@ _cairo_xlib_surface_add_glyph (Display *dpy,
}
n = new;
d = data;
while ((c -= 4) >= 0)
while (c >= 4)
{
n[3] = d[0];
n[2] = d[1];
@ -2442,6 +2456,7 @@ _cairo_xlib_surface_add_glyph (Display *dpy,
n[0] = d[3];
d += 4;
n += 4;
c -= 4;
}
data = new;
}
@ -2674,12 +2689,13 @@ _cairo_xlib_surface_show_glyphs (void *abstract_dst,
cairo_surface_attributes_t attributes;
cairo_xlib_surface_t *src = NULL;
cairo_glyph_t *output_glyphs;
const cairo_glyph_t *glyphs_chunk;
int glyphs_remaining, chunk_size, max_chunk_size;
cairo_scaled_glyph_t *scaled_glyph;
cairo_xlib_surface_font_private_t *font_private;
int i;
int i, o;
unsigned long max_index = 0;
cairo_xlib_surface_show_glyphs_func_t show_glyphs_func;
@ -2723,6 +2739,13 @@ _cairo_xlib_surface_show_glyphs (void *abstract_dst,
(font_private != NULL && font_private->dpy != dst->dpy))
return CAIRO_INT_STATUS_UNSUPPORTED;
/* We make a copy of the glyphs so that we can elide any size-zero
* glyphs to workaround an X server bug, (present in at least Xorg
* 7.1 without EXA). */
output_glyphs = malloc (num_glyphs * sizeof (cairo_glyph_t));
if (output_glyphs == NULL)
return CAIRO_STATUS_NO_MEMORY;
/* After passing all those tests, we're now committed to rendering
* these glyphs or to fail trying. We first upload any glyphs to
* the X server that it doesn't have already, then we draw
@ -2781,7 +2804,7 @@ _cairo_xlib_surface_show_glyphs (void *abstract_dst,
goto BAIL;
/* Send all unsent glyphs to the server, and count the max of the glyph indices */
for (i = 0; i < num_glyphs; i++) {
for (i = 0, o = 0; i < num_glyphs; i++) {
if (glyphs[i].index > max_index)
max_index = glyphs[i].index;
status = _cairo_scaled_glyph_lookup (scaled_font,
@ -2790,11 +2813,18 @@ _cairo_xlib_surface_show_glyphs (void *abstract_dst,
&scaled_glyph);
if (status != CAIRO_STATUS_SUCCESS)
goto BAIL;
if (scaled_glyph->surface_private == NULL) {
_cairo_xlib_surface_add_glyph (dst->dpy, scaled_font, scaled_glyph);
scaled_glyph->surface_private = (void *) 1;
/* Don't put any size-zero glyphs into output_glyphs to avoid
* an X server bug which stops rendering glyphs after the
* first size-zero glyph. */
if (scaled_glyph->surface->width && scaled_glyph->surface->height) {
output_glyphs[o++] = glyphs[i];
if (scaled_glyph->surface_private == NULL) {
_cairo_xlib_surface_add_glyph (dst->dpy, scaled_font, scaled_glyph);
scaled_glyph->surface_private = (void *) 1;
}
}
}
num_glyphs = o;
_cairo_xlib_surface_ensure_dst_picture (dst);
@ -2811,7 +2841,7 @@ _cairo_xlib_surface_show_glyphs (void *abstract_dst,
}
max_chunk_size /= sz_xGlyphElt;
for (glyphs_remaining = num_glyphs, glyphs_chunk = glyphs;
for (glyphs_remaining = num_glyphs, glyphs_chunk = output_glyphs;
glyphs_remaining;
glyphs_remaining -= chunk_size, glyphs_chunk += chunk_size)
{
@ -2826,6 +2856,7 @@ _cairo_xlib_surface_show_glyphs (void *abstract_dst,
BAIL:
_cairo_scaled_font_thaw_cache (scaled_font);
free (output_glyphs);
if (src)
_cairo_pattern_release_surface (src_pattern, &src->base, &attributes);

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

@ -1,3 +1,4 @@
/* -*- Mode: c; c-basic-offset: 4; indent-tabs-mode: t; tab-width: 8; -*- */
/* cairo - a vector graphics library with display and print output
*
* Copyright © 2002 University of Southern California
@ -44,7 +45,7 @@
#define CAIRO_TOLERANCE_MINIMUM 0.0002 /* We're limited by 16 bits of sub-pixel precision */
static const cairo_t cairo_nil = {
(unsigned int)-1, /* ref_count */
CAIRO_REF_COUNT_INVALID, /* ref_count */
CAIRO_STATUS_NO_MEMORY, /* status */
{ /* path */
NULL, NULL, /* op_buf_head, op_buf_tail */
@ -62,7 +63,7 @@ static const cairo_t cairo_nil = {
* a bit of a pain, but it should be easy to always catch as long as
* one adds a new test case to test a trigger of the new status value.
*/
#define CAIRO_STATUS_LAST_STATUS CAIRO_STATUS_INVALID_DSC_COMMENT
#define CAIRO_STATUS_LAST_STATUS CAIRO_STATUS_INVALID_INDEX
/**
* _cairo_error:
@ -206,6 +207,7 @@ cairo_create (cairo_surface_t *target)
return cr;
}
slim_hidden_def (cairo_create);
/**
* cairo_reference:
@ -223,7 +225,7 @@ cairo_reference (cairo_t *cr)
if (cr == NULL)
return NULL;
if (cr->ref_count == (unsigned int)-1)
if (cr->ref_count == CAIRO_REF_COUNT_INVALID)
return cr;
assert (cr->ref_count > 0);
@ -247,7 +249,7 @@ cairo_destroy (cairo_t *cr)
if (cr == NULL)
return;
if (cr->ref_count == (unsigned int)-1)
if (cr->ref_count == CAIRO_REF_COUNT_INVALID)
return;
assert (cr->ref_count > 0);
@ -267,6 +269,7 @@ cairo_destroy (cairo_t *cr)
free (cr);
}
slim_hidden_def (cairo_destroy);
/**
* cairo_save:
@ -571,6 +574,7 @@ cairo_set_operator (cairo_t *cr, cairo_operator_t op)
if (cr->status)
_cairo_set_error (cr, cr->status);
}
slim_hidden_def (cairo_set_operator);
/**
* cairo_set_source_rgb
@ -674,6 +678,7 @@ cairo_set_source_surface (cairo_t *cr,
cairo_set_source (cr, pattern);
cairo_pattern_destroy (pattern);
}
slim_hidden_def (cairo_set_source_surface);
/**
* cairo_set_source
@ -714,6 +719,7 @@ cairo_set_source (cairo_t *cr, cairo_pattern_t *source)
if (cr->status)
_cairo_set_error (cr, cr->status);
}
slim_hidden_def (cairo_set_source);
/**
* cairo_get_source:
@ -928,10 +934,10 @@ cairo_set_line_join (cairo_t *cr, cairo_line_join_t line_join)
* #CAIRO_STATUS_INVALID_DASH.
**/
void
cairo_set_dash (cairo_t *cr,
double *dashes,
int num_dashes,
double offset)
cairo_set_dash (cairo_t *cr,
const double *dashes,
int num_dashes,
double offset)
{
if (cr->status)
return;
@ -942,6 +948,64 @@ cairo_set_dash (cairo_t *cr,
_cairo_set_error (cr, cr->status);
}
/**
* cairo_get_dash_count:
* @cr: a #cairo_t
* @count: return value for the number of dash values, or %NULL
*
* Gets the length of the dash array in @cr.
*
* Return value: %CAIRO_STATUS_SUCCESS, or error status set on
* @cr.
*
* Since: 1.4
*/
cairo_status_t
cairo_get_dash_count (cairo_t *cr,
int *count)
{
if (cr->status)
return cr->status;
if (count)
*count = cr->gstate->stroke_style.num_dashes;
return CAIRO_STATUS_SUCCESS;
}
/**
* cairo_get_dash:
* @cr: a #cairo_t
* @dashes: return value for the dash array, or %NULL
* @offset: return value for the current dash offset, or %NULL
*
* Gets the current dash array. If not %NULL, @dashes should be big
* enough to hold at least the number of values returned by
* cairo_get_dash_count().
*
* Return value: %CAIRO_STATUS_SUCCESS, or error status set on
* @cr.
*
* Since: 1.4
**/
cairo_status_t
cairo_get_dash (cairo_t *cr,
double *dashes,
double *offset)
{
if (cr->status)
return cr->status;
memcpy (dashes,
cr->gstate->stroke_style.dash,
sizeof(double) * cr->gstate->stroke_style.num_dashes);
if (offset)
*offset = cr->gstate->stroke_style.dash_offset;
return CAIRO_STATUS_SUCCESS;
}
void
cairo_set_miter_limit (cairo_t *cr, double limit)
{
@ -1268,6 +1332,7 @@ cairo_line_to (cairo_t *cr, double x, double y)
if (cr->status)
_cairo_set_error (cr, cr->status);
}
slim_hidden_def (cairo_line_to);
/**
* cairo_curve_to:
@ -1321,6 +1386,7 @@ cairo_curve_to (cairo_t *cr,
if (cr->status)
_cairo_set_error (cr, cr->status);
}
slim_hidden_def (cairo_curve_to);
/**
* cairo_arc:
@ -1645,6 +1711,14 @@ cairo_stroke_to_path (cairo_t *cr)
*
* If there is no current point before the call to cairo_close_path,
* this function will have no effect.
*
* Note: As of cairo version 1.2.4 any call to cairo_close_path will
* place an explicit MOVE_TO element into the path immediately after
* the CLOSE_PATH element, (which can be seen in cairo_copy_path() for
* example). This can simplify path processing in some cases as it may
* not be necessary to save the "last move_to point" during processing
* as the MOVE_TO immediately after the CLOSE_PATH will provide that
* point.
**/
void
cairo_close_path (cairo_t *cr)
@ -1675,6 +1749,7 @@ cairo_paint (cairo_t *cr)
if (cr->status)
_cairo_set_error (cr, cr->status);
}
slim_hidden_def (cairo_paint);
/**
* cairo_paint_with_alpha:
@ -1722,7 +1797,7 @@ cairo_paint_with_alpha (cairo_t *cr,
*
* A drawing operator that paints the current source
* using the alpha channel of @pattern as a mask. (Opaque
* areas of @mask are painted with the source, transparent
* areas of @pattern are painted with the source, transparent
* areas are not painted.)
*/
void
@ -1746,6 +1821,7 @@ cairo_mask (cairo_t *cr,
if (cr->status)
_cairo_set_error (cr, cr->status);
}
slim_hidden_def (cairo_mask);
/**
* cairo_mask_surface:
@ -1887,6 +1963,15 @@ cairo_fill_preserve (cairo_t *cr)
}
slim_hidden_def(cairo_fill_preserve);
/**
* cairo_copy_page:
* @cr: a cairo context
*
* Emits the current page for backends that support multiple pages, but
* doesn't clear it, so, the contents of the current page will be retained
* for the next page too. Use cairo_show_page() if you want to get an
* empty page after the emission.
**/
void
cairo_copy_page (cairo_t *cr)
{
@ -1898,6 +1983,13 @@ cairo_copy_page (cairo_t *cr)
_cairo_set_error (cr, cr->status);
}
/**
* cairo_show_page:
* @cr: a cairo context
*
* Emits and clears the current page for backends that support multiple
* pages. Use cairo_copy_page() if you don't want to clear the page.
**/
void
cairo_show_page (cairo_t *cr)
{
@ -1909,6 +2001,20 @@ cairo_show_page (cairo_t *cr)
_cairo_set_error (cr, cr->status);
}
/**
* cairo_in_stroke:
* @cr: a cairo context
* @x: X coordinate of the point to test
* @y: Y coordinate of the point to test
*
* Tests whether the given point is on the area stroked by doing a
* cairo_stroke() operation on @cr given the current path and stroking
* parameters.
*
* See cairo_stroke, cairo_set_line_width(), cairo_set_line_join(),
* cairo_set_line_cap(), cairo_set_dash(), and
* cairo_stroke_preserve().
**/
cairo_bool_t
cairo_in_stroke (cairo_t *cr, double x, double y)
{
@ -1926,6 +2032,18 @@ cairo_in_stroke (cairo_t *cr, double x, double y)
return inside;
}
/**
* cairo_in_fill:
* @cr: a cairo context
* @x: X coordinate of the point to test
* @y: Y coordinate of the point to test
*
* Tests whether the given point is on the area filled by doing a
* cairo_stroke() operation on @cr given the current path and filling
* parameters.
*
* See cairo_fill(), cairo_set_fill_rule() and cairo_fill_preserve().
**/
cairo_bool_t
cairo_in_fill (cairo_t *cr, double x, double y)
{
@ -1945,6 +2063,19 @@ cairo_in_fill (cairo_t *cr, double x, double y)
return inside;
}
/**
* cairo_stroke_extents:
* @cr: a cairo context
* @x1: left of the resulting extents
* @y1: top of the resulting extents
* @x2: right of the resulting extents
* @y2: bottom of the resulting extents
*
* Computes a bounding box in user coordinates covering all area that will
* be stroked by the current path with the current stroking parameters. If
* the current path is empty, returns an empty rectangle. Surface dimensions
* and clipping are not taken into account.
**/
void
cairo_stroke_extents (cairo_t *cr,
double *x1, double *y1, double *x2, double *y2)
@ -1959,6 +2090,19 @@ cairo_stroke_extents (cairo_t *cr,
_cairo_set_error (cr, cr->status);
}
/**
* cairo_fill_extents:
* @cr: a cairo context
* @x1: left of the resulting extents
* @y1: top of the resulting extents
* @x2: right of the resulting extents
* @y2: bottom of the resulting extents
*
* Computes a bounding box in user coordinates covering all area that will
* be filled by the current path. If the current path is empty, returns an
* empty rectangle. Surface dimensions and clipping are not taken into
* account.
**/
void
cairo_fill_extents (cairo_t *cr,
double *x1, double *y1, double *x2, double *y2)
@ -2064,6 +2208,67 @@ cairo_reset_clip (cairo_t *cr)
_cairo_set_error (cr, cr->status);
}
/**
* cairo_clip_extents:
* @cr: a cairo context
* @x1: left of the resulting extents
* @y1: top of the resulting extents
* @x2: right of the resulting extents
* @y2: bottom of the resulting extents
*
* Computes a bounding box in user coordinates covering the area inside the
* current clip.
**/
void
cairo_clip_extents (cairo_t *cr,
double *x1, double *y1,
double *x2, double *y2)
{
if (cr->status)
return;
cr->status = _cairo_gstate_clip_extents (cr->gstate, x1, y1, x2, y2);
if (cr->status)
_cairo_set_error (cr, cr->status);
}
static cairo_rectangle_list_t *
_cairo_rectangle_list_create_for_status (cairo_status_t status)
{
cairo_rectangle_list_t *list;
list = malloc (sizeof (cairo_rectangle_list_t));
if (list == NULL)
return (cairo_rectangle_list_t*) &_cairo_rectangles_nil;
list->status = status;
list->rectangles = NULL;
list->num_rectangles = 0;
return list;
}
/**
* cairo_copy_clip_rectangles:
*
* Returns the current clip region as a list of rectangles in user coordinates.
* Never returns %NULL.
*
* The status in the list may be CAIRO_STATUS_CLIP_NOT_REPRESENTABLE to
* indicate that the clip region cannot be represented as a list of
* user-space rectangles. The status may have other values to indicate
* other errors.
*
* The caller must always call cairo_rectangle_list_destroy on the result of
* this function.
**/
cairo_rectangle_list_t *
cairo_copy_clip_rectangles (cairo_t *cr)
{
if (cr->status)
return _cairo_rectangle_list_create_for_status (cr->status);
return _cairo_gstate_copy_clip_rectangles (cr->gstate);
}
/**
* cairo_select_font_face:
* @cr: a #cairo_t
@ -2478,7 +2683,7 @@ cairo_show_text (cairo_t *cr, const char *utf8)
}
void
cairo_show_glyphs (cairo_t *cr, cairo_glyph_t *glyphs, int num_glyphs)
cairo_show_glyphs (cairo_t *cr, const cairo_glyph_t *glyphs, int num_glyphs)
{
if (cr->status)
return;
@ -2564,6 +2769,7 @@ cairo_get_tolerance (cairo_t *cr)
{
return _cairo_gstate_get_tolerance (cr->gstate);
}
slim_hidden_def (cairo_get_tolerance);
/**
* cairo_get_antialias:
@ -2707,6 +2913,7 @@ cairo_get_matrix (cairo_t *cr, cairo_matrix_t *matrix)
{
_cairo_gstate_get_matrix (cr->gstate, matrix);
}
slim_hidden_def (cairo_get_matrix);
/**
* cairo_get_target:
@ -2862,7 +3069,8 @@ cairo_append_path (cairo_t *cr,
}
if (path->status) {
if (path->status <= CAIRO_STATUS_LAST_STATUS)
if (path->status > CAIRO_STATUS_SUCCESS &&
path->status <= CAIRO_STATUS_LAST_STATUS)
_cairo_set_error (cr, path->status);
else
_cairo_set_error (cr, CAIRO_STATUS_INVALID_STATUS);
@ -2892,6 +3100,7 @@ cairo_status (cairo_t *cr)
{
return cr->status;
}
slim_hidden_def (cairo_status);
/**
* cairo_status_to_string:
@ -2947,6 +3156,10 @@ cairo_status_to_string (cairo_status_t status)
return "invalid value for a dash setting";
case CAIRO_STATUS_INVALID_DSC_COMMENT:
return "invalid value for a DSC comment";
case CAIRO_STATUS_INVALID_INDEX:
return "invalid index passed to getter";
case CAIRO_STATUS_CLIP_NOT_REPRESENTABLE:
return "clip region not representable in desired format";
}
return "<unknown error status>";
@ -2960,42 +3173,3 @@ _cairo_restrict_value (double *value, double min, double max)
else if (*value > max)
*value = max;
}
/**
* cairo_has_clip
* @cr: a cairo context
*
* Returns TRUE if the cairo context has any clipping active, otherwise
* FALSE.
*/
cairo_bool_t
cairo_has_clip (cairo_t *cr)
{
if (cr->status)
return FALSE;
return _cairo_gstate_has_clip (cr->gstate);
}
/**
* cairo_extract_clip_rectangles
* @cr: a cairo context
* @max_rectangles: the maximum number of rectangles to be returned
* @rectangles_out: the output buffer for the rectangles
* @num_rectangles_out: the number of rectangles returned
*
* If the current clip can be expressed as the union of at most
* 'max_rectangles' device-coordinate rectangles, then we fill in the array
* with the rectangles, and return True. Otherwise we return False. When there
* is no clipping active, we return False.
*/
cairo_bool_t
cairo_extract_clip_rectangles (cairo_t *cr,
int max_rectangles,
cairo_clip_rect_t *rectangles_out,
int *num_rectangles_out)
{
if (cr->status)
return FALSE;
return _cairo_gstate_extract_clip_rectangles (cr->gstate, max_rectangles,
rectangles_out, num_rectangles_out);
}

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

@ -39,6 +39,7 @@
#define CAIRO_H
#include <cairo-features.h>
#include <cairo-deprecated.h>
CAIRO_BEGIN_DECLS
@ -168,12 +169,16 @@ typedef struct _cairo_user_data_key {
* @CAIRO_STATUS_FILE_NOT_FOUND: file not found
* @CAIRO_STATUS_INVALID_DASH: invalid value for a dash setting
* @CAIRO_STATUS_INVALID_DSC_COMMENT: invalid value for a DSC comment (Since 1.2)
* @CAIRO_STATUS_INVALID_INDEX: invalid index value for a getter (Since 1.3+)
* @CAIRO_STATUS_INVALID_INDEX: invalid index passed to getter
* @CAIRO_STATUS_CLIP_NOT_REPRESENTABLE: clip region not representable in desired format (Since 1.4)
*
* #cairo_status_t is used to indicate errors that can occur when
* using Cairo. In some cases it is returned directly by functions.
* but when using #cairo_t, the last error, if any, is stored in
* the context and can be retrieved with cairo_status().
*
* New entries may be added in future versions. Use cairo_status_to_string()
* to get a human-readable representation of an error message.
**/
typedef enum _cairo_status {
CAIRO_STATUS_SUCCESS = 0,
@ -197,7 +202,8 @@ typedef enum _cairo_status {
CAIRO_STATUS_FILE_NOT_FOUND,
CAIRO_STATUS_INVALID_DASH,
CAIRO_STATUS_INVALID_DSC_COMMENT,
CAIRO_STATUS_INVALID_INDEX
CAIRO_STATUS_INVALID_INDEX,
CAIRO_STATUS_CLIP_NOT_REPRESENTABLE
} cairo_status_t;
/**
@ -376,6 +382,8 @@ cairo_set_antialias (cairo_t *cr, cairo_antialias_t antialias);
* or have a tricky intersection such as intersecting tangent to the path.
* (Note that filling is not actually implemented in this way. This
* is just a description of the rule that is applied.)
*
* New entries may be added in future versions.
**/
typedef enum _cairo_fill_rule {
CAIRO_FILL_RULE_WINDING,
@ -415,10 +423,10 @@ cairo_public void
cairo_set_line_join (cairo_t *cr, cairo_line_join_t line_join);
cairo_public void
cairo_set_dash (cairo_t *cr,
double *dashes,
int num_dashes,
double offset);
cairo_set_dash (cairo_t *cr,
const double *dashes,
int num_dashes,
double offset);
cairo_public void
cairo_set_miter_limit (cairo_t *cr, double limit);
@ -583,6 +591,38 @@ cairo_clip (cairo_t *cr);
cairo_public void
cairo_clip_preserve (cairo_t *cr);
cairo_public void
cairo_clip_extents (cairo_t *cr,
double *x1, double *y1,
double *x2, double *y2);
/**
* cairo_rectangle_t:
*
* A data structure for holding a rectangle.
*/
typedef struct _cairo_rectangle {
double x, y, width, height;
} cairo_rectangle_t;
/**
* cairo_rectangle_list_t:
*
* A data structure for holding a dynamically allocated
* array of rectangles.
*/
typedef struct _cairo_rectangle_list {
cairo_status_t status;
cairo_rectangle_t *rectangles;
int num_rectangles;
} cairo_rectangle_list_t;
cairo_public cairo_rectangle_list_t *
cairo_copy_clip_rectangles (cairo_t *cr);
cairo_public void
cairo_rectangle_list_destroy (cairo_rectangle_list_t *rectangle_list);
/* Font/Text functions */
/**
@ -777,6 +817,8 @@ typedef enum _cairo_subpixel_order {
* involves distorting them, it also reduces the faithfulness
* to the original outline shapes. Not all of the outline hinting
* styles are supported by all font backends.
*
* New entries may be added in future versions.
*/
typedef enum _cairo_hint_style {
CAIRO_HINT_STYLE_DEFAULT,
@ -889,7 +931,7 @@ cairo_public void
cairo_show_text (cairo_t *cr, const char *utf8);
cairo_public void
cairo_show_glyphs (cairo_t *cr, cairo_glyph_t *glyphs, int num_glyphs);
cairo_show_glyphs (cairo_t *cr, const cairo_glyph_t *glyphs, int num_glyphs);
cairo_public cairo_font_face_t *
cairo_get_font_face (cairo_t *cr);
@ -961,6 +1003,8 @@ cairo_font_face_status (cairo_font_face_t *font_face);
* The behavior of calling a type-specific function with a scaled font
* of the wrong type is undefined.
*
* New entries may be added in future versions.
*
* Since: 1.2
*/
typedef enum _cairo_font_type {
@ -1065,7 +1109,11 @@ cairo_get_line_join (cairo_t *cr);
cairo_public double
cairo_get_miter_limit (cairo_t *cr);
/* XXX: How to do cairo_get_dash??? Do we want to switch to a cairo_dash object? */
cairo_public cairo_status_t
cairo_get_dash_count (cairo_t *cr, int *count);
cairo_public cairo_status_t
cairo_get_dash (cairo_t *cr, double *dashes, double *offset);
cairo_public void
cairo_get_matrix (cairo_t *cr, cairo_matrix_t *matrix);
@ -1160,8 +1208,8 @@ union _cairo_path_data_t {
* @num_data: the number of elements in the data array
*
* A data structure for holding a path. This data structure serves as
* the return value for cairo_copy_path_data() and
* cairo_copy_path_data_flat() as well the input value for
* the return value for cairo_copy_path() and
* cairo_copy_path_flat() as well the input value for
* cairo_append_path().
*
* See #cairo_path_data_t for hints on how to iterate over the
@ -1191,24 +1239,6 @@ cairo_append_path (cairo_t *cr,
cairo_public void
cairo_path_destroy (cairo_path_t *path);
/**
* cairo_clip_rect_t:
*
* A data structure for holding clip rectangles.
*/
typedef struct _cairo_clip_rect {
double x, y, width, height;
} cairo_clip_rect_t;
cairo_public cairo_bool_t
cairo_has_clip (cairo_t *cr);
cairo_public cairo_bool_t
cairo_extract_clip_rectangles (cairo_t *cr,
int max_rectangles,
cairo_clip_rect_t *rectangles_out,
int *num_rectangles_out);
/* Error status queries */
cairo_public cairo_status_t
@ -1250,6 +1280,7 @@ cairo_surface_status (cairo_surface_t *surface);
* @CAIRO_SURFACE_TYPE_BEOS: The surface is of type beos
* @CAIRO_SURFACE_TYPE_DIRECTFB: The surface is of type directfb
* @CAIRO_SURFACE_TYPE_SVG: The surface is of type svg
* @CAIRO_SURFACE_TYPE_OS2: The surface is of type os2
*
* #cairo_surface_type_t is used to describe the type of a given
* surface. The surface types are also known as "backends" or "surface
@ -1270,6 +1301,8 @@ cairo_surface_status (cairo_surface_t *surface);
* The behavior of calling a type-specific function with a surface of
* the wrong type is undefined.
*
* New entries may be added in future versions.
*
* Since: 1.2
*/
typedef enum _cairo_surface_type {
@ -1284,7 +1317,8 @@ typedef enum _cairo_surface_type {
CAIRO_SURFACE_TYPE_BEOS,
CAIRO_SURFACE_TYPE_DIRECTFB,
CAIRO_SURFACE_TYPE_SVG,
CAIRO_SURFACE_TYPE_NQUARTZ
CAIRO_SURFACE_TYPE_NQUARTZ,
CAIRO_SURFACE_TYPE_OS2
} cairo_surface_type_t;
cairo_public cairo_surface_type_t
@ -1368,19 +1402,24 @@ cairo_surface_set_fallback_resolution (cairo_surface_t *surface,
* endianess of the platform. On a big-endian machine, the
* first pixel is in the uppermost bit, on a little-endian
* machine the first pixel is in the least-significant bit.
* @CAIRO_FORMAT_RGB16_565: each pixel is a 16-bit quantity,
* with red in the upper 5 bits, then green in the next 6,
* then blue in the lowest 5 bits. (Since 1.2)
* @CAIRO_FORMAT_RGB16_565: This format value is deprecated. It has
* never been properly implemented in cairo and should not be used
* by applications. (since 1.2)
*
* #cairo_format_t is used to identify the memory format of
* image data.
*
* New entries may be added in future versions.
*/
typedef enum _cairo_format {
CAIRO_FORMAT_ARGB32,
CAIRO_FORMAT_RGB24,
CAIRO_FORMAT_A8,
CAIRO_FORMAT_A1,
CAIRO_FORMAT_RGB16_565
CAIRO_FORMAT_A1
/* The value of 4 is reserved by a deprecated enum value.
* The next format added must have an explicit value of 5.
CAIRO_FORMAT_RGB16_565 = 4,
*/
} cairo_format_t;
cairo_public cairo_surface_t *
@ -1476,6 +1515,8 @@ cairo_pattern_status (cairo_pattern_t *pattern);
* gradient patterns (either LINEAR or RADIAL). Otherwise the pattern
* will be shutdown and put into an error state.
*
* New entries may be added in future versions.
*
* Since: 1.2
*/
typedef enum _cairo_pattern_type {
@ -1507,15 +1548,6 @@ cairo_public void
cairo_pattern_get_matrix (cairo_pattern_t *pattern,
cairo_matrix_t *matrix);
cairo_public cairo_status_t
cairo_pattern_get_solid_color (cairo_pattern_t *pattern,
double *r, double *g, double *b, double *a);
cairo_public cairo_status_t
cairo_pattern_get_color_stop (cairo_pattern_t *pattern,
int stop_index, double *offset,
double *r, double *g, double *b, double *a);
/**
* cairo_extend_t
* @CAIRO_EXTEND_NONE: pixels outside of the source pattern
@ -1529,6 +1561,8 @@ cairo_pattern_get_color_stop (cairo_pattern_t *pattern,
*
* #cairo_extend_t is used to describe how the area outside
* of a pattern will be drawn.
*
* New entries may be added in future versions.
*/
typedef enum _cairo_extend {
CAIRO_EXTEND_NONE,
@ -1558,6 +1592,36 @@ cairo_pattern_set_filter (cairo_pattern_t *pattern, cairo_filter_t filter);
cairo_public cairo_filter_t
cairo_pattern_get_filter (cairo_pattern_t *pattern);
cairo_public cairo_status_t
cairo_pattern_get_rgba (cairo_pattern_t *pattern,
double *red, double *green,
double *blue, double *alpha);
cairo_public cairo_status_t
cairo_pattern_get_surface (cairo_pattern_t *pattern,
cairo_surface_t **surface);
cairo_public cairo_status_t
cairo_pattern_get_color_stop_rgba (cairo_pattern_t *pattern,
int index, double *offset,
double *red, double *green,
double *blue, double *alpha);
cairo_public cairo_status_t
cairo_pattern_get_color_stop_count (cairo_pattern_t *pattern,
int *count);
cairo_public cairo_status_t
cairo_pattern_get_linear_points (cairo_pattern_t *pattern,
double *x0, double *y0,
double *x1, double *y1);
cairo_public cairo_status_t
cairo_pattern_get_radial_circles (cairo_pattern_t *pattern,
double *x0, double *y0, double *r0,
double *x1, double *y1, double *r1);
/* Matrix functions */
cairo_public void
@ -1610,92 +1674,6 @@ cairo_matrix_transform_point (const cairo_matrix_t *matrix,
cairo_public void
cairo_debug_reset_static_data (void);
#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
* having to dig through lots of documentation.
*
* The first set of REPLACED_BY functions is for functions whose names
* have just been changed. So fixing these up is mechanical, (and
* automated by means of the cairo/util/cairo-api-update script.
*
* The second set of DEPRECATED_BY functions is for functions where
* the replacement is used in a different way, (ie. different
* arguments, multiple functions instead of one, etc). Fixing these up
* will require a bit more work on the user's part, (and hopefully we
* can get cairo-api-update to find these and print some guiding
* information).
*/
#define cairo_current_font_extents cairo_current_font_extents_REPLACED_BY_cairo_font_extents
#define cairo_get_font_extents cairo_get_font_extents_REPLACED_BY_cairo_font_extents
#define cairo_current_operator cairo_current_operator_REPLACED_BY_cairo_get_operator
#define cairo_current_tolerance cairo_current_tolerance_REPLACED_BY_cairo_get_tolerance
#define cairo_current_point cairo_current_point_REPLACED_BY_cairo_get_current_point
#define cairo_current_fill_rule cairo_current_fill_rule_REPLACED_BY_cairo_get_fill_rule
#define cairo_current_line_width cairo_current_line_width_REPLACED_BY_cairo_get_line_width
#define cairo_current_line_cap cairo_current_line_cap_REPLACED_BY_cairo_get_line_cap
#define cairo_current_line_join cairo_current_line_join_REPLACED_BY_cairo_get_line_join
#define cairo_current_miter_limit cairo_current_miter_limit_REPLACED_BY_cairo_get_miter_limit
#define cairo_current_matrix cairo_current_matrix_REPLACED_BY_cairo_get_matrix
#define cairo_current_target_surface cairo_current_target_surface_REPLACED_BY_cairo_get_target
#define cairo_get_status cairo_get_status_REPLACED_BY_cairo_status
#define cairo_concat_matrix cairo_concat_matrix_REPLACED_BY_cairo_transform
#define cairo_scale_font cairo_scale_font_REPLACED_BY_cairo_set_font_size
#define cairo_select_font cairo_select_font_REPLACED_BY_cairo_select_font_face
#define cairo_transform_font cairo_transform_font_REPLACED_BY_cairo_set_font_matrix
#define cairo_transform_point cairo_transform_point_REPLACED_BY_cairo_user_to_device
#define cairo_transform_distance cairo_transform_distance_REPLACED_BY_cairo_user_to_device_distance
#define cairo_inverse_transform_point cairo_inverse_transform_point_REPLACED_BY_cairo_device_to_user
#define cairo_inverse_transform_distance cairo_inverse_transform_distance_REPLACED_BY_cairo_device_to_user_distance
#define cairo_init_clip cairo_init_clip_REPLACED_BY_cairo_reset_clip
#define cairo_surface_create_for_image cairo_surface_create_for_image_REPLACED_BY_cairo_image_surface_create_for_data
#define cairo_default_matrix cairo_default_matrix_REPLACED_BY_cairo_identity_matrix
#define cairo_matrix_set_affine cairo_matrix_set_affine_REPLACED_BY_cairo_matrix_init
#define cairo_matrix_set_identity cairo_matrix_set_identity_REPLACED_BY_cairo_matrix_init_identity
#define cairo_pattern_add_color_stop cairo_pattern_add_color_stop_REPLACED_BY_cairo_pattern_add_color_stop_rgba
#define cairo_set_rgb_color cairo_set_rgb_color_REPLACED_BY_cairo_set_source_rgb
#define cairo_set_pattern cairo_set_pattern_REPLACED_BY_cairo_set_source
#define cairo_xlib_surface_create_for_pixmap_with_visual cairo_xlib_surface_create_for_pixmap_with_visual_REPLACED_BY_cairo_xlib_surface_create
#define cairo_xlib_surface_create_for_window_with_visual cairo_xlib_surface_create_for_window_with_visual_REPLACED_BY_cairo_xlib_surface_create
#define cairo_xcb_surface_create_for_pixmap_with_visual cairo_xcb_surface_create_for_pixmap_with_visual_REPLACED_BY_cairo_xcb_surface_create
#define cairo_xcb_surface_create_for_window_with_visual cairo_xcb_surface_create_for_window_with_visual_REPLACED_BY_cairo_xcb_surface_create
#define cairo_ps_surface_set_dpi cairo_ps_surface_set_dpi_REPLACED_BY_cairo_surface_set_fallback_resolution
#define cairo_pdf_surface_set_dpi cairo_pdf_surface_set_dpi_REPLACED_BY_cairo_surface_set_fallback_resolution
#define cairo_svg_surface_set_dpi cairo_svg_surface_set_dpi_REPLACED_BY_cairo_surface_set_fallback_resolution
#define cairo_current_path cairo_current_path_DEPRECATED_BY_cairo_copy_path
#define cairo_current_path_flat cairo_current_path_flat_DEPRECATED_BY_cairo_copy_path_flat
#define cairo_get_path cairo_get_path_DEPRECATED_BY_cairo_copy_path
#define cairo_get_path_flat cairo_get_path_flat_DEPRECATED_BY_cairo_get_path_flat
#define cairo_set_alpha cairo_set_alpha_DEPRECATED_BY_cairo_set_source_rgba_OR_cairo_paint_with_alpha
#define cairo_show_surface cairo_show_surface_DEPRECATED_BY_cairo_set_source_surface_AND_cairo_paint
#define cairo_copy cairo_copy_DEPRECATED_BY_cairo_create_AND_MANY_INDIVIDUAL_FUNCTIONS
#define cairo_surface_set_repeat cairo_surface_set_repeat_DEPRECATED_BY_cairo_pattern_set_extend
#define cairo_surface_set_matrix cairo_surface_set_matrix_DEPRECATED_BY_cairo_pattern_set_matrix
#define cairo_surface_get_matrix cairo_surface_get_matrix_DEPRECATED_BY_cairo_pattern_get_matrix
#define cairo_surface_set_filter cairo_surface_set_filter_DEPRECATED_BY_cairo_pattern_set_filter
#define cairo_surface_get_filter cairo_surface_get_filter_DEPRECATED_BY_cairo_pattern_get_filter
#define cairo_matrix_create cairo_matrix_create_DEPRECATED_BY_cairo_matrix_t
#define cairo_matrix_destroy cairo_matrix_destroy_DEPRECATED_BY_cairo_matrix_t
#define cairo_matrix_copy cairo_matrix_copy_DEPRECATED_BY_cairo_matrix_t
#define cairo_matrix_get_affine cairo_matrix_get_affine_DEPRECATED_BY_cairo_matrix_t
#define cairo_set_target_surface cairo_set_target_surface_DEPRECATED_BY_cairo_create
#define cairo_set_target_glitz cairo_set_target_glitz_DEPRECATED_BY_cairo_glitz_surface_create
#define cairo_set_target_image cairo_set_target_image_DEPRECATED_BY_cairo_image_surface_create_for_data
#define cairo_set_target_pdf cairo_set_target_pdf_DEPRECATED_BY_cairo_pdf_surface_create
#define cairo_set_target_png cairo_set_target_png_DEPRECATED_BY_cairo_surface_write_to_png
#define cairo_set_target_ps cairo_set_target_ps_DEPRECATED_BY_cairo_ps_surface_create
#define cairo_set_target_quartz cairo_set_target_quartz_DEPRECATED_BY_cairo_quartz_surface_create
#define cairo_set_target_win32 cairo_set_target_win32_DEPRECATED_BY_cairo_win32_surface_create
#define cairo_set_target_xcb cairo_set_target_xcb_DEPRECATED_BY_cairo_xcb_surface_create
#define cairo_set_target_drawable cairo_set_target_drawable_DEPRECATED_BY_cairo_xlib_surface_create
#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
CAIRO_END_DECLS
#endif /* CAIRO_H */

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

@ -65,19 +65,21 @@
#include "cairo.h"
#include <pixman.h>
CAIRO_BEGIN_DECLS
#ifndef PACKAGE_BUGREPORT
#define PACKAGE_BUGREPORT "(unknown)"
#ifdef _MSC_VER
#define snprintf _snprintf
#define inline __inline
#endif
CAIRO_BEGIN_DECLS
#if __GNUC__ >= 3 && defined(__ELF__)
# define slim_hidden_proto(name) slim_hidden_proto1(name, INT_##name)
# define slim_hidden_def(name) slim_hidden_def1(name, INT_##name)
# define slim_hidden_proto(name) slim_hidden_proto1(name, slim_hidden_int_name(name))
# define slim_hidden_def(name) slim_hidden_def1(name, slim_hidden_int_name(name))
# define slim_hidden_int_name(name) INT_##name
# define slim_hidden_proto1(name, internal) \
extern __typeof (name) name \
__asm__ (slim_hidden_asmname (internal)) \
cairo_private;
cairo_private
# define slim_hidden_def1(name, internal) \
extern __typeof (name) EXT_##name __asm__(slim_hidden_asmname(name)) \
__attribute__((__alias__(slim_hidden_asmname(internal))))
@ -147,7 +149,12 @@ CAIRO_BEGIN_DECLS
#endif
#if !defined(CAIRO_MUTEX_DECLARE) && defined CAIRO_HAS_WIN32_SURFACE
# define WIN32_LEAN_AND_MEAN
# ifndef WIN32_LEAN_AND_MEAN
# define WIN32_LEAN_AND_MEAN
# endif
# ifndef WINVER
# define WINVER 0xFFFFF /* use newest and greatest */
# endif
# include <windows.h>
/* the real initialization must take place in DllMain */
# define CAIRO_MUTEX_DECLARE(name) extern CRITICAL_SECTION name;
@ -156,6 +163,17 @@ CAIRO_BEGIN_DECLS
# define CAIRO_MUTEX_UNLOCK(name) LeaveCriticalSection (&name)
#endif
#if defined(__OS2__) && !defined(CAIRO_MUTEX_DECLARE)
# define INCL_BASE
# define INCL_PM
# include <os2.h>
# define CAIRO_MUTEX_DECLARE(name) extern HMTX name
# define CAIRO_MUTEX_DECLARE_GLOBAL(name) extern HMTX name
# define CAIRO_MUTEX_LOCK(name) DosRequestMutexSem(name, SEM_INDEFINITE_WAIT)
# define CAIRO_MUTEX_UNLOCK(name) DosReleaseMutexSem(name)
#endif
#if !defined(CAIRO_MUTEX_DECLARE) && defined CAIRO_HAS_BEOS_SURFACE
cairo_private void _cairo_beos_lock(void*);
cairo_private void _cairo_beos_unlock(void*);
@ -198,6 +216,8 @@ do { \
assert (NOT_REACHED); \
} while (0)
#define CAIRO_REF_COUNT_INVALID ((unsigned int) -1)
#include "cairo-wideint-private.h"
typedef int32_t cairo_fixed_16_16_t;
@ -282,6 +302,35 @@ typedef enum cairo_internal_surface_type {
CAIRO_INTERNAL_SURFACE_TYPE_TEST_PAGINATED
} cairo_internal_surface_type_t;
/* For xlib fallbacks, we use image surfaces with formats that match
* the visual of the X server. There are a couple of common X server
* visuals for which we do not have corresponding public
* cairo_format_t values, since we do not plan on always guaranteeing
* that cairo will be able to draw to these formats.
*
* So, currently pixman does provide support for these formats. It's
* possible that in the future we will change the implementation to
* instead convert to a supported format. This would allow us to be
* able to simplify pixman to handle fewer formats.
*
* The RGB16_565 case could probably have been handled this same way,
* (and in fact we could still change it to do so, and maybe just
* leave the value in the enum but deprecate it entirely). We can't
* drop the value since it did appear in cairo 1.2.0 so it might
* appear in code, (particularly bindings which are thorough about
* things like that). But we did neglect to update CAIRO_FORMAT_VALID
* for 1.2 so we know that no functional code is out there relying on
* being able to create an image surface with a 565 format, (which is
* good since things like write_to_png are missing support for the 565
* format.
*
* NOTE: The implementation of CAIRO_FORMAT_VALID *must* *not*
* consider these internal formats as valid. */
typedef enum cairo_internal_format {
CAIRO_INTERNAL_FORMAT_ABGR32 = 0x1000,
CAIRO_INTERNAL_FORMAT_BGR24
} cairo_internal_format_t;
typedef enum cairo_direction {
CAIRO_DIRECTION_FORWARD,
CAIRO_DIRECTION_REVERSE
@ -356,9 +405,9 @@ _cairo_rectangle_intersect (cairo_rectangle_int16_t *dest, cairo_rectangle_int16
typedef struct _cairo_array cairo_array_t;
struct _cairo_array {
int size;
int num_elements;
int element_size;
unsigned int size;
unsigned int num_elements;
unsigned int element_size;
char **elements;
cairo_bool_t is_snapshot;
@ -378,7 +427,7 @@ cairo_private cairo_status_t
_cairo_array_grow_by (cairo_array_t *array, int additional);
cairo_private void
_cairo_array_truncate (cairo_array_t *array, int length);
_cairo_array_truncate (cairo_array_t *array, unsigned int num_elements);
cairo_private cairo_status_t
_cairo_array_append (cairo_array_t *array, const void *element);
@ -390,11 +439,11 @@ _cairo_array_append_multiple (cairo_array_t *array,
cairo_private cairo_status_t
_cairo_array_allocate (cairo_array_t *array,
int num_elements,
unsigned int num_elements,
void **elements);
cairo_private void *
_cairo_array_index (cairo_array_t *array, int index);
_cairo_array_index (cairo_array_t *array, unsigned int index);
cairo_private void
_cairo_array_copy_element (cairo_array_t *array, int index, void *dst);
@ -402,6 +451,9 @@ _cairo_array_copy_element (cairo_array_t *array, int index, void *dst);
cairo_private int
_cairo_array_num_elements (cairo_array_t *array);
cairo_private int
_cairo_array_size (cairo_array_t *array);
typedef cairo_array_t cairo_user_data_array_t;
cairo_private void
@ -433,7 +485,7 @@ typedef struct _cairo_font_face_backend cairo_font_face_backend_t;
*/
typedef struct _cairo_unscaled_font {
cairo_hash_entry_t hash_entry;
int ref_count;
unsigned int ref_count;
const cairo_unscaled_font_backend_t *backend;
} cairo_unscaled_font_t;
@ -463,7 +515,7 @@ struct _cairo_scaled_font {
/* useful bits for _cairo_scaled_font_nil */
cairo_status_t status;
int ref_count;
unsigned int ref_count;
/* hash key members */
cairo_font_face_t *font_face; /* may be NULL */
@ -492,7 +544,7 @@ struct _cairo_font_face {
/* hash_entry must be first */
cairo_hash_entry_t hash_entry;
cairo_status_t status;
int ref_count;
unsigned int ref_count;
cairo_user_data_array_t user_data;
const cairo_font_face_backend_t *backend;
};
@ -580,6 +632,12 @@ struct _cairo_scaled_font_backend {
const cairo_glyph_t *glyphs,
int num_glyphs);
cairo_int_status_t
(*load_truetype_table)(void *scaled_font,
unsigned long tag,
long offset,
unsigned char *buffer,
unsigned long *length);
};
struct _cairo_font_face_backend {
@ -624,7 +682,7 @@ typedef struct _cairo_stroke_style {
cairo_line_join_t line_join;
double miter_limit;
double *dash;
int num_dashes;
unsigned int num_dashes;
double dash_offset;
} cairo_stroke_style_t;
@ -899,6 +957,14 @@ struct _cairo_surface {
/* A "snapshot" surface is immutable. See _cairo_surface_snapshot. */
cairo_bool_t is_snapshot;
/*
* Surface font options, falling back to backend's default options,
* and set using _cairo_surface_set_font_options(), and propagated by
* cairo_surface_create_similar().
*/
cairo_bool_t has_font_options;
cairo_font_options_t font_options;
};
struct _cairo_image_surface {
@ -974,7 +1040,7 @@ typedef struct _cairo_gradient_pattern {
cairo_pattern_t base;
pixman_gradient_stop_t *stops;
int n_stops;
unsigned int n_stops;
} cairo_gradient_pattern_t;
typedef struct _cairo_linear_pattern {
@ -1168,7 +1234,7 @@ cairo_private cairo_line_join_t
_cairo_gstate_get_line_join (cairo_gstate_t *gstate);
cairo_private cairo_status_t
_cairo_gstate_set_dash (cairo_gstate_t *gstate, double *dash, int num_dashes, double offset);
_cairo_gstate_set_dash (cairo_gstate_t *gstate, const double *dash, int num_dashes, double offset);
cairo_private cairo_status_t
_cairo_gstate_set_miter_limit (cairo_gstate_t *gstate, double limit);
@ -1217,6 +1283,12 @@ _cairo_gstate_user_to_backend (cairo_gstate_t *gstate, double *x, double *y);
cairo_private void
_cairo_gstate_backend_to_user (cairo_gstate_t *gstate, double *x, double *y);
cairo_private void
_cairo_gstate_backend_to_user_rectangle (cairo_gstate_t *gstate,
double *x1, double *y1,
double *x2, double *y2,
cairo_bool_t *is_tight);
cairo_private cairo_status_t
_cairo_gstate_paint (cairo_gstate_t *gstate);
@ -1268,6 +1340,16 @@ _cairo_gstate_clip (cairo_gstate_t *gstate, cairo_path_fixed_t *path);
cairo_private cairo_status_t
_cairo_gstate_reset_clip (cairo_gstate_t *gstate);
cairo_private cairo_status_t
_cairo_gstate_clip_extents (cairo_gstate_t *gstate,
double *x1,
double *y1,
double *x2,
double *y2);
cairo_private cairo_rectangle_list_t*
_cairo_gstate_copy_clip_rectangles (cairo_gstate_t *gstate);
cairo_private cairo_status_t
_cairo_gstate_show_surface (cairo_gstate_t *gstate,
cairo_surface_t *surface,
@ -1330,7 +1412,7 @@ _cairo_gstate_glyph_extents (cairo_gstate_t *gstate,
cairo_private cairo_status_t
_cairo_gstate_show_glyphs (cairo_gstate_t *gstate,
cairo_glyph_t *glyphs,
const cairo_glyph_t *glyphs,
int num_glyphs);
cairo_private cairo_status_t
@ -1676,6 +1758,10 @@ _cairo_surface_init (cairo_surface_t *surface,
const cairo_surface_backend_t *backend,
cairo_content_t content);
cairo_private void
_cairo_surface_set_font_options (cairo_surface_t *surface,
cairo_font_options_t *options);
cairo_private cairo_clip_mode_t
_cairo_surface_get_clip_mode (cairo_surface_t *surface);
@ -1894,8 +1980,37 @@ _cairo_surface_has_device_transform (cairo_surface_t *surface);
/* cairo_image_surface.c */
#define CAIRO_FORMAT_VALID(format) ((format) >= CAIRO_FORMAT_ARGB32 && \
(format) <= CAIRO_FORMAT_A1)
/* XXX: In cairo 1.2.0 we added a new CAIRO_FORMAT_RGB16_565 but
* neglected to adjust this macro. The net effect is that it's
* impossible to externally create an image surface with this
* format. This is perhaps a good thing since we also neglected to fix
* up things like cairo_surface_write_to_png for the new format
* (-Wswitch-enum will tell you where). Is it obvious that format was
* added in haste?
*
* The reason for the new format was to allow the xlib backend to be
* used on X servers with a 565 visual. So the new format did its job
* for that, even without being considered "valid" for the sake of
* things like cairo_image_surface_create.
*
* Since 1.2.0 we ran into the same situtation with X servers with BGR
* visuals. This time we invented cairo_internal_format_t instead,
* (see it for more discussion).
*
* The punchline is that CAIRO_FORMAT_VALID must not conside any
* internal format to be valid. Also we need to decide if the
* RGB16_565 should be moved to instead be an internal format. If so,
* this macro need not change for it. (We probably will need to leave
* an RGB16_565 value in the header files for the sake of code that
* might have that value in it.)
*
* If we do decide to start fully supporting RGB16_565 as an external
* format, then CAIRO_FORMAT_VALID needs to be adjusted to include
* it. But that should not happen before all necessary code is fixed
* to support it (at least cairo_surface_write_to_png and a few spots
* in cairo-xlib-surface.c--again see -Wswitch-enum).
*/
#define CAIRO_FORMAT_VALID(format) ((format) <= CAIRO_FORMAT_A1)
#define CAIRO_CONTENT_VALID(content) ((content) && \
(((content) & ~(CAIRO_CONTENT_COLOR | \
@ -1948,6 +2063,10 @@ cairo_private cairo_int_status_t
_cairo_image_surface_set_clip_region (void *abstract_surface,
pixman_region16_t *region);
cairo_private cairo_image_surface_t *
_cairo_image_surface_clone (cairo_image_surface_t *surface,
cairo_format_t format);
cairo_private cairo_bool_t
_cairo_surface_is_image (const cairo_surface_t *surface);
@ -2039,7 +2158,8 @@ _cairo_matrix_get_affine (const cairo_matrix_t *matrix,
cairo_private void
_cairo_matrix_transform_bounding_box (const cairo_matrix_t *matrix,
double *x, double *y,
double *width, double *height);
double *width, double *height,
cairo_bool_t *is_tight);
cairo_private void
_cairo_matrix_compute_determinant (const cairo_matrix_t *matrix, double *det);
@ -2153,7 +2273,7 @@ _cairo_pattern_transform (cairo_pattern_t *pattern,
cairo_private cairo_bool_t
_cairo_pattern_is_opaque_solid (const cairo_pattern_t *pattern);
cairo_bool_t
cairo_private cairo_bool_t
_cairo_pattern_is_opaque (const cairo_pattern_t *abstract_pattern);
cairo_private cairo_int_status_t
@ -2227,32 +2347,88 @@ cairo_private int
_cairo_dtostr (char *buffer, size_t size, double d);
/* Avoid unnecessary PLT entries. */
slim_hidden_proto(cairo_get_current_point)
slim_hidden_proto(cairo_fill_preserve)
slim_hidden_proto(cairo_clip_preserve)
slim_hidden_proto(cairo_close_path)
slim_hidden_proto(cairo_matrix_invert)
slim_hidden_proto(cairo_matrix_multiply)
slim_hidden_proto(cairo_matrix_scale)
slim_hidden_proto(cairo_matrix_init)
slim_hidden_proto(cairo_matrix_init_identity)
slim_hidden_proto(cairo_matrix_init_translate)
slim_hidden_proto(cairo_matrix_init_scale)
slim_hidden_proto(cairo_matrix_init_rotate)
slim_hidden_proto(cairo_matrix_transform_distance)
slim_hidden_proto(cairo_matrix_transform_point)
slim_hidden_proto(cairo_move_to)
slim_hidden_proto(cairo_new_path)
slim_hidden_proto(cairo_rel_line_to)
slim_hidden_proto(cairo_restore)
slim_hidden_proto(cairo_save)
slim_hidden_proto(cairo_stroke_preserve)
slim_hidden_proto(cairo_surface_destroy)
slim_hidden_proto(cairo_surface_get_content)
slim_hidden_proto(cairo_push_group)
slim_hidden_proto(cairo_push_group_with_content)
slim_hidden_proto(cairo_pop_group)
slim_hidden_proto(cairo_pop_group_to_source)
slim_hidden_proto (cairo_clip_preserve);
slim_hidden_proto (cairo_close_path);
slim_hidden_proto (cairo_create);
slim_hidden_proto (cairo_curve_to);
slim_hidden_proto (cairo_destroy);
slim_hidden_proto (cairo_fill_preserve);
slim_hidden_proto (cairo_font_face_destroy);
slim_hidden_proto (cairo_font_face_reference);
slim_hidden_proto (cairo_font_options_create);
slim_hidden_proto (cairo_font_options_destroy);
slim_hidden_proto (cairo_font_options_equal);
slim_hidden_proto (cairo_font_options_hash);
slim_hidden_proto (cairo_font_options_merge);
slim_hidden_proto (cairo_font_options_set_antialias);
slim_hidden_proto (cairo_font_options_set_hint_metrics);
slim_hidden_proto (cairo_font_options_set_hint_style);
slim_hidden_proto (cairo_font_options_set_subpixel_order);
slim_hidden_proto (cairo_get_current_point);
slim_hidden_proto (cairo_get_matrix);
slim_hidden_proto (cairo_get_tolerance);
slim_hidden_proto (cairo_image_surface_create);
slim_hidden_proto (cairo_image_surface_create_for_data);
slim_hidden_proto (cairo_image_surface_get_height);
slim_hidden_proto (cairo_image_surface_get_width);
slim_hidden_proto (cairo_line_to);
slim_hidden_proto (cairo_mask);
slim_hidden_proto (cairo_matrix_init);
slim_hidden_proto (cairo_matrix_init_identity);
slim_hidden_proto (cairo_matrix_init_rotate);
slim_hidden_proto (cairo_matrix_init_scale);
slim_hidden_proto (cairo_matrix_init_translate);
slim_hidden_proto (cairo_matrix_invert);
slim_hidden_proto (cairo_matrix_multiply);
slim_hidden_proto (cairo_matrix_scale);
slim_hidden_proto (cairo_matrix_transform_distance);
slim_hidden_proto (cairo_matrix_transform_point);
slim_hidden_proto (cairo_matrix_translate);
slim_hidden_proto (cairo_move_to);
slim_hidden_proto (cairo_new_path);
slim_hidden_proto (cairo_paint);
slim_hidden_proto (cairo_pattern_create_for_surface);
slim_hidden_proto (cairo_pattern_create_rgb);
slim_hidden_proto (cairo_pattern_create_rgba);
slim_hidden_proto (cairo_pattern_destroy);
slim_hidden_proto (cairo_pattern_get_extend);
slim_hidden_proto (cairo_pattern_get_type);
slim_hidden_proto (cairo_pattern_reference);
slim_hidden_proto (cairo_pattern_set_matrix);
slim_hidden_proto (cairo_pop_group);
slim_hidden_proto (cairo_pop_group_to_source);
slim_hidden_proto (cairo_push_group);
slim_hidden_proto (cairo_push_group_with_content);
slim_hidden_proto (cairo_rel_line_to);
slim_hidden_proto (cairo_restore);
slim_hidden_proto (cairo_save);
slim_hidden_proto (cairo_scaled_font_create);
slim_hidden_proto (cairo_scaled_font_destroy);
slim_hidden_proto (cairo_scaled_font_extents);
slim_hidden_proto (cairo_scaled_font_get_ctm);
slim_hidden_proto (cairo_scaled_font_get_font_face);
slim_hidden_proto (cairo_scaled_font_get_font_matrix);
slim_hidden_proto (cairo_scaled_font_get_font_options);
slim_hidden_proto (cairo_scaled_font_glyph_extents);
slim_hidden_proto (cairo_scaled_font_reference);
slim_hidden_proto (cairo_set_operator);
slim_hidden_proto (cairo_set_source);
slim_hidden_proto (cairo_set_source_surface);
slim_hidden_proto (cairo_status);
slim_hidden_proto (cairo_stroke_preserve);
slim_hidden_proto (cairo_surface_create_similar);
slim_hidden_proto (cairo_surface_destroy);
slim_hidden_proto (cairo_surface_finish);
slim_hidden_proto (cairo_surface_get_content);
slim_hidden_proto (cairo_surface_get_device_offset);
slim_hidden_proto (cairo_surface_get_font_options);
slim_hidden_proto (cairo_surface_get_type);
slim_hidden_proto (cairo_surface_mark_dirty_rectangle);
slim_hidden_proto (cairo_surface_reference);
slim_hidden_proto (cairo_surface_set_device_offset);
slim_hidden_proto (cairo_surface_set_fallback_resolution);
slim_hidden_proto (cairo_surface_status);
slim_hidden_proto (cairo_surface_write_to_png_stream);
CAIRO_END_DECLS

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

@ -64,6 +64,8 @@ typedef struct _test_fallback_surface {
const cairo_private cairo_surface_backend_t test_fallback_surface_backend;
slim_hidden_proto (_test_fallback_surface_create);
cairo_surface_t *
_test_fallback_surface_create (cairo_content_t content,
int width,
@ -89,6 +91,7 @@ _test_fallback_surface_create (cairo_content_t content,
return &surface->base;
}
slim_hidden_def (_test_fallback_surface_create);
static cairo_surface_t *
_test_fallback_surface_create_similar (void *abstract_surface,

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

@ -95,6 +95,16 @@ _test_paginated_surface_create_for_data (unsigned char *data,
&test_paginated_surface_paginated_backend);
}
static cairo_status_t
_test_paginated_surface_finish (void *abstract_surface)
{
test_paginated_surface_t *surface = abstract_surface;
cairo_surface_destroy (surface->target);
return CAIRO_STATUS_SUCCESS;
}
static cairo_int_status_t
_test_paginated_surface_set_clip_region (void *abstract_surface,
pixman_region16_t *region)
@ -247,7 +257,7 @@ static const cairo_surface_backend_t test_paginated_surface_backend = {
* surface backend interface as historical cruft and ignore it. */
NULL, /* create_similar */
NULL, /* finish */
_test_paginated_surface_finish,
NULL, /* acquire_source_image */
NULL, /* release_source_image */
NULL, /* acquire_dest_image */

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

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

@ -28,6 +28,7 @@
#endif
#include "pixman-xserver-compat.h"
#include "fbpict.h"
#include "fbmmx.h"
#ifdef RENDER
@ -3092,8 +3093,8 @@ static void fbFetchTransformed(PicturePtr pict, int x, int y, int width, CARD32
if (pict->filter == PIXMAN_FILTER_NEAREST || pict->filter == PIXMAN_FILTER_FAST)
{
if (pict->repeat == RepeatNormal) {
if (PIXREGION_NUM_RECTS(pict->pCompositeClip) == 1) {
box = pict->pCompositeClip->extents;
if (PIXREGION_NUM_RECTS(pict->pSourceClip) == 1) {
box = pict->pSourceClip->extents;
for (i = 0; i < width; ++i) {
if (!mask || mask[i] & maskBits)
{
@ -3128,7 +3129,7 @@ static void fbFetchTransformed(PicturePtr pict, int x, int y, int width, CARD32
y = MOD(v.vector[1]>>16, pict->pDrawable->height);
x = MOD(v.vector[0]>>16, pict->pDrawable->width);
}
if (pixman_region_contains_point (pict->pCompositeClip, x, y, &box))
if (pixman_region_contains_point (pict->pSourceClip, x, y, &box))
buffer[i] = fetch(bits + (y + pict->pDrawable->y)*stride, x + pict->pDrawable->x, indexed);
else
buffer[i] = 0;
@ -3140,8 +3141,8 @@ static void fbFetchTransformed(PicturePtr pict, int x, int y, int width, CARD32
}
}
} else {
if (PIXREGION_NUM_RECTS(pict->pCompositeClip) == 1) {
box = pict->pCompositeClip->extents;
if (PIXREGION_NUM_RECTS(pict->pSourceClip) == 1) {
box = pict->pSourceClip->extents;
for (i = 0; i < width; ++i) {
if (!mask || mask[i] & maskBits)
{
@ -3175,7 +3176,7 @@ static void fbFetchTransformed(PicturePtr pict, int x, int y, int width, CARD32
y = v.vector[1]>>16;
x = v.vector[0]>>16;
}
if (pixman_region_contains_point (pict->pCompositeClip, x, y, &box))
if (pixman_region_contains_point (pict->pSourceClip, x, y, &box))
buffer[i] = fetch(bits + (y + pict->pDrawable->y)*stride, x + pict->pDrawable->x, indexed);
else
buffer[i] = 0;
@ -3194,8 +3195,8 @@ static void fbFetchTransformed(PicturePtr pict, int x, int y, int width, CARD32
unit.vector[1] -= unit.vector[2]/2;
if (pict->repeat == RepeatNormal) {
if (PIXREGION_NUM_RECTS(pict->pCompositeClip) == 1) {
box = pict->pCompositeClip->extents;
if (PIXREGION_NUM_RECTS(pict->pSourceClip) == 1) {
box = pict->pSourceClip->extents;
for (i = 0; i < width; ++i) {
if (!mask || mask[i] & maskBits)
{
@ -3298,14 +3299,14 @@ static void fbFetchTransformed(PicturePtr pict, int x, int y, int width, CARD32
b = bits + (y1 + pict->pDrawable->y)*stride;
tl = pixman_region_contains_point(pict->pCompositeClip, x1, y1, &box)
tl = pixman_region_contains_point(pict->pSourceClip, x1, y1, &box)
? fetch(b, x1 + pict->pDrawable->x, indexed) : 0;
tr = pixman_region_contains_point(pict->pCompositeClip, x2, y1, &box)
tr = pixman_region_contains_point(pict->pSourceClip, x2, y1, &box)
? fetch(b, x2 + pict->pDrawable->x, indexed) : 0;
b = bits + (y2 + pict->pDrawable->y)*stride;
bl = pixman_region_contains_point(pict->pCompositeClip, x1, y2, &box)
bl = pixman_region_contains_point(pict->pSourceClip, x1, y2, &box)
? fetch(b, x1 + pict->pDrawable->x, indexed) : 0;
br = pixman_region_contains_point(pict->pCompositeClip, x2, y2, &box)
br = pixman_region_contains_point(pict->pSourceClip, x2, y2, &box)
? fetch(b, x2 + pict->pDrawable->x, indexed) : 0;
ft = FbGet8(tl,0) * idistx + FbGet8(tr,0) * distx;
@ -3329,8 +3330,8 @@ static void fbFetchTransformed(PicturePtr pict, int x, int y, int width, CARD32
}
}
} else {
if (PIXREGION_NUM_RECTS(pict->pCompositeClip) == 1) {
box = pict->pCompositeClip->extents;
if (PIXREGION_NUM_RECTS(pict->pSourceClip) == 1) {
box = pict->pSourceClip->extents;
for (i = 0; i < width; ++i) {
if (!mask || mask[i] & maskBits)
{
@ -3431,14 +3432,14 @@ static void fbFetchTransformed(PicturePtr pict, int x, int y, int width, CARD32
b = bits + (y1 + pict->pDrawable->y)*stride;
x_off = x1 + pict->pDrawable->x;
tl = pixman_region_contains_point(pict->pCompositeClip, x1, y1, &box)
tl = pixman_region_contains_point(pict->pSourceClip, x1, y1, &box)
? fetch(b, x_off, indexed) : 0;
tr = pixman_region_contains_point(pict->pCompositeClip, x2, y1, &box)
tr = pixman_region_contains_point(pict->pSourceClip, x2, y1, &box)
? fetch(b, x_off + 1, indexed) : 0;
b += stride;
bl = pixman_region_contains_point(pict->pCompositeClip, x1, y2, &box)
bl = pixman_region_contains_point(pict->pSourceClip, x1, y2, &box)
? fetch(b, x_off, indexed) : 0;
br = pixman_region_contains_point(pict->pCompositeClip, x2, y2, &box)
br = pixman_region_contains_point(pict->pSourceClip, x2, y2, &box)
? fetch(b, x_off + 1, indexed) : 0;
ft = FbGet8(tl,0) * idistx + FbGet8(tr,0) * distx;
@ -3500,7 +3501,7 @@ static void fbFetchTransformed(PicturePtr pict, int x, int y, int width, CARD32
for (x = x1; x < x2; x++) {
if (*p) {
int tx = (pict->repeat == RepeatNormal) ? MOD (x, pict->pDrawable->width) : x;
if (pixman_region_contains_point (pict->pCompositeClip, tx, ty, &box)) {
if (pixman_region_contains_point (pict->pSourceClip, tx, ty, &box)) {
FbBits *b = bits + (ty + pict->pDrawable->y)*stride;
CARD32 c = fetch(b, tx + pict->pDrawable->x, indexed);
@ -3755,6 +3756,24 @@ fbCompositeRect (const FbComposeData *data, CARD32 *scanline_buffer)
if (!compose)
return;
/* XXX: The non-MMX version of some of the fbCompose functions
* overwrite the source or mask data (ones that use
* fbCombineMaskC, fbCombineMaskAlphaC, or fbCombineMaskValueC
* as helpers). This causes problems with the optimization in
* this function that only fetches the source or mask once if
* possible. If we're on a non-MMX machine, disable this
* optimization as a bandaid fix.
*
* https://bugs.freedesktop.org/show_bug.cgi?id=5777
*/
#ifdef USE_MMX
if (!fbHaveMMX())
#endif
{
srcClass = SourcePictClassUnknown;
maskClass = SourcePictClassUnknown;
}
for (i = 0; i < data->height; ++i) {
/* fill first half of scanline with source */
if (fetchSrc)
@ -3764,7 +3783,7 @@ fbCompositeRect (const FbComposeData *data, CARD32 *scanline_buffer)
/* fetch mask before source so that fetching of
source can be optimized */
fetchMask (data->mask, data->xMask, data->yMask + i,
data->width, mask_buffer, 0, 0);
data->width, mask_buffer, NULL, 0);
if (maskClass == SourcePictClassHorizontal)
fetchMask = NULL;
@ -3773,7 +3792,7 @@ fbCompositeRect (const FbComposeData *data, CARD32 *scanline_buffer)
if (srcClass == SourcePictClassHorizontal)
{
fetchSrc (data->src, data->xSrc, data->ySrc + i,
data->width, src_buffer, 0, 0);
data->width, src_buffer, NULL, 0);
fetchSrc = NULL;
}
else
@ -3786,7 +3805,7 @@ fbCompositeRect (const FbComposeData *data, CARD32 *scanline_buffer)
else if (fetchMask)
{
fetchMask (data->mask, data->xMask, data->yMask + i,
data->width, mask_buffer, 0, 0);
data->width, mask_buffer, NULL, 0);
}
if (store)
@ -3794,7 +3813,7 @@ fbCompositeRect (const FbComposeData *data, CARD32 *scanline_buffer)
/* fill dest into second half of scanline */
if (fetchDest)
fetchDest (data->dest, data->xDest, data->yDest + i,
data->width, dest_buffer, 0, 0);
data->width, dest_buffer, NULL, 0);
/* blend */
compose (dest_buffer, src_buffer, mask_buffer, data->width);
@ -3814,8 +3833,8 @@ fbCompositeRect (const FbComposeData *data, CARD32 *scanline_buffer)
}
else
{
CARD32 *src_mask_buffer = 0; /* squelch bogus compiler warning */
CARD32 *mask_buffer = 0;
CARD32 *src_mask_buffer = NULL; /* squelch bogus compiler warning */
CARD32 *mask_buffer = NULL;
CombineFuncU compose = composeFunctions.combineU[data->op];
if (!compose)
return;
@ -3832,7 +3851,7 @@ fbCompositeRect (const FbComposeData *data, CARD32 *scanline_buffer)
/* fetch mask before source so that fetching of
source can be optimized */
fetchMask (data->mask, data->xMask, data->yMask + i,
data->width, mask_buffer, 0, 0);
data->width, mask_buffer, NULL, 0);
if (maskClass == SourcePictClassHorizontal)
fetchMask = NULL;
@ -3841,7 +3860,7 @@ fbCompositeRect (const FbComposeData *data, CARD32 *scanline_buffer)
if (srcClass == SourcePictClassHorizontal)
{
fetchSrc (data->src, data->xSrc, data->ySrc + i,
data->width, src_buffer, 0, 0);
data->width, src_buffer, NULL, 0);
if (mask_buffer)
{
@ -3870,7 +3889,7 @@ fbCompositeRect (const FbComposeData *data, CARD32 *scanline_buffer)
else if (fetchMask)
{
fetchMask (data->mask, data->xMask, data->yMask + i,
data->width, mask_buffer, 0, 0);
data->width, mask_buffer, NULL, 0);
fbCombineInU (mask_buffer, src_buffer, data->width);
@ -3882,7 +3901,7 @@ fbCompositeRect (const FbComposeData *data, CARD32 *scanline_buffer)
/* fill dest into second half of scanline */
if (fetchDest)
fetchDest (data->dest, data->xDest, data->yDest + i,
data->width, dest_buffer, 0, 0);
data->width, dest_buffer, NULL, 0);
/* blend */
compose (dest_buffer, src_mask_buffer, data->width);

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

@ -1060,7 +1060,7 @@ fbCompositeSolidMask_nx8888x8888Cmmx (pixman_operator_t op,
while (height--)
{
int twidth = width;
unsigned int twidth = width;
CARD32 *p = (CARD32 *)maskLine;
CARD32 *q = (CARD32 *)dstLine;
@ -2020,7 +2020,7 @@ fbCompositeSolidMask_nx8888x0565Cmmx (pixman_operator_t op,
while (height--)
{
int twidth = width;
unsigned int twidth = width;
CARD32 *p = (CARD32 *)maskLine;
CARD16 *q = (CARD16 *)dstLine;
@ -2270,7 +2270,7 @@ fbSolidFillmmx (FbPixels *pDraw,
while (height--)
{
int w;
unsigned int w;
CARD8 *d = byte_line;
byte_line += stride;
w = byte_width;
@ -2386,7 +2386,7 @@ fbCopyAreammx (FbPixels *pSrc,
while (height--)
{
int w;
unsigned int w;
CARD8 *s = src_bytes;
CARD8 *d = dst_bytes;
src_bytes += src_stride;
@ -2401,7 +2401,7 @@ fbCopyAreammx (FbPixels *pSrc,
d += 2;
}
while (w >= 4 && ((unsigned int)d & 7))
while (w >= 4 && ((unsigned long)d & 7))
{
*(CARD32 *)d = *(CARD32 *)s;

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

@ -29,6 +29,7 @@
#ifdef USE_MMX
#if !defined(__amd64__) && !defined(__x86_64__)
pixman_private
Bool fbHaveMMX(void);
#else
#define fbHaveMMX() TRUE
@ -40,8 +41,10 @@ Bool fbHaveMMX(void);
#ifdef USE_MMX
pixman_private
void fbComposeSetupMMX(void);
pixman_private
void fbCompositeSolidMask_nx8888x0565Cmmx (pixman_operator_t op,
PicturePtr pSrc,
PicturePtr pMask,
@ -54,6 +57,7 @@ void fbCompositeSolidMask_nx8888x0565Cmmx (pixman_operator_t op,
INT16 yDst,
CARD16 width,
CARD16 height);
pixman_private
void fbCompositeSrcAdd_8888x8888mmx (pixman_operator_t op,
PicturePtr pSrc,
PicturePtr pMask,
@ -66,6 +70,7 @@ void fbCompositeSrcAdd_8888x8888mmx (pixman_operator_t op,
INT16 yDst,
CARD16 width,
CARD16 height);
pixman_private
void fbCompositeSolidMask_nx8888x8888Cmmx (pixman_operator_t op,
PicturePtr pSrc,
PicturePtr pMask,
@ -78,6 +83,7 @@ void fbCompositeSolidMask_nx8888x8888Cmmx (pixman_operator_t op,
INT16 yDst,
CARD16 width,
CARD16 height);
pixman_private
void fbCompositeSolidMask_nx8x8888mmx (pixman_operator_t op,
PicturePtr pSrc,
PicturePtr pMask,
@ -90,6 +96,7 @@ void fbCompositeSolidMask_nx8x8888mmx (pixman_operator_t op,
INT16 yDst,
CARD16 width,
CARD16 height);
pixman_private
void fbCompositeSolidMaskSrc_nx8x8888mmx (pixman_operator_t op,
PicturePtr pSrc,
PicturePtr pMask,
@ -102,6 +109,7 @@ void fbCompositeSolidMaskSrc_nx8x8888mmx (pixman_operator_t op,
INT16 yDst,
CARD16 width,
CARD16 height);
pixman_private
void fbCompositeSrcAdd_8000x8000mmx (pixman_operator_t op,
PicturePtr pSrc,
PicturePtr pMask,
@ -114,6 +122,7 @@ void fbCompositeSrcAdd_8000x8000mmx (pixman_operator_t op,
INT16 yDst,
CARD16 width,
CARD16 height);
pixman_private
void fbCompositeSrc_8888RevNPx8888mmx (pixman_operator_t op,
PicturePtr pSrc,
PicturePtr pMask,
@ -126,6 +135,7 @@ void fbCompositeSrc_8888RevNPx8888mmx (pixman_operator_t op,
INT16 yDst,
CARD16 width,
CARD16 height);
pixman_private
void fbCompositeSrc_8888RevNPx0565mmx (pixman_operator_t op,
PicturePtr pSrc,
PicturePtr pMask,
@ -138,6 +148,7 @@ void fbCompositeSrc_8888RevNPx0565mmx (pixman_operator_t op,
INT16 yDst,
CARD16 width,
CARD16 height);
pixman_private
void fbCompositeSolid_nx8888mmx (pixman_operator_t op,
PicturePtr pSrc,
PicturePtr pMask,
@ -150,6 +161,7 @@ void fbCompositeSolid_nx8888mmx (pixman_operator_t op,
INT16 yDst,
CARD16 width,
CARD16 height);
pixman_private
void fbCompositeSolid_nx0565mmx (pixman_operator_t op,
PicturePtr pSrc,
PicturePtr pMask,
@ -162,6 +174,7 @@ void fbCompositeSolid_nx0565mmx (pixman_operator_t op,
INT16 yDst,
CARD16 width,
CARD16 height);
pixman_private
void fbCompositeSolidMask_nx8x0565mmx (pixman_operator_t op,
PicturePtr pSrc,
PicturePtr pMask,
@ -174,6 +187,7 @@ void fbCompositeSolidMask_nx8x0565mmx (pixman_operator_t op,
INT16 yDst,
CARD16 width,
CARD16 height);
pixman_private
void fbCompositeSrc_x888x8x8888mmx (pixman_operator_t op,
PicturePtr pSrc,
PicturePtr pMask,
@ -186,6 +200,7 @@ void fbCompositeSrc_x888x8x8888mmx (pixman_operator_t op,
INT16 yDst,
CARD16 width,
CARD16 height);
pixman_private
void fbCompositeSrc_8888x8x8888mmx (pixman_operator_t op,
PicturePtr pSrc,
PicturePtr pMask,
@ -198,6 +213,7 @@ void fbCompositeSrc_8888x8x8888mmx (pixman_operator_t op,
INT16 yDst,
CARD16 width,
CARD16 height);
pixman_private
void fbCompositeSrc_8888x8888mmx (pixman_operator_t op,
PicturePtr pSrc,
PicturePtr pMask,
@ -210,6 +226,7 @@ void fbCompositeSrc_8888x8888mmx (pixman_operator_t op,
INT16 yDst,
CARD16 width,
CARD16 height);
pixman_private
Bool fbCopyAreammx (FbPixels *pSrc,
FbPixels *pDst,
int src_x,
@ -218,6 +235,8 @@ Bool fbCopyAreammx (FbPixels *pSrc,
int dst_y,
int width,
int height);
pixman_private
void fbCompositeCopyAreammx (pixman_operator_t op,
PicturePtr pSrc,
PicturePtr pMask,
@ -230,6 +249,8 @@ void fbCompositeCopyAreammx (pixman_operator_t op,
INT16 yDst,
CARD16 width,
CARD16 height);
pixman_private
Bool fbSolidFillmmx (FbPixels *pDraw,
int x,
int y,

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

@ -1349,7 +1349,7 @@ pixman_composite (pixman_operator_t op,
Bool maskAlphaMap = FALSE;
Bool dstAlphaMap = pDst->alphaMap != 0;
int x_msk, y_msk, x_src, y_src, x_dst, y_dst;
int w, h, w_this, h_this;
unsigned int w, h, w_this, h_this;
#ifdef USE_MMX
static Bool mmx_setup = FALSE;
@ -1798,6 +1798,17 @@ pixman_composite (pixman_operator_t op,
}
}
break;
case PIXMAN_OPERATOR_CLEAR:
case PIXMAN_OPERATOR_DST:
case PIXMAN_OPERATOR_OVER_REVERSE:
case PIXMAN_OPERATOR_IN:
case PIXMAN_OPERATOR_IN_REVERSE:
case PIXMAN_OPERATOR_OUT:
case PIXMAN_OPERATOR_OUT_REVERSE:
case PIXMAN_OPERATOR_ATOP:
case PIXMAN_OPERATOR_ATOP_REVERSE:
case PIXMAN_OPERATOR_XOR:
case PIXMAN_OPERATOR_SATURATE:
default:
/* For any operator not specifically handled above we default out to the general code. */
func = NULL;
@ -1891,7 +1902,6 @@ pixman_composite (pixman_operator_t op,
}
pixman_region_destroy (region);
}
slim_hidden_def(pixman_composite);
/* The CPU detection code needs to be in a file not compiled with
* "-mmmx -msse", as gcc would generate CMOV instructions otherwise

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

@ -53,7 +53,6 @@ pixman_color_to_pixel (const pixman_format_t *format,
a = a << format->alpha;
*pixel = r|g|b|a;
}
slim_hidden_def(pixman_color_to_pixel);
static uint16_t
FbFillColor (uint32_t pixel, int bits)

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

@ -23,7 +23,7 @@
#include "icint.h"
#define Mask(n) ((n) == 32 ? 0xffffffff : ((1 << (n))-1))
#define Mask(n) ((n) == 32 ? 0xffffffff : (unsigned) ((1 << (n))-1))
pixman_format_t *
pixman_format_create (pixman_format_name_t name)
@ -53,6 +53,18 @@ pixman_format_create (pixman_format_name_t name)
0xf800,
0x07e0,
0x001f);
case PIXMAN_FORMAT_NAME_ABGR32:
return pixman_format_create_masks (32,
0xff000000,
0x000000ff,
0x0000ff00,
0x00ff0000);
case PIXMAN_FORMAT_NAME_BGR24:
return pixman_format_create_masks (32,
0x0,
0x000000ff,
0x0000ff00,
0x00ff0000);
}
return NULL;
@ -159,7 +171,6 @@ pixman_format_init (pixman_format_t *format, int format_code)
(format->blueMask << format->blue) |
(format->greenMask << format->green));
}
slim_hidden_def(pixman_format_init);
void
pixman_format_destroy (pixman_format_t *format)
@ -169,11 +180,11 @@ pixman_format_destroy (pixman_format_t *format)
void
pixman_format_get_masks (pixman_format_t *format,
int *bpp,
int *alpha_mask,
int *red_mask,
int *green_mask,
int *blue_mask)
unsigned int *bpp,
unsigned int *alpha_mask,
unsigned int *red_mask,
unsigned int *green_mask,
unsigned int *blue_mask)
{
*bpp = PICT_FORMAT_BPP (format->format_code);

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

@ -45,7 +45,6 @@ pixman_image_create (pixman_format_t *format,
return image;
}
slim_hidden_def(pixman_image_create);
pixman_image_t *
pixman_image_create_for_data (FbBits *data, pixman_format_t *format, int width, int height, int bpp, int stride)
@ -188,8 +187,8 @@ _pixman_create_source_image (void)
pixman_image_t *image;
image = (pixman_image_t *) malloc (sizeof (pixman_image_t));
image->pDrawable = 0;
image->pixels = 0;
image->pDrawable = NULL;
image->pixels = NULL;
image->format_code = PICT_a8r8g8b8;
pixman_image_init (image);
@ -206,18 +205,18 @@ pixman_image_create_linear_gradient (const pixman_linear_gradient_t *gradient,
pixman_image_t *image;
if (n_stops < 2)
return 0;
return NULL;
image = _pixman_create_source_image ();
if (!image)
return 0;
return NULL;
linear = malloc (sizeof (pixman_linear_gradient_image_t) +
sizeof (pixman_gradient_stop_t) * n_stops);
if (!linear)
{
free (image);
return 0;
return NULL;
}
linear->stops = (pixman_gradient_stop_t *) (linear + 1);
@ -233,8 +232,9 @@ pixman_image_create_linear_gradient (const pixman_linear_gradient_t *gradient,
if (_pixman_init_gradient (&image->pSourcePict->gradient, stops, n_stops))
{
free (linear);
free (image);
return 0;
return NULL;
}
return image;
@ -250,18 +250,18 @@ pixman_image_create_radial_gradient (const pixman_radial_gradient_t *gradient,
double x;
if (n_stops < 2)
return 0;
return NULL;
image = _pixman_create_source_image ();
if (!image)
return 0;
return NULL;
radial = malloc (sizeof (pixman_radial_gradient_image_t) +
sizeof (pixman_gradient_stop_t) * n_stops);
if (!radial)
{
free (image);
return 0;
return NULL;
}
radial->stops = (pixman_gradient_stop_t *) (radial + 1);
@ -288,8 +288,9 @@ pixman_image_create_radial_gradient (const pixman_radial_gradient_t *gradient,
if (_pixman_init_gradient (&image->pSourcePict->gradient, stops, n_stops))
{
free (radial);
free (image);
return 0;
return NULL;
}
return image;
@ -367,7 +368,6 @@ pixman_image_set_component_alpha (pixman_image_t *image,
if (image)
image->componentAlpha = component_alpha;
}
slim_hidden_def(pixman_image_set_component_alpha);
int
pixman_image_set_transform (pixman_image_t *image,
@ -410,7 +410,6 @@ pixman_image_set_repeat (pixman_image_t *image,
if (image)
image->repeat = repeat;
}
slim_hidden_def(pixman_image_set_repeat);
void
pixman_image_set_filter (pixman_image_t *image,
@ -468,7 +467,7 @@ pixman_image_get_data (pixman_image_t *image)
if (image->pixels)
return image->pixels->data;
return 0;
return NULL;
}
void
@ -503,7 +502,6 @@ pixman_image_destroy (pixman_image_t *image)
free (image);
}
slim_hidden_def(pixman_image_destroy);
void
pixman_image_destroyClip (pixman_image_t *image)

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

@ -243,7 +243,7 @@ FbComputeCompositeRegion (pixman_region16_t *region,
uint16_t width,
uint16_t height);
int
pixman_private int
miIsSolidAlpha (pixman_image_t *src);
/*

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

@ -33,8 +33,6 @@
#include <string.h>
#include <limits.h>
#include "slim_internal.h"
#ifndef __GNUC__
#define __inline
#endif
@ -813,7 +811,7 @@ fbRasterizeTrapezoid (pixman_image_t *pMask,
# endif
#else
# define ICINT_NEED_IC_ONES
int
pixman_private int
_FbOnes(unsigned long mask);
#endif
@ -852,17 +850,6 @@ pixman_private int
pixman_transform_point (pixman_transform_t *transform,
pixman_vector_t *vector);
/* Avoid unnessecary PLT entries. */
slim_hidden_proto(pixman_image_create)
slim_hidden_proto(pixman_color_to_pixel)
slim_hidden_proto(pixman_format_init)
slim_hidden_proto(pixman_image_destroy)
slim_hidden_proto(pixman_fill_rectangles)
slim_hidden_proto(pixman_image_set_component_alpha)
slim_hidden_proto(pixman_image_set_repeat)
slim_hidden_proto(pixman_composite)
#include "icrop.h"
/* XXX: For now, I'm just wholesale pasting Xserver/render/picture.h here: */

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

@ -363,4 +363,3 @@ bail1:
;
}
}
slim_hidden_def(pixman_fill_rectangles);

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

@ -143,7 +143,7 @@ pixman_composite_triangles (pixman_operator_t op,
const pixman_triangle_t *tris,
int ntris)
{
pixman_box16_t bounds;
pixman_box16_t bounds = {0, 0, 0, 0}; /* shut gcc up */
pixman_image_t *image = NULL;
int xDst, yDst;
int xRel, yRel;
@ -215,7 +215,7 @@ pixman_composite_tri_strip (pixman_operator_t op,
int npoints)
{
pixman_triangle_t tri;
pixman_box16_t bounds;
pixman_box16_t bounds = {0, 0, 0, 0}; /* shut gcc up */
pixman_image_t *image = NULL;
int xDst, yDst;
int xRel, yRel;
@ -292,7 +292,7 @@ pixman_composite_tri_fan (pixman_operator_t op,
int npoints)
{
pixman_triangle_t tri;
pixman_box16_t bounds;
pixman_box16_t bounds = {0, 0, 0, 0}; /* shut gcc up */
pixman_image_t *image = NULL;
const pixman_point_fixed_t *first;
int xDst, yDst;

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

@ -281,5 +281,5 @@ fbStippleTable(int bits)
case 8:
return fbStipple8Bits;
}
return 0;
return NULL;
}

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

@ -1,79 +1,79 @@
#define pixman_add_trapezoids _moz_cairo_pixman_add_trapezoids
#define pixman_color_to_pixel _moz_cairo_pixman_color_to_pixel
#define composeFunctions _moz_cairo_pixman_compose_functions
#define fbComposeSetupMMX _moz_cairo_pixman_compose_setup_mmx
#define pixman_composite _moz_cairo_pixman_composite
#define fbCompositeCopyAreammx _moz_cairo_pixman_composite_copy_area_mmx
#define fbCompositeSolidMask_nx8888x0565Cmmx _moz_cairo_pixman_composite_solid_mask_nx8888x0565Cmmx
#define fbCompositeSolidMask_nx8888x8888Cmmx _moz_cairo_pixman_composite_solid_mask_nx8888x8888Cmmx
#define fbCompositeSolidMask_nx8x0565mmx _moz_cairo_pixman_composite_solid_mask_nx8x0565mmx
#define fbCompositeSolidMask_nx8x8888mmx _moz_cairo_pixman_composite_solid_mask_nx8x8888mmx
#define fbCompositeSolidMaskSrc_nx8x8888mmx _moz_cairo_pixman_composite_solid_mask_src_nx8x8888mmx
#define fbCompositeSolid_nx0565mmx _moz_cairo_pixman_composite_solid_nx0565mmx
#define fbCompositeSolid_nx8888mmx _moz_cairo_pixman_composite_solid_nx8888mmx
#define fbCompositeSrc_8888RevNPx0565mmx _moz_cairo_pixman_composite_src_8888RevNPx0565mmx
#define fbCompositeSrc_8888RevNPx8888mmx _moz_cairo_pixman_composite_src_8888RevNPx8888_mmx
#define fbCompositeSrc_8888x8888mmx _moz_cairo_pixman_composite_src_8888x8888mmx
#define fbCompositeSrc_8888x8x8888mmx _moz_cairo_pixman_composite_src_8888x8x8888mmx
#define fbCompositeSrcAdd_8000x8000mmx _moz_cairo_pixman_composite_src_add_8000x8000mmx
#define fbCompositeSrcAdd_8888x8888mmx _moz_cairo_pixman_composite_src_add_8888x8888mmx
#define fbCompositeSrc_x888x8x8888mmx _moz_cairo_pixman_composite_src_x888x8x8888mmx
#define pixman_composite_trapezoids _moz_cairo_pixman_composite_trapezoids
#define pixman_composite_tri_fan _moz_cairo_pixman_composite_tri_fan
#define pixman_composite_tri_strip _moz_cairo_pixman_composite_tri_strip
#define pixman_composite_triangles _moz_cairo_pixman_composite_triangles
#define fbCopyAreammx _moz_cairo_pixman_copy_area_mmx
#define pixman_fill_rectangle _moz_cairo_pixman_fill_rectangle
#define pixman_fill_rectangles _moz_cairo_pixman_fill_rectangles
#define pixman_format_create _moz_cairo_pixman_format_create
#define pixman_format_create_masks _moz_cairo_pixman_format_create_masks
#define pixman_format_destroy _moz_cairo_pixman_format_destroy
#define pixman_format_get_masks _moz_cairo_pixman_format_get_masks
#define pixman_format_init _moz_cairo_pixman_format_init
#define pixman_add_trapezoids _cairo_pixman_add_trapezoids
#define pixman_color_to_pixel _cairo_pixman_color_to_pixel
#define composeFunctions _cairo_pixman_compose_functions
#define fbComposeSetupMMX _cairo_pixman_compose_setup_mmx
#define pixman_composite _cairo_pixman_composite
#define fbCompositeCopyAreammx _cairo_pixman_composite_copy_area_mmx
#define fbCompositeSolidMask_nx8888x0565Cmmx _cairo_pixman_composite_solid_mask_nx8888x0565Cmmx
#define fbCompositeSolidMask_nx8888x8888Cmmx _cairo_pixman_composite_solid_mask_nx8888x8888Cmmx
#define fbCompositeSolidMask_nx8x0565mmx _cairo_pixman_composite_solid_mask_nx8x0565mmx
#define fbCompositeSolidMask_nx8x8888mmx _cairo_pixman_composite_solid_mask_nx8x8888mmx
#define fbCompositeSolidMaskSrc_nx8x8888mmx _cairo_pixman_composite_solid_mask_src_nx8x8888mmx
#define fbCompositeSolid_nx0565mmx _cairo_pixman_composite_solid_nx0565mmx
#define fbCompositeSolid_nx8888mmx _cairo_pixman_composite_solid_nx8888mmx
#define fbCompositeSrc_8888RevNPx0565mmx _cairo_pixman_composite_src_8888RevNPx0565mmx
#define fbCompositeSrc_8888RevNPx8888mmx _cairo_pixman_composite_src_8888RevNPx8888_mmx
#define fbCompositeSrc_8888x8888mmx _cairo_pixman_composite_src_8888x8888mmx
#define fbCompositeSrc_8888x8x8888mmx _cairo_pixman_composite_src_8888x8x8888mmx
#define fbCompositeSrcAdd_8000x8000mmx _cairo_pixman_composite_src_add_8000x8000mmx
#define fbCompositeSrcAdd_8888x8888mmx _cairo_pixman_composite_src_add_8888x8888mmx
#define fbCompositeSrc_x888x8x8888mmx _cairo_pixman_composite_src_x888x8x8888mmx
#define pixman_composite_trapezoids _cairo_pixman_composite_trapezoids
#define pixman_composite_tri_fan _cairo_pixman_composite_tri_fan
#define pixman_composite_tri_strip _cairo_pixman_composite_tri_strip
#define pixman_composite_triangles _cairo_pixman_composite_triangles
#define fbCopyAreammx _cairo_pixman_copy_area_mmx
#define pixman_fill_rectangle _cairo_pixman_fill_rectangle
#define pixman_fill_rectangles _cairo_pixman_fill_rectangles
#define pixman_format_create _cairo_pixman_format_create
#define pixman_format_create_masks _cairo_pixman_format_create_masks
#define pixman_format_destroy _cairo_pixman_format_destroy
#define pixman_format_get_masks _cairo_pixman_format_get_masks
#define pixman_format_init _cairo_pixman_format_init
#if defined(USE_MMX) && !defined(__amd64__) && !defined(__x86_64__)
#define fbHaveMMX _moz_cairo_pixman_have_mmx
#define fbHaveMMX _cairo_pixman_have_mmx
#endif
#define pixman_image_create _moz_cairo_pixman_image_create
#define pixman_image_create_for_data _moz_cairo_pixman_image_create_for_data
#define pixman_image_destroy _moz_cairo_pixman_image_destroy
#define pixman_image_get_data _moz_cairo_pixman_image_get_data
#define pixman_image_get_depth _moz_cairo_pixman_image_get_depth
#define pixman_image_get_format _moz_cairo_pixman_image_get_format
#define pixman_image_get_height _moz_cairo_pixman_image_get_height
#define pixman_image_get_stride _moz_cairo_pixman_image_get_stride
#define pixman_image_get_width _moz_cairo_pixman_image_get_width
#define pixman_image_set_clip_region _moz_cairo_pixman_image_set_clip_region
#define pixman_image_set_component_alpha _moz_cairo_pixman_image_set_component_alpha
#define pixman_image_set_filter _moz_cairo_pixman_image_set_filter
#define pixman_image_set_repeat _moz_cairo_pixman_image_set_repeat
#define pixman_image_set_transform _moz_cairo_pixman_image_set_transform
#define pixman_image_create_linear_gradient _moz_cairo_pixman_image_create_linear_gradient
#define pixman_image_create_radial_gradient _moz_cairo_pixman_image_create_radial_gradient
#define miIsSolidAlpha _moz_cairo_pixman_is_solid_alpha
#define pixman_pixel_to_color _moz_cairo_pixman_pixel_to_color
#define pixman_region_append _moz_cairo_pixman_region_append
#define pixman_region_contains_point _moz_cairo_pixman_region_contains_point
#define pixman_region_contains_rectangle _moz_cairo_pixman_region_contains_rectangle
#define pixman_region_copy _moz_cairo_pixman_region_copy
#define pixman_region_create _moz_cairo_pixman_region_create
#define pixman_region_create_simple _moz_cairo_pixman_region_create_simple
#define pixman_region_destroy _moz_cairo_pixman_region_destroy
#define pixman_region_empty _moz_cairo_pixman_region_empty
#define pixman_region_extents _moz_cairo_pixman_region_extents
#define pixman_region_intersect _moz_cairo_pixman_region_intersect
#define pixman_region_inverse _moz_cairo_pixman_region_inverse
#define pixman_region_not_empty _moz_cairo_pixman_region_not_empty
#define pixman_region_num_rects _moz_cairo_pixman_region_num_rects
#define pixman_region_rects _moz_cairo_pixman_region_rects
#define pixman_region_reset _moz_cairo_pixman_region_reset
#define pixman_region_subtract _moz_cairo_pixman_region_subtract
#define pixman_region_translate _moz_cairo_pixman_region_translate
#define pixman_region_union _moz_cairo_pixman_region_union
#define pixman_region_union_rect _moz_cairo_pixman_region_union_rect
#define pixman_region_validate _moz_cairo_pixman_region_validate
#define RenderEdgeInit _moz_cairo_pixman_render_edge_init
#define RenderEdgeStep _moz_cairo_pixman_render_edge_step
#define RenderLineFixedEdgeInit _moz_cairo_pixman_render_line_fixed_edge_init
#define RenderSampleCeilY _moz_cairo_pixman_render_sample_ceil_y
#define RenderSampleFloorY _moz_cairo_pixman_render_sample_floor_y
#define fbSolidFillmmx _moz_cairo_pixman_solid_fill_mmx
#define pixman_image_create _cairo_pixman_image_create
#define pixman_image_create_for_data _cairo_pixman_image_create_for_data
#define pixman_image_destroy _cairo_pixman_image_destroy
#define pixman_image_get_data _cairo_pixman_image_get_data
#define pixman_image_get_depth _cairo_pixman_image_get_depth
#define pixman_image_get_format _cairo_pixman_image_get_format
#define pixman_image_get_height _cairo_pixman_image_get_height
#define pixman_image_get_stride _cairo_pixman_image_get_stride
#define pixman_image_get_width _cairo_pixman_image_get_width
#define pixman_image_set_clip_region _cairo_pixman_image_set_clip_region
#define pixman_image_set_component_alpha _cairo_pixman_image_set_component_alpha
#define pixman_image_set_filter _cairo_pixman_image_set_filter
#define pixman_image_set_repeat _cairo_pixman_image_set_repeat
#define pixman_image_set_transform _cairo_pixman_image_set_transform
#define pixman_image_create_linear_gradient _cairo_pixman_image_create_linear_gradient
#define pixman_image_create_radial_gradient _cairo_pixman_image_create_radial_gradient
#define miIsSolidAlpha _cairo_pixman_is_solid_alpha
#define pixman_pixel_to_color _cairo_pixman_pixel_to_color
#define pixman_region_append _cairo_pixman_region_append
#define pixman_region_contains_point _cairo_pixman_region_contains_point
#define pixman_region_contains_rectangle _cairo_pixman_region_contains_rectangle
#define pixman_region_copy _cairo_pixman_region_copy
#define pixman_region_create _cairo_pixman_region_create
#define pixman_region_create_simple _cairo_pixman_region_create_simple
#define pixman_region_destroy _cairo_pixman_region_destroy
#define pixman_region_empty _cairo_pixman_region_empty
#define pixman_region_extents _cairo_pixman_region_extents
#define pixman_region_intersect _cairo_pixman_region_intersect
#define pixman_region_inverse _cairo_pixman_region_inverse
#define pixman_region_not_empty _cairo_pixman_region_not_empty
#define pixman_region_num_rects _cairo_pixman_region_num_rects
#define pixman_region_rects _cairo_pixman_region_rects
#define pixman_region_reset _cairo_pixman_region_reset
#define pixman_region_subtract _cairo_pixman_region_subtract
#define pixman_region_translate _cairo_pixman_region_translate
#define pixman_region_union _cairo_pixman_region_union
#define pixman_region_union_rect _cairo_pixman_region_union_rect
#define pixman_region_validate _cairo_pixman_region_validate
#define RenderEdgeInit _cairo_pixman_render_edge_init
#define RenderEdgeStep _cairo_pixman_render_edge_step
#define RenderLineFixedEdgeInit _cairo_pixman_render_line_fixed_edge_init
#define RenderSampleCeilY _cairo_pixman_render_sample_ceil_y
#define RenderSampleFloorY _cairo_pixman_render_sample_floor_y
#define fbSolidFillmmx _cairo_pixman_solid_fill_mmx

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

@ -99,6 +99,14 @@ SOFTWARE.
#include "pixman-remap.h"
#if (__GNUC__ > 3 || (__GNUC__ == 3 && __GNUC_MINOR__ >= 3)) && defined(__ELF__)
#define pixman_private __attribute__((__visibility__("hidden")))
#elif defined(__SUNPRO_C) && (__SUNPRO_C >= 0x550)
#define pixman_private __hidden
#else /* not gcc >= 3.3 and not Sun Studio >= 8 */
#define pixman_private
#endif
#if defined(__cplusplus) || defined(c_plusplus)
extern "C" {
#endif
@ -118,37 +126,37 @@ typedef enum {
/* creation/destruction */
pixman_region16_t *
pixman_private pixman_region16_t *
pixman_region_create (void);
pixman_region16_t *
pixman_private pixman_region16_t *
pixman_region_create_simple (pixman_box16_t *extents);
void
pixman_private void
pixman_region_destroy (pixman_region16_t *region);
/* manipulation */
void
pixman_private void
pixman_region_translate (pixman_region16_t *region, int x, int y);
pixman_region_status_t
pixman_private pixman_region_status_t
pixman_region_copy (pixman_region16_t *dest, pixman_region16_t *source);
pixman_region_status_t
pixman_private pixman_region_status_t
pixman_region_intersect (pixman_region16_t *newReg, pixman_region16_t *reg1, pixman_region16_t *reg2);
pixman_region_status_t
pixman_private pixman_region_status_t
pixman_region_union (pixman_region16_t *newReg, pixman_region16_t *reg1, pixman_region16_t *reg2);
pixman_region_status_t
pixman_private pixman_region_status_t
pixman_region_union_rect(pixman_region16_t *dest, pixman_region16_t *source,
int x, int y, unsigned int width, unsigned int height);
pixman_region_status_t
pixman_private pixman_region_status_t
pixman_region_subtract (pixman_region16_t *regD, pixman_region16_t *regM, pixman_region16_t *regS);
pixman_region_status_t
pixman_private pixman_region_status_t
pixman_region_inverse (pixman_region16_t *newReg, pixman_region16_t *reg1, pixman_box16_t *invRect);
/* XXX: Need to fix this so it doesn't depend on an X data structure
@ -159,10 +167,10 @@ RectsTopixman_region16_t (int nrects, xRectanglePtr prect, int ctype);
/* querying */
/* XXX: These should proably be combined: pixman_region_get_rects? */
int
pixman_private int
pixman_region_num_rects (pixman_region16_t *region);
pixman_box16_t *
pixman_private pixman_box16_t *
pixman_region_rects (pixman_region16_t *region);
/* XXX: Change to an enum */
@ -170,36 +178,36 @@ pixman_region_rects (pixman_region16_t *region);
#define rgnIN 1
#define rgnPART 2
int
pixman_private int
pixman_region_contains_point (pixman_region16_t *region, int x, int y, pixman_box16_t *box);
int
pixman_private int
pixman_region_contains_rectangle (pixman_region16_t *pixman_region16_t, pixman_box16_t *prect);
int
pixman_private int
pixman_region_not_empty (pixman_region16_t *region);
pixman_box16_t *
pixman_private pixman_box16_t *
pixman_region_extents (pixman_region16_t *region);
/* mucking around */
/* WARNING: calling pixman_region_append may leave dest as an invalid
region. Follow-up with pixman_region_validate to fix it up. */
pixman_region_status_t
pixman_private pixman_region_status_t
pixman_region_append (pixman_region16_t *dest, pixman_region16_t *region);
pixman_region_status_t
pixman_private pixman_region_status_t
pixman_region_validate (pixman_region16_t *badreg, int *pOverlap);
/* Unclassified functionality
* XXX: Do all of these need to be exported?
*/
void
pixman_private void
pixman_region_reset (pixman_region16_t *region, pixman_box16_t *pBox);
void
pixman_private void
pixman_region_empty (pixman_region16_t *region);
/* ic.h */
@ -227,37 +235,39 @@ typedef enum pixman_format_name {
PIXMAN_FORMAT_NAME_RGB24,
PIXMAN_FORMAT_NAME_A8,
PIXMAN_FORMAT_NAME_A1,
PIXMAN_FORMAT_NAME_RGB16_565
PIXMAN_FORMAT_NAME_RGB16_565,
PIXMAN_FORMAT_NAME_ABGR32,
PIXMAN_FORMAT_NAME_BGR24
} pixman_format_name_t;
typedef struct pixman_format pixman_format_t;
pixman_format_t *
pixman_private pixman_format_t *
pixman_format_create (pixman_format_name_t name);
pixman_format_t *
pixman_private pixman_format_t *
pixman_format_create_masks (int bpp,
int alpha_mask,
int red_mask,
int green_mask,
int blue_mask);
void
pixman_private void
pixman_format_destroy (pixman_format_t *format);
void
pixman_private void
pixman_format_get_masks (pixman_format_t *format,
int *bpp,
int *alpha_mask,
int *red_mask,
int *green_mask,
int *blue_mask);
unsigned int *bpp,
unsigned int *alpha_mask,
unsigned int *red_mask,
unsigned int *green_mask,
unsigned int *blue_mask);
/* icimage.c */
typedef struct pixman_image pixman_image_t;
pixman_image_t *
pixman_private pixman_image_t *
pixman_image_create (pixman_format_t *format,
int width,
int height);
@ -282,16 +292,16 @@ pixman_image_create (pixman_format_t *format,
typedef uint32_t pixman_bits_t;
#endif
pixman_image_t *
pixman_private pixman_image_t *
pixman_image_create_for_data (pixman_bits_t *data,
pixman_format_t *format,
int width, int height,
int bpp, int stride);
void
pixman_private void
pixman_image_destroy (pixman_image_t *image);
int
pixman_private int
pixman_image_set_clip_region (pixman_image_t *image,
pixman_region16_t *region);
@ -366,11 +376,11 @@ typedef enum {
PIXMAN_FILTER_BILINEAR
} pixman_filter_t;
void
pixman_private void
pixman_image_set_component_alpha (pixman_image_t *image,
int component_alpha);
int
pixman_private int
pixman_image_set_transform (pixman_image_t *image,
pixman_transform_t *transform);
@ -382,57 +392,57 @@ typedef enum {
PIXMAN_REPEAT_REFLECT
} pixman_repeat_t;
void
pixman_private void
pixman_image_set_repeat (pixman_image_t *image,
pixman_repeat_t repeat);
void
pixman_private void
pixman_image_set_filter (pixman_image_t *image,
pixman_filter_t filter);
int
pixman_private int
pixman_image_get_width (pixman_image_t *image);
int
pixman_private int
pixman_image_get_height (pixman_image_t *image);
int
pixman_private int
pixman_image_get_stride (pixman_image_t *image);
int
pixman_private int
pixman_image_get_depth (pixman_image_t *image);
pixman_format_t *
pixman_private pixman_format_t *
pixman_image_get_format (pixman_image_t *image);
pixman_bits_t *
pixman_private pixman_bits_t *
pixman_image_get_data (pixman_image_t *image);
pixman_image_t *
pixman_private pixman_image_t *
pixman_image_create_linear_gradient (const pixman_linear_gradient_t *gradient,
const pixman_gradient_stop_t *stops,
int n_stops);
pixman_image_t *
pixman_private pixman_image_t *
pixman_image_create_radial_gradient (const pixman_radial_gradient_t *gradient,
const pixman_gradient_stop_t *stops,
int n_stops);
/* iccolor.c */
void
pixman_private void
pixman_color_to_pixel (const pixman_format_t *format,
const pixman_color_t *color,
pixman_bits_t *pixel);
void
pixman_private void
pixman_pixel_to_color (const pixman_format_t *format,
pixman_bits_t pixel,
pixman_color_t *color);
/* icrect.c */
void
pixman_private void
pixman_fill_rectangle (pixman_operator_t op,
pixman_image_t *dst,
const pixman_color_t *color,
@ -441,7 +451,7 @@ pixman_fill_rectangle (pixman_operator_t op,
unsigned int width,
unsigned int height);
void
pixman_private void
pixman_fill_rectangles (pixman_operator_t op,
pixman_image_t *dst,
const pixman_color_t *color,
@ -450,7 +460,7 @@ pixman_fill_rectangles (pixman_operator_t op,
/* ictrap.c */
void
pixman_private void
pixman_composite_trapezoids (pixman_operator_t op,
pixman_image_t *src,
pixman_image_t *dst,
@ -459,7 +469,7 @@ pixman_composite_trapezoids (pixman_operator_t op,
const pixman_trapezoid_t *traps,
int ntrap);
void
pixman_private void
pixman_add_trapezoids (pixman_image_t *dst,
int x_off,
int y_off,
@ -468,7 +478,7 @@ pixman_add_trapezoids (pixman_image_t *dst,
/* ictri.c */
void
pixman_private void
pixman_composite_triangles (pixman_operator_t op,
pixman_image_t *src,
pixman_image_t *dst,
@ -477,7 +487,7 @@ pixman_composite_triangles (pixman_operator_t op,
const pixman_triangle_t *tris,
int ntris);
void
pixman_private void
pixman_composite_tri_strip (pixman_operator_t op,
pixman_image_t *src,
pixman_image_t *dst,
@ -486,7 +496,7 @@ pixman_composite_tri_strip (pixman_operator_t op,
const pixman_point_fixed_t *points,
int npoints);
void
pixman_private void
pixman_composite_tri_fan (pixman_operator_t op,
pixman_image_t *src,
pixman_image_t *dst,
@ -497,7 +507,7 @@ pixman_composite_tri_fan (pixman_operator_t op,
/* ic.c */
void
pixman_private void
pixman_composite (pixman_operator_t op,
pixman_image_t *iSrc,
pixman_image_t *iMask,

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

@ -50,7 +50,6 @@ SOFTWARE.
#include <string.h>
#include "pixregionint.h"
#include "slim_internal.h"
#if defined (__GNUC__) && !defined (NO_INLINES)
#define INLINE __inline
@ -89,10 +88,6 @@ pixman_init (pixman_region16_t *region, pixman_box16_t *rect);
static void
pixman_uninit (pixman_region16_t *region);
slim_hidden_proto(pixman_region_create_simple)
slim_hidden_proto(pixman_region_copy)
slim_hidden_proto(pixman_region_union)
/*
* The functions in this file implement the Region abstraction used extensively
* throughout the X11 sample server. A Region is simply a set of disjoint
@ -327,7 +322,6 @@ pixman_region_create_simple (pixman_box16_t *extents)
return region;
}
slim_hidden_def(pixman_region_create_simple);
/*****************************************************************
* RegionInit(pReg, rect, size)
@ -452,7 +446,6 @@ pixman_region_copy(pixman_region16_t *dst, pixman_region16_t *src)
dst->data->numRects * sizeof(pixman_box16_t));
return PIXMAN_REGION_STATUS_SUCCESS;
}
slim_hidden_def(pixman_region_copy);
/*======================================================================
* Generic Region Operator
@ -988,10 +981,9 @@ pixman_region_intersectO (
}
pixman_region_status_t
pixman_region_intersect(newReg, reg1, reg2)
pixman_region16_t * newReg; /* destination Region */
pixman_region16_t * reg1;
pixman_region16_t * reg2; /* source regions */
pixman_region_intersect(pixman_region16_t * newReg,
pixman_region16_t * reg1,
pixman_region16_t * reg2)
{
good(reg1);
good(reg2);
@ -1233,7 +1225,6 @@ pixman_region_union(pixman_region16_t *newReg, pixman_region16_t *reg1, pixman_r
good(newReg);
return PIXMAN_REGION_STATUS_SUCCESS;
}
slim_hidden_def(pixman_region_union);
/*======================================================================
* Batch Rectangle Union
@ -1257,9 +1248,8 @@ slim_hidden_def(pixman_region_union);
*
*/
pixman_region_status_t
pixman_region_append(dstrgn, rgn)
pixman_region16_t * dstrgn;
pixman_region16_t * rgn;
pixman_region_append(pixman_region16_t * dstrgn,
pixman_region16_t * rgn)
{
int numRects, dnumRects, size;
pixman_box16_t *new, *old;
@ -1442,9 +1432,8 @@ QuickSortRects(
*/
pixman_region_status_t
pixman_region_validate(badreg, pOverlap)
pixman_region16_t * badreg;
int *pOverlap;
pixman_region_validate(pixman_region16_t * badreg,
int *pOverlap)
{
/* Descriptor for regions under construction in Step 2. */
typedef struct {
@ -1858,10 +1847,9 @@ pixman_region_subtractO (
*-----------------------------------------------------------------------
*/
pixman_region_status_t
pixman_region_subtract(regD, regM, regS)
pixman_region16_t * regD;
pixman_region16_t * regM;
pixman_region16_t * regS;
pixman_region_subtract(pixman_region16_t * regD,
pixman_region16_t * regM,
pixman_region16_t * regS)
{
int overlap; /* result ignored */
@ -1923,10 +1911,9 @@ pixman_region_subtract(regD, regM, regS)
*-----------------------------------------------------------------------
*/
pixman_region_status_t
pixman_region_inverse(newReg, reg1, invRect)
pixman_region16_t * newReg; /* Destination region */
pixman_region16_t * reg1; /* Region to invert */
pixman_box16_t * invRect; /* Bounding box for inversion */
pixman_region_inverse(pixman_region16_t * newReg, /* Destination region */
pixman_region16_t * reg1, /* Region to invert */
pixman_box16_t * invRect) /* Bounding box for inversion */
{
pixman_region16_t invReg; /* Quick and dirty region made from the
* bounding box */
@ -1983,9 +1970,8 @@ pixman_region_inverse(newReg, reg1, invRect)
*/
int
pixman_region_contains_rectangle(region, prect)
pixman_region16_t * region;
pixman_box16_t * prect;
pixman_region_contains_rectangle(pixman_region16_t * region,
pixman_box16_t * prect)
{
int x;
int y;
@ -2200,11 +2186,11 @@ pixman_region_reset(pixman_region16_t *region, pixman_box16_t *box)
region->data = (pixman_region16_data_t *)NULL;
}
/* box is "return" value */
int
pixman_region_contains_point(region, x, y, box)
pixman_region16_t * region;
int x, y;
pixman_box16_t * box; /* "return" value */
pixman_region_contains_point(pixman_region16_t * region,
int x, int y,
pixman_box16_t * box)
{
pixman_box16_t *pbox, *pboxEnd;
int numRects;
@ -2235,8 +2221,7 @@ pixman_region_contains_point(region, x, y, box)
}
int
pixman_region_not_empty(region)
pixman_region16_t * region;
pixman_region_not_empty(pixman_region16_t * region)
{
good(region);
return(!PIXREGION_NIL(region));
@ -2252,8 +2237,7 @@ pixman_region16_broken(pixman_region16_t * region)
*/
void
pixman_region_empty(region)
pixman_region16_t * region;
pixman_region_empty(pixman_region16_t * region)
{
good(region);
freeData(region);
@ -2263,8 +2247,7 @@ pixman_region_empty(region)
}
pixman_box16_t *
pixman_region_extents(region)
pixman_region16_t * region;
pixman_region_extents(pixman_region16_t * region)
{
good(region);
return(&region->extents);

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

@ -128,16 +128,16 @@ typedef struct {
} \
}
xFixed
pixman_private xFixed
RenderSampleCeilY (xFixed y, int bpp);
xFixed
pixman_private xFixed
RenderSampleFloorY (xFixed y, int bpp);
void
pixman_private void
RenderEdgeStep (RenderEdge *e, int n);
void
pixman_private void
RenderEdgeInit (RenderEdge *e,
int bpp,
xFixed y_start,
@ -146,7 +146,7 @@ RenderEdgeInit (RenderEdge *e,
xFixed x_bot,
xFixed y_bot);
void
pixman_private void
RenderLineFixedEdgeInit (RenderEdge *e,
int bpp,
xFixed y,

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

@ -78,8 +78,9 @@
level. */
#if __GNUC__ >= 3 && defined(__ELF__)
# define slim_hidden_proto(name) slim_hidden_proto1(name, INT_##name)
# define slim_hidden_def(name) slim_hidden_def1(name, INT_##name)
# define slim_hidden_proto(name) slim_hidden_proto1(name, slim_hidden_int_name(name))
# define slim_hidden_def(name) slim_hidden_def1(name, slim_hidden_int_name(name))
# define slim_hidden_int_name(name) INT_##name
# define slim_hidden_proto1(name, internal) \
extern __typeof (name) name \
__asm__ (slim_hidden_asmname (internal)) \

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

@ -1,734 +0,0 @@
Index: src/cairo-gstate-private.h
===================================================================
--- src/cairo-gstate-private.h.orig 2006-02-09 17:51:53.843750000 -0800
+++ src/cairo-gstate-private.h 2006-02-09 18:03:23.546875000 -0800
@@ -55,7 +55,9 @@
cairo_clip_t clip;
- cairo_surface_t *target;
+ cairo_surface_t *target; /* The target to which all rendering is directed */
+ cairo_surface_t *parent_target; /* The previous target which was receiving rendering */
+ cairo_surface_t *original_target; /* The original target the initial gstate was created with */
cairo_matrix_t ctm;
cairo_matrix_t ctm_inverse;
Index: src/cairo-gstate.c
===================================================================
--- src/cairo-gstate.c.orig 2006-02-09 18:01:01.859375000 -0800
+++ src/cairo-gstate.c 2006-02-09 18:03:23.562500000 -0800
@@ -119,6 +119,8 @@
_cairo_clip_init (&gstate->clip, target);
gstate->target = cairo_surface_reference (target);
+ gstate->parent_target = NULL;
+ gstate->original_target = cairo_surface_reference (target);
_cairo_gstate_identity_matrix (gstate);
gstate->source_ctm_inverse = gstate->ctm_inverse;
@@ -166,6 +168,9 @@
_cairo_clip_init_copy (&gstate->clip, &other->clip);
gstate->target = cairo_surface_reference (other->target);
+ /* parent_target is always set to NULL; it's only ever set by redirect_target */
+ gstate->parent_target = NULL;
+ gstate->original_target = cairo_surface_reference (other->original_target);
gstate->ctm = other->ctm;
gstate->ctm_inverse = other->ctm_inverse;
@@ -194,6 +199,12 @@
cairo_surface_destroy (gstate->target);
gstate->target = NULL;
+ cairo_surface_destroy (gstate->parent_target);
+ gstate->parent_target = NULL;
+
+ cairo_surface_destroy (gstate->original_target);
+ gstate->target = NULL;
+
cairo_pattern_destroy (gstate->source);
gstate->source = NULL;
}
@@ -248,94 +259,153 @@
gstate->target = cairo_surface_reference (target);
}
-/* Push rendering off to an off-screen group. */
-/* XXX: Rethinking this API
-cairo_status_t
-_cairo_gstate_begin_group (cairo_gstate_t *gstate)
+static cairo_status_t
+_cairo_gstate_recursive_apply_clip_path (cairo_gstate_t *gstate,
+ cairo_clip_path_t *cpath)
{
- Pixmap pix;
- unsigned int width, height;
-
- gstate->parent_surface = gstate->target;
-
- width = _cairo_surface_get_width (gstate->target);
- height = _cairo_surface_get_height (gstate->target);
+ cairo_status_t status;
- pix = XCreatePixmap (gstate->dpy,
- _cairo_surface_get_drawable (gstate->target),
- width, height,
- _cairo_surface_get_depth (gstate->target));
- if (pix == 0)
- return CAIRO_STATUS_NO_MEMORY;
+ if (cpath == NULL)
+ return CAIRO_STATUS_SUCCESS;
- gstate->target = cairo_surface_create (gstate->dpy);
- if (gstate->target->status)
- return gstate->target->status;
-
- _cairo_surface_set_drawableWH (gstate->target, pix, width, height);
-
- status = _cairo_surface_fill_rectangle (gstate->target,
- CAIRO_OPERATOR_CLEAR,
- CAIRO_COLOR_TRANSPARENT,
- 0, 0,
- _cairo_surface_get_width (gstate->target),
- _cairo_surface_get_height (gstate->target));
- if (status)
- return status;
+ status = _cairo_gstate_recursive_apply_clip_path (gstate, cpath->prev);
+ if (status)
+ return status;
- return CAIRO_STATUS_SUCCESS;
+ return _cairo_clip_clip (&gstate->clip,
+ &cpath->path,
+ cpath->fill_rule,
+ cpath->tolerance,
+ cpath->antialias,
+ gstate->target);
}
-*/
-/* Complete the current offscreen group, composing its contents onto the parent surface. */
-/* XXX: Rethinking this API
-cairo_status_t
-_cairo_gstate_end_group (cairo_gstate_t *gstate)
+/**
+ * _cairo_gstate_redirect_target:
+ * @gstate: a #cairo_gstate_t
+ * @child: the new child target
+ *
+ * Redirect @gstate rendering to a "child" target. The original
+ * "parent" target with which the gstate was created will not be
+ * affected. See _cairo_gstate_get_target().
+ *
+ * Unless the redirected target has the same device offsets as the
+ * original #cairo_t target, the clip will be INVALID after this call,
+ * and the caller should either recreate or reset the clip.
+ **/
+void
+_cairo_gstate_redirect_target (cairo_gstate_t *gstate, cairo_surface_t *child)
{
- Pixmap pix;
- cairo_color_t mask_color;
- cairo_surface_t mask;
-
- if (gstate->parent_surface == NULL)
- return CAIRO_STATUS_INVALID_POP_GROUP;
-
- _cairo_surface_init (&mask, gstate->dpy);
- _cairo_color_init (&mask_color);
-
- _cairo_surface_set_solid_color (&mask, &mask_color);
-
- * XXX: This could be made much more efficient by using
- _cairo_surface_get_damaged_width/Height if cairo_surface_t actually kept
- track of such informaton. *
- _cairo_surface_composite (gstate->op,
- gstate->target,
- mask,
- gstate->parent_surface,
- 0, 0,
- 0, 0,
- 0, 0,
- _cairo_surface_get_width (gstate->target),
- _cairo_surface_get_height (gstate->target));
-
- _cairo_surface_fini (&mask);
-
- pix = _cairo_surface_get_drawable (gstate->target);
- XFreePixmap (gstate->dpy, pix);
-
- cairo_surface_destroy (gstate->target);
- gstate->target = gstate->parent_surface;
- gstate->parent_surface = NULL;
+ /* If this gstate is already redirected, this is an error; we need a
+ * new gstate to be able to redirect */
+ assert (gstate->parent_target == NULL);
+
+ /* Set up our new parent_target based on our current target;
+ * gstate->parent_target will take the ref that is held by gstate->target
+ */
+ cairo_surface_destroy (gstate->parent_target);
+ gstate->parent_target = gstate->target;
+
+ /* Now set up our new target; we overwrite gstate->target directly,
+ * since its ref is now owned by gstate->parent_target */
+ gstate->target = cairo_surface_reference (child);
+
+ /* Check that the new surface's clip mode is compatible */
+ if (gstate->clip.mode != _cairo_surface_get_clip_mode (child)) {
+ /* clip is not compatible; try to recreate it */
+ /* XXX - saving the clip path always might be useful here,
+ * so that we could recover non-CLIP_MODE_PATH clips */
+ if (gstate->clip.mode == CAIRO_CLIP_MODE_PATH) {
+ cairo_clip_t saved_clip = gstate->clip;
+
+ _cairo_clip_init (&gstate->clip, child);
+
+ /* unwind the path and re-apply */
+ _cairo_gstate_recursive_apply_clip_path (gstate, saved_clip.path);
+
+ _cairo_clip_fini (&saved_clip);
+ } else {
+ /* uh, not sure what to do here.. */
+ _cairo_clip_fini (&gstate->clip);
+ _cairo_clip_init (&gstate->clip, child);
+ }
+ } else {
+ /* clip is compatible; allocate a new serial for the new surface. */
+ if (gstate->clip.serial)
+ gstate->clip.serial = _cairo_surface_allocate_clip_serial (child);
+ }
+}
- return CAIRO_STATUS_SUCCESS;
+/**
+ * _cairo_gstate_is_redirected
+ * @gstate: a #cairo_gstate_t
+ *
+ * Return value: TRUE if the gstate is redirected to a traget
+ * different than the original, FALSE otherwise.
+ **/
+cairo_bool_t
+_cairo_gstate_is_redirected (cairo_gstate_t *gstate)
+{
+ return (gstate->target != gstate->original_target);
}
-*/
+/**
+ * _cairo_gstate_get_target:
+ * @gstate: a #cairo_gstate_t
+ *
+ * Return the current drawing target; if drawing is not redirected,
+ * this will be the same as _cairo_gstate_get_original_target().
+ *
+ * Return value: the current target surface
+ **/
cairo_surface_t *
_cairo_gstate_get_target (cairo_gstate_t *gstate)
{
return gstate->target;
}
+/**
+ * _cairo_gstate_get_parent_target:
+ * @gstate: a #cairo_gstate_t
+ *
+ * Return the parent surface of the current drawing target surface;
+ * if this particular gstate isn't a redirect gstate, this will return NULL.
+ **/
+cairo_surface_t *
+_cairo_gstate_get_parent_target (cairo_gstate_t *gstate)
+{
+ return gstate->parent_target;
+}
+
+/**
+ * _cairo_gstate_get_original_target:
+ * @gstate: a #cairo_gstate_t
+ *
+ * Return the original target with which @gstate was created. This
+ * function always returns the original target independent of any
+ * child target that may have been set with
+ * _cairo_gstate_redirect_target.
+ *
+ * Return value: the original target surface
+ **/
+cairo_surface_t *
+_cairo_gstate_get_original_target (cairo_gstate_t *gstate)
+{
+ return gstate->original_target;
+}
+
+/**
+ * _cairo_gstate_get_clip:
+ * @gstate: a #cairo_gstate_t
+ *
+ * Return value: a pointer to the gstate's cairo_clip_t structure.
+ */
+cairo_clip_t *
+_cairo_gstate_get_clip (cairo_gstate_t *gstate)
+{
+ return &gstate->clip;
+}
+
cairo_status_t
_cairo_gstate_set_source (cairo_gstate_t *gstate,
cairo_pattern_t *source)
Index: src/cairo.c
===================================================================
--- src/cairo.c.orig 2006-02-09 17:51:53.846750000 -0800
+++ src/cairo.c 2006-02-09 18:56:40.375000000 -0800
@@ -347,33 +347,133 @@
}
slim_hidden_def(moz_cairo_set_target);
-/* XXX: I want to rethink this API
+/**
+ * cairo_push_group:
+ * @cr: a cairo context
+ *
+ * Pushes a CAIRO_CONTENT_COLOR_ALPHA temporary surface onto
+ * the rendering stack, redirecting all rendering into it.
+ * See cairo_push_group_with_content().
+ */
+
void
cairo_push_group (cairo_t *cr)
{
- if (cr->status)
- return;
+ cairo_push_group_with_content (cr, CAIRO_CONTENT_COLOR_ALPHA);
+}
+slim_hidden_def(cairo_push_group);
- cr->status = cairoPush (cr);
- if (cr->status)
- return;
+/**
+ * cairo_push_group_with_content:
+ * @cr: a cairo context
+ * @content: a %cairo_content_t indicating the type of group that
+ * will be created
+ *
+ * Pushes a temporary surface onto the rendering stack, redirecting
+ * all rendering into it. The surface dimensions are the size of
+ * the current clipping bounding box. Initially, this surface
+ * is painted with CAIRO_OPERATOR_CLEAR.
+ *
+ * cairo_push_group() calls cairo_save() so that any changes to the
+ * graphics state will not be visible after cairo_pop_group() or
+ * cairo_pop_group_with_alpha(). See cairo_pop_group() and
+ * cairo_pop_group_with_alpha().
+ */
- cr->status = _cairo_gstate_begin_group (cr->gstate);
+void
+cairo_push_group_with_content (cairo_t *cr, cairo_content_t content)
+{
+ cairo_status_t status;
+ cairo_rectangle_t extents;
+ cairo_surface_t *group_surface = NULL;
+
+ /* Get the extents that we'll use in creating our new group surface */
+ _cairo_surface_get_extents (_cairo_gstate_get_target (cr->gstate), &extents);
+ status = _cairo_clip_intersect_to_rectangle (_cairo_gstate_get_clip (cr->gstate), &extents);
+ if (status != CAIRO_STATUS_SUCCESS)
+ goto bail;
+
+ group_surface = cairo_surface_create_similar (_cairo_gstate_get_target (cr->gstate),
+ content,
+ extents.width,
+ extents.height);
+ status = cairo_surface_status (group_surface);
+ if (status)
+ goto bail;
+
+ /* Set device offsets on the new surface so that logically it appears at
+ * the same location on the parent surface. */
+ cairo_surface_set_device_offset (group_surface, -extents.x, -extents.y);
+
+ /* create a new gstate for the redirect */
+ cairo_save (cr);
+ if (cr->status)
+ goto bail;
+
+ _cairo_gstate_redirect_target (cr->gstate, group_surface);
+
+bail:
+ cairo_surface_destroy (group_surface);
+ if (status)
+ _cairo_set_error (cr, status);
}
+slim_hidden_def(cairo_push_group_with_content);
-void
+cairo_pattern_t *
cairo_pop_group (cairo_t *cr)
{
- if (cr->status)
- return;
+ cairo_surface_t *group_surface, *parent_target;
+ cairo_pattern_t *group_pattern = NULL;
+ cairo_matrix_t group_matrix;
+
+ /* Grab the active surfaces */
+ group_surface = _cairo_gstate_get_target (cr->gstate);
+ parent_target = _cairo_gstate_get_parent_target (cr->gstate);
+
+ /* Verify that we are at the right nesting level */
+ if (parent_target == NULL) {
+ _cairo_set_error (cr, CAIRO_STATUS_INVALID_POP_GROUP);
+ return NULL;
+ }
+
+ /* We need to save group_surface before we restore; we don't need
+ * to reference parent_target and original_target, since the
+ * gstate will still hold refs to them once we restore. */
+ cairo_surface_reference (group_surface);
+
+ cairo_restore (cr);
- cr->status = _cairo_gstate_end_group (cr->gstate);
if (cr->status)
- return;
+ goto done;
+
+ group_pattern = cairo_pattern_create_for_surface (group_surface);
+ if (!group_pattern) {
+ cr->status = CAIRO_STATUS_NO_MEMORY;
+ goto done;
+ }
+
+ _cairo_gstate_get_matrix (cr->gstate, &group_matrix);
+ cairo_pattern_set_matrix (group_pattern, &group_matrix);
+done:
+ cairo_surface_destroy (group_surface);
- cr->status = cairoPop (cr);
+ return group_pattern;
}
-*/
+slim_hidden_def(cairo_pop_group);
+
+void
+cairo_pop_group_to_source (cairo_t *cr)
+{
+ cairo_pattern_t *group_pattern;
+
+ group_pattern = cairo_pop_group (cr);
+ if (!group_pattern)
+ return;
+
+ cairo_set_source (cr, group_pattern);
+ cairo_pattern_destroy (group_pattern);
+}
+slim_hidden_def(cairo_pop_group_to_source);
/**
* cairo_set_operator:
@@ -2421,6 +2521,30 @@
if (cr->status)
return (cairo_surface_t*) &_cairo_surface_nil;
+ return _cairo_gstate_get_original_target (cr->gstate);
+}
+
+/**
+ * cairo_get_group_target:
+ * @cr: a cairo context
+ *
+ * Gets the target surface for the current transparency group
+ * started by the last cairo_push_group() call on the cairo
+ * context.
+ *
+ * This function may return NULL if there is no transparency
+ * group on the target.
+ *
+ * Return value: the target group surface, or NULL if none. This
+ * object is owned by cairo. To keep a reference to it, you must call
+ * cairo_surface_reference().
+ **/
+cairo_surface_t *
+cairo_get_group_target (cairo_t *cr)
+{
+ if (cr->status)
+ return (cairo_surface_t*) &_cairo_surface_nil;
+
return _cairo_gstate_get_target (cr->gstate);
}
Index: src/cairo.h
===================================================================
--- src/cairo.h.orig 2006-02-09 17:51:53.847750000 -0800
+++ src/cairo.h 2006-02-09 18:04:02.390625000 -0800
@@ -197,6 +197,26 @@
} cairo_status_t;
/**
+ * cairo_content_t
+ * @CAIRO_CONTENT_COLOR: The surface will hold color content only.
+ * @CAIRO_CONTENT_ALPHA: The surface will hold alpha content only.
+ * @CAIRO_CONTENT_COLOR_ALPHA: The surface will hold color and alpha content.
+ *
+ * @cairo_content_t is used to describe the content that a surface will
+ * contain, whether color information, alpha information (translucence
+ * vs. opacity), or both.
+ *
+ * Note: The large values here are designed to keep cairo_content_t
+ * values distinct from cairo_format_t values so that the
+ * implementation can detect the error if users confuse the two types.
+ */
+typedef enum _cairo_content {
+ CAIRO_CONTENT_COLOR = 0x1000,
+ CAIRO_CONTENT_ALPHA = 0x2000,
+ CAIRO_CONTENT_COLOR_ALPHA = 0x3000
+} cairo_content_t;
+
+/**
* cairo_write_func_t:
* @closure: the output closure
* @data: the buffer containing the data to write
@@ -255,13 +275,17 @@
cairo_public void
moz_cairo_set_target (cairo_t *cr, cairo_surface_t *target);
-/* XXX: I want to rethink this API
cairo_public void
cairo_push_group (cairo_t *cr);
cairo_public void
+cairo_push_group_with_content (cairo_t *cr, cairo_content_t content);
+
+cairo_public cairo_pattern_t *
cairo_pop_group (cairo_t *cr);
-*/
+
+cairo_public void
+cairo_pop_group_to_source (cairo_t *cr);
/* Modify state */
@@ -996,6 +1020,9 @@
cairo_public cairo_surface_t *
cairo_get_target (cairo_t *cr);
+cairo_public cairo_surface_t *
+cairo_get_group_target (cairo_t *cr);
+
typedef enum _cairo_path_data_type {
CAIRO_PATH_MOVE_TO,
CAIRO_PATH_LINE_TO,
@@ -1121,26 +1148,6 @@
/* Surface manipulation */
-/**
- * cairo_content_t
- * @CAIRO_CONTENT_COLOR: The surface will hold color content only.
- * @CAIRO_CONTENT_ALPHA: The surface will hold alpha content only.
- * @CAIRO_CONTENT_COLOR_ALPHA: The surface will hold color and alpha content.
- *
- * @cairo_content_t is used to describe the content that a surface will
- * contain, whether color information, alpha information (translucence
- * vs. opacity), or both.
- *
- * Note: The large values here are designed to keep cairo_content_t
- * values distinct from cairo_format_t values so that the
- * implementation can detect the error if users confuse the two types.
- */
-typedef enum _cairo_content {
- CAIRO_CONTENT_COLOR = 0x1000,
- CAIRO_CONTENT_ALPHA = 0x2000,
- CAIRO_CONTENT_COLOR_ALPHA = 0x3000
-} cairo_content_t;
-
cairo_public cairo_surface_t *
cairo_surface_create_similar (cairo_surface_t *other,
cairo_content_t content,
Index: src/cairoint.h
===================================================================
--- src/cairoint.h.orig 2006-02-09 18:01:01.890625000 -0800
+++ src/cairoint.h 2006-02-09 18:51:23.265625000 -0800
@@ -1077,9 +1077,24 @@
cairo_private void
_moz_cairo_gstate_set_target (cairo_gstate_t *gstate, cairo_surface_t *target);
+cairo_private cairo_bool_t
+_cairo_gstate_is_redirected (cairo_gstate_t *gstate);
+
+cairo_private void
+_cairo_gstate_redirect_target (cairo_gstate_t *gstate, cairo_surface_t *child);
+
cairo_private cairo_surface_t *
_cairo_gstate_get_target (cairo_gstate_t *gstate);
+cairo_private cairo_surface_t *
+_cairo_gstate_get_parent_target (cairo_gstate_t *gstate);
+
+cairo_private cairo_surface_t *
+_cairo_gstate_get_original_target (cairo_gstate_t *gstate);
+
+cairo_private cairo_clip_t *
+_cairo_gstate_get_clip (cairo_gstate_t *gstate);
+
cairo_private cairo_status_t
_cairo_gstate_set_source (cairo_gstate_t *gstate, cairo_pattern_t *source);
@@ -2189,6 +2204,10 @@
slim_hidden_proto(cairo_save)
slim_hidden_proto(cairo_stroke_preserve)
slim_hidden_proto(cairo_surface_destroy)
+slim_hidden_proto(cairo_push_group)
+slim_hidden_proto(cairo_push_group_with_content)
+slim_hidden_proto(cairo_pop_group)
+slim_hidden_proto(cairo_pop_group_to_source)
slim_hidden_proto(moz_cairo_set_target)
CAIRO_END_DECLS
Index: test/Makefile.am
===================================================================
--- test/Makefile.am.orig 2006-02-09 17:51:53.912750000 -0800
+++ test/Makefile.am 2006-02-09 18:03:23.671875000 -0800
@@ -59,7 +59,8 @@
unantialiased-shapes \
unbounded-operator \
user-data \
-rel-path
+rel-path \
+push-group
if HAVE_PTHREAD
TESTS += pthread-show-text
@@ -346,6 +347,7 @@
user_data_LDADD = $(LDADDS)
rel_path_LDADD = $(LDADDS)
xlib_surface_LDADD = $(LDADDS)
+push_group_LDADD = $(LDADDS)
noinst_PROGRAMS = imagediff png-flatten
imagediff_LDADD = $(LDADDS)
Index: test/push-group.c
===================================================================
--- /dev/null 1970-01-01 00:00:00.000000000 +0000
+++ test/push-group.c 2006-02-09 18:03:23.671875000 -0800
@@ -0,0 +1,119 @@
+/*
+ * Copyright © 2005 Mozilla Corporation
+ *
+ * Permission to use, copy, modify, distribute, and sell this software
+ * and its documentation for any purpose is hereby granted without
+ * fee, provided that the above copyright notice appear in all copies
+ * and that both that copyright notice and this permission notice
+ * appear in supporting documentation, and that the name of
+ * Mozilla Corporation not be used in advertising or publicity pertaining to
+ * distribution of the software without specific, written prior
+ * permission. Mozilla Corporation makes no representations about the
+ * suitability of this software for any purpose. It is provided "as
+ * is" without express or implied warranty.
+ *
+ * MOZILLA CORPORATION DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS
+ * SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND
+ * FITNESS, IN NO EVENT SHALL MOZILLA CORPORATION BE LIABLE FOR ANY SPECIAL,
+ * INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER
+ * RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
+ * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR
+ * IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ *
+ * Author: Vladimir Vukicevic <vladimir@pobox.com>
+ */
+
+
+#include "cairo-test.h"
+
+
+#define UNIT_SIZE 100
+#define PAD 5
+#define INNER_PAD 10
+
+#define WIDTH (UNIT_SIZE + PAD) + PAD
+#define HEIGHT (UNIT_SIZE + PAD) + PAD
+
+cairo_test_t test = {
+ "push-group",
+ "Verify that cairo_push_group works.",
+ WIDTH, HEIGHT
+};
+
+static cairo_test_status_t
+draw (cairo_t *cr, int width, int height)
+{
+ cairo_pattern_t *gradient;
+ int i, j;
+
+ gradient = cairo_pattern_create_linear (UNIT_SIZE - (INNER_PAD*2), 0,
+ UNIT_SIZE - (INNER_PAD*2), UNIT_SIZE - (INNER_PAD*2));
+ cairo_pattern_add_color_stop_rgba (gradient, 0.0, 0.3, 0.3, 0.3, 1.0);
+ cairo_pattern_add_color_stop_rgba (gradient, 1.0, 1.0, 1.0, 1.0, 1.0);
+
+ for (j = 0; j < 1; j++) {
+ for (i = 0; i < 1; i++) {
+ double x = (i * UNIT_SIZE) + (i + 1) * PAD;
+ double y = (j * UNIT_SIZE) + (j + 1) * PAD;
+
+ cairo_save (cr);
+
+ cairo_translate (cr, x, y);
+
+ /* draw a gradient background */
+ cairo_save (cr);
+ cairo_translate (cr, INNER_PAD, INNER_PAD);
+ cairo_new_path (cr);
+ cairo_rectangle (cr, 0, 0,
+ UNIT_SIZE - (INNER_PAD*2), UNIT_SIZE - (INNER_PAD*2));
+ cairo_set_source (cr, gradient);
+ cairo_fill (cr);
+ cairo_restore (cr);
+
+ /* clip to the unit size */
+ cairo_rectangle (cr, 0, 0,
+ UNIT_SIZE, UNIT_SIZE);
+ cairo_clip (cr);
+
+ cairo_rectangle (cr, 0, 0,
+ UNIT_SIZE, UNIT_SIZE);
+ cairo_set_source_rgba (cr, 0, 0, 0, 1);
+ cairo_set_line_width (cr, 2);
+ cairo_stroke (cr);
+
+ /* start a group */
+ cairo_push_group (cr);
+
+ /* draw diamond */
+ cairo_move_to (cr, UNIT_SIZE / 2, 0);
+ cairo_line_to (cr, UNIT_SIZE , UNIT_SIZE / 2);
+ cairo_line_to (cr, UNIT_SIZE / 2, UNIT_SIZE);
+ cairo_line_to (cr, 0 , UNIT_SIZE / 2);
+ cairo_close_path (cr);
+ cairo_set_source_rgba (cr, 0, 0, 1, 1);
+ cairo_fill (cr);
+
+ /* draw circle */
+ cairo_arc (cr,
+ UNIT_SIZE / 2, UNIT_SIZE / 2,
+ UNIT_SIZE / 3.5,
+ 0, M_PI * 2);
+ cairo_set_source_rgba (cr, 1, 0, 0, 1);
+ cairo_fill (cr);
+
+ /* end group and paint */
+ cairo_pop_group_to_source (cr);
+ cairo_paint_with_alpha (cr, 0.5);
+
+ cairo_restore (cr);
+ }
+ }
+
+ return CAIRO_TEST_SUCCESS;
+}
+
+int
+main (void)
+{
+ return cairo_test (&test, draw);
+}

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

@ -121,11 +121,11 @@ public:
/* returns TRUE if it succeeded */
PRBool GetSolidColor(gfxRGBA& aColor) {
return cairo_pattern_get_solid_color(mPattern,
&aColor.r,
&aColor.g,
&aColor.b,
&aColor.a) == CAIRO_STATUS_SUCCESS;
return cairo_pattern_get_rgba(mPattern,
&aColor.r,
&aColor.g,
&aColor.b,
&aColor.a) == CAIRO_STATUS_SUCCESS;
}
protected:

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

@ -114,7 +114,6 @@ _intersect_interval (double a_begin, double a_end, double b_begin, double b_end,
return *out_begin < *out_end;
}
#define MAX_STATIC_CLIP_RECTANGLES 50
static cairo_bool_t
_get_rectangular_clip (cairo_t *cr,
int bounds_x, int bounds_y,
@ -123,24 +122,31 @@ _get_rectangular_clip (cairo_t *cr,
XRectangle *rectangles, int max_rectangles,
int *num_rectangles)
{
cairo_clip_rect_t clips[MAX_STATIC_CLIP_RECTANGLES];
int count;
cairo_rectangle_list_t *cliplist;
cairo_rectangle_t *clips;
int i;
double b_x = bounds_x;
double b_y = bounds_y;
double b_x_most = bounds_x + bounds_width;
double b_y_most = bounds_y + bounds_height;
int rect_count = 0;
if (!cairo_has_clip (cr)) {
*need_clip = False;
return True;
cairo_bool_t retval = True;
cliplist = cairo_copy_clip_rectangles (cr);
if (cliplist->status != CAIRO_STATUS_SUCCESS) {
retval = False;
goto FINISH;
}
if (!cairo_extract_clip_rectangles (cr, MAX_STATIC_CLIP_RECTANGLES, clips, &count))
return False;
if (cliplist->num_rectangles == 0) {
*num_rectangles = 0;
*need_clip = True;
goto FINISH;
}
for (i = 0; i < count; ++i) {
clips = cliplist->rectangles;
for (i = 0; i < cliplist->num_rectangles; ++i) {
double intersect_x, intersect_y, intersect_x_most, intersect_y_most;
/* the clip is always in surface backend coordinates (i.e. native backend coords) */
@ -148,7 +154,7 @@ _get_rectangular_clip (cairo_t *cr,
b_y >= clips[i].y && b_y_most <= clips[i].y + clips[i].height) {
/* the bounds are entirely inside the clip region so we don't need to clip. */
*need_clip = False;
return True;
goto FINISH;
}
if (_intersect_interval (b_x, b_x_most, clips[i].x, clips[i].x + clips[i].width,
@ -157,14 +163,19 @@ _get_rectangular_clip (cairo_t *cr,
&intersect_y, &intersect_y_most)) {
XRectangle *rect = &rectangles[rect_count];
if (rect_count >= max_rectangles)
return False;
if (rect_count >= max_rectangles) {
retval = False;
goto FINISH;
}
if (!_convert_coord_to_short (intersect_x, &rect->x) ||
!_convert_coord_to_short (intersect_y, &rect->y) ||
!_convert_coord_to_unsigned_short (intersect_x_most - intersect_x, &rect->width) ||
!_convert_coord_to_unsigned_short (intersect_y_most - intersect_y, &rect->height))
return False;
{
retval = False;
goto FINISH;
}
++rect_count;
}
@ -172,9 +183,15 @@ _get_rectangular_clip (cairo_t *cr,
*need_clip = True;
*num_rectangles = rect_count;
return True;
FINISH:
cairo_rectangle_list_destroy (cliplist);
return retval;
}
#define MAX_STATIC_CLIP_RECTANGLES 50
/**
* Try the direct path.
* @param status the status returned by the callback, if we took the direct path

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

@ -569,11 +569,11 @@ gfxContext::SetColor(const gfxRGBA& c)
PRBool
gfxContext::GetColor(gfxRGBA& c)
{
return cairo_pattern_get_solid_color(cairo_get_source(mCairo),
&c.r,
&c.g,
&c.b,
&c.a) == CAIRO_STATUS_SUCCESS;
return cairo_pattern_get_rgba(cairo_get_source(mCairo),
&c.r,
&c.g,
&c.b,
&c.a) == CAIRO_STATUS_SUCCESS;
}
void