diff options
author | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-06-12 05:43:14 +0000 |
---|---|---|
committer | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-06-12 05:43:14 +0000 |
commit | 8dd16259287f58f9273002717ec4d27e97127719 (patch) | |
tree | 3863e62a53829a84037444beab3abd4ed9dfc7d0 /gfx/cairo | |
parent | Releasing progress-linux version 126.0.1-1~progress7.99u1. (diff) | |
download | firefox-8dd16259287f58f9273002717ec4d27e97127719.tar.xz firefox-8dd16259287f58f9273002717ec4d27e97127719.zip |
Merging upstream version 127.0.
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'gfx/cairo')
343 files changed, 21505 insertions, 76284 deletions
diff --git a/gfx/cairo/00-cairo_public.patch b/gfx/cairo/00-cairo_public.patch new file mode 100644 index 0000000000..3d718b0214 --- /dev/null +++ b/gfx/cairo/00-cairo_public.patch @@ -0,0 +1,21 @@ +# HG changeset patch +# User Jonathan Kew <jkew@mozilla.com> +# Date 1713882230 -3600 +# Tue Apr 23 15:23:50 2024 +0100 +# Node ID 18ffa0ace007ca3b1acb66c9081089ea2d2e0917 +# Parent 8f822dbadb73fcfb8765937ea6bdfbaed5bd0c2c +Avoid redefinition of cairo_public + +diff --git a/gfx/cairo/cairo/src/cairo.h b/gfx/cairo/cairo/src/cairo.h +--- a/gfx/cairo/cairo/src/cairo.h ++++ b/gfx/cairo/cairo/src/cairo.h +@@ -67,7 +67,9 @@ + # define _cairo_api _cairo_import + #endif + ++#ifndef cairo_public + #define cairo_public _cairo_api extern ++#endif + + CAIRO_BEGIN_DECLS + diff --git a/gfx/cairo/04-subpixel-aa-api.patch b/gfx/cairo/04-subpixel-aa-api.patch index c4763638eb..73e54e3418 100644 --- a/gfx/cairo/04-subpixel-aa-api.patch +++ b/gfx/cairo/04-subpixel-aa-api.patch @@ -1,3 +1,11 @@ +# HG changeset patch +# User Jonathan Kew <jkew@mozilla.com> +# Date 1713886888 -3600 +# Tue Apr 23 16:41:28 2024 +0100 +# Node ID 5795122842a66df4f6217e4b5e9aac0e20b4389e +# Parent a0271c8e8524b6a3a11f76fe5854b402c71926a3 +Apply cairo/04-subpixel-aa-api.patch (with modification in cairo-quartz-surface.c) + diff --git a/gfx/cairo/cairo/src/cairo-compositor-private.h b/gfx/cairo/cairo/src/cairo-compositor-private.h --- a/gfx/cairo/cairo/src/cairo-compositor-private.h +++ b/gfx/cairo/cairo/src/cairo-compositor-private.h @@ -14,7 +22,7 @@ diff --git a/gfx/cairo/cairo/src/cairo-compositor-private.h b/gfx/cairo/cairo/sr diff --git a/gfx/cairo/cairo/src/cairo-compositor.c b/gfx/cairo/cairo/src/cairo-compositor.c --- a/gfx/cairo/cairo/src/cairo-compositor.c +++ b/gfx/cairo/cairo/src/cairo-compositor.c -@@ -248,7 +248,8 @@ cairo_int_status_t +@@ -290,7 +290,8 @@ cairo_int_status_t compositor = compositor->delegate; status = compositor->glyphs (compositor, &extents, @@ -40,7 +48,7 @@ diff --git a/gfx/cairo/cairo/src/cairo-no-compositor.c b/gfx/cairo/cairo/src/cai diff --git a/gfx/cairo/cairo/src/cairo-quartz-surface.c b/gfx/cairo/cairo/src/cairo-quartz-surface.c --- a/gfx/cairo/cairo/src/cairo-quartz-surface.c +++ b/gfx/cairo/cairo/src/cairo-quartz-surface.c -@@ -1947,7 +1947,8 @@ static cairo_int_status_t +@@ -1871,7 +1871,8 @@ static cairo_int_status_t cairo_scaled_font_t *scaled_font, cairo_glyph_t *glyphs, int num_glyphs, @@ -49,29 +57,30 @@ diff --git a/gfx/cairo/cairo/src/cairo-quartz-surface.c b/gfx/cairo/cairo/src/ca + cairo_bool_t permit_subpixel_antialiasing) { CGAffineTransform textTransform, invTextTransform; - CGGlyph glyphs_static[CAIRO_STACK_ARRAY_LENGTH (CGSize)]; -@@ -1963,6 +1964,7 @@ static cairo_int_status_t - CGFontRef cgfref = NULL; + CGGlyph glyphs_static[CAIRO_STACK_ARRAY_LENGTH (CGPoint)]; +@@ -1885,6 +1886,7 @@ static cairo_int_status_t + CTFontRef ctFont = NULL; cairo_bool_t didForceFontSmoothing = FALSE; + cairo_antialias_t effective_antialiasing; if (cairo_scaled_font_get_type (scaled_font) != CAIRO_FONT_TYPE_QUARTZ) return CAIRO_INT_STATUS_UNSUPPORTED; -@@ -1983,7 +1985,12 @@ static cairo_int_status_t - CGContextSetFont (state.cgMaskContext, cgfref); - CGContextSetFontSize (state.cgMaskContext, 1.0); +@@ -1904,6 +1906,14 @@ static cairo_int_status_t + ctFont = _cairo_quartz_scaled_font_get_ct_font (scaled_font); + _cairo_quartz_set_antialiasing (state.cgMaskContext, scaled_font->options.antialias); -- switch (scaled_font->options.antialias) { + effective_antialiasing = scaled_font->options.antialias; + if (effective_antialiasing == CAIRO_ANTIALIAS_SUBPIXEL && + !permit_subpixel_antialiasing) { + effective_antialiasing = CAIRO_ANTIALIAS_GRAY; + } -+ switch (effective_antialiasing) { - case CAIRO_ANTIALIAS_SUBPIXEL: - case CAIRO_ANTIALIAS_BEST: - CGContextSetShouldAntialias (state.cgMaskContext, TRUE); ++ ++ _cairo_quartz_set_antialiasing (state.cgMaskContext, effective_antialiasing); ++ + if (num_glyphs > ARRAY_LENGTH (glyphs_static)) { + cg_glyphs = (CGGlyph*) _cairo_malloc_ab (num_glyphs, sizeof (CGGlyph) + sizeof (CGPoint)); + if (unlikely (cg_glyphs == NULL)) { diff --git a/gfx/cairo/cairo/src/cairo-surface-private.h b/gfx/cairo/cairo/src/cairo-surface-private.h --- a/gfx/cairo/cairo/src/cairo-surface-private.h +++ b/gfx/cairo/cairo/src/cairo-surface-private.h @@ -86,7 +95,7 @@ diff --git a/gfx/cairo/cairo/src/cairo-surface-private.h b/gfx/cairo/cairo/src/c diff --git a/gfx/cairo/cairo/src/cairo-surface.c b/gfx/cairo/cairo/src/cairo-surface.c --- a/gfx/cairo/cairo/src/cairo-surface.c +++ b/gfx/cairo/cairo/src/cairo-surface.c -@@ -115,6 +115,7 @@ const cairo_surface_t name = { \ +@@ -114,6 +114,7 @@ const cairo_surface_t name = { \ FALSE, /* has_font_options */ \ FALSE, /* owns_device */ \ FALSE, /* is_vector */ \ @@ -94,7 +103,7 @@ diff --git a/gfx/cairo/cairo/src/cairo-surface.c b/gfx/cairo/cairo/src/cairo-sur { 0, 0, 0, NULL, }, /* user_data */ \ { 0, 0, 0, NULL, }, /* mime_data */ \ { 1.0, 0.0, 0.0, 1.0, 0.0, 0.0 }, /* device_transform */ \ -@@ -421,6 +422,7 @@ void +@@ -426,6 +427,7 @@ void surface->serial = 0; surface->damage = NULL; surface->owns_device = (device != NULL); @@ -102,8 +111,8 @@ diff --git a/gfx/cairo/cairo/src/cairo-surface.c b/gfx/cairo/cairo/src/cairo-sur _cairo_user_data_array_init (&surface->user_data); _cairo_user_data_array_init (&surface->mime_data); -@@ -452,6 +454,8 @@ static void - _cairo_surface_set_font_options (surface, &options); +@@ -461,6 +463,8 @@ static void + _cairo_font_options_fini (&options); } + surface->permit_subpixel_antialiasing = other->permit_subpixel_antialiasing; @@ -111,9 +120,9 @@ diff --git a/gfx/cairo/cairo/src/cairo-surface.c b/gfx/cairo/cairo/src/cairo-sur cairo_surface_set_fallback_resolution (surface, other->x_fallback_resolution, other->y_fallback_resolution); -@@ -1619,6 +1623,51 @@ cairo_surface_get_font_options (cairo_su +@@ -1626,6 +1630,51 @@ cairo_surface_get_font_options (cairo_su + _cairo_font_options_init_copy (options, &surface->font_options); } - slim_hidden_def (cairo_surface_get_font_options); +/** + * cairo_surface_set_subpixel_antialiasing: @@ -166,7 +175,7 @@ diff --git a/gfx/cairo/cairo/src/cairo-surface.c b/gfx/cairo/cairo/src/cairo-sur diff --git a/gfx/cairo/cairo/src/cairo-xcb-private.h b/gfx/cairo/cairo/src/cairo-xcb-private.h --- a/gfx/cairo/cairo/src/cairo-xcb-private.h +++ b/gfx/cairo/cairo/src/cairo-xcb-private.h -@@ -453,7 +453,8 @@ cairo_private cairo_int_status_t +@@ -443,7 +443,8 @@ cairo_private cairo_int_status_t cairo_scaled_font_t *scaled_font, cairo_glyph_t *glyphs, int num_glyphs, @@ -179,7 +188,7 @@ diff --git a/gfx/cairo/cairo/src/cairo-xcb-private.h b/gfx/cairo/cairo/src/cairo diff --git a/gfx/cairo/cairo/src/cairo-xcb-surface-render.c b/gfx/cairo/cairo/src/cairo-xcb-surface-render.c --- a/gfx/cairo/cairo/src/cairo-xcb-surface-render.c +++ b/gfx/cairo/cairo/src/cairo-xcb-surface-render.c -@@ -4816,7 +4816,8 @@ cairo_int_status_t +@@ -4814,7 +4814,8 @@ cairo_int_status_t cairo_scaled_font_t *scaled_font, cairo_glyph_t *glyphs, int num_glyphs, @@ -192,7 +201,7 @@ diff --git a/gfx/cairo/cairo/src/cairo-xcb-surface-render.c b/gfx/cairo/cairo/sr diff --git a/gfx/cairo/cairo/src/cairo-xcb-surface.c b/gfx/cairo/cairo/src/cairo-xcb-surface.c --- a/gfx/cairo/cairo/src/cairo-xcb-surface.c +++ b/gfx/cairo/cairo/src/cairo-xcb-surface.c -@@ -912,7 +912,8 @@ static cairo_int_status_t +@@ -906,7 +906,8 @@ static cairo_int_status_t cairo_scaled_font_t *scaled_font, cairo_glyph_t *glyphs, int num_glyphs, @@ -205,7 +214,7 @@ diff --git a/gfx/cairo/cairo/src/cairo-xcb-surface.c b/gfx/cairo/cairo/src/cairo diff --git a/gfx/cairo/cairo/src/cairo.h b/gfx/cairo/cairo/src/cairo.h --- a/gfx/cairo/cairo/src/cairo.h +++ b/gfx/cairo/cairo/src/cairo.h -@@ -2573,6 +2573,26 @@ cairo_surface_show_page (cairo_surface_t +@@ -2737,6 +2737,26 @@ cairo_surface_show_page (cairo_surface_t cairo_public cairo_bool_t cairo_surface_has_show_text_glyphs (cairo_surface_t *surface); diff --git a/gfx/cairo/06-shared-ft-face.patch b/gfx/cairo/06-shared-ft-face.patch index f98714db18..62dfbee3ac 100644 --- a/gfx/cairo/06-shared-ft-face.patch +++ b/gfx/cairo/06-shared-ft-face.patch @@ -1,7 +1,15 @@ +# HG changeset patch +# User Jonathan Kew <jkew@mozilla.com> +# Date 1713888724 -3600 +# Tue Apr 23 17:12:04 2024 +0100 +# Node ID 575933bf80efb0d5f1f9c1cb257837b62c75c64e +# Parent ccbfe29b41b8479213bb9f22f6eb22e01879ad7c +Apply cairo/06-shared-ft-face.patch (with update in cairo-ft-font.c) + diff --git a/gfx/cairo/cairo/src/cairo-ft-font.c b/gfx/cairo/cairo/src/cairo-ft-font.c --- a/gfx/cairo/cairo/src/cairo-ft-font.c +++ b/gfx/cairo/cairo/src/cairo-ft-font.c -@@ -101,6 +101,24 @@ +@@ -113,6 +113,24 @@ */ #define MAX_OPEN_FACES 10 @@ -26,7 +34,7 @@ diff --git a/gfx/cairo/cairo/src/cairo-ft-font.c b/gfx/cairo/cairo/src/cairo-ft- /** * SECTION:cairo-ft * @Title: FreeType Fonts -@@ -154,6 +172,7 @@ struct _cairo_ft_unscaled_font { +@@ -166,6 +184,7 @@ struct _cairo_ft_unscaled_font { cairo_bool_t from_face; /* was the FT_Face provided by user? */ FT_Face face; /* provided or cached face */ @@ -34,7 +42,7 @@ diff --git a/gfx/cairo/cairo/src/cairo-ft-font.c b/gfx/cairo/cairo/src/cairo-ft- /* only set if from_face is false */ char *filename; -@@ -336,7 +355,9 @@ static void +@@ -351,7 +370,9 @@ static void _cairo_hash_table_remove (font_map->hash_table, &unscaled->base.hash_entry); @@ -45,7 +53,7 @@ diff --git a/gfx/cairo/cairo/src/cairo-ft-font.c b/gfx/cairo/cairo/src/cairo-ft- _font_map_release_face_lock_held (font_map, unscaled); _cairo_ft_unscaled_font_fini (unscaled); -@@ -395,7 +416,8 @@ static void +@@ -410,7 +431,8 @@ static void cairo_bool_t from_face, char *filename, int id, @@ -53,9 +61,9 @@ diff --git a/gfx/cairo/cairo/src/cairo-ft-font.c b/gfx/cairo/cairo/src/cairo-ft- + FT_Face face, + void *face_context) { - unsigned long hash; + uintptr_t hash; -@@ -403,6 +425,7 @@ static void +@@ -418,6 +440,7 @@ static void key->filename = filename; key->id = id; key->face = face; @@ -63,7 +71,7 @@ diff --git a/gfx/cairo/cairo/src/cairo-ft-font.c b/gfx/cairo/cairo/src/cairo-ft- hash = _cairo_hash_string (filename); /* the constants are just arbitrary primes */ -@@ -438,7 +461,8 @@ static cairo_status_t +@@ -453,7 +476,8 @@ static cairo_status_t cairo_bool_t from_face, const char *filename, int id, @@ -73,7 +81,7 @@ diff --git a/gfx/cairo/cairo/src/cairo-ft-font.c b/gfx/cairo/cairo/src/cairo-ft- { _cairo_unscaled_font_init (&unscaled->base, &cairo_ft_unscaled_font_backend); -@@ -447,7 +471,7 @@ static cairo_status_t +@@ -462,7 +486,7 @@ static cairo_status_t if (from_face) { unscaled->from_face = TRUE; @@ -82,7 +90,7 @@ diff --git a/gfx/cairo/cairo/src/cairo-ft-font.c b/gfx/cairo/cairo/src/cairo-ft- unscaled->have_color = FT_HAS_COLOR (face) != 0; -@@ -474,12 +498,13 @@ static cairo_status_t +@@ -489,12 +513,13 @@ static cairo_status_t unscaled->from_face = FALSE; unscaled->face = NULL; @@ -97,7 +105,7 @@ diff --git a/gfx/cairo/cairo/src/cairo-ft-font.c b/gfx/cairo/cairo/src/cairo-ft- unscaled->have_color_set = FALSE; } -@@ -528,7 +553,8 @@ static int +@@ -543,7 +568,8 @@ static int unscaled_a->from_face == unscaled_b->from_face) { if (unscaled_a->from_face) @@ -107,7 +115,7 @@ diff --git a/gfx/cairo/cairo/src/cairo-ft-font.c b/gfx/cairo/cairo/src/cairo-ft- if (unscaled_a->filename == NULL && unscaled_b->filename == NULL) return TRUE; -@@ -549,6 +575,7 @@ static cairo_status_t +@@ -564,6 +590,7 @@ static cairo_status_t char *filename, int id, FT_Face font_face, @@ -115,7 +123,7 @@ diff --git a/gfx/cairo/cairo/src/cairo-ft-font.c b/gfx/cairo/cairo/src/cairo-ft- cairo_ft_unscaled_font_t **out) { cairo_ft_unscaled_font_t key, *unscaled; -@@ -559,7 +586,7 @@ static cairo_status_t +@@ -574,7 +601,7 @@ static cairo_status_t if (unlikely (font_map == NULL)) return _cairo_error (CAIRO_STATUS_NO_MEMORY); @@ -124,7 +132,7 @@ diff --git a/gfx/cairo/cairo/src/cairo-ft-font.c b/gfx/cairo/cairo/src/cairo-ft- /* Return existing unscaled font if it exists in the hash table. */ unscaled = _cairo_hash_table_lookup (font_map->hash_table, -@@ -576,7 +603,7 @@ static cairo_status_t +@@ -591,7 +618,7 @@ static cairo_status_t goto UNWIND_FONT_MAP_LOCK; } @@ -133,7 +141,7 @@ diff --git a/gfx/cairo/cairo/src/cairo-ft-font.c b/gfx/cairo/cairo/src/cairo-ft- if (unlikely (status)) goto UNWIND_UNSCALED_MALLOC; -@@ -586,6 +613,8 @@ static cairo_status_t +@@ -601,6 +628,8 @@ static cairo_status_t if (unlikely (status)) goto UNWIND_UNSCALED_FONT_INIT; @@ -142,7 +150,7 @@ diff --git a/gfx/cairo/cairo/src/cairo-ft-font.c b/gfx/cairo/cairo/src/cairo-ft- DONE: _cairo_ft_unscaled_font_map_unlock (); *out = unscaled; -@@ -638,16 +667,17 @@ static cairo_status_t +@@ -653,16 +682,17 @@ static cairo_status_t DONE: return _cairo_ft_unscaled_font_create_internal (font_face != NULL, @@ -162,7 +170,7 @@ diff --git a/gfx/cairo/cairo/src/cairo-ft-font.c b/gfx/cairo/cairo/src/cairo-ft- } static cairo_bool_t -@@ -675,12 +705,16 @@ static cairo_bool_t +@@ -690,12 +720,16 @@ static cairo_bool_t */ if (unscaled->faces && unscaled->faces->unscaled == NULL) { assert (unscaled->faces->next == NULL); @@ -179,7 +187,7 @@ diff --git a/gfx/cairo/cairo/src/cairo-ft-font.c b/gfx/cairo/cairo/src/cairo-ft- _cairo_ft_unscaled_font_map_unlock (); -@@ -709,7 +743,13 @@ static cairo_warn FT_Face +@@ -724,7 +758,13 @@ static cairo_warn FT_Face FT_Face face = NULL; FT_Error error; @@ -194,16 +202,16 @@ diff --git a/gfx/cairo/cairo/src/cairo-ft-font.c b/gfx/cairo/cairo/src/cairo-ft- unscaled->lock_count++; if (unscaled->face) -@@ -744,7 +784,7 @@ static cairo_warn FT_Face +@@ -759,7 +799,7 @@ static cairo_warn FT_Face if (error) { unscaled->lock_count--; - CAIRO_MUTEX_UNLOCK (unscaled->mutex); + CAIRO_FT_UNLOCK (unscaled); - _cairo_error_throw (_ft_to_cairo_error (error)); + _cairo_error_throw (_cairo_ft_to_cairo_error (error)); return NULL; } -@@ -769,7 +809,7 @@ static void +@@ -784,7 +824,7 @@ static void unscaled->lock_count--; @@ -212,7 +220,7 @@ diff --git a/gfx/cairo/cairo/src/cairo-ft-font.c b/gfx/cairo/cairo/src/cairo-ft- } -@@ -3164,19 +3204,21 @@ static cairo_bool_t +@@ -3997,19 +4037,21 @@ static cairo_bool_t * font_face <------- unscaled */ @@ -246,7 +254,7 @@ diff --git a/gfx/cairo/cairo/src/cairo-ft-font.c b/gfx/cairo/cairo/src/cairo-ft- cairo_ft_font_face_t *tmp_face = NULL; cairo_ft_font_face_t *last_face = NULL; -@@ -3195,6 +3237,7 @@ static cairo_bool_t +@@ -4028,6 +4070,7 @@ static cairo_bool_t last_face = tmp_face; } @@ -254,7 +262,7 @@ diff --git a/gfx/cairo/cairo/src/cairo-ft-font.c b/gfx/cairo/cairo/src/cairo-ft- _cairo_unscaled_font_destroy (&font_face->unscaled->base); font_face->unscaled = NULL; } -@@ -3268,6 +3311,24 @@ static cairo_font_face_t * +@@ -4101,6 +4144,24 @@ static cairo_font_face_t * return abstract_face; } @@ -279,7 +287,7 @@ diff --git a/gfx/cairo/cairo/src/cairo-ft-font.c b/gfx/cairo/cairo/src/cairo-ft- const cairo_font_face_backend_t _cairo_ft_font_face_backend = { CAIRO_FONT_TYPE_FT, #if CAIRO_HAS_FC_FONT -@@ -3277,7 +3338,11 @@ const cairo_font_face_backend_t _cairo_f +@@ -4110,7 +4171,11 @@ const cairo_font_face_backend_t _cairo_f #endif _cairo_ft_font_face_destroy, _cairo_ft_font_face_scaled_font_create, @@ -292,7 +300,7 @@ diff --git a/gfx/cairo/cairo/src/cairo-ft-font.c b/gfx/cairo/cairo/src/cairo-ft- }; #if CAIRO_HAS_FC_FONT -@@ -3320,6 +3385,8 @@ static cairo_font_face_t * +@@ -4153,6 +4218,8 @@ static cairo_font_face_t * { cairo_ft_font_face_t *font_face, **prev_font_face; @@ -301,7 +309,7 @@ diff --git a/gfx/cairo/cairo/src/cairo-ft-font.c b/gfx/cairo/cairo/src/cairo-ft- /* Looked for an existing matching font face */ for (font_face = unscaled->faces, prev_font_face = &unscaled->faces; font_face; -@@ -3341,15 +3408,19 @@ static cairo_font_face_t * +@@ -4174,15 +4241,19 @@ static cairo_font_face_t * * from owner to ownee. */ font_face->unscaled = unscaled; _cairo_unscaled_font_reference (&unscaled->base); @@ -324,7 +332,7 @@ diff --git a/gfx/cairo/cairo/src/cairo-ft-font.c b/gfx/cairo/cairo/src/cairo-ft- _cairo_error_throw (CAIRO_STATUS_NO_MEMORY); return (cairo_font_face_t *)&_cairo_font_face_nil; } -@@ -3376,6 +3447,7 @@ static cairo_font_face_t * +@@ -4209,6 +4280,7 @@ static cairo_font_face_t * _cairo_font_face_init (&font_face->base, &_cairo_ft_font_face_backend); @@ -332,7 +340,7 @@ diff --git a/gfx/cairo/cairo/src/cairo-ft-font.c b/gfx/cairo/cairo/src/cairo-ft- return &font_face->base; } -@@ -3737,14 +3809,16 @@ cairo_ft_font_face_create_for_pattern (F +@@ -4570,14 +4642,16 @@ cairo_ft_font_face_create_for_pattern (F cairo_font_face_t * cairo_ft_font_face_create_for_ft_face (FT_Face face, int load_flags, @@ -351,7 +359,7 @@ diff --git a/gfx/cairo/cairo/src/cairo-ft-font.c b/gfx/cairo/cairo/src/cairo-ft- if (unlikely (status)) return (cairo_font_face_t *)&_cairo_font_face_nil; -@@ -3896,7 +3970,7 @@ cairo_ft_scaled_font_lock_face (cairo_sc +@@ -4729,7 +4803,7 @@ cairo_ft_scaled_font_lock_face (cairo_sc * opportunity for creating deadlock. This is obviously unsafe, * but as documented, the user must add manual locking when using * this function. */ @@ -360,7 +368,7 @@ diff --git a/gfx/cairo/cairo/src/cairo-ft-font.c b/gfx/cairo/cairo/src/cairo-ft- return face; } -@@ -3929,7 +4003,7 @@ cairo_ft_scaled_font_unlock_face (cairo_ +@@ -4762,7 +4836,7 @@ cairo_ft_scaled_font_unlock_face (cairo_ * cairo_ft_scaled_font_lock_face, so we have to acquire it again * as _cairo_ft_unscaled_font_unlock_face expects it to be held * when we call into it. */ diff --git a/gfx/cairo/08-directwrite-additions.patch b/gfx/cairo/08-directwrite-additions.patch deleted file mode 100644 index b6521c4aec..0000000000 --- a/gfx/cairo/08-directwrite-additions.patch +++ /dev/null @@ -1,718 +0,0 @@ -diff --git a/gfx/cairo/cairo/src/cairo-win32.h b/gfx/cairo/cairo/src/cairo-win32.h ---- a/gfx/cairo/cairo/src/cairo-win32.h -+++ b/gfx/cairo/cairo/src/cairo-win32.h -@@ -69,9 +69,15 @@ cairo_win32_surface_create_with_dib (cai - cairo_public HDC - cairo_win32_surface_get_dc (cairo_surface_t *surface); - -+cairo_public HDC -+cairo_win32_get_dc_with_clip (cairo_t *cr); -+ - cairo_public cairo_surface_t * - cairo_win32_surface_get_image (cairo_surface_t *surface); - -+cairo_public cairo_status_t -+cairo_win32_surface_get_size (const cairo_surface_t *surface, int *width, int *height); -+ - #if CAIRO_HAS_WIN32_FONT - - /* -@@ -105,8 +111,33 @@ cairo_public void - cairo_win32_scaled_font_get_device_to_logical (cairo_scaled_font_t *scaled_font, - cairo_matrix_t *device_to_logical); - -+cairo_public BYTE -+cairo_win32_get_system_text_quality (void); -+ - #endif /* CAIRO_HAS_WIN32_FONT */ - -+#if CAIRO_HAS_DWRITE_FONT -+ -+/* -+ * Win32 DirectWrite font support -+ */ -+cairo_public cairo_font_face_t * -+cairo_dwrite_font_face_create_for_dwrite_fontface (void *dwrite_font, void *dwrite_font_face); -+ -+void -+cairo_dwrite_scaled_font_set_force_GDI_classic (cairo_scaled_font_t *dwrite_scaled_font, cairo_bool_t allowed); -+ -+cairo_bool_t -+cairo_dwrite_scaled_font_get_force_GDI_classic (cairo_scaled_font_t *dwrite_scaled_font); -+ -+void -+cairo_dwrite_set_cleartype_params (FLOAT gamma, FLOAT contrast, FLOAT level, int geometry, int mode); -+ -+int -+cairo_dwrite_get_cleartype_rendering_mode (); -+ -+#endif /* CAIRO_HAS_DWRITE_FONT */ -+ - CAIRO_END_DECLS - - #else /* CAIRO_HAS_WIN32_SURFACE */ -diff --git a/gfx/cairo/cairo/src/cairo.h b/gfx/cairo/cairo/src/cairo.h ---- a/gfx/cairo/cairo/src/cairo.h -+++ b/gfx/cairo/cairo/src/cairo.h -@@ -1609,7 +1609,8 @@ typedef enum _cairo_font_type { - CAIRO_FONT_TYPE_FT, - CAIRO_FONT_TYPE_WIN32, - CAIRO_FONT_TYPE_QUARTZ, -- CAIRO_FONT_TYPE_USER -+ CAIRO_FONT_TYPE_USER, -+ CAIRO_FONT_TYPE_DWRITE - } cairo_font_type_t; - - cairo_public cairo_font_type_t -diff --git a/gfx/cairo/cairo/src/win32/cairo-dwrite-font.cpp b/gfx/cairo/cairo/src/win32/cairo-dwrite-font.cpp ---- a/gfx/cairo/cairo/src/win32/cairo-dwrite-font.cpp -+++ b/gfx/cairo/cairo/src/win32/cairo-dwrite-font.cpp -@@ -37,7 +37,9 @@ - #include "cairoint.h" - - #include "cairo-win32-private.h" -+#include "cairo-pattern-private.h" - #include "cairo-surface-private.h" -+#include "cairo-image-surface-private.h" - #include "cairo-clip-private.h" - #include "cairo-win32-refptr.h" - -@@ -136,7 +138,7 @@ ID2D1DCRenderTarget *D2DFactory::mRender - static cairo_status_t - _cairo_dwrite_font_face_create_for_toy (cairo_toy_font_face_t *toy_face, - cairo_font_face_t **font_face); --static void -+static cairo_bool_t - _cairo_dwrite_font_face_destroy (void *font_face); - - static cairo_status_t -@@ -162,22 +164,6 @@ static cairo_warn cairo_int_status_t - cairo_scaled_glyph_t *scaled_glyph, - cairo_scaled_glyph_info_t info); - --cairo_warn cairo_int_status_t --_cairo_dwrite_scaled_show_glyphs(void *scaled_font, -- cairo_operator_t op, -- const cairo_pattern_t *pattern, -- cairo_surface_t *surface, -- int source_x, -- int source_y, -- int dest_x, -- int dest_y, -- unsigned int width, -- unsigned int height, -- cairo_glyph_t *glyphs, -- int num_glyphs, -- cairo_region_t *clip_region, -- int *remaining_glyphs); -- - cairo_int_status_t - _cairo_dwrite_load_truetype_table(void *scaled_font, - unsigned long tag, -@@ -193,33 +179,18 @@ const cairo_scaled_font_backend_t _cairo - CAIRO_FONT_TYPE_DWRITE, - _cairo_dwrite_scaled_font_fini, - _cairo_dwrite_scaled_glyph_init, -- NULL, -+ NULL, /* text_to_glyphs */ - _cairo_dwrite_ucs4_to_index, -- _cairo_dwrite_scaled_show_glyphs, - _cairo_dwrite_load_truetype_table, -- NULL, -+ NULL, /* index_to_ucs4 */ -+ NULL, /* is_synthetic */ -+ NULL, /* index_to_glyph_name */ -+ NULL, /* load_type1_data */ -+ NULL, /* has_color_glyphs */ - }; - - /* Helper conversion functions */ - --/** -- * Get a D2D matrix from a cairo matrix. Note that D2D uses row vectors where cairo -- * uses column vectors. Hence the transposition. -- * -- * \param Cairo matrix -- * \return D2D matrix -- */ --static D2D1::Matrix3x2F --_cairo_d2d_matrix_from_matrix(const cairo_matrix_t *matrix) --{ -- return D2D1::Matrix3x2F((FLOAT)matrix->xx, -- (FLOAT)matrix->yx, -- (FLOAT)matrix->xy, -- (FLOAT)matrix->yy, -- (FLOAT)matrix->x0, -- (FLOAT)matrix->y0); --} -- - - /** - * Get a DirectWrite matrix from a cairo matrix. Note that DirectWrite uses row -@@ -316,7 +287,7 @@ static cairo_status_t - return CAIRO_STATUS_SUCCESS; - } - --static void -+static cairo_bool_t - _cairo_dwrite_font_face_destroy (void *font_face) - { - cairo_dwrite_font_face_t *dwrite_font_face = static_cast<cairo_dwrite_font_face_t*>(font_face); -@@ -324,6 +295,7 @@ static void - dwrite_font_face->dwriteface->Release(); - if (dwrite_font_face->font) - dwrite_font_face->font->Release(); -+ return TRUE; - } - - -@@ -507,7 +479,6 @@ static cairo_status_t - dwriteFont->antialias_mode = options->antialias; - } - -- dwriteFont->manual_show_glyphs_allowed = TRUE; - dwriteFont->rendering_mode = - default_quality == CAIRO_ANTIALIAS_SUBPIXEL ? - cairo_dwrite_scaled_font_t::TEXT_RENDERING_NORMAL : cairo_dwrite_scaled_font_t::TEXT_RENDERING_NO_CLEARTYPE; -@@ -562,162 +533,6 @@ unsigned long - return index; - } - --cairo_warn cairo_int_status_t --_cairo_dwrite_scaled_show_glyphs(void *scaled_font, -- cairo_operator_t op, -- const cairo_pattern_t *pattern, -- cairo_surface_t *generic_surface, -- int source_x, -- int source_y, -- int dest_x, -- int dest_y, -- unsigned int width, -- unsigned int height, -- cairo_glyph_t *glyphs, -- int num_glyphs, -- cairo_region_t *clip_region, -- int *remaining_glyphs) --{ -- cairo_win32_surface_t *surface = (cairo_win32_surface_t *)generic_surface; -- cairo_int_status_t status; -- -- if (width == 0 || height == 0) -- return (cairo_int_status_t)CAIRO_STATUS_SUCCESS; -- -- if (_cairo_surface_is_win32 (generic_surface) && -- surface->format == CAIRO_FORMAT_RGB24 && -- op == CAIRO_OPERATOR_OVER) { -- -- //XXX: we need to set the clip region here -- -- status = (cairo_int_status_t)_cairo_dwrite_show_glyphs_on_surface (surface, op, pattern, -- glyphs, num_glyphs, -- (cairo_scaled_font_t*)scaled_font, NULL); -- -- return status; -- } else { -- cairo_dwrite_scaled_font_t *dwritesf = -- static_cast<cairo_dwrite_scaled_font_t*>(scaled_font); -- BOOL transform = FALSE; -- -- AutoDWriteGlyphRun run; -- run.allocate(num_glyphs); -- UINT16 *indices = const_cast<UINT16*>(run.glyphIndices); -- FLOAT *advances = const_cast<FLOAT*>(run.glyphAdvances); -- DWRITE_GLYPH_OFFSET *offsets = const_cast<DWRITE_GLYPH_OFFSET*>(run.glyphOffsets); -- -- run.bidiLevel = 0; -- run.fontFace = ((cairo_dwrite_font_face_t*)dwritesf->base.font_face)->dwriteface; -- run.isSideways = FALSE; -- IDWriteGlyphRunAnalysis *analysis; -- -- if (dwritesf->mat.xy == 0 && dwritesf->mat.yx == 0 && -- dwritesf->mat.xx == dwritesf->base.font_matrix.xx && -- dwritesf->mat.yy == dwritesf->base.font_matrix.yy) { -- -- for (int i = 0; i < num_glyphs; i++) { -- indices[i] = (WORD) glyphs[i].index; -- // Since we will multiply by our ctm matrix later for rotation effects -- // and such, adjust positions by the inverse matrix now. -- offsets[i].ascenderOffset = (FLOAT)dest_y - (FLOAT)glyphs[i].y; -- offsets[i].advanceOffset = (FLOAT)glyphs[i].x - dest_x; -- advances[i] = 0.0; -- } -- run.fontEmSize = (FLOAT)dwritesf->base.font_matrix.yy; -- } else { -- transform = TRUE; -- -- for (int i = 0; i < num_glyphs; i++) { -- indices[i] = (WORD) glyphs[i].index; -- double x = glyphs[i].x - dest_x; -- double y = glyphs[i].y - dest_y; -- cairo_matrix_transform_point(&dwritesf->mat_inverse, &x, &y); -- // Since we will multiply by our ctm matrix later for rotation effects -- // and such, adjust positions by the inverse matrix now. -- offsets[i].ascenderOffset = -(FLOAT)y; -- offsets[i].advanceOffset = (FLOAT)x; -- advances[i] = 0.0; -- } -- run.fontEmSize = 1.0f; -- } -- -- HRESULT hr; -- if (!transform) { -- hr = DWriteFactory::Instance()->CreateGlyphRunAnalysis(&run, -- 1.0f, -- NULL, -- DWRITE_RENDERING_MODE_CLEARTYPE_NATURAL_SYMMETRIC, -- DWRITE_MEASURING_MODE_NATURAL, -- 0, -- 0, -- &analysis); -- } else { -- DWRITE_MATRIX dwmatrix = _cairo_dwrite_matrix_from_matrix(&dwritesf->mat); -- hr = DWriteFactory::Instance()->CreateGlyphRunAnalysis(&run, -- 1.0f, -- &dwmatrix, -- DWRITE_RENDERING_MODE_CLEARTYPE_NATURAL_SYMMETRIC, -- DWRITE_MEASURING_MODE_NATURAL, -- 0, -- 0, -- &analysis); -- } -- -- if (FAILED(hr) || !analysis) { -- return CAIRO_INT_STATUS_UNSUPPORTED; -- } -- -- RECT r; -- r.left = 0; -- r.top = 0; -- r.right = width; -- r.bottom = height; -- -- BYTE *surface = new BYTE[width * height * 3]; -- -- analysis->CreateAlphaTexture(DWRITE_TEXTURE_CLEARTYPE_3x1, &r, surface, width * height * 3); -- -- cairo_image_surface_t *mask_surface = -- (cairo_image_surface_t*)cairo_image_surface_create(CAIRO_FORMAT_ARGB32, width, height); -- -- cairo_surface_flush(&mask_surface->base); -- -- for (unsigned int y = 0; y < height; y++) { -- for (unsigned int x = 0; x < width; x++) { -- mask_surface->data[y * mask_surface->stride + x * 4] = surface[y * width * 3 + x * 3 + 1]; -- mask_surface->data[y * mask_surface->stride + x * 4 + 1] = surface[y * width * 3 + x * 3 + 1]; -- mask_surface->data[y * mask_surface->stride + x * 4 + 2] = surface[y * width * 3 + x * 3 + 1]; -- mask_surface->data[y * mask_surface->stride + x * 4 + 3] = surface[y * width * 3 + x * 3 + 1]; -- } -- } -- cairo_surface_mark_dirty(&mask_surface->base); -- -- pixman_image_set_component_alpha(mask_surface->pixman_image, 1); -- -- cairo_surface_pattern_t mask; -- _cairo_pattern_init_for_surface (&mask, &mask_surface->base); -- -- status = (cairo_int_status_t)_cairo_surface_composite (op, pattern, -- &mask.base, -- generic_surface, -- source_x, source_y, -- 0, 0, -- dest_x, dest_y, -- width, height, -- clip_region); -- -- _cairo_pattern_fini (&mask.base); -- -- analysis->Release(); -- delete [] surface; -- -- cairo_surface_destroy (&mask_surface->base); -- *remaining_glyphs = 0; -- -- return (cairo_int_status_t)CAIRO_STATUS_SUCCESS; -- } --} -- - /* cairo_dwrite_scaled_glyph_init helper function bodies */ - cairo_int_status_t - _cairo_dwrite_scaled_font_init_glyph_metrics(cairo_dwrite_scaled_font_t *scaled_font, -@@ -906,37 +721,40 @@ cairo_int_status_t - return CAIRO_INT_STATUS_SUCCESS; - } - --/* Helper function also stolen from cairo-win32-font.c */ -+/* Helper function adapted from _compute_mask in cairo-win32-font.c */ - - /* Compute an alpha-mask from a monochrome RGB24 image - */ - static cairo_surface_t * --_compute_a8_mask (cairo_win32_surface_t *mask_surface) -+_compute_a8_mask (cairo_surface_t *surface) - { -- cairo_image_surface_t *image24 = (cairo_image_surface_t *)mask_surface->image; -- cairo_image_surface_t *image8; -+ cairo_image_surface_t *glyph; -+ cairo_image_surface_t *mask; - int i, j; - -- if (image24->base.status) -- return cairo_surface_reference (&image24->base); -+ glyph = (cairo_image_surface_t *)cairo_surface_map_to_image (surface, NULL); -+ if (unlikely (glyph->base.status)) -+ return &glyph->base; - -- image8 = (cairo_image_surface_t *)cairo_image_surface_create (CAIRO_FORMAT_A8, -- image24->width, image24->height); -- if (image8->base.status) -- return &image8->base; -+ /* No quality param, just use the non-ClearType path */ - -- for (i = 0; i < image24->height; i++) { -- uint32_t *p = (uint32_t *) (image24->data + i * image24->stride); -- unsigned char *q = (unsigned char *) (image8->data + i * image8->stride); -+ /* Compute an alpha-mask by using the green channel of a (presumed monochrome) -+ * RGB24 image. -+ */ -+ mask = (cairo_image_surface_t *) -+ cairo_image_surface_create (CAIRO_FORMAT_A8, glyph->width, glyph->height); -+ if (likely (mask->base.status == CAIRO_STATUS_SUCCESS)) { -+ for (i = 0; i < glyph->height; i++) { -+ uint32_t *p = (uint32_t *) (glyph->data + i * glyph->stride); -+ uint8_t *q = (uint8_t *) (mask->data + i * mask->stride); - -- for (j = 0; j < image24->width; j++) { -- *q = 255 - ((*p & 0x0000ff00) >> 8); -- p++; -- q++; -- } -+ for (j = 0; j < glyph->width; j++) -+ *q++ = 255 - ((*p++ & 0x0000ff00) >> 8); -+ } - } - -- return &image8->base; -+ cairo_surface_unmap_image (surface, &glyph->base); -+ return &mask->base; - } - - cairo_int_status_t -@@ -1017,7 +835,7 @@ cairo_int_status_t - - GdiFlush(); - -- image = _compute_a8_mask (surface); -+ image = _compute_a8_mask (&surface->base); - status = (cairo_int_status_t)image->status; - if (status) - goto FAIL; -@@ -1091,13 +909,6 @@ cairo_dwrite_font_face_create_for_dwrite - } - - void --cairo_dwrite_scaled_font_allow_manual_show_glyphs(cairo_scaled_font_t *dwrite_scaled_font, cairo_bool_t allowed) --{ -- cairo_dwrite_scaled_font_t *font = reinterpret_cast<cairo_dwrite_scaled_font_t*>(dwrite_scaled_font); -- font->manual_show_glyphs_allowed = allowed; --} -- --void - cairo_dwrite_scaled_font_set_force_GDI_classic(cairo_scaled_font_t *dwrite_scaled_font, cairo_bool_t force) - { - cairo_dwrite_scaled_font_t *font = reinterpret_cast<cairo_dwrite_scaled_font_t*>(dwrite_scaled_font); -@@ -1299,20 +1110,11 @@ cairo_int_status_t - - /* If we have a fallback mask clip set on the dst, we have - * to go through the fallback path */ -- if (clip != NULL) { -- if ((dst->flags & CAIRO_WIN32_SURFACE_FOR_PRINTING) == 0) { -- cairo_region_t *clip_region; -- cairo_int_status_t status; -- -- status = _cairo_clip_get_region (clip, &clip_region); -- assert (status != CAIRO_INT_STATUS_NOTHING_TO_DO); -- if (status) -- return status; -- -- _cairo_win32_surface_set_clip_region (dst, clip_region); -- } -- } else { -- _cairo_win32_surface_set_clip_region (surface, NULL); -+ if (!_cairo_surface_is_win32_printing (&dst->base)) { -+ if (clip != NULL) -+ _cairo_win32_display_surface_set_clip (to_win32_display_surface (dst), clip); -+ else -+ _cairo_win32_display_surface_unset_clip (to_win32_display_surface (dst)); - } - - /* It is vital that dx values for dxy_buf are calculated from the delta of -diff --git a/gfx/cairo/cairo/src/win32/cairo-dwrite-private.h b/gfx/cairo/cairo/src/win32/cairo-dwrite-private.h ---- a/gfx/cairo/cairo/src/win32/cairo-dwrite-private.h -+++ b/gfx/cairo/cairo/src/win32/cairo-dwrite-private.h -@@ -50,7 +50,6 @@ struct _cairo_dwrite_scaled_font { - cairo_matrix_t mat_inverse; - cairo_antialias_t antialias_mode; - DWRITE_MEASURING_MODE measuring_mode; -- cairo_bool_t manual_show_glyphs_allowed; - enum TextRenderingState { - TEXT_RENDERING_UNINITIALIZED, - TEXT_RENDERING_NO_CLEARTYPE, -diff --git a/gfx/cairo/cairo/src/win32/cairo-win32-font.c b/gfx/cairo/cairo/src/win32/cairo-win32-font.c ---- a/gfx/cairo/cairo/src/win32/cairo-win32-font.c -+++ b/gfx/cairo/cairo/src/win32/cairo-win32-font.c -@@ -286,8 +286,8 @@ static cairo_bool_t - version_info.dwMinorVersion >= 1)); /* XP or newer */ - } - --static BYTE --_get_system_quality (void) -+BYTE -+cairo_win32_get_system_text_quality (void) - { - BOOL font_smoothing; - UINT smoothing_type; -@@ -354,7 +354,7 @@ static cairo_status_t - * here is the hint_metrics options. - */ - if (options->antialias == CAIRO_ANTIALIAS_DEFAULT) -- f->quality = _get_system_quality (); -+ f->quality = cairo_win32_get_system_text_quality (); - else { - switch (options->antialias) { - case CAIRO_ANTIALIAS_NONE: -diff --git a/gfx/cairo/cairo/src/win32/cairo-win32-printing-surface.c b/gfx/cairo/cairo/src/win32/cairo-win32-printing-surface.c ---- a/gfx/cairo/cairo/src/win32/cairo-win32-printing-surface.c -+++ b/gfx/cairo/cairo/src/win32/cairo-win32-printing-surface.c -@@ -244,7 +244,7 @@ static cairo_status_t - case CAIRO_PATTERN_TYPE_MESH: - default: - ASSERT_NOT_REACHED; -- break; -+ return CAIRO_INT_STATUS_UNSUPPORTED; - } - - _cairo_pattern_init_for_surface (image_pattern, &image->base); -@@ -1808,6 +1808,7 @@ static cairo_int_status_t - cairo_solid_pattern_t clear; - cairo_composite_rectangles_t extents; - cairo_bool_t overlap; -+ cairo_scaled_font_t *local_scaled_font = NULL; - - status = _cairo_composite_rectangles_init_for_glyphs (&extents, - &surface->win32.base, -@@ -1851,6 +1852,13 @@ static cairo_int_status_t - } - #endif - -+#if CAIRO_HAS_DWRITE_FONT -+ if (cairo_scaled_font_get_type (scaled_font) == CAIRO_FONT_TYPE_DWRITE) { -+ status = _cairo_win32_printing_surface_analyze_operation (surface, op, source, &extents.bounded); -+ goto cleanup_composite; -+ } -+#endif -+ - /* For non win32 fonts we need to check that each glyph has a - * path available. If a path is not available, - * _cairo_scaled_glyph_lookup() will return -@@ -1890,6 +1898,23 @@ static cairo_int_status_t - source = opaque; - } - -+#if CAIRO_HAS_DWRITE_FONT -+ /* For a printer, the dwrite path is not desirable as it goes through the -+ * bitmap-blitting GDI interop route. Better to create a win32 (GDI) font -+ * so that ExtTextOut can be used, giving the printer driver the chance -+ * to do the right thing with the text. -+ */ -+ if (cairo_scaled_font_get_type (scaled_font) == CAIRO_FONT_TYPE_DWRITE) { -+ status = _cairo_dwrite_scaled_font_create_win32_scaled_font (scaled_font, &local_scaled_font); -+ if (status == CAIRO_STATUS_SUCCESS) { -+ scaled_font = local_scaled_font; -+ } else { -+ /* Reset status; we'll fall back to drawing glyphs as paths */ -+ status = CAIRO_STATUS_SUCCESS; -+ } -+ } -+#endif -+ - #if CAIRO_HAS_WIN32_FONT - if (cairo_scaled_font_get_type (scaled_font) == CAIRO_FONT_TYPE_WIN32 && - source->type == CAIRO_PATTERN_TYPE_SOLID) -@@ -1948,6 +1973,10 @@ static cairo_int_status_t - - cleanup_composite: - _cairo_composite_rectangles_fini (&extents); -+ -+ if (local_scaled_font) -+ cairo_scaled_font_destroy (local_scaled_font); -+ - return status; - } - -@@ -2181,6 +2210,12 @@ cairo_win32_printing_surface_create (HDC - return paginated; - } - -+cairo_bool_t -+_cairo_surface_is_win32_printing (const cairo_surface_t *surface) -+{ -+ return surface->backend && surface->backend->type == CAIRO_SURFACE_TYPE_WIN32_PRINTING; -+} -+ - static const cairo_surface_backend_t cairo_win32_printing_surface_backend = { - CAIRO_SURFACE_TYPE_WIN32_PRINTING, - _cairo_win32_printing_surface_finish, -diff --git a/gfx/cairo/cairo/src/win32/cairo-win32-private.h b/gfx/cairo/cairo/src/win32/cairo-win32-private.h ---- a/gfx/cairo/cairo/src/win32/cairo-win32-private.h -+++ b/gfx/cairo/cairo/src/win32/cairo-win32-private.h -@@ -53,6 +53,8 @@ - - #define WIN32_FONT_LOGICAL_SCALE 32 - -+CAIRO_BEGIN_DECLS -+ - /* Surface DC flag values */ - enum { - /* If this is a surface created for printing or not */ -@@ -199,6 +201,12 @@ const cairo_compositor_t * - cairo_status_t - _cairo_win32_print_gdi_error (const char *context); - -+cairo_bool_t -+_cairo_surface_is_win32 (const cairo_surface_t *surface); -+ -+cairo_bool_t -+_cairo_surface_is_win32_printing (const cairo_surface_t *surface); -+ - cairo_private void - _cairo_win32_display_surface_discard_fallback (cairo_win32_display_surface_t *surface); - -@@ -245,4 +253,23 @@ cairo_bool_t - cairo_bool_t - _cairo_win32_scaled_font_is_bitmap (cairo_scaled_font_t *scaled_font); - -+#ifdef CAIRO_HAS_DWRITE_FONT -+ -+cairo_int_status_t -+_cairo_dwrite_show_glyphs_on_surface (void *surface, -+ cairo_operator_t op, -+ const cairo_pattern_t *source, -+ cairo_glyph_t *glyphs, -+ int num_glyphs, -+ cairo_scaled_font_t *scaled_font, -+ cairo_clip_t *clip); -+ -+cairo_int_status_t -+_cairo_dwrite_scaled_font_create_win32_scaled_font (cairo_scaled_font_t *scaled_font, -+ cairo_scaled_font_t **new_font); -+ -+#endif /* CAIRO_HAS_DWRITE_FONT */ -+ -+CAIRO_END_DECLS -+ - #endif /* CAIRO_WIN32_PRIVATE_H */ -diff --git a/gfx/cairo/cairo/src/win32/cairo-win32-surface.c b/gfx/cairo/cairo/src/win32/cairo-win32-surface.c ---- a/gfx/cairo/cairo/src/win32/cairo-win32-surface.c -+++ b/gfx/cairo/cairo/src/win32/cairo-win32-surface.c -@@ -48,6 +48,7 @@ - - #include "cairoint.h" - -+#include "cairo-backend-private.h" - #include "cairo-default-context-private.h" - #include "cairo-error-private.h" - #include "cairo-image-surface-private.h" -@@ -170,6 +171,48 @@ cairo_win32_surface_get_dc (cairo_surfac - return NULL; - } - -+HDC -+cairo_win32_get_dc_with_clip (cairo_t *cr) -+{ -+ cairo_surface_t *surface = cairo_get_target (cr); -+ if (cr->backend->type == CAIRO_TYPE_DEFAULT) { -+ cairo_default_context_t *c = (cairo_default_context_t *) cr; -+ cairo_clip_t *clip = _cairo_clip_copy (_cairo_gstate_get_clip (c->gstate)); -+ if (_cairo_surface_is_win32 (surface)) { -+ cairo_win32_display_surface_t *winsurf = (cairo_win32_display_surface_t *) surface; -+ -+ _cairo_win32_display_surface_set_clip (winsurf, clip); -+ -+ _cairo_clip_destroy (clip); -+ return winsurf->win32.dc; -+ } -+ -+ if (_cairo_surface_is_paginated (surface)) { -+ cairo_surface_t *target; -+ -+ target = _cairo_paginated_surface_get_target (surface); -+ -+#ifndef CAIRO_OMIT_WIN32_PRINTING -+ if (_cairo_surface_is_win32_printing (target)) { -+ cairo_status_t status; -+ cairo_win32_printing_surface_t *psurf = (cairo_win32_printing_surface_t *) target; -+ -+ status = _cairo_surface_clipper_set_clip (&psurf->clipper, clip); -+ -+ _cairo_clip_destroy (clip); -+ -+ if (status) -+ return NULL; -+ -+ return psurf->win32.dc; -+ } -+#endif -+ } -+ _cairo_clip_destroy (clip); -+ } -+ return NULL; -+} -+ - /** - * _cairo_surface_is_win32: - * @surface: a #cairo_surface_t -@@ -178,7 +221,7 @@ cairo_win32_surface_get_dc (cairo_surfac - * - * Return value: %TRUE if the surface is an win32 surface - **/ --static inline cairo_bool_t -+cairo_bool_t - _cairo_surface_is_win32 (const cairo_surface_t *surface) - { - /* _cairo_surface_nil sets a NULL backend so be safe */ -@@ -219,6 +262,16 @@ cairo_int_status_t - cairo_scaled_font_t *scaled_font, - cairo_bool_t glyph_indexing) - { -+#if CAIRO_HAS_DWRITE_FONT -+ if (scaled_font->backend->type == CAIRO_FONT_TYPE_DWRITE) { -+ if (!glyph_indexing) return CAIRO_INT_STATUS_UNSUPPORTED; -+ -+ // FIXME: fake values for params that aren't currently passed in here -+ cairo_operator_t op = CAIRO_OPERATOR_SOURCE; -+ cairo_clip_t *clip = NULL; -+ return _cairo_dwrite_show_glyphs_on_surface (dst, op, source, glyphs, num_glyphs, scaled_font, clip /* , glyph_indexing */ ); -+ } -+#endif - #if CAIRO_HAS_WIN32_FONT - WORD glyph_buf_stack[STACK_GLYPH_SIZE]; - WORD *glyph_buf = glyph_buf_stack; -@@ -335,3 +388,18 @@ cairo_int_status_t - #endif - } - #undef STACK_GLYPH_SIZE -+ -+cairo_status_t -+cairo_win32_surface_get_size (const cairo_surface_t *surface, int *width, int *height) -+{ -+ if (surface->type != CAIRO_SURFACE_TYPE_WIN32) -+ return CAIRO_STATUS_SURFACE_TYPE_MISMATCH; -+ -+ const cairo_win32_surface_t *winsurface = (const cairo_win32_surface_t *) surface; -+ -+ *width = winsurface->extents.width; -+ *height = winsurface->extents.height; -+ -+ return CAIRO_STATUS_SUCCESS; -+} -+ diff --git a/gfx/cairo/09-quartz-surface-additions.patch b/gfx/cairo/09-quartz-surface-additions.patch index 104d453f4f..287a0dc9e0 100644 --- a/gfx/cairo/09-quartz-surface-additions.patch +++ b/gfx/cairo/09-quartz-surface-additions.patch @@ -1,22 +1,32 @@ -diff --git a/gfx/cairo/cairo/src/cairo-quartz-private.h b/gfx/cairo/cairo/src/cairo-quartz-private.h ---- a/gfx/cairo/cairo/src/cairo-quartz-private.h -+++ b/gfx/cairo/cairo/src/cairo-quartz-private.h -@@ -71,8 +71,11 @@ typedef struct cairo_quartz_surface { - cairo_surface_t *imageSurfaceEquiv; - - cairo_surface_clipper_t clipper; -+ - cairo_rectangle_int_t extents; - cairo_rectangle_int_t virtual_extents; -+ -+ cairo_bool_t ownsData; - } cairo_quartz_surface_t; - - typedef struct cairo_quartz_image_surface { +# HG changeset patch +# User Jonathan Kew <jkew@mozilla.com> +# Date 1713889662 -3600 +# Tue Apr 23 17:27:42 2024 +0100 +# Node ID fd010d43c6a9aabbffd9cba9d0f290996c052c65 +# Parent cf33e155ac6207c3903408de7341e0ac68be7474 +Bug 1892913 - patch 12 - Update and apply 09-quartz-surface-additions.patch + diff --git a/gfx/cairo/cairo/src/cairo-quartz-surface.c b/gfx/cairo/cairo/src/cairo-quartz-surface.c --- a/gfx/cairo/cairo/src/cairo-quartz-surface.c +++ b/gfx/cairo/cairo/src/cairo-quartz-surface.c -@@ -1520,6 +1520,103 @@ static cairo_int_status_t +@@ -409,6 +409,7 @@ static CGBlendMode + default: + ASSERT_NOT_REACHED; + } ++ return kCGBlendModeNormal; /* unreached */ + } + + static cairo_int_status_t +@@ -998,7 +999,7 @@ static cairo_int_status_t + _cairo_surface_get_extents (&surface->base, &pattern_extents); + } + +- if (source->extend == CAIRO_EXTEND_NONE) { ++ if (source->extend == CAIRO_EXTEND_NONE || source->extend == CAIRO_EXTEND_PAD) { + int x, y; + + if (op == CAIRO_OPERATOR_SOURCE && +@@ -1402,6 +1403,97 @@ static cairo_int_status_t /* @@ -31,17 +41,11 @@ diff --git a/gfx/cairo/cairo/src/cairo-quartz-surface.c b/gfx/cairo/cairo/src/ca + unsigned char *imageData; + cairo_image_surface_t *isurf; + -+ if (IS_EMPTY(surface)) { ++ if (_cairo_quartz_is_zero_surface (&surface->base)) { + *image_out = (cairo_image_surface_t*) cairo_image_surface_create (CAIRO_FORMAT_ARGB32, 0, 0); + return CAIRO_STATUS_SUCCESS; + } + -+ if (surface->imageSurfaceEquiv) { -+ CGContextFlush(surface->cgContext); -+ *image_out = (cairo_image_surface_t*) cairo_surface_reference(surface->imageSurfaceEquiv); -+ return CAIRO_STATUS_SUCCESS; -+ } -+ + if (_cairo_quartz_is_cgcontext_bitmap_context(surface->cgContext)) { + unsigned int stride; + unsigned int bitinfo; @@ -120,160 +124,11 @@ diff --git a/gfx/cairo/cairo/src/cairo-quartz-surface.c b/gfx/cairo/cairo/src/ca * Cairo surface backend implementations */ -@@ -1542,11 +1639,14 @@ static cairo_status_t - surface->cgContext = NULL; - - if (surface->imageSurfaceEquiv) { -+ if (surface->ownsData) -+ _cairo_image_surface_assume_ownership_of_data (surface->imageSurfaceEquiv); - cairo_surface_destroy (surface->imageSurfaceEquiv); - surface->imageSurfaceEquiv = NULL; -+ } else if (surface->imageData && surface->ownsData) { -+ free (surface->imageData); - } - -- free (surface->imageData); - surface->imageData = NULL; - +@@ -2478,3 +2570,15 @@ cairo_status_t + CGImageRelease (image); return CAIRO_STATUS_SUCCESS; -@@ -2298,6 +2398,8 @@ cairo_quartz_surface_t * - surface->cgContext = cgContext; - surface->cgContextBaseCTM = CGContextGetCTM (cgContext); - -+ surface->ownsData = TRUE; -+ - return surface; } - -@@ -2452,10 +2554,124 @@ cairo_quartz_surface_create (cairo_forma - surf->imageData = imageData; - surf->imageSurfaceEquiv = cairo_image_surface_create_for_data (imageData, format, width, height, stride); - -+ // We created this data, so we can delete it. -+ surf->ownsData = TRUE; + - return &surf->base; - } - - /** -+ * cairo_quartz_surface_create_for_data -+ * @data: a pointer to a buffer supplied by the application in which -+ * to write contents. This pointer must be suitably aligned for any -+ * kind of variable, (for example, a pointer returned by malloc). -+ * @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 Quartz surface backed by a CGBitmap. The surface is -+ * created using the Device RGB (or Device Gray, for A8) color space. -+ * All Cairo operations, including those that require software -+ * rendering, will succeed on this surface. -+ * -+ * Return value: the newly created surface. -+ * -+ * Since: 1.12 [Mozilla addition] -+ **/ -+cairo_surface_t * -+cairo_quartz_surface_create_for_data (unsigned char *data, -+ cairo_format_t format, -+ unsigned int width, -+ unsigned int height, -+ unsigned int stride) -+{ -+ cairo_quartz_surface_t *surf; -+ CGContextRef cgc; -+ CGColorSpaceRef cgColorspace; -+ CGBitmapInfo bitinfo; -+ void *imageData = data; -+ int bitsPerComponent; -+ unsigned int i; -+ -+ // verify width and height of surface -+ if (!_cairo_quartz_verify_surface_size(width, height)) -+ return _cairo_surface_create_in_error (_cairo_error (CAIRO_STATUS_INVALID_SIZE)); -+ -+ if (width == 0 || height == 0) { -+ return (cairo_surface_t*) _cairo_quartz_surface_create_internal (NULL, _cairo_content_from_format (format), -+ width, height); -+ } -+ -+ if (format == CAIRO_FORMAT_ARGB32 || -+ format == CAIRO_FORMAT_RGB24) -+ { -+ cgColorspace = CGColorSpaceCreateDeviceRGB(); -+ bitinfo = kCGBitmapByteOrder32Host; -+ if (format == CAIRO_FORMAT_ARGB32) -+ bitinfo |= kCGImageAlphaPremultipliedFirst; -+ else -+ bitinfo |= kCGImageAlphaNoneSkipFirst; -+ bitsPerComponent = 8; -+ } else if (format == CAIRO_FORMAT_A8) { -+ cgColorspace = NULL; -+ bitinfo = kCGImageAlphaOnly; -+ bitsPerComponent = 8; -+ } else if (format == CAIRO_FORMAT_A1) { -+ /* I don't think we can usefully support this, as defined by -+ * cairo_format_t -- these are 1-bit pixels stored in 32-bit -+ * quantities. -+ */ -+ return _cairo_surface_create_in_error (_cairo_error (CAIRO_STATUS_INVALID_FORMAT)); -+ } else { -+ return _cairo_surface_create_in_error (_cairo_error (CAIRO_STATUS_INVALID_FORMAT)); -+ } -+ -+ cgc = CGBitmapContextCreate (imageData, -+ width, -+ height, -+ bitsPerComponent, -+ stride, -+ cgColorspace, -+ bitinfo); -+ CGColorSpaceRelease (cgColorspace); -+ -+ if (!cgc) { -+ free (imageData); -+ return _cairo_surface_create_in_error (_cairo_error (CAIRO_STATUS_NO_MEMORY)); -+ } -+ -+ /* flip the Y axis */ -+ CGContextTranslateCTM (cgc, 0.0, height); -+ CGContextScaleCTM (cgc, 1.0, -1.0); -+ -+ surf = _cairo_quartz_surface_create_internal (cgc, _cairo_content_from_format (format), -+ width, height); -+ if (surf->base.status) { -+ CGContextRelease (cgc); -+ free (imageData); -+ // create_internal will have set an error -+ return (cairo_surface_t*) surf; -+ } -+ -+ surf->imageData = imageData; -+ -+ cairo_surface_t* tmpImageSurfaceEquiv = -+ cairo_image_surface_create_for_data (imageData, format, -+ width, height, stride); -+ -+ if (cairo_surface_status (tmpImageSurfaceEquiv)) { -+ // Tried & failed to create an imageSurfaceEquiv! -+ cairo_surface_destroy (tmpImageSurfaceEquiv); -+ surf->imageSurfaceEquiv = NULL; -+ } else { -+ surf->imageSurfaceEquiv = tmpImageSurfaceEquiv; -+ surf->ownsData = FALSE; -+ } -+ -+ return (cairo_surface_t *) surf; -+} -+ -+/** - * cairo_quartz_surface_get_cg_context: - * @surface: the Cairo Quartz surface - * -@@ -2497,6 +2713,18 @@ cairo_bool_t - return surface->backend == &cairo_quartz_surface_backend; - } - +cairo_surface_t * +cairo_quartz_surface_get_image (cairo_surface_t *surface) +{ @@ -285,24 +140,10 @@ diff --git a/gfx/cairo/cairo/src/cairo-quartz-surface.c b/gfx/cairo/cairo/src/ca + + return (cairo_surface_t *)image; +} -+ - /* Debug stuff */ - - #ifdef QUARTZ_DEBUG diff --git a/gfx/cairo/cairo/src/cairo-quartz.h b/gfx/cairo/cairo/src/cairo-quartz.h --- a/gfx/cairo/cairo/src/cairo-quartz.h +++ b/gfx/cairo/cairo/src/cairo-quartz.h -@@ -54,9 +54,19 @@ cairo_quartz_surface_create_for_cg_conte - unsigned int width, - unsigned int height); - -+cairo_surface_t * -+cairo_quartz_surface_create_for_data (unsigned char *data, -+ cairo_format_t format, -+ unsigned int width, -+ unsigned int height, -+ unsigned int stride); -+ +@@ -57,6 +57,9 @@ cairo_quartz_surface_create_for_cg_conte cairo_public CGContextRef cairo_quartz_surface_get_cg_context (cairo_surface_t *surface); diff --git a/gfx/cairo/10-zero-sized-image.patch b/gfx/cairo/10-zero-sized-image.patch deleted file mode 100644 index 887341566a..0000000000 --- a/gfx/cairo/10-zero-sized-image.patch +++ /dev/null @@ -1,13 +0,0 @@ -diff --git a/gfx/cairo/cairo/src/cairo-image-surface.c b/gfx/cairo/cairo/src/cairo-image-surface.c ---- a/gfx/cairo/cairo/src/cairo-image-surface.c -+++ b/gfx/cairo/cairo/src/cairo-image-surface.c -@@ -1243,6 +1243,9 @@ static cairo_image_color_t - int x, y; - cairo_image_color_t color; - -+ if (image->width == 0 || image->height == 0) -+ return CAIRO_IMAGE_IS_MONOCHROME; -+ - if (image->format == CAIRO_FORMAT_A1) - return CAIRO_IMAGE_IS_MONOCHROME; - diff --git a/gfx/cairo/11-quartz-surface-tags.patch b/gfx/cairo/11-quartz-surface-tags.patch index 7f73d388ea..b66efcc496 100644 --- a/gfx/cairo/11-quartz-surface-tags.patch +++ b/gfx/cairo/11-quartz-surface-tags.patch @@ -1,3 +1,11 @@ +# HG changeset patch +# User Jonathan Kew <jkew@mozilla.com> +# Date 1713889788 -3600 +# Tue Apr 23 17:29:48 2024 +0100 +# Node ID 0421354d816b993767e2409c425aaa95a5291a26 +# Parent 2a04d0b05957b4db2cd9e97f29d28565badca201 +Bug 1892913 - patch 13 - Apply 11-quartz-surface-tags.patch + diff --git a/gfx/cairo/cairo/src/cairo-quartz-surface.c b/gfx/cairo/cairo/src/cairo-quartz-surface.c --- a/gfx/cairo/cairo/src/cairo-quartz-surface.c +++ b/gfx/cairo/cairo/src/cairo-quartz-surface.c @@ -9,7 +17,7 @@ diff --git a/gfx/cairo/cairo/src/cairo-quartz-surface.c b/gfx/cairo/cairo/src/ca #include <dlfcn.h> -@@ -2313,6 +2314,70 @@ static cairo_status_t +@@ -2190,6 +2191,70 @@ static cairo_status_t return CAIRO_STATUS_SUCCESS; } @@ -79,15 +87,12 @@ diff --git a/gfx/cairo/cairo/src/cairo-quartz-surface.c b/gfx/cairo/cairo/src/ca + // XXXtodo implement show_page; need to figure out how to handle begin/end - static const struct _cairo_surface_backend cairo_quartz_surface_backend = { -@@ -2346,6 +2411,11 @@ static const struct _cairo_surface_backe - _cairo_quartz_surface_fill, - NULL, /* fill-stroke */ - _cairo_quartz_surface_glyphs, -+ -+ NULL, /* has_show_text_glyphs */ -+ NULL, /* show_text_glyphs */ -+ NULL, /* get_supported_mime_types */ + static const cairo_surface_backend_t cairo_quartz_surface_backend = { +@@ -2226,7 +2291,7 @@ static const cairo_surface_backend_t cai + NULL, /* has_show_text_glyphs */ + NULL, /* show_text_glyphs */ + NULL, /* get_supported_mime_types */ +- NULL, /* tag */ + _cairo_quartz_surface_tag /* tag */ }; diff --git a/gfx/cairo/12-pdf-surface-typo.patch b/gfx/cairo/12-pdf-surface-typo.patch deleted file mode 100644 index 53bb47b967..0000000000 --- a/gfx/cairo/12-pdf-surface-typo.patch +++ /dev/null @@ -1,12 +0,0 @@ -diff --git a/gfx/cairo/cairo/src/cairo-pdf-surface.c b/gfx/cairo/cairo/src/cairo-pdf-surface.c ---- a/gfx/cairo/cairo/src/cairo-pdf-surface.c -+++ b/gfx/cairo/cairo/src/cairo-pdf-surface.c -@@ -7560,7 +7560,7 @@ static cairo_int_status_t - if (_cairo_surface_get_extents (surface_pattern->surface, &rec_extents)) { - if (_cairo_fixed_integer_ceil(box.p1.x) < rec_extents.x || - _cairo_fixed_integer_ceil(box.p1.y) < rec_extents.y || -- _cairo_fixed_integer_floor(box.p2.y) > rec_extents.x + rec_extents.width || -+ _cairo_fixed_integer_floor(box.p2.x) > rec_extents.x + rec_extents.width || - _cairo_fixed_integer_floor(box.p2.y) > rec_extents.y + rec_extents.height) - { - return CAIRO_INT_STATUS_UNSUPPORTED; diff --git a/gfx/cairo/12-quartz-named-destination.patch b/gfx/cairo/12-quartz-named-destination.patch new file mode 100644 index 0000000000..b750087bc9 --- /dev/null +++ b/gfx/cairo/12-quartz-named-destination.patch @@ -0,0 +1,166 @@ +# HG changeset patch +# User Jonathan Kew <jkew@mozilla.com> +# Date 1628081557 0 +# Wed Aug 04 12:52:37 2021 +0000 +# Node ID 2635200eb5ec6f6eff1ecd0fad1ef029f0b994af +# Parent 99c4916f4a924ede94aee9044fe3f753d2e2be2d +Bug 1892913 - patch 14 - Add cairo-quartz-surface named-destination support from bug 1722300 patch 3. + +diff --git a/gfx/cairo/cairo/src/cairo-quartz-surface.c b/gfx/cairo/cairo/src/cairo-quartz-surface.c +--- a/gfx/cairo/cairo/src/cairo-quartz-surface.c ++++ b/gfx/cairo/cairo/src/cairo-quartz-surface.c +@@ -2192,24 +2192,13 @@ static cairo_status_t + } + + static cairo_int_status_t +-_cairo_quartz_surface_tag (void *abstract_surface, +- cairo_bool_t begin, +- const char *tag_name, +- const char *attributes, +- const cairo_pattern_t *source, +- const cairo_stroke_style_t *style, +- const cairo_matrix_t *ctm, +- const cairo_matrix_t *ctm_inverse, +- const cairo_clip_t *clip) ++_cairo_quartz_surface_link (cairo_quartz_surface_t *surface, ++ cairo_bool_t begin, ++ const char *attributes) + { + cairo_link_attrs_t link_attrs; + cairo_int_status_t status = CAIRO_STATUS_SUCCESS; + int i, num_rects; +- cairo_quartz_surface_t *surface = (cairo_quartz_surface_t *) abstract_surface; +- +- /* Currently the only tag we support is "Link" */ +- if (strcmp (tag_name, "Link")) +- return CAIRO_INT_STATUS_UNSUPPORTED; + + /* We only process the 'begin' tag, and expect a rect attribute; + using the extents of the drawing operations enclosed by the begin/end +@@ -2223,11 +2212,24 @@ static cairo_int_status_t + + num_rects = _cairo_array_num_elements (&link_attrs.rects); + if (num_rects > 0) { +- CFURLRef url = CFURLCreateWithBytes (NULL, +- (const UInt8 *) link_attrs.uri, +- strlen (link_attrs.uri), +- kCFStringEncodingUTF8, +- NULL); ++ /* Create either a named destination or a URL, depending which is present ++ in the link attributes. */ ++ CFURLRef url = NULL; ++ CFStringRef name = NULL; ++ if (link_attrs.uri && *link_attrs.uri) ++ url = CFURLCreateWithBytes (NULL, ++ (const UInt8 *) link_attrs.uri, ++ strlen (link_attrs.uri), ++ kCFStringEncodingUTF8, ++ NULL); ++ else if (link_attrs.dest && *link_attrs.dest) ++ name = CFStringCreateWithBytes (kCFAllocatorDefault, ++ (const UInt8 *) link_attrs.dest, ++ strlen (link_attrs.dest), ++ kCFStringEncodingUTF8, ++ FALSE); ++ else /* silently ignore link that doesn't have a usable target */ ++ goto cleanup; + + for (i = 0; i < num_rects; i++) { + CGRect link_rect; +@@ -2241,12 +2243,19 @@ static cairo_int_status_t + rectf.width, + rectf.height); + +- CGPDFContextSetURLForRect (surface->cgContext, url, link_rect); ++ if (url) ++ CGPDFContextSetURLForRect (surface->cgContext, url, link_rect); ++ else ++ CGPDFContextSetDestinationForRect (surface->cgContext, name, link_rect); + } + +- CFRelease (url); ++ if (url) ++ CFRelease (url); ++ else ++ CFRelease (name); + } + ++cleanup: + _cairo_array_fini (&link_attrs.rects); + free (link_attrs.dest); + free (link_attrs.uri); +@@ -2255,6 +2264,74 @@ static cairo_int_status_t + return status; + } + ++static cairo_int_status_t ++_cairo_quartz_surface_dest (cairo_quartz_surface_t *surface, ++ cairo_bool_t begin, ++ const char *attributes) ++{ ++ cairo_dest_attrs_t dest_attrs; ++ cairo_int_status_t status = CAIRO_STATUS_SUCCESS; ++ double x = 0, y = 0; ++ ++ /* We only process the 'begin' tag, and expect 'x' and 'y' attributes. */ ++ if (!begin) ++ return status; ++ ++ status = _cairo_tag_parse_dest_attributes (attributes, &dest_attrs); ++ if (unlikely (status)) ++ return status; ++ ++ if (unlikely (!dest_attrs.name || !strlen (dest_attrs.name))) ++ goto cleanup; ++ ++ CFStringRef name = CFStringCreateWithBytes (kCFAllocatorDefault, ++ (const UInt8 *) dest_attrs.name, ++ strlen (dest_attrs.name), ++ kCFStringEncodingUTF8, ++ FALSE); ++ ++ if (dest_attrs.x_valid) ++ x = dest_attrs.x; ++ if (dest_attrs.y_valid) ++ y = dest_attrs.y; ++ ++ CGPDFContextAddDestinationAtPoint (surface->cgContext, ++ name, ++ CGPointMake (x, surface->extents.height - y)); ++ CFRelease (name); ++ ++cleanup: ++ free (dest_attrs.name); ++ ++ return status; ++} ++ ++static cairo_int_status_t ++_cairo_quartz_surface_tag (void *abstract_surface, ++ cairo_bool_t begin, ++ const char *tag_name, ++ const char *attributes, ++ const cairo_pattern_t *source, ++ const cairo_stroke_style_t *style, ++ const cairo_matrix_t *ctm, ++ const cairo_matrix_t *ctm_inverse, ++ const cairo_clip_t *clip) ++{ ++ cairo_link_attrs_t link_attrs; ++ int i, num_rects; ++ cairo_quartz_surface_t *surface = (cairo_quartz_surface_t *) abstract_surface; ++ ++ /* Currently the only tags we support are CAIRO_TAG_LINK and CAIRO_TAG_DEST */ ++ if (!strcmp (tag_name, CAIRO_TAG_LINK)) ++ return _cairo_quartz_surface_link (surface, begin, attributes); ++ ++ if (!strcmp (tag_name, CAIRO_TAG_DEST)) ++ return _cairo_quartz_surface_dest (surface, begin, attributes); ++ ++ /* Unknown tag names are silently ignored here. */ ++ return CAIRO_INT_STATUS_SUCCESS; ++} ++ + // XXXtodo implement show_page; need to figure out how to handle begin/end + + static const cairo_surface_backend_t cairo_quartz_surface_backend = { diff --git a/gfx/cairo/13-quartz-cglayer-surface.patch b/gfx/cairo/13-quartz-cglayer-surface.patch deleted file mode 100644 index f4edc5f364..0000000000 --- a/gfx/cairo/13-quartz-cglayer-surface.patch +++ /dev/null @@ -1,253 +0,0 @@ -diff --git a/gfx/cairo/cairo/src/cairo-quartz-private.h b/gfx/cairo/cairo/src/cairo-quartz-private.h ---- a/gfx/cairo/cairo/src/cairo-quartz-private.h -+++ b/gfx/cairo/cairo/src/cairo-quartz-private.h -@@ -55,7 +55,8 @@ typedef enum { - DO_DIRECT, - DO_SHADING, - DO_IMAGE, -- DO_TILED_IMAGE -+ DO_TILED_IMAGE, -+ DO_LAYER - } cairo_quartz_action_t; - - /* define CTFontRef for pre-10.5 SDKs */ -@@ -72,6 +73,11 @@ typedef struct cairo_quartz_surface { - - cairo_surface_clipper_t clipper; - -+ /** -+ * If non-null, this is the CGLayer for the surface. -+ */ -+ CGLayerRef cgLayer; -+ - cairo_rectangle_int_t extents; - cairo_rectangle_int_t virtual_extents; - -diff --git a/gfx/cairo/cairo/src/cairo-quartz-surface.c b/gfx/cairo/cairo/src/cairo-quartz-surface.c ---- a/gfx/cairo/cairo/src/cairo-quartz-surface.c -+++ b/gfx/cairo/cairo/src/cairo-quartz-surface.c -@@ -503,6 +503,7 @@ static CGBlendMode - default: - ASSERT_NOT_REACHED; - } -+ return kCGBlendModeNormal; /* just to silence clang warning [-Wreturn-type] */ - } - - static cairo_int_status_t -@@ -1065,7 +1066,7 @@ typedef struct { - /* Destination rect */ - CGRect rect; - -- /* Used with DO_SHADING, DO_IMAGE and DO_TILED_IMAGE */ -+ /* Used with DO_SHADING, DO_IMAGE, DO_TILED_IMAGE, DO_LAYER */ - CGAffineTransform transform; - - /* Used with DO_IMAGE and DO_TILED_IMAGE */ -@@ -1077,6 +1078,11 @@ typedef struct { - /* Temporary destination for unbounded operations */ - CGLayerRef layer; - CGRect clipRect; -+ -+ /* Source layer to be rendered when using DO_LAYER. -+ Unlike 'layer' above, this is not owned by the drawing state -+ but by the source surface. */ -+ CGLayerRef sourceLayer; - } cairo_quartz_drawing_state_t; - - /* -@@ -1253,7 +1259,9 @@ static cairo_int_status_t - } - - if (source->type == CAIRO_PATTERN_TYPE_SURFACE && -- (source->extend == CAIRO_EXTEND_NONE || (CGContextDrawTiledImagePtr && source->extend == CAIRO_EXTEND_REPEAT))) -+ (source->extend == CAIRO_EXTEND_NONE || -+ source->extend == CAIRO_EXTEND_PAD || -+ (CGContextDrawTiledImagePtr && source->extend == CAIRO_EXTEND_REPEAT))) - { - const cairo_surface_pattern_t *spat = (const cairo_surface_pattern_t *) source; - cairo_surface_t *pat_surf = spat->surface; -@@ -1265,6 +1273,20 @@ static cairo_int_status_t - cairo_fixed_t fw, fh; - cairo_bool_t is_bounded; - -+ /* Draw nonrepeating CGLayer surface using DO_LAYER */ -+ if (source->extend != CAIRO_EXTEND_REPEAT && -+ cairo_surface_get_type (pat_surf) == CAIRO_SURFACE_TYPE_QUARTZ) { -+ cairo_quartz_surface_t *quartz_surf = (cairo_quartz_surface_t *) pat_surf; -+ if (quartz_surf->cgLayer) { -+ cairo_matrix_invert(&m); -+ _cairo_quartz_cairo_matrix_to_quartz (&m, &state->transform); -+ state->rect = CGRectMake (0, 0, quartz_surf->extents.width, quartz_surf->extents.height); -+ state->sourceLayer = quartz_surf->cgLayer; -+ state->action = DO_LAYER; -+ return CAIRO_STATUS_SUCCESS; -+ } -+ } -+ - _cairo_surface_get_extents (composite->surface, &extents); - status = _cairo_surface_to_cgimage (pat_surf, &extents, format, - &m, clip, &img); -@@ -1426,7 +1448,14 @@ static void - CGContextTranslateCTM (state->cgDrawContext, 0, state->rect.size.height); - CGContextScaleCTM (state->cgDrawContext, 1, -1); - -- if (state->action == DO_IMAGE) { -+ if (state->action == DO_LAYER) { -+ /* Note that according to Apple docs it's completely legal to draw a CGLayer -+ * to any CGContext, even one it wasn't created for. -+ */ -+ assert (state->sourceLayer); -+ CGContextDrawLayerAtPoint (state->cgDrawContext, state->rect.origin, -+ state->sourceLayer); -+ } else if (state->action == DO_IMAGE) { - CGContextDrawImage (state->cgDrawContext, state->rect, state->image); - if (op == CAIRO_OPERATOR_SOURCE && - state->cgDrawContext == state->cgMaskContext) -@@ -1655,6 +1684,10 @@ static cairo_status_t - - surface->imageData = NULL; - -+ if (surface->cgLayer) { -+ CGLayerRelease (surface->cgLayer); -+ } -+ - return CAIRO_STATUS_SUCCESS; - } - -@@ -1693,9 +1726,14 @@ static cairo_surface_t * - int width, - int height) - { -- cairo_quartz_surface_t *surface, *similar_quartz; -+ cairo_quartz_surface_t *similar_quartz; - cairo_surface_t *similar; - cairo_format_t format; -+ cairo_quartz_surface_t *surface = (cairo_quartz_surface_t *) abstract_surface; -+ -+ if (surface->cgLayer) -+ return cairo_quartz_surface_create_cg_layer (abstract_surface, content, -+ width, height); - - if (content == CAIRO_CONTENT_COLOR_ALPHA) - format = CAIRO_FORMAT_ARGB32; -@@ -2068,7 +2106,6 @@ static cairo_int_status_t - cairo_quartz_drawing_state_t state; - cairo_int_status_t rv = CAIRO_INT_STATUS_UNSUPPORTED; - int i; -- CGFontRef cgfref = NULL; - - cairo_bool_t didForceFontSmoothing = FALSE; - cairo_antialias_t effective_antialiasing; -@@ -2087,10 +2124,12 @@ static cairo_int_status_t - CGContextSetTextDrawingMode (state.cgMaskContext, kCGTextClip); - } - -- /* this doesn't addref */ -- cgfref = _cairo_quartz_scaled_font_get_cg_font_ref (scaled_font); -- CGContextSetFont (state.cgMaskContext, cgfref); -- CGContextSetFontSize (state.cgMaskContext, 1.0); -+ if (!CTFontDrawGlyphsPtr) { -+ /* this doesn't addref */ -+ CGFontRef cgfref = _cairo_quartz_scaled_font_get_cg_font_ref (scaled_font); -+ CGContextSetFont (state.cgMaskContext, cgfref); -+ CGContextSetFontSize (state.cgMaskContext, 1.0); -+ } - - effective_antialiasing = scaled_font->options.antialias; - if (effective_antialiasing == CAIRO_ANTIALIAS_SUBPIXEL && -@@ -2625,6 +2664,79 @@ cairo_quartz_surface_create_for_cg_conte - } - - /** -+ * cairo_quartz_surface_create_cg_layer -+ * @surface: The returned surface can be efficiently drawn into this -+ * destination surface (if tiling is not used)." -+ * @content: the content type of the surface -+ * @width: width of the surface, in pixels -+ * @height: height of the surface, in pixels -+ * -+ * Creates a Quartz surface backed by a CGLayer, if the given surface -+ * is a Quartz surface; the CGLayer is created to match the surface's -+ * Quartz context. Otherwise just calls cairo_surface_create_similar. -+ * The returned surface can be efficiently blitted to the given surface, -+ * but tiling and 'extend' modes other than NONE are not so efficient. -+ * -+ * Return value: the newly created surface. -+ * -+ * Since: 1.10 -+ **/ -+cairo_surface_t * -+cairo_quartz_surface_create_cg_layer (cairo_surface_t *surface, -+ cairo_content_t content, -+ unsigned int width, -+ unsigned int height) -+{ -+ cairo_quartz_surface_t *surf; -+ CGLayerRef layer; -+ CGContextRef ctx; -+ CGContextRef cgContext; -+ -+ cgContext = cairo_quartz_surface_get_cg_context (surface); -+ if (!cgContext) -+ return cairo_surface_create_similar (surface, content, -+ width, height); -+ -+ if (!_cairo_quartz_verify_surface_size(width, height)) -+ return _cairo_surface_create_in_error (_cairo_error (CAIRO_STATUS_INVALID_SIZE)); -+ -+ /* If we pass zero width or height into CGLayerCreateWithContext below, -+ * it will fail. -+ */ -+ if (width == 0 || height == 0) { -+ return (cairo_surface_t*) -+ _cairo_quartz_surface_create_internal (NULL, content, -+ width, height); -+ } -+ -+ layer = CGLayerCreateWithContext (cgContext, -+ CGSizeMake (width, height), -+ NULL); -+ if (!layer) -+ return _cairo_surface_create_in_error (_cairo_error (CAIRO_STATUS_NO_MEMORY)); -+ -+ ctx = CGLayerGetContext (layer); -+ /* Flip it when we draw into it, so that when we finally composite it -+ * to a flipped target, the directions match and Quartz will optimize -+ * the composition properly -+ */ -+ CGContextTranslateCTM (ctx, 0, height); -+ CGContextScaleCTM (ctx, 1, -1); -+ -+ CGContextRetain (ctx); -+ surf = _cairo_quartz_surface_create_internal (ctx, content, -+ width, height); -+ if (surf->base.status) { -+ CGLayerRelease (layer); -+ // create_internal will have set an error -+ return (cairo_surface_t*) surf; -+ } -+ surf->cgLayer = layer; -+ -+ return (cairo_surface_t *) surf; -+} -+ -+/** - * cairo_quartz_surface_create: - * @format: format of pixels in the surface to create - * @width: width of the surface, in pixels -diff --git a/gfx/cairo/cairo/src/cairo-quartz.h b/gfx/cairo/cairo/src/cairo-quartz.h ---- a/gfx/cairo/cairo/src/cairo-quartz.h -+++ b/gfx/cairo/cairo/src/cairo-quartz.h -@@ -61,6 +61,12 @@ cairo_quartz_surface_create_for_data (un - unsigned int height, - unsigned int stride); - -+cairo_public cairo_surface_t * -+cairo_quartz_surface_create_cg_layer (cairo_surface_t *surface, -+ cairo_content_t content, -+ unsigned int width, -+ unsigned int height); -+ - cairo_public CGContextRef - cairo_quartz_surface_get_cg_context (cairo_surface_t *surface); - diff --git a/gfx/cairo/14-image-surface-oob-read.patch b/gfx/cairo/14-image-surface-oob-read.patch deleted file mode 100644 index 6aa4c1b678..0000000000 --- a/gfx/cairo/14-image-surface-oob-read.patch +++ /dev/null @@ -1,17 +0,0 @@ -diff --git a/gfx/cairo/cairo/src/cairo-quartz-surface.c b/gfx/cairo/cairo/src/cairo-quartz-surface.c ---- a/gfx/cairo/cairo/src/cairo-quartz-surface.c -+++ b/gfx/cairo/cairo/src/cairo-quartz-surface.c -@@ -873,8 +873,12 @@ static cairo_status_t - return _cairo_error (CAIRO_STATUS_NO_MEMORY); - } - -+ // The last row of data may have less than stride bytes so make sure we -+ // only copy the minimum amount required from that row. - memcpy (image_data, image_surface->data, -- image_surface->height * image_surface->stride); -+ (image_surface->height - 1) * image_surface->stride + -+ cairo_format_stride_for_width (image_surface->format, -+ image_surface->width)); - *image_out = CairoQuartzCreateCGImage (image_surface->format, - image_surface->width, - image_surface->height, diff --git a/gfx/cairo/15-remove-quartz-surface-for-data.patch b/gfx/cairo/15-remove-quartz-surface-for-data.patch deleted file mode 100644 index a82d4aab21..0000000000 --- a/gfx/cairo/15-remove-quartz-surface-for-data.patch +++ /dev/null @@ -1,138 +0,0 @@ -diff --git a/gfx/cairo/cairo/src/cairo-quartz-surface.c b/gfx/cairo/cairo/src/cairo-quartz-surface.c ---- a/gfx/cairo/cairo/src/cairo-quartz-surface.c -+++ b/gfx/cairo/cairo/src/cairo-quartz-surface.c -@@ -2856,117 +2856,6 @@ cairo_quartz_surface_create (cairo_forma - } - - /** -- * cairo_quartz_surface_create_for_data -- * @data: a pointer to a buffer supplied by the application in which -- * to write contents. This pointer must be suitably aligned for any -- * kind of variable, (for example, a pointer returned by malloc). -- * @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 Quartz surface backed by a CGBitmap. The surface is -- * created using the Device RGB (or Device Gray, for A8) color space. -- * All Cairo operations, including those that require software -- * rendering, will succeed on this surface. -- * -- * Return value: the newly created surface. -- * -- * Since: 1.12 [Mozilla addition] -- **/ --cairo_surface_t * --cairo_quartz_surface_create_for_data (unsigned char *data, -- cairo_format_t format, -- unsigned int width, -- unsigned int height, -- unsigned int stride) --{ -- cairo_quartz_surface_t *surf; -- CGContextRef cgc; -- CGColorSpaceRef cgColorspace; -- CGBitmapInfo bitinfo; -- void *imageData = data; -- int bitsPerComponent; -- unsigned int i; -- -- // verify width and height of surface -- if (!_cairo_quartz_verify_surface_size(width, height)) -- return _cairo_surface_create_in_error (_cairo_error (CAIRO_STATUS_INVALID_SIZE)); -- -- if (width == 0 || height == 0) { -- return (cairo_surface_t*) _cairo_quartz_surface_create_internal (NULL, _cairo_content_from_format (format), -- width, height); -- } -- -- if (format == CAIRO_FORMAT_ARGB32 || -- format == CAIRO_FORMAT_RGB24) -- { -- cgColorspace = CGColorSpaceCreateDeviceRGB(); -- bitinfo = kCGBitmapByteOrder32Host; -- if (format == CAIRO_FORMAT_ARGB32) -- bitinfo |= kCGImageAlphaPremultipliedFirst; -- else -- bitinfo |= kCGImageAlphaNoneSkipFirst; -- bitsPerComponent = 8; -- } else if (format == CAIRO_FORMAT_A8) { -- cgColorspace = NULL; -- bitinfo = kCGImageAlphaOnly; -- bitsPerComponent = 8; -- } else if (format == CAIRO_FORMAT_A1) { -- /* I don't think we can usefully support this, as defined by -- * cairo_format_t -- these are 1-bit pixels stored in 32-bit -- * quantities. -- */ -- return _cairo_surface_create_in_error (_cairo_error (CAIRO_STATUS_INVALID_FORMAT)); -- } else { -- return _cairo_surface_create_in_error (_cairo_error (CAIRO_STATUS_INVALID_FORMAT)); -- } -- -- cgc = CGBitmapContextCreate (imageData, -- width, -- height, -- bitsPerComponent, -- stride, -- cgColorspace, -- bitinfo); -- CGColorSpaceRelease (cgColorspace); -- -- if (!cgc) { -- free (imageData); -- return _cairo_surface_create_in_error (_cairo_error (CAIRO_STATUS_NO_MEMORY)); -- } -- -- /* flip the Y axis */ -- CGContextTranslateCTM (cgc, 0.0, height); -- CGContextScaleCTM (cgc, 1.0, -1.0); -- -- surf = _cairo_quartz_surface_create_internal (cgc, _cairo_content_from_format (format), -- width, height); -- if (surf->base.status) { -- CGContextRelease (cgc); -- free (imageData); -- // create_internal will have set an error -- return (cairo_surface_t*) surf; -- } -- -- surf->imageData = imageData; -- -- cairo_surface_t* tmpImageSurfaceEquiv = -- cairo_image_surface_create_for_data (imageData, format, -- width, height, stride); -- -- if (cairo_surface_status (tmpImageSurfaceEquiv)) { -- // Tried & failed to create an imageSurfaceEquiv! -- cairo_surface_destroy (tmpImageSurfaceEquiv); -- surf->imageSurfaceEquiv = NULL; -- } else { -- surf->imageSurfaceEquiv = tmpImageSurfaceEquiv; -- surf->ownsData = FALSE; -- } -- -- return (cairo_surface_t *) surf; --} -- --/** - * cairo_quartz_surface_get_cg_context: - * @surface: the Cairo Quartz surface - * -diff --git a/gfx/cairo/cairo/src/cairo-quartz.h b/gfx/cairo/cairo/src/cairo-quartz.h ---- a/gfx/cairo/cairo/src/cairo-quartz.h -+++ b/gfx/cairo/cairo/src/cairo-quartz.h -@@ -54,13 +54,6 @@ cairo_quartz_surface_create_for_cg_conte - unsigned int width, - unsigned int height); - --cairo_surface_t * --cairo_quartz_surface_create_for_data (unsigned char *data, -- cairo_format_t format, -- unsigned int width, -- unsigned int height, -- unsigned int stride); -- - cairo_public cairo_surface_t * - cairo_quartz_surface_create_cg_layer (cairo_surface_t *surface, - cairo_content_t content, diff --git a/gfx/cairo/16-quartz-surface-doimage-extendpad.patch b/gfx/cairo/16-quartz-surface-doimage-extendpad.patch deleted file mode 100644 index eaf67b42a4..0000000000 --- a/gfx/cairo/16-quartz-surface-doimage-extendpad.patch +++ /dev/null @@ -1,12 +0,0 @@ -diff --git a/gfx/cairo/cairo/src/cairo-quartz-surface.c b/gfx/cairo/cairo/src/cairo-quartz-surface.c ---- a/gfx/cairo/cairo/src/cairo-quartz-surface.c -+++ b/gfx/cairo/cairo/src/cairo-quartz-surface.c -@@ -1315,7 +1315,7 @@ static cairo_int_status_t - - srcRect = CGRectMake (0, 0, extents.width, extents.height); - -- if (source->extend == CAIRO_EXTEND_NONE) { -+ if (source->extend == CAIRO_EXTEND_NONE || source->extend == CAIRO_EXTEND_PAD) { - int x, y; - if (op == CAIRO_OPERATOR_SOURCE && - (pat_surf->content == CAIRO_CONTENT_ALPHA || diff --git a/gfx/cairo/18-quartz-granular-ifdefs.patch b/gfx/cairo/18-quartz-granular-ifdefs.patch index 47d50762e2..5140fd1eb0 100644 --- a/gfx/cairo/18-quartz-granular-ifdefs.patch +++ b/gfx/cairo/18-quartz-granular-ifdefs.patch @@ -1,30 +1,35 @@ +# HG changeset patch +# User Jonathan Kew <jkew@mozilla.com> +# Date 1713891373 -3600 +# Tue Apr 23 17:56:13 2024 +0100 +# Node ID a7bd4153d6421d17cb2991435ceb5a5fff06dba6 +# Parent c0c2246d28b91b5e933f42d903b06d575d943e6e +Bug 1892913 - patch 16 - Apply 18-quartz-granular-ifdefs.patch + diff --git a/gfx/cairo/cairo/src/cairo-quartz-font.c b/gfx/cairo/cairo/src/cairo-quartz-font.c -index 48f79d1680920..740ca108e7d19 100644 --- a/gfx/cairo/cairo/src/cairo-quartz-font.c +++ b/gfx/cairo/cairo/src/cairo-quartz-font.c -@@ -102,8 +102,10 @@ static int (*CGFontGetAscentPtr) (CGFontRef fontRef) = NULL; - static int (*CGFontGetDescentPtr) (CGFontRef fontRef) = NULL; - static int (*CGFontGetLeadingPtr) (CGFontRef fontRef) = NULL; +@@ -65,7 +65,9 @@ + /* These are private functions */ + static bool (*CGContextGetAllowsFontSmoothingPtr) (CGContextRef) = NULL; +#ifdef CAIRO_HAS_QUARTZ_ATSUFONTID - /* Not public anymore in 64-bits nor in 10.7 */ --static ATSFontRef (*FMGetATSFontRefFromFontPtr) (FMFont iFont) = NULL; -+static ATSFontRef (*FMGetATSFontRefFromFontPtr) (ATSUFontID iFont) = NULL; + static ATSFontRef (*FMGetATSFontRefFromFontPtr) (FMFont iFont) = NULL; +#endif /* CAIRO_HAS_QUARTZ_ATSUFONTID */ static cairo_bool_t _cairo_quartz_font_symbol_lookup_done = FALSE; - static cairo_bool_t _cairo_quartz_font_symbols_present = FALSE; -@@ -164,7 +166,9 @@ quartz_font_ensure_symbols(void) - CGContextGetAllowsFontSmoothingPtr = dlsym(RTLD_DEFAULT, "CGContextGetAllowsFontSmoothing"); - CGContextSetAllowsFontSmoothingPtr = dlsym(RTLD_DEFAULT, "CGContextSetAllowsFontSmoothing"); + /* Cairo's transformations assume a unit-scaled font. */ +@@ -92,7 +94,9 @@ quartz_font_ensure_symbols(void) + CGContextGetAllowsFontSmoothingPtr = + dlsym (RTLD_DEFAULT, "CGContextGetAllowsFontSmoothing"); +#ifdef CAIRO_HAS_QUARTZ_ATSUFONTID FMGetATSFontRefFromFontPtr = dlsym(RTLD_DEFAULT, "FMGetATSFontRefFromFont"); +#endif /* CAIRO_HAS_QUARTZ_ATSUFONTID */ - if ((CGFontCreateWithFontNamePtr || CGFontCreateWithNamePtr) && - CGFontGetGlyphBBoxesPtr && -@@ -870,6 +874,7 @@ _cairo_quartz_scaled_font_get_ct_font_ref (cairo_scaled_font_t *abstract_font) + _cairo_quartz_font_symbol_lookup_done = TRUE; + } +@@ -795,6 +799,7 @@ CTFontRef /* * compat with old ATSUI backend */ @@ -32,14 +37,13 @@ index 48f79d1680920..740ca108e7d19 100644 /** * cairo_quartz_font_face_create_for_atsu_font_id: -@@ -913,3 +918,5 @@ cairo_atsui_font_face_create_for_atsu_font_id (ATSUFontID font_id) +@@ -838,3 +843,5 @@ cairo_atsui_font_face_create_for_atsu_fo { return cairo_quartz_font_face_create_for_atsu_font_id (font_id); } + +#endif /* CAIRO_HAS_QUARTZ_ATSUFONTID */ diff --git a/gfx/cairo/cairo/src/cairo-quartz-image.h b/gfx/cairo/cairo/src/cairo-quartz-image.h -index 0dd5abb4fd2d2..9e8409c1169b3 100644 --- a/gfx/cairo/cairo/src/cairo-quartz-image.h +++ b/gfx/cairo/cairo/src/cairo-quartz-image.h @@ -40,8 +40,6 @@ @@ -52,7 +56,6 @@ index 0dd5abb4fd2d2..9e8409c1169b3 100644 cairo_public cairo_surface_t * diff --git a/gfx/cairo/cairo/src/cairo-quartz.h b/gfx/cairo/cairo/src/cairo-quartz.h -index 20c86423b25de..2118d8ff9c842 100644 --- a/gfx/cairo/cairo/src/cairo-quartz.h +++ b/gfx/cairo/cairo/src/cairo-quartz.h @@ -40,7 +40,14 @@ @@ -70,7 +73,7 @@ index 20c86423b25de..2118d8ff9c842 100644 CAIRO_BEGIN_DECLS -@@ -75,8 +82,10 @@ cairo_quartz_surface_get_image (cairo_surface_t *surface); +@@ -69,8 +76,10 @@ cairo_quartz_surface_get_image (cairo_su cairo_public cairo_font_face_t * cairo_quartz_font_face_create_for_cgfont (CGFontRef font); diff --git a/gfx/cairo/19-ft-color-ifdef.patch b/gfx/cairo/19-ft-color-ifdef.patch new file mode 100644 index 0000000000..a58fcc8cf4 --- /dev/null +++ b/gfx/cairo/19-ft-color-ifdef.patch @@ -0,0 +1,51 @@ +# HG changeset patch +# User Jonathan Kew <jkew@mozilla.com> +# Date 1713898119 -3600 +# Tue Apr 23 19:48:39 2024 +0100 +# Node ID 2e47d112a6cf17da455d80727fdd7c96d02e48d0 +# Parent c4a8e2e58b280f250a5741e35f986957a4db3f86 +Bug 1892913 - patch 17 - Add missing #include FT_COLOR_H to cairo-ft-font.c + +diff --git a/gfx/cairo/cairo/src/cairo-ft-font.c b/gfx/cairo/cairo/src/cairo-ft-font.c +--- a/gfx/cairo/cairo/src/cairo-ft-font.c ++++ b/gfx/cairo/cairo/src/cairo-ft-font.c +@@ -66,6 +66,10 @@ + #include FT_SYNTHESIS_H + #endif + ++#ifdef FT_COLOR_H ++#include FT_COLOR_H ++#endif ++ + #if HAVE_FT_LIBRARY_SETLCDFILTER + #include FT_LCD_FILTER_H + #endif +@@ -2597,6 +2601,7 @@ static void + } + + ++#ifdef FT_COLOR_H + static void + _cairo_ft_scaled_glyph_set_palette (cairo_ft_scaled_font_t *scaled_font, + FT_Face face, +@@ -2637,6 +2642,20 @@ static void + if (entries_ret) + *entries_ret = entries; + } ++#else ++static void ++_cairo_ft_scaled_glyph_set_palette (cairo_ft_scaled_font_t *scaled_font, ++ FT_Face face, ++ unsigned int *num_entries_ret, ++ void **entries_ret) ++{ ++ if (num_entries_ret) ++ *num_entries_ret = 0; ++ ++ if (entries_ret) ++ *entries_ret = NULL; ++} ++#endif + + /* returns TRUE if foreground color used */ + static cairo_bool_t diff --git a/gfx/cairo/20-ios-colorspace.patch b/gfx/cairo/20-ios-colorspace.patch new file mode 100644 index 0000000000..e15643e8ac --- /dev/null +++ b/gfx/cairo/20-ios-colorspace.patch @@ -0,0 +1,65 @@ +# HG changeset patch +# User Jonathan Kew <jkew@mozilla.com> +# Date 1714124453 -3600 +# Fri Apr 26 10:40:53 2024 +0100 +# Node ID 6d9a0fd66f0a4e02df968ea479d890a41031db15 +# Parent e606a18e8d85eb481139530055d38f125665fb50 +Bug 1892913 - patch 18 - Cairo fixes for iOS build. + +diff --git a/gfx/cairo/cairo/src/cairo-features.h b/gfx/cairo/cairo/src/cairo-features.h +--- a/gfx/cairo/cairo/src/cairo-features.h ++++ b/gfx/cairo/cairo/src/cairo-features.h +@@ -75,6 +75,10 @@ + #define CAIRO_HAS_QUARTZ_APPLICATION_SERVICES 1 + #endif + ++#if defined(MOZ_WIDGET_UIKIT) ++#define CAIRO_HAS_IMAGE_IO 1 ++#endif ++ + #ifdef XP_WIN + #define CAIRO_HAS_DWRITE_FONT 1 + #define CAIRO_HAS_WIN32_FONT 1 +diff --git a/gfx/cairo/cairo/src/cairo-quartz-image-surface.c b/gfx/cairo/cairo/src/cairo-quartz-image-surface.c +--- a/gfx/cairo/cairo/src/cairo-quartz-image-surface.c ++++ b/gfx/cairo/cairo/src/cairo-quartz-image-surface.c +@@ -307,7 +307,11 @@ cairo_quartz_image_surface_create (cairo + colorspace = _cairo_quartz_create_color_space (context); + } + else { ++#if CAIRO_HAS_QUARTZ_APPLICATION_SERVICES /* available on macOS but not iOS */ + colorspace = CGDisplayCopyColorSpace (CGMainDisplayID ()); ++#else ++ colorspace = CGColorSpaceCreateDeviceRGB (); ++#endif + } + + bitinfo |= format == CAIRO_FORMAT_ARGB32 ? kCGImageAlphaPremultipliedFirst : kCGImageAlphaNoneSkipFirst; +diff --git a/gfx/cairo/cairo/src/cairo-quartz-surface.c b/gfx/cairo/cairo/src/cairo-quartz-surface.c +--- a/gfx/cairo/cairo/src/cairo-quartz-surface.c ++++ b/gfx/cairo/cairo/src/cairo-quartz-surface.c +@@ -201,8 +201,10 @@ CGColorSpaceRef + if (color_space) + return color_space; + } ++#if CAIRO_HAS_QUARTZ_APPLICATION_SERVICES /* available on macOS but not iOS */ + if (!color_space) + color_space = CGDisplayCopyColorSpace (CGMainDisplayID ()); ++#endif + + if (!color_space) + color_space = CGColorSpaceCreateDeviceRGB (); +diff --git a/gfx/cairo/cairo/src/cairo-quartz.h b/gfx/cairo/cairo/src/cairo-quartz.h +--- a/gfx/cairo/cairo/src/cairo-quartz.h ++++ b/gfx/cairo/cairo/src/cairo-quartz.h +@@ -49,6 +49,10 @@ + #include <ApplicationServices/ApplicationServices.h> + #endif + ++#if CAIRO_HAS_IMAGE_IO ++#include <ImageIO/ImageIO.h> ++#endif ++ + CAIRO_BEGIN_DECLS + + cairo_public cairo_surface_t * diff --git a/gfx/cairo/21-quartz-surface-leak.patch b/gfx/cairo/21-quartz-surface-leak.patch new file mode 100644 index 0000000000..60c94730d7 --- /dev/null +++ b/gfx/cairo/21-quartz-surface-leak.patch @@ -0,0 +1,30 @@ +# HG changeset patch +# User Jonathan Kew <jkew@mozilla.com> +# Date 1714678834 -3600 +# Thu May 02 20:40:34 2024 +0100 +# Node ID 92c20a5fcddecdc04b4c05ecbfa7fcc64e78ea4e +# Parent 7378b3133191c988cfd1bd3e3f2b615140d79d33 +Bug 1892913 - patch 19 - Don't prematurely clear cairo_quartz_image_surface_t's imageSurface field, it still needs to hold a reference to the wrapped image surface. + +Without this, we end up leaking the DataSourceSurfaceRawData that backs the +quartz image surface created during surface-pattern rendering, because the +imageSurface pointer holds a strong reference and then gets cleared without +releasing it. + +diff --git a/gfx/cairo/cairo/src/cairo-quartz-surface.c b/gfx/cairo/cairo/src/cairo-quartz-surface.c +--- a/gfx/cairo/cairo/src/cairo-quartz-surface.c ++++ b/gfx/cairo/cairo/src/cairo-quartz-surface.c +@@ -759,7 +759,12 @@ static cairo_status_t + + if (acquired) { + _cairo_surface_release_source_image (source, image_surface->imageSurface, image_extra); +- image_surface->imageSurface = NULL; ++ /* If source itself is an image surface, _cairo_surface_release_source_image ++ does not release it, and image_surface->imageSurface still owns a reference ++ to it. So we don't clear that field here; _cairo_quartz_image_surface_finish ++ will take care of it. */ ++ if (source->type != CAIRO_SURFACE_TYPE_IMAGE) ++ image_surface->imageSurface = NULL; + } + cairo_surface_destroy (&image_surface->base); + diff --git a/gfx/cairo/22-windows-build-fix.patch b/gfx/cairo/22-windows-build-fix.patch new file mode 100644 index 0000000000..a4ab3e895b --- /dev/null +++ b/gfx/cairo/22-windows-build-fix.patch @@ -0,0 +1,64 @@ +# HG changeset patch +# User Jonathan Kew <jkew@mozilla.com> +# Date 1714037079 -3600 +# Thu Apr 25 10:24:39 2024 +0100 +# Node ID 796a9cf6d3d64e08056fe7583e7de11066729130 +# Parent c150548d5702cdf69be21a30407b4ce75d5b662d +Bug 1892913 - patch 20 - Add #ifdef guards around mingw-specific __CRT_UUID_DECL lines in d2d1-extra.h + +To fix the Gecko build on Windows, as this is a mingw-ism that isn't +supported or needed. + +diff --git a/gfx/cairo/cairo/src/win32/d2d1-extra.h b/gfx/cairo/cairo/src/win32/d2d1-extra.h +--- a/gfx/cairo/cairo/src/win32/d2d1-extra.h ++++ b/gfx/cairo/cairo/src/win32/d2d1-extra.h +@@ -39,7 +39,10 @@ ID2D1DeviceContext1 : public ID2D1Device + virtual void STDMETHODCALLTYPE CreateStrokedGeometryRealization() = 0; + virtual void STDMETHODCALLTYPE DrawGeometryRealization() = 0; + }; ++#ifdef __CRT_UUID_DECL + __CRT_UUID_DECL(ID2D1DeviceContext1, 0xd37f57e4, 0x6908, 0x459f, 0xa1, 0x99, 0xe7, 0x2f, 0x24, 0xf7, 0x99, 0x87) ++#endif ++ + + DEFINE_GUID(IID_ID2D1DeviceContext2, 0x394ea6a3, 0x0c34, 0x4321, 0x95, 0x0b, 0x6c, 0xa2, 0x0f, 0x0b, 0xe6, 0xc7); + MIDL_INTERFACE("394ea6a3-0c34-4321-950b-6ca20f0be6c7") +@@ -57,7 +60,9 @@ ID2D1DeviceContext2 : public ID2D1Device + virtual void STDMETHODCALLTYPE DrawGdiMetafile() = 0; + virtual void STDMETHODCALLTYPE CreateTransformedImageSource() = 0; + }; ++#ifdef __CRT_UUID_DECL + __CRT_UUID_DECL(ID2D1DeviceContext2, 0x394ea6a3, 0x0c34, 0x4321, 0x95, 0x0b, 0x6c, 0xa2, 0x0f, 0x0b, 0xe6, 0xc7) ++#endif + + + DEFINE_GUID(IID_ID2D1DeviceContext3, 0x235a7496, 0x8351, 0x414c, 0xbc, 0xd4, 0x66, 0x72, 0xab, 0x2d, 0x8e, 0x00); +@@ -67,7 +72,9 @@ ID2D1DeviceContext3 : public ID2D1Device + virtual void STDMETHODCALLTYPE CreateSpriteBatch() = 0; + virtual void STDMETHODCALLTYPE DrawSpriteBatch() = 0; + }; ++#ifdef __CRT_UUID_DECL + __CRT_UUID_DECL(ID2D1DeviceContext3, 0x235a7496, 0x8351, 0x414c, 0xbc, 0xd4, 0x66, 0x72, 0xab, 0x2d, 0x8e, 0x00) ++#endif + + + DEFINE_GUID(IID_ID2D1SvgGlyphStyle, 0xaf671749, 0xd241, 0x4db8, 0x8e, 0x41, 0xdc, 0xc2, 0xe5, 0xc1, 0xa4, 0x38); +@@ -80,7 +87,9 @@ ID2D1SvgGlyphStyle : public ID2D1Resour + virtual void STDMETHODCALLTYPE GetStrokeDashesCount() = 0; + virtual void STDMETHODCALLTYPE GetStroke() = 0; + }; ++#ifdef __CRT_UUID_DECL + __CRT_UUID_DECL(ID2D1SvgGlyphStyle, 0xaf671749, 0xd241, 0x4db8, 0x8e, 0x41, 0xdc, 0xc2, 0xe5, 0xc1, 0xa4, 0x38) ++#endif + + + DEFINE_GUID(IID_ID2D1DeviceContext4, 0x8c427831, 0x3d90, 0x4476, 0xb6, 0x47, 0xc4, 0xfa, 0xe3, 0x49, 0xe4, 0xdb); +@@ -106,6 +115,8 @@ ID2D1DeviceContext4 : public ID2D1Device + DWRITE_MEASURING_MODE measuringMode) = 0; + + }; ++#ifdef __CRT_UUID_DECL + __CRT_UUID_DECL(ID2D1DeviceContext4, 0x8c427831, 0x3d90, 0x4476, 0xb6, 0x47, 0xc4, 0xfa, 0xe3, 0x49, 0xe4, 0xdb) ++#endif + + #endif diff --git a/gfx/cairo/23-win32-api-additions.patch b/gfx/cairo/23-win32-api-additions.patch new file mode 100644 index 0000000000..65b1a90dea --- /dev/null +++ b/gfx/cairo/23-win32-api-additions.patch @@ -0,0 +1,101 @@ +# HG changeset patch +# User Jonathan Kew <jkew@mozilla.com> +# Date 1714049062 -3600 +# Thu Apr 25 13:44:22 2024 +0100 +# Node ID cae7821ff41ed99081818f5434a347d224833f70 +# Parent 8f09f0d54c643029b7601dc58f3a8ff125eca699 +Bug 1892913 - patch 21 - Add cairo_win32_surface APIs wanted for gecko. + +diff --git a/gfx/cairo/cairo/src/cairo-win32.h b/gfx/cairo/cairo/src/cairo-win32.h +--- a/gfx/cairo/cairo/src/cairo-win32.h ++++ b/gfx/cairo/cairo/src/cairo-win32.h +@@ -72,6 +72,14 @@ cairo_win32_surface_get_dc (cairo_surfac + cairo_public cairo_surface_t * + cairo_win32_surface_get_image (cairo_surface_t *surface); + ++cairo_public HDC ++cairo_win32_get_dc_with_clip(cairo_t* cr); ++ ++cairo_public cairo_status_t ++cairo_win32_surface_get_size(const cairo_surface_t* surface, ++ int* width, ++ int* height); ++ + #if CAIRO_HAS_WIN32_FONT + + /* +diff --git a/gfx/cairo/cairo/src/win32/cairo-win32-surface.c b/gfx/cairo/cairo/src/win32/cairo-win32-surface.c +--- a/gfx/cairo/cairo/src/win32/cairo-win32-surface.c ++++ b/gfx/cairo/cairo/src/win32/cairo-win32-surface.c +@@ -163,6 +163,52 @@ cairo_win32_surface_get_dc (cairo_surfac + } + + /** ++ * cairo_win32_get_dc_with_clip: ++ * (Mozilla addition) ++ */ ++HDC ++cairo_win32_get_dc_with_clip(cairo_t* cr) ++{ ++ cairo_surface_t* surface = cairo_get_target(cr); ++ if (cr->backend->type == CAIRO_TYPE_DEFAULT) { ++ cairo_default_context_t* c = (cairo_default_context_t*)cr; ++ cairo_clip_t* clip = _cairo_clip_copy(_cairo_gstate_get_clip(c->gstate)); ++ if (_cairo_surface_is_win32(surface)) { ++ cairo_win32_display_surface_t* winsurf = (cairo_win32_display_surface_t*)surface; ++ ++ _cairo_win32_display_surface_set_clip(winsurf, clip); ++ ++ _cairo_clip_destroy(clip); ++ return winsurf->win32.dc; ++ } ++ ++ if (_cairo_surface_is_paginated(surface)) { ++ cairo_surface_t* target; ++ ++ target = _cairo_paginated_surface_get_target(surface); ++ ++#ifndef CAIRO_OMIT_WIN32_PRINTING ++ if (_cairo_surface_is_win32_printing(target)) { ++ cairo_status_t status; ++ cairo_win32_printing_surface_t* psurf = (cairo_win32_printing_surface_t*)target; ++ ++ status = _cairo_surface_clipper_set_clip(&psurf->clipper, clip); ++ ++ _cairo_clip_destroy(clip); ++ ++ if (status) ++ return NULL; ++ ++ return psurf->win32.dc; ++ } ++#endif ++ } ++ _cairo_clip_destroy(clip); ++ } ++ return NULL; ++} ++ ++/** + * _cairo_surface_is_win32: + * @surface: a #cairo_surface_t + * +@@ -337,3 +383,17 @@ cairo_int_status_t + #endif + } + #undef STACK_GLYPH_SIZE ++ ++cairo_status_t ++cairo_win32_surface_get_size(const cairo_surface_t* surface, int* width, int* height) ++{ ++ if (!_cairo_surface_is_win32(surface)) ++ return CAIRO_STATUS_SURFACE_TYPE_MISMATCH; ++ ++ const cairo_win32_surface_t* winsurface = (const cairo_win32_surface_t*)surface; ++ ++ *width = winsurface->extents.width; ++ *height = winsurface->extents.height; ++ ++ return CAIRO_STATUS_SUCCESS; ++} +\ No newline at end of file diff --git a/gfx/cairo/24-pdf-destination-missing.patch b/gfx/cairo/24-pdf-destination-missing.patch new file mode 100644 index 0000000000..64819a2a4b --- /dev/null +++ b/gfx/cairo/24-pdf-destination-missing.patch @@ -0,0 +1,21 @@ +# HG changeset patch +# User Jonathan Kew <jkew@mozilla.com> +# Date 1715329864 -3600 +# Fri May 10 09:31:04 2024 +0100 +# Node ID 0e12f0bc1e445c0afb23e620aa0321ccf7d7c4a8 +# Parent 8f49349eeb0ec5df0e1dd3ddd98423138921a029 +Bug 1895872 - Avoid generating a broken PDF when a link destination is missing. r=#gfx-reviewers + +diff --git a/gfx/cairo/cairo/src/cairo-pdf-interchange.c b/gfx/cairo/cairo/src/cairo-pdf-interchange.c +--- a/gfx/cairo/cairo/src/cairo-pdf-interchange.c ++++ b/gfx/cairo/cairo/src/cairo-pdf-interchange.c +@@ -1506,7 +1506,8 @@ cairo_pdf_interchange_write_forward_link + TRUE, + x, y); + } else { +- return _cairo_tag_error ("Link to dest=\"%s\" not found", link->dest); ++ // Destination is missing: just give the link an empty dest string. ++ _cairo_output_stream_printf(surface->object_stream.stream, "<>\n"); + } + } else { + cairo_pdf_interchange_write_explicit_dest (surface, diff --git a/gfx/cairo/24-pdf-interchange-mcid-crash.patch b/gfx/cairo/24-pdf-interchange-mcid-crash.patch new file mode 100644 index 0000000000..f8293e7592 --- /dev/null +++ b/gfx/cairo/24-pdf-interchange-mcid-crash.patch @@ -0,0 +1,20 @@ +# HG changeset patch +# User Jonathan Kew <jkew@mozilla.com> +# Date 1715706811 -3600 +# Tue May 14 18:13:31 2024 +0100 +# Node ID c3ad2cb3ec3c7833187b9cea6002632cb1b692b4 +# Parent 4df4e109202ff67836eaa61c66a7c65a2f712e11 +Bug 1896173 - Check that we have a render_node name before attempting MCID tagging in pdf output. r=#gfx-reviewers + +diff --git a/gfx/cairo/cairo/src/cairo-pdf-interchange.c b/gfx/cairo/cairo/src/cairo-pdf-interchange.c +--- a/gfx/cairo/cairo/src/cairo-pdf-interchange.c ++++ b/gfx/cairo/cairo/src/cairo-pdf-interchange.c +@@ -2043,7 +2043,7 @@ cairo_int_status_t + if (command_list_has_content (surface, command_id, NULL)) { + ic->render_next_command_has_content = TRUE; + } +- } else if (ic->render_next_command_has_content) { ++ } else if (ic->render_next_command_has_content && ic->current_render_node->name) { + add_mcid_to_node (surface, ic->current_render_node, ic->command_id, &mcid); + status = _cairo_pdf_operators_tag_begin (&surface->pdf_operators, + ic->current_render_node->name, mcid); diff --git a/gfx/cairo/26-quartz-surface-mask.patch b/gfx/cairo/26-quartz-surface-mask.patch new file mode 100644 index 0000000000..dd5c71c07a --- /dev/null +++ b/gfx/cairo/26-quartz-surface-mask.patch @@ -0,0 +1,124 @@ +# HG changeset patch +# User Jonathan Kew <jkew@mozilla.com> +# Date 1717237382 -3600 +# Sat Jun 01 11:23:02 2024 +0100 +# Node ID d5f7b9fd904e04406c56899c5cac9248b122ea35 +# Parent c8d3e447c892474e061c9ffd22ec1823f06ecffa +Bug 1900028 - Handle CAIRO_FORMAT_A8 in _cairo_surface_to_cgimage for masking operations. + +Differential Revision: https://phabricator.services.mozilla.com/D212354 + +diff --git a/gfx/cairo/cairo/src/cairo-quartz-surface.c b/gfx/cairo/cairo/src/cairo-quartz-surface.c +--- a/gfx/cairo/cairo/src/cairo-quartz-surface.c ++++ b/gfx/cairo/cairo/src/cairo-quartz-surface.c +@@ -684,6 +684,55 @@ CairoQuartzCreateGradientFunction (const + &gradient_callbacks); + } + ++static CGImageRef ++CairoQuartzCreateCGImageMask (cairo_format_t format, ++ unsigned int width, ++ unsigned int height, ++ unsigned int stride, ++ void *data, ++ cairo_bool_t interpolate, ++ CGDataProviderReleaseDataCallback releaseCallback, ++ void *releaseInfo) ++{ ++ CGImageRef image = NULL; ++ CGDataProviderRef dataProvider = NULL; ++ int bitsPerComponent = 8, bitsPerPixel = 8; ++ ++ if (format != CAIRO_FORMAT_A8) ++ return NULL; ++ ++ dataProvider = CGDataProviderCreateWithData (releaseInfo, ++ data, ++ height * stride, ++ releaseCallback); ++ ++ if (unlikely (!dataProvider)) { ++ // manually release ++ if (releaseCallback) ++ releaseCallback (releaseInfo, data, height * stride); ++ goto FINISH; ++ } ++ ++ cairo_quartz_float_t decode[] = {1.0, 0.0}; ++ image = CGImageMaskCreate (width, height, ++ bitsPerComponent, ++ bitsPerPixel, ++ stride, ++ dataProvider, ++ decode, ++ interpolate); ++ ++FINISH: ++ CGDataProviderRelease (dataProvider); ++ return image; ++} ++ ++static void ++DataProviderReleaseCallback (void *info, const void *data, size_t size) ++{ ++ free (info); ++} ++ + static cairo_status_t + _cairo_surface_to_cgimage (cairo_surface_t *source, + cairo_rectangle_int_t *extents, +@@ -742,13 +791,48 @@ static cairo_status_t + &image_extra); + if (unlikely (status)) + return status; +- image_surface = +- (cairo_quartz_image_surface_t*)cairo_quartz_image_surface_create (&surface->base); +- status = image_surface->base.status; +- if (status) ++ ++ if (surface->format == CAIRO_FORMAT_A8) { ++ /* cairo_quartz_image_surface_create doesn't handle CAIRO_FORMAT_A8, ++ * so we create a CGImage manually here for masking operations. ++ */ ++ void* image_data = _cairo_malloc_ab (surface->height, surface->stride); ++ if (unlikely (!image_data)) ++ { ++ _cairo_surface_release_source_image (source, surface, image_extra); ++ return _cairo_error (CAIRO_STATUS_NO_MEMORY); ++ } ++ ++ /* The last row of data may have less than stride bytes so make sure we ++ * only copy the minimum amount required from that row. ++ */ ++ memcpy (image_data, surface->data, ++ (surface->height - 1) * surface->stride + ++ cairo_format_stride_for_width (surface->format, ++ surface->width)); ++ *image_out = CairoQuartzCreateCGImageMask (surface->format, ++ surface->width, ++ surface->height, ++ surface->stride, ++ image_data, ++ TRUE, ++ DataProviderReleaseCallback, ++ image_data); ++ /* TODO: differentiate memory error and unsupported surface type */ ++ if (unlikely (*image_out == NULL)) ++ status = CAIRO_INT_STATUS_UNSUPPORTED; ++ + _cairo_surface_release_source_image (source, surface, image_extra); +- else +- acquired = TRUE; ++ return status; ++ } else { ++ image_surface = ++ (cairo_quartz_image_surface_t*)cairo_quartz_image_surface_create (&surface->base); ++ status = image_surface->base.status; ++ if (status) ++ _cairo_surface_release_source_image (source, surface, image_extra); ++ else ++ acquired = TRUE; ++ } + } + + *image_out = NULL; diff --git a/gfx/cairo/README b/gfx/cairo/README index 27f2cc14ca..e79e603ea7 100644 --- a/gfx/cairo/README +++ b/gfx/cairo/README @@ -7,217 +7,53 @@ http://www.cairographics.org/. VERSIONS: - cairo (277a1daec80cb6cf7bfb0e200cf78e7842cb2f82) - pixman (0.42.2) + cairo (1.18.0) + pixman (0.43.4) -==== Patches ==== +==== Local cairo patches ==== -Some specific things: +00-cairo_public.patch: allow cairo_public to be predefined -max-font-size.patch: Clamp freetype font size to 1000 to avoid overflow issues +01-xlib-xrender-private.patch: xrender build fix -win32-logical-font-scale.patch: set CAIRO_WIN32_LOGICAL_FONT_SCALE to 1 +02-cplusplus-no-register.patch: 'register' keyword not allowed when cairo.h is included by C++ code -nonfatal-assertions.patch: Make assertions non-fatal +03-expose-lcd-filter.patch: expose the LCD filter settings as public API -buggy-repeat.patch: Unconditionally turn on buggy-repeat handling to bandaid bug 413583. +04-subpixel-aa-api.patch: add API for setting subpixel-AA -cairo-version-fixes.patch: fix up cairo-version.c/cairo-version.h for in-place builds +05-ft-font-synth-flags-api.patch: enable client to control whether FreeType synthetic styles are allowed -win32-ddb-dib.patch: fix for bug 455513; not upstream yet pending feebdack +06-shared-ft-face.patch: integrate with Gecko SharedFTFace -win32-vertically-offset-glyph.patch: bug 454098; vertical positioning errors when drawing glyph runs including delta-y offsets on screen via GDI +07-ft-variations-runtime-check.patch: runtime check for FreeType variation support -ignore-rank0.patch: bug 474886; Not redrawing the background when changing page on flickr +09-quartz-surface-additions.patch: add cairo_quartz_surface_get_image -win32-canvas-glyph-position.patch: bug 475092; horizontal positioning errors when drawing glyph runs with delta-y offsets to canvas through win32-font +11-quartz-surface-tags.patch: support for LINK tags in the quartz-surface backend -win32-cleartype-clipping.patch: bug 445087; some glyphs are clipped, mainly on right-hand edge, when ClearType is enabled and drawing to RGBA canvas +12-quartz-named-destination.patch: support for named destinations in quartz-surface -on-edge.patch: reverts the in-fill semantic change. +17-active-edges-crash.patch: avoid potential crash in active_edges -wrap-source_image.patch: make sure we don't free the source image until we're done with it. +18-quartz-granular-ifdefs.patch: build fixes for iOS -zero-sized.patch: deal with zero sized surface in ways less likely to crash. +19-ft-color-ifdef.patch: FT_COLOR build fix -text-path-filling-threshold.patch: use path filling instead of platform glyph rasterization at a smaller size threshold of 256 device pixels, if the backend supports native filling (which we assume will be fast). +20-ios-colorspace.patch: iOS doesn't support per-display color spaces -zombie-face.patch: bug 486974; leak and possible crash with @font-face{src:url()}. Upstream commit: 0238fe2cafea2e1ed19bb222117bd73ee6898d4d +21-quartz-surface-leak.patch: fix DataSourceSurfaceRawData leak on quartz surface -win32-raster.patch: bug 498689; use scanline rasterizer on win32 +22-windows-build-fix.patch: build fix for Windows/non-mingw -quartz-falback.patch: try to fix Quartz fallback-to-pixman path; possiby incorrect and obsoleted by Andrea Canciani patch +23-win32-api-additions.patch: Windows API additions for gecko -quartz-repeating-radial-gradients.patch: use Quartz to render repeating radial gradients instead of falling back - -quartz-const-globals.patch: make some Quartz color function data const globals instead of local variables - -quartz-minimze-gradient-repeat.patch: reduce the number of gradient stop repetitions we use, to improve quality of Quartz's gradient rendering - -quartz-first-stop.patch: return the first stop for negative positions on the gradient line of a nonrepeating linear gradient - -quartz-glyph-extents.patch: bug 534260; work around incorrect glyph extents returned by quartz for anomalous empty glyphs - -quartz-state.patch: bug 522859; refactor cairo-quartz-surface so that state local to a drawing operation is stored in a cairo_quartz_drawing_state_t instead of the surface - -quartz-cache-CGImageRef.patch: cache CGImageRef for a CGBitmapContext; when we reuse it, Quartz will cache stuff, improving performance - -quartz-remove-snapshot.patch: remove broken implementation of backend snapshot - -quartz-cglayers.patch: add support for cairo surfaces backed by CGLayers - -quartz-cglayers-fix-fallback.patch: Bug 572912; fix bug in fallback code in previous patch - -quartz-get-image.patch: Bug 575521; add a way to get the image surface associated with a surface - -quartz-create-for-data.patch: Bug 575521; add a way to create quartz surfaces backed with application-provided data - -premultiply-alpha-solid-gradients.patch: bug 539165; multiply the solid color by the alpha component before using it for a solid surface - -xlib-initialize-members.path: bug 548793; initialize XRender version if the server doesn't have the extension - -remove-comma: remove a comma from enum - -d2d.patch: add d2d support - -fix-zero-len-graident.patch: fix zero length gradients - -fix-clip-copy.patch: fix clip copying - -fix-clip-region-simplification.patch: fixes a bug in clip region simplifications - -expand-in-stroke-limits.patch: expand the in-stroke limits to avoid a bug - -d2d-dwrite.patch: update the d2d/dwrite stuff - -add-a-stash-of-cairo_t-s.patch: use the stash to avoid malloc/freeing cairo_t's - -bgr.patch: fix image wrapping - -disable-server-graidents.patch: disable server-side gradients - -clip-invariant.patch: make rasterization closer to being clip invariant - -fix-unnecessary-fallback.patch: avoid unnecessary fallback - -handle-a1-upload.patch: handle a1 image uploads through converter - -surface-clipper.patch: remove an incorrect optimization - -fix-win32-show-glyphs-clipping.patch: fix a clipping bug - -native-clipping.patch: Add support for a native clipping api - -quartz-is-clear.patch: Propagate the quartz is_clear flag. - -cairo-qt-compile.patch: Fix compile error, return not reached, and clone_similar interface - -dwrite-glyph-extents.patch: Add padding to extents of antialiased glyphs, to avoid unwanted clipping. (bug 568191) - -fix-ps-output.patch: PS: Add missing 'q' when resetting clip path (42b5cac7668625c9761113ff72b47af5cfd10377) - -ensure-text-flushed.patch: PDF-operators: ensure text operations flushed before emitting clip (42b5cac7668625c9761113ff72b47af5cfd10377) - -fix-xcopyarea-with-clips.patch: 5d07307b691afccccbb15f773d5231669ba44f5a - -cairo-x-visual.patch: make valid visua for cairo_xlib_surface_create_with_xrender_format (55037bfb2454a671332d961e061c712ab5471580) - -win32-transparent-surface.patch: add API so we can create a win32 surface for an HDC and indicate the surface has an alpha channel - -cairo_qt_glyphs.patch: Drop X surface from Qt surface, add support for new qt glyphs api - -empty-clip-rectangles.patch: f2fa15680ec3ac95cb68d4957557f06561a7dc55 - -empty-clip-extents.patch: b79ea8a6cab8bd28aebecf6e1e8229d5ac017264 - -clip-rects-surface-extents.patch: 108b1c7825116ed3f93aa57384bbd3290cdc9181 - -disable-previous-scaled-font-cache.patch: Disable the previous-scaled-font-cache until we figure out our ctm handling (#583035) - -copyarea-with-alpha.patch: support simple overlapping self copies in (some) color_alpha xlib surfaces. https://bugs.freedesktop.org/show_bug.cgi?id=29250 - -fix-clip-test.patch: Use y 498c10032ea3f8631a928cd7df96766f2c8ddca4 - -quartz-refactor-surface-setup.patch: Extract the surface-source setup chunk of _cairo_quartz_setup_state into its own function - -quartz-fix-PAD.patch: Treat PAD like NONE instead of REPEAT - -quartz-mask-non-OVER.patch: Don't use CGContextSetAlpha to optimize alpha masking for non-OVER operators - -quartz-layers-content.patch: Store cairo content type in CGLayer surfaces - -quartz-optimize-OVER.patch: Optimize OVER to SOURCE for opaque patterns - -quartz-check-imageSurfaceEquiv.patch: Drop cairo_quartz_surface_t's "imageSurfaceEquiv" member variable if we have problems creating it - -disable-subpixel-antialiasing.patch: Add API to disable subpixel antialiasing completely for a target surface - -tee-surfaces-pointwise.patch: Composite tee subsurfaces pointwise if possible - -pattern_get_surface-no-error.patch: Don't put a pattern into error if cairo_pattern_get_surface fails - -missing-cairo-clip-init.diff: Missing cairo_clip_init call in cairo_gstate_show_text_glyphs lead to crash - -fix-cairo-win32-print-gdi-error.diff: Don't use fwprintf with char* format. Flush stderr so that all error messages appears before exit. - -pixman-image-transform.patch: Reset the transform on pixman images when using them as destinations. - -fix-cairo-surface-wrapper-flush-build-warning.patch: Ensures that _cairo_surface_wrapper_flush always returns a status, to silence the build warning - -fixup-unbounded.patch: Hack to work around bad assumption. - -quartz-get-image-performance: Make cairo_quartz_get_image faster in the failure case by not flushing unless we are going to succeed. - -lround-c99-only.patch: Only use lround in C99 programs. - -unicode-printing.patch: Print as unicode (bug 454532) - -quartz-mark-dirty.patch: Add a quartz implementation of mark_dirty_rectangle (bug 715704) - -expose-snapshot.patch: Make functions to add snapshots public, as well as allow creating null surfaces publically. (bug 715658) - -fix-build-with-Werror=return-type.patch: Fix builds with -Werror=return-type (bug 737909) - -avoid-extend-none.patch: Avoid incorrectly using EXTEND_NONE (bug 751668) - -win32-ExtCreatePen-zero-size.patch: Don't pass zero width or dash lengths to ExtCreatePen (bug 768348) - -d2d-repeating-gradients.patch: Minimize number of gradient stops added to handle repeating with path fills (bug 768775) - -xlib-glyph-clip-region.patch: bug 709477, addressed upstream by be1ff2f45fdbc69537e513834fcffa0435e63073 - -gdi-RGB24-ARGB32.patch: bug 788794 - -dwrite-font-printing.patch: bug 468568; don't substitute a GDI font for a DWrite font if the name tables aren't equal - -d2d-gradient-ensure-stops.patch: bug 792903, ensure we don't set num_stops to 0 - -setlcdfilter_in_tree.patch: bug 790139; force cairo to use FT_Library_SetLcdFilter from our in tree library rather than picking it up from the system - -dwrite-font-match-robustness.patch: bug 717178, don't crash when _name_tables_match is passed a nil scaled-font - -handle-multi-path-clip.patch: bug 813124, handle multiple clip paths correctly - -win32-gdi-font-cache.patch: Bug 717178, cache GDI font faces to reduce usage of GDI resources - -win32-gdi-font-cache-no-HFONT.patch: Bug 717178, don't cache GDI font faces when an HFONT belonging to the caller is passed in - -fix-win32-font-assertion.patch: Bug 838617, fix assertion from bug 717178 that was in the wrong place - -xlib-flush-glyphs.patch: bug 839745, flush glyphs when necessary - -dasharray-zero-gap.patch: bug 885585, ensure strokes get painted when the gaps in a dash array are all zero length - -cairo-mask-extends-bug.patch: bug 918671, sometimes when building a mask we wouldn't clear it properly. This is fixed in cairo 1.12 - -ft-no-subpixel-if-surface-disables.patch: bug 929451, don't use subpixel aa for ft fonts on surfaces that don't support it - -win32-printing-axis-swap.patch: bug 1205854, workaround for Windows printer drivers that can't handle swapped X and Y axes - -no-pixman-image-reuse-across-threads.patch: bug 1273701, picked from 71e8a4c23019b01aa43b334fcb2784c70daae9b5 +cff-font-creation.patch: make cairo_cff_font_t allocation consistent ==== pixman patches ==== +pixman-armasm.patch: add an ifdef guard around pixman-config.h include + pixman-clangcl.patch: clang-cl compilation fix pixman-export.patch: make sure pixman symbols are not exported in libxul @@ -226,32 +62,4 @@ pixman-interp.patch: use lower quality interpolation by default on mobile pixman-intrin.patch: include intrin.h on Windows to fix bustage -pixman-mingw32.patch: include xmmintrin.h on MINGW32 builds to avoid redefinition - pixman-rename.patch: include pixman-rename.h for renaming of external symbols - -pixman-arm32-clang.patch: don't use -no-integrated-as for arm32 - -pixman-arm64-clang.patch: don't use -no-integrated-as for aarch64 - -quartz-support-color-emoji-font.patch: support Apple Color Emoji font in cairo-quartz backend - -use-show-text-glyphs-if-glyph-path-fails.patch: fall back to show_text_glyphs even at huge sizes if scaled_font_glyph_path didn't work - -win32-d3dsurface9.patch: Create a win32 d3d9 surface to support LockRect - -win32-avoid-extend-pad-fallback: Avoid falling back to pixman when using EXTEND_PAD - -support-new-style-atomic-primitives.patch: Support the __atomic_* primitives for atomic operations - -clang-cl-popcount.patch: Use __builtin_popcount for Clang (including clang-cl) - -==== disable printing patch ==== - -disable-printing.patch: allows us to use NS_PRINTING to disable printing. - -==== cairo clamp bounday patch ==== -cairo-clamp-boundary.patch: don't call pixman_fill with negative starts or negative sizes - -==== cairo zero subpath bounds patch ==== -zero-subpath-bounds.patch: include zero length paths in bounds diff --git a/gfx/cairo/cairo/BUGS b/gfx/cairo/cairo/BUGS new file mode 100644 index 0000000000..452d523006 --- /dev/null +++ b/gfx/cairo/cairo/BUGS @@ -0,0 +1,85 @@ +If you find a bug in cairo we would love to hear about it. We're also +trying to make cairo better, and learning about the bugs that users +encounter is an essential part of that. So we really appreciate the +extra effort users put in to providing high-quality bug reports. + +There are two acceptable ways to report cairo bugs, and you can choose +which you prefer: + +1) Bugzilla bug tracking database: + + You can use the following web interface to report new bugs, follow + up on previous bug reports, and search for existing, known + bugs. Just use the "cairo" product: + + https://bugs.freedesktop.org + + It is necessary to go through a quick account creation process, + (with email address verification), in order to be able to report + new bugs in bugzilla. We apologize for any inconvenience that might + cause, and hope it won't prevent you from reporting bugs. + +2) Cairo mailing list: + + For people who cannot stand the bugzilla interface, you can just + send an email to cairo mailing list (cairo@cairographics.org). The + mailing list only allows posting from subscribers, so use the + following page for subscription instructions: + + https://cairographics.org/lists + + Again, we apologize for any inconvenience this subscription step + might cause, but we've found it necessary to require this in order + to enjoy spam-free discussions on the list. + + If you don't actually _want_ to be a subscriber to the mailing + list, but just want to be able to send a message, the easiest thing + to do is to go through the subscription process, and then use the + preferences page to disable message delivery to your address. + +Which of the above you use to report bugs depends on your own +preferences. Some people find just typing an email message much easier +than using the web-based forms on bugzilla. Others greatly prefer the +ability to check back on a specific bug entry in bugzilla without +having to ask on the mailing list if an issue has been resolved. + +Regardless of which method you use, here are some general tips that +will help you improve the quality of your bug report, (which will help +in getting the bug fixed sooner): + +1) Check to see if the bug has been reported already. It's pretty easy + to run a search or two against the cairo product in the + https://bugs.freedesktop.org bugzilla database. Another place to + look for known bugs is the cairo ROADMAP: + + https://cairographics.org/ROADMAP + + which shows a planned schedule of releases and which bug fixes are + being planned for each release. + +2) Provide an accurate description of the bug with detailed steps for + how we can reproduce the problem. + +3) If possible provide a minimal test case demonstrating the bug. A + great test case would be a minimal self-contained function in C or + python or whatever language you are using for cairo. The function + might accept nothing more than a cairo context, (cairo_t* in C). + +4) If you feel like being particularly helpful, you could craft this + minimal test case in the form necessary for cairo's test + suite. This isn't much more work than writing a minimal + function. Just look at the cairo/test/README file and imitate the + style of existing test cases. + + If you do submit a test case, be sure to include Copyright + information, (with the standard MIT licensing blurb if you want us + to include your test in the test case). Also, including a reference + image showing the expected result will be extremely useful. + +5) Finally, the best bug report also comes attached with a patch to + cairo to fix the bug. So send this too if you have it! Otherwise, + don't worry about it and we'll try to fix cairo when we can. + +Thanks, and have fun with cairo! + +-Carl diff --git a/gfx/cairo/cairo/CODING_STYLE b/gfx/cairo/cairo/CODING_STYLE new file mode 100644 index 0000000000..7e96c36d1a --- /dev/null +++ b/gfx/cairo/cairo/CODING_STYLE @@ -0,0 +1,292 @@ +Cairo coding style. + +This document is intended to be a short description of the preferred +coding style for the cairo source code. Good style requires good +taste, which means this can't all be reduced to automated rules, and +there are exceptions. + +We want the code to be easy to understand and maintain, and consistent +style plays an important part in that, even if some of the specific +details seem trivial. If nothing else, this document gives a place to +put consistent answers for issues that would otherwise be arbitrary. + +Most of the guidelines here are demonstrated by examples, (which means +this document is quicker to read than it might appear given its +length). Most of the examples are positive examples that you should +imitate. The few negative examples are clearly marked with a comment +of /* Yuck! */. Please don't submit code to cairo that looks like any +of these. + +Indentation +----------- +Each new level is indented 4 more spaces than the previous level: + + if (condition) + do_something (); + +This may be achieved with space characters or a combination of tab +characters and space characters. It may not be achieved with tab +characters exclusively (see below). + +Tab characters +-------------- +The tab character must always be interpreted according to its +traditional meaning: + + Advance to the next column which is a multiple of 8. + +With this definition, even levels of indentation can be achieved with +a sequence of tab characters, while odd levels of indentation may +begin with a sequence of tab character but must end with 4 space +characters. + +Some programmers have been misled by certain text editors into +thinking that 4-space indentation can be achieved with tab characters +exclusively by changing the meaning of tab character to be "advance to +the next column which is a multiple of 4". Code formatted in this way, +making an assumption of a fictitious 4-character-tab will not be +accepted into cairo. + +The rationale here is that tabs are used in the code for lining things +up other than indentation, (see the Whitespace section below), and +changing the interpretation of tab from its traditional meaning will +break this alignment. + +Braces +------ +Most of the code in cairo uses bracing in the style of K&R: + + if (condition) { + do_this (); + do_that (); + } else { + do_the_other (); + } + +but some of the code uses an alternate style: + + if (condition) + { + do_this (); + do_that (); + } + else + { + do_the_other (); + } + +and that seems just fine. We won't lay down any strict rule on this +point, (though there should be some local consistency). If you came +here hoping to find some guidance, then use the first form above. + +If all of the substatements of an if statement are single statements, +the optional braces should not usually appear: + + if (condition) + do_this (); + else + do_that (); + +But the braces are mandatory when mixing single statement and compound +statements in the various clauses. For example, do not do this: + + if (condition) { + do_this (); + do_that (); + } else /* Yuck! */ + do_the_other (); + +And of course, there are exceptions for when the code just looks +better with the braces: + + if (condition) { + /* Note that we have to be careful here. */ + do_something_dangerous (with_care); + } + + if (condition && + other_condition && + yet_another) + { + do_something (); + } + +And note that this last example also shows a situation in which the +opening brace really needs to be on its own line. The following looks awful: + + if (condition && + other_condition && + yet_another) { /* Yuck! */ + do_something (); + } + +As we said above, legible code that is easy to understand and maintain +is the goal, not adherence to strict rules. + +Whitespace +---------- +Separate logically distinct chunks with a single newline. This +obviously applies between functions, but also applies within a +function or block and can even be used to good effect within a +structure definition: + + struct _cairo_gstate { + cairo_operator_t op; + + double tolerance; + + /* stroke style */ + double line_width; + cairo_line_cap_t line_cap; + cairo_line_join_t line_join; + double miter_limit; + + cairo_fill_rule_t fill_rule; + + double *dash; + int num_dashes; + double dash_offset; + + ... + } + +Use a single space before a left parenthesis, except where the +standard will not allow it, (eg. when defining a parameterized macro). + +Don't eliminate newlines just because things would still fit on one +line. This breaks the expected visual structure of the code making it +much harder to read and understand: + + if (condition) foo (); else bar (); /* Yuck! */ + +Do eliminate trailing whitespace (space or tab characters) on any +line. Also, avoid putting initial or final blank lines into any file, +and never use multiple blank lines instead of a single blank line. + +Do enable the default git pre-commit hook that detect trailing +whitespace for you and help you to avoid corrupting cairo's tree with +it. Do that as follows: + + chmod a+x .git/hooks/pre-commit + +You might also find the git-stripspace utility helpful which acts as a +filter to remove trailing whitespace as well as initial, final, and +duplicate blank lines. + +As a special case of the bracing and whitespace guidelines, function +definitions should always take the following form: + + void + my_function (argument) + { + do_my_things (); + } + +And function prototypes should similarly have the return type (and +associated specifiers and qualifiers) on a line above the function, so +that the function name is flush left. + +Break up long lines (> ~80 characters) and use whitespace to align +things nicely. For example the arguments in a long list to a function +call should all be aligned with each other: + + align_function_arguments (argument_the_first, + argument_the_second, + argument_the_third); + +And as a special rule, in a function prototype, (as well as in the +definition), whitespace should be inserted between the parameter types +and names so that the names are aligned: + + void + align_parameter_names_in_prototypes (const char *char_star_arg, + int int_arg, + double *double_star_arg, + double double_arg); + +Note that parameters with a * prefix are aligned one character to the +left so that the actual names are aligned. + +Managing nested blocks +---------------------- +Long blocks that are deeply nested make the code very hard to +read. Fortunately such blocks often indicate logically distinct chunks +of functionality that are begging to be split into their own +functions. Please listen to the blocks when they beg. + +In other cases, gratuitous nesting comes about because the primary +functionality gets buried in a nested block rather than living at the +primary level where it belongs. Consider the following: + + foo = malloc (sizeof (foo_t)); + if (foo) { /* Yuck! */ + ... + /* lots of code to initialize foo */ + ... + return SUCCESS; + } + return FAILURE; + +This kind of gratuitous nesting can be avoided by following a pattern +of handling exceptional cases early and returning: + + foo = malloc (sizeof (foo_t)); + if (foo == NULL) + return FAILURE; + + ... + /* lots of code to initialize foo */ + ... + return SUCCESS; + +The return statement is often the best thing to use in a pattern like +this. If it's not available due to additional nesting above which +require some cleanup after the current block, then consider splitting +the current block into a new function before using goto. + +Memory allocation +----------------- + +Because much of cairo's data consists of dynamically allocated arrays, +it's very easy to introduce integer overflow issues whenever malloc() +is called. Use the _cairo_malloc2(), _cairo_malloc3(), and +_cairo_malloc2_add1 macros to avoid these cases; these macros check +for overflow and will return NULL in that case. + + malloc (n * size) => _cairo_malloc_ab (n, size) + e.g. malloc (num_elts * sizeof(some_type)) => + _cairo_malloc2 (num_elts, sizeof(some_type)) + + malloc (a * b * size) => _cairo_malloc_abc (a, b, size) + e.g. malloc (width * height * 4) => + _cairo_malloc3 (width, height, 4) + + malloc (n * size + k) => _cairo_malloc_ab_plus_c (n, size, k) + e.g. malloc (num * sizeof(entry) + sizeof(header)) => + _cairo_malloc2k (num, sizeof(entry), sizeof(header)) + +In general, be wary of performing any arithmetic operations in an +argument to malloc. You should explicitly check for integer overflow +yourself in any more complex situations. + +Mode lines +---------- + +So given the rules above, what is the best way to simplify one's life as +a code monkey? Get your editor to do most of the tedious work of +beautifying your code! + +As a reward for reading this far, here are some mode lines for the more +popular editors: +/* + * vim:sw=4:sts=4:ts=8:tw=78:fo=tcroq:cindent:cino=\:0,(0 + * vim:isk=a-z,A-Z,48-57,_,.,-,> + * -*- Mode: c; tab-width: 8; c-basic-offset: 4; indent-tabs-mode: t; -*- + */ + + +TODO +---- + +Write rules for common editors to use this style. Also cleanup/unify +the modelines in the source files. diff --git a/gfx/cairo/cairo/HACKING b/gfx/cairo/cairo/HACKING new file mode 100644 index 0000000000..bc97f53248 --- /dev/null +++ b/gfx/cairo/cairo/HACKING @@ -0,0 +1,185 @@ +Hacking Cairo +============= + +This is a high-level guide to how the cairo distribution is organized +and how to get started hacking on it. Make sure you read through the +file README before continuing. + + +Coding Style +------------ + +The easiest way to write code in the cairo style is to follow code close +to the place you are hacking, but if you want a written down set of +rules, see file CODING_STYLE. + +Files for backends that depend on languages other than C (C++ or +Objective C for example) may use features specific to those languages. +For example, "//" comments are allowed, though discouraged, in those files. + + +Contact +------- + +Various ways to get in touch with other cairo developers and maintainers +have been enumerated at: + + https://cairographics.org/contact/ + +Most of that information is also reflected in the following sections. + + +Mailing Lists +------------- + +There are various mailing lists that are useful when developing cairo +code. A complete list is always available at: + + https://cairographics.org/lists/ + +It is recommended that cairo developers subscribe to all those lists. +The cairo list by itself generates much more traffic than the others +combined, so developers and contributors should not be intimidated by +the -commit and -bugs lists. + + +Bug Tracking System +------------------- + +We use a standard bugzilla bug tracking system available at: + + https://bugs.freedesktop.org/ + +See file named BUGS for detailed information on reporting bugs. In short, +for straight bug reports, it's best to report them there such that they +are not lost or forgotten. For discussion of new features or +complicated issues, use the mailing list. + + +IRC +--- + +It's a great idea to hang around the cairo IRC channel if you have any +interest in cairo. We use the #cairo channel on irc.freenode.net. + +Make sure you introduce yourself if your nick is not easy to match to +the name you use on the mailing list. + + +Version Control System +---------------------- + +We use /git/ for version control. See: + + https://cairographics.org/download/ + +For more information on using git, see: + + https://freedesktop.org/wiki/Infrastructure/git/ + + +Build System +------------ + +We use the autotools build system with cairo, but with various +customizations and advanced features. Reading configure.in is your +best bet to understanding it, or just ask on IRC. + +To bootstrap the build system run ./autogen.sh. After that the +regular "./configure; make; make install" sequence can be used. +See file named INSTALL for more details. + +There is limited support for a win32 build system. +See README.win32 and Makefile.win32 files in various directories. + + +ChangeLog +--------- + +We generate ChangeLog files automatically from the git commit log. +No manual ChangeLog writing is necessary. + + +Copyrights and Licensing +------------------------ + +The cairo library is dual-licensed under LGPL and MPL. See the file +named COPYING for details. The test suites are more liberal, and are +allowed to include GPL code. + +When writing new code, update the file headers to add your (or your +employers) copyright line and contributor line. If adding new files +or splitting a file, copy the file header from other files. + + +Source Code +----------- + +The library source code and headers live in the src/ directory. +See src/README for more information. + + +Regression Test Suite +--------------------- + +Cairo has a fairly extensive regression-testing suite. Indeed, without +these tests it would be impossible to make a cairo release without +introducing tens of regressions. We still manage to introduce +regressions with each release even with the hundreds of tests we already +have. + +The regression test suite is located under the test/ directory. +See test/README for more information. + + +Performance Test Suite +---------------------- + +There is a performance test suite located under the perf/ directory. +A collection of traces of real-world behavior are also available in the +cairo-traces repository, which can be used in isolation or hooked in +with the main performance test suite. See perf/README for more +information. + + +Boilerplate +----------- + +The cairo-boilerplate is a small private library used by the regression +and performance test suites. It includes the boilerplace code needed +to initialize various backends for the test suites, as well as allow +tweaking some of the internal workings of the backends for more testing. + +The boilerplate code is localted under the boilerplate/ directory. +See boilerplate/README for more information. + + +Documentation +------------- + +Cairo uses the gtk-doc system for reference API documentation. + +The reference documentation is located under doc/public. +See doc/public/README for more information. + +For more documentation including frequently asked questions, tutorials, +samples, roadmap, todo list, etc visit: + + https://cairographics.org/documentation/ + +Some of those should gradually be moved to doc/. + + +Utilities +--------- + +We have developed several utilities useful for writing cairo or code +that uses cairo. These tools can be found under the util/ directory. +See util/README for more information. + + +Releasing +--------- + +Now you are a cairo maintainer, so what? See file named RELEASING. + diff --git a/gfx/cairo/cairo/INSTALL b/gfx/cairo/cairo/INSTALL index dfdc2139ed..2229680496 100644 --- a/gfx/cairo/cairo/INSTALL +++ b/gfx/cairo/cairo/INSTALL @@ -1,184 +1,47 @@ -Quick-start build instructions ------------------------------- -1) Configure the package: +Installation Instructions +========================= - ./configure +Requirements +------------ +As well as the requirements listed in README, the meson build also requires: + meson (http://mesonbuild.com) + ninja (http://ninja-build.org) -2) Compile it: +Basic Installation +------------------ + meson setup $builddir + ninja -C $builddir + ninja -C $builddir install - make +where $builddir is the name of the directory where the build artifacts +will be written to. -3) Install it: +Some of the common options that can be used with "meson setup" include: - make install +Set the install prefix. + --prefix=<path> -This final step may require temporary root access (eg. with sudo) if -you don't have write permission to the directory in which cairo will -be installed. +Set the build type. Some common build types include "debug" and "release" + --buildtype=<buildtype> -NOTE: If you are working with source from git/cvs rather than from a tar -file, then you should use ./autogen.sh in place of ./configure -anywhere it is mentioned in these instructions. +Compiler and linker flags can be set with the CFLAGS and LDFLAGS +environment variables. -More detailed build instructions --------------------------------- -1) Configure the package +Configuring cairo backends +-------------------------- +After running "meson build", "meson configure" can be used to display +or modify the build configuration. - The first step in building cairo is to configure the package by - running the configure script. [Note: if you don't have a configure - script, skip down below to the Extremely detailed build - instructions.] +eg - The configure script attempts to automatically detect as much as - possible about your system. So, you should primarily just accept - its defaults by running: + Display configuration: + meson configure $builddir - ./configure + Enable pdf and disable ps: + meson configure $builddir -Dpdf=enabled -Dps=disabled - The configure script does accept a large number of options for - fine-tuning its behavior. See "./configure --help" for a complete - list. The most commonly used options are discussed here. +The "-D" options can also be used with "meson setup" - --prefix=PREFIX - - This option specifies the directory under which the software - should be installed. By default configure will choose a - directory such as /usr/local. If you would like to install - cairo to some other location, pass the director to configure - with the --prefix option. For example: - - ./configure --prefix=/opt/cairo - - would install cairo into the /opt/cairo directory. You could - also choose a prefix directory within your home directory if - you don't have write access to any system-wide directory. - - After installing into a custom prefix, you will need to set - some environment variables to allow the software to be - found. Assuming the /opt/cairo prefix and assuming you are - using the bash shell, the following environment variables - should be set: - - PKG_CONFIG_PATH=/opt/cairo/lib/pkgconfig - LD_LIBRARY_PATH=/opt/cairo/lib - export PKG_CONFIG_PATH LD_LIBRARY_PATH - - (NOTE: On Mac OS X, at least, use DYLD_LIBRARY_PATH in place - of LD_LIBRARY_PATH above.) - - --enable-XYZ - --enable-XYZ=yes - --enable-XYZ=auto - --enable-XYZ=no - --disable-XYZ - - Cairo's various font and surface backends and other features can be - enabled or disabled at configure time. Features can be divided into - three categories based on their default state: - - * default=yes: These are the recommended features like PNG functions - and PS/PDF/SVG backends. It is highly recommended to not disable - these features but if that's really what one wants, they can be - disabled using --disable-XYZ. - - * default=auto: These are the "native" features, that is, they are - platform specific, like the Xlib surface backend. You probably - want one or two of these. They will be automatically enabled if - all their required facilities are available. Or you can use - --enable-XYZ or --disable-XYZ to make your desire clear, and then - cairo errs during configure if your intention cannot be followed. - - * default=no: These are the "experimental" features, and hence by - default off. Use --enable-XYZ to enable them. - - The list of all features and their default state can be seen in the - output of ./configure --help. - -2) Compile the package: - - This step is very simple. Just: - - make - - The Makefiles included with cairo are designed to work on as many - different systems as possible. - - When cairo is compiled, you can also run some automated tests of - cairo with: - - make check - - NOTE: Some versions of X servers will cause the -xlib tests to - report failures in make check even when cairo is working just - fine. If you see failures in nothing but -xlib tests, please - examine the corresponding -xlib-out.png images and compare them to - the -ref.png reference images (the -xlib-diff.png images might also - be useful). If the results seem "close enough" please do not report - a bug against cairo as the "failures" you are seeing are just due - to subtle variations in X server implementations. - -3) Install the package: - - The final step is to install the package with: - - make install - - If you are installing to a system-wide location you may need to - temporarily acquire root access in order to perform this - operation. A good way to do this is to use the sudo program: - - sudo make install - -Extremely detailed build instructions -------------------------------------- -So you want to build cairo but it didn't come with a configure -script. This is probably because you have checked out the latest -in-development code via git. If you need to be on the bleeding edge, -(for example, because you're wanting to develop some aspect of cairo -itself), then you're in the right place and should read on. - -However, if you don't need such a bleeding-edge version of cairo, then -you might prefer to start by building the latest stable cairo release: - - https://cairographics.org/releases - -or perhaps the latest (unstable) development snapshot: - - https://cairographics.org/snapshots - -There you'll find nicely packaged tar files that include a configure -script so you can go back the the simpler instructions above. - -But you're still reading, so you're someone that loves to -learn. Excellent! We hope you'll learn enough to make some excellent -contributions to cairo. Since you're not using a packaged tar file, -you're going to need some additional tools beyond just a C compiler in -order to compile cairo. Specifically, you need the following utilities: - - automake - autoconf - autoheader - aclocal - libtoolize - pkg-config [at least version 0.16] - gtk-doc (recommended) - -Hopefully your platform of choice has packages readily available so -that you can easily install things with your system's package -management tool, (such as "apt-get install automake" on Debian or "yum -install automake" on Fedora, etc.). Note that Mac OS X ships with -glibtoolize instead of libtoolize. - -Once you have all of those packages installed, the next step is to run -the autogen.sh script. That can be as simple as: - - ./autogen.sh - -But before you run that command, note that the autogen.sh script -accepts all the same arguments as the configure script, (and in fact, -will generate the configure script and run it with the arguments you -provide). So go back up to step (1) above and see what additional -arguments you might want to pass, (such as prefix). Then continue with -the instructions, simply using ./autogen.sh in place of ./configure. - -Happy hacking! +Tests +----- +Refer to test/README diff --git a/gfx/cairo/cairo/NEWS b/gfx/cairo/cairo/NEWS index 3eeb1c389e..49acef8706 100644 --- a/gfx/cairo/cairo/NEWS +++ b/gfx/cairo/cairo/NEWS @@ -1,3 +1,129 @@ +Release 1.18.0 (2023-09-20 Emmanuele Bassi <ebassi@gnome.org>) +============================================================== + +The first stable cairo release in five years should be cause for celebration. + +All the API added in the 1.17 development cycle is now considered stable, and +will not change. + +Many thanks to all the contributors for this release. + +The cairo-sphinx tool has been removed; we could not find any instruction on +how to use it, and no user answered our call for help. If you were using +cairo-sphinx, please reach out to the cairo maintainers. + +Cairo now implements Type 3 color fonts for PDF. Thanks to Adrian Johnson for +his work on this feature. + +Khaled Hosny contributed multiple documentation fixes, to ensure that the +cairo API reference is up to date. Khaled also fixed multiple compiler +warnings generated when building cairo. + +The XML surface has been removed; it was disabled by default when building +cairo, and we could not find any downstream distributor that would enable +it. + +The Tee surface is now automatically enabled. Downstream distributors of +cairo have been enabling for years it in order to build Firefox. + +Fujii Hironori and Adrian Johnson fixed multiple issues with the DWrite +font backend. + +John Ralls improved the Quartz surface; mainly, Quartz surfaces now use +the main display ColorSpace, speeding up rendering operations. + +Cairo now hides all private symbols by default on every platform; the old +"slim" symbols hack to alias internally used symbols has been dropped, in +favor of using `-Bsymbolic-functions` with toolchains that support it. + +Uli Schlachter fixed multiple memory leaks in the code base and test suite, +and helped with many reviews and general maintenance. + +Marc Jeanmougin added new API to expose the Pixman dithering filter to cairo +patterns; this is currently implemented only for image surfaces. + +Release 1.17.8 (2023-01-30 Emmanuele Bassi <ebassi@gnome.org>) +============================================================== + +A new cairo snapshot! And it only took less than one year, this time! + +Many thanks to everyone who contributed to cairo, and especially +to (in no particular order): + +- Adrian Johnson +- Khaled Hosny +- Behdad Esfahbod +- Matthias Clasen +- Uli Schlachter +- Manuel Stoeckl +- Fujii Hironori +- Tim-Philipp Müller +- Luca Bacci +- Caolán McNamara +- John Ralls + +In a continuing effort to reduce the amount of legacy code, and increase +the long-term maintainability of cairo, the following backends have been +removed: + +- GL and GLES drawing + +Additionally, cairo's Autotools build system has been removed; from now on, +cairo will only support the Meson build system. While the end result should +be identical, further testing is appreciated. + +In this snapshot, cairo gained support for rendering COLRv1 fonts, and +rendering SVG and COLRv1 fonts with custom palettes. + +Support for macOS and Windows has been improved, with lots of build and bug +fixes. + +Lots of safety issues have been fixed, with array bounds checking and +plugging memory leaks, as well as fixes for bugs identified via fuzzying. + +This is going to be the last snapshot of the 1.17 development cycle; we only +expect minor bug fixing and improvements until the 1.18.0 release. + +Release 1.17.6 (2022-03-18 Emmanuele Bassi <ebassi@gnome.org>) +============================================================== + +I spy with my little eye… a cairo snapshot! + +First of all, many, many thanks to everyone who contributed to cairo +during this development cycle. A special thank you goes to: + +- Adrian Johnson +- Uli Schlachter + +for their tireless efforts in ensuring that the lights are still on +in the cairo project. + +This snapshot sees the removal of the following backends and platform +support: + +- Qt4 +- BeOS +- OS/2 +- DirectFB +- DRM +- Cogl +- OpenVG + +Thanks to all past contributors for their work on them. If you were using +any of these backends then you will need to stick to cairo 1.16. + +To offset the removal of the backends above, Adrian Johnson landed the +DWrite font rendering backend on Windows. + +There have been multiple improvements in the Quartz backend, courtesy of +John Ralls. + +Tim-Philipp Müller has kept the Meson build in top shape. + +This snapshot is going to be the **last** release of cairo with the +Autotools build system. The Meson build has seen many improvements and +it is considerably easier to maintain and faster to build. + Release 1.17.4 (2020-11-27 Bryce Harrington <bryce@bryceharrington.org>) ======================================================================== @@ -26,7 +152,7 @@ includes implementation of core functionality, performance optimizations, and stabilization. Subpixel positioning support allows improved glyph outlines with the -Freetype font backend. +FreeType font backend. For a complete log of changes, please see @@ -8141,7 +8267,7 @@ the PNG generation in the demos. These have now been resolved. 2003-10 ======= Graydon Hoare <graydon@redhat.com> implemented the first real text -support using Freetype/fontconfig, (previous versions of cairo used +support using FreeType/fontconfig, (previous versions of cairo used Xft and could only draw text when using an X backend). 2003-09 diff --git a/gfx/cairo/cairo/README b/gfx/cairo/cairo/README deleted file mode 100644 index 0bcf140121..0000000000 --- a/gfx/cairo/cairo/README +++ /dev/null @@ -1,198 +0,0 @@ -Cairo - Multi-platform 2D graphics library -https://cairographics.org - -What is cairo -============= -Cairo is a 2D graphics library with support for multiple output -devices. Currently supported output targets include the X Window -System (via both Xlib and XCB), quartz, win32, and image buffers, -as well as PDF, PostScript, and SVG file output. Experimental backends -include OpenGL, BeOS, OS/2, and DirectFB. - -Cairo is designed to produce consistent output on all output media -while taking advantage of display hardware acceleration when available -(for example, through the X Render Extension). - -The cairo API provides operations similar to the drawing operators of -PostScript and PDF. Operations in cairo include stroking and filling -cubic Bézier splines, transforming and compositing translucent images, -and antialiased text rendering. All drawing operations can be -transformed by any affine transformation (scale, rotation, shear, -etc.). - -Cairo has been designed to let you draw anything you want in a modern -2D graphical user interface. At the same time, the cairo API has been -designed to be as fun and easy to learn as possible. If you're not -having fun while programming with cairo, then we have failed -somewhere---let us know and we'll try to fix it next time around. - -Cairo is free software and is available to be redistributed and/or -modified under the terms of either the GNU Lesser General Public -License (LGPL) version 2.1 or the Mozilla Public License (MPL) version -1.1. - -Where to get more information about cairo -========================================= -The primary source of information about cairo is: - - https://cairographics.org/ - -The latest versions of cairo can always be found at: - - https://cairographics.org/download - -Documentation on using cairo and frequently-asked questions: - - https://cairographics.org/documentation - https://cairographics.org/FAQ - -Mailing lists for contacting cairo users and developers: - - https://cairographics.org/lists - -Roadmap and unscheduled things to do, (please feel free to help out): - - https://cairographics.org/roadmap - https://cairographics.org/todo - -Dependencies -============ -The set of libraries needed to compile cairo depends on which backends -are enabled when cairo is configured. So look at the list below to -determine which dependencies are needed for the backends of interest. - -For the surface backends, we have both "supported" and "experimental" -backends. Further, the supported backends can be divided into the -"standard" backends which can be easily built on any platform, and the -"platform" backends which depend on some underlying platform-specific -system, (such as the X Window System or some other window system). - -As an example, for a standard Linux build similar to what's shipped by -your distro, (with image, png, pdf, PostScript, svg, and xlib surface -backends, and the freetype font backend), the following sample commands -will install necessary dependencies: - - Debian (and similar): - - apt-get build-dep cairo - - Fedora (and similar): - - yum install libpng-devel zlib-devel libXrender-devel fontconfig-devel - -Technically you probably don't need pixman from the distribution since -if you're manually compiling Cairo you probably want an updated pixman -as well. However, if you follow the default settings and install pixman -to /usr/local, your Cairo build should properly use it in preference to -the system pixman. - - -Supported, "standard" surface backends ------------------------------------- - image backend (required) - ------------------------ - pixman >= 0.30.0 https://cairographics.org/releases - - png support (can be left out if desired, but many - ----------- applications expect it to be present) - libpng http://www.libpng.org/pub/png/libpng.html - - pdf backend - ----------- - zlib http://www.gzip.org/zlib - - postscript backend - ------------------ - zlib http://www.gzip.org/zlib - - svg backend - ----------- - [none] - -Supported, "platform" surface backends ------------------------------------ - xlib backend - ------------ - X11 https://freedesktop.org/Software/xlibs - - xlib-xrender backend - -------------------- - Xrender >= 0.6 https://freedesktop.org/Software/xlibs - - quartz backend - -------------- - MacOS X >= 10.4 with Xcode >= 2.5 - - win32 backend - ------------- - Microsoft Windows 2000 or newer[*]. - - xcb backend - ----------- - XCB https://xcb.freedesktop.org - -Font backends (required to have at least one) ---------------------------------------------- - freetype font backend - --------------------- - freetype >= 2.1.9 http://freetype.org - fontconfig http://fontconfig.org - - quartz-font backend - ------------------- - MacOS X >= 10.4 with Xcode >= 2.4 - - win32 font backend - ------------------ - Microsoft Windows 2000 or newer[*]. - - [*] The Win32 backend should work on Windows 2000 and newer - (excluding Windows Me.) Most testing has been done on - Windows XP. While some portions of the code have been - adapted to work on older versions of Windows, considerable - work still needs to be done to get cairo running in those - environments. - - Cairo can be compiled on Windows with either the gcc - toolchain (see http://www.mingw.org) or with Microsoft - Visual C++. If the gcc toolchain is used, the standard - build instructions using configure apply, (see INSTALL). - If Visual C++ is desired, GNU make is required and - Makefile.win32 can be used via 'make -f Makefile.win32'. - The compiler, include paths, and library paths must be set - up correctly in the environment. - - MSVC versions earlier than 7.1 are known to miscompile - parts of cairo and pixman, and so should be avoided. MSVC - 7.1 or later, including the free Microsoft Visual Studio - Express editions, produce correct code. - -Experimental surface backends ------------------------------ - beos backend - ------------ - No dependencies in itself other than an installed BeOS system, but cairo - requires a font backend. See the freetype dependency list. - - os2 backend - ----------- - Cairo should run on any recent version of OS/2 or eComStation, but it - requires a font backend. See the freetype dependency list. Ready to use - packages and developer dependencies are available at Netlabs: - ftp://ftp.netlabs.org/pub/cairo - - -Compiling -========= -See the INSTALL document for build instructions. - - -History -======= -Cairo was originally developed by Carl Worth <cworth@cworth.org> and -Keith Packard <keithp@keithp.com>. Many thanks are due to Lyle Ramshaw -without whose patient help our ignorance would be much more apparent. - -Since the original development, many more people have contributed to -cairo. See the AUTHORS files for as complete a list as we've been able -to compile so far. diff --git a/gfx/cairo/cairo/README.md b/gfx/cairo/cairo/README.md new file mode 100644 index 0000000000..ebe3f99e10 --- /dev/null +++ b/gfx/cairo/cairo/README.md @@ -0,0 +1,176 @@ +# Cairo: Multi-platform 2D graphics library + +<https://cairographics.org> + +What is cairo +------------- + +Cairo is a 2D graphics library with support for multiple output +devices. Currently supported output targets include the X Window +System (via both Xlib and XCB), quartz, win32, and image buffers, +as well as PDF, PostScript, and SVG file output. + +Cairo is designed to produce consistent output on all output media +while taking advantage of display hardware acceleration when available +(for example, through the X Render Extension). + +The cairo API provides operations similar to the drawing operators of +PostScript and PDF. Operations in cairo include stroking and filling +cubic Bézier splines, transforming and compositing translucent images, +and antialiased text rendering. All drawing operations can be +transformed by any affine transformation (scale, rotation, shear, +etc.). + +Cairo has been designed to let you draw anything you want in a modern +2D graphical user interface. At the same time, the cairo API has been +designed to be as fun and easy to learn as possible. If you're not +having fun while programming with cairo, then we have failed +somewhere---let us know and we'll try to fix it next time around. + +Cairo is free software and is available to be redistributed and/or +modified under the terms of either the GNU Lesser General Public +License (LGPL) version 2.1 or the Mozilla Public License (MPL) version +1.1. + +Where to get more information about cairo +----------------------------------------- + +The primary source of information about cairo is its website: + +- <https://cairographics.org> + +The latest versions of cairo can always be found at: + +- <https://cairographics.org/download> + +Documentation on using cairo and frequently-asked questions: + +- <https://cairographics.org/documentation> +- <https://cairographics.org/FAQ> + +Mailing lists for contacting cairo users and developers: + +- <https://cairographics.org/lists> + +Roadmap and unscheduled things to do, (please feel free to help out): + +- https://cairographics.org/roadmap +- https://cairographics.org/todo + +Dependencies +------------ + +The set of libraries needed to compile cairo depends on which backends are +enabled when cairo is configured. So look at the list below to determine +which dependencies are needed for the backends of interest. + +For the surface backends, we have both "supported" and "experimental" +backends. Further, the supported backends can be divided into the "standard" +backends which can be easily built on any platform, and the "platform" +backends which depend on some underlying platform-specific system, (such as +the X Window System or some other window system). + +As an example, for a standard Linux build similar to what's shipped by your +distro, (with image, png, pdf, PostScript, svg, and xlib surface backends, +and the freetype font backend), the following sample commands will install +necessary dependencies: + +- Debian (and similar): + - `apt-get build-dep cairo` + +- Fedora (and similar): + - `dnf builddep cairo` + +Technically you probably don't need pixman from the distribution since if +you're manually compiling Cairo you probably want an updated pixman as well. +However, if you follow the default settings and install pixman to +/usr/local, your Cairo build should properly use it in preference to the +system pixman. + + +### Supported, "standard" surface backends + +#### image backend (required) + +- [pixman](https://cairographics.org/releases) >= 0.30.0 + +#### PNG support (preferred) + +- [libpng](http://www.libpng.org/pub/png/libpng.html) + +#### PDF backend + +- [zlib](http://www.gzip.org/zlib) + +#### PostScript backend + +- [zlib](http://www.gzip.org/zlib) + +#### SVG backend + +- none + +### Supported, "platform" surface backends + +#### Xlib backend + +- [X11](https://freedesktop.org/Software/xlibs) + +#### xlib-xrender backend + +- [Xrender](https://freedesktop.org/Software/xlibs) >= 0.6 + +#### Quartz backend + +- macOS >= 10.4 with Xcode >= 2.5 + +#### Windows backend + +- Microsoft Windows 2000 or newer. + +#### XCB backend + +- [XCB](https://xcb.freedesktop.org) + +### Font backends (required) + +#### freetype font backend + +- [freetype](https://freetype.org) >= 2.1.9 +- [fontconfig](https://www.freedesktop.org/wiki/Software/fontconfig/) + +#### Quartz-font backend + +- MacOS X >= 10.4 with Xcode >= 2.5 + +#### Windows GDI font backend + +- Microsoft Windows 2000 or newer + +#### Windows DirectWrite font backend + +- Microsoft Windows 7 or newer + +Compiling +--------- + +See the [`INSTALL`](./INSTALL) document for build instructions. + +Licensing +--------- + +Cairo is released under the terms of either the GNU Lesser General Public +License version 2.1, or the terms of the Mozilla Public License version 1.1. + +See the [`COPYING`](./COPYING) document for more information. + +History +------- + +Cairo was originally developed by Carl Worth <cworth@cworth.org> and Keith +Packard <keithp@keithp.com>. Many thanks are due to Lyle Ramshaw without +whose patient help our ignorance would be much more apparent. + +Since the original development, many more people have contributed to cairo. +See the [`AUTHORS`](./AUTHORS) document for as complete a list as we've been +able to compile so far. diff --git a/gfx/cairo/cairo/meson-cc-tests/atomic-ops-cxx11.c b/gfx/cairo/cairo/meson-cc-tests/atomic-ops-cxx11.c new file mode 100644 index 0000000000..aeef0d849c --- /dev/null +++ b/gfx/cairo/cairo/meson-cc-tests/atomic-ops-cxx11.c @@ -0,0 +1,3 @@ +int atomic_add(int i) { return __atomic_fetch_add(&i, 1, __ATOMIC_SEQ_CST); } +int atomic_cmpxchg(int i, int j, int k) { return __atomic_compare_exchange_n(&i, &j, k, 0, __ATOMIC_SEQ_CST, __ATOMIC_SEQ_CST); } +int main(void) { return 0; } diff --git a/gfx/cairo/cairo/meson-cc-tests/atomic-ops-gcc-legacy.c b/gfx/cairo/cairo/meson-cc-tests/atomic-ops-gcc-legacy.c new file mode 100644 index 0000000000..99331968dd --- /dev/null +++ b/gfx/cairo/cairo/meson-cc-tests/atomic-ops-gcc-legacy.c @@ -0,0 +1,3 @@ +int atomic_add(int i) { return __sync_fetch_and_add (&i, 1); } +int atomic_cmpxchg(int i, int j, int k) { return __sync_val_compare_and_swap (&i, j, k); } +int main(void) { return 0; } diff --git a/gfx/cairo/cairo/meson-cc-tests/bfd-section-flags.c b/gfx/cairo/cairo/meson-cc-tests/bfd-section-flags.c new file mode 100644 index 0000000000..b58118d06f --- /dev/null +++ b/gfx/cairo/cairo/meson-cc-tests/bfd-section-flags.c @@ -0,0 +1,9 @@ +#include <bfd.h> + +int +f (asection *s) +{ + return bfd_section_flags(s) == 0; +} + +int main (void) { return 0; } diff --git a/gfx/cairo/cairo/meson-cc-tests/check-unused-result.c b/gfx/cairo/cairo/meson-cc-tests/check-unused-result.c new file mode 100644 index 0000000000..ce7279ec8b --- /dev/null +++ b/gfx/cairo/cairo/meson-cc-tests/check-unused-result.c @@ -0,0 +1,9 @@ +__attribute__((__warn_unused_result__)) void f (void) {} +__attribute__((__warn_unused_result__)) int g; + +int main(int c, char **v) +{ + (void)c; + (void)v; + return 0; +} diff --git a/gfx/cairo/cairo/meson-cc-tests/ft_has_color.c b/gfx/cairo/cairo/meson-cc-tests/ft_has_color.c new file mode 100644 index 0000000000..daeed7f358 --- /dev/null +++ b/gfx/cairo/cairo/meson-cc-tests/ft_has_color.c @@ -0,0 +1,7 @@ +#include <ft2build.h> +#include FT_FREETYPE_H + +int main(void) { + FT_Long has_color = FT_HAS_COLOR(((FT_Face)NULL)); + return 0; +} diff --git a/gfx/cairo/cairo/meson-cc-tests/fuzzer.c b/gfx/cairo/cairo/meson-cc-tests/fuzzer.c new file mode 100644 index 0000000000..0ae4a3101a --- /dev/null +++ b/gfx/cairo/cairo/meson-cc-tests/fuzzer.c @@ -0,0 +1,7 @@ +#include <stddef.h> +#include <stdint.h> + +int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) +{ + return 0; +} diff --git a/gfx/cairo/cairo/meson-cc-tests/ipc_rmid_deferred_release.c b/gfx/cairo/cairo/meson-cc-tests/ipc_rmid_deferred_release.c new file mode 100644 index 0000000000..2c9290d253 --- /dev/null +++ b/gfx/cairo/cairo/meson-cc-tests/ipc_rmid_deferred_release.c @@ -0,0 +1,18 @@ +#include <sys/types.h> +#include <sys/ipc.h> +#include <sys/shm.h> +int main() +{ + char *shmaddr; + int id = shmget (IPC_PRIVATE, 4, IPC_CREAT | 0600); + if (id == -1) return 2; + shmaddr = shmat (id, 0, 0); + shmctl (id, IPC_RMID, 0); + if ((char*) shmat (id, 0, 0) == (char*) -1) { + shmdt (shmaddr); + return 1; + } + shmdt (shmaddr); + shmdt (shmaddr); + return 0; +} diff --git a/gfx/cairo/cairo/meson-cc-tests/mkdir-variant-1.c b/gfx/cairo/cairo/meson-cc-tests/mkdir-variant-1.c new file mode 100644 index 0000000000..88910d1076 --- /dev/null +++ b/gfx/cairo/cairo/meson-cc-tests/mkdir-variant-1.c @@ -0,0 +1,12 @@ +#ifdef HAVE_SYS_STAT_H +#include <sys/stat.h> +#endif +#ifdef HAVE_IO_H +#include <io.h> +#endif + +int main(int ac, char **av) +{ + mkdir("hello.world"); + return 0; +} diff --git a/gfx/cairo/cairo/meson-cc-tests/mkdir-variant-2.c b/gfx/cairo/cairo/meson-cc-tests/mkdir-variant-2.c new file mode 100644 index 0000000000..d0ab7b298d --- /dev/null +++ b/gfx/cairo/cairo/meson-cc-tests/mkdir-variant-2.c @@ -0,0 +1,12 @@ +#ifdef HAVE_SYS_STAT_H +#include <sys/stat.h> +#endif +#ifdef HAVE_IO_H +#include <io.h> +#endif + +int main(int ac, char **av) +{ + mkdir("hello.world", 0777); + return 0; +} diff --git a/gfx/cairo/cairo/meson-cc-tests/pthread.c b/gfx/cairo/cairo/meson-cc-tests/pthread.c new file mode 100644 index 0000000000..035cb3a94d --- /dev/null +++ b/gfx/cairo/cairo/meson-cc-tests/pthread.c @@ -0,0 +1,35 @@ +#ifndef _GNU_SOURCE +#define _GNU_SOURCE /* for PTHREAD_MUTEX_INITIALIZER under linux */ +#endif +#include <pthread.h> + +pthread_mutex_t test_mutex_initializer = PTHREAD_MUTEX_INITIALIZER; +int test_mutex (void) +{ + int x = 0; + pthread_mutex_t mutex; + x |= pthread_mutex_init (&mutex, NULL); + x |= pthread_mutex_lock (&mutex); + x |= pthread_mutex_unlock (&mutex); + x |= pthread_mutex_destroy (&mutex); + return 0; +} + +int test_mutex_attr (void) +{ + int x = 0; + pthread_mutexattr_t attr; + pthread_mutex_t mutex; + x |= pthread_mutexattr_init (&attr); + x |= pthread_mutexattr_settype (&attr, PTHREAD_MUTEX_RECURSIVE); + x |= pthread_mutex_init (&mutex, &attr); + x |= pthread_mutex_lock (&mutex); + x |= pthread_mutex_unlock (&mutex); + x |= pthread_mutex_destroy (&mutex); + x |= pthread_mutexattr_destroy (&attr); + return x; +} + +int main(void) { + return 0; +} diff --git a/gfx/cairo/cairo/meson.build b/gfx/cairo/cairo/meson.build new file mode 100644 index 0000000000..9100152eec --- /dev/null +++ b/gfx/cairo/cairo/meson.build @@ -0,0 +1,855 @@ +project('cairo', 'c', 'cpp', + meson_version: '>= 0.59.0', + version: run_command(find_program('version.py'), check: true).stdout().strip(), + default_options: ['warning_level=2'], +) + +freetype_required_version = '>= 9.7.3' +freetype_colrv1_required_version = '>= 25.0.19' +fontconfig_required_version = '>= 2.2.95' +xrender_required_version = '>= 0.6' +xcb_required_version = '>= 1.6' +xcb_render_required_version = '>= 1.6' +libudev_required_version = '>= 136' +glib_required_version = '>= 2.14' + +# library versioning +version_arr = meson.project_version().split('.') +cairo_version_major = version_arr[0].to_int() +cairo_version_minor = version_arr[1].to_int() +cairo_version_micro = version_arr[2].to_int() + +# The libtool shared library version stuff. +# Try and maintain compatibility with the previous library versioning. +cairo_version_sonum = cairo_version_major + 1 +cairo_version = cairo_version_major * 10000 + cairo_version_minor * 100 + cairo_version_micro + +if cairo_version_minor % 2 == 1 + # unstable release + cairo_libversion = '@0@.@1@.0'.format(cairo_version_sonum, cairo_version) +else + # stable release + cairo_libversion = '@0@.@1@.@2@'.format(cairo_version_sonum, cairo_version, cairo_version_micro) +endif + +conf = configuration_data() + +cc = meson.get_compiler('c') + +# Compiler flags +cflags = [] +if cc.get_id() != 'msvc' + cflags += [ + '-Wmissing-declarations', + '-Werror-implicit-function-declaration', + '-Wpointer-arith', + '-Wwrite-strings', + '-Wsign-compare', + '-Wpacked', + '-Wswitch-enum', + '-Wmissing-format-attribute', + '-Wvolatile-register-var', + '-Wstrict-aliasing=2', + '-Winit-self', + '-Wunsafe-loop-optimizations', + '-Wno-missing-field-initializers', + '-Wno-unused-parameter', + '-Wno-attributes', + '-Wno-long-long', + '-Winline' + ] + + cflags += ['-Wno-unused-but-set-variable', + '-Wno-enum-conversion' + ] + + cflags += [ + '-fno-strict-aliasing', + '-fno-common' + ] + + if get_option('optimization') in ['1', '2', '3'] + cflags += '-Wp,-D_FORTIFY_SOURCE=2' + endif + + supported_cflags = cc.get_supported_arguments(cflags) + add_project_arguments(supported_cflags, language: 'c') + + # We only wish to enable attribute(warn_unused_result) if we can prevent + # gcc from generating thousands of warnings about the misapplication of the + # attribute to void functions and variables. + warn_unused_result = '' + if supported_cflags.contains('-Wno-attributes') + if cc.compiles(files('meson-cc-tests/check-unused-result.c'), args : ['-Wno-attributes', '-Werror']) + warn_unused_result = '__attribute__((__warn_unused_result__))' + endif + endif + conf.set('WARN_UNUSED_RESULT', warn_unused_result) +endif + +if cc.get_id() == 'msvc' + # Basic usage in the cairo type system that causes spammy and useless warnings + add_project_arguments('/wd4244', '/wd4146', + # Don't warn about double -> float truncation + '/wd4305', + language : 'c') +endif + +add_project_arguments('-D_GNU_SOURCE', language: 'c') + +pkgmod = import('pkgconfig') +python3 = import('python').find_installation() + +check_sizeofs = [ + ['void *', {'conf-name': 'SIZEOF_VOID_P'}], + ['int'], + ['long'], + ['long long'], + ['size_t'], +] + +check_headers = [ + ['stdint.h'], + ['inttypes.h'], + ['sys/int_types.h'], + ['fcntl.h'], + ['unistd.h'], + ['signal.h'], + ['sys/stat.h'], + ['sys/socket.h'], + ['poll.h'], + ['sys/poll.h'], + ['sys/un.h'], + ['sched.h', {'check-funcs': ['sched_getaffinity']}], + ['sys/mman.h', {'check-funcs': ['mmap']}], + ['time.h', {'check-funcs': ['clock_gettime']}], + ['libgen.h'], + ['byteswap.h'], + ['signal.h'], + ['setjmp.h'], + ['fenv.h'], + ['sys/wait.h'], + ['sys/stat.h'], + ['io.h'], + ['fenv.h', {'check-funcs': ['feenableexcept', 'fedisableexcept', 'feclearexcept']}], + ['xlocale.h'], + ['sys/ioctl.h'], + ['intsafe.h'], +] + +check_types = [ + ['uint64_t', {'headers': ['stdint.h']}], + ['uint128_t', {'headers': ['stdint.h']}], + ['__uint128_t'] +] + +check_funcs = [ + 'alarm', + 'ctime_r', + 'localtime_r', + 'gmtime_r', + 'drand48', + 'flockfile', + 'funlockfile', + 'getline', + 'link', + 'fork', + 'waitpid', + 'raise', + 'newlocale', + 'strtod_l', +] + +check_thread_flags = [ + [['-D_REENTRANT'], ['-lpthread']], + [['-pthread'], []], + [['-D_REENTRANT'], [], {'real': false}], +] + +m_dep = cc.find_library('m', required: false) +# Used in util +gtk_dep = dependency('gtk+-2.0', required: get_option('gtk2-utils')) + +deps = [m_dep] +test_deps = [] +internal_deps = [] +extra_link_args = [] + +extra_link_args += cc.get_supported_link_arguments([ + '-Wl,-Bsymbolic-functions', +]) + +if host_machine.endian() == 'big' + conf.set('WORDS_BIGENDIAN', 1) +endif + +float_order = cc.get_define('__FLOAT_WORD_ORDER__') +if float_order != '' + if float_order == cc.get_define('__ORDER_BIG_ENDIAN__') + conf.set('FLOAT_WORDS_BIGENDIAN', 1) + endif +else + # Assume same as platform endian + if host_machine.endian() == 'big' + conf.set('FLOAT_WORDS_BIGENDIAN', 1) + endif +endif + +lzo_dep = dependency('lzo2', required: false) +if lzo_dep.found() + conf.set('HAVE_LZO', 1) +endif + +dl_dep = cc.find_library('dl', required: false) +if dl_dep.found() and cc.has_function('dlsym', dependencies: [dl_dep]) + deps += [dl_dep] + conf.set('CAIRO_HAS_DLSYM', 1) +elif cc.has_function('dlsym') + conf.set('CAIRO_HAS_DLSYM', 1) +elif cc.has_function('dlsym', prefix: '#include <dlfcn.h>') + conf.set('CAIRO_HAS_DLSYM', 1) +endif + +feature_conf = configuration_data() + +# Array of dictionaries, used to generate per-feature pc files +# Mandatory keys: name, description +# Optional keys: requires, libs +built_features = [] + +zlib_dep = dependency('zlib', + required: get_option('zlib'), + fallback : ['zlib', 'zlib_dep'], +) +if zlib_dep.found() + if zlib_dep.type_name() == 'internal' + internal_deps += [zlib_dep] + else + deps += [zlib_dep] + endif + conf.set('HAVE_ZLIB', 1) +endif + +png_dep = dependency('libpng', + required: get_option('png'), + fallback: ['libpng', 'libpng_dep'] +) +if png_dep.found() + feature_conf.set('CAIRO_HAS_SVG_SURFACE', 1) + feature_conf.set('CAIRO_HAS_PNG_FUNCTIONS', 1) + built_features += [ + { + 'name': 'cairo-png', + 'description': 'PNG functions', + 'deps': [png_dep], + }, + { + 'name': 'cairo-svg', + 'description': 'SVG surface backend', + 'deps': [png_dep], + } + ] + + if png_dep.type_name() == 'internal' + internal_deps += [png_dep] + else + deps += [png_dep] + endif +endif + +# Disable fontconfig by default on platforms where it is optional +fontconfig_option = get_option('fontconfig') +fontconfig_required = host_machine.system() not in ['windows', 'darwin'] +fontconfig_option = fontconfig_option.disable_auto_if(not fontconfig_required) + +fontconfig_dep = dependency('fontconfig', + required: fontconfig_option, + version: fontconfig_required_version, + fallback: ['fontconfig', 'fontconfig_dep'], +) +if fontconfig_dep.found() + fc_check_funcs = [ + 'FcInit', + 'FcFini' + ] + + if fontconfig_dep.type_name() == 'internal' + foreach func : fc_check_funcs + conf.set('HAVE_@0@'.format(func.to_upper()), 1) + endforeach + internal_deps += [fontconfig_dep] + else + check_funcs += fc_check_funcs + deps += [fontconfig_dep] + endif + + feature_conf.set('CAIRO_HAS_FC_FONT', 1) + built_features += [{ + 'name': 'cairo-fc', + 'description': 'Fontconfig font backend', + 'deps': [fontconfig_dep], + }] +endif + +ttx = find_program('ttx', required: false) + +# Disable FreeType by default on platforms where it is optional +freetype_option = get_option('freetype') +freetype_required = host_machine.system() not in ['windows', 'darwin'] +freetype_option = freetype_option.disable_auto_if(not freetype_required) + +freetype_dep = dependency('freetype2', + required: freetype_option, + version: freetype_required_version, + fallback: ['freetype2', 'freetype_dep'], +) +if freetype_dep.found() + feature_conf.set('CAIRO_HAS_FT_FONT', 1) + built_features += [{ + 'name': 'cairo-ft', + 'description': 'FreeType font backend', + 'deps': [freetype_dep], + # cairo-ft.h includes fontconfig.h so it needs its cflags + 'compile-deps': [fontconfig_dep.partial_dependency(compile_args: true, includes: true)], + }] + + ft_check_funcs = [ + 'FT_Get_X11_Font_Format', + 'FT_GlyphSlot_Embolden', + 'FT_GlyphSlot_Oblique', + 'FT_Load_Sfnt_Table', + 'FT_Library_SetLcdFilter', + 'FT_Get_Var_Design_Coordinates', + 'FT_Done_MM_Var', + 'FT_Palette_Select', + ] + + if freetype_dep.type_name() == 'internal' + foreach func : ft_check_funcs + conf.set('HAVE_@0@'.format(func.to_upper()), 1) + endforeach + internal_deps += [freetype_dep] + else + if not cc.links(files('meson-cc-tests/ft_has_color.c'), dependencies: freetype_dep, name: 'FT has color') + conf.set('FT_HAS_COLOR', '(0)') + endif + if png_dep.found() and \ + cc.has_type('FT_SVG_Document', dependencies: freetype_dep, prefix: '#include <freetype/otsvg.h>') + conf.set('HAVE_FT_SVG_DOCUMENT', 1) + if ttx.found() + conf.set('CAIRO_CAN_TEST_TTX_FONT', 1) + endif + endif + if freetype_dep.version().version_compare(freetype_colrv1_required_version) and \ + cc.has_function('FT_Get_Color_Glyph_Paint', dependencies: freetype_dep) + conf.set('HAVE_FT_COLR_V1', 1) + endif + check_funcs += ft_check_funcs + deps += [freetype_dep] + endif +endif + +x11_dep = dependency('x11', required: get_option('xlib')) +xext_dep = dependency('xext', required: get_option('xlib')) +if x11_dep.found() and xext_dep.found() + feature_conf.set('CAIRO_HAS_XLIB_SURFACE', 1) + built_features += [{ + 'name': 'cairo-xlib', + 'description': 'Xlib surface backend', + 'deps': [x11_dep, xext_dep], + }] + + extra_headers = ['X11/Xlibint.h', 'X11/Xproto.h'] + check_headers += [ + ['X11/extensions/XShm.h', {'extra-headers': extra_headers}], + ['X11/extensions/shmproto.h', {'extra-headers': extra_headers}], + ['X11/extensions/shmstr.h', {'extra-headers': extra_headers}], + ] + deps += [x11_dep, xext_dep] + + # Can skip the run check by providing the result in a cross file or + # native file as bool property value. + prop = meson.get_external_property('ipc_rmid_deferred_release', 'auto') + # We don't know the type of prop (bool, string) but need to differentiate + # between a set value (bool) or the fallback value (string), so convert to + # a string and check the string value. + prop_str = '@0@'.format(prop) + if prop_str in ['true', 'false'] + ipc_rmid_deferred_release = (prop_str == 'true') + message('IPC_RMID_DEFERRED_RELEASE:', ipc_rmid_deferred_release) + elif prop_str == 'auto' + res = cc.run(files('meson-cc-tests/ipc_rmid_deferred_release.c'), + dependencies: [x11_dep, xext_dep], + name: 'shmctl IPC_RMID allowes subsequent attaches') + + ipc_rmid_deferred_release = (res.returncode() == 0) + else + error('Unexpected value for external property ipc_rmid_deferred_release: @0@'.format(prop_str)) + endif + + conf.set10('IPC_RMID_DEFERRED_RELEASE', ipc_rmid_deferred_release) +endif + +if feature_conf.get('CAIRO_HAS_XLIB_SURFACE', 0) == 1 + xrender_dep = dependency('xrender', required: get_option('xlib'), + version: xrender_required_version) + + if xrender_dep.found() + check_funcs += [ + 'XRenderCreateSolidFill', + 'XRenderCreateLinearGradient', + 'XRenderCreateRadialGradient', + 'XRenderCreateConicalGradient', + ] + + deps += [xrender_dep] + + built_features += [{ + 'name': 'cairo-xlib-xrender', + 'description': 'Xlib Xrender surface backend', + 'deps': [xrender_dep], + }] + feature_conf.set('CAIRO_HAS_XLIB_XRENDER_SURFACE', 1) + endif +endif + +xcb_dep = dependency('xcb', required: get_option('xcb'), + version: xcb_required_version) +xcb_render_dep = dependency('xcb-render', required: get_option('xcb'), + version: xcb_render_required_version) +if xcb_dep.found() and xcb_render_dep.found() + feature_conf.set('CAIRO_HAS_XCB_SURFACE', 1) + built_features += [{ + 'name': 'cairo-xcb', + 'description': 'XCB surface backend', + 'deps': [xcb_dep, xcb_render_dep], + }] + + deps += [xcb_dep, xcb_render_dep] +endif + +if feature_conf.get('CAIRO_HAS_XCB_SURFACE', 0) == 1 and feature_conf.get('CAIRO_HAS_XLIB_SURFACE', 0) == 1 + x11xcb_dep = dependency('x11-xcb', required: get_option('xlib-xcb')) + if x11xcb_dep.found() + deps += [x11xcb_dep] + feature_conf.set('CAIRO_HAS_XLIB_XCB_FUNCTIONS', 1) + built_features += [{ + 'name': 'cairo-xlib-xcb', + 'description': 'Xlib/XCB functions', + 'deps': [x11xcb_dep], + }] + endif +endif + +if feature_conf.get('CAIRO_HAS_XCB_SURFACE', 0) == 1 + xcbshm_dep = dependency('xcb-shm', required: get_option('xcb')) + if xcbshm_dep.found() + feature_conf.set('CAIRO_HAS_XCB_SHM_FUNCTIONS', 1) + deps += [xcbshm_dep] + built_features += [{ + 'name': 'cairo-xcb-shm', + 'description': 'XCB/SHM functions', + 'deps': [xcbshm_dep], + }] + endif +endif + +if host_machine.system() == 'darwin' and not get_option('quartz').disabled() + quartz_deps = dependency('appleframeworks', modules : ['CoreFoundation', 'ApplicationServices'], required: get_option('quartz')) + + if quartz_deps.found() + deps += [quartz_deps] + + feature_conf.set('CAIRO_HAS_QUARTZ_SURFACE', 1) + feature_conf.set('CAIRO_HAS_QUARTZ_IMAGE_SURFACE', 1) + + built_features += [ + { + 'name': 'cairo-quartz', + 'description': 'Quartz surface backend', + 'deps': quartz_deps, + }, + { + 'name': 'cairo-quartz-image', + 'description': 'Quartz Image surface backend', + 'deps': quartz_deps, + }] + compiler = meson.get_compiler('c') + if compiler.has_function('CTFontDrawGlyphs', prefix: '#include <ApplicationServices/ApplicationServices.h>', + dependencies: quartz_deps) + built_features += [ + { + 'name': 'cairo-quartz-font', + 'description': 'Quartz font backend', + 'deps': quartz_deps, + }] + feature_conf.set('CAIRO_HAS_QUARTZ_FONT', 1) + endif + endif +endif + +if host_machine.system() == 'windows' + add_project_arguments('-DWIN32_LEAN_AND_MEAN', '-DNOMINMAX', language: ['c', 'cpp']) + + win32_extra_deps = [ + cc.find_library('gdi32'), + cc.find_library('msimg32'), + ] + + deps += win32_extra_deps + + feature_conf.set('CAIRO_HAS_WIN32_SURFACE', 1) + feature_conf.set('CAIRO_HAS_WIN32_FONT', 1) + + built_features += [ + { + 'name': 'cairo-win32', + 'description': 'Microsoft Windows surface backend', + 'deps': win32_extra_deps, + }, + { + 'name': 'cairo-win32-font', + 'description': 'Microsoft Windows font backend', + 'deps': win32_extra_deps, + } + ] + + cpp_compiler = meson.get_compiler('cpp') + d2d_dep = cpp_compiler.find_library('d2d1', required: get_option('dwrite')) + dwrite_dep = cpp_compiler.find_library('dwrite', required: get_option('dwrite')) + d2d_header = cpp_compiler.has_header('d2d1.h') + d2d_3_header = cpp_compiler.has_header('d2d1_3.h') + dwrite_header = cpp_compiler.has_header('dwrite.h') + wincodec_dep = cpp_compiler.find_library('windowscodecs', required: get_option('dwrite')) + wincodec_header = cpp_compiler.has_header('wincodec.h') + + if d2d_dep.found() and dwrite_dep.found() and d2d_header and dwrite_header and wincodec_dep.found() and wincodec_header + feature_conf.set('CAIRO_HAS_DWRITE_FONT', 1) + built_features += [{ + 'name': 'cairo-dwrite-font', + 'description': 'Microsoft Windows DWrite font backend', + 'deps': [dwrite_dep, d2d_dep, wincodec_dep], + }] + deps += [dwrite_dep, d2d_dep, wincodec_dep] + + if cpp_compiler.has_header('d2d1_3.h') + conf.set('HAVE_D2D1_3_H', 1) + endif + + add_project_arguments('-DWINVER=_WIN32_WINNT_WIN10', '-D_WIN32_WINNT=_WIN32_WINNT_WIN10', '-DNTDDI_VERSION=NTDDI_WIN10_RS3', language: ['c', 'cpp']) + else + add_project_arguments('-DWINVER=_WIN32_WINNT_WIN2K', '-D_WIN32_WINNT=_WIN32_WINNT_WIN2K', language: ['c', 'cpp']) + endif +endif + +gobject_dep = dependency('gobject-2.0', + required: get_option('glib'), + fallback: ['glib', 'libgobject_dep'] +) +glib_dep = dependency('glib-2.0', + required: get_option('glib'), + version: glib_required_version, + fallback: ['glib', 'libglib_dep'], +) +if gobject_dep.found() and glib_dep.found() + feature_conf.set('CAIRO_HAS_GOBJECT_FUNCTIONS', 1) +endif + +if zlib_dep.found() + feature_conf.set('CAIRO_HAS_SCRIPT_SURFACE', 1) + built_features += [{ + 'name': 'cairo-script', + 'description': 'script surface backend', + 'deps': [zlib_dep], + }] +endif + +if zlib_dep.found() + feature_conf.set('CAIRO_HAS_PS_SURFACE', 1) + built_features += [{ + 'name': 'cairo-ps', + 'description': 'PostScript surface backend', + 'deps': [zlib_dep], + }] +endif + +if zlib_dep.found() + feature_conf.set('CAIRO_HAS_PDF_SURFACE', 1) + built_features += [{ + 'name': 'cairo-pdf', + 'description': 'PDF surface backend', + 'deps': [zlib_dep], + }] +endif + +if zlib_dep.found() + conf.set('CAIRO_HAS_INTERPRETER', 1) +endif + +bfd_dep = cc.find_library('bfd', has_headers: ['bfd.h'], required: get_option('symbol-lookup')) +if bfd_dep.found() and \ + cc.has_function('bfd_openr', dependencies: [bfd_dep]) and \ + cc.links(files('meson-cc-tests/bfd-section-flags.c'), name: 'bfd_section_flags', dependencies: bfd_dep) + conf.set('HAVE_BFD', 1) + deps += [bfd_dep] +elif get_option('symbol-lookup').enabled() + error('symbol lookup via bfd was enabled via options but is not available (bfd might be too old)') +endif + +if conf.get('HAVE_BFD', 0) == 1 + conf.set('CAIRO_HAS_SYMBOL_LOOKUP', 1) +endif + +if feature_conf.get('CAIRO_HAS_PS_SURFACE', 0) == 1 + gs = find_program('gs', required: get_option('tests')) + libspectre_dep = dependency('libspectre', version: '>= 0.2.0', + required: get_option('spectre')) + if gs.found() and libspectre_dep.found() + conf.set('CAIRO_CAN_TEST_PS_SURFACE', 1) + endif + + if libspectre_dep.found() + conf.set('CAIRO_HAS_SPECTRE', 1) + test_deps += [libspectre_dep] + endif +endif + +if feature_conf.get('CAIRO_HAS_PDF_SURFACE', 0) == 1 + poppler_dep = dependency('poppler-glib', version: '>= 0.17.4', + required: get_option('tests')) + if poppler_dep.found() and cc.has_function('poppler_page_render', dependencies: [poppler_dep]) + conf.set('CAIRO_CAN_TEST_PDF_SURFACE', 1) + test_deps += [poppler_dep] + endif +endif + +if feature_conf.get('CAIRO_HAS_SVG_SURFACE', 0) == 1 + librsvg_dep = dependency('librsvg-2.0', version: '>= 2.35.0', + required: get_option('tests')) + if librsvg_dep.found() + conf.set('CAIRO_CAN_TEST_SVG_SURFACE', 1) + test_deps += [librsvg_dep] + endif +endif + +pixman_dep = dependency('pixman-1', + version: '>= 0.36.0', + fallback: ['pixman', 'idep_pixman'], +) +if pixman_dep.found() + feature_conf.set('CAIRO_HAS_IMAGE_SURFACE', 1) + conf.set('HAS_PIXMAN_GLYPHS', 1) + if pixman_dep.type_name() == 'internal' + internal_deps += [pixman_dep] + else + deps += [pixman_dep] + endif +endif + +feature_conf.set('CAIRO_FEATURES_H', true) +feature_conf.set('CAIRO_HAS_USER_FONT', 1) + +feature_conf.set('CAIRO_HAS_MIME_SURFACE', 1) +feature_conf.set('CAIRO_HAS_RECORDING_SURFACE', 1) +feature_conf.set('CAIRO_HAS_OBSERVER_SURFACE', 1) + +if not get_option('tee').disabled() + feature_conf.set('CAIRO_HAS_TEE_SURFACE', 1) + built_features += [{ + 'name': 'cairo-tee', + 'description': 'Tee surface backend', + }] +endif + +incbase = include_directories('.') + +foreach check : check_sizeofs + type = check[0] + opts = check.length() > 1 ? check[1] : {} + + conf_name = opts.get('conf-name', 'SIZEOF_@0@'.format(type.underscorify().to_upper())) + + conf.set(conf_name, cc.sizeof(type)) +endforeach + +foreach check : check_headers + name = check[0] + opts = check.length() > 1 ? check[1] : {} + prefix = '' + + foreach header : opts.get('extra-headers', []) + prefix += '#include <@0@>\n'.format(header) + endforeach + + if cc.has_header(name, prefix: prefix) + conf.set('HAVE_@0@'.format(name.to_upper().underscorify()), 1) + check_funcs += check.length() > 1 ? check[1].get('check-funcs', []) : [] + endif +endforeach + +foreach check : check_types + name = check[0] + opts = check.length() > 1 ? check[1] : {} + prefix = '' + + foreach header : opts.get('headers', []) + prefix += '#include <@0@>\n'.format(header) + endforeach + + if cc.has_type(name, prefix: prefix) + conf.set('HAVE_@0@'.format(name.to_upper()), 1) + endif +endforeach + +foreach name : check_funcs + if cc.has_function(name, dependencies: deps) + conf.set('HAVE_@0@'.format(name.to_upper()), 1) + endif +endforeach + +conf.set('HAVE_STRNDUP', cc.has_function('strndup', prefix : '#include <string.h>')) + +pthread_c_args = [] +pthread_link_args = [] + +foreach thread_flags : check_thread_flags + if not conf.has('CAIRO_HAS_PTHREAD') + cflags = thread_flags[0] + lflags = thread_flags[1] + real_pthread = thread_flags.length() > 2 ? thread_flags[2].get('real', true) : true + + if cc.links(files('meson-cc-tests/pthread.c'), args: cflags + lflags, name: 'pthreads') + conf.set('CAIRO_HAS_PTHREAD', 1) + if real_pthread + conf.set('CAIRO_HAS_REAL_PTHREAD', 1) + endif + pthread_c_args = cflags + pthread_link_args = lflags + endif + endif +endforeach + +extra_link_args += pthread_link_args + +if cc.links(files('meson-cc-tests/atomic-ops-cxx11.c'), name: 'Atomic ops: cxx11') + conf.set('HAVE_CXX11_ATOMIC_PRIMITIVES', 1) +elif cc.links(files('meson-cc-tests/atomic-ops-gcc-legacy.c'), name: 'Atomic ops: gcc legacy') + conf.set('HAVE_GCC_LEGACY_ATOMICS', 1) +elif cc.has_header('atomic_ops.h') + conf.set('HAVE_LIB_ATOMIC_OPS', 1) +elif cc.has_header('libkern/OSAtomic.h') + conf.set('HAVE_OS_ATOMIC_OPS', 1) +endif + +test_mkdir_c_args = [] +if conf.get('HAVE_SYS_STAT_H', 0) == 1 + test_mkdir_c_args += ['-DHAVE_SYS_STAT_H'] +endif + +if conf.get('HAVE_IO_H', 0) == 1 + test_mkdir_c_args += ['-DHAVE_IO_H'] +endif + +if cc.links(files('meson-cc-tests/mkdir-variant-1.c'), args: test_mkdir_c_args) + conf.set('HAVE_MKDIR', 1) +elif cc.links(files('meson-cc-tests/mkdir-variant-2.c'), args: test_mkdir_c_args) + conf.set('HAVE_MKDIR', 2) +else + conf.set('HAVE_MKDIR', 0) +endif + +if not ['x86', 'x86_64'].contains(host_machine.cpu_family()) + conf.set('ATOMIC_OP_NEEDS_MEMORY_BARRIER', 1) +endif + +have_ld_preload = ['linux', 'freebsd', 'darwin', 'dragonfly'].contains(host_machine.system()) + +if have_ld_preload and zlib_dep.found() and conf.get('CAIRO_HAS_REAL_PTHREAD', 0) == 1 and conf.get('CAIRO_HAS_DLSYM', 0) == 1 + conf.set('CAIRO_HAS_TRACE', 1) +endif + +rt_dep = cc.find_library('rt', required: false) +have_shm = false +if rt_dep.found() and cc.has_function('shm_open', dependencies: [rt_dep]) + have_shm = true +endif + +# This to make sure we don't run checks against internal deps +deps += internal_deps + +subdir('src') + +if feature_conf.get('CAIRO_HAS_PNG_FUNCTIONS', 0) == 1 + subdir('boilerplate') +else + cairoboilerplate_dep = dependency('', required: false) +endif + +subdir('util') + +if not get_option('tests').disabled() and feature_conf.get('CAIRO_HAS_PNG_FUNCTIONS', 0) == 1 + subdir('test') + subdir('perf') +endif + +if get_option('gtk_doc') + doc_srcdir = include_directories('src') + subdir('doc/public') +endif + +configure_file(output: 'config.h', configuration: conf) + +foreach feature: built_features + feature_deps = feature.get('deps', []) + feature_libs = feature.get('libs', []) + feature_compile_deps = feature.get('compile-deps', []) + pkgmod.generate(libraries: [libcairo, feature_deps, feature_libs], + name: feature['name'], + description: feature['description'] + ' for cairo graphics library', + ) + meson.override_dependency(feature['name'], + declare_dependency(dependencies: [libcairo_dep, feature_deps, feature_compile_deps], + link_args: feature_libs, + ) + ) +endforeach + +# summary +summary({ + 'Image': true, + 'Recording': true, + 'Observer': true, + 'Mime': true, + 'Tee': feature_conf.get('CAIRO_HAS_TEE_SURFACE', 0) == 1, + 'Xlib': feature_conf.get('CAIRO_HAS_XLIB_SURFACE', 0) == 1, + 'Xlib Xrender': feature_conf.get('CAIRO_HAS_XLIB_XRENDER_SURFACE', 0) == 1, + 'Quartz': feature_conf.get('CAIRO_HAS_QUARTZ_SURFACE', 0) == 1, + 'Quartz-image': feature_conf.get('CAIRO_HAS_QUARTZ_IMAGE_SURFACE', 0) == 1, + 'XCB': feature_conf.get('CAIRO_HAS_XCB_SURFACE', 0) == 1, + 'Win32': feature_conf.get('CAIRO_HAS_WIN32_SURFACE', 0) == 1, + 'CairoScript': feature_conf.get('CAIRO_HAS_SCRIPT_SURFACE', 0) == 1, + 'PostScript': feature_conf.get('CAIRO_HAS_PS_SURFACE', 0) == 1, + 'PDF': feature_conf.get('CAIRO_HAS_PDF_SURFACE', 0) == 1, + 'SVG': feature_conf.get('CAIRO_HAS_SVG_SURFACE', 0) == 1, + }, section: 'Surface Backends', bool_yn: true) + +summary({ + 'User': true, + 'FreeType': feature_conf.get('CAIRO_HAS_FT_FONT', 0) == 1, + 'Fontconfig': feature_conf.get('CAIRO_HAS_FC_FONT', 0) == 1, + 'Win32': feature_conf.get('CAIRO_HAS_WIN32_FONT', 0) == 1, + 'Win32 DWrite': feature_conf.get('CAIRO_HAS_DWRITE_FONT', 0) == 1, + 'Quartz': feature_conf.get('CAIRO_HAS_QUARTZ_FONT', 0) == 1, + }, section: 'Font Backends', bool_yn: true) + +summary({ + 'PNG functions': feature_conf.get('CAIRO_HAS_PNG_FUNCTIONS', 0) == 1, + 'X11-xcb': feature_conf.get('CAIRO_HAS_XLIB_XCB_FUNCTIONS', 0) == 1, + 'XCB-shm': feature_conf.get('CAIRO_HAS_XCB_SHM_FUNCTIONS', 0) == 1, + }, section: 'Functions', bool_yn: true) + +summary({ + 'cairo-trace:': conf.get('CAIRO_HAS_TRACE', 0) == 1, + 'cairo-script-interpreter': conf.get('CAIRO_HAS_INTERPRETER', 0) == 1, + 'API reference': get_option('gtk_doc'), + }, section: 'Features and Utilities', bool_yn: true) diff --git a/gfx/cairo/cairo/meson_options.txt b/gfx/cairo/cairo/meson_options.txt new file mode 100644 index 0000000000..f481ef3eaf --- /dev/null +++ b/gfx/cairo/cairo/meson_options.txt @@ -0,0 +1,29 @@ +# Cairo font backends +option('dwrite', type : 'feature', value : 'auto') +option('fontconfig', type : 'feature', value : 'auto') +option('freetype', type : 'feature', value : 'auto') + +# Cairo surface backends +option('png', type : 'feature', value : 'auto') # png and svg surfaces +option('quartz', type : 'feature', value : 'auto') +option('tee', type : 'feature', value : 'auto') +option('xcb', type : 'feature', value : 'auto') +option('xlib', type : 'feature', value : 'auto') +option('xlib-xcb', type : 'feature', value : 'disabled') +option('zlib', type : 'feature', value : 'auto') # script, ps, pdf, xml surfaces + +# Tests +option('tests', type : 'feature', value : 'auto') + +# Util deps +option('gtk2-utils', type : 'feature', value : 'disabled') + +# Misc deps +option('glib', type : 'feature', value : 'auto') +option('spectre', type : 'feature', value : 'auto') +option('symbol-lookup', type: 'feature', value : 'auto', + description: 'Symbol lookup in debug utils via binutils/bfd') + +# Documentation +option('gtk_doc', type : 'boolean', value : false, + description: 'Build the Cairo API reference (depends on gtk-doc)') diff --git a/gfx/cairo/cairo/moz.yaml b/gfx/cairo/cairo/moz.yaml deleted file mode 100644 index 693000cdcd..0000000000 --- a/gfx/cairo/cairo/moz.yaml +++ /dev/null @@ -1,16 +0,0 @@ -schema: 1 - -bugzilla: - product: "Core" - component: "Audio/Video: Playback" - -origin: - name: "cairo" - description: "2D graphics library" - - url: "https://www.cairographics.org/" - license: "MPL-1.1" - license-file: "COPYING-MPL-1.1" - - # git://anongit.freedesktop.org/git/cairo - release: "12d521df8acc483b2daa844d4f05dc2fe2765ba6 (2010-01-21)" diff --git a/gfx/cairo/cairo/src/.gitignore b/gfx/cairo/cairo/src/.gitignore new file mode 100644 index 0000000000..32fb7333e8 --- /dev/null +++ b/gfx/cairo/cairo/src/.gitignore @@ -0,0 +1,38 @@ +.deps +.libs +Makefile +Makefile.in +Makefile.am.features +#Makefile.win32.features +*.gcda +*.gcno +*.la +*.lo +*.loT +*.pc +cairo-features.h +cairo-supported-features.h +cairo.def +*.i +*.s +*.o +*.obj +*.pdb +*.dll +*.manifest +*.ilk +*.exp +*.lib +*.trs +*~ +.*.sw? +TAGS +tags +check-has-hidden-symbols.i +check-link +check-skiplist +headers-standalone +!cairo.pc.in +!cairo-uninstalled.pc.in +!cairo-features.pc.in +!cairo-features-uninstalled.pc.in diff --git a/gfx/cairo/cairo/src/Makefile.am.analysis b/gfx/cairo/cairo/src/Makefile.am.analysis deleted file mode 100644 index fab4cf7a51..0000000000 --- a/gfx/cairo/cairo/src/Makefile.am.analysis +++ /dev/null @@ -1,35 +0,0 @@ - -SPARSE = sparse -sparse: - @echo Checking enabled sources with sparse checker - @status=true; for f in $(enabled_cairo_sources) $(enabled_cairo_cxx_sources); do \ - echo $(SPARSE) $(PREPROCESS_ARGS) $(srcdir)/$$f; \ - $(SPARSE) $(PREPROCESS_ARGS) $(srcdir)/$$f || status=false; \ - done; $$status - -SPLINT = splint -badflag -splint: - @echo Checking enabled sources with splint checker - @status=true; for f in $(enabled_cairo_sources) $(enabled_cairo_cxx_sources); do \ - echo $(SPLINT) $(PREPROCESS_ARGS) $(srcdir)/$$f; \ - $(SPLINT) $(PREPROCESS_ARGS) $(srcdir)/$$f || status=false; \ - done; $$status - -UNO = uno -uno: - @echo Checking enabled sources with uno checker - cd $(srcdir); $(UNO) $(PREPROCESS_ARGS) -DHAVE_CONFIG_H -U__GNUC__ $(enabled_cairo_sources) - -headers-standalone: $(enabled_cairo_headers) $(enabled_cairo_private) - @echo Checking that enabled public/private headers can be compiled standalone - @status=true; for f in $(enabled_cairo_headers) $(enabled_cairo_private); do \ - echo " CHECK $$f"; \ - echo "#include \"$(srcdir)/$$f\"" > headers-standalone-tmp.c; \ - echo "int main(int argc, char * argv[]) { return 0; }" >> headers-standalone-tmp.c; \ - $(COMPILE) -o headers-standalone-tmp headers-standalone-tmp.c || status=false; \ - $(RM) headers-standalone-tmp headers-standalone-tmp.c; \ - done; $$status - @touch $@ -CLEANFILES += headers-standalone - -analysis: all headers-standalone sparse splint uno diff --git a/gfx/cairo/cairo/src/Makefile.am.features b/gfx/cairo/cairo/src/Makefile.am.features deleted file mode 100644 index 47c95db1f9..0000000000 --- a/gfx/cairo/cairo/src/Makefile.am.features +++ /dev/null @@ -1,657 +0,0 @@ -# Generated by configure. Do not edit. - -include $(top_srcdir)/src/Makefile.sources - -supported_cairo_headers = $(cairo_headers) -unsupported_cairo_headers = -all_cairo_headers = $(cairo_headers) -all_cairo_private = $(cairo_private) -all_cairo_cxx_sources = $(cairo_cxx_sources) -all_cairo_sources = $(cairo_sources) - -enabled_cairo_headers = $(cairo_headers) -enabled_cairo_private = $(cairo_private) -enabled_cairo_cxx_sources = $(cairo_cxx_sources) -enabled_cairo_sources = $(cairo_sources) - -all_cairo_pkgconf = cairo.pc -enabled_cairo_pkgconf = cairo.pc - -supported_cairo_headers += $(cairo_xlib_headers) -all_cairo_headers += $(cairo_xlib_headers) -all_cairo_private += $(cairo_xlib_private) -all_cairo_cxx_sources += $(cairo_xlib_cxx_sources) -all_cairo_sources += $(cairo_xlib_sources) -if CAIRO_HAS_XLIB_SURFACE -enabled_cairo_headers += $(cairo_xlib_headers) -enabled_cairo_private += $(cairo_xlib_private) -enabled_cairo_cxx_sources += $(cairo_xlib_cxx_sources) -enabled_cairo_sources += $(cairo_xlib_sources) -endif -all_cairo_pkgconf += cairo-xlib.pc -if CAIRO_HAS_XLIB_SURFACE -enabled_cairo_pkgconf += cairo-xlib.pc -endif - -supported_cairo_headers += $(cairo_xlib_xrender_headers) -all_cairo_headers += $(cairo_xlib_xrender_headers) -all_cairo_private += $(cairo_xlib_xrender_private) -all_cairo_cxx_sources += $(cairo_xlib_xrender_cxx_sources) -all_cairo_sources += $(cairo_xlib_xrender_sources) -if CAIRO_HAS_XLIB_XRENDER_SURFACE -enabled_cairo_headers += $(cairo_xlib_xrender_headers) -enabled_cairo_private += $(cairo_xlib_xrender_private) -enabled_cairo_cxx_sources += $(cairo_xlib_xrender_cxx_sources) -enabled_cairo_sources += $(cairo_xlib_xrender_sources) -endif -all_cairo_pkgconf += cairo-xlib-xrender.pc -if CAIRO_HAS_XLIB_XRENDER_SURFACE -enabled_cairo_pkgconf += cairo-xlib-xrender.pc -endif - -supported_cairo_headers += $(cairo_xcb_headers) -all_cairo_headers += $(cairo_xcb_headers) -all_cairo_private += $(cairo_xcb_private) -all_cairo_cxx_sources += $(cairo_xcb_cxx_sources) -all_cairo_sources += $(cairo_xcb_sources) -if CAIRO_HAS_XCB_SURFACE -enabled_cairo_headers += $(cairo_xcb_headers) -enabled_cairo_private += $(cairo_xcb_private) -enabled_cairo_cxx_sources += $(cairo_xcb_cxx_sources) -enabled_cairo_sources += $(cairo_xcb_sources) -endif -all_cairo_pkgconf += cairo-xcb.pc -if CAIRO_HAS_XCB_SURFACE -enabled_cairo_pkgconf += cairo-xcb.pc -endif - -unsupported_cairo_headers += $(cairo_xlib_xcb_headers) -all_cairo_headers += $(cairo_xlib_xcb_headers) -all_cairo_private += $(cairo_xlib_xcb_private) -all_cairo_cxx_sources += $(cairo_xlib_xcb_cxx_sources) -all_cairo_sources += $(cairo_xlib_xcb_sources) -if CAIRO_HAS_XLIB_XCB_FUNCTIONS -enabled_cairo_headers += $(cairo_xlib_xcb_headers) -enabled_cairo_private += $(cairo_xlib_xcb_private) -enabled_cairo_cxx_sources += $(cairo_xlib_xcb_cxx_sources) -enabled_cairo_sources += $(cairo_xlib_xcb_sources) -endif -all_cairo_pkgconf += cairo-xlib-xcb.pc -if CAIRO_HAS_XLIB_XCB_FUNCTIONS -enabled_cairo_pkgconf += cairo-xlib-xcb.pc -endif - -supported_cairo_headers += $(cairo_xcb_shm_headers) -all_cairo_headers += $(cairo_xcb_shm_headers) -all_cairo_private += $(cairo_xcb_shm_private) -all_cairo_cxx_sources += $(cairo_xcb_shm_cxx_sources) -all_cairo_sources += $(cairo_xcb_shm_sources) -if CAIRO_HAS_XCB_SHM_FUNCTIONS -enabled_cairo_headers += $(cairo_xcb_shm_headers) -enabled_cairo_private += $(cairo_xcb_shm_private) -enabled_cairo_cxx_sources += $(cairo_xcb_shm_cxx_sources) -enabled_cairo_sources += $(cairo_xcb_shm_sources) -endif -all_cairo_pkgconf += cairo-xcb-shm.pc -if CAIRO_HAS_XCB_SHM_FUNCTIONS -enabled_cairo_pkgconf += cairo-xcb-shm.pc -endif - -unsupported_cairo_headers += $(cairo_qt_headers) -all_cairo_headers += $(cairo_qt_headers) -all_cairo_private += $(cairo_qt_private) -all_cairo_cxx_sources += $(cairo_qt_cxx_sources) -all_cairo_sources += $(cairo_qt_sources) -if CAIRO_HAS_QT_SURFACE -enabled_cairo_headers += $(cairo_qt_headers) -enabled_cairo_private += $(cairo_qt_private) -enabled_cairo_cxx_sources += $(cairo_qt_cxx_sources) -enabled_cairo_sources += $(cairo_qt_sources) -endif -all_cairo_pkgconf += cairo-qt.pc -if CAIRO_HAS_QT_SURFACE -enabled_cairo_pkgconf += cairo-qt.pc -endif - -supported_cairo_headers += $(cairo_quartz_headers) -all_cairo_headers += $(cairo_quartz_headers) -all_cairo_private += $(cairo_quartz_private) -all_cairo_cxx_sources += $(cairo_quartz_cxx_sources) -all_cairo_sources += $(cairo_quartz_sources) -if CAIRO_HAS_QUARTZ_SURFACE -enabled_cairo_headers += $(cairo_quartz_headers) -enabled_cairo_private += $(cairo_quartz_private) -enabled_cairo_cxx_sources += $(cairo_quartz_cxx_sources) -enabled_cairo_sources += $(cairo_quartz_sources) -endif -all_cairo_pkgconf += cairo-quartz.pc -if CAIRO_HAS_QUARTZ_SURFACE -enabled_cairo_pkgconf += cairo-quartz.pc -endif - -supported_cairo_headers += $(cairo_quartz_font_headers) -all_cairo_headers += $(cairo_quartz_font_headers) -all_cairo_private += $(cairo_quartz_font_private) -all_cairo_cxx_sources += $(cairo_quartz_font_cxx_sources) -all_cairo_sources += $(cairo_quartz_font_sources) -if CAIRO_HAS_QUARTZ_FONT -enabled_cairo_headers += $(cairo_quartz_font_headers) -enabled_cairo_private += $(cairo_quartz_font_private) -enabled_cairo_cxx_sources += $(cairo_quartz_font_cxx_sources) -enabled_cairo_sources += $(cairo_quartz_font_sources) -endif -all_cairo_pkgconf += cairo-quartz-font.pc -if CAIRO_HAS_QUARTZ_FONT -enabled_cairo_pkgconf += cairo-quartz-font.pc -endif - -unsupported_cairo_headers += $(cairo_quartz_image_headers) -all_cairo_headers += $(cairo_quartz_image_headers) -all_cairo_private += $(cairo_quartz_image_private) -all_cairo_cxx_sources += $(cairo_quartz_image_cxx_sources) -all_cairo_sources += $(cairo_quartz_image_sources) -if CAIRO_HAS_QUARTZ_IMAGE_SURFACE -enabled_cairo_headers += $(cairo_quartz_image_headers) -enabled_cairo_private += $(cairo_quartz_image_private) -enabled_cairo_cxx_sources += $(cairo_quartz_image_cxx_sources) -enabled_cairo_sources += $(cairo_quartz_image_sources) -endif -all_cairo_pkgconf += cairo-quartz-image.pc -if CAIRO_HAS_QUARTZ_IMAGE_SURFACE -enabled_cairo_pkgconf += cairo-quartz-image.pc -endif - -supported_cairo_headers += $(cairo_win32_headers) -all_cairo_headers += $(cairo_win32_headers) -all_cairo_private += $(cairo_win32_private) -all_cairo_cxx_sources += $(cairo_win32_cxx_sources) -all_cairo_sources += $(cairo_win32_sources) -if CAIRO_HAS_WIN32_SURFACE -enabled_cairo_headers += $(cairo_win32_headers) -enabled_cairo_private += $(cairo_win32_private) -enabled_cairo_cxx_sources += $(cairo_win32_cxx_sources) -enabled_cairo_sources += $(cairo_win32_sources) -endif -all_cairo_pkgconf += cairo-win32.pc -if CAIRO_HAS_WIN32_SURFACE -enabled_cairo_pkgconf += cairo-win32.pc -endif - -supported_cairo_headers += $(cairo_win32_font_headers) -all_cairo_headers += $(cairo_win32_font_headers) -all_cairo_private += $(cairo_win32_font_private) -all_cairo_cxx_sources += $(cairo_win32_font_cxx_sources) -all_cairo_sources += $(cairo_win32_font_sources) -if CAIRO_HAS_WIN32_FONT -enabled_cairo_headers += $(cairo_win32_font_headers) -enabled_cairo_private += $(cairo_win32_font_private) -enabled_cairo_cxx_sources += $(cairo_win32_font_cxx_sources) -enabled_cairo_sources += $(cairo_win32_font_sources) -endif -all_cairo_pkgconf += cairo-win32-font.pc -if CAIRO_HAS_WIN32_FONT -enabled_cairo_pkgconf += cairo-win32-font.pc -endif - -unsupported_cairo_headers += $(cairo_os2_headers) -all_cairo_headers += $(cairo_os2_headers) -all_cairo_private += $(cairo_os2_private) -all_cairo_cxx_sources += $(cairo_os2_cxx_sources) -all_cairo_sources += $(cairo_os2_sources) -if CAIRO_HAS_OS2_SURFACE -enabled_cairo_headers += $(cairo_os2_headers) -enabled_cairo_private += $(cairo_os2_private) -enabled_cairo_cxx_sources += $(cairo_os2_cxx_sources) -enabled_cairo_sources += $(cairo_os2_sources) -endif -all_cairo_pkgconf += cairo-os2.pc -if CAIRO_HAS_OS2_SURFACE -enabled_cairo_pkgconf += cairo-os2.pc -endif - -unsupported_cairo_headers += $(cairo_beos_headers) -all_cairo_headers += $(cairo_beos_headers) -all_cairo_private += $(cairo_beos_private) -all_cairo_cxx_sources += $(cairo_beos_cxx_sources) -all_cairo_sources += $(cairo_beos_sources) -if CAIRO_HAS_BEOS_SURFACE -enabled_cairo_headers += $(cairo_beos_headers) -enabled_cairo_private += $(cairo_beos_private) -enabled_cairo_cxx_sources += $(cairo_beos_cxx_sources) -enabled_cairo_sources += $(cairo_beos_sources) -endif -all_cairo_pkgconf += cairo-beos.pc -if CAIRO_HAS_BEOS_SURFACE -enabled_cairo_pkgconf += cairo-beos.pc -endif - -unsupported_cairo_headers += $(cairo_drm_headers) -all_cairo_headers += $(cairo_drm_headers) -all_cairo_private += $(cairo_drm_private) -all_cairo_cxx_sources += $(cairo_drm_cxx_sources) -all_cairo_sources += $(cairo_drm_sources) -if CAIRO_HAS_DRM_SURFACE -enabled_cairo_headers += $(cairo_drm_headers) -enabled_cairo_private += $(cairo_drm_private) -enabled_cairo_cxx_sources += $(cairo_drm_cxx_sources) -enabled_cairo_sources += $(cairo_drm_sources) -endif -all_cairo_pkgconf += cairo-drm.pc -if CAIRO_HAS_DRM_SURFACE -enabled_cairo_pkgconf += cairo-drm.pc -endif - -unsupported_cairo_headers += $(cairo_gallium_headers) -all_cairo_headers += $(cairo_gallium_headers) -all_cairo_private += $(cairo_gallium_private) -all_cairo_cxx_sources += $(cairo_gallium_cxx_sources) -all_cairo_sources += $(cairo_gallium_sources) -if CAIRO_HAS_GALLIUM_SURFACE -enabled_cairo_headers += $(cairo_gallium_headers) -enabled_cairo_private += $(cairo_gallium_private) -enabled_cairo_cxx_sources += $(cairo_gallium_cxx_sources) -enabled_cairo_sources += $(cairo_gallium_sources) -endif -all_cairo_pkgconf += cairo-gallium.pc -if CAIRO_HAS_GALLIUM_SURFACE -enabled_cairo_pkgconf += cairo-gallium.pc -endif - -supported_cairo_headers += $(cairo_png_headers) -all_cairo_headers += $(cairo_png_headers) -all_cairo_private += $(cairo_png_private) -all_cairo_cxx_sources += $(cairo_png_cxx_sources) -all_cairo_sources += $(cairo_png_sources) -if CAIRO_HAS_PNG_FUNCTIONS -enabled_cairo_headers += $(cairo_png_headers) -enabled_cairo_private += $(cairo_png_private) -enabled_cairo_cxx_sources += $(cairo_png_cxx_sources) -enabled_cairo_sources += $(cairo_png_sources) -endif -all_cairo_pkgconf += cairo-png.pc -if CAIRO_HAS_PNG_FUNCTIONS -enabled_cairo_pkgconf += cairo-png.pc -endif - -unsupported_cairo_headers += $(cairo_gl_headers) -all_cairo_headers += $(cairo_gl_headers) -all_cairo_private += $(cairo_gl_private) -all_cairo_cxx_sources += $(cairo_gl_cxx_sources) -all_cairo_sources += $(cairo_gl_sources) -if CAIRO_HAS_GL_SURFACE -enabled_cairo_headers += $(cairo_gl_headers) -enabled_cairo_private += $(cairo_gl_private) -enabled_cairo_cxx_sources += $(cairo_gl_cxx_sources) -enabled_cairo_sources += $(cairo_gl_sources) -endif -all_cairo_pkgconf += cairo-gl.pc -if CAIRO_HAS_GL_SURFACE -enabled_cairo_pkgconf += cairo-gl.pc -endif - -unsupported_cairo_headers += $(cairo_glesv2_headers) -all_cairo_headers += $(cairo_glesv2_headers) -all_cairo_private += $(cairo_glesv2_private) -all_cairo_cxx_sources += $(cairo_glesv2_cxx_sources) -all_cairo_sources += $(cairo_glesv2_sources) -if CAIRO_HAS_GLESV2_SURFACE -enabled_cairo_headers += $(cairo_glesv2_headers) -enabled_cairo_private += $(cairo_glesv2_private) -enabled_cairo_cxx_sources += $(cairo_glesv2_cxx_sources) -enabled_cairo_sources += $(cairo_glesv2_sources) -endif -all_cairo_pkgconf += cairo-glesv2.pc -if CAIRO_HAS_GLESV2_SURFACE -enabled_cairo_pkgconf += cairo-glesv2.pc -endif - -unsupported_cairo_headers += $(cairo_glesv3_headers) -all_cairo_headers += $(cairo_glesv3_headers) -all_cairo_private += $(cairo_glesv3_private) -all_cairo_cxx_sources += $(cairo_glesv3_cxx_sources) -all_cairo_sources += $(cairo_glesv3_sources) -if CAIRO_HAS_GLESV3_SURFACE -enabled_cairo_headers += $(cairo_glesv3_headers) -enabled_cairo_private += $(cairo_glesv3_private) -enabled_cairo_cxx_sources += $(cairo_glesv3_cxx_sources) -enabled_cairo_sources += $(cairo_glesv3_sources) -endif -all_cairo_pkgconf += cairo-glesv3.pc -if CAIRO_HAS_GLESV3_SURFACE -enabled_cairo_pkgconf += cairo-glesv3.pc -endif - -unsupported_cairo_headers += $(cairo_cogl_headers) -all_cairo_headers += $(cairo_cogl_headers) -all_cairo_private += $(cairo_cogl_private) -all_cairo_cxx_sources += $(cairo_cogl_cxx_sources) -all_cairo_sources += $(cairo_cogl_sources) -if CAIRO_HAS_COGL_SURFACE -enabled_cairo_headers += $(cairo_cogl_headers) -enabled_cairo_private += $(cairo_cogl_private) -enabled_cairo_cxx_sources += $(cairo_cogl_cxx_sources) -enabled_cairo_sources += $(cairo_cogl_sources) -endif -all_cairo_pkgconf += cairo-cogl.pc -if CAIRO_HAS_COGL_SURFACE -enabled_cairo_pkgconf += cairo-cogl.pc -endif - -unsupported_cairo_headers += $(cairo_directfb_headers) -all_cairo_headers += $(cairo_directfb_headers) -all_cairo_private += $(cairo_directfb_private) -all_cairo_cxx_sources += $(cairo_directfb_cxx_sources) -all_cairo_sources += $(cairo_directfb_sources) -if CAIRO_HAS_DIRECTFB_SURFACE -enabled_cairo_headers += $(cairo_directfb_headers) -enabled_cairo_private += $(cairo_directfb_private) -enabled_cairo_cxx_sources += $(cairo_directfb_cxx_sources) -enabled_cairo_sources += $(cairo_directfb_sources) -endif -all_cairo_pkgconf += cairo-directfb.pc -if CAIRO_HAS_DIRECTFB_SURFACE -enabled_cairo_pkgconf += cairo-directfb.pc -endif - -unsupported_cairo_headers += $(cairo_vg_headers) -all_cairo_headers += $(cairo_vg_headers) -all_cairo_private += $(cairo_vg_private) -all_cairo_cxx_sources += $(cairo_vg_cxx_sources) -all_cairo_sources += $(cairo_vg_sources) -if CAIRO_HAS_VG_SURFACE -enabled_cairo_headers += $(cairo_vg_headers) -enabled_cairo_private += $(cairo_vg_private) -enabled_cairo_cxx_sources += $(cairo_vg_cxx_sources) -enabled_cairo_sources += $(cairo_vg_sources) -endif -all_cairo_pkgconf += cairo-vg.pc -if CAIRO_HAS_VG_SURFACE -enabled_cairo_pkgconf += cairo-vg.pc -endif - -supported_cairo_headers += $(cairo_egl_headers) -all_cairo_headers += $(cairo_egl_headers) -all_cairo_private += $(cairo_egl_private) -all_cairo_cxx_sources += $(cairo_egl_cxx_sources) -all_cairo_sources += $(cairo_egl_sources) -if CAIRO_HAS_EGL_FUNCTIONS -enabled_cairo_headers += $(cairo_egl_headers) -enabled_cairo_private += $(cairo_egl_private) -enabled_cairo_cxx_sources += $(cairo_egl_cxx_sources) -enabled_cairo_sources += $(cairo_egl_sources) -endif -all_cairo_pkgconf += cairo-egl.pc -if CAIRO_HAS_EGL_FUNCTIONS -enabled_cairo_pkgconf += cairo-egl.pc -endif - -supported_cairo_headers += $(cairo_glx_headers) -all_cairo_headers += $(cairo_glx_headers) -all_cairo_private += $(cairo_glx_private) -all_cairo_cxx_sources += $(cairo_glx_cxx_sources) -all_cairo_sources += $(cairo_glx_sources) -if CAIRO_HAS_GLX_FUNCTIONS -enabled_cairo_headers += $(cairo_glx_headers) -enabled_cairo_private += $(cairo_glx_private) -enabled_cairo_cxx_sources += $(cairo_glx_cxx_sources) -enabled_cairo_sources += $(cairo_glx_sources) -endif -all_cairo_pkgconf += cairo-glx.pc -if CAIRO_HAS_GLX_FUNCTIONS -enabled_cairo_pkgconf += cairo-glx.pc -endif - -supported_cairo_headers += $(cairo_wgl_headers) -all_cairo_headers += $(cairo_wgl_headers) -all_cairo_private += $(cairo_wgl_private) -all_cairo_cxx_sources += $(cairo_wgl_cxx_sources) -all_cairo_sources += $(cairo_wgl_sources) -if CAIRO_HAS_WGL_FUNCTIONS -enabled_cairo_headers += $(cairo_wgl_headers) -enabled_cairo_private += $(cairo_wgl_private) -enabled_cairo_cxx_sources += $(cairo_wgl_cxx_sources) -enabled_cairo_sources += $(cairo_wgl_sources) -endif -all_cairo_pkgconf += cairo-wgl.pc -if CAIRO_HAS_WGL_FUNCTIONS -enabled_cairo_pkgconf += cairo-wgl.pc -endif - -supported_cairo_headers += $(cairo_script_headers) -all_cairo_headers += $(cairo_script_headers) -all_cairo_private += $(cairo_script_private) -all_cairo_cxx_sources += $(cairo_script_cxx_sources) -all_cairo_sources += $(cairo_script_sources) -if CAIRO_HAS_SCRIPT_SURFACE -enabled_cairo_headers += $(cairo_script_headers) -enabled_cairo_private += $(cairo_script_private) -enabled_cairo_cxx_sources += $(cairo_script_cxx_sources) -enabled_cairo_sources += $(cairo_script_sources) -endif -all_cairo_pkgconf += cairo-script.pc -if CAIRO_HAS_SCRIPT_SURFACE -enabled_cairo_pkgconf += cairo-script.pc -endif - -supported_cairo_headers += $(cairo_ft_headers) -all_cairo_headers += $(cairo_ft_headers) -all_cairo_private += $(cairo_ft_private) -all_cairo_cxx_sources += $(cairo_ft_cxx_sources) -all_cairo_sources += $(cairo_ft_sources) -if CAIRO_HAS_FT_FONT -enabled_cairo_headers += $(cairo_ft_headers) -enabled_cairo_private += $(cairo_ft_private) -enabled_cairo_cxx_sources += $(cairo_ft_cxx_sources) -enabled_cairo_sources += $(cairo_ft_sources) -endif -all_cairo_pkgconf += cairo-ft.pc -if CAIRO_HAS_FT_FONT -enabled_cairo_pkgconf += cairo-ft.pc -endif - -supported_cairo_headers += $(cairo_fc_headers) -all_cairo_headers += $(cairo_fc_headers) -all_cairo_private += $(cairo_fc_private) -all_cairo_cxx_sources += $(cairo_fc_cxx_sources) -all_cairo_sources += $(cairo_fc_sources) -if CAIRO_HAS_FC_FONT -enabled_cairo_headers += $(cairo_fc_headers) -enabled_cairo_private += $(cairo_fc_private) -enabled_cairo_cxx_sources += $(cairo_fc_cxx_sources) -enabled_cairo_sources += $(cairo_fc_sources) -endif -all_cairo_pkgconf += cairo-fc.pc -if CAIRO_HAS_FC_FONT -enabled_cairo_pkgconf += cairo-fc.pc -endif - -supported_cairo_headers += $(cairo_ps_headers) -all_cairo_headers += $(cairo_ps_headers) -all_cairo_private += $(cairo_ps_private) -all_cairo_cxx_sources += $(cairo_ps_cxx_sources) -all_cairo_sources += $(cairo_ps_sources) -if CAIRO_HAS_PS_SURFACE -enabled_cairo_headers += $(cairo_ps_headers) -enabled_cairo_private += $(cairo_ps_private) -enabled_cairo_cxx_sources += $(cairo_ps_cxx_sources) -enabled_cairo_sources += $(cairo_ps_sources) -endif -all_cairo_pkgconf += cairo-ps.pc -if CAIRO_HAS_PS_SURFACE -enabled_cairo_pkgconf += cairo-ps.pc -endif - -supported_cairo_headers += $(cairo_pdf_headers) -all_cairo_headers += $(cairo_pdf_headers) -all_cairo_private += $(cairo_pdf_private) -all_cairo_cxx_sources += $(cairo_pdf_cxx_sources) -all_cairo_sources += $(cairo_pdf_sources) -if CAIRO_HAS_PDF_SURFACE -enabled_cairo_headers += $(cairo_pdf_headers) -enabled_cairo_private += $(cairo_pdf_private) -enabled_cairo_cxx_sources += $(cairo_pdf_cxx_sources) -enabled_cairo_sources += $(cairo_pdf_sources) -endif -all_cairo_pkgconf += cairo-pdf.pc -if CAIRO_HAS_PDF_SURFACE -enabled_cairo_pkgconf += cairo-pdf.pc -endif - -supported_cairo_headers += $(cairo_svg_headers) -all_cairo_headers += $(cairo_svg_headers) -all_cairo_private += $(cairo_svg_private) -all_cairo_cxx_sources += $(cairo_svg_cxx_sources) -all_cairo_sources += $(cairo_svg_sources) -if CAIRO_HAS_SVG_SURFACE -enabled_cairo_headers += $(cairo_svg_headers) -enabled_cairo_private += $(cairo_svg_private) -enabled_cairo_cxx_sources += $(cairo_svg_cxx_sources) -enabled_cairo_sources += $(cairo_svg_sources) -endif -all_cairo_pkgconf += cairo-svg.pc -if CAIRO_HAS_SVG_SURFACE -enabled_cairo_pkgconf += cairo-svg.pc -endif - -all_cairo_private += $(cairo_test_surfaces_private) $(cairo_test_surfaces_headers) -all_cairo_cxx_sources += $(cairo_test_surfaces_cxx_sources) -all_cairo_sources += $(cairo_test_surfaces_sources) -if CAIRO_HAS_TEST_SURFACES -enabled_cairo_private += $(cairo_test_surfaces_private) $(cairo_test_surfaces_headers) -enabled_cairo_cxx_sources += $(cairo_test_surfaces_cxx_sources) -enabled_cairo_sources += $(cairo_test_surfaces_sources) -endif - -supported_cairo_headers += $(cairo_image_headers) -all_cairo_headers += $(cairo_image_headers) -all_cairo_private += $(cairo_image_private) -all_cairo_cxx_sources += $(cairo_image_cxx_sources) -all_cairo_sources += $(cairo_image_sources) -enabled_cairo_headers += $(cairo_image_headers) -enabled_cairo_private += $(cairo_image_private) -enabled_cairo_cxx_sources += $(cairo_image_cxx_sources) -enabled_cairo_sources += $(cairo_image_sources) - -supported_cairo_headers += $(cairo_mime_headers) -all_cairo_headers += $(cairo_mime_headers) -all_cairo_private += $(cairo_mime_private) -all_cairo_cxx_sources += $(cairo_mime_cxx_sources) -all_cairo_sources += $(cairo_mime_sources) -enabled_cairo_headers += $(cairo_mime_headers) -enabled_cairo_private += $(cairo_mime_private) -enabled_cairo_cxx_sources += $(cairo_mime_cxx_sources) -enabled_cairo_sources += $(cairo_mime_sources) - -supported_cairo_headers += $(cairo_recording_headers) -all_cairo_headers += $(cairo_recording_headers) -all_cairo_private += $(cairo_recording_private) -all_cairo_cxx_sources += $(cairo_recording_cxx_sources) -all_cairo_sources += $(cairo_recording_sources) -enabled_cairo_headers += $(cairo_recording_headers) -enabled_cairo_private += $(cairo_recording_private) -enabled_cairo_cxx_sources += $(cairo_recording_cxx_sources) -enabled_cairo_sources += $(cairo_recording_sources) - -supported_cairo_headers += $(cairo_observer_headers) -all_cairo_headers += $(cairo_observer_headers) -all_cairo_private += $(cairo_observer_private) -all_cairo_cxx_sources += $(cairo_observer_cxx_sources) -all_cairo_sources += $(cairo_observer_sources) -enabled_cairo_headers += $(cairo_observer_headers) -enabled_cairo_private += $(cairo_observer_private) -enabled_cairo_cxx_sources += $(cairo_observer_cxx_sources) -enabled_cairo_sources += $(cairo_observer_sources) - -unsupported_cairo_headers += $(cairo_tee_headers) -all_cairo_headers += $(cairo_tee_headers) -all_cairo_private += $(cairo_tee_private) -all_cairo_cxx_sources += $(cairo_tee_cxx_sources) -all_cairo_sources += $(cairo_tee_sources) -if CAIRO_HAS_TEE_SURFACE -enabled_cairo_headers += $(cairo_tee_headers) -enabled_cairo_private += $(cairo_tee_private) -enabled_cairo_cxx_sources += $(cairo_tee_cxx_sources) -enabled_cairo_sources += $(cairo_tee_sources) -endif -all_cairo_pkgconf += cairo-tee.pc -if CAIRO_HAS_TEE_SURFACE -enabled_cairo_pkgconf += cairo-tee.pc -endif - -unsupported_cairo_headers += $(cairo_xml_headers) -all_cairo_headers += $(cairo_xml_headers) -all_cairo_private += $(cairo_xml_private) -all_cairo_cxx_sources += $(cairo_xml_cxx_sources) -all_cairo_sources += $(cairo_xml_sources) -if CAIRO_HAS_XML_SURFACE -enabled_cairo_headers += $(cairo_xml_headers) -enabled_cairo_private += $(cairo_xml_private) -enabled_cairo_cxx_sources += $(cairo_xml_cxx_sources) -enabled_cairo_sources += $(cairo_xml_sources) -endif -all_cairo_pkgconf += cairo-xml.pc -if CAIRO_HAS_XML_SURFACE -enabled_cairo_pkgconf += cairo-xml.pc -endif - -supported_cairo_headers += $(cairo_user_headers) -all_cairo_headers += $(cairo_user_headers) -all_cairo_private += $(cairo_user_private) -all_cairo_cxx_sources += $(cairo_user_cxx_sources) -all_cairo_sources += $(cairo_user_sources) -enabled_cairo_headers += $(cairo_user_headers) -enabled_cairo_private += $(cairo_user_private) -enabled_cairo_cxx_sources += $(cairo_user_cxx_sources) -enabled_cairo_sources += $(cairo_user_sources) - -all_cairo_private += $(cairo_pthread_private) $(cairo_pthread_headers) -all_cairo_cxx_sources += $(cairo_pthread_cxx_sources) -all_cairo_sources += $(cairo_pthread_sources) -if CAIRO_HAS_PTHREAD -enabled_cairo_private += $(cairo_pthread_private) $(cairo_pthread_headers) -enabled_cairo_cxx_sources += $(cairo_pthread_cxx_sources) -enabled_cairo_sources += $(cairo_pthread_sources) -endif - -supported_cairo_headers += $(cairo_gobject_headers) -all_cairo_headers += $(cairo_gobject_headers) -all_cairo_private += $(cairo_gobject_private) -all_cairo_cxx_sources += $(cairo_gobject_cxx_sources) -all_cairo_sources += $(cairo_gobject_sources) -if CAIRO_HAS_GOBJECT_FUNCTIONS -enabled_cairo_headers += $(cairo_gobject_headers) -enabled_cairo_private += $(cairo_gobject_private) -enabled_cairo_cxx_sources += $(cairo_gobject_cxx_sources) -enabled_cairo_sources += $(cairo_gobject_sources) -endif -all_cairo_pkgconf += cairo-gobject.pc -if CAIRO_HAS_GOBJECT_FUNCTIONS -enabled_cairo_pkgconf += cairo-gobject.pc -endif - -all_cairo_private += $(cairo_trace_private) $(cairo_trace_headers) -all_cairo_cxx_sources += $(cairo_trace_cxx_sources) -all_cairo_sources += $(cairo_trace_sources) -if CAIRO_HAS_TRACE -enabled_cairo_private += $(cairo_trace_private) $(cairo_trace_headers) -enabled_cairo_cxx_sources += $(cairo_trace_cxx_sources) -enabled_cairo_sources += $(cairo_trace_sources) -endif - -all_cairo_private += $(cairo_interpreter_private) $(cairo_interpreter_headers) -all_cairo_cxx_sources += $(cairo_interpreter_cxx_sources) -all_cairo_sources += $(cairo_interpreter_sources) -if CAIRO_HAS_INTERPRETER -enabled_cairo_private += $(cairo_interpreter_private) $(cairo_interpreter_headers) -enabled_cairo_cxx_sources += $(cairo_interpreter_cxx_sources) -enabled_cairo_sources += $(cairo_interpreter_sources) -endif - -all_cairo_private += $(cairo_symbol_lookup_private) $(cairo_symbol_lookup_headers) -all_cairo_cxx_sources += $(cairo_symbol_lookup_cxx_sources) -all_cairo_sources += $(cairo_symbol_lookup_sources) -if CAIRO_HAS_SYMBOL_LOOKUP -enabled_cairo_private += $(cairo_symbol_lookup_private) $(cairo_symbol_lookup_headers) -enabled_cairo_cxx_sources += $(cairo_symbol_lookup_cxx_sources) -enabled_cairo_sources += $(cairo_symbol_lookup_sources) -endif diff --git a/gfx/cairo/cairo/src/Makefile.am.hide b/gfx/cairo/cairo/src/Makefile.am.hide deleted file mode 100644 index 23ba1861d4..0000000000 --- a/gfx/cairo/cairo/src/Makefile.am.hide +++ /dev/null @@ -1,117 +0,0 @@ -# Note: All source files are listed in Makefile.sources. - -include $(top_srcdir)/build/Makefile.am.common -include $(srcdir)/Makefile.am.features - -EXTRA_DIST += Makefile.win32 Makefile.win32.features -#MAINTAINERCLEANFILES += $(srcdir)/Makefile.win32.features - -AM_CPPFLAGS = -I$(srcdir) $(CAIRO_CFLAGS) -AM_LDFLAGS = $(CAIRO_LDFLAGS) - -if OS_WIN32 -export_symbols = -export-symbols cairo.def -cairo_def_dependency = cairo.def -endif - -$(top_builddir)/config.h: $(top_srcdir)/config.h.in - cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) config.h - -cairoincludedir = $(includedir)/cairo -cairoinclude_HEADERS = $(enabled_cairo_headers) - -lib_LTLIBRARIES = libcairo.la - -if BUILD_CXX -cairo_cxx_lib = libcairo_cxx.la -else -cairo_cxx_lib = -endif - -noinst_LTLIBRARIES = $(cairo_cxx_lib) -libcairo_cxx_la_SOURCES = \ - $(enabled_cairo_headers) \ - $(enabled_cairo_private) \ - $(enabled_cairo_cxx_sources) \ - $(NULL) -libcairo_cxx_la_LDFLAGS = $(AM_LDFLAGS) $(export_symbols) -libcairo_cxx_la_LIBADD = $(CAIRO_LIBS) -libcairo_cxx_la_DEPENDENCIES = $(cairo_def_dependency) - - -libcairo_la_SOURCES = \ - $(enabled_cairo_headers) \ - $(enabled_cairo_private) \ - $(enabled_cairo_sources) \ - $(NULL) -libcairo_la_LDFLAGS = $(AM_LDFLAGS) -version-info $(CAIRO_LIBTOOL_VERSION_INFO) -no-undefined $(export_symbols) -libcairo_la_LIBADD = $(CAIRO_LIBS) \ - $(cairo_cxx_lib) -libcairo_la_DEPENDENCIES = $(cairo_def_dependency) $(cairo_cxx_lib) - -# Special headers -nodist_cairoinclude_HEADERS = cairo-features.h -nodist_libcairo_la_SOURCES = cairo-features.h -BUILT_SOURCES += cairo-features.h cairo-supported-features.h -DISTCLEANFILES += cairo-features.h cairo-supported-features.h -cairo-features.h cairo-supported-features.h: - cd $(top_builddir) && ./config.status src/$@ - -pkgconfigdir = $(libdir)/pkgconfig -pkgconfig_DATA = $(enabled_cairo_pkgconf) - -CLEANFILES += cairo.def -cairo.def: cairo-features.h $(enabled_cairo_headers) - @echo Generating $@ - @(echo EXPORTS; \ - (cd $(srcdir); cat $(enabled_cairo_headers) || echo 'cairo_ERROR ()' ) | \ - $(EGREP) -v '^# *include' | \ - ( cat cairo-features.h - | $(CPP) -D__cplusplus - || echo 'cairo_ERROR ()' ) | \ - $(EGREP) '^cairo_.* \(' | \ - sed -e 's/[ ].*//' | \ - sort; \ - echo LIBRARY libcairo-$(CAIRO_VERSION_SONUM).dll; \ - ) >$@ - @ ! grep -q cairo_ERROR $@ || ($(RM) $@; false) - -TESTS_ENVIRONMENT = \ - srcdir="$(srcdir)" \ - MAKE="$(MAKE) $(AM_MAKEFLAGS)" \ - all_cairo_files="$(all_cairo_files)" \ - all_cairo_headers="$(all_cairo_headers)" \ - all_cairo_private="$(all_cairo_private)" \ - all_cairo_sources="$(all_cairo_sources)" \ - enabled_cairo_headers="$(enabled_cairo_headers)" \ - enabled_cairo_private="$(enabled_cairo_private)" \ - enabled_cairo_sources="$(enabled_cairo_sources)" \ - $(NULL) -TESTS_SH = \ - check-def.sh \ - check-doc-syntax.sh \ - check-headers.sh \ - check-plt.sh \ - check-preprocessor-syntax.sh \ - $(NULL) -TESTS += $(TESTS_SH) -if CROSS_COMPILING -else -TESTS += check-link$(EXEEXT) -endif - -EXTRA_DIST += $(TESTS_SH) check-has-hidden-symbols.c check-doc-syntax.awk -check_PROGRAMS += check-link -check_link_LDADD = libcairo.la - -check: headers-standalone - -PREPROCESS_ARGS = $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) -COMPILE_ARGS = $(PREPROCESS_ARGS) $(AM_CFLAGS) $(CFLAGS) - -# The pre-processed result is used by check-{def,plt}.sh to determine whether -# cairo has been compiled with symbol hiding. -.c.i: $(cairoinclude_HEADERS) $(nodist_cairoinclude_HEADERS) cairoint.h $(top_builddir)/config.h - $(CPP) $(PREPROCESS_ARGS) $< -o $@ -.c.s: $(cairoinclude_HEADERS) $(nodist_cairoinclude_HEADERS) cairoint.h $(top_builddir)/config.h - $(CC) $(COMPILE_ARGS) $< -S -o $@ - -include $(srcdir)/Makefile.am.analysis diff --git a/gfx/cairo/cairo/src/Makefile.in.hide b/gfx/cairo/cairo/src/Makefile.in.hide deleted file mode 100644 index ff28491201..0000000000 --- a/gfx/cairo/cairo/src/Makefile.in.hide +++ /dev/null @@ -1,3703 +0,0 @@ -# Makefile.in generated by automake 1.16.1 from Makefile.am. -# @configure_input@ - -# Copyright (C) 1994-2018 Free Software Foundation, Inc. - -# This Makefile.in is free software; the Free Software Foundation -# gives unlimited permission to copy and/or distribute it, -# with or without modifications, as long as this notice is preserved. - -# This program is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY, to the extent permitted by law; without -# even the implied warranty of MERCHANTABILITY or FITNESS FOR A -# PARTICULAR PURPOSE. - -@SET_MAKE@ - -# Note: All source files are listed in Makefile.sources. - -# Generated by configure. Do not edit. - -# Makefile.sources -# -# This file is the canonical location listing all the source files used -# to build the cairo library. Every source file is categorized as one of: -# -# * public header file -# * private header file (must end in -private.h except for cairoint.h) -# * source code file -# -# Every source file should be specified exactly once, grouped with the -# feature that uses the source file. If more than one feature use the -# file (like pdf_operators or font_subset files), the files should be -# appended to to the base cairo files, and the code inside them -# enabled/disabled using C preprocessor macros defined in cairoint.h. -# See how pdf_operators or font_subset are handled. -# -# The sources are picked up according to the configured features -# by the generated file Makefile.am.features or Makefile.win32.features. -# -# These are a few special source files. Those are not included in this -# file to not confuse build systems. Each build system must handle them -# separately. These files include: -# -# * cairo-features.h: -# This file is generated by configure and includes macros signifying -# which features are enabled. This file should be installed like -# other public headers, but should NOT be distributed in the cairo -# distribution. -# -# * cairo-supported-features.h: -# This file is generated by configure and includes macros signifying -# all supported features. This is used by gtk-doc to generate -# documentation for all those macros, enabled or not. -# This file is NOT used during the build of the library and should -# NOT be installed or distributed. -# -# Please follow the strict syntax of this file, including keeping file -# lists sorted. -# - - - -VPATH = @srcdir@ -am__is_gnu_make = { \ - if test -z '$(MAKELEVEL)'; then \ - false; \ - elif test -n '$(MAKE_HOST)'; then \ - true; \ - elif test -n '$(MAKE_VERSION)' && test -n '$(CURDIR)'; then \ - true; \ - else \ - false; \ - fi; \ -} -am__make_running_with_option = \ - case $${target_option-} in \ - ?) ;; \ - *) echo "am__make_running_with_option: internal error: invalid" \ - "target option '$${target_option-}' specified" >&2; \ - exit 1;; \ - esac; \ - has_opt=no; \ - sane_makeflags=$$MAKEFLAGS; \ - if $(am__is_gnu_make); then \ - sane_makeflags=$$MFLAGS; \ - else \ - case $$MAKEFLAGS in \ - *\\[\ \ ]*) \ - bs=\\; \ - sane_makeflags=`printf '%s\n' "$$MAKEFLAGS" \ - | sed "s/$$bs$$bs[$$bs $$bs ]*//g"`;; \ - esac; \ - fi; \ - skip_next=no; \ - strip_trailopt () \ - { \ - flg=`printf '%s\n' "$$flg" | sed "s/$$1.*$$//"`; \ - }; \ - for flg in $$sane_makeflags; do \ - test $$skip_next = yes && { skip_next=no; continue; }; \ - case $$flg in \ - *=*|--*) continue;; \ - -*I) strip_trailopt 'I'; skip_next=yes;; \ - -*I?*) strip_trailopt 'I';; \ - -*O) strip_trailopt 'O'; skip_next=yes;; \ - -*O?*) strip_trailopt 'O';; \ - -*l) strip_trailopt 'l'; skip_next=yes;; \ - -*l?*) strip_trailopt 'l';; \ - -[dEDm]) skip_next=yes;; \ - -[JT]) skip_next=yes;; \ - esac; \ - case $$flg in \ - *$$target_option*) has_opt=yes; break;; \ - esac; \ - done; \ - test $$has_opt = yes -am__make_dryrun = (target_option=n; $(am__make_running_with_option)) -am__make_keepgoing = (target_option=k; $(am__make_running_with_option)) -pkgdatadir = $(datadir)/@PACKAGE@ -pkgincludedir = $(includedir)/@PACKAGE@ -pkglibdir = $(libdir)/@PACKAGE@ -pkglibexecdir = $(libexecdir)/@PACKAGE@ -am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd -install_sh_DATA = $(install_sh) -c -m 644 -install_sh_PROGRAM = $(install_sh) -c -install_sh_SCRIPT = $(install_sh) -c -INSTALL_HEADER = $(INSTALL_DATA) -transform = $(program_transform_name) -NORMAL_INSTALL = : -PRE_INSTALL = : -POST_INSTALL = : -NORMAL_UNINSTALL = : -PRE_UNINSTALL = : -POST_UNINSTALL = : -build_triplet = @build@ -host_triplet = @host@ -EXTRA_PROGRAMS = -TESTS = $(am__EXEEXT_1) $(am__append_186) -check_PROGRAMS = check-link$(EXEEXT) -@CAIRO_HAS_XLIB_SURFACE_TRUE@am__append_1 = $(cairo_xlib_headers) -@CAIRO_HAS_XLIB_SURFACE_TRUE@am__append_2 = $(cairo_xlib_private) -@CAIRO_HAS_XLIB_SURFACE_TRUE@am__append_3 = $(cairo_xlib_cxx_sources) -@CAIRO_HAS_XLIB_SURFACE_TRUE@am__append_4 = $(cairo_xlib_sources) -@CAIRO_HAS_XLIB_SURFACE_TRUE@am__append_5 = cairo-xlib.pc -@CAIRO_HAS_XLIB_XRENDER_SURFACE_TRUE@am__append_6 = $(cairo_xlib_xrender_headers) -@CAIRO_HAS_XLIB_XRENDER_SURFACE_TRUE@am__append_7 = $(cairo_xlib_xrender_private) -@CAIRO_HAS_XLIB_XRENDER_SURFACE_TRUE@am__append_8 = $(cairo_xlib_xrender_cxx_sources) -@CAIRO_HAS_XLIB_XRENDER_SURFACE_TRUE@am__append_9 = $(cairo_xlib_xrender_sources) -@CAIRO_HAS_XLIB_XRENDER_SURFACE_TRUE@am__append_10 = cairo-xlib-xrender.pc -@CAIRO_HAS_XCB_SURFACE_TRUE@am__append_11 = $(cairo_xcb_headers) -@CAIRO_HAS_XCB_SURFACE_TRUE@am__append_12 = $(cairo_xcb_private) -@CAIRO_HAS_XCB_SURFACE_TRUE@am__append_13 = $(cairo_xcb_cxx_sources) -@CAIRO_HAS_XCB_SURFACE_TRUE@am__append_14 = $(cairo_xcb_sources) -@CAIRO_HAS_XCB_SURFACE_TRUE@am__append_15 = cairo-xcb.pc -@CAIRO_HAS_XLIB_XCB_FUNCTIONS_TRUE@am__append_16 = $(cairo_xlib_xcb_headers) -@CAIRO_HAS_XLIB_XCB_FUNCTIONS_TRUE@am__append_17 = $(cairo_xlib_xcb_private) -@CAIRO_HAS_XLIB_XCB_FUNCTIONS_TRUE@am__append_18 = $(cairo_xlib_xcb_cxx_sources) -@CAIRO_HAS_XLIB_XCB_FUNCTIONS_TRUE@am__append_19 = $(cairo_xlib_xcb_sources) -@CAIRO_HAS_XLIB_XCB_FUNCTIONS_TRUE@am__append_20 = cairo-xlib-xcb.pc -@CAIRO_HAS_XCB_SHM_FUNCTIONS_TRUE@am__append_21 = $(cairo_xcb_shm_headers) -@CAIRO_HAS_XCB_SHM_FUNCTIONS_TRUE@am__append_22 = $(cairo_xcb_shm_private) -@CAIRO_HAS_XCB_SHM_FUNCTIONS_TRUE@am__append_23 = $(cairo_xcb_shm_cxx_sources) -@CAIRO_HAS_XCB_SHM_FUNCTIONS_TRUE@am__append_24 = $(cairo_xcb_shm_sources) -@CAIRO_HAS_XCB_SHM_FUNCTIONS_TRUE@am__append_25 = cairo-xcb-shm.pc -@CAIRO_HAS_QT_SURFACE_TRUE@am__append_26 = $(cairo_qt_headers) -@CAIRO_HAS_QT_SURFACE_TRUE@am__append_27 = $(cairo_qt_private) -@CAIRO_HAS_QT_SURFACE_TRUE@am__append_28 = $(cairo_qt_cxx_sources) -@CAIRO_HAS_QT_SURFACE_TRUE@am__append_29 = $(cairo_qt_sources) -@CAIRO_HAS_QT_SURFACE_TRUE@am__append_30 = cairo-qt.pc -@CAIRO_HAS_QUARTZ_SURFACE_TRUE@am__append_31 = $(cairo_quartz_headers) -@CAIRO_HAS_QUARTZ_SURFACE_TRUE@am__append_32 = $(cairo_quartz_private) -@CAIRO_HAS_QUARTZ_SURFACE_TRUE@am__append_33 = $(cairo_quartz_cxx_sources) -@CAIRO_HAS_QUARTZ_SURFACE_TRUE@am__append_34 = $(cairo_quartz_sources) -@CAIRO_HAS_QUARTZ_SURFACE_TRUE@am__append_35 = cairo-quartz.pc -@CAIRO_HAS_QUARTZ_FONT_TRUE@am__append_36 = $(cairo_quartz_font_headers) -@CAIRO_HAS_QUARTZ_FONT_TRUE@am__append_37 = $(cairo_quartz_font_private) -@CAIRO_HAS_QUARTZ_FONT_TRUE@am__append_38 = $(cairo_quartz_font_cxx_sources) -@CAIRO_HAS_QUARTZ_FONT_TRUE@am__append_39 = $(cairo_quartz_font_sources) -@CAIRO_HAS_QUARTZ_FONT_TRUE@am__append_40 = cairo-quartz-font.pc -@CAIRO_HAS_QUARTZ_IMAGE_SURFACE_TRUE@am__append_41 = $(cairo_quartz_image_headers) -@CAIRO_HAS_QUARTZ_IMAGE_SURFACE_TRUE@am__append_42 = $(cairo_quartz_image_private) -@CAIRO_HAS_QUARTZ_IMAGE_SURFACE_TRUE@am__append_43 = $(cairo_quartz_image_cxx_sources) -@CAIRO_HAS_QUARTZ_IMAGE_SURFACE_TRUE@am__append_44 = $(cairo_quartz_image_sources) -@CAIRO_HAS_QUARTZ_IMAGE_SURFACE_TRUE@am__append_45 = cairo-quartz-image.pc -@CAIRO_HAS_WIN32_SURFACE_TRUE@am__append_46 = $(cairo_win32_headers) -@CAIRO_HAS_WIN32_SURFACE_TRUE@am__append_47 = $(cairo_win32_private) -@CAIRO_HAS_WIN32_SURFACE_TRUE@am__append_48 = $(cairo_win32_cxx_sources) -@CAIRO_HAS_WIN32_SURFACE_TRUE@am__append_49 = $(cairo_win32_sources) -@CAIRO_HAS_WIN32_SURFACE_TRUE@am__append_50 = cairo-win32.pc -@CAIRO_HAS_WIN32_FONT_TRUE@am__append_51 = $(cairo_win32_font_headers) -@CAIRO_HAS_WIN32_FONT_TRUE@am__append_52 = $(cairo_win32_font_private) -@CAIRO_HAS_WIN32_FONT_TRUE@am__append_53 = $(cairo_win32_font_cxx_sources) -@CAIRO_HAS_WIN32_FONT_TRUE@am__append_54 = $(cairo_win32_font_sources) -@CAIRO_HAS_WIN32_FONT_TRUE@am__append_55 = cairo-win32-font.pc -@CAIRO_HAS_OS2_SURFACE_TRUE@am__append_56 = $(cairo_os2_headers) -@CAIRO_HAS_OS2_SURFACE_TRUE@am__append_57 = $(cairo_os2_private) -@CAIRO_HAS_OS2_SURFACE_TRUE@am__append_58 = $(cairo_os2_cxx_sources) -@CAIRO_HAS_OS2_SURFACE_TRUE@am__append_59 = $(cairo_os2_sources) -@CAIRO_HAS_OS2_SURFACE_TRUE@am__append_60 = cairo-os2.pc -@CAIRO_HAS_BEOS_SURFACE_TRUE@am__append_61 = $(cairo_beos_headers) -@CAIRO_HAS_BEOS_SURFACE_TRUE@am__append_62 = $(cairo_beos_private) -@CAIRO_HAS_BEOS_SURFACE_TRUE@am__append_63 = $(cairo_beos_cxx_sources) -@CAIRO_HAS_BEOS_SURFACE_TRUE@am__append_64 = $(cairo_beos_sources) -@CAIRO_HAS_BEOS_SURFACE_TRUE@am__append_65 = cairo-beos.pc -@CAIRO_HAS_DRM_SURFACE_TRUE@am__append_66 = $(cairo_drm_headers) -@CAIRO_HAS_DRM_SURFACE_TRUE@am__append_67 = $(cairo_drm_private) -@CAIRO_HAS_DRM_SURFACE_TRUE@am__append_68 = $(cairo_drm_cxx_sources) -@CAIRO_HAS_DRM_SURFACE_TRUE@am__append_69 = $(cairo_drm_sources) -@CAIRO_HAS_DRM_SURFACE_TRUE@am__append_70 = cairo-drm.pc -@CAIRO_HAS_GALLIUM_SURFACE_TRUE@am__append_71 = $(cairo_gallium_headers) -@CAIRO_HAS_GALLIUM_SURFACE_TRUE@am__append_72 = $(cairo_gallium_private) -@CAIRO_HAS_GALLIUM_SURFACE_TRUE@am__append_73 = $(cairo_gallium_cxx_sources) -@CAIRO_HAS_GALLIUM_SURFACE_TRUE@am__append_74 = $(cairo_gallium_sources) -@CAIRO_HAS_GALLIUM_SURFACE_TRUE@am__append_75 = cairo-gallium.pc -@CAIRO_HAS_PNG_FUNCTIONS_TRUE@am__append_76 = $(cairo_png_headers) -@CAIRO_HAS_PNG_FUNCTIONS_TRUE@am__append_77 = $(cairo_png_private) -@CAIRO_HAS_PNG_FUNCTIONS_TRUE@am__append_78 = $(cairo_png_cxx_sources) -@CAIRO_HAS_PNG_FUNCTIONS_TRUE@am__append_79 = $(cairo_png_sources) -@CAIRO_HAS_PNG_FUNCTIONS_TRUE@am__append_80 = cairo-png.pc -@CAIRO_HAS_GL_SURFACE_TRUE@am__append_81 = $(cairo_gl_headers) -@CAIRO_HAS_GL_SURFACE_TRUE@am__append_82 = $(cairo_gl_private) -@CAIRO_HAS_GL_SURFACE_TRUE@am__append_83 = $(cairo_gl_cxx_sources) -@CAIRO_HAS_GL_SURFACE_TRUE@am__append_84 = $(cairo_gl_sources) -@CAIRO_HAS_GL_SURFACE_TRUE@am__append_85 = cairo-gl.pc -@CAIRO_HAS_GLESV2_SURFACE_TRUE@am__append_86 = $(cairo_glesv2_headers) -@CAIRO_HAS_GLESV2_SURFACE_TRUE@am__append_87 = $(cairo_glesv2_private) -@CAIRO_HAS_GLESV2_SURFACE_TRUE@am__append_88 = $(cairo_glesv2_cxx_sources) -@CAIRO_HAS_GLESV2_SURFACE_TRUE@am__append_89 = $(cairo_glesv2_sources) -@CAIRO_HAS_GLESV2_SURFACE_TRUE@am__append_90 = cairo-glesv2.pc -@CAIRO_HAS_GLESV3_SURFACE_TRUE@am__append_91 = $(cairo_glesv3_headers) -@CAIRO_HAS_GLESV3_SURFACE_TRUE@am__append_92 = $(cairo_glesv3_private) -@CAIRO_HAS_GLESV3_SURFACE_TRUE@am__append_93 = $(cairo_glesv3_cxx_sources) -@CAIRO_HAS_GLESV3_SURFACE_TRUE@am__append_94 = $(cairo_glesv3_sources) -@CAIRO_HAS_GLESV3_SURFACE_TRUE@am__append_95 = cairo-glesv3.pc -@CAIRO_HAS_COGL_SURFACE_TRUE@am__append_96 = $(cairo_cogl_headers) -@CAIRO_HAS_COGL_SURFACE_TRUE@am__append_97 = $(cairo_cogl_private) -@CAIRO_HAS_COGL_SURFACE_TRUE@am__append_98 = $(cairo_cogl_cxx_sources) -@CAIRO_HAS_COGL_SURFACE_TRUE@am__append_99 = $(cairo_cogl_sources) -@CAIRO_HAS_COGL_SURFACE_TRUE@am__append_100 = cairo-cogl.pc -@CAIRO_HAS_DIRECTFB_SURFACE_TRUE@am__append_101 = $(cairo_directfb_headers) -@CAIRO_HAS_DIRECTFB_SURFACE_TRUE@am__append_102 = $(cairo_directfb_private) -@CAIRO_HAS_DIRECTFB_SURFACE_TRUE@am__append_103 = $(cairo_directfb_cxx_sources) -@CAIRO_HAS_DIRECTFB_SURFACE_TRUE@am__append_104 = $(cairo_directfb_sources) -@CAIRO_HAS_DIRECTFB_SURFACE_TRUE@am__append_105 = cairo-directfb.pc -@CAIRO_HAS_VG_SURFACE_TRUE@am__append_106 = $(cairo_vg_headers) -@CAIRO_HAS_VG_SURFACE_TRUE@am__append_107 = $(cairo_vg_private) -@CAIRO_HAS_VG_SURFACE_TRUE@am__append_108 = $(cairo_vg_cxx_sources) -@CAIRO_HAS_VG_SURFACE_TRUE@am__append_109 = $(cairo_vg_sources) -@CAIRO_HAS_VG_SURFACE_TRUE@am__append_110 = cairo-vg.pc -@CAIRO_HAS_EGL_FUNCTIONS_TRUE@am__append_111 = $(cairo_egl_headers) -@CAIRO_HAS_EGL_FUNCTIONS_TRUE@am__append_112 = $(cairo_egl_private) -@CAIRO_HAS_EGL_FUNCTIONS_TRUE@am__append_113 = $(cairo_egl_cxx_sources) -@CAIRO_HAS_EGL_FUNCTIONS_TRUE@am__append_114 = $(cairo_egl_sources) -@CAIRO_HAS_EGL_FUNCTIONS_TRUE@am__append_115 = cairo-egl.pc -@CAIRO_HAS_GLX_FUNCTIONS_TRUE@am__append_116 = $(cairo_glx_headers) -@CAIRO_HAS_GLX_FUNCTIONS_TRUE@am__append_117 = $(cairo_glx_private) -@CAIRO_HAS_GLX_FUNCTIONS_TRUE@am__append_118 = $(cairo_glx_cxx_sources) -@CAIRO_HAS_GLX_FUNCTIONS_TRUE@am__append_119 = $(cairo_glx_sources) -@CAIRO_HAS_GLX_FUNCTIONS_TRUE@am__append_120 = cairo-glx.pc -@CAIRO_HAS_WGL_FUNCTIONS_TRUE@am__append_121 = $(cairo_wgl_headers) -@CAIRO_HAS_WGL_FUNCTIONS_TRUE@am__append_122 = $(cairo_wgl_private) -@CAIRO_HAS_WGL_FUNCTIONS_TRUE@am__append_123 = $(cairo_wgl_cxx_sources) -@CAIRO_HAS_WGL_FUNCTIONS_TRUE@am__append_124 = $(cairo_wgl_sources) -@CAIRO_HAS_WGL_FUNCTIONS_TRUE@am__append_125 = cairo-wgl.pc -@CAIRO_HAS_SCRIPT_SURFACE_TRUE@am__append_126 = $(cairo_script_headers) -@CAIRO_HAS_SCRIPT_SURFACE_TRUE@am__append_127 = $(cairo_script_private) -@CAIRO_HAS_SCRIPT_SURFACE_TRUE@am__append_128 = $(cairo_script_cxx_sources) -@CAIRO_HAS_SCRIPT_SURFACE_TRUE@am__append_129 = $(cairo_script_sources) -@CAIRO_HAS_SCRIPT_SURFACE_TRUE@am__append_130 = cairo-script.pc -@CAIRO_HAS_FT_FONT_TRUE@am__append_131 = $(cairo_ft_headers) -@CAIRO_HAS_FT_FONT_TRUE@am__append_132 = $(cairo_ft_private) -@CAIRO_HAS_FT_FONT_TRUE@am__append_133 = $(cairo_ft_cxx_sources) -@CAIRO_HAS_FT_FONT_TRUE@am__append_134 = $(cairo_ft_sources) -@CAIRO_HAS_FT_FONT_TRUE@am__append_135 = cairo-ft.pc -@CAIRO_HAS_FC_FONT_TRUE@am__append_136 = $(cairo_fc_headers) -@CAIRO_HAS_FC_FONT_TRUE@am__append_137 = $(cairo_fc_private) -@CAIRO_HAS_FC_FONT_TRUE@am__append_138 = $(cairo_fc_cxx_sources) -@CAIRO_HAS_FC_FONT_TRUE@am__append_139 = $(cairo_fc_sources) -@CAIRO_HAS_FC_FONT_TRUE@am__append_140 = cairo-fc.pc -@CAIRO_HAS_PS_SURFACE_TRUE@am__append_141 = $(cairo_ps_headers) -@CAIRO_HAS_PS_SURFACE_TRUE@am__append_142 = $(cairo_ps_private) -@CAIRO_HAS_PS_SURFACE_TRUE@am__append_143 = $(cairo_ps_cxx_sources) -@CAIRO_HAS_PS_SURFACE_TRUE@am__append_144 = $(cairo_ps_sources) -@CAIRO_HAS_PS_SURFACE_TRUE@am__append_145 = cairo-ps.pc -@CAIRO_HAS_PDF_SURFACE_TRUE@am__append_146 = $(cairo_pdf_headers) -@CAIRO_HAS_PDF_SURFACE_TRUE@am__append_147 = $(cairo_pdf_private) -@CAIRO_HAS_PDF_SURFACE_TRUE@am__append_148 = $(cairo_pdf_cxx_sources) -@CAIRO_HAS_PDF_SURFACE_TRUE@am__append_149 = $(cairo_pdf_sources) -@CAIRO_HAS_PDF_SURFACE_TRUE@am__append_150 = cairo-pdf.pc -@CAIRO_HAS_SVG_SURFACE_TRUE@am__append_151 = $(cairo_svg_headers) -@CAIRO_HAS_SVG_SURFACE_TRUE@am__append_152 = $(cairo_svg_private) -@CAIRO_HAS_SVG_SURFACE_TRUE@am__append_153 = $(cairo_svg_cxx_sources) -@CAIRO_HAS_SVG_SURFACE_TRUE@am__append_154 = $(cairo_svg_sources) -@CAIRO_HAS_SVG_SURFACE_TRUE@am__append_155 = cairo-svg.pc -@CAIRO_HAS_TEST_SURFACES_TRUE@am__append_156 = $(cairo_test_surfaces_private) $(cairo_test_surfaces_headers) -@CAIRO_HAS_TEST_SURFACES_TRUE@am__append_157 = $(cairo_test_surfaces_cxx_sources) -@CAIRO_HAS_TEST_SURFACES_TRUE@am__append_158 = $(cairo_test_surfaces_sources) -@CAIRO_HAS_TEE_SURFACE_TRUE@am__append_159 = $(cairo_tee_headers) -@CAIRO_HAS_TEE_SURFACE_TRUE@am__append_160 = $(cairo_tee_private) -@CAIRO_HAS_TEE_SURFACE_TRUE@am__append_161 = $(cairo_tee_cxx_sources) -@CAIRO_HAS_TEE_SURFACE_TRUE@am__append_162 = $(cairo_tee_sources) -@CAIRO_HAS_TEE_SURFACE_TRUE@am__append_163 = cairo-tee.pc -@CAIRO_HAS_XML_SURFACE_TRUE@am__append_164 = $(cairo_xml_headers) -@CAIRO_HAS_XML_SURFACE_TRUE@am__append_165 = $(cairo_xml_private) -@CAIRO_HAS_XML_SURFACE_TRUE@am__append_166 = $(cairo_xml_cxx_sources) -@CAIRO_HAS_XML_SURFACE_TRUE@am__append_167 = $(cairo_xml_sources) -@CAIRO_HAS_XML_SURFACE_TRUE@am__append_168 = cairo-xml.pc -@CAIRO_HAS_PTHREAD_TRUE@am__append_169 = $(cairo_pthread_private) $(cairo_pthread_headers) -@CAIRO_HAS_PTHREAD_TRUE@am__append_170 = $(cairo_pthread_cxx_sources) -@CAIRO_HAS_PTHREAD_TRUE@am__append_171 = $(cairo_pthread_sources) -@CAIRO_HAS_GOBJECT_FUNCTIONS_TRUE@am__append_172 = $(cairo_gobject_headers) -@CAIRO_HAS_GOBJECT_FUNCTIONS_TRUE@am__append_173 = $(cairo_gobject_private) -@CAIRO_HAS_GOBJECT_FUNCTIONS_TRUE@am__append_174 = $(cairo_gobject_cxx_sources) -@CAIRO_HAS_GOBJECT_FUNCTIONS_TRUE@am__append_175 = $(cairo_gobject_sources) -@CAIRO_HAS_GOBJECT_FUNCTIONS_TRUE@am__append_176 = cairo-gobject.pc -@CAIRO_HAS_TRACE_TRUE@am__append_177 = $(cairo_trace_private) $(cairo_trace_headers) -@CAIRO_HAS_TRACE_TRUE@am__append_178 = $(cairo_trace_cxx_sources) -@CAIRO_HAS_TRACE_TRUE@am__append_179 = $(cairo_trace_sources) -@CAIRO_HAS_INTERPRETER_TRUE@am__append_180 = $(cairo_interpreter_private) $(cairo_interpreter_headers) -@CAIRO_HAS_INTERPRETER_TRUE@am__append_181 = $(cairo_interpreter_cxx_sources) -@CAIRO_HAS_INTERPRETER_TRUE@am__append_182 = $(cairo_interpreter_sources) -@CAIRO_HAS_SYMBOL_LOOKUP_TRUE@am__append_183 = $(cairo_symbol_lookup_private) $(cairo_symbol_lookup_headers) -@CAIRO_HAS_SYMBOL_LOOKUP_TRUE@am__append_184 = $(cairo_symbol_lookup_cxx_sources) -@CAIRO_HAS_SYMBOL_LOOKUP_TRUE@am__append_185 = $(cairo_symbol_lookup_sources) -@CROSS_COMPILING_FALSE@am__append_186 = check-link$(EXEEXT) -subdir = src -ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 -am__aclocal_m4_deps = $(top_srcdir)/build/aclocal.cairo.m4 \ - $(top_srcdir)/build/aclocal.compare.m4 \ - $(top_srcdir)/build/aclocal.enable.m4 \ - $(top_srcdir)/build/aclocal.float.m4 \ - $(top_srcdir)/build/aclocal.gtk-doc.m4 \ - $(top_srcdir)/build/aclocal.makefile.m4 \ - $(top_srcdir)/build/aclocal.pkg.m4 \ - $(top_srcdir)/build/libtool.m4 \ - $(top_srcdir)/build/ltoptions.m4 \ - $(top_srcdir)/build/ltsugar.m4 \ - $(top_srcdir)/build/ltversion.m4 \ - $(top_srcdir)/build/lt~obsolete.m4 $(top_srcdir)/acinclude.m4 \ - $(top_srcdir)/src/cairo-version.h \ - $(top_srcdir)/build/configure.ac.version \ - $(top_srcdir)/build/configure.ac.tools \ - $(top_srcdir)/build/configure.ac.features \ - $(top_srcdir)/build/configure.ac.warnings \ - $(top_srcdir)/build/configure.ac.system \ - $(top_srcdir)/build/configure.ac.analysis \ - $(top_srcdir)/build/configure.ac.noversion \ - $(top_srcdir)/build/configure.ac.pthread \ - $(top_srcdir)/configure.ac -am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ - $(ACLOCAL_M4) -DIST_COMMON = $(srcdir)/Makefile.am $(am__cairoinclude_HEADERS_DIST) \ - $(am__DIST_COMMON) -mkinstalldirs = $(install_sh) -d -CONFIG_HEADER = $(top_builddir)/config.h -CONFIG_CLEAN_FILES = cairo.pc cairo-xlib.pc cairo-xlib-xrender.pc \ - cairo-xcb.pc cairo-xlib-xcb.pc cairo-xcb-shm.pc cairo-qt.pc \ - cairo-quartz.pc cairo-quartz-font.pc cairo-quartz-image.pc \ - cairo-win32.pc cairo-win32-font.pc cairo-os2.pc cairo-beos.pc \ - cairo-drm.pc cairo-gallium.pc cairo-png.pc cairo-gl.pc \ - cairo-glesv2.pc cairo-glesv3.pc cairo-cogl.pc \ - cairo-directfb.pc cairo-vg.pc cairo-egl.pc cairo-glx.pc \ - cairo-wgl.pc cairo-script.pc cairo-ft.pc cairo-fc.pc \ - cairo-ps.pc cairo-pdf.pc cairo-svg.pc cairo-tee.pc \ - cairo-xml.pc cairo-gobject.pc -CONFIG_CLEAN_VPATH_FILES = -am__vpath_adj_setup = srcdirstrip=`echo "$(srcdir)" | sed 's|.|.|g'`; -am__vpath_adj = case $$p in \ - $(srcdir)/*) f=`echo "$$p" | sed "s|^$$srcdirstrip/||"`;; \ - *) f=$$p;; \ - esac; -am__strip_dir = f=`echo $$p | sed -e 's|^.*/||'`; -am__install_max = 40 -am__nobase_strip_setup = \ - srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*|]/\\\\&/g'` -am__nobase_strip = \ - for p in $$list; do echo "$$p"; done | sed -e "s|$$srcdirstrip/||" -am__nobase_list = $(am__nobase_strip_setup); \ - for p in $$list; do echo "$$p $$p"; done | \ - sed "s| $$srcdirstrip/| |;"' / .*\//!s/ .*/ ./; s,\( .*\)/[^/]*$$,\1,' | \ - $(AWK) 'BEGIN { files["."] = "" } { files[$$2] = files[$$2] " " $$1; \ - if (++n[$$2] == $(am__install_max)) \ - { print $$2, files[$$2]; n[$$2] = 0; files[$$2] = "" } } \ - END { for (dir in files) print dir, files[dir] }' -am__base_list = \ - sed '$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;s/\n/ /g' | \ - sed '$$!N;$$!N;$$!N;$$!N;s/\n/ /g' -am__uninstall_files_from_dir = { \ - test -z "$$files" \ - || { test ! -d "$$dir" && test ! -f "$$dir" && test ! -r "$$dir"; } \ - || { echo " ( cd '$$dir' && rm -f" $$files ")"; \ - $(am__cd) "$$dir" && rm -f $$files; }; \ - } -am__installdirs = "$(DESTDIR)$(libdir)" "$(DESTDIR)$(pkgconfigdir)" \ - "$(DESTDIR)$(cairoincludedir)" "$(DESTDIR)$(cairoincludedir)" -LTLIBRARIES = $(lib_LTLIBRARIES) $(noinst_LTLIBRARIES) -am__DEPENDENCIES_1 = -@BUILD_CXX_TRUE@am__DEPENDENCIES_2 = libcairo_cxx.la -am__libcairo_la_SOURCES_DIST = cairo.h cairo-version.h \ - cairo-deprecated.h cairo-xlib.h cairo-xlib-xrender.h \ - cairo-xcb.h cairo-qt.h cairo-quartz.h cairo-quartz-image.h \ - cairo-win32.h cairo-os2.h cairo-beos.h cairo-drm.h cairo-gl.h \ - cairo-cogl.h cairo-directfb.h cairo-vg.h cairo-script.h \ - cairo-ft.h cairo-ps.h cairo-pdf.h cairo-svg.h cairo-tee.h \ - cairo-xml.h cairoint.h cairo-analysis-surface-private.h \ - cairo-arc-private.h cairo-array-private.h \ - cairo-atomic-private.h cairo-backend-private.h \ - cairo-box-inline.h cairo-boxes-private.h cairo-cache-private.h \ - cairo-clip-inline.h cairo-clip-private.h \ - cairo-combsort-inline.h cairo-compiler-private.h \ - cairo-composite-rectangles-private.h \ - cairo-compositor-private.h cairo-contour-inline.h \ - cairo-contour-private.h cairo-damage-private.h \ - cairo-default-context-private.h cairo-device-private.h \ - cairo-error-inline.h cairo-error-private.h \ - cairo-fixed-private.h cairo-fixed-type-private.h \ - cairo-fontconfig-private.h cairo-freed-pool-private.h \ - cairo-freelist-private.h cairo-freelist-type-private.h \ - cairo-gstate-private.h cairo-hash-private.h \ - cairo-image-info-private.h cairo-image-surface-inline.h \ - cairo-image-surface-private.h cairo-line-inline.h \ - cairo-line-private.h cairo-list-inline.h cairo-list-private.h \ - cairo-malloc-private.h cairo-mempool-private.h \ - cairo-mutex-impl-private.h cairo-mutex-list-private.h \ - cairo-mutex-private.h cairo-mutex-type-private.h \ - cairo-output-stream-private.h cairo-paginated-private.h \ - cairo-paginated-surface-private.h cairo-path-fixed-private.h \ - cairo-path-private.h cairo-pattern-inline.h \ - cairo-pattern-private.h cairo-pixman-private.h cairo-private.h \ - cairo-recording-surface-inline.h \ - cairo-recording-surface-private.h \ - cairo-reference-count-private.h cairo-region-private.h \ - cairo-rtree-private.h cairo-scaled-font-private.h \ - cairo-slope-private.h cairo-spans-compositor-private.h \ - cairo-spans-private.h cairo-stroke-dash-private.h \ - cairo-surface-backend-private.h \ - cairo-surface-clipper-private.h \ - cairo-surface-fallback-private.h cairo-surface-inline.h \ - cairo-surface-observer-inline.h \ - cairo-surface-observer-private.h \ - cairo-surface-offset-private.h cairo-surface-private.h \ - cairo-surface-snapshot-inline.h \ - cairo-surface-snapshot-private.h \ - cairo-surface-subsurface-inline.h \ - cairo-surface-subsurface-private.h \ - cairo-surface-wrapper-private.h cairo-time-private.h \ - cairo-traps-private.h cairo-tristrip-private.h \ - cairo-types-private.h cairo-user-font-private.h \ - cairo-wideint-private.h cairo-wideint-type-private.h \ - cairo-scaled-font-subsets-private.h \ - cairo-truetype-subset-private.h cairo-type1-private.h \ - cairo-type3-glyph-surface-private.h \ - cairo-pdf-operators-private.h cairo-pdf-shading-private.h \ - cairo-tag-attributes-private.h cairo-xlib-private.h \ - cairo-xlib-surface-private.h cairo-xlib-xrender-private.h \ - cairo-xcb-private.h cairo-quartz-private.h \ - win32/cairo-win32-private.h cairo-os2-private.h \ - drm/cairo-drm-private.h drm/cairo-drm-intel-private.h \ - drm/cairo-drm-intel-brw-defines.h \ - drm/cairo-drm-intel-brw-structs.h drm/cairo-drm-intel-brw-eu.h \ - drm/cairo-drm-intel-command-private.h \ - drm/cairo-drm-intel-ioctl-private.h \ - drm/cairo-drm-i915-private.h drm/cairo-drm-i965-private.h \ - drm/cairo-drm-radeon-private.h cairo-gl-private.h \ - cairo-gl-dispatch-private.h cairo-gl-ext-def-private.h \ - cairo-gl-gradient-private.h cairo-cogl-private.h \ - cairo-cogl-gradient-private.h cairo-script-private.h \ - cairo-ft-private.h cairo-ps-surface-private.h \ - cairo-pdf-surface-private.h cairo-tag-stack-private.h \ - cairo-svg-surface-private.h test-compositor-surface.h \ - test-compositor-surface-private.h \ - test-null-compositor-surface.h test-paginated-surface.h \ - cairo-tee-surface-private.h cairo-analysis-surface.c \ - cairo-arc.c cairo-array.c cairo-atomic.c cairo-base64-stream.c \ - cairo-base85-stream.c cairo-bentley-ottmann-rectangular.c \ - cairo-bentley-ottmann-rectilinear.c cairo-bentley-ottmann.c \ - cairo-botor-scan-converter.c cairo-boxes-intersect.c \ - cairo-boxes.c cairo-cache.c cairo-clip-boxes.c \ - cairo-clip-polygon.c cairo-clip-region.c cairo-clip-surface.c \ - cairo-clip-tor-scan-converter.c cairo-clip.c cairo-color.c \ - cairo-composite-rectangles.c cairo-compositor.c \ - cairo-contour.c cairo-damage.c cairo-debug.c \ - cairo-default-context.c cairo-device.c cairo-error.c \ - cairo-fallback-compositor.c cairo-fixed.c \ - cairo-font-face-twin-data.c cairo-font-face-twin.c \ - cairo-font-face.c cairo-font-options.c cairo-freed-pool.c \ - cairo-freelist.c cairo-gstate.c cairo-hash.c cairo-hull.c \ - cairo-image-compositor.c cairo-image-info.c \ - cairo-image-source.c cairo-image-surface.c cairo-line.c \ - cairo-lzw.c cairo-mask-compositor.c cairo-matrix.c \ - cairo-mempool.c cairo-mesh-pattern-rasterizer.c cairo-misc.c \ - cairo-mono-scan-converter.c cairo-mutex.c \ - cairo-no-compositor.c cairo-observer.c cairo-output-stream.c \ - cairo-paginated-surface.c cairo-path-bounds.c \ - cairo-path-fill.c cairo-path-fixed.c cairo-path-in-fill.c \ - cairo-path-stroke-boxes.c cairo-path-stroke-polygon.c \ - cairo-path-stroke-traps.c cairo-path-stroke-tristrip.c \ - cairo-path-stroke.c cairo-path.c cairo-pattern.c cairo-pen.c \ - cairo-polygon-intersect.c cairo-polygon-reduce.c \ - cairo-polygon.c cairo-raster-source-pattern.c \ - cairo-recording-surface.c cairo-rectangle.c \ - cairo-rectangular-scan-converter.c cairo-region.c \ - cairo-rtree.c cairo-scaled-font.c \ - cairo-shape-mask-compositor.c cairo-slope.c \ - cairo-spans-compositor.c cairo-spans.c cairo-spline.c \ - cairo-stroke-dash.c cairo-stroke-style.c \ - cairo-surface-clipper.c cairo-surface-fallback.c \ - cairo-surface-observer.c cairo-surface-offset.c \ - cairo-surface-snapshot.c cairo-surface-subsurface.c \ - cairo-surface-wrapper.c cairo-surface.c cairo-time.c \ - cairo-tor-scan-converter.c cairo-tor22-scan-converter.c \ - cairo-toy-font-face.c cairo-traps-compositor.c cairo-traps.c \ - cairo-tristrip.c cairo-unicode.c cairo-user-font.c \ - cairo-version.c cairo-wideint.c cairo.c cairo-cff-subset.c \ - cairo-scaled-font-subsets.c cairo-truetype-subset.c \ - cairo-type1-fallback.c cairo-type1-glyph-names.c \ - cairo-type1-subset.c cairo-type3-glyph-surface.c \ - cairo-pdf-operators.c cairo-pdf-shading.c \ - cairo-tag-attributes.c cairo-deflate-stream.c \ - cairo-xlib-display.c cairo-xlib-core-compositor.c \ - cairo-xlib-fallback-compositor.c \ - cairo-xlib-render-compositor.c cairo-xlib-screen.c \ - cairo-xlib-source.c cairo-xlib-surface.c \ - cairo-xlib-surface-shm.c cairo-xlib-visual.c \ - cairo-xlib-xcb-surface.c cairo-xcb-connection.c \ - cairo-xcb-connection-core.c cairo-xcb-connection-render.c \ - cairo-xcb-connection-shm.c cairo-xcb-screen.c cairo-xcb-shm.c \ - cairo-xcb-surface.c cairo-xcb-surface-core.c \ - cairo-xcb-surface-render.c cairo-xcb-resources.c \ - cairo-quartz-surface.c cairo-quartz-font.c \ - cairo-quartz-image-surface.c win32/cairo-win32-debug.c \ - win32/cairo-win32-device.c win32/cairo-win32-gdi-compositor.c \ - win32/cairo-win32-system.c win32/cairo-win32-surface.c \ - win32/cairo-win32-display-surface.c \ - win32/cairo-win32-printing-surface.c win32/cairo-win32-font.c \ - cairo-os2-surface.c drm/cairo-drm.c drm/cairo-drm-bo.c \ - drm/cairo-drm-surface.c drm/cairo-drm-intel.c \ - drm/cairo-drm-intel-debug.c drm/cairo-drm-intel-surface.c \ - drm/cairo-drm-i915-surface.c drm/cairo-drm-i915-glyphs.c \ - drm/cairo-drm-i915-shader.c drm/cairo-drm-i915-spans.c \ - drm/cairo-drm-i965-surface.c drm/cairo-drm-i965-glyphs.c \ - drm/cairo-drm-i965-shader.c drm/cairo-drm-i965-spans.c \ - drm/cairo-drm-intel-brw-eu.c drm/cairo-drm-intel-brw-eu-emit.c \ - drm/cairo-drm-intel-brw-eu-util.c drm/cairo-drm-radeon.c \ - drm/cairo-drm-radeon-surface.c drm/cairo-drm-gallium-surface.c \ - cairo-png.c cairo-gl-composite.c cairo-gl-device.c \ - cairo-gl-dispatch.c cairo-gl-glyphs.c cairo-gl-gradient.c \ - cairo-gl-info.c cairo-gl-msaa-compositor.c cairo-gl-operand.c \ - cairo-gl-shaders.c cairo-gl-source.c \ - cairo-gl-spans-compositor.c cairo-gl-surface.c \ - cairo-gl-traps-compositor.c cairo-cogl-surface.c \ - cairo-cogl-gradient.c cairo-directfb-surface.c \ - cairo-vg-surface.c cairo-egl-context.c cairo-glx-context.c \ - cairo-wgl-context.c cairo-script-surface.c cairo-ft-font.c \ - cairo-ps-surface.c cairo-pdf-surface.c cairo-pdf-interchange.c \ - cairo-tag-stack.c cairo-svg-surface.c \ - test-compositor-surface.c test-null-compositor-surface.c \ - test-base-compositor-surface.c test-paginated-surface.c \ - cairo-tee-surface.c cairo-xml-surface.c -am__objects_1 = -@CAIRO_HAS_XLIB_SURFACE_TRUE@am__objects_2 = $(am__objects_1) -@CAIRO_HAS_XLIB_XRENDER_SURFACE_TRUE@am__objects_3 = $(am__objects_1) -@CAIRO_HAS_XCB_SURFACE_TRUE@am__objects_4 = $(am__objects_1) -@CAIRO_HAS_QT_SURFACE_TRUE@am__objects_5 = $(am__objects_1) -@CAIRO_HAS_QUARTZ_SURFACE_TRUE@am__objects_6 = $(am__objects_1) -@CAIRO_HAS_QUARTZ_IMAGE_SURFACE_TRUE@am__objects_7 = $(am__objects_1) -@CAIRO_HAS_WIN32_SURFACE_TRUE@am__objects_8 = $(am__objects_1) -@CAIRO_HAS_OS2_SURFACE_TRUE@am__objects_9 = $(am__objects_1) -@CAIRO_HAS_BEOS_SURFACE_TRUE@am__objects_10 = $(am__objects_1) -@CAIRO_HAS_DRM_SURFACE_TRUE@am__objects_11 = $(am__objects_1) -@CAIRO_HAS_GL_SURFACE_TRUE@am__objects_12 = $(am__objects_1) -am__objects_13 = $(am__objects_1) -@CAIRO_HAS_GLESV2_SURFACE_TRUE@am__objects_14 = $(am__objects_13) -@CAIRO_HAS_GLESV3_SURFACE_TRUE@am__objects_15 = $(am__objects_13) -@CAIRO_HAS_COGL_SURFACE_TRUE@am__objects_16 = $(am__objects_1) -@CAIRO_HAS_DIRECTFB_SURFACE_TRUE@am__objects_17 = $(am__objects_1) -@CAIRO_HAS_VG_SURFACE_TRUE@am__objects_18 = $(am__objects_1) -@CAIRO_HAS_SCRIPT_SURFACE_TRUE@am__objects_19 = $(am__objects_1) -@CAIRO_HAS_FT_FONT_TRUE@am__objects_20 = $(am__objects_1) -@CAIRO_HAS_PS_SURFACE_TRUE@am__objects_21 = $(am__objects_1) -@CAIRO_HAS_PDF_SURFACE_TRUE@am__objects_22 = $(am__objects_1) -@CAIRO_HAS_SVG_SURFACE_TRUE@am__objects_23 = $(am__objects_1) -@CAIRO_HAS_TEE_SURFACE_TRUE@am__objects_24 = $(am__objects_1) -@CAIRO_HAS_XML_SURFACE_TRUE@am__objects_25 = $(am__objects_1) -am__objects_26 = $(am__objects_1) $(am__objects_2) $(am__objects_3) \ - $(am__objects_4) $(am__objects_1) $(am__objects_1) \ - $(am__objects_5) $(am__objects_6) $(am__objects_1) \ - $(am__objects_7) $(am__objects_8) $(am__objects_1) \ - $(am__objects_9) $(am__objects_10) $(am__objects_11) \ - $(am__objects_1) $(am__objects_1) $(am__objects_12) \ - $(am__objects_14) $(am__objects_15) $(am__objects_16) \ - $(am__objects_17) $(am__objects_18) $(am__objects_1) \ - $(am__objects_1) $(am__objects_1) $(am__objects_19) \ - $(am__objects_20) $(am__objects_1) $(am__objects_21) \ - $(am__objects_22) $(am__objects_23) $(am__objects_24) \ - $(am__objects_25) $(am__objects_1) -am__objects_27 = $(am__objects_1) $(am__objects_1) -@CAIRO_HAS_TEST_SURFACES_TRUE@am__objects_28 = $(am__objects_1) -am__objects_29 = $(am__objects_27) $(am__objects_2) $(am__objects_1) \ - $(am__objects_4) $(am__objects_1) $(am__objects_1) \ - $(am__objects_1) $(am__objects_6) $(am__objects_1) \ - $(am__objects_1) $(am__objects_8) $(am__objects_1) \ - $(am__objects_9) $(am__objects_1) $(am__objects_11) \ - $(am__objects_1) $(am__objects_1) $(am__objects_12) \ - $(am__objects_14) $(am__objects_15) $(am__objects_16) \ - $(am__objects_1) $(am__objects_1) $(am__objects_1) \ - $(am__objects_1) $(am__objects_1) $(am__objects_19) \ - $(am__objects_20) $(am__objects_1) $(am__objects_21) \ - $(am__objects_22) $(am__objects_23) $(am__objects_28) \ - $(am__objects_24) $(am__objects_1) $(am__objects_1) \ - $(am__objects_1) $(am__objects_1) $(am__objects_1) \ - $(am__objects_1) -am__objects_30 = cairo-cff-subset.lo cairo-scaled-font-subsets.lo \ - cairo-truetype-subset.lo cairo-type1-fallback.lo \ - cairo-type1-glyph-names.lo cairo-type1-subset.lo \ - cairo-type3-glyph-surface.lo -am__objects_31 = cairo-pdf-operators.lo cairo-pdf-shading.lo \ - cairo-tag-attributes.lo -am__objects_32 = cairo-deflate-stream.lo -am__objects_33 = cairo-analysis-surface.lo cairo-arc.lo cairo-array.lo \ - cairo-atomic.lo cairo-base64-stream.lo cairo-base85-stream.lo \ - cairo-bentley-ottmann-rectangular.lo \ - cairo-bentley-ottmann-rectilinear.lo cairo-bentley-ottmann.lo \ - cairo-botor-scan-converter.lo cairo-boxes-intersect.lo \ - cairo-boxes.lo cairo-cache.lo cairo-clip-boxes.lo \ - cairo-clip-polygon.lo cairo-clip-region.lo \ - cairo-clip-surface.lo cairo-clip-tor-scan-converter.lo \ - cairo-clip.lo cairo-color.lo cairo-composite-rectangles.lo \ - cairo-compositor.lo cairo-contour.lo cairo-damage.lo \ - cairo-debug.lo cairo-default-context.lo cairo-device.lo \ - cairo-error.lo cairo-fallback-compositor.lo cairo-fixed.lo \ - cairo-font-face-twin-data.lo cairo-font-face-twin.lo \ - cairo-font-face.lo cairo-font-options.lo cairo-freed-pool.lo \ - cairo-freelist.lo cairo-gstate.lo cairo-hash.lo cairo-hull.lo \ - cairo-image-compositor.lo cairo-image-info.lo \ - cairo-image-source.lo cairo-image-surface.lo cairo-line.lo \ - cairo-lzw.lo cairo-mask-compositor.lo cairo-matrix.lo \ - cairo-mempool.lo cairo-mesh-pattern-rasterizer.lo \ - cairo-misc.lo cairo-mono-scan-converter.lo cairo-mutex.lo \ - cairo-no-compositor.lo cairo-observer.lo \ - cairo-output-stream.lo cairo-paginated-surface.lo \ - cairo-path-bounds.lo cairo-path-fill.lo cairo-path-fixed.lo \ - cairo-path-in-fill.lo cairo-path-stroke-boxes.lo \ - cairo-path-stroke-polygon.lo cairo-path-stroke-traps.lo \ - cairo-path-stroke-tristrip.lo cairo-path-stroke.lo \ - cairo-path.lo cairo-pattern.lo cairo-pen.lo \ - cairo-polygon-intersect.lo cairo-polygon-reduce.lo \ - cairo-polygon.lo cairo-raster-source-pattern.lo \ - cairo-recording-surface.lo cairo-rectangle.lo \ - cairo-rectangular-scan-converter.lo cairo-region.lo \ - cairo-rtree.lo cairo-scaled-font.lo \ - cairo-shape-mask-compositor.lo cairo-slope.lo \ - cairo-spans-compositor.lo cairo-spans.lo cairo-spline.lo \ - cairo-stroke-dash.lo cairo-stroke-style.lo \ - cairo-surface-clipper.lo cairo-surface-fallback.lo \ - cairo-surface-observer.lo cairo-surface-offset.lo \ - cairo-surface-snapshot.lo cairo-surface-subsurface.lo \ - cairo-surface-wrapper.lo cairo-surface.lo cairo-time.lo \ - cairo-tor-scan-converter.lo cairo-tor22-scan-converter.lo \ - cairo-toy-font-face.lo cairo-traps-compositor.lo \ - cairo-traps.lo cairo-tristrip.lo cairo-unicode.lo \ - cairo-user-font.lo cairo-version.lo cairo-wideint.lo cairo.lo \ - $(am__objects_30) $(am__objects_31) $(am__objects_32) -am__objects_34 = cairo-xlib-display.lo cairo-xlib-core-compositor.lo \ - cairo-xlib-fallback-compositor.lo \ - cairo-xlib-render-compositor.lo cairo-xlib-screen.lo \ - cairo-xlib-source.lo cairo-xlib-surface.lo \ - cairo-xlib-surface-shm.lo cairo-xlib-visual.lo \ - cairo-xlib-xcb-surface.lo -@CAIRO_HAS_XLIB_SURFACE_TRUE@am__objects_35 = $(am__objects_34) -am__objects_36 = cairo-xcb-connection.lo cairo-xcb-connection-core.lo \ - cairo-xcb-connection-render.lo cairo-xcb-connection-shm.lo \ - cairo-xcb-screen.lo cairo-xcb-shm.lo cairo-xcb-surface.lo \ - cairo-xcb-surface-core.lo cairo-xcb-surface-render.lo \ - cairo-xcb-resources.lo -@CAIRO_HAS_XCB_SURFACE_TRUE@am__objects_37 = $(am__objects_36) -am__objects_38 = cairo-quartz-surface.lo -@CAIRO_HAS_QUARTZ_SURFACE_TRUE@am__objects_39 = $(am__objects_38) -am__objects_40 = cairo-quartz-font.lo -@CAIRO_HAS_QUARTZ_FONT_TRUE@am__objects_41 = $(am__objects_40) -am__objects_42 = cairo-quartz-image-surface.lo -@CAIRO_HAS_QUARTZ_IMAGE_SURFACE_TRUE@am__objects_43 = \ -@CAIRO_HAS_QUARTZ_IMAGE_SURFACE_TRUE@ $(am__objects_42) -am__objects_44 = cairo-win32-debug.lo cairo-win32-device.lo \ - cairo-win32-gdi-compositor.lo cairo-win32-system.lo \ - cairo-win32-surface.lo cairo-win32-display-surface.lo \ - cairo-win32-printing-surface.lo -@CAIRO_HAS_WIN32_SURFACE_TRUE@am__objects_45 = $(am__objects_44) -am__objects_46 = cairo-win32-font.lo -@CAIRO_HAS_WIN32_FONT_TRUE@am__objects_47 = $(am__objects_46) -am__objects_48 = cairo-os2-surface.lo -@CAIRO_HAS_OS2_SURFACE_TRUE@am__objects_49 = $(am__objects_48) -am__objects_50 = cairo-drm.lo cairo-drm-bo.lo cairo-drm-surface.lo \ - cairo-drm-intel.lo cairo-drm-intel-debug.lo \ - cairo-drm-intel-surface.lo cairo-drm-i915-surface.lo \ - cairo-drm-i915-glyphs.lo cairo-drm-i915-shader.lo \ - cairo-drm-i915-spans.lo cairo-drm-i965-surface.lo \ - cairo-drm-i965-glyphs.lo cairo-drm-i965-shader.lo \ - cairo-drm-i965-spans.lo cairo-drm-intel-brw-eu.lo \ - cairo-drm-intel-brw-eu-emit.lo cairo-drm-intel-brw-eu-util.lo \ - cairo-drm-radeon.lo cairo-drm-radeon-surface.lo -@CAIRO_HAS_DRM_SURFACE_TRUE@am__objects_51 = $(am__objects_50) -am__objects_52 = cairo-drm-gallium-surface.lo -@CAIRO_HAS_GALLIUM_SURFACE_TRUE@am__objects_53 = $(am__objects_52) -am__objects_54 = cairo-png.lo -@CAIRO_HAS_PNG_FUNCTIONS_TRUE@am__objects_55 = $(am__objects_54) -am__objects_56 = cairo-gl-composite.lo cairo-gl-device.lo \ - cairo-gl-dispatch.lo cairo-gl-glyphs.lo cairo-gl-gradient.lo \ - cairo-gl-info.lo cairo-gl-msaa-compositor.lo \ - cairo-gl-operand.lo cairo-gl-shaders.lo cairo-gl-source.lo \ - cairo-gl-spans-compositor.lo cairo-gl-surface.lo \ - cairo-gl-traps-compositor.lo -@CAIRO_HAS_GL_SURFACE_TRUE@am__objects_57 = $(am__objects_56) -am__objects_58 = $(am__objects_56) -@CAIRO_HAS_GLESV2_SURFACE_TRUE@am__objects_59 = $(am__objects_58) -@CAIRO_HAS_GLESV3_SURFACE_TRUE@am__objects_60 = $(am__objects_58) -am__objects_61 = cairo-cogl-surface.lo cairo-cogl-gradient.lo -@CAIRO_HAS_COGL_SURFACE_TRUE@am__objects_62 = $(am__objects_61) -am__objects_63 = cairo-directfb-surface.lo -@CAIRO_HAS_DIRECTFB_SURFACE_TRUE@am__objects_64 = $(am__objects_63) -am__objects_65 = cairo-vg-surface.lo -@CAIRO_HAS_VG_SURFACE_TRUE@am__objects_66 = $(am__objects_65) -am__objects_67 = cairo-egl-context.lo -@CAIRO_HAS_EGL_FUNCTIONS_TRUE@am__objects_68 = $(am__objects_67) -am__objects_69 = cairo-glx-context.lo -@CAIRO_HAS_GLX_FUNCTIONS_TRUE@am__objects_70 = $(am__objects_69) -am__objects_71 = cairo-wgl-context.lo -@CAIRO_HAS_WGL_FUNCTIONS_TRUE@am__objects_72 = $(am__objects_71) -am__objects_73 = cairo-script-surface.lo -@CAIRO_HAS_SCRIPT_SURFACE_TRUE@am__objects_74 = $(am__objects_73) -am__objects_75 = cairo-ft-font.lo -@CAIRO_HAS_FT_FONT_TRUE@am__objects_76 = $(am__objects_75) -am__objects_77 = cairo-ps-surface.lo -@CAIRO_HAS_PS_SURFACE_TRUE@am__objects_78 = $(am__objects_77) -am__objects_79 = cairo-pdf-surface.lo cairo-pdf-interchange.lo \ - cairo-tag-stack.lo -@CAIRO_HAS_PDF_SURFACE_TRUE@am__objects_80 = $(am__objects_79) -am__objects_81 = cairo-svg-surface.lo -@CAIRO_HAS_SVG_SURFACE_TRUE@am__objects_82 = $(am__objects_81) -am__objects_83 = test-compositor-surface.lo \ - test-null-compositor-surface.lo \ - test-base-compositor-surface.lo test-paginated-surface.lo -@CAIRO_HAS_TEST_SURFACES_TRUE@am__objects_84 = $(am__objects_83) -am__objects_85 = cairo-tee-surface.lo -@CAIRO_HAS_TEE_SURFACE_TRUE@am__objects_86 = $(am__objects_85) -am__objects_87 = cairo-xml-surface.lo -@CAIRO_HAS_XML_SURFACE_TRUE@am__objects_88 = $(am__objects_87) -am__objects_89 = $(am__objects_33) $(am__objects_35) $(am__objects_1) \ - $(am__objects_37) $(am__objects_1) $(am__objects_1) \ - $(am__objects_1) $(am__objects_39) $(am__objects_41) \ - $(am__objects_43) $(am__objects_45) $(am__objects_47) \ - $(am__objects_49) $(am__objects_1) $(am__objects_51) \ - $(am__objects_53) $(am__objects_55) $(am__objects_57) \ - $(am__objects_59) $(am__objects_60) $(am__objects_62) \ - $(am__objects_64) $(am__objects_66) $(am__objects_68) \ - $(am__objects_70) $(am__objects_72) $(am__objects_74) \ - $(am__objects_76) $(am__objects_1) $(am__objects_78) \ - $(am__objects_80) $(am__objects_82) $(am__objects_84) \ - $(am__objects_86) $(am__objects_88) $(am__objects_1) \ - $(am__objects_1) $(am__objects_1) $(am__objects_1) \ - $(am__objects_1) -am_libcairo_la_OBJECTS = $(am__objects_26) $(am__objects_29) \ - $(am__objects_89) -nodist_libcairo_la_OBJECTS = -libcairo_la_OBJECTS = $(am_libcairo_la_OBJECTS) \ - $(nodist_libcairo_la_OBJECTS) -AM_V_lt = $(am__v_lt_@AM_V@) -am__v_lt_ = $(am__v_lt_@AM_DEFAULT_V@) -am__v_lt_0 = --silent -am__v_lt_1 = -libcairo_la_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \ - $(LIBTOOLFLAGS) --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) \ - $(libcairo_la_LDFLAGS) $(LDFLAGS) -o $@ -am__libcairo_cxx_la_SOURCES_DIST = cairo.h cairo-version.h \ - cairo-deprecated.h cairo-xlib.h cairo-xlib-xrender.h \ - cairo-xcb.h cairo-qt.h cairo-quartz.h cairo-quartz-image.h \ - cairo-win32.h cairo-os2.h cairo-beos.h cairo-drm.h cairo-gl.h \ - cairo-cogl.h cairo-directfb.h cairo-vg.h cairo-script.h \ - cairo-ft.h cairo-ps.h cairo-pdf.h cairo-svg.h cairo-tee.h \ - cairo-xml.h cairoint.h cairo-analysis-surface-private.h \ - cairo-arc-private.h cairo-array-private.h \ - cairo-atomic-private.h cairo-backend-private.h \ - cairo-box-inline.h cairo-boxes-private.h cairo-cache-private.h \ - cairo-clip-inline.h cairo-clip-private.h \ - cairo-combsort-inline.h cairo-compiler-private.h \ - cairo-composite-rectangles-private.h \ - cairo-compositor-private.h cairo-contour-inline.h \ - cairo-contour-private.h cairo-damage-private.h \ - cairo-default-context-private.h cairo-device-private.h \ - cairo-error-inline.h cairo-error-private.h \ - cairo-fixed-private.h cairo-fixed-type-private.h \ - cairo-fontconfig-private.h cairo-freed-pool-private.h \ - cairo-freelist-private.h cairo-freelist-type-private.h \ - cairo-gstate-private.h cairo-hash-private.h \ - cairo-image-info-private.h cairo-image-surface-inline.h \ - cairo-image-surface-private.h cairo-line-inline.h \ - cairo-line-private.h cairo-list-inline.h cairo-list-private.h \ - cairo-malloc-private.h cairo-mempool-private.h \ - cairo-mutex-impl-private.h cairo-mutex-list-private.h \ - cairo-mutex-private.h cairo-mutex-type-private.h \ - cairo-output-stream-private.h cairo-paginated-private.h \ - cairo-paginated-surface-private.h cairo-path-fixed-private.h \ - cairo-path-private.h cairo-pattern-inline.h \ - cairo-pattern-private.h cairo-pixman-private.h cairo-private.h \ - cairo-recording-surface-inline.h \ - cairo-recording-surface-private.h \ - cairo-reference-count-private.h cairo-region-private.h \ - cairo-rtree-private.h cairo-scaled-font-private.h \ - cairo-slope-private.h cairo-spans-compositor-private.h \ - cairo-spans-private.h cairo-stroke-dash-private.h \ - cairo-surface-backend-private.h \ - cairo-surface-clipper-private.h \ - cairo-surface-fallback-private.h cairo-surface-inline.h \ - cairo-surface-observer-inline.h \ - cairo-surface-observer-private.h \ - cairo-surface-offset-private.h cairo-surface-private.h \ - cairo-surface-snapshot-inline.h \ - cairo-surface-snapshot-private.h \ - cairo-surface-subsurface-inline.h \ - cairo-surface-subsurface-private.h \ - cairo-surface-wrapper-private.h cairo-time-private.h \ - cairo-traps-private.h cairo-tristrip-private.h \ - cairo-types-private.h cairo-user-font-private.h \ - cairo-wideint-private.h cairo-wideint-type-private.h \ - cairo-scaled-font-subsets-private.h \ - cairo-truetype-subset-private.h cairo-type1-private.h \ - cairo-type3-glyph-surface-private.h \ - cairo-pdf-operators-private.h cairo-pdf-shading-private.h \ - cairo-tag-attributes-private.h cairo-xlib-private.h \ - cairo-xlib-surface-private.h cairo-xlib-xrender-private.h \ - cairo-xcb-private.h cairo-quartz-private.h \ - win32/cairo-win32-private.h cairo-os2-private.h \ - drm/cairo-drm-private.h drm/cairo-drm-intel-private.h \ - drm/cairo-drm-intel-brw-defines.h \ - drm/cairo-drm-intel-brw-structs.h drm/cairo-drm-intel-brw-eu.h \ - drm/cairo-drm-intel-command-private.h \ - drm/cairo-drm-intel-ioctl-private.h \ - drm/cairo-drm-i915-private.h drm/cairo-drm-i965-private.h \ - drm/cairo-drm-radeon-private.h cairo-gl-private.h \ - cairo-gl-dispatch-private.h cairo-gl-ext-def-private.h \ - cairo-gl-gradient-private.h cairo-cogl-private.h \ - cairo-cogl-gradient-private.h cairo-script-private.h \ - cairo-ft-private.h cairo-ps-surface-private.h \ - cairo-pdf-surface-private.h cairo-tag-stack-private.h \ - cairo-svg-surface-private.h test-compositor-surface.h \ - test-compositor-surface-private.h \ - test-null-compositor-surface.h test-paginated-surface.h \ - cairo-tee-surface-private.h cairo-qt-surface.cpp \ - cairo-beos-surface.cpp -am__objects_90 = cairo-qt-surface.lo -@CAIRO_HAS_QT_SURFACE_TRUE@am__objects_91 = $(am__objects_90) -am__objects_92 = cairo-beos-surface.lo -@CAIRO_HAS_BEOS_SURFACE_TRUE@am__objects_93 = $(am__objects_92) -am__objects_94 = $(am__objects_1) $(am__objects_1) $(am__objects_1) \ - $(am__objects_1) $(am__objects_1) $(am__objects_91) \ - $(am__objects_1) $(am__objects_1) $(am__objects_1) \ - $(am__objects_1) $(am__objects_1) $(am__objects_1) \ - $(am__objects_93) $(am__objects_1) $(am__objects_1) \ - $(am__objects_1) $(am__objects_1) $(am__objects_1) \ - $(am__objects_1) $(am__objects_1) $(am__objects_1) \ - $(am__objects_1) $(am__objects_1) $(am__objects_1) \ - $(am__objects_1) $(am__objects_1) $(am__objects_1) \ - $(am__objects_1) $(am__objects_1) $(am__objects_1) \ - $(am__objects_1) $(am__objects_1) $(am__objects_1) \ - $(am__objects_1) $(am__objects_1) $(am__objects_1) \ - $(am__objects_1) $(am__objects_1) $(am__objects_1) -am_libcairo_cxx_la_OBJECTS = $(am__objects_26) $(am__objects_29) \ - $(am__objects_94) -libcairo_cxx_la_OBJECTS = $(am_libcairo_cxx_la_OBJECTS) -libcairo_cxx_la_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CXX \ - $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=link $(CXXLD) \ - $(AM_CXXFLAGS) $(CXXFLAGS) $(libcairo_cxx_la_LDFLAGS) \ - $(LDFLAGS) -o $@ -@BUILD_CXX_TRUE@am_libcairo_cxx_la_rpath = -check_link_SOURCES = check-link.c -check_link_OBJECTS = check-link.$(OBJEXT) -check_link_DEPENDENCIES = libcairo.la -AM_V_P = $(am__v_P_@AM_V@) -am__v_P_ = $(am__v_P_@AM_DEFAULT_V@) -am__v_P_0 = false -am__v_P_1 = : -AM_V_GEN = $(am__v_GEN_@AM_V@) -am__v_GEN_ = $(am__v_GEN_@AM_DEFAULT_V@) -am__v_GEN_0 = @echo " GEN " $@; -am__v_GEN_1 = -AM_V_at = $(am__v_at_@AM_V@) -am__v_at_ = $(am__v_at_@AM_DEFAULT_V@) -am__v_at_0 = @ -am__v_at_1 = -DEFAULT_INCLUDES = -I.@am__isrc@ -I$(top_builddir) -depcomp = $(SHELL) $(top_srcdir)/build/depcomp -am__maybe_remake_depfiles = depfiles -am__depfiles_remade = ./$(DEPDIR)/cairo-analysis-surface.Plo \ - ./$(DEPDIR)/cairo-arc.Plo ./$(DEPDIR)/cairo-array.Plo \ - ./$(DEPDIR)/cairo-atomic.Plo \ - ./$(DEPDIR)/cairo-base64-stream.Plo \ - ./$(DEPDIR)/cairo-base85-stream.Plo \ - ./$(DEPDIR)/cairo-bentley-ottmann-rectangular.Plo \ - ./$(DEPDIR)/cairo-bentley-ottmann-rectilinear.Plo \ - ./$(DEPDIR)/cairo-bentley-ottmann.Plo \ - ./$(DEPDIR)/cairo-beos-surface.Plo \ - ./$(DEPDIR)/cairo-botor-scan-converter.Plo \ - ./$(DEPDIR)/cairo-boxes-intersect.Plo \ - ./$(DEPDIR)/cairo-boxes.Plo ./$(DEPDIR)/cairo-cache.Plo \ - ./$(DEPDIR)/cairo-cff-subset.Plo \ - ./$(DEPDIR)/cairo-clip-boxes.Plo \ - ./$(DEPDIR)/cairo-clip-polygon.Plo \ - ./$(DEPDIR)/cairo-clip-region.Plo \ - ./$(DEPDIR)/cairo-clip-surface.Plo \ - ./$(DEPDIR)/cairo-clip-tor-scan-converter.Plo \ - ./$(DEPDIR)/cairo-clip.Plo ./$(DEPDIR)/cairo-cogl-gradient.Plo \ - ./$(DEPDIR)/cairo-cogl-surface.Plo ./$(DEPDIR)/cairo-color.Plo \ - ./$(DEPDIR)/cairo-composite-rectangles.Plo \ - ./$(DEPDIR)/cairo-compositor.Plo ./$(DEPDIR)/cairo-contour.Plo \ - ./$(DEPDIR)/cairo-damage.Plo ./$(DEPDIR)/cairo-debug.Plo \ - ./$(DEPDIR)/cairo-default-context.Plo \ - ./$(DEPDIR)/cairo-deflate-stream.Plo \ - ./$(DEPDIR)/cairo-device.Plo \ - ./$(DEPDIR)/cairo-directfb-surface.Plo \ - ./$(DEPDIR)/cairo-drm-bo.Plo \ - ./$(DEPDIR)/cairo-drm-gallium-surface.Plo \ - ./$(DEPDIR)/cairo-drm-i915-glyphs.Plo \ - ./$(DEPDIR)/cairo-drm-i915-shader.Plo \ - ./$(DEPDIR)/cairo-drm-i915-spans.Plo \ - ./$(DEPDIR)/cairo-drm-i915-surface.Plo \ - ./$(DEPDIR)/cairo-drm-i965-glyphs.Plo \ - ./$(DEPDIR)/cairo-drm-i965-shader.Plo \ - ./$(DEPDIR)/cairo-drm-i965-spans.Plo \ - ./$(DEPDIR)/cairo-drm-i965-surface.Plo \ - ./$(DEPDIR)/cairo-drm-intel-brw-eu-emit.Plo \ - ./$(DEPDIR)/cairo-drm-intel-brw-eu-util.Plo \ - ./$(DEPDIR)/cairo-drm-intel-brw-eu.Plo \ - ./$(DEPDIR)/cairo-drm-intel-debug.Plo \ - ./$(DEPDIR)/cairo-drm-intel-surface.Plo \ - ./$(DEPDIR)/cairo-drm-intel.Plo \ - ./$(DEPDIR)/cairo-drm-radeon-surface.Plo \ - ./$(DEPDIR)/cairo-drm-radeon.Plo \ - ./$(DEPDIR)/cairo-drm-surface.Plo ./$(DEPDIR)/cairo-drm.Plo \ - ./$(DEPDIR)/cairo-egl-context.Plo ./$(DEPDIR)/cairo-error.Plo \ - ./$(DEPDIR)/cairo-fallback-compositor.Plo \ - ./$(DEPDIR)/cairo-fixed.Plo \ - ./$(DEPDIR)/cairo-font-face-twin-data.Plo \ - ./$(DEPDIR)/cairo-font-face-twin.Plo \ - ./$(DEPDIR)/cairo-font-face.Plo \ - ./$(DEPDIR)/cairo-font-options.Plo \ - ./$(DEPDIR)/cairo-freed-pool.Plo \ - ./$(DEPDIR)/cairo-freelist.Plo ./$(DEPDIR)/cairo-ft-font.Plo \ - ./$(DEPDIR)/cairo-gl-composite.Plo \ - ./$(DEPDIR)/cairo-gl-device.Plo \ - ./$(DEPDIR)/cairo-gl-dispatch.Plo \ - ./$(DEPDIR)/cairo-gl-glyphs.Plo \ - ./$(DEPDIR)/cairo-gl-gradient.Plo \ - ./$(DEPDIR)/cairo-gl-info.Plo \ - ./$(DEPDIR)/cairo-gl-msaa-compositor.Plo \ - ./$(DEPDIR)/cairo-gl-operand.Plo \ - ./$(DEPDIR)/cairo-gl-shaders.Plo \ - ./$(DEPDIR)/cairo-gl-source.Plo \ - ./$(DEPDIR)/cairo-gl-spans-compositor.Plo \ - ./$(DEPDIR)/cairo-gl-surface.Plo \ - ./$(DEPDIR)/cairo-gl-traps-compositor.Plo \ - ./$(DEPDIR)/cairo-glx-context.Plo ./$(DEPDIR)/cairo-gstate.Plo \ - ./$(DEPDIR)/cairo-hash.Plo ./$(DEPDIR)/cairo-hull.Plo \ - ./$(DEPDIR)/cairo-image-compositor.Plo \ - ./$(DEPDIR)/cairo-image-info.Plo \ - ./$(DEPDIR)/cairo-image-source.Plo \ - ./$(DEPDIR)/cairo-image-surface.Plo ./$(DEPDIR)/cairo-line.Plo \ - ./$(DEPDIR)/cairo-lzw.Plo \ - ./$(DEPDIR)/cairo-mask-compositor.Plo \ - ./$(DEPDIR)/cairo-matrix.Plo ./$(DEPDIR)/cairo-mempool.Plo \ - ./$(DEPDIR)/cairo-mesh-pattern-rasterizer.Plo \ - ./$(DEPDIR)/cairo-misc.Plo \ - ./$(DEPDIR)/cairo-mono-scan-converter.Plo \ - ./$(DEPDIR)/cairo-mutex.Plo \ - ./$(DEPDIR)/cairo-no-compositor.Plo \ - ./$(DEPDIR)/cairo-observer.Plo \ - ./$(DEPDIR)/cairo-os2-surface.Plo \ - ./$(DEPDIR)/cairo-output-stream.Plo \ - ./$(DEPDIR)/cairo-paginated-surface.Plo \ - ./$(DEPDIR)/cairo-path-bounds.Plo \ - ./$(DEPDIR)/cairo-path-fill.Plo \ - ./$(DEPDIR)/cairo-path-fixed.Plo \ - ./$(DEPDIR)/cairo-path-in-fill.Plo \ - ./$(DEPDIR)/cairo-path-stroke-boxes.Plo \ - ./$(DEPDIR)/cairo-path-stroke-polygon.Plo \ - ./$(DEPDIR)/cairo-path-stroke-traps.Plo \ - ./$(DEPDIR)/cairo-path-stroke-tristrip.Plo \ - ./$(DEPDIR)/cairo-path-stroke.Plo ./$(DEPDIR)/cairo-path.Plo \ - ./$(DEPDIR)/cairo-pattern.Plo \ - ./$(DEPDIR)/cairo-pdf-interchange.Plo \ - ./$(DEPDIR)/cairo-pdf-operators.Plo \ - ./$(DEPDIR)/cairo-pdf-shading.Plo \ - ./$(DEPDIR)/cairo-pdf-surface.Plo ./$(DEPDIR)/cairo-pen.Plo \ - ./$(DEPDIR)/cairo-png.Plo \ - ./$(DEPDIR)/cairo-polygon-intersect.Plo \ - ./$(DEPDIR)/cairo-polygon-reduce.Plo \ - ./$(DEPDIR)/cairo-polygon.Plo ./$(DEPDIR)/cairo-ps-surface.Plo \ - ./$(DEPDIR)/cairo-qt-surface.Plo \ - ./$(DEPDIR)/cairo-quartz-font.Plo \ - ./$(DEPDIR)/cairo-quartz-image-surface.Plo \ - ./$(DEPDIR)/cairo-quartz-surface.Plo \ - ./$(DEPDIR)/cairo-raster-source-pattern.Plo \ - ./$(DEPDIR)/cairo-recording-surface.Plo \ - ./$(DEPDIR)/cairo-rectangle.Plo \ - ./$(DEPDIR)/cairo-rectangular-scan-converter.Plo \ - ./$(DEPDIR)/cairo-region.Plo ./$(DEPDIR)/cairo-rtree.Plo \ - ./$(DEPDIR)/cairo-scaled-font-subsets.Plo \ - ./$(DEPDIR)/cairo-scaled-font.Plo \ - ./$(DEPDIR)/cairo-script-surface.Plo \ - ./$(DEPDIR)/cairo-shape-mask-compositor.Plo \ - ./$(DEPDIR)/cairo-slope.Plo \ - ./$(DEPDIR)/cairo-spans-compositor.Plo \ - ./$(DEPDIR)/cairo-spans.Plo ./$(DEPDIR)/cairo-spline.Plo \ - ./$(DEPDIR)/cairo-stroke-dash.Plo \ - ./$(DEPDIR)/cairo-stroke-style.Plo \ - ./$(DEPDIR)/cairo-surface-clipper.Plo \ - ./$(DEPDIR)/cairo-surface-fallback.Plo \ - ./$(DEPDIR)/cairo-surface-observer.Plo \ - ./$(DEPDIR)/cairo-surface-offset.Plo \ - ./$(DEPDIR)/cairo-surface-snapshot.Plo \ - ./$(DEPDIR)/cairo-surface-subsurface.Plo \ - ./$(DEPDIR)/cairo-surface-wrapper.Plo \ - ./$(DEPDIR)/cairo-surface.Plo \ - ./$(DEPDIR)/cairo-svg-surface.Plo \ - ./$(DEPDIR)/cairo-tag-attributes.Plo \ - ./$(DEPDIR)/cairo-tag-stack.Plo \ - ./$(DEPDIR)/cairo-tee-surface.Plo ./$(DEPDIR)/cairo-time.Plo \ - ./$(DEPDIR)/cairo-tor-scan-converter.Plo \ - ./$(DEPDIR)/cairo-tor22-scan-converter.Plo \ - ./$(DEPDIR)/cairo-toy-font-face.Plo \ - ./$(DEPDIR)/cairo-traps-compositor.Plo \ - ./$(DEPDIR)/cairo-traps.Plo ./$(DEPDIR)/cairo-tristrip.Plo \ - ./$(DEPDIR)/cairo-truetype-subset.Plo \ - ./$(DEPDIR)/cairo-type1-fallback.Plo \ - ./$(DEPDIR)/cairo-type1-glyph-names.Plo \ - ./$(DEPDIR)/cairo-type1-subset.Plo \ - ./$(DEPDIR)/cairo-type3-glyph-surface.Plo \ - ./$(DEPDIR)/cairo-unicode.Plo ./$(DEPDIR)/cairo-user-font.Plo \ - ./$(DEPDIR)/cairo-version.Plo ./$(DEPDIR)/cairo-vg-surface.Plo \ - ./$(DEPDIR)/cairo-wgl-context.Plo \ - ./$(DEPDIR)/cairo-wideint.Plo \ - ./$(DEPDIR)/cairo-win32-debug.Plo \ - ./$(DEPDIR)/cairo-win32-device.Plo \ - ./$(DEPDIR)/cairo-win32-display-surface.Plo \ - ./$(DEPDIR)/cairo-win32-font.Plo \ - ./$(DEPDIR)/cairo-win32-gdi-compositor.Plo \ - ./$(DEPDIR)/cairo-win32-printing-surface.Plo \ - ./$(DEPDIR)/cairo-win32-surface.Plo \ - ./$(DEPDIR)/cairo-win32-system.Plo \ - ./$(DEPDIR)/cairo-xcb-connection-core.Plo \ - ./$(DEPDIR)/cairo-xcb-connection-render.Plo \ - ./$(DEPDIR)/cairo-xcb-connection-shm.Plo \ - ./$(DEPDIR)/cairo-xcb-connection.Plo \ - ./$(DEPDIR)/cairo-xcb-resources.Plo \ - ./$(DEPDIR)/cairo-xcb-screen.Plo ./$(DEPDIR)/cairo-xcb-shm.Plo \ - ./$(DEPDIR)/cairo-xcb-surface-core.Plo \ - ./$(DEPDIR)/cairo-xcb-surface-render.Plo \ - ./$(DEPDIR)/cairo-xcb-surface.Plo \ - ./$(DEPDIR)/cairo-xlib-core-compositor.Plo \ - ./$(DEPDIR)/cairo-xlib-display.Plo \ - ./$(DEPDIR)/cairo-xlib-fallback-compositor.Plo \ - ./$(DEPDIR)/cairo-xlib-render-compositor.Plo \ - ./$(DEPDIR)/cairo-xlib-screen.Plo \ - ./$(DEPDIR)/cairo-xlib-source.Plo \ - ./$(DEPDIR)/cairo-xlib-surface-shm.Plo \ - ./$(DEPDIR)/cairo-xlib-surface.Plo \ - ./$(DEPDIR)/cairo-xlib-visual.Plo \ - ./$(DEPDIR)/cairo-xlib-xcb-surface.Plo \ - ./$(DEPDIR)/cairo-xml-surface.Plo ./$(DEPDIR)/cairo.Plo \ - ./$(DEPDIR)/check-link.Po \ - ./$(DEPDIR)/test-base-compositor-surface.Plo \ - ./$(DEPDIR)/test-compositor-surface.Plo \ - ./$(DEPDIR)/test-null-compositor-surface.Plo \ - ./$(DEPDIR)/test-paginated-surface.Plo -am__mv = mv -f -COMPILE = $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) \ - $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -LTCOMPILE = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \ - $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) \ - $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) \ - $(AM_CFLAGS) $(CFLAGS) -AM_V_CC = $(am__v_CC_@AM_V@) -am__v_CC_ = $(am__v_CC_@AM_DEFAULT_V@) -am__v_CC_0 = @echo " CC " $@; -am__v_CC_1 = -CCLD = $(CC) -LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \ - $(LIBTOOLFLAGS) --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) \ - $(AM_LDFLAGS) $(LDFLAGS) -o $@ -AM_V_CCLD = $(am__v_CCLD_@AM_V@) -am__v_CCLD_ = $(am__v_CCLD_@AM_DEFAULT_V@) -am__v_CCLD_0 = @echo " CCLD " $@; -am__v_CCLD_1 = -CXXCOMPILE = $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) \ - $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -LTCXXCOMPILE = $(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) \ - $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) \ - $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) \ - $(AM_CXXFLAGS) $(CXXFLAGS) -AM_V_CXX = $(am__v_CXX_@AM_V@) -am__v_CXX_ = $(am__v_CXX_@AM_DEFAULT_V@) -am__v_CXX_0 = @echo " CXX " $@; -am__v_CXX_1 = -CXXLD = $(CXX) -CXXLINK = $(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) \ - $(LIBTOOLFLAGS) --mode=link $(CXXLD) $(AM_CXXFLAGS) \ - $(CXXFLAGS) $(AM_LDFLAGS) $(LDFLAGS) -o $@ -AM_V_CXXLD = $(am__v_CXXLD_@AM_V@) -am__v_CXXLD_ = $(am__v_CXXLD_@AM_DEFAULT_V@) -am__v_CXXLD_0 = @echo " CXXLD " $@; -am__v_CXXLD_1 = -SOURCES = $(libcairo_la_SOURCES) $(nodist_libcairo_la_SOURCES) \ - $(libcairo_cxx_la_SOURCES) check-link.c -DIST_SOURCES = $(am__libcairo_la_SOURCES_DIST) \ - $(am__libcairo_cxx_la_SOURCES_DIST) check-link.c -am__can_run_installinfo = \ - case $$AM_UPDATE_INFO_DIR in \ - n|no|NO) false;; \ - *) (install-info --version) >/dev/null 2>&1;; \ - esac -DATA = $(pkgconfig_DATA) -am__cairoinclude_HEADERS_DIST = cairo.h cairo-version.h \ - cairo-deprecated.h cairo-xlib.h cairo-xlib-xrender.h \ - cairo-xcb.h cairo-qt.h cairo-quartz.h cairo-quartz-image.h \ - cairo-win32.h cairo-os2.h cairo-beos.h cairo-drm.h cairo-gl.h \ - cairo-cogl.h cairo-directfb.h cairo-vg.h cairo-script.h \ - cairo-ft.h cairo-ps.h cairo-pdf.h cairo-svg.h cairo-tee.h \ - cairo-xml.h -HEADERS = $(cairoinclude_HEADERS) $(nodist_cairoinclude_HEADERS) -am__tagged_files = $(HEADERS) $(SOURCES) $(TAGS_FILES) $(LISP) -# Read a list of newline-separated strings from the standard input, -# and print each of them once, without duplicates. Input order is -# *not* preserved. -am__uniquify_input = $(AWK) '\ - BEGIN { nonempty = 0; } \ - { items[$$0] = 1; nonempty = 1; } \ - END { if (nonempty) { for (i in items) print i; }; } \ -' -# Make sure the list of sources is unique. This is necessary because, -# e.g., the same source file might be shared among _SOURCES variables -# for different programs/libraries. -am__define_uniq_tagged_files = \ - list='$(am__tagged_files)'; \ - unique=`for i in $$list; do \ - if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ - done | $(am__uniquify_input)` -ETAGS = etags -CTAGS = ctags -am__tty_colors_dummy = \ - mgn= red= grn= lgn= blu= brg= std=; \ - am__color_tests=no -am__tty_colors = { \ - $(am__tty_colors_dummy); \ - if test "X$(AM_COLOR_TESTS)" = Xno; then \ - am__color_tests=no; \ - elif test "X$(AM_COLOR_TESTS)" = Xalways; then \ - am__color_tests=yes; \ - elif test "X$$TERM" != Xdumb && { test -t 1; } 2>/dev/null; then \ - am__color_tests=yes; \ - fi; \ - if test $$am__color_tests = yes; then \ - red='[0;31m'; \ - grn='[0;32m'; \ - lgn='[1;32m'; \ - blu='[1;34m'; \ - mgn='[0;35m'; \ - brg='[1m'; \ - std='[m'; \ - fi; \ -} -am__recheck_rx = ^[ ]*:recheck:[ ]* -am__global_test_result_rx = ^[ ]*:global-test-result:[ ]* -am__copy_in_global_log_rx = ^[ ]*:copy-in-global-log:[ ]* -# A command that, given a newline-separated list of test names on the -# standard input, print the name of the tests that are to be re-run -# upon "make recheck". -am__list_recheck_tests = $(AWK) '{ \ - recheck = 1; \ - while ((rc = (getline line < ($$0 ".trs"))) != 0) \ - { \ - if (rc < 0) \ - { \ - if ((getline line2 < ($$0 ".log")) < 0) \ - recheck = 0; \ - break; \ - } \ - else if (line ~ /$(am__recheck_rx)[nN][Oo]/) \ - { \ - recheck = 0; \ - break; \ - } \ - else if (line ~ /$(am__recheck_rx)[yY][eE][sS]/) \ - { \ - break; \ - } \ - }; \ - if (recheck) \ - print $$0; \ - close ($$0 ".trs"); \ - close ($$0 ".log"); \ -}' -# A command that, given a newline-separated list of test names on the -# standard input, create the global log from their .trs and .log files. -am__create_global_log = $(AWK) ' \ -function fatal(msg) \ -{ \ - print "fatal: making $@: " msg | "cat >&2"; \ - exit 1; \ -} \ -function rst_section(header) \ -{ \ - print header; \ - len = length(header); \ - for (i = 1; i <= len; i = i + 1) \ - printf "="; \ - printf "\n\n"; \ -} \ -{ \ - copy_in_global_log = 1; \ - global_test_result = "RUN"; \ - while ((rc = (getline line < ($$0 ".trs"))) != 0) \ - { \ - if (rc < 0) \ - fatal("failed to read from " $$0 ".trs"); \ - if (line ~ /$(am__global_test_result_rx)/) \ - { \ - sub("$(am__global_test_result_rx)", "", line); \ - sub("[ ]*$$", "", line); \ - global_test_result = line; \ - } \ - else if (line ~ /$(am__copy_in_global_log_rx)[nN][oO]/) \ - copy_in_global_log = 0; \ - }; \ - if (copy_in_global_log) \ - { \ - rst_section(global_test_result ": " $$0); \ - while ((rc = (getline line < ($$0 ".log"))) != 0) \ - { \ - if (rc < 0) \ - fatal("failed to read from " $$0 ".log"); \ - print line; \ - }; \ - printf "\n"; \ - }; \ - close ($$0 ".trs"); \ - close ($$0 ".log"); \ -}' -# Restructured Text title. -am__rst_title = { sed 's/.*/ & /;h;s/./=/g;p;x;s/ *$$//;p;g' && echo; } -# Solaris 10 'make', and several other traditional 'make' implementations, -# pass "-e" to $(SHELL), and POSIX 2008 even requires this. Work around it -# by disabling -e (using the XSI extension "set +e") if it's set. -am__sh_e_setup = case $$- in *e*) set +e;; esac -# Default flags passed to test drivers. -am__common_driver_flags = \ - --color-tests "$$am__color_tests" \ - --enable-hard-errors "$$am__enable_hard_errors" \ - --expect-failure "$$am__expect_failure" -# To be inserted before the command running the test. Creates the -# directory for the log if needed. Stores in $dir the directory -# containing $f, in $tst the test, in $log the log. Executes the -# developer- defined test setup AM_TESTS_ENVIRONMENT (if any), and -# passes TESTS_ENVIRONMENT. Set up options for the wrapper that -# will run the test scripts (or their associated LOG_COMPILER, if -# thy have one). -am__check_pre = \ -$(am__sh_e_setup); \ -$(am__vpath_adj_setup) $(am__vpath_adj) \ -$(am__tty_colors); \ -srcdir=$(srcdir); export srcdir; \ -case "$@" in \ - */*) am__odir=`echo "./$@" | sed 's|/[^/]*$$||'`;; \ - *) am__odir=.;; \ -esac; \ -test "x$$am__odir" = x"." || test -d "$$am__odir" \ - || $(MKDIR_P) "$$am__odir" || exit $$?; \ -if test -f "./$$f"; then dir=./; \ -elif test -f "$$f"; then dir=; \ -else dir="$(srcdir)/"; fi; \ -tst=$$dir$$f; log='$@'; \ -if test -n '$(DISABLE_HARD_ERRORS)'; then \ - am__enable_hard_errors=no; \ -else \ - am__enable_hard_errors=yes; \ -fi; \ -case " $(XFAIL_TESTS) " in \ - *[\ \ ]$$f[\ \ ]* | *[\ \ ]$$dir$$f[\ \ ]*) \ - am__expect_failure=yes;; \ - *) \ - am__expect_failure=no;; \ -esac; \ -$(AM_TESTS_ENVIRONMENT) $(TESTS_ENVIRONMENT) -# A shell command to get the names of the tests scripts with any registered -# extension removed (i.e., equivalently, the names of the test logs, with -# the '.log' extension removed). The result is saved in the shell variable -# '$bases'. This honors runtime overriding of TESTS and TEST_LOGS. Sadly, -# we cannot use something simpler, involving e.g., "$(TEST_LOGS:.log=)", -# since that might cause problem with VPATH rewrites for suffix-less tests. -# See also 'test-harness-vpath-rewrite.sh' and 'test-trs-basic.sh'. -am__set_TESTS_bases = \ - bases='$(TEST_LOGS)'; \ - bases=`for i in $$bases; do echo $$i; done | sed 's/\.log$$//'`; \ - bases=`echo $$bases` -RECHECK_LOGS = $(TEST_LOGS) -AM_RECURSIVE_TARGETS = check recheck -am__EXEEXT_1 = check-def.sh check-doc-syntax.sh check-headers.sh \ - check-plt.sh check-preprocessor-syntax.sh -TEST_SUITE_LOG = test-suite.log -TEST_EXTENSIONS = @EXEEXT@ .test -LOG_DRIVER = $(SHELL) $(top_srcdir)/build/test-driver -LOG_COMPILE = $(LOG_COMPILER) $(AM_LOG_FLAGS) $(LOG_FLAGS) -am__set_b = \ - case '$@' in \ - */*) \ - case '$*' in \ - */*) b='$*';; \ - *) b=`echo '$@' | sed 's/\.log$$//'`; \ - esac;; \ - *) \ - b='$*';; \ - esac -am__test_logs1 = $(TESTS:=.log) -am__test_logs2 = $(am__test_logs1:@EXEEXT@.log=.log) -TEST_LOGS = $(am__test_logs2:.test.log=.log) -TEST_LOG_DRIVER = $(SHELL) $(top_srcdir)/build/test-driver -TEST_LOG_COMPILE = $(TEST_LOG_COMPILER) $(AM_TEST_LOG_FLAGS) \ - $(TEST_LOG_FLAGS) -am__DIST_COMMON = $(srcdir)/Makefile.am.analysis \ - $(srcdir)/Makefile.am.features $(srcdir)/Makefile.in \ - $(srcdir)/cairo-features.pc.in $(srcdir)/cairo.pc.in \ - $(top_srcdir)/build/Makefile.am.common \ - $(top_srcdir)/build/depcomp $(top_srcdir)/build/test-driver \ - $(top_srcdir)/src/Makefile.sources README -DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) -ACLOCAL = @ACLOCAL@ -AMTAR = @AMTAR@ -AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@ -AR = @AR@ -AS = @AS@ -AUTOCONF = @AUTOCONF@ -AUTOHEADER = @AUTOHEADER@ -AUTOMAKE = @AUTOMAKE@ -AWK = @AWK@ -BFD_LIBS = @BFD_LIBS@ -CAIROBOILERPLATE_LIBS = @CAIROBOILERPLATE_LIBS@ -CAIRO_CFLAGS = @CAIRO_CFLAGS@ -CAIRO_LDFLAGS = @CAIRO_LDFLAGS@ -CAIRO_LIBS = @CAIRO_LIBS@ -CAIRO_LIBTOOL_VERSION_INFO = @CAIRO_LIBTOOL_VERSION_INFO@ -CAIRO_NONPKGCONFIG_CFLAGS = @CAIRO_NONPKGCONFIG_CFLAGS@ -CAIRO_NONPKGCONFIG_LIBS = @CAIRO_NONPKGCONFIG_LIBS@ -CAIRO_RELEASE_STATUS = @CAIRO_RELEASE_STATUS@ -CAIRO_REQUIRES = @CAIRO_REQUIRES@ -CAIRO_TEST_MODE = @CAIRO_TEST_MODE@ -CAIRO_TEST_UNDEFINED_LDFLAGS = @CAIRO_TEST_UNDEFINED_LDFLAGS@ -CAIRO_VERSION_MAJOR = @CAIRO_VERSION_MAJOR@ -CAIRO_VERSION_MICRO = @CAIRO_VERSION_MICRO@ -CAIRO_VERSION_MINOR = @CAIRO_VERSION_MINOR@ -CAIRO_VERSION_SONUM = @CAIRO_VERSION_SONUM@ -CC = @CC@ -CCDEPMODE = @CCDEPMODE@ -CFLAGS = @CFLAGS@ -CPP = @CPP@ -CPPFLAGS = @CPPFLAGS@ -CXX = @CXX@ -CXXCPP = @CXXCPP@ -CXXDEPMODE = @CXXDEPMODE@ -CXXFLAGS = @CXXFLAGS@ -CYGPATH_W = @CYGPATH_W@ -DEFS = @DEFS@ -DEPDIR = @DEPDIR@ -DLLTOOL = @DLLTOOL@ -DSYMUTIL = @DSYMUTIL@ -DUMPBIN = @DUMPBIN@ -ECHO_C = @ECHO_C@ -ECHO_N = @ECHO_N@ -ECHO_T = @ECHO_T@ -EGREP = @EGREP@ -EXEEXT = @EXEEXT@ -FGREP = @FGREP@ -FIND = @FIND@ -FONTCONFIG_CFLAGS = @FONTCONFIG_CFLAGS@ -FONTCONFIG_LIBS = @FONTCONFIG_LIBS@ -FREETYPE_CFLAGS = @FREETYPE_CFLAGS@ -FREETYPE_CONFIG = @FREETYPE_CONFIG@ -FREETYPE_LIBS = @FREETYPE_LIBS@ -GOBJECT_CFLAGS = @GOBJECT_CFLAGS@ -GOBJECT_LIBS = @GOBJECT_LIBS@ -GREP = @GREP@ -GS = @GS@ -GTKDOC_CHECK = @GTKDOC_CHECK@ -HTML_DIR = @HTML_DIR@ -INSTALL = @INSTALL@ -INSTALL_DATA = @INSTALL_DATA@ -INSTALL_PROGRAM = @INSTALL_PROGRAM@ -INSTALL_SCRIPT = @INSTALL_SCRIPT@ -INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ -LD = @LD@ -LDFLAGS = @LDFLAGS@ -LIBM = @LIBM@ -LIBOBJS = @LIBOBJS@ -LIBRSVG_CFLAGS = @LIBRSVG_CFLAGS@ -LIBRSVG_LIBS = @LIBRSVG_LIBS@ -LIBS = @LIBS@ -LIBSPECTRE_CFLAGS = @LIBSPECTRE_CFLAGS@ -LIBSPECTRE_LIBS = @LIBSPECTRE_LIBS@ -LIBTOOL = @LIBTOOL@ -LIPO = @LIPO@ -LN_S = @LN_S@ -LTLIBOBJS = @LTLIBOBJS@ -LTP = @LTP@ -LTP_GENHTML = @LTP_GENHTML@ -LT_SYS_LIBRARY_PATH = @LT_SYS_LIBRARY_PATH@ -MAKEINFO = @MAKEINFO@ -MANIFEST_TOOL = @MANIFEST_TOOL@ -MKDIR_P = @MKDIR_P@ -NM = @NM@ -NMEDIT = @NMEDIT@ -OBJDUMP = @OBJDUMP@ -OBJEXT = @OBJEXT@ -OTOOL = @OTOOL@ -OTOOL64 = @OTOOL64@ -PACKAGE = @PACKAGE@ -PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@ -PACKAGE_NAME = @PACKAGE_NAME@ -PACKAGE_STRING = @PACKAGE_STRING@ -PACKAGE_TARNAME = @PACKAGE_TARNAME@ -PACKAGE_URL = @PACKAGE_URL@ -PACKAGE_VERSION = @PACKAGE_VERSION@ -PATH_SEPARATOR = @PATH_SEPARATOR@ -PKGCONFIG_REQUIRES = @PKGCONFIG_REQUIRES@ -PKG_CONFIG = @PKG_CONFIG@ -POPPLER_CFLAGS = @POPPLER_CFLAGS@ -POPPLER_LIBS = @POPPLER_LIBS@ -RANLIB = @RANLIB@ -SED = @SED@ -SET_MAKE = @SET_MAKE@ -SHELL = @SHELL@ -SHLIB_EXT = @SHLIB_EXT@ -SHM_LIBS = @SHM_LIBS@ -SHTOOL = @SHTOOL@ -STRINGS = @STRINGS@ -STRIP = @STRIP@ -VALGRIND_CFLAGS = @VALGRIND_CFLAGS@ -VALGRIND_LIBS = @VALGRIND_LIBS@ -VERSION = @VERSION@ -XARGS = @XARGS@ -XMKMF = @XMKMF@ -X_CFLAGS = @X_CFLAGS@ -X_EXTRA_LIBS = @X_EXTRA_LIBS@ -X_LIBS = @X_LIBS@ -X_PRE_LIBS = @X_PRE_LIBS@ -abs_builddir = @abs_builddir@ -abs_srcdir = @abs_srcdir@ -abs_top_builddir = @abs_top_builddir@ -abs_top_srcdir = @abs_top_srcdir@ -ac_ct_AR = @ac_ct_AR@ -ac_ct_CC = @ac_ct_CC@ -ac_ct_CXX = @ac_ct_CXX@ -ac_ct_DUMPBIN = @ac_ct_DUMPBIN@ -am__include = @am__include@ -am__leading_dot = @am__leading_dot@ -am__quote = @am__quote@ -am__tar = @am__tar@ -am__untar = @am__untar@ -bindir = @bindir@ -build = @build@ -build_alias = @build_alias@ -build_cpu = @build_cpu@ -build_os = @build_os@ -build_vendor = @build_vendor@ -builddir = @builddir@ -cogl_CFLAGS = @cogl_CFLAGS@ -cogl_LIBS = @cogl_LIBS@ -datadir = @datadir@ -datarootdir = @datarootdir@ -directfb_CFLAGS = @directfb_CFLAGS@ -directfb_LIBS = @directfb_LIBS@ -docdir = @docdir@ -drm_CFLAGS = @drm_CFLAGS@ -drm_LIBS = @drm_LIBS@ -dvidir = @dvidir@ -egl_CFLAGS = @egl_CFLAGS@ -egl_LIBS = @egl_LIBS@ -exec_prefix = @exec_prefix@ -gallium_DIR = @gallium_DIR@ -gl_CFLAGS = @gl_CFLAGS@ -gl_LIBS = @gl_LIBS@ -glesv2_CFLAGS = @glesv2_CFLAGS@ -glesv2_LIBS = @glesv2_LIBS@ -glesv3_CFLAGS = @glesv3_CFLAGS@ -glesv3_LIBS = @glesv3_LIBS@ -glib_CFLAGS = @glib_CFLAGS@ -glib_LIBS = @glib_LIBS@ -gtk_CFLAGS = @gtk_CFLAGS@ -gtk_LIBS = @gtk_LIBS@ -host = @host@ -host_alias = @host_alias@ -host_cpu = @host_cpu@ -host_os = @host_os@ -host_vendor = @host_vendor@ -htmldir = @htmldir@ -includedir = @includedir@ -infodir = @infodir@ -install_sh = @install_sh@ -libdir = @libdir@ -libexecdir = @libexecdir@ -localedir = @localedir@ -localstatedir = @localstatedir@ -lzo_LIBS = @lzo_LIBS@ -mandir = @mandir@ -mesa_DIR = @mesa_DIR@ -mkdir_p = @mkdir_p@ -oldincludedir = @oldincludedir@ -pdfdir = @pdfdir@ -pixman_CFLAGS = @pixman_CFLAGS@ -pixman_LIBS = @pixman_LIBS@ -png_CFLAGS = @png_CFLAGS@ -png_LIBS = @png_LIBS@ -png_REQUIRES = @png_REQUIRES@ -prefix = @prefix@ -program_transform_name = @program_transform_name@ -psdir = @psdir@ -pthread_CFLAGS = @pthread_CFLAGS@ -pthread_LIBS = @pthread_LIBS@ -qt_CFLAGS = @qt_CFLAGS@ -qt_LIBS = @qt_LIBS@ -real_pthread_CFLAGS = @real_pthread_CFLAGS@ -real_pthread_LIBS = @real_pthread_LIBS@ -runstatedir = @runstatedir@ -sbindir = @sbindir@ -sharedstatedir = @sharedstatedir@ -shm_LIBS = @shm_LIBS@ -srcdir = @srcdir@ -sysconfdir = @sysconfdir@ -target_alias = @target_alias@ -top_build_prefix = @top_build_prefix@ -top_builddir = @top_builddir@ -top_srcdir = @top_srcdir@ -xcb_CFLAGS = @xcb_CFLAGS@ -xcb_LIBS = @xcb_LIBS@ -xcb_shm_CFLAGS = @xcb_shm_CFLAGS@ -xcb_shm_LIBS = @xcb_shm_LIBS@ -xlib_CFLAGS = @xlib_CFLAGS@ -xlib_LIBS = @xlib_LIBS@ -xlib_xcb_CFLAGS = @xlib_xcb_CFLAGS@ -xlib_xcb_LIBS = @xlib_xcb_LIBS@ -xlib_xrender_CFLAGS = @xlib_xrender_CFLAGS@ -xlib_xrender_LIBS = @xlib_xrender_LIBS@ -BUILT_SOURCES = cairo-features.h cairo-supported-features.h -CLEANFILES = *.i *.s *.gch $(EXTRA_LTLIBRARIES) $(EXTRA_PROGRAMS) \ - $(check_PROGRAMS) cairo.def headers-standalone -DISTCLEANFILES = $(BUILT_SOURCES) cairo-features.h \ - cairo-supported-features.h -EXTRA_DIST = Makefile.win32 Makefile.win32.features $(TESTS_SH) \ - check-has-hidden-symbols.c check-doc-syntax.awk -EXTRA_LTLIBRARIES = -MAINTAINERCLEANFILES = Makefile.in -cairo_headers = cairo.h cairo-version.h cairo-deprecated.h -cairo_private = cairoint.h cairo-analysis-surface-private.h \ - cairo-arc-private.h cairo-array-private.h \ - cairo-atomic-private.h cairo-backend-private.h \ - cairo-box-inline.h cairo-boxes-private.h cairo-cache-private.h \ - cairo-clip-inline.h cairo-clip-private.h \ - cairo-combsort-inline.h cairo-compiler-private.h \ - cairo-composite-rectangles-private.h \ - cairo-compositor-private.h cairo-contour-inline.h \ - cairo-contour-private.h cairo-damage-private.h \ - cairo-default-context-private.h cairo-device-private.h \ - cairo-error-inline.h cairo-error-private.h \ - cairo-fixed-private.h cairo-fixed-type-private.h \ - cairo-fontconfig-private.h cairo-freed-pool-private.h \ - cairo-freelist-private.h cairo-freelist-type-private.h \ - cairo-gstate-private.h cairo-hash-private.h \ - cairo-image-info-private.h cairo-image-surface-inline.h \ - cairo-image-surface-private.h cairo-line-inline.h \ - cairo-line-private.h cairo-list-inline.h cairo-list-private.h \ - cairo-malloc-private.h cairo-mempool-private.h \ - cairo-mutex-impl-private.h cairo-mutex-list-private.h \ - cairo-mutex-private.h cairo-mutex-type-private.h \ - cairo-output-stream-private.h cairo-paginated-private.h \ - cairo-paginated-surface-private.h cairo-path-fixed-private.h \ - cairo-path-private.h cairo-pattern-inline.h \ - cairo-pattern-private.h cairo-pixman-private.h cairo-private.h \ - cairo-recording-surface-inline.h \ - cairo-recording-surface-private.h \ - cairo-reference-count-private.h cairo-region-private.h \ - cairo-rtree-private.h cairo-scaled-font-private.h \ - cairo-slope-private.h cairo-spans-compositor-private.h \ - cairo-spans-private.h cairo-stroke-dash-private.h \ - cairo-surface-backend-private.h \ - cairo-surface-clipper-private.h \ - cairo-surface-fallback-private.h cairo-surface-inline.h \ - cairo-surface-observer-inline.h \ - cairo-surface-observer-private.h \ - cairo-surface-offset-private.h cairo-surface-private.h \ - cairo-surface-snapshot-inline.h \ - cairo-surface-snapshot-private.h \ - cairo-surface-subsurface-inline.h \ - cairo-surface-subsurface-private.h \ - cairo-surface-wrapper-private.h cairo-time-private.h \ - cairo-traps-private.h cairo-tristrip-private.h \ - cairo-types-private.h cairo-user-font-private.h \ - cairo-wideint-private.h cairo-wideint-type-private.h $(NULL) \ - $(_cairo_font_subset_private) $(_cairo_pdf_operators_private) -cairo_sources = cairo-analysis-surface.c cairo-arc.c cairo-array.c \ - cairo-atomic.c cairo-base64-stream.c cairo-base85-stream.c \ - cairo-bentley-ottmann-rectangular.c \ - cairo-bentley-ottmann-rectilinear.c cairo-bentley-ottmann.c \ - cairo-botor-scan-converter.c cairo-boxes-intersect.c \ - cairo-boxes.c cairo-cache.c cairo-clip-boxes.c \ - cairo-clip-polygon.c cairo-clip-region.c cairo-clip-surface.c \ - cairo-clip-tor-scan-converter.c cairo-clip.c cairo-color.c \ - cairo-composite-rectangles.c cairo-compositor.c \ - cairo-contour.c cairo-damage.c cairo-debug.c \ - cairo-default-context.c cairo-device.c cairo-error.c \ - cairo-fallback-compositor.c cairo-fixed.c \ - cairo-font-face-twin-data.c cairo-font-face-twin.c \ - cairo-font-face.c cairo-font-options.c cairo-freed-pool.c \ - cairo-freelist.c cairo-gstate.c cairo-hash.c cairo-hull.c \ - cairo-image-compositor.c cairo-image-info.c \ - cairo-image-source.c cairo-image-surface.c cairo-line.c \ - cairo-lzw.c cairo-mask-compositor.c cairo-matrix.c \ - cairo-mempool.c cairo-mesh-pattern-rasterizer.c cairo-misc.c \ - cairo-mono-scan-converter.c cairo-mutex.c \ - cairo-no-compositor.c cairo-observer.c cairo-output-stream.c \ - cairo-paginated-surface.c cairo-path-bounds.c \ - cairo-path-fill.c cairo-path-fixed.c cairo-path-in-fill.c \ - cairo-path-stroke-boxes.c cairo-path-stroke-polygon.c \ - cairo-path-stroke-traps.c cairo-path-stroke-tristrip.c \ - cairo-path-stroke.c cairo-path.c cairo-pattern.c cairo-pen.c \ - cairo-polygon-intersect.c cairo-polygon-reduce.c \ - cairo-polygon.c cairo-raster-source-pattern.c \ - cairo-recording-surface.c cairo-rectangle.c \ - cairo-rectangular-scan-converter.c cairo-region.c \ - cairo-rtree.c cairo-scaled-font.c \ - cairo-shape-mask-compositor.c cairo-slope.c \ - cairo-spans-compositor.c cairo-spans.c cairo-spline.c \ - cairo-stroke-dash.c cairo-stroke-style.c \ - cairo-surface-clipper.c cairo-surface-fallback.c \ - cairo-surface-observer.c cairo-surface-offset.c \ - cairo-surface-snapshot.c cairo-surface-subsurface.c \ - cairo-surface-wrapper.c cairo-surface.c cairo-time.c \ - cairo-tor-scan-converter.c cairo-tor22-scan-converter.c \ - cairo-toy-font-face.c cairo-traps-compositor.c cairo-traps.c \ - cairo-tristrip.c cairo-unicode.c cairo-user-font.c \ - cairo-version.c cairo-wideint.c cairo.c $(NULL) \ - $(_cairo_font_subset_sources) $(_cairo_pdf_operators_sources) \ - $(_cairo_deflate_stream_sources) -_cairo_font_subset_private = \ - cairo-scaled-font-subsets-private.h \ - cairo-truetype-subset-private.h \ - cairo-type1-private.h \ - cairo-type3-glyph-surface-private.h \ - $(NULL) - -_cairo_font_subset_sources = \ - cairo-cff-subset.c \ - cairo-scaled-font-subsets.c \ - cairo-truetype-subset.c \ - cairo-type1-fallback.c \ - cairo-type1-glyph-names.c \ - cairo-type1-subset.c \ - cairo-type3-glyph-surface.c \ - $(NULL) - -cairo_egl_sources = cairo-egl-context.c -cairo_glx_sources = cairo-glx-context.c -cairo_wgl_sources = cairo-wgl-context.c -_cairo_pdf_operators_private = \ - cairo-pdf-operators-private.h \ - cairo-pdf-shading-private.h \ - cairo-tag-attributes-private.h \ - $(NULL) - -_cairo_pdf_operators_sources = \ - cairo-pdf-operators.c \ - cairo-pdf-shading.c \ - cairo-tag-attributes.c \ - $(NULL) - -cairo_png_sources = cairo-png.c -cairo_ps_headers = cairo-ps.h -cairo_ps_private = cairo-ps-surface-private.h -cairo_ps_sources = cairo-ps-surface.c -_cairo_deflate_stream_sources = cairo-deflate-stream.c -cairo_pdf_headers = cairo-pdf.h -cairo_pdf_private = cairo-pdf-surface-private.h cairo-tag-stack-private.h -cairo_pdf_sources = cairo-pdf-surface.c cairo-pdf-interchange.c cairo-tag-stack.c -cairo_svg_headers = cairo-svg.h -cairo_svg_private = cairo-svg-surface-private.h -cairo_svg_sources = cairo-svg-surface.c -cairo_ft_headers = cairo-ft.h -cairo_ft_private = cairo-ft-private.h -cairo_ft_sources = cairo-ft-font.c - -# These are private, even though they look like public headers -cairo_test_surfaces_private = \ - test-compositor-surface.h \ - test-compositor-surface-private.h \ - test-null-compositor-surface.h \ - test-paginated-surface.h \ - $(NULL) - -cairo_test_surfaces_sources = \ - test-compositor-surface.c \ - test-null-compositor-surface.c \ - test-base-compositor-surface.c \ - test-paginated-surface.c \ - $(NULL) - -cairo_xlib_headers = cairo-xlib.h -cairo_xlib_private = \ - cairo-xlib-private.h \ - cairo-xlib-surface-private.h \ - cairo-xlib-xrender-private.h \ - $(NULL) - -cairo_xlib_sources = \ - cairo-xlib-display.c \ - cairo-xlib-core-compositor.c \ - cairo-xlib-fallback-compositor.c \ - cairo-xlib-render-compositor.c \ - cairo-xlib-screen.c \ - cairo-xlib-source.c \ - cairo-xlib-surface.c \ - cairo-xlib-surface-shm.c \ - cairo-xlib-visual.c \ - cairo-xlib-xcb-surface.c \ - $(NULL) - -cairo_xlib_xrender_headers = cairo-xlib-xrender.h -cairo_xcb_headers = cairo-xcb.h -cairo_xcb_private = cairo-xcb-private.h -cairo_xcb_sources = \ - cairo-xcb-connection.c \ - cairo-xcb-connection-core.c \ - cairo-xcb-connection-render.c \ - cairo-xcb-connection-shm.c \ - cairo-xcb-screen.c \ - cairo-xcb-shm.c \ - cairo-xcb-surface.c \ - cairo-xcb-surface-core.c \ - cairo-xcb-surface-render.c \ - cairo-xcb-resources.c \ - $(NULL) - -cairo_qt_headers = cairo-qt.h -cairo_qt_cxx_sources = cairo-qt-surface.cpp -cairo_quartz_headers = cairo-quartz.h -cairo_quartz_private = cairo-quartz-private.h -cairo_quartz_sources = cairo-quartz-surface.c -cairo_quartz_image_headers = cairo-quartz-image.h -cairo_quartz_image_sources = cairo-quartz-image-surface.c -cairo_quartz_font_sources = cairo-quartz-font.c -cairo_win32_headers = cairo-win32.h -cairo_win32_private = win32/cairo-win32-private.h -cairo_win32_sources = \ - win32/cairo-win32-debug.c \ - win32/cairo-win32-device.c \ - win32/cairo-win32-gdi-compositor.c \ - win32/cairo-win32-system.c \ - win32/cairo-win32-surface.c \ - win32/cairo-win32-display-surface.c \ - win32/cairo-win32-printing-surface.c \ - $(NULL) - -cairo_win32_font_sources = \ - win32/cairo-win32-font.c \ - $(NULL) - -cairo_os2_headers = cairo-os2.h -cairo_os2_private = cairo-os2-private.h -cairo_os2_sources = cairo-os2-surface.c - -# automake is stupid enough to always use c++ linker if we enable the -# following lines, even if beos surface is not enabled. Disable it for now. -cairo_beos_headers = cairo-beos.h -cairo_beos_cxx_sources = cairo-beos-surface.cpp -cairo_gl_headers = cairo-gl.h -cairo_gl_private = cairo-gl-private.h \ - cairo-gl-dispatch-private.h \ - cairo-gl-ext-def-private.h \ - cairo-gl-gradient-private.h - -cairo_gl_sources = cairo-gl-composite.c \ - cairo-gl-device.c \ - cairo-gl-dispatch.c \ - cairo-gl-glyphs.c \ - cairo-gl-gradient.c \ - cairo-gl-info.c \ - cairo-gl-msaa-compositor.c \ - cairo-gl-operand.c \ - cairo-gl-shaders.c \ - cairo-gl-source.c \ - cairo-gl-spans-compositor.c \ - cairo-gl-surface.c \ - cairo-gl-traps-compositor.c - -cairo_glesv2_headers = $(cairo_gl_headers) -cairo_glesv2_private = $(cairo_gl_private) -cairo_glesv2_sources = $(cairo_gl_sources) -cairo_glesv3_headers = $(cairo_gl_headers) -cairo_glesv3_private = $(cairo_gl_private) -cairo_glesv3_sources = $(cairo_gl_sources) -cairo_directfb_headers = cairo-directfb.h -cairo_directfb_sources = cairo-directfb-surface.c -cairo_drm_headers = cairo-drm.h -cairo_drm_private = drm/cairo-drm-private.h \ - drm/cairo-drm-intel-private.h \ - drm/cairo-drm-intel-brw-defines.h \ - drm/cairo-drm-intel-brw-structs.h \ - drm/cairo-drm-intel-brw-eu.h \ - drm/cairo-drm-intel-command-private.h \ - drm/cairo-drm-intel-ioctl-private.h \ - drm/cairo-drm-i915-private.h \ - drm/cairo-drm-i965-private.h \ - drm/cairo-drm-radeon-private.h - -cairo_drm_sources = drm/cairo-drm.c \ - drm/cairo-drm-bo.c \ - drm/cairo-drm-surface.c \ - drm/cairo-drm-intel.c \ - drm/cairo-drm-intel-debug.c \ - drm/cairo-drm-intel-surface.c \ - drm/cairo-drm-i915-surface.c \ - drm/cairo-drm-i915-glyphs.c \ - drm/cairo-drm-i915-shader.c \ - drm/cairo-drm-i915-spans.c \ - drm/cairo-drm-i965-surface.c \ - drm/cairo-drm-i965-glyphs.c \ - drm/cairo-drm-i965-shader.c \ - drm/cairo-drm-i965-spans.c \ - drm/cairo-drm-intel-brw-eu.c \ - drm/cairo-drm-intel-brw-eu-emit.c \ - drm/cairo-drm-intel-brw-eu-util.c \ - drm/cairo-drm-radeon.c \ - drm/cairo-drm-radeon-surface.c - -cairo_gallium_sources = drm/cairo-drm-gallium-surface.c -cairo_script_headers = cairo-script.h -cairo_script_private = cairo-script-private.h -cairo_script_sources = cairo-script-surface.c -cairo_tee_headers = cairo-tee.h -cairo_tee_private = cairo-tee-surface-private.h -cairo_tee_sources = cairo-tee-surface.c -cairo_xml_headers = cairo-xml.h -cairo_xml_sources = cairo-xml-surface.c -cairo_vg_headers = cairo-vg.h -cairo_vg_sources = cairo-vg-surface.c -cairo_cogl_headers = cairo-cogl.h -cairo_cogl_private = cairo-cogl-private.h \ - cairo-cogl-gradient-private.h - -cairo_cogl_sources = cairo-cogl-surface.c \ - cairo-cogl-gradient.c - -supported_cairo_headers = $(cairo_headers) $(cairo_xlib_headers) \ - $(cairo_xlib_xrender_headers) $(cairo_xcb_headers) \ - $(cairo_xcb_shm_headers) $(cairo_quartz_headers) \ - $(cairo_quartz_font_headers) $(cairo_win32_headers) \ - $(cairo_win32_font_headers) $(cairo_png_headers) \ - $(cairo_egl_headers) $(cairo_glx_headers) $(cairo_wgl_headers) \ - $(cairo_script_headers) $(cairo_ft_headers) \ - $(cairo_fc_headers) $(cairo_ps_headers) $(cairo_pdf_headers) \ - $(cairo_svg_headers) $(cairo_image_headers) \ - $(cairo_mime_headers) $(cairo_recording_headers) \ - $(cairo_observer_headers) $(cairo_user_headers) \ - $(cairo_gobject_headers) -unsupported_cairo_headers = $(cairo_xlib_xcb_headers) \ - $(cairo_qt_headers) $(cairo_quartz_image_headers) \ - $(cairo_os2_headers) $(cairo_beos_headers) \ - $(cairo_drm_headers) $(cairo_gallium_headers) \ - $(cairo_gl_headers) $(cairo_glesv2_headers) \ - $(cairo_glesv3_headers) $(cairo_cogl_headers) \ - $(cairo_directfb_headers) $(cairo_vg_headers) \ - $(cairo_tee_headers) $(cairo_xml_headers) -all_cairo_headers = $(cairo_headers) $(cairo_xlib_headers) \ - $(cairo_xlib_xrender_headers) $(cairo_xcb_headers) \ - $(cairo_xlib_xcb_headers) $(cairo_xcb_shm_headers) \ - $(cairo_qt_headers) $(cairo_quartz_headers) \ - $(cairo_quartz_font_headers) $(cairo_quartz_image_headers) \ - $(cairo_win32_headers) $(cairo_win32_font_headers) \ - $(cairo_os2_headers) $(cairo_beos_headers) \ - $(cairo_drm_headers) $(cairo_gallium_headers) \ - $(cairo_png_headers) $(cairo_gl_headers) \ - $(cairo_glesv2_headers) $(cairo_glesv3_headers) \ - $(cairo_cogl_headers) $(cairo_directfb_headers) \ - $(cairo_vg_headers) $(cairo_egl_headers) $(cairo_glx_headers) \ - $(cairo_wgl_headers) $(cairo_script_headers) \ - $(cairo_ft_headers) $(cairo_fc_headers) $(cairo_ps_headers) \ - $(cairo_pdf_headers) $(cairo_svg_headers) \ - $(cairo_image_headers) $(cairo_mime_headers) \ - $(cairo_recording_headers) $(cairo_observer_headers) \ - $(cairo_tee_headers) $(cairo_xml_headers) \ - $(cairo_user_headers) $(cairo_gobject_headers) -all_cairo_private = $(cairo_private) $(cairo_xlib_private) \ - $(cairo_xlib_xrender_private) $(cairo_xcb_private) \ - $(cairo_xlib_xcb_private) $(cairo_xcb_shm_private) \ - $(cairo_qt_private) $(cairo_quartz_private) \ - $(cairo_quartz_font_private) $(cairo_quartz_image_private) \ - $(cairo_win32_private) $(cairo_win32_font_private) \ - $(cairo_os2_private) $(cairo_beos_private) \ - $(cairo_drm_private) $(cairo_gallium_private) \ - $(cairo_png_private) $(cairo_gl_private) \ - $(cairo_glesv2_private) $(cairo_glesv3_private) \ - $(cairo_cogl_private) $(cairo_directfb_private) \ - $(cairo_vg_private) $(cairo_egl_private) $(cairo_glx_private) \ - $(cairo_wgl_private) $(cairo_script_private) \ - $(cairo_ft_private) $(cairo_fc_private) $(cairo_ps_private) \ - $(cairo_pdf_private) $(cairo_svg_private) \ - $(cairo_test_surfaces_private) $(cairo_test_surfaces_headers) \ - $(cairo_image_private) $(cairo_mime_private) \ - $(cairo_recording_private) $(cairo_observer_private) \ - $(cairo_tee_private) $(cairo_xml_private) \ - $(cairo_user_private) $(cairo_pthread_private) \ - $(cairo_pthread_headers) $(cairo_gobject_private) \ - $(cairo_trace_private) $(cairo_trace_headers) \ - $(cairo_interpreter_private) $(cairo_interpreter_headers) \ - $(cairo_symbol_lookup_private) $(cairo_symbol_lookup_headers) -all_cairo_cxx_sources = $(cairo_cxx_sources) $(cairo_xlib_cxx_sources) \ - $(cairo_xlib_xrender_cxx_sources) $(cairo_xcb_cxx_sources) \ - $(cairo_xlib_xcb_cxx_sources) $(cairo_xcb_shm_cxx_sources) \ - $(cairo_qt_cxx_sources) $(cairo_quartz_cxx_sources) \ - $(cairo_quartz_font_cxx_sources) \ - $(cairo_quartz_image_cxx_sources) $(cairo_win32_cxx_sources) \ - $(cairo_win32_font_cxx_sources) $(cairo_os2_cxx_sources) \ - $(cairo_beos_cxx_sources) $(cairo_drm_cxx_sources) \ - $(cairo_gallium_cxx_sources) $(cairo_png_cxx_sources) \ - $(cairo_gl_cxx_sources) $(cairo_glesv2_cxx_sources) \ - $(cairo_glesv3_cxx_sources) $(cairo_cogl_cxx_sources) \ - $(cairo_directfb_cxx_sources) $(cairo_vg_cxx_sources) \ - $(cairo_egl_cxx_sources) $(cairo_glx_cxx_sources) \ - $(cairo_wgl_cxx_sources) $(cairo_script_cxx_sources) \ - $(cairo_ft_cxx_sources) $(cairo_fc_cxx_sources) \ - $(cairo_ps_cxx_sources) $(cairo_pdf_cxx_sources) \ - $(cairo_svg_cxx_sources) $(cairo_test_surfaces_cxx_sources) \ - $(cairo_image_cxx_sources) $(cairo_mime_cxx_sources) \ - $(cairo_recording_cxx_sources) $(cairo_observer_cxx_sources) \ - $(cairo_tee_cxx_sources) $(cairo_xml_cxx_sources) \ - $(cairo_user_cxx_sources) $(cairo_pthread_cxx_sources) \ - $(cairo_gobject_cxx_sources) $(cairo_trace_cxx_sources) \ - $(cairo_interpreter_cxx_sources) \ - $(cairo_symbol_lookup_cxx_sources) -all_cairo_sources = $(cairo_sources) $(cairo_xlib_sources) \ - $(cairo_xlib_xrender_sources) $(cairo_xcb_sources) \ - $(cairo_xlib_xcb_sources) $(cairo_xcb_shm_sources) \ - $(cairo_qt_sources) $(cairo_quartz_sources) \ - $(cairo_quartz_font_sources) $(cairo_quartz_image_sources) \ - $(cairo_win32_sources) $(cairo_win32_font_sources) \ - $(cairo_os2_sources) $(cairo_beos_sources) \ - $(cairo_drm_sources) $(cairo_gallium_sources) \ - $(cairo_png_sources) $(cairo_gl_sources) \ - $(cairo_glesv2_sources) $(cairo_glesv3_sources) \ - $(cairo_cogl_sources) $(cairo_directfb_sources) \ - $(cairo_vg_sources) $(cairo_egl_sources) $(cairo_glx_sources) \ - $(cairo_wgl_sources) $(cairo_script_sources) \ - $(cairo_ft_sources) $(cairo_fc_sources) $(cairo_ps_sources) \ - $(cairo_pdf_sources) $(cairo_svg_sources) \ - $(cairo_test_surfaces_sources) $(cairo_image_sources) \ - $(cairo_mime_sources) $(cairo_recording_sources) \ - $(cairo_observer_sources) $(cairo_tee_sources) \ - $(cairo_xml_sources) $(cairo_user_sources) \ - $(cairo_pthread_sources) $(cairo_gobject_sources) \ - $(cairo_trace_sources) $(cairo_interpreter_sources) \ - $(cairo_symbol_lookup_sources) -enabled_cairo_headers = $(cairo_headers) $(am__append_1) \ - $(am__append_6) $(am__append_11) $(am__append_16) \ - $(am__append_21) $(am__append_26) $(am__append_31) \ - $(am__append_36) $(am__append_41) $(am__append_46) \ - $(am__append_51) $(am__append_56) $(am__append_61) \ - $(am__append_66) $(am__append_71) $(am__append_76) \ - $(am__append_81) $(am__append_86) $(am__append_91) \ - $(am__append_96) $(am__append_101) $(am__append_106) \ - $(am__append_111) $(am__append_116) $(am__append_121) \ - $(am__append_126) $(am__append_131) $(am__append_136) \ - $(am__append_141) $(am__append_146) $(am__append_151) \ - $(cairo_image_headers) $(cairo_mime_headers) \ - $(cairo_recording_headers) $(cairo_observer_headers) \ - $(am__append_159) $(am__append_164) $(cairo_user_headers) \ - $(am__append_172) -enabled_cairo_private = $(cairo_private) $(am__append_2) \ - $(am__append_7) $(am__append_12) $(am__append_17) \ - $(am__append_22) $(am__append_27) $(am__append_32) \ - $(am__append_37) $(am__append_42) $(am__append_47) \ - $(am__append_52) $(am__append_57) $(am__append_62) \ - $(am__append_67) $(am__append_72) $(am__append_77) \ - $(am__append_82) $(am__append_87) $(am__append_92) \ - $(am__append_97) $(am__append_102) $(am__append_107) \ - $(am__append_112) $(am__append_117) $(am__append_122) \ - $(am__append_127) $(am__append_132) $(am__append_137) \ - $(am__append_142) $(am__append_147) $(am__append_152) \ - $(am__append_156) $(cairo_image_private) $(cairo_mime_private) \ - $(cairo_recording_private) $(cairo_observer_private) \ - $(am__append_160) $(am__append_165) $(cairo_user_private) \ - $(am__append_169) $(am__append_173) $(am__append_177) \ - $(am__append_180) $(am__append_183) -enabled_cairo_cxx_sources = $(cairo_cxx_sources) $(am__append_3) \ - $(am__append_8) $(am__append_13) $(am__append_18) \ - $(am__append_23) $(am__append_28) $(am__append_33) \ - $(am__append_38) $(am__append_43) $(am__append_48) \ - $(am__append_53) $(am__append_58) $(am__append_63) \ - $(am__append_68) $(am__append_73) $(am__append_78) \ - $(am__append_83) $(am__append_88) $(am__append_93) \ - $(am__append_98) $(am__append_103) $(am__append_108) \ - $(am__append_113) $(am__append_118) $(am__append_123) \ - $(am__append_128) $(am__append_133) $(am__append_138) \ - $(am__append_143) $(am__append_148) $(am__append_153) \ - $(am__append_157) $(cairo_image_cxx_sources) \ - $(cairo_mime_cxx_sources) $(cairo_recording_cxx_sources) \ - $(cairo_observer_cxx_sources) $(am__append_161) \ - $(am__append_166) $(cairo_user_cxx_sources) $(am__append_170) \ - $(am__append_174) $(am__append_178) $(am__append_181) \ - $(am__append_184) -enabled_cairo_sources = $(cairo_sources) $(am__append_4) \ - $(am__append_9) $(am__append_14) $(am__append_19) \ - $(am__append_24) $(am__append_29) $(am__append_34) \ - $(am__append_39) $(am__append_44) $(am__append_49) \ - $(am__append_54) $(am__append_59) $(am__append_64) \ - $(am__append_69) $(am__append_74) $(am__append_79) \ - $(am__append_84) $(am__append_89) $(am__append_94) \ - $(am__append_99) $(am__append_104) $(am__append_109) \ - $(am__append_114) $(am__append_119) $(am__append_124) \ - $(am__append_129) $(am__append_134) $(am__append_139) \ - $(am__append_144) $(am__append_149) $(am__append_154) \ - $(am__append_158) $(cairo_image_sources) $(cairo_mime_sources) \ - $(cairo_recording_sources) $(cairo_observer_sources) \ - $(am__append_162) $(am__append_167) $(cairo_user_sources) \ - $(am__append_171) $(am__append_175) $(am__append_179) \ - $(am__append_182) $(am__append_185) -all_cairo_pkgconf = cairo.pc cairo-xlib.pc cairo-xlib-xrender.pc \ - cairo-xcb.pc cairo-xlib-xcb.pc cairo-xcb-shm.pc cairo-qt.pc \ - cairo-quartz.pc cairo-quartz-font.pc cairo-quartz-image.pc \ - cairo-win32.pc cairo-win32-font.pc cairo-os2.pc cairo-beos.pc \ - cairo-drm.pc cairo-gallium.pc cairo-png.pc cairo-gl.pc \ - cairo-glesv2.pc cairo-glesv3.pc cairo-cogl.pc \ - cairo-directfb.pc cairo-vg.pc cairo-egl.pc cairo-glx.pc \ - cairo-wgl.pc cairo-script.pc cairo-ft.pc cairo-fc.pc \ - cairo-ps.pc cairo-pdf.pc cairo-svg.pc cairo-tee.pc \ - cairo-xml.pc cairo-gobject.pc -enabled_cairo_pkgconf = cairo.pc $(am__append_5) $(am__append_10) \ - $(am__append_15) $(am__append_20) $(am__append_25) \ - $(am__append_30) $(am__append_35) $(am__append_40) \ - $(am__append_45) $(am__append_50) $(am__append_55) \ - $(am__append_60) $(am__append_65) $(am__append_70) \ - $(am__append_75) $(am__append_80) $(am__append_85) \ - $(am__append_90) $(am__append_95) $(am__append_100) \ - $(am__append_105) $(am__append_110) $(am__append_115) \ - $(am__append_120) $(am__append_125) $(am__append_130) \ - $(am__append_135) $(am__append_140) $(am__append_145) \ - $(am__append_150) $(am__append_155) $(am__append_163) \ - $(am__append_168) $(am__append_176) -#MAINTAINERCLEANFILES += $(srcdir)/Makefile.win32.features -AM_CPPFLAGS = -I$(srcdir) $(CAIRO_CFLAGS) -AM_LDFLAGS = $(CAIRO_LDFLAGS) -@OS_WIN32_TRUE@export_symbols = -export-symbols cairo.def -@OS_WIN32_TRUE@cairo_def_dependency = cairo.def -cairoincludedir = $(includedir)/cairo -cairoinclude_HEADERS = $(enabled_cairo_headers) -lib_LTLIBRARIES = libcairo.la -@BUILD_CXX_FALSE@cairo_cxx_lib = -@BUILD_CXX_TRUE@cairo_cxx_lib = libcairo_cxx.la -noinst_LTLIBRARIES = $(cairo_cxx_lib) -libcairo_cxx_la_SOURCES = \ - $(enabled_cairo_headers) \ - $(enabled_cairo_private) \ - $(enabled_cairo_cxx_sources) \ - $(NULL) - -libcairo_cxx_la_LDFLAGS = $(AM_LDFLAGS) $(export_symbols) -libcairo_cxx_la_LIBADD = $(CAIRO_LIBS) -libcairo_cxx_la_DEPENDENCIES = $(cairo_def_dependency) -libcairo_la_SOURCES = \ - $(enabled_cairo_headers) \ - $(enabled_cairo_private) \ - $(enabled_cairo_sources) \ - $(NULL) - -libcairo_la_LDFLAGS = $(AM_LDFLAGS) -version-info $(CAIRO_LIBTOOL_VERSION_INFO) -no-undefined $(export_symbols) -libcairo_la_LIBADD = $(CAIRO_LIBS) \ - $(cairo_cxx_lib) - -libcairo_la_DEPENDENCIES = $(cairo_def_dependency) $(cairo_cxx_lib) - -# Special headers -nodist_cairoinclude_HEADERS = cairo-features.h -nodist_libcairo_la_SOURCES = cairo-features.h -pkgconfigdir = $(libdir)/pkgconfig -pkgconfig_DATA = $(enabled_cairo_pkgconf) -TESTS_ENVIRONMENT = \ - srcdir="$(srcdir)" \ - MAKE="$(MAKE) $(AM_MAKEFLAGS)" \ - all_cairo_files="$(all_cairo_files)" \ - all_cairo_headers="$(all_cairo_headers)" \ - all_cairo_private="$(all_cairo_private)" \ - all_cairo_sources="$(all_cairo_sources)" \ - enabled_cairo_headers="$(enabled_cairo_headers)" \ - enabled_cairo_private="$(enabled_cairo_private)" \ - enabled_cairo_sources="$(enabled_cairo_sources)" \ - $(NULL) - -TESTS_SH = \ - check-def.sh \ - check-doc-syntax.sh \ - check-headers.sh \ - check-plt.sh \ - check-preprocessor-syntax.sh \ - $(NULL) - -check_link_LDADD = libcairo.la -PREPROCESS_ARGS = $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) -COMPILE_ARGS = $(PREPROCESS_ARGS) $(AM_CFLAGS) $(CFLAGS) -SPARSE = sparse -SPLINT = splint -badflag -UNO = uno -all: $(BUILT_SOURCES) - $(MAKE) $(AM_MAKEFLAGS) all-am - -.SUFFIXES: -.SUFFIXES: .c .cpp .i .lo .log .o .obj .s .test .test$(EXEEXT) .trs -$(srcdir)/Makefile.in: $(srcdir)/Makefile.am $(top_srcdir)/build/Makefile.am.common $(srcdir)/Makefile.am.features $(top_srcdir)/src/Makefile.sources $(srcdir)/Makefile.am.analysis $(am__configure_deps) - @for dep in $?; do \ - case '$(am__configure_deps)' in \ - *$$dep*) \ - ( cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh ) \ - && { if test -f $@; then exit 0; else break; fi; }; \ - exit 1;; \ - esac; \ - done; \ - echo ' cd $(top_srcdir) && $(AUTOMAKE) --foreign src/Makefile'; \ - $(am__cd) $(top_srcdir) && \ - $(AUTOMAKE) --foreign src/Makefile -Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status - @case '$?' in \ - *config.status*) \ - cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \ - *) \ - echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__maybe_remake_depfiles)'; \ - cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__maybe_remake_depfiles);; \ - esac; -$(top_srcdir)/build/Makefile.am.common $(srcdir)/Makefile.am.features $(top_srcdir)/src/Makefile.sources $(srcdir)/Makefile.am.analysis $(am__empty): - -$(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES) - cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh - -$(top_srcdir)/configure: $(am__configure_deps) - cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh -$(ACLOCAL_M4): $(am__aclocal_m4_deps) - cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh -$(am__aclocal_m4_deps): -cairo.pc: $(top_builddir)/config.status $(srcdir)/cairo.pc.in - cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ -cairo-xlib.pc: $(top_builddir)/config.status $(srcdir)/cairo-features.pc.in - cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ -cairo-xlib-xrender.pc: $(top_builddir)/config.status $(srcdir)/cairo-features.pc.in - cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ -cairo-xcb.pc: $(top_builddir)/config.status $(srcdir)/cairo-features.pc.in - cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ -cairo-xlib-xcb.pc: $(top_builddir)/config.status $(srcdir)/cairo-features.pc.in - cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ -cairo-xcb-shm.pc: $(top_builddir)/config.status $(srcdir)/cairo-features.pc.in - cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ -cairo-qt.pc: $(top_builddir)/config.status $(srcdir)/cairo-features.pc.in - cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ -cairo-quartz.pc: $(top_builddir)/config.status $(srcdir)/cairo-features.pc.in - cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ -cairo-quartz-font.pc: $(top_builddir)/config.status $(srcdir)/cairo-features.pc.in - cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ -cairo-quartz-image.pc: $(top_builddir)/config.status $(srcdir)/cairo-features.pc.in - cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ -cairo-win32.pc: $(top_builddir)/config.status $(srcdir)/cairo-features.pc.in - cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ -cairo-win32-font.pc: $(top_builddir)/config.status $(srcdir)/cairo-features.pc.in - cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ -cairo-os2.pc: $(top_builddir)/config.status $(srcdir)/cairo-features.pc.in - cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ -cairo-beos.pc: $(top_builddir)/config.status $(srcdir)/cairo-features.pc.in - cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ -cairo-drm.pc: $(top_builddir)/config.status $(srcdir)/cairo-features.pc.in - cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ -cairo-gallium.pc: $(top_builddir)/config.status $(srcdir)/cairo-features.pc.in - cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ -cairo-png.pc: $(top_builddir)/config.status $(srcdir)/cairo-features.pc.in - cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ -cairo-gl.pc: $(top_builddir)/config.status $(srcdir)/cairo-features.pc.in - cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ -cairo-glesv2.pc: $(top_builddir)/config.status $(srcdir)/cairo-features.pc.in - cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ -cairo-glesv3.pc: $(top_builddir)/config.status $(srcdir)/cairo-features.pc.in - cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ -cairo-cogl.pc: $(top_builddir)/config.status $(srcdir)/cairo-features.pc.in - cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ -cairo-directfb.pc: $(top_builddir)/config.status $(srcdir)/cairo-features.pc.in - cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ -cairo-vg.pc: $(top_builddir)/config.status $(srcdir)/cairo-features.pc.in - cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ -cairo-egl.pc: $(top_builddir)/config.status $(srcdir)/cairo-features.pc.in - cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ -cairo-glx.pc: $(top_builddir)/config.status $(srcdir)/cairo-features.pc.in - cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ -cairo-wgl.pc: $(top_builddir)/config.status $(srcdir)/cairo-features.pc.in - cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ -cairo-script.pc: $(top_builddir)/config.status $(srcdir)/cairo-features.pc.in - cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ -cairo-ft.pc: $(top_builddir)/config.status $(srcdir)/cairo-features.pc.in - cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ -cairo-fc.pc: $(top_builddir)/config.status $(srcdir)/cairo-features.pc.in - cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ -cairo-ps.pc: $(top_builddir)/config.status $(srcdir)/cairo-features.pc.in - cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ -cairo-pdf.pc: $(top_builddir)/config.status $(srcdir)/cairo-features.pc.in - cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ -cairo-svg.pc: $(top_builddir)/config.status $(srcdir)/cairo-features.pc.in - cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ -cairo-tee.pc: $(top_builddir)/config.status $(srcdir)/cairo-features.pc.in - cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ -cairo-xml.pc: $(top_builddir)/config.status $(srcdir)/cairo-features.pc.in - cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ -cairo-gobject.pc: $(top_builddir)/config.status $(srcdir)/cairo-features.pc.in - cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ - -clean-checkPROGRAMS: - @list='$(check_PROGRAMS)'; test -n "$$list" || exit 0; \ - echo " rm -f" $$list; \ - rm -f $$list || exit $$?; \ - test -n "$(EXEEXT)" || exit 0; \ - list=`for p in $$list; do echo "$$p"; done | sed 's/$(EXEEXT)$$//'`; \ - echo " rm -f" $$list; \ - rm -f $$list - -install-libLTLIBRARIES: $(lib_LTLIBRARIES) - @$(NORMAL_INSTALL) - @list='$(lib_LTLIBRARIES)'; test -n "$(libdir)" || list=; \ - list2=; for p in $$list; do \ - if test -f $$p; then \ - list2="$$list2 $$p"; \ - else :; fi; \ - done; \ - test -z "$$list2" || { \ - echo " $(MKDIR_P) '$(DESTDIR)$(libdir)'"; \ - $(MKDIR_P) "$(DESTDIR)$(libdir)" || exit 1; \ - echo " $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL) $(INSTALL_STRIP_FLAG) $$list2 '$(DESTDIR)$(libdir)'"; \ - $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL) $(INSTALL_STRIP_FLAG) $$list2 "$(DESTDIR)$(libdir)"; \ - } - -uninstall-libLTLIBRARIES: - @$(NORMAL_UNINSTALL) - @list='$(lib_LTLIBRARIES)'; test -n "$(libdir)" || list=; \ - for p in $$list; do \ - $(am__strip_dir) \ - echo " $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=uninstall rm -f '$(DESTDIR)$(libdir)/$$f'"; \ - $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=uninstall rm -f "$(DESTDIR)$(libdir)/$$f"; \ - done - -clean-libLTLIBRARIES: - -test -z "$(lib_LTLIBRARIES)" || rm -f $(lib_LTLIBRARIES) - @list='$(lib_LTLIBRARIES)'; \ - locs=`for p in $$list; do echo $$p; done | \ - sed 's|^[^/]*$$|.|; s|/[^/]*$$||; s|$$|/so_locations|' | \ - sort -u`; \ - test -z "$$locs" || { \ - echo rm -f $${locs}; \ - rm -f $${locs}; \ - } - -clean-noinstLTLIBRARIES: - -test -z "$(noinst_LTLIBRARIES)" || rm -f $(noinst_LTLIBRARIES) - @list='$(noinst_LTLIBRARIES)'; \ - locs=`for p in $$list; do echo $$p; done | \ - sed 's|^[^/]*$$|.|; s|/[^/]*$$||; s|$$|/so_locations|' | \ - sort -u`; \ - test -z "$$locs" || { \ - echo rm -f $${locs}; \ - rm -f $${locs}; \ - } - -libcairo.la: $(libcairo_la_OBJECTS) $(libcairo_la_DEPENDENCIES) $(EXTRA_libcairo_la_DEPENDENCIES) - $(AM_V_CCLD)$(libcairo_la_LINK) -rpath $(libdir) $(libcairo_la_OBJECTS) $(libcairo_la_LIBADD) $(LIBS) - -libcairo_cxx.la: $(libcairo_cxx_la_OBJECTS) $(libcairo_cxx_la_DEPENDENCIES) $(EXTRA_libcairo_cxx_la_DEPENDENCIES) - $(AM_V_CXXLD)$(libcairo_cxx_la_LINK) $(am_libcairo_cxx_la_rpath) $(libcairo_cxx_la_OBJECTS) $(libcairo_cxx_la_LIBADD) $(LIBS) - -check-link$(EXEEXT): $(check_link_OBJECTS) $(check_link_DEPENDENCIES) $(EXTRA_check_link_DEPENDENCIES) - @rm -f check-link$(EXEEXT) - $(AM_V_CCLD)$(LINK) $(check_link_OBJECTS) $(check_link_LDADD) $(LIBS) - -mostlyclean-compile: - -rm -f *.$(OBJEXT) - -distclean-compile: - -rm -f *.tab.c - -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/cairo-analysis-surface.Plo@am__quote@ # am--include-marker -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/cairo-arc.Plo@am__quote@ # am--include-marker -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/cairo-array.Plo@am__quote@ # am--include-marker -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/cairo-atomic.Plo@am__quote@ # am--include-marker -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/cairo-base64-stream.Plo@am__quote@ # am--include-marker -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/cairo-base85-stream.Plo@am__quote@ # am--include-marker -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/cairo-bentley-ottmann-rectangular.Plo@am__quote@ # am--include-marker -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/cairo-bentley-ottmann-rectilinear.Plo@am__quote@ # am--include-marker -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/cairo-bentley-ottmann.Plo@am__quote@ # am--include-marker -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/cairo-beos-surface.Plo@am__quote@ # am--include-marker -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/cairo-botor-scan-converter.Plo@am__quote@ # am--include-marker -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/cairo-boxes-intersect.Plo@am__quote@ # am--include-marker -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/cairo-boxes.Plo@am__quote@ # am--include-marker -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/cairo-cache.Plo@am__quote@ # am--include-marker -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/cairo-cff-subset.Plo@am__quote@ # am--include-marker -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/cairo-clip-boxes.Plo@am__quote@ # am--include-marker -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/cairo-clip-polygon.Plo@am__quote@ # am--include-marker -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/cairo-clip-region.Plo@am__quote@ # am--include-marker -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/cairo-clip-surface.Plo@am__quote@ # am--include-marker -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/cairo-clip-tor-scan-converter.Plo@am__quote@ # am--include-marker -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/cairo-clip.Plo@am__quote@ # am--include-marker -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/cairo-cogl-gradient.Plo@am__quote@ # am--include-marker -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/cairo-cogl-surface.Plo@am__quote@ # am--include-marker -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/cairo-color.Plo@am__quote@ # am--include-marker -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/cairo-composite-rectangles.Plo@am__quote@ # am--include-marker -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/cairo-compositor.Plo@am__quote@ # am--include-marker -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/cairo-contour.Plo@am__quote@ # am--include-marker -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/cairo-damage.Plo@am__quote@ # am--include-marker -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/cairo-debug.Plo@am__quote@ # am--include-marker -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/cairo-default-context.Plo@am__quote@ # am--include-marker -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/cairo-deflate-stream.Plo@am__quote@ # am--include-marker -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/cairo-device.Plo@am__quote@ # am--include-marker -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/cairo-directfb-surface.Plo@am__quote@ # am--include-marker -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/cairo-drm-bo.Plo@am__quote@ # am--include-marker -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/cairo-drm-gallium-surface.Plo@am__quote@ # am--include-marker -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/cairo-drm-i915-glyphs.Plo@am__quote@ # am--include-marker -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/cairo-drm-i915-shader.Plo@am__quote@ # am--include-marker -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/cairo-drm-i915-spans.Plo@am__quote@ # am--include-marker -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/cairo-drm-i915-surface.Plo@am__quote@ # am--include-marker -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/cairo-drm-i965-glyphs.Plo@am__quote@ # am--include-marker -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/cairo-drm-i965-shader.Plo@am__quote@ # am--include-marker -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/cairo-drm-i965-spans.Plo@am__quote@ # am--include-marker -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/cairo-drm-i965-surface.Plo@am__quote@ # am--include-marker -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/cairo-drm-intel-brw-eu-emit.Plo@am__quote@ # am--include-marker -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/cairo-drm-intel-brw-eu-util.Plo@am__quote@ # am--include-marker -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/cairo-drm-intel-brw-eu.Plo@am__quote@ # am--include-marker -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/cairo-drm-intel-debug.Plo@am__quote@ # am--include-marker -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/cairo-drm-intel-surface.Plo@am__quote@ # am--include-marker -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/cairo-drm-intel.Plo@am__quote@ # am--include-marker -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/cairo-drm-radeon-surface.Plo@am__quote@ # am--include-marker -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/cairo-drm-radeon.Plo@am__quote@ # am--include-marker -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/cairo-drm-surface.Plo@am__quote@ # am--include-marker -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/cairo-drm.Plo@am__quote@ # am--include-marker -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/cairo-egl-context.Plo@am__quote@ # am--include-marker -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/cairo-error.Plo@am__quote@ # am--include-marker -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/cairo-fallback-compositor.Plo@am__quote@ # am--include-marker -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/cairo-fixed.Plo@am__quote@ # am--include-marker -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/cairo-font-face-twin-data.Plo@am__quote@ # am--include-marker -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/cairo-font-face-twin.Plo@am__quote@ # am--include-marker -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/cairo-font-face.Plo@am__quote@ # am--include-marker -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/cairo-font-options.Plo@am__quote@ # am--include-marker -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/cairo-freed-pool.Plo@am__quote@ # am--include-marker -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/cairo-freelist.Plo@am__quote@ # am--include-marker -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/cairo-ft-font.Plo@am__quote@ # am--include-marker -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/cairo-gl-composite.Plo@am__quote@ # am--include-marker -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/cairo-gl-device.Plo@am__quote@ # am--include-marker -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/cairo-gl-dispatch.Plo@am__quote@ # am--include-marker -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/cairo-gl-glyphs.Plo@am__quote@ # am--include-marker -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/cairo-gl-gradient.Plo@am__quote@ # am--include-marker -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/cairo-gl-info.Plo@am__quote@ # am--include-marker -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/cairo-gl-msaa-compositor.Plo@am__quote@ # am--include-marker -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/cairo-gl-operand.Plo@am__quote@ # am--include-marker -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/cairo-gl-shaders.Plo@am__quote@ # am--include-marker -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/cairo-gl-source.Plo@am__quote@ # am--include-marker -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/cairo-gl-spans-compositor.Plo@am__quote@ # am--include-marker -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/cairo-gl-surface.Plo@am__quote@ # am--include-marker -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/cairo-gl-traps-compositor.Plo@am__quote@ # am--include-marker -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/cairo-glx-context.Plo@am__quote@ # am--include-marker -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/cairo-gstate.Plo@am__quote@ # am--include-marker -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/cairo-hash.Plo@am__quote@ # am--include-marker -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/cairo-hull.Plo@am__quote@ # am--include-marker -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/cairo-image-compositor.Plo@am__quote@ # am--include-marker -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/cairo-image-info.Plo@am__quote@ # am--include-marker -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/cairo-image-source.Plo@am__quote@ # am--include-marker -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/cairo-image-surface.Plo@am__quote@ # am--include-marker -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/cairo-line.Plo@am__quote@ # am--include-marker -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/cairo-lzw.Plo@am__quote@ # am--include-marker -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/cairo-mask-compositor.Plo@am__quote@ # am--include-marker -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/cairo-matrix.Plo@am__quote@ # am--include-marker -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/cairo-mempool.Plo@am__quote@ # am--include-marker -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/cairo-mesh-pattern-rasterizer.Plo@am__quote@ # am--include-marker -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/cairo-misc.Plo@am__quote@ # am--include-marker -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/cairo-mono-scan-converter.Plo@am__quote@ # am--include-marker -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/cairo-mutex.Plo@am__quote@ # am--include-marker -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/cairo-no-compositor.Plo@am__quote@ # am--include-marker -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/cairo-observer.Plo@am__quote@ # am--include-marker -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/cairo-os2-surface.Plo@am__quote@ # am--include-marker -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/cairo-output-stream.Plo@am__quote@ # am--include-marker -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/cairo-paginated-surface.Plo@am__quote@ # am--include-marker -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/cairo-path-bounds.Plo@am__quote@ # am--include-marker -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/cairo-path-fill.Plo@am__quote@ # am--include-marker -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/cairo-path-fixed.Plo@am__quote@ # am--include-marker -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/cairo-path-in-fill.Plo@am__quote@ # am--include-marker -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/cairo-path-stroke-boxes.Plo@am__quote@ # am--include-marker -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/cairo-path-stroke-polygon.Plo@am__quote@ # am--include-marker -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/cairo-path-stroke-traps.Plo@am__quote@ # am--include-marker -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/cairo-path-stroke-tristrip.Plo@am__quote@ # am--include-marker -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/cairo-path-stroke.Plo@am__quote@ # am--include-marker -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/cairo-path.Plo@am__quote@ # am--include-marker -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/cairo-pattern.Plo@am__quote@ # am--include-marker -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/cairo-pdf-interchange.Plo@am__quote@ # am--include-marker -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/cairo-pdf-operators.Plo@am__quote@ # am--include-marker -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/cairo-pdf-shading.Plo@am__quote@ # am--include-marker -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/cairo-pdf-surface.Plo@am__quote@ # am--include-marker -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/cairo-pen.Plo@am__quote@ # am--include-marker -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/cairo-png.Plo@am__quote@ # am--include-marker -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/cairo-polygon-intersect.Plo@am__quote@ # am--include-marker -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/cairo-polygon-reduce.Plo@am__quote@ # am--include-marker -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/cairo-polygon.Plo@am__quote@ # am--include-marker -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/cairo-ps-surface.Plo@am__quote@ # am--include-marker -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/cairo-qt-surface.Plo@am__quote@ # am--include-marker -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/cairo-quartz-font.Plo@am__quote@ # am--include-marker -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/cairo-quartz-image-surface.Plo@am__quote@ # am--include-marker -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/cairo-quartz-surface.Plo@am__quote@ # am--include-marker -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/cairo-raster-source-pattern.Plo@am__quote@ # am--include-marker -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/cairo-recording-surface.Plo@am__quote@ # am--include-marker -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/cairo-rectangle.Plo@am__quote@ # am--include-marker -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/cairo-rectangular-scan-converter.Plo@am__quote@ # am--include-marker -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/cairo-region.Plo@am__quote@ # am--include-marker -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/cairo-rtree.Plo@am__quote@ # am--include-marker -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/cairo-scaled-font-subsets.Plo@am__quote@ # am--include-marker -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/cairo-scaled-font.Plo@am__quote@ # am--include-marker -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/cairo-script-surface.Plo@am__quote@ # am--include-marker -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/cairo-shape-mask-compositor.Plo@am__quote@ # am--include-marker -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/cairo-slope.Plo@am__quote@ # am--include-marker -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/cairo-spans-compositor.Plo@am__quote@ # am--include-marker -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/cairo-spans.Plo@am__quote@ # am--include-marker -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/cairo-spline.Plo@am__quote@ # am--include-marker -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/cairo-stroke-dash.Plo@am__quote@ # am--include-marker -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/cairo-stroke-style.Plo@am__quote@ # am--include-marker -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/cairo-surface-clipper.Plo@am__quote@ # am--include-marker -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/cairo-surface-fallback.Plo@am__quote@ # am--include-marker -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/cairo-surface-observer.Plo@am__quote@ # am--include-marker -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/cairo-surface-offset.Plo@am__quote@ # am--include-marker -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/cairo-surface-snapshot.Plo@am__quote@ # am--include-marker -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/cairo-surface-subsurface.Plo@am__quote@ # am--include-marker -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/cairo-surface-wrapper.Plo@am__quote@ # am--include-marker -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/cairo-surface.Plo@am__quote@ # am--include-marker -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/cairo-svg-surface.Plo@am__quote@ # am--include-marker -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/cairo-tag-attributes.Plo@am__quote@ # am--include-marker -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/cairo-tag-stack.Plo@am__quote@ # am--include-marker -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/cairo-tee-surface.Plo@am__quote@ # am--include-marker -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/cairo-time.Plo@am__quote@ # am--include-marker -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/cairo-tor-scan-converter.Plo@am__quote@ # am--include-marker -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/cairo-tor22-scan-converter.Plo@am__quote@ # am--include-marker -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/cairo-toy-font-face.Plo@am__quote@ # am--include-marker -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/cairo-traps-compositor.Plo@am__quote@ # am--include-marker -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/cairo-traps.Plo@am__quote@ # am--include-marker -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/cairo-tristrip.Plo@am__quote@ # am--include-marker -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/cairo-truetype-subset.Plo@am__quote@ # am--include-marker -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/cairo-type1-fallback.Plo@am__quote@ # am--include-marker -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/cairo-type1-glyph-names.Plo@am__quote@ # am--include-marker -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/cairo-type1-subset.Plo@am__quote@ # am--include-marker -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/cairo-type3-glyph-surface.Plo@am__quote@ # am--include-marker -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/cairo-unicode.Plo@am__quote@ # am--include-marker -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/cairo-user-font.Plo@am__quote@ # am--include-marker -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/cairo-version.Plo@am__quote@ # am--include-marker -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/cairo-vg-surface.Plo@am__quote@ # am--include-marker -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/cairo-wgl-context.Plo@am__quote@ # am--include-marker -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/cairo-wideint.Plo@am__quote@ # am--include-marker -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/cairo-win32-debug.Plo@am__quote@ # am--include-marker -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/cairo-win32-device.Plo@am__quote@ # am--include-marker -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/cairo-win32-display-surface.Plo@am__quote@ # am--include-marker -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/cairo-win32-font.Plo@am__quote@ # am--include-marker -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/cairo-win32-gdi-compositor.Plo@am__quote@ # am--include-marker -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/cairo-win32-printing-surface.Plo@am__quote@ # am--include-marker -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/cairo-win32-surface.Plo@am__quote@ # am--include-marker -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/cairo-win32-system.Plo@am__quote@ # am--include-marker -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/cairo-xcb-connection-core.Plo@am__quote@ # am--include-marker -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/cairo-xcb-connection-render.Plo@am__quote@ # am--include-marker -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/cairo-xcb-connection-shm.Plo@am__quote@ # am--include-marker -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/cairo-xcb-connection.Plo@am__quote@ # am--include-marker -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/cairo-xcb-resources.Plo@am__quote@ # am--include-marker -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/cairo-xcb-screen.Plo@am__quote@ # am--include-marker -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/cairo-xcb-shm.Plo@am__quote@ # am--include-marker -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/cairo-xcb-surface-core.Plo@am__quote@ # am--include-marker -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/cairo-xcb-surface-render.Plo@am__quote@ # am--include-marker -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/cairo-xcb-surface.Plo@am__quote@ # am--include-marker -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/cairo-xlib-core-compositor.Plo@am__quote@ # am--include-marker -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/cairo-xlib-display.Plo@am__quote@ # am--include-marker -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/cairo-xlib-fallback-compositor.Plo@am__quote@ # am--include-marker -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/cairo-xlib-render-compositor.Plo@am__quote@ # am--include-marker -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/cairo-xlib-screen.Plo@am__quote@ # am--include-marker -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/cairo-xlib-source.Plo@am__quote@ # am--include-marker -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/cairo-xlib-surface-shm.Plo@am__quote@ # am--include-marker -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/cairo-xlib-surface.Plo@am__quote@ # am--include-marker -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/cairo-xlib-visual.Plo@am__quote@ # am--include-marker -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/cairo-xlib-xcb-surface.Plo@am__quote@ # am--include-marker -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/cairo-xml-surface.Plo@am__quote@ # am--include-marker -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/cairo.Plo@am__quote@ # am--include-marker -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/check-link.Po@am__quote@ # am--include-marker -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/test-base-compositor-surface.Plo@am__quote@ # am--include-marker -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/test-compositor-surface.Plo@am__quote@ # am--include-marker -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/test-null-compositor-surface.Plo@am__quote@ # am--include-marker -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/test-paginated-surface.Plo@am__quote@ # am--include-marker - -$(am__depfiles_remade): - @$(MKDIR_P) $(@D) - @echo '# dummy' >$@-t && $(am__mv) $@-t $@ - -am--depfiles: $(am__depfiles_remade) - -.c.o: -@am__fastdepCC_TRUE@ $(AM_V_CC)$(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $< -@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po -@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ -@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ -@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(COMPILE) -c -o $@ $< - -.c.obj: -@am__fastdepCC_TRUE@ $(AM_V_CC)$(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ `$(CYGPATH_W) '$<'` -@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po -@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ -@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ -@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(COMPILE) -c -o $@ `$(CYGPATH_W) '$<'` - -.c.lo: -@am__fastdepCC_TRUE@ $(AM_V_CC)$(LTCOMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $< -@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Plo -@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=yes @AMDEPBACKSLASH@ -@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ -@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LTCOMPILE) -c -o $@ $< - -cairo-win32-debug.lo: win32/cairo-win32-debug.c -@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT cairo-win32-debug.lo -MD -MP -MF $(DEPDIR)/cairo-win32-debug.Tpo -c -o cairo-win32-debug.lo `test -f 'win32/cairo-win32-debug.c' || echo '$(srcdir)/'`win32/cairo-win32-debug.c -@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/cairo-win32-debug.Tpo $(DEPDIR)/cairo-win32-debug.Plo -@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='win32/cairo-win32-debug.c' object='cairo-win32-debug.lo' libtool=yes @AMDEPBACKSLASH@ -@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ -@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o cairo-win32-debug.lo `test -f 'win32/cairo-win32-debug.c' || echo '$(srcdir)/'`win32/cairo-win32-debug.c - -cairo-win32-device.lo: win32/cairo-win32-device.c -@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT cairo-win32-device.lo -MD -MP -MF $(DEPDIR)/cairo-win32-device.Tpo -c -o cairo-win32-device.lo `test -f 'win32/cairo-win32-device.c' || echo '$(srcdir)/'`win32/cairo-win32-device.c -@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/cairo-win32-device.Tpo $(DEPDIR)/cairo-win32-device.Plo -@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='win32/cairo-win32-device.c' object='cairo-win32-device.lo' libtool=yes @AMDEPBACKSLASH@ -@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ -@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o cairo-win32-device.lo `test -f 'win32/cairo-win32-device.c' || echo '$(srcdir)/'`win32/cairo-win32-device.c - -cairo-win32-gdi-compositor.lo: win32/cairo-win32-gdi-compositor.c -@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT cairo-win32-gdi-compositor.lo -MD -MP -MF $(DEPDIR)/cairo-win32-gdi-compositor.Tpo -c -o cairo-win32-gdi-compositor.lo `test -f 'win32/cairo-win32-gdi-compositor.c' || echo '$(srcdir)/'`win32/cairo-win32-gdi-compositor.c -@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/cairo-win32-gdi-compositor.Tpo $(DEPDIR)/cairo-win32-gdi-compositor.Plo -@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='win32/cairo-win32-gdi-compositor.c' object='cairo-win32-gdi-compositor.lo' libtool=yes @AMDEPBACKSLASH@ -@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ -@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o cairo-win32-gdi-compositor.lo `test -f 'win32/cairo-win32-gdi-compositor.c' || echo '$(srcdir)/'`win32/cairo-win32-gdi-compositor.c - -cairo-win32-system.lo: win32/cairo-win32-system.c -@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT cairo-win32-system.lo -MD -MP -MF $(DEPDIR)/cairo-win32-system.Tpo -c -o cairo-win32-system.lo `test -f 'win32/cairo-win32-system.c' || echo '$(srcdir)/'`win32/cairo-win32-system.c -@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/cairo-win32-system.Tpo $(DEPDIR)/cairo-win32-system.Plo -@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='win32/cairo-win32-system.c' object='cairo-win32-system.lo' libtool=yes @AMDEPBACKSLASH@ -@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ -@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o cairo-win32-system.lo `test -f 'win32/cairo-win32-system.c' || echo '$(srcdir)/'`win32/cairo-win32-system.c - -cairo-win32-surface.lo: win32/cairo-win32-surface.c -@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT cairo-win32-surface.lo -MD -MP -MF $(DEPDIR)/cairo-win32-surface.Tpo -c -o cairo-win32-surface.lo `test -f 'win32/cairo-win32-surface.c' || echo '$(srcdir)/'`win32/cairo-win32-surface.c -@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/cairo-win32-surface.Tpo $(DEPDIR)/cairo-win32-surface.Plo -@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='win32/cairo-win32-surface.c' object='cairo-win32-surface.lo' libtool=yes @AMDEPBACKSLASH@ -@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ -@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o cairo-win32-surface.lo `test -f 'win32/cairo-win32-surface.c' || echo '$(srcdir)/'`win32/cairo-win32-surface.c - -cairo-win32-display-surface.lo: win32/cairo-win32-display-surface.c -@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT cairo-win32-display-surface.lo -MD -MP -MF $(DEPDIR)/cairo-win32-display-surface.Tpo -c -o cairo-win32-display-surface.lo `test -f 'win32/cairo-win32-display-surface.c' || echo '$(srcdir)/'`win32/cairo-win32-display-surface.c -@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/cairo-win32-display-surface.Tpo $(DEPDIR)/cairo-win32-display-surface.Plo -@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='win32/cairo-win32-display-surface.c' object='cairo-win32-display-surface.lo' libtool=yes @AMDEPBACKSLASH@ -@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ -@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o cairo-win32-display-surface.lo `test -f 'win32/cairo-win32-display-surface.c' || echo '$(srcdir)/'`win32/cairo-win32-display-surface.c - -cairo-win32-printing-surface.lo: win32/cairo-win32-printing-surface.c -@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT cairo-win32-printing-surface.lo -MD -MP -MF $(DEPDIR)/cairo-win32-printing-surface.Tpo -c -o cairo-win32-printing-surface.lo `test -f 'win32/cairo-win32-printing-surface.c' || echo '$(srcdir)/'`win32/cairo-win32-printing-surface.c -@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/cairo-win32-printing-surface.Tpo $(DEPDIR)/cairo-win32-printing-surface.Plo -@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='win32/cairo-win32-printing-surface.c' object='cairo-win32-printing-surface.lo' libtool=yes @AMDEPBACKSLASH@ -@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ -@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o cairo-win32-printing-surface.lo `test -f 'win32/cairo-win32-printing-surface.c' || echo '$(srcdir)/'`win32/cairo-win32-printing-surface.c - -cairo-win32-font.lo: win32/cairo-win32-font.c -@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT cairo-win32-font.lo -MD -MP -MF $(DEPDIR)/cairo-win32-font.Tpo -c -o cairo-win32-font.lo `test -f 'win32/cairo-win32-font.c' || echo '$(srcdir)/'`win32/cairo-win32-font.c -@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/cairo-win32-font.Tpo $(DEPDIR)/cairo-win32-font.Plo -@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='win32/cairo-win32-font.c' object='cairo-win32-font.lo' libtool=yes @AMDEPBACKSLASH@ -@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ -@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o cairo-win32-font.lo `test -f 'win32/cairo-win32-font.c' || echo '$(srcdir)/'`win32/cairo-win32-font.c - -cairo-drm.lo: drm/cairo-drm.c -@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT cairo-drm.lo -MD -MP -MF $(DEPDIR)/cairo-drm.Tpo -c -o cairo-drm.lo `test -f 'drm/cairo-drm.c' || echo '$(srcdir)/'`drm/cairo-drm.c -@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/cairo-drm.Tpo $(DEPDIR)/cairo-drm.Plo -@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='drm/cairo-drm.c' object='cairo-drm.lo' libtool=yes @AMDEPBACKSLASH@ -@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ -@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o cairo-drm.lo `test -f 'drm/cairo-drm.c' || echo '$(srcdir)/'`drm/cairo-drm.c - -cairo-drm-bo.lo: drm/cairo-drm-bo.c -@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT cairo-drm-bo.lo -MD -MP -MF $(DEPDIR)/cairo-drm-bo.Tpo -c -o cairo-drm-bo.lo `test -f 'drm/cairo-drm-bo.c' || echo '$(srcdir)/'`drm/cairo-drm-bo.c -@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/cairo-drm-bo.Tpo $(DEPDIR)/cairo-drm-bo.Plo -@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='drm/cairo-drm-bo.c' object='cairo-drm-bo.lo' libtool=yes @AMDEPBACKSLASH@ -@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ -@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o cairo-drm-bo.lo `test -f 'drm/cairo-drm-bo.c' || echo '$(srcdir)/'`drm/cairo-drm-bo.c - -cairo-drm-surface.lo: drm/cairo-drm-surface.c -@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT cairo-drm-surface.lo -MD -MP -MF $(DEPDIR)/cairo-drm-surface.Tpo -c -o cairo-drm-surface.lo `test -f 'drm/cairo-drm-surface.c' || echo '$(srcdir)/'`drm/cairo-drm-surface.c -@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/cairo-drm-surface.Tpo $(DEPDIR)/cairo-drm-surface.Plo -@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='drm/cairo-drm-surface.c' object='cairo-drm-surface.lo' libtool=yes @AMDEPBACKSLASH@ -@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ -@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o cairo-drm-surface.lo `test -f 'drm/cairo-drm-surface.c' || echo '$(srcdir)/'`drm/cairo-drm-surface.c - -cairo-drm-intel.lo: drm/cairo-drm-intel.c -@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT cairo-drm-intel.lo -MD -MP -MF $(DEPDIR)/cairo-drm-intel.Tpo -c -o cairo-drm-intel.lo `test -f 'drm/cairo-drm-intel.c' || echo '$(srcdir)/'`drm/cairo-drm-intel.c -@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/cairo-drm-intel.Tpo $(DEPDIR)/cairo-drm-intel.Plo -@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='drm/cairo-drm-intel.c' object='cairo-drm-intel.lo' libtool=yes @AMDEPBACKSLASH@ -@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ -@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o cairo-drm-intel.lo `test -f 'drm/cairo-drm-intel.c' || echo '$(srcdir)/'`drm/cairo-drm-intel.c - -cairo-drm-intel-debug.lo: drm/cairo-drm-intel-debug.c -@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT cairo-drm-intel-debug.lo -MD -MP -MF $(DEPDIR)/cairo-drm-intel-debug.Tpo -c -o cairo-drm-intel-debug.lo `test -f 'drm/cairo-drm-intel-debug.c' || echo '$(srcdir)/'`drm/cairo-drm-intel-debug.c -@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/cairo-drm-intel-debug.Tpo $(DEPDIR)/cairo-drm-intel-debug.Plo -@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='drm/cairo-drm-intel-debug.c' object='cairo-drm-intel-debug.lo' libtool=yes @AMDEPBACKSLASH@ -@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ -@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o cairo-drm-intel-debug.lo `test -f 'drm/cairo-drm-intel-debug.c' || echo '$(srcdir)/'`drm/cairo-drm-intel-debug.c - -cairo-drm-intel-surface.lo: drm/cairo-drm-intel-surface.c -@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT cairo-drm-intel-surface.lo -MD -MP -MF $(DEPDIR)/cairo-drm-intel-surface.Tpo -c -o cairo-drm-intel-surface.lo `test -f 'drm/cairo-drm-intel-surface.c' || echo '$(srcdir)/'`drm/cairo-drm-intel-surface.c -@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/cairo-drm-intel-surface.Tpo $(DEPDIR)/cairo-drm-intel-surface.Plo -@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='drm/cairo-drm-intel-surface.c' object='cairo-drm-intel-surface.lo' libtool=yes @AMDEPBACKSLASH@ -@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ -@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o cairo-drm-intel-surface.lo `test -f 'drm/cairo-drm-intel-surface.c' || echo '$(srcdir)/'`drm/cairo-drm-intel-surface.c - -cairo-drm-i915-surface.lo: drm/cairo-drm-i915-surface.c -@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT cairo-drm-i915-surface.lo -MD -MP -MF $(DEPDIR)/cairo-drm-i915-surface.Tpo -c -o cairo-drm-i915-surface.lo `test -f 'drm/cairo-drm-i915-surface.c' || echo '$(srcdir)/'`drm/cairo-drm-i915-surface.c -@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/cairo-drm-i915-surface.Tpo $(DEPDIR)/cairo-drm-i915-surface.Plo -@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='drm/cairo-drm-i915-surface.c' object='cairo-drm-i915-surface.lo' libtool=yes @AMDEPBACKSLASH@ -@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ -@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o cairo-drm-i915-surface.lo `test -f 'drm/cairo-drm-i915-surface.c' || echo '$(srcdir)/'`drm/cairo-drm-i915-surface.c - -cairo-drm-i915-glyphs.lo: drm/cairo-drm-i915-glyphs.c -@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT cairo-drm-i915-glyphs.lo -MD -MP -MF $(DEPDIR)/cairo-drm-i915-glyphs.Tpo -c -o cairo-drm-i915-glyphs.lo `test -f 'drm/cairo-drm-i915-glyphs.c' || echo '$(srcdir)/'`drm/cairo-drm-i915-glyphs.c -@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/cairo-drm-i915-glyphs.Tpo $(DEPDIR)/cairo-drm-i915-glyphs.Plo -@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='drm/cairo-drm-i915-glyphs.c' object='cairo-drm-i915-glyphs.lo' libtool=yes @AMDEPBACKSLASH@ -@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ -@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o cairo-drm-i915-glyphs.lo `test -f 'drm/cairo-drm-i915-glyphs.c' || echo '$(srcdir)/'`drm/cairo-drm-i915-glyphs.c - -cairo-drm-i915-shader.lo: drm/cairo-drm-i915-shader.c -@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT cairo-drm-i915-shader.lo -MD -MP -MF $(DEPDIR)/cairo-drm-i915-shader.Tpo -c -o cairo-drm-i915-shader.lo `test -f 'drm/cairo-drm-i915-shader.c' || echo '$(srcdir)/'`drm/cairo-drm-i915-shader.c -@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/cairo-drm-i915-shader.Tpo $(DEPDIR)/cairo-drm-i915-shader.Plo -@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='drm/cairo-drm-i915-shader.c' object='cairo-drm-i915-shader.lo' libtool=yes @AMDEPBACKSLASH@ -@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ -@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o cairo-drm-i915-shader.lo `test -f 'drm/cairo-drm-i915-shader.c' || echo '$(srcdir)/'`drm/cairo-drm-i915-shader.c - -cairo-drm-i915-spans.lo: drm/cairo-drm-i915-spans.c -@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT cairo-drm-i915-spans.lo -MD -MP -MF $(DEPDIR)/cairo-drm-i915-spans.Tpo -c -o cairo-drm-i915-spans.lo `test -f 'drm/cairo-drm-i915-spans.c' || echo '$(srcdir)/'`drm/cairo-drm-i915-spans.c -@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/cairo-drm-i915-spans.Tpo $(DEPDIR)/cairo-drm-i915-spans.Plo -@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='drm/cairo-drm-i915-spans.c' object='cairo-drm-i915-spans.lo' libtool=yes @AMDEPBACKSLASH@ -@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ -@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o cairo-drm-i915-spans.lo `test -f 'drm/cairo-drm-i915-spans.c' || echo '$(srcdir)/'`drm/cairo-drm-i915-spans.c - -cairo-drm-i965-surface.lo: drm/cairo-drm-i965-surface.c -@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT cairo-drm-i965-surface.lo -MD -MP -MF $(DEPDIR)/cairo-drm-i965-surface.Tpo -c -o cairo-drm-i965-surface.lo `test -f 'drm/cairo-drm-i965-surface.c' || echo '$(srcdir)/'`drm/cairo-drm-i965-surface.c -@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/cairo-drm-i965-surface.Tpo $(DEPDIR)/cairo-drm-i965-surface.Plo -@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='drm/cairo-drm-i965-surface.c' object='cairo-drm-i965-surface.lo' libtool=yes @AMDEPBACKSLASH@ -@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ -@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o cairo-drm-i965-surface.lo `test -f 'drm/cairo-drm-i965-surface.c' || echo '$(srcdir)/'`drm/cairo-drm-i965-surface.c - -cairo-drm-i965-glyphs.lo: drm/cairo-drm-i965-glyphs.c -@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT cairo-drm-i965-glyphs.lo -MD -MP -MF $(DEPDIR)/cairo-drm-i965-glyphs.Tpo -c -o cairo-drm-i965-glyphs.lo `test -f 'drm/cairo-drm-i965-glyphs.c' || echo '$(srcdir)/'`drm/cairo-drm-i965-glyphs.c -@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/cairo-drm-i965-glyphs.Tpo $(DEPDIR)/cairo-drm-i965-glyphs.Plo -@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='drm/cairo-drm-i965-glyphs.c' object='cairo-drm-i965-glyphs.lo' libtool=yes @AMDEPBACKSLASH@ -@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ -@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o cairo-drm-i965-glyphs.lo `test -f 'drm/cairo-drm-i965-glyphs.c' || echo '$(srcdir)/'`drm/cairo-drm-i965-glyphs.c - -cairo-drm-i965-shader.lo: drm/cairo-drm-i965-shader.c -@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT cairo-drm-i965-shader.lo -MD -MP -MF $(DEPDIR)/cairo-drm-i965-shader.Tpo -c -o cairo-drm-i965-shader.lo `test -f 'drm/cairo-drm-i965-shader.c' || echo '$(srcdir)/'`drm/cairo-drm-i965-shader.c -@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/cairo-drm-i965-shader.Tpo $(DEPDIR)/cairo-drm-i965-shader.Plo -@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='drm/cairo-drm-i965-shader.c' object='cairo-drm-i965-shader.lo' libtool=yes @AMDEPBACKSLASH@ -@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ -@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o cairo-drm-i965-shader.lo `test -f 'drm/cairo-drm-i965-shader.c' || echo '$(srcdir)/'`drm/cairo-drm-i965-shader.c - -cairo-drm-i965-spans.lo: drm/cairo-drm-i965-spans.c -@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT cairo-drm-i965-spans.lo -MD -MP -MF $(DEPDIR)/cairo-drm-i965-spans.Tpo -c -o cairo-drm-i965-spans.lo `test -f 'drm/cairo-drm-i965-spans.c' || echo '$(srcdir)/'`drm/cairo-drm-i965-spans.c -@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/cairo-drm-i965-spans.Tpo $(DEPDIR)/cairo-drm-i965-spans.Plo -@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='drm/cairo-drm-i965-spans.c' object='cairo-drm-i965-spans.lo' libtool=yes @AMDEPBACKSLASH@ -@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ -@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o cairo-drm-i965-spans.lo `test -f 'drm/cairo-drm-i965-spans.c' || echo '$(srcdir)/'`drm/cairo-drm-i965-spans.c - -cairo-drm-intel-brw-eu.lo: drm/cairo-drm-intel-brw-eu.c -@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT cairo-drm-intel-brw-eu.lo -MD -MP -MF $(DEPDIR)/cairo-drm-intel-brw-eu.Tpo -c -o cairo-drm-intel-brw-eu.lo `test -f 'drm/cairo-drm-intel-brw-eu.c' || echo '$(srcdir)/'`drm/cairo-drm-intel-brw-eu.c -@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/cairo-drm-intel-brw-eu.Tpo $(DEPDIR)/cairo-drm-intel-brw-eu.Plo -@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='drm/cairo-drm-intel-brw-eu.c' object='cairo-drm-intel-brw-eu.lo' libtool=yes @AMDEPBACKSLASH@ -@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ -@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o cairo-drm-intel-brw-eu.lo `test -f 'drm/cairo-drm-intel-brw-eu.c' || echo '$(srcdir)/'`drm/cairo-drm-intel-brw-eu.c - -cairo-drm-intel-brw-eu-emit.lo: drm/cairo-drm-intel-brw-eu-emit.c -@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT cairo-drm-intel-brw-eu-emit.lo -MD -MP -MF $(DEPDIR)/cairo-drm-intel-brw-eu-emit.Tpo -c -o cairo-drm-intel-brw-eu-emit.lo `test -f 'drm/cairo-drm-intel-brw-eu-emit.c' || echo '$(srcdir)/'`drm/cairo-drm-intel-brw-eu-emit.c -@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/cairo-drm-intel-brw-eu-emit.Tpo $(DEPDIR)/cairo-drm-intel-brw-eu-emit.Plo -@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='drm/cairo-drm-intel-brw-eu-emit.c' object='cairo-drm-intel-brw-eu-emit.lo' libtool=yes @AMDEPBACKSLASH@ -@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ -@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o cairo-drm-intel-brw-eu-emit.lo `test -f 'drm/cairo-drm-intel-brw-eu-emit.c' || echo '$(srcdir)/'`drm/cairo-drm-intel-brw-eu-emit.c - -cairo-drm-intel-brw-eu-util.lo: drm/cairo-drm-intel-brw-eu-util.c -@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT cairo-drm-intel-brw-eu-util.lo -MD -MP -MF $(DEPDIR)/cairo-drm-intel-brw-eu-util.Tpo -c -o cairo-drm-intel-brw-eu-util.lo `test -f 'drm/cairo-drm-intel-brw-eu-util.c' || echo '$(srcdir)/'`drm/cairo-drm-intel-brw-eu-util.c -@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/cairo-drm-intel-brw-eu-util.Tpo $(DEPDIR)/cairo-drm-intel-brw-eu-util.Plo -@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='drm/cairo-drm-intel-brw-eu-util.c' object='cairo-drm-intel-brw-eu-util.lo' libtool=yes @AMDEPBACKSLASH@ -@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ -@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o cairo-drm-intel-brw-eu-util.lo `test -f 'drm/cairo-drm-intel-brw-eu-util.c' || echo '$(srcdir)/'`drm/cairo-drm-intel-brw-eu-util.c - -cairo-drm-radeon.lo: drm/cairo-drm-radeon.c -@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT cairo-drm-radeon.lo -MD -MP -MF $(DEPDIR)/cairo-drm-radeon.Tpo -c -o cairo-drm-radeon.lo `test -f 'drm/cairo-drm-radeon.c' || echo '$(srcdir)/'`drm/cairo-drm-radeon.c -@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/cairo-drm-radeon.Tpo $(DEPDIR)/cairo-drm-radeon.Plo -@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='drm/cairo-drm-radeon.c' object='cairo-drm-radeon.lo' libtool=yes @AMDEPBACKSLASH@ -@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ -@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o cairo-drm-radeon.lo `test -f 'drm/cairo-drm-radeon.c' || echo '$(srcdir)/'`drm/cairo-drm-radeon.c - -cairo-drm-radeon-surface.lo: drm/cairo-drm-radeon-surface.c -@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT cairo-drm-radeon-surface.lo -MD -MP -MF $(DEPDIR)/cairo-drm-radeon-surface.Tpo -c -o cairo-drm-radeon-surface.lo `test -f 'drm/cairo-drm-radeon-surface.c' || echo '$(srcdir)/'`drm/cairo-drm-radeon-surface.c -@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/cairo-drm-radeon-surface.Tpo $(DEPDIR)/cairo-drm-radeon-surface.Plo -@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='drm/cairo-drm-radeon-surface.c' object='cairo-drm-radeon-surface.lo' libtool=yes @AMDEPBACKSLASH@ -@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ -@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o cairo-drm-radeon-surface.lo `test -f 'drm/cairo-drm-radeon-surface.c' || echo '$(srcdir)/'`drm/cairo-drm-radeon-surface.c - -cairo-drm-gallium-surface.lo: drm/cairo-drm-gallium-surface.c -@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT cairo-drm-gallium-surface.lo -MD -MP -MF $(DEPDIR)/cairo-drm-gallium-surface.Tpo -c -o cairo-drm-gallium-surface.lo `test -f 'drm/cairo-drm-gallium-surface.c' || echo '$(srcdir)/'`drm/cairo-drm-gallium-surface.c -@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/cairo-drm-gallium-surface.Tpo $(DEPDIR)/cairo-drm-gallium-surface.Plo -@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='drm/cairo-drm-gallium-surface.c' object='cairo-drm-gallium-surface.lo' libtool=yes @AMDEPBACKSLASH@ -@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ -@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o cairo-drm-gallium-surface.lo `test -f 'drm/cairo-drm-gallium-surface.c' || echo '$(srcdir)/'`drm/cairo-drm-gallium-surface.c - -.cpp.o: -@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXXCOMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $< -@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po -@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ -@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ -@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXXCOMPILE) -c -o $@ $< - -.cpp.obj: -@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXXCOMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ `$(CYGPATH_W) '$<'` -@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po -@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ -@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ -@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXXCOMPILE) -c -o $@ `$(CYGPATH_W) '$<'` - -.cpp.lo: -@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(LTCXXCOMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $< -@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Plo -@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='$<' object='$@' libtool=yes @AMDEPBACKSLASH@ -@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ -@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(LTCXXCOMPILE) -c -o $@ $< - -mostlyclean-libtool: - -rm -f *.lo - -clean-libtool: - -rm -rf .libs _libs -install-pkgconfigDATA: $(pkgconfig_DATA) - @$(NORMAL_INSTALL) - @list='$(pkgconfig_DATA)'; test -n "$(pkgconfigdir)" || list=; \ - if test -n "$$list"; then \ - echo " $(MKDIR_P) '$(DESTDIR)$(pkgconfigdir)'"; \ - $(MKDIR_P) "$(DESTDIR)$(pkgconfigdir)" || exit 1; \ - fi; \ - for p in $$list; do \ - if test -f "$$p"; then d=; else d="$(srcdir)/"; fi; \ - echo "$$d$$p"; \ - done | $(am__base_list) | \ - while read files; do \ - echo " $(INSTALL_DATA) $$files '$(DESTDIR)$(pkgconfigdir)'"; \ - $(INSTALL_DATA) $$files "$(DESTDIR)$(pkgconfigdir)" || exit $$?; \ - done - -uninstall-pkgconfigDATA: - @$(NORMAL_UNINSTALL) - @list='$(pkgconfig_DATA)'; test -n "$(pkgconfigdir)" || list=; \ - files=`for p in $$list; do echo $$p; done | sed -e 's|^.*/||'`; \ - dir='$(DESTDIR)$(pkgconfigdir)'; $(am__uninstall_files_from_dir) -install-cairoincludeHEADERS: $(cairoinclude_HEADERS) - @$(NORMAL_INSTALL) - @list='$(cairoinclude_HEADERS)'; test -n "$(cairoincludedir)" || list=; \ - if test -n "$$list"; then \ - echo " $(MKDIR_P) '$(DESTDIR)$(cairoincludedir)'"; \ - $(MKDIR_P) "$(DESTDIR)$(cairoincludedir)" || exit 1; \ - fi; \ - for p in $$list; do \ - if test -f "$$p"; then d=; else d="$(srcdir)/"; fi; \ - echo "$$d$$p"; \ - done | $(am__base_list) | \ - while read files; do \ - echo " $(INSTALL_HEADER) $$files '$(DESTDIR)$(cairoincludedir)'"; \ - $(INSTALL_HEADER) $$files "$(DESTDIR)$(cairoincludedir)" || exit $$?; \ - done - -uninstall-cairoincludeHEADERS: - @$(NORMAL_UNINSTALL) - @list='$(cairoinclude_HEADERS)'; test -n "$(cairoincludedir)" || list=; \ - files=`for p in $$list; do echo $$p; done | sed -e 's|^.*/||'`; \ - dir='$(DESTDIR)$(cairoincludedir)'; $(am__uninstall_files_from_dir) -install-nodist_cairoincludeHEADERS: $(nodist_cairoinclude_HEADERS) - @$(NORMAL_INSTALL) - @list='$(nodist_cairoinclude_HEADERS)'; test -n "$(cairoincludedir)" || list=; \ - if test -n "$$list"; then \ - echo " $(MKDIR_P) '$(DESTDIR)$(cairoincludedir)'"; \ - $(MKDIR_P) "$(DESTDIR)$(cairoincludedir)" || exit 1; \ - fi; \ - for p in $$list; do \ - if test -f "$$p"; then d=; else d="$(srcdir)/"; fi; \ - echo "$$d$$p"; \ - done | $(am__base_list) | \ - while read files; do \ - echo " $(INSTALL_HEADER) $$files '$(DESTDIR)$(cairoincludedir)'"; \ - $(INSTALL_HEADER) $$files "$(DESTDIR)$(cairoincludedir)" || exit $$?; \ - done - -uninstall-nodist_cairoincludeHEADERS: - @$(NORMAL_UNINSTALL) - @list='$(nodist_cairoinclude_HEADERS)'; test -n "$(cairoincludedir)" || list=; \ - files=`for p in $$list; do echo $$p; done | sed -e 's|^.*/||'`; \ - dir='$(DESTDIR)$(cairoincludedir)'; $(am__uninstall_files_from_dir) - -ID: $(am__tagged_files) - $(am__define_uniq_tagged_files); mkid -fID $$unique -tags: tags-am -TAGS: tags - -tags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files) - set x; \ - here=`pwd`; \ - $(am__define_uniq_tagged_files); \ - shift; \ - if test -z "$(ETAGS_ARGS)$$*$$unique"; then :; else \ - test -n "$$unique" || unique=$$empty_fix; \ - if test $$# -gt 0; then \ - $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ - "$$@" $$unique; \ - else \ - $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ - $$unique; \ - fi; \ - fi -ctags: ctags-am - -CTAGS: ctags -ctags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files) - $(am__define_uniq_tagged_files); \ - test -z "$(CTAGS_ARGS)$$unique" \ - || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \ - $$unique - -GTAGS: - here=`$(am__cd) $(top_builddir) && pwd` \ - && $(am__cd) $(top_srcdir) \ - && gtags -i $(GTAGS_ARGS) "$$here" -cscopelist: cscopelist-am - -cscopelist-am: $(am__tagged_files) - list='$(am__tagged_files)'; \ - case "$(srcdir)" in \ - [\\/]* | ?:[\\/]*) sdir="$(srcdir)" ;; \ - *) sdir=$(subdir)/$(srcdir) ;; \ - esac; \ - for i in $$list; do \ - if test -f "$$i"; then \ - echo "$(subdir)/$$i"; \ - else \ - echo "$$sdir/$$i"; \ - fi; \ - done >> $(top_builddir)/cscope.files - -distclean-tags: - -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags - -# Recover from deleted '.trs' file; this should ensure that -# "rm -f foo.log; make foo.trs" re-run 'foo.test', and re-create -# both 'foo.log' and 'foo.trs'. Break the recipe in two subshells -# to avoid problems with "make -n". -.log.trs: - rm -f $< $@ - $(MAKE) $(AM_MAKEFLAGS) $< - -# Leading 'am--fnord' is there to ensure the list of targets does not -# expand to empty, as could happen e.g. with make check TESTS=''. -am--fnord $(TEST_LOGS) $(TEST_LOGS:.log=.trs): $(am__force_recheck) -am--force-recheck: - @: - -$(TEST_SUITE_LOG): $(TEST_LOGS) - @$(am__set_TESTS_bases); \ - am__f_ok () { test -f "$$1" && test -r "$$1"; }; \ - redo_bases=`for i in $$bases; do \ - am__f_ok $$i.trs && am__f_ok $$i.log || echo $$i; \ - done`; \ - if test -n "$$redo_bases"; then \ - redo_logs=`for i in $$redo_bases; do echo $$i.log; done`; \ - redo_results=`for i in $$redo_bases; do echo $$i.trs; done`; \ - if $(am__make_dryrun); then :; else \ - rm -f $$redo_logs && rm -f $$redo_results || exit 1; \ - fi; \ - fi; \ - if test -n "$$am__remaking_logs"; then \ - echo "fatal: making $(TEST_SUITE_LOG): possible infinite" \ - "recursion detected" >&2; \ - elif test -n "$$redo_logs"; then \ - am__remaking_logs=yes $(MAKE) $(AM_MAKEFLAGS) $$redo_logs; \ - fi; \ - if $(am__make_dryrun); then :; else \ - st=0; \ - errmsg="fatal: making $(TEST_SUITE_LOG): failed to create"; \ - for i in $$redo_bases; do \ - test -f $$i.trs && test -r $$i.trs \ - || { echo "$$errmsg $$i.trs" >&2; st=1; }; \ - test -f $$i.log && test -r $$i.log \ - || { echo "$$errmsg $$i.log" >&2; st=1; }; \ - done; \ - test $$st -eq 0 || exit 1; \ - fi - @$(am__sh_e_setup); $(am__tty_colors); $(am__set_TESTS_bases); \ - ws='[ ]'; \ - results=`for b in $$bases; do echo $$b.trs; done`; \ - test -n "$$results" || results=/dev/null; \ - all=` grep "^$$ws*:test-result:" $$results | wc -l`; \ - pass=` grep "^$$ws*:test-result:$$ws*PASS" $$results | wc -l`; \ - fail=` grep "^$$ws*:test-result:$$ws*FAIL" $$results | wc -l`; \ - skip=` grep "^$$ws*:test-result:$$ws*SKIP" $$results | wc -l`; \ - xfail=`grep "^$$ws*:test-result:$$ws*XFAIL" $$results | wc -l`; \ - xpass=`grep "^$$ws*:test-result:$$ws*XPASS" $$results | wc -l`; \ - error=`grep "^$$ws*:test-result:$$ws*ERROR" $$results | wc -l`; \ - if test `expr $$fail + $$xpass + $$error` -eq 0; then \ - success=true; \ - else \ - success=false; \ - fi; \ - br='==================='; br=$$br$$br$$br$$br; \ - result_count () \ - { \ - if test x"$$1" = x"--maybe-color"; then \ - maybe_colorize=yes; \ - elif test x"$$1" = x"--no-color"; then \ - maybe_colorize=no; \ - else \ - echo "$@: invalid 'result_count' usage" >&2; exit 4; \ - fi; \ - shift; \ - desc=$$1 count=$$2; \ - if test $$maybe_colorize = yes && test $$count -gt 0; then \ - color_start=$$3 color_end=$$std; \ - else \ - color_start= color_end=; \ - fi; \ - echo "$${color_start}# $$desc $$count$${color_end}"; \ - }; \ - create_testsuite_report () \ - { \ - result_count $$1 "TOTAL:" $$all "$$brg"; \ - result_count $$1 "PASS: " $$pass "$$grn"; \ - result_count $$1 "SKIP: " $$skip "$$blu"; \ - result_count $$1 "XFAIL:" $$xfail "$$lgn"; \ - result_count $$1 "FAIL: " $$fail "$$red"; \ - result_count $$1 "XPASS:" $$xpass "$$red"; \ - result_count $$1 "ERROR:" $$error "$$mgn"; \ - }; \ - { \ - echo "$(PACKAGE_STRING): $(subdir)/$(TEST_SUITE_LOG)" | \ - $(am__rst_title); \ - create_testsuite_report --no-color; \ - echo; \ - echo ".. contents:: :depth: 2"; \ - echo; \ - for b in $$bases; do echo $$b; done \ - | $(am__create_global_log); \ - } >$(TEST_SUITE_LOG).tmp || exit 1; \ - mv $(TEST_SUITE_LOG).tmp $(TEST_SUITE_LOG); \ - if $$success; then \ - col="$$grn"; \ - else \ - col="$$red"; \ - test x"$$VERBOSE" = x || cat $(TEST_SUITE_LOG); \ - fi; \ - echo "$${col}$$br$${std}"; \ - echo "$${col}Testsuite summary for $(PACKAGE_STRING)$${std}"; \ - echo "$${col}$$br$${std}"; \ - create_testsuite_report --maybe-color; \ - echo "$$col$$br$$std"; \ - if $$success; then :; else \ - echo "$${col}See $(subdir)/$(TEST_SUITE_LOG)$${std}"; \ - if test -n "$(PACKAGE_BUGREPORT)"; then \ - echo "$${col}Please report to $(PACKAGE_BUGREPORT)$${std}"; \ - fi; \ - echo "$$col$$br$$std"; \ - fi; \ - $$success || exit 1 - -check-TESTS: $(check_PROGRAMS) - @list='$(RECHECK_LOGS)'; test -z "$$list" || rm -f $$list - @list='$(RECHECK_LOGS:.log=.trs)'; test -z "$$list" || rm -f $$list - @test -z "$(TEST_SUITE_LOG)" || rm -f $(TEST_SUITE_LOG) - @set +e; $(am__set_TESTS_bases); \ - log_list=`for i in $$bases; do echo $$i.log; done`; \ - trs_list=`for i in $$bases; do echo $$i.trs; done`; \ - log_list=`echo $$log_list`; trs_list=`echo $$trs_list`; \ - $(MAKE) $(AM_MAKEFLAGS) $(TEST_SUITE_LOG) TEST_LOGS="$$log_list"; \ - exit $$?; -recheck: all $(check_PROGRAMS) - @test -z "$(TEST_SUITE_LOG)" || rm -f $(TEST_SUITE_LOG) - @set +e; $(am__set_TESTS_bases); \ - bases=`for i in $$bases; do echo $$i; done \ - | $(am__list_recheck_tests)` || exit 1; \ - log_list=`for i in $$bases; do echo $$i.log; done`; \ - log_list=`echo $$log_list`; \ - $(MAKE) $(AM_MAKEFLAGS) $(TEST_SUITE_LOG) \ - am__force_recheck=am--force-recheck \ - TEST_LOGS="$$log_list"; \ - exit $$? -check-def.sh.log: check-def.sh - @p='check-def.sh'; \ - b='check-def.sh'; \ - $(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \ - --log-file $$b.log --trs-file $$b.trs \ - $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \ - "$$tst" $(AM_TESTS_FD_REDIRECT) -check-doc-syntax.sh.log: check-doc-syntax.sh - @p='check-doc-syntax.sh'; \ - b='check-doc-syntax.sh'; \ - $(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \ - --log-file $$b.log --trs-file $$b.trs \ - $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \ - "$$tst" $(AM_TESTS_FD_REDIRECT) -check-headers.sh.log: check-headers.sh - @p='check-headers.sh'; \ - b='check-headers.sh'; \ - $(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \ - --log-file $$b.log --trs-file $$b.trs \ - $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \ - "$$tst" $(AM_TESTS_FD_REDIRECT) -check-plt.sh.log: check-plt.sh - @p='check-plt.sh'; \ - b='check-plt.sh'; \ - $(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \ - --log-file $$b.log --trs-file $$b.trs \ - $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \ - "$$tst" $(AM_TESTS_FD_REDIRECT) -check-preprocessor-syntax.sh.log: check-preprocessor-syntax.sh - @p='check-preprocessor-syntax.sh'; \ - b='check-preprocessor-syntax.sh'; \ - $(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \ - --log-file $$b.log --trs-file $$b.trs \ - $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \ - "$$tst" $(AM_TESTS_FD_REDIRECT) -check-link.log: check-link$(EXEEXT) - @p='check-link$(EXEEXT)'; \ - b='check-link'; \ - $(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \ - --log-file $$b.log --trs-file $$b.trs \ - $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \ - "$$tst" $(AM_TESTS_FD_REDIRECT) -.test.log: - @p='$<'; \ - $(am__set_b); \ - $(am__check_pre) $(TEST_LOG_DRIVER) --test-name "$$f" \ - --log-file $$b.log --trs-file $$b.trs \ - $(am__common_driver_flags) $(AM_TEST_LOG_DRIVER_FLAGS) $(TEST_LOG_DRIVER_FLAGS) -- $(TEST_LOG_COMPILE) \ - "$$tst" $(AM_TESTS_FD_REDIRECT) -@am__EXEEXT_TRUE@.test$(EXEEXT).log: -@am__EXEEXT_TRUE@ @p='$<'; \ -@am__EXEEXT_TRUE@ $(am__set_b); \ -@am__EXEEXT_TRUE@ $(am__check_pre) $(TEST_LOG_DRIVER) --test-name "$$f" \ -@am__EXEEXT_TRUE@ --log-file $$b.log --trs-file $$b.trs \ -@am__EXEEXT_TRUE@ $(am__common_driver_flags) $(AM_TEST_LOG_DRIVER_FLAGS) $(TEST_LOG_DRIVER_FLAGS) -- $(TEST_LOG_COMPILE) \ -@am__EXEEXT_TRUE@ "$$tst" $(AM_TESTS_FD_REDIRECT) - -distdir: $(BUILT_SOURCES) - $(MAKE) $(AM_MAKEFLAGS) distdir-am - -distdir-am: $(DISTFILES) - @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ - topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ - list='$(DISTFILES)'; \ - dist_files=`for file in $$list; do echo $$file; done | \ - sed -e "s|^$$srcdirstrip/||;t" \ - -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \ - case $$dist_files in \ - */*) $(MKDIR_P) `echo "$$dist_files" | \ - sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \ - sort -u` ;; \ - esac; \ - for file in $$dist_files; do \ - if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \ - if test -d $$d/$$file; then \ - dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \ - if test -d "$(distdir)/$$file"; then \ - find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ - fi; \ - if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \ - cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \ - find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ - fi; \ - cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \ - else \ - test -f "$(distdir)/$$file" \ - || cp -p $$d/$$file "$(distdir)/$$file" \ - || exit 1; \ - fi; \ - done -check-am: all-am - $(MAKE) $(AM_MAKEFLAGS) $(check_PROGRAMS) - $(MAKE) $(AM_MAKEFLAGS) check-TESTS -check: $(BUILT_SOURCES) - $(MAKE) $(AM_MAKEFLAGS) check-am -all-am: Makefile $(LTLIBRARIES) $(DATA) $(HEADERS) -installdirs: - for dir in "$(DESTDIR)$(libdir)" "$(DESTDIR)$(pkgconfigdir)" "$(DESTDIR)$(cairoincludedir)" "$(DESTDIR)$(cairoincludedir)"; do \ - test -z "$$dir" || $(MKDIR_P) "$$dir"; \ - done -install: $(BUILT_SOURCES) - $(MAKE) $(AM_MAKEFLAGS) install-am -install-exec: install-exec-am -install-data: install-data-am -uninstall: uninstall-am - -install-am: all-am - @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am - -installcheck: installcheck-am -install-strip: - if test -z '$(STRIP)'; then \ - $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ - install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ - install; \ - else \ - $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ - install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ - "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'" install; \ - fi -mostlyclean-generic: - -test -z "$(TEST_LOGS)" || rm -f $(TEST_LOGS) - -test -z "$(TEST_LOGS:.log=.trs)" || rm -f $(TEST_LOGS:.log=.trs) - -test -z "$(TEST_SUITE_LOG)" || rm -f $(TEST_SUITE_LOG) - -clean-generic: - -test -z "$(CLEANFILES)" || rm -f $(CLEANFILES) - -distclean-generic: - -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES) - -test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES) - -test -z "$(DISTCLEANFILES)" || rm -f $(DISTCLEANFILES) - -maintainer-clean-generic: - @echo "This command is intended for maintainers to use" - @echo "it deletes files that may require special tools to rebuild." - -test -z "$(BUILT_SOURCES)" || rm -f $(BUILT_SOURCES) - -test -z "$(MAINTAINERCLEANFILES)" || rm -f $(MAINTAINERCLEANFILES) -clean: clean-am - -clean-am: clean-checkPROGRAMS clean-generic clean-libLTLIBRARIES \ - clean-libtool clean-noinstLTLIBRARIES mostlyclean-am - -distclean: distclean-am - -rm -f ./$(DEPDIR)/cairo-analysis-surface.Plo - -rm -f ./$(DEPDIR)/cairo-arc.Plo - -rm -f ./$(DEPDIR)/cairo-array.Plo - -rm -f ./$(DEPDIR)/cairo-atomic.Plo - -rm -f ./$(DEPDIR)/cairo-base64-stream.Plo - -rm -f ./$(DEPDIR)/cairo-base85-stream.Plo - -rm -f ./$(DEPDIR)/cairo-bentley-ottmann-rectangular.Plo - -rm -f ./$(DEPDIR)/cairo-bentley-ottmann-rectilinear.Plo - -rm -f ./$(DEPDIR)/cairo-bentley-ottmann.Plo - -rm -f ./$(DEPDIR)/cairo-beos-surface.Plo - -rm -f ./$(DEPDIR)/cairo-botor-scan-converter.Plo - -rm -f ./$(DEPDIR)/cairo-boxes-intersect.Plo - -rm -f ./$(DEPDIR)/cairo-boxes.Plo - -rm -f ./$(DEPDIR)/cairo-cache.Plo - -rm -f ./$(DEPDIR)/cairo-cff-subset.Plo - -rm -f ./$(DEPDIR)/cairo-clip-boxes.Plo - -rm -f ./$(DEPDIR)/cairo-clip-polygon.Plo - -rm -f ./$(DEPDIR)/cairo-clip-region.Plo - -rm -f ./$(DEPDIR)/cairo-clip-surface.Plo - -rm -f ./$(DEPDIR)/cairo-clip-tor-scan-converter.Plo - -rm -f ./$(DEPDIR)/cairo-clip.Plo - -rm -f ./$(DEPDIR)/cairo-cogl-gradient.Plo - -rm -f ./$(DEPDIR)/cairo-cogl-surface.Plo - -rm -f ./$(DEPDIR)/cairo-color.Plo - -rm -f ./$(DEPDIR)/cairo-composite-rectangles.Plo - -rm -f ./$(DEPDIR)/cairo-compositor.Plo - -rm -f ./$(DEPDIR)/cairo-contour.Plo - -rm -f ./$(DEPDIR)/cairo-damage.Plo - -rm -f ./$(DEPDIR)/cairo-debug.Plo - -rm -f ./$(DEPDIR)/cairo-default-context.Plo - -rm -f ./$(DEPDIR)/cairo-deflate-stream.Plo - -rm -f ./$(DEPDIR)/cairo-device.Plo - -rm -f ./$(DEPDIR)/cairo-directfb-surface.Plo - -rm -f ./$(DEPDIR)/cairo-drm-bo.Plo - -rm -f ./$(DEPDIR)/cairo-drm-gallium-surface.Plo - -rm -f ./$(DEPDIR)/cairo-drm-i915-glyphs.Plo - -rm -f ./$(DEPDIR)/cairo-drm-i915-shader.Plo - -rm -f ./$(DEPDIR)/cairo-drm-i915-spans.Plo - -rm -f ./$(DEPDIR)/cairo-drm-i915-surface.Plo - -rm -f ./$(DEPDIR)/cairo-drm-i965-glyphs.Plo - -rm -f ./$(DEPDIR)/cairo-drm-i965-shader.Plo - -rm -f ./$(DEPDIR)/cairo-drm-i965-spans.Plo - -rm -f ./$(DEPDIR)/cairo-drm-i965-surface.Plo - -rm -f ./$(DEPDIR)/cairo-drm-intel-brw-eu-emit.Plo - -rm -f ./$(DEPDIR)/cairo-drm-intel-brw-eu-util.Plo - -rm -f ./$(DEPDIR)/cairo-drm-intel-brw-eu.Plo - -rm -f ./$(DEPDIR)/cairo-drm-intel-debug.Plo - -rm -f ./$(DEPDIR)/cairo-drm-intel-surface.Plo - -rm -f ./$(DEPDIR)/cairo-drm-intel.Plo - -rm -f ./$(DEPDIR)/cairo-drm-radeon-surface.Plo - -rm -f ./$(DEPDIR)/cairo-drm-radeon.Plo - -rm -f ./$(DEPDIR)/cairo-drm-surface.Plo - -rm -f ./$(DEPDIR)/cairo-drm.Plo - -rm -f ./$(DEPDIR)/cairo-egl-context.Plo - -rm -f ./$(DEPDIR)/cairo-error.Plo - -rm -f ./$(DEPDIR)/cairo-fallback-compositor.Plo - -rm -f ./$(DEPDIR)/cairo-fixed.Plo - -rm -f ./$(DEPDIR)/cairo-font-face-twin-data.Plo - -rm -f ./$(DEPDIR)/cairo-font-face-twin.Plo - -rm -f ./$(DEPDIR)/cairo-font-face.Plo - -rm -f ./$(DEPDIR)/cairo-font-options.Plo - -rm -f ./$(DEPDIR)/cairo-freed-pool.Plo - -rm -f ./$(DEPDIR)/cairo-freelist.Plo - -rm -f ./$(DEPDIR)/cairo-ft-font.Plo - -rm -f ./$(DEPDIR)/cairo-gl-composite.Plo - -rm -f ./$(DEPDIR)/cairo-gl-device.Plo - -rm -f ./$(DEPDIR)/cairo-gl-dispatch.Plo - -rm -f ./$(DEPDIR)/cairo-gl-glyphs.Plo - -rm -f ./$(DEPDIR)/cairo-gl-gradient.Plo - -rm -f ./$(DEPDIR)/cairo-gl-info.Plo - -rm -f ./$(DEPDIR)/cairo-gl-msaa-compositor.Plo - -rm -f ./$(DEPDIR)/cairo-gl-operand.Plo - -rm -f ./$(DEPDIR)/cairo-gl-shaders.Plo - -rm -f ./$(DEPDIR)/cairo-gl-source.Plo - -rm -f ./$(DEPDIR)/cairo-gl-spans-compositor.Plo - -rm -f ./$(DEPDIR)/cairo-gl-surface.Plo - -rm -f ./$(DEPDIR)/cairo-gl-traps-compositor.Plo - -rm -f ./$(DEPDIR)/cairo-glx-context.Plo - -rm -f ./$(DEPDIR)/cairo-gstate.Plo - -rm -f ./$(DEPDIR)/cairo-hash.Plo - -rm -f ./$(DEPDIR)/cairo-hull.Plo - -rm -f ./$(DEPDIR)/cairo-image-compositor.Plo - -rm -f ./$(DEPDIR)/cairo-image-info.Plo - -rm -f ./$(DEPDIR)/cairo-image-source.Plo - -rm -f ./$(DEPDIR)/cairo-image-surface.Plo - -rm -f ./$(DEPDIR)/cairo-line.Plo - -rm -f ./$(DEPDIR)/cairo-lzw.Plo - -rm -f ./$(DEPDIR)/cairo-mask-compositor.Plo - -rm -f ./$(DEPDIR)/cairo-matrix.Plo - -rm -f ./$(DEPDIR)/cairo-mempool.Plo - -rm -f ./$(DEPDIR)/cairo-mesh-pattern-rasterizer.Plo - -rm -f ./$(DEPDIR)/cairo-misc.Plo - -rm -f ./$(DEPDIR)/cairo-mono-scan-converter.Plo - -rm -f ./$(DEPDIR)/cairo-mutex.Plo - -rm -f ./$(DEPDIR)/cairo-no-compositor.Plo - -rm -f ./$(DEPDIR)/cairo-observer.Plo - -rm -f ./$(DEPDIR)/cairo-os2-surface.Plo - -rm -f ./$(DEPDIR)/cairo-output-stream.Plo - -rm -f ./$(DEPDIR)/cairo-paginated-surface.Plo - -rm -f ./$(DEPDIR)/cairo-path-bounds.Plo - -rm -f ./$(DEPDIR)/cairo-path-fill.Plo - -rm -f ./$(DEPDIR)/cairo-path-fixed.Plo - -rm -f ./$(DEPDIR)/cairo-path-in-fill.Plo - -rm -f ./$(DEPDIR)/cairo-path-stroke-boxes.Plo - -rm -f ./$(DEPDIR)/cairo-path-stroke-polygon.Plo - -rm -f ./$(DEPDIR)/cairo-path-stroke-traps.Plo - -rm -f ./$(DEPDIR)/cairo-path-stroke-tristrip.Plo - -rm -f ./$(DEPDIR)/cairo-path-stroke.Plo - -rm -f ./$(DEPDIR)/cairo-path.Plo - -rm -f ./$(DEPDIR)/cairo-pattern.Plo - -rm -f ./$(DEPDIR)/cairo-pdf-interchange.Plo - -rm -f ./$(DEPDIR)/cairo-pdf-operators.Plo - -rm -f ./$(DEPDIR)/cairo-pdf-shading.Plo - -rm -f ./$(DEPDIR)/cairo-pdf-surface.Plo - -rm -f ./$(DEPDIR)/cairo-pen.Plo - -rm -f ./$(DEPDIR)/cairo-png.Plo - -rm -f ./$(DEPDIR)/cairo-polygon-intersect.Plo - -rm -f ./$(DEPDIR)/cairo-polygon-reduce.Plo - -rm -f ./$(DEPDIR)/cairo-polygon.Plo - -rm -f ./$(DEPDIR)/cairo-ps-surface.Plo - -rm -f ./$(DEPDIR)/cairo-qt-surface.Plo - -rm -f ./$(DEPDIR)/cairo-quartz-font.Plo - -rm -f ./$(DEPDIR)/cairo-quartz-image-surface.Plo - -rm -f ./$(DEPDIR)/cairo-quartz-surface.Plo - -rm -f ./$(DEPDIR)/cairo-raster-source-pattern.Plo - -rm -f ./$(DEPDIR)/cairo-recording-surface.Plo - -rm -f ./$(DEPDIR)/cairo-rectangle.Plo - -rm -f ./$(DEPDIR)/cairo-rectangular-scan-converter.Plo - -rm -f ./$(DEPDIR)/cairo-region.Plo - -rm -f ./$(DEPDIR)/cairo-rtree.Plo - -rm -f ./$(DEPDIR)/cairo-scaled-font-subsets.Plo - -rm -f ./$(DEPDIR)/cairo-scaled-font.Plo - -rm -f ./$(DEPDIR)/cairo-script-surface.Plo - -rm -f ./$(DEPDIR)/cairo-shape-mask-compositor.Plo - -rm -f ./$(DEPDIR)/cairo-slope.Plo - -rm -f ./$(DEPDIR)/cairo-spans-compositor.Plo - -rm -f ./$(DEPDIR)/cairo-spans.Plo - -rm -f ./$(DEPDIR)/cairo-spline.Plo - -rm -f ./$(DEPDIR)/cairo-stroke-dash.Plo - -rm -f ./$(DEPDIR)/cairo-stroke-style.Plo - -rm -f ./$(DEPDIR)/cairo-surface-clipper.Plo - -rm -f ./$(DEPDIR)/cairo-surface-fallback.Plo - -rm -f ./$(DEPDIR)/cairo-surface-observer.Plo - -rm -f ./$(DEPDIR)/cairo-surface-offset.Plo - -rm -f ./$(DEPDIR)/cairo-surface-snapshot.Plo - -rm -f ./$(DEPDIR)/cairo-surface-subsurface.Plo - -rm -f ./$(DEPDIR)/cairo-surface-wrapper.Plo - -rm -f ./$(DEPDIR)/cairo-surface.Plo - -rm -f ./$(DEPDIR)/cairo-svg-surface.Plo - -rm -f ./$(DEPDIR)/cairo-tag-attributes.Plo - -rm -f ./$(DEPDIR)/cairo-tag-stack.Plo - -rm -f ./$(DEPDIR)/cairo-tee-surface.Plo - -rm -f ./$(DEPDIR)/cairo-time.Plo - -rm -f ./$(DEPDIR)/cairo-tor-scan-converter.Plo - -rm -f ./$(DEPDIR)/cairo-tor22-scan-converter.Plo - -rm -f ./$(DEPDIR)/cairo-toy-font-face.Plo - -rm -f ./$(DEPDIR)/cairo-traps-compositor.Plo - -rm -f ./$(DEPDIR)/cairo-traps.Plo - -rm -f ./$(DEPDIR)/cairo-tristrip.Plo - -rm -f ./$(DEPDIR)/cairo-truetype-subset.Plo - -rm -f ./$(DEPDIR)/cairo-type1-fallback.Plo - -rm -f ./$(DEPDIR)/cairo-type1-glyph-names.Plo - -rm -f ./$(DEPDIR)/cairo-type1-subset.Plo - -rm -f ./$(DEPDIR)/cairo-type3-glyph-surface.Plo - -rm -f ./$(DEPDIR)/cairo-unicode.Plo - -rm -f ./$(DEPDIR)/cairo-user-font.Plo - -rm -f ./$(DEPDIR)/cairo-version.Plo - -rm -f ./$(DEPDIR)/cairo-vg-surface.Plo - -rm -f ./$(DEPDIR)/cairo-wgl-context.Plo - -rm -f ./$(DEPDIR)/cairo-wideint.Plo - -rm -f ./$(DEPDIR)/cairo-win32-debug.Plo - -rm -f ./$(DEPDIR)/cairo-win32-device.Plo - -rm -f ./$(DEPDIR)/cairo-win32-display-surface.Plo - -rm -f ./$(DEPDIR)/cairo-win32-font.Plo - -rm -f ./$(DEPDIR)/cairo-win32-gdi-compositor.Plo - -rm -f ./$(DEPDIR)/cairo-win32-printing-surface.Plo - -rm -f ./$(DEPDIR)/cairo-win32-surface.Plo - -rm -f ./$(DEPDIR)/cairo-win32-system.Plo - -rm -f ./$(DEPDIR)/cairo-xcb-connection-core.Plo - -rm -f ./$(DEPDIR)/cairo-xcb-connection-render.Plo - -rm -f ./$(DEPDIR)/cairo-xcb-connection-shm.Plo - -rm -f ./$(DEPDIR)/cairo-xcb-connection.Plo - -rm -f ./$(DEPDIR)/cairo-xcb-resources.Plo - -rm -f ./$(DEPDIR)/cairo-xcb-screen.Plo - -rm -f ./$(DEPDIR)/cairo-xcb-shm.Plo - -rm -f ./$(DEPDIR)/cairo-xcb-surface-core.Plo - -rm -f ./$(DEPDIR)/cairo-xcb-surface-render.Plo - -rm -f ./$(DEPDIR)/cairo-xcb-surface.Plo - -rm -f ./$(DEPDIR)/cairo-xlib-core-compositor.Plo - -rm -f ./$(DEPDIR)/cairo-xlib-display.Plo - -rm -f ./$(DEPDIR)/cairo-xlib-fallback-compositor.Plo - -rm -f ./$(DEPDIR)/cairo-xlib-render-compositor.Plo - -rm -f ./$(DEPDIR)/cairo-xlib-screen.Plo - -rm -f ./$(DEPDIR)/cairo-xlib-source.Plo - -rm -f ./$(DEPDIR)/cairo-xlib-surface-shm.Plo - -rm -f ./$(DEPDIR)/cairo-xlib-surface.Plo - -rm -f ./$(DEPDIR)/cairo-xlib-visual.Plo - -rm -f ./$(DEPDIR)/cairo-xlib-xcb-surface.Plo - -rm -f ./$(DEPDIR)/cairo-xml-surface.Plo - -rm -f ./$(DEPDIR)/cairo.Plo - -rm -f ./$(DEPDIR)/check-link.Po - -rm -f ./$(DEPDIR)/test-base-compositor-surface.Plo - -rm -f ./$(DEPDIR)/test-compositor-surface.Plo - -rm -f ./$(DEPDIR)/test-null-compositor-surface.Plo - -rm -f ./$(DEPDIR)/test-paginated-surface.Plo - -rm -f Makefile -distclean-am: clean-am distclean-compile distclean-generic \ - distclean-tags - -dvi: dvi-am - -dvi-am: - -html: html-am - -html-am: - -info: info-am - -info-am: - -install-data-am: install-cairoincludeHEADERS \ - install-nodist_cairoincludeHEADERS install-pkgconfigDATA - -install-dvi: install-dvi-am - -install-dvi-am: - -install-exec-am: install-libLTLIBRARIES - -install-html: install-html-am - -install-html-am: - -install-info: install-info-am - -install-info-am: - -install-man: - -install-pdf: install-pdf-am - -install-pdf-am: - -install-ps: install-ps-am - -install-ps-am: - -installcheck-am: - -maintainer-clean: maintainer-clean-am - -rm -f ./$(DEPDIR)/cairo-analysis-surface.Plo - -rm -f ./$(DEPDIR)/cairo-arc.Plo - -rm -f ./$(DEPDIR)/cairo-array.Plo - -rm -f ./$(DEPDIR)/cairo-atomic.Plo - -rm -f ./$(DEPDIR)/cairo-base64-stream.Plo - -rm -f ./$(DEPDIR)/cairo-base85-stream.Plo - -rm -f ./$(DEPDIR)/cairo-bentley-ottmann-rectangular.Plo - -rm -f ./$(DEPDIR)/cairo-bentley-ottmann-rectilinear.Plo - -rm -f ./$(DEPDIR)/cairo-bentley-ottmann.Plo - -rm -f ./$(DEPDIR)/cairo-beos-surface.Plo - -rm -f ./$(DEPDIR)/cairo-botor-scan-converter.Plo - -rm -f ./$(DEPDIR)/cairo-boxes-intersect.Plo - -rm -f ./$(DEPDIR)/cairo-boxes.Plo - -rm -f ./$(DEPDIR)/cairo-cache.Plo - -rm -f ./$(DEPDIR)/cairo-cff-subset.Plo - -rm -f ./$(DEPDIR)/cairo-clip-boxes.Plo - -rm -f ./$(DEPDIR)/cairo-clip-polygon.Plo - -rm -f ./$(DEPDIR)/cairo-clip-region.Plo - -rm -f ./$(DEPDIR)/cairo-clip-surface.Plo - -rm -f ./$(DEPDIR)/cairo-clip-tor-scan-converter.Plo - -rm -f ./$(DEPDIR)/cairo-clip.Plo - -rm -f ./$(DEPDIR)/cairo-cogl-gradient.Plo - -rm -f ./$(DEPDIR)/cairo-cogl-surface.Plo - -rm -f ./$(DEPDIR)/cairo-color.Plo - -rm -f ./$(DEPDIR)/cairo-composite-rectangles.Plo - -rm -f ./$(DEPDIR)/cairo-compositor.Plo - -rm -f ./$(DEPDIR)/cairo-contour.Plo - -rm -f ./$(DEPDIR)/cairo-damage.Plo - -rm -f ./$(DEPDIR)/cairo-debug.Plo - -rm -f ./$(DEPDIR)/cairo-default-context.Plo - -rm -f ./$(DEPDIR)/cairo-deflate-stream.Plo - -rm -f ./$(DEPDIR)/cairo-device.Plo - -rm -f ./$(DEPDIR)/cairo-directfb-surface.Plo - -rm -f ./$(DEPDIR)/cairo-drm-bo.Plo - -rm -f ./$(DEPDIR)/cairo-drm-gallium-surface.Plo - -rm -f ./$(DEPDIR)/cairo-drm-i915-glyphs.Plo - -rm -f ./$(DEPDIR)/cairo-drm-i915-shader.Plo - -rm -f ./$(DEPDIR)/cairo-drm-i915-spans.Plo - -rm -f ./$(DEPDIR)/cairo-drm-i915-surface.Plo - -rm -f ./$(DEPDIR)/cairo-drm-i965-glyphs.Plo - -rm -f ./$(DEPDIR)/cairo-drm-i965-shader.Plo - -rm -f ./$(DEPDIR)/cairo-drm-i965-spans.Plo - -rm -f ./$(DEPDIR)/cairo-drm-i965-surface.Plo - -rm -f ./$(DEPDIR)/cairo-drm-intel-brw-eu-emit.Plo - -rm -f ./$(DEPDIR)/cairo-drm-intel-brw-eu-util.Plo - -rm -f ./$(DEPDIR)/cairo-drm-intel-brw-eu.Plo - -rm -f ./$(DEPDIR)/cairo-drm-intel-debug.Plo - -rm -f ./$(DEPDIR)/cairo-drm-intel-surface.Plo - -rm -f ./$(DEPDIR)/cairo-drm-intel.Plo - -rm -f ./$(DEPDIR)/cairo-drm-radeon-surface.Plo - -rm -f ./$(DEPDIR)/cairo-drm-radeon.Plo - -rm -f ./$(DEPDIR)/cairo-drm-surface.Plo - -rm -f ./$(DEPDIR)/cairo-drm.Plo - -rm -f ./$(DEPDIR)/cairo-egl-context.Plo - -rm -f ./$(DEPDIR)/cairo-error.Plo - -rm -f ./$(DEPDIR)/cairo-fallback-compositor.Plo - -rm -f ./$(DEPDIR)/cairo-fixed.Plo - -rm -f ./$(DEPDIR)/cairo-font-face-twin-data.Plo - -rm -f ./$(DEPDIR)/cairo-font-face-twin.Plo - -rm -f ./$(DEPDIR)/cairo-font-face.Plo - -rm -f ./$(DEPDIR)/cairo-font-options.Plo - -rm -f ./$(DEPDIR)/cairo-freed-pool.Plo - -rm -f ./$(DEPDIR)/cairo-freelist.Plo - -rm -f ./$(DEPDIR)/cairo-ft-font.Plo - -rm -f ./$(DEPDIR)/cairo-gl-composite.Plo - -rm -f ./$(DEPDIR)/cairo-gl-device.Plo - -rm -f ./$(DEPDIR)/cairo-gl-dispatch.Plo - -rm -f ./$(DEPDIR)/cairo-gl-glyphs.Plo - -rm -f ./$(DEPDIR)/cairo-gl-gradient.Plo - -rm -f ./$(DEPDIR)/cairo-gl-info.Plo - -rm -f ./$(DEPDIR)/cairo-gl-msaa-compositor.Plo - -rm -f ./$(DEPDIR)/cairo-gl-operand.Plo - -rm -f ./$(DEPDIR)/cairo-gl-shaders.Plo - -rm -f ./$(DEPDIR)/cairo-gl-source.Plo - -rm -f ./$(DEPDIR)/cairo-gl-spans-compositor.Plo - -rm -f ./$(DEPDIR)/cairo-gl-surface.Plo - -rm -f ./$(DEPDIR)/cairo-gl-traps-compositor.Plo - -rm -f ./$(DEPDIR)/cairo-glx-context.Plo - -rm -f ./$(DEPDIR)/cairo-gstate.Plo - -rm -f ./$(DEPDIR)/cairo-hash.Plo - -rm -f ./$(DEPDIR)/cairo-hull.Plo - -rm -f ./$(DEPDIR)/cairo-image-compositor.Plo - -rm -f ./$(DEPDIR)/cairo-image-info.Plo - -rm -f ./$(DEPDIR)/cairo-image-source.Plo - -rm -f ./$(DEPDIR)/cairo-image-surface.Plo - -rm -f ./$(DEPDIR)/cairo-line.Plo - -rm -f ./$(DEPDIR)/cairo-lzw.Plo - -rm -f ./$(DEPDIR)/cairo-mask-compositor.Plo - -rm -f ./$(DEPDIR)/cairo-matrix.Plo - -rm -f ./$(DEPDIR)/cairo-mempool.Plo - -rm -f ./$(DEPDIR)/cairo-mesh-pattern-rasterizer.Plo - -rm -f ./$(DEPDIR)/cairo-misc.Plo - -rm -f ./$(DEPDIR)/cairo-mono-scan-converter.Plo - -rm -f ./$(DEPDIR)/cairo-mutex.Plo - -rm -f ./$(DEPDIR)/cairo-no-compositor.Plo - -rm -f ./$(DEPDIR)/cairo-observer.Plo - -rm -f ./$(DEPDIR)/cairo-os2-surface.Plo - -rm -f ./$(DEPDIR)/cairo-output-stream.Plo - -rm -f ./$(DEPDIR)/cairo-paginated-surface.Plo - -rm -f ./$(DEPDIR)/cairo-path-bounds.Plo - -rm -f ./$(DEPDIR)/cairo-path-fill.Plo - -rm -f ./$(DEPDIR)/cairo-path-fixed.Plo - -rm -f ./$(DEPDIR)/cairo-path-in-fill.Plo - -rm -f ./$(DEPDIR)/cairo-path-stroke-boxes.Plo - -rm -f ./$(DEPDIR)/cairo-path-stroke-polygon.Plo - -rm -f ./$(DEPDIR)/cairo-path-stroke-traps.Plo - -rm -f ./$(DEPDIR)/cairo-path-stroke-tristrip.Plo - -rm -f ./$(DEPDIR)/cairo-path-stroke.Plo - -rm -f ./$(DEPDIR)/cairo-path.Plo - -rm -f ./$(DEPDIR)/cairo-pattern.Plo - -rm -f ./$(DEPDIR)/cairo-pdf-interchange.Plo - -rm -f ./$(DEPDIR)/cairo-pdf-operators.Plo - -rm -f ./$(DEPDIR)/cairo-pdf-shading.Plo - -rm -f ./$(DEPDIR)/cairo-pdf-surface.Plo - -rm -f ./$(DEPDIR)/cairo-pen.Plo - -rm -f ./$(DEPDIR)/cairo-png.Plo - -rm -f ./$(DEPDIR)/cairo-polygon-intersect.Plo - -rm -f ./$(DEPDIR)/cairo-polygon-reduce.Plo - -rm -f ./$(DEPDIR)/cairo-polygon.Plo - -rm -f ./$(DEPDIR)/cairo-ps-surface.Plo - -rm -f ./$(DEPDIR)/cairo-qt-surface.Plo - -rm -f ./$(DEPDIR)/cairo-quartz-font.Plo - -rm -f ./$(DEPDIR)/cairo-quartz-image-surface.Plo - -rm -f ./$(DEPDIR)/cairo-quartz-surface.Plo - -rm -f ./$(DEPDIR)/cairo-raster-source-pattern.Plo - -rm -f ./$(DEPDIR)/cairo-recording-surface.Plo - -rm -f ./$(DEPDIR)/cairo-rectangle.Plo - -rm -f ./$(DEPDIR)/cairo-rectangular-scan-converter.Plo - -rm -f ./$(DEPDIR)/cairo-region.Plo - -rm -f ./$(DEPDIR)/cairo-rtree.Plo - -rm -f ./$(DEPDIR)/cairo-scaled-font-subsets.Plo - -rm -f ./$(DEPDIR)/cairo-scaled-font.Plo - -rm -f ./$(DEPDIR)/cairo-script-surface.Plo - -rm -f ./$(DEPDIR)/cairo-shape-mask-compositor.Plo - -rm -f ./$(DEPDIR)/cairo-slope.Plo - -rm -f ./$(DEPDIR)/cairo-spans-compositor.Plo - -rm -f ./$(DEPDIR)/cairo-spans.Plo - -rm -f ./$(DEPDIR)/cairo-spline.Plo - -rm -f ./$(DEPDIR)/cairo-stroke-dash.Plo - -rm -f ./$(DEPDIR)/cairo-stroke-style.Plo - -rm -f ./$(DEPDIR)/cairo-surface-clipper.Plo - -rm -f ./$(DEPDIR)/cairo-surface-fallback.Plo - -rm -f ./$(DEPDIR)/cairo-surface-observer.Plo - -rm -f ./$(DEPDIR)/cairo-surface-offset.Plo - -rm -f ./$(DEPDIR)/cairo-surface-snapshot.Plo - -rm -f ./$(DEPDIR)/cairo-surface-subsurface.Plo - -rm -f ./$(DEPDIR)/cairo-surface-wrapper.Plo - -rm -f ./$(DEPDIR)/cairo-surface.Plo - -rm -f ./$(DEPDIR)/cairo-svg-surface.Plo - -rm -f ./$(DEPDIR)/cairo-tag-attributes.Plo - -rm -f ./$(DEPDIR)/cairo-tag-stack.Plo - -rm -f ./$(DEPDIR)/cairo-tee-surface.Plo - -rm -f ./$(DEPDIR)/cairo-time.Plo - -rm -f ./$(DEPDIR)/cairo-tor-scan-converter.Plo - -rm -f ./$(DEPDIR)/cairo-tor22-scan-converter.Plo - -rm -f ./$(DEPDIR)/cairo-toy-font-face.Plo - -rm -f ./$(DEPDIR)/cairo-traps-compositor.Plo - -rm -f ./$(DEPDIR)/cairo-traps.Plo - -rm -f ./$(DEPDIR)/cairo-tristrip.Plo - -rm -f ./$(DEPDIR)/cairo-truetype-subset.Plo - -rm -f ./$(DEPDIR)/cairo-type1-fallback.Plo - -rm -f ./$(DEPDIR)/cairo-type1-glyph-names.Plo - -rm -f ./$(DEPDIR)/cairo-type1-subset.Plo - -rm -f ./$(DEPDIR)/cairo-type3-glyph-surface.Plo - -rm -f ./$(DEPDIR)/cairo-unicode.Plo - -rm -f ./$(DEPDIR)/cairo-user-font.Plo - -rm -f ./$(DEPDIR)/cairo-version.Plo - -rm -f ./$(DEPDIR)/cairo-vg-surface.Plo - -rm -f ./$(DEPDIR)/cairo-wgl-context.Plo - -rm -f ./$(DEPDIR)/cairo-wideint.Plo - -rm -f ./$(DEPDIR)/cairo-win32-debug.Plo - -rm -f ./$(DEPDIR)/cairo-win32-device.Plo - -rm -f ./$(DEPDIR)/cairo-win32-display-surface.Plo - -rm -f ./$(DEPDIR)/cairo-win32-font.Plo - -rm -f ./$(DEPDIR)/cairo-win32-gdi-compositor.Plo - -rm -f ./$(DEPDIR)/cairo-win32-printing-surface.Plo - -rm -f ./$(DEPDIR)/cairo-win32-surface.Plo - -rm -f ./$(DEPDIR)/cairo-win32-system.Plo - -rm -f ./$(DEPDIR)/cairo-xcb-connection-core.Plo - -rm -f ./$(DEPDIR)/cairo-xcb-connection-render.Plo - -rm -f ./$(DEPDIR)/cairo-xcb-connection-shm.Plo - -rm -f ./$(DEPDIR)/cairo-xcb-connection.Plo - -rm -f ./$(DEPDIR)/cairo-xcb-resources.Plo - -rm -f ./$(DEPDIR)/cairo-xcb-screen.Plo - -rm -f ./$(DEPDIR)/cairo-xcb-shm.Plo - -rm -f ./$(DEPDIR)/cairo-xcb-surface-core.Plo - -rm -f ./$(DEPDIR)/cairo-xcb-surface-render.Plo - -rm -f ./$(DEPDIR)/cairo-xcb-surface.Plo - -rm -f ./$(DEPDIR)/cairo-xlib-core-compositor.Plo - -rm -f ./$(DEPDIR)/cairo-xlib-display.Plo - -rm -f ./$(DEPDIR)/cairo-xlib-fallback-compositor.Plo - -rm -f ./$(DEPDIR)/cairo-xlib-render-compositor.Plo - -rm -f ./$(DEPDIR)/cairo-xlib-screen.Plo - -rm -f ./$(DEPDIR)/cairo-xlib-source.Plo - -rm -f ./$(DEPDIR)/cairo-xlib-surface-shm.Plo - -rm -f ./$(DEPDIR)/cairo-xlib-surface.Plo - -rm -f ./$(DEPDIR)/cairo-xlib-visual.Plo - -rm -f ./$(DEPDIR)/cairo-xlib-xcb-surface.Plo - -rm -f ./$(DEPDIR)/cairo-xml-surface.Plo - -rm -f ./$(DEPDIR)/cairo.Plo - -rm -f ./$(DEPDIR)/check-link.Po - -rm -f ./$(DEPDIR)/test-base-compositor-surface.Plo - -rm -f ./$(DEPDIR)/test-compositor-surface.Plo - -rm -f ./$(DEPDIR)/test-null-compositor-surface.Plo - -rm -f ./$(DEPDIR)/test-paginated-surface.Plo - -rm -f Makefile -maintainer-clean-am: distclean-am maintainer-clean-generic - -mostlyclean: mostlyclean-am - -mostlyclean-am: mostlyclean-compile mostlyclean-generic \ - mostlyclean-libtool - -pdf: pdf-am - -pdf-am: - -ps: ps-am - -ps-am: - -uninstall-am: uninstall-cairoincludeHEADERS uninstall-libLTLIBRARIES \ - uninstall-nodist_cairoincludeHEADERS uninstall-pkgconfigDATA - -.MAKE: all check check-am install install-am install-strip - -.PHONY: CTAGS GTAGS TAGS all all-am am--depfiles check check-TESTS \ - check-am clean clean-checkPROGRAMS clean-generic \ - clean-libLTLIBRARIES clean-libtool clean-noinstLTLIBRARIES \ - cscopelist-am ctags ctags-am distclean distclean-compile \ - distclean-generic distclean-libtool distclean-tags distdir dvi \ - dvi-am html html-am info info-am install install-am \ - install-cairoincludeHEADERS install-data install-data-am \ - install-dvi install-dvi-am install-exec install-exec-am \ - install-html install-html-am install-info install-info-am \ - install-libLTLIBRARIES install-man \ - install-nodist_cairoincludeHEADERS install-pdf install-pdf-am \ - install-pkgconfigDATA install-ps install-ps-am install-strip \ - installcheck installcheck-am installdirs maintainer-clean \ - maintainer-clean-generic mostlyclean mostlyclean-compile \ - mostlyclean-generic mostlyclean-libtool pdf pdf-am ps ps-am \ - recheck tags tags-am uninstall uninstall-am \ - uninstall-cairoincludeHEADERS uninstall-libLTLIBRARIES \ - uninstall-nodist_cairoincludeHEADERS uninstall-pkgconfigDATA - -.PRECIOUS: Makefile - - -$(top_builddir)/config.h: $(top_srcdir)/config.h.in - cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) config.h -cairo-features.h cairo-supported-features.h: - cd $(top_builddir) && ./config.status src/$@ -cairo.def: cairo-features.h $(enabled_cairo_headers) - @echo Generating $@ - @(echo EXPORTS; \ - (cd $(srcdir); cat $(enabled_cairo_headers) || echo 'cairo_ERROR ()' ) | \ - $(EGREP) -v '^# *include' | \ - ( cat cairo-features.h - | $(CPP) -D__cplusplus - || echo 'cairo_ERROR ()' ) | \ - $(EGREP) '^cairo_.* \(' | \ - sed -e 's/[ ].*//' | \ - sort; \ - echo LIBRARY libcairo-$(CAIRO_VERSION_SONUM).dll; \ - ) >$@ - @ ! grep -q cairo_ERROR $@ || ($(RM) $@; false) - -check: headers-standalone - -# The pre-processed result is used by check-{def,plt}.sh to determine whether -# cairo has been compiled with symbol hiding. -.c.i: $(cairoinclude_HEADERS) $(nodist_cairoinclude_HEADERS) cairoint.h $(top_builddir)/config.h - $(CPP) $(PREPROCESS_ARGS) $< -o $@ -.c.s: $(cairoinclude_HEADERS) $(nodist_cairoinclude_HEADERS) cairoint.h $(top_builddir)/config.h - $(CC) $(COMPILE_ARGS) $< -S -o $@ -sparse: - @echo Checking enabled sources with sparse checker - @status=true; for f in $(enabled_cairo_sources) $(enabled_cairo_cxx_sources); do \ - echo $(SPARSE) $(PREPROCESS_ARGS) $(srcdir)/$$f; \ - $(SPARSE) $(PREPROCESS_ARGS) $(srcdir)/$$f || status=false; \ - done; $$status -splint: - @echo Checking enabled sources with splint checker - @status=true; for f in $(enabled_cairo_sources) $(enabled_cairo_cxx_sources); do \ - echo $(SPLINT) $(PREPROCESS_ARGS) $(srcdir)/$$f; \ - $(SPLINT) $(PREPROCESS_ARGS) $(srcdir)/$$f || status=false; \ - done; $$status -uno: - @echo Checking enabled sources with uno checker - cd $(srcdir); $(UNO) $(PREPROCESS_ARGS) -DHAVE_CONFIG_H -U__GNUC__ $(enabled_cairo_sources) - -headers-standalone: $(enabled_cairo_headers) $(enabled_cairo_private) - @echo Checking that enabled public/private headers can be compiled standalone - @status=true; for f in $(enabled_cairo_headers) $(enabled_cairo_private); do \ - echo " CHECK $$f"; \ - echo "#include \"$(srcdir)/$$f\"" > headers-standalone-tmp.c; \ - echo "int main(int argc, char * argv[]) { return 0; }" >> headers-standalone-tmp.c; \ - $(COMPILE) -o headers-standalone-tmp headers-standalone-tmp.c || status=false; \ - $(RM) headers-standalone-tmp headers-standalone-tmp.c; \ - done; $$status - @touch $@ - -analysis: all headers-standalone sparse splint uno - -# Tell versions [3.59,3.63) of GNU make to not export all variables. -# Otherwise a system limit (for SysV at least) may be exceeded. -.NOEXPORT: diff --git a/gfx/cairo/cairo/src/Makefile.sources b/gfx/cairo/cairo/src/Makefile.sources deleted file mode 100644 index 0a1ce35274..0000000000 --- a/gfx/cairo/cairo/src/Makefile.sources +++ /dev/null @@ -1,461 +0,0 @@ -# Makefile.sources -# -# This file is the canonical location listing all the source files used -# to build the cairo library. Every source file is categorized as one of: -# -# * public header file -# * private header file (must end in -private.h except for cairoint.h) -# * source code file -# -# Every source file should be specified exactly once, grouped with the -# feature that uses the source file. If more than one feature use the -# file (like pdf_operators or font_subset files), the files should be -# appended to to the base cairo files, and the code inside them -# enabled/disabled using C preprocessor macros defined in cairoint.h. -# See how pdf_operators or font_subset are handled. -# -# The sources are picked up according to the configured features -# by the generated file Makefile.am.features or Makefile.win32.features. -# -# These are a few special source files. Those are not included in this -# file to not confuse build systems. Each build system must handle them -# separately. These files include: -# -# * cairo-features.h: -# This file is generated by configure and includes macros signifying -# which features are enabled. This file should be installed like -# other public headers, but should NOT be distributed in the cairo -# distribution. -# -# * cairo-supported-features.h: -# This file is generated by configure and includes macros signifying -# all supported features. This is used by gtk-doc to generate -# documentation for all those macros, enabled or not. -# This file is NOT used during the build of the library and should -# NOT be installed or distributed. -# -# Please follow the strict syntax of this file, including keeping file -# lists sorted. -# - -cairo_headers = cairo.h cairo-version.h cairo-deprecated.h -cairo_private = \ - cairoint.h \ - cairo-analysis-surface-private.h \ - cairo-arc-private.h \ - cairo-array-private.h \ - cairo-atomic-private.h \ - cairo-backend-private.h \ - cairo-box-inline.h \ - cairo-boxes-private.h \ - cairo-cache-private.h \ - cairo-clip-inline.h \ - cairo-clip-private.h \ - cairo-combsort-inline.h \ - cairo-compiler-private.h \ - cairo-composite-rectangles-private.h \ - cairo-compositor-private.h \ - cairo-contour-inline.h \ - cairo-contour-private.h \ - cairo-damage-private.h \ - cairo-default-context-private.h \ - cairo-device-private.h \ - cairo-error-inline.h \ - cairo-error-private.h \ - cairo-fixed-private.h \ - cairo-fixed-type-private.h \ - cairo-fontconfig-private.h \ - cairo-freed-pool-private.h \ - cairo-freelist-private.h \ - cairo-freelist-type-private.h \ - cairo-gstate-private.h \ - cairo-hash-private.h \ - cairo-image-info-private.h \ - cairo-image-surface-inline.h \ - cairo-image-surface-private.h \ - cairo-line-inline.h \ - cairo-line-private.h \ - cairo-list-inline.h \ - cairo-list-private.h \ - cairo-malloc-private.h \ - cairo-mempool-private.h \ - cairo-mutex-impl-private.h \ - cairo-mutex-list-private.h \ - cairo-mutex-private.h \ - cairo-mutex-type-private.h \ - cairo-output-stream-private.h \ - cairo-paginated-private.h \ - cairo-paginated-surface-private.h \ - cairo-path-fixed-private.h \ - cairo-path-private.h \ - cairo-pattern-inline.h \ - cairo-pattern-private.h \ - cairo-pixman-private.h \ - cairo-private.h \ - cairo-recording-surface-inline.h \ - cairo-recording-surface-private.h \ - cairo-reference-count-private.h \ - cairo-region-private.h \ - cairo-rtree-private.h \ - cairo-scaled-font-private.h \ - cairo-slope-private.h \ - cairo-spans-compositor-private.h \ - cairo-spans-private.h \ - cairo-stroke-dash-private.h \ - cairo-surface-backend-private.h \ - cairo-surface-clipper-private.h \ - cairo-surface-fallback-private.h \ - cairo-surface-inline.h \ - cairo-surface-observer-inline.h \ - cairo-surface-observer-private.h \ - cairo-surface-offset-private.h \ - cairo-surface-private.h \ - cairo-surface-snapshot-inline.h \ - cairo-surface-snapshot-private.h \ - cairo-surface-subsurface-inline.h \ - cairo-surface-subsurface-private.h \ - cairo-surface-wrapper-private.h \ - cairo-time-private.h \ - cairo-traps-private.h \ - cairo-tristrip-private.h \ - cairo-types-private.h \ - cairo-user-font-private.h \ - cairo-wideint-private.h \ - cairo-wideint-type-private.h \ - $(NULL) -cairo_sources = \ - cairo-analysis-surface.c \ - cairo-arc.c \ - cairo-array.c \ - cairo-atomic.c \ - cairo-base64-stream.c \ - cairo-base85-stream.c \ - cairo-bentley-ottmann-rectangular.c \ - cairo-bentley-ottmann-rectilinear.c \ - cairo-bentley-ottmann.c \ - cairo-botor-scan-converter.c \ - cairo-boxes-intersect.c \ - cairo-boxes.c \ - cairo-cache.c \ - cairo-clip-boxes.c \ - cairo-clip-polygon.c \ - cairo-clip-region.c \ - cairo-clip-surface.c \ - cairo-clip-tor-scan-converter.c \ - cairo-clip.c \ - cairo-color.c \ - cairo-composite-rectangles.c \ - cairo-compositor.c \ - cairo-contour.c \ - cairo-damage.c \ - cairo-debug.c \ - cairo-default-context.c \ - cairo-device.c \ - cairo-error.c \ - cairo-fallback-compositor.c \ - cairo-fixed.c \ - cairo-font-face-twin-data.c \ - cairo-font-face-twin.c \ - cairo-font-face.c \ - cairo-font-options.c \ - cairo-freed-pool.c \ - cairo-freelist.c \ - cairo-gstate.c \ - cairo-hash.c \ - cairo-hull.c \ - cairo-image-compositor.c \ - cairo-image-info.c \ - cairo-image-source.c \ - cairo-image-surface.c \ - cairo-line.c \ - cairo-lzw.c \ - cairo-mask-compositor.c \ - cairo-matrix.c \ - cairo-mempool.c \ - cairo-mesh-pattern-rasterizer.c \ - cairo-misc.c \ - cairo-mono-scan-converter.c \ - cairo-mutex.c \ - cairo-no-compositor.c \ - cairo-observer.c \ - cairo-output-stream.c \ - cairo-paginated-surface.c \ - cairo-path-bounds.c \ - cairo-path-fill.c \ - cairo-path-fixed.c \ - cairo-path-in-fill.c \ - cairo-path-stroke-boxes.c \ - cairo-path-stroke-polygon.c \ - cairo-path-stroke-traps.c \ - cairo-path-stroke-tristrip.c \ - cairo-path-stroke.c \ - cairo-path.c \ - cairo-pattern.c \ - cairo-pen.c \ - cairo-polygon-intersect.c \ - cairo-polygon-reduce.c \ - cairo-polygon.c \ - cairo-raster-source-pattern.c \ - cairo-recording-surface.c \ - cairo-rectangle.c \ - cairo-rectangular-scan-converter.c \ - cairo-region.c \ - cairo-rtree.c \ - cairo-scaled-font.c \ - cairo-shape-mask-compositor.c \ - cairo-slope.c \ - cairo-spans-compositor.c \ - cairo-spans.c \ - cairo-spline.c \ - cairo-stroke-dash.c \ - cairo-stroke-style.c \ - cairo-surface-clipper.c \ - cairo-surface-fallback.c \ - cairo-surface-observer.c \ - cairo-surface-offset.c \ - cairo-surface-snapshot.c \ - cairo-surface-subsurface.c \ - cairo-surface-wrapper.c \ - cairo-surface.c \ - cairo-time.c \ - cairo-tor-scan-converter.c \ - cairo-tor22-scan-converter.c \ - cairo-toy-font-face.c \ - cairo-traps-compositor.c \ - cairo-traps.c \ - cairo-tristrip.c \ - cairo-unicode.c \ - cairo-user-font.c \ - cairo-version.c \ - cairo-wideint.c \ - cairo.c \ - $(NULL) - -_cairo_font_subset_private = \ - cairo-scaled-font-subsets-private.h \ - cairo-truetype-subset-private.h \ - cairo-type1-private.h \ - cairo-type3-glyph-surface-private.h \ - $(NULL) -_cairo_font_subset_sources = \ - cairo-cff-subset.c \ - cairo-scaled-font-subsets.c \ - cairo-truetype-subset.c \ - cairo-type1-fallback.c \ - cairo-type1-glyph-names.c \ - cairo-type1-subset.c \ - cairo-type3-glyph-surface.c \ - $(NULL) -cairo_private += $(_cairo_font_subset_private) -cairo_sources += $(_cairo_font_subset_sources) - -cairo_egl_sources = -cairo_glx_sources = -cairo_wgl_sources = - -_cairo_pdf_operators_private = \ - cairo-pdf-operators-private.h \ - cairo-pdf-shading-private.h \ - cairo-tag-attributes-private.h \ - $(NULL) -_cairo_pdf_operators_sources = \ - cairo-pdf-operators.c \ - cairo-pdf-shading.c \ - cairo-tag-attributes.c \ - $(NULL) -cairo_private += $(_cairo_pdf_operators_private) -cairo_sources += $(_cairo_pdf_operators_sources) - -cairo_png_sources = cairo-png.c - -cairo_ps_headers = cairo-ps.h -cairo_ps_private = cairo-ps-surface-private.h -cairo_ps_sources = cairo-ps-surface.c - -_cairo_deflate_stream_sources = cairo-deflate-stream.c -cairo_sources += $(_cairo_deflate_stream_sources) - -cairo_pdf_headers = cairo-pdf.h -cairo_pdf_private = cairo-pdf-surface-private.h cairo-tag-stack-private.h -cairo_pdf_sources = cairo-pdf-surface.c cairo-pdf-interchange.c cairo-tag-stack.c - -cairo_svg_headers = cairo-svg.h -cairo_svg_private = cairo-svg-surface-private.h -cairo_svg_sources = cairo-svg-surface.c - -cairo_ft_headers = cairo-ft.h -cairo_ft_private = cairo-ft-private.h -cairo_ft_sources = cairo-ft-font.c - -# These are private, even though they look like public headers -cairo_test_surfaces_private = \ - test-compositor-surface.h \ - test-compositor-surface-private.h \ - test-null-compositor-surface.h \ - test-paginated-surface.h \ - $(NULL) -cairo_test_surfaces_sources = \ - test-compositor-surface.c \ - test-null-compositor-surface.c \ - test-base-compositor-surface.c \ - test-paginated-surface.c \ - $(NULL) - -cairo_xlib_headers = cairo-xlib.h -cairo_xlib_private = \ - cairo-xlib-private.h \ - cairo-xlib-surface-private.h \ - cairo-xlib-xrender-private.h \ - $(NULL) -cairo_xlib_sources = \ - cairo-xlib-display.c \ - cairo-xlib-core-compositor.c \ - cairo-xlib-fallback-compositor.c \ - cairo-xlib-render-compositor.c \ - cairo-xlib-screen.c \ - cairo-xlib-source.c \ - cairo-xlib-surface.c \ - cairo-xlib-surface-shm.c \ - cairo-xlib-visual.c \ - cairo-xlib-xcb-surface.c \ - $(NULL) - -cairo_xlib_xrender_headers = cairo-xlib-xrender.h - -cairo_xcb_headers = cairo-xcb.h -cairo_xcb_private = cairo-xcb-private.h -cairo_xcb_sources = \ - cairo-xcb-connection.c \ - cairo-xcb-connection-core.c \ - cairo-xcb-connection-render.c \ - cairo-xcb-connection-shm.c \ - cairo-xcb-screen.c \ - cairo-xcb-shm.c \ - cairo-xcb-surface.c \ - cairo-xcb-surface-core.c \ - cairo-xcb-surface-render.c \ - cairo-xcb-resources.c \ - $(NULL) - -cairo_qt_headers = cairo-qt.h -cairo_qt_cxx_sources = cairo-qt-surface.cpp - -cairo_quartz_headers = cairo-quartz.h -cairo_quartz_private = cairo-quartz-private.h -cairo_quartz_sources = cairo-quartz-surface.c - -cairo_quartz_image_headers = cairo-quartz-image.h -cairo_quartz_image_sources = cairo-quartz-image-surface.c - -cairo_quartz_font_sources = cairo-quartz-font.c - -cairo_win32_headers = cairo-win32.h -cairo_win32_private = win32/cairo-win32-private.h -cairo_win32_sources = \ - win32/cairo-win32-debug.c \ - win32/cairo-win32-device.c \ - win32/cairo-win32-gdi-compositor.c \ - win32/cairo-win32-system.c \ - win32/cairo-win32-surface.c \ - win32/cairo-win32-display-surface.c \ - win32/cairo-win32-printing-surface.c \ - $(NULL) -cairo_win32_font_sources = \ - win32/cairo-win32-font.c \ - $(NULL) - -cairo_os2_headers = cairo-os2.h -cairo_os2_private = cairo-os2-private.h -cairo_os2_sources = cairo-os2-surface.c - -# automake is stupid enough to always use c++ linker if we enable the -# following lines, even if beos surface is not enabled. Disable it for now. -cairo_beos_headers = cairo-beos.h -cairo_beos_cxx_sources = cairo-beos-surface.cpp - -cairo_gl_headers = cairo-gl.h -cairo_gl_private = cairo-gl-private.h \ - cairo-gl-dispatch-private.h \ - cairo-gl-ext-def-private.h \ - cairo-gl-gradient-private.h - -cairo_gl_sources = cairo-gl-composite.c \ - cairo-gl-device.c \ - cairo-gl-dispatch.c \ - cairo-gl-glyphs.c \ - cairo-gl-gradient.c \ - cairo-gl-info.c \ - cairo-gl-msaa-compositor.c \ - cairo-gl-operand.c \ - cairo-gl-shaders.c \ - cairo-gl-source.c \ - cairo-gl-spans-compositor.c \ - cairo-gl-surface.c \ - cairo-gl-traps-compositor.c - -cairo_glesv2_headers = $(cairo_gl_headers) -cairo_glesv2_private = $(cairo_gl_private) -cairo_glesv2_sources = $(cairo_gl_sources) - -cairo_glesv3_headers = $(cairo_gl_headers) -cairo_glesv3_private = $(cairo_gl_private) -cairo_glesv3_sources = $(cairo_gl_sources) - -cairo_egl_sources += cairo-egl-context.c -cairo_glx_sources += cairo-glx-context.c -cairo_wgl_sources += cairo-wgl-context.c - -cairo_directfb_headers = cairo-directfb.h -cairo_directfb_sources = cairo-directfb-surface.c - -cairo_drm_headers = cairo-drm.h -cairo_drm_private = drm/cairo-drm-private.h \ - drm/cairo-drm-intel-private.h \ - drm/cairo-drm-intel-brw-defines.h \ - drm/cairo-drm-intel-brw-structs.h \ - drm/cairo-drm-intel-brw-eu.h \ - drm/cairo-drm-intel-command-private.h \ - drm/cairo-drm-intel-ioctl-private.h \ - drm/cairo-drm-i915-private.h \ - drm/cairo-drm-i965-private.h \ - drm/cairo-drm-radeon-private.h -cairo_drm_sources = drm/cairo-drm.c \ - drm/cairo-drm-bo.c \ - drm/cairo-drm-surface.c \ - drm/cairo-drm-intel.c \ - drm/cairo-drm-intel-debug.c \ - drm/cairo-drm-intel-surface.c \ - drm/cairo-drm-i915-surface.c \ - drm/cairo-drm-i915-glyphs.c \ - drm/cairo-drm-i915-shader.c \ - drm/cairo-drm-i915-spans.c \ - drm/cairo-drm-i965-surface.c \ - drm/cairo-drm-i965-glyphs.c \ - drm/cairo-drm-i965-shader.c \ - drm/cairo-drm-i965-spans.c \ - drm/cairo-drm-intel-brw-eu.c \ - drm/cairo-drm-intel-brw-eu-emit.c \ - drm/cairo-drm-intel-brw-eu-util.c \ - drm/cairo-drm-radeon.c \ - drm/cairo-drm-radeon-surface.c -cairo_gallium_sources = drm/cairo-drm-gallium-surface.c - -cairo_script_headers = cairo-script.h -cairo_script_private = cairo-script-private.h -cairo_script_sources = cairo-script-surface.c - -cairo_tee_headers = cairo-tee.h -cairo_tee_private = cairo-tee-surface-private.h -cairo_tee_sources = cairo-tee-surface.c - -cairo_xml_headers = cairo-xml.h -cairo_xml_sources = cairo-xml-surface.c - -cairo_vg_headers = cairo-vg.h -cairo_vg_sources = cairo-vg-surface.c - -cairo_cogl_headers = cairo-cogl.h -cairo_cogl_private = cairo-cogl-private.h \ - cairo-cogl-gradient-private.h -cairo_cogl_sources = cairo-cogl-surface.c \ - cairo-cogl-gradient.c diff --git a/gfx/cairo/cairo/src/Makefile.win32 b/gfx/cairo/cairo/src/Makefile.win32 deleted file mode 100644 index 9afefe2b79..0000000000 --- a/gfx/cairo/cairo/src/Makefile.win32 +++ /dev/null @@ -1,28 +0,0 @@ -top_srcdir = .. -include $(top_srcdir)/build/Makefile.win32.common -include Makefile.win32.features - -SOURCES = $(enabled_cairo_sources) - -STATIC_SOURCES = cairo-system.c - -OBJECTS = $(patsubst %.c, $(CFG)/%.obj, $(SOURCES)) -OBJECTS_STATIC = $(patsubst %cairo-system.obj, %cairo-system-static.obj, $(OBJECTS)) - -static: inform $(CFG)/cairo-static.lib -dynamic: inform $(CFG)/cairo.dll - -$(CFG)/cairo.dll: $(OBJECTS) - @$(LD) $(CAIRO_LDFLAGS) -DLL -OUT:$@ $(CAIRO_LIBS) $(PIXMAN_LIBS) $(OBJECTS) - -$(CFG)/cairo-static.lib: $(OBJECTS_STATIC) - @$(AR) $(CAIRO_ARFLAGS) -OUT:$@ $(PIXMAN_LIBS) $(OBJECTS_STATIC) - -all: inform $(CFG)/cairo.dll $(CFG)/cairo-static.lib - @echo "Built successfully!" - @echo "You should copy the following files to a proper place now:" - @echo "" - @echo " src/cairo-features.h" - @for x in $(enabled_cairo_headers); do echo " src/$$x"; done - @echo " src/$(CFG)/cairo.dll" - @echo " src/$(CFG)/cairo-static.lib" diff --git a/gfx/cairo/cairo/src/Makefile.win32.features b/gfx/cairo/cairo/src/Makefile.win32.features deleted file mode 100644 index 377d6dd12a..0000000000 --- a/gfx/cairo/cairo/src/Makefile.win32.features +++ /dev/null @@ -1,661 +0,0 @@ -# Generated by configure. Do not edit. - -ifeq ($(top_srcdir),) -include Makefile.sources -else -include $(top_srcdir)/src/Makefile.sources -endif - -supported_cairo_headers = $(cairo_headers) -unsupported_cairo_headers = -all_cairo_headers = $(cairo_headers) -all_cairo_private = $(cairo_private) -all_cairo_cxx_sources = $(cairo_cxx_sources) -all_cairo_sources = $(cairo_sources) - -enabled_cairo_headers = $(cairo_headers) -enabled_cairo_private = $(cairo_private) -enabled_cairo_cxx_sources = $(cairo_cxx_sources) -enabled_cairo_sources = $(cairo_sources) - -all_cairo_pkgconf = cairo.pc -enabled_cairo_pkgconf = cairo.pc - -supported_cairo_headers += $(cairo_xlib_headers) -all_cairo_headers += $(cairo_xlib_headers) -all_cairo_private += $(cairo_xlib_private) -all_cairo_cxx_sources += $(cairo_xlib_cxx_sources) -all_cairo_sources += $(cairo_xlib_sources) -ifeq ($(CAIRO_HAS_XLIB_SURFACE),1) -enabled_cairo_headers += $(cairo_xlib_headers) -enabled_cairo_private += $(cairo_xlib_private) -enabled_cairo_cxx_sources += $(cairo_xlib_cxx_sources) -enabled_cairo_sources += $(cairo_xlib_sources) -endif -all_cairo_pkgconf += cairo-xlib.pc -ifeq ($(CAIRO_HAS_XLIB_SURFACE),1) -enabled_cairo_pkgconf += cairo-xlib.pc -endif - -supported_cairo_headers += $(cairo_xlib_xrender_headers) -all_cairo_headers += $(cairo_xlib_xrender_headers) -all_cairo_private += $(cairo_xlib_xrender_private) -all_cairo_cxx_sources += $(cairo_xlib_xrender_cxx_sources) -all_cairo_sources += $(cairo_xlib_xrender_sources) -ifeq ($(CAIRO_HAS_XLIB_XRENDER_SURFACE),1) -enabled_cairo_headers += $(cairo_xlib_xrender_headers) -enabled_cairo_private += $(cairo_xlib_xrender_private) -enabled_cairo_cxx_sources += $(cairo_xlib_xrender_cxx_sources) -enabled_cairo_sources += $(cairo_xlib_xrender_sources) -endif -all_cairo_pkgconf += cairo-xlib-xrender.pc -ifeq ($(CAIRO_HAS_XLIB_XRENDER_SURFACE),1) -enabled_cairo_pkgconf += cairo-xlib-xrender.pc -endif - -supported_cairo_headers += $(cairo_xcb_headers) -all_cairo_headers += $(cairo_xcb_headers) -all_cairo_private += $(cairo_xcb_private) -all_cairo_cxx_sources += $(cairo_xcb_cxx_sources) -all_cairo_sources += $(cairo_xcb_sources) -ifeq ($(CAIRO_HAS_XCB_SURFACE),1) -enabled_cairo_headers += $(cairo_xcb_headers) -enabled_cairo_private += $(cairo_xcb_private) -enabled_cairo_cxx_sources += $(cairo_xcb_cxx_sources) -enabled_cairo_sources += $(cairo_xcb_sources) -endif -all_cairo_pkgconf += cairo-xcb.pc -ifeq ($(CAIRO_HAS_XCB_SURFACE),1) -enabled_cairo_pkgconf += cairo-xcb.pc -endif - -unsupported_cairo_headers += $(cairo_xlib_xcb_headers) -all_cairo_headers += $(cairo_xlib_xcb_headers) -all_cairo_private += $(cairo_xlib_xcb_private) -all_cairo_cxx_sources += $(cairo_xlib_xcb_cxx_sources) -all_cairo_sources += $(cairo_xlib_xcb_sources) -ifeq ($(CAIRO_HAS_XLIB_XCB_FUNCTIONS),1) -enabled_cairo_headers += $(cairo_xlib_xcb_headers) -enabled_cairo_private += $(cairo_xlib_xcb_private) -enabled_cairo_cxx_sources += $(cairo_xlib_xcb_cxx_sources) -enabled_cairo_sources += $(cairo_xlib_xcb_sources) -endif -all_cairo_pkgconf += cairo-xlib-xcb.pc -ifeq ($(CAIRO_HAS_XLIB_XCB_FUNCTIONS),1) -enabled_cairo_pkgconf += cairo-xlib-xcb.pc -endif - -supported_cairo_headers += $(cairo_xcb_shm_headers) -all_cairo_headers += $(cairo_xcb_shm_headers) -all_cairo_private += $(cairo_xcb_shm_private) -all_cairo_cxx_sources += $(cairo_xcb_shm_cxx_sources) -all_cairo_sources += $(cairo_xcb_shm_sources) -ifeq ($(CAIRO_HAS_XCB_SHM_FUNCTIONS),1) -enabled_cairo_headers += $(cairo_xcb_shm_headers) -enabled_cairo_private += $(cairo_xcb_shm_private) -enabled_cairo_cxx_sources += $(cairo_xcb_shm_cxx_sources) -enabled_cairo_sources += $(cairo_xcb_shm_sources) -endif -all_cairo_pkgconf += cairo-xcb-shm.pc -ifeq ($(CAIRO_HAS_XCB_SHM_FUNCTIONS),1) -enabled_cairo_pkgconf += cairo-xcb-shm.pc -endif - -unsupported_cairo_headers += $(cairo_qt_headers) -all_cairo_headers += $(cairo_qt_headers) -all_cairo_private += $(cairo_qt_private) -all_cairo_cxx_sources += $(cairo_qt_cxx_sources) -all_cairo_sources += $(cairo_qt_sources) -ifeq ($(CAIRO_HAS_QT_SURFACE),1) -enabled_cairo_headers += $(cairo_qt_headers) -enabled_cairo_private += $(cairo_qt_private) -enabled_cairo_cxx_sources += $(cairo_qt_cxx_sources) -enabled_cairo_sources += $(cairo_qt_sources) -endif -all_cairo_pkgconf += cairo-qt.pc -ifeq ($(CAIRO_HAS_QT_SURFACE),1) -enabled_cairo_pkgconf += cairo-qt.pc -endif - -supported_cairo_headers += $(cairo_quartz_headers) -all_cairo_headers += $(cairo_quartz_headers) -all_cairo_private += $(cairo_quartz_private) -all_cairo_cxx_sources += $(cairo_quartz_cxx_sources) -all_cairo_sources += $(cairo_quartz_sources) -ifeq ($(CAIRO_HAS_QUARTZ_SURFACE),1) -enabled_cairo_headers += $(cairo_quartz_headers) -enabled_cairo_private += $(cairo_quartz_private) -enabled_cairo_cxx_sources += $(cairo_quartz_cxx_sources) -enabled_cairo_sources += $(cairo_quartz_sources) -endif -all_cairo_pkgconf += cairo-quartz.pc -ifeq ($(CAIRO_HAS_QUARTZ_SURFACE),1) -enabled_cairo_pkgconf += cairo-quartz.pc -endif - -supported_cairo_headers += $(cairo_quartz_font_headers) -all_cairo_headers += $(cairo_quartz_font_headers) -all_cairo_private += $(cairo_quartz_font_private) -all_cairo_cxx_sources += $(cairo_quartz_font_cxx_sources) -all_cairo_sources += $(cairo_quartz_font_sources) -ifeq ($(CAIRO_HAS_QUARTZ_FONT),1) -enabled_cairo_headers += $(cairo_quartz_font_headers) -enabled_cairo_private += $(cairo_quartz_font_private) -enabled_cairo_cxx_sources += $(cairo_quartz_font_cxx_sources) -enabled_cairo_sources += $(cairo_quartz_font_sources) -endif -all_cairo_pkgconf += cairo-quartz-font.pc -ifeq ($(CAIRO_HAS_QUARTZ_FONT),1) -enabled_cairo_pkgconf += cairo-quartz-font.pc -endif - -unsupported_cairo_headers += $(cairo_quartz_image_headers) -all_cairo_headers += $(cairo_quartz_image_headers) -all_cairo_private += $(cairo_quartz_image_private) -all_cairo_cxx_sources += $(cairo_quartz_image_cxx_sources) -all_cairo_sources += $(cairo_quartz_image_sources) -ifeq ($(CAIRO_HAS_QUARTZ_IMAGE_SURFACE),1) -enabled_cairo_headers += $(cairo_quartz_image_headers) -enabled_cairo_private += $(cairo_quartz_image_private) -enabled_cairo_cxx_sources += $(cairo_quartz_image_cxx_sources) -enabled_cairo_sources += $(cairo_quartz_image_sources) -endif -all_cairo_pkgconf += cairo-quartz-image.pc -ifeq ($(CAIRO_HAS_QUARTZ_IMAGE_SURFACE),1) -enabled_cairo_pkgconf += cairo-quartz-image.pc -endif - -supported_cairo_headers += $(cairo_win32_headers) -all_cairo_headers += $(cairo_win32_headers) -all_cairo_private += $(cairo_win32_private) -all_cairo_cxx_sources += $(cairo_win32_cxx_sources) -all_cairo_sources += $(cairo_win32_sources) -ifeq ($(CAIRO_HAS_WIN32_SURFACE),1) -enabled_cairo_headers += $(cairo_win32_headers) -enabled_cairo_private += $(cairo_win32_private) -enabled_cairo_cxx_sources += $(cairo_win32_cxx_sources) -enabled_cairo_sources += $(cairo_win32_sources) -endif -all_cairo_pkgconf += cairo-win32.pc -ifeq ($(CAIRO_HAS_WIN32_SURFACE),1) -enabled_cairo_pkgconf += cairo-win32.pc -endif - -supported_cairo_headers += $(cairo_win32_font_headers) -all_cairo_headers += $(cairo_win32_font_headers) -all_cairo_private += $(cairo_win32_font_private) -all_cairo_cxx_sources += $(cairo_win32_font_cxx_sources) -all_cairo_sources += $(cairo_win32_font_sources) -ifeq ($(CAIRO_HAS_WIN32_FONT),1) -enabled_cairo_headers += $(cairo_win32_font_headers) -enabled_cairo_private += $(cairo_win32_font_private) -enabled_cairo_cxx_sources += $(cairo_win32_font_cxx_sources) -enabled_cairo_sources += $(cairo_win32_font_sources) -endif -all_cairo_pkgconf += cairo-win32-font.pc -ifeq ($(CAIRO_HAS_WIN32_FONT),1) -enabled_cairo_pkgconf += cairo-win32-font.pc -endif - -unsupported_cairo_headers += $(cairo_os2_headers) -all_cairo_headers += $(cairo_os2_headers) -all_cairo_private += $(cairo_os2_private) -all_cairo_cxx_sources += $(cairo_os2_cxx_sources) -all_cairo_sources += $(cairo_os2_sources) -ifeq ($(CAIRO_HAS_OS2_SURFACE),1) -enabled_cairo_headers += $(cairo_os2_headers) -enabled_cairo_private += $(cairo_os2_private) -enabled_cairo_cxx_sources += $(cairo_os2_cxx_sources) -enabled_cairo_sources += $(cairo_os2_sources) -endif -all_cairo_pkgconf += cairo-os2.pc -ifeq ($(CAIRO_HAS_OS2_SURFACE),1) -enabled_cairo_pkgconf += cairo-os2.pc -endif - -unsupported_cairo_headers += $(cairo_beos_headers) -all_cairo_headers += $(cairo_beos_headers) -all_cairo_private += $(cairo_beos_private) -all_cairo_cxx_sources += $(cairo_beos_cxx_sources) -all_cairo_sources += $(cairo_beos_sources) -ifeq ($(CAIRO_HAS_BEOS_SURFACE),1) -enabled_cairo_headers += $(cairo_beos_headers) -enabled_cairo_private += $(cairo_beos_private) -enabled_cairo_cxx_sources += $(cairo_beos_cxx_sources) -enabled_cairo_sources += $(cairo_beos_sources) -endif -all_cairo_pkgconf += cairo-beos.pc -ifeq ($(CAIRO_HAS_BEOS_SURFACE),1) -enabled_cairo_pkgconf += cairo-beos.pc -endif - -unsupported_cairo_headers += $(cairo_drm_headers) -all_cairo_headers += $(cairo_drm_headers) -all_cairo_private += $(cairo_drm_private) -all_cairo_cxx_sources += $(cairo_drm_cxx_sources) -all_cairo_sources += $(cairo_drm_sources) -ifeq ($(CAIRO_HAS_DRM_SURFACE),1) -enabled_cairo_headers += $(cairo_drm_headers) -enabled_cairo_private += $(cairo_drm_private) -enabled_cairo_cxx_sources += $(cairo_drm_cxx_sources) -enabled_cairo_sources += $(cairo_drm_sources) -endif -all_cairo_pkgconf += cairo-drm.pc -ifeq ($(CAIRO_HAS_DRM_SURFACE),1) -enabled_cairo_pkgconf += cairo-drm.pc -endif - -unsupported_cairo_headers += $(cairo_gallium_headers) -all_cairo_headers += $(cairo_gallium_headers) -all_cairo_private += $(cairo_gallium_private) -all_cairo_cxx_sources += $(cairo_gallium_cxx_sources) -all_cairo_sources += $(cairo_gallium_sources) -ifeq ($(CAIRO_HAS_GALLIUM_SURFACE),1) -enabled_cairo_headers += $(cairo_gallium_headers) -enabled_cairo_private += $(cairo_gallium_private) -enabled_cairo_cxx_sources += $(cairo_gallium_cxx_sources) -enabled_cairo_sources += $(cairo_gallium_sources) -endif -all_cairo_pkgconf += cairo-gallium.pc -ifeq ($(CAIRO_HAS_GALLIUM_SURFACE),1) -enabled_cairo_pkgconf += cairo-gallium.pc -endif - -supported_cairo_headers += $(cairo_png_headers) -all_cairo_headers += $(cairo_png_headers) -all_cairo_private += $(cairo_png_private) -all_cairo_cxx_sources += $(cairo_png_cxx_sources) -all_cairo_sources += $(cairo_png_sources) -ifeq ($(CAIRO_HAS_PNG_FUNCTIONS),1) -enabled_cairo_headers += $(cairo_png_headers) -enabled_cairo_private += $(cairo_png_private) -enabled_cairo_cxx_sources += $(cairo_png_cxx_sources) -enabled_cairo_sources += $(cairo_png_sources) -endif -all_cairo_pkgconf += cairo-png.pc -ifeq ($(CAIRO_HAS_PNG_FUNCTIONS),1) -enabled_cairo_pkgconf += cairo-png.pc -endif - -unsupported_cairo_headers += $(cairo_gl_headers) -all_cairo_headers += $(cairo_gl_headers) -all_cairo_private += $(cairo_gl_private) -all_cairo_cxx_sources += $(cairo_gl_cxx_sources) -all_cairo_sources += $(cairo_gl_sources) -ifeq ($(CAIRO_HAS_GL_SURFACE),1) -enabled_cairo_headers += $(cairo_gl_headers) -enabled_cairo_private += $(cairo_gl_private) -enabled_cairo_cxx_sources += $(cairo_gl_cxx_sources) -enabled_cairo_sources += $(cairo_gl_sources) -endif -all_cairo_pkgconf += cairo-gl.pc -ifeq ($(CAIRO_HAS_GL_SURFACE),1) -enabled_cairo_pkgconf += cairo-gl.pc -endif - -unsupported_cairo_headers += $(cairo_glesv2_headers) -all_cairo_headers += $(cairo_glesv2_headers) -all_cairo_private += $(cairo_glesv2_private) -all_cairo_cxx_sources += $(cairo_glesv2_cxx_sources) -all_cairo_sources += $(cairo_glesv2_sources) -ifeq ($(CAIRO_HAS_GLESV2_SURFACE),1) -enabled_cairo_headers += $(cairo_glesv2_headers) -enabled_cairo_private += $(cairo_glesv2_private) -enabled_cairo_cxx_sources += $(cairo_glesv2_cxx_sources) -enabled_cairo_sources += $(cairo_glesv2_sources) -endif -all_cairo_pkgconf += cairo-glesv2.pc -ifeq ($(CAIRO_HAS_GLESV2_SURFACE),1) -enabled_cairo_pkgconf += cairo-glesv2.pc -endif - -unsupported_cairo_headers += $(cairo_glesv3_headers) -all_cairo_headers += $(cairo_glesv3_headers) -all_cairo_private += $(cairo_glesv3_private) -all_cairo_cxx_sources += $(cairo_glesv3_cxx_sources) -all_cairo_sources += $(cairo_glesv3_sources) -ifeq ($(CAIRO_HAS_GLESV3_SURFACE),1) -enabled_cairo_headers += $(cairo_glesv3_headers) -enabled_cairo_private += $(cairo_glesv3_private) -enabled_cairo_cxx_sources += $(cairo_glesv3_cxx_sources) -enabled_cairo_sources += $(cairo_glesv3_sources) -endif -all_cairo_pkgconf += cairo-glesv3.pc -ifeq ($(CAIRO_HAS_GLESV3_SURFACE),1) -enabled_cairo_pkgconf += cairo-glesv3.pc -endif - -unsupported_cairo_headers += $(cairo_cogl_headers) -all_cairo_headers += $(cairo_cogl_headers) -all_cairo_private += $(cairo_cogl_private) -all_cairo_cxx_sources += $(cairo_cogl_cxx_sources) -all_cairo_sources += $(cairo_cogl_sources) -ifeq ($(CAIRO_HAS_COGL_SURFACE),1) -enabled_cairo_headers += $(cairo_cogl_headers) -enabled_cairo_private += $(cairo_cogl_private) -enabled_cairo_cxx_sources += $(cairo_cogl_cxx_sources) -enabled_cairo_sources += $(cairo_cogl_sources) -endif -all_cairo_pkgconf += cairo-cogl.pc -ifeq ($(CAIRO_HAS_COGL_SURFACE),1) -enabled_cairo_pkgconf += cairo-cogl.pc -endif - -unsupported_cairo_headers += $(cairo_directfb_headers) -all_cairo_headers += $(cairo_directfb_headers) -all_cairo_private += $(cairo_directfb_private) -all_cairo_cxx_sources += $(cairo_directfb_cxx_sources) -all_cairo_sources += $(cairo_directfb_sources) -ifeq ($(CAIRO_HAS_DIRECTFB_SURFACE),1) -enabled_cairo_headers += $(cairo_directfb_headers) -enabled_cairo_private += $(cairo_directfb_private) -enabled_cairo_cxx_sources += $(cairo_directfb_cxx_sources) -enabled_cairo_sources += $(cairo_directfb_sources) -endif -all_cairo_pkgconf += cairo-directfb.pc -ifeq ($(CAIRO_HAS_DIRECTFB_SURFACE),1) -enabled_cairo_pkgconf += cairo-directfb.pc -endif - -unsupported_cairo_headers += $(cairo_vg_headers) -all_cairo_headers += $(cairo_vg_headers) -all_cairo_private += $(cairo_vg_private) -all_cairo_cxx_sources += $(cairo_vg_cxx_sources) -all_cairo_sources += $(cairo_vg_sources) -ifeq ($(CAIRO_HAS_VG_SURFACE),1) -enabled_cairo_headers += $(cairo_vg_headers) -enabled_cairo_private += $(cairo_vg_private) -enabled_cairo_cxx_sources += $(cairo_vg_cxx_sources) -enabled_cairo_sources += $(cairo_vg_sources) -endif -all_cairo_pkgconf += cairo-vg.pc -ifeq ($(CAIRO_HAS_VG_SURFACE),1) -enabled_cairo_pkgconf += cairo-vg.pc -endif - -supported_cairo_headers += $(cairo_egl_headers) -all_cairo_headers += $(cairo_egl_headers) -all_cairo_private += $(cairo_egl_private) -all_cairo_cxx_sources += $(cairo_egl_cxx_sources) -all_cairo_sources += $(cairo_egl_sources) -ifeq ($(CAIRO_HAS_EGL_FUNCTIONS),1) -enabled_cairo_headers += $(cairo_egl_headers) -enabled_cairo_private += $(cairo_egl_private) -enabled_cairo_cxx_sources += $(cairo_egl_cxx_sources) -enabled_cairo_sources += $(cairo_egl_sources) -endif -all_cairo_pkgconf += cairo-egl.pc -ifeq ($(CAIRO_HAS_EGL_FUNCTIONS),1) -enabled_cairo_pkgconf += cairo-egl.pc -endif - -supported_cairo_headers += $(cairo_glx_headers) -all_cairo_headers += $(cairo_glx_headers) -all_cairo_private += $(cairo_glx_private) -all_cairo_cxx_sources += $(cairo_glx_cxx_sources) -all_cairo_sources += $(cairo_glx_sources) -ifeq ($(CAIRO_HAS_GLX_FUNCTIONS),1) -enabled_cairo_headers += $(cairo_glx_headers) -enabled_cairo_private += $(cairo_glx_private) -enabled_cairo_cxx_sources += $(cairo_glx_cxx_sources) -enabled_cairo_sources += $(cairo_glx_sources) -endif -all_cairo_pkgconf += cairo-glx.pc -ifeq ($(CAIRO_HAS_GLX_FUNCTIONS),1) -enabled_cairo_pkgconf += cairo-glx.pc -endif - -supported_cairo_headers += $(cairo_wgl_headers) -all_cairo_headers += $(cairo_wgl_headers) -all_cairo_private += $(cairo_wgl_private) -all_cairo_cxx_sources += $(cairo_wgl_cxx_sources) -all_cairo_sources += $(cairo_wgl_sources) -ifeq ($(CAIRO_HAS_WGL_FUNCTIONS),1) -enabled_cairo_headers += $(cairo_wgl_headers) -enabled_cairo_private += $(cairo_wgl_private) -enabled_cairo_cxx_sources += $(cairo_wgl_cxx_sources) -enabled_cairo_sources += $(cairo_wgl_sources) -endif -all_cairo_pkgconf += cairo-wgl.pc -ifeq ($(CAIRO_HAS_WGL_FUNCTIONS),1) -enabled_cairo_pkgconf += cairo-wgl.pc -endif - -supported_cairo_headers += $(cairo_script_headers) -all_cairo_headers += $(cairo_script_headers) -all_cairo_private += $(cairo_script_private) -all_cairo_cxx_sources += $(cairo_script_cxx_sources) -all_cairo_sources += $(cairo_script_sources) -ifeq ($(CAIRO_HAS_SCRIPT_SURFACE),1) -enabled_cairo_headers += $(cairo_script_headers) -enabled_cairo_private += $(cairo_script_private) -enabled_cairo_cxx_sources += $(cairo_script_cxx_sources) -enabled_cairo_sources += $(cairo_script_sources) -endif -all_cairo_pkgconf += cairo-script.pc -ifeq ($(CAIRO_HAS_SCRIPT_SURFACE),1) -enabled_cairo_pkgconf += cairo-script.pc -endif - -supported_cairo_headers += $(cairo_ft_headers) -all_cairo_headers += $(cairo_ft_headers) -all_cairo_private += $(cairo_ft_private) -all_cairo_cxx_sources += $(cairo_ft_cxx_sources) -all_cairo_sources += $(cairo_ft_sources) -ifeq ($(CAIRO_HAS_FT_FONT),1) -enabled_cairo_headers += $(cairo_ft_headers) -enabled_cairo_private += $(cairo_ft_private) -enabled_cairo_cxx_sources += $(cairo_ft_cxx_sources) -enabled_cairo_sources += $(cairo_ft_sources) -endif -all_cairo_pkgconf += cairo-ft.pc -ifeq ($(CAIRO_HAS_FT_FONT),1) -enabled_cairo_pkgconf += cairo-ft.pc -endif - -supported_cairo_headers += $(cairo_fc_headers) -all_cairo_headers += $(cairo_fc_headers) -all_cairo_private += $(cairo_fc_private) -all_cairo_cxx_sources += $(cairo_fc_cxx_sources) -all_cairo_sources += $(cairo_fc_sources) -ifeq ($(CAIRO_HAS_FC_FONT),1) -enabled_cairo_headers += $(cairo_fc_headers) -enabled_cairo_private += $(cairo_fc_private) -enabled_cairo_cxx_sources += $(cairo_fc_cxx_sources) -enabled_cairo_sources += $(cairo_fc_sources) -endif -all_cairo_pkgconf += cairo-fc.pc -ifeq ($(CAIRO_HAS_FC_FONT),1) -enabled_cairo_pkgconf += cairo-fc.pc -endif - -supported_cairo_headers += $(cairo_ps_headers) -all_cairo_headers += $(cairo_ps_headers) -all_cairo_private += $(cairo_ps_private) -all_cairo_cxx_sources += $(cairo_ps_cxx_sources) -all_cairo_sources += $(cairo_ps_sources) -ifeq ($(CAIRO_HAS_PS_SURFACE),1) -enabled_cairo_headers += $(cairo_ps_headers) -enabled_cairo_private += $(cairo_ps_private) -enabled_cairo_cxx_sources += $(cairo_ps_cxx_sources) -enabled_cairo_sources += $(cairo_ps_sources) -endif -all_cairo_pkgconf += cairo-ps.pc -ifeq ($(CAIRO_HAS_PS_SURFACE),1) -enabled_cairo_pkgconf += cairo-ps.pc -endif - -supported_cairo_headers += $(cairo_pdf_headers) -all_cairo_headers += $(cairo_pdf_headers) -all_cairo_private += $(cairo_pdf_private) -all_cairo_cxx_sources += $(cairo_pdf_cxx_sources) -all_cairo_sources += $(cairo_pdf_sources) -ifeq ($(CAIRO_HAS_PDF_SURFACE),1) -enabled_cairo_headers += $(cairo_pdf_headers) -enabled_cairo_private += $(cairo_pdf_private) -enabled_cairo_cxx_sources += $(cairo_pdf_cxx_sources) -enabled_cairo_sources += $(cairo_pdf_sources) -endif -all_cairo_pkgconf += cairo-pdf.pc -ifeq ($(CAIRO_HAS_PDF_SURFACE),1) -enabled_cairo_pkgconf += cairo-pdf.pc -endif - -supported_cairo_headers += $(cairo_svg_headers) -all_cairo_headers += $(cairo_svg_headers) -all_cairo_private += $(cairo_svg_private) -all_cairo_cxx_sources += $(cairo_svg_cxx_sources) -all_cairo_sources += $(cairo_svg_sources) -ifeq ($(CAIRO_HAS_SVG_SURFACE),1) -enabled_cairo_headers += $(cairo_svg_headers) -enabled_cairo_private += $(cairo_svg_private) -enabled_cairo_cxx_sources += $(cairo_svg_cxx_sources) -enabled_cairo_sources += $(cairo_svg_sources) -endif -all_cairo_pkgconf += cairo-svg.pc -ifeq ($(CAIRO_HAS_SVG_SURFACE),1) -enabled_cairo_pkgconf += cairo-svg.pc -endif - -all_cairo_private += $(cairo_test_surfaces_private) $(cairo_test_surfaces_headers) -all_cairo_cxx_sources += $(cairo_test_surfaces_cxx_sources) -all_cairo_sources += $(cairo_test_surfaces_sources) -ifeq ($(CAIRO_HAS_TEST_SURFACES),1) -enabled_cairo_private += $(cairo_test_surfaces_private) $(cairo_test_surfaces_headers) -enabled_cairo_cxx_sources += $(cairo_test_surfaces_cxx_sources) -enabled_cairo_sources += $(cairo_test_surfaces_sources) -endif - -supported_cairo_headers += $(cairo_image_headers) -all_cairo_headers += $(cairo_image_headers) -all_cairo_private += $(cairo_image_private) -all_cairo_cxx_sources += $(cairo_image_cxx_sources) -all_cairo_sources += $(cairo_image_sources) -enabled_cairo_headers += $(cairo_image_headers) -enabled_cairo_private += $(cairo_image_private) -enabled_cairo_cxx_sources += $(cairo_image_cxx_sources) -enabled_cairo_sources += $(cairo_image_sources) - -supported_cairo_headers += $(cairo_mime_headers) -all_cairo_headers += $(cairo_mime_headers) -all_cairo_private += $(cairo_mime_private) -all_cairo_cxx_sources += $(cairo_mime_cxx_sources) -all_cairo_sources += $(cairo_mime_sources) -enabled_cairo_headers += $(cairo_mime_headers) -enabled_cairo_private += $(cairo_mime_private) -enabled_cairo_cxx_sources += $(cairo_mime_cxx_sources) -enabled_cairo_sources += $(cairo_mime_sources) - -supported_cairo_headers += $(cairo_recording_headers) -all_cairo_headers += $(cairo_recording_headers) -all_cairo_private += $(cairo_recording_private) -all_cairo_cxx_sources += $(cairo_recording_cxx_sources) -all_cairo_sources += $(cairo_recording_sources) -enabled_cairo_headers += $(cairo_recording_headers) -enabled_cairo_private += $(cairo_recording_private) -enabled_cairo_cxx_sources += $(cairo_recording_cxx_sources) -enabled_cairo_sources += $(cairo_recording_sources) - -supported_cairo_headers += $(cairo_observer_headers) -all_cairo_headers += $(cairo_observer_headers) -all_cairo_private += $(cairo_observer_private) -all_cairo_cxx_sources += $(cairo_observer_cxx_sources) -all_cairo_sources += $(cairo_observer_sources) -enabled_cairo_headers += $(cairo_observer_headers) -enabled_cairo_private += $(cairo_observer_private) -enabled_cairo_cxx_sources += $(cairo_observer_cxx_sources) -enabled_cairo_sources += $(cairo_observer_sources) - -unsupported_cairo_headers += $(cairo_tee_headers) -all_cairo_headers += $(cairo_tee_headers) -all_cairo_private += $(cairo_tee_private) -all_cairo_cxx_sources += $(cairo_tee_cxx_sources) -all_cairo_sources += $(cairo_tee_sources) -ifeq ($(CAIRO_HAS_TEE_SURFACE),1) -enabled_cairo_headers += $(cairo_tee_headers) -enabled_cairo_private += $(cairo_tee_private) -enabled_cairo_cxx_sources += $(cairo_tee_cxx_sources) -enabled_cairo_sources += $(cairo_tee_sources) -endif -all_cairo_pkgconf += cairo-tee.pc -ifeq ($(CAIRO_HAS_TEE_SURFACE),1) -enabled_cairo_pkgconf += cairo-tee.pc -endif - -unsupported_cairo_headers += $(cairo_xml_headers) -all_cairo_headers += $(cairo_xml_headers) -all_cairo_private += $(cairo_xml_private) -all_cairo_cxx_sources += $(cairo_xml_cxx_sources) -all_cairo_sources += $(cairo_xml_sources) -ifeq ($(CAIRO_HAS_XML_SURFACE),1) -enabled_cairo_headers += $(cairo_xml_headers) -enabled_cairo_private += $(cairo_xml_private) -enabled_cairo_cxx_sources += $(cairo_xml_cxx_sources) -enabled_cairo_sources += $(cairo_xml_sources) -endif -all_cairo_pkgconf += cairo-xml.pc -ifeq ($(CAIRO_HAS_XML_SURFACE),1) -enabled_cairo_pkgconf += cairo-xml.pc -endif - -supported_cairo_headers += $(cairo_user_headers) -all_cairo_headers += $(cairo_user_headers) -all_cairo_private += $(cairo_user_private) -all_cairo_cxx_sources += $(cairo_user_cxx_sources) -all_cairo_sources += $(cairo_user_sources) -enabled_cairo_headers += $(cairo_user_headers) -enabled_cairo_private += $(cairo_user_private) -enabled_cairo_cxx_sources += $(cairo_user_cxx_sources) -enabled_cairo_sources += $(cairo_user_sources) - -all_cairo_private += $(cairo_pthread_private) $(cairo_pthread_headers) -all_cairo_cxx_sources += $(cairo_pthread_cxx_sources) -all_cairo_sources += $(cairo_pthread_sources) -ifeq ($(CAIRO_HAS_PTHREAD),1) -enabled_cairo_private += $(cairo_pthread_private) $(cairo_pthread_headers) -enabled_cairo_cxx_sources += $(cairo_pthread_cxx_sources) -enabled_cairo_sources += $(cairo_pthread_sources) -endif - -supported_cairo_headers += $(cairo_gobject_headers) -all_cairo_headers += $(cairo_gobject_headers) -all_cairo_private += $(cairo_gobject_private) -all_cairo_cxx_sources += $(cairo_gobject_cxx_sources) -all_cairo_sources += $(cairo_gobject_sources) -ifeq ($(CAIRO_HAS_GOBJECT_FUNCTIONS),1) -enabled_cairo_headers += $(cairo_gobject_headers) -enabled_cairo_private += $(cairo_gobject_private) -enabled_cairo_cxx_sources += $(cairo_gobject_cxx_sources) -enabled_cairo_sources += $(cairo_gobject_sources) -endif -all_cairo_pkgconf += cairo-gobject.pc -ifeq ($(CAIRO_HAS_GOBJECT_FUNCTIONS),1) -enabled_cairo_pkgconf += cairo-gobject.pc -endif - -all_cairo_private += $(cairo_trace_private) $(cairo_trace_headers) -all_cairo_cxx_sources += $(cairo_trace_cxx_sources) -all_cairo_sources += $(cairo_trace_sources) -ifeq ($(CAIRO_HAS_TRACE),1) -enabled_cairo_private += $(cairo_trace_private) $(cairo_trace_headers) -enabled_cairo_cxx_sources += $(cairo_trace_cxx_sources) -enabled_cairo_sources += $(cairo_trace_sources) -endif - -all_cairo_private += $(cairo_interpreter_private) $(cairo_interpreter_headers) -all_cairo_cxx_sources += $(cairo_interpreter_cxx_sources) -all_cairo_sources += $(cairo_interpreter_sources) -ifeq ($(CAIRO_HAS_INTERPRETER),1) -enabled_cairo_private += $(cairo_interpreter_private) $(cairo_interpreter_headers) -enabled_cairo_cxx_sources += $(cairo_interpreter_cxx_sources) -enabled_cairo_sources += $(cairo_interpreter_sources) -endif - -all_cairo_private += $(cairo_symbol_lookup_private) $(cairo_symbol_lookup_headers) -all_cairo_cxx_sources += $(cairo_symbol_lookup_cxx_sources) -all_cairo_sources += $(cairo_symbol_lookup_sources) -ifeq ($(CAIRO_HAS_SYMBOL_LOOKUP),1) -enabled_cairo_private += $(cairo_symbol_lookup_private) $(cairo_symbol_lookup_headers) -enabled_cairo_cxx_sources += $(cairo_symbol_lookup_cxx_sources) -enabled_cairo_sources += $(cairo_symbol_lookup_sources) -endif diff --git a/gfx/cairo/cairo/src/cairo-analysis-surface-private.h b/gfx/cairo/cairo/src/cairo-analysis-surface-private.h index 1e054c209a..6489cceb86 100644 --- a/gfx/cairo/cairo/src/cairo-analysis-surface-private.h +++ b/gfx/cairo/cairo/src/cairo-analysis-surface-private.h @@ -38,7 +38,8 @@ #include "cairoint.h" cairo_private cairo_surface_t * -_cairo_analysis_surface_create (cairo_surface_t *target); +_cairo_analysis_surface_create (cairo_surface_t *target, + cairo_bool_t create_region_ids); cairo_private void _cairo_analysis_surface_set_ctm (cairo_surface_t *surface, @@ -64,6 +65,12 @@ cairo_private void _cairo_analysis_surface_get_bounding_box (cairo_surface_t *surface, cairo_box_t *bbox); +cairo_private unsigned int +_cairo_analysis_surface_get_source_region_id (cairo_surface_t *surface); + +cairo_private unsigned int +_cairo_analysis_surface_get_mask_region_id (cairo_surface_t *surface); + cairo_private cairo_int_status_t _cairo_analysis_surface_merge_status (cairo_int_status_t status_a, cairo_int_status_t status_b); @@ -71,4 +78,10 @@ _cairo_analysis_surface_merge_status (cairo_int_status_t status_a, cairo_private cairo_surface_t * _cairo_null_surface_create (cairo_content_t content); +static inline cairo_bool_t +_cairo_surface_is_analysis (const cairo_surface_t *surface) +{ + return (cairo_internal_surface_type_t)surface->backend->type == CAIRO_INTERNAL_SURFACE_TYPE_ANALYSIS; +} + #endif /* CAIRO_ANALYSIS_SURFACE_H */ diff --git a/gfx/cairo/cairo/src/cairo-analysis-surface.c b/gfx/cairo/cairo/src/cairo-analysis-surface.c index a118e338c4..6889be38f6 100644 --- a/gfx/cairo/cairo/src/cairo-analysis-surface.c +++ b/gfx/cairo/cairo/src/cairo-analysis-surface.c @@ -1,3 +1,4 @@ +/* -*- Mode: c; tab-width: 8; c-basic-offset: 4; indent-tabs-mode: t; -*- */ /* * Copyright © 2006 Keith Packard * Copyright © 2007 Adrian Johnson @@ -59,6 +60,10 @@ typedef struct { cairo_region_t fallback_region; cairo_box_t page_bbox; + cairo_bool_t create_region_ids; + unsigned source_region_id; + unsigned mask_region_id; + cairo_bool_t has_ctm; cairo_matrix_t ctm; @@ -257,7 +262,9 @@ _add_operation (cairo_analysis_surface_t *surface, static cairo_int_status_t _analyze_recording_surface_pattern (cairo_analysis_surface_t *surface, const cairo_pattern_t *pattern, - cairo_rectangle_int_t *extents) + cairo_rectangle_int_t *extents, + unsigned int *regions_id, + cairo_analysis_source_t source_type) { const cairo_surface_pattern_t *surface_pattern; cairo_analysis_surface_t *tmp; @@ -267,6 +274,7 @@ _analyze_recording_surface_pattern (cairo_analysis_surface_t *surface, cairo_int_status_t analysis_status = CAIRO_INT_STATUS_SUCCESS; cairo_bool_t surface_is_unbounded; cairo_bool_t unused; + cairo_bool_t replay_all; assert (pattern->type == CAIRO_PATTERN_TYPE_SURFACE); surface_pattern = (const cairo_surface_pattern_t *) pattern; @@ -280,9 +288,9 @@ _analyze_recording_surface_pattern (cairo_analysis_surface_t *surface, } tmp = (cairo_analysis_surface_t *) - _cairo_analysis_surface_create (surface->target); + _cairo_analysis_surface_create (surface->target, surface->create_region_ids); if (unlikely (tmp->base.status)) { - status =tmp->base.status; + status = tmp->base.status; goto cleanup1; } proxy = attach_proxy (source, &tmp->base); @@ -292,16 +300,63 @@ _analyze_recording_surface_pattern (cairo_analysis_surface_t *surface, assert (status == CAIRO_INT_STATUS_SUCCESS); _cairo_analysis_surface_set_ctm (&tmp->base, &p2d); - source = _cairo_surface_get_source (source, NULL); surface_is_unbounded = (pattern->extend == CAIRO_EXTEND_REPEAT - || pattern->extend == CAIRO_EXTEND_REFLECT); - status = _cairo_recording_surface_replay_and_create_regions (source, + || pattern->extend == CAIRO_EXTEND_REFLECT); + + if (surface->create_region_ids) { + status = _cairo_recording_surface_region_array_attach (source, regions_id); + if (unlikely (status)) + goto cleanup2; + } + + replay_all = FALSE; + if (surface->target->backend->analyze_recording_surface) { + status = surface->target->backend->analyze_recording_surface ( + surface->target, + surface_pattern, + surface->create_region_ids ? *regions_id : 0, + source_type, + TRUE); + if (status == CAIRO_INT_STATUS_ANALYZE_RECORDING_SURFACE_PATTERN) { + /* Ensure all commands are replayed even if previously + * replayed and assigned to a region.*/ + replay_all = TRUE; + status = CAIRO_INT_STATUS_SUCCESS; + } + if (unlikely (status)) + goto cleanup3; + } + + if (surface->create_region_ids) { + status = _cairo_recording_surface_replay_and_create_regions (source, + *regions_id, + &pattern->matrix, + &tmp->base, + surface_is_unbounded, + replay_all); + if (unlikely (status)) + goto cleanup3; + } else { + status = _cairo_recording_surface_replay_with_transform (source, &pattern->matrix, &tmp->base, - surface_is_unbounded); - if (unlikely (status)) - goto cleanup2; + surface_is_unbounded, + replay_all); + if (unlikely (status)) + goto cleanup3; + } + + if (surface->target->backend->analyze_recording_surface) { + status = surface->target->backend->analyze_recording_surface ( + surface->target, + surface_pattern, + surface->create_region_ids ? *regions_id : 0, + source_type, + FALSE); + if (unlikely (status)) + goto cleanup3; + } /* black background or mime data fills entire extents */ if (!(source->content & CAIRO_CONTENT_ALPHA) || _cairo_surface_has_mime_image (source)) { @@ -317,7 +372,7 @@ _analyze_recording_surface_pattern (cairo_analysis_surface_t *surface, if (status == CAIRO_INT_STATUS_IMAGE_FALLBACK) status = CAIRO_INT_STATUS_SUCCESS; if (unlikely (status)) - goto cleanup2; + goto cleanup3; } } @@ -341,6 +396,10 @@ _analyze_recording_surface_pattern (cairo_analysis_surface_t *surface, _cairo_box_round_to_rectangle (&tmp->page_bbox, extents); } + cleanup3: + if (surface->create_region_ids && unlikely (status)) { + _cairo_recording_surface_region_array_remove (source, *regions_id); + } cleanup2: detach_proxy (proxy); cleanup1: @@ -412,6 +471,8 @@ _cairo_analysis_surface_paint (void *abstract_surface, cairo_int_status_t backend_status; cairo_rectangle_int_t extents; + surface->source_region_id = 0; + surface->mask_region_id = 0; if (surface->target->backend->paint == NULL) { backend_status = CAIRO_INT_STATUS_UNSUPPORTED; } else { @@ -427,7 +488,11 @@ _cairo_analysis_surface_paint (void *abstract_surface, &extents); if (backend_status == CAIRO_INT_STATUS_ANALYZE_RECORDING_SURFACE_PATTERN) { cairo_rectangle_int_t rec_extents; - backend_status = _analyze_recording_surface_pattern (surface, source, &rec_extents); + backend_status = _analyze_recording_surface_pattern (surface, + source, + &rec_extents, + &surface->source_region_id, + CAIRO_ANALYSIS_SOURCE_PAINT); _cairo_rectangle_intersect (&extents, &rec_extents); } @@ -445,6 +510,8 @@ _cairo_analysis_surface_mask (void *abstract_surface, cairo_int_status_t backend_status; cairo_rectangle_int_t extents; + surface->source_region_id = 0; + surface->mask_region_id = 0; if (surface->target->backend->mask == NULL) { backend_status = CAIRO_INT_STATUS_UNSUPPORTED; } else { @@ -468,7 +535,11 @@ _cairo_analysis_surface_mask (void *abstract_surface, src_surface = _cairo_surface_get_source (src_surface, NULL); if (_cairo_surface_is_recording (src_surface)) { backend_source_status = - _analyze_recording_surface_pattern (surface, source, &rec_extents); + _analyze_recording_surface_pattern (surface, + source, + &rec_extents, + &surface->source_region_id, + CAIRO_ANALYSIS_SOURCE_MASK); if (_cairo_int_status_is_error (backend_source_status)) return backend_source_status; @@ -481,7 +552,11 @@ _cairo_analysis_surface_mask (void *abstract_surface, mask_surface = _cairo_surface_get_source (mask_surface, NULL); if (_cairo_surface_is_recording (mask_surface)) { backend_mask_status = - _analyze_recording_surface_pattern (surface, mask, &rec_extents); + _analyze_recording_surface_pattern (surface, + mask, + &rec_extents, + &surface->mask_region_id, + CAIRO_ANALYSIS_MASK_MASK); if (_cairo_int_status_is_error (backend_mask_status)) return backend_mask_status; @@ -520,6 +595,8 @@ _cairo_analysis_surface_stroke (void *abstract_surface, cairo_int_status_t backend_status; cairo_rectangle_int_t extents; + surface->source_region_id = 0; + surface->mask_region_id = 0; if (surface->target->backend->stroke == NULL) { backend_status = CAIRO_INT_STATUS_UNSUPPORTED; } else { @@ -538,7 +615,11 @@ _cairo_analysis_surface_stroke (void *abstract_surface, &extents); if (backend_status == CAIRO_INT_STATUS_ANALYZE_RECORDING_SURFACE_PATTERN) { cairo_rectangle_int_t rec_extents; - backend_status = _analyze_recording_surface_pattern (surface, source, &rec_extents); + backend_status = _analyze_recording_surface_pattern (surface, + source, + &rec_extents, + &surface->source_region_id, + CAIRO_ANALYSIS_SOURCE_STROKE); _cairo_rectangle_intersect (&extents, &rec_extents); } @@ -590,7 +671,11 @@ _cairo_analysis_surface_fill (void *abstract_surface, &extents); if (backend_status == CAIRO_INT_STATUS_ANALYZE_RECORDING_SURFACE_PATTERN) { cairo_rectangle_int_t rec_extents; - backend_status = _analyze_recording_surface_pattern (surface, source, &rec_extents); + backend_status = _analyze_recording_surface_pattern (surface, + source, + &rec_extents, + &surface->source_region_id, + CAIRO_ANALYSIS_SOURCE_FILL); _cairo_rectangle_intersect (&extents, &rec_extents); } @@ -619,6 +704,9 @@ _cairo_analysis_surface_show_glyphs (void *abstract_surface, cairo_int_status_t status, backend_status; cairo_rectangle_int_t extents, glyph_extents; + surface->source_region_id = 0; + surface->mask_region_id = 0; + /* Adapted from _cairo_surface_show_glyphs */ if (surface->target->backend->show_glyphs != NULL) { backend_status = @@ -654,7 +742,11 @@ _cairo_analysis_surface_show_glyphs (void *abstract_surface, &extents); if (backend_status == CAIRO_INT_STATUS_ANALYZE_RECORDING_SURFACE_PATTERN) { cairo_rectangle_int_t rec_extents; - backend_status = _analyze_recording_surface_pattern (surface, source, &rec_extents); + backend_status = _analyze_recording_surface_pattern (surface, + source, + &rec_extents, + &surface->source_region_id, + CAIRO_ANALYSIS_SOURCE_SHOW_GLYPHS); _cairo_rectangle_intersect (&extents, &rec_extents); } @@ -699,6 +791,9 @@ _cairo_analysis_surface_show_text_glyphs (void *abstract_surface, cairo_int_status_t status, backend_status; cairo_rectangle_int_t extents, glyph_extents; + surface->source_region_id = 0; + surface->mask_region_id = 0; + /* Adapted from _cairo_surface_show_glyphs */ backend_status = CAIRO_INT_STATUS_UNSUPPORTED; if (surface->target->backend->show_text_glyphs != NULL) { @@ -732,7 +827,11 @@ _cairo_analysis_surface_show_text_glyphs (void *abstract_surface, &extents); if (backend_status == CAIRO_INT_STATUS_ANALYZE_RECORDING_SURFACE_PATTERN) { cairo_rectangle_int_t rec_extents; - backend_status = _analyze_recording_surface_pattern (surface, source, &rec_extents); + _analyze_recording_surface_pattern (surface, + source, + &rec_extents, + &surface->source_region_id, + CAIRO_ANALYSIS_SOURCE_SHOW_GLYPHS); _cairo_rectangle_intersect (&extents, &rec_extents); } @@ -760,6 +859,8 @@ _cairo_analysis_surface_tag (void *abstract_surface, cairo_analysis_surface_t *surface = abstract_surface; cairo_int_status_t backend_status; + surface->source_region_id = 0; + surface->mask_region_id = 0; backend_status = CAIRO_INT_STATUS_SUCCESS; if (surface->target->backend->tag != NULL) { backend_status = @@ -774,6 +875,33 @@ _cairo_analysis_surface_tag (void *abstract_surface, return backend_status; } +static cairo_bool_t +_cairo_analysis_surface_supports_color_glyph (void *abstract_surface, + cairo_scaled_font_t *scaled_font, + unsigned long glyph_index) +{ + return TRUE; +} + +static cairo_int_status_t +_cairo_analysis_surface_command_id (void *abstract_surface, + unsigned int recording_id, + unsigned int command_id) +{ + cairo_analysis_surface_t *surface = abstract_surface; + cairo_int_status_t backend_status; + + backend_status = CAIRO_INT_STATUS_SUCCESS; + if (surface->target->backend->command_id != NULL) { + backend_status = + surface->target->backend->command_id (surface->target, + recording_id, + command_id); + } + + return backend_status; +} + static const cairo_surface_backend_t cairo_analysis_surface_backend = { CAIRO_INTERNAL_SURFACE_TYPE_ANALYSIS, @@ -808,11 +936,15 @@ static const cairo_surface_backend_t cairo_analysis_surface_backend = { _cairo_analysis_surface_has_show_text_glyphs, _cairo_analysis_surface_show_text_glyphs, NULL, /* get_supported_mime_types */ - _cairo_analysis_surface_tag + _cairo_analysis_surface_tag, + _cairo_analysis_surface_supports_color_glyph, + NULL, /* analyze_recording_surface */ + _cairo_analysis_surface_command_id, }; cairo_surface_t * -_cairo_analysis_surface_create (cairo_surface_t *target) +_cairo_analysis_surface_create (cairo_surface_t *target, + cairo_bool_t create_region_ids) { cairo_analysis_surface_t *surface; cairo_status_t status; @@ -841,6 +973,10 @@ _cairo_analysis_surface_create (cairo_surface_t *target) surface->has_supported = FALSE; surface->has_unsupported = FALSE; + surface->create_region_ids = create_region_ids; + surface->source_region_id = 0; + surface->mask_region_id = 0; + _cairo_region_init (&surface->supported_region); _cairo_region_init (&surface->fallback_region); @@ -918,6 +1054,23 @@ _cairo_analysis_surface_get_bounding_box (cairo_surface_t *abstract_surface, *bbox = surface->page_bbox; } +unsigned int +_cairo_analysis_surface_get_source_region_id (cairo_surface_t *abstract_surface) +{ + cairo_analysis_surface_t *surface = (cairo_analysis_surface_t *) abstract_surface; + + return surface->source_region_id; +} + +unsigned int +_cairo_analysis_surface_get_mask_region_id (cairo_surface_t *abstract_surface) +{ + cairo_analysis_surface_t *surface = (cairo_analysis_surface_t *) abstract_surface; + + return surface->mask_region_id; +} + + /* null surface type: a surface that does nothing (has no side effects, yay!) */ static cairo_int_status_t @@ -926,6 +1079,12 @@ _paint_return_success (void *surface, const cairo_pattern_t *source, const cairo_clip_t *clip) { + if (source->type == CAIRO_PATTERN_TYPE_SURFACE) { + cairo_surface_pattern_t *surface_pattern = (cairo_surface_pattern_t *) source; + if (surface_pattern->surface->type == CAIRO_SURFACE_TYPE_RECORDING) + return CAIRO_INT_STATUS_ANALYZE_RECORDING_SURFACE_PATTERN; + } + return CAIRO_INT_STATUS_SUCCESS; } @@ -936,6 +1095,18 @@ _mask_return_success (void *surface, const cairo_pattern_t *mask, const cairo_clip_t *clip) { + if (source->type == CAIRO_PATTERN_TYPE_SURFACE) { + cairo_surface_pattern_t *surface_pattern = (cairo_surface_pattern_t *) source; + if (surface_pattern->surface->type == CAIRO_SURFACE_TYPE_RECORDING) + return CAIRO_INT_STATUS_ANALYZE_RECORDING_SURFACE_PATTERN; + } + + if (mask->type == CAIRO_PATTERN_TYPE_SURFACE) { + cairo_surface_pattern_t *surface_pattern = (cairo_surface_pattern_t *) mask; + if (surface_pattern->surface->type == CAIRO_SURFACE_TYPE_RECORDING) + return CAIRO_INT_STATUS_ANALYZE_RECORDING_SURFACE_PATTERN; + } + return CAIRO_INT_STATUS_SUCCESS; } @@ -951,6 +1122,12 @@ _stroke_return_success (void *surface, cairo_antialias_t antialias, const cairo_clip_t *clip) { + if (source->type == CAIRO_PATTERN_TYPE_SURFACE) { + cairo_surface_pattern_t *surface_pattern = (cairo_surface_pattern_t *) source; + if (surface_pattern->surface->type == CAIRO_SURFACE_TYPE_RECORDING) + return CAIRO_INT_STATUS_ANALYZE_RECORDING_SURFACE_PATTERN; + } + return CAIRO_INT_STATUS_SUCCESS; } @@ -964,6 +1141,12 @@ _fill_return_success (void *surface, cairo_antialias_t antialias, const cairo_clip_t *clip) { + if (source->type == CAIRO_PATTERN_TYPE_SURFACE) { + cairo_surface_pattern_t *surface_pattern = (cairo_surface_pattern_t *) source; + if (surface_pattern->surface->type == CAIRO_SURFACE_TYPE_RECORDING) + return CAIRO_INT_STATUS_ANALYZE_RECORDING_SURFACE_PATTERN; + } + return CAIRO_INT_STATUS_SUCCESS; } @@ -976,6 +1159,12 @@ _show_glyphs_return_success (void *surface, cairo_scaled_font_t *scaled_font, const cairo_clip_t *clip) { + if (source->type == CAIRO_PATTERN_TYPE_SURFACE) { + cairo_surface_pattern_t *surface_pattern = (cairo_surface_pattern_t *) source; + if (surface_pattern->surface->type == CAIRO_SURFACE_TYPE_RECORDING) + return CAIRO_INT_STATUS_ANALYZE_RECORDING_SURFACE_PATTERN; + } + return CAIRO_INT_STATUS_SUCCESS; } @@ -1011,7 +1200,12 @@ static const cairo_surface_backend_t cairo_null_surface_backend = { NULL, /* fill_stroke */ _show_glyphs_return_success, /* show_glyphs */ NULL, /* has_show_text_glyphs */ - NULL /* show_text_glyphs */ + NULL, /* show_text_glyphs */ + NULL, /* get_supported_mime_types */ + NULL, /* tag */ + NULL, /* supports_color_glyph */ + NULL, /* analyze_recording_surface */ + NULL, /* command_id*/ }; cairo_surface_t * diff --git a/gfx/cairo/cairo/src/cairo-arc.c b/gfx/cairo/cairo/src/cairo-arc.c index 390397bae1..010b9c1a7a 100644 --- a/gfx/cairo/cairo/src/cairo-arc.c +++ b/gfx/cairo/cairo/src/cairo-arc.c @@ -90,16 +90,18 @@ _arc_max_angle_for_tolerance_normalized (double tolerance) { M_PI / 11.0, 9.81410988043554039085e-09 }, }; int table_size = ARRAY_LENGTH (table); + const int max_segments = 1000; /* this value is chosen arbitrarily. this gives an error of about 1.74909e-20 */ for (i = 0; i < table_size; i++) if (table[i].error < tolerance) return table[i].angle; ++i; + do { angle = M_PI / i++; error = _arc_error_normalized (angle); - } while (error > tolerance); + } while (error > tolerance && i < max_segments); return angle; } @@ -186,6 +188,9 @@ _cairo_arc_in_direction (cairo_t *cr, if (cairo_status (cr)) return; + if (! ISFINITE (angle_max) || ! ISFINITE (angle_min)) + return; + assert (angle_max >= angle_min); if (angle_max - angle_min > 2 * M_PI * MAX_FULL_CIRCLES) { diff --git a/gfx/cairo/cairo/src/cairo-array-private.h b/gfx/cairo/cairo/src/cairo-array-private.h index 8e779d41aa..ff5b51f504 100644 --- a/gfx/cairo/cairo/src/cairo-array-private.h +++ b/gfx/cairo/cairo/src/cairo-array-private.h @@ -1,3 +1,4 @@ +/* -*- Mode: c; tab-width: 8; c-basic-offset: 4; indent-tabs-mode: t; -*- */ /* cairo - a vector graphics library with display and print output * * Copyright © 2002 University of Southern California @@ -88,6 +89,12 @@ _cairo_array_size (const cairo_array_t *array); cairo_private void _cairo_array_sort (const cairo_array_t *array, int (*compar)(const void *, const void *)); +cairo_private cairo_bool_t +_cairo_array_pop_element (cairo_array_t *array, void *dst); + +cairo_private void * +_cairo_array_last_element (cairo_array_t *array); + CAIRO_END_DECLS #endif /* CAIRO_ARRAY_PRIVATE_H */ diff --git a/gfx/cairo/cairo/src/cairo-array.c b/gfx/cairo/cairo/src/cairo-array.c index 60f45db4e4..a4a4f8c846 100644 --- a/gfx/cairo/cairo/src/cairo-array.c +++ b/gfx/cairo/cairo/src/cairo-array.c @@ -40,7 +40,7 @@ #include "cairo-array-private.h" #include "cairo-error-private.h" -/** +/*< private > * _cairo_array_init: * * Initialize a new #cairo_array_t object to store objects each of size @@ -63,7 +63,7 @@ _cairo_array_init (cairo_array_t *array, unsigned int element_size) array->elements = NULL; } -/** +/*< private > * _cairo_array_fini: * @array: A #cairo_array_t * @@ -77,7 +77,7 @@ _cairo_array_fini (cairo_array_t *array) free (array->elements); } -/** +/*< private > * _cairo_array_grow_by: * @array: a #cairo_array_t * @@ -125,7 +125,7 @@ _cairo_array_grow_by (cairo_array_t *array, unsigned int additional) return CAIRO_STATUS_SUCCESS; } -/** +/*< private > * _cairo_array_truncate: * @array: a #cairo_array_t * @@ -140,17 +140,16 @@ _cairo_array_truncate (cairo_array_t *array, unsigned int num_elements) array->num_elements = num_elements; } -/** +/*< private > * _cairo_array_index: * @array: a #cairo_array_t - * Returns: A pointer to the object stored at @index. * * If the resulting value is assigned to a pointer to an object of the same * element_size as initially passed to _cairo_array_init() then that * pointer may be used for further direct indexing with []. For * example: * - * <informalexample><programlisting> + * |[<!-- language="C" --> * cairo_array_t array; * double *values; * @@ -160,7 +159,9 @@ _cairo_array_truncate (cairo_array_t *array, unsigned int num_elements) * values = _cairo_array_index (&array, 0); * for (i = 0; i < _cairo_array_num_elements (&array); i++) * ... use values[i] here ... - * </programlisting></informalexample> + * ]| + * + * Returns: A pointer to the object stored at @index. **/ void * _cairo_array_index (cairo_array_t *array, unsigned int index) @@ -181,20 +182,19 @@ _cairo_array_index (cairo_array_t *array, unsigned int index) assert (index < array->num_elements); - return array->elements + index * array->element_size; + return array->elements + (size_t)index * array->element_size; } -/** +/*< private > * _cairo_array_index_const: * @array: a #cairo_array_t - * Returns: A pointer to the object stored at @index. * * If the resulting value is assigned to a pointer to an object of the same * element_size as initially passed to _cairo_array_init() then that * pointer may be used for further direct indexing with []. For * example: * - * <informalexample><programlisting> + * |[<!-- language="C" --. * cairo_array_t array; * const double *values; * @@ -204,7 +204,9 @@ _cairo_array_index (cairo_array_t *array, unsigned int index) * values = _cairo_array_index_const (&array, 0); * for (i = 0; i < _cairo_array_num_elements (&array); i++) * ... read values[i] here ... - * </programlisting></informalexample> + * ]| + * + * Returns: A pointer to the object stored at @index. **/ const void * _cairo_array_index_const (const cairo_array_t *array, unsigned int index) @@ -225,10 +227,10 @@ _cairo_array_index_const (const cairo_array_t *array, unsigned int index) assert (index < array->num_elements); - return array->elements + index * array->element_size; + return array->elements + (size_t)index * array->element_size; } -/** +/*< private > * _cairo_array_copy_element: * @array: a #cairo_array_t * @@ -243,7 +245,7 @@ _cairo_array_copy_element (const cairo_array_t *array, memcpy (dst, _cairo_array_index_const (array, index), array->element_size); } -/** +/*< private > * _cairo_array_append: * @array: a #cairo_array_t * @@ -265,7 +267,7 @@ _cairo_array_append (cairo_array_t *array, return _cairo_array_append_multiple (array, element, 1); } -/** +/*< private > * _cairo_array_append_multiple: * @array: a #cairo_array_t * @@ -289,12 +291,12 @@ _cairo_array_append_multiple (cairo_array_t *array, if (unlikely (status)) return status; - memcpy (dest, elements, num_elements * array->element_size); + memcpy (dest, elements, (size_t)num_elements * array->element_size); return CAIRO_STATUS_SUCCESS; } -/** +/*< private > * _cairo_array_allocate: * @array: a #cairo_array_t * @@ -320,19 +322,20 @@ _cairo_array_allocate (cairo_array_t *array, assert (array->num_elements + num_elements <= array->size); - *elements = array->elements + array->num_elements * array->element_size; + *elements = array->elements + (size_t)array->num_elements * array->element_size; array->num_elements += num_elements; return CAIRO_STATUS_SUCCESS; } -/** +/*< private > * _cairo_array_num_elements: * @array: a #cairo_array_t - * Returns: The number of elements stored in @array. * * This space was left intentionally blank, but gtk-doc filled it. + * + * Returns: The number of elements stored in @array. **/ unsigned int _cairo_array_num_elements (const cairo_array_t *array) @@ -340,13 +343,14 @@ _cairo_array_num_elements (const cairo_array_t *array) return array->num_elements; } -/** +/*< private > * _cairo_array_size: * @array: a #cairo_array_t - * Returns: The number of elements for which there is currently space - * allocated in @array. * * This space was left intentionally blank, but gtk-doc filled it. + * + * Returns: The number of elements for which there is currently space + * allocated in @array. **/ unsigned int _cairo_array_size (const cairo_array_t *array) @@ -354,7 +358,7 @@ _cairo_array_size (const cairo_array_t *array) return array->size; } -/** +/*< private > * _cairo_user_data_array_init: * @array: a #cairo_user_data_array_t * @@ -369,7 +373,7 @@ _cairo_user_data_array_init (cairo_user_data_array_t *array) _cairo_array_init (array, sizeof (cairo_user_data_slot_t)); } -/** +/*< private > * _cairo_user_data_array_fini: * @array: a #cairo_user_data_array_t * @@ -396,7 +400,7 @@ _cairo_user_data_array_fini (cairo_user_data_array_t *array) _cairo_array_fini (array); } -/** +/*< private > * _cairo_user_data_array_get_data: * @array: a #cairo_user_data_array_t * @key: the address of the #cairo_user_data_key_t the user data was @@ -412,7 +416,7 @@ void * _cairo_user_data_array_get_data (cairo_user_data_array_t *array, const cairo_user_data_key_t *key) { - int i, num_slots; + unsigned int i, num_slots; cairo_user_data_slot_t *slots; /* We allow this to support degenerate objects such as cairo_surface_nil. */ @@ -429,7 +433,7 @@ _cairo_user_data_array_get_data (cairo_user_data_array_t *array, return NULL; } -/** +/*< private > * _cairo_user_data_array_set_data: * @array: a #cairo_user_data_array_t * @key: the address of a #cairo_user_data_key_t to attach the user data to @@ -452,7 +456,7 @@ _cairo_user_data_array_set_data (cairo_user_data_array_t *array, cairo_destroy_func_t destroy) { cairo_status_t status; - int i, num_slots; + unsigned int i, num_slots; cairo_user_data_slot_t *slots, *slot, new_slot; if (user_data) { @@ -523,7 +527,7 @@ _cairo_user_data_array_foreach (cairo_user_data_array_t *array, void *closure) { cairo_user_data_slot_t *slots; - int i, num_slots; + unsigned int i, num_slots; num_slots = array->num_elements; slots = _cairo_array_index (array, 0); @@ -538,3 +542,39 @@ _cairo_array_sort (const cairo_array_t *array, int (*compar)(const void *, const { qsort (array->elements, array->num_elements, array->element_size, compar); } + +/*< private > + * _cairo_array_pop_element: + * @array: a #cairo_array_t + * Returns: A TRUE if element successfully popped, FALSE if the array is empty. + * + * Copy the last element out of the array from index @index into the + * location pointed to by @dst and remove the element from the array. + **/ +cairo_bool_t +_cairo_array_pop_element (cairo_array_t *array, void *dst) +{ + if (array->num_elements > 0) { + _cairo_array_copy_element (array, array->num_elements - 1, dst); + array->num_elements--; + return TRUE; + } + + return FALSE; +} + +/*< private > + * _cairo_array_top_element: + * @array: a #cairo_array_t + * Returns: A pointer to the last of object or NULL if array is empty. + * + * Get the pointer to the last element of of the array. + **/ +void * +_cairo_array_last_element (cairo_array_t *array) +{ + if (array->num_elements > 0) + return _cairo_array_index (array, array->num_elements - 1); + + return NULL; +} diff --git a/gfx/cairo/cairo/src/cairo-atomic-private.h b/gfx/cairo/cairo/src/cairo-atomic-private.h index 46761856fa..89556ef7fe 100644 --- a/gfx/cairo/cairo/src/cairo-atomic-private.h +++ b/gfx/cairo/cairo/src/cairo-atomic-private.h @@ -39,11 +39,9 @@ #ifndef CAIRO_ATOMIC_PRIVATE_H #define CAIRO_ATOMIC_PRIVATE_H -# include "cairo-compiler-private.h" +#include "cairo-compiler-private.h" -#if HAVE_CONFIG_H #include "config.h" -#endif #include <assert.h> @@ -279,7 +277,12 @@ typedef int64_t cairo_atomic_intptr_t; #endif -#ifndef HAS_ATOMIC_OPS +#if !defined(HAS_ATOMIC_OPS) && defined(_WIN32) +#include <windows.h> + +#define HAS_ATOMIC_OPS 1 + +typedef int32_t cairo_atomic_int_t; #if SIZEOF_VOID_P==SIZEOF_INT typedef unsigned int cairo_atomic_intptr_t; @@ -291,7 +294,63 @@ typedef unsigned long long cairo_atomic_intptr_t; #error No matching integer pointer type #endif -typedef cairo_atomic_intptr_t cairo_atomic_int_t; +static cairo_always_inline cairo_atomic_int_t +_cairo_atomic_int_get (cairo_atomic_int_t *x) +{ + MemoryBarrier (); + return *x; +} + +# define _cairo_atomic_int_get_relaxed(x) *(x) +# define _cairo_atomic_int_set_relaxed(x, val) *(x) = (val) + +# define _cairo_atomic_int_inc(x) ((void) InterlockedIncrement ((LONG*)x)) +# define _cairo_atomic_int_dec(x) ((void) InterlockedDecrement ((LONG*)x)) +# define _cairo_atomic_int_dec_and_test(x) (InterlockedDecrement ((LONG*)x) == 0) + +static cairo_always_inline cairo_bool_t +_cairo_atomic_int_cmpxchg (cairo_atomic_int_t *x, + cairo_atomic_int_t oldv, + cairo_atomic_int_t newv) +{ + return InterlockedCompareExchange ((LONG*)x, (LONG)newv, (LONG)oldv) == oldv; +} + +static cairo_always_inline void * +_cairo_atomic_ptr_get (void **x) +{ + MemoryBarrier (); + return *x; +} + +static cairo_always_inline cairo_bool_t +_cairo_atomic_ptr_cmpxchg (void **x, void *oldv, void *newv) +{ + return InterlockedCompareExchangePointer (x, newv, oldv) == oldv; +} + +static cairo_always_inline void * +_cairo_atomic_ptr_cmpxchg_return_old (void **x, void *oldv, void *newv) +{ + return InterlockedCompareExchangePointer (x, newv, oldv); +} + +#endif /* !defined(HAS_ATOMIC_OPS) && defined(_WIN32) */ + + +#ifndef HAS_ATOMIC_OPS + +typedef int cairo_atomic_int_t; + +#if SIZEOF_VOID_P==SIZEOF_INT +typedef unsigned int cairo_atomic_intptr_t; +#elif SIZEOF_VOID_P==SIZEOF_LONG +typedef unsigned long cairo_atomic_intptr_t; +#elif SIZEOF_VOID_P==SIZEOF_LONG_LONG +typedef unsigned long long cairo_atomic_intptr_t; +#else +#error No matching integer pointer type +#endif cairo_private void _cairo_atomic_int_inc (cairo_atomic_int_t *x); @@ -317,7 +376,8 @@ cairo_private cairo_atomic_int_t _cairo_atomic_int_get_relaxed (cairo_atomic_int_t *x); void _cairo_atomic_int_set_relaxed (cairo_atomic_int_t *x, cairo_atomic_int_t val); -# define _cairo_atomic_ptr_get(x) (void *) _cairo_atomic_int_get((cairo_atomic_int_t *) x) +cairo_private void* +_cairo_atomic_ptr_get(void **x); #else # define _cairo_atomic_int_get(x) (*x) # define _cairo_atomic_int_get_relaxed(x) (*x) @@ -382,6 +442,7 @@ _cairo_atomic_ptr_cmpxchg_return_old_fallback(void **x, void *oldv, void *newv) #define _cairo_status_set_error(status, err) do { \ int ret__; \ assert (err < CAIRO_STATUS_LAST_STATUS); \ + assert (sizeof(*status) == sizeof(cairo_atomic_int_t)); \ /* hide compiler warnings about cairo_status_t != int (gcc treats its as \ * an unsigned integer instead, and about ignoring the return value. */ \ ret__ = _cairo_atomic_int_cmpxchg ((cairo_atomic_int_t *) status, CAIRO_STATUS_SUCCESS, err); \ diff --git a/gfx/cairo/cairo/src/cairo-atomic.c b/gfx/cairo/cairo/src/cairo-atomic.c index 2af50cd387..3c4d519729 100644 --- a/gfx/cairo/cairo/src/cairo-atomic.c +++ b/gfx/cairo/cairo/src/cairo-atomic.c @@ -42,7 +42,7 @@ COMPILE_TIME_ASSERT(sizeof(void*) == sizeof(int) || sizeof(void*) == sizeof(long long)); #else void -_cairo_atomic_int_inc (cairo_atomic_intptr_t *x) +_cairo_atomic_int_inc (cairo_atomic_int_t *x) { CAIRO_MUTEX_LOCK (_cairo_atomic_mutex); *x += 1; @@ -50,7 +50,7 @@ _cairo_atomic_int_inc (cairo_atomic_intptr_t *x) } cairo_bool_t -_cairo_atomic_int_dec_and_test (cairo_atomic_intptr_t *x) +_cairo_atomic_int_dec_and_test (cairo_atomic_int_t *x) { cairo_bool_t ret; @@ -61,10 +61,10 @@ _cairo_atomic_int_dec_and_test (cairo_atomic_intptr_t *x) return ret; } -cairo_atomic_intptr_t -_cairo_atomic_int_cmpxchg_return_old_impl (cairo_atomic_intptr_t *x, cairo_atomic_intptr_t oldv, cairo_atomic_intptr_t newv) +cairo_atomic_int_t +_cairo_atomic_int_cmpxchg_return_old_impl (cairo_atomic_int_t *x, cairo_atomic_int_t oldv, cairo_atomic_int_t newv) { - cairo_atomic_intptr_t ret; + cairo_atomic_int_t ret; CAIRO_MUTEX_LOCK (_cairo_atomic_mutex); ret = *x; @@ -90,10 +90,10 @@ _cairo_atomic_ptr_cmpxchg_return_old_impl (void **x, void *oldv, void *newv) } #ifdef ATOMIC_OP_NEEDS_MEMORY_BARRIER -cairo_atomic_intptr_t -_cairo_atomic_int_get (cairo_atomic_intptr_t *x) +cairo_atomic_int_t +_cairo_atomic_int_get (cairo_atomic_int_t *x) { - cairo_atomic_intptr_t ret; + cairo_atomic_int_t ret; CAIRO_MUTEX_LOCK (_cairo_atomic_mutex); ret = *x; @@ -102,19 +102,31 @@ _cairo_atomic_int_get (cairo_atomic_intptr_t *x) return ret; } -cairo_atomic_intptr_t -_cairo_atomic_int_get_relaxed (cairo_atomic_intptr_t *x) +cairo_atomic_int_t +_cairo_atomic_int_get_relaxed (cairo_atomic_int_t *x) { return _cairo_atomic_int_get (x); } void -_cairo_atomic_int_set_relaxed (cairo_atomic_intptr_t *x, cairo_atomic_intptr_t val) +_cairo_atomic_int_set_relaxed (cairo_atomic_int_t *x, cairo_atomic_int_t val) { CAIRO_MUTEX_LOCK (_cairo_atomic_mutex); *x = val; CAIRO_MUTEX_UNLOCK (_cairo_atomic_mutex); } + +void* +_cairo_atomic_ptr_get (void **x) +{ + void *ret; + + CAIRO_MUTEX_LOCK (_cairo_atomic_mutex); + ret = *x; + CAIRO_MUTEX_UNLOCK (_cairo_atomic_mutex); + + return ret; +} #endif #endif diff --git a/gfx/cairo/cairo/src/cairo-backend-private.h b/gfx/cairo/cairo/src/cairo-backend-private.h index 67607c12f3..86689c7957 100644 --- a/gfx/cairo/cairo/src/cairo-backend-private.h +++ b/gfx/cairo/cairo/src/cairo-backend-private.h @@ -68,6 +68,7 @@ struct _cairo_backend { cairo_status_t (*set_line_cap) (void *cr, cairo_line_cap_t line_cap); cairo_status_t (*set_line_join) (void *cr, cairo_line_join_t line_join); cairo_status_t (*set_line_width) (void *cr, double line_width); + cairo_status_t (*set_hairline) (void *cr, cairo_bool_t set_hairline); cairo_status_t (*set_miter_limit) (void *cr, double limit); cairo_status_t (*set_opacity) (void *cr, double opacity); cairo_status_t (*set_operator) (void *cr, cairo_operator_t op); @@ -79,6 +80,7 @@ struct _cairo_backend { cairo_line_cap_t (*get_line_cap) (void *cr); cairo_line_join_t (*get_line_join) (void *cr); double (*get_line_width) (void *cr); + cairo_bool_t (*get_hairline) (void *cr); double (*get_miter_limit) (void *cr); double (*get_opacity) (void *cr); cairo_operator_t (*get_operator) (void *cr); diff --git a/gfx/cairo/cairo/src/cairo-beos-surface.cpp b/gfx/cairo/cairo/src/cairo-beos-surface.cpp deleted file mode 100644 index 65db0b97ac..0000000000 --- a/gfx/cairo/cairo/src/cairo-beos-surface.cpp +++ /dev/null @@ -1,984 +0,0 @@ -/* vim:set ts=8 sw=4 noet cin: */ -/* cairo - a vector graphics library with display and print output - * - * Copyright © 2005 Christian Biesinger <cbiesinger@web.de> - * - * 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., 51 Franklin Street, Suite 500, Boston, MA 02110-1335, 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 Christian Biesinger - * <cbiesinger@web.de> - * - * Contributor(s): - */ - -// This is a C++ file in order to use the C++ BeOS API - -#include "cairoint.h" - -#include "cairo-beos.h" - -#include "cairo-error-private.h" -#include "cairo-image-surface-inline.h" - -#include <new> - -#include <Bitmap.h> -#include <Region.h> -#if 0 -#include <DirectWindow.h> -#endif -#include <Screen.h> -#include <Window.h> -#include <Locker.h> - -/** - * SECTION:beos-surface - * @Title: BeOS Surfaces - * @Short_Description: BeOS surface support - * @See_Also: #cairo_surface_t - * - * The BeOS surface is used to render cairo graphics to BeOS views - * and bitmaps. - **/ - -#define CAIRO_INT_STATUS_SUCCESS (cairo_int_status_t)(CAIRO_STATUS_SUCCESS) - -struct cairo_beos_surface_t { - cairo_surface_t base; - - cairo_region_t *clip_region; - - BView* view; - - /* - * A view is either attached to a bitmap, a window, or unattached. - * If it is attached to a window, we can copy data out of it using BScreen. - * If it is attached to a bitmap, we can read the bitmap data. - * If it is not attached, it doesn't draw anything, we need not bother. - * - * Since there doesn't seem to be a way to get the bitmap from a view if it - * is attached to one, we have to use a special surface creation function. - */ - - BBitmap* bitmap; - - // If true, surface and view should be deleted when this surface is - // destroyed - bool owns_bitmap_view; -}; - -class AutoLockView { - public: - AutoLockView(BView* view) : mView(view) { - mOK = mView->LockLooper(); - } - - ~AutoLockView() { - if (mOK) - mView->UnlockLooper(); - } - - operator bool() { - return mOK; - } - - private: - BView* mView; - bool mOK; -}; - -static cairo_surface_t * -_cairo_beos_surface_create_internal (BView* view, - BBitmap* bmp, - bool owns_bitmap_view = false); - -static inline BRect -_cairo_rectangle_to_brect (const cairo_rectangle_int_t* rect) -{ - // A BRect is one pixel wider than you'd think - return BRect (rect->x, rect->y, - rect->x + rect->width - 1, - rect->y + rect->height - 1); -} - -static inline cairo_rectangle_int_t -_brect_to_cairo_rectangle (const BRect &rect) -{ - cairo_rectangle_int_t retval; - retval.x = floor (rect.left); - retval.y = floor (rect.top); - retval.width = ceil (rect.right) - retval.x + 1; - retval.height = ceil (rect.bottom) - rectval.y + 1; - return retval; -} - -static inline rgb_color -_cairo_color_to_be_color (const cairo_color_t *color) -{ - // This factor ensures a uniform distribution of numbers - const float factor = 256 - 1e-5; - // Using doubles to have non-premultiplied colors - rgb_color be_color = { uint8(color->red * factor), - uint8(color->green * factor), - uint8(color->blue * factor), - uint8(color->alpha * factor) }; - - return be_color; -} - -enum ViewCopyStatus { - OK, - NOT_VISIBLE, // The view or the interest rect is not visible on screen - ERROR // The view was visible, but the rect could not be copied. Probably OOM -}; - -/** - * _cairo_beos_view_to_bitmap: - * @bitmap: [out] The resulting bitmap. - * @rect: [out] The rectangle that was copied, in the view's coordinate system - * @interestRect: If non-null, only this part of the view will be copied (view's coord system). - * - * Gets the contents of the view as a BBitmap*. Caller must delete the bitmap. - **/ -static ViewCopyStatus -_cairo_beos_view_to_bitmap (BView* view, - BBitmap** bitmap, - BRect* rect = NULL, - const BRect* interestRect = NULL) -{ - *bitmap = NULL; - - BWindow* wnd = view->Window(); - // If we have no window, can't do anything - if (!wnd) - return NOT_VISIBLE; - - view->Sync(); - wnd->Sync(); - -#if 0 - // Is it a direct window? - BDirectWindow* directWnd = dynamic_cast<BDirectWindow*>(wnd); - if (directWnd) { - // WRITEME - } -#endif - - // Is it visible? If so, we can copy the content off the screen - if (wnd->IsHidden()) - return NOT_VISIBLE; - - BRect rectToCopy(view->Bounds()); - if (interestRect) - rectToCopy = rectToCopy & *interestRect; - - if (!rectToCopy.IsValid()) - return NOT_VISIBLE; - - BScreen screen(wnd); - BRect screenRect(view->ConvertToScreen(rectToCopy)); - screenRect = screenRect & screen.Frame(); - - if (!screen.IsValid()) - return NOT_VISIBLE; - - if (rect) - *rect = view->ConvertFromScreen(screenRect); - - if (screen.GetBitmap(bitmap, false, &screenRect) == B_OK) - return OK; - - return ERROR; -} - -static void -unpremultiply_bgra (unsigned char* data, - int width, - int height, - int stride, - unsigned char* retdata) -{ - unsigned char* end = data + stride * height; - for (unsigned char* in = data, *out = retdata; - in < end; - in += stride, out += stride) - { - for (int i = 0; i < width; i ++) { - uint8_t *b = &out[4*i]; - uint32_t pixel; - uint8_t alpha; - - memcpy (&pixel, &data[4*i], sizeof (uint32_t)); - alpha = pixel & 0xff; - if (alpha == 0) { - b[0] = b[1] = b[2] = b[3] = 0; - } else { - b[0] = (((pixel >> 24) & 0xff) * 255 + alpha / 2) / alpha; - b[1] = (((pixel >> 16) & 0xff) * 255 + alpha / 2) / alpha; - b[2] = (((pixel >> 8) & 0xff) * 255 + alpha / 2) / alpha; - b[3] = alpha; - } - } - } -} - -static inline int -multiply_alpha (int alpha, int color) -{ - int temp = (alpha * color) + 0x80; - return ((temp + (temp >> 8)) >> 8); -} - -static unsigned char* -premultiply_bgra (unsigned char* data, - int width, - int height, - int stride) -{ - uint8_t * retdata = reinterpret_cast<unsigned char*>(_cairo_malloc_ab(height, stride)); - if (!retdata) - return NULL; - - uint8_t * end = data + stride * height; - for (uint8_t * in = data, *out = retdata; - in < end; - in += stride, out += stride) - { - for (int i = 0; i < width; i ++) { - uint8_t *base = &in[4*i]; - uint8_t alpha = base[3]; - uint32_t p; - - if (alpha == 0) { - p = 0; - } else { - uint8_t blue = base[0]; - uint8_t green = base[1]; - uint8_t red = base[2]; - - if (alpha != 0xff) { - blue = multiply_alpha (alpha, blue); - green = multiply_alpha (alpha, green); - red = multiply_alpha (alpha, red); - } - p = (alpha << 0) | (red << 8) | (green << 16) | ((uint32_t)blue << 24); - } - memcpy (&out[4*i], &p, sizeof (uint32_t)); - } - } - return retdata; -} - -static cairo_int_status_t -_cairo_beos_surface_set_clip_region (cairo_beos_surface_t *surface, - cairo_region_t *region) -{ - cairo_beos_surface_t *surface = reinterpret_cast<cairo_beos_surface_t*>( - abstract_surface); - AutoLockView locker(surface->view); - assert (locker); - - if (region == surface->clip_region) - return CAIRO_INT_STATUS_SUCCESS; - - cairo_region_destroy (surface->clip_region); - surface->clip_region = cairo_region_reference (region); - - if (region == NULL) { - // No clipping - surface->view->ConstrainClippingRegion(NULL); - return CAIRO_INT_STATUS_SUCCESS; - } - - int count = cairo_region_num_rectangles (region); - BRegion bregion; - for (int i = 0; i < count; ++i) { - cairo_rectangle_int_t rect; - - cairo_region_get_rectangle (region, i, &rect); - // Have to subtract one, because for pixman, the second coordinate - // lies outside the rectangle. - bregion.Include (_cairo_rectangle_to_brect (&rect)); - } - surface->view->ConstrainClippingRegion(&bregion); - return CAIRO_INT_STATUS_SUCCESS; -} - - -/** - * _cairo_beos_bitmap_to_surface: - * - * Returns an addrefed image surface for a BBitmap. The bitmap need not outlive - * the surface. - **/ -static cairo_image_surface_t* -_cairo_beos_bitmap_to_surface (BBitmap* bitmap) -{ - color_space format = bitmap->ColorSpace(); - if (format != B_RGB32 && format != B_RGBA32) { - BBitmap bmp(bitmap->Bounds(), B_RGB32, true); - BView view(bitmap->Bounds(), "Cairo bitmap drawing view", - B_FOLLOW_ALL_SIDES, 0); - bmp.AddChild(&view); - - view.LockLooper(); - - view.DrawBitmap(bitmap, BPoint(0.0, 0.0)); - view.Sync(); - - cairo_image_surface_t* imgsurf = _cairo_beos_bitmap_to_surface(&bmp); - - view.UnlockLooper(); - bmp.RemoveChild(&view); - return imgsurf; - } - - cairo_format_t cformat = format == B_RGB32 ? - CAIRO_FORMAT_RGB24 : CAIRO_FORMAT_ARGB32; - - BRect bounds(bitmap->Bounds()); - unsigned char* bits = reinterpret_cast<unsigned char*>(bitmap->Bits()); - int width = bounds.IntegerWidth() + 1; - int height = bounds.IntegerHeight() + 1; - unsigned char* premultiplied; - if (cformat == CAIRO_FORMAT_ARGB32) { - premultiplied = premultiply_bgra (bits, width, height, - bitmap->BytesPerRow()); - } else { - premultiplied = reinterpret_cast<unsigned char*>( - _cairo_malloc_ab(bitmap->BytesPerRow(), height)); - if (premultiplied) - memcpy(premultiplied, bits, bitmap->BytesPerRow() * height); - } - if (!premultiplied) - return _cairo_surface_create_in_error (_cairo_error (CAIRO_STATUS_NO_MEMORY)); - - cairo_image_surface_t* surf = reinterpret_cast<cairo_image_surface_t*> - (cairo_image_surface_create_for_data(premultiplied, - cformat, - width, - height, - bitmap->BytesPerRow())); - if (surf->base.status) - free(premultiplied); - else - _cairo_image_surface_assume_ownership_of_data(surf); - return surf; -} - -/** - * _cairo_image_surface_to_bitmap: - * - * Converts an image surface to a BBitmap. The return value must be freed with - * delete. - **/ -static BBitmap* -_cairo_image_surface_to_bitmap (cairo_image_surface_t* surface) -{ - BRect size(0.0, 0.0, surface->width - 1, surface->height - 1); - switch (surface->format) { - case CAIRO_FORMAT_ARGB32: { - BBitmap* data = new BBitmap(size, B_RGBA32); - unpremultiply_bgra (surface->data, - surface->width, - surface->height, - surface->stride, - reinterpret_cast<unsigned char*>(data->Bits())); - return data; - } - case CAIRO_FORMAT_RGB24: { - BBitmap* data = new BBitmap(size, B_RGB32); - memcpy(data->Bits(), surface->data, surface->height * surface->stride); - return data; - } - default: - assert(0); - return NULL; - } -} - -/** - * _cairo_op_to_be_op: - * - * Converts a cairo drawing operator to a beos drawing_mode. Returns true if - * the operator could be converted, false otherwise. - **/ -static bool -_cairo_op_to_be_op (cairo_operator_t cairo_op, - drawing_mode* beos_op) -{ - switch (cairo_op) { - case CAIRO_OPERATOR_SOURCE: - *beos_op = B_OP_COPY; - return true; - case CAIRO_OPERATOR_OVER: - *beos_op = B_OP_ALPHA; - return true; - - case CAIRO_OPERATOR_ADD: - // Does not actually work - // XXX This is a fundamental compositing operator, it has to work! -#if 1 - return false; -#else - *beos_op = B_OP_ADD; - return true; -#endif - - case CAIRO_OPERATOR_CLEAR: - // Does not map to B_OP_ERASE - it replaces the dest with the low - // color, instead of transparency; could be done by setting low - // color appropriately. - - case CAIRO_OPERATOR_IN: - case CAIRO_OPERATOR_OUT: - case CAIRO_OPERATOR_ATOP: - - case CAIRO_OPERATOR_DEST: - case CAIRO_OPERATOR_DEST_OVER: - case CAIRO_OPERATOR_DEST_IN: - case CAIRO_OPERATOR_DEST_OUT: - case CAIRO_OPERATOR_DEST_ATOP: - - case CAIRO_OPERATOR_XOR: - case CAIRO_OPERATOR_SATURATE: - - default: - return false; - } -} - -static cairo_surface_t * -_cairo_beos_surface_create_similar (void *abstract_surface, - cairo_content_t content, - int width, - int height) -{ - cairo_beos_surface_t *surface = reinterpret_cast<cairo_beos_surface_t*>( - abstract_surface); - - if (width <= 0) - width = 1; - if (height <= 0) - height = 1; - - BRect rect(0.0, 0.0, width - 1, height - 1); - BBitmap* bmp; - switch (content) { - case CAIRO_CONTENT_ALPHA: - return NULL; - case CAIRO_CONTENT_COLOR_ALPHA: - bmp = new BBitmap(rect, B_RGBA32, true); - break; - case CAIRO_CONTENT_COLOR: - // Match the color depth - if (surface->bitmap) { - color_space space = surface->bitmap->ColorSpace(); - // No alpha was requested -> make sure not to return - // a surface with alpha - if (space == B_RGBA32) - space = B_RGB32; - if (space == B_RGBA15) - space = B_RGB15; - bmp = new BBitmap(rect, space, true); - } else { - BScreen scr(surface->view->Window()); - color_space space = B_RGB32; - if (scr.IsValid()) - space = scr.ColorSpace(); - bmp = new BBitmap(rect, space, true); - } - break; - default: - ASSERT_NOT_REACHED; - return NULL; - } - BView* view = new BView(rect, "Cairo bitmap view", B_FOLLOW_ALL_SIDES, 0); - bmp->AddChild(view); - return _cairo_beos_surface_create_internal(view, bmp, true); -} - -static cairo_status_t -_cairo_beos_surface_finish (void *abstract_surface) -{ - cairo_beos_surface_t *surface = reinterpret_cast<cairo_beos_surface_t*>( - abstract_surface); - if (surface->owns_bitmap_view) { - if (surface->bitmap) - surface->bitmap->RemoveChild(surface->view); - - delete surface->view; - delete surface->bitmap; - - surface->view = NULL; - surface->bitmap = NULL; - } - - cairo_region_destroy (surface->clip_region); - - return CAIRO_STATUS_SUCCESS; -} - -static cairo_status_t -_cairo_beos_surface_acquire_source_image (void *abstract_surface, - cairo_image_surface_t **image_out, - void **image_extra) -{ - cairo_beos_surface_t *surface = reinterpret_cast<cairo_beos_surface_t*>( - abstract_surface); - AutoLockView locker(surface->view); - if (!locker) - return CAIRO_STATUS_NO_MEMORY; /// XXX not exactly right, but what can we do? - - - surface->view->Sync(); - - if (surface->bitmap) { - *image_out = _cairo_beos_bitmap_to_surface (surface->bitmap); - if (unlikely ((*image_out)->base.status)) - return (*image_out)->base.status; - - *image_extra = NULL; - return CAIRO_STATUS_SUCCESS; - } - - BBitmap* bmp; - if (_cairo_beos_view_to_bitmap(surface->view, &bmp) != OK) - return CAIRO_STATUS_NO_MEMORY; /// XXX incorrect if the error was NOT_VISIBLE - - *image_out = _cairo_beos_bitmap_to_surface (bmp); - if (unlikely ((*image_out)->base.status)) { - delete bmp; - return (*image_out)->base.status; - } - *image_extra = bmp; - - return CAIRO_STATUS_SUCCESS; -} - -static void -_cairo_beos_surface_release_source_image (void *abstract_surface, - cairo_image_surface_t *image, - void *image_extra) -{ - cairo_surface_destroy (&image->base); - - if (image_extra != NULL) { - BBitmap* bmp = static_cast<BBitmap*>(image_extra); - delete bmp; - } -} - -static cairo_status_t -_cairo_beos_surface_acquire_dest_image (void *abstract_surface, - cairo_rectangle_int_t *interest_rect, - cairo_image_surface_t **image_out, - cairo_rectangle_int_t *image_rect, - void **image_extra) -{ - cairo_beos_surface_t *surface = reinterpret_cast<cairo_beos_surface_t*>( - abstract_surface); - - AutoLockView locker(surface->view); - if (!locker) { - *image_out = NULL; - *image_extra = NULL; - return (cairo_status_t) CAIRO_INT_STATUS_NOTHING_TO_DO; - } - - if (surface->bitmap) { - surface->view->Sync(); - *image_out = _cairo_beos_bitmap_to_surface(surface->bitmap); - if (unlikely ((*image_out)->base.status)) - return (*image_out)->base.status; - - image_rect->x = 0; - image_rect->y = 0; - image_rect->width = (*image_out)->width; - image_rect->height = (*image_out)->height; - - *image_extra = NULL; - return CAIRO_STATUS_SUCCESS; - } - - BRect b_interest_rect (_cairo_rectangle_to_brect (interest_rect)); - - BRect rect; - BBitmap* bitmap; - ViewCopyStatus status = _cairo_beos_view_to_bitmap(surface->view, &bitmap, - &rect, &b_interest_rect); - if (status == NOT_VISIBLE) { - *image_out = NULL; - *image_extra = NULL; - return CAIRO_STATUS_SUCCESS; - } - if (status == ERROR) - return CAIRO_STATUS_NO_MEMORY; - - *image_rect = _brect_to_cairo_rectangle(rect); - *image_out = _cairo_beos_bitmap_to_surface(bitmap); - delete bitmap; - if (unlikely ((*image_out)->base.status)) - return (*image_out)->base.status; - - *image_extra = NULL; - - return CAIRO_STATUS_SUCCESS; -} - - -static void -_cairo_beos_surface_release_dest_image (void *abstract_surface, - cairo_rectangle_int_t *intersect_rect, - cairo_image_surface_t *image, - cairo_rectangle_int_t *image_rect, - void *image_extra) -{ - cairo_beos_surface_t *surface = reinterpret_cast<cairo_beos_surface_t*>( - abstract_surface); - - AutoLockView locker(surface->view); - if (!locker) - return; - - BBitmap* bitmap_to_draw = _cairo_image_surface_to_bitmap(image); - surface->view->PushState(); - - surface->view->SetDrawingMode(B_OP_COPY); - - surface->view->DrawBitmap (bitmap_to_draw, - _cairo_rectangle_to_brect (image_rect)); - - surface->view->PopState(); - - delete bitmap_to_draw; - cairo_surface_destroy(&image->base); -} - -static cairo_int_status_t -_cairo_beos_surface_composite (cairo_operator_t op, - cairo_pattern_t *src, - cairo_pattern_t *mask, - void *dst, - int src_x, - int src_y, - int mask_x, - int mask_y, - int dst_x, - int dst_y, - unsigned int width, - unsigned int height, - cairo_region_t *clip_region) -{ - cairo_beos_surface_t *surface = reinterpret_cast<cairo_beos_surface_t*>( - dst); - cairo_int_status_t status; - AutoLockView locker(surface->view); - if (!locker) - return CAIRO_INT_STATUS_SUCCESS; - - drawing_mode mode; - if (!_cairo_op_to_be_op(op, &mode)) - return CAIRO_INT_STATUS_UNSUPPORTED; - - // XXX Masks are not yet supported - if (mask) - return CAIRO_INT_STATUS_UNSUPPORTED; - - // XXX should eventually support the others - if (src->type != CAIRO_PATTERN_TYPE_SURFACE || - src->extend != CAIRO_EXTEND_NONE) - { - return CAIRO_INT_STATUS_UNSUPPORTED; - } - - // Can we maybe support other matrices as well? (scale? if the filter is right) - int itx, ity; - if (!_cairo_matrix_is_integer_translation(&src->matrix, &itx, &ity)) - return CAIRO_INT_STATUS_UNSUPPORTED; - - status = _cairo_beos_surface_set_clip_region (surface, clip_region); - if (unlikely (status)) - return status; - - BRect srcRect(src_x + itx, - src_y + ity, - src_x + itx + width - 1, - src_y + ity + height - 1); - BRect dstRect(dst_x, dst_y, dst_x + width - 1, dst_y + height - 1); - - cairo_surface_t* src_surface = reinterpret_cast<cairo_surface_pattern_t*>(src)-> - surface; - - // Get a bitmap - BBitmap* bmp = NULL; - bool free_bmp = false; - if (_cairo_surface_is_image(src_surface)) { - cairo_image_surface_t* img_surface = - reinterpret_cast<cairo_image_surface_t*>(src_surface); - - bmp = _cairo_image_surface_to_bitmap(img_surface); - free_bmp = true; - } else if (src_surface->backend == surface->base.backend) { - cairo_beos_surface_t *beos_surface = - reinterpret_cast<cairo_beos_surface_t*>(src_surface); - if (beos_surface->bitmap) { - AutoLockView locker(beos_surface->view); - if (locker) - beos_surface->view->Sync(); - bmp = beos_surface->bitmap; - } else { - _cairo_beos_view_to_bitmap(surface->view, &bmp); - free_bmp = true; - } - } - - if (!bmp) - return CAIRO_INT_STATUS_UNSUPPORTED; - - // So, BeOS seems to screw up painting an opaque bitmap onto a - // translucent one (it makes them partly transparent). Just return - // unsupported. - if (bmp->ColorSpace() == B_RGB32 && surface->bitmap && - surface->bitmap->ColorSpace() == B_RGBA32 && - (mode == B_OP_COPY || mode == B_OP_ALPHA)) - { - if (free_bmp) - delete bmp; - return CAIRO_INT_STATUS_UNSUPPORTED; - } - - // Draw it on screen. - surface->view->PushState(); - - // If our image rect is only a subrect of the desired size, and we - // aren't using B_OP_ALPHA, then we need to fill the rect first. - if (mode == B_OP_COPY && !bmp->Bounds().Contains(srcRect)) { - rgb_color black = { 0, 0, 0, 0 }; - - surface->view->SetDrawingMode(mode); - surface->view->SetHighColor(black); - surface->view->FillRect(dstRect); - } - - if (mode == B_OP_ALPHA && bmp->ColorSpace() == B_RGB32) { - mode = B_OP_COPY; - } - surface->view->SetDrawingMode(mode); - - if (surface->bitmap && surface->bitmap->ColorSpace() == B_RGBA32) - surface->view->SetBlendingMode(B_PIXEL_ALPHA, B_ALPHA_COMPOSITE); - else - surface->view->SetBlendingMode(B_PIXEL_ALPHA, B_ALPHA_OVERLAY); - - surface->view->DrawBitmap(bmp, srcRect, dstRect); - - surface->view->PopState(); - - if (free_bmp) - delete bmp; - - return CAIRO_INT_STATUS_SUCCESS; -} - - -static cairo_int_status_t -_cairo_beos_surface_fill_rectangles (void *abstract_surface, - cairo_operator_t op, - const cairo_color_t *color, - cairo_rectangle_int_t *rects, - int num_rects, - cairo_region_t *clip_region) -{ - cairo_beos_surface_t *surface = reinterpret_cast<cairo_beos_surface_t*>( - abstract_surface); - cairo_int_status_t status; - - if (num_rects <= 0) - return CAIRO_INT_STATUS_SUCCESS; - - AutoLockView locker(surface->view); - if (!locker) - return CAIRO_INT_STATUS_SUCCESS; - - drawing_mode mode; - if (!_cairo_op_to_be_op(op, &mode)) - return CAIRO_INT_STATUS_UNSUPPORTED; - - status = _cairo_beos_surface_set_clip_region (surface, clip_region); - if (unlikely (status)) - return status; - - rgb_color be_color = _cairo_color_to_be_color(color); - - if (mode == B_OP_ALPHA && be_color.alpha == 0xFF) - mode = B_OP_COPY; - - // For CAIRO_OPERATOR_SOURCE, cairo expects us to use the premultiplied - // color info. This is only relevant when drawing into an rgb24 buffer - // (as for others, we can convert when asked for the image) - if (mode == B_OP_COPY && be_color.alpha != 0xFF && - (!surface->bitmap || surface->bitmap->ColorSpace() != B_RGBA32)) - { - be_color.red = color->red_short >> 8; - be_color.green = color->green_short >> 8; - be_color.blue = color->blue_short >> 8; - } - - surface->view->PushState(); - - surface->view->SetDrawingMode(mode); - surface->view->SetHighColor(be_color); - if (surface->bitmap && surface->bitmap->ColorSpace() == B_RGBA32) - surface->view->SetBlendingMode(B_CONSTANT_ALPHA, B_ALPHA_COMPOSITE); - else - surface->view->SetBlendingMode(B_CONSTANT_ALPHA, B_ALPHA_OVERLAY); - - for (int i = 0; i < num_rects; ++i) - surface->view->FillRect (_cairo_rectangle_to_brect (&rects[i])); - - surface->view->PopState(); - - return CAIRO_INT_STATUS_SUCCESS; -} - -static cairo_bool_t -_cairo_beos_surface_get_extents (void *abstract_surface, - cairo_rectangle_int_t *rectangle) -{ - cairo_beos_surface_t *surface = reinterpret_cast<cairo_beos_surface_t*>( - abstract_surface); - AutoLockView locker(surface->view); - if (!locker) - return FALSE; - - *rectangle = _brect_to_cairo_rectangle (surface->view->Bounds()); - return TRUE; -} - -static const struct _cairo_surface_backend cairo_beos_surface_backend = { - CAIRO_SURFACE_TYPE_BEOS, - _cairo_beos_surface_create_similar, - _cairo_beos_surface_finish, - _cairo_beos_surface_acquire_source_image, - _cairo_beos_surface_release_source_image, - _cairo_beos_surface_acquire_dest_image, - _cairo_beos_surface_release_dest_image, - NULL, /* clone_similar */ - _cairo_beos_surface_composite, /* composite */ - _cairo_beos_surface_fill_rectangles, - NULL, /* composite_trapezoids */ - NULL, /* create_span_renderer */ - NULL, /* check_span_renderer */ - NULL, /* copy_page */ - NULL, /* show_page */ - _cairo_beos_surface_get_extents, - NULL, /* old_show_glyphs */ - NULL, /* get_font_options */ - NULL, /* flush */ - NULL, /* mark_dirty_rectangle */ - NULL, /* scaled_font_fini */ - NULL, /* scaled_glyph_fini */ - - NULL, /* paint */ - NULL, /* mask */ - NULL, /* stroke */ - NULL, /* fill */ - NULL /* show_glyphs */ -}; - -static cairo_surface_t * -_cairo_beos_surface_create_internal (BView* view, - BBitmap* bmp, - bool owns_bitmap_view) -{ - // Must use malloc, because cairo code will use free() on the surface - cairo_beos_surface_t *surface = static_cast<cairo_beos_surface_t*>( - malloc(sizeof(cairo_beos_surface_t))); - if (surface == NULL) { - _cairo_error (CAIRO_STATUS_NO_MEMORY); - return const_cast<cairo_surface_t*>(&_cairo_surface_nil); - } - - cairo_content_t content = CAIRO_CONTENT_COLOR; - if (bmp && (bmp->ColorSpace() == B_RGBA32 || bmp->ColorSpace() == B_RGBA15)) - content = CAIRO_CONTENT_COLOR_ALPHA; - _cairo_surface_init (&surface->base, - &cairo_beos_surface_backend, - NULL, /* device */ - content); - - surface->view = view; - surface->bitmap = bmp; - surface->owns_bitmap_view = owns_bitmap_view; - - surface->clip_region = NULL; - - return &surface->base; -} - -/** - * cairo_beos_surface_create: - * @view: The view to draw on - * - * Creates a Cairo surface that draws onto a BeOS BView. - * The caller must ensure that the view does not get deleted before the surface. - * If the view is attached to a bitmap rather than an on-screen window, use - * cairo_beos_surface_create_for_bitmap() instead of this function. - * - * Since: TBD - **/ -cairo_surface_t * -cairo_beos_surface_create (BView* view) -{ - return cairo_beos_surface_create_for_bitmap(view, NULL); -} - -/** - * cairo_beos_surface_create_for_bitmap: - * @view: The view to draw on - * @bmp: The bitmap to which the view is attached - * - * Creates a Cairo surface that draws onto a BeOS BView which is attached to a - * BBitmap. - * The caller must ensure that the view and the bitmap do not get deleted - * before the surface. - * - * For views that draw to a bitmap (as opposed to a screen), use this function - * rather than cairo_beos_surface_create(). Not using this function WILL lead to - * incorrect behaviour. - * - * For now, only views that draw to the entire area of bmp are supported. - * The view must already be attached to the bitmap. - * - * Since: TBD - **/ -cairo_surface_t * -cairo_beos_surface_create_for_bitmap (BView* view, - BBitmap* bmp) -{ - return _cairo_beos_surface_create_internal(view, bmp); -} diff --git a/gfx/cairo/cairo/src/cairo-beos.h b/gfx/cairo/cairo/src/cairo-beos.h deleted file mode 100644 index fdb89a6c4d..0000000000 --- a/gfx/cairo/cairo/src/cairo-beos.h +++ /dev/null @@ -1,60 +0,0 @@ -/* cairo - a vector graphics library with display and print output - * - * Copyright © 2005 Christian Biesinger <cbiesinger@web.de> - * - * 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., 51 Franklin Street, Suite 500, Boston, MA 02110-1335, 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 Christian Biesinger - * <cbiesinger@web.de> - * - * Contributor(s): - */ - -#ifndef CAIRO_BEOS_H -#define CAIRO_BEOS_H - -#include "cairo.h" - -#if CAIRO_HAS_BEOS_SURFACE - -#include <View.h> - -CAIRO_BEGIN_DECLS - -cairo_public cairo_surface_t * -cairo_beos_surface_create (BView* view); - -cairo_public cairo_surface_t * -cairo_beos_surface_create_for_bitmap (BView* view, - BBitmap* bmp); - -CAIRO_END_DECLS - -#else /* CAIRO_HAS_BEOS_SURFACE */ -# error Cairo was not compiled with support for the beos backend -#endif /* CAIRO_HAS_BEOS_SURFACE */ - -#endif /* CAIRO_BEOS_H */ diff --git a/gfx/cairo/cairo/src/cairo-boxes.c b/gfx/cairo/cairo/src/cairo-boxes.c index 3c5d2a7502..383a3eefb4 100644 --- a/gfx/cairo/cairo/src/cairo-boxes.c +++ b/gfx/cairo/cairo/src/cairo-boxes.c @@ -102,16 +102,16 @@ _cairo_boxes_init_for_array (cairo_boxes_t *boxes, boxes->is_pixel_aligned = n == num_boxes; } -/** _cairo_boxes_limit: +/** + * _cairo_boxes_limit: + * @boxes: the box set to be filled (return buffer) + * @limits: array of the limiting boxes to compute the bounding + * box from + * @num_limits: length of the limits array * * Computes the minimum bounding box of the given list of boxes and assign * it to the given boxes set. It also assigns that list as the list of * limiting boxes in the box set. - * - * @param boxes the box set to be filled (return buffer) - * @param limits array of the limiting boxes to compute the bounding - * box from - * @param num_limits length of the limits array */ void _cairo_boxes_limit (cairo_boxes_t *boxes, @@ -276,13 +276,13 @@ _cairo_boxes_add (cairo_boxes_t *boxes, return boxes->status; } -/** _cairo_boxes_extents: +/** + * _cairo_boxes_extents: + * @boxes: The box set whose minimum bounding is computed. + * @box: Return buffer for the computed result. * * Computes the minimum bounding box of the given box set and stores * it in the given box. - * - * @param boxes The box set whose minimum bounding is computed. - * @param box Return buffer for the computed result. */ void _cairo_boxes_extents (const cairo_boxes_t *boxes, @@ -336,15 +336,16 @@ _cairo_boxes_clear (cairo_boxes_t *boxes) boxes->is_pixel_aligned = TRUE; } -/** _cairo_boxes_to_array: +/** + * _cairo_boxes_to_array: + * @boxes The box set to be converted. + * @num_boxes Return buffer for the number of boxes (array count). * * Linearize a box set of possibly multiple chunks into one big chunk * and returns an array of boxes * - * @param boxes The box set to be converted. - * @param num_boxes Return buffer for the number of boxes (array count). - * @return Pointer to the newly allocated array of boxes - * (the number o elements is given in num_boxes). + * Return value: Pointer to the newly allocated array of boxes (the number o + * elements is given in num_boxes). */ cairo_box_t * _cairo_boxes_to_array (const cairo_boxes_t *boxes, diff --git a/gfx/cairo/cairo/src/cairo-cache-private.h b/gfx/cairo/cairo/src/cairo-cache-private.h index 24b6d0b209..03e2bbf31d 100644 --- a/gfx/cairo/cairo/src/cairo-cache-private.h +++ b/gfx/cairo/cairo/src/cairo-cache-private.h @@ -84,7 +84,7 @@ * not be initialized if so desired. **/ typedef struct _cairo_cache_entry { - unsigned long hash; + uintptr_t hash; unsigned long size; } cairo_cache_entry_t; diff --git a/gfx/cairo/cairo/src/cairo-cache.c b/gfx/cairo/cairo/src/cairo-cache.c index 5c4e4caa3d..afdca984eb 100644 --- a/gfx/cairo/cairo/src/cairo-cache.c +++ b/gfx/cairo/cairo/src/cairo-cache.c @@ -56,7 +56,6 @@ _cairo_cache_entry_is_non_zero (const void *entry) * @keys_equal: a function to return %TRUE if two keys are equal * @entry_destroy: destroy notifier for cache entries * @max_size: the maximum size for this cache - * Returns: the newly created #cairo_cache_t * * Creates a new cache using the keys_equal() function to determine * the equality of entries. @@ -84,6 +83,8 @@ _cairo_cache_entry_is_non_zero (const void *entry) * _cairo_cache_freeze() and _cairo_cache_thaw() calls can be * used to establish a window during which no automatic removal of * entries will occur. + * + * Returns: the newly created #cairo_cache_t **/ cairo_status_t _cairo_cache_init (cairo_cache_t *cache, @@ -315,18 +316,18 @@ _cairo_cache_foreach (cairo_cache_t *cache, closure); } -unsigned long +uintptr_t _cairo_hash_string (const char *c) { /* This is the djb2 hash. */ - unsigned long hash = _CAIRO_HASH_INIT_VALUE; + uintptr_t hash = _CAIRO_HASH_INIT_VALUE; while (c && *c) hash = ((hash << 5) + hash) + *c++; return hash; } -unsigned long -_cairo_hash_bytes (unsigned long hash, +uintptr_t +_cairo_hash_bytes (uintptr_t hash, const void *ptr, unsigned int length) { @@ -336,3 +337,10 @@ _cairo_hash_bytes (unsigned long hash, hash = ((hash << 5) + hash) + *bytes++; return hash; } + +uintptr_t +_cairo_hash_uintptr (uintptr_t hash, + uintptr_t u) +{ + return _cairo_hash_bytes (hash, &u, sizeof(u)); +} diff --git a/gfx/cairo/cairo/src/cairo-cff-subset.c b/gfx/cairo/cairo/src/cairo-cff-subset.c index 39e6693a2b..fd74d2ddc0 100644 --- a/gfx/cairo/cairo/src/cairo-cff-subset.c +++ b/gfx/cairo/cairo/src/cairo-cff-subset.c @@ -247,10 +247,10 @@ static unsigned char * decode_integer (unsigned char *p, int *integer) { if (*p == 28) { - *integer = (int)(p[1]<<8 | p[2]); + *integer = (int16_t)(p[1]<<8 | p[2]); p += 3; } else if (*p == 29) { - *integer = (int)(((uint32_t)p[1] << 24) | (p[2] << 16) | (p[3] << 8) | p[4]); + *integer = (int32_t)(((uint32_t)p[1] << 24) | (p[2] << 16) | (p[3] << 8) | p[4]); p += 5; } else if (*p >= 32 && *p <= 246) { *integer = *p++ - 139; @@ -390,7 +390,7 @@ encode_index_offset (unsigned char *p, int offset_size, unsigned long offset) return p + offset_size; } -static unsigned long +static size_t decode_index_offset(unsigned char *p, int off_size) { unsigned long offset = 0; @@ -412,8 +412,8 @@ cff_index_read (cairo_array_t *index, unsigned char **ptr, unsigned char *end_pt cff_index_element_t element; unsigned char *data, *p; cairo_status_t status; - int offset_size, count, start, i; - int end = 0; + int offset_size, count, i; + size_t start, end = 0; p = *ptr; if (p + 2 > end_ptr) @@ -422,7 +422,7 @@ cff_index_read (cairo_array_t *index, unsigned char **ptr, unsigned char *end_pt p += 2; if (count > 0) { offset_size = *p++; - if (p + (count + 1)*offset_size > end_ptr) + if (p + (count + 1)*offset_size > end_ptr || offset_size > 4) return CAIRO_INT_STATUS_UNSUPPORTED; data = p + offset_size*(count + 1) - 1; start = decode_index_offset (p, offset_size); @@ -430,7 +430,7 @@ cff_index_read (cairo_array_t *index, unsigned char **ptr, unsigned char *end_pt for (i = 0; i < count; i++) { end = decode_index_offset (p, offset_size); p += offset_size; - if (p > end_ptr) + if (p > end_ptr || end < start || data + end > end_ptr) return CAIRO_INT_STATUS_UNSUPPORTED; element.length = end - start; element.is_copy = FALSE; @@ -554,7 +554,7 @@ cff_index_append_copy (cairo_array_t *index, element.length = length; element.is_copy = TRUE; element.data = _cairo_malloc (element.length); - if (unlikely (element.data == NULL)) + if (unlikely (element.data == NULL && length != 0)) return _cairo_error (CAIRO_STATUS_NO_MEMORY); memcpy (element.data, object, element.length); @@ -875,7 +875,7 @@ cairo_cff_font_read_name (cairo_cff_font_t *font) cff_index_init (&index); status = cff_index_read (&index, &font->current_ptr, font->data_end); - if (!font->is_opentype) { + if (status == CAIRO_INT_STATUS_SUCCESS && !font->is_opentype) { element = _cairo_array_index (&index, 0); p = element->data; len = element->length; @@ -890,12 +890,10 @@ cairo_cff_font_read_name (cairo_cff_font_t *font) len -= 7; } } - font->ps_name = _cairo_malloc (len + 1); - if (unlikely (font->ps_name == NULL)) - return _cairo_error (CAIRO_STATUS_NO_MEMORY); - memcpy (font->ps_name, p, len); - font->ps_name[len] = 0; + font->ps_name = _cairo_strndup ((char*)p, len); + if (unlikely (font->ps_name == NULL)) + return _cairo_error (CAIRO_STATUS_NO_MEMORY); status = _cairo_escape_ps_name (&font->ps_name); } @@ -1164,7 +1162,7 @@ cairo_cff_font_read_font_metrics (cairo_cff_font_t *font, cairo_hash_table_t *t if (p < end) p = decode_number (p, &yy); } - /* Freetype uses 1/abs(yy) to get units per EM */ + /* FreeType uses 1/abs(yy) to get units per EM */ font->units_per_em = _cairo_round(1.0/fabs(yy)); } @@ -1187,6 +1185,8 @@ cairo_cff_font_read_top_dict (cairo_cff_font_t *font) goto fail; element = _cairo_array_index (&index, 0); + if (element == NULL) + return CAIRO_STATUS_NO_MEMORY; status = cff_dict_read (font->top_dict, element->data, element->length); if (unlikely (status)) goto fail; @@ -1598,15 +1598,17 @@ cairo_cff_parse_charstring (cairo_cff_font_t *font, if (font->is_cid) { fd = font->fdselect[glyph_id]; - sub_num = font->type2_stack_top_value + font->fd_local_sub_bias[fd]; + sub_num = font->type2_stack_top_value + font->fd_local_sub_bias[fd]; + if (sub_num >= (int)_cairo_array_num_elements(&font->fd_local_sub_index[fd])) + return CAIRO_INT_STATUS_UNSUPPORTED; element = _cairo_array_index (&font->fd_local_sub_index[fd], sub_num); if (! font->fd_local_subs_used[fd][sub_num]) { font->fd_local_subs_used[fd][sub_num] = TRUE; cairo_cff_parse_charstring (font, element->data, element->length, glyph_id, need_width); } } else { - sub_num = font->type2_stack_top_value + font->local_sub_bias; - if (sub_num >= _cairo_array_num_elements(&font->local_sub_index)) + sub_num = font->type2_stack_top_value + font->local_sub_bias; + if (sub_num >= (int)_cairo_array_num_elements(&font->local_sub_index)) return CAIRO_INT_STATUS_UNSUPPORTED; element = _cairo_array_index (&font->local_sub_index, sub_num); if (! font->local_subs_used[sub_num] || @@ -1632,6 +1634,8 @@ cairo_cff_parse_charstring (cairo_cff_font_t *font, font->type2_seen_first_int = FALSE; sub_num = font->type2_stack_top_value + font->global_sub_bias; + if (sub_num >= (int)_cairo_array_num_elements(&font->global_sub_index)) + return CAIRO_INT_STATUS_UNSUPPORTED; element = _cairo_array_index (&font->global_sub_index, sub_num); if (! font->global_subs_used[sub_num] || (need_width && !font->type2_found_width)) @@ -3126,6 +3130,8 @@ _cairo_cff_scaled_font_is_cid_cff (cairo_scaled_font_t *scaled_font) goto fail2; element = _cairo_array_index (&index, 0); + if (element == NULL) + goto fail3; status = cff_dict_read (top_dict, element->data, element->length); if (unlikely (status)) goto fail3; diff --git a/gfx/cairo/cairo/src/cairo-clip-boxes.c b/gfx/cairo/cairo/src/cairo-clip-boxes.c index aaddeb7f7b..3ebcd509c6 100644 --- a/gfx/cairo/cairo/src/cairo-clip-boxes.c +++ b/gfx/cairo/cairo/src/cairo-clip-boxes.c @@ -52,19 +52,6 @@ #include "cairo-composite-rectangles-private.h" #include "cairo-region-private.h" -static inline int -pot (int v) -{ - v--; - v |= v >> 1; - v |= v >> 2; - v |= v >> 4; - v |= v >> 8; - v |= v >> 16; - v++; - return v; -} - static cairo_bool_t _cairo_clip_contains_rectangle_box (const cairo_clip_t *clip, const cairo_rectangle_int_t *rect, diff --git a/gfx/cairo/cairo/src/cairo-cogl-gradient-private.h b/gfx/cairo/cairo/src/cairo-cogl-gradient-private.h deleted file mode 100644 index 9367044f3f..0000000000 --- a/gfx/cairo/cairo/src/cairo-cogl-gradient-private.h +++ /dev/null @@ -1,90 +0,0 @@ -/* cairo - a vector graphics library with display and print output - * - * Copyright © 2011 Intel Corporation. - * - * This library is free software; you can redistribute it and/or - * modify it either under the terms of the GNU Lesser General Public - * License version 2.1 as published by the Free Software Foundation - * (the "LGPL") or, at your option, under the terms of the Mozilla - * Public License Version 1.1 (the "MPL"). If you do not alter this - * notice, a recipient may use your version of this file under either - * the MPL or the LGPL. - * - * You should have received a copy of the LGPL along with this library - * in the file COPYING-LGPL-2.1; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Suite 500, Boston, MA 02110-1335, 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.og/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. - * - * Contributor(s): - * Robert Bragg <robert@linux.intel.com> - */ - -#ifndef CAIRO_COGL_GRADIENT_PRIVATE_H -#define CAIRO_COGL_GRADIENT_PRIVATE_H - -#include "cairoint.h" -#include "cairo-pattern-private.h" - -#include <cogl/cogl2-experimental.h> - -#define CAIRO_COGL_LINEAR_GRADIENT_CACHE_SIZE (1024 * 1024) - -typedef enum _cairo_cogl_gradient_compatibility { - CAIRO_COGL_GRADIENT_CAN_EXTEND_PAD = 1<<0, - CAIRO_COGL_GRADIENT_CAN_EXTEND_REPEAT = 1<<1, - CAIRO_COGL_GRADIENT_CAN_EXTEND_REFLECT = 1<<2, - CAIRO_COGL_GRADIENT_CAN_EXTEND_NONE = 1<<3 -} cairo_cogl_gradient_compatibility_t; -#define CAIRO_COGL_GRADIENT_CAN_EXTEND_ALL (CAIRO_COGL_GRADIENT_CAN_EXTEND_PAD |\ - CAIRO_COGL_GRADIENT_CAN_EXTEND_REPEAT|\ - CAIRO_COGL_GRADIENT_CAN_EXTEND_REFLECT|\ - CAIRO_COGL_GRADIENT_CAN_EXTEND_NONE) - -typedef struct _cairo_cogl_linear_texture_entry { - cairo_cogl_gradient_compatibility_t compatibility; - CoglTexture *texture; - float translate_x; - float scale_x; -} cairo_cogl_linear_texture_entry_t; - -typedef struct _cairo_cogl_linear_gradient { - cairo_cache_entry_t cache_entry; - cairo_reference_count_t ref_count; - GList *textures; - int n_stops; - const cairo_gradient_stop_t *stops; - cairo_gradient_stop_t stops_embedded[1]; -} cairo_cogl_linear_gradient_t; - -cairo_int_status_t -_cairo_cogl_get_linear_gradient (cairo_cogl_device_t *context, - cairo_extend_t extend_mode, - int n_stops, - const cairo_gradient_stop_t *stops, - const cairo_bool_t need_mirrored_gradient, - cairo_cogl_linear_gradient_t **gradient_out); - -cairo_cogl_linear_texture_entry_t * -_cairo_cogl_linear_gradient_texture_for_extend (cairo_cogl_linear_gradient_t *gradient, - cairo_extend_t extend_mode); - -cairo_cogl_linear_gradient_t * -_cairo_cogl_linear_gradient_reference (cairo_cogl_linear_gradient_t *gradient); - -void -_cairo_cogl_linear_gradient_destroy (cairo_cogl_linear_gradient_t *gradient); - -cairo_bool_t -_cairo_cogl_linear_gradient_equal (const void *key_a, const void *key_b); - -#endif /* CAIRO_COGL_GRADIENT_PRIVATE_H */ diff --git a/gfx/cairo/cairo/src/cairo-cogl-gradient.c b/gfx/cairo/cairo/src/cairo-cogl-gradient.c deleted file mode 100644 index cdb4cae82d..0000000000 --- a/gfx/cairo/cairo/src/cairo-cogl-gradient.c +++ /dev/null @@ -1,678 +0,0 @@ -/* cairo - a vector graphics library with display and print output - * - * Copyright © 2011 Intel Corporation. - * - * This library is free software; you can redistribute it and/or - * modify it either under the terms of the GNU Lesser General Public - * License version 2.1 as published by the Free Software Foundation - * (the "LGPL") or, at your option, under the terms of the Mozilla - * Public License Version 1.1 (the "MPL"). If you do not alter this - * notice, a recipient may use your version of this file under either - * the MPL or the LGPL. - * - * You should have received a copy of the LGPL along with this library - * in the file COPYING-LGPL-2.1; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Suite 500, Boston, MA 02110-1335, 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.og/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. - * - * Contributor(s): - * Robert Bragg <robert@linux.intel.com> - */ -//#include "cairoint.h" - -#include "cairo-cogl-private.h" -#include "cairo-cogl-gradient-private.h" -#include "cairo-image-surface-private.h" - -#include <cogl/cogl2-experimental.h> -#include <glib.h> - -//#define DUMP_GRADIENTS_TO_PNG - -static unsigned long -_cairo_cogl_linear_gradient_hash (unsigned int n_stops, - const cairo_gradient_stop_t *stops) -{ - return _cairo_hash_bytes (n_stops, stops, - sizeof (cairo_gradient_stop_t) * n_stops); -} - -static cairo_cogl_linear_gradient_t * -_cairo_cogl_linear_gradient_lookup (cairo_cogl_device_t *ctx, - unsigned long hash, - unsigned int n_stops, - const cairo_gradient_stop_t *stops) -{ - cairo_cogl_linear_gradient_t lookup; - - lookup.cache_entry.hash = hash, - lookup.n_stops = n_stops; - lookup.stops = stops; - - return _cairo_cache_lookup (&ctx->linear_cache, &lookup.cache_entry); -} - -cairo_bool_t -_cairo_cogl_linear_gradient_equal (const void *key_a, const void *key_b) -{ - const cairo_cogl_linear_gradient_t *a = key_a; - const cairo_cogl_linear_gradient_t *b = key_b; - - if (a->n_stops != b->n_stops) - return FALSE; - - return memcmp (a->stops, b->stops, a->n_stops * sizeof (cairo_gradient_stop_t)) == 0; -} - -cairo_cogl_linear_gradient_t * -_cairo_cogl_linear_gradient_reference (cairo_cogl_linear_gradient_t *gradient) -{ - assert (CAIRO_REFERENCE_COUNT_HAS_REFERENCE (&gradient->ref_count)); - - _cairo_reference_count_inc (&gradient->ref_count); - - return gradient; -} - -void -_cairo_cogl_linear_gradient_destroy (cairo_cogl_linear_gradient_t *gradient) -{ - GList *l; - - assert (CAIRO_REFERENCE_COUNT_HAS_REFERENCE (&gradient->ref_count)); - - if (! _cairo_reference_count_dec_and_test (&gradient->ref_count)) - return; - - for (l = gradient->textures; l; l = l->next) { - cairo_cogl_linear_texture_entry_t *entry = l->data; - cogl_object_unref (entry->texture); - free (entry); - } - g_list_free (gradient->textures); - - free (gradient); -} - -static int -_cairo_cogl_util_next_p2 (int a) -{ - int rval = 1; - - while (rval < a) - rval <<= 1; - - return rval; -} - -static float -get_max_color_component_range (const cairo_color_stop_t *color0, - const cairo_color_stop_t *color1) -{ - float range; - float max = 0; - - range = fabs (color0->red - color1->red); - max = MAX (range, max); - range = fabs (color0->green - color1->green); - max = MAX (range, max); - range = fabs (color0->blue - color1->blue); - max = MAX (range, max); - range = fabs (color0->alpha - color1->alpha); - max = MAX (range, max); - - return max; -} - -static int -_cairo_cogl_linear_gradient_width_for_stops (cairo_extend_t extend, - unsigned int n_stops, - const cairo_gradient_stop_t *stops) -{ - unsigned int n; - float max_texels_per_unit_offset = 0; - float total_offset_range; - - /* Find the stop pair demanding the most precision because we are - * interpolating the largest color-component range. - * - * From that we can define the relative sizes of all the other - * stop pairs within our texture and thus the overall size. - * - * To determine the maximum number of texels for a given gap we - * look at the range of colors we are expected to interpolate (so - * long as the stop offsets are not degenerate) and we simply - * assume we want one texel for each unique color value possible - * for a one byte-per-component representation. - * XXX: maybe this is overkill and just allowing 128 levels - * instead of 256 would be enough and then we'd rely on the - * bilinear filtering to give the full range. - * - * XXX: potentially we could try and map offsets to pixels to come - * up with a more precise mapping, but we are aiming to cache - * the gradients so we can't make assumptions about how it will be - * scaled in the future. - */ - for (n = 1; n < n_stops; n++) { - float color_range; - float offset_range; - float texels; - float texels_per_unit_offset; - - /* note: degenerate stops don't need to be represented in the - * texture but we want to be sure that solid gaps get at least - * one texel and all other gaps get at least 2 texels. - */ - - if (stops[n].offset == stops[n-1].offset) - continue; - - color_range = get_max_color_component_range (&stops[n].color, &stops[n-1].color); - if (color_range == 0) - texels = 1; - else - texels = MAX (2, 256.0f * color_range); - - /* So how many texels would we need to map over the full [0,1] - * gradient range so this gap would have enough texels? ... */ - offset_range = stops[n].offset - stops[n - 1].offset; - texels_per_unit_offset = texels / offset_range; - - if (texels_per_unit_offset > max_texels_per_unit_offset) - max_texels_per_unit_offset = texels_per_unit_offset; - } - - total_offset_range = fabs (stops[n_stops - 1].offset - stops[0].offset); - return max_texels_per_unit_offset * total_offset_range; -} - -/* Aim to create gradient textures without an alpha component so we can avoid - * needing to use blending... */ -static CoglTextureComponents -_cairo_cogl_linear_gradient_components_for_stops (cairo_extend_t extend, - unsigned int n_stops, - const cairo_gradient_stop_t *stops) -{ - unsigned int n; - - /* We have to add extra transparent texels to the end of the gradient to - * handle CAIRO_EXTEND_NONE... */ - if (extend == CAIRO_EXTEND_NONE) - return COGL_TEXTURE_COMPONENTS_RGBA; - - for (n = 1; n < n_stops; n++) { - if (stops[n].color.alpha != 1.0) - return COGL_TEXTURE_COMPONENTS_RGBA; - } - - return COGL_TEXTURE_COMPONENTS_RGBA; -} - -static cairo_cogl_gradient_compatibility_t -_cairo_cogl_compatibility_from_extend_mode (cairo_extend_t extend_mode) -{ - switch (extend_mode) - { - case CAIRO_EXTEND_NONE: - return CAIRO_COGL_GRADIENT_CAN_EXTEND_NONE; - case CAIRO_EXTEND_PAD: - return CAIRO_COGL_GRADIENT_CAN_EXTEND_PAD; - case CAIRO_EXTEND_REPEAT: - return CAIRO_COGL_GRADIENT_CAN_EXTEND_REPEAT; - case CAIRO_EXTEND_REFLECT: - return CAIRO_COGL_GRADIENT_CAN_EXTEND_REFLECT; - } - - assert (0); /* not reached */ - return CAIRO_EXTEND_NONE; -} - -cairo_cogl_linear_texture_entry_t * -_cairo_cogl_linear_gradient_texture_for_extend (cairo_cogl_linear_gradient_t *gradient, - cairo_extend_t extend_mode) -{ - GList *l; - cairo_cogl_gradient_compatibility_t compatibility = - _cairo_cogl_compatibility_from_extend_mode (extend_mode); - for (l = gradient->textures; l; l = l->next) { - cairo_cogl_linear_texture_entry_t *entry = l->data; - if (entry->compatibility & compatibility) - return entry; - } - return NULL; -} - -static void -color_stop_lerp (const cairo_color_stop_t *c0, - const cairo_color_stop_t *c1, - float factor, - cairo_color_stop_t *dest) -{ - /* NB: we always ignore the short members in this file so we don't need to - * worry about initializing them here. */ - dest->red = c0->red * (1.0f-factor) + c1->red * factor; - dest->green = c0->green * (1.0f-factor) + c1->green * factor; - dest->blue = c0->blue * (1.0f-factor) + c1->blue * factor; - dest->alpha = c0->alpha * (1.0f-factor) + c1->alpha * factor; -} - -static size_t -_cairo_cogl_linear_gradient_size (cairo_cogl_linear_gradient_t *gradient) -{ - GList *l; - size_t size = 0; - for (l = gradient->textures; l; l = l->next) { - cairo_cogl_linear_texture_entry_t *entry = l->data; - size += cogl_texture_get_width (entry->texture) * 4; - } - return size; -} - -static void -emit_stop (CoglVertexP2C4 **position, - float left, - float right, - const cairo_color_stop_t *left_color, - const cairo_color_stop_t *right_color) -{ - CoglVertexP2C4 *p = *position; - - guint8 lr = left_color->red * 255; - guint8 lg = left_color->green * 255; - guint8 lb = left_color->blue * 255; - guint8 la = left_color->alpha * 255; - - guint8 rr = right_color->red * 255; - guint8 rg = right_color->green * 255; - guint8 rb = right_color->blue * 255; - guint8 ra = right_color->alpha * 255; - - p[0].x = left; - p[0].y = 0; - p[0].r = lr; p[0].g = lg; p[0].b = lb; p[0].a = la; - p[1].x = left; - p[1].y = 1; - p[1].r = lr; p[1].g = lg; p[1].b = lb; p[1].a = la; - p[2].x = right; - p[2].y = 1; - p[2].r = rr; p[2].g = rg; p[2].b = rb; p[2].a = ra; - - p[3].x = left; - p[3].y = 0; - p[3].r = lr; p[3].g = lg; p[3].b = lb; p[3].a = la; - p[4].x = right; - p[4].y = 1; - p[4].r = rr; p[4].g = rg; p[4].b = rb; p[4].a = ra; - p[5].x = right; - p[5].y = 0; - p[5].r = rr; p[5].g = rg; p[5].b = rb; p[5].a = ra; - - *position = &p[6]; -} - -#ifdef DUMP_GRADIENTS_TO_PNG -static void -dump_gradient_to_png (CoglTexture *texture) -{ - cairo_image_surface_t *image = (cairo_image_surface_t *) - cairo_image_surface_create (CAIRO_FORMAT_ARGB32, - cogl_texture_get_width (texture), - cogl_texture_get_height (texture)); - CoglPixelFormat format; - static int gradient_id = 0; - char *gradient_name; - - if (image->base.status) - return; - -#if G_BYTE_ORDER == G_LITTLE_ENDIAN - format = COGL_PIXEL_FORMAT_BGRA_8888_PRE; -#else - format = COGL_PIXEL_FORMAT_ARGB_8888_PRE; -#endif - cogl_texture_get_data (texture, - format, - 0, - image->data); - gradient_name = g_strdup_printf ("./gradient%d.png", gradient_id++); - g_print ("writing gradient: %s\n", gradient_name); - cairo_surface_write_to_png ((cairo_surface_t *)image, gradient_name); - g_free (gradient_name); -} -#endif - -cairo_int_status_t -_cairo_cogl_get_linear_gradient (cairo_cogl_device_t *device, - cairo_extend_t extend_mode, - int n_stops, - const cairo_gradient_stop_t *stops, - const cairo_bool_t need_mirrored_gradient, - cairo_cogl_linear_gradient_t **gradient_out) -{ - unsigned long hash; - cairo_cogl_linear_gradient_t *gradient; - cairo_cogl_linear_texture_entry_t *entry; - cairo_gradient_stop_t *internal_stops; - int stop_offset; - int n_internal_stops; - int n; - cairo_cogl_gradient_compatibility_t compatibilities; - int width; - int tex_width; - int left_padding = 0; - cairo_color_stop_t left_padding_color; - int right_padding = 0; - cairo_color_stop_t right_padding_color; - CoglTextureComponents components; - CoglTexture2D *tex; - int un_padded_width; - CoglFramebuffer *offscreen = NULL; - cairo_int_status_t status; - int n_quads; - int n_vertices; - float prev; - float right; - CoglVertexP2C4 *vertices; - CoglVertexP2C4 *p; - CoglPrimitive *prim; - CoglPipeline *pipeline; - - hash = _cairo_cogl_linear_gradient_hash (n_stops, stops); - - gradient = _cairo_cogl_linear_gradient_lookup (device, hash, n_stops, stops); - if (gradient) { - cairo_cogl_linear_texture_entry_t *entry = - _cairo_cogl_linear_gradient_texture_for_extend (gradient, extend_mode); - if (entry) { - *gradient_out = _cairo_cogl_linear_gradient_reference (gradient); - return CAIRO_INT_STATUS_SUCCESS; - } - } - - if (!gradient) { - gradient = _cairo_malloc (sizeof (cairo_cogl_linear_gradient_t) + - sizeof (cairo_gradient_stop_t) * (n_stops - 1)); - if (!gradient) - return CAIRO_INT_STATUS_NO_MEMORY; - - CAIRO_REFERENCE_COUNT_INIT (&gradient->ref_count, 1); - /* NB: we update the cache_entry size at the end before - * [re]adding it to the cache. */ - gradient->cache_entry.hash = hash; - gradient->textures = NULL; - gradient->n_stops = n_stops; - gradient->stops = gradient->stops_embedded; - memcpy (gradient->stops_embedded, stops, sizeof (cairo_gradient_stop_t) * n_stops); - } else { - _cairo_cogl_linear_gradient_reference (gradient); - } - - entry = _cairo_malloc (sizeof (cairo_cogl_linear_texture_entry_t)); - if (unlikely (!entry)) { - status = CAIRO_INT_STATUS_NO_MEMORY; - goto BAIL; - } - - compatibilities = _cairo_cogl_compatibility_from_extend_mode (extend_mode); - - n_internal_stops = n_stops; - stop_offset = 0; - - /* We really need stops covering the full [0,1] range for repeat/reflect - * if we want to use sampler REPEAT/MIRROR wrap modes so we may need - * to add some extra stops... */ - if (extend_mode == CAIRO_EXTEND_REPEAT || extend_mode == CAIRO_EXTEND_REFLECT) - { - /* If we don't need any extra stops then actually the texture - * will be shareable for repeat and reflect... */ - compatibilities = (CAIRO_COGL_GRADIENT_CAN_EXTEND_REPEAT | - CAIRO_COGL_GRADIENT_CAN_EXTEND_REFLECT); - - if (stops[0].offset != 0) { - n_internal_stops++; - stop_offset++; - } - - if (stops[n_stops - 1].offset != 1) - n_internal_stops++; - } - - internal_stops = alloca (n_internal_stops * sizeof (cairo_gradient_stop_t)); - memcpy (&internal_stops[stop_offset], stops, sizeof (cairo_gradient_stop_t) * n_stops); - - /* cairo_color_stop_t values are all unpremultiplied but we need to - * interpolate premultiplied colors so we premultiply all the double - * components now. (skipping any extra stops added for repeat/reflect) - * - * Another thing to note is that by premultiplying the colors - * early we'll also reduce the range of colors to interpolate - * which can result in smaller gradient textures. - */ - for (n = stop_offset; n < n_stops; n++) { - cairo_color_stop_t *color = &internal_stops[n].color; - color->red *= color->alpha; - color->green *= color->alpha; - color->blue *= color->alpha; - } - - if (n_internal_stops != n_stops) - { - if (extend_mode == CAIRO_EXTEND_REPEAT) { - compatibilities &= ~CAIRO_COGL_GRADIENT_CAN_EXTEND_REFLECT; - if (stops[0].offset != 0) { - /* what's the wrap-around distance between the user's end-stops? */ - double dx = (1.0 - stops[n_stops - 1].offset) + stops[0].offset; - internal_stops[0].offset = 0; - color_stop_lerp (&stops[0].color, - &stops[n_stops - 1].color, - stops[0].offset / dx, - &internal_stops[0].color); - } - if (stops[n_stops - 1].offset != 1) { - internal_stops[n_internal_stops - 1].offset = 1; - internal_stops[n_internal_stops - 1].color = internal_stops[0].color; - } - } else if (extend_mode == CAIRO_EXTEND_REFLECT) { - compatibilities &= ~CAIRO_COGL_GRADIENT_CAN_EXTEND_REPEAT; - if (stops[0].offset != 0) { - internal_stops[0].offset = 0; - internal_stops[0].color = stops[n_stops - 1].color; - } - if (stops[n_stops - 1].offset != 1) { - internal_stops[n_internal_stops - 1].offset = 1; - internal_stops[n_internal_stops - 1].color = stops[0].color; - } - } - } - - stops = internal_stops; - n_stops = n_internal_stops; - - width = _cairo_cogl_linear_gradient_width_for_stops (extend_mode, n_stops, stops); - - if (extend_mode == CAIRO_EXTEND_PAD) { - - /* Here we need to guarantee that the edge texels of our - * texture correspond to the desired padding color so we - * can use CLAMP_TO_EDGE. - * - * For short stop-gaps and especially for degenerate stops - * it's possible that without special consideration the - * user's end stop colors would not be present in our final - * texture. - * - * To handle this we forcibly add two extra padding texels - * at the edges which extend beyond the [0,1] range of the - * gradient itself and we will later report a translate and - * scale transform to compensate for this. - */ - - /* XXX: If we consider generating a mipmap for our 1d texture - * at some point then we also need to consider how much - * padding to add to be sure lower mipmap levels still have - * the desired edge color (as opposed to a linear blend with - * other colors of the gradient). - */ - - left_padding = 1; - left_padding_color = stops[0].color; - right_padding = 1; - right_padding_color = stops[n_stops - 1].color; - } else if (extend_mode == CAIRO_EXTEND_NONE) { - /* We handle EXTEND_NONE by adding two extra, transparent, texels at - * the ends of the texture and use CLAMP_TO_EDGE. - * - * We add a scale and translate transform so to account for our texels - * extending beyond the [0,1] range. */ - - left_padding = 1; - left_padding_color.red = 0; - left_padding_color.green = 0; - left_padding_color.blue = 0; - left_padding_color.alpha = 0; - right_padding = 1; - right_padding_color = left_padding_color; - } - - /* If we still have stops that don't cover the full [0,1] range - * then we need to define a texture-coordinate scale + translate - * transform to account for that... */ - if (stops[n_stops - 1].offset - stops[0].offset < 1) { - float range = stops[n_stops - 1].offset - stops[0].offset; - entry->scale_x = 1.0 / range; - entry->translate_x = -(stops[0].offset * entry->scale_x); - } - - width += left_padding + right_padding; - - width = _cairo_cogl_util_next_p2 (width); - width = MIN (4096, width); /* lets not go too stupidly big! */ - - if (!device->has_npots) - width = pow (2, ceil (log2 (width))); - - if (need_mirrored_gradient) - tex_width = width * 2; - else - tex_width = width; - - components = _cairo_cogl_linear_gradient_components_for_stops (extend_mode, n_stops, stops); - - do { - tex = cogl_texture_2d_new_with_size (device->cogl_context, - tex_width, 1); - } while (tex == NULL && width >> 1 && tex_width >> 1); - - if (unlikely (!tex)) { - status = CAIRO_INT_STATUS_NO_MEMORY; - goto BAIL; - } - - cogl_texture_set_components (tex, components); - - entry->texture = tex; - entry->compatibility = compatibilities; - - un_padded_width = width - left_padding - right_padding; - - /* XXX: only when we know the final texture width can we calculate the - * scale and translate factors needed to account for padding... */ - if (un_padded_width != width) - entry->scale_x *= (float)un_padded_width / (float)width; - if (left_padding) - entry->translate_x += (entry->scale_x / (float)un_padded_width) * (float)left_padding; - - offscreen = cogl_offscreen_new_with_texture (tex); - cogl_framebuffer_orthographic (offscreen, 0, 0, - tex_width, 1, - -1, 100); - cogl_framebuffer_clear4f (offscreen, - COGL_BUFFER_BIT_COLOR, - 0, 0, 0, 0); - - n_quads = n_stops - 1 + !!left_padding + !!right_padding; - n_vertices = 6 * n_quads; - vertices = _cairo_malloc_ab (n_vertices, sizeof (CoglVertexP2C4)); - if (unlikely (!vertices)) { - status = CAIRO_INT_STATUS_NO_MEMORY; - goto BAIL; - } - - p = vertices; - if (left_padding) - emit_stop (&p, 0, left_padding, &left_padding_color, &left_padding_color); - prev = (float)left_padding; - for (n = 1; n < n_stops; n++) { - right = (float)left_padding + (float)un_padded_width * stops[n].offset; - emit_stop (&p, prev, right, &stops[n-1].color, &stops[n].color); - prev = right; - } - if (right_padding) - emit_stop (&p, prev, width, &right_padding_color, &right_padding_color); - - prim = cogl_primitive_new_p2c4 (device->cogl_context, - COGL_VERTICES_MODE_TRIANGLES, - n_vertices, - vertices); - free (vertices); - pipeline = cogl_pipeline_new (device->cogl_context); - cogl_primitive_draw (prim, offscreen, pipeline); - - if (need_mirrored_gradient) { - /* In order to use a reflected gradient on hardware that - * doesn't have a mirrored repeating texture wrap mode, we - * render two reflected images to a double-length linear - * texture and reflect that */ - CoglMatrix transform; - - cogl_matrix_init_identity (&transform); - cogl_matrix_translate (&transform, tex_width, 0.0f, 0.0f); - cogl_matrix_scale (&transform, -1.0f, 1.0f, 1.0f); - - cogl_framebuffer_transform (offscreen, &transform); - cogl_primitive_draw (prim, offscreen, pipeline); - } - - cogl_object_unref (prim); - cogl_object_unref (pipeline); - - cogl_object_unref (offscreen); - offscreen = NULL; - - gradient->textures = g_list_prepend (gradient->textures, entry); - gradient->cache_entry.size = _cairo_cogl_linear_gradient_size (gradient); - -#ifdef DUMP_GRADIENTS_TO_PNG - dump_gradient_to_png (tex); -#endif - -#warning "FIXME:" - /* XXX: it seems the documentation of _cairo_cache_insert isn't true - it - * doesn't handle re-adding the same entry gracefully - the cache will - * just keep on growing and then it will start randomly evicting things - * pointlessly */ - /* we ignore errors here and just return an uncached gradient */ - if (likely (! _cairo_cache_insert (&device->linear_cache, &gradient->cache_entry))) - _cairo_cogl_linear_gradient_reference (gradient); - - *gradient_out = gradient; - return CAIRO_INT_STATUS_SUCCESS; - -BAIL: - free (entry); - if (gradient) - _cairo_cogl_linear_gradient_destroy (gradient); - if (offscreen) - cogl_object_unref (offscreen); - return status; -} diff --git a/gfx/cairo/cairo/src/cairo-cogl-private.h b/gfx/cairo/cairo/src/cairo-cogl-private.h deleted file mode 100644 index b0be2661eb..0000000000 --- a/gfx/cairo/cairo/src/cairo-cogl-private.h +++ /dev/null @@ -1,164 +0,0 @@ -/* cairo - a vector graphics library with display and print output - * - * Copyright © 2011 Intel Corporation. - * - * This library is free software; you can redistribute it and/or - * modify it either under the terms of the GNU Lesser General Public - * License version 2.1 as published by the Free Software Foundation - * (the "LGPL") or, at your option, under the terms of the Mozilla - * Public License Version 1.1 (the "MPL"). If you do not alter this - * notice, a recipient may use your version of this file under either - * the MPL or the LGPL. - * - * You should have received a copy of the LGPL along with this library - * in the file COPYING-LGPL-2.1; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Suite 500, Boston, MA 02110-1335, 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.og/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. - * - * Contributor(s): - * Robert Bragg <robert@linux.intel.com> - */ - -#ifndef CAIRO_COGL_PRIVATE_H -#define CAIRO_COGL_PRIVATE_H - -#include "cairo-device-private.h" -#include "cairo-cache-private.h" -#include "cairo-backend-private.h" -#include "cairo-default-context-private.h" -#include "cairo-surface-private.h" -#include "cairo-freelist-private.h" - -#include <cogl/cogl2-experimental.h> - -typedef enum _cairo_cogl_template_type { - /* solid source */ - CAIRO_COGL_TEMPLATE_TYPE_SOLID, - /* solid source with solid mask */ - CAIRO_COGL_TEMPLATE_TYPE_SOLID_MASK_SOLID, - /* solid source with texture mask */ - CAIRO_COGL_TEMPLATE_TYPE_TEXTURE_MASK_SOLID, - /* texture source */ - CAIRO_COGL_TEMPLATE_TYPE_TEXTURE, - /* texture source with solid mask */ - CAIRO_COGL_TEMPLATE_TYPE_SOLID_MASK_TEXTURE, - /* texture source with texture mask */ - CAIRO_COGL_TEMPLATE_TYPE_TEXTURE_MASK_TEXTURE, - /* texture source with source alpha ignored */ - CAIRO_COGL_TEMPLATE_TYPE_TEXTURE_IGNORE_ALPHA, - /* texture source with solid mask with source alpha ignored */ - CAIRO_COGL_TEMPLATE_TYPE_SOLID_MASK_TEXTURE_IGNORE_ALPHA, - /* texture source with texture mask with source alpha ignored */ - CAIRO_COGL_TEMPLATE_TYPE_TEXTURE_MASK_TEXTURE_IGNORE_ALPHA, - CAIRO_COGL_TEMPLATE_TYPE_COUNT -} cairo_cogl_template_type; - -typedef struct _cairo_cogl_device { - cairo_device_t base; - - CoglContext *cogl_context; - - cairo_bool_t has_npots; - cairo_bool_t has_mirrored_repeat; - - CoglAttributeBuffer *buffer_stack; - size_t buffer_stack_size; - size_t buffer_stack_offset; - guint8 *buffer_stack_pointer; - - /* This is a limited set of templates because we don't support the - * full range of operators that cairo has. The CAIRO_OPERATOR_ADD - * is the operator enum with the highest value that we support so - * we cap the size of the array by that. - * - * For each operator, we have a template for when we have a solid - * source and a non-solid source. For each of those, we also have - * additional templates for when we have a solid mask or a - * non-solid mask, for a total of six templates per operator. - * - * The templates are set to null at device creation time and only - * actually created on their first use. - */ - CoglPipeline *template_pipelines[CAIRO_OPERATOR_ADD + 1][CAIRO_COGL_TEMPLATE_TYPE_COUNT]; - - /* Caches 1d linear gradient textures */ - cairo_cache_t linear_cache; - - cairo_cache_t path_fill_prim_cache; - cairo_cache_t path_stroke_prim_cache; - - cairo_freelist_t path_fill_meta_freelist; - cairo_freelist_t path_stroke_meta_freelist; -} cairo_cogl_device_t; - -typedef struct _cairo_cogl_clip_primitives { - cairo_t *clip; - CoglPrimitive **primitives; -} cairo_cogl_clip_primitives_t; - -typedef struct _cairo_cogl_surface { - cairo_surface_t base; - - /* We currently have 3 basic kinds of Cogl surfaces: - * 1) A light surface simply wrapping a CoglTexture - * 2) A CoglOffscreen framebuffer that implicitly also wraps a CoglTexture - * 3) A CoglOnscreen framebuffer which could potentially be mapped to - * a CoglTexture (e.g. via tfp on X11) but we don't currently do - * that. - */ - - CoglTexture *texture; - CoglFramebuffer *framebuffer; - - int width; - int height; - - /* Is this a snapshot used for mirrored repeating on hardware which - * doesn't have it, consisting of four reflected images? */ - cairo_bool_t is_mirrored_snapshot; - - GQueue *journal; - - cairo_clip_t *last_clip; - - /* A small fifo of recently used cairo_clip_ts paired with CoglPrimitives - * that can be used to mask the stencil buffer. */ - GList *clips_fifo; - - int n_clip_updates_per_frame; - - /* Since the surface backend drawing operator functions don't get - * passed the current cairo_t context we don't have a good way - * to get our user-coordinates path into our surface_fill function. - * - * For now we use our _cairo_cogl_context_fill() wrapper to set this - * side band data on the surface... - */ - cairo_path_fixed_t *user_path; - cairo_matrix_t ctm; - cairo_matrix_t ctm_inverse; - cairo_bool_t path_is_rectangle; - double path_rectangle_x; - double path_rectangle_y; - double path_rectangle_width; - double path_rectangle_height; -} cairo_cogl_surface_t; - -cairo_status_t -_cairo_cogl_path_fixed_rectangle (cairo_path_fixed_t *path, - cairo_fixed_t x, - cairo_fixed_t y, - cairo_fixed_t width, - cairo_fixed_t height); - -#endif /* CAIRO_COGL_PRIVATE_H */ diff --git a/gfx/cairo/cairo/src/cairo-cogl-surface.c b/gfx/cairo/cairo/src/cairo-cogl-surface.c deleted file mode 100644 index 36e5f77d8b..0000000000 --- a/gfx/cairo/cairo/src/cairo-cogl-surface.c +++ /dev/null @@ -1,4106 +0,0 @@ -/* cairo - a vector graphics library with display and print output - * - * Copyright © 2011 Intel Corporation. - * - * This library is free software; you can redistribute it and/or - * modify it either under the terms of the GNU Lesser General Public - * License version 2.1 as published by the Free Software Foundation - * (the "LGPL") or, at your option, under the terms of the Mozilla - * Public License Version 1.1 (the "MPL"). If you do not alter this - * notice, a recipient may use your version of this file under either - * the MPL or the LGPL. - * - * You should have received a copy of the LGPL along with this library - * in the file COPYING-LGPL-2.1; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Suite 500, Boston, MA 02110-1335, 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.og/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. - * - * Contributor(s): - * Robert Bragg <robert@linux.intel.com> - */ -#include "cairoint.h" - -#include "cairo-cache-private.h" -#include "cairo-error-private.h" -#include "cairo-path-fixed-private.h" -#include "cairo-recording-surface-private.h" -#include "cairo-recording-surface-inline.h" -#include "cairo-fixed-private.h" -#include "cairo-device-private.h" -#include "cairo-composite-rectangles-private.h" -#include "cairo-image-surface-inline.h" -#include "cairo-cogl-private.h" -#include "cairo-cogl-gradient-private.h" -#include "cairo-arc-private.h" -#include "cairo-traps-private.h" -#include "cairo-surface-subsurface-inline.h" -#include "cairo-surface-fallback-private.h" -#include "cairo-surface-offset-private.h" - -#include "cairo-cogl.h" - -#include <cogl/cogl2-experimental.h> -#include <glib.h> - -#define CAIRO_COGL_DEBUG 0 -//#define DISABLE_BATCHING -#define MAX_JOURNAL_SIZE 100 - -#if CAIRO_COGL_DEBUG && __GNUC__ -#define UNSUPPORTED(reason) ({ \ - g_warning ("cairo-cogl: hit unsupported operation: %s", reason); \ - CAIRO_INT_STATUS_UNSUPPORTED; \ -}) -#else -#define UNSUPPORTED(reason) CAIRO_INT_STATUS_UNSUPPORTED -#endif - -#define CAIRO_COGL_PATH_META_CACHE_SIZE (1024 * 1024) - -typedef struct _cairo_cogl_texture_attributes { - /* nabbed from cairo_surface_attributes_t... */ - cairo_matrix_t matrix; - cairo_extend_t extend; - cairo_bool_t has_component_alpha; - - CoglPipelineFilter filter; - CoglPipelineWrapMode s_wrap; - CoglPipelineWrapMode t_wrap; -} cairo_cogl_texture_attributes_t; - -typedef struct _cairo_cogl_pipeline { - int n_layers; - cairo_operator_t op; - - /* These are not always the same as the operator's, as sometimes - * this is a pre-render for a different operator */ - cairo_bool_t src_bounded; - cairo_bool_t mask_bounded; - - cairo_bool_t has_src_tex_clip; - cairo_path_fixed_t src_tex_clip; - cairo_bool_t has_mask_tex_clip; - cairo_path_fixed_t mask_tex_clip; - cairo_rectangle_int_t unbounded_extents; - - CoglPipeline *pipeline; -} cairo_cogl_pipeline_t; - -typedef enum _cairo_cogl_journal_entry_type { - CAIRO_COGL_JOURNAL_ENTRY_TYPE_RECTANGLE, - CAIRO_COGL_JOURNAL_ENTRY_TYPE_PRIMITIVE, - CAIRO_COGL_JOURNAL_ENTRY_TYPE_CLIP -} cairo_cogl_journal_entry_type_t; - -typedef struct _cairo_cogl_journal_entry { - cairo_cogl_journal_entry_type_t type; -} cairo_cogl_journal_entry_t; - -typedef struct _cairo_cogl_journal_clip_entry { - cairo_cogl_journal_entry_t base; - cairo_clip_t *clip; -} cairo_cogl_journal_clip_entry_t; - -typedef struct _cairo_cogl_journal_rect_entry { - cairo_cogl_journal_entry_t base; - cairo_cogl_pipeline_t *pipeline; - - float x; - float y; - float width; - float height; - cairo_matrix_t ctm; -} cairo_cogl_journal_rect_entry_t; - -typedef struct _cairo_cogl_journal_prim_entry { - cairo_cogl_journal_entry_t base; - cairo_cogl_pipeline_t *pipeline; - - CoglPrimitive *primitive; - cairo_matrix_t transform; -} cairo_cogl_journal_prim_entry_t; - -typedef struct _cairo_cogl_path_fill_meta { - cairo_cache_entry_t base; - cairo_path_fixed_t path; - cairo_fill_rule_t fill_rule; - double tolerance; - - CoglPrimitive *prim; - - cairo_freelist_t *freelist; -} cairo_cogl_path_fill_meta_t; - -typedef struct _cairo_cogl_path_stroke_meta { - cairo_cache_entry_t base; - cairo_path_fixed_t path; - cairo_stroke_style_t style; - double tolerance; - - CoglPrimitive *prim; - - cairo_freelist_t *freelist; -} cairo_cogl_path_stroke_meta_t; - -static cairo_surface_t * -_cairo_cogl_surface_create_full (cairo_cogl_device_t *dev, - cairo_content_t content, - CoglFramebuffer *framebuffer, - CoglTexture *texture); - -static void -_cairo_cogl_journal_flush (cairo_cogl_surface_t *surface); - -cairo_private extern const cairo_surface_backend_t _cairo_cogl_surface_backend; - -slim_hidden_proto (cairo_cogl_device_create); -slim_hidden_proto (cairo_cogl_surface_create_for_fb); -slim_hidden_proto (cairo_cogl_onscreen_surface_create); -slim_hidden_proto (cairo_cogl_offscreen_surface_create); -slim_hidden_proto (cairo_cogl_surface_get_framebuffer); -slim_hidden_proto (cairo_cogl_surface_get_texture); -slim_hidden_proto (cairo_cogl_surface_end_frame); -slim_hidden_proto (cairo_cogl_surface_synchronize); - -static cairo_cogl_device_t * -to_device (cairo_device_t *device) -{ - return (cairo_cogl_device_t *)device; -} - -/* moves trap points such that they become the actual corners of the trapezoid */ -static void -_sanitize_trap (cairo_trapezoid_t *t) -{ - cairo_trapezoid_t s = *t; - -#define FIX(lr, tb, p) \ - if (t->lr.p.y != t->tb) { \ - t->lr.p.x = s.lr.p2.x + _cairo_fixed_mul_div_floor (s.lr.p1.x - s.lr.p2.x, s.tb - s.lr.p2.y, s.lr.p1.y - s.lr.p2.y); \ - t->lr.p.y = s.tb; \ - } - FIX (left, top, p1); - FIX (left, bottom, p2); - FIX (right, top, p1); - FIX (right, bottom, p2); -} - -static cairo_status_t -_cairo_cogl_surface_ensure_framebuffer (cairo_cogl_surface_t *surface) -{ - CoglError *error = NULL; - - if (surface->framebuffer) - return CAIRO_STATUS_SUCCESS; - - surface->framebuffer = - cogl_offscreen_new_with_texture (surface->texture); - if (unlikely (!cogl_framebuffer_allocate (surface->framebuffer, - &error))) - { - g_warning ("Could not create framebuffer for surface: %s", - error->message); - cogl_error_free (error); - cogl_object_unref (surface->framebuffer); - surface->framebuffer = NULL; - return CAIRO_STATUS_NO_MEMORY; - } - - cogl_framebuffer_orthographic (surface->framebuffer, 0, 0, - cogl_texture_get_width (surface->texture), - cogl_texture_get_height (surface->texture), - -1, 100); - - return CAIRO_STATUS_SUCCESS; -} - -static cairo_bool_t -_cairo_cogl_surface_get_extents (void *abstract_surface, - cairo_rectangle_int_t *extents) -{ - cairo_cogl_surface_t *surface = abstract_surface; - - extents->x = 0; - extents->y = 0; - extents->width = surface->width; - extents->height = surface->height; - - return TRUE; -} - -/* Taken from cairo-surface-clipper.c */ -static cairo_status_t -_cairo_path_fixed_add_box (cairo_path_fixed_t *path, - const cairo_box_t *box) -{ - cairo_status_t status; - - status = _cairo_path_fixed_move_to (path, box->p1.x, box->p1.y); - if (unlikely (status)) - return status; - - status = _cairo_path_fixed_line_to (path, box->p2.x, box->p1.y); - if (unlikely (status)) - return status; - - status = _cairo_path_fixed_line_to (path, box->p2.x, box->p2.y); - if (unlikely (status)) - return status; - - status = _cairo_path_fixed_line_to (path, box->p1.x, box->p2.y); - if (unlikely (status)) - return status; - - return _cairo_path_fixed_close_path (path); -} - -static void -_cairo_cogl_journal_discard (cairo_cogl_surface_t *surface) -{ - GList *l; - - if (!surface->journal) { - assert (surface->last_clip == NULL); - return; - } - - for (l = surface->journal->head; l; l = l->next) { - cairo_cogl_journal_entry_t *entry = l->data; - gsize entry_size; - - switch (entry->type) - { - case CAIRO_COGL_JOURNAL_ENTRY_TYPE_CLIP: { - cairo_cogl_journal_clip_entry_t *clip_entry = - (cairo_cogl_journal_clip_entry_t *)entry; - _cairo_clip_destroy (clip_entry->clip); - entry_size = sizeof (cairo_cogl_journal_clip_entry_t); - break; - } - case CAIRO_COGL_JOURNAL_ENTRY_TYPE_RECTANGLE: { - cairo_cogl_journal_rect_entry_t *rect_entry = - (cairo_cogl_journal_rect_entry_t *)entry; - cogl_object_unref (rect_entry->pipeline->pipeline); - if (rect_entry->pipeline->has_src_tex_clip) - _cairo_path_fixed_fini (&rect_entry->pipeline->src_tex_clip); - if (rect_entry->pipeline->has_mask_tex_clip) - _cairo_path_fixed_fini (&rect_entry->pipeline->mask_tex_clip); - g_free (rect_entry->pipeline); - entry_size = sizeof (cairo_cogl_journal_rect_entry_t); - break; - } - case CAIRO_COGL_JOURNAL_ENTRY_TYPE_PRIMITIVE: { - cairo_cogl_journal_prim_entry_t *prim_entry = - (cairo_cogl_journal_prim_entry_t *)entry; - cogl_object_unref (prim_entry->pipeline->pipeline); - if (prim_entry->primitive) - cogl_object_unref (prim_entry->primitive); - if (prim_entry->pipeline->has_src_tex_clip) - _cairo_path_fixed_fini (&prim_entry->pipeline->src_tex_clip); - if (prim_entry->pipeline->has_mask_tex_clip) - _cairo_path_fixed_fini (&prim_entry->pipeline->mask_tex_clip); - g_free (prim_entry->pipeline); - entry_size = sizeof (cairo_cogl_journal_prim_entry_t); - break; - } - default: - assert (0); /* not reached! */ - entry_size = 0; /* avoid compiler warning */ - } - g_slice_free1 (entry_size, entry); - } - - g_queue_clear (surface->journal); - - if (surface->last_clip) { - _cairo_clip_destroy (surface->last_clip); - surface->last_clip = NULL; - } -} - -static void -_cairo_cogl_journal_free (cairo_cogl_surface_t *surface) -{ - _cairo_cogl_journal_discard (surface); - g_queue_free (surface->journal); - surface->journal = NULL; -} - -static void -_cairo_cogl_journal_log_primitive (cairo_cogl_surface_t *surface, - cairo_cogl_pipeline_t *pipeline, - CoglPrimitive *primitive, - cairo_matrix_t *transform) -{ - cairo_cogl_journal_prim_entry_t *entry; - - if (unlikely (surface->journal == NULL)) - surface->journal = g_queue_new (); - - /* FIXME: Instead of a GList here we should stack allocate the journal - * entries so it would be cheaper to allocate and they can all be freed in - * one go after flushing! */ - entry = g_slice_new (cairo_cogl_journal_prim_entry_t); - entry->base.type = CAIRO_COGL_JOURNAL_ENTRY_TYPE_PRIMITIVE; - - entry->pipeline = pipeline; - - entry->primitive = primitive; - if (primitive) - cogl_object_ref (primitive); - - entry->transform = *transform; - - g_queue_push_tail (surface->journal, entry); - -#ifdef DISABLE_BATCHING - _cairo_cogl_journal_flush (surface); -#else - /* To avoid consuming too much memory, flush the journal if it gets - * to a certain size */ - if (g_queue_get_length (surface->journal) > MAX_JOURNAL_SIZE) - _cairo_cogl_journal_flush (surface); -#endif -} - -static void -_cairo_cogl_journal_log_rectangle (cairo_cogl_surface_t *surface, - cairo_cogl_pipeline_t *pipeline, - float x, - float y, - float width, - float height, - cairo_matrix_t *ctm) -{ - cairo_cogl_journal_rect_entry_t *entry; - - if (unlikely (surface->journal == NULL)) - surface->journal = g_queue_new (); - - /* FIXME: Instead of a GList here we should stack allocate the journal - * entries so it would be cheaper to allocate and they can all be freed in - * one go after flushing! */ - entry = g_slice_new (cairo_cogl_journal_rect_entry_t); - entry->base.type = CAIRO_COGL_JOURNAL_ENTRY_TYPE_RECTANGLE; - - entry->pipeline = pipeline; - - entry->x = x; - entry->y = y; - entry->width = width; - entry->height = height; - entry->ctm = *ctm; - - g_queue_push_tail (surface->journal, entry); - -#ifdef DISABLE_BATCHING - _cairo_cogl_journal_flush (surface); -#else - /* To avoid consuming too much memory, flush the journal if it gets - * to a certain size */ - if (g_queue_get_length (surface->journal) > MAX_JOURNAL_SIZE) - _cairo_cogl_journal_flush (surface); -#endif -} - -static void -_cairo_cogl_journal_log_clip (cairo_cogl_surface_t *surface, - const cairo_clip_t *clip) -{ - cairo_cogl_journal_clip_entry_t *entry; - - if (unlikely (surface->journal == NULL)) - surface->journal = g_queue_new (); - - /* FIXME: Instead of a GList here we should stack allocate the journal - * entries so it would be cheaper to allocate and they can all be freed in - * one go after flushing! */ - entry = g_slice_new (cairo_cogl_journal_clip_entry_t); - entry->base.type = CAIRO_COGL_JOURNAL_ENTRY_TYPE_CLIP; - entry->clip = _cairo_clip_copy (clip); - - g_queue_push_tail (surface->journal, entry); -} - -static CoglAttributeBuffer * -_cairo_cogl_device_allocate_buffer_space (cairo_cogl_device_t *dev, - size_t size, - size_t *offset, - void **pointer) -{ - /* XXX: In the Cogl journal we found it more efficient to have a pool of - * buffers that we re-cycle but for now we simply throw away our stack - * buffer each time we flush. */ - if (unlikely (dev->buffer_stack && - (dev->buffer_stack_size - dev->buffer_stack_offset) < size)) { - cogl_buffer_unmap (dev->buffer_stack); - cogl_object_unref (dev->buffer_stack); - dev->buffer_stack = NULL; - dev->buffer_stack_size *= 2; - } - - if (unlikely (dev->buffer_stack_size < size)) - dev->buffer_stack_size = size * 2; - - if (unlikely (dev->buffer_stack == NULL)) { - dev->buffer_stack = - cogl_attribute_buffer_new (dev->cogl_context, - dev->buffer_stack_size, - NULL); - dev->buffer_stack_pointer = - cogl_buffer_map (dev->buffer_stack, - COGL_BUFFER_ACCESS_WRITE, - COGL_BUFFER_MAP_HINT_DISCARD); - dev->buffer_stack_offset = 0; - } - - *pointer = dev->buffer_stack_pointer + dev->buffer_stack_offset; - *offset = dev->buffer_stack_offset; - - dev->buffer_stack_offset += size; - return cogl_object_ref (dev->buffer_stack); -} - - -static CoglAttributeBuffer * -_cairo_cogl_traps_to_triangles_buffer (cairo_cogl_surface_t *surface, - cairo_traps_t *traps, - size_t *offset, - cairo_bool_t one_shot) -{ - CoglAttributeBuffer *buffer; - int n_traps = traps->num_traps; - int i; - CoglVertexP2 *triangles; - cairo_cogl_device_t *dev = to_device(surface->base.device); - - if (one_shot) { - buffer = - _cairo_cogl_device_allocate_buffer_space (dev, - n_traps * sizeof (CoglVertexP2) * 6, - offset, - (void **)&triangles); - if (!buffer) - return NULL; - } else { - buffer = - cogl_attribute_buffer_new (dev->cogl_context, - n_traps * sizeof (CoglVertexP2) * 6, - NULL); - if (!buffer) - return NULL; - triangles = cogl_buffer_map (buffer, - COGL_BUFFER_ACCESS_WRITE, - COGL_BUFFER_MAP_HINT_DISCARD); - if (!triangles) - return NULL; - *offset = 0; - } - - /* XXX: This is can be very expensive. I'm not sure a.t.m if it's - * predominantly the bandwidth required or the cost of the fixed_to_float - * conversions but either way we should try using an index buffer to - * reduce the amount we upload by 1/3 (offset by allocating and uploading - * indices though) sadly though my experience with the intel mesa drivers - * is that slow paths can easily be hit when starting to use indices. - */ - for (i = 0; i < n_traps; i++) - { - CoglVertexP2 *p = &triangles[i * 6]; - cairo_trapezoid_t *trap = &traps->traps[i]; - - p[0].x = _cairo_fixed_to_double (trap->left.p1.x); - p[0].y = _cairo_fixed_to_double (trap->left.p1.y); - - p[1].x = _cairo_fixed_to_double (trap->left.p2.x); - p[1].y = _cairo_fixed_to_double (trap->left.p2.y); - - p[2].x = _cairo_fixed_to_double (trap->right.p2.x); - p[2].y = _cairo_fixed_to_double (trap->right.p2.y); - - p[3].x = p[0].x; - p[3].y = p[0].y; - - p[4].x = p[2].x; - p[4].y = p[2].y; - - p[5].x = _cairo_fixed_to_double (trap->right.p1.x); - p[5].y = _cairo_fixed_to_double (trap->right.p1.y); - } - - if (!one_shot) - cogl_buffer_unmap (buffer); - - return buffer; -} - -static CoglPrimitive * -_cairo_cogl_traps_to_composite_prim (cairo_cogl_surface_t *surface, - cairo_traps_t *traps, - cairo_bool_t one_shot) -{ - int n_traps = traps->num_traps; - size_t offset; - CoglAttributeBuffer *buffer; - CoglPrimitive *prim; - CoglAttribute *attributes[3]; - const char *attrib_names[3] = {"cogl_position_in", - "cogl_tex_coord0_in", - "cogl_tex_coord1_in"}; - int i; - - /* XXX: Ideally we would skip tessellating to traps entirely since - * given their representation, conversion to triangles is quite expensive. - * - * This simplifies the conversion to triangles by making the end points of - * the two side lines actually just correspond to the corners of the - * traps. - */ - for (i = 0; i < n_traps; i++) - _sanitize_trap (&traps->traps[i]); - - buffer = _cairo_cogl_traps_to_triangles_buffer (surface, - traps, - &offset, - one_shot); - - /* We create the largest used number of texture coordinate - * attributes here to ensure that when cached, they can be reused - * with any pipeline that we may associate with a given path. If - * the corresponding layer for a texture coordinates attribute - * doesn't exist, cogl simply ignores it. Since all of the - * attributes are aliasing the same attribute buffer, the overhead - * of specifying them is minimal. */ - for (i = 0; i < 3; i++) { - attributes[i] = cogl_attribute_new (buffer, - attrib_names[i], - sizeof (CoglVertexP2), - offset, - 2, - COGL_ATTRIBUTE_TYPE_FLOAT); - } - - /* The attributes will have taken references on the buffer */ - cogl_object_unref (buffer); - - prim = - cogl_primitive_new_with_attributes (COGL_VERTICES_MODE_TRIANGLES, - n_traps * 6, attributes, 3); - - /* The primitive will now keep the attributes alive... */ - for (i = 0; i < 3; i++) - cogl_object_unref (attributes[i]); - - return prim; -} - -/* In order to facilitate path caching, we transform the input path - * into a form that will make all translations and rotations of a given - * path identical, thereby allowing them to be identified with - * conventional path hashing and equivalence functions. A - * transformation matrix is also output so that the path can be - * transformed back into its original form during rendering. */ -static cairo_int_status_t -_cairo_cogl_get_untransformed_path (cairo_path_fixed_t *copy, - const cairo_path_fixed_t *orig, - cairo_matrix_t *transform_out) -{ - cairo_matrix_t transform; - cairo_int_status_t status; - - if (orig->buf.base.num_points < 1) - return CAIRO_INT_STATUS_NOTHING_TO_DO; - - status = _cairo_path_fixed_init_copy (copy, orig); - if (unlikely (status)) - return status; - - /* First the path is translated so that its first point lies on the - * origin. */ - cairo_matrix_init_translate (&transform, - -_cairo_fixed_to_double(orig->buf.points[0].x), - -_cairo_fixed_to_double(orig->buf.points[0].y)); - - /* Then the path is rotated so that its second point lies on the - * x axis. */ - if (orig->buf.base.num_points > 1) { - double x = _cairo_fixed_to_double(orig->buf.points[1].x) - - _cairo_fixed_to_double(orig->buf.points[0].x); - double y = _cairo_fixed_to_double(orig->buf.points[1].y) - - _cairo_fixed_to_double(orig->buf.points[0].y); - double hyp = sqrt (x * x + y * y); - - transform.xx = x / hyp; - transform.yy = x / hyp; - transform.xy = -y / hyp; - transform.yx = y / hyp; - } - - _cairo_path_fixed_transform (copy, &transform); - - *transform_out = transform; - status = cairo_matrix_invert (transform_out); - if (unlikely (status)) { - _cairo_path_fixed_fini (copy); - return status; - } - - return CAIRO_INT_STATUS_SUCCESS; -} - -static void -_cairo_cogl_path_fill_meta_destroy (cairo_cogl_path_fill_meta_t *meta) -{ - _cairo_path_fixed_fini (&meta->path); - cogl_object_unref (meta->prim); - - _cairo_freelist_free (meta->freelist, meta); -} - -static cairo_bool_t -_cairo_cogl_path_fill_meta_equal (const void *key_a, const void *key_b) -{ - const cairo_cogl_path_fill_meta_t *meta0 = key_a; - const cairo_cogl_path_fill_meta_t *meta1 = key_b; - - if (meta0->fill_rule != meta1->fill_rule) - return FALSE; - - if (meta0->tolerance != meta1->tolerance) - return FALSE; - - if (!_cairo_path_fixed_equal (&meta0->path, &meta1->path)) - return FALSE; - - return TRUE; -} - -static cairo_int_status_t -_cairo_cogl_fill_to_primitive (cairo_cogl_surface_t *surface, - const cairo_path_fixed_t *path, - cairo_fill_rule_t fill_rule, - double tolerance, - cairo_bool_t one_shot, - CoglPrimitive **primitive, - cairo_matrix_t *transform) -{ - cairo_traps_t traps; - cairo_int_status_t status; - cairo_cogl_path_fill_meta_t meta; - cairo_cogl_path_fill_meta_t *acquired_meta; - cairo_cogl_path_fill_meta_t *insert_meta = NULL; - cairo_cogl_device_t *dev = to_device (surface->base.device); - unsigned long hash; - - *primitive = NULL; - - status = _cairo_cogl_get_untransformed_path (&meta.path, - path, - transform); - if (unlikely (status)) - return status; - - hash = _cairo_path_fixed_hash (&meta.path); - hash = _cairo_hash_bytes (hash, &fill_rule, sizeof (fill_rule)); - hash = _cairo_hash_bytes (hash, &tolerance, sizeof (tolerance)); - meta.base.hash = hash; - meta.tolerance = tolerance; - meta.fill_rule = fill_rule; - - acquired_meta = _cairo_cache_lookup (&dev->path_fill_prim_cache, - &meta.base); - - if (acquired_meta) { - // g_print ("fill cache hit"); - *primitive = cogl_object_ref (acquired_meta->prim); - _cairo_path_fixed_fini (&meta.path); - return CAIRO_STATUS_SUCCESS; - } - - _cairo_traps_init (&traps); - status = _cairo_path_fixed_fill_to_traps (&meta.path, - fill_rule, - tolerance, - &traps); - if (unlikely (status)) - goto BAIL; - - if (traps.num_traps == 0) { - status = CAIRO_INT_STATUS_NOTHING_TO_DO; - goto BAIL; - } - - *primitive = _cairo_cogl_traps_to_composite_prim (surface, - &traps, - one_shot); - if (unlikely (!*primitive)) { - status = CAIRO_INT_STATUS_NO_MEMORY; - goto BAIL; - } - - insert_meta = - _cairo_freelist_alloc (&dev->path_fill_meta_freelist); - if (unlikely (!insert_meta)) { - status = CAIRO_INT_STATUS_NO_MEMORY; - goto BAIL; - } - - insert_meta->base.hash = meta.base.hash; - insert_meta->base.size = - traps.num_traps * sizeof (CoglVertexP2) * 6; - insert_meta->tolerance = tolerance; - insert_meta->fill_rule = fill_rule; - insert_meta->prim = cogl_object_ref (*primitive); - insert_meta->freelist = &dev->path_fill_meta_freelist; - - status = _cairo_path_fixed_init_copy (&insert_meta->path, - &meta.path); - if (unlikely (status)) - goto BAIL; - - if (unlikely (_cairo_cache_insert (&dev->path_fill_prim_cache, - &insert_meta->base))) - { - g_warning ("Fill primitive cache insertion unsuccessful"); - goto BAIL; - } - - _cairo_path_fixed_fini (&meta.path); - _cairo_traps_fini (&traps); - - return status; - -BAIL: - if (*primitive) { - cogl_object_unref (*primitive); - *primitive = NULL; - } - if (insert_meta) - _cairo_cogl_path_fill_meta_destroy (insert_meta); - _cairo_path_fixed_fini (&meta.path); - _cairo_traps_fini (&traps); - - return status; -} - -static cairo_bool_t -_cairo_cogl_stroke_style_equal (const cairo_stroke_style_t *a, - const cairo_stroke_style_t *b) -{ - if (a->line_width == b->line_width && - a->line_cap == b->line_cap && - a->line_join == b->line_join && - a->miter_limit == b->miter_limit && - a->num_dashes == b->num_dashes && - a->dash_offset == b->dash_offset) - { - unsigned int i; - for (i = 0; i < a->num_dashes; i++) { - if (a->dash[i] != b->dash[i]) - return FALSE; - } - } - return TRUE; -} - -static cairo_bool_t -_cairo_cogl_path_stroke_meta_equal (const void *key_a, - const void *key_b) -{ - const cairo_cogl_path_stroke_meta_t *meta0 = key_a; - const cairo_cogl_path_stroke_meta_t *meta1 = key_b; - - if (meta0->tolerance != meta1->tolerance) - return FALSE; - - if (!_cairo_cogl_stroke_style_equal (&meta0->style, &meta1->style)) - return FALSE; - - if (!_cairo_path_fixed_equal (&meta0->path, &meta1->path)) - return FALSE; - - return TRUE; -} - -static void -_cairo_cogl_path_stroke_meta_destroy (cairo_cogl_path_stroke_meta_t *meta) -{ - _cairo_stroke_style_fini (&meta->style); - _cairo_path_fixed_fini (&meta->path); - cogl_object_unref (meta->prim); - - _cairo_freelist_free (meta->freelist, meta); -} - -static unsigned long -_cairo_cogl_stroke_style_hash (unsigned long hash, - const cairo_stroke_style_t *style) -{ - unsigned int i; - hash = _cairo_hash_bytes (hash, &style->line_width, sizeof (style->line_width)); - hash = _cairo_hash_bytes (hash, &style->line_cap, sizeof (style->line_cap)); - hash = _cairo_hash_bytes (hash, &style->line_join, sizeof (style->line_join)); - hash = _cairo_hash_bytes (hash, &style->miter_limit, sizeof (style->miter_limit)); - hash = _cairo_hash_bytes (hash, &style->num_dashes, sizeof (style->num_dashes)); - hash = _cairo_hash_bytes (hash, &style->dash_offset, sizeof (style->dash_offset)); - for (i = 0; i < style->num_dashes; i++) - hash = _cairo_hash_bytes (hash, &style->dash[i], sizeof (double)); - return hash; -} - -static cairo_int_status_t -_cairo_cogl_stroke_to_primitive (cairo_cogl_surface_t *surface, - const cairo_path_fixed_t *path, - const cairo_stroke_style_t *style, - double tolerance, - cairo_bool_t one_shot, - CoglPrimitive **primitive, - cairo_matrix_t *transform) -{ - cairo_traps_t traps; - cairo_int_status_t status; - cairo_cogl_path_stroke_meta_t meta; - cairo_cogl_path_stroke_meta_t *acquired_meta; - cairo_cogl_path_stroke_meta_t *insert_meta = NULL; - cairo_matrix_t identity; - cairo_cogl_device_t *dev = to_device (surface->base.device); - unsigned long hash; - - *primitive = NULL; - - status = _cairo_cogl_get_untransformed_path (&meta.path, - path, - transform); - if (unlikely (status)) - return status; - - hash = _cairo_path_fixed_hash (&meta.path); - hash = _cairo_cogl_stroke_style_hash (hash, style); - hash = _cairo_hash_bytes (hash, &tolerance, sizeof (tolerance)); - meta.base.hash = hash; - meta.tolerance = tolerance; - - status = _cairo_stroke_style_init_copy (&meta.style, style); - if (unlikely (status)) { - _cairo_path_fixed_fini (&meta.path); - return status; - } - - acquired_meta = _cairo_cache_lookup (&dev->path_stroke_prim_cache, - &meta.base); - - if (acquired_meta) { - // g_print ("stroke cache hit"); - *primitive = cogl_object_ref (acquired_meta->prim); - _cairo_path_fixed_fini (&meta.path); - return CAIRO_STATUS_SUCCESS; - } - - _cairo_traps_init (&traps); - - cairo_matrix_init_identity (&identity); - status = _cairo_path_fixed_stroke_polygon_to_traps (&meta.path, - style, - &identity, - &identity, - tolerance, - &traps); - if (unlikely (status)) - goto BAIL; - - if (traps.num_traps == 0) { - status = CAIRO_INT_STATUS_NOTHING_TO_DO; - goto BAIL; - } - - *primitive = _cairo_cogl_traps_to_composite_prim (surface, - &traps, - one_shot); - if (unlikely (!*primitive)) { - status = CAIRO_INT_STATUS_NO_MEMORY; - goto BAIL; - } - - insert_meta = - _cairo_freelist_alloc (&dev->path_stroke_meta_freelist); - if (unlikely (!insert_meta)) { - status = CAIRO_INT_STATUS_NO_MEMORY; - goto BAIL; - } - - insert_meta->base.hash = meta.base.hash; - insert_meta->base.size = - traps.num_traps * sizeof (CoglVertexP2) * 6; - insert_meta->tolerance = tolerance; - insert_meta->prim = cogl_object_ref (*primitive); - insert_meta->freelist = &dev->path_stroke_meta_freelist; - - status = _cairo_stroke_style_init_copy (&insert_meta->style, - style); - if (unlikely (status)) { - _cairo_stroke_style_fini (&insert_meta->style); - free (insert_meta); - insert_meta = NULL; - goto BAIL; - } - - status = _cairo_path_fixed_init_copy (&insert_meta->path, - &meta.path); - if (unlikely (status)) - goto BAIL; - - if (unlikely (_cairo_cache_insert (&dev->path_stroke_prim_cache, - &insert_meta->base))) - { - g_warning ("Stroke primitive cache insertion unsuccessful"); - goto BAIL; - } - - _cairo_path_fixed_fini (&meta.path); - _cairo_stroke_style_fini (&meta.style); - _cairo_traps_fini (&traps); - - return status; - -BAIL: - if (*primitive) { - cogl_object_unref (*primitive); - *primitive = NULL; - } - if (insert_meta) - _cairo_cogl_path_stroke_meta_destroy (insert_meta); - _cairo_path_fixed_fini (&meta.path); - _cairo_stroke_style_fini (&meta.style); - _cairo_traps_fini (&traps); - - return status; -} - -static void -_cairo_cogl_set_path_prim_clip (cairo_cogl_surface_t *surface, - cairo_path_fixed_t *path, - int *clip_stack_depth, - cairo_fill_rule_t fill_rule, - double tolerance) -{ - cairo_rectangle_int_t extents; - cairo_int_status_t status; - CoglPrimitive *prim; - cairo_matrix_t transform; - CoglMatrix matrix; - double x1, y1, x2, y2; - - status = _cairo_cogl_fill_to_primitive (surface, - path, - fill_rule, - tolerance, - FALSE, - &prim, - &transform); - if (status == CAIRO_INT_STATUS_NOTHING_TO_DO) { - /* If the clip is of zero fill area, set all clipped */ - cogl_framebuffer_push_scissor_clip (surface->framebuffer, - 0, 0, 0, 0); - (*clip_stack_depth)++; - return; - } else if (unlikely (status)) { - g_warning ("Failed to get primitive for clip path while " - "flushing journal"); - goto BAIL; - } - - float transformfv[16] = { - transform.xx, transform.yx, 0, 0, - transform.xy, transform.yy, 0, 0, - 0, 0, 1, 0, - transform.x0, transform.y0, 0, 1 - }; - - cogl_matrix_init_from_array (&matrix, transformfv); - - cogl_framebuffer_push_matrix (surface->framebuffer); - cogl_framebuffer_transform (surface->framebuffer, &matrix); - - _cairo_path_fixed_approximate_clip_extents (path, &extents); - - /* The extents need to be transformed by the inverse of the - * modelview matrix because they are in terms of un-transformed - * device coordinates and the bounds coordinates will be - * transformed by the modelview matrix */ - status = cairo_matrix_invert (&transform); - if (unlikely (status)) { - g_warning ("Could not apply clip due to invalid matrix from " - "path transformation"); - goto BAIL; - } - - x1 = extents.x; - y1 = extents.y; - x2 = extents.x + extents.width; - y2 = extents.y + extents.height; - _cairo_matrix_transform_bounding_box (&transform, - &x1, &y1, &x2, &y2, - NULL); - - cogl_framebuffer_push_primitive_clip (surface->framebuffer, prim, - x1, y1, x2, y2); - (*clip_stack_depth)++; - - cogl_framebuffer_pop_matrix (surface->framebuffer); - -BAIL: - if (prim) - cogl_object_unref (prim); -} - -/* This is the way in which we handle CAIRO_EXTEND_NONE set on the - * source or mask pattern surfaces, as well as unbounded operators. - * First, we limit the rendering area to the region which will not be - * sampled from beyond the source or mask textures with additional clip - * paths, which were created when we obtained the original pipeline. - * The region will also be limited by the drawing area due to the fact - * we are drawing with the original primitive's vertices. - * - * In order to handle unbounded operators, we do a second rendering pass - * for places outside of such region. We limit the rending to outside - * this region by using a depth buffer to preserve all places where - * rendering took place during the first pass. For this region, we also - * have to remove the CAIRO_EXTEND_NONE clips if the operator is not - * bound by their respective contents. Because OpenGL sets all vertex - * z-values to 0.0 if none are supplied in the attributes data (we only - * supply x and y values), it will update the region in the buffer to a - * value over the default clearing value of 1.0. Given that the default - * test function is GL_LESS, we don't have to set z attributes on the - * vertices of the second rendering pass either, as 0.0 will never be - * less than 0.0. If cogl ever adds a method to clip out a primitive - * instead of just clipping it in, we may be able to use a more - * efficient method using the stencil buffer. */ -static void -_cairo_cogl_apply_tex_clips (cairo_cogl_surface_t *surface, - int *clip_stack_depth, - cairo_cogl_pipeline_t *pipeline) -{ - CoglDepthState depth_state; - CoglBool cogl_status; - - /* Enable the depth test if it will be needed */ - if ((!pipeline->mask_bounded && pipeline->has_mask_tex_clip) || - (!pipeline->src_bounded && pipeline->has_src_tex_clip)) - { - cogl_depth_state_init (&depth_state); - cogl_depth_state_set_test_enabled (&depth_state, TRUE); - cogl_status = cogl_pipeline_set_depth_state (pipeline->pipeline, - &depth_state, - NULL); - if (unlikely (cogl_status != TRUE)) - g_warning ("Error setting depth state for unbounded render"); - - /* Clear the depth buffer to 1.0. The color values are unused - * placeholders. */ - cogl_framebuffer_clear4f (surface->framebuffer, - COGL_BUFFER_BIT_DEPTH, - 0.0, 0.0, 0.0, 0.0); - } - - if (pipeline->mask_bounded && !pipeline->src_bounded) { - /* Push mask clip first so later we can pop the source clip - * and still be bound by the mask clip */ - if (pipeline->has_mask_tex_clip) - _cairo_cogl_set_path_prim_clip (surface, - &pipeline->mask_tex_clip, - clip_stack_depth, - CAIRO_FILL_RULE_WINDING, - 0.0); - if (pipeline->has_src_tex_clip) - _cairo_cogl_set_path_prim_clip (surface, - &pipeline->src_tex_clip, - clip_stack_depth, - CAIRO_FILL_RULE_WINDING, - 0.0); - } else { - if (pipeline->has_src_tex_clip) - _cairo_cogl_set_path_prim_clip (surface, - &pipeline->src_tex_clip, - clip_stack_depth, - CAIRO_FILL_RULE_WINDING, - 0.0); - if (pipeline->has_mask_tex_clip) - _cairo_cogl_set_path_prim_clip (surface, - &pipeline->mask_tex_clip, - clip_stack_depth, - CAIRO_FILL_RULE_WINDING, - 0.0); - } -} - -/* Get the pipeline for the second pass */ -static CoglPipeline * -_cairo_cogl_setup_unbounded_area_pipeline (cairo_cogl_surface_t *surface, - cairo_operator_t op) -{ - CoglPipeline *unbounded_pipeline; - CoglDepthState depth_state; - CoglBool cogl_status; - cairo_cogl_device_t *dev = to_device(surface->base.device); - - /* If a template pipeline exists for any given operator, the - * corresponding solid template pipeline always exists */ - unbounded_pipeline = - cogl_pipeline_copy (dev->template_pipelines[op][CAIRO_COGL_TEMPLATE_TYPE_SOLID]); - cogl_pipeline_set_color4f (unbounded_pipeline, 0.0, 0.0, 0.0, 0.0); - - /* Enable depth test on second-pass pipeline */ - cogl_depth_state_init (&depth_state); - cogl_depth_state_set_test_enabled (&depth_state, TRUE); - cogl_status = cogl_pipeline_set_depth_state (unbounded_pipeline, - &depth_state, - NULL); - if (unlikely (cogl_status != TRUE)) - g_warning ("Error setting depth state for unbounded render"); - - return unbounded_pipeline; -} - -static void -_cairo_cogl_unbounded_render (cairo_cogl_surface_t *surface, - int *clip_stack_depth, - cairo_cogl_pipeline_t *pipeline, - cairo_bool_t *needs_vertex_render) -{ - /* We will need a second rendering of the original vertices if we - * still need to be bounded by the mask but had a source tex clip */ - *needs_vertex_render = FALSE; - - /* Pop all unbounded tex clips. Do not pop clips the operator is - * bounded by, so that we can still be bounded by them during the - * second pass (vertex render or extents render). */ - if (pipeline->mask_bounded && pipeline->src_bounded) { - /* We don't need a second pass if it will just be in the same - * region as the first */ - } else if (pipeline->src_bounded) { - if (pipeline->has_mask_tex_clip) { - cogl_framebuffer_pop_clip (surface->framebuffer); - (*clip_stack_depth)--; - } - } else if (pipeline->mask_bounded) { - if (pipeline->has_src_tex_clip) { - cogl_framebuffer_pop_clip (surface->framebuffer); - (*clip_stack_depth)--; - *needs_vertex_render = TRUE; - } - } else { - if (pipeline->has_src_tex_clip) { - cogl_framebuffer_pop_clip (surface->framebuffer); - (*clip_stack_depth)--; - } - if (pipeline->has_mask_tex_clip) { - cogl_framebuffer_pop_clip (surface->framebuffer); - (*clip_stack_depth)--; - } - } - - /* If an operator is unbounded by the mask, we need to render the - * second transparent pass within the full unbounded extents */ - if (!pipeline->mask_bounded) { - CoglPipeline *unbounded_pipeline; - - /* Draw a transparent rectangle to cover the entire extents */ - unbounded_pipeline = - _cairo_cogl_setup_unbounded_area_pipeline (surface, - pipeline->op); - cogl_framebuffer_draw_rectangle (surface->framebuffer, - unbounded_pipeline, - pipeline->unbounded_extents.x, - pipeline->unbounded_extents.y, - pipeline->unbounded_extents.x + pipeline->unbounded_extents.width, - pipeline->unbounded_extents.y + pipeline->unbounded_extents.height); - cogl_object_unref (unbounded_pipeline); - } -} - -static void -_cairo_cogl_post_unbounded_render (cairo_cogl_surface_t *surface, - int *clip_stack_depth, - cairo_cogl_pipeline_t *pipeline) -{ - CoglDepthState depth_state; - CoglBool cogl_status; - - /* Disable the depth test */ - if ((!pipeline->mask_bounded && pipeline->has_mask_tex_clip) || - (!pipeline->src_bounded && pipeline->has_src_tex_clip)) - { - cogl_depth_state_init (&depth_state); - cogl_depth_state_set_test_enabled (&depth_state, FALSE); - cogl_status = cogl_pipeline_set_depth_state (pipeline->pipeline, - &depth_state, - NULL); - if (unlikely (cogl_status != TRUE)) - g_warning ("Error setting depth state after unbounded render"); - } - - /* Pop all bounded tex clips (those that were not popped before) */ - if (pipeline->src_bounded && pipeline->mask_bounded) { - if (pipeline->has_src_tex_clip) { - cogl_framebuffer_pop_clip (surface->framebuffer); - (*clip_stack_depth)--; - } - if (pipeline->has_mask_tex_clip) { - cogl_framebuffer_pop_clip (surface->framebuffer); - (*clip_stack_depth)--; - } - } else if (pipeline->src_bounded) { - if (pipeline->has_src_tex_clip) { - cogl_framebuffer_pop_clip (surface->framebuffer); - (*clip_stack_depth)--; - } - } else if (pipeline->mask_bounded) { - if (pipeline->has_mask_tex_clip) { - cogl_framebuffer_pop_clip (surface->framebuffer); - (*clip_stack_depth)--; - } - } else { - /* We have already popped all of the clips in the - * unbounded_render function */ - } -} - -static void -_cairo_cogl_journal_flush (cairo_cogl_surface_t *surface) -{ - GList *l; - cairo_cogl_device_t *dev; - int clip_stack_depth = 0; - int i; - - if (!surface->journal) - return; - - dev = to_device(surface->base.device); - if (dev->buffer_stack && dev->buffer_stack_offset) { - cogl_buffer_unmap (dev->buffer_stack); - cogl_object_unref (dev->buffer_stack); - dev->buffer_stack = NULL; - } - - if (unlikely (_cairo_cogl_surface_ensure_framebuffer (surface))) { - g_warning ("Could not get framebuffer for flushing journal"); - assert (0); - } - - cogl_framebuffer_push_matrix (surface->framebuffer); - - for (l = surface->journal->head; l; l = l->next) { - cairo_cogl_journal_entry_t *entry = l->data; - - switch (entry->type) - { - case CAIRO_COGL_JOURNAL_ENTRY_TYPE_CLIP: { - cairo_cogl_journal_clip_entry_t *clip_entry = - (cairo_cogl_journal_clip_entry_t *)entry; - cairo_clip_path_t *path; - - for (i = 0; i < clip_stack_depth; i++) - cogl_framebuffer_pop_clip (surface->framebuffer); - clip_stack_depth = 0; - - if (clip_entry->clip == NULL) - continue; // there is no clip - - for (path = clip_entry->clip->path, i = 0; - path; - path = path->prev, i++) - { - _cairo_cogl_set_path_prim_clip (surface, - &path->path, - &clip_stack_depth, - path->fill_rule, - path->tolerance); - } - - if (clip_entry->clip->num_boxes > 0) { - cairo_path_fixed_t boxes_path; - - _cairo_path_fixed_init (&boxes_path); - for (int i = 0; i < clip_entry->clip->num_boxes; i++) { - if (unlikely (_cairo_path_fixed_add_box (&boxes_path, - &clip_entry->clip->boxes[i]))) - { - g_warning ("Could not add all clip boxes while " - "flushing journal"); - break; - } - } - - _cairo_cogl_set_path_prim_clip (surface, - &boxes_path, - &clip_stack_depth, - CAIRO_FILL_RULE_WINDING, - 0.0); - - _cairo_path_fixed_fini (&boxes_path); - } - - surface->n_clip_updates_per_frame++; - break; - } - case CAIRO_COGL_JOURNAL_ENTRY_TYPE_RECTANGLE: { - cairo_cogl_journal_rect_entry_t *rect_entry = - (cairo_cogl_journal_rect_entry_t *)entry; - float tex_coords[8]; - float x1 = rect_entry->x; - float y1 = rect_entry->y; - float x2 = rect_entry->x + rect_entry->width; - float y2 = rect_entry->y + rect_entry->height; - cairo_matrix_t *ctm = &rect_entry->ctm; - float ctmfv[16] = { - ctm->xx, ctm->yx, 0, 0, - ctm->xy, ctm->yy, 0, 0, - 0, 0, 1, 0, - ctm->x0, ctm->y0, 0, 1 - }; - CoglMatrix transform; - cairo_bool_t needs_vertex_render; - CoglPipeline *unbounded_pipeline; - - cogl_matrix_init_from_array (&transform, ctmfv); - - _cairo_cogl_apply_tex_clips (surface, - &clip_stack_depth, - rect_entry->pipeline); - - if (rect_entry->pipeline->n_layers) { - g_assert (rect_entry->pipeline->n_layers <= 2); - tex_coords[0] = x1; - tex_coords[1] = y1; - tex_coords[2] = x2; - tex_coords[3] = y2; - if (rect_entry->pipeline->n_layers > 1) - memcpy (&tex_coords[4], tex_coords, sizeof (float) * 4); - } - - cogl_framebuffer_push_matrix (surface->framebuffer); - cogl_framebuffer_transform (surface->framebuffer, &transform); - cogl_framebuffer_draw_multitextured_rectangle (surface->framebuffer, - rect_entry->pipeline->pipeline, - x1, y1, - x2, y2, - tex_coords, - 4 * rect_entry->pipeline->n_layers); - - _cairo_cogl_unbounded_render (surface, - &clip_stack_depth, - rect_entry->pipeline, - &needs_vertex_render); - if (needs_vertex_render) { - unbounded_pipeline = - _cairo_cogl_setup_unbounded_area_pipeline (surface, - rect_entry->pipeline->op); - cogl_framebuffer_draw_multitextured_rectangle (surface->framebuffer, - unbounded_pipeline, - x1, y1, - x2, y2, - tex_coords, - 4 * rect_entry->pipeline->n_layers); - cogl_object_unref (unbounded_pipeline); - } - _cairo_cogl_post_unbounded_render (surface, - &clip_stack_depth, - rect_entry->pipeline); - - cogl_framebuffer_pop_matrix (surface->framebuffer); - break; - } - case CAIRO_COGL_JOURNAL_ENTRY_TYPE_PRIMITIVE: { - cairo_cogl_journal_prim_entry_t *prim_entry = - (cairo_cogl_journal_prim_entry_t *)entry; - CoglMatrix transform; - cairo_bool_t needs_vertex_render; - CoglPipeline *unbounded_pipeline; - - _cairo_cogl_apply_tex_clips (surface, - &clip_stack_depth, - prim_entry->pipeline); - - cogl_framebuffer_push_matrix (surface->framebuffer); - cairo_matrix_t *ctm = &prim_entry->transform; - float ctmfv[16] = { - ctm->xx, ctm->yx, 0, 0, - ctm->xy, ctm->yy, 0, 0, - 0, 0, 1, 0, - ctm->x0, ctm->y0, 0, 1 - }; - cogl_matrix_init_from_array (&transform, ctmfv); - cogl_framebuffer_transform (surface->framebuffer, &transform); - - /* If the primitive is NULL, it means we just draw the - * unbounded rectangle */ - if (prim_entry->primitive) - cogl_primitive_draw (prim_entry->primitive, - surface->framebuffer, - prim_entry->pipeline->pipeline); - - _cairo_cogl_unbounded_render (surface, - &clip_stack_depth, - prim_entry->pipeline, - &needs_vertex_render); - if (needs_vertex_render && prim_entry->primitive) { - unbounded_pipeline = - _cairo_cogl_setup_unbounded_area_pipeline (surface, - prim_entry->pipeline->op); - cogl_primitive_draw (prim_entry->primitive, - surface->framebuffer, - unbounded_pipeline); - cogl_object_unref (unbounded_pipeline); - } - _cairo_cogl_post_unbounded_render (surface, - &clip_stack_depth, - prim_entry->pipeline); - - cogl_framebuffer_pop_matrix (surface->framebuffer); - break; - } - default: - assert (0); /* not reached! */ - } - } - - cogl_framebuffer_pop_matrix (surface->framebuffer); - - for (i = 0; i < clip_stack_depth; i++) - cogl_framebuffer_pop_clip (surface->framebuffer); - - _cairo_cogl_journal_discard (surface); -} - -static cairo_status_t -_cairo_cogl_surface_flush (void *abstract_surface, - unsigned flags) -{ - cairo_cogl_surface_t *surface = (cairo_cogl_surface_t *)abstract_surface; - - if (flags) - return CAIRO_STATUS_SUCCESS; - - _cairo_cogl_journal_flush (surface); - - return CAIRO_STATUS_SUCCESS; -} - -static cairo_status_t -_cairo_cogl_surface_finish (void *abstract_surface) -{ - cairo_cogl_surface_t *surface = abstract_surface; - - if (surface->texture) - cogl_object_unref (surface->texture); - - if (surface->framebuffer) - cogl_object_unref (surface->framebuffer); - - if (surface->journal) - _cairo_cogl_journal_free (surface); - - /*XXX wtf */ - cairo_device_release (surface->base.device); - - return CAIRO_STATUS_SUCCESS; -} - -static CoglTextureComponents -get_components_from_cairo_content (cairo_content_t content) -{ - /* We use RGBA for color-only surfaces due to the fact that cogl - * does not provide a padded XRGB format, thereby making us use - * RGBA formats to represent e.g. CAIRO_FORMAT_RGB24 and doing very - * expensive format conversions on the cpu when images are read - * back */ - return (content & CAIRO_CONTENT_COLOR) ? - COGL_TEXTURE_COMPONENTS_RGBA : - COGL_TEXTURE_COMPONENTS_A; -} - -static CoglPixelFormat -get_default_cogl_format_from_components (CoglTextureComponents components) -{ - switch (components) - { - case COGL_TEXTURE_COMPONENTS_A: - return COGL_PIXEL_FORMAT_A_8; - case COGL_TEXTURE_COMPONENTS_RG: - return COGL_PIXEL_FORMAT_RG_88; - case COGL_TEXTURE_COMPONENTS_RGB: - case COGL_TEXTURE_COMPONENTS_RGBA: -#if G_BYTE_ORDER == G_LITTLE_ENDIAN - return COGL_PIXEL_FORMAT_BGRA_8888_PRE; -#else - return COGL_PIXEL_FORMAT_ARGB_8888_PRE; -#endif - case COGL_TEXTURE_COMPONENTS_DEPTH: - return COGL_PIXEL_FORMAT_DEPTH_32; - default: - return 0; - } -} - -static CoglTextureComponents -get_components_from_cairo_format (cairo_format_t format) -{ - switch (format) - { - case CAIRO_FORMAT_A1: - case CAIRO_FORMAT_A8: - return COGL_TEXTURE_COMPONENTS_A; - - case CAIRO_FORMAT_RGB16_565: - case CAIRO_FORMAT_RGB24: - case CAIRO_FORMAT_RGB30: - case CAIRO_FORMAT_RGB96F: - return COGL_TEXTURE_COMPONENTS_RGB; - - case CAIRO_FORMAT_ARGB32: - case CAIRO_FORMAT_RGBA128F: - return COGL_TEXTURE_COMPONENTS_RGBA; - - case CAIRO_FORMAT_INVALID: - default: - g_warning("Cairo format unrepresentable by cogl"); - return 0; - } -} - -static CoglPixelFormat -get_cogl_format_from_cairo_format (cairo_format_t cairo_format); - -/* XXX: We often use RGBA format for onscreen framebuffers so make sure - * to handle CAIRO_FORMAT_INVALID sensibly */ -static cairo_format_t -get_cairo_format_from_cogl_format (CoglPixelFormat format) -{ - switch ((int)format) - { - case COGL_PIXEL_FORMAT_A_8: - return CAIRO_FORMAT_A8; - case COGL_PIXEL_FORMAT_RGB_565: - return CAIRO_FORMAT_RGB16_565; - case COGL_PIXEL_FORMAT_RG_88: - g_warning ("cairo cannot handle red-green textures"); - return CAIRO_FORMAT_INVALID; - case COGL_PIXEL_FORMAT_DEPTH_32: - g_warning ("cairo cannot handle depth textures"); - return CAIRO_FORMAT_INVALID; - - case COGL_PIXEL_FORMAT_BGRA_8888_PRE: - case COGL_PIXEL_FORMAT_ARGB_8888_PRE: - case COGL_PIXEL_FORMAT_RGBA_8888_PRE: - /* Note: this is ambiguous since CAIRO_FORMAT_RGB24 - * would also map to the same CoglPixelFormat */ - return CAIRO_FORMAT_ARGB32; - - default: - g_warning("bad format: %x a? %d, bgr? %d, pre %d, format: %d", - format, - format & COGL_A_BIT, - format & COGL_BGR_BIT, - format & COGL_PREMULT_BIT, - format & ~(COGL_A_BIT | COGL_BGR_BIT | COGL_PREMULT_BIT)); - return CAIRO_FORMAT_INVALID; - } -} - -static CoglPixelFormat -get_cogl_format_from_cairo_format (cairo_format_t cairo_format) -{ - switch (cairo_format) - { - case CAIRO_FORMAT_ARGB32: - case CAIRO_FORMAT_RGB24: -#if G_BYTE_ORDER == G_LITTLE_ENDIAN - return COGL_PIXEL_FORMAT_BGRA_8888_PRE; -#else - return COGL_PIXEL_FORMAT_ARGB_8888_PRE; -#endif - case CAIRO_FORMAT_A8: - return COGL_PIXEL_FORMAT_A_8; - case CAIRO_FORMAT_RGB16_565: - return COGL_PIXEL_FORMAT_RGB_565; - case CAIRO_FORMAT_INVALID: - case CAIRO_FORMAT_A1: - case CAIRO_FORMAT_RGB30: - case CAIRO_FORMAT_RGB96F: - case CAIRO_FORMAT_RGBA128F: - return 0; - } - - g_warn_if_reached (); - return 0; -} - -static cairo_surface_t * -_cairo_cogl_surface_create_similar (void *abstract_surface, - cairo_content_t content, - int width, - int height) -{ - cairo_cogl_surface_t *reference_surface = abstract_surface; - cairo_cogl_surface_t *surface; - CoglTexture *texture; - cairo_status_t status; - cairo_cogl_device_t *dev = - to_device(reference_surface->base.device); - int tex_width = width; - int tex_height = height; - - /* In the case of lack of NPOT texture support, we allocate texture - * with dimensions of the next power of two */ - if (!dev->has_npots) { - tex_width = pow (2, ceil (log2 (tex_width))); - tex_height = pow (2, ceil (log2 (tex_height))); - } - - texture = cogl_texture_2d_new_with_size (dev->cogl_context, - tex_width, tex_height); - if (!texture) - return _cairo_surface_create_in_error (_cairo_error (CAIRO_STATUS_NO_MEMORY)); - - cogl_texture_set_components (texture, - get_components_from_cairo_content (content)); - - surface = (cairo_cogl_surface_t *) - _cairo_cogl_surface_create_full (dev, content, NULL, texture); - if (unlikely (surface->base.status)) - return &surface->base; - - /* The surface will take a reference on the texture */ - cogl_object_unref (texture); - - /* If we passed a texture with larger dimensions, we need to set - * the surface dimensions */ - surface->width = width; - surface->height = height; - - status = _cairo_cogl_surface_ensure_framebuffer (surface); - if (unlikely (status)) { - cairo_surface_destroy (&surface->base); - return _cairo_surface_create_in_error (status); - } - - return &surface->base; -} - -static cairo_status_t -_cairo_cogl_surface_read_rect_to_image_surface (cairo_cogl_surface_t *surface, - cairo_rectangle_int_t *interest, - cairo_image_surface_t **image_out) -{ - cairo_image_surface_t *image; - cairo_status_t status; - cairo_format_t cairo_format; - CoglPixelFormat cogl_format; - - status = _cairo_cogl_surface_ensure_framebuffer (surface); - if (unlikely (status)) - return status; - - if (surface->texture) - { - cogl_format = - get_default_cogl_format_from_components ( - cogl_texture_get_components (surface->texture) ); - cairo_format = get_cairo_format_from_cogl_format (cogl_format); - } else { - cairo_format = - _cairo_format_from_content (surface->base.content); - cogl_format = get_cogl_format_from_cairo_format (cairo_format); - } - - image = (cairo_image_surface_t *) - cairo_image_surface_create (cairo_format, - surface->width, - surface->height); - if (image->base.status) - return image->base.status; - - cogl_framebuffer_read_pixels (surface->framebuffer, 0, 0, - surface->width, surface->height, - cogl_format, image->data); - - *image_out = image; - - return CAIRO_STATUS_SUCCESS; -} - -static cairo_status_t -_cairo_cogl_surface_acquire_source_image (void *abstract_surface, - cairo_image_surface_t **image_out, - void **image_extra) -{ - cairo_cogl_surface_t *surface = abstract_surface; - cairo_status_t status; - - if (unlikely (_cairo_surface_flush (abstract_surface, 0))) - g_warning ("Error flushing journal while acquiring image"); - - if (surface->texture) { - CoglTextureComponents components = - cogl_texture_get_components(surface->texture); - CoglPixelFormat cogl_format = - get_default_cogl_format_from_components (components); - cairo_format_t cairo_format = - get_cairo_format_from_cogl_format (cogl_format); - if (cairo_format == CAIRO_FORMAT_INVALID) { - cairo_format = CAIRO_FORMAT_ARGB32; - cogl_format = - get_cogl_format_from_cairo_format (cairo_format); - } - - /* We use the actual texture dimensions here instead, because - * if we have a larger texture than the surface dimensions for - * devices not supporting NPOT textures, the surface dimensions - * will not be able to fit the data */ - cairo_image_surface_t *image = (cairo_image_surface_t *) - cairo_image_surface_create (cairo_format, - cogl_texture_get_width (surface->texture), - cogl_texture_get_height (surface->texture)); - if (image->base.status) - return image->base.status; - - cogl_texture_get_data (surface->texture, - cogl_format, - 0, - image->data); - - /* If the texture dimensions were different than the surface - * dimensions, this will set them to the correct values. - * Because the stride stays the same, it will still function - * correctly */ - image->width = surface->width; - image->height = surface->height; - - image->base.is_clear = FALSE; - *image_out = image; - } else { - cairo_rectangle_int_t extents = { - 0, 0, surface->width, surface->height - }; - status = _cairo_cogl_surface_read_rect_to_image_surface (surface, &extents, - image_out); - if (unlikely (status)) - return status; - } - - *image_extra = NULL; - - return CAIRO_STATUS_SUCCESS; -} - -static void -_cairo_cogl_surface_release_source_image (void *abstract_surface, - cairo_image_surface_t *image, - void *image_extra) -{ - cairo_surface_destroy (&image->base); -} - -static cairo_status_t -_cairo_cogl_surface_clear (cairo_cogl_surface_t *surface, - const cairo_color_t *color) -{ - /* Anything batched in the journal up until now is redundant... */ - _cairo_cogl_journal_discard (surface); - - /* XXX: we currently implicitly clear the depth and stencil buffer here - * but since we use the framebuffer_discard extension when available I - * suppose this doesn't matter too much. - * - * The main concern is that we want to avoid re-loading an external z - * buffer at the start of each frame, but also many gpu architectures have - * optimizations for how they handle the depth/stencil buffers and can get - * upset if they aren't cleared together at the start of the frame. - * - * FIXME: we need a way to assert that the clip stack currently isn't - * using the stencil buffer before clearing it here! - */ - cogl_framebuffer_clear4f (surface->framebuffer, - COGL_BUFFER_BIT_COLOR | - COGL_BUFFER_BIT_DEPTH | - COGL_BUFFER_BIT_STENCIL, - color->red * color->alpha, - color->green * color->alpha, - color->blue * color->alpha, - color->alpha); - return CAIRO_STATUS_SUCCESS; -} - -cairo_status_t -_cairo_cogl_path_fixed_rectangle (cairo_path_fixed_t *path, - cairo_fixed_t x, - cairo_fixed_t y, - cairo_fixed_t width, - cairo_fixed_t height) -{ - cairo_status_t status; - - status = _cairo_path_fixed_move_to (path, x, y); - if (unlikely (status)) - return status; - - status = _cairo_path_fixed_rel_line_to (path, width, 0); - if (unlikely (status)) - return status; - - status = _cairo_path_fixed_rel_line_to (path, 0, height); - if (unlikely (status)) - return status; - - status = _cairo_path_fixed_rel_line_to (path, -width, 0); - if (unlikely (status)) - return status; - - status = _cairo_path_fixed_close_path (path); - if (unlikely (status)) - return status; - - return CAIRO_STATUS_SUCCESS; -} - - -static CoglPipelineWrapMode -get_cogl_wrap_mode_for_extend (cairo_extend_t extend_mode, - cairo_cogl_device_t *dev) -{ - switch (extend_mode) - { - case CAIRO_EXTEND_NONE: - return COGL_PIPELINE_WRAP_MODE_CLAMP_TO_EDGE; - case CAIRO_EXTEND_PAD: - return COGL_PIPELINE_WRAP_MODE_CLAMP_TO_EDGE; - case CAIRO_EXTEND_REPEAT: - return COGL_PIPELINE_WRAP_MODE_REPEAT; - case CAIRO_EXTEND_REFLECT: - if (!dev->has_mirrored_repeat) - /* If the hardware cannot support mirrored repeating, we - * emulate it elsewhere */ - return COGL_PIPELINE_WRAP_MODE_REPEAT; - else - return COGL_PIPELINE_WRAP_MODE_MIRRORED_REPEAT; - } - assert (0); /* not reached */ - return COGL_PIPELINE_WRAP_MODE_CLAMP_TO_EDGE; -} - -static CoglPipelineFilter -get_cogl_filter_for_filter (cairo_filter_t filter) -{ - switch (filter) - { - case CAIRO_FILTER_FAST: - case CAIRO_FILTER_NEAREST: - return COGL_PIPELINE_FILTER_NEAREST; - - case CAIRO_FILTER_GOOD: - case CAIRO_FILTER_BEST: - case CAIRO_FILTER_BILINEAR: - return COGL_PIPELINE_FILTER_LINEAR; - - case CAIRO_FILTER_GAUSSIAN: - default: - g_warning("Invalid pattern filter"); - return COGL_PIPELINE_FILTER_NEAREST; - } -} - -static void -_cairo_cogl_matrix_all_scale (cairo_matrix_t *matrix, - double xscale, - double yscale) -{ - /* Since cairo_matrix_scale does not scale the x0 and y0 components, - * which is required for scaling translations to normalized - * coordinates, use a custom solution here. */ - matrix->xx *= xscale; - matrix->yx *= yscale; - matrix->xy *= xscale; - matrix->yy *= yscale; - matrix->x0 *= xscale; - matrix->y0 *= yscale; -} - -static CoglTexture * -_cairo_cogl_scale_texture (CoglContext *context, - CoglTexture *texture_in, - unsigned int new_width, - unsigned int new_height, - cairo_bool_t do_mirror_texture, - cairo_bool_t always_new_texture) -{ - CoglTexture *texture_out = NULL; - CoglPipeline *copying_pipeline = NULL; - CoglFramebuffer *fb = NULL; - CoglError *error = NULL; - unsigned int tex_width = new_width; - unsigned int tex_height = new_height; - - /* If the texture is already in the desired dimensions and we are - * not mirroring it, copying it, or reading from different extents, - * return it unmodified */ - if (!do_mirror_texture && !always_new_texture && - new_width == cogl_texture_get_width (texture_in) && - new_height == cogl_texture_get_height (texture_in)) - return texture_in; - - if (do_mirror_texture) { - tex_width *= 2; - tex_height *= 2; - } - - texture_out = - cogl_texture_2d_new_with_size (context, tex_width, tex_height); - if (unlikely (!texture_out)) { - g_warning ("Failed to get texture for scaling"); - goto BAIL; - } - - cogl_texture_set_components (texture_out, - cogl_texture_get_components (texture_in)); - - fb = cogl_offscreen_new_with_texture (texture_out); - if (unlikely (!cogl_framebuffer_allocate (fb, &error))) { - g_warning ("Could not get framebuffer for texture scaling: %s", - error->message); - cogl_error_free (error); - goto BAIL; - } - - cogl_framebuffer_orthographic (fb, 0, 0, - tex_width, tex_height, - -1, 100); - - copying_pipeline = cogl_pipeline_new (context); - cogl_pipeline_set_layer_texture (copying_pipeline, 0, texture_in); - cogl_pipeline_set_layer_filters (copying_pipeline, 0, - COGL_PIPELINE_FILTER_NEAREST, - COGL_PIPELINE_FILTER_NEAREST); - - if (do_mirror_texture) { - /* Draw four rectangles to the new texture with the appropriate - * reflection on each one */ - - const float rect_coordinates[32] = { - /* Rectangle 1 */ - 0, 0, 0.5 * tex_width, 0.5 * tex_height, - 0, 0, 1, 1, - - /* Rectangle 2 */ - tex_width, 0, 0.5 * tex_width, 0.5 * tex_height, - 0, 0, 1, 1, - - /* Rectangle 3 */ - 0, tex_height, 0.5 * tex_width, 0.5 * tex_height, - 0, 0, 1, 1, - - /* Rectangle 4 */ - tex_width, tex_height, 0.5 * tex_width, 0.5 * tex_height, - 0, 0, 1, 1 - }; - - cogl_framebuffer_draw_textured_rectangles (fb, - copying_pipeline, - rect_coordinates, - 4); - } else { - cogl_framebuffer_draw_textured_rectangle (fb, - copying_pipeline, - 0, 0, - tex_width, - tex_height, - 0, 0, 1, 1); - } - - cogl_object_unref (fb); - cogl_object_unref (copying_pipeline); - cogl_object_unref (texture_in); - - return texture_out; - -BAIL: - if (texture_out) - cogl_object_unref (texture_out); - if (fb) - cogl_object_unref (fb); - if (copying_pipeline) - cogl_object_unref (copying_pipeline); - - return NULL; -} - -/* NB: a reference for the texture is transferred to the caller which - * should be unrefed */ -static CoglTexture * -_cairo_cogl_acquire_cogl_surface_texture (cairo_cogl_surface_t *reference_surface, - cairo_surface_t *surface, - const cairo_rectangle_int_t *surface_extents, - const cairo_matrix_t *pattern_matrix, - cairo_matrix_t *out_matrix, - const cairo_bool_t need_mirrored_texture, - cairo_bool_t *is_mirrored_texture) -{ - CoglTexture *texture; - cairo_surface_t *clone = NULL; - cairo_cogl_surface_t *cogl_surface = - (cairo_cogl_surface_t *)surface; - cairo_bool_t do_mirror_texture; - cairo_cogl_device_t *dev = - to_device (reference_surface->base.device); - double xscale, yscale; - int new_width = surface_extents->width; - int new_height = surface_extents->height; - - if (surface_extents->x < 0 || surface_extents->y < 0 || - (surface_extents->x + surface_extents->width) > - cogl_surface->width || - (surface_extents->y + surface_extents->height) > - cogl_surface->height) - return NULL; - - *out_matrix = *pattern_matrix; - *is_mirrored_texture = FALSE; - - if (unlikely (_cairo_surface_flush (surface, 0))) { - g_warning ("Error flushing source surface while getting " - "pattern texture"); - goto BAIL; - } - - *is_mirrored_texture = - need_mirrored_texture || cogl_surface->is_mirrored_snapshot; - do_mirror_texture = - need_mirrored_texture && !cogl_surface->is_mirrored_snapshot; - - /* There seems to be a bug in which cogl isn't flushing its own - * internal journal when reading from dependent sub-textures. - * If this is ever fixed, the following block of code can be - * removed. */ - { - _cairo_cogl_surface_ensure_framebuffer (cogl_surface); - cogl_framebuffer_finish (cogl_surface->framebuffer); - } - /* We copy the surface to a new texture, thereby making a - * snapshot of it, as its contents may change between the time - * we log the pipeline and when we flush the journal. The sub - * texture itself cannot be used while drawing primitives, so we do - * a copy to a 2d texture. */ - texture = cogl_sub_texture_new (dev->cogl_context, - cogl_surface->texture, - surface_extents->x, - surface_extents->y, - surface_extents->width, - surface_extents->height); - if (unlikely (!texture)) - goto BAIL; - - /* If we do not support NPOT dimensions, scale the new texture to - * the next power of two while copying */ - if (!dev->has_npots) { - new_width = (int)pow (2, ceil (log2 (new_width))); - new_height = (int)pow (2, ceil (log2 (new_height))); - } - texture = _cairo_cogl_scale_texture (dev->cogl_context, - texture, - new_width, - new_height, - do_mirror_texture, - TRUE); - if (unlikely (!texture)) - goto BAIL; - - clone = - _cairo_cogl_surface_create_full (dev, - reference_surface->base.content, - NULL, - texture); - if (unlikely (clone->status)) { - g_warning ("Could not get clone surface for texture"); - goto BAIL; - } - _cairo_surface_attach_snapshot (surface, clone, NULL); - - /* Attaching the snapshot will take a reference on the clone surface... */ - cairo_surface_destroy (clone); - clone = NULL; - - /* Convert from un-normalized source coordinates in backend - * coordinates to normalized texture coordinates. */ - if (*is_mirrored_texture) { - xscale = 0.5 / surface_extents->width; - yscale = 0.5 / surface_extents->height; - } else { - xscale = 1.0 / surface_extents->width; - yscale = 1.0 / surface_extents->height; - } - _cairo_cogl_matrix_all_scale (out_matrix, xscale, yscale); - - return texture; - -BAIL: - if (texture) - cogl_object_unref (texture); - if (clone) - cairo_surface_destroy (clone); - - return NULL; -} - -/* NB: a reference for the texture is transferred to the caller which - * should be unrefed */ -static CoglTexture * -_cairo_cogl_acquire_recording_surface_texture (cairo_cogl_surface_t *reference_surface, - cairo_surface_t *surface, - const cairo_rectangle_int_t *extents, - const cairo_matrix_t *pattern_matrix, - cairo_matrix_t *out_matrix, - const cairo_bool_t need_mirrored_texture, - cairo_bool_t *is_mirrored_texture) -{ - CoglTexture *texture = NULL; - cairo_surface_t *clone = NULL; - cairo_cogl_device_t *dev = - to_device (reference_surface->base.device); - cairo_matrix_t transform; - int tex_height, tex_width; - double xscale, yscale; - - *is_mirrored_texture = FALSE; - - /* We will pre-transform all of the drawing by the pattern matrix - * and confine it to the required extents, so no later transform - * will be required */ - cairo_matrix_init_translate (out_matrix, -extents->x, -extents->y); - - cairo_matrix_init_translate (&transform, extents->x, extents->y); - cairo_matrix_multiply (&transform, &transform, pattern_matrix); - - if (!dev->has_npots) { - /* Record to a texture sized to the next power of two */ - tex_width = (int)pow (2, ceil (log2 (extents->width))); - tex_height = (int)pow (2, ceil (log2 (extents->height))); - - /* And scale accordingly */ - cairo_matrix_scale (&transform, - (double)extents->width / (double)tex_width, - (double)extents->height / (double)tex_height); - } else { - tex_width = extents->width; - tex_height = extents->height; - } - - texture = cogl_texture_2d_new_with_size (dev->cogl_context, - tex_width, - tex_height); - if (unlikely (!texture)) { - g_warning ("Failed to create texture for replaying recording " - "surface"); - goto BAIL; - } - - cogl_texture_set_components (texture, - get_components_from_cairo_content (surface->content)); - - /* Do not attach this as a snapshot, as it only represents part of - * the surface */ - clone = - _cairo_cogl_surface_create_full (dev, - reference_surface->base.content, - NULL, - texture); - if (unlikely (_cairo_cogl_surface_ensure_framebuffer ((cairo_cogl_surface_t *)clone))) - { - g_warning ("Could not get framebuffer for replaying recording " - "surface"); - goto BAIL; - } - - if (unlikely (_cairo_recording_surface_replay_with_clip (surface, - &transform, - clone, - NULL))) - { - g_warning ("Could not replay recording surface"); - goto BAIL; - } - _cairo_cogl_journal_flush ((cairo_cogl_surface_t *)clone); - cairo_surface_destroy (clone); - - if (need_mirrored_texture) { - /* Scale to the same image extents, but mirror the texture, - * thereby making it larger */ - texture = _cairo_cogl_scale_texture (dev->cogl_context, - texture, - tex_width, - tex_height, - TRUE, - FALSE); - if (unlikely (!texture)) - goto BAIL; - - *is_mirrored_texture = TRUE; - } - - /* Convert from un-normalized source coordinates in backend - * coordinates to normalized texture coordinates. */ - if (*is_mirrored_texture) { - xscale = 0.5 / extents->width; - yscale = 0.5 / extents->height; - } else { - xscale = 1.0 / extents->width; - yscale = 1.0 / extents->height; - } - _cairo_cogl_matrix_all_scale (out_matrix, xscale, yscale); - - return texture; - -BAIL: - if (clone) - cairo_surface_destroy (clone); - if (texture) - cogl_object_unref (texture); - - return NULL; -} - -/* NB: a reference for the texture is transferred to the caller which - * should be unrefed */ -static CoglTexture * -_cairo_cogl_acquire_generic_surface_texture (cairo_cogl_surface_t *reference_surface, - cairo_surface_t *surface, - const cairo_matrix_t *pattern_matrix, - cairo_matrix_t *out_matrix, - const cairo_bool_t need_mirrored_texture, - cairo_bool_t *is_mirrored_texture) -{ - CoglTexture *texture = NULL; - cairo_image_surface_t *image; - cairo_image_surface_t *acquired_image = NULL; - void *image_extra; - cairo_image_surface_t *image_clone = NULL; - CoglBitmap *bitmap; - CoglError *error = NULL; - cairo_surface_t *clone = NULL; - CoglPixelFormat format; - cairo_cogl_device_t *dev = - to_device (reference_surface->base.device); - ptrdiff_t stride; - unsigned char *data; - double xscale, yscale; - - *out_matrix = *pattern_matrix; - *is_mirrored_texture = FALSE; - - if (_cairo_surface_is_image (surface)) { - image = (cairo_image_surface_t *)surface; - } else { - cairo_status_t status = - _cairo_surface_acquire_source_image (surface, - &acquired_image, - &image_extra); - if (unlikely (status)) { - g_warning ("acquire_source_image failed: %s [%d]", - cairo_status_to_string (status), status); - return NULL; - } - image = acquired_image; - } - - format = get_cogl_format_from_cairo_format (image->format); - if (!format) { - image_clone = _cairo_image_surface_coerce (image); - if (unlikely (image_clone->base.status)) { - g_warning ("image_surface_coerce failed"); - texture = NULL; - goto BAIL; - } - - format = - get_cogl_format_from_cairo_format (image_clone->format); - assert (format); - - image = image_clone; - } - - if (image->stride < 0) { - /* If the stride is negative, this modifies the data pointer so - * that all of the pixels are read into the texture, but - * upside-down. We then invert the matrix so the texture is - * read from the bottom up instead of from the top down. */ - stride = -image->stride; - data = image->data - stride * (image->height - 1); - - out_matrix->yx *= -1.0; - out_matrix->yy *= -1.0; - out_matrix->y0 += image->height; - } else { - stride = image->stride; - data = image->data; - } - - bitmap = cogl_bitmap_new_for_data (dev->cogl_context, - image->width, - image->height, - format, /* incoming */ - stride, - data); - - if (!dev->has_npots) - texture = - cogl_texture_2d_sliced_new_from_bitmap (bitmap, - COGL_TEXTURE_MAX_WASTE); - else - texture = cogl_texture_2d_new_from_bitmap (bitmap); - - /* The texture will have taken a reference on the bitmap */ - cogl_object_unref (bitmap); - - cogl_texture_set_components (texture, - get_components_from_cairo_format (image->format)); - - if (unlikely (!cogl_texture_allocate (texture, &error))) { - g_warning ("Failed to allocate texture: %s", error->message); - cogl_error_free (error); - goto BAIL; - } - - if (need_mirrored_texture) { - int new_width = image->width; - int new_height = image->height; - - /* If the device does not support npot textures, scale to the - * next power of two as well */ - if (!dev->has_npots) { - new_width = (int)pow (2, ceil (log2 (new_width))); - new_height = (int)pow (2, ceil (log2 (new_height))); - } - - texture = _cairo_cogl_scale_texture (dev->cogl_context, - texture, - new_width, - new_height, - TRUE, - FALSE); - if (unlikely (!texture)) - goto BAIL; - - *is_mirrored_texture = TRUE; - } else if (!dev->has_npots) { - /* We need to scale the texture up if the hardware does not - * support npots */ - - /* Get dimensions for the next power of two */ - int new_width = (int)pow (2, ceil (log2 (image->width))); - int new_height = (int)pow (2, ceil (log2 (image->height))); - - texture = _cairo_cogl_scale_texture (dev->cogl_context, - texture, - new_width, - new_height, - FALSE, - FALSE); - if (unlikely (!texture)) - goto BAIL; - } - - clone = - _cairo_cogl_surface_create_full (dev, - reference_surface->base.content, - NULL, - texture); - if (unlikely (clone->status)) { - g_warning ("Unable to create clone surface for texture"); - goto BAIL; - } - - if (*is_mirrored_texture) - ((cairo_cogl_surface_t *)clone)->is_mirrored_snapshot = TRUE; - - if (_cairo_surface_is_subsurface (surface)) - _cairo_surface_subsurface_set_snapshot (surface, clone); - else - _cairo_surface_attach_snapshot (surface, clone, NULL); - - /* Attaching the snapshot will take a reference on the clone surface... */ - cairo_surface_destroy (clone); - clone = NULL; - - /* Convert from un-normalized source coordinates in backend - * coordinates to normalized texture coordinates. */ - if (*is_mirrored_texture) { - xscale = 0.5 / image->width; - yscale = 0.5 / image->height; - } else { - xscale = 1.0 / image->width; - yscale = 1.0 / image->height; - } - _cairo_cogl_matrix_all_scale (out_matrix, xscale, yscale); - - /* Release intermediate surface representations */ - if (image_clone) { - cairo_surface_destroy (&image_clone->base); - image_clone = NULL; - } - if (acquired_image) { - _cairo_surface_release_source_image (surface, - acquired_image, - image_extra); - acquired_image = NULL; - } - - return texture; - -BAIL: - if (clone) - cairo_surface_destroy (clone); - if (image_clone) - cairo_surface_destroy (&image_clone->base); - if (acquired_image) - _cairo_surface_release_source_image (surface, - acquired_image, - image_extra); - if (texture) - cogl_object_unref (texture); - - return NULL; -} - -static cairo_status_t -_cairo_cogl_create_tex_clip (cairo_path_fixed_t *tex_clip, - cairo_matrix_t inverse, - cairo_bool_t is_mirrored_texture) -{ - cairo_status_t status; - - status = cairo_matrix_invert (&inverse); - if (unlikely (status)) - return status; - - if (is_mirrored_texture) - status = - _cairo_cogl_path_fixed_rectangle (tex_clip, 0, 0, - _cairo_fixed_from_double (0.5), - _cairo_fixed_from_double (0.5)); - else - status = _cairo_cogl_path_fixed_rectangle (tex_clip, 0, 0, - CAIRO_FIXED_ONE, - CAIRO_FIXED_ONE); - if (unlikely (status)) - return status; - - _cairo_path_fixed_transform (tex_clip, &inverse); - - return CAIRO_STATUS_SUCCESS; -} - -/* NB: a reference for the texture is transferred to the caller which should - * be unrefed */ -static CoglTexture * -_cairo_cogl_acquire_pattern_texture (const cairo_pattern_t *pattern, - cairo_cogl_surface_t *destination, - const cairo_rectangle_int_t *extents, - cairo_cogl_texture_attributes_t *attributes, - cairo_path_fixed_t *tex_clip) -{ - CoglTexture *texture = NULL; - cairo_cogl_device_t *dev = to_device (destination->base.device); - cairo_bool_t is_mirrored_texture; - cairo_bool_t need_mirrored_texture = - (pattern->extend == CAIRO_EXTEND_REFLECT && - !dev->has_mirrored_repeat); - - switch ((int)pattern->type) - { - case CAIRO_PATTERN_TYPE_SURFACE: { - cairo_cogl_surface_t *clone; - cairo_surface_t *surface = ((cairo_surface_pattern_t *)pattern)->surface; - - clone = (cairo_cogl_surface_t *) - _cairo_surface_has_snapshot (surface, - &_cairo_cogl_surface_backend); - if (clone && clone->texture) - if ((!need_mirrored_texture) || clone->is_mirrored_snapshot) - { - texture = cogl_object_ref (clone->texture); - attributes->matrix = pattern->matrix; - is_mirrored_texture = clone->is_mirrored_snapshot; - - /* Convert from un-normalized source coordinates in - * backend coordinates to normalized texture - * coordinates. */ - _cairo_cogl_matrix_all_scale (&attributes->matrix, - 1.0 / clone->width, - 1.0 / clone->height); - }; - - if (!texture) { - cairo_rectangle_int_t surface_extents; - cairo_surface_t *unwrapped = - _cairo_surface_get_source (surface, &surface_extents); - - if (_cairo_surface_is_recording (surface)) { - texture = - _cairo_cogl_acquire_recording_surface_texture (destination, - surface, - extents, - &pattern->matrix, - &attributes->matrix, - need_mirrored_texture, - &is_mirrored_texture); - } else if (surface->type == CAIRO_SURFACE_TYPE_COGL && - ((cairo_cogl_surface_t *)unwrapped)->texture) { - texture = - _cairo_cogl_acquire_cogl_surface_texture (destination, - unwrapped, - &surface_extents, - &pattern->matrix, - &attributes->matrix, - need_mirrored_texture, - &is_mirrored_texture); - } - } - - if (!texture) - texture = - _cairo_cogl_acquire_generic_surface_texture (destination, - surface, - &pattern->matrix, - &attributes->matrix, - need_mirrored_texture, - &is_mirrored_texture); - - if (unlikely (!texture)) - return NULL; - - attributes->extend = pattern->extend; - attributes->filter = - get_cogl_filter_for_filter (pattern->filter); - attributes->has_component_alpha = pattern->has_component_alpha; - - attributes->s_wrap = - get_cogl_wrap_mode_for_extend (pattern->extend, dev); - attributes->t_wrap = attributes->s_wrap; - - /* In order to support CAIRO_EXTEND_NONE, we use the same wrap - * mode as CAIRO_EXTEND_PAD, but pass a clip to the drawing - * function to make sure that we never sample anything beyond - * the texture boundaries. */ - if (pattern->extend == CAIRO_EXTEND_NONE && tex_clip) - if (_cairo_cogl_create_tex_clip (tex_clip, - attributes->matrix, - is_mirrored_texture)) - { - cogl_object_unref (texture); - return NULL; - } - - return texture; - } - case CAIRO_PATTERN_TYPE_RADIAL: - case CAIRO_PATTERN_TYPE_MESH: - case CAIRO_PATTERN_TYPE_RASTER_SOURCE: { - cairo_surface_t *surface; - cairo_matrix_t new_pattern_matrix; - - surface = cairo_image_surface_create (CAIRO_FORMAT_ARGB32, - extents->width, extents->height); - if (_cairo_surface_offset_paint (surface, - extents->x, extents->y, - CAIRO_OPERATOR_SOURCE, - pattern, NULL)) { - cairo_surface_destroy (surface); - return NULL; - } - - cairo_matrix_init_translate (&new_pattern_matrix, - -extents->x, -extents->y); - - texture = - _cairo_cogl_acquire_generic_surface_texture (destination, - surface, - &new_pattern_matrix, - &attributes->matrix, - need_mirrored_texture, - &is_mirrored_texture); - if (unlikely (!texture)) - goto BAIL; - - attributes->extend = pattern->extend; - attributes->filter = COGL_PIPELINE_FILTER_NEAREST; - attributes->has_component_alpha = pattern->has_component_alpha; - - /* any pattern extend modes have already been dealt with... */ - attributes->s_wrap = COGL_PIPELINE_WRAP_MODE_CLAMP_TO_EDGE; - attributes->t_wrap = attributes->s_wrap; - - /* In order to support CAIRO_EXTEND_NONE, we use the same wrap - * mode as CAIRO_EXTEND_PAD, but pass a clip to the drawing - * function to make sure that we never sample anything beyond - * the texture boundaries. */ - if (pattern->extend == CAIRO_EXTEND_NONE && tex_clip) - if (_cairo_cogl_create_tex_clip (tex_clip, - attributes->matrix, - is_mirrored_texture)) - { - cogl_object_unref (texture); - cairo_surface_destroy (surface); - return NULL; - } - -BAIL: - cairo_surface_destroy (surface); - - return texture; - } - case CAIRO_PATTERN_TYPE_LINEAR: { - cairo_linear_pattern_t *linear_pattern = (cairo_linear_pattern_t *)pattern; - cairo_cogl_linear_gradient_t *gradient; - cairo_cogl_linear_texture_entry_t *linear_texture; - cairo_int_status_t status; - double dist, scale; - - status = _cairo_cogl_get_linear_gradient (to_device(destination->base.device), - pattern->extend, - linear_pattern->base.n_stops, - linear_pattern->base.stops, - need_mirrored_texture, - &gradient); - if (unlikely (status)) - return NULL; - - linear_texture = _cairo_cogl_linear_gradient_texture_for_extend (gradient, pattern->extend); - - attributes->extend = pattern->extend; - attributes->filter = - get_cogl_filter_for_filter (pattern->filter); - attributes->has_component_alpha = pattern->has_component_alpha; - attributes->s_wrap = - get_cogl_wrap_mode_for_extend (pattern->extend, dev); - attributes->t_wrap = attributes->s_wrap; - - attributes->matrix = pattern->matrix; - - double a = linear_pattern->pd2.x - linear_pattern->pd1.x; - double b = linear_pattern->pd2.y - linear_pattern->pd1.y; - double angle = - atan2f (b, a); - - cairo_matrix_rotate (&attributes->matrix, angle); - - cairo_matrix_translate (&attributes->matrix, - -linear_pattern->pd1.x, - -linear_pattern->pd1.y); - - /* Convert from un-normalized source coordinates in backend - * coordinates to normalized texture coordinates. */ - dist = sqrtf (a*a + b*b); - if (need_mirrored_texture) - scale = 0.5 / dist; - else - scale = 1.0 / dist; - _cairo_cogl_matrix_all_scale (&attributes->matrix, - scale, scale); - - return cogl_object_ref (linear_texture->texture); - } - default: - g_warning ("Unsupported source type"); - return NULL; - } -} - -static cairo_bool_t -set_blend (CoglPipeline *pipeline, const char *blend_string) -{ - CoglError *error = NULL; - if (unlikely (!cogl_pipeline_set_blend (pipeline, - blend_string, - &error))) - { - g_warning ("Unsupported blend string with current gpu/driver: %s", blend_string); - cogl_error_free (error); - return FALSE; - } - return TRUE; -} - -static cairo_bool_t -_cairo_cogl_setup_op_state (CoglPipeline *pipeline, - cairo_operator_t op) -{ - cairo_bool_t status = FALSE; - - switch ((int)op) - { - case CAIRO_OPERATOR_OVER: - status = set_blend (pipeline, "RGBA = ADD (SRC_COLOR, DST_COLOR * (1 - SRC_COLOR[A]))"); - break; - case CAIRO_OPERATOR_IN: - status = set_blend (pipeline, "RGBA = ADD (SRC_COLOR * DST_COLOR[A], 0)"); - break; - case CAIRO_OPERATOR_OUT: - status = set_blend (pipeline, "RGBA = ADD (SRC_COLOR * (1 - DST_COLOR[A]), 0)"); - break; - case CAIRO_OPERATOR_ATOP: - status = set_blend (pipeline, "RGBA = ADD (SRC_COLOR * DST_COLOR[A], DST_COLOR * (1 - SRC_COLOR[A]))"); - break; - case CAIRO_OPERATOR_DEST: - status = set_blend (pipeline, "RGBA = ADD (0, DST_COLOR)"); - break; - case CAIRO_OPERATOR_DEST_OVER: - status = set_blend (pipeline, "RGBA = ADD (SRC_COLOR * (1 - DST_COLOR[A]), DST_COLOR)"); - break; - case CAIRO_OPERATOR_DEST_IN: - status = set_blend (pipeline, "RGBA = ADD (0, DST_COLOR * SRC_COLOR[A])"); - break; - case CAIRO_OPERATOR_DEST_OUT: - status = set_blend (pipeline, "RGBA = ADD (0, DST_COLOR * (1 - SRC_COLOR[A]))"); - break; - case CAIRO_OPERATOR_DEST_ATOP: - status = set_blend (pipeline, "RGBA = ADD (SRC_COLOR * (1 - DST_COLOR[A]), DST_COLOR * SRC_COLOR[A])"); - break; - case CAIRO_OPERATOR_XOR: - status = set_blend (pipeline, "RGBA = ADD (SRC_COLOR * (1 - DST_COLOR[A]), DST_COLOR * (1 - SRC_COLOR[A]))"); - break; - /* In order to handle SOURCE with a mask, we use two passes. The - * first consists of a CAIRO_OPERATOR_DEST_OUT with the source alpha - * replaced by the mask alpha in order to multiply all the - * destination values by one minus the mask alpha. The second pass - * (this one) then adds the source values, which have already been - * premultiplied by the mask alpha. */ - case CAIRO_OPERATOR_SOURCE: - case CAIRO_OPERATOR_ADD: - status = set_blend (pipeline, "RGBA = ADD (SRC_COLOR, DST_COLOR)"); - break; - case CAIRO_OPERATOR_CLEAR: - /* Runtime check */ - /* CAIRO_OPERATOR_CLEAR is not supposed to use its own pipeline - * type. Use CAIRO_OPERATOR_DEST_OUT with the mask alpha as - * source alpha instead. */ - assert (0); - default: - g_warning ("Unsupported blend operator"); - assert (0); - } - - return status; -} - -static void -create_template_for_op_type (cairo_cogl_device_t *dev, - cairo_operator_t op, - cairo_cogl_template_type type) -{ - CoglPipeline *pipeline; - CoglColor color; - - if (dev->template_pipelines[op][type]) - return; - - cogl_color_init_from_4f (&color, 1.0f, 1.0f, 1.0f, 1.0f); - - if (!dev->template_pipelines[op][CAIRO_COGL_TEMPLATE_TYPE_SOLID]) { - CoglPipeline *base = cogl_pipeline_new (dev->cogl_context); - - if (!_cairo_cogl_setup_op_state (base, op)) { - cogl_object_unref (base); - return; - } - - dev->template_pipelines[op][CAIRO_COGL_TEMPLATE_TYPE_SOLID] = base; - } - - switch ((int)type) - { - case CAIRO_COGL_TEMPLATE_TYPE_SOLID: - return; - case CAIRO_COGL_TEMPLATE_TYPE_SOLID_MASK_SOLID: - pipeline = - cogl_pipeline_copy (dev->template_pipelines[op][CAIRO_COGL_TEMPLATE_TYPE_SOLID]); - cogl_pipeline_set_layer_combine_constant (pipeline, 0, &color); - cogl_pipeline_set_layer_combine (pipeline, 0, - "RGBA = MODULATE (PRIMARY, CONSTANT[A])", - NULL); - break; - case CAIRO_COGL_TEMPLATE_TYPE_TEXTURE_MASK_SOLID: - pipeline = - cogl_pipeline_copy (dev->template_pipelines[op][CAIRO_COGL_TEMPLATE_TYPE_SOLID]); - cogl_pipeline_set_layer_null_texture (pipeline, 0, - COGL_TEXTURE_TYPE_2D); - cogl_pipeline_set_layer_combine (pipeline, 0, - "RGBA = MODULATE (PRIMARY, TEXTURE[A])", - NULL); - break; - case CAIRO_COGL_TEMPLATE_TYPE_TEXTURE: - pipeline = - cogl_pipeline_copy (dev->template_pipelines[op][CAIRO_COGL_TEMPLATE_TYPE_SOLID]); - cogl_pipeline_set_layer_null_texture (pipeline, 0, - COGL_TEXTURE_TYPE_2D); - break; - case CAIRO_COGL_TEMPLATE_TYPE_SOLID_MASK_TEXTURE: - pipeline = - cogl_pipeline_copy (dev->template_pipelines[op][CAIRO_COGL_TEMPLATE_TYPE_SOLID]); - cogl_pipeline_set_layer_null_texture (pipeline, 0, - COGL_TEXTURE_TYPE_2D); - cogl_pipeline_set_layer_combine_constant (pipeline, 1, &color); - cogl_pipeline_set_layer_combine (pipeline, 1, - "RGBA = MODULATE (PREVIOUS, CONSTANT[A])", - NULL); - break; - case CAIRO_COGL_TEMPLATE_TYPE_TEXTURE_MASK_TEXTURE: - pipeline = - cogl_pipeline_copy (dev->template_pipelines[op][CAIRO_COGL_TEMPLATE_TYPE_SOLID]); - cogl_pipeline_set_layer_null_texture (pipeline, 0, - COGL_TEXTURE_TYPE_2D); - cogl_pipeline_set_layer_null_texture (pipeline, 1, - COGL_TEXTURE_TYPE_2D); - cogl_pipeline_set_layer_combine (pipeline, 1, - "RGBA = MODULATE (PREVIOUS, TEXTURE[A])", - NULL); - break; - case CAIRO_COGL_TEMPLATE_TYPE_TEXTURE_IGNORE_ALPHA: - pipeline = - cogl_pipeline_copy (dev->template_pipelines[op][CAIRO_COGL_TEMPLATE_TYPE_SOLID]); - cogl_pipeline_set_layer_null_texture (pipeline, 0, - COGL_TEXTURE_TYPE_2D); - /* We do not set the combine color when we use this template - * pipeline, so the source texture alpha will be replaces by - * ones */ - cogl_pipeline_set_layer_combine_constant (pipeline, 0, &color); - cogl_pipeline_set_layer_combine (pipeline, 0, - "RGB = REPLACE (TEXTURE)" - "A = REPLACE (CONSTANT)", - NULL); - break; - case CAIRO_COGL_TEMPLATE_TYPE_SOLID_MASK_TEXTURE_IGNORE_ALPHA: - pipeline = - cogl_pipeline_copy (dev->template_pipelines[op][CAIRO_COGL_TEMPLATE_TYPE_SOLID]); - cogl_pipeline_set_layer_null_texture (pipeline, 0, - COGL_TEXTURE_TYPE_2D); - /* We do not set the combine color when we use this template - * pipeline, so the source texture alpha will be replaces by - * ones */ - cogl_pipeline_set_layer_combine_constant (pipeline, 0, &color); - cogl_pipeline_set_layer_combine (pipeline, 0, - "RGB = REPLACE (TEXTURE)" - "A = REPLACE (CONSTANT)", - NULL); - cogl_pipeline_set_layer_combine_constant (pipeline, 1, &color); - cogl_pipeline_set_layer_combine (pipeline, 1, - "RGBA = MODULATE (PREVIOUS, CONSTANT[A])", - NULL); - break; - case CAIRO_COGL_TEMPLATE_TYPE_TEXTURE_MASK_TEXTURE_IGNORE_ALPHA: - pipeline = - cogl_pipeline_copy (dev->template_pipelines[op][CAIRO_COGL_TEMPLATE_TYPE_SOLID]); - cogl_pipeline_set_layer_null_texture (pipeline, 0, - COGL_TEXTURE_TYPE_2D); - /* We do not set the combine color when we use this template - * pipeline, so the source texture alpha will be replaces by - * ones */ - cogl_pipeline_set_layer_combine_constant (pipeline, 0, &color); - cogl_pipeline_set_layer_combine (pipeline, 0, - "RGB = REPLACE (TEXTURE)" - "A = REPLACE (CONSTANT)", - NULL); - cogl_pipeline_set_layer_null_texture (pipeline, 1, - COGL_TEXTURE_TYPE_2D); - cogl_pipeline_set_layer_combine (pipeline, 1, - "RGBA = MODULATE (PREVIOUS, TEXTURE[A])", - NULL); - break; - default: - g_warning ("Invalid cogl pipeline template type"); - return; - } - - dev->template_pipelines[op][type] = pipeline; -} - -static void -set_layer_texture_with_attributes (CoglPipeline *pipeline, - int layer_index, - CoglTexture *texture, - cairo_cogl_texture_attributes_t *attributes, - cairo_matrix_t *path_transform) -{ - cairo_matrix_t m; - - cogl_pipeline_set_layer_texture (pipeline, layer_index, texture); - - cogl_pipeline_set_layer_filters (pipeline, - layer_index, - attributes->filter, - attributes->filter); - - /* We multiply in the path transform here so that we read texture - * values from coordinates that are consistent with the coordinates - * of the path after it is transformed by the modelview matrix */ - if (path_transform) - cairo_matrix_multiply (&m, path_transform, &attributes->matrix); - else - m = attributes->matrix; - - if (!_cairo_matrix_is_identity (&m)) { - float texture_matrixfv[16] = { - m.xx, m.yx, 0, 0, - m.xy, m.yy, 0, 0, - 0, 0, 1, 0, - m.x0, m.y0, 0, 1 - }; - CoglMatrix texture_matrix; - cogl_matrix_init_from_array (&texture_matrix, texture_matrixfv); - cogl_pipeline_set_layer_matrix (pipeline, layer_index, &texture_matrix); - } - - if (attributes->s_wrap != attributes->t_wrap) { - cogl_pipeline_set_layer_wrap_mode_s (pipeline, layer_index, attributes->s_wrap); - cogl_pipeline_set_layer_wrap_mode_t (pipeline, layer_index, attributes->t_wrap); - } else { - cogl_pipeline_set_layer_wrap_mode (pipeline, layer_index, attributes->s_wrap); - } -} - -/* This takes an argument of a pointer to an array of two pointers to - * #cairo_cogl_pipeline_t. On failure, both pointers will be set to - * NULL */ -static void -get_source_mask_operator_destination_pipelines (cairo_cogl_pipeline_t **pipelines, - const cairo_pattern_t *mask, - const cairo_pattern_t *source, - cairo_operator_t op, - cairo_cogl_surface_t *destination, - cairo_composite_rectangles_t *extents, - cairo_matrix_t *path_transform) -{ - cairo_cogl_template_type template_type; - cairo_cogl_device_t *dev = to_device(destination->base.device); - - pipelines[0] = NULL; - pipelines[1] = NULL; - - switch ((int)source->type) - { - case CAIRO_PATTERN_TYPE_SOLID: - if (mask) { - /* If the mask surface has no alpha content, we use a mask - * of solid ones */ - if ((mask->type == CAIRO_PATTERN_TYPE_SOLID) || - (mask->type == CAIRO_PATTERN_TYPE_SURFACE && - ((cairo_surface_pattern_t *)mask)->surface->content == CAIRO_CONTENT_COLOR)) - template_type = - CAIRO_COGL_TEMPLATE_TYPE_SOLID_MASK_SOLID; - else - template_type = - CAIRO_COGL_TEMPLATE_TYPE_TEXTURE_MASK_SOLID; - } else { - template_type = CAIRO_COGL_TEMPLATE_TYPE_SOLID; - } - break; - case CAIRO_PATTERN_TYPE_SURFACE: - /* If the source does not have alpha content, we have to use - * a specialized set of texture combining functions in order to - * ensure that if we have a CAIRO_FORMAT_RGB24 source, we are - * ignoring the alpha and replacing it with ones. Otherwise, we - * use the template types for any other type of non-solid - * source. */ - if (((cairo_surface_pattern_t *)source)->surface->content == - CAIRO_CONTENT_COLOR) - { - if (mask) { - /* If the mask surface has no alpha content, we use a - * mask of solid ones */ - if ((mask->type == CAIRO_PATTERN_TYPE_SOLID) || - (mask->type == CAIRO_PATTERN_TYPE_SURFACE && - ((cairo_surface_pattern_t *)mask)->surface->content == CAIRO_CONTENT_COLOR)) - template_type = - CAIRO_COGL_TEMPLATE_TYPE_SOLID_MASK_TEXTURE_IGNORE_ALPHA; - else - template_type = - CAIRO_COGL_TEMPLATE_TYPE_TEXTURE_MASK_TEXTURE_IGNORE_ALPHA; - } else { - template_type = - CAIRO_COGL_TEMPLATE_TYPE_TEXTURE_IGNORE_ALPHA; - } - break; - } - // else fall through - case CAIRO_PATTERN_TYPE_LINEAR: - case CAIRO_PATTERN_TYPE_RADIAL: - case CAIRO_PATTERN_TYPE_MESH: - case CAIRO_PATTERN_TYPE_RASTER_SOURCE: - if (mask) { - /* If the mask surface has no alpha content, we use a mask - * of solid ones */ - if ((mask->type == CAIRO_PATTERN_TYPE_SOLID) || - (mask->type == CAIRO_PATTERN_TYPE_SURFACE && - ((cairo_surface_pattern_t *)mask)->surface->content == CAIRO_CONTENT_COLOR)) - template_type = - CAIRO_COGL_TEMPLATE_TYPE_SOLID_MASK_TEXTURE; - else - template_type = - CAIRO_COGL_TEMPLATE_TYPE_TEXTURE_MASK_TEXTURE; - } else { - template_type = CAIRO_COGL_TEMPLATE_TYPE_TEXTURE; - } - break; - default: - g_warning ("Unsupported source type"); - return; - } - - /* pipelines[0] is for pre-rendering the mask alpha in the case - * that it cannot be represented through the source color alpha - * value. For more details, go to the description in - * _cairo_cogl_setup_op_state */ - if (op == CAIRO_OPERATOR_CLEAR || op == CAIRO_OPERATOR_SOURCE) { - cairo_cogl_template_type prerender_type; - - pipelines[0] = g_new (cairo_cogl_pipeline_t, 1); - - if (mask && mask->type != CAIRO_PATTERN_TYPE_SOLID) - prerender_type = CAIRO_COGL_TEMPLATE_TYPE_SOLID; - else - prerender_type = CAIRO_COGL_TEMPLATE_TYPE_TEXTURE; - - /* Lazily create pipeline templates */ - if (unlikely (dev->template_pipelines[CAIRO_OPERATOR_DEST_OUT][prerender_type] == NULL)) - create_template_for_op_type (dev, - CAIRO_OPERATOR_DEST_OUT, - prerender_type); - - pipelines[0]->pipeline = - cogl_pipeline_copy (dev->template_pipelines[CAIRO_OPERATOR_DEST_OUT][prerender_type]); - - pipelines[0]->mask_bounded = - _cairo_operator_bounded_by_mask (op); - pipelines[0]->src_bounded = - _cairo_operator_bounded_by_source (op); - pipelines[0]->op = CAIRO_OPERATOR_DEST_OUT; - pipelines[0]->n_layers = 0; - pipelines[0]->has_src_tex_clip = FALSE; - pipelines[0]->has_mask_tex_clip = FALSE; - pipelines[0]->unbounded_extents = extents->unbounded; - } - - /* pipelines[1] is for normal rendering, modulating the mask with - * the source. Most operators will only need this pipeline. */ - if (op != CAIRO_OPERATOR_CLEAR) { - pipelines[1] = g_new (cairo_cogl_pipeline_t, 1); - - /* Lazily create pipeline templates */ - if (unlikely (dev->template_pipelines[op][template_type] == NULL)) - create_template_for_op_type (dev, op, template_type); - - pipelines[1]->pipeline = - cogl_pipeline_copy (dev->template_pipelines[op][template_type]); - - pipelines[1]->mask_bounded = - _cairo_operator_bounded_by_mask (op); - pipelines[1]->src_bounded = - _cairo_operator_bounded_by_source (op); - pipelines[1]->op = op; - pipelines[1]->n_layers = 0; - pipelines[1]->has_src_tex_clip = FALSE; - pipelines[1]->has_mask_tex_clip = FALSE; - pipelines[1]->unbounded_extents = extents->unbounded; - } - - if (pipelines[1]) { - if (source->type == CAIRO_PATTERN_TYPE_SOLID) { - cairo_solid_pattern_t *solid_pattern = (cairo_solid_pattern_t *)source; - cogl_pipeline_set_color4f (pipelines[1]->pipeline, - solid_pattern->color.red * solid_pattern->color.alpha, - solid_pattern->color.green * solid_pattern->color.alpha, - solid_pattern->color.blue * solid_pattern->color.alpha, - solid_pattern->color.alpha); - } else { - cairo_cogl_texture_attributes_t attributes; - - _cairo_path_fixed_init (&pipelines[1]->src_tex_clip); - - CoglTexture *texture = - _cairo_cogl_acquire_pattern_texture (source, destination, - &extents->bounded, - &attributes, - &pipelines[1]->src_tex_clip); - if (unlikely (!texture)) - goto BAIL; - set_layer_texture_with_attributes (pipelines[1]->pipeline, - pipelines[1]->n_layers++, - texture, - &attributes, - path_transform); - cogl_object_unref (texture); - - if (pipelines[1]->src_tex_clip.buf.base.num_ops > 0) - pipelines[1]->has_src_tex_clip = TRUE; - else - _cairo_path_fixed_fini (&pipelines[1]->src_tex_clip); - } - } - - if (mask) { - if (mask->type == CAIRO_PATTERN_TYPE_SOLID) { - cairo_solid_pattern_t *solid_pattern = (cairo_solid_pattern_t *)mask; - CoglColor color; - cogl_color_init_from_4f (&color, - solid_pattern->color.red * solid_pattern->color.alpha, - solid_pattern->color.green * solid_pattern->color.alpha, - solid_pattern->color.blue * solid_pattern->color.alpha, - solid_pattern->color.alpha); - if (pipelines[1]) - cogl_pipeline_set_layer_combine_constant (pipelines[1]->pipeline, - pipelines[1]->n_layers++, - &color); - if (pipelines[0]) - cogl_pipeline_set_color (pipelines[0]->pipeline, - &color); - /* If the only component present in our mask is a color - * component, skip setting the layer texture, as we already - * set a solid of uniform ones on it during the template - * creation process */ - } else if (!(mask->type == CAIRO_PATTERN_TYPE_SURFACE && - ((cairo_surface_pattern_t *)mask)->surface->content == CAIRO_CONTENT_COLOR)) { - cairo_cogl_texture_attributes_t attributes; - cairo_path_fixed_t mask_tex_clip; - - _cairo_path_fixed_init (&mask_tex_clip); - - CoglTexture *texture = - _cairo_cogl_acquire_pattern_texture (mask, destination, - &extents->bounded, - &attributes, - &mask_tex_clip); - if (unlikely (!texture)) - goto BAIL; - if (pipelines[1]) { - if (mask_tex_clip.buf.base.num_ops > 0) { - pipelines[1]->has_mask_tex_clip = TRUE; - if (unlikely (_cairo_path_fixed_init_copy (&pipelines[1]->mask_tex_clip, - &mask_tex_clip))) - goto BAIL; - } - set_layer_texture_with_attributes (pipelines[1]->pipeline, - pipelines[1]->n_layers++, - texture, - &attributes, - path_transform); - } - if (pipelines[0]) { - if (mask_tex_clip.buf.base.num_ops > 0) { - pipelines[0]->has_mask_tex_clip = TRUE; - if (unlikely (_cairo_path_fixed_init_copy (&pipelines[0]->mask_tex_clip, - &mask_tex_clip))) - goto BAIL; - } - set_layer_texture_with_attributes (pipelines[0]->pipeline, - pipelines[0]->n_layers++, - texture, - &attributes, - path_transform); - } - - _cairo_path_fixed_fini (&mask_tex_clip); - cogl_object_unref (texture); - } - } - - return; - -BAIL: - if (pipelines[0]) { - cogl_object_unref (pipelines[0]->pipeline); - if (pipelines[0]->has_src_tex_clip) - _cairo_path_fixed_fini (&pipelines[0]->src_tex_clip); - if (pipelines[0]->has_mask_tex_clip) - _cairo_path_fixed_fini (&pipelines[0]->mask_tex_clip); - g_free (pipelines[0]); - pipelines[0] = NULL; - } - if (pipelines[1]) { - cogl_object_unref (pipelines[1]->pipeline); - if (pipelines[1]->has_src_tex_clip) - _cairo_path_fixed_fini (&pipelines[1]->src_tex_clip); - if (pipelines[1]->has_mask_tex_clip) - _cairo_path_fixed_fini (&pipelines[1]->mask_tex_clip); - g_free (pipelines[1]); - pipelines[1] = NULL; - } -} - -#if 0 -CoglPrimitive * -_cairo_cogl_rectangle_new_p2t2t2 (CoglContext *cogl_context, - float x, - float y, - float width, - float height) -{ - CoglVertexP2 vertices[] = { - {x, y}, {x, y + height}, {x + width, y + height}, - {x, y}, {x + width, y + height}, {x + width, y} - }; - CoglAttributeBuffer *buffer = cogl_attribute_buffer_new (cogl_context, - sizeof (vertices)); - CoglAttribute *pos = cogl_attribute_new (buffer, - "cogl_position_in", - sizeof (CoglVertexP2), - 0, - 2, - COGL_ATTRIBUTE_TYPE_FLOAT); - CoglAttribute *tex_coords0 = cogl_attribute_new (buffer, - "cogl_tex_coord0_in", - sizeof (CoglVertexP2), - 0, - 2, - COGL_ATTRIBUTE_TYPE_FLOAT); - CoglAttribute *tex_coords0 = cogl_attribute_new (buffer, - "cogl_tex_coord0_in", - sizeof (CoglVertexP2), - 0, - 2, - COGL_ATTRIBUTE_TYPE_FLOAT); - CoglPrimitive *prim; - - cogl_buffer_set_data (buffer, 0, vertices, sizeof (vertices)); - - /* The attributes will now keep the buffer alive... */ - cogl_object_unref (buffer); - - prim = cogl_primitive_new (COGL_VERTICES_MODE_TRIANGLES, - 6, pos, tex_coords, NULL); - - /* The primitive will now keep the attribute alive... */ - cogl_object_unref (pos); - - return prim; -} -#endif - -static void -_cairo_cogl_log_clip (cairo_cogl_surface_t *surface, - const cairo_clip_t *clip) -{ - if (!_cairo_clip_equal (clip, surface->last_clip)) { - _cairo_cogl_journal_log_clip (surface, clip); - _cairo_clip_destroy (surface->last_clip); - surface->last_clip = _cairo_clip_copy (clip); - } -} - -static void -_cairo_cogl_maybe_log_clip (cairo_cogl_surface_t *surface, - cairo_composite_rectangles_t *composite) -{ - cairo_clip_t *clip = composite->clip; - - if (_cairo_composite_rectangles_can_reduce_clip (composite, clip)) - clip = NULL; - - if (clip == NULL) { - if (_cairo_composite_rectangles_can_reduce_clip (composite, - surface->last_clip)) - return; - } - - _cairo_cogl_log_clip (surface, clip); -} - -static cairo_bool_t -is_operator_supported (cairo_operator_t op) -{ - switch ((int)op) { - case CAIRO_OPERATOR_CLEAR: - case CAIRO_OPERATOR_SOURCE: - case CAIRO_OPERATOR_OVER: - case CAIRO_OPERATOR_IN: - case CAIRO_OPERATOR_OUT: - case CAIRO_OPERATOR_ATOP: - case CAIRO_OPERATOR_DEST: - case CAIRO_OPERATOR_DEST_OVER: - case CAIRO_OPERATOR_DEST_IN: - case CAIRO_OPERATOR_DEST_OUT: - case CAIRO_OPERATOR_DEST_ATOP: - case CAIRO_OPERATOR_XOR: - case CAIRO_OPERATOR_ADD: - return TRUE; - - default: - g_warning("cairo-cogl: Blend operator not supported"); - return FALSE; - } -} - -static cairo_int_status_t -_cairo_cogl_surface_paint (void *abstract_surface, - cairo_operator_t op, - const cairo_pattern_t *source, - const cairo_clip_t *clip) -{ - cairo_cogl_surface_t *surface; - cairo_int_status_t status; - cairo_matrix_t identity; - cairo_cogl_pipeline_t *pipelines[2]; - cairo_composite_rectangles_t extents; - - if (clip == NULL) { - status = _cairo_cogl_surface_ensure_framebuffer (abstract_surface); - if (unlikely (status)) - return status; - - if (op == CAIRO_OPERATOR_CLEAR) - return _cairo_cogl_surface_clear (abstract_surface, CAIRO_COLOR_TRANSPARENT); - else if (source->type == CAIRO_PATTERN_TYPE_SOLID && - (op == CAIRO_OPERATOR_SOURCE || - (op == CAIRO_OPERATOR_OVER && (((cairo_surface_t *)abstract_surface)->is_clear || _cairo_pattern_is_opaque_solid (source))))) { - return _cairo_cogl_surface_clear (abstract_surface, - &((cairo_solid_pattern_t *) source)->color); - } - } - - /* fall back to handling the paint in terms of a rectangle... */ - - surface = (cairo_cogl_surface_t *)abstract_surface; - - if (!is_operator_supported (op)) - return CAIRO_INT_STATUS_UNSUPPORTED; - - status = - _cairo_composite_rectangles_init_for_paint (&extents, - &surface->base, - op, - source, - clip); - if (unlikely (status)) - return status; - - get_source_mask_operator_destination_pipelines (pipelines, - NULL, - source, - op, - surface, - &extents, - NULL); - if (unlikely (pipelines[0] == NULL && pipelines[1] == NULL)) { - status = CAIRO_INT_STATUS_UNSUPPORTED; - goto BAIL; - } - - _cairo_cogl_maybe_log_clip (surface, &extents); - - cairo_matrix_init_identity (&identity); - if (pipelines[0]) - _cairo_cogl_journal_log_rectangle (surface, - pipelines[0], - extents.bounded.x, - extents.bounded.y, - extents.bounded.width, - extents.bounded.height, - &identity); - if (pipelines[1]) - _cairo_cogl_journal_log_rectangle (surface, - pipelines[1], - extents.bounded.x, - extents.bounded.y, - extents.bounded.width, - extents.bounded.height, - &identity); - -BAIL: - _cairo_composite_rectangles_fini (&extents); - - return status; -} - -static cairo_int_status_t -_cairo_cogl_surface_mask (void *abstract_surface, - cairo_operator_t op, - const cairo_pattern_t *source, - const cairo_pattern_t *mask, - const cairo_clip_t *clip) -{ - cairo_cogl_surface_t *surface = abstract_surface; - cairo_composite_rectangles_t extents; - cairo_int_status_t status; - cairo_cogl_pipeline_t *pipelines[2]; - cairo_matrix_t identity; - - /* XXX: Use this to smoke test the acquire_source/dest_image fallback - * paths... */ - //return CAIRO_INT_STATUS_UNSUPPORTED; - - if (!is_operator_supported (op)) - return CAIRO_INT_STATUS_UNSUPPORTED; - - status = _cairo_composite_rectangles_init_for_mask (&extents, - &surface->base, - op, source, mask, clip); - if (unlikely (status)) - return status; - - get_source_mask_operator_destination_pipelines (pipelines, - mask, - source, - op, - surface, - &extents, - NULL); - if (unlikely (pipelines[0] == NULL && pipelines[1] == NULL)) { - status = CAIRO_INT_STATUS_UNSUPPORTED; - goto BAIL; - } - - _cairo_cogl_maybe_log_clip (surface, &extents); - - cairo_matrix_init_identity (&identity); - if (pipelines[0]) - _cairo_cogl_journal_log_rectangle (surface, - pipelines[0], - extents.bounded.x, - extents.bounded.y, - extents.bounded.width, - extents.bounded.height, - &identity); - if (pipelines[1]) - _cairo_cogl_journal_log_rectangle (surface, - pipelines[1], - extents.bounded.x, - extents.bounded.y, - extents.bounded.width, - extents.bounded.height, - &identity); - -BAIL: - _cairo_composite_rectangles_fini (&extents); - - return status; -} - -static cairo_int_status_t -_cairo_cogl_surface_stroke (void *abstract_surface, - cairo_operator_t op, - const cairo_pattern_t *source, - const cairo_path_fixed_t *path, - const cairo_stroke_style_t *style, - const cairo_matrix_t *ctm, - const cairo_matrix_t *ctm_inverse, - double tolerance, - cairo_antialias_t antialias, - const cairo_clip_t *clip) -{ - cairo_cogl_surface_t *surface = (cairo_cogl_surface_t *)abstract_surface; - cairo_composite_rectangles_t extents; - cairo_cogl_pipeline_t *pipelines[2]; - cairo_int_status_t status; - cairo_matrix_t transform; - CoglPrimitive *prim = NULL; - - if (! is_operator_supported (op)) - return CAIRO_INT_STATUS_UNSUPPORTED; - - status = _cairo_composite_rectangles_init_for_stroke (&extents, - &surface->base, - op, source, path, - style, - ctm, - clip); - if (unlikely (status)) - return status; - - status = _cairo_cogl_stroke_to_primitive (surface, path, style, - tolerance, TRUE, &prim, - &transform); - if (status == CAIRO_INT_STATUS_NOTHING_TO_DO - && _cairo_operator_bounded_by_mask (op) == FALSE) { - /* Just render the unbounded rectangle */ - prim = NULL; - } else if (unlikely (status)) { - goto BAIL; - } - - get_source_mask_operator_destination_pipelines (pipelines, - NULL, - source, - op, - surface, - &extents, - &transform); - if (unlikely (pipelines[0] == NULL && pipelines[1] == NULL)) { - status = CAIRO_INT_STATUS_UNSUPPORTED; - goto BAIL; - } - - _cairo_cogl_maybe_log_clip (surface, &extents); - - if (pipelines[0]) - _cairo_cogl_journal_log_primitive (surface, - pipelines[0], - prim, - &transform); - if (pipelines[1]) - _cairo_cogl_journal_log_primitive (surface, - pipelines[1], - prim, - &transform); - -BAIL: - /* The journal will take a reference on the primitive... */ - if (prim) - cogl_object_unref (prim); - - _cairo_composite_rectangles_fini (&extents); - - return status; -} - -static cairo_int_status_t -_cairo_cogl_surface_fill (void *abstract_surface, - cairo_operator_t op, - const cairo_pattern_t *source, - const cairo_path_fixed_t *path, - cairo_fill_rule_t fill_rule, - double tolerance, - cairo_antialias_t antialias, - const cairo_clip_t *clip) -{ - cairo_cogl_surface_t *surface = abstract_surface; - cairo_composite_rectangles_t extents; - cairo_int_status_t status; - cairo_matrix_t transform; - CoglPrimitive *prim = NULL; - cairo_cogl_pipeline_t *pipelines[2]; - - if (! is_operator_supported (op)) - return CAIRO_INT_STATUS_UNSUPPORTED; - - status = _cairo_composite_rectangles_init_for_fill (&extents, - &surface->base, - op, source, path, - clip); - if (unlikely (status)) - return status; - - status = _cairo_cogl_fill_to_primitive (surface, path, fill_rule, - tolerance, TRUE, &prim, - &transform); - if (status == CAIRO_INT_STATUS_NOTHING_TO_DO - && _cairo_operator_bounded_by_mask (op) == FALSE) { - /* Just render the unbounded rectangle */ - prim = NULL; - } else if (unlikely (status)) { - goto BAIL; - } - - get_source_mask_operator_destination_pipelines (pipelines, - NULL, - source, - op, - surface, - &extents, - &transform); - if (unlikely (pipelines[0] == NULL && pipelines[1] == NULL)) { - status = CAIRO_INT_STATUS_UNSUPPORTED; - goto BAIL; - } - - _cairo_cogl_maybe_log_clip (surface, &extents); - - if (pipelines[0]) - _cairo_cogl_journal_log_primitive (surface, - pipelines[0], - prim, - &transform); - if (pipelines[1]) - _cairo_cogl_journal_log_primitive (surface, - pipelines[1], - prim, - &transform); - -BAIL: - /* The journal will take a reference on the prim */ - if (prim) - cogl_object_unref (prim); - _cairo_composite_rectangles_fini (&extents); - - return status; -} - -/* Mostly taken from #cairo_vg_surface.c */ -/* TODO: implement actual font support, with either cogl-pango's glyph - * cache or our own */ -static cairo_int_status_t -_cairo_cogl_surface_show_glyphs (void *abstract_surface, - cairo_operator_t op, - const cairo_pattern_t *source, - cairo_glyph_t *glyphs, - int num_glyphs, - cairo_scaled_font_t *scaled_font, - const cairo_clip_t *clip) -{ - cairo_status_t status = CAIRO_STATUS_SUCCESS; - cairo_path_fixed_t path; - int num_chunk_glyphs; - int i; - - if (num_glyphs <= 0) - return CAIRO_STATUS_SUCCESS; - -#define GLYPH_CHUNK_SIZE 100 - - /* Chunk glyphs in order to avoid large computation overheads - * during tessellation of long strings */ - for (i = 0; i < num_glyphs; i += GLYPH_CHUNK_SIZE) { - num_chunk_glyphs = (num_glyphs - i) < GLYPH_CHUNK_SIZE ? - (num_glyphs - i) : GLYPH_CHUNK_SIZE; - - _cairo_path_fixed_init (&path); - status = _cairo_scaled_font_glyph_path (scaled_font, - &glyphs[i], - num_chunk_glyphs, - &path); - if (unlikely (status)) - goto BAIL; - - status = _cairo_cogl_surface_fill (abstract_surface, - op, source, &path, - CAIRO_FILL_RULE_WINDING, - CAIRO_GSTATE_TOLERANCE_DEFAULT, - CAIRO_ANTIALIAS_DEFAULT, - clip); - - _cairo_path_fixed_fini (&path); - } - -#undef GLYPH_CHUNK_SIZE - - return CAIRO_STATUS_SUCCESS; - -BAIL: - _cairo_path_fixed_fini (&path); - - return status; -} - -const cairo_surface_backend_t _cairo_cogl_surface_backend = { - CAIRO_SURFACE_TYPE_COGL, - _cairo_cogl_surface_finish, - _cairo_default_context_create, - - _cairo_cogl_surface_create_similar, - NULL, /* create similar image */ - NULL, /* map to image */ - NULL, /* unmap image */ - - _cairo_surface_default_source, - _cairo_cogl_surface_acquire_source_image, - _cairo_cogl_surface_release_source_image, - NULL, /* snapshot */ - - NULL, /* copy_page */ - NULL, /* show_page */ - - _cairo_cogl_surface_get_extents, - NULL, /* get_font_options */ - - _cairo_cogl_surface_flush, /* flush */ - NULL, /* mark_dirty_rectangle */ - - _cairo_cogl_surface_paint, - _cairo_cogl_surface_mask, - _cairo_cogl_surface_stroke, - _cairo_cogl_surface_fill, - NULL, /* fill_stroke */ - _cairo_cogl_surface_show_glyphs, -}; - -static cairo_surface_t * -_cairo_cogl_surface_create_full (cairo_cogl_device_t *dev, - cairo_content_t content, - CoglFramebuffer *framebuffer, - CoglTexture *texture) -{ - cairo_cogl_surface_t *surface; - cairo_status_t status; - - status = cairo_device_acquire (&dev->base); - if (unlikely (status)) - return _cairo_surface_create_in_error (status); - - surface = _cairo_malloc (sizeof (cairo_cogl_surface_t)); - if (unlikely (surface == NULL)) - return _cairo_surface_create_in_error (_cairo_error (CAIRO_STATUS_NO_MEMORY)); - - surface->is_mirrored_snapshot = FALSE; - - surface->framebuffer = framebuffer; - if (framebuffer) { - surface->width = cogl_framebuffer_get_width (framebuffer); - surface->height = cogl_framebuffer_get_height (framebuffer); - cogl_object_ref (framebuffer); - } - - /* FIXME: If texture == NULL and we are given an offscreen framebuffer - * then we want a way to poke inside the framebuffer to get a texture */ - surface->texture = texture; - if (texture) { - if (!framebuffer) { - surface->width = cogl_texture_get_width (texture); - surface->height = cogl_texture_get_height (texture); - } - cogl_object_ref (texture); - } - - surface->journal = NULL; - - surface->last_clip = NULL; - - surface->n_clip_updates_per_frame = 0; - - surface->path_is_rectangle = FALSE; - surface->user_path = NULL; - - _cairo_surface_init (&surface->base, - &_cairo_cogl_surface_backend, - &dev->base, - content, - FALSE); /* is_vector */ - - return &surface->base; -} - -cairo_surface_t * -cairo_cogl_surface_create_for_fb (cairo_device_t *abstract_device, - CoglFramebuffer *framebuffer, - cairo_content_t content) -{ - cairo_cogl_device_t *dev = (cairo_cogl_device_t *)abstract_device; - - if (abstract_device == NULL) - return _cairo_surface_create_in_error (CAIRO_STATUS_DEVICE_ERROR); - - if (abstract_device->status) - return _cairo_surface_create_in_error (abstract_device->status); - - if (abstract_device->backend->type != CAIRO_DEVICE_TYPE_COGL) - return _cairo_surface_create_in_error (_cairo_error (CAIRO_STATUS_SURFACE_TYPE_MISMATCH)); - - return _cairo_cogl_surface_create_full (dev, - content, - framebuffer, - NULL); -} -slim_hidden_def (cairo_cogl_surface_create_for_fb); - -cairo_surface_t * -cairo_cogl_onscreen_surface_create (cairo_device_t *abstract_device, - cairo_content_t content, - int width, int height) -{ - CoglFramebuffer *fb; - CoglTextureComponents components; - CoglError *error = NULL; - cairo_surface_t *surface; - cairo_cogl_device_t *dev = (cairo_cogl_device_t *)abstract_device; - - if (abstract_device->backend->type != CAIRO_DEVICE_TYPE_COGL) - return _cairo_surface_create_in_error (_cairo_error (CAIRO_STATUS_SURFACE_TYPE_MISMATCH)); - - /* We don't yet have a way to set the components of a framebuffer */ - components = get_components_from_cairo_content (content); - - fb = cogl_onscreen_new (dev->cogl_context, width, height); - - if (unlikely (!cogl_framebuffer_allocate (fb, &error))) { - g_warning ("Could not allocate framebuffer for onscreen " - "surface: %s", error->message); - cogl_error_free (error); - return _cairo_surface_create_in_error (CAIRO_STATUS_DEVICE_ERROR); - } - cogl_framebuffer_orthographic (fb, 0, 0, width, height, -1, 100); - - surface = cairo_cogl_surface_create_for_fb (abstract_device, - fb, - content); - - /* The surface will take a reference on the framebuffer */ - cogl_object_unref (fb); - - return surface; -} -slim_hidden_def (cairo_cogl_onscreen_surface_create); - -cairo_surface_t * -cairo_cogl_offscreen_surface_create (cairo_device_t *abstract_device, - cairo_content_t content, - int width, int height) -{ - CoglFramebuffer *fb; - CoglTexture *tex; - CoglError *error = NULL; - cairo_surface_t *surface; - cairo_cogl_device_t *dev = (cairo_cogl_device_t *)abstract_device; - int tex_width = width; - int tex_height = height; - - if (abstract_device->backend->type != CAIRO_DEVICE_TYPE_COGL) - return _cairo_surface_create_in_error (_cairo_error (CAIRO_STATUS_SURFACE_TYPE_MISMATCH)); - - /* If we cannot use an NPOT texture, allocate the texture in power - * of two dimensions instead */ - if (!dev->has_npots) { - tex_width = (int)pow (2, ceil (log2 (tex_width))); - tex_height = (int)pow (2, ceil (log2 (tex_height))); - } - - tex = cogl_texture_2d_new_with_size (dev->cogl_context, - tex_width, tex_height); - cogl_texture_set_components (tex, - get_components_from_cairo_content (content)); - fb = cogl_offscreen_new_with_texture (tex); - - if (unlikely (!cogl_framebuffer_allocate (fb, &error))) { - g_warning ("Could not allocate framebuffer for offscreen " - "surface: %s", error->message); - cogl_error_free (error); - return _cairo_surface_create_in_error (CAIRO_STATUS_DEVICE_ERROR); - } - cogl_framebuffer_orthographic (fb, 0, 0, - tex_width, tex_height, - -1, 100); - - /* The framebuffer will take a reference on the texture */ - cogl_object_unref (tex); - - surface = cairo_cogl_surface_create_for_fb (abstract_device, - fb, - content); - - /* The surface will take a reference on the framebuffer */ - cogl_object_unref (fb); - - ((cairo_cogl_surface_t *)surface)->width = width; - ((cairo_cogl_surface_t *)surface)->height = height; - - return surface; -} -slim_hidden_def (cairo_cogl_offscreen_surface_create); - -CoglFramebuffer * -cairo_cogl_surface_get_framebuffer (cairo_surface_t *abstract_surface) -{ - cairo_cogl_surface_t *surface; - - if (abstract_surface->backend != &_cairo_cogl_surface_backend) { - _cairo_error_throw (CAIRO_STATUS_SURFACE_TYPE_MISMATCH); - return NULL; - } - - surface = (cairo_cogl_surface_t *) abstract_surface; - - return surface->framebuffer; -} -slim_hidden_def (cairo_cogl_surface_get_framebuffer); - -CoglTexture * -cairo_cogl_surface_get_texture (cairo_surface_t *abstract_surface) -{ - cairo_cogl_surface_t *surface; - - if (abstract_surface->backend != &_cairo_cogl_surface_backend) { - _cairo_error_throw (CAIRO_STATUS_SURFACE_TYPE_MISMATCH); - return NULL; - } - - surface = (cairo_cogl_surface_t *) abstract_surface; - - return surface->texture; -} -slim_hidden_def (cairo_cogl_surface_get_texture); - -static cairo_status_t -_cairo_cogl_device_flush (void *device) -{ - cairo_status_t status; - cairo_cogl_device_t *dev = device; - - status = cairo_device_acquire (device); - if (unlikely (status)) - return status; - - /* XXX: we don't need to flush Cogl here, we just need to flush - * any batching we do of compositing primitives. */ - - if (dev->buffer_stack && dev->buffer_stack_offset) { - cogl_buffer_unmap (dev->buffer_stack); - cogl_object_unref (dev->buffer_stack); - dev->buffer_stack = NULL; - } - - cairo_device_release (device); - - return CAIRO_STATUS_SUCCESS; -} - -static void -_cairo_cogl_device_finish (void *device) -{ - cairo_status_t status; - cairo_cogl_device_t *dev = device; - int i, j; - - status = cairo_device_acquire (device); - if (unlikely (status)) - return; - - /* XXX: Drop references to external resources */ - - _cairo_cache_fini (&dev->linear_cache); - _cairo_cache_fini (&dev->path_fill_prim_cache); - _cairo_cache_fini (&dev->path_stroke_prim_cache); - - _cairo_freelist_fini (&dev->path_fill_meta_freelist); - _cairo_freelist_fini (&dev->path_stroke_meta_freelist); - - if (dev->buffer_stack && dev->buffer_stack_offset) { - cogl_buffer_unmap (dev->buffer_stack); - cogl_object_unref (dev->buffer_stack); - dev->buffer_stack = NULL; - } - - for (i = 0; i < CAIRO_OPERATOR_SATURATE; i++) - for (j = 0; j < CAIRO_COGL_TEMPLATE_TYPE_COUNT; j++) - if (dev->template_pipelines[i][j] != NULL) { - cogl_object_unref (dev->template_pipelines[i][j]); - dev->template_pipelines[i][j] = NULL; - } - - cogl_object_unref (dev->cogl_context); - - cairo_device_release (device); -} - -static void -_cairo_cogl_device_destroy (void *device) -{ - cairo_cogl_device_t *dev = device; - - g_free (dev); -} - -static const cairo_device_backend_t _cairo_cogl_device_backend = { - CAIRO_DEVICE_TYPE_COGL, - - NULL, /* lock */ - NULL, /* unlock */ - - _cairo_cogl_device_flush, - _cairo_cogl_device_finish, - _cairo_cogl_device_destroy, -}; - -cairo_device_t * -cairo_cogl_device_create (CoglContext *cogl_context) -{ - cairo_cogl_device_t *dev = g_new (cairo_cogl_device_t, 1); - cairo_status_t status; - - dev->cogl_context = cogl_object_ref (cogl_context); - - dev->has_npots = - cogl_has_features (cogl_context, - COGL_FEATURE_ID_TEXTURE_NPOT_BASIC, - COGL_FEATURE_ID_TEXTURE_NPOT_REPEAT, - 0); - - dev->has_mirrored_repeat = - cogl_has_feature (cogl_context, - COGL_FEATURE_ID_MIRRORED_REPEAT); - - dev->buffer_stack = NULL; - dev->buffer_stack_size = 4096; - - /* Set all template pipelines to NULL */ - memset (dev->template_pipelines, 0, sizeof (dev->template_pipelines)); - - status = _cairo_cache_init (&dev->linear_cache, - _cairo_cogl_linear_gradient_equal, - NULL, - (cairo_destroy_func_t) _cairo_cogl_linear_gradient_destroy, - CAIRO_COGL_LINEAR_GRADIENT_CACHE_SIZE); - if (unlikely (status)) { - g_free (dev); - return _cairo_device_create_in_error (status); - } - - status = _cairo_cache_init (&dev->path_fill_prim_cache, - _cairo_cogl_path_fill_meta_equal, - NULL, - (cairo_destroy_func_t) _cairo_cogl_path_fill_meta_destroy, - CAIRO_COGL_PATH_META_CACHE_SIZE); - - status = _cairo_cache_init (&dev->path_stroke_prim_cache, - _cairo_cogl_path_stroke_meta_equal, - NULL, - (cairo_destroy_func_t) _cairo_cogl_path_stroke_meta_destroy, - CAIRO_COGL_PATH_META_CACHE_SIZE); - - _cairo_freelist_init (&dev->path_fill_meta_freelist, - sizeof(cairo_cogl_path_fill_meta_t)); - _cairo_freelist_init (&dev->path_stroke_meta_freelist, - sizeof(cairo_cogl_path_stroke_meta_t)); - - _cairo_device_init (&dev->base, &_cairo_cogl_device_backend); - return &dev->base; -} -slim_hidden_def (cairo_cogl_device_create); - -cairo_status_t -cairo_cogl_surface_end_frame (cairo_surface_t *abstract_surface) -{ - cairo_cogl_surface_t *surface = (cairo_cogl_surface_t *)abstract_surface; - - if (abstract_surface->backend != &_cairo_cogl_surface_backend) - return CAIRO_STATUS_SURFACE_TYPE_MISMATCH; - - cairo_surface_flush (abstract_surface); - - if (surface->framebuffer) - if (cogl_is_onscreen (surface->framebuffer)) - cogl_onscreen_swap_buffers (surface->framebuffer); - - //g_print ("n_clip_updates_per_frame = %d\n", surface->n_clip_updates_per_frame); - surface->n_clip_updates_per_frame = 0; - - return CAIRO_STATUS_SUCCESS; -} -slim_hidden_def (cairo_cogl_surface_end_frame); - -cairo_status_t -cairo_cogl_surface_synchronize (cairo_surface_t *abstract_surface) -{ - cairo_cogl_surface_t *surface = (cairo_cogl_surface_t *)abstract_surface; - - if (abstract_surface->backend != &_cairo_cogl_surface_backend) - return CAIRO_STATUS_SURFACE_TYPE_MISMATCH; - - if (surface->framebuffer) - cogl_framebuffer_finish (surface->framebuffer); - - return CAIRO_STATUS_SUCCESS; -} -slim_hidden_def (cairo_cogl_surface_synchronize); diff --git a/gfx/cairo/cairo/src/cairo-cogl.h b/gfx/cairo/cairo/src/cairo-cogl.h deleted file mode 100644 index b7a5b8e5c0..0000000000 --- a/gfx/cairo/cairo/src/cairo-cogl.h +++ /dev/null @@ -1,86 +0,0 @@ -/* cairo - a vector graphics library with display and print output - * - * Copyright © 2011 Intel Corporation. - * - * This library is free software; you can redistribute it and/or - * modify it either under the terms of the GNU Lesser General Public - * License version 2.1 as published by the Free Software Foundation - * (the "LGPL") or, at your option, under the terms of the Mozilla - * Public License Version 1.1 (the "MPL"). If you do not alter this - * notice, a recipient may use your version of this file under either - * the MPL or the LGPL. - * - * You should have received a copy of the LGPL along with this library - * in the file COPYING-LGPL-2.1; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Suite 500, Boston, MA 02110-1335, USA - * You should have received a copy of the MPL along with this library - * in the file COPYING-MPL-1.1 - * - * The contents of this file are subject to the Mozilla Public License - * Version 1.1 (the "License"); you may not use this file except in - * compliance with the License. You may obtain a copy of the License at - * http://www.mozilla.org/MPL/ - * - * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY - * OF ANY KIND, either express or implied. See the LGPL or the MPL for - * the specific language governing rights and limitations. - * - * The Original Code is the cairo graphics library. - * - * The Initial Developer of the Original Code is Mozilla Corporation. - * - * Contributor(s): - * Robert Bragg <robert@linux.intel.com> - */ - -#ifndef CAIRO_COGL_H -#define CAIRO_COGL_H - -#include "cairo.h" - -#if CAIRO_HAS_COGL_SURFACE - -#include <cogl/cogl2-experimental.h> - -CAIRO_BEGIN_DECLS - -cairo_public cairo_device_t * -cairo_cogl_device_create (CoglContext *context); - -cairo_public cairo_surface_t * -cairo_cogl_onscreen_surface_create (cairo_device_t *device, - cairo_content_t content, - int width, int height); - -cairo_public cairo_surface_t * -cairo_cogl_offscreen_surface_create (cairo_device_t *device, - cairo_content_t content, - int width, int height); - -cairo_public cairo_surface_t * -cairo_cogl_surface_create_for_fb (cairo_device_t *device, - CoglFramebuffer *framebuffer, - cairo_content_t content); - -cairo_public CoglFramebuffer * -cairo_cogl_surface_get_framebuffer (cairo_surface_t *surface); - -/* If NPOT textures are not supported, the contents of interests may - * only be in the lowest-coordinate corner of the texture obtained from - * this function */ -cairo_public CoglTexture * -cairo_cogl_surface_get_texture (cairo_surface_t *surface); - -cairo_public cairo_status_t -cairo_cogl_surface_end_frame (cairo_surface_t *surface); - -cairo_public cairo_status_t -cairo_cogl_surface_synchronize (cairo_surface_t *surface); - -CAIRO_END_DECLS - -#else /* CAIRO_HAS_COGL_SURFACE*/ -# error Cairo was not compiled with support for the Cogl backend -#endif /* CAIRO_HAS_COGL_SURFACE*/ - -#endif /* CAIRO_COGL_H */ diff --git a/gfx/cairo/cairo/src/cairo-colr-glyph-render.c b/gfx/cairo/cairo/src/cairo-colr-glyph-render.c new file mode 100644 index 0000000000..28254fd51a --- /dev/null +++ b/gfx/cairo/cairo/src/cairo-colr-glyph-render.c @@ -0,0 +1,1248 @@ +/* -*- Mode: c; c-basic-offset: 4; indent-tabs-mode: t; tab-width: 8; -*- */ +/* cairo - a vector graphics library with display and print output + * + * Copyright © 2022 Matthias Clasen + * + * 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., 51 Franklin Street, Suite 500, Boston, MA 02110-1335, 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. + * + * Contributor(s): + * Matthias Clasen <mclasen@redhat.com> + */ + +#include "cairoint.h" +#include "cairo-array-private.h" +#include "cairo-ft-private.h" +#include "cairo-path-private.h" +#include "cairo-pattern-private.h" + +#include <assert.h> +#include <math.h> +#include <stdio.h> +#include <string.h> + +#if HAVE_FT_COLR_V1 + +#include <ft2build.h> +#include FT_CONFIG_OPTIONS_H +#include FT_COLOR_H +#include FT_GLYPH_H +#include FT_OUTLINE_H +#include FT_SIZES_H + +/* #define DEBUG_COLR 1 */ + +typedef struct _cairo_colr_glyph_render { + FT_Face face; + FT_Color *palette; + unsigned int num_palette_entries; + cairo_pattern_t *foreground_marker; + cairo_pattern_t *foreground_source; + cairo_bool_t foreground_source_used; + int level; +} cairo_colr_glyph_render_t; + +static cairo_status_t +draw_paint (cairo_colr_glyph_render_t *render, + FT_OpaquePaint *paint, + cairo_t *cr); + + +static inline double +double_from_16_16 (FT_Fixed f) +{ + return f / (double) (1 << 16); +} + +static inline double +double_from_26_6 (FT_F26Dot6 f) +{ + return f / (double) (1 << 6); +} + +static inline double +double_from_2_14 (FT_F2Dot14 f) +{ + return f / (double) (1 << 14); +} + +static inline double +interpolate (double f0, double f1, double f) +{ + return f0 + f * (f1 - f0); +} + +static inline void +interpolate_points (cairo_point_double_t *p0, + cairo_point_double_t *p1, + double f, + cairo_point_double_t *out) +{ + out->x = interpolate (p0->x, p1->x, f); + out->y = interpolate (p0->y, p1->y, f); +} + +static inline void +interpolate_colors (cairo_color_t *c0, + cairo_color_t *c1, + double f, + cairo_color_t *out) +{ + out->red = interpolate (c0->red, c1->red, f); + out->green = interpolate (c0->green, c1->green, f); + out->blue = interpolate (c0->blue, c1->blue, f); + out->alpha = interpolate (c0->alpha, c1->alpha, f); +} + +static inline double +dot (cairo_point_double_t p, cairo_point_double_t q) +{ + return p.x * q.x + p.y * q.y; +} + +static inline cairo_point_double_t +normalize (cairo_point_double_t p) +{ + double len = sqrt (dot (p, p)); + + return (cairo_point_double_t) { p.x / len, p.y / len }; +} + +static inline cairo_point_double_t +sum (cairo_point_double_t p, cairo_point_double_t q) +{ + return (cairo_point_double_t) { p.x + q.x, p.y + q.y }; +} + +static inline cairo_point_double_t +difference (cairo_point_double_t p, cairo_point_double_t q) +{ + return (cairo_point_double_t) { p.x - q.x, p.y - q.y }; +} + +static inline cairo_point_double_t +scale (cairo_point_double_t p, double f) +{ + return (cairo_point_double_t) { p.x * f, p.y * f }; +} + +static cairo_operator_t +cairo_operator_from_ft_composite_mode (FT_Composite_Mode mode) +{ + switch (mode) + { + case FT_COLR_COMPOSITE_CLEAR: return CAIRO_OPERATOR_CLEAR; + case FT_COLR_COMPOSITE_SRC: return CAIRO_OPERATOR_SOURCE; + case FT_COLR_COMPOSITE_DEST: return CAIRO_OPERATOR_DEST; + case FT_COLR_COMPOSITE_SRC_OVER: return CAIRO_OPERATOR_OVER; + case FT_COLR_COMPOSITE_DEST_OVER: return CAIRO_OPERATOR_DEST_OVER; + case FT_COLR_COMPOSITE_SRC_IN: return CAIRO_OPERATOR_IN; + case FT_COLR_COMPOSITE_DEST_IN: return CAIRO_OPERATOR_DEST_IN; + case FT_COLR_COMPOSITE_SRC_OUT: return CAIRO_OPERATOR_OUT; + case FT_COLR_COMPOSITE_DEST_OUT: return CAIRO_OPERATOR_DEST_OUT; + case FT_COLR_COMPOSITE_SRC_ATOP: return CAIRO_OPERATOR_ATOP; + case FT_COLR_COMPOSITE_DEST_ATOP: return CAIRO_OPERATOR_DEST_ATOP; + case FT_COLR_COMPOSITE_XOR: return CAIRO_OPERATOR_XOR; + case FT_COLR_COMPOSITE_PLUS: return CAIRO_OPERATOR_ADD; + case FT_COLR_COMPOSITE_SCREEN: return CAIRO_OPERATOR_SCREEN; + case FT_COLR_COMPOSITE_OVERLAY: return CAIRO_OPERATOR_OVERLAY; + case FT_COLR_COMPOSITE_DARKEN: return CAIRO_OPERATOR_DARKEN; + case FT_COLR_COMPOSITE_LIGHTEN: return CAIRO_OPERATOR_LIGHTEN; + case FT_COLR_COMPOSITE_COLOR_DODGE: return CAIRO_OPERATOR_COLOR_DODGE; + case FT_COLR_COMPOSITE_COLOR_BURN: return CAIRO_OPERATOR_COLOR_BURN; + case FT_COLR_COMPOSITE_HARD_LIGHT: return CAIRO_OPERATOR_HARD_LIGHT; + case FT_COLR_COMPOSITE_SOFT_LIGHT: return CAIRO_OPERATOR_SOFT_LIGHT; + case FT_COLR_COMPOSITE_DIFFERENCE: return CAIRO_OPERATOR_DIFFERENCE; + case FT_COLR_COMPOSITE_EXCLUSION: return CAIRO_OPERATOR_EXCLUSION; + case FT_COLR_COMPOSITE_MULTIPLY: return CAIRO_OPERATOR_MULTIPLY; + case FT_COLR_COMPOSITE_HSL_HUE: return CAIRO_OPERATOR_HSL_HUE; + case FT_COLR_COMPOSITE_HSL_SATURATION: return CAIRO_OPERATOR_HSL_SATURATION; + case FT_COLR_COMPOSITE_HSL_COLOR: return CAIRO_OPERATOR_HSL_COLOR; + case FT_COLR_COMPOSITE_HSL_LUMINOSITY: return CAIRO_OPERATOR_HSL_LUMINOSITY; + case FT_COLR_COMPOSITE_MAX: + default: + ASSERT_NOT_REACHED; + } +} + +static cairo_extend_t +cairo_extend_from_ft_paint_extend (FT_PaintExtend extend) +{ + switch (extend) + { + case FT_COLR_PAINT_EXTEND_PAD: return CAIRO_EXTEND_PAD; + case FT_COLR_PAINT_EXTEND_REPEAT: return CAIRO_EXTEND_REPEAT; + case FT_COLR_PAINT_EXTEND_REFLECT: return CAIRO_EXTEND_REFLECT; + default: + ASSERT_NOT_REACHED; + } +} + +static cairo_status_t +draw_paint_colr_layers (cairo_colr_glyph_render_t *render, + FT_PaintColrLayers *colr_layers, + cairo_t *cr) +{ + FT_OpaquePaint paint; + cairo_status_t status = CAIRO_STATUS_SUCCESS; + +#if DEBUG_COLR + printf ("%*sDraw PaintColrLayers\n", 2 * render->level, ""); +#endif + + while (FT_Get_Paint_Layers (render->face, &colr_layers->layer_iterator, &paint)) { + cairo_push_group (cr); + status = draw_paint (render, &paint, cr); + cairo_pop_group_to_source (cr); + cairo_set_operator (cr, CAIRO_OPERATOR_OVER); + cairo_paint (cr); + + if (unlikely (status)) + break; + } + + return status; +} + +static void +get_palette_color (cairo_colr_glyph_render_t *render, + FT_ColorIndex *ci, + cairo_color_t *color, + double *colr_alpha, + cairo_bool_t *is_foreground_color) +{ + cairo_bool_t foreground = FALSE; + + if (ci->palette_index == 0xffff || ci->palette_index >= render->num_palette_entries) { + color->red = 0; + color->green = 0; + color->blue = 0; + color->alpha = 1; + foreground = TRUE; + } else { + FT_Color c = render->palette[ci->palette_index]; + color->red = c.red / 255.0; + color->green = c.green / 255.0; + color->blue = c.blue / 255.0; + color->alpha = c.alpha / 255.0; + } + + *colr_alpha = double_from_2_14 (ci->alpha); + *is_foreground_color = foreground; +} + +static cairo_status_t +draw_paint_solid (cairo_colr_glyph_render_t *render, + FT_PaintSolid *solid, + cairo_t *cr) +{ + cairo_color_t color; + double colr_alpha; + cairo_bool_t is_foreground_color; + +#if DEBUG_COLR + printf ("%*sDraw PaintSolid\n", 2 * render->level, ""); +#endif + + get_palette_color (render, &solid->color, &color, &colr_alpha, &is_foreground_color); + if (is_foreground_color) { + cairo_set_source (cr, render->foreground_marker); + cairo_paint_with_alpha (cr, colr_alpha); + } else { + cairo_set_source_rgba (cr, color.red, color.green, color.blue, color.alpha * colr_alpha); + cairo_paint (cr); + } + + return CAIRO_STATUS_SUCCESS; +} + +typedef struct _cairo_colr_color_stop { + cairo_color_t color; + double position; +} cairo_colr_color_stop_t; + +typedef struct _cairo_colr_color_line { + int n_stops; + cairo_colr_color_stop_t *stops; +} cairo_colr_color_line_t; + +static void +free_colorline (cairo_colr_color_line_t *cl) +{ + free (cl->stops); + free (cl); +} + +static int +_compare_stops (const void *p1, const void *p2) +{ + const cairo_colr_color_stop_t *c1 = p1; + const cairo_colr_color_stop_t *c2 = p2; + + if (c1->position < c2->position) + return -1; + else if (c1->position > c2->position) + return 1; + else + return 0; +} + +static cairo_colr_color_line_t * +read_colorline (cairo_colr_glyph_render_t *render, + FT_ColorLine *colorline) +{ + cairo_colr_color_line_t *cl; + FT_ColorStop stop; + int i; + double colr_alpha; + cairo_bool_t is_foreground_color; + + cl = calloc (1, sizeof (cairo_colr_color_line_t)); + if (unlikely (cl == NULL)) + return NULL; + + cl->n_stops = colorline->color_stop_iterator.num_color_stops; + cl->stops = calloc (cl->n_stops, sizeof (cairo_colr_color_stop_t)); + if (unlikely (cl->stops == NULL)) { + free (cl); + return NULL; + } + + i = 0; + while (FT_Get_Colorline_Stops (render->face, &stop, &colorline->color_stop_iterator)) { + cl->stops[i].position = double_from_16_16 (stop.stop_offset); + get_palette_color (render, &stop.color, &cl->stops[i].color, &colr_alpha, &is_foreground_color); + if (is_foreground_color) { + double red, green, blue, alpha; + if (cairo_pattern_get_rgba (render->foreground_source, + &red, &green, &blue, &alpha) == CAIRO_STATUS_SUCCESS) + { + cl->stops[i].color.red = red; + cl->stops[i].color.green = green; + cl->stops[i].color.blue = blue; + cl->stops[i].color.alpha = alpha * colr_alpha; + render->foreground_source_used = TRUE; + } + else + { + cl->stops[i].color.red = 0; + cl->stops[i].color.green = 0; + cl->stops[i].color.blue = 0; + cl->stops[i].color.alpha = colr_alpha; + } + } else { + cl->stops[i].color.alpha *= colr_alpha; + } + i++; + } + + qsort (cl->stops, cl->n_stops, sizeof (cairo_colr_color_stop_t), _compare_stops); + + return cl; +} + +static void +reduce_anchors (FT_PaintLinearGradient *gradient, + cairo_point_double_t *pp0, + cairo_point_double_t *pp1) +{ + cairo_point_double_t p0, p1, p2; + cairo_point_double_t q1, q2; + double s; + double k; + + p0.x = double_from_16_16 (gradient->p0.x); + p0.y = double_from_16_16 (gradient->p0.y); + p1.x = double_from_16_16 (gradient->p1.x); + p1.y = double_from_16_16 (gradient->p1.y); + p2.x = double_from_16_16 (gradient->p2.x); + p2.y = double_from_16_16 (gradient->p2.y); + + q2.x = p2.x - p0.x; + q2.y = p2.y - p0.y; + q1.x = p1.x - p0.x; + q1.y = p1.y - p0.y; + + s = q2.x * q2.x + q2.y * q2.y; + if (s < 0.000001) + { + pp0->x = p0.x; pp0->y = p0.y; + pp1->x = p1.x; pp1->y = p1.y; + return; + } + + k = (q2.x * q1.x + q2.y * q1.y) / s; + pp0->x = p0.x; + pp0->y = p0.y; + pp1->x = p1.x - k * q2.x; + pp1->y = p1.y - k * q2.y; +} + +static void +normalize_colorline (cairo_colr_color_line_t *cl, + double *out_min, + double *out_max) +{ + double min, max; + + *out_min = 0.; + *out_max = 1.; + + min = max = cl->stops[0].position; + for (int i = 0; i < cl->n_stops; i++) { + cairo_colr_color_stop_t *stop = &cl->stops[i]; + min = MIN (min, stop->position); + max = MAX (max, stop->position); + } + + if (min != max) { + for (int i = 0; i < cl->n_stops; i++) { + cairo_colr_color_stop_t *stop = &cl->stops[i]; + stop->position = (stop->position - min) / (max - min); + } + *out_min = min; + *out_max = max; + } +} + +static cairo_status_t +draw_paint_linear_gradient (cairo_colr_glyph_render_t *render, + FT_PaintLinearGradient *gradient, + cairo_t *cr) +{ + cairo_colr_color_line_t *cl; + cairo_point_double_t p0, p1; + cairo_point_double_t pp0, pp1; + cairo_pattern_t *pattern; + cairo_status_t status = CAIRO_STATUS_SUCCESS; + double min, max; + +#if DEBUG_COLR + printf ("%*sDraw PaintLinearGradient\n", 2 * render->level, ""); +#endif + + cl = read_colorline (render, &gradient->colorline); + if (unlikely (cl == NULL)) + return CAIRO_STATUS_NO_MEMORY; + + /* cairo only allows stop positions between 0 and 1 */ + normalize_colorline (cl, &min, &max); + reduce_anchors (gradient, &p0, &p1); + interpolate_points (&p0, &p1, min, &pp0); + interpolate_points (&p0, &p1, max, &pp1); + + pattern = cairo_pattern_create_linear (pp0.x, pp0.y, pp1.x, pp1.y); + + cairo_pattern_set_extend (pattern, cairo_extend_from_ft_paint_extend (gradient->colorline.extend)); + + for (int i = 0; i < cl->n_stops; i++) { + cairo_colr_color_stop_t *stop = &cl->stops[i]; + cairo_pattern_add_color_stop_rgba (pattern, stop->position, + stop->color.red, stop->color.green, stop->color.blue, stop->color.alpha); + } + + cairo_set_source (cr, pattern); + cairo_paint (cr); + + cairo_pattern_destroy (pattern); + + free_colorline (cl); + + return status; +} + +static cairo_status_t +draw_paint_radial_gradient (cairo_colr_glyph_render_t *render, + FT_PaintRadialGradient *gradient, + cairo_t *cr) +{ + cairo_colr_color_line_t *cl; + cairo_point_double_t start, end; + cairo_point_double_t start1, end1; + double start_radius, end_radius; + double start_radius1, end_radius1; + double min, max; + cairo_pattern_t *pattern; + cairo_status_t status = CAIRO_STATUS_SUCCESS; + +#if DEBUG_COLR + printf ("%*sDraw PaintRadialGradient\n", 2 * render->level, ""); +#endif + + cl = read_colorline (render, &gradient->colorline); + if (unlikely (cl == NULL)) + return CAIRO_STATUS_NO_MEMORY; + + start.x = double_from_16_16 (gradient->c0.x); + start.y = double_from_16_16 (gradient->c0.y); + end.x = double_from_16_16 (gradient->c1.x); + end.y = double_from_16_16 (gradient->c1.y); + + start_radius = double_from_16_16 (gradient->r0); + end_radius = double_from_16_16 (gradient->r1); + + /* cairo only allows stop positions between 0 and 1 */ + normalize_colorline (cl, &min, &max); + interpolate_points (&start, &end, min, &start1); + interpolate_points (&start, &end, max, &end1); + start_radius1 = interpolate (start_radius, end_radius, min); + end_radius1 = interpolate (start_radius, end_radius, max); + + pattern = cairo_pattern_create_radial (start1.x, start1.y, start_radius1, + end1.x, end1.y, end_radius1); + + cairo_pattern_set_extend (pattern, cairo_extend_from_ft_paint_extend (gradient->colorline.extend)); + + for (int i = 0; i < cl->n_stops; i++) { + cairo_colr_color_stop_t *stop = &cl->stops[i]; + cairo_pattern_add_color_stop_rgba (pattern, stop->position, + stop->color.red, stop->color.green, stop->color.blue, stop->color.alpha); + } + + cairo_set_source (cr, pattern); + cairo_paint (cr); + + cairo_pattern_destroy (pattern); + + free_colorline (cl); + + return status; +} + +typedef struct { + cairo_point_double_t center, p0, c0, c1, p1; + cairo_color_t color0, color1; +} cairo_colr_gradient_patch_t; + +static void +add_patch (cairo_pattern_t *pattern, + cairo_point_double_t *center, + cairo_colr_gradient_patch_t *p) +{ + cairo_mesh_pattern_begin_patch (pattern); + cairo_mesh_pattern_move_to (pattern, center->x, center->y); + cairo_mesh_pattern_line_to (pattern, p->p0.x, p->p0.y); + cairo_mesh_pattern_curve_to (pattern, + p->c0.x, p->c0.y, + p->c1.x, p->c1.y, + p->p1.x, p->p1.y); + cairo_mesh_pattern_line_to (pattern, center->x, center->y); + cairo_mesh_pattern_set_corner_color_rgba (pattern, 0, + p->color0.red, + p->color0.green, + p->color0.blue, + p->color0.alpha); + cairo_mesh_pattern_set_corner_color_rgba (pattern, 1, + p->color0.red, + p->color0.green, + p->color0.blue, + p->color0.alpha); + cairo_mesh_pattern_set_corner_color_rgba (pattern, 2, + p->color1.red, + p->color1.green, + p->color1.blue, + p->color1.alpha); + cairo_mesh_pattern_set_corner_color_rgba (pattern, 3, + p->color1.red, + p->color1.green, + p->color1.blue, + p->color1.alpha); + cairo_mesh_pattern_end_patch (pattern); +} + +#define MAX_ANGLE (M_PI / 8.) + +static void +add_sweep_gradient_patches1 (cairo_point_double_t *center, + double radius, + double a0, + cairo_color_t *c0, + double a1, + cairo_color_t *c1, + cairo_pattern_t *pattern) +{ + + int num_splits; + cairo_point_double_t p0; + cairo_color_t color0, color1; + + num_splits = ceilf (fabs (a1 - a0) / MAX_ANGLE); + p0 = (cairo_point_double_t) { cosf (a0), sinf (a0) }; + color0 = *c0; + + for (int a = 0; a < num_splits; a++) { + double k = (a + 1.) / num_splits; + double angle1; + cairo_point_double_t p1; + cairo_point_double_t A, U; + cairo_point_double_t C0, C1; + cairo_colr_gradient_patch_t patch; + + angle1 = interpolate (a0, a1, k); + interpolate_colors (c0, c1, k, &color1); + + patch.color0 = color0; + patch.color1 = color1; + + p1 = (cairo_point_double_t) { cosf (angle1), sinf (angle1) }; + patch.p0 = sum (*center, scale (p0, radius)); + patch.p1 = sum (*center, scale (p1, radius)); + + A = normalize (sum (p0, p1)); + U = (cairo_point_double_t) { -A.y, A.x }; + C0 = sum (A, scale (U, dot (difference (p0, A), p0) / dot (U, p0))); + C1 = sum (A, scale (U, dot (difference (p1, A), p1) / dot (U, p1))); + patch.c0 = sum (*center, scale (sum (C0, scale (difference (C0, p0), 0.33333)), radius)); + patch.c1 = sum (*center, scale (sum (C1, scale (difference (C1, p1), 0.33333)), radius)); + + add_patch (pattern, center, &patch); + + p0 = p1; + color0 = color1; + } +} + +static void +add_sweep_gradient_patches (cairo_colr_color_line_t *cl, + cairo_extend_t extend, + cairo_point_double_t *center, + double radius, + double start_angle, + double end_angle, + cairo_pattern_t *pattern) +{ + double *angles; + cairo_color_t color0, color1; + + if (start_angle == end_angle) { + if (extend == CAIRO_EXTEND_PAD) { + if (start_angle > 0) + add_sweep_gradient_patches1 (center, radius, + 0., &cl->stops[0].color, + start_angle, &cl->stops[0].color, + pattern); + if (end_angle < 2 * M_PI) + add_sweep_gradient_patches1 (center, radius, + end_angle, &cl->stops[cl->n_stops - 1].color, + 2 * M_PI, &cl->stops[cl->n_stops - 1].color, + pattern); + } + return; + } + + assert (start_angle != end_angle); + + angles = alloca (sizeof (double) * cl->n_stops); + + for (int i = 0; i < cl->n_stops; i++) + angles[i] = start_angle + cl->stops[i].position * (end_angle - start_angle); + + /* handle directions */ + if (end_angle < start_angle) { + for (int i = 0; i < cl->n_stops - 1 - i; i++) { + cairo_colr_color_stop_t stop = cl->stops[i]; + double a = angles[i]; + cl->stops[i] = cl->stops[cl->n_stops - 1 - i]; + cl->stops[cl->n_stops - 1 - i] = stop; + angles[i] = angles[cl->n_stops - 1 - i]; + angles[cl->n_stops - 1 - i] = a; + } + } + + if (extend == CAIRO_EXTEND_PAD) + { + int pos; + + color0 = cl->stops[0].color; + for (pos = 0; pos < cl->n_stops; pos++) { + if (angles[pos] >= 0) { + if (pos > 0) { + double k = (0 - angles[pos - 1]) / (angles[pos] - angles[pos - 1]); + interpolate_colors (&cl->stops[pos - 1].color, &cl->stops[pos].color, k, &color0); + } + break; + } + } + if (pos == cl->n_stops) { + /* everything is below 0 */ + color0 = cl->stops[cl->n_stops - 1].color; + add_sweep_gradient_patches1 (center, radius, + 0., &color0, + 2 * M_PI, &color0, + pattern); + return; + } + + add_sweep_gradient_patches1 (center, radius, + 0., &color0, + angles[pos], &cl->stops[pos].color, + pattern); + + for (pos++; pos < cl->n_stops; pos++) { + if (angles[pos] <= 2 * M_PI) { + add_sweep_gradient_patches1 (center, radius, + angles[pos - 1], &cl->stops[pos - 1].color, + angles[pos], &cl->stops[pos].color, + pattern); + } else { + double k = (2 * M_PI - angles[pos - 1]) / (angles[pos] - angles[pos - 1]); + interpolate_colors (&cl->stops[pos - 1].color, &cl->stops[pos].color, k, &color1); + add_sweep_gradient_patches1 (center, radius, + angles[pos - 1], &cl->stops[pos - 1].color, + 2 * M_PI, &color1, + pattern); + break; + } + } + + if (pos == cl->n_stops) { + /* everything is below 2*M_PI */ + color0 = cl->stops[cl->n_stops - 1].color; + add_sweep_gradient_patches1 (center, radius, + angles[cl->n_stops - 1], &color0, + 2 * M_PI, &color0, + pattern); + return; + } + } else { + int k; + double span; + + span = angles[cl->n_stops - 1] - angles[0]; + k = 0; + if (angles[0] >= 0) { + double ss = angles[0]; + while (ss > 0) { + if (span > 0) { + ss -= span; + k--; + } else { + ss += span; + k++; + } + } + } + else if (angles[0] < 0) + { + double ee = angles[cl->n_stops - 1]; + while (ee < 0) { + if (span > 0) { + ee += span; + k++; + } else { + ee -= span; + k--; + } + } + } + + //assert (angles[0] + k * span <= 0 && 0 < angles[cl->n_stops - 1] + k * span); + + for (int l = k; TRUE; l++) { + for (int i = 1; i < cl->n_stops; i++) { + double a0, a1; + cairo_color_t *c0, *c1; + + if ((l % 2 != 0) && (extend == CAIRO_EXTEND_REFLECT)) { + a0 = angles[0] + angles[cl->n_stops - 1] - angles[cl->n_stops - 1 - (i-1)] + l * span; + a1 = angles[0] + angles[cl->n_stops - 1] - angles[cl->n_stops - 1 - i] + l * span; + c0 = &cl->stops[cl->n_stops - 1 - (i-1)].color; + c1 = &cl->stops[cl->n_stops - 1 - i].color; + } else { + a0 = angles[i-1] + l * span; + a1 = angles[i] + l * span; + c0 = &cl->stops[i-1].color; + c1 = &cl->stops[i].color; + } + + if (a1 < 0) + continue; + + if (a0 < 0) { + cairo_color_t color; + double f = (0 - a0)/(a1 - a0); + interpolate_colors (c0, c1, f, &color); + add_sweep_gradient_patches1 (center, radius, + 0, &color, + a1, c1, + pattern); + } else if (a1 >= 2 * M_PI) { + cairo_color_t color; + double f = (2 * M_PI - a0)/(a1 - a0); + interpolate_colors (c0, c1, f, &color); + add_sweep_gradient_patches1 (center, radius, + a0, c0, + 2 * M_PI, &color, + pattern); + return; + } else { + add_sweep_gradient_patches1 (center, radius, + a0, c0, + a1, c1, + pattern); + } + } + } + } +} + +static cairo_status_t +draw_paint_sweep_gradient (cairo_colr_glyph_render_t *render, + FT_PaintSweepGradient *gradient, + cairo_t *cr) +{ + cairo_colr_color_line_t *cl; + cairo_point_double_t center; + double start_angle, end_angle; + double x1, y1, x2, y2; + double max_x, max_y, R; + cairo_pattern_t *pattern; + cairo_extend_t extend; + +#if DEBUG_COLR + printf ("%*sDraw PaintSweepGradient\n", 2 * render->level, ""); +#endif + + cl = read_colorline (render, &gradient->colorline); + if (unlikely (cl == NULL)) + return CAIRO_STATUS_NO_MEMORY; + + center.x = double_from_16_16 (gradient->center.x); + center.y = double_from_16_16 (gradient->center.y); + start_angle = (double_from_16_16 (gradient->start_angle) + 1) * M_PI; + end_angle = (double_from_16_16 (gradient->end_angle) + 1) * M_PI; + + pattern = cairo_pattern_create_mesh (); + + cairo_clip_extents (cr, &x1, &y1, &x2, &y2); + max_x = MAX ((x1 - center.x) * (x1 - center.x), (x2 - center.x) * (x2 - center.x)); + max_y = MAX ((y1 - center.y) * (y1 - center.y), (y2 - center.y) * (y2 - center.y)); + R = sqrt (max_x + max_y); + + extend = cairo_extend_from_ft_paint_extend (gradient->colorline.extend); + + add_sweep_gradient_patches (cl, extend, ¢er, R, start_angle, end_angle, pattern); + + cairo_set_source (cr, pattern); + cairo_paint (cr); + + cairo_pattern_destroy (pattern); + + free_colorline (cl); + + return CAIRO_STATUS_SUCCESS; +} + +static cairo_status_t +draw_paint_glyph (cairo_colr_glyph_render_t *render, + FT_PaintGlyph *glyph, + cairo_t *cr) +{ + cairo_path_fixed_t *path_fixed; + cairo_path_t *path; + cairo_status_t status = CAIRO_STATUS_SUCCESS; + FT_Error error; + +#if DEBUG_COLR + printf ("%*sDraw PaintGlyph\n", 2 * render->level, ""); +#endif + + error = FT_Load_Glyph (render->face, glyph->glyphID, FT_LOAD_DEFAULT); + status = _cairo_ft_to_cairo_error (error); + if (unlikely (status)) + return status; + + status = _cairo_ft_face_decompose_glyph_outline (render->face, &path_fixed); + if (unlikely (status)) + return status; + + cairo_save (cr); + cairo_identity_matrix (cr); + path = _cairo_path_create (path_fixed, cr); + _cairo_path_fixed_destroy (path_fixed); + cairo_restore (cr); + + cairo_save (cr); + + cairo_new_path (cr); + cairo_append_path (cr, path); + cairo_path_destroy (path); + cairo_clip (cr); + + status = draw_paint (render, &glyph->paint, cr); + + cairo_restore (cr); + + return status; +} + +static cairo_status_t draw_colr_glyph (cairo_colr_glyph_render_t *render, + unsigned long glyph, + FT_Color_Root_Transform root, + cairo_t *cr); + +static cairo_status_t +draw_paint_colr_glyph (cairo_colr_glyph_render_t *render, + FT_PaintColrGlyph *colr_glyph, + cairo_t *cr) +{ +#if DEBUG_COLR + printf ("%*sDraw PaintColrGlyph\n", 2 * render->level, ""); +#endif + + return draw_colr_glyph (render, colr_glyph->glyphID, FT_COLOR_NO_ROOT_TRANSFORM, cr); +} + +static cairo_status_t +draw_paint_transform (cairo_colr_glyph_render_t *render, + FT_PaintTransform *transform, + cairo_t *cr) +{ + cairo_matrix_t t; + cairo_status_t status = CAIRO_STATUS_SUCCESS; + +#if DEBUG_COLR + printf ("%*sDraw PaintTransform\n", 2 * render->level, ""); +#endif + + cairo_matrix_init (&t, + double_from_16_16 (transform->affine.xx), + double_from_16_16 (transform->affine.yx), + double_from_16_16 (transform->affine.xy), + double_from_16_16 (transform->affine.yy), + double_from_16_16 (transform->affine.dx), + double_from_16_16 (transform->affine.dy)); + + cairo_save (cr); + + cairo_transform (cr, &t); + status = draw_paint (render, &transform->paint, cr); + + cairo_restore (cr); + + return status; +} + +static cairo_status_t +draw_paint_translate (cairo_colr_glyph_render_t *render, + FT_PaintTranslate *translate, + cairo_t *cr) +{ + cairo_status_t status = CAIRO_STATUS_SUCCESS; + +#if DEBUG_COLR + printf ("%*sDraw PaintTranslate\n", 2 * render->level, ""); +#endif + + cairo_save (cr); + + cairo_translate (cr, double_from_16_16 (translate->dx), double_from_16_16 (translate->dy)); + status = draw_paint (render, &translate->paint, cr); + + cairo_restore (cr); + + return status; +} + +static cairo_status_t +draw_paint_rotate (cairo_colr_glyph_render_t *render, + FT_PaintRotate *rotate, + cairo_t *cr) +{ + cairo_status_t status = CAIRO_STATUS_SUCCESS; + +#if DEBUG_COLR + printf ("%*sDraw PaintRotate\n", 2 * render->level, ""); +#endif + + cairo_save (cr); + + cairo_translate (cr, double_from_16_16 (rotate->center_x), double_from_16_16 (rotate->center_y)); + cairo_rotate (cr, double_from_16_16 (rotate->angle) * M_PI); + cairo_translate (cr, - double_from_16_16 (rotate->center_x), - double_from_16_16 (rotate->center_y)); + status = draw_paint (render, &rotate->paint, cr); + + cairo_restore (cr); + + return status; +} + +static cairo_status_t +draw_paint_scale (cairo_colr_glyph_render_t *render, + FT_PaintScale *scale, + cairo_t *cr) +{ + cairo_status_t status = CAIRO_STATUS_SUCCESS; + +#if DEBUG_COLR + printf ("%*sDraw PaintScale\n", 2 * render->level, ""); +#endif + + cairo_save (cr); + + cairo_translate (cr, double_from_16_16 (scale->center_x), double_from_16_16 (scale->center_y)); + cairo_scale (cr, double_from_16_16 (scale->scale_x), double_from_16_16 (scale->scale_y)); + cairo_translate (cr, - double_from_16_16 (scale->center_x), - double_from_16_16 (scale->center_y)); + status = draw_paint (render, &scale->paint, cr); + + cairo_restore (cr); + + return status; +} + +static cairo_status_t +draw_paint_skew (cairo_colr_glyph_render_t *render, + FT_PaintSkew *skew, + cairo_t *cr) +{ + cairo_matrix_t s; + cairo_status_t status = CAIRO_STATUS_SUCCESS; + +#if DEBUG_COLR + printf ("%*sDraw PaintSkew\n", 2 * render->level, ""); +#endif + + cairo_save (cr); + + cairo_translate (cr, double_from_16_16 (skew->center_x), double_from_16_16 (skew->center_y)); + cairo_matrix_init (&s, 1., tan (double_from_16_16 (skew->y_skew_angle) * M_PI), - tan (double_from_16_16 (skew->x_skew_angle) * M_PI), 1., 0., 0.); + cairo_transform (cr, &s); + cairo_translate (cr, - double_from_16_16 (skew->center_x), - double_from_16_16 (skew->center_y)); + status = draw_paint (render, &skew->paint, cr); + + cairo_restore (cr); + + return status; +} + +static cairo_status_t +draw_paint_composite (cairo_colr_glyph_render_t *render, + FT_PaintComposite *composite, + cairo_t *cr) +{ + cairo_status_t status = CAIRO_STATUS_SUCCESS; + + +#if DEBUG_COLR + printf ("%*sDraw PaintComposite\n", 2 * render->level, ""); +#endif + + cairo_save (cr); + + status = draw_paint (render, &composite->backdrop_paint, cr); + if (unlikely (status)) { + cairo_pattern_destroy (cairo_pop_group (cr)); + goto cleanup; + } + + cairo_push_group (cr); + status = draw_paint (render, &composite->source_paint, cr); + if (unlikely (status)) { + cairo_pattern_destroy (cairo_pop_group (cr)); + cairo_pattern_destroy (cairo_pop_group (cr)); + goto cleanup; + } + + cairo_pop_group_to_source (cr); + cairo_set_operator (cr, cairo_operator_from_ft_composite_mode (composite->composite_mode)); + cairo_paint (cr); + + cleanup: + cairo_restore (cr); + + return status; +} + +static cairo_status_t +draw_paint (cairo_colr_glyph_render_t *render, + FT_OpaquePaint *paint, + cairo_t *cr) +{ + FT_COLR_Paint p; + FT_Size orig_size; + FT_Size unscaled_size; + FT_Matrix orig_transform; + FT_Vector orig_delta; + cairo_status_t status = CAIRO_STATUS_SUCCESS; + + assert (cairo_status (cr) == CAIRO_STATUS_SUCCESS); + + if (!FT_Get_Paint (render->face, *paint, &p)) + return CAIRO_STATUS_NO_MEMORY; + + if (render->level == 0) { + /* Now that the FT_Get_Paint call has applied the root transform, + * make the face unscaled and untransformed, so we can load glyph + * contours. + */ + + FT_Matrix transform; + FT_Vector delta; + + orig_size = render->face->size; + FT_New_Size (render->face, &unscaled_size); + FT_Activate_Size (unscaled_size); + FT_Set_Char_Size (render->face, render->face->units_per_EM << 6, 0, 0, 0); + + transform.xx = transform.yy = 1 << 16; + transform.xy = transform.yx = 0; + delta.x = delta.y = 0; + + FT_Get_Transform (render->face, &orig_transform, &orig_delta); + FT_Set_Transform (render->face, &transform, &delta); + } + + render->level++; + + switch (p.format) { + case FT_COLR_PAINTFORMAT_COLR_LAYERS: + status = draw_paint_colr_layers (render, &p.u.colr_layers, cr); + break; + case FT_COLR_PAINTFORMAT_SOLID: + status = draw_paint_solid (render, &p.u.solid, cr); + break; + case FT_COLR_PAINTFORMAT_LINEAR_GRADIENT: + status = draw_paint_linear_gradient (render, &p.u.linear_gradient, cr); + break; + case FT_COLR_PAINTFORMAT_RADIAL_GRADIENT: + status = draw_paint_radial_gradient (render, &p.u.radial_gradient, cr); + break; + case FT_COLR_PAINTFORMAT_SWEEP_GRADIENT: + status = draw_paint_sweep_gradient (render, &p.u.sweep_gradient, cr); + break; + case FT_COLR_PAINTFORMAT_GLYPH: + status = draw_paint_glyph (render, &p.u.glyph, cr); + break; + case FT_COLR_PAINTFORMAT_COLR_GLYPH: + status = draw_paint_colr_glyph (render, &p.u.colr_glyph, cr); + break; + case FT_COLR_PAINTFORMAT_TRANSFORM: + status = draw_paint_transform (render, &p.u.transform, cr); + break; + case FT_COLR_PAINTFORMAT_TRANSLATE: + status = draw_paint_translate (render, &p.u.translate, cr); + break; + case FT_COLR_PAINTFORMAT_ROTATE: + status = draw_paint_rotate (render, &p.u.rotate, cr); + break; + case FT_COLR_PAINTFORMAT_SCALE: + status = draw_paint_scale (render, &p.u.scale, cr); + break; + case FT_COLR_PAINTFORMAT_SKEW: + status = draw_paint_skew (render, &p.u.skew, cr); + break; + case FT_COLR_PAINTFORMAT_COMPOSITE: + status = draw_paint_composite (render, &p.u.composite, cr); + break; + case FT_COLR_PAINT_FORMAT_MAX: + case FT_COLR_PAINTFORMAT_UNSUPPORTED: + default: + ASSERT_NOT_REACHED; + } + + render->level--; + + if (render->level == 0) { + FT_Set_Transform (render->face, &orig_transform, &orig_delta); + FT_Activate_Size (orig_size); + FT_Done_Size (unscaled_size); + } + + return status; +} + +static cairo_status_t +draw_colr_glyph (cairo_colr_glyph_render_t *render, + unsigned long glyph, + FT_Color_Root_Transform root, + cairo_t *cr) +{ + FT_OpaquePaint paint = { NULL, 0 }; + FT_ClipBox box; + cairo_status_t status = CAIRO_STATUS_SUCCESS; + + cairo_save (cr); + + if (FT_Get_Color_Glyph_ClipBox (render->face, glyph, &box)) { + double xmin, ymin, xmax, ymax; + + xmin = double_from_26_6 (box.bottom_left.x); + ymin = double_from_26_6 (box.bottom_left.y); + xmax = double_from_26_6 (box.top_right.x); + ymax = double_from_26_6 (box.top_right.y); + + cairo_new_path (cr); + cairo_rectangle (cr, xmin, ymin, xmax - xmin, ymax - ymin); + cairo_clip (cr); + } + + if (FT_Get_Color_Glyph_Paint (render->face, glyph, root, &paint)) + status = draw_paint (render, &paint, cr); + + cairo_restore (cr); + + return status; +} + +/* Create an image surface and render the glyph onto it, + * using the given colors. + */ +cairo_status_t +_cairo_render_colr_v1_glyph (FT_Face face, + unsigned long glyph, + FT_Color *palette, + int num_palette_entries, + cairo_t *cr, + cairo_pattern_t *foreground_source, + cairo_bool_t *foreground_source_used) +{ + cairo_status_t status = CAIRO_STATUS_SUCCESS; + cairo_colr_glyph_render_t colr_render; + +#if DEBUG_COLR + printf ("_cairo_render_colr_glyph glyph index: %ld\n", glyph); +#endif + + colr_render.face = face; + colr_render.palette = palette; + colr_render.num_palette_entries = num_palette_entries; + colr_render.foreground_marker = _cairo_pattern_create_foreground_marker (); + colr_render.foreground_source = cairo_pattern_reference (foreground_source);; + colr_render.foreground_source_used = FALSE; + colr_render.level = 0; + + status = draw_colr_glyph (&colr_render, + glyph, + FT_COLOR_INCLUDE_ROOT_TRANSFORM, + cr); + + cairo_pattern_destroy (colr_render.foreground_marker); + cairo_pattern_destroy (colr_render.foreground_source); + *foreground_source_used = colr_render.foreground_source_used; + + return status; +} + +#endif /* HAVE_FT_COLR_V1 */ diff --git a/gfx/cairo/cairo/src/cairo-compiler-private.h b/gfx/cairo/cairo/src/cairo-compiler-private.h index 4562bea666..28455f99d1 100644 --- a/gfx/cairo/cairo/src/cairo-compiler-private.h +++ b/gfx/cairo/cairo/src/cairo-compiler-private.h @@ -40,9 +40,10 @@ #include "cairo.h" -#if HAVE_CONFIG_H #include "config.h" -#endif + +#include <stddef.h> /* size_t */ +#include <stdint.h> /* SIZE_MAX */ /* Size in bytes of buffer to use off the stack per functions. * Mostly used by text functions. For larger allocations, they'll @@ -53,66 +54,18 @@ #define CAIRO_STACK_ARRAY_LENGTH(T) (CAIRO_STACK_BUFFER_SIZE / sizeof(T)) -/* - * The goal of this block is to define the following macros for - * providing faster linkage to functions in the public API for calls - * from within cairo. - * - * slim_hidden_proto(f) - * slim_hidden_proto_no_warn(f) - * - * Declares `f' as a library internal function and hides the - * function from the global symbol table. This macro must be - * expanded after `f' has been declared with a prototype but before - * any calls to the function are seen by the compiler. The no_warn - * variant inhibits warnings about the return value being unused at - * call sites. The macro works by renaming `f' to an internal name - * in the symbol table and hiding that. As far as cairo internal - * calls are concerned they're calling a library internal function - * and thus don't need to bounce via the procedure linkage table (PLT). - * - * slim_hidden_def(f) - * - * Exports `f' back to the global symbol table. This macro must be - * expanded right after the function definition and only for symbols - * hidden previously with slim_hidden_proto(). The macro works by - * adding a global entry to the symbol table which points at the - * internal name of `f' created by slim_hidden_proto(). - * - * Functions in the public API which aren't called by the library - * don't need to be hidden and re-exported using the slim hidden - * macros. - */ -#if __GNUC__ >= 3 && defined(__ELF__) && !defined(__sun) -# define slim_hidden_proto(name) slim_hidden_proto1(name, slim_hidden_int_name(name)) cairo_private -# define slim_hidden_proto_no_warn(name) slim_hidden_proto1(name, slim_hidden_int_name(name)) cairo_private_no_warn -# 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)) -# define slim_hidden_def1(name, internal) \ - extern __typeof (name) EXT_##name __asm__(slim_hidden_asmname(name)) \ - __attribute__((__alias__(slim_hidden_asmname(internal)))) -# define slim_hidden_ulp slim_hidden_ulp1(__USER_LABEL_PREFIX__) -# define slim_hidden_ulp1(x) slim_hidden_ulp2(x) -# define slim_hidden_ulp2(x) #x -# define slim_hidden_asmname(name) slim_hidden_asmname1(name) -# define slim_hidden_asmname1(name) slim_hidden_ulp #name -#else -# define slim_hidden_proto(name) int _cairo_dummy_prototype(void) -# define slim_hidden_proto_no_warn(name) int _cairo_dummy_prototype(void) -# define slim_hidden_def(name) int _cairo_dummy_prototype(void) -#endif - #if __GNUC__ > 2 || (__GNUC__ == 2 && __GNUC_MINOR__ > 4) -#define CAIRO_PRINTF_FORMAT(fmt_index, va_index) \ +#ifdef __MINGW32__ +#define CAIRO_PRINTF_FORMAT(fmt_index, va_index) \ + __attribute__((__format__(__MINGW_PRINTF_FORMAT, fmt_index, va_index))) +#else +#define CAIRO_PRINTF_FORMAT(fmt_index, va_index) \ __attribute__((__format__(__printf__, fmt_index, va_index))) +#endif #else #define CAIRO_PRINTF_FORMAT(fmt_index, va_index) #endif -/* slim_internal.h */ #define CAIRO_HAS_HIDDEN_SYMBOLS 1 #if (__GNUC__ > 3 || (__GNUC__ == 3 && __GNUC_MINOR__ >= 3)) && \ (defined(__ELF__) || defined(__APPLE__)) && \ @@ -128,6 +81,7 @@ #ifndef WARN_UNUSED_RESULT #define WARN_UNUSED_RESULT #endif + /* Add attribute(warn_unused_result) if supported */ #define cairo_warn WARN_UNUSED_RESULT #define cairo_private cairo_private_no_warn cairo_warn @@ -197,6 +151,9 @@ #if (defined(__WIN32__) && !defined(__WINE__)) || defined(_MSC_VER) #define access _access +#ifndef R_OK +#define R_OK 4 +#endif #define fdopen _fdopen #define hypot _hypot #define pclose _pclose @@ -243,4 +200,55 @@ #define inline __inline__ #endif +/* size_t add/multiply with overflow check. + * + * These _cairo_fallback_*_size_t_overflow() functions are always defined + * to allow them to be tested in the test suite. They are used + * if no compiler builtin is available. + */ +static cairo_always_inline cairo_bool_t +_cairo_fallback_add_size_t_overflow(size_t a, size_t b, size_t *c) +{ + if (b > SIZE_MAX - a) + return 1; + + *c = a + b; + return 0; +} + +static cairo_always_inline cairo_bool_t +_cairo_fallback_mul_size_t_overflow(size_t a, size_t b, size_t *c) +{ + if (b != 0 && a > SIZE_MAX / b) + return 1; + + *c = a * b; + return 0; +} + +/* Clang defines __GNUC__ so check clang builtins before gcc. + * MSVC does not support feature macros so hide the __has_builtin inside the #if __clang__ block + */ +#ifdef __clang__ +#if defined(__has_builtin) && __has_builtin(__builtin_add_overflow) +#define _cairo_add_size_t_overflow(a, b, c) __builtin_add_overflow((size_t)(a), (size_t)(b), (size_t*)(c)) +#define _cairo_mul_size_t_overflow(a, b, c) __builtin_mul_overflow((size_t)(a), (size_t)(b), (size_t*)(c)) +#endif +#elif __GNUC__ >= 8 || (__GNUC__ >= 5 && (INTPTR_MAX == INT64_MAX)) +/* Overflow builtins are available in gcc 5 but the 32-bit version is broken on gcc < 8. + * https://gcc.gnu.org/bugzilla/show_bug.cgi?id=82274 + */ +#define _cairo_add_size_t_overflow(a, b, c) __builtin_add_overflow((size_t)(a), (size_t)(b), (size_t*)(c)) +#define _cairo_mul_size_t_overflow(a, b, c) __builtin_mul_overflow((size_t)(a), (size_t)(b), (size_t*)(c)) +#elif defined(_MSC_VER) && defined(HAVE_INTSAFE_H) +#include <intsafe.h> +#define _cairo_add_size_t_overflow(a,b,c) (SizeTAdd((size_t)(a), (size_t)(b), (size_t*)(c)) != S_OK) +#define _cairo_mul_size_t_overflow(a,b,c) (SizeTMult((size_t)(a), (size_t)(b), (size_t*)(c)) != S_OK) +#endif + +#ifndef _cairo_add_size_t_overflow +#define _cairo_add_size_t_overflow _cairo_fallback_add_size_t_overflow +#define _cairo_mul_size_t_overflow _cairo_fallback_mul_size_t_overflow +#endif + #endif diff --git a/gfx/cairo/cairo/src/cairo-composite-rectangles.c b/gfx/cairo/cairo/src/cairo-composite-rectangles.c index f102eddbce..80e23f23ae 100644 --- a/gfx/cairo/cairo/src/cairo-composite-rectangles.c +++ b/gfx/cairo/cairo/src/cairo-composite-rectangles.c @@ -44,7 +44,11 @@ void _cairo_composite_rectangles_fini (cairo_composite_rectangles_t *extents) { + /* If adding further free() code here, make sure those fields are inited by + * _cairo_composite_rectangles_init IN ALL CASES + */ _cairo_clip_destroy (extents->clip); + extents->clip = NULL; } static void @@ -76,14 +80,16 @@ _cairo_composite_rectangles_init (cairo_composite_rectangles_t *extents, const cairo_pattern_t *source, const cairo_clip_t *clip) { + /* Always set the clip so that a _cairo_composite_rectangles_init can ALWAYS be + * balanced by a _cairo_composite_rectangles_fini */ + extents->clip = NULL; + if (_cairo_clip_is_all_clipped (clip)) return FALSE; - extents->surface = surface; extents->op = op; _cairo_surface_get_extents (surface, &extents->destination); - extents->clip = NULL; extents->unbounded = extents->destination; if (clip && ! _cairo_rectangle_intersect (&extents->unbounded, @@ -122,25 +128,28 @@ _cairo_composite_rectangles_init_for_paint (cairo_composite_rectangles_t *extent if (! _cairo_composite_rectangles_init (extents, surface, op, source, clip)) { - return CAIRO_INT_STATUS_NOTHING_TO_DO; + goto NOTHING_TO_DO; } extents->mask = extents->destination; extents->clip = _cairo_clip_reduce_for_composite (clip, extents); if (_cairo_clip_is_all_clipped (extents->clip)) - return CAIRO_INT_STATUS_NOTHING_TO_DO; + goto NOTHING_TO_DO; if (! _cairo_rectangle_intersect (&extents->unbounded, _cairo_clip_get_extents (extents->clip))) - return CAIRO_INT_STATUS_NOTHING_TO_DO; + goto NOTHING_TO_DO; if (extents->source_pattern.base.type != CAIRO_PATTERN_TYPE_SOLID) _cairo_pattern_sampled_area (&extents->source_pattern.base, &extents->bounded, &extents->source_sample_area); - return CAIRO_STATUS_SUCCESS; + return CAIRO_INT_STATUS_SUCCESS; +NOTHING_TO_DO: + _cairo_composite_rectangles_fini(extents); + return CAIRO_INT_STATUS_NOTHING_TO_DO; } static cairo_int_status_t @@ -188,7 +197,7 @@ _cairo_composite_rectangles_intersect (cairo_composite_rectangles_t *extents, } } - return CAIRO_STATUS_SUCCESS; + return CAIRO_INT_STATUS_SUCCESS; } cairo_int_status_t @@ -323,9 +332,11 @@ _cairo_composite_rectangles_init_for_mask (cairo_composite_rectangles_t *extents const cairo_pattern_t *mask, const cairo_clip_t *clip) { + cairo_int_status_t status; if (! _cairo_composite_rectangles_init (extents, surface, op, source, clip)) { + _cairo_composite_rectangles_fini(extents); return CAIRO_INT_STATUS_NOTHING_TO_DO; } @@ -333,7 +344,11 @@ _cairo_composite_rectangles_init_for_mask (cairo_composite_rectangles_t *extents _cairo_composite_reduce_pattern (mask, &extents->mask_pattern); _cairo_pattern_get_extents (&extents->mask_pattern.base, &extents->mask, surface->is_vector); - return _cairo_composite_rectangles_intersect (extents, clip); + status = _cairo_composite_rectangles_intersect (extents, clip); + if(status == CAIRO_INT_STATUS_NOTHING_TO_DO) { + _cairo_composite_rectangles_fini(extents); + } + return status; } cairo_int_status_t @@ -346,15 +361,21 @@ _cairo_composite_rectangles_init_for_stroke (cairo_composite_rectangles_t *exten const cairo_matrix_t *ctm, const cairo_clip_t *clip) { + cairo_int_status_t status; if (! _cairo_composite_rectangles_init (extents, surface, op, source, clip)) { + _cairo_composite_rectangles_fini(extents); return CAIRO_INT_STATUS_NOTHING_TO_DO; } _cairo_path_fixed_approximate_stroke_extents (path, style, ctm, surface->is_vector, &extents->mask); - return _cairo_composite_rectangles_intersect (extents, clip); + status = _cairo_composite_rectangles_intersect (extents, clip); + if(status == CAIRO_INT_STATUS_NOTHING_TO_DO) { + _cairo_composite_rectangles_fini(extents); + } + return status; } cairo_int_status_t @@ -365,15 +386,21 @@ _cairo_composite_rectangles_init_for_fill (cairo_composite_rectangles_t *extents const cairo_path_fixed_t *path, const cairo_clip_t *clip) { + cairo_int_status_t status; if (! _cairo_composite_rectangles_init (extents, surface, op, source, clip)) { + _cairo_composite_rectangles_fini(extents); return CAIRO_INT_STATUS_NOTHING_TO_DO; } _cairo_path_fixed_approximate_fill_extents (path, &extents->mask); - return _cairo_composite_rectangles_intersect (extents, clip); + status = _cairo_composite_rectangles_intersect (extents, clip); + if(status == CAIRO_INT_STATUS_NOTHING_TO_DO) { + _cairo_composite_rectangles_fini(extents); + } + return status; } cairo_int_status_t @@ -384,14 +411,20 @@ _cairo_composite_rectangles_init_for_polygon (cairo_composite_rectangles_t *exte const cairo_polygon_t *polygon, const cairo_clip_t *clip) { + cairo_int_status_t status; if (! _cairo_composite_rectangles_init (extents, surface, op, source, clip)) { + _cairo_composite_rectangles_fini(extents); return CAIRO_INT_STATUS_NOTHING_TO_DO; } _cairo_box_round_to_rectangle (&polygon->extents, &extents->mask); - return _cairo_composite_rectangles_intersect (extents, clip); + status = _cairo_composite_rectangles_intersect (extents, clip); + if(status == CAIRO_INT_STATUS_NOTHING_TO_DO) { + _cairo_composite_rectangles_fini(extents); + } + return status; } cairo_int_status_t @@ -403,16 +436,22 @@ _cairo_composite_rectangles_init_for_boxes (cairo_composite_rectangles_t *extent const cairo_clip_t *clip) { cairo_box_t box; + cairo_int_status_t status; if (! _cairo_composite_rectangles_init (extents, surface, op, source, clip)) { + _cairo_composite_rectangles_fini(extents); return CAIRO_INT_STATUS_NOTHING_TO_DO; } _cairo_boxes_extents (boxes, &box); _cairo_box_round_to_rectangle (&box, &extents->mask); - return _cairo_composite_rectangles_intersect (extents, clip); + status = _cairo_composite_rectangles_intersect (extents, clip); + if(status == CAIRO_INT_STATUS_NOTHING_TO_DO) { + _cairo_composite_rectangles_fini(extents); + } + return status; } cairo_int_status_t @@ -427,29 +466,21 @@ _cairo_composite_rectangles_init_for_glyphs (cairo_composite_rectangles_t *exten cairo_bool_t *overlap) { cairo_status_t status; + cairo_int_status_t int_status; - if (! _cairo_composite_rectangles_init (extents, surface, op, source, clip)) + if (! _cairo_composite_rectangles_init (extents, surface, op, source, clip)) { + _cairo_composite_rectangles_fini(extents); return CAIRO_INT_STATUS_NOTHING_TO_DO; - - /* Computing the exact bbox and the overlap is expensive. - * First perform a cheap test to see if the glyphs are all clipped out. - */ - if (extents->is_bounded & CAIRO_OPERATOR_BOUND_BY_MASK && - _cairo_scaled_font_glyph_approximate_extents (scaled_font, - glyphs, num_glyphs, - &extents->mask)) - { - if (! _cairo_rectangle_intersect (&extents->bounded, &extents->mask)) - return CAIRO_INT_STATUS_NOTHING_TO_DO; } status = _cairo_scaled_font_glyph_device_extents (scaled_font, glyphs, num_glyphs, &extents->mask, overlap); - if (unlikely (status)) + if (unlikely (status)) { + _cairo_composite_rectangles_fini(extents); return status; - + } if (overlap && *overlap && scaled_font->options.antialias == CAIRO_ANTIALIAS_NONE && _cairo_pattern_is_opaque_solid (&extents->source_pattern.base)) @@ -457,7 +488,11 @@ _cairo_composite_rectangles_init_for_glyphs (cairo_composite_rectangles_t *exten *overlap = FALSE; } - return _cairo_composite_rectangles_intersect (extents, clip); + int_status = _cairo_composite_rectangles_intersect (extents, clip); + if (int_status == CAIRO_INT_STATUS_NOTHING_TO_DO) { + _cairo_composite_rectangles_fini(extents); + } + return int_status; } cairo_bool_t diff --git a/gfx/cairo/cairo/src/cairo-compositor.c b/gfx/cairo/cairo/src/cairo-compositor.c index 6f35ee04f9..606043cdf9 100644 --- a/gfx/cairo/cairo/src/cairo-compositor.c +++ b/gfx/cairo/cairo/src/cairo-compositor.c @@ -122,18 +122,18 @@ _cairo_compositor_mask (const cairo_compositor_t *compositor, return status; } -cairo_int_status_t -_cairo_compositor_stroke (const cairo_compositor_t *compositor, - cairo_surface_t *surface, - cairo_operator_t op, - const cairo_pattern_t *source, - const cairo_path_fixed_t *path, - const cairo_stroke_style_t *style, - const cairo_matrix_t *ctm, - const cairo_matrix_t *ctm_inverse, - double tolerance, - cairo_antialias_t antialias, - const cairo_clip_t *clip) +static cairo_int_status_t +_cairo_compositor_stroke_impl (const cairo_compositor_t *compositor, + cairo_surface_t *surface, + cairo_operator_t op, + const cairo_pattern_t *source, + const cairo_path_fixed_t *path, + const cairo_stroke_style_t *style, + const cairo_matrix_t *ctm, + const cairo_matrix_t *ctm_inverse, + double tolerance, + cairo_antialias_t antialias, + const cairo_clip_t *clip) { cairo_composite_rectangles_t extents; cairo_int_status_t status; @@ -176,6 +176,48 @@ _cairo_compositor_stroke (const cairo_compositor_t *compositor, } cairo_int_status_t +_cairo_compositor_stroke (const cairo_compositor_t *compositor, + cairo_surface_t *surface, + cairo_operator_t op, + const cairo_pattern_t *source, + const cairo_path_fixed_t *path, + const cairo_stroke_style_t *style, + const cairo_matrix_t *ctm, + const cairo_matrix_t *ctm_inverse, + double tolerance, + cairo_antialias_t antialias, + const cairo_clip_t *clip) +{ + if (!style->is_hairline) + return _cairo_compositor_stroke_impl (compositor, surface, + op, source, path, + style, ctm, ctm_inverse, + tolerance, antialias, clip); + else { + cairo_stroke_style_t hairline_style; + cairo_status_t status; + cairo_matrix_t identity; + + status = _cairo_stroke_style_init_copy (&hairline_style, style); + if (unlikely (status)) + return status; + + hairline_style.line_width = 1.0; + + cairo_matrix_init_identity (&identity); + + status = _cairo_compositor_stroke_impl (compositor, surface, + op, source, path, + &hairline_style, &identity, &identity, + tolerance, antialias, clip); + + _cairo_stroke_style_fini (&hairline_style); + + return status; + } +} + +cairo_int_status_t _cairo_compositor_fill (const cairo_compositor_t *compositor, cairo_surface_t *surface, cairo_operator_t op, diff --git a/gfx/cairo/cairo/src/cairo-directfb.h b/gfx/cairo/cairo/src/cairo-ctype-inline.h index e3d818c668..6cc5d005b5 100644 --- a/gfx/cairo/cairo/src/cairo-directfb.h +++ b/gfx/cairo/cairo/src/cairo-ctype-inline.h @@ -1,6 +1,6 @@ /* cairo - a vector graphics library with display and print output * - * Copyright © 2003 University of Southern California + * Copyright © 2009,2016,2021,2022 Adrian Johnson * * This library is free software; you can redistribute it and/or * modify it either under the terms of the GNU Lesser General Public @@ -31,37 +31,56 @@ * California. * * Contributor(s): - * Carl D. Worth <cworth@isi.edu> + * Adrian Johnson <ajohnson@redneon.com> */ -/* - * Environment variables affecting the backend: - * - * %CAIRO_DIRECTFB_NO_ACCEL (boolean) - * if found, disables acceleration at all - * - * %CAIRO_DIRECTFB_ARGB_FONT (boolean) - * if found, enables using ARGB fonts instead of A8 +#ifndef _CAIRO_CTYPE_INLINE_H_ +#define _CAIRO_CTYPE_INLINE_H_ + +#include "cairo-error-private.h" + +CAIRO_BEGIN_DECLS + +/* ASCII only versions of some ctype.h character classification functions. + * The glibc versions are slow in UTF-8 locales. */ -#ifndef CAIRO_DIRECTFB_H -#define CAIRO_DIRECTFB_H +static inline int cairo_const +_cairo_isspace (int c) +{ + return (c == 0x20 || (c >= 0x09 && c <= 0x0d)); +} -#include "cairo.h" +static inline int cairo_const +_cairo_isdigit (int c) +{ + return (c >= '0' && c <= '9'); +} -#if CAIRO_HAS_DIRECTFB_SURFACE +static inline int cairo_const +_cairo_isxdigit (int c) +{ + return ((c >= '0' && c <= '9') || (c >= 'a' && c <= 'f') || (c >= 'A' && c <= 'F')); +} -#include <directfb.h> +static inline int cairo_const +_cairo_isalpha (int c) +{ + return (c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z'); +} -CAIRO_BEGIN_DECLS +static inline int cairo_const +_cairo_isprint (int c) +{ + return (c >= 0x20 && c <= 0x7e); +} -cairo_public cairo_surface_t * -cairo_directfb_surface_create (IDirectFB *dfb, IDirectFBSurface *surface); +static inline int cairo_const +_cairo_isalnum (int c) +{ + return ((c >= '0' && c <= '9') || (c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z')); +} CAIRO_END_DECLS -#else /*CAIRO_HAS_DIRECTFB_SURFACE*/ -# error Cairo was not compiled with support for the directfb backend -#endif /*CAIRO_HAS_DIRECTFB_SURFACE*/ - -#endif /*CAIRO_DIRECTFB_H*/ +#endif /* _CAIRO_CTYPE_INLINE_H_ */ diff --git a/gfx/cairo/cairo/src/cairo-debug.c b/gfx/cairo/cairo/src/cairo-debug.c index 6acdea9dde..11777f04be 100644 --- a/gfx/cairo/cairo/src/cairo-debug.c +++ b/gfx/cairo/cairo/src/cairo-debug.c @@ -88,10 +88,6 @@ cairo_debug_reset_static_data (void) _cairo_image_compositor_reset_static_data (); -#if CAIRO_HAS_DRM_SURFACE - _cairo_drm_device_reset_static_data (); -#endif - _cairo_default_context_reset_static_data (); CAIRO_MUTEX_FINALIZE (); @@ -323,3 +319,102 @@ _cairo_debug_print_rect (FILE *file, const cairo_rectangle_int_t *rect) rect->x, rect->y, rect->width, rect->height); } + +const char * +_cairo_debug_operator_to_string (cairo_operator_t op) +{ + switch (op) { + case CAIRO_OPERATOR_CLEAR: return "CLEAR"; + case CAIRO_OPERATOR_SOURCE: return "SOURCE"; + case CAIRO_OPERATOR_OVER: return "OVER"; + case CAIRO_OPERATOR_IN: return "IN"; + case CAIRO_OPERATOR_OUT: return "OUT"; + case CAIRO_OPERATOR_ATOP: return "ATOP"; + case CAIRO_OPERATOR_DEST: return "DEST"; + case CAIRO_OPERATOR_DEST_OVER: return "DEST_OVER"; + case CAIRO_OPERATOR_DEST_IN: return "DEST_IN"; + case CAIRO_OPERATOR_DEST_OUT: return "DEST_OUT"; + case CAIRO_OPERATOR_DEST_ATOP: return "DEST_ATOP"; + case CAIRO_OPERATOR_XOR: return "XOR"; + case CAIRO_OPERATOR_ADD: return "ADD"; + case CAIRO_OPERATOR_SATURATE: return "SATURATE"; + case CAIRO_OPERATOR_MULTIPLY: return "MULTIPLY"; + case CAIRO_OPERATOR_SCREEN: return "SCREEN"; + case CAIRO_OPERATOR_OVERLAY: return "OVERLAY"; + case CAIRO_OPERATOR_DARKEN: return "DARKEN"; + case CAIRO_OPERATOR_LIGHTEN: return "LIGHTEN"; + case CAIRO_OPERATOR_COLOR_DODGE: return "COLOR_DODGE"; + case CAIRO_OPERATOR_COLOR_BURN: return "COLOR_BURN"; + case CAIRO_OPERATOR_HARD_LIGHT: return "HARD_LIGHT"; + case CAIRO_OPERATOR_SOFT_LIGHT: return "SOFT_LIGHT"; + case CAIRO_OPERATOR_DIFFERENCE: return "DIFFERENCE"; + case CAIRO_OPERATOR_EXCLUSION: return "EXCLUSION"; + case CAIRO_OPERATOR_HSL_HUE: return "HSL_HUE"; + case CAIRO_OPERATOR_HSL_SATURATION: return "HSL_SATURATION"; + case CAIRO_OPERATOR_HSL_COLOR: return "HSL_COLOR"; + case CAIRO_OPERATOR_HSL_LUMINOSITY: return "HSL_LUMINOSITY"; + } + return "UNKNOWN"; +} + +const char * +_cairo_debug_status_to_string (cairo_int_status_t status) +{ + switch (status) { + case CAIRO_INT_STATUS_SUCCESS: return "SUCCESS"; + case CAIRO_INT_STATUS_NO_MEMORY: return "NO_MEMORY"; + case CAIRO_INT_STATUS_INVALID_RESTORE: return "INVALID_RESTORE"; + case CAIRO_INT_STATUS_INVALID_POP_GROUP: return "INVALID_POP_GROUP"; + case CAIRO_INT_STATUS_NO_CURRENT_POINT: return "NO_CURRENT_POINT"; + case CAIRO_INT_STATUS_INVALID_MATRIX: return "INVALID_MATRIX"; + case CAIRO_INT_STATUS_INVALID_STATUS: return "INVALID_STATUS"; + case CAIRO_INT_STATUS_NULL_POINTER: return "NULL_POINTER"; + case CAIRO_INT_STATUS_INVALID_STRING: return "INVALID_STRING"; + case CAIRO_INT_STATUS_INVALID_PATH_DATA: return "INVALID_PATH_DATA"; + case CAIRO_INT_STATUS_READ_ERROR: return "READ_ERROR"; + case CAIRO_INT_STATUS_WRITE_ERROR: return "WRITE_ERROR"; + case CAIRO_INT_STATUS_SURFACE_FINISHED: return "SURFACE_FINISHED"; + case CAIRO_INT_STATUS_SURFACE_TYPE_MISMATCH: return "SURFACE_TYPE_MISMATCH"; + case CAIRO_INT_STATUS_PATTERN_TYPE_MISMATCH: return "PATTERN_TYPE_MISMATCH"; + case CAIRO_INT_STATUS_INVALID_CONTENT: return "INVALID_CONTENT"; + case CAIRO_INT_STATUS_INVALID_FORMAT: return "INVALID_FORMAT"; + case CAIRO_INT_STATUS_INVALID_VISUAL: return "INVALID_VISUAL"; + case CAIRO_INT_STATUS_FILE_NOT_FOUND: return "FILE_NOT_FOUND"; + case CAIRO_INT_STATUS_INVALID_DASH: return "INVALID_DASH"; + case CAIRO_INT_STATUS_INVALID_DSC_COMMENT: return "INVALID_DSC_COMMENT"; + case CAIRO_INT_STATUS_INVALID_INDEX: return "INVALID_INDEX"; + case CAIRO_INT_STATUS_CLIP_NOT_REPRESENTABLE: return "CLIP_NOT_REPRESENTABLE"; + case CAIRO_INT_STATUS_TEMP_FILE_ERROR: return "TEMP_FILE_ERROR"; + case CAIRO_INT_STATUS_INVALID_STRIDE: return "INVALID_STRIDE"; + case CAIRO_INT_STATUS_FONT_TYPE_MISMATCH: return "FONT_TYPE_MISMATCH"; + case CAIRO_INT_STATUS_USER_FONT_IMMUTABLE: return "USER_FONT_IMMUTABLE"; + case CAIRO_INT_STATUS_USER_FONT_ERROR: return "USER_FONT_ERROR"; + case CAIRO_INT_STATUS_NEGATIVE_COUNT: return "NEGATIVE_COUNT"; + case CAIRO_INT_STATUS_INVALID_CLUSTERS: return "INVALID_CLUSTERS"; + case CAIRO_INT_STATUS_INVALID_SLANT: return "INVALID_SLANT"; + case CAIRO_INT_STATUS_INVALID_WEIGHT: return "INVALID_WEIGHT"; + case CAIRO_INT_STATUS_INVALID_SIZE: return "INVALID_SIZE"; + case CAIRO_INT_STATUS_USER_FONT_NOT_IMPLEMENTED: return "USER_FONT_NOT_IMPLEMENTED"; + case CAIRO_INT_STATUS_DEVICE_TYPE_MISMATCH: return "DEVICE_TYPE_MISMATCH"; + case CAIRO_INT_STATUS_DEVICE_ERROR: return "DEVICE_ERROR"; + case CAIRO_INT_STATUS_INVALID_MESH_CONSTRUCTION: return "INVALID_MESH_CONSTRUCTION"; + case CAIRO_INT_STATUS_DEVICE_FINISHED: return "DEVICE_FINISHED"; + case CAIRO_INT_STATUS_JBIG2_GLOBAL_MISSING: return "JBIG2_GLOBAL_MISSING"; + case CAIRO_INT_STATUS_PNG_ERROR: return "PNG_ERROR"; + case CAIRO_INT_STATUS_FREETYPE_ERROR: return "FREETYPE_ERROR"; + case CAIRO_INT_STATUS_WIN32_GDI_ERROR: return "WIN32_GDI_ERROR"; + case CAIRO_INT_STATUS_TAG_ERROR: return "TAG_ERROR"; + case CAIRO_INT_STATUS_DWRITE_ERROR: return "DWRITE_ERROR"; + case CAIRO_INT_STATUS_SVG_FONT_ERROR: return "SVG_FONT_ERROR"; + + case CAIRO_INT_STATUS_LAST_STATUS: return "LAST_STATUS"; + + case CAIRO_INT_STATUS_UNSUPPORTED: return "UNSUPPORTED"; + case CAIRO_INT_STATUS_DEGENERATE: return "DEGENERATE"; + case CAIRO_INT_STATUS_NOTHING_TO_DO: return "NOTHING_TO_DO"; + case CAIRO_INT_STATUS_FLATTEN_TRANSPARENCY: return "FLATTEN_TRANSPARENCY"; + case CAIRO_INT_STATUS_IMAGE_FALLBACK: return "IMAGE_FALLBACK"; + case CAIRO_INT_STATUS_ANALYZE_RECORDING_SURFACE_PATTERN: return "ANALYZE_RECORDING_SURFACE_PATTERN"; + } + return "UNKNOWN"; +} diff --git a/gfx/cairo/cairo/src/cairo-default-context.c b/gfx/cairo/cairo/src/cairo-default-context.c index d2c9cae10d..87370cdc76 100644 --- a/gfx/cairo/cairo/src/cairo-default-context.c +++ b/gfx/cairo/cairo/src/cairo-default-context.c @@ -404,6 +404,14 @@ _cairo_default_context_set_line_width (void *abstract_cr, } static cairo_status_t +_cairo_default_context_set_hairline (void *abstract_cr, cairo_bool_t set_hairline) +{ + cairo_default_context_t *cr = abstract_cr; + + return _cairo_gstate_set_hairline (cr->gstate, set_hairline); +} + +static cairo_status_t _cairo_default_context_set_line_cap (void *abstract_cr, cairo_line_cap_t line_cap) { @@ -477,6 +485,14 @@ _cairo_default_context_get_line_width (void *abstract_cr) return _cairo_gstate_get_line_width (cr->gstate); } +static cairo_bool_t +_cairo_default_context_get_hairline (void *abstract_cr) +{ + cairo_default_context_t *cr = abstract_cr; + + return _cairo_gstate_get_hairline (cr->gstate); +} + static cairo_line_cap_t _cairo_default_context_get_line_cap (void *abstract_cr) { @@ -697,10 +713,12 @@ _cairo_default_context_move_to (void *abstract_cr, double x, double y) { cairo_default_context_t *cr = abstract_cr; cairo_fixed_t x_fixed, y_fixed; + double width; _cairo_gstate_user_to_backend (cr->gstate, &x, &y); - x_fixed = _cairo_fixed_from_double (x); - y_fixed = _cairo_fixed_from_double (y); + width = _cairo_gstate_get_line_width (cr->gstate); + x_fixed = _cairo_fixed_from_double_clamped (x, width); + y_fixed = _cairo_fixed_from_double_clamped (y, width); return _cairo_path_fixed_move_to (cr->path, x_fixed, y_fixed); } @@ -710,10 +728,12 @@ _cairo_default_context_line_to (void *abstract_cr, double x, double y) { cairo_default_context_t *cr = abstract_cr; cairo_fixed_t x_fixed, y_fixed; + double width; _cairo_gstate_user_to_backend (cr->gstate, &x, &y); - x_fixed = _cairo_fixed_from_double (x); - y_fixed = _cairo_fixed_from_double (y); + width = _cairo_gstate_get_line_width (cr->gstate); + x_fixed = _cairo_fixed_from_double_clamped (x, width); + y_fixed = _cairo_fixed_from_double_clamped (y, width); return _cairo_path_fixed_line_to (cr->path, x_fixed, y_fixed); } @@ -728,19 +748,21 @@ _cairo_default_context_curve_to (void *abstract_cr, cairo_fixed_t x1_fixed, y1_fixed; cairo_fixed_t x2_fixed, y2_fixed; cairo_fixed_t x3_fixed, y3_fixed; + double width; _cairo_gstate_user_to_backend (cr->gstate, &x1, &y1); _cairo_gstate_user_to_backend (cr->gstate, &x2, &y2); _cairo_gstate_user_to_backend (cr->gstate, &x3, &y3); + width = _cairo_gstate_get_line_width (cr->gstate); - x1_fixed = _cairo_fixed_from_double (x1); - y1_fixed = _cairo_fixed_from_double (y1); + x1_fixed = _cairo_fixed_from_double_clamped (x1, width); + y1_fixed = _cairo_fixed_from_double_clamped (y1, width); - x2_fixed = _cairo_fixed_from_double (x2); - y2_fixed = _cairo_fixed_from_double (y2); + x2_fixed = _cairo_fixed_from_double_clamped (x2, width); + y2_fixed = _cairo_fixed_from_double_clamped (y2, width); - x3_fixed = _cairo_fixed_from_double (x3); - y3_fixed = _cairo_fixed_from_double (y3); + x3_fixed = _cairo_fixed_from_double_clamped (x3, width); + y3_fixed = _cairo_fixed_from_double_clamped (y3, width); return _cairo_path_fixed_curve_to (cr->path, x1_fixed, y1_fixed, @@ -1365,6 +1387,7 @@ static const cairo_backend_t _cairo_default_context_backend = { _cairo_default_context_set_line_cap, _cairo_default_context_set_line_join, _cairo_default_context_set_line_width, + _cairo_default_context_set_hairline, _cairo_default_context_set_miter_limit, _cairo_default_context_set_opacity, _cairo_default_context_set_operator, @@ -1375,6 +1398,7 @@ static const cairo_backend_t _cairo_default_context_backend = { _cairo_default_context_get_line_cap, _cairo_default_context_get_line_join, _cairo_default_context_get_line_width, + _cairo_default_context_get_hairline, _cairo_default_context_get_miter_limit, _cairo_default_context_get_opacity, _cairo_default_context_get_operator, diff --git a/gfx/cairo/cairo/src/cairo-device-private.h b/gfx/cairo/cairo/src/cairo-device-private.h index 6eb44f3b63..02bf73d022 100644 --- a/gfx/cairo/cairo/src/cairo-device-private.h +++ b/gfx/cairo/cairo/src/cairo-device-private.h @@ -76,11 +76,4 @@ cairo_private cairo_status_t _cairo_device_set_error (cairo_device_t *device, cairo_status_t error); -slim_hidden_proto_no_warn (cairo_device_reference); -slim_hidden_proto (cairo_device_acquire); -slim_hidden_proto (cairo_device_release); -slim_hidden_proto (cairo_device_flush); -slim_hidden_proto (cairo_device_finish); -slim_hidden_proto (cairo_device_destroy); - #endif /* _CAIRO_DEVICE_PRIVATE_H_ */ diff --git a/gfx/cairo/cairo/src/cairo-device.c b/gfx/cairo/cairo/src/cairo-device.c index 965c84c651..1790df3ff7 100644 --- a/gfx/cairo/cairo/src/cairo-device.c +++ b/gfx/cairo/cairo/src/cairo-device.c @@ -163,6 +163,8 @@ _cairo_device_create_in_error (cairo_status_t status) case CAIRO_STATUS_FREETYPE_ERROR: case CAIRO_STATUS_WIN32_GDI_ERROR: case CAIRO_STATUS_TAG_ERROR: + case CAIRO_STATUS_DWRITE_ERROR: + case CAIRO_STATUS_SVG_FONT_ERROR: default: _cairo_error_throw (CAIRO_STATUS_NO_MEMORY); return (cairo_device_t *) &_nil_device; @@ -215,7 +217,6 @@ cairo_device_reference (cairo_device_t *device) return device; } -slim_hidden_def (cairo_device_reference); /** * cairo_device_status: @@ -270,7 +271,6 @@ cairo_device_flush (cairo_device_t *device) status = _cairo_device_set_error (device, status); } } -slim_hidden_def (cairo_device_flush); /** * cairo_device_finish: @@ -314,7 +314,6 @@ cairo_device_finish (cairo_device_t *device) */ device->finished = TRUE; } -slim_hidden_def (cairo_device_finish); /** * cairo_device_destroy: @@ -355,7 +354,6 @@ cairo_device_destroy (cairo_device_t *device) _cairo_user_data_array_fini (&user_data); } -slim_hidden_def (cairo_device_destroy); /** * cairo_device_get_type: @@ -430,7 +428,6 @@ cairo_device_acquire (cairo_device_t *device) return CAIRO_STATUS_SUCCESS; } -slim_hidden_def (cairo_device_acquire); /** * cairo_device_release: @@ -456,7 +453,6 @@ cairo_device_release (cairo_device_t *device) CAIRO_MUTEX_UNLOCK (device->mutex); } -slim_hidden_def (cairo_device_release); cairo_status_t _cairo_device_set_error (cairo_device_t *device, diff --git a/gfx/cairo/cairo/src/cairo-directfb-surface.c b/gfx/cairo/cairo/src/cairo-directfb-surface.c deleted file mode 100644 index 0deedf0d54..0000000000 --- a/gfx/cairo/cairo/src/cairo-directfb-surface.c +++ /dev/null @@ -1,545 +0,0 @@ -/* cairo - a vector graphics library with display and print output - * - * Copyright © 2012 Intel Corporation - * - * This library is free software; you can redistribute it and/or - * modify it either under the terms of the GNU Lesser General Public - * License version 2.1 as published by the Free Software Foundation - * (the "LGPL") or, at your option, under the terms of the Mozilla - * Public License Version 1.1 (the "MPL"). If you do not alter this - * notice, a recipient may use your version of this file under either - * the MPL or the LGPL. - * - * You should have received a copy of the LGPL along with this library - * in the file COPYING-LGPL-2.1; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Suite 500, Boston, MA 02110-1335, 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 Chris Wilson - * - * Contributor(s): - * Chris Wilson <chris@chris-wilson.co.uk> - */ - -#include "cairoint.h" -#include "cairo-directfb.h" - -#include "cairo-clip-private.h" -#include "cairo-compositor-private.h" -#include "cairo-default-context-private.h" -#include "cairo-error-private.h" -#include "cairo-image-surface-inline.h" -#include "cairo-pattern-private.h" -#include "cairo-surface-backend-private.h" -#include "cairo-surface-fallback-private.h" - -#include <pixman.h> - -#include <directfb.h> -#include <direct/types.h> -#include <direct/debug.h> -#include <direct/memcpy.h> -#include <direct/util.h> - -slim_hidden_proto(cairo_directfb_surface_create); - -typedef struct _cairo_dfb_surface { - cairo_image_surface_t image; - - IDirectFB *dfb; - IDirectFBSurface *dfb_surface; - - unsigned blit_premultiplied : 1; -} cairo_dfb_surface_t; - -static cairo_content_t -_directfb_format_to_content (DFBSurfacePixelFormat format) -{ - cairo_content_t content = 0; - - if (DFB_PIXELFORMAT_HAS_ALPHA (format)) - content |= CAIRO_CONTENT_ALPHA; - if (DFB_COLOR_BITS_PER_PIXEL (format)) - content |= CAIRO_CONTENT_COLOR_ALPHA; - - assert(content); - return content; -} - -static inline pixman_format_code_t -_directfb_to_pixman_format (DFBSurfacePixelFormat format) -{ - switch (format) { - case DSPF_UNKNOWN: return 0; - case DSPF_ARGB1555: return PIXMAN_a1r5g5b5; - case DSPF_RGB16: return PIXMAN_r5g6b5; - case DSPF_RGB24: return PIXMAN_r8g8b8; - case DSPF_RGB32: return PIXMAN_x8r8g8b8; - case DSPF_ARGB: return PIXMAN_a8r8g8b8; - case DSPF_A8: return PIXMAN_a8; - case DSPF_YUY2: return PIXMAN_yuy2; - case DSPF_RGB332: return PIXMAN_r3g3b2; - case DSPF_UYVY: return 0; - case DSPF_I420: return 0; - case DSPF_YV12: return PIXMAN_yv12; - case DSPF_LUT8: return 0; - case DSPF_ALUT44: return 0; - case DSPF_AiRGB: return 0; - case DSPF_A1: return 0; /* bit reversed, oops */ - case DSPF_NV12: return 0; - case DSPF_NV16: return 0; - case DSPF_ARGB2554: return 0; - case DSPF_ARGB4444: return PIXMAN_a4r4g4b4; - case DSPF_NV21: return 0; - case DSPF_AYUV: return 0; - case DSPF_A4: return PIXMAN_a4; - case DSPF_ARGB1666: return 0; - case DSPF_ARGB6666: return 0; - case DSPF_RGB18: return 0; - case DSPF_LUT2: return 0; - case DSPF_RGB444: return PIXMAN_x4r4g4b4; - case DSPF_RGB555: return PIXMAN_x1r5g5b5; -#if DFB_NUM_PIXELFORMATS >= 29 - case DSPF_BGR555: return PIXMAN_x1b5g5r5; -#endif - } - return 0; -} - -static cairo_surface_t * -_cairo_dfb_surface_create_similar (void *abstract_src, - cairo_content_t content, - int width, - int height) -{ - cairo_dfb_surface_t *other = abstract_src; - DFBSurfacePixelFormat format; - IDirectFBSurface *buffer; - DFBSurfaceDescription dsc; - cairo_surface_t *surface; - - if (width <= 0 || height <= 0) - return _cairo_image_surface_create_with_content (content, width, height); - - switch (content) { - default: - ASSERT_NOT_REACHED; - case CAIRO_CONTENT_COLOR_ALPHA: - format = DSPF_ARGB; - break; - case CAIRO_CONTENT_COLOR: - format = DSPF_RGB32; - break; - case CAIRO_CONTENT_ALPHA: - format = DSPF_A8; - break; - } - - dsc.flags = DSDESC_WIDTH | DSDESC_HEIGHT | DSDESC_PIXELFORMAT; - dsc.caps = DSCAPS_PREMULTIPLIED; - dsc.width = width; - dsc.height = height; - dsc.pixelformat = format; - - if (other->dfb->CreateSurface (other->dfb, &dsc, &buffer)) - return _cairo_surface_create_in_error (_cairo_error (CAIRO_STATUS_DEVICE_ERROR)); - - surface = cairo_directfb_surface_create (other->dfb, buffer); - buffer->Release (buffer); - - return surface; -} - -static cairo_status_t -_cairo_dfb_surface_finish (void *abstract_surface) -{ - cairo_dfb_surface_t *surface = abstract_surface; - - surface->dfb_surface->Release (surface->dfb_surface); - return _cairo_image_surface_finish (abstract_surface); -} - -static cairo_image_surface_t * -_cairo_dfb_surface_map_to_image (void *abstract_surface, - const cairo_rectangle_int_t *extents) -{ - cairo_dfb_surface_t *surface = abstract_surface; - - if (surface->image.pixman_image == NULL) { - IDirectFBSurface *buffer = surface->dfb_surface; - pixman_image_t *image; - void *data; - int pitch; - - if (buffer->Lock (buffer, DSLF_READ | DSLF_WRITE, &data, &pitch)) - return _cairo_image_surface_create_in_error (_cairo_error (CAIRO_STATUS_NO_MEMORY)); - - image = pixman_image_create_bits (surface->image.pixman_format, - surface->image.width, - surface->image.height, - data, pitch); - if (image == NULL) { - buffer->Unlock (buffer); - return _cairo_image_surface_create_in_error (_cairo_error (CAIRO_STATUS_NO_MEMORY)); - } - _cairo_image_surface_init (&surface->image, image, surface->image.pixman_format); - } - - return _cairo_image_surface_map_to_image (&surface->image.base, extents); -} - -static cairo_int_status_t -_cairo_dfb_surface_unmap_image (void *abstract_surface, - cairo_image_surface_t *image) -{ - cairo_dfb_surface_t *surface = abstract_surface; - return _cairo_image_surface_unmap_image (&surface->image.base, image); -} - -static cairo_status_t -_cairo_dfb_surface_flush (void *abstract_surface, - unsigned flags) -{ - cairo_dfb_surface_t *surface = abstract_surface; - - if (flags) - return CAIRO_STATUS_SUCCESS; - - if (surface->image.pixman_image) { - surface->dfb_surface->Unlock (surface->dfb_surface); - - pixman_image_unref (surface->image.pixman_image); - surface->image.pixman_image = NULL; - surface->image.data = NULL; - } - - return CAIRO_STATUS_SUCCESS; -} - -#if 0 -static inline DFBSurfacePixelFormat -_directfb_from_pixman_format (pixman_format_code_t format) -{ - switch ((int) format) { - case PIXMAN_a1r5g5b5: return DSPF_ARGB1555; - case PIXMAN_r5g6b5: return DSPF_RGB16; - case PIXMAN_r8g8b8: return DSPF_RGB24; - case PIXMAN_x8r8g8b8: return DSPF_RGB32; - case PIXMAN_a8r8g8b8: return DSPF_ARGB; - case PIXMAN_a8: return DSPF_A8; - case PIXMAN_yuy2: return DSPF_YUY2; - case PIXMAN_r3g3b2: return DSPF_RGB332; - case PIXMAN_yv12: return DSPF_YV12; - case PIXMAN_a1: return DSPF_A1; /* bit reversed, oops */ - case PIXMAN_a4r4g4b4: return DSPF_ARGB4444; - case PIXMAN_a4: return DSPF_A4; - case PIXMAN_x4r4g4b4: return DSPF_RGB444; - case PIXMAN_x1r5g5b5: return DSPF_RGB555; -#if DFB_NUM_PIXELFORMATS >= 29 - case PIXMAN_x1b5g5r5: return DSPF_BGR555; -#endif - default: return 0; - } -} - -static cairo_bool_t -_directfb_get_operator (cairo_operator_t operator, - DFBSurfaceBlendFunction *ret_srcblend, - DFBSurfaceBlendFunction *ret_dstblend) -{ - DFBSurfaceBlendFunction srcblend = DSBF_ONE; - DFBSurfaceBlendFunction dstblend = DSBF_ZERO; - - switch (operator) { - case CAIRO_OPERATOR_CLEAR: - srcblend = DSBF_ZERO; - dstblend = DSBF_ZERO; - break; - case CAIRO_OPERATOR_SOURCE: - srcblend = DSBF_ONE; - dstblend = DSBF_ZERO; - break; - case CAIRO_OPERATOR_OVER: - srcblend = DSBF_ONE; - dstblend = DSBF_INVSRCALPHA; - break; - case CAIRO_OPERATOR_IN: - srcblend = DSBF_DESTALPHA; - dstblend = DSBF_ZERO; - break; - case CAIRO_OPERATOR_OUT: - srcblend = DSBF_INVDESTALPHA; - dstblend = DSBF_ZERO; - break; - case CAIRO_OPERATOR_ATOP: - srcblend = DSBF_DESTALPHA; - dstblend = DSBF_INVSRCALPHA; - break; - case CAIRO_OPERATOR_DEST: - srcblend = DSBF_ZERO; - dstblend = DSBF_ONE; - break; - case CAIRO_OPERATOR_DEST_OVER: - srcblend = DSBF_INVDESTALPHA; - dstblend = DSBF_ONE; - break; - case CAIRO_OPERATOR_DEST_IN: - srcblend = DSBF_ZERO; - dstblend = DSBF_SRCALPHA; - break; - case CAIRO_OPERATOR_DEST_OUT: - srcblend = DSBF_ZERO; - dstblend = DSBF_INVSRCALPHA; - break; - case CAIRO_OPERATOR_DEST_ATOP: - srcblend = DSBF_INVDESTALPHA; - dstblend = DSBF_SRCALPHA; - break; - case CAIRO_OPERATOR_XOR: - srcblend = DSBF_INVDESTALPHA; - dstblend = DSBF_INVSRCALPHA; - break; - case CAIRO_OPERATOR_ADD: - srcblend = DSBF_ONE; - dstblend = DSBF_ONE; - break; - case CAIRO_OPERATOR_SATURATE: - /* XXX This does not work. */ -#if 0 - srcblend = DSBF_SRCALPHASAT; - dstblend = DSBF_ONE; - break; -#endif - case CAIRO_OPERATOR_MULTIPLY: - case CAIRO_OPERATOR_SCREEN: - case CAIRO_OPERATOR_OVERLAY: - case CAIRO_OPERATOR_DARKEN: - case CAIRO_OPERATOR_LIGHTEN: - case CAIRO_OPERATOR_COLOR_DODGE: - case CAIRO_OPERATOR_COLOR_BURN: - case CAIRO_OPERATOR_HARD_LIGHT: - case CAIRO_OPERATOR_SOFT_LIGHT: - case CAIRO_OPERATOR_DIFFERENCE: - case CAIRO_OPERATOR_EXCLUSION: - case CAIRO_OPERATOR_HSL_HUE: - case CAIRO_OPERATOR_HSL_SATURATION: - case CAIRO_OPERATOR_HSL_COLOR: - case CAIRO_OPERATOR_HSL_LUMINOSITY: - default: - return FALSE; - } - - *ret_srcblend = srcblend; - *ret_dstblend = dstblend; - - return TRUE; -} -#define RUN_CLIPPED(surface, clip_region, clip, func) {\ - if ((clip_region) != NULL) {\ - int n_clips = cairo_region_num_rectangles (clip_region), n; \ - for (n = 0; n < n_clips; n++) {\ - if (clip) {\ - DFBRegion reg, *cli = (clip); \ - cairo_rectangle_int_t rect; \ - cairo_region_get_rectangle (clip_region, n, &rect); \ - reg.x1 = rect.x; \ - reg.y1 = rect.y; \ - reg.x2 = rect.x + rect.width - 1; \ - reg.y2 = rect.y + rect.height - 1; \ - if (reg.x2 < cli->x1 || reg.y2 < cli->y1 ||\ - reg.x1 > cli->x2 || reg.y1 > cli->y2)\ - continue;\ - if (reg.x1 < cli->x1)\ - reg.x1 = cli->x1;\ - if (reg.y1 < cli->y1)\ - reg.y1 = cli->y1;\ - if (reg.x2 > cli->x2)\ - reg.x2 = cli->x2;\ - if (reg.y2 > cli->y2)\ - reg.y2 = cli->y2;\ - (surface)->dfbsurface->SetClip ((surface)->dfbsurface, ®);\ - } else {\ - DFBRegion reg; \ - cairo_rectangle_int_t rect; \ - cairo_region_get_rectangle (clip_region, n, &rect); \ - reg.x1 = rect.x; \ - reg.y1 = rect.y; \ - reg.x2 = rect.x + rect.width - 1; \ - reg.y2 = rect.y + rect.height - 1; \ - (surface)->dfbsurface->SetClip ((surface)->dfbsurface, ®); \ - }\ - func;\ - }\ - } else {\ - (surface)->dfbsurface->SetClip ((surface)->dfbsurface, clip);\ - func;\ - }\ -} - -static cairo_int_status_t -_cairo_dfb_surface_fill_rectangles (void *abstract_surface, - cairo_operator_t op, - const cairo_color_t *color, - cairo_rectangle_int_t *rects, - int n_rects) -{ - cairo_dfb_surface_t *dst = abstract_surface; - DFBSurfaceDrawingFlags flags; - DFBSurfaceBlendFunction sblend; - DFBSurfaceBlendFunction dblend; - DFBRectangle r[n_rects]; - int i; - - D_DEBUG_AT (CairoDFB_Render, - "%s( dst=%p, op=%d, color=%p, rects=%p, n_rects=%d ).\n", - __FUNCTION__, dst, op, color, rects, n_rects); - - if (! dst->supported_destination) - return CAIRO_INT_STATUS_UNSUPPORTED; - - if (! _directfb_get_operator (op, &sblend, &dblend)) - return CAIRO_INT_STATUS_UNSUPPORTED; - - if (CAIRO_COLOR_IS_OPAQUE (color)) { - if (sblend == DSBF_SRCALPHA) - sblend = DSBF_ONE; - else if (sblend == DSBF_INVSRCALPHA) - sblend = DSBF_ZERO; - - if (dblend == DSBF_SRCALPHA) - dblend = DSBF_ONE; - else if (dblend == DSBF_INVSRCALPHA) - dblend = DSBF_ZERO; - } - if ((dst->base.content & CAIRO_CONTENT_ALPHA) == 0) { - if (sblend == DSBF_DESTALPHA) - sblend = DSBF_ONE; - else if (sblend == DSBF_INVDESTALPHA) - sblend = DSBF_ZERO; - - if (dblend == DSBF_DESTALPHA) - dblend = DSBF_ONE; - else if (dblend == DSBF_INVDESTALPHA) - dblend = DSBF_ZERO; - } - - flags = (sblend == DSBF_ONE && dblend == DSBF_ZERO) ? DSDRAW_NOFX : DSDRAW_BLEND; - dst->dfbsurface->SetDrawingFlags (dst->dfbsurface, flags); - if (flags & DSDRAW_BLEND) { - dst->dfbsurface->SetSrcBlendFunction (dst->dfbsurface, sblend); - dst->dfbsurface->SetDstBlendFunction (dst->dfbsurface, dblend); - } - - dst->dfbsurface->SetColor (dst->dfbsurface, - color->red_short >> 8, - color->green_short >> 8, - color->blue_short >> 8, - color->alpha_short >> 8); - - for (i = 0; i < n_rects; i++) { - r[i].x = rects[i].x; - r[i].y = rects[i].y; - r[i].w = rects[i].width; - r[i].h = rects[i].height; - } - - RUN_CLIPPED (dst, NULL, NULL, - dst->dfbsurface->FillRectangles (dst->dfbsurface, r, n_rects)); - - return CAIRO_STATUS_SUCCESS; -} -#endif - -static cairo_surface_backend_t -_cairo_dfb_surface_backend = { - CAIRO_SURFACE_TYPE_DIRECTFB, /*type*/ - _cairo_dfb_surface_finish, /*finish*/ - _cairo_default_context_create, - - _cairo_dfb_surface_create_similar,/*create_similar*/ - NULL, /* create similar image */ - _cairo_dfb_surface_map_to_image, - _cairo_dfb_surface_unmap_image, - - _cairo_surface_default_source, - _cairo_surface_default_acquire_source_image, - _cairo_surface_default_release_source_image, - NULL, - - NULL, /* copy_page */ - NULL, /* show_page */ - - _cairo_image_surface_get_extents, - _cairo_image_surface_get_font_options, - - _cairo_dfb_surface_flush, - NULL, /* mark_dirty_rectangle */ - - _cairo_surface_fallback_paint, - _cairo_surface_fallback_mask, - _cairo_surface_fallback_stroke, - _cairo_surface_fallback_fill, - NULL, /* fill-stroke */ - _cairo_surface_fallback_glyphs, -}; - -cairo_surface_t * -cairo_directfb_surface_create (IDirectFB *dfb, IDirectFBSurface *dfbsurface) -{ - cairo_dfb_surface_t *surface; - DFBSurfacePixelFormat format; - DFBSurfaceCapabilities caps; - pixman_format_code_t pixman_format; - int width, height; - - D_ASSERT (dfb != NULL); - D_ASSERT (dfbsurface != NULL); - - dfbsurface->GetPixelFormat (dfbsurface, &format); - dfbsurface->GetSize (dfbsurface, &width, &height); - - pixman_format = _directfb_to_pixman_format (format); - if (! pixman_format_supported_destination (pixman_format)) - return _cairo_surface_create_in_error (_cairo_error (CAIRO_STATUS_INVALID_FORMAT)); - - surface = calloc (1, sizeof (cairo_dfb_surface_t)); - if (surface == NULL) - return _cairo_surface_create_in_error (_cairo_error (CAIRO_STATUS_NO_MEMORY)); - - /* XXX dfb -> device */ - _cairo_surface_init (&surface->image.base, - &_cairo_dfb_surface_backend, - NULL, /* device */ - _directfb_format_to_content (format), - FALSE); /* is_vector */ - - surface->image.pixman_format = pixman_format; - surface->image.format = _cairo_format_from_pixman_format (pixman_format); - - surface->image.width = width; - surface->image.height = height; - surface->image.depth = PIXMAN_FORMAT_DEPTH(pixman_format); - - surface->dfb = dfb; - surface->dfb_surface = dfbsurface; - dfbsurface->AddRef (dfbsurface); - - dfbsurface->GetCapabilities (dfbsurface, &caps); - if (caps & DSCAPS_PREMULTIPLIED) - surface->blit_premultiplied = TRUE; - - return &surface->image.base; -} -slim_hidden_def(cairo_directfb_surface_create); diff --git a/gfx/cairo/cairo/src/cairo-drm.h b/gfx/cairo/cairo/src/cairo-drm.h deleted file mode 100644 index 907610dcde..0000000000 --- a/gfx/cairo/cairo/src/cairo-drm.h +++ /dev/null @@ -1,120 +0,0 @@ -/* Cairo - a vector graphics library with display and print output - * - * Copyright © 2009 Chris Wilson - * - * 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., 51 Franklin Street, Suite 500, Boston, MA 02110-1335, 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 Chris Wilson. - */ - -#ifndef CAIRO_DRM_H -#define CAIRO_DRM_H - -#include "cairo.h" - -#if CAIRO_HAS_DRM_SURFACE - -CAIRO_BEGIN_DECLS - -struct udev_device; - -cairo_public cairo_device_t * -cairo_drm_device_get (struct udev_device *device); - -cairo_public cairo_device_t * -cairo_drm_device_get_for_fd (int fd); - -cairo_public cairo_device_t * -cairo_drm_device_default (void); - -cairo_public int -cairo_drm_device_get_fd (cairo_device_t *device); - -cairo_public void -cairo_drm_device_throttle (cairo_device_t *device); - -cairo_public cairo_surface_t * -cairo_drm_surface_create (cairo_device_t *device, - cairo_format_t format, - int width, int height); - -cairo_public cairo_surface_t * -cairo_drm_surface_create_for_name (cairo_device_t *device, - unsigned int name, - cairo_format_t format, - int width, int height, int stride); - -cairo_public cairo_surface_t * -cairo_drm_surface_create_from_cacheable_image (cairo_device_t *device, - cairo_surface_t *surface); - -cairo_public cairo_status_t -cairo_drm_surface_enable_scan_out (cairo_surface_t *surface); - -cairo_public unsigned int -cairo_drm_surface_get_handle (cairo_surface_t *surface); - -cairo_public unsigned int -cairo_drm_surface_get_name (cairo_surface_t *surface); - -cairo_public cairo_format_t -cairo_drm_surface_get_format (cairo_surface_t *surface); - -cairo_public int -cairo_drm_surface_get_width (cairo_surface_t *surface); - -cairo_public int -cairo_drm_surface_get_height (cairo_surface_t *surface); - -cairo_public int -cairo_drm_surface_get_stride (cairo_surface_t *surface); - -/* XXX map/unmap, general surface layer? */ - -/* Rough outline, culled from a conversation on IRC: - * map() returns an image-surface representation of the drm-surface, - * which you unmap() when you are finished, i.e. map() pulls the buffer back - * from the GPU, maps it into the CPU domain and gives you direct access to - * the pixels. With the unmap(), the buffer is ready to be used again by the - * GPU and *until* the unmap(), all operations will be done in software. - * - * (Technically calling cairo_surface_flush() on the underlying drm-surface - * will also disassociate the mapping.) -*/ -cairo_public cairo_surface_t * -cairo_drm_surface_map_to_image (cairo_surface_t *surface); - -cairo_public void -cairo_drm_surface_unmap (cairo_surface_t *drm_surface, - cairo_surface_t *image_surface); - -CAIRO_END_DECLS - -#else /* CAIRO_HAS_DRM_SURFACE */ -# error Cairo was not compiled with support for the DRM backend -#endif /* CAIRO_HAS_DRM_SURFACE */ - -#endif /* CAIRO_DRM_H */ diff --git a/gfx/cairo/cairo/src/cairo-xml.h b/gfx/cairo/cairo/src/cairo-dwrite.h index 9ae76e90aa..b1ff718a01 100644 --- a/gfx/cairo/cairo/src/cairo-xml.h +++ b/gfx/cairo/cairo/src/cairo-dwrite.h @@ -1,6 +1,6 @@ /* cairo - a vector graphics library with display and print output * - * Copyright © 2009 Chris Wilson + * Copyright © 2023 Adrian Johnson * * This library is free software; you can redistribute it and/or * modify it either under the terms of the GNU Lesser General Public @@ -27,41 +27,46 @@ * * The Original Code is the cairo graphics library. * - * The Initial Developer of the Original Code is Chris Wilson - * * Contributor(s): - * Chris Wilson <chris@chris-wilson.co.uk> + * Adrian Johnson <ajohnson@redneon.com> */ -#ifndef CAIRO_XML_H -#define CAIRO_XML_H +#ifndef _CAIRO_DWRITE_H_ +#define _CAIRO_DWRITE_H_ #include "cairo.h" -#if CAIRO_HAS_XML_SURFACE +#if CAIRO_HAS_DWRITE_FONT + +#ifdef __cplusplus + +#include <dwrite.h> CAIRO_BEGIN_DECLS -cairo_public cairo_device_t * -cairo_xml_create (const char *filename); +cairo_public cairo_font_face_t * +cairo_dwrite_font_face_create_for_dwrite_fontface (IDWriteFontFace *dwrite_font_face); -cairo_public cairo_device_t * -cairo_xml_create_for_stream (cairo_write_func_t write_func, - void *closure); +cairo_public IDWriteRenderingParams * +cairo_dwrite_font_face_get_rendering_params (cairo_font_face_t *font_face); -cairo_public cairo_surface_t * -cairo_xml_surface_create (cairo_device_t *xml, - cairo_content_t content, - double width, double height); +cairo_public void +cairo_dwrite_font_face_set_rendering_params (cairo_font_face_t *font_face, IDWriteRenderingParams *params); -cairo_public cairo_status_t -cairo_xml_for_recording_surface (cairo_device_t *xml, - cairo_surface_t *surface); +cairo_public DWRITE_MEASURING_MODE +cairo_dwrite_font_face_get_measuring_mode (cairo_font_face_t *font_face); + +cairo_public void +cairo_dwrite_font_face_set_measuring_mode (cairo_font_face_t *font_face, DWRITE_MEASURING_MODE mode); CAIRO_END_DECLS -#else /*CAIRO_HAS_XML_SURFACE*/ -# error Cairo was not compiled with support for the XML backend -#endif /*CAIRO_HAS_XML_SURFACE*/ +#else /* __cplusplus */ +#error DWrite font backend requires C++ +#endif /* __cplusplus */ + +#else /* CAIRO_HAS_DWRITE_FONT */ +# error Cairo was not compiled with support for DWrite font backend +#endif /* CAIRO_HAS_DWRITE_FONT */ -#endif /*CAIRO_XML_H*/ +#endif /* _CAIRO_DWRITE_H_ */ diff --git a/gfx/cairo/cairo/src/cairo-egl-context.c b/gfx/cairo/cairo/src/cairo-egl-context.c deleted file mode 100644 index bf704c630f..0000000000 --- a/gfx/cairo/cairo/src/cairo-egl-context.c +++ /dev/null @@ -1,317 +0,0 @@ -/* cairo - a vector graphics library with display and print output - * - * Copyright © 2009 Eric Anholt - * Copyright © 2009 Chris Wilson - * Copyright © 2005 Red Hat, Inc - * - * This library is free software; you can redistribute it and/or - * modify it either under the terms of the GNU Lesser General Public - * License version 2.1 as published by the Free Software Foundation - * (the "LGPL") or, at your option, under the terms of the Mozilla - * Public License Version 1.1 (the "MPL"). If you do not alter this - * notice, a recipient may use your version of this file under either - * the MPL or the LGPL. - * - * You should have received a copy of the LGPL along with this library - * in the file COPYING-LGPL-2.1; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Suite 500, Boston, MA 02110-1335, 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 Worth <cworth@cworth.org> - * Chris Wilson <chris@chris-wilson.co.uk> - */ - -#include "cairoint.h" - -#include "cairo-gl-private.h" - -#include "cairo-error-private.h" - -typedef struct _cairo_egl_context { - cairo_gl_context_t base; - - EGLDisplay display; - EGLContext context; - - EGLSurface dummy_surface; - - EGLContext previous_context; - EGLSurface previous_surface; -} cairo_egl_context_t; - -typedef struct _cairo_egl_surface { - cairo_gl_surface_t base; - - EGLSurface egl; -} cairo_egl_surface_t; - - -static cairo_bool_t -_context_acquisition_changed_egl_state (cairo_egl_context_t *ctx, - EGLSurface current_surface) -{ - return ctx->previous_context != ctx->context || - ctx->previous_surface != current_surface; -} - -static EGLSurface -_egl_get_current_surface (cairo_egl_context_t *ctx) -{ - if (ctx->base.current_target == NULL || - _cairo_gl_surface_is_texture (ctx->base.current_target)) { - return ctx->dummy_surface; - } - - return ((cairo_egl_surface_t *) ctx->base.current_target)->egl; -} - -static void -_egl_query_current_state (cairo_egl_context_t *ctx) -{ - ctx->previous_surface = eglGetCurrentSurface (EGL_DRAW); - ctx->previous_context = eglGetCurrentContext (); - - /* If any of the values were none, assume they are all none. Not all - drivers seem well behaved when it comes to using these values across - multiple threads. */ - if (ctx->previous_surface == EGL_NO_SURFACE || - ctx->previous_context == EGL_NO_CONTEXT) { - ctx->previous_surface = EGL_NO_SURFACE; - ctx->previous_context = EGL_NO_CONTEXT; - } -} - -static void -_egl_acquire (void *abstract_ctx) -{ - cairo_egl_context_t *ctx = abstract_ctx; - EGLSurface current_surface = _egl_get_current_surface (ctx); - - _egl_query_current_state (ctx); - if (!_context_acquisition_changed_egl_state (ctx, current_surface)) - return; - - eglMakeCurrent (ctx->display, - current_surface, current_surface, ctx->context); -} - -static void -_egl_release (void *abstract_ctx) -{ - cairo_egl_context_t *ctx = abstract_ctx; - if (!ctx->base.thread_aware || - !_context_acquisition_changed_egl_state (ctx, - _egl_get_current_surface (ctx))) { - return; - } - - eglMakeCurrent (ctx->display, - EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT); -} - -static void -_egl_make_current (void *abstract_ctx, - cairo_gl_surface_t *abstract_surface) -{ - cairo_egl_context_t *ctx = abstract_ctx; - cairo_egl_surface_t *surface = (cairo_egl_surface_t *) abstract_surface; - - eglMakeCurrent(ctx->display, surface->egl, surface->egl, ctx->context); -} - -static void -_egl_swap_buffers (void *abstract_ctx, - cairo_gl_surface_t *abstract_surface) -{ - cairo_egl_context_t *ctx = abstract_ctx; - cairo_egl_surface_t *surface = (cairo_egl_surface_t *) abstract_surface; - - eglSwapBuffers (ctx->display, surface->egl); -} - -static void -_egl_destroy (void *abstract_ctx) -{ - cairo_egl_context_t *ctx = abstract_ctx; - - eglMakeCurrent (ctx->display, - EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT); - if (ctx->dummy_surface != EGL_NO_SURFACE) - eglDestroySurface (ctx->display, ctx->dummy_surface); -} - -static cairo_bool_t -_egl_make_current_surfaceless(cairo_egl_context_t *ctx) -{ - const char *extensions; - - extensions = eglQueryString(ctx->display, EGL_EXTENSIONS); - if (strstr(extensions, "EGL_KHR_surfaceless_context") == NULL && - strstr(extensions, "EGL_KHR_surfaceless_opengl") == NULL) - return FALSE; - - if (!eglMakeCurrent(ctx->display, - EGL_NO_SURFACE, EGL_NO_SURFACE, ctx->context)) - return FALSE; - - return TRUE; -} - -cairo_device_t * -cairo_egl_device_create (EGLDisplay dpy, EGLContext egl) -{ - cairo_egl_context_t *ctx; - cairo_status_t status; - int attribs[] = { - EGL_WIDTH, 1, - EGL_HEIGHT, 1, - EGL_NONE, - }; - EGLConfig config; - EGLint numConfigs; - - ctx = calloc (1, sizeof (cairo_egl_context_t)); - if (unlikely (ctx == NULL)) - return _cairo_gl_context_create_in_error (CAIRO_STATUS_NO_MEMORY); - - ctx->display = dpy; - ctx->context = egl; - - ctx->base.acquire = _egl_acquire; - ctx->base.release = _egl_release; - ctx->base.make_current = _egl_make_current; - ctx->base.swap_buffers = _egl_swap_buffers; - ctx->base.destroy = _egl_destroy; - - /* We are about the change the current state of EGL, so we should - * query the pre-existing surface now instead of later. */ - _egl_query_current_state (ctx); - - if (!_egl_make_current_surfaceless (ctx)) { - /* Fall back to dummy surface, meh. */ - EGLint config_attribs[] = { - EGL_CONFIG_ID, 0, - EGL_NONE - }; - - /* - * In order to be able to make an egl context current when using a - * pbuffer surface, that surface must have been created with a config - * that is compatible with the context config. For Mesa, this means - * that the configs must be the same. - */ - eglQueryContext (dpy, egl, EGL_CONFIG_ID, &config_attribs[1]); - eglChooseConfig (dpy, config_attribs, &config, 1, &numConfigs); - - ctx->dummy_surface = eglCreatePbufferSurface (dpy, config, attribs); - if (ctx->dummy_surface == NULL) { - free (ctx); - return _cairo_gl_context_create_in_error (CAIRO_STATUS_NO_MEMORY); - } - - if (!eglMakeCurrent (dpy, ctx->dummy_surface, ctx->dummy_surface, egl)) { - free (ctx); - return _cairo_gl_context_create_in_error (CAIRO_STATUS_NO_MEMORY); - } - } - - status = _cairo_gl_dispatch_init (&ctx->base.dispatch, eglGetProcAddress); - if (unlikely (status)) { - free (ctx); - return _cairo_gl_context_create_in_error (status); - } - - status = _cairo_gl_context_init (&ctx->base); - if (unlikely (status)) { - if (ctx->dummy_surface != EGL_NO_SURFACE) - eglDestroySurface (dpy, ctx->dummy_surface); - free (ctx); - return _cairo_gl_context_create_in_error (status); - } - - /* Tune the default VBO size to reduce overhead on embedded devices. - * This smaller size means that flushing needs to be done more often, - * but it is less demanding of scarce memory on embedded devices. - */ - ctx->base.vbo_size = 16*1024; - - eglMakeCurrent (dpy, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT); - - return &ctx->base.base; -} - -cairo_surface_t * -cairo_gl_surface_create_for_egl (cairo_device_t *device, - EGLSurface egl, - int width, - int height) -{ - cairo_egl_surface_t *surface; - - if (unlikely (device->status)) - return _cairo_surface_create_in_error (device->status); - - if (device->backend->type != CAIRO_DEVICE_TYPE_GL) - return _cairo_surface_create_in_error (_cairo_error (CAIRO_STATUS_SURFACE_TYPE_MISMATCH)); - - if (width <= 0 || height <= 0) - return _cairo_surface_create_in_error (_cairo_error (CAIRO_STATUS_INVALID_SIZE)); - - surface = calloc (1, sizeof (cairo_egl_surface_t)); - if (unlikely (surface == NULL)) - return _cairo_surface_create_in_error (_cairo_error (CAIRO_STATUS_NO_MEMORY)); - - _cairo_gl_surface_init (device, &surface->base, - CAIRO_CONTENT_COLOR_ALPHA, width, height); - surface->egl = egl; - - return &surface->base.base; -} - -static cairo_bool_t is_egl_device (cairo_device_t *device) -{ - return (device->backend != NULL && - device->backend->type == CAIRO_DEVICE_TYPE_GL); -} - -static cairo_egl_context_t *to_egl_context (cairo_device_t *device) -{ - return (cairo_egl_context_t *) device; -} - -EGLDisplay -cairo_egl_device_get_display (cairo_device_t *device) -{ - if (! is_egl_device (device)) { - _cairo_error_throw (CAIRO_STATUS_DEVICE_TYPE_MISMATCH); - return EGL_NO_DISPLAY; - } - - return to_egl_context (device)->display; -} - -cairo_public EGLContext -cairo_egl_device_get_context (cairo_device_t *device) -{ - if (! is_egl_device (device)) { - _cairo_error_throw (CAIRO_STATUS_DEVICE_TYPE_MISMATCH); - return EGL_NO_CONTEXT; - } - - return to_egl_context (device)->context; -} diff --git a/gfx/cairo/cairo/src/cairo-error-private.h b/gfx/cairo/cairo/src/cairo-error-private.h index 1ab57ddf84..ba95db767e 100644 --- a/gfx/cairo/cairo/src/cairo-error-private.h +++ b/gfx/cairo/cairo/src/cairo-error-private.h @@ -98,6 +98,8 @@ enum _cairo_int_status { CAIRO_INT_STATUS_FREETYPE_ERROR, CAIRO_INT_STATUS_WIN32_GDI_ERROR, CAIRO_INT_STATUS_TAG_ERROR, + CAIRO_INT_STATUS_DWRITE_ERROR, + CAIRO_INT_STATUS_SVG_FONT_ERROR, CAIRO_INT_STATUS_LAST_STATUS, @@ -112,10 +114,10 @@ enum _cairo_int_status { typedef enum _cairo_int_status cairo_int_status_t; #define _cairo_status_is_error(status) \ - (status != CAIRO_STATUS_SUCCESS && status < CAIRO_STATUS_LAST_STATUS) + ((status) != CAIRO_STATUS_SUCCESS && (status) < CAIRO_STATUS_LAST_STATUS) #define _cairo_int_status_is_error(status) \ - (status != CAIRO_INT_STATUS_SUCCESS && status < CAIRO_INT_STATUS_LAST_STATUS) + ((status) != CAIRO_INT_STATUS_SUCCESS && (status) < CAIRO_INT_STATUS_LAST_STATUS) cairo_private cairo_status_t _cairo_error (cairo_status_t status); diff --git a/gfx/cairo/cairo/src/cairo-error.c b/gfx/cairo/cairo/src/cairo-error.c index 1b9bd76be1..2dd015f46a 100644 --- a/gfx/cairo/cairo/src/cairo-error.c +++ b/gfx/cairo/cairo/src/cairo-error.c @@ -44,7 +44,7 @@ #include <assert.h> -/** +/*< private > * _cairo_error: * @status: a status value indicating an error, (eg. not * %CAIRO_STATUS_SUCCESS) diff --git a/gfx/cairo/cairo/src/cairo-features-uninstalled.pc.in b/gfx/cairo/cairo/src/cairo-features-uninstalled.pc.in deleted file mode 100644 index b9cd9d3ad2..0000000000 --- a/gfx/cairo/cairo/src/cairo-features-uninstalled.pc.in +++ /dev/null @@ -1,7 +0,0 @@ -Name: @FEATURE_PC@ -Description: @FEATURE_NAME@ for cairo graphics library -Version: @VERSION@ - -Requires: @FEATURE_BASE@ @FEATURE_REQUIRES@ -Libs: @FEATURE_NONPKGCONFIG_LIBS@ @FEATURE_NONPKGCONFIG_EXTRA_LIBS@ -Cflags: -I${pc_top_builddir}/${pcfiledir}/@srcdir@/src @FEATURE_NONPKGCONFIG_CFLAGS@ diff --git a/gfx/cairo/cairo/src/cairo-features.h b/gfx/cairo/cairo/src/cairo-features.h index 6ccfd25b4f..4262816f98 100644 --- a/gfx/cairo/cairo/src/cairo-features.h +++ b/gfx/cairo/cairo/src/cairo-features.h @@ -75,6 +75,10 @@ #define CAIRO_HAS_QUARTZ_APPLICATION_SERVICES 1 #endif +#if defined(MOZ_WIDGET_UIKIT) +#define CAIRO_HAS_IMAGE_IO 1 +#endif + #ifdef XP_WIN #define CAIRO_HAS_DWRITE_FONT 1 #define CAIRO_HAS_WIN32_FONT 1 diff --git a/gfx/cairo/cairo/src/cairo-features.pc.in b/gfx/cairo/cairo/src/cairo-features.pc.in deleted file mode 100644 index 9a4b657c8d..0000000000 --- a/gfx/cairo/cairo/src/cairo-features.pc.in +++ /dev/null @@ -1,12 +0,0 @@ -prefix=@prefix@ -exec_prefix=@exec_prefix@ -libdir=@libdir@ -includedir=@includedir@ - -Name: @FEATURE_PC@ -Description: @FEATURE_NAME@ for cairo graphics library -Version: @VERSION@ - -Requires: @FEATURE_BASE@ @FEATURE_REQUIRES@ -Libs: @FEATURE_NONPKGCONFIG_LIBS@ @FEATURE_NONPKGCONFIG_EXTRA_LIBS@ -Cflags: -I${includedir}/cairo @FEATURE_NONPKGCONFIG_CFLAGS@ diff --git a/gfx/cairo/cairo/src/cairo-fixed-private.h b/gfx/cairo/cairo/src/cairo-fixed-private.h index 5f9ce684c3..97329c36fc 100644 --- a/gfx/cairo/cairo/src/cairo-fixed-private.h +++ b/gfx/cairo/cairo/src/cairo-fixed-private.h @@ -53,6 +53,11 @@ #define CAIRO_FIXED_ONE_DOUBLE ((double)(1 << CAIRO_FIXED_FRAC_BITS)) #define CAIRO_FIXED_EPSILON ((cairo_fixed_t)(1)) +#define CAIRO_FIXED_MAX INT32_MAX /* Maximum fixed point value */ +#define CAIRO_FIXED_MIN INT32_MIN /* Minimum fixed point value */ +#define CAIRO_FIXED_MAX_DOUBLE (((double) CAIRO_FIXED_MAX) / CAIRO_FIXED_ONE_DOUBLE) +#define CAIRO_FIXED_MIN_DOUBLE (((double) CAIRO_FIXED_MIN) / CAIRO_FIXED_ONE_DOUBLE) + #define CAIRO_FIXED_ERROR_DOUBLE (1. / (2 * CAIRO_FIXED_ONE_DOUBLE)) #define CAIRO_FIXED_FRAC_MASK ((cairo_fixed_t)(((cairo_fixed_unsigned_t)(-1)) >> (CAIRO_FIXED_BITS - CAIRO_FIXED_FRAC_BITS))) @@ -61,7 +66,7 @@ static inline cairo_fixed_t _cairo_fixed_from_int (int i) { - return i << CAIRO_FIXED_FRAC_BITS; + return (cairo_fixed_unsigned_t)i << CAIRO_FIXED_FRAC_BITS; } /* This is the "magic number" approach to converting a double into fixed @@ -129,6 +134,17 @@ _cairo_fixed_from_double (double d) #endif static inline cairo_fixed_t +_cairo_fixed_from_double_clamped (double d, double tolerance) +{ + if (d > CAIRO_FIXED_MAX_DOUBLE - tolerance) + d = CAIRO_FIXED_MAX_DOUBLE - tolerance; + else if (d < CAIRO_FIXED_MIN_DOUBLE + tolerance) + d = CAIRO_FIXED_MIN_DOUBLE + tolerance; + + return _cairo_fixed_from_double (d); +} + +static inline cairo_fixed_t _cairo_fixed_from_26_6 (uint32_t i) { #if CAIRO_FIXED_FRAC_BITS > 6 diff --git a/gfx/cairo/cairo/src/cairo-font-face.c b/gfx/cairo/cairo/src/cairo-font-face.c index e10a6eac2f..c5569eb2e9 100644 --- a/gfx/cairo/cairo/src/cairo-font-face.c +++ b/gfx/cairo/cairo/src/cairo-font-face.c @@ -133,7 +133,6 @@ cairo_font_face_reference (cairo_font_face_t *font_face) return font_face; } -slim_hidden_def (cairo_font_face_reference); static inline cairo_bool_t __put(cairo_reference_count_t *v) @@ -190,7 +189,6 @@ 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: @@ -272,7 +270,6 @@ cairo_font_face_get_user_data (cairo_font_face_t *font_face, return _cairo_user_data_array_get_data (&font_face->user_data, key); } -slim_hidden_def (cairo_font_face_get_user_data); /** * cairo_font_face_set_user_data: @@ -304,7 +301,6 @@ cairo_font_face_set_user_data (cairo_font_face_t *font_face, return _cairo_user_data_array_set_data (&font_face->user_data, key, user_data, destroy); } -slim_hidden_def (cairo_font_face_set_user_data); void _cairo_unscaled_font_init (cairo_unscaled_font_t *unscaled_font, diff --git a/gfx/cairo/cairo/src/cairo-font-options.c b/gfx/cairo/cairo/src/cairo-font-options.c index 7064d00acd..e9e64aa252 100644 --- a/gfx/cairo/cairo/src/cairo-font-options.c +++ b/gfx/cairo/cairo/src/cairo-font-options.c @@ -56,7 +56,10 @@ static const cairo_font_options_t _cairo_font_options_nil = { CAIRO_HINT_STYLE_DEFAULT, CAIRO_HINT_METRICS_DEFAULT, CAIRO_ROUND_GLYPH_POS_DEFAULT, - NULL + NULL, /* variations */ + CAIRO_COLOR_MODE_DEFAULT, + CAIRO_COLOR_PALETTE_DEFAULT, + NULL, 0, /* custom palette */ }; /** @@ -75,6 +78,10 @@ _cairo_font_options_init_default (cairo_font_options_t *options) options->hint_metrics = CAIRO_HINT_METRICS_DEFAULT; options->round_glyph_positions = CAIRO_ROUND_GLYPH_POS_DEFAULT; options->variations = NULL; + options->color_mode = CAIRO_COLOR_MODE_DEFAULT; + options->palette_index = CAIRO_COLOR_PALETTE_DEFAULT; + options->custom_palette = NULL; + options->custom_palette_size = 0; } void @@ -88,6 +95,49 @@ _cairo_font_options_init_copy (cairo_font_options_t *options, options->hint_metrics = other->hint_metrics; options->round_glyph_positions = other->round_glyph_positions; options->variations = other->variations ? strdup (other->variations) : NULL; + options->color_mode = other->color_mode; + options->palette_index = other->palette_index; + options->custom_palette_size = other->custom_palette_size; + options->custom_palette = NULL; + if (other->custom_palette) { + options->custom_palette = (cairo_palette_color_t *) malloc (sizeof (cairo_palette_color_t) * options->custom_palette_size); + memcpy (options->custom_palette, other->custom_palette, sizeof (cairo_palette_color_t) * options->custom_palette_size); + } +} + +cairo_bool_t +_cairo_font_options_compare (const cairo_font_options_t *a, + const cairo_font_options_t *b) +{ + if (a->antialias != b->antialias || + a->subpixel_order != b->subpixel_order || + a->lcd_filter != b->lcd_filter || + a->hint_style != b->hint_style || + a->hint_metrics != b->hint_metrics || + a->round_glyph_positions != b->round_glyph_positions || + a->color_mode != b->color_mode || + a->palette_index != b->palette_index || + a->custom_palette_size != b->custom_palette_size) + { + return FALSE; + } + + if (a->variations && b->variations && strcmp (a->variations, b->variations) != 0) + return FALSE; + else if (a->variations != b->variations) + return FALSE; + + if (a->custom_palette && b->custom_palette && + memcmp (a->custom_palette, b->custom_palette, sizeof (cairo_palette_color_t) * a->custom_palette_size) != 0) + { + return FALSE; + } + else if (a->custom_palette != b->custom_palette) + { + return FALSE; + } + + return TRUE; } /** @@ -158,6 +208,7 @@ void _cairo_font_options_fini (cairo_font_options_t *options) { free (options->variations); + free (options->custom_palette); } /** @@ -186,7 +237,8 @@ cairo_font_options_destroy (cairo_font_options_t *options) * Checks whether an error has previously occurred for this * font options object * - * Return value: %CAIRO_STATUS_SUCCESS or %CAIRO_STATUS_NO_MEMORY + * Return value: %CAIRO_STATUS_SUCCESS, %CAIRO_STATUS_NO_MEMORY, or + * %CAIRO_STATUS_NULL_POINTER. * * Since: 1.0 **/ @@ -200,7 +252,6 @@ cairo_font_options_status (cairo_font_options_t *options) else return CAIRO_STATUS_SUCCESS; } -slim_hidden_def (cairo_font_options_status); /** * cairo_font_options_merge: @@ -254,8 +305,18 @@ cairo_font_options_merge (cairo_font_options_t *options, options->variations = strdup (other->variations); } } + + if (other->color_mode != CAIRO_COLOR_MODE_DEFAULT) + options->color_mode = other->color_mode; + if (other->palette_index != CAIRO_COLOR_PALETTE_DEFAULT) + options->palette_index = other->palette_index; + if (other->custom_palette) { + options->custom_palette_size = other->custom_palette_size; + free (options->custom_palette); + options->custom_palette = (cairo_palette_color_t *) malloc (sizeof (cairo_palette_color_t) * options->custom_palette_size); + memcpy (options->custom_palette, other->custom_palette, sizeof (cairo_palette_color_t) * options->custom_palette_size); + } } -slim_hidden_def (cairo_font_options_merge); /** * cairo_font_options_equal: @@ -290,9 +351,15 @@ cairo_font_options_equal (const cairo_font_options_t *options, options->round_glyph_positions == other->round_glyph_positions && ((options->variations == NULL && other->variations == NULL) || (options->variations != NULL && other->variations != NULL && - strcmp (options->variations, other->variations) == 0))); + strcmp (options->variations, other->variations) == 0)) && + options->color_mode == other->color_mode && + options->palette_index == other->palette_index && + ((options->custom_palette == NULL && other->custom_palette == NULL) || + (options->custom_palette != NULL && other->custom_palette != NULL && + options->custom_palette_size == other->custom_palette_size && + memcmp (options->custom_palette, other->custom_palette, + sizeof (cairo_palette_color_t) * options->custom_palette_size) == 0))); } -slim_hidden_def (cairo_font_options_equal); /** * cairo_font_options_hash: @@ -319,13 +386,15 @@ cairo_font_options_hash (const cairo_font_options_t *options) if (options->variations) hash = _cairo_string_hash (options->variations, strlen (options->variations)); + hash ^= options->palette_index; + return ((options->antialias) | (options->subpixel_order << 4) | (options->lcd_filter << 8) | (options->hint_style << 12) | - (options->hint_metrics << 16)) ^ hash; + (options->hint_metrics << 16) | + (options->color_mode << 20)) ^ hash; } -slim_hidden_def (cairo_font_options_hash); /** * cairo_font_options_set_antialias: @@ -346,7 +415,6 @@ 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: @@ -389,7 +457,6 @@ 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: @@ -505,7 +572,6 @@ 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: @@ -548,7 +614,6 @@ 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: @@ -620,3 +685,187 @@ cairo_font_options_get_variations (cairo_font_options_t *options) { return options->variations; } + +/** + * cairo_font_options_set_color_mode: + * @options: a #cairo_font_options_t + * @color_mode: the new color mode + * + * Sets the color mode for the font options object. This controls + * whether color fonts are to be rendered in color or as outlines. + * See the documentation for #cairo_color_mode_t for full details. + * + * Since: 1.18 + **/ +cairo_public void +cairo_font_options_set_color_mode (cairo_font_options_t *options, + cairo_color_mode_t color_mode) +{ + if (cairo_font_options_status (options)) + return; + + options->color_mode = color_mode; +} + +/** + * cairo_font_options_get_color_mode: + * @options: a #cairo_font_options_t + * + * Gets the color mode for the font options object. + * See the documentation for #cairo_color_mode_t for full details. + * + * Return value: the color mode for the font options object + * + * Since: 1.18 + **/ +cairo_public cairo_color_mode_t +cairo_font_options_get_color_mode (const cairo_font_options_t *options) +{ + if (cairo_font_options_status ((cairo_font_options_t *) options)) + return CAIRO_COLOR_MODE_DEFAULT; + + return options->color_mode; +} + +/** + * CAIRO_COLOR_PALETTE_DEFAULT: + * + * The default color palette index. + * + * Since: 1.18 + **/ + +/** + * cairo_font_options_set_color_palette: + * @options: a #cairo_font_options_t + * @palette_index: the palette index in the CPAL table + * + * Sets the OpenType font color palette for the font options + * object. OpenType color fonts with a CPAL table may contain multiple + * palettes. The default color palette index is %CAIRO_COLOR_PALETTE_DEFAULT. + * + * If @palette_index is invalid, the default palette is used. + * + * Individual colors within the palette may be overriden with + * cairo_font_options_set_custom_palette_color(). + * + * Since: 1.18 + **/ +void +cairo_font_options_set_color_palette (cairo_font_options_t *options, + unsigned int palette_index) +{ + if (cairo_font_options_status (options)) + return; + + options->palette_index = palette_index; +} + +/** + * cairo_font_options_get_color_palette: + * @options: a #cairo_font_options_t + * + * Gets the current OpenType color font palette for the font options object. + * + * Return value: the palette index + * + * Since: 1.18 + **/ +unsigned int +cairo_font_options_get_color_palette (const cairo_font_options_t *options) +{ + if (cairo_font_options_status ((cairo_font_options_t *) options)) + return CAIRO_COLOR_PALETTE_DEFAULT; + + return options->palette_index; +} + +/** + * cairo_font_options_set_custom_palette_color: + * @options: a #cairo_font_options_t + * @index: the index of the color to set + * @red: red component of color + * @green: green component of color + * @blue: blue component of color + * @alpha: alpha component of color + * + * Sets a custom palette color for the font options object. This + * overrides the palette color at the specified color index. This override is + * independent of the selected palette index and will remain in place + * even if cairo_font_options_set_color_palette() is called to change + * the palette index. + * + * It is only possible to override color indexes already in the font + * palette. + * + * Since: 1.18 + */ +void +cairo_font_options_set_custom_palette_color (cairo_font_options_t *options, + unsigned int index, + double red, double green, + double blue, double alpha) +{ + unsigned int idx; + + for (idx = 0; idx < options->custom_palette_size; idx++) { + if (options->custom_palette[idx].index == index) { + break; + } + } + + if (idx == options->custom_palette_size) { + options->custom_palette_size++; + options->custom_palette = (cairo_palette_color_t *) + _cairo_realloc_ab (options->custom_palette, + sizeof (cairo_palette_color_t), + options->custom_palette_size); + } + + /* beware of holes */ + memset (&options->custom_palette[idx], 0, sizeof (cairo_palette_color_t)); + + options->custom_palette[idx].index = index; + options->custom_palette[idx].red = red; + options->custom_palette[idx].green = green; + options->custom_palette[idx].blue = blue; + options->custom_palette[idx].alpha = alpha; +} + +/** + * cairo_font_options_get_custom_palette_color: + * @options: a #cairo_font_options_t + * @index: the index of the color to get + * @red: return location for red component of color + * @green: return location for green component of color + * @blue: return location for blue component of color + * @alpha: return location for alpha component of color + * + * Gets the custom palette color for the color index for the font options object. + * + * Returns: `CAIRO_STATUS_SUCCESS` if a custom palette color is + * returned, `CAIRO_STATUS_INVALID_INDEX` if no custom color exists + * for the color index. + * + * Since: 1.18 + */ +cairo_status_t +cairo_font_options_get_custom_palette_color (cairo_font_options_t *options, + unsigned int index, + double *red, double *green, + double *blue, double *alpha) +{ + unsigned int idx; + + for (idx = 0; idx < options->custom_palette_size; idx++) { + if (options->custom_palette[idx].index == index) { + *red = options->custom_palette[idx].red; + *green = options->custom_palette[idx].green; + *blue = options->custom_palette[idx].blue; + *alpha = options->custom_palette[idx].alpha; + return CAIRO_STATUS_SUCCESS; + } + } + + return CAIRO_STATUS_INVALID_INDEX; +} diff --git a/gfx/cairo/cairo/src/cairo-ft-font.c b/gfx/cairo/cairo/src/cairo-ft-font.c index 7b2afea237..00cfd3a261 100644 --- a/gfx/cairo/cairo/src/cairo-ft-font.c +++ b/gfx/cairo/cairo/src/cairo-ft-font.c @@ -44,8 +44,11 @@ #include "cairo-error-private.h" #include "cairo-image-surface-private.h" #include "cairo-ft-private.h" +#include "cairo-list-inline.h" +#include "cairo-path-private.h" #include "cairo-pattern-private.h" #include "cairo-pixman-private.h" +#include "cairo-recording-surface-private.h" #include <float.h> @@ -63,13 +66,21 @@ #include FT_SYNTHESIS_H #endif +#ifdef FT_COLOR_H +#include FT_COLOR_H +#endif + #if HAVE_FT_LIBRARY_SETLCDFILTER #include FT_LCD_FILTER_H #endif +#if HAVE_FT_SVG_DOCUMENT +#include FT_OTSVG_H +#endif + #if HAVE_UNISTD_H #include <unistd.h> -#else +#elif !defined(access) #define access(p, m) 0 #endif #include <dlfcn.h> @@ -94,6 +105,11 @@ #define FT_LCD_FILTER_LEGACY 16 #endif +/* FreeType version older than 2.11 does not have the FT_RENDER_MODE_SDF enum value in FT_Render_Mode */ +#if FREETYPE_MAJOR > 2 || (FREETYPE_MAJOR == 2 && FREETYPE_MINOR >= 11) +#define HAVE_FT_RENDER_MODE_SDF 1 +#endif + #define DOUBLE_FROM_26_6(t) ((double)(t) / 64.0) #define DOUBLE_TO_16_16(d) ((FT_Fixed)((d) * 65536.0)) #define DOUBLE_FROM_16_16(t) ((double)(t) / 65536.0) @@ -201,6 +217,7 @@ struct _cairo_ft_unscaled_font { unsigned int have_color_set : 1; unsigned int have_color : 1; /* true if the font contains color glyphs */ FT_Fixed *variations; /* variation settings that FT_Face came */ + unsigned int num_palettes; cairo_mutex_t mutex; int lock_count; @@ -265,17 +282,19 @@ _cairo_ft_resolve_pattern (FcPattern *pattern, #endif -static cairo_status_t -_ft_to_cairo_error (FT_Error error) +cairo_status_t +_cairo_ft_to_cairo_error (FT_Error error) { /* Currently we don't get many (any?) useful statuses here. * Populate as needed. */ switch (error) { - case FT_Err_Out_Of_Memory: - return CAIRO_STATUS_NO_MEMORY; - default: - return CAIRO_STATUS_FREETYPE_ERROR; + case FT_Err_Ok: + return CAIRO_STATUS_SUCCESS; + case FT_Err_Out_Of_Memory: + return CAIRO_STATUS_NO_MEMORY; + default: + return CAIRO_STATUS_FREETYPE_ERROR; } } @@ -430,7 +449,7 @@ _cairo_ft_unscaled_font_init_key (cairo_ft_unscaled_font_t *key, FT_Face face, void *face_context) { - unsigned long hash; + uintptr_t hash; key->from_face = from_face; key->filename = filename; @@ -440,8 +459,8 @@ _cairo_ft_unscaled_font_init_key (cairo_ft_unscaled_font_t *key, hash = _cairo_hash_string (filename); /* the constants are just arbitrary primes */ - hash += ((unsigned long) id) * 1607; - hash += ((unsigned long) face) * 2137; + hash += ((uintptr_t) id) * 1607; + hash += ((uintptr_t) face) * 2137; key->base.hash_entry.hash = hash; } @@ -805,7 +824,7 @@ _cairo_ft_unscaled_font_lock_face (cairo_ft_unscaled_font_t *unscaled) { unscaled->lock_count--; CAIRO_FT_UNLOCK (unscaled); - _cairo_error_throw (_ft_to_cairo_error (error)); + _cairo_error_throw (_cairo_ft_to_cairo_error (error)); return NULL; } @@ -962,7 +981,7 @@ _cairo_ft_unscaled_font_set_scale (cairo_ft_unscaled_font_t *unscaled, sf.y_scale * 64.0 + .5, 0, 0); if (error) - return _cairo_error (_ft_to_cairo_error (error)); + return _cairo_error (_cairo_ft_to_cairo_error (error)); return CAIRO_STATUS_SUCCESS; } @@ -1249,7 +1268,7 @@ _fill_xrender_bitmap(FT_Bitmap *target, #ifdef FT_LOAD_COLOR case FT_PIXEL_MODE_BGRA: for (h = height; h > 0; h--, srcLine += src_pitch, dstLine += pitch) - memcpy (dstLine, srcLine, width * 4); + memcpy (dstLine, srcLine, (size_t)width * 4); break; #endif @@ -1296,7 +1315,7 @@ _get_bitmap_surface (FT_Bitmap *bitmap, return _cairo_error (CAIRO_STATUS_NO_MEMORY); if (stride == bitmap->pitch) { - memcpy (data, bitmap->buffer, stride * height); + memcpy (data, bitmap->buffer, (size_t)stride * height); } else { int i; unsigned char *source, *dest; @@ -1349,7 +1368,7 @@ _get_bitmap_surface (FT_Bitmap *bitmap, if (!data) return _cairo_error (CAIRO_STATUS_NO_MEMORY); - memcpy (data, bitmap->buffer, stride * height); + memcpy (data, bitmap->buffer, (size_t)stride * height); } format = CAIRO_FORMAT_A8; @@ -1370,7 +1389,7 @@ _get_bitmap_surface (FT_Bitmap *bitmap, if (!data) return _cairo_error (CAIRO_STATUS_NO_MEMORY); - memcpy (data, bitmap->buffer, stride * height); + memcpy (data, bitmap->buffer, (size_t)stride * height); } if (!_cairo_is_little_endian ()) @@ -1379,7 +1398,7 @@ _get_bitmap_surface (FT_Bitmap *bitmap, unsigned int i, count = height * width; uint32_t *p = (uint32_t *) data; for (i = 0; i < count; i++) - p[i] = be32_to_cpu (p[i]); + p[i] = bswap_32 (p[i]); } format = CAIRO_FORMAT_ARGB32; break; @@ -1404,7 +1423,7 @@ _get_bitmap_surface (FT_Bitmap *bitmap, error = FT_Bitmap_Convert( library, bitmap, &tmp, align ); if (error) - return _cairo_error (_ft_to_cairo_error (error)); + return _cairo_error (_cairo_ft_to_cairo_error (error)); FT_Bitmap_Done( library, bitmap ); *bitmap = tmp; @@ -1426,7 +1445,7 @@ _get_bitmap_surface (FT_Bitmap *bitmap, } } - memcpy (data, bitmap->buffer, stride * height); + memcpy (data, bitmap->buffer, (size_t)stride * height); break; } /* fall through */ @@ -1478,7 +1497,7 @@ _render_glyph_outline (FT_Face face, cairo_image_surface_t **surface) { int rgba = FC_RGBA_UNKNOWN; - int lcd_filter = FT_LCD_FILTER_LEGACY; + int lcd_filter = FT_LCD_FILTER_DEFAULT; FT_GlyphSlot glyphslot = face->glyph; FT_Outline *outline = &glyphslot->outline; FT_Bitmap bitmap; @@ -1513,13 +1532,13 @@ _render_glyph_outline (FT_Face face, case CAIRO_LCD_FILTER_NONE: lcd_filter = FT_LCD_FILTER_NONE; break; - case CAIRO_LCD_FILTER_DEFAULT: case CAIRO_LCD_FILTER_INTRA_PIXEL: lcd_filter = FT_LCD_FILTER_LEGACY; break; case CAIRO_LCD_FILTER_FIR3: lcd_filter = FT_LCD_FILTER_LIGHT; break; + case CAIRO_LCD_FILTER_DEFAULT: case CAIRO_LCD_FILTER_FIR5: lcd_filter = FT_LCD_FILTER_DEFAULT; break; @@ -1558,6 +1577,9 @@ _render_glyph_outline (FT_Face face, case FT_RENDER_MODE_LIGHT: case FT_RENDER_MODE_NORMAL: case FT_RENDER_MODE_MAX: +#if HAVE_FT_RENDER_MODE_SDF + case FT_RENDER_MODE_SDF: +#endif default: format = CAIRO_FORMAT_A8; break; @@ -1591,6 +1613,9 @@ _render_glyph_outline (FT_Face face, case FT_RENDER_MODE_LIGHT: case FT_RENDER_MODE_NORMAL: case FT_RENDER_MODE_MAX: +#if HAVE_FT_RENDER_MODE_SDF + case FT_RENDER_MODE_SDF: +#endif default: break; } @@ -1606,7 +1631,7 @@ _render_glyph_outline (FT_Face face, #endif if (error) - return _cairo_error (_ft_to_cairo_error (error)); + return _cairo_error (_cairo_ft_to_cairo_error (error)); bitmap_size = _compute_xrender_bitmap_size (&bitmap, face->glyph, @@ -2005,8 +2030,7 @@ _cairo_ft_options_merge (cairo_ft_options_t *options, } if (other->base.antialias == CAIRO_ANTIALIAS_SUBPIXEL && - (options->base.antialias == CAIRO_ANTIALIAS_DEFAULT || - options->base.antialias == CAIRO_ANTIALIAS_GRAY)) { + options->base.antialias == CAIRO_ANTIALIAS_DEFAULT) { options->base.antialias = CAIRO_ANTIALIAS_SUBPIXEL; options->base.subpixel_order = other->base.subpixel_order; } @@ -2213,6 +2237,7 @@ _cairo_ft_scaled_font_fini (void *abstract_font) if (scaled_font == NULL) return; + _cairo_font_options_fini (&scaled_font->ft_options.base); _cairo_unscaled_font_destroy (&scaled_font->unscaled->base); } @@ -2310,10 +2335,9 @@ _cubic_to (FT_Vector *control1, FT_Vector *control2, return 0; } -static cairo_status_t -_decompose_glyph_outline (FT_Face face, - cairo_font_options_t *options, - cairo_path_fixed_t **pathp) +cairo_status_t +_cairo_ft_face_decompose_glyph_outline (FT_Face face, + cairo_path_fixed_t **pathp) { static const FT_Outline_Funcs outline_funcs = { (FT_Outline_MoveToFunc)_move_to, @@ -2553,250 +2577,1078 @@ _cairo_ft_scaled_glyph_load_glyph (cairo_ft_scaled_font_t *scaled_font, return CAIRO_STATUS_SUCCESS; } +typedef enum { + CAIRO_FT_GLYPH_TYPE_BITMAP, + CAIRO_FT_GLYPH_TYPE_OUTLINE, + CAIRO_FT_GLYPH_TYPE_SVG, + CAIRO_FT_GLYPH_TYPE_COLR_V0, + CAIRO_FT_GLYPH_TYPE_COLR_V1, +} cairo_ft_glyph_format_t; + +typedef struct { + cairo_scaled_glyph_private_t base; + + cairo_ft_glyph_format_t format; +} cairo_ft_glyph_private_t; + +static void +_cairo_ft_glyph_fini (cairo_scaled_glyph_private_t *glyph_private, + cairo_scaled_glyph_t *glyph, + cairo_scaled_font_t *font) +{ + cairo_list_del (&glyph_private->link); + free (glyph_private); +} + + +#ifdef FT_COLOR_H +static void +_cairo_ft_scaled_glyph_set_palette (cairo_ft_scaled_font_t *scaled_font, + FT_Face face, + unsigned int *num_entries_ret, + FT_Color **entries_ret) +{ + unsigned int num_entries = 0; + FT_Color *entries = NULL; + +#ifdef HAVE_FT_PALETTE_SELECT + FT_Palette_Data palette_data; + + if (FT_Palette_Data_Get (face, &palette_data) == 0 && palette_data.num_palettes > 0) { + FT_UShort palette_index = CAIRO_COLOR_PALETTE_DEFAULT; + if (scaled_font->base.options.palette_index < palette_data.num_palettes) + palette_index = scaled_font->base.options.palette_index; + + if (FT_Palette_Select (face, palette_index, &entries) == 0) { + num_entries = palette_data.num_palette_entries; + + /* Overlay custom colors */ + for (unsigned int i = 0; i < scaled_font->base.options.custom_palette_size; i++) { + cairo_palette_color_t *entry = &scaled_font->base.options.custom_palette[i]; + if (entry->index < num_entries) { + entries[entry->index].red = 255 * entry->red; + entries[entry->index].green = 255 * entry->green; + entries[entry->index].blue = 255 * entry->blue; + entries[entry->index].alpha = 255 * entry->alpha; + } + } + } + } +#endif + + if (num_entries_ret) + *num_entries_ret = num_entries; + + if (entries_ret) + *entries_ret = entries; +} +#else +static void +_cairo_ft_scaled_glyph_set_palette (cairo_ft_scaled_font_t *scaled_font, + FT_Face face, + unsigned int *num_entries_ret, + void **entries_ret) +{ + if (num_entries_ret) + *num_entries_ret = 0; + + if (entries_ret) + *entries_ret = NULL; +} +#endif + +/* returns TRUE if foreground color used */ +static cairo_bool_t +_cairo_ft_scaled_glyph_set_foreground_color (cairo_ft_scaled_font_t *scaled_font, + cairo_scaled_glyph_t *scaled_glyph, + FT_Face face, + const cairo_color_t *foreground_color) +{ + cairo_bool_t uses_foreground_color = FALSE; +#ifdef HAVE_FT_PALETTE_SELECT + FT_LayerIterator iterator; + FT_UInt layer_glyph_index; + FT_UInt layer_color_index; + FT_Color color; + + /* Check if there is a layer that uses the foreground color */ + iterator.p = NULL; + while (FT_Get_Color_Glyph_Layer(face, + _cairo_scaled_glyph_index (scaled_glyph), + &layer_glyph_index, + &layer_color_index, + &iterator)) { + if (layer_color_index == 0xFFFF) { + uses_foreground_color = TRUE; + break; + } + } + + if (uses_foreground_color) { + color.red = (FT_Byte)(foreground_color->red * 0xFF); + color.green = (FT_Byte)(foreground_color->green * 0xFF); + color.blue = (FT_Byte)(foreground_color->blue * 0xFF); + color.alpha = (FT_Byte)(foreground_color->alpha * 0xFF); + FT_Palette_Set_Foreground_Color (face, color); + } +#endif + return uses_foreground_color; +} + static cairo_int_status_t -_cairo_ft_scaled_glyph_init (void *abstract_font, - cairo_scaled_glyph_t *scaled_glyph, - cairo_scaled_glyph_info_t info) +_cairo_ft_scaled_glyph_init_surface (cairo_ft_scaled_font_t *scaled_font, + cairo_scaled_glyph_t *scaled_glyph, + cairo_ft_glyph_private_t *glyph_priv, + cairo_scaled_glyph_info_t info, + FT_Face face, + const cairo_color_t *foreground_color, + cairo_bool_t vertical_layout, + int load_flags) { - cairo_text_extents_t fs_metrics; - cairo_ft_scaled_font_t *scaled_font = abstract_font; cairo_ft_unscaled_font_t *unscaled = scaled_font->unscaled; FT_GlyphSlot glyph; - FT_Face face; - int load_flags = scaled_font->ft_options.load_flags; - FT_Glyph_Metrics *metrics; - double x_factor, y_factor; - cairo_bool_t vertical_layout = FALSE; - cairo_status_t status = CAIRO_STATUS_SUCCESS; - cairo_bool_t scaled_glyph_loaded = FALSE; + cairo_status_t status; + cairo_image_surface_t *surface; + cairo_bool_t uses_foreground_color = FALSE; - face = _cairo_ft_unscaled_font_lock_face (unscaled); - if (!face) - return _cairo_error (CAIRO_STATUS_NO_MEMORY); + /* Only one info type at a time handled in this function */ + assert (info == CAIRO_SCALED_GLYPH_INFO_COLOR_SURFACE || info == CAIRO_SCALED_GLYPH_INFO_SURFACE); - /* Ignore global advance unconditionally */ - load_flags |= FT_LOAD_IGNORE_GLOBAL_ADVANCE_WIDTH; + if (info == CAIRO_SCALED_GLYPH_INFO_COLOR_SURFACE) { + if (!unscaled->have_color) { + scaled_glyph->color_glyph = FALSE; + scaled_glyph->color_glyph_set = TRUE; + return CAIRO_INT_STATUS_UNSUPPORTED; + } - if ((info & CAIRO_SCALED_GLYPH_INFO_PATH) != 0 && - (info & (CAIRO_SCALED_GLYPH_INFO_SURFACE | - CAIRO_SCALED_GLYPH_INFO_COLOR_SURFACE)) == 0) { - load_flags |= FT_LOAD_NO_BITMAP; + uses_foreground_color = _cairo_ft_scaled_glyph_set_foreground_color (scaled_font, + scaled_glyph, + face, + foreground_color); + _cairo_ft_scaled_glyph_set_palette (scaled_font, face, NULL, NULL); + + load_flags &= ~FT_LOAD_MONOCHROME; + /* clear load target mode */ + load_flags &= ~(FT_LOAD_TARGET_(FT_LOAD_TARGET_MODE(load_flags))); + load_flags |= FT_LOAD_TARGET_NORMAL; +#ifdef FT_LOAD_COLOR + load_flags |= FT_LOAD_COLOR; +#endif + } else { /* info == CAIRO_SCALED_GLYPH_INFO_SURFACE */ +#ifdef FT_LOAD_COLOR + load_flags &= ~FT_LOAD_COLOR; +#endif } - /* - * Don't pass FT_LOAD_VERTICAL_LAYOUT to FT_Load_Glyph here as - * suggested by freetype people. - */ - if (load_flags & FT_LOAD_VERTICAL_LAYOUT) { - load_flags &= ~FT_LOAD_VERTICAL_LAYOUT; - vertical_layout = TRUE; + status = _cairo_ft_scaled_glyph_load_glyph (scaled_font, + scaled_glyph, + face, + load_flags, + FALSE, + vertical_layout); + if (unlikely (status)) + return status; + + glyph = face->glyph; + + if (glyph_priv->format == CAIRO_FT_GLYPH_TYPE_OUTLINE) { + + status = _render_glyph_outline (face, &scaled_font->ft_options.base, + &surface); + } else { + status = _render_glyph_bitmap (face, &scaled_font->ft_options.base, + &surface); + if (likely (status == CAIRO_STATUS_SUCCESS) && unscaled->have_shape) { + status = _transform_glyph_bitmap (&unscaled->current_shape, + &surface); + if (unlikely (status)) + cairo_surface_destroy (&surface->base); + } } -#ifdef FT_LOAD_COLOR + if (unlikely (status)) + return status; + + if (info == CAIRO_SCALED_GLYPH_INFO_COLOR_SURFACE) { + /* We tried loading a color glyph and can now check if we got + * a color glyph and set scaled_glyph->color_glyph + * accordingly */ + if (pixman_image_get_format (surface->pixman_image) == PIXMAN_a8r8g8b8 && + !pixman_image_get_component_alpha (surface->pixman_image)) + { + _cairo_scaled_glyph_set_color_surface (scaled_glyph, + &scaled_font->base, + surface, + uses_foreground_color ? foreground_color : NULL); + + scaled_glyph->color_glyph = TRUE; + } else { + /* We didn't ask for a non-color surface, but store it + * anyway so we don't have to load it again. */ + _cairo_scaled_glyph_set_surface (scaled_glyph, + &scaled_font->base, + surface); + scaled_glyph->color_glyph = FALSE; + status = CAIRO_INT_STATUS_UNSUPPORTED; + } + scaled_glyph->color_glyph_set = TRUE; + } else { /* info == CAIRO_SCALED_GLYPH_INFO_SURFACE */ + _cairo_scaled_glyph_set_surface (scaled_glyph, + &scaled_font->base, + surface); + } + + return status; +} + +static cairo_int_status_t +_cairo_ft_scaled_glyph_init_record_colr_v0_glyph (cairo_ft_scaled_font_t *scaled_font, + cairo_scaled_glyph_t *scaled_glyph, + FT_Face face, + cairo_bool_t vertical_layout, + int load_flags) +{ +#ifdef HAVE_FT_PALETTE_SELECT + cairo_surface_t *recording_surface; + cairo_t *cr; + cairo_status_t status; + FT_Color *palette; + unsigned int num_palette_entries; + FT_LayerIterator iterator; + FT_UInt layer_glyph_index; + FT_UInt layer_color_index; + cairo_path_fixed_t *path_fixed; + cairo_path_t *path; + + _cairo_ft_scaled_glyph_set_palette (scaled_font, face, &num_palette_entries, &palette); + + load_flags &= ~FT_LOAD_MONOCHROME; + /* clear load target mode */ + load_flags &= ~(FT_LOAD_TARGET_(FT_LOAD_TARGET_MODE(load_flags))); + load_flags |= FT_LOAD_TARGET_NORMAL; load_flags |= FT_LOAD_COLOR; -#endif + recording_surface = + cairo_recording_surface_create (CAIRO_CONTENT_COLOR_ALPHA, NULL); - if (info & CAIRO_SCALED_GLYPH_INFO_METRICS) { + cr = cairo_create (recording_surface); - cairo_bool_t hint_metrics = scaled_font->base.options.hint_metrics != CAIRO_HINT_METRICS_OFF; + if (!_cairo_matrix_is_scale_0 (&scaled_font->base.scale)) { + cairo_matrix_t scale; + scale = scaled_font->base.scale; + scale.x0 = scale.y0 = 0.; + cairo_set_matrix (cr, &scale); + } - status = _cairo_ft_scaled_glyph_load_glyph (scaled_font, - scaled_glyph, - face, - load_flags, - !hint_metrics, - vertical_layout); + iterator.p = NULL; + while (FT_Get_Color_Glyph_Layer(face, + _cairo_scaled_glyph_index (scaled_glyph), + &layer_glyph_index, + &layer_color_index, + &iterator)) + { + cairo_pattern_t *pattern; + if (layer_color_index == 0xFFFF) { + pattern = _cairo_pattern_create_foreground_marker (); + } else { + double r = 0, g = 0, b = 0, a = 1; + if (layer_color_index < num_palette_entries) { + FT_Color *color = &palette[layer_color_index]; + r = color->red / 255.0; + g = color->green/ 255.0; + b = color->blue / 255.0; + a = color->alpha / 255.0; + } + pattern = cairo_pattern_create_rgba (r, g, b, a); + } + cairo_set_source (cr, pattern); + cairo_pattern_destroy (pattern); + + if (FT_Load_Glyph (face, layer_glyph_index, load_flags) != 0) { + status = CAIRO_INT_STATUS_UNSUPPORTED; + goto cleanup; + } + + status = _cairo_ft_face_decompose_glyph_outline (face, &path_fixed); if (unlikely (status)) - goto FAIL; + return status; - glyph = face->glyph; - scaled_glyph_loaded = hint_metrics; + path = _cairo_path_create (path_fixed, cr); + _cairo_path_fixed_destroy (path_fixed); + cairo_append_path(cr, path); + cairo_path_destroy (path); + cairo_fill (cr); + } + + cleanup: + cairo_destroy (cr); - /* - * Compute font-space metrics + if (status) { + cairo_surface_destroy (recording_surface); + return status; + } + + _cairo_scaled_glyph_set_recording_surface (scaled_glyph, + &scaled_font->base, + recording_surface, + NULL); + return status; +#else + return CAIRO_INT_STATUS_UNSUPPORTED; +#endif +} + +static cairo_int_status_t +_cairo_ft_scaled_glyph_init_record_colr_v1_glyph (cairo_ft_scaled_font_t *scaled_font, + cairo_scaled_glyph_t *scaled_glyph, + FT_Face face, + const cairo_color_t *foreground_color, + cairo_text_extents_t *extents) +{ +#if HAVE_FT_COLR_V1 + cairo_status_t status = CAIRO_STATUS_SUCCESS; + cairo_surface_t *recording_surface; + cairo_t *cr; + FT_Color *palette; + unsigned int num_palette_entries; + cairo_bool_t foreground_source_used = FALSE; + + recording_surface = + cairo_recording_surface_create (CAIRO_CONTENT_COLOR_ALPHA, NULL); + + cairo_surface_set_device_scale (recording_surface, 1, -1); + + cr = cairo_create (recording_surface); + + cairo_set_font_size (cr, 1.0); + cairo_set_font_options (cr, &scaled_font->base.options); + + extents->x_bearing = DOUBLE_FROM_26_6(face->bbox.xMin); + extents->y_bearing = DOUBLE_FROM_26_6(face->bbox.yMin); + extents->width = DOUBLE_FROM_26_6(face->bbox.xMax) - extents->x_bearing; + extents->height = DOUBLE_FROM_26_6(face->bbox.yMax) - extents->y_bearing; + + _cairo_ft_scaled_glyph_set_palette (scaled_font, face, &num_palette_entries, &palette); + + if (!_cairo_matrix_is_scale_0 (&scaled_font->base.scale)) { + cairo_pattern_t *foreground_pattern = _cairo_pattern_create_solid (foreground_color); + status = _cairo_render_colr_v1_glyph (face, + _cairo_scaled_glyph_index (scaled_glyph), + palette, + num_palette_entries, + cr, + foreground_pattern, + &foreground_source_used); + cairo_pattern_destroy (foreground_pattern); + if (status == CAIRO_STATUS_SUCCESS) + status = cairo_status (cr); + } + + cairo_destroy (cr); + + if (status) { + cairo_surface_destroy (recording_surface); + scaled_glyph->color_glyph = FALSE; + scaled_glyph->color_glyph_set = TRUE; + return status; + } + + _cairo_scaled_glyph_set_recording_surface (scaled_glyph, + &scaled_font->base, + recording_surface, + foreground_source_used ? foreground_color : NULL); + + scaled_glyph->color_glyph = TRUE; + scaled_glyph->color_glyph_set = TRUE; + + /* get metrics */ + + /* Copied from cairo-user-font.c */ + cairo_matrix_t extent_scale; + double extent_x_scale; + double extent_y_scale; + double snap_x_scale; + double snap_y_scale; + double fixed_scale, x_scale, y_scale; + + extent_scale = scaled_font->base.scale_inverse; + snap_x_scale = 1.0; + snap_y_scale = 1.0; + status = _cairo_matrix_compute_basis_scale_factors (&extent_scale, + &x_scale, &y_scale, + 1); + if (status == CAIRO_STATUS_SUCCESS) { + if (x_scale == 0) + x_scale = 1; + if (y_scale == 0) + y_scale = 1; + + snap_x_scale = x_scale; + snap_y_scale = y_scale; + + /* since glyphs are pretty much 1.0x1.0, we can reduce error by + * scaling to a larger square. say, 1024.x1024. */ + fixed_scale = 1024; + x_scale /= fixed_scale; + y_scale /= fixed_scale; + + cairo_matrix_scale (&extent_scale, 1.0 / x_scale, 1.0 / y_scale); + + extent_x_scale = x_scale; + extent_y_scale = y_scale; + } + + { + /* compute width / height */ + cairo_box_t bbox; + double x1, y1, x2, y2; + double x_scale, y_scale; + + /* Compute extents.x/y/width/height from recording_surface, + * in font space. */ - metrics = &glyph->metrics; + status = _cairo_recording_surface_get_bbox ((cairo_recording_surface_t *) recording_surface, + &bbox, + &extent_scale); + if (unlikely (status)) + return status; - if (unscaled->x_scale == 0) - x_factor = 0; - else - x_factor = 1 / unscaled->x_scale; + _cairo_box_to_doubles (&bbox, &x1, &y1, &x2, &y2); - if (unscaled->y_scale == 0) - y_factor = 0; - else - y_factor = 1 / unscaled->y_scale; + x_scale = extent_x_scale; + y_scale = extent_y_scale; + extents->x_bearing = x1 * x_scale; + extents->y_bearing = y1 * y_scale; + extents->width = (x2 - x1) * x_scale; + extents->height = (y2 - y1) * y_scale; + } + + if (scaled_font->base.options.hint_metrics != CAIRO_HINT_METRICS_OFF) { + extents->x_advance = _cairo_lround (extents->x_advance / snap_x_scale) * snap_x_scale; + extents->y_advance = _cairo_lround (extents->y_advance / snap_y_scale) * snap_y_scale; + } + + return status; +#else + return CAIRO_INT_STATUS_UNSUPPORTED; +#endif +} + +static cairo_int_status_t +_cairo_ft_scaled_glyph_init_record_svg_glyph (cairo_ft_scaled_font_t *scaled_font, + cairo_scaled_glyph_t *scaled_glyph, + FT_Face face, + const cairo_color_t *foreground_color, + cairo_text_extents_t *extents) +{ +#if HAVE_FT_SVG_DOCUMENT + cairo_status_t status = CAIRO_STATUS_SUCCESS; + cairo_surface_t *recording_surface; + cairo_t *cr; + FT_SVG_Document svg_doc = face->glyph->other; + char *svg_document; + FT_Color *palette; + unsigned int num_palette_entries; + cairo_bool_t foreground_source_used = FALSE; + + /* Create NULL terminated SVG document */ + svg_document = _cairo_strndup ((const char*)svg_doc->svg_document, svg_doc->svg_document_length); + + recording_surface = + cairo_recording_surface_create (CAIRO_CONTENT_COLOR_ALPHA, NULL); + + cr = cairo_create (recording_surface); + + if (!_cairo_matrix_is_scale_0 (&scaled_font->base.scale)) { + cairo_matrix_t scale; + scale = scaled_font->base.scale; + scale.x0 = scale.y0 = 0.; + cairo_set_matrix (cr, &scale); + } + + cairo_set_font_size (cr, 1.0); + cairo_set_font_options (cr, &scaled_font->base.options); + + extents->x_bearing = DOUBLE_FROM_26_6(face->bbox.xMin); + extents->y_bearing = DOUBLE_FROM_26_6(face->bbox.yMin); + extents->width = DOUBLE_FROM_26_6(face->bbox.xMax) - extents->x_bearing; + extents->height = DOUBLE_FROM_26_6(face->bbox.yMax) - extents->y_bearing; + + _cairo_ft_scaled_glyph_set_palette (scaled_font, face, &num_palette_entries, &palette); + + if (!_cairo_matrix_is_scale_0 (&scaled_font->base.scale)) { + cairo_pattern_t *foreground_pattern = _cairo_pattern_create_solid (foreground_color); + status = _cairo_render_svg_glyph (svg_document, + svg_doc->start_glyph_id, + svg_doc->end_glyph_id, + _cairo_scaled_glyph_index(scaled_glyph), + svg_doc->units_per_EM, + palette, + num_palette_entries, + cr, + foreground_pattern, + &foreground_source_used); + cairo_pattern_destroy (foreground_pattern); + if (status == CAIRO_STATUS_SUCCESS) + status = cairo_status (cr); + } + + cairo_destroy (cr); + free (svg_document); + + if (status) { + cairo_surface_destroy (recording_surface); + scaled_glyph->color_glyph = FALSE; + scaled_glyph->color_glyph_set = TRUE; + return status; + } + + _cairo_scaled_glyph_set_recording_surface (scaled_glyph, + &scaled_font->base, + recording_surface, + foreground_source_used ? foreground_color : NULL); + + scaled_glyph->color_glyph = TRUE; + scaled_glyph->color_glyph_set = TRUE; + + /* get metrics */ + + /* Copied from cairo-user-font.c */ + cairo_matrix_t extent_scale; + double extent_x_scale; + double extent_y_scale; + double snap_x_scale; + double snap_y_scale; + double fixed_scale, x_scale, y_scale; + + extent_scale = scaled_font->base.scale_inverse; + snap_x_scale = 1.0; + snap_y_scale = 1.0; + status = _cairo_matrix_compute_basis_scale_factors (&extent_scale, + &x_scale, &y_scale, + 1); + if (status == CAIRO_STATUS_SUCCESS) { + if (x_scale == 0) + x_scale = 1; + if (y_scale == 0) + y_scale = 1; + + snap_x_scale = x_scale; + snap_y_scale = y_scale; + + /* since glyphs are pretty much 1.0x1.0, we can reduce error by + * scaling to a larger square. say, 1024.x1024. */ + fixed_scale = 1024; + x_scale /= fixed_scale; + y_scale /= fixed_scale; + + cairo_matrix_scale (&extent_scale, 1.0 / x_scale, 1.0 / y_scale); + + extent_x_scale = x_scale; + extent_y_scale = y_scale; + } - /* - * 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 - * - * If we want hinted metrics but aren't asking for hinted glyphs from - * FreeType, then we need to do the metric hinting ourselves. + { + /* compute width / height */ + cairo_box_t bbox; + double x1, y1, x2, y2; + double x_scale, y_scale; + + /* Compute extents.x/y/width/height from recording_surface, + * in font space. */ + status = _cairo_recording_surface_get_bbox ((cairo_recording_surface_t *) recording_surface, + &bbox, + &extent_scale); + if (unlikely (status)) + return status; - if (hint_metrics && (load_flags & FT_LOAD_NO_HINTING)) - { - FT_Pos x1, x2; - FT_Pos y1, y2; - FT_Pos advance; + _cairo_box_to_doubles (&bbox, &x1, &y1, &x2, &y2); + + x_scale = extent_x_scale; + y_scale = extent_y_scale; + extents->x_bearing = x1 * x_scale; + extents->y_bearing = y1 * y_scale; + extents->width = (x2 - x1) * x_scale; + extents->height = (y2 - y1) * y_scale; + } + + if (scaled_font->base.options.hint_metrics != CAIRO_HINT_METRICS_OFF) { + extents->x_advance = _cairo_lround (extents->x_advance / snap_x_scale) * snap_x_scale; + extents->y_advance = _cairo_lround (extents->y_advance / snap_y_scale) * snap_y_scale; + } + + return status; +#else + return CAIRO_INT_STATUS_UNSUPPORTED; +#endif +} - if (!vertical_layout) { - x1 = (metrics->horiBearingX) & -64; - x2 = (metrics->horiBearingX + metrics->width + 63) & -64; - y1 = (-metrics->horiBearingY) & -64; - y2 = (-metrics->horiBearingY + metrics->height + 63) & -64; +static cairo_int_status_t +_cairo_ft_scaled_glyph_init_surface_for_recording_surface (cairo_ft_scaled_font_t *scaled_font, + cairo_scaled_glyph_t *scaled_glyph, + const cairo_color_t *foreground_color) +{ + cairo_surface_t *surface; + int width, height; + cairo_int_status_t status = CAIRO_STATUS_SUCCESS; + cairo_bool_t foreground_used; - advance = ((metrics->horiAdvance + 32) & -64); + width = _cairo_fixed_integer_ceil (scaled_glyph->bbox.p2.x) - + _cairo_fixed_integer_floor (scaled_glyph->bbox.p1.x); + height = _cairo_fixed_integer_ceil (scaled_glyph->bbox.p2.y) - + _cairo_fixed_integer_floor (scaled_glyph->bbox.p1.y); - fs_metrics.x_bearing = DOUBLE_FROM_26_6 (x1) * x_factor; - fs_metrics.y_bearing = DOUBLE_FROM_26_6 (y1) * y_factor; + surface = cairo_image_surface_create (CAIRO_FORMAT_ARGB32, width, height); - fs_metrics.width = DOUBLE_FROM_26_6 (x2 - x1) * x_factor; - fs_metrics.height = DOUBLE_FROM_26_6 (y2 - y1) * y_factor; + cairo_surface_set_device_offset (surface, + - _cairo_fixed_integer_floor (scaled_glyph->bbox.p1.x), + - _cairo_fixed_integer_floor (scaled_glyph->bbox.p1.y)); - fs_metrics.x_advance = DOUBLE_FROM_26_6 (advance) * x_factor; - fs_metrics.y_advance = 0; - } else { - x1 = (metrics->vertBearingX) & -64; - x2 = (metrics->vertBearingX + metrics->width + 63) & -64; - y1 = (metrics->vertBearingY) & -64; - y2 = (metrics->vertBearingY + metrics->height + 63) & -64; + status = _cairo_recording_surface_replay_with_foreground_color (scaled_glyph->recording_surface, + surface, + foreground_color, + &foreground_used); + if (unlikely (status)) { + cairo_surface_destroy(surface); + return status; + } - advance = ((metrics->vertAdvance + 32) & -64); + _cairo_scaled_glyph_set_color_surface (scaled_glyph, + &scaled_font->base, + (cairo_image_surface_t *)surface, + foreground_used ? foreground_color : NULL); + surface = NULL; - fs_metrics.x_bearing = DOUBLE_FROM_26_6 (x1) * x_factor; - fs_metrics.y_bearing = DOUBLE_FROM_26_6 (y1) * y_factor; + if (surface) + cairo_surface_destroy (surface); - fs_metrics.width = DOUBLE_FROM_26_6 (x2 - x1) * x_factor; - fs_metrics.height = DOUBLE_FROM_26_6 (y2 - y1) * y_factor; + return status; +} - fs_metrics.x_advance = 0; - fs_metrics.y_advance = DOUBLE_FROM_26_6 (advance) * y_factor; - } - } else { - fs_metrics.width = DOUBLE_FROM_26_6 (metrics->width) * x_factor; - fs_metrics.height = DOUBLE_FROM_26_6 (metrics->height) * y_factor; +static void +_cairo_ft_scaled_glyph_get_metrics (cairo_ft_scaled_font_t *scaled_font, + FT_Face face, + cairo_bool_t vertical_layout, + int load_flags, + cairo_text_extents_t *fs_metrics) +{ + FT_Glyph_Metrics *metrics; + double x_factor, y_factor; + cairo_ft_unscaled_font_t *unscaled = scaled_font->unscaled; + cairo_bool_t hint_metrics = scaled_font->base.options.hint_metrics != CAIRO_HINT_METRICS_OFF; + FT_GlyphSlot glyph = face->glyph; - if (!vertical_layout) { - fs_metrics.x_bearing = DOUBLE_FROM_26_6 (metrics->horiBearingX) * x_factor; - fs_metrics.y_bearing = DOUBLE_FROM_26_6 (-metrics->horiBearingY) * y_factor; + /* + * Compute font-space metrics + */ + metrics = &glyph->metrics; - if (hint_metrics || glyph->format != FT_GLYPH_FORMAT_OUTLINE) - fs_metrics.x_advance = DOUBLE_FROM_26_6 (metrics->horiAdvance) * x_factor; - else - fs_metrics.x_advance = DOUBLE_FROM_16_16 (glyph->linearHoriAdvance) * x_factor; - fs_metrics.y_advance = 0 * y_factor; - } else { - fs_metrics.x_bearing = DOUBLE_FROM_26_6 (metrics->vertBearingX) * x_factor; - fs_metrics.y_bearing = DOUBLE_FROM_26_6 (metrics->vertBearingY) * y_factor; + if (unscaled->x_scale == 0) + x_factor = 0; + else + x_factor = 1 / unscaled->x_scale; - fs_metrics.x_advance = 0 * x_factor; - if (hint_metrics || glyph->format != FT_GLYPH_FORMAT_OUTLINE) - fs_metrics.y_advance = DOUBLE_FROM_26_6 (metrics->vertAdvance) * y_factor; - else - fs_metrics.y_advance = DOUBLE_FROM_16_16 (glyph->linearVertAdvance) * y_factor; - } - } + if (unscaled->y_scale == 0) + y_factor = 0; + else + y_factor = 1 / unscaled->y_scale; - _cairo_scaled_glyph_set_metrics (scaled_glyph, - &scaled_font->base, - &fs_metrics); + /* + * 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 + * + * If we want hinted metrics but aren't asking for hinted glyphs from + * FreeType, then we need to do the metric hinting ourselves. + */ + + if (hint_metrics && (load_flags & FT_LOAD_NO_HINTING)) + { + FT_Pos x1, x2; + FT_Pos y1, y2; + FT_Pos advance; + + if (!vertical_layout) { + x1 = (metrics->horiBearingX) & -64; + x2 = (metrics->horiBearingX + metrics->width + 63) & -64; + y1 = (-metrics->horiBearingY) & -64; + y2 = (-metrics->horiBearingY + metrics->height + 63) & -64; + + advance = ((metrics->horiAdvance + 32) & -64); + + fs_metrics->x_bearing = DOUBLE_FROM_26_6 (x1) * x_factor; + fs_metrics->y_bearing = DOUBLE_FROM_26_6 (y1) * y_factor; + + fs_metrics->width = DOUBLE_FROM_26_6 (x2 - x1) * x_factor; + fs_metrics->height = DOUBLE_FROM_26_6 (y2 - y1) * y_factor; + + fs_metrics->x_advance = DOUBLE_FROM_26_6 (advance) * x_factor; + fs_metrics->y_advance = 0; + } else { + x1 = (metrics->vertBearingX) & -64; + x2 = (metrics->vertBearingX + metrics->width + 63) & -64; + y1 = (metrics->vertBearingY) & -64; + y2 = (metrics->vertBearingY + metrics->height + 63) & -64; + + advance = ((metrics->vertAdvance + 32) & -64); + + fs_metrics->x_bearing = DOUBLE_FROM_26_6 (x1) * x_factor; + fs_metrics->y_bearing = DOUBLE_FROM_26_6 (y1) * y_factor; + + fs_metrics->width = DOUBLE_FROM_26_6 (x2 - x1) * x_factor; + fs_metrics->height = DOUBLE_FROM_26_6 (y2 - y1) * y_factor; + + fs_metrics->x_advance = 0; + fs_metrics->y_advance = DOUBLE_FROM_26_6 (advance) * y_factor; + } + } else { + fs_metrics->width = DOUBLE_FROM_26_6 (metrics->width) * x_factor; + fs_metrics->height = DOUBLE_FROM_26_6 (metrics->height) * y_factor; + + if (!vertical_layout) { + fs_metrics->x_bearing = DOUBLE_FROM_26_6 (metrics->horiBearingX) * x_factor; + fs_metrics->y_bearing = DOUBLE_FROM_26_6 (-metrics->horiBearingY) * y_factor; + + if (hint_metrics || glyph->format != FT_GLYPH_FORMAT_OUTLINE) + fs_metrics->x_advance = DOUBLE_FROM_26_6 (metrics->horiAdvance) * x_factor; + else + fs_metrics->x_advance = DOUBLE_FROM_16_16 (glyph->linearHoriAdvance) * x_factor; + fs_metrics->y_advance = 0 * y_factor; + } else { + fs_metrics->x_bearing = DOUBLE_FROM_26_6 (metrics->vertBearingX) * x_factor; + fs_metrics->y_bearing = DOUBLE_FROM_26_6 (metrics->vertBearingY) * y_factor; + + fs_metrics->x_advance = 0 * x_factor; + if (hint_metrics || glyph->format != FT_GLYPH_FORMAT_OUTLINE) + fs_metrics->y_advance = DOUBLE_FROM_26_6 (metrics->vertAdvance) * y_factor; + else + fs_metrics->y_advance = DOUBLE_FROM_16_16 (glyph->linearVertAdvance) * y_factor; + } + } +} + +static cairo_bool_t +_cairo_ft_scaled_glyph_is_colr_v0 (cairo_ft_scaled_font_t *scaled_font, + cairo_scaled_glyph_t *scaled_glyph, + FT_Face face) +{ +#ifdef HAVE_FT_PALETTE_SELECT + FT_LayerIterator iterator; + FT_UInt layer_glyph_index; + FT_UInt layer_color_index; + + iterator.p = NULL; + if (FT_Get_Color_Glyph_Layer(face, + _cairo_scaled_glyph_index (scaled_glyph), + &layer_glyph_index, + &layer_color_index, + &iterator) == 1) + { + return TRUE; + } +#endif + return FALSE; +} + +static cairo_bool_t +_cairo_ft_scaled_glyph_is_colr_v1 (cairo_ft_scaled_font_t *scaled_font, + cairo_scaled_glyph_t *scaled_glyph, + FT_Face face) +{ +#if HAVE_FT_COLR_V1 + FT_OpaquePaint paint = { NULL, 0 }; + + if (FT_Get_Color_Glyph_Paint (face, + _cairo_scaled_glyph_index (scaled_glyph), + FT_COLOR_INCLUDE_ROOT_TRANSFORM, + &paint) == 1) + { + return TRUE; } +#endif + return FALSE; +} -LOAD: - if (info & (CAIRO_SCALED_GLYPH_INFO_SURFACE | CAIRO_SCALED_GLYPH_INFO_COLOR_SURFACE)) { - cairo_image_surface_t *surface; +static const int ft_glyph_private_key; - if (!scaled_glyph_loaded) { +static cairo_int_status_t +_cairo_ft_scaled_glyph_init_metrics (cairo_ft_scaled_font_t *scaled_font, + cairo_scaled_glyph_t *scaled_glyph, + FT_Face face, + cairo_bool_t vertical_layout, + int load_flags, + const cairo_color_t *foreground_color) +{ + cairo_int_status_t status = CAIRO_INT_STATUS_SUCCESS; + cairo_text_extents_t fs_metrics; + cairo_ft_glyph_private_t *glyph_priv; + + cairo_bool_t hint_metrics = scaled_font->base.options.hint_metrics != CAIRO_HINT_METRICS_OFF; + + /* _cairo_ft_scaled_glyph_init_metrics() is called once the first + * time a cairo_scaled_glyph_t is created. We first allocate the + * cairo_ft_glyph_private_t struct and determine the glyph type. + */ + + glyph_priv = _cairo_malloc (sizeof (*glyph_priv)); + if (unlikely (glyph_priv == NULL)) + return _cairo_error (CAIRO_STATUS_NO_MEMORY); + + _cairo_scaled_glyph_attach_private (scaled_glyph, &glyph_priv->base, + &ft_glyph_private_key, + _cairo_ft_glyph_fini); + + /* We need to load color to determine if this is a color format. */ + int color_flag = 0; + +#ifdef FT_LOAD_COLOR + if (scaled_font->unscaled->have_color && scaled_font->base.options.color_mode != CAIRO_COLOR_MODE_NO_COLOR) + color_flag = FT_LOAD_COLOR; +#endif + /* Ensure use_em_size = FALSE as the format (bitmap or outline) + * may change with the size. */ + status = _cairo_ft_scaled_glyph_load_glyph (scaled_font, + scaled_glyph, + face, + load_flags | color_flag, + FALSE, + vertical_layout); + if (unlikely (status)) + return status; + + cairo_bool_t is_svg_format = FALSE; +#if HAVE_FT_SVG_DOCUMENT + if (face->glyph->format == FT_GLYPH_FORMAT_SVG) + is_svg_format = TRUE; +#endif + + if (is_svg_format) { + glyph_priv->format = CAIRO_FT_GLYPH_TYPE_SVG; + } else if (face->glyph->format == FT_GLYPH_FORMAT_OUTLINE) { + glyph_priv->format = CAIRO_FT_GLYPH_TYPE_OUTLINE; + if (color_flag) { + if (_cairo_ft_scaled_glyph_is_colr_v1 (scaled_font, scaled_glyph, face)) + glyph_priv->format = CAIRO_FT_GLYPH_TYPE_COLR_V1; + else if (_cairo_ft_scaled_glyph_is_colr_v0 (scaled_font, scaled_glyph, face)) + glyph_priv->format = CAIRO_FT_GLYPH_TYPE_COLR_V0; + } + } else { + /* For anything else we let FreeType render a bitmap. */ + glyph_priv->format = CAIRO_FT_GLYPH_TYPE_BITMAP; + } + + /* If hinting is off, load the glyph with font size set the the em size. */ + if (!hint_metrics) { + status = _cairo_ft_scaled_glyph_load_glyph (scaled_font, + scaled_glyph, + face, + load_flags | color_flag, + TRUE, + vertical_layout); + if (unlikely (status)) + return status; + } + + _cairo_ft_scaled_glyph_get_metrics (scaled_font, + face, + vertical_layout, + load_flags, + &fs_metrics); + + + /* SVG and COLRv1 glyphs require the bounding box to be obtained + * from the ink extents of the rendering. We need to render glyph + * to a recording surface to obtain these extents. But we also + * need the advance from _cairo_ft_scaled_glyph_get_metrics() + * before calling this function. + */ + + if (glyph_priv->format == CAIRO_FT_GLYPH_TYPE_SVG) { + status = (cairo_int_status_t)_cairo_ft_scaled_glyph_init_record_svg_glyph (scaled_font, + scaled_glyph, + face, + foreground_color, + &fs_metrics); + if (unlikely (status)) + return status; + } + + if (glyph_priv->format == CAIRO_FT_GLYPH_TYPE_COLR_V1) { + /* Restore font size if previously loaded at em_size. */ + if (!hint_metrics) { status = _cairo_ft_scaled_glyph_load_glyph (scaled_font, scaled_glyph, face, - load_flags, + load_flags | color_flag, FALSE, vertical_layout); if (unlikely (status)) - goto FAIL; - - glyph = face->glyph; - scaled_glyph_loaded = TRUE; + return status; } - if (glyph->format == FT_GLYPH_FORMAT_OUTLINE) { - status = _render_glyph_outline (face, &scaled_font->ft_options.base, - &surface); - } else { - status = _render_glyph_bitmap (face, &scaled_font->ft_options.base, - &surface); - if (likely (status == CAIRO_STATUS_SUCCESS) && - unscaled->have_shape) - { - status = _transform_glyph_bitmap (&unscaled->current_shape, - &surface); - if (unlikely (status)) - cairo_surface_destroy (&surface->base); - } - } + status = (cairo_int_status_t)_cairo_ft_scaled_glyph_init_record_colr_v1_glyph (scaled_font, + scaled_glyph, + face, + foreground_color, + &fs_metrics); if (unlikely (status)) - goto FAIL; - - if (pixman_image_get_format (surface->pixman_image) == PIXMAN_a8r8g8b8 && - !pixman_image_get_component_alpha (surface->pixman_image)) { - _cairo_scaled_glyph_set_color_surface (scaled_glyph, - &scaled_font->base, - surface); - } else { - _cairo_scaled_glyph_set_surface (scaled_glyph, - &scaled_font->base, - surface); - } + return status; } - if (((info & (CAIRO_SCALED_GLYPH_INFO_SURFACE | CAIRO_SCALED_GLYPH_INFO_COLOR_SURFACE)) != 0) && - ((scaled_glyph->has_info & CAIRO_SCALED_GLYPH_INFO_SURFACE) == 0)) { - /* - * A kludge -- load again, without color. - * No need to load the metrics again, though - */ - scaled_glyph_loaded = FALSE; - info &= ~CAIRO_SCALED_GLYPH_INFO_METRICS; + _cairo_scaled_glyph_set_metrics (scaled_glyph, + &scaled_font->base, + &fs_metrics); + + return status; +} + +static cairo_int_status_t +_cairo_ft_scaled_glyph_init (void *abstract_font, + cairo_scaled_glyph_t *scaled_glyph, + cairo_scaled_glyph_info_t info, + const cairo_color_t *foreground_color) +{ + cairo_ft_scaled_font_t *scaled_font = abstract_font; + cairo_ft_unscaled_font_t *unscaled = scaled_font->unscaled; + FT_Face face; + int load_flags = scaled_font->ft_options.load_flags; + cairo_bool_t vertical_layout = FALSE; + cairo_status_t status = CAIRO_STATUS_SUCCESS; + cairo_ft_glyph_private_t *glyph_priv; + int color_flag = 0; + #ifdef FT_LOAD_COLOR - load_flags &= ~FT_LOAD_COLOR; + color_flag = FT_LOAD_COLOR; #endif - goto LOAD; + + face = _cairo_ft_unscaled_font_lock_face (unscaled); + if (!face) + return _cairo_error (CAIRO_STATUS_NO_MEMORY); + + /* Ignore global advance unconditionally */ + load_flags |= FT_LOAD_IGNORE_GLOBAL_ADVANCE_WIDTH; + + if ((info & CAIRO_SCALED_GLYPH_INFO_PATH) != 0 && + (info & (CAIRO_SCALED_GLYPH_INFO_SURFACE | + CAIRO_SCALED_GLYPH_INFO_COLOR_SURFACE)) == 0) { + load_flags |= FT_LOAD_NO_BITMAP; } - if (info & CAIRO_SCALED_GLYPH_INFO_PATH) { - cairo_path_fixed_t *path = NULL; /* hide compiler warning */ + /* + * Don't pass FT_LOAD_VERTICAL_LAYOUT to FT_Load_Glyph here as + * suggested by freetype people. + */ + if (load_flags & FT_LOAD_VERTICAL_LAYOUT) { + load_flags &= ~FT_LOAD_VERTICAL_LAYOUT; + vertical_layout = TRUE; + } - /* - * A kludge -- the above code will trash the outline, - * so reload it. This will probably never occur though - */ - if ((info & (CAIRO_SCALED_GLYPH_INFO_SURFACE | CAIRO_SCALED_GLYPH_INFO_COLOR_SURFACE)) != 0) { - scaled_glyph_loaded = FALSE; - load_flags |= FT_LOAD_NO_BITMAP; - } + /* Metrics will always be requested when a scaled glyph is created */ + if (info & CAIRO_SCALED_GLYPH_INFO_METRICS) { + status = _cairo_ft_scaled_glyph_init_metrics (scaled_font, + scaled_glyph, + face, + vertical_layout, + load_flags, + foreground_color); + if (unlikely (status)) + goto FAIL; + } - if (!scaled_glyph_loaded) { + glyph_priv = (cairo_ft_glyph_private_t *) _cairo_scaled_glyph_find_private (scaled_glyph, + &ft_glyph_private_key); + assert (glyph_priv != NULL); + + if (info & CAIRO_SCALED_GLYPH_INFO_RECORDING_SURFACE) { + status = CAIRO_INT_STATUS_UNSUPPORTED; + if (glyph_priv->format == CAIRO_FT_GLYPH_TYPE_SVG || + glyph_priv->format == CAIRO_FT_GLYPH_TYPE_COLR_V0 || + glyph_priv->format == CAIRO_FT_GLYPH_TYPE_COLR_V1) + { status = _cairo_ft_scaled_glyph_load_glyph (scaled_font, scaled_glyph, face, - load_flags, + load_flags | color_flag, FALSE, vertical_layout); if (unlikely (status)) goto FAIL; - glyph = face->glyph; + if (glyph_priv->format == CAIRO_FT_GLYPH_TYPE_SVG) { + status = _cairo_ft_scaled_glyph_init_record_svg_glyph (scaled_font, + scaled_glyph, + face, + foreground_color, + &scaled_glyph->fs_metrics); + } else if (glyph_priv->format == CAIRO_FT_GLYPH_TYPE_COLR_V1) { + status = _cairo_ft_scaled_glyph_init_record_colr_v1_glyph (scaled_font, + scaled_glyph, + face, + foreground_color, + &scaled_glyph->fs_metrics); + } else if (glyph_priv->format == CAIRO_FT_GLYPH_TYPE_COLR_V0) { + status = _cairo_ft_scaled_glyph_init_record_colr_v0_glyph (scaled_font, + scaled_glyph, + face, + vertical_layout, + load_flags); + } + } + if (status) + goto FAIL; + } + + if ((info & CAIRO_SCALED_GLYPH_INFO_COLOR_SURFACE) && scaled_font->base.options.color_mode != CAIRO_COLOR_MODE_NO_COLOR) { + if (glyph_priv->format == CAIRO_FT_GLYPH_TYPE_SVG || + glyph_priv->format == CAIRO_FT_GLYPH_TYPE_COLR_V1) + { + status = _cairo_ft_scaled_glyph_init_surface_for_recording_surface (scaled_font, + scaled_glyph, + foreground_color); + } else { + status = _cairo_ft_scaled_glyph_init_surface (scaled_font, + scaled_glyph, + glyph_priv, + CAIRO_SCALED_GLYPH_INFO_COLOR_SURFACE, + face, + foreground_color, + vertical_layout, + load_flags); } + if (unlikely (status)) + goto FAIL; + } - if (glyph->format == FT_GLYPH_FORMAT_OUTLINE) - status = _decompose_glyph_outline (face, &scaled_font->ft_options.base, - &path); + if (info & CAIRO_SCALED_GLYPH_INFO_SURFACE) { + status = _cairo_ft_scaled_glyph_init_surface (scaled_font, + scaled_glyph, + glyph_priv, + CAIRO_SCALED_GLYPH_INFO_SURFACE, + face, + NULL, /* foreground color */ + vertical_layout, + load_flags); + if (unlikely (status)) + goto FAIL; + } + + if (info & CAIRO_SCALED_GLYPH_INFO_PATH) { + cairo_path_fixed_t *path = NULL; /* hide compiler warning */ + + /* Load non-color glyph */ + status = _cairo_ft_scaled_glyph_load_glyph (scaled_font, + scaled_glyph, + face, + load_flags, + FALSE, + vertical_layout); + if (unlikely (status)) + goto FAIL; + + if (face->glyph->format == FT_GLYPH_FORMAT_OUTLINE) + status = _cairo_ft_face_decompose_glyph_outline (face, &path); else status = CAIRO_INT_STATUS_UNSUPPORTED; @@ -2948,7 +3800,7 @@ _cairo_ft_is_synthetic (void *abstract_font, error = getVar ? (*getVar) (face, &mm_var) : -1; if (error) { - status = _cairo_error (_ft_to_cairo_error (error)); + status = _cairo_error (_cairo_ft_to_cairo_error (error)); goto cleanup; } @@ -3307,8 +4159,6 @@ _cairo_ft_font_face_get_implementation (void *abstract_face, const cairo_matrix_t *ctm, const cairo_font_options_t *options) { - cairo_ft_font_face_t *font_face = abstract_face; - /* The handling of font options is different depending on how the * font face was created. When the user creates a font face with * cairo_ft_font_face_create_for_ft_face(), then the load flags @@ -3320,6 +4170,8 @@ _cairo_ft_font_face_get_implementation (void *abstract_face, */ #if CAIRO_HAS_FC_FONT + cairo_ft_font_face_t *font_face = abstract_face; + /* If we have an unresolved pattern, resolve it and create * unscaled font. Otherwise, use the ones stored in font_face. */ @@ -3566,7 +4418,6 @@ _cairo_ft_font_options_substitute (const cairo_font_options_t *options, case CAIRO_LCD_FILTER_NONE: lcd_filter = FT_LCD_FILTER_NONE; break; - case CAIRO_LCD_FILTER_DEFAULT: case CAIRO_LCD_FILTER_INTRA_PIXEL: lcd_filter = FT_LCD_FILTER_LEGACY; break; @@ -3574,6 +4425,7 @@ _cairo_ft_font_options_substitute (const cairo_font_options_t *options, lcd_filter = FT_LCD_FILTER_LIGHT; break; default: + case CAIRO_LCD_FILTER_DEFAULT: case CAIRO_LCD_FILTER_FIR5: lcd_filter = FT_LCD_FILTER_DEFAULT; break; diff --git a/gfx/cairo/cairo/src/cairo-ft-private.h b/gfx/cairo/cairo/src/cairo-ft-private.h index 0dc8114726..836f7e523e 100644 --- a/gfx/cairo/cairo/src/cairo-ft-private.h +++ b/gfx/cairo/cairo/src/cairo-ft-private.h @@ -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 © 2005 Red Hat, Inc @@ -55,6 +56,41 @@ _cairo_scaled_font_is_ft (cairo_scaled_font_t *scaled_font); cairo_private unsigned int _cairo_ft_scaled_font_get_load_flags (cairo_scaled_font_t *scaled_font); +cairo_private cairo_status_t +_cairo_ft_to_cairo_error (FT_Error error); + +cairo_private cairo_status_t +_cairo_ft_face_decompose_glyph_outline (FT_Face face, + cairo_path_fixed_t **pathp); + +#if HAVE_FT_SVG_DOCUMENT + +typedef struct FT_Color_ FT_Color; + +cairo_private cairo_status_t +_cairo_render_svg_glyph (const char *svg_document, + unsigned long first_glyph, + unsigned long last_glyph, + unsigned long glyph, + double units_per_em, + FT_Color *palette, + int num_palette_entries, + cairo_t *cr, + cairo_pattern_t *foreground_source, + cairo_bool_t *foreground_source_used); +#endif + +#if HAVE_FT_COLR_V1 +cairo_private cairo_status_t +_cairo_render_colr_v1_glyph (FT_Face face, + unsigned long glyph, + FT_Color *palette, + int num_palette_entries, + cairo_t *cr, + cairo_pattern_t *foreground_source, + cairo_bool_t *foreground_source_used); +#endif + CAIRO_END_DECLS #endif /* CAIRO_HAS_FT_FONT */ diff --git a/gfx/cairo/cairo/src/cairo-ft.h b/gfx/cairo/cairo/src/cairo-ft.h index f5a832b105..09959b7c2e 100644 --- a/gfx/cairo/cairo/src/cairo-ft.h +++ b/gfx/cairo/cairo/src/cairo-ft.h @@ -41,7 +41,7 @@ #if CAIRO_HAS_FT_FONT -/* Fontconfig/Freetype platform-specific font interface */ +/* Fontconfig/FreeType platform-specific font interface */ #include <ft2build.h> #include FT_FREETYPE_H diff --git a/gfx/cairo/cairo/src/cairo-gl-composite.c b/gfx/cairo/cairo/src/cairo-gl-composite.c deleted file mode 100644 index 5477ef0d8a..0000000000 --- a/gfx/cairo/cairo/src/cairo-gl-composite.c +++ /dev/null @@ -1,1364 +0,0 @@ -/* cairo - a vector graphics library with display and print output - * - * Copyright © 2009 Eric Anholt - * Copyright © 2009 Chris Wilson - * Copyright © 2005,2010 Red Hat, Inc - * Copyright © 2011 Linaro Limited - * Copyright © 2011 Samsung Electronics - * - * 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., 51 Franklin Street, Suite 500, Boston, MA 02110-1335, 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): - * Benjamin Otte <otte@gnome.org> - * Carl Worth <cworth@cworth.org> - * Chris Wilson <chris@chris-wilson.co.uk> - * Eric Anholt <eric@anholt.net> - * Alexandros Frantzis <alexandros.frantzis@linaro.org> - * Henry Song <hsong@sisa.samsung.com> - * Martin Robinson <mrobinson@igalia.com> - */ - -#include "cairoint.h" - -#include "cairo-gl-private.h" - -#include "cairo-composite-rectangles-private.h" -#include "cairo-clip-private.h" -#include "cairo-error-private.h" -#include "cairo-image-surface-private.h" - -/* FIXME: Copy of same routine in cairo-gl-msaa-compositor.c */ -static cairo_int_status_t -_draw_int_rect (cairo_gl_context_t *ctx, - cairo_gl_composite_t *setup, - cairo_rectangle_int_t *rect) -{ - cairo_box_t box; - cairo_point_t quad[4]; - - _cairo_box_from_rectangle (&box, rect); - quad[0].x = box.p1.x; - quad[0].y = box.p1.y; - quad[1].x = box.p1.x; - quad[1].y = box.p2.y; - quad[2].x = box.p2.x; - quad[2].y = box.p2.y; - quad[3].x = box.p2.x; - quad[3].y = box.p1.y; - - return _cairo_gl_composite_emit_quad_as_tristrip (ctx, setup, quad); -} - -static cairo_int_status_t -_blit_texture_to_renderbuffer (cairo_gl_surface_t *surface) -{ - cairo_gl_context_t *ctx = NULL; - cairo_gl_composite_t setup; - cairo_surface_pattern_t pattern; - cairo_rectangle_int_t extents; - cairo_int_status_t status; - - /* FIXME: This only permits blit when glesv3 is enabled. But note that - glesv2 with the ANGLE extension should also be able to support this feature, - so once the ANGLE support code is in place this check can be relaxed. */ - if (((cairo_gl_context_t *)surface->base.device)->gl_flavor != CAIRO_GL_FLAVOR_ES3) - return CAIRO_INT_STATUS_SUCCESS; - - if (! surface->content_in_texture) - return CAIRO_INT_STATUS_SUCCESS; - - memset (&setup, 0, sizeof (cairo_gl_composite_t)); - - status = _cairo_gl_composite_set_operator (&setup, - CAIRO_OPERATOR_SOURCE, - FALSE); - - if (status) - return status; - - setup.dst = surface; - setup.clip_region = surface->clip_region; - - _cairo_pattern_init_for_surface (&pattern, &surface->base); - status = _cairo_gl_composite_set_source (&setup, &pattern.base, - NULL, NULL, FALSE); - _cairo_pattern_fini (&pattern.base); - - if (unlikely (status)) - goto FAIL; - - _cairo_gl_composite_set_multisample (&setup); - - status = _cairo_gl_composite_begin (&setup, &ctx); - - if (unlikely (status)) - goto FAIL; - - extents.x = extents.y = 0; - extents.width = surface->width; - extents.height = surface->height; - - status = _draw_int_rect (ctx, &setup, &extents); - - if (status == CAIRO_INT_STATUS_SUCCESS) - surface->content_in_texture = FALSE; - -FAIL: - _cairo_gl_composite_fini (&setup); - - if (ctx) { - _cairo_gl_composite_flush (ctx); - status = _cairo_gl_context_release (ctx, status); - } - - return status; -} - -cairo_int_status_t -_cairo_gl_composite_set_source (cairo_gl_composite_t *setup, - const cairo_pattern_t *pattern, - const cairo_rectangle_int_t *sample, - const cairo_rectangle_int_t *extents, - cairo_bool_t use_texgen) -{ - _cairo_gl_operand_destroy (&setup->src); - return _cairo_gl_operand_init (&setup->src, pattern, setup->dst, - sample, extents, use_texgen); -} - -void -_cairo_gl_composite_set_source_operand (cairo_gl_composite_t *setup, - const cairo_gl_operand_t *source) -{ - cairo_int_status_t status; - - _cairo_gl_operand_destroy (&setup->src); - _cairo_gl_operand_copy (&setup->src, source); - - if (source->type == CAIRO_GL_OPERAND_TEXTURE) - status = _cairo_gl_surface_resolve_multisampling (source->texture.surface); -} - -void -_cairo_gl_composite_set_solid_source (cairo_gl_composite_t *setup, - const cairo_color_t *color) -{ - _cairo_gl_operand_destroy (&setup->src); - _cairo_gl_solid_operand_init (&setup->src, color); -} - -cairo_int_status_t -_cairo_gl_composite_set_mask (cairo_gl_composite_t *setup, - const cairo_pattern_t *pattern, - const cairo_rectangle_int_t *sample, - const cairo_rectangle_int_t *extents, - cairo_bool_t use_texgen) -{ - _cairo_gl_operand_destroy (&setup->mask); - if (pattern == NULL) - return CAIRO_STATUS_SUCCESS; - - return _cairo_gl_operand_init (&setup->mask, pattern, setup->dst, - sample, extents, use_texgen); -} - -void -_cairo_gl_composite_set_mask_operand (cairo_gl_composite_t *setup, - const cairo_gl_operand_t *mask) -{ - cairo_int_status_t status; - _cairo_gl_operand_destroy (&setup->mask); - if (mask) { - _cairo_gl_operand_copy (&setup->mask, mask); - if (mask->type == CAIRO_GL_OPERAND_TEXTURE) - status = _cairo_gl_surface_resolve_multisampling (mask->texture.surface); - } -} - -void -_cairo_gl_composite_set_spans (cairo_gl_composite_t *setup) -{ - setup->spans = TRUE; -} - -void -_cairo_gl_composite_set_multisample (cairo_gl_composite_t *setup) -{ - setup->multisample = TRUE; -} - -void -_cairo_gl_composite_set_clip_region (cairo_gl_composite_t *setup, - cairo_region_t *clip_region) -{ - setup->clip_region = clip_region; -} - -void -_cairo_gl_composite_set_clip (cairo_gl_composite_t *setup, - cairo_clip_t *clip) -{ - setup->clip = clip; -} - -static void -_cairo_gl_composite_bind_to_shader (cairo_gl_context_t *ctx, - cairo_gl_composite_t *setup) -{ - _cairo_gl_shader_bind_matrix4f(ctx, ctx->current_shader->mvp_location, - ctx->modelviewprojection_matrix); - _cairo_gl_operand_bind_to_shader (ctx, &setup->src, CAIRO_GL_TEX_SOURCE); - _cairo_gl_operand_bind_to_shader (ctx, &setup->mask, CAIRO_GL_TEX_MASK); -} - -static void -_cairo_gl_texture_set_filter (cairo_gl_context_t *ctx, - GLuint target, - cairo_filter_t filter) -{ - switch (filter) { - case CAIRO_FILTER_FAST: - case CAIRO_FILTER_NEAREST: - glTexParameteri (target, GL_TEXTURE_MIN_FILTER, GL_NEAREST); - glTexParameteri (target, GL_TEXTURE_MAG_FILTER, GL_NEAREST); - break; - case CAIRO_FILTER_GOOD: - case CAIRO_FILTER_BEST: - case CAIRO_FILTER_BILINEAR: - glTexParameteri (target, GL_TEXTURE_MIN_FILTER, GL_LINEAR); - glTexParameteri (target, GL_TEXTURE_MAG_FILTER, GL_LINEAR); - break; - default: - case CAIRO_FILTER_GAUSSIAN: - ASSERT_NOT_REACHED; - } -} - -static void -_cairo_gl_texture_set_extend (cairo_gl_context_t *ctx, - GLuint target, - cairo_extend_t extend) -{ - GLint wrap_mode; - assert (! _cairo_gl_device_requires_power_of_two_textures (&ctx->base) || - (extend != CAIRO_EXTEND_REPEAT && extend != CAIRO_EXTEND_REFLECT)); - - switch (extend) { - case CAIRO_EXTEND_NONE: - if (ctx->gl_flavor == CAIRO_GL_FLAVOR_ES3 || - ctx->gl_flavor == CAIRO_GL_FLAVOR_ES2) - wrap_mode = GL_CLAMP_TO_EDGE; - else - wrap_mode = GL_CLAMP_TO_BORDER; - break; - case CAIRO_EXTEND_PAD: - wrap_mode = GL_CLAMP_TO_EDGE; - break; - case CAIRO_EXTEND_REPEAT: - if (ctx->has_npot_repeat) - wrap_mode = GL_REPEAT; - else - wrap_mode = GL_CLAMP_TO_EDGE; - break; - case CAIRO_EXTEND_REFLECT: - if (ctx->has_npot_repeat) - wrap_mode = GL_MIRRORED_REPEAT; - else - wrap_mode = GL_CLAMP_TO_EDGE; - break; - default: - wrap_mode = 0; - } - - if (likely (wrap_mode)) { - glTexParameteri (target, GL_TEXTURE_WRAP_S, wrap_mode); - glTexParameteri (target, GL_TEXTURE_WRAP_T, wrap_mode); - } -} - - -static void -_cairo_gl_context_setup_operand (cairo_gl_context_t *ctx, - cairo_gl_tex_t tex_unit, - cairo_gl_operand_t *operand, - unsigned int vertex_offset, - cairo_bool_t vertex_size_changed) -{ - cairo_gl_dispatch_t *dispatch = &ctx->dispatch; - cairo_bool_t needs_setup; - - /* XXX: we need to do setup when switching from shaders - * to no shaders (or back) */ - needs_setup = vertex_size_changed; - needs_setup |= _cairo_gl_operand_needs_setup (&ctx->operands[tex_unit], - operand, - vertex_offset); - - if (needs_setup) { - _cairo_gl_composite_flush (ctx); - _cairo_gl_context_destroy_operand (ctx, tex_unit); - } - - memcpy (&ctx->operands[tex_unit], operand, sizeof (cairo_gl_operand_t)); - ctx->operands[tex_unit].vertex_offset = vertex_offset; - - if (! needs_setup) - return; - - switch (operand->type) { - default: - case CAIRO_GL_OPERAND_COUNT: - ASSERT_NOT_REACHED; - case CAIRO_GL_OPERAND_NONE: - break; - /* fall through */ - case CAIRO_GL_OPERAND_CONSTANT: - break; - case CAIRO_GL_OPERAND_TEXTURE: - glActiveTexture (GL_TEXTURE0 + tex_unit); - glBindTexture (ctx->tex_target, operand->texture.tex); - _cairo_gl_texture_set_extend (ctx, ctx->tex_target, - operand->texture.attributes.extend); - _cairo_gl_texture_set_filter (ctx, ctx->tex_target, - operand->texture.attributes.filter); - - if (! operand->texture.texgen) { - dispatch->VertexAttribPointer (CAIRO_GL_TEXCOORD0_ATTRIB_INDEX + tex_unit, 2, - GL_FLOAT, GL_FALSE, ctx->vertex_size, - ctx->vb + vertex_offset); - dispatch->EnableVertexAttribArray (CAIRO_GL_TEXCOORD0_ATTRIB_INDEX + tex_unit); - } - break; - case CAIRO_GL_OPERAND_LINEAR_GRADIENT: - case CAIRO_GL_OPERAND_RADIAL_GRADIENT_A0: - case CAIRO_GL_OPERAND_RADIAL_GRADIENT_NONE: - case CAIRO_GL_OPERAND_RADIAL_GRADIENT_EXT: - glActiveTexture (GL_TEXTURE0 + tex_unit); - glBindTexture (ctx->tex_target, operand->gradient.gradient->tex); - _cairo_gl_texture_set_extend (ctx, ctx->tex_target, operand->gradient.extend); - _cairo_gl_texture_set_filter (ctx, ctx->tex_target, CAIRO_FILTER_BILINEAR); - - if (! operand->gradient.texgen) { - dispatch->VertexAttribPointer (CAIRO_GL_TEXCOORD0_ATTRIB_INDEX + tex_unit, 2, - GL_FLOAT, GL_FALSE, ctx->vertex_size, - ctx->vb + vertex_offset); - dispatch->EnableVertexAttribArray (CAIRO_GL_TEXCOORD0_ATTRIB_INDEX + tex_unit); - } - break; - } -} - -static void -_cairo_gl_context_setup_spans (cairo_gl_context_t *ctx, - cairo_bool_t spans_enabled, - unsigned int vertex_size, - unsigned int vertex_offset) -{ - cairo_gl_dispatch_t *dispatch = &ctx->dispatch; - - if (! spans_enabled) { - dispatch->DisableVertexAttribArray (CAIRO_GL_COLOR_ATTRIB_INDEX); - ctx->spans = FALSE; - return; - } - - dispatch->VertexAttribPointer (CAIRO_GL_COLOR_ATTRIB_INDEX, 4, - GL_UNSIGNED_BYTE, GL_TRUE, vertex_size, - ctx->vb + vertex_offset); - dispatch->EnableVertexAttribArray (CAIRO_GL_COLOR_ATTRIB_INDEX); - ctx->spans = TRUE; -} - -void -_cairo_gl_context_destroy_operand (cairo_gl_context_t *ctx, - cairo_gl_tex_t tex_unit) -{ - cairo_gl_dispatch_t *dispatch = &ctx->dispatch; - - if (!_cairo_gl_context_is_flushed (ctx)) - _cairo_gl_composite_flush (ctx); - - switch (ctx->operands[tex_unit].type) { - default: - case CAIRO_GL_OPERAND_COUNT: - ASSERT_NOT_REACHED; - case CAIRO_GL_OPERAND_NONE: - break; - /* fall through */ - case CAIRO_GL_OPERAND_CONSTANT: - break; - case CAIRO_GL_OPERAND_TEXTURE: - dispatch->DisableVertexAttribArray (CAIRO_GL_TEXCOORD0_ATTRIB_INDEX + tex_unit); - break; - case CAIRO_GL_OPERAND_LINEAR_GRADIENT: - case CAIRO_GL_OPERAND_RADIAL_GRADIENT_A0: - case CAIRO_GL_OPERAND_RADIAL_GRADIENT_NONE: - case CAIRO_GL_OPERAND_RADIAL_GRADIENT_EXT: - dispatch->DisableVertexAttribArray (CAIRO_GL_TEXCOORD0_ATTRIB_INDEX + tex_unit); - break; - } - - memset (&ctx->operands[tex_unit], 0, sizeof (cairo_gl_operand_t)); -} - -static void -_cairo_gl_set_operator (cairo_gl_context_t *ctx, - cairo_operator_t op, - cairo_bool_t component_alpha) -{ - struct { - GLenum src; - GLenum dst; - } blend_factors[] = { - { GL_ZERO, GL_ZERO }, /* Clear */ - { GL_ONE, GL_ZERO }, /* Source */ - { GL_ONE, GL_ONE_MINUS_SRC_ALPHA }, /* Over */ - { GL_DST_ALPHA, GL_ZERO }, /* In */ - { GL_ONE_MINUS_DST_ALPHA, GL_ZERO }, /* Out */ - { GL_DST_ALPHA, GL_ONE_MINUS_SRC_ALPHA }, /* Atop */ - - { GL_ZERO, GL_ONE }, /* Dest */ - { GL_ONE_MINUS_DST_ALPHA, GL_ONE }, /* DestOver */ - { GL_ZERO, GL_SRC_ALPHA }, /* DestIn */ - { GL_ZERO, GL_ONE_MINUS_SRC_ALPHA }, /* DestOut */ - { GL_ONE_MINUS_DST_ALPHA, GL_SRC_ALPHA }, /* DestAtop */ - - { GL_ONE_MINUS_DST_ALPHA, GL_ONE_MINUS_SRC_ALPHA }, /* Xor */ - { GL_ONE, GL_ONE }, /* Add */ - }; - GLenum src_factor, dst_factor; - - assert (op < ARRAY_LENGTH (blend_factors)); - /* different dst and component_alpha changes cause flushes elsewhere */ - if (ctx->current_operator != op) - _cairo_gl_composite_flush (ctx); - ctx->current_operator = op; - - src_factor = blend_factors[op].src; - dst_factor = blend_factors[op].dst; - - /* Even when the user requests CAIRO_CONTENT_COLOR, we use GL_RGBA - * due to texture filtering of GL_CLAMP_TO_BORDER. So fix those - * bits in that case. - */ - if (ctx->current_target->base.content == CAIRO_CONTENT_COLOR) { - if (src_factor == GL_ONE_MINUS_DST_ALPHA) - src_factor = GL_ZERO; - if (src_factor == GL_DST_ALPHA) - src_factor = GL_ONE; - } - - if (component_alpha) { - if (dst_factor == GL_ONE_MINUS_SRC_ALPHA) - dst_factor = GL_ONE_MINUS_SRC_COLOR; - if (dst_factor == GL_SRC_ALPHA) - dst_factor = GL_SRC_COLOR; - } - - if (ctx->current_target->base.content == CAIRO_CONTENT_ALPHA) { - glBlendFuncSeparate (GL_ZERO, GL_ZERO, src_factor, dst_factor); - } else if (ctx->current_target->base.content == CAIRO_CONTENT_COLOR) { - glBlendFuncSeparate (src_factor, dst_factor, GL_ONE, GL_ONE); - } else { - glBlendFunc (src_factor, dst_factor); - } -} - -static cairo_status_t -_cairo_gl_composite_begin_component_alpha (cairo_gl_context_t *ctx, - cairo_gl_composite_t *setup) -{ - cairo_gl_shader_t *pre_shader = NULL; - cairo_status_t status; - - /* For CLEAR, cairo's rendering equation (quoting Owen's description in: - * https://lists.cairographics.org/archives/cairo/2005-August/004992.html) - * is: - * mask IN clip ? src OP dest : dest - * or more simply: - * mask IN CLIP ? 0 : dest - * - * where the ternary operator A ? B : C is (A * B) + ((1 - A) * C). - * - * The model we use in _cairo_gl_set_operator() is Render's: - * src IN mask IN clip OP dest - * which would boil down to: - * 0 (bounded by the extents of the drawing). - * - * However, we can do a Render operation using an opaque source - * and DEST_OUT to produce: - * 1 IN mask IN clip DEST_OUT dest - * which is - * mask IN clip ? 0 : dest - */ - if (setup->op == CAIRO_OPERATOR_CLEAR) { - _cairo_gl_solid_operand_init (&setup->src, CAIRO_COLOR_WHITE); - setup->op = CAIRO_OPERATOR_DEST_OUT; - } - - /* - * implements component-alpha %CAIRO_OPERATOR_OVER using two passes of - * the simpler operations %CAIRO_OPERATOR_DEST_OUT and %CAIRO_OPERATOR_ADD. - * - * From http://anholt.livejournal.com/32058.html: - * - * The trouble is that component-alpha rendering requires two different sources - * for blending: one for the source value to the blender, which is the - * per-channel multiplication of source and mask, and one for the source alpha - * for multiplying with the destination channels, which is the multiplication - * of the source channels by the mask alpha. So the equation for Over is: - * - * dst.A = src.A * mask.A + (1 - (src.A * mask.A)) * dst.A - * dst.R = src.R * mask.R + (1 - (src.A * mask.R)) * dst.R - * dst.G = src.G * mask.G + (1 - (src.A * mask.G)) * dst.G - * dst.B = src.B * mask.B + (1 - (src.A * mask.B)) * dst.B - * - * But we can do some simpler operations, right? How about PictOpOutReverse, - * which has a source factor of 0 and dest factor of (1 - source alpha). We - * can get the source alpha value (srca.X = src.A * mask.X) out of the texture - * blenders pretty easily. So we can do a component-alpha OutReverse, which - * gets us: - * - * dst.A = 0 + (1 - (src.A * mask.A)) * dst.A - * dst.R = 0 + (1 - (src.A * mask.R)) * dst.R - * dst.G = 0 + (1 - (src.A * mask.G)) * dst.G - * dst.B = 0 + (1 - (src.A * mask.B)) * dst.B - * - * OK. And if an op doesn't use the source alpha value for the destination - * factor, then we can do the channel multiplication in the texture blenders - * to get the source value, and ignore the source alpha that we wouldn't use. - * We've supported this in the Radeon driver for a long time. An example would - * be PictOpAdd, which does: - * - * dst.A = src.A * mask.A + dst.A - * dst.R = src.R * mask.R + dst.R - * dst.G = src.G * mask.G + dst.G - * dst.B = src.B * mask.B + dst.B - * - * Hey, this looks good! If we do a PictOpOutReverse and then a PictOpAdd right - * after it, we get: - * - * dst.A = src.A * mask.A + ((1 - (src.A * mask.A)) * dst.A) - * dst.R = src.R * mask.R + ((1 - (src.A * mask.R)) * dst.R) - * dst.G = src.G * mask.G + ((1 - (src.A * mask.G)) * dst.G) - * dst.B = src.B * mask.B + ((1 - (src.A * mask.B)) * dst.B) - * - * This two-pass trickery could be avoided using a new GL extension that - * lets two values come out of the shader and into the blend unit. - */ - if (setup->op == CAIRO_OPERATOR_OVER) { - setup->op = CAIRO_OPERATOR_ADD; - status = _cairo_gl_get_shader_by_type (ctx, - &setup->src, - &setup->mask, - setup->spans, - CAIRO_GL_SHADER_IN_CA_SOURCE_ALPHA, - &pre_shader); - if (unlikely (status)) - return status; - } - - if (ctx->pre_shader != pre_shader) - _cairo_gl_composite_flush (ctx); - ctx->pre_shader = pre_shader; - - return CAIRO_STATUS_SUCCESS; -} - -static void -_scissor_to_doubles (cairo_gl_surface_t *surface, - double x1, double y1, - double x2, double y2) -{ - double height; - - height = y2 - y1; - if (_cairo_gl_surface_is_texture (surface) == FALSE) - y1 = surface->height - (y1 + height); - glScissor (x1, y1, x2 - x1, height); - glEnable (GL_SCISSOR_TEST); -} - -void -_cairo_gl_scissor_to_rectangle (cairo_gl_surface_t *surface, - const cairo_rectangle_int_t *r) -{ - _scissor_to_doubles (surface, r->x, r->y, r->x+r->width, r->y+r->height); -} - -static void -_scissor_to_box (cairo_gl_surface_t *surface, - const cairo_box_t *box) -{ - double x1, y1, x2, y2; - _cairo_box_to_doubles (box, &x1, &y1, &x2, &y2); - _scissor_to_doubles (surface, x1, y1, x2, y2); -} - -static cairo_bool_t -_cairo_gl_composite_setup_vbo (cairo_gl_context_t *ctx, - unsigned int size_per_vertex) -{ - cairo_bool_t vertex_size_changed = ctx->vertex_size != size_per_vertex; - if (vertex_size_changed) { - ctx->vertex_size = size_per_vertex; - _cairo_gl_composite_flush (ctx); - } - - if (_cairo_gl_context_is_flushed (ctx)) { - ctx->dispatch.VertexAttribPointer (CAIRO_GL_VERTEX_ATTRIB_INDEX, 2, - GL_FLOAT, GL_FALSE, size_per_vertex, - ctx->vb); - ctx->dispatch.EnableVertexAttribArray (CAIRO_GL_VERTEX_ATTRIB_INDEX); - } - - return vertex_size_changed; -} - -static void -_disable_stencil_buffer (void) -{ - glDisable (GL_STENCIL_TEST); - glDepthMask (GL_FALSE); -} - -static cairo_int_status_t -_cairo_gl_composite_setup_painted_clipping (cairo_gl_composite_t *setup, - cairo_gl_context_t *ctx, - int vertex_size) -{ - cairo_int_status_t status = CAIRO_INT_STATUS_SUCCESS; - - cairo_gl_surface_t *dst = setup->dst; - cairo_clip_t *clip = setup->clip; - - if (clip->num_boxes == 1 && clip->path == NULL) { - _scissor_to_box (dst, &clip->boxes[0]); - goto disable_stencil_buffer_and_return; - } - - if (! _cairo_gl_ensure_stencil (ctx, setup->dst)) { - status = CAIRO_INT_STATUS_UNSUPPORTED; - goto disable_stencil_buffer_and_return; - } - - /* We only want to clear the part of the stencil buffer - * that we are about to use. It also does not hurt to - * scissor around the painted clip. */ - _cairo_gl_scissor_to_rectangle (dst, _cairo_clip_get_extents (clip)); - - /* The clip is not rectangular, so use the stencil buffer. */ - glDepthMask (GL_TRUE); - glEnable (GL_STENCIL_TEST); - - /* Texture surfaces have private depth/stencil buffers, so we can - * rely on any previous clip being cached there. */ - if (_cairo_gl_surface_is_texture (setup->dst)) { - cairo_clip_t *old_clip = setup->dst->clip_on_stencil_buffer; - if (_cairo_clip_equal (old_clip, setup->clip)) - goto activate_stencil_buffer_and_return; - - if (old_clip) { - _cairo_clip_destroy (setup->dst->clip_on_stencil_buffer); - } - - setup->dst->clip_on_stencil_buffer = _cairo_clip_copy (setup->clip); - } - - glClearStencil (0); - glClear (GL_STENCIL_BUFFER_BIT); - - glStencilOp (GL_REPLACE, GL_REPLACE, GL_REPLACE); - glStencilFunc (GL_EQUAL, 1, 0xffffffff); - glColorMask (0, 0, 0, 0); - - status = _cairo_gl_msaa_compositor_draw_clip (ctx, setup, clip); - - if (unlikely (status)) { - glColorMask (1, 1, 1, 1); - goto disable_stencil_buffer_and_return; - } - - /* We want to only render to the stencil buffer, so draw everything now. - Flushing also unbinds the VBO, which we want to rebind for regular - drawing. */ - _cairo_gl_composite_flush (ctx); - _cairo_gl_composite_setup_vbo (ctx, vertex_size); - -activate_stencil_buffer_and_return: - glColorMask (1, 1, 1, 1); - glStencilOp (GL_KEEP, GL_KEEP, GL_KEEP); - glStencilFunc (GL_EQUAL, 1, 0xffffffff); - return CAIRO_INT_STATUS_SUCCESS; - -disable_stencil_buffer_and_return: - _disable_stencil_buffer (); - return status; -} - -static cairo_int_status_t -_cairo_gl_composite_setup_clipping (cairo_gl_composite_t *setup, - cairo_gl_context_t *ctx, - int vertex_size) -{ - cairo_bool_t clip_changing = TRUE; - cairo_bool_t clip_region_changing = TRUE; - - if (! ctx->clip && ! setup->clip && ! setup->clip_region && ! ctx->clip_region) - goto disable_all_clipping; - - clip_changing = ! _cairo_clip_equal (ctx->clip, setup->clip); - clip_region_changing = ! cairo_region_equal (ctx->clip_region, setup->clip_region); - if (! _cairo_gl_context_is_flushed (ctx) && - (clip_region_changing || clip_changing)) - _cairo_gl_composite_flush (ctx); - - assert (!setup->clip_region || !setup->clip); - - /* setup->clip is only used by the msaa compositor and setup->clip_region - * only by the other compositors, so it's safe to wait to clean up obsolete - * clips. */ - if (clip_region_changing) { - cairo_region_destroy (ctx->clip_region); - ctx->clip_region = cairo_region_reference (setup->clip_region); - } - if (clip_changing) { - _cairo_clip_destroy (ctx->clip); - ctx->clip = _cairo_clip_copy (setup->clip); - } - - /* For clip regions, we scissor right before drawing. */ - if (setup->clip_region) - goto disable_all_clipping; - - if (setup->clip) - return _cairo_gl_composite_setup_painted_clipping (setup, ctx, - vertex_size); -disable_all_clipping: - _disable_stencil_buffer (); - glDisable (GL_SCISSOR_TEST); - return CAIRO_INT_STATUS_SUCCESS; -} - -cairo_status_t -_cairo_gl_set_operands_and_operator (cairo_gl_composite_t *setup, - cairo_gl_context_t *ctx) -{ - unsigned int dst_size, src_size, mask_size, vertex_size; - cairo_status_t status; - cairo_gl_shader_t *shader; - cairo_bool_t component_alpha; - cairo_bool_t vertex_size_changed; - - component_alpha = - setup->mask.type == CAIRO_GL_OPERAND_TEXTURE && - setup->mask.texture.attributes.has_component_alpha; - - /* Do various magic for component alpha */ - if (component_alpha) { - status = _cairo_gl_composite_begin_component_alpha (ctx, setup); - if (unlikely (status)) - return status; - } else { - if (ctx->pre_shader) { - _cairo_gl_composite_flush (ctx); - ctx->pre_shader = NULL; - } - } - - status = _cairo_gl_get_shader_by_type (ctx, - &setup->src, - &setup->mask, - setup->spans, - component_alpha ? - CAIRO_GL_SHADER_IN_CA_SOURCE : - CAIRO_GL_SHADER_IN_NORMAL, - &shader); - if (unlikely (status)) { - ctx->pre_shader = NULL; - return status; - } - if (ctx->current_shader != shader) - _cairo_gl_composite_flush (ctx); - - status = CAIRO_STATUS_SUCCESS; - - dst_size = 2 * sizeof (GLfloat); - src_size = _cairo_gl_operand_get_vertex_size (&setup->src); - mask_size = _cairo_gl_operand_get_vertex_size (&setup->mask); - vertex_size = dst_size + src_size + mask_size; - - if (setup->spans) - vertex_size += sizeof (GLfloat); - - vertex_size_changed = _cairo_gl_composite_setup_vbo (ctx, vertex_size); - - _cairo_gl_context_setup_operand (ctx, CAIRO_GL_TEX_SOURCE, &setup->src, dst_size, vertex_size_changed); - _cairo_gl_context_setup_operand (ctx, CAIRO_GL_TEX_MASK, &setup->mask, dst_size + src_size, vertex_size_changed); - - _cairo_gl_context_setup_spans (ctx, setup->spans, vertex_size, - dst_size + src_size + mask_size); - - _cairo_gl_set_operator (ctx, setup->op, component_alpha); - - if (_cairo_gl_context_is_flushed (ctx)) { - if (ctx->pre_shader) { - _cairo_gl_set_shader (ctx, ctx->pre_shader); - _cairo_gl_composite_bind_to_shader (ctx, setup); - } - _cairo_gl_set_shader (ctx, shader); - _cairo_gl_composite_bind_to_shader (ctx, setup); - } - - return status; -} - -cairo_status_t -_cairo_gl_composite_begin (cairo_gl_composite_t *setup, - cairo_gl_context_t **ctx_out) -{ - cairo_gl_context_t *ctx; - cairo_status_t status; - - assert (setup->dst); - - status = _cairo_gl_context_acquire (setup->dst->base.device, &ctx); - if (unlikely (status)) - return status; - - _cairo_gl_context_set_destination (ctx, setup->dst, setup->multisample); - glEnable (GL_BLEND); - - status = _cairo_gl_set_operands_and_operator (setup, ctx); - if (unlikely (status)) - goto FAIL; - - status = _cairo_gl_composite_setup_clipping (setup, ctx, ctx->vertex_size); - if (unlikely (status)) - goto FAIL; - - *ctx_out = ctx; - -FAIL: - if (unlikely (status)) - status = _cairo_gl_context_release (ctx, status); - - return status; -} - -static inline void -_cairo_gl_composite_draw_tristrip (cairo_gl_context_t *ctx) -{ - cairo_array_t* indices = &ctx->tristrip_indices; - const unsigned short *indices_array = _cairo_array_index_const (indices, 0); - - if (ctx->pre_shader) { - cairo_gl_shader_t *prev_shader = ctx->current_shader; - - _cairo_gl_set_shader (ctx, ctx->pre_shader); - _cairo_gl_set_operator (ctx, CAIRO_OPERATOR_DEST_OUT, TRUE); - glDrawElements (GL_TRIANGLE_STRIP, _cairo_array_num_elements (indices), GL_UNSIGNED_SHORT, indices_array); - - _cairo_gl_set_shader (ctx, prev_shader); - _cairo_gl_set_operator (ctx, CAIRO_OPERATOR_ADD, TRUE); - } - - glDrawElements (GL_TRIANGLE_STRIP, _cairo_array_num_elements (indices), GL_UNSIGNED_SHORT, indices_array); - _cairo_array_truncate (indices, 0); -} - -static inline void -_cairo_gl_composite_draw_triangles (cairo_gl_context_t *ctx, - unsigned int count) -{ - if (! ctx->pre_shader) { - glDrawArrays (GL_TRIANGLES, 0, count); - } else { - cairo_gl_shader_t *prev_shader = ctx->current_shader; - - _cairo_gl_set_shader (ctx, ctx->pre_shader); - _cairo_gl_set_operator (ctx, CAIRO_OPERATOR_DEST_OUT, TRUE); - glDrawArrays (GL_TRIANGLES, 0, count); - - _cairo_gl_set_shader (ctx, prev_shader); - _cairo_gl_set_operator (ctx, CAIRO_OPERATOR_ADD, TRUE); - glDrawArrays (GL_TRIANGLES, 0, count); - } -} - -static void -_cairo_gl_composite_draw_triangles_with_clip_region (cairo_gl_context_t *ctx, - unsigned int count) -{ - int i, num_rectangles; - - if (!ctx->clip_region) { - _cairo_gl_composite_draw_triangles (ctx, count); - return; - } - - num_rectangles = cairo_region_num_rectangles (ctx->clip_region); - for (i = 0; i < num_rectangles; i++) { - cairo_rectangle_int_t rect; - - cairo_region_get_rectangle (ctx->clip_region, i, &rect); - - _cairo_gl_scissor_to_rectangle (ctx->current_target, &rect); - _cairo_gl_composite_draw_triangles (ctx, count); - } -} - -static void -_cairo_gl_composite_unmap_vertex_buffer (cairo_gl_context_t *ctx) -{ - ctx->vb_offset = 0; -} - -void -_cairo_gl_composite_flush (cairo_gl_context_t *ctx) -{ - unsigned int count; - int i; - - if (_cairo_gl_context_is_flushed (ctx)) - return; - - count = ctx->vb_offset / ctx->vertex_size; - _cairo_gl_composite_unmap_vertex_buffer (ctx); - - if (ctx->primitive_type == CAIRO_GL_PRIMITIVE_TYPE_TRISTRIPS) { - _cairo_gl_composite_draw_tristrip (ctx); - } else { - assert (ctx->primitive_type == CAIRO_GL_PRIMITIVE_TYPE_TRIANGLES); - _cairo_gl_composite_draw_triangles_with_clip_region (ctx, count); - } - - for (i = 0; i < ARRAY_LENGTH (ctx->glyph_cache); i++) - _cairo_gl_glyph_cache_unlock (&ctx->glyph_cache[i]); -} - -static void -_cairo_gl_composite_prepare_buffer (cairo_gl_context_t *ctx, - unsigned int n_vertices, - cairo_gl_primitive_type_t primitive_type) -{ - if (ctx->primitive_type != primitive_type) { - _cairo_gl_composite_flush (ctx); - ctx->primitive_type = primitive_type; - } - - assert(ctx->vbo_size > 0); - if (ctx->vb_offset + n_vertices * ctx->vertex_size > ctx->vbo_size) - _cairo_gl_composite_flush (ctx); -} - -static inline void -_cairo_gl_composite_emit_vertex (cairo_gl_context_t *ctx, - GLfloat x, GLfloat y) -{ - GLfloat *vb = (GLfloat *) (void *) &ctx->vb[ctx->vb_offset]; - - *vb++ = x; - *vb++ = y; - - _cairo_gl_operand_emit (&ctx->operands[CAIRO_GL_TEX_SOURCE], &vb, x, y); - _cairo_gl_operand_emit (&ctx->operands[CAIRO_GL_TEX_MASK ], &vb, x, y); - - ctx->vb_offset += ctx->vertex_size; -} - -static inline void -_cairo_gl_composite_emit_alpha_vertex (cairo_gl_context_t *ctx, - GLfloat x, GLfloat y, uint8_t alpha) -{ - GLfloat *vb = (GLfloat *) (void *) &ctx->vb[ctx->vb_offset]; - union fi { - float f; - GLbyte bytes[4]; - } fi; - - *vb++ = x; - *vb++ = y; - - _cairo_gl_operand_emit (&ctx->operands[CAIRO_GL_TEX_SOURCE], &vb, x, y); - _cairo_gl_operand_emit (&ctx->operands[CAIRO_GL_TEX_MASK ], &vb, x, y); - - fi.bytes[0] = 0; - fi.bytes[1] = 0; - fi.bytes[2] = 0; - fi.bytes[3] = alpha; - *vb++ = fi.f; - - ctx->vb_offset += ctx->vertex_size; -} - -static void -_cairo_gl_composite_emit_point (cairo_gl_context_t *ctx, - const cairo_point_t *point) -{ - _cairo_gl_composite_emit_vertex (ctx, - _cairo_fixed_to_double (point->x), - _cairo_fixed_to_double (point->y)); -} - -static void -_cairo_gl_composite_emit_rect (cairo_gl_context_t *ctx, - GLfloat x1, GLfloat y1, - GLfloat x2, GLfloat y2) -{ - _cairo_gl_composite_prepare_buffer (ctx, 6, - CAIRO_GL_PRIMITIVE_TYPE_TRIANGLES); - - _cairo_gl_composite_emit_vertex (ctx, x1, y1); - _cairo_gl_composite_emit_vertex (ctx, x2, y1); - _cairo_gl_composite_emit_vertex (ctx, x1, y2); - - _cairo_gl_composite_emit_vertex (ctx, x2, y1); - _cairo_gl_composite_emit_vertex (ctx, x2, y2); - _cairo_gl_composite_emit_vertex (ctx, x1, y2); -} - -cairo_gl_emit_rect_t -_cairo_gl_context_choose_emit_rect (cairo_gl_context_t *ctx) -{ - return _cairo_gl_composite_emit_rect; -} - -void -_cairo_gl_context_emit_rect (cairo_gl_context_t *ctx, - GLfloat x1, GLfloat y1, - GLfloat x2, GLfloat y2) -{ - _cairo_gl_composite_emit_rect (ctx, x1, y1, x2, y2); -} - -static void -_cairo_gl_composite_emit_span (cairo_gl_context_t *ctx, - GLfloat x1, GLfloat y1, - GLfloat x2, GLfloat y2, - uint8_t alpha) -{ - _cairo_gl_composite_prepare_buffer (ctx, 6, - CAIRO_GL_PRIMITIVE_TYPE_TRIANGLES); - - _cairo_gl_composite_emit_alpha_vertex (ctx, x1, y1, alpha); - _cairo_gl_composite_emit_alpha_vertex (ctx, x2, y1, alpha); - _cairo_gl_composite_emit_alpha_vertex (ctx, x1, y2, alpha); - - _cairo_gl_composite_emit_alpha_vertex (ctx, x2, y1, alpha); - _cairo_gl_composite_emit_alpha_vertex (ctx, x2, y2, alpha); - _cairo_gl_composite_emit_alpha_vertex (ctx, x1, y2, alpha); -} - -static void -_cairo_gl_composite_emit_solid_span (cairo_gl_context_t *ctx, - GLfloat x1, GLfloat y1, - GLfloat x2, GLfloat y2, - uint8_t alpha) -{ - GLfloat *v; - union fi { - float f; - GLbyte bytes[4]; - } fi; - - _cairo_gl_composite_prepare_buffer (ctx, 6, - CAIRO_GL_PRIMITIVE_TYPE_TRIANGLES); - v = (GLfloat *) (void *) &ctx->vb[ctx->vb_offset]; - - v[15] = v[ 6] = v[0] = x1; - v[10] = v[ 4] = v[1] = y1; - v[12] = v[ 9] = v[3] = x2; - v[16] = v[13] = v[7] = y2; - - fi.bytes[0] = 0; - fi.bytes[1] = 0; - fi.bytes[2] = 0; - fi.bytes[3] = alpha; - v[17] =v[14] = v[11] = v[8] = v[5] = v[2] = fi.f; - - ctx->vb_offset += 6*3 * sizeof(GLfloat); -} - -cairo_gl_emit_span_t -_cairo_gl_context_choose_emit_span (cairo_gl_context_t *ctx) -{ - if (ctx->operands[CAIRO_GL_TEX_MASK].type != CAIRO_GL_OPERAND_NONE) { - switch (ctx->operands[CAIRO_GL_TEX_MASK].type) { - default: - case CAIRO_GL_OPERAND_COUNT: - ASSERT_NOT_REACHED; - case CAIRO_GL_OPERAND_NONE: - case CAIRO_GL_OPERAND_CONSTANT: - break; - - case CAIRO_GL_OPERAND_LINEAR_GRADIENT: - case CAIRO_GL_OPERAND_RADIAL_GRADIENT_A0: - case CAIRO_GL_OPERAND_RADIAL_GRADIENT_NONE: - case CAIRO_GL_OPERAND_RADIAL_GRADIENT_EXT: - if (!ctx->operands[CAIRO_GL_TEX_MASK].gradient.texgen) - return _cairo_gl_composite_emit_span; - break; - - case CAIRO_GL_OPERAND_TEXTURE: - if (!ctx->operands[CAIRO_GL_TEX_MASK].texture.texgen) - return _cairo_gl_composite_emit_span; - break; - } - } - - switch (ctx->operands[CAIRO_GL_TEX_SOURCE].type) { - default: - case CAIRO_GL_OPERAND_COUNT: - ASSERT_NOT_REACHED; - case CAIRO_GL_OPERAND_NONE: - case CAIRO_GL_OPERAND_CONSTANT: - break; - - case CAIRO_GL_OPERAND_LINEAR_GRADIENT: - case CAIRO_GL_OPERAND_RADIAL_GRADIENT_A0: - case CAIRO_GL_OPERAND_RADIAL_GRADIENT_NONE: - case CAIRO_GL_OPERAND_RADIAL_GRADIENT_EXT: - if (!ctx->operands[CAIRO_GL_TEX_SOURCE].gradient.texgen) - return _cairo_gl_composite_emit_span; - break; - - case CAIRO_GL_OPERAND_TEXTURE: - if (!ctx->operands[CAIRO_GL_TEX_SOURCE].texture.texgen) - return _cairo_gl_composite_emit_span; - } - - return _cairo_gl_composite_emit_solid_span; -} - -static inline void -_cairo_gl_composite_emit_glyph_vertex (cairo_gl_context_t *ctx, - GLfloat x, GLfloat y, - GLfloat glyph_x, GLfloat glyph_y) -{ - GLfloat *vb = (GLfloat *) (void *) &ctx->vb[ctx->vb_offset]; - - *vb++ = x; - *vb++ = y; - - _cairo_gl_operand_emit (&ctx->operands[CAIRO_GL_TEX_SOURCE], &vb, x, y); - - *vb++ = glyph_x; - *vb++ = glyph_y; - - ctx->vb_offset += ctx->vertex_size; -} - -static void -_cairo_gl_composite_emit_glyph (cairo_gl_context_t *ctx, - GLfloat x1, GLfloat y1, - GLfloat x2, GLfloat y2, - GLfloat glyph_x1, GLfloat glyph_y1, - GLfloat glyph_x2, GLfloat glyph_y2) -{ - _cairo_gl_composite_prepare_buffer (ctx, 6, - CAIRO_GL_PRIMITIVE_TYPE_TRIANGLES); - - _cairo_gl_composite_emit_glyph_vertex (ctx, x1, y1, glyph_x1, glyph_y1); - _cairo_gl_composite_emit_glyph_vertex (ctx, x2, y1, glyph_x2, glyph_y1); - _cairo_gl_composite_emit_glyph_vertex (ctx, x1, y2, glyph_x1, glyph_y2); - - _cairo_gl_composite_emit_glyph_vertex (ctx, x2, y1, glyph_x2, glyph_y1); - _cairo_gl_composite_emit_glyph_vertex (ctx, x2, y2, glyph_x2, glyph_y2); - _cairo_gl_composite_emit_glyph_vertex (ctx, x1, y2, glyph_x1, glyph_y2); -} - -static void -_cairo_gl_composite_emit_solid_glyph (cairo_gl_context_t *ctx, - GLfloat x1, GLfloat y1, - GLfloat x2, GLfloat y2, - GLfloat glyph_x1, GLfloat glyph_y1, - GLfloat glyph_x2, GLfloat glyph_y2) -{ - GLfloat *v; - - _cairo_gl_composite_prepare_buffer (ctx, 6, - CAIRO_GL_PRIMITIVE_TYPE_TRIANGLES); - - v = (GLfloat *) (void *) &ctx->vb[ctx->vb_offset]; - - v[20] = v[ 8] = v[0] = x1; - v[13] = v[ 5] = v[1] = y1; - v[22] = v[10] = v[2] = glyph_x1; - v[15] = v[ 7] = v[3] = glyph_y1; - - v[16] = v[12] = v[4] = x2; - v[18] = v[14] = v[6] = glyph_x2; - - v[21] = v[17] = v[ 9] = y2; - v[23] = v[19] = v[11] = glyph_y2; - - ctx->vb_offset += 4 * 6 * sizeof (GLfloat); -} - -cairo_gl_emit_glyph_t -_cairo_gl_context_choose_emit_glyph (cairo_gl_context_t *ctx) -{ - switch (ctx->operands[CAIRO_GL_TEX_SOURCE].type) { - default: - case CAIRO_GL_OPERAND_COUNT: - ASSERT_NOT_REACHED; - case CAIRO_GL_OPERAND_NONE: - case CAIRO_GL_OPERAND_CONSTANT: - return _cairo_gl_composite_emit_solid_glyph; - - case CAIRO_GL_OPERAND_LINEAR_GRADIENT: - case CAIRO_GL_OPERAND_RADIAL_GRADIENT_A0: - case CAIRO_GL_OPERAND_RADIAL_GRADIENT_NONE: - case CAIRO_GL_OPERAND_RADIAL_GRADIENT_EXT: - case CAIRO_GL_OPERAND_TEXTURE: - return _cairo_gl_composite_emit_glyph; - } -} - -void -_cairo_gl_composite_fini (cairo_gl_composite_t *setup) -{ - _cairo_gl_operand_destroy (&setup->src); - _cairo_gl_operand_destroy (&setup->mask); -} - -cairo_status_t -_cairo_gl_composite_set_operator (cairo_gl_composite_t *setup, - cairo_operator_t op, - cairo_bool_t assume_component_alpha) -{ - if (assume_component_alpha) { - if (op != CAIRO_OPERATOR_CLEAR && - op != CAIRO_OPERATOR_OVER && - op != CAIRO_OPERATOR_ADD) - return UNSUPPORTED ("unsupported component alpha operator"); - } else { - if (! _cairo_gl_operator_is_supported (op)) - return UNSUPPORTED ("unsupported operator"); - } - - setup->op = op; - return CAIRO_STATUS_SUCCESS; -} - -cairo_status_t -_cairo_gl_composite_init (cairo_gl_composite_t *setup, - cairo_operator_t op, - cairo_gl_surface_t *dst, - cairo_bool_t assume_component_alpha) -{ - cairo_status_t status; - - status = _blit_texture_to_renderbuffer (dst); - - memset (setup, 0, sizeof (cairo_gl_composite_t)); - - status = _cairo_gl_composite_set_operator (setup, op, - assume_component_alpha); - if (status) - return status; - - setup->dst = dst; - setup->clip_region = dst->clip_region; - - return CAIRO_STATUS_SUCCESS; -} - -static cairo_int_status_t -_cairo_gl_composite_append_vertex_indices (cairo_gl_context_t *ctx, - int number_of_new_indices) -{ - cairo_int_status_t status = CAIRO_INT_STATUS_SUCCESS; - cairo_array_t *indices = &ctx->tristrip_indices; - int number_of_indices = _cairo_array_num_elements (indices); - unsigned short current_vertex_index = 0; - int i; - - assert (number_of_new_indices > 0); - - /* If any preexisting triangle triangle strip indices exist on this - context, we insert a set of degenerate triangles from the last - preexisting vertex to our first one. */ - if (number_of_indices > 0) { - const unsigned short *indices_array = _cairo_array_index_const (indices, 0); - current_vertex_index = indices_array[number_of_indices - 1]; - - status = _cairo_array_append (indices, ¤t_vertex_index); - if (unlikely (status)) - return status; - - current_vertex_index++; - status =_cairo_array_append (indices, ¤t_vertex_index); - if (unlikely (status)) - return status; - } - - for (i = 0; i < number_of_new_indices; i++) { - status = _cairo_array_append (indices, ¤t_vertex_index); - current_vertex_index++; - if (unlikely (status)) - return status; - } - - return CAIRO_STATUS_SUCCESS; -} - -cairo_int_status_t -_cairo_gl_composite_emit_quad_as_tristrip (cairo_gl_context_t *ctx, - cairo_gl_composite_t *setup, - const cairo_point_t quad[4]) -{ - _cairo_gl_composite_prepare_buffer (ctx, 4, - CAIRO_GL_PRIMITIVE_TYPE_TRISTRIPS); - - _cairo_gl_composite_emit_point (ctx, &quad[0]); - _cairo_gl_composite_emit_point (ctx, &quad[1]); - - /* Cairo stores quad vertices in counter-clockwise order, but we need to - emit them from top to bottom in the triangle strip, so we need to reverse - the order of the last two vertices. */ - _cairo_gl_composite_emit_point (ctx, &quad[3]); - _cairo_gl_composite_emit_point (ctx, &quad[2]); - - return _cairo_gl_composite_append_vertex_indices (ctx, 4); -} - -cairo_int_status_t -_cairo_gl_composite_emit_triangle_as_tristrip (cairo_gl_context_t *ctx, - cairo_gl_composite_t *setup, - const cairo_point_t triangle[3]) -{ - _cairo_gl_composite_prepare_buffer (ctx, 3, - CAIRO_GL_PRIMITIVE_TYPE_TRISTRIPS); - - _cairo_gl_composite_emit_point (ctx, &triangle[0]); - _cairo_gl_composite_emit_point (ctx, &triangle[1]); - _cairo_gl_composite_emit_point (ctx, &triangle[2]); - return _cairo_gl_composite_append_vertex_indices (ctx, 3); -} diff --git a/gfx/cairo/cairo/src/cairo-gl-device.c b/gfx/cairo/cairo/src/cairo-gl-device.c deleted file mode 100644 index 6f4c852a45..0000000000 --- a/gfx/cairo/cairo/src/cairo-gl-device.c +++ /dev/null @@ -1,851 +0,0 @@ -/* cairo - a vector graphics library with display and print output - * - * Copyright © 2009 Eric Anholt - * Copyright © 2009 Chris Wilson - * Copyright © 2005,2010 Red Hat, Inc - * Copyright © 2010 Linaro Limited - * - * 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., 51 Franklin Street, Suite 500, Boston, MA 02110-1335, 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): - * Benjamin Otte <otte@gnome.org> - * Carl Worth <cworth@cworth.org> - * Chris Wilson <chris@chris-wilson.co.uk> - * Eric Anholt <eric@anholt.net> - * Alexandros Frantzis <alexandros.frantzis@linaro.org> - */ - -#include "cairoint.h" - -#include "cairo-error-private.h" -#include "cairo-gl-private.h" - -#define MAX_MSAA_SAMPLES 4 - -static void -_gl_lock (void *device) -{ - cairo_gl_context_t *ctx = (cairo_gl_context_t *) device; - - ctx->acquire (ctx); -} - -static void -_gl_unlock (void *device) -{ - cairo_gl_context_t *ctx = (cairo_gl_context_t *) device; - - ctx->release (ctx); -} - -static cairo_status_t -_gl_flush (void *device) -{ - cairo_gl_context_t *ctx; - cairo_status_t status; - - status = _cairo_gl_context_acquire (device, &ctx); - if (unlikely (status)) - return status; - - _cairo_gl_composite_flush (ctx); - - _cairo_gl_context_destroy_operand (ctx, CAIRO_GL_TEX_SOURCE); - _cairo_gl_context_destroy_operand (ctx, CAIRO_GL_TEX_MASK); - - if (ctx->clip_region) { - cairo_region_destroy (ctx->clip_region); - ctx->clip_region = NULL; - } - - ctx->current_target = NULL; - ctx->current_operator = -1; - ctx->vertex_size = 0; - ctx->pre_shader = NULL; - _cairo_gl_set_shader (ctx, NULL); - - ctx->dispatch.BindBuffer (GL_ARRAY_BUFFER, 0); - - glDisable (GL_SCISSOR_TEST); - glDisable (GL_BLEND); - - return _cairo_gl_context_release (ctx, status); -} - -static void -_gl_finish (void *device) -{ - cairo_gl_context_t *ctx = device; - int n; - - _gl_lock (device); - - _cairo_cache_fini (&ctx->gradients); - - _cairo_gl_context_fini_shaders (ctx); - - for (n = 0; n < ARRAY_LENGTH (ctx->glyph_cache); n++) - _cairo_gl_glyph_cache_fini (ctx, &ctx->glyph_cache[n]); - - _gl_unlock (device); -} - -static void -_gl_destroy (void *device) -{ - cairo_gl_context_t *ctx = device; - - ctx->acquire (ctx); - - while (! cairo_list_is_empty (&ctx->fonts)) { - cairo_gl_font_t *font; - - font = cairo_list_first_entry (&ctx->fonts, - cairo_gl_font_t, - link); - - cairo_list_del (&font->base.link); - cairo_list_del (&font->link); - free (font); - } - - _cairo_array_fini (&ctx->tristrip_indices); - - cairo_region_destroy (ctx->clip_region); - _cairo_clip_destroy (ctx->clip); - - free (ctx->vb); - - ctx->destroy (ctx); - - free (ctx); -} - -static const cairo_device_backend_t _cairo_gl_device_backend = { - CAIRO_DEVICE_TYPE_GL, - - _gl_lock, - _gl_unlock, - - _gl_flush, /* flush */ - _gl_finish, - _gl_destroy, -}; - -static cairo_bool_t -_cairo_gl_msaa_compositor_enabled (void) -{ - const char *env = getenv ("CAIRO_GL_COMPOSITOR"); - return env && strcmp(env, "msaa") == 0; -} - -static cairo_bool_t -test_can_read_bgra (cairo_gl_flavor_t gl_flavor) -{ - /* Desktop GL always supports BGRA formats. */ - if (gl_flavor == CAIRO_GL_FLAVOR_DESKTOP) - return TRUE; - - assert (gl_flavor == CAIRO_GL_FLAVOR_ES3 || - gl_flavor == CAIRO_GL_FLAVOR_ES2); - - /* For OpenGL ES we have to look for the specific extension and BGRA only - * matches cairo's integer packed bytes on little-endian machines. */ - if (!_cairo_is_little_endian()) - return FALSE; - return _cairo_gl_has_extension ("EXT_read_format_bgra"); -} - -cairo_status_t -_cairo_gl_context_init (cairo_gl_context_t *ctx) -{ - cairo_status_t status; - cairo_gl_dispatch_t *dispatch = &ctx->dispatch; - int gl_version = _cairo_gl_get_version (); - cairo_gl_flavor_t gl_flavor = _cairo_gl_get_flavor (); - int n; - - cairo_bool_t is_desktop = gl_flavor == CAIRO_GL_FLAVOR_DESKTOP; - cairo_bool_t is_gles = (gl_flavor == CAIRO_GL_FLAVOR_ES3 || - gl_flavor == CAIRO_GL_FLAVOR_ES2); - - _cairo_device_init (&ctx->base, &_cairo_gl_device_backend); - - /* XXX The choice of compositor should be made automatically at runtime. - * However, it is useful to force one particular compositor whilst - * testing. - */ - if (_cairo_gl_msaa_compositor_enabled ()) - ctx->compositor = _cairo_gl_msaa_compositor_get (); - else - ctx->compositor = _cairo_gl_span_compositor_get (); - - - ctx->thread_aware = TRUE; - - memset (ctx->glyph_cache, 0, sizeof (ctx->glyph_cache)); - cairo_list_init (&ctx->fonts); - - /* Support only GL version >= 1.3 */ - if (gl_version < CAIRO_GL_VERSION_ENCODE (1, 3)) - return _cairo_error (CAIRO_STATUS_DEVICE_ERROR); - - /* Check for required extensions */ - if (is_desktop) { - if (_cairo_gl_has_extension ("GL_ARB_texture_non_power_of_two")) { - ctx->tex_target = GL_TEXTURE_2D; - ctx->has_npot_repeat = TRUE; - } else if (_cairo_gl_has_extension ("GL_ARB_texture_rectangle")) { - ctx->tex_target = GL_TEXTURE_RECTANGLE; - ctx->has_npot_repeat = FALSE; - } else - return _cairo_error (CAIRO_STATUS_DEVICE_ERROR); - } else { - ctx->tex_target = GL_TEXTURE_2D; - if (_cairo_gl_has_extension ("GL_OES_texture_npot") || - _cairo_gl_has_extension ("GL_IMG_texture_npot")) - ctx->has_npot_repeat = TRUE; - else - ctx->has_npot_repeat = FALSE; - } - - if (is_desktop && gl_version < CAIRO_GL_VERSION_ENCODE (2, 1) && - ! _cairo_gl_has_extension ("GL_ARB_pixel_buffer_object")) - return _cairo_error (CAIRO_STATUS_DEVICE_ERROR); - - if (is_gles && ! _cairo_gl_has_extension ("GL_EXT_texture_format_BGRA8888")) - return _cairo_error (CAIRO_STATUS_DEVICE_ERROR); - - ctx->has_map_buffer = - is_desktop || (is_gles && _cairo_gl_has_extension ("GL_OES_mapbuffer")); - - ctx->can_read_bgra = test_can_read_bgra (gl_flavor); - - ctx->has_mesa_pack_invert = - _cairo_gl_has_extension ("GL_MESA_pack_invert"); - - ctx->has_packed_depth_stencil = - (is_desktop && _cairo_gl_has_extension ("GL_EXT_packed_depth_stencil")) || - (is_gles && _cairo_gl_has_extension ("GL_OES_packed_depth_stencil")); - - ctx->num_samples = 1; - -#if CAIRO_HAS_GL_SURFACE - if (is_desktop && ctx->has_packed_depth_stencil && - (gl_version >= CAIRO_GL_VERSION_ENCODE (3, 0) || - _cairo_gl_has_extension ("GL_ARB_framebuffer_object") || - (_cairo_gl_has_extension ("GL_EXT_framebuffer_blit") && - _cairo_gl_has_extension ("GL_EXT_framebuffer_multisample")))) { - glGetIntegerv(GL_MAX_SAMPLES_EXT, &ctx->num_samples); - } -#endif - -#if CAIRO_HAS_GLESV3_SURFACE - if (is_gles && ctx->has_packed_depth_stencil) { - glGetIntegerv(GL_MAX_SAMPLES, &ctx->num_samples); - } - -#elif CAIRO_HAS_GLESV2_SURFACE && defined(GL_MAX_SAMPLES_EXT) - if (is_gles && ctx->has_packed_depth_stencil && - _cairo_gl_has_extension ("GL_EXT_multisampled_render_to_texture")) { - glGetIntegerv(GL_MAX_SAMPLES_EXT, &ctx->num_samples); - } - - if (is_gles && ctx->has_packed_depth_stencil && - _cairo_gl_has_extension ("GL_IMG_multisampled_render_to_texture")) { - glGetIntegerv(GL_MAX_SAMPLES_IMG, &ctx->num_samples); - } -#endif - - /* we always use renderbuffer for rendering in glesv3 */ - if (ctx->gl_flavor == CAIRO_GL_FLAVOR_ES3) - ctx->supports_msaa = TRUE; - else - ctx->supports_msaa = ctx->num_samples > 1; - if (ctx->num_samples > MAX_MSAA_SAMPLES) - ctx->num_samples = MAX_MSAA_SAMPLES; - - ctx->current_operator = -1; - ctx->gl_flavor = gl_flavor; - - status = _cairo_gl_context_init_shaders (ctx); - if (unlikely (status)) - return status; - - status = _cairo_cache_init (&ctx->gradients, - _cairo_gl_gradient_equal, - NULL, - (cairo_destroy_func_t) _cairo_gl_gradient_destroy, - CAIRO_GL_GRADIENT_CACHE_SIZE); - if (unlikely (status)) - return status; - - ctx->vbo_size = _cairo_gl_get_vbo_size(); - - ctx->vb = _cairo_malloc (ctx->vbo_size); - if (unlikely (ctx->vb == NULL)) { - _cairo_cache_fini (&ctx->gradients); - return _cairo_error (CAIRO_STATUS_NO_MEMORY); - } - - ctx->primitive_type = CAIRO_GL_PRIMITIVE_TYPE_TRIANGLES; - _cairo_array_init (&ctx->tristrip_indices, sizeof (unsigned short)); - - /* PBO for any sort of texture upload */ - dispatch->GenBuffers (1, &ctx->texture_load_pbo); - - ctx->max_framebuffer_size = 0; - glGetIntegerv (GL_MAX_RENDERBUFFER_SIZE, &ctx->max_framebuffer_size); - ctx->max_texture_size = 0; - glGetIntegerv (GL_MAX_TEXTURE_SIZE, &ctx->max_texture_size); - ctx->max_textures = 0; - glGetIntegerv (GL_MAX_TEXTURE_IMAGE_UNITS, &ctx->max_textures); - - for (n = 0; n < ARRAY_LENGTH (ctx->glyph_cache); n++) - _cairo_gl_glyph_cache_init (&ctx->glyph_cache[n]); - - return CAIRO_STATUS_SUCCESS; -} - -void -_cairo_gl_context_activate (cairo_gl_context_t *ctx, - cairo_gl_tex_t tex_unit) -{ - if (ctx->max_textures <= (GLint) tex_unit) { - if (tex_unit < 2) { - _cairo_gl_composite_flush (ctx); - _cairo_gl_context_destroy_operand (ctx, ctx->max_textures - 1); - } - glActiveTexture (ctx->max_textures - 1); - } else { - glActiveTexture (GL_TEXTURE0 + tex_unit); - } -} - -static GLenum -_get_depth_stencil_format (cairo_gl_context_t *ctx) -{ - /* This is necessary to properly handle the situation where both - OpenGL and OpenGLES are active and returning a sane default. */ -#if CAIRO_HAS_GL_SURFACE - if (ctx->gl_flavor == CAIRO_GL_FLAVOR_DESKTOP) - return GL_DEPTH_STENCIL; -#endif - -#if CAIRO_HAS_GLESV2_SURFACE && !CAIRO_HAS_GLESV3_SURFACE - if (ctx->gl_flavor == CAIRO_GL_FLAVOR_DESKTOP) - return GL_DEPTH24_STENCIL8_OES; -#endif - -#if CAIRO_HAS_GL_SURFACE - return GL_DEPTH_STENCIL; -#elif CAIRO_HAS_GLESV3_SURFACE - return GL_DEPTH24_STENCIL8; -#elif CAIRO_HAS_GLESV2_SURFACE - return GL_DEPTH24_STENCIL8_OES; -#endif -} - -#if CAIRO_HAS_GLESV2_SURFACE -static void -_cairo_gl_ensure_msaa_gles_framebuffer (cairo_gl_context_t *ctx, - cairo_gl_surface_t *surface) -{ - if (surface->msaa_active) - return; - - ctx->dispatch.FramebufferTexture2DMultisample(GL_FRAMEBUFFER, - GL_COLOR_ATTACHMENT0, - ctx->tex_target, - surface->tex, - 0, - ctx->num_samples); - - /* From now on MSAA will always be active on this surface. */ - surface->msaa_active = TRUE; -} -#endif - -void -_cairo_gl_ensure_framebuffer (cairo_gl_context_t *ctx, - cairo_gl_surface_t *surface) -{ - GLenum status; - cairo_gl_dispatch_t *dispatch = &ctx->dispatch; - - if (likely (surface->fb)) - return; - - /* Create a framebuffer object wrapping the texture so that we can render - * to it. - */ - dispatch->GenFramebuffers (1, &surface->fb); - dispatch->BindFramebuffer (GL_FRAMEBUFFER, surface->fb); - - /* Unlike for desktop GL we only maintain one multisampling framebuffer - for OpenGLES since the EXT_multisampled_render_to_texture extension - does not require an explicit multisample resolution. */ -#if CAIRO_HAS_GLESV2_SURFACE - if (surface->supports_msaa && _cairo_gl_msaa_compositor_enabled () && - ctx->gl_flavor == CAIRO_GL_FLAVOR_ES2) { - _cairo_gl_ensure_msaa_gles_framebuffer (ctx, surface); - } else -#endif - dispatch->FramebufferTexture2D (GL_FRAMEBUFFER, - GL_COLOR_ATTACHMENT0, - ctx->tex_target, - surface->tex, - 0); - -#if CAIRO_HAS_GL_SURFACE - glDrawBuffer (GL_COLOR_ATTACHMENT0); - glReadBuffer (GL_COLOR_ATTACHMENT0); -#endif - - status = dispatch->CheckFramebufferStatus (GL_FRAMEBUFFER); - if (status != GL_FRAMEBUFFER_COMPLETE) { - const char *str; - switch (status) { - //case GL_FRAMEBUFFER_UNDEFINED: str= "undefined"; break; - case GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT: str= "incomplete attachment"; break; - case GL_FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT: str= "incomplete/missing attachment"; break; - case GL_FRAMEBUFFER_INCOMPLETE_DRAW_BUFFER: str= "incomplete draw buffer"; break; - case GL_FRAMEBUFFER_INCOMPLETE_READ_BUFFER: str= "incomplete read buffer"; break; - case GL_FRAMEBUFFER_UNSUPPORTED: str= "unsupported"; break; - case GL_FRAMEBUFFER_INCOMPLETE_MULTISAMPLE: str= "incomplete multiple"; break; - default: str = "unknown error"; break; - } - - fprintf (stderr, - "destination is framebuffer incomplete: %s [%#x]\n", - str, status); - } -} -#if CAIRO_HAS_GL_SURFACE || CAIRO_HAS_GLESV3_SURFACE -static void -_cairo_gl_ensure_multisampling (cairo_gl_context_t *ctx, - cairo_gl_surface_t *surface) -{ - assert (surface->supports_msaa); - assert (ctx->gl_flavor == CAIRO_GL_FLAVOR_DESKTOP || - ctx->gl_flavor == CAIRO_GL_FLAVOR_ES3); - - if (surface->msaa_fb) - return; - - /* We maintain a separate framebuffer for multisampling operations. - This allows us to do a fast paint to the non-multisampling framebuffer - when mulitsampling is disabled. */ - ctx->dispatch.GenFramebuffers (1, &surface->msaa_fb); - ctx->dispatch.BindFramebuffer (GL_FRAMEBUFFER, surface->msaa_fb); - ctx->dispatch.GenRenderbuffers (1, &surface->msaa_rb); - ctx->dispatch.BindRenderbuffer (GL_RENDERBUFFER, surface->msaa_rb); - - /* FIXME: For now we assume that textures passed from the outside have GL_RGBA - format, but eventually we need to expose a way for the API consumer to pass - this information. */ - ctx->dispatch.RenderbufferStorageMultisample (GL_RENDERBUFFER, - ctx->num_samples, -#if CAIRO_HAS_GLESV3_SURFACE - GL_RGBA8, -#else - GL_RGBA, -#endif - surface->width, - surface->height); - ctx->dispatch.FramebufferRenderbuffer (GL_FRAMEBUFFER, - GL_COLOR_ATTACHMENT0, - GL_RENDERBUFFER, - surface->msaa_rb); - - /* Cairo surfaces start out initialized to transparent (black) */ - glDisable (GL_SCISSOR_TEST); - glClearColor (0, 0, 0, 0); - glClear (GL_COLOR_BUFFER_BIT); - - /* for glesv3 with multisample renderbuffer, we always render to - this renderbuffer */ - if (ctx->gl_flavor == CAIRO_GL_FLAVOR_ES3) - surface->msaa_active = TRUE; -} -#endif - -static cairo_bool_t -_cairo_gl_ensure_msaa_depth_stencil_buffer (cairo_gl_context_t *ctx, - cairo_gl_surface_t *surface) -{ - cairo_gl_dispatch_t *dispatch = &ctx->dispatch; - if (surface->msaa_depth_stencil) - return TRUE; - - _cairo_gl_ensure_framebuffer (ctx, surface); -#if CAIRO_HAS_GL_SURFACE || CAIRO_HAS_GLESV3_SURFACE - if (ctx->gl_flavor == CAIRO_GL_FLAVOR_DESKTOP || - ctx->gl_flavor == CAIRO_GL_FLAVOR_ES3) - _cairo_gl_ensure_multisampling (ctx, surface); -#endif - - dispatch->GenRenderbuffers (1, &surface->msaa_depth_stencil); - dispatch->BindRenderbuffer (GL_RENDERBUFFER, - surface->msaa_depth_stencil); - - dispatch->RenderbufferStorageMultisample (GL_RENDERBUFFER, - ctx->num_samples, - _get_depth_stencil_format (ctx), - surface->width, - surface->height); - -#if CAIRO_HAS_GL_SURFACE || CAIRO_HAS_GLESV3_SURFACE - if (ctx->gl_flavor == CAIRO_GL_FLAVOR_DESKTOP || - ctx->gl_flavor == CAIRO_GL_FLAVOR_ES3) { - dispatch->FramebufferRenderbuffer (GL_FRAMEBUFFER, - GL_DEPTH_STENCIL_ATTACHMENT, - GL_RENDERBUFFER, - surface->msaa_depth_stencil); - } -#endif - -#if CAIRO_HAS_GLESV2_SURFACE - if (ctx->gl_flavor == CAIRO_GL_FLAVOR_ES2) { - dispatch->FramebufferRenderbuffer (GL_FRAMEBUFFER, - GL_DEPTH_ATTACHMENT, - GL_RENDERBUFFER, - surface->msaa_depth_stencil); - dispatch->FramebufferRenderbuffer (GL_FRAMEBUFFER, - GL_STENCIL_ATTACHMENT, - GL_RENDERBUFFER, - surface->msaa_depth_stencil); - } -#endif - - if (dispatch->CheckFramebufferStatus (GL_FRAMEBUFFER) != GL_FRAMEBUFFER_COMPLETE) { - dispatch->DeleteRenderbuffers (1, &surface->msaa_depth_stencil); - surface->msaa_depth_stencil = 0; - return FALSE; - } - - return TRUE; -} - -static cairo_bool_t -_cairo_gl_ensure_depth_stencil_buffer (cairo_gl_context_t *ctx, - cairo_gl_surface_t *surface) -{ - cairo_gl_dispatch_t *dispatch = &ctx->dispatch; - - if (surface->depth_stencil) - return TRUE; - - _cairo_gl_ensure_framebuffer (ctx, surface); - - dispatch->GenRenderbuffers (1, &surface->depth_stencil); - dispatch->BindRenderbuffer (GL_RENDERBUFFER, surface->depth_stencil); - dispatch->RenderbufferStorage (GL_RENDERBUFFER, - _get_depth_stencil_format (ctx), - surface->width, surface->height); - - dispatch->FramebufferRenderbuffer (GL_FRAMEBUFFER, GL_STENCIL_ATTACHMENT, - GL_RENDERBUFFER, surface->depth_stencil); - dispatch->FramebufferRenderbuffer (GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, - GL_RENDERBUFFER, surface->depth_stencil); - if (dispatch->CheckFramebufferStatus (GL_FRAMEBUFFER) != GL_FRAMEBUFFER_COMPLETE) { - dispatch->DeleteRenderbuffers (1, &surface->depth_stencil); - surface->depth_stencil = 0; - return FALSE; - } - - return TRUE; -} - -cairo_bool_t -_cairo_gl_ensure_stencil (cairo_gl_context_t *ctx, - cairo_gl_surface_t *surface) -{ - if (! _cairo_gl_surface_is_texture (surface)) - return TRUE; /* best guess for now, will check later */ - if (! ctx->has_packed_depth_stencil) - return FALSE; - - if (surface->msaa_active) - return _cairo_gl_ensure_msaa_depth_stencil_buffer (ctx, surface); - else - return _cairo_gl_ensure_depth_stencil_buffer (ctx, surface); -} - -/* - * Stores a parallel projection transformation in matrix 'm', - * using column-major order. - * - * This is equivalent to: - * - * glLoadIdentity() - * gluOrtho2D() - * - * The calculation for the ortho transformation was taken from the - * mesa source code. - */ -static void -_gl_identity_ortho (GLfloat *m, - GLfloat left, GLfloat right, - GLfloat bottom, GLfloat top) -{ -#define M(row,col) m[col*4+row] - M(0,0) = 2.f / (right - left); - M(0,1) = 0.f; - M(0,2) = 0.f; - M(0,3) = -(right + left) / (right - left); - - M(1,0) = 0.f; - M(1,1) = 2.f / (top - bottom); - M(1,2) = 0.f; - M(1,3) = -(top + bottom) / (top - bottom); - - M(2,0) = 0.f; - M(2,1) = 0.f; - M(2,2) = -1.f; - M(2,3) = 0.f; - - M(3,0) = 0.f; - M(3,1) = 0.f; - M(3,2) = 0.f; - M(3,3) = 1.f; -#undef M -} - -#if CAIRO_HAS_GL_SURFACE || CAIRO_HAS_GLESV3_SURFACE -static void -bind_multisample_framebuffer (cairo_gl_context_t *ctx, - cairo_gl_surface_t *surface) -{ - cairo_bool_t stencil_test_enabled; - cairo_bool_t scissor_test_enabled; - - assert (surface->supports_msaa); - assert (ctx->gl_flavor == CAIRO_GL_FLAVOR_DESKTOP || - ctx->gl_flavor == CAIRO_GL_FLAVOR_ES3); - - _cairo_gl_ensure_framebuffer (ctx, surface); - _cairo_gl_ensure_multisampling (ctx, surface); - - if (surface->msaa_active) { -#if CAIRO_HAS_GL_SURFACE - glEnable (GL_MULTISAMPLE); -#endif - ctx->dispatch.BindFramebuffer (GL_FRAMEBUFFER, surface->msaa_fb); - if (ctx->gl_flavor == CAIRO_GL_FLAVOR_ES3) - surface->content_in_texture = FALSE; - return; - } - - _cairo_gl_composite_flush (ctx); - - stencil_test_enabled = glIsEnabled (GL_STENCIL_TEST); - scissor_test_enabled = glIsEnabled (GL_SCISSOR_TEST); - glDisable (GL_STENCIL_TEST); - glDisable (GL_SCISSOR_TEST); - -#if CAIRO_HAS_GL_SURFACE - glEnable (GL_MULTISAMPLE); -#endif - - /* The last time we drew to the surface, we were not using multisampling, - so we need to blit from the non-multisampling framebuffer into the - multisampling framebuffer. */ - ctx->dispatch.BindFramebuffer (GL_DRAW_FRAMEBUFFER, surface->msaa_fb); - ctx->dispatch.BindFramebuffer (GL_READ_FRAMEBUFFER, surface->fb); - ctx->dispatch.BlitFramebuffer (0, 0, surface->width, surface->height, - 0, 0, surface->width, surface->height, - GL_COLOR_BUFFER_BIT -#if CAIRO_HAS_GL_SURFACE - | GL_STENCIL_BUFFER_BIT -#endif - , - GL_NEAREST); - ctx->dispatch.BindFramebuffer (GL_FRAMEBUFFER, surface->msaa_fb); - - if (stencil_test_enabled) - glEnable (GL_STENCIL_TEST); - if (scissor_test_enabled) - glEnable (GL_SCISSOR_TEST); - if (ctx->gl_flavor == CAIRO_GL_FLAVOR_ES3) - surface->content_in_texture = FALSE; -} -#endif - -#if CAIRO_HAS_GL_SURFACE || CAIRO_HAS_GLESV3_SURFACE -static void -bind_singlesample_framebuffer (cairo_gl_context_t *ctx, - cairo_gl_surface_t *surface) -{ - cairo_bool_t stencil_test_enabled; - cairo_bool_t scissor_test_enabled; - - assert (ctx->gl_flavor == CAIRO_GL_FLAVOR_DESKTOP || - ctx->gl_flavor == CAIRO_GL_FLAVOR_ES3); - _cairo_gl_ensure_framebuffer (ctx, surface); - - if (! surface->msaa_active) { -#if CAIRO_HAS_GL_SURFACE - glDisable (GL_MULTISAMPLE); -#endif - - ctx->dispatch.BindFramebuffer (GL_FRAMEBUFFER, surface->fb); - return; - } - - _cairo_gl_composite_flush (ctx); - - stencil_test_enabled = glIsEnabled (GL_STENCIL_TEST); - scissor_test_enabled = glIsEnabled (GL_SCISSOR_TEST); - glDisable (GL_STENCIL_TEST); - glDisable (GL_SCISSOR_TEST); - -#if CAIRO_HAS_GL_SURFACE - glDisable (GL_MULTISAMPLE); -#endif - - /* The last time we drew to the surface, we were using multisampling, - so we need to blit from the multisampling framebuffer into the - non-multisampling framebuffer. */ - ctx->dispatch.BindFramebuffer (GL_DRAW_FRAMEBUFFER, surface->fb); - ctx->dispatch.BindFramebuffer (GL_READ_FRAMEBUFFER, surface->msaa_fb); - ctx->dispatch.BlitFramebuffer (0, 0, surface->width, surface->height, - 0, 0, surface->width, surface->height, - GL_COLOR_BUFFER_BIT, GL_NEAREST); - ctx->dispatch.BindFramebuffer (GL_FRAMEBUFFER, surface->fb); - - if (stencil_test_enabled) - glEnable (GL_STENCIL_TEST); - if (scissor_test_enabled) - glEnable (GL_SCISSOR_TEST); -} -#endif - -void -_cairo_gl_context_bind_framebuffer (cairo_gl_context_t *ctx, - cairo_gl_surface_t *surface, - cairo_bool_t multisampling) -{ - if (_cairo_gl_surface_is_texture (surface)) { - /* OpenGL ES surfaces only have either a multisample framebuffer or a - * singlesample framebuffer, so we cannot switch back and forth. */ - if (ctx->gl_flavor == CAIRO_GL_FLAVOR_ES2) { - _cairo_gl_ensure_framebuffer (ctx, surface); - ctx->dispatch.BindFramebuffer (GL_FRAMEBUFFER, surface->fb); - return; - } - -#if CAIRO_HAS_GL_SURFACE || CAIRO_HAS_GLESV3_SURFACE - if (multisampling) - bind_multisample_framebuffer (ctx, surface); - else - bind_singlesample_framebuffer (ctx, surface); -#endif - } else { - ctx->dispatch.BindFramebuffer (GL_FRAMEBUFFER, 0); - -#if CAIRO_HAS_GL_SURFACE - if (ctx->gl_flavor == CAIRO_GL_FLAVOR_DESKTOP) { - if (multisampling) - glEnable (GL_MULTISAMPLE); - else - glDisable (GL_MULTISAMPLE); - } -#endif - } - - if (ctx->gl_flavor == CAIRO_GL_FLAVOR_DESKTOP) - surface->msaa_active = multisampling; -} - -void -_cairo_gl_context_set_destination (cairo_gl_context_t *ctx, - cairo_gl_surface_t *surface, - cairo_bool_t multisampling) -{ - cairo_bool_t changing_surface, changing_sampling; - - /* The decision whether or not to use multisampling happens when - * we create an OpenGL ES surface, so we can never switch modes. */ - if (ctx->gl_flavor == CAIRO_GL_FLAVOR_ES2) - multisampling = surface->msaa_active; - /* For GLESV3, we always use renderbuffer for drawing */ - else if (ctx->gl_flavor == CAIRO_GL_FLAVOR_ES3) - multisampling = TRUE; - - changing_surface = ctx->current_target != surface || surface->needs_update; - changing_sampling = (surface->msaa_active != multisampling || - surface->content_in_texture); - if (! changing_surface && ! changing_sampling) - return; - - if (! changing_surface) { - _cairo_gl_composite_flush (ctx); - _cairo_gl_context_bind_framebuffer (ctx, surface, multisampling); - return; - } - - _cairo_gl_composite_flush (ctx); - - ctx->current_target = surface; - surface->needs_update = FALSE; - - if (! _cairo_gl_surface_is_texture (surface)) { - ctx->make_current (ctx, surface); - } - - _cairo_gl_context_bind_framebuffer (ctx, surface, multisampling); - - if (! _cairo_gl_surface_is_texture (surface)) { -#if CAIRO_HAS_GL_SURFACE - glDrawBuffer (GL_BACK_LEFT); - glReadBuffer (GL_BACK_LEFT); -#endif - } - - glDisable (GL_DITHER); - glViewport (0, 0, surface->width, surface->height); - - if (_cairo_gl_surface_is_texture (surface)) - _gl_identity_ortho (ctx->modelviewprojection_matrix, - 0, surface->width, 0, surface->height); - else - _gl_identity_ortho (ctx->modelviewprojection_matrix, - 0, surface->width, surface->height, 0); -} - -void -cairo_gl_device_set_thread_aware (cairo_device_t *device, - cairo_bool_t thread_aware) -{ - if (device->backend->type != CAIRO_DEVICE_TYPE_GL) { - _cairo_error_throw (CAIRO_STATUS_DEVICE_TYPE_MISMATCH); - return; - } - ((cairo_gl_context_t *) device)->thread_aware = thread_aware; -} diff --git a/gfx/cairo/cairo/src/cairo-gl-dispatch-private.h b/gfx/cairo/cairo/src/cairo-gl-dispatch-private.h deleted file mode 100644 index cabf76f0d6..0000000000 --- a/gfx/cairo/cairo/src/cairo-gl-dispatch-private.h +++ /dev/null @@ -1,129 +0,0 @@ -/* cairo - a vector graphics library with display and print output - * - * Copyright © 2010 Linaro Limited - * - * 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., 51 Franklin Street, Suite 500, Boston, MA 02110-1335, 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. - * - * Contributor(s): - * Alexandros Frantzis <alexandros.frantzis@linaro.org> - */ - -#ifndef CAIRO_GL_DISPATCH_PRIVATE_H -#define CAIRO_GL_DISPATCH_PRIVATE_H - -#include "cairo-gl-private.h" -#include <stddef.h> - -typedef enum _cairo_gl_dispatch_name { - CAIRO_GL_DISPATCH_NAME_CORE, - CAIRO_GL_DISPATCH_NAME_EXT, - CAIRO_GL_DISPATCH_NAME_ES, - CAIRO_GL_DISPATCH_NAME_COUNT -} cairo_gl_dispatch_name_t; - -typedef struct _cairo_gl_dispatch_entry { - const char *name[CAIRO_GL_DISPATCH_NAME_COUNT]; - size_t offset; -} cairo_gl_dispatch_entry_t; - -#define DISPATCH_ENTRY_ARB(name) { { "gl"#name, "gl"#name"ARB", "gl"#name }, \ - offsetof(cairo_gl_dispatch_t, name) } -#define DISPATCH_ENTRY_EXT(name) { { "gl"#name, "gl"#name"EXT", "gl"#name }, \ - offsetof(cairo_gl_dispatch_t, name) } -#define DISPATCH_ENTRY_ARB_OES(name) { { "gl"#name, "gl"#name"ARB", "gl"#name"OES" }, \ - offsetof(cairo_gl_dispatch_t, name) } -#define DISPATCH_ENTRY_EXT_IMG(name) { { "gl"#name, "gl"#name"EXT", "gl"#name"IMG" }, \ - offsetof(cairo_gl_dispatch_t, name) } -#define DISPATCH_ENTRY_CUSTOM(name, name2) { { "gl"#name, "gl"#name2, "gl"#name }, \ - offsetof(cairo_gl_dispatch_t, name)} -#define DISPATCH_ENTRY_LAST { { NULL, NULL, NULL }, 0 } - -cairo_private cairo_gl_dispatch_entry_t dispatch_buffers_entries[] = { - DISPATCH_ENTRY_ARB (GenBuffers), - DISPATCH_ENTRY_ARB (BindBuffer), - DISPATCH_ENTRY_ARB (BufferData), - DISPATCH_ENTRY_ARB_OES (MapBuffer), - DISPATCH_ENTRY_ARB_OES (UnmapBuffer), - DISPATCH_ENTRY_LAST -}; - -cairo_private cairo_gl_dispatch_entry_t dispatch_shaders_entries[] = { - /* Shaders */ - DISPATCH_ENTRY_CUSTOM (CreateShader, CreateShaderObjectARB), - DISPATCH_ENTRY_ARB (ShaderSource), - DISPATCH_ENTRY_ARB (CompileShader), - DISPATCH_ENTRY_CUSTOM (GetShaderiv, GetObjectParameterivARB), - DISPATCH_ENTRY_CUSTOM (GetShaderInfoLog, GetInfoLogARB), - DISPATCH_ENTRY_CUSTOM (DeleteShader, DeleteObjectARB), - - /* Programs */ - DISPATCH_ENTRY_CUSTOM (CreateProgram, CreateProgramObjectARB), - DISPATCH_ENTRY_CUSTOM (AttachShader, AttachObjectARB), - DISPATCH_ENTRY_CUSTOM (DeleteProgram, DeleteObjectARB), - DISPATCH_ENTRY_ARB (LinkProgram), - DISPATCH_ENTRY_CUSTOM (UseProgram, UseProgramObjectARB), - DISPATCH_ENTRY_CUSTOM (GetProgramiv, GetObjectParameterivARB), - DISPATCH_ENTRY_CUSTOM (GetProgramInfoLog, GetInfoLogARB), - - /* Uniforms */ - DISPATCH_ENTRY_ARB (GetUniformLocation), - DISPATCH_ENTRY_ARB (Uniform1f), - DISPATCH_ENTRY_ARB (Uniform2f), - DISPATCH_ENTRY_ARB (Uniform3f), - DISPATCH_ENTRY_ARB (Uniform4f), - DISPATCH_ENTRY_ARB (UniformMatrix3fv), - DISPATCH_ENTRY_ARB (UniformMatrix4fv), - DISPATCH_ENTRY_ARB (Uniform1i), - - /* Attributes */ - DISPATCH_ENTRY_ARB (BindAttribLocation), - DISPATCH_ENTRY_ARB (VertexAttribPointer), - DISPATCH_ENTRY_ARB (EnableVertexAttribArray), - DISPATCH_ENTRY_ARB (DisableVertexAttribArray), - - DISPATCH_ENTRY_LAST -}; - -cairo_private cairo_gl_dispatch_entry_t dispatch_fbo_entries[] = { - DISPATCH_ENTRY_EXT (GenFramebuffers), - DISPATCH_ENTRY_EXT (BindFramebuffer), - DISPATCH_ENTRY_EXT (FramebufferTexture2D), - DISPATCH_ENTRY_EXT (CheckFramebufferStatus), - DISPATCH_ENTRY_EXT (DeleteFramebuffers), - DISPATCH_ENTRY_EXT (GenRenderbuffers), - DISPATCH_ENTRY_EXT (BindRenderbuffer), - DISPATCH_ENTRY_EXT (RenderbufferStorage), - DISPATCH_ENTRY_EXT (FramebufferRenderbuffer), - DISPATCH_ENTRY_EXT (DeleteRenderbuffers), - DISPATCH_ENTRY_EXT (BlitFramebuffer), - DISPATCH_ENTRY_LAST -}; - -cairo_private cairo_gl_dispatch_entry_t dispatch_multisampling_entries[] = { - DISPATCH_ENTRY_EXT_IMG (RenderbufferStorageMultisample), - DISPATCH_ENTRY_EXT_IMG (FramebufferTexture2DMultisample), - DISPATCH_ENTRY_LAST -}; - -#endif /* CAIRO_GL_DISPATCH_PRIVATE_H */ diff --git a/gfx/cairo/cairo/src/cairo-gl-dispatch.c b/gfx/cairo/cairo/src/cairo-gl-dispatch.c deleted file mode 100644 index a49199dbb0..0000000000 --- a/gfx/cairo/cairo/src/cairo-gl-dispatch.c +++ /dev/null @@ -1,273 +0,0 @@ -/* cairo - a vector graphics library with display and print output - * - * Copyright © 2010 Linaro Limited - * - * 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., 51 Franklin Street, Suite 500, Boston, MA 02110-1335, 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. - * - * Contributor(s): - * Alexandros Frantzis <alexandros.frantzis@linaro.org> - */ - -#include "cairoint.h" -#include "cairo-gl-private.h" -#include "cairo-gl-dispatch-private.h" -#if CAIRO_HAS_DLSYM -#include <dlfcn.h> -#endif - -#if CAIRO_HAS_DLSYM -static void * -_cairo_gl_dispatch_open_lib (void) -{ - return dlopen (NULL, RTLD_LAZY); -} - -static void -_cairo_gl_dispatch_close_lib (void *handle) -{ - dlclose (handle); -} - -static cairo_gl_generic_func_t -_cairo_gl_dispatch_get_proc_addr (void *handle, const char *name) -{ - return (cairo_gl_generic_func_t) dlsym (handle, name); -} -#else -static void * -_cairo_gl_dispatch_open_lib (void) -{ - return NULL; -} - -static void -_cairo_gl_dispatch_close_lib (void *handle) -{ - return; -} - -static cairo_gl_generic_func_t -_cairo_gl_dispatch_get_proc_addr (void *handle, const char *name) -{ - return NULL; -} -#endif /* CAIRO_HAS_DLSYM */ - - -static void -_cairo_gl_dispatch_init_entries (cairo_gl_dispatch_t *dispatch, - cairo_gl_get_proc_addr_func_t get_proc_addr, - cairo_gl_dispatch_entry_t *entries, - cairo_gl_dispatch_name_t dispatch_name) -{ - cairo_gl_dispatch_entry_t *entry = entries; - void *handle = _cairo_gl_dispatch_open_lib (); - - while (entry->name[CAIRO_GL_DISPATCH_NAME_CORE] != NULL) { - void *dispatch_ptr = &((char *) dispatch)[entry->offset]; - const char *name = entry->name[dispatch_name]; - - /* - * In strictly conforming EGL implementations, eglGetProcAddress() can - * be used only to get extension functions, but some of the functions - * we want belong to core GL(ES). If the *GetProcAddress function - * provided by the context fails, try to get the address of the wanted - * GL function using standard system facilities (eg dlsym() in *nix - * systems). - */ - cairo_gl_generic_func_t func = get_proc_addr (name); - if (func == NULL) - func = _cairo_gl_dispatch_get_proc_addr (handle, name); - - *((cairo_gl_generic_func_t *) dispatch_ptr) = func; - - ++entry; - } - - _cairo_gl_dispatch_close_lib (handle); -} - -static cairo_status_t -_cairo_gl_dispatch_init_buffers (cairo_gl_dispatch_t *dispatch, - cairo_gl_get_proc_addr_func_t get_proc_addr, - int gl_version, cairo_gl_flavor_t gl_flavor) -{ - cairo_gl_dispatch_name_t dispatch_name; - - if (gl_flavor == CAIRO_GL_FLAVOR_DESKTOP) - { - if (gl_version >= CAIRO_GL_VERSION_ENCODE (1, 5)) - dispatch_name = CAIRO_GL_DISPATCH_NAME_CORE; - else if (_cairo_gl_has_extension ("GL_ARB_vertex_buffer_object")) - dispatch_name = CAIRO_GL_DISPATCH_NAME_EXT; - else - return CAIRO_STATUS_DEVICE_ERROR; - } - else if (gl_flavor == CAIRO_GL_FLAVOR_ES3) - { - dispatch_name = CAIRO_GL_DISPATCH_NAME_CORE; - } - else if (gl_flavor == CAIRO_GL_FLAVOR_ES2 && - gl_version >= CAIRO_GL_VERSION_ENCODE (2, 0)) - { - dispatch_name = CAIRO_GL_DISPATCH_NAME_ES; - } - else - { - return CAIRO_STATUS_DEVICE_ERROR; - } - - _cairo_gl_dispatch_init_entries (dispatch, get_proc_addr, - dispatch_buffers_entries, dispatch_name); - - return CAIRO_STATUS_SUCCESS; -} - -static cairo_status_t -_cairo_gl_dispatch_init_shaders (cairo_gl_dispatch_t *dispatch, - cairo_gl_get_proc_addr_func_t get_proc_addr, - int gl_version, cairo_gl_flavor_t gl_flavor) -{ - cairo_gl_dispatch_name_t dispatch_name; - - if (gl_flavor == CAIRO_GL_FLAVOR_DESKTOP) - { - if (gl_version >= CAIRO_GL_VERSION_ENCODE (2, 0)) - dispatch_name = CAIRO_GL_DISPATCH_NAME_CORE; - else if (_cairo_gl_has_extension ("GL_ARB_shader_objects")) - dispatch_name = CAIRO_GL_DISPATCH_NAME_EXT; - else - return CAIRO_STATUS_DEVICE_ERROR; - } - else if (gl_flavor == CAIRO_GL_FLAVOR_ES3) - { - dispatch_name = CAIRO_GL_DISPATCH_NAME_CORE; - } - else if (gl_flavor == CAIRO_GL_FLAVOR_ES2 && - gl_version >= CAIRO_GL_VERSION_ENCODE (2, 0)) - { - dispatch_name = CAIRO_GL_DISPATCH_NAME_ES; - } - else - { - return CAIRO_STATUS_DEVICE_ERROR; - } - - _cairo_gl_dispatch_init_entries (dispatch, get_proc_addr, - dispatch_shaders_entries, dispatch_name); - - return CAIRO_STATUS_SUCCESS; -} - -static cairo_status_t -_cairo_gl_dispatch_init_fbo (cairo_gl_dispatch_t *dispatch, - cairo_gl_get_proc_addr_func_t get_proc_addr, - int gl_version, cairo_gl_flavor_t gl_flavor) -{ - cairo_gl_dispatch_name_t dispatch_name; - - if (gl_flavor == CAIRO_GL_FLAVOR_DESKTOP) - { - if (gl_version >= CAIRO_GL_VERSION_ENCODE (3, 0) || - _cairo_gl_has_extension ("GL_ARB_framebuffer_object")) - dispatch_name = CAIRO_GL_DISPATCH_NAME_CORE; - else if (_cairo_gl_has_extension ("GL_EXT_framebuffer_object")) - dispatch_name = CAIRO_GL_DISPATCH_NAME_EXT; - else - return CAIRO_STATUS_DEVICE_ERROR; - } - else if (gl_flavor == CAIRO_GL_FLAVOR_ES3) - { - dispatch_name = CAIRO_GL_DISPATCH_NAME_CORE; - } - else if (gl_flavor == CAIRO_GL_FLAVOR_ES2 && - gl_version >= CAIRO_GL_VERSION_ENCODE (2, 0)) - { - dispatch_name = CAIRO_GL_DISPATCH_NAME_ES; - } - else - { - return CAIRO_STATUS_DEVICE_ERROR; - } - - _cairo_gl_dispatch_init_entries (dispatch, get_proc_addr, - dispatch_fbo_entries, dispatch_name); - - return CAIRO_STATUS_SUCCESS; -} - -static cairo_status_t -_cairo_gl_dispatch_init_multisampling (cairo_gl_dispatch_t *dispatch, - cairo_gl_get_proc_addr_func_t get_proc_addr, - int gl_version, - cairo_gl_flavor_t gl_flavor) -{ - /* For the multisampling table, there are two GLES versions of the - * extension, so we put one in the EXT slot and one in the real ES slot.*/ - cairo_gl_dispatch_name_t dispatch_name = CAIRO_GL_DISPATCH_NAME_CORE; - if (gl_flavor == CAIRO_GL_FLAVOR_ES2) { - if (_cairo_gl_has_extension ("GL_EXT_multisampled_render_to_texture")) - dispatch_name = CAIRO_GL_DISPATCH_NAME_EXT; - else if (_cairo_gl_has_extension ("GL_IMG_multisampled_render_to_texture")) - dispatch_name = CAIRO_GL_DISPATCH_NAME_ES; - } - _cairo_gl_dispatch_init_entries (dispatch, get_proc_addr, - dispatch_multisampling_entries, - dispatch_name); - return CAIRO_STATUS_SUCCESS; -} - -cairo_status_t -_cairo_gl_dispatch_init (cairo_gl_dispatch_t *dispatch, - cairo_gl_get_proc_addr_func_t get_proc_addr) -{ - cairo_status_t status; - int gl_version; - cairo_gl_flavor_t gl_flavor; - - gl_version = _cairo_gl_get_version (); - gl_flavor = _cairo_gl_get_flavor (); - - status = _cairo_gl_dispatch_init_buffers (dispatch, get_proc_addr, - gl_version, gl_flavor); - if (status != CAIRO_STATUS_SUCCESS) - return status; - - status = _cairo_gl_dispatch_init_shaders (dispatch, get_proc_addr, - gl_version, gl_flavor); - if (status != CAIRO_STATUS_SUCCESS) - return status; - - status = _cairo_gl_dispatch_init_fbo (dispatch, get_proc_addr, - gl_version, gl_flavor); - if (status != CAIRO_STATUS_SUCCESS) - return status; - - status = _cairo_gl_dispatch_init_multisampling (dispatch, get_proc_addr, - gl_version, gl_flavor); - if (status != CAIRO_STATUS_SUCCESS) - return status; - - return CAIRO_STATUS_SUCCESS; -} diff --git a/gfx/cairo/cairo/src/cairo-gl-ext-def-private.h b/gfx/cairo/cairo/src/cairo-gl-ext-def-private.h deleted file mode 100644 index a261947bef..0000000000 --- a/gfx/cairo/cairo/src/cairo-gl-ext-def-private.h +++ /dev/null @@ -1,143 +0,0 @@ -/* cairo - a vector graphics library with display and print output - * - * Copyright © 2010 Linaro Limited - * - * 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., 51 Franklin Street, Suite 500, Boston, MA 02110-1335, 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. - * - * Contributor(s): - * Alexandros Frantzis <alexandros.frantzis@linaro.org> - */ - -#ifndef CAIRO_GL_EXT_DEF_PRIVATE_H -#define CAIRO_GL_EXT_DEF_PRIVATE_H - -#ifndef GL_TEXTURE_RECTANGLE -#define GL_TEXTURE_RECTANGLE 0x84F5 -#endif - -#ifndef GL_ARRAY_BUFFER -#define GL_ARRAY_BUFFER 0x8892 -#endif - -#ifndef GL_STREAM_DRAW -#define GL_STREAM_DRAW 0x88E0 -#endif - -#ifndef GL_WRITE_ONLY -#define GL_WRITE_ONLY 0x88B9 -#endif - -#ifndef GL_PIXEL_UNPACK_BUFFER -#define GL_PIXEL_UNPACK_BUFFER 0x88EC -#endif - -#ifndef GL_FRAMEBUFFER -#define GL_FRAMEBUFFER 0x8D40 -#endif - -#ifndef GL_COLOR_ATTACHMENT0 -#define GL_COLOR_ATTACHMENT0 0x8CE0 -#endif - -#ifndef GL_FRAMEBUFFER_COMPLETE -#define GL_FRAMEBUFFER_COMPLETE 0x8CD5 -#endif - -#ifndef GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT -#define GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT 0x8CD6 -#endif - -#ifndef GL_FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT -#define GL_FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT 0x8CD7 -#endif - -#ifndef GL_FRAMEBUFFER_INCOMPLETE_DIMENSIONS -#define GL_FRAMEBUFFER_INCOMPLETE_DIMENSIONS 0x8CD9 -#endif - -#ifndef GL_FRAMEBUFFER_INCOMPLETE_FORMATS -#define GL_FRAMEBUFFER_INCOMPLETE_FORMATS 0x8CDA -#endif - -#ifndef GL_FRAMEBUFFER_INCOMPLETE_DRAW_BUFFER -#define GL_FRAMEBUFFER_INCOMPLETE_DRAW_BUFFER 0x8CDB -#endif - -#ifndef GL_FRAMEBUFFER_INCOMPLETE_READ_BUFFER -#define GL_FRAMEBUFFER_INCOMPLETE_READ_BUFFER 0x8CDC -#endif - -#ifndef GL_FRAMEBUFFER_UNSUPPORTED -#define GL_FRAMEBUFFER_UNSUPPORTED 0x8CDD -#endif - -#ifndef GL_PACK_INVERT_MESA -#define GL_PACK_INVERT_MESA 0x8758 -#endif - -#ifndef GL_CLAMP_TO_BORDER -#define GL_CLAMP_TO_BORDER 0x812D -#endif - -#ifndef GL_BGR -#define GL_BGR 0x80E0 -#endif - -#ifndef GL_BGRA -#define GL_BGRA 0x80E1 -#endif - -#ifndef GL_RGBA8 -#define GL_RGBA8 0x8058 -#endif - -#ifndef GL_UNSIGNED_INT_8_8_8_8 -#define GL_UNSIGNED_INT_8_8_8_8 0x8035 -#endif - -#ifndef GL_UNSIGNED_SHORT_5_6_5_REV -#define GL_UNSIGNED_SHORT_5_6_5_REV 0x8364 -#endif - -#ifndef GL_UNSIGNED_SHORT_1_5_5_5_REV -#define GL_UNSIGNED_SHORT_1_5_5_5_REV 0x8366 -#endif - -#ifndef GL_UNSIGNED_INT_8_8_8_8_REV -#define GL_UNSIGNED_INT_8_8_8_8_REV 0x8367 -#endif - -#ifndef GL_PACK_ROW_LENGTH -#define GL_PACK_ROW_LENGTH 0x0D02 -#endif - -#ifndef GL_UNPACK_ROW_LENGTH -#define GL_UNPACK_ROW_LENGTH 0x0CF2 -#endif - -#ifndef GL_FRAMEBUFFER_INCOMPLETE_MULTISAMPLE -#define GL_FRAMEBUFFER_INCOMPLETE_MULTISAMPLE 0x8D56 -#endif - -#endif /* CAIRO_GL_EXT_DEF_PRIVATE_H */ diff --git a/gfx/cairo/cairo/src/cairo-gl-glyphs.c b/gfx/cairo/cairo/src/cairo-gl-glyphs.c deleted file mode 100644 index 5923af4414..0000000000 --- a/gfx/cairo/cairo/src/cairo-gl-glyphs.c +++ /dev/null @@ -1,503 +0,0 @@ -/* Cairo - a vector graphics library with display and print output - * - * Copyright © 2009 Chris Wilson - * Copyright © 2010 Intel Corporation - * Copyright © 2010 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., 51 Franklin Street, Suite 500, Boston, MA 02110-1335, 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 Chris Wilson. - * - * Contributors: - * Benjamin Otte <otte@gnome.org> - * Chris Wilson <chris@chris-wilson.co.uk> - */ - -#include "cairoint.h" - -#include "cairo-gl-private.h" - -#include "cairo-compositor-private.h" -#include "cairo-composite-rectangles-private.h" -#include "cairo-error-private.h" -#include "cairo-image-surface-private.h" -#include "cairo-rtree-private.h" - -#define GLYPH_CACHE_WIDTH 1024 -#define GLYPH_CACHE_HEIGHT 1024 -#define GLYPH_CACHE_MIN_SIZE 4 -#define GLYPH_CACHE_MAX_SIZE 128 - -typedef struct _cairo_gl_glyph { - cairo_rtree_node_t node; - cairo_scaled_glyph_private_t base; - cairo_scaled_glyph_t *glyph; - cairo_gl_glyph_cache_t *cache; - struct { float x, y; } p1, p2; -} cairo_gl_glyph_t; - -static void -_cairo_gl_node_destroy (cairo_rtree_node_t *node) -{ - cairo_gl_glyph_t *priv = cairo_container_of (node, cairo_gl_glyph_t, node); - cairo_scaled_glyph_t *glyph; - - glyph = priv->glyph; - if (glyph == NULL) - return; - - if (glyph->dev_private_key == priv->cache) { - glyph->dev_private = NULL; - glyph->dev_private_key = NULL; - } - cairo_list_del (&priv->base.link); - priv->glyph = NULL; -} - -static void -_cairo_gl_glyph_fini (cairo_scaled_glyph_private_t *glyph_private, - cairo_scaled_glyph_t *scaled_glyph, - cairo_scaled_font_t *scaled_font) -{ - cairo_gl_glyph_t *priv = cairo_container_of (glyph_private, - cairo_gl_glyph_t, - base); - - assert (priv->glyph); - - _cairo_gl_node_destroy (&priv->node); - - /* XXX thread-safety? Probably ok due to the frozen scaled-font. */ - if (! priv->node.pinned) - _cairo_rtree_node_remove (&priv->cache->rtree, &priv->node); - - assert (priv->glyph == NULL); -} - -static cairo_int_status_t -_cairo_gl_glyph_cache_add_glyph (cairo_gl_context_t *ctx, - cairo_gl_glyph_cache_t *cache, - cairo_scaled_glyph_t *scaled_glyph) -{ - cairo_image_surface_t *glyph_surface = scaled_glyph->surface; - cairo_gl_glyph_t *glyph_private; - cairo_rtree_node_t *node = NULL; - cairo_int_status_t status; - int width, height; - - width = glyph_surface->width; - if (width < GLYPH_CACHE_MIN_SIZE) - width = GLYPH_CACHE_MIN_SIZE; - height = glyph_surface->height; - if (height < GLYPH_CACHE_MIN_SIZE) - height = GLYPH_CACHE_MIN_SIZE; - - /* search for an available slot */ - status = _cairo_rtree_insert (&cache->rtree, width, height, &node); - /* search for an unlocked slot */ - if (status == CAIRO_INT_STATUS_UNSUPPORTED) { - status = _cairo_rtree_evict_random (&cache->rtree, - width, height, &node); - if (status == CAIRO_INT_STATUS_SUCCESS) { - status = _cairo_rtree_node_insert (&cache->rtree, - node, width, height, &node); - } - } - if (status) - return status; - - /* XXX: Make sure we use the mask texture. This should work automagically somehow */ - glActiveTexture (GL_TEXTURE1); - status = _cairo_gl_surface_draw_image (cache->surface, glyph_surface, - 0, 0, - glyph_surface->width, glyph_surface->height, - node->x, node->y, FALSE); - if (unlikely (status)) - return status; - - glyph_private = (cairo_gl_glyph_t *) node; - glyph_private->cache = cache; - glyph_private->glyph = scaled_glyph; - _cairo_scaled_glyph_attach_private (scaled_glyph, - &glyph_private->base, - cache, - _cairo_gl_glyph_fini); - - scaled_glyph->dev_private = glyph_private; - scaled_glyph->dev_private_key = cache; - - /* compute tex coords */ - glyph_private->p1.x = node->x; - glyph_private->p1.y = node->y; - glyph_private->p2.x = node->x + glyph_surface->width; - glyph_private->p2.y = node->y + glyph_surface->height; - if (! _cairo_gl_device_requires_power_of_two_textures (&ctx->base)) { - glyph_private->p1.x /= GLYPH_CACHE_WIDTH; - glyph_private->p2.x /= GLYPH_CACHE_WIDTH; - glyph_private->p1.y /= GLYPH_CACHE_HEIGHT; - glyph_private->p2.y /= GLYPH_CACHE_HEIGHT; - } - - return CAIRO_STATUS_SUCCESS; -} - -static cairo_gl_glyph_t * -_cairo_gl_glyph_cache_lock (cairo_gl_glyph_cache_t *cache, - cairo_scaled_glyph_t *scaled_glyph) -{ - return _cairo_rtree_pin (&cache->rtree, scaled_glyph->dev_private); -} - -static cairo_status_t -cairo_gl_context_get_glyph_cache (cairo_gl_context_t *ctx, - cairo_format_t format, - cairo_gl_glyph_cache_t **cache_out) -{ - cairo_gl_glyph_cache_t *cache; - cairo_content_t content; - - switch (format) { - case CAIRO_FORMAT_RGB30: - case CAIRO_FORMAT_RGB16_565: - case CAIRO_FORMAT_ARGB32: - case CAIRO_FORMAT_RGB24: - cache = &ctx->glyph_cache[0]; - content = CAIRO_CONTENT_COLOR_ALPHA; - break; - case CAIRO_FORMAT_A8: - case CAIRO_FORMAT_A1: - cache = &ctx->glyph_cache[1]; - content = CAIRO_CONTENT_ALPHA; - break; - default: - case CAIRO_FORMAT_INVALID: - ASSERT_NOT_REACHED; - return _cairo_error (CAIRO_STATUS_INVALID_FORMAT); - } - - if (unlikely (cache->surface == NULL)) { - cairo_surface_t *surface; - - surface = _cairo_gl_surface_create_scratch_for_caching (ctx, - content, - GLYPH_CACHE_WIDTH, - GLYPH_CACHE_HEIGHT); - if (unlikely (surface->status)) - return surface->status; - - _cairo_surface_release_device_reference (surface); - - cache->surface = (cairo_gl_surface_t *)surface; - cache->surface->operand.texture.attributes.has_component_alpha = - content == CAIRO_CONTENT_COLOR_ALPHA; - } - - *cache_out = cache; - return CAIRO_STATUS_SUCCESS; -} - -static cairo_status_t -render_glyphs (cairo_gl_surface_t *dst, - int dst_x, int dst_y, - cairo_operator_t op, - cairo_surface_t *source, - cairo_composite_glyphs_info_t *info, - cairo_bool_t *has_component_alpha, - cairo_clip_t *clip) -{ - cairo_format_t last_format = CAIRO_FORMAT_INVALID; - cairo_gl_glyph_cache_t *cache = NULL; - cairo_gl_context_t *ctx; - cairo_gl_emit_glyph_t emit = NULL; - cairo_gl_composite_t setup; - cairo_int_status_t status; - int i = 0; - - TRACE ((stderr, "%s (%d, %d)x(%d, %d)\n", __FUNCTION__, - info->extents.x, info->extents.y, - info->extents.width, info->extents.height)); - - *has_component_alpha = FALSE; - - status = _cairo_gl_context_acquire (dst->base.device, &ctx); - if (unlikely (status)) - return status; - - status = _cairo_gl_composite_init (&setup, op, dst, TRUE); - if (unlikely (status)) - goto FINISH; - - if (source == NULL) { - _cairo_gl_composite_set_solid_source (&setup, CAIRO_COLOR_WHITE); - } else { - _cairo_gl_composite_set_source_operand (&setup, - source_to_operand (source)); - - } - - _cairo_gl_composite_set_clip (&setup, clip); - - for (i = 0; i < info->num_glyphs; i++) { - cairo_scaled_glyph_t *scaled_glyph; - cairo_gl_glyph_t *glyph; - double x_offset, y_offset; - double x1, x2, y1, y2; - - status = _cairo_scaled_glyph_lookup (info->font, - info->glyphs[i].index, - CAIRO_SCALED_GLYPH_INFO_SURFACE, - &scaled_glyph); - if (unlikely (status)) - goto FINISH; - - if (scaled_glyph->surface->width == 0 || - scaled_glyph->surface->height == 0) - { - continue; - } - if (scaled_glyph->surface->format != last_format) { - status = cairo_gl_context_get_glyph_cache (ctx, - scaled_glyph->surface->format, - &cache); - if (unlikely (status)) - goto FINISH; - - last_format = scaled_glyph->surface->format; - - _cairo_gl_composite_set_mask_operand (&setup, &cache->surface->operand); - *has_component_alpha |= cache->surface->operand.texture.attributes.has_component_alpha; - - /* XXX Shoot me. */ - status = _cairo_gl_composite_begin (&setup, &ctx); - status = _cairo_gl_context_release (ctx, status); - if (unlikely (status)) - goto FINISH; - - emit = _cairo_gl_context_choose_emit_glyph (ctx); - } - - if (scaled_glyph->dev_private_key != cache) { - cairo_scaled_glyph_private_t *priv; - - priv = _cairo_scaled_glyph_find_private (scaled_glyph, cache); - if (priv) { - scaled_glyph->dev_private_key = cache; - scaled_glyph->dev_private = cairo_container_of (priv, - cairo_gl_glyph_t, - base); - } else { - status = _cairo_gl_glyph_cache_add_glyph (ctx, cache, scaled_glyph); - - if (status == CAIRO_INT_STATUS_UNSUPPORTED) { - /* Cache is full, so flush existing prims and try again. */ - _cairo_gl_composite_flush (ctx); - _cairo_gl_glyph_cache_unlock (cache); - status = _cairo_gl_glyph_cache_add_glyph (ctx, cache, scaled_glyph); - } - - if (unlikely (_cairo_int_status_is_error (status))) - goto FINISH; - } - } - - x_offset = scaled_glyph->surface->base.device_transform.x0; - y_offset = scaled_glyph->surface->base.device_transform.y0; - - x1 = _cairo_lround (info->glyphs[i].x - x_offset - dst_x); - y1 = _cairo_lround (info->glyphs[i].y - y_offset - dst_y); - x2 = x1 + scaled_glyph->surface->width; - y2 = y1 + scaled_glyph->surface->height; - - glyph = _cairo_gl_glyph_cache_lock (cache, scaled_glyph); - assert (emit); - emit (ctx, - x1, y1, x2, y2, - glyph->p1.x, glyph->p1.y, - glyph->p2.x, glyph->p2.y); - } - - status = CAIRO_STATUS_SUCCESS; - FINISH: - status = _cairo_gl_context_release (ctx, status); - - _cairo_gl_composite_fini (&setup); - return status; -} - -static cairo_int_status_t -render_glyphs_via_mask (cairo_gl_surface_t *dst, - int dst_x, int dst_y, - cairo_operator_t op, - cairo_surface_t *source, - cairo_composite_glyphs_info_t *info, - cairo_clip_t *clip) -{ - cairo_surface_t *mask; - cairo_status_t status; - cairo_bool_t has_component_alpha; - - TRACE ((stderr, "%s\n", __FUNCTION__)); - - /* XXX: For non-CA, this should be CAIRO_CONTENT_ALPHA to save memory */ - mask = cairo_gl_surface_create (dst->base.device, - CAIRO_CONTENT_COLOR_ALPHA, - info->extents.width, - info->extents.height); - if (unlikely (mask->status)) - return mask->status; - - status = render_glyphs ((cairo_gl_surface_t *) mask, - info->extents.x, info->extents.y, - CAIRO_OPERATOR_ADD, NULL, - info, &has_component_alpha, NULL); - if (likely (status == CAIRO_STATUS_SUCCESS)) { - cairo_surface_pattern_t mask_pattern; - cairo_surface_pattern_t source_pattern; - cairo_rectangle_int_t clip_extents; - - mask->is_clear = FALSE; - _cairo_pattern_init_for_surface (&mask_pattern, mask); - mask_pattern.base.has_component_alpha = has_component_alpha; - mask_pattern.base.filter = CAIRO_FILTER_NEAREST; - mask_pattern.base.extend = CAIRO_EXTEND_NONE; - - cairo_matrix_init_translate (&mask_pattern.base.matrix, - dst_x-info->extents.x, dst_y-info->extents.y); - - _cairo_pattern_init_for_surface (&source_pattern, source); - cairo_matrix_init_translate (&source_pattern.base.matrix, - dst_x-info->extents.x, dst_y-info->extents.y); - - clip = _cairo_clip_copy (clip); - clip_extents.x = info->extents.x - dst_x; - clip_extents.y = info->extents.y - dst_y; - clip_extents.width = info->extents.width; - clip_extents.height = info->extents.height; - clip = _cairo_clip_intersect_rectangle (clip, &clip_extents); - - status = _cairo_surface_mask (&dst->base, op, - &source_pattern.base, - &mask_pattern.base, - clip); - - _cairo_clip_destroy (clip); - - _cairo_pattern_fini (&mask_pattern.base); - _cairo_pattern_fini (&source_pattern.base); - } - - cairo_surface_destroy (mask); - - return status; -} - -cairo_int_status_t -_cairo_gl_check_composite_glyphs (const cairo_composite_rectangles_t *extents, - cairo_scaled_font_t *scaled_font, - cairo_glyph_t *glyphs, - int *num_glyphs) -{ - if (! _cairo_gl_operator_is_supported (extents->op)) - return UNSUPPORTED ("unsupported operator"); - - /* XXX use individual masks for large glyphs? */ - if (ceil (scaled_font->max_scale) >= GLYPH_CACHE_MAX_SIZE) - return UNSUPPORTED ("glyphs too large"); - - return CAIRO_STATUS_SUCCESS; -} - -cairo_int_status_t -_cairo_gl_composite_glyphs_with_clip (void *_dst, - cairo_operator_t op, - cairo_surface_t *_src, - int src_x, - int src_y, - int dst_x, - int dst_y, - cairo_composite_glyphs_info_t *info, - cairo_clip_t *clip) -{ - cairo_gl_surface_t *dst = _dst; - cairo_bool_t has_component_alpha; - - TRACE ((stderr, "%s\n", __FUNCTION__)); - - /* If any of the glyphs require component alpha, we have to go through - * a mask, since only _cairo_gl_surface_composite() currently supports - * component alpha. - */ - if (!dst->base.is_clear && ! info->use_mask && op != CAIRO_OPERATOR_OVER && - (info->font->options.antialias == CAIRO_ANTIALIAS_SUBPIXEL || - info->font->options.antialias == CAIRO_ANTIALIAS_BEST)) - { - info->use_mask = TRUE; - } - - if (info->use_mask) { - return render_glyphs_via_mask (dst, dst_x, dst_y, - op, _src, info, clip); - } else { - return render_glyphs (dst, dst_x, dst_y, - op, _src, info, - &has_component_alpha, - clip); - } - -} - -cairo_int_status_t -_cairo_gl_composite_glyphs (void *_dst, - cairo_operator_t op, - cairo_surface_t *_src, - int src_x, - int src_y, - int dst_x, - int dst_y, - cairo_composite_glyphs_info_t *info) -{ - return _cairo_gl_composite_glyphs_with_clip (_dst, op, _src, src_x, src_y, - dst_x, dst_y, info, NULL); -} - -void -_cairo_gl_glyph_cache_init (cairo_gl_glyph_cache_t *cache) -{ - _cairo_rtree_init (&cache->rtree, - GLYPH_CACHE_WIDTH, - GLYPH_CACHE_HEIGHT, - GLYPH_CACHE_MIN_SIZE, - sizeof (cairo_gl_glyph_t), - _cairo_gl_node_destroy); -} - -void -_cairo_gl_glyph_cache_fini (cairo_gl_context_t *ctx, - cairo_gl_glyph_cache_t *cache) -{ - _cairo_rtree_fini (&cache->rtree); - cairo_surface_destroy (&cache->surface->base); -} diff --git a/gfx/cairo/cairo/src/cairo-gl-gradient-private.h b/gfx/cairo/cairo/src/cairo-gl-gradient-private.h deleted file mode 100644 index 0d9f41f54b..0000000000 --- a/gfx/cairo/cairo/src/cairo-gl-gradient-private.h +++ /dev/null @@ -1,96 +0,0 @@ -/* cairo - a vector graphics library with display and print output - * - * Copyright © 2009 Eric Anholt - * Copyright © 2009 Chris Wilson - * Copyright © 2005,2010 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., 51 Franklin Street, Suite 500, Boston, MA 02110-1335, 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): - * Benjamin Otte <otte@gnome.org> - * Carl Worth <cworth@cworth.org> - * Chris Wilson <chris@chris-wilson.co.uk> - * Eric Anholt <eric@anholt.net> - */ - -#ifndef CAIRO_GL_GRADIENT_PRIVATE_H -#define CAIRO_GL_GRADIENT_PRIVATE_H - -#define GL_GLEXT_PROTOTYPES - -#include "cairo-cache-private.h" -#include "cairo-device-private.h" -#include "cairo-reference-count-private.h" -#include "cairo-pattern-private.h" -#include "cairo-types-private.h" - -#include "cairo-gl.h" - -#if CAIRO_HAS_GLESV3_SURFACE -#include <GLES3/gl3.h> -#include <GLES3/gl3ext.h> -#elif CAIRO_HAS_GLESV2_SURFACE -#include <GLES2/gl2.h> -#include <GLES2/gl2ext.h> -#elif CAIRO_HAS_GL_SURFACE -#include <GL/gl.h> -#include <GL/glext.h> -#endif - -#define CAIRO_GL_GRADIENT_CACHE_SIZE 4096 - -/* XXX: Declare in a better place */ -typedef struct _cairo_gl_context cairo_gl_context_t; - -typedef struct _cairo_gl_gradient { - cairo_cache_entry_t cache_entry; - cairo_reference_count_t ref_count; - cairo_device_t *device; /* NB: we don't hold a reference */ - GLuint tex; - unsigned int n_stops; - const cairo_gradient_stop_t *stops; - cairo_gradient_stop_t stops_embedded[1]; -} cairo_gl_gradient_t; - -cairo_private cairo_int_status_t -_cairo_gl_gradient_create (cairo_gl_context_t *ctx, - unsigned int n_stops, - const cairo_gradient_stop_t *stops, - cairo_gl_gradient_t **gradient_out); - -cairo_private_no_warn cairo_gl_gradient_t * -_cairo_gl_gradient_reference (cairo_gl_gradient_t *gradient); - -cairo_private void -_cairo_gl_gradient_destroy (cairo_gl_gradient_t *gradient); - -cairo_private cairo_bool_t -_cairo_gl_gradient_equal (const void *key_a, const void *key_b); - - -#endif /* CAIRO_GL_GRADIENT_PRIVATE_H */ diff --git a/gfx/cairo/cairo/src/cairo-gl-gradient.c b/gfx/cairo/cairo/src/cairo-gl-gradient.c deleted file mode 100644 index 1bbd8dd0e6..0000000000 --- a/gfx/cairo/cairo/src/cairo-gl-gradient.c +++ /dev/null @@ -1,339 +0,0 @@ -/* cairo - a vector graphics library with display and print output - * - * Copyright © 2009 Eric Anholt - * Copyright © 2009 Chris Wilson - * Copyright © 2005,2010 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., 51 Franklin Street, Suite 500, Boston, MA 02110-1335, 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): - * Benjamin Otte <otte@gnome.org> - * Carl Worth <cworth@cworth.org> - * Chris Wilson <chris@chris-wilson.co.uk> - * Eric Anholt <eric@anholt.net> - */ - -#include "cairoint.h" -#include <stdint.h> -#include "cairo-error-private.h" -#include "cairo-gl-gradient-private.h" -#include "cairo-gl-private.h" - - -static int -_cairo_gl_gradient_sample_width (unsigned int n_stops, - const cairo_gradient_stop_t *stops) -{ - unsigned int n; - int width; - - width = 8; - for (n = 1; n < n_stops; n++) { - double dx = stops[n].offset - stops[n-1].offset; - double delta, max; - int ramp; - - if (dx == 0) - return 1024; /* we need to emulate an infinitely sharp step */ - - max = fabs (stops[n].color.red - stops[n-1].color.red); - - delta = fabs (stops[n].color.green - stops[n-1].color.green); - if (delta > max) - max = delta; - - delta = fabs (stops[n].color.blue - stops[n-1].color.blue); - if (delta > max) - max = delta; - - delta = fabs (stops[n].color.alpha - stops[n-1].color.alpha); - if (delta > max) - max = delta; - - ramp = 128 * max / dx; - if (ramp > width) - width = ramp; - } - - return (width + 7) & -8; -} - -static uint8_t premultiply(double c, double a) -{ - int v = c * a * 256; - return v - (v >> 8); -} - -static uint32_t color_stop_to_pixel(const cairo_gradient_stop_t *stop) -{ - uint8_t a, r, g, b; - - a = stop->color.alpha_short >> 8; - r = premultiply(stop->color.red, stop->color.alpha); - g = premultiply(stop->color.green, stop->color.alpha); - b = premultiply(stop->color.blue, stop->color.alpha); - - if (_cairo_is_little_endian ()) - return (uint32_t)a << 24 | r << 16 | g << 8 | b << 0; - else - return a << 0 | r << 8 | g << 16 | (uint32_t)b << 24; -} - -static cairo_status_t -_cairo_gl_gradient_render (const cairo_gl_context_t *ctx, - unsigned int n_stops, - const cairo_gradient_stop_t *stops, - void *bytes, - int width) -{ - pixman_image_t *gradient, *image; - pixman_gradient_stop_t pixman_stops_stack[32]; - pixman_gradient_stop_t *pixman_stops; - pixman_point_fixed_t p1, p2; - unsigned int i; - pixman_format_code_t gradient_pixman_format; - - /* - * Ensure that the order of the gradient's components in memory is BGRA. - * This is done so that the gradient's pixel data is always suitable for - * texture upload using format=GL_BGRA and type=GL_UNSIGNED_BYTE. - */ - if (_cairo_is_little_endian ()) - gradient_pixman_format = PIXMAN_a8r8g8b8; - else - gradient_pixman_format = PIXMAN_b8g8r8a8; - - pixman_stops = pixman_stops_stack; - if (unlikely (n_stops > ARRAY_LENGTH (pixman_stops_stack))) { - pixman_stops = _cairo_malloc_ab (n_stops, - sizeof (pixman_gradient_stop_t)); - if (unlikely (pixman_stops == NULL)) - return _cairo_error (CAIRO_STATUS_NO_MEMORY); - } - - for (i = 0; i < n_stops; i++) { - pixman_stops[i].x = _cairo_fixed_16_16_from_double (stops[i].offset); - pixman_stops[i].color.red = stops[i].color.red_short; - pixman_stops[i].color.green = stops[i].color.green_short; - pixman_stops[i].color.blue = stops[i].color.blue_short; - pixman_stops[i].color.alpha = stops[i].color.alpha_short; - } - - p1.x = _cairo_fixed_16_16_from_double (0.5); - p1.y = 0; - p2.x = _cairo_fixed_16_16_from_double (width - 0.5); - p2.y = 0; - - gradient = pixman_image_create_linear_gradient (&p1, &p2, - pixman_stops, - n_stops); - if (pixman_stops != pixman_stops_stack) - free (pixman_stops); - - if (unlikely (gradient == NULL)) - return _cairo_error (CAIRO_STATUS_NO_MEMORY); - - pixman_image_set_filter (gradient, PIXMAN_FILTER_BILINEAR, NULL, 0); - pixman_image_set_repeat (gradient, PIXMAN_REPEAT_PAD); - - image = pixman_image_create_bits (gradient_pixman_format, width, 1, - bytes, sizeof(uint32_t)*width); - if (unlikely (image == NULL)) { - pixman_image_unref (gradient); - return _cairo_error (CAIRO_STATUS_NO_MEMORY); - } - - pixman_image_composite32 (PIXMAN_OP_SRC, - gradient, NULL, image, - 0, 0, - 0, 0, - 0, 0, - width, 1); - - pixman_image_unref (gradient); - pixman_image_unref (image); - - /* We need to fudge pixel 0 to hold the left-most color stop and not - * the neareset stop to the zeroth pixel centre in order to correctly - * populate the border color. For completeness, do both edges. - */ - ((uint32_t*)bytes)[0] = color_stop_to_pixel(&stops[0]); - ((uint32_t*)bytes)[width-1] = color_stop_to_pixel(&stops[n_stops-1]); - - return CAIRO_STATUS_SUCCESS; -} - -static unsigned long -_cairo_gl_gradient_hash (unsigned int n_stops, - const cairo_gradient_stop_t *stops) -{ - return _cairo_hash_bytes (n_stops, - stops, - sizeof (cairo_gradient_stop_t) * n_stops); -} - -static cairo_gl_gradient_t * -_cairo_gl_gradient_lookup (cairo_gl_context_t *ctx, - unsigned long hash, - unsigned int n_stops, - const cairo_gradient_stop_t *stops) -{ - cairo_gl_gradient_t lookup; - - lookup.cache_entry.hash = hash, - lookup.n_stops = n_stops; - lookup.stops = stops; - - return _cairo_cache_lookup (&ctx->gradients, &lookup.cache_entry); -} - -cairo_bool_t -_cairo_gl_gradient_equal (const void *key_a, const void *key_b) -{ - const cairo_gl_gradient_t *a = key_a; - const cairo_gl_gradient_t *b = key_b; - - if (a->n_stops != b->n_stops) - return FALSE; - - return memcmp (a->stops, b->stops, a->n_stops * sizeof (cairo_gradient_stop_t)) == 0; -} - -cairo_int_status_t -_cairo_gl_gradient_create (cairo_gl_context_t *ctx, - unsigned int n_stops, - const cairo_gradient_stop_t *stops, - cairo_gl_gradient_t **gradient_out) -{ - unsigned long hash; - cairo_gl_gradient_t *gradient; - cairo_status_t status; - int tex_width; - GLint internal_format; - void *data; - - if ((unsigned int) ctx->max_texture_size / 2 <= n_stops) - return CAIRO_INT_STATUS_UNSUPPORTED; - - hash = _cairo_gl_gradient_hash (n_stops, stops); - - gradient = _cairo_gl_gradient_lookup (ctx, hash, n_stops, stops); - if (gradient) { - *gradient_out = _cairo_gl_gradient_reference (gradient); - return CAIRO_STATUS_SUCCESS; - } - - gradient = _cairo_malloc (sizeof (cairo_gl_gradient_t) + sizeof (cairo_gradient_stop_t) * (n_stops - 1)); - if (gradient == NULL) - return _cairo_error (CAIRO_STATUS_NO_MEMORY); - - tex_width = _cairo_gl_gradient_sample_width (n_stops, stops); - if (tex_width > ctx->max_texture_size) - tex_width = ctx->max_texture_size; - - CAIRO_REFERENCE_COUNT_INIT (&gradient->ref_count, 2); - gradient->cache_entry.hash = hash; - gradient->cache_entry.size = tex_width; - gradient->device = &ctx->base; - gradient->n_stops = n_stops; - gradient->stops = gradient->stops_embedded; - memcpy (gradient->stops_embedded, stops, n_stops * sizeof (cairo_gradient_stop_t)); - - glGenTextures (1, &gradient->tex); - _cairo_gl_context_activate (ctx, CAIRO_GL_TEX_TEMP); - glBindTexture (ctx->tex_target, gradient->tex); - - data = _cairo_malloc_ab (tex_width, sizeof (uint32_t)); - if (unlikely (data == NULL)) { - status = _cairo_error (CAIRO_STATUS_NO_MEMORY); - goto cleanup_gradient; - } - - status = _cairo_gl_gradient_render (ctx, n_stops, stops, data, tex_width); - if (unlikely (status)) - goto cleanup_data; - - /* - * In OpenGL ES 2.0 no format conversion is allowed i.e. 'internalFormat' - * must match 'format' in glTexImage2D. - */ - if (_cairo_gl_get_flavor () == CAIRO_GL_FLAVOR_ES3 || - _cairo_gl_get_flavor () == CAIRO_GL_FLAVOR_ES2) - internal_format = GL_BGRA; - else - internal_format = GL_RGBA; - - glTexImage2D (ctx->tex_target, 0, internal_format, tex_width, 1, 0, - GL_BGRA, GL_UNSIGNED_BYTE, data); - - free (data); - - /* we ignore errors here and just return an uncached gradient */ - if (unlikely (_cairo_cache_insert (&ctx->gradients, &gradient->cache_entry))) - CAIRO_REFERENCE_COUNT_INIT (&gradient->ref_count, 1); - - *gradient_out = gradient; - return CAIRO_STATUS_SUCCESS; - -cleanup_data: - free (data); -cleanup_gradient: - free (gradient); - return status; -} - -cairo_gl_gradient_t * -_cairo_gl_gradient_reference (cairo_gl_gradient_t *gradient) -{ - assert (CAIRO_REFERENCE_COUNT_HAS_REFERENCE (&gradient->ref_count)); - - _cairo_reference_count_inc (&gradient->ref_count); - - return gradient; -} - -void -_cairo_gl_gradient_destroy (cairo_gl_gradient_t *gradient) -{ - cairo_gl_context_t *ctx; - cairo_status_t ignore; - - assert (CAIRO_REFERENCE_COUNT_HAS_REFERENCE (&gradient->ref_count)); - - if (! _cairo_reference_count_dec_and_test (&gradient->ref_count)) - return; - - if (_cairo_gl_context_acquire (gradient->device, &ctx) == CAIRO_STATUS_SUCCESS) { - /* The gradient my still be active in the last operation, so flush */ - _cairo_gl_composite_flush (ctx); - glDeleteTextures (1, &gradient->tex); - ignore = _cairo_gl_context_release (ctx, CAIRO_STATUS_SUCCESS); - } - - free (gradient); -} diff --git a/gfx/cairo/cairo/src/cairo-gl-info.c b/gfx/cairo/cairo/src/cairo-gl-info.c deleted file mode 100644 index 53f5b17209..0000000000 --- a/gfx/cairo/cairo/src/cairo-gl-info.c +++ /dev/null @@ -1,145 +0,0 @@ -/* cairo - a vector graphics library with display and print output - * - * Copyright © 2010 Linaro Limited - * - * 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., 51 Franklin Street, Suite 500, Boston, MA 02110-1335, 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. - * - * Contributor(s): - * Alexandros Frantzis <alexandros.frantzis@linaro.org> - * Heiko Lewin <heiko.lewin@gmx.de> - */ - -#include "cairoint.h" -#include "cairo-gl-private.h" - -#include <errno.h> - -int -_cairo_gl_get_version (void) -{ - int major, minor; - const char *version = (const char *) glGetString (GL_VERSION); - const char *dot = version == NULL ? NULL : strchr (version, '.'); - const char *major_start = dot; - - /* Sanity check */ - if (dot == NULL || dot == version || *(dot + 1) == '\0') { - major = 0; - minor = 0; - } else { - /* Find the start of the major version in the string */ - while (major_start > version && *major_start != ' ') - --major_start; - major = strtol (major_start, NULL, 10); - minor = strtol (dot + 1, NULL, 10); - } - - return CAIRO_GL_VERSION_ENCODE (major, minor); -} - - -cairo_gl_flavor_t -_cairo_gl_degrade_flavor_by_build_features (cairo_gl_flavor_t flavor) { - switch(flavor) { - case CAIRO_GL_FLAVOR_DESKTOP: -#if CAIRO_HAS_GL_SURFACE - return CAIRO_GL_FLAVOR_DESKTOP; -#else - return CAIRO_GL_FLAVOR_NONE; -#endif - - case CAIRO_GL_FLAVOR_ES3: -#if CAIRO_HAS_GLESV3_SURFACE - return CAIRO_GL_FLAVOR_ES3; -#else - /* intentional fall through: degrade to GLESv2 if GLESv3-surfaces are not available */ -#endif - - case CAIRO_GL_FLAVOR_ES2: -#if CAIRO_HAS_GLESV2_SURFACE - return CAIRO_GL_FLAVOR_ES2; -#else - /* intentional fall through: no OpenGL in first place or no surfaces for it's version */ -#endif - - default: - return CAIRO_GL_FLAVOR_NONE; - } -} - -cairo_gl_flavor_t -_cairo_gl_get_flavor (void) -{ - const char *version = (const char *) glGetString (GL_VERSION); - cairo_gl_flavor_t flavor; - - if (version == NULL) { - flavor = CAIRO_GL_FLAVOR_NONE; - } else if (strstr (version, "OpenGL ES 3") != NULL) { - flavor = CAIRO_GL_FLAVOR_ES3; - } else if (strstr (version, "OpenGL ES 2") != NULL) { - flavor = CAIRO_GL_FLAVOR_ES2; - } else { - flavor = CAIRO_GL_FLAVOR_DESKTOP; - } - - return _cairo_gl_degrade_flavor_by_build_features(flavor); -} - -unsigned long -_cairo_gl_get_vbo_size (void) -{ - unsigned long vbo_size; - - const char *env = getenv ("CAIRO_GL_VBO_SIZE"); - if (env == NULL) { - vbo_size = CAIRO_GL_VBO_SIZE_DEFAULT; - } else { - errno = 0; - vbo_size = strtol (env, NULL, 10); - assert (errno == 0); - assert (vbo_size > 0); - } - - return vbo_size; -} - -cairo_bool_t -_cairo_gl_has_extension (const char *ext) -{ - const char *extensions = (const char *) glGetString (GL_EXTENSIONS); - size_t len = strlen (ext); - const char *ext_ptr = extensions; - - if (unlikely (ext_ptr == NULL)) - return 0; - - while ((ext_ptr = strstr (ext_ptr, ext)) != NULL) { - if (ext_ptr[len] == ' ' || ext_ptr[len] == '\0') - break; - ext_ptr += len; - } - - return (ext_ptr != NULL); -} diff --git a/gfx/cairo/cairo/src/cairo-gl-msaa-compositor.c b/gfx/cairo/cairo/src/cairo-gl-msaa-compositor.c deleted file mode 100644 index 7a83dd2194..0000000000 --- a/gfx/cairo/cairo/src/cairo-gl-msaa-compositor.c +++ /dev/null @@ -1,956 +0,0 @@ -/* -*- Mode: c; tab-width: 8; c-basic-offset: 4; indent-tabs-mode: t; -*- */ -/* cairo - a vector graphics library with display and print output - * - * Copyright © 2002 University of Southern California - * Copyright © 2005 Red Hat, Inc. - * Copyright © 2011 Intel Corporation - * Copyright © 2011 Samsung Electronics - * - * 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., 51 Franklin Street, Suite 500, Boston, MA 02110-1335, USA - * You should have received a copy of the MPL along with this library - * in the file COPYING-MPL-1.1 - * - * The contents of this file are subject to the Mozilla Public License - * Version 1.1 (the "License"); you may not use this file except in - * compliance with the License. You may obtain a copy of the License at - * http://www.mozilla.org/MPL/ - * - * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY - * OF ANY KIND, either express or implied. See the LGPL or the MPL for - * the specific language governing rights and limitations. - * - * The Original Code is the cairo graphics library. - * - * The Initial Developer of the Original Code is University of Southern - * California. - * - * Contributor(s): - * Henry Song <hsong@sisa.samsung.com> - * Martin Robinson <mrobinson@igalia.com> - */ - -#include "cairoint.h" - -#include "cairo-clip-inline.h" -#include "cairo-composite-rectangles-private.h" -#include "cairo-compositor-private.h" -#include "cairo-gl-private.h" -#include "cairo-path-private.h" -#include "cairo-traps-private.h" - -static cairo_bool_t -can_use_msaa_compositor (cairo_gl_surface_t *surface, - cairo_antialias_t antialias); - -static void -query_surface_capabilities (cairo_gl_surface_t *surface); - -struct _tristrip_composite_info { - cairo_gl_composite_t setup; - cairo_gl_context_t *ctx; -}; - -static cairo_int_status_t -_draw_trap (cairo_gl_context_t *ctx, - cairo_gl_composite_t *setup, - cairo_trapezoid_t *trap) -{ - cairo_point_t quad[4]; - - quad[0].x = _cairo_edge_compute_intersection_x_for_y (&trap->left.p1, - &trap->left.p2, - trap->top); - quad[0].y = trap->top; - - quad[1].x = _cairo_edge_compute_intersection_x_for_y (&trap->left.p1, - &trap->left.p2, - trap->bottom); - quad[1].y = trap->bottom; - - quad[2].x = _cairo_edge_compute_intersection_x_for_y (&trap->right.p1, - &trap->right.p2, - trap->bottom); - quad[2].y = trap->bottom; - - quad[3].x = _cairo_edge_compute_intersection_x_for_y (&trap->right.p1, - &trap->right.p2, - trap->top); - quad[3].y = trap->top; - return _cairo_gl_composite_emit_quad_as_tristrip (ctx, setup, quad); -} - -static cairo_int_status_t -_draw_traps (cairo_gl_context_t *ctx, - cairo_gl_composite_t *setup, - cairo_traps_t *traps) -{ - cairo_int_status_t status = CAIRO_STATUS_SUCCESS; - int i; - - for (i = 0; i < traps->num_traps; i++) { - cairo_trapezoid_t *trap = traps->traps + i; - if (unlikely ((status = _draw_trap (ctx, setup, trap)))) - return status; - } - - return status; -} - -static cairo_int_status_t -_draw_int_rect (cairo_gl_context_t *ctx, - cairo_gl_composite_t *setup, - cairo_rectangle_int_t *rect) -{ - cairo_box_t box; - cairo_point_t quad[4]; - - _cairo_box_from_rectangle (&box, rect); - quad[0].x = box.p1.x; - quad[0].y = box.p1.y; - quad[1].x = box.p1.x; - quad[1].y = box.p2.y; - quad[2].x = box.p2.x; - quad[2].y = box.p2.y; - quad[3].x = box.p2.x; - quad[3].y = box.p1.y; - - return _cairo_gl_composite_emit_quad_as_tristrip (ctx, setup, quad); -} - -static cairo_int_status_t -_draw_triangle_fan (cairo_gl_context_t *ctx, - cairo_gl_composite_t *setup, - const cairo_point_t *midpt, - const cairo_point_t *points, - int npoints) -{ - int i; - - /* Our strategy here is to not even try to build a triangle fan, but to - draw each triangle as if it was an unconnected member of a triangle strip. */ - for (i = 1; i < npoints; i++) { - cairo_int_status_t status; - cairo_point_t triangle[3]; - - triangle[0] = *midpt; - triangle[1] = points[i - 1]; - triangle[2] = points[i]; - - status = _cairo_gl_composite_emit_triangle_as_tristrip (ctx, setup, triangle); - if (unlikely (status)) - return status; - } - - return CAIRO_STATUS_SUCCESS; -} - -static cairo_int_status_t -_clip_to_traps (cairo_clip_t *clip, - cairo_traps_t *traps) -{ - cairo_int_status_t status; - cairo_polygon_t polygon; - cairo_antialias_t antialias; - cairo_fill_rule_t fill_rule; - - _cairo_traps_init (traps); - - if (clip->num_boxes == 1 && clip->path == NULL) { - cairo_boxes_t boxes; - _cairo_boxes_init_for_array (&boxes, clip->boxes, clip->num_boxes); - return _cairo_traps_init_boxes (traps, &boxes); - } - - status = _cairo_clip_get_polygon (clip, &polygon, &fill_rule, &antialias); - if (unlikely (status)) - return status; - - /* We ignore the antialias mode of the clip here, since the user requested - * unantialiased rendering of their path and we expect that this stencil - * based rendering of the clip to be a reasonable approximation to - * the intersection between that clip and the path. - * - * In other words, what the user expects when they try to perform - * a geometric intersection between an unantialiased polygon and an - * antialiased polygon is open to interpretation. And we choose the fast - * option. - */ - - _cairo_traps_init (traps); - status = _cairo_bentley_ottmann_tessellate_polygon (traps, - &polygon, - fill_rule); - _cairo_polygon_fini (&polygon); - - return status; -} - -cairo_int_status_t -_cairo_gl_msaa_compositor_draw_clip (cairo_gl_context_t *ctx, - cairo_gl_composite_t *setup, - cairo_clip_t *clip) -{ - cairo_int_status_t status; - cairo_traps_t traps; - - status = _clip_to_traps (clip, &traps); - if (unlikely (status)) - return status; - status = _draw_traps (ctx, setup, &traps); - - _cairo_traps_fini (&traps); - return status; -} - -static cairo_bool_t -_should_use_unbounded_surface (cairo_composite_rectangles_t *composite) -{ - cairo_gl_surface_t *dst = (cairo_gl_surface_t *) composite->surface; - cairo_rectangle_int_t *source = &composite->source; - - if (composite->is_bounded) - return FALSE; - - /* This isn't just an optimization. It also detects when painting is used - to paint back the unbounded surface, preventing infinite recursion. */ - return ! (source->x <= 0 && source->y <= 0 && - source->height + source->y >= dst->height && - source->width + source->x >= dst->width); -} - -static cairo_surface_t* -_prepare_unbounded_surface (cairo_gl_surface_t *dst) -{ - - cairo_surface_t* surface = cairo_gl_surface_create (dst->base.device, - dst->base.content, - dst->width, - dst->height); - if (surface == NULL) - return NULL; - if (unlikely (surface->status)) { - cairo_surface_destroy (surface); - return NULL; - } - return surface; -} - -static cairo_int_status_t -_paint_back_unbounded_surface (const cairo_compositor_t *compositor, - cairo_composite_rectangles_t *composite, - cairo_surface_t *surface) -{ - cairo_gl_surface_t *dst = (cairo_gl_surface_t *) composite->surface; - cairo_int_status_t status; - - cairo_pattern_t *pattern = cairo_pattern_create_for_surface (surface); - if (unlikely (pattern->status)) { - status = pattern->status; - goto finish; - } - - status = _cairo_compositor_paint (compositor, &dst->base, - composite->op, pattern, - composite->clip); - -finish: - cairo_pattern_destroy (pattern); - cairo_surface_destroy (surface); - return status; -} - -static cairo_bool_t -can_use_msaa_compositor (cairo_gl_surface_t *surface, - cairo_antialias_t antialias) -{ - cairo_gl_flavor_t gl_flavor = ((cairo_gl_context_t *) surface->base.device)->gl_flavor; - - query_surface_capabilities (surface); - if (! surface->supports_stencil) - return FALSE; - - /* Multisampling OpenGL ES surfaces only maintain one multisampling - framebuffer and thus must use the spans compositor to do non-antialiased - rendering. */ - if ((gl_flavor == CAIRO_GL_FLAVOR_ES3 || - gl_flavor == CAIRO_GL_FLAVOR_ES2) - && surface->supports_msaa - && surface->num_samples > 1 - && antialias == CAIRO_ANTIALIAS_NONE) - return FALSE; - - /* The MSAA compositor has a single-sample mode, so we can - support non-antialiased rendering. */ - if (antialias == CAIRO_ANTIALIAS_NONE) - return TRUE; - - if (antialias == CAIRO_ANTIALIAS_FAST || antialias == CAIRO_ANTIALIAS_DEFAULT) - return surface->supports_msaa; - return FALSE; -} - -static void -_cairo_gl_msaa_compositor_set_clip (cairo_composite_rectangles_t *composite, - cairo_gl_composite_t *setup) -{ - if (_cairo_composite_rectangles_can_reduce_clip (composite, composite->clip)) - return; - _cairo_gl_composite_set_clip (setup, composite->clip); -} - -/* Masking with the SOURCE operator requires two passes. In the first - * pass we use the mask as the source to get: - * result = (1 - ma) * dst - * In the second pass we use the add operator to achieve: - * result = (src * ma) + dst - * Combined this produces: - * result = (src * ma) + (1 - ma) * dst - */ -static cairo_int_status_t -_cairo_gl_msaa_compositor_mask_source_operator (const cairo_compositor_t *compositor, - cairo_composite_rectangles_t *composite) -{ - cairo_gl_composite_t setup; - cairo_gl_surface_t *dst = (cairo_gl_surface_t *) composite->surface; - cairo_gl_context_t *ctx = NULL; - cairo_int_status_t status; - - cairo_clip_t *clip = composite->clip; - cairo_traps_t traps; - - /* If we have a non-rectangular clip, we can avoid using the stencil buffer - * for clipping and just draw the clip polygon. */ - if (clip) { - status = _clip_to_traps (clip, &traps); - if (unlikely (status)) { - _cairo_traps_fini (&traps); - return status; - } - } - - status = _cairo_gl_composite_init (&setup, - CAIRO_OPERATOR_DEST_OUT, - dst, - FALSE /* assume_component_alpha */); - if (unlikely (status)) - return status; - status = _cairo_gl_composite_set_source (&setup, - &composite->mask_pattern.base, - &composite->mask_sample_area, - &composite->bounded, - FALSE); - if (unlikely (status)) - goto finish; - _cairo_gl_composite_set_multisample (&setup); - status = _cairo_gl_composite_begin (&setup, &ctx); - if (unlikely (status)) - goto finish; - - if (! clip) - status = _draw_int_rect (ctx, &setup, &composite->bounded); - else - status = _draw_traps (ctx, &setup, &traps); - if (unlikely (status)) - goto finish; - - /* Now draw the second pass. */ - status = _cairo_gl_composite_set_operator (&setup, CAIRO_OPERATOR_ADD, - FALSE /* assume_component_alpha */); - if (unlikely (status)) - goto finish; - status = _cairo_gl_composite_set_source (&setup, - &composite->source_pattern.base, - &composite->source_sample_area, - &composite->bounded, - FALSE); - if (unlikely (status)) - goto finish; - status = _cairo_gl_composite_set_mask (&setup, - &composite->mask_pattern.base, - &composite->source_sample_area, - &composite->bounded, - FALSE); - if (unlikely (status)) - goto finish; - - _cairo_gl_context_set_destination (ctx, dst, setup.multisample); - - status = _cairo_gl_set_operands_and_operator (&setup, ctx); - if (unlikely (status)) - goto finish; - - if (! clip) - status = _draw_int_rect (ctx, &setup, &composite->bounded); - else - status = _draw_traps (ctx, &setup, &traps); - -finish: - _cairo_gl_composite_fini (&setup); - if (ctx) - status = _cairo_gl_context_release (ctx, status); - if (clip) - _cairo_traps_fini (&traps); - - return status; -} - -static cairo_int_status_t -_cairo_gl_msaa_compositor_mask (const cairo_compositor_t *compositor, - cairo_composite_rectangles_t *composite) -{ - cairo_gl_composite_t setup; - cairo_gl_surface_t *dst = (cairo_gl_surface_t *) composite->surface; - cairo_gl_context_t *ctx = NULL; - cairo_int_status_t status; - cairo_operator_t op = composite->op; - cairo_clip_t *clip = composite->clip; - - if (! can_use_msaa_compositor (dst, CAIRO_ANTIALIAS_DEFAULT)) - return CAIRO_INT_STATUS_UNSUPPORTED; - - if (composite->op == CAIRO_OPERATOR_CLEAR && - composite->original_mask_pattern != NULL) - return CAIRO_INT_STATUS_UNSUPPORTED; - - /* GL compositing operators cannot properly represent a mask operation - using the SOURCE compositing operator in one pass. This only matters if - there actually is a mask (there isn't in a paint operation) and if the - mask isn't totally opaque. */ - if (op == CAIRO_OPERATOR_SOURCE && - composite->original_mask_pattern != NULL && - ! _cairo_pattern_is_opaque (&composite->mask_pattern.base, - &composite->mask_sample_area)) { - - if (! _cairo_pattern_is_opaque (&composite->source_pattern.base, - &composite->source_sample_area)) { - return _cairo_gl_msaa_compositor_mask_source_operator (compositor, composite); - } - - /* If the source is opaque the operation reduces to OVER. */ - op = CAIRO_OPERATOR_OVER; - } - - if (_should_use_unbounded_surface (composite)) { - cairo_surface_t* surface = _prepare_unbounded_surface (dst); - - if (unlikely (surface == NULL)) - return CAIRO_INT_STATUS_UNSUPPORTED; - - /* This may be a paint operation. */ - if (composite->original_mask_pattern == NULL) { - status = _cairo_compositor_paint (compositor, surface, - CAIRO_OPERATOR_SOURCE, - &composite->source_pattern.base, - NULL); - } else { - status = _cairo_compositor_mask (compositor, surface, - CAIRO_OPERATOR_SOURCE, - &composite->source_pattern.base, - &composite->mask_pattern.base, - NULL); - } - - if (unlikely (status)) { - cairo_surface_destroy (surface); - return status; - } - - return _paint_back_unbounded_surface (compositor, composite, surface); - } - - status = _cairo_gl_composite_init (&setup, - op, - dst, - FALSE /* assume_component_alpha */); - if (unlikely (status)) - return status; - - status = _cairo_gl_composite_set_source (&setup, - &composite->source_pattern.base, - &composite->source_sample_area, - &composite->bounded, - FALSE); - if (unlikely (status)) - goto finish; - - if (composite->original_mask_pattern != NULL) { - status = _cairo_gl_composite_set_mask (&setup, - &composite->mask_pattern.base, - &composite->mask_sample_area, - &composite->bounded, - FALSE); - } - if (unlikely (status)) - goto finish; - - /* We always use multisampling here, because we do not yet have the smarts - to calculate when the clip or the source requires it. */ - _cairo_gl_composite_set_multisample (&setup); - - status = _cairo_gl_composite_begin (&setup, &ctx); - if (unlikely (status)) - goto finish; - - if (! clip) - status = _draw_int_rect (ctx, &setup, &composite->bounded); - else - status = _cairo_gl_msaa_compositor_draw_clip (ctx, &setup, clip); - -finish: - _cairo_gl_composite_fini (&setup); - - if (ctx) - status = _cairo_gl_context_release (ctx, status); - - return status; -} - -static cairo_int_status_t -_cairo_gl_msaa_compositor_paint (const cairo_compositor_t *compositor, - cairo_composite_rectangles_t *composite) -{ - return _cairo_gl_msaa_compositor_mask (compositor, composite); -} - -static cairo_status_t -_stroke_shaper_add_triangle (void *closure, - const cairo_point_t triangle[3]) -{ - struct _tristrip_composite_info *info = closure; - return _cairo_gl_composite_emit_triangle_as_tristrip (info->ctx, - &info->setup, - triangle); -} - -static cairo_status_t -_stroke_shaper_add_triangle_fan (void *closure, - const cairo_point_t *midpoint, - const cairo_point_t *points, - int npoints) -{ - struct _tristrip_composite_info *info = closure; - return _draw_triangle_fan (info->ctx, &info->setup, - midpoint, points, npoints); -} - -static cairo_status_t -_stroke_shaper_add_quad (void *closure, - const cairo_point_t quad[4]) -{ - struct _tristrip_composite_info *info = closure; - return _cairo_gl_composite_emit_quad_as_tristrip (info->ctx, &info->setup, - quad); -} - -static cairo_int_status_t -_prevent_overlapping_strokes (cairo_gl_context_t *ctx, - cairo_gl_composite_t *setup, - cairo_composite_rectangles_t *composite, - const cairo_path_fixed_t *path, - const cairo_stroke_style_t *style, - const cairo_matrix_t *ctm) -{ - cairo_rectangle_int_t stroke_extents; - - if (! _cairo_gl_ensure_stencil (ctx, setup->dst)) - return CAIRO_INT_STATUS_UNSUPPORTED; - - if (_cairo_pattern_is_opaque (&composite->source_pattern.base, - &composite->source_sample_area)) - return CAIRO_INT_STATUS_SUCCESS; - - if (glIsEnabled (GL_STENCIL_TEST) == FALSE) { - cairo_bool_t scissor_was_enabled; - - /* In case we have pending operations we have to flush before - adding the stencil buffer. */ - _cairo_gl_composite_flush (ctx); - - /* Enable the stencil buffer, even if we are not using it for clipping, - so we can use it below to prevent overlapping shapes. We initialize - it all to one here which represents infinite clip. */ - glDepthMask (GL_TRUE); - glEnable (GL_STENCIL_TEST); - - /* We scissor here so that we don't have to clear the entire stencil - * buffer. If the scissor test is already enabled, it was enabled - * for clipping. In that case, instead of calculating an intersection, - * we just reuse it, and risk clearing too much. */ - scissor_was_enabled = glIsEnabled (GL_SCISSOR_TEST); - if (! scissor_was_enabled) { - _cairo_path_fixed_approximate_stroke_extents (path, style, ctm, - FALSE, /* is_vector */ - &stroke_extents); - _cairo_gl_scissor_to_rectangle (setup->dst, &stroke_extents); - } - glClearStencil (1); - glClear (GL_STENCIL_BUFFER_BIT); - if (! scissor_was_enabled) - glDisable (GL_SCISSOR_TEST); - - glStencilFunc (GL_EQUAL, 1, 1); - } - - /* This means that once we draw to a particular pixel nothing else can - be drawn there until the stencil buffer is reset or the stencil test - is disabled. */ - glStencilOp (GL_ZERO, GL_ZERO, GL_ZERO); - - _cairo_clip_destroy (setup->dst->clip_on_stencil_buffer); - setup->dst->clip_on_stencil_buffer = NULL; - - return CAIRO_INT_STATUS_SUCCESS; -} - -static void -query_surface_capabilities (cairo_gl_surface_t *surface) -{ - GLint samples, stencil_bits; - cairo_gl_context_t *ctx; - cairo_int_status_t status; - - /* Texture surfaces are create in such a way that they always - have stencil and multisample bits if possible, so we don't - need to query their capabilities lazily. */ - if (_cairo_gl_surface_is_texture (surface)) - return; - if (surface->stencil_and_msaa_caps_initialized) - return; - - surface->stencil_and_msaa_caps_initialized = TRUE; - surface->supports_stencil = FALSE; - surface->supports_msaa = FALSE; - - status = _cairo_gl_context_acquire (surface->base.device, &ctx); - if (unlikely (status)) - return; - - _cairo_gl_context_set_destination (ctx, surface, FALSE); - - glGetIntegerv(GL_SAMPLES, &samples); - glGetIntegerv(GL_STENCIL_BITS, &stencil_bits); - surface->supports_stencil = stencil_bits > 0; - surface->supports_msaa = samples > 1; - surface->num_samples = samples; - - status = _cairo_gl_context_release (ctx, status); -} - -static cairo_int_status_t -_cairo_gl_msaa_compositor_stroke (const cairo_compositor_t *compositor, - cairo_composite_rectangles_t *composite, - const cairo_path_fixed_t *path, - const cairo_stroke_style_t *style, - const cairo_matrix_t *ctm, - const cairo_matrix_t *ctm_inverse, - double tolerance, - cairo_antialias_t antialias) -{ - cairo_int_status_t status; - cairo_gl_surface_t *dst = (cairo_gl_surface_t *) composite->surface; - struct _tristrip_composite_info info; - - if (! can_use_msaa_compositor (dst, antialias)) - return CAIRO_INT_STATUS_UNSUPPORTED; - - if (composite->is_bounded == FALSE) { - cairo_surface_t* surface = _prepare_unbounded_surface (dst); - - if (unlikely (surface == NULL)) - return CAIRO_INT_STATUS_UNSUPPORTED; - - status = _cairo_compositor_stroke (compositor, surface, - CAIRO_OPERATOR_SOURCE, - &composite->source_pattern.base, - path, style, ctm, ctm_inverse, - tolerance, antialias, NULL); - if (unlikely (status)) { - cairo_surface_destroy (surface); - return status; - } - - return _paint_back_unbounded_surface (compositor, composite, surface); - } - - status = _cairo_gl_composite_init (&info.setup, - composite->op, - dst, - FALSE /* assume_component_alpha */); - if (unlikely (status)) - return status; - - info.ctx = NULL; - - status = _cairo_gl_composite_set_source (&info.setup, - &composite->source_pattern.base, - &composite->source_sample_area, - &composite->bounded, - FALSE); - if (unlikely (status)) - goto finish; - - _cairo_gl_msaa_compositor_set_clip (composite, &info.setup); - if (antialias != CAIRO_ANTIALIAS_NONE) - _cairo_gl_composite_set_multisample (&info.setup); - - status = _cairo_gl_composite_begin (&info.setup, &info.ctx); - if (unlikely (status)) - goto finish; - - status = _prevent_overlapping_strokes (info.ctx, &info.setup, - composite, path, style, ctm); - if (unlikely (status)) - goto finish; - - status = _cairo_path_fixed_stroke_to_shaper ((cairo_path_fixed_t *) path, - style, - ctm, - ctm_inverse, - tolerance, - _stroke_shaper_add_triangle, - _stroke_shaper_add_triangle_fan, - _stroke_shaper_add_quad, - &info); - if (unlikely (status)) - goto finish; - -finish: - _cairo_gl_composite_fini (&info.setup); - - if (info.ctx) - status = _cairo_gl_context_release (info.ctx, status); - - return status; -} - -static cairo_int_status_t -_draw_simple_quad_path (cairo_gl_context_t *ctx, - cairo_gl_composite_t *setup, - const cairo_path_fixed_t *path) -{ - cairo_point_t triangle[3]; - cairo_int_status_t status; - const cairo_point_t *points; - - points = cairo_path_head (path)->points; - triangle[0] = points[0]; - triangle[1] = points[1]; - triangle[2] = points[2]; - status = _cairo_gl_composite_emit_triangle_as_tristrip (ctx, setup, triangle); - if (status) - return status; - - triangle[0] = points[2]; - triangle[1] = points[3]; - triangle[2] = points[0]; - return _cairo_gl_composite_emit_triangle_as_tristrip (ctx, setup, triangle); -} - -static cairo_int_status_t -_cairo_gl_msaa_compositor_fill (const cairo_compositor_t *compositor, - cairo_composite_rectangles_t *composite, - const cairo_path_fixed_t *path, - cairo_fill_rule_t fill_rule, - double tolerance, - cairo_antialias_t antialias) -{ - cairo_gl_composite_t setup; - cairo_gl_surface_t *dst = (cairo_gl_surface_t *) composite->surface; - cairo_gl_context_t *ctx = NULL; - cairo_int_status_t status; - cairo_traps_t traps; - cairo_bool_t draw_path_with_traps; - - if (! can_use_msaa_compositor (dst, antialias)) - return CAIRO_INT_STATUS_UNSUPPORTED; - - if (composite->is_bounded == FALSE) { - cairo_surface_t* surface = _prepare_unbounded_surface (dst); - - if (unlikely (surface == NULL)) - return CAIRO_INT_STATUS_UNSUPPORTED; - - - status = _cairo_compositor_fill (compositor, surface, - CAIRO_OPERATOR_SOURCE, - &composite->source_pattern.base, - path, fill_rule, tolerance, - antialias, NULL); - - if (unlikely (status)) { - cairo_surface_destroy (surface); - return status; - } - - return _paint_back_unbounded_surface (compositor, composite, surface); - } - - draw_path_with_traps = ! _cairo_path_fixed_is_simple_quad (path); - - if (draw_path_with_traps) { - _cairo_traps_init (&traps); - status = _cairo_path_fixed_fill_to_traps (path, fill_rule, tolerance, &traps); - if (unlikely (status)) - goto cleanup_traps; - } - - status = _cairo_gl_composite_init (&setup, - composite->op, - dst, - FALSE /* assume_component_alpha */); - if (unlikely (status)) - goto cleanup_traps; - - status = _cairo_gl_composite_set_source (&setup, - &composite->source_pattern.base, - &composite->source_sample_area, - &composite->bounded, - FALSE); - if (unlikely (status)) - goto cleanup_setup; - - _cairo_gl_msaa_compositor_set_clip (composite, &setup); - if (antialias != CAIRO_ANTIALIAS_NONE) - _cairo_gl_composite_set_multisample (&setup); - - status = _cairo_gl_composite_begin (&setup, &ctx); - if (unlikely (status)) - goto cleanup_setup; - - if (! draw_path_with_traps) - status = _draw_simple_quad_path (ctx, &setup, path); - else - status = _draw_traps (ctx, &setup, &traps); - if (unlikely (status)) - goto cleanup_setup; - -cleanup_setup: - _cairo_gl_composite_fini (&setup); - - if (ctx) - status = _cairo_gl_context_release (ctx, status); - -cleanup_traps: - if (draw_path_with_traps) - _cairo_traps_fini (&traps); - - return status; -} - -static cairo_int_status_t -_cairo_gl_msaa_compositor_glyphs (const cairo_compositor_t *compositor, - cairo_composite_rectangles_t *composite, - cairo_scaled_font_t *scaled_font, - cairo_glyph_t *glyphs, - int num_glyphs, - cairo_bool_t overlap) -{ - cairo_int_status_t status; - cairo_surface_t *src = NULL; - int src_x, src_y; - cairo_composite_glyphs_info_t info; - - cairo_gl_surface_t *dst = (cairo_gl_surface_t *) composite->surface; - - query_surface_capabilities (dst); - if (! dst->supports_stencil) - return CAIRO_INT_STATUS_UNSUPPORTED; - - if (composite->op == CAIRO_OPERATOR_CLEAR) - return CAIRO_INT_STATUS_UNSUPPORTED; - - if (composite->is_bounded == FALSE) { - cairo_surface_t* surface = _prepare_unbounded_surface (dst); - - if (unlikely (surface == NULL)) - return CAIRO_INT_STATUS_UNSUPPORTED; - - status = _cairo_compositor_glyphs (compositor, surface, - CAIRO_OPERATOR_SOURCE, - &composite->source_pattern.base, - glyphs, num_glyphs, - scaled_font, composite->clip); - - if (unlikely (status)) { - cairo_surface_destroy (surface); - return status; - } - - return _paint_back_unbounded_surface (compositor, composite, surface); - } - - src = _cairo_gl_pattern_to_source (&dst->base, - &composite->source_pattern.base, - FALSE, - &composite->bounded, - &composite->source_sample_area, - &src_x, &src_y); - if (unlikely (src->status)) { - status = src->status; - goto finish; - } - - status = _cairo_gl_check_composite_glyphs (composite, - scaled_font, glyphs, - &num_glyphs); - if (unlikely (status != CAIRO_INT_STATUS_SUCCESS)) - goto finish; - - info.font = scaled_font; - info.glyphs = glyphs; - info.num_glyphs = num_glyphs; - info.use_mask = overlap || ! composite->is_bounded || - composite->op == CAIRO_OPERATOR_SOURCE; - info.extents = composite->bounded; - - _cairo_scaled_font_freeze_cache (scaled_font); - status = _cairo_gl_composite_glyphs_with_clip (dst, composite->op, - src, src_x, src_y, - 0, 0, &info, - composite->clip); - - _cairo_scaled_font_thaw_cache (scaled_font); - -finish: - if (src) - cairo_surface_destroy (src); - - return status; -} - -static void -_cairo_gl_msaa_compositor_init (cairo_compositor_t *compositor, - const cairo_compositor_t *delegate) -{ - compositor->delegate = delegate; - - compositor->paint = _cairo_gl_msaa_compositor_paint; - compositor->mask = _cairo_gl_msaa_compositor_mask; - compositor->fill = _cairo_gl_msaa_compositor_fill; - compositor->stroke = _cairo_gl_msaa_compositor_stroke; - compositor->glyphs = _cairo_gl_msaa_compositor_glyphs; -} - -const cairo_compositor_t * -_cairo_gl_msaa_compositor_get (void) -{ - static cairo_atomic_once_t once = CAIRO_ATOMIC_ONCE_INIT; - static cairo_compositor_t compositor; - if (_cairo_atomic_init_once_enter(&once)) { - _cairo_gl_msaa_compositor_init (&compositor, - _cairo_gl_span_compositor_get ()); - _cairo_atomic_init_once_leave(&once); - } - - return &compositor; -} diff --git a/gfx/cairo/cairo/src/cairo-gl-operand.c b/gfx/cairo/cairo/src/cairo-gl-operand.c deleted file mode 100644 index a754bde2f3..0000000000 --- a/gfx/cairo/cairo/src/cairo-gl-operand.c +++ /dev/null @@ -1,793 +0,0 @@ -/* cairo - a vector graphics library with display and print output - * - * Copyright © 2009 Eric Anholt - * Copyright © 2009 Chris Wilson - * Copyright © 2005,2010 Red Hat, Inc - * Copyright © 2011 Intel Corporation - * - * This library is free software; you can redistribute it and/or - * modify it either under the terms of the GNU Lesser General Public - * License version 2.1 as published by the Free Software Foundation - * (the "LGPL") or, at your option, under the terms of the Mozilla - * Public License Version 1.1 (the "MPL"). If you do not alter this - * notice, a recipient may use your version of this file under either - * the MPL or the LGPL. - * - * You should have received a copy of the LGPL along with this library - * in the file COPYING-LGPL-2.1; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Suite 500, Boston, MA 02110-1335, 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): - * Benjamin Otte <otte@gnome.org> - * Carl Worth <cworth@cworth.org> - * Chris Wilson <chris@chris-wilson.co.uk> - * Eric Anholt <eric@anholt.net> - */ - -#include "cairoint.h" - -#include "cairo-gl-private.h" - -#include "cairo-composite-rectangles-private.h" -#include "cairo-compositor-private.h" -#include "cairo-default-context-private.h" -#include "cairo-error-private.h" -#include "cairo-image-surface-private.h" -#include "cairo-surface-backend-private.h" -#include "cairo-surface-offset-private.h" -#include "cairo-surface-subsurface-inline.h" - -static cairo_int_status_t -_cairo_gl_create_gradient_texture (cairo_gl_surface_t *dst, - const cairo_gradient_pattern_t *pattern, - cairo_gl_gradient_t **gradient) -{ - cairo_gl_context_t *ctx; - cairo_status_t status; - - status = _cairo_gl_context_acquire (dst->base.device, &ctx); - if (unlikely (status)) - return status; - - status = _cairo_gl_gradient_create (ctx, pattern->n_stops, pattern->stops, gradient); - - return _cairo_gl_context_release (ctx, status); -} - -static cairo_status_t -_cairo_gl_subsurface_clone_operand_init (cairo_gl_operand_t *operand, - const cairo_pattern_t *_src, - cairo_gl_surface_t *dst, - const cairo_rectangle_int_t *sample, - const cairo_rectangle_int_t *extents, - cairo_bool_t use_texgen) -{ - const cairo_surface_pattern_t *src = (cairo_surface_pattern_t *)_src; - cairo_surface_pattern_t local_pattern; - cairo_surface_subsurface_t *sub; - cairo_gl_surface_t *surface; - cairo_gl_context_t *ctx; - cairo_surface_attributes_t *attributes; - cairo_status_t status; - - sub = (cairo_surface_subsurface_t *) src->surface; - - if (sub->snapshot && - sub->snapshot->type == CAIRO_SURFACE_TYPE_GL && - sub->snapshot->device == dst->base.device) - { - surface = (cairo_gl_surface_t *) - cairo_surface_reference (sub->snapshot); - } - else - { - status = _cairo_gl_context_acquire (dst->base.device, &ctx); - if (unlikely (status)) - return status; - - /* XXX Trim surface to the sample area within the subsurface? */ - surface = (cairo_gl_surface_t *) - _cairo_gl_surface_create_scratch (ctx, - sub->target->content, - sub->extents.width, - sub->extents.height); - if (surface->base.status) - return _cairo_gl_context_release (ctx, surface->base.status); - - _cairo_pattern_init_for_surface (&local_pattern, sub->target); - cairo_matrix_init_translate (&local_pattern.base.matrix, - sub->extents.x, sub->extents.y); - local_pattern.base.filter = CAIRO_FILTER_NEAREST; - status = _cairo_surface_paint (&surface->base, - CAIRO_OPERATOR_SOURCE, - &local_pattern.base, - NULL); - _cairo_pattern_fini (&local_pattern.base); - - status = _cairo_gl_context_release (ctx, status); - if (unlikely (status)) { - cairo_surface_destroy (&surface->base); - return status; - } - - _cairo_surface_subsurface_set_snapshot (&sub->base, &surface->base); - } - - status = _cairo_gl_surface_resolve_multisampling (surface); - if (unlikely (status)) - return status; - - attributes = &operand->texture.attributes; - - operand->type = CAIRO_GL_OPERAND_TEXTURE; - operand->texture.surface = surface; - operand->texture.owns_surface = surface; - operand->texture.tex = surface->tex; - - if (_cairo_gl_device_requires_power_of_two_textures (dst->base.device)) { - attributes->matrix = src->base.matrix; - } else { - cairo_matrix_t m; - - cairo_matrix_init_scale (&m, - 1.0 / surface->width, - 1.0 / surface->height); - cairo_matrix_multiply (&attributes->matrix, &src->base.matrix, &m); - } - - attributes->extend = src->base.extend; - attributes->filter = src->base.filter; - attributes->has_component_alpha = src->base.has_component_alpha; - - operand->texture.texgen = use_texgen; - return CAIRO_STATUS_SUCCESS; -} - -static cairo_status_t -_cairo_gl_subsurface_operand_init (cairo_gl_operand_t *operand, - const cairo_pattern_t *_src, - cairo_gl_surface_t *dst, - const cairo_rectangle_int_t *sample, - const cairo_rectangle_int_t *extents, - cairo_bool_t use_texgen) -{ - const cairo_surface_pattern_t *src = (cairo_surface_pattern_t *)_src; - cairo_surface_subsurface_t *sub; - cairo_gl_surface_t *surface; - cairo_surface_attributes_t *attributes; - cairo_int_status_t status; - - sub = (cairo_surface_subsurface_t *) src->surface; - - if (sample->x < 0 || sample->y < 0 || - sample->x + sample->width > sub->extents.width || - sample->y + sample->height > sub->extents.height) - { - return _cairo_gl_subsurface_clone_operand_init (operand, _src, - dst, sample, extents, - use_texgen); - } - - surface = (cairo_gl_surface_t *) sub->target; - if (surface->base.device && surface->base.device != dst->base.device) - return CAIRO_INT_STATUS_UNSUPPORTED; - - if (! _cairo_gl_surface_is_texture (surface)) - return CAIRO_INT_STATUS_UNSUPPORTED; - - status = _cairo_gl_surface_resolve_multisampling (surface); - if (unlikely (status)) - return status; - - /* Translate the matrix from - * (unnormalized src -> unnormalized src) to - * (unnormalized dst -> unnormalized src) - */ - _cairo_gl_operand_copy(operand, &surface->operand); - - attributes = &operand->texture.attributes; - attributes->matrix = src->base.matrix; - attributes->matrix.x0 += sub->extents.x; - attributes->matrix.y0 += sub->extents.y; - cairo_matrix_multiply (&attributes->matrix, - &attributes->matrix, - &surface->operand.texture.attributes.matrix); - - attributes->extend = src->base.extend; - attributes->filter = src->base.filter; - attributes->has_component_alpha = src->base.has_component_alpha; - - operand->texture.texgen = use_texgen; - return CAIRO_STATUS_SUCCESS; -} - -static cairo_status_t -_cairo_gl_surface_operand_init (cairo_gl_operand_t *operand, - const cairo_pattern_t *_src, - cairo_gl_surface_t *dst, - const cairo_rectangle_int_t *sample, - const cairo_rectangle_int_t *extents, - cairo_bool_t use_texgen) -{ - const cairo_surface_pattern_t *src = (cairo_surface_pattern_t *)_src; - cairo_gl_surface_t *surface; - cairo_surface_attributes_t *attributes; - cairo_int_status_t status; - - surface = (cairo_gl_surface_t *) src->surface; - if (surface->base.type != CAIRO_SURFACE_TYPE_GL) - return CAIRO_INT_STATUS_UNSUPPORTED; - - if (surface->base.backend->type != CAIRO_SURFACE_TYPE_GL) { - if (_cairo_surface_is_subsurface (&surface->base)) - return _cairo_gl_subsurface_operand_init (operand, _src, dst, - sample, extents, - use_texgen); - - return CAIRO_INT_STATUS_UNSUPPORTED; - } - - if (surface->base.device && surface->base.device != dst->base.device) - return CAIRO_INT_STATUS_UNSUPPORTED; - - if (surface->base.device && ! _cairo_gl_surface_is_texture (surface)) - return CAIRO_INT_STATUS_UNSUPPORTED; - - status = _cairo_gl_surface_resolve_multisampling (surface); - if (unlikely (status)) - return status; - - _cairo_gl_operand_copy(operand, &surface->operand); - - attributes = &operand->texture.attributes; - cairo_matrix_multiply (&attributes->matrix, - &src->base.matrix, - &attributes->matrix); - - attributes->extend = src->base.extend; - attributes->filter = src->base.filter; - attributes->has_component_alpha = src->base.has_component_alpha; - - operand->texture.texgen = use_texgen; - return CAIRO_STATUS_SUCCESS; -} - -static cairo_status_t -_cairo_gl_pattern_texture_setup (cairo_gl_operand_t *operand, - const cairo_pattern_t *_src, - cairo_gl_surface_t *dst, - const cairo_rectangle_int_t *extents) -{ - cairo_status_t status; - cairo_gl_surface_t *surface; - cairo_gl_context_t *ctx; - cairo_image_surface_t *image; - cairo_bool_t src_is_gl_surface = FALSE; - cairo_rectangle_int_t map_extents; - - if (_src->type == CAIRO_PATTERN_TYPE_SURFACE) { - cairo_surface_t* src_surface = ((cairo_surface_pattern_t *) _src)->surface; - src_is_gl_surface = src_surface->type == CAIRO_SURFACE_TYPE_GL; - } - - status = _cairo_gl_context_acquire (dst->base.device, &ctx); - if (unlikely (status)) - return status; - - surface = (cairo_gl_surface_t *) - _cairo_gl_surface_create_scratch (ctx, - CAIRO_CONTENT_COLOR_ALPHA, - extents->width, extents->height); - map_extents = *extents; - map_extents.x = map_extents.y = 0; - image = _cairo_surface_map_to_image (&surface->base, &map_extents); - - /* If the pattern is a GL surface, it belongs to some other GL context, - so we need to release this device while we paint it to the image. */ - if (src_is_gl_surface) { - status = _cairo_gl_context_release (ctx, status); - if (unlikely (status)) { - _cairo_surface_unmap_image (&surface->base, image); - goto fail; - } - } - - status = _cairo_surface_offset_paint (&image->base, extents->x, extents->y, - CAIRO_OPERATOR_SOURCE, _src, NULL); - - if (src_is_gl_surface) { - status = _cairo_gl_context_acquire (dst->base.device, &ctx); - if (unlikely (status)) { - _cairo_surface_unmap_image (&surface->base, image); - goto fail; - } - } - - status = _cairo_surface_unmap_image (&surface->base, image); - status = _cairo_gl_context_release (ctx, status); - if (unlikely (status)) - goto fail; - - *operand = surface->operand; - operand->texture.owns_surface = surface; - operand->texture.attributes.matrix.x0 -= extents->x * operand->texture.attributes.matrix.xx; - operand->texture.attributes.matrix.y0 -= extents->y * operand->texture.attributes.matrix.yy; - return CAIRO_STATUS_SUCCESS; - -fail: - cairo_surface_destroy (&surface->base); - return status; -} - -void -_cairo_gl_solid_operand_init (cairo_gl_operand_t *operand, - const cairo_color_t *color) -{ - operand->type = CAIRO_GL_OPERAND_CONSTANT; - operand->constant.color[0] = color->red * color->alpha; - operand->constant.color[1] = color->green * color->alpha; - operand->constant.color[2] = color->blue * color->alpha; - operand->constant.color[3] = color->alpha; -} - -void -_cairo_gl_operand_translate (cairo_gl_operand_t *operand, - double tx, double ty) -{ - switch (operand->type) { - case CAIRO_GL_OPERAND_TEXTURE: - operand->texture.attributes.matrix.x0 -= tx * operand->texture.attributes.matrix.xx; - operand->texture.attributes.matrix.y0 -= ty * operand->texture.attributes.matrix.yy; - break; - - case CAIRO_GL_OPERAND_LINEAR_GRADIENT: - case CAIRO_GL_OPERAND_RADIAL_GRADIENT_A0: - case CAIRO_GL_OPERAND_RADIAL_GRADIENT_NONE: - case CAIRO_GL_OPERAND_RADIAL_GRADIENT_EXT: - operand->gradient.m.x0 -= tx * operand->gradient.m.xx; - operand->gradient.m.y0 -= ty * operand->gradient.m.yy; - break; - - case CAIRO_GL_OPERAND_NONE: - case CAIRO_GL_OPERAND_CONSTANT: - case CAIRO_GL_OPERAND_COUNT: - default: - break; - } -} - -static cairo_status_t -_cairo_gl_gradient_operand_init (cairo_gl_operand_t *operand, - const cairo_pattern_t *pattern, - cairo_gl_surface_t *dst, - cairo_bool_t use_texgen) -{ - const cairo_gradient_pattern_t *gradient = (const cairo_gradient_pattern_t *)pattern; - cairo_status_t status; - - assert (gradient->base.type == CAIRO_PATTERN_TYPE_LINEAR || - gradient->base.type == CAIRO_PATTERN_TYPE_RADIAL); - - if (! _cairo_gl_device_has_glsl (dst->base.device)) - return CAIRO_INT_STATUS_UNSUPPORTED; - - status = _cairo_gl_create_gradient_texture (dst, - gradient, - &operand->gradient.gradient); - if (unlikely (status)) - return status; - - if (gradient->base.type == CAIRO_PATTERN_TYPE_LINEAR) { - cairo_linear_pattern_t *linear = (cairo_linear_pattern_t *) gradient; - double x0, y0, dx, dy, sf, offset; - - dx = linear->pd2.x - linear->pd1.x; - dy = linear->pd2.y - linear->pd1.y; - sf = 1.0 / (dx * dx + dy * dy); - dx *= sf; - dy *= sf; - - x0 = linear->pd1.x; - y0 = linear->pd1.y; - offset = dx * x0 + dy * y0; - - operand->type = CAIRO_GL_OPERAND_LINEAR_GRADIENT; - - cairo_matrix_init (&operand->gradient.m, dx, 0, dy, 1, -offset, 0); - if (! _cairo_matrix_is_identity (&pattern->matrix)) { - cairo_matrix_multiply (&operand->gradient.m, - &pattern->matrix, - &operand->gradient.m); - } - } else { - cairo_matrix_t m; - cairo_circle_double_t circles[2]; - double x0, y0, r0, dx, dy, dr; - - /* - * Some fragment shader implementations use half-floats to - * represent numbers, so the maximum number they can represent - * is about 2^14. Some intermediate computations used in the - * radial gradient shaders can produce results of up to 2*k^4. - * Setting k=8 makes the maximum result about 8192 (assuming - * that the extreme circles are not much smaller than the - * destination image). - */ - _cairo_gradient_pattern_fit_to_range (gradient, 8., - &operand->gradient.m, circles); - - x0 = circles[0].center.x; - y0 = circles[0].center.y; - r0 = circles[0].radius; - dx = circles[1].center.x - x0; - dy = circles[1].center.y - y0; - dr = circles[1].radius - r0; - - operand->gradient.a = dx * dx + dy * dy - dr * dr; - operand->gradient.radius_0 = r0; - operand->gradient.circle_d.center.x = dx; - operand->gradient.circle_d.center.y = dy; - operand->gradient.circle_d.radius = dr; - - if (operand->gradient.a == 0) - operand->type = CAIRO_GL_OPERAND_RADIAL_GRADIENT_A0; - else if (pattern->extend == CAIRO_EXTEND_NONE) - operand->type = CAIRO_GL_OPERAND_RADIAL_GRADIENT_NONE; - else - operand->type = CAIRO_GL_OPERAND_RADIAL_GRADIENT_EXT; - - cairo_matrix_init_translate (&m, -x0, -y0); - cairo_matrix_multiply (&operand->gradient.m, - &operand->gradient.m, - &m); - } - - operand->gradient.extend = pattern->extend; - operand->gradient.texgen = use_texgen; - - return CAIRO_STATUS_SUCCESS; -} - -void -_cairo_gl_operand_copy (cairo_gl_operand_t *dst, - const cairo_gl_operand_t *src) -{ - *dst = *src; - switch (dst->type) { - case CAIRO_GL_OPERAND_CONSTANT: - break; - case CAIRO_GL_OPERAND_LINEAR_GRADIENT: - case CAIRO_GL_OPERAND_RADIAL_GRADIENT_A0: - case CAIRO_GL_OPERAND_RADIAL_GRADIENT_NONE: - case CAIRO_GL_OPERAND_RADIAL_GRADIENT_EXT: - _cairo_gl_gradient_reference (dst->gradient.gradient); - break; - case CAIRO_GL_OPERAND_TEXTURE: - cairo_surface_reference (&dst->texture.owns_surface->base); - break; - default: - case CAIRO_GL_OPERAND_COUNT: - ASSERT_NOT_REACHED; - case CAIRO_GL_OPERAND_NONE: - break; - } -} - -void -_cairo_gl_operand_destroy (cairo_gl_operand_t *operand) -{ - switch (operand->type) { - case CAIRO_GL_OPERAND_CONSTANT: - break; - case CAIRO_GL_OPERAND_LINEAR_GRADIENT: - case CAIRO_GL_OPERAND_RADIAL_GRADIENT_A0: - case CAIRO_GL_OPERAND_RADIAL_GRADIENT_NONE: - case CAIRO_GL_OPERAND_RADIAL_GRADIENT_EXT: - _cairo_gl_gradient_destroy (operand->gradient.gradient); - break; - case CAIRO_GL_OPERAND_TEXTURE: - cairo_surface_destroy (&operand->texture.owns_surface->base); - break; - default: - case CAIRO_GL_OPERAND_COUNT: - ASSERT_NOT_REACHED; - case CAIRO_GL_OPERAND_NONE: - break; - } - - operand->type = CAIRO_GL_OPERAND_NONE; -} - -cairo_int_status_t -_cairo_gl_operand_init (cairo_gl_operand_t *operand, - const cairo_pattern_t *pattern, - cairo_gl_surface_t *dst, - const cairo_rectangle_int_t *sample, - const cairo_rectangle_int_t *extents, - cairo_bool_t use_texgen) -{ - cairo_int_status_t status; - - TRACE ((stderr, "%s: type=%d\n", __FUNCTION__, pattern->type)); - switch (pattern->type) { - case CAIRO_PATTERN_TYPE_SOLID: - _cairo_gl_solid_operand_init (operand, - &((cairo_solid_pattern_t *) pattern)->color); - return CAIRO_STATUS_SUCCESS; - case CAIRO_PATTERN_TYPE_SURFACE: - status = _cairo_gl_surface_operand_init (operand, pattern, dst, - sample, extents, use_texgen); - if (status == CAIRO_INT_STATUS_UNSUPPORTED) - break; - - return status; - - case CAIRO_PATTERN_TYPE_LINEAR: - case CAIRO_PATTERN_TYPE_RADIAL: - status = _cairo_gl_gradient_operand_init (operand, pattern, dst, - use_texgen); - if (status == CAIRO_INT_STATUS_UNSUPPORTED) - break; - - return status; - - default: - case CAIRO_PATTERN_TYPE_MESH: - case CAIRO_PATTERN_TYPE_RASTER_SOURCE: - break; - } - - return _cairo_gl_pattern_texture_setup (operand, pattern, dst, extents); -} - -cairo_filter_t -_cairo_gl_operand_get_filter (cairo_gl_operand_t *operand) -{ - cairo_filter_t filter; - - switch ((int) operand->type) { - case CAIRO_GL_OPERAND_TEXTURE: - filter = operand->texture.attributes.filter; - break; - case CAIRO_GL_OPERAND_LINEAR_GRADIENT: - case CAIRO_GL_OPERAND_RADIAL_GRADIENT_A0: - case CAIRO_GL_OPERAND_RADIAL_GRADIENT_NONE: - case CAIRO_GL_OPERAND_RADIAL_GRADIENT_EXT: - filter = CAIRO_FILTER_BILINEAR; - break; - default: - filter = CAIRO_FILTER_DEFAULT; - break; - } - - return filter; -} - -GLint -_cairo_gl_operand_get_gl_filter (cairo_gl_operand_t *operand) -{ - cairo_filter_t filter = _cairo_gl_operand_get_filter (operand); - - return filter != CAIRO_FILTER_FAST && filter != CAIRO_FILTER_NEAREST ? - GL_LINEAR : - GL_NEAREST; -} - -cairo_extend_t -_cairo_gl_operand_get_extend (cairo_gl_operand_t *operand) -{ - cairo_extend_t extend; - - switch ((int) operand->type) { - case CAIRO_GL_OPERAND_TEXTURE: - extend = operand->texture.attributes.extend; - break; - case CAIRO_GL_OPERAND_LINEAR_GRADIENT: - case CAIRO_GL_OPERAND_RADIAL_GRADIENT_A0: - case CAIRO_GL_OPERAND_RADIAL_GRADIENT_NONE: - case CAIRO_GL_OPERAND_RADIAL_GRADIENT_EXT: - extend = operand->gradient.extend; - break; - default: - extend = CAIRO_EXTEND_NONE; - break; - } - - return extend; -} - - -void -_cairo_gl_operand_bind_to_shader (cairo_gl_context_t *ctx, - cairo_gl_operand_t *operand, - cairo_gl_tex_t tex_unit) -{ - const cairo_matrix_t *texgen = NULL; - - switch (operand->type) { - default: - case CAIRO_GL_OPERAND_COUNT: - ASSERT_NOT_REACHED; - case CAIRO_GL_OPERAND_NONE: - return; - - case CAIRO_GL_OPERAND_CONSTANT: - _cairo_gl_shader_bind_vec4 (ctx, - ctx->current_shader->constant_location[tex_unit], - operand->constant.color[0], - operand->constant.color[1], - operand->constant.color[2], - operand->constant.color[3]); - return; - - case CAIRO_GL_OPERAND_RADIAL_GRADIENT_NONE: - case CAIRO_GL_OPERAND_RADIAL_GRADIENT_EXT: - _cairo_gl_shader_bind_float (ctx, - ctx->current_shader->a_location[tex_unit], - operand->gradient.a); - /* fall through */ - case CAIRO_GL_OPERAND_RADIAL_GRADIENT_A0: - _cairo_gl_shader_bind_vec3 (ctx, - ctx->current_shader->circle_d_location[tex_unit], - operand->gradient.circle_d.center.x, - operand->gradient.circle_d.center.y, - operand->gradient.circle_d.radius); - _cairo_gl_shader_bind_float (ctx, - ctx->current_shader->radius_0_location[tex_unit], - operand->gradient.radius_0); - /* fall through */ - case CAIRO_GL_OPERAND_LINEAR_GRADIENT: - case CAIRO_GL_OPERAND_TEXTURE: - /* - * For GLES2 we use shaders to implement GL_CLAMP_TO_BORDER (used - * with CAIRO_EXTEND_NONE). When bilinear filtering is enabled, - * these shaders need the texture dimensions for their calculations. - */ - if ((ctx->gl_flavor == CAIRO_GL_FLAVOR_ES3 || - ctx->gl_flavor == CAIRO_GL_FLAVOR_ES2) && - _cairo_gl_operand_get_extend (operand) == CAIRO_EXTEND_NONE && - _cairo_gl_operand_get_gl_filter (operand) == GL_LINEAR) - { - float width, height; - if (operand->type == CAIRO_GL_OPERAND_TEXTURE) { - width = operand->texture.surface->width; - height = operand->texture.surface->height; - } - else { - width = operand->gradient.gradient->cache_entry.size, - height = 1; - } - _cairo_gl_shader_bind_vec2 (ctx, - ctx->current_shader->texdims_location[tex_unit], - width, height); - } - break; - } - - if (operand->type == CAIRO_GL_OPERAND_TEXTURE) { - if (operand->texture.texgen) - texgen = &operand->texture.attributes.matrix; - } else { - if (operand->gradient.texgen) - texgen = &operand->gradient.m; - } - if (texgen) { - _cairo_gl_shader_bind_matrix(ctx, - ctx->current_shader->texgen_location[tex_unit], - texgen); - } -} - - -cairo_bool_t -_cairo_gl_operand_needs_setup (cairo_gl_operand_t *dest, - cairo_gl_operand_t *source, - unsigned int vertex_offset) -{ - if (dest->type != source->type) - return TRUE; - if (dest->vertex_offset != vertex_offset) - return TRUE; - - switch (source->type) { - case CAIRO_GL_OPERAND_NONE: - return FALSE; - case CAIRO_GL_OPERAND_CONSTANT: - return dest->constant.color[0] != source->constant.color[0] || - dest->constant.color[1] != source->constant.color[1] || - dest->constant.color[2] != source->constant.color[2] || - dest->constant.color[3] != source->constant.color[3]; - case CAIRO_GL_OPERAND_TEXTURE: - return dest->texture.surface != source->texture.surface || - dest->texture.attributes.extend != source->texture.attributes.extend || - dest->texture.attributes.filter != source->texture.attributes.filter || - dest->texture.attributes.has_component_alpha != source->texture.attributes.has_component_alpha; - case CAIRO_GL_OPERAND_LINEAR_GRADIENT: - case CAIRO_GL_OPERAND_RADIAL_GRADIENT_A0: - case CAIRO_GL_OPERAND_RADIAL_GRADIENT_NONE: - case CAIRO_GL_OPERAND_RADIAL_GRADIENT_EXT: - /* XXX: improve this */ - return TRUE; - default: - case CAIRO_GL_OPERAND_COUNT: - ASSERT_NOT_REACHED; - break; - } - return TRUE; -} - -unsigned int -_cairo_gl_operand_get_vertex_size (const cairo_gl_operand_t *operand) -{ - switch (operand->type) { - default: - case CAIRO_GL_OPERAND_COUNT: - ASSERT_NOT_REACHED; - case CAIRO_GL_OPERAND_NONE: - case CAIRO_GL_OPERAND_CONSTANT: - return 0; - case CAIRO_GL_OPERAND_TEXTURE: - return operand->texture.texgen ? 0 : 2 * sizeof (GLfloat); - case CAIRO_GL_OPERAND_LINEAR_GRADIENT: - case CAIRO_GL_OPERAND_RADIAL_GRADIENT_A0: - case CAIRO_GL_OPERAND_RADIAL_GRADIENT_NONE: - case CAIRO_GL_OPERAND_RADIAL_GRADIENT_EXT: - return operand->gradient.texgen ? 0 : 2 * sizeof (GLfloat); - } -} - -void -_cairo_gl_operand_emit (cairo_gl_operand_t *operand, - GLfloat ** vb, - GLfloat x, - GLfloat y) -{ - switch (operand->type) { - default: - case CAIRO_GL_OPERAND_COUNT: - ASSERT_NOT_REACHED; - case CAIRO_GL_OPERAND_NONE: - case CAIRO_GL_OPERAND_CONSTANT: - break; - case CAIRO_GL_OPERAND_LINEAR_GRADIENT: - case CAIRO_GL_OPERAND_RADIAL_GRADIENT_A0: - case CAIRO_GL_OPERAND_RADIAL_GRADIENT_NONE: - case CAIRO_GL_OPERAND_RADIAL_GRADIENT_EXT: - if (! operand->gradient.texgen) { - double s = x; - double t = y; - - cairo_matrix_transform_point (&operand->gradient.m, &s, &t); - - *(*vb)++ = s; - *(*vb)++ = t; - } - break; - case CAIRO_GL_OPERAND_TEXTURE: - if (! operand->texture.texgen) { - cairo_surface_attributes_t *src_attributes = &operand->texture.attributes; - double s = x; - double t = y; - - cairo_matrix_transform_point (&src_attributes->matrix, &s, &t); - *(*vb)++ = s; - *(*vb)++ = t; - } - break; - } -} diff --git a/gfx/cairo/cairo/src/cairo-gl-private.h b/gfx/cairo/cairo/src/cairo-gl-private.h deleted file mode 100644 index f02a58763e..0000000000 --- a/gfx/cairo/cairo/src/cairo-gl-private.h +++ /dev/null @@ -1,865 +0,0 @@ -/* cairo - a vector graphics library with display and print output - * - * Copyright © 2009 Eric Anholt - * Copyright © 2009 Chris Wilson - * Copyright © 2005,2010 Red Hat, Inc - * Copyright © 2011 Linaro Limited - * - * 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., 51 Franklin Street, Suite 500, Boston, MA 02110-1335, 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): - * Benjamin Otte <otte@gnome.org> - * Carl Worth <cworth@cworth.org> - * Chris Wilson <chris@chris-wilson.co.uk> - * Eric Anholt <eric@anholt.net> - * T. Zachary Laine <whatwasthataddress@gmail.com> - * Alexandros Frantzis <alexandros.frantzis@linaro.org> - */ - -#ifndef CAIRO_GL_PRIVATE_H -#define CAIRO_GL_PRIVATE_H - -#define GL_GLEXT_PROTOTYPES - -#include "cairoint.h" - -#include "cairo-gl.h" -#include "cairo-gl-gradient-private.h" - -#include "cairo-device-private.h" -#include "cairo-error-private.h" -#include "cairo-rtree-private.h" -#include "cairo-scaled-font-private.h" -#include "cairo-spans-compositor-private.h" -#include "cairo-array-private.h" - -#include <assert.h> - -#if CAIRO_HAS_GLESV3_SURFACE -#include <GLES3/gl3.h> -#include <GLES3/gl3ext.h> -#elif CAIRO_HAS_GLESV2_SURFACE -#include <GLES2/gl2.h> -#include <GLES2/gl2ext.h> -#elif CAIRO_HAS_GL_SURFACE -#include <GL/gl.h> -#include <GL/glext.h> -#endif - -#include "cairo-gl-ext-def-private.h" - -#define DEBUG_GL 0 - -#if DEBUG_GL && __GNUC__ -#define UNSUPPORTED(reason) ({ \ - fprintf (stderr, \ - "cairo-gl: hit unsupported operation in %s(), line %d: %s\n", \ - __FUNCTION__, __LINE__, reason); \ - CAIRO_INT_STATUS_UNSUPPORTED; \ -}) -#else -#define UNSUPPORTED(reason) CAIRO_INT_STATUS_UNSUPPORTED -#endif - -#define CAIRO_GL_VERSION_ENCODE(major, minor) ( \ - ((major) * 256) \ - + ((minor) * 1)) - -/* maximal number of shaders we keep in the cache. - * Random number that is hopefully big enough to not cause many cache evictions. */ -#define CAIRO_GL_MAX_SHADERS_PER_CONTEXT 64 - -/* VBO size that we allocate, smaller size means we gotta flush more often, - * but larger means hogging more memory and can cause trouble for drivers - * (especially on embedded devices). Use the CAIRO_GL_VBO_SIZE environment - * variable to set this to a different size. */ -#define CAIRO_GL_VBO_SIZE_DEFAULT (1024*1024) - -typedef struct _cairo_gl_surface cairo_gl_surface_t; - -/* GL flavor is the type of GL supported by the underlying platform. */ -typedef enum cairo_gl_flavor { - CAIRO_GL_FLAVOR_NONE = 0, - CAIRO_GL_FLAVOR_DESKTOP = 1, - CAIRO_GL_FLAVOR_ES2 = 2, - CAIRO_GL_FLAVOR_ES3 = 3 -} cairo_gl_flavor_t; - -/* Indices for vertex attributes used by BindAttribLocation, etc. */ -enum { - CAIRO_GL_VERTEX_ATTRIB_INDEX = 0, - CAIRO_GL_COLOR_ATTRIB_INDEX = 1, - CAIRO_GL_TEXCOORD0_ATTRIB_INDEX = 2, - CAIRO_GL_TEXCOORD1_ATTRIB_INDEX = CAIRO_GL_TEXCOORD0_ATTRIB_INDEX + 1 -}; - -typedef enum cairo_gl_operand_type { - CAIRO_GL_OPERAND_NONE, - CAIRO_GL_OPERAND_CONSTANT, - CAIRO_GL_OPERAND_TEXTURE, - CAIRO_GL_OPERAND_LINEAR_GRADIENT, - CAIRO_GL_OPERAND_RADIAL_GRADIENT_A0, - CAIRO_GL_OPERAND_RADIAL_GRADIENT_NONE, - CAIRO_GL_OPERAND_RADIAL_GRADIENT_EXT, - - CAIRO_GL_OPERAND_COUNT -} cairo_gl_operand_type_t; - -/* This union structure describes a potential source or mask operand to the - * compositing equation. - */ -typedef struct cairo_gl_operand { - cairo_gl_operand_type_t type; - union { - struct { - GLuint tex; - cairo_gl_surface_t *surface; - cairo_gl_surface_t *owns_surface; - cairo_surface_attributes_t attributes; - int texgen; - } texture; - struct { - GLfloat color[4]; - } constant; - struct { - cairo_gl_gradient_t *gradient; - cairo_matrix_t m; - cairo_circle_double_t circle_d; - double radius_0, a; - cairo_extend_t extend; - int texgen; - } gradient; - }; - unsigned int vertex_offset; -} cairo_gl_operand_t; - -typedef struct cairo_gl_source { - cairo_surface_t base; - cairo_gl_operand_t operand; -} cairo_gl_source_t; - -struct _cairo_gl_surface { - cairo_surface_t base; - cairo_gl_operand_t operand; - - int width, height; - - GLuint tex; /* GL texture object containing our data. */ - GLuint fb; /* GL framebuffer object wrapping our data. */ - GLuint depth_stencil; /* GL renderbuffer object for holding stencil buffer clip. */ - -#if CAIRO_HAS_GL_SURFACE || CAIRO_HAS_GLESV3_SURFACE - GLuint msaa_rb; /* The ARB MSAA path uses a renderbuffer. */ - GLuint msaa_fb; -#endif - GLuint msaa_depth_stencil; - - cairo_bool_t stencil_and_msaa_caps_initialized; - cairo_bool_t supports_stencil; /* Stencil support for for non-texture surfaces. */ - cairo_bool_t supports_msaa; - GLint num_samples; - cairo_bool_t msaa_active; /* Whether the multisampling - framebuffer is active or not. */ - cairo_bool_t content_in_texture; /* whether we just uploaded image - to texture, used for certain - gles2 extensions and glesv3 */ - cairo_clip_t *clip_on_stencil_buffer; - - int owns_tex; - cairo_bool_t needs_update; - - cairo_region_t *clip_region; -}; - -typedef struct cairo_gl_glyph_cache { - cairo_rtree_t rtree; - cairo_gl_surface_t *surface; -} cairo_gl_glyph_cache_t; - -typedef enum cairo_gl_tex { - CAIRO_GL_TEX_SOURCE = 0, - CAIRO_GL_TEX_MASK = 1, - CAIRO_GL_TEX_TEMP = 2 -} cairo_gl_tex_t; - -typedef struct cairo_gl_shader { - GLuint fragment_shader; - GLuint program; - GLint mvp_location; - GLint constant_location[2]; - GLint a_location[2]; - GLint circle_d_location[2]; - GLint radius_0_location[2]; - GLint texdims_location[2]; - GLint texgen_location[2]; -} cairo_gl_shader_t; - -typedef enum cairo_gl_shader_in { - CAIRO_GL_SHADER_IN_NORMAL, - CAIRO_GL_SHADER_IN_CA_SOURCE, - CAIRO_GL_SHADER_IN_CA_SOURCE_ALPHA, - - CAIRO_GL_SHADER_IN_COUNT -} cairo_gl_shader_in_t; - -typedef enum cairo_gl_var_type { - CAIRO_GL_VAR_NONE, - CAIRO_GL_VAR_TEXCOORDS, - CAIRO_GL_VAR_TEXGEN, -} cairo_gl_var_type_t; - -typedef enum cairo_gl_primitive_type { - CAIRO_GL_PRIMITIVE_TYPE_TRIANGLES, - CAIRO_GL_PRIMITIVE_TYPE_TRISTRIPS -} cairo_gl_primitive_type_t; - -typedef void (*cairo_gl_emit_rect_t) (cairo_gl_context_t *ctx, - GLfloat x1, GLfloat y1, - GLfloat x2, GLfloat y2); - -typedef void (*cairo_gl_emit_span_t) (cairo_gl_context_t *ctx, - GLfloat x1, GLfloat y1, - GLfloat x2, GLfloat y2, - uint8_t alpha); - -typedef void (*cairo_gl_emit_glyph_t) (cairo_gl_context_t *ctx, - GLfloat x1, GLfloat y1, - GLfloat x2, GLfloat y2, - GLfloat glyph_x1, GLfloat glyph_y1, - GLfloat glyph_x2, GLfloat glyph_y2); - -#define cairo_gl_var_type_hash(src,mask,spans,dest) ((spans) << 5) | ((mask) << 3 | (src << 1) | (dest)) -#define CAIRO_GL_VAR_TYPE_MAX (1 << 6) - -typedef void (*cairo_gl_generic_func_t)(void); -typedef cairo_gl_generic_func_t (*cairo_gl_get_proc_addr_func_t)(const char *procname); - -typedef struct _cairo_gl_dispatch { - /* Buffers */ - void (*GenBuffers) (GLsizei n, GLuint *buffers); - void (*BindBuffer) (GLenum target, GLuint buffer); - void (*BufferData) (GLenum target, GLsizeiptr size, - const GLvoid* data, GLenum usage); - GLvoid *(*MapBuffer) (GLenum target, GLenum access); - GLboolean (*UnmapBuffer) (GLenum target); - - /* Shaders */ - GLuint (*CreateShader) (GLenum type); - void (*ShaderSource) (GLuint shader, GLsizei count, - const GLchar** string, const GLint* length); - void (*CompileShader) (GLuint shader); - void (*GetShaderiv) (GLuint shader, GLenum pname, GLint *params); - void (*GetShaderInfoLog) (GLuint shader, GLsizei bufSize, - GLsizei *length, GLchar *infoLog); - void (*DeleteShader) (GLuint shader); - - /* Programs */ - GLuint (*CreateProgram) (void); - void (*AttachShader) (GLuint program, GLuint shader); - void (*DeleteProgram) (GLuint program); - void (*LinkProgram) (GLuint program); - void (*UseProgram) (GLuint program); - void (*GetProgramiv) (GLuint program, GLenum pname, GLint *params); - void (*GetProgramInfoLog) (GLuint program, GLsizei bufSize, - GLsizei *length, GLchar *infoLog); - - /* Uniforms */ - GLint (*GetUniformLocation) (GLuint program, const GLchar* name); - void (*Uniform1f) (GLint location, GLfloat x); - void (*Uniform2f) (GLint location, GLfloat x, GLfloat y); - void (*Uniform3f) (GLint location, GLfloat x, GLfloat y, GLfloat z); - void (*Uniform4f) (GLint location, GLfloat x, GLfloat y, GLfloat z, - GLfloat w); - void (*UniformMatrix3fv) (GLint location, GLsizei count, - GLboolean transpose, const GLfloat *value); - void (*UniformMatrix4fv) (GLint location, GLsizei count, - GLboolean transpose, const GLfloat *value); - void (*Uniform1i) (GLint location, GLint x); - - /* Attributes */ - void (*BindAttribLocation) (GLuint program, GLuint index, - const GLchar *name); - void (*VertexAttribPointer) (GLuint index, GLint size, GLenum type, - GLboolean normalized, GLsizei stride, - const GLvoid *pointer); - void (*EnableVertexAttribArray) (GLuint index); - void (*DisableVertexAttribArray) (GLuint index); - - /* Framebuffer objects */ - void (*GenFramebuffers) (GLsizei n, GLuint* framebuffers); - void (*BindFramebuffer) (GLenum target, GLuint framebuffer); - void (*FramebufferTexture2D) (GLenum target, GLenum attachment, - GLenum textarget, GLuint texture, - GLint level); - GLenum (*CheckFramebufferStatus) (GLenum target); - void (*DeleteFramebuffers) (GLsizei n, const GLuint* framebuffers); - void (*GenRenderbuffers) (GLsizei n, GLuint *renderbuffers); - void (*BindRenderbuffer) (GLenum target, GLuint renderbuffer); - void (*RenderbufferStorage) (GLenum target, GLenum internal_format, - GLsizei width, GLsizei height); - void (*FramebufferRenderbuffer) (GLenum target, GLenum attachment, - GLenum renderbuffer_ttarget, GLuint renderbuffer); - void (*DeleteRenderbuffers) (GLsizei n, GLuint *renderbuffers); - void (*BlitFramebuffer) (GLint srcX0, GLint srcY0, GLint srcX1, GLint srcY1, - GLint dstX0, GLint dstY0, GLint dstX1, GLint dstY1, - GLbitfield mask, GLenum filter); - void (*RenderbufferStorageMultisample) (GLenum target, GLsizei samples, - GLenum internalformat, - GLsizei width, GLsizei height); - void (*FramebufferTexture2DMultisample) (GLenum target, GLenum attachment, - GLenum textarget, GLuint texture, - GLint level, GLsizei samples); -} cairo_gl_dispatch_t; - -struct _cairo_gl_context { - cairo_device_t base; - - const cairo_compositor_t *compositor; - - GLuint texture_load_pbo; - GLint max_framebuffer_size; - GLint max_texture_size; - GLint max_textures; - GLenum tex_target; - - GLint num_samples; - cairo_bool_t supports_msaa; - char *vb; - - cairo_bool_t has_shader_support; - - GLuint vertex_shaders[CAIRO_GL_VAR_TYPE_MAX]; - cairo_gl_shader_t fill_rectangles_shader; - cairo_cache_t shaders; - - cairo_cache_t gradients; - - cairo_gl_glyph_cache_t glyph_cache[2]; - cairo_list_t fonts; - - cairo_gl_surface_t *current_target; - cairo_operator_t current_operator; - cairo_gl_shader_t *pre_shader; /* for component alpha */ - cairo_gl_shader_t *current_shader; - - cairo_gl_operand_t operands[2]; - cairo_bool_t spans; - - unsigned int vbo_size; - unsigned int vb_offset; - unsigned int vertex_size; - cairo_region_t *clip_region; - cairo_clip_t *clip; - - cairo_gl_primitive_type_t primitive_type; - cairo_array_t tristrip_indices; - - cairo_bool_t has_mesa_pack_invert; - cairo_gl_dispatch_t dispatch; - GLfloat modelviewprojection_matrix[16]; - cairo_gl_flavor_t gl_flavor; - cairo_bool_t has_map_buffer; - cairo_bool_t has_packed_depth_stencil; - cairo_bool_t has_npot_repeat; - cairo_bool_t can_read_bgra; - - cairo_bool_t thread_aware; - - void (*acquire) (void *ctx); - void (*release) (void *ctx); - - void (*make_current) (void *ctx, cairo_gl_surface_t *surface); - void (*swap_buffers)(void *ctx, cairo_gl_surface_t *surface); - void (*destroy) (void *ctx); -}; - -typedef struct _cairo_gl_composite { - cairo_gl_surface_t *dst; - cairo_operator_t op; - cairo_region_t *clip_region; - - cairo_gl_operand_t src; - cairo_gl_operand_t mask; - cairo_bool_t spans; - - cairo_clip_t *clip; - cairo_bool_t multisample; -} cairo_gl_composite_t; - -typedef struct _cairo_gl_font { - cairo_scaled_font_private_t base; - cairo_device_t *device; - cairo_list_t link; -} cairo_gl_font_t; - -static cairo_always_inline GLenum -_cairo_gl_get_error (void) -{ - GLenum err = glGetError(); - - if (unlikely (err)) - while (glGetError ()); - - return err; -} - -static inline cairo_device_t * -_cairo_gl_context_create_in_error (cairo_status_t status) -{ - return (cairo_device_t *) _cairo_device_create_in_error (status); -} - -cairo_private cairo_status_t -_cairo_gl_context_init (cairo_gl_context_t *ctx); - -cairo_private void -_cairo_gl_surface_init (cairo_device_t *device, - cairo_gl_surface_t *surface, - cairo_content_t content, - int width, int height); - -static cairo_always_inline cairo_bool_t cairo_warn -_cairo_gl_surface_is_texture (cairo_gl_surface_t *surface) -{ - return surface->tex != 0; -} - -cairo_private cairo_status_t -_cairo_gl_surface_draw_image (cairo_gl_surface_t *dst, - cairo_image_surface_t *src, - int src_x, int src_y, - int width, int height, - int dst_x, int dst_y, - cairo_bool_t force_flush); - -cairo_private cairo_int_status_t -_cairo_gl_surface_resolve_multisampling (cairo_gl_surface_t *surface); - -static cairo_always_inline cairo_bool_t -_cairo_gl_device_has_glsl (cairo_device_t *device) -{ - return ((cairo_gl_context_t *) device)->has_shader_support; -} - -static cairo_always_inline cairo_bool_t -_cairo_gl_device_requires_power_of_two_textures (cairo_device_t *device) -{ - return ((cairo_gl_context_t *) device)->tex_target == GL_TEXTURE_RECTANGLE; -} - -static cairo_always_inline cairo_status_t cairo_warn -_cairo_gl_context_acquire (cairo_device_t *device, - cairo_gl_context_t **ctx) -{ - cairo_status_t status; - - status = cairo_device_acquire (device); - if (unlikely (status)) - return status; - - /* clear potential previous GL errors */ - _cairo_gl_get_error (); - - *ctx = (cairo_gl_context_t *) device; - return CAIRO_STATUS_SUCCESS; -} - -static cairo_always_inline cairo_warn cairo_status_t -_cairo_gl_context_release (cairo_gl_context_t *ctx, cairo_status_t status) -{ - GLenum err; - - err = _cairo_gl_get_error (); - - if (unlikely (err)) { - cairo_status_t new_status; - new_status = _cairo_error (CAIRO_STATUS_DEVICE_ERROR); - if (status == CAIRO_STATUS_SUCCESS) - status = new_status; - } - - cairo_device_release (&(ctx)->base); - - return status; -} - -cairo_private void -_cairo_gl_context_set_destination (cairo_gl_context_t *ctx, - cairo_gl_surface_t *surface, - cairo_bool_t multisampling); - -cairo_private void -_cairo_gl_context_bind_framebuffer (cairo_gl_context_t *ctx, - cairo_gl_surface_t *surface, - cairo_bool_t multisampling); - -cairo_private cairo_gl_emit_rect_t -_cairo_gl_context_choose_emit_rect (cairo_gl_context_t *ctx); - -cairo_private void -_cairo_gl_context_emit_rect (cairo_gl_context_t *ctx, - GLfloat x1, GLfloat y1, - GLfloat x2, GLfloat y2); - -cairo_private cairo_gl_emit_span_t -_cairo_gl_context_choose_emit_span (cairo_gl_context_t *ctx); - -cairo_private cairo_gl_emit_glyph_t -_cairo_gl_context_choose_emit_glyph (cairo_gl_context_t *ctx); - -cairo_private void -_cairo_gl_context_activate (cairo_gl_context_t *ctx, - cairo_gl_tex_t tex_unit); - -cairo_private cairo_bool_t -_cairo_gl_operator_is_supported (cairo_operator_t op); - -cairo_private cairo_bool_t -_cairo_gl_ensure_stencil (cairo_gl_context_t *ctx, - cairo_gl_surface_t *surface); - -cairo_private cairo_status_t -_cairo_gl_composite_init (cairo_gl_composite_t *setup, - cairo_operator_t op, - cairo_gl_surface_t *dst, - cairo_bool_t has_component_alpha); - -cairo_private void -_cairo_gl_composite_fini (cairo_gl_composite_t *setup); - -cairo_private cairo_status_t -_cairo_gl_composite_set_operator (cairo_gl_composite_t *setup, - cairo_operator_t op, - cairo_bool_t assume_component_alpha); - -cairo_private void -_cairo_gl_composite_set_clip_region (cairo_gl_composite_t *setup, - cairo_region_t *clip_region); - -cairo_private void -_cairo_gl_composite_set_clip(cairo_gl_composite_t *setup, - cairo_clip_t *clip); - -cairo_private cairo_int_status_t -_cairo_gl_composite_set_source (cairo_gl_composite_t *setup, - const cairo_pattern_t *pattern, - const cairo_rectangle_int_t *sample, - const cairo_rectangle_int_t *extents, - cairo_bool_t use_texgen); - -cairo_private void -_cairo_gl_composite_set_solid_source (cairo_gl_composite_t *setup, - const cairo_color_t *color); - -cairo_private void -_cairo_gl_composite_set_source_operand (cairo_gl_composite_t *setup, - const cairo_gl_operand_t *source); - -cairo_private cairo_int_status_t -_cairo_gl_composite_set_mask (cairo_gl_composite_t *setup, - const cairo_pattern_t *pattern, - const cairo_rectangle_int_t *sample, - const cairo_rectangle_int_t *extents, - cairo_bool_t use_texgen); - -cairo_private void -_cairo_gl_composite_set_mask_operand (cairo_gl_composite_t *setup, - const cairo_gl_operand_t *mask); - -cairo_private void -_cairo_gl_composite_set_spans (cairo_gl_composite_t *setup); - -cairo_private void -_cairo_gl_composite_set_multisample (cairo_gl_composite_t *setup); - -cairo_private cairo_status_t -_cairo_gl_composite_begin (cairo_gl_composite_t *setup, - cairo_gl_context_t **ctx); - -cairo_private cairo_status_t -_cairo_gl_set_operands_and_operator (cairo_gl_composite_t *setup, - cairo_gl_context_t *ctx); - -cairo_private void -_cairo_gl_composite_flush (cairo_gl_context_t *ctx); - -cairo_private cairo_int_status_t -_cairo_gl_composite_emit_quad_as_tristrip (cairo_gl_context_t *ctx, - cairo_gl_composite_t *setup, - const cairo_point_t quad[4]); - -cairo_private cairo_int_status_t -_cairo_gl_composite_emit_triangle_as_tristrip (cairo_gl_context_t *ctx, - cairo_gl_composite_t *setup, - const cairo_point_t triangle[3]); - -cairo_private void -_cairo_gl_context_destroy_operand (cairo_gl_context_t *ctx, - cairo_gl_tex_t tex_unit); - -cairo_private cairo_bool_t -_cairo_gl_get_image_format_and_type (cairo_gl_flavor_t flavor, - pixman_format_code_t pixman_format, - GLenum *internal_format, GLenum *format, - GLenum *type, cairo_bool_t *has_alpha, - cairo_bool_t *needs_swap); - -cairo_private void -_cairo_gl_glyph_cache_init (cairo_gl_glyph_cache_t *cache); - -cairo_private void -_cairo_gl_glyph_cache_fini (cairo_gl_context_t *ctx, - cairo_gl_glyph_cache_t *cache); - -cairo_private cairo_int_status_t -_cairo_gl_surface_show_glyphs (void *abstract_dst, - cairo_operator_t op, - const cairo_pattern_t *source, - cairo_glyph_t *glyphs, - int num_glyphs, - cairo_scaled_font_t *scaled_font, - const cairo_clip_t *clip, - int *remaining_glyphs); - -cairo_private cairo_status_t -_cairo_gl_context_init_shaders (cairo_gl_context_t *ctx); - -cairo_private void -_cairo_gl_context_fini_shaders (cairo_gl_context_t *ctx); - -static cairo_always_inline cairo_bool_t -_cairo_gl_context_is_flushed (cairo_gl_context_t *ctx) -{ - return ctx->vb_offset == 0; -} - -cairo_private cairo_status_t -_cairo_gl_get_shader_by_type (cairo_gl_context_t *ctx, - cairo_gl_operand_t *source, - cairo_gl_operand_t *mask, - cairo_bool_t use_coverage, - cairo_gl_shader_in_t in, - cairo_gl_shader_t **shader); - -cairo_private void -_cairo_gl_shader_bind_float (cairo_gl_context_t *ctx, - GLint location, - float value); - -cairo_private void -_cairo_gl_shader_bind_vec2 (cairo_gl_context_t *ctx, - GLint location, - float value0, float value1); - -cairo_private void -_cairo_gl_shader_bind_vec3 (cairo_gl_context_t *ctx, - GLint location, - float value0, - float value1, - float value2); - -cairo_private void -_cairo_gl_shader_bind_vec4 (cairo_gl_context_t *ctx, - GLint location, - float value0, float value1, - float value2, float value3); - -cairo_private void -_cairo_gl_shader_bind_matrix (cairo_gl_context_t *ctx, - GLint location, - const cairo_matrix_t* m); - -cairo_private void -_cairo_gl_shader_bind_matrix4f (cairo_gl_context_t *ctx, - GLint location, - GLfloat* gl_m); - -cairo_private void -_cairo_gl_set_shader (cairo_gl_context_t *ctx, - cairo_gl_shader_t *shader); - -cairo_private void -_cairo_gl_shader_fini (cairo_gl_context_t *ctx, cairo_gl_shader_t *shader); - -cairo_private int -_cairo_gl_get_version (void); - -cairo_private cairo_gl_flavor_t -_cairo_gl_get_flavor (void); - -cairo_private unsigned long -_cairo_gl_get_vbo_size (void); - -cairo_private cairo_bool_t -_cairo_gl_has_extension (const char *ext); - -cairo_private cairo_status_t -_cairo_gl_dispatch_init(cairo_gl_dispatch_t *dispatch, - cairo_gl_get_proc_addr_func_t get_proc_addr); - -cairo_private cairo_int_status_t -_cairo_gl_operand_init (cairo_gl_operand_t *operand, - const cairo_pattern_t *pattern, - cairo_gl_surface_t *dst, - const cairo_rectangle_int_t *sample, - const cairo_rectangle_int_t *extents, - cairo_bool_t use_texgen); - -cairo_private void -_cairo_gl_solid_operand_init (cairo_gl_operand_t *operand, - const cairo_color_t *color); - -cairo_private cairo_filter_t -_cairo_gl_operand_get_filter (cairo_gl_operand_t *operand); - -cairo_private GLint -_cairo_gl_operand_get_gl_filter (cairo_gl_operand_t *operand); - -cairo_private cairo_extend_t -_cairo_gl_operand_get_extend (cairo_gl_operand_t *operand); - -cairo_private unsigned int -_cairo_gl_operand_get_vertex_size (const cairo_gl_operand_t *operand); - -cairo_private cairo_bool_t -_cairo_gl_operand_needs_setup (cairo_gl_operand_t *dest, - cairo_gl_operand_t *source, - unsigned int vertex_offset); - -cairo_private void -_cairo_gl_operand_bind_to_shader (cairo_gl_context_t *ctx, - cairo_gl_operand_t *operand, - cairo_gl_tex_t tex_unit); - -cairo_private void -_cairo_gl_operand_emit (cairo_gl_operand_t *operand, - GLfloat ** vb, - GLfloat x, - GLfloat y); - -cairo_private void -_cairo_gl_operand_copy (cairo_gl_operand_t *dst, - const cairo_gl_operand_t *src); - -cairo_private void -_cairo_gl_operand_translate (cairo_gl_operand_t *operand, - double tx, double ty); - -cairo_private void -_cairo_gl_operand_destroy (cairo_gl_operand_t *operand); - -cairo_private const cairo_compositor_t * -_cairo_gl_msaa_compositor_get (void); - -cairo_private const cairo_compositor_t * -_cairo_gl_span_compositor_get (void); - -cairo_private const cairo_compositor_t * -_cairo_gl_traps_compositor_get (void); - -cairo_private cairo_int_status_t -_cairo_gl_check_composite_glyphs (const cairo_composite_rectangles_t *extents, - cairo_scaled_font_t *scaled_font, - cairo_glyph_t *glyphs, - int *num_glyphs); - -cairo_private cairo_int_status_t -_cairo_gl_composite_glyphs (void *_dst, - cairo_operator_t op, - cairo_surface_t *_src, - int src_x, - int src_y, - int dst_x, - int dst_y, - cairo_composite_glyphs_info_t *info); - -cairo_private cairo_int_status_t -_cairo_gl_composite_glyphs_with_clip (void *_dst, - cairo_operator_t op, - cairo_surface_t *_src, - int src_x, - int src_y, - int dst_x, - int dst_y, - cairo_composite_glyphs_info_t *info, - cairo_clip_t *clip); - -cairo_private void -_cairo_gl_ensure_framebuffer (cairo_gl_context_t *ctx, - cairo_gl_surface_t *surface); - -cairo_private cairo_surface_t * -_cairo_gl_surface_create_scratch (cairo_gl_context_t *ctx, - cairo_content_t content, - int width, - int height); - -cairo_private cairo_surface_t * -_cairo_gl_surface_create_scratch_for_caching (cairo_gl_context_t *ctx, - cairo_content_t content, - int width, - int height); - -cairo_private cairo_surface_t * -_cairo_gl_pattern_to_source (cairo_surface_t *dst, - const cairo_pattern_t *pattern, - cairo_bool_t is_mask, - const cairo_rectangle_int_t *extents, - const cairo_rectangle_int_t *sample, - int *src_x, int *src_y); - -cairo_private cairo_int_status_t -_cairo_gl_msaa_compositor_draw_clip (cairo_gl_context_t *ctx, - cairo_gl_composite_t *setup, - cairo_clip_t *clip); - -cairo_private cairo_surface_t * -_cairo_gl_white_source (void); - -cairo_private void -_cairo_gl_scissor_to_rectangle (cairo_gl_surface_t *surface, - const cairo_rectangle_int_t *r); - -static inline cairo_gl_operand_t * -source_to_operand (cairo_surface_t *surface) -{ - cairo_gl_source_t *source = (cairo_gl_source_t *)surface; - return source ? &source->operand : NULL; -} - -static inline void -_cairo_gl_glyph_cache_unlock (cairo_gl_glyph_cache_t *cache) -{ - _cairo_rtree_unpin (&cache->rtree); -} - - -slim_hidden_proto (cairo_gl_surface_create); -slim_hidden_proto (cairo_gl_surface_create_for_texture); - -#endif /* CAIRO_GL_PRIVATE_H */ diff --git a/gfx/cairo/cairo/src/cairo-gl-shaders.c b/gfx/cairo/cairo/src/cairo-gl-shaders.c deleted file mode 100644 index b70c177f22..0000000000 --- a/gfx/cairo/cairo/src/cairo-gl-shaders.c +++ /dev/null @@ -1,1111 +0,0 @@ -/* cairo - a vector graphics library with display and print output - * - * Copyright © 2009 T. Zachary Laine - * Copyright © 2010 Eric Anholt - * Copyright © 2010 Red Hat, Inc - * Copyright © 2010 Linaro Limited - * - * 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., 51 Franklin Street, Suite 500, Boston, MA 02110-1335, 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 T. Zachary Laine. - * - * Contributor(s): - * Benjamin Otte <otte@gnome.org> - * Eric Anholt <eric@anholt.net> - * T. Zachary Laine <whatwasthataddress@gmail.com> - * Alexandros Frantzis <alexandros.frantzis@linaro.org> - * H. Lewin <heiko.lewin@gmx.de> - */ - -#include "cairoint.h" -#include "cairo-gl-private.h" -#include "cairo-error-private.h" -#include "cairo-output-stream-private.h" - -static cairo_status_t -_cairo_gl_shader_compile_and_link (cairo_gl_context_t *ctx, - cairo_gl_shader_t *shader, - cairo_gl_var_type_t src, - cairo_gl_var_type_t mask, - cairo_bool_t use_coverage, - const char *fragment_text); - -typedef struct _cairo_shader_cache_entry { - cairo_cache_entry_t base; - - unsigned vertex; - - cairo_gl_operand_type_t src; - cairo_gl_operand_type_t mask; - cairo_gl_operand_type_t dest; - cairo_bool_t use_coverage; - - cairo_gl_shader_in_t in; - GLint src_gl_filter; - cairo_bool_t src_border_fade; - cairo_extend_t src_extend; - GLint mask_gl_filter; - cairo_bool_t mask_border_fade; - cairo_extend_t mask_extend; - - cairo_gl_context_t *ctx; /* XXX: needed to destroy the program */ - cairo_gl_shader_t shader; -} cairo_shader_cache_entry_t; - -static cairo_bool_t -_cairo_gl_shader_cache_equal_desktop (const void *key_a, const void *key_b) -{ - const cairo_shader_cache_entry_t *a = key_a; - const cairo_shader_cache_entry_t *b = key_b; - cairo_bool_t both_have_npot_repeat = - a->ctx->has_npot_repeat && b->ctx->has_npot_repeat; - - return (a->vertex == b->vertex && - a->src == b->src && - a->mask == b->mask && - a->dest == b->dest && - a->use_coverage == b->use_coverage && - a->in == b->in && - (both_have_npot_repeat || a->src_extend == b->src_extend) && - (both_have_npot_repeat || a->mask_extend == b->mask_extend)); -} - -/* - * For GLES2 we use more complicated shaders to implement missing GL - * features. In this case we need more parameters to uniquely identify - * a shader (vs _cairo_gl_shader_cache_equal_desktop()). - */ -static cairo_bool_t -_cairo_gl_shader_cache_equal_gles2 (const void *key_a, const void *key_b) -{ - const cairo_shader_cache_entry_t *a = key_a; - const cairo_shader_cache_entry_t *b = key_b; - cairo_bool_t both_have_npot_repeat = - a->ctx->has_npot_repeat && b->ctx->has_npot_repeat; - - return (a->vertex == b->vertex && - a->src == b->src && - a->mask == b->mask && - a->dest == b->dest && - a->use_coverage == b->use_coverage && - a->in == b->in && - a->src_gl_filter == b->src_gl_filter && - a->src_border_fade == b->src_border_fade && - (both_have_npot_repeat || a->src_extend == b->src_extend) && - a->mask_gl_filter == b->mask_gl_filter && - a->mask_border_fade == b->mask_border_fade && - (both_have_npot_repeat || a->mask_extend == b->mask_extend)); -} - -static unsigned long -_cairo_gl_shader_cache_hash (const cairo_shader_cache_entry_t *entry) -{ - return (((uint32_t)entry->src << 24) | (entry->mask << 16) | (entry->dest << 8) | (entry->in << 1) | entry->use_coverage) ^ entry->vertex; -} - -static void -_cairo_gl_shader_cache_destroy (void *data) -{ - cairo_shader_cache_entry_t *entry = data; - - _cairo_gl_shader_fini (entry->ctx, &entry->shader); - if (entry->ctx->current_shader == &entry->shader) - entry->ctx->current_shader = NULL; - free (entry); -} - -static void -_cairo_gl_shader_init (cairo_gl_shader_t *shader) -{ - shader->fragment_shader = 0; - shader->program = 0; -} - -cairo_status_t -_cairo_gl_context_init_shaders (cairo_gl_context_t *ctx) -{ - static const char *fill_fs_source = - "#ifdef GL_ES\n" - "precision mediump float;\n" - "#endif\n" - "uniform vec4 color;\n" - "void main()\n" - "{\n" - " gl_FragColor = color;\n" - "}\n"; - cairo_status_t status; - - if (_cairo_gl_get_version () >= CAIRO_GL_VERSION_ENCODE (2, 0) || - (_cairo_gl_has_extension ("GL_ARB_shader_objects") && - _cairo_gl_has_extension ("GL_ARB_fragment_shader") && - _cairo_gl_has_extension ("GL_ARB_vertex_shader"))) { - ctx->has_shader_support = TRUE; - } else { - ctx->has_shader_support = FALSE; - fprintf (stderr, "Error: The cairo gl backend requires shader support!\n"); - return CAIRO_STATUS_DEVICE_ERROR; - } - - memset (ctx->vertex_shaders, 0, sizeof (ctx->vertex_shaders)); - - status = _cairo_cache_init (&ctx->shaders, - ctx->gl_flavor == CAIRO_GL_FLAVOR_DESKTOP ? - _cairo_gl_shader_cache_equal_desktop : - _cairo_gl_shader_cache_equal_gles2, - NULL, - _cairo_gl_shader_cache_destroy, - CAIRO_GL_MAX_SHADERS_PER_CONTEXT); - if (unlikely (status)) - return status; - - _cairo_gl_shader_init (&ctx->fill_rectangles_shader); - status = _cairo_gl_shader_compile_and_link (ctx, - &ctx->fill_rectangles_shader, - CAIRO_GL_VAR_NONE, - CAIRO_GL_VAR_NONE, - FALSE, - fill_fs_source); - if (unlikely (status)) - return status; - - return CAIRO_STATUS_SUCCESS; -} - -void -_cairo_gl_context_fini_shaders (cairo_gl_context_t *ctx) -{ - int i; - - for (i = 0; i < CAIRO_GL_VAR_TYPE_MAX; i++) { - if (ctx->vertex_shaders[i]) - ctx->dispatch.DeleteShader (ctx->vertex_shaders[i]); - } - - _cairo_gl_shader_fini(ctx, &ctx->fill_rectangles_shader); - _cairo_cache_fini (&ctx->shaders); -} - -void -_cairo_gl_shader_fini (cairo_gl_context_t *ctx, - cairo_gl_shader_t *shader) -{ - if (shader->fragment_shader) - ctx->dispatch.DeleteShader (shader->fragment_shader); - - if (shader->program) - ctx->dispatch.DeleteProgram (shader->program); -} - -static const char *operand_names[] = { "source", "mask", "dest" }; - -static cairo_gl_var_type_t -cairo_gl_operand_get_var_type (cairo_gl_operand_t *operand) -{ - switch (operand->type) { - default: - case CAIRO_GL_OPERAND_COUNT: - ASSERT_NOT_REACHED; - case CAIRO_GL_OPERAND_NONE: - case CAIRO_GL_OPERAND_CONSTANT: - return CAIRO_GL_VAR_NONE; - case CAIRO_GL_OPERAND_LINEAR_GRADIENT: - case CAIRO_GL_OPERAND_RADIAL_GRADIENT_A0: - case CAIRO_GL_OPERAND_RADIAL_GRADIENT_NONE: - case CAIRO_GL_OPERAND_RADIAL_GRADIENT_EXT: - return operand->gradient.texgen ? CAIRO_GL_VAR_TEXGEN : CAIRO_GL_VAR_TEXCOORDS; - case CAIRO_GL_OPERAND_TEXTURE: - return operand->texture.texgen ? CAIRO_GL_VAR_TEXGEN : CAIRO_GL_VAR_TEXCOORDS; - } -} - -static void -cairo_gl_shader_emit_variable (cairo_output_stream_t *stream, - cairo_gl_var_type_t type, - cairo_gl_tex_t name) -{ - switch (type) { - default: - ASSERT_NOT_REACHED; - case CAIRO_GL_VAR_NONE: - break; - case CAIRO_GL_VAR_TEXCOORDS: - _cairo_output_stream_printf (stream, - "attribute vec4 MultiTexCoord%d;\n" - "varying vec2 %s_texcoords;\n", - name, - operand_names[name]); - break; - case CAIRO_GL_VAR_TEXGEN: - _cairo_output_stream_printf (stream, - "uniform mat3 %s_texgen;\n" - "varying vec2 %s_texcoords;\n", - operand_names[name], - operand_names[name]); - break; - } -} - -static void -cairo_gl_shader_emit_vertex (cairo_output_stream_t *stream, - cairo_gl_var_type_t type, - cairo_gl_tex_t name) -{ - switch (type) { - default: - ASSERT_NOT_REACHED; - case CAIRO_GL_VAR_NONE: - break; - case CAIRO_GL_VAR_TEXCOORDS: - _cairo_output_stream_printf (stream, - " %s_texcoords = MultiTexCoord%d.xy;\n", - operand_names[name], name); - break; - - case CAIRO_GL_VAR_TEXGEN: - _cairo_output_stream_printf (stream, - " %s_texcoords = (%s_texgen * Vertex.xyw).xy;\n", - operand_names[name], operand_names[name]); - break; - } -} - -static void -cairo_gl_shader_dcl_coverage (cairo_output_stream_t *stream) -{ - _cairo_output_stream_printf (stream, "varying float coverage;\n"); -} - -static void -cairo_gl_shader_def_coverage (cairo_output_stream_t *stream) -{ - _cairo_output_stream_printf (stream, " coverage = Color.a;\n"); -} - -static cairo_status_t -cairo_gl_shader_get_vertex_source (cairo_gl_var_type_t src, - cairo_gl_var_type_t mask, - cairo_bool_t use_coverage, - cairo_gl_var_type_t dest, - char **out) -{ - cairo_output_stream_t *stream = _cairo_memory_stream_create (); - unsigned char *source; - unsigned long length; - cairo_status_t status; - - cairo_gl_shader_emit_variable (stream, src, CAIRO_GL_TEX_SOURCE); - cairo_gl_shader_emit_variable (stream, mask, CAIRO_GL_TEX_MASK); - if (use_coverage) - cairo_gl_shader_dcl_coverage (stream); - - _cairo_output_stream_printf (stream, - "attribute vec4 Vertex;\n" - "attribute vec4 Color;\n" - "uniform mat4 ModelViewProjectionMatrix;\n" - "void main()\n" - "{\n" - " gl_Position = ModelViewProjectionMatrix * Vertex;\n"); - - cairo_gl_shader_emit_vertex (stream, src, CAIRO_GL_TEX_SOURCE); - cairo_gl_shader_emit_vertex (stream, mask, CAIRO_GL_TEX_MASK); - if (use_coverage) - cairo_gl_shader_def_coverage (stream); - - _cairo_output_stream_write (stream, - "}\n\0", 3); - - status = _cairo_memory_stream_destroy (stream, &source, &length); - if (unlikely (status)) - return status; - - *out = (char *) source; - return CAIRO_STATUS_SUCCESS; -} - -/* - * Returns whether an operand needs a special border fade fragment shader - * to simulate the GL_CLAMP_TO_BORDER wrapping method that is missing in GLES2. - */ -static cairo_bool_t -_cairo_gl_shader_needs_border_fade (cairo_gl_operand_t *operand) -{ - cairo_extend_t extend =_cairo_gl_operand_get_extend (operand); - - return extend == CAIRO_EXTEND_NONE && - (operand->type == CAIRO_GL_OPERAND_TEXTURE || - operand->type == CAIRO_GL_OPERAND_LINEAR_GRADIENT || - operand->type == CAIRO_GL_OPERAND_RADIAL_GRADIENT_NONE || - operand->type == CAIRO_GL_OPERAND_RADIAL_GRADIENT_A0); -} - -static void -cairo_gl_shader_emit_color (cairo_output_stream_t *stream, - cairo_gl_context_t *ctx, - cairo_gl_operand_t *op, - cairo_gl_tex_t name) -{ - const char *namestr = operand_names[name]; - const char *rectstr = (ctx->tex_target == GL_TEXTURE_RECTANGLE ? "Rect" : ""); - - switch (op->type) { - case CAIRO_GL_OPERAND_COUNT: - default: - ASSERT_NOT_REACHED; - break; - case CAIRO_GL_OPERAND_NONE: - _cairo_output_stream_printf (stream, - "vec4 get_%s()\n" - "{\n" - " return vec4 (0, 0, 0, 1);\n" - "}\n", - namestr); - break; - case CAIRO_GL_OPERAND_CONSTANT: - _cairo_output_stream_printf (stream, - "uniform vec4 %s_constant;\n" - "vec4 get_%s()\n" - "{\n" - " return %s_constant;\n" - "}\n", - namestr, namestr, namestr); - break; - case CAIRO_GL_OPERAND_TEXTURE: - _cairo_output_stream_printf (stream, - "uniform sampler2D%s %s_sampler;\n" - "uniform vec2 %s_texdims;\n" - "varying vec2 %s_texcoords;\n" - "vec4 get_%s()\n" - "{\n", - rectstr, namestr, namestr, namestr, namestr); - if ((ctx->gl_flavor == CAIRO_GL_FLAVOR_ES3 || - ctx->gl_flavor == CAIRO_GL_FLAVOR_ES2) && - _cairo_gl_shader_needs_border_fade (op)) - { - _cairo_output_stream_printf (stream, - " vec2 border_fade = %s_border_fade (%s_texcoords, %s_texdims);\n" - " vec4 texel = texture2D%s (%s_sampler, %s_texcoords);\n" - " return texel * border_fade.x * border_fade.y;\n" - "}\n", - namestr, namestr, namestr, rectstr, namestr, namestr); - } - else - { - _cairo_output_stream_printf (stream, - " return texture2D%s (%s_sampler, %s_wrap (%s_texcoords));\n" - "}\n", - rectstr, namestr, namestr, namestr); - } - break; - case CAIRO_GL_OPERAND_LINEAR_GRADIENT: - _cairo_output_stream_printf (stream, - "varying vec2 %s_texcoords;\n" - "uniform vec2 %s_texdims;\n" - "uniform sampler2D%s %s_sampler;\n" - "\n" - "vec4 get_%s()\n" - "{\n", - namestr, namestr, rectstr, namestr, namestr); - if ((ctx->gl_flavor == CAIRO_GL_FLAVOR_ES3 || - ctx->gl_flavor == CAIRO_GL_FLAVOR_ES2) && - _cairo_gl_shader_needs_border_fade (op)) - { - _cairo_output_stream_printf (stream, - " float border_fade = %s_border_fade (%s_texcoords.x, %s_texdims.x);\n" - " vec4 texel = texture2D%s (%s_sampler, vec2 (%s_texcoords.x, 0.5));\n" - " return texel * border_fade;\n" - "}\n", - namestr, namestr, namestr, rectstr, namestr, namestr); - } - else - { - _cairo_output_stream_printf (stream, - " return texture2D%s (%s_sampler, %s_wrap (vec2 (%s_texcoords.x, 0.5)));\n" - "}\n", - rectstr, namestr, namestr, namestr); - } - break; - case CAIRO_GL_OPERAND_RADIAL_GRADIENT_A0: - _cairo_output_stream_printf (stream, - "varying vec2 %s_texcoords;\n" - "uniform vec2 %s_texdims;\n" - "uniform sampler2D%s %s_sampler;\n" - "uniform vec3 %s_circle_d;\n" - "uniform float %s_radius_0;\n" - "\n" - "vec4 get_%s()\n" - "{\n" - " vec3 pos = vec3 (%s_texcoords, %s_radius_0);\n" - " \n" - " float B = dot (pos, %s_circle_d);\n" - " float C = dot (pos, vec3 (pos.xy, -pos.z));\n" - " \n" - " float t = 0.5 * C / B;\n" - " float is_valid = step (-%s_radius_0, t * %s_circle_d.z);\n", - namestr, namestr, rectstr, namestr, namestr, namestr, namestr, - namestr, namestr, namestr, namestr, namestr); - if ((ctx->gl_flavor == CAIRO_GL_FLAVOR_ES3 || - ctx->gl_flavor == CAIRO_GL_FLAVOR_ES2) && - _cairo_gl_shader_needs_border_fade (op)) - { - _cairo_output_stream_printf (stream, - " float border_fade = %s_border_fade (t, %s_texdims.x);\n" - " vec4 texel = texture2D%s (%s_sampler, vec2 (t, 0.5));\n" - " return mix (vec4 (0.0), texel * border_fade, is_valid);\n" - "}\n", - namestr, namestr, rectstr, namestr); - } - else - { - _cairo_output_stream_printf (stream, - " vec4 texel = texture2D%s (%s_sampler, %s_wrap (vec2 (t, 0.5)));\n" - " return mix (vec4 (0.0), texel, is_valid);\n" - "}\n", - rectstr, namestr, namestr); - } - break; - case CAIRO_GL_OPERAND_RADIAL_GRADIENT_NONE: - _cairo_output_stream_printf (stream, - "varying vec2 %s_texcoords;\n" - "uniform vec2 %s_texdims;\n" - "uniform sampler2D%s %s_sampler;\n" - "uniform vec3 %s_circle_d;\n" - "uniform float %s_a;\n" - "uniform float %s_radius_0;\n" - "\n" - "vec4 get_%s()\n" - "{\n" - " vec3 pos = vec3 (%s_texcoords, %s_radius_0);\n" - " \n" - " float B = dot (pos, %s_circle_d);\n" - " float C = dot (pos, vec3 (pos.xy, -pos.z));\n" - " \n" - " float det = dot (vec2 (B, %s_a), vec2 (B, -C));\n" - " float sqrtdet = sqrt (abs (det));\n" - " vec2 t = (B + vec2 (sqrtdet, -sqrtdet)) / %s_a;\n" - " \n" - " vec2 is_valid = step (vec2 (0.0), t) * step (t, vec2(1.0));\n" - " float has_color = step (0., det) * max (is_valid.x, is_valid.y);\n" - " \n" - " float upper_t = mix (t.y, t.x, is_valid.x);\n", - namestr, namestr, rectstr, namestr, namestr, namestr, namestr, - namestr, namestr, namestr, namestr, namestr, namestr); - if ((ctx->gl_flavor == CAIRO_GL_FLAVOR_ES3 || - ctx->gl_flavor == CAIRO_GL_FLAVOR_ES2) && - _cairo_gl_shader_needs_border_fade (op)) - { - _cairo_output_stream_printf (stream, - " float border_fade = %s_border_fade (upper_t, %s_texdims.x);\n" - " vec4 texel = texture2D%s (%s_sampler, vec2 (upper_t, 0.5));\n" - " return mix (vec4 (0.0), texel * border_fade, has_color);\n" - "}\n", - namestr, namestr, rectstr, namestr); - } - else - { - _cairo_output_stream_printf (stream, - " vec4 texel = texture2D%s (%s_sampler, %s_wrap (vec2(upper_t, 0.5)));\n" - " return mix (vec4 (0.0), texel, has_color);\n" - "}\n", - rectstr, namestr, namestr); - } - break; - case CAIRO_GL_OPERAND_RADIAL_GRADIENT_EXT: - _cairo_output_stream_printf (stream, - "varying vec2 %s_texcoords;\n" - "uniform sampler2D%s %s_sampler;\n" - "uniform vec3 %s_circle_d;\n" - "uniform float %s_a;\n" - "uniform float %s_radius_0;\n" - "\n" - "vec4 get_%s()\n" - "{\n" - " vec3 pos = vec3 (%s_texcoords, %s_radius_0);\n" - " \n" - " float B = dot (pos, %s_circle_d);\n" - " float C = dot (pos, vec3 (pos.xy, -pos.z));\n" - " \n" - " float det = dot (vec2 (B, %s_a), vec2 (B, -C));\n" - " float sqrtdet = sqrt (abs (det));\n" - " vec2 t = (B + vec2 (sqrtdet, -sqrtdet)) / %s_a;\n" - " \n" - " vec2 is_valid = step (vec2 (-%s_radius_0), t * %s_circle_d.z);\n" - " float has_color = step (0., det) * max (is_valid.x, is_valid.y);\n" - " \n" - " float upper_t = mix (t.y, t.x, is_valid.x);\n" - " vec4 texel = texture2D%s (%s_sampler, %s_wrap (vec2(upper_t, 0.5)));\n" - " return mix (vec4 (0.0), texel, has_color);\n" - "}\n", - namestr, rectstr, namestr, namestr, namestr, namestr, - namestr, namestr, namestr, namestr, namestr, - namestr, namestr, namestr, rectstr, namestr, namestr); - break; - } -} - -/* - * Emits the border fade functions used by an operand. - * - * If bilinear filtering is used, the emitted function performs a linear - * fade to transparency effect in the intervals [-1/2n, 1/2n] and - * [1 - 1/2n, 1 + 1/2n] (n: texture size). - * - * If nearest filtering is used, the emitted function just returns - * 0.0 for all values outside [0, 1). - */ -static void -_cairo_gl_shader_emit_border_fade (cairo_output_stream_t *stream, - cairo_gl_operand_t *operand, - cairo_gl_tex_t name) -{ - const char *namestr = operand_names[name]; - GLint gl_filter = _cairo_gl_operand_get_gl_filter (operand); - - /* 2D version */ - _cairo_output_stream_printf (stream, - "vec2 %s_border_fade (vec2 coords, vec2 dims)\n" - "{\n", - namestr); - - if (gl_filter == GL_LINEAR) - _cairo_output_stream_printf (stream, - " return clamp(-abs(dims * (coords - 0.5)) + (dims + vec2(1.0)) * 0.5, 0.0, 1.0);\n"); - else - _cairo_output_stream_printf (stream, - " bvec2 in_tex1 = greaterThanEqual (coords, vec2 (0.0));\n" - " bvec2 in_tex2 = lessThan (coords, vec2 (1.0));\n" - " return vec2 (float (all (in_tex1) && all (in_tex2)));\n"); - - _cairo_output_stream_printf (stream, "}\n"); - - /* 1D version */ - _cairo_output_stream_printf (stream, - "float %s_border_fade (float x, float dim)\n" - "{\n", - namestr); - if (gl_filter == GL_LINEAR) - _cairo_output_stream_printf (stream, - " return clamp(-abs(dim * (x - 0.5)) + (dim + 1.0) * 0.5, 0.0, 1.0);\n"); - else - _cairo_output_stream_printf (stream, - " bool in_tex = x >= 0.0 && x < 1.0;\n" - " return float (in_tex);\n"); - - _cairo_output_stream_printf (stream, "}\n"); -} - -/* - * Emits the wrap function used by an operand. - * - * In OpenGL ES 2.0, repeat wrap modes (GL_REPEAT and GL_MIRRORED REPEAT) are - * only available for NPOT textures if the GL_OES_texture_npot is supported. - * If GL_OES_texture_npot is not supported, we need to implement the wrapping - * functionality in the shader. - */ -static void -_cairo_gl_shader_emit_wrap (cairo_gl_context_t *ctx, - cairo_output_stream_t *stream, - cairo_gl_operand_t *operand, - cairo_gl_tex_t name) -{ - const char *namestr = operand_names[name]; - cairo_extend_t extend = _cairo_gl_operand_get_extend (operand); - - _cairo_output_stream_printf (stream, - "vec2 %s_wrap(vec2 coords)\n" - "{\n", - namestr); - - if (! ctx->has_npot_repeat && - (extend == CAIRO_EXTEND_REPEAT || extend == CAIRO_EXTEND_REFLECT)) - { - if (extend == CAIRO_EXTEND_REPEAT) { - _cairo_output_stream_printf (stream, - " return fract(coords);\n"); - } else { /* CAIRO_EXTEND_REFLECT */ - _cairo_output_stream_printf (stream, - " return mix(fract(coords), 1.0 - fract(coords), floor(mod(coords, 2.0)));\n"); - } - } - else - { - _cairo_output_stream_printf (stream, " return coords;\n"); - } - - _cairo_output_stream_printf (stream, "}\n"); -} - -static cairo_status_t -cairo_gl_shader_get_fragment_source (cairo_gl_context_t *ctx, - cairo_gl_shader_in_t in, - cairo_gl_operand_t *src, - cairo_gl_operand_t *mask, - cairo_bool_t use_coverage, - cairo_gl_operand_type_t dest_type, - char **out) -{ - cairo_output_stream_t *stream = _cairo_memory_stream_create (); - unsigned char *source; - unsigned long length; - cairo_status_t status; - const char *coverage_str; - - _cairo_output_stream_printf (stream, - "#ifdef GL_ES\n" - "precision mediump float;\n" - "#endif\n"); - - _cairo_gl_shader_emit_wrap (ctx, stream, src, CAIRO_GL_TEX_SOURCE); - _cairo_gl_shader_emit_wrap (ctx, stream, mask, CAIRO_GL_TEX_MASK); - - if (ctx->gl_flavor == CAIRO_GL_FLAVOR_ES3 || - ctx->gl_flavor == CAIRO_GL_FLAVOR_ES2) { - if (_cairo_gl_shader_needs_border_fade (src)) - _cairo_gl_shader_emit_border_fade (stream, src, CAIRO_GL_TEX_SOURCE); - if (_cairo_gl_shader_needs_border_fade (mask)) - _cairo_gl_shader_emit_border_fade (stream, mask, CAIRO_GL_TEX_MASK); - } - - cairo_gl_shader_emit_color (stream, ctx, src, CAIRO_GL_TEX_SOURCE); - cairo_gl_shader_emit_color (stream, ctx, mask, CAIRO_GL_TEX_MASK); - - coverage_str = ""; - if (use_coverage) { - _cairo_output_stream_printf (stream, "varying float coverage;\n"); - coverage_str = " * coverage"; - } - - _cairo_output_stream_printf (stream, - "void main()\n" - "{\n"); - switch (in) { - case CAIRO_GL_SHADER_IN_COUNT: - default: - ASSERT_NOT_REACHED; - case CAIRO_GL_SHADER_IN_NORMAL: - _cairo_output_stream_printf (stream, - " gl_FragColor = get_source() * get_mask().a%s;\n", - coverage_str); - break; - case CAIRO_GL_SHADER_IN_CA_SOURCE: - _cairo_output_stream_printf (stream, - " gl_FragColor = get_source() * get_mask()%s;\n", - coverage_str); - break; - case CAIRO_GL_SHADER_IN_CA_SOURCE_ALPHA: - _cairo_output_stream_printf (stream, - " gl_FragColor = get_source().a * get_mask()%s;\n", - coverage_str); - break; - } - - _cairo_output_stream_write (stream, - "}\n\0", 3); - - status = _cairo_memory_stream_destroy (stream, &source, &length); - if (unlikely (status)) - return status; - - *out = (char *) source; - return CAIRO_STATUS_SUCCESS; -} - -static void -compile_shader (cairo_gl_context_t *ctx, - GLuint *shader, - GLenum type, - const char *source) -{ - cairo_gl_dispatch_t *dispatch = &ctx->dispatch; - GLint success, log_size, num_chars; - char *log; - - *shader = dispatch->CreateShader (type); - dispatch->ShaderSource (*shader, 1, &source, 0); - dispatch->CompileShader (*shader); - dispatch->GetShaderiv (*shader, GL_COMPILE_STATUS, &success); - - if (success) - return; - - dispatch->GetShaderiv (*shader, GL_INFO_LOG_LENGTH, &log_size); - if (log_size < 0) { - printf ("OpenGL shader compilation failed.\n"); - ASSERT_NOT_REACHED; - return; - } - - log = _cairo_malloc (log_size + 1); - dispatch->GetShaderInfoLog (*shader, log_size, &num_chars, log); - log[num_chars] = '\0'; - - printf ("OpenGL shader compilation failed. Shader:\n%s\n", source); - printf ("OpenGL compilation log:\n%s\n", log); - - free (log); - ASSERT_NOT_REACHED; -} - -static void -link_shader_program (cairo_gl_context_t *ctx, - GLuint *program, - GLuint vert, - GLuint frag) -{ - cairo_gl_dispatch_t *dispatch = &ctx->dispatch; - GLint success, log_size, num_chars; - char *log; - - *program = dispatch->CreateProgram (); - dispatch->AttachShader (*program, vert); - dispatch->AttachShader (*program, frag); - - dispatch->BindAttribLocation (*program, CAIRO_GL_VERTEX_ATTRIB_INDEX, - "Vertex"); - dispatch->BindAttribLocation (*program, CAIRO_GL_COLOR_ATTRIB_INDEX, - "Color"); - dispatch->BindAttribLocation (*program, CAIRO_GL_TEXCOORD0_ATTRIB_INDEX, - "MultiTexCoord0"); - dispatch->BindAttribLocation (*program, CAIRO_GL_TEXCOORD1_ATTRIB_INDEX, - "MultiTexCoord1"); - - dispatch->LinkProgram (*program); - dispatch->GetProgramiv (*program, GL_LINK_STATUS, &success); - if (success) - return; - - dispatch->GetProgramiv (*program, GL_INFO_LOG_LENGTH, &log_size); - if (log_size < 0) { - printf ("OpenGL shader link failed.\n"); - ASSERT_NOT_REACHED; - return; - } - - log = _cairo_malloc (log_size + 1); - dispatch->GetProgramInfoLog (*program, log_size, &num_chars, log); - log[num_chars] = '\0'; - - printf ("OpenGL shader link failed:\n%s\n", log); - free (log); - ASSERT_NOT_REACHED; -} - -static GLint -_cairo_gl_get_op_uniform_location(cairo_gl_context_t *ctx, - cairo_gl_shader_t *shader, - cairo_gl_tex_t tex_unit, - const char *suffix) -{ - cairo_gl_dispatch_t *dispatch = &ctx->dispatch; - char uniform_name[100]; - const char *unit_name[2] = { "source", "mask" }; - - snprintf (uniform_name, sizeof (uniform_name), "%s_%s", - unit_name[tex_unit], suffix); - - return dispatch->GetUniformLocation (shader->program, uniform_name); -} - -static cairo_status_t -_cairo_gl_shader_compile_and_link (cairo_gl_context_t *ctx, - cairo_gl_shader_t *shader, - cairo_gl_var_type_t src, - cairo_gl_var_type_t mask, - cairo_bool_t use_coverage, - const char *fragment_text) -{ - cairo_gl_dispatch_t *dispatch = &ctx->dispatch; - unsigned int vertex_shader; - cairo_status_t status; - int i; - - assert (shader->program == 0); - - vertex_shader = cairo_gl_var_type_hash (src, mask, use_coverage, - CAIRO_GL_VAR_NONE); - if (ctx->vertex_shaders[vertex_shader] == 0) { - char *source; - - status = cairo_gl_shader_get_vertex_source (src, - mask, - use_coverage, - CAIRO_GL_VAR_NONE, - &source); - if (unlikely (status)) - goto FAILURE; - - compile_shader (ctx, &ctx->vertex_shaders[vertex_shader], - GL_VERTEX_SHADER, source); - free (source); - } - - compile_shader (ctx, &shader->fragment_shader, - GL_FRAGMENT_SHADER, fragment_text); - - link_shader_program (ctx, &shader->program, - ctx->vertex_shaders[vertex_shader], - shader->fragment_shader); - - shader->mvp_location = - dispatch->GetUniformLocation (shader->program, - "ModelViewProjectionMatrix"); - - for (i = 0; i < 2; i++) { - shader->constant_location[i] = - _cairo_gl_get_op_uniform_location (ctx, shader, i, "constant"); - shader->a_location[i] = - _cairo_gl_get_op_uniform_location (ctx, shader, i, "a"); - shader->circle_d_location[i] = - _cairo_gl_get_op_uniform_location (ctx, shader, i, "circle_d"); - shader->radius_0_location[i] = - _cairo_gl_get_op_uniform_location (ctx, shader, i, "radius_0"); - shader->texdims_location[i] = - _cairo_gl_get_op_uniform_location (ctx, shader, i, "texdims"); - shader->texgen_location[i] = - _cairo_gl_get_op_uniform_location (ctx, shader, i, "texgen"); - } - - return CAIRO_STATUS_SUCCESS; - - FAILURE: - _cairo_gl_shader_fini (ctx, shader); - shader->fragment_shader = 0; - shader->program = 0; - - return status; -} - -/* We always bind the source to texture unit 0 if present, and mask to - * texture unit 1 if present, so we can just initialize these once at - * compile time. - */ -static cairo_status_t -_cairo_gl_shader_set_samplers (cairo_gl_context_t *ctx, - cairo_gl_shader_t *shader) -{ - cairo_gl_dispatch_t *dispatch = &ctx->dispatch; - GLint location; - GLint saved_program; - - /* We have to save/restore the current program because we might be - * asked for a different program while a shader is bound. This shouldn't - * be a performance issue, since this is only called once per compile. - */ - glGetIntegerv (GL_CURRENT_PROGRAM, &saved_program); - dispatch->UseProgram (shader->program); - - location = dispatch->GetUniformLocation (shader->program, "source_sampler"); - if (location != -1) { - dispatch->Uniform1i (location, CAIRO_GL_TEX_SOURCE); - } - - location = dispatch->GetUniformLocation (shader->program, "mask_sampler"); - if (location != -1) { - dispatch->Uniform1i (location, CAIRO_GL_TEX_MASK); - } - if(_cairo_gl_get_error()) return CAIRO_STATUS_DEVICE_ERROR; - dispatch->UseProgram (saved_program); - /* Pop and ignore a possible gl-error when restoring the previous program. - * It may be that being selected in the gl-context was the last reference - * to the shader. - */ - _cairo_gl_get_error(); - return CAIRO_STATUS_SUCCESS; -} - -void -_cairo_gl_shader_bind_float (cairo_gl_context_t *ctx, - GLint location, - float value) -{ - cairo_gl_dispatch_t *dispatch = &ctx->dispatch; - assert (location != -1); - dispatch->Uniform1f (location, value); -} - -void -_cairo_gl_shader_bind_vec2 (cairo_gl_context_t *ctx, - GLint location, - float value0, - float value1) -{ - cairo_gl_dispatch_t *dispatch = &ctx->dispatch; - assert (location != -1); - dispatch->Uniform2f (location, value0, value1); -} - -void -_cairo_gl_shader_bind_vec3 (cairo_gl_context_t *ctx, - GLint location, - float value0, - float value1, - float value2) -{ - cairo_gl_dispatch_t *dispatch = &ctx->dispatch; - assert (location != -1); - dispatch->Uniform3f (location, value0, value1, value2); -} - -void -_cairo_gl_shader_bind_vec4 (cairo_gl_context_t *ctx, - GLint location, - float value0, float value1, - float value2, float value3) -{ - cairo_gl_dispatch_t *dispatch = &ctx->dispatch; - assert (location != -1); - dispatch->Uniform4f (location, value0, value1, value2, value3); -} - -void -_cairo_gl_shader_bind_matrix (cairo_gl_context_t *ctx, - GLint location, - const cairo_matrix_t* m) -{ - cairo_gl_dispatch_t *dispatch = &ctx->dispatch; - float gl_m[9] = { - m->xx, m->yx, 0, - m->xy, m->yy, 0, - m->x0, m->y0, 1 - }; - assert (location != -1); - dispatch->UniformMatrix3fv (location, 1, GL_FALSE, gl_m); -} - -void -_cairo_gl_shader_bind_matrix4f (cairo_gl_context_t *ctx, - GLint location, GLfloat* gl_m) -{ - cairo_gl_dispatch_t *dispatch = &ctx->dispatch; - assert (location != -1); - dispatch->UniformMatrix4fv (location, 1, GL_FALSE, gl_m); -} - -void -_cairo_gl_set_shader (cairo_gl_context_t *ctx, - cairo_gl_shader_t *shader) -{ - if (ctx->current_shader == shader) - return; - - if (shader) - ctx->dispatch.UseProgram (shader->program); - else - ctx->dispatch.UseProgram (0); - - ctx->current_shader = shader; -} - -cairo_status_t -_cairo_gl_get_shader_by_type (cairo_gl_context_t *ctx, - cairo_gl_operand_t *source, - cairo_gl_operand_t *mask, - cairo_bool_t use_coverage, - cairo_gl_shader_in_t in, - cairo_gl_shader_t **shader) -{ - cairo_shader_cache_entry_t lookup, *entry; - char *fs_source; - cairo_status_t status; - - lookup.ctx = ctx; - - lookup.vertex = cairo_gl_var_type_hash (cairo_gl_operand_get_var_type (source), - cairo_gl_operand_get_var_type (mask), - use_coverage, - CAIRO_GL_VAR_NONE); - - lookup.src = source->type; - lookup.mask = mask->type; - lookup.dest = CAIRO_GL_OPERAND_NONE; - lookup.use_coverage = use_coverage; - lookup.in = in; - lookup.src_gl_filter = _cairo_gl_operand_get_gl_filter (source); - lookup.src_border_fade = _cairo_gl_shader_needs_border_fade (source); - lookup.src_extend = _cairo_gl_operand_get_extend (source); - lookup.mask_gl_filter = _cairo_gl_operand_get_gl_filter (mask); - lookup.mask_border_fade = _cairo_gl_shader_needs_border_fade (mask); - lookup.mask_extend = _cairo_gl_operand_get_extend (mask); - lookup.base.hash = _cairo_gl_shader_cache_hash (&lookup); - lookup.base.size = 1; - - entry = _cairo_cache_lookup (&ctx->shaders, &lookup.base); - if (entry) { - assert (entry->shader.program); - *shader = &entry->shader; - return CAIRO_STATUS_SUCCESS; - } - - status = cairo_gl_shader_get_fragment_source (ctx, - in, - source, - mask, - use_coverage, - CAIRO_GL_OPERAND_NONE, - &fs_source); - if (unlikely (status)) - return status; - - entry = _cairo_malloc (sizeof (cairo_shader_cache_entry_t)); - if (unlikely (entry == NULL)) { - free (fs_source); - return _cairo_error (CAIRO_STATUS_NO_MEMORY); - } - - memcpy (entry, &lookup, sizeof (cairo_shader_cache_entry_t)); - - entry->ctx = ctx; - _cairo_gl_shader_init (&entry->shader); - status = _cairo_gl_shader_compile_and_link (ctx, - &entry->shader, - cairo_gl_operand_get_var_type (source), - cairo_gl_operand_get_var_type (mask), - use_coverage, - fs_source); - free (fs_source); - - if (unlikely (status)) { - free (entry); - return status; - } - - status = _cairo_gl_shader_set_samplers (ctx, &entry->shader); - if (unlikely (status)) { - _cairo_gl_shader_fini (ctx, &entry->shader); - free (entry); - return status; - } - - status = _cairo_cache_insert (&ctx->shaders, &entry->base); - if (unlikely (status)) { - _cairo_gl_shader_fini (ctx, &entry->shader); - free (entry); - return status; - } - - *shader = &entry->shader; - - return CAIRO_STATUS_SUCCESS; -} diff --git a/gfx/cairo/cairo/src/cairo-gl-source.c b/gfx/cairo/cairo/src/cairo-gl-source.c deleted file mode 100644 index 7e0ee4a826..0000000000 --- a/gfx/cairo/cairo/src/cairo-gl-source.c +++ /dev/null @@ -1,113 +0,0 @@ -/* cairo - a vector graphics library with display and print output - * - * Copyright © 2011 Intel Corporation - * - * This library is free software; you can redistribute it and/or - * modify it either under the terms of the GNU Lesser General Public - * License version 2.1 as published by the Free Software Foundation - * (the "LGPL") or, at your option, under the terms of the Mozilla - * Public License Version 1.1 (the "MPL"). If you do not alter this - * notice, a recipient may use your version of this file under either - * the MPL or the LGPL. - * - * You should have received a copy of the LGPL along with this library - * in the file COPYING-LGPL-2.1; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Suite 500, Boston, MA 02110-1335, 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): - * Chris Wilson <chris@chris-wilson.co.uk> - */ - -#include "cairoint.h" - -#include "cairo-gl-private.h" - -#include "cairo-surface-backend-private.h" - -static cairo_status_t -_cairo_gl_source_finish (void *abstract_surface) -{ - cairo_gl_source_t *source = abstract_surface; - - _cairo_gl_operand_destroy (&source->operand); - return CAIRO_STATUS_SUCCESS; -} - -static const cairo_surface_backend_t cairo_gl_source_backend = { - CAIRO_SURFACE_TYPE_GL, - _cairo_gl_source_finish, - NULL, /* read-only wrapper */ -}; - -cairo_surface_t * -_cairo_gl_pattern_to_source (cairo_surface_t *dst, - const cairo_pattern_t *pattern, - cairo_bool_t is_mask, - const cairo_rectangle_int_t *extents, - const cairo_rectangle_int_t *sample, - int *src_x, int *src_y) -{ - cairo_gl_source_t *source; - cairo_int_status_t status; - - TRACE ((stderr, "%s\n", __FUNCTION__)); - if (pattern == NULL) - return _cairo_gl_white_source (); - - source = _cairo_malloc (sizeof (*source)); - if (unlikely (source == NULL)) - return _cairo_surface_create_in_error (_cairo_error (CAIRO_STATUS_NO_MEMORY)); - - _cairo_surface_init (&source->base, - &cairo_gl_source_backend, - NULL, /* device */ - CAIRO_CONTENT_COLOR_ALPHA, - FALSE); /* is_vector */ - - *src_x = *src_y = 0; - status = _cairo_gl_operand_init (&source->operand, pattern, - (cairo_gl_surface_t *)dst, - sample, extents, - FALSE); - if (unlikely (status)) { - cairo_surface_destroy (&source->base); - return _cairo_surface_create_in_error (status); - } - - return &source->base; -} - -cairo_surface_t * -_cairo_gl_white_source (void) -{ - cairo_gl_source_t *source; - - source = _cairo_malloc (sizeof (*source)); - if (unlikely (source == NULL)) - return _cairo_surface_create_in_error (_cairo_error (CAIRO_STATUS_NO_MEMORY)); - - _cairo_surface_init (&source->base, - &cairo_gl_source_backend, - NULL, /* device */ - CAIRO_CONTENT_COLOR_ALPHA, - FALSE); /* is_vector */ - - _cairo_gl_solid_operand_init (&source->operand, CAIRO_COLOR_WHITE); - - return &source->base; -} diff --git a/gfx/cairo/cairo/src/cairo-gl-spans-compositor.c b/gfx/cairo/cairo/src/cairo-gl-spans-compositor.c deleted file mode 100644 index 0a4538a047..0000000000 --- a/gfx/cairo/cairo/src/cairo-gl-spans-compositor.c +++ /dev/null @@ -1,556 +0,0 @@ -/* cairo - a vector graphics library with display and print output - * - * Copyright © 2009 Eric Anholt - * Copyright © 2009 Chris Wilson - * Copyright © 2005,2010 Red Hat, Inc - * Copyright © 2011 Intel Corporation - * - * This library is free software; you can redistribute it and/or - * modify it either under the terms of the GNU Lesser General Public - * License version 2.1 as published by the Free Software Foundation - * (the "LGPL") or, at your option, under the terms of the Mozilla - * Public License Version 1.1 (the "MPL"). If you do not alter this - * notice, a recipient may use your version of this file under either - * the MPL or the LGPL. - * - * You should have received a copy of the LGPL along with this library - * in the file COPYING-LGPL-2.1; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Suite 500, Boston, MA 02110-1335, 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): - * Benjamin Otte <otte@gnome.org> - * Carl Worth <cworth@cworth.org> - * Chris Wilson <chris@chris-wilson.co.uk> - * Eric Anholt <eric@anholt.net> - */ - -#include "cairoint.h" - -#include "cairo-gl-private.h" - -#include "cairo-composite-rectangles-private.h" -#include "cairo-compositor-private.h" -#include "cairo-default-context-private.h" -#include "cairo-error-private.h" -#include "cairo-image-surface-private.h" -#include "cairo-spans-compositor-private.h" -#include "cairo-surface-backend-private.h" - -typedef struct _cairo_gl_span_renderer { - cairo_span_renderer_t base; - - cairo_gl_composite_t setup; - double opacity; - - cairo_gl_emit_span_t emit; - - int xmin, xmax; - int ymin, ymax; - - cairo_gl_context_t *ctx; -} cairo_gl_span_renderer_t; - -static cairo_status_t -_cairo_gl_bounded_opaque_spans (void *abstract_renderer, - int y, int height, - const cairo_half_open_span_t *spans, - unsigned num_spans) -{ - cairo_gl_span_renderer_t *r = abstract_renderer; - cairo_gl_emit_span_t emit = r->emit; - - if (num_spans == 0) - return CAIRO_STATUS_SUCCESS; - - do { - if (spans[0].coverage) { - emit (r->ctx, - spans[0].x, y, - spans[1].x, y + height, - spans[0].coverage); - } - - spans++; - } while (--num_spans > 1); - - return CAIRO_STATUS_SUCCESS; -} - -static cairo_status_t -_cairo_gl_bounded_spans (void *abstract_renderer, - int y, int height, - const cairo_half_open_span_t *spans, - unsigned num_spans) -{ - cairo_gl_span_renderer_t *r = abstract_renderer; - cairo_gl_emit_span_t emit = r->emit; - - if (num_spans == 0) - return CAIRO_STATUS_SUCCESS; - - do { - if (spans[0].coverage) { - emit (r->ctx, - spans[0].x, y, - spans[1].x, y + height, - r->opacity * spans[0].coverage); - } - - spans++; - } while (--num_spans > 1); - - return CAIRO_STATUS_SUCCESS; -} - -static cairo_status_t -_cairo_gl_unbounded_spans (void *abstract_renderer, - int y, int height, - const cairo_half_open_span_t *spans, - unsigned num_spans) -{ - cairo_gl_span_renderer_t *r = abstract_renderer; - cairo_gl_emit_span_t emit = r->emit; - - if (y > r->ymin) { - emit (r->ctx, - r->xmin, r->ymin, - r->xmax, y, - 0); - } - - if (num_spans == 0) { - emit (r->ctx, - r->xmin, y, - r->xmax, y + height, - 0); - } else { - if (spans[0].x != r->xmin) { - emit (r->ctx, - r->xmin, y, - spans[0].x, y + height, - 0); - } - - do { - emit (r->ctx, - spans[0].x, y, - spans[1].x, y + height, - r->opacity * spans[0].coverage); - spans++; - } while (--num_spans > 1); - - if (spans[0].x != r->xmax) { - emit (r->ctx, - spans[0].x, y, - r->xmax, y + height, - 0); - } - } - - r->ymin = y + height; - return CAIRO_STATUS_SUCCESS; -} - -/* XXX */ -static cairo_status_t -_cairo_gl_clipped_spans (void *abstract_renderer, - int y, int height, - const cairo_half_open_span_t *spans, - unsigned num_spans) -{ - cairo_gl_span_renderer_t *r = abstract_renderer; - cairo_gl_emit_span_t emit = r->emit; - - if (y > r->ymin) { - emit (r->ctx, - r->xmin, r->ymin, - r->xmax, y, - 0); - } - - if (num_spans == 0) { - emit (r->ctx, - r->xmin, y, - r->xmax, y + height, - 0); - } else { - if (spans[0].x != r->xmin) { - emit (r->ctx, - r->xmin, y, - spans[0].x, y + height, - 0); - } - - do { - emit (r->ctx, - spans[0].x, y, - spans[1].x, y + height, - r->opacity * spans[0].coverage); - spans++; - } while (--num_spans > 1); - - if (spans[0].x != r->xmax) { - emit (r->ctx, - spans[0].x, y, - r->xmax, y + height, - 0); - } - } - - r->ymin = y + height; - return CAIRO_STATUS_SUCCESS; -} - -static cairo_status_t -_cairo_gl_finish_unbounded_spans (void *abstract_renderer) -{ - cairo_gl_span_renderer_t *r = abstract_renderer; - cairo_gl_emit_span_t emit = r->emit; - - if (r->ymax > r->ymin) { - emit (r->ctx, - r->xmin, r->ymin, - r->xmax, r->ymax, - 0); - } - - return _cairo_gl_context_release (r->ctx, CAIRO_STATUS_SUCCESS); -} - -static cairo_status_t -_cairo_gl_finish_bounded_spans (void *abstract_renderer) -{ - cairo_gl_span_renderer_t *r = abstract_renderer; - - return _cairo_gl_context_release (r->ctx, CAIRO_STATUS_SUCCESS); -} - -static void -emit_aligned_boxes (cairo_gl_context_t *ctx, - const cairo_boxes_t *boxes) -{ - const struct _cairo_boxes_chunk *chunk; - cairo_gl_emit_rect_t emit = _cairo_gl_context_choose_emit_rect (ctx); - int i; - - TRACE ((stderr, "%s: num_boxes=%d\n", __FUNCTION__, boxes->num_boxes)); - for (chunk = &boxes->chunks; chunk; chunk = chunk->next) { - for (i = 0; i < chunk->count; i++) { - int x1 = _cairo_fixed_integer_part (chunk->base[i].p1.x); - int y1 = _cairo_fixed_integer_part (chunk->base[i].p1.y); - int x2 = _cairo_fixed_integer_part (chunk->base[i].p2.x); - int y2 = _cairo_fixed_integer_part (chunk->base[i].p2.y); - emit (ctx, x1, y1, x2, y2); - } - } -} - -static cairo_int_status_t -fill_boxes (void *_dst, - cairo_operator_t op, - const cairo_color_t *color, - cairo_boxes_t *boxes) -{ - cairo_gl_composite_t setup; - cairo_gl_context_t *ctx; - cairo_int_status_t status; - - TRACE ((stderr, "%s\n", __FUNCTION__)); - status = _cairo_gl_composite_init (&setup, op, _dst, FALSE); - if (unlikely (status)) - goto FAIL; - - _cairo_gl_composite_set_solid_source (&setup, color); - - status = _cairo_gl_composite_begin (&setup, &ctx); - if (unlikely (status)) - goto FAIL; - - emit_aligned_boxes (ctx, boxes); - status = _cairo_gl_context_release (ctx, CAIRO_STATUS_SUCCESS); - -FAIL: - _cairo_gl_composite_fini (&setup); - return status; -} - -static cairo_int_status_t -draw_image_boxes (void *_dst, - cairo_image_surface_t *image, - cairo_boxes_t *boxes, - int dx, int dy) -{ - cairo_gl_surface_t *dst = _dst; - struct _cairo_boxes_chunk *chunk; - int i; - - for (chunk = &boxes->chunks; chunk; chunk = chunk->next) { - for (i = 0; i < chunk->count; i++) { - cairo_box_t *b = &chunk->base[i]; - int x = _cairo_fixed_integer_part (b->p1.x); - int y = _cairo_fixed_integer_part (b->p1.y); - int w = _cairo_fixed_integer_part (b->p2.x) - x; - int h = _cairo_fixed_integer_part (b->p2.y) - y; - cairo_status_t status; - - status = _cairo_gl_surface_draw_image (dst, image, - x + dx, y + dy, - w, h, - x, y, TRUE); - if (unlikely (status)) - return status; - } - } - - return CAIRO_STATUS_SUCCESS; -} - -static cairo_int_status_t copy_boxes (void *_dst, - cairo_surface_t *_src, - cairo_boxes_t *boxes, - const cairo_rectangle_int_t *extents, - int dx, int dy) -{ - cairo_gl_surface_t *dst = _dst; - cairo_gl_surface_t *src = (cairo_gl_surface_t *)_src; - cairo_gl_composite_t setup; - cairo_gl_context_t *ctx; - cairo_int_status_t status; - - TRACE ((stderr, "%s\n", __FUNCTION__)); - if (! _cairo_gl_surface_is_texture (src)) - return CAIRO_INT_STATUS_UNSUPPORTED; - - if (src->base.device != dst->base.device) - return CAIRO_INT_STATUS_UNSUPPORTED; - - status = _cairo_gl_composite_init (&setup, CAIRO_OPERATOR_SOURCE, _dst, FALSE); - if (unlikely (status)) - goto FAIL; - - _cairo_gl_composite_set_source_operand (&setup, &src->operand); - _cairo_gl_operand_translate (&setup.src, -dx, -dy); - - status = _cairo_gl_composite_begin (&setup, &ctx); - if (unlikely (status)) - goto FAIL; - - emit_aligned_boxes (ctx, boxes); - status = _cairo_gl_context_release (ctx, CAIRO_STATUS_SUCCESS); - -FAIL: - _cairo_gl_composite_fini (&setup); - return status; -} - -static cairo_int_status_t -composite_boxes (void *_dst, - cairo_operator_t op, - cairo_surface_t *abstract_src, - cairo_surface_t *abstract_mask, - int src_x, - int src_y, - int mask_x, - int mask_y, - int dst_x, - int dst_y, - cairo_boxes_t *boxes, - const cairo_rectangle_int_t *extents) -{ - cairo_gl_composite_t setup; - cairo_gl_context_t *ctx; - cairo_int_status_t status; - cairo_gl_operand_t tmp_operand; - cairo_gl_operand_t *src_operand; - - TRACE ((stderr, "%s mask=(%d,%d), dst=(%d, %d)\n", __FUNCTION__, - mask_x, mask_y, dst_x, dst_y)); - - if (abstract_mask) { - if (op == CAIRO_OPERATOR_CLEAR) { - _cairo_gl_solid_operand_init (&tmp_operand, CAIRO_COLOR_WHITE); - src_operand = &tmp_operand; - op = CAIRO_OPERATOR_DEST_OUT; - } else if (op == CAIRO_OPERATOR_SOURCE) { - /* requires a LERP in the shader between dest and source */ - return CAIRO_INT_STATUS_UNSUPPORTED; - } else - src_operand = source_to_operand (abstract_src); - } else - src_operand = source_to_operand (abstract_src); - - status = _cairo_gl_composite_init (&setup, op, _dst, FALSE); - if (unlikely (status)) - goto FAIL; - - _cairo_gl_composite_set_source_operand (&setup, - src_operand); - _cairo_gl_operand_translate (&setup.src, -src_x, -src_y); - - _cairo_gl_composite_set_mask_operand (&setup, - source_to_operand (abstract_mask)); - _cairo_gl_operand_translate (&setup.mask, -mask_x, -mask_y); - - status = _cairo_gl_composite_begin (&setup, &ctx); - if (unlikely (status)) - goto FAIL; - - emit_aligned_boxes (ctx, boxes); - status = _cairo_gl_context_release (ctx, CAIRO_STATUS_SUCCESS); - -FAIL: - _cairo_gl_composite_fini (&setup); - if (src_operand == &tmp_operand) - _cairo_gl_operand_destroy (&tmp_operand); - return status; -} - -static cairo_int_status_t -_cairo_gl_span_renderer_init (cairo_abstract_span_renderer_t *_r, - const cairo_composite_rectangles_t *composite, - cairo_antialias_t antialias, - cairo_bool_t needs_clip) -{ - cairo_gl_span_renderer_t *r = (cairo_gl_span_renderer_t *)_r; - const cairo_pattern_t *source = &composite->source_pattern.base; - cairo_operator_t op = composite->op; - cairo_int_status_t status; - - if (op == CAIRO_OPERATOR_SOURCE) { - if (! _cairo_pattern_is_opaque (&composite->source_pattern.base, - &composite->source_sample_area)) - return CAIRO_INT_STATUS_UNSUPPORTED; - op = CAIRO_OPERATOR_OVER; - } - - /* XXX earlier! */ - if (op == CAIRO_OPERATOR_CLEAR) { - source = &_cairo_pattern_white.base; - op = CAIRO_OPERATOR_DEST_OUT; - } else if (composite->surface->is_clear && - (op == CAIRO_OPERATOR_SOURCE || - op == CAIRO_OPERATOR_OVER || - op == CAIRO_OPERATOR_ADD)) { - op = CAIRO_OPERATOR_SOURCE; - } else if (op == CAIRO_OPERATOR_SOURCE) { - /* no lerp equivalent without some major PITA */ - return CAIRO_INT_STATUS_UNSUPPORTED; - } else if (! _cairo_gl_operator_is_supported (op)) - return CAIRO_INT_STATUS_UNSUPPORTED; - - status = _cairo_gl_composite_init (&r->setup, - op, (cairo_gl_surface_t *)composite->surface, - FALSE); - if (unlikely (status)) - goto FAIL; - - status = _cairo_gl_composite_set_source (&r->setup, source, - &composite->source_sample_area, - &composite->unbounded, - TRUE); - if (unlikely (status)) - goto FAIL; - - r->opacity = 1.0; - if (composite->mask_pattern.base.type == CAIRO_PATTERN_TYPE_SOLID) { - r->opacity = composite->mask_pattern.solid.color.alpha; - } else { - status = _cairo_gl_composite_set_mask (&r->setup, - &composite->mask_pattern.base, - &composite->mask_sample_area, - &composite->unbounded, - TRUE); - if (unlikely (status)) - goto FAIL; - } - - _cairo_gl_composite_set_spans (&r->setup); - - status = _cairo_gl_composite_begin (&r->setup, &r->ctx); - if (unlikely (status)) - goto FAIL; - - r->emit = _cairo_gl_context_choose_emit_span (r->ctx); - if (composite->is_bounded) { - if (r->opacity == 1.) - r->base.render_rows = _cairo_gl_bounded_opaque_spans; - else - r->base.render_rows = _cairo_gl_bounded_spans; - r->base.finish = _cairo_gl_finish_bounded_spans; - } else { - if (needs_clip) - r->base.render_rows = _cairo_gl_clipped_spans; - else - r->base.render_rows = _cairo_gl_unbounded_spans; - r->base.finish = _cairo_gl_finish_unbounded_spans; - r->xmin = composite->unbounded.x; - r->xmax = composite->unbounded.x + composite->unbounded.width; - r->ymin = composite->unbounded.y; - r->ymax = composite->unbounded.y + composite->unbounded.height; - } - - return CAIRO_STATUS_SUCCESS; - -FAIL: - return status; -} - -static void -_cairo_gl_span_renderer_fini (cairo_abstract_span_renderer_t *_r, - cairo_int_status_t status) -{ - cairo_gl_span_renderer_t *r = (cairo_gl_span_renderer_t *) _r; - - if (status == CAIRO_INT_STATUS_UNSUPPORTED) - return; - - if (status == CAIRO_INT_STATUS_SUCCESS) - r->base.finish (r); - - _cairo_gl_composite_fini (&r->setup); -} - -const cairo_compositor_t * -_cairo_gl_span_compositor_get (void) -{ - static cairo_atomic_once_t once = CAIRO_ATOMIC_ONCE_INIT; - static cairo_spans_compositor_t spans; - static cairo_compositor_t shape; - - if (_cairo_atomic_init_once_enter(&once)) { - /* The fallback to traps here is essentially just for glyphs... */ - _cairo_shape_mask_compositor_init (&shape, - _cairo_gl_traps_compositor_get()); - shape.glyphs = NULL; - - _cairo_spans_compositor_init (&spans, &shape); - spans.fill_boxes = fill_boxes; - spans.draw_image_boxes = draw_image_boxes; - spans.copy_boxes = copy_boxes; - //spans.check_composite_boxes = check_composite_boxes; - spans.pattern_to_surface = _cairo_gl_pattern_to_source; - spans.composite_boxes = composite_boxes; - //spans.check_span_renderer = check_span_renderer; - spans.renderer_init = _cairo_gl_span_renderer_init; - spans.renderer_fini = _cairo_gl_span_renderer_fini; - - _cairo_atomic_init_once_leave(&once); - } - - return &spans.base; -} diff --git a/gfx/cairo/cairo/src/cairo-gl-surface-legacy.c b/gfx/cairo/cairo/src/cairo-gl-surface-legacy.c deleted file mode 100644 index 87dca2f03e..0000000000 --- a/gfx/cairo/cairo/src/cairo-gl-surface-legacy.c +++ /dev/null @@ -1,602 +0,0 @@ -/* cairo - a vector graphics library with display and print output - * - * Copyright © 2009 Eric Anholt - * Copyright © 2009 Chris Wilson - * Copyright © 2005,2010 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., 51 Franklin Street, Suite 500, Boston, MA 02110-1335, 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): - * Benjamin Otte <otte@gnome.org> - * Carl Worth <cworth@cworth.org> - * Chris Wilson <chris@chris-wilson.co.uk> - * Eric Anholt <eric@anholt.net> - */ - -#include "cairoint.h" - -#include "cairo-composite-rectangles-private.h" -#include "cairo-default-context-private.h" -#include "cairo-error-private.h" -#include "cairo-gl-private.h" -#include "cairo-image-surface-inline.h" - -cairo_status_t -_cairo_gl_surface_acquire_dest_image (void *abstract_surface, - cairo_rectangle_int_t *interest_rect, - cairo_image_surface_t **image_out, - cairo_rectangle_int_t *image_rect_out, - void **image_extra) -{ - cairo_gl_surface_t *surface = abstract_surface; - cairo_int_status_t status; - - status = _cairo_gl_surface_deferred_clear (surface); - if (unlikely (status)) - return status; - - *image_extra = NULL; - return _cairo_gl_surface_get_image (surface, interest_rect, image_out, - image_rect_out); -} - -void -_cairo_gl_surface_release_dest_image (void *abstract_surface, - cairo_rectangle_int_t *interest_rect, - cairo_image_surface_t *image, - cairo_rectangle_int_t *image_rect, - void *image_extra) -{ - cairo_status_t status; - - status = _cairo_gl_surface_draw_image (abstract_surface, image, - 0, 0, - image->width, image->height, - image_rect->x, image_rect->y, - TRUE); - /* as we created the image, its format should be directly applicable */ - assert (status == CAIRO_STATUS_SUCCESS); - - cairo_surface_destroy (&image->base); -} - -cairo_status_t -_cairo_gl_surface_clone_similar (void *abstract_surface, - cairo_surface_t *src, - int src_x, - int src_y, - int width, - int height, - int *clone_offset_x, - int *clone_offset_y, - cairo_surface_t **clone_out) -{ - cairo_gl_surface_t *surface = abstract_surface; - cairo_int_status_t status; - - /* XXX: Use GLCopyTexImage2D to clone non-texture-surfaces */ - if (src->device == surface->base.device && - _cairo_gl_surface_is_texture ((cairo_gl_surface_t *) src)) { - status = _cairo_gl_surface_deferred_clear ((cairo_gl_surface_t *)src); - if (unlikely (status)) - return status; - - *clone_offset_x = 0; - *clone_offset_y = 0; - *clone_out = cairo_surface_reference (src); - - return CAIRO_STATUS_SUCCESS; - } else if (_cairo_surface_is_image (src)) { - cairo_image_surface_t *image_src = (cairo_image_surface_t *)src; - cairo_gl_surface_t *clone; - - clone = (cairo_gl_surface_t *) - _cairo_gl_surface_create_similar (&surface->base, - src->content, - width, height); - if (clone == NULL) - return UNSUPPORTED ("create_similar failed"); - if (clone->base.status) - return clone->base.status; - - status = _cairo_gl_surface_draw_image (clone, image_src, - src_x, src_y, - width, height, - 0, 0, TRUE); - if (status) { - cairo_surface_destroy (&clone->base); - return status; - } - - *clone_out = &clone->base; - *clone_offset_x = src_x; - *clone_offset_y = src_y; - - return CAIRO_STATUS_SUCCESS; - } - - return UNSUPPORTED ("unknown src surface type in clone_similar"); -} - -/* Creates a cairo-gl pattern surface for the given trapezoids */ -static cairo_status_t -_cairo_gl_get_traps_pattern (cairo_gl_surface_t *dst, - int dst_x, int dst_y, - int width, int height, - cairo_trapezoid_t *traps, - int num_traps, - cairo_antialias_t antialias, - cairo_surface_pattern_t *pattern) -{ - pixman_format_code_t pixman_format; - pixman_image_t *image; - cairo_surface_t *surface; - int i; - - pixman_format = antialias != CAIRO_ANTIALIAS_NONE ? PIXMAN_a8 : PIXMAN_a1, - image = pixman_image_create_bits (pixman_format, width, height, NULL, 0); - if (unlikely (image == NULL)) - return _cairo_error (CAIRO_STATUS_NO_MEMORY); - - for (i = 0; i < num_traps; i++) { - pixman_trapezoid_t trap; - - trap.top = _cairo_fixed_to_16_16 (traps[i].top); - trap.bottom = _cairo_fixed_to_16_16 (traps[i].bottom); - - trap.left.p1.x = _cairo_fixed_to_16_16 (traps[i].left.p1.x); - trap.left.p1.y = _cairo_fixed_to_16_16 (traps[i].left.p1.y); - trap.left.p2.x = _cairo_fixed_to_16_16 (traps[i].left.p2.x); - trap.left.p2.y = _cairo_fixed_to_16_16 (traps[i].left.p2.y); - - trap.right.p1.x = _cairo_fixed_to_16_16 (traps[i].right.p1.x); - trap.right.p1.y = _cairo_fixed_to_16_16 (traps[i].right.p1.y); - trap.right.p2.x = _cairo_fixed_to_16_16 (traps[i].right.p2.x); - trap.right.p2.y = _cairo_fixed_to_16_16 (traps[i].right.p2.y); - - pixman_rasterize_trapezoid (image, &trap, -dst_x, -dst_y); - } - - surface = _cairo_image_surface_create_for_pixman_image (image, - pixman_format); - if (unlikely (surface->status)) { - pixman_image_unref (image); - return surface->status; - } - - _cairo_pattern_init_for_surface (pattern, surface); - cairo_surface_destroy (surface); - - return CAIRO_STATUS_SUCCESS; -} - -cairo_int_status_t -_cairo_gl_surface_composite (cairo_operator_t op, - const cairo_pattern_t *src, - const cairo_pattern_t *mask, - void *abstract_dst, - int src_x, - int src_y, - int mask_x, - int mask_y, - int dst_x, - int dst_y, - unsigned int width, - unsigned int height, - cairo_region_t *clip_region) -{ - cairo_gl_surface_t *dst = abstract_dst; - cairo_gl_context_t *ctx; - cairo_status_t status; - cairo_gl_composite_t setup; - cairo_rectangle_int_t rect = { dst_x, dst_y, width, height }; - int dx, dy; - - status = _cairo_gl_surface_deferred_clear (dst); - if (unlikely (status)) - return status; - - if (op == CAIRO_OPERATOR_SOURCE && - mask == NULL && - src->type == CAIRO_PATTERN_TYPE_SURFACE && - _cairo_surface_is_image (((cairo_surface_pattern_t *) src)->surface) && - _cairo_matrix_is_integer_translation (&src->matrix, &dx, &dy)) { - cairo_image_surface_t *image = (cairo_image_surface_t *) - ((cairo_surface_pattern_t *) src)->surface; - dx += src_x; - dy += src_y; - if (dx >= 0 && - dy >= 0 && - dx + width <= (unsigned int) image->width && - dy + height <= (unsigned int) image->height) { - status = _cairo_gl_surface_draw_image (dst, image, - dx, dy, - width, height, - dst_x, dst_y, TRUE); - if (status != CAIRO_INT_STATUS_UNSUPPORTED) - return status; - } - } - - status = _cairo_gl_composite_init (&setup, op, dst, - mask && mask->has_component_alpha, - &rect); - if (unlikely (status)) - goto CLEANUP; - - status = _cairo_gl_composite_set_source (&setup, src, - src_x, src_y, - dst_x, dst_y, - width, height); - if (unlikely (status)) - goto CLEANUP; - - status = _cairo_gl_composite_set_mask (&setup, mask, - mask_x, mask_y, - dst_x, dst_y, - width, height); - if (unlikely (status)) - goto CLEANUP; - - status = _cairo_gl_composite_begin (&setup, &ctx); - if (unlikely (status)) - goto CLEANUP; - - if (clip_region != NULL) { - int i, num_rectangles; - - num_rectangles = cairo_region_num_rectangles (clip_region); - - for (i = 0; i < num_rectangles; i++) { - cairo_rectangle_int_t rect; - - cairo_region_get_rectangle (clip_region, i, &rect); - _cairo_gl_composite_emit_rect (ctx, - rect.x, rect.y, - rect.x + rect.width, rect.y + rect.height, - 0); - } - } else { - _cairo_gl_composite_emit_rect (ctx, - dst_x, dst_y, - dst_x + width, dst_y + height, - 0); - } - - status = _cairo_gl_context_release (ctx, status); - - CLEANUP: - _cairo_gl_composite_fini (&setup); - - return status; -} - -cairo_int_status_t -_cairo_gl_surface_composite_trapezoids (cairo_operator_t op, - const cairo_pattern_t *pattern, - void *abstract_dst, - cairo_antialias_t antialias, - int src_x, int src_y, - int dst_x, int dst_y, - unsigned int width, - unsigned int height, - cairo_trapezoid_t *traps, - int num_traps, - cairo_region_t *clip_region) -{ - cairo_gl_surface_t *dst = abstract_dst; - cairo_surface_pattern_t traps_pattern; - cairo_int_status_t status; - - if (! _cairo_gl_operator_is_supported (op)) - return UNSUPPORTED ("unsupported operator"); - - status = _cairo_gl_surface_deferred_clear (dst); - if (unlikely (status)) - return status; - - status = _cairo_gl_get_traps_pattern (dst, - dst_x, dst_y, width, height, - traps, num_traps, antialias, - &traps_pattern); - if (unlikely (status)) - return status; - - status = _cairo_gl_surface_composite (op, - pattern, &traps_pattern.base, dst, - src_x, src_y, - 0, 0, - dst_x, dst_y, - width, height, - clip_region); - - _cairo_pattern_fini (&traps_pattern.base); - - assert (status != CAIRO_INT_STATUS_UNSUPPORTED); - return status; -} - -cairo_int_status_t -_cairo_gl_surface_fill_rectangles (void *abstract_dst, - cairo_operator_t op, - const cairo_color_t *color, - cairo_rectangle_int_t *rects, - int num_rects) -{ - cairo_gl_surface_t *dst = abstract_dst; - cairo_solid_pattern_t solid; - cairo_gl_context_t *ctx; - cairo_status_t status; - cairo_gl_composite_t setup; - int i; - - status = _cairo_gl_surface_deferred_clear (dst); - if (unlikely (status)) - return status; - - status = _cairo_gl_composite_init (&setup, op, dst, - FALSE, - /* XXX */ NULL); - if (unlikely (status)) - goto CLEANUP; - - _cairo_pattern_init_solid (&solid, color); - status = _cairo_gl_composite_set_source (&setup, &solid.base, - 0, 0, - 0, 0, - 0, 0); - if (unlikely (status)) - goto CLEANUP; - - status = _cairo_gl_composite_set_mask (&setup, NULL, - 0, 0, - 0, 0, - 0, 0); - if (unlikely (status)) - goto CLEANUP; - - status = _cairo_gl_composite_begin (&setup, &ctx); - if (unlikely (status)) - goto CLEANUP; - - for (i = 0; i < num_rects; i++) { - _cairo_gl_composite_emit_rect (ctx, - rects[i].x, - rects[i].y, - rects[i].x + rects[i].width, - rects[i].y + rects[i].height, - 0); - } - - status = _cairo_gl_context_release (ctx, status); - - CLEANUP: - _cairo_gl_composite_fini (&setup); - - return status; -} - -typedef struct _cairo_gl_surface_span_renderer { - cairo_span_renderer_t base; - - cairo_gl_composite_t setup; - - int xmin, xmax; - int ymin, ymax; - - cairo_gl_context_t *ctx; -} cairo_gl_surface_span_renderer_t; - -static cairo_status_t -_cairo_gl_render_bounded_spans (void *abstract_renderer, - int y, int height, - const cairo_half_open_span_t *spans, - unsigned num_spans) -{ - cairo_gl_surface_span_renderer_t *renderer = abstract_renderer; - - if (num_spans == 0) - return CAIRO_STATUS_SUCCESS; - - do { - if (spans[0].coverage) { - _cairo_gl_composite_emit_rect (renderer->ctx, - spans[0].x, y, - spans[1].x, y + height, - spans[0].coverage); - } - - spans++; - } while (--num_spans > 1); - - return CAIRO_STATUS_SUCCESS; -} - -static cairo_status_t -_cairo_gl_render_unbounded_spans (void *abstract_renderer, - int y, int height, - const cairo_half_open_span_t *spans, - unsigned num_spans) -{ - cairo_gl_surface_span_renderer_t *renderer = abstract_renderer; - - if (y > renderer->ymin) { - _cairo_gl_composite_emit_rect (renderer->ctx, - renderer->xmin, renderer->ymin, - renderer->xmax, y, - 0); - } - - if (num_spans == 0) { - _cairo_gl_composite_emit_rect (renderer->ctx, - renderer->xmin, y, - renderer->xmax, y + height, - 0); - } else { - if (spans[0].x != renderer->xmin) { - _cairo_gl_composite_emit_rect (renderer->ctx, - renderer->xmin, y, - spans[0].x, y + height, - 0); - } - - do { - _cairo_gl_composite_emit_rect (renderer->ctx, - spans[0].x, y, - spans[1].x, y + height, - spans[0].coverage); - spans++; - } while (--num_spans > 1); - - if (spans[0].x != renderer->xmax) { - _cairo_gl_composite_emit_rect (renderer->ctx, - spans[0].x, y, - renderer->xmax, y + height, - 0); - } - } - - renderer->ymin = y + height; - return CAIRO_STATUS_SUCCESS; -} - -static cairo_status_t -_cairo_gl_finish_unbounded_spans (void *abstract_renderer) -{ - cairo_gl_surface_span_renderer_t *renderer = abstract_renderer; - - if (renderer->ymax > renderer->ymin) { - _cairo_gl_composite_emit_rect (renderer->ctx, - renderer->xmin, renderer->ymin, - renderer->xmax, renderer->ymax, - 0); - } - - return _cairo_gl_context_release (renderer->ctx, CAIRO_STATUS_SUCCESS); -} - -static cairo_status_t -_cairo_gl_finish_bounded_spans (void *abstract_renderer) -{ - cairo_gl_surface_span_renderer_t *renderer = abstract_renderer; - - return _cairo_gl_context_release (renderer->ctx, CAIRO_STATUS_SUCCESS); -} - -static void -_cairo_gl_surface_span_renderer_destroy (void *abstract_renderer) -{ - cairo_gl_surface_span_renderer_t *renderer = abstract_renderer; - - if (!renderer) - return; - - _cairo_gl_composite_fini (&renderer->setup); - - free (renderer); -} - -cairo_bool_t -_cairo_gl_surface_check_span_renderer (cairo_operator_t op, - const cairo_pattern_t *pattern, - void *abstract_dst, - cairo_antialias_t antialias) -{ - if (! _cairo_gl_operator_is_supported (op)) - return FALSE; - - return TRUE; - - (void) pattern; - (void) abstract_dst; - (void) antialias; -} - -cairo_span_renderer_t * -_cairo_gl_surface_create_span_renderer (cairo_operator_t op, - const cairo_pattern_t *src, - void *abstract_dst, - cairo_antialias_t antialias, - const cairo_composite_rectangles_t *rects) -{ - cairo_gl_surface_t *dst = abstract_dst; - cairo_gl_surface_span_renderer_t *renderer; - cairo_status_t status; - const cairo_rectangle_int_t *extents; - - status = _cairo_gl_surface_deferred_clear (dst); - if (unlikely (status)) - return _cairo_span_renderer_create_in_error (status); - - renderer = calloc (1, sizeof (*renderer)); - if (unlikely (renderer == NULL)) - return _cairo_span_renderer_create_in_error (CAIRO_STATUS_NO_MEMORY); - - renderer->base.destroy = _cairo_gl_surface_span_renderer_destroy; - if (rects->is_bounded) { - renderer->base.render_rows = _cairo_gl_render_bounded_spans; - renderer->base.finish = _cairo_gl_finish_bounded_spans; - extents = &rects->bounded; - } else { - renderer->base.render_rows = _cairo_gl_render_unbounded_spans; - renderer->base.finish = _cairo_gl_finish_unbounded_spans; - extents = &rects->unbounded; - } - renderer->xmin = extents->x; - renderer->xmax = extents->x + extents->width; - renderer->ymin = extents->y; - renderer->ymax = extents->y + extents->height; - - status = _cairo_gl_composite_init (&renderer->setup, - op, dst, - FALSE, extents); - if (unlikely (status)) - goto FAIL; - - status = _cairo_gl_composite_set_source (&renderer->setup, src, - extents->x, extents->y, - extents->x, extents->y, - extents->width, extents->height); - if (unlikely (status)) - goto FAIL; - - _cairo_gl_composite_set_spans (&renderer->setup); - _cairo_gl_composite_set_clip_region (&renderer->setup, - _cairo_clip_get_region (rects->clip)); - - status = _cairo_gl_composite_begin (&renderer->setup, &renderer->ctx); - if (unlikely (status)) - goto FAIL; - - return &renderer->base; - -FAIL: - _cairo_gl_composite_fini (&renderer->setup); - free (renderer); - return _cairo_span_renderer_create_in_error (status); -} diff --git a/gfx/cairo/cairo/src/cairo-gl-surface.c b/gfx/cairo/cairo/src/cairo-gl-surface.c deleted file mode 100644 index b0f42d6aa1..0000000000 --- a/gfx/cairo/cairo/src/cairo-gl-surface.c +++ /dev/null @@ -1,1550 +0,0 @@ -/* cairo - a vector graphics library with display and print output - * - * Copyright © 2009 Eric Anholt - * Copyright © 2009 Chris Wilson - * Copyright © 2005,2010 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., 51 Franklin Street, Suite 500, Boston, MA 02110-1335, 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): - * Benjamin Otte <otte@gnome.org> - * Carl Worth <cworth@cworth.org> - * Chris Wilson <chris@chris-wilson.co.uk> - * Eric Anholt <eric@anholt.net> - */ - -#include "cairoint.h" - -#include "cairo-gl-private.h" - -#include "cairo-composite-rectangles-private.h" -#include "cairo-compositor-private.h" -#include "cairo-default-context-private.h" -#include "cairo-error-private.h" -#include "cairo-image-surface-inline.h" -#include "cairo-surface-backend-private.h" - -static const cairo_surface_backend_t _cairo_gl_surface_backend; - -static cairo_status_t -_cairo_gl_surface_flush (void *abstract_surface, unsigned flags); - -static cairo_bool_t _cairo_surface_is_gl (cairo_surface_t *surface) -{ - return surface->backend == &_cairo_gl_surface_backend; -} - -static cairo_bool_t -_cairo_gl_get_image_format_and_type_gles2 (pixman_format_code_t pixman_format, - GLenum *internal_format, GLenum *format, - GLenum *type, cairo_bool_t *has_alpha, - cairo_bool_t *needs_swap) -{ - cairo_bool_t is_little_endian = _cairo_is_little_endian (); - - *has_alpha = TRUE; - - switch ((int) pixman_format) { - case PIXMAN_a8r8g8b8: - *internal_format = GL_BGRA; - *format = GL_BGRA; - *type = GL_UNSIGNED_BYTE; - *needs_swap = !is_little_endian; - return TRUE; - - case PIXMAN_x8r8g8b8: - *internal_format = GL_BGRA; - *format = GL_BGRA; - *type = GL_UNSIGNED_BYTE; - *has_alpha = FALSE; - *needs_swap = !is_little_endian; - return TRUE; - - case PIXMAN_a8b8g8r8: - *internal_format = GL_RGBA; - *format = GL_RGBA; - *type = GL_UNSIGNED_BYTE; - *needs_swap = !is_little_endian; - return TRUE; - - case PIXMAN_x8b8g8r8: - *internal_format = GL_RGBA; - *format = GL_RGBA; - *type = GL_UNSIGNED_BYTE; - *has_alpha = FALSE; - *needs_swap = !is_little_endian; - return TRUE; - - case PIXMAN_b8g8r8a8: - *internal_format = GL_BGRA; - *format = GL_BGRA; - *type = GL_UNSIGNED_BYTE; - *needs_swap = is_little_endian; - return TRUE; - - case PIXMAN_b8g8r8x8: - *internal_format = GL_BGRA; - *format = GL_BGRA; - *type = GL_UNSIGNED_BYTE; - *has_alpha = FALSE; - *needs_swap = is_little_endian; - return TRUE; - - case PIXMAN_r8g8b8: - *internal_format = GL_RGB; - *format = GL_RGB; - *type = GL_UNSIGNED_BYTE; - *needs_swap = is_little_endian; - return TRUE; - - case PIXMAN_b8g8r8: - *internal_format = GL_RGB; - *format = GL_RGB; - *type = GL_UNSIGNED_BYTE; - *needs_swap = !is_little_endian; - return TRUE; - - case PIXMAN_r5g6b5: - *internal_format = GL_RGB; - *format = GL_RGB; - *type = GL_UNSIGNED_SHORT_5_6_5; - *needs_swap = FALSE; - return TRUE; - - case PIXMAN_b5g6r5: - *internal_format = GL_RGB; - *format = GL_RGB; - *type = GL_UNSIGNED_SHORT_5_6_5; - *needs_swap = TRUE; - return TRUE; - - case PIXMAN_a1b5g5r5: - *internal_format = GL_RGBA; - *format = GL_RGBA; - *type = GL_UNSIGNED_SHORT_5_5_5_1; - *needs_swap = TRUE; - return TRUE; - - case PIXMAN_x1b5g5r5: - *internal_format = GL_RGBA; - *format = GL_RGBA; - *type = GL_UNSIGNED_SHORT_5_5_5_1; - *has_alpha = FALSE; - *needs_swap = TRUE; - return TRUE; - - case PIXMAN_a8: - *internal_format = GL_ALPHA; - *format = GL_ALPHA; - *type = GL_UNSIGNED_BYTE; - *needs_swap = FALSE; - return TRUE; - - default: - return FALSE; - } -} - -static cairo_bool_t -_cairo_gl_get_image_format_and_type_gl (pixman_format_code_t pixman_format, - GLenum *internal_format, GLenum *format, - GLenum *type, cairo_bool_t *has_alpha, - cairo_bool_t *needs_swap) -{ - *has_alpha = TRUE; - *needs_swap = FALSE; - - switch (pixman_format) { - case PIXMAN_a8r8g8b8: - *internal_format = GL_RGBA; - *format = GL_BGRA; - *type = GL_UNSIGNED_INT_8_8_8_8_REV; - return TRUE; - case PIXMAN_x8r8g8b8: - *internal_format = GL_RGB; - *format = GL_BGRA; - *type = GL_UNSIGNED_INT_8_8_8_8_REV; - *has_alpha = FALSE; - return TRUE; - case PIXMAN_a8b8g8r8: - *internal_format = GL_RGBA; - *format = GL_RGBA; - *type = GL_UNSIGNED_INT_8_8_8_8_REV; - return TRUE; - case PIXMAN_x8b8g8r8: - *internal_format = GL_RGB; - *format = GL_RGBA; - *type = GL_UNSIGNED_INT_8_8_8_8_REV; - *has_alpha = FALSE; - return TRUE; - case PIXMAN_b8g8r8a8: - *internal_format = GL_RGBA; - *format = GL_BGRA; - *type = GL_UNSIGNED_INT_8_8_8_8; - return TRUE; - case PIXMAN_b8g8r8x8: - *internal_format = GL_RGB; - *format = GL_BGRA; - *type = GL_UNSIGNED_INT_8_8_8_8; - *has_alpha = FALSE; - return TRUE; - case PIXMAN_r8g8b8: - *internal_format = GL_RGB; - *format = GL_RGB; - *type = GL_UNSIGNED_BYTE; - return TRUE; - case PIXMAN_b8g8r8: - *internal_format = GL_RGB; - *format = GL_BGR; - *type = GL_UNSIGNED_BYTE; - return TRUE; - case PIXMAN_r5g6b5: - *internal_format = GL_RGB; - *format = GL_RGB; - *type = GL_UNSIGNED_SHORT_5_6_5; - return TRUE; - case PIXMAN_b5g6r5: - *internal_format = GL_RGB; - *format = GL_RGB; - *type = GL_UNSIGNED_SHORT_5_6_5_REV; - return TRUE; - case PIXMAN_a1r5g5b5: - *internal_format = GL_RGBA; - *format = GL_BGRA; - *type = GL_UNSIGNED_SHORT_1_5_5_5_REV; - return TRUE; - case PIXMAN_x1r5g5b5: - *internal_format = GL_RGB; - *format = GL_BGRA; - *type = GL_UNSIGNED_SHORT_1_5_5_5_REV; - *has_alpha = FALSE; - return TRUE; - case PIXMAN_a1b5g5r5: - *internal_format = GL_RGBA; - *format = GL_RGBA; - *type = GL_UNSIGNED_SHORT_1_5_5_5_REV; - return TRUE; - case PIXMAN_x1b5g5r5: - *internal_format = GL_RGB; - *format = GL_RGBA; - *type = GL_UNSIGNED_SHORT_1_5_5_5_REV; - *has_alpha = FALSE; - return TRUE; - case PIXMAN_a8: - *internal_format = GL_ALPHA; - *format = GL_ALPHA; - *type = GL_UNSIGNED_BYTE; - return TRUE; - -#if PIXMAN_VERSION >= PIXMAN_VERSION_ENCODE(0,27,2) - case PIXMAN_a8r8g8b8_sRGB: -#endif - case PIXMAN_a2b10g10r10: - case PIXMAN_x2b10g10r10: - case PIXMAN_a4r4g4b4: - case PIXMAN_x4r4g4b4: - case PIXMAN_a4b4g4r4: - case PIXMAN_x4b4g4r4: - case PIXMAN_r3g3b2: - case PIXMAN_b2g3r3: - case PIXMAN_a2r2g2b2: - case PIXMAN_a2b2g2r2: - case PIXMAN_c8: - case PIXMAN_x4a4: - /* case PIXMAN_x4c4: */ - case PIXMAN_x4g4: - case PIXMAN_a4: - case PIXMAN_r1g2b1: - case PIXMAN_b1g2r1: - case PIXMAN_a1r1g1b1: - case PIXMAN_a1b1g1r1: - case PIXMAN_c4: - case PIXMAN_g4: - case PIXMAN_a1: - case PIXMAN_g1: - case PIXMAN_yuy2: - case PIXMAN_yv12: - case PIXMAN_x2r10g10b10: - case PIXMAN_a2r10g10b10: - case PIXMAN_r8g8b8x8: - case PIXMAN_r8g8b8a8: - case PIXMAN_x14r6g6b6: - default: - return FALSE; - } -} - -/* - * Extracts pixel data from an image surface. - */ -static cairo_status_t -_cairo_gl_surface_extract_image_data (cairo_image_surface_t *image, - int x, int y, - int width, int height, - void **output) -{ - int cpp = PIXMAN_FORMAT_BPP (image->pixman_format) / 8; - char *data = _cairo_malloc_ab (width * height, cpp); - char *dst = data; - unsigned char *src = image->data + y * image->stride + x * cpp; - int i; - - if (unlikely (data == NULL)) - return CAIRO_STATUS_NO_MEMORY; - - for (i = 0; i < height; i++) { - memcpy (dst, src, width * cpp); - src += image->stride; - dst += width * cpp; - } - - *output = data; - - return CAIRO_STATUS_SUCCESS; -} - -cairo_bool_t -_cairo_gl_get_image_format_and_type (cairo_gl_flavor_t flavor, - pixman_format_code_t pixman_format, - GLenum *internal_format, GLenum *format, - GLenum *type, cairo_bool_t *has_alpha, - cairo_bool_t *needs_swap) -{ - if (flavor == CAIRO_GL_FLAVOR_DESKTOP) - return _cairo_gl_get_image_format_and_type_gl (pixman_format, - internal_format, format, - type, has_alpha, - needs_swap); - else - return _cairo_gl_get_image_format_and_type_gles2 (pixman_format, - internal_format, format, - type, has_alpha, - needs_swap); - -} - -cairo_bool_t -_cairo_gl_operator_is_supported (cairo_operator_t op) -{ - return op < CAIRO_OPERATOR_SATURATE; -} - -static void -_cairo_gl_surface_embedded_operand_init (cairo_gl_surface_t *surface) -{ - cairo_gl_operand_t *operand = &surface->operand; - cairo_surface_attributes_t *attributes = &operand->texture.attributes; - - memset (operand, 0, sizeof (cairo_gl_operand_t)); - - operand->type = CAIRO_GL_OPERAND_TEXTURE; - operand->texture.surface = surface; - operand->texture.tex = surface->tex; - - if (_cairo_gl_device_requires_power_of_two_textures (surface->base.device)) { - cairo_matrix_init_identity (&attributes->matrix); - } else { - cairo_matrix_init_scale (&attributes->matrix, - 1.0 / surface->width, - 1.0 / surface->height); - } - - attributes->extend = CAIRO_EXTEND_NONE; - attributes->filter = CAIRO_FILTER_NEAREST; -} - -void -_cairo_gl_surface_init (cairo_device_t *device, - cairo_gl_surface_t *surface, - cairo_content_t content, - int width, int height) -{ - assert (width > 0 && height > 0); - - _cairo_surface_init (&surface->base, - &_cairo_gl_surface_backend, - device, - content, - FALSE); /* is_vector */ - - surface->width = width; - surface->height = height; - surface->needs_update = FALSE; - surface->content_in_texture = FALSE; - - _cairo_gl_surface_embedded_operand_init (surface); -} - -static cairo_bool_t -_cairo_gl_surface_size_valid_for_context (cairo_gl_context_t *ctx, - int width, int height) -{ - return width > 0 && height > 0 && - width <= ctx->max_framebuffer_size && - height <= ctx->max_framebuffer_size; -} - -static cairo_bool_t -_cairo_gl_surface_size_valid (cairo_gl_surface_t *surface, - int width, int height) -{ - cairo_gl_context_t *ctx = (cairo_gl_context_t *)surface->base.device; - return _cairo_gl_surface_size_valid_for_context (ctx, width, height); -} - -static cairo_surface_t * -_cairo_gl_surface_create_scratch_for_texture (cairo_gl_context_t *ctx, - cairo_content_t content, - GLuint tex, - int width, - int height) -{ - cairo_gl_surface_t *surface; - - surface = calloc (1, sizeof (cairo_gl_surface_t)); - if (unlikely (surface == NULL)) - return _cairo_surface_create_in_error (_cairo_error (CAIRO_STATUS_NO_MEMORY)); - - surface->tex = tex; - _cairo_gl_surface_init (&ctx->base, surface, content, width, height); - - surface->supports_msaa = ctx->supports_msaa; - surface->num_samples = ctx->num_samples; - surface->supports_stencil = TRUE; - - /* Create the texture used to store the surface's data. */ - _cairo_gl_context_activate (ctx, CAIRO_GL_TEX_TEMP); - glBindTexture (ctx->tex_target, surface->tex); - glTexParameteri (ctx->tex_target, GL_TEXTURE_MIN_FILTER, GL_NEAREST); - glTexParameteri (ctx->tex_target, GL_TEXTURE_MAG_FILTER, GL_NEAREST); - - return &surface->base; -} - -static cairo_surface_t * -_create_scratch_internal (cairo_gl_context_t *ctx, - cairo_content_t content, - int width, - int height, - cairo_bool_t for_caching) -{ - cairo_gl_surface_t *surface; - GLenum format; - GLuint tex; - - glGenTextures (1, &tex); - surface = (cairo_gl_surface_t *) - _cairo_gl_surface_create_scratch_for_texture (ctx, content, - tex, width, height); - if (unlikely (surface->base.status)) - return &surface->base; - - surface->owns_tex = TRUE; - - /* adjust the texture size after setting our real extents */ - if (width < 1) - width = 1; - if (height < 1) - height = 1; - - switch (content) { - default: - ASSERT_NOT_REACHED; - case CAIRO_CONTENT_COLOR_ALPHA: - format = GL_RGBA; - break; - case CAIRO_CONTENT_ALPHA: - /* When using GL_ALPHA, compositing doesn't work properly, but for - * caching surfaces, we are just uploading pixel data, so it isn't - * an issue. */ - if (for_caching) - format = GL_ALPHA; - else - format = GL_RGBA; - break; - case CAIRO_CONTENT_COLOR: - /* GL_RGB is almost what we want here -- sampling 1 alpha when - * texturing, using 1 as destination alpha factor in blending, - * etc. However, when filtering with GL_CLAMP_TO_BORDER, the - * alpha channel of the border color will also be clamped to - * 1, when we actually want the border color we explicitly - * specified. So, we have to store RGBA, and fill the alpha - * channel with 1 when blending. - */ - format = GL_RGBA; - break; - } - - glTexImage2D (ctx->tex_target, 0, format, width, height, 0, - format, GL_UNSIGNED_BYTE, NULL); - - return &surface->base; -} - -cairo_surface_t * -_cairo_gl_surface_create_scratch (cairo_gl_context_t *ctx, - cairo_content_t content, - int width, - int height) -{ - return _create_scratch_internal (ctx, content, width, height, FALSE); -} - -cairo_surface_t * -_cairo_gl_surface_create_scratch_for_caching (cairo_gl_context_t *ctx, - cairo_content_t content, - int width, - int height) -{ - return _create_scratch_internal (ctx, content, width, height, TRUE); -} - -static cairo_status_t -_cairo_gl_surface_clear (cairo_gl_surface_t *surface, - const cairo_color_t *color) -{ - cairo_gl_context_t *ctx; - cairo_status_t status; - double r, g, b, a; - - status = _cairo_gl_context_acquire (surface->base.device, &ctx); - if (unlikely (status)) - return status; - - _cairo_gl_context_set_destination (ctx, surface, surface->msaa_active); - if (surface->base.content & CAIRO_CONTENT_COLOR) { - r = color->red * color->alpha; - g = color->green * color->alpha; - b = color->blue * color->alpha; - } else { - r = g = b = 0; - } - if (surface->base.content & CAIRO_CONTENT_ALPHA) { - a = color->alpha; - } else { - a = 1.0; - } - - glDisable (GL_SCISSOR_TEST); - glClearColor (r, g, b, a); - glClear (GL_COLOR_BUFFER_BIT); - - if (a == 0) - surface->base.is_clear = TRUE; - - return _cairo_gl_context_release (ctx, status); -} - -static cairo_surface_t * -_cairo_gl_surface_create_and_clear_scratch (cairo_gl_context_t *ctx, - cairo_content_t content, - int width, - int height) -{ - cairo_gl_surface_t *surface; - cairo_int_status_t status; - - surface = (cairo_gl_surface_t *) - _cairo_gl_surface_create_scratch (ctx, content, width, height); - if (unlikely (surface->base.status)) - return &surface->base; - - /* Cairo surfaces start out initialized to transparent (black) */ - status = _cairo_gl_surface_clear (surface, CAIRO_COLOR_TRANSPARENT); - if (unlikely (status)) { - cairo_surface_destroy (&surface->base); - return _cairo_surface_create_in_error (status); - } - - return &surface->base; -} - -cairo_surface_t * -cairo_gl_surface_create (cairo_device_t *abstract_device, - cairo_content_t content, - int width, - int height) -{ - cairo_gl_context_t *ctx; - cairo_gl_surface_t *surface; - cairo_status_t status; - - if (! CAIRO_CONTENT_VALID (content)) - return _cairo_surface_create_in_error (_cairo_error (CAIRO_STATUS_INVALID_CONTENT)); - - if (abstract_device == NULL) - return _cairo_image_surface_create_with_content (content, width, height); - - if (abstract_device->status) - return _cairo_surface_create_in_error (abstract_device->status); - - if (abstract_device->backend->type != CAIRO_DEVICE_TYPE_GL) - return _cairo_surface_create_in_error (_cairo_error (CAIRO_STATUS_SURFACE_TYPE_MISMATCH)); - - status = _cairo_gl_context_acquire (abstract_device, &ctx); - if (unlikely (status)) - return _cairo_surface_create_in_error (status); - - if (! _cairo_gl_surface_size_valid_for_context (ctx, width, height)) { - status = _cairo_gl_context_release (ctx, status); - return _cairo_surface_create_in_error (_cairo_error (CAIRO_STATUS_INVALID_SIZE)); - } - - surface = (cairo_gl_surface_t *) - _cairo_gl_surface_create_and_clear_scratch (ctx, content, width, height); - if (unlikely (surface->base.status)) { - status = _cairo_gl_context_release (ctx, surface->base.status); - cairo_surface_destroy (&surface->base); - return _cairo_surface_create_in_error (status); - } - - status = _cairo_gl_context_release (ctx, status); - if (unlikely (status)) { - cairo_surface_destroy (&surface->base); - return _cairo_surface_create_in_error (status); - } - - return &surface->base; -} -slim_hidden_def (cairo_gl_surface_create); - -/** - * cairo_gl_surface_create_for_texture: - * @content: type of content in the surface - * @tex: name of texture to use for storage of surface pixels - * @width: width of the surface, in pixels - * @height: height of the surface, in pixels - * - * Creates a GL surface for the specified texture with the specified - * content and dimensions. The texture must be kept around until the - * #cairo_surface_t is destroyed or cairo_surface_finish() is called - * on the surface. The initial contents of @tex will be used as the - * initial image contents; you must explicitly clear the buffer, - * using, for example, cairo_rectangle() and cairo_fill() if you want - * it cleared. The format of @tex should be compatible with @content, - * in the sense that it must have the color components required by - * @content. - * - * Return value: a pointer to the newly created surface. The caller - * owns the surface and should call cairo_surface_destroy() when done - * with it. - * - * This function always returns a valid pointer, but it will return a - * pointer to a "nil" surface if an error such as out of memory - * occurs. You can use cairo_surface_status() to check for this. - * - * Since: TBD - **/ -cairo_surface_t * -cairo_gl_surface_create_for_texture (cairo_device_t *abstract_device, - cairo_content_t content, - unsigned int tex, - int width, - int height) -{ - cairo_gl_context_t *ctx; - cairo_gl_surface_t *surface; - cairo_status_t status; - - if (! CAIRO_CONTENT_VALID (content)) - return _cairo_surface_create_in_error (_cairo_error (CAIRO_STATUS_INVALID_CONTENT)); - - if (abstract_device == NULL) - return _cairo_surface_create_in_error (_cairo_error (CAIRO_STATUS_NULL_POINTER)); - - if (abstract_device->status) - return _cairo_surface_create_in_error (abstract_device->status); - - if (abstract_device->backend->type != CAIRO_DEVICE_TYPE_GL) - return _cairo_surface_create_in_error (_cairo_error (CAIRO_STATUS_DEVICE_TYPE_MISMATCH)); - - status = _cairo_gl_context_acquire (abstract_device, &ctx); - if (unlikely (status)) - return _cairo_surface_create_in_error (status); - - if (! _cairo_gl_surface_size_valid_for_context (ctx, width, height)) { - status = _cairo_gl_context_release (ctx, status); - return _cairo_surface_create_in_error (_cairo_error (CAIRO_STATUS_INVALID_SIZE)); - } - - surface = (cairo_gl_surface_t *) - _cairo_gl_surface_create_scratch_for_texture (ctx, content, - tex, width, height); - status = _cairo_gl_context_release (ctx, status); - - return &surface->base; -} -slim_hidden_def (cairo_gl_surface_create_for_texture); - - -void -cairo_gl_surface_set_size (cairo_surface_t *abstract_surface, - int width, - int height) -{ - cairo_gl_surface_t *surface = (cairo_gl_surface_t *) abstract_surface; - - if (unlikely (abstract_surface->status)) - return; - if (unlikely (abstract_surface->finished)) { - _cairo_surface_set_error (abstract_surface, - _cairo_error (CAIRO_STATUS_SURFACE_FINISHED)); - return; - } - - if (! _cairo_surface_is_gl (abstract_surface) || - _cairo_gl_surface_is_texture (surface)) { - _cairo_surface_set_error (abstract_surface, - _cairo_error (CAIRO_STATUS_SURFACE_TYPE_MISMATCH)); - return; - } - - if (surface->width != width || surface->height != height) { - surface->needs_update = TRUE; - surface->width = width; - surface->height = height; - } -} - -int -cairo_gl_surface_get_width (cairo_surface_t *abstract_surface) -{ - cairo_gl_surface_t *surface = (cairo_gl_surface_t *) abstract_surface; - - if (! _cairo_surface_is_gl (abstract_surface)) - return 0; - - return surface->width; -} - -int -cairo_gl_surface_get_height (cairo_surface_t *abstract_surface) -{ - cairo_gl_surface_t *surface = (cairo_gl_surface_t *) abstract_surface; - - if (! _cairo_surface_is_gl (abstract_surface)) - return 0; - - return surface->height; -} - -void -cairo_gl_surface_swapbuffers (cairo_surface_t *abstract_surface) -{ - cairo_gl_surface_t *surface = (cairo_gl_surface_t *) abstract_surface; - - if (unlikely (abstract_surface->status)) - return; - if (unlikely (abstract_surface->finished)) { - _cairo_surface_set_error (abstract_surface, - _cairo_error (CAIRO_STATUS_SURFACE_FINISHED)); - return; - } - - if (! _cairo_surface_is_gl (abstract_surface)) { - _cairo_surface_set_error (abstract_surface, - CAIRO_STATUS_SURFACE_TYPE_MISMATCH); - return; - } - - if (! _cairo_gl_surface_is_texture (surface)) { - cairo_gl_context_t *ctx; - cairo_status_t status; - - status = _cairo_gl_context_acquire (surface->base.device, &ctx); - if (unlikely (status)) - return; - - /* For swapping on EGL, at least, we need a valid context/target. */ - _cairo_gl_context_set_destination (ctx, surface, FALSE); - /* And in any case we should flush any pending operations. */ - _cairo_gl_composite_flush (ctx); - - ctx->swap_buffers (ctx, surface); - - status = _cairo_gl_context_release (ctx, status); - if (status) - status = _cairo_surface_set_error (abstract_surface, status); - } -} - -static cairo_surface_t * -_cairo_gl_surface_create_similar (void *abstract_surface, - cairo_content_t content, - int width, - int height) -{ - cairo_surface_t *surface = abstract_surface; - cairo_gl_context_t *ctx; - cairo_status_t status; - - if (! _cairo_gl_surface_size_valid (abstract_surface, width, height)) - return _cairo_image_surface_create_with_content (content, width, height); - - status = _cairo_gl_context_acquire (surface->device, &ctx); - if (unlikely (status)) - return _cairo_surface_create_in_error (status); - - surface = _cairo_gl_surface_create_and_clear_scratch (ctx, content, width, height); - - status = _cairo_gl_context_release (ctx, status); - if (unlikely (status)) { - cairo_surface_destroy (surface); - return _cairo_surface_create_in_error (status); - } - - return surface; -} - -static cairo_int_status_t -_cairo_gl_surface_fill_alpha_channel (cairo_gl_surface_t *dst, - cairo_gl_context_t *ctx, - int x, int y, - int width, int height) -{ - cairo_gl_composite_t setup; - cairo_status_t status; - - _cairo_gl_composite_flush (ctx); - glColorMask(GL_FALSE, GL_FALSE, GL_FALSE, GL_TRUE); - - status = _cairo_gl_composite_init (&setup, CAIRO_OPERATOR_SOURCE, - dst, FALSE); - if (unlikely (status)) - goto CLEANUP; - - _cairo_gl_composite_set_solid_source (&setup, CAIRO_COLOR_BLACK); - - status = _cairo_gl_composite_begin (&setup, &ctx); - if (unlikely (status)) - goto CLEANUP; - - _cairo_gl_context_emit_rect (ctx, x, y, x + width, y + height); - - status = _cairo_gl_context_release (ctx, status); - - CLEANUP: - _cairo_gl_composite_fini (&setup); - - _cairo_gl_composite_flush (ctx); - glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE); - - return status; -} - -cairo_status_t -_cairo_gl_surface_draw_image (cairo_gl_surface_t *dst, - cairo_image_surface_t *src, - int src_x, int src_y, - int width, int height, - int dst_x, int dst_y, - cairo_bool_t force_flush) -{ - GLenum internal_format, format, type; - cairo_bool_t has_alpha, needs_swap; - cairo_image_surface_t *clone = NULL; - cairo_gl_context_t *ctx; - int cpp; - cairo_image_surface_t *rgba_clone = NULL; - cairo_int_status_t status = CAIRO_INT_STATUS_SUCCESS; - - status = _cairo_gl_context_acquire (dst->base.device, &ctx); - if (unlikely (status)) - return status; - - if (_cairo_gl_get_flavor () == CAIRO_GL_FLAVOR_ES3 || - _cairo_gl_get_flavor () == CAIRO_GL_FLAVOR_ES2) { - pixman_format_code_t pixman_format; - cairo_surface_pattern_t pattern; - cairo_bool_t require_conversion = FALSE; - pixman_format = _cairo_is_little_endian () ? PIXMAN_a8b8g8r8 : PIXMAN_r8g8b8a8; - - if (src->base.content != CAIRO_CONTENT_ALPHA) { - if (src->pixman_format != pixman_format) - require_conversion = TRUE; - } - else if (dst->base.content != CAIRO_CONTENT_ALPHA) { - require_conversion = TRUE; - } - else if (src->pixman_format != PIXMAN_a8) { - pixman_format = PIXMAN_a8; - require_conversion = TRUE; - } - - if (require_conversion) { - rgba_clone = (cairo_image_surface_t *) - _cairo_image_surface_create_with_pixman_format (NULL, - pixman_format, - src->width, - src->height, - 0); - if (unlikely (rgba_clone->base.status)) - goto FAIL; - - _cairo_pattern_init_for_surface (&pattern, &src->base); - status = _cairo_surface_paint (&rgba_clone->base, - CAIRO_OPERATOR_SOURCE, - &pattern.base, NULL); - _cairo_pattern_fini (&pattern.base); - if (unlikely (status)) - goto FAIL; - - src = rgba_clone; - } - } - - if (! _cairo_gl_get_image_format_and_type (ctx->gl_flavor, - src->pixman_format, - &internal_format, - &format, - &type, - &has_alpha, - &needs_swap)) - { - cairo_bool_t is_supported; - - clone = _cairo_image_surface_coerce (src); - if (unlikely (status = clone->base.status)) - goto FAIL; - - is_supported = - _cairo_gl_get_image_format_and_type (ctx->gl_flavor, - clone->pixman_format, - &internal_format, - &format, - &type, - &has_alpha, - &needs_swap); - assert (is_supported); - assert (!needs_swap); - src = clone; - } - - cpp = PIXMAN_FORMAT_BPP (src->pixman_format) / 8; - - if (force_flush) { - status = _cairo_gl_surface_flush (&dst->base, 0); - if (unlikely (status)) - goto FAIL; - } - - if (_cairo_gl_surface_is_texture (dst)) { - void *data_start = src->data + src_y * src->stride + src_x * cpp; - void *data_start_gles2 = NULL; - - /* - * Due to GL_UNPACK_ROW_LENGTH missing in GLES2 we have to extract the - * image data ourselves in some cases. In particular, we must extract - * the pixels if: - * a. we don't want full-length lines or - * b. the row stride cannot be handled by GL itself using a 4 byte - * alignment constraint - */ - if (src->stride < 0 || - (ctx->gl_flavor == CAIRO_GL_FLAVOR_ES2 && - (src->width * cpp < src->stride - 3 || - width != src->width))) - { - glPixelStorei (GL_UNPACK_ALIGNMENT, 1); - status = _cairo_gl_surface_extract_image_data (src, src_x, src_y, - width, height, - &data_start_gles2); - if (unlikely (status)) - goto FAIL; - - data_start = data_start_gles2; - } - else - { - glPixelStorei (GL_UNPACK_ALIGNMENT, 4); - if (ctx->gl_flavor == CAIRO_GL_FLAVOR_DESKTOP || - ctx->gl_flavor == CAIRO_GL_FLAVOR_ES3) - glPixelStorei (GL_UNPACK_ROW_LENGTH, src->stride / cpp); - } - - /* we must resolve the renderbuffer to texture before we - upload image */ - status = _cairo_gl_surface_resolve_multisampling (dst); - if (unlikely (status)) { - free (data_start_gles2); - goto FAIL; - } - - _cairo_gl_context_activate (ctx, CAIRO_GL_TEX_TEMP); - glBindTexture (ctx->tex_target, dst->tex); - glTexParameteri (ctx->tex_target, GL_TEXTURE_MIN_FILTER, GL_NEAREST); - glTexParameteri (ctx->tex_target, GL_TEXTURE_MAG_FILTER, GL_NEAREST); - glTexSubImage2D (ctx->tex_target, 0, - dst_x, dst_y, width, height, - format, type, data_start); - - free (data_start_gles2); - - /* If we just treated some rgb-only data as rgba, then we have to - * go back and fix up the alpha channel where we filled in this - * texture data. - */ - if (!has_alpha) { - _cairo_gl_surface_fill_alpha_channel (dst, ctx, - dst_x, dst_y, - width, height); - } - if (ctx->gl_flavor == CAIRO_GL_FLAVOR_ES3) - dst->content_in_texture = TRUE; - } else { - cairo_surface_t *tmp; - - tmp = _cairo_gl_surface_create_scratch (ctx, - dst->base.content, - width, height); - if (unlikely (tmp->status)) - goto FAIL; - - status = _cairo_gl_surface_draw_image ((cairo_gl_surface_t *) tmp, - src, - src_x, src_y, - width, height, - 0, 0, force_flush); - if (status == CAIRO_INT_STATUS_SUCCESS) { - cairo_surface_pattern_t tmp_pattern; - cairo_rectangle_int_t r; - cairo_clip_t *clip; - - _cairo_pattern_init_for_surface (&tmp_pattern, tmp); - cairo_matrix_init_translate (&tmp_pattern.base.matrix, - -dst_x, -dst_y); - tmp_pattern.base.filter = CAIRO_FILTER_NEAREST; - tmp_pattern.base.extend = CAIRO_EXTEND_NONE; - - r.x = dst_x; - r.y = dst_y; - r.width = width; - r.height = height; - clip = _cairo_clip_intersect_rectangle (NULL, &r); - status = _cairo_surface_paint (&dst->base, - CAIRO_OPERATOR_SOURCE, - &tmp_pattern.base, - clip); - _cairo_clip_destroy (clip); - _cairo_pattern_fini (&tmp_pattern.base); - } - - cairo_surface_destroy (tmp); - if (ctx->gl_flavor == CAIRO_GL_FLAVOR_ES3) - dst->content_in_texture = TRUE; - } - -FAIL: - status = _cairo_gl_context_release (ctx, status); - - if (clone) - cairo_surface_destroy (&clone->base); - - if (rgba_clone) - cairo_surface_destroy (&rgba_clone->base); - - return status; -} - -static int _cairo_gl_surface_flavor (cairo_gl_surface_t *surface) -{ - cairo_gl_context_t *ctx = (cairo_gl_context_t *)surface->base.device; - return ctx->gl_flavor; -} - -static cairo_status_t -_cairo_gl_surface_finish (void *abstract_surface) -{ - cairo_gl_surface_t *surface = abstract_surface; - cairo_status_t status; - cairo_gl_context_t *ctx; - - status = _cairo_gl_context_acquire (surface->base.device, &ctx); - if (unlikely (status)) - return status; - - if (ctx->operands[CAIRO_GL_TEX_SOURCE].type == CAIRO_GL_OPERAND_TEXTURE && - ctx->operands[CAIRO_GL_TEX_SOURCE].texture.surface == surface) - _cairo_gl_context_destroy_operand (ctx, CAIRO_GL_TEX_SOURCE); - if (ctx->operands[CAIRO_GL_TEX_MASK].type == CAIRO_GL_OPERAND_TEXTURE && - ctx->operands[CAIRO_GL_TEX_MASK].texture.surface == surface) - _cairo_gl_context_destroy_operand (ctx, CAIRO_GL_TEX_MASK); - if (ctx->current_target == surface) - ctx->current_target = NULL; - - if (surface->fb) - ctx->dispatch.DeleteFramebuffers (1, &surface->fb); - if (surface->depth_stencil) - ctx->dispatch.DeleteRenderbuffers (1, &surface->depth_stencil); - if (surface->owns_tex) - glDeleteTextures (1, &surface->tex); - - if (surface->msaa_depth_stencil) - ctx->dispatch.DeleteRenderbuffers (1, &surface->msaa_depth_stencil); - -#if CAIRO_HAS_GL_SURFACE || CAIRO_HAS_GLESV3_SURFACE - if (surface->msaa_fb) - ctx->dispatch.DeleteFramebuffers (1, &surface->msaa_fb); - if (surface->msaa_rb) - ctx->dispatch.DeleteRenderbuffers (1, &surface->msaa_rb); -#endif - - _cairo_clip_destroy (surface->clip_on_stencil_buffer); - - return _cairo_gl_context_release (ctx, status); -} - -static cairo_image_surface_t * -_cairo_gl_surface_map_to_image (void *abstract_surface, - const cairo_rectangle_int_t *extents) -{ - cairo_gl_surface_t *surface = abstract_surface; - cairo_image_surface_t *image; - cairo_gl_context_t *ctx; - GLenum format, type; - pixman_format_code_t pixman_format; - unsigned int cpp; - cairo_bool_t flipped, mesa_invert; - cairo_status_t status; - int y; - - status = _cairo_gl_context_acquire (surface->base.device, &ctx); - if (unlikely (status)) { - return _cairo_image_surface_create_in_error (status); - } - - /* Want to use a switch statement here but the compiler gets whiny. */ - if (surface->base.content == CAIRO_CONTENT_COLOR_ALPHA) { - format = GL_BGRA; - pixman_format = PIXMAN_a8r8g8b8; - type = GL_UNSIGNED_INT_8_8_8_8_REV; - cpp = 4; - } else if (surface->base.content == CAIRO_CONTENT_COLOR) { - format = GL_BGRA; - pixman_format = PIXMAN_x8r8g8b8; - type = GL_UNSIGNED_INT_8_8_8_8_REV; - cpp = 4; - } else if (surface->base.content == CAIRO_CONTENT_ALPHA) { - format = GL_ALPHA; - pixman_format = PIXMAN_a8; - type = GL_UNSIGNED_BYTE; - cpp = 1; - } else { - ASSERT_NOT_REACHED; - return NULL; - } - - if (_cairo_gl_surface_flavor (surface) == CAIRO_GL_FLAVOR_ES3 || - _cairo_gl_surface_flavor (surface) == CAIRO_GL_FLAVOR_ES2) { - /* If only RGBA is supported, we must download data in a compatible - * format. This means that pixman will convert the data on the CPU when - * interacting with other image surfaces. For ALPHA, GLES2 does not - * support GL_PACK_ROW_LENGTH anyway, and this makes sure that the - * pixman image that is created has row_stride = row_width * bpp. */ - if (surface->base.content == CAIRO_CONTENT_ALPHA || !ctx->can_read_bgra) { - cairo_bool_t little_endian = _cairo_is_little_endian (); - format = GL_RGBA; - - if (surface->base.content == CAIRO_CONTENT_COLOR) { - pixman_format = little_endian ? - PIXMAN_x8b8g8r8 : PIXMAN_r8g8b8x8; - } else { - pixman_format = little_endian ? - PIXMAN_a8b8g8r8 : PIXMAN_r8g8b8a8; - } - } - - /* GLES2 only supports GL_UNSIGNED_BYTE. */ - type = GL_UNSIGNED_BYTE; - cpp = 4; - } - - image = (cairo_image_surface_t*) - _cairo_image_surface_create_with_pixman_format (NULL, - pixman_format, - extents->width, - extents->height, - -1); - if (unlikely (image->base.status)) { - status = _cairo_gl_context_release (ctx, status); - return image; - } - - cairo_surface_set_device_offset (&image->base, -extents->x, -extents->y); - - /* If the original surface has not been modified or - * is clear, we can avoid downloading data. */ - if (surface->base.is_clear || surface->base.serial == 0) { - status = _cairo_gl_context_release (ctx, status); - return image; - } - - /* This is inefficient, as we'd rather just read the thing without making - * it the destination. But then, this is the fallback path, so let's not - * fall back instead. - */ - _cairo_gl_composite_flush (ctx); - - if (ctx->gl_flavor != CAIRO_GL_FLAVOR_ES3) { - _cairo_gl_context_set_destination (ctx, surface, FALSE); - } else { - if (surface->content_in_texture) { - _cairo_gl_ensure_framebuffer (ctx, surface); - ctx->dispatch.BindFramebuffer (GL_FRAMEBUFFER, surface->fb); - } else { - status = _cairo_gl_surface_resolve_multisampling (surface); - if (unlikely (status)) { - status = _cairo_gl_context_release (ctx, status); - cairo_surface_destroy (&image->base); - return _cairo_image_surface_create_in_error (status); - } - } - } - - flipped = ! _cairo_gl_surface_is_texture (surface); - mesa_invert = flipped && ctx->has_mesa_pack_invert; - - glPixelStorei (GL_PACK_ALIGNMENT, 4); - if (ctx->gl_flavor == CAIRO_GL_FLAVOR_DESKTOP || - ctx->gl_flavor == CAIRO_GL_FLAVOR_ES3) - glPixelStorei (GL_PACK_ROW_LENGTH, image->stride / cpp); - if (mesa_invert) - glPixelStorei (GL_PACK_INVERT_MESA, 1); - - y = extents->y; - if (flipped) - y = surface->height - extents->y - extents->height; - - glReadPixels (extents->x, y, - extents->width, extents->height, - format, type, image->data); - if (mesa_invert) - glPixelStorei (GL_PACK_INVERT_MESA, 0); - - status = _cairo_gl_context_release (ctx, status); - if (unlikely (status)) { - cairo_surface_destroy (&image->base); - return _cairo_image_surface_create_in_error (status); - } - - /* We must invert the image manually if we lack GL_MESA_pack_invert */ - if (flipped && ! mesa_invert) { - uint8_t stack[1024], *row = stack; - uint8_t *top = image->data; - uint8_t *bot = image->data + (image->height-1)*image->stride; - - if (image->stride > (int)sizeof(stack)) { - row = _cairo_malloc (image->stride); - if (unlikely (row == NULL)) { - cairo_surface_destroy (&image->base); - return _cairo_image_surface_create_in_error (_cairo_error (CAIRO_STATUS_NO_MEMORY)); - } - } - - while (top < bot) { - memcpy (row, top, image->stride); - memcpy (top, bot, image->stride); - memcpy (bot, row, image->stride); - top += image->stride; - bot -= image->stride; - } - - if (row != stack) - free(row); - } - - image->base.is_clear = FALSE; - return image; -} - -static cairo_surface_t * -_cairo_gl_surface_source (void *abstract_surface, - cairo_rectangle_int_t *extents) -{ - cairo_gl_surface_t *surface = abstract_surface; - - if (extents) { - extents->x = extents->y = 0; - extents->width = surface->width; - extents->height = surface->height; - } - - return &surface->base; -} - -static cairo_status_t -_cairo_gl_surface_acquire_source_image (void *abstract_surface, - cairo_image_surface_t **image_out, - void **image_extra) -{ - cairo_gl_surface_t *surface = abstract_surface; - cairo_rectangle_int_t extents; - - *image_extra = NULL; - - extents.x = extents.y = 0; - extents.width = surface->width; - extents.height = surface->height; - - *image_out = (cairo_image_surface_t *) - _cairo_gl_surface_map_to_image (surface, &extents); - return (*image_out)->base.status; -} - -static void -_cairo_gl_surface_release_source_image (void *abstract_surface, - cairo_image_surface_t *image, - void *image_extra) -{ - cairo_surface_destroy (&image->base); -} - -static cairo_int_status_t -_cairo_gl_surface_unmap_image (void *abstract_surface, - cairo_image_surface_t *image) -{ - cairo_int_status_t status; - - status = _cairo_gl_surface_draw_image (abstract_surface, image, - 0, 0, - image->width, image->height, - image->base.device_transform_inverse.x0, - image->base.device_transform_inverse.y0, - TRUE); - - cairo_surface_finish (&image->base); - cairo_surface_destroy (&image->base); - - return status; -} - -static cairo_bool_t -_cairo_gl_surface_get_extents (void *abstract_surface, - cairo_rectangle_int_t *rectangle) -{ - cairo_gl_surface_t *surface = abstract_surface; - - rectangle->x = 0; - rectangle->y = 0; - rectangle->width = surface->width; - rectangle->height = surface->height; - - return TRUE; -} - -static cairo_status_t -_cairo_gl_surface_flush (void *abstract_surface, unsigned flags) -{ - cairo_gl_surface_t *surface = abstract_surface; - cairo_status_t status; - cairo_gl_context_t *ctx; - - if (flags) - return CAIRO_STATUS_SUCCESS; - - status = _cairo_gl_context_acquire (surface->base.device, &ctx); - if (unlikely (status)) - return status; - - if ((ctx->operands[CAIRO_GL_TEX_SOURCE].type == CAIRO_GL_OPERAND_TEXTURE && - ctx->operands[CAIRO_GL_TEX_SOURCE].texture.surface == surface) || - (ctx->operands[CAIRO_GL_TEX_MASK].type == CAIRO_GL_OPERAND_TEXTURE && - ctx->operands[CAIRO_GL_TEX_MASK].texture.surface == surface) || - (ctx->current_target == surface)) - _cairo_gl_composite_flush (ctx); - - status = _cairo_gl_surface_resolve_multisampling (surface); - - return _cairo_gl_context_release (ctx, status); -} - -cairo_int_status_t -_cairo_gl_surface_resolve_multisampling (cairo_gl_surface_t *surface) -{ - cairo_gl_context_t *ctx; - cairo_int_status_t status; - - if (! surface->msaa_active) - return CAIRO_INT_STATUS_SUCCESS; - - if (surface->base.device == NULL) - return CAIRO_INT_STATUS_SUCCESS; - - /* GLES surfaces do not need explicit resolution. */ - if (((cairo_gl_context_t *) surface->base.device)->gl_flavor == CAIRO_GL_FLAVOR_ES2) - return CAIRO_INT_STATUS_SUCCESS; - else if (((cairo_gl_context_t *) surface->base.device)->gl_flavor == CAIRO_GL_FLAVOR_ES3 && - surface->content_in_texture) - return CAIRO_INT_STATUS_SUCCESS; - - if (! _cairo_gl_surface_is_texture (surface)) - return CAIRO_INT_STATUS_SUCCESS; - - status = _cairo_gl_context_acquire (surface->base.device, &ctx); - if (unlikely (status)) - return status; - -#if CAIRO_HAS_GLESV3_SURFACE - _cairo_gl_composite_flush (ctx); - ctx->current_target = NULL; - _cairo_gl_context_bind_framebuffer (ctx, surface, FALSE); - if (ctx->gl_flavor == CAIRO_GL_FLAVOR_ES3) - surface->content_in_texture = TRUE; - -#elif CAIRO_HAS_GL_SURFACE - ctx->current_target = surface; - _cairo_gl_context_bind_framebuffer (ctx, surface, FALSE); - -#else - ctx->current_target = surface; - -#endif - - status = _cairo_gl_context_release (ctx, status); - return status; -} - -static const cairo_compositor_t * -get_compositor (cairo_gl_surface_t *surface) -{ - cairo_gl_context_t *ctx = (cairo_gl_context_t *)surface->base.device; - return ctx->compositor; -} - -static cairo_int_status_t -_cairo_gl_surface_paint (void *surface, - cairo_operator_t op, - const cairo_pattern_t *source, - const cairo_clip_t *clip) -{ - /* simplify the common case of clearing the surface */ - if (clip == NULL) { - if (op == CAIRO_OPERATOR_CLEAR) - return _cairo_gl_surface_clear (surface, CAIRO_COLOR_TRANSPARENT); - else if (source->type == CAIRO_PATTERN_TYPE_SOLID && - (op == CAIRO_OPERATOR_SOURCE || - (op == CAIRO_OPERATOR_OVER && _cairo_pattern_is_opaque_solid (source)))) { - return _cairo_gl_surface_clear (surface, - &((cairo_solid_pattern_t *) source)->color); - } - } - - return _cairo_compositor_paint (get_compositor (surface), surface, - op, source, clip); -} - -static cairo_int_status_t -_cairo_gl_surface_mask (void *surface, - cairo_operator_t op, - const cairo_pattern_t *source, - const cairo_pattern_t *mask, - const cairo_clip_t *clip) -{ - return _cairo_compositor_mask (get_compositor (surface), surface, - op, source, mask, clip); -} - -static cairo_int_status_t -_cairo_gl_surface_stroke (void *surface, - cairo_operator_t op, - const cairo_pattern_t *source, - const cairo_path_fixed_t *path, - const cairo_stroke_style_t *style, - const cairo_matrix_t *ctm, - const cairo_matrix_t *ctm_inverse, - double tolerance, - cairo_antialias_t antialias, - const cairo_clip_t *clip) -{ - return _cairo_compositor_stroke (get_compositor (surface), surface, - op, source, path, style, - ctm, ctm_inverse, tolerance, antialias, - clip); -} - -static cairo_int_status_t -_cairo_gl_surface_fill (void *surface, - cairo_operator_t op, - const cairo_pattern_t *source, - const cairo_path_fixed_t*path, - cairo_fill_rule_t fill_rule, - double tolerance, - cairo_antialias_t antialias, - const cairo_clip_t *clip) -{ - return _cairo_compositor_fill (get_compositor (surface), surface, - op, source, path, - fill_rule, tolerance, antialias, - clip); -} - -static cairo_int_status_t -_cairo_gl_surface_glyphs (void *surface, - cairo_operator_t op, - const cairo_pattern_t *source, - cairo_glyph_t *glyphs, - int num_glyphs, - cairo_scaled_font_t *font, - const cairo_clip_t *clip) -{ - return _cairo_compositor_glyphs (get_compositor (surface), surface, - op, source, glyphs, num_glyphs, font, - clip); -} - -static const cairo_surface_backend_t _cairo_gl_surface_backend = { - CAIRO_SURFACE_TYPE_GL, - _cairo_gl_surface_finish, - _cairo_default_context_create, - - _cairo_gl_surface_create_similar, - NULL, /* similar image */ - _cairo_gl_surface_map_to_image, - _cairo_gl_surface_unmap_image, - - _cairo_gl_surface_source, - _cairo_gl_surface_acquire_source_image, - _cairo_gl_surface_release_source_image, - NULL, /* snapshot */ - - NULL, /* copy_page */ - NULL, /* show_page */ - - _cairo_gl_surface_get_extents, - _cairo_image_surface_get_font_options, - - _cairo_gl_surface_flush, - NULL, /* mark_dirty_rectangle */ - - _cairo_gl_surface_paint, - _cairo_gl_surface_mask, - _cairo_gl_surface_stroke, - _cairo_gl_surface_fill, - NULL, /* fill/stroke */ - _cairo_gl_surface_glyphs, -}; diff --git a/gfx/cairo/cairo/src/cairo-gl-traps-compositor.c b/gfx/cairo/cairo/src/cairo-gl-traps-compositor.c deleted file mode 100644 index 7938c5b20a..0000000000 --- a/gfx/cairo/cairo/src/cairo-gl-traps-compositor.c +++ /dev/null @@ -1,531 +0,0 @@ -/* cairo - a vector graphics library with display and print output - * - * Copyright © 2009 Eric Anholt - * Copyright © 2009 Chris Wilson - * Copyright © 2005,2010 Red Hat, Inc - * Copyright © 2011 Intel Corporation - * - * This library is free software; you can redistribute it and/or - * modify it either under the terms of the GNU Lesser General Public - * License version 2.1 as published by the Free Software Foundation - * (the "LGPL") or, at your option, under the terms of the Mozilla - * Public License Version 1.1 (the "MPL"). If you do not alter this - * notice, a recipient may use your version of this file under either - * the MPL or the LGPL. - * - * You should have received a copy of the LGPL along with this library - * in the file COPYING-LGPL-2.1; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Suite 500, Boston, MA 02110-1335, 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): - * Benjamin Otte <otte@gnome.org> - * Carl Worth <cworth@cworth.org> - * Chris Wilson <chris@chris-wilson.co.uk> - * Eric Anholt <eric@anholt.net> - */ - -#include "cairoint.h" - -#include "cairo-gl-private.h" - -#include "cairo-composite-rectangles-private.h" -#include "cairo-compositor-private.h" -#include "cairo-default-context-private.h" -#include "cairo-error-private.h" -#include "cairo-image-surface-private.h" -#include "cairo-spans-compositor-private.h" -#include "cairo-surface-backend-private.h" -#include "cairo-surface-offset-private.h" - -static cairo_int_status_t -acquire (void *abstract_dst) -{ - return CAIRO_STATUS_SUCCESS; -} - -static cairo_int_status_t -release (void *abstract_dst) -{ - return CAIRO_STATUS_SUCCESS; -} - -static cairo_int_status_t -set_clip_region (void *_surface, - cairo_region_t *region) -{ - cairo_gl_surface_t *surface = _surface; - - surface->clip_region = region; - return CAIRO_STATUS_SUCCESS; -} - -static cairo_int_status_t -draw_image_boxes (void *_dst, - cairo_image_surface_t *image, - cairo_boxes_t *boxes, - int dx, int dy) -{ - cairo_gl_surface_t *dst = _dst; - struct _cairo_boxes_chunk *chunk; - int i; - - for (chunk = &boxes->chunks; chunk; chunk = chunk->next) { - for (i = 0; i < chunk->count; i++) { - cairo_box_t *b = &chunk->base[i]; - int x = _cairo_fixed_integer_part (b->p1.x); - int y = _cairo_fixed_integer_part (b->p1.y); - int w = _cairo_fixed_integer_part (b->p2.x) - x; - int h = _cairo_fixed_integer_part (b->p2.y) - y; - cairo_status_t status; - - status = _cairo_gl_surface_draw_image (dst, image, - x + dx, y + dy, - w, h, - x, y, - TRUE); - if (unlikely (status)) - return status; - } - } - - return CAIRO_STATUS_SUCCESS; -} - -static void -emit_aligned_boxes (cairo_gl_context_t *ctx, - const cairo_boxes_t *boxes) -{ - const struct _cairo_boxes_chunk *chunk; - cairo_gl_emit_rect_t emit = _cairo_gl_context_choose_emit_rect (ctx); - int i; - - for (chunk = &boxes->chunks; chunk; chunk = chunk->next) { - for (i = 0; i < chunk->count; i++) { - int x1 = _cairo_fixed_integer_part (chunk->base[i].p1.x); - int y1 = _cairo_fixed_integer_part (chunk->base[i].p1.y); - int x2 = _cairo_fixed_integer_part (chunk->base[i].p2.x); - int y2 = _cairo_fixed_integer_part (chunk->base[i].p2.y); - emit (ctx, x1, y1, x2, y2); - } - } -} - -static cairo_int_status_t -fill_boxes (void *_dst, - cairo_operator_t op, - const cairo_color_t *color, - cairo_boxes_t *boxes) -{ - cairo_gl_composite_t setup; - cairo_gl_context_t *ctx; - cairo_int_status_t status; - - status = _cairo_gl_composite_init (&setup, op, _dst, FALSE); - if (unlikely (status)) - goto FAIL; - - _cairo_gl_composite_set_solid_source (&setup, color); - - status = _cairo_gl_composite_begin (&setup, &ctx); - if (unlikely (status)) - goto FAIL; - - emit_aligned_boxes (ctx, boxes); - status = _cairo_gl_context_release (ctx, CAIRO_STATUS_SUCCESS); - -FAIL: - _cairo_gl_composite_fini (&setup); - return status; -} - -static cairo_int_status_t -composite_boxes (void *_dst, - cairo_operator_t op, - cairo_surface_t *abstract_src, - cairo_surface_t *abstract_mask, - int src_x, - int src_y, - int mask_x, - int mask_y, - int dst_x, - int dst_y, - cairo_boxes_t *boxes, - const cairo_rectangle_int_t *extents) -{ - cairo_gl_composite_t setup; - cairo_gl_context_t *ctx; - cairo_int_status_t status; - - status = _cairo_gl_composite_init (&setup, op, _dst, FALSE); - if (unlikely (status)) - goto FAIL; - - _cairo_gl_composite_set_source_operand (&setup, - source_to_operand (abstract_src)); - _cairo_gl_operand_translate (&setup.src, dst_x-src_x, dst_y-src_y); - - _cairo_gl_composite_set_mask_operand (&setup, - source_to_operand (abstract_mask)); - _cairo_gl_operand_translate (&setup.mask, dst_x-mask_x, dst_y-mask_y); - - status = _cairo_gl_composite_begin (&setup, &ctx); - if (unlikely (status)) - goto FAIL; - - emit_aligned_boxes (ctx, boxes); - status = _cairo_gl_context_release (ctx, CAIRO_STATUS_SUCCESS); - -FAIL: - _cairo_gl_composite_fini (&setup); - return status; -} - -static cairo_int_status_t -composite (void *_dst, - cairo_operator_t op, - cairo_surface_t *abstract_src, - cairo_surface_t *abstract_mask, - int src_x, - int src_y, - int mask_x, - int mask_y, - int dst_x, - int dst_y, - unsigned int width, - unsigned int height) -{ - cairo_gl_composite_t setup; - cairo_gl_context_t *ctx; - cairo_int_status_t status; - - status = _cairo_gl_composite_init (&setup, op, _dst, FALSE); - if (unlikely (status)) - goto FAIL; - - _cairo_gl_composite_set_source_operand (&setup, - source_to_operand (abstract_src)); - _cairo_gl_operand_translate (&setup.src, dst_x-src_x, dst_y-src_y); - - _cairo_gl_composite_set_mask_operand (&setup, - source_to_operand (abstract_mask)); - _cairo_gl_operand_translate (&setup.mask, dst_x-mask_x, dst_y-mask_y); - - status = _cairo_gl_composite_begin (&setup, &ctx); - if (unlikely (status)) - goto FAIL; - - /* XXX clip */ - _cairo_gl_context_emit_rect (ctx, dst_x, dst_y, dst_x+width, dst_y+height); - status = _cairo_gl_context_release (ctx, CAIRO_STATUS_SUCCESS); - -FAIL: - _cairo_gl_composite_fini (&setup); - return status; -} - -static cairo_int_status_t -lerp (void *dst, - cairo_surface_t *src, - cairo_surface_t *mask, - int src_x, - int src_y, - int mask_x, - int mask_y, - int dst_x, - int dst_y, - unsigned int width, - unsigned int height) -{ - cairo_int_status_t status; - - /* we could avoid some repetition... */ - status = composite (dst, CAIRO_OPERATOR_DEST_OUT, mask, NULL, - mask_x, mask_y, - 0, 0, - dst_x, dst_y, - width, height); - if (unlikely (status)) - return status; - - status = composite (dst, CAIRO_OPERATOR_ADD, src, mask, - src_x, src_y, - mask_x, mask_y, - dst_x, dst_y, - width, height); - if (unlikely (status)) - return status; - - return CAIRO_STATUS_SUCCESS; -} - -static cairo_int_status_t -traps_to_operand (void *_dst, - const cairo_rectangle_int_t *extents, - cairo_antialias_t antialias, - cairo_traps_t *traps, - cairo_gl_operand_t *operand, - int dst_x, int dst_y) -{ - pixman_format_code_t pixman_format; - pixman_image_t *pixman_image; - cairo_surface_t *image, *mask; - cairo_surface_pattern_t pattern; - cairo_status_t status; - - pixman_format = antialias != CAIRO_ANTIALIAS_NONE ? PIXMAN_a8 : PIXMAN_a1; - pixman_image = pixman_image_create_bits (pixman_format, - extents->width, - extents->height, - NULL, 0); - if (unlikely (pixman_image == NULL)) - return _cairo_error (CAIRO_STATUS_NO_MEMORY); - - _pixman_image_add_traps (pixman_image, extents->x, extents->y, traps); - image = _cairo_image_surface_create_for_pixman_image (pixman_image, - pixman_format); - if (unlikely (image->status)) { - pixman_image_unref (pixman_image); - return image->status; - } - - mask = _cairo_surface_create_scratch (_dst, - CAIRO_CONTENT_COLOR_ALPHA, - extents->width, - extents->height, - NULL); - if (unlikely (mask->status)) { - cairo_surface_destroy (image); - return mask->status; - } - - status = _cairo_gl_surface_draw_image ((cairo_gl_surface_t *)mask, - (cairo_image_surface_t *)image, - 0, 0, - extents->width, extents->height, - 0, 0, - TRUE); - cairo_surface_destroy (image); - - if (unlikely (status)) - goto error; - - _cairo_pattern_init_for_surface (&pattern, mask); - cairo_matrix_init_translate (&pattern.base.matrix, - -extents->x+dst_x, -extents->y+dst_y); - pattern.base.filter = CAIRO_FILTER_NEAREST; - pattern.base.extend = CAIRO_EXTEND_NONE; - status = _cairo_gl_operand_init (operand, &pattern.base, _dst, - &_cairo_unbounded_rectangle, - &_cairo_unbounded_rectangle, - FALSE); - _cairo_pattern_fini (&pattern.base); - - if (unlikely (status)) - goto error; - - operand->texture.owns_surface = (cairo_gl_surface_t *)mask; - return CAIRO_STATUS_SUCCESS; - -error: - cairo_surface_destroy (mask); - return status; -} - -static cairo_int_status_t -composite_traps (void *_dst, - cairo_operator_t op, - cairo_surface_t *abstract_src, - int src_x, - int src_y, - int dst_x, - int dst_y, - const cairo_rectangle_int_t *extents, - cairo_antialias_t antialias, - cairo_traps_t *traps) -{ - cairo_gl_composite_t setup; - cairo_gl_context_t *ctx; - cairo_int_status_t status; - - status = _cairo_gl_composite_init (&setup, op, _dst, FALSE); - if (unlikely (status)) - goto FAIL; - - _cairo_gl_composite_set_source_operand (&setup, - source_to_operand (abstract_src)); - _cairo_gl_operand_translate (&setup.src, -src_x-dst_x, -src_y-dst_y); - status = traps_to_operand (_dst, extents, antialias, traps, &setup.mask, dst_x, dst_y); - if (unlikely (status)) - goto FAIL; - - status = _cairo_gl_composite_begin (&setup, &ctx); - if (unlikely (status)) - goto FAIL; - - /* XXX clip */ - _cairo_gl_context_emit_rect (ctx, - extents->x-dst_x, extents->y-dst_y, - extents->x-dst_x+extents->width, - extents->y-dst_y+extents->height); - status = _cairo_gl_context_release (ctx, CAIRO_STATUS_SUCCESS); - -FAIL: - _cairo_gl_composite_fini (&setup); - return status; -} - -static cairo_gl_surface_t * -tristrip_to_surface (void *_dst, - const cairo_rectangle_int_t *extents, - cairo_antialias_t antialias, - cairo_tristrip_t *strip) -{ - pixman_format_code_t pixman_format; - pixman_image_t *pixman_image; - cairo_surface_t *image, *mask; - cairo_status_t status; - - pixman_format = antialias != CAIRO_ANTIALIAS_NONE ? PIXMAN_a8 : PIXMAN_a1, - pixman_image = pixman_image_create_bits (pixman_format, - extents->width, - extents->height, - NULL, 0); - if (unlikely (pixman_image == NULL)) - return (cairo_gl_surface_t *)_cairo_surface_create_in_error (_cairo_error (CAIRO_STATUS_NO_MEMORY)); - - _pixman_image_add_tristrip (pixman_image, extents->x, extents->y, strip); - image = _cairo_image_surface_create_for_pixman_image (pixman_image, - pixman_format); - if (unlikely (image->status)) { - pixman_image_unref (pixman_image); - return (cairo_gl_surface_t *)image; - } - - mask = _cairo_surface_create_scratch (_dst, - CAIRO_CONTENT_COLOR_ALPHA, - extents->width, - extents->height, - NULL); - if (unlikely (mask->status)) { - cairo_surface_destroy (image); - return (cairo_gl_surface_t *)mask; - } - - status = _cairo_gl_surface_draw_image ((cairo_gl_surface_t *)mask, - (cairo_image_surface_t *)image, - 0, 0, - extents->width, extents->height, - 0, 0, - TRUE); - cairo_surface_destroy (image); - if (unlikely (status)) { - cairo_surface_destroy (mask); - return (cairo_gl_surface_t*)_cairo_surface_create_in_error (status); - } - - return (cairo_gl_surface_t*)mask; -} - -static cairo_int_status_t -composite_tristrip (void *_dst, - cairo_operator_t op, - cairo_surface_t *abstract_src, - int src_x, - int src_y, - int dst_x, - int dst_y, - const cairo_rectangle_int_t *extents, - cairo_antialias_t antialias, - cairo_tristrip_t *strip) -{ - cairo_gl_composite_t setup; - cairo_gl_context_t *ctx; - cairo_gl_surface_t *mask; - cairo_int_status_t status; - - mask = tristrip_to_surface (_dst, extents, antialias, strip); - if (unlikely (mask->base.status)) - return mask->base.status; - - status = _cairo_gl_composite_init (&setup, op, _dst, FALSE); - if (unlikely (status)) - goto FAIL; - - _cairo_gl_composite_set_source_operand (&setup, - source_to_operand (abstract_src)); - - //_cairo_gl_composite_set_mask_surface (&setup, mask, 0, 0); - - status = _cairo_gl_composite_begin (&setup, &ctx); - if (unlikely (status)) - goto FAIL; - - /* XXX clip */ - _cairo_gl_context_emit_rect (ctx, - dst_x, dst_y, - dst_x+extents->width, - dst_y+extents->height); - status = _cairo_gl_context_release (ctx, CAIRO_STATUS_SUCCESS); - -FAIL: - _cairo_gl_composite_fini (&setup); - cairo_surface_destroy (&mask->base); - return status; -} - -static cairo_int_status_t -check_composite (const cairo_composite_rectangles_t *extents) -{ - if (! _cairo_gl_operator_is_supported (extents->op)) - return UNSUPPORTED ("unsupported operator"); - - return CAIRO_STATUS_SUCCESS; -} - -const cairo_compositor_t * -_cairo_gl_traps_compositor_get (void) -{ - static cairo_atomic_once_t once = CAIRO_ATOMIC_ONCE_INIT; - static cairo_traps_compositor_t compositor; - - if (_cairo_atomic_init_once_enter(&once)) { - _cairo_traps_compositor_init (&compositor, &_cairo_fallback_compositor); - compositor.acquire = acquire; - compositor.release = release; - compositor.set_clip_region = set_clip_region; - compositor.pattern_to_surface = _cairo_gl_pattern_to_source; - compositor.draw_image_boxes = draw_image_boxes; - //compositor.copy_boxes = copy_boxes; - compositor.fill_boxes = fill_boxes; - compositor.check_composite = check_composite; - compositor.composite = composite; - compositor.lerp = lerp; - //compositor.check_composite_boxes = check_composite_boxes; - compositor.composite_boxes = composite_boxes; - //compositor.check_composite_traps = check_composite_traps; - compositor.composite_traps = composite_traps; - //compositor.check_composite_tristrip = check_composite_traps; - compositor.composite_tristrip = composite_tristrip; - compositor.check_composite_glyphs = _cairo_gl_check_composite_glyphs; - compositor.composite_glyphs = _cairo_gl_composite_glyphs; - - _cairo_atomic_init_once_leave(&once); - } - - return &compositor.base; -} diff --git a/gfx/cairo/cairo/src/cairo-gl.h b/gfx/cairo/cairo/src/cairo-gl.h deleted file mode 100644 index 7cd869c76b..0000000000 --- a/gfx/cairo/cairo/src/cairo-gl.h +++ /dev/null @@ -1,155 +0,0 @@ -/* Cairo - a vector graphics library with display and print output - * - * Copyright © 2009 Eric Anholt - * Copyright © 2009 Chris Wilson - * - * 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., 51 Franklin Street, Suite 500, Boston, MA 02110-1335, 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 Eric Anholt. - */ - -/* - * cairo-gl.h: - * - * The cairo-gl backend provides an implementation of possibly - * hardware-accelerated cairo rendering by targeting the OpenGL API. - * The goal of the cairo-gl backend is to provide better performance - * with equal functionality to cairo-image where possible. It does - * not directly provide for applying additional OpenGL effects to - * cairo surfaces. - * - * Cairo-gl allows interoperability with other GL rendering through GL - * context sharing. Cairo-gl surfaces are created in reference to a - * #cairo_device_t, which represents a GL context created by the user. - * When that GL context is created with its sharePtr set to another - * context (or vice versa), its objects (textures backing cairo-gl - * surfaces) can be accessed in the other OpenGL context. This allows - * cairo-gl to maintain its drawing state in one context while the - * user's 3D rendering occurs in the user's other context. - * - * However, as only one context can be current to a thread at a time, - * cairo-gl may make its context current to the thread on any cairo - * call which interacts with a cairo-gl surface or the cairo-gl - * device. As a result, the user must make their own context current - * between any cairo calls and their own OpenGL rendering. - **/ - -#ifndef CAIRO_GL_H -#define CAIRO_GL_H - -#include "cairo.h" - -#if CAIRO_HAS_GL_SURFACE || CAIRO_HAS_GLESV2_SURFACE || CAIRO_HAS_GLESV3_SURFACE - -CAIRO_BEGIN_DECLS - -cairo_public cairo_surface_t * -cairo_gl_surface_create (cairo_device_t *device, - cairo_content_t content, - int width, int height); - -cairo_public cairo_surface_t * -cairo_gl_surface_create_for_texture (cairo_device_t *abstract_device, - cairo_content_t content, - unsigned int tex, - int width, int height); -cairo_public void -cairo_gl_surface_set_size (cairo_surface_t *surface, int width, int height); - -cairo_public int -cairo_gl_surface_get_width (cairo_surface_t *abstract_surface); - -cairo_public int -cairo_gl_surface_get_height (cairo_surface_t *abstract_surface); - -cairo_public void -cairo_gl_surface_swapbuffers (cairo_surface_t *surface); - -cairo_public void -cairo_gl_device_set_thread_aware (cairo_device_t *device, - cairo_bool_t thread_aware); - -#if CAIRO_HAS_GLX_FUNCTIONS -#include <GL/glx.h> - -cairo_public cairo_device_t * -cairo_glx_device_create (Display *dpy, GLXContext gl_ctx); - -cairo_public Display * -cairo_glx_device_get_display (cairo_device_t *device); - -cairo_public GLXContext -cairo_glx_device_get_context (cairo_device_t *device); - -cairo_public cairo_surface_t * -cairo_gl_surface_create_for_window (cairo_device_t *device, - Window win, - int width, int height); -#endif - -#if CAIRO_HAS_WGL_FUNCTIONS -#include <windows.h> - -cairo_public cairo_device_t * -cairo_wgl_device_create (HGLRC rc); - -cairo_public HGLRC -cairo_wgl_device_get_context (cairo_device_t *device); - -cairo_public cairo_surface_t * -cairo_gl_surface_create_for_dc (cairo_device_t *device, - HDC dc, - int width, - int height); -#endif - -#if CAIRO_HAS_EGL_FUNCTIONS -#include <EGL/egl.h> - -cairo_public cairo_device_t * -cairo_egl_device_create (EGLDisplay dpy, EGLContext egl); - -cairo_public cairo_surface_t * -cairo_gl_surface_create_for_egl (cairo_device_t *device, - EGLSurface egl, - int width, - int height); - -cairo_public EGLDisplay -cairo_egl_device_get_display (cairo_device_t *device); - -cairo_public EGLSurface -cairo_egl_device_get_context (cairo_device_t *device); - -#endif - -CAIRO_END_DECLS - -#else /* CAIRO_HAS_GL_SURFACE */ -# error Cairo was not compiled with support for the GL backend -#endif /* CAIRO_HAS_GL_SURFACE */ - -#endif /* CAIRO_GL_H */ diff --git a/gfx/cairo/cairo/src/cairo-glx-context.c b/gfx/cairo/cairo/src/cairo-glx-context.c deleted file mode 100644 index 66f5a0d1b4..0000000000 --- a/gfx/cairo/cairo/src/cairo-glx-context.c +++ /dev/null @@ -1,324 +0,0 @@ -/* cairo - a vector graphics library with display and print output - * - * Copyright © 2009 Eric Anholt - * Copyright © 2009 Chris Wilson - * Copyright © 2005 Red Hat, Inc - * - * This library is free software; you can redistribute it and/or - * modify it either under the terms of the GNU Lesser General Public - * License version 2.1 as published by the Free Software Foundation - * (the "LGPL") or, at your option, under the terms of the Mozilla - * Public License Version 1.1 (the "MPL"). If you do not alter this - * notice, a recipient may use your version of this file under either - * the MPL or the LGPL. - * - * You should have received a copy of the LGPL along with this library - * in the file COPYING-LGPL-2.1; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Suite 500, Boston, MA 02110-1335, 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 Worth <cworth@cworth.org> - * Chris Wilson <chris@chris-wilson.co.uk> - */ - -#include "cairoint.h" - -#include "cairo-gl-private.h" - -#include "cairo-error-private.h" - -#include <X11/Xutil.h> - -/* XXX needs hooking into XCloseDisplay() */ - -typedef struct _cairo_glx_context { - cairo_gl_context_t base; - - Display *display; - Window dummy_window; - GLXContext context; - - GLXDrawable previous_drawable; - GLXContext previous_context; - - cairo_bool_t has_multithread_makecurrent; -} cairo_glx_context_t; - -typedef struct _cairo_glx_surface { - cairo_gl_surface_t base; - - Window win; -} cairo_glx_surface_t; - -static cairo_bool_t -_context_acquisition_changed_glx_state (cairo_glx_context_t *ctx, - GLXDrawable current_drawable) -{ - return ctx->previous_drawable != current_drawable || - ctx->previous_context != ctx->context; -} - -static GLXDrawable -_glx_get_current_drawable (cairo_glx_context_t *ctx) -{ - if (ctx->base.current_target == NULL || - _cairo_gl_surface_is_texture (ctx->base.current_target)) { - return ctx->dummy_window; - } - - return ((cairo_glx_surface_t *) ctx->base.current_target)->win; -} - -static void -_glx_query_current_state (cairo_glx_context_t * ctx) -{ - ctx->previous_drawable = glXGetCurrentDrawable (); - ctx->previous_context = glXGetCurrentContext (); - - /* If any of the values were none, assume they are all none. Not all - drivers seem well behaved when it comes to using these values across - multiple threads. */ - if (ctx->previous_drawable == None || - ctx->previous_context == None) { - ctx->previous_drawable = None; - ctx->previous_context = None; - } -} - -static void -_glx_acquire (void *abstract_ctx) -{ - cairo_glx_context_t *ctx = abstract_ctx; - GLXDrawable current_drawable = _glx_get_current_drawable (ctx); - - _glx_query_current_state (ctx); - if (!_context_acquisition_changed_glx_state (ctx, current_drawable)) - return; - - glXMakeCurrent (ctx->display, current_drawable, ctx->context); -} - -static void -_glx_make_current (void *abstract_ctx, cairo_gl_surface_t *abstract_surface) -{ - cairo_glx_context_t *ctx = abstract_ctx; - cairo_glx_surface_t *surface = (cairo_glx_surface_t *) abstract_surface; - - /* Set the window as the target of our context. */ - glXMakeCurrent (ctx->display, surface->win, ctx->context); -} - -static void -_glx_release (void *abstract_ctx) -{ - cairo_glx_context_t *ctx = abstract_ctx; - - if (ctx->has_multithread_makecurrent || !ctx->base.thread_aware || - !_context_acquisition_changed_glx_state (ctx, - _glx_get_current_drawable (ctx))) { - return; - } - - glXMakeCurrent (ctx->display, None, None); -} - -static void -_glx_swap_buffers (void *abstract_ctx, - cairo_gl_surface_t *abstract_surface) -{ - cairo_glx_context_t *ctx = abstract_ctx; - cairo_glx_surface_t *surface = (cairo_glx_surface_t *) abstract_surface; - - glXSwapBuffers (ctx->display, surface->win); -} - -static void -_glx_destroy (void *abstract_ctx) -{ - cairo_glx_context_t *ctx = abstract_ctx; - - if (ctx->dummy_window != None) - XDestroyWindow (ctx->display, ctx->dummy_window); - - glXMakeCurrent (ctx->display, None, None); -} - -static cairo_status_t -_glx_dummy_window (Display *dpy, GLXContext gl_ctx, Window *dummy) -{ - int attr[3] = { GLX_FBCONFIG_ID, 0, None }; - GLXFBConfig *config; - XVisualInfo *vi; - Colormap cmap; - XSetWindowAttributes swa; - Window win = None; - int cnt; - - /* Create a dummy window created for the target GLX context that we can - * use to query the available GL/GLX extensions. - */ - glXQueryContext (dpy, gl_ctx, GLX_FBCONFIG_ID, &attr[1]); - - cnt = 0; - config = glXChooseFBConfig (dpy, DefaultScreen (dpy), attr, &cnt); - if (unlikely (cnt == 0)) - return _cairo_error (CAIRO_STATUS_INVALID_FORMAT); - - vi = glXGetVisualFromFBConfig (dpy, config[0]); - XFree (config); - - if (unlikely (vi == NULL)) - return _cairo_error (CAIRO_STATUS_INVALID_FORMAT); - - cmap = XCreateColormap (dpy, - RootWindow (dpy, vi->screen), - vi->visual, - AllocNone); - swa.colormap = cmap; - swa.border_pixel = 0; - win = XCreateWindow (dpy, RootWindow (dpy, vi->screen), - -1, -1, 1, 1, 0, - vi->depth, - InputOutput, - vi->visual, - CWBorderPixel | CWColormap, &swa); - XFreeColormap (dpy, cmap); - XFree (vi); - - XFlush (dpy); - if (unlikely (! glXMakeCurrent (dpy, win, gl_ctx))) { - XDestroyWindow (dpy, win); - return _cairo_error (CAIRO_STATUS_NO_MEMORY); - } - - *dummy = win; - return CAIRO_STATUS_SUCCESS; -} - -cairo_device_t * -cairo_glx_device_create (Display *dpy, GLXContext gl_ctx) -{ - cairo_glx_context_t *ctx; - cairo_status_t status; - Window dummy = None; - const char *glx_extensions; - - ctx = calloc (1, sizeof (cairo_glx_context_t)); - if (unlikely (ctx == NULL)) - return _cairo_gl_context_create_in_error (CAIRO_STATUS_NO_MEMORY); - - /* glx_dummy_window will call glXMakeCurrent, so we need to - * query the current state of the context now. */ - _glx_query_current_state (ctx); - - status = _glx_dummy_window (dpy, gl_ctx, &dummy); - if (unlikely (status)) { - free (ctx); - return _cairo_gl_context_create_in_error (status); - } - - ctx->display = dpy; - ctx->dummy_window = dummy; - ctx->context = gl_ctx; - - ctx->base.acquire = _glx_acquire; - ctx->base.release = _glx_release; - ctx->base.make_current = _glx_make_current; - ctx->base.swap_buffers = _glx_swap_buffers; - ctx->base.destroy = _glx_destroy; - - status = _cairo_gl_dispatch_init (&ctx->base.dispatch, - (cairo_gl_get_proc_addr_func_t) glXGetProcAddress); - if (unlikely (status)) { - free (ctx); - return _cairo_gl_context_create_in_error (status); - } - - status = _cairo_gl_context_init (&ctx->base); - if (unlikely (status)) { - free (ctx); - return _cairo_gl_context_create_in_error (status); - } - - glx_extensions = glXQueryExtensionsString (dpy, DefaultScreen (dpy)); - if (strstr(glx_extensions, "GLX_MESA_multithread_makecurrent")) { - ctx->has_multithread_makecurrent = TRUE; - } - - ctx->base.release (ctx); - - return &ctx->base.base; -} - -Display * -cairo_glx_device_get_display (cairo_device_t *device) -{ - cairo_glx_context_t *ctx; - - if (device->backend->type != CAIRO_DEVICE_TYPE_GL) { - _cairo_error_throw (CAIRO_STATUS_DEVICE_TYPE_MISMATCH); - return NULL; - } - - ctx = (cairo_glx_context_t *) device; - - return ctx->display; -} - -GLXContext -cairo_glx_device_get_context (cairo_device_t *device) -{ - cairo_glx_context_t *ctx; - - if (device->backend->type != CAIRO_DEVICE_TYPE_GL) { - _cairo_error_throw (CAIRO_STATUS_DEVICE_TYPE_MISMATCH); - return NULL; - } - - ctx = (cairo_glx_context_t *) device; - - return ctx->context; -} - -cairo_surface_t * -cairo_gl_surface_create_for_window (cairo_device_t *device, - Window win, - int width, - int height) -{ - cairo_glx_surface_t *surface; - - if (unlikely (device->status)) - return _cairo_surface_create_in_error (device->status); - - if (device->backend->type != CAIRO_DEVICE_TYPE_GL) - return _cairo_surface_create_in_error (_cairo_error (CAIRO_STATUS_SURFACE_TYPE_MISMATCH)); - - if (width <= 0 || height <= 0) - return _cairo_surface_create_in_error (_cairo_error (CAIRO_STATUS_INVALID_SIZE)); - - surface = calloc (1, sizeof (cairo_glx_surface_t)); - if (unlikely (surface == NULL)) - return _cairo_surface_create_in_error (_cairo_error (CAIRO_STATUS_NO_MEMORY)); - - _cairo_gl_surface_init (device, &surface->base, - CAIRO_CONTENT_COLOR_ALPHA, width, height); - surface->win = win; - - return &surface->base.base; -} diff --git a/gfx/cairo/cairo/src/cairo-gstate-private.h b/gfx/cairo/cairo/src/cairo-gstate-private.h index 198c669985..fe1556b038 100644 --- a/gfx/cairo/cairo/src/cairo-gstate-private.h +++ b/gfx/cairo/cairo/src/cairo-gstate-private.h @@ -140,6 +140,12 @@ cairo_private double _cairo_gstate_get_line_width (cairo_gstate_t *gstate); cairo_private cairo_status_t +_cairo_gstate_set_hairline (cairo_gstate_t *gstate, cairo_bool_t set_hairline); + +cairo_private cairo_bool_t +_cairo_gstate_get_hairline (cairo_gstate_t *gstate); + +cairo_private cairo_status_t _cairo_gstate_set_line_cap (cairo_gstate_t *gstate, cairo_line_cap_t line_cap); cairo_private cairo_line_cap_t diff --git a/gfx/cairo/cairo/src/cairo-gstate.c b/gfx/cairo/cairo/src/cairo-gstate.c index 4b31dca3b6..323f80488f 100644 --- a/gfx/cairo/cairo/src/cairo-gstate.c +++ b/gfx/cairo/cairo/src/cairo-gstate.c @@ -193,6 +193,7 @@ void _cairo_gstate_fini (cairo_gstate_t *gstate) { _cairo_stroke_style_fini (&gstate->stroke_style); + _cairo_font_options_fini (&gstate->font_options); cairo_font_face_destroy (gstate->font_face); gstate->font_face = NULL; @@ -470,7 +471,10 @@ _cairo_gstate_get_fill_rule (cairo_gstate_t *gstate) cairo_status_t _cairo_gstate_set_line_width (cairo_gstate_t *gstate, double width) { - gstate->stroke_style.line_width = width; + if (gstate->stroke_style.is_hairline) + gstate->stroke_style.pre_hairline_line_width = width; + else + gstate->stroke_style.line_width = width; return CAIRO_STATUS_SUCCESS; } @@ -482,6 +486,29 @@ _cairo_gstate_get_line_width (cairo_gstate_t *gstate) } cairo_status_t +_cairo_gstate_set_hairline (cairo_gstate_t *gstate, cairo_bool_t set_hairline) +{ + if (gstate->stroke_style.is_hairline != set_hairline) { + gstate->stroke_style.is_hairline = set_hairline; + + if (set_hairline) { + gstate->stroke_style.pre_hairline_line_width = gstate->stroke_style.line_width; + gstate->stroke_style.line_width = 0.0; + } else { + gstate->stroke_style.line_width = gstate->stroke_style.pre_hairline_line_width; + } + } + + return CAIRO_STATUS_SUCCESS; +} + +cairo_bool_t +_cairo_gstate_get_hairline (cairo_gstate_t *gstate) +{ + return gstate->stroke_style.is_hairline; +} + +cairo_status_t _cairo_gstate_set_line_cap (cairo_gstate_t *gstate, cairo_line_cap_t line_cap) { gstate->stroke_style.line_cap = line_cap; @@ -937,9 +964,22 @@ _cairo_gstate_copy_transformed_pattern (cairo_gstate_t *gstate, const cairo_pattern_t *original, const cairo_matrix_t *ctm_inverse) { + /* + * What calculations below do can be described in pseudo-code (so using nonexistent fields) as (using column vectors): + * pattern->matrix = surface->device_transform * + * pattern->matrix * + * ctm_inverse * + * gstate->target->device_transform_inverse + * + * The inverse of which is: + * pattern->matrix_inverse = gstate->target->device_transform * + * ctm * + * pattern->matrix_inverse * + * surface->device_transform_inverse + */ + _cairo_gstate_copy_pattern (pattern, original); - /* apply device_transform first so that it is transformed by ctm_inverse */ if (original->type == CAIRO_PATTERN_TYPE_SURFACE) { cairo_surface_pattern_t *surface_pattern; cairo_surface_t *surface; @@ -1106,7 +1146,7 @@ _cairo_gstate_mask (cairo_gstate_t *gstate, } _cairo_gstate_copy_transformed_mask (gstate, &mask_pattern.base, mask); - if (source->type == CAIRO_PATTERN_TYPE_SOLID && + if (source->type == CAIRO_PATTERN_TYPE_SOLID && !source->is_foreground_marker && mask_pattern.base.type == CAIRO_PATTERN_TYPE_SOLID && _cairo_operator_bounded_by_source (op)) { @@ -1159,7 +1199,7 @@ _cairo_gstate_stroke (cairo_gstate_t *gstate, cairo_path_fixed_t *path) if (gstate->op == CAIRO_OPERATOR_DEST) return CAIRO_STATUS_SUCCESS; - if (gstate->stroke_style.line_width <= 0.0) + if (gstate->stroke_style.line_width <= 0.0 && !gstate->stroke_style.is_hairline) return CAIRO_STATUS_SUCCESS; if (_cairo_clip_is_all_clipped (gstate->clip)) @@ -1709,11 +1749,12 @@ void _cairo_gstate_set_font_options (cairo_gstate_t *gstate, const cairo_font_options_t *options) { - if (memcmp (options, &gstate->font_options, sizeof (cairo_font_options_t)) == 0) + if (_cairo_font_options_compare (options, &gstate->font_options)) return; _cairo_gstate_unset_scaled_font (gstate); + _cairo_font_options_fini (&gstate->font_options); _cairo_font_options_init_copy (&gstate->font_options, options); } @@ -1721,7 +1762,8 @@ void _cairo_gstate_get_font_options (cairo_gstate_t *gstate, cairo_font_options_t *options) { - *options = gstate->font_options; + _cairo_font_options_fini (options); + _cairo_font_options_init_copy (options, &gstate->font_options); } cairo_status_t @@ -1878,6 +1920,8 @@ _cairo_gstate_ensure_scaled_font (cairo_gstate_t *gstate) &font_ctm, &options); + _cairo_font_options_fini (&options); + status = cairo_scaled_font_status (scaled_font); if (unlikely (status)) return status; diff --git a/gfx/cairo/cairo/src/cairo-hash.c b/gfx/cairo/cairo/src/cairo-hash.c index 151842eb6d..a3cc452b74 100644 --- a/gfx/cairo/cairo/src/cairo-hash.c +++ b/gfx/cairo/cairo/src/cairo-hash.c @@ -340,7 +340,7 @@ _cairo_hash_table_lookup (cairo_hash_table_t *hash_table, { cairo_hash_entry_t *entry; unsigned long table_size, i, idx, step; - unsigned long hash = key->hash; + uintptr_t hash = key->hash; entry = hash_table->cache[hash & 31]; if (entry && entry->hash == hash && hash_table->keys_equal (key, entry)) diff --git a/gfx/cairo/cairo/src/cairo-image-compositor.c b/gfx/cairo/cairo/src/cairo-image-compositor.c index 8bf3fd4b1e..0a293f05d6 100644 --- a/gfx/cairo/cairo/src/cairo-image-compositor.c +++ b/gfx/cairo/cairo/src/cairo-image-compositor.c @@ -898,7 +898,7 @@ composite_glyphs (void *_dst, index = index | (xphase << 24) | (yphase << 26); - glyph = pixman_glyph_cache_lookup (glyph_cache, info->font, (void *)index); + glyph = pixman_glyph_cache_lookup (glyph_cache, info->font, (void *)(uintptr_t)index); if (!glyph) { cairo_scaled_glyph_t *scaled_glyph; cairo_image_surface_t *glyph_surface; @@ -909,6 +909,7 @@ composite_glyphs (void *_dst, CAIRO_MUTEX_UNLOCK (_cairo_glyph_cache_mutex); status = _cairo_scaled_glyph_lookup (info->font, index, CAIRO_SCALED_GLYPH_INFO_SURFACE, + NULL, /* foreground color */ &scaled_glyph); CAIRO_MUTEX_LOCK (_cairo_glyph_cache_mutex); @@ -916,7 +917,7 @@ composite_glyphs (void *_dst, goto out_thaw; glyph_surface = scaled_glyph->surface; - glyph = pixman_glyph_cache_insert (glyph_cache, info->font, (void *)index, + glyph = pixman_glyph_cache_insert (glyph_cache, info->font, (void *)(uintptr_t)index, glyph_surface->base.device_transform.x0, glyph_surface->base.device_transform.y0, glyph_surface->pixman_image); @@ -997,6 +998,7 @@ composite_one_glyph (void *_dst, status = _cairo_scaled_glyph_lookup (info->font, info->glyphs[0].index, CAIRO_SCALED_GLYPH_INFO_SURFACE, + NULL, /* foreground color */ &scaled_glyph); if (unlikely (status)) @@ -1059,6 +1061,7 @@ composite_glyphs_via_mask (void *_dst, status = _cairo_scaled_glyph_lookup (info->font, info->glyphs[0].index, CAIRO_SCALED_GLYPH_INFO_SURFACE, + NULL, /* foreground color */ &scaled_glyph); if (unlikely (status)) { pixman_image_unref (white); @@ -1105,6 +1108,7 @@ composite_glyphs_via_mask (void *_dst, { status = _cairo_scaled_glyph_lookup (info->font, glyph_index, CAIRO_SCALED_GLYPH_INFO_SURFACE, + NULL, /* foreground color */ &scaled_glyph); if (unlikely (status)) { @@ -1231,6 +1235,7 @@ composite_glyphs (void *_dst, { status = _cairo_scaled_glyph_lookup (info->font, glyph_index, CAIRO_SCALED_GLYPH_INFO_SURFACE, + NULL, /* foreground color */ &scaled_glyph); if (unlikely (status)) diff --git a/gfx/cairo/cairo/src/cairo-image-info-private.h b/gfx/cairo/cairo/src/cairo-image-info-private.h index e64928e40e..3808d07b3d 100644 --- a/gfx/cairo/cairo/src/cairo-image-info-private.h +++ b/gfx/cairo/cairo/src/cairo-image-info-private.h @@ -48,7 +48,7 @@ typedef struct _cairo_image_info { cairo_private cairo_int_status_t _cairo_image_info_get_jpeg_info (cairo_image_info_t *info, const unsigned char *data, - long length); + unsigned long length); cairo_private cairo_int_status_t _cairo_image_info_get_jpx_info (cairo_image_info_t *info, diff --git a/gfx/cairo/cairo/src/cairo-image-info.c b/gfx/cairo/cairo/src/cairo-image-info.c index d147e37239..9693e487f6 100644 --- a/gfx/cairo/cairo/src/cairo-image-info.c +++ b/gfx/cairo/cairo/src/cairo-image-info.c @@ -90,7 +90,7 @@ _jpeg_extract_info (cairo_image_info_t *info, const unsigned char *p) cairo_int_status_t _cairo_image_info_get_jpeg_info (cairo_image_info_t *info, const unsigned char *data, - long length) + unsigned long length) { const unsigned char *p = data; @@ -162,9 +162,15 @@ static const unsigned char _jpx_signature[] = { }; static const unsigned char * -_jpx_next_box (const unsigned char *p) +_jpx_next_box (const unsigned char *p, const unsigned char *end) { - return p + get_unaligned_be32 (p); + if (p + 4 < end) { + uint32_t length = get_unaligned_be32 (p); + if (p + length < end) + return p + length; + } + + return end; } static const unsigned char * @@ -193,19 +199,25 @@ _jpx_find_box (const unsigned char *p, const unsigned char *end, uint32_t type) while (p < end) { if (_jpx_match_box (p, end, type)) return p; - p = _jpx_next_box (p); + p = _jpx_next_box (p, end); } return NULL; } -static void -_jpx_extract_info (const unsigned char *p, cairo_image_info_t *info) +static cairo_int_status_t +_jpx_extract_info (const unsigned char *p, cairo_image_info_t *info, const unsigned char *end) { + if (p + 11 >= end) { + return CAIRO_INT_STATUS_UNSUPPORTED; + } + info->height = get_unaligned_be32 (p); info->width = get_unaligned_be32 (p + 4); info->num_components = (p[8] << 8) + p[9]; info->bits_per_component = p[10]; + + return CAIRO_STATUS_SUCCESS; } cairo_int_status_t @@ -227,7 +239,7 @@ _cairo_image_info_get_jpx_info (cairo_image_info_t *info, if (! _jpx_match_box (p, end, JPX_FILETYPE)) return CAIRO_INT_STATUS_UNSUPPORTED; - p = _jpx_next_box (p); + p = _jpx_next_box (p, end); /* Locate the JP2 header box. */ p = _jpx_find_box (p, end, JPX_JP2_HEADER); @@ -242,9 +254,7 @@ _cairo_image_info_get_jpx_info (cairo_image_info_t *info, /* Get the image info */ p = _jpx_get_box_contents (p); - _jpx_extract_info (p, info); - - return CAIRO_STATUS_SUCCESS; + return _jpx_extract_info (p, info, end); } /* PNG (image/png) @@ -348,6 +358,8 @@ _jbig2_get_next_segment (const unsigned char *p, num_segs = p[0] >> 5; if (num_segs == 7) { + if (p + 4 >= end) + return NULL; num_segs = get_unaligned_be32 (p) & 0x1fffffff; ref_seg_bytes = 4 + ((num_segs + 1)/8); } else { diff --git a/gfx/cairo/cairo/src/cairo-image-source.c b/gfx/cairo/cairo/src/cairo-image-source.c index c56845ab2d..b8c1c88f59 100644 --- a/gfx/cairo/cairo/src/cairo-image-source.c +++ b/gfx/cairo/cairo/src/cairo-image-source.c @@ -1207,6 +1207,8 @@ _pixman_image_for_recording (cairo_image_surface_t *dst, clone = _cairo_image_surface_create_with_content (source->content, limit.width, limit.height); + if (dst->base.foreground_source) + clone->foreground_source = cairo_pattern_reference (dst->base.foreground_source); } m = NULL; @@ -1224,6 +1226,8 @@ _pixman_image_for_recording (cairo_image_surface_t *dst, /* Handle recursion by returning future reads from the current image */ proxy = attach_proxy (source, clone); status = _cairo_recording_surface_replay_with_clip (source, m, clone, NULL); + if (clone->foreground_used) + dst->base.foreground_used = clone->foreground_used; detach_proxy (source, proxy); if (unlikely (status)) { cairo_surface_destroy (clone); diff --git a/gfx/cairo/cairo/src/cairo-image-surface.c b/gfx/cairo/cairo/src/cairo-image-surface.c index 3b11eb9815..fe64cd76c1 100644 --- a/gfx/cairo/cairo/src/cairo-image-surface.c +++ b/gfx/cairo/cairo/src/cairo-image-surface.c @@ -248,6 +248,27 @@ _pixman_format_from_masks (cairo_format_masks_t *masks, return TRUE; } +#if PIXMAN_VERSION >= PIXMAN_VERSION_ENCODE(0,39,0) +/* Convenience function to convert #cairo_dither_t into #pixman_dither_t */ +static pixman_dither_t +_cairo_dither_to_pixman_dither (cairo_dither_t dither) +{ + switch (dither) { + case CAIRO_DITHER_FAST: + return PIXMAN_DITHER_FAST; + case CAIRO_DITHER_GOOD: + return PIXMAN_DITHER_GOOD; + case CAIRO_DITHER_BEST: + return PIXMAN_DITHER_BEST; + case CAIRO_DITHER_NONE: + case CAIRO_DITHER_DEFAULT: + default: + return PIXMAN_DITHER_NONE; + } +} +#endif + + /* A mask consisting of N bits set to 1. */ #define MASK(N) ((1UL << (N))-1) @@ -411,9 +432,8 @@ cairo_image_surface_create (cairo_format_t format, return _cairo_image_surface_create_with_pixman_format (NULL, pixman_format, width, height, -1); } -slim_hidden_def (cairo_image_surface_create); - cairo_surface_t * +cairo_surface_t * _cairo_image_surface_create_with_content (cairo_content_t content, int width, int height) @@ -449,7 +469,7 @@ _cairo_image_surface_create_with_content (cairo_content_t content, * * Since: 1.6 **/ - int +int cairo_format_stride_for_width (cairo_format_t format, int width) { @@ -466,7 +486,6 @@ cairo_format_stride_for_width (cairo_format_t format, return CAIRO_STRIDE_FOR_WIDTH_BPP (width, bpp); } -slim_hidden_def (cairo_format_stride_for_width); /** * cairo_image_surface_create_for_data: @@ -513,7 +532,7 @@ slim_hidden_def (cairo_format_stride_for_width); * * Since: 1.0 **/ - cairo_surface_t * +cairo_surface_t * cairo_image_surface_create_for_data (unsigned char *data, cairo_format_t format, int width, @@ -549,7 +568,6 @@ cairo_image_surface_create_for_data (unsigned char *data, width, height, stride); } -slim_hidden_def (cairo_image_surface_create_for_data); /** * cairo_image_surface_get_data: @@ -581,7 +599,6 @@ cairo_image_surface_get_data (cairo_surface_t *surface) return image_surface->data; } -slim_hidden_def (cairo_image_surface_get_data); /** * cairo_image_surface_get_format: @@ -605,7 +622,6 @@ cairo_image_surface_get_format (cairo_surface_t *surface) return image_surface->format; } -slim_hidden_def (cairo_image_surface_get_format); /** * cairo_image_surface_get_width: @@ -629,7 +645,6 @@ 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: @@ -653,7 +668,6 @@ 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: @@ -681,9 +695,8 @@ cairo_image_surface_get_stride (cairo_surface_t *surface) return image_surface->stride; } -slim_hidden_def (cairo_image_surface_get_stride); - cairo_format_t +cairo_format_t _cairo_format_from_content (cairo_content_t content) { switch (content) { @@ -699,7 +712,7 @@ _cairo_format_from_content (cairo_content_t content) return CAIRO_FORMAT_INVALID; } - cairo_content_t +cairo_content_t _cairo_content_from_format (cairo_format_t format) { switch (format) { @@ -724,7 +737,7 @@ _cairo_content_from_format (cairo_format_t format) return CAIRO_CONTENT_COLOR_ALPHA; } - int +int _cairo_format_bits_per_pixel (cairo_format_t format) { switch (format) { @@ -938,6 +951,8 @@ _cairo_image_surface_paint (void *abstract_surface, const cairo_clip_t *clip) { cairo_image_surface_t *surface = abstract_surface; + pixman_dither_t pixman_dither = _cairo_dither_to_pixman_dither (source->dither); + pixman_image_set_dither (surface->pixman_image, pixman_dither); TRACE ((stderr, "%s (surface=%d)\n", __FUNCTION__, surface->base.unique_id)); diff --git a/gfx/cairo/cairo/src/cairo-list-inline.h b/gfx/cairo/cairo/src/cairo-list-inline.h index 0955178d24..959c038061 100644 --- a/gfx/cairo/cairo/src/cairo-list-inline.h +++ b/gfx/cairo/cairo/src/cairo-list-inline.h @@ -39,6 +39,14 @@ #include "cairo-list-private.h" +/*< private > + * cairo_list_entry: + * @ptr: the pointer to the #cairo_list_t member. + * @type: the type of the struct. + * @member: the name of the list_head within the struct. + * + * Return value: the pointer the struct containing the @member that @ptr points to. + **/ #define cairo_list_entry(ptr, type, member) \ cairo_container_of(ptr, type, member) @@ -48,25 +56,91 @@ #define cairo_list_last_entry(ptr, type, member) \ cairo_list_entry((ptr)->prev, type, member) -#define cairo_list_foreach(pos, head) \ +/*< private > + * cairo_list_foreach: + * @pos: a #cairo_list_t* to use as a loop variable. + * @head: the list. + * + * Iterate the list. @pos points to the #cairo_list_t member of the entry struct. + **/ +#define cairo_list_foreach(pos, head) \ for (pos = (head)->next; pos != (head); pos = pos->next) +/*< private > + * cairo_list_foreach_entry: + * @pos: a variable of type T * to use as a loop variable. + * @type: the type of the entry struct + * @head: the list + * @member: the name of the #cairo_list_t member of the entry + * + * Iterate the list of type T. + **/ #define cairo_list_foreach_entry(pos, type, head, member) \ for (pos = cairo_list_entry((head)->next, type, member);\ &pos->member != (head); \ pos = cairo_list_entry(pos->member.next, type, member)) +/*< private > + * cairo_list_foreach_entry_safe: + * @pos: a variable of type T * to use as a loop variable. + * @n: a variable of type T * that point to the next item after @pos. + * @type: the type of the entry struct + * @head: the list + * @member: the name of the #cairo_list_t member of the entry + * + * Iterate the list of type T. It is safe to remove items while + * iterating. @n is a temporary variable required to support safe + * iterating. + * + * |[<!-- language="C" --> + * struct foo { + * int a; + * cairo_list_t list; + * } + * + * struct foo linked_list; + * cairo_list_init (&linked_list); + * ... calls to cairo_list_add (entry, &linked_list); + * + * struct foo *pos, *next; + * cairo_list_foreach_entry_safe(pos, next, struct foo, &linked_list, list) { + * printf("%d\n", pos->a); + * cairo_list_del (pos); + * } + * ]| + **/ #define cairo_list_foreach_entry_safe(pos, n, type, head, member) \ for (pos = cairo_list_entry ((head)->next, type, member),\ n = cairo_list_entry (pos->member.next, type, member);\ &pos->member != (head); \ pos = n, n = cairo_list_entry (n->member.next, type, member)) +/*< private > + * cairo_list_foreach_entry: + * @pos: a variable of type T * to use as a loop variable. + * @type: the type of the entry struct + * @head: the list + * @member: the name of the #cairo_list_t member of the entry + * + * Iterate the list of type T in reverse direction. + **/ #define cairo_list_foreach_entry_reverse(pos, type, head, member) \ for (pos = cairo_list_entry((head)->prev, type, member);\ &pos->member != (head); \ pos = cairo_list_entry(pos->member.prev, type, member)) +/*< private > + * cairo_list_foreach_entry_safe: + * @pos: a variable of type T * to use as a loop variable. + * @n: a variable of type T * that point to the next item after @pos. + * @type: the type of the entry struct + * @head: the list + * @member: the name of the #cairo_list_t member of the entry + * + * Iterate the list of type T in reverse direction. It is safe to + * remove items while iterating. @n is a temporary variable required + * to support safe iterating. + **/ #define cairo_list_foreach_entry_reverse_safe(pos, n, type, head, member) \ for (pos = cairo_list_entry((head)->prev, type, member),\ n = cairo_list_entry (pos->member.prev, type, member);\ @@ -101,6 +175,13 @@ cairo_list_validate_is_empty (const cairo_list_t *head) #define cairo_list_validate_is_empty(head) #endif +/*< private > + * cairo_list_init: + * @entry: list entry to initialize + * + * Initializes the list entry to point to itself. The result is an + * empty list. + **/ static inline void cairo_list_init (cairo_list_t *entry) { @@ -119,6 +200,13 @@ __cairo_list_add (cairo_list_t *entry, prev->next = entry; } +/*< private > + * cairo_list_add: + * @entry: new entry + * @head: linked list head + * + * Insert a @entry at the start of the list. + **/ static inline void cairo_list_add (cairo_list_t *entry, cairo_list_t *head) { @@ -128,6 +216,13 @@ cairo_list_add (cairo_list_t *entry, cairo_list_t *head) cairo_list_validate (head); } +/*< private > + * cairo_list_add_tail: + * @entry: new entry + * @head: linked list head + * + * Append a @entry to the end of the list. + **/ static inline void cairo_list_add_tail (cairo_list_t *entry, cairo_list_t *head) { @@ -150,6 +245,12 @@ _cairo_list_del (cairo_list_t *entry) __cairo_list_del (entry->prev, entry->next); } +/*< private > + * cairo_list_del: + * @entry: entry to remove + * + * Remove @entry from the list it is in. + **/ static inline void cairo_list_del (cairo_list_t *entry) { @@ -157,6 +258,13 @@ cairo_list_del (cairo_list_t *entry) cairo_list_init (entry); } +/*< private > + * cairo_list_move: + * @entry: entry to move + * @head: linked list to move @entry to + * + * Remove @entry from the list it is in and insert it at the start of @head list. + **/ static inline void cairo_list_move (cairo_list_t *entry, cairo_list_t *head) { @@ -166,6 +274,13 @@ cairo_list_move (cairo_list_t *entry, cairo_list_t *head) cairo_list_validate (head); } +/*< private > + * cairo_list_move_tail: + * @entry: entry tp move + * @head: linked list to move @entry to + * + * Remove @entry from the list it is in and append it to the end of @head list. + **/ static inline void cairo_list_move_tail (cairo_list_t *entry, cairo_list_t *head) { @@ -175,13 +290,27 @@ cairo_list_move_tail (cairo_list_t *entry, cairo_list_t *head) cairo_list_validate (head); } +/*< private > + * cairo_list_move_list: + * @old: List to move + * @new: List to move to. Should be empty, + * + * Move @old list to @new list, fixing up the references. + **/ static inline void -cairo_list_swap (cairo_list_t *entry, cairo_list_t *other) +cairo_list_move_list (cairo_list_t *old, cairo_list_t *new) { - __cairo_list_add (entry, other->prev, other->next); - cairo_list_init (other); + __cairo_list_add (new, old->prev, old->next); + cairo_list_init (old); } +/*< private > + * cairo_list_is_first: + * @entry: entry to check + * @head: linked list + * + * Return %TRUE if @entry is the first item in @head. + **/ static inline cairo_bool_t cairo_list_is_first (const cairo_list_t *entry, const cairo_list_t *head) @@ -190,6 +319,13 @@ cairo_list_is_first (const cairo_list_t *entry, return entry->prev == head; } +/*< private > + * cairo_list_is_last: + * @entry: entry to check + * @head: linked list + * + * Return %TRUE if @entry is the last item in @head. + **/ static inline cairo_bool_t cairo_list_is_last (const cairo_list_t *entry, const cairo_list_t *head) @@ -198,6 +334,12 @@ cairo_list_is_last (const cairo_list_t *entry, return entry->next == head; } +/*< private > + * cairo_list_is_empty: + * @head: linked list + * + * Return %TRUE if @head is empty. + **/ static inline cairo_bool_t cairo_list_is_empty (const cairo_list_t *head) { @@ -205,11 +347,17 @@ cairo_list_is_empty (const cairo_list_t *head) return head->next == head; } +/*< private > + * cairo_list_is_singular: + * @head: linked list + * + * Return %TRUE if @head has only one entry. + **/ static inline cairo_bool_t cairo_list_is_singular (const cairo_list_t *head) { cairo_list_validate (head); - return head->next == head || head->next == head->prev; + return head->next != head && head->next == head->prev; } #endif /* CAIRO_LIST_INLINE_H */ diff --git a/gfx/cairo/cairo/src/cairo-lzw.c b/gfx/cairo/cairo/src/cairo-lzw.c index f27b3c3384..e17cdfc1c7 100644 --- a/gfx/cairo/cairo/src/cairo-lzw.c +++ b/gfx/cairo/cairo/src/cairo-lzw.c @@ -369,10 +369,10 @@ _cairo_lzw_compress (unsigned char *data, unsigned long *size_in_out) * lookup. */ _lzw_buf_store_bits (&buf, prev, code_bits); - if (bytes_remaining == 0) - break; + if (likely (slot != NULL)) + LZW_SYMBOL_SET_CODE (*slot, code_next, prev, next); - LZW_SYMBOL_SET_CODE (*slot, code_next++, prev, next); + code_next++; if (code_next > LZW_BITS_BOUNDARY(code_bits)) { @@ -384,6 +384,9 @@ _cairo_lzw_compress (unsigned char *data, unsigned long *size_in_out) code_next = LZW_CODE_FIRST; } } + + if (bytes_remaining == 0) + break; } /* The LZW footer is an end-of-data code. */ diff --git a/gfx/cairo/cairo/src/cairo-malloc-private.h b/gfx/cairo/cairo/src/cairo-malloc-private.h index 570f7cb0ee..0de52a561d 100644 --- a/gfx/cairo/cairo/src/cairo-malloc-private.h +++ b/gfx/cairo/cairo/src/cairo-malloc-private.h @@ -60,7 +60,7 @@ **/ #define _cairo_malloc(size) \ - ((size) > 0 ? malloc((unsigned) (size)) : NULL) + ((size) != 0 ? malloc(size) : NULL) /** * _cairo_malloc_ab: @@ -79,9 +79,15 @@ * case of malloc() failure or overflow. **/ -#define _cairo_malloc_ab(a, size) \ - ((size) && (unsigned) (a) >= INT32_MAX / (unsigned) (size) ? NULL : \ - _cairo_malloc((unsigned) (a) * (unsigned) (size))) +static cairo_always_inline void * +_cairo_malloc_ab(size_t a, size_t size) +{ + size_t c; + if (_cairo_mul_size_t_overflow (a, size, &c)) + return NULL; + + return _cairo_malloc(c); +} /** * _cairo_realloc_ab: @@ -101,9 +107,15 @@ * of memory * is left untouched). **/ -#define _cairo_realloc_ab(ptr, a, size) \ - ((size) && (unsigned) (a) >= INT32_MAX / (unsigned) (size) ? NULL : \ - realloc(ptr, (unsigned) (a) * (unsigned) (size))) +static cairo_always_inline void * +_cairo_realloc_ab(void *ptr, size_t a, size_t size) +{ + size_t c; + if (_cairo_mul_size_t_overflow (a, size, &c)) + return NULL; + + return realloc(ptr, c); +} /** * _cairo_malloc_abc: @@ -122,10 +134,18 @@ * case of malloc() failure or overflow. **/ -#define _cairo_malloc_abc(a, b, size) \ - ((b) && (unsigned) (a) >= INT32_MAX / (unsigned) (b) ? NULL : \ - (size) && (unsigned) ((a)*(b)) >= INT32_MAX / (unsigned) (size) ? NULL : \ - _cairo_malloc((unsigned) (a) * (unsigned) (b) * (unsigned) (size))) +static cairo_always_inline void * +_cairo_malloc_abc(size_t a, size_t b, size_t size) +{ + size_t c, d; + if (_cairo_mul_size_t_overflow (a, b, &c)) + return NULL; + + if (_cairo_mul_size_t_overflow (c, size, &d)) + return NULL; + + return _cairo_malloc(d); +} /** * _cairo_malloc_ab_plus_c: @@ -141,9 +161,17 @@ * case of malloc() failure or overflow. **/ -#define _cairo_malloc_ab_plus_c(a, size, c) \ - ((size) && (unsigned) (a) >= INT32_MAX / (unsigned) (size) ? NULL : \ - (unsigned) (c) >= INT32_MAX - (unsigned) (a) * (unsigned) (size) ? NULL : \ - _cairo_malloc((unsigned) (a) * (unsigned) (size) + (unsigned) (c))) +static cairo_always_inline void * +_cairo_malloc_ab_plus_c(size_t a, size_t size, size_t c) +{ + size_t d, e; + if (_cairo_mul_size_t_overflow (a, size, &d)) + return NULL; + + if (_cairo_add_size_t_overflow (d, c, &e)) + return NULL; + + return _cairo_malloc(e); +} #endif /* CAIRO_MALLOC_PRIVATE_H */ diff --git a/gfx/cairo/cairo/src/cairo-matrix.c b/gfx/cairo/cairo/src/cairo-matrix.c index f3cf684c9d..f2be48b74d 100644 --- a/gfx/cairo/cairo/src/cairo-matrix.c +++ b/gfx/cairo/cairo/src/cairo-matrix.c @@ -85,7 +85,6 @@ cairo_matrix_init_identity (cairo_matrix_t *matrix) 0, 1, 0, 0); } -slim_hidden_def(cairo_matrix_init_identity); /** * cairo_matrix_init: @@ -118,7 +117,6 @@ cairo_matrix_init (cairo_matrix_t *matrix, matrix->xy = xy; matrix->yy = yy; matrix->x0 = x0; matrix->y0 = y0; } -slim_hidden_def(cairo_matrix_init); /** * _cairo_matrix_get_affine: @@ -178,7 +176,6 @@ cairo_matrix_init_translate (cairo_matrix_t *matrix, 0, 1, tx, ty); } -slim_hidden_def(cairo_matrix_init_translate); /** * cairo_matrix_translate: @@ -202,7 +199,6 @@ 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: @@ -224,7 +220,6 @@ cairo_matrix_init_scale (cairo_matrix_t *matrix, 0, sy, 0, 0); } -slim_hidden_def(cairo_matrix_init_scale); /** * cairo_matrix_scale: @@ -247,7 +242,6 @@ cairo_matrix_scale (cairo_matrix_t *matrix, double sx, double sy) cairo_matrix_multiply (matrix, &tmp, matrix); } -slim_hidden_def(cairo_matrix_scale); /** * cairo_matrix_init_rotate: @@ -277,7 +271,6 @@ cairo_matrix_init_rotate (cairo_matrix_t *matrix, -s, c, 0, 0); } -slim_hidden_def(cairo_matrix_init_rotate); /** * cairo_matrix_rotate: @@ -343,7 +336,6 @@ cairo_matrix_multiply (cairo_matrix_t *result, const cairo_matrix_t *a, const ca *result = r; } -slim_hidden_def(cairo_matrix_multiply); void _cairo_matrix_multiply (cairo_matrix_t *r, @@ -372,15 +364,10 @@ _cairo_matrix_multiply (cairo_matrix_t *r, * the returned vector is as follows: * * <programlisting> - * dx2 = dx1 * a + dy1 * c; - * dy2 = dx1 * b + dy1 * d; + * dx_new = xx * dx + xy * dy; + * dy_new = yx * dx + yy * dy; * </programlisting> * - * Affine transformations are position invariant, so the same vector - * always transforms to the same vector. If (@x1,@y1) transforms - * to (@x2,@y2) then (@x1+@dx1,@y1+@dy1) will transform to - * (@x1+@dx2,@y1+@dy2) for all values of @x1 and @x2. - * * Since: 1.0 **/ void @@ -394,7 +381,6 @@ cairo_matrix_transform_distance (const cairo_matrix_t *matrix, double *dx, doubl *dx = new_x; *dy = new_y; } -slim_hidden_def(cairo_matrix_transform_distance); /** * cairo_matrix_transform_point: @@ -414,7 +400,6 @@ cairo_matrix_transform_point (const cairo_matrix_t *matrix, double *x, double *y *x += matrix->x0; *y += matrix->y0; } -slim_hidden_def(cairo_matrix_transform_point); void _cairo_matrix_transform_bounding_box (const cairo_matrix_t *matrix, @@ -625,7 +610,6 @@ cairo_matrix_invert (cairo_matrix_t *matrix) return CAIRO_STATUS_SUCCESS; } -slim_hidden_def(cairo_matrix_invert); cairo_bool_t _cairo_matrix_is_invertible (const cairo_matrix_t *matrix) diff --git a/gfx/cairo/cairo/src/cairo-mempool.c b/gfx/cairo/cairo/src/cairo-mempool.c index ce40ce521f..dd47562610 100644 --- a/gfx/cairo/cairo/src/cairo-mempool.c +++ b/gfx/cairo/cairo/src/cairo-mempool.c @@ -78,14 +78,14 @@ free_bits (cairo_mempool_t *pool, size_t start, int bits, cairo_bool_t clear) struct _cairo_memblock *block; if (clear) - clear_bits (pool, start, start + (1 << bits)); + clear_bits (pool, start, start + (((size_t) 1) << bits)); block = pool->blocks + start; block->bits = bits; cairo_list_add (&block->link, &pool->free[bits]); - pool->free_bytes += 1 << (bits + pool->min_bits); + pool->free_bytes += ((size_t) 1) << (bits + pool->min_bits); if (bits > pool->max_free_bits) pool->max_free_bits = bits; } @@ -157,10 +157,10 @@ get_buddy (cairo_mempool_t *pool, size_t offset, int bits) { struct _cairo_memblock *block; - if (offset + (1 << bits) >= pool->num_blocks) + if (offset + (((size_t) 1) << bits) >= pool->num_blocks) return NULL; /* invalid */ - if (BITTEST (pool, offset + (1 << bits) - 1)) + if (BITTEST (pool, offset + (((size_t) 1) << bits) - 1)) return NULL; /* buddy is allocated */ block = pool->blocks + offset; @@ -180,7 +180,7 @@ merge_buddies (cairo_mempool_t *pool, while (bits < max_bits - 1) { /* while you can, merge two blocks and get a legal block size */ - size_t buddy_offset = block_offset ^ (1 << bits); + size_t buddy_offset = block_offset ^ (((size_t) 1) << bits); block = get_buddy (pool, buddy_offset, bits); if (block == NULL) @@ -216,7 +216,7 @@ merge_bits (cairo_mempool_t *pool, int max_bits) &pool->free[bits], link) { - size_t buddy_offset = (block - pool->blocks) ^ (1 << bits); + size_t buddy_offset = (block - pool->blocks) ^ (((size_t) 1) << bits); buddy = get_buddy (pool, buddy_offset, bits); if (buddy == NULL) @@ -268,13 +268,13 @@ buddy_malloc (cairo_mempool_t *pool, int bits) /* Mark end of allocated area */ offset = block - pool->blocks; - past = offset + (1 << bits); + past = offset + (((size_t) 1) << bits); BITSET (pool, past - 1); block->bits = bits; /* If we used a larger free block than we needed, free the rest */ - pool->free_bytes -= 1 << (b + pool->min_bits); - free_blocks (pool, past, offset + (1 << b), 0); + pool->free_bytes -= ((size_t) 1) << (b + pool->min_bits); + free_blocks (pool, past, offset + (((size_t) 1) << b), 0); return pool->base + ((block - pool->blocks) << pool->min_bits); } @@ -284,19 +284,19 @@ _cairo_mempool_init (cairo_mempool_t *pool, void *base, size_t bytes, int min_bits, int num_sizes) { - unsigned long tmp; + uintptr_t tmp; int num_blocks; int i; /* Align the start to an integral chunk */ - tmp = ((unsigned long) base) & ((1 << min_bits) - 1); + tmp = ((uintptr_t) base) & ((((size_t) 1) << min_bits) - 1); if (tmp) { - tmp = (1 << min_bits) - tmp; + tmp = (((size_t) 1) << min_bits) - tmp; base = (char *)base + tmp; bytes -= tmp; } - assert ((((unsigned long) base) & ((1 << min_bits) - 1)) == 0); + assert ((((uintptr_t) base) & ((((size_t) 1) << min_bits) - 1)) == 0); assert (num_sizes < ARRAY_LENGTH (pool->free)); pool->base = base; @@ -337,7 +337,7 @@ _cairo_mempool_alloc (cairo_mempool_t *pool, size_t bytes) size_t size; int bits; - size = 1 << pool->min_bits; + size = ((size_t) 1) << pool->min_bits; for (bits = 0; size < bytes; bits++) size <<= 1; if (bits >= pool->num_sizes) @@ -355,8 +355,8 @@ _cairo_mempool_free (cairo_mempool_t *pool, void *storage) block_offset = ((char *)storage - pool->base) >> pool->min_bits; block = pool->blocks + block_offset; - BITCLEAR (pool, block_offset + ((1 << block->bits) - 1)); - pool->free_bytes += 1 << (block->bits + pool->min_bits); + BITCLEAR (pool, block_offset + ((((size_t) 1) << block->bits) - 1)); + pool->free_bytes += ((size_t) 1) << (block->bits + pool->min_bits); merge_buddies (pool, block, pool->num_sizes); } diff --git a/gfx/cairo/cairo/src/cairo-mesh-pattern-rasterizer.c b/gfx/cairo/cairo/src/cairo-mesh-pattern-rasterizer.c index e7f0db666a..f47800c8ae 100644 --- a/gfx/cairo/cairo/src/cairo-mesh-pattern-rasterizer.c +++ b/gfx/cairo/cairo/src/cairo-mesh-pattern-rasterizer.c @@ -659,7 +659,7 @@ draw_bezier_curve (unsigned char *data, int width, int height, int stride, * width, height are the dimensions of the image * stride is the stride in bytes between adjacent rows * vshift is log2(n) if n is the number of desired steps - * p[i][j], p[i][j] are the the nodes of the Bezier patch + * p[i][j], p[i][j] are the nodes of the Bezier patch * col[i][j] is the j-th color component of the i-th corner * * Output: data will be changed to have the requested patch drawn in diff --git a/gfx/cairo/cairo/src/cairo-misc.c b/gfx/cairo/cairo/src/cairo-misc.c index ac4d446224..6e3189740a 100644 --- a/gfx/cairo/cairo/src/cairo-misc.c +++ b/gfx/cairo/cairo/src/cairo-misc.c @@ -38,8 +38,6 @@ * Adrian Johnson <ajohnson@redneon.com> */ -#define _GNU_SOURCE 1 /* strtod_l() */ - #include "cairoint.h" #include "cairo-error-private.h" @@ -176,13 +174,16 @@ cairo_status_to_string (cairo_status_t status) return "error occurred in the Windows Graphics Device Interface"; case CAIRO_STATUS_TAG_ERROR: return "invalid tag name, attributes, or nesting"; + case CAIRO_STATUS_DWRITE_ERROR: + return "Window Direct Write error"; + case CAIRO_STATUS_SVG_FONT_ERROR: + return "error occured while rendering an OpenType-SVG font"; default: case CAIRO_STATUS_LAST_STATUS: return "<unknown error status>"; } } - /** * cairo_glyph_allocate: * @num_glyphs: number of glyphs to allocate @@ -211,7 +212,6 @@ cairo_glyph_allocate (int num_glyphs) return _cairo_malloc_ab (num_glyphs, sizeof (cairo_glyph_t)); } -slim_hidden_def (cairo_glyph_allocate); /** * cairo_glyph_free: @@ -231,7 +231,6 @@ cairo_glyph_free (cairo_glyph_t *glyphs) { free (glyphs); } -slim_hidden_def (cairo_glyph_free); /** * cairo_text_cluster_allocate: @@ -261,7 +260,6 @@ cairo_text_cluster_allocate (int num_clusters) return _cairo_malloc_ab (num_clusters, sizeof (cairo_text_cluster_t)); } -slim_hidden_def (cairo_text_cluster_allocate); /** * cairo_text_cluster_free: @@ -281,8 +279,6 @@ cairo_text_cluster_free (cairo_text_cluster_t *clusters) { free (clusters); } -slim_hidden_def (cairo_text_cluster_free); - /* Private stuff */ @@ -404,10 +400,10 @@ _cairo_operator_bounded_by_mask (cairo_operator_t op) case CAIRO_OPERATOR_DEST_IN: case CAIRO_OPERATOR_DEST_ATOP: return FALSE; + default: + ASSERT_NOT_REACHED; + return FALSE; /* squelch warning */ } - - ASSERT_NOT_REACHED; - return FALSE; } /** @@ -459,18 +455,16 @@ _cairo_operator_bounded_by_source (cairo_operator_t op) case CAIRO_OPERATOR_DEST_IN: case CAIRO_OPERATOR_DEST_ATOP: return FALSE; + default: + ASSERT_NOT_REACHED; + return FALSE; /* squelch warning */ } - - ASSERT_NOT_REACHED; - return FALSE; } uint32_t _cairo_operator_bounded_by_either (cairo_operator_t op) { switch (op) { - default: - ASSERT_NOT_REACHED; case CAIRO_OPERATOR_OVER: case CAIRO_OPERATOR_ATOP: case CAIRO_OPERATOR_DEST: @@ -503,6 +497,9 @@ _cairo_operator_bounded_by_either (cairo_operator_t op) case CAIRO_OPERATOR_DEST_IN: case CAIRO_OPERATOR_DEST_ATOP: return 0; + default: + ASSERT_NOT_REACHED; + return FALSE; /* squelch warning */ } } @@ -887,6 +884,33 @@ _cairo_strtod (const char *nptr, char **endptr) } #endif +#ifndef HAVE_STRNDUP +char * +_cairo_strndup (const char *s, size_t n) +{ + const char *end; + size_t len; + char *sdup; + + if (s == NULL) + return NULL; + + end = memchr (s, 0, n); + if (end) + len = end - s; + else + len = n; + + sdup = (char *) _cairo_malloc (len + 1); + if (sdup != NULL) { + memcpy (sdup, s, len); + sdup[len] = '\0'; + } + + return sdup; +} +#endif + /** * _cairo_fopen: * @filename: filename to open @@ -948,15 +972,6 @@ _cairo_fopen (const char *filename, const char *mode, FILE **file_out) #ifdef _WIN32 -#define WIN32_LEAN_AND_MEAN -/* We require Windows 2000 features such as ETO_PDY */ -#if !defined(WINVER) || (WINVER < 0x0500) -# define WINVER 0x0500 -#endif -#if !defined(_WIN32_WINNT) || (_WIN32_WINNT < 0x0500) -# define _WIN32_WINNT 0x0500 -#endif - #include <windows.h> #include <io.h> diff --git a/gfx/cairo/cairo/src/cairo-mono-scan-converter.c b/gfx/cairo/cairo/src/cairo-mono-scan-converter.c index 891f435c9e..32ddfcc515 100644 --- a/gfx/cairo/cairo/src/cairo-mono-scan-converter.c +++ b/gfx/cairo/cairo/src/cairo-mono-scan-converter.c @@ -85,21 +85,6 @@ struct mono_scan_converter { #define I(x) _cairo_fixed_integer_round_down(x) -/* Compute the floored division a/b. Assumes / and % perform symmetric - * division. */ -inline static struct quorem -floored_divrem(int a, int b) -{ - struct quorem qr; - qr.quo = a/b; - qr.rem = a%b; - if ((a^b)<0 && qr.rem) { - qr.quo -= 1; - qr.rem += b; - } - return qr; -} - /* Compute the floored division (x*a)/b. Assumes / and % perform symmetric * division. */ static struct quorem @@ -377,15 +362,6 @@ row (struct mono_scan_converter *c, unsigned int mask) } } -inline static void dec (struct edge *e, int h) -{ - e->height_left -= h; - if (e->height_left == 0) { - e->prev->next = e->next; - e->next->prev = e->prev; - } -} - static cairo_status_t _mono_scan_converter_init(struct mono_scan_converter *c, int xmin, int ymin, @@ -403,7 +379,6 @@ _mono_scan_converter_init(struct mono_scan_converter *c, c->spans = _cairo_malloc_ab (max_num_spans, sizeof (cairo_half_open_span_t)); if (unlikely (c->spans == NULL)) { - polygon_fini (c->polygon); return _cairo_error (CAIRO_STATUS_NO_MEMORY); } } else diff --git a/gfx/cairo/cairo/src/cairo-mutex-impl-private.h b/gfx/cairo/cairo/src/cairo-mutex-impl-private.h index 25223f3eac..b9430beef2 100644 --- a/gfx/cairo/cairo/src/cairo-mutex-impl-private.h +++ b/gfx/cairo/cairo/src/cairo-mutex-impl-private.h @@ -43,9 +43,7 @@ #include "cairo.h" -#if HAVE_CONFIG_H #include "config.h" -#endif #if HAVE_LOCKDEP #include <lockdep.h> @@ -89,6 +87,9 @@ * No trailing semicolons are needed (in any macro you define here). * You should be able to compile the following snippet: * + * - #define CAIRO_MUTEX_IMPL_TRY_LOCK(mutex) to try locking the mutex object, + * returning TRUE if the lock is acquired, FALSE if the mutex could not be locked. + * * <programlisting> * cairo_mutex_impl_t _cairo_some_mutex; * @@ -165,6 +166,7 @@ # define CAIRO_MUTEX_IMPL_NO 1 # define CAIRO_MUTEX_IMPL_INITIALIZE() CAIRO_MUTEX_IMPL_NOOP # define CAIRO_MUTEX_IMPL_LOCK(mutex) CAIRO_MUTEX_IMPL_NOOP1(mutex) +# define CAIRO_MUTEX_IMPL_TRY_LOCK(mutex) ((mutex), TRUE) # define CAIRO_MUTEX_IMPL_UNLOCK(mutex) CAIRO_MUTEX_IMPL_NOOP1(mutex) # define CAIRO_MUTEX_IMPL_NIL_INITIALIZER 0 @@ -177,52 +179,18 @@ #elif defined(_WIN32) /******************************************************/ -#define WIN32_LEAN_AND_MEAN -/* We require Windows 2000 features such as ETO_PDY */ -#if !defined(WINVER) || (WINVER < 0x0500) -# define WINVER 0x0500 -#endif -#if !defined(_WIN32_WINNT) || (_WIN32_WINNT < 0x0500) -# define _WIN32_WINNT 0x0500 -#endif - # include <windows.h> typedef CRITICAL_SECTION cairo_mutex_impl_t; # define CAIRO_MUTEX_IMPL_WIN32 1 # define CAIRO_MUTEX_IMPL_LOCK(mutex) EnterCriticalSection (&(mutex)) +# define CAIRO_MUTEX_IMPL_TRY_LOCK(mutex) TryEnterCriticalSection (&(mutex)) # define CAIRO_MUTEX_IMPL_UNLOCK(mutex) LeaveCriticalSection (&(mutex)) # define CAIRO_MUTEX_IMPL_INIT(mutex) InitializeCriticalSection (&(mutex)) # define CAIRO_MUTEX_IMPL_FINI(mutex) DeleteCriticalSection (&(mutex)) # define CAIRO_MUTEX_IMPL_NIL_INITIALIZER { NULL, 0, 0, NULL, NULL, 0 } -#elif defined __OS2__ /******************************************************/ - -# define INCL_BASE -# define INCL_PM -# include <os2.h> - - typedef HMTX cairo_mutex_impl_t; - -# define CAIRO_MUTEX_IMPL_OS2 1 -# define CAIRO_MUTEX_IMPL_LOCK(mutex) DosRequestMutexSem(mutex, SEM_INDEFINITE_WAIT) -# define CAIRO_MUTEX_IMPL_UNLOCK(mutex) DosReleaseMutexSem(mutex) -# define CAIRO_MUTEX_IMPL_INIT(mutex) DosCreateMutexSem (NULL, &(mutex), 0L, FALSE) -# define CAIRO_MUTEX_IMPL_FINI(mutex) DosCloseMutexSem (mutex) -# define CAIRO_MUTEX_IMPL_NIL_INITIALIZER 0 - -#elif CAIRO_HAS_BEOS_SURFACE /***********************************************/ - - typedef BLocker* cairo_mutex_impl_t; - -# define CAIRO_MUTEX_IMPL_BEOS 1 -# define CAIRO_MUTEX_IMPL_LOCK(mutex) (mutex)->Lock() -# define CAIRO_MUTEX_IMPL_UNLOCK(mutex) (mutex)->Unlock() -# define CAIRO_MUTEX_IMPL_INIT(mutex) (mutex) = new BLocker() -# define CAIRO_MUTEX_IMPL_FINI(mutex) delete (mutex) -# define CAIRO_MUTEX_IMPL_NIL_INITIALIZER NULL - #elif CAIRO_HAS_PTHREAD /* and finally if there are no native mutexes ********/ # include <pthread.h> @@ -236,6 +204,7 @@ # define CAIRO_MUTEX_IMPL_INIT(mutex) pthread_mutex_init (&(mutex), NULL) #endif # define CAIRO_MUTEX_IMPL_LOCK(mutex) pthread_mutex_lock (&(mutex)) +# define CAIRO_MUTEX_IMPL_TRY_LOCK(mutex) (pthread_mutex_trylock (&(mutex)) == 0) # define CAIRO_MUTEX_IMPL_UNLOCK(mutex) pthread_mutex_unlock (&(mutex)) #if HAVE_LOCKDEP # define CAIRO_MUTEX_IS_LOCKED(mutex) LOCKDEP_IS_LOCKED (&(mutex)) diff --git a/gfx/cairo/cairo/src/cairo-mutex-list-private.h b/gfx/cairo/cairo/src/cairo-mutex-list-private.h index ca74030062..af5cc0517a 100644 --- a/gfx/cairo/cairo/src/cairo-mutex-list-private.h +++ b/gfx/cairo/cairo/src/cairo-mutex-list-private.h @@ -64,16 +64,9 @@ CAIRO_MUTEX_DECLARE (_cairo_xlib_display_mutex) CAIRO_MUTEX_DECLARE (_cairo_xcb_connections_mutex) #endif -#if CAIRO_HAS_GL_SURFACE -CAIRO_MUTEX_DECLARE (_cairo_gl_context_mutex) -#endif - #if !defined (HAS_ATOMIC_OPS) || defined (ATOMIC_OP_NEEDS_MEMORY_BARRIER) CAIRO_MUTEX_DECLARE (_cairo_atomic_mutex) #endif -#if CAIRO_HAS_DRM_SURFACE -CAIRO_MUTEX_DECLARE (_cairo_drm_device_mutex) -#endif /* Undefine, to err on unintended inclusion */ #undef CAIRO_MUTEX_DECLARE diff --git a/gfx/cairo/cairo/src/cairo-mutex-private.h b/gfx/cairo/cairo/src/cairo-mutex-private.h index 61a7160a06..65732a180f 100644 --- a/gfx/cairo/cairo/src/cairo-mutex-private.h +++ b/gfx/cairo/cairo/src/cairo-mutex-private.h @@ -53,7 +53,7 @@ cairo_private void _cairo_mutex_finalize (void); #endif /* only if using static initializer and/or finalizer define the boolean */ #if _CAIRO_MUTEX_IMPL_USE_STATIC_INITIALIZER || _CAIRO_MUTEX_IMPL_USE_STATIC_FINALIZER - cairo_private extern cairo_bool_t _cairo_mutex_initialized; + cairo_private extern int _cairo_mutex_initialized; #endif /* Finally, extern the static mutexes and undef */ diff --git a/gfx/cairo/cairo/src/cairo-mutex-type-private.h b/gfx/cairo/cairo/src/cairo-mutex-type-private.h index e8c493985c..ef8fc5e463 100644 --- a/gfx/cairo/cairo/src/cairo-mutex-type-private.h +++ b/gfx/cairo/cairo/src/cairo-mutex-type-private.h @@ -48,6 +48,9 @@ #ifndef CAIRO_MUTEX_IMPL_LOCK # error "CAIRO_MUTEX_IMPL_LOCK not defined. Check cairo-mutex-impl-private.h." #endif +#ifndef CAIRO_MUTEX_IMPL_TRY_LOCK +# error "CAIRO_MUTEX_IMPL_TRY_LOCK not defined. Check cairo-mutex-impl-private.h." +#endif #ifndef CAIRO_MUTEX_IMPL_UNLOCK # error "CAIRO_MUTEX_IMPL_UNLOCK not defined. Check cairo-mutex-impl-private.h." #endif @@ -138,6 +141,9 @@ #ifndef CAIRO_MUTEX_IMPL_LOCK # error "CAIRO_MUTEX_IMPL_LOCK not defined" #endif +#ifndef CAIRO_MUTEX_IMPL_TRY_LOCK +# error "CAIRO_MUTEX_IMPL_TRY_LOCK not defined" +#endif #ifndef CAIRO_MUTEX_IMPL_UNLOCK # error "CAIRO_MUTEX_IMPL_UNLOCK not defined" #endif @@ -167,6 +173,7 @@ typedef cairo_recursive_mutex_impl_t cairo_recursive_mutex_t; #define CAIRO_MUTEX_INITIALIZE CAIRO_MUTEX_IMPL_INITIALIZE #define CAIRO_MUTEX_FINALIZE CAIRO_MUTEX_IMPL_FINALIZE #define CAIRO_MUTEX_LOCK CAIRO_MUTEX_IMPL_LOCK +#define CAIRO_MUTEX_TRY_LOCK CAIRO_MUTEX_IMPL_TRY_LOCK #define CAIRO_MUTEX_UNLOCK CAIRO_MUTEX_IMPL_UNLOCK #define CAIRO_MUTEX_INIT CAIRO_MUTEX_IMPL_INIT #define CAIRO_MUTEX_FINI CAIRO_MUTEX_IMPL_FINI diff --git a/gfx/cairo/cairo/src/cairo-mutex.c b/gfx/cairo/cairo/src/cairo-mutex.c index 0a31dced3e..5b6debeca7 100644 --- a/gfx/cairo/cairo/src/cairo-mutex.c +++ b/gfx/cairo/cairo/src/cairo-mutex.c @@ -41,13 +41,17 @@ #if _CAIRO_MUTEX_IMPL_USE_STATIC_INITIALIZER || _CAIRO_MUTEX_IMPL_USE_STATIC_FINALIZER +#define _CAIRO_MUTEX_UNINITIALIZED 0 +#define _CAIRO_MUTEX_INITIALIZING 1 +#define _CAIRO_MUTEX_INITIALIZED 2 + # if _CAIRO_MUTEX_IMPL_USE_STATIC_INITIALIZER -# define _CAIRO_MUTEX_IMPL_INITIALIZED_DEFAULT_VALUE FALSE +# define _CAIRO_MUTEX_IMPL_INITIALIZED_DEFAULT_VALUE _CAIRO_MUTEX_UNINITIALIZED # else -# define _CAIRO_MUTEX_IMPL_INITIALIZED_DEFAULT_VALUE TRUE +# define _CAIRO_MUTEX_IMPL_INITIALIZED_DEFAULT_VALUE _CAIRO_MUTEX_INITIALIZED # endif -cairo_bool_t _cairo_mutex_initialized = _CAIRO_MUTEX_IMPL_INITIALIZED_DEFAULT_VALUE; +int _cairo_mutex_initialized = _CAIRO_MUTEX_IMPL_INITIALIZED_DEFAULT_VALUE; # undef _CAIRO_MUTEX_IMPL_INITIALIZED_DEFAULT_VALUE @@ -56,24 +60,47 @@ cairo_bool_t _cairo_mutex_initialized = _CAIRO_MUTEX_IMPL_INITIALIZED_DEFAULT_VA #if _CAIRO_MUTEX_IMPL_USE_STATIC_INITIALIZER void _cairo_mutex_initialize (void) { - if (_cairo_mutex_initialized) +#if HAS_ATOMIC_OPS + int old_value; + do { + old_value = _cairo_atomic_int_cmpxchg_return_old (&_cairo_mutex_initialized, + _CAIRO_MUTEX_UNINITIALIZED, + _CAIRO_MUTEX_INITIALIZING); + if (old_value == _CAIRO_MUTEX_INITIALIZED) + return; + + } while (old_value == _CAIRO_MUTEX_INITIALIZING); +#else + if (_cairo_mutex_initialized == _CAIRO_MUTEX_INITIALIZED) return; - _cairo_mutex_initialized = TRUE; + _cairo_mutex_initialized = _CAIRO_MUTEX_INITIALIZED; +#endif #define CAIRO_MUTEX_DECLARE(mutex) CAIRO_MUTEX_INIT (mutex); #include "cairo-mutex-list-private.h" #undef CAIRO_MUTEX_DECLARE + +#if HAS_ATOMIC_OPS + _cairo_atomic_int_set_relaxed (&_cairo_mutex_initialized, _CAIRO_MUTEX_INITIALIZED); +#endif } #endif #if _CAIRO_MUTEX_IMPL_USE_STATIC_FINALIZER void _cairo_mutex_finalize (void) { - if (!_cairo_mutex_initialized) +#if HAS_ATOMIC_OPS + if (!_cairo_atomic_int_cmpxchg (&_cairo_mutex_initialized, + _CAIRO_MUTEX_INITIALIZED, + _CAIRO_MUTEX_UNINITIALIZED)) + return; +#else + if (_cairo_mutex_initialized != _CAIRO_MUTEX_INITIALIZED) return; - _cairo_mutex_initialized = FALSE; + _cairo_mutex_initialized = _CAIRO_MUTEX_UNINITIALIZED; +#endif #define CAIRO_MUTEX_DECLARE(mutex) CAIRO_MUTEX_FINI (mutex); #include "cairo-mutex-list-private.h" diff --git a/gfx/cairo/cairo/src/cairo-os2-private.h b/gfx/cairo/cairo/src/cairo-os2-private.h deleted file mode 100644 index 829dd3c8d4..0000000000 --- a/gfx/cairo/cairo/src/cairo-os2-private.h +++ /dev/null @@ -1,67 +0,0 @@ -/* 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., 51 Franklin Street, Suite 500, Boston, MA 02110-1335, 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_PRIVATE_H -#define CAIRO_OS2_PRIVATE_H - -#include "cairo-os2.h" -#include "cairoint.h" - -typedef struct _cairo_os2_surface -{ - cairo_surface_t base; - - /* 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; - - RECTL rcl_dirty_area; - cairo_bool_t dirty_area_present; - - /* General flags: */ - cairo_bool_t blit_as_changes; - cairo_bool_t use_24bpp; -} cairo_os2_surface_t; - -#endif /* CAIRO_OS2_PRIVATE_H */ diff --git a/gfx/cairo/cairo/src/cairo-os2-surface.c b/gfx/cairo/cairo/src/cairo-os2-surface.c deleted file mode 100644 index 84f08c8077..0000000000 --- a/gfx/cairo/cairo/src/cairo-os2-surface.c +++ /dev/null @@ -1,1416 +0,0 @@ -/* 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., 51 Franklin Street, Suite 500, Boston, MA 02110-1335, 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> - * Rich Walsh <dragtext@e-vertise.com> - */ - -#include "cairoint.h" - -#include "cairo-os2-private.h" -#include "cairo-default-context-private.h" -#include "cairo-error-private.h" -#include "cairo-surface-fallback-private.h" -#include "cairo-image-surface-private.h" - -#if CAIRO_HAS_FC_FONT -#include <fontconfig/fontconfig.h> -#endif - -#include <float.h> -#ifdef BUILD_CAIRO_DLL -# include "cairo-os2.h" -# ifndef __WATCOMC__ -# include <emx/startup.h> -# endif -#endif - -/* - * Here comes the extra API for the OS/2 platform. Currently it consists - * of two extra functions, the cairo_os2_init() and the - * cairo_os2_fini(). Both of them are called automatically if - * Cairo is compiled to be a DLL file, but you have to call them before - * using the Cairo API if you link to Cairo statically! - * - * You'll also find the code in here which deals with DLL initialization - * and termination, if the code is built to be a DLL. - * (if BUILD_CAIRO_DLL is defined) - */ - -/* Initialization counter: */ -static int cairo_os2_initialization_count = 0; - -static inline void -DisableFPUException (void) -{ - unsigned short usCW; - - /* Some OS/2 PM API calls modify the FPU Control Word, - * but forget to restore it. - * - * This can result in XCPT_FLOAT_INVALID_OPCODE exceptions, - * so to be sure, we disable Invalid Opcode FPU exception - * before using FPU stuffs. - */ - usCW = _control87 (0, 0); - usCW = usCW | EM_INVALID | 0x80; - _control87 (usCW, MCW_EM | 0x80); -} - -/** - * 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. - * - * Since: 1.4 - **/ -cairo_public void -cairo_os2_init (void) -{ - /* This may initialize some stuffs, like create mutex semaphores etc.. */ - - cairo_os2_initialization_count++; - if (cairo_os2_initialization_count > 1) return; - - DisableFPUException (); - -#if CAIRO_HAS_FC_FONT - /* Initialize FontConfig */ - FcInit (); -#endif - - CAIRO_MUTEX_INITIALIZE (); -} - -/** - * 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. - * - * Since: 1.4 - **/ -cairo_public void -cairo_os2_fini (void) -{ - /* This has to uninitialize some stuffs, like destroy mutex semaphores etc.. */ - - if (cairo_os2_initialization_count <= 0) return; - cairo_os2_initialization_count--; - if (cairo_os2_initialization_count > 0) return; - - DisableFPUException (); - - cairo_debug_reset_static_data (); - -#if CAIRO_HAS_FC_FONT -# if HAVE_FCFINI - /* Uninitialize FontConfig */ - FcFini (); -# endif -#endif - -#ifdef __WATCOMC__ - /* It can happen that the libraries we use have memory leaks, - * so there are still memory chunks allocated at this point. - * In these cases, Watcom might still have a bigger memory chunk, - * called "the heap" allocated from the OS. - * As we want to minimize the memory we lose from the point of - * view of the OS, we call this function to shrink that heap - * as much as possible. - */ - _heapshrink (); -#else - /* GCC has a heapmin function that approximately corresponds to - * what the Watcom function does - */ - _heapmin (); -#endif -} - -/* - * This function calls the allocation function depending on which - * method was compiled into the library: it can be native allocation - * (DosAllocMem/DosFreeMem) or C-Library based allocation (malloc/free). - * Actually, for pixel buffers that we use this function for, cairo - * uses _cairo_malloc_abc, so we use that here, too. And use the - * change to check the size argument - */ -void *_buffer_alloc (size_t a, size_t b, const unsigned int size) -{ - size_t nbytes; - void *buffer = NULL; - - if (!a || !b || !size || - a >= INT32_MAX / b || a*b >= INT32_MAX / size) { - return NULL; - } - nbytes = a * b * size; - -#ifdef OS2_USE_PLATFORM_ALLOC - /* Using OBJ_ANY on a machine that isn't configured for hi-mem - * will cause ERROR_INVALID_PARAMETER. If this occurs, or this - * build doesn't have hi-mem enabled, fall back to using lo-mem. - */ -#ifdef OS2_HIGH_MEMORY - if (!DosAllocMem (&buffer, nbytes, - OBJ_ANY | PAG_READ | PAG_WRITE | PAG_COMMIT)) - return buffer; -#endif - if (DosAllocMem (&buffer, nbytes, - PAG_READ | PAG_WRITE | PAG_COMMIT)) - return NULL; -#else - /* Clear the malloc'd buffer the way DosAllocMem() does. */ - buffer = _cairo_malloc (nbytes); - if (buffer) { - memset (buffer, 0, nbytes); - } -#endif - return buffer; -} - -/* - * This function selects the free function depending on which - * allocation method was compiled into the library - */ -void _buffer_free (void *buffer) -{ -#ifdef OS2_USE_PLATFORM_ALLOC - DosFreeMem (buffer); -#else - free (buffer); -#endif -} - -/* XXX - * The cairo_os2_ini() and cairo_os2_fini() functions should be removed and - * the LibMain code moved to cairo-system.c. It should also call - * cairo_debug_reset_static_data() instead of duplicating its logic... - */ - -#ifdef BUILD_CAIRO_DLL -/* The main DLL entry for DLL initialization and uninitialization */ -/* Only include this code if we're about to build a DLL. */ - -#ifdef __WATCOMC__ -unsigned _System -LibMain (unsigned hmod, - unsigned termination) -#else -unsigned long _System -_DLL_InitTerm (unsigned long hModule, - unsigned long termination) -#endif -{ - if (termination) { - /* Unloading the DLL */ - cairo_os2_fini (); - -#ifndef __WATCOMC__ - /* Uninitialize RTL of GCC */ - __ctordtorTerm (); - _CRT_term (); -#endif - return 1; - } else { - /* Loading the DLL */ -#ifndef __WATCOMC__ - /* Initialize RTL of GCC */ - if (_CRT_init () != 0) - return 0; - __ctordtorInit (); -#endif - - cairo_os2_init (); - return 1; - } -} - -#endif /* BUILD_CAIRO_DLL */ - -/* - * The following part of the source file contains the code which might - * be called the "core" of the OS/2 backend support. This contains the - * OS/2 surface support functions and structures. - */ - -/* Forward declaration */ -static const cairo_surface_backend_t cairo_os2_surface_backend; - -/* Unpublished API: - * GpiEnableYInversion = PMGPI.723 - * GpiQueryYInversion = PMGPI.726 - * BOOL APIENTRY GpiEnableYInversion (HPS hps, LONG lHeight); - * LONG APIENTRY GpiQueryYInversion (HPS hps); - */ -BOOL APIENTRY GpiEnableYInversion (HPS hps, LONG lHeight); -LONG APIENTRY GpiQueryYInversion (HPS hps); - -#ifdef __WATCOMC__ -/* Function declaration for GpiDrawBits () (missing from OpenWatcom headers) */ -LONG APIENTRY GpiDrawBits (HPS hps, - PVOID pBits, - PBITMAPINFO2 pbmiInfoTable, - LONG lCount, - PPOINTL aptlPoints, - LONG lRop, - ULONG flOptions); -#endif - -static void -_cairo_os2_surface_blit_pixels (cairo_os2_surface_t *surface, - HPS hps_begin_paint, - PRECTL prcl_begin_paint_rect) -{ - POINTL aptlPoints[4]; - LONG lOldYInversion; - LONG rc = GPI_OK; - - /* Check the limits (may not be necessary) */ - if (prcl_begin_paint_rect->xLeft < 0) - prcl_begin_paint_rect->xLeft = 0; - if (prcl_begin_paint_rect->yBottom < 0) - prcl_begin_paint_rect->yBottom = 0; - if (prcl_begin_paint_rect->xRight > (LONG) surface->bitmap_info.cx) - prcl_begin_paint_rect->xRight = (LONG) surface->bitmap_info.cx; - if (prcl_begin_paint_rect->yTop > (LONG) surface->bitmap_info.cy) - prcl_begin_paint_rect->yTop = (LONG) surface->bitmap_info.cy; - - /* Exit if the rectangle is empty */ - if (prcl_begin_paint_rect->xLeft >= prcl_begin_paint_rect->xRight || - prcl_begin_paint_rect->yBottom >= prcl_begin_paint_rect->yTop) - return; - - /* Set the Target & Source coordinates */ - *((PRECTL)&aptlPoints[0]) = *prcl_begin_paint_rect; - *((PRECTL)&aptlPoints[2]) = *prcl_begin_paint_rect; - - /* Make the Target coordinates non-inclusive */ - aptlPoints[1].x -= 1; - aptlPoints[1].y -= 1; - - /* Enable Y Inversion for the HPS, so GpiDrawBits will - * work with upside-top image, not with upside-down image! - */ - lOldYInversion = GpiQueryYInversion (hps_begin_paint); - GpiEnableYInversion (hps_begin_paint, surface->bitmap_info.cy-1); - - /* Debug code to draw rectangle limits */ -#if 0 - { - int x, y; - unsigned char *pixels; - - pixels = surface->pixels; - for (x = 0; x < surface->bitmap_info.cx; x++) { - for (y = 0; y < surface->bitmap_info.cy; y++) { - if ((x == 0) || - (y == 0) || - (x == y) || - (x >= surface->bitmap_info.cx-1) || - (y >= surface->bitmap_info.cy-1)) - { - pixels[y*surface->bitmap_info.cx*4+x*4] = 255; - } - } - } - } -#endif - if (!surface->use_24bpp) { - rc = GpiDrawBits (hps_begin_paint, - surface->pixels, - &(surface->bitmap_info), - 4, - aptlPoints, - ROP_SRCCOPY, - BBO_IGNORE); - if (rc != GPI_OK) - surface->use_24bpp = TRUE; - } - - if (surface->use_24bpp) { - /* If GpiDrawBits () failed then this is most likely because the - * display driver could not handle a 32bit bitmap. So we need to - * - create a buffer that only contains 3 bytes per pixel - * - change the bitmap info header to contain 24bit - * - pass the new buffer to GpiDrawBits () again - * - clean up the new buffer - */ - BITMAPINFO2 bmpinfo; - unsigned char *pchPixBuf; - unsigned char *pchTarget; - ULONG *pulSource; - ULONG ulX; - ULONG ulY; - ULONG ulPad; - - /* Set up the bitmap header, but this time for 24bit depth. */ - bmpinfo = surface->bitmap_info; - bmpinfo.cBitCount = 24; - - /* The start of each row has to be DWORD aligned. Calculate the - * of number aligned bytes per row, the total size of the bitmap, - * and the number of padding bytes at the end of each row. - */ - ulX = (((bmpinfo.cx * bmpinfo.cBitCount) + 31) / 32) * 4; - bmpinfo.cbImage = ulX * bmpinfo.cy; - ulPad = ulX - bmpinfo.cx * 3; - - /* Allocate temporary pixel buffer. If the rows don't need - * padding, it has to be 1 byte larger than the size of the - * bitmap or else the high-order byte from the last source - * row will end up in unallocated memory. - */ - pchPixBuf = (unsigned char *)_buffer_alloc (1, 1, - bmpinfo.cbImage + (ulPad ? 0 : 1)); - - if (pchPixBuf) { - /* Copy 4 bytes from the source but advance the target ptr only - * 3 bytes, so the high-order alpha byte will be overwritten by - * the next copy. At the end of each row, skip over the padding. - */ - pchTarget = pchPixBuf; - pulSource = (ULONG*)surface->pixels; - for (ulY = bmpinfo.cy; ulY; ulY--) { - for (ulX = bmpinfo.cx; ulX; ulX--) { - *((ULONG*)pchTarget) = *pulSource++; - pchTarget += 3; - } - pchTarget += ulPad; - } - - rc = GpiDrawBits (hps_begin_paint, - pchPixBuf, - &bmpinfo, - 4, - aptlPoints, - ROP_SRCCOPY, - BBO_IGNORE); - if (rc != GPI_OK) - surface->use_24bpp = FALSE; - - _buffer_free (pchPixBuf); - } - } - - /* Restore Y inversion */ - GpiEnableYInversion (hps_begin_paint, lOldYInversion); -} - -static void -_cairo_os2_surface_get_pixels_from_screen (cairo_os2_surface_t *surface, - HPS hps_begin_paint, - PRECTL prcl_begin_paint_rect) -{ - HPS hps; - HDC hdc; - SIZEL sizlTemp; - HBITMAP hbmpTemp; - BITMAPINFO2 bmi2Temp; - POINTL aptlPoints[4]; - int y; - unsigned char *pchTemp; - - /* To copy pixels from screen to our buffer, we do the following steps: - * - * - Blit pixels from screen to a HBITMAP: - * -- Create Memory Device Context - * -- Create a PS into it - * -- Create a HBITMAP - * -- Select HBITMAP into memory PS - * -- Blit dirty pixels from screen to HBITMAP - * - Copy HBITMAP lines (pixels) into our buffer - * - Free resources - */ - - /* Create a memory device context */ - hdc = DevOpenDC (0, OD_MEMORY,"*",0L, NULL, NULLHANDLE); - if (!hdc) { - return; - } - - /* Create a memory PS */ - sizlTemp.cx = prcl_begin_paint_rect->xRight - prcl_begin_paint_rect->xLeft; - sizlTemp.cy = prcl_begin_paint_rect->yTop - prcl_begin_paint_rect->yBottom; - hps = GpiCreatePS (0, - hdc, - &sizlTemp, - PU_PELS | GPIT_NORMAL | GPIA_ASSOC); - if (!hps) { - DevCloseDC (hdc); - return; - } - - /* Create an uninitialized bitmap. */ - /* Prepare BITMAPINFO2 structure for our buffer */ - memset (&bmi2Temp, 0, sizeof (bmi2Temp)); - bmi2Temp.cbFix = sizeof (BITMAPINFOHEADER2); - bmi2Temp.cx = sizlTemp.cx; - bmi2Temp.cy = sizlTemp.cy; - bmi2Temp.cPlanes = 1; - bmi2Temp.cBitCount = 32; - - hbmpTemp = GpiCreateBitmap (hps, - (PBITMAPINFOHEADER2) &bmi2Temp, - 0, - NULL, - NULL); - - if (!hbmpTemp) { - GpiDestroyPS (hps); - DevCloseDC (hdc); - return; - } - - /* Select the bitmap into the memory device context. */ - GpiSetBitmap (hps, hbmpTemp); - - /* Target coordinates (Noninclusive) */ - aptlPoints[0].x = 0; - aptlPoints[0].y = 0; - - aptlPoints[1].x = sizlTemp.cx; - aptlPoints[1].y = sizlTemp.cy; - - /* Source coordinates (Inclusive) */ - aptlPoints[2].x = prcl_begin_paint_rect->xLeft; - aptlPoints[2].y = surface->bitmap_info.cy - prcl_begin_paint_rect->yBottom; - - aptlPoints[3].x = prcl_begin_paint_rect->xRight; - aptlPoints[3].y = surface->bitmap_info.cy - prcl_begin_paint_rect->yTop; - - /* Blit pixels from screen to bitmap */ - GpiBitBlt (hps, - hps_begin_paint, - 4, - aptlPoints, - ROP_SRCCOPY, - BBO_IGNORE); - - /* Now we have to extract the pixels from the bitmap. */ - pchTemp = - surface->pixels + - (prcl_begin_paint_rect->yBottom)*surface->bitmap_info.cx*4 + - prcl_begin_paint_rect->xLeft*4; - for (y = 0; y < sizlTemp.cy; y++) { - /* Get one line of pixels */ - GpiQueryBitmapBits (hps, - sizlTemp.cy - y - 1, /* lScanStart */ - 1, /* lScans */ - (PBYTE)pchTemp, - &bmi2Temp); - - /* Go for next line */ - pchTemp += surface->bitmap_info.cx*4; - } - - /* Clean up resources */ - GpiSetBitmap (hps, (HBITMAP) NULL); - GpiDeleteBitmap (hbmpTemp); - GpiDestroyPS (hps); - DevCloseDC (hdc); -} - -static cairo_status_t -_cairo_os2_surface_acquire_source_image (void *abstract_surface, - cairo_image_surface_t **image_out, - void **image_extra) -{ - cairo_os2_surface_t *surface = (cairo_os2_surface_t *) abstract_surface; - - DosRequestMutexSem (surface->hmtx_use_private_fields, SEM_INDEFINITE_WAIT); - - /* Increase lend counter */ - surface->pixel_array_lend_count++; - - *image_out = surface->image_surface; - *image_extra = NULL; - - DosReleaseMutexSem (surface->hmtx_use_private_fields); - - return CAIRO_STATUS_SUCCESS; -} - -static void -_cairo_os2_surface_release_source_image (void *abstract_surface, - cairo_image_surface_t *image, - void *image_extra) -{ - cairo_os2_surface_t *surface = (cairo_os2_surface_t *) abstract_surface; - - /* Decrease Lend counter! */ - DosRequestMutexSem (surface->hmtx_use_private_fields, SEM_INDEFINITE_WAIT); - - if (surface->pixel_array_lend_count > 0) - surface->pixel_array_lend_count--; - DosPostEventSem (surface->hev_pixel_array_came_back); - - DosReleaseMutexSem (surface->hmtx_use_private_fields); -} - -static cairo_image_surface_t * -_cairo_os2_surface_map_to_image (void *abstract_surface, - const cairo_rectangle_int_t *extents) -{ - cairo_os2_surface_t *surface = (cairo_os2_surface_t *) abstract_surface; - - DosRequestMutexSem (surface->hmtx_use_private_fields, SEM_INDEFINITE_WAIT); - /* Increase lend counter */ - surface->pixel_array_lend_count++; - DosReleaseMutexSem (local_os2_surface->hmtx_use_private_fields); - - /* XXX: BROKEN! */ - *image_out = _cairo_surface_create_for_rectangle_int (surface->image_surface, - extents); - - return CAIRO_STATUS_SUCCESS; -} - -static cairo_int_status_t -_cairo_os2_surface_unmap_image (void *abstract_surface, - cairo_image_surface_t *image) -{ - cairo_os2_surface_t *surface = (cairo_os2_surface_t *) abstract_surface; - - /* So, we got back the image, and if all goes well, then - * something has been changed inside the interest_rect. - * So, we blit it to the screen! - */ - if (surface->blit_as_changes) { - RECTL rclToBlit; - - /* Get mutex, we'll work with the pixel array! */ - if (DosRequestMutexSem (surface->hmtx_use_private_fields, - SEM_INDEFINITE_WAIT) != NO_ERROR) - { - /* Could not get mutex! */ - return; - } - - rclToBlit.xLeft = image->base.device_transform_inverse.x0; - rclToBlit.xRight = rclToBlit.xLeft + image->width; /* Noninclusive */ - rclToBlit.yTop = image->base.device_transform_inverse.y0; - rclToBlit.yBottom = rclToBlit.yTop + image->height; /* Noninclusive */ - - if (surface->hwnd_client_window) { - /* We know the HWND, so let's invalidate the window region, - * so the application will redraw itself, using the - * cairo_os2_surface_refresh_window () API from its own PM thread. - * - * This is the safe method, which should be preferred every time. - */ - rclToBlit.yTop = surface->bitmap_info.cy - rclToBlit.yTop; - rclToBlit.yBottom = surface->bitmap_info.cy - rclToBlit.yTop; - WinInvalidateRect (surface->hwnd_client_window, - &rclToBlit, - FALSE); - } else { - /* We don't know the HWND, so try to blit the pixels from here! - * Please note that it can be problematic if this is not the PM thread! - * - * It can cause internal PM stuffs to be screwed up, for some reason. - * Please always tell the HWND to the surface using the - * cairo_os2_surface_set_hwnd () API, and call cairo_os2_surface_refresh_window () - * from your WM_PAINT, if it's possible! - */ - _cairo_os2_surface_blit_pixels (surface, - surface->hps_client_window, - &rclToBlit); - } - - DosReleaseMutexSem (surface->hmtx_use_private_fields); - } - /* Also decrease Lend counter! */ - DosRequestMutexSem (surface->hmtx_use_private_fields, SEM_INDEFINITE_WAIT); - - if (surface->pixel_array_lend_count > 0) - surface->pixel_array_lend_count--; - DosPostEventSem (surface->hev_pixel_array_came_back); - - DosReleaseMutexSem (surface->hmtx_use_private_fields); -} - -static cairo_bool_t -_cairo_os2_surface_get_extents (void *abstract_surface, - cairo_rectangle_int_t *rectangle) -{ - cairo_os2_surface_t *surface = (cairo_os2_surface_t *) abstract_surface; - - rectangle->x = 0; - rectangle->y = 0; - rectangle->width = surface->bitmap_info.cx; - rectangle->height = surface->bitmap_info.cy; - - return TRUE; -} - -/** - * cairo_os2_surface_create: - * @hps_client_window: the presentation handle to bind the surface to - * @width: the width of the surface - * @height: the height of the surface - * - * Create a Cairo surface which is bound to a given presentation space (HPS). - * The caller retains ownership of the HPS and must dispose of it after the - * the surface has been destroyed. 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 - * cairo_os2_surface_set_manual_window_refresh(). - * 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 cairo_surface_mark_dirty() to fill the surface - * with pixels from the window/HPS. - * - * Return value: the newly created surface - * - * Since: 1.4 - **/ -cairo_surface_t * -cairo_os2_surface_create (HPS hps_client_window, - int width, - int height) -{ - cairo_os2_surface_t *local_os2_surface = 0; - cairo_status_t status; - int rc; - - /* Check the size of the window */ - if ((width <= 0) || (height <= 0)) { - status = _cairo_error (CAIRO_STATUS_INVALID_SIZE); - goto error_exit; - } - - /* Allocate an OS/2 surface structure. */ - local_os2_surface = (cairo_os2_surface_t *) _cairo_malloc (sizeof (cairo_os2_surface_t)); - if (!local_os2_surface) { - status = _cairo_error (CAIRO_STATUS_NO_MEMORY); - goto error_exit; - } - - memset(local_os2_surface, 0, sizeof(cairo_os2_surface_t)); - - /* Allocate resources: mutex & event semaphores and the pixel buffer */ - if (DosCreateMutexSem (NULL, - &(local_os2_surface->hmtx_use_private_fields), - 0, - FALSE)) - { - status = _cairo_error (CAIRO_STATUS_DEVICE_ERROR); - goto error_exit; - } - - if (DosCreateEventSem (NULL, - &(local_os2_surface->hev_pixel_array_came_back), - 0, - FALSE)) - { - status = _cairo_error (CAIRO_STATUS_DEVICE_ERROR); - goto error_exit; - } - - local_os2_surface->pixels = (unsigned char *) _buffer_alloc (height, width, 4); - if (!local_os2_surface->pixels) { - status = _cairo_error (CAIRO_STATUS_NO_MEMORY); - goto error_exit; - } - - /* Create image surface from pixel array */ - local_os2_surface->image_surface = (cairo_image_surface_t *) - cairo_image_surface_create_for_data (local_os2_surface->pixels, - CAIRO_FORMAT_ARGB32, - width, /* Width */ - height, /* Height */ - width * 4); /* Rowstride */ - status = local_os2_surface->image_surface->base.status; - if (status) - goto error_exit; - - /* Set values for OS/2-specific data that aren't zero/NULL/FALSE. - * Note: hps_client_window may be null if this was called by - * cairo_os2_surface_create_for_window(). - */ - local_os2_surface->hps_client_window = hps_client_window; - local_os2_surface->blit_as_changes = TRUE; - - /* Prepare BITMAPINFO2 structure for our buffer */ - local_os2_surface->bitmap_info.cbFix = sizeof (BITMAPINFOHEADER2); - local_os2_surface->bitmap_info.cx = width; - local_os2_surface->bitmap_info.cy = height; - local_os2_surface->bitmap_info.cPlanes = 1; - local_os2_surface->bitmap_info.cBitCount = 32; - - /* Initialize base surface */ - _cairo_surface_init (&local_os2_surface->base, - &cairo_os2_surface_backend, - NULL, /* device */ - _cairo_content_from_format (CAIRO_FORMAT_ARGB32), - FALSE); /* is_vector */ - - /* Successful exit */ - return (cairo_surface_t *)local_os2_surface; - - error_exit: - - /* This point will only be reached if an error occurred */ - - if (local_os2_surface) { - if (local_os2_surface->pixels) - _buffer_free (local_os2_surface->pixels); - if (local_os2_surface->hev_pixel_array_came_back) - DosCloseEventSem (local_os2_surface->hev_pixel_array_came_back); - if (local_os2_surface->hmtx_use_private_fields) - DosCloseMutexSem (local_os2_surface->hmtx_use_private_fields); - free (local_os2_surface); - } - - return _cairo_surface_create_in_error (status); -} - -/** - * cairo_os2_surface_create_for_window: - * @hwnd_client_window: the window handle to bind the surface to - * @width: the width of the surface - * @height: the height of the surface - * - * Create a Cairo surface which is bound to a given window; the caller retains - * ownership of the window. This is a convenience function for use with - * windows that will only be updated when cairo_os2_surface_refresh_window() - * is called (usually in response to a WM_PAINT message). It avoids the need - * to create a persistent HPS for every window and assumes that one will be - * supplied by the caller when a cairo function needs one. If it isn't, an - * HPS will be created on-the-fly and released before the function which needs - * it returns. - * - * Return value: the newly created surface - * - * Since: 1.10 - **/ -cairo_surface_t * -cairo_os2_surface_create_for_window (HWND hwnd_client_window, - int width, - int height) -{ - cairo_os2_surface_t *local_os2_surface; - - /* A window handle must be provided. */ - if (!hwnd_client_window) { - return _cairo_surface_create_in_error ( - _cairo_error (CAIRO_STATUS_NO_MEMORY)); - } - - /* Create the surface. */ - local_os2_surface = (cairo_os2_surface_t *) - cairo_os2_surface_create (0, width, height); - - /* If successful, save the hwnd & turn off automatic repainting. */ - if (!local_os2_surface->image_surface->base.status) { - local_os2_surface->hwnd_client_window = hwnd_client_window; - local_os2_surface->blit_as_changes = FALSE; - } - - return (cairo_surface_t *)local_os2_surface; -} - -/** - * cairo_os2_surface_set_size: - * @surface: the cairo surface to resize - * @new_width: the new width of the surface - * @new_height: the new height of the surface - * @timeout: timeout value in milliseconds - * - * When the client window is resized, call this API to set the new size in the - * underlying surface accordingly. 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. So the notes of - * cairo_os2_surface_create() apply here, too. - * - * The timeout value specifies how long the function should wait on other parts - * of the program to release the buffers. It is necessary, because it can happen - * that Cairo is just drawing something into the surface while we want to - * destroy and recreate it. - * - * Return value: %CAIRO_STATUS_SUCCESS if the surface could be resized, - * %CAIRO_STATUS_SURFACE_TYPE_MISMATCH if the surface is not an OS/2 surface, - * %CAIRO_STATUS_INVALID_SIZE for invalid sizes - * %CAIRO_STATUS_NO_MEMORY if the new size could not be allocated, or if the - * timeout happened before all the buffers were released - * - * Since: 1.4 - **/ -int -cairo_os2_surface_set_size (cairo_surface_t *surface, - int new_width, - int new_height, - int timeout) -{ - cairo_os2_surface_t *local_os2_surface; - unsigned char *pchNewPixels; - int rc; - cairo_image_surface_t *pNewImageSurface; - - local_os2_surface = (cairo_os2_surface_t *) surface; - if ((!local_os2_surface) || - (local_os2_surface->base.backend != &cairo_os2_surface_backend)) - { - /* Invalid parameter (wrong surface)! */ - return _cairo_error (CAIRO_STATUS_SURFACE_TYPE_MISMATCH); - } - - if ((new_width <= 0) || - (new_height <= 0)) - { - /* Invalid size! */ - return _cairo_error (CAIRO_STATUS_INVALID_SIZE); - } - - /* Allocate memory for new stuffs */ - pchNewPixels = (unsigned char *) _buffer_alloc (new_height, new_width, 4); - if (!pchNewPixels) { - /* Not enough memory for the pixels! - * Everything remains the same! - */ - return _cairo_error (CAIRO_STATUS_NO_MEMORY); - } - - /* Create image surface from new pixel array */ - pNewImageSurface = (cairo_image_surface_t *) - cairo_image_surface_create_for_data (pchNewPixels, - CAIRO_FORMAT_ARGB32, - new_width, /* Width */ - new_height, /* Height */ - new_width * 4); /* Rowstride */ - - if (pNewImageSurface->base.status) { - /* Could not create image surface! - * Everything remains the same! - */ - _buffer_free (pchNewPixels); - return _cairo_error (CAIRO_STATUS_NO_MEMORY); - } - - /* Okay, new memory allocated, so it's time to swap old buffers - * to new ones! - */ - if (DosRequestMutexSem (local_os2_surface->hmtx_use_private_fields, SEM_INDEFINITE_WAIT)!=NO_ERROR) { - /* Could not get mutex! - * Everything remains the same! - */ - cairo_surface_destroy ((cairo_surface_t *) pNewImageSurface); - _buffer_free (pchNewPixels); - return _cairo_error (CAIRO_STATUS_NO_MEMORY); - } - - /* We have to make sure that we won't destroy a surface which - * is lent to some other code (Cairo is drawing into it)! - */ - while (local_os2_surface->pixel_array_lend_count > 0) { - ULONG ulPostCount; - DosResetEventSem (local_os2_surface->hev_pixel_array_came_back, &ulPostCount); - DosReleaseMutexSem (local_os2_surface->hmtx_use_private_fields); - /* Wait for somebody to return the pixels! */ - rc = DosWaitEventSem (local_os2_surface->hev_pixel_array_came_back, timeout); - if (rc != NO_ERROR) { - /* Either timeout or something wrong... Exit. */ - cairo_surface_destroy ((cairo_surface_t *) pNewImageSurface); - _buffer_free (pchNewPixels); - return _cairo_error (CAIRO_STATUS_NO_MEMORY); - } - /* Okay, grab mutex and check counter again! */ - if (DosRequestMutexSem (local_os2_surface->hmtx_use_private_fields, SEM_INDEFINITE_WAIT) - != NO_ERROR) - { - /* Could not get mutex! - * Everything remains the same! - */ - cairo_surface_destroy ((cairo_surface_t *) pNewImageSurface); - _buffer_free (pchNewPixels); - return _cairo_error (CAIRO_STATUS_NO_MEMORY); - } - } - - /* Destroy old image surface */ - cairo_surface_destroy ((cairo_surface_t *) (local_os2_surface->image_surface)); - /* Destroy old pixel buffer */ - _buffer_free (local_os2_surface->pixels); - /* Set new image surface */ - local_os2_surface->image_surface = pNewImageSurface; - /* Set new pixel buffer */ - local_os2_surface->pixels = pchNewPixels; - /* Change bitmap2 structure */ - local_os2_surface->bitmap_info.cx = new_width; - local_os2_surface->bitmap_info.cy = new_height; - - DosReleaseMutexSem (local_os2_surface->hmtx_use_private_fields); - return CAIRO_STATUS_SUCCESS; -} - -/** - * cairo_os2_surface_refresh_window: - * @surface: the cairo surface to refresh - * @hps_begin_paint: the presentation handle of the window to refresh - * @prcl_begin_paint_rect: the rectangle to redraw - * - * This function can be used to force a repaint of a given area of the client - * window. It should usually be called from the WM_PAINT processing of the - * window procedure. However, it can be called any time a given part of the - * window has to be updated. - * - * The HPS and RECTL to be passed can be taken from the usual WinBeginPaint call - * of the window procedure, but you can also get the HPS using WinGetPS, and you - * can assemble your own update rectangle by hand. - * If hps_begin_paint is %NULL, the function will use the HPS passed into - * cairo_os2_surface_create(). If @prcl_begin_paint_rect is %NULL, the function - * will query the current window size and repaint the whole window. - * - * Cairo assumes that if you set the HWND to the surface using - * cairo_os2_surface_set_hwnd(), this function will be called by the application - * every time it gets a WM_PAINT for that HWND. If the HWND is set in the - * surface, Cairo uses this function to handle dirty areas too. - * - * Since: 1.4 - **/ -void -cairo_os2_surface_refresh_window (cairo_surface_t *surface, - HPS hps_begin_paint, - PRECTL prcl_begin_paint_rect) -{ - cairo_os2_surface_t *local_os2_surface; - RECTL rclTemp; - HPS hpsTemp = 0; - - local_os2_surface = (cairo_os2_surface_t *) surface; - if ((!local_os2_surface) || - (local_os2_surface->base.backend != &cairo_os2_surface_backend)) - { - /* Invalid parameter (wrong surface)! */ - return; - } - - /* If an HPS wasn't provided, see if we can get one. */ - if (!hps_begin_paint) { - hps_begin_paint = local_os2_surface->hps_client_window; - if (!hps_begin_paint) { - if (local_os2_surface->hwnd_client_window) { - hpsTemp = WinGetPS(local_os2_surface->hwnd_client_window); - hps_begin_paint = hpsTemp; - } - /* No HPS & no way to get one, so exit */ - if (!hps_begin_paint) - return; - } - } - - if (prcl_begin_paint_rect == NULL) { - /* Update the whole window! */ - rclTemp.xLeft = 0; - rclTemp.xRight = local_os2_surface->bitmap_info.cx; - rclTemp.yTop = local_os2_surface->bitmap_info.cy; - rclTemp.yBottom = 0; - } else { - /* Use the rectangle we got passed as parameter! */ - rclTemp.xLeft = prcl_begin_paint_rect->xLeft; - rclTemp.xRight = prcl_begin_paint_rect->xRight; - rclTemp.yTop = local_os2_surface->bitmap_info.cy - prcl_begin_paint_rect->yBottom; - rclTemp.yBottom = local_os2_surface->bitmap_info.cy - prcl_begin_paint_rect->yTop ; - } - - /* Get mutex, we'll work with the pixel array! */ - if (DosRequestMutexSem (local_os2_surface->hmtx_use_private_fields, SEM_INDEFINITE_WAIT) - != NO_ERROR) - { - /* Could not get mutex! */ - if (hpsTemp) - WinReleasePS(hpsTemp); - return; - } - - if ((local_os2_surface->dirty_area_present) && - (local_os2_surface->rcl_dirty_area.xLeft == rclTemp.xLeft) && - (local_os2_surface->rcl_dirty_area.xRight == rclTemp.xRight) && - (local_os2_surface->rcl_dirty_area.yTop == rclTemp.yTop) && - (local_os2_surface->rcl_dirty_area.yBottom == rclTemp.yBottom)) - { - /* Aha, this call was because of a dirty area, so in this case we - * have to blit the pixels from the screen to the surface! - */ - local_os2_surface->dirty_area_present = FALSE; - _cairo_os2_surface_get_pixels_from_screen (local_os2_surface, - hps_begin_paint, - &rclTemp); - } else { - /* Okay, we have the surface, have the HPS - * (might be from WinBeginPaint () or from WinGetPS () ) - * Now blit there the stuffs! - */ - _cairo_os2_surface_blit_pixels (local_os2_surface, - hps_begin_paint, - &rclTemp); - } - - DosReleaseMutexSem (local_os2_surface->hmtx_use_private_fields); - - if (hpsTemp) - WinReleasePS(hpsTemp); -} - -static cairo_status_t -_cairo_os2_surface_finish (void *abstract_surface) -{ - cairo_os2_surface_t *local_os2_surface; - - local_os2_surface = (cairo_os2_surface_t *) abstract_surface; - if ((!local_os2_surface) || - (local_os2_surface->base.backend != &cairo_os2_surface_backend)) - { - /* Invalid parameter (wrong surface)! */ - return _cairo_error (CAIRO_STATUS_SURFACE_TYPE_MISMATCH); - } - - DosRequestMutexSem (local_os2_surface->hmtx_use_private_fields, SEM_INDEFINITE_WAIT); - - /* Destroy old image surface */ - cairo_surface_destroy ((cairo_surface_t *) (local_os2_surface->image_surface)); - /* Destroy old pixel buffer */ - _buffer_free (local_os2_surface->pixels); - DosCloseMutexSem (local_os2_surface->hmtx_use_private_fields); - DosCloseEventSem (local_os2_surface->hev_pixel_array_came_back); - - /* The memory itself will be free'd by the cairo_surface_destroy () - * who called us. - */ - - return CAIRO_STATUS_SUCCESS; -} - -/** - * cairo_os2_surface_set_hwnd: - * @surface: the cairo surface to associate with the window handle - * @hwnd_client_window: the window handle of the client window - * - * Sets window handle for surface; the caller retains ownership of the window. - * If Cairo wants to blit into the window because it is set to blit as the - * surface changes (see cairo_os2_surface_set_manual_window_refresh()), 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. - * - * Since: 1.4 - **/ -void -cairo_os2_surface_set_hwnd (cairo_surface_t *surface, - HWND hwnd_client_window) -{ - cairo_os2_surface_t *local_os2_surface; - - local_os2_surface = (cairo_os2_surface_t *) surface; - if ((!local_os2_surface) || - (local_os2_surface->base.backend != &cairo_os2_surface_backend)) - { - /* Invalid parameter (wrong surface)! */ - return; - } - - if (DosRequestMutexSem (local_os2_surface->hmtx_use_private_fields, SEM_INDEFINITE_WAIT) - != NO_ERROR) - { - /* Could not get mutex! */ - return; - } - - local_os2_surface->hwnd_client_window = hwnd_client_window; - - DosReleaseMutexSem (local_os2_surface->hmtx_use_private_fields); -} - -/** - * cairo_os2_surface_set_manual_window_refresh: - * @surface: the cairo surface to set the refresh mode for - * @manual_refresh: the switch for manual surface 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 - * once the user calls cairo_os2_surface_refresh_window() explicitly. If the - * HWND was not set in the cairo surface, then the HPS will be used to blit the - * graphics. Otherwise it will invalidate the given window region so the user - * will get the WM_PAINT message 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 manual refresh mode by passing a true value to this function. Then call - * cairo_os2_surface_refresh() whenever desired. - * - * Since: 1.4 - **/ -void -cairo_os2_surface_set_manual_window_refresh (cairo_surface_t *surface, - cairo_bool_t manual_refresh) -{ - cairo_os2_surface_t *local_os2_surface; - - local_os2_surface = (cairo_os2_surface_t *) surface; - if ((!local_os2_surface) || - (local_os2_surface->base.backend != &cairo_os2_surface_backend)) - { - /* Invalid parameter (wrong surface)! */ - return; - } - - local_os2_surface->blit_as_changes = !manual_refresh; -} - -/** - * cairo_os2_surface_get_manual_window_refresh: - * @surface: the cairo surface to query the refresh mode from - * - * This space left intentionally blank. - * - * Return value: current refresh mode of the surface (true by default) - * - * Since: 1.4 - **/ -cairo_bool_t -cairo_os2_surface_get_manual_window_refresh (cairo_surface_t *surface) -{ - cairo_os2_surface_t *local_os2_surface; - - local_os2_surface = (cairo_os2_surface_t *) surface; - if ((!local_os2_surface) || - (local_os2_surface->base.backend != &cairo_os2_surface_backend)) - { - /* Invalid parameter (wrong surface)! */ - return FALSE; - } - - return !(local_os2_surface->blit_as_changes); -} - -/** - * cairo_os2_surface_get_hps: - * @surface: the cairo surface to be querued - * @hps: HPS currently associated with the surface (if any) - * - * This API retrieves the HPS associated with the surface. - * - * Return value: %CAIRO_STATUS_SUCCESS if the hps could be retrieved, - * %CAIRO_STATUS_SURFACE_TYPE_MISMATCH if the surface is not an OS/2 surface, - * %CAIRO_STATUS_NULL_POINTER if the hps argument is null - * - * Since: 1.10 - **/ -cairo_status_t -cairo_os2_surface_get_hps (cairo_surface_t *surface, - HPS *hps) -{ - cairo_os2_surface_t *local_os2_surface; - - local_os2_surface = (cairo_os2_surface_t *) surface; - if ((!local_os2_surface) || - (local_os2_surface->base.backend != &cairo_os2_surface_backend)) - { - /* Invalid parameter (wrong surface)! */ - return _cairo_error (CAIRO_STATUS_SURFACE_TYPE_MISMATCH); - } - if (!hps) - { - return _cairo_error (CAIRO_STATUS_NULL_POINTER); - } - *hps = local_os2_surface->hps_client_window; - - return CAIRO_STATUS_SUCCESS; -} - -/** - * cairo_os2_surface_set_hps: - * @surface: the cairo surface to associate with the HPS - * @hps: new HPS to be associated with the surface (the HPS may be null) - * - * This API replaces the HPS associated with the surface with a new one. - * The caller retains ownership of the HPS and must dispose of it after - * the surface has been destroyed or it has been replaced by another - * call to this function. - * - * Return value: %CAIRO_STATUS_SUCCESS if the hps could be replaced, - * %CAIRO_STATUS_SURFACE_TYPE_MISMATCH if the surface is not an OS/2 surface, - * - * Since: 1.10 - **/ -cairo_status_t -cairo_os2_surface_set_hps (cairo_surface_t *surface, - HPS hps) -{ - cairo_os2_surface_t *local_os2_surface; - - local_os2_surface = (cairo_os2_surface_t *) surface; - if ((!local_os2_surface) || - (local_os2_surface->base.backend != &cairo_os2_surface_backend)) - { - /* Invalid parameter (wrong surface)! */ - return _cairo_error (CAIRO_STATUS_SURFACE_TYPE_MISMATCH); - } - local_os2_surface->hps_client_window = hps; - - return CAIRO_STATUS_SUCCESS; -} - -static cairo_status_t -_cairo_os2_surface_mark_dirty_rectangle (void *surface, - int x, - int y, - int width, - int height) -{ - cairo_os2_surface_t *local_os2_surface; - RECTL rclToBlit; - - local_os2_surface = (cairo_os2_surface_t *) surface; - if ((!local_os2_surface) || - (local_os2_surface->base.backend != &cairo_os2_surface_backend)) - { - /* Invalid parameter (wrong surface)! */ - return _cairo_error (CAIRO_STATUS_SURFACE_TYPE_MISMATCH); - } - - /* Get mutex, we'll work with the pixel array! */ - if (DosRequestMutexSem (local_os2_surface->hmtx_use_private_fields, SEM_INDEFINITE_WAIT) - != NO_ERROR) - { - /* Could not get mutex! */ - return CAIRO_STATUS_NO_MEMORY; - } - - /* Check for defaults */ - if (width < 0) - width = local_os2_surface->bitmap_info.cx; - if (height < 0) - height = local_os2_surface->bitmap_info.cy; - - if (local_os2_surface->hwnd_client_window) { - /* We know the HWND, so let's invalidate the window region, - * so the application will redraw itself, using the - * cairo_os2_surface_refresh_window () API from its own PM thread. - * From that function we'll note that it's not a redraw but a - * dirty-rectangle deal stuff, so we'll handle the things from - * there. - * - * This is the safe method, which should be preferred every time. - */ - rclToBlit.xLeft = x; - rclToBlit.xRight = x + width; /* Noninclusive */ - rclToBlit.yTop = local_os2_surface->bitmap_info.cy - (y); - rclToBlit.yBottom = local_os2_surface->bitmap_info.cy - (y + height); /* Noninclusive */ - -#if 0 - if (local_os2_surface->dirty_area_present) { - /* Yikes, there is already a dirty area which should be - * cleaned up, but we'll overwrite it. Sorry. - * TODO: Something clever should be done here. - */ - } -#endif - - /* Set up dirty area reminder stuff */ - memcpy (&(local_os2_surface->rcl_dirty_area), &rclToBlit, sizeof (RECTL)); - local_os2_surface->dirty_area_present = TRUE; - - /* Invalidate window area */ - WinInvalidateRect (local_os2_surface->hwnd_client_window, - &rclToBlit, - FALSE); - } else { - /* We don't know the HWND, so try to blit the pixels from here! - * Please note that it can be problematic if this is not the PM thread! - * - * It can cause internal PM stuffs to be scewed up, for some reason. - * Please always tell the HWND to the surface using the - * cairo_os2_surface_set_hwnd () API, and call cairo_os2_surface_refresh_window () - * from your WM_PAINT, if it's possible! - */ - - rclToBlit.xLeft = x; - rclToBlit.xRight = x + width; /* Noninclusive */ - rclToBlit.yBottom = y; - rclToBlit.yTop = y + height; /* Noninclusive */ - /* Now get the pixels from the screen! */ - _cairo_os2_surface_get_pixels_from_screen (local_os2_surface, - local_os2_surface->hps_client_window, - &rclToBlit); - } - - DosReleaseMutexSem (local_os2_surface->hmtx_use_private_fields); - - return CAIRO_STATUS_SUCCESS; -} - -static const cairo_surface_backend_t cairo_os2_surface_backend = { - CAIRO_SURFACE_TYPE_OS2, - _cairo_os2_surface_finish, - _cairo_default_context_create, - - NULL, /* create_similar */ - NULL, /* create_similar_image */ - _cairo_os2_surface_map_to_image, - _cairo_os2_surface_unmap_image, - - _cairo_surface_default_source, - _cairo_os2_surface_acquire_source_image, - _cairo_os2_surface_release_source_image, - NULL, /* snapshot */ - - _cairo_os2_surface_get_extents, - NULL, /* get_font_options */ - - NULL, /* flush */ - _cairo_os2_surface_mark_dirty_rectangle, - - _cairo_surface_fallback_paint, - _cairo_surface_fallback_mask, - _cairo_surface_fallback_fill, - _cairo_surface_fallback_stroke, - NULL, /* fill/stroke */ - _cairo_surface_fallback_glyphs, -}; diff --git a/gfx/cairo/cairo/src/cairo-os2.h b/gfx/cairo/cairo/src/cairo-os2.h deleted file mode 100644 index d23f2dec42..0000000000 --- a/gfx/cairo/cairo/src/cairo-os2.h +++ /dev/null @@ -1,110 +0,0 @@ -/* 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., 51 Franklin Street, Suite 500, Boston, MA 02110-1335, 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> - * Rich Walsh <dragtext@e-vertise.com> - */ - -#ifndef _CAIRO_OS2_H_ -#define _CAIRO_OS2_H_ - -#define INCL_DOS -#define INCL_DOSSEMAPHORES -#define INCL_DOSERRORS -#define INCL_WIN -#define INCL_GPI - -#include "cairo.h" - -#include <os2.h> - -CAIRO_BEGIN_DECLS - -/* The OS/2 Specific Cairo API */ - -cairo_public void -cairo_os2_init (void); - -cairo_public void -cairo_os2_fini (void); - -#if CAIRO_HAS_OS2_SURFACE - -cairo_public cairo_surface_t * -cairo_os2_surface_create (HPS hps_client_window, - int width, - int height); - -cairo_public cairo_surface_t * -cairo_os2_surface_create_for_window (HWND hwnd_client_window, - int width, - int height); - -cairo_public void -cairo_os2_surface_set_hwnd (cairo_surface_t *surface, - HWND hwnd_client_window); - -cairo_public int -cairo_os2_surface_set_size (cairo_surface_t *surface, - int new_width, - int new_height, - int timeout); - -cairo_public void -cairo_os2_surface_refresh_window (cairo_surface_t *surface, - HPS hps_begin_paint, - PRECTL prcl_begin_paint_rect); - -cairo_public void -cairo_os2_surface_set_manual_window_refresh (cairo_surface_t *surface, - cairo_bool_t manual_refresh); - -cairo_public cairo_bool_t -cairo_os2_surface_get_manual_window_refresh (cairo_surface_t *surface); - -cairo_public cairo_status_t -cairo_os2_surface_get_hps (cairo_surface_t *surface, - HPS *hps); - -cairo_public cairo_status_t -cairo_os2_surface_set_hps (cairo_surface_t *surface, - HPS hps); - -#else /* CAIRO_HAS_OS2_SURFACE */ -# error Cairo was not compiled with support for the OS/2 backend -#endif /* CAIRO_HAS_OS2_SURFACE */ - -CAIRO_END_DECLS - -#endif /* _CAIRO_OS2_H_ */ diff --git a/gfx/cairo/cairo/src/cairo-output-stream-private.h b/gfx/cairo/cairo/src/cairo-output-stream-private.h index 2542646b86..fe091d0c07 100644 --- a/gfx/cairo/cairo/src/cairo-output-stream-private.h +++ b/gfx/cairo/cairo/src/cairo-output-stream-private.h @@ -58,7 +58,7 @@ struct _cairo_output_stream { cairo_output_stream_write_func_t write_func; cairo_output_stream_flush_func_t flush_func; cairo_output_stream_close_func_t close_func; - unsigned long position; + long long position; cairo_status_t status; cairo_bool_t closed; }; @@ -140,7 +140,7 @@ cairo_private void _cairo_output_stream_print_matrix (cairo_output_stream_t *stream, const cairo_matrix_t *matrix); -cairo_private long +cairo_private long long _cairo_output_stream_get_position (cairo_output_stream_t *stream); cairo_private cairo_status_t diff --git a/gfx/cairo/cairo/src/cairo-output-stream.c b/gfx/cairo/cairo/src/cairo-output-stream.c index 935fa44c33..7305b52ca2 100644 --- a/gfx/cairo/cairo/src/cairo-output-stream.c +++ b/gfx/cairo/cairo/src/cairo-output-stream.c @@ -1,3 +1,4 @@ +/* -*- Mode: c; tab-width: 8; c-basic-offset: 4; indent-tabs-mode: t; -*- */ /* cairo-output-stream.c: Output stream abstraction * * Copyright © 2005 Red Hat, Inc @@ -258,11 +259,13 @@ void _cairo_output_stream_write (cairo_output_stream_t *stream, const void *data, size_t length) { - if (length == 0) + if (length == 0 || stream->status) return; - if (stream->status) + if (stream->closed) { + stream->status = CAIRO_STATUS_WRITE_ERROR; return; + } stream->status = stream->write_func (stream, data, length); stream->position += length; @@ -277,9 +280,6 @@ _cairo_output_stream_write_hex_string (cairo_output_stream_t *stream, char buffer[2]; unsigned int i, column; - if (stream->status) - return; - for (i = 0, column = 0; i < length; i++, column++) { if (column == 38) { _cairo_output_stream_write (stream, "\n", 1); @@ -382,7 +382,8 @@ _cairo_dtostr (char *buffer, size_t size, double d, cairo_bool_t limited_precisi } enum { - LENGTH_MODIFIER_LONG = 0x100 + LENGTH_MODIFIER_LONG = 0x100, + LENGTH_MODIFIER_LONG_LONG = 0x200 }; /* Here's a limited reimplementation of printf. The reason for doing @@ -405,9 +406,6 @@ _cairo_output_stream_vprintf (cairo_output_stream_t *stream, int length_modifier, width; cairo_bool_t var_width; - if (stream->status) - return; - f = fmt; p = buffer; while (*f != '\0') { @@ -440,6 +438,10 @@ _cairo_output_stream_vprintf (cairo_output_stream_t *stream, if (*f == 'l') { length_modifier = LENGTH_MODIFIER_LONG; f++; + if (*f == 'l') { + length_modifier = LENGTH_MODIFIER_LONG_LONG; + f++; + } } /* The only format strings exist in the cairo implementation @@ -490,6 +492,20 @@ _cairo_output_stream_vprintf (cairo_output_stream_t *stream, single_fmt, va_arg (ap, long int)); } break; + case 'd' | LENGTH_MODIFIER_LONG_LONG: + case 'u' | LENGTH_MODIFIER_LONG_LONG: + case 'o' | LENGTH_MODIFIER_LONG_LONG: + case 'x' | LENGTH_MODIFIER_LONG_LONG: + case 'X' | LENGTH_MODIFIER_LONG_LONG: + if (var_width) { + width = va_arg (ap, int); + snprintf (buffer, sizeof buffer, + single_fmt, width, va_arg (ap, long long int)); + } else { + snprintf (buffer, sizeof buffer, + single_fmt, va_arg (ap, long long int)); + } + break; case 's': { /* Write out strings as they may be larger than the buffer. */ const char *s = va_arg (ap, const char *); @@ -570,7 +586,7 @@ _cairo_output_stream_print_matrix (cairo_output_stream_t *stream, m.xx, m.yx, m.xy, m.yy, m.x0, m.y0); } -long +long long _cairo_output_stream_get_position (cairo_output_stream_t *stream) { return stream->position; @@ -766,9 +782,6 @@ _cairo_memory_stream_copy (cairo_output_stream_t *base, { memory_stream_t *stream = (memory_stream_t *) base; - if (dest->status) - return; - if (base->status) { dest->status = base->status; return; diff --git a/gfx/cairo/cairo/src/cairo-paginated-private.h b/gfx/cairo/cairo/src/cairo-paginated-private.h index 89f1c99a25..cc8fd1c7b4 100644 --- a/gfx/cairo/cairo/src/cairo-paginated-private.h +++ b/gfx/cairo/cairo/src/cairo-paginated-private.h @@ -178,7 +178,7 @@ _cairo_surface_is_paginated (cairo_surface_t *surface); cairo_private cairo_status_t _cairo_paginated_surface_set_size (cairo_surface_t *surface, - int width, - int height); + double width, + double height); #endif /* CAIRO_PAGINATED_H */ diff --git a/gfx/cairo/cairo/src/cairo-paginated-surface.c b/gfx/cairo/cairo/src/cairo-paginated-surface.c index a3f7cd9b2d..ac24745e33 100644 --- a/gfx/cairo/cairo/src/cairo-paginated-surface.c +++ b/gfx/cairo/cairo/src/cairo-paginated-surface.c @@ -1,3 +1,4 @@ +/* -*- 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 @@ -166,8 +167,8 @@ _cairo_paginated_surface_get_recording (cairo_surface_t *surface) cairo_status_t _cairo_paginated_surface_set_size (cairo_surface_t *surface, - int width, - int height) + double width, + double height) { cairo_paginated_surface_t *paginated_surface; cairo_status_t status; @@ -401,11 +402,13 @@ _paint_page (cairo_paginated_surface_t *surface) cairo_surface_t *analysis; cairo_int_status_t status; cairo_bool_t has_supported, has_page_fallback, has_finegrained_fallback; + unsigned int regions_id = 0; + cairo_bool_t replay_all; if (unlikely (surface->target->status)) return surface->target->status; - analysis = _cairo_analysis_surface_create (surface->target); + analysis = _cairo_analysis_surface_create (surface->target, TRUE); if (unlikely (analysis->status)) return _cairo_surface_set_error (surface->target, analysis->status); @@ -414,21 +417,33 @@ _paint_page (cairo_paginated_surface_t *surface) if (unlikely (status)) goto FAIL; + replay_all = FALSE; + if (surface->target->backend->analyze_recording_surface && + _cairo_recording_surface_has_tags (surface->recording_surface)) + { + replay_all = TRUE; + } + + status = _cairo_recording_surface_region_array_attach (surface->recording_surface, ®ions_id); + if (status) + goto FAIL; + status = _cairo_recording_surface_replay_and_create_regions (surface->recording_surface, - NULL, analysis, FALSE); + regions_id, + NULL, analysis, FALSE, replay_all); if (status) goto FAIL; assert (analysis->status == CAIRO_STATUS_SUCCESS); - if (surface->backend->set_bounding_box) { - cairo_box_t bbox; + if (surface->backend->set_bounding_box) { + cairo_box_t bbox; - _cairo_analysis_surface_get_bounding_box (analysis, &bbox); - status = surface->backend->set_bounding_box (surface->target, &bbox); - if (unlikely (status)) - goto FAIL; - } + _cairo_analysis_surface_get_bounding_box (analysis, &bbox); + status = surface->backend->set_bounding_box (surface->target, &bbox); + if (unlikely (status)) + goto FAIL; + } if (surface->backend->set_fallback_images_required) { cairo_bool_t has_fallbacks = _cairo_analysis_surface_has_unsupported (analysis); @@ -460,13 +475,14 @@ _paint_page (cairo_paginated_surface_t *surface) has_finegrained_fallback = FALSE; } - if (has_supported) { - status = surface->backend->set_paginated_mode (surface->target, - CAIRO_PAGINATED_MODE_RENDER); - if (unlikely (status)) - goto FAIL; + status = surface->backend->set_paginated_mode (surface->target, + CAIRO_PAGINATED_MODE_RENDER); + if (unlikely (status)) + goto FAIL; + if (has_supported) { status = _cairo_recording_surface_replay_region (surface->recording_surface, + regions_id, NULL, surface->target, CAIRO_RECORDING_REGION_NATIVE); @@ -525,6 +541,9 @@ _paint_page (cairo_paginated_surface_t *surface) } FAIL: + if (regions_id) + _cairo_recording_surface_region_array_remove (surface->recording_surface, regions_id); + cairo_surface_destroy (analysis); return _cairo_surface_set_error (surface->target, status); @@ -745,6 +764,14 @@ _cairo_paginated_surface_tag (void *abstract_surface, begin, tag_name, attributes); } +static cairo_bool_t +_cairo_paginated_surface_supports_color_glyph (void *abstract_surface, + cairo_scaled_font_t *scaled_font, + unsigned long glyph_index) +{ + return TRUE; +} + static cairo_surface_t * _cairo_paginated_surface_snapshot (void *abstract_other) { @@ -800,4 +827,5 @@ static const cairo_surface_backend_t cairo_paginated_surface_backend = { _cairo_paginated_surface_show_text_glyphs, _cairo_paginated_surface_get_supported_mime_types, _cairo_paginated_surface_tag, + _cairo_paginated_surface_supports_color_glyph, }; diff --git a/gfx/cairo/cairo/src/cairo-path-fill.c b/gfx/cairo/cairo/src/cairo-path-fill.c index 4000c9c586..d0c8551dc7 100644 --- a/gfx/cairo/cairo/src/cairo-path-fill.c +++ b/gfx/cairo/cairo/src/cairo-path-fill.c @@ -70,6 +70,14 @@ _cairo_filler_line_to (void *closure, } static cairo_status_t +_cairo_filler_add_point (void *closure, + const cairo_point_t *point, + const cairo_slope_t *tangent) +{ + return _cairo_filler_line_to (closure, point); +}; + +static cairo_status_t _cairo_filler_close (void *closure) { cairo_filler_t *filler = closure; @@ -113,7 +121,7 @@ _cairo_filler_curve_to (void *closure, } if (! _cairo_spline_init (&spline, - (cairo_spline_add_point_func_t)_cairo_filler_line_to, filler, + _cairo_filler_add_point, filler, &filler->current_point, p1, p2, p3)) { return _cairo_filler_line_to (closure, p3); diff --git a/gfx/cairo/cairo/src/cairo-path-fixed-private.h b/gfx/cairo/cairo/src/cairo-path-fixed-private.h index cf7cd0836f..e499063444 100644 --- a/gfx/cairo/cairo/src/cairo-path-fixed-private.h +++ b/gfx/cairo/cairo/src/cairo-path-fixed-private.h @@ -126,7 +126,7 @@ _cairo_path_fixed_append (cairo_path_fixed_t *path, cairo_fixed_t tx, cairo_fixed_t ty); -cairo_private unsigned long +cairo_private uintptr_t _cairo_path_fixed_hash (const cairo_path_fixed_t *path); cairo_private unsigned long diff --git a/gfx/cairo/cairo/src/cairo-path-fixed.c b/gfx/cairo/cairo/src/cairo-path-fixed.c index d741823460..fc146f3b30 100644 --- a/gfx/cairo/cairo/src/cairo-path-fixed.c +++ b/gfx/cairo/cairo/src/cairo-path-fixed.c @@ -172,10 +172,10 @@ _cairo_path_fixed_init_copy (cairo_path_fixed_t *path, return CAIRO_STATUS_SUCCESS; } -unsigned long +uintptr_t _cairo_path_fixed_hash (const cairo_path_fixed_t *path) { - unsigned long hash = _CAIRO_HASH_INIT_VALUE; + uintptr_t hash = _CAIRO_HASH_INIT_VALUE; const cairo_path_buf_t *buf; unsigned int count; @@ -1135,6 +1135,14 @@ _cpf_line_to (void *closure, } static cairo_status_t +_cpf_add_point (void *closure, + const cairo_point_t *point, + const cairo_slope_t *tangent) +{ + return _cpf_line_to (closure, point); +}; + +static cairo_status_t _cpf_curve_to (void *closure, const cairo_point_t *p1, const cairo_point_t *p2, @@ -1146,8 +1154,8 @@ _cpf_curve_to (void *closure, cairo_point_t *p0 = &cpf->current_point; if (! _cairo_spline_init (&spline, - (cairo_spline_add_point_func_t)cpf->line_to, - cpf->closure, + _cpf_add_point, + cpf, p0, p1, p2, p3)) { return _cpf_line_to (closure, p3); diff --git a/gfx/cairo/cairo/src/cairo-path-in-fill.c b/gfx/cairo/cairo/src/cairo-path-in-fill.c index 1787fb1a3b..342d5a28e8 100644 --- a/gfx/cairo/cairo/src/cairo-path-in-fill.c +++ b/gfx/cairo/cairo/src/cairo-path-in-fill.c @@ -184,6 +184,14 @@ _cairo_in_fill_line_to (void *closure, } static cairo_status_t +_cairo_in_fill_add_point (void *closure, + const cairo_point_t *point, + const cairo_slope_t *tangent) +{ + return _cairo_in_fill_line_to (closure, point); +}; + +static cairo_status_t _cairo_in_fill_curve_to (void *closure, const cairo_point_t *b, const cairo_point_t *c, @@ -217,7 +225,7 @@ _cairo_in_fill_curve_to (void *closure, /* XXX Investigate direct inspection of the inflections? */ if (! _cairo_spline_init (&spline, - (cairo_spline_add_point_func_t)_cairo_in_fill_line_to, + _cairo_in_fill_add_point, in_fill, &in_fill->current_point, b, c, d)) { diff --git a/gfx/cairo/cairo/src/cairo-path-stroke-polygon.c b/gfx/cairo/cairo/src/cairo-path-stroke-polygon.c index 3f7c498028..510ad3a6ae 100644 --- a/gfx/cairo/cairo/src/cairo-path-stroke-polygon.c +++ b/gfx/cairo/cairo/src/cairo-path-stroke-polygon.c @@ -142,17 +142,6 @@ slope_compare_sgn (double dx1, double dy1, double dx2, double dy2) return 0; } -static inline int -range_step (int i, int step, int max) -{ - i += step; - if (i < 0) - i = max - 1; - if (i >= max) - i = 0; - return i; -} - /* * Construct a fan around the midpoint using the vertices from pen between * inpt and outpt. @@ -399,16 +388,16 @@ outer_close (struct stroker *stroker, switch (stroker->style.line_join) { case CAIRO_LINE_JOIN_ROUND: - /* construct a fan around the common midpoint */ if ((in->dev_slope.x * out->dev_slope.x + in->dev_slope.y * out->dev_slope.y) < stroker->spline_cusp_tolerance) { + /* construct a fan around the common midpoint */ add_fan (stroker, &in->dev_vector, &out->dev_vector, &in->point, clockwise, outer); - break; - } - /* else fall through */ + } /* else: bevel join */ + break; + case CAIRO_LINE_JOIN_MITER: default: { /* dot product of incoming slope vector with outgoing slope vector */ @@ -587,10 +576,14 @@ outer_join (struct stroker *stroker, switch (stroker->style.line_join) { case CAIRO_LINE_JOIN_ROUND: - /* construct a fan around the common midpoint */ - add_fan (stroker, - &in->dev_vector, &out->dev_vector, &in->point, - clockwise, outer); + if ((in->dev_slope.x * out->dev_slope.x + + in->dev_slope.y * out->dev_slope.y) < stroker->spline_cusp_tolerance) + { + /* construct a fan around the common midpoint */ + add_fan (stroker, + &in->dev_vector, &out->dev_vector, &in->point, + clockwise, outer); + } /* else: bevel join */ break; case CAIRO_LINE_JOIN_MITER: @@ -1291,17 +1284,72 @@ _cairo_path_fixed_stroke_to_polygon (const cairo_path_fixed_t *path, stroker.ctm_inverse = ctm_inverse; stroker.tolerance = tolerance; stroker.half_line_width = style->line_width / 2.; - /* To test whether we need to join two segments of a spline using - * a round-join or a bevel-join, we can inspect the angle between the - * two segments. If the difference between the chord distance - * (half-line-width times the cosine of the bisection angle) and the - * half-line-width itself is greater than tolerance then we need to - * inject a point. + + /* If `CAIRO_LINE_JOIN_ROUND` is selected and a joint's `arc height` + * is greater than `tolerance` then two segments are joined with + * round-join, otherwise bevel-join is used. + * + * (See https://gitlab.freedesktop.org/cairo/cairo/-/merge_requests/372#note_1698225 + * for an illustration.) + * + * `Arc height` is the distance from the center of arc's chord to + * the center of the arc. It is also the difference of arc's radius + * and the "distance from a point where segments are joined to the + * chord" (distance to the chord). Arc's radius is the half of a line + * width and the "distance to the chord" is equal to "half of a line width" + * times `cos(half the angle between segment vectors)`. So + * + * arc_height = w/2 - w/2 * cos(phi/2), + * + * where `w/2` is the "half of a line width". + * + * Using the double angle cosine formula we can express the `cos(phi/2)` + * with just `cos(phi)` which is also the dot product of segments' + * unit vectors. + * + * cos(phi/2) = sqrt ( (1 + cos(phi)) / 2 ); + * cos(phi/2) is in [0; 1] range, cannot be negative; + * + * cos(phi) = a . b = (ax * bx + ay * by), + * + * where `a` and `b` are unit vectors of the segments to be joined. + * + * Since `arc height` should be greater than the `tolerance` to produce + * a round-join we can write + * + * w/2 * (1 - cos(phi/2)) > tolerance; + * 1 - tolerance / (w/2) > cos(phi/2); [!] + * + * which can be rewritten with the above double angle formula to + * + * cos(phi) < 2 * ( 1 - tolerance / (w/2) )^2 - 1, + * + * [!] Note that `w/2` is in [tolerance; +inf] range, since `cos(phi/2)` + * cannot be negative. The left part of the above inequality is the + * dot product and the right part is the `spline_cusp_tolerance`: + * + * (ax * bx + ay * by) < spline_cusp_tolerance. + * + * In the code below only the `spline_cusp_tolerance` is calculated. + * The dot product is calculated later, in the condition expression + * itself. "Half of a line width" must be scaled with CTM for tolerance + * condition to be properly met. Also, since `arch height` cannot exceed + * the "half of a line width" and since `cos(phi/2)` cannot be negative, + * when `tolerance` is greater than the "half of a line width" the + * bevel-join should be produced. */ - stroker.spline_cusp_tolerance = 1 - tolerance / stroker.half_line_width; - stroker.spline_cusp_tolerance *= stroker.spline_cusp_tolerance; - stroker.spline_cusp_tolerance *= 2; - stroker.spline_cusp_tolerance -= 1; + double scaled_hlw = hypot(stroker.half_line_width * ctm->xx, + stroker.half_line_width * ctm->yx); + + if (scaled_hlw <= tolerance) { + stroker.spline_cusp_tolerance = -1.0; + } else { + stroker.spline_cusp_tolerance = 1 - tolerance / scaled_hlw; + stroker.spline_cusp_tolerance *= stroker.spline_cusp_tolerance; + stroker.spline_cusp_tolerance *= 2; + stroker.spline_cusp_tolerance -= 1; + } + stroker.ctm_det_positive = _cairo_matrix_compute_determinant (ctm) >= 0.0; diff --git a/gfx/cairo/cairo/src/cairo-path-stroke-traps.c b/gfx/cairo/cairo/src/cairo-path-stroke-traps.c index 1363ffa86e..4eabf6583e 100644 --- a/gfx/cairo/cairo/src/cairo-path-stroke-traps.c +++ b/gfx/cairo/cairo/src/cairo-path-stroke-traps.c @@ -102,17 +102,29 @@ stroker_init (struct stroker *stroker, stroker->tolerance = tolerance; stroker->traps = traps; - /* To test whether we need to join two segments of a spline using - * a round-join or a bevel-join, we can inspect the angle between the - * two segments. If the difference between the chord distance - * (half-line-width times the cosine of the bisection angle) and the - * half-line-width itself is greater than tolerance then we need to - * inject a point. + /* If `CAIRO_LINE_JOIN_ROUND` is selected and a joint's `arc height` + * is greater than `tolerance` then two segments are joined with + * round-join, otherwise bevel-join is used. + * + * `Arc height` is the difference of the "half of a line width" and + * the "half of a line width" times `cos(half the angle between segment vectors)`. + * + * See detailed description in the `_cairo_path_fixed_stroke_to_polygon()` + * function in the `cairo-path-stroke-polygon.c` file or follow the + * https://gitlab.freedesktop.org/cairo/cairo/-/merge_requests/372#note_1698225 + * link to see the detailed description with an illustration. */ - stroker->spline_cusp_tolerance = 1 - tolerance / stroker->half_line_width; - stroker->spline_cusp_tolerance *= stroker->spline_cusp_tolerance; - stroker->spline_cusp_tolerance *= 2; - stroker->spline_cusp_tolerance -= 1; + double scaled_hlw = hypot(stroker->half_line_width * ctm->xx, + stroker->half_line_width * ctm->yx); + + if (scaled_hlw <= tolerance) { + stroker->spline_cusp_tolerance = -1.0; + } else { + stroker->spline_cusp_tolerance = 1 - tolerance / scaled_hlw; + stroker->spline_cusp_tolerance *= stroker->spline_cusp_tolerance; + stroker->spline_cusp_tolerance *= 2; + stroker->spline_cusp_tolerance -= 1; + } stroker->ctm_determinant = _cairo_matrix_compute_determinant (stroker->ctm); stroker->ctm_det_positive = stroker->ctm_determinant >= 0.0; @@ -931,6 +943,14 @@ line_to_dashed (void *closure, const cairo_point_t *point) } static cairo_status_t +add_point (void *closure, + const cairo_point_t *point, + const cairo_slope_t *tangent) +{ + return line_to_dashed (closure, point); +}; + +static cairo_status_t spline_to (void *closure, const cairo_point_t *point, const cairo_slope_t *tangent) @@ -1042,7 +1062,7 @@ curve_to_dashed (void *closure, cairo_spline_add_point_func_t func; cairo_status_t status; - func = (cairo_spline_add_point_func_t)line_to_dashed; + func = add_point; if (stroker->has_bounds && ! _cairo_spline_intersects (&stroker->current_face.point, b, c, d, diff --git a/gfx/cairo/cairo/src/cairo-path-stroke.c b/gfx/cairo/cairo/src/cairo-path-stroke.c index 64cec8f272..9ebeb6cd3f 100644 --- a/gfx/cairo/cairo/src/cairo-path-stroke.c +++ b/gfx/cairo/cairo/src/cairo-path-stroke.c @@ -214,17 +214,6 @@ _cairo_slope_compare_sgn (double dx1, double dy1, double dx2, double dy2) return 0; } -static inline int -_range_step (int i, int step, int max) -{ - i += step; - if (i < 0) - i = max - 1; - if (i >= max) - i = 0; - return i; -} - /* * Construct a fan around the midpoint using the vertices from pen between * inpt and outpt. @@ -996,6 +985,14 @@ _cairo_stroker_line_to (void *closure, } static cairo_status_t +_cairo_stroker_add_point_line_to (void *closure, + const cairo_point_t *point, + const cairo_slope_t *tangent) +{ + return _cairo_stroker_line_to (closure, point); +}; + +static cairo_status_t _cairo_stroker_spline_to (void *closure, const cairo_point_t *point, const cairo_slope_t *tangent) @@ -1226,6 +1223,14 @@ _cairo_stroker_line_to_dashed (void *closure, } static cairo_status_t +_cairo_stroker_add_point_line_to_dashed (void *closure, + const cairo_point_t *point, + const cairo_slope_t *tangent) +{ + return _cairo_stroker_line_to_dashed (closure, point); +}; + +static cairo_status_t _cairo_stroker_curve_to (void *closure, const cairo_point_t *b, const cairo_point_t *c, @@ -1241,13 +1246,13 @@ _cairo_stroker_curve_to (void *closure, cairo_status_t status = CAIRO_STATUS_SUCCESS; line_to = stroker->dash.dashed ? - (cairo_spline_add_point_func_t) _cairo_stroker_line_to_dashed : - (cairo_spline_add_point_func_t) _cairo_stroker_line_to; + _cairo_stroker_add_point_line_to_dashed : + _cairo_stroker_add_point_line_to; /* spline_to is only capable of rendering non-degenerate splines. */ spline_to = stroker->dash.dashed ? - (cairo_spline_add_point_func_t) _cairo_stroker_line_to_dashed : - (cairo_spline_add_point_func_t) _cairo_stroker_spline_to; + _cairo_stroker_add_point_line_to_dashed : + _cairo_stroker_spline_to; if (! _cairo_spline_init (&spline, spline_to, diff --git a/gfx/cairo/cairo/src/cairo-path.c b/gfx/cairo/cairo/src/cairo-path.c index 566e86f5a8..efd84901e4 100644 --- a/gfx/cairo/cairo/src/cairo-path.c +++ b/gfx/cairo/cairo/src/cairo-path.c @@ -372,7 +372,6 @@ cairo_path_destroy (cairo_path_t *path) free (path); } -slim_hidden_def (cairo_path_destroy); /** * _cairo_path_create: diff --git a/gfx/cairo/cairo/src/cairo-pattern-private.h b/gfx/cairo/cairo/src/cairo-pattern-private.h index 26d584e686..0e69d01776 100644 --- a/gfx/cairo/cairo/src/cairo-pattern-private.h +++ b/gfx/cairo/cairo/src/cairo-pattern-private.h @@ -52,6 +52,7 @@ enum { CAIRO_PATTERN_NOTIFY_FILTER = 0x2, CAIRO_PATTERN_NOTIFY_EXTEND = 0x4, CAIRO_PATTERN_NOTIFY_OPACITY = 0x9, + CAIRO_PATTERN_NOTIFY_DITHER = 0x12, }; struct _cairo_pattern_observer { @@ -72,6 +73,8 @@ struct _cairo_pattern { cairo_filter_t filter; cairo_extend_t extend; cairo_bool_t has_component_alpha; + cairo_bool_t is_foreground_marker; + cairo_dither_t dither; cairo_matrix_t matrix; double opacity; @@ -86,6 +89,12 @@ typedef struct _cairo_surface_pattern { cairo_pattern_t base; cairo_surface_t *surface; + + /* This field is only used by the wrapper surface for retreiving + * the region id from the target during create regions and passing + * the region id to the target surface during playback. + */ + unsigned int region_array_id; } cairo_surface_pattern_t; typedef struct _cairo_gradient_stop { @@ -233,6 +242,9 @@ _cairo_pattern_fini (cairo_pattern_t *pattern); cairo_private cairo_pattern_t * _cairo_pattern_create_solid (const cairo_color_t *color); +cairo_private cairo_pattern_t * +_cairo_pattern_create_foreground_marker (void); + cairo_private void _cairo_pattern_transform (cairo_pattern_t *pattern, const cairo_matrix_t *ctm_inverse); @@ -308,15 +320,15 @@ cairo_private cairo_int_status_t _cairo_pattern_get_ink_extents (const cairo_pattern_t *pattern, cairo_rectangle_int_t *extents); -cairo_private unsigned long +cairo_private uintptr_t _cairo_pattern_hash (const cairo_pattern_t *pattern); -cairo_private unsigned long -_cairo_linear_pattern_hash (unsigned long hash, +cairo_private uintptr_t +_cairo_linear_pattern_hash (uintptr_t hash, const cairo_linear_pattern_t *linear); -cairo_private unsigned long -_cairo_radial_pattern_hash (unsigned long hash, +cairo_private uintptr_t +_cairo_radial_pattern_hash (uintptr_t hash, const cairo_radial_pattern_t *radial); cairo_private cairo_bool_t diff --git a/gfx/cairo/cairo/src/cairo-pattern.c b/gfx/cairo/cairo/src/cairo-pattern.c index 32811af595..fcaaf46b8b 100644 --- a/gfx/cairo/cairo/src/cairo-pattern.c +++ b/gfx/cairo/cairo/src/cairo-pattern.c @@ -63,6 +63,14 @@ * functions. **/ +/** + * CAIRO_HAS_MIME_SURFACE: + * + * Unused symbol, always defined. + * + * Since: 1.12 + **/ + static freed_pool_t freed_pattern_pool[5]; static const cairo_solid_pattern_t _cairo_pattern_nil = { @@ -76,6 +84,8 @@ static const cairo_solid_pattern_t _cairo_pattern_nil = { CAIRO_FILTER_DEFAULT, /* filter */ CAIRO_EXTEND_GRADIENT_DEFAULT, /* extend */ FALSE, /* has component alpha */ + FALSE, /* is_foreground_marker */ + CAIRO_DITHER_DEFAULT, /* dither */ { 1., 0., 0., 1., 0., 0., }, /* matrix */ 1.0 /* opacity */ } @@ -92,6 +102,8 @@ static const cairo_solid_pattern_t _cairo_pattern_nil_null_pointer = { CAIRO_FILTER_DEFAULT, /* filter */ CAIRO_EXTEND_GRADIENT_DEFAULT, /* extend */ FALSE, /* has component alpha */ + FALSE, /* is_foreground_marker */ + CAIRO_DITHER_DEFAULT, /* dither */ { 1., 0., 0., 1., 0., 0., }, /* matrix */ 1.0 /* opacity */ } @@ -108,6 +120,8 @@ const cairo_solid_pattern_t _cairo_pattern_black = { CAIRO_FILTER_NEAREST, /* filter */ CAIRO_EXTEND_REPEAT, /* extend */ FALSE, /* has component alpha */ + FALSE, /* is_foreground_marker */ + CAIRO_DITHER_DEFAULT, /* dither */ { 1., 0., 0., 1., 0., 0., }, /* matrix */ 1.0 /* opacity */ }, @@ -125,6 +139,8 @@ const cairo_solid_pattern_t _cairo_pattern_clear = { CAIRO_FILTER_NEAREST, /* filter */ CAIRO_EXTEND_REPEAT, /* extend */ FALSE, /* has component alpha */ + FALSE, /* is_foreground_marker */ + CAIRO_DITHER_DEFAULT, /* dither */ { 1., 0., 0., 1., 0., 0., }, /* matrix */ 1.0 /* opacity */ }, @@ -142,6 +158,8 @@ const cairo_solid_pattern_t _cairo_pattern_white = { CAIRO_FILTER_NEAREST, /* filter */ CAIRO_EXTEND_REPEAT, /* extend */ FALSE, /* has component alpha */ + FALSE, /* is_foreground_marker */ + CAIRO_DITHER_DEFAULT, /* dither */ { 1., 0., 0., 1., 0., 0., }, /* matrix */ 1.0 /* opacity */ }, @@ -233,6 +251,9 @@ _cairo_pattern_init (cairo_pattern_t *pattern, cairo_pattern_type_t type) pattern->opacity = 1.0; pattern->has_component_alpha = FALSE; + pattern->is_foreground_marker = FALSE; + + pattern->dither = CAIRO_DITHER_DEFAULT; cairo_matrix_init_identity (&pattern->matrix); @@ -555,6 +576,7 @@ _cairo_pattern_init_for_surface (cairo_surface_pattern_t *pattern, _cairo_pattern_init (&pattern->base, CAIRO_PATTERN_TYPE_SURFACE); pattern->surface = cairo_surface_reference (surface); + pattern->region_array_id = 0; } static void @@ -618,6 +640,14 @@ _cairo_pattern_create_solid (const cairo_color_t *color) } cairo_pattern_t * +_cairo_pattern_create_foreground_marker (void) +{ + cairo_pattern_t *pattern = _cairo_pattern_create_solid (CAIRO_COLOR_BLACK); + pattern->is_foreground_marker = TRUE; + return pattern; +} + +cairo_pattern_t * _cairo_pattern_create_in_error (cairo_status_t status) { cairo_pattern_t *pattern; @@ -661,7 +691,6 @@ cairo_pattern_create_rgb (double red, double green, double blue) { return cairo_pattern_create_rgba (red, green, blue, 1.0); } -slim_hidden_def (cairo_pattern_create_rgb); /** * cairo_pattern_create_rgba: @@ -675,6 +704,8 @@ slim_hidden_def (cairo_pattern_create_rgb); * 1. If the values passed in are outside that range, they will be * clamped. * + * The color is specified in the same way as in cairo_set_source_rgb(). + * * Return value: the newly created #cairo_pattern_t if successful, or * an error pattern in case of no memory. The caller owns the * returned object and should call cairo_pattern_destroy() when @@ -703,7 +734,6 @@ cairo_pattern_create_rgba (double red, double green, double blue, return _cairo_pattern_create_solid (&color); } -slim_hidden_def (cairo_pattern_create_rgba); /** * cairo_pattern_create_for_surface: @@ -752,7 +782,6 @@ cairo_pattern_create_for_surface (cairo_surface_t *surface) return &pattern->base; } -slim_hidden_def (cairo_pattern_create_for_surface); /** * cairo_pattern_create_linear: @@ -1067,7 +1096,6 @@ cairo_pattern_reference (cairo_pattern_t *pattern) return pattern; } -slim_hidden_def (cairo_pattern_reference); /** * cairo_pattern_get_type: @@ -1138,7 +1166,6 @@ cairo_pattern_destroy (cairo_pattern_t *pattern) else free (pattern); } -slim_hidden_def (cairo_pattern_destroy); /** * cairo_pattern_get_reference_count: @@ -1273,7 +1300,6 @@ cairo_mesh_pattern_begin_patch (cairo_pattern_t *pattern) mesh->has_color[i] = FALSE; } - static void _calc_control_point (cairo_mesh_patch_t *patch, int control_point) { @@ -1478,7 +1504,6 @@ cairo_mesh_pattern_curve_to (cairo_pattern_t *pattern, mesh->current_patch->points[i][j].y = y3; } } -slim_hidden_def (cairo_mesh_pattern_curve_to); /** * cairo_mesh_pattern_line_to: @@ -1549,7 +1574,6 @@ cairo_mesh_pattern_line_to (cairo_pattern_t *pattern, (last_point.y + 2 * y) * (1. / 3), x, y); } -slim_hidden_def (cairo_mesh_pattern_line_to); /** * cairo_mesh_pattern_move_to: @@ -1599,7 +1623,6 @@ cairo_mesh_pattern_move_to (cairo_pattern_t *pattern, mesh->current_patch->points[0][0].x = x; mesh->current_patch->points[0][0].y = y; } -slim_hidden_def (cairo_mesh_pattern_move_to); /** * cairo_mesh_pattern_set_control_point: @@ -1818,7 +1841,6 @@ cairo_mesh_pattern_set_corner_color_rgba (cairo_pattern_t *pattern, _cairo_mesh_pattern_set_corner_color (mesh, corner_num, red, green, blue, alpha); } -slim_hidden_def (cairo_mesh_pattern_set_corner_color_rgba); static void _cairo_pattern_add_color_stop (cairo_gradient_pattern_t *pattern, @@ -1962,7 +1984,6 @@ cairo_pattern_add_color_stop_rgba (cairo_pattern_t *pattern, _cairo_pattern_add_color_stop ((cairo_gradient_pattern_t *) pattern, offset, red, green, blue, alpha); } -slim_hidden_def (cairo_pattern_add_color_stop_rgba); /** * cairo_pattern_set_matrix: @@ -2019,7 +2040,6 @@ cairo_pattern_set_matrix (cairo_pattern_t *pattern, if (unlikely (status)) status = _cairo_pattern_set_error (pattern, status); } -slim_hidden_def (cairo_pattern_set_matrix); /** * cairo_pattern_get_matrix: @@ -2086,6 +2106,45 @@ cairo_pattern_get_filter (cairo_pattern_t *pattern) } /** + * cairo_pattern_get_dither: + * @pattern: a #cairo_pattern_t + * + * Gets the current dithering mode, as set by + * cairo_pattern_set_dither(). + * + * Return value: the current dithering mode. + * + * Since: 1.18 + **/ +cairo_dither_t +cairo_pattern_get_dither (cairo_pattern_t *pattern) +{ + return pattern->dither; +} + +/** + * cairo_pattern_set_dither: + * @pattern: a #cairo_pattern_t + * @dither: a #cairo_dither_t describing the new dithering mode + * + * Set the dithering mode of the rasterizer used for drawing shapes. + * This value is a hint, and a particular backend may or may not support + * a particular value. At the current time, only pixman is supported. + * + * Since: 1.18 + **/ +void +cairo_pattern_set_dither (cairo_pattern_t *pattern, cairo_dither_t dither) +{ + if (pattern->status) + return; + + pattern->dither = dither; + _cairo_pattern_notify_observers (pattern, CAIRO_PATTERN_NOTIFY_DITHER); + +} + +/** * cairo_pattern_set_extend: * @pattern: a #cairo_pattern_t * @extend: a #cairo_extend_t describing how the area outside of the @@ -2127,7 +2186,6 @@ cairo_pattern_get_extend (cairo_pattern_t *pattern) { return pattern->extend; } -slim_hidden_def (cairo_pattern_get_extend); void _cairo_pattern_pretransform (cairo_pattern_t *pattern, @@ -2691,7 +2749,6 @@ _cairo_gradient_pattern_interpolate (const cairo_gradient_pattern_t *gradient, #undef lerp } - /** * _cairo_gradient_pattern_fit_to_range: * @@ -3416,9 +3473,10 @@ use_bilinear(double x, double y, double t) /** * _cairo_pattern_analyze_filter: * @pattern: surface pattern - * Returns: the optimized #cairo_filter_t to use with @pattern. * * Possibly optimize the filter to a simpler value depending on transformation + * + * Returns: the optimized #cairo_filter_t to use with @pattern. **/ cairo_filter_t _cairo_pattern_analyze_filter (const cairo_pattern_t *pattern) @@ -3863,8 +3921,8 @@ _cairo_pattern_get_ink_extents (const cairo_pattern_t *pattern, return CAIRO_STATUS_SUCCESS; } -static unsigned long -_cairo_solid_pattern_hash (unsigned long hash, +static uintptr_t +_cairo_solid_pattern_hash (uintptr_t hash, const cairo_solid_pattern_t *solid) { hash = _cairo_hash_bytes (hash, &solid->color, sizeof (solid->color)); @@ -3872,8 +3930,8 @@ _cairo_solid_pattern_hash (unsigned long hash, return hash; } -static unsigned long -_cairo_gradient_color_stops_hash (unsigned long hash, +static uintptr_t +_cairo_gradient_color_stops_hash (uintptr_t hash, const cairo_gradient_pattern_t *gradient) { unsigned int n; @@ -3894,8 +3952,8 @@ _cairo_gradient_color_stops_hash (unsigned long hash, return hash; } -unsigned long -_cairo_linear_pattern_hash (unsigned long hash, +uintptr_t +_cairo_linear_pattern_hash (uintptr_t hash, const cairo_linear_pattern_t *linear) { hash = _cairo_hash_bytes (hash, &linear->pd1, sizeof (linear->pd1)); @@ -3904,8 +3962,8 @@ _cairo_linear_pattern_hash (unsigned long hash, return _cairo_gradient_color_stops_hash (hash, &linear->base); } -unsigned long -_cairo_radial_pattern_hash (unsigned long hash, +uintptr_t +_cairo_radial_pattern_hash (uintptr_t hash, const cairo_radial_pattern_t *radial) { hash = _cairo_hash_bytes (hash, &radial->cd1.center, sizeof (radial->cd1.center)); @@ -3916,8 +3974,8 @@ _cairo_radial_pattern_hash (unsigned long hash, return _cairo_gradient_color_stops_hash (hash, &radial->base); } -static unsigned long -_cairo_mesh_pattern_hash (unsigned long hash, const cairo_mesh_pattern_t *mesh) +static uintptr_t +_cairo_mesh_pattern_hash (uintptr_t hash, const cairo_mesh_pattern_t *mesh) { const cairo_mesh_patch_t *patch = _cairo_array_index_const (&mesh->patches, 0); unsigned int i, n = _cairo_array_num_elements (&mesh->patches); @@ -3928,8 +3986,8 @@ _cairo_mesh_pattern_hash (unsigned long hash, const cairo_mesh_pattern_t *mesh) return hash; } -static unsigned long -_cairo_surface_pattern_hash (unsigned long hash, +static uintptr_t +_cairo_surface_pattern_hash (uintptr_t hash, const cairo_surface_pattern_t *surface) { hash ^= surface->surface->unique_id; @@ -3937,8 +3995,8 @@ _cairo_surface_pattern_hash (unsigned long hash, return hash; } -static unsigned long -_cairo_raster_source_pattern_hash (unsigned long hash, +static uintptr_t +_cairo_raster_source_pattern_hash (uintptr_t hash, const cairo_raster_source_pattern_t *raster) { hash ^= (uintptr_t)raster->user_data; @@ -3946,10 +4004,10 @@ _cairo_raster_source_pattern_hash (unsigned long hash, return hash; } -unsigned long +uintptr_t _cairo_pattern_hash (const cairo_pattern_t *pattern) { - unsigned long hash = _CAIRO_HASH_INIT_VALUE; + uintptr_t hash = _CAIRO_HASH_INIT_VALUE; if (pattern->status) return 0; @@ -4154,6 +4212,8 @@ _cairo_pattern_equal (const cairo_pattern_t *a, const cairo_pattern_t *b) * * Gets the solid color for a solid color pattern. * + * Note that the color and alpha values are not premultiplied. + * * Return value: %CAIRO_STATUS_SUCCESS, or * %CAIRO_STATUS_PATTERN_TYPE_MISMATCH if the pattern is not a solid * color pattern. @@ -4236,6 +4296,8 @@ cairo_pattern_get_surface (cairo_pattern_t *pattern, * where n is the number returned * by cairo_pattern_get_color_stop_count(). * + * Note that the color and alpha values are not premultiplied. + * * 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 @@ -4434,7 +4496,6 @@ cairo_mesh_pattern_get_patch_count (cairo_pattern_t *pattern, return CAIRO_STATUS_SUCCESS; } -slim_hidden_def (cairo_mesh_pattern_get_patch_count); /** * cairo_mesh_pattern_get_path: @@ -4522,7 +4583,6 @@ cairo_mesh_pattern_get_path (cairo_pattern_t *pattern, return path; } -slim_hidden_def (cairo_mesh_pattern_get_path); /** * cairo_mesh_pattern_get_corner_color_rgba: @@ -4543,6 +4603,8 @@ slim_hidden_def (cairo_mesh_pattern_get_path); * Valid values for @corner_num are from 0 to 3 and identify the * corners as explained in cairo_pattern_create_mesh(). * + * Note that the color and alpha values are not premultiplied. + * * Return value: %CAIRO_STATUS_SUCCESS, or %CAIRO_STATUS_INVALID_INDEX * if @patch_num or @corner_num is not valid for @pattern. If * @pattern is not a mesh pattern, %CAIRO_STATUS_PATTERN_TYPE_MISMATCH @@ -4590,7 +4652,6 @@ cairo_mesh_pattern_get_corner_color_rgba (cairo_pattern_t *pattern, return CAIRO_STATUS_SUCCESS; } -slim_hidden_def (cairo_mesh_pattern_get_corner_color_rgba); /** * cairo_mesh_pattern_get_control_point: @@ -4655,7 +4716,6 @@ cairo_mesh_pattern_get_control_point (cairo_pattern_t *pattern, return CAIRO_STATUS_SUCCESS; } -slim_hidden_def (cairo_mesh_pattern_get_control_point); void _cairo_pattern_reset_static_data (void) diff --git a/gfx/cairo/cairo/src/cairo-pdf-interchange.c b/gfx/cairo/cairo/src/cairo-pdf-interchange.c index 81c5759263..6c21ada4bc 100644 --- a/gfx/cairo/cairo/src/cairo-pdf-interchange.c +++ b/gfx/cairo/cairo/src/cairo-pdf-interchange.c @@ -52,6 +52,9 @@ #include "cairo-array-private.h" #include "cairo-error-private.h" #include "cairo-output-stream-private.h" +#include "cairo-recording-surface-inline.h" +#include "cairo-recording-surface-private.h" +#include "cairo-surface-snapshot-inline.h" #include <time.h> @@ -62,6 +65,275 @@ #define gmtime_r(T, BUF) (*(BUF) = *gmtime (T)) #endif +/* #define DEBUG_PDF_INTERCHANGE 1 */ + +#if DEBUG_PDF_INTERCHANGE +static void +print_tree (cairo_pdf_surface_t *surface, cairo_pdf_struct_tree_node_t *node); + +static void +print_command (cairo_pdf_command_t *command, int indent); + +static void +print_command_list(cairo_pdf_command_list_t *command_list); +#endif + +static void +_cairo_pdf_command_init_key (cairo_pdf_command_entry_t *key) +{ + key->base.hash = _cairo_hash_uintptr (_CAIRO_HASH_INIT_VALUE, (uintptr_t)key->recording_id); + key->base.hash = _cairo_hash_uintptr (key->base.hash, (uintptr_t)key->command_id); +} + +static cairo_bool_t +_cairo_pdf_command_equal (const void *key_a, const void *key_b) +{ + const cairo_pdf_command_entry_t *a = key_a; + const cairo_pdf_command_entry_t *b = key_b; + + return a->recording_id == b->recording_id && a->command_id == b->command_id; +} + +static void +_cairo_pdf_command_pluck (void *entry, void *closure) +{ + cairo_pdf_command_entry_t *dest = entry; + cairo_hash_table_t *table = closure; + + _cairo_hash_table_remove (table, &dest->base); + free (dest); +} + +static cairo_pdf_struct_tree_node_t * +lookup_node_for_command (cairo_pdf_surface_t *surface, + unsigned int recording_id, + unsigned int command_id) +{ + cairo_pdf_command_entry_t entry_key; + cairo_pdf_command_entry_t *entry; + cairo_pdf_interchange_t *ic = &surface->interchange; + + entry_key.recording_id = recording_id; + entry_key.command_id = command_id; + _cairo_pdf_command_init_key (&entry_key); + entry = _cairo_hash_table_lookup (ic->command_to_node_map, &entry_key.base); + assert (entry != NULL); + return entry->node; +} + +static cairo_int_status_t +command_list_add (cairo_pdf_surface_t *surface, + unsigned int command_id, + cairo_pdf_operation_t flags) +{ + cairo_pdf_interchange_t *ic = &surface->interchange; + cairo_pdf_command_t command; + cairo_int_status_t status; + + unsigned num_elements = _cairo_array_num_elements (&ic->current_commands->commands); + if (command_id > num_elements) { + void *elements; + unsigned additional_elements = command_id - num_elements; + status = _cairo_array_allocate (&ic->current_commands->commands, additional_elements, &elements); + if (unlikely (status)) + return status; + memset (elements, 0, additional_elements * sizeof(cairo_pdf_command_t)); + } + + command.group = NULL; + command.node = NULL; + command.command_id = command_id; + command.mcid_index = 0; + command.flags = flags; + return _cairo_array_append (&ic->current_commands->commands, &command); +} + +static cairo_int_status_t +command_list_push_group (cairo_pdf_surface_t *surface, + unsigned int command_id, + cairo_surface_t *recording_surface, + unsigned int region_id) +{ + cairo_pdf_interchange_t *ic = &surface->interchange; + cairo_pdf_command_t *command; + cairo_pdf_command_list_t *group; + cairo_pdf_recording_surface_commands_t recording_commands; + cairo_int_status_t status = CAIRO_STATUS_SUCCESS; + + group = _cairo_malloc (sizeof(cairo_pdf_command_list_t)); + _cairo_array_init (&group->commands, sizeof(cairo_pdf_command_t)); + group->parent = ic->current_commands; + + command_list_add (surface, command_id, PDF_GROUP); + command = _cairo_array_index (&ic->current_commands->commands, command_id); + command->group = group; + ic->current_commands = group; + + recording_commands.recording_surface = recording_surface; + recording_commands.command_list = group; + recording_commands.region_id = region_id; + status = _cairo_array_append (&ic->recording_surface_commands, &recording_commands); + + return status; +} + +static void +command_list_pop_group (cairo_pdf_surface_t *surface) +{ + cairo_pdf_interchange_t *ic = &surface->interchange; + + ic->current_commands = ic->current_commands->parent; +} + +static cairo_bool_t +command_list_is_group (cairo_pdf_surface_t *surface, + unsigned int command_id) +{ + cairo_pdf_interchange_t *ic = &surface->interchange; + cairo_pdf_command_t *command; + unsigned num_elements = _cairo_array_num_elements (&ic->current_commands->commands); + + if (command_id >= num_elements) + return FALSE; + + command = _cairo_array_index (&ic->current_commands->commands, command_id); + return command->flags == PDF_GROUP; +} + + +/* Is there any content between current command and next + * begin/end/group? */ +static cairo_bool_t +command_list_has_content (cairo_pdf_surface_t *surface, + unsigned int command_id, + unsigned int *content_command_id) +{ + cairo_pdf_interchange_t *ic = &surface->interchange; + cairo_pdf_command_t *command; + unsigned i; + unsigned num_elements = _cairo_array_num_elements (&ic->current_commands->commands); + + for (i = command_id + 1; i < num_elements; i++) { + command = _cairo_array_index (&ic->current_commands->commands, i); + switch (command->flags) { + case PDF_CONTENT: + if (content_command_id) + *content_command_id = i; + return TRUE; + break; + case PDF_BEGIN: + case PDF_END: + case PDF_GROUP: + return FALSE; + case PDF_NONE: + break; + } + } + return FALSE; +} + +static void +command_list_set_mcid (cairo_pdf_surface_t *surface, + unsigned int command_id, + cairo_pdf_struct_tree_node_t *node, + int mcid_index) +{ + cairo_pdf_interchange_t *ic = &surface->interchange; + cairo_pdf_command_t *command; + + command = _cairo_array_index (&ic->current_commands->commands, command_id); + command->node = node; + command->mcid_index = mcid_index; +} + +static void +command_list_set_current_recording_commands (cairo_pdf_surface_t *surface, + cairo_surface_t *recording_surface, + unsigned int region_id) +{ + cairo_pdf_interchange_t *ic = &surface->interchange; + unsigned i; + cairo_pdf_recording_surface_commands_t *commands; + unsigned num_elements = _cairo_array_num_elements (&ic->recording_surface_commands); + + for (i = 0; i < num_elements; i++) { + commands = _cairo_array_index (&ic->recording_surface_commands, i); + if (commands->region_id == region_id) { + ic->current_commands = commands->command_list; + return; + } + } + ASSERT_NOT_REACHED; /* recording_surface not found */ +} + +static void +update_mcid_order (cairo_pdf_surface_t *surface, + cairo_pdf_command_list_t *command_list) +{ + cairo_pdf_interchange_t *ic = &surface->interchange; + cairo_pdf_command_t *command; + cairo_pdf_page_mcid_t *mcid_elem; + unsigned i; + unsigned num_elements = _cairo_array_num_elements (&command_list->commands); + + for (i = 0; i < num_elements; i++) { + command = _cairo_array_index (&command_list->commands, i); + if (command->node) { + mcid_elem = _cairo_array_index (&command->node->mcid, command->mcid_index); + mcid_elem->order = ic->mcid_order++; + } + + if (command->group) + update_mcid_order (surface, command->group); + } +} + +static void +_cairo_pdf_content_tag_init_key (cairo_pdf_content_tag_t *key) +{ + key->base.hash = _cairo_hash_string (key->node->attributes.content.id); +} + +static cairo_bool_t +_cairo_pdf_content_tag_equal (const void *key_a, const void *key_b) +{ + const cairo_pdf_content_tag_t *a = key_a; + const cairo_pdf_content_tag_t *b = key_b; + + return strcmp (a->node->attributes.content.id, b->node->attributes.content.id) == 0; +} + +static void +_cairo_pdf_content_tag_pluck (void *entry, void *closure) +{ + cairo_pdf_content_tag_t *content_tag = entry; + cairo_hash_table_t *table = closure; + + _cairo_hash_table_remove (table, &content_tag->base); + free (content_tag); +} + +static cairo_status_t +lookup_content_node_for_ref_node (cairo_pdf_surface_t *surface, + cairo_pdf_struct_tree_node_t *ref_node, + cairo_pdf_struct_tree_node_t **node) +{ + cairo_pdf_content_tag_t entry_key; + cairo_pdf_content_tag_t *entry; + cairo_pdf_interchange_t *ic = &surface->interchange; + + entry_key.node = ref_node; + _cairo_pdf_content_tag_init_key (&entry_key); + entry = _cairo_hash_table_lookup (ic->content_tag_map, &entry_key.base); + if (!entry) { + return _cairo_tag_error ("CONTENT_REF ref='%s' not found", + ref_node->attributes.content_ref.ref); + } + + *node = entry->node; + return CAIRO_STATUS_SUCCESS; +} + static void write_rect_to_pdf_quad_points (cairo_output_stream_t *stream, const cairo_rectangle_t *rect, @@ -96,9 +368,11 @@ static cairo_int_status_t add_tree_node (cairo_pdf_surface_t *surface, cairo_pdf_struct_tree_node_t *parent, const char *name, + const char *attributes, cairo_pdf_struct_tree_node_t **new_node) { cairo_pdf_struct_tree_node_t *node; + cairo_int_status_t status = CAIRO_STATUS_SUCCESS; node = _cairo_malloc (sizeof(cairo_pdf_struct_tree_node_t)); if (unlikely (node == NULL)) @@ -111,21 +385,26 @@ add_tree_node (cairo_pdf_surface_t *surface, node->parent = parent; cairo_list_init (&node->children); - _cairo_array_init (&node->mcid, sizeof(struct page_mcid)); - node->annot_res.id = 0; + _cairo_array_init (&node->mcid, sizeof (cairo_pdf_page_mcid_t)); + node->annot = NULL; node->extents.valid = FALSE; - cairo_list_init (&node->extents.link); cairo_list_add_tail (&node->link, &parent->children); - *new_node = node; - return CAIRO_STATUS_SUCCESS; -} + if (strcmp (node->name, CAIRO_TAG_CONTENT) == 0) { + node->type = PDF_NODE_CONTENT; + status = _cairo_tag_parse_content_attributes (attributes, &node->attributes.content); + } else if (strcmp (node->name, CAIRO_TAG_CONTENT_REF) == 0) { + node->type = PDF_NODE_CONTENT_REF; + status = _cairo_tag_parse_content_ref_attributes (attributes, &node->attributes.content_ref); + } else if (strcmp (node->name, "Artifact") == 0) { + node->type = PDF_NODE_ARTIFACT; + } else { + node->type = PDF_NODE_STRUCT; + } -static cairo_bool_t -is_leaf_node (cairo_pdf_struct_tree_node_t *node) -{ - return node->parent && cairo_list_is_empty (&node->children) ; + *new_node = node; + return status; } static void @@ -137,23 +416,30 @@ free_node (cairo_pdf_struct_tree_node_t *node) return; cairo_list_foreach_entry_safe (child, next, cairo_pdf_struct_tree_node_t, - &node->children, link) + &node->children, + link) { cairo_list_del (&child->link); free_node (child); } free (node->name); _cairo_array_fini (&node->mcid); + if (node->type == PDF_NODE_CONTENT) + _cairo_tag_free_content_attributes (&node->attributes.content); + + if (node->type == PDF_NODE_CONTENT_REF) + _cairo_tag_free_content_ref_attributes (&node->attributes.content_ref); + free (node); } static cairo_status_t add_mcid_to_node (cairo_pdf_surface_t *surface, cairo_pdf_struct_tree_node_t *node, - int page, + unsigned int command_id, int *mcid) { - struct page_mcid mcid_elem; + cairo_pdf_page_mcid_t mcid_elem; cairo_int_status_t status; cairo_pdf_interchange_t *ic = &surface->interchange; @@ -161,12 +447,33 @@ add_mcid_to_node (cairo_pdf_surface_t *surface, if (unlikely (status)) return status; - mcid_elem.page = page; + mcid_elem.order = -1; + mcid_elem.page = _cairo_array_num_elements (&surface->pages); + mcid_elem.xobject_res = ic->current_recording_surface_res; mcid_elem.mcid = _cairo_array_num_elements (&ic->mcid_to_tree) - 1; + mcid_elem.child_node = NULL; + command_list_set_mcid (surface, command_id, node, _cairo_array_num_elements (&node->mcid)); *mcid = mcid_elem.mcid; return _cairo_array_append (&node->mcid, &mcid_elem); } +static cairo_status_t +add_child_to_mcid_array (cairo_pdf_surface_t *surface, + cairo_pdf_struct_tree_node_t *node, + unsigned int command_id, + cairo_pdf_struct_tree_node_t *child) +{ + cairo_pdf_page_mcid_t mcid_elem; + + mcid_elem.order = -1; + mcid_elem.page = 0; + mcid_elem.xobject_res.id = 0; + mcid_elem.mcid = 0; + mcid_elem.child_node = child; + command_list_set_mcid (surface, command_id, node, _cairo_array_num_elements (&node->mcid)); + return _cairo_array_append (&node->mcid, &mcid_elem); +} + static cairo_int_status_t add_annotation (cairo_pdf_surface_t *surface, cairo_pdf_struct_tree_node_t *node, @@ -177,7 +484,7 @@ add_annotation (cairo_pdf_surface_t *surface, cairo_pdf_interchange_t *ic = &surface->interchange; cairo_pdf_annotation_t *annot; - annot = malloc (sizeof(cairo_pdf_annotation_t)); + annot = _cairo_malloc (sizeof (cairo_pdf_annotation_t)); if (unlikely (annot == NULL)) return _cairo_error (CAIRO_STATUS_NO_MEMORY); @@ -187,8 +494,16 @@ add_annotation (cairo_pdf_surface_t *surface, return status; } + if (annot->link_attrs.link_page == 0) + annot->link_attrs.link_page = _cairo_array_num_elements (&surface->pages); + annot->node = node; + annot->res = _cairo_pdf_surface_new_object (surface); + if (annot->res.id == 0) + return _cairo_error (CAIRO_STATUS_NO_MEMORY); + + node->annot = annot; status = _cairo_array_append (&ic->annots, &annot); return status; @@ -197,10 +512,7 @@ add_annotation (cairo_pdf_surface_t *surface, static void free_annotation (cairo_pdf_annotation_t *annot) { - _cairo_array_fini (&annot->link_attrs.rects); - free (annot->link_attrs.dest); - free (annot->link_attrs.uri); - free (annot->link_attrs.file); + _cairo_tag_free_link_attributes (&annot->link_attrs); free (annot); } @@ -220,15 +532,72 @@ cairo_pdf_interchange_clear_annotations (cairo_pdf_surface_t *surface) _cairo_array_truncate (&ic->annots, 0); } +static void +cairo_pdf_interchange_write_node_mcid (cairo_pdf_surface_t *surface, + cairo_pdf_page_mcid_t *mcid_elem, + int page) +{ + cairo_pdf_page_info_t *page_info; + + page_info = _cairo_array_index (&surface->pages, mcid_elem->page - 1); + if (mcid_elem->page == page && mcid_elem->xobject_res.id == 0) { + _cairo_output_stream_printf (surface->object_stream.stream, "%d ", mcid_elem->mcid); + } else { + _cairo_output_stream_printf (surface->object_stream.stream, + "\n << /Type /MCR "); + if (mcid_elem->page != page) { + _cairo_output_stream_printf (surface->object_stream.stream, + "/Pg %d 0 R ", + page_info->page_res.id); + } + if (mcid_elem->xobject_res.id != 0) { + _cairo_output_stream_printf (surface->object_stream.stream, + "/Stm %d 0 R ", + mcid_elem->xobject_res.id); + } + _cairo_output_stream_printf (surface->object_stream.stream, + "/MCID %d >> ", + mcid_elem->mcid); + } +} + +static int +_mcid_order_compare (const void *a, + const void *b) +{ + const cairo_pdf_page_mcid_t *mcid_a = a; + const cairo_pdf_page_mcid_t *mcid_b = b; + + if (mcid_a->order < mcid_b->order) + return -1; + else if (mcid_a->order > mcid_b->order) + return 1; + else + return 0; +} + static cairo_int_status_t cairo_pdf_interchange_write_node_object (cairo_pdf_surface_t *surface, - cairo_pdf_struct_tree_node_t *node) + cairo_pdf_struct_tree_node_t *node, + int depth) { - struct page_mcid *mcid_elem; - int i, num_mcid, first_page; - cairo_pdf_resource_t *page_res; - cairo_pdf_struct_tree_node_t *child; + cairo_pdf_page_mcid_t *mcid_elem, *child_mcid_elem; + unsigned i, j, num_mcid; + int first_page = 0; + cairo_pdf_page_info_t *page_info; cairo_int_status_t status; + cairo_bool_t has_children = FALSE; + + /* The Root node is written in cairo_pdf_interchange_write_struct_tree(). */ + if (!node->parent) + return CAIRO_STATUS_SUCCESS; + + if (node->type == PDF_NODE_CONTENT || + node->type == PDF_NODE_CONTENT_REF || + node->type == PDF_NODE_ARTIFACT) + { + return CAIRO_STATUS_SUCCESS; + } status = _cairo_pdf_surface_object_begin (surface, node->res); if (unlikely (status)) @@ -241,57 +610,98 @@ cairo_pdf_interchange_write_node_object (cairo_pdf_surface_t *surface node->name, node->parent->res.id); - if (! cairo_list_is_empty (&node->children)) { - if (cairo_list_is_singular (&node->children) && node->annot_res.id == 0) { - child = cairo_list_first_entry (&node->children, cairo_pdf_struct_tree_node_t, link); - _cairo_output_stream_printf (surface->object_stream.stream, " /K %d 0 R\n", child->res.id); - } else { - _cairo_output_stream_printf (surface->object_stream.stream, " /K [ "); - if (node->annot_res.id != 0) { + /* Write /K entry (children of this StructElem) */ + num_mcid = _cairo_array_num_elements (&node->mcid); + if (num_mcid > 0 ) { + _cairo_array_sort (&node->mcid, _mcid_order_compare); + /* Find the first MCID element and use the page number to set /Pg */ + for (i = 0; i < num_mcid; i++) { + mcid_elem = _cairo_array_index (&node->mcid, i); + assert (mcid_elem->order != -1); + if (mcid_elem->child_node) { + if (mcid_elem->child_node->type == PDF_NODE_CONTENT_REF) { + cairo_pdf_struct_tree_node_t *content_node; + status = lookup_content_node_for_ref_node (surface, mcid_elem->child_node, &content_node); + if (status) + return status; + + /* CONTENT_REF will not have child nodes */ + if (_cairo_array_num_elements (&content_node->mcid) > 0) { + child_mcid_elem = _cairo_array_index (&content_node->mcid, 0); + first_page = child_mcid_elem->page; + page_info = _cairo_array_index (&surface->pages, first_page - 1); + _cairo_output_stream_printf (surface->object_stream.stream, + " /Pg %d 0 R\n", + page_info->page_res.id); + has_children = TRUE; + break; + } + } else { + has_children = TRUE; + } + } else { + first_page = mcid_elem->page; + page_info = _cairo_array_index (&surface->pages, first_page - 1); _cairo_output_stream_printf (surface->object_stream.stream, - "<< /Type /OBJR /Obj %d 0 R >> ", - node->annot_res.id); - } - cairo_list_foreach_entry (child, cairo_pdf_struct_tree_node_t, - &node->children, link) - { - _cairo_output_stream_printf (surface->object_stream.stream, "%d 0 R ", child->res.id); + " /Pg %d 0 R\n", + page_info->page_res.id); + has_children = TRUE; + break; } - _cairo_output_stream_printf (surface->object_stream.stream, "]\n"); } - } else { - num_mcid = _cairo_array_num_elements (&node->mcid); - if (num_mcid > 0 ) { - mcid_elem = _cairo_array_index (&node->mcid, 0); - first_page = mcid_elem->page; - page_res = _cairo_array_index (&surface->pages, first_page - 1); - _cairo_output_stream_printf (surface->object_stream.stream, " /Pg %d 0 R\n", page_res->id); - - if (num_mcid == 1 && node->annot_res.id == 0) { - _cairo_output_stream_printf (surface->object_stream.stream, " /K %d\n", mcid_elem->mcid); - } else { - _cairo_output_stream_printf (surface->object_stream.stream, " /K [ "); - if (node->annot_res.id != 0) { - _cairo_output_stream_printf (surface->object_stream.stream, - "<< /Type /OBJR /Obj %d 0 R >> ", - node->annot_res.id); - } - for (i = 0; i < num_mcid; i++) { - mcid_elem = _cairo_array_index (&node->mcid, i); - page_res = _cairo_array_index (&surface->pages, mcid_elem->page - 1); - if (mcid_elem->page == first_page) { - _cairo_output_stream_printf (surface->object_stream.stream, "%d ", mcid_elem->mcid); + + if (has_children || node->annot) { + _cairo_output_stream_printf (surface->object_stream.stream, " /K "); + + if (num_mcid > 1 || node->annot) + _cairo_output_stream_printf (surface->object_stream.stream, "[ "); + + for (i = 0; i < num_mcid; i++) { + if (node->annot) { + if (node->annot->link_attrs.link_page != first_page) { + page_info = _cairo_array_index (&surface->pages, node->annot->link_attrs.link_page - 1); + _cairo_output_stream_printf (surface->object_stream.stream, + "<< /Type /OBJR /Pg %d 0 R /Obj %d 0 R >> ", + page_info->page_res.id, + node->annot->res.id); } else { _cairo_output_stream_printf (surface->object_stream.stream, - "\n << /Type /MCR /Pg %d 0 R /MCID %d >> ", - page_res->id, - mcid_elem->mcid); + "<< /Type /OBJR /Obj %d 0 R >> ", + node->annot->res.id); } } - _cairo_output_stream_printf (surface->object_stream.stream, "]\n"); + mcid_elem = _cairo_array_index (&node->mcid, i); + if (mcid_elem->child_node) { + if (mcid_elem->child_node->type == PDF_NODE_CONTENT_REF) { + cairo_pdf_struct_tree_node_t *content_node; + status = lookup_content_node_for_ref_node (surface, mcid_elem->child_node, &content_node); + if (status) + return status; + + assert (content_node->type == PDF_NODE_CONTENT); + + /* CONTENT_REF will not have child nodes */ + for (j = 0; j < _cairo_array_num_elements (&content_node->mcid); j++) { + child_mcid_elem = _cairo_array_index (&content_node->mcid, j); + cairo_pdf_interchange_write_node_mcid (surface, child_mcid_elem, first_page); + } + } else if (mcid_elem->child_node->type != PDF_NODE_CONTENT) { + _cairo_output_stream_printf (surface->object_stream.stream, + " %d 0 R ", + mcid_elem->child_node->res.id); + } + } else { + cairo_pdf_interchange_write_node_mcid (surface, mcid_elem, first_page); + } } + + if (num_mcid > 1 || node->annot) + _cairo_output_stream_printf (surface->object_stream.stream, "]"); } + + _cairo_output_stream_printf (surface->object_stream.stream, "\n"); } + _cairo_output_stream_printf (surface->object_stream.stream, ">>\n"); @@ -324,7 +734,7 @@ _named_dest_pluck (void *entry, void *closure) cairo_hash_table_t *table = closure; _cairo_hash_table_remove (table, &dest->base); - free (dest->attrs.name); + _cairo_tag_free_dest_attributes (&dest->attrs); free (dest); } @@ -335,21 +745,20 @@ cairo_pdf_interchange_write_explicit_dest (cairo_pdf_surface_t *surface, double x, double y) { - cairo_pdf_resource_t res; - double height; + cairo_pdf_page_info_t *page_info; + + page_info = _cairo_array_index (&surface->pages, page - 1); - _cairo_array_copy_element (&surface->page_heights, page - 1, &height); - _cairo_array_copy_element (&surface->pages, page - 1, &res); if (has_pos) { _cairo_output_stream_printf (surface->object_stream.stream, "[%d 0 R /XYZ %f %f 0]\n", - res.id, + page_info->page_res.id, x, - height - y); + page_info->height - y); } else { _cairo_output_stream_printf (surface->object_stream.stream, "[%d 0 R /XYZ null null 0]\n", - res.id); + page_info->page_res.id); } return CAIRO_STATUS_SUCCESS; @@ -438,6 +847,71 @@ cairo_pdf_interchange_write_dest (cairo_pdf_surface_t *surface, } static cairo_int_status_t +_cairo_utf8_to_pdf_utf8_hexstring (const char *utf8, char **str_out) +{ + int i; + int len; + unsigned char *p; + cairo_bool_t ascii; + char *str; + cairo_int_status_t status = CAIRO_STATUS_SUCCESS; + + ascii = TRUE; + p = (unsigned char *)utf8; + len = 0; + while (*p) { + if (*p < 32 || *p > 126) { + ascii = FALSE; + } + if (*p == '(' || *p == ')' || *p == '\\') + len += 2; + else + len++; + p++; + } + + if (ascii) { + str = _cairo_malloc (len + 3); + if (str == NULL) + return _cairo_error (CAIRO_STATUS_NO_MEMORY); + + str[0] = '('; + p = (unsigned char *)utf8; + i = 1; + while (*p) { + if (*p == '(' || *p == ')' || *p == '\\') + str[i++] = '\\'; + str[i++] = *p; + p++; + } + str[i++] = ')'; + str[i++] = 0; + } else { + str = _cairo_malloc (len*2 + 3); + if (str == NULL) + return _cairo_error (CAIRO_STATUS_NO_MEMORY); + + str[0] = '<'; + p = (unsigned char *)utf8; + i = 1; + while (*p) { + if (*p == '\\') { + snprintf(str + i, 3, "%02x", '\\'); + i += 2; + } + snprintf(str + i, 3, "%02x", *p); + i += 2; + p++; + } + str[i++] = '>'; + str[i++] = 0; + } + *str_out = str; + + return status; +} + +static cairo_int_status_t cairo_pdf_interchange_write_link_action (cairo_pdf_surface_t *surface, cairo_link_attrs_t *link_attrs) { @@ -469,12 +943,42 @@ cairo_pdf_interchange_write_link_action (cairo_pdf_surface_t *surface, dest); free (dest); } else if (link_attrs->link_type == TAG_LINK_FILE) { + /* According to "Developing with PDF", Leonard Rosenthol, 2013, + * The F key is encoded in the "standard encoding for the + * platform on which the document is being viewed. For most + * modern operating systems, that's UTF-8" + * + * As we don't know the target platform, we assume UTF-8. The + * F key may contain multi-byte encodings using the hex + * encoding. + * + * For PDF 1.7 we also include the UF key which uses the + * standard PDF UTF-16BE strings. + */ + status = _cairo_utf8_to_pdf_utf8_hexstring (link_attrs->file, &dest); + if (unlikely (status)) + return status; + _cairo_output_stream_printf (surface->object_stream.stream, " /A <<\n" " /Type /Action\n" " /S /GoToR\n" - " /F (%s)\n", - link_attrs->file); + " /F %s\n", + dest); + free (dest); + + if (surface->pdf_version >= CAIRO_PDF_VERSION_1_7) + { + status = _cairo_utf8_to_pdf_string (link_attrs->file, &dest); + if (unlikely (status)) + return status; + + _cairo_output_stream_printf (surface->object_stream.stream, + " /UF %s\n", + dest); + free (dest); + } + if (link_attrs->dest) { status = _cairo_utf8_to_pdf_string (link_attrs->dest, &dest); if (unlikely (status)) @@ -487,13 +991,13 @@ cairo_pdf_interchange_write_link_action (cairo_pdf_surface_t *surface, } else { if (link_attrs->has_pos) { _cairo_output_stream_printf (surface->object_stream.stream, - " /D [%d %f %f 0]\n", + " /D [%d /XYZ %f %f 0]\n", link_attrs->page, link_attrs->pos.x, link_attrs->pos.y); } else { _cairo_output_stream_printf (surface->object_stream.stream, - " /D [%d null null 0]\n", + " /D [%d /XYZ null null 0]\n", link_attrs->page); } } @@ -506,7 +1010,8 @@ cairo_pdf_interchange_write_link_action (cairo_pdf_surface_t *surface, static cairo_int_status_t cairo_pdf_interchange_write_annot (cairo_pdf_surface_t *surface, - cairo_pdf_annotation_t *annot) + cairo_pdf_annotation_t *annot, + cairo_bool_t struct_parents) { cairo_int_status_t status = CAIRO_STATUS_SUCCESS; cairo_pdf_interchange_t *ic = &surface->interchange; @@ -526,23 +1031,19 @@ cairo_pdf_interchange_write_annot (cairo_pdf_surface_t *surface, sp = _cairo_array_num_elements (&ic->parent_tree) - 1; - node->annot_res = _cairo_pdf_surface_new_object (surface); - if (node->annot_res.id == 0) - return _cairo_error (CAIRO_STATUS_NO_MEMORY); - - status = _cairo_array_append (&surface->page_annots, &node->annot_res); - if (unlikely (status)) - return status; - - status = _cairo_pdf_surface_object_begin (surface, node->annot_res); + status = _cairo_pdf_surface_object_begin (surface, annot->res); if (unlikely (status)) return status; _cairo_output_stream_printf (surface->object_stream.stream, "<< /Type /Annot\n" - " /Subtype /Link\n" - " /StructParent %d\n", - sp); + " /Subtype /Link\n"); + + if (struct_parents) { + _cairo_output_stream_printf (surface->object_stream.stream, + " /StructParent %d\n", + sp); + } height = surface->height; if (num_rects > 0) { @@ -581,7 +1082,7 @@ cairo_pdf_interchange_write_annot (cairo_pdf_surface_t *surface, return status; _cairo_output_stream_printf (surface->object_stream.stream, - " /BS << /W 0 >>" + " /BS << /W 0 >>\n" ">>\n"); _cairo_pdf_surface_object_end (surface); @@ -594,25 +1095,27 @@ cairo_pdf_interchange_write_annot (cairo_pdf_surface_t *surface, static cairo_int_status_t cairo_pdf_interchange_walk_struct_tree (cairo_pdf_surface_t *surface, cairo_pdf_struct_tree_node_t *node, - cairo_int_status_t (*func) (cairo_pdf_surface_t *surface, - cairo_pdf_struct_tree_node_t *node)) + int depth, + cairo_int_status_t (*func) (cairo_pdf_surface_t *surface, + cairo_pdf_struct_tree_node_t *node, + int depth)) { cairo_int_status_t status; cairo_pdf_struct_tree_node_t *child; - if (node->parent) { - status = func (surface, node); - if (unlikely (status)) - return status; - } + status = func (surface, node, depth); + if (unlikely (status)) + return status; + depth++; cairo_list_foreach_entry (child, cairo_pdf_struct_tree_node_t, &node->children, link) { - status = cairo_pdf_interchange_walk_struct_tree (surface, child, func); + status = cairo_pdf_interchange_walk_struct_tree (surface, child, depth, func); if (unlikely (status)) return status; } + depth--; return CAIRO_STATUS_SUCCESS; } @@ -627,15 +1130,12 @@ cairo_pdf_interchange_write_struct_tree (cairo_pdf_surface_t *surface) if (cairo_list_is_empty (&ic->struct_root->children)) return CAIRO_STATUS_SUCCESS; - surface->struct_tree_root = _cairo_pdf_surface_new_object (surface); - if (surface->struct_tree_root.id == 0) - return _cairo_error (CAIRO_STATUS_NO_MEMORY); - - ic->struct_root->res = surface->struct_tree_root; - - cairo_pdf_interchange_walk_struct_tree (surface, ic->struct_root, cairo_pdf_interchange_write_node_object); - - child = cairo_list_first_entry (&ic->struct_root->children, cairo_pdf_struct_tree_node_t, link); + status = cairo_pdf_interchange_walk_struct_tree (surface, + ic->struct_root, + 0, + cairo_pdf_interchange_write_node_object); + if (unlikely (status)) + return status; status = _cairo_pdf_surface_object_begin (surface, surface->struct_tree_root); if (unlikely (status)) @@ -655,6 +1155,9 @@ cairo_pdf_interchange_write_struct_tree (cairo_pdf_surface_t *surface) cairo_list_foreach_entry (child, cairo_pdf_struct_tree_node_t, &ic->struct_root->children, link) { + if (child->type == PDF_NODE_CONTENT || child->type == PDF_NODE_ARTIFACT) + continue; + _cairo_output_stream_printf (surface->object_stream.stream, "%d 0 R ", child->res.id); } _cairo_output_stream_printf (surface->object_stream.stream, "]\n"); @@ -668,18 +1171,31 @@ cairo_pdf_interchange_write_struct_tree (cairo_pdf_surface_t *surface) } static cairo_int_status_t -cairo_pdf_interchange_write_page_annots (cairo_pdf_surface_t *surface) +cairo_pdf_interchange_write_annots (cairo_pdf_surface_t *surface, + cairo_bool_t struct_parents) { cairo_pdf_interchange_t *ic = &surface->interchange; - int num_elems, i; + int num_elems, i, page_num; + cairo_pdf_page_info_t *page_info; + cairo_pdf_annotation_t *annot; cairo_int_status_t status = CAIRO_STATUS_SUCCESS; num_elems = _cairo_array_num_elements (&ic->annots); for (i = 0; i < num_elems; i++) { - cairo_pdf_annotation_t * annot; - _cairo_array_copy_element (&ic->annots, i, &annot); - status = cairo_pdf_interchange_write_annot (surface, annot); + page_num = annot->link_attrs.link_page; + if (page_num > (int)_cairo_array_num_elements (&surface->pages)) { + return _cairo_tag_error ("Link attribute: \"link_page=%d\" page exceeds page count (%d)", + page_num, + _cairo_array_num_elements (&surface->pages)); + } + + page_info = _cairo_array_index (&surface->pages, page_num - 1); + status = _cairo_array_append (&page_info->annots, &annot->res); + if (status) + return status; + + status = cairo_pdf_interchange_write_annot (surface, annot, struct_parents); if (unlikely (status)) return status; } @@ -688,43 +1204,72 @@ cairo_pdf_interchange_write_page_annots (cairo_pdf_surface_t *surface) } static cairo_int_status_t -cairo_pdf_interchange_write_page_parent_elems (cairo_pdf_surface_t *surface) +cairo_pdf_interchange_write_content_parent_elems (cairo_pdf_surface_t *surface) { int num_elems, i; cairo_pdf_struct_tree_node_t *node; - cairo_pdf_resource_t res; cairo_pdf_interchange_t *ic = &surface->interchange; cairo_int_status_t status = CAIRO_STATUS_SUCCESS; - surface->page_parent_tree = -1; num_elems = _cairo_array_num_elements (&ic->mcid_to_tree); - if (num_elems > 0) { - res = _cairo_pdf_surface_new_object (surface); - if (res.id == 0) - return _cairo_error (CAIRO_STATUS_NO_MEMORY); - - status = _cairo_pdf_surface_object_begin (surface, res); - if (unlikely (status)) - return status; + status = _cairo_pdf_surface_object_begin (surface, ic->content_parent_res); + if (unlikely (status)) + return status; - _cairo_output_stream_printf (surface->object_stream.stream, + _cairo_output_stream_printf (surface->object_stream.stream, "[\n"); - for (i = 0; i < num_elems; i++) { - _cairo_array_copy_element (&ic->mcid_to_tree, i, &node); - _cairo_output_stream_printf (surface->object_stream.stream, " %d 0 R\n", node->res.id); - } - _cairo_output_stream_printf (surface->object_stream.stream, - "]\n"); - _cairo_pdf_surface_object_end (surface); - - status = _cairo_array_append (&ic->parent_tree, &res); - surface->page_parent_tree = _cairo_array_num_elements (&ic->parent_tree) - 1; + for (i = 0; i < num_elems; i++) { + _cairo_array_copy_element (&ic->mcid_to_tree, i, &node); + _cairo_output_stream_printf (surface->object_stream.stream, " %d 0 R\n", node->res.id); } + _cairo_output_stream_printf (surface->object_stream.stream, + "]\n"); + _cairo_pdf_surface_object_end (surface); return status; } static cairo_int_status_t +cairo_pdf_interchange_apply_extents_from_content_ref (cairo_pdf_surface_t *surface, + cairo_pdf_struct_tree_node_t *node, + int depth) +{ + cairo_int_status_t status; + + if (node->type != PDF_NODE_CONTENT_REF) + return CAIRO_STATUS_SUCCESS; + + cairo_pdf_struct_tree_node_t *content_node; + status = lookup_content_node_for_ref_node (surface, node, &content_node); + if (status) + return status; + + /* Merge extents with all parent nodes */ + node = node->parent; + while (node) { + if (node->extents.valid) { + _cairo_rectangle_union (&node->extents.extents, &content_node->extents.extents); + } else { + node->extents = content_node->extents; + } + node = node->parent; + } + + return CAIRO_STATUS_SUCCESS; +} + +static cairo_int_status_t +cairo_pdf_interchange_update_extents (cairo_pdf_surface_t *surface) +{ + cairo_pdf_interchange_t *ic = &surface->interchange; + + return cairo_pdf_interchange_walk_struct_tree (surface, + ic->struct_root, + 0, + cairo_pdf_interchange_apply_extents_from_content_ref); +} + +static cairo_int_status_t cairo_pdf_interchange_write_parent_tree (cairo_pdf_surface_t *surface) { int num_elems, i; @@ -961,7 +1506,8 @@ cairo_pdf_interchange_write_forward_links (cairo_pdf_surface_t *surface) TRUE, x, y); } else { - return _cairo_tag_error ("Link to dest=\"%s\" not found", link->dest); + // Destination is missing: just give the link an empty dest string. + _cairo_output_stream_printf(surface->object_stream.stream, "<>\n"); } } else { cairo_pdf_interchange_write_explicit_dest (surface, @@ -1083,6 +1629,7 @@ _cairo_pdf_interchange_write_document_dests (cairo_pdf_surface_t *surface) int i; cairo_pdf_interchange_t *ic = &surface->interchange; cairo_int_status_t status; + cairo_pdf_page_info_t *page_info; if (ic->num_dests == 0) { ic->dests_res.id = 0; @@ -1110,10 +1657,8 @@ _cairo_pdf_interchange_write_document_dests (cairo_pdf_surface_t *surface) "<< /Names [\n"); for (i = 0; i < ic->num_dests; i++) { cairo_pdf_named_dest_t *dest = ic->sorted_dests[i]; - cairo_pdf_resource_t page_res; double x = 0; double y = 0; - double height; if (dest->attrs.internal) continue; @@ -1129,14 +1674,13 @@ _cairo_pdf_interchange_write_document_dests (cairo_pdf_surface_t *surface) if (dest->attrs.y_valid) y = dest->attrs.y; - _cairo_array_copy_element (&surface->pages, dest->page - 1, &page_res); - _cairo_array_copy_element (&surface->page_heights, dest->page - 1, &height); + page_info = _cairo_array_index (&surface->pages, dest->page - 1); _cairo_output_stream_printf (surface->object_stream.stream, " (%s) [%d 0 R /XYZ %f %f 0]\n", dest->attrs.name, - page_res.id, + page_info->page_res.id, x, - height - y); + page_info->height - y); } _cairo_output_stream_printf (surface->object_stream.stream, " ]\n" @@ -1180,6 +1724,9 @@ cairo_pdf_interchange_write_docinfo (cairo_pdf_surface_t *surface) { cairo_pdf_interchange_t *ic = &surface->interchange; cairo_int_status_t status; + unsigned int i, num_elems; + struct metadata *data; + unsigned char *p; surface->docinfo_res = _cairo_pdf_surface_new_object (surface); if (surface->docinfo_res.id == 0) @@ -1214,6 +1761,26 @@ cairo_pdf_interchange_write_docinfo (cairo_pdf_surface_t *surface) if (ic->docinfo.mod_date) _cairo_output_stream_printf (surface->object_stream.stream, " /ModDate %s\n", ic->docinfo.mod_date); + num_elems = _cairo_array_num_elements (&ic->custom_metadata); + for (i = 0; i < num_elems; i++) { + data = _cairo_array_index (&ic->custom_metadata, i); + if (data->value) { + _cairo_output_stream_printf (surface->object_stream.stream, " /"); + /* The name can be any utf8 string. Use hex codes as + * specified in section 7.3.5 of PDF reference + */ + p = (unsigned char *)data->name; + while (*p) { + if (*p < 0x21 || *p > 0x7e || *p == '#' || *p == '/') + _cairo_output_stream_printf (surface->object_stream.stream, "#%02x", *p); + else + _cairo_output_stream_printf (surface->object_stream.stream, "%c", *p); + p++; + } + _cairo_output_stream_printf (surface->object_stream.stream, " %s\n", data->value); + } + } + _cairo_output_stream_printf (surface->object_stream.stream, ">>\n"); _cairo_pdf_surface_object_end (surface); @@ -1227,32 +1794,79 @@ _cairo_pdf_interchange_begin_structure_tag (cairo_pdf_surface_t *surface, const char *name, const char *attributes) { - int page_num, mcid; + int mcid; cairo_int_status_t status = CAIRO_STATUS_SUCCESS; cairo_pdf_interchange_t *ic = &surface->interchange; + cairo_pdf_command_entry_t *command_entry; + cairo_pdf_struct_tree_node_t *parent_node; + unsigned int content_command_id; if (surface->paginated_mode == CAIRO_PAGINATED_MODE_ANALYZE) { - status = add_tree_node (surface, ic->current_node, name, &ic->current_node); + ic->content_emitted = FALSE; + status = add_tree_node (surface, ic->current_analyze_node, name, attributes, &ic->current_analyze_node); + if (unlikely (status)) + return status; + + status = command_list_add (surface, ic->command_id, PDF_BEGIN); if (unlikely (status)) return status; - _cairo_tag_stack_set_top_data (&ic->analysis_tag_stack, ic->current_node); + /* Add to command_id to node map. */ + command_entry = _cairo_malloc (sizeof(cairo_pdf_command_entry_t)); + command_entry->recording_id = ic->recording_id; + command_entry->command_id = ic->command_id; + command_entry->node = ic->current_analyze_node; + _cairo_pdf_command_init_key (command_entry); + status = _cairo_hash_table_insert (ic->command_to_node_map, &command_entry->base); + if (unlikely(status)) + return status; if (tag_type & TAG_TYPE_LINK) { - status = add_annotation (surface, ic->current_node, name, attributes); + status = add_annotation (surface, ic->current_analyze_node, name, attributes); if (unlikely (status)) return status; + } - cairo_list_add_tail (&ic->current_node->extents.link, &ic->extents_list); + if (ic->current_analyze_node->type == PDF_NODE_CONTENT) { + cairo_pdf_content_tag_t *content = _cairo_malloc (sizeof(cairo_pdf_content_tag_t)); + content->node = ic->current_analyze_node; + _cairo_pdf_content_tag_init_key (content); + status = _cairo_hash_table_insert (ic->content_tag_map, &content->base); + if (unlikely (status)) + return status; } + ic->content_emitted = FALSE; + } else if (surface->paginated_mode == CAIRO_PAGINATED_MODE_RENDER) { - ic->current_node = _cairo_tag_stack_top_elem (&ic->render_tag_stack)->data; - assert (ic->current_node != NULL); - if (is_leaf_node (ic->current_node)) { - page_num = _cairo_array_num_elements (&surface->pages); - add_mcid_to_node (surface, ic->current_node, page_num, &mcid); - status = _cairo_pdf_operators_tag_begin (&surface->pdf_operators, name, mcid); + if (ic->marked_content_open) { + status = _cairo_pdf_operators_tag_end (&surface->pdf_operators); + ic->marked_content_open = FALSE; + if (unlikely (status)) + return status; + } + + ic->current_render_node = lookup_node_for_command (surface, ic->recording_id, ic->command_id); + if (ic->current_render_node->type == PDF_NODE_ARTIFACT) { + if (command_list_has_content (surface, ic->command_id, NULL)) { + status = _cairo_pdf_operators_tag_begin (&surface->pdf_operators, name, -1); + ic->marked_content_open = TRUE; + } + } else if (ic->current_render_node->type == PDF_NODE_CONTENT_REF) { + parent_node = ic->current_render_node->parent; + add_child_to_mcid_array (surface, parent_node, ic->command_id, ic->current_render_node); + } else { + parent_node = ic->current_render_node->parent; + add_child_to_mcid_array (surface, parent_node, ic->command_id, ic->current_render_node); + if (command_list_has_content (surface, ic->command_id, &content_command_id)) { + add_mcid_to_node (surface, ic->current_render_node, content_command_id, &mcid); + const char *tag_name = name; + if (ic->current_render_node->type == PDF_NODE_CONTENT) + tag_name = ic->current_render_node->attributes.content.tag_name; + + status = _cairo_pdf_operators_tag_begin (&surface->pdf_operators, tag_name, mcid); + ic->marked_content_open = TRUE; + } } } @@ -1284,15 +1898,13 @@ _cairo_pdf_interchange_begin_dest_tag (cairo_pdf_surface_t *surface, dest->page = _cairo_array_num_elements (&surface->pages); init_named_dest_key (dest); status = _cairo_hash_table_insert (ic->named_dests, &dest->base); - if (unlikely (status)) - { + if (unlikely (status)) { free (dest->attrs.name); free (dest); return status; } _cairo_tag_stack_set_top_data (&ic->analysis_tag_stack, dest); - cairo_list_add_tail (&dest->extents.link, &ic->extents_list); ic->num_dests++; } @@ -1307,22 +1919,21 @@ _cairo_pdf_interchange_tag_begin (cairo_pdf_surface_t *surface, cairo_int_status_t status = CAIRO_STATUS_SUCCESS; cairo_tag_type_t tag_type; cairo_pdf_interchange_t *ic = &surface->interchange; - void *ptr; + + if (ic->ignore_current_surface) + return CAIRO_STATUS_SUCCESS; if (surface->paginated_mode == CAIRO_PAGINATED_MODE_ANALYZE) { status = _cairo_tag_stack_push (&ic->analysis_tag_stack, name, attributes); } else if (surface->paginated_mode == CAIRO_PAGINATED_MODE_RENDER) { status = _cairo_tag_stack_push (&ic->render_tag_stack, name, attributes); - _cairo_array_copy_element (&ic->push_data, ic->push_data_index++, &ptr); - _cairo_tag_stack_set_top_data (&ic->render_tag_stack, ptr); } - if (unlikely (status)) return status; tag_type = _cairo_tag_get_type (name); - if (tag_type & TAG_TYPE_STRUCTURE) { + if (tag_type & (TAG_TYPE_STRUCTURE|TAG_TYPE_CONTENT|TAG_TYPE_CONTENT_REF|TAG_TYPE_ARTIFACT)) { status = _cairo_pdf_interchange_begin_structure_tag (surface, tag_type, name, attributes); if (unlikely (status)) return status; @@ -1334,11 +1945,6 @@ _cairo_pdf_interchange_tag_begin (cairo_pdf_surface_t *surface, return status; } - if (surface->paginated_mode == CAIRO_PAGINATED_MODE_ANALYZE) { - ptr = _cairo_tag_stack_top_elem (&ic->analysis_tag_stack)->data; - status = _cairo_array_append (&ic->push_data, &ptr); - } - return status; } @@ -1347,59 +1953,39 @@ _cairo_pdf_interchange_end_structure_tag (cairo_pdf_surface_t *surface, cairo_tag_type_t tag_type, cairo_tag_stack_elem_t *elem) { - const cairo_pdf_struct_tree_node_t *node; - struct tag_extents *tag, *next; cairo_pdf_interchange_t *ic = &surface->interchange; cairo_int_status_t status = CAIRO_STATUS_SUCCESS; + int mcid; + unsigned int content_command_id; - assert (elem->data != NULL); - node = elem->data; if (surface->paginated_mode == CAIRO_PAGINATED_MODE_ANALYZE) { - if (tag_type & TAG_TYPE_LINK) { - cairo_list_foreach_entry_safe (tag, next, struct tag_extents, - &ic->extents_list, link) { - if (tag == &node->extents) { - cairo_list_del (&tag->link); - break; - } - } - } + assert (ic->current_analyze_node->parent != NULL); + status = command_list_add (surface, ic->command_id, PDF_END); + if (unlikely (status)) + return status; + + ic->content_emitted = FALSE; + ic->current_analyze_node = ic->current_analyze_node->parent; + } else if (surface->paginated_mode == CAIRO_PAGINATED_MODE_RENDER) { - if (is_leaf_node (ic->current_node)) { + if (ic->marked_content_open) { status = _cairo_pdf_operators_tag_end (&surface->pdf_operators); + ic->marked_content_open = FALSE; if (unlikely (status)) return status; } - } - - ic->current_node = ic->current_node->parent; - assert (ic->current_node != NULL); - - return status; -} - -static cairo_int_status_t -_cairo_pdf_interchange_end_dest_tag (cairo_pdf_surface_t *surface, - cairo_tag_type_t tag_type, - cairo_tag_stack_elem_t *elem) -{ - struct tag_extents *tag, *next; - cairo_pdf_named_dest_t *dest; - cairo_pdf_interchange_t *ic = &surface->interchange; - - if (surface->paginated_mode == CAIRO_PAGINATED_MODE_ANALYZE) { - assert (elem->data != NULL); - dest = (cairo_pdf_named_dest_t *) elem->data; - cairo_list_foreach_entry_safe (tag, next, struct tag_extents, - &ic->extents_list, link) { - if (tag == &dest->extents) { - cairo_list_del (&tag->link); - break; - } + ic->current_render_node = ic->current_render_node->parent; + if (ic->current_render_node->parent && + command_list_has_content (surface, ic->command_id, &content_command_id)) + { + add_mcid_to_node (surface, ic->current_render_node, content_command_id, &mcid); + status = _cairo_pdf_operators_tag_begin (&surface->pdf_operators, + ic->current_render_node->name, mcid); + ic->marked_content_open = TRUE; } } - return CAIRO_STATUS_SUCCESS; + return status; } cairo_int_status_t @@ -1411,27 +1997,25 @@ _cairo_pdf_interchange_tag_end (cairo_pdf_surface_t *surface, cairo_tag_type_t tag_type; cairo_tag_stack_elem_t *elem; - if (surface->paginated_mode == CAIRO_PAGINATED_MODE_ANALYZE) + if (ic->ignore_current_surface) + return CAIRO_STATUS_SUCCESS; + + if (surface->paginated_mode == CAIRO_PAGINATED_MODE_ANALYZE) { status = _cairo_tag_stack_pop (&ic->analysis_tag_stack, name, &elem); - else if (surface->paginated_mode == CAIRO_PAGINATED_MODE_RENDER) - status = _cairo_tag_stack_pop (&ic->render_tag_stack, name, &elem); + } else if (surface->paginated_mode == CAIRO_PAGINATED_MODE_RENDER) { + status = _cairo_tag_stack_pop (&ic->render_tag_stack, name, &elem); + } if (unlikely (status)) return status; tag_type = _cairo_tag_get_type (name); - if (tag_type & TAG_TYPE_STRUCTURE) { + if (tag_type & (TAG_TYPE_STRUCTURE|TAG_TYPE_CONTENT|TAG_TYPE_CONTENT_REF|TAG_TYPE_ARTIFACT)) { status = _cairo_pdf_interchange_end_structure_tag (surface, tag_type, elem); if (unlikely (status)) goto cleanup; } - if (tag_type & TAG_TYPE_DEST) { - status = _cairo_pdf_interchange_end_dest_tag (surface, tag_type, elem); - if (unlikely (status)) - goto cleanup; - } - cleanup: _cairo_tag_stack_free_elem (elem); @@ -1439,52 +2023,322 @@ _cairo_pdf_interchange_tag_end (cairo_pdf_surface_t *surface, } cairo_int_status_t +_cairo_pdf_interchange_command_id (cairo_pdf_surface_t *surface, + unsigned int recording_id, + unsigned int command_id) +{ + cairo_pdf_interchange_t *ic = &surface->interchange; + int mcid; + cairo_int_status_t status = CAIRO_STATUS_SUCCESS; + + ic->recording_id = recording_id; + ic->command_id = command_id; + + if (surface->paginated_mode == CAIRO_PAGINATED_MODE_RENDER && ic->current_render_node) { + /* TODO If the group does not have tags we don't need to close the current tag. */ + if (command_list_is_group (surface, command_id)) { + if (ic->marked_content_open) { + status = _cairo_pdf_operators_tag_end (&surface->pdf_operators); + ic->marked_content_open = FALSE; + } + if (command_list_has_content (surface, command_id, NULL)) { + ic->render_next_command_has_content = TRUE; + } + } else if (ic->render_next_command_has_content && ic->current_render_node->name) { + add_mcid_to_node (surface, ic->current_render_node, ic->command_id, &mcid); + status = _cairo_pdf_operators_tag_begin (&surface->pdf_operators, + ic->current_render_node->name, mcid); + ic->marked_content_open = TRUE; + ic->render_next_command_has_content = FALSE; + } + } + + return status; +} + +/* Check if this use of recording surface is or will need to be part of the the struct tree */ +cairo_bool_t +_cairo_pdf_interchange_struct_tree_requires_recording_surface ( + cairo_pdf_surface_t *surface, + const cairo_surface_pattern_t *recording_surface_pattern, + cairo_analysis_source_t source_type) +{ + cairo_surface_t *recording_surface = recording_surface_pattern->surface; + cairo_surface_t *free_me = NULL; + cairo_bool_t requires_recording = FALSE; + + if (recording_surface_pattern->base.extend != CAIRO_EXTEND_NONE) + return FALSE; + + if (_cairo_surface_is_snapshot (recording_surface)) + free_me = recording_surface = _cairo_surface_snapshot_get_target (recording_surface); + + if (_cairo_surface_is_recording(recording_surface) && + _cairo_recording_surface_has_tags(recording_surface)) + { + /* Check if tags are to be ignored in this source */ + switch (source_type) { + case CAIRO_ANALYSIS_SOURCE_PAINT: + case CAIRO_ANALYSIS_SOURCE_FILL: + requires_recording = TRUE; + break; + case CAIRO_ANALYSIS_SOURCE_MASK: /* TODO: allow SOURCE_MASK with solid MASK_MASK */ + case CAIRO_ANALYSIS_MASK_MASK: + case CAIRO_ANALYSIS_SOURCE_STROKE: + case CAIRO_ANALYSIS_SOURCE_SHOW_GLYPHS: + case CAIRO_ANALYSIS_SOURCE_NONE: + break; + } + } + + cairo_surface_destroy (free_me); + return requires_recording; +} + +/* Called at the start of a recording group during analyze. This will + * be called during the analysis of the drawing operation. */ +cairo_int_status_t +_cairo_pdf_interchange_recording_source_surface_begin ( + cairo_pdf_surface_t *surface, + const cairo_surface_pattern_t *recording_surface_pattern, + unsigned int region_id, + cairo_analysis_source_t source_type) +{ + cairo_pdf_interchange_t *ic = &surface->interchange; + cairo_recording_surface_stack_entry_t element; + cairo_int_status_t status; + + /* A new recording surface is being replayed */ + ic->ignore_current_surface = TRUE; + if (_cairo_pdf_interchange_struct_tree_requires_recording_surface (surface, + recording_surface_pattern, + source_type)) + { + ic->ignore_current_surface = FALSE; + } + + element.ignore_surface = ic->ignore_current_surface; + element.current_node = ic->current_analyze_node; + ic->content_emitted = FALSE; + + /* Push to stack so that the current source identifiers can be + * restored after this recording surface has ended. */ + status = _cairo_array_append (&ic->recording_surface_stack, &element); + if (status) + return status; + + if (ic->ignore_current_surface) + return CAIRO_STATUS_SUCCESS; + + status = command_list_push_group (surface, ic->command_id, recording_surface_pattern->surface, region_id); + if (unlikely (status)) + return status; + + return CAIRO_INT_STATUS_ANALYZE_RECORDING_SURFACE_PATTERN; +} + +/* Called at the end of a recording group during analyze. */ +cairo_int_status_t +_cairo_pdf_interchange_recording_source_surface_end ( + cairo_pdf_surface_t *surface, + const cairo_surface_pattern_t *recording_surface_pattern, + unsigned int region_id, + cairo_analysis_source_t source_type) +{ + cairo_pdf_interchange_t *ic = &surface->interchange; + cairo_recording_surface_stack_entry_t element; + cairo_recording_surface_stack_entry_t *element_ptr; + + if (!ic->ignore_current_surface) + command_list_pop_group (surface); + + if (_cairo_array_pop_element (&ic->recording_surface_stack, &element)) { + element_ptr = _cairo_array_last_element (&ic->recording_surface_stack); + if (element_ptr) { + ic->ignore_current_surface = element_ptr->ignore_surface; + assert (ic->current_analyze_node == element_ptr->current_node); + } else { + /* Back at the page content. */ + ic->ignore_current_surface = FALSE; + } + ic->content_emitted = FALSE; + return CAIRO_STATUS_SUCCESS; + } + ASSERT_NOT_REACHED; /* _recording_source_surface_begin/end mismatch */ + + return CAIRO_STATUS_SUCCESS; +} + +/* Called at the start of a recording group during render. This will + * be called after the end of page content. */ +cairo_int_status_t +_cairo_pdf_interchange_emit_recording_surface_begin (cairo_pdf_surface_t *surface, + cairo_surface_t *recording_surface, + int region_id, + cairo_pdf_resource_t surface_resource, + int *struct_parents) +{ + cairo_pdf_interchange_t *ic = &surface->interchange; + cairo_int_status_t status; + + /* When + * _cairo_pdf_interchange_struct_tree_requires_recording_surface() + * is false, the region_id of the recording surface is set to 0. + */ + if (region_id == 0) { + ic->ignore_current_surface = TRUE; + return CAIRO_STATUS_SUCCESS; + } + + command_list_set_current_recording_commands (surface, recording_surface, region_id); + + ic->ignore_current_surface = FALSE; + _cairo_array_truncate (&ic->mcid_to_tree, 0); + ic->current_recording_surface_res = surface_resource; + + ic->content_parent_res = _cairo_pdf_surface_new_object (surface); + if (ic->content_parent_res.id == 0) + return _cairo_error (CAIRO_STATUS_NO_MEMORY); + + status = _cairo_array_append (&ic->parent_tree, &ic->content_parent_res); + if (unlikely (status)) + return status; + + *struct_parents = _cairo_array_num_elements (&ic->parent_tree) - 1; + + ic->render_next_command_has_content = FALSE; + + return CAIRO_STATUS_SUCCESS; +} + +/* Called at the end of a recording group during render. */ +cairo_int_status_t +_cairo_pdf_interchange_emit_recording_surface_end (cairo_pdf_surface_t *surface, + cairo_surface_t *recording_surface) +{ + cairo_pdf_interchange_t *ic = &surface->interchange; + + if (ic->ignore_current_surface) + return CAIRO_STATUS_SUCCESS; + + ic->current_recording_surface_res.id = 0; + return cairo_pdf_interchange_write_content_parent_elems (surface); +} + +static void _add_operation_extents_to_dest_tag (cairo_tag_stack_elem_t *elem, + void *closure) +{ + const cairo_rectangle_int_t *extents = (const cairo_rectangle_int_t *) closure; + cairo_pdf_named_dest_t *dest; + + if (_cairo_tag_get_type (elem->name) & TAG_TYPE_DEST) { + if (elem->data) { + dest = (cairo_pdf_named_dest_t *) elem->data; + if (dest->extents.valid) { + _cairo_rectangle_union (&dest->extents.extents, extents); + } else { + dest->extents.extents = *extents; + dest->extents.valid = TRUE; + } + } + } +} + +cairo_int_status_t _cairo_pdf_interchange_add_operation_extents (cairo_pdf_surface_t *surface, const cairo_rectangle_int_t *extents) { cairo_pdf_interchange_t *ic = &surface->interchange; - struct tag_extents *tag; + /* Add extents to current node and all DEST tags on the stack */ if (surface->paginated_mode == CAIRO_PAGINATED_MODE_ANALYZE) { - cairo_list_foreach_entry (tag, struct tag_extents, &ic->extents_list, link) { - if (tag->valid) { - _cairo_rectangle_union (&tag->extents, extents); + if (ic->current_analyze_node) { + if (ic->current_analyze_node->extents.valid) { + _cairo_rectangle_union (&ic->current_analyze_node->extents.extents, extents); } else { - tag->extents = *extents; - tag->valid = TRUE; + ic->current_analyze_node->extents.extents = *extents; + ic->current_analyze_node->extents.valid = TRUE; } } + + _cairo_tag_stack_foreach (&ic->analysis_tag_stack, + _add_operation_extents_to_dest_tag, + (void*)extents); } return CAIRO_STATUS_SUCCESS; } cairo_int_status_t +_cairo_pdf_interchange_add_content (cairo_pdf_surface_t *surface) +{ + cairo_pdf_interchange_t *ic = &surface->interchange; + cairo_int_status_t status = CAIRO_STATUS_SUCCESS; + + if (ic->ignore_current_surface) + return CAIRO_STATUS_SUCCESS; + + if (surface->paginated_mode == CAIRO_PAGINATED_MODE_ANALYZE) { + status = command_list_add (surface, ic->command_id, PDF_CONTENT); + if (unlikely (status)) + return status; + } + + return status; +} + +/* Called at the start of 1emiting the page content during analyze or render */ +cairo_int_status_t _cairo_pdf_interchange_begin_page_content (cairo_pdf_surface_t *surface) { cairo_pdf_interchange_t *ic = &surface->interchange; cairo_int_status_t status = CAIRO_STATUS_SUCCESS; - int page_num, mcid; + int mcid; + unsigned int content_command_id; + cairo_pdf_command_list_t *page_commands; if (surface->paginated_mode == CAIRO_PAGINATED_MODE_ANALYZE) { - _cairo_array_truncate (&ic->mcid_to_tree, 0); - _cairo_array_truncate (&ic->push_data, 0); - ic->begin_page_node = ic->current_node; + status = _cairo_array_allocate (&ic->page_commands, 1, (void**)&page_commands); + if (unlikely (status)) + return status; + + _cairo_array_init (&page_commands->commands, sizeof(cairo_pdf_command_t)); + page_commands->parent = NULL; + ic->current_commands = page_commands; + ic->ignore_current_surface = FALSE; } else if (surface->paginated_mode == CAIRO_PAGINATED_MODE_RENDER) { - ic->push_data_index = 0; - ic->current_node = ic->begin_page_node; - if (ic->end_page_node && is_leaf_node (ic->end_page_node)) { - page_num = _cairo_array_num_elements (&surface->pages); - add_mcid_to_node (surface, ic->end_page_node, page_num, &mcid); - status = _cairo_pdf_operators_tag_begin (&surface->pdf_operators, - ic->end_page_node->name, - mcid); + ic->current_commands = _cairo_array_last_element (&ic->page_commands); + /* Each page has its own parent tree to map MCID to nodes. */ + _cairo_array_truncate (&ic->mcid_to_tree, 0); + ic->ignore_current_surface = FALSE; + ic->content_parent_res = _cairo_pdf_surface_new_object (surface); + if (ic->content_parent_res.id == 0) + return _cairo_error (CAIRO_STATUS_NO_MEMORY); + + status = _cairo_array_append (&ic->parent_tree, &ic->content_parent_res); + if (unlikely (status)) + return status; + + surface->page_parent_tree = _cairo_array_num_elements (&ic->parent_tree) - 1; + + if (ic->next_page_render_node && ic->next_page_render_node->parent && + command_list_has_content (surface, -1, &content_command_id)) + { + add_mcid_to_node (surface, ic->next_page_render_node, content_command_id, &mcid); + const char *tag_name = ic->next_page_render_node->name; + if (ic->next_page_render_node->type == PDF_NODE_CONTENT) + tag_name = ic->next_page_render_node->attributes.content.tag_name; + + status = _cairo_pdf_operators_tag_begin (&surface->pdf_operators, tag_name, mcid); + ic->marked_content_open = TRUE; } + ic->render_next_command_has_content = FALSE; } return status; } +/* Called at the end of emiting the page content during analyze or render */ cairo_int_status_t _cairo_pdf_interchange_end_page_content (cairo_pdf_surface_t *surface) { @@ -1492,9 +2346,12 @@ _cairo_pdf_interchange_end_page_content (cairo_pdf_surface_t *surface) cairo_int_status_t status = CAIRO_STATUS_SUCCESS; if (surface->paginated_mode == CAIRO_PAGINATED_MODE_RENDER) { - ic->end_page_node = ic->current_node; - if (is_leaf_node (ic->current_node)) + /* If a content tag is open across pages, the old page needs an EMC emitted. */ + if (ic->marked_content_open) { status = _cairo_pdf_operators_tag_end (&surface->pdf_operators); + ic->marked_content_open = FALSE; + } + ic->next_page_render_node = ic->current_render_node; } return status; @@ -1503,15 +2360,7 @@ _cairo_pdf_interchange_end_page_content (cairo_pdf_surface_t *surface) cairo_int_status_t _cairo_pdf_interchange_write_page_objects (cairo_pdf_surface_t *surface) { - cairo_int_status_t status; - - status = cairo_pdf_interchange_write_page_annots (surface); - if (unlikely (status)) - return status; - - cairo_pdf_interchange_clear_annotations (surface); - - return cairo_pdf_interchange_write_page_parent_elems (surface); + return cairo_pdf_interchange_write_content_parent_elems (surface); } cairo_int_status_t @@ -1520,15 +2369,41 @@ _cairo_pdf_interchange_write_document_objects (cairo_pdf_surface_t *surface) cairo_pdf_interchange_t *ic = &surface->interchange; cairo_int_status_t status = CAIRO_STATUS_SUCCESS; cairo_tag_stack_structure_type_t tag_type; + cairo_bool_t write_struct_tree = FALSE; + + status = cairo_pdf_interchange_update_extents (surface); + if (unlikely (status)) + return status; tag_type = _cairo_tag_stack_get_structure_type (&ic->analysis_tag_stack); if (tag_type == TAG_TREE_TYPE_TAGGED || tag_type == TAG_TREE_TYPE_STRUCTURE || - tag_type == TAG_TREE_TYPE_LINK_ONLY) { + tag_type == TAG_TREE_TYPE_LINK_ONLY) + { + write_struct_tree = TRUE; + } + + status = cairo_pdf_interchange_write_annots (surface, write_struct_tree); + if (unlikely (status)) + return status; + + if (write_struct_tree) { + surface->struct_tree_root = _cairo_pdf_surface_new_object (surface); + if (surface->struct_tree_root.id == 0) + return _cairo_error (CAIRO_STATUS_NO_MEMORY); + + ic->struct_root->res = surface->struct_tree_root; status = cairo_pdf_interchange_write_parent_tree (surface); if (unlikely (status)) return status; + unsigned num_pages = _cairo_array_num_elements (&ic->page_commands); + for (unsigned i = 0; i < num_pages; i++) { + cairo_pdf_command_list_t *command_list; + command_list = _cairo_array_index (&ic->page_commands, i); + update_mcid_order (surface, command_list); + } + status = cairo_pdf_interchange_write_struct_tree (surface); if (unlikely (status)) return status; @@ -1606,16 +2481,27 @@ _cairo_pdf_interchange_init (cairo_pdf_surface_t *surface) _cairo_tag_stack_init (&ic->analysis_tag_stack); _cairo_tag_stack_init (&ic->render_tag_stack); - _cairo_array_init (&ic->push_data, sizeof(void *)); ic->struct_root = calloc (1, sizeof(cairo_pdf_struct_tree_node_t)); if (unlikely (ic->struct_root == NULL)) return _cairo_error (CAIRO_STATUS_NO_MEMORY); + ic->struct_root->res.id = 0; cairo_list_init (&ic->struct_root->children); - _cairo_array_init (&ic->struct_root->mcid, sizeof(struct page_mcid)); - ic->current_node = ic->struct_root; - ic->begin_page_node = NULL; - ic->end_page_node = NULL; + _cairo_array_init (&ic->struct_root->mcid, sizeof(cairo_pdf_page_mcid_t)); + + ic->current_analyze_node = ic->struct_root; + ic->current_render_node = NULL; + ic->next_page_render_node = ic->struct_root; + _cairo_array_init (&ic->recording_surface_stack, sizeof(cairo_recording_surface_stack_entry_t)); + ic->current_recording_surface_res.id = 0; + ic->command_to_node_map = _cairo_hash_table_create (_cairo_pdf_command_equal); + if (unlikely (ic->command_to_node_map == NULL)) + return _cairo_error (CAIRO_STATUS_NO_MEMORY); + + ic->content_tag_map = _cairo_hash_table_create (_cairo_pdf_content_tag_equal); + if (unlikely (ic->content_tag_map == NULL)) + return _cairo_error (CAIRO_STATUS_NO_MEMORY); + _cairo_array_init (&ic->parent_tree, sizeof(cairo_pdf_resource_t)); _cairo_array_init (&ic->mcid_to_tree, sizeof(cairo_pdf_struct_tree_node_t *)); _cairo_array_init (&ic->annots, sizeof(cairo_pdf_annotation_t *)); @@ -1625,9 +2511,18 @@ _cairo_pdf_interchange_init (cairo_pdf_surface_t *surface) if (unlikely (ic->named_dests == NULL)) return _cairo_error (CAIRO_STATUS_NO_MEMORY); + _cairo_array_init (&ic->page_commands, sizeof(cairo_pdf_command_list_t)); + ic->current_commands = NULL; + _cairo_array_init (&ic->recording_surface_commands, sizeof(cairo_pdf_recording_surface_commands_t)); + ic->num_dests = 0; ic->sorted_dests = NULL; ic->dests_res.id = 0; + ic->ignore_current_surface = FALSE; + ic->content_emitted = FALSE; + ic->marked_content_open = FALSE; + ic->render_next_command_has_content = FALSE; + ic->mcid_order = 0; _cairo_array_init (&ic->outline, sizeof(cairo_pdf_outline_entry_t *)); outline_root = calloc (1, sizeof(cairo_pdf_outline_entry_t)); @@ -1635,6 +2530,7 @@ _cairo_pdf_interchange_init (cairo_pdf_surface_t *surface) return _cairo_error (CAIRO_STATUS_NO_MEMORY); memset (&ic->docinfo, 0, sizeof (ic->docinfo)); + _cairo_array_init (&ic->custom_metadata, sizeof(struct metadata)); _cairo_pdf_interchange_set_create_date (surface); status = _cairo_array_append (&ic->outline, &outline_root); @@ -1653,9 +2549,7 @@ _cairo_pdf_interchange_free_outlines (cairo_pdf_surface_t *surface) _cairo_array_copy_element (&ic->outline, i, &outline); free (outline->name); - free (outline->link_attrs.dest); - free (outline->link_attrs.uri); - free (outline->link_attrs.file); + _cairo_tag_free_link_attributes (&outline->link_attrs); free (outline); } _cairo_array_fini (&ic->outline); @@ -1665,17 +2559,51 @@ void _cairo_pdf_interchange_fini (cairo_pdf_surface_t *surface) { cairo_pdf_interchange_t *ic = &surface->interchange; + unsigned int i, num_elems; + struct metadata *data; _cairo_tag_stack_fini (&ic->analysis_tag_stack); _cairo_tag_stack_fini (&ic->render_tag_stack); - _cairo_array_fini (&ic->push_data); - free_node (ic->struct_root); _cairo_array_fini (&ic->mcid_to_tree); cairo_pdf_interchange_clear_annotations (surface); _cairo_array_fini (&ic->annots); + + _cairo_array_fini (&ic->recording_surface_stack); _cairo_array_fini (&ic->parent_tree); + + _cairo_hash_table_foreach (ic->command_to_node_map, + _cairo_pdf_command_pluck, + ic->command_to_node_map); + _cairo_hash_table_destroy (ic->command_to_node_map); + _cairo_hash_table_foreach (ic->named_dests, _named_dest_pluck, ic->named_dests); _cairo_hash_table_destroy (ic->named_dests); + + _cairo_hash_table_foreach (ic->content_tag_map, _cairo_pdf_content_tag_pluck, ic->content_tag_map); + _cairo_hash_table_destroy(ic->content_tag_map); + + free_node (ic->struct_root); + + num_elems = _cairo_array_num_elements (&ic->recording_surface_commands); + for (i = 0; i < num_elems; i++) { + cairo_pdf_recording_surface_commands_t *recording_command; + cairo_pdf_command_list_t *command_list; + + recording_command = _cairo_array_index (&ic->recording_surface_commands, i); + command_list = recording_command->command_list; + _cairo_array_fini (&command_list->commands); + free (command_list); + } + _cairo_array_fini (&ic->recording_surface_commands); + + num_elems = _cairo_array_num_elements (&ic->page_commands); + for (i = 0; i < num_elems; i++) { + cairo_pdf_command_list_t *command_list; + command_list = _cairo_array_index (&ic->page_commands, i); + _cairo_array_fini (&command_list->commands); + } + _cairo_array_fini (&ic->page_commands); + free (ic->sorted_dests); _cairo_pdf_interchange_free_outlines (surface); free (ic->docinfo.title); @@ -1685,6 +2613,14 @@ _cairo_pdf_interchange_fini (cairo_pdf_surface_t *surface) free (ic->docinfo.creator); free (ic->docinfo.create_date); free (ic->docinfo.mod_date); + + num_elems = _cairo_array_num_elements (&ic->custom_metadata); + for (i = 0; i < num_elems; i++) { + data = _cairo_array_index (&ic->custom_metadata, i); + free (data->name); + free (data->value); + } + _cairo_array_fini (&ic->custom_metadata); } cairo_int_status_t @@ -1879,3 +2815,189 @@ _cairo_pdf_interchange_set_metadata (cairo_pdf_surface_t *surface, return CAIRO_STATUS_SUCCESS; } + +static const char *reserved_metadata_names[] = { + "", + "Title", + "Author", + "Subject", + "Keywords", + "Creator", + "Producer", + "CreationDate", + "ModDate", + "Trapped", +}; + +cairo_int_status_t +_cairo_pdf_interchange_set_custom_metadata (cairo_pdf_surface_t *surface, + const char *name, + const char *value) +{ + cairo_pdf_interchange_t *ic = &surface->interchange; + struct metadata *data; + struct metadata new_data; + int i, num_elems; + cairo_int_status_t status; + char *s = NULL; + + if (name == NULL) + return CAIRO_STATUS_NULL_POINTER; + + for (i = 0; i < ARRAY_LENGTH (reserved_metadata_names); i++) { + if (strcmp(name, reserved_metadata_names[i]) == 0) + return CAIRO_STATUS_INVALID_STRING; + } + + /* First check if we already have an entry for this name. If so, + * update the value. A NULL value means the entry has been removed + * and will not be emitted. */ + num_elems = _cairo_array_num_elements (&ic->custom_metadata); + for (i = 0; i < num_elems; i++) { + data = _cairo_array_index (&ic->custom_metadata, i); + if (strcmp(name, data->name) == 0) { + free (data->value); + data->value = NULL; + if (value && strlen(value)) { + status = _cairo_utf8_to_pdf_string (value, &s); + if (unlikely (status)) + return status; + data->value = s; + } + return CAIRO_STATUS_SUCCESS; + } + } + + /* Add new entry */ + status = CAIRO_STATUS_SUCCESS; + if (value && strlen(value)) { + new_data.name = strdup (name); + status = _cairo_utf8_to_pdf_string (value, &s); + if (unlikely (status)) + return status; + new_data.value = s; + status = _cairo_array_append (&ic->custom_metadata, &new_data); + } + + return status; +} + +#if DEBUG_PDF_INTERCHANGE +static cairo_int_status_t +print_node (cairo_pdf_surface_t *surface, + cairo_pdf_struct_tree_node_t *node, + int depth) +{ + if (node == NULL) { + printf("%*sNode: ptr: NULL\n", depth*2, ""); + } else if (node == surface->interchange.struct_root) { + printf("%*sNode: ptr: %p root\n", depth*2, "", node); + } else { + printf("%*sNode: ptr: %p name: '%s'\n", depth*2, "", node, node->name); + } + depth++; + printf("%*sType: ", depth*2, ""); + switch (node->type) { + case PDF_NODE_STRUCT: + printf("STRUCT\n"); + break; + case PDF_NODE_CONTENT: + printf("CONTENT\n"); + printf("%*sContent.id: %s\n", depth*2, "", node->attributes.content.id); + printf("%*sContent.tag_name: %s\n", depth*2, "", node->attributes.content.tag_name); + break; + case PDF_NODE_CONTENT_REF: + printf("CONTENT_REF\n"); + printf("%*sContent_Ref.ref: %s\n", depth*2, "", node->attributes.content_ref.ref); + break; + case PDF_NODE_ARTIFACT: + printf("ARTIFACT\n"); + break; + } + printf("%*sres: %d\n", depth*2, "", node->res.id); + printf("%*sparent: %p\n", depth*2, "", node->parent); + printf("%*sannot:", depth*2, ""); + if (node->annot) + printf(" node: %p res: %d", node->annot->node, node->annot->res.id); + printf("\n"); + printf("%*sextents: ", depth*2, ""); + if (node->extents.valid) { + printf("x: %d y: %d w: %d h: %d\n", + node->extents.extents.x, + node->extents.extents.y, + node->extents.extents.width, + node->extents.extents.height); + } else { + printf("not valid\n"); + } + + printf("%*smcid: ", depth*2, ""); + int num_mcid = _cairo_array_num_elements (&node->mcid); + for (int i = 0; i < num_mcid; i++) { + cairo_pdf_page_mcid_t *mcid_elem = _cairo_array_index (&node->mcid, i); + if (mcid_elem->child_node) { + printf("(order: %d, %p) ", mcid_elem->order, mcid_elem->child_node); + } else { + printf("(order: %d, pg: %d, xobject_res: %d, mcid: %d) ", + mcid_elem->order, mcid_elem->page, mcid_elem->xobject_res.id, mcid_elem->mcid); + } + } + printf("\n"); + return CAIRO_STATUS_SUCCESS; +} + +static void +print_tree (cairo_pdf_surface_t *surface, + cairo_pdf_struct_tree_node_t *node) +{ + printf("Structure Tree:\n"); + cairo_pdf_interchange_walk_struct_tree (surface, node, 0, print_node); +} + +static void +print_command (cairo_pdf_command_t *command, int indent) +{ + printf("%*s%d ", indent*2, "", command->command_id); + switch (command->flags) { + case PDF_CONTENT: + printf("CONTENT"); + break; + case PDF_BEGIN: + printf("BEGIN"); + break; + case PDF_END: + printf("END"); + break; + case PDF_GROUP: + printf("GROUP: %p", command->group); + break; + case PDF_NONE: + printf("NONE"); + break; + } + printf(" node: %p index: %d\n", command->node, command->mcid_index); +} + +static void +print_commands (cairo_pdf_command_list_t *command_list, int indent) +{ + cairo_pdf_command_t *command; + unsigned i; + unsigned num_elements = _cairo_array_num_elements (&command_list->commands); + + for (i = 0; i < num_elements; i++) { + command = _cairo_array_index (&command_list->commands, i); + print_command (command, indent); + if (command->flags == PDF_GROUP) + print_commands (command->group, indent + 1); + } +} + +static void +print_command_list(cairo_pdf_command_list_t *command_list) +{ + printf("Command List: %p\n", command_list); + print_commands (command_list, 0); + printf("end\n"); +} +#endif diff --git a/gfx/cairo/cairo/src/cairo-pdf-operators.c b/gfx/cairo/cairo/src/cairo-pdf-operators.c index 328e893d71..176f45b481 100644 --- a/gfx/cairo/cairo/src/cairo-pdf-operators.c +++ b/gfx/cairo/cairo/src/cairo-pdf-operators.c @@ -1568,10 +1568,16 @@ _cairo_pdf_operators_tag_begin (cairo_pdf_operators_t *pdf_operators, return status; } - _cairo_output_stream_printf (pdf_operators->stream, - "/%s << /MCID %d >> BDC\n", - tag_name, - mcid); + if (mcid >= 0) { + _cairo_output_stream_printf (pdf_operators->stream, + "/%s << /MCID %d >> BDC\n", + tag_name, + mcid); + } else { + _cairo_output_stream_printf (pdf_operators->stream, + "/%s BMC\n", + tag_name); + } return _cairo_output_stream_get_status (pdf_operators->stream); } diff --git a/gfx/cairo/cairo/src/cairo-pdf-surface-private.h b/gfx/cairo/cairo/src/cairo-pdf-surface-private.h index b2d8575507..13ccc50019 100644 --- a/gfx/cairo/cairo/src/cairo-pdf-surface-private.h +++ b/gfx/cairo/cairo/src/cairo-pdf-surface-private.h @@ -74,6 +74,10 @@ typedef struct _cairo_pdf_source_surface_entry { unsigned char *unique_id; unsigned long unique_id_length; cairo_operator_t operator; + + /* If not 0, this is the recording surface region id of the source surface. */ + int region_id; + cairo_bool_t interpolate; cairo_bool_t stencil_mask; cairo_bool_t smask; @@ -95,6 +99,7 @@ typedef struct _cairo_pdf_source_surface_entry { typedef struct _cairo_pdf_source_surface { cairo_pattern_type_t type; cairo_surface_t *surface; + unsigned int region_id; cairo_pattern_t *raster_pattern; cairo_pdf_source_surface_entry_t *hash_entry; } cairo_pdf_source_surface_t; @@ -109,6 +114,9 @@ typedef struct _cairo_pdf_pattern { cairo_operator_t operator; cairo_bool_t is_shading; + /* Index into nodes array in cairo_pdf_surface_node_entry_t or -1 if not used */ + int region_id; + /* PDF pattern space is the pattern matrix concatenated with the * initial space of the parent object. If the parent object is the * page, the initial space does not include the Y-axis flipping @@ -160,38 +168,87 @@ typedef struct _cairo_pdf_jbig2_global { cairo_bool_t emitted; } cairo_pdf_jbig2_global_t; -/* cairo-pdf-interchange.c types */ +typedef struct _cairo_pdf_page_info { + double width; + double height; + cairo_pdf_resource_t page_res; + cairo_pdf_resource_t content; + cairo_pdf_resource_t resources; + cairo_pdf_resource_t thumbnail; + cairo_array_t annots; /* <cairo_pdf_resource_t> */ + int struct_parents; +} cairo_pdf_page_info_t; -struct page_mcid { - int page; - int mcid; -}; -struct tag_extents { +/* cairo-pdf-interchange.c types */ + +typedef struct _pdf_tag_extents { cairo_rectangle_int_t extents; cairo_bool_t valid; - cairo_list_t link; -}; +} cairo_pdf_tag_extents_t; + +typedef struct _pdf_page_mcid { + int order; + int page; + cairo_pdf_resource_t xobject_res; /* 0 if not in an XObject */ + int mcid; + struct _cairo_pdf_struct_tree_node *child_node; +} cairo_pdf_page_mcid_t; + +/* The non PDF_NODE_STRUCT types are excluded from the struct tree embedded in + * the PDF. */ +typedef enum _cairo_pdf_tree_node_type { + PDF_NODE_STRUCT, + PDF_NODE_CONTENT, + PDF_NODE_CONTENT_REF, + PDF_NODE_ARTIFACT, +} cairo_pdf_tree_node_type_t; typedef struct _cairo_pdf_struct_tree_node { + cairo_hash_entry_t hash; + cairo_pdf_tree_node_type_t type; char *name; cairo_pdf_resource_t res; struct _cairo_pdf_struct_tree_node *parent; cairo_list_t children; - cairo_array_t mcid; /* array of struct page_mcid */ - cairo_pdf_resource_t annot_res; /* 0 if no annot */ - struct tag_extents extents; - cairo_list_t link; + cairo_array_t mcid; /* array of cairo_pdf_page_mcid_t */ + struct _cairo_pdf_annotation *annot; + cairo_pdf_tag_extents_t extents; + + union { + cairo_content_attrs_t content; /* type == PDF_NODE_CONTENT */ + cairo_content_ref_attrs_t content_ref; /* type == PDF_NODE_CONTENT_REF */ + } attributes; + + cairo_list_t link; /* linked list of parent's children */ } cairo_pdf_struct_tree_node_t; +typedef struct _cairo_pdf_command_entry { + cairo_hash_entry_t base; + unsigned int recording_id; + unsigned int command_id; + cairo_pdf_struct_tree_node_t *node; +} cairo_pdf_command_entry_t; + +typedef struct _cairo_recording_surface_stack_entry { + cairo_bool_t ignore_surface; + cairo_pdf_struct_tree_node_t *current_node; +} cairo_recording_surface_stack_entry_t; + +typedef struct _cairo_pdf_content_tag { + cairo_hash_entry_t base; + cairo_pdf_struct_tree_node_t *node; +} cairo_pdf_content_tag_t; + typedef struct _cairo_pdf_annotation { cairo_pdf_struct_tree_node_t *node; /* node containing the annotation */ cairo_link_attrs_t link_attrs; + cairo_pdf_resource_t res; } cairo_pdf_annotation_t; typedef struct _cairo_pdf_named_dest { cairo_hash_entry_t base; - struct tag_extents extents; + cairo_pdf_tag_extents_t extents; cairo_dest_attrs_t attrs; int page; } cairo_pdf_named_dest_t; @@ -227,19 +284,70 @@ struct docinfo { char *mod_date; }; +struct metadata { + char *name; + char *value; +}; + +typedef enum _cairo_pdf_operation_flags_t { + PDF_NONE = 0, + PDF_CONTENT, + PDF_BEGIN, + PDF_END, + PDF_GROUP, +} cairo_pdf_operation_flags_t; + +typedef struct _pdf_command_list { + cairo_array_t commands; + struct _pdf_command_list *parent; +} cairo_pdf_command_list_t; + +typedef struct _pdf_operation { + cairo_pdf_command_list_t *group; + cairo_pdf_struct_tree_node_t *node; + unsigned int command_id; + int mcid_index; + cairo_pdf_operation_flags_t flags; +} cairo_pdf_command_t; + +typedef struct _pdf_recording_surface_commands { + cairo_surface_t *recording_surface; + cairo_pdf_command_list_t *command_list; + unsigned int region_id; +} cairo_pdf_recording_surface_commands_t; + typedef struct _cairo_pdf_interchange { cairo_tag_stack_t analysis_tag_stack; cairo_tag_stack_t render_tag_stack; - cairo_array_t push_data; /* records analysis_tag_stack data field for each push */ - int push_data_index; cairo_pdf_struct_tree_node_t *struct_root; - cairo_pdf_struct_tree_node_t *current_node; - cairo_pdf_struct_tree_node_t *begin_page_node; - cairo_pdf_struct_tree_node_t *end_page_node; - cairo_array_t parent_tree; /* parent tree resources */ - cairo_array_t mcid_to_tree; /* mcid to tree node mapping for current page */ + + /* Current position in the tree during the analysis stage and across + * pages as each page adds to the tree */ + cairo_pdf_struct_tree_node_t *current_analyze_node; + + /* Currently open tag content containing content. NULL if no content tag open. + * A content containg tag may be open across pages */ + cairo_pdf_struct_tree_node_t *current_render_node; + cairo_pdf_struct_tree_node_t *next_page_render_node; + + cairo_array_t recording_surface_stack; /* cairo_recording_surface_stack_entry_t */ + cairo_pdf_resource_t current_recording_surface_res; + cairo_hash_table_t *command_to_node_map; /* <cairo_pdf_surface_node_entry_t> */ + cairo_bool_t ignore_current_surface; + cairo_hash_table_t *content_tag_map; /* <char*,cairo_pdf_content_tag_t> */ + + cairo_array_t parent_tree; /* <cairo_pdf_resource_t> */ cairo_array_t annots; /* array of pointers to cairo_pdf_annotation_t */ + cairo_pdf_resource_t content_parent_res; cairo_pdf_resource_t parent_tree_res; + + /* mcid to tree node for current page or group */ + cairo_array_t mcid_to_tree; /* <cairo_pdf_struct_tree_node_t *> */ + + cairo_array_t page_commands; /* <cairo_pdf_command_list_t> */ + cairo_pdf_command_list_t *current_commands; /* <cairo_pdf_command_list_t> */ + cairo_array_t recording_surface_commands; /* <cairo_pdf_recording_surface_commands_t> */ + cairo_list_t extents_list; cairo_hash_table_t *named_dests; int num_dests; @@ -248,9 +356,23 @@ typedef struct _cairo_pdf_interchange { int annot_page; cairo_array_t outline; /* array of pointers to cairo_pdf_outline_entry_t; */ struct docinfo docinfo; + cairo_array_t custom_metadata; /* array of struct metadata */ + cairo_bool_t content_emitted; + cairo_bool_t marked_content_open; + unsigned int recording_id; + unsigned int command_id; + cairo_bool_t render_next_command_has_content; + int mcid_order; } cairo_pdf_interchange_t; +typedef struct _cairo_pdf_color_glyph { + cairo_hash_entry_t base; + cairo_scaled_font_t *scaled_font; + unsigned long glyph_index; + cairo_bool_t supported; +} cairo_pdf_color_glyph_t; + /* pdf surface data */ typedef struct _cairo_pdf_surface cairo_pdf_surface_t; @@ -269,18 +391,19 @@ struct _cairo_pdf_surface { cairo_matrix_t cairo_to_pdf; cairo_bool_t in_xobject; - cairo_array_t objects; - cairo_array_t pages; + cairo_array_t objects; /* cairo_pdf_resource_t - list of every resource in the PDF */ + cairo_array_t pages; /* <cairo_pdf_page_info_t> */ cairo_array_t rgb_linear_functions; cairo_array_t alpha_linear_functions; - cairo_array_t page_patterns; - cairo_array_t page_surfaces; - cairo_array_t doc_surfaces; - cairo_hash_table_t *all_surfaces; + cairo_array_t page_patterns; /* cairo_pdf_pattern_t */ + cairo_array_t page_surfaces; /* cairo_pdf_source_surface_t */ + cairo_array_t doc_surfaces; /* cairo_pdf_source_surface_t */ + cairo_hash_table_t *all_surfaces; /* cairo_pdf_source_surface_entry_t* */ + int duplicate_surface_number; cairo_array_t smask_groups; cairo_array_t knockout_group; cairo_array_t jbig2_global; - cairo_array_t page_heights; + cairo_hash_table_t *color_glyphs; cairo_scaled_font_subsets_t *font_subsets; cairo_array_t fonts; @@ -302,7 +425,7 @@ struct _cairo_pdf_surface { cairo_bool_t active; cairo_pdf_resource_t self; cairo_pdf_resource_t length; - long start_offset; + long long start_offset; cairo_bool_t compressed; cairo_output_stream_t *old_output; } pdf_stream; @@ -328,11 +451,13 @@ struct _cairo_pdf_surface { cairo_pdf_operators_t pdf_operators; cairo_paginated_mode_t paginated_mode; + cairo_bool_t type3_replay; cairo_bool_t select_pattern_gstate_saved; cairo_bool_t force_fallbacks; cairo_operator_t current_operator; + cairo_bool_t reset_gs_required; cairo_bool_t current_pattern_is_solid_color; cairo_bool_t current_color_is_stroke; double current_color_red; @@ -357,6 +482,8 @@ struct _cairo_pdf_surface { cairo_image_surface_t *thumbnail_image; cairo_surface_t *paginated_surface; + + cairo_bool_t debug; }; cairo_private cairo_pdf_resource_t @@ -393,15 +520,56 @@ _cairo_pdf_surface_object_begin (cairo_pdf_surface_t *surface, cairo_private void _cairo_pdf_surface_object_end (cairo_pdf_surface_t *surface); +cairo_private cairo_bool_t +_cairo_pdf_interchange_struct_tree_requires_recording_surface ( + cairo_pdf_surface_t *surface, + const cairo_surface_pattern_t *recording_surface, + cairo_analysis_source_t source_type); + +cairo_private cairo_int_status_t +_cairo_pdf_interchange_recording_source_surface_begin ( + cairo_pdf_surface_t *surface, + const cairo_surface_pattern_t *recording_surface_pattern, + unsigned int region_id, + cairo_analysis_source_t source_type); + +cairo_private cairo_int_status_t +_cairo_pdf_interchange_recording_source_surface_end ( + cairo_pdf_surface_t *surface, + const cairo_surface_pattern_t *recording_surface_pattern, + unsigned int region_id, + cairo_analysis_source_t source_type); + +cairo_private cairo_int_status_t +_cairo_pdf_interchange_emit_recording_surface_begin ( + cairo_pdf_surface_t *surface, + cairo_surface_t *recording_surface, + int region_id, + cairo_pdf_resource_t surface_resource, + int *struct_parents); + +cairo_private cairo_int_status_t +_cairo_pdf_interchange_emit_recording_surface_end ( + cairo_pdf_surface_t *surface, + cairo_surface_t *recording_surface); + cairo_private cairo_int_status_t _cairo_pdf_interchange_tag_end (cairo_pdf_surface_t *surface, const char *name); cairo_private cairo_int_status_t +_cairo_pdf_interchange_command_id (cairo_pdf_surface_t *surface, + unsigned int recording_id, + unsigned int command_id); + +cairo_private cairo_int_status_t _cairo_pdf_interchange_add_operation_extents (cairo_pdf_surface_t *surface, const cairo_rectangle_int_t *extents); cairo_private cairo_int_status_t +_cairo_pdf_interchange_add_content (cairo_pdf_surface_t *surface); + +cairo_private cairo_int_status_t _cairo_pdf_interchange_write_page_objects (cairo_pdf_surface_t *surface); cairo_private cairo_int_status_t @@ -420,4 +588,9 @@ _cairo_pdf_interchange_set_metadata (cairo_pdf_surface_t *surface, cairo_pdf_metadata_t metadata, const char *utf8); +cairo_private cairo_int_status_t +_cairo_pdf_interchange_set_custom_metadata (cairo_pdf_surface_t *surface, + const char *name, + const char *value); + #endif /* CAIRO_PDF_SURFACE_PRIVATE_H */ diff --git a/gfx/cairo/cairo/src/cairo-pdf-surface.c b/gfx/cairo/cairo/src/cairo-pdf-surface.c index 9496941113..50f4daa57a 100644 --- a/gfx/cairo/cairo/src/cairo-pdf-surface.c +++ b/gfx/cairo/cairo/src/cairo-pdf-surface.c @@ -54,6 +54,7 @@ #include "cairo-error-private.h" #include "cairo-image-surface-inline.h" #include "cairo-image-info-private.h" +#include "cairo-recording-surface-inline.h" #include "cairo-recording-surface-private.h" #include "cairo-output-stream-private.h" #include "cairo-paginated-private.h" @@ -132,10 +133,10 @@ * The PDF surface is used to render cairo graphics to Adobe * PDF files and is a multi-page vector surface backend. * - * The following mime types are supported: %CAIRO_MIME_TYPE_JPEG, - * %CAIRO_MIME_TYPE_JP2, %CAIRO_MIME_TYPE_UNIQUE_ID, - * %CAIRO_MIME_TYPE_JBIG2, %CAIRO_MIME_TYPE_JBIG2_GLOBAL, - * %CAIRO_MIME_TYPE_JBIG2_GLOBAL_ID, + * The following mime types are supported on source patterns: + * %CAIRO_MIME_TYPE_JPEG, %CAIRO_MIME_TYPE_JP2, + * %CAIRO_MIME_TYPE_UNIQUE_ID, %CAIRO_MIME_TYPE_JBIG2, + * %CAIRO_MIME_TYPE_JBIG2_GLOBAL, %CAIRO_MIME_TYPE_JBIG2_GLOBAL_ID, * %CAIRO_MIME_TYPE_CCITT_FAX, %CAIRO_MIME_TYPE_CCITT_FAX_PARAMS. * * # JBIG2 Images # @@ -209,7 +210,9 @@ _cairo_pdf_surface_get_extents (void *abstract_surface, static const cairo_pdf_version_t _cairo_pdf_versions[] = { CAIRO_PDF_VERSION_1_4, - CAIRO_PDF_VERSION_1_5 + CAIRO_PDF_VERSION_1_5, + CAIRO_PDF_VERSION_1_6, + CAIRO_PDF_VERSION_1_7 }; #define CAIRO_PDF_VERSION_LAST ARRAY_LENGTH (_cairo_pdf_versions) @@ -217,7 +220,9 @@ static const cairo_pdf_version_t _cairo_pdf_versions[] = static const char * _cairo_pdf_version_strings[CAIRO_PDF_VERSION_LAST] = { "PDF 1.4", - "PDF 1.5" + "PDF 1.5", + "PDF 1.6", + "PDF 1.7" }; static const char *_cairo_pdf_supported_mime_types[] = @@ -243,7 +248,7 @@ typedef enum { typedef struct _cairo_pdf_object { cairo_pdf_object_type_t type; union { - long offset; /* type == PDF_OBJECT_UNCOMPRESSED */ + long long offset; /* type == PDF_OBJECT_UNCOMPRESSED */ struct compressed_obj { /* type == PDF_OBJECT_COMPRESSED */ cairo_pdf_resource_t xref_stream; int index; @@ -253,7 +258,7 @@ typedef struct _cairo_pdf_object { typedef struct _cairo_xref_stream_object { cairo_pdf_resource_t resource; - long offset; + long long offset; } cairo_xref_stream_object_t; typedef struct _cairo_pdf_font { @@ -275,7 +280,8 @@ typedef struct _cairo_pdf_alpha_linear_function { } cairo_pdf_alpha_linear_function_t; static void -_cairo_pdf_surface_clear (cairo_pdf_surface_t *surface); +_cairo_pdf_surface_clear (cairo_pdf_surface_t *surface, + cairo_bool_t clear_doc_surfaces); static void _cairo_pdf_smask_group_destroy (cairo_pdf_smask_group_t *group); @@ -313,7 +319,7 @@ static cairo_int_status_t _cairo_pdf_surface_write_catalog (cairo_pdf_surface_t *surface, cairo_pdf_resource_t catalog); -static long +static long long _cairo_pdf_surface_write_xref (cairo_pdf_surface_t *surface); static cairo_int_status_t @@ -321,7 +327,7 @@ _cairo_pdf_surface_write_xref_stream (cairo_pdf_surface_t *surface, cairo_pdf_resource_t xref_res, cairo_pdf_resource_t root_res, cairo_pdf_resource_t info_res, - long *xref_offset); + long long *xref_offset); static cairo_int_status_t _cairo_pdf_surface_write_patterns_and_smask_groups (cairo_pdf_surface_t *surface, @@ -333,6 +339,9 @@ _cairo_pdf_surface_emit_font_subsets (cairo_pdf_surface_t *surface); static cairo_bool_t _cairo_pdf_source_surface_equal (const void *key_a, const void *key_b); +static cairo_bool_t +_cairo_pdf_color_glyph_equal (const void *key_a, const void *key_b); + static const cairo_surface_backend_t cairo_pdf_surface_backend; static const cairo_paginated_surface_backend_t cairo_pdf_surface_paginated_backend; @@ -462,7 +471,7 @@ _cairo_pdf_surface_create_for_stream_internal (cairo_output_stream_t *output, surface->surface_bounded = TRUE; _cairo_array_init (&surface->objects, sizeof (cairo_pdf_object_t)); - _cairo_array_init (&surface->pages, sizeof (cairo_pdf_resource_t)); + _cairo_array_init (&surface->pages, sizeof (cairo_pdf_page_info_t)); _cairo_array_init (&surface->rgb_linear_functions, sizeof (cairo_pdf_rgb_linear_function_t)); _cairo_array_init (&surface->alpha_linear_functions, sizeof (cairo_pdf_alpha_linear_function_t)); _cairo_array_init (&surface->fonts, sizeof (cairo_pdf_font_t)); @@ -473,19 +482,26 @@ _cairo_pdf_surface_create_for_stream_internal (cairo_output_stream_t *output, _cairo_array_init (&surface->page_surfaces, sizeof (cairo_pdf_source_surface_t)); _cairo_array_init (&surface->doc_surfaces, sizeof (cairo_pdf_source_surface_t)); _cairo_array_init (&surface->jbig2_global, sizeof (cairo_pdf_jbig2_global_t)); - _cairo_array_init (&surface->page_heights, sizeof (double)); surface->all_surfaces = _cairo_hash_table_create (_cairo_pdf_source_surface_equal); if (unlikely (surface->all_surfaces == NULL)) { status = _cairo_error (CAIRO_STATUS_NO_MEMORY); goto BAIL0; } + surface->color_glyphs = _cairo_hash_table_create (_cairo_pdf_color_glyph_equal); + if (unlikely (surface->color_glyphs == NULL)) { + status = _cairo_error (CAIRO_STATUS_NO_MEMORY); + goto BAIL1; + } + + surface->duplicate_surface_number = 0; + _cairo_pdf_group_resources_init (&surface->resources); surface->font_subsets = _cairo_scaled_font_subsets_create_composite (); if (! surface->font_subsets) { status = _cairo_error (CAIRO_STATUS_NO_MEMORY); - goto BAIL1; + goto BAIL2; } _cairo_scaled_font_subsets_enable_latin_subset (surface->font_subsets, TRUE); @@ -494,11 +510,11 @@ _cairo_pdf_surface_create_for_stream_internal (cairo_output_stream_t *output, surface->pages_resource = _cairo_pdf_surface_new_object (surface); if (surface->pages_resource.id == 0) { status = _cairo_error (CAIRO_STATUS_NO_MEMORY); - goto BAIL2; + goto BAIL3; } surface->struct_tree_root.id = 0; - surface->pdf_version = CAIRO_PDF_VERSION_1_5; + surface->pdf_version = CAIRO_PDF_VERSION_1_7; surface->compress_streams = TRUE; surface->pdf_stream.active = FALSE; surface->pdf_stream.old_output = NULL; @@ -510,11 +526,13 @@ _cairo_pdf_surface_create_for_stream_internal (cairo_output_stream_t *output, _cairo_array_init (&surface->object_stream.objects, sizeof (cairo_xref_stream_object_t)); surface->paginated_mode = CAIRO_PAGINATED_MODE_ANALYZE; + surface->type3_replay = FALSE; surface->force_fallbacks = FALSE; surface->select_pattern_gstate_saved = FALSE; surface->current_pattern_is_solid_color = FALSE; surface->current_operator = CAIRO_OPERATOR_OVER; + surface->reset_gs_required = FALSE; surface->header_emitted = FALSE; _cairo_surface_clipper_init (&surface->clipper, @@ -532,7 +550,7 @@ _cairo_pdf_surface_create_for_stream_internal (cairo_output_stream_t *output, status = _cairo_pdf_interchange_init (surface); if (unlikely (status)) - goto BAIL2; + goto BAIL3; surface->page_parent_tree = -1; _cairo_array_init (&surface->page_annots, sizeof (cairo_pdf_resource_t)); @@ -548,8 +566,11 @@ _cairo_pdf_surface_create_for_stream_internal (cairo_output_stream_t *output, surface->thumbnail_height = 0; surface->thumbnail_image = NULL; - if (getenv ("CAIRO_DEBUG_PDF") != NULL) + surface->debug = FALSE; + if (getenv ("CAIRO_DEBUG_PDF") != NULL) { + surface->debug = TRUE; surface->compress_streams = FALSE; + } surface->paginated_surface = _cairo_paginated_surface_create ( &surface->base, @@ -563,8 +584,10 @@ _cairo_pdf_surface_create_for_stream_internal (cairo_output_stream_t *output, return surface->paginated_surface; } -BAIL2: +BAIL3: _cairo_scaled_font_subsets_destroy (surface->font_subsets); +BAIL2: + _cairo_hash_table_destroy (surface->color_glyphs); BAIL1: _cairo_hash_table_destroy (surface->all_surfaces); BAIL0: @@ -775,7 +798,7 @@ cairo_pdf_get_versions (cairo_pdf_version_t const **versions, const char * cairo_pdf_version_to_string (cairo_pdf_version_t version) { - if (version >= CAIRO_PDF_VERSION_LAST) + if (version < 0 || version >= CAIRO_PDF_VERSION_LAST) return NULL; return _cairo_pdf_version_strings[version]; @@ -909,6 +932,42 @@ cairo_pdf_surface_set_metadata (cairo_surface_t *surface, } /** + * cairo_pdf_surface_set_custom_metadata: + * @surface: a PDF #cairo_surface_t + * @name: The name of the custom metadata item to set (utf8). + * @value: The value of the metadata (utf8). + * + * Set custom document metadata. @name may be any string except for + * the following names reserved by PDF: "Title", "Author", "Subject", + * "Keywords", "Creator", "Producer", "CreationDate", "ModDate", + * "Trapped". + * + * If @value is NULL or an empty string, the @name metadata will not be set. + * + * For example: + * <informalexample><programlisting> + * cairo_pdf_surface_set_custom_metadata (surface, "ISBN", "978-0123456789"); + * </programlisting></informalexample> + * + * Since: 1.18 + **/ +void +cairo_pdf_surface_set_custom_metadata (cairo_surface_t *surface, + const char *name, + const char *value) +{ + cairo_pdf_surface_t *pdf_surface = NULL; /* hide compiler warning */ + cairo_status_t status; + + if (! _extract_pdf_surface (surface, &pdf_surface)) + return; + + status = _cairo_pdf_interchange_set_custom_metadata (pdf_surface, name, value); + if (status) + status = _cairo_surface_set_error (surface, status); +} + +/** * cairo_pdf_surface_set_page_label: * @surface: a PDF #cairo_surface_t * @utf8: The page label. @@ -957,12 +1016,14 @@ cairo_pdf_surface_set_thumbnail_size (cairo_surface_t *surface, } static void -_cairo_pdf_surface_clear (cairo_pdf_surface_t *surface) +_cairo_pdf_surface_clear (cairo_pdf_surface_t *surface, + cairo_bool_t clear_doc_surfaces) { int i, size; cairo_pdf_pattern_t *pattern; cairo_pdf_source_surface_t *src_surface; cairo_pdf_smask_group_t *group; + cairo_pdf_source_surface_t doc_surface; size = _cairo_array_num_elements (&surface->page_patterns); for (i = 0; i < size; i++) { @@ -974,7 +1035,13 @@ _cairo_pdf_surface_clear (cairo_pdf_surface_t *surface) size = _cairo_array_num_elements (&surface->page_surfaces); for (i = 0; i < size; i++) { src_surface = (cairo_pdf_source_surface_t *) _cairo_array_index (&surface->page_surfaces, i); - cairo_surface_destroy (src_surface->surface); + if (src_surface->type == CAIRO_PATTERN_TYPE_RASTER_SOURCE) { + cairo_pattern_destroy (src_surface->raster_pattern); + } else { + if (_cairo_surface_is_recording (src_surface->surface) && src_surface->region_id != 0) + _cairo_recording_surface_region_array_remove (src_surface->surface, src_surface->region_id); + cairo_surface_destroy (src_surface->surface); + } } _cairo_array_truncate (&surface->page_surfaces, 0); @@ -990,6 +1057,21 @@ _cairo_pdf_surface_clear (cairo_pdf_surface_t *surface) if (surface->thumbnail_image) cairo_surface_destroy (&surface->thumbnail_image->base); surface->thumbnail_image = NULL; + + if (clear_doc_surfaces) { + size = _cairo_array_num_elements (&surface->doc_surfaces); + for (i = 0; i < size; i++) { + _cairo_array_copy_element (&surface->doc_surfaces, i, &doc_surface); + if (doc_surface.type == CAIRO_PATTERN_TYPE_RASTER_SOURCE) { + cairo_pattern_destroy (doc_surface.raster_pattern); + } else { + if (_cairo_surface_is_recording (doc_surface.surface) && doc_surface.region_id != 0) + _cairo_recording_surface_region_array_remove (doc_surface.surface, doc_surface.region_id); + cairo_surface_destroy (doc_surface.surface); + } + } + _cairo_array_truncate (&surface->doc_surfaces, 0); + } } static void @@ -1379,6 +1461,9 @@ _cairo_pdf_source_surface_equal (const void *key_a, const void *key_b) if (a->interpolate != b->interpolate) return FALSE; + if (a->region_id != b->region_id) + return FALSE; + if (a->unique_id && b->unique_id && a->unique_id_length == b->unique_id_length) return (memcmp (a->unique_id, b->unique_id, a->unique_id_length) == 0); @@ -1394,6 +1479,28 @@ _cairo_pdf_source_surface_init_key (cairo_pdf_source_surface_entry_t *key) } else { key->base.hash = key->id; } + key->base.hash = _cairo_hash_bytes (key->base.hash, + &key->region_id, + sizeof(key->region_id)); +} + +static cairo_bool_t +_cairo_pdf_color_glyph_equal (const void *key_a, const void *key_b) +{ + const cairo_pdf_color_glyph_t *a = key_a; + const cairo_pdf_color_glyph_t *b = key_b; + + if (a->scaled_font != b->scaled_font) + return FALSE; + + return (a->glyph_index == b->glyph_index); +} + +static void +_cairo_pdf_color_glyph_init_key (cairo_pdf_color_glyph_t *key) +{ + key->base.hash = _cairo_hash_uintptr (_CAIRO_HASH_INIT_VALUE, (uintptr_t)key->scaled_font); + key->base.hash = _cairo_hash_uintptr (key->base.hash, key->glyph_index); } static cairo_int_status_t @@ -1504,6 +1611,11 @@ _get_source_surface_extents (cairo_surface_t *source, * @surface: [in] the pdf surface * @source_surface: [in] A #cairo_surface_t to use as the source surface * @source_pattern: [in] A #cairo_pattern_t of type SURFACE or RASTER_SOURCE to use as the source + * @region_id: [in] Surfaces containing tags set this to the recording + * surface region id. When tags are used in a XObject, PDF requires a + * separate object for each use (section 14.7.4.2) @region_id is used + * as a key to ensure a separate object is emitted for each use. Set + * to 0 for surfaces without tags. * @op: [in] the operator used to composite this source * @filter: [in] filter type of the source pattern * @stencil_mask: [in] if true, the surface will be written to the PDF as an /ImageMask @@ -1531,6 +1643,7 @@ static cairo_int_status_t _cairo_pdf_surface_add_source_surface (cairo_pdf_surface_t *surface, cairo_surface_t *source_surface, const cairo_pattern_t *source_pattern, + int region_id, cairo_operator_t op, cairo_filter_t filter, cairo_bool_t stencil_mask, @@ -1556,6 +1669,7 @@ _cairo_pdf_surface_add_source_surface (cairo_pdf_surface_t *surface, cairo_rectangle_int_t op_extents; double x, y; cairo_bool_t subsurface; + cairo_bool_t emit_image; switch (filter) { default: @@ -1603,10 +1717,21 @@ _cairo_pdf_surface_add_source_surface (cairo_pdf_surface_t *surface, *source_extents = op_extents; surface_key.id = source_surface->unique_id; - surface_key.interpolate = interpolate; + + /* Recording surfaces do not use interpolate. Ensure it is always + * false for recording surfaces. This is because pdf-interchange + * needs to lookup recording surfaces in the hash table using + * interpolate = FALSE in the key since it does not know the + * interpolate value passed to this function. + */ + emit_image = source_surface->type != CAIRO_SURFACE_TYPE_RECORDING; + surface_key.interpolate = emit_image ? interpolate : FALSE; + cairo_surface_get_mime_data (source_surface, CAIRO_MIME_TYPE_UNIQUE_ID, (const unsigned char **) &surface_key.unique_id, &surface_key.unique_id_length); + + surface_key.region_id = region_id; _cairo_pdf_source_surface_init_key (&surface_key); surface_entry = _cairo_hash_table_lookup (surface->all_surfaces, &surface_key.base); if (surface_entry) { @@ -1649,9 +1774,12 @@ _cairo_pdf_surface_add_source_surface (cairo_pdf_surface_t *surface, if (pdf_source) *pdf_source = surface_entry; + surface_entry->id = surface_key.id; + surface_entry->region_id = region_id; surface_entry->operator = op; - surface_entry->interpolate = interpolate; + surface_entry->interpolate = emit_image ? interpolate : FALSE; + surface_entry->emit_image = emit_image; surface_entry->stencil_mask = stencil_mask; surface_entry->smask = smask; surface_entry->need_transp_group = need_transp_group; @@ -1683,6 +1811,7 @@ _cairo_pdf_surface_add_source_surface (cairo_pdf_surface_t *surface, _cairo_pdf_source_surface_init_key (surface_entry); src_surface.hash_entry = surface_entry; + src_surface.region_id = 0; if (source_pattern && source_pattern->type == CAIRO_PATTERN_TYPE_RASTER_SOURCE) { src_surface.type = CAIRO_PATTERN_TYPE_RASTER_SOURCE; src_surface.surface = NULL; @@ -1694,6 +1823,16 @@ _cairo_pdf_surface_add_source_surface (cairo_pdf_surface_t *surface, src_surface.type = CAIRO_PATTERN_TYPE_SURFACE; src_surface.surface = cairo_surface_reference (source_surface); src_surface.raster_pattern = NULL; + if (source_pattern) { + cairo_surface_pattern_t *surface_pattern = (cairo_surface_pattern_t *) source_pattern; + src_surface.region_id = surface_pattern->region_array_id; + if (_cairo_surface_is_recording (surface_pattern->surface) && + surface_pattern->region_array_id != 0) + { + _cairo_recording_surface_region_array_reference (surface_pattern->surface, + surface_pattern->region_array_id); + } + } } surface_entry->surface_res = _cairo_pdf_surface_new_object (surface); @@ -1702,11 +1841,6 @@ _cairo_pdf_surface_add_source_surface (cairo_pdf_surface_t *surface, goto fail3; } - /* Test if surface will be emitted as image or recording */ - status = _cairo_pdf_surface_emit_surface (surface, &src_surface, TRUE, &surface_entry->emit_image); - if (unlikely (status)) - goto fail3; - if (surface_entry->bounded) { status = _cairo_array_append (&surface->page_surfaces, &src_surface); if (unlikely (status)) @@ -1750,6 +1884,7 @@ static cairo_int_status_t _cairo_pdf_surface_add_pdf_pattern_or_shading (cairo_pdf_surface_t *surface, const cairo_pattern_t *pattern, cairo_operator_t op, + cairo_analysis_source_t source_type, const cairo_rectangle_int_t *extents, cairo_bool_t is_shading, cairo_pdf_resource_t *pattern_res, @@ -1757,6 +1892,7 @@ _cairo_pdf_surface_add_pdf_pattern_or_shading (cairo_pdf_surface_t *surface, { cairo_pdf_pattern_t pdf_pattern; cairo_int_status_t status; + int region_id = 0; pdf_pattern.is_shading = is_shading; pdf_pattern.operator = op; @@ -1815,6 +1951,17 @@ _cairo_pdf_surface_add_pdf_pattern_or_shading (cairo_pdf_surface_t *surface, * Y-axis. */ pdf_pattern.inverted_y_axis = pdf_pattern.gstate_res.id ? TRUE : surface->in_xobject; + if (pattern->type == CAIRO_PATTERN_TYPE_SURFACE) { + cairo_surface_pattern_t *surface_pattern = (cairo_surface_pattern_t *) pattern; + if (_cairo_pdf_interchange_struct_tree_requires_recording_surface (surface, + surface_pattern, + source_type)) + { + region_id = surface_pattern->region_array_id; + } + } + pdf_pattern.region_id = region_id; + status = _cairo_array_append (&surface->page_patterns, &pdf_pattern); if (unlikely (status)) { cairo_pattern_destroy (pdf_pattern.pattern); @@ -1846,6 +1993,7 @@ _cairo_pdf_surface_add_pdf_shading (cairo_pdf_surface_t *surface, return _cairo_pdf_surface_add_pdf_pattern_or_shading (surface, pattern, op, + CAIRO_ANALYSIS_SOURCE_NONE, extents, TRUE, shading_res, @@ -1856,6 +2004,7 @@ static cairo_int_status_t _cairo_pdf_surface_add_pdf_pattern (cairo_pdf_surface_t *surface, const cairo_pattern_t *pattern, cairo_operator_t op, + cairo_analysis_source_t source_type, const cairo_rectangle_int_t *extents, cairo_pdf_resource_t *pattern_res, cairo_pdf_resource_t *gstate_res) @@ -1863,6 +2012,7 @@ _cairo_pdf_surface_add_pdf_pattern (cairo_pdf_surface_t *surface, return _cairo_pdf_surface_add_pdf_pattern_or_shading (surface, pattern, op, + source_type, extents, FALSE, pattern_res, @@ -1943,7 +2093,7 @@ static cairo_int_status_t _cairo_pdf_surface_close_stream (cairo_pdf_surface_t *surface) { cairo_int_status_t status; - long length; + long long length; if (! surface->pdf_stream.active) return CAIRO_INT_STATUS_SUCCESS; @@ -1973,7 +2123,7 @@ _cairo_pdf_surface_close_stream (cairo_pdf_surface_t *surface) surface->pdf_stream.length); _cairo_output_stream_printf (surface->output, "%d 0 obj\n" - " %ld\n" + " %lld\n" "endobj\n", surface->pdf_stream.length.id, length); @@ -2073,7 +2223,7 @@ _cairo_pdf_surface_open_group (cairo_pdf_surface_t *surface, surface->group_stream.bbox = *bbox; /* Reset gstate */ - _cairo_output_stream_printf (surface->output, "/gs0 gs\n"); + surface->reset_gs_required = TRUE; surface->current_pattern_is_solid_color = FALSE; surface->current_operator = CAIRO_OPERATOR_OVER; _cairo_pdf_operators_reset (&surface->pdf_operators); @@ -2134,6 +2284,7 @@ _cairo_pdf_surface_close_group (cairo_pdf_surface_t *surface, surface->group_stream.mem_stream = NULL; surface->group_stream.stream = NULL; + surface->reset_gs_required = FALSE; return status; } @@ -2141,7 +2292,7 @@ _cairo_pdf_surface_close_group (cairo_pdf_surface_t *surface, static cairo_int_status_t _cairo_pdf_surface_open_object_stream (cairo_pdf_surface_t *surface) { - if (surface->pdf_version < CAIRO_PDF_VERSION_1_5) { + if (surface->debug || surface->pdf_version < CAIRO_PDF_VERSION_1_5) { /* Object streams not supported. All objects will be written * directly to the file. */ assert (surface->pdf_stream.active == FALSE); @@ -2197,7 +2348,9 @@ _cairo_pdf_surface_object_end (cairo_pdf_surface_t *surface) } } -static int _cairo_xref_stream_object_compare (const void *a, const void *b) +static int +_cairo_xref_stream_object_compare (const void *a, + const void *b) { const cairo_xref_stream_object_t *a_obj = a; const cairo_xref_stream_object_t *b_obj = b; @@ -2215,7 +2368,7 @@ _cairo_pdf_surface_close_object_stream (cairo_pdf_surface_t *surface) { int i, num_objects; cairo_xref_stream_object_t *xref_obj; - long start_pos, length; + long long start_pos, length; cairo_output_stream_t *index_stream; cairo_output_stream_t *deflate_stream; cairo_pdf_resource_t length_res; @@ -2240,7 +2393,7 @@ _cairo_pdf_surface_close_object_stream (cairo_pdf_surface_t *surface) for (i = 0; i < num_objects; i++) { xref_obj = _cairo_array_index (&surface->object_stream.objects, i); _cairo_output_stream_printf (index_stream, - "%d %ld\n", + "%d %lld\n", xref_obj->resource.id, xref_obj->offset); } @@ -2295,7 +2448,7 @@ _cairo_pdf_surface_close_object_stream (cairo_pdf_surface_t *surface) length_res); _cairo_output_stream_printf (surface->output, "%d 0 obj\n" - " %ld\n" + " %lld\n" "endobj\n", length_res.id, length); @@ -2319,7 +2472,8 @@ _cairo_pdf_surface_open_content_stream (cairo_pdf_surface_t *surface, const cairo_box_double_t *bbox, cairo_pdf_resource_t *resource, cairo_bool_t is_form, - cairo_bool_t is_group) + cairo_bool_t is_group, + int struct_parents) { cairo_int_status_t status; @@ -2333,41 +2487,57 @@ _cairo_pdf_surface_open_content_stream (cairo_pdf_surface_t *surface, if (is_form) { assert (bbox != NULL); + cairo_output_stream_t *mem_stream = _cairo_memory_stream_create (); if (is_group) { - status = - _cairo_pdf_surface_open_stream (surface, - resource, - surface->compress_streams, - " /Type /XObject\n" - " /Subtype /Form\n" - " /BBox [ %f %f %f %f ]\n" - " /Group <<\n" - " /Type /Group\n" - " /S /Transparency\n" - " /I true\n" - " /CS /DeviceRGB\n" - " >>\n" - " /Resources %d 0 R\n", - bbox->p1.x, - bbox->p1.y, - bbox->p2.x, - bbox->p2.y, - surface->content_resources.id); + _cairo_output_stream_printf (mem_stream, + " /Type /XObject\n" + " /Subtype /Form\n" + " /BBox [ %f %f %f %f ]\n" + " /Group <<\n" + " /Type /Group\n" + " /S /Transparency\n" + " /I true\n" + " /CS /DeviceRGB\n" + " >>\n" + " /Resources %d 0 R\n", + bbox->p1.x, + bbox->p1.y, + bbox->p2.x, + bbox->p2.y, + surface->content_resources.id); } else { - status = - _cairo_pdf_surface_open_stream (surface, - resource, - surface->compress_streams, - " /Type /XObject\n" - " /Subtype /Form\n" - " /BBox [ %f %f %f %f ]\n" - " /Resources %d 0 R\n", - bbox->p1.x, - bbox->p1.y, - bbox->p2.x, - bbox->p2.y, - surface->content_resources.id); + _cairo_output_stream_printf (mem_stream, + " /Type /XObject\n" + " /Subtype /Form\n" + " /BBox [ %f %f %f %f ]\n" + " /Resources %d 0 R\n", + bbox->p1.x, + bbox->p1.y, + bbox->p2.x, + bbox->p2.y, + surface->content_resources.id); } + if (struct_parents >= 0) { + _cairo_output_stream_printf (mem_stream, + " /StructParents %d\n", struct_parents); + } + + unsigned char *data; + unsigned long length; + status = _cairo_memory_stream_destroy (mem_stream, &data, &length); + if (unlikely (status)) + return status; + + char *str = _cairo_strndup ((const char*)data, length); /* Add NULL terminator */ + + status = + _cairo_pdf_surface_open_stream (surface, + resource, + surface->compress_streams, + "%s", + str); + free (str); + free (data); } else { status = _cairo_pdf_surface_open_stream (surface, @@ -2430,15 +2600,93 @@ _cairo_pdf_source_surface_entry_pluck (void *entry, void *closure) free (surface_entry); } +static void +_cairo_pdf_color_glyph_pluck (void *entry, void *closure) +{ + cairo_pdf_color_glyph_t *glyph_entry = entry; + cairo_hash_table_t *patterns = closure; + + _cairo_hash_table_remove (patterns, &glyph_entry->base); + cairo_scaled_font_destroy (glyph_entry->scaled_font); + + free (glyph_entry); +} + +static cairo_int_status_t +_cairo_pdf_surface_write_page_dicts (cairo_pdf_surface_t *surface) +{ + cairo_int_status_t status; + cairo_pdf_page_info_t *page_info; + int num_annots; + cairo_pdf_resource_t res; + + for (unsigned i = 0; i < _cairo_array_num_elements (&surface->pages); i++) { + page_info = _cairo_array_index (&surface->pages, i); + + status = _cairo_pdf_surface_object_begin (surface, page_info->page_res); + if (unlikely (status)) + return status; + + _cairo_output_stream_printf (surface->object_stream.stream, + "<< /Type /Page %% %d\n" + " /Parent %d 0 R\n" + " /MediaBox [ 0 0 %f %f ]\n" + " /Contents %d 0 R\n" + " /Group <<\n" + " /Type /Group\n" + " /S /Transparency\n" + " /I true\n" + " /CS /DeviceRGB\n" + " >>\n" + " /Resources %d 0 R\n", + i + 1, + surface->pages_resource.id, + page_info->width, + page_info->height, + page_info->content.id, + page_info->resources.id); + + if (page_info->struct_parents >= 0) { + _cairo_output_stream_printf (surface->object_stream.stream, + " /StructParents %d\n", + page_info->struct_parents); + } + + num_annots = _cairo_array_num_elements (&page_info->annots); + if (num_annots > 0) { + _cairo_output_stream_printf (surface->object_stream.stream, + " /Annots [ "); + for (int j = 0; j < num_annots; j++) { + _cairo_array_copy_element (&page_info->annots, j, &res); + _cairo_output_stream_printf (surface->object_stream.stream, + "%d 0 R ", + res.id); + } + _cairo_output_stream_printf (surface->object_stream.stream, "]\n"); + } + + if (page_info->thumbnail.id) { + _cairo_output_stream_printf (surface->object_stream.stream, + " /Thumb %d 0 R\n", + page_info->thumbnail.id); + } + + _cairo_output_stream_printf (surface->object_stream.stream, + ">>\n"); + _cairo_pdf_surface_object_end (surface); + } + + return status; +} + static cairo_status_t _cairo_pdf_surface_finish (void *abstract_surface) { cairo_pdf_surface_t *surface = abstract_surface; - long offset; + long long offset; cairo_pdf_resource_t catalog; cairo_status_t status = CAIRO_STATUS_SUCCESS, status2; int size, i; - cairo_pdf_source_surface_t doc_surface; cairo_pdf_jbig2_global_t *global; char *label; cairo_pdf_resource_t xref_res; @@ -2447,7 +2695,7 @@ _cairo_pdf_surface_finish (void *abstract_surface) if (surface->base.status != CAIRO_STATUS_SUCCESS) goto CLEANUP; - _cairo_pdf_surface_clear (surface); + _cairo_pdf_surface_clear (surface, FALSE); status = _cairo_pdf_surface_open_object_stream (surface); if (unlikely (status)) @@ -2456,10 +2704,17 @@ _cairo_pdf_surface_finish (void *abstract_surface) /* Emit unbounded surfaces */ _cairo_pdf_surface_write_patterns_and_smask_groups (surface, TRUE); + _cairo_pdf_surface_clear (surface, TRUE); + status = surface->base.status; if (status == CAIRO_STATUS_SUCCESS) status = _cairo_pdf_surface_emit_font_subsets (surface); + /* Emit any new patterns or surfaces created by the Type 3 font subset. */ + _cairo_pdf_surface_write_patterns_and_smask_groups (surface, TRUE); + + _cairo_pdf_surface_clear (surface, TRUE); + status = _cairo_pdf_surface_write_pages (surface); if (unlikely (status)) return status; @@ -2468,6 +2723,10 @@ _cairo_pdf_surface_finish (void *abstract_surface) if (unlikely (status)) return status; + status = _cairo_pdf_surface_write_page_dicts (surface); + if (unlikely (status)) + return status; + catalog = _cairo_pdf_surface_new_object (surface); if (catalog.id == 0) return _cairo_error (CAIRO_STATUS_NO_MEMORY); @@ -2480,7 +2739,7 @@ _cairo_pdf_surface_finish (void *abstract_surface) if (unlikely (status)) return status; - if (surface->pdf_version >= CAIRO_PDF_VERSION_1_5) + if (!surface->debug && surface->pdf_version >= CAIRO_PDF_VERSION_1_5) { xref_res = _cairo_pdf_surface_new_object (surface); status = _cairo_pdf_surface_write_xref_stream (surface, @@ -2502,7 +2761,7 @@ _cairo_pdf_surface_finish (void *abstract_surface) } _cairo_output_stream_printf (surface->output, "startxref\n" - "%ld\n" + "%lld\n" "%%%%EOF\n", offset); @@ -2543,6 +2802,11 @@ _cairo_pdf_surface_finish (void *abstract_surface) _cairo_pdf_group_resources_fini (&surface->resources); _cairo_array_fini (&surface->objects); + size = _cairo_array_num_elements (&surface->pages); + for (i = 0; i < size; i++) { + cairo_pdf_page_info_t *page_info = _cairo_array_index (&surface->pages, i); + _cairo_array_fini (&page_info->annots); + } _cairo_array_fini (&surface->pages); _cairo_array_fini (&surface->rgb_linear_functions); _cairo_array_fini (&surface->alpha_linear_functions); @@ -2550,11 +2814,6 @@ _cairo_pdf_surface_finish (void *abstract_surface) _cairo_array_fini (&surface->page_surfaces); _cairo_array_fini (&surface->object_stream.objects); - size = _cairo_array_num_elements (&surface->doc_surfaces); - for (i = 0; i < size; i++) { - _cairo_array_copy_element (&surface->doc_surfaces, i, &doc_surface); - cairo_surface_destroy (doc_surface.surface); - } _cairo_array_fini (&surface->doc_surfaces); _cairo_hash_table_foreach (surface->all_surfaces, _cairo_pdf_source_surface_entry_pluck, @@ -2566,6 +2825,11 @@ _cairo_pdf_surface_finish (void *abstract_surface) _cairo_array_fini (&surface->page_annots); _cairo_array_fini (&surface->forward_links); + _cairo_hash_table_foreach (surface->color_glyphs, + _cairo_pdf_color_glyph_pluck, + surface->color_glyphs); + _cairo_hash_table_destroy (surface->color_glyphs); + if (surface->font_subsets) { _cairo_scaled_font_subsets_destroy (surface->font_subsets); surface->font_subsets = NULL; @@ -2579,7 +2843,6 @@ _cairo_pdf_surface_finish (void *abstract_surface) return _cairo_error (CAIRO_STATUS_JBIG2_GLOBAL_MISSING); } _cairo_array_fini (&surface->jbig2_global); - _cairo_array_fini (&surface->page_heights); size = _cairo_array_num_elements (&surface->page_labels); for (i = 0; i < size; i++) { @@ -2599,7 +2862,7 @@ static cairo_int_status_t _cairo_pdf_surface_start_page (void *abstract_surface) { cairo_pdf_surface_t *surface = abstract_surface; - cairo_pdf_resource_t page; + cairo_pdf_page_info_t page_info; cairo_int_status_t status; /* Document header */ @@ -2610,10 +2873,16 @@ _cairo_pdf_surface_start_page (void *abstract_surface) case CAIRO_PDF_VERSION_1_4: version = "1.4"; break; - default: case CAIRO_PDF_VERSION_1_5: version = "1.5"; break; + case CAIRO_PDF_VERSION_1_6: + version = "1.6"; + break; + default: + case CAIRO_PDF_VERSION_1_7: + version = "1.7"; + break; } _cairo_output_stream_printf (surface->output, @@ -2626,11 +2895,19 @@ _cairo_pdf_surface_start_page (void *abstract_surface) _cairo_pdf_group_resources_clear (&surface->resources); surface->in_xobject = FALSE; - page = _cairo_pdf_surface_new_object (surface); - if (page.id == 0) + page_info.page_res = _cairo_pdf_surface_new_object (surface); + if (page_info.page_res.id == 0) return _cairo_error (CAIRO_STATUS_NO_MEMORY); - status = _cairo_array_append (&surface->pages, &page); + page_info.width = surface->width; + page_info.height = surface->height; + page_info.content.id = 0; + page_info.resources.id = 0; + page_info.thumbnail.id = 0; + page_info.struct_parents = -1; + _cairo_array_init (&page_info.annots, sizeof (cairo_pdf_resource_t)); + + status = _cairo_array_append (&surface->pages, &page_info); if (unlikely (status)) return status; @@ -2645,13 +2922,17 @@ _cairo_pdf_surface_has_fallback_images (void *abstract_surface, cairo_pdf_surface_t *surface = abstract_surface; cairo_box_double_t bbox; + status = _cairo_pdf_interchange_end_page_content (surface); + if (unlikely (status)) + return status; + surface->has_fallback_images = has_fallbacks; surface->in_xobject = has_fallbacks; bbox.p1.x = 0; bbox.p1.y = 0; bbox.p2.x = surface->width; bbox.p2.y = surface->height; - status = _cairo_pdf_surface_open_content_stream (surface, &bbox, NULL, has_fallbacks, has_fallbacks); + status = _cairo_pdf_surface_open_content_stream (surface, &bbox, NULL, has_fallbacks, has_fallbacks, -1); if (unlikely (status)) return status; @@ -2751,6 +3032,7 @@ _cairo_pdf_surface_add_padded_image_surface (cairo_pdf_surface_t *surfa status = _cairo_pdf_surface_add_source_surface (surface, pad_image, NULL, + -1 , /* node_surface_index */ CAIRO_OPERATOR_OVER, /* not used for images */ source->filter, FALSE, /* stencil mask */ @@ -3489,9 +3771,10 @@ _cairo_pdf_surface_emit_ccitt_image (cairo_pdf_surface_t *surface, return CAIRO_INT_STATUS_UNSUPPORTED; /* ensure params_string is null terminated */ - params = malloc (ccitt_params_string_len + 1); - memcpy (params, ccitt_params_string, ccitt_params_string_len); - params[ccitt_params_string_len] = 0; + params = _cairo_strndup ((const char *)ccitt_params_string, ccitt_params_string_len); + if (unlikely (params == NULL)) + return _cairo_surface_set_error (&surface->base, CAIRO_STATUS_NO_MEMORY); + status = _cairo_tag_parse_ccitt_params (params, &ccitt_params); if (unlikely(status)) return source->status; @@ -3589,6 +3872,7 @@ _cairo_pdf_surface_emit_recording_surface (cairo_pdf_surface_t *surface, cairo_bool_t is_subsurface; cairo_bool_t transparency_group; cairo_recording_surface_t *recording; + int struct_parents = -1; assert (pdf_source->type == CAIRO_PATTERN_TYPE_SURFACE); @@ -3647,16 +3931,25 @@ _cairo_pdf_surface_emit_recording_surface (cairo_pdf_surface_t *surface, _cairo_recording_surface_has_only_bilevel_alpha (recording) && _cairo_recording_surface_has_only_op_over (recording)); + status = _cairo_pdf_interchange_emit_recording_surface_begin (surface, + pdf_source->surface, + pdf_source->hash_entry->region_id, + pdf_source->hash_entry->surface_res, + &struct_parents); + if (unlikely (status)) + goto err; + status = _cairo_pdf_surface_open_content_stream (surface, &bbox, &pdf_source->hash_entry->surface_res, TRUE, - transparency_group); + transparency_group, + struct_parents); if (unlikely (status)) goto err; /* Reset gstate */ - _cairo_output_stream_printf (surface->output, "/gs0 gs\n"); + surface->reset_gs_required = TRUE; if (source->content == CAIRO_CONTENT_COLOR) { status = _cairo_pdf_surface_add_alpha (surface, 1.0, &alpha); @@ -3673,6 +3966,7 @@ _cairo_pdf_surface_emit_recording_surface (cairo_pdf_surface_t *surface, } status = _cairo_recording_surface_replay_region (source, + pdf_source->region_id, is_subsurface ? extents : NULL, &surface->base, CAIRO_RECORDING_REGION_NATIVE); @@ -3689,6 +3983,10 @@ _cairo_pdf_surface_emit_recording_surface (cairo_pdf_surface_t *surface, surface->paginated_mode = old_paginated_mode; surface->surface_extents = old_surface_extents; surface->surface_bounded = old_surface_bounded; + surface->reset_gs_required = FALSE; + + if (pdf_source->hash_entry->region_id > 0) + status = _cairo_pdf_interchange_emit_recording_surface_end (surface, pdf_source->surface); err: cairo_surface_destroy (free_me); @@ -3830,6 +4128,7 @@ _cairo_pdf_surface_emit_surface_pattern (cairo_pdf_surface_t *surface, status = _cairo_pdf_surface_add_source_surface (surface, NULL, pattern, + pdf_pattern->region_id, pdf_pattern->operator, pattern->filter, FALSE, /* stencil mask */ @@ -4974,6 +5273,7 @@ static cairo_int_status_t _cairo_pdf_surface_paint_surface_pattern (cairo_pdf_surface_t *surface, cairo_operator_t op, const cairo_pattern_t *source, + cairo_analysis_source_t source_type, const cairo_rectangle_int_t *extents, double alpha, cairo_pdf_resource_t *smask_res, @@ -4985,6 +5285,7 @@ _cairo_pdf_surface_paint_surface_pattern (cairo_pdf_surface_t *surface, double x_offset; double y_offset; cairo_pdf_source_surface_entry_t *pdf_source; + int region_id = 0; if (source->extend == CAIRO_EXTEND_PAD && !(source->type == CAIRO_PATTERN_TYPE_SURFACE && @@ -4998,9 +5299,19 @@ _cairo_pdf_surface_paint_surface_pattern (cairo_pdf_surface_t *surface, &y_offset, NULL); } else { + if (source->type == CAIRO_PATTERN_TYPE_SURFACE) { + cairo_surface_pattern_t *surface_pattern = (cairo_surface_pattern_t *) source; + if (_cairo_pdf_interchange_struct_tree_requires_recording_surface (surface, + surface_pattern, + source_type)) + { + region_id = surface_pattern->region_array_id; + } + } status = _cairo_pdf_surface_add_source_surface (surface, NULL, source, + region_id, op, source->filter, stencil_mask, @@ -5008,6 +5319,7 @@ _cairo_pdf_surface_paint_surface_pattern (cairo_pdf_surface_t *surface, alpha != 1.0, /* need_transp_group */ extents, smask_res, + &pdf_source, &x_offset, &y_offset, @@ -5134,6 +5446,7 @@ static cairo_int_status_t _cairo_pdf_surface_paint_pattern (cairo_pdf_surface_t *surface, cairo_operator_t op, const cairo_pattern_t *source, + cairo_analysis_source_t source_type, const cairo_rectangle_int_t *extents, double alpha, cairo_bool_t mask) @@ -5144,6 +5457,7 @@ _cairo_pdf_surface_paint_pattern (cairo_pdf_surface_t *surface, return _cairo_pdf_surface_paint_surface_pattern (surface, op, source, + source_type, extents, alpha, NULL, @@ -5195,6 +5509,11 @@ _cairo_pdf_surface_select_operator (cairo_pdf_surface_t *surface, { cairo_int_status_t status; + if (surface->reset_gs_required) { + _cairo_output_stream_printf (surface->output, "/gs0 gs\n"); + surface->reset_gs_required = FALSE; + } + if (op == surface->current_operator) return CAIRO_STATUS_SUCCESS; @@ -5334,10 +5653,6 @@ _cairo_pdf_surface_show_page (void *abstract_surface) cairo_pdf_surface_t *surface = abstract_surface; cairo_int_status_t status; - status = _cairo_array_append (&surface->page_heights, &surface->height); - if (unlikely (status)) - return status; - status = _cairo_array_append (&surface->page_labels, &surface->current_page_label); if (unlikely (status)) return status; @@ -5358,7 +5673,7 @@ _cairo_pdf_surface_show_page (void *abstract_surface) if (unlikely (status)) return status; - _cairo_pdf_surface_clear (surface); + _cairo_pdf_surface_clear (surface, FALSE); return CAIRO_STATUS_SUCCESS; } @@ -5390,7 +5705,7 @@ _cairo_pdf_surface_get_font_options (void *abstract_surface, static cairo_int_status_t _cairo_pdf_surface_write_pages (cairo_pdf_surface_t *surface) { - cairo_pdf_resource_t page; + cairo_pdf_page_info_t *page_info; int num_pages, i; cairo_int_status_t status; @@ -5404,8 +5719,8 @@ _cairo_pdf_surface_write_pages (cairo_pdf_surface_t *surface) num_pages = _cairo_array_num_elements (&surface->pages); for (i = 0; i < num_pages; i++) { - _cairo_array_copy_element (&surface->pages, i, &page); - _cairo_output_stream_printf (surface->object_stream.stream, "%d 0 R ", page.id); + page_info = _cairo_array_index (&surface->pages, i); + _cairo_output_stream_printf (surface->object_stream.stream, "%d 0 R ", page_info->page_res.id); } _cairo_output_stream_printf (surface->object_stream.stream, "]\n"); @@ -6408,42 +6723,205 @@ _cairo_pdf_emit_imagemask (cairo_image_surface_t *image, } static cairo_int_status_t -_cairo_pdf_surface_analyze_user_font_subset (cairo_scaled_font_subset_t *font_subset, - void *closure) -{ - cairo_pdf_surface_t *surface = closure; - cairo_int_status_t status = CAIRO_INT_STATUS_SUCCESS; - cairo_int_status_t status2; - unsigned int i; - cairo_surface_t *type3_surface; - cairo_output_stream_t *null_stream; +cairo_pdf_surface_emit_color_glyph (cairo_pdf_surface_t *surface, + cairo_scaled_font_t *scaled_font, + unsigned long glyph_index, + cairo_box_t *bbox, + double *width) +{ + cairo_rectangle_int_t extents; + cairo_scaled_glyph_t *scaled_glyph; + cairo_matrix_t mat; + cairo_int_status_t status; + double x_advance, y_advance; + cairo_matrix_t font_matrix_inverse; + cairo_surface_t *analysis; + cairo_rectangle_int_t old_surface_extents; + cairo_bool_t old_surface_bounded; + cairo_paginated_mode_t old_paginated_mode; + cairo_surface_t *glyph_surface = NULL; + unsigned int regions_id = 0; + cairo_surface_pattern_t surface_pattern; + + _cairo_scaled_font_freeze_cache (scaled_font); + status = _cairo_scaled_glyph_lookup (scaled_font, + glyph_index, + CAIRO_SCALED_GLYPH_INFO_RECORDING_SURFACE, + NULL, /* foreground color */ + &scaled_glyph); + if (status == CAIRO_INT_STATUS_SUCCESS) + glyph_surface = cairo_surface_reference (scaled_glyph->recording_surface); - null_stream = _cairo_null_stream_create (); - type3_surface = _cairo_type3_glyph_surface_create (font_subset->scaled_font, - null_stream, - _cairo_pdf_emit_imagemask, - surface->font_subsets, - FALSE); - if (unlikely (type3_surface->status)) { - status2 = _cairo_output_stream_destroy (null_stream); - return type3_surface->status; + _cairo_scaled_font_thaw_cache (scaled_font); + if (unlikely (status)) + return status; + + analysis = _cairo_analysis_surface_create (&surface->base, TRUE); + if (unlikely (analysis->status)) { + status = _cairo_surface_set_error (&surface->base, analysis->status); + goto cleanup; } - _cairo_type3_glyph_surface_set_font_subsets_callback (type3_surface, - _cairo_pdf_surface_add_font, - surface); + extents.x = _cairo_fixed_to_double (scaled_glyph->bbox.p1.x); + extents.y = _cairo_fixed_to_double (scaled_glyph->bbox.p1.y); + extents.width = _cairo_fixed_to_double (scaled_glyph->bbox.p2.x) - extents.x; + extents.height = _cairo_fixed_to_double (scaled_glyph->bbox.p2.y) - extents.y; - for (i = 0; i < font_subset->num_glyphs; i++) { - status = _cairo_type3_glyph_surface_analyze_glyph (type3_surface, - font_subset->glyphs[i]); - if (unlikely (status)) - break; + old_surface_extents = surface->surface_extents; + old_surface_bounded = surface->surface_bounded; + old_paginated_mode = surface->paginated_mode; + surface->paginated_mode = CAIRO_PAGINATED_MODE_ANALYZE; + surface->type3_replay = TRUE; + surface->surface_extents = extents; + surface->surface_bounded = TRUE; + + status = _cairo_recording_surface_region_array_attach (glyph_surface, ®ions_id); + if (status) + goto cleanup; + + status = _cairo_recording_surface_replay_and_create_regions (glyph_surface, regions_id, + NULL, analysis, TRUE, FALSE); + if (status) + goto cleanup; + + surface->surface_extents = old_surface_extents; + surface->surface_bounded = old_surface_bounded; + surface->paginated_mode = old_paginated_mode; + surface->type3_replay = FALSE; + + if (status == CAIRO_INT_STATUS_SUCCESS && + _cairo_analysis_surface_has_unsupported (analysis)) + { + status = CAIRO_INT_STATUS_UNSUPPORTED; } - cairo_surface_destroy (type3_surface); - status2 = _cairo_output_stream_destroy (null_stream); - if (status == CAIRO_INT_STATUS_SUCCESS) - status = status2; + cairo_surface_destroy (analysis); + if (status) + goto cleanup; + + _cairo_pattern_init_for_surface (&surface_pattern, glyph_surface); + surface_pattern.region_array_id = regions_id; + + cairo_matrix_init_identity (&mat); + cairo_matrix_multiply (&mat, &mat, &scaled_font->scale_inverse); + + /* transform glyph extents to operation space */ + cairo_box_t box; + _cairo_box_from_rectangle (&box, &extents); + _cairo_matrix_transform_bounding_box_fixed (&mat, &box, NULL); + _cairo_box_round_to_rectangle (&box, &extents); + + status = cairo_matrix_invert (&mat); + if (status) { + status = CAIRO_INT_STATUS_UNSUPPORTED; + goto cleanup; + } + + cairo_pattern_set_matrix (&surface_pattern.base, &mat); + + x_advance = scaled_glyph->metrics.x_advance; + y_advance = scaled_glyph->metrics.y_advance; + font_matrix_inverse = scaled_font->font_matrix; + status = cairo_matrix_invert (&font_matrix_inverse); + if (status) { + status = CAIRO_INT_STATUS_UNSUPPORTED; + goto cleanup; + } + + cairo_matrix_transform_distance (&font_matrix_inverse, &x_advance, &y_advance); + *width = x_advance; + + *bbox = scaled_glyph->bbox; + _cairo_matrix_transform_bounding_box_fixed (&scaled_font->scale_inverse, + bbox, NULL); + + _cairo_output_stream_printf (surface->output, + "%f 0 d0\n", + x_advance); + + _cairo_pdf_surface_paint_surface_pattern (surface, + CAIRO_OPERATOR_OVER, + &surface_pattern.base, + CAIRO_ANALYSIS_SOURCE_NONE, + &extents, + 1.0, /* alpha */ + NULL, /* smask_res */ + FALSE); /* mask */ + + cleanup: + cairo_surface_destroy (glyph_surface); + + return status; +} + +static cairo_int_status_t +cairo_pdf_surface_emit_color_glyph_image (cairo_pdf_surface_t *surface, + cairo_scaled_font_t *scaled_font, + unsigned long glyph_index, + cairo_box_t *bbox, + double *width) +{ + cairo_rectangle_int_t extents; + cairo_pattern_t *image_pattern; + cairo_scaled_glyph_t *scaled_glyph; + cairo_matrix_t mat; + cairo_int_status_t status, status2; + double x_advance, y_advance; + cairo_matrix_t font_matrix_inverse; + + _cairo_scaled_font_freeze_cache (scaled_font); + status = _cairo_scaled_glyph_lookup (scaled_font, + glyph_index, + CAIRO_SCALED_GLYPH_INFO_COLOR_SURFACE, + NULL, /* foreground color */ + &scaled_glyph); + if (unlikely (status)) + goto FAIL; + + extents.x = _cairo_fixed_to_double (scaled_glyph->bbox.p1.x); + extents.y = _cairo_fixed_to_double (scaled_glyph->bbox.p1.y); + extents.width = _cairo_fixed_to_double (scaled_glyph->bbox.p2.x) - extents.x; + extents.height = _cairo_fixed_to_double (scaled_glyph->bbox.p2.y) - extents.y; + + image_pattern = cairo_pattern_create_for_surface (&scaled_glyph->color_surface->base); + + cairo_matrix_init_translate (&mat, extents.x, extents.y); + cairo_matrix_multiply (&mat, &mat, &scaled_font->scale_inverse); + status2 = cairo_matrix_invert (&mat); + cairo_pattern_set_matrix (image_pattern, &mat); + + x_advance = scaled_glyph->metrics.x_advance; + y_advance = scaled_glyph->metrics.y_advance; + font_matrix_inverse = scaled_font->font_matrix; + status2 = cairo_matrix_invert (&font_matrix_inverse); + + /* The invertability of font_matrix is tested in + * pdf_operators_show_glyphs before any glyphs are mapped to the + * subset. */ + assert (status2 == CAIRO_INT_STATUS_SUCCESS); + + cairo_matrix_transform_distance (&font_matrix_inverse, &x_advance, &y_advance); + *width = x_advance; + + *bbox = scaled_glyph->bbox; + _cairo_matrix_transform_bounding_box_fixed (&scaled_font->scale_inverse, + bbox, NULL); + + _cairo_output_stream_printf (surface->output, + "%f 0 d0\n", + x_advance); + + _cairo_pdf_surface_paint_surface_pattern (surface, + CAIRO_OPERATOR_OVER, + image_pattern, + CAIRO_ANALYSIS_SOURCE_NONE, + &extents, + 1.0, /* alpha */ + NULL, /* smask_res */ + FALSE); /* mask */ + cairo_pattern_destroy (image_pattern); + FAIL: + _cairo_scaled_font_thaw_cache (scaled_font); return status; } @@ -6510,6 +6988,20 @@ _cairo_pdf_surface_emit_type3_font_subset (cairo_pdf_surface_t *surface, font_subset->glyphs[i], &bbox, &widths[i]); + if (status == CAIRO_INT_STATUS_UNSUPPORTED) { + status = cairo_pdf_surface_emit_color_glyph (surface, + font_subset->scaled_font, + font_subset->glyphs[i], + &bbox, + &widths[i]); + if (status == CAIRO_INT_STATUS_UNSUPPORTED) { + status = cairo_pdf_surface_emit_color_glyph_image (surface, + font_subset->scaled_font, + font_subset->glyphs[i], + &bbox, + &widths[i]); + } + } if (unlikely (status)) break; @@ -6685,12 +7177,6 @@ _cairo_pdf_surface_emit_font_subsets (cairo_pdf_surface_t *surface) { cairo_int_status_t status; - status = _cairo_scaled_font_subsets_foreach_user (surface->font_subsets, - _cairo_pdf_surface_analyze_user_font_subset, - surface); - if (unlikely (status)) - goto BAIL; - status = _cairo_scaled_font_subsets_foreach_unscaled (surface->font_subsets, _cairo_pdf_surface_emit_unscaled_font_subset, surface); @@ -6700,12 +7186,6 @@ _cairo_pdf_surface_emit_font_subsets (cairo_pdf_surface_t *surface) status = _cairo_scaled_font_subsets_foreach_scaled (surface->font_subsets, _cairo_pdf_surface_emit_scaled_font_subset, surface); - if (unlikely (status)) - goto BAIL; - - status = _cairo_scaled_font_subsets_foreach_user (surface->font_subsets, - _cairo_pdf_surface_emit_scaled_font_subset, - surface); BAIL: _cairo_scaled_font_subsets_destroy (surface->font_subsets); @@ -6764,13 +7244,12 @@ _cairo_pdf_surface_write_catalog (cairo_pdf_surface_t *surface, return status; } -static long +static long long _cairo_pdf_surface_write_xref (cairo_pdf_surface_t *surface) { cairo_pdf_object_t *object; int num_objects, i; - long offset; - char buffer[11]; + long long offset; num_objects = _cairo_array_num_elements (&surface->objects); @@ -6784,9 +7263,8 @@ _cairo_pdf_surface_write_xref (cairo_pdf_surface_t *surface) "0000000000 65535 f \n"); for (i = 0; i < num_objects; i++) { object = _cairo_array_index (&surface->objects, i); - snprintf (buffer, sizeof buffer, "%010ld", object->u.offset); _cairo_output_stream_printf (surface->output, - "%s 00000 n \n", buffer); + "%010lld 00000 n \n", object->u.offset); } return offset; @@ -6797,7 +7275,7 @@ _cairo_write_xref_stream_entry (cairo_output_stream_t *stream, int id, int type, int field2_size, - long field2, + long long field2, int field3, cairo_bool_t write_as_comments) { @@ -6805,7 +7283,7 @@ _cairo_write_xref_stream_entry (cairo_output_stream_t *stream, int i; if (write_as_comments) { - _cairo_output_stream_printf (stream, "%% %5d %2d %10ld %d\n", id, type, field2, field3); + _cairo_output_stream_printf (stream, "%% %5d %2d %10lld %d\n", id, type, field2, field3); } else { /* Each field is big endian */ buf[0] = type; /* field 1 */ @@ -6820,10 +7298,10 @@ _cairo_write_xref_stream_entry (cairo_output_stream_t *stream, } static void -_cairo_write_xref_stream_entrys (cairo_pdf_surface_t *surface, - cairo_output_stream_t *stream, - int field2_size, - cairo_bool_t write_as_comments) +_cairo_write_xref_stream_entries (cairo_pdf_surface_t *surface, + cairo_output_stream_t *stream, + int field2_size, + cairo_bool_t write_as_comments) { cairo_pdf_object_t *object; int num_objects, i; @@ -6873,11 +7351,11 @@ _cairo_pdf_surface_write_xref_stream (cairo_pdf_surface_t *surface, cairo_pdf_resource_t xref_res, cairo_pdf_resource_t root_res, cairo_pdf_resource_t info_res, - long *xref_offset) + long long *xref_offset) { cairo_output_stream_t *mem_stream; cairo_output_stream_t *xref_stream; - long offset; + long long offset; int offset_bytes; cairo_status_t status; @@ -6893,7 +7371,7 @@ _cairo_pdf_surface_write_xref_stream (cairo_pdf_surface_t *surface, mem_stream = _cairo_memory_stream_create (); xref_stream = _cairo_deflate_stream_create (mem_stream); - _cairo_write_xref_stream_entrys (surface, xref_stream, offset_bytes, FALSE); + _cairo_write_xref_stream_entries (surface, xref_stream, offset_bytes, FALSE); status = _cairo_output_stream_destroy (xref_stream); if (unlikely (status)) @@ -6926,7 +7404,7 @@ _cairo_pdf_surface_write_xref_stream (cairo_pdf_surface_t *surface, */ _cairo_output_stream_printf (surface->output, "%% id type offset/obj gen/index\n"); - _cairo_write_xref_stream_entrys (surface, surface->output, offset_bytes, TRUE); + _cairo_write_xref_stream_entries (surface, surface->output, offset_bytes, TRUE); } _cairo_output_stream_printf (surface->output, @@ -6966,6 +7444,7 @@ _cairo_pdf_surface_write_mask_group (cairo_pdf_surface_t *surface, status = _cairo_pdf_surface_paint_pattern (surface, CAIRO_OPERATOR_OVER, group->mask, + CAIRO_ANALYSIS_MASK_MASK, &group->extents, 1.0, /* alpha */ FALSE); /* mask */ @@ -6978,6 +7457,7 @@ _cairo_pdf_surface_write_mask_group (cairo_pdf_surface_t *surface, gstate_res.id = 0; status = _cairo_pdf_surface_add_pdf_pattern (surface, group->mask, CAIRO_OPERATOR_OVER, + CAIRO_ANALYSIS_MASK_MASK, NULL, &pattern_res, &gstate_res); if (unlikely (status)) @@ -7043,6 +7523,7 @@ _cairo_pdf_surface_write_mask_group (cairo_pdf_surface_t *surface, status = _cairo_pdf_surface_paint_pattern (surface, CAIRO_OPERATOR_OVER, group->source, + CAIRO_ANALYSIS_MASK_MASK, &group->extents, 1.0, /* alpha */ FALSE); /* mask */ @@ -7055,6 +7536,7 @@ _cairo_pdf_surface_write_mask_group (cairo_pdf_surface_t *surface, gstate_res.id = 0; status = _cairo_pdf_surface_add_pdf_pattern (surface, group->source, CAIRO_OPERATOR_OVER, + CAIRO_ANALYSIS_MASK_MASK, NULL, &pattern_res, &gstate_res); if (unlikely (status)) @@ -7292,10 +7774,12 @@ _cairo_pdf_surface_write_patterns_and_smask_groups (cairo_pdf_surface_t *surface static cairo_int_status_t _cairo_pdf_surface_write_page (cairo_pdf_surface_t *surface) { - cairo_pdf_resource_t knockout, res, thumbnail_res; - cairo_pdf_resource_t *page; + cairo_pdf_resource_t knockout, res; cairo_int_status_t status; - unsigned int i, len, page_num, num_annots; + unsigned int i, len; + cairo_pdf_page_info_t *page_info; + + page_info = _cairo_array_last_element (&surface->pages); status = _cairo_pdf_surface_open_object_stream (surface); if (unlikely (status)) @@ -7341,7 +7825,7 @@ _cairo_pdf_surface_write_page (cairo_pdf_surface_t *surface) return status; _cairo_pdf_group_resources_clear (&surface->resources); - status = _cairo_pdf_surface_open_content_stream (surface, NULL, NULL, FALSE, FALSE); + status = _cairo_pdf_surface_open_content_stream (surface, NULL, NULL, FALSE, FALSE, -1); if (unlikely (status)) return status; @@ -7357,70 +7841,18 @@ _cairo_pdf_surface_write_page (cairo_pdf_surface_t *surface) return status; } - thumbnail_res.id = 0; if (surface->thumbnail_image) { cairo_pdf_source_surface_entry_t entry; memset (&entry, 0, sizeof (entry)); - thumbnail_res = _cairo_pdf_surface_new_object (surface); - entry.surface_res = thumbnail_res; + page_info->thumbnail = _cairo_pdf_surface_new_object (surface); + entry.surface_res = page_info->thumbnail; _cairo_pdf_surface_emit_image (surface, surface->thumbnail_image, &entry); } - page_num = _cairo_array_num_elements (&surface->pages); - page = _cairo_array_index (&surface->pages, page_num - 1); - - status = _cairo_pdf_surface_object_begin (surface, *page); - if (unlikely (status)) - return status; - - _cairo_output_stream_printf (surface->object_stream.stream, - "<< /Type /Page %% %d\n" - " /Parent %d 0 R\n" - " /MediaBox [ 0 0 %f %f ]\n" - " /Contents %d 0 R\n" - " /Group <<\n" - " /Type /Group\n" - " /S /Transparency\n" - " /I true\n" - " /CS /DeviceRGB\n" - " >>\n" - " /Resources %d 0 R\n", - page_num, - surface->pages_resource.id, - surface->width, - surface->height, - surface->content.id, - surface->content_resources.id); - - if (surface->page_parent_tree >= 0) { - _cairo_output_stream_printf (surface->object_stream.stream, - " /StructParents %d\n", - surface->page_parent_tree); - } - - num_annots = _cairo_array_num_elements (&surface->page_annots); - if (num_annots > 0) { - _cairo_output_stream_printf (surface->object_stream.stream, - " /Annots [ "); - for (i = 0; i < num_annots; i++) { - _cairo_array_copy_element (&surface->page_annots, i, &res); - _cairo_output_stream_printf (surface->object_stream.stream, - "%d 0 R ", - res.id); - } - _cairo_output_stream_printf (surface->object_stream.stream, "]\n"); - } - - if (thumbnail_res.id) { - _cairo_output_stream_printf (surface->object_stream.stream, - " /Thumb %d 0 R\n", - thumbnail_res.id); - } - - _cairo_output_stream_printf (surface->object_stream.stream, - ">>\n"); - _cairo_pdf_surface_object_end (surface); + page_info->content = surface->content; + page_info->resources = surface->content_resources; + page_info->struct_parents = surface->page_parent_tree; status = _cairo_pdf_surface_write_patterns_and_smask_groups (surface, FALSE); if (unlikely (status)) @@ -7604,6 +8036,9 @@ _cairo_pdf_surface_analyze_operation (cairo_pdf_surface_t *surface, /* The SOURCE operator is supported if the pattern is opaque or if * there is nothing painted underneath. */ if (op == CAIRO_OPERATOR_SOURCE) { + if (surface->type3_replay) + return CAIRO_INT_STATUS_UNSUPPORTED; + if (pattern->type == CAIRO_PATTERN_TYPE_SURFACE) { cairo_surface_pattern_t *surface_pattern = (cairo_surface_pattern_t *) pattern; @@ -7664,7 +8099,7 @@ _cairo_pdf_surface_start_fallback (cairo_pdf_surface_t *surface) bbox.p1.y = 0; bbox.p2.x = surface->width; bbox.p2.y = surface->height; - status = _cairo_pdf_surface_open_content_stream (surface, &bbox, NULL, TRUE, TRUE); + status = _cairo_pdf_surface_open_content_stream (surface, &bbox, NULL, TRUE, TRUE, -1); if (unlikely (status)) return status; @@ -7811,6 +8246,7 @@ _cairo_pdf_surface_emit_combined_smask (cairo_pdf_surface_t *surface, status = _cairo_pdf_surface_add_source_surface (surface, NULL, mask, + -1, /* node_surface_index */ op, source->filter, FALSE, /* stencil mask */ @@ -7831,7 +8267,9 @@ _cairo_pdf_surface_emit_combined_smask (cairo_pdf_surface_t *surface, return status; _cairo_output_stream_printf (surface->output, "q\n"); - status = _cairo_pdf_surface_paint_surface_pattern (surface, op, source, extents, + status = _cairo_pdf_surface_paint_surface_pattern (surface, op, source, + CAIRO_ANALYSIS_SOURCE_NONE, + extents, 1.0, /* alpha */ need_smask ? &pdf_source->surface_res : NULL, FALSE); @@ -7896,7 +8334,9 @@ _cairo_pdf_surface_emit_stencil_mask (cairo_pdf_surface_t *surface, return status; _cairo_output_stream_printf (surface->output, "q\n"); - status = _cairo_pdf_surface_paint_surface_pattern (surface, op, mask, extents, 1.0, NULL, TRUE); + status = _cairo_pdf_surface_paint_surface_pattern (surface, op, mask, + CAIRO_ANALYSIS_SOURCE_NONE, + extents, 1.0, NULL, TRUE); if (unlikely (status)) return status; @@ -7978,6 +8418,7 @@ _cairo_pdf_surface_paint (void *abstract_surface, status = _cairo_pdf_surface_paint_pattern (surface, op, source, + CAIRO_ANALYSIS_SOURCE_PAINT, &extents.bounded, 1.0, /* alpha */ FALSE); /* mask */ @@ -7992,6 +8433,7 @@ _cairo_pdf_surface_paint (void *abstract_surface, pattern_res.id = 0; gstate_res.id = 0; status = _cairo_pdf_surface_add_pdf_pattern (surface, source, op, + CAIRO_ANALYSIS_SOURCE_PAINT, &extents.bounded, &pattern_res, &gstate_res); if (unlikely (status)) @@ -8163,6 +8605,7 @@ _cairo_pdf_surface_mask (void *abstract_surface, status = _cairo_pdf_surface_paint_pattern (surface, op, source, + CAIRO_ANALYSIS_SOURCE_MASK, &extents.bounded, alpha, FALSE); /* mask */ @@ -8292,6 +8735,7 @@ _cairo_pdf_surface_stroke (void *abstract_surface, pattern_res.id = 0; gstate_res.id = 0; status = _cairo_pdf_surface_add_pdf_pattern (surface, source, op, + CAIRO_ANALYSIS_SOURCE_STROKE, &extents.bounded, &pattern_res, &gstate_res); if (unlikely (status)) @@ -8450,6 +8894,7 @@ _cairo_pdf_surface_fill (void *abstract_surface, status = _cairo_pdf_surface_paint_pattern (surface, op, source, + CAIRO_ANALYSIS_SOURCE_FILL, &extents.bounded, 1.0, /* alpha */ FALSE); /* mask */ @@ -8464,6 +8909,7 @@ _cairo_pdf_surface_fill (void *abstract_surface, pattern_res.id = 0; gstate_res.id = 0; status = _cairo_pdf_surface_add_pdf_pattern (surface, source, op, + CAIRO_ANALYSIS_SOURCE_FILL, &extents.bounded, &pattern_res, &gstate_res); if (unlikely (status)) @@ -8643,6 +9089,7 @@ _cairo_pdf_surface_fill_stroke (void *abstract_surface, gstate_res.id = 0; status = _cairo_pdf_surface_add_pdf_pattern (surface, fill_source, fill_op, + CAIRO_ANALYSIS_SOURCE_FILL, &extents.bounded, &fill_pattern_res, &gstate_res); @@ -8656,6 +9103,7 @@ _cairo_pdf_surface_fill_stroke (void *abstract_surface, status = _cairo_pdf_surface_add_pdf_pattern (surface, stroke_source, stroke_op, + CAIRO_ANALYSIS_SOURCE_STROKE, &extents.bounded, &stroke_pattern_res, &gstate_res); @@ -8734,11 +9182,22 @@ _cairo_pdf_surface_show_text_glyphs (void *abstract_surface, if (unlikely (status)) return status; + status = _cairo_pdf_interchange_add_content (surface); + if (unlikely (status)) + return status; + status = _cairo_pdf_interchange_add_operation_extents (surface, &extents.bounded); if (unlikely (status)) return status; if (surface->paginated_mode == CAIRO_PAGINATED_MODE_ANALYZE) { + /* Enabling text in Type 3 fonts currently crashes cairo. Most + * PDF viewers don't seem to suport text in Type 3 so we let + * this go to image fallback. + */ + if (surface->type3_replay) + return CAIRO_INT_STATUS_UNSUPPORTED; + status = _cairo_pdf_surface_analyze_operation (surface, op, source, &extents.bounded); goto cleanup; } @@ -8752,6 +9211,7 @@ _cairo_pdf_surface_show_text_glyphs (void *abstract_surface, pattern_res.id = 0; gstate_res.id = 0; status = _cairo_pdf_surface_add_pdf_pattern (surface, source, op, + CAIRO_ANALYSIS_SOURCE_SHOW_GLYPHS, &extents.bounded, &pattern_res, &gstate_res); if (unlikely (status)) @@ -8880,9 +9340,10 @@ _cairo_pdf_surface_tag (void *abstract_surface, cairo_bool_t begin, const char *tag_name, const char *attributes) + { cairo_pdf_surface_t *surface = abstract_surface; - cairo_int_status_t status = 0; + cairo_int_status_t status = CAIRO_INT_STATUS_SUCCESS; if (begin) status = _cairo_pdf_interchange_tag_begin (surface, tag_name, attributes); @@ -8893,6 +9354,105 @@ _cairo_pdf_surface_tag (void *abstract_surface, } static cairo_int_status_t +_cairo_pdf_surface_command_id (void *abstract_surface, + unsigned int recording_id, + unsigned int command_id) +{ + cairo_pdf_surface_t *surface = abstract_surface; + + return _cairo_pdf_interchange_command_id (surface, recording_id, command_id); +} + +/* The Type 3 font subset support will the embed the + * CAIRO_SCALED_GLYPH_INFO_COLOR_SURFACE image if vector operations + * are not supported. The only case we don't currently handle is if a + * foreground color is used. + */ +static cairo_bool_t +_cairo_pdf_surface_supports_color_glyph (void *abstract_surface, + cairo_scaled_font_t *scaled_font, + unsigned long glyph_index) +{ + cairo_pdf_surface_t *surface = abstract_surface; + cairo_pdf_color_glyph_t glyph_key; + cairo_pdf_color_glyph_t *glyph_entry; + cairo_scaled_glyph_t *scaled_glyph; + cairo_status_t status; + + glyph_key.scaled_font = scaled_font; + glyph_key.glyph_index = glyph_index; + + _cairo_pdf_color_glyph_init_key (&glyph_key); + glyph_entry = _cairo_hash_table_lookup (surface->color_glyphs, &glyph_key.base); + if (glyph_entry) + return glyph_entry->supported; + + glyph_entry = _cairo_malloc (sizeof (cairo_pdf_color_glyph_t)); + if (glyph_entry == NULL) { + status = _cairo_surface_set_error (&surface->base, + _cairo_error (CAIRO_STATUS_NO_MEMORY)); + return FALSE; + } + + glyph_entry->scaled_font = cairo_scaled_font_reference (scaled_font); + glyph_entry->glyph_index = glyph_index; + _cairo_pdf_color_glyph_init_key (glyph_entry); + + glyph_entry->supported = FALSE; + _cairo_scaled_font_freeze_cache (scaled_font); + status = _cairo_scaled_glyph_lookup (scaled_font, + glyph_index, + CAIRO_SCALED_GLYPH_INFO_COLOR_SURFACE, + NULL, /* foreground color */ + &scaled_glyph); + if (unlikely (status)) + goto done; + + glyph_entry->supported = !(scaled_glyph->recording_uses_foreground_color || + scaled_glyph->recording_uses_foreground_marker); + + done: + _cairo_scaled_font_thaw_cache (scaled_font); + + status = _cairo_hash_table_insert (surface->color_glyphs, + &glyph_entry->base); + if (unlikely(status)) { + status = _cairo_surface_set_error (&surface->base, + _cairo_error (CAIRO_STATUS_NO_MEMORY)); + return FALSE; + } + + return glyph_entry->supported; +} + +static cairo_int_status_t +_cairo_pdf_surface_analyze_recording_surface(void *abstract_surface, + const cairo_surface_pattern_t *recording_surface_pattern, + unsigned int region_id, + cairo_analysis_source_t source_type, + cairo_bool_t begin) +{ + cairo_pdf_surface_t *surface = abstract_surface; + cairo_int_status_t status = CAIRO_INT_STATUS_SUCCESS; + + if (begin) { + status = _cairo_pdf_interchange_recording_source_surface_begin ( + surface, + recording_surface_pattern, + region_id, + source_type); + } else { + status = _cairo_pdf_interchange_recording_source_surface_end ( + surface, + recording_surface_pattern, + region_id, + source_type); + } + + return status; +} + +static cairo_int_status_t _cairo_pdf_surface_set_paginated_mode (void *abstract_surface, cairo_paginated_mode_t paginated_mode) { @@ -8900,6 +9460,7 @@ _cairo_pdf_surface_set_paginated_mode (void *abstract_surface, cairo_int_status_t status; surface->paginated_mode = paginated_mode; + status = _cairo_pdf_interchange_begin_page_content (surface); if (unlikely (status)) return status; @@ -8950,6 +9511,9 @@ static const cairo_surface_backend_t cairo_pdf_surface_backend = { _cairo_pdf_surface_show_text_glyphs, _cairo_pdf_surface_get_supported_mime_types, _cairo_pdf_surface_tag, + _cairo_pdf_surface_supports_color_glyph, + _cairo_pdf_surface_analyze_recording_surface, + _cairo_pdf_surface_command_id, }; static const cairo_paginated_surface_backend_t diff --git a/gfx/cairo/cairo/src/cairo-pdf.h b/gfx/cairo/cairo/src/cairo-pdf.h index 5be0b3f1be..7e8025be30 100644 --- a/gfx/cairo/cairo/src/cairo-pdf.h +++ b/gfx/cairo/cairo/src/cairo-pdf.h @@ -47,6 +47,8 @@ CAIRO_BEGIN_DECLS * cairo_pdf_version_t: * @CAIRO_PDF_VERSION_1_4: The version 1.4 of the PDF specification. (Since 1.10) * @CAIRO_PDF_VERSION_1_5: The version 1.5 of the PDF specification. (Since 1.10) + * @CAIRO_PDF_VERSION_1_6: The version 1.6 of the PDF specification. (Since 1.18) + * @CAIRO_PDF_VERSION_1_7: The version 1.7 of the PDF specification. (Since 1.18) * * #cairo_pdf_version_t is used to describe the version number of the PDF * specification that a generated PDF file will conform to. @@ -55,7 +57,9 @@ CAIRO_BEGIN_DECLS **/ typedef enum _cairo_pdf_version { CAIRO_PDF_VERSION_1_4, - CAIRO_PDF_VERSION_1_5 + CAIRO_PDF_VERSION_1_5, + CAIRO_PDF_VERSION_1_6, + CAIRO_PDF_VERSION_1_7 } cairo_pdf_version_t; cairo_public cairo_surface_t * @@ -144,6 +148,11 @@ cairo_pdf_surface_set_metadata (cairo_surface_t *surface, const char *utf8); cairo_public void +cairo_pdf_surface_set_custom_metadata (cairo_surface_t *surface, + const char *name, + const char *value); + +cairo_public void cairo_pdf_surface_set_page_label (cairo_surface_t *surface, const char *utf8); diff --git a/gfx/cairo/cairo/src/cairo-pen.c b/gfx/cairo/cairo/src/cairo-pen.c index 9bf960423d..a4b84aae58 100644 --- a/gfx/cairo/cairo/src/cairo-pen.c +++ b/gfx/cairo/cairo/src/cairo-pen.c @@ -289,7 +289,12 @@ _cairo_pen_vertices_needed (double tolerance, } else if (tolerance >= major_axis) { num_vertices = 4; } else { - num_vertices = ceil (2*M_PI / acos (1 - tolerance / major_axis)); + double divisor = acos (1 - tolerance / major_axis); + + if (divisor == 0.0) + return 4; + + num_vertices = ceil (2*M_PI / divisor); /* number of vertices must be even */ if (num_vertices % 2) diff --git a/gfx/cairo/cairo/src/cairo-png.c b/gfx/cairo/cairo/src/cairo-png.c index f576047b19..63e3c4cdbd 100644 --- a/gfx/cairo/cairo/src/cairo-png.c +++ b/gfx/cairo/cairo/src/cairo-png.c @@ -407,6 +407,14 @@ write_png (cairo_surface_t *surface, */ png_write_info (png, info); +#ifndef WORDS_BIGENDIAN + /* libpng treats 16-bit data as big-endian by default. Swapping the + * byte-order on little endian ensures the native-endian data can be + * provided to png_write_image. This does not affect 8-bit data. + */ + png_set_swap (png); +#endif + if (png_color_type == PNG_COLOR_TYPE_RGB_ALPHA) { if (clone->format != CAIRO_FORMAT_RGBA128F) png_set_write_user_transform_fn (png, unpremultiply_data); @@ -561,7 +569,6 @@ 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) @@ -702,6 +709,14 @@ read_png (struct png_read_closure_t *png_closure) png_read_info (png, info); +#ifndef WORDS_BIGENDIAN + /* libpng treats 16-bit data as big-endian by default. Swapping the + * byte-order on little endian ensures the native-endian data can be + * provided to png_read_image. This does not affect 8-bit data. + */ + png_set_swap (png); +#endif + png_get_IHDR (png, info, &png_width, &png_height, &depth, &color_type, &interlace, NULL, NULL); diff --git a/gfx/cairo/cairo/src/cairo-ps-surface-private.h b/gfx/cairo/cairo/src/cairo-ps-surface-private.h index f184031902..e825b57fdd 100644 --- a/gfx/cairo/cairo/src/cairo-ps-surface-private.h +++ b/gfx/cairo/cairo/src/cairo-ps-surface-private.h @@ -56,6 +56,7 @@ typedef struct _cairo_ps_form { cairo_bool_t is_image; int id; cairo_surface_t *src_surface; + unsigned int regions_id; cairo_rectangle_int_t src_surface_extents; cairo_bool_t src_surface_bounded; cairo_filter_t filter; diff --git a/gfx/cairo/cairo/src/cairo-ps-surface.c b/gfx/cairo/cairo/src/cairo-ps-surface.c index 4adccad6b7..381b4cf751 100644 --- a/gfx/cairo/cairo/src/cairo-ps-surface.c +++ b/gfx/cairo/cairo/src/cairo-ps-surface.c @@ -66,18 +66,19 @@ #include "cairo-composite-rectangles-private.h" #include "cairo-default-context-private.h" #include "cairo-error-private.h" +#include "cairo-image-info-private.h" #include "cairo-image-surface-inline.h" #include "cairo-list-inline.h" -#include "cairo-scaled-font-subsets-private.h" +#include "cairo-output-stream-private.h" #include "cairo-paginated-private.h" +#include "cairo-recording-surface-inline.h" #include "cairo-recording-surface-private.h" +#include "cairo-scaled-font-subsets-private.h" #include "cairo-surface-clipper-private.h" #include "cairo-surface-snapshot-inline.h" #include "cairo-surface-subsurface-private.h" -#include "cairo-output-stream-private.h" -#include "cairo-type3-glyph-surface-private.h" -#include "cairo-image-info-private.h" #include "cairo-tag-attributes-private.h" +#include "cairo-type3-glyph-surface-private.h" #include <stdio.h> #include <ctype.h> @@ -102,7 +103,11 @@ #endif #ifndef HAVE_CTIME_R -#define ctime_r(T, BUF) ctime (T) +static char *ctime_r(const time_t *timep, char *buf) +{ + (void)buf; + return ctime(timep); +} #endif /** @@ -114,9 +119,8 @@ * The PostScript surface is used to render cairo graphics to Adobe * PostScript files and is a multi-page vector surface backend. * - * The following mime types are supported: %CAIRO_MIME_TYPE_JPEG, - * %CAIRO_MIME_TYPE_UNIQUE_ID, - * %CAIRO_MIME_TYPE_CCITT_FAX, %CAIRO_MIME_TYPE_CCITT_FAX_PARAMS, + * The following mime types are supported on source patterns: + * %CAIRO_MIME_TYPE_JPEG, %CAIRO_MIME_TYPE_UNIQUE_ID, * %CAIRO_MIME_TYPE_CCITT_FAX, %CAIRO_MIME_TYPE_CCITT_FAX_PARAMS, * %CAIRO_MIME_TYPE_EPS, %CAIRO_MIME_TYPE_EPS_PARAMS. * @@ -144,7 +148,7 @@ * ury]" that specifies the bounding box (in PS coordinates) of the * EPS graphics. The parameters are: lower left x, lower left y, upper * right x, upper right y. Normally the bbox data is identical to the - * %%%BoundingBox data in the EPS file. + * \%\%\%BoundingBox data in the EPS file. * **/ @@ -172,6 +176,7 @@ typedef enum { typedef struct { /* input params */ cairo_surface_t *src_surface; + unsigned int regions_id; cairo_operator_t op; const cairo_rectangle_int_t *src_surface_extents; cairo_bool_t src_surface_bounded; @@ -213,8 +218,11 @@ static const char * _cairo_ps_level_strings[CAIRO_PS_LEVEL_LAST] = static const char *_cairo_ps_supported_mime_types[] = { CAIRO_MIME_TYPE_JPEG, + CAIRO_MIME_TYPE_UNIQUE_ID, CAIRO_MIME_TYPE_CCITT_FAX, CAIRO_MIME_TYPE_CCITT_FAX_PARAMS, + CAIRO_MIME_TYPE_EPS, + CAIRO_MIME_TYPE_EPS_PARAMS, NULL }; @@ -282,6 +290,8 @@ _cairo_ps_form_pluck (void *entry, void *closure) _cairo_hash_table_remove (patterns, &surface_entry->base); free (surface_entry->unique_id); + if (_cairo_surface_is_recording (surface_entry->src_surface) && surface_entry->regions_id != 0) + _cairo_recording_surface_region_array_remove (surface_entry->src_surface, surface_entry->regions_id); cairo_surface_destroy (surface_entry->src_surface); free (surface_entry); } @@ -312,17 +322,21 @@ _cairo_ps_surface_emit_header (cairo_ps_surface_t *surface) _cairo_output_stream_printf (surface->final_stream, "%%!PS-Adobe-3.0%s\n" - "%%%%Creator: cairo %s (https://cairographics.org)\n" - "%%%%CreationDate: %s" - "%%%%Pages: %d\n", + "%%%%Creator: cairo %s (https://cairographics.org)\n", eps_header, - cairo_version_string (), - ctime_r (&now, ctime_buf), - surface->num_pages); + cairo_version_string ()); + + if (!getenv ("CAIRO_DEBUG_PS_NO_DATE")) { + _cairo_output_stream_printf (surface->final_stream, + "%%%%CreationDate: %s", + ctime_r (&now, ctime_buf)); + } _cairo_output_stream_printf (surface->final_stream, + "%%%%Pages: %d\n" "%%%%DocumentData: Clean7Bit\n" "%%%%LanguageLevel: %d\n", + surface->num_pages, level); if (!cairo_list_is_empty (&surface->document_media)) { @@ -497,17 +511,6 @@ _cairo_ps_surface_emit_header (cairo_ps_surface_t *surface) _cairo_output_stream_printf (surface->final_stream, "%%%%EndProlog\n"); - - num_comments = _cairo_array_num_elements (&surface->dsc_setup_comments); - if (num_comments) { - comments = _cairo_array_index (&surface->dsc_setup_comments, 0); - for (i = 0; i < num_comments; i++) { - _cairo_output_stream_printf (surface->final_stream, - "%s\n", comments[i]); - free (comments[i]); - comments[i] = NULL; - } - } } static cairo_status_t @@ -737,34 +740,6 @@ _cairo_ps_emit_imagemask (cairo_image_surface_t *image, return _cairo_output_stream_get_status (stream); } -static cairo_int_status_t -_cairo_ps_surface_analyze_user_font_subset (cairo_scaled_font_subset_t *font_subset, - void *closure) -{ - cairo_ps_surface_t *surface = closure; - cairo_status_t status = CAIRO_STATUS_SUCCESS; - unsigned int i; - cairo_surface_t *type3_surface; - - type3_surface = _cairo_type3_glyph_surface_create (font_subset->scaled_font, - NULL, - _cairo_ps_emit_imagemask, - surface->font_subsets, - TRUE); - - for (i = 0; i < font_subset->num_glyphs; i++) { - status = _cairo_type3_glyph_surface_analyze_glyph (type3_surface, - font_subset->glyphs[i]); - if (unlikely (status)) - break; - - } - cairo_surface_finish (type3_surface); - cairo_surface_destroy (type3_surface); - - return status; -} - static cairo_status_t _cairo_ps_surface_emit_type3_font_subset (cairo_ps_surface_t *surface, cairo_scaled_font_subset_t *font_subset) @@ -931,30 +906,17 @@ _cairo_ps_surface_emit_font_subsets (cairo_ps_surface_t *surface) "%% _cairo_ps_surface_emit_font_subsets\n"); #endif - status = _cairo_scaled_font_subsets_foreach_user (surface->font_subsets, - _cairo_ps_surface_analyze_user_font_subset, - surface); - if (unlikely (status)) - return status; - status = _cairo_scaled_font_subsets_foreach_unscaled (surface->font_subsets, _cairo_ps_surface_emit_unscaled_font_subset, surface); if (unlikely (status)) return status; - status = _cairo_scaled_font_subsets_foreach_scaled (surface->font_subsets, - _cairo_ps_surface_emit_scaled_font_subset, - surface); - if (unlikely (status)) - return status; - - return _cairo_scaled_font_subsets_foreach_user (surface->font_subsets, - _cairo_ps_surface_emit_scaled_font_subset, - surface); + return _cairo_scaled_font_subsets_foreach_scaled (surface->font_subsets, + _cairo_ps_surface_emit_scaled_font_subset, + surface); } - static cairo_int_status_t _cairo_ps_surface_emit_forms (cairo_ps_surface_t *surface) { @@ -1583,7 +1545,7 @@ cairo_ps_surface_set_size (cairo_surface_t *surface, * beyond these two conditions, this function will not enforce * conformance of the comment with any particular specification. * - * The comment string should not have a trailing newline. + * The comment string must not contain any newline characters. * * The DSC specifies different sections in which particular comments * can appear. This function provides for comments to be emitted @@ -1764,6 +1726,17 @@ _cairo_ps_surface_finish (void *abstract_surface) _cairo_output_stream_printf (surface->final_stream, "%%%%BeginSetup\n"); + num_comments = _cairo_array_num_elements (&surface->dsc_setup_comments); + if (num_comments) { + comments = _cairo_array_index (&surface->dsc_setup_comments, 0); + for (i = 0; i < num_comments; i++) { + _cairo_output_stream_printf (surface->final_stream, + "%s\n", comments[i]); + free (comments[i]); + comments[i] = NULL; + } + } + status = _cairo_ps_surface_emit_font_subsets (surface); if (unlikely (status)) goto CLEANUP; @@ -2481,6 +2454,7 @@ _cairo_ps_surface_emit_base85_string (cairo_ps_surface_t *surface, unsigned char *data_compressed; unsigned long data_compressed_size; cairo_status_t status, status2; + cairo_status_t this_cannot_be_handled; if (use_strings) string_array_stream = _base85_strings_stream_create (surface->stream); @@ -2498,6 +2472,7 @@ _cairo_ps_surface_emit_base85_string (cairo_ps_surface_t *surface, return _cairo_output_stream_destroy (base85_stream); } + status = 0; switch (compress) { case CAIRO_PS_COMPRESS_NONE: _cairo_output_stream_write (base85_stream, data, length); @@ -2509,8 +2484,8 @@ _cairo_ps_surface_emit_base85_string (cairo_ps_surface_t *surface, data_compressed_size = length; data_compressed = _cairo_lzw_compress ((unsigned char*)data, &data_compressed_size); if (unlikely (data_compressed == NULL)) { - status = _cairo_output_stream_destroy (string_array_stream); - status = _cairo_output_stream_destroy (base85_stream); + this_cannot_be_handled = _cairo_output_stream_destroy (string_array_stream); + this_cannot_be_handled = _cairo_output_stream_destroy (base85_stream); return _cairo_error (CAIRO_STATUS_NO_MEMORY); } _cairo_output_stream_write (base85_stream, data_compressed, data_compressed_size); @@ -2525,9 +2500,9 @@ _cairo_ps_surface_emit_base85_string (cairo_ps_surface_t *surface, _cairo_output_stream_write (deflate_stream, data, length); status = _cairo_output_stream_destroy (deflate_stream); if (unlikely (status)) { - status2 = _cairo_output_stream_destroy (string_array_stream); - status2 = _cairo_output_stream_destroy (base85_stream); - return _cairo_output_stream_destroy (deflate_stream); + this_cannot_be_handled = _cairo_output_stream_destroy (string_array_stream); + this_cannot_be_handled = _cairo_output_stream_destroy (base85_stream); + return status; } break; } @@ -2603,7 +2578,6 @@ _cairo_ps_surface_emit_image (cairo_ps_surface_t *surface, surf = _cairo_image_surface_create_with_content (image->base.content, image->width, image->height); - image = (cairo_image_surface_t *) surf; if (surf->status) { status = surf->status; goto bail0; @@ -2614,6 +2588,7 @@ _cairo_ps_surface_emit_image (cairo_ps_surface_t *surface, CAIRO_OPERATOR_SOURCE, &pattern.base, NULL); _cairo_pattern_fini (&pattern.base); + image = (cairo_image_surface_t *) surf; if (unlikely (status)) goto bail0; } @@ -3085,9 +3060,10 @@ _cairo_ps_surface_emit_ccitt_image (cairo_ps_surface_t *surface, return CAIRO_INT_STATUS_UNSUPPORTED; /* ensure params_string is null terminated */ - ccitt_params_string = malloc (ccitt_params_data_len + 1); - memcpy (ccitt_params_string, ccitt_params_data, ccitt_params_data_len); - ccitt_params_string[ccitt_params_data_len] = 0; + ccitt_params_string = _cairo_strndup ((const char *)ccitt_params_data, ccitt_params_data_len); + if (unlikely (ccitt_params_string == NULL)) + return _cairo_surface_set_error (&surface->base, CAIRO_STATUS_NO_MEMORY); + status = _cairo_tag_parse_ccitt_params (ccitt_params_string, &ccitt_params); if (unlikely(status)) return status; @@ -3270,9 +3246,10 @@ _cairo_ps_surface_emit_eps (cairo_ps_surface_t *surface, return CAIRO_INT_STATUS_UNSUPPORTED; /* ensure params_string is null terminated */ - params_string = malloc (eps_params_string_len + 1); - memcpy (params_string, eps_params_string, eps_params_string_len); - params_string[eps_params_string_len] = 0; + params_string = _cairo_strndup ((const char *)eps_params_string, eps_params_string_len); + if (unlikely (params_string == NULL)) + return _cairo_surface_set_error (&surface->base, CAIRO_STATUS_NO_MEMORY); + status = _cairo_tag_parse_eps_params (params_string, &eps_params); if (unlikely(status)) return status; @@ -3317,7 +3294,11 @@ _cairo_ps_surface_emit_eps (cairo_ps_surface_t *surface, eps_width, eps_height); + _cairo_output_stream_printf (surface->stream, + "%%%%BeginDocument: Document%d\n", + params->src_surface->unique_id); _cairo_output_stream_write (surface->stream, eps_data, eps_data_len); + _cairo_output_stream_printf (surface->stream, "%%%%EndDocument"); _cairo_output_stream_printf (surface->stream, "\ncairo_eps_end\n"); return CAIRO_STATUS_SUCCESS; @@ -3326,6 +3307,7 @@ _cairo_ps_surface_emit_eps (cairo_ps_surface_t *surface, static cairo_status_t _cairo_ps_surface_emit_recording_surface (cairo_ps_surface_t *surface, cairo_surface_t *recording_surface, + unsigned int regions_id, const cairo_rectangle_int_t *recording_extents, cairo_bool_t subsurface) { @@ -3396,6 +3378,7 @@ _cairo_ps_surface_emit_recording_surface (cairo_ps_surface_t *surface, } status = _cairo_recording_surface_replay_region (recording_surface, + regions_id, subsurface ? recording_extents : NULL, &surface->base, CAIRO_RECORDING_REGION_NATIVE); @@ -3548,6 +3531,9 @@ _cairo_ps_surface_use_form (cairo_ps_surface_t *surface, source_entry->unique_id = unique_id; source_entry->id = surface->num_forms++; source_entry->src_surface = cairo_surface_reference (params->src_surface); + source_entry->regions_id = params->regions_id; + if (_cairo_surface_is_recording (source_entry->src_surface) && source_entry->regions_id != 0) + _cairo_recording_surface_region_array_reference (source_entry->src_surface, source_entry->regions_id); source_entry->src_surface_extents = *params->src_surface_extents; source_entry->src_surface_bounded = params->src_surface_bounded; source_entry->required_extents = *params->src_op_extents; @@ -3680,11 +3666,13 @@ _cairo_ps_surface_emit_surface (cairo_ps_surface_t *surface, cairo_surface_subsurface_t *sub = (cairo_surface_subsurface_t *) params->src_surface; status = _cairo_ps_surface_emit_recording_surface (surface, sub->target, + params->regions_id, &sub->extents, TRUE); } else { status = _cairo_ps_surface_emit_recording_surface (surface, params->src_surface, + params->regions_id, params->src_op_extents, FALSE); } @@ -3703,11 +3691,11 @@ _cairo_ps_surface_emit_surface (cairo_ps_surface_t *surface, status = _cairo_memory_stream_destroy (surface->stream, &data, &length); free (data); + surface->stream = old_stream; if (unlikely (status)) return status; params->approx_size = length; - surface->stream = old_stream; _cairo_pdf_operators_set_stream (&surface->pdf_operators, surface->stream); } @@ -3727,6 +3715,7 @@ _cairo_ps_form_emit (void *entry, void *closure) cairo_output_stream_t *old_stream; params.src_surface = form->src_surface; + params.regions_id = form->regions_id; params.op = CAIRO_OPERATOR_OVER; params.src_surface_extents = &form->src_surface_extents; params.src_surface_bounded = form->src_surface_bounded; @@ -3868,11 +3857,17 @@ _cairo_ps_surface_paint_surface (cairo_ps_surface_t *surface, cairo_path_fixed_t path; cairo_emit_surface_params_t params; cairo_image_surface_t *image = NULL; + unsigned int region_id = 0; status = _cairo_pdf_operators_flush (&surface->pdf_operators); if (unlikely (status)) return status; + if (pattern->type == CAIRO_PATTERN_TYPE_SURFACE) { + cairo_surface_pattern_t *surface_pattern = (cairo_surface_pattern_t *) pattern; + region_id = surface_pattern->region_array_id; + } + status = _cairo_ps_surface_acquire_source_surface_from_pattern (surface, pattern, extents, @@ -3958,6 +3953,7 @@ _cairo_ps_surface_paint_surface (cairo_ps_surface_t *surface, cairo_matrix_translate (&ps_p2d, x_offset, y_offset); params.src_surface = image ? &image->base : source_surface; + params.regions_id = image ? 0 : region_id; params.op = op; params.src_surface_extents = &src_surface_extents; params.src_surface_bounded = src_surface_bounded; @@ -4012,12 +4008,18 @@ _cairo_ps_surface_emit_surface_pattern (cairo_ps_surface_t *surface, cairo_rectangle_int_t src_op_extents; cairo_emit_surface_params_t params; cairo_extend_t extend = cairo_pattern_get_extend (pattern); + unsigned int region_id = 0; cairo_p2d = pattern->matrix; status = cairo_matrix_invert (&cairo_p2d); /* cairo_pattern_set_matrix ensures the matrix is invertible */ assert (status == CAIRO_STATUS_SUCCESS); + if (pattern->type == CAIRO_PATTERN_TYPE_SURFACE) { + cairo_surface_pattern_t *surface_pattern = (cairo_surface_pattern_t *) pattern; + region_id = surface_pattern->region_array_id; + } + status = _cairo_ps_surface_acquire_source_surface_from_pattern (surface, pattern, extents, @@ -4111,6 +4113,7 @@ _cairo_ps_surface_emit_surface_pattern (cairo_ps_surface_t *surface, old_paint_proc = surface->paint_proc; surface->paint_proc = TRUE; params.src_surface = image ? &image->base : source_surface; + params.regions_id = image ? 0 : region_id; params.op = op; params.src_surface_extents = &pattern_extents; params.src_surface_bounded = bounded; @@ -4405,7 +4408,7 @@ _cairo_ps_surface_emit_pattern_stops (cairo_ps_surface_t *surface, /* no need for stitched function */ _cairo_ps_surface_emit_linear_colorgradient (surface, &stops[0], &stops[1]); } else { - /* multiple stops: stitch. XXX possible optimization: regulary spaced + /* multiple stops: stitch. XXX possible optimization: regularly spaced * stops do not require stitching. XXX */ _cairo_ps_surface_emit_stitched_colorgradient (surface, n_stops, stops); } diff --git a/gfx/cairo/cairo/src/cairo-qt-surface.cpp b/gfx/cairo/cairo/src/cairo-qt-surface.cpp deleted file mode 100644 index d276f059e1..0000000000 --- a/gfx/cairo/cairo/src/cairo-qt-surface.cpp +++ /dev/null @@ -1,1741 +0,0 @@ -/* -*- Mode: c; c-basic-offset: 4; indent-tabs-mode: t; tab-width: 8; -*- */ -/* cairo - a vector graphics library with display and print output - * - * Copyright © 2008 Mozilla Corporation - * - * This library is free software; you can redistribute it and/or - * modify it either under the terms of the GNU Lesser General Public - * License version 2.1 as published by the Free Software Foundation - * (the "LGPL") or, at your option, under the terms of the Mozilla - * Public License Version 1.1 (the "MPL"). If you do not alter this - * notice, a recipient may use your version of this file under either - * the MPL or the LGPL. - * - * You should have received a copy of the LGPL along with this library - * in the file COPYING-LGPL-2.1; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Suite 500, Boston, MA 02110-1335, USA - * You should have received a copy of the MPL along with this library - * in the file COPYING-MPL-1.1 - * - * The contents of this file are subject to the Mozilla Public License - * Version 1.1 (the "License"); you may not use this file except in - * compliance with the License. You may obtain a copy of the License at - * http://www.mozilla.org/MPL/ - * - * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY - * OF ANY KIND, either express or implied. See the LGPL or the MPL for - * the specific language governing rights and limitations. - * - * The Original Code is the cairo graphics library. - * - * The Initial Developer of the Original Code is Mozilla Corporation. - * - * Contributor(s): - * Vladimir Vukicevic <vladimir@mozilla.com> - */ - -/* Get INT16_MIN etc. as per C99 */ -#define __STDC_LIMIT_MACROS - -#include "cairoint.h" - -#include "cairo-clip-private.h" -#include "cairo-default-context-private.h" -#include "cairo-error-private.h" -#include "cairo-region-private.h" -#include "cairo-surface-clipper-private.h" -#include "cairo-types-private.h" -#include "cairo-image-surface-private.h" -#include "cairo-pattern-private.h" -#include "cairo-surface-backend-private.h" -#include "cairo-surface-fallback-private.h" - -#include "cairo-ft.h" -#include "cairo-qt.h" - -#include <memory> - -#include <QtGui/QPainter> -#include <QtGui/QPaintEngine> -#include <QtGui/QPaintDevice> -#include <QtGui/QImage> -#include <QtGui/QPixmap> -#include <QtGui/QBrush> -#include <QtGui/QPen> -#include <QWidget> -#include <QtCore/QVarLengthArray> - -#if ((QT_VERSION >= QT_VERSION_CHECK(4, 7, 0)) || defined(QT_GLYPHS_API_BACKPORT)) && 0 -extern void qt_draw_glyphs(QPainter *, const quint32 *glyphs, const QPointF *positions, int count); -#endif - -#include <sys/time.h> - -/* Enable workaround slow regional Qt paths */ -#define ENABLE_FAST_FILL 0 -#define ENABLE_FAST_CLIP 0 - -#if 0 -#define D(x) x -static const char * -_opstr (cairo_operator_t op) -{ - const char *ops[] = { - "CLEAR", - "SOURCE", - "OVER", - "IN", - "OUT", - "ATOP", - "DEST", - "DEST_OVER", - "DEST_IN", - "DEST_OUT", - "DEST_ATOP", - "XOR", - "ADD", - "SATURATE" - }; - - if (op < CAIRO_OPERATOR_CLEAR || op > CAIRO_OPERATOR_SATURATE) - return "(\?\?\?)"; - - return ops[op]; -} -#else -#define D(x) do { } while(0) -#endif - -#ifndef CAIRO_INT_STATUS_SUCCESS -#define CAIRO_INT_STATUS_SUCCESS ((cairo_int_status_t) CAIRO_STATUS_SUCCESS) -#endif - -/* Qt::PenStyle optimization based on the assumption that dots are 1*w and dashes are 3*w. */ -#define DOT_LENGTH 1.0 -#define DASH_LENGTH 3.0 - -struct cairo_qt_surface_t { - cairo_surface_t base; - - cairo_bool_t supports_porter_duff; - - QPainter *p; - - /* The pixmap/image constructors will store their objects here */ - QPixmap *pixmap; - QImage *image; - - QRect window; - - cairo_surface_clipper_t clipper; - - cairo_surface_t *image_equiv; -}; - -/* Will be true if we ever try to create a QPixmap and end - * up with one without an alpha channel. - */ -static cairo_bool_t _qpixmaps_have_no_alpha = FALSE; - -/* - * Helper methods - */ - -static QPainter::CompositionMode -_qpainter_compositionmode_from_cairo_op (cairo_operator_t op) -{ - switch (op) { - case CAIRO_OPERATOR_CLEAR: - return QPainter::CompositionMode_Clear; - - case CAIRO_OPERATOR_SOURCE: - return QPainter::CompositionMode_Source; - case CAIRO_OPERATOR_OVER: - return QPainter::CompositionMode_SourceOver; - case CAIRO_OPERATOR_IN: - return QPainter::CompositionMode_SourceIn; - case CAIRO_OPERATOR_OUT: - return QPainter::CompositionMode_SourceOut; - case CAIRO_OPERATOR_ATOP: - return QPainter::CompositionMode_SourceAtop; - - case CAIRO_OPERATOR_DEST: - return QPainter::CompositionMode_Destination; - case CAIRO_OPERATOR_DEST_OVER: - return QPainter::CompositionMode_DestinationOver; - case CAIRO_OPERATOR_DEST_IN: - return QPainter::CompositionMode_DestinationIn; - case CAIRO_OPERATOR_DEST_OUT: - return QPainter::CompositionMode_DestinationOut; - case CAIRO_OPERATOR_DEST_ATOP: - return QPainter::CompositionMode_DestinationAtop; - - case CAIRO_OPERATOR_XOR: - return QPainter::CompositionMode_Xor; - - default: - case CAIRO_OPERATOR_ADD: - case CAIRO_OPERATOR_SATURATE: - case CAIRO_OPERATOR_MULTIPLY: - case CAIRO_OPERATOR_SCREEN: - case CAIRO_OPERATOR_OVERLAY: - case CAIRO_OPERATOR_DARKEN: - case CAIRO_OPERATOR_LIGHTEN: - case CAIRO_OPERATOR_COLOR_DODGE: - case CAIRO_OPERATOR_COLOR_BURN: - case CAIRO_OPERATOR_HARD_LIGHT: - case CAIRO_OPERATOR_SOFT_LIGHT: - case CAIRO_OPERATOR_DIFFERENCE: - case CAIRO_OPERATOR_EXCLUSION: - case CAIRO_OPERATOR_HSL_HUE: - case CAIRO_OPERATOR_HSL_SATURATION: - case CAIRO_OPERATOR_HSL_COLOR: - case CAIRO_OPERATOR_HSL_LUMINOSITY: - ASSERT_NOT_REACHED; - } -} - -static bool -_op_is_supported (cairo_qt_surface_t *qs, cairo_operator_t op) -{ - if (qs->p == NULL) - return false; - - if (qs->supports_porter_duff) { - switch (op) { - case CAIRO_OPERATOR_CLEAR: - case CAIRO_OPERATOR_SOURCE: - case CAIRO_OPERATOR_OVER: - case CAIRO_OPERATOR_IN: - case CAIRO_OPERATOR_OUT: - case CAIRO_OPERATOR_ATOP: - - case CAIRO_OPERATOR_DEST: - case CAIRO_OPERATOR_DEST_OVER: - case CAIRO_OPERATOR_DEST_IN: - case CAIRO_OPERATOR_DEST_OUT: - case CAIRO_OPERATOR_DEST_ATOP: - - case CAIRO_OPERATOR_XOR: - return TRUE; - - default: - ASSERT_NOT_REACHED; - case CAIRO_OPERATOR_ADD: - case CAIRO_OPERATOR_SATURATE: - case CAIRO_OPERATOR_MULTIPLY: - case CAIRO_OPERATOR_SCREEN: - case CAIRO_OPERATOR_OVERLAY: - case CAIRO_OPERATOR_DARKEN: - case CAIRO_OPERATOR_LIGHTEN: - case CAIRO_OPERATOR_COLOR_DODGE: - case CAIRO_OPERATOR_COLOR_BURN: - case CAIRO_OPERATOR_HARD_LIGHT: - case CAIRO_OPERATOR_SOFT_LIGHT: - case CAIRO_OPERATOR_DIFFERENCE: - case CAIRO_OPERATOR_EXCLUSION: - case CAIRO_OPERATOR_HSL_HUE: - case CAIRO_OPERATOR_HSL_SATURATION: - case CAIRO_OPERATOR_HSL_COLOR: - case CAIRO_OPERATOR_HSL_LUMINOSITY: - return FALSE; - - } - } else { - return op == CAIRO_OPERATOR_OVER; - } -} - -static cairo_format_t -_cairo_format_from_qimage_format (QImage::Format fmt) -{ - switch (fmt) { - case QImage::Format_ARGB32_Premultiplied: - return CAIRO_FORMAT_ARGB32; - case QImage::Format_RGB32: - return CAIRO_FORMAT_RGB24; - case QImage::Format_Indexed8: // XXX not quite - return CAIRO_FORMAT_A8; -#ifdef WORDS_BIGENDIAN - case QImage::Format_Mono: -#else - case QImage::Format_MonoLSB: -#endif - return CAIRO_FORMAT_A1; - - case QImage::Format_Invalid: -#ifdef WORDS_BIGENDIAN - case QImage::Format_MonoLSB: -#else - case QImage::Format_Mono: -#endif - case QImage::Format_ARGB32: - case QImage::Format_RGB16: - case QImage::Format_ARGB8565_Premultiplied: - case QImage::Format_RGB666: - case QImage::Format_ARGB6666_Premultiplied: - case QImage::Format_RGB555: - case QImage::Format_ARGB8555_Premultiplied: - case QImage::Format_RGB888: - case QImage::Format_RGB444: - case QImage::Format_ARGB4444_Premultiplied: - case QImage::NImageFormats: - default: - ASSERT_NOT_REACHED; - return (cairo_format_t) -1; - } -} - -static QImage::Format -_qimage_format_from_cairo_format (cairo_format_t fmt) -{ - switch (fmt) { - case CAIRO_FORMAT_INVALID: - ASSERT_NOT_REACHED; - case CAIRO_FORMAT_ARGB32: - return QImage::Format_ARGB32_Premultiplied; - case CAIRO_FORMAT_RGB24: - return QImage::Format_RGB32; - case CAIRO_FORMAT_RGB16_565: - return QImage::Format_RGB16; - case CAIRO_FORMAT_A8: - return QImage::Format_Indexed8; // XXX not quite - case CAIRO_FORMAT_A1: -#ifdef WORDS_BIGENDIAN - return QImage::Format_Mono; // XXX think we need to choose between this and LSB -#else - return QImage::Format_MonoLSB; -#endif - case CAIRO_FORMAT_RGB30: - return QImage::Format_Mono; - } - - return QImage::Format_Mono; -} - -static inline QMatrix -_qmatrix_from_cairo_matrix (const cairo_matrix_t& m) -{ - return QMatrix(m.xx, m.yx, m.xy, m.yy, m.x0, m.y0); -} - -/* Path conversion */ -typedef struct _qpainter_path_transform { - QPainterPath path; - const cairo_matrix_t *ctm_inverse; -} qpainter_path_data; - -/* cairo path -> execute in context */ -static cairo_status_t -_cairo_path_to_qpainterpath_move_to (void *closure, const cairo_point_t *point) -{ - qpainter_path_data *pdata = static_cast <qpainter_path_data *> (closure); - double x = _cairo_fixed_to_double (point->x); - double y = _cairo_fixed_to_double (point->y); - - if (pdata->ctm_inverse) - cairo_matrix_transform_point (pdata->ctm_inverse, &x, &y); - - pdata->path.moveTo(x, y); - - return CAIRO_STATUS_SUCCESS; -} - -static cairo_status_t -_cairo_path_to_qpainterpath_line_to (void *closure, const cairo_point_t *point) -{ - qpainter_path_data *pdata = static_cast <qpainter_path_data *> (closure); - double x = _cairo_fixed_to_double (point->x); - double y = _cairo_fixed_to_double (point->y); - - if (pdata->ctm_inverse) - cairo_matrix_transform_point (pdata->ctm_inverse, &x, &y); - - pdata->path.lineTo(x, y); - - return CAIRO_STATUS_SUCCESS; -} - -static cairo_status_t -_cairo_path_to_qpainterpath_curve_to (void *closure, const cairo_point_t *p0, const cairo_point_t *p1, const cairo_point_t *p2) -{ - qpainter_path_data *pdata = static_cast <qpainter_path_data *> (closure); - double x0 = _cairo_fixed_to_double (p0->x); - double y0 = _cairo_fixed_to_double (p0->y); - double x1 = _cairo_fixed_to_double (p1->x); - double y1 = _cairo_fixed_to_double (p1->y); - double x2 = _cairo_fixed_to_double (p2->x); - double y2 = _cairo_fixed_to_double (p2->y); - - if (pdata->ctm_inverse) { - cairo_matrix_transform_point (pdata->ctm_inverse, &x0, &y0); - cairo_matrix_transform_point (pdata->ctm_inverse, &x1, &y1); - cairo_matrix_transform_point (pdata->ctm_inverse, &x2, &y2); - } - - pdata->path.cubicTo (x0, y0, x1, y1, x2, y2); - - return CAIRO_STATUS_SUCCESS; -} - -static cairo_status_t -_cairo_path_to_qpainterpath_close_path (void *closure) -{ - qpainter_path_data *pdata = static_cast <qpainter_path_data *> (closure); - - pdata->path.closeSubpath(); - - return CAIRO_STATUS_SUCCESS; -} - -static QPainterPath -path_to_qt (const cairo_path_fixed_t *path, - const cairo_matrix_t *ctm_inverse = NULL) -{ - qpainter_path_data data; - cairo_status_t status; - - if (ctm_inverse && _cairo_matrix_is_identity (ctm_inverse)) - ctm_inverse = NULL; - data.ctm_inverse = ctm_inverse; - - status = _cairo_path_fixed_interpret (path, - _cairo_path_to_qpainterpath_move_to, - _cairo_path_to_qpainterpath_line_to, - _cairo_path_to_qpainterpath_curve_to, - _cairo_path_to_qpainterpath_close_path, - &data); - assert (status == CAIRO_STATUS_SUCCESS); - - return data.path; -} - -static inline QPainterPath -path_to_qt (const cairo_path_fixed_t *path, - cairo_fill_rule_t fill_rule, - cairo_matrix_t *ctm_inverse = NULL) -{ - QPainterPath qpath = path_to_qt (path, ctm_inverse); - - qpath.setFillRule (fill_rule == CAIRO_FILL_RULE_WINDING ? - Qt::WindingFill : - Qt::OddEvenFill); - - return qpath; -} - -/* - * Surface backend methods - */ -static cairo_surface_t * -_cairo_qt_surface_create_similar (void *abstract_surface, - cairo_content_t content, - int width, - int height) -{ - cairo_qt_surface_t *qs = (cairo_qt_surface_t *) abstract_surface; - bool use_pixmap; - - D(fprintf(stderr, "q[%p] create_similar: %d %d [%d] -> ", abstract_surface, width, height, content)); - - use_pixmap = qs->image == NULL; - if (use_pixmap) { - switch (content) { - case CAIRO_CONTENT_ALPHA: - use_pixmap = FALSE; - break; - case CAIRO_CONTENT_COLOR: - break; - case CAIRO_CONTENT_COLOR_ALPHA: - use_pixmap = ! _qpixmaps_have_no_alpha; - break; - } - } - - if (use_pixmap) { - cairo_surface_t *result = - cairo_qt_surface_create_with_qpixmap (content, width, height); - - /* XXX result->content is always content. ??? */ - if (result->content == content) { - D(fprintf(stderr, "qpixmap content: %d\n", content)); - return result; - } - - _qpixmaps_have_no_alpha = TRUE; - cairo_surface_destroy (result); - } - - D(fprintf (stderr, "qimage\n")); - return cairo_qt_surface_create_with_qimage - (_cairo_format_from_content (content), width, height); -} - -static cairo_status_t -_cairo_qt_surface_finish (void *abstract_surface) -{ - cairo_qt_surface_t *qs = (cairo_qt_surface_t *) abstract_surface; - - D(fprintf(stderr, "q[%p] finish\n", abstract_surface)); - - /* Only delete p if we created it */ - if (qs->image || qs->pixmap) - delete qs->p; - else - qs->p->restore (); - - if (qs->image_equiv) - cairo_surface_destroy (qs->image_equiv); - - _cairo_surface_clipper_reset (&qs->clipper); - - if (qs->image) - delete qs->image; - - if (qs->pixmap) - delete qs->pixmap; - - return CAIRO_STATUS_SUCCESS; -} - -static void -_qimg_destroy (void *closure) -{ - QImage *qimg = (QImage *) closure; - delete qimg; -} - -static cairo_status_t -_cairo_qt_surface_acquire_source_image (void *abstract_surface, - cairo_image_surface_t **image_out, - void **image_extra) -{ - cairo_qt_surface_t *qs = (cairo_qt_surface_t *) abstract_surface; - - D(fprintf(stderr, "q[%p] acquire_source_image\n", abstract_surface)); - - *image_extra = NULL; - - if (qs->image_equiv) { - *image_out = (cairo_image_surface_t*) - cairo_surface_reference (qs->image_equiv); - - return CAIRO_STATUS_SUCCESS; - } - - if (qs->pixmap) { - QImage *qimg = new QImage(qs->pixmap->toImage()); - cairo_surface_t *image; - cairo_status_t status; - - image = cairo_image_surface_create_for_data (qimg->bits(), - _cairo_format_from_qimage_format (qimg->format()), - qimg->width(), qimg->height(), - qimg->bytesPerLine()); - - status = _cairo_user_data_array_set_data (&image->user_data, - (const cairo_user_data_key_t *)&_qimg_destroy, - qimg, - _qimg_destroy); - if (status) { - cairo_surface_destroy (image); - return status; - } - - *image_out = (cairo_image_surface_t *) image; - return CAIRO_STATUS_SUCCESS; - } - - return _cairo_error (CAIRO_STATUS_NO_MEMORY); -} - -static void -_cairo_qt_surface_release_source_image (void *abstract_surface, - cairo_image_surface_t *image, - void *image_extra) -{ - //cairo_qt_surface_t *qs = (cairo_qt_surface_t *) abstract_surface; - - D(fprintf(stderr, "q[%p] release_source_image\n", abstract_surface)); - - cairo_surface_destroy (&image->base); -} - -struct _qimage_surface { - cairo_image_surface_t image; - QImage *qimg; -}; - -static cairo_surface_t * -map_qimage_to_image (QImage *qimg, const cairo_rectangle_int_t *extents) -{ - struct _qimage_surface *surface; - pixman_image_t *pixman_image; - pixman_format_code_t pixman_format; - uint8_t *data; - - if (qimg == NULL) - return _cairo_surface_create_in_error (CAIRO_STATUS_NO_MEMORY); - - switch (qimg->format()) { - case QImage::Format_ARGB32_Premultiplied: - pixman_format = PIXMAN_a8r8g8b8; - break; - case QImage::Format_RGB32: - pixman_format = PIXMAN_x8r8g8b8; - break; - case QImage::Format_Indexed8: // XXX not quite - pixman_format = PIXMAN_a8; - break; -#ifdef WORDS_BIGENDIAN - case QImage::Format_Mono: -#else - case QImage::Format_MonoLSB: -#endif - pixman_format = PIXMAN_a1; - break; - - case QImage::Format_Invalid: -#ifdef WORDS_BIGENDIAN - case QImage::Format_MonoLSB: -#else - case QImage::Format_Mono: -#endif - case QImage::Format_ARGB32: - case QImage::Format_RGB16: - case QImage::Format_ARGB8565_Premultiplied: - case QImage::Format_RGB666: - case QImage::Format_ARGB6666_Premultiplied: - case QImage::Format_RGB555: - case QImage::Format_ARGB8555_Premultiplied: - case QImage::Format_RGB888: - case QImage::Format_RGB444: - case QImage::Format_ARGB4444_Premultiplied: - case QImage::NImageFormats: - default: - delete qimg; - return _cairo_surface_create_in_error (CAIRO_STATUS_INVALID_FORMAT); - } - - data = qimg->bits(); - data += extents->y * qimg->bytesPerLine(); - data += extents->x * PIXMAN_FORMAT_BPP (pixman_format) / 8; - - pixman_image = pixman_image_create_bits (pixman_format, - extents->width, - extents->height, - (uint32_t *)data, - qimg->bytesPerLine()); - if (pixman_image == NULL) { - delete qimg; - return _cairo_surface_create_in_error (CAIRO_STATUS_NO_MEMORY); - } - - surface = (struct _qimage_surface *) _cairo_malloc (sizeof(*surface)); - if (unlikely (surface == NULL)) { - pixman_image_unref (pixman_image); - delete qimg; - return _cairo_surface_create_in_error (CAIRO_STATUS_NO_MEMORY); - } - - _cairo_image_surface_init (&surface->image, pixman_image, pixman_format); - surface->qimg = qimg; - - cairo_surface_set_device_offset (&surface->image.base, - -extents->x, -extents->y); - - return &surface->image.base; -} - -static cairo_image_surface_t * -_cairo_qt_surface_map_to_image (void *abstract_surface, - const cairo_rectangle_int_t *extents) -{ - cairo_qt_surface_t *qs = (cairo_qt_surface_t *) abstract_surface; - QImage *qimg = NULL; - - D(fprintf(stderr, "q[%p] acquire_dest_image\n", abstract_surface)); - - if (qs->image_equiv) - return _cairo_image_surface_map_to_image (qs->image_equiv, - extents); - - QPoint offset; - - if (qs->pixmap) { - qimg = new QImage(qs->pixmap->toImage()); - } else { - // Try to figure out what kind of QPaintDevice we have, and - // how we can grab an image from it - QPaintDevice *pd = qs->p->device(); - if (!pd) - return (cairo_image_surface_t *) _cairo_surface_create_in_error (CAIRO_STATUS_NO_MEMORY); - - QPaintDevice *rpd = QPainter::redirected(pd, &offset); - if (rpd) - pd = rpd; - - if (pd->devType() == QInternal::Image) { - qimg = new QImage(((QImage*) pd)->copy()); - } else if (pd->devType() == QInternal::Pixmap) { - qimg = new QImage(((QPixmap*) pd)->toImage()); - } else if (pd->devType() == QInternal::Widget) { - qimg = new QImage(QPixmap::grabWindow(((QWidget*)pd)->winId()).toImage()); - } - } - - return (cairo_image_surface_t *) map_qimage_to_image (qimg, extents); -} - -static cairo_int_status_t -_cairo_qt_surface_unmap_image (void *abstract_surface, - cairo_image_surface_t *image) -{ - cairo_qt_surface_t *qs = (cairo_qt_surface_t *) abstract_surface; - - D(fprintf(stderr, "q[%p] release_dest_image\n", abstract_surface)); - - if (!qs->image_equiv) { - struct _qimage_surface *qimage = (struct _qimage_surface *)image; - - // XXX should I be using setBackgroundMode here instead of setCompositionMode? - if (qs->supports_porter_duff) - qs->p->setCompositionMode (QPainter::CompositionMode_Source); - - qs->p->drawImage ((int)qimage->image.base.device_transform.x0, - (int)qimage->image.base.device_transform.y0, - *qimage->qimg, - (int)qimage->image.base.device_transform.x0, - (int)qimage->image.base.device_transform.y0, - (int)qimage->image.width, - (int)qimage->image.height); - - if (qs->supports_porter_duff) - qs->p->setCompositionMode (QPainter::CompositionMode_SourceOver); - - delete qimage->qimg; - } - - cairo_surface_finish (&image->base); - cairo_surface_destroy (&image->base); - - return CAIRO_INT_STATUS_SUCCESS; -} - -static cairo_bool_t -_cairo_qt_surface_get_extents (void *abstract_surface, - cairo_rectangle_int_t *extents) -{ - cairo_qt_surface_t *qs = (cairo_qt_surface_t *) abstract_surface; - - extents->x = qs->window.x(); - extents->y = qs->window.y(); - extents->width = qs->window.width(); - extents->height = qs->window.height(); - - return TRUE; -} - -static cairo_status_t -_cairo_qt_surface_clipper_intersect_clip_path (cairo_surface_clipper_t *clipper, - cairo_path_fixed_t *path, - cairo_fill_rule_t fill_rule, - double tolerance, - cairo_antialias_t antialias) -{ - cairo_qt_surface_t *qs = cairo_container_of (clipper, - cairo_qt_surface_t, - clipper); - - if (path == NULL) { - if (qs->pixmap || qs->image) { - // we own p - qs->p->setClipping (false); - } else { - qs->p->restore (); - qs->p->save (); - } - } else { - // XXX Antialiasing is ignored - qs->p->setClipPath (path_to_qt (path, fill_rule), Qt::IntersectClip); - } - - return CAIRO_STATUS_SUCCESS; -} - -static void -_cairo_qt_surface_set_clip_region (cairo_qt_surface_t *qs, - const cairo_region_t *clip_region) -{ - _cairo_surface_clipper_reset (&qs->clipper); - - if (clip_region == NULL) { - // How the clip path is reset depends on whether we own p or not - if (qs->pixmap || qs->image) { - // we own p - qs->p->setClipping (false); - } else { - qs->p->restore (); - qs->p->save (); - } - } else { - QRegion qr; - int num_rects = cairo_region_num_rectangles (clip_region); - for (int i = 0; i < num_rects; ++i) { - cairo_rectangle_int_t rect; - - cairo_region_get_rectangle (clip_region, i, &rect); - - QRect r(rect.x, rect.y, rect.width, rect.height); - qr = qr.unite(r); - } - - qs->p->setClipRegion (qr, Qt::IntersectClip); - } -} - -static cairo_int_status_t -_cairo_qt_surface_set_clip (cairo_qt_surface_t *qs, - const cairo_clip_t *clip) -{ - cairo_int_status_t status; - - D(fprintf(stderr, "q[%p] intersect_clip_path %s\n", abstract_surface, path ? "(path)" : "(clear)")); - - if (clip == NULL) { - _cairo_surface_clipper_reset (&qs->clipper); - // How the clip path is reset depends on whether we own p or not - if (qs->pixmap || qs->image) { - // we own p - qs->p->setClipping (false); - } else { - qs->p->restore (); - qs->p->save (); - } - - return CAIRO_INT_STATUS_SUCCESS; - } - -#if ENABLE_FAST_CLIP - // Qt will implicitly enable clipping, and will use ReplaceClip - // instead of IntersectClip if clipping was disabled before - - // Note: Qt is really bad at dealing with clip paths. It doesn't - // seem to usefully recognize rectangular paths, instead going down - // extremely slow paths whenever a clip path is set. So, - // we do a bunch of work here to try to get rectangles or regions - // down to Qt for clipping. - - cairo_region_t *clip_region = NULL; - - status = _cairo_clip_get_region (clip, &clip_region); - if (status == CAIRO_INT_STATUS_UNSUPPORTED) { - // We weren't able to extract a region from the traps. - // Just hand the path down to QPainter. - status = (cairo_int_status_t) - _cairo_surface_clipper_set_clip (&qs->clipper, clip); - } else if (status == CAIRO_INT_STATUS_SUCCESS) { - _cairo_qt_surface_set_clip_region (qs, clip_region); - status = CAIRO_INT_STATUS_SUCCESS; - } -#else - status = (cairo_int_status_t) - _cairo_surface_clipper_set_clip (&qs->clipper, clip); -#endif - - return status; -} - -/* - * Brush conversion - */ - -struct PatternToBrushConverter { - PatternToBrushConverter (const cairo_pattern_t *pattern) - __attribute__ ((noinline)) : - mAcquiredImageParent(0), - mAcquiredImage(0), - mAcquiredImageExtra(0) - { - if (pattern->type == CAIRO_PATTERN_TYPE_SOLID) { - cairo_solid_pattern_t *solid = (cairo_solid_pattern_t*) pattern; - QColor color; - color.setRgbF(solid->color.red, - solid->color.green, - solid->color.blue, - solid->color.alpha); - - mBrush = QBrush(color); - } else if (pattern->type == CAIRO_PATTERN_TYPE_SURFACE) { - cairo_surface_pattern_t *spattern = (cairo_surface_pattern_t*) pattern; - cairo_surface_t *surface = spattern->surface; - - if (surface->type == CAIRO_SURFACE_TYPE_QT) { - cairo_qt_surface_t *qs = (cairo_qt_surface_t*) surface; - - if (qs->image) { - mBrush = QBrush(*qs->image); - } else if (qs->pixmap) { - mBrush = QBrush(*qs->pixmap); - } else { - // do something smart - mBrush = QBrush(0xff0000ff); - } - } else { - cairo_image_surface_t *isurf = NULL; - - if (surface->type == CAIRO_SURFACE_TYPE_IMAGE) { - isurf = (cairo_image_surface_t*) surface; - } else { - void *image_extra; - - if (_cairo_surface_acquire_source_image (surface, &isurf, &image_extra) == CAIRO_STATUS_SUCCESS) { - mAcquiredImageParent = surface; - mAcquiredImage = isurf; - mAcquiredImageExtra = image_extra; - } else { - isurf = NULL; - } - } - - if (isurf) { - mBrush = QBrush (QImage ((const uchar *) isurf->data, - isurf->width, - isurf->height, - isurf->stride, - _qimage_format_from_cairo_format (isurf->format))); - } else { - mBrush = QBrush(0x0000ffff); - } - } - } else if (pattern->type == CAIRO_PATTERN_TYPE_LINEAR || - pattern->type == CAIRO_PATTERN_TYPE_RADIAL) - { - QGradient *grad; - cairo_bool_t reverse_stops = FALSE; - cairo_bool_t emulate_reflect = FALSE; - double offset = 0.0; - - cairo_extend_t extend = pattern->extend; - - cairo_gradient_pattern_t *gpat = (cairo_gradient_pattern_t *) pattern; - - if (pattern->type == CAIRO_PATTERN_TYPE_LINEAR) { - cairo_linear_pattern_t *lpat = (cairo_linear_pattern_t *) pattern; - grad = new QLinearGradient (lpat->pd1.x, lpat->pd1.y, - lpat->pd2.x, lpat->pd2.y); - } else if (pattern->type == CAIRO_PATTERN_TYPE_RADIAL) { - cairo_radial_pattern_t *rpat = (cairo_radial_pattern_t *) pattern; - - /* Based on the SVG surface code */ - - cairo_circle_double_t *c0, *c1; - double x0, y0, r0, x1, y1, r1; - - if (rpat->cd1.radius < rpat->cd2.radius) { - c0 = &rpat->cd1; - c1 = &rpat->cd2; - reverse_stops = FALSE; - } else { - c0 = &rpat->cd2; - c1 = &rpat->cd1; - reverse_stops = TRUE; - } - - x0 = c0->center.x; - y0 = c0->center.y; - r0 = c0->radius; - x1 = c1->center.x; - y1 = c1->center.y; - r1 = c1->radius; - - if (r0 == r1) { - grad = new QRadialGradient (x1, y1, r1, x1, y1); - } else { - double fx = (r1 * x0 - r0 * x1) / (r1 - r0); - double fy = (r1 * y0 - r0 * y1) / (r1 - r0); - - /* QPainter doesn't support the inner circle and use instead a gradient focal. - * That means we need to emulate the cairo behaviour by processing the - * cairo gradient stops. - * The CAIRO_EXTENT_NONE and CAIRO_EXTENT_PAD modes are quite easy to handle, - * it's just a matter of stop position translation and calculation of - * the corresponding SVG radial gradient focal. - * The CAIRO_EXTENT_REFLECT and CAIRO_EXTEND_REPEAT modes require to compute a new - * radial gradient, with an new outer circle, equal to r1 - r0 in the CAIRO_EXTEND_REPEAT - * case, and 2 * (r1 - r0) in the CAIRO_EXTENT_REFLECT case, and a new gradient stop - * list that maps to the original cairo stop list. - */ - if ((extend == CAIRO_EXTEND_REFLECT || extend == CAIRO_EXTEND_REPEAT) && r0 > 0.0) { - double r_org = r1; - double r, x, y; - - if (extend == CAIRO_EXTEND_REFLECT) { - r1 = 2 * r1 - r0; - emulate_reflect = TRUE; - } - - offset = fmod (r1, r1 - r0) / (r1 - r0) - 1.0; - r = r1 - r0; - - /* New position of outer circle. */ - x = r * (x1 - fx) / r_org + fx; - y = r * (y1 - fy) / r_org + fy; - - x1 = x; - y1 = y; - r1 = r; - r0 = 0.0; - } else { - offset = r0 / r1; - } - - grad = new QRadialGradient (x1, y1, r1, fx, fy); - - if (extend == CAIRO_EXTEND_NONE && r0 != 0.0) - grad->setColorAt (r0 / r1, Qt::transparent); - } - } - - switch (extend) { - case CAIRO_EXTEND_NONE: - case CAIRO_EXTEND_PAD: - grad->setSpread(QGradient::PadSpread); - - grad->setColorAt (0.0, Qt::transparent); - grad->setColorAt (1.0, Qt::transparent); - break; - - case CAIRO_EXTEND_REFLECT: - grad->setSpread(QGradient::ReflectSpread); - break; - - case CAIRO_EXTEND_REPEAT: - grad->setSpread(QGradient::RepeatSpread); - break; - } - - for (unsigned int i = 0; i < gpat->n_stops; i++) { - int index = i; - if (reverse_stops) - index = gpat->n_stops - i - 1; - - double offset = gpat->stops[i].offset; - QColor color; - color.setRgbF (gpat->stops[i].color.red, - gpat->stops[i].color.green, - gpat->stops[i].color.blue, - gpat->stops[i].color.alpha); - - if (emulate_reflect) { - offset = offset / 2.0; - grad->setColorAt (1.0 - offset, color); - } - - grad->setColorAt (offset, color); - } - - mBrush = QBrush(*grad); - - delete grad; - } - - if (mBrush.style() != Qt::NoBrush && - pattern->type != CAIRO_PATTERN_TYPE_SOLID && - ! _cairo_matrix_is_identity (&pattern->matrix)) - { - cairo_matrix_t pm = pattern->matrix; - cairo_status_t status = cairo_matrix_invert (&pm); - assert (status == CAIRO_STATUS_SUCCESS); - mBrush.setMatrix (_qmatrix_from_cairo_matrix (pm)); - } - } - - ~PatternToBrushConverter () __attribute__ ((noinline)){ - if (mAcquiredImageParent) - _cairo_surface_release_source_image (mAcquiredImageParent, mAcquiredImage, mAcquiredImageExtra); - } - - operator QBrush& () { - return mBrush; - } - - QBrush mBrush; - - private: - cairo_surface_t *mAcquiredImageParent; - cairo_image_surface_t *mAcquiredImage; - void *mAcquiredImageExtra; -}; - -struct PatternToPenConverter { - PatternToPenConverter (const cairo_pattern_t *source, - const cairo_stroke_style_t *style) : - mBrushConverter(source) - { - Qt::PenJoinStyle join = Qt::MiterJoin; - Qt::PenCapStyle cap = Qt::SquareCap; - - switch (style->line_cap) { - case CAIRO_LINE_CAP_BUTT: - cap = Qt::FlatCap; - break; - case CAIRO_LINE_CAP_ROUND: - cap = Qt::RoundCap; - break; - case CAIRO_LINE_CAP_SQUARE: - cap = Qt::SquareCap; - break; - } - - switch (style->line_join) { - case CAIRO_LINE_JOIN_MITER: - join = Qt::MiterJoin; - break; - case CAIRO_LINE_JOIN_ROUND: - join = Qt::RoundJoin; - break; - case CAIRO_LINE_JOIN_BEVEL: - join = Qt::BevelJoin; - break; - } - - mPen = QPen(mBrushConverter, style->line_width, Qt::SolidLine, cap, join); - mPen.setMiterLimit (style->miter_limit); - - if (style->dash && style->num_dashes) { - Qt::PenStyle pstyle = Qt::NoPen; - - if (style->num_dashes == 2) { - if ((style->dash[0] == style->line_width && - style->dash[1] == style->line_width && style->line_width <= 2.0) || - (style->dash[0] == 0.0 && - style->dash[1] == style->line_width * 2 && cap == Qt::RoundCap)) - { - pstyle = Qt::DotLine; - } else if (style->dash[0] == style->line_width * DASH_LENGTH && - style->dash[1] == style->line_width * DASH_LENGTH && - cap == Qt::FlatCap) - { - pstyle = Qt::DashLine; - } - } - - if (pstyle != Qt::NoPen) { - mPen.setStyle(pstyle); - return; - } - - unsigned int odd_dash = style->num_dashes % 2; - - QVector<qreal> dashes (odd_dash ? style->num_dashes * 2 : style->num_dashes); - for (unsigned int i = 0; i < odd_dash+1; i++) { - for (unsigned int j = 0; j < style->num_dashes; j++) { - // In Qt, the dash lengths are given in units of line width, whereas - // in cairo, they are in user-space units. We'll always apply the CTM, - // so all we have to do here is divide cairo's dash lengths by the line - // width. - dashes.append (style->dash[j] / style->line_width); - } - } - - mPen.setDashPattern(dashes); - mPen.setDashOffset(style->dash_offset / style->line_width); - } - } - - ~PatternToPenConverter() { } - - operator QPen& () { - return mPen; - } - - QPen mPen; - PatternToBrushConverter mBrushConverter; -}; - -/* - * Core drawing operations - */ - -static bool -_cairo_qt_fast_fill (cairo_qt_surface_t *qs, - const cairo_pattern_t *source, - const cairo_path_fixed_t *path = NULL, - cairo_fill_rule_t fill_rule = CAIRO_FILL_RULE_WINDING, - double tolerance = 0.0, - cairo_antialias_t antialias = CAIRO_ANTIALIAS_NONE) -{ -#if ENABLE_FAST_FILL - QImage *qsSrc_image = NULL; - QPixmap *qsSrc_pixmap = NULL; - std::auto_ptr<QImage> qsSrc_image_d; - - - if (source->type == CAIRO_PATTERN_TYPE_SURFACE) { - cairo_surface_pattern_t *spattern = (cairo_surface_pattern_t*) source; - if (spattern->surface->type == CAIRO_SURFACE_TYPE_QT) { - cairo_qt_surface_t *p = (cairo_qt_surface_t*) spattern->surface; - - qsSrc_image = p->image; - qsSrc_pixmap = p->pixmap; - } else if (spattern->surface->type == CAIRO_SURFACE_TYPE_IMAGE) { - cairo_image_surface_t *p = (cairo_image_surface_t*) spattern->surface; - qsSrc_image = new QImage((const uchar*) p->data, - p->width, - p->height, - p->stride, - _qimage_format_from_cairo_format(p->format)); - qsSrc_image_d.reset(qsSrc_image); - } - } - - if (!qsSrc_image && !qsSrc_pixmap) - return false; - - // We can only drawTiledPixmap; there's no drawTiledImage - if (! qsSrc_pixmap && - (source->extend == CAIRO_EXTEND_REPEAT || - source->extend == CAIRO_EXTEND_REFLECT)) - { - return false; - } - - QMatrix sourceMatrix = _qmatrix_from_cairo_matrix (source->matrix); - - // We can draw this faster by clipping and calling drawImage/drawPixmap. - // Use our own clipping function so that we can get the - // region handling to end up with the fastest possible clip. - // - // XXX Antialiasing will fail pretty hard here, since we can't clip with AA - // with QPainter. - qs->p->save(); - - if (path) { - cairo_int_status_t status; - - cairo_clip_t clip, old_clip = qs->clipper.clip; - - qs->clipper.clip = _cairo_clip_copy (&clip); - status = (cairo_int_status_t) _cairo_clip_clip (&clip, - path, - fill_rule, - tolerance, - antialias); - if (unlikely (status)) { - qs->p->restore(); - return false; - } - - status = _cairo_qt_surface_set_clip (qs, &clip); - if (unlikely (status)) { - qs->p->restore(); - return false; - } - - _cairo_clip_reset (&clip); - qs->clipper.clip = old_clip; - } - - qs->p->setWorldMatrix (sourceMatrix.inverted(), true); - - switch (source->extend) { - case CAIRO_EXTEND_REPEAT: - // XXX handle reflect by tiling 4 times first - case CAIRO_EXTEND_REFLECT: { - assert (qsSrc_pixmap); - - // Render the tiling to cover the entire destination window (because - // it'll be clipped). Transform the window rect by the inverse - // of the current world transform so that the device coordinates - // end up as the right thing. - QRectF dest = qs->p->worldTransform().inverted().mapRect(QRectF(qs->window)); - QPointF origin = sourceMatrix.map(QPointF(0.0, 0.0)); - - qs->p->drawTiledPixmap (dest, *qsSrc_pixmap, origin); - } - break; - case CAIRO_EXTEND_NONE: - case CAIRO_EXTEND_PAD: // XXX not exactly right, but good enough - default: - if (qsSrc_image) - qs->p->drawImage (0, 0, *qsSrc_image); - else if (qsSrc_pixmap) - qs->p->drawPixmap (0, 0, *qsSrc_pixmap); - break; - } - - qs->p->restore(); - - return true; -#else - return false; -#endif -} - -static cairo_int_status_t -_cairo_qt_surface_paint (void *abstract_surface, - cairo_operator_t op, - const cairo_pattern_t *source, - const cairo_clip_t *clip) -{ - cairo_qt_surface_t *qs = (cairo_qt_surface_t *) abstract_surface; - cairo_int_status_t status; - - D(fprintf(stderr, "q[%p] paint op:%s\n", abstract_surface, _opstr(op))); - - if (! _op_is_supported (qs, op)) - return _cairo_surface_fallback_paint (abstract_surface, op, source, clip); - - status = _cairo_qt_surface_set_clip (qs, clip); - if (unlikely (status)) - return status; - - if (qs->supports_porter_duff) - qs->p->setCompositionMode (_qpainter_compositionmode_from_cairo_op (op)); - - if (! _cairo_qt_fast_fill (qs, source)) { - PatternToBrushConverter brush (source); - qs->p->fillRect (qs->window, brush); - } - - if (qs->supports_porter_duff) - qs->p->setCompositionMode (QPainter::CompositionMode_SourceOver); - - return CAIRO_INT_STATUS_SUCCESS; -} - -static cairo_int_status_t -_cairo_qt_surface_fill (void *abstract_surface, - cairo_operator_t op, - const cairo_pattern_t *source, - const cairo_path_fixed_t *path, - cairo_fill_rule_t fill_rule, - double tolerance, - cairo_antialias_t antialias, - const cairo_clip_t *clip) -{ - cairo_qt_surface_t *qs = (cairo_qt_surface_t *) abstract_surface; - - D(fprintf(stderr, "q[%p] fill op:%s\n", abstract_surface, _opstr(op))); - - if (! _op_is_supported (qs, op)) - return _cairo_surface_fallback_fill (abstract_surface, op, - source, path, fill_rule, - tolerance, antialias, clip); - - cairo_int_status_t status = _cairo_qt_surface_set_clip (qs, clip); - if (unlikely (status)) - return status; - - if (qs->supports_porter_duff) - qs->p->setCompositionMode (_qpainter_compositionmode_from_cairo_op (op)); - - // XXX Qt4.3, 4.4 misrenders some complex paths if antialiasing is - // enabled - //qs->p->setRenderHint (QPainter::Antialiasing, antialias == CAIRO_ANTIALIAS_NONE ? false : true); - qs->p->setRenderHint (QPainter::SmoothPixmapTransform, source->filter != CAIRO_FILTER_FAST); - - if (! _cairo_qt_fast_fill (qs, source, - path, fill_rule, tolerance, antialias)) - { - PatternToBrushConverter brush(source); - qs->p->fillPath (path_to_qt (path, fill_rule), brush); - } - - if (qs->supports_porter_duff) - qs->p->setCompositionMode (QPainter::CompositionMode_SourceOver); - - return CAIRO_INT_STATUS_SUCCESS; -} - -static cairo_int_status_t -_cairo_qt_surface_stroke (void *abstract_surface, - cairo_operator_t op, - const cairo_pattern_t *source, - const cairo_path_fixed_t *path, - const cairo_stroke_style_t *style, - const cairo_matrix_t *ctm, - const cairo_matrix_t *ctm_inverse, - double tolerance, - cairo_antialias_t antialias, - const cairo_clip_t *clip) -{ - cairo_qt_surface_t *qs = (cairo_qt_surface_t *) abstract_surface; - - D(fprintf(stderr, "q[%p] stroke op:%s\n", abstract_surface, _opstr(op))); - - if (! _op_is_supported (qs, op)) - return _cairo_surface_fallback_stroke (abstract_surface, op, - source, path, style, ctm, - ctm_inverse, tolerance, - antialias, clip); - - cairo_int_status_t int_status = _cairo_qt_surface_set_clip (qs, clip); - if (unlikely (int_status)) - return int_status; - - QMatrix savedMatrix = qs->p->worldMatrix(); - - if (qs->supports_porter_duff) - qs->p->setCompositionMode (_qpainter_compositionmode_from_cairo_op (op)); - - qs->p->setWorldMatrix (_qmatrix_from_cairo_matrix (*ctm), true); - // XXX Qt4.3, 4.4 misrenders some complex paths if antialiasing is - // enabled - //qs->p->setRenderHint (QPainter::Antialiasing, antialias == CAIRO_ANTIALIAS_NONE ? false : true); - qs->p->setRenderHint (QPainter::SmoothPixmapTransform, source->filter != CAIRO_FILTER_FAST); - - PatternToPenConverter pen(source, style); - - qs->p->setPen(pen); - qs->p->drawPath(path_to_qt (path, ctm_inverse)); - qs->p->setPen(Qt::black); - - qs->p->setWorldMatrix (savedMatrix, false); - - if (qs->supports_porter_duff) - qs->p->setCompositionMode (QPainter::CompositionMode_SourceOver); - - return CAIRO_INT_STATUS_SUCCESS; -} - -static cairo_int_status_t -_cairo_qt_surface_show_glyphs (void *abstract_surface, - cairo_operator_t op, - const cairo_pattern_t *source, - cairo_glyph_t *glyphs, - int num_glyphs, - cairo_scaled_font_t *scaled_font, - const cairo_clip_t *clip) -{ -#if ((QT_VERSION >= QT_VERSION_CHECK(4, 7, 0)) || defined(QT_GLYPHS_API_BACKPORT)) && 0 - cairo_qt_surface_t *qs = (cairo_qt_surface_t *) abstract_surface; - - // pick out the colour to use from the cairo source - cairo_solid_pattern_t *solid = (cairo_solid_pattern_t*) source; - cairo_scaled_glyph_t* glyph; - // documentation says you have to freeze the cache, but I don't believe it - _cairo_scaled_font_freeze_cache(scaled_font); - - QColor tempColour(solid->color.red * 255, solid->color.green * 255, solid->color.blue * 255); - QVarLengthArray<QPointF> positions(num_glyphs); - QVarLengthArray<unsigned int> glyphss(num_glyphs); - FT_Face face = cairo_ft_scaled_font_lock_face (scaled_font); - const FT_Size_Metrics& ftMetrics = face->size->metrics; - QFont font(face->family_name); - font.setStyleStrategy(QFont::NoFontMerging); - font.setBold(face->style_flags & FT_STYLE_FLAG_BOLD); - font.setItalic(face->style_flags & FT_STYLE_FLAG_ITALIC); - font.setKerning(face->face_flags & FT_FACE_FLAG_KERNING); - font.setPixelSize(ftMetrics.y_ppem); - cairo_ft_scaled_font_unlock_face(scaled_font); - qs->p->setFont(font); - qs->p->setPen(tempColour); - for (int currentGlyph = 0; currentGlyph < num_glyphs; currentGlyph++) { - positions[currentGlyph].setX(glyphs[currentGlyph].x); - positions[currentGlyph].setY(glyphs[currentGlyph].y); - glyphss[currentGlyph] = glyphs[currentGlyph].index; - } - qt_draw_glyphs(qs->p, glyphss.data(), positions.data(), num_glyphs); - _cairo_scaled_font_thaw_cache(scaled_font); - return CAIRO_INT_STATUS_SUCCESS; -#else - return _cairo_surface_fallback_glyphs (abstract_surface, op, - source, glyphs, num_glyphs, - scaled_font, clip); -#endif -} - -static cairo_int_status_t -_cairo_qt_surface_mask (void *abstract_surface, - cairo_operator_t op, - const cairo_pattern_t *source, - const cairo_pattern_t *mask, - const cairo_clip_t *clip) -{ - cairo_qt_surface_t *qs = (cairo_qt_surface_t *) abstract_surface; - - D(fprintf(stderr, "q[%p] mask op:%s\n", abstract_surface, _opstr(op))); - - if (qs->p && mask->type == CAIRO_PATTERN_TYPE_SOLID) { - cairo_solid_pattern_t *solid_mask = (cairo_solid_pattern_t *) mask; - cairo_int_status_t result; - - qs->p->setOpacity (solid_mask->color.alpha); - - result = _cairo_qt_surface_paint (abstract_surface, op, source, clip); - - qs->p->setOpacity (1.0); - - return result; - } - - // otherwise skip for now - return _cairo_surface_fallback_mask (abstract_surface, op, source, mask, clip); -} - -static cairo_status_t -_cairo_qt_surface_mark_dirty (void *abstract_surface, - int x, int y, - int width, int height) -{ - cairo_qt_surface_t *qs = (cairo_qt_surface_t *) abstract_surface; - - if (qs->p && !(qs->image || qs->pixmap)) - qs->p->save (); - - return CAIRO_STATUS_SUCCESS; -} - -/* - * Backend struct - */ - -static const cairo_surface_backend_t cairo_qt_surface_backend = { - CAIRO_SURFACE_TYPE_QT, - _cairo_qt_surface_finish, - - _cairo_default_context_create, /* XXX */ - - _cairo_qt_surface_create_similar, - NULL, /* similar image */ - _cairo_qt_surface_map_to_image, - _cairo_qt_surface_unmap_image, - - _cairo_surface_default_source, - _cairo_qt_surface_acquire_source_image, - _cairo_qt_surface_release_source_image, - NULL, /* snapshot */ - - NULL, /* copy_page */ - NULL, /* show_page */ - - _cairo_qt_surface_get_extents, - NULL, /* get_font_options */ - - NULL, /* flush */ - _cairo_qt_surface_mark_dirty, - - _cairo_qt_surface_paint, - _cairo_qt_surface_mask, - _cairo_qt_surface_stroke, - _cairo_qt_surface_fill, - NULL, /* fill_stroke */ - _cairo_qt_surface_show_glyphs -}; - -cairo_surface_t * -cairo_qt_surface_create (QPainter *painter) -{ - cairo_qt_surface_t *qs; - - qs = (cairo_qt_surface_t *) _cairo_malloc (sizeof(cairo_qt_surface_t)); - if (qs == NULL) - return _cairo_surface_create_in_error (_cairo_error (CAIRO_STATUS_NO_MEMORY)); - - memset (qs, 0, sizeof(cairo_qt_surface_t)); - - _cairo_surface_init (&qs->base, - &cairo_qt_surface_backend, - NULL, /* device */ - CAIRO_CONTENT_COLOR_ALPHA, - FALSE); /* is_vector */ - - _cairo_surface_clipper_init (&qs->clipper, - _cairo_qt_surface_clipper_intersect_clip_path); - - qs->p = painter; - if (qs->p->paintEngine()) - qs->supports_porter_duff = qs->p->paintEngine()->hasFeature(QPaintEngine::PorterDuff); - else - qs->supports_porter_duff = FALSE; - - // Save so that we can always get back to the original state - qs->p->save(); - - qs->window = painter->window(); - - D(fprintf(stderr, "qpainter_surface_create: window: [%d %d %d %d] pd:%d\n", - qs->window.x(), qs->window.y(), qs->window.width(), qs->window.height(), - qs->supports_porter_duff)); - - return &qs->base; -} - -cairo_surface_t * -cairo_qt_surface_create_with_qimage (cairo_format_t format, - int width, - int height) -{ - cairo_qt_surface_t *qs; - - qs = (cairo_qt_surface_t *) _cairo_malloc (sizeof(cairo_qt_surface_t)); - if (qs == NULL) - return _cairo_surface_create_in_error (_cairo_error (CAIRO_STATUS_NO_MEMORY)); - - memset (qs, 0, sizeof(cairo_qt_surface_t)); - - _cairo_surface_init (&qs->base, - &cairo_qt_surface_backend, - NULL, /* device */ - _cairo_content_from_format (format), - FALSE); /* is_vector */ - - _cairo_surface_clipper_init (&qs->clipper, - _cairo_qt_surface_clipper_intersect_clip_path); - - - QImage *image = new QImage (width, height, - _qimage_format_from_cairo_format (format)); - - qs->image = image; - - if (!image->isNull()) { - qs->p = new QPainter(image); - qs->supports_porter_duff = qs->p->paintEngine()->hasFeature(QPaintEngine::PorterDuff); - } - - qs->image_equiv = cairo_image_surface_create_for_data (image->bits(), - format, - width, height, - image->bytesPerLine()); - - qs->window = QRect(0, 0, width, height); - - D(fprintf(stderr, "qpainter_surface_create: qimage: [%d %d %d %d] pd:%d\n", - qs->window.x(), qs->window.y(), qs->window.width(), qs->window.height(), - qs->supports_porter_duff)); - - return &qs->base; -} - -cairo_surface_t * -cairo_qt_surface_create_with_qpixmap (cairo_content_t content, - int width, - int height) -{ - cairo_qt_surface_t *qs; - - if ((content & CAIRO_CONTENT_COLOR) == 0) - return _cairo_surface_create_in_error (_cairo_error (CAIRO_STATUS_INVALID_CONTENT)); - - qs = (cairo_qt_surface_t *) _cairo_malloc (sizeof(cairo_qt_surface_t)); - if (qs == NULL) - return _cairo_surface_create_in_error (_cairo_error (CAIRO_STATUS_NO_MEMORY)); - - memset (qs, 0, sizeof(cairo_qt_surface_t)); - - QPixmap *pixmap = new QPixmap (width, height); - if (pixmap == NULL) { - free (qs); - return _cairo_surface_create_in_error (_cairo_error (CAIRO_STATUS_NO_MEMORY)); - } - - // By default, a QPixmap is opaque; however, if it's filled - // with a color with a transparency component, it is converted - // to a format that preserves transparency. - if (content == CAIRO_CONTENT_COLOR_ALPHA) - pixmap->fill(Qt::transparent); - - _cairo_surface_init (&qs->base, - &cairo_qt_surface_backend, - NULL, /* device */ - content, - FALSE); /* is_vector */ - - _cairo_surface_clipper_init (&qs->clipper, - _cairo_qt_surface_clipper_intersect_clip_path); - - qs->pixmap = pixmap; - - if (!pixmap->isNull()) { - qs->p = new QPainter(pixmap); - qs->supports_porter_duff = qs->p->paintEngine()->hasFeature(QPaintEngine::PorterDuff); - } - - qs->window = QRect(0, 0, width, height); - - D(fprintf(stderr, "qpainter_surface_create: qpixmap: [%d %d %d %d] pd:%d\n", - qs->window.x(), qs->window.y(), qs->window.width(), qs->window.height(), - qs->supports_porter_duff)); - - return &qs->base; -} - -/** - * _cairo_surface_is_qt: - * @surface: a #cairo_surface_t - * - * Checks if a surface is a #cairo_qt_surface_t - * - * Return value: True if the surface is an qt surface - **/ -static inline cairo_bool_t -_cairo_surface_is_qt (cairo_surface_t *surface) -{ - return surface->backend == &cairo_qt_surface_backend; -} - -QPainter * -cairo_qt_surface_get_qpainter (cairo_surface_t *surface) -{ - cairo_qt_surface_t *qs = (cairo_qt_surface_t*) surface; - - /* Throw an error for a non-qt surface */ - if (! _cairo_surface_is_qt (surface)) { - _cairo_error_throw (CAIRO_STATUS_SURFACE_TYPE_MISMATCH); - return NULL; - } - - return qs->p; -} - -QImage * -cairo_qt_surface_get_qimage (cairo_surface_t *surface) -{ - cairo_qt_surface_t *qs = (cairo_qt_surface_t*) surface; - - /* Throw an error for a non-qt surface */ - if (! _cairo_surface_is_qt (surface)) { - _cairo_error_throw (CAIRO_STATUS_SURFACE_TYPE_MISMATCH); - return NULL; - } - - return qs->image; -} - -cairo_surface_t * -cairo_qt_surface_get_image (cairo_surface_t *surface) -{ - cairo_qt_surface_t *qs = (cairo_qt_surface_t*) surface; - - /* Throw an error for a non-qt surface */ - if (! _cairo_surface_is_qt (surface)) { - return _cairo_surface_create_in_error (_cairo_error (CAIRO_STATUS_SURFACE_TYPE_MISMATCH)); - } - - return qs->image_equiv; -} - -/* - * TODO: - * - * - Figure out why QBrush isn't working with non-repeated images - * - * - Correct repeat mode; right now, every surface source is EXTEND_REPEAT - * - implement EXTEND_NONE (?? probably need to clip to the extents of the source) - * - implement EXTEND_REFLECT (create temporary and copy 4x, then EXTEND_REPEAT that) - * - * - stroke-image failure - * - * - Implement mask() with non-solid masks (probably will need to use a temporary and use IN) - * - * - Implement gradient sources - * - * - Make create_similar smarter -- create QPixmaps in more circumstances - * (e.g. if the pixmap can have alpha) - * - * - Implement show_glyphs() in terms of Qt - * - */ diff --git a/gfx/cairo/cairo/src/cairo-qt.h b/gfx/cairo/cairo/src/cairo-qt.h deleted file mode 100644 index c20bbb18d0..0000000000 --- a/gfx/cairo/cairo/src/cairo-qt.h +++ /dev/null @@ -1,85 +0,0 @@ -/* -*- Mode: c; c-basic-offset: 4; indent-tabs-mode: t; tab-width: 8; -*- */ -/* cairo - a vector graphics library with display and print output - * - * Copyright © 2008 Mozilla Corporation - * - * This library is free software; you can redistribute it and/or - * modify it either under the terms of the GNU Lesser General Public - * License version 2.1 as published by the Free Software Foundation - * (the "LGPL") or, at your option, under the terms of the Mozilla - * Public License Version 1.1 (the "MPL"). If you do not alter this - * notice, a recipient may use your version of this file under either - * the MPL or the LGPL. - * - * You should have received a copy of the LGPL along with this library - * in the file COPYING-LGPL-2.1; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Suite 500, Boston, MA 02110-1335, USA - * You should have received a copy of the MPL along with this library - * in the file COPYING-MPL-1.1 - * - * The contents of this file are subject to the Mozilla Public License - * Version 1.1 (the "License"); you may not use this file except in - * compliance with the License. You may obtain a copy of the License at - * http://www.mozilla.org/MPL/ - * - * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY - * OF ANY KIND, either express or implied. See the LGPL or the MPL for - * the specific language governing rights and limitations. - * - * The Original Code is the cairo graphics library. - * - * The Initial Developer of the Original Code is Mozilla Corporation. - * - * Contributor(s): - * Vladimir Vukicevic <vladimir@mozilla.com> - */ - -#ifndef CAIRO_QT_H -#define CAIRO_QT_H - -#include "cairo.h" - -#if CAIRO_HAS_QT_SURFACE - -#include <QtGui/QImage> -#include <QtGui/QPainter> - -CAIRO_BEGIN_DECLS - -cairo_public cairo_surface_t * -cairo_qt_surface_create (QPainter *painter); - -cairo_public cairo_surface_t * -cairo_qt_surface_create_with_qimage (cairo_format_t format, - int width, - int height); - -cairo_public cairo_surface_t * -cairo_qt_surface_create_with_qpixmap (cairo_content_t content, - int width, - int height); - -cairo_public QPainter * -cairo_qt_surface_get_qpainter (cairo_surface_t *surface); - -/* XXX needs hooking to generic surface layer, my vote is for -cairo_public cairo_surface_t * -cairo_surface_map_image (cairo_surface_t *surface); -cairo_public void -cairo_surface_unmap_image (cairo_surface_t *surface, cairo_surface_t *image); -*/ -cairo_public cairo_surface_t * -cairo_qt_surface_get_image (cairo_surface_t *surface); - -cairo_public QImage * -cairo_qt_surface_get_qimage (cairo_surface_t *surface); - -CAIRO_END_DECLS - -#else /* CAIRO_HAS_QT_SURFACE */ - -# error Cairo was not compiled with support for the Qt backend - -#endif /* CAIRO_HAS_QT_SURFACE */ - -#endif /* CAIRO_QT_H */ diff --git a/gfx/cairo/cairo/src/cairo-quartz-font.c b/gfx/cairo/cairo/src/cairo-quartz-font.c index 740ca108e7..f95c54d0f7 100644 --- a/gfx/cairo/cairo/src/cairo-quartz-font.c +++ b/gfx/cairo/cairo/src/cairo-quartz-font.c @@ -44,15 +44,14 @@ #include "cairo-error-private.h" +//#define DEBUG /* Uncomment this to get debug messages on the console. */ /** * SECTION:cairo-quartz-fonts * @Title: Quartz (CGFont) Fonts - * @Short_Description: Font support via CGFont on OS X + * @Short_Description: Font support via Core Text on Apple operating systems. * @See_Also: #cairo_font_face_t * - * The Quartz font backend is primarily used to render text on Apple - * MacOS X systems. The CGFont API is used for the internal - * implementation of the font backend methods. + * Provide support for font faces via Core Text. **/ /** @@ -64,121 +63,41 @@ * Since: 1.6 **/ -static CFDataRef (*CGFontCopyTableForTagPtr) (CGFontRef font, uint32_t tag) = NULL; - -/* CreateWithFontName exists in 10.5, but not in 10.4; CreateWithName isn't public in 10.4 */ -static CGFontRef (*CGFontCreateWithFontNamePtr) (CFStringRef) = NULL; -static CGFontRef (*CGFontCreateWithNamePtr) (const char *) = NULL; - -/* These aren't public before 10.5, and some have different names in 10.4 */ -static int (*CGFontGetUnitsPerEmPtr) (CGFontRef) = NULL; -static bool (*CGFontGetGlyphAdvancesPtr) (CGFontRef, const CGGlyph[], size_t, int[]) = NULL; -static bool (*CGFontGetGlyphBBoxesPtr) (CGFontRef, const CGGlyph[], size_t, CGRect[]) = NULL; -static CGRect (*CGFontGetFontBBoxPtr) (CGFontRef) = NULL; - -/* Not public, but present */ -static void (*CGFontGetGlyphsForUnicharsPtr) (CGFontRef, const UniChar[], const CGGlyph[], size_t) = NULL; -static void (*CGContextSetAllowsFontSmoothingPtr) (CGContextRef, bool) = NULL; +/* These are private functions */ static bool (*CGContextGetAllowsFontSmoothingPtr) (CGContextRef) = NULL; - -/* Not public in the least bit */ -static CGPathRef (*CGFontGetGlyphPathPtr) (CGFontRef fontRef, CGAffineTransform *textTransform, int unknown, CGGlyph glyph) = NULL; - -/* CTFontCreateWithGraphicsFont is not available until 10.5 */ -typedef const struct __CTFontDescriptor *CTFontDescriptorRef; -static CTFontRef (*CTFontCreateWithGraphicsFontPtr) (CGFontRef, CGFloat, const CGAffineTransform*, CTFontDescriptorRef) = NULL; -static CGPathRef (*CTFontCreatePathForGlyphPtr) (CTFontRef, CGGlyph, CGAffineTransform *) = NULL; -static double (*CTFontGetAdvancesForGlyphsPtr) (CTFontRef, CTFontOrientation, const CGGlyph*, CGSize *, CFIndex) = NULL; -static CGRect (*CTFontGetBoundingRectsForGlyphsPtr) (CTFontRef, CTFontOrientation, const CGGlyph*, CGRect *, CFIndex) = NULL; - -/* CGFontGetHMetrics isn't public, but the other functions are public/present in 10.5 */ -typedef struct { - int ascent; - int descent; - int leading; -} quartz_CGFontMetrics; -static quartz_CGFontMetrics* (*CGFontGetHMetricsPtr) (CGFontRef fontRef) = NULL; -static int (*CGFontGetAscentPtr) (CGFontRef fontRef) = NULL; -static int (*CGFontGetDescentPtr) (CGFontRef fontRef) = NULL; -static int (*CGFontGetLeadingPtr) (CGFontRef fontRef) = NULL; - #ifdef CAIRO_HAS_QUARTZ_ATSUFONTID -/* Not public anymore in 64-bits nor in 10.7 */ -static ATSFontRef (*FMGetATSFontRefFromFontPtr) (ATSUFontID iFont) = NULL; +static ATSFontRef (*FMGetATSFontRefFromFontPtr) (FMFont iFont) = NULL; #endif /* CAIRO_HAS_QUARTZ_ATSUFONTID */ static cairo_bool_t _cairo_quartz_font_symbol_lookup_done = FALSE; -static cairo_bool_t _cairo_quartz_font_symbols_present = FALSE; +/* Cairo's transformations assume a unit-scaled font. */ +static const CGFloat font_scale = 1.0; /* Defined in 10.11 */ #define CGGLYPH_MAX ((CGGlyph) 0xFFFE) /* kCGFontIndexMax */ #define CGGLYPH_INVALID ((CGGlyph) 0xFFFF) /* kCGFontIndexInvalid */ +#if MAC_OS_X_VERSION_MIN_REQUIRED < 1080 +#define FONT_ORIENTATION_HORIZONTAL kCTFontHorizontalOrientation +#define FONT_COLOR_GLYPHS kCTFontTraitColorGlyphs +#else +#define FONT_ORIENTATION_HORIZONTAL kCTFontOrientationHorizontal +#define FONT_COLOR_GLYPHS kCTFontColorGlyphsTrait +#endif + static void quartz_font_ensure_symbols(void) { if (_cairo_quartz_font_symbol_lookup_done) return; - CGFontCopyTableForTagPtr = dlsym(RTLD_DEFAULT, "CGFontCopyTableForTag"); - - /* Look for the 10.5 versions first */ - CGFontGetGlyphBBoxesPtr = dlsym(RTLD_DEFAULT, "CGFontGetGlyphBBoxes"); - if (!CGFontGetGlyphBBoxesPtr) - CGFontGetGlyphBBoxesPtr = dlsym(RTLD_DEFAULT, "CGFontGetGlyphBoundingBoxes"); - - CGFontGetGlyphsForUnicharsPtr = dlsym(RTLD_DEFAULT, "CGFontGetGlyphsForUnichars"); - if (!CGFontGetGlyphsForUnicharsPtr) - CGFontGetGlyphsForUnicharsPtr = dlsym(RTLD_DEFAULT, "CGFontGetGlyphsForUnicodes"); - - CGFontGetFontBBoxPtr = dlsym(RTLD_DEFAULT, "CGFontGetFontBBox"); - - /* We just need one of these two */ - CGFontCreateWithFontNamePtr = dlsym(RTLD_DEFAULT, "CGFontCreateWithFontName"); - CGFontCreateWithNamePtr = dlsym(RTLD_DEFAULT, "CGFontCreateWithName"); - - /* These have the same name in 10.4 and 10.5 */ - CGFontGetUnitsPerEmPtr = dlsym(RTLD_DEFAULT, "CGFontGetUnitsPerEm"); - CGFontGetGlyphAdvancesPtr = dlsym(RTLD_DEFAULT, "CGFontGetGlyphAdvances"); - - /* - * Some Tiger systems have a partial version of CoreText, which - * has incompatible signatures: CTFontCreateWithGraphicsFont - * accepts a double for the size argument even on i386 and all - * functions omit the CTFontOrientation arguments. Since the 10.4 - * CoreText library does not provide the CTFontCreatePathForGlyph - * symbol, use it to determine whether to use CoreText at all. - */ - CTFontCreatePathForGlyphPtr = dlsym(RTLD_DEFAULT, "CTFontCreatePathForGlyph"); - if (CTFontCreatePathForGlyphPtr) { - CTFontCreateWithGraphicsFontPtr = dlsym(RTLD_DEFAULT, "CTFontCreateWithGraphicsFont"); - CTFontGetAdvancesForGlyphsPtr = dlsym(RTLD_DEFAULT, "CTFontGetAdvancesForGlyphs"); - CTFontGetBoundingRectsForGlyphsPtr = dlsym(RTLD_DEFAULT, "CTFontGetBoundingRectsForGlyphs"); - } else { - CGFontGetGlyphPathPtr = dlsym(RTLD_DEFAULT, "CGFontGetGlyphPath"); - } - - CGFontGetHMetricsPtr = dlsym(RTLD_DEFAULT, "CGFontGetHMetrics"); - CGFontGetAscentPtr = dlsym(RTLD_DEFAULT, "CGFontGetAscent"); - CGFontGetDescentPtr = dlsym(RTLD_DEFAULT, "CGFontGetDescent"); - CGFontGetLeadingPtr = dlsym(RTLD_DEFAULT, "CGFontGetLeading"); - - CGContextGetAllowsFontSmoothingPtr = dlsym(RTLD_DEFAULT, "CGContextGetAllowsFontSmoothing"); - CGContextSetAllowsFontSmoothingPtr = dlsym(RTLD_DEFAULT, "CGContextSetAllowsFontSmoothing"); + CGContextGetAllowsFontSmoothingPtr = + dlsym (RTLD_DEFAULT, "CGContextGetAllowsFontSmoothing"); #ifdef CAIRO_HAS_QUARTZ_ATSUFONTID FMGetATSFontRefFromFontPtr = dlsym(RTLD_DEFAULT, "FMGetATSFontRefFromFont"); #endif /* CAIRO_HAS_QUARTZ_ATSUFONTID */ - if ((CGFontCreateWithFontNamePtr || CGFontCreateWithNamePtr) && - CGFontGetGlyphBBoxesPtr && - CGFontGetGlyphsForUnicharsPtr && - CGFontGetUnitsPerEmPtr && - CGFontGetGlyphAdvancesPtr && - ((CTFontCreateWithGraphicsFontPtr && CTFontCreatePathForGlyphPtr) || CGFontGetGlyphPathPtr) && - (CGFontGetHMetricsPtr || (CGFontGetAscentPtr && CGFontGetDescentPtr && CGFontGetLeadingPtr))) - _cairo_quartz_font_symbols_present = TRUE; - _cairo_quartz_font_symbol_lookup_done = TRUE; } @@ -187,13 +106,13 @@ typedef struct _cairo_quartz_scaled_font cairo_quartz_scaled_font_t; struct _cairo_quartz_scaled_font { cairo_scaled_font_t base; + CTFontRef ctFont; }; struct _cairo_quartz_font_face { cairo_font_face_t base; CGFontRef cgFont; - CTFontRef ctFont; }; /* @@ -206,14 +125,10 @@ _cairo_quartz_font_face_create_for_toy (cairo_toy_font_face_t *toy_face, { const char *family; char *full_name; - CFStringRef cgFontName = NULL; + CFStringRef FontName = NULL; CGFontRef cgFont = NULL; int loop; - quartz_font_ensure_symbols(); - if (! _cairo_quartz_font_symbols_present) - return _cairo_error (CAIRO_STATUS_NO_MEMORY); - family = toy_face->family; full_name = _cairo_malloc (strlen (family) + 64); // give us a bit of room to tack on Bold, Oblique, etc. /* handle CSS-ish faces */ @@ -240,23 +155,19 @@ _cairo_quartz_font_face_create_for_toy (cairo_toy_font_face_t *toy_face, if (loop < 3 && (loop & 1) == 0) { if (toy_face->weight == CAIRO_FONT_WEIGHT_BOLD) - strcat (full_name, " Bold"); + strcat (full_name, "-Bold"); } if (loop < 3 && (loop & 2) == 0) { if (toy_face->slant == CAIRO_FONT_SLANT_ITALIC) - strcat (full_name, " Italic"); + strcat (full_name, "-Italic"); else if (toy_face->slant == CAIRO_FONT_SLANT_OBLIQUE) - strcat (full_name, " Oblique"); + strcat (full_name, "-Oblique"); } - if (CGFontCreateWithFontNamePtr) { - cgFontName = CFStringCreateWithCString (NULL, full_name, kCFStringEncodingASCII); - cgFont = CGFontCreateWithFontNamePtr (cgFontName); - CFRelease (cgFontName); - } else { - cgFont = CGFontCreateWithNamePtr (full_name); - } + FontName = CFStringCreateWithCString (NULL, full_name, kCFStringEncodingASCII); + cgFont = CGFontCreateWithFontName (FontName); + CFRelease (FontName); if (cgFont) break; @@ -268,7 +179,7 @@ _cairo_quartz_font_face_create_for_toy (cairo_toy_font_face_t *toy_face, } *font_face = cairo_quartz_font_face_create_for_cgfont (cgFont); - CGFontRelease (cgFont); + CFRelease (cgFont); return CAIRO_STATUS_SUCCESS; } @@ -278,15 +189,57 @@ _cairo_quartz_font_face_destroy (void *abstract_face) { cairo_quartz_font_face_t *font_face = (cairo_quartz_font_face_t*) abstract_face; - if (font_face->ctFont) - CFRelease (font_face->ctFont); - CGFontRelease (font_face->cgFont); return TRUE; } static const cairo_scaled_font_backend_t _cairo_quartz_scaled_font_backend; +#ifdef DEBUG +static void +_cairo_quartz_debug_font_characteristics (cairo_quartz_scaled_font_t *font) +{ + CGRect ct_bbox = CTFontGetBoundingBox (font->ctFont); + CGFloat ct_ascent = CTFontGetAscent (font->ctFont); + CGFloat ct_descent = CTFontGetDescent (font->ctFont); + CGFloat ct_leading = CTFontGetLeading (font->ctFont); + CGFloat ct_capheight = CTFontGetCapHeight (font->ctFont); + CGFloat ct_xheight = CTFontGetXHeight (font->ctFont); + char chars[] = "ymMW"; + CGGlyph glyphs[4]; + UniChar *utf16 = NULL; + CGSize ct_advances[4]; + CGRect ct_gbbox[4], ct_gobox[4], ct_rbbox, ct_robox; + double ct_radvance; + int converted; + cairo_status_t rv; + + rv = _cairo_utf8_to_utf16 (chars, 4, &utf16, &converted); + if (rv) return; + CTFontGetGlyphsForCharacters (font->ctFont, utf16, glyphs, 4); + free (utf16); + ct_rbbox = CTFontGetBoundingRectsForGlyphs (font->ctFont, FONT_ORIENTATION_HORIZONTAL, glyphs, ct_gbbox, 4); + ct_robox = CTFontGetOpticalBoundsForGlyphs (font->ctFont, glyphs, ct_gobox, 4, 0); + ct_radvance = CTFontGetAdvancesForGlyphs (font->ctFont, FONT_ORIENTATION_HORIZONTAL, glyphs, ct_advances, 4); + + fprintf (stderr, "\nCTFont Bounding Box: %f %f %f %f\nAscent %f Descent %f Leading %f Cap Height %f X-Height %f\n", + ct_bbox.origin.x, ct_bbox.origin.y, ct_bbox.size.width, ct_bbox.size.height, ct_ascent, ct_descent, + ct_leading, ct_capheight, ct_xheight); + fprintf (stderr, "CTFont string\n\t bounding box %f %f %f %f advance %f\n\toptical box %f %f %f %f\n\n", + ct_rbbox.origin.x, ct_rbbox.origin.y, ct_rbbox.size.width, ct_rbbox.size.height, ct_radvance, + ct_robox.origin.x, ct_robox.origin.y, ct_robox.size.width, ct_robox.size.height); + for (int i = 0; i < 4; ++i) + { + fprintf (stderr, "Character %c\n", chars[i]); + fprintf (stderr, "\tbox %f %f %f %f\n\toptical %f %f %f %f advance %f %f\n", + ct_gbbox[i].origin.x, ct_gbbox[i].origin.y, ct_gbbox[i].size.width, ct_gbbox[i].size.height, + ct_advances[i].width, ct_advances[i].height, + ct_gobox[i].origin.x, ct_gobox[i].origin.y, ct_gobox[i].size.width, ct_gobox[i].size.height); + } + fprintf (stderr, "\n"); +} +#endif + static cairo_status_t _cairo_quartz_font_face_scaled_font_create (void *abstract_face, const cairo_matrix_t *font_matrix, @@ -298,13 +251,9 @@ _cairo_quartz_font_face_scaled_font_create (void *abstract_face, cairo_quartz_scaled_font_t *font = NULL; cairo_status_t status; cairo_font_extents_t fs_metrics; - double ems; + CTFontRef ctFont; CGRect bbox; - quartz_font_ensure_symbols(); - if (!_cairo_quartz_font_symbols_present) - return _cairo_error (CAIRO_STATUS_NO_MEMORY); - font = _cairo_malloc (sizeof(cairo_quartz_scaled_font_t)); if (font == NULL) return _cairo_error (CAIRO_STATUS_NO_MEMORY); @@ -317,48 +266,29 @@ _cairo_quartz_font_face_scaled_font_create (void *abstract_face, if (status) goto FINISH; - ems = CGFontGetUnitsPerEmPtr (font_face->cgFont); - + ctFont = CTFontCreateWithGraphicsFont (font_face->cgFont, font_scale, NULL, NULL); /* initialize metrics */ - if (CGFontGetFontBBoxPtr && CGFontGetAscentPtr) { - fs_metrics.ascent = (CGFontGetAscentPtr (font_face->cgFont) / ems); - fs_metrics.descent = - (CGFontGetDescentPtr (font_face->cgFont) / ems); - fs_metrics.height = fs_metrics.ascent + fs_metrics.descent + - (CGFontGetLeadingPtr (font_face->cgFont) / ems); - - bbox = CGFontGetFontBBoxPtr (font_face->cgFont); - fs_metrics.max_x_advance = CGRectGetMaxX(bbox) / ems; - fs_metrics.max_y_advance = 0.0; - } else { - CGGlyph wGlyph; - UniChar u; - - quartz_CGFontMetrics *m; - m = CGFontGetHMetricsPtr (font_face->cgFont); - - /* On OX 10.4, GetHMetricsPtr sometimes returns NULL for unknown reasons */ - if (!m) { - status = _cairo_error(CAIRO_STATUS_NULL_POINTER); - goto FINISH; - } + fs_metrics.ascent = CTFontGetAscent (ctFont); + fs_metrics.descent = CTFontGetDescent (ctFont); + fs_metrics.height = fs_metrics.ascent + fs_metrics.descent + + CTFontGetLeading (ctFont); + + bbox = CTFontGetBoundingBox (ctFont); + fs_metrics.max_x_advance = CGRectGetMaxX(bbox); + fs_metrics.max_y_advance = 0.0; + font->ctFont = CFRetain (ctFont); + status = _cairo_scaled_font_set_metrics (&font->base, &fs_metrics); +#ifdef DEBUG + { + CFStringRef fontFullName = CTFontCopyFullName (ctFont); + const char* font_full_name = CFStringGetCStringPtr(fontFullName, kCFStringEncodingUTF8); - fs_metrics.ascent = (m->ascent / ems); - fs_metrics.descent = - (m->descent / ems); - fs_metrics.height = fs_metrics.ascent + fs_metrics.descent + (m->leading / ems); - - /* We kind of have to guess here; W's big, right? */ - u = (UniChar) 'W'; - CGFontGetGlyphsForUnicharsPtr (font_face->cgFont, &u, &wGlyph, 1); - if (wGlyph && CGFontGetGlyphBBoxesPtr (font_face->cgFont, &wGlyph, 1, &bbox)) { - fs_metrics.max_x_advance = CGRectGetMaxX(bbox) / ems; - fs_metrics.max_y_advance = 0.0; - } else { - fs_metrics.max_x_advance = 0.0; - fs_metrics.max_y_advance = 0.0; - } + fprintf (stderr, "Create scaled font %s with scale %f ascent %f, descent %f, height %f, x-advance %f\n", + font_full_name, fs_metrics.ascent, fs_metrics.descent, fs_metrics.height, + fs_metrics.max_x_advance); + _cairo_quartz_debug_font_characteristics (font); } - - status = _cairo_scaled_font_set_metrics (&font->base, &fs_metrics); +#endif FINISH: if (status != CAIRO_STATUS_SUCCESS) { @@ -377,6 +307,23 @@ const cairo_font_face_backend_t _cairo_quartz_font_face_backend = { _cairo_quartz_font_face_scaled_font_create }; +static inline cairo_quartz_font_face_t* +_cairo_quartz_font_face_create () +{ + cairo_quartz_font_face_t *font_face = + _cairo_malloc (sizeof (cairo_quartz_font_face_t)); + + if (!font_face) { + cairo_status_t ignore_status; + ignore_status = _cairo_error (CAIRO_STATUS_NO_MEMORY); + return (cairo_quartz_font_face_t *)&_cairo_font_face_nil; + } + + _cairo_font_face_init (&font_face->base, &_cairo_quartz_font_face_backend); + + return font_face; +} + /** * cairo_quartz_font_face_create_for_cgfont: * @font: a #CGFontRef obtained through a method external to cairo. @@ -393,26 +340,13 @@ const cairo_font_face_backend_t _cairo_quartz_font_face_backend = { cairo_font_face_t * cairo_quartz_font_face_create_for_cgfont (CGFontRef font) { - cairo_quartz_font_face_t *font_face; + cairo_quartz_font_face_t* font_face = _cairo_quartz_font_face_create (); - quartz_font_ensure_symbols(); - - font_face = _cairo_malloc (sizeof (cairo_quartz_font_face_t)); - if (!font_face) { - cairo_status_t ignore_status; - ignore_status = _cairo_error (CAIRO_STATUS_NO_MEMORY); - return (cairo_font_face_t *)&_cairo_font_face_nil; - } + if (cairo_font_face_status (&font_face->base)) + return &font_face->base; font_face->cgFont = CGFontRetain (font); - if (CTFontCreateWithGraphicsFontPtr) - font_face->ctFont = CTFontCreateWithGraphicsFontPtr (font, 1.0, NULL, NULL); - else - font_face->ctFont = NULL; - - _cairo_font_face_init (&font_face->base, &_cairo_quartz_font_face_backend); - return &font_face->base; } @@ -432,6 +366,8 @@ _cairo_quartz_scaled_to_face (void *abstract_font) static void _cairo_quartz_scaled_font_fini(void *abstract_font) { + cairo_quartz_scaled_font_t* font = (cairo_quartz_scaled_font_t*)abstract_font; + CFRelease (font->ctFont); } static inline CGGlyph @@ -446,67 +382,30 @@ _cairo_quartz_init_glyph_metrics (cairo_quartz_scaled_font_t *font, { cairo_int_status_t status = CAIRO_STATUS_SUCCESS; - cairo_quartz_font_face_t *font_face = _cairo_quartz_scaled_to_face(font); cairo_text_extents_t extents = {0, 0, 0, 0, 0, 0}; CGGlyph glyph = _cairo_quartz_scaled_glyph_index (scaled_glyph); - int advance; + CGSize advance; CGRect bbox; double xmin, ymin, xmax, ymax; if (unlikely (glyph == CGGLYPH_INVALID)) goto FAIL; - if (font_face->ctFont) { - CGSize advanceSize; - CTFontGetBoundingRectsForGlyphsPtr (font_face->ctFont, - kCTFontOrientationDefault, - &glyph, &bbox, 1); - - CTFontGetAdvancesForGlyphsPtr (font_face->ctFont, - kCTFontOrientationDefault, - &glyph, &advanceSize, 1); - - extents.x_advance = advanceSize.width; - extents.y_advance = advanceSize.height; - } else if (CGFontGetGlyphAdvancesPtr (font_face->cgFont, &glyph, 1, &advance) && - CGFontGetGlyphBBoxesPtr (font_face->cgFont, &glyph, 1, &bbox)) { - double emscale = CGFontGetUnitsPerEmPtr (font_face->cgFont); - - /* broken fonts like Al Bayan return incorrect bounds for some null - * characters,see https://bugzilla.mozilla.org/show_bug.cgi?id=534260 */ - if (unlikely (bbox.origin.x == -32767 && - bbox.origin.y == -32767 && - bbox.size.width == 65534 && - bbox.size.height == 65534)) { - bbox.origin.x = bbox.origin.y = 0; - bbox.size.width = bbox.size.height = 0; - } - - bbox = CGRectMake (bbox.origin.x / emscale, - bbox.origin.y / emscale, - bbox.size.width / emscale, - bbox.size.height / emscale); - - extents.x_advance = advance / emscale; - extents.y_advance = 0.0; - } else { - goto FAIL; - }; - - /* Should we want to always integer-align glyph extents, we can do so in this way */ -#if 0 - { - CGAffineTransform textMatrix; - textMatrix = CGAffineTransformMake (font->base.scale.xx, - -font->base.scale.yx, - -font->base.scale.xy, - font->base.scale.yy, - 0.0f, 0.0f); - - bbox = CGRectApplyAffineTransform (bbox, textMatrix); - bbox = CGRectIntegral (bbox); - bbox = CGRectApplyAffineTransform (bbox, CGAffineTransformInvert (textMatrix)); + CTFontGetAdvancesForGlyphs (font->ctFont, FONT_ORIENTATION_HORIZONTAL, &glyph, &advance, 1); + CTFontGetBoundingRectsForGlyphs (font->ctFont, FONT_ORIENTATION_HORIZONTAL, &glyph, &bbox, 1); + /* broken fonts like Al Bayan return incorrect bounds for some null characters, + see https://bugzilla.mozilla.org/show_bug.cgi?id=534260 */ + if (unlikely (bbox.origin.x == -32767 && + bbox.origin.y == -32767 && + bbox.size.width == 65534 && + bbox.size.height == 65534)) { + bbox.origin.x = bbox.origin.y = 0; + bbox.size.width = bbox.size.height = 0; } + +#ifdef DEBUG + fprintf (stderr, "[0x%04x] bbox: x %f y %f width %f height %f\n", glyph, + bbox.origin.x, bbox.origin.y, bbox.size.width, bbox.size.height); #endif xmin = CGRectGetMinX(bbox); @@ -518,10 +417,17 @@ _cairo_quartz_init_glyph_metrics (cairo_quartz_scaled_font_t *font, extents.y_bearing = - ymax; extents.width = xmax - xmin; extents.height = ymax - ymin; +/* At the necessary 1.0pt ctFont size some glyphs get a reduced + * advance that causes overlaps when scaled up. We can avoid that by + * using the width instead if it's wider. Since cairo doesn't support + * vertical font layout we don't do the same for y_advance. + */ + extents.x_advance = MAX(extents.width, advance.width); + extents.y_advance = advance.height; -#if 0 - fprintf (stderr, "[0x%04x] extents: bearings: %f %f dim: %f %f adv: %f\n\n", glyph, - extents.x_bearing, extents.y_bearing, extents.width, extents.height, extents.x_advance); +#ifdef DEBUG + fprintf (stderr, "[0x%04x] extents: bearings: %f %f dim: %f %f adv: %f %f\n\n", glyph, + extents.x_bearing, extents.y_bearing, extents.width, extents.height, extents.x_advance, extents.y_advance); #endif FAIL: @@ -577,7 +483,7 @@ _cairo_quartz_path_apply_func (void *info, const CGPathElement *el) _cairo_fixed_from_double(el->points[1].y), _cairo_fixed_from_double(el->points[2].x), _cairo_fixed_from_double(el->points[2].y)); - assert(!status); + assert(!status); break; case kCGPathElementCloseSubpath: status = _cairo_path_fixed_close_path (path); @@ -590,7 +496,6 @@ static cairo_int_status_t _cairo_quartz_init_glyph_path (cairo_quartz_scaled_font_t *font, cairo_scaled_glyph_t *scaled_glyph) { - cairo_quartz_font_face_t *font_face = _cairo_quartz_scaled_to_face(font); CGGlyph glyph = _cairo_quartz_scaled_glyph_index (scaled_glyph); CGAffineTransform textMatrix; CGPathRef glyphPath; @@ -608,11 +513,7 @@ _cairo_quartz_init_glyph_path (cairo_quartz_scaled_font_t *font, -font->base.scale.yy, 0, 0); - if (font_face->ctFont) { - glyphPath = CTFontCreatePathForGlyphPtr (font_face->ctFont, glyph, &textMatrix); - } else { - glyphPath = CGFontGetGlyphPathPtr (font_face->cgFont, &textMatrix, 0, glyph); - } + glyphPath = CTFontCreatePathForGlyph (font->ctFont, glyph, &textMatrix); if (!glyphPath) return CAIRO_INT_STATUS_UNSUPPORTED; @@ -632,30 +533,42 @@ _cairo_quartz_init_glyph_path (cairo_quartz_scaled_font_t *font, return CAIRO_STATUS_SUCCESS; } +static cairo_bool_t +_cairo_quartz_font_has_color_glyphs (void *abstract_font) +{ + cairo_quartz_scaled_font_t *face = (cairo_quartz_scaled_font_t*)abstract_font; + CTFontSymbolicTraits traits = CTFontGetSymbolicTraits (face->ctFont); + return traits & FONT_COLOR_GLYPHS; +} + static cairo_int_status_t _cairo_quartz_init_glyph_surface (cairo_quartz_scaled_font_t *font, - cairo_scaled_glyph_t *scaled_glyph) + cairo_scaled_glyph_t *scaled_glyph, + cairo_scaled_glyph_info_t info, + const cairo_color_t *fg_color) { cairo_int_status_t status = CAIRO_STATUS_SUCCESS; - - cairo_quartz_font_face_t *font_face = _cairo_quartz_scaled_to_face(font); - cairo_image_surface_t *surface = NULL; CGGlyph glyph = _cairo_quartz_scaled_glyph_index (scaled_glyph); - - int advance; - CGRect bbox; + cairo_text_extents_t metrics = scaled_glyph->fs_metrics; + CGRect bbox = CGRectMake (metrics.x_bearing, -(metrics.y_bearing + metrics.height), + metrics.width, metrics.height); double width, height; - double emscale = CGFontGetUnitsPerEmPtr (font_face->cgFont); - CGContextRef cgContext = NULL; CGAffineTransform textMatrix; CGRect glyphRect, glyphRectInt; CGPoint glyphOrigin; - - //fprintf (stderr, "scaled_glyph: %p surface: %p\n", scaled_glyph, scaled_glyph->surface); - + cairo_bool_t is_color = info & CAIRO_SCALED_GLYPH_INFO_COLOR_SURFACE; + cairo_format_t format = is_color ? CAIRO_FORMAT_ARGB32 : CAIRO_FORMAT_A8; + +#ifdef DEBUG + fprintf (stderr, "[0x%04x] bearing: %f %f width %f height %f advances %f %f\n", + glyph, metrics.x_bearing, metrics.y_bearing, metrics.width, metrics.height, + metrics.x_advance, metrics.y_advance); + fprintf (stderr, "[0x%04x] bounds: origin %f %f, size %f %f\n", glyph, bbox.origin.x, + bbox.origin.y, bbox.size.width, bbox.size.height); +#endif /* Create blank 2x2 image if we don't have this character. * Maybe we should draw a better missing-glyph slug or something, * but this is ok for now. @@ -672,31 +585,33 @@ _cairo_quartz_init_glyph_surface (cairo_quartz_scaled_font_t *font, return CAIRO_STATUS_SUCCESS; } - if (!CGFontGetGlyphAdvancesPtr (font_face->cgFont, &glyph, 1, &advance) || - !CGFontGetGlyphBBoxesPtr (font_face->cgFont, &glyph, 1, &bbox)) - { +/* Note: Certain opentype color fonts have the ability to provide a + * mixture of color and not-color glyphs. The Core Text API doesn't + * expose a way to query individual glyphs and at the level that that + * API is written it's not supposed to matter. The following code will + * cheerfully render any glyph requested onto the image surface. If + * the font is capable of color and + * COLOR_SCALED_GLYPH_INFO_COLOR_SURFACE is set then you get back a + * CAIRO_FORMAT_ARGB32 surface. If a foreground color is provided then + * the glyph will be drawn in that color, otherwise it will be black. + */ + if (unlikely (is_color && ! _cairo_quartz_font_has_color_glyphs (font))) return CAIRO_INT_STATUS_UNSUPPORTED; - } /* scale(1,-1) * font->base.scale * scale(1,-1) */ textMatrix = CGAffineTransformMake (font->base.scale.xx, -font->base.scale.yx, -font->base.scale.xy, font->base.scale.yy, - 0, -0); - glyphRect = CGRectMake (bbox.origin.x / emscale, - bbox.origin.y / emscale, - bbox.size.width / emscale, - bbox.size.height / emscale); - - glyphRect = CGRectApplyAffineTransform (glyphRect, textMatrix); + 0, 0); + glyphRect = CGRectApplyAffineTransform (bbox, textMatrix); /* Round the rectangle outwards, so that we don't have to deal * with non-integer-pixel origins or dimensions. */ glyphRectInt = CGRectIntegral (glyphRect); -#if 0 +#ifdef DEBUG fprintf (stderr, "glyphRect[o]: %f %f %f %f\n", glyphRect.origin.x, glyphRect.origin.y, glyphRect.size.width, glyphRect.size.height); fprintf (stderr, "glyphRectInt: %f %f %f %f\n", @@ -705,70 +620,50 @@ _cairo_quartz_init_glyph_surface (cairo_quartz_scaled_font_t *font, glyphOrigin = glyphRectInt.origin; - //textMatrix = CGAffineTransformConcat (textMatrix, CGAffineTransformInvert (ctm)); - width = glyphRectInt.size.width; height = glyphRectInt.size.height; - //fprintf (stderr, "glyphRect[n]: %f %f %f %f\n", glyphRect.origin.x, glyphRect.origin.y, glyphRect.size.width, glyphRect.size.height); - - surface = (cairo_image_surface_t*) cairo_image_surface_create (CAIRO_FORMAT_A8, width, height); + surface = (cairo_image_surface_t*) cairo_image_surface_create (format, width, height); if (surface->base.status) return surface->base.status; if (surface->width != 0 && surface->height != 0) { - cgContext = CGBitmapContextCreate (surface->data, - surface->width, - surface->height, - 8, - surface->stride, - NULL, - kCGImageAlphaOnly); + CGColorSpaceRef colorspace = is_color ? CGColorSpaceCreateDeviceRGB () : NULL; + CGBitmapInfo bitinfo = is_color ? kCGBitmapByteOrder32Host | kCGImageAlphaPremultipliedFirst : kCGImageAlphaOnly; + + CGContextRef cgContext = CGBitmapContextCreate (surface->data, + surface->width, + surface->height, + 8, + surface->stride, + colorspace, + bitinfo); if (cgContext == NULL) { cairo_surface_destroy (&surface->base); return _cairo_error (CAIRO_STATUS_NO_MEMORY); } - CGContextSetFont (cgContext, font_face->cgFont); - CGContextSetFontSize (cgContext, 1.0); - CGContextSetTextMatrix (cgContext, textMatrix); - - switch (font->base.options.antialias) { - case CAIRO_ANTIALIAS_SUBPIXEL: - case CAIRO_ANTIALIAS_BEST: - CGContextSetShouldAntialias (cgContext, TRUE); - CGContextSetShouldSmoothFonts (cgContext, TRUE); - if (CGContextSetAllowsFontSmoothingPtr && - !CGContextGetAllowsFontSmoothingPtr (cgContext)) - CGContextSetAllowsFontSmoothingPtr (cgContext, TRUE); - break; - case CAIRO_ANTIALIAS_NONE: - CGContextSetShouldAntialias (cgContext, FALSE); - break; - case CAIRO_ANTIALIAS_GRAY: - case CAIRO_ANTIALIAS_GOOD: - case CAIRO_ANTIALIAS_FAST: - CGContextSetShouldAntialias (cgContext, TRUE); - CGContextSetShouldSmoothFonts (cgContext, FALSE); - break; - case CAIRO_ANTIALIAS_DEFAULT: - default: - /* Don't do anything */ - break; - } - + if (fg_color) + CGContextSetRGBFillColor (cgContext, fg_color->red, fg_color->green, fg_color->blue, fg_color->alpha); + _cairo_quartz_set_antialiasing (cgContext, font->base.options.antialias); CGContextSetAlpha (cgContext, 1.0); - CGContextShowGlyphsAtPoint (cgContext, - glyphOrigin.x, - glyphOrigin.y, &glyph, 1); - + CGContextTranslateCTM (cgContext, -glyphOrigin.x, -glyphOrigin.y); + CGContextConcatCTM (cgContext, textMatrix); + CTFontDrawGlyphs (font->ctFont, &glyph, &CGPointZero, 1, cgContext); CGContextRelease (cgContext); + CGColorSpaceRelease (colorspace); } cairo_surface_set_device_offset (&surface->base, - glyphOrigin.x, height + glyphOrigin.y); + cairo_surface_mark_dirty (&surface->base); - _cairo_scaled_glyph_set_surface (scaled_glyph, &font->base, surface); + if (is_color) + _cairo_scaled_glyph_set_color_surface (scaled_glyph, &font->base, surface, fg_color); + else + _cairo_scaled_glyph_set_surface (scaled_glyph, &font->base, surface); return status; } @@ -776,7 +671,8 @@ _cairo_quartz_init_glyph_surface (cairo_quartz_scaled_font_t *font, static cairo_int_status_t _cairo_quartz_scaled_glyph_init (void *abstract_font, cairo_scaled_glyph_t *scaled_glyph, - cairo_scaled_glyph_info_t info) + cairo_scaled_glyph_info_t info, + const cairo_color_t *foreground_color) { cairo_quartz_scaled_font_t *font = (cairo_quartz_scaled_font_t *) abstract_font; cairo_int_status_t status = CAIRO_STATUS_SUCCESS; @@ -787,8 +683,10 @@ _cairo_quartz_scaled_glyph_init (void *abstract_font, if (!status && (info & CAIRO_SCALED_GLYPH_INFO_PATH)) status = _cairo_quartz_init_glyph_path (font, scaled_glyph); - if (!status && (info & CAIRO_SCALED_GLYPH_INFO_SURFACE)) - status = _cairo_quartz_init_glyph_surface (font, scaled_glyph); + if (!status && (info & (CAIRO_SCALED_GLYPH_INFO_SURFACE | + CAIRO_SCALED_GLYPH_INFO_COLOR_SURFACE ))) + status = _cairo_quartz_init_glyph_surface (font, scaled_glyph, + info, foreground_color); return status; } @@ -798,13 +696,11 @@ _cairo_quartz_ucs4_to_index (void *abstract_font, uint32_t ucs4) { cairo_quartz_scaled_font_t *font = (cairo_quartz_scaled_font_t*) abstract_font; - cairo_quartz_font_face_t *ffont = _cairo_quartz_scaled_to_face(font); CGGlyph glyph[2]; UniChar utf16[2]; int len = _cairo_ucs4_to_utf16 (ucs4, utf16); - CGFontGetGlyphsForUnicharsPtr (ffont->cgFont, utf16, glyph, len); - + CTFontGetGlyphsForCharacters (font->ctFont, utf16, glyph, len); return glyph[0]; } @@ -815,11 +711,8 @@ _cairo_quartz_load_truetype_table (void *abstract_font, unsigned char *buffer, unsigned long *length) { - cairo_quartz_font_face_t *font_face = _cairo_quartz_scaled_to_face (abstract_font); - CFDataRef data = NULL; - - if (likely (CGFontCopyTableForTagPtr)) - data = CGFontCopyTableForTagPtr (font_face->cgFont, tag); + cairo_quartz_scaled_font_t *font = (cairo_quartz_scaled_font_t*) abstract_font; + CFDataRef data = CTFontCopyTable (font->ctFont, tag, kCTFontTableOptionNoOptions); if (!data) return CAIRO_INT_STATUS_UNSUPPORTED; @@ -848,9 +741,12 @@ static const cairo_scaled_font_backend_t _cairo_quartz_scaled_font_backend = { NULL, /* text_to_glyphs */ _cairo_quartz_ucs4_to_index, _cairo_quartz_load_truetype_table, - NULL, /* map_glyphs_to_unicode */ + NULL, /*index_to_ucs4*/ + NULL, /* is_synthetic */ + NULL, /* index_to_glyph_name */ + NULL, /* load_type1_data */ + _cairo_quartz_font_has_color_glyphs }; - /* * private methods that the quartz surface uses */ @@ -864,13 +760,42 @@ _cairo_quartz_scaled_font_get_cg_font_ref (cairo_scaled_font_t *abstract_font) } CTFontRef -_cairo_quartz_scaled_font_get_ct_font_ref (cairo_scaled_font_t *abstract_font) +_cairo_quartz_scaled_font_get_ct_font (cairo_scaled_font_t *abstract_font) { - cairo_quartz_font_face_t *ffont = _cairo_quartz_scaled_to_face(abstract_font); + cairo_quartz_scaled_font_t *font = (cairo_quartz_scaled_font_t*) abstract_font; - return ffont->ctFont; + return font->ctFont; } + void + _cairo_quartz_set_antialiasing (CGContextRef cgContext, cairo_antialias_t antialias) +{ + switch (antialias) { + case CAIRO_ANTIALIAS_SUBPIXEL: + case CAIRO_ANTIALIAS_BEST: + CGContextSetShouldAntialias (cgContext, TRUE); + CGContextSetShouldSmoothFonts (cgContext, TRUE); + quartz_font_ensure_symbols (); + if (CGContextGetAllowsFontSmoothingPtr && + !CGContextGetAllowsFontSmoothingPtr (cgContext)) + CGContextSetAllowsFontSmoothing (cgContext, TRUE); + break; + case CAIRO_ANTIALIAS_NONE: + CGContextSetShouldAntialias (cgContext, FALSE); + break; + case CAIRO_ANTIALIAS_GRAY: + case CAIRO_ANTIALIAS_GOOD: + case CAIRO_ANTIALIAS_FAST: + CGContextSetShouldAntialias (cgContext, TRUE); + CGContextSetShouldSmoothFonts (cgContext, FALSE); + break; + case CAIRO_ANTIALIAS_DEFAULT: + default: + /* Don't do anything */ + break; + } + +} /* * compat with old ATSUI backend */ diff --git a/gfx/cairo/cairo/src/cairo-quartz-image-surface.c b/gfx/cairo/cairo/src/cairo-quartz-image-surface.c index 30d92d6bed..48edbced3b 100644 --- a/gfx/cairo/cairo/src/cairo-quartz-image-surface.c +++ b/gfx/cairo/cairo/src/cairo-quartz-image-surface.c @@ -49,11 +49,14 @@ #define SURFACE_ERROR_INVALID_SIZE (_cairo_surface_create_in_error(_cairo_error(CAIRO_STATUS_INVALID_SIZE))) #define SURFACE_ERROR_INVALID_FORMAT (_cairo_surface_create_in_error(_cairo_error(CAIRO_STATUS_INVALID_FORMAT))) -static void -DataProviderReleaseCallback (void *image_info, const void *data, size_t size) -{ - free (image_info); -} +/** + * CAIRO_HAS_QUARTZ_IMAGE_SURFACE: + * + * Defined if the Quartz image surface backend is available. + * This macro can be used to conditionally compile backend-specific code. + * + * Since: 1.10 + **/ static cairo_surface_t * _cairo_quartz_image_surface_create_similar (void *asurface, @@ -87,8 +90,9 @@ _cairo_quartz_image_surface_finish (void *asurface) { cairo_quartz_image_surface_t *surface = (cairo_quartz_image_surface_t *) asurface; - CGImageRelease (surface->image); - cairo_surface_destroy ( (cairo_surface_t*) surface->imageSurface); + CGContextRelease (surface->cgContext); + if (surface->imageSurface) + cairo_surface_destroy ( (cairo_surface_t*) surface->imageSurface); return CAIRO_STATUS_SUCCESS; } @@ -134,47 +138,6 @@ _cairo_quartz_image_surface_get_extents (void *asurface, return TRUE; } -/* we assume some drawing happened to the image buffer; make sure it's - * represented in the CGImage on flush() - */ - -static cairo_status_t -_cairo_quartz_image_surface_flush (void *asurface, - unsigned flags) -{ - cairo_quartz_image_surface_t *surface = (cairo_quartz_image_surface_t *) asurface; - CGImageRef oldImage = surface->image; - CGImageRef newImage = NULL; - void *image_data; - const unsigned int size = surface->imageSurface->height * surface->imageSurface->stride; - if (flags) - return CAIRO_STATUS_SUCCESS; - - /* XXX only flush if the image has been modified. */ - - image_data = _cairo_malloc_ab ( surface->imageSurface->height, - surface->imageSurface->stride); - if (unlikely (!image_data)) - return _cairo_error (CAIRO_STATUS_NO_MEMORY); - - memcpy (image_data, surface->imageSurface->data, - surface->imageSurface->height * surface->imageSurface->stride); - newImage = CairoQuartzCreateCGImage (surface->imageSurface->format, - surface->imageSurface->width, - surface->imageSurface->height, - surface->imageSurface->stride, - image_data, - TRUE, - NULL, - DataProviderReleaseCallback, - image_data); - - surface->image = newImage; - CGImageRelease (oldImage); - - return CAIRO_STATUS_SUCCESS; -} - static cairo_int_status_t _cairo_quartz_image_surface_paint (void *abstract_surface, cairo_operator_t op, @@ -275,7 +238,7 @@ static const cairo_surface_backend_t cairo_quartz_image_surface_backend = { _cairo_quartz_image_surface_get_extents, NULL, /* get_font_options */ - _cairo_quartz_image_surface_flush, + NULL, /*surface_flush */ NULL, /* mark_dirty_rectangle */ _cairo_quartz_image_surface_paint, @@ -290,12 +253,9 @@ static const cairo_surface_backend_t cairo_quartz_image_surface_backend = { * cairo_quartz_image_surface_create: * @image_surface: a cairo image surface to wrap with a quartz image surface * - * Creates a Quartz surface backed by a CGImageRef that references the + * Creates a Quartz surface backed by a CGBitmapContext that references the * given image surface. The resulting surface can be rendered quickly - * when used as a source when rendering to a #cairo_quartz_surface. If - * the data in the image surface is ever updated, cairo_surface_flush() - * must be called on the #cairo_quartz_image_surface to ensure that the - * CGImageRef refers to the updated data. + * when used as a source when rendering to a #cairo_quartz_surface. * * Return value: the newly created surface. * @@ -305,13 +265,11 @@ cairo_surface_t * cairo_quartz_image_surface_create (cairo_surface_t *surface) { cairo_quartz_image_surface_t *qisurf; - - CGImageRef image; - cairo_image_surface_t *image_surface; int width, height, stride; cairo_format_t format; - void *image_data; + CGBitmapInfo bitinfo = kCGBitmapByteOrder32Host; + CGColorSpaceRef colorspace; if (surface->status) return surface; @@ -338,54 +296,104 @@ cairo_quartz_image_surface_create (cairo_surface_t *surface) if (qisurf == NULL) return SURFACE_ERROR_NO_MEMORY; - memset (qisurf, 0, sizeof(cairo_quartz_image_surface_t)); - - image_data = _cairo_malloc_ab (height, stride); - if (unlikely (!image_data)) { - free(qisurf); - return SURFACE_ERROR_NO_MEMORY; - } - - memcpy (image_data, image_surface->data, height * stride); - image = CairoQuartzCreateCGImage (format, - width, height, - stride, - image_data, - TRUE, - NULL, - DataProviderReleaseCallback, - image_data); - - if (!image) { - free (qisurf); - return SURFACE_ERROR_NO_MEMORY; - } - _cairo_surface_init (&qisurf->base, &cairo_quartz_image_surface_backend, NULL, /* device */ _cairo_content_from_format (format), FALSE); /* is_vector */ + if (_cairo_surface_is_quartz (surface) || _cairo_surface_is_quartz_image (surface)) { + CGContextRef context = cairo_quartz_surface_get_cg_context(surface); + colorspace = _cairo_quartz_create_color_space (context); + } + else { +#if CAIRO_HAS_QUARTZ_APPLICATION_SERVICES /* available on macOS but not iOS */ + colorspace = CGDisplayCopyColorSpace (CGMainDisplayID ()); +#else + colorspace = CGColorSpaceCreateDeviceRGB (); +#endif + } + + bitinfo |= format == CAIRO_FORMAT_ARGB32 ? kCGImageAlphaPremultipliedFirst : kCGImageAlphaNoneSkipFirst; + qisurf->width = width; qisurf->height = height; - qisurf->image = image; + qisurf->cgContext = CGBitmapContextCreate (image_surface->data, width, height, 8, image_surface->stride, + colorspace, bitinfo); qisurf->imageSurface = (cairo_image_surface_t*) cairo_surface_reference(surface); + CGColorSpaceRelease (colorspace); return &qisurf->base; } +/** + * cairo_quartz_image_surface_get_image: + * @surface: a #cairo_surface_t + * + * Returns a #cairo_surface_t image surface that refers to the same bits + * as the image of the quartz surface. + * + * Return value: a #cairo_surface_t (owned by the quartz #cairo_surface_t), + * or %NULL if the quartz surface is not an image surface. + * + * Since: 1.6 + **/ cairo_surface_t * -cairo_quartz_image_surface_get_image (cairo_surface_t *asurface) +cairo_quartz_image_surface_get_image (cairo_surface_t *surface) { - cairo_quartz_image_surface_t *surface = (cairo_quartz_image_surface_t*) asurface; + cairo_quartz_image_surface_t *qsurface = (cairo_quartz_image_surface_t*) surface; /* Throw an error for a non-quartz surface */ - if (! _cairo_surface_is_quartz (asurface)) { + if (! _cairo_surface_is_quartz (surface)) { return SURFACE_ERROR_TYPE_MISMATCH; } - return (cairo_surface_t*) surface->imageSurface; + return (cairo_surface_t*) qsurface->imageSurface; +} + +/* + * _cairo_quartz_image_surface_get_cg_context: + * @surface: the Cairo Quartz surface + * + * Returns the CGContextRef that the given Quartz surface is backed + * by. + * + * A call to cairo_surface_flush() is required before using the + * CGContextRef to ensure that all pending drawing operations are + * finished and to restore any temporary modification cairo has made + * to its state. A call to cairo_surface_mark_dirty() is required + * after the state or the content of the CGContextRef has been + * modified. + * + * Return value: the CGContextRef for the given surface. + * + **/ +CGContextRef +_cairo_quartz_image_surface_get_cg_context (cairo_surface_t *surface) +{ + if (surface && _cairo_surface_is_quartz_image (surface)) { + cairo_quartz_surface_t *quartz = (cairo_quartz_surface_t *) surface; + return quartz->cgContext; + } else + return NULL; +} + +/* + * _cairo_surface_is_quartz_image: + * @surface: a #cairo_surface_t + * + * Checks if a surface is a #cairo_quartz_surface_t + * + * Return value: True if the surface is an quartz surface + **/ +cairo_bool_t +_cairo_surface_is_quartz_image (const cairo_surface_t *surface) { + return surface->backend == &cairo_quartz_image_surface_backend; +} + +cairo_bool_t +_cairo_quartz_image_surface_is_zero (const cairo_quartz_image_surface_t *surface) { + return surface->width == 0 || surface->height == 0; } diff --git a/gfx/cairo/cairo/src/cairo-quartz-private.h b/gfx/cairo/cairo/src/cairo-quartz-private.h index d789191900..bdfdf8c2bb 100644 --- a/gfx/cairo/cairo/src/cairo-quartz-private.h +++ b/gfx/cairo/cairo/src/cairo-quartz-private.h @@ -55,7 +55,6 @@ typedef enum { DO_DIRECT, DO_SHADING, DO_IMAGE, - DO_TILED_IMAGE, DO_LAYER } cairo_quartz_action_t; @@ -68,28 +67,21 @@ typedef struct cairo_quartz_surface { CGContextRef cgContext; CGAffineTransform cgContextBaseCTM; +#if MAC_OS_X_VERSION_MIN_REQUIRED < 10600 void *imageData; - cairo_surface_t *imageSurfaceEquiv; +#endif cairo_surface_clipper_t clipper; - - /** - * If non-null, this is the CGLayer for the surface. - */ - CGLayerRef cgLayer; - cairo_rectangle_int_t extents; cairo_rectangle_int_t virtual_extents; - - cairo_bool_t ownsData; + CGLayerRef cgLayer; } cairo_quartz_surface_t; typedef struct cairo_quartz_image_surface { cairo_surface_t base; int width, height; - - CGImageRef image; + CGContextRef cgContext; cairo_image_surface_t *imageSurface; } cairo_quartz_image_surface_t; @@ -99,22 +91,27 @@ _cairo_quartz_verify_surface_size(int width, int height); cairo_private cairo_bool_t _cairo_surface_is_quartz (const cairo_surface_t *surface); -cairo_private CGImageRef -CairoQuartzCreateCGImage (cairo_format_t format, - unsigned int width, - unsigned int height, - unsigned int stride, - void *data, - cairo_bool_t interpolate, - CGColorSpaceRef colorSpaceOverride, - CGDataProviderReleaseDataCallback releaseCallback, - void *releaseInfo); +cairo_private cairo_bool_t +_cairo_surface_is_quartz_image (const cairo_surface_t *surface); +cairo_private cairo_bool_t +_cairo_quartz_image_surface_is_zero (const cairo_quartz_image_surface_t *surface); + +cairo_private CGColorSpaceRef +_cairo_quartz_create_color_space (CGContextRef context); +cairo_private CGContextRef +_cairo_quartz_image_surface_get_cg_context (cairo_surface_t *surface); cairo_private CGFontRef _cairo_quartz_scaled_font_get_cg_font_ref (cairo_scaled_font_t *sfont); - cairo_private CTFontRef -_cairo_quartz_scaled_font_get_ct_font_ref (cairo_scaled_font_t *sfont); +_cairo_quartz_scaled_font_get_ct_font (cairo_scaled_font_t *sfont); +cairo_private cairo_font_face_t* +_cairo_quartz_font_face_create_for_ctfont (CTFontRef ctFont); +cairo_private void +_cairo_quartz_set_antialiasing (CGContextRef context, cairo_antialias_t antialias); + +cairo_status_t _cairo_quartz_surface_to_png (cairo_surface_t *abstract_surface, const char *dest); +cairo_private void _cairo_quartz_image_to_png (CGImageRef, const char *dest); #else diff --git a/gfx/cairo/cairo/src/cairo-quartz-surface.c b/gfx/cairo/cairo/src/cairo-quartz-surface.c index b97967fb21..6b4e226b96 100644 --- a/gfx/cairo/cairo/src/cairo-quartz-surface.c +++ b/gfx/cairo/cairo/src/cairo-quartz-surface.c @@ -34,10 +34,10 @@ * Vladimir Vukicevic <vladimir@mozilla.com> */ -#define _GNU_SOURCE /* required for RTLD_DEFAULT */ #include "cairoint.h" #include "cairo-quartz-private.h" +#include "cairo-quartz-image.h" #include "cairo-composite-rectangles-private.h" #include "cairo-compositor-private.h" @@ -57,6 +57,7 @@ #endif #include <limits.h> +#include <assert.h> #undef QUARTZ_DEBUG @@ -66,7 +67,30 @@ #define ND(_x) do {} while(0) #endif -#define IS_EMPTY(s) ((s)->extents.width == 0 || (s)->extents.height == 0) +#if MAC_OS_X_VERSION_MIN_REQUIRED < 1080 +#define FONT_ORIENTATION_HORIZONTAL kCTFontHorizontalOrientation +#else +#define FONT_ORIENTATION_HORIZONTAL kCTFontOrientationHorizontal +#endif + +static inline cairo_bool_t +_is_quartz_surface (cairo_surface_t *surface) { + return _cairo_surface_is_quartz (surface) || _cairo_surface_is_quartz_image (surface); +} + +static inline cairo_bool_t +_cairo_quartz_surface_is_zero (cairo_quartz_surface_t* surface) { + return surface->extents.width == 0 || surface->extents.height == 0; +} + +static inline cairo_bool_t +_cairo_quartz_is_zero_surface (cairo_surface_t* surface) { + assert (_is_quartz_surface (surface)); + if (_cairo_surface_is_quartz (surface)) + return (_cairo_quartz_surface_is_zero ((cairo_quartz_surface_t*) surface)); + else + return (_cairo_quartz_image_surface_is_zero ((cairo_quartz_image_surface_t*) surface)); +} /** * SECTION:cairo-quartz @@ -87,56 +111,51 @@ * Since: 1.6 **/ -#if __MAC_OS_X_VERSION_MIN_REQUIRED < 1050 -/* 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)) -}; -typedef enum PrivateCGCompositeMode PrivateCGCompositeMode; -CG_EXTERN void CGContextSetCompositeOperation (CGContextRef, PrivateCGCompositeMode); -#endif - -/* Some of these are present in earlier versions of the OS than where - * they are public; other are not public at all +/* + * macOS Private functions */ -/* public since 10.5 */ -static void (*CGContextDrawTiledImagePtr) (CGContextRef, CGRect, CGImageRef) = NULL; +typedef enum { + kCGContextTypeUnknown, + kCGContextTypePDF, + kCGContextTypePostScript, + kCGContextTypeWindow, + kCGContextTypeBitmap, + kCGContextTypeGL, + kCGContextTypeDisplayList, + kCGContextTypeKSeparation, + kCGContextTypeIOSurface, + kCGContextTypeCount +} CGContextType; -/* public since 10.6 */ -static CGPathRef (*CGContextCopyPathPtr) (CGContextRef) = NULL; -static void (*CGContextSetAllowsFontSmoothingPtr) (CGContextRef, bool) = NULL; -/* not yet public */ -static unsigned int (*CGContextGetTypePtr) (CGContextRef) = NULL; static bool (*CGContextGetAllowsFontSmoothingPtr) (CGContextRef) = NULL; +static unsigned int (*CGContextGetTypePtr) (CGContextRef) = NULL; +static void +quartz_ensure_symbols() +{ + static cairo_bool_t symbol_lookup_done = FALSE; + if (!symbol_lookup_done) { + CGContextGetTypePtr = dlsym (RTLD_DEFAULT, "CGContextGetType"); + CGContextGetAllowsFontSmoothingPtr = + dlsym (RTLD_DEFAULT, "CGContextGetAllowsFontSmoothing"); + symbol_lookup_done = TRUE; + } +} -/* CTFontDrawGlyphs is not available until 10.7 */ -static void (*CTFontDrawGlyphsPtr) (CTFontRef, const CGGlyph[], const CGPoint[], size_t, CGContextRef) = NULL; - -static cairo_bool_t _cairo_quartz_symbol_lookup_done = FALSE; +typedef struct +{ + cairo_surface_t base; + CGImageRef image; +} cairo_quartz_snapshot_t; -/* - * Utility functions - */ +static cairo_surface_t* _cairo_quartz_snapshot_create (cairo_surface_t *surface); +static cairo_status_t _cairo_quartz_snapshot_finish (void *surface); +static CGImageRef _cairo_quartz_surface_snapshot_get_image (cairo_surface_t *surface); -#ifdef QUARTZ_DEBUG -static void quartz_surface_to_png (cairo_quartz_surface_t *nq, char *dest); -static void quartz_image_to_png (CGImageRef, char *dest); -#endif +static const cairo_surface_backend_t cairo_quartz_snapshot_backend = { + CAIRO_INTERNAL_SURFACE_TYPE_QUARTZ_SNAPSHOT, + _cairo_quartz_snapshot_finish, +}; static cairo_quartz_surface_t * _cairo_quartz_surface_create_internal (CGContextRef cgContext, @@ -144,117 +163,74 @@ _cairo_quartz_surface_create_internal (CGContextRef cgContext, unsigned int width, unsigned int height); -/* Load all extra symbols */ -static void quartz_ensure_symbols (void) +CGColorSpaceRef +_cairo_quartz_create_color_space (CGContextRef context) { - if (likely (_cairo_quartz_symbol_lookup_done)) - return; + CGColorSpaceRef color_space = NULL; + CGContextType cgtype = kCGContextTypeUnknown; - CGContextDrawTiledImagePtr = dlsym (RTLD_DEFAULT, "CGContextDrawTiledImage"); - CGContextGetTypePtr = dlsym (RTLD_DEFAULT, "CGContextGetType"); - CGContextCopyPathPtr = dlsym (RTLD_DEFAULT, "CGContextCopyPath"); - CGContextGetAllowsFontSmoothingPtr = dlsym (RTLD_DEFAULT, "CGContextGetAllowsFontSmoothing"); - CGContextSetAllowsFontSmoothingPtr = dlsym (RTLD_DEFAULT, "CGContextSetAllowsFontSmoothing"); + if (context) + { + if (CGBitmapContextGetBitsPerPixel (context) < 24) + return 0; + + quartz_ensure_symbols(); + cgtype = CGContextGetTypePtr (context); + switch (cgtype) + { + case kCGContextTypeUnknown: + break; + case kCGContextTypePDF: + color_space = CGColorSpaceCreateDeviceRGB (); + break; + case kCGContextTypePostScript: + case kCGContextTypeWindow: + break; + case kCGContextTypeBitmap: + color_space = CGBitmapContextGetColorSpace (context); + color_space = CGColorSpaceRetain (color_space); + break; + case kCGContextTypeGL: + case kCGContextTypeDisplayList: + case kCGContextTypeKSeparation: + case kCGContextTypeIOSurface: + case kCGContextTypeCount: + default: + break; + } + if (color_space) + return color_space; + } +#if CAIRO_HAS_QUARTZ_APPLICATION_SERVICES /* available on macOS but not iOS */ + if (!color_space) + color_space = CGDisplayCopyColorSpace (CGMainDisplayID ()); +#endif - CTFontDrawGlyphsPtr = dlsym(RTLD_DEFAULT, "CTFontDrawGlyphs"); + if (!color_space) + color_space = CGColorSpaceCreateDeviceRGB (); - _cairo_quartz_symbol_lookup_done = TRUE; + return color_space; } -CGImageRef -CairoQuartzCreateCGImage (cairo_format_t format, - unsigned int width, - unsigned int height, - unsigned int stride, - void *data, - cairo_bool_t interpolate, - CGColorSpaceRef colorSpaceOverride, - CGDataProviderReleaseDataCallback releaseCallback, - void *releaseInfo) +static CGColorRef +_cairo_quartz_create_cgcolor (CGColorSpaceRef cs, CGFloat red, CGFloat green, + CGFloat blue, CGFloat alpha) { - CGImageRef image = NULL; - CGDataProviderRef dataProvider = NULL; - CGColorSpaceRef colorSpace = colorSpaceOverride; - CGBitmapInfo bitinfo = kCGBitmapByteOrder32Host; - int bitsPerComponent, bitsPerPixel; - - switch (format) { - case CAIRO_FORMAT_ARGB32: - if (colorSpace == NULL) - colorSpace = CGColorSpaceCreateDeviceRGB (); - bitinfo |= kCGImageAlphaPremultipliedFirst; - bitsPerComponent = 8; - bitsPerPixel = 32; - break; - - case CAIRO_FORMAT_RGB24: - if (colorSpace == NULL) - colorSpace = CGColorSpaceCreateDeviceRGB (); - bitinfo |= kCGImageAlphaNoneSkipFirst; - bitsPerComponent = 8; - bitsPerPixel = 32; - break; - - case CAIRO_FORMAT_A8: - bitsPerComponent = 8; - bitsPerPixel = 8; - break; - - case CAIRO_FORMAT_A1: -#ifdef WORDS_BIGENDIAN - bitsPerComponent = 1; - bitsPerPixel = 1; - break; -#endif - - case CAIRO_FORMAT_RGB30: - case CAIRO_FORMAT_RGB16_565: - case CAIRO_FORMAT_INVALID: - default: - return NULL; - } - - dataProvider = CGDataProviderCreateWithData (releaseInfo, - data, - height * stride, - releaseCallback); - - if (unlikely (!dataProvider)) { - // manually release - if (releaseCallback) - releaseCallback (releaseInfo, data, height * stride); - goto FINISH; + CGFloat colors[4] = { red, green, blue, alpha }; + CGColorRef cgc; + if (!CGColorSpaceRetain(cs)) + { + cs = _cairo_quartz_create_color_space (NULL); } + cgc = CGColorCreate (cs, colors); + CGColorSpaceRelease (cs); + return cgc; +} - if (format == CAIRO_FORMAT_A8 || format == CAIRO_FORMAT_A1) { - cairo_quartz_float_t decode[] = {1.0, 0.0}; - image = CGImageMaskCreate (width, height, - bitsPerComponent, - bitsPerPixel, - stride, - dataProvider, - decode, - interpolate); - } else - image = CGImageCreate (width, height, - bitsPerComponent, - bitsPerPixel, - stride, - colorSpace, - bitinfo, - dataProvider, - NULL, - interpolate, - kCGRenderingIntentDefault); - -FINISH: - - CGDataProviderRelease (dataProvider); - - if (colorSpace != colorSpaceOverride) - CGColorSpaceRelease (colorSpace); - - return image; +static CGColorRef +_cairo_quartz_black (CGColorSpaceRef cs) +{ + return _cairo_quartz_create_cgcolor (cs, 0.0, 0.0, 0.0, 1.0); } static inline cairo_bool_t @@ -263,9 +239,10 @@ _cairo_quartz_is_cgcontext_bitmap_context (CGContextRef cgc) if (unlikely (cgc == NULL)) return FALSE; + quartz_ensure_symbols (); if (likely (CGContextGetTypePtr)) { /* 4 is the type value of a bitmap context */ - return CGContextGetTypePtr (cgc) == 4; + return CGContextGetTypePtr (cgc) == kCGContextTypeBitmap; } /* This will cause a (harmless) warning to be printed if called on a non-bitmap context */ @@ -370,58 +347,6 @@ _cairo_quartz_cairo_path_to_quartz_context (const cairo_path_fixed_t *path, * Misc helpers/callbacks */ -#if __MAC_OS_X_VERSION_MIN_REQUIRED < 1050 -static PrivateCGCompositeMode -_cairo_quartz_cairo_operator_to_quartz_composite (cairo_operator_t op) -{ - switch (op) { - case CAIRO_OPERATOR_CLEAR: - return kPrivateCGCompositeClear; - case CAIRO_OPERATOR_SOURCE: - return kPrivateCGCompositeCopy; - case CAIRO_OPERATOR_OVER: - return kPrivateCGCompositeSourceOver; - case CAIRO_OPERATOR_IN: - return kPrivateCGCompositeSourceIn; - case CAIRO_OPERATOR_OUT: - return kPrivateCGCompositeSourceOut; - case CAIRO_OPERATOR_ATOP: - return kPrivateCGCompositeSourceAtop; - case CAIRO_OPERATOR_DEST_OVER: - return kPrivateCGCompositeDestinationOver; - case CAIRO_OPERATOR_DEST_IN: - return kPrivateCGCompositeDestinationIn; - case CAIRO_OPERATOR_DEST_OUT: - return kPrivateCGCompositeDestinationOut; - case CAIRO_OPERATOR_DEST_ATOP: - return kPrivateCGCompositeDestinationAtop; - case CAIRO_OPERATOR_XOR: - return kPrivateCGCompositeXOR; - case CAIRO_OPERATOR_ADD: - return kPrivateCGCompositePlusLighter; - - case CAIRO_OPERATOR_DEST: - case CAIRO_OPERATOR_SATURATE: - case CAIRO_OPERATOR_MULTIPLY: - case CAIRO_OPERATOR_SCREEN: - case CAIRO_OPERATOR_OVERLAY: - case CAIRO_OPERATOR_DARKEN: - case CAIRO_OPERATOR_LIGHTEN: - case CAIRO_OPERATOR_COLOR_DODGE: - case CAIRO_OPERATOR_COLOR_BURN: - case CAIRO_OPERATOR_HARD_LIGHT: - case CAIRO_OPERATOR_SOFT_LIGHT: - case CAIRO_OPERATOR_DIFFERENCE: - case CAIRO_OPERATOR_EXCLUSION: - case CAIRO_OPERATOR_HSL_HUE: - case CAIRO_OPERATOR_HSL_SATURATION: - case CAIRO_OPERATOR_HSL_COLOR: - case CAIRO_OPERATOR_HSL_LUMINOSITY: - default: - ASSERT_NOT_REACHED; - } -} -#endif static CGBlendMode _cairo_quartz_cairo_operator_to_quartz_blend (cairo_operator_t op) @@ -458,7 +383,6 @@ _cairo_quartz_cairo_operator_to_quartz_blend (cairo_operator_t op) case CAIRO_OPERATOR_HSL_LUMINOSITY: return kCGBlendModeLuminosity; -#if __MAC_OS_X_VERSION_MIN_REQUIRED >= 1050 case CAIRO_OPERATOR_CLEAR: return kCGBlendModeClear; case CAIRO_OPERATOR_SOURCE: @@ -483,27 +407,12 @@ _cairo_quartz_cairo_operator_to_quartz_blend (cairo_operator_t op) return kCGBlendModeXOR; case CAIRO_OPERATOR_ADD: return kCGBlendModePlusLighter; -#else - case CAIRO_OPERATOR_CLEAR: - case CAIRO_OPERATOR_SOURCE: - case CAIRO_OPERATOR_OVER: - case CAIRO_OPERATOR_IN: - case CAIRO_OPERATOR_OUT: - case CAIRO_OPERATOR_ATOP: - case CAIRO_OPERATOR_DEST_OVER: - case CAIRO_OPERATOR_DEST_IN: - case CAIRO_OPERATOR_DEST_OUT: - case CAIRO_OPERATOR_DEST_ATOP: - case CAIRO_OPERATOR_XOR: - case CAIRO_OPERATOR_ADD: -#endif - case CAIRO_OPERATOR_DEST: case CAIRO_OPERATOR_SATURATE: default: ASSERT_NOT_REACHED; } - return kCGBlendModeNormal; /* just to silence clang warning [-Wreturn-type] */ + return kCGBlendModeNormal; /* unreached */ } static cairo_int_status_t @@ -528,16 +437,6 @@ _cairo_cgcontext_set_cairo_operator (CGContextRef context, cairo_operator_t op) return CAIRO_INT_STATUS_UNSUPPORTED; } -#if __MAC_OS_X_VERSION_MIN_REQUIRED < 1050 - if (op <= CAIRO_OPERATOR_ADD) { - PrivateCGCompositeMode compmode; - - compmode = _cairo_quartz_cairo_operator_to_quartz_composite (op); - CGContextSetCompositeOperation (context, compmode); - return CAIRO_STATUS_SUCCESS; - } -#endif - blendmode = _cairo_quartz_cairo_operator_to_quartz_blend (op); CGContextSetBlendMode (context, blendmode); return CAIRO_STATUS_SUCCESS; @@ -785,6 +684,49 @@ CairoQuartzCreateGradientFunction (const cairo_gradient_pattern_t *gradient, &gradient_callbacks); } +static CGImageRef +CairoQuartzCreateCGImageMask (cairo_format_t format, + unsigned int width, + unsigned int height, + unsigned int stride, + void *data, + cairo_bool_t interpolate, + CGDataProviderReleaseDataCallback releaseCallback, + void *releaseInfo) +{ + CGImageRef image = NULL; + CGDataProviderRef dataProvider = NULL; + int bitsPerComponent = 8, bitsPerPixel = 8; + + if (format != CAIRO_FORMAT_A8) + return NULL; + + dataProvider = CGDataProviderCreateWithData (releaseInfo, + data, + height * stride, + releaseCallback); + + if (unlikely (!dataProvider)) { + // manually release + if (releaseCallback) + releaseCallback (releaseInfo, data, height * stride); + goto FINISH; + } + + cairo_quartz_float_t decode[] = {1.0, 0.0}; + image = CGImageMaskCreate (width, height, + bitsPerComponent, + bitsPerPixel, + stride, + dataProvider, + decode, + interpolate); + +FINISH: + CGDataProviderRelease (dataProvider); + return image; +} + static void DataProviderReleaseCallback (void *info, const void *data, size_t size) { @@ -800,104 +742,120 @@ _cairo_surface_to_cgimage (cairo_surface_t *source, CGImageRef *image_out) { cairo_status_t status; - cairo_image_surface_t *image_surface; - void *image_data, *image_extra; + cairo_quartz_image_surface_t *image_surface; + void *image_extra; cairo_bool_t acquired = FALSE; - if (source->backend && source->backend->type == CAIRO_SURFACE_TYPE_QUARTZ_IMAGE) { - cairo_quartz_image_surface_t *surface = (cairo_quartz_image_surface_t *) source; - *image_out = CGImageRetain (surface->image); - return CAIRO_STATUS_SUCCESS; - } - - if (_cairo_surface_is_quartz (source)) { - cairo_quartz_surface_t *surface = (cairo_quartz_surface_t *) source; - if (IS_EMPTY (surface)) { + if (_is_quartz_surface (source)) { + CGContextRef cgContext = cairo_quartz_surface_get_cg_context(source); + if (_cairo_quartz_is_zero_surface (source)) { *image_out = NULL; return CAIRO_INT_STATUS_NOTHING_TO_DO; } - if (_cairo_quartz_is_cgcontext_bitmap_context (surface->cgContext)) { - *image_out = CGBitmapContextCreateImage (surface->cgContext); - if (*image_out) - return CAIRO_STATUS_SUCCESS; + if (_cairo_quartz_is_cgcontext_bitmap_context (cgContext)) { + *image_out = _cairo_quartz_surface_snapshot_get_image (source); + return CAIRO_STATUS_SUCCESS; } + + *image_out = NULL; + return CAIRO_STATUS_SURFACE_TYPE_MISMATCH; } if (source->type == CAIRO_SURFACE_TYPE_RECORDING) { - image_surface = (cairo_image_surface_t *) - cairo_image_surface_create (format, extents->width, extents->height); - if (unlikely (image_surface->base.status)) { - status = image_surface->base.status; - cairo_surface_destroy (&image_surface->base); + cairo_image_surface_t *surface = + (cairo_image_surface_t*)cairo_image_surface_create (format, extents->width, + extents->height); + if (unlikely (surface->base.status)) { + status = surface->base.status; + cairo_surface_destroy (&surface->base); return status; } status = _cairo_recording_surface_replay_with_clip (source, matrix, - &image_surface->base, + &surface->base, NULL); if (unlikely (status)) { - cairo_surface_destroy (&image_surface->base); + cairo_surface_destroy (&surface->base); return status; } + image_surface = + (cairo_quartz_image_surface_t*)cairo_quartz_image_surface_create (&surface->base); cairo_matrix_init_identity (matrix); } else { - status = _cairo_surface_acquire_source_image (source, &image_surface, + cairo_image_surface_t *surface; + status = _cairo_surface_acquire_source_image (source, &surface, &image_extra); if (unlikely (status)) return status; - acquired = TRUE; - } - if (image_surface->width == 0 || image_surface->height == 0) { - *image_out = NULL; - if (acquired) - _cairo_surface_release_source_image (source, image_surface, image_extra); - else - cairo_surface_destroy (&image_surface->base); + if (surface->format == CAIRO_FORMAT_A8) { + /* cairo_quartz_image_surface_create doesn't handle CAIRO_FORMAT_A8, + * so we create a CGImage manually here for masking operations. + */ + void* image_data = _cairo_malloc_ab (surface->height, surface->stride); + if (unlikely (!image_data)) + { + _cairo_surface_release_source_image (source, surface, image_extra); + return _cairo_error (CAIRO_STATUS_NO_MEMORY); + } - return status; + /* The last row of data may have less than stride bytes so make sure we + * only copy the minimum amount required from that row. + */ + memcpy (image_data, surface->data, + (surface->height - 1) * surface->stride + + cairo_format_stride_for_width (surface->format, + surface->width)); + *image_out = CairoQuartzCreateCGImageMask (surface->format, + surface->width, + surface->height, + surface->stride, + image_data, + TRUE, + DataProviderReleaseCallback, + image_data); + /* TODO: differentiate memory error and unsupported surface type */ + if (unlikely (*image_out == NULL)) + status = CAIRO_INT_STATUS_UNSUPPORTED; + + _cairo_surface_release_source_image (source, surface, image_extra); + return status; + } else { + image_surface = + (cairo_quartz_image_surface_t*)cairo_quartz_image_surface_create (&surface->base); + status = image_surface->base.status; + if (status) + _cairo_surface_release_source_image (source, surface, image_extra); + else + acquired = TRUE; + } } - image_data = _cairo_malloc_ab (image_surface->height, image_surface->stride); - if (unlikely (!image_data)) - { - if (acquired) - _cairo_surface_release_source_image (source, image_surface, image_extra); - else - cairo_surface_destroy (&image_surface->base); - - return _cairo_error (CAIRO_STATUS_NO_MEMORY); + *image_out = NULL; + if (image_surface->width > 0 && image_surface->height > 0) { + *image_out = _cairo_quartz_surface_snapshot_get_image (&image_surface->base); + status = CAIRO_STATUS_SUCCESS; } - // The last row of data may have less than stride bytes so make sure we - // only copy the minimum amount required from that row. - memcpy (image_data, image_surface->data, - (image_surface->height - 1) * image_surface->stride + - cairo_format_stride_for_width (image_surface->format, - image_surface->width)); - *image_out = CairoQuartzCreateCGImage (image_surface->format, - image_surface->width, - image_surface->height, - image_surface->stride, - image_data, - TRUE, - NULL, - DataProviderReleaseCallback, - image_data); + if (acquired) { + _cairo_surface_release_source_image (source, image_surface->imageSurface, image_extra); + /* If source itself is an image surface, _cairo_surface_release_source_image + does not release it, and image_surface->imageSurface still owns a reference + to it. So we don't clear that field here; _cairo_quartz_image_surface_finish + will take care of it. */ + if (source->type != CAIRO_SURFACE_TYPE_IMAGE) + image_surface->imageSurface = NULL; + } + cairo_surface_destroy (&image_surface->base); /* TODO: differentiate memory error and unsupported surface type */ if (unlikely (*image_out == NULL)) status = CAIRO_INT_STATUS_UNSUPPORTED; - if (acquired) - _cairo_surface_release_source_image (source, image_surface, image_extra); - else - cairo_surface_destroy (&image_surface->base); - return status; } @@ -952,15 +910,15 @@ SurfacePatternReleaseInfoFunc (void *ainfo) } static cairo_int_status_t -_cairo_quartz_cairo_repeating_surface_pattern_to_quartz (cairo_quartz_surface_t *dest, - const cairo_pattern_t *apattern, +_cairo_quartz_cairo_repeating_surface_pattern_to_quartz (cairo_quartz_surface_t *surface, + const cairo_pattern_t *source, const cairo_clip_t *clip, CGPatternRef *cgpat) { - cairo_surface_pattern_t *spattern; - cairo_surface_t *pat_surf; + cairo_surface_pattern_t *spattern = (cairo_surface_pattern_t *) source; + cairo_surface_t *pat_surf = spattern->surface; cairo_rectangle_int_t extents; - cairo_format_t format = _cairo_format_from_content (dest->base.content); + cairo_format_t format = _cairo_format_from_content (surface->base.content); CGImageRef image; CGRect pbounds; @@ -971,42 +929,28 @@ _cairo_quartz_cairo_repeating_surface_pattern_to_quartz (cairo_quartz_surface_t SurfacePatternDrawInfo *info; cairo_quartz_float_t rw, rh; cairo_status_t status; - cairo_bool_t is_bounded; - - cairo_matrix_t m; + cairo_bool_t is_bounded = _cairo_surface_get_extents (pat_surf, &extents); + cairo_matrix_t m = spattern->base.matrix; /* SURFACE is the only type we'll handle here */ - assert (apattern->type == CAIRO_PATTERN_TYPE_SURFACE); - - spattern = (cairo_surface_pattern_t *) apattern; - pat_surf = spattern->surface; + assert (source->type == CAIRO_PATTERN_TYPE_SURFACE); - if (pat_surf->type != CAIRO_SURFACE_TYPE_RECORDING) { - is_bounded = _cairo_surface_get_extents (pat_surf, &extents); + if (pat_surf->type != CAIRO_SURFACE_TYPE_RECORDING) assert (is_bounded); - } - else - _cairo_surface_get_extents (&dest->base, &extents); - m = spattern->base.matrix; status = _cairo_surface_to_cgimage (pat_surf, &extents, format, &m, clip, &image); + if (unlikely (status)) return status; info = _cairo_malloc (sizeof (SurfacePatternDrawInfo)); if (unlikely (!info)) + { + CGImageRelease (image); return CAIRO_STATUS_NO_MEMORY; + } - /* XXX -- if we're printing, we may need to call CGImageCreateCopy to make sure - * that the data will stick around for this image when the printer gets to it. - * Otherwise, the underlying data store may disappear from under us! - * - * _cairo_surface_to_cgimage will copy when it converts non-Quartz surfaces, - * since the Quartz surfaces have a higher chance of sticking around. If the - * source is a quartz image surface, then it's set up to retain a ref to the - * image surface that it's backed by. - */ info->image = image; info->imageBounds = CGRectMake (0, 0, extents.width, extents.height); info->do_reflect = FALSE; @@ -1014,13 +958,18 @@ _cairo_quartz_cairo_repeating_surface_pattern_to_quartz (cairo_quartz_surface_t pbounds.origin.x = 0; pbounds.origin.y = 0; - if (spattern->base.extend == CAIRO_EXTEND_REFLECT) { + switch (spattern->base.extend) { + case CAIRO_EXTEND_NONE: + case CAIRO_EXTEND_PAD: + case CAIRO_EXTEND_REPEAT: + pbounds.size.width = extents.width; + pbounds.size.height = extents.height; + break; + case CAIRO_EXTEND_REFLECT: pbounds.size.width = 2.0 * extents.width; pbounds.size.height = 2.0 * extents.height; info->do_reflect = TRUE; - } else { - pbounds.size.width = extents.width; - pbounds.size.height = extents.height; + break; } rw = pbounds.size.width; rh = pbounds.size.height; @@ -1033,12 +982,12 @@ _cairo_quartz_cairo_repeating_surface_pattern_to_quartz (cairo_quartz_surface_t * So we take the pattern matrix and the original context matrix, * which gives us the correct base translation/y flip. */ - ptransform = CGAffineTransformConcat (stransform, dest->cgContextBaseCTM); + ptransform = CGAffineTransformConcat (stransform, surface->cgContextBaseCTM); #ifdef QUARTZ_DEBUG ND ((stderr, " pbounds: %f %f %f %f\n", pbounds.origin.x, pbounds.origin.y, pbounds.size.width, pbounds.size.height)); ND ((stderr, " pattern xform: t: %f %f xx: %f xy: %f yx: %f yy: %f\n", ptransform.tx, ptransform.ty, ptransform.a, ptransform.b, ptransform.c, ptransform.d)); - CGAffineTransform xform = CGContextGetCTM (dest->cgContext); + CGAffineTransform xform = CGContextGetCTM (surface->cgContext); ND ((stderr, " context xform: t: %f %f xx: %f xy: %f yx: %f yy: %f\n", xform.tx, xform.ty, xform.a, xform.b, xform.c, xform.d)); #endif @@ -1070,10 +1019,10 @@ typedef struct { /* Destination rect */ CGRect rect; - /* Used with DO_SHADING, DO_IMAGE, DO_TILED_IMAGE, DO_LAYER */ + /* Used with DO_SHADING, DO_IMAGE */ CGAffineTransform transform; - /* Used with DO_IMAGE and DO_TILED_IMAGE */ + /* Used with DO_IMAGE */ CGImageRef image; /* Used with DO_SHADING */ @@ -1082,15 +1031,130 @@ typedef struct { /* Temporary destination for unbounded operations */ CGLayerRef layer; CGRect clipRect; - - /* Source layer to be rendered when using DO_LAYER. - Unlike 'layer' above, this is not owned by the drawing state - but by the source surface. */ - CGLayerRef sourceLayer; } cairo_quartz_drawing_state_t; +static cairo_int_status_t +_cairo_quartz_setup_pattern_source (cairo_quartz_drawing_state_t *state, + const cairo_pattern_t *source, + cairo_quartz_surface_t *surface, + const cairo_clip_t *clip, + cairo_operator_t op) +{ + const cairo_surface_pattern_t *spat = (const cairo_surface_pattern_t *) source; + cairo_surface_t *pat_surf = spat->surface; + cairo_matrix_t m = spat->base.matrix; + cairo_format_t format = _cairo_format_from_content (surface->base.content); + cairo_rectangle_int_t extents, pattern_extents; + CGImageRef img; + + cairo_quartz_float_t patternAlpha = 1.0f; + CGColorSpaceRef patternSpace; + CGPatternRef cgpat = NULL; + cairo_int_status_t status; + CGColorRef black = _cairo_quartz_black (_cairo_quartz_create_color_space (state->cgDrawContext)); + + _cairo_surface_get_extents (&surface->base, &extents); + + if (pat_surf->backend->type == CAIRO_SURFACE_TYPE_QUARTZ) { + cairo_quartz_surface_t *quartz_surf = (cairo_quartz_surface_t *) pat_surf; + + if (quartz_surf->cgLayer && source->extend == CAIRO_EXTEND_NONE) { + cairo_matrix_invert (&m); + _cairo_quartz_cairo_matrix_to_quartz (&m, &state->transform); + state->rect = CGRectMake (0, 0, quartz_surf->extents.width, quartz_surf->extents.height); + state->layer = quartz_surf->cgLayer; + state->action = DO_LAYER; + return CAIRO_STATUS_SUCCESS; + } + } + + status = _cairo_surface_to_cgimage (pat_surf, &extents, format, + &m, clip, &img); // Note that only pat_surf will get used! + if (unlikely (status)) + return status; + + state->image = img; + + if (state->filter == kCGInterpolationNone && _cairo_matrix_is_translation (&m)) { + m.x0 = -ceil (m.x0 - 0.5); + m.y0 = -ceil (m.y0 - 0.5); + } else { + cairo_matrix_invert (&m); + } + + _cairo_quartz_cairo_matrix_to_quartz (&m, &state->transform); + + if (pat_surf->type != CAIRO_SURFACE_TYPE_RECORDING) { + cairo_bool_t is_bounded = _cairo_surface_get_extents (pat_surf, &pattern_extents); + assert (is_bounded); + } else { + _cairo_surface_get_extents (&surface->base, &pattern_extents); + } + + if (source->extend == CAIRO_EXTEND_NONE || source->extend == CAIRO_EXTEND_PAD) { + int x, y; + + if (op == CAIRO_OPERATOR_SOURCE && + (pat_surf->content == CAIRO_CONTENT_ALPHA || + ! _cairo_matrix_is_integer_translation (&m, &x, &y))) + { + state->layer = CGLayerCreateWithContext (surface->cgContext, + state->clipRect.size, + NULL); + state->cgDrawContext = CGLayerGetContext (state->layer); + CGContextTranslateCTM (state->cgDrawContext, + -state->clipRect.origin.x, + -state->clipRect.origin.y); + } + + CGContextSetFillColorWithColor (state->cgDrawContext, black); + + state->rect = CGRectMake (0, 0, pattern_extents.width, pattern_extents.height); + state->action = DO_IMAGE; + return CAIRO_STATUS_SUCCESS; + } + + if (source->extend == CAIRO_EXTEND_REPEAT) + { + CGAffineTransform xform = CGAffineTransformConcat (CGContextGetCTM (state->cgDrawContext), + state->transform); + CGRect srcRect = CGRectMake (0, 0, extents.width, extents.height); + srcRect = CGRectApplyAffineTransform (srcRect, xform); + xform = CGAffineTransformInvert (xform); + srcRect = CGRectApplyAffineTransform (srcRect, xform); + state->rect = srcRect; + } + + status = _cairo_quartz_cairo_repeating_surface_pattern_to_quartz (surface, source, clip, &cgpat); + if (unlikely (status)) + return status; + + patternSpace = CGColorSpaceCreatePattern (NULL); + /* To pass pthread-same-source. */ + if (source->extend == CAIRO_EXTEND_REPEAT) + CGContextSetInterpolationQuality(state->cgDrawContext, state->filter); + CGContextSetFillColorSpace (state->cgDrawContext, patternSpace); + CGContextSetFillPattern (state->cgDrawContext, cgpat, &patternAlpha); + CGContextSetStrokeColorSpace (state->cgDrawContext, patternSpace); + CGContextSetStrokePattern (state->cgDrawContext, cgpat, &patternAlpha); + CGColorSpaceRelease (patternSpace); + + /* Quartz likes to munge the pattern phase (as yet unexplained + * why); force it to 0,0 as we've already baked in the correct + * pattern translation into the pattern matrix + */ + CGContextSetPatternPhase (state->cgDrawContext, CGSizeMake (0, 0)); + + CGPatternRelease (cgpat); + CGColorRelease (black); + + state->action = DO_DIRECT; + return CAIRO_STATUS_SUCCESS; +} + + /* -Quartz does not support repeating radients. We handle repeating gradients +Quartz does not support repeating gradients. We handle repeating gradients by manually extending the gradient and repeating color stops. We need to minimize the number of repetitions since Quartz seems to sample our color function across the entire range, even if part of that range is not needed @@ -1122,7 +1186,7 @@ _cairo_quartz_setup_gradient_source (cairo_quartz_drawing_state_t *state, if (unlikely (gradFunc == NULL)) return CAIRO_INT_STATUS_UNSUPPORTED; - rgb = CGColorSpaceCreateDeviceRGB (); + rgb = _cairo_quartz_create_color_space (NULL); if (gradient->base.type == CAIRO_PATTERN_TYPE_LINEAR) { state->shading = CGShadingCreateAxial (rgb, @@ -1161,13 +1225,13 @@ _cairo_quartz_setup_state (cairo_quartz_drawing_state_t *state, const cairo_clip_t *clip = composite->clip; cairo_bool_t needs_temp; cairo_status_t status; - cairo_format_t format = _cairo_format_from_content (composite->surface->content); state->layer = NULL; state->image = NULL; state->shading = NULL; state->cgDrawContext = NULL; state->cgMaskContext = NULL; + state->layer = NULL; status = _cairo_surface_clipper_set_clip (&surface->clipper, clip); if (unlikely (status)) @@ -1193,9 +1257,11 @@ _cairo_quartz_setup_state (cairo_quartz_drawing_state_t *state, state->filter = _cairo_quartz_filter_to_quartz (source->filter); if (op == CAIRO_OPERATOR_CLEAR) { - CGContextSetRGBFillColor (state->cgDrawContext, 0, 0, 0, 1); + CGColorRef black = _cairo_quartz_black (_cairo_quartz_create_color_space (surface->cgContext)); + CGContextSetFillColorWithColor (state->cgDrawContext, black); state->action = DO_DIRECT; + CGColorRelease (black); return CAIRO_STATUS_SUCCESS; } @@ -1232,18 +1298,17 @@ _cairo_quartz_setup_state (cairo_quartz_drawing_state_t *state, if (source->type == CAIRO_PATTERN_TYPE_SOLID) { cairo_solid_pattern_t *solid = (cairo_solid_pattern_t *) source; + CGColorRef color = _cairo_quartz_create_cgcolor (_cairo_quartz_create_color_space (state->cgDrawContext), + solid->color.red, + solid->color.green, + solid->color.blue, + solid->color.alpha); + - CGContextSetRGBStrokeColor (state->cgDrawContext, - solid->color.red, - solid->color.green, - solid->color.blue, - solid->color.alpha); - CGContextSetRGBFillColor (state->cgDrawContext, - solid->color.red, - solid->color.green, - solid->color.blue, - solid->color.alpha); + CGContextSetStrokeColorWithColor (state->cgDrawContext, color); + CGContextSetFillColorWithColor (state->cgDrawContext, color); + CGColorRelease (color); state->action = DO_DIRECT; return CAIRO_STATUS_SUCCESS; } @@ -1262,147 +1327,9 @@ _cairo_quartz_setup_state (cairo_quartz_drawing_state_t *state, return _cairo_quartz_setup_gradient_source (state, gpat, &extents); } - if (source->type == CAIRO_PATTERN_TYPE_SURFACE && - (source->extend == CAIRO_EXTEND_NONE || - source->extend == CAIRO_EXTEND_PAD || - (CGContextDrawTiledImagePtr && source->extend == CAIRO_EXTEND_REPEAT))) - { - const cairo_surface_pattern_t *spat = (const cairo_surface_pattern_t *) source; - cairo_surface_t *pat_surf = spat->surface; - CGImageRef img; - cairo_matrix_t m = spat->base.matrix; - cairo_rectangle_int_t extents; - CGAffineTransform xform; - CGRect srcRect; - cairo_fixed_t fw, fh; - cairo_bool_t is_bounded; - - /* Draw nonrepeating CGLayer surface using DO_LAYER */ - if (source->extend != CAIRO_EXTEND_REPEAT && - cairo_surface_get_type (pat_surf) == CAIRO_SURFACE_TYPE_QUARTZ) { - cairo_quartz_surface_t *quartz_surf = (cairo_quartz_surface_t *) pat_surf; - if (quartz_surf->cgLayer) { - cairo_matrix_invert(&m); - _cairo_quartz_cairo_matrix_to_quartz (&m, &state->transform); - state->rect = CGRectMake (0, 0, quartz_surf->extents.width, quartz_surf->extents.height); - state->sourceLayer = quartz_surf->cgLayer; - state->action = DO_LAYER; - return CAIRO_STATUS_SUCCESS; - } - } - - _cairo_surface_get_extents (composite->surface, &extents); - status = _cairo_surface_to_cgimage (pat_surf, &extents, format, - &m, clip, &img); - if (unlikely (status)) - return status; - - state->image = img; - - if (state->filter == kCGInterpolationNone && _cairo_matrix_is_translation (&m)) { - m.x0 = -ceil (m.x0 - 0.5); - m.y0 = -ceil (m.y0 - 0.5); - } else { - cairo_matrix_invert (&m); - } - - _cairo_quartz_cairo_matrix_to_quartz (&m, &state->transform); - - if (pat_surf->type != CAIRO_SURFACE_TYPE_RECORDING) { - is_bounded = _cairo_surface_get_extents (pat_surf, &extents); - assert (is_bounded); - } - - srcRect = CGRectMake (0, 0, extents.width, extents.height); - - if (source->extend == CAIRO_EXTEND_NONE || source->extend == CAIRO_EXTEND_PAD) { - int x, y; - if (op == CAIRO_OPERATOR_SOURCE && - (pat_surf->content == CAIRO_CONTENT_ALPHA || - ! _cairo_matrix_is_integer_translation (&m, &x, &y))) - { - state->layer = CGLayerCreateWithContext (surface->cgContext, - state->clipRect.size, - NULL); - state->cgDrawContext = CGLayerGetContext (state->layer); - CGContextTranslateCTM (state->cgDrawContext, - -state->clipRect.origin.x, - -state->clipRect.origin.y); - } - - CGContextSetRGBFillColor (state->cgDrawContext, 0, 0, 0, 1); - - state->rect = srcRect; - state->action = DO_IMAGE; - return CAIRO_STATUS_SUCCESS; - } - - CGContextSetRGBFillColor (state->cgDrawContext, 0, 0, 0, 1); - - /* Quartz seems to tile images at pixel-aligned regions only -- this - * leads to seams if the image doesn't end up scaling to fill the - * space exactly. The CGPattern tiling approach doesn't have this - * problem. Check if we're going to fill up the space (within some - * epsilon), and if not, fall back to the CGPattern type. - */ - xform = CGAffineTransformConcat (CGContextGetCTM (state->cgDrawContext), - state->transform); - - srcRect = CGRectApplyAffineTransform (srcRect, xform); - - fw = _cairo_fixed_from_double (srcRect.size.width); - fh = _cairo_fixed_from_double (srcRect.size.height); - - if ((fw & CAIRO_FIXED_FRAC_MASK) <= CAIRO_FIXED_EPSILON && - (fh & CAIRO_FIXED_FRAC_MASK) <= CAIRO_FIXED_EPSILON) - { - /* We're good to use DrawTiledImage, but ensure that - * the math works out */ - - srcRect.size.width = round (srcRect.size.width); - srcRect.size.height = round (srcRect.size.height); - - xform = CGAffineTransformInvert (xform); - - srcRect = CGRectApplyAffineTransform (srcRect, xform); - - state->rect = srcRect; - state->action = DO_TILED_IMAGE; - return CAIRO_STATUS_SUCCESS; - } - - /* Fall through to generic SURFACE case */ - } - - if (source->type == CAIRO_PATTERN_TYPE_SURFACE) { - cairo_quartz_float_t patternAlpha = 1.0f; - CGColorSpaceRef patternSpace; - CGPatternRef pattern = NULL; - cairo_int_status_t status; - - status = _cairo_quartz_cairo_repeating_surface_pattern_to_quartz (surface, source, clip, &pattern); - if (unlikely (status)) - return status; - - patternSpace = CGColorSpaceCreatePattern (NULL); - CGContextSetFillColorSpace (state->cgDrawContext, patternSpace); - CGContextSetFillPattern (state->cgDrawContext, pattern, &patternAlpha); - CGContextSetStrokeColorSpace (state->cgDrawContext, patternSpace); - CGContextSetStrokePattern (state->cgDrawContext, pattern, &patternAlpha); - CGColorSpaceRelease (patternSpace); - - /* Quartz likes to munge the pattern phase (as yet unexplained - * why); force it to 0,0 as we've already baked in the correct - * pattern translation into the pattern matrix - */ - CGContextSetPatternPhase (state->cgDrawContext, CGSizeMake (0, 0)); - - CGPatternRelease (pattern); - - state->action = DO_DIRECT; - return CAIRO_STATUS_SUCCESS; - } + if (source->type == CAIRO_PATTERN_TYPE_SURFACE) + return _cairo_quartz_setup_pattern_source (state, source, surface, clip, op); return CAIRO_INT_STATUS_UNSUPPORTED; } @@ -1414,9 +1341,10 @@ _cairo_quartz_teardown_state (cairo_quartz_drawing_state_t *state, cairo_quartz_surface_t *surface = (cairo_quartz_surface_t *) extents->surface; if (state->layer) { - CGContextDrawLayerInRect (surface->cgContext, - state->clipRect, - state->layer); + if (state->action != DO_LAYER) + CGContextDrawLayerInRect (surface->cgContext, + state->clipRect, + state->layer); CGLayerRelease (state->layer); } @@ -1430,6 +1358,33 @@ _cairo_quartz_teardown_state (cairo_quartz_drawing_state_t *state, CGShadingRelease (state->shading); } +static inline void +_cairo_quartz_draw_cgcontext (cairo_quartz_drawing_state_t *state, + cairo_operator_t op) +{ + CGColorSpaceRef cs = _cairo_quartz_create_color_space (state->cgDrawContext); + CGColorRef transparent = _cairo_quartz_create_cgcolor (cs, 0.0, 0.0, 0.0, 0.0); //releases cs + + if (! (op == CAIRO_OPERATOR_SOURCE && + state->cgDrawContext == state->cgMaskContext)) + return; + + CGContextBeginPath (state->cgDrawContext); + CGContextAddRect (state->cgDrawContext, state->rect); + + CGContextTranslateCTM (state->cgDrawContext, 0, state->rect.size.height); + CGContextScaleCTM (state->cgDrawContext, 1, -1); + CGContextConcatCTM (state->cgDrawContext, + CGAffineTransformInvert (state->transform)); + + CGContextAddRect (state->cgDrawContext, state->clipRect); + + CGContextSetFillColorWithColor (state->cgDrawContext, transparent); + CGContextEOFillPath (state->cgDrawContext); + CGColorRelease (transparent); +} + + static void _cairo_quartz_draw_source (cairo_quartz_drawing_state_t *state, cairo_operator_t op) @@ -1452,34 +1407,18 @@ _cairo_quartz_draw_source (cairo_quartz_drawing_state_t *state, CGContextTranslateCTM (state->cgDrawContext, 0, state->rect.size.height); CGContextScaleCTM (state->cgDrawContext, 1, -1); - if (state->action == DO_LAYER) { - /* Note that according to Apple docs it's completely legal to draw a CGLayer - * to any CGContext, even one it wasn't created for. - */ - assert (state->sourceLayer); - CGContextDrawLayerAtPoint (state->cgDrawContext, state->rect.origin, - state->sourceLayer); - } else if (state->action == DO_IMAGE) { + if (state->action == DO_IMAGE) { CGContextDrawImage (state->cgDrawContext, state->rect, state->image); - if (op == CAIRO_OPERATOR_SOURCE && - state->cgDrawContext == state->cgMaskContext) - { - CGContextBeginPath (state->cgDrawContext); - CGContextAddRect (state->cgDrawContext, state->rect); - - CGContextTranslateCTM (state->cgDrawContext, 0, state->rect.size.height); - CGContextScaleCTM (state->cgDrawContext, 1, -1); - CGContextConcatCTM (state->cgDrawContext, - CGAffineTransformInvert (state->transform)); - - CGContextAddRect (state->cgDrawContext, state->clipRect); + _cairo_quartz_draw_cgcontext (state, op); + return; + } - CGContextSetRGBFillColor (state->cgDrawContext, 0, 0, 0, 0); - CGContextEOFillPath (state->cgDrawContext); - } - } else { - CGContextDrawTiledImagePtr (state->cgDrawContext, state->rect, state->image); + if (state->action == DO_LAYER) { + CGContextDrawLayerInRect (state->cgDrawContext, state->rect, state->layer); + _cairo_quartz_draw_cgcontext (state, op); + return; } + assert (FALSE); // Unreachable } static cairo_image_surface_t * @@ -1487,26 +1426,25 @@ _cairo_quartz_surface_map_to_image (void *abstract_surface, const cairo_rectangle_int_t *extents) { cairo_quartz_surface_t *surface = (cairo_quartz_surface_t *) abstract_surface; + cairo_surface_t *return_surface = NULL; unsigned int stride, bitinfo, bpp, color_comps; CGColorSpaceRef colorspace; - void *imageData; + unsigned char *imageData; cairo_format_t format; - if (surface->imageSurfaceEquiv) - return _cairo_surface_map_to_image (surface->imageSurfaceEquiv, extents); - - if (IS_EMPTY (surface)) + if (_cairo_quartz_is_zero_surface (&surface->base)) return (cairo_image_surface_t *) cairo_image_surface_create (CAIRO_FORMAT_ARGB32, 0, 0); if (! _cairo_quartz_is_cgcontext_bitmap_context (surface->cgContext)) - return _cairo_image_surface_create_in_error (_cairo_error (CAIRO_STATUS_NO_MEMORY)); + return _cairo_image_surface_create_in_error (_cairo_error (CAIRO_STATUS_SURFACE_TYPE_MISMATCH)); bitinfo = CGBitmapContextGetBitmapInfo (surface->cgContext); bpp = CGBitmapContextGetBitsPerPixel (surface->cgContext); // let's hope they don't add YUV under us - colorspace = CGBitmapContextGetColorSpace (surface->cgContext); + colorspace = _cairo_quartz_create_color_space (surface->cgContext); color_comps = CGColorSpaceGetNumberOfComponents (colorspace); + CGColorSpaceRelease (colorspace); /* XXX TODO: We can handle many more data formats by * converting to pixman_format_t */ @@ -1523,34 +1461,32 @@ _cairo_quartz_surface_map_to_image (void *abstract_surface, { format = CAIRO_FORMAT_RGB24; } - else if (bpp == 8 && color_comps == 1) + else if (bpp == 8 && color_comps == 0) { - format = CAIRO_FORMAT_A1; + format = CAIRO_FORMAT_A8; } else { - return _cairo_image_surface_create_in_error (_cairo_error (CAIRO_STATUS_NO_MEMORY)); + return _cairo_image_surface_create_in_error (_cairo_error (CAIRO_STATUS_INVALID_FORMAT)); } imageData = CGBitmapContextGetData (surface->cgContext); stride = CGBitmapContextGetBytesPerRow (surface->cgContext); - return (cairo_image_surface_t *) cairo_image_surface_create_for_data (imageData, - format, - extents->width, - extents->height, - stride); + imageData += extents->y * stride + extents->x * bpp / 8; + return_surface = cairo_image_surface_create_for_data (imageData, + format, + extents->width, + extents->height, + stride); + + return (cairo_image_surface_t *) return_surface; } static cairo_int_status_t _cairo_quartz_surface_unmap_image (void *abstract_surface, cairo_image_surface_t *image) { - cairo_quartz_surface_t *surface = (cairo_quartz_surface_t *) abstract_surface; - - if (surface->imageSurfaceEquiv) - return _cairo_surface_unmap_image (surface->imageSurfaceEquiv, image); - cairo_surface_finish (&image->base); cairo_surface_destroy (&image->base); @@ -1570,17 +1506,11 @@ _cairo_quartz_get_image (cairo_quartz_surface_t *surface, unsigned char *imageData; cairo_image_surface_t *isurf; - if (IS_EMPTY(surface)) { + if (_cairo_quartz_is_zero_surface (&surface->base)) { *image_out = (cairo_image_surface_t*) cairo_image_surface_create (CAIRO_FORMAT_ARGB32, 0, 0); return CAIRO_STATUS_SUCCESS; } - if (surface->imageSurfaceEquiv) { - CGContextFlush(surface->cgContext); - *image_out = (cairo_image_surface_t*) cairo_surface_reference(surface->imageSurfaceEquiv); - return CAIRO_STATUS_SUCCESS; - } - if (_cairo_quartz_is_cgcontext_bitmap_context(surface->cgContext)) { unsigned int stride; unsigned int bitinfo; @@ -1666,7 +1596,7 @@ _cairo_quartz_surface_finish (void *abstract_surface) ND ((stderr, "_cairo_quartz_surface_finish[%p] cgc: %p\n", surface, surface->cgContext)); - if (IS_EMPTY (surface)) + if (_cairo_quartz_is_zero_surface (&surface->base)) return CAIRO_STATUS_SUCCESS; /* Restore our saved gstate that we use to reset clipping */ @@ -1677,19 +1607,10 @@ _cairo_quartz_surface_finish (void *abstract_surface) surface->cgContext = NULL; - if (surface->imageSurfaceEquiv) { - if (surface->ownsData) - _cairo_image_surface_assume_ownership_of_data (surface->imageSurfaceEquiv); - cairo_surface_destroy (surface->imageSurfaceEquiv); - surface->imageSurfaceEquiv = NULL; - } else if (surface->imageData && surface->ownsData) { - free (surface->imageData); - } - - surface->imageData = NULL; - - if (surface->cgLayer) { - CGLayerRelease (surface->cgLayer); + if (surface->cgLayer) + { + CGLayerRelease (surface->cgLayer); + surface->cgLayer = NULL; } return CAIRO_STATUS_SUCCESS; @@ -1724,20 +1645,66 @@ _cairo_quartz_surface_release_source_image (void *abstract_surface, _cairo_quartz_surface_unmap_image (abstract_surface, image); } +static cairo_surface_t* +_cairo_quartz_surface_create_with_cglayer (cairo_quartz_surface_t *surface, + cairo_content_t content, + int width, int height) +{ + CGAffineTransform xform; + CGContextRef context; + CGLayerRef layer; + cairo_quartz_surface_t* new_surface; + + if (surface->cgContext == NULL || surface->cgLayer != NULL) + return NULL; + + if (width <= 0 || height <= 0) + return NULL; + + xform = CGContextGetUserSpaceToDeviceSpaceTransform (surface->cgContext); + layer = CGLayerCreateWithContext (surface->cgContext, + CGSizeMake (width * xform.a, + height * xform.d), + NULL); + + context = CGLayerGetContext (layer); + CGContextTranslateCTM (context, 0.0, height); + CGContextScaleCTM (context, xform.a, -xform.d); + new_surface = _cairo_quartz_surface_create_internal (context, content, + width, height); + if (unlikely (new_surface->base.status)) + { + CGContextRelease (context); + CGLayerRelease (layer); + return &new_surface->base; + } + new_surface->cgLayer = CGLayerRetain(layer); + CGContextRetain(context); + new_surface->virtual_extents = surface->virtual_extents; + + return &new_surface->base; +} + static cairo_surface_t * _cairo_quartz_surface_create_similar (void *abstract_surface, cairo_content_t content, int width, int height) { - cairo_quartz_surface_t *similar_quartz; + cairo_quartz_surface_t *surface, *similar_quartz; cairo_surface_t *similar; cairo_format_t format; - cairo_quartz_surface_t *surface = (cairo_quartz_surface_t *) abstract_surface; - if (surface->cgLayer) - return cairo_quartz_surface_create_cg_layer (abstract_surface, content, - width, height); + // verify width and height of surface + if (!_cairo_quartz_verify_surface_size (width, height)) { + return _cairo_surface_create_in_error (_cairo_error + (CAIRO_STATUS_INVALID_SIZE)); + } + + surface = (cairo_quartz_surface_t *) abstract_surface; + if (surface->cgContext && !surface->cgLayer && !(width && height)) + _cairo_quartz_surface_create_with_cglayer (surface, content, + width, height); if (content == CAIRO_CONTENT_COLOR_ALPHA) format = CAIRO_FORMAT_ARGB32; @@ -1748,17 +1715,10 @@ _cairo_quartz_surface_create_similar (void *abstract_surface, else return NULL; - // verify width and height of surface - if (!_cairo_quartz_verify_surface_size (width, height)) { - return _cairo_surface_create_in_error (_cairo_error - (CAIRO_STATUS_INVALID_SIZE)); - } - similar = cairo_quartz_surface_create (format, width, height); if (unlikely (similar->status)) return similar; - surface = (cairo_quartz_surface_t *) abstract_surface; similar_quartz = (cairo_quartz_surface_t *) similar; similar_quartz->virtual_extents = surface->virtual_extents; @@ -1902,7 +1862,7 @@ _cairo_quartz_cg_mask (const cairo_compositor_t *compositor, mask_surf = extents->mask_pattern.surface.surface; /* When an opaque surface used as a mask in Quartz, its - * luminosity is used as the alpha value, so we con only use + * luminosity is used as the alpha value, so we can only use * surfaces with alpha without creating a temporary mask. */ need_temp = ! (mask_surf->content & CAIRO_CONTENT_ALPHA); } @@ -2099,17 +2059,15 @@ _cairo_quartz_cg_glyphs (const cairo_compositor_t *compositor, cairo_bool_t permit_subpixel_antialiasing) { CGAffineTransform textTransform, invTextTransform; - CGGlyph glyphs_static[CAIRO_STACK_ARRAY_LENGTH (CGSize)]; - CGSize cg_advances_static[CAIRO_STACK_ARRAY_LENGTH (CGSize)]; + CGGlyph glyphs_static[CAIRO_STACK_ARRAY_LENGTH (CGPoint)]; + CGPoint cg_positions_static[CAIRO_STACK_ARRAY_LENGTH (CGPoint)]; CGGlyph *cg_glyphs = &glyphs_static[0]; - CGSize *cg_advances = &cg_advances_static[0]; - CGPoint *cg_positions; - COMPILE_TIME_ASSERT (sizeof (CGGlyph) <= sizeof (CGSize)); - COMPILE_TIME_ASSERT (sizeof (CGPoint) == sizeof (CGSize)); + CGPoint *cg_positions = &cg_positions_static[0]; cairo_quartz_drawing_state_t state; cairo_int_status_t rv = CAIRO_INT_STATUS_UNSUPPORTED; - int i; + CGPoint origin; + CTFontRef ctFont = NULL; cairo_bool_t didForceFontSmoothing = FALSE; cairo_antialias_t effective_antialiasing; @@ -2128,54 +2086,26 @@ _cairo_quartz_cg_glyphs (const cairo_compositor_t *compositor, CGContextSetTextDrawingMode (state.cgMaskContext, kCGTextClip); } - if (!CTFontDrawGlyphsPtr) { - /* this doesn't addref */ - CGFontRef cgfref = _cairo_quartz_scaled_font_get_cg_font_ref (scaled_font); - CGContextSetFont (state.cgMaskContext, cgfref); - CGContextSetFontSize (state.cgMaskContext, 1.0); - } + /* this doesn't addref */ + ctFont = _cairo_quartz_scaled_font_get_ct_font (scaled_font); + _cairo_quartz_set_antialiasing (state.cgMaskContext, scaled_font->options.antialias); effective_antialiasing = scaled_font->options.antialias; if (effective_antialiasing == CAIRO_ANTIALIAS_SUBPIXEL && !permit_subpixel_antialiasing) { effective_antialiasing = CAIRO_ANTIALIAS_GRAY; } - switch (effective_antialiasing) { - case CAIRO_ANTIALIAS_SUBPIXEL: - case CAIRO_ANTIALIAS_BEST: - CGContextSetShouldAntialias (state.cgMaskContext, TRUE); - CGContextSetShouldSmoothFonts (state.cgMaskContext, TRUE); - if (CGContextSetAllowsFontSmoothingPtr && - !CGContextGetAllowsFontSmoothingPtr (state.cgMaskContext)) - { - didForceFontSmoothing = TRUE; - CGContextSetAllowsFontSmoothingPtr (state.cgMaskContext, TRUE); - } - break; - case CAIRO_ANTIALIAS_NONE: - CGContextSetShouldAntialias (state.cgMaskContext, FALSE); - break; - case CAIRO_ANTIALIAS_GRAY: - case CAIRO_ANTIALIAS_GOOD: - case CAIRO_ANTIALIAS_FAST: - CGContextSetShouldAntialias (state.cgMaskContext, TRUE); - CGContextSetShouldSmoothFonts (state.cgMaskContext, FALSE); - break; - case CAIRO_ANTIALIAS_DEFAULT: - /* Don't do anything */ - break; - } - if (num_glyphs > ARRAY_LENGTH (glyphs_static)) { - cg_advances = _cairo_malloc_ab (num_glyphs, - sizeof (CGSize) + sizeof (CGGlyph)); + _cairo_quartz_set_antialiasing (state.cgMaskContext, effective_antialiasing); - if (unlikely (cg_advances == NULL)) { + if (num_glyphs > ARRAY_LENGTH (glyphs_static)) { + cg_glyphs = (CGGlyph*) _cairo_malloc_ab (num_glyphs, sizeof (CGGlyph) + sizeof (CGPoint)); + if (unlikely (cg_glyphs == NULL)) { rv = _cairo_error (CAIRO_STATUS_NO_MEMORY); goto BAIL; } - cg_glyphs = (CGGlyph*) (cg_advances + num_glyphs); + cg_positions = (CGPoint*) (cg_glyphs + num_glyphs); } /* scale(1,-1) * scaled_font->scale */ @@ -2192,72 +2122,35 @@ _cairo_quartz_cg_glyphs (const cairo_compositor_t *compositor, -scaled_font->scale_inverse.yy, 0.0, 0.0); - /* - * CGContextShowGlyphsWithAdvances does not transform the advances - * by the text matrix, if the drawing mode is kCGTextClip. Instead - * of trying to recompute the advances, make sure that the text - * matrix is the identity and rely on the CTM for the text - * transform. - */ - CGContextSetTextMatrix (state.cgMaskContext, CGAffineTransformIdentity); - CGContextTranslateCTM (state.cgMaskContext, glyphs[0].x, glyphs[0].y); - CGContextConcatCTM (state.cgMaskContext, textTransform); - /* Convert glyph positions to glyph advances. */ - cg_glyphs[0] = glyphs[0].index; - for (i = 1; i < num_glyphs; i++) { - CGSize advance = CGSizeMake (glyphs[i].x - glyphs[i-1].x, - glyphs[i].y - glyphs[i-1].y); - cg_advances[i] = CGSizeApplyAffineTransform (advance, invTextTransform); + origin = CGPointMake (glyphs[0].x, glyphs[0].y); + for (int i = 0; i < num_glyphs; ++i) + { cg_glyphs[i] = glyphs[i].index; + cg_positions[i] = CGPointMake (glyphs[i].x - origin.x, glyphs[i].y - origin.y); + cg_positions[i] = CGPointApplyAffineTransform (cg_positions[i], invTextTransform); } - if (CTFontDrawGlyphsPtr) { - /* If CTFontDrawGlyphs is available, we want to use that - * instead of the deprecated CGContextShowGlyphsWithAdvances - * so that colored-bitmap fonts like Apple Color Emoji will - * render properly. */ - - /* Accumulate the glyph advances into glyph positions, - * overwriting them. Start at (0,0) because the CTM already - * takes into account the position of the first glyph. */ - CGPoint pos = CGPointMake (0, 0); - cg_positions = (CGPoint *) cg_advances; - cg_positions[0] = pos; - for (i = 1; i < num_glyphs; i++) { - pos.x += cg_advances[i].width; - pos.y += cg_advances[i].height; - cg_positions[i] = pos; - } + /* Translate to the first glyph's position before drawing */ + CGContextTranslateCTM (state.cgMaskContext, origin.x, origin.y); + CGContextConcatCTM (state.cgMaskContext, textTransform); - CTFontDrawGlyphsPtr (_cairo_quartz_scaled_font_get_ct_font_ref (scaled_font), - cg_glyphs, - cg_positions, - num_glyphs, - state.cgMaskContext); - } else { - CGContextShowGlyphsWithAdvances (state.cgMaskContext, - cg_glyphs, - cg_advances + 1, - num_glyphs); - } + CTFontDrawGlyphs (ctFont, cg_glyphs, cg_positions, num_glyphs, state.cgMaskContext); - /* Revert the changes to the CTM. This fragment cannot rely on - * CG{Save,Restore}GState, as that would reset the clip. */ CGContextConcatCTM (state.cgMaskContext, invTextTransform); - CGContextTranslateCTM (state.cgMaskContext, -glyphs[0].x, -glyphs[0].y); + CGContextTranslateCTM (state.cgMaskContext, -origin.x, -origin.y); if (state.action != DO_DIRECT) _cairo_quartz_draw_source (&state, extents->op); BAIL: if (didForceFontSmoothing) - CGContextSetAllowsFontSmoothingPtr (state.cgMaskContext, FALSE); + CGContextSetAllowsFontSmoothing (state.cgMaskContext, FALSE); _cairo_quartz_teardown_state (&state, extents); - if (cg_advances != cg_advances_static) - free (cg_advances); + if (cg_glyphs != glyphs_static) + free (cg_glyphs); return rv; } @@ -2360,7 +2253,7 @@ _cairo_quartz_surface_clipper_intersect_clip_path (cairo_surface_clipper_t *clip ND ((stderr, "%p _cairo_quartz_surface_intersect_clip_path path: %p\n", surface, path)); - if (IS_EMPTY (surface)) + if (_cairo_quartz_is_zero_surface (&surface->base)) return CAIRO_STATUS_SUCCESS; if (path == NULL) { @@ -2532,7 +2425,7 @@ _cairo_quartz_surface_tag (void *abstract_surface, // XXXtodo implement show_page; need to figure out how to handle begin/end -static const struct _cairo_surface_backend cairo_quartz_surface_backend = { +static const cairo_surface_backend_t cairo_quartz_surface_backend = { CAIRO_SURFACE_TYPE_QUARTZ, _cairo_quartz_surface_finish, @@ -2563,10 +2456,9 @@ static const struct _cairo_surface_backend cairo_quartz_surface_backend = { _cairo_quartz_surface_fill, NULL, /* fill-stroke */ _cairo_quartz_surface_glyphs, - - NULL, /* has_show_text_glyphs */ - NULL, /* show_text_glyphs */ - NULL, /* get_supported_mime_types */ + NULL, /* has_show_text_glyphs */ + NULL, /* show_text_glyphs */ + NULL, /* get_supported_mime_types */ _cairo_quartz_surface_tag /* tag */ }; @@ -2578,8 +2470,6 @@ _cairo_quartz_surface_create_internal (CGContextRef cgContext, { cairo_quartz_surface_t *surface; - quartz_ensure_symbols (); - /* Init the base surface */ surface = _cairo_malloc (sizeof (cairo_quartz_surface_t)); if (unlikely (surface == NULL)) @@ -2601,11 +2491,8 @@ _cairo_quartz_surface_create_internal (CGContextRef cgContext, surface->extents.width = width; surface->extents.height = height; surface->virtual_extents = surface->extents; - surface->imageData = NULL; - surface->imageSurfaceEquiv = NULL; - - if (IS_EMPTY (surface)) { + if (_cairo_quartz_is_zero_surface (&surface->base)) { surface->cgContext = NULL; surface->cgContextBaseCTM = CGAffineTransformIdentity; surface->base.is_clear = TRUE; @@ -2620,8 +2507,6 @@ _cairo_quartz_surface_create_internal (CGContextRef cgContext, surface->cgContext = cgContext; surface->cgContextBaseCTM = CGContextGetCTM (cgContext); - surface->ownsData = TRUE; - return surface; } @@ -2657,10 +2542,9 @@ cairo_quartz_surface_create_for_cg_context (CGContextRef cgContext, unsigned int width, unsigned int height) { - cairo_quartz_surface_t *surf; - - surf = _cairo_quartz_surface_create_internal (cgContext, CAIRO_CONTENT_COLOR_ALPHA, - width, height); + cairo_quartz_surface_t *surf = + _cairo_quartz_surface_create_internal (cgContext, CAIRO_CONTENT_COLOR_ALPHA, + width, height); if (likely (!surf->base.status)) CGContextRetain (cgContext); @@ -2668,86 +2552,19 @@ cairo_quartz_surface_create_for_cg_context (CGContextRef cgContext, } /** - * cairo_quartz_surface_create_cg_layer - * @surface: The returned surface can be efficiently drawn into this - * destination surface (if tiling is not used)." - * @content: the content type of the surface - * @width: width of the surface, in pixels - * @height: height of the surface, in pixels - * - * Creates a Quartz surface backed by a CGLayer, if the given surface - * is a Quartz surface; the CGLayer is created to match the surface's - * Quartz context. Otherwise just calls cairo_surface_create_similar. - * The returned surface can be efficiently blitted to the given surface, - * but tiling and 'extend' modes other than NONE are not so efficient. - * - * Return value: the newly created surface. - * - * Since: 1.10 - **/ -cairo_surface_t * -cairo_quartz_surface_create_cg_layer (cairo_surface_t *surface, - cairo_content_t content, - unsigned int width, - unsigned int height) -{ - cairo_quartz_surface_t *surf; - CGLayerRef layer; - CGContextRef ctx; - CGContextRef cgContext; - - cgContext = cairo_quartz_surface_get_cg_context (surface); - if (!cgContext) - return cairo_surface_create_similar (surface, content, - width, height); - - if (!_cairo_quartz_verify_surface_size(width, height)) - return _cairo_surface_create_in_error (_cairo_error (CAIRO_STATUS_INVALID_SIZE)); - - /* If we pass zero width or height into CGLayerCreateWithContext below, - * it will fail. - */ - if (width == 0 || height == 0) { - return (cairo_surface_t*) - _cairo_quartz_surface_create_internal (NULL, content, - width, height); - } - - layer = CGLayerCreateWithContext (cgContext, - CGSizeMake (width, height), - NULL); - if (!layer) - return _cairo_surface_create_in_error (_cairo_error (CAIRO_STATUS_NO_MEMORY)); - - ctx = CGLayerGetContext (layer); - /* Flip it when we draw into it, so that when we finally composite it - * to a flipped target, the directions match and Quartz will optimize - * the composition properly - */ - CGContextTranslateCTM (ctx, 0, height); - CGContextScaleCTM (ctx, 1, -1); - - CGContextRetain (ctx); - surf = _cairo_quartz_surface_create_internal (ctx, content, - width, height); - if (surf->base.status) { - CGLayerRelease (layer); - // create_internal will have set an error - return (cairo_surface_t*) surf; - } - surf->cgLayer = layer; - - return (cairo_surface_t *) surf; -} - -/** * cairo_quartz_surface_create: * @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 Quartz surface backed by a CGBitmap. The surface is - * created using the Device RGB (or Device Gray, for A8) color space. + * Creates a Quartz surface backed by a CGBitmapContext using the main + * display's colorspace to avoid an expensive colorspace transform + * done serially on the CPU. This may produce slightly different + * colors from what's intended. Programs for which color management is + * important should create their own CGBitmapContext with a + * device-independent color space; most will expect Cairo to draw in + * sRGB and would use CGColorSpaceCreateWithName(kCGColorSpaceSRGB). + * * All Cairo operations, including those that require software * rendering, will succeed on this surface. * @@ -2764,7 +2581,7 @@ cairo_quartz_surface_create (cairo_format_t format, CGContextRef cgc; CGColorSpaceRef cgColorspace; CGBitmapInfo bitinfo; - void *imageData; + void *imageData = NULL; int stride; int bitsPerComponent; @@ -2779,7 +2596,7 @@ cairo_quartz_surface_create (cairo_format_t format, if (format == CAIRO_FORMAT_ARGB32 || format == CAIRO_FORMAT_RGB24) { - cgColorspace = CGColorSpaceCreateDeviceRGB (); + cgColorspace = _cairo_quartz_create_color_space (NULL); bitinfo = kCGBitmapByteOrder32Host; if (format == CAIRO_FORMAT_ARGB32) bitinfo |= kCGImageAlphaPremultipliedFirst; @@ -2807,16 +2624,6 @@ cairo_quartz_surface_create (cairo_format_t format, * so we don't have to anything special on allocation. */ stride = (stride + 15) & ~15; - - imageData = _cairo_malloc_ab (height, stride); - if (unlikely (!imageData)) { - CGColorSpaceRelease (cgColorspace); - return _cairo_surface_create_in_error (_cairo_error (CAIRO_STATUS_NO_MEMORY)); - } - - /* zero the memory to match the image surface behaviour */ - memset (imageData, 0, height * stride); - cgc = CGBitmapContextCreate (imageData, width, height, @@ -2827,7 +2634,9 @@ cairo_quartz_surface_create (cairo_format_t format, CGColorSpaceRelease (cgColorspace); if (!cgc) { - free (imageData); + if (imageData) + free (imageData); + return _cairo_surface_create_in_error (_cairo_error (CAIRO_STATUS_NO_MEMORY)); } @@ -2839,19 +2648,16 @@ cairo_quartz_surface_create (cairo_format_t format, width, height); if (surf->base.status) { CGContextRelease (cgc); - free (imageData); + + if (imageData) + free (imageData); + // create_internal will have set an error return &surf->base; } surf->base.is_clear = TRUE; - surf->imageData = imageData; - surf->imageSurfaceEquiv = cairo_image_surface_create_for_data (imageData, format, width, height, stride); - - // We created this data, so we can delete it. - surf->ownsData = TRUE; - return &surf->base; } @@ -2879,8 +2685,14 @@ cairo_quartz_surface_get_cg_context (cairo_surface_t *surface) if (surface && _cairo_surface_is_quartz (surface)) { cairo_quartz_surface_t *quartz = (cairo_quartz_surface_t *) surface; return quartz->cgContext; - } else - return NULL; + } + + if (surface && _cairo_surface_is_quartz_image (surface)) { + cairo_quartz_image_surface_t *quartz = (cairo_quartz_image_surface_t *) surface; + return quartz->cgContext; + } + + return NULL; } /** @@ -2897,111 +2709,109 @@ _cairo_surface_is_quartz (const cairo_surface_t *surface) return surface->backend == &cairo_quartz_surface_backend; } -cairo_surface_t * -cairo_quartz_surface_get_image (cairo_surface_t *surface) +cairo_surface_t* +_cairo_quartz_snapshot_create (cairo_surface_t *surface) { - cairo_quartz_surface_t *quartz = (cairo_quartz_surface_t *)surface; - cairo_image_surface_t *image; - - if (_cairo_quartz_get_image(quartz, &image)) - return NULL; + cairo_quartz_snapshot_t *snapshot = NULL; + CGContextRef cgContext; + if (!surface || ! _is_quartz_surface (surface) || _cairo_quartz_is_zero_surface (surface)) + return NULL; - return (cairo_surface_t *)image; -} + if (_cairo_surface_is_quartz (surface) && + ! _cairo_quartz_is_cgcontext_bitmap_context (((cairo_quartz_surface_t*)surface)->cgContext)) + return NULL; -/* Debug stuff */ + snapshot = _cairo_malloc (sizeof (cairo_quartz_snapshot_t)); -#ifdef QUARTZ_DEBUG + if (unlikely (surface == NULL)) + return _cairo_surface_create_in_error (_cairo_error (CAIRO_STATUS_NO_MEMORY)); -#include <Movies.h> + memset (snapshot, 0, sizeof (cairo_quartz_snapshot_t)); + cgContext = cairo_quartz_surface_get_cg_context (surface); + _cairo_surface_init (&snapshot->base, + &cairo_quartz_snapshot_backend, + NULL, CAIRO_CONTENT_COLOR_ALPHA, FALSE); + snapshot->image = CGBitmapContextCreateImage (cgContext); + _cairo_surface_attach_snapshot (surface, &snapshot->base, NULL); + cairo_surface_destroy (&snapshot->base); // The surface has reffed the snapshot so we must unref it here. + + return &snapshot->base; +} -void ExportCGImageToPNGFile (CGImageRef inImageRef, char* dest) +cairo_status_t +_cairo_quartz_snapshot_finish (void *surface) { - Handle dataRef = NULL; - OSType dataRefType; - CFStringRef inPath = CFStringCreateWithCString (NULL, dest, kCFStringEncodingASCII); - - GraphicsExportComponent grex = 0; - unsigned long sizeWritten; - - ComponentResult result; - - // create the data reference - result = QTNewDataReferenceFromFullPathCFString (inPath, kQTNativeDefaultPathStyle, - 0, &dataRef, &dataRefType); - - if (NULL != dataRef && noErr == result) { - // 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 (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); - } - } - - // remember to close the component - CloseComponent (grex); - } - - // remember to dispose of the data reference handle - DisposeHandle (dataRef); - } + cairo_quartz_snapshot_t *snapshot = (cairo_quartz_snapshot_t *)surface; + if (snapshot->image) + CGImageRelease (snapshot->image); + return CAIRO_STATUS_SUCCESS; } -void -quartz_image_to_png (CGImageRef imgref, char *dest) +CGImageRef +_cairo_quartz_surface_snapshot_get_image (cairo_surface_t *surface) { - static int sctr = 0; - char sptr[] = "/Users/vladimir/Desktop/barXXXXX.png"; + cairo_surface_t *snapshot; + assert (_is_quartz_surface (surface)); + snapshot = + _cairo_surface_has_snapshot (surface, &cairo_quartz_snapshot_backend); - if (dest == NULL) { - fprintf (stderr, "** Writing %p to bar%d\n", imgref, sctr); - sprintf (sptr, "/Users/vladimir/Desktop/bar%d.png", sctr); - sctr++; - dest = sptr; + if (unlikely (!snapshot)) + { + snapshot = _cairo_quartz_snapshot_create (surface); + if (unlikely (!snapshot || cairo_surface_status (snapshot))) + return NULL; } - ExportCGImageToPNGFile (imgref, dest); + return CGImageRetain (((cairo_quartz_snapshot_t*)snapshot)->image); } void -quartz_surface_to_png (cairo_quartz_surface_t *nq, char *dest) +_cairo_quartz_image_to_png (CGImageRef image, const char *dest) { - static int sctr = 0; - char sptr[] = "/Users/vladimir/Desktop/fooXXXXX.png"; + CFStringRef png_utti = CFSTR("public.png"); + CFStringRef path; + CFURLRef url; + CGImageDestinationRef image_dest; - if (nq->base.type != CAIRO_SURFACE_TYPE_QUARTZ) { - fprintf (stderr, "** quartz_surface_to_png: surface %p isn't quartz!\n", nq); + if (!dest) return; - } + path = CFStringCreateWithCString (NULL, dest, kCFStringEncodingUTF8); + url = CFURLCreateWithFileSystemPath (NULL, path, kCFURLPOSIXPathStyle, FALSE); + image_dest = CGImageDestinationCreateWithURL (url, png_utti, 1, NULL); - if (dest == NULL) { - fprintf (stderr, "** Writing %p to foo%d\n", nq, sctr); - sprintf (sptr, "/Users/vladimir/Desktop/foo%d.png", sctr); - sctr++; - dest = sptr; - } + CGImageDestinationAddImage (image_dest, image, NULL); + CGImageDestinationFinalize (image_dest); - CGImageRef imgref = CGBitmapContextCreateImage (nq->cgContext); - if (imgref == NULL) { - fprintf (stderr, "quartz surface at %p is not a bitmap context!\n", nq); - return; + CFRelease (url); + CFRelease (path); + } + +cairo_status_t +_cairo_quartz_surface_to_png (cairo_surface_t *abstract_surface, const char *dest) +{ + CGImageRef image; + cairo_quartz_surface_t *surface; + if (!(_cairo_surface_is_quartz (abstract_surface) && + _cairo_quartz_is_cgcontext_bitmap_context (((cairo_quartz_surface_t*)abstract_surface)->cgContext))) { + return CAIRO_STATUS_SURFACE_TYPE_MISMATCH; } - ExportCGImageToPNGFile (imgref, dest); + surface = (cairo_quartz_surface_t*)abstract_surface; + image = CGBitmapContextCreateImage (surface->cgContext); + _cairo_quartz_image_to_png (image, dest); - CGImageRelease (imgref); + CGImageRelease (image); + return CAIRO_STATUS_SUCCESS; } -#endif /* QUARTZ_DEBUG */ +cairo_surface_t * +cairo_quartz_surface_get_image (cairo_surface_t *surface) +{ + cairo_quartz_surface_t *quartz = (cairo_quartz_surface_t *)surface; + cairo_image_surface_t *image; + + if (_cairo_quartz_get_image(quartz, &image)) + return NULL; + + return (cairo_surface_t *)image; +} diff --git a/gfx/cairo/cairo/src/cairo-quartz.h b/gfx/cairo/cairo/src/cairo-quartz.h index 2118d8ff9c..009e3e9fb8 100644 --- a/gfx/cairo/cairo/src/cairo-quartz.h +++ b/gfx/cairo/cairo/src/cairo-quartz.h @@ -49,6 +49,10 @@ #include <ApplicationServices/ApplicationServices.h> #endif +#if CAIRO_HAS_IMAGE_IO +#include <ImageIO/ImageIO.h> +#endif + CAIRO_BEGIN_DECLS cairo_public cairo_surface_t * @@ -61,12 +65,6 @@ cairo_quartz_surface_create_for_cg_context (CGContextRef cgContext, unsigned int width, unsigned int height); -cairo_public cairo_surface_t * -cairo_quartz_surface_create_cg_layer (cairo_surface_t *surface, - cairo_content_t content, - unsigned int width, - unsigned int height); - cairo_public CGContextRef cairo_quartz_surface_get_cg_context (cairo_surface_t *surface); diff --git a/gfx/cairo/cairo/src/cairo-recording-surface-private.h b/gfx/cairo/cairo/src/cairo-recording-surface-private.h index e8d98e8fa7..2ee414e7d1 100644 --- a/gfx/cairo/cairo/src/cairo-recording-surface-private.h +++ b/gfx/cairo/cairo/src/cairo-recording-surface-private.h @@ -1,3 +1,4 @@ +/* -*- 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 @@ -55,14 +56,19 @@ typedef enum { } cairo_command_type_t; typedef enum { - CAIRO_RECORDING_REGION_ALL, + CAIRO_RECORDING_REGION_ALL = 0, CAIRO_RECORDING_REGION_NATIVE, CAIRO_RECORDING_REGION_IMAGE_FALLBACK } cairo_recording_region_type_t; +typedef enum { + CAIRO_RECORDING_REPLAY, + CAIRO_RECORDING_CREATE_REGIONS, + CAIRO_RECORDING_REPLAY_REGION +} cairo_recording_replay_type_t; + typedef struct _cairo_command_header { cairo_command_type_t type; - cairo_recording_region_type_t region; cairo_operator_t op; cairo_rectangle_int_t extents; cairo_clip_t *clip; @@ -149,15 +155,33 @@ typedef struct _cairo_recording_surface { cairo_bool_t optimize_clears; cairo_bool_t has_bilevel_alpha; cairo_bool_t has_only_op_over; + cairo_bool_t has_tags; struct bbtree { cairo_box_t extents; struct bbtree *left, *right; cairo_command_header_t *chain; } bbtree; + + /* The mutex protects modification to all subsequent fields. */ + cairo_mutex_t mutex; + + cairo_list_t region_array_list; + } cairo_recording_surface_t; -slim_hidden_proto (cairo_recording_surface_create); +typedef struct _cairo_recording_region_element { + cairo_recording_region_type_t region; + unsigned int source_id; + unsigned int mask_id; +} cairo_recording_region_element_t; + +typedef struct _cairo_recording_region_array { + unsigned int id; + cairo_reference_count_t ref_count; + cairo_array_t regions; /* cairo_recording_region_element_t */ + cairo_list_t link; +} cairo_recording_regions_array_t; cairo_private cairo_int_status_t _cairo_recording_surface_get_path (cairo_surface_t *surface, @@ -173,21 +197,38 @@ _cairo_recording_surface_replay (cairo_surface_t *surface, cairo_surface_t *target); cairo_private cairo_status_t -_cairo_recording_surface_replay_with_clip (cairo_surface_t *surface, - const cairo_matrix_t *surface_transform, - cairo_surface_t *target, - const cairo_clip_t *target_clip); +_cairo_recording_surface_replay_with_foreground_color (cairo_surface_t *surface, + cairo_surface_t *target, + const cairo_color_t *foreground_color, + cairo_bool_t *foreground_used); + +cairo_private cairo_status_t +_cairo_recording_surface_replay_with_transform (cairo_surface_t *surface, + const cairo_matrix_t *surface_transform, + cairo_surface_t *target, + cairo_bool_t surface_is_unbounded, + cairo_bool_t replay_all); cairo_private cairo_status_t -_cairo_recording_surface_replay_and_create_regions (cairo_surface_t *surface, +_cairo_recording_surface_replay_with_clip (cairo_surface_t *surface, + const cairo_matrix_t *surface_transform, + cairo_surface_t *target, + const cairo_clip_t *target_clip); + +cairo_private cairo_status_t +_cairo_recording_surface_replay_and_create_regions (cairo_surface_t *surface, + unsigned int regions_id, const cairo_matrix_t *surface_transform, - cairo_surface_t *target, - cairo_bool_t surface_is_unbounded); + cairo_surface_t *target, + cairo_bool_t surface_is_unbounded, + cairo_bool_t replay_all); + cairo_private cairo_status_t _cairo_recording_surface_replay_region (cairo_surface_t *surface, - const cairo_rectangle_int_t *surface_extents, + unsigned int regions_id, + const cairo_rectangle_int_t *surface_extents, cairo_surface_t *target, - cairo_recording_region_type_t region); + cairo_recording_region_type_t region); cairo_private cairo_status_t _cairo_recording_surface_get_bbox (cairo_recording_surface_t *recording, @@ -205,4 +246,26 @@ _cairo_recording_surface_has_only_bilevel_alpha (cairo_recording_surface_t *surf cairo_private cairo_bool_t _cairo_recording_surface_has_only_op_over (cairo_recording_surface_t *surface); +cairo_private cairo_bool_t +_cairo_recording_surface_has_tags (cairo_surface_t *surface); + +cairo_private cairo_status_t +_cairo_recording_surface_region_array_attach (cairo_surface_t *surface, + unsigned int *id); + +cairo_private void +_cairo_recording_surface_region_array_reference (cairo_surface_t *surface, + unsigned int id); + +cairo_private void +_cairo_recording_surface_region_array_remove (cairo_surface_t *surface, + unsigned int id); + +cairo_private void +_cairo_debug_print_recording_surface (FILE *file, + cairo_surface_t *surface, + unsigned int regions_id, + int indent, + cairo_bool_t recurse); + #endif /* CAIRO_RECORDING_SURFACE_H */ diff --git a/gfx/cairo/cairo/src/cairo-recording-surface.c b/gfx/cairo/cairo/src/cairo-recording-surface.c index 327bff3c39..9089f7bb6c 100644 --- a/gfx/cairo/cairo/src/cairo-recording-surface.c +++ b/gfx/cairo/cairo/src/cairo-recording-surface.c @@ -86,15 +86,25 @@ #include "cairo-default-context-private.h" #include "cairo-error-private.h" #include "cairo-image-surface-private.h" +#include "cairo-list-inline.h" #include "cairo-recording-surface-inline.h" #include "cairo-surface-snapshot-inline.h" #include "cairo-surface-wrapper-private.h" #include "cairo-traps-private.h" -typedef enum { - CAIRO_RECORDING_REPLAY, - CAIRO_RECORDING_CREATE_REGIONS -} cairo_recording_replay_type_t; +typedef struct _cairo_recording_surface_replay_params { + const cairo_rectangle_int_t *surface_extents; + const cairo_matrix_t *surface_transform; + cairo_surface_t *target; + const cairo_clip_t *target_clip; + cairo_bool_t surface_is_unbounded; + cairo_recording_replay_type_t type; + cairo_recording_region_type_t region; + unsigned int regions_id; + const cairo_color_t *foreground_color; + cairo_bool_t foreground_used; + cairo_bool_t replay_all; +} cairo_recording_surface_replay_params_t; static const cairo_surface_backend_t cairo_recording_surface_backend; @@ -355,7 +365,10 @@ _cairo_recording_surface_create_bbtree (cairo_recording_surface_t *surface) return CAIRO_STATUS_SUCCESS; cleanup: - bbtree_del (&surface->bbtree); + if (surface->bbtree.left) + bbtree_del (surface->bbtree.left); + if (surface->bbtree.right) + bbtree_del (surface->bbtree.right); return status; } @@ -424,10 +437,14 @@ cairo_recording_surface_create (cairo_content_t content, surface->optimize_clears = TRUE; surface->has_bilevel_alpha = FALSE; surface->has_only_op_over = FALSE; + surface->has_tags = FALSE; + + CAIRO_MUTEX_INIT (surface->mutex); + + cairo_list_init (&surface->region_array_list); return &surface->base; } -slim_hidden_def (cairo_recording_surface_create); static cairo_surface_t * _cairo_recording_surface_create_similar (void *abstract_surface, @@ -442,12 +459,88 @@ _cairo_recording_surface_create_similar (void *abstract_surface, return cairo_recording_surface_create (content, &extents); } +static void +destroy_pattern_region_array (const cairo_pattern_t *pattern, + unsigned int region_id) +{ + if (region_id != 0) { + if (pattern->type == CAIRO_PATTERN_TYPE_SURFACE) { + cairo_surface_pattern_t *surface_pattern = (cairo_surface_pattern_t *) pattern; + if (_cairo_surface_is_recording (surface_pattern->surface)) + _cairo_recording_surface_region_array_remove (surface_pattern->surface, region_id); + } + } +} + +static void +_cairo_recording_surface_region_array_destroy (cairo_recording_surface_t *surface, + cairo_recording_regions_array_t *region_array) +{ + cairo_command_t **elements; + cairo_recording_region_element_t *region_elements; + int i, num_elements; + + num_elements = MIN(surface->commands.num_elements, _cairo_array_num_elements(®ion_array->regions)); + elements = _cairo_array_index (&surface->commands, 0); + region_elements = _cairo_array_index (®ion_array->regions, 0); + for (i = 0; i < num_elements; i++) { + cairo_command_t *command = elements[i]; + cairo_recording_region_element_t *region_element = ®ion_elements[i]; + + switch (command->header.type) { + case CAIRO_COMMAND_PAINT: + destroy_pattern_region_array (&command->paint.source.base, region_element->source_id); + break; + + case CAIRO_COMMAND_MASK: + destroy_pattern_region_array (&command->mask.source.base, region_element->source_id); + destroy_pattern_region_array (&command->mask.mask.base, region_element->mask_id); + break; + + case CAIRO_COMMAND_STROKE: + destroy_pattern_region_array (&command->stroke.source.base, region_element->source_id); + break; + + case CAIRO_COMMAND_FILL: + destroy_pattern_region_array (&command->fill.source.base, region_element->source_id); + break; + + case CAIRO_COMMAND_SHOW_TEXT_GLYPHS: + destroy_pattern_region_array (&command->show_text_glyphs.source.base, region_element->source_id); + break; + + case CAIRO_COMMAND_TAG: + break; + + default: + ASSERT_NOT_REACHED; + } + } + + _cairo_array_fini (®ion_array->regions); + free (region_array); +} + static cairo_status_t _cairo_recording_surface_finish (void *abstract_surface) { cairo_recording_surface_t *surface = abstract_surface; cairo_command_t **elements; int i, num_elements; + cairo_recording_regions_array_t *region_array, *region_next; + + /* Normally backend surfaces hold a reference to the surface as + * well as the region and free the region before the surface. So + * the regions should already be freed at this point but just in + * case we ensure the regions are freed before destroying the + * surface. */ + cairo_list_foreach_entry_safe (region_array, region_next, + cairo_recording_regions_array_t, + &surface->region_array_list, link) + { + cairo_list_del (®ion_array->link); + _cairo_recording_surface_region_array_destroy (surface, region_array); + } num_elements = surface->commands.num_elements; elements = _cairo_array_index (&surface->commands, 0); @@ -603,7 +696,8 @@ _cairo_recording_surface_acquire_source_image (void *abstract_surface, return CAIRO_STATUS_SUCCESS; } - assert (! surface->unbounded); + if (surface->unbounded) + return CAIRO_INT_STATUS_UNSUPPORTED; image = _cairo_image_surface_create_with_content (surface->base.content, surface->extents.width, surface->extents.height); @@ -611,6 +705,8 @@ _cairo_recording_surface_acquire_source_image (void *abstract_surface, if (unlikely (image->status)) return image->status; + cairo_surface_set_device_offset(image, -surface->extents.x, -surface->extents.y); + /* Handle recursion by returning future reads from the current image */ proxy = attach_proxy (abstract_surface, image); status = _cairo_recording_surface_replay (&surface->base, image); @@ -645,7 +741,6 @@ _command_init (cairo_recording_surface_t *surface, command->type = type; command->op = op; - command->region = CAIRO_RECORDING_REGION_ALL; command->extents = composite ? composite->unbounded : _cairo_empty_rectangle; command->chain = NULL; @@ -1096,6 +1191,8 @@ _cairo_recording_surface_tag (void *abstract_surface, TRACE ((stderr, "%s: surface=%d\n", __FUNCTION__, surface->base.unique_id)); + surface->has_tags = TRUE; + command = calloc (1, sizeof (cairo_command_tag_t)); if (unlikely (command == NULL)) { return _cairo_error (CAIRO_STATUS_NO_MEMORY); @@ -1140,6 +1237,14 @@ _cairo_recording_surface_tag (void *abstract_surface, return status; } +static cairo_bool_t +_cairo_recording_surface_supports_color_glyph (void *abstract_surface, + cairo_scaled_font_t *scaled_font, + unsigned long glyph_index) +{ + return TRUE; +} + static void _command_init_copy (cairo_recording_surface_t *surface, cairo_command_header_t *dst, @@ -1147,7 +1252,6 @@ _command_init_copy (cairo_recording_surface_t *surface, { dst->type = src->type; dst->op = src->op; - dst->region = CAIRO_RECORDING_REGION_ALL; dst->extents = src->extents; dst->chain = NULL; @@ -1532,6 +1636,9 @@ _cairo_recording_surface_snapshot (void *abstract_other) surface->extents_pixels = other->extents_pixels; surface->extents = other->extents; surface->unbounded = other->unbounded; + surface->has_bilevel_alpha = other->has_bilevel_alpha; + surface->has_only_op_over = other->has_only_op_over; + surface->has_tags = other->has_tags; surface->base.is_clear = other->base.is_clear; @@ -1541,8 +1648,10 @@ _cairo_recording_surface_snapshot (void *abstract_other) surface->indices = NULL; surface->num_indices = 0; surface->optimize_clears = TRUE; - surface->has_bilevel_alpha = other->has_bilevel_alpha; - surface->has_only_op_over = other->has_only_op_over; + + CAIRO_MUTEX_INIT (surface->mutex); + + cairo_list_init (&surface->region_array_list); _cairo_array_init (&surface->commands, sizeof (cairo_command_t *)); status = _cairo_recording_surface_copy (surface, other); @@ -1607,8 +1716,128 @@ static const cairo_surface_backend_t cairo_recording_surface_backend = { _cairo_recording_surface_show_text_glyphs, NULL, /* get_supported_mime_types */ _cairo_recording_surface_tag, + _cairo_recording_surface_supports_color_glyph, + NULL, /* analyze_recording_surface */ + NULL, /* command_id */ }; +static unsigned int +_cairo_recording_surface_regions_allocate_unique_id (void) +{ + static cairo_atomic_int_t unique_id; + +#if CAIRO_NO_MUTEX + if (++unique_id == 0) + unique_id = 1; + return unique_id; +#else + cairo_atomic_int_t old, id; + + do { + old = _cairo_atomic_uint_get (&unique_id); + id = old + 1; + if (id == 0) + id = 1; + } while (! _cairo_atomic_uint_cmpxchg (&unique_id, old, id)); + + return id; +#endif +} + +static cairo_recording_regions_array_t * +_cairo_recording_surface_region_array_find (cairo_recording_surface_t *surface, + unsigned int id) +{ + cairo_recording_regions_array_t *regions; + + cairo_list_foreach_entry (regions, cairo_recording_regions_array_t, + &surface->region_array_list, link) + { + if (regions->id == id) + return regions; + } + + return NULL; +} + +/* Create and initialize a new #cairo_recording_regions_array_t. Attach + * it to the recording surface and return its id + */ +cairo_status_t +_cairo_recording_surface_region_array_attach (cairo_surface_t *abstract_surface, + unsigned int *id) +{ + cairo_recording_regions_array_t *region_array; + cairo_recording_surface_t *surface = (cairo_recording_surface_t *) abstract_surface; + + assert (_cairo_surface_is_recording (abstract_surface)); + + region_array = _cairo_malloc (sizeof (cairo_recording_regions_array_t)); + if (region_array == NULL) { + *id = 0; + return _cairo_error (CAIRO_STATUS_NO_MEMORY); + } + + region_array->id = _cairo_recording_surface_regions_allocate_unique_id (); + + CAIRO_REFERENCE_COUNT_INIT (®ion_array->ref_count, 1); + + _cairo_array_init (®ion_array->regions, sizeof (cairo_recording_region_element_t)); + + CAIRO_MUTEX_LOCK (surface->mutex); + cairo_list_add (®ion_array->link, &surface->region_array_list); + CAIRO_MUTEX_UNLOCK (surface->mutex); + + *id = region_array->id; + + return CAIRO_STATUS_SUCCESS; +} + +void +_cairo_recording_surface_region_array_remove (cairo_surface_t *abstract_surface, + unsigned int id) +{ + cairo_recording_regions_array_t *region_array; + cairo_recording_surface_t *surface = (cairo_recording_surface_t *) abstract_surface; + + if (id == 0) + return; + + assert (_cairo_surface_is_recording (abstract_surface)); + + CAIRO_MUTEX_LOCK (surface->mutex); + region_array = _cairo_recording_surface_region_array_find (surface, id); + if (region_array) { + if (_cairo_reference_count_dec_and_test (®ion_array->ref_count)) + cairo_list_del (®ion_array->link); + else + region_array = NULL; + } + + CAIRO_MUTEX_UNLOCK (surface->mutex); + + if (region_array) + _cairo_recording_surface_region_array_destroy (surface, region_array); +} + +void +_cairo_recording_surface_region_array_reference (cairo_surface_t *abstract_surface, + unsigned int id) +{ + cairo_recording_regions_array_t *region_array; + cairo_recording_surface_t *surface = (cairo_recording_surface_t *) abstract_surface; + + assert (_cairo_surface_is_recording (abstract_surface)); + + CAIRO_MUTEX_LOCK (surface->mutex); + region_array = _cairo_recording_surface_region_array_find (surface, id); + if (region_array) { + _cairo_reference_count_inc (®ion_array->ref_count); + } + + CAIRO_MUTEX_UNLOCK (surface->mutex); +} + cairo_int_status_t _cairo_recording_surface_get_path (cairo_surface_t *abstract_surface, cairo_path_fixed_t *path) @@ -1693,7 +1922,7 @@ _cairo_recording_surface_get_visible_commands (cairo_recording_surface_t *surfac cairo_box_t box; if (surface->commands.num_elements == 0) - return 0; + return 0; _cairo_box_from_rectangle (&box, extents); @@ -1778,18 +2007,12 @@ _cairo_recording_surface_merge_source_attributes (cairo_recording_surface_t *su static cairo_status_t _cairo_recording_surface_replay_internal (cairo_recording_surface_t *surface, - const cairo_rectangle_int_t *surface_extents, - const cairo_matrix_t *surface_transform, - cairo_surface_t *target, - const cairo_clip_t *target_clip, - cairo_bool_t surface_is_unbounded, - cairo_recording_replay_type_t type, - cairo_recording_region_type_t region) + cairo_recording_surface_replay_params_t *params) { cairo_surface_wrapper_t wrapper; cairo_command_t **elements; - cairo_bool_t replay_all = - type == CAIRO_RECORDING_CREATE_REGIONS || region == CAIRO_RECORDING_REGION_ALL; + cairo_recording_regions_array_t *regions_array = NULL; + cairo_recording_region_element_t *region_elements = NULL; cairo_int_status_t status = CAIRO_STATUS_SUCCESS; cairo_rectangle_int_t extents; cairo_bool_t use_indices = FALSE; @@ -1799,8 +2022,8 @@ _cairo_recording_surface_replay_internal (cairo_recording_surface_t *surface, if (unlikely (surface->base.status)) return surface->base.status; - if (unlikely (target->status)) - return target->status; + if (unlikely (params->target->status)) + return params->target->status; if (unlikely (surface->base.finished)) return _cairo_error (CAIRO_STATUS_SURFACE_FINISHED); @@ -1810,76 +2033,144 @@ _cairo_recording_surface_replay_internal (cairo_recording_surface_t *surface, assert (_cairo_surface_is_recording (&surface->base)); - _cairo_surface_wrapper_init (&wrapper, target); - if (surface_extents) - _cairo_surface_wrapper_intersect_extents (&wrapper, surface_extents); + if (params->regions_id != 0) { + regions_array = _cairo_recording_surface_region_array_find (surface, params->regions_id); + assert (regions_array != NULL); + } + + _cairo_surface_wrapper_init (&wrapper, params->target); + if (params->surface_extents) + _cairo_surface_wrapper_intersect_extents (&wrapper, params->surface_extents); r = &_cairo_unbounded_rectangle; - if (! surface->unbounded && !surface_is_unbounded) { + if (! surface->unbounded && !params->surface_is_unbounded) { _cairo_surface_wrapper_intersect_extents (&wrapper, &surface->extents); r = &surface->extents; } - _cairo_surface_wrapper_set_inverse_transform (&wrapper, surface_transform); - _cairo_surface_wrapper_set_clip (&wrapper, target_clip); + _cairo_surface_wrapper_set_inverse_transform (&wrapper, params->surface_transform); + _cairo_surface_wrapper_set_clip (&wrapper, params->target_clip); + + if (params->foreground_color) { + params->target->foreground_source = _cairo_pattern_create_solid (params->foreground_color); + params->target->foreground_used = FALSE; + } /* Compute the extents of the target clip in recorded device space */ - if (! _cairo_surface_wrapper_get_target_extents (&wrapper, surface_is_unbounded, &extents)) + if (! _cairo_surface_wrapper_get_target_extents (&wrapper, params->surface_is_unbounded, &extents)) goto done; surface->has_bilevel_alpha = TRUE; surface->has_only_op_over = TRUE; num_elements = surface->commands.num_elements; + if (regions_array) { + if (params->type == CAIRO_RECORDING_CREATE_REGIONS) { + /* Re-running create regions with the same region id is not supported. */ + assert (_cairo_array_num_elements (®ions_array->regions) == 0); + void *array_elems; + status = _cairo_array_allocate (®ions_array->regions, num_elements, &array_elems); + if (unlikely (status)) + return status; + + /* Set regions to CAIRO_RECORDING_REGION_ALL and ids to 0 */ + memset (array_elems, 0, num_elements * sizeof (cairo_recording_region_element_t)); + } else { + assert (_cairo_array_num_elements (®ions_array->regions) == num_elements); + } + } + elements = _cairo_array_index (&surface->commands, 0); - if (extents.width < r->width || extents.height < r->height) { + if (regions_array) + region_elements = _cairo_array_index (®ions_array->regions, 0); + + if (!params->replay_all && (extents.width < r->width || extents.height < r->height)) { num_elements = _cairo_recording_surface_get_visible_commands (surface, &extents); use_indices = num_elements != surface->commands.num_elements; } + cairo_bool_t target_is_analysis = _cairo_surface_is_analysis (params->target); + for (i = 0; i < num_elements; i++) { cairo_command_t *command = elements[use_indices ? surface->indices[i] : i]; + cairo_recording_region_element_t *region_element = NULL; + unsigned int source_region_id = 0; + unsigned int mask_region_id = 0; + + if (region_elements) + region_element = ®ion_elements[use_indices ? surface->indices[i] : i]; - if (! replay_all && command->header.region != region) + if (region_element && params->type == CAIRO_RECORDING_REPLAY_REGION && + region_element->region != params->region) + { continue; + } if (! _cairo_rectangle_intersects (&extents, &command->header.extents)) { if (command->header.type != CAIRO_COMMAND_TAG) continue; } + + if (params->target->backend->command_id) { + status = params->target->backend->command_id (params->target, params->regions_id, i); + if (unlikely (status)) + return status; + } + switch (command->header.type) { case CAIRO_COMMAND_PAINT: + if (region_element) + source_region_id = region_element->source_id; + status = _cairo_surface_wrapper_paint (&wrapper, command->header.op, &command->paint.source.base, + source_region_id, command->header.clip); - if (type == CAIRO_RECORDING_CREATE_REGIONS) { + if (params->type == CAIRO_RECORDING_CREATE_REGIONS) { _cairo_recording_surface_merge_source_attributes (surface, command->header.op, &command->paint.source.base); + if (region_element && target_is_analysis) + region_element->source_id = _cairo_analysis_surface_get_source_region_id (params->target); } break; case CAIRO_COMMAND_MASK: + if (region_element) { + source_region_id = region_element->source_id; + mask_region_id = region_element->mask_id; + } + status = _cairo_surface_wrapper_mask (&wrapper, command->header.op, &command->mask.source.base, + source_region_id, &command->mask.mask.base, + mask_region_id, command->header.clip); - if (type == CAIRO_RECORDING_CREATE_REGIONS) { + if (params->type == CAIRO_RECORDING_CREATE_REGIONS) { _cairo_recording_surface_merge_source_attributes (surface, command->header.op, &command->mask.source.base); _cairo_recording_surface_merge_source_attributes (surface, command->header.op, &command->mask.mask.base); + if (region_element && target_is_analysis) { + region_element->source_id = _cairo_analysis_surface_get_source_region_id (params->target); + region_element->mask_id = _cairo_analysis_surface_get_mask_region_id (params->target); + } } break; case CAIRO_COMMAND_STROKE: + if (region_element) + source_region_id = region_element->source_id; + status = _cairo_surface_wrapper_stroke (&wrapper, command->header.op, &command->stroke.source.base, + source_region_id, &command->stroke.path, &command->stroke.style, &command->stroke.ctm, @@ -1887,27 +2178,43 @@ _cairo_recording_surface_replay_internal (cairo_recording_surface_t *surface, command->stroke.tolerance, command->stroke.antialias, command->header.clip); - if (type == CAIRO_RECORDING_CREATE_REGIONS) { + if (params->type == CAIRO_RECORDING_CREATE_REGIONS) { _cairo_recording_surface_merge_source_attributes (surface, command->header.op, &command->stroke.source.base); + if (region_element && target_is_analysis) + region_element->source_id = _cairo_analysis_surface_get_source_region_id (params->target); } break; case CAIRO_COMMAND_FILL: status = CAIRO_INT_STATUS_UNSUPPORTED; - if (_cairo_surface_wrapper_has_fill_stroke (&wrapper)) { - cairo_command_t *stroke_command; + if (region_element) + source_region_id = region_element->source_id; - stroke_command = NULL; - if (type != CAIRO_RECORDING_CREATE_REGIONS && i < num_elements - 1) + if (_cairo_surface_wrapper_has_fill_stroke (&wrapper)) { + cairo_command_t *stroke_command = NULL; + cairo_recording_region_element_t *stroke_region_element = NULL; + unsigned stroke_region_id = 0; + + /* The analysis surface does not implement + * fill_stroke. When creating regions the fill and + * stroke commands are tested separately. + */ + if (params->type != CAIRO_RECORDING_CREATE_REGIONS && i < num_elements - 1) { stroke_command = elements[i + 1]; + if (region_elements) + stroke_region_element = ®ion_elements[i + 1]; + } - if (stroke_command != NULL && - type == CAIRO_RECORDING_REPLAY && - region != CAIRO_RECORDING_REGION_ALL) + if (stroke_region_element) + stroke_region_id = stroke_region_element->source_id; + + if (stroke_command && stroke_region_element && + params->type == CAIRO_RECORDING_REPLAY_REGION && + params->region != CAIRO_RECORDING_REGION_ALL) { - if (stroke_command->header.region != region) + if (stroke_region_element->region != params->region) stroke_command = NULL; } @@ -1921,19 +2228,21 @@ _cairo_recording_surface_replay_internal (cairo_recording_surface_t *surface, status = _cairo_surface_wrapper_fill_stroke (&wrapper, command->header.op, &command->fill.source.base, + source_region_id, command->fill.fill_rule, command->fill.tolerance, command->fill.antialias, &command->fill.path, stroke_command->header.op, &stroke_command->stroke.source.base, + stroke_region_id, &stroke_command->stroke.style, &stroke_command->stroke.ctm, &stroke_command->stroke.ctm_inverse, stroke_command->stroke.tolerance, stroke_command->stroke.antialias, command->header.clip); - if (type == CAIRO_RECORDING_CREATE_REGIONS) { + if (params->type == CAIRO_RECORDING_CREATE_REGIONS) { _cairo_recording_surface_merge_source_attributes (surface, command->header.op, &command->fill.source.base); @@ -1948,33 +2257,43 @@ _cairo_recording_surface_replay_internal (cairo_recording_surface_t *surface, status = _cairo_surface_wrapper_fill (&wrapper, command->header.op, &command->fill.source.base, + source_region_id, &command->fill.path, command->fill.fill_rule, command->fill.tolerance, command->fill.antialias, command->header.clip); - if (type == CAIRO_RECORDING_CREATE_REGIONS) { + if (params->type == CAIRO_RECORDING_CREATE_REGIONS) { _cairo_recording_surface_merge_source_attributes (surface, command->header.op, &command->fill.source.base); + if (region_element && target_is_analysis) + region_element->source_id = _cairo_analysis_surface_get_source_region_id (params->target); } } break; case CAIRO_COMMAND_SHOW_TEXT_GLYPHS: + if (region_element) + source_region_id = region_element->source_id; + status = _cairo_surface_wrapper_show_text_glyphs (&wrapper, command->header.op, &command->show_text_glyphs.source.base, + source_region_id, command->show_text_glyphs.utf8, command->show_text_glyphs.utf8_len, command->show_text_glyphs.glyphs, command->show_text_glyphs.num_glyphs, command->show_text_glyphs.clusters, command->show_text_glyphs.num_clusters, command->show_text_glyphs.cluster_flags, command->show_text_glyphs.scaled_font, command->header.clip); - if (type == CAIRO_RECORDING_CREATE_REGIONS) { + if (params->type == CAIRO_RECORDING_CREATE_REGIONS) { _cairo_recording_surface_merge_source_attributes (surface, command->header.op, &command->show_text_glyphs.source.base); + if (region_element && target_is_analysis) + region_element->source_id = _cairo_analysis_surface_get_source_region_id (params->target); + } break; @@ -1993,11 +2312,11 @@ _cairo_recording_surface_replay_internal (cairo_recording_surface_t *surface, if (unlikely (status == CAIRO_INT_STATUS_NOTHING_TO_DO)) status = CAIRO_INT_STATUS_SUCCESS; - if (type == CAIRO_RECORDING_CREATE_REGIONS && command->header.region != CAIRO_RECORDING_REGION_NATIVE) { + if (params->type == CAIRO_RECORDING_CREATE_REGIONS && region_element) { if (status == CAIRO_INT_STATUS_SUCCESS) { - command->header.region = CAIRO_RECORDING_REGION_NATIVE; + region_element->region = CAIRO_RECORDING_REGION_NATIVE; } else if (status == CAIRO_INT_STATUS_IMAGE_FALLBACK) { - command->header.region = CAIRO_RECORDING_REGION_IMAGE_FALLBACK; + region_element->region = CAIRO_RECORDING_REGION_IMAGE_FALLBACK; status = CAIRO_INT_STATUS_SUCCESS; } else { assert (_cairo_int_status_is_error (status)); @@ -2009,6 +2328,12 @@ _cairo_recording_surface_replay_internal (cairo_recording_surface_t *surface, } done: + if (params->foreground_color) { + cairo_pattern_destroy (params->target->foreground_source); + params->target->foreground_source = NULL; + params->foreground_used = params->target->foreground_used; + } + _cairo_surface_wrapper_fini (&wrapper); return _cairo_surface_set_error (&surface->base, status); } @@ -2020,7 +2345,7 @@ _cairo_recording_surface_replay_one (cairo_recording_surface_t *surface, { cairo_surface_wrapper_t wrapper; cairo_command_t **elements, *command; - cairo_int_status_t status; + cairo_int_status_t status = CAIRO_INT_STATUS_SUCCESS; if (unlikely (surface->base.status)) return surface->base.status; @@ -2049,6 +2374,7 @@ _cairo_recording_surface_replay_one (cairo_recording_surface_t *surface, status = _cairo_surface_wrapper_paint (&wrapper, command->header.op, &command->paint.source.base, + 0, command->header.clip); break; @@ -2056,7 +2382,9 @@ _cairo_recording_surface_replay_one (cairo_recording_surface_t *surface, status = _cairo_surface_wrapper_mask (&wrapper, command->header.op, &command->mask.source.base, + 0, &command->mask.mask.base, + 0, command->header.clip); break; @@ -2064,6 +2392,7 @@ _cairo_recording_surface_replay_one (cairo_recording_surface_t *surface, status = _cairo_surface_wrapper_stroke (&wrapper, command->header.op, &command->stroke.source.base, + 0, &command->stroke.path, &command->stroke.style, &command->stroke.ctm, @@ -2077,6 +2406,7 @@ _cairo_recording_surface_replay_one (cairo_recording_surface_t *surface, status = _cairo_surface_wrapper_fill (&wrapper, command->header.op, &command->fill.source.base, + 0, &command->fill.path, command->fill.fill_rule, command->fill.tolerance, @@ -2088,6 +2418,7 @@ _cairo_recording_surface_replay_one (cairo_recording_surface_t *surface, status = _cairo_surface_wrapper_show_text_glyphs (&wrapper, command->header.op, &command->show_text_glyphs.source.base, + 0, command->show_text_glyphs.utf8, command->show_text_glyphs.utf8_len, command->show_text_glyphs.glyphs, command->show_text_glyphs.num_glyphs, command->show_text_glyphs.clusters, command->show_text_glyphs.num_clusters, @@ -2126,10 +2457,70 @@ cairo_status_t _cairo_recording_surface_replay (cairo_surface_t *surface, cairo_surface_t *target) { - return _cairo_recording_surface_replay_internal ((cairo_recording_surface_t *) surface, NULL, NULL, - target, NULL, FALSE, - CAIRO_RECORDING_REPLAY, - CAIRO_RECORDING_REGION_ALL); + cairo_recording_surface_replay_params_t params; + + params.surface_extents = NULL; + params.surface_transform = NULL; + params.target = target; + params.target_clip = NULL; + params.surface_is_unbounded = FALSE; + params.type = CAIRO_RECORDING_REPLAY; + params.region = CAIRO_RECORDING_REGION_ALL; + params.regions_id = 0; + params.foreground_color = NULL; + params.replay_all = FALSE; + + return _cairo_recording_surface_replay_internal ((cairo_recording_surface_t *) surface, ¶ms); +} + +cairo_status_t +_cairo_recording_surface_replay_with_foreground_color (cairo_surface_t *surface, + cairo_surface_t *target, + const cairo_color_t *foreground_color, + cairo_bool_t *foreground_used) +{ + cairo_recording_surface_replay_params_t params; + cairo_status_t status; + + params.surface_extents = NULL; + params.surface_transform = NULL; + params.target = target; + params.target_clip = NULL; + params.surface_is_unbounded = FALSE; + params.type = CAIRO_RECORDING_REPLAY; + params.region = CAIRO_RECORDING_REGION_ALL; + params.regions_id = 0; + params.foreground_color = foreground_color; + params.foreground_used = FALSE; + params.replay_all = FALSE; + + status = _cairo_recording_surface_replay_internal ((cairo_recording_surface_t *) surface, ¶ms); + *foreground_used = params.foreground_used; + + return status; +} + +cairo_status_t +_cairo_recording_surface_replay_with_transform (cairo_surface_t *surface, + const cairo_matrix_t *surface_transform, + cairo_surface_t *target, + cairo_bool_t surface_is_unbounded, + cairo_bool_t replay_all) +{ + cairo_recording_surface_replay_params_t params; + + params.surface_extents = NULL; + params.surface_transform = surface_transform; + params.target = target; + params.target_clip = NULL; + params.surface_is_unbounded = surface_is_unbounded; + params.type = CAIRO_RECORDING_REPLAY; + params.region = CAIRO_RECORDING_REGION_ALL; + params.regions_id = 0; + params.foreground_color = NULL; + params.replay_all = replay_all; + + return _cairo_recording_surface_replay_internal ((cairo_recording_surface_t *) surface, ¶ms); } cairo_status_t @@ -2138,10 +2529,20 @@ _cairo_recording_surface_replay_with_clip (cairo_surface_t *surface, cairo_surface_t *target, const cairo_clip_t *target_clip) { - return _cairo_recording_surface_replay_internal ((cairo_recording_surface_t *) surface, NULL, surface_transform, - target, target_clip, FALSE, - CAIRO_RECORDING_REPLAY, - CAIRO_RECORDING_REGION_ALL); + cairo_recording_surface_replay_params_t params; + + params.surface_extents = NULL; + params.surface_transform = surface_transform; + params.target = target; + params.target_clip = target_clip; + params.surface_is_unbounded = FALSE; + params.type = CAIRO_RECORDING_REPLAY; + params.region = CAIRO_RECORDING_REGION_ALL; + params.regions_id = 0; + params.foreground_color = NULL; + params.replay_all = FALSE; + + return _cairo_recording_surface_replay_internal ((cairo_recording_surface_t *) surface, ¶ms); } /* Replay recording to surface. When the return status of each operation is @@ -2152,28 +2553,49 @@ _cairo_recording_surface_replay_with_clip (cairo_surface_t *surface, */ cairo_status_t _cairo_recording_surface_replay_and_create_regions (cairo_surface_t *surface, + unsigned int regions_id, const cairo_matrix_t *surface_transform, cairo_surface_t *target, - cairo_bool_t surface_is_unbounded) + cairo_bool_t surface_is_unbounded, + cairo_bool_t replay_all) { - return _cairo_recording_surface_replay_internal ((cairo_recording_surface_t *) surface, NULL, surface_transform, - target, NULL, - surface_is_unbounded, - CAIRO_RECORDING_CREATE_REGIONS, - CAIRO_RECORDING_REGION_ALL); + cairo_recording_surface_replay_params_t params; + + params.surface_extents = NULL; + params.surface_transform = surface_transform; + params.target = target; + params.target_clip = NULL; + params.surface_is_unbounded = surface_is_unbounded; + params.type = CAIRO_RECORDING_CREATE_REGIONS; + params.region = CAIRO_RECORDING_REGION_ALL; + params.regions_id = regions_id; + params.foreground_color = NULL; + params.replay_all = replay_all; + + return _cairo_recording_surface_replay_internal ((cairo_recording_surface_t *) surface, ¶ms); } cairo_status_t _cairo_recording_surface_replay_region (cairo_surface_t *surface, + unsigned int regions_id, const cairo_rectangle_int_t *surface_extents, cairo_surface_t *target, cairo_recording_region_type_t region) { - return _cairo_recording_surface_replay_internal ((cairo_recording_surface_t *) surface, - surface_extents, NULL, - target, NULL, FALSE, - CAIRO_RECORDING_REPLAY, - region); + cairo_recording_surface_replay_params_t params; + + params.surface_extents = surface_extents; + params.surface_transform = NULL; + params.target = target; + params.target_clip = NULL; + params.surface_is_unbounded = FALSE; + params.type = CAIRO_RECORDING_REPLAY_REGION; + params.region = region; + params.regions_id = regions_id; + params.foreground_color = NULL; + params.replay_all = FALSE; + + return _cairo_recording_surface_replay_internal ((cairo_recording_surface_t *) surface, ¶ms); } static cairo_status_t @@ -2186,7 +2608,7 @@ _recording_surface_get_ink_bbox (cairo_recording_surface_t *surface, cairo_status_t status; null_surface = _cairo_null_surface_create (surface->base.content); - analysis_surface = _cairo_analysis_surface_create (null_surface); + analysis_surface = _cairo_analysis_surface_create (null_surface, FALSE); cairo_surface_destroy (null_surface); status = analysis_surface->status; @@ -2317,3 +2739,204 @@ _cairo_recording_surface_has_only_op_over (cairo_recording_surface_t *surface) { return surface->has_only_op_over; } + +cairo_bool_t +_cairo_recording_surface_has_tags (cairo_surface_t *surface) +{ + cairo_recording_surface_t *record; + + if (surface->status || ! _cairo_surface_is_recording (surface)) { + _cairo_error_throw (CAIRO_STATUS_SURFACE_TYPE_MISMATCH); + return FALSE; + } + + record = (cairo_recording_surface_t *)surface; + + return record->has_tags; +} + +static void +print_indent (FILE *file, int indent) +{ + fprintf (file, "%*s", indent * 2, ""); +} + +static void +print_pattern (FILE *file, + const cairo_pattern_t *pattern, + unsigned int region_id, + int indent, + cairo_bool_t recurse) +{ + switch (pattern->type) { + case CAIRO_PATTERN_TYPE_SOLID: { + cairo_solid_pattern_t *p = (cairo_solid_pattern_t *) pattern; + if (pattern->is_foreground_marker) { + fprintf (file, "solid foreground\n"); + } else { + fprintf (file, "solid rgba: %f %f %f %f\n", + p->color.red, + p->color.green, + p->color.blue, + p->color.alpha); + } + } break; + case CAIRO_PATTERN_TYPE_SURFACE: { + cairo_surface_pattern_t *p = (cairo_surface_pattern_t *) pattern; + fprintf (file, "surface "); + if (p->surface->type == CAIRO_SURFACE_TYPE_RECORDING) { + fprintf (file, "recording id: %d\n", p->surface->unique_id); + if (recurse) { + _cairo_debug_print_recording_surface (file, p->surface, + region_id, + indent + 1, recurse); + } + } else if (p->surface->type == CAIRO_SURFACE_TYPE_IMAGE) { + cairo_image_surface_t *image = (cairo_image_surface_t *)p->surface; + fprintf (file, "image format: "); + switch (image->format) { + case CAIRO_FORMAT_INVALID: fputs ("INVALID", file); break; + case CAIRO_FORMAT_ARGB32: fputs ("ARGB32", file); break; + case CAIRO_FORMAT_RGB24: fputs ("RGB24", file); break; + case CAIRO_FORMAT_A8: fputs ("A8", file); break; + case CAIRO_FORMAT_A1: fputs ("A1", file); break; + case CAIRO_FORMAT_RGB16_565: fputs ("RGB16_565", file); break; + case CAIRO_FORMAT_RGB30: fputs ("RGB30", file); break; + case CAIRO_FORMAT_RGB96F: fputs ("RGB96F", file); break; + case CAIRO_FORMAT_RGBA128F: fputs ("RGBA128F", file); break; + } + fprintf (file, " width: %d height: %d\n", image->width, image->height); + } else { + fprintf (file, "type %d\n", p->surface->type); + } + } break; + case CAIRO_PATTERN_TYPE_LINEAR: + fprintf (file, "linear\n"); + break; + case CAIRO_PATTERN_TYPE_RADIAL: + fprintf (file, "radial\n"); + break; + case CAIRO_PATTERN_TYPE_MESH: + fprintf (file, "mesh\n"); + break; + case CAIRO_PATTERN_TYPE_RASTER_SOURCE: + fprintf (file, "raster\n"); + break; + } +} + +void +_cairo_debug_print_recording_surface (FILE *file, + cairo_surface_t *surface, + unsigned int regions_id, + int indent, + cairo_bool_t recurse) +{ + cairo_command_t **elements; + cairo_recording_region_element_t *region_elements = NULL; + unsigned int i, num_elements; + cairo_recording_surface_t *recording_surface; + cairo_surface_t *free_me = NULL; + char common[100]; + + if (_cairo_surface_is_snapshot (surface)) + free_me = surface = _cairo_surface_snapshot_get_target (surface); + + assert (_cairo_surface_is_recording (surface)); + recording_surface = (cairo_recording_surface_t *)surface; + + print_indent (file, indent); + indent++; + fprintf(file, "recording surface id: %d regions id: %d\n", recording_surface->base.unique_id, regions_id); + num_elements = recording_surface->commands.num_elements; + elements = _cairo_array_index (&recording_surface->commands, 0); + + if (regions_id != 0) { + cairo_recording_regions_array_t *regions_array; + regions_array = _cairo_recording_surface_region_array_find (recording_surface, regions_id); + assert (regions_array != NULL); + assert (_cairo_array_num_elements (®ions_array->regions) == num_elements); + region_elements = _cairo_array_index (®ions_array->regions, 0); + } + + for (i = 0; i < num_elements; i++) { + cairo_command_t *command = elements[i]; + unsigned int source_region_id = 0; + unsigned int mask_region_id = 0; + + common[0] = 0; + if (region_elements) { + cairo_recording_region_element_t *region_element = ®ion_elements[i]; + strcpy (common, "region: "); + switch (region_element->region) { + case CAIRO_RECORDING_REGION_ALL: strcat (common, "all"); break; + case CAIRO_RECORDING_REGION_NATIVE: strcat (common, "native"); break; + case CAIRO_RECORDING_REGION_IMAGE_FALLBACK: strcat (common, "fallback"); break; + } + source_region_id = region_element->source_id; + mask_region_id = region_element->mask_id; + } + sprintf (common + strlen(common), " op: %s", _cairo_debug_operator_to_string (command->header.op)); + + switch (command->header.type) { + case CAIRO_COMMAND_PAINT: + print_indent (file, indent); + fprintf(file, "%d PAINT %s source: ", i, common); + print_pattern (file, &command->paint.source.base, source_region_id, indent + 1, recurse); + break; + + case CAIRO_COMMAND_MASK: + print_indent (file, indent); + fprintf(file, "%d MASK %s\n", i, common); + print_indent (file, indent + 1); + fprintf(file, "source: "); + print_pattern (file, &command->mask.source.base, source_region_id, indent + 1, recurse); + print_indent (file, indent + 1); + fprintf(file, "mask: "); + print_pattern (file, &command->mask.mask.base, mask_region_id, indent + 1, recurse); + break; + + case CAIRO_COMMAND_STROKE: + print_indent (file, indent); + fprintf(file, "%d STROKE %s source:", i, common); + print_pattern (file, &command->stroke.source.base, source_region_id, indent + 1, recurse); + break; + + case CAIRO_COMMAND_FILL: + print_indent (file, indent); + fprintf(file, "%d FILL %s source: ", i, common); + print_pattern (file, &command->fill.source.base, source_region_id, indent + 1, recurse); + break; + + case CAIRO_COMMAND_SHOW_TEXT_GLYPHS: + print_indent (file, indent); + fprintf(file, "%d SHOW_TEXT_GLYPHS %s font_type: ", i, common); + switch (command->show_text_glyphs.scaled_font->backend->type) { + case CAIRO_FONT_TYPE_TOY: fputs ("toy", file); break; + case CAIRO_FONT_TYPE_FT: fputs ("ft", file); break; + case CAIRO_FONT_TYPE_WIN32: fputs ("win32", file); break; + case CAIRO_FONT_TYPE_QUARTZ: fputs ("quartz", file); break; + case CAIRO_FONT_TYPE_USER: fputs ("user", file); break; + case CAIRO_FONT_TYPE_DWRITE: fputs ("dwrite", file); break; + } + fprintf (file, " glyphs:"); + for (unsigned j = 0; j < command->show_text_glyphs.num_glyphs; j++) + fprintf (file, " %ld", command->show_text_glyphs.glyphs[j].index); + fprintf (file, " source:"); + print_pattern (file, &command->show_text_glyphs.source.base, source_region_id, indent + 1, recurse); + break; + + case CAIRO_COMMAND_TAG: + print_indent (file, indent); + fprintf(file, "%d %s %s '%s'\n", + i, + command->tag.begin ? "BEGIN TAG" : "END TAG", + command->tag.tag_name, command->tag.attributes); + break; + + default: + ASSERT_NOT_REACHED; + } + } + cairo_surface_destroy (free_me); +} diff --git a/gfx/cairo/cairo/src/cairo-region.c b/gfx/cairo/cairo/src/cairo-region.c index c1d35e174a..320a23fa9b 100644 --- a/gfx/cairo/cairo/src/cairo-region.c +++ b/gfx/cairo/cairo/src/cairo-region.c @@ -111,6 +111,8 @@ _cairo_region_create_in_error (cairo_status_t status) case CAIRO_STATUS_FREETYPE_ERROR: case CAIRO_STATUS_WIN32_GDI_ERROR: case CAIRO_STATUS_TAG_ERROR: + case CAIRO_STATUS_DWRITE_ERROR: + case CAIRO_STATUS_SVG_FONT_ERROR: default: _cairo_error_throw (CAIRO_STATUS_NO_MEMORY); return (cairo_region_t *) &_cairo_region_nil; @@ -211,7 +213,6 @@ cairo_region_create (void) return region; } -slim_hidden_def (cairo_region_create); /** * cairo_region_create_rectangles: @@ -279,7 +280,6 @@ cairo_region_create_rectangles (const cairo_rectangle_int_t *rects, return region; } -slim_hidden_def (cairo_region_create_rectangles); cairo_region_t * _cairo_region_create_from_boxes (const cairo_box_t *boxes, int count) @@ -345,7 +345,6 @@ cairo_region_create_rectangle (const cairo_rectangle_int_t *rectangle) return region; } -slim_hidden_def (cairo_region_create_rectangle); /** * cairo_region_copy: @@ -382,7 +381,6 @@ cairo_region_copy (const cairo_region_t *original) return copy; } -slim_hidden_def (cairo_region_copy); /** * cairo_region_reference: @@ -407,7 +405,6 @@ cairo_region_reference (cairo_region_t *region) _cairo_reference_count_inc (®ion->ref_count); return region; } -slim_hidden_def (cairo_region_reference); /** * cairo_region_destroy: @@ -433,7 +430,6 @@ cairo_region_destroy (cairo_region_t *region) _cairo_region_fini (region); free (region); } -slim_hidden_def (cairo_region_destroy); /** * cairo_region_num_rectangles: @@ -453,7 +449,6 @@ cairo_region_num_rectangles (const cairo_region_t *region) return pixman_region32_n_rects (CONST_CAST ®ion->rgn); } -slim_hidden_def (cairo_region_num_rectangles); /** * cairo_region_get_rectangle: @@ -485,7 +480,6 @@ cairo_region_get_rectangle (const cairo_region_t *region, rectangle->width = pbox->x2 - pbox->x1; rectangle->height = pbox->y2 - pbox->y1; } -slim_hidden_def (cairo_region_get_rectangle); /** * cairo_region_get_extents: @@ -515,7 +509,6 @@ cairo_region_get_extents (const cairo_region_t *region, extents->width = pextents->x2 - pextents->x1; extents->height = pextents->y2 - pextents->y1; } -slim_hidden_def (cairo_region_get_extents); /** * cairo_region_status: @@ -533,7 +526,6 @@ cairo_region_status (const cairo_region_t *region) { return region->status; } -slim_hidden_def (cairo_region_status); /** * cairo_region_subtract: @@ -564,7 +556,6 @@ cairo_region_subtract (cairo_region_t *dst, const cairo_region_t *other) return CAIRO_STATUS_SUCCESS; } -slim_hidden_def (cairo_region_subtract); /** * cairo_region_subtract_rectangle: @@ -598,7 +589,6 @@ cairo_region_subtract_rectangle (cairo_region_t *dst, return status; } -slim_hidden_def (cairo_region_subtract_rectangle); /** * cairo_region_intersect: @@ -625,7 +615,6 @@ cairo_region_intersect (cairo_region_t *dst, const cairo_region_t *other) return CAIRO_STATUS_SUCCESS; } -slim_hidden_def (cairo_region_intersect); /** * cairo_region_intersect_rectangle: @@ -660,7 +649,6 @@ cairo_region_intersect_rectangle (cairo_region_t *dst, return status; } -slim_hidden_def (cairo_region_intersect_rectangle); /** * cairo_region_union: @@ -688,7 +676,6 @@ cairo_region_union (cairo_region_t *dst, return CAIRO_STATUS_SUCCESS; } -slim_hidden_def (cairo_region_union); /** * cairo_region_union_rectangle: @@ -722,7 +709,6 @@ cairo_region_union_rectangle (cairo_region_t *dst, return status; } -slim_hidden_def (cairo_region_union_rectangle); /** * cairo_region_xor: @@ -761,7 +747,6 @@ cairo_region_xor (cairo_region_t *dst, const cairo_region_t *other) return status; } -slim_hidden_def (cairo_region_xor); /** * cairo_region_xor_rectangle: @@ -802,7 +787,6 @@ cairo_region_xor_rectangle (cairo_region_t *dst, return status; } -slim_hidden_def (cairo_region_xor_rectangle); /** * cairo_region_is_empty: @@ -822,7 +806,6 @@ cairo_region_is_empty (const cairo_region_t *region) return ! pixman_region32_not_empty (CONST_CAST ®ion->rgn); } -slim_hidden_def (cairo_region_is_empty); /** * cairo_region_translate: @@ -843,7 +826,6 @@ cairo_region_translate (cairo_region_t *region, pixman_region32_translate (®ion->rgn, dx, dy); } -slim_hidden_def (cairo_region_translate); /** * cairo_region_contains_rectangle: @@ -884,7 +866,6 @@ cairo_region_contains_rectangle (const cairo_region_t *region, case PIXMAN_REGION_PART: return CAIRO_REGION_OVERLAP_PART; } } -slim_hidden_def (cairo_region_contains_rectangle); /** * cairo_region_contains_point: @@ -909,7 +890,6 @@ cairo_region_contains_point (const cairo_region_t *region, return pixman_region32_contains_point (CONST_CAST ®ion->rgn, x, y, &box); } -slim_hidden_def (cairo_region_contains_point); /** * cairo_region_equal: @@ -940,4 +920,3 @@ cairo_region_equal (const cairo_region_t *a, return pixman_region32_equal (CONST_CAST &a->rgn, CONST_CAST &b->rgn); } -slim_hidden_def (cairo_region_equal); diff --git a/gfx/cairo/cairo/src/cairo-scaled-font-private.h b/gfx/cairo/cairo/src/cairo-scaled-font-private.h index 317d211979..64abbe0f51 100644 --- a/gfx/cairo/cairo/src/cairo-scaled-font-private.h +++ b/gfx/cairo/cairo/src/cairo-scaled-font-private.h @@ -107,12 +107,13 @@ struct _cairo_scaled_font { cairo_font_extents_t fs_extents; /* font space */ /* The mutex protects modification to all subsequent fields. */ - cairo_mutex_t mutex; + cairo_recursive_mutex_t mutex; cairo_hash_table_t *glyphs; cairo_list_t glyph_pages; cairo_bool_t cache_frozen; cairo_bool_t global_cache_frozen; + cairo_array_t recording_surfaces_to_free; /* array of cairo_surface_t* */ cairo_list_t dev_privates; @@ -146,6 +147,19 @@ struct _cairo_scaled_glyph { const void *dev_private_key; void *dev_private; cairo_list_t dev_privates; + + cairo_color_t foreground_color; /* only used for color glyphs */ + + /* TRUE if the recording_surface used the foreground_source to render. */ + unsigned recording_uses_foreground_color : 1; + + /* TRUE if the recording surface uses the foreground marker. */ + unsigned recording_uses_foreground_marker : 1; + + /* TRUE if color_glyph specifies if glyph is color or non color, FALSE if glyph color type unknown. */ + unsigned color_glyph_set : 1; + + unsigned color_glyph : 1; }; struct _cairo_scaled_glyph_private { diff --git a/gfx/cairo/cairo/src/cairo-scaled-font-subsets-private.h b/gfx/cairo/cairo/src/cairo-scaled-font-subsets-private.h index e7809f03aa..2599bb6c35 100644 --- a/gfx/cairo/cairo/src/cairo-scaled-font-subsets-private.h +++ b/gfx/cairo/cairo/src/cairo-scaled-font-subsets-private.h @@ -41,6 +41,8 @@ #if CAIRO_HAS_FONT_SUBSET +CAIRO_BEGIN_DECLS + typedef struct _cairo_scaled_font_subsets_glyph { unsigned int font_id; unsigned int subset_id; @@ -202,7 +204,7 @@ _cairo_scaled_font_subsets_enable_latin_subset (cairo_scaled_font_subsets_t *fon * @x_advance, @y_advance: When @is_scaled is true, @x_advance and @y_advance contain * the x and y advance for the mapped glyph in device space. * When @is_scaled is false, @x_advance and @y_advance contain the x and y advance for - * the the mapped glyph from an unhinted 1 point font. + * the mapped glyph from an unhinted 1 point font. * @utf8_is_mapped: If true the utf8 string provided to _cairo_scaled_font_subsets_map_glyph() * is (or already was) the utf8 string mapped to this glyph. If false the glyph is already * mapped to a different utf8 string. @@ -295,41 +297,6 @@ _cairo_scaled_font_subsets_foreach_unscaled (cairo_scaled_font_subsets_t void *closure); /** - * _cairo_scaled_font_subsets_foreach_user: - * @font_subsets: a #cairo_scaled_font_subsets_t - * @font_subset_callback: a function to be called for each font subset - * @closure: closure data for the callback function - * - * Iterate over each unique scaled font subset as created by calls to - * _cairo_scaled_font_subsets_map_glyph(). A subset is determined by - * unique pairs of (font_id, subset_id) as returned by - * _cairo_scaled_font_subsets_map_glyph(). - * - * For each subset, @font_subset_callback will be called and will be - * provided with both a #cairo_scaled_font_subset_t object containing - * all the glyphs in the subset as well as the value of @closure. - * - * The #cairo_scaled_font_subset_t object contains the scaled_font, - * the font_id, and the subset_id corresponding to all glyphs - * belonging to the subset. In addition, it contains an array providing - * a mapping between subset glyph indices and the original scaled font - * glyph indices. - * - * The index of the array corresponds to subset_glyph_index values - * returned by _cairo_scaled_font_subsets_map_glyph() while the - * values of the array correspond to the scaled_font_glyph_index - * values passed as input to the same function. - * - * Return value: %CAIRO_STATUS_SUCCESS if successful, or a non-zero - * value indicating an error. Possible errors include - * %CAIRO_STATUS_NO_MEMORY. - **/ -cairo_private cairo_status_t -_cairo_scaled_font_subsets_foreach_user (cairo_scaled_font_subsets_t *font_subsets, - cairo_scaled_font_subset_callback_func_t font_subset_callback, - void *closure); - -/** * _cairo_scaled_font_subset_create_glyph_names: * @font_subsets: a #cairo_scaled_font_subsets_t * @@ -735,6 +702,9 @@ cairo_private void dump_scaled_font_subsets (cairo_scaled_font_subsets_t *font_subsets); #endif +CAIRO_END_DECLS + + #endif /* CAIRO_HAS_FONT_SUBSET */ #endif /* CAIRO_SCALED_FONT_SUBSETS_PRIVATE_H */ diff --git a/gfx/cairo/cairo/src/cairo-scaled-font-subsets.c b/gfx/cairo/cairo/src/cairo-scaled-font-subsets.c index 1f0e53577f..8a25a4612d 100644 --- a/gfx/cairo/cairo/src/cairo-scaled-font-subsets.c +++ b/gfx/cairo/cairo/src/cairo-scaled-font-subsets.c @@ -1,3 +1,4 @@ +/* -*- Mode: c; tab-width: 8; c-basic-offset: 4; indent-tabs-mode: t; -*- */ /* cairo - a vector graphics library with display and print output * * Copyright © 2003 University of Southern California @@ -61,7 +62,6 @@ typedef enum { typedef enum { CAIRO_SUBSETS_FOREACH_UNSCALED, CAIRO_SUBSETS_FOREACH_SCALED, - CAIRO_SUBSETS_FOREACH_USER } cairo_subsets_foreach_type_t; typedef struct _cairo_sub_font { @@ -69,7 +69,6 @@ typedef struct _cairo_sub_font { cairo_bool_t is_scaled; cairo_bool_t is_composite; - cairo_bool_t is_user; cairo_bool_t use_latin_subset; cairo_bool_t reserve_notdef; cairo_scaled_font_subsets_t *parent; @@ -255,12 +254,12 @@ _cairo_sub_font_init_key (cairo_sub_font_t *sub_font, { if (sub_font->is_scaled) { - sub_font->base.hash = (unsigned long) scaled_font; + sub_font->base.hash = (uintptr_t) scaled_font; sub_font->scaled_font = scaled_font; } else { - sub_font->base.hash = (unsigned long) scaled_font->font_face; + sub_font->base.hash = (uintptr_t) scaled_font->font_face; sub_font->scaled_font = scaled_font; } } @@ -283,8 +282,7 @@ _cairo_sub_font_create (cairo_scaled_font_subsets_t *parent, sub_font->is_scaled = is_scaled; sub_font->is_composite = is_composite; - sub_font->is_user = _cairo_font_face_is_user (scaled_font->font_face); - sub_font->reserve_notdef = !sub_font->is_user; + sub_font->reserve_notdef = !sub_font->is_scaled; _cairo_sub_font_init_key (sub_font, scaled_font); sub_font->parent = parent; @@ -294,7 +292,7 @@ _cairo_sub_font_create (cairo_scaled_font_subsets_t *parent, sub_font->use_latin_subset = parent->use_latin_subset; /* latin subsets of Type 3 and CID CFF fonts are not supported */ - if (sub_font->is_user || sub_font->is_scaled || + if (sub_font->is_scaled || _cairo_cff_scaled_font_is_cid_cff (scaled_font) ) { sub_font->use_latin_subset = FALSE; @@ -404,12 +402,10 @@ _cairo_sub_font_glyph_lookup_unicode (cairo_scaled_font_t *scaled_font, if (unicode != (uint32_t) -1) { len = _cairo_ucs4_to_utf8 (unicode, buf); if (len > 0) { - *utf8_out = _cairo_malloc (len + 1); - if (unlikely (*utf8_out == NULL)) - return _cairo_error (CAIRO_STATUS_NO_MEMORY); + *utf8_out = _cairo_strndup (buf, len); + if (unlikely (*utf8_out == NULL)) + return _cairo_error (CAIRO_STATUS_NO_MEMORY); - memcpy (*utf8_out, buf, len); - (*utf8_out)[len] = 0; *utf8_len_out = len; } } @@ -434,19 +430,17 @@ _cairo_sub_font_glyph_map_to_unicode (cairo_sub_font_glyph_t *sub_font_glyph, if (utf8 != NULL && utf8_len != 0) { if (sub_font_glyph->utf8 != NULL) { if (utf8_len == sub_font_glyph->utf8_len && - memcmp (utf8, sub_font_glyph->utf8, utf8_len) == 0) + strncmp (utf8, sub_font_glyph->utf8, utf8_len) == 0) { /* Requested utf8 mapping matches the existing mapping */ *is_mapped = TRUE; } } else { /* No existing mapping. Use the requested mapping */ - sub_font_glyph->utf8 = _cairo_malloc (utf8_len + 1); - if (unlikely (sub_font_glyph->utf8 == NULL)) - return _cairo_error (CAIRO_STATUS_NO_MEMORY); + sub_font_glyph->utf8 = _cairo_strndup (utf8, utf8_len); + if (unlikely (sub_font_glyph->utf8 == NULL)) + return _cairo_error (CAIRO_STATUS_NO_MEMORY); - memcpy (sub_font_glyph->utf8, utf8, utf8_len); - sub_font_glyph->utf8[utf8_len] = 0; sub_font_glyph->utf8_len = utf8_len; *is_mapped = TRUE; } @@ -513,6 +507,7 @@ _cairo_sub_font_add_glyph (cairo_sub_font_t *sub_font, status = _cairo_scaled_glyph_lookup (sub_font->scaled_font, scaled_font_glyph_index, CAIRO_SCALED_GLYPH_INFO_METRICS, + NULL, /* foreground color */ &scaled_glyph); assert (status != CAIRO_INT_STATUS_UNSUPPORTED); if (unlikely (status)) { @@ -611,25 +606,22 @@ _cairo_sub_font_map_glyph (cairo_sub_font_t *sub_font, if (ucs4_len == 1) { font_unicode = ucs4[0]; free (font_utf8); - font_utf8 = _cairo_malloc (text_utf8_len + 1); - if (font_utf8 == NULL) { - free (ucs4); - return _cairo_error (CAIRO_STATUS_NO_MEMORY); + font_utf8 = _cairo_strndup (text_utf8, text_utf8_len); + if (font_utf8 == NULL) { + free (ucs4); + return _cairo_error (CAIRO_STATUS_NO_MEMORY); } - memcpy (font_utf8, text_utf8, text_utf8_len); - font_utf8[text_utf8_len] = 0; font_utf8_len = text_utf8_len; } free (ucs4); } } - /* If glyph is in the winansi encoding and font is not a user + /* If glyph is in the winansi encoding and font is not a scaled * font, put glyph in the latin subset. */ is_latin = FALSE; latin_character = -1; - if (sub_font->use_latin_subset && - (! _cairo_font_face_is_user (sub_font->scaled_font->font_face))) + if (sub_font->use_latin_subset && !sub_font->is_scaled) { latin_character = _cairo_unicode_to_winansi (font_unicode); if (latin_character > 0) @@ -843,6 +835,9 @@ _cairo_scaled_font_subsets_map_glyph (cairo_scaled_font_subsets_t *subsets, cairo_int_status_t status; int max_glyphs; cairo_bool_t type1_font; + cairo_bool_t has_path; + cairo_bool_t has_color; + cairo_bool_t is_user; /* Lookup glyph in unscaled subsets */ if (subsets->type != CAIRO_SUBSETS_SCALED) { @@ -876,29 +871,47 @@ _cairo_scaled_font_subsets_map_glyph (cairo_scaled_font_subsets_t *subsets, /* Glyph not found. Determine whether the glyph is outline or * bitmap and add to the appropriate subset. - * - * glyph_index 0 (the .notdef glyph) is a special case. Some fonts + */ + is_user = _cairo_font_face_is_user (scaled_font->font_face); + _cairo_scaled_font_freeze_cache (scaled_font); + /* Check if glyph is color */ + status = _cairo_scaled_glyph_lookup (scaled_font, + scaled_font_glyph_index, + CAIRO_SCALED_GLYPH_INFO_COLOR_SURFACE, + NULL, /* foreground color */ + &scaled_glyph); + has_color = (status == CAIRO_INT_STATUS_SUCCESS); + + /* Check if glyph has a path */ + status = _cairo_scaled_glyph_lookup (scaled_font, + scaled_font_glyph_index, + CAIRO_SCALED_GLYPH_INFO_PATH, + NULL, /* foreground color */ + &scaled_glyph); + has_path = (status == CAIRO_INT_STATUS_SUCCESS); + + /* glyph_index 0 (the .notdef glyph) is a special case. Some fonts * will return CAIRO_INT_STATUS_UNSUPPORTED when doing a * _scaled_glyph_lookup(_GLYPH_INFO_PATH). Type1-fallback creates * empty glyphs in this case so we can put the glyph in a unscaled - * subset. */ - if (scaled_font_glyph_index == 0 || - _cairo_font_face_is_user (scaled_font->font_face)) { - status = CAIRO_STATUS_SUCCESS; - } else { - _cairo_scaled_font_freeze_cache (scaled_font); - status = _cairo_scaled_glyph_lookup (scaled_font, - scaled_font_glyph_index, - CAIRO_SCALED_GLYPH_INFO_PATH, - &scaled_glyph); - _cairo_scaled_font_thaw_cache (scaled_font); - } + * subset. + */ + if (scaled_font_glyph_index == 0 && !is_user) + has_path = TRUE; + + /* If this fails there is nothing we can do with this glyph. */ + status = _cairo_scaled_glyph_lookup (scaled_font, + scaled_font_glyph_index, + CAIRO_SCALED_GLYPH_INFO_SURFACE, + NULL, /* foreground color */ + &scaled_glyph); + _cairo_scaled_font_thaw_cache (scaled_font); if (_cairo_int_status_is_error (status)) return status; - if (status == CAIRO_INT_STATUS_SUCCESS && - subsets->type != CAIRO_SUBSETS_SCALED && - ! _cairo_font_face_is_user (scaled_font->font_face)) + /* Type 3 glyphs (is_user and has_color) must be added to scaled subset */ + if (subsets->type != CAIRO_SUBSETS_SCALED && + has_path && !has_color && !is_user) { /* Path available. Add to unscaled subset. */ key.is_scaled = FALSE; @@ -1010,19 +1023,12 @@ _cairo_scaled_font_subsets_foreach_internal (cairo_scaled_font_subsets_t { cairo_sub_font_collection_t collection; cairo_sub_font_t *sub_font; - cairo_bool_t is_scaled, is_user; + cairo_bool_t is_scaled; is_scaled = FALSE; - is_user = FALSE; - - if (type == CAIRO_SUBSETS_FOREACH_USER) - is_user = TRUE; - if (type == CAIRO_SUBSETS_FOREACH_SCALED || - type == CAIRO_SUBSETS_FOREACH_USER) - { + if (type == CAIRO_SUBSETS_FOREACH_SCALED) is_scaled = TRUE; - } if (is_scaled) collection.glyphs_size = font_subsets->max_glyphs_per_scaled_subset_used; @@ -1058,9 +1064,7 @@ _cairo_scaled_font_subsets_foreach_internal (cairo_scaled_font_subsets_t sub_font = font_subsets->unscaled_sub_fonts_list; while (sub_font) { - if (sub_font->is_user == is_user) - _cairo_sub_font_collect (sub_font, &collection); - + _cairo_sub_font_collect (sub_font, &collection); sub_font = sub_font->next; } free (collection.utf8); @@ -1093,17 +1097,6 @@ _cairo_scaled_font_subsets_foreach_unscaled (cairo_scaled_font_subsets_t *fo CAIRO_SUBSETS_FOREACH_UNSCALED); } -cairo_status_t -_cairo_scaled_font_subsets_foreach_user (cairo_scaled_font_subsets_t *font_subsets, - cairo_scaled_font_subset_callback_func_t font_subset_callback, - void *closure) -{ - return _cairo_scaled_font_subsets_foreach_internal (font_subsets, - font_subset_callback, - closure, - CAIRO_SUBSETS_FOREACH_USER); -} - static cairo_bool_t _cairo_string_equal (const void *key_a, const void *key_b) { diff --git a/gfx/cairo/cairo/src/cairo-scaled-font.c b/gfx/cairo/cairo/src/cairo-scaled-font.c index d53915fee0..70d1eab2a0 100755 --- a/gfx/cairo/cairo/src/cairo-scaled-font.c +++ b/gfx/cairo/cairo/src/cairo-scaled-font.c @@ -39,6 +39,7 @@ */ #include "cairoint.h" +#include "cairo-array-private.h" #include "cairo-error-private.h" #include "cairo-image-surface-private.h" #include "cairo-list-inline.h" @@ -56,7 +57,7 @@ * size and transformation and a certain set of font options. **/ -static uint32_t +static uintptr_t _cairo_scaled_font_compute_hash (cairo_scaled_font_t *scaled_font); /* Global Glyph Cache @@ -215,8 +216,17 @@ _cairo_scaled_glyph_fini (cairo_scaled_font_t *scaled_font, _cairo_path_fixed_destroy (scaled_glyph->path); if (scaled_glyph->recording_surface != NULL) { - cairo_surface_finish (scaled_glyph->recording_surface); - cairo_surface_destroy (scaled_glyph->recording_surface); + cairo_status_t status; + + /* If the recording surface contains other fonts, destroying + * it while holding _cairo_scaled_glyph_page_cache_mutex will + * result in deadlock when the recording surface font is + * destroyed. Instead, move the recording surface to a list of + * surfaces to free and free it in + * _cairo_scaled_font_thaw_cache() after + * _cairo_scaled_glyph_page_cache_mutex is unlocked. */ + status = _cairo_array_append (&scaled_font->recording_surfaces_to_free, &scaled_glyph->recording_surface); + assert (status == CAIRO_STATUS_SUCCESS); } if (scaled_glyph->color_surface != NULL) @@ -250,6 +260,7 @@ static const cairo_scaled_font_t _cairo_scaled_font_nil = { { NULL, NULL }, /* pages */ FALSE, /* cache_frozen */ FALSE, /* global_cache_frozen */ + { 0, 0, sizeof(cairo_surface_t*), NULL }, /* recording_surfaces_to_free */ { NULL, NULL }, /* privates */ NULL /* backend */ }; @@ -325,7 +336,6 @@ cairo_scaled_font_status (cairo_scaled_font_t *scaled_font) { return scaled_font->status; } -slim_hidden_def (cairo_scaled_font_status); /* Here we keep a unique mapping from * font_face/matrix/ctm/font_options => #cairo_scaled_font_t. @@ -476,7 +486,7 @@ _cairo_scaled_glyph_page_pluck (void *closure) scaled_font = page->scaled_font; - CAIRO_MUTEX_LOCK (scaled_font->mutex); + /* The font is locked in _cairo_scaled_glyph_page_can_remove () */ _cairo_scaled_glyph_page_destroy (scaled_font, page); CAIRO_MUTEX_UNLOCK (scaled_font->mutex); } @@ -598,25 +608,25 @@ _cairo_scaled_font_placeholder_wait_for_creation_to_finish (cairo_scaled_font_t * well tested with binary data. */ -#define FNV_32_PRIME ((uint32_t)0x01000193) -#define FNV1_32_INIT ((uint32_t)0x811c9dc5) +#define FNV_64_PRIME ((uint64_t)0x00000100000001B3) +#define FNV1_64_INIT ((uint64_t)0xcbf29ce484222325) -static uint32_t +static uint64_t _hash_matrix_fnv (const cairo_matrix_t *matrix, - uint32_t hval) + uint64_t hval) { const uint8_t *buffer = (const uint8_t *) matrix; int len = sizeof (cairo_matrix_t); do { - hval *= FNV_32_PRIME; + hval *= FNV_64_PRIME; hval ^= *buffer++; } while (--len); return hval; } -static uint32_t -_hash_mix_bits (uint32_t hash) +static uint64_t +_hash_mix_bits (uint64_t hash) { hash += hash << 12; hash ^= hash >> 7; @@ -626,17 +636,17 @@ _hash_mix_bits (uint32_t hash) return hash; } -static uint32_t +static uintptr_t _cairo_scaled_font_compute_hash (cairo_scaled_font_t *scaled_font) { - uint32_t hash = FNV1_32_INIT; + uint64_t hash = FNV1_64_INIT; /* We do a bytewise hash on the font matrices */ hash = _hash_matrix_fnv (&scaled_font->font_matrix, hash); hash = _hash_matrix_fnv (&scaled_font->ctm, hash); hash = _hash_mix_bits (hash); - hash ^= (unsigned long) scaled_font->original_font_face; + hash ^= (uintptr_t) scaled_font->original_font_face; hash ^= cairo_font_options_hash (&scaled_font->options); /* final mixing of bits */ @@ -668,6 +678,12 @@ _cairo_scaled_font_init_key (cairo_scaled_font_t *scaled_font, _cairo_scaled_font_compute_hash (scaled_font); } +static void +_cairo_scaled_font_fini_key (cairo_scaled_font_t *scaled_font) +{ + _cairo_font_options_fini (&scaled_font->options); +} + static cairo_bool_t _cairo_scaled_font_keys_equal (const void *abstract_key_a, const void *abstract_key_b) @@ -765,6 +781,7 @@ _cairo_scaled_font_init (cairo_scaled_font_t *scaled_font, cairo_list_init (&scaled_font->glyph_pages); scaled_font->cache_frozen = FALSE; scaled_font->global_cache_frozen = FALSE; + _cairo_array_init (&scaled_font->recording_surfaces_to_free, sizeof (cairo_surface_t *)); scaled_font->holdover = FALSE; scaled_font->finished = FALSE; @@ -776,7 +793,7 @@ _cairo_scaled_font_init (cairo_scaled_font_t *scaled_font, cairo_font_face_reference (font_face); scaled_font->original_font_face = NULL; - CAIRO_MUTEX_INIT (scaled_font->mutex); + CAIRO_RECURSIVE_MUTEX_INIT (scaled_font->mutex); cairo_list_init (&scaled_font->dev_privates); @@ -786,6 +803,22 @@ _cairo_scaled_font_init (cairo_scaled_font_t *scaled_font, return CAIRO_STATUS_SUCCESS; } +static void _cairo_scaled_font_free_recording_surfaces (cairo_scaled_font_t *scaled_font) +{ + int num_recording_surfaces; + cairo_surface_t *surface; + + num_recording_surfaces = _cairo_array_num_elements (&scaled_font->recording_surfaces_to_free); + if (num_recording_surfaces > 0) { + for (int i = 0; i < num_recording_surfaces; i++) { + _cairo_array_copy_element (&scaled_font->recording_surfaces_to_free, i, &surface); + cairo_surface_finish (surface); + cairo_surface_destroy (surface); + } + _cairo_array_truncate (&scaled_font->recording_surfaces_to_free, 0); + } +} + void _cairo_scaled_font_freeze_cache (cairo_scaled_font_t *scaled_font) { @@ -808,6 +841,8 @@ _cairo_scaled_font_thaw_cache (cairo_scaled_font_t *scaled_font) scaled_font->global_cache_frozen = FALSE; } + _cairo_scaled_font_free_recording_surfaces (scaled_font); + scaled_font->cache_frozen = FALSE; CAIRO_MUTEX_UNLOCK (scaled_font->mutex); } @@ -885,10 +920,14 @@ _cairo_scaled_font_fini_internal (cairo_scaled_font_t *scaled_font) _cairo_scaled_font_reset_cache (scaled_font); _cairo_hash_table_destroy (scaled_font->glyphs); + _cairo_font_options_fini (&scaled_font->options); cairo_font_face_destroy (scaled_font->font_face); cairo_font_face_destroy (scaled_font->original_font_face); + _cairo_scaled_font_free_recording_surfaces (scaled_font); + _cairo_array_fini (&scaled_font->recording_surfaces_to_free); + CAIRO_MUTEX_FINI (scaled_font->mutex); while (! cairo_list_is_empty (&scaled_font->dev_privates)) { @@ -1073,6 +1112,7 @@ cairo_scaled_font_create (cairo_font_face_t *font_face, * just wait until it's done, then retry */ _cairo_scaled_font_placeholder_wait_for_creation_to_finish (scaled_font); } + _cairo_scaled_font_fini_key (&key); if (scaled_font != NULL) { /* If the original reference count is 0, then this font must have @@ -1143,7 +1183,6 @@ cairo_scaled_font_create (cairo_font_face_t *font_face, status = font_face->backend->scaled_font_create (font_face, font_matrix, ctm, options, &scaled_font); - /* Did we leave the backend in an error state? */ if (unlikely (status)) { _cairo_scaled_font_map_unlock (); if (font_face != original_font_face) @@ -1152,7 +1191,6 @@ cairo_scaled_font_create (cairo_font_face_t *font_face, if (dead != NULL) cairo_scaled_font_destroy (dead); - status = _cairo_font_face_set_error (font_face, status); return _cairo_scaled_font_create_in_error (status); } /* Or did we encounter an error whilst constructing the scaled font? */ @@ -1208,7 +1246,6 @@ cairo_scaled_font_create (cairo_font_face_t *font_face, return scaled_font; } -slim_hidden_def (cairo_scaled_font_create); static cairo_scaled_font_t *_cairo_scaled_font_nil_objects[CAIRO_STATUS_LAST_STATUS + 1]; @@ -1294,7 +1331,6 @@ cairo_scaled_font_reference (cairo_scaled_font_t *scaled_font) return scaled_font; } -slim_hidden_def (cairo_scaled_font_reference); /** * cairo_scaled_font_destroy: @@ -1378,7 +1414,6 @@ cairo_scaled_font_destroy (cairo_scaled_font_t *scaled_font) free (lru); } } -slim_hidden_def (cairo_scaled_font_destroy); /** * cairo_scaled_font_get_reference_count: @@ -1422,7 +1457,6 @@ cairo_scaled_font_get_user_data (cairo_scaled_font_t *scaled_font, return _cairo_user_data_array_get_data (&scaled_font->user_data, key); } -slim_hidden_def (cairo_scaled_font_get_user_data); /** * cairo_scaled_font_set_user_data: @@ -1454,7 +1488,6 @@ cairo_scaled_font_set_user_data (cairo_scaled_font_t *scaled_font, return _cairo_user_data_array_set_data (&scaled_font->user_data, key, user_data, destroy); } -slim_hidden_def (cairo_scaled_font_set_user_data); /* Public font API follows. */ @@ -1482,7 +1515,6 @@ 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: @@ -1611,6 +1643,7 @@ cairo_scaled_font_glyph_extents (cairo_scaled_font_t *scaled_font, status = _cairo_scaled_glyph_lookup (scaled_font, glyphs[i].index, CAIRO_SCALED_GLYPH_INFO_METRICS, + NULL, /* foreground color */ &scaled_glyph); if (unlikely (status)) { status = _cairo_scaled_font_set_error (scaled_font, status); @@ -1681,7 +1714,6 @@ ZERO_EXTENTS: extents->x_advance = 0.0; extents->y_advance = 0.0; } -slim_hidden_def (cairo_scaled_font_glyph_extents); #define GLYPH_LUT_SIZE 64 static cairo_status_t @@ -1732,6 +1764,7 @@ cairo_scaled_font_text_to_glyphs_internal_cached (cairo_scaled_font_t *scaled_ status = _cairo_scaled_glyph_lookup (scaled_font, g, CAIRO_SCALED_GLYPH_INFO_METRICS, + NULL, /* foreground color */ &scaled_glyph); if (unlikely (status)) return status; @@ -1792,6 +1825,7 @@ cairo_scaled_font_text_to_glyphs_internal_uncached (cairo_scaled_font_t *scaled status = _cairo_scaled_glyph_lookup (scaled_font, g, CAIRO_SCALED_GLYPH_INFO_METRICS, + NULL, /* foreground color */ &scaled_glyph); if (unlikely (status)) return status; @@ -1813,9 +1847,9 @@ cairo_scaled_font_text_to_glyphs_internal_uncached (cairo_scaled_font_t *scaled /** * cairo_scaled_font_text_to_glyphs: + * @scaled_font: a #cairo_scaled_font_t * @x: X position to place first glyph * @y: Y position to place first glyph - * @scaled_font: a #cairo_scaled_font_t * @utf8: a string of text encoded in UTF-8 * @utf8_len: length of @utf8 in bytes, or -1 if it is NUL-terminated * @glyphs: pointer to array of glyphs to fill @@ -2146,7 +2180,6 @@ cairo_scaled_font_text_to_glyphs (cairo_scaled_font_t *scaled_font, return status; } -slim_hidden_def (cairo_scaled_font_text_to_glyphs); static inline cairo_bool_t _range_contains_glyph (const cairo_box_t *extents, @@ -2176,6 +2209,7 @@ _cairo_scaled_font_single_glyph_device_extents (cairo_scaled_font_t *scaled_fon status = _cairo_scaled_glyph_lookup (scaled_font, glyph->index, CAIRO_SCALED_GLYPH_INFO_METRICS, + NULL, /* foreground color */ &scaled_glyph); if (likely (status == CAIRO_STATUS_SUCCESS)) { cairo_bool_t round_xy = _cairo_font_options_get_round_glyph_positions (&scaled_font->options) == CAIRO_ROUND_GLYPH_POS_ON; @@ -2246,6 +2280,7 @@ _cairo_scaled_font_glyph_device_extents (cairo_scaled_font_t *scaled_font, status = _cairo_scaled_glyph_lookup (scaled_font, glyphs[i].index, CAIRO_SCALED_GLYPH_INFO_METRICS, + NULL, /* foreground color */ &scaled_glyph); if (unlikely (status)) break; @@ -2337,200 +2372,6 @@ _cairo_scaled_font_glyph_approximate_extents (cairo_scaled_font_t *scaled_font, return TRUE; } -#if 0 -/* XXX win32 */ -cairo_status_t -_cairo_scaled_font_show_glyphs (cairo_scaled_font_t *scaled_font, - cairo_operator_t op, - const cairo_pattern_t *pattern, - cairo_surface_t *surface, - int source_x, - int source_y, - int dest_x, - int dest_y, - unsigned int width, - unsigned int height, - cairo_glyph_t *glyphs, - int num_glyphs, - cairo_region_t *clip_region) -{ - cairo_int_status_t status; - cairo_surface_t *mask = NULL; - cairo_format_t mask_format = CAIRO_FORMAT_A1; /* shut gcc up */ - cairo_surface_pattern_t mask_pattern; - int i; - - /* These operators aren't interpreted the same way by the backends; - * they are implemented in terms of other operators in cairo-gstate.c - */ - assert (op != CAIRO_OPERATOR_SOURCE && op != CAIRO_OPERATOR_CLEAR); - - if (scaled_font->status) - return scaled_font->status; - - if (!num_glyphs) - return CAIRO_STATUS_SUCCESS; - - if (scaled_font->backend->show_glyphs != NULL) { - int remaining_glyphs = num_glyphs; - status = scaled_font->backend->show_glyphs (scaled_font, - op, pattern, - surface, - source_x, source_y, - dest_x, dest_y, - width, height, - glyphs, num_glyphs, - clip_region, - &remaining_glyphs); - glyphs += num_glyphs - remaining_glyphs; - num_glyphs = remaining_glyphs; - if (remaining_glyphs == 0) - status = CAIRO_INT_STATUS_SUCCESS; - if (status != CAIRO_INT_STATUS_UNSUPPORTED) - return _cairo_scaled_font_set_error (scaled_font, status); - } - - /* Font display routine either does not exist or failed. */ - - _cairo_scaled_font_freeze_cache (scaled_font); - - for (i = 0; i < num_glyphs; i++) { - int x, y; - cairo_image_surface_t *glyph_surface; - cairo_scaled_glyph_t *scaled_glyph; - - status = _cairo_scaled_glyph_lookup (scaled_font, - glyphs[i].index, - CAIRO_SCALED_GLYPH_INFO_SURFACE, - &scaled_glyph); - - if (unlikely (status)) - goto CLEANUP_MASK; - - glyph_surface = scaled_glyph->surface; - - /* To start, create the mask using the format from the first - * glyph. Later we'll deal with different formats. */ - if (mask == NULL) { - mask_format = glyph_surface->format; - mask = cairo_image_surface_create (mask_format, width, height); - status = mask->status; - if (unlikely (status)) - goto CLEANUP_MASK; - } - - /* If we have glyphs of different formats, we "upgrade" the mask - * to the wider of the formats. */ - if (glyph_surface->format != mask_format && - _cairo_format_bits_per_pixel (mask_format) < - _cairo_format_bits_per_pixel (glyph_surface->format) ) - { - cairo_surface_t *new_mask; - - switch (glyph_surface->format) { - case CAIRO_FORMAT_ARGB32: - case CAIRO_FORMAT_A8: - case CAIRO_FORMAT_A1: - mask_format = glyph_surface->format; - break; - case CAIRO_FORMAT_RGB16_565: - case CAIRO_FORMAT_RGB24: - case CAIRO_FORMAT_RGB30: - case CAIRO_FORMAT_INVALID: - default: - ASSERT_NOT_REACHED; - mask_format = CAIRO_FORMAT_ARGB32; - break; - } - - new_mask = cairo_image_surface_create (mask_format, width, height); - status = new_mask->status; - if (unlikely (status)) { - cairo_surface_destroy (new_mask); - goto CLEANUP_MASK; - } - - _cairo_pattern_init_for_surface (&mask_pattern, mask); - /* Note that we only upgrade masks, i.e. A1 -> A8 -> ARGB32, so there is - * never any component alpha here. - */ - status = _cairo_surface_composite (CAIRO_OPERATOR_ADD, - &_cairo_pattern_white.base, - &mask_pattern.base, - new_mask, - 0, 0, - 0, 0, - 0, 0, - width, height, - NULL); - - _cairo_pattern_fini (&mask_pattern.base); - - if (unlikely (status)) { - cairo_surface_destroy (new_mask); - goto CLEANUP_MASK; - } - - cairo_surface_destroy (mask); - mask = new_mask; - } - - if (glyph_surface->width && glyph_surface->height) { - cairo_surface_pattern_t glyph_pattern; - - /* round glyph locations to the nearest pixel */ - /* XXX: FRAGILE: We're ignoring device_transform scaling here. A bug? */ - x = _cairo_lround (glyphs[i].x - - glyph_surface->base.device_transform.x0); - y = _cairo_lround (glyphs[i].y - - glyph_surface->base.device_transform.y0); - - _cairo_pattern_init_for_surface (&glyph_pattern, - &glyph_surface->base); - if (mask_format == CAIRO_FORMAT_ARGB32) - glyph_pattern.base.has_component_alpha = TRUE; - - status = _cairo_surface_composite (CAIRO_OPERATOR_ADD, - &_cairo_pattern_white.base, - &glyph_pattern.base, - mask, - 0, 0, - 0, 0, - x - dest_x, y - dest_y, - glyph_surface->width, - glyph_surface->height, - NULL); - - _cairo_pattern_fini (&glyph_pattern.base); - - if (unlikely (status)) - goto CLEANUP_MASK; - } - } - - _cairo_pattern_init_for_surface (&mask_pattern, mask); - if (mask_format == CAIRO_FORMAT_ARGB32) - mask_pattern.base.has_component_alpha = TRUE; - - status = _cairo_surface_composite (op, pattern, &mask_pattern.base, - surface, - source_x, source_y, - 0, 0, - dest_x, dest_y, - width, height, - clip_region); - - _cairo_pattern_fini (&mask_pattern.base); - -CLEANUP_MASK: - _cairo_scaled_font_thaw_cache (scaled_font); - - if (mask != NULL) - cairo_surface_destroy (mask); - return _cairo_scaled_font_set_error (scaled_font, status); -} -#endif - /* Add a single-device-unit rectangle to a path. */ static cairo_status_t _add_unit_rectangle_to_path (cairo_path_fixed_t *path, @@ -2656,6 +2497,7 @@ _cairo_scaled_font_glyph_path (cairo_scaled_font_t *scaled_font, status = _cairo_scaled_glyph_lookup (scaled_font, glyphs[i].index, CAIRO_SCALED_GLYPH_INFO_PATH, + NULL, /* foreground color */ &scaled_glyph); if (status == CAIRO_INT_STATUS_SUCCESS) { status = _cairo_path_fixed_append (path, @@ -2670,6 +2512,7 @@ _cairo_scaled_font_glyph_path (cairo_scaled_font_t *scaled_font, status = _cairo_scaled_glyph_lookup (scaled_font, glyphs[i].index, CAIRO_SCALED_GLYPH_INFO_SURFACE, + NULL, /* foreground color */ &scaled_glyph); if (unlikely (status)) goto BAIL; @@ -2809,10 +2652,21 @@ _cairo_scaled_glyph_set_path (cairo_scaled_glyph_t *scaled_glyph, scaled_glyph->has_info &= ~CAIRO_SCALED_GLYPH_INFO_PATH; } +/** + * _cairo_scaled_glyph_set_recording_surface: + * @scaled_glyph: a #cairo_scaled_glyph_t + * @scaled_font: a #cairo_scaled_font_t + * @recording_surface: The recording surface + * @foreground_color: The foreground color that was used to record the + * glyph, or NULL if foreground color not required. + * + * Sets the surface that was used to record the glyph. + **/ void _cairo_scaled_glyph_set_recording_surface (cairo_scaled_glyph_t *scaled_glyph, - cairo_scaled_font_t *scaled_font, - cairo_surface_t *recording_surface) + cairo_scaled_font_t *scaled_font, + cairo_surface_t *recording_surface, + const cairo_color_t * foreground_color) { if (scaled_glyph->recording_surface != NULL) { cairo_surface_finish (scaled_glyph->recording_surface); @@ -2820,6 +2674,9 @@ _cairo_scaled_glyph_set_recording_surface (cairo_scaled_glyph_t *scaled_glyph, } scaled_glyph->recording_surface = recording_surface; + scaled_glyph->recording_uses_foreground_color = foreground_color != NULL; + if (foreground_color) + scaled_glyph->foreground_color = *foreground_color; if (recording_surface != NULL) scaled_glyph->has_info |= CAIRO_SCALED_GLYPH_INFO_RECORDING_SURFACE; @@ -2827,10 +2684,22 @@ _cairo_scaled_glyph_set_recording_surface (cairo_scaled_glyph_t *scaled_glyph, scaled_glyph->has_info &= ~CAIRO_SCALED_GLYPH_INFO_RECORDING_SURFACE; } +/** + * _cairo_scaled_glyph_set_color_surface: + * @scaled_glyph: a #cairo_scaled_glyph_t + * @scaled_font: a #cairo_scaled_font_t + * @surface: The image surface + * @foreground_marker_color: The foreground color that was used to + * substitute the foreground_marker, or NULL if foreground_marker not + * used when rendering the surface color. + * + * Sets the color surface of the glyph. + **/ void -_cairo_scaled_glyph_set_color_surface (cairo_scaled_glyph_t *scaled_glyph, - cairo_scaled_font_t *scaled_font, - cairo_image_surface_t *surface) +_cairo_scaled_glyph_set_color_surface (cairo_scaled_glyph_t *scaled_glyph, + cairo_scaled_font_t *scaled_font, + cairo_image_surface_t *surface, + const cairo_color_t *foreground_marker_color) { if (scaled_glyph->color_surface != NULL) cairo_surface_destroy (&scaled_glyph->color_surface->base); @@ -2838,6 +2707,9 @@ _cairo_scaled_glyph_set_color_surface (cairo_scaled_glyph_t *scaled_glyph, /* sanity check the backend glyph contents */ _cairo_debug_check_image_surface_is_defined (&surface->base); scaled_glyph->color_surface = surface; + scaled_glyph->recording_uses_foreground_marker = foreground_marker_color != NULL; + if (foreground_marker_color) + scaled_glyph->foreground_color = *foreground_marker_color; if (surface != NULL) scaled_glyph->has_info |= CAIRO_SCALED_GLYPH_INFO_COLOR_SURFACE; @@ -2845,14 +2717,26 @@ _cairo_scaled_glyph_set_color_surface (cairo_scaled_glyph_t *scaled_glyph, scaled_glyph->has_info &= ~CAIRO_SCALED_GLYPH_INFO_COLOR_SURFACE; } +/* _cairo_hash_table_random_entry () predicate. To avoid race conditions, + * the font is locked when tested. The font is unlocked in + * _cairo_scaled_glyph_page_pluck. */ static cairo_bool_t _cairo_scaled_glyph_page_can_remove (const void *closure) { const cairo_scaled_glyph_page_t *page = closure; - const cairo_scaled_font_t *scaled_font; + cairo_scaled_font_t *scaled_font; scaled_font = page->scaled_font; - return scaled_font->cache_frozen == 0; + + if (!CAIRO_MUTEX_TRY_LOCK (scaled_font->mutex)) + return FALSE; + + if (scaled_font->cache_frozen != 0) { + CAIRO_MUTEX_UNLOCK (scaled_font->mutex); + return FALSE; + } + + return TRUE; } static cairo_status_t @@ -2879,7 +2763,7 @@ _cairo_scaled_font_allocate_glyph (cairo_scaled_font_t *scaled_font, if (unlikely (page == NULL)) return _cairo_error (CAIRO_STATUS_NO_MEMORY); - page->cache_entry.hash = (unsigned long) scaled_font; + page->cache_entry.hash = (uintptr_t) scaled_font; page->scaled_font = scaled_font; page->cache_entry.size = 1; /* XXX occupancy weighting? */ page->num_glyphs = 0; @@ -2956,6 +2840,11 @@ _cairo_scaled_font_free_last_glyph (cairo_scaled_font_t *scaled_font, * @index: the glyph to create * @info: a #cairo_scaled_glyph_info_t marking which portions of * the glyph should be filled in. + * @foreground_color - foreground color to use when rendering color + * fonts. Use NULL if not requesting + * CAIRO_SCALED_GLYPH_INFO_RECORDING_SURFACE or + * CAIRO_SCALED_GLYPH_INFO_COLOR_SURFACE, or foreground color is + * unknown. * @scaled_glyph_ret: a #cairo_scaled_glyph_t where the glyph * is returned. * @@ -2976,16 +2865,20 @@ _cairo_scaled_font_free_last_glyph (cairo_scaled_font_t *scaled_font, * %CAIRO_SCALED_GLYPH_INFO_METRICS - glyph metrics and bounding box * %CAIRO_SCALED_GLYPH_INFO_SURFACE - surface holding glyph image * %CAIRO_SCALED_GLYPH_INFO_PATH - path holding glyph outline in device space + * %CAIRO_SCALED_GLYPH_INFO_RECORDING_SURFACE - surface holding recording of glyph + * %CAIRO_SCALED_GLYPH_INFO_COLOR_SURFACE - surface holding color glyph image **/ cairo_int_status_t _cairo_scaled_glyph_lookup (cairo_scaled_font_t *scaled_font, unsigned long index, cairo_scaled_glyph_info_t info, + const cairo_color_t *foreground_color, cairo_scaled_glyph_t **scaled_glyph_ret) { cairo_int_status_t status = CAIRO_INT_STATUS_SUCCESS; cairo_scaled_glyph_t *scaled_glyph; cairo_scaled_glyph_info_t need_info; + cairo_hash_entry_t key; *scaled_glyph_ret = NULL; @@ -2998,11 +2891,14 @@ _cairo_scaled_glyph_lookup (cairo_scaled_font_t *scaled_font, if (CAIRO_INJECT_FAULT ()) return _cairo_error (CAIRO_STATUS_NO_MEMORY); + if (foreground_color == NULL) + foreground_color = CAIRO_COLOR_BLACK; + /* * Check cache for glyph */ - scaled_glyph = _cairo_hash_table_lookup (scaled_font->glyphs, - (cairo_hash_entry_t *) &index); + key.hash = index; + scaled_glyph = _cairo_hash_table_lookup (scaled_font->glyphs, &key); if (scaled_glyph == NULL) { status = _cairo_scaled_font_allocate_glyph (scaled_font, &scaled_glyph); if (unlikely (status)) @@ -3016,7 +2912,8 @@ _cairo_scaled_glyph_lookup (cairo_scaled_font_t *scaled_font, status = scaled_font->backend->scaled_glyph_init (scaled_font, scaled_glyph, - info | CAIRO_SCALED_GLYPH_INFO_METRICS); + info | CAIRO_SCALED_GLYPH_INFO_METRICS, + foreground_color); if (unlikely (status)) { _cairo_scaled_font_free_last_glyph (scaled_font, scaled_glyph); goto err; @@ -3035,10 +2932,37 @@ _cairo_scaled_glyph_lookup (cairo_scaled_font_t *scaled_font, * already has the requested data and amend it if not */ need_info = info & ~scaled_glyph->has_info; + + /* If this is not a color glyph, don't try loading the color surface again. */ + if ((need_info & CAIRO_SCALED_GLYPH_INFO_COLOR_SURFACE) && + scaled_glyph->color_glyph_set && !scaled_glyph->color_glyph) + return CAIRO_INT_STATUS_UNSUPPORTED; + + /* If requesting a color surface or recording for a glyph that has + * used the foreground color to render the recording, and the + * foreground color has changed, request a new recording. */ + if ((info & (CAIRO_SCALED_GLYPH_INFO_RECORDING_SURFACE | CAIRO_SCALED_GLYPH_INFO_COLOR_SURFACE)) && + scaled_glyph->recording_uses_foreground_color && + !_cairo_color_equal (foreground_color, &scaled_glyph->foreground_color)) + { + need_info |= CAIRO_SCALED_GLYPH_INFO_RECORDING_SURFACE; + } + + /* If requesting a color surface for a glyph that has + * used the foreground color to render the color_surface, and the + * foreground color has changed, request a new image. */ + if (info & CAIRO_SCALED_GLYPH_INFO_COLOR_SURFACE && + (scaled_glyph->recording_uses_foreground_marker || scaled_glyph->recording_uses_foreground_color) && + !_cairo_color_equal (foreground_color, &scaled_glyph->foreground_color)) + { + need_info |= CAIRO_SCALED_GLYPH_INFO_COLOR_SURFACE; + } + if (need_info) { status = scaled_font->backend->scaled_glyph_init (scaled_font, scaled_glyph, - need_info); + need_info, + foreground_color); if (unlikely (status)) goto err; @@ -3066,7 +2990,6 @@ _cairo_scaled_font_get_max_scale (cairo_scaled_font_t *scaled_font) return scaled_font->max_scale; } - /** * cairo_scaled_font_get_font_face: * @scaled_font: a #cairo_scaled_font_t @@ -3092,7 +3015,6 @@ 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: @@ -3115,7 +3037,6 @@ 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: @@ -3140,7 +3061,6 @@ 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_scale_matrix: @@ -3188,9 +3108,9 @@ cairo_scaled_font_get_font_options (cairo_scaled_font_t *scaled_font, return; } + _cairo_font_options_fini (options); _cairo_font_options_init_copy (options, &scaled_font->options); } -slim_hidden_def (cairo_scaled_font_get_font_options); cairo_bool_t _cairo_scaled_font_has_color_glyphs (cairo_scaled_font_t *scaled_font) diff --git a/gfx/cairo/cairo/src/cairo-script-private.h b/gfx/cairo/cairo/src/cairo-script-private.h index 5b506f500c..989401244e 100644 --- a/gfx/cairo/cairo/src/cairo-script-private.h +++ b/gfx/cairo/cairo/src/cairo-script-private.h @@ -52,8 +52,6 @@ cairo_private void _cairo_script_context_attach_snapshots (cairo_device_t *device, cairo_bool_t enable); -slim_hidden_proto (cairo_script_surface_create); - CAIRO_END_DECLS #endif /* CAIRO_SCRIPT_PRIVATE_H */ diff --git a/gfx/cairo/cairo/src/cairo-script-surface.c b/gfx/cairo/cairo/src/cairo-script-surface.c index 4d7778b990..46790ab9ab 100644 --- a/gfx/cairo/cairo/src/cairo-script-surface.c +++ b/gfx/cairo/cairo/src/cairo-script-surface.c @@ -371,6 +371,21 @@ _filter_to_string (cairo_filter_t filter) } static const char * +_dither_to_string (cairo_dither_t dither) +{ + static const char *names[] = { + "DITHER_DEFAULT", /* CAIRO_FILTER_FAST */ + "DITHER_NONE", /* CAIRO_FILTER_GOOD */ + "DITHER_FAST", /* CAIRO_FILTER_BEST */ + "DITHER_GOOD", /* CAIRO_FILTER_NEAREST */ + "DITHER_BEST", /* CAIRO_FILTER_BILINEAR */ + }; + assert (dither < ARRAY_LENGTH (names)); + return names[dither]; +} + + +static const char * _fill_rule_to_string (cairo_fill_rule_t rule) { static const char *names[] = { @@ -709,6 +724,24 @@ _emit_line_width (cairo_script_surface_t *surface, } static cairo_status_t +_emit_hairline (cairo_script_surface_t *surface, cairo_bool_t set_hairline) +{ + assert (target_is_active (surface)); + + if (surface->cr.current_style.is_hairline == set_hairline) + { + return CAIRO_STATUS_SUCCESS; + } + + surface->cr.current_style.is_hairline = set_hairline; + + _cairo_output_stream_printf (to_context (surface)->stream, + "%d set-hairline\n", + set_hairline); + return CAIRO_STATUS_SUCCESS; +} + +static cairo_status_t _emit_line_cap (cairo_script_surface_t *surface, cairo_line_cap_t line_cap) { @@ -858,6 +891,10 @@ _emit_stroke_style (cairo_script_surface_t *surface, if (unlikely (status)) return status; + status = _emit_hairline (surface, style->is_hairline); + if (unlikely (status)) + return status; + status = _emit_dash (surface, style->dash, style->num_dashes, style->dash_offset, force); @@ -1709,6 +1746,17 @@ _emit_pattern (cairo_script_surface_t *surface, " //%s set-filter\n ", _filter_to_string (pattern->filter)); } + /* XXX need to discriminate the user explicitly setting the default */ + if (pattern->dither != CAIRO_DITHER_DEFAULT) { + if (need_newline) { + _cairo_output_stream_puts (ctx->stream, "\n "); + need_newline = FALSE; + } + + _cairo_output_stream_printf (ctx->stream, + " //%s set-dither\n ", + _dither_to_string (pattern->dither)); + } if (! is_default_extend ){ if (need_newline) { _cairo_output_stream_puts (ctx->stream, "\n "); @@ -1860,7 +1908,7 @@ _emit_path_boxes (cairo_script_surface_t *surface, if (! _cairo_path_fixed_iter_at_end (&iter)) { _cairo_boxes_fini (&boxes); - return CAIRO_STATUS_INVALID_PATH_DATA; + return CAIRO_INT_STATUS_UNSUPPORTED; } for (chunk = &boxes.chunks; chunk; chunk = chunk->next) { @@ -2091,6 +2139,16 @@ _device_flush (void *abstract_device) } static void +_device_finish (void *abstract_device) +{ + cairo_script_context_t *ctx = abstract_device; + + cairo_status_t status = _cairo_output_stream_close (ctx->stream); + status = _cairo_device_set_error (&ctx->base, status); + (void) status; +} + +static void _device_destroy (void *abstract_device) { cairo_script_context_t *ctx = abstract_device; @@ -2172,6 +2230,7 @@ _cairo_script_surface_finish (void *abstract_surface) _cairo_pattern_fini (&surface->cr.current_source.base); _cairo_path_fixed_fini (&surface->cr.current_path); + _cairo_font_options_fini (&surface->cr.current_font_options); _cairo_surface_clipper_reset (&surface->clipper); status = cairo_device_acquire (&ctx->base); @@ -2207,8 +2266,7 @@ _cairo_script_surface_finish (void *abstract_surface) cairo_list_del (&surface->operand.link); } else { link->operand.type = DEFERRED; - cairo_list_swap (&link->operand.link, - &surface->operand.link); + cairo_list_move_list (&surface->operand.link, &link->operand.link); cairo_list_add (&link->link, &ctx->deferred); } } @@ -2477,7 +2535,7 @@ _cairo_script_surface_paint (void *abstract_surface, if (_cairo_surface_wrapper_is_active (&surface->wrapper)) { return _cairo_surface_wrapper_paint (&surface->wrapper, - op, source, clip); + op, source, 0, clip); } return CAIRO_STATUS_SUCCESS; @@ -2534,7 +2592,7 @@ _cairo_script_surface_mask (void *abstract_surface, if (_cairo_surface_wrapper_is_active (&surface->wrapper)) { return _cairo_surface_wrapper_mask (&surface->wrapper, - op, source, mask, clip); + op, source, 0, mask, 0, clip); } return CAIRO_STATUS_SUCCESS; @@ -2621,7 +2679,7 @@ _cairo_script_surface_stroke (void *abstract_surface, if (_cairo_surface_wrapper_is_active (&surface->wrapper)) { return _cairo_surface_wrapper_stroke (&surface->wrapper, - op, source, path, + op, source, 0, path, style, ctm, ctm_inverse, tolerance, antialias, @@ -2702,7 +2760,7 @@ _cairo_script_surface_fill (void *abstract_surface, if (_cairo_surface_wrapper_is_active (&surface->wrapper)) { return _cairo_surface_wrapper_fill (&surface->wrapper, - op, source, path, + op, source, 0, path, fill_rule, tolerance, antialias, @@ -3012,6 +3070,7 @@ _emit_scaled_font (cairo_script_surface_t *surface, if (unlikely (status)) return status; + _cairo_font_options_init_default (&options); cairo_scaled_font_get_font_options (scaled_font, &options); status = _emit_font_options (surface, &options); if (unlikely (status)) @@ -3047,7 +3106,7 @@ _emit_scaled_glyph_vector (cairo_script_surface_t *surface, index = ++font_private->subset_glyph_index; scaled_glyph->dev_private_key = ctx; - scaled_glyph->dev_private = (void *) index; + scaled_glyph->dev_private = (void *)(uintptr_t)index; _cairo_output_stream_printf (ctx->stream, "%lu <<\n" @@ -3095,7 +3154,7 @@ _emit_scaled_glyph_bitmap (cairo_script_surface_t *surface, index = ++font_private->subset_glyph_index; scaled_glyph->dev_private_key = ctx; - scaled_glyph->dev_private = (void *) index; + scaled_glyph->dev_private = (void *)(uintptr_t)index; _cairo_output_stream_printf (ctx->stream, "%lu <<\n" @@ -3172,6 +3231,7 @@ _emit_scaled_glyphs (cairo_script_surface_t *surface, status = _cairo_scaled_glyph_lookup (scaled_font, glyphs[n].index, CAIRO_SCALED_GLYPH_INFO_METRICS, + NULL, /* foreground color */ &scaled_glyph); if (unlikely (status)) break; @@ -3182,6 +3242,7 @@ _emit_scaled_glyphs (cairo_script_surface_t *surface, status = _cairo_scaled_glyph_lookup (scaled_font, glyphs[n].index, CAIRO_SCALED_GLYPH_INFO_RECORDING_SURFACE, + NULL, /* foreground color */ &scaled_glyph); if (_cairo_status_is_error (status)) break; @@ -3207,6 +3268,7 @@ _emit_scaled_glyphs (cairo_script_surface_t *surface, status = _cairo_scaled_glyph_lookup (scaled_font, glyphs[n].index, CAIRO_SCALED_GLYPH_INFO_SURFACE, + NULL, /* foreground color */ &scaled_glyph); if (_cairo_status_is_error (status)) break; @@ -3290,7 +3352,7 @@ ESCAPED_CHAR: _cairo_output_stream_printf (ctx->stream, "\\%c", c); break; default: - if (isprint (c) || isspace (c)) { + if (_cairo_isprint(c)) { _cairo_output_stream_printf (ctx->stream, "%c", c); } else { char buf[4] = { '\\' }; @@ -3389,13 +3451,14 @@ _cairo_script_surface_show_text_glyphs (void *abstract_surface, status = _cairo_scaled_glyph_lookup (scaled_font, glyphs[n].index, CAIRO_SCALED_GLYPH_INFO_METRICS, + NULL, /* foreground color */ &scaled_glyph); if (unlikely (status)) { _cairo_scaled_font_thaw_cache (scaled_font); goto BAIL; } - if ((long unsigned) scaled_glyph->dev_private > 256) + if ((uintptr_t)scaled_glyph->dev_private > 256) break; } } @@ -3412,6 +3475,7 @@ _cairo_script_surface_show_text_glyphs (void *abstract_surface, status = _cairo_scaled_glyph_lookup (scaled_font, glyphs[n].index, CAIRO_SCALED_GLYPH_INFO_METRICS, + NULL, /* foreground color */ &scaled_glyph); if (unlikely (status)) { _cairo_scaled_font_thaw_cache (scaled_font); @@ -3466,7 +3530,7 @@ _cairo_script_surface_show_text_glyphs (void *abstract_surface, if (font_private->has_sfnt) c = glyphs[n].index; else - c = (uint8_t) (long unsigned) scaled_glyph->dev_private; + c = (uint8_t) (uintptr_t) scaled_glyph->dev_private; _cairo_output_stream_write (base85_stream, &c, 1); } else { @@ -3475,7 +3539,7 @@ _cairo_script_surface_show_text_glyphs (void *abstract_surface, glyphs[n].index); else _cairo_output_stream_printf (ctx->stream, " %lu", - (long unsigned) scaled_glyph->dev_private); + (long unsigned) (uintptr_t)scaled_glyph->dev_private); } dx = scaled_glyph->metrics.x_advance; @@ -3548,7 +3612,7 @@ _cairo_script_surface_show_text_glyphs (void *abstract_surface, if (_cairo_surface_wrapper_is_active (&surface->wrapper)){ return _cairo_surface_wrapper_show_text_glyphs (&surface->wrapper, - op, source, + op, source, 0, utf8, utf8_len, glyphs, num_glyphs, clusters, num_clusters, @@ -3704,7 +3768,7 @@ static const cairo_device_backend_t _cairo_script_device_backend = { NULL, NULL, /* lock, unlock */ _device_flush, /* flush */ - NULL, /* finish */ + _device_finish, /* finish */ _device_destroy }; @@ -3926,7 +3990,6 @@ cairo_script_surface_create (cairo_device_t *script, content, extents, NULL)->base; } -slim_hidden_def (cairo_script_surface_create); /** * cairo_script_surface_create_for_target: diff --git a/gfx/cairo/cairo/src/cairo-shape-mask-compositor.c b/gfx/cairo/cairo/src/cairo-shape-mask-compositor.c index 3117267ccc..0f4918603d 100644 --- a/gfx/cairo/cairo/src/cairo-shape-mask-compositor.c +++ b/gfx/cairo/cairo/src/cairo-shape-mask-compositor.c @@ -116,7 +116,7 @@ _cairo_shape_mask_compositor_stroke (const cairo_compositor_t *_compositor, &_cairo_pattern_white.base, &pattern.base, clip); - if ((status == CAIRO_INT_STATUS_SUCCESS)) { + if (status == CAIRO_INT_STATUS_SUCCESS) { status = _cairo_surface_mask (extents->surface, CAIRO_OPERATOR_ADD, &extents->source_pattern.base, @@ -210,7 +210,7 @@ _cairo_shape_mask_compositor_fill (const cairo_compositor_t *_compositor, &_cairo_pattern_white.base, &pattern.base, clip); - if ((status == CAIRO_INT_STATUS_SUCCESS)) { + if (status == CAIRO_INT_STATUS_SUCCESS) { status = _cairo_surface_mask (extents->surface, CAIRO_OPERATOR_ADD, &extents->source_pattern.base, @@ -303,7 +303,7 @@ _cairo_shape_mask_compositor_glyphs (const cairo_compositor_t *_compositor, &_cairo_pattern_white.base, &pattern.base, clip); - if ((status == CAIRO_INT_STATUS_SUCCESS)) { + if (status == CAIRO_INT_STATUS_SUCCESS) { status = _cairo_surface_mask (extents->surface, CAIRO_OPERATOR_ADD, &extents->source_pattern.base, diff --git a/gfx/cairo/cairo/src/cairo-spans.c b/gfx/cairo/cairo/src/cairo-spans.c index 59452c0ba6..711c0c1068 100644 --- a/gfx/cairo/cairo/src/cairo-spans.c +++ b/gfx/cairo/cairo/src/cairo-spans.c @@ -132,6 +132,8 @@ _cairo_scan_converter_create_in_error (cairo_status_t status) case CAIRO_STATUS_FREETYPE_ERROR: case CAIRO_STATUS_WIN32_GDI_ERROR: case CAIRO_STATUS_TAG_ERROR: + case CAIRO_STATUS_DWRITE_ERROR: + case CAIRO_STATUS_SVG_FONT_ERROR: default: break; } @@ -249,6 +251,8 @@ _cairo_span_renderer_create_in_error (cairo_status_t status) case CAIRO_STATUS_FREETYPE_ERROR: RETURN_NIL; case CAIRO_STATUS_WIN32_GDI_ERROR: RETURN_NIL; case CAIRO_STATUS_TAG_ERROR: RETURN_NIL; + case CAIRO_STATUS_DWRITE_ERROR: RETURN_NIL; + case CAIRO_STATUS_SVG_FONT_ERROR: RETURN_NIL; default: break; } diff --git a/gfx/cairo/cairo/src/cairo-spline.c b/gfx/cairo/cairo/src/cairo-spline.c index 44634faec8..6f50a637a9 100644 --- a/gfx/cairo/cairo/src/cairo-spline.c +++ b/gfx/cairo/cairo/src/cairo-spline.c @@ -177,7 +177,7 @@ _cairo_spline_error_squared (const cairo_spline_knots_t *knots) double bdx, bdy, berr; double cdx, cdy, cerr; - /* We are going to compute the distance (squared) between each of the the b + /* We are going to compute the distance (squared) between each of the b * and c control points and the segment a-b. The maximum of these two * distances will be our approximation error. */ diff --git a/gfx/cairo/cairo/src/cairo-stroke-style.c b/gfx/cairo/cairo/src/cairo-stroke-style.c index 9c373c3332..fed8aec55f 100644 --- a/gfx/cairo/cairo/src/cairo-stroke-style.c +++ b/gfx/cairo/cairo/src/cairo-stroke-style.c @@ -49,6 +49,8 @@ _cairo_stroke_style_init (cairo_stroke_style_t *style) style->dash = NULL; style->num_dashes = 0; style->dash_offset = 0.0; + + style->is_hairline = FALSE; } cairo_status_t @@ -80,6 +82,8 @@ _cairo_stroke_style_init_copy (cairo_stroke_style_t *style, style->dash_offset = other->dash_offset; + style->is_hairline = other->is_hairline; + return CAIRO_STATUS_SUCCESS; } @@ -199,7 +203,7 @@ _cairo_stroke_style_dash_period (const cairo_stroke_style_t *style) * respect to c: * solve ( diff (integrate ((f(w,d) - c*d)^2, d, 0, w), c), c) * Which leads to c = 9/32*pi*w - * Since we're not interested in the true area, but just in a coverage extimate, + * Since we're not interested in the true area, but just in a coverage estimate, * we always divide the real area by the line width (w). * The same computation for square caps would be * f(w,d) = 2 * integrate(w/2, x, -d/2, d/2) diff --git a/gfx/cairo/cairo/src/cairo-surface-backend-private.h b/gfx/cairo/cairo/src/cairo-surface-backend-private.h index d31655be89..856c596c86 100644 --- a/gfx/cairo/cairo/src/cairo-surface-backend-private.h +++ b/gfx/cairo/cairo/src/cairo-surface-backend-private.h @@ -1,3 +1,4 @@ +/* -*- Mode: c; tab-width: 8; c-basic-offset: 4; indent-tabs-mode: t; -*- */ /* cairo - a vector graphics library with display and print output * * Copyright © 2002 University of Southern California @@ -40,6 +41,7 @@ #include "cairo-compiler-private.h" #include "cairo-error-private.h" +#include "cairo-pattern-private.h" CAIRO_BEGIN_DECLS @@ -124,14 +126,14 @@ struct _cairo_surface_backend { (*paint) (void *surface, cairo_operator_t op, const cairo_pattern_t *source, - const cairo_clip_t *clip); + const cairo_clip_t *clip); cairo_warn cairo_int_status_t (*mask) (void *surface, cairo_operator_t op, const cairo_pattern_t *source, const cairo_pattern_t *mask, - const cairo_clip_t *clip); + const cairo_clip_t *clip); cairo_warn cairo_int_status_t (*stroke) (void *surface, @@ -143,7 +145,7 @@ struct _cairo_surface_backend { const cairo_matrix_t *ctm_inverse, double tolerance, cairo_antialias_t antialias, - const cairo_clip_t *clip); + const cairo_clip_t *clip); cairo_warn cairo_int_status_t (*fill) (void *surface, @@ -153,7 +155,7 @@ struct _cairo_surface_backend { cairo_fill_rule_t fill_rule, double tolerance, cairo_antialias_t antialias, - const cairo_clip_t *clip); + const cairo_clip_t *clip); cairo_warn cairo_int_status_t (*fill_stroke) (void *surface, @@ -196,7 +198,7 @@ struct _cairo_surface_backend { int num_clusters, cairo_text_cluster_flags_t cluster_flags, cairo_scaled_font_t *scaled_font, - const cairo_clip_t *clip); + const cairo_clip_t *clip); const char ** (*get_supported_mime_types) (void *surface); @@ -207,6 +209,33 @@ struct _cairo_surface_backend { const char *tag_name, const char *attributes); + cairo_bool_t + (*supports_color_glyph) (void *surface, + cairo_scaled_font_t *scaled_font, + unsigned long glyph_index); + + /* Paginated surfaces only. During the analysis stage, if any + * recording surfaces used as a source are to be replayed, this + * function will be called at the begining and end of the replay. + * + * @recording_surface - the recording surface used as a source + * @source_type - a type indicating the combination of drawing + * operation and source type + * @begin - TRUE when called before the replay, FALSE when called + * after the replay has finished. + */ + cairo_warn cairo_int_status_t + (*analyze_recording_surface)(void *surface, + const cairo_surface_pattern_t *recording_surface_pattern, + unsigned int region_id, + cairo_analysis_source_t source_type, + cairo_bool_t begin); + + cairo_warn cairo_int_status_t + (*command_id) (void *surface, + unsigned int recording_id, + unsigned int command_id); + }; cairo_private cairo_status_t diff --git a/gfx/cairo/cairo/src/cairo-surface-observer.c b/gfx/cairo/cairo/src/cairo-surface-observer.c index 9c4432e246..83aa41801c 100644 --- a/gfx/cairo/cairo/src/cairo-surface-observer.c +++ b/gfx/cairo/cairo/src/cairo-surface-observer.c @@ -54,6 +54,24 @@ #include "cairo-script-private.h" #endif +/** + * SECTION:cairo-surface-observer + * @Title: Surface Observer + * @Short_Description: Observing other surfaces + * @See_Also: #cairo_surface_t + * + * A surface that exists solely to watch what another surface is doing. + **/ + +/** + * CAIRO_HAS_OBSERVER_SURFACE: + * + * Defined if the observer surface backend is available. + * This macro can be used to conditionally compile backend-specific code. + * + * Since: 1.12 + **/ + static const cairo_surface_backend_t _cairo_surface_observer_backend; /* observation/stats */ @@ -1373,8 +1391,8 @@ static const cairo_surface_backend_t _cairo_surface_observer_backend = { * the process it will log operations and times, which are fast, which are * slow, which are frequent, etc. * - * The @mode parameter can be set to either CAIRO_SURFACE_OBSERVER_NORMAL - * or CAIRO_SURFACE_OBSERVER_RECORD_OPERATIONS, to control whether or not + * The @mode parameter can be set to either %CAIRO_SURFACE_OBSERVER_NORMAL + * or %CAIRO_SURFACE_OBSERVER_RECORD_OPERATIONS, to control whether or not * the internal observer should record operations. * * Return value: a pointer to the newly allocated surface. The caller @@ -1429,6 +1447,18 @@ _cairo_surface_observer_add_callback (cairo_list_t *head, return CAIRO_STATUS_SUCCESS; } +/** + * cairo_surface_observer_add_paint_callback: + * @abstract_surface: a #cairo_surface_observer_t + * @func: callback function for paint operations + * @data: closure to pass to the callback + * + * Adds a callback for paint operations on the observed surface. + * + * Returns: the status of the surface + * + * Since: 1.12 + **/ cairo_status_t cairo_surface_observer_add_paint_callback (cairo_surface_t *abstract_surface, cairo_surface_observer_callback_t func, @@ -1447,6 +1477,18 @@ cairo_surface_observer_add_paint_callback (cairo_surface_t *abstract_surface, func, data); } +/** + * cairo_surface_observer_add_mask_callback: + * @abstract_surface: a #cairo_surface_observer_t + * @func: callback function for mask operations + * @data: closure to pass to the callback + * + * Adds a callback for mask operations on the observed surface. + * + * Returns: the status of the surface + * + * Since: 1.12 + **/ cairo_status_t cairo_surface_observer_add_mask_callback (cairo_surface_t *abstract_surface, cairo_surface_observer_callback_t func, @@ -1465,6 +1507,18 @@ cairo_surface_observer_add_mask_callback (cairo_surface_t *abstract_surface, func, data); } +/** + * cairo_surface_observer_add_fill_callback: + * @abstract_surface: a #cairo_surface_observer_t + * @func: callback function for fill operations + * @data: closure to pass to the callback + * + * Adds a callback for fill operations on the observed surface. + * + * Returns: the status of the surface + * + * Since: 1.12 + **/ cairo_status_t cairo_surface_observer_add_fill_callback (cairo_surface_t *abstract_surface, cairo_surface_observer_callback_t func, @@ -1483,6 +1537,18 @@ cairo_surface_observer_add_fill_callback (cairo_surface_t *abstract_surface, func, data); } +/** + * cairo_surface_observer_add_stroke_callback: + * @abstract_surface: a #cairo_surface_observer_t + * @func: callback function for stroke operations + * @data: closure to pass to the callback + * + * Adds a callback for stroke operations on the observed surface. + * + * Returns: the status of the surface + * + * Since: 1.12 + **/ cairo_status_t cairo_surface_observer_add_stroke_callback (cairo_surface_t *abstract_surface, cairo_surface_observer_callback_t func, @@ -1501,6 +1567,18 @@ cairo_surface_observer_add_stroke_callback (cairo_surface_t *abstract_surface, func, data); } +/** + * cairo_surface_observer_add_glyphs_callback: + * @abstract_surface: a #cairo_surface_observer_t + * @func: callback function for glyph operations + * @data: closure to pass to the callback + * + * Adds a callback for glyph operations on the observed surface. + * + * Returns: the status of the surface + * + * Since: 1.10 + **/ cairo_status_t cairo_surface_observer_add_glyphs_callback (cairo_surface_t *abstract_surface, cairo_surface_observer_callback_t func, @@ -1519,6 +1597,18 @@ cairo_surface_observer_add_glyphs_callback (cairo_surface_t *abstract_surface, func, data); } +/** + * cairo_surface_observer_add_flush_callback: + * @abstract_surface: a #cairo_surface_observer_t + * @func: callback for flush operations + * @data: closure to pass to the callback + * + * Adds a callback for flush operations on the observed surface. + * + * Returns: the status of the surface + * + * Since: 1.10 + **/ cairo_status_t cairo_surface_observer_add_flush_callback (cairo_surface_t *abstract_surface, cairo_surface_observer_callback_t func, @@ -1537,6 +1627,18 @@ cairo_surface_observer_add_flush_callback (cairo_surface_t *abstract_surface, func, data); } +/** + * cairo_surface_observer_add_finish_callback: + * @abstract_surface: a #cairo_surface_observer_t + * @func: callback function for the finish operation + * @data: closure to pass to the callback + * + * Adds a callback for finish operations on the observed surface. + * + * Returns: the status of the surface + * + * Since: 1.10 + **/ cairo_status_t cairo_surface_observer_add_finish_callback (cairo_surface_t *abstract_surface, cairo_surface_observer_callback_t func, @@ -1957,6 +2059,18 @@ _cairo_observation_print (cairo_output_stream_t *stream, cairo_device_destroy (script); } +/** + * cairo_surface_observer_print: + * @abstract_surface: a #cairo_surface_observer_t + * @write_func: callback for writing on a stream + * @closure: data to pass to @write_func + * + * Prints the observer log using the given callback. + * + * Returns: the status of the print operation + * + * Since: 1.12 + **/ cairo_status_t cairo_surface_observer_print (cairo_surface_t *abstract_surface, cairo_write_func_t write_func, @@ -1978,6 +2092,16 @@ cairo_surface_observer_print (cairo_surface_t *abstract_surface, return _cairo_output_stream_destroy (stream); } +/** + * cairo_surface_observer_elapsed: + * @abstract_surface: a #cairo_surface_observer_t + * + * Returns the total observation time. + * + * Returns: the elapsed time, in nanoseconds + * + * Since: 1.12 + **/ double cairo_surface_observer_elapsed (cairo_surface_t *abstract_surface) { @@ -1993,6 +2117,18 @@ cairo_surface_observer_elapsed (cairo_surface_t *abstract_surface) return _cairo_time_to_ns (_cairo_observation_total_elapsed (&surface->log)); } +/** + * cairo_device_observer_print: + * @abstract_device: the observed #cairo_device_t + * @write_func: the write function + * @closure: data to pass to the @write_func + * + * Prints the device log using the given function. + * + * Returns: the status after the operation + * + * Since: 1.12 + **/ cairo_status_t cairo_device_observer_print (cairo_device_t *abstract_device, cairo_write_func_t write_func, @@ -2014,6 +2150,16 @@ cairo_device_observer_print (cairo_device_t *abstract_device, return _cairo_output_stream_destroy (stream); } +/** + * cairo_device_observer_elapsed: + * @abstract_device: the observed #cairo_device_t + * + * Returns the total elapsed time of the observation. + * + * Returns: the elapsed time, in nanoseconds. + * + * Since: 1.12 + **/ double cairo_device_observer_elapsed (cairo_device_t *abstract_device) { @@ -2029,6 +2175,16 @@ cairo_device_observer_elapsed (cairo_device_t *abstract_device) return _cairo_time_to_ns (_cairo_observation_total_elapsed (&device->log)); } +/** + * cairo_device_observer_paint_elapsed: + * @abstract_device: the observed #cairo_device_t + * + * Returns the elapsed time of the paint operations. + * + * Returns: the elapsed time, in nanoseconds. + * + * Since: 1.12 + **/ double cairo_device_observer_paint_elapsed (cairo_device_t *abstract_device) { @@ -2044,6 +2200,16 @@ cairo_device_observer_paint_elapsed (cairo_device_t *abstract_device) return _cairo_time_to_ns (device->log.paint.elapsed); } +/** + * cairo_device_observer_mask_elapsed: + * @abstract_device: the observed #cairo_device_t + * + * Returns the elapsed time of the mask operations. + * + * Returns: the elapsed time, in nanoseconds + * + * Since: 1.12 + **/ double cairo_device_observer_mask_elapsed (cairo_device_t *abstract_device) { @@ -2059,6 +2225,16 @@ cairo_device_observer_mask_elapsed (cairo_device_t *abstract_device) return _cairo_time_to_ns (device->log.mask.elapsed); } +/** + * cairo_device_observer_fill_elapsed: + * @abstract_device: the observed #cairo_device_t + * + * Returns the elapsed time of the fill operations. + * + * Returns: the elapsed time, in nanoseconds. + * + * Since: 1.12 + **/ double cairo_device_observer_fill_elapsed (cairo_device_t *abstract_device) { @@ -2074,6 +2250,16 @@ cairo_device_observer_fill_elapsed (cairo_device_t *abstract_device) return _cairo_time_to_ns (device->log.fill.elapsed); } +/** + * cairo_device_observer_stroke_elapsed: + * @abstract_device: the observed #cairo_device_t + * + * Returns the elapsed time of the stroke operations. + * + * Returns: the elapsed time, in nanoseconds. + * + * Since: 1.12 + **/ double cairo_device_observer_stroke_elapsed (cairo_device_t *abstract_device) { @@ -2089,6 +2275,16 @@ cairo_device_observer_stroke_elapsed (cairo_device_t *abstract_device) return _cairo_time_to_ns (device->log.stroke.elapsed); } +/** + * cairo_device_observer_glyphs_elapsed: + * @abstract_device: the observed #cairo_device_t + * + * Returns the elapsed time of the glyph operations. + * + * Returns: the elapsed time, in nanoseconds. + * + * Since: 1.12 + **/ double cairo_device_observer_glyphs_elapsed (cairo_device_t *abstract_device) { diff --git a/gfx/cairo/cairo/src/cairo-surface-private.h b/gfx/cairo/cairo/src/cairo-surface-private.h index 41f2f2cad8..71112afa5c 100644 --- a/gfx/cairo/cairo/src/cairo-surface-private.h +++ b/gfx/cairo/cairo/src/cairo-surface-private.h @@ -105,6 +105,9 @@ struct _cairo_surface { * cairo_surface_create_similar(). */ cairo_font_options_t font_options; + + cairo_pattern_t *foreground_source; + cairo_bool_t foreground_used; }; cairo_private cairo_surface_t * diff --git a/gfx/cairo/cairo/src/cairo-surface-wrapper-private.h b/gfx/cairo/cairo/src/cairo-surface-wrapper-private.h index 380ba099dc..016402d7ea 100644 --- a/gfx/cairo/cairo/src/cairo-surface-wrapper-private.h +++ b/gfx/cairo/cairo/src/cairo-surface-wrapper-private.h @@ -1,3 +1,4 @@ +/* -*- Mode: c; tab-width: 8; c-basic-offset: 4; indent-tabs-mode: t; -*- */ /* cairo - a vector graphics library with display and print output * * Copyright © 2002 University of Southern California @@ -41,6 +42,7 @@ #include "cairoint.h" #include "cairo-types-private.h" +#include "cairo-recording-surface-private.h" #include "cairo-surface-backend-private.h" CAIRO_BEGIN_DECLS @@ -54,6 +56,9 @@ struct _cairo_surface_wrapper { cairo_rectangle_int_t extents; const cairo_clip_t *clip; + unsigned int source_region_id; + unsigned int mask_region_id; + cairo_bool_t needs_transform; }; @@ -95,60 +100,68 @@ _cairo_surface_wrapper_release_source_image (cairo_surface_wrapper_t *wrapper, cairo_private cairo_status_t _cairo_surface_wrapper_paint (cairo_surface_wrapper_t *wrapper, - cairo_operator_t op, - const cairo_pattern_t *source, - const cairo_clip_t *clip); + cairo_operator_t op, + const cairo_pattern_t *source, + unsigned int source_region_id, + const cairo_clip_t *clip); cairo_private cairo_status_t _cairo_surface_wrapper_mask (cairo_surface_wrapper_t *wrapper, - cairo_operator_t op, - const cairo_pattern_t *source, - const cairo_pattern_t *mask, - const cairo_clip_t *clip); + cairo_operator_t op, + const cairo_pattern_t *source, + unsigned int source_region_id, + const cairo_pattern_t *mask, + unsigned int mask_region_id, + const cairo_clip_t *clip); cairo_private cairo_status_t -_cairo_surface_wrapper_stroke (cairo_surface_wrapper_t *wrapper, - cairo_operator_t op, - const cairo_pattern_t *source, - const cairo_path_fixed_t *path, - const cairo_stroke_style_t *stroke_style, - const cairo_matrix_t *ctm, - const cairo_matrix_t *ctm_inverse, - double tolerance, - cairo_antialias_t antialias, - const cairo_clip_t *clip); +_cairo_surface_wrapper_stroke (cairo_surface_wrapper_t *wrapper, + cairo_operator_t op, + const cairo_pattern_t *source, + unsigned int source_region_id, + const cairo_path_fixed_t *path, + const cairo_stroke_style_t *stroke_style, + const cairo_matrix_t *ctm, + const cairo_matrix_t *ctm_inverse, + double tolerance, + cairo_antialias_t antialias, + const cairo_clip_t *clip); cairo_private cairo_status_t -_cairo_surface_wrapper_fill_stroke (cairo_surface_wrapper_t *wrapper, - cairo_operator_t fill_op, - const cairo_pattern_t *fill_source, - cairo_fill_rule_t fill_rule, - double fill_tolerance, - cairo_antialias_t fill_antialias, - const cairo_path_fixed_t*path, - cairo_operator_t stroke_op, - const cairo_pattern_t *stroke_source, - const cairo_stroke_style_t *stroke_style, - const cairo_matrix_t *stroke_ctm, - const cairo_matrix_t *stroke_ctm_inverse, - double stroke_tolerance, - cairo_antialias_t stroke_antialias, - const cairo_clip_t *clip); +_cairo_surface_wrapper_fill_stroke (cairo_surface_wrapper_t *wrapper, + cairo_operator_t fill_op, + const cairo_pattern_t *fill_source, + unsigned int fill_region_id, + cairo_fill_rule_t fill_rule, + double fill_tolerance, + cairo_antialias_t fill_antialias, + const cairo_path_fixed_t *path, + cairo_operator_t stroke_op, + const cairo_pattern_t *stroke_source, + unsigned int stroke_region_id, + const cairo_stroke_style_t *stroke_style, + const cairo_matrix_t *stroke_ctm, + const cairo_matrix_t *stroke_ctm_inverse, + double stroke_tolerance, + cairo_antialias_t stroke_antialias, + const cairo_clip_t *clip); cairo_private cairo_status_t -_cairo_surface_wrapper_fill (cairo_surface_wrapper_t *wrapper, - cairo_operator_t op, - const cairo_pattern_t *source, - const cairo_path_fixed_t *path, - cairo_fill_rule_t fill_rule, - double tolerance, - cairo_antialias_t antialias, - const cairo_clip_t *clip); +_cairo_surface_wrapper_fill (cairo_surface_wrapper_t *wrapper, + cairo_operator_t op, + const cairo_pattern_t *source, + unsigned int source_region_id, + const cairo_path_fixed_t *path, + cairo_fill_rule_t fill_rule, + double tolerance, + cairo_antialias_t antialias, + const cairo_clip_t *clip); cairo_private cairo_status_t -_cairo_surface_wrapper_show_text_glyphs (cairo_surface_wrapper_t *wrapper, +_cairo_surface_wrapper_show_text_glyphs (cairo_surface_wrapper_t *wrapper, cairo_operator_t op, const cairo_pattern_t *source, + unsigned int source_region_id, const char *utf8, int utf8_len, const cairo_glyph_t *glyphs, diff --git a/gfx/cairo/cairo/src/cairo-surface-wrapper.c b/gfx/cairo/cairo/src/cairo-surface-wrapper.c index 7fb417a202..29c19c5a5f 100644 --- a/gfx/cairo/cairo/src/cairo-surface-wrapper.c +++ b/gfx/cairo/cairo/src/cairo-surface-wrapper.c @@ -1,3 +1,4 @@ +/* -*- 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 @@ -47,12 +48,18 @@ static void _copy_transformed_pattern (cairo_pattern_t *pattern, const cairo_pattern_t *original, - const cairo_matrix_t *ctm_inverse) + const cairo_matrix_t *ctm_inverse, + unsigned int region_id) { _cairo_pattern_init_static_copy (pattern, original); if (! _cairo_matrix_is_identity (ctm_inverse)) _cairo_pattern_transform (pattern, ctm_inverse); + + if (pattern->type == CAIRO_PATTERN_TYPE_SURFACE) { + cairo_surface_pattern_t *surface_pattern = (cairo_surface_pattern_t *) pattern; + surface_pattern->region_array_id = region_id; + } } cairo_status_t @@ -129,9 +136,10 @@ _cairo_surface_wrapper_get_clip (cairo_surface_wrapper_t *wrapper, cairo_status_t _cairo_surface_wrapper_paint (cairo_surface_wrapper_t *wrapper, - cairo_operator_t op, - const cairo_pattern_t *source, - const cairo_clip_t *clip) + cairo_operator_t op, + const cairo_pattern_t *source, + unsigned int source_region_id, + const cairo_clip_t *clip) { cairo_status_t status; cairo_clip_t *dev_clip; @@ -144,7 +152,7 @@ _cairo_surface_wrapper_paint (cairo_surface_wrapper_t *wrapper, if (_cairo_clip_is_all_clipped (dev_clip)) return CAIRO_INT_STATUS_NOTHING_TO_DO; - if (wrapper->needs_transform) { + if (wrapper->needs_transform || source_region_id != 0) { cairo_matrix_t m; _cairo_surface_wrapper_get_transform (wrapper, &m); @@ -152,7 +160,7 @@ _cairo_surface_wrapper_paint (cairo_surface_wrapper_t *wrapper, status = cairo_matrix_invert (&m); assert (status == CAIRO_STATUS_SUCCESS); - _copy_transformed_pattern (&source_copy.base, source, &m); + _copy_transformed_pattern (&source_copy.base, source, &m, source_region_id); source = &source_copy.base; } @@ -162,13 +170,14 @@ _cairo_surface_wrapper_paint (cairo_surface_wrapper_t *wrapper, return status; } - cairo_status_t _cairo_surface_wrapper_mask (cairo_surface_wrapper_t *wrapper, - cairo_operator_t op, - const cairo_pattern_t *source, - const cairo_pattern_t *mask, - const cairo_clip_t *clip) + cairo_operator_t op, + const cairo_pattern_t *source, + unsigned int source_region_id, + const cairo_pattern_t *mask, + unsigned int mask_region_id, + const cairo_clip_t *clip) { cairo_status_t status; cairo_clip_t *dev_clip; @@ -182,7 +191,7 @@ _cairo_surface_wrapper_mask (cairo_surface_wrapper_t *wrapper, if (_cairo_clip_is_all_clipped (dev_clip)) return CAIRO_INT_STATUS_NOTHING_TO_DO; - if (wrapper->needs_transform) { + if (wrapper->needs_transform || source_region_id != 0 || mask_region_id != 0) { cairo_matrix_t m; _cairo_surface_wrapper_get_transform (wrapper, &m); @@ -190,10 +199,10 @@ _cairo_surface_wrapper_mask (cairo_surface_wrapper_t *wrapper, status = cairo_matrix_invert (&m); assert (status == CAIRO_STATUS_SUCCESS); - _copy_transformed_pattern (&source_copy.base, source, &m); + _copy_transformed_pattern (&source_copy.base, source, &m, source_region_id); source = &source_copy.base; - _copy_transformed_pattern (&mask_copy.base, mask, &m); + _copy_transformed_pattern (&mask_copy.base, mask, &m, mask_region_id); mask = &mask_copy.base; } @@ -204,16 +213,17 @@ _cairo_surface_wrapper_mask (cairo_surface_wrapper_t *wrapper, } cairo_status_t -_cairo_surface_wrapper_stroke (cairo_surface_wrapper_t *wrapper, - cairo_operator_t op, - const cairo_pattern_t *source, - const cairo_path_fixed_t *path, - const cairo_stroke_style_t *stroke_style, - const cairo_matrix_t *ctm, - const cairo_matrix_t *ctm_inverse, - double tolerance, - cairo_antialias_t antialias, - const cairo_clip_t *clip) +_cairo_surface_wrapper_stroke (cairo_surface_wrapper_t *wrapper, + cairo_operator_t op, + const cairo_pattern_t *source, + unsigned int source_region_id, + const cairo_path_fixed_t *path, + const cairo_stroke_style_t *stroke_style, + const cairo_matrix_t *ctm, + const cairo_matrix_t *ctm_inverse, + double tolerance, + cairo_antialias_t antialias, + const cairo_clip_t *clip) { cairo_status_t status; cairo_path_fixed_t path_copy, *dev_path = (cairo_path_fixed_t *) path; @@ -229,7 +239,7 @@ _cairo_surface_wrapper_stroke (cairo_surface_wrapper_t *wrapper, if (_cairo_clip_is_all_clipped (dev_clip)) return CAIRO_INT_STATUS_NOTHING_TO_DO; - if (wrapper->needs_transform) { + if (wrapper->needs_transform || source_region_id != 0) { cairo_matrix_t m; _cairo_surface_wrapper_get_transform (wrapper, &m); @@ -248,7 +258,7 @@ _cairo_surface_wrapper_stroke (cairo_surface_wrapper_t *wrapper, cairo_matrix_multiply (&dev_ctm_inverse, &m, &dev_ctm_inverse); - _copy_transformed_pattern (&source_copy.base, source, &m); + _copy_transformed_pattern (&source_copy.base, source, &m, source_region_id); source = &source_copy.base; } @@ -266,21 +276,23 @@ _cairo_surface_wrapper_stroke (cairo_surface_wrapper_t *wrapper, } cairo_status_t -_cairo_surface_wrapper_fill_stroke (cairo_surface_wrapper_t *wrapper, - cairo_operator_t fill_op, - const cairo_pattern_t *fill_source, - cairo_fill_rule_t fill_rule, - double fill_tolerance, - cairo_antialias_t fill_antialias, - const cairo_path_fixed_t*path, - cairo_operator_t stroke_op, - const cairo_pattern_t *stroke_source, - const cairo_stroke_style_t *stroke_style, - const cairo_matrix_t *stroke_ctm, - const cairo_matrix_t *stroke_ctm_inverse, - double stroke_tolerance, - cairo_antialias_t stroke_antialias, - const cairo_clip_t *clip) +_cairo_surface_wrapper_fill_stroke (cairo_surface_wrapper_t *wrapper, + cairo_operator_t fill_op, + const cairo_pattern_t *fill_source, + unsigned int fill_region_id, + cairo_fill_rule_t fill_rule, + double fill_tolerance, + cairo_antialias_t fill_antialias, + const cairo_path_fixed_t *path, + cairo_operator_t stroke_op, + const cairo_pattern_t *stroke_source, + unsigned int stroke_region_id, + const cairo_stroke_style_t *stroke_style, + const cairo_matrix_t *stroke_ctm, + const cairo_matrix_t *stroke_ctm_inverse, + double stroke_tolerance, + cairo_antialias_t stroke_antialias, + const cairo_clip_t *clip) { cairo_status_t status; cairo_path_fixed_t path_copy, *dev_path = (cairo_path_fixed_t *)path; @@ -297,7 +309,7 @@ _cairo_surface_wrapper_fill_stroke (cairo_surface_wrapper_t *wrapper, if (_cairo_clip_is_all_clipped (dev_clip)) return CAIRO_INT_STATUS_NOTHING_TO_DO; - if (wrapper->needs_transform) { + if (wrapper->needs_transform || fill_region_id != 0 || stroke_region_id != 0) { cairo_matrix_t m; _cairo_surface_wrapper_get_transform (wrapper, &m); @@ -316,10 +328,10 @@ _cairo_surface_wrapper_fill_stroke (cairo_surface_wrapper_t *wrapper, cairo_matrix_multiply (&dev_ctm_inverse, &m, &dev_ctm_inverse); - _copy_transformed_pattern (&stroke_source_copy.base, stroke_source, &m); + _copy_transformed_pattern (&stroke_source_copy.base, stroke_source, &m, fill_region_id); stroke_source = &stroke_source_copy.base; - _copy_transformed_pattern (&fill_source_copy.base, fill_source, &m); + _copy_transformed_pattern (&fill_source_copy.base, fill_source, &m, stroke_region_id); fill_source = &fill_source_copy.base; } @@ -341,14 +353,15 @@ _cairo_surface_wrapper_fill_stroke (cairo_surface_wrapper_t *wrapper, } cairo_status_t -_cairo_surface_wrapper_fill (cairo_surface_wrapper_t *wrapper, - cairo_operator_t op, - const cairo_pattern_t *source, - const cairo_path_fixed_t *path, - cairo_fill_rule_t fill_rule, - double tolerance, - cairo_antialias_t antialias, - const cairo_clip_t *clip) +_cairo_surface_wrapper_fill (cairo_surface_wrapper_t *wrapper, + cairo_operator_t op, + const cairo_pattern_t *source, + unsigned int source_region_id, + const cairo_path_fixed_t *path, + cairo_fill_rule_t fill_rule, + double tolerance, + cairo_antialias_t antialias, + const cairo_clip_t *clip) { cairo_status_t status; cairo_path_fixed_t path_copy, *dev_path = (cairo_path_fixed_t *) path; @@ -362,7 +375,7 @@ _cairo_surface_wrapper_fill (cairo_surface_wrapper_t *wrapper, if (_cairo_clip_is_all_clipped (dev_clip)) return CAIRO_INT_STATUS_NOTHING_TO_DO; - if (wrapper->needs_transform) { + if (wrapper->needs_transform || source_region_id != 0) { cairo_matrix_t m; _cairo_surface_wrapper_get_transform (wrapper, &m); @@ -377,7 +390,7 @@ _cairo_surface_wrapper_fill (cairo_surface_wrapper_t *wrapper, status = cairo_matrix_invert (&m); assert (status == CAIRO_STATUS_SUCCESS); - _copy_transformed_pattern (&source_copy.base, source, &m); + _copy_transformed_pattern (&source_copy.base, source, &m, source_region_id); source = &source_copy.base; } @@ -394,9 +407,10 @@ _cairo_surface_wrapper_fill (cairo_surface_wrapper_t *wrapper, } cairo_status_t -_cairo_surface_wrapper_show_text_glyphs (cairo_surface_wrapper_t *wrapper, +_cairo_surface_wrapper_show_text_glyphs (cairo_surface_wrapper_t *wrapper, cairo_operator_t op, const cairo_pattern_t *source, + unsigned int source_region_id, const char *utf8, int utf8_len, const cairo_glyph_t *glyphs, @@ -425,7 +439,7 @@ _cairo_surface_wrapper_show_text_glyphs (cairo_surface_wrapper_t *wrapper, cairo_surface_get_font_options (wrapper->target, &options); cairo_font_options_merge (&options, &scaled_font->options); - if (wrapper->needs_transform) { + if (wrapper->needs_transform || source_region_id != 0) { cairo_matrix_t m; int i; @@ -460,7 +474,7 @@ _cairo_surface_wrapper_show_text_glyphs (cairo_surface_wrapper_t *wrapper, status = cairo_matrix_invert (&m); assert (status == CAIRO_STATUS_SUCCESS); - _copy_transformed_pattern (&source_copy.base, source, &m); + _copy_transformed_pattern (&source_copy.base, source, &m, source_region_id); source = &source_copy.base; } else { if (! cairo_font_options_equal (&options, &scaled_font->options)) { @@ -622,6 +636,8 @@ _cairo_surface_wrapper_init (cairo_surface_wrapper_t *wrapper, wrapper->has_extents = FALSE; wrapper->extents.x = wrapper->extents.y = 0; wrapper->clip = NULL; + wrapper->source_region_id = 0; + wrapper->mask_region_id = 0; wrapper->needs_transform = FALSE; if (target) { diff --git a/gfx/cairo/cairo/src/cairo-surface.c b/gfx/cairo/cairo/src/cairo-surface.c index 32a9e825cd..494aa37365 100644 --- a/gfx/cairo/cairo/src/cairo-surface.c +++ b/gfx/cairo/cairo/src/cairo-surface.c @@ -49,7 +49,6 @@ #include "cairo-recording-surface-private.h" #include "cairo-region-private.h" #include "cairo-surface-inline.h" -#include "cairo-tee-surface-private.h" /** * SECTION:cairo-surface @@ -129,13 +128,20 @@ const cairo_surface_t name = { \ NULL, /* snapshot_detach */ \ { NULL, NULL }, /* snapshots */ \ { NULL, NULL }, /* snapshot */ \ - { CAIRO_ANTIALIAS_DEFAULT, /* antialias */ \ + { /* font options begin */\ + CAIRO_ANTIALIAS_DEFAULT, /* antialias */ \ CAIRO_SUBPIXEL_ORDER_DEFAULT, /* subpixel_order */ \ CAIRO_LCD_FILTER_DEFAULT, /* lcd_filter */ \ CAIRO_HINT_STYLE_DEFAULT, /* hint_style */ \ CAIRO_HINT_METRICS_DEFAULT, /* hint_metrics */ \ - CAIRO_ROUND_GLYPH_POS_DEFAULT /* round_glyph_positions */ \ - } /* font_options */ \ + CAIRO_ROUND_GLYPH_POS_DEFAULT, /* round_glyph_positions */ \ + NULL, /* variations */ \ + CAIRO_COLOR_MODE_DEFAULT, /* color mode */ \ + CAIRO_COLOR_PALETTE_DEFAULT, /* color palette */ \ + NULL, 0, /* custom palette */ \ + }, /* font_options end */ \ + NULL, /* foreground_source */ \ + FALSE, /* foreground_used */ \ } /* XXX error object! */ @@ -260,7 +266,6 @@ cairo_surface_status (cairo_surface_t *surface) { return surface->status; } -slim_hidden_def (cairo_surface_status); static unsigned int _cairo_surface_allocate_unique_id (void) @@ -441,6 +446,9 @@ _cairo_surface_init (cairo_surface_t *surface, surface->snapshot_of = NULL; surface->has_font_options = FALSE; + + surface->foreground_source = NULL; + surface->foreground_used = FALSE; } static void @@ -452,6 +460,7 @@ _cairo_surface_copy_similar_properties (cairo_surface_t *surface, cairo_surface_get_font_options (other, &options); _cairo_surface_set_font_options (surface, &options); + _cairo_font_options_fini (&options); } surface->permit_subpixel_antialiasing = other->permit_subpixel_antialiasing; @@ -605,7 +614,6 @@ cairo_surface_create_similar_image (cairo_surface_t *other, return image; } -slim_hidden_def (cairo_surface_create_similar_image); /** * _cairo_surface_map_to_image: @@ -937,7 +945,6 @@ cairo_surface_reference (cairo_surface_t *surface) return surface; } -slim_hidden_def (cairo_surface_reference); /** * cairo_surface_destroy: @@ -980,9 +987,15 @@ cairo_surface_destroy (cairo_surface_t *surface) _cairo_user_data_array_fini (&surface->user_data); _cairo_user_data_array_fini (&surface->mime_data); + if (surface->foreground_source) + cairo_pattern_destroy (surface->foreground_source); + if (surface->owns_device) cairo_device_destroy (surface->device); + if (surface->has_font_options) + _cairo_font_options_fini (&surface->font_options); + assert (surface->snapshot_of == NULL); assert (! _cairo_surface_has_snapshots (surface)); /* paranoid check that nobody took a reference whilst finishing */ @@ -990,7 +1003,6 @@ cairo_surface_destroy (cairo_surface_t *surface) free (surface); } -slim_hidden_def(cairo_surface_destroy); /** * cairo_surface_get_reference_count: @@ -1084,7 +1096,6 @@ cairo_surface_finish (cairo_surface_t *surface) cairo_surface_destroy (surface); } -slim_hidden_def (cairo_surface_finish); /** * _cairo_surface_release_device_reference: @@ -1212,7 +1223,6 @@ cairo_surface_get_mime_data (cairo_surface_t *surface, } } } -slim_hidden_def (cairo_surface_get_mime_data); static void _cairo_mime_data_destroy (void *ptr) @@ -1469,7 +1479,6 @@ cairo_surface_set_mime_data (cairo_surface_t *surface, return CAIRO_STATUS_SUCCESS; } -slim_hidden_def (cairo_surface_set_mime_data); /** * cairo_surface_supports_mime_type: @@ -1509,7 +1518,6 @@ cairo_surface_supports_mime_type (cairo_surface_t *surface, return FALSE; } -slim_hidden_def (cairo_surface_supports_mime_type); static void _cairo_mime_data_reference (const void *key, void *elt, void *closure) @@ -1621,7 +1629,6 @@ cairo_surface_get_font_options (cairo_surface_t *surface, _cairo_font_options_init_copy (options, &surface->font_options); } -slim_hidden_def (cairo_surface_get_font_options); /** * cairo_surface_set_subpixel_antialiasing: @@ -1708,7 +1715,6 @@ cairo_surface_flush (cairo_surface_t *surface) if (unlikely (status)) _cairo_surface_set_error (surface, status); } -slim_hidden_def (cairo_surface_flush); /** * cairo_surface_mark_dirty: @@ -1737,7 +1743,6 @@ cairo_surface_mark_dirty (cairo_surface_t *surface) extents.x, extents.y, extents.width, extents.height); } -slim_hidden_def (cairo_surface_mark_dirty); /** * cairo_surface_mark_dirty_rectangle: @@ -1811,7 +1816,6 @@ 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: @@ -1823,7 +1827,7 @@ slim_hidden_def (cairo_surface_mark_dirty_rectangle); * by the CTM when drawing to @surface. One common use for this is to * render to very high resolution display devices at a scale factor, so * that code that assumes 1 pixel will be a certain size will still work. - * Setting a transformation via cairo_translate() isn't + * Setting a transformation via cairo_scale() isn't * sufficient to do this, since functions like * cairo_device_to_user() will expose the hidden scale. * @@ -1867,7 +1871,6 @@ cairo_surface_set_device_scale (cairo_surface_t *surface, _cairo_observers_notify (&surface->device_transform_observers, surface); } -slim_hidden_def (cairo_surface_set_device_scale); /** * cairo_surface_get_device_scale: @@ -1875,7 +1878,7 @@ slim_hidden_def (cairo_surface_set_device_scale); * @x_scale: the scale in the X direction, in device units * @y_scale: the scale in the Y direction, in device units * - * This function returns the previous device offset set by + * This function returns the previous device scale set by * cairo_surface_set_device_scale(). * * Since: 1.14 @@ -1890,7 +1893,6 @@ cairo_surface_get_device_scale (cairo_surface_t *surface, if (y_scale) *y_scale = surface->device_transform.yy; } -slim_hidden_def (cairo_surface_get_device_scale); /** * cairo_surface_set_device_offset: @@ -1945,7 +1947,6 @@ cairo_surface_set_device_offset (cairo_surface_t *surface, _cairo_observers_notify (&surface->device_transform_observers, surface); } -slim_hidden_def (cairo_surface_set_device_offset); /** * cairo_surface_get_device_offset: @@ -1968,7 +1969,6 @@ cairo_surface_get_device_offset (cairo_surface_t *surface, if (y_offset) *y_offset = surface->device_transform.y0; } -slim_hidden_def (cairo_surface_get_device_offset); /** * cairo_surface_set_fallback_resolution: @@ -2037,7 +2037,6 @@ 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_surface_get_fallback_resolution: @@ -2245,6 +2244,11 @@ _cairo_surface_paint (cairo_surface_t *surface, if (unlikely (status)) return status; + if (source->is_foreground_marker && surface->foreground_source) { + source = surface->foreground_source; + surface->foreground_used = TRUE; + } + status = surface->backend->paint (surface, op, source, clip); is_clear = op == CAIRO_OPERATOR_CLEAR && clip == NULL; if (status != CAIRO_INT_STATUS_NOTHING_TO_DO || is_clear) { @@ -2295,6 +2299,11 @@ _cairo_surface_mask (cairo_surface_t *surface, if (unlikely (status)) return status; + if (source->is_foreground_marker && surface->foreground_source) { + source = surface->foreground_source; + surface->foreground_used = TRUE; + } + status = surface->backend->mask (surface, op, source, mask, clip); if (status != CAIRO_INT_STATUS_NOTHING_TO_DO) { surface->is_clear = FALSE; @@ -2351,6 +2360,16 @@ _cairo_surface_fill_stroke (cairo_surface_t *surface, if (unlikely (status)) return status; + if (fill_source->is_foreground_marker && surface->foreground_source) { + fill_source = surface->foreground_source; + surface->foreground_used = TRUE; + } + + if (stroke_source->is_foreground_marker && surface->foreground_source) { + stroke_source = surface->foreground_source; + surface->foreground_used = TRUE; + } + if (surface->backend->fill_stroke) { cairo_matrix_t dev_ctm = *stroke_ctm; cairo_matrix_t dev_ctm_inverse = *stroke_ctm_inverse; @@ -2425,6 +2444,11 @@ _cairo_surface_stroke (cairo_surface_t *surface, if (unlikely (status)) return status; + if (source->is_foreground_marker && surface->foreground_source) { + source = surface->foreground_source; + surface->foreground_used = TRUE; + } + status = surface->backend->stroke (surface, op, source, path, stroke_style, ctm, ctm_inverse, @@ -2470,6 +2494,11 @@ _cairo_surface_fill (cairo_surface_t *surface, if (unlikely (status)) return status; + if (source->is_foreground_marker && surface->foreground_source) { + source = surface->foreground_source; + surface->foreground_used = TRUE; + } + status = surface->backend->fill (surface, op, source, path, fill_rule, tolerance, antialias, @@ -2515,7 +2544,6 @@ cairo_surface_copy_page (cairo_surface_t *surface) _cairo_surface_set_error (surface, surface->backend->copy_page (surface)); } -slim_hidden_def (cairo_surface_copy_page); /** * cairo_surface_show_page: @@ -2554,7 +2582,6 @@ cairo_surface_show_page (cairo_surface_t *surface) _cairo_surface_set_error (surface, surface->backend->show_page (surface)); } -slim_hidden_def (cairo_surface_show_page); /** * _cairo_surface_get_extents: @@ -2645,12 +2672,12 @@ cairo_surface_has_show_text_glyphs (cairo_surface_t *surface) else return surface->backend->show_text_glyphs != NULL; } -slim_hidden_def (cairo_surface_has_show_text_glyphs); #define GLYPH_CACHE_SIZE 64 static inline cairo_int_status_t ensure_scaled_glyph (cairo_scaled_font_t *scaled_font, + cairo_color_t *foreground_color, cairo_scaled_glyph_t **glyph_cache, cairo_glyph_t *glyph, cairo_scaled_glyph_t **scaled_glyph) @@ -2663,8 +2690,17 @@ ensure_scaled_glyph (cairo_scaled_font_t *scaled_font, if (*scaled_glyph == NULL || _cairo_scaled_glyph_index (*scaled_glyph) != glyph->index) { status = _cairo_scaled_glyph_lookup (scaled_font, glyph->index, - CAIRO_SCALED_GLYPH_INFO_SURFACE, + CAIRO_SCALED_GLYPH_INFO_COLOR_SURFACE, + foreground_color, scaled_glyph); + if (status == CAIRO_INT_STATUS_UNSUPPORTED) { + /* If the color surface not available, ensure scaled_glyph is not NULL. */ + status = _cairo_scaled_glyph_lookup (scaled_font, + glyph->index, + CAIRO_SCALED_GLYPH_INFO_SURFACE, + NULL, /* foreground color */ + scaled_glyph); + } if (unlikely (status)) status = _cairo_scaled_font_set_error (scaled_font, status); @@ -2680,31 +2716,39 @@ composite_one_color_glyph (cairo_surface_t *surface, const cairo_pattern_t *source, const cairo_clip_t *clip, cairo_glyph_t *glyph, - cairo_scaled_glyph_t *scaled_glyph) + cairo_scaled_glyph_t *scaled_glyph, + double x_scale, + double y_scale) { cairo_int_status_t status; cairo_image_surface_t *glyph_surface; cairo_pattern_t *pattern; cairo_matrix_t matrix; + int has_color; status = CAIRO_INT_STATUS_SUCCESS; - glyph_surface = scaled_glyph->color_surface; + has_color = scaled_glyph->has_info & CAIRO_SCALED_GLYPH_INFO_COLOR_SURFACE; + if (has_color) + glyph_surface = scaled_glyph->color_surface; + else + glyph_surface = scaled_glyph->surface; if (glyph_surface->width && glyph_surface->height) { int x, y; /* round glyph locations to the nearest pixels */ /* XXX: FRAGILE: We're ignoring device_transform scaling here. A bug? */ - x = _cairo_lround (glyph->x - glyph_surface->base.device_transform.x0); - y = _cairo_lround (glyph->y - glyph_surface->base.device_transform.y0); + x = _cairo_lround (glyph->x * x_scale - glyph_surface->base.device_transform.x0); + y = _cairo_lround (glyph->y * y_scale - glyph_surface->base.device_transform.y0); pattern = cairo_pattern_create_for_surface ((cairo_surface_t *)glyph_surface); cairo_matrix_init_translate (&matrix, - x, - y); + cairo_matrix_scale (&matrix, x_scale, y_scale); cairo_pattern_set_matrix (pattern, &matrix); - if (op == CAIRO_OPERATOR_SOURCE || op == CAIRO_OPERATOR_CLEAR) - status = surface->backend->mask (surface, op, pattern, pattern, clip); - else - status = surface->backend->paint (surface, op, pattern, clip); + if (op == CAIRO_OPERATOR_SOURCE || op == CAIRO_OPERATOR_CLEAR || !has_color) + status = _cairo_surface_mask (surface, op, pattern, pattern, clip); + else + status = _cairo_surface_paint (surface, op, pattern, clip); cairo_pattern_destroy (pattern); } @@ -2735,6 +2779,32 @@ composite_color_glyphs (cairo_surface_t *surface, int byte_pos = 0; int gp; cairo_scaled_glyph_t *glyph_cache[GLYPH_CACHE_SIZE]; + cairo_color_t *foreground_color = NULL; + double x_scale = 1.0; + double y_scale = 1.0; + + if (surface->is_vector) { + cairo_font_face_t *font_face; + cairo_matrix_t font_matrix; + cairo_matrix_t ctm; + cairo_font_options_t font_options; + + x_scale = surface->x_fallback_resolution / surface->x_resolution; + y_scale = surface->y_fallback_resolution / surface->y_resolution; + font_face = cairo_scaled_font_get_font_face (scaled_font); + cairo_scaled_font_get_font_matrix (scaled_font, &font_matrix); + cairo_scaled_font_get_ctm (scaled_font, &ctm); + _cairo_font_options_init_default (&font_options); + cairo_scaled_font_get_font_options (scaled_font, &font_options); + cairo_matrix_scale (&ctm, x_scale, y_scale); + scaled_font = cairo_scaled_font_create (font_face, + &font_matrix, + &ctm, + &font_options); + } + + if (source->type == CAIRO_PATTERN_TYPE_SOLID) + foreground_color = &((cairo_solid_pattern_t *) source)->color; memset (glyph_cache, 0, sizeof (glyph_cache)); @@ -2748,7 +2818,7 @@ composite_color_glyphs (cairo_surface_t *surface, glyph_pos = *num_glyphs - 1; for (i = 0; i < *num_clusters; i++) { - cairo_bool_t skip_cluster = FALSE; + cairo_bool_t skip_cluster = TRUE; for (j = 0; j < clusters[i].num_glyphs; j++) { if (cluster_flags & CAIRO_TEXT_CLUSTER_FLAG_BACKWARD) @@ -2756,15 +2826,27 @@ composite_color_glyphs (cairo_surface_t *surface, else gp = glyph_pos + j; - status = ensure_scaled_glyph (scaled_font, glyph_cache, + status = ensure_scaled_glyph (scaled_font, foreground_color, glyph_cache, &glyphs[gp], &scaled_glyph); if (unlikely (status)) goto UNLOCK; - if ((scaled_glyph->has_info & CAIRO_SCALED_GLYPH_INFO_COLOR_SURFACE) == 0) { - skip_cluster = TRUE; - break; - } + if ((scaled_glyph->has_info & CAIRO_SCALED_GLYPH_INFO_COLOR_SURFACE) != 0) { + cairo_bool_t supports_color_glyph = FALSE; + + if (surface->backend->supports_color_glyph) { + _cairo_scaled_font_thaw_cache (scaled_font); + supports_color_glyph = _cairo_surface_supports_color_glyph (surface, scaled_font, glyphs[gp].index); + + memset (glyph_cache, 0, sizeof (glyph_cache)); + _cairo_scaled_font_freeze_cache (scaled_font); + } + + if (!supports_color_glyph) { + skip_cluster = FALSE; + break; + } + } } if (skip_cluster) { @@ -2787,13 +2869,14 @@ composite_color_glyphs (cairo_surface_t *surface, else gp = glyph_pos + j; - status = ensure_scaled_glyph (scaled_font, glyph_cache, + status = ensure_scaled_glyph (scaled_font, foreground_color, glyph_cache, &glyphs[gp], &scaled_glyph); if (unlikely (status)) goto UNLOCK; status = composite_one_color_glyph (surface, op, source, clip, - &glyphs[gp], scaled_glyph); + &glyphs[gp], scaled_glyph, + x_scale, y_scale); if (unlikely (status && status != CAIRO_INT_STATUS_NOTHING_TO_DO)) goto UNLOCK; } @@ -2806,8 +2889,10 @@ composite_color_glyphs (cairo_surface_t *surface, byte_pos += clusters[i].num_bytes; } - if (cluster_flags & CAIRO_TEXT_CLUSTER_FLAG_BACKWARD) + if (cluster_flags & CAIRO_TEXT_CLUSTER_FLAG_BACKWARD) { memmove (utf8, utf8 + *utf8_len - remaining_bytes, remaining_bytes); + memmove (glyphs, glyphs + (*num_glyphs - remaining_glyphs), sizeof (cairo_glyph_t) * remaining_glyphs); + } *utf8_len = remaining_bytes; *num_glyphs = remaining_glyphs; @@ -2816,7 +2901,7 @@ composite_color_glyphs (cairo_surface_t *surface, } else { for (glyph_pos = 0; glyph_pos < *num_glyphs; glyph_pos++) { - status = ensure_scaled_glyph (scaled_font, glyph_cache, + status = ensure_scaled_glyph (scaled_font, foreground_color, glyph_cache, &glyphs[glyph_pos], &scaled_glyph); if (unlikely (status)) goto UNLOCK; @@ -2827,7 +2912,8 @@ composite_color_glyphs (cairo_surface_t *surface, } status = composite_one_color_glyph (surface, op, source, clip, - &glyphs[glyph_pos], scaled_glyph); + &glyphs[glyph_pos], scaled_glyph, + x_scale, y_scale); if (unlikely (status && status != CAIRO_INT_STATUS_NOTHING_TO_DO)) goto UNLOCK; } @@ -2838,6 +2924,9 @@ composite_color_glyphs (cairo_surface_t *surface, UNLOCK: _cairo_scaled_font_thaw_cache (scaled_font); + if (surface->is_vector) + cairo_scaled_font_destroy (scaled_font); + return status; } @@ -2868,7 +2957,7 @@ _cairo_surface_show_text_glyphs (cairo_surface_t *surface, int num_clusters, cairo_text_cluster_flags_t cluster_flags, cairo_scaled_font_t *scaled_font, - const cairo_clip_t *clip) + const cairo_clip_t *clip) { cairo_int_status_t status; char *utf8_copy = NULL; @@ -2889,16 +2978,27 @@ _cairo_surface_show_text_glyphs (cairo_surface_t *surface, if (unlikely (status)) return status; - if (nothing_to_do (surface, op, source)) - return CAIRO_STATUS_SUCCESS; + status = cairo_scaled_font_status (scaled_font); + if (unlikely (status)) + return status; + + if (!(_cairo_scaled_font_has_color_glyphs (scaled_font) && + scaled_font->options.color_mode != CAIRO_COLOR_MODE_NO_COLOR)) + { + if (nothing_to_do (surface, op, source)) + return CAIRO_STATUS_SUCCESS; + } status = _cairo_surface_begin_modification (surface); if (unlikely (status)) return status; - status = CAIRO_INT_STATUS_UNSUPPORTED; + if (source->is_foreground_marker && surface->foreground_source) + source = surface->foreground_source; - if (_cairo_scaled_font_has_color_glyphs (scaled_font)) { + if (_cairo_scaled_font_has_color_glyphs (scaled_font) && + scaled_font->options.color_mode != CAIRO_COLOR_MODE_NO_COLOR) + { utf8_copy = malloc (sizeof (char) * utf8_len); memcpy (utf8_copy, utf8, sizeof (char) * utf8_len); utf8 = utf8_copy; @@ -2916,13 +3016,14 @@ _cairo_surface_show_text_glyphs (cairo_surface_t *surface, if (num_glyphs == 0) goto DONE; - } - else + } else { utf8_copy = NULL; + } /* The logic here is duplicated in _cairo_analysis_surface show_glyphs and * show_text_glyphs. Keep in synch. */ if (clusters) { + status = CAIRO_INT_STATUS_UNSUPPORTED; /* A real show_text_glyphs call. Try show_text_glyphs backend * method first */ if (surface->backend->show_text_glyphs != NULL) { @@ -3005,6 +3106,16 @@ _cairo_surface_tag (cairo_surface_t *surface, return _cairo_surface_set_error (surface, status); } +cairo_bool_t +_cairo_surface_supports_color_glyph (cairo_surface_t *surface, + cairo_scaled_font_t *scaled_font, + unsigned long glyph_index) +{ + if (surface->backend->supports_color_glyph != NULL) + return surface->backend->supports_color_glyph (surface, scaled_font, glyph_index); + + return FALSE; +} /** * _cairo_surface_set_resolution: @@ -3102,7 +3213,9 @@ _cairo_surface_create_in_error (cairo_status_t status) case CAIRO_STATUS_PNG_ERROR: case CAIRO_STATUS_FREETYPE_ERROR: case CAIRO_STATUS_WIN32_GDI_ERROR: + case CAIRO_INT_STATUS_DWRITE_ERROR: case CAIRO_STATUS_TAG_ERROR: + case CAIRO_STATUS_SVG_FONT_ERROR: default: _cairo_error_throw (CAIRO_STATUS_NO_MEMORY); return (cairo_surface_t *) &_cairo_surface_nil; diff --git a/gfx/cairo/cairo/src/cairo-svg-glyph-render.c b/gfx/cairo/cairo/src/cairo-svg-glyph-render.c new file mode 100644 index 0000000000..cac8a7a73d --- /dev/null +++ b/gfx/cairo/cairo/src/cairo-svg-glyph-render.c @@ -0,0 +1,3243 @@ +/* -*- Mode: c; c-basic-offset: 4; indent-tabs-mode: t; tab-width: 8; -*- */ +/* cairo - a vector graphics library with display and print output + * + * Copyright © 2022 Adrian Johnson + * + * This library is free software; you can redistribute it and/or + * modify it either under the terms of the GNU Lesser General Public + * License version 2.1 as published by the Free Software Foundation + * (the "LGPL") or, at your option, under the terms of the Mozilla + * Public License Version 1.1 (the "MPL"). If you do not alter this + * notice, a recipient may use your version of this file under either + * the MPL or the LGPL. + * + * You should have received a copy of the LGPL along with this library + * in the file COPYING-LGPL-2.1; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Suite 500, Boston, MA 02110-1335, USA + * You should have received a copy of the MPL along with this library + * in the file COPYING-MPL-1.1 + * + * The contents of this file are subject to the Mozilla Public License + * Version 1.1 (the "License"); you may not use this file except in + * compliance with the License. You may obtain a copy of the License at + * http://www.mozilla.org/MPL/ + * + * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY + * OF ANY KIND, either express or implied. See the LGPL or the MPL for + * the specific language governing rights and limitations. + * + * The Original Code is the cairo graphics library. + * + * The Initial Developer of the Original Code is Adrian Johnson. + * + * Contributor(s): + * Adrian Johnson <ajohnson@redneon.com> + */ + +#include "cairoint.h" +#include "cairo-array-private.h" +#include "cairo-ft-private.h" +#include "cairo-pattern-private.h" +#include "cairo-scaled-font-subsets-private.h" + +#include <stdarg.h> +#include <stdio.h> +#include <string.h> + +#if HAVE_FT_SVG_DOCUMENT + +#include <ft2build.h> +#include FT_COLOR_H + +/* #define SVG_RENDER_PRINT_FUNCTIONS 1 */ + +#define WHITE_SPACE_CHARS " \n\r\t\v\f" + +typedef struct { + const char *name; + int red; + int green; + int blue; +} color_name_t; + +/* Must be sorted */ +static color_name_t color_names[] = { + { "aliceblue", 240, 248, 255 }, + { "antiquewhite", 250, 235, 215 }, + { "aqua", 0, 255, 255 }, + { "aquamarine", 127, 255, 212 }, + { "azure", 240, 255, 255 }, + { "beige", 245, 245, 220 }, + { "bisque", 255, 228, 196 }, + { "black", 0, 0, 0 }, + { "blanchedalmond", 255, 235, 205 }, + { "blue", 0, 0, 255 }, + { "blueviolet", 138, 43, 226 }, + { "brown", 165, 42, 42 }, + { "burlywood", 222, 184, 135 }, + { "cadetblue", 95, 158, 160 }, + { "chartreuse", 127, 255, 0 }, + { "chocolate", 210, 105, 30 }, + { "coral", 255, 127, 80 }, + { "cornflowerblue", 100, 149, 237 }, + { "cornsilk", 255, 248, 220 }, + { "crimson", 220, 20, 60 }, + { "cyan", 0, 255, 255 }, + { "darkblue", 0, 0, 139 }, + { "darkcyan", 0, 139, 139 }, + { "darkgoldenrod", 184, 134, 11 }, + { "darkgray", 169, 169, 169 }, + { "darkgreen", 0, 100, 0 }, + { "darkgrey", 169, 169, 169 }, + { "darkkhaki", 189, 183, 107 }, + { "darkmagenta", 139, 0, 139 }, + { "darkolivegreen", 85, 107, 47 }, + { "darkorange", 255, 140, 0 }, + { "darkorchid", 153, 50, 204 }, + { "darkred", 139, 0, 0 }, + { "darksalmon", 233, 150, 122 }, + { "darkseagreen", 143, 188, 143 }, + { "darkslateblue", 72, 61, 139 }, + { "darkslategray", 47, 79, 79 }, + { "darkslategrey", 47, 79, 79 }, + { "darkturquoise", 0, 206, 209 }, + { "darkviolet", 148, 0, 211 }, + { "deeppink", 255, 20, 147 }, + { "deepskyblue", 0, 191, 255 }, + { "dimgray", 105, 105, 105 }, + { "dimgrey", 105, 105, 105 }, + { "dodgerblue", 30, 144, 255 }, + { "firebrick", 178, 34, 34 }, + { "floralwhite", 255, 250, 240 }, + { "forestgreen", 34, 139, 34 }, + { "fuchsia", 255, 0, 255 }, + { "gainsboro", 220, 220, 220 }, + { "ghostwhite", 248, 248, 255 }, + { "gold", 255, 215, 0 }, + { "goldenrod", 218, 165, 32 }, + { "gray", 128, 128, 128 }, + { "green", 0, 128, 0 }, + { "greenyellow", 173, 255, 47 }, + { "grey", 128, 128, 128 }, + { "honeydew", 240, 255, 240 }, + { "hotpink", 255, 105, 180 }, + { "indianred", 205, 92, 92 }, + { "indigo", 75, 0, 130 }, + { "ivory", 255, 255, 240 }, + { "khaki", 240, 230, 140 }, + { "lavender", 230, 230, 250 }, + { "lavenderblush", 255, 240, 245 }, + { "lawngreen", 124, 252, 0 }, + { "lemonchiffon", 255, 250, 205 }, + { "lightblue", 173, 216, 230 }, + { "lightcoral", 240, 128, 128 }, + { "lightcyan", 224, 255, 255 }, + { "lightgoldenrodyellow", 250, 250, 210 }, + { "lightgray", 211, 211, 211 }, + { "lightgreen", 144, 238, 144 }, + { "lightgrey", 211, 211, 211 }, + { "lightpink", 255, 182, 193 }, + { "lightsalmon", 255, 160, 122 }, + { "lightseagreen", 32, 178, 170 }, + { "lightskyblue", 135, 206, 250 }, + { "lightslategray", 119, 136, 153 }, + { "lightslategrey", 119, 136, 153 }, + { "lightsteelblue", 176, 196, 222 }, + { "lightyellow", 255, 255, 224 }, + { "lime", 0, 255, 0 }, + { "limegreen", 50, 205, 50 }, + { "linen", 250, 240, 230 }, + { "magenta", 255, 0, 255 }, + { "maroon", 128, 0, 0 }, + { "mediumaquamarine", 102, 205, 170 }, + { "mediumblue", 0, 0, 205 }, + { "mediumorchid", 186, 85, 211 }, + { "mediumpurple", 147, 112, 219 }, + { "mediumseagreen", 60, 179, 113 }, + { "mediumslateblue", 123, 104, 238 }, + { "mediumspringgreen", 0, 250, 154 }, + { "mediumturquoise", 72, 209, 204 }, + { "mediumvioletred", 199, 21, 133 }, + { "midnightblue", 25, 25, 112 }, + { "mintcream", 245, 255, 250 }, + { "mistyrose", 255, 228, 225 }, + { "moccasin", 255, 228, 181 }, + { "navajowhite", 255, 222, 173 }, + { "navy", 0, 0, 128 }, + { "oldlace", 253, 245, 230 }, + { "olive", 128, 128, 0 }, + { "olivedrab", 107, 142, 35 }, + { "orange", 255, 165, 0 }, + { "orangered", 255, 69, 0 }, + { "orchid", 218, 112, 214 }, + { "palegoldenrod", 238, 232, 170 }, + { "palegreen", 152, 251, 152 }, + { "paleturquoise", 175, 238, 238 }, + { "palevioletred", 219, 112, 147 }, + { "papayawhip", 255, 239, 213 }, + { "peachpuff", 255, 218, 185 }, + { "peru", 205, 133, 63 }, + { "pink", 255, 192, 203 }, + { "plum", 221, 160, 221 }, + { "powderblue", 176, 224, 230 }, + { "purple", 128, 0, 128 }, + { "red", 255, 0, 0 }, + { "rosybrown", 188, 143, 143 }, + { "royalblue", 65, 105, 225 }, + { "saddlebrown", 139, 69, 19 }, + { "salmon", 250, 128, 114 }, + { "sandybrown", 244, 164, 96 }, + { "seagreen", 46, 139, 87 }, + { "seashell", 255, 245, 238 }, + { "sienna", 160, 82, 45 }, + { "silver", 192, 192, 192 }, + { "skyblue", 135, 206, 235 }, + { "slateblue", 106, 90, 205 }, + { "slategray", 112, 128, 144 }, + { "slategrey", 112, 128, 144 }, + { "snow", 255, 250, 250 }, + { "springgreen", 0, 255, 127 }, + { "steelblue", 70, 130, 180 }, + { "tan", 210, 180, 140 }, + { "teal", 0, 128, 128 }, + { "thistle", 216, 191, 216 }, + { "tomato", 255, 99, 71 }, + { "turquoise", 64, 224, 208 }, + { "violet", 238, 130, 238 }, + { "wheat", 245, 222, 179 }, + { "white", 255, 255, 255 }, + { "whitesmoke", 245, 245, 245 }, + { "yellow", 255, 255, 0 }, + { "yellowgreen", 154, 205, 50 } +}; + +typedef struct { + char *name; + char *value; +} svg_attribute_t; + +typedef enum { + CONTAINER_ELEMENT, + EMPTY_ELEMENT, + PROCESSING_INSTRUCTION, + DOCTYPE, + CDATA, + COMMENT +} tag_type_t; + +#define TOP_ELEMENT_TAG "_top" + +typedef struct _cairo_svg_element { + cairo_hash_entry_t base; + tag_type_t type; + char *tag; + char *id; + cairo_array_t attributes; /* svg_attribute_t */ + cairo_array_t children; /* cairo_svg_element_t* */ + cairo_array_t content; /* char */ + cairo_pattern_t *pattern; /* defined if a paint server */ + struct _cairo_svg_element *next; /* next on element stack */ +} cairo_svg_element_t; + +typedef struct _cairo_svg_color { + enum { RGB, FOREGROUND } type; + double red; + double green; + double blue; +} cairo_svg_color_t; + +typedef struct _cairo_svg_paint { + enum { PAINT_COLOR, PAINT_SERVER, PAINT_NONE } type; + cairo_svg_color_t color; + cairo_svg_element_t *paint_server; +} cairo_svg_paint_t; + +typedef enum { + GS_RENDER, + GS_NO_RENDER, + GS_COMPUTE_BBOX, + GS_CLIP +} gs_mode_t; + +typedef struct _cairo_svg_graphics_state { + cairo_svg_paint_t fill; + cairo_svg_paint_t stroke; + cairo_svg_color_t color; + double fill_opacity; + double stroke_opacity; + double opacity; + cairo_fill_rule_t fill_rule; + cairo_fill_rule_t clip_rule; + cairo_path_t *clip_path; + char *dash_array; + double dash_offset; + gs_mode_t mode; + struct { + double x; + double y; + double width; + double height; + } bbox; + struct _cairo_svg_graphics_state *next; +} cairo_svg_graphics_state_t; + +typedef enum { + BUILD_PATTERN_NONE, + BUILD_PATTERN_LINEAR, + BUILD_PATTERN_RADIAL +} build_pattern_t; + +typedef struct _cairo_svg_glyph_render { + cairo_svg_element_t *tree; + cairo_hash_table_t *ids; + cairo_svg_graphics_state_t *graphics_state; + cairo_t *cr; + double units_per_em; + struct { + cairo_svg_element_t *paint_server; + cairo_pattern_t *pattern; + build_pattern_t type; + } build_pattern; + int render_element_tree_depth; + int num_palette_entries; + FT_Color* palette; + + /* Viewport */ + double width; + double height; + cairo_bool_t view_port_set; + + cairo_pattern_t *foreground_marker; + cairo_pattern_t *foreground_source; + cairo_bool_t foreground_source_used; + + int debug; /* 0 = quiet, 1 = errors, 2 = warnings, 3 = info */ +} cairo_svg_glyph_render_t; + + +#define SVG_RENDER_ERROR 1 +#define SVG_RENDER_WARNING 2 +#define SVG_RENDER_INFO 3 + +#define print_error(render, ...) cairo_svg_glyph_render_printf(render, SVG_RENDER_ERROR, ##__VA_ARGS__) +#define print_warning(render, ...) cairo_svg_glyph_render_printf(render, SVG_RENDER_WARNING, ##__VA_ARGS__) +#define print_info(render, ...) cairo_svg_glyph_render_printf(render, SVG_RENDER_INFO, ##__VA_ARGS__) + +static void +cairo_svg_glyph_render_printf (cairo_svg_glyph_render_t *svg_render, + int level, + const char *fmt, ...) CAIRO_PRINTF_FORMAT (3, 4); + +static void +cairo_svg_glyph_render_printf (cairo_svg_glyph_render_t *svg_render, + int level, + const char *fmt, ...) +{ + va_list ap; + + if (svg_render->debug >= level ) { + switch (level) { + case SVG_RENDER_ERROR: + printf("ERROR: "); + break; + case SVG_RENDER_WARNING: + printf("WARNING: "); + break; + } + va_start (ap, fmt); + vprintf (fmt, ap); + va_end (ap); + printf ("\n"); + } +} + +static cairo_bool_t +string_equal (const char *s1, const char *s2) +{ + if (s1 && s2) + return strcmp (s1, s2) == 0; + + if (!s1 && !s2) + return TRUE; + + return FALSE; +} + +static cairo_bool_t +string_match (const char **p, const char *str) +{ + if (*p && strncmp (*p, str, strlen (str)) == 0) { + *p += strlen (str); + return TRUE; + } + return FALSE; +} + +static const char * +skip_space (const char *p) +{ + while (*p && _cairo_isspace (*p)) + p++; + + return p; +} + +/* Skip over character c and and whitespace before or after. Returns + * NULL if c not found. */ +static const char * +skip_char (const char *p, char c) +{ + while (_cairo_isspace (*p)) + p++; + + if (*p != c) + return NULL; + + p++; + + while (_cairo_isspace (*p)) + p++; + + return p; +} + +static int +_color_name_compare (const void *a, const void *b) +{ + const color_name_t *a_color = a; + const color_name_t *b_color = b; + + return strcmp (a_color->name, b_color->name); +} + +static void +init_element_id_key (cairo_svg_element_t *element) +{ + element->base.hash = _cairo_hash_string (element->id); +} + +static cairo_bool_t +_element_id_equal (const void *key_a, const void *key_b) +{ + const cairo_svg_element_t *a = key_a; + const cairo_svg_element_t *b = key_b; + + return string_equal (a->id, b->id); +} + +/* Find element with the "id" attribute matching id. id may have the + * '#' prefix. It will be stripped before searching. + */ +static cairo_svg_element_t * +lookup_element (cairo_svg_glyph_render_t *svg_render, const char *id) +{ + cairo_svg_element_t key; + + if (!id || strlen (id) < 1) + return NULL; + + key.id = (char *)(id[0] == '#' ? id + 1 : id); + init_element_id_key (&key); + return _cairo_hash_table_lookup (svg_render->ids, &key.base); +} + +/* Find element with the "id" attribute matching url where url is of + * the form "url(#id)". + */ +static cairo_svg_element_t * +lookup_url_element (cairo_svg_glyph_render_t *svg_render, const char *url) +{ + const char *p = url; + cairo_svg_element_t *element = NULL; + + if (p && string_match (&p, "url")) { + p = skip_char (p, '('); + if (!p) + return NULL; + + const char *end = strpbrk(p, WHITE_SPACE_CHARS ")"); + if (end) { + char *id = _cairo_strndup (p, end - p); + element = lookup_element (svg_render, id); + free (id); + } + } + return element; +} + +static const char * +get_attribute (const cairo_svg_element_t *element, const char *name) +{ + svg_attribute_t attr; + int num_elems, i; + + num_elems = _cairo_array_num_elements (&element->attributes); + for (i = 0; i < num_elems; i++) { + _cairo_array_copy_element (&element->attributes, i, &attr); + if (string_equal (attr.name, name)) + return attr.value; + } + return NULL; +} + +static const char * +get_href_attribute (const cairo_svg_element_t *element) +{ + svg_attribute_t attr; + int num_elems, i, len; + + /* SVG2 requires the href attribute to be "href". Older versions + * used "xlink:href". I have seen at least one font that used an + * alternative name space eg "ns1:href". To keep things simple we + * search for an attribute named "href" or ending in ":href". + */ + num_elems = _cairo_array_num_elements (&element->attributes); + for (i = 0; i < num_elems; i++) { + _cairo_array_copy_element (&element->attributes, i, &attr); + if (string_equal (attr.name, "href")) + return attr.value; + + len = strlen (attr.name); + if (len > 4 && string_equal (attr.name + len - 5, ":href")) + return attr.value; + } + return NULL; +} + +/* Get a float attribute or float percentage. If attribute is a + * percentage, the returned value is percentage * scale. Does not + * modify value if it returns FALSE. This allows value to be set to a + * default before calling get_float_attribute(), then used without + * checking the return value of this function. + */ +static cairo_bool_t +get_float_or_percent_attribute (const cairo_svg_element_t *element, + const char *name, + double scale, + double *value) +{ + const char *p; + char *end; + double v; + + p = get_attribute (element, name); + if (p) { + v = _cairo_strtod (p, &end); + if (end != p) { + *value = v; + if (*end == '%') + *value *= scale / 100.0; + return TRUE; + } + } + return FALSE; +} + +/* Does not modify value if it returns FALSE. This allows value to be + * set to a default before calling get_float_attribute(), then used + * without checking the return value of this function. + */ +static cairo_bool_t +get_float_attribute (const cairo_svg_element_t *element, const char *name, double *value) +{ + const char *p; + char *end; + double v; + + p = get_attribute (element, name); + if (p) { + v = _cairo_strtod (p, &end); + if (end != p) { + *value = v; + return TRUE; + } + } + return FALSE; +} + +static cairo_fill_rule_t +get_fill_rule_attribute (const cairo_svg_element_t *element, const char *name, cairo_fill_rule_t default_value) +{ + const char *p; + + p = get_attribute (element, name); + if (string_equal (p, "nonzero")) + return CAIRO_FILL_RULE_WINDING; + else if (string_equal (p, "evenodd")) + return CAIRO_FILL_RULE_EVEN_ODD; + else + return default_value; +} + +static void +free_elements (cairo_svg_glyph_render_t *svg_render, + cairo_svg_element_t *element) +{ + int num_elems; + + num_elems = _cairo_array_num_elements (&element->children); + for (int i = 0; i < num_elems; i++) { + cairo_svg_element_t *child; + _cairo_array_copy_element (&element->children, i, &child); + free_elements (svg_render, child); + } + _cairo_array_fini (&element->children); + + num_elems = _cairo_array_num_elements (&element->attributes); + for (int i = 0; i < num_elems; i++) { + svg_attribute_t *attr = _cairo_array_index (&element->attributes, i); + free (attr->name); + free (attr->value); + } + _cairo_array_fini (&element->attributes); + _cairo_array_fini (&element->content); + + free (element->tag); + + if (element->id) { + _cairo_hash_table_remove (svg_render->ids, &element->base); + free (element->id); + } + + if (element->pattern) + cairo_pattern_destroy (element->pattern); + + free (element); +} + +#if SVG_RENDER_PRINT_FUNCTIONS + +static void indent(int level) +{ + for (int i = 1; i < level; i++) + printf(" "); +} + +static void +print_element (cairo_svg_element_t *element, cairo_bool_t recurse, int level) +{ + char *content = strndup (_cairo_array_index_const (&element->content, 0), + _cairo_array_num_elements (&element->content)); + + indent(level); + if (element->type == COMMENT) { + printf("<!--%s-->\n", content); + } else if (element->type == CDATA) { + printf("<![CDATA[%s]]>\n", content); + } else if (element->type == DOCTYPE) { + printf("<!DOCTYPE%s>\n", content); + } else if (element->type == PROCESSING_INSTRUCTION) { + printf("<?%s?>\n", content); + } else { + cairo_bool_t top_element = string_equal (element->tag, TOP_ELEMENT_TAG); + + if (!top_element) { + printf("<%s", element->tag); + int num_elems = _cairo_array_num_elements (&element->attributes); + for (int i = 0; i < num_elems; i++) { + svg_attribute_t *attr = _cairo_array_index (&element->attributes, i); + printf(" %s=\"%s\"", attr->name, attr->value); + } + if (num_elems > 0) + printf(" "); + + if (element->type == EMPTY_ELEMENT) + printf("/>\n"); + else + printf(">\n"); + } + + if (element->type == CONTAINER_ELEMENT) { + if (recurse) { + int num_elems = _cairo_array_num_elements (&element->children); + for (int i = 0; i < num_elems; i++) { + cairo_svg_element_t *child; + _cairo_array_copy_element (&element->children, i, &child); + print_element (child, TRUE, level + 1); + } + } + if (!top_element) + printf("</%s>\n", element->tag); + } + } + free (content); +} +#endif + +static const char * +parse_list_of_floats (const char *p, + int num_required, + int num_optional, + cairo_bool_t *have_optional, + va_list ap) +{ + double d; + double *dp; + char *end; + const char *q = NULL; + int num_found = 0; + + for (int i = 0; i < num_required + num_optional; i++) { + while (p && (*p == ',' || _cairo_isspace (*p))) + p++; + + if (!p) + break; + + d = _cairo_strtod (p, &end); + if (end == p) { + p = NULL; + break; + } + p = end; + dp = va_arg (ap, double *); + *dp = d; + num_found++; + if (num_found == num_required) + q = p; + } + + if (num_optional > 0) { + if (num_found == num_required + num_optional) { + *have_optional = TRUE; + } else { + *have_optional = FALSE; + /* restore pointer to end of required floats */ + p = q; + } + } + + return p; +} + +static const char * +get_floats (const char *p, + int num_required, + int num_optional, + cairo_bool_t *have_optional, + ...) +{ + va_list ap; + + va_start (ap, have_optional); + p = parse_list_of_floats (p, num_required, num_optional, have_optional, ap); + va_end (ap); + return p; +} + +static const char * +get_path_params (const char *p, int num_params, ...) +{ + va_list ap; + + va_start (ap, num_params); + p = parse_list_of_floats (p, num_params, 0, NULL, ap); + va_end (ap); + return p; +} + +static cairo_bool_t +get_color (cairo_svg_glyph_render_t *svg_render, + const char *s, + cairo_svg_color_t *color) +{ + int len, matched; + unsigned r = 0, g = 0, b = 0; + + if (!s) + return FALSE; + + len = strlen(s); + + if (string_equal (s, "inherit")) { + return FALSE; + } else if (string_equal (s, "currentColor") || + string_equal (s, "context-fill") || + string_equal (s, "context-stroke")) + { + *color = svg_render->graphics_state->color; + return TRUE; + } else if (len > 0 && s[0] == '#') { + if (len == 4) { + matched = sscanf (s + 1, "%1x%1x%1x", &r, &g, &b); + if (matched == 3) { + /* Each digit is repeated to convert to 6 digits. eg 0x123 -> 0x112233 */ + color->type = RGB; + color->red = 0x11*r/255.0; + color->green = 0x11*g/255.0; + color->blue = 0x11*b/255.0; + return TRUE; + } + } else if (len == 7) { + matched = sscanf (s + 1, "%2x%2x%2x", &r, &g, &b); + if (matched == 3) { + color->type = RGB; + color->red = r/255.0; + color->green = g/255.0; + color->blue = b/255.0; + return TRUE; + } + } + } else if (strncmp (s, "rgb", 3) == 0) { + matched = sscanf (s, "rgb ( %u , %u , %u )", &r, &g, &b); + if (matched == 3) { + color->type = RGB; + color->red = r/255.0; + color->green = g/255.0; + color->blue = b/255.0; + return TRUE; + } + } else if (strncmp (s, "var", 3) == 0) { + /* CPAL palettes colors. eg "var(--color0, yellow)" */ + s += 3; + s = skip_char (s, '('); + if (!string_match (&s, "--color")) + return FALSE; + + char *end; + int entry = strtol (s, &end, 10); + if (end == s) + return FALSE; + + if (svg_render->palette && entry >= 0 && entry < svg_render->num_palette_entries) { + FT_Color *palette_color = &svg_render->palette[entry]; + color->type = RGB; + color->red = palette_color->red / 255.0; + color->green = palette_color->green/ 255.0; + color->blue = palette_color->blue / 255.0; + return TRUE; + } else { + /* Fallback color */ + s = skip_char (end, ','); + if (!s) + return FALSE; + + end = strpbrk(s, WHITE_SPACE_CHARS ")"); + if (!end || end == s) + return FALSE; + + char *fallback = _cairo_strndup (s, end - s); + cairo_bool_t success = get_color (svg_render, fallback, color); + free (fallback); + return success; + } + } else { + const color_name_t *color_name; + color_name_t color_name_key; + + color_name_key.name = (char *) s; + color_name = bsearch (&color_name_key, + color_names, + ARRAY_LENGTH (color_names), + sizeof (color_name_t), + _color_name_compare); + if (color_name) { + color->type = RGB; + color->red = color_name->red/255.0; + color->green = color_name->green/255.0; + color->blue = color_name->blue/255.0; + return TRUE; + } + } + return FALSE; +} + +static void +get_paint (cairo_svg_glyph_render_t *svg_render, + const char *p, + cairo_svg_paint_t *paint) +{ + cairo_svg_element_t *element; + + if (string_match (&p, "none")) { + paint->type = PAINT_NONE; + paint->paint_server = NULL; + } else if (p && strncmp (p, "url", 3) == 0) { + element = lookup_url_element (svg_render, p); + if (element) { + paint->type = PAINT_SERVER; + paint->paint_server = element; + } + } else { + if (get_color (svg_render, p, &paint->color)) { + paint->type = PAINT_COLOR; + paint->paint_server = NULL; + } + } +} + +#ifdef SVG_RENDER_PRINT_FUNCTIONS + +static void +print_color (cairo_svg_color_t *color) +{ + switch (color->type) { + case FOREGROUND_COLOR: + printf("foreground"); + break; + case RGB: + printf("#%02x%02x%02x", + (int)(color->red*255), + (int)(color->red*255), + (int)(color->red*255)); + break; + } +} + +static void +print_paint (cairo_svg_paint_t *paint) +{ + printf("Paint: "); + switch (paint->type) { + case PAINT_COLOR: + printf("color: "); + print_color (&paint->color); + break; + case PAINT_SERVER: + printf("server: %s", paint->paint_server->tag); + break; + case PAINT_NONE: + printf("none"); + break; + } + printf("\n"); +} + +#endif + +static void +parse_error (cairo_svg_glyph_render_t *svg_render, + const char *string, + const char *location, + const char *fmt, + ...) CAIRO_PRINTF_FORMAT (4, 5); + +static void +parse_error (cairo_svg_glyph_render_t *svg_render, + const char *string, + const char *location, + const char *fmt, + ...) +{ + va_list ap; + const int context = 40; + const char *start; + const char *end; + + if (svg_render->debug >= SVG_RENDER_ERROR) { + printf("ERROR: "); + va_start (ap, fmt); + vprintf (fmt, ap); + va_end (ap); + putchar ('\n'); + start = location - context; + if (start < string) + start = string; + + end = location + strlen (location); + if (end - location > context) + end = location + context; + + for (const char *p = start; p < end; p++) { + if (_cairo_isspace (*p)) + putchar (' '); + else + putchar (*p); + } + putchar ('\n'); + + for (int i = 0; i < location - start; i++) + putchar(' '); + putchar ('^'); + putchar ('\n'); + printf (" at position %td\n", location - string); + } +} + +static cairo_bool_t +append_attribute (cairo_svg_element_t *element, svg_attribute_t *attribute) +{ + const char *p; + const char *end; + svg_attribute_t attr; + + memset (&attr, 0, sizeof (attr)); + if (string_equal (attribute->name, "style")) { + /* split style into individual attributes */ + p = attribute->value; + while (*p) { + end = strchr (p, ':'); + if (!end || end == p) + break; + attr.name = _cairo_strndup (p, end - p); + p = end + 1; + p = skip_space(p); + end = strchr (p, ';'); + if (!end) + end = strchr (p, 0); + if (end == p) + goto split_style_fail; + + attr.value = _cairo_strndup (p, end - p); + if (*end) + p = end + 1; + + if (_cairo_array_append (&element->attributes, &attr)) + goto split_style_fail; + + memset (&attr, 0, sizeof (attr)); + p = skip_space (p); + } + } + + if (_cairo_array_append (&element->attributes, attribute)) + return FALSE; + + return TRUE; + + split_style_fail: + free (attr.name); + free (attr.value); + return FALSE; +} + +static cairo_bool_t +add_child_element (cairo_svg_glyph_render_t *svg_render, + cairo_svg_element_t *parent, + cairo_svg_element_t *child) +{ + cairo_status_t status; + const char* id; + + id = get_attribute (child, "id"); + if (id) { + child->id = strdup (id); + init_element_id_key (child); + status = _cairo_hash_table_insert (svg_render->ids, &child->base); + if (unlikely (status)) + return FALSE; + } + + status = _cairo_array_append (&parent->children, &child); + return status == CAIRO_STATUS_SUCCESS; +} + +static cairo_svg_element_t * +create_element (tag_type_t type, char *tag) +{ + cairo_svg_element_t *elem; + cairo_status_t status; + + elem = _cairo_malloc (sizeof (cairo_svg_element_t)); + if (unlikely (elem == NULL)) { + status = _cairo_error (CAIRO_STATUS_NO_MEMORY); + return NULL; + } + + elem->type = type; + elem->tag = tag; + elem->id = NULL; + _cairo_array_init (&elem->attributes, sizeof(svg_attribute_t)); + _cairo_array_init (&elem->children, sizeof(cairo_svg_element_t *)); + _cairo_array_init (&elem->content, sizeof(char)); + elem->pattern = NULL; + elem->next = NULL; + + return elem; +} + +static const char * +parse_attributes (cairo_svg_glyph_render_t *svg_render, + const char *attributes, + cairo_svg_element_t *element) +{ + svg_attribute_t attr; + char quote_char; + const char *p; + const char *end; + + p = attributes; + memset (&attr, 0, sizeof (svg_attribute_t)); + p = skip_space (p); + while (*p && *p != '/' && *p != '>' && *p != '?') { + end = strpbrk(p, WHITE_SPACE_CHARS "="); + if (!end) { + parse_error (svg_render, attributes, p, "Could not find '='"); + goto fail; + } + + if (end == p) { + parse_error (svg_render, attributes, p, "Missing attribute name"); + goto fail; + } + + attr.name = _cairo_strndup (p, end - p); + p = end; + + p = skip_space (p); + if (*p != '=') { + parse_error (svg_render, attributes, p, "Expected '='"); + goto fail; + } + + p++; + p = skip_space (p); + if (*p == '\"' || *p == '\'') { + quote_char = *p; + } else { + parse_error (svg_render, attributes, p, "Could not find '\"' or '''"); + goto fail; + } + + p++; + end = strchr (p, quote_char); + if (!end) { + parse_error (svg_render, attributes, p, "Could not find '%c'", quote_char); + goto fail; + } + + attr.value = _cairo_strndup (p, end - p); + p = end + 1; + + if (!append_attribute (element, &attr)) + goto fail; + + memset (&attr, 0, sizeof (svg_attribute_t)); + + p = skip_space (p); + } + + return p; + + fail: + free (attr.name); + free (attr.value); + return NULL; +} + +static cairo_bool_t +parse_svg (cairo_svg_glyph_render_t *svg_render, + const char *svg_document) +{ + const char *p = svg_document; + const char *end; + int nesting; /* when > 0 we parse content */ + cairo_svg_element_t *open_elem; /* Stack of open elements */ + cairo_svg_element_t *new_elem = NULL; + char *name; + cairo_status_t status; + + /* Create top level element to use as a container for all top + * level elements in the document and push it on the stack. */ + open_elem = create_element (CONTAINER_ELEMENT, strdup(TOP_ELEMENT_TAG)); + + /* We don't want to add content to the top level container. There + * should only be whitesapce between tags. */ + nesting = 0; + + while (*p) { + if (nesting > 0) { + /* In an open element. Anything before the next '<' is content */ + end = strchr (p, '<'); + if (!end) { + parse_error (svg_render, svg_document, p, "Could not find '<'"); + goto fail; + } + status = _cairo_array_append_multiple (&open_elem->content, p, end - p); + p = end; + + } else { + p = skip_space (p); + if (*p == 0) + break; /* end of document */ + } + + /* We should now be at the start of a tag */ + if (*p != '<') { + parse_error (svg_render, svg_document, p, "Could not find '<'"); + goto fail; + } + + p++; + if (*p == '!') { + p++; + if (string_match (&p, "[CDATA[")) { + new_elem = create_element (CDATA, NULL); + end = strstr (p, "]]>"); + if (!end) { + parse_error (svg_render, svg_document, p, "Could not find ']]>'"); + goto fail; + } + + status = _cairo_array_append_multiple (&new_elem->content, p, end - p); + p = end + 3; + } else if (string_match (&p, "--")) { + new_elem = create_element (COMMENT, NULL); + end = strstr (p, "-->"); + if (!end) { + parse_error (svg_render, svg_document, p, "Could not find '-->'"); + goto fail; + } + + status = _cairo_array_append_multiple (&new_elem->content, p, end - p); + p = end + 3; + } else if (string_match (&p, "DOCTYPE")) { + new_elem = create_element (DOCTYPE, NULL); + end = strchr (p, '>'); + if (!end) { + parse_error (svg_render, svg_document, p, "Could not find '>'"); + goto fail; + } + + status = _cairo_array_append_multiple (&new_elem->content, p, end - p); + p = end + 1; + } else { + parse_error (svg_render, svg_document, p, "Invalid"); + goto fail; + } + + if (!add_child_element (svg_render, open_elem, new_elem)) + goto fail; + + new_elem = NULL; + continue; + } + + if (*p == '?') { + p++; + new_elem = create_element (PROCESSING_INSTRUCTION, NULL); + end = strstr (p, "?>"); + if (!end) { + parse_error (svg_render, svg_document, p, "Could not find '?>'"); + goto fail; + } + + status = _cairo_array_append_multiple (&new_elem->content, p, end - p); + p = end + 2; + + if (!add_child_element (svg_render, open_elem, new_elem)) + goto fail; + + new_elem = NULL; + continue; + } + + if (*p == '/') { + /* Closing tag */ + p++; + + /* find end of tag name */ + end = strpbrk(p, WHITE_SPACE_CHARS ">"); + if (!end) { + parse_error (svg_render, svg_document, p, "Could not find '>'"); + goto fail; + } + + name = _cairo_strndup (p, end - p); + p = end; + p = skip_space (p); + if (*p != '>') { + parse_error (svg_render, svg_document, p, "Could not find '>'"); + free (name); + goto fail; + } + + p++; + if (nesting == 0) { + parse_error (svg_render, svg_document, p, "parse_elements: parsed </%s> but no matching start tag", name); + free (name); + goto fail; + } + if (!string_equal (name, open_elem->tag)) { + parse_error (svg_render, svg_document, p, + "parse_elements: found </%s> but current open tag is <%s>", + name, open_elem->tag); + free (name); + goto fail; + } + + /* pop top element on open elements stack into new_elem */ + new_elem = open_elem; + open_elem = open_elem->next; + new_elem->next = NULL; + nesting--; + + free (name); + if (!add_child_element (svg_render, open_elem, new_elem)) + goto fail; + + new_elem = NULL; + continue; + } + + /* We should now be in a start or empty element tag */ + + /* find end of tag name */ + end = strpbrk(p, WHITE_SPACE_CHARS "/>"); + if (!end) { + parse_error (svg_render, svg_document, p, "Could not find '>'"); + goto fail; + } + + name = _cairo_strndup (p, end - p); + p = end; + + new_elem = create_element (CONTAINER_ELEMENT, name); + p = parse_attributes (svg_render, p, new_elem); + if (!p) + goto fail; + + p = skip_space (p); + if (*p == '/') { + new_elem->type = EMPTY_ELEMENT; + p++; + } + + if (!p || *p != '>') { + print_error (svg_render, "Could not find '>'"); + goto fail; + } + + p++; + if (new_elem->type == EMPTY_ELEMENT) { + if (!add_child_element (svg_render, open_elem, new_elem)) + goto fail; + + new_elem = NULL; + } else { + /* push new elem onto open elements stack */ + new_elem->next = open_elem; + open_elem = new_elem; + new_elem = NULL; + nesting++; + } + } + + if (nesting != 0) { + parse_error (svg_render, svg_document, p, "Missing closing tag for <%s>", open_elem->tag); + goto fail; + } + + svg_render->tree = open_elem; + return TRUE; + + fail: + if (new_elem) + free_elements (svg_render, new_elem); + + while (open_elem) { + cairo_svg_element_t *elem = open_elem; + open_elem = open_elem->next; + free_elements (svg_render, elem); + } + + return FALSE; +} + +static cairo_bool_t +parse_transform (const char *p, cairo_matrix_t *matrix) +{ + cairo_matrix_t m; + double x, y, a; + cairo_bool_t have_optional; + + cairo_matrix_init_identity (matrix); + while (p) { + while (p && (*p == ',' || _cairo_isspace (*p))) + p++; + + if (!p || *p == 0) + break; + + if (string_match (&p, "matrix")) { + p = skip_char (p, '('); + if (!p) + break; + + p = get_floats (p, 6, 0, NULL, &m.xx, &m.yx, &m.xy, &m.yy, &m.x0, &m.y0); + if (!p) + break; + + p = skip_char (p, ')'); + if (!p) + break; + + cairo_matrix_multiply (matrix, &m, matrix); + + } else if (string_match (&p, "translate")) { + p = skip_char (p, '('); + if (!p) + break; + + p = get_floats (p, 1, 1, &have_optional, &x, &y); + if (!p) + break; + + p = skip_char (p, ')'); + if (!p) + break; + + if (!have_optional) + y = 0; + + cairo_matrix_translate (matrix, x, y); + + } else if (string_match (&p, "scale")) { + p = skip_char (p, '('); + if (!p) + break; + + p = get_floats (p, 1, 1, &have_optional, &x, &y); + if (!p) + break; + + p = skip_char (p, ')'); + if (!p) + break; + + if (!have_optional) + y = x; + + cairo_matrix_scale (matrix, x, y); + + } else if (string_match (&p, "rotate")) { + p = skip_char (p, '('); + if (!p) + break; + + p = get_floats (p, 1, 2, &have_optional, &a, &x, &y); + if (!p) + break; + + p = skip_char (p, ')'); + if (!p) + break; + + if (!have_optional) { + x = 0; + y = 0; + } + + a *= M_PI/180.0; + cairo_matrix_translate (matrix, x, y); + cairo_matrix_rotate (matrix, a); + cairo_matrix_translate (matrix, -x, -y); + + } else if (string_match (&p, "skewX")) { + p = skip_char (p, '('); + if (!p) + break; + + p = get_floats (p, 1, 0, NULL, &a); + if (!p) + break; + + p = skip_char (p, ')'); + if (!p) + break; + + a *= M_PI/180.0; + cairo_matrix_init_identity (&m); + m.xy = tan (a); + cairo_matrix_multiply (matrix, &m, matrix); + + } else if (string_match (&p, "skewY")) { + p = skip_char (p, '('); + if (!p) + break; + + p = get_floats (p, 1, 0, NULL, &a); + if (!p) + break; + + p = skip_char (p, ')'); + if (!p) + break; + + a *= M_PI/180.0; + cairo_matrix_init_identity (&m); + m.yx = tan (a); + cairo_matrix_multiply (matrix, &m, matrix); + + } else { + break; + } + } + return p != NULL; +} + +static void +render_element_tree (cairo_svg_glyph_render_t *svg_render, + cairo_svg_element_t *element, + cairo_svg_element_t *display_element, + cairo_bool_t children_only); + +static cairo_pattern_t * +create_pattern (cairo_svg_glyph_render_t *svg_render, + cairo_svg_element_t *paint_server) +{ + cairo_pattern_t *pattern = NULL; + + if (paint_server) { + svg_render->build_pattern.paint_server = paint_server; + render_element_tree (svg_render, paint_server, NULL, FALSE); + pattern = svg_render->build_pattern.pattern; + svg_render->build_pattern.pattern = NULL; + svg_render->build_pattern.paint_server = NULL; + svg_render->build_pattern.type = BUILD_PATTERN_NONE; + } + + if (!pattern) + pattern = cairo_pattern_create_rgb (0, 0, 0); + + return pattern; +} + +static cairo_bool_t +render_element_svg (cairo_svg_glyph_render_t *svg_render, + cairo_svg_element_t *element, + cairo_bool_t end_tag) +{ + double width, height; + double vb_x, vb_y, vb_height, vb_width; + const char *p; + const char *end; + + if (end_tag) + return FALSE; + + /* Default viewport width, height is EM square */ + if (!get_float_or_percent_attribute (element, "width", svg_render->units_per_em, &width)) + width = svg_render->units_per_em; + + if (!get_float_or_percent_attribute (element, "height", svg_render->units_per_em, &height)) + height = svg_render->units_per_em; + + /* Transform viewport to unit square, centering it if width != height. */ + if (width > height) { + cairo_scale (svg_render->cr, 1.0/width, 1.0/width); + cairo_translate (svg_render->cr, 0, (width - height)/2.0); + } else { + cairo_scale (svg_render->cr, 1.0/height, 1.0/height); + cairo_translate (svg_render->cr, (height - width)/2.0, 0); + } + + svg_render->width = width; + svg_render->height = height; + + p = get_attribute (element, "viewBox"); + if (p) { + /* Transform viewport to viewbox */ + end = get_path_params (p, 4, &vb_x, &vb_y, &vb_width, &vb_height); + if (!end) { + print_warning (svg_render, "viewBox expected 4 numbers: %s", p); + return FALSE; + } + cairo_translate (svg_render->cr, -vb_x * width/vb_width, -vb_y * width/vb_width); + cairo_scale (svg_render->cr, width/vb_width, height/vb_height); + svg_render->width = vb_width; + svg_render->height = vb_height; + } + + svg_render->view_port_set = TRUE; + return TRUE; +} + +static cairo_bool_t +render_element_clip_path (cairo_svg_glyph_render_t *svg_render, + cairo_svg_element_t *element, + cairo_bool_t end_tag) +{ + cairo_svg_graphics_state_t *gs = svg_render->graphics_state; + const char *p; + + if (end_tag || gs->mode != GS_CLIP || svg_render->build_pattern.type != BUILD_PATTERN_NONE) { + return FALSE; + } + + p = get_attribute (element, "clipPathUnits"); + if (string_equal (p, "objectBoundingBox")) { + cairo_translate (svg_render->cr, + svg_render->graphics_state->bbox.x, + svg_render->graphics_state->bbox.y); + cairo_scale (svg_render->cr, + svg_render->graphics_state->bbox.width, + svg_render->graphics_state->bbox.height); + } + + return TRUE; +} + +static void +apply_gradient_attributes (cairo_svg_glyph_render_t *svg_render, + cairo_svg_element_t *element) +{ + cairo_pattern_t *pattern = svg_render->build_pattern.pattern; + cairo_bool_t object_bbox = TRUE; + cairo_matrix_t transform; + cairo_matrix_t mat; + const char *p; + + if (!pattern) + return; + + p = get_attribute (element, "gradientUnits"); + if (string_equal (p, "userSpaceOnUse")) + object_bbox = FALSE; + + cairo_matrix_init_identity (&mat); + if (object_bbox) { + cairo_matrix_translate (&mat, + svg_render->graphics_state->bbox.x, + svg_render->graphics_state->bbox.y); + cairo_matrix_scale (&mat, + svg_render->graphics_state->bbox.width, + svg_render->graphics_state->bbox.height); + } + + p = get_attribute (element, "gradientTransform"); + if (parse_transform (p, &transform)) + cairo_matrix_multiply (&mat, &transform, &mat); + + if (cairo_matrix_invert (&mat) == CAIRO_STATUS_SUCCESS) + cairo_pattern_set_matrix (pattern, &mat); + + p = get_attribute (element, "spreadMethod"); + if (string_equal (p, "reflect")) + cairo_pattern_set_extend (pattern, CAIRO_EXTEND_REFLECT); + else if (string_equal (p, "repeat")) + cairo_pattern_set_extend (pattern, CAIRO_EXTEND_REPEAT); +} + +static cairo_bool_t +render_element_linear_gradient (cairo_svg_glyph_render_t *svg_render, + cairo_svg_element_t *element, + cairo_bool_t end_tag) +{ + double x1, y1, x2, y2; + + if (svg_render->build_pattern.paint_server != element || + end_tag || + svg_render->build_pattern.type != BUILD_PATTERN_NONE) + return FALSE; + + /* FIXME default value for userSpaceOnUse? */ + double width = 1.0; + double height = 1.0; + + if (!get_float_or_percent_attribute (element, "x1", width, &x1)) + x1 = 0.0; + + if (!get_float_or_percent_attribute (element, "y1", height, &y1)) + y1 = 0.0; + + if (!get_float_or_percent_attribute (element, "x2", width, &x2)) + x2 = width; + + if (!get_float_or_percent_attribute (element, "y2", height, &y2)) + y2 = 0.0; + + if (svg_render->build_pattern.pattern) + abort(); + + svg_render->build_pattern.pattern = cairo_pattern_create_linear (x1, y1, x2, y2); + svg_render->build_pattern.type = BUILD_PATTERN_LINEAR; + apply_gradient_attributes (svg_render, element); + return TRUE; +} + +static cairo_bool_t +render_element_radial_gradient (cairo_svg_glyph_render_t *svg_render, + cairo_svg_element_t *element, + cairo_bool_t end_tag) +{ + double cx, cy, r, fx, fy; + + if (svg_render->build_pattern.paint_server != element || + end_tag || + svg_render->build_pattern.type != BUILD_PATTERN_NONE) + return FALSE; + + /* FIXME default value for userSpaceOnUse? */ + double width = 1.0; + double height = 1.0; + + if (!get_float_or_percent_attribute (element, "cx", width, &cx)) + cx = 0.5 * width; + + if (!get_float_or_percent_attribute (element, "cy", height, &cy)) + cy = 0.5 * height; + + if (!get_float_or_percent_attribute (element, "r", width, &r)) + r = 0.5 * width; + + if (!get_float_or_percent_attribute (element, "fx", width, &fx)) + fx = cx; + + if (!get_float_or_percent_attribute (element, "fy", height, &fy)) + fy = cy; + + svg_render->build_pattern.pattern = cairo_pattern_create_radial (fx, fy, 0, cx, cy, r); + svg_render->build_pattern.type = BUILD_PATTERN_RADIAL; + apply_gradient_attributes (svg_render, element); + return TRUE; +} + +static cairo_bool_t +render_element_stop (cairo_svg_glyph_render_t *svg_render, + cairo_svg_element_t *element, + cairo_bool_t end_tag) +{ + double offset, opacity; + cairo_pattern_t *pattern = svg_render->build_pattern.pattern; + + if (!pattern) + return FALSE; + + if (cairo_pattern_get_type (pattern) != CAIRO_PATTERN_TYPE_LINEAR && + cairo_pattern_get_type (pattern) != CAIRO_PATTERN_TYPE_RADIAL) + return FALSE; + + if (!get_float_or_percent_attribute (element, "offset", 1.0, &offset)) + return FALSE; + + if (!get_float_attribute (element, "stop-opacity", &opacity)) + opacity = 1.0; + + cairo_svg_color_t color; + get_color (svg_render, "black", &color); + get_color (svg_render, get_attribute(element, "stop-color"), &color); + if (color.type == RGB) { + cairo_pattern_add_color_stop_rgba (pattern, + offset, + color.red, + color.green, + color.blue, + opacity); + } else { /* color.type == FOREGROUND */ + double red, green, blue, alpha; + if (cairo_pattern_get_rgba (svg_render->foreground_source, &red, &green, &blue, &alpha) == CAIRO_STATUS_SUCCESS) { + svg_render->foreground_source_used = TRUE; + } else { + red = green = blue = 0; + alpha = 1; + } + cairo_pattern_add_color_stop_rgba (pattern, offset, red, green, blue, alpha); + } + return TRUE; +} + +static cairo_bool_t +render_element_g (cairo_svg_glyph_render_t *svg_render, + cairo_svg_element_t *element, + cairo_bool_t end_tag) +{ + if (svg_render->graphics_state->mode == GS_NO_RENDER || + svg_render->build_pattern.type != BUILD_PATTERN_NONE) + return FALSE; + + if (!end_tag) { + cairo_push_group (svg_render->cr); + } else { + cairo_pop_group_to_source (svg_render->cr); + cairo_paint_with_alpha (svg_render->cr, svg_render->graphics_state->opacity); + } + return TRUE; +} + +typedef struct { + const char *data; /* current position in base64 data */ + char buf[3]; /* decode buffer */ + int buf_pos; /* current position in buf_pos. */ +} base64_decode_t; + +static cairo_status_t +_read_png_from_base64 (void *closure, unsigned char *data, unsigned int length) +{ + base64_decode_t *decode = closure; + int n, c; + unsigned val; + + while (length) { + if (decode->buf_pos >= 0) { + *data++ = decode->buf[decode->buf_pos++]; + length--; + if (decode->buf_pos == 3) + decode->buf_pos = -1; + } + if (length > 0 && decode->buf_pos < 0) { + n = 0; + while (*decode->data && n < 4) { + c = *decode->data++; + if (c >='A' && c <='Z') { + val = (val << 6) | (c -'A'); + n++; + } else if (c >='a' && c <='z') { + val = (val << 6) | (c -'a' + 26); + n++; + } else if (c >='0' && c <='9') { + val = (val << 6) | (c -'0' + 52); + n++; + } else if (c =='+') { + val = (val << 6) | 62; + n++; + } else if (c =='/') { + val = (val << 6) | 63; + n++; + } else if (c == '=') { + val = (val << 6); + n++; + } + } + if (n < 4) + return CAIRO_STATUS_READ_ERROR; + + decode->buf[0] = val >> 16; + decode->buf[1] = val >> 8; + decode->buf[2] = val >> 0; + decode->buf_pos = 0; + } + } + + return CAIRO_STATUS_SUCCESS; +} + +static cairo_bool_t +render_element_image (cairo_svg_glyph_render_t *svg_render, + cairo_svg_element_t *element, + cairo_bool_t end_tag) +{ + double x, y, width, height; + int w, h; + const char *data; + cairo_surface_t *surface; + base64_decode_t decode; + + if (svg_render->graphics_state->mode == GS_NO_RENDER || + svg_render->build_pattern.type != BUILD_PATTERN_NONE) + return FALSE; + + if (!get_float_attribute (element, "x", &x)) + x = 0; + + if (!get_float_attribute (element, "y", &y)) + y = 0; + + if (!get_float_attribute (element, "width", &width)) + return FALSE; + + if (!get_float_attribute (element, "height", &height)) + return FALSE; + + data = get_href_attribute (element); + if (!data) + return FALSE; + + if (!string_match (&data, "data:image/png;base64,")) + return FALSE; + + decode.data = data; + decode.buf_pos = -1; + surface = cairo_image_surface_create_from_png_stream (_read_png_from_base64, &decode); + if (cairo_surface_status (surface)) { + print_warning (svg_render, "Unable to decode PNG"); + cairo_surface_destroy (surface); + return FALSE; + } + + w = cairo_image_surface_get_width (surface); + h = cairo_image_surface_get_height (surface); + + if (w > 0 && h > 0) { + cairo_translate (svg_render->cr, x, y); + cairo_scale (svg_render->cr, width/w, height/h); + cairo_set_source_surface (svg_render->cr, surface, 0, 0); + cairo_paint (svg_render->cr); + } + + cairo_surface_destroy (surface); + + return FALSE; +} + +static cairo_bool_t +render_element_use (cairo_svg_glyph_render_t *svg_render, + cairo_svg_element_t *element, + cairo_bool_t end_tag) +{ + double x = 0; + double y = 0; + const char *id; + + if (end_tag || svg_render->graphics_state->mode == GS_NO_RENDER || + svg_render->build_pattern.type != BUILD_PATTERN_NONE) + return FALSE; + + get_float_attribute (element, "x", &x); + get_float_attribute (element, "y", &y); + + id = get_href_attribute (element); + if (!id) + return FALSE; + + cairo_svg_element_t *use_element = lookup_element (svg_render, id); + cairo_translate (svg_render->cr, x, y); + render_element_tree (svg_render, use_element, NULL, FALSE); + return TRUE; +} + +static cairo_bool_t +draw_path (cairo_svg_glyph_render_t *svg_render) +{ + cairo_svg_graphics_state_t *gs = svg_render->graphics_state; + cairo_pattern_t *pattern; + cairo_bool_t opacity_group = FALSE; + + if (gs->mode == GS_COMPUTE_BBOX) { + cairo_set_source_rgb (svg_render->cr, 0, 0, 0); + cairo_set_fill_rule (svg_render->cr, gs->fill_rule); + cairo_fill (svg_render->cr); + return FALSE; + } else if (gs->mode == GS_CLIP) { + return FALSE; + } + + if (gs->opacity < 1.0) { + cairo_push_group (svg_render->cr); + opacity_group = TRUE; + } + + cairo_path_t *path = cairo_copy_path (svg_render->cr); + cairo_new_path (svg_render->cr); + + if (gs->fill.type != PAINT_NONE) { + cairo_bool_t group = FALSE; + if (gs->fill.type == PAINT_COLOR) { + if (gs->fill.color.type == RGB) { + cairo_set_source_rgba (svg_render->cr, + gs->fill.color.red, + gs->fill.color.green, + gs->fill.color.blue, + gs->fill_opacity); + } else if (gs->fill.color.type == FOREGROUND) { + cairo_set_source (svg_render->cr, svg_render->foreground_marker); + if (gs->fill_opacity < 1.0) + group = TRUE; + } + } else if (gs->fill.type == PAINT_SERVER) { + pattern = create_pattern (svg_render, gs->fill.paint_server); + cairo_set_source (svg_render->cr, pattern); + cairo_pattern_destroy (pattern); + if (gs->fill_opacity < 1.0) + group = TRUE; + } + + if (group) + cairo_push_group (svg_render->cr); + + cairo_append_path (svg_render->cr, path); + cairo_set_fill_rule (svg_render->cr, gs->fill_rule); + cairo_fill (svg_render->cr); + if (group) { + cairo_pop_group_to_source (svg_render->cr); + cairo_paint_with_alpha (svg_render->cr, gs->fill_opacity); + } + } + + if (gs->stroke.type != PAINT_NONE) { + cairo_bool_t group = FALSE; + if (gs->stroke.type == PAINT_COLOR) { + if (gs->stroke.color.type == RGB) { + cairo_set_source_rgba (svg_render->cr, + gs->stroke.color.red, + gs->stroke.color.green, + gs->stroke.color.blue, + gs->stroke_opacity); + } else if (gs->fill.color.type == FOREGROUND) { + cairo_set_source (svg_render->cr, svg_render->foreground_marker); + if (gs->fill_opacity < 1.0) + group = TRUE; + } + } else if (gs->stroke.type == PAINT_SERVER) { + pattern = create_pattern (svg_render, gs->stroke.paint_server); + cairo_set_source (svg_render->cr, pattern); + cairo_pattern_destroy (pattern); + if (gs->stroke_opacity < 1.0) + group = TRUE; + } + + if (group) + cairo_push_group (svg_render->cr); + + cairo_append_path (svg_render->cr, path); + cairo_stroke (svg_render->cr); + + if (group) { + cairo_pop_group_to_source (svg_render->cr); + cairo_paint_with_alpha (svg_render->cr, gs->stroke_opacity); + } + } + + cairo_path_destroy (path); + + if (opacity_group) { + cairo_pop_group_to_source (svg_render->cr); + cairo_paint_with_alpha (svg_render->cr, gs->opacity); + } + return TRUE; +} + +static void +elliptical_arc (cairo_svg_glyph_render_t *svg_render, + double cx, + double cy, + double rx, + double ry, + double angle1, + double angle2) +{ + cairo_save (svg_render->cr); + cairo_translate (svg_render->cr, cx, cy); + cairo_scale (svg_render->cr, rx, ry); + cairo_arc (svg_render->cr, 0, 0, 1, angle1, angle2); + cairo_restore (svg_render->cr); +} + +static cairo_bool_t +render_element_rect (cairo_svg_glyph_render_t *svg_render, + cairo_svg_element_t *element, + cairo_bool_t end_tag) +{ + double x = 0; + double y = 0; + double width = svg_render->width; + double height = svg_render->height; + double rx = 0; + double ry = 0; + + if (end_tag || + svg_render->graphics_state->mode == GS_NO_RENDER || + svg_render->build_pattern.type != BUILD_PATTERN_NONE) + return FALSE; + + get_float_or_percent_attribute (element, "x", svg_render->width, &x); + get_float_or_percent_attribute (element, "y", svg_render->height, &y); + get_float_or_percent_attribute (element, "width", svg_render->width, &width); + get_float_or_percent_attribute (element, "height", svg_render->height, &height); + get_float_or_percent_attribute (element, "rx", svg_render->width, &rx); + get_float_or_percent_attribute (element, "ry", svg_render->height, &ry); + + if (rx == 0 && ry == 0) { + cairo_rectangle (svg_render->cr, x, y, width, height); + } else { + cairo_move_to (svg_render->cr, x + rx, y); + cairo_line_to (svg_render->cr, x + width - rx, y); + elliptical_arc (svg_render, x + width - rx, y + ry, rx, ry, -M_PI/2, 0); + cairo_line_to (svg_render->cr, x + width, y + height - ry); + elliptical_arc (svg_render, x + width - rx, y + height - ry, rx, ry, 0, M_PI/2); + cairo_line_to (svg_render->cr, x + rx, y + height); + elliptical_arc (svg_render, x + rx, y + height - ry, rx, ry, M_PI/2, M_PI); + cairo_line_to (svg_render->cr, x, y + ry); + elliptical_arc (svg_render, x + rx, y + ry, rx, ry, M_PI, -M_PI/2); + } + + draw_path (svg_render); + return TRUE; +} + +static cairo_bool_t +render_element_circle (cairo_svg_glyph_render_t *svg_render, + cairo_svg_element_t *element, + cairo_bool_t end_tag) +{ + double cx = 0; + double cy = 0; + double r = 0; + + if (end_tag || + svg_render->graphics_state->mode == GS_NO_RENDER || + svg_render->build_pattern.type != BUILD_PATTERN_NONE) + return FALSE; + + get_float_or_percent_attribute (element, "cx", svg_render->width, &cx); + get_float_or_percent_attribute (element, "cy", svg_render->height, &cy); + get_float_or_percent_attribute (element, "r", svg_render->width, &r); + + cairo_arc (svg_render->cr, cx, cy, r, 0, 2*M_PI); + + draw_path (svg_render); + return TRUE; +} + +static cairo_bool_t +render_element_ellipse (cairo_svg_glyph_render_t *svg_render, + cairo_svg_element_t *element, + cairo_bool_t end_tag) +{ + double cx = 0; + double cy = 0; + double rx = 0; + double ry = 0; + + if (end_tag || + svg_render->graphics_state->mode == GS_NO_RENDER || + svg_render->build_pattern.type != BUILD_PATTERN_NONE) + return FALSE; + + get_float_or_percent_attribute (element, "cx", svg_render->width, &cx); + get_float_or_percent_attribute (element, "cy", svg_render->height, &cy); + get_float_or_percent_attribute (element, "rx", svg_render->width, &rx); + get_float_or_percent_attribute (element, "ry", svg_render->height, &ry); + + elliptical_arc (svg_render, cx, cy, rx, ry, 0, 2*M_PI); + draw_path (svg_render); + return TRUE; +} + +static cairo_bool_t +render_element_line (cairo_svg_glyph_render_t *svg_render, + cairo_svg_element_t *element, + cairo_bool_t end_tag) +{ + double x1 = 0; + double y1 = 0; + double x2 = 0; + double y2 = 0; + + if (end_tag || + svg_render->graphics_state->mode == GS_NO_RENDER || + svg_render->build_pattern.type != BUILD_PATTERN_NONE) + return FALSE; + + get_float_or_percent_attribute (element, "x1", svg_render->width, &x1); + get_float_or_percent_attribute (element, "y1", svg_render->height, &y1); + get_float_or_percent_attribute (element, "x2", svg_render->width, &x2); + get_float_or_percent_attribute (element, "y2", svg_render->height, &y2); + + cairo_move_to (svg_render->cr, x1, y1); + cairo_line_to (svg_render->cr, x2, y2); + + draw_path (svg_render); + return TRUE; +} + +static cairo_bool_t +render_element_polyline (cairo_svg_glyph_render_t *svg_render, + cairo_svg_element_t *element, + cairo_bool_t end_tag) +{ + const char *p; + const char *end; + double x, y; + cairo_bool_t have_move = FALSE; + + if (end_tag || + svg_render->graphics_state->mode == GS_NO_RENDER || + svg_render->build_pattern.type != BUILD_PATTERN_NONE) + return FALSE; + + p = get_attribute (element, "points"); + do { + end = get_path_params (p, 2, &x, &y); + if (!end) { + print_warning (svg_render, "points expected 2 numbers: %s", p); + break; + } + p = end; + if (!have_move) { + cairo_move_to (svg_render->cr, x, y); + have_move = TRUE; + } else { + cairo_line_to (svg_render->cr, x, y); + } + p = skip_space (p); + } while (p && *p); + + if (string_equal (element->tag, "polygon")) + cairo_close_path (svg_render->cr); + + draw_path (svg_render); + return TRUE; +} + +static double +angle_between_vectors (double ux, + double uy, + double vx, + double vy) +{ + double dot = ux*vx + uy*vy; + double umag = sqrt (ux*ux + uy*uy); + double vmag = sqrt (vx*vx + vy*vy); + double c = dot/(umag*vmag); + if (c > 1.0) + c = 1.0; + + if (c < -1.0) + c = -1.0; + + double a = acos (c); + if (ux * vy - uy * vx < 0.0) + a = -a; + + return a; +} + +static void +arc_path (cairo_t *cr, + double x1, double y1, + double x2, double y2, + double rx, double ry, + double rotate, + cairo_bool_t large_flag, + cairo_bool_t sweep_flag) +{ + double x1_, y1_, cx_, cy_; + double xm, ym, cx, cy; + double a, b, d; + double ux, uy, vx, vy; + double theta, delta_theta; + double epsilon; + cairo_matrix_t ctm; + + cairo_get_matrix (cr, &ctm); + epsilon = _cairo_matrix_transformed_circle_major_axis (&ctm, cairo_get_tolerance (cr)); + + rotate *= M_PI/180.0; + + /* Convert endpoint to center parameterization. + * See SVG 1.1 Appendix F.6. Step numbers are the steps in the appendix. + */ + + rx = fabs (rx); + ry = fabs (ry); + if (rx < epsilon || ry < epsilon) { + cairo_line_to (cr, x2, y2); + return; + } + + if (fabs(x1 - x2) < epsilon && fabs(y1 - y2) < epsilon) { + cairo_line_to (cr, x2, y2); + return; + } + + /* Step 1 */ + xm = (x1 - x2)/2; + ym = (y1 - y2)/2; + x1_ = xm * cos (rotate) + ym * sin (rotate); + y1_ = xm * -sin (rotate) + ym * cos (rotate); + + d = (x1_*x1_)/(rx*rx) + (y1_*y1_)/(ry*ry); + if (d > 1.0) { + d = sqrt (d); + rx *= d; + ry *= d; + } + + /* Step 2 */ + a = (rx*rx * y1_*y1_) + (ry*ry * x1_*x1_); + if (a == 0.0) + return; + + b = (rx*rx * ry*ry) / a - 1.0; + if (b < 0) + b = 0.0; + + d = sqrt(b); + if (large_flag == sweep_flag) + d = -d; + + cx_ = d * rx*y1_/ry; + cy_ = d * -ry*x1_/rx; + + /* Step 3 */ + cx = cx_ * cos (rotate) - cy_ * sin (rotate) + (x1 + x2)/2; + cy = cx_ * sin (rotate) + cy_ * cos (rotate) + (y1 + y2)/2; + + /* Step 4 */ + ux = (x1_ - cx_)/rx; + uy = (y1_ - cy_)/ry; + vx = (-x1_ - cx_)/rx; + vy = (-y1_ - cy_)/ry; + theta = angle_between_vectors (1.0, 0, ux, uy); + delta_theta = angle_between_vectors (ux, uy, vx, vy); + + if (!sweep_flag && delta_theta > 0) + delta_theta -= 2 * M_PI; + else if (sweep_flag && delta_theta < 0) + delta_theta += 2 * M_PI; + + /* Now we can call cairo_arc() */ + cairo_save (cr); + cairo_translate (cr, cx, cy); + cairo_scale (cr, rx, ry); + cairo_rotate (cr, theta); + if (delta_theta >= 0.0) + cairo_arc (cr, 0, 0, 1, 0, delta_theta); + else + cairo_arc_negative (cr, 0, 0, 1, 0, delta_theta); + cairo_restore (cr); +} + +static void +get_current_point (cairo_svg_glyph_render_t *svg_render, double *x, double *y) +{ + if (cairo_has_current_point (svg_render->cr)) { + cairo_get_current_point (svg_render->cr, x, y); + } else { + *x = 0; + *y = 0; + } +} + +static void +reflect_point (double origin_x, double origin_y, double *x, double *y) +{ + *x = 2*origin_x - *x; + *y = 2*origin_y - *y; +} + +static cairo_bool_t +render_element_path (cairo_svg_glyph_render_t *svg_render, + cairo_svg_element_t *element, + cairo_bool_t end_tag) +{ + double cur_x, cur_y; + double last_cp_x, last_cp_y; + double x, y, x1, y1, x2, y2; + double qx1, qy1, qx2, qy2; + double rx, ry, rotate, large_flag, sweep_flag; + cairo_bool_t rel, have_move; + enum { CUBIC, QUADRATIC, OTHER } last_op; + + if (end_tag || + svg_render->graphics_state->mode == GS_NO_RENDER || + svg_render->build_pattern.type != BUILD_PATTERN_NONE) + return FALSE; + + last_op = OTHER; + const char *p = get_attribute (element, "d"); + const char *end; + int op; + + while (p) { + while (p && _cairo_isspace (*p)) + p++; + + if (!p || *p == 0) + break; + + op = *p; + switch (op) { + case 'M': + case 'm': + rel = op == 'm'; + p++; + have_move = FALSE; + do { + end = get_path_params (p, 2, &x, &y); + if (!end) { + print_warning (svg_render, "path %c expected 2 numbers: %s", op, p); + break; + } + p = end; + if (rel) { + get_current_point (svg_render, &cur_x, &cur_y); + x += cur_x; + y += cur_y; + } + if (!have_move) { + cairo_move_to (svg_render->cr, x, y); + have_move = TRUE; + } else { + cairo_line_to (svg_render->cr, x, y); + } + p = skip_space (p); + } while (p && *p && !_cairo_isalpha(*p)); + last_op = OTHER; + break; + case 'Z': + case 'z': + p++; + cairo_close_path (svg_render->cr); + last_op = OTHER; + break; + case 'L': + case 'l': + rel = op == 'l'; + p++; + do { + end = get_path_params (p, 2, &x, &y); + if (!end) { + print_warning (svg_render, "path %c expected 2 numbers: %s", op, p); + break; + } + p = end; + if (rel) { + get_current_point (svg_render, &cur_x, &cur_y); + x += cur_x; + y += cur_y; + } + cairo_line_to (svg_render->cr, x, y); + p = skip_space (p); + } while (p && *p && !_cairo_isalpha(*p)); + last_op = OTHER; + break; + case 'H': + case 'h': + rel = op == 'h'; + p++; + do { + end = get_path_params (p, 1, &x1); + if (!end) { + print_warning (svg_render, "path %c expected a number: %s", op, p); + break; + } + p = end; + get_current_point (svg_render, &cur_x, &cur_y); + if (rel) { + x1 += cur_x; + } + cairo_line_to (svg_render->cr, x1, cur_y); + p = skip_space (p); + } while (p && *p && !_cairo_isalpha(*p)); + last_op = OTHER; + break; + case 'V': + case 'v': + rel = op == 'v'; + p++; + do { + end = get_path_params (p, 1, &y1); + if (!end) { + print_warning (svg_render, "path %c expected a number: %s", op, p); + break; + } + p = end; + get_current_point (svg_render, &cur_x, &cur_y); + if (rel) { + y1 += cur_y; + } + cairo_line_to (svg_render->cr, cur_x, y1); + p = skip_space (p); + } while (p && *p && !_cairo_isalpha(*p)); + last_op = OTHER; + break; + case 'C': + case 'c': + rel = op == 'c'; + p++; + do { + end = get_path_params (p, 6, &x1, &y1, &x2, &y2, &x, &y); + if (!end) { + print_warning (svg_render, "path %c expected 6 numbers: %s", op, p); + break; + } + p = end; + if (rel) { + get_current_point (svg_render, &cur_x, &cur_y); + x1 += cur_x; + y1 += cur_y; + x2 += cur_x; + y2 += cur_y; + x += cur_x; + y += cur_y; + } + cairo_curve_to (svg_render->cr, x1, y1, x2, y2, x, y); + p = skip_space (p); + } while (p && *p && !_cairo_isalpha(*p)); + last_op = CUBIC; + last_cp_x = x2; + last_cp_y = y2; + break; + case 'S': + case 's': + rel = op == 's'; + p++; + do { + end = get_path_params (p, 4, &x2, &y2, &x, &y); + if (!end) { + print_warning (svg_render, "path %c expected 4 numbers: %s", op, p); + break; + } + p = end; + get_current_point (svg_render, &cur_x, &cur_y); + if (rel) { + x2 += cur_x; + y2 += cur_y; + x += cur_x; + y += cur_y; + } + if (last_op == CUBIC) { + x1 = last_cp_x; + y1 = last_cp_y; + reflect_point (cur_x, cur_y, &x1, &y1); + } else { + x1 = cur_x; + y1 = cur_y; + } + cairo_curve_to (svg_render->cr, x1, y1, x2, y2, x, y); + last_op = CUBIC; + last_cp_x = x2; + last_cp_y = y2; + p = skip_space (p); + } while (p && *p && !_cairo_isalpha(*p)); + break; + case 'Q': + case 'q': + rel = op == 'q'; + p++; + do { + end = get_path_params (p, 4, &x1, &y1, &x, &y); + if (!end) { + print_warning (svg_render, "path %c expected 4 numbers: %s", op, p); + break; + } + p = end; + get_current_point (svg_render, &cur_x, &cur_y); + if (rel) { + x1 += cur_x; + y1 += cur_y; + x += cur_x; + y += cur_y; + } + qx1 = cur_x + (x1 - cur_x)*2/3; + qy1 = cur_y + (y1 - cur_y)*2/3; + qx2 = x + (x1 - x)*2/3; + qy2 = y + (y1 - y)*2/3; + cairo_curve_to (svg_render->cr, qx1, qy1, qx2, qy2, x, y); + p = skip_space (p); + } while (p && *p && !_cairo_isalpha(*p)); + last_op = QUADRATIC; + last_cp_x = x1; + last_cp_y = y1; + break; + case 'T': + case 't': + rel = op == 't'; + p++; + do { + end = get_path_params (p, 2, &x, &y); + if (!end) { + print_warning (svg_render, "path %c expected 2 numbers: %s", op, p); + break; + } + p = end; + get_current_point (svg_render, &cur_x, &cur_y); + if (rel) { + x += cur_x; + y += cur_y; + } + if (last_op == QUADRATIC) { + x1 = last_cp_x; + y1 = last_cp_y; + reflect_point (cur_x, cur_y, &x1, &y1); + } else { + x1 = cur_x; + y1 = cur_y; + } + qx1 = cur_x + (x1 - cur_x)*2/3; + qy1 = cur_y + (y1 - cur_y)*2/3; + qx2 = x + (x1 - x)*2/3; + qy2 = y + (y1 - y)*2/3; + cairo_curve_to (svg_render->cr, qx1, qy1, qx2, qy2, x, y); + last_op = QUADRATIC; + last_cp_x = x1; + last_cp_y = y1; + p = skip_space (p); + } while (p && *p && *p && !_cairo_isalpha(*p)); + break; + case 'A': + case 'a': + rel = op == 'a'; + p++; + do { + end = get_path_params (p, 7, &rx, &ry, &rotate, &large_flag, &sweep_flag, &x, &y); + if (!end) { + print_warning (svg_render, "path %c expected 7 numbers: %s", op, p); + break; + } + p = end; + get_current_point (svg_render, &cur_x, &cur_y); + if (rel) { + x += cur_x; + y += cur_y; + } + arc_path (svg_render->cr, + cur_x, cur_y, + x, y, + rx, ry, + rotate, + large_flag > 0.5, + sweep_flag > 0.5); + p = skip_space (p); + } while (p && *p && !_cairo_isalpha(*p)); + last_op = OTHER; + break; + default: + p = NULL; + break; + } + } + + draw_path (svg_render); + return TRUE; +} + +static void +init_graphics_state (cairo_svg_glyph_render_t *svg_render) +{ + cairo_svg_graphics_state_t *gs; + + gs = _cairo_malloc (sizeof (cairo_svg_graphics_state_t)); + get_paint (svg_render, "black", &gs->fill); + get_paint (svg_render, "none", &gs->stroke); + gs->color.type = FOREGROUND; + gs->fill_opacity = 1.0; + gs->stroke_opacity = 1.0; + gs->opacity = 1.0; + gs->fill_rule = CAIRO_FILL_RULE_WINDING; + gs->clip_rule = CAIRO_FILL_RULE_WINDING; + gs->clip_path = NULL; + gs->dash_array = NULL; + gs->dash_offset = 0.0; + gs->mode = GS_RENDER; + gs->bbox.x = 0; + gs->bbox.y = 0; + gs->bbox.width = 0; + gs->bbox.height = 0; + gs->next = NULL; + + svg_render->graphics_state = gs; + + cairo_save (svg_render->cr); + cairo_set_source_rgb (svg_render->cr, 0, 0, 0); + cairo_set_line_width (svg_render->cr, 1.0); + cairo_set_line_cap (svg_render->cr, CAIRO_LINE_CAP_BUTT); + cairo_set_line_join (svg_render->cr, CAIRO_LINE_JOIN_MITER); + cairo_set_miter_limit (svg_render->cr, 4.0); +} + +#define MAX_DASHES 100 +static void update_dash (cairo_svg_glyph_render_t *svg_render, + cairo_svg_element_t *element) +{ + cairo_svg_graphics_state_t *gs = svg_render->graphics_state; + const char *p; + char *end; + double value; + double dash_array[MAX_DASHES]; + int num_dashes = 0; + cairo_bool_t not_zero = FALSE; + + if (gs->dash_array == NULL || string_equal (gs->dash_array, "none")) { + cairo_set_dash (svg_render->cr, NULL, 0, 0); + return; + } + + p = gs->dash_array; + while (*p && num_dashes < MAX_DASHES) { + while (*p && (*p == ',' || _cairo_isspace (*p))) + p++; + + if (*p == 0) + break; + + value = _cairo_strtod (p, &end); + if (end == p) + break; + + p = end; + if (*p == '%') { + value *= svg_render->width / 100.0; + p++; + } + + if (value < 0.0) + return; + + if (value > 0.0) + not_zero = TRUE; + + dash_array[num_dashes++] = value; + } + + if (not_zero) + cairo_set_dash (svg_render->cr, dash_array, num_dashes, gs->dash_offset); +} + +static cairo_bool_t +pattern_requires_bbox (cairo_svg_glyph_render_t *svg_render, + cairo_svg_element_t *paint_server) +{ + const char *p; + + if (string_equal (paint_server->tag, "linearGradient") || + string_equal (paint_server->tag, "radialGradient")) + { + p = get_attribute (paint_server, "gradientUnits"); + if (string_equal (p, "userSpaceOnUse")) + return FALSE; + + return TRUE; + } + return FALSE; +} + +static cairo_bool_t +clip_requires_bbox (cairo_svg_glyph_render_t *svg_render, + const char *clip_path) +{ + cairo_svg_element_t *element; + const char *p; + + if (clip_path && strncmp (clip_path, "url", 3) == 0) { + element = lookup_url_element (svg_render, clip_path); + if (element) { + p = get_attribute (element, "clipPathUnits"); + if (string_equal (p, "objectBoundingBox")) + return TRUE; + } + } + return FALSE; +} + +static cairo_bool_t +need_bbox (cairo_svg_glyph_render_t *svg_render, + cairo_svg_element_t *element) +{ + cairo_svg_graphics_state_t *gs = svg_render->graphics_state; + cairo_bool_t fill_needs_bbox = FALSE; + cairo_bool_t stroke_needs_bbox = FALSE; + cairo_bool_t clip_needs_bbox = FALSE; + + if (gs->mode != GS_RENDER) + return FALSE; + + if (gs->fill.type == PAINT_SERVER && pattern_requires_bbox (svg_render, gs->fill.paint_server)) + fill_needs_bbox = TRUE; + + if (gs->stroke.type == PAINT_SERVER && pattern_requires_bbox (svg_render, gs->stroke.paint_server)) + stroke_needs_bbox = TRUE; + + if (clip_requires_bbox (svg_render, get_attribute (element, "clip-path"))) + clip_needs_bbox = TRUE; + + if (string_equal (element->tag, "circle") || + string_equal (element->tag, "ellipse") || + string_equal (element->tag, "path") || + string_equal (element->tag, "polygon") || + string_equal (element->tag, "rect")) + { + return fill_needs_bbox || stroke_needs_bbox || clip_needs_bbox; + } + + if (string_equal (element->tag, "line") || + string_equal (element->tag, "polyline")) + { + return stroke_needs_bbox || clip_needs_bbox; + } + + if (string_equal (element->tag, "g") || + string_equal (element->tag, "image") || + string_equal (element->tag, "use")) + { + return clip_needs_bbox; + } + + return FALSE; +} + +static cairo_bool_t +call_element (cairo_svg_glyph_render_t *svg_render, + cairo_svg_element_t *element, + cairo_bool_t end_tag); + +static void +update_graphics_state (cairo_svg_glyph_render_t *svg_render, + cairo_svg_element_t *element) +{ + double value; + const char *p; + cairo_svg_graphics_state_t *gs = svg_render->graphics_state; + + p = get_attribute (element, "transform"); + if (p) { + cairo_matrix_t m; + if (parse_transform (p, &m)) + cairo_transform (svg_render->cr, &m); + } + + /* The transform is all we need for bbox computation. The SVG spec + * excludes clipping and stroke-width from the bbox. */ + if (gs->mode == GS_COMPUTE_BBOX) + return; + + p = get_attribute (element, "color"); + if (p) + get_color (svg_render, p, &gs->color); + + if (!get_float_attribute (element, "opacity", &gs->opacity)) + gs->opacity = 1.0; + + p = get_attribute (element, "fill"); + if (p) { + get_paint (svg_render, p, &gs->fill); + } + + get_float_attribute (element, "fill-opacity", &gs->fill_opacity); + + gs->fill_rule = get_fill_rule_attribute (element, "fill-rule", gs->fill_rule); + + gs->clip_rule = get_fill_rule_attribute (element, "fill-rule", gs->clip_rule); + + p = get_attribute (element, "stroke"); + if (p) + get_paint (svg_render, p, &gs->stroke); + + if (get_float_or_percent_attribute (element, "stroke-width", svg_render->width, &value)) + cairo_set_line_width (svg_render->cr, value); + + p = get_attribute (element, "stroke-linecap"); + if (string_equal (p, "butt")) + cairo_set_line_cap (svg_render->cr, CAIRO_LINE_CAP_BUTT); + else if (string_equal (p, "round")) + cairo_set_line_cap (svg_render->cr, CAIRO_LINE_CAP_ROUND); + else if (string_equal (p, "square")) + cairo_set_line_cap (svg_render->cr, CAIRO_LINE_CAP_SQUARE); + + p = get_attribute (element, "stroke-linejoin"); + if (string_equal (p, "miter")) + cairo_set_line_join (svg_render->cr, CAIRO_LINE_JOIN_MITER); + else if (string_equal (p, "round")) + cairo_set_line_join (svg_render->cr, CAIRO_LINE_JOIN_ROUND); + else if (string_equal (p, "bevel")) + cairo_set_line_join (svg_render->cr, CAIRO_LINE_JOIN_BEVEL); + + if (get_float_attribute (element, "stroke-miterlimit", &value)) + cairo_set_miter_limit (svg_render->cr, value); + + p = get_attribute (element, "stroke-dasharray"); + if (p) { + free (gs->dash_array); + gs->dash_array = strdup (p); + } + + get_float_or_percent_attribute (element, "stroke-dashoffset", svg_render->width, &gs->dash_offset); + update_dash (svg_render, element); + + /* Some elements may need the bounding box of the element thay are + * applied to. As this recursively calls render_element on the + * same element while we are in render_element and setting up the + * graphics state, we check gs->mode to avoid re-entering the + * compute bbox code. The GS_COMPUTE_MODE flag is also used by + * render functions to ignore patterns and strokes (SVG spec + * ignores stroke with in bbox calculations) and just use a solid + * color. + */ + if (gs->mode == GS_RENDER && need_bbox (svg_render, element)) { + cairo_surface_t *recording = cairo_recording_surface_create (CAIRO_CONTENT_COLOR_ALPHA, NULL); + cairo_t *old_cr = svg_render->cr; + svg_render->cr = cairo_create (recording); + gs_mode_t old_mode = gs->mode; + gs->mode = GS_COMPUTE_BBOX; + /* To avoid recursing back into this function, we call the + * element directory then use render_element_tree to render + * the children */ + call_element (svg_render, element, FALSE); + render_element_tree (svg_render, element, NULL, TRUE); + if (element->type == CONTAINER_ELEMENT) + call_element (svg_render, element, TRUE); + gs->mode = old_mode; + cairo_destroy (svg_render->cr); + svg_render->cr = old_cr; + cairo_recording_surface_ink_extents (recording, + &gs->bbox.x, + &gs->bbox.y, + &gs->bbox.width, + &gs->bbox.height); + cairo_surface_destroy (recording); + } + + /* clip-path may require bbox */ + p = get_attribute (element, "clip-path"); + if (p && strncmp (p, "url", 3) == 0) { + element = lookup_url_element (svg_render, p); + if (element) { + gs_mode_t old_mode = gs->mode; + gs->mode = GS_CLIP; + render_element_tree (svg_render, element, NULL, FALSE); + cairo_set_fill_rule (svg_render->cr, gs->clip_rule); + cairo_clip (svg_render->cr); + gs->mode = old_mode; + } + } +} + +static void +save_graphics_state (cairo_svg_glyph_render_t *svg_render) +{ + cairo_svg_graphics_state_t *gs; + + cairo_save (svg_render->cr); + + gs = _cairo_malloc (sizeof (cairo_svg_graphics_state_t)); + gs->fill = svg_render->graphics_state->fill; + gs->stroke = svg_render->graphics_state->stroke; + gs->color = svg_render->graphics_state->color; + gs->fill_opacity = svg_render->graphics_state->fill_opacity; + gs->stroke_opacity = svg_render->graphics_state->stroke_opacity; + gs->opacity = svg_render->graphics_state->opacity; + gs->fill_rule = svg_render->graphics_state->fill_rule; + gs->clip_rule = svg_render->graphics_state->clip_rule; + gs->clip_path = NULL; + gs->dash_array = NULL; + if (svg_render->graphics_state->dash_array) + gs->dash_array = strdup (svg_render->graphics_state->dash_array); + gs->dash_offset = svg_render->graphics_state->dash_offset; + gs->mode = svg_render->graphics_state->mode; + gs->bbox = svg_render->graphics_state->bbox; + gs->next = svg_render->graphics_state; + svg_render->graphics_state = gs; +} + +static void +restore_graphics_state (cairo_svg_glyph_render_t *svg_render) +{ + cairo_svg_graphics_state_t *gs; + + gs = svg_render->graphics_state; + svg_render->graphics_state = gs->next; + if (gs->clip_path) + cairo_path_destroy (gs->clip_path); + free (gs->dash_array); + free (gs); + + cairo_restore (svg_render->cr); +} + +/* render function returns TRUE if render_element_tree() is to render + * the child nodes, FALSE if render_element_tree() is to skip the + * child nodes. + */ +struct render_func { + const char *tag; + cairo_bool_t (*render) (cairo_svg_glyph_render_t *, cairo_svg_element_t *, cairo_bool_t); +}; + +/* Must be sorted */ +static const struct render_func render_funcs[] = { + { "circle", render_element_circle }, + { "clipPath", render_element_clip_path }, + { "defs", NULL }, + { "desc", NULL }, + { "ellipse", render_element_ellipse }, + { "g", render_element_g }, + { "image", render_element_image }, + { "line", render_element_line }, + { "linearGradient", render_element_linear_gradient }, + { "metadata", NULL }, + { "path", render_element_path }, + { "polygon", render_element_polyline }, + { "polyline", render_element_polyline }, + { "radialGradient", render_element_radial_gradient }, + { "rect", render_element_rect }, + { "stop", render_element_stop }, + { "svg", render_element_svg }, + { "title", NULL }, + { "use", render_element_use }, +}; + +static int +_render_func_compare (const void *a, const void *b) +{ + const struct render_func *render_func_a = a; + const struct render_func *render_func_b = b; + + return strcmp (render_func_a->tag, render_func_b->tag); +} + +static cairo_bool_t +call_element (cairo_svg_glyph_render_t *svg_render, + cairo_svg_element_t *element, + cairo_bool_t end_tag) +{ + const struct render_func *func; + struct render_func key; + cairo_bool_t recurse = FALSE; + + key.tag = element->tag; + key.render = NULL; + func = bsearch (&key, + render_funcs, + ARRAY_LENGTH (render_funcs), + sizeof (struct render_func), + _render_func_compare); + if (func) { + if (func->render) { + recurse = func->render (svg_render, element, end_tag); + } + } else { + print_warning (svg_render, "Unsupported element: %s", element->tag); + } + + return recurse; +} + +static cairo_bool_t +render_element (cairo_svg_glyph_render_t *svg_render, + cairo_svg_element_t *element, + cairo_bool_t end_tag, + cairo_svg_element_t *display_element) +{ + cairo_bool_t recurse = FALSE; + cairo_svg_graphics_state_t *gs; + + /* Ignore elements if we have not seen "<svg>". Ignore + * "<svg>" if we have seen it */ + if (svg_render->view_port_set) { + if (string_equal (element->tag, "svg")) + return FALSE; + } else { + if (!string_equal (element->tag, "svg")) + return FALSE; + } + + if (element->type == EMPTY_ELEMENT || + (element->type == CONTAINER_ELEMENT && !end_tag)) + { + save_graphics_state (svg_render); + update_graphics_state (svg_render, element); + } + + gs = svg_render->graphics_state; + if (gs->mode == GS_NO_RENDER && element == display_element) + gs->mode = GS_RENDER; + + recurse = call_element (svg_render, element, end_tag); + + if (element->type == EMPTY_ELEMENT || + (element->type == CONTAINER_ELEMENT && end_tag)) + { + restore_graphics_state (svg_render); + } + + return recurse; +} + +#define MAX_DEPTH 100 + +static void +render_element_tree (cairo_svg_glyph_render_t *svg_render, + cairo_svg_element_t *element, + cairo_svg_element_t *display_element, + cairo_bool_t children_only) +{ + if (!element) + return; + + /* Avoid circular references by limiting the number of recursive + * calls to this function. */ + if (svg_render->render_element_tree_depth > MAX_DEPTH) + return; + + svg_render->render_element_tree_depth++; + if (element->type == EMPTY_ELEMENT && !children_only) { + render_element (svg_render, element, FALSE, display_element); + + } else if (element->type == CONTAINER_ELEMENT) { + int num_elems; + cairo_bool_t recurse = TRUE;; + + if (!children_only) + recurse = render_element (svg_render, element, FALSE, display_element); + + /* We only render the children if the parent returned + * success. This is how we avoid rendering non display + * elements like gradients, <defs>, and anything not + * implemented. */ + if (recurse) { + num_elems = _cairo_array_num_elements (&element->children); + for (int i = 0; i < num_elems; i++) { + cairo_svg_element_t *child; + _cairo_array_copy_element (&element->children, i, &child); + render_element_tree (svg_render, child, display_element, FALSE); + } + } + + if (!children_only) + render_element (svg_render, element, TRUE, display_element); + } + svg_render->render_element_tree_depth--; +} + +static void +render_element_tree_id (cairo_svg_glyph_render_t *svg_render, + const char *element_id) +{ + cairo_svg_element_t *glyph_element = NULL; + + if (element_id) + glyph_element = lookup_element (svg_render, element_id); + + if (glyph_element) + svg_render->graphics_state->mode = GS_NO_RENDER; + else + svg_render->graphics_state->mode = GS_RENDER; + + render_element_tree (svg_render, svg_render->tree, glyph_element, TRUE); +} + +cairo_status_t +_cairo_render_svg_glyph (const char *svg_document, + unsigned long first_glyph, + unsigned long last_glyph, + unsigned long glyph, + double units_per_em, + FT_Color *palette, + int num_palette_entries, + cairo_t *cr, + cairo_pattern_t *foreground_source, + cairo_bool_t *foreground_source_used) +{ + cairo_status_t status = CAIRO_STATUS_SUCCESS; + + cairo_svg_glyph_render_t *svg_render = _cairo_malloc (sizeof (cairo_svg_glyph_render_t)); + if (unlikely (svg_render == NULL)) + return _cairo_error (CAIRO_STATUS_NO_MEMORY); + + svg_render->tree = NULL; + svg_render->ids = _cairo_hash_table_create (_element_id_equal); + if (unlikely (svg_render->ids == NULL)) { + free (svg_render); + return _cairo_error (CAIRO_STATUS_NO_MEMORY); + } + + svg_render->debug = 0; + const char *s = getenv ("CAIRO_DEBUG_SVG_RENDER"); + if (s) { + if (strlen (s) > 0) + svg_render->debug = atoi (s); + else + svg_render->debug = SVG_RENDER_ERROR; + } + + svg_render->cr = cr; + svg_render->units_per_em = units_per_em; + svg_render->build_pattern.paint_server = NULL; + svg_render->build_pattern.pattern = NULL; + svg_render->build_pattern.type = BUILD_PATTERN_NONE; + svg_render->render_element_tree_depth = 0; + svg_render->view_port_set = FALSE; + svg_render->num_palette_entries = num_palette_entries; + svg_render->palette = palette; + + svg_render->foreground_marker = _cairo_pattern_create_foreground_marker (); + svg_render->foreground_source = cairo_pattern_reference (foreground_source);; + svg_render->foreground_source_used = FALSE; + + init_graphics_state (svg_render); + + print_info (svg_render, "Glyph ID: %ld", glyph); + print_info (svg_render, "Palette Entries: %d", num_palette_entries); + print_info (svg_render, "Units per EM: %f", units_per_em); + print_info (svg_render, "SVG Document:\n%s\n", svg_document); + + /* First parse elements into a tree and populate ids hash table */ + if (!parse_svg (svg_render, svg_document)) { + print_error (svg_render, "Parse SVG document failed"); + status = CAIRO_STATUS_SVG_FONT_ERROR; + goto cleanup; + } + +#if SVG_RENDER_PRINT_FUNCTIONS + printf("\nTREE\n"); + if (svg_render->tree) { + print_element (svg_render->tree, TRUE, 0); + printf("\n"); + } +#endif + + /* Next, render glyph */ + if (first_glyph == last_glyph) { + /* Render whole document */ + render_element_tree_id (svg_render, NULL); + } else { + /* Render element with id "glyphID" where ID is glyph number. */ + + char glyph_id[30]; + snprintf(glyph_id, sizeof(glyph_id), "#glyph%ld", glyph); + render_element_tree_id (svg_render, glyph_id); + } + + cleanup: + if (svg_render->build_pattern.pattern) + cairo_pattern_destroy (svg_render->build_pattern.pattern); + + if (svg_render->tree) + free_elements (svg_render, svg_render->tree); + + while (svg_render->graphics_state) + restore_graphics_state (svg_render); + + cairo_pattern_destroy (svg_render->foreground_marker); + cairo_pattern_destroy (svg_render->foreground_source); + *foreground_source_used = svg_render->foreground_source_used; + + /* The hash entry for each element with an id is removed by + * free_elements() */ + _cairo_hash_table_destroy (svg_render->ids); + + free (svg_render); + + return status; +} + +#ifdef DEBUG_SVG_RENDER + +/** + * _cairo_debug_svg_render: + * + * Debug function for cairo-svg-glyph-render.c. Allows invoking the renderer from outside + * cairo to test with SVG documents, and to facilitate comparison with librsvg rendering. + * The viewport is . + * + * @cr: render target + * @svg_document: SVG Document + * @element: element within svg_document to render (eg "#glyph8"), or NULL to render entire document. + * @debug_level: 0 - quiet, 1 - print errors, 2 - print warnings, 3 - info + * @return TRUE on success, ie no errors, FALSE if error + **/ +cairo_bool_t +_cairo_debug_svg_render (cairo_t *cr, + const char *svg_document, + const char *element, + double units_per_em, + int debug_level); + +cairo_bool_t +_cairo_debug_svg_render (cairo_t *cr, + const char *svg_document, + const char *element, + double units_per_em, + int debug_level) +{ + cairo_status_t status; + cairo_bool_t foreground_source_used; + cairo_pattern_t *foreground = _cairo_pattern_create_foreground_marker (); + + status = _cairo_render_svg_glyph (svg_document, + 1, 1, 1, + units_per_em, + NULL, 0, + cr, + foreground, + &foreground_source_used); + cairo_pattern_destroy (foreground); + + return status == CAIRO_STATUS_SUCCESS; +} + +#endif /* DEBUG_SVG_RENDER */ + +#endif /* HAVE_FT_SVG_DOCUMENT */ diff --git a/gfx/cairo/cairo/src/cairo-svg-surface-private.h b/gfx/cairo/cairo/src/cairo-svg-surface-private.h index 6f693252a8..e2a194081b 100644 --- a/gfx/cairo/cairo/src/cairo-svg-surface-private.h +++ b/gfx/cairo/cairo/src/cairo-svg-surface-private.h @@ -44,40 +44,20 @@ #include "cairo-svg.h" #include "cairo-surface-private.h" -#include "cairo-surface-clipper-private.h" -typedef struct cairo_svg_document cairo_svg_document_t; - -typedef struct _cairo_svg_source_surface { - cairo_hash_entry_t base; - unsigned int id; - unsigned char *unique_id; - unsigned long unique_id_length; -} cairo_svg_source_surface_t; - -typedef struct cairo_svg_surface { +struct _cairo_svg_surface_start { cairo_surface_t base; - cairo_content_t content; - - double width; - double height; - cairo_bool_t surface_bounded; - - cairo_svg_document_t *document; - - cairo_output_stream_t *xml_node; - cairo_array_t page_set; - cairo_hash_table_t *source_surfaces; - - cairo_surface_clipper_t clipper; - unsigned int clip_level; - unsigned int base_clip; - cairo_bool_t is_base_clip_emitted; + cairo_bool_t force_fallbacks; +}; - cairo_paginated_mode_t paginated_mode; +static inline void +_cairo_svg_surface_set_force_fallbacks (void *abstract_surface, + cairo_bool_t force_fallbacks) +{ + struct _cairo_svg_surface_start *surface = (struct _cairo_svg_surface_start *) abstract_surface; - cairo_bool_t force_fallbacks; -} cairo_svg_surface_t; + surface->force_fallbacks = force_fallbacks; +} #endif /* CAIRO_SVG_SURFACE_PRIVATE_H */ diff --git a/gfx/cairo/cairo/src/cairo-svg-surface.c b/gfx/cairo/cairo/src/cairo-svg-surface.c index 7e7051eb68..b7212a5478 100644 --- a/gfx/cairo/cairo/src/cairo-svg-surface.c +++ b/gfx/cairo/cairo/src/cairo-svg-surface.c @@ -4,6 +4,7 @@ * Copyright © 2004 Red Hat, Inc * Copyright © 2005-2007 Emmanuel Pacaud <emmanuel.pacaud@free.fr> * Copyright © 2006 Red Hat, Inc + * Copyright © 2020-2021 Anton Danilkin <afdw@yandex.ru> * * This library is free software; you can redistribute it and/or * modify it either under the terms of the GNU Lesser General Public @@ -37,22 +38,20 @@ * Kristian Høgsberg <krh@redhat.com> * Emmanuel Pacaud <emmanuel.pacaud@free.fr> * Carl Worth <cworth@cworth.org> + * Anton Danilkin <afdw@yandex.ru> */ -#define _DEFAULT_SOURCE /* for snprintf() */ #include "cairoint.h" #include "cairo-svg.h" #include "cairo-array-private.h" -#include "cairo-analysis-surface-private.h" #include "cairo-default-context-private.h" #include "cairo-error-private.h" #include "cairo-image-info-private.h" #include "cairo-image-surface-private.h" #include "cairo-recording-surface-inline.h" #include "cairo-output-stream-private.h" -#include "cairo-path-fixed-private.h" #include "cairo-paginated-private.h" #include "cairo-scaled-font-subsets-private.h" #include "cairo-surface-clipper-private.h" @@ -69,6 +68,333 @@ * SVG files and is a multi-page vector surface backend. **/ +typedef struct _cairo_svg_source_surface { + cairo_hash_entry_t base; + unsigned int id; + unsigned char *unique_id; + unsigned long unique_id_length; + cairo_bool_t transitive_paint_used; +} cairo_svg_source_surface_t; + +/* + * _cairo_svg_paint_element and _cairo_svg_paint are used to implement paints in transformed recording patterns. + */ + +typedef struct _cairo_svg_paint_element { + unsigned int source_id; + cairo_matrix_t matrix; +} cairo_svg_paint_element_t; + +typedef struct _cairo_svg_paint { + cairo_hash_entry_t base; + unsigned int source_id; + cairo_array_t paint_elements; + cairo_box_double_t box; +} cairo_svg_paint_t; + +static void +_cairo_svg_source_surface_init_key (cairo_svg_source_surface_t *source_surface) +{ + if (source_surface->unique_id && source_surface->unique_id_length > 0) { + source_surface->base.hash = _cairo_hash_bytes (_CAIRO_HASH_INIT_VALUE, + source_surface->unique_id, + source_surface->unique_id_length); + } else { + source_surface->base.hash = source_surface->id; + } +} + +static cairo_bool_t +_cairo_svg_source_surface_equal (const void *key_a, const void *key_b) +{ + const cairo_svg_source_surface_t *a = key_a; + const cairo_svg_source_surface_t *b = key_b; + + if (a->unique_id && b->unique_id && a->unique_id_length == b->unique_id_length) { + return memcmp (a->unique_id, b->unique_id, a->unique_id_length) == 0; + } + + return a->id == b->id; +} + +static void +_cairo_svg_source_surface_pluck (void *entry, void *closure) +{ + cairo_svg_source_surface_t *source_surface = entry; + cairo_hash_table_t *patterns = closure; + + _cairo_hash_table_remove (patterns, &source_surface->base); + free (source_surface->unique_id); + free (source_surface); +} + +static void +_cairo_svg_paint_init_key (cairo_svg_paint_t *paint) +{ + paint->base.hash = paint->source_id; +} + +static cairo_bool_t +_cairo_svg_paint_equal (const void *key_a, const void *key_b) +{ + const cairo_svg_paint_t *a = key_a; + const cairo_svg_paint_t *b = key_b; + + return a->source_id == b->source_id; +} + +static void +_cairo_svg_paint_pluck (void *entry, void *closure) +{ + cairo_svg_paint_t *paint = entry; + cairo_hash_table_t *patterns = closure; + + _cairo_hash_table_remove (patterns, &paint->base); + _cairo_array_fini (&paint->paint_elements); + free (paint); +} + +static void +_cairo_svg_paint_box_add_padding (cairo_box_double_t *box) +{ + double width = box->p2.x - box->p1.x; + double height = box->p2.y - box->p1.y; + + box->p1.x -= width / 10.0; + box->p1.y -= height / 10.0; + box->p2.x += width / 10.0; + box->p2.y += height / 10.0; +} + +enum cairo_svg_stream_element_type { + CAIRO_SVG_STREAM_ELEMENT_TYPE_TEXT, + CAIRO_SVG_STREAM_ELEMENT_TYPE_PAINT_DEPENDENT, +}; + +enum cairo_svg_stream_paint_dependent_element_type { + CAIRO_SVG_STREAM_PAINT_DEPENDENT_ELEMENT_TYPE_RECTANGLE, + CAIRO_SVG_STREAM_PAINT_DEPENDENT_ELEMENT_TYPE_RECTANGLE_AT_ORIGIN, + CAIRO_SVG_STREAM_PAINT_DEPENDENT_ELEMENT_TYPE_TRANSLATION, + CAIRO_SVG_STREAM_PAINT_DEPENDENT_ELEMENT_TYPE_INVERSE_TRANSLATION, +}; + +typedef struct _cairo_svg_stream_element { + enum cairo_svg_stream_element_type type; + union { + struct { + cairo_output_stream_t *output_stream; + } text; + struct { + unsigned int source_id; + enum cairo_svg_stream_paint_dependent_element_type type; + } paint_dependent; + }; +} cairo_svg_stream_element_t; + +typedef struct _cairo_svg_stream { + cairo_status_t status; + cairo_array_t elements; +} cairo_svg_stream_t; + +static cairo_svg_stream_t +_cairo_svg_stream_create () +{ + cairo_svg_stream_t svg_stream; + svg_stream.status = CAIRO_STATUS_SUCCESS; + _cairo_array_init (&svg_stream.elements, sizeof (cairo_svg_stream_element_t)); + return svg_stream; +} + +static void +_cairo_svg_stream_write (cairo_svg_stream_t *svg_stream, + const void *data, + size_t length) +{ + cairo_status_t status; + + cairo_svg_stream_element_t *last_element = NULL; + if (svg_stream->elements.num_elements > 0) { + last_element = _cairo_array_index (&svg_stream->elements, + svg_stream->elements.num_elements - 1); + } + + if (last_element == NULL || last_element->type != CAIRO_SVG_STREAM_ELEMENT_TYPE_TEXT) { + cairo_svg_stream_element_t element; + element.type = CAIRO_SVG_STREAM_ELEMENT_TYPE_TEXT; + element.text.output_stream = _cairo_memory_stream_create(); + status = _cairo_array_append (&svg_stream->elements, &element); + if (unlikely (status)) { + if (svg_stream->status == CAIRO_STATUS_SUCCESS) { + svg_stream->status = status; + } + return; + } + last_element = _cairo_array_index (&svg_stream->elements, + svg_stream->elements.num_elements - 1); + } + + _cairo_output_stream_write (last_element->text.output_stream, data, length); +} + +static void CAIRO_PRINTF_FORMAT (2, 0) +_cairo_svg_stream_printf (cairo_svg_stream_t *svg_stream, + const char *fmt, + ...) +{ + cairo_status_t status; + + cairo_svg_stream_element_t *last_element = NULL; + if (svg_stream->elements.num_elements > 0) { + last_element = _cairo_array_index (&svg_stream->elements, + svg_stream->elements.num_elements - 1); + } + + if (last_element == NULL || last_element->type != CAIRO_SVG_STREAM_ELEMENT_TYPE_TEXT) { + cairo_svg_stream_element_t element; + element.type = CAIRO_SVG_STREAM_ELEMENT_TYPE_TEXT; + element.text.output_stream = _cairo_memory_stream_create(); + status = _cairo_array_append (&svg_stream->elements, &element); + if (unlikely (status)) { + if (svg_stream->status == CAIRO_STATUS_SUCCESS) { + svg_stream->status = status; + } + return; + } + last_element = _cairo_array_index (&svg_stream->elements, + svg_stream->elements.num_elements - 1); + } + + va_list ap; + va_start (ap, fmt); + _cairo_output_stream_vprintf (last_element->text.output_stream, fmt, ap); + va_end (ap); +} + +static void +_cairo_svg_stream_append_paint_dependent (cairo_svg_stream_t *svg_stream, + unsigned int source_id, + enum cairo_svg_stream_paint_dependent_element_type type) +{ + cairo_status_t status; + + cairo_svg_stream_element_t element; + element.type = CAIRO_SVG_STREAM_ELEMENT_TYPE_PAINT_DEPENDENT; + element.paint_dependent.source_id = source_id; + element.paint_dependent.type = type; + status = _cairo_array_append (&svg_stream->elements, &element); + if (svg_stream->status == CAIRO_STATUS_SUCCESS) { + svg_stream->status = status; + } +} + +static void +_cairo_svg_stream_copy (cairo_svg_stream_t *from, + cairo_svg_stream_t *to) +{ + cairo_status_t status; + + if (unlikely (from->status)) { + if (to->status == CAIRO_STATUS_SUCCESS) { + to->status = from->status; + } + return; + } + + for (unsigned int i = 0; i < from->elements.num_elements; i++) { + cairo_svg_stream_element_t *element = _cairo_array_index (&from->elements, i); + cairo_svg_stream_element_t element_copy = *element; + if (element->type == CAIRO_SVG_STREAM_ELEMENT_TYPE_TEXT) { + element_copy.text.output_stream = _cairo_memory_stream_create (); + _cairo_memory_stream_copy (element->text.output_stream, element_copy.text.output_stream); + if (to->status == CAIRO_STATUS_SUCCESS) { + to->status = element->text.output_stream->status; + } + } + status = _cairo_array_append (&to->elements, &element_copy); + if (unlikely (status)) { + if (to->status == CAIRO_STATUS_SUCCESS) { + to->status = status; + } + return; + } + } +} + +static void +_cairo_svg_stream_copy_to_output_stream (cairo_svg_stream_t *from, + cairo_output_stream_t *to, + cairo_hash_table_t *paints) +{ + if (unlikely (from->status)) { + if (to->status == CAIRO_STATUS_SUCCESS) { + to->status = from->status; + } + return; + } + + for (unsigned int i = 0; i < from->elements.num_elements; i++) { + cairo_svg_stream_element_t *element = _cairo_array_index (&from->elements, i); + if (element->type == CAIRO_SVG_STREAM_ELEMENT_TYPE_TEXT) { + _cairo_memory_stream_copy (element->text.output_stream, to); + } + if (element->type == CAIRO_SVG_STREAM_ELEMENT_TYPE_PAINT_DEPENDENT) { + cairo_svg_paint_t paint_key; + paint_key.source_id = element->paint_dependent.source_id; + _cairo_svg_paint_init_key (&paint_key); + + cairo_svg_paint_t *found_paint_entry = _cairo_hash_table_lookup (paints, + &paint_key.base); + assert (found_paint_entry); + + switch (element->paint_dependent.type) { + case CAIRO_SVG_STREAM_PAINT_DEPENDENT_ELEMENT_TYPE_RECTANGLE: + _cairo_output_stream_printf (to, + " x=\"%f\" y=\"%f\" width=\"%f\" height=\"%f\"", + found_paint_entry->box.p1.x, + found_paint_entry->box.p1.y, + found_paint_entry->box.p2.x - found_paint_entry->box.p1.x, + found_paint_entry->box.p2.y - found_paint_entry->box.p1.y); + break; + case CAIRO_SVG_STREAM_PAINT_DEPENDENT_ELEMENT_TYPE_RECTANGLE_AT_ORIGIN: + _cairo_output_stream_printf (to, + " x=\"0\" y=\"0\" width=\"%f\" height=\"%f\"", + found_paint_entry->box.p2.x - found_paint_entry->box.p1.x, + found_paint_entry->box.p2.y - found_paint_entry->box.p1.y); + break; + case CAIRO_SVG_STREAM_PAINT_DEPENDENT_ELEMENT_TYPE_TRANSLATION: + _cairo_output_stream_printf (to, + " transform=\"translate(%f, %f)\"", + found_paint_entry->box.p1.x, + found_paint_entry->box.p1.y); + break; + case CAIRO_SVG_STREAM_PAINT_DEPENDENT_ELEMENT_TYPE_INVERSE_TRANSLATION: + _cairo_output_stream_printf (to, + " transform=\"translate(%f, %f)\"", + -found_paint_entry->box.p1.x, + -found_paint_entry->box.p1.y); + break; + } + } + } +} + +static cairo_status_t +_cairo_svg_stream_destroy (cairo_svg_stream_t *svg_stream) +{ + cairo_status_t status = svg_stream->status; + for (unsigned int i = 0; i < svg_stream->elements.num_elements; i++) { + cairo_svg_stream_element_t *element = _cairo_array_index (&svg_stream->elements, i); + if (element->type == CAIRO_SVG_STREAM_ELEMENT_TYPE_TEXT) { + cairo_status_t element_status = _cairo_output_stream_destroy (element->text.output_stream); + if (status == CAIRO_STATUS_SUCCESS) { + status = element_status; + } + } + } + _cairo_array_fini (&svg_stream->elements); + return status; +} + /** * CAIRO_HAS_SVG_SURFACE: * @@ -78,9 +404,7 @@ * Since: 1.2 **/ -typedef struct cairo_svg_page cairo_svg_page_t; - -static const int invalid_pattern_id = -1; +static const unsigned int invalid_pattern_id = -1; static const cairo_svg_version_t _cairo_svg_versions[] = { @@ -100,15 +424,9 @@ static const char *_cairo_svg_supported_mime_types[] = }; static void -_cairo_svg_surface_emit_path (cairo_output_stream_t *output, - const cairo_path_fixed_t *path, - const cairo_matrix_t *ctm_inverse); - -static cairo_bool_t -_cairo_svg_version_has_page_set_support (cairo_svg_version_t version) -{ - return version > CAIRO_SVG_VERSION_1_1; -} +_cairo_svg_surface_emit_path (cairo_svg_stream_t *output, + const cairo_path_fixed_t *path, + const cairo_matrix_t *ctm_inverse); static const char * _cairo_svg_version_strings[CAIRO_SVG_VERSION_LAST] = { @@ -116,12 +434,6 @@ static const char * _cairo_svg_version_strings[CAIRO_SVG_VERSION_LAST] = "SVG 1.2" }; -static const char * _cairo_svg_internal_version_strings[CAIRO_SVG_VERSION_LAST] = -{ - "1.1", - "1.2" -}; - static const char * _cairo_svg_unit_strings[] = { "", @@ -136,13 +448,39 @@ static const char * _cairo_svg_unit_strings[] = "%" }; -struct cairo_svg_page { - unsigned int surface_id; - unsigned int clip_level; - cairo_output_stream_t *xml_node; +enum cairo_svg_filter { + CAIRO_SVG_FILTER_REMOVE_COLOR, + CAIRO_SVG_FILTER_REMOVE_COLOR_AND_INVERT_ALPHA, + CAIRO_SVG_FILTER_COLOR_TO_ALPHA, + CAIRO_SVG_FILTER_LAST_STATIC_FILTER, + CAIRO_SVG_FILTER_OVER, + CAIRO_SVG_FILTER_IN, + CAIRO_SVG_FILTER_OUT, + CAIRO_SVG_FILTER_ATOP, + CAIRO_SVG_FILTER_XOR, + CAIRO_SVG_FILTER_ADD, + CAIRO_SVG_FILTER_MULTIPLY, + CAIRO_SVG_FILTER_SCREEN, + CAIRO_SVG_FILTER_OVERLAY, + CAIRO_SVG_FILTER_DARKEN, + CAIRO_SVG_FILTER_LIGHTEN, + CAIRO_SVG_FILTER_COLOR_DODGE, + CAIRO_SVG_FILTER_COLOR_BURN, + CAIRO_SVG_FILTER_HARD_LIGHT, + CAIRO_SVG_FILTER_SOFT_LIGHT, + CAIRO_SVG_FILTER_DIFFERENCE, + CAIRO_SVG_FILTER_EXCLUSION, + CAIRO_SVG_FILTER_HUE, + CAIRO_SVG_FILTER_SATURATION, + CAIRO_SVG_FILTER_COLOR, + CAIRO_SVG_FILTER_LUMINOSITY, }; -struct cairo_svg_document { +typedef struct _cairo_svg_page { + cairo_svg_stream_t xml_node; +} cairo_svg_page_t; + +typedef struct _cairo_svg_document { cairo_output_stream_t *output_stream; unsigned long refcount; cairo_surface_t *owner; @@ -152,29 +490,62 @@ struct cairo_svg_document { double height; cairo_svg_unit_t unit; - cairo_output_stream_t *xml_node_defs; - cairo_output_stream_t *xml_node_glyphs; + cairo_svg_stream_t xml_node_defs; + cairo_svg_stream_t xml_node_glyphs; + cairo_svg_stream_t xml_node_filters; unsigned int linear_pattern_id; unsigned int radial_pattern_id; unsigned int pattern_id; - unsigned int filter_id; unsigned int clip_id; unsigned int mask_id; + unsigned int compositing_group_id; + unsigned int filter_id; - cairo_bool_t alpha_filter; + cairo_bool_t filters_emitted[CAIRO_SVG_FILTER_LAST_STATIC_FILTER]; cairo_svg_version_t svg_version; cairo_scaled_font_subsets_t *font_subsets; -}; + + cairo_hash_table_t *paints; +} cairo_svg_document_t; + +// Must be compatible with the struct _cairo_svg_surface_start. +typedef struct _cairo_svg_surface { + cairo_surface_t base; + + cairo_bool_t force_fallbacks; + + unsigned int source_id; + unsigned int depth; + + double width; + double height; + cairo_bool_t surface_bounded; + + cairo_svg_document_t *document; + + cairo_svg_stream_t xml_node; + cairo_array_t page_set; + + cairo_hash_table_t *source_surfaces; + + cairo_surface_clipper_t clipper; + cairo_svg_stream_t *current_clipper_stream; + unsigned int clip_level; + + cairo_bool_t transitive_paint_used; + + cairo_paginated_mode_t paginated_mode; +} cairo_svg_surface_t; static cairo_status_t -_cairo_svg_document_create (cairo_output_stream_t *stream, - double width, - double height, - cairo_svg_version_t version, - cairo_svg_document_t **document_out); +_cairo_svg_document_create (cairo_output_stream_t *stream, + double width, + double height, + cairo_svg_version_t version, + cairo_svg_document_t **document_out); static cairo_status_t _cairo_svg_document_destroy (cairo_svg_document_t *document); @@ -185,21 +556,31 @@ _cairo_svg_document_finish (cairo_svg_document_t *document); static cairo_svg_document_t * _cairo_svg_document_reference (cairo_svg_document_t *document); -static unsigned int -_cairo_svg_document_allocate_mask_id (cairo_svg_document_t *document); - static cairo_surface_t * -_cairo_svg_surface_create_for_document (cairo_svg_document_t *document, - cairo_content_t content, - double width, - double height, - cairo_bool_t bounded); +_cairo_svg_surface_create_for_document (cairo_svg_document_t *document, + cairo_content_t content, + double width, + double height, + cairo_bool_t bounded); static cairo_surface_t * -_cairo_svg_surface_create_for_stream_internal (cairo_output_stream_t *stream, - double width, - double height, - cairo_svg_version_t version); +_cairo_svg_surface_create_for_stream_internal (cairo_output_stream_t *stream, + double width, + double height, + cairo_svg_version_t version); + +static cairo_status_t +_cairo_svg_surface_emit_composite_pattern (cairo_svg_stream_t *output, + cairo_svg_surface_t *surface, + cairo_surface_pattern_t *pattern, + unsigned int pattern_id, + const cairo_matrix_t *parent_matrix); + +static cairo_status_t +_cairo_svg_surface_emit_paint (cairo_svg_stream_t *output, + cairo_svg_surface_t *surface, + const cairo_pattern_t *source, + cairo_bool_t at_origin); static const cairo_surface_backend_t cairo_svg_surface_backend; static const cairo_paginated_surface_backend_t cairo_svg_surface_paginated_backend; @@ -308,41 +689,35 @@ _cairo_surface_is_svg (cairo_surface_t *surface) * target. Otherwise return FALSE. */ static cairo_bool_t -_extract_svg_surface (cairo_surface_t *surface, - cairo_svg_surface_t **svg_surface) +_extract_svg_surface (cairo_surface_t *surface, + cairo_svg_surface_t **svg_surface) { cairo_surface_t *target; - cairo_status_t status_ignored; if (surface->status) return FALSE; if (surface->finished) { - status_ignored = _cairo_surface_set_error (surface, - _cairo_error (CAIRO_STATUS_SURFACE_FINISHED)); - return FALSE; + (void) _cairo_surface_set_error (surface, _cairo_error (CAIRO_STATUS_SURFACE_FINISHED)); + return FALSE; } - if (! _cairo_surface_is_paginated (surface)) { - status_ignored = _cairo_surface_set_error (surface, - _cairo_error (CAIRO_STATUS_SURFACE_TYPE_MISMATCH)); + if (!_cairo_surface_is_paginated (surface)) { + (void) _cairo_surface_set_error (surface, _cairo_error (CAIRO_STATUS_SURFACE_TYPE_MISMATCH)); return FALSE; } target = _cairo_paginated_surface_get_target (surface); if (target->status) { - status_ignored = _cairo_surface_set_error (surface, - target->status); + (void) _cairo_surface_set_error (surface, target->status); return FALSE; } if (target->finished) { - status_ignored = _cairo_surface_set_error (surface, - _cairo_error (CAIRO_STATUS_SURFACE_FINISHED)); - return FALSE; + (void) _cairo_surface_set_error (surface, _cairo_error (CAIRO_STATUS_SURFACE_FINISHED)); + return FALSE; } - if (! _cairo_surface_is_svg (target)) { - status_ignored = _cairo_surface_set_error (surface, - _cairo_error (CAIRO_STATUS_SURFACE_TYPE_MISMATCH)); + if (!_cairo_surface_is_svg (target)) { + (void) _cairo_surface_set_error (surface, _cairo_error (CAIRO_STATUS_SURFACE_TYPE_MISMATCH)); return FALSE; } @@ -369,7 +744,7 @@ void cairo_svg_surface_restrict_to_version (cairo_surface_t *abstract_surface, cairo_svg_version_t version) { - cairo_svg_surface_t *surface = NULL; /* hide compiler warning */ + cairo_svg_surface_t *surface; if (! _extract_svg_surface (abstract_surface, &surface)) return; @@ -439,7 +814,7 @@ cairo_svg_version_to_string (cairo_svg_version_t version) * creating the SVG surface. * * Note if this function is never called, the default unit for SVG documents - * generated by cairo will be "pt". This is for historical reasons. + * generated by cairo will be user unit. * * Since: 1.16 **/ @@ -447,7 +822,7 @@ void cairo_svg_surface_set_document_unit (cairo_surface_t *abstract_surface, cairo_svg_unit_t unit) { - cairo_svg_surface_t *surface = NULL; /* hide compiler warning */ + cairo_svg_surface_t *surface; if (! _extract_svg_surface (abstract_surface, &surface)) return; @@ -473,7 +848,7 @@ cairo_svg_surface_set_document_unit (cairo_surface_t *abstract_surface, cairo_svg_unit_t cairo_svg_surface_get_document_unit (cairo_surface_t *abstract_surface) { - cairo_svg_surface_t *surface = NULL; /* hide compiler warning */ + cairo_svg_surface_t *surface; if (! _extract_svg_surface (abstract_surface, &surface)) { _cairo_error_throw (CAIRO_STATUS_SURFACE_TYPE_MISMATCH); @@ -484,160 +859,165 @@ cairo_svg_surface_get_document_unit (cairo_surface_t *abstract_surface) } static void -_cairo_svg_source_surface_init_key (cairo_svg_source_surface_t *key) -{ - if (key->unique_id && key->unique_id_length > 0) { - key->base.hash = _cairo_hash_bytes (_CAIRO_HASH_INIT_VALUE, - key->unique_id, key->unique_id_length); - } else { - key->base.hash = key->id; - } -} +_cairo_svg_paint_compute (cairo_svg_document_t *document, cairo_svg_paint_t *paint) { + for (unsigned int i = 0; i < paint->paint_elements.num_elements; i++) { + cairo_svg_paint_element_t *paint_element = _cairo_array_index (&paint->paint_elements, i); -static cairo_bool_t -_cairo_svg_source_surface_equal (const void *key_a, const void *key_b) -{ - const cairo_svg_source_surface_t *a = key_a; - const cairo_svg_source_surface_t *b = key_b; + cairo_svg_paint_t paint_key; + paint_key.source_id = paint_element->source_id; + _cairo_svg_paint_init_key (&paint_key); + + cairo_svg_paint_t *found_paint_entry = _cairo_hash_table_lookup (document->paints, + &paint_key.base); + assert (found_paint_entry); - if (a->unique_id && b->unique_id && a->unique_id_length == b->unique_id_length) - return (memcmp (a->unique_id, b->unique_id, a->unique_id_length) == 0); + _cairo_svg_paint_compute (document, found_paint_entry); - return (a->id == b->id); + cairo_box_double_t box = found_paint_entry->box; + _cairo_matrix_transform_bounding_box (&paint_element->matrix, + &box.p1.x, &box.p1.y, + &box.p2.x, &box.p2.y, + NULL); + _cairo_svg_paint_box_add_padding (&box); + + if (i == 0) { + paint->box = box; + } else { + paint->box.p1.x = MIN (paint->box.p1.x, box.p1.x); + paint->box.p1.y = MIN (paint->box.p1.y, box.p1.y); + paint->box.p2.x = MAX (paint->box.p2.x, box.p2.x); + paint->box.p2.y = MAX (paint->box.p2.y, box.p2.y); + } + } + _cairo_array_truncate (&paint->paint_elements, 0); } static void -_cairo_svg_source_surface_pluck (void *entry, void *closure) +_cairo_svg_paint_compute_func (void *entry, void *closure) { - cairo_svg_source_surface_t *surface_entry = entry; - cairo_hash_table_t *patterns = closure; + cairo_svg_paint_t *paint = entry; + cairo_svg_document_t *document = closure; - _cairo_hash_table_remove (patterns, &surface_entry->base); - free (surface_entry->unique_id); - free (surface_entry); + _cairo_svg_paint_compute (document, paint); } static cairo_status_t -_cairo_svg_surface_add_source_surface (cairo_svg_surface_t *surface, - cairo_surface_t *source_surface, - int *source_id, - cairo_bool_t *is_new) +_cairo_svg_surface_add_source_surface (cairo_svg_surface_t *surface, + cairo_surface_t *source_surface, + cairo_bool_t *is_new, + cairo_svg_source_surface_t **result_source_surface) { - cairo_svg_source_surface_t source_key; - cairo_svg_source_surface_t *source_entry; - unsigned char *unique_id = NULL; - unsigned long unique_id_length = 0; cairo_status_t status; - source_key.id = source_surface->unique_id; - cairo_surface_get_mime_data (source_surface, CAIRO_MIME_TYPE_UNIQUE_ID, - (const unsigned char **) &source_key.unique_id, - &source_key.unique_id_length); - _cairo_svg_source_surface_init_key (&source_key); - source_entry = _cairo_hash_table_lookup (surface->source_surfaces, &source_key.base); - if (source_entry) { - *source_id = source_entry->id; + cairo_svg_source_surface_t source_surface_key; + source_surface_key.id = source_surface->unique_id; + cairo_surface_get_mime_data (source_surface, + CAIRO_MIME_TYPE_UNIQUE_ID, + (const unsigned char **) &source_surface_key.unique_id, + &source_surface_key.unique_id_length); + _cairo_svg_source_surface_init_key (&source_surface_key); + + cairo_svg_source_surface_t *found_source_surface_entry = _cairo_hash_table_lookup (surface->source_surfaces, + &source_surface_key.base); + if (found_source_surface_entry) { *is_new = FALSE; + *result_source_surface = found_source_surface_entry; return CAIRO_STATUS_SUCCESS; } - if (source_key.unique_id && source_key.unique_id_length > 0) { - unique_id = _cairo_malloc (source_key.unique_id_length); + unsigned char *unique_id = NULL; + unsigned long unique_id_length = 0; + if (source_surface_key.unique_id && source_surface_key.unique_id_length > 0) { + unique_id = _cairo_malloc (source_surface_key.unique_id_length); if (unique_id == NULL) { return _cairo_error (CAIRO_STATUS_NO_MEMORY); } - unique_id_length = source_key.unique_id_length; - memcpy (unique_id, source_key.unique_id, unique_id_length); + unique_id_length = source_surface_key.unique_id_length; + memcpy (unique_id, source_surface_key.unique_id, unique_id_length); } else { unique_id = NULL; unique_id_length = 0; } - source_entry = malloc (sizeof (cairo_svg_source_surface_t)); - if (source_entry == NULL) { + cairo_svg_source_surface_t *source_surface_entry = malloc (sizeof (cairo_svg_source_surface_t)); + if (source_surface_entry == NULL) { status = _cairo_error (CAIRO_STATUS_NO_MEMORY); goto fail; } - - source_entry->id = source_key.id; - source_entry->unique_id_length = unique_id_length; - source_entry->unique_id = unique_id; - _cairo_svg_source_surface_init_key (source_entry); - status = _cairo_hash_table_insert (surface->source_surfaces, &source_entry->base); - if (unlikely(status)) + source_surface_entry->id = source_surface_key.id; + source_surface_entry->unique_id_length = unique_id_length; + source_surface_entry->unique_id = unique_id; + _cairo_svg_source_surface_init_key (source_surface_entry); + status = _cairo_hash_table_insert (surface->source_surfaces, &source_surface_entry->base); + if (unlikely (status)) { goto fail; + } *is_new = TRUE; - *source_id = source_entry->id; + *result_source_surface = source_surface_entry; return CAIRO_STATUS_SUCCESS; - fail: + fail: free (unique_id); - free (source_entry); + free (source_surface_entry); return status; } static cairo_bool_t -_cliprect_covers_surface (cairo_svg_surface_t *surface, - cairo_path_fixed_t *path) +_cairo_svg_surface_cliprect_covers_surface (cairo_svg_surface_t *surface, + cairo_path_fixed_t *path) { cairo_box_t box; - if (_cairo_path_fixed_is_box (path, &box)) { - if (box.p1.x <= 0 && - box.p1.y <= 0 && - _cairo_fixed_to_double (box.p2.x) >= surface->width && - _cairo_fixed_to_double (box.p2.y) >= surface->height) - { - return TRUE; - } - } - - return FALSE; + return surface->surface_bounded && + _cairo_path_fixed_is_box (path, &box) && + box.p1.x <= 0 && + box.p1.y <= 0 && + _cairo_fixed_to_double (box.p2.x) >= surface->width && + _cairo_fixed_to_double (box.p2.y) >= surface->height; } static cairo_status_t _cairo_svg_surface_clipper_intersect_clip_path (cairo_surface_clipper_t *clipper, - cairo_path_fixed_t *path, - cairo_fill_rule_t fill_rule, - double tolerance, - cairo_antialias_t antialias) + cairo_path_fixed_t *path, + cairo_fill_rule_t fill_rule, + double tolerance, + cairo_antialias_t antialias) { cairo_svg_surface_t *surface = cairo_container_of (clipper, cairo_svg_surface_t, clipper); cairo_svg_document_t *document = surface->document; - unsigned int i; if (path == NULL) { - for (i = 0; i < surface->clip_level; i++) - _cairo_output_stream_printf (surface->xml_node, "</g>\n"); - + for (unsigned int i = 0; i < surface->clip_level; i++) { + _cairo_svg_stream_printf (surface->current_clipper_stream, "</g>\n"); + } surface->clip_level = 0; return CAIRO_STATUS_SUCCESS; } /* skip trivial whole-page clips */ - if (_cliprect_covers_surface (surface, path)) + if (_cairo_svg_surface_cliprect_covers_surface (surface, path)) { return CAIRO_STATUS_SUCCESS; + } + + _cairo_svg_stream_printf (&document->xml_node_defs, + "<clipPath id=\"clip-%d\">\n", + document->clip_id); - _cairo_output_stream_printf (document->xml_node_defs, - "<clipPath id=\"clip%d\">\n" - " <path ", - document->clip_id); - _cairo_svg_surface_emit_path (document->xml_node_defs, path, NULL); + _cairo_svg_stream_printf (&document->xml_node_defs, + "<path clip-rule=\"%s\"", + fill_rule == CAIRO_FILL_RULE_EVEN_ODD ? "evenodd" : "nonzero"); + _cairo_svg_surface_emit_path (&document->xml_node_defs, path, NULL); + _cairo_svg_stream_printf (&document->xml_node_defs, "/>\n"); - _cairo_output_stream_printf (document->xml_node_defs, - "/>\n" - "</clipPath>\n"); + _cairo_svg_stream_printf (&document->xml_node_defs, "</clipPath>\n"); - _cairo_output_stream_printf (surface->xml_node, - "<g clip-path=\"url(#clip%d)\" " - "clip-rule=\"%s\">\n", - document->clip_id, - fill_rule == CAIRO_FILL_RULE_EVEN_ODD ? - "evenodd" : "nonzero"); + _cairo_svg_stream_printf (surface->current_clipper_stream, + "<g clip-path=\"url(#clip-%d)\">\n", + document->clip_id); document->clip_id++; surface->clip_level++; @@ -645,20 +1025,45 @@ _cairo_svg_surface_clipper_intersect_clip_path (cairo_surface_clipper_t *clipper return CAIRO_STATUS_SUCCESS; } +static void +_cairo_svg_surface_reset_clip (cairo_svg_surface_t *surface) +{ + _cairo_surface_clipper_reset (&surface->clipper); + if (surface->current_clipper_stream != NULL) { + for (unsigned int i = 0; i < surface->clip_level; i++) { + _cairo_svg_stream_printf (surface->current_clipper_stream, "</g>\n"); + } + } + surface->clip_level = 0; +} + +static cairo_status_t +_cairo_svg_surface_set_clip (cairo_svg_surface_t *surface, + cairo_svg_stream_t *clipper_stream, + const cairo_clip_t *clip) +{ + if (surface->current_clipper_stream != clipper_stream) { + _cairo_svg_surface_reset_clip (surface); + surface->current_clipper_stream = clipper_stream; + } + return _cairo_surface_clipper_set_clip (&surface->clipper, clip); +} + static cairo_surface_t * -_cairo_svg_surface_create_for_document (cairo_svg_document_t *document, - cairo_content_t content, - double width, - double height, - cairo_bool_t bounded) +_cairo_svg_surface_create_for_document (cairo_svg_document_t *document, + cairo_content_t content, + double width, + double height, + cairo_bool_t bounded) { cairo_svg_surface_t *surface; cairo_surface_t *paginated; - cairo_status_t status, status_ignored; + cairo_status_t status; surface = _cairo_malloc (sizeof (cairo_svg_surface_t)); - if (unlikely (surface == NULL)) + if (unlikely (surface == NULL)) { return _cairo_surface_create_in_error (_cairo_error (CAIRO_STATUS_NO_MEMORY)); + } _cairo_surface_init (&surface->base, &cairo_svg_surface_backend, @@ -666,49 +1071,36 @@ _cairo_svg_surface_create_for_document (cairo_svg_document_t *document, content, TRUE); /* is_vector */ + surface->source_id = surface->base.unique_id; + surface->depth = 0; + surface->width = width; surface->height = height; surface->surface_bounded = bounded; surface->document = _cairo_svg_document_reference (document); - surface->clip_level = 0; - _cairo_surface_clipper_init (&surface->clipper, - _cairo_svg_surface_clipper_intersect_clip_path); - - surface->base_clip = document->clip_id++; - surface->is_base_clip_emitted = FALSE; - - surface->xml_node = _cairo_memory_stream_create (); - status = _cairo_output_stream_get_status (surface->xml_node); - if (unlikely (status)) - goto CLEANUP; - + surface->xml_node = _cairo_svg_stream_create (); _cairo_array_init (&surface->page_set, sizeof (cairo_svg_page_t)); - if (content == CAIRO_CONTENT_COLOR) { - _cairo_output_stream_printf (surface->xml_node, - "<rect width=\"%f\" height=\"%f\" " - "style=\"opacity:1;stroke:none;" - "fill:rgb(0,0,0);\"/>\n", - width, height); - status = _cairo_output_stream_get_status (surface->xml_node); - if (unlikely (status)) - goto CLEANUP; - } - - surface->paginated_mode = CAIRO_PAGINATED_MODE_ANALYZE; - surface->force_fallbacks = FALSE; - surface->content = content; - surface->source_surfaces = _cairo_hash_table_create (_cairo_svg_source_surface_equal); if (unlikely (surface->source_surfaces == NULL)) { status = _cairo_error (CAIRO_STATUS_NO_MEMORY); goto CLEANUP; } + _cairo_surface_clipper_init (&surface->clipper, _cairo_svg_surface_clipper_intersect_clip_path); + surface->current_clipper_stream = NULL; + surface->clip_level = 0; + surface->transitive_paint_used = FALSE; + + surface->paginated_mode = CAIRO_PAGINATED_MODE_ANALYZE; + + surface->force_fallbacks = FALSE; + + paginated = _cairo_paginated_surface_create (&surface->base, - surface->content, + surface->base.content, &cairo_svg_surface_paginated_backend); status = paginated->status; if (status == CAIRO_STATUS_SUCCESS) { @@ -718,9 +1110,9 @@ _cairo_svg_surface_create_for_document (cairo_svg_document_t *document, } /* ignore status as we are on the error path */ -CLEANUP: - status_ignored = _cairo_output_stream_destroy (surface->xml_node); - status_ignored = _cairo_svg_document_destroy (document); + CLEANUP: + (void) _cairo_svg_stream_destroy (&surface->xml_node); + (void) _cairo_svg_document_destroy (document); free (surface); @@ -733,7 +1125,7 @@ _cairo_svg_surface_create_for_stream_internal (cairo_output_stream_t *stream, double height, cairo_svg_version_t version) { - cairo_svg_document_t *document = NULL; /* silence compiler */ + cairo_svg_document_t *document; cairo_surface_t *surface; cairo_status_t status; @@ -750,7 +1142,6 @@ _cairo_svg_surface_create_for_stream_internal (cairo_output_stream_t *stream, surface = _cairo_svg_surface_create_for_document (document, CAIRO_CONTENT_COLOR_ALPHA, width, height, TRUE); if (surface->status) { - status = _cairo_svg_document_destroy (document); return surface; } @@ -765,33 +1156,13 @@ _cairo_svg_surface_create_for_stream_internal (cairo_output_stream_t *stream, static cairo_svg_page_t * _cairo_svg_surface_store_page (cairo_svg_surface_t *surface) { + _cairo_svg_surface_reset_clip (surface); cairo_svg_page_t page; - cairo_output_stream_t *stream; - cairo_int_status_t status; - unsigned int i; - - stream = _cairo_memory_stream_create (); - if (_cairo_output_stream_get_status (stream)) { - status = _cairo_output_stream_destroy (stream); - return NULL; - } - - page.surface_id = surface->base.unique_id; - page.clip_level = surface->clip_level; page.xml_node = surface->xml_node; - if (_cairo_array_append (&surface->page_set, &page)) { - status = _cairo_output_stream_destroy (stream); return NULL; } - - surface->xml_node = stream; - surface->clip_level = 0; - for (i = 0; i < page.clip_level; i++) - _cairo_output_stream_printf (page.xml_node, "</g>\n"); - - _cairo_surface_clipper_reset (&surface->clipper); - + surface->xml_node = _cairo_svg_stream_create (); return _cairo_array_index (&surface->page_set, surface->page_set.num_elements - 1); } @@ -800,13 +1171,13 @@ static cairo_int_status_t _cairo_svg_surface_copy_page (void *abstract_surface) { cairo_svg_surface_t *surface = abstract_surface; - cairo_svg_page_t *page; - page = _cairo_svg_surface_store_page (surface); - if (unlikely (page == NULL)) + cairo_svg_page_t *page = _cairo_svg_surface_store_page (surface); + if (unlikely (page == NULL)) { return _cairo_error (CAIRO_STATUS_NO_MEMORY); + } - _cairo_memory_stream_copy (page->xml_node, surface->xml_node); + _cairo_svg_stream_copy (&page->xml_node, &surface->xml_node); return CAIRO_STATUS_SUCCESS; } @@ -816,34 +1187,38 @@ _cairo_svg_surface_show_page (void *abstract_surface) { cairo_svg_surface_t *surface = abstract_surface; - if (unlikely (_cairo_svg_surface_store_page (surface) == NULL)) + cairo_svg_page_t *page = _cairo_svg_surface_store_page (surface); + if (unlikely (page == NULL)) { return _cairo_error (CAIRO_STATUS_NO_MEMORY); + } return CAIRO_STATUS_SUCCESS; } static void -_cairo_svg_surface_emit_transform (cairo_output_stream_t *output, - char const *attribute_str, - const cairo_matrix_t *object_matrix, - const cairo_matrix_t *parent_matrix) +_cairo_svg_surface_emit_transform (cairo_svg_stream_t *output, + char const *attribute_name, + const cairo_matrix_t *object_matrix, + const cairo_matrix_t *parent_matrix) { cairo_matrix_t matrix = *object_matrix; - if (parent_matrix != NULL) + if (parent_matrix != NULL) { cairo_matrix_multiply (&matrix, &matrix, parent_matrix); + } - if (!_cairo_matrix_is_identity (&matrix)) - _cairo_output_stream_printf (output, - "%s=\"matrix(%f,%f,%f,%f,%f,%f)\"", - attribute_str, - matrix.xx, matrix.yx, - matrix.xy, matrix.yy, - matrix.x0, matrix.y0); + if (!_cairo_matrix_is_identity (&matrix)) { + _cairo_svg_stream_printf (output, + " %s=\"matrix(%f, %f, %f, %f, %f, %f)\"", + attribute_name, + matrix.xx, matrix.yx, + matrix.xy, matrix.yy, + matrix.x0, matrix.y0); + } } typedef struct { - cairo_output_stream_t *output; + cairo_svg_stream_t *output; const cairo_matrix_t *ctm_inverse; } svg_path_info_t; @@ -858,7 +1233,7 @@ _cairo_svg_path_move_to (void *closure, if (info->ctm_inverse) cairo_matrix_transform_point (info->ctm_inverse, &x, &y); - _cairo_output_stream_printf (info->output, "M %f %f ", x, y); + _cairo_svg_stream_printf (info->output, "M %f %f ", x, y); return CAIRO_STATUS_SUCCESS; } @@ -874,7 +1249,7 @@ _cairo_svg_path_line_to (void *closure, if (info->ctm_inverse) cairo_matrix_transform_point (info->ctm_inverse, &x, &y); - _cairo_output_stream_printf (info->output, "L %f %f ", x, y); + _cairo_svg_stream_printf (info->output, "L %f %f ", x, y); return CAIRO_STATUS_SUCCESS; } @@ -899,9 +1274,9 @@ _cairo_svg_path_curve_to (void *closure, cairo_matrix_transform_point (info->ctm_inverse, &dx, &dy); } - _cairo_output_stream_printf (info->output, - "C %f %f %f %f %f %f ", - bx, by, cx, cy, dx, dy); + _cairo_svg_stream_printf (info->output, + "C %f %f %f %f %f %f ", + bx, by, cx, cy, dx, dy); return CAIRO_STATUS_SUCCESS; } @@ -911,20 +1286,20 @@ _cairo_svg_path_close_path (void *closure) { svg_path_info_t *info = closure; - _cairo_output_stream_printf (info->output, "Z "); + _cairo_svg_stream_printf (info->output, "Z "); return CAIRO_STATUS_SUCCESS; } static void -_cairo_svg_surface_emit_path (cairo_output_stream_t *output, - const cairo_path_fixed_t *path, - const cairo_matrix_t *ctm_inverse) +_cairo_svg_surface_emit_path (cairo_svg_stream_t *output, + const cairo_path_fixed_t *path, + const cairo_matrix_t *ctm_inverse) { cairo_status_t status; svg_path_info_t info; - _cairo_output_stream_printf (output, "d=\""); + _cairo_svg_stream_printf (output, " d=\""); info.output = output; info.ctm_inverse = ctm_inverse; @@ -936,85 +1311,189 @@ _cairo_svg_surface_emit_path (cairo_output_stream_t *output, &info); assert (status == CAIRO_STATUS_SUCCESS); - _cairo_output_stream_printf (output, "\""); + _cairo_svg_stream_printf (output, "\""); } static cairo_int_status_t -_cairo_svg_document_emit_outline_glyph_data (cairo_svg_document_t *document, - cairo_scaled_font_t *scaled_font, - unsigned long glyph_index) +_cairo_svg_document_emit_outline_glyph_data (cairo_svg_document_t *document, + cairo_scaled_font_t *scaled_font, + unsigned long glyph_index) { cairo_scaled_glyph_t *scaled_glyph; cairo_int_status_t status; status = _cairo_scaled_glyph_lookup (scaled_font, glyph_index, - CAIRO_SCALED_GLYPH_INFO_METRICS| - CAIRO_SCALED_GLYPH_INFO_PATH, + CAIRO_SCALED_GLYPH_INFO_METRICS | CAIRO_SCALED_GLYPH_INFO_PATH, + NULL, /* foreground color */ &scaled_glyph); - if (unlikely (status)) + if (unlikely (status)) { return status; + } - _cairo_output_stream_printf (document->xml_node_glyphs, - "<path style=\"stroke:none;\" "); + if (_cairo_path_fixed_size (scaled_glyph->path) != 0) { + _cairo_svg_stream_printf (&document->xml_node_glyphs, + "<path"); - _cairo_svg_surface_emit_path (document->xml_node_glyphs, - scaled_glyph->path, NULL); + _cairo_svg_surface_emit_path (&document->xml_node_glyphs, + scaled_glyph->path, + NULL); - _cairo_output_stream_printf (document->xml_node_glyphs, - "/>\n"); + _cairo_svg_stream_printf (&document->xml_node_glyphs, + "/>\n"); + } return status; } static cairo_int_status_t -_cairo_svg_document_emit_bitmap_glyph_data (cairo_svg_document_t *document, - cairo_scaled_font_t *scaled_font, - unsigned long glyph_index) +_cairo_svg_document_emit_bitmap_glyph_data (cairo_svg_document_t *document, + cairo_scaled_font_t *scaled_font, + unsigned long glyph_index) { - cairo_scaled_glyph_t *scaled_glyph; - cairo_image_surface_t *image; cairo_status_t status; - uint8_t *row, *byte; - int rows, cols; - int x, y, bit; + cairo_scaled_glyph_t *scaled_glyph; status = _cairo_scaled_glyph_lookup (scaled_font, glyph_index, - CAIRO_SCALED_GLYPH_INFO_METRICS | - CAIRO_SCALED_GLYPH_INFO_SURFACE, + CAIRO_SCALED_GLYPH_INFO_METRICS | CAIRO_SCALED_GLYPH_INFO_SURFACE, + NULL, /* foreground color */ &scaled_glyph); - if (unlikely (status)) - return status; - - image = _cairo_image_surface_coerce_to_format (scaled_glyph->surface, - CAIRO_FORMAT_A1); - status = image->base.status; - if (unlikely (status)) + if (unlikely (status)) { return status; + } - _cairo_output_stream_printf (document->xml_node_glyphs, "<g"); - _cairo_svg_surface_emit_transform (document->xml_node_glyphs, " transform", - &image->base.device_transform_inverse, NULL); - _cairo_output_stream_printf (document->xml_node_glyphs, ">\n"); - - for (y = 0, row = image->data, rows = image->height; rows; row += image->stride, rows--, y++) { - for (x = 0, byte = row, cols = (image->width + 7) / 8; cols; byte++, cols--) { - uint8_t output_byte = CAIRO_BITSWAP8_IF_LITTLE_ENDIAN (*byte); - for (bit = 7; bit >= 0 && x < image->width; bit--, x++) { - if (output_byte & (1 << bit)) { - _cairo_output_stream_printf (document->xml_node_glyphs, - "<rect x=\"%d\" y=\"%d\" width=\"1\" height=\"1\"/>\n", - x, y); + cairo_bool_t use_recording_surface = (scaled_glyph->has_info & CAIRO_SCALED_GLYPH_INFO_RECORDING_SURFACE) != 0; + cairo_matrix_t glyph_matrix = scaled_glyph->surface->base.device_transform_inverse; + cairo_image_surface_t *glyph_image_surface = scaled_glyph->surface; + + // Attempt to recognize a common pattern for a bitmap font and extract the original glyph image from it + cairo_surface_t *extracted_surface; + cairo_image_surface_t *extracted_image = NULL; + void *extracted_image_extra; + if (use_recording_surface) { + cairo_recording_surface_t *recording_surface = (cairo_recording_surface_t *) scaled_glyph->recording_surface; + if (recording_surface->commands.num_elements == 1) { + cairo_command_t *command = *((cairo_command_t **) _cairo_array_index (&recording_surface->commands, 0)); + if (command->header.type == CAIRO_COMMAND_MASK && + command->header.op == CAIRO_OPERATOR_OVER && + command->header.clip == NULL && + command->mask.source.base.type == CAIRO_PATTERN_TYPE_SOLID && + _cairo_color_equal (&command->mask.source.solid.color, _cairo_stock_color (CAIRO_STOCK_BLACK)) && + command->mask.mask.base.extend == CAIRO_EXTEND_NONE && + command->mask.mask.base.type == CAIRO_PATTERN_TYPE_SURFACE && + command->mask.mask.surface.surface->type == CAIRO_SURFACE_TYPE_IMAGE) { + extracted_surface = command->mask.mask.surface.surface; + if (_cairo_surface_acquire_source_image (extracted_surface, + &extracted_image, + &extracted_image_extra) == CAIRO_STATUS_SUCCESS) { + if (extracted_image->format == CAIRO_FORMAT_A1 || extracted_image->format == CAIRO_FORMAT_A8) { + use_recording_surface = FALSE; + glyph_image_surface = extracted_image; + glyph_matrix = command->mask.mask.base.matrix; + status = cairo_matrix_invert (&glyph_matrix); + assert (status == CAIRO_STATUS_SUCCESS); + } } } } } - _cairo_output_stream_printf (document->xml_node_glyphs, "</g>\n"); - cairo_surface_destroy (&image->base); + cairo_surface_t *paginated_surface = _cairo_svg_surface_create_for_document (document, + CAIRO_CONTENT_COLOR_ALPHA, + 0, + 0, + FALSE); + cairo_svg_surface_t *svg_surface = (cairo_svg_surface_t *) _cairo_paginated_surface_get_target (paginated_surface); + status = paginated_surface->status; + if (unlikely (status)) { + goto cleanup; + } - return CAIRO_STATUS_SUCCESS; + unsigned int source_id = svg_surface->base.unique_id; + + cairo_surface_set_fallback_resolution (paginated_surface, + document->owner->x_fallback_resolution, + document->owner->y_fallback_resolution); + + cairo_svg_stream_t temporary_stream = _cairo_svg_stream_create (); + + unsigned int mask_id = document->mask_id++; + + _cairo_svg_stream_printf (&temporary_stream, + "<mask id=\"mask-%d\">\n", + mask_id); + + cairo_pattern_t *pattern = cairo_pattern_create_for_surface (use_recording_surface ? scaled_glyph->recording_surface + : &glyph_image_surface->base); + _cairo_svg_surface_emit_composite_pattern (&temporary_stream, + svg_surface, + (cairo_surface_pattern_t *) pattern, + invalid_pattern_id, + NULL); + cairo_pattern_destroy (pattern); + + _cairo_svg_stream_printf (&temporary_stream, "</mask>\n"); + + _cairo_svg_stream_copy (&temporary_stream, &document->xml_node_defs); + + status = _cairo_svg_stream_destroy (&temporary_stream); + if (unlikely (status)) { + goto cleanup; + } + + svg_surface->transitive_paint_used = TRUE; + + _cairo_svg_stream_printf (&document->xml_node_glyphs, "<rect"); + _cairo_svg_stream_append_paint_dependent (&document->xml_node_glyphs, + source_id, + CAIRO_SVG_STREAM_PAINT_DEPENDENT_ELEMENT_TYPE_RECTANGLE); + _cairo_svg_stream_printf (&document->xml_node_glyphs, + " mask=\"url(#mask-%d)\"", + mask_id); + if (!use_recording_surface) { + _cairo_svg_surface_emit_transform (&document->xml_node_glyphs, + "transform", + &glyph_matrix, + NULL); + } + _cairo_svg_stream_printf (&document->xml_node_glyphs, "/>\n"); + + cairo_svg_paint_t *paint_entry = malloc (sizeof (cairo_svg_paint_t)); + if (paint_entry == NULL) { + status = _cairo_error (CAIRO_STATUS_NO_MEMORY); + goto cleanup; + } + paint_entry->source_id = source_id; + paint_entry->box.p1.x = 0; + paint_entry->box.p1.y = 0; + paint_entry->box.p2.x = glyph_image_surface->width; + paint_entry->box.p2.y = glyph_image_surface->height; + if (use_recording_surface) { + _cairo_matrix_transform_bounding_box (&glyph_matrix, + &paint_entry->box.p1.x, &paint_entry->box.p1.y, + &paint_entry->box.p2.x, &paint_entry->box.p2.y, + NULL); + } + _cairo_svg_paint_box_add_padding (&paint_entry->box); + _cairo_array_init (&paint_entry->paint_elements, sizeof (cairo_svg_paint_element_t)); + _cairo_svg_paint_init_key (paint_entry); + status = _cairo_hash_table_insert (document->paints, &paint_entry->base); + if (unlikely (status)) { + goto cleanup; + } + + cleanup: + if (status == CAIRO_STATUS_SUCCESS) { + status = cairo_surface_status (paginated_surface); + } + cairo_surface_destroy (paginated_surface); + + if (extracted_image != NULL) { + _cairo_surface_release_source_image (extracted_surface, extracted_image, extracted_image_extra); + } + + return status; } static cairo_int_status_t @@ -1026,10 +1505,10 @@ _cairo_svg_document_emit_glyph (cairo_svg_document_t *document, { cairo_int_status_t status; - _cairo_output_stream_printf (document->xml_node_glyphs, - "<symbol overflow=\"visible\" id=\"glyph%d-%d\">\n", - font_id, - subset_glyph_index); + _cairo_svg_stream_printf (&document->xml_node_glyphs, + "<g id=\"glyph-%d-%d\">\n", + font_id, + subset_glyph_index); status = _cairo_svg_document_emit_outline_glyph_data (document, scaled_font, @@ -1041,7 +1520,7 @@ _cairo_svg_document_emit_glyph (cairo_svg_document_t *document, if (unlikely (status)) return status; - _cairo_output_stream_printf (document->xml_node_glyphs, "</symbol>\n"); + _cairo_svg_stream_printf (&document->xml_node_glyphs, "</g>\n"); return CAIRO_INT_STATUS_SUCCESS; } @@ -1076,162 +1555,331 @@ _cairo_svg_document_emit_font_subsets (cairo_svg_document_t *document) status = _cairo_scaled_font_subsets_foreach_scaled (document->font_subsets, _cairo_svg_document_emit_font_subset, document); - if (unlikely (status)) - goto FAIL; - - status = _cairo_scaled_font_subsets_foreach_user (document->font_subsets, - _cairo_svg_document_emit_font_subset, - document); - - FAIL: _cairo_scaled_font_subsets_destroy (document->font_subsets); document->font_subsets = NULL; return status; } -static char const * -_cairo_svg_surface_operators[] = { - "clear", - - "src", "src-over", "src-in", - "src-out", "src-atop", - - "dst", "dst-over", "dst-in", - "dst-out", "dst-atop", - - "xor", "plus", - "color-dodge", /* FIXME: saturate ? */ - - "multiply", "screen", "overlay", - "darken", "lighten", - "color-dodge", "color-burn", - "hard-light", "soft-light", - "difference", "exclusion" -}; - static cairo_bool_t -_cairo_svg_surface_analyze_operator (cairo_svg_surface_t *surface, - cairo_operator_t op) +_cairo_svg_surface_are_operation_and_pattern_supported (cairo_svg_surface_t *surface, + cairo_operator_t op, + const cairo_pattern_t *pattern) { - /* guard against newly added operators */ - if (op >= ARRAY_LENGTH (_cairo_svg_surface_operators)) - return CAIRO_INT_STATUS_UNSUPPORTED; - - /* allow operators being NULL if they are unsupported */ - if (_cairo_svg_surface_operators[op] == NULL) - return CAIRO_INT_STATUS_UNSUPPORTED; - - return CAIRO_STATUS_SUCCESS; -} - -static cairo_int_status_t -_cairo_svg_surface_analyze_operation (cairo_svg_surface_t *surface, - cairo_operator_t op, - const cairo_pattern_t *pattern) -{ - cairo_svg_document_t *document = surface->document; - - if (surface->force_fallbacks && - surface->paginated_mode == CAIRO_PAGINATED_MODE_ANALYZE) - { - return CAIRO_INT_STATUS_UNSUPPORTED; + if (surface->force_fallbacks) { + return FALSE; } - if (pattern->type == CAIRO_PATTERN_TYPE_MESH) - return CAIRO_INT_STATUS_UNSUPPORTED; + if (op == CAIRO_OPERATOR_SATURATE) { + return FALSE; + } - /* SVG doesn't support extend reflect for image pattern */ - if (pattern->type == CAIRO_PATTERN_TYPE_SURFACE && - pattern->extend == CAIRO_EXTEND_REFLECT) - return CAIRO_INT_STATUS_UNSUPPORTED; + /* SVG 1.1 does not support these operators. We already have code for them for SVG 2 + * that can be enabled when SVG 2 becomes widespread. */ + if (op == CAIRO_OPERATOR_OVERLAY || + op == CAIRO_OPERATOR_COLOR_DODGE || + op == CAIRO_OPERATOR_COLOR_BURN || + op == CAIRO_OPERATOR_HARD_LIGHT || + op == CAIRO_OPERATOR_SOFT_LIGHT || + op == CAIRO_OPERATOR_DIFFERENCE || + op == CAIRO_OPERATOR_EXCLUSION || + op == CAIRO_OPERATOR_HSL_HUE || + op == CAIRO_OPERATOR_HSL_SATURATION || + op == CAIRO_OPERATOR_HSL_COLOR || + op == CAIRO_OPERATOR_HSL_LUMINOSITY) { + return FALSE; + } - if (document->svg_version >= CAIRO_SVG_VERSION_1_2) - return _cairo_svg_surface_analyze_operator (surface, op); + if (pattern->type == CAIRO_PATTERN_TYPE_SURFACE) { + /* Do not cause stack overflow because of too deep or infinite recording surfaces. */ + if (((cairo_surface_pattern_t *) pattern)->surface->type == CAIRO_SURFACE_TYPE_RECORDING && + surface->depth > 1000) { + return FALSE; + } + /* SVG doesn't support extends reflect and pad for surface pattern. */ + if (pattern->extend != CAIRO_EXTEND_NONE && pattern->extend != CAIRO_EXTEND_REPEAT) { + return FALSE; + } + } - if (op == CAIRO_OPERATOR_OVER) - return CAIRO_STATUS_SUCCESS; + /* SVG 1.1 does not support the focal point (fx, fy) that is outside of the circle defined by (cx, cy) and r. */ + if (pattern->type == CAIRO_PATTERN_TYPE_RADIAL) { + cairo_radial_pattern_t *radial_pattern = (cairo_radial_pattern_t *) pattern; + double max_radius; + if (radial_pattern->cd1.radius > radial_pattern->cd2.radius) { + max_radius = radial_pattern->cd1.radius; + } else { + max_radius = radial_pattern->cd2.radius; + } + cairo_point_double_t c1 = radial_pattern->cd1.center; + cairo_point_double_t c2 = radial_pattern->cd2.center; + if ((c1.x - c2.x) * (c1.x - c2.x) + (c1.y - c2.y) * (c1.y - c2.y) >= max_radius * max_radius) { + return FALSE; + } + } - /* The SOURCE operator is only supported if there is nothing - * painted underneath. */ - if (op == CAIRO_OPERATOR_SOURCE) - return CAIRO_INT_STATUS_FLATTEN_TRANSPARENCY; + if (pattern->type == CAIRO_PATTERN_TYPE_MESH) { + return FALSE; + } - return CAIRO_INT_STATUS_UNSUPPORTED; -} + if (pattern->type == CAIRO_PATTERN_TYPE_RASTER_SOURCE) { + return FALSE; + } -static cairo_int_status_t -_cairo_svg_surface_operation_supported (cairo_svg_surface_t *surface, - cairo_operator_t op, - const cairo_pattern_t *pattern) -{ - return _cairo_svg_surface_analyze_operation (surface, op, pattern) != CAIRO_INT_STATUS_UNSUPPORTED; + return TRUE; } static cairo_status_t _cairo_svg_surface_finish (void *abstract_surface) { - cairo_status_t status, status2; + cairo_status_t status, final_status; cairo_svg_surface_t *surface = abstract_surface; - cairo_svg_document_t *document = surface->document; - cairo_svg_page_t *page; - unsigned int i; - if (_cairo_paginated_surface_get_target (document->owner) == &surface->base) - status = _cairo_svg_document_finish (document); - else - status = CAIRO_STATUS_SUCCESS; + if (_cairo_paginated_surface_get_target (surface->document->owner) == &surface->base) { + final_status = _cairo_svg_document_finish (surface->document); + } else { + final_status = CAIRO_STATUS_SUCCESS; + } - if (surface->xml_node != NULL) { - status2 = _cairo_output_stream_destroy (surface->xml_node); - if (status == CAIRO_STATUS_SUCCESS) - status = status2; + status = _cairo_svg_stream_destroy (&surface->xml_node); + if (final_status == CAIRO_STATUS_SUCCESS) { + final_status = status; } - for (i = 0; i < surface->page_set.num_elements; i++) { - page = _cairo_array_index (&surface->page_set, i); - status2 = _cairo_output_stream_destroy (page->xml_node); - if (status == CAIRO_STATUS_SUCCESS) - status = status2; + for (unsigned int i = 0; i < surface->page_set.num_elements; i++) { + cairo_svg_page_t *page = _cairo_array_index (&surface->page_set, i); + status = _cairo_svg_stream_destroy (&page->xml_node); + if (final_status == CAIRO_STATUS_SUCCESS) { + final_status = status; + } } _cairo_array_fini (&surface->page_set); _cairo_surface_clipper_reset (&surface->clipper); - _cairo_hash_table_foreach (surface->source_surfaces, - _cairo_svg_source_surface_pluck, - surface->source_surfaces); + _cairo_hash_table_foreach (surface->source_surfaces, _cairo_svg_source_surface_pluck, surface->source_surfaces); _cairo_hash_table_destroy (surface->source_surfaces); - status2 = _cairo_svg_document_destroy (document); - if (status == CAIRO_STATUS_SUCCESS) - status = status2; + status = _cairo_svg_document_destroy (surface->document); + if (final_status == CAIRO_STATUS_SUCCESS) { + final_status = status; + } - return status; + return final_status; } - -static void -_cairo_svg_surface_emit_alpha_filter (cairo_svg_document_t *document) +static const char * +_cairo_svg_surface_emit_static_filter (cairo_svg_document_t *document, enum cairo_svg_filter filter) { - if (document->alpha_filter) - return; + if (!document->filters_emitted[filter]) { + document->filters_emitted[filter] = TRUE; + if (filter == CAIRO_SVG_FILTER_REMOVE_COLOR) { + // (r, g, b, a) -> (1, 1, 1, a) + _cairo_svg_stream_printf (&document->xml_node_filters, + "<filter id=\"filter-remove-color\" " + "x=\"0%%\" y=\"0%%\" width=\"100%%\" height=\"100%%\">\n" + "<feColorMatrix color-interpolation-filters=\"sRGB\" " + "values=\"0 0 0 0 1 " + /* */ "0 0 0 0 1 " + /* */ "0 0 0 0 1 " + /* */ "0 0 0 1 0\" />\n" + "</filter>\n"); + } else if (filter == CAIRO_SVG_FILTER_REMOVE_COLOR_AND_INVERT_ALPHA) { + // (r, g, b, a) -> (1, 1, 1, 1 - a) + _cairo_svg_stream_printf (&document->xml_node_filters, + "<filter id=\"filter-remove-color-and-invert-alpha\" " + "x=\"0%%\" y=\"0%%\" width=\"100%%\" height=\"100%%\">\n" + "<feColorMatrix color-interpolation-filters=\"sRGB\" " + "values=\"0 0 0 0 1 " + /* */ "0 0 0 0 1 " + /* */ "0 0 0 0 1 " + /* */ "0 0 0 -1 1\"/>\n" + "</filter>\n"); + } else if (filter == CAIRO_SVG_FILTER_COLOR_TO_ALPHA) { + // (r, g, b, a) -> (1, 1, 1, 0.2126 * r + 0.7152 * g + 0.0722 * b) + _cairo_svg_stream_printf (&document->xml_node_filters, + "<filter id=\"filter-color-to-alpha\" " + "x=\"0%%\" y=\"0%%\" width=\"100%%\" height=\"100%%\">\n" + "<feColorMatrix color-interpolation-filters=\"sRGB\" " + "values=\"0 0 0 0 1 " + /* */ "0 0 0 0 1 " + /* */ "0 0 0 0 1 " + /* */ "0.2126 0.7152 0.0722 0 0\"/>\n" + "</filter>\n"); + } + } - _cairo_output_stream_printf (document->xml_node_defs, - "<filter id=\"alpha\" " - "filterUnits=\"objectBoundingBox\" " - "x=\"0%%\" y=\"0%%\" " - "width=\"100%%\" height=\"100%%\">\n" - " <feColorMatrix type=\"matrix\" " - "in=\"SourceGraphic\" " - "values=\"0 0 0 0 1 0 0 0 0 1 0 0 0 0 1 0 0 0 1 0\"/>\n" - "</filter>\n"); + if (filter == CAIRO_SVG_FILTER_REMOVE_COLOR) { + return "remove-color"; + } else if (filter == CAIRO_SVG_FILTER_REMOVE_COLOR_AND_INVERT_ALPHA) { + return "remove-color-and-invert-alpha"; + } else if (filter == CAIRO_SVG_FILTER_COLOR_TO_ALPHA) { + return "color-to-alpha"; + } else { + ASSERT_NOT_REACHED; + } + return FALSE; /* squelch warning */ +} - document->alpha_filter = TRUE; +#define _CAIRO_SVG_SURFACE_OUTPUT_FE_COMPOSITE_FILTER(operation) \ + _cairo_svg_stream_printf (&surface->document->xml_node_filters, \ + "<filter id=\"filter-%d\" " \ + "x=\"0%%\" y=\"0%%\" width=\"100%%\" height=\"100%%\">\n" \ + "<feImage xlink:href=\"#compositing-group-%d\" result=\"source\"", \ + filter_id, \ + source_compositing_group_id); \ + _cairo_svg_stream_append_paint_dependent (&surface->document->xml_node_filters, \ + surface->source_id, \ + CAIRO_SVG_STREAM_PAINT_DEPENDENT_ELEMENT_TYPE_RECTANGLE_AT_ORIGIN); \ + _cairo_svg_stream_printf (&surface->document->xml_node_filters, \ + "/>\n" \ + "<feImage xlink:href=\"#compositing-group-%d\" result=\"destination\"", \ + destination_compositing_group_id); \ + _cairo_svg_stream_append_paint_dependent (&surface->document->xml_node_filters, \ + surface->source_id, \ + CAIRO_SVG_STREAM_PAINT_DEPENDENT_ELEMENT_TYPE_RECTANGLE_AT_ORIGIN); \ + _cairo_svg_stream_printf (&surface->document->xml_node_filters, \ + "/>\n" \ + "<feComposite in=\"source\" in2=\"destination\" " \ + "operator=\"" operation "\" " \ + "color-interpolation-filters=\"sRGB\"/>\n" \ + "</filter>\n", \ + filter_id, \ + source_compositing_group_id, \ + destination_compositing_group_id); + +#define _CAIRO_SVG_SURFACE_OUTPUT_FE_BLEND_FILTER(mode) \ + _cairo_svg_stream_printf (&surface->document->xml_node_filters, \ + "<filter id=\"filter-%d\" " \ + "x=\"0%%\" y=\"0%%\" width=\"100%%\" height=\"100%%\">\n" \ + "<feImage xlink:href=\"#compositing-group-%d\" result=\"source\"", \ + filter_id, \ + source_compositing_group_id); \ + _cairo_svg_stream_append_paint_dependent (&surface->document->xml_node_filters, \ + surface->source_id, \ + CAIRO_SVG_STREAM_PAINT_DEPENDENT_ELEMENT_TYPE_RECTANGLE_AT_ORIGIN); \ + _cairo_svg_stream_printf (&surface->document->xml_node_filters, \ + "/>\n" \ + "<feImage xlink:href=\"#compositing-group-%d\" result=\"destination\"", \ + destination_compositing_group_id); \ + _cairo_svg_stream_append_paint_dependent (&surface->document->xml_node_filters, \ + surface->source_id, \ + CAIRO_SVG_STREAM_PAINT_DEPENDENT_ELEMENT_TYPE_RECTANGLE_AT_ORIGIN); \ + _cairo_svg_stream_printf (&surface->document->xml_node_filters, \ + "/>\n" \ + "<feBlend in=\"source\" in2=\"destination\" " \ + "mode=\"" mode "\" " \ + "color-interpolation-filters=\"sRGB\"/>\n" \ + "</filter>\n", \ + filter_id, \ + source_compositing_group_id, \ + destination_compositing_group_id); + +static unsigned int +_cairo_svg_surface_emit_parametric_filter (cairo_svg_surface_t *surface, + enum cairo_svg_filter filter, + unsigned int source_compositing_group_id, + unsigned int destination_compositing_group_id) +{ + unsigned int filter_id = surface->document->filter_id++; + switch (filter) { + case CAIRO_SVG_FILTER_OVER: + _CAIRO_SVG_SURFACE_OUTPUT_FE_COMPOSITE_FILTER ("over") + break; + case CAIRO_SVG_FILTER_IN: + _CAIRO_SVG_SURFACE_OUTPUT_FE_COMPOSITE_FILTER ("in") + break; + case CAIRO_SVG_FILTER_OUT: + _CAIRO_SVG_SURFACE_OUTPUT_FE_COMPOSITE_FILTER ("out") + break; + case CAIRO_SVG_FILTER_ATOP: + _CAIRO_SVG_SURFACE_OUTPUT_FE_COMPOSITE_FILTER ("atop") + break; + case CAIRO_SVG_FILTER_XOR: + _CAIRO_SVG_SURFACE_OUTPUT_FE_COMPOSITE_FILTER ("xor") + break; + case CAIRO_SVG_FILTER_ADD: + // This can also be done with <feComposite operator="lighter"/>, but it is not in SVG 1.1 + _cairo_svg_stream_printf (&surface->document->xml_node_filters, + "<filter id=\"filter-%d\" " + "x=\"0%%\" y=\"0%%\" width=\"100%%\" height=\"100%%\">\n" + "<feImage xlink:href=\"#compositing-group-%d\" result=\"source\"", + filter_id, + source_compositing_group_id); + _cairo_svg_stream_append_paint_dependent (&surface->document->xml_node_filters, + surface->source_id, + CAIRO_SVG_STREAM_PAINT_DEPENDENT_ELEMENT_TYPE_RECTANGLE_AT_ORIGIN); + _cairo_svg_stream_printf (&surface->document->xml_node_filters, + "/>\n" + "<feImage xlink:href=\"#compositing-group-%d\" result=\"destination\"", + destination_compositing_group_id); + _cairo_svg_stream_append_paint_dependent (&surface->document->xml_node_filters, + surface->source_id, + CAIRO_SVG_STREAM_PAINT_DEPENDENT_ELEMENT_TYPE_RECTANGLE_AT_ORIGIN); + _cairo_svg_stream_printf (&surface->document->xml_node_filters, + "/>\n" + "<feComposite in=\"source\" in2=\"destination\" " + "operator=\"arithmetic\" k1=\"0\" k2=\"1\" k3=\"1\" k4=\"0\" " + "color-interpolation-filters=\"sRGB\"/>\n" + "</filter>\n"); + break; + case CAIRO_SVG_FILTER_MULTIPLY: + _CAIRO_SVG_SURFACE_OUTPUT_FE_BLEND_FILTER ("multiply") + break; + case CAIRO_SVG_FILTER_SCREEN: + _CAIRO_SVG_SURFACE_OUTPUT_FE_BLEND_FILTER ("screen") + break; + case CAIRO_SVG_FILTER_OVERLAY: + _CAIRO_SVG_SURFACE_OUTPUT_FE_BLEND_FILTER ("overlay") + break; + case CAIRO_SVG_FILTER_DARKEN: + _CAIRO_SVG_SURFACE_OUTPUT_FE_BLEND_FILTER ("darken") + break; + case CAIRO_SVG_FILTER_LIGHTEN: + _CAIRO_SVG_SURFACE_OUTPUT_FE_BLEND_FILTER ("lighten") + break; + case CAIRO_SVG_FILTER_COLOR_DODGE: + _CAIRO_SVG_SURFACE_OUTPUT_FE_BLEND_FILTER ("color-dodge") + break; + case CAIRO_SVG_FILTER_COLOR_BURN: + _CAIRO_SVG_SURFACE_OUTPUT_FE_BLEND_FILTER ("color-burn") + break; + case CAIRO_SVG_FILTER_HARD_LIGHT: + _CAIRO_SVG_SURFACE_OUTPUT_FE_BLEND_FILTER ("hard-light") + break; + case CAIRO_SVG_FILTER_SOFT_LIGHT: + _CAIRO_SVG_SURFACE_OUTPUT_FE_BLEND_FILTER ("soft-light") + break; + case CAIRO_SVG_FILTER_DIFFERENCE: + _CAIRO_SVG_SURFACE_OUTPUT_FE_BLEND_FILTER ("difference") + break; + case CAIRO_SVG_FILTER_EXCLUSION: + _CAIRO_SVG_SURFACE_OUTPUT_FE_BLEND_FILTER ("exclusion") + break; + case CAIRO_SVG_FILTER_HUE: + _CAIRO_SVG_SURFACE_OUTPUT_FE_BLEND_FILTER ("hue") + break; + case CAIRO_SVG_FILTER_SATURATION: + _CAIRO_SVG_SURFACE_OUTPUT_FE_BLEND_FILTER ("saturation") + break; + case CAIRO_SVG_FILTER_COLOR: + _CAIRO_SVG_SURFACE_OUTPUT_FE_BLEND_FILTER ("color") + break; + case CAIRO_SVG_FILTER_LUMINOSITY: + _CAIRO_SVG_SURFACE_OUTPUT_FE_BLEND_FILTER ("luminosity") + break; + case CAIRO_SVG_FILTER_REMOVE_COLOR: + case CAIRO_SVG_FILTER_REMOVE_COLOR_AND_INVERT_ALPHA: + case CAIRO_SVG_FILTER_COLOR_TO_ALPHA: + case CAIRO_SVG_FILTER_LAST_STATIC_FILTER: + default: + ASSERT_NOT_REACHED; + } + return filter_id; } typedef struct { - cairo_output_stream_t *output; + cairo_svg_stream_t *output; unsigned int in_mem; unsigned int trailing; unsigned char src[3]; @@ -1282,7 +1930,7 @@ base64_write_func (void *closure, default: break; } - _cairo_output_stream_write (info->output, dst, 4); + _cairo_svg_stream_write (info->output, dst, 4); } while (length >= 3); for (i = 0; i < length; i++) { @@ -1290,12 +1938,12 @@ base64_write_func (void *closure, } info->in_mem = length; - return _cairo_output_stream_get_status (info->output); + return info->output->status; } static cairo_int_status_t _cairo_surface_base64_encode_jpeg (cairo_surface_t *surface, - cairo_output_stream_t *output) + cairo_svg_stream_t *output) { const unsigned char *mime_data; unsigned long mime_data_length; @@ -1315,7 +1963,7 @@ _cairo_surface_base64_encode_jpeg (cairo_surface_t *surface, if (image_info.num_components == 4) return CAIRO_INT_STATUS_UNSUPPORTED; - _cairo_output_stream_printf (output, "data:image/jpeg;base64,"); + _cairo_svg_stream_printf (output, "data:image/jpeg;base64,"); info.output = output; info.in_mem = 0; @@ -1337,7 +1985,7 @@ _cairo_surface_base64_encode_jpeg (cairo_surface_t *surface, static cairo_int_status_t _cairo_surface_base64_encode_png (cairo_surface_t *surface, - cairo_output_stream_t *output) + cairo_svg_stream_t *output) { const unsigned char *mime_data; unsigned long mime_data_length; @@ -1351,7 +1999,7 @@ _cairo_surface_base64_encode_png (cairo_surface_t *surface, if (mime_data == NULL) return CAIRO_INT_STATUS_UNSUPPORTED; - _cairo_output_stream_printf (output, "data:image/png;base64,"); + _cairo_svg_stream_printf (output, "data:image/png;base64,"); info.output = output; info.in_mem = 0; @@ -1373,7 +2021,7 @@ _cairo_surface_base64_encode_png (cairo_surface_t *surface, static cairo_int_status_t _cairo_surface_base64_encode (cairo_surface_t *surface, - cairo_output_stream_t *output) + cairo_svg_stream_t *output) { cairo_int_status_t status; base64_write_closure_t info; @@ -1390,7 +2038,7 @@ _cairo_surface_base64_encode (cairo_surface_t *surface, info.in_mem = 0; info.trailing = 0; - _cairo_output_stream_printf (info.output, "data:image/png;base64,"); + _cairo_svg_stream_printf (info.output, "data:image/png;base64,"); status = cairo_surface_write_to_png_stream (surface, base64_write_func, (void *) &info); @@ -1408,32 +2056,6 @@ _cairo_surface_base64_encode (cairo_surface_t *surface, return status; } -static void -_cairo_svg_surface_emit_operator (cairo_output_stream_t *output, - cairo_svg_surface_t *surface, - cairo_operator_t op) -{ - if (surface->document->svg_version >= CAIRO_SVG_VERSION_1_2 && - op != CAIRO_OPERATOR_OVER) { - _cairo_output_stream_printf (output, " comp-op=\"%s\"", _cairo_svg_surface_operators[op]); - if (!_cairo_operator_bounded_by_source (op)) - _cairo_output_stream_printf (output, " clip-to-self=\"true\""); - } -} - -static void -_cairo_svg_surface_emit_operator_for_style (cairo_output_stream_t *output, - cairo_svg_surface_t *surface, - cairo_operator_t op) -{ - if (surface->document->svg_version >= CAIRO_SVG_VERSION_1_2 && - op != CAIRO_OPERATOR_OVER) { - _cairo_output_stream_printf (output, "comp-op:%s;", _cairo_svg_surface_operators[op]); - if (!_cairo_operator_bounded_by_source (op)) - _cairo_output_stream_printf (output, "clip-to-self:true;"); - } -} - /** * _cairo_svg_surface_emit_attr_value: * @@ -1442,7 +2064,7 @@ _cairo_svg_surface_emit_operator_for_style (cairo_output_stream_t *output, * attribute's value context: & and ". **/ static void -_cairo_svg_surface_emit_attr_value (cairo_output_stream_t *stream, +_cairo_svg_surface_emit_attr_value (cairo_svg_stream_t *stream, const unsigned char *value, unsigned int length) { @@ -1457,26 +2079,26 @@ _cairo_svg_surface_emit_attr_value (cairo_output_stream_t *stream, if (*p == '&' || *p == '"') { /* flush what's left before special char */ if (p != q) { - _cairo_output_stream_write (stream, q, p - q); + _cairo_svg_stream_write (stream, q, p - q); q = p + 1; } if (*p == '&') - _cairo_output_stream_printf (stream, "&"); + _cairo_svg_stream_printf (stream, "&"); else // p == '"' - _cairo_output_stream_printf (stream, """); + _cairo_svg_stream_printf (stream, """); } } /* flush the trailing chars if any */ if (p != q) - _cairo_output_stream_write (stream, q, p - q); + _cairo_svg_stream_write (stream, q, p - q); } static cairo_status_t _cairo_svg_surface_emit_surface (cairo_svg_document_t *document, cairo_surface_t *surface, - int source_id) + unsigned int source_id) { cairo_rectangle_int_t extents; cairo_bool_t is_bounded; @@ -1487,62 +2109,65 @@ _cairo_svg_surface_emit_surface (cairo_svg_document_t *document, is_bounded = _cairo_surface_get_extents (surface, &extents); assert (is_bounded); - _cairo_output_stream_printf (document->xml_node_defs, - "<image id=\"image%d\" width=\"%d\" height=\"%d\"", - source_id, - extents.width, extents.height); - - _cairo_output_stream_printf (document->xml_node_defs, " xlink:href=\""); - - cairo_surface_get_mime_data (surface, CAIRO_MIME_TYPE_URI, - &uri, &uri_len); - if (uri != NULL) { - _cairo_svg_surface_emit_attr_value (document->xml_node_defs, - uri, uri_len); - } else { - status = _cairo_surface_base64_encode (surface, - document->xml_node_defs); - if (unlikely (status)) - return status; + _cairo_svg_stream_printf (&document->xml_node_defs, + "<image id=\"source-%d\" x=\"%d\" y=\"%d\" width=\"%d\" height=\"%d\"", + source_id, + extents.x, extents.y, + extents.width, extents.height); + + if (extents.width != 0 && extents.height != 0) { + _cairo_svg_stream_printf (&document->xml_node_defs, " xlink:href=\""); + cairo_surface_get_mime_data (surface, CAIRO_MIME_TYPE_URI, + &uri, &uri_len); + if (uri != NULL) { + _cairo_svg_surface_emit_attr_value (&document->xml_node_defs, + uri, uri_len); + } else { + status = _cairo_surface_base64_encode (surface, + &document->xml_node_defs); + if (unlikely (status)) + return status; + } + _cairo_svg_stream_printf (&document->xml_node_defs, "\""); } - _cairo_output_stream_printf (document->xml_node_defs, "\"/>\n"); + _cairo_svg_stream_printf (&document->xml_node_defs, "/>\n"); return CAIRO_STATUS_SUCCESS; } static cairo_status_t -_cairo_svg_surface_emit_composite_surface_pattern (cairo_output_stream_t *output, - cairo_svg_surface_t *svg_surface, - cairo_operator_t op, +_cairo_svg_surface_emit_composite_surface_pattern (cairo_svg_stream_t *output, + cairo_svg_surface_t *surface, cairo_surface_pattern_t *pattern, - int pattern_id, - const cairo_matrix_t *parent_matrix, - const char *extra_attributes) + unsigned int pattern_id, + const cairo_matrix_t *parent_matrix) { cairo_status_t status; - cairo_matrix_t p2u; - int source_id; - cairo_bool_t is_new; - p2u = pattern->base.matrix; + cairo_matrix_t p2u = pattern->base.matrix; status = cairo_matrix_invert (&p2u); /* cairo_pattern_set_matrix ensures the matrix is invertible */ assert (status == CAIRO_STATUS_SUCCESS); - status = _cairo_svg_surface_add_source_surface (svg_surface, + cairo_bool_t is_new; + cairo_svg_source_surface_t *source_surface; + status = _cairo_svg_surface_add_source_surface (surface, pattern->surface, - &source_id, - &is_new); - if (unlikely (status)) + &is_new, + &source_surface); + if (unlikely (status)) { return status; + } + unsigned int source_id = source_surface->id; if (is_new) { - status = _cairo_svg_surface_emit_surface (svg_surface->document, + status = _cairo_svg_surface_emit_surface (surface->document, pattern->surface, source_id); - if (unlikely (status)) + if (unlikely (status)) { return status; + } } if (pattern_id != invalid_pattern_id) { @@ -1552,70 +2177,89 @@ _cairo_svg_surface_emit_composite_surface_pattern (cairo_output_stream_t *outp is_bounded = _cairo_surface_get_extents (pattern->surface, &extents); assert (is_bounded); - _cairo_output_stream_printf (output, - "<pattern id=\"pattern%d\" " - "patternUnits=\"userSpaceOnUse\" " - "width=\"%d\" height=\"%d\" ", - pattern_id, - extents.width, extents.height); + _cairo_svg_stream_printf (output, + "<pattern id=\"pattern-%d\" " + "patternUnits=\"userSpaceOnUse\" " + "x=\"%d\" y=\"%d\" " + "width=\"%d\" height=\"%d\" " + "viewBox=\"%d %d %d %d\"", + pattern_id, + extents.x, extents.y, + extents.width, extents.height, + extents.x, extents.y, + extents.width, extents.height); _cairo_svg_surface_emit_transform (output, - " patternTransform", - &p2u, parent_matrix); - _cairo_output_stream_printf (output, ">\n "); + "patternTransform", + &p2u, + parent_matrix); + _cairo_svg_stream_printf (output, ">\n"); } - _cairo_output_stream_printf (output, - "<use xlink:href=\"#image%d\"", - source_id); - if (extra_attributes) - _cairo_output_stream_printf (output, " %s", extra_attributes); - + _cairo_svg_stream_printf (output, + "<use xlink:href=\"#source-%d\"", + source_id); + if (pattern->surface->content == CAIRO_CONTENT_ALPHA) { + cairo_bool_t can_skip_filter = FALSE; + if (pattern->surface->backend && + pattern->surface->backend->type == CAIRO_SURFACE_TYPE_IMAGE && + (((cairo_image_surface_t *) pattern->surface)->format == CAIRO_FORMAT_A1 || + ((cairo_image_surface_t *) pattern->surface)->format == CAIRO_FORMAT_A8)) { + can_skip_filter = TRUE; + } + if (!can_skip_filter) { + _cairo_svg_stream_printf (output, + " filter=\"url(#filter-%s)\"", + _cairo_svg_surface_emit_static_filter (surface->document, + CAIRO_SVG_FILTER_COLOR_TO_ALPHA)); + } + } if (pattern_id == invalid_pattern_id) { - _cairo_svg_surface_emit_operator (output, svg_surface, op); _cairo_svg_surface_emit_transform (output, - " transform", - &p2u, parent_matrix); + "transform", + &p2u, + parent_matrix); } - _cairo_output_stream_printf (output, "/>\n"); - + _cairo_svg_stream_printf (output, "/>\n"); - if (pattern_id != invalid_pattern_id) - _cairo_output_stream_printf (output, "</pattern>\n"); + if (pattern_id != invalid_pattern_id) { + _cairo_svg_stream_printf (output, "</pattern>\n"); + } return CAIRO_STATUS_SUCCESS; } static cairo_status_t -_cairo_svg_surface_emit_recording_surface (cairo_svg_document_t *document, +_cairo_svg_surface_emit_recording_surface (cairo_svg_surface_t *surface, cairo_recording_surface_t *source, - int source_id) + unsigned int source_id, + cairo_bool_t *transitive_paint_used) { cairo_status_t status; - cairo_surface_t *paginated_surface; - cairo_svg_surface_t *svg_surface; - cairo_array_t *page_set; - cairo_rectangle_int_t extents; - cairo_bool_t bounded; - cairo_output_stream_t *contents; - - bounded = _cairo_surface_get_extents (&source->base, &extents); - paginated_surface = _cairo_svg_surface_create_for_document (document, - source->base.content, - extents.width, - extents.height, - bounded); - if (unlikely (paginated_surface->status)) + cairo_svg_document_t *document = surface->document; + + cairo_surface_t *paginated_surface = _cairo_svg_surface_create_for_document (document, + source->base.content, + 0, + 0, + FALSE); + cairo_svg_surface_t *svg_surface = (cairo_svg_surface_t *) _cairo_paginated_surface_get_target (paginated_surface); + if (unlikely (paginated_surface->status)) { return paginated_surface->status; + } + + svg_surface->source_id = source_id; + svg_surface->depth = surface->depth + 1; + + cairo_rectangle_int_t extents; + cairo_bool_t bounded = _cairo_surface_get_extents (&source->base, &extents); - svg_surface = (cairo_svg_surface_t *) - _cairo_paginated_surface_get_target (paginated_surface); cairo_surface_set_fallback_resolution (paginated_surface, document->owner->x_fallback_resolution, document->owner->y_fallback_resolution); - cairo_surface_set_device_offset (&svg_surface->base, - -source->extents_pixels.x, - -source->extents_pixels.y); + if (source->base.content == CAIRO_CONTENT_COLOR) { + _cairo_svg_surface_emit_paint (&svg_surface->xml_node, svg_surface, &_cairo_pattern_black.base, FALSE); + } status = _cairo_recording_surface_replay (&source->base, paginated_surface); if (unlikely (status)) { cairo_surface_destroy (paginated_surface); @@ -1629,55 +2273,55 @@ _cairo_svg_surface_emit_recording_surface (cairo_svg_document_t *document, return status; } - if (! svg_surface->is_base_clip_emitted) { - svg_surface->is_base_clip_emitted = TRUE; - if (_cairo_surface_get_extents (&svg_surface->base, &extents)) { - _cairo_output_stream_printf (document->xml_node_defs, - "<clipPath id=\"clip%d\">\n" - " <rect x=\"%d\" y=\"%d\" width=\"%d\" height=\"%d\"/>\n" - "</clipPath>\n", - svg_surface->base_clip, - extents.x, - extents.y, - extents.width, - extents.height); - } + unsigned int clip_id; + if (bounded) { + clip_id = document->clip_id++; + + _cairo_svg_stream_printf (&document->xml_node_defs, + "<clipPath id=\"clip-%d\">\n" + "<rect x=\"%d\" y=\"%d\" width=\"%d\" height=\"%d\"/>\n" + "</clipPath>\n", + clip_id, + extents.x, + extents.y, + extents.width, + extents.height); + } + + _cairo_svg_stream_printf (&document->xml_node_defs, + "<g id=\"source-%d\"", + source_id); + + if (bounded) { + _cairo_svg_stream_printf (&document->xml_node_defs, + " clip-path=\"url(#clip-%d)\"", + clip_id); } if (source->base.content == CAIRO_CONTENT_ALPHA) { - _cairo_svg_surface_emit_alpha_filter (document); - _cairo_output_stream_printf (document->xml_node_defs, - "<g id=\"surface%d\" " - "clip-path=\"url(#clip%d)\" " - "filter=\"url(#alpha)\">\n", - source_id, - svg_surface->base_clip); - } else { - _cairo_output_stream_printf (document->xml_node_defs, - "<g id=\"surface%d\" " - "clip-path=\"url(#clip%d)\">\n", - source_id, - svg_surface->base_clip); + _cairo_svg_stream_printf (&document->xml_node_defs, + " filter=\"url(#filter-%s)\"", + _cairo_svg_surface_emit_static_filter (document, CAIRO_SVG_FILTER_REMOVE_COLOR)); } - contents = svg_surface->xml_node; - page_set = &svg_surface->page_set; + _cairo_svg_stream_printf (&document->xml_node_defs, ">\n"); - if (_cairo_memory_stream_length (contents) > 0) { - if (unlikely (_cairo_svg_surface_store_page (svg_surface) == NULL)) { + if (svg_surface->xml_node.elements.num_elements > 0) { + cairo_svg_page_t *page = _cairo_svg_surface_store_page (svg_surface); + if (unlikely (page == NULL)) { cairo_surface_destroy (paginated_surface); return _cairo_error (CAIRO_STATUS_NO_MEMORY); } } - if (page_set->num_elements > 0) { - cairo_svg_page_t *page; - - page = _cairo_array_index (page_set, page_set->num_elements - 1); - _cairo_memory_stream_copy (page->xml_node, document->xml_node_defs); + if (svg_surface->page_set.num_elements > 0) { + cairo_svg_page_t *page = _cairo_array_index (&svg_surface->page_set, svg_surface->page_set.num_elements - 1); + _cairo_svg_stream_copy (&page->xml_node, &document->xml_node_defs); } - _cairo_output_stream_printf (document->xml_node_defs, "</g>\n"); + _cairo_svg_stream_printf (&document->xml_node_defs, "</g>\n"); + + *transitive_paint_used = svg_surface->transitive_paint_used; status = cairo_surface_status (paginated_surface); cairo_surface_destroy (paginated_surface); @@ -1686,7 +2330,7 @@ _cairo_svg_surface_emit_recording_surface (cairo_svg_document_t *document, } static cairo_recording_surface_t * -to_recording_surface (const cairo_surface_pattern_t *pattern) +_cairo_svg_surface_to_recording_surface (const cairo_surface_pattern_t *pattern) { cairo_surface_t *surface = pattern->surface; if (_cairo_surface_is_paginated (surface)) @@ -1696,192 +2340,256 @@ to_recording_surface (const cairo_surface_pattern_t *pattern) return (cairo_recording_surface_t *) surface; } +static cairo_bool_t +_cairo_svg_surface_svg_pattern_should_be_used (const cairo_pattern_t *pattern) +{ + cairo_rectangle_int_t extents; + return pattern->type == CAIRO_PATTERN_TYPE_SURFACE && + pattern->extend == CAIRO_EXTEND_REPEAT && + _cairo_surface_get_extents (((cairo_surface_pattern_t *) pattern)->surface, &extents); +} + +static cairo_bool_t +_cairo_svg_surface_svg_clip_or_svg_mask_should_be_used (const cairo_pattern_t *pattern) +{ + return pattern->type == CAIRO_PATTERN_TYPE_SURFACE && !_cairo_svg_surface_svg_pattern_should_be_used (pattern); +} + static cairo_status_t -_cairo_svg_surface_emit_composite_recording_pattern (cairo_output_stream_t *output, - cairo_svg_surface_t *surface, - cairo_operator_t op, - cairo_surface_pattern_t *pattern, - int pattern_id, - const cairo_matrix_t *parent_matrix, - const char *extra_attributes) +_cairo_svg_surface_emit_composite_recording_pattern (cairo_svg_stream_t *output, + cairo_svg_surface_t *surface, + cairo_surface_pattern_t *pattern, + unsigned int pattern_id, + const cairo_matrix_t *parent_matrix) { - cairo_svg_document_t *document = surface->document; - cairo_recording_surface_t *recording_surface; - cairo_matrix_t p2u; cairo_status_t status; - int source_id; - cairo_bool_t is_new; + cairo_svg_document_t *document = surface->document; - p2u = pattern->base.matrix; + cairo_matrix_t p2u = pattern->base.matrix; status = cairo_matrix_invert (&p2u); /* cairo_pattern_set_matrix ensures the matrix is invertible */ assert (status == CAIRO_STATUS_SUCCESS); + cairo_bool_t is_new; + cairo_svg_source_surface_t *source_surface; status = _cairo_svg_surface_add_source_surface (surface, pattern->surface, - &source_id, - &is_new); - if (unlikely (status)) + &is_new, + &source_surface); + if (unlikely (status)) { return status; + } + unsigned int source_id = source_surface->id; - recording_surface = to_recording_surface (pattern); + cairo_recording_surface_t *recording_surface = _cairo_svg_surface_to_recording_surface (pattern); if (is_new) { - status = _cairo_svg_surface_emit_recording_surface (document, recording_surface, source_id); - if (unlikely (status)) + status = _cairo_svg_surface_emit_recording_surface (surface, + recording_surface, + source_id, + &source_surface->transitive_paint_used); + if (unlikely (status)) { return status; + } + + if (source_surface->transitive_paint_used) { + cairo_svg_paint_t *paint_entry = malloc (sizeof (cairo_svg_paint_t)); + if (paint_entry == NULL) { + return _cairo_error (CAIRO_STATUS_NO_MEMORY); + } + paint_entry->source_id = source_id; + _cairo_array_init (&paint_entry->paint_elements, sizeof (cairo_svg_paint_element_t)); + _cairo_svg_paint_init_key (paint_entry); + status = _cairo_hash_table_insert (document->paints, &paint_entry->base); + if (unlikely (status)) { + return status; + } + } + } + + if (source_surface->transitive_paint_used) { + cairo_svg_paint_t paint_key; + paint_key.source_id = source_id; + _cairo_svg_paint_init_key (&paint_key); + + cairo_svg_paint_t *found_paint_entry = _cairo_hash_table_lookup (document->paints, + &paint_key.base); + assert (found_paint_entry); + + cairo_svg_paint_element_t paint_element; + paint_element.source_id = surface->source_id; + paint_element.matrix = pattern->base.matrix; + if (parent_matrix != NULL) { + cairo_matrix_t parent_matrix_inverse = *parent_matrix; + status = cairo_matrix_invert (&parent_matrix_inverse); + /* cairo_pattern_set_matrix ensures the matrix is invertible */ + assert (status == CAIRO_STATUS_SUCCESS); + cairo_matrix_multiply (&paint_element.matrix, &parent_matrix_inverse, &paint_element.matrix); + } + status = _cairo_array_append (&found_paint_entry->paint_elements, &paint_element); + if (unlikely (status)) { + return status; + } + + surface->transitive_paint_used = TRUE; } if (pattern_id != invalid_pattern_id) { - _cairo_output_stream_printf (output, - "<pattern id=\"pattern%d\" " - "patternUnits=\"userSpaceOnUse\" " - "width=\"%d\" height=\"%d\"", - pattern_id, - recording_surface->extents.width, - recording_surface->extents.height); - _cairo_svg_surface_emit_transform (output, " patternTransform", &p2u, parent_matrix); - _cairo_output_stream_printf (output, ">\n"); + assert (!recording_surface->unbounded); + _cairo_svg_stream_printf (output, + "<pattern id=\"pattern-%d\" " + "patternUnits=\"userSpaceOnUse\" " + "x=\"%f\" y=\"%f\" width=\"%f\" height=\"%f\" " + "viewBox=\"%f %f %f %f\"", + pattern_id, + recording_surface->extents_pixels.x, + recording_surface->extents_pixels.y, + recording_surface->extents_pixels.width, + recording_surface->extents_pixels.height, + recording_surface->extents_pixels.x, + recording_surface->extents_pixels.y, + recording_surface->extents_pixels.width, + recording_surface->extents_pixels.height); + _cairo_svg_surface_emit_transform (output, "patternTransform", &p2u, parent_matrix); + _cairo_svg_stream_printf (output, ">\n"); } - _cairo_output_stream_printf (output, - "<use xlink:href=\"#surface%d\"", - source_id); + _cairo_svg_stream_printf (output, + "<use xlink:href=\"#source-%d\"", + source_id); if (pattern_id == invalid_pattern_id) { - _cairo_svg_surface_emit_operator (output, surface, op); - _cairo_svg_surface_emit_transform (output, " transform", &p2u, parent_matrix); + _cairo_svg_surface_emit_transform (output, "transform", &p2u, parent_matrix); } - if (extra_attributes) - _cairo_output_stream_printf (output, " %s", extra_attributes); + _cairo_svg_stream_printf (output, "/>\n"); - _cairo_output_stream_printf (output, "/>\n"); - - if (pattern_id != invalid_pattern_id) - _cairo_output_stream_printf (output, "</pattern>\n"); + if (pattern_id != invalid_pattern_id) { + _cairo_svg_stream_printf (output, "</pattern>\n"); + } return CAIRO_STATUS_SUCCESS; } static cairo_status_t -_cairo_svg_surface_emit_composite_pattern (cairo_output_stream_t *output, - cairo_svg_surface_t *surface, - cairo_operator_t op, +_cairo_svg_surface_emit_composite_pattern (cairo_svg_stream_t *output, + cairo_svg_surface_t *surface, cairo_surface_pattern_t *pattern, - int pattern_id, - const cairo_matrix_t *parent_matrix, - const char *extra_attributes) + unsigned int pattern_id, + const cairo_matrix_t *parent_matrix) { + if (pattern_id != invalid_pattern_id) { + assert (_cairo_svg_surface_svg_pattern_should_be_used (&pattern->base)); + } if (pattern->surface->type == CAIRO_SURFACE_TYPE_RECORDING) { - return _cairo_svg_surface_emit_composite_recording_pattern (output, surface, - op, pattern, + return _cairo_svg_surface_emit_composite_recording_pattern (output, + surface, + pattern, pattern_id, - parent_matrix, - extra_attributes); + parent_matrix); + } else { + return _cairo_svg_surface_emit_composite_surface_pattern (output, + surface, + pattern, + pattern_id, + parent_matrix); } - - return _cairo_svg_surface_emit_composite_surface_pattern (output, surface, - op, pattern, - pattern_id, - parent_matrix, - extra_attributes); } static cairo_status_t -_cairo_svg_surface_emit_solid_pattern (cairo_svg_surface_t *surface, - cairo_solid_pattern_t *pattern, - cairo_output_stream_t *style, - cairo_bool_t is_stroke) -{ - _cairo_output_stream_printf (style, is_stroke ? - "stroke:rgb(%f%%,%f%%,%f%%);stroke-opacity:%f;": - "fill:rgb(%f%%,%f%%,%f%%);fill-opacity:%f;", - pattern->color.red * 100.0, - pattern->color.green * 100.0, - pattern->color.blue * 100.0, - pattern->color.alpha); +_cairo_svg_surface_emit_solid_pattern (cairo_svg_surface_t *surface, + cairo_solid_pattern_t *pattern, + cairo_svg_stream_t *output, + cairo_bool_t is_stroke) +{ + _cairo_svg_stream_printf (output, + is_stroke ? " stroke=\"rgb(%f%%, %f%%, %f%%)\" stroke-opacity=\"%f\"" + : " fill=\"rgb(%f%%, %f%%, %f%%)\" fill-opacity=\"%f\"", + pattern->color.red * 100.0, + pattern->color.green * 100.0, + pattern->color.blue * 100.0, + pattern->color.alpha); return CAIRO_STATUS_SUCCESS; } static cairo_status_t -_cairo_svg_surface_emit_surface_pattern (cairo_svg_surface_t *surface, +_cairo_svg_surface_emit_surface_pattern (cairo_svg_surface_t *surface, cairo_surface_pattern_t *pattern, - cairo_output_stream_t *style, - cairo_bool_t is_stroke, - const cairo_matrix_t *parent_matrix) + cairo_svg_stream_t *output, + cairo_bool_t is_stroke, + const cairo_matrix_t *parent_matrix) { cairo_svg_document_t *document = surface->document; cairo_status_t status; - int pattern_id; - pattern_id = document->pattern_id++; - status = _cairo_svg_surface_emit_composite_pattern (document->xml_node_defs, - surface, CAIRO_OPERATOR_SOURCE, pattern, - pattern_id, parent_matrix, NULL); + unsigned int pattern_id = document->pattern_id++; + + status = _cairo_svg_surface_emit_composite_pattern (&document->xml_node_defs, + surface, + pattern, + pattern_id, + parent_matrix); if (unlikely (status)) return status; - _cairo_output_stream_printf (style, - "%s:url(#pattern%d);", - is_stroke ? "stroke" : "fill", - pattern_id); + _cairo_svg_stream_printf (output, + is_stroke ? " stroke=\"url(#pattern-%d)\"" + : " fill=\"url(#pattern-%d)\"", + pattern_id); return CAIRO_STATUS_SUCCESS; } static cairo_status_t -_cairo_svg_surface_emit_pattern_stops (cairo_output_stream_t *output, - cairo_gradient_pattern_t const *pattern, - double start_offset, - cairo_bool_t reverse_stops, - cairo_bool_t emulate_reflect) +_cairo_svg_surface_emit_pattern_stops (cairo_svg_stream_t *output, + const cairo_gradient_pattern_t *pattern, + double start_offset, + cairo_bool_t reverse_stops, + cairo_bool_t emulate_reflect) { cairo_gradient_stop_t *stops; - double offset; unsigned int n_stops; - unsigned int i; - if (pattern->n_stops < 1) + if (pattern->n_stops < 1) { return CAIRO_STATUS_SUCCESS; + } if (pattern->n_stops == 1) { - _cairo_output_stream_printf (output, - "<stop offset=\"%f\" style=\"" - "stop-color:rgb(%f%%,%f%%,%f%%);" - "stop-opacity:%f;\"/>\n", - pattern->stops[0].offset, - pattern->stops[0].color.red * 100.0, - pattern->stops[0].color.green * 100.0, - pattern->stops[0].color.blue * 100.0, - pattern->stops[0].color.alpha); - return CAIRO_STATUS_SUCCESS; + _cairo_svg_stream_printf (output, + "<stop offset=\"%f\" " + "stop-color=\"rgb(%f%%, %f%%, %f%%)\" " + "stop-opacity=\"%f\"/>\n", + pattern->stops[0].offset, + pattern->stops[0].color.red * 100.0, + pattern->stops[0].color.green * 100.0, + pattern->stops[0].color.blue * 100.0, + pattern->stops[0].color.alpha); + return CAIRO_STATUS_SUCCESS; } if (emulate_reflect || reverse_stops) { - n_stops = emulate_reflect ? pattern->n_stops * 2 - 2: pattern->n_stops; + n_stops = emulate_reflect ? pattern->n_stops * 2 - 2 : pattern->n_stops; stops = _cairo_malloc_ab (n_stops, sizeof (cairo_gradient_stop_t)); if (unlikely (stops == NULL)) return _cairo_error (CAIRO_STATUS_NO_MEMORY); - for (i = 0; i < pattern->n_stops; i++) { + for (unsigned int i = 0; i < pattern->n_stops; i++) { if (reverse_stops) { stops[i] = pattern->stops[pattern->n_stops - i - 1]; stops[i].offset = 1.0 - stops[i].offset; - } else + } else { stops[i] = pattern->stops[i]; + } if (emulate_reflect) { - stops[i].offset /= 2; - if (i > 0 && i < (pattern->n_stops - 1)) { + stops[i].offset *= 0.5; + if (i > 0 && i < pattern->n_stops - 1) { if (reverse_stops) { stops[i + pattern->n_stops - 1] = pattern->stops[i]; - stops[i + pattern->n_stops - 1].offset = - 0.5 + 0.5 * stops[i + pattern->n_stops - 1].offset; + stops[i + pattern->n_stops - 1].offset = 0.5 + 0.5 * stops[i + pattern->n_stops - 1].offset; } else { stops[i + pattern->n_stops - 1] = pattern->stops[pattern->n_stops - i - 1]; - stops[i + pattern->n_stops - 1].offset = - 1 - 0.5 * stops[i + pattern->n_stops - 1].offset; + stops[i + pattern->n_stops - 1].offset = 1.0 - 0.5 * stops[i + pattern->n_stops - 1].offset; } } } @@ -1891,53 +2599,50 @@ _cairo_svg_surface_emit_pattern_stops (cairo_output_stream_t *output, stops = pattern->stops; } - if (start_offset >= 0.0) - for (i = 0; i < n_stops; i++) { - offset = start_offset + (1 - start_offset ) * stops[i].offset; - _cairo_output_stream_printf (output, - "<stop offset=\"%f\" style=\"" - "stop-color:rgb(%f%%,%f%%,%f%%);" - "stop-opacity:%f;\"/>\n", - offset, - stops[i].color.red * 100.0, - stops[i].color.green * 100.0, - stops[i].color.blue * 100.0, - stops[i].color.alpha); + if (start_offset >= 0.0) { + for (unsigned int i = 0; i < n_stops; i++) { + _cairo_svg_stream_printf (output, + "<stop offset=\"%f\" " + "stop-color=\"rgb(%f%%, %f%%, %f%%)\" " + "stop-opacity=\"%f\"/>\n", + start_offset + (1.0 - start_offset) * stops[i].offset, + stops[i].color.red * 100.0, + stops[i].color.green * 100.0, + stops[i].color.blue * 100.0, + stops[i].color.alpha); } - else { + } else { cairo_bool_t found = FALSE; unsigned int offset_index; cairo_color_stop_t offset_color_start, offset_color_stop; - for (i = 0; i < n_stops; i++) { - if (stops[i].offset >= -start_offset) { + for (unsigned int i = 0; i <= n_stops; i++) { + double x1 = i == n_stops ? stops[0].offset + 1 : stops[i].offset; + cairo_color_stop_t *color1 = i == n_stops ? &stops[0].color : &stops[i].color; + if (x1 >= -start_offset) { if (i > 0) { - if (stops[i].offset != stops[i-1].offset) { - double x0, x1; - cairo_color_stop_t *color0, *color1; - - x0 = stops[i-1].offset; - x1 = stops[i].offset; - color0 = &stops[i-1].color; - color1 = &stops[i].color; + double x0 = stops[i - 1].offset; + cairo_color_stop_t *color0 = &stops[i - 1].color; + if (x0 != x1) { offset_color_start.red = color0->red + (color1->red - color0->red) - * (-start_offset - x0) / (x1 - x0); + * (-start_offset - x0) / (x1 - x0); offset_color_start.green = color0->green + (color1->green - color0->green) - * (-start_offset - x0) / (x1 - x0); + * (-start_offset - x0) / (x1 - x0); offset_color_start.blue = color0->blue + (color1->blue - color0->blue) - * (-start_offset - x0) / (x1 - x0); + * (-start_offset - x0) / (x1 - x0); offset_color_start.alpha = color0->alpha + (color1->alpha - color0->alpha) - * (-start_offset - x0) / (x1 - x0); + * (-start_offset - x0) / (x1 - x0); offset_color_stop = offset_color_start; } else { - offset_color_stop = stops[i-1].color; + offset_color_stop = stops[i - 1].color; offset_color_start = stops[i].color; } - } else - offset_color_stop = offset_color_start = stops[i].color; - offset_index = i; - found = TRUE; - break; + } else { + offset_color_stop = offset_color_start = stops[i].color; + } + offset_index = i; + found = TRUE; + break; } } @@ -1946,136 +2651,134 @@ _cairo_svg_surface_emit_pattern_stops (cairo_output_stream_t *output, offset_color_stop = offset_color_start = stops[offset_index].color; } - _cairo_output_stream_printf (output, - "<stop offset=\"0\" style=\"" - "stop-color:rgb(%f%%,%f%%,%f%%);" - "stop-opacity:%f;\"/>\n", - offset_color_start.red * 100.0, - offset_color_start.green * 100.0, - offset_color_start.blue * 100.0, - offset_color_start.alpha); - for (i = offset_index; i < n_stops; i++) { - _cairo_output_stream_printf (output, - "<stop offset=\"%f\" style=\"" - "stop-color:rgb(%f%%,%f%%,%f%%);" - "stop-opacity:%f;\"/>\n", - stops[i].offset + start_offset, - stops[i].color.red * 100.0, - stops[i].color.green * 100.0, - stops[i].color.blue * 100.0, - stops[i].color.alpha); + _cairo_svg_stream_printf (output, + "<stop offset=\"0\" " + "stop-color=\"rgb(%f%%, %f%%, %f%%)\" " + "stop-opacity=\"%f\"/>\n", + offset_color_start.red * 100.0, + offset_color_start.green * 100.0, + offset_color_start.blue * 100.0, + offset_color_start.alpha); + for (unsigned int i = offset_index; i < n_stops; i++) { + _cairo_svg_stream_printf (output, + "<stop offset=\"%f\" " + "stop-color=\"rgb(%f%%, %f%%, %f%%)\" " + "stop-opacity=\"%f\"/>\n", + stops[i].offset + start_offset, + stops[i].color.red * 100.0, + stops[i].color.green * 100.0, + stops[i].color.blue * 100.0, + stops[i].color.alpha); } - for (i = 0; i < offset_index; i++) { - _cairo_output_stream_printf (output, - "<stop offset=\"%f\" style=\"" - "stop-color:rgb(%f%%,%f%%,%f%%);" - "stop-opacity:%f;\"/>\n", - 1.0 + stops[i].offset + start_offset, - stops[i].color.red * 100.0, - stops[i].color.green * 100.0, - stops[i].color.blue * 100.0, - stops[i].color.alpha); + for (unsigned int i = 0; i < offset_index; i++) { + _cairo_svg_stream_printf (output, + "<stop offset=\"%f\" " + "stop-color=\"rgb(%f%%, %f%%, %f%%)\" " + "stop-opacity=\"%f\"/>\n", + 1.0 + stops[i].offset + start_offset, + stops[i].color.red * 100.0, + stops[i].color.green * 100.0, + stops[i].color.blue * 100.0, + stops[i].color.alpha); } - _cairo_output_stream_printf (output, - "<stop offset=\"1\" style=\"" - "stop-color:rgb(%f%%,%f%%,%f%%);" - "stop-opacity:%f;\"/>\n", - offset_color_stop.red * 100.0, - offset_color_stop.green * 100.0, - offset_color_stop.blue * 100.0, - offset_color_stop.alpha); + _cairo_svg_stream_printf (output, + "<stop offset=\"1\" " + "stop-color=\"rgb(%f%%, %f%%, %f%%)\" " + "stop-opacity=\"%f\"/>\n", + offset_color_stop.red * 100.0, + offset_color_stop.green * 100.0, + offset_color_stop.blue * 100.0, + offset_color_stop.alpha); } - if (reverse_stops || emulate_reflect) + if (reverse_stops || emulate_reflect) { free (stops); + } return CAIRO_STATUS_SUCCESS; } static void -_cairo_svg_surface_emit_pattern_extend (cairo_output_stream_t *output, - cairo_pattern_t *pattern) +_cairo_svg_surface_emit_pattern_extend (cairo_svg_stream_t *output, + cairo_pattern_t *pattern) { switch (pattern->extend) { - case CAIRO_EXTEND_REPEAT: - _cairo_output_stream_printf (output, "spreadMethod=\"repeat\" "); - break; - case CAIRO_EXTEND_REFLECT: - _cairo_output_stream_printf (output, "spreadMethod=\"reflect\" "); - break; - case CAIRO_EXTEND_NONE: - case CAIRO_EXTEND_PAD: - break; + case CAIRO_EXTEND_REPEAT: + _cairo_svg_stream_printf (output, " spreadMethod=\"repeat\""); + break; + case CAIRO_EXTEND_REFLECT: + _cairo_svg_stream_printf (output, " spreadMethod=\"reflect\""); + break; + case CAIRO_EXTEND_NONE: + case CAIRO_EXTEND_PAD: + break; } } static cairo_status_t -_cairo_svg_surface_emit_linear_pattern (cairo_svg_surface_t *surface, +_cairo_svg_surface_emit_linear_pattern (cairo_svg_surface_t *surface, cairo_linear_pattern_t *pattern, - cairo_output_stream_t *style, - cairo_bool_t is_stroke, - const cairo_matrix_t *parent_matrix) + cairo_svg_stream_t *output, + cairo_bool_t is_stroke, + const cairo_matrix_t *parent_matrix) { - cairo_svg_document_t *document = surface->document; - cairo_matrix_t p2u; cairo_status_t status; + cairo_svg_document_t *document = surface->document; - p2u = pattern->base.base.matrix; + cairo_matrix_t p2u = pattern->base.base.matrix; status = cairo_matrix_invert (&p2u); /* cairo_pattern_set_matrix ensures the matrix is invertible */ assert (status == CAIRO_STATUS_SUCCESS); - _cairo_output_stream_printf (document->xml_node_defs, - "<linearGradient id=\"linear%d\" " - "gradientUnits=\"userSpaceOnUse\" " - "x1=\"%f\" y1=\"%f\" x2=\"%f\" y2=\"%f\" ", - document->linear_pattern_id, - pattern->pd1.x, pattern->pd1.y, - pattern->pd2.x, pattern->pd2.y); - - _cairo_svg_surface_emit_pattern_extend (document->xml_node_defs, &pattern->base.base), - _cairo_svg_surface_emit_transform (document->xml_node_defs, "gradientTransform", &p2u, parent_matrix); - _cairo_output_stream_printf (document->xml_node_defs, ">\n"); - - status = _cairo_svg_surface_emit_pattern_stops (document->xml_node_defs, - &pattern->base, 0.0, - FALSE, FALSE); + unsigned int linear_pattern_id = document->linear_pattern_id++; + + _cairo_svg_stream_printf (&document->xml_node_defs, + "<linearGradient id=\"linear-pattern-%d\" " + "gradientUnits=\"userSpaceOnUse\" " + "x1=\"%f\" y1=\"%f\" x2=\"%f\" y2=\"%f\"", + linear_pattern_id, + pattern->pd1.x, pattern->pd1.y, + pattern->pd2.x, pattern->pd2.y); + + _cairo_svg_surface_emit_pattern_extend (&document->xml_node_defs, &pattern->base.base); + _cairo_svg_surface_emit_transform (&document->xml_node_defs, "gradientTransform", &p2u, parent_matrix); + _cairo_svg_stream_printf (&document->xml_node_defs, ">\n"); + + status = _cairo_svg_surface_emit_pattern_stops (&document->xml_node_defs, + &pattern->base, + 0.0, + FALSE, + FALSE); if (unlikely (status)) return status; - _cairo_output_stream_printf (document->xml_node_defs, - "</linearGradient>\n"); - - _cairo_output_stream_printf (style, - "%s:url(#linear%d);", - is_stroke ? "stroke" : "fill", - document->linear_pattern_id); + _cairo_svg_stream_printf (&document->xml_node_defs, + "</linearGradient>\n"); - document->linear_pattern_id++; + _cairo_svg_stream_printf (output, + is_stroke ? " stroke=\"url(#linear-pattern-%d)\"" + : " fill=\"url(#linear-pattern-%d)\"", + linear_pattern_id); return CAIRO_STATUS_SUCCESS; } static cairo_status_t -_cairo_svg_surface_emit_radial_pattern (cairo_svg_surface_t *surface, +_cairo_svg_surface_emit_radial_pattern (cairo_svg_surface_t *surface, cairo_radial_pattern_t *pattern, - cairo_output_stream_t *style, - cairo_bool_t is_stroke, - const cairo_matrix_t *parent_matrix) + cairo_svg_stream_t *output, + cairo_bool_t is_stroke, + const cairo_matrix_t *parent_matrix) { - cairo_svg_document_t *document = surface->document; - cairo_matrix_t p2u; - cairo_extend_t extend; - double x0, y0, x1, y1, r0, r1; - double fx, fy; - cairo_bool_t reverse_stops; cairo_status_t status; - cairo_circle_double_t *c0, *c1; + cairo_svg_document_t *document = surface->document; - extend = pattern->base.base.extend; + cairo_extend_t extend = pattern->base.base.extend; + cairo_bool_t reverse_stops; + cairo_circle_double_t *c0, *c1; if (pattern->cd1.radius < pattern->cd2.radius) { c0 = &pattern->cd1; c1 = &pattern->cd2; @@ -2086,166 +2789,126 @@ _cairo_svg_surface_emit_radial_pattern (cairo_svg_surface_t *surface, reverse_stops = TRUE; } - x0 = c0->center.x; - y0 = c0->center.y; - r0 = c0->radius; - x1 = c1->center.x; - y1 = c1->center.y; - r1 = c1->radius; + double x0 = c0->center.x; + double y0 = c0->center.y; + double r0 = c0->radius; + double x1 = c1->center.x; + double y1 = c1->center.y; + double r1 = c1->radius; - p2u = pattern->base.base.matrix; + cairo_matrix_t p2u = pattern->base.base.matrix; status = cairo_matrix_invert (&p2u); /* cairo_pattern_set_matrix ensures the matrix is invertible */ assert (status == CAIRO_STATUS_SUCCESS); - if (r0 == r1) { - unsigned int n_stops = pattern->base.n_stops; - - _cairo_output_stream_printf (document->xml_node_defs, - "<radialGradient id=\"radial%d\" " - "gradientUnits=\"userSpaceOnUse\" " - "cx=\"%f\" cy=\"%f\" " - "fx=\"%f\" fy=\"%f\" r=\"%f\" ", - document->radial_pattern_id, - x1, y1, - x1, y1, r1); - _cairo_svg_surface_emit_transform (document->xml_node_defs, - "gradientTransform", - &p2u, parent_matrix); - _cairo_output_stream_printf (document->xml_node_defs, ">\n"); - - if (extend == CAIRO_EXTEND_NONE || n_stops < 1) - _cairo_output_stream_printf (document->xml_node_defs, - "<stop offset=\"0\" style=\"" - "stop-color:rgb(0%%,0%%,0%%);" - "stop-opacity:0;\"/>\n"); - else { - _cairo_output_stream_printf (document->xml_node_defs, - "<stop offset=\"0\" style=\"" - "stop-color:rgb(%f%%,%f%%,%f%%);" - "stop-opacity %f;\"/>\n", - pattern->base.stops[0].color.red * 100.0, - pattern->base.stops[0].color.green * 100.0, - pattern->base.stops[0].color.blue * 100.0, - pattern->base.stops[0].color.alpha); - if (n_stops > 1) - _cairo_output_stream_printf (document->xml_node_defs, - "<stop offset=\"0\" style=\"" - "stop-color:rgb(%f%%,%f%%,%f%%);" - "stop-opacity:%f;\"/>\n", - pattern->base.stops[n_stops - 1].color.red * 100.0, - pattern->base.stops[n_stops - 1].color.green * 100.0, - pattern->base.stops[n_stops - 1].color.blue * 100.0, - pattern->base.stops[n_stops - 1].color.alpha); - } + unsigned int radial_pattern_id = document->radial_pattern_id++; - } else { - double offset, r, x, y; - cairo_bool_t emulate_reflect = FALSE; - - fx = (r1 * x0 - r0 * x1) / (r1 - r0); - fy = (r1 * y0 - r0 * y1) / (r1 - r0); - - /* SVG doesn't support the inner circle and use instead a gradient focal. - * That means we need to emulate the cairo behaviour by processing the - * cairo gradient stops. - * The CAIRO_EXTENT_NONE and CAIRO_EXTENT_PAD modes are quite easy to handle, - * it's just a matter of stop position translation and calculation of - * the corresponding SVG radial gradient focal. - * The CAIRO_EXTENT_REFLECT and CAIRO_EXTEND_REPEAT modes require to compute a new - * radial gradient, with an new outer circle, equal to r1 - r0 in the CAIRO_EXTEND_REPEAT - * case, and 2 * (r1 - r0) in the CAIRO_EXTENT_REFLECT case, and a new gradient stop - * list that maps to the original cairo stop list. - */ - if ((extend == CAIRO_EXTEND_REFLECT - || extend == CAIRO_EXTEND_REPEAT) - && r0 > 0.0) { - double r_org = r1; - - if (extend == CAIRO_EXTEND_REFLECT) { - r1 = 2 * r1 - r0; - emulate_reflect = TRUE; - } + double start_offset; + cairo_bool_t emulate_reflect = FALSE; - offset = fmod (r1, r1 - r0) / (r1 - r0) - 1.0; - r = r1 - r0; + double fx = (r1 * x0 - r0 * x1) / (r1 - r0); + double fy = (r1 * y0 - r0 * y1) / (r1 - r0); - /* New position of outer circle. */ - x = r * (x1 - fx) / r_org + fx; - y = r * (y1 - fy) / r_org + fy; + /* SVG doesn't support the inner circle and use instead a gradient focal. + * That means we need to emulate the cairo behaviour by processing the + * cairo gradient stops. + * The CAIRO_EXTEND_NONE and CAIRO_EXTEND_PAD modes are quite easy to handle, + * it's just a matter of stop position translation and calculation of + * the corresponding SVG radial gradient focal. + * The CAIRO_EXTEND_REFLECT and CAIRO_EXTEND_REPEAT modes require to compute a new + * radial gradient, with an new outer circle, equal to r1 - r0 in the CAIRO_EXTEND_REPEAT + * case, and 2 * r1 - r0 in the CAIRO_EXTEND_REFLECT case, and a new gradient stop + * list that maps to the original cairo stop list. + */ + if ((extend == CAIRO_EXTEND_REFLECT || extend == CAIRO_EXTEND_REPEAT) && r0 > 0.0) { + double r_org = r1; - x1 = x; - y1 = y; - r1 = r; - r0 = 0.0; - } else { - offset = r0 / r1; + if (extend == CAIRO_EXTEND_REFLECT) { + r1 = 2.0 * r1 - r0; + emulate_reflect = TRUE; } - _cairo_output_stream_printf (document->xml_node_defs, - "<radialGradient id=\"radial%d\" " - "gradientUnits=\"userSpaceOnUse\" " - "cx=\"%f\" cy=\"%f\" " - "fx=\"%f\" fy=\"%f\" r=\"%f\" ", - document->radial_pattern_id, - x1, y1, - fx, fy, r1); - - if (emulate_reflect) - _cairo_output_stream_printf (document->xml_node_defs, "spreadMethod=\"repeat\" "); - else - _cairo_svg_surface_emit_pattern_extend (document->xml_node_defs, &pattern->base.base); - _cairo_svg_surface_emit_transform (document->xml_node_defs, "gradientTransform", &p2u, parent_matrix); - _cairo_output_stream_printf (document->xml_node_defs, ">\n"); - - /* To support cairo's EXTEND_NONE, (for which SVG has no similar - * notion), we add transparent color stops on either end of the - * user-provided stops. */ - if (extend == CAIRO_EXTEND_NONE) { - _cairo_output_stream_printf (document->xml_node_defs, - "<stop offset=\"0\" style=\"" - "stop-color:rgb(0%%,0%%,0%%);" - "stop-opacity:0;\"/>\n"); - if (r0 != 0.0) - _cairo_output_stream_printf (document->xml_node_defs, - "<stop offset=\"%f\" style=\"" - "stop-color:rgb(0%%,0%%,0%%);" - "stop-opacity:0;\"/>\n", - r0 / r1); - } - status = _cairo_svg_surface_emit_pattern_stops (document->xml_node_defs, - &pattern->base, offset, - reverse_stops, - emulate_reflect); - if (unlikely (status)) - return status; + start_offset = fmod (r1, r1 - r0) / (r1 - r0) - 1.0; + double r = r1 - r0; - if (pattern->base.base.extend == CAIRO_EXTEND_NONE) - _cairo_output_stream_printf (document->xml_node_defs, - "<stop offset=\"1.0\" style=\"" - "stop-color:rgb(0%%,0%%,0%%);" - "stop-opacity:0;\"/>\n"); + /* New position of outer circle. */ + double x = r * (x1 - fx) / r_org + fx; + double y = r * (y1 - fy) / r_org + fy; + + x1 = x; + y1 = y; + r1 = r; + r0 = 0.0; + } else { + start_offset = r0 / r1; + } + + _cairo_svg_stream_printf (&document->xml_node_defs, + "<radialGradient id=\"radial-pattern-%d\" " + "gradientUnits=\"userSpaceOnUse\" " + "cx=\"%f\" cy=\"%f\" " + "fx=\"%f\" fy=\"%f\" r=\"%f\"", + radial_pattern_id, + x1, y1, + fx, fy, r1); + + if (emulate_reflect) { + _cairo_svg_stream_printf (&document->xml_node_defs, " spreadMethod=\"repeat\""); + } else { + _cairo_svg_surface_emit_pattern_extend (&document->xml_node_defs, &pattern->base.base); + } + _cairo_svg_surface_emit_transform (&document->xml_node_defs, "gradientTransform", &p2u, parent_matrix); + _cairo_svg_stream_printf (&document->xml_node_defs, ">\n"); + + /* To support cairo's EXTEND_NONE, (for which SVG has no similar + * notion), we add transparent color stops on either end of the + * user-provided stops. */ + if (extend == CAIRO_EXTEND_NONE) { + _cairo_svg_stream_printf (&document->xml_node_defs, + "<stop offset=\"0\" " + "stop-color=\"rgb(0%%, 0%%, 0%%)\" " + "stop-opacity=\"0\"/>\n"); + if (r0 != 0.0) { + _cairo_svg_stream_printf (&document->xml_node_defs, + "<stop offset=\"%f\" " + "stop-color=\"rgb(0%%, 0%%, 0%%)\" " + "stop-opacity=\"0\"/>\n", + r0 / r1); + } + } + status = _cairo_svg_surface_emit_pattern_stops (&document->xml_node_defs, + &pattern->base, + start_offset, + reverse_stops, + emulate_reflect); + if (unlikely (status)) { + return status; } - _cairo_output_stream_printf (document->xml_node_defs, - "</radialGradient>\n"); + if (pattern->base.base.extend == CAIRO_EXTEND_NONE) { + _cairo_svg_stream_printf (&document->xml_node_defs, + "<stop offset=\"1\" " + "stop-color=\"rgb(0%%, 0%%, 0%%)\" " + "stop-opacity=\"0\"/>\n"); + } - _cairo_output_stream_printf (style, - "%s:url(#radial%d);", - is_stroke ? "stroke" : "fill", - document->radial_pattern_id); + _cairo_svg_stream_printf (&document->xml_node_defs, + "</radialGradient>\n"); - document->radial_pattern_id++; + _cairo_svg_stream_printf (output, + is_stroke ? " stroke=\"url(#radial-pattern-%d)\"" + : " fill=\"url(#radial-pattern-%d)\"", + radial_pattern_id); return CAIRO_STATUS_SUCCESS; } static cairo_status_t -_cairo_svg_surface_emit_pattern (cairo_svg_surface_t *surface, - const cairo_pattern_t *pattern, - cairo_output_stream_t *output, - cairo_bool_t is_stroke, - const cairo_matrix_t *parent_matrix) +_cairo_svg_surface_emit_pattern (cairo_svg_surface_t *surface, + const cairo_pattern_t *pattern, + cairo_svg_stream_t *output, + cairo_bool_t is_stroke, + const cairo_matrix_t *parent_matrix) { switch (pattern->type) { case CAIRO_PATTERN_TYPE_SOLID: @@ -2272,176 +2935,98 @@ _cairo_svg_surface_emit_pattern (cairo_svg_surface_t *surface, } static cairo_status_t -_cairo_svg_surface_emit_fill_style (cairo_output_stream_t *output, - cairo_svg_surface_t *surface, - cairo_operator_t op, - const cairo_pattern_t *source, - cairo_fill_rule_t fill_rule, - const cairo_matrix_t *parent_matrix) +_cairo_svg_surface_emit_fill_style (cairo_svg_stream_t *output, + cairo_svg_surface_t *surface, + const cairo_pattern_t *source, + cairo_fill_rule_t fill_rule, + const cairo_matrix_t *parent_matrix) { - _cairo_output_stream_printf (output, - "fill-rule:%s;", - fill_rule == CAIRO_FILL_RULE_EVEN_ODD ? - "evenodd" : "nonzero"); - _cairo_svg_surface_emit_operator_for_style (output, surface, op); + _cairo_svg_stream_printf (output, + " fill-rule=\"%s\"", + fill_rule == CAIRO_FILL_RULE_EVEN_ODD ? "evenodd" : "nonzero"); return _cairo_svg_surface_emit_pattern (surface, source, output, FALSE, parent_matrix); } static cairo_status_t -_cairo_svg_surface_emit_stroke_style (cairo_output_stream_t *output, - cairo_svg_surface_t *surface, - cairo_operator_t op, - const cairo_pattern_t *source, - const cairo_stroke_style_t *stroke_style, - const cairo_matrix_t *parent_matrix) +_cairo_svg_surface_emit_stroke_style (cairo_svg_stream_t *output, + cairo_svg_surface_t *surface, + const cairo_pattern_t *source, + const cairo_stroke_style_t *stroke_style, + const cairo_matrix_t *parent_matrix) { cairo_status_t status; const char *line_cap, *line_join; unsigned int i; switch (stroke_style->line_cap) { - case CAIRO_LINE_CAP_BUTT: - line_cap = "butt"; - break; - case CAIRO_LINE_CAP_ROUND: - line_cap = "round"; - break; - case CAIRO_LINE_CAP_SQUARE: - line_cap = "square"; - break; - default: - ASSERT_NOT_REACHED; + case CAIRO_LINE_CAP_BUTT: + line_cap = "butt"; + break; + case CAIRO_LINE_CAP_ROUND: + line_cap = "round"; + break; + case CAIRO_LINE_CAP_SQUARE: + line_cap = "square"; + break; + default: + ASSERT_NOT_REACHED; } switch (stroke_style->line_join) { - case CAIRO_LINE_JOIN_MITER: - line_join = "miter"; - break; - case CAIRO_LINE_JOIN_ROUND: - line_join = "round"; - break; - case CAIRO_LINE_JOIN_BEVEL: - line_join = "bevel"; - break; - default: - ASSERT_NOT_REACHED; + case CAIRO_LINE_JOIN_MITER: + line_join = "miter"; + break; + case CAIRO_LINE_JOIN_ROUND: + line_join = "round"; + break; + case CAIRO_LINE_JOIN_BEVEL: + line_join = "bevel"; + break; + default: + ASSERT_NOT_REACHED; } - _cairo_output_stream_printf (output, - "stroke-width:%f;" - "stroke-linecap:%s;" - "stroke-linejoin:%s;", - stroke_style->line_width, - line_cap, - line_join); - - status = _cairo_svg_surface_emit_pattern (surface, source, output, TRUE, parent_matrix); - if (unlikely (status)) - return status; + if (stroke_style->is_hairline) { + _cairo_svg_stream_printf (output, + " stroke-width=\"1px\"" + " stroke-linecap=\"%s\"" + " stroke-linejoin=\"%s\"" + " style=\"vector-effect: non-scaling-stroke\"", + line_cap, + line_join); + } else { + _cairo_svg_stream_printf (output, + " stroke-width=\"%f\"" + " stroke-linecap=\"%s\"" + " stroke-linejoin=\"%s\"", + stroke_style->line_width, + line_cap, + line_join); + } - _cairo_svg_surface_emit_operator_for_style (output, surface, op); + status = _cairo_svg_surface_emit_pattern (surface, source, output, TRUE, parent_matrix); + if (unlikely (status)) { + return status; + } if (stroke_style->num_dashes > 0) { - _cairo_output_stream_printf (output, "stroke-dasharray:"); + _cairo_svg_stream_printf (output, " stroke-dasharray=\""); for (i = 0; i < stroke_style->num_dashes; i++) { - _cairo_output_stream_printf (output, "%f", - stroke_style->dash[i]); - if (i + 1 < stroke_style->num_dashes) - _cairo_output_stream_printf (output, ","); - else - _cairo_output_stream_printf (output, ";"); + _cairo_svg_stream_printf (output, + "%f", + stroke_style->dash[i]); + _cairo_svg_stream_printf (output, i + 1 < stroke_style->num_dashes ? " " : "\""); } if (stroke_style->dash_offset != 0.0) { - _cairo_output_stream_printf (output, - "stroke-dashoffset:%f;", - stroke_style->dash_offset); + _cairo_svg_stream_printf (output, + " stroke-dashoffset=\"%f\"", + stroke_style->dash_offset); } } - _cairo_output_stream_printf (output, - "stroke-miterlimit:%f;", - stroke_style->miter_limit); - - return CAIRO_STATUS_SUCCESS; -} - -static cairo_int_status_t -_cairo_svg_surface_fill_stroke (void *abstract_surface, - cairo_operator_t fill_op, - const cairo_pattern_t *fill_source, - cairo_fill_rule_t fill_rule, - double fill_tolerance, - cairo_antialias_t fill_antialias, - const cairo_path_fixed_t*path, - cairo_operator_t stroke_op, - const cairo_pattern_t *stroke_source, - const cairo_stroke_style_t *stroke_style, - const cairo_matrix_t *stroke_ctm, - const cairo_matrix_t *stroke_ctm_inverse, - double stroke_tolerance, - cairo_antialias_t stroke_antialias, - const cairo_clip_t *clip) -{ - cairo_svg_surface_t *surface = abstract_surface; - cairo_status_t status; - - status = _cairo_surface_clipper_set_clip (&surface->clipper, clip); - if (unlikely (status)) - return status; - - _cairo_output_stream_printf (surface->xml_node, "<path style=\""); - status = _cairo_svg_surface_emit_fill_style (surface->xml_node, surface, fill_op, - fill_source, fill_rule, stroke_ctm_inverse); - if (unlikely (status)) - return status; - - status = _cairo_svg_surface_emit_stroke_style (surface->xml_node, surface, stroke_op, - stroke_source, stroke_style, stroke_ctm_inverse); - if (unlikely (status)) - return status; - - _cairo_output_stream_printf (surface->xml_node, "\" "); - - _cairo_svg_surface_emit_path (surface->xml_node, path, stroke_ctm_inverse); - - _cairo_svg_surface_emit_transform (surface->xml_node, " transform", stroke_ctm, NULL); - _cairo_output_stream_printf (surface->xml_node, "/>\n"); - - return CAIRO_STATUS_SUCCESS; -} - -static cairo_int_status_t -_cairo_svg_surface_fill (void *abstract_surface, - cairo_operator_t op, - const cairo_pattern_t *source, - const cairo_path_fixed_t*path, - cairo_fill_rule_t fill_rule, - double tolerance, - cairo_antialias_t antialias, - const cairo_clip_t *clip) -{ - cairo_svg_surface_t *surface = abstract_surface; - cairo_status_t status; - - if (surface->paginated_mode == CAIRO_PAGINATED_MODE_ANALYZE) - return _cairo_svg_surface_analyze_operation (surface, op, source); - - assert (_cairo_svg_surface_operation_supported (surface, op, source)); - - status = _cairo_surface_clipper_set_clip (&surface->clipper, clip); - if (unlikely (status)) - return status; - - _cairo_output_stream_printf (surface->xml_node, "<path style=\" stroke:none;"); - status = _cairo_svg_surface_emit_fill_style (surface->xml_node, surface, op, source, fill_rule, NULL); - if (unlikely (status)) - return status; - - _cairo_output_stream_printf (surface->xml_node, "\" "); - - _cairo_svg_surface_emit_path (surface->xml_node, path, NULL); - - _cairo_output_stream_printf (surface->xml_node, "/>\n"); + _cairo_svg_stream_printf (output, + " stroke-miterlimit=\"%f\"", + stroke_style->miter_limit); return CAIRO_STATUS_SUCCESS; } @@ -2466,50 +3051,603 @@ _cairo_svg_surface_get_extents (void *abstract_surface, } static cairo_status_t -_cairo_svg_surface_emit_paint (cairo_output_stream_t *output, - cairo_svg_surface_t *surface, - cairo_operator_t op, - const cairo_pattern_t *source, - const cairo_pattern_t *mask_source, - const char *extra_attributes) +_cairo_svg_surface_emit_paint (cairo_svg_stream_t *output, + cairo_svg_surface_t *surface, + const cairo_pattern_t *source, + cairo_bool_t at_origin) { cairo_status_t status; - if (source->type == CAIRO_PATTERN_TYPE_SURFACE && - source->extend == CAIRO_EXTEND_NONE) + if (_cairo_svg_surface_svg_clip_or_svg_mask_should_be_used (source)) { return _cairo_svg_surface_emit_composite_pattern (output, surface, - op, (cairo_surface_pattern_t *) source, invalid_pattern_id, - mask_source ? &mask_source->matrix :NULL, - extra_attributes); + NULL); + } - _cairo_output_stream_printf (output, - "<rect x=\"0\" y=\"0\" " - "width=\"%f\" height=\"%f\" " - "style=\"", - surface->width, surface->height); - _cairo_svg_surface_emit_operator_for_style (output, surface, op); + surface->transitive_paint_used = TRUE; + + _cairo_svg_stream_printf (output, "<rect"); + if (at_origin) { + _cairo_svg_stream_append_paint_dependent (output, + surface->source_id, + CAIRO_SVG_STREAM_PAINT_DEPENDENT_ELEMENT_TYPE_RECTANGLE_AT_ORIGIN); + } else { + _cairo_svg_stream_append_paint_dependent (output, + surface->source_id, + CAIRO_SVG_STREAM_PAINT_DEPENDENT_ELEMENT_TYPE_RECTANGLE); + } status = _cairo_svg_surface_emit_pattern (surface, source, output, FALSE, NULL); - if (unlikely (status)) + if (unlikely (status)) { return status; + } + _cairo_svg_stream_printf (output, "/>\n"); + + return CAIRO_STATUS_SUCCESS; +} + +static cairo_int_status_t +_cairo_svg_surface_do_operator (cairo_svg_stream_t *output, + cairo_svg_surface_t *surface, + cairo_operator_t op, + const cairo_clip_t *clip, + cairo_svg_stream_t *mask_stream, + cairo_svg_stream_t *source_stream, + cairo_svg_stream_t *destination_stream) +{ + cairo_status_t status; + cairo_svg_document_t *document = surface->document; + + // For operators that do not always produce opaque output, we first need to emit a black paint + // if the content does not have alpha + if (surface->base.content == CAIRO_CONTENT_COLOR && (op == CAIRO_OPERATOR_CLEAR || + op == CAIRO_OPERATOR_SOURCE || + op == CAIRO_OPERATOR_IN || + op == CAIRO_OPERATOR_OUT || + op == CAIRO_OPERATOR_DEST_IN || + op == CAIRO_OPERATOR_DEST_OUT || + op == CAIRO_OPERATOR_DEST_ATOP || + op == CAIRO_OPERATOR_XOR)) { + _cairo_svg_surface_emit_paint (output, surface, &_cairo_pattern_black.base, FALSE); + } + + if (op == CAIRO_OPERATOR_CLEAR) { + /* + * The result is the same as one of the SOURCE operation application with the same arguments, + * but with an empty source. + */ + + status = _cairo_svg_stream_destroy (source_stream); + if (unlikely (status)) { + (void) _cairo_svg_stream_destroy (destination_stream); + (void) _cairo_svg_stream_destroy (mask_stream); + return status; + } + cairo_svg_stream_t empty_stream = _cairo_svg_stream_create (); + return _cairo_svg_surface_do_operator (output, + surface, + CAIRO_OPERATOR_SOURCE, + clip, + mask_stream, + &empty_stream, + destination_stream); + } + + if (op == CAIRO_OPERATOR_SOURCE) { + /* + * Below we use the "Bounded" equation with SOURCE as the operation from the "Clipping and masking" section + * of https://cairographics.org/operators/: + * result = source LEPR_(clip IN mask) destination + * + * It is equivalent to: + * result = (source IN (clip IN mask)) ADD (destination IN (NOT (clip IN mask))) + * + * 1. We put the clip masked with the mask into the SVG group `lerp_compositing_group`. + * 2. `positive_lerp_mask` is an SVG mask with `lerp_compositing_group`. + * 3. `negative_lerp_mask` is an SVG mask with inverted `lerp_compositing_group`. + * 5. We put the source masked with `positive_lerp_mask` into the SVG group `lerped_source_compositing_group`. + * 6. We put the destination masked with `negative_lerp_mask` into + * the SVG group `lerped_destination_compositing_group`. + * 7. The result is addition of `lerped_source_compositing_group` and `lerped_destination_compositing_group`. + */ + + unsigned int lerp_compositing_group_id = document->compositing_group_id++; + _cairo_svg_stream_printf (&document->xml_node_defs, + "<g id=\"compositing-group-%d\"", + lerp_compositing_group_id); + _cairo_svg_stream_append_paint_dependent (&document->xml_node_defs, + surface->source_id, + CAIRO_SVG_STREAM_PAINT_DEPENDENT_ELEMENT_TYPE_INVERSE_TRANSLATION); + _cairo_svg_stream_printf (&document->xml_node_defs, ">\n"); + _cairo_svg_surface_emit_paint (&document->xml_node_defs, surface, &_cairo_pattern_clear.base, FALSE); + status = _cairo_svg_surface_set_clip (surface, &document->xml_node_defs, clip); + if (unlikely (status)) { + (void) _cairo_svg_stream_destroy (destination_stream); + (void) _cairo_svg_stream_destroy (source_stream); + (void) _cairo_svg_stream_destroy (mask_stream); + return status; + } + _cairo_svg_stream_copy (mask_stream, &document->xml_node_defs); + status = _cairo_svg_stream_destroy (mask_stream); + if (unlikely (status)) { + (void) _cairo_svg_stream_destroy (destination_stream); + (void) _cairo_svg_stream_destroy (source_stream); + return status; + } + _cairo_svg_surface_reset_clip (surface); + _cairo_svg_stream_printf (&document->xml_node_defs, "</g>\n"); + + unsigned int positive_lerp_mask_id = document->mask_id++; + _cairo_svg_stream_printf (&document->xml_node_defs, + "<mask id=\"mask-%d\">\n", + positive_lerp_mask_id); + _cairo_svg_stream_printf (&document->xml_node_defs, + "<use xlink:href=\"#compositing-group-%d\"/>\n", + lerp_compositing_group_id); + _cairo_svg_stream_printf (&document->xml_node_defs, "</mask>\n"); + + unsigned int negative_lerp_mask_id = document->mask_id++; + _cairo_svg_stream_printf (&document->xml_node_defs, + "<mask id=\"mask-%d\">\n", + negative_lerp_mask_id); + _cairo_svg_stream_printf (&document->xml_node_defs, + "<use xlink:href=\"#compositing-group-%d\" filter=\"url(#filter-%s)\"/>\n", + lerp_compositing_group_id, + _cairo_svg_surface_emit_static_filter (document, + CAIRO_SVG_FILTER_REMOVE_COLOR_AND_INVERT_ALPHA)); + _cairo_svg_stream_printf (&document->xml_node_defs, "</mask>\n"); + + unsigned int lerped_source_compositing_group_id = document->compositing_group_id++; + _cairo_svg_stream_printf (&document->xml_node_defs, + "<g id=\"compositing-group-%d\" mask=\"url(#mask-%d)\">\n", + lerped_source_compositing_group_id, + positive_lerp_mask_id); + _cairo_svg_stream_printf (&document->xml_node_defs, "<g"); + _cairo_svg_stream_append_paint_dependent (&document->xml_node_defs, + surface->source_id, + CAIRO_SVG_STREAM_PAINT_DEPENDENT_ELEMENT_TYPE_INVERSE_TRANSLATION); + _cairo_svg_stream_printf (&document->xml_node_defs, ">\n"); + _cairo_svg_stream_copy (source_stream, &document->xml_node_defs); + status = _cairo_svg_stream_destroy (source_stream); + if (unlikely (status)) { + (void) _cairo_svg_stream_destroy (destination_stream); + return status; + } + _cairo_svg_stream_printf (&document->xml_node_defs, "</g>\n"); + _cairo_svg_stream_printf (&document->xml_node_defs, "</g>\n"); + + unsigned int lerped_destination_compositing_group_id = document->compositing_group_id++; + _cairo_svg_stream_printf (&document->xml_node_defs, + "<g id=\"compositing-group-%d\" mask=\"url(#mask-%d)\">\n", + lerped_destination_compositing_group_id, + negative_lerp_mask_id); + _cairo_svg_stream_printf (&document->xml_node_defs, "<g"); + _cairo_svg_stream_append_paint_dependent (&document->xml_node_defs, + surface->source_id, + CAIRO_SVG_STREAM_PAINT_DEPENDENT_ELEMENT_TYPE_INVERSE_TRANSLATION); + _cairo_svg_stream_printf (&document->xml_node_defs, ">\n"); + _cairo_svg_stream_copy (destination_stream, &document->xml_node_defs); + status = _cairo_svg_stream_destroy (destination_stream); + if (unlikely (status)) { + return status; + } + _cairo_svg_stream_printf (&document->xml_node_defs, "</g>\n"); + _cairo_svg_stream_printf (&document->xml_node_defs, "</g>\n"); + + _cairo_svg_stream_printf (&surface->xml_node, + "<g filter=\"url(#filter-%d)\"", + _cairo_svg_surface_emit_parametric_filter (surface, + CAIRO_SVG_FILTER_ADD, + lerped_source_compositing_group_id, + lerped_destination_compositing_group_id)); + _cairo_svg_stream_append_paint_dependent (&surface->xml_node, + surface->source_id, + CAIRO_SVG_STREAM_PAINT_DEPENDENT_ELEMENT_TYPE_TRANSLATION); + _cairo_svg_stream_printf (&surface->xml_node, ">\n"); + status = _cairo_svg_surface_emit_paint (&surface->xml_node, surface, &_cairo_pattern_black.base, TRUE); + if (unlikely (status)) { + return status; + } + _cairo_svg_stream_printf (&surface->xml_node, "</g>\n"); - _cairo_output_stream_printf (output, "stroke:none;\""); + return CAIRO_STATUS_SUCCESS; + } - if (extra_attributes) - _cairo_output_stream_printf (output, " %s", extra_attributes); + if (op == CAIRO_OPERATOR_DEST) { + /* + * The result is the destination. + */ + + _cairo_svg_stream_copy (destination_stream, &surface->xml_node); + status = _cairo_svg_stream_destroy (destination_stream); + if (unlikely (status)) { + (void) _cairo_svg_stream_destroy (source_stream); + (void) _cairo_svg_stream_destroy (mask_stream); + return status; + } + status = _cairo_svg_stream_destroy (source_stream); + if (unlikely (status)) { + (void) _cairo_svg_stream_destroy (source_stream); + return status; + } + status = _cairo_svg_stream_destroy (source_stream); + if (unlikely (status)) { + return status; + } + return CAIRO_STATUS_SUCCESS; + } + + /* + * Below we use the "XRender" equation from the "Clipping and masking" section + * of https://cairographics.org/operators/: + * result = ((source IN mask) OP destination) LERP_clip destination + * + * It is equivalent to: + * result = (((source IN mask) OP destination) IN clip) ADD (destination IN (NOT clip)) + * + * 1. We put the clip into the SVG group `lerp_compositing_group`. + * 2. `positive_lerp_mask` is an SVG mask with `lerp_compositing_group`. + * 3. `negative_lerp_mask` is an SVG mask with inverted `lerp_compositing_group`. + * 4. We put the mask into the SVG mask `mask_mask`. + * 5. We put the source masked with `mask_mask` into the SVG group `masked_source_compositing_group`. + * 6. We put the destination into the SVG group `destination_compositing_group`. + * 7. `lerped_operation_compositing_group` is an SVG group of operation applied to + * (`masked_source_compositing_group`, `destination_compositing_group`) + * masked with `positive_lerp_mask`. + * 8. `lerped_destination_compositing_group` is an SVG group of `destination_compositing_group` + * masked with `negative_lerp_mask`. + * 9. The result is addition of `lerped_operation_compositing_group` and `lerped_destination_compositing_group`. + */ + + unsigned int lerp_compositing_group_id = document->compositing_group_id++; + _cairo_svg_stream_printf (&document->xml_node_defs, + "<g id=\"compositing-group-%d\"", + lerp_compositing_group_id); + _cairo_svg_stream_append_paint_dependent (&document->xml_node_defs, + surface->source_id, + CAIRO_SVG_STREAM_PAINT_DEPENDENT_ELEMENT_TYPE_INVERSE_TRANSLATION); + _cairo_svg_stream_printf (&document->xml_node_defs, ">\n"); + _cairo_svg_surface_emit_paint (&document->xml_node_defs, surface, &_cairo_pattern_clear.base, FALSE); + status = _cairo_svg_surface_set_clip (surface, &document->xml_node_defs, clip); + if (unlikely (status)) { + (void) _cairo_svg_stream_destroy (destination_stream); + (void) _cairo_svg_stream_destroy (source_stream); + (void) _cairo_svg_stream_destroy (mask_stream); + return status; + } + status = _cairo_svg_surface_emit_paint (&document->xml_node_defs, surface, &_cairo_pattern_white.base, FALSE); + if (unlikely (status)) { + (void) _cairo_svg_stream_destroy (destination_stream); + (void) _cairo_svg_stream_destroy (source_stream); + (void) _cairo_svg_stream_destroy (mask_stream); + return status; + } + _cairo_svg_surface_reset_clip (surface); + _cairo_svg_stream_printf (&document->xml_node_defs, "</g>\n"); + + unsigned int positive_lerp_mask_id = document->mask_id++; + _cairo_svg_stream_printf (&document->xml_node_defs, + "<mask id=\"mask-%d\">\n", + positive_lerp_mask_id); + _cairo_svg_stream_printf (&document->xml_node_defs, + "<use xlink:href=\"#compositing-group-%d\"/>\n", + lerp_compositing_group_id); + _cairo_svg_stream_printf (&document->xml_node_defs, "</mask>\n"); + + unsigned int negative_lerp_mask_id = document->mask_id++; + _cairo_svg_stream_printf (&document->xml_node_defs, + "<mask id=\"mask-%d\">\n", + negative_lerp_mask_id); + _cairo_svg_stream_printf (&document->xml_node_defs, + "<use xlink:href=\"#compositing-group-%d\" filter=\"url(#filter-%s)\"/>\n", + lerp_compositing_group_id, + _cairo_svg_surface_emit_static_filter (document, + CAIRO_SVG_FILTER_REMOVE_COLOR_AND_INVERT_ALPHA)); + _cairo_svg_stream_printf (&document->xml_node_defs, "</mask>\n"); + + unsigned int mask_mask_id = document->mask_id++; + _cairo_svg_stream_printf (&document->xml_node_defs, + "<mask id=\"mask-%d\">\n", + mask_mask_id); + _cairo_svg_stream_printf (&document->xml_node_defs, "<g"); + _cairo_svg_stream_append_paint_dependent (&document->xml_node_defs, + surface->source_id, + CAIRO_SVG_STREAM_PAINT_DEPENDENT_ELEMENT_TYPE_INVERSE_TRANSLATION); + _cairo_svg_stream_printf (&document->xml_node_defs, ">\n"); + _cairo_svg_stream_copy (mask_stream, &document->xml_node_defs); + status = _cairo_svg_stream_destroy (mask_stream); + if (unlikely (status)) { + (void) _cairo_svg_stream_destroy (source_stream); + (void) _cairo_svg_stream_destroy (destination_stream); + return status; + } + _cairo_svg_stream_printf (&document->xml_node_defs, "</g>\n"); + _cairo_svg_stream_printf (&document->xml_node_defs, "</mask>\n"); + + unsigned int masked_source_compositing_group_id = document->compositing_group_id++; + _cairo_svg_stream_printf (&document->xml_node_defs, + "<g id=\"compositing-group-%d\" mask=\"url(#mask-%d)\">\n", + masked_source_compositing_group_id, + mask_mask_id); + _cairo_svg_stream_printf (&document->xml_node_defs, "<g"); + _cairo_svg_stream_append_paint_dependent (&document->xml_node_defs, + surface->source_id, + CAIRO_SVG_STREAM_PAINT_DEPENDENT_ELEMENT_TYPE_INVERSE_TRANSLATION); + _cairo_svg_stream_printf (&document->xml_node_defs, ">\n"); + _cairo_svg_stream_copy (source_stream, &document->xml_node_defs); + status = _cairo_svg_stream_destroy (source_stream); + if (unlikely (status)) { + (void) _cairo_svg_stream_destroy (destination_stream); + return status; + } + _cairo_svg_stream_printf (&document->xml_node_defs, "</g>\n"); + _cairo_svg_stream_printf (&document->xml_node_defs, "</g>\n"); + + unsigned int destination_compositing_group_id = document->compositing_group_id++; + _cairo_svg_stream_printf (&document->xml_node_defs, + "<g id=\"compositing-group-%d\"", + destination_compositing_group_id); + _cairo_svg_stream_append_paint_dependent (&document->xml_node_defs, + surface->source_id, + CAIRO_SVG_STREAM_PAINT_DEPENDENT_ELEMENT_TYPE_INVERSE_TRANSLATION); + _cairo_svg_stream_printf (&document->xml_node_defs, ">\n"); + _cairo_svg_stream_copy (destination_stream, &document->xml_node_defs); + status = _cairo_svg_stream_destroy (destination_stream); + if (unlikely (status)) { + return status; + } + _cairo_svg_stream_printf (&document->xml_node_defs, "</g>\n"); - _cairo_output_stream_printf (output, "/>\n"); + unsigned int lerped_operation_compositing_group_id = document->compositing_group_id++; + _cairo_svg_stream_printf (&document->xml_node_defs, + "<g id=\"compositing-group-%d\"", + lerped_operation_compositing_group_id); + unsigned int filter_id; + switch (op) { + case CAIRO_OPERATOR_CLEAR: + case CAIRO_OPERATOR_SOURCE: + case CAIRO_OPERATOR_OVER: + ASSERT_NOT_REACHED; + case CAIRO_OPERATOR_IN: + filter_id = _cairo_svg_surface_emit_parametric_filter (surface, + CAIRO_SVG_FILTER_IN, + masked_source_compositing_group_id, + destination_compositing_group_id); + break; + case CAIRO_OPERATOR_OUT: + filter_id = _cairo_svg_surface_emit_parametric_filter (surface, + CAIRO_SVG_FILTER_OUT, + masked_source_compositing_group_id, + destination_compositing_group_id); + break; + case CAIRO_OPERATOR_ATOP: + filter_id = _cairo_svg_surface_emit_parametric_filter (surface, + CAIRO_SVG_FILTER_ATOP, + masked_source_compositing_group_id, + destination_compositing_group_id); + break; + case CAIRO_OPERATOR_DEST: + ASSERT_NOT_REACHED; + case CAIRO_OPERATOR_DEST_OVER: + filter_id = _cairo_svg_surface_emit_parametric_filter (surface, + CAIRO_SVG_FILTER_OVER, + destination_compositing_group_id, + masked_source_compositing_group_id); + break; + case CAIRO_OPERATOR_DEST_IN: + filter_id = _cairo_svg_surface_emit_parametric_filter (surface, + CAIRO_SVG_FILTER_IN, + destination_compositing_group_id, + masked_source_compositing_group_id); + break; + case CAIRO_OPERATOR_DEST_OUT: + filter_id = _cairo_svg_surface_emit_parametric_filter (surface, + CAIRO_SVG_FILTER_OUT, + destination_compositing_group_id, + masked_source_compositing_group_id); + break; + case CAIRO_OPERATOR_DEST_ATOP: + filter_id = _cairo_svg_surface_emit_parametric_filter (surface, + CAIRO_SVG_FILTER_ATOP, + destination_compositing_group_id, + masked_source_compositing_group_id); + break; + case CAIRO_OPERATOR_XOR: + filter_id = _cairo_svg_surface_emit_parametric_filter (surface, + CAIRO_SVG_FILTER_XOR, + masked_source_compositing_group_id, + destination_compositing_group_id); + break; + case CAIRO_OPERATOR_ADD: + filter_id = _cairo_svg_surface_emit_parametric_filter (surface, + CAIRO_SVG_FILTER_ADD, + masked_source_compositing_group_id, + destination_compositing_group_id); + break; + case CAIRO_OPERATOR_SATURATE: + ASSERT_NOT_REACHED; + case CAIRO_OPERATOR_MULTIPLY: + filter_id = _cairo_svg_surface_emit_parametric_filter (surface, + CAIRO_SVG_FILTER_MULTIPLY, + masked_source_compositing_group_id, + destination_compositing_group_id); + break; + case CAIRO_OPERATOR_SCREEN: + filter_id = _cairo_svg_surface_emit_parametric_filter (surface, + CAIRO_SVG_FILTER_SCREEN, + masked_source_compositing_group_id, + destination_compositing_group_id); + break; + case CAIRO_OPERATOR_OVERLAY: + filter_id = _cairo_svg_surface_emit_parametric_filter (surface, + CAIRO_SVG_FILTER_OVERLAY, + masked_source_compositing_group_id, + destination_compositing_group_id); + break; + case CAIRO_OPERATOR_DARKEN: + filter_id = _cairo_svg_surface_emit_parametric_filter (surface, + CAIRO_SVG_FILTER_DARKEN, + masked_source_compositing_group_id, + destination_compositing_group_id); + break; + case CAIRO_OPERATOR_LIGHTEN: + filter_id = _cairo_svg_surface_emit_parametric_filter (surface, + CAIRO_SVG_FILTER_LIGHTEN, + masked_source_compositing_group_id, + destination_compositing_group_id); + break; + case CAIRO_OPERATOR_COLOR_DODGE: + filter_id = _cairo_svg_surface_emit_parametric_filter (surface, + CAIRO_SVG_FILTER_COLOR_DODGE, + masked_source_compositing_group_id, + destination_compositing_group_id); + break; + case CAIRO_OPERATOR_COLOR_BURN: + filter_id = _cairo_svg_surface_emit_parametric_filter (surface, + CAIRO_SVG_FILTER_COLOR_BURN, + masked_source_compositing_group_id, + destination_compositing_group_id); + break; + case CAIRO_OPERATOR_HARD_LIGHT: + filter_id = _cairo_svg_surface_emit_parametric_filter (surface, + CAIRO_SVG_FILTER_HARD_LIGHT, + masked_source_compositing_group_id, + destination_compositing_group_id); + break; + case CAIRO_OPERATOR_SOFT_LIGHT: + filter_id = _cairo_svg_surface_emit_parametric_filter (surface, + CAIRO_SVG_FILTER_SOFT_LIGHT, + masked_source_compositing_group_id, + destination_compositing_group_id); + break; + case CAIRO_OPERATOR_DIFFERENCE: + filter_id = _cairo_svg_surface_emit_parametric_filter (surface, + CAIRO_SVG_FILTER_DIFFERENCE, + masked_source_compositing_group_id, + destination_compositing_group_id); + break; + case CAIRO_OPERATOR_EXCLUSION: + filter_id = _cairo_svg_surface_emit_parametric_filter (surface, + CAIRO_SVG_FILTER_EXCLUSION, + masked_source_compositing_group_id, + destination_compositing_group_id); + break; + case CAIRO_OPERATOR_HSL_HUE: + filter_id = _cairo_svg_surface_emit_parametric_filter (surface, + CAIRO_SVG_FILTER_HUE, + masked_source_compositing_group_id, + destination_compositing_group_id); + break; + case CAIRO_OPERATOR_HSL_SATURATION: + filter_id = _cairo_svg_surface_emit_parametric_filter (surface, + CAIRO_SVG_FILTER_SATURATION, + masked_source_compositing_group_id, + destination_compositing_group_id); + break; + case CAIRO_OPERATOR_HSL_COLOR: + filter_id = _cairo_svg_surface_emit_parametric_filter (surface, + CAIRO_SVG_FILTER_COLOR, + masked_source_compositing_group_id, + destination_compositing_group_id); + break; + case CAIRO_OPERATOR_HSL_LUMINOSITY: + filter_id = _cairo_svg_surface_emit_parametric_filter (surface, + CAIRO_SVG_FILTER_LUMINOSITY, + masked_source_compositing_group_id, + destination_compositing_group_id); + break; + default: + ASSERT_NOT_REACHED; + } + _cairo_svg_stream_printf (&document->xml_node_defs, + " filter=\"url(#filter-%d)\" mask=\"url(#mask-%d)\">\n", + filter_id, + positive_lerp_mask_id); + status = _cairo_svg_surface_emit_paint (&document->xml_node_defs, surface, &_cairo_pattern_black.base, TRUE); + if (unlikely (status)) { + return status; + } + _cairo_svg_stream_printf (&document->xml_node_defs, "</g>\n"); + + unsigned int lerped_destination_compositing_group_id = document->compositing_group_id++; + _cairo_svg_stream_printf (&document->xml_node_defs, + "<g id=\"compositing-group-%d\" mask=\"url(#mask-%d)\">\n", + lerped_destination_compositing_group_id, + negative_lerp_mask_id); + _cairo_svg_stream_printf (&document->xml_node_defs, + "<use xlink:href=\"#compositing-group-%d\"/>\n", + destination_compositing_group_id); + _cairo_svg_stream_printf (&document->xml_node_defs, "</g>\n"); + + _cairo_svg_stream_printf (&surface->xml_node, + "<g filter=\"url(#filter-%d)\"", + _cairo_svg_surface_emit_parametric_filter (surface, + CAIRO_SVG_FILTER_ADD, + lerped_operation_compositing_group_id, + lerped_destination_compositing_group_id)); + _cairo_svg_stream_append_paint_dependent (&surface->xml_node, + surface->source_id, + CAIRO_SVG_STREAM_PAINT_DEPENDENT_ELEMENT_TYPE_TRANSLATION); + _cairo_svg_stream_printf (&surface->xml_node, ">\n"); + status = _cairo_svg_surface_emit_paint (&surface->xml_node, surface, &_cairo_pattern_black.base, TRUE); + if (unlikely (status)) { + return status; + } + _cairo_svg_stream_printf (&surface->xml_node, "</g>\n"); return CAIRO_STATUS_SUCCESS; } +#define _CAIRO_SVG_SURFACE_CALL_OPERATOR_IMPL(OPERATOR_IMPL, SOURCE, ...) \ + if (op == CAIRO_OPERATOR_OVER) { \ + status = _cairo_svg_surface_set_clip (surface, &surface->xml_node, clip); \ + if (unlikely (status)) { \ + return status; \ + } \ + return OPERATOR_IMPL (&surface->xml_node, surface, SOURCE, ## __VA_ARGS__); \ + } else { \ + _cairo_svg_surface_reset_clip (surface); \ + cairo_svg_stream_t mask_stream = _cairo_svg_stream_create (); \ + status = OPERATOR_IMPL (&mask_stream, surface, &_cairo_pattern_white.base, ## __VA_ARGS__); \ + if (unlikely (status)) { \ + (void) _cairo_svg_stream_destroy (&mask_stream); \ + return status; \ + } \ + cairo_svg_stream_t source_stream = _cairo_svg_stream_create (); \ + status = _cairo_svg_surface_emit_paint (&source_stream, \ + surface, \ + SOURCE, \ + FALSE); \ + if (unlikely (status)) { \ + (void) _cairo_svg_stream_destroy (&source_stream); \ + (void) _cairo_svg_stream_destroy (&mask_stream); \ + return status; \ + } \ + cairo_svg_stream_t destination_stream = surface->xml_node; \ + surface->xml_node = _cairo_svg_stream_create (); \ + return _cairo_svg_surface_do_operator (&surface->xml_node, \ + surface, \ + op, \ + clip, \ + &mask_stream, \ + &source_stream, \ + &destination_stream); \ + } + +static cairo_int_status_t +_cairo_svg_surface_paint_impl (cairo_svg_stream_t *output, + cairo_svg_surface_t *surface, + const cairo_pattern_t *source) +{ + return _cairo_svg_surface_emit_paint (output, surface, source, FALSE); +} + static cairo_int_status_t -_cairo_svg_surface_paint (void *abstract_surface, - cairo_operator_t op, - const cairo_pattern_t *source, - const cairo_clip_t *clip) +_cairo_svg_surface_paint (void *abstract_surface, + cairo_operator_t op, + const cairo_pattern_t *source, + const cairo_clip_t *clip) { cairo_status_t status; cairo_svg_surface_t *surface = abstract_surface; @@ -2518,283 +3656,457 @@ _cairo_svg_surface_paint (void *abstract_surface, * is defined. We just delete existing content of surface root node, * and exit early if operator is clear. */ - if ((op == CAIRO_OPERATOR_CLEAR || op == CAIRO_OPERATOR_SOURCE) && - clip == NULL) - { + if ((op == CAIRO_OPERATOR_CLEAR || op == CAIRO_OPERATOR_SOURCE) && clip == NULL) { switch (surface->paginated_mode) { - case CAIRO_PAGINATED_MODE_FALLBACK: - ASSERT_NOT_REACHED; case CAIRO_PAGINATED_MODE_ANALYZE: return CAIRO_STATUS_SUCCESS; - case CAIRO_PAGINATED_MODE_RENDER: - status = _cairo_output_stream_destroy (surface->xml_node); + status = _cairo_svg_stream_destroy (&surface->xml_node); if (unlikely (status)) { - surface->xml_node = NULL; return status; } - surface->xml_node = _cairo_memory_stream_create (); - if (_cairo_output_stream_get_status (surface->xml_node)) { - status = _cairo_output_stream_destroy (surface->xml_node); - surface->xml_node = NULL; - return status; - } + surface->xml_node = _cairo_svg_stream_create (); if (op == CAIRO_OPERATOR_CLEAR) { - if (surface->content == CAIRO_CONTENT_COLOR) { - _cairo_output_stream_printf (surface->xml_node, - "<rect " - "width=\"%f\" height=\"%f\" " - "style=\"opacity:1;" - "stroke:none;" - "fill:rgb(0,0,0);\"/>\n", - surface->width, surface->height); - } return CAIRO_STATUS_SUCCESS; } break; + case CAIRO_PAGINATED_MODE_FALLBACK: + ASSERT_NOT_REACHED; } - } else { - if (surface->paginated_mode == CAIRO_PAGINATED_MODE_ANALYZE) - return _cairo_svg_surface_analyze_operation (surface, op, source); + } else if (surface->paginated_mode == CAIRO_PAGINATED_MODE_ANALYZE) { + return _cairo_svg_surface_are_operation_and_pattern_supported (surface, op, source) + ? CAIRO_STATUS_SUCCESS + : CAIRO_INT_STATUS_UNSUPPORTED; + } + + _CAIRO_SVG_SURFACE_CALL_OPERATOR_IMPL (_cairo_svg_surface_paint_impl, + source) +} - assert (_cairo_svg_surface_operation_supported (surface, op, source)); +static cairo_int_status_t +_cairo_svg_surface_mask_impl (cairo_svg_stream_t *output, + cairo_svg_surface_t *surface, + const cairo_pattern_t *source, + const cairo_pattern_t *mask) +{ + cairo_status_t status; + cairo_svg_document_t *document = surface->document; + + /* _cairo_svg_surface_emit_paint() will output a pattern definition to + * document->xml_node_defs so we need to write the mask element to + * a temporary stream and then copy that to xml_node_defs. */ + cairo_svg_stream_t temporary_stream = _cairo_svg_stream_create (); + + unsigned int mask_id = document->mask_id++; + + _cairo_svg_stream_printf (&temporary_stream, + "<mask id=\"mask-%d\">\n", + mask_id); + _cairo_svg_stream_printf (&temporary_stream, + "<g filter=\"url(#filter-%s)\">\n", + _cairo_svg_surface_emit_static_filter (document, CAIRO_SVG_FILTER_REMOVE_COLOR)); + status = _cairo_svg_surface_emit_paint (&temporary_stream, surface, mask, FALSE); + if (unlikely (status)) { + (void) _cairo_svg_stream_destroy (&temporary_stream); + return status; } + _cairo_svg_stream_printf (&temporary_stream, "</g>\n"); + _cairo_svg_stream_printf (&temporary_stream, "</mask>\n"); - status = _cairo_surface_clipper_set_clip (&surface->clipper, clip); - if (unlikely (status)) + _cairo_svg_stream_copy (&temporary_stream, &document->xml_node_defs); + + status = _cairo_svg_stream_destroy (&temporary_stream); + if (unlikely (status)) { + return status; + } + + _cairo_svg_stream_printf (output, + "<g mask=\"url(#mask-%d)\">\n", + mask_id); + + status = _cairo_svg_surface_emit_paint (output, surface, source, FALSE); + if (unlikely (status)) { return status; + } + + _cairo_svg_stream_printf (output, "</g>\n"); - return _cairo_svg_surface_emit_paint (surface->xml_node, - surface, op, source, 0, NULL); + return CAIRO_STATUS_SUCCESS; } static cairo_int_status_t -_cairo_svg_surface_mask (void *abstract_surface, - cairo_operator_t op, - const cairo_pattern_t *source, - const cairo_pattern_t *mask, - const cairo_clip_t *clip) +_cairo_svg_surface_mask (void *abstract_surface, + cairo_operator_t op, + const cairo_pattern_t *source, + const cairo_pattern_t *mask, + const cairo_clip_t *clip) { cairo_status_t status; cairo_svg_surface_t *surface = abstract_surface; - cairo_svg_document_t *document = surface->document; - cairo_output_stream_t *mask_stream; - char buffer[64]; - cairo_bool_t discard_filter = FALSE; - unsigned int mask_id; if (surface->paginated_mode == CAIRO_PAGINATED_MODE_ANALYZE) { - cairo_status_t source_status, mask_status; - - source_status = _cairo_svg_surface_analyze_operation (surface, op, source); - if (_cairo_status_is_error (source_status)) - return source_status; + return _cairo_svg_surface_are_operation_and_pattern_supported (surface, op, source) && + _cairo_svg_surface_are_operation_and_pattern_supported (surface, op, mask) + ? CAIRO_STATUS_SUCCESS + : CAIRO_INT_STATUS_UNSUPPORTED; + } - if (mask->has_component_alpha) { - mask_status = CAIRO_INT_STATUS_UNSUPPORTED; - } else { - mask_status = _cairo_svg_surface_analyze_operation (surface, op, mask); - if (_cairo_status_is_error (mask_status)) - return mask_status; - } + _CAIRO_SVG_SURFACE_CALL_OPERATOR_IMPL (_cairo_svg_surface_mask_impl, + source, + mask) +} - return _cairo_analysis_surface_merge_status (source_status, - mask_status); - } +static cairo_int_status_t +_cairo_svg_surface_stroke_impl (cairo_svg_stream_t *output, + cairo_svg_surface_t *surface, + const cairo_pattern_t *source, + const cairo_path_fixed_t *path, + const cairo_stroke_style_t *stroke_style, + const cairo_matrix_t *ctm, + const cairo_matrix_t *ctm_inverse, + double tolerance, + cairo_antialias_t antialias) +{ + cairo_status_t status; - assert (_cairo_svg_surface_operation_supported (surface, op, source)); - assert (_cairo_svg_surface_operation_supported (surface, CAIRO_OPERATOR_OVER, mask)); + cairo_bool_t svg_clip_or_svg_mask_should_be_used = _cairo_svg_surface_svg_clip_or_svg_mask_should_be_used (source); + unsigned int mask_id; + cairo_svg_stream_t *output_stream = output; + if (svg_clip_or_svg_mask_should_be_used) { + mask_id = surface->document->mask_id++; - status = _cairo_surface_clipper_set_clip (&surface->clipper, clip); - if (unlikely (status)) - return status; + output_stream = &surface->document->xml_node_defs; - if (mask->type == CAIRO_PATTERN_TYPE_SURFACE) { - const cairo_surface_pattern_t *surface_pattern = (const cairo_surface_pattern_t*) mask; - cairo_content_t content = surface_pattern->surface->content; - if (content == CAIRO_CONTENT_ALPHA) - discard_filter = TRUE; + _cairo_svg_stream_printf (output_stream, + "<mask id=\"mask-%d\">\n", + mask_id); } - if (!discard_filter) - _cairo_svg_surface_emit_alpha_filter (document); + _cairo_svg_stream_printf (output_stream, "<path fill=\"none\""); + status = _cairo_svg_surface_emit_stroke_style (output_stream, + surface, + svg_clip_or_svg_mask_should_be_used ? &_cairo_pattern_white.base + : source, + stroke_style, + ctm_inverse); - /* _cairo_svg_surface_emit_paint() will output a pattern definition to - * document->xml_node_defs so we need to write the mask element to - * a temporary stream and then copy that to xml_node_defs. */ - mask_stream = _cairo_memory_stream_create (); - if (_cairo_output_stream_get_status (mask_stream)) - return _cairo_output_stream_destroy (mask_stream); - - mask_id = _cairo_svg_document_allocate_mask_id (document); - - _cairo_output_stream_printf (mask_stream, - "<mask id=\"mask%d\">\n" - "%s", - mask_id, - discard_filter ? "" : " <g filter=\"url(#alpha)\">\n"); - status = _cairo_svg_surface_emit_paint (mask_stream, surface, CAIRO_OPERATOR_OVER, mask, source, NULL); if (unlikely (status)) { - cairo_status_t ignore = _cairo_output_stream_destroy (mask_stream); return status; - (void) ignore; } - _cairo_output_stream_printf (mask_stream, - "%s" - "</mask>\n", - discard_filter ? "" : " </g>\n"); - _cairo_memory_stream_copy (mask_stream, document->xml_node_defs); + _cairo_svg_surface_emit_path (output_stream, path, ctm_inverse); - status = _cairo_output_stream_destroy (mask_stream); - if (unlikely (status)) - return status; + _cairo_svg_surface_emit_transform (output_stream, "transform", ctm, NULL); + _cairo_svg_stream_printf (output_stream, "/>\n"); - snprintf (buffer, sizeof buffer, "mask=\"url(#mask%d)\"", - mask_id); - status = _cairo_svg_surface_emit_paint (surface->xml_node, surface, op, source, 0, buffer); - if (unlikely (status)) - return status; + if (svg_clip_or_svg_mask_should_be_used) { + _cairo_svg_stream_printf (output_stream, "</mask>\n"); + + _cairo_svg_stream_printf (output, + "<g mask=\"url(#mask-%d)\">\n", + mask_id); + + status = _cairo_svg_surface_emit_composite_pattern (output, + surface, + (cairo_surface_pattern_t *) source, + invalid_pattern_id, + NULL); + if (unlikely (status)) { + return status; + } + + _cairo_svg_stream_printf (output, "</g>\n"); + } return CAIRO_STATUS_SUCCESS; } static cairo_int_status_t -_cairo_svg_surface_stroke (void *abstract_dst, - cairo_operator_t op, +_cairo_svg_surface_stroke (void *abstract_dst, + cairo_operator_t op, const cairo_pattern_t *source, - const cairo_path_fixed_t*path, + const cairo_path_fixed_t *path, const cairo_stroke_style_t *stroke_style, - const cairo_matrix_t *ctm, - const cairo_matrix_t *ctm_inverse, - double tolerance, - cairo_antialias_t antialias, - const cairo_clip_t *clip) + const cairo_matrix_t *ctm, + const cairo_matrix_t *ctm_inverse, + double tolerance, + cairo_antialias_t antialias, + const cairo_clip_t *clip) { cairo_svg_surface_t *surface = abstract_dst; cairo_status_t status; - if (surface->paginated_mode == CAIRO_PAGINATED_MODE_ANALYZE) - return _cairo_svg_surface_analyze_operation (surface, op, source); + if (surface->paginated_mode == CAIRO_PAGINATED_MODE_ANALYZE) { + return _cairo_svg_surface_are_operation_and_pattern_supported (surface, op, source) + ? CAIRO_STATUS_SUCCESS + : CAIRO_INT_STATUS_UNSUPPORTED; + } - assert (_cairo_svg_surface_operation_supported (surface, op, source)); + _CAIRO_SVG_SURFACE_CALL_OPERATOR_IMPL (_cairo_svg_surface_stroke_impl, + source, + path, + stroke_style, + ctm, + ctm_inverse, + tolerance, + antialias) +} - status = _cairo_surface_clipper_set_clip (&surface->clipper, clip); - if (unlikely (status)) - return status; +static cairo_int_status_t +_cairo_svg_surface_fill_impl (cairo_svg_stream_t *output, + cairo_svg_surface_t *surface, + const cairo_pattern_t *source, + const cairo_path_fixed_t *path, + cairo_fill_rule_t fill_rule, + double tolerance, + cairo_antialias_t antialias) +{ + cairo_status_t status; - _cairo_output_stream_printf (surface->xml_node, "<path style=\"fill:none;"); - status = _cairo_svg_surface_emit_stroke_style (surface->xml_node, surface, op, - source, stroke_style, ctm_inverse); - if (unlikely (status)) - return status; + if (_cairo_svg_surface_svg_clip_or_svg_mask_should_be_used (source)) { + _cairo_svg_stream_printf (&surface->document->xml_node_defs, + "<clipPath id=\"clip-%d\">\n", + surface->document->clip_id); + + _cairo_svg_stream_printf (&surface->document->xml_node_defs, + "<path clip-rule=\"%s\"", + fill_rule == CAIRO_FILL_RULE_EVEN_ODD ? "evenodd" : "nonzero"); + _cairo_svg_surface_emit_path (&surface->document->xml_node_defs, path, NULL); + _cairo_svg_stream_printf (&surface->document->xml_node_defs, "/>\n"); + + _cairo_svg_stream_printf (&surface->document->xml_node_defs, "</clipPath>\n"); + + _cairo_svg_stream_printf (output, + "<g clip-path=\"url(#clip-%d)\">\n", + surface->document->clip_id++); + + status = _cairo_svg_surface_emit_composite_pattern (output, + surface, + (cairo_surface_pattern_t *) source, + invalid_pattern_id, + NULL); + if (unlikely (status)) { + return status; + } - _cairo_output_stream_printf (surface->xml_node, "\" "); + _cairo_svg_stream_printf (output, "</g>"); + } else { + _cairo_svg_stream_printf (output, "<path"); + status = _cairo_svg_surface_emit_fill_style (output, surface, source, fill_rule, NULL); + if (unlikely (status)) { + return status; + } + _cairo_svg_surface_emit_path (output, path, NULL); + _cairo_svg_stream_printf (output, "/>\n"); + } + + return CAIRO_STATUS_SUCCESS; +} - _cairo_svg_surface_emit_path (surface->xml_node, path, ctm_inverse); +static cairo_int_status_t +_cairo_svg_surface_fill (void *abstract_surface, + cairo_operator_t op, + const cairo_pattern_t *source, + const cairo_path_fixed_t *path, + cairo_fill_rule_t fill_rule, + double tolerance, + cairo_antialias_t antialias, + const cairo_clip_t *clip) +{ + cairo_svg_surface_t *surface = abstract_surface; + cairo_status_t status; - _cairo_svg_surface_emit_transform (surface->xml_node, " transform", ctm, NULL); - _cairo_output_stream_printf (surface->xml_node, "/>\n"); + if (surface->paginated_mode == CAIRO_PAGINATED_MODE_ANALYZE) { + return _cairo_svg_surface_are_operation_and_pattern_supported (surface, op, source) + ? CAIRO_STATUS_SUCCESS + : CAIRO_INT_STATUS_UNSUPPORTED; + } - return CAIRO_STATUS_SUCCESS; + _CAIRO_SVG_SURFACE_CALL_OPERATOR_IMPL (_cairo_svg_surface_fill_impl, + source, + path, + fill_rule, + tolerance, + antialias) } static cairo_int_status_t -_cairo_svg_surface_show_glyphs (void *abstract_surface, - cairo_operator_t op, - const cairo_pattern_t *pattern, - cairo_glyph_t *glyphs, - int num_glyphs, - cairo_scaled_font_t *scaled_font, - const cairo_clip_t *clip) +_cairo_svg_surface_fill_stroke (void *abstract_surface, + cairo_operator_t fill_op, + const cairo_pattern_t *fill_source, + cairo_fill_rule_t fill_rule, + double fill_tolerance, + cairo_antialias_t fill_antialias, + const cairo_path_fixed_t *path, + cairo_operator_t stroke_op, + const cairo_pattern_t *stroke_source, + const cairo_stroke_style_t *stroke_style, + const cairo_matrix_t *stroke_ctm, + const cairo_matrix_t *stroke_ctm_inverse, + double stroke_tolerance, + cairo_antialias_t stroke_antialias, + const cairo_clip_t *clip) { cairo_svg_surface_t *surface = abstract_surface; - cairo_svg_document_t *document = surface->document; - cairo_path_fixed_t path; - cairo_int_status_t status; - cairo_scaled_font_subsets_glyph_t subset_glyph; - int i; + cairo_status_t status; - if (surface->paginated_mode == CAIRO_PAGINATED_MODE_ANALYZE) - return _cairo_svg_surface_analyze_operation (surface, op, pattern); + if (_cairo_svg_surface_svg_clip_or_svg_mask_should_be_used (fill_source) || + _cairo_svg_surface_svg_clip_or_svg_mask_should_be_used (stroke_source) || + fill_op != CAIRO_OPERATOR_OVER || + stroke_op != CAIRO_OPERATOR_OVER) { + return CAIRO_INT_STATUS_UNSUPPORTED; + } - assert (_cairo_svg_surface_operation_supported (surface, op, pattern)); + if (surface->paginated_mode == CAIRO_PAGINATED_MODE_ANALYZE) { + return _cairo_svg_surface_are_operation_and_pattern_supported (surface, fill_op, fill_source) + && _cairo_svg_surface_are_operation_and_pattern_supported (surface, stroke_op, stroke_source) + ? CAIRO_STATUS_SUCCESS + : CAIRO_INT_STATUS_UNSUPPORTED; + } - if (num_glyphs <= 0) - return CAIRO_STATUS_SUCCESS; + status = _cairo_svg_surface_set_clip (surface, &surface->xml_node, clip); + if (unlikely (status)) { + return status; + } - status = _cairo_surface_clipper_set_clip (&surface->clipper, clip); - if (unlikely (status)) + _cairo_svg_stream_printf (&surface->xml_node, "<path"); + status = _cairo_svg_surface_emit_fill_style (&surface->xml_node, surface, + fill_source, fill_rule, stroke_ctm_inverse); + if (unlikely (status)) { + return status; + } + + status = _cairo_svg_surface_emit_stroke_style (&surface->xml_node, surface, + stroke_source, stroke_style, stroke_ctm_inverse); + if (unlikely (status)) { return status; + } + + _cairo_svg_surface_emit_path (&surface->xml_node, path, stroke_ctm_inverse); + + _cairo_svg_surface_emit_transform (&surface->xml_node, "transform", stroke_ctm, NULL); + + _cairo_svg_stream_printf (&surface->xml_node, "/>\n"); + + return CAIRO_STATUS_SUCCESS; +} - /* FIXME it's probably possible to apply a pattern of a gradient to +static cairo_int_status_t +_cairo_svg_surface_show_glyphs_impl (cairo_svg_stream_t *output, + cairo_svg_surface_t *surface, + const cairo_pattern_t *source, + cairo_glyph_t *glyphs, + int num_glyphs, + cairo_scaled_font_t *scaled_font) +{ + cairo_status_t status; + cairo_svg_document_t *document = surface->document; + + if (num_glyphs <= 0) { + return CAIRO_STATUS_SUCCESS; + } + + /* FIXME it's probably possible to apply a source of a gradient to * a group of symbols, but I don't know how yet. Gradients or patterns * are translated by x and y properties of use element. */ - if (pattern->type != CAIRO_PATTERN_TYPE_SOLID) - goto FALLBACK; + if (source->type != CAIRO_PATTERN_TYPE_SOLID) { + goto fallback; + } - _cairo_output_stream_printf (surface->xml_node, "<g style=\""); - status = _cairo_svg_surface_emit_pattern (surface, pattern, - surface->xml_node, FALSE, NULL); - if (unlikely (status)) + _cairo_svg_stream_printf (output, "<g"); + + status = _cairo_svg_surface_emit_pattern (surface, source, output, FALSE, NULL); + if (unlikely (status)) { return status; + } - _cairo_svg_surface_emit_operator_for_style (surface->xml_node, surface, op); + _cairo_svg_stream_printf (output, ">\n"); - _cairo_output_stream_printf (surface->xml_node, "\">\n"); + for (int i = 0; i < num_glyphs; i++) { + cairo_scaled_font_subsets_glyph_t subset_glyph; - for (i = 0; i < num_glyphs; i++) { status = _cairo_scaled_font_subsets_map_glyph (document->font_subsets, - scaled_font, glyphs[i].index, - NULL, 0, - &subset_glyph); - if (status == CAIRO_INT_STATUS_UNSUPPORTED) { - _cairo_output_stream_printf (surface->xml_node, "</g>\n"); + scaled_font, + glyphs[i].index, + NULL, + 0, + &subset_glyph); + if ((cairo_int_status_t) status == CAIRO_INT_STATUS_UNSUPPORTED) { + _cairo_svg_stream_printf (output, "</g>\n"); glyphs += i; num_glyphs -= i; - goto FALLBACK; + goto fallback; } - if (unlikely (status)) + if (unlikely (status)) { return status; + } - _cairo_output_stream_printf (surface->xml_node, - " <use xlink:href=\"#glyph%d-%d\" " - "x=\"%f\" y=\"%f\"/>\n", - subset_glyph.font_id, - subset_glyph.subset_glyph_index, - glyphs[i].x, glyphs[i].y); + _cairo_svg_stream_printf (output, + "<use xlink:href=\"#glyph-%d-%d\" x=\"%f\" y=\"%f\"/>\n", + subset_glyph.font_id, + subset_glyph.subset_glyph_index, + glyphs[i].x, glyphs[i].y); } - _cairo_output_stream_printf (surface->xml_node, "</g>\n"); + _cairo_svg_stream_printf (output, "</g>\n"); return CAIRO_STATUS_SUCCESS; -FALLBACK: + fallback:; + cairo_path_fixed_t path; + _cairo_path_fixed_init (&path); status = _cairo_scaled_font_glyph_path (scaled_font, (cairo_glyph_t *) glyphs, num_glyphs, &path); - if (unlikely (status)) { _cairo_path_fixed_fini (&path); return status; } - status = _cairo_svg_surface_fill (abstract_surface, op, pattern, - &path, CAIRO_FILL_RULE_WINDING, - 0.0, CAIRO_ANTIALIAS_SUBPIXEL, - clip); + status = _cairo_svg_surface_fill_impl (output, + surface, + source, + &path, + CAIRO_FILL_RULE_WINDING, + 0.0, + CAIRO_ANTIALIAS_DEFAULT); _cairo_path_fixed_fini (&path); return status; } +static cairo_int_status_t +_cairo_svg_surface_show_glyphs (void *abstract_surface, + cairo_operator_t op, + const cairo_pattern_t *source, + cairo_glyph_t *glyphs, + int num_glyphs, + cairo_scaled_font_t *scaled_font, + const cairo_clip_t *clip) +{ + cairo_svg_surface_t *surface = abstract_surface; + cairo_int_status_t status; + + if (surface->paginated_mode == CAIRO_PAGINATED_MODE_ANALYZE) { + return _cairo_svg_surface_are_operation_and_pattern_supported (surface, op, source) + ? CAIRO_STATUS_SUCCESS + : CAIRO_INT_STATUS_UNSUPPORTED; + } + + _CAIRO_SVG_SURFACE_CALL_OPERATOR_IMPL (_cairo_svg_surface_show_glyphs_impl, + source, + glyphs, + num_glyphs, + scaled_font) +} + static void _cairo_svg_surface_get_font_options (void *abstract_surface, cairo_font_options_t *options) @@ -2851,69 +4163,72 @@ static const cairo_surface_backend_t cairo_svg_surface_backend = { }; static cairo_status_t -_cairo_svg_document_create (cairo_output_stream_t *output_stream, - double width, - double height, - cairo_svg_version_t version, - cairo_svg_document_t **document_out) +_cairo_svg_document_create (cairo_output_stream_t *output_stream, + double width, + double height, + cairo_svg_version_t version, + cairo_svg_document_t **document_out) { cairo_svg_document_t *document; - cairo_status_t status, status_ignored; - if (output_stream->status) + if (output_stream->status) { return output_stream->status; + } document = _cairo_malloc (sizeof (cairo_svg_document_t)); - if (unlikely (document == NULL)) + if (unlikely (document == NULL)) { return _cairo_error (CAIRO_STATUS_NO_MEMORY); - - /* The use of defs for font glyphs imposes no per-subset limit. */ - document->font_subsets = _cairo_scaled_font_subsets_create_scaled (); - if (unlikely (document->font_subsets == NULL)) { - status = _cairo_error (CAIRO_STATUS_NO_MEMORY); - goto CLEANUP_DOCUMENT; } document->output_stream = output_stream; document->refcount = 1; document->owner = NULL; document->finished = FALSE; + document->width = width; document->height = height; - document->unit = CAIRO_SVG_UNIT_PT; + document->unit = CAIRO_SVG_UNIT_USER; + + document->xml_node_defs = _cairo_svg_stream_create (); + document->xml_node_glyphs = _cairo_svg_stream_create (); + document->xml_node_filters = _cairo_svg_stream_create (); document->linear_pattern_id = 0; document->radial_pattern_id = 0; document->pattern_id = 0; - document->filter_id = 0; document->clip_id = 0; document->mask_id = 0; + document->compositing_group_id = 0; + document->filter_id = 0; - document->xml_node_defs = _cairo_memory_stream_create (); - status = _cairo_output_stream_get_status (document->xml_node_defs); - if (unlikely (status)) - goto CLEANUP_NODE_DEFS; + for (enum cairo_svg_filter filter = 0; filter < CAIRO_SVG_FILTER_LAST_STATIC_FILTER; filter++) { + document->filters_emitted[filter] = FALSE; + } - document->xml_node_glyphs = _cairo_memory_stream_create (); - status = _cairo_output_stream_get_status (document->xml_node_glyphs); - if (unlikely (status)) - goto CLEANUP_NODE_GLYPHS; + document->svg_version = version; - document->alpha_filter = FALSE; + /* The use of defs for font glyphs imposes no per-subset limit. */ + document->font_subsets = _cairo_scaled_font_subsets_create_scaled (); + if (unlikely (document->font_subsets == NULL)) { + (void) _cairo_svg_stream_destroy(&document->xml_node_defs); + (void) _cairo_svg_stream_destroy(&document->xml_node_glyphs); + (void) _cairo_svg_stream_destroy(&document->xml_node_filters); + free (document); + return _cairo_error (CAIRO_STATUS_NO_MEMORY); + } - document->svg_version = version; + document->paints = _cairo_hash_table_create (_cairo_svg_paint_equal); + if (unlikely (document->paints == NULL)) { + (void) _cairo_svg_stream_destroy(&document->xml_node_defs); + (void) _cairo_svg_stream_destroy(&document->xml_node_glyphs); + (void) _cairo_svg_stream_destroy(&document->xml_node_filters); + _cairo_scaled_font_subsets_destroy (document->font_subsets); + free (document); + return _cairo_error (CAIRO_STATUS_NO_MEMORY); + } *document_out = document; return CAIRO_STATUS_SUCCESS; - - CLEANUP_NODE_GLYPHS: - status_ignored = _cairo_output_stream_destroy (document->xml_node_glyphs); - CLEANUP_NODE_DEFS: - status_ignored = _cairo_output_stream_destroy (document->xml_node_defs); - _cairo_scaled_font_subsets_destroy (document->font_subsets); - CLEANUP_DOCUMENT: - free (document); - return status; } static cairo_svg_document_t * @@ -2924,12 +4239,6 @@ _cairo_svg_document_reference (cairo_svg_document_t *document) return document; } -static unsigned int -_cairo_svg_document_allocate_mask_id (cairo_svg_document_t *document) -{ - return document->mask_id++; -} - static cairo_status_t _cairo_svg_document_destroy (cairo_svg_document_t *document) { @@ -2949,13 +4258,14 @@ _cairo_svg_document_destroy (cairo_svg_document_t *document) static cairo_status_t _cairo_svg_document_finish (cairo_svg_document_t *document) { - cairo_status_t status, status2; - cairo_output_stream_t *output = document->output_stream; - cairo_svg_page_t *page; - unsigned int i; - - if (document->finished) + if (document->finished) { return CAIRO_STATUS_SUCCESS; + } + document->finished = TRUE; + + cairo_status_t status, final_status = CAIRO_STATUS_SUCCESS; + + cairo_output_stream_t *output = document->output_stream; /* * Should we add DOCTYPE? @@ -2984,78 +4294,105 @@ _cairo_svg_document_finish (cairo_svg_document_t *document) "<svg xmlns=\"http://www.w3.org/2000/svg\" " "xmlns:xlink=\"http://www.w3.org/1999/xlink\" " "width=\"%f%s\" height=\"%f%s\" " - "viewBox=\"0 0 %f %f\" version=\"%s\">\n", - document->width, _cairo_svg_unit_strings [document->unit], - document->height, _cairo_svg_unit_strings [document->unit], - document->width, document->height, - _cairo_svg_internal_version_strings [document->svg_version]); + "viewBox=\"0 0 %f %f\">\n", + document->width, _cairo_svg_unit_strings[document->unit], + document->height, _cairo_svg_unit_strings[document->unit], + document->width, document->height); status = _cairo_svg_document_emit_font_subsets (document); + if (final_status == CAIRO_STATUS_SUCCESS) { + final_status = status; + } + + cairo_svg_surface_t *surface = NULL; + if (document->owner != NULL) { + surface = (cairo_svg_surface_t *) _cairo_paginated_surface_get_target (document->owner); + + if (surface->xml_node.elements.num_elements > 0) { + cairo_svg_page_t *page = _cairo_svg_surface_store_page (surface); + if (final_status == CAIRO_STATUS_SUCCESS && page == NULL) { + final_status = _cairo_error (CAIRO_STATUS_NO_MEMORY); + } + } - if (_cairo_memory_stream_length (document->xml_node_glyphs) > 0 || - _cairo_memory_stream_length (document->xml_node_defs) > 0) { + if (surface->transitive_paint_used) { + cairo_svg_paint_t *paint_entry = malloc (sizeof (cairo_svg_paint_t)); + if (paint_entry == NULL) { + return _cairo_error (CAIRO_STATUS_NO_MEMORY); + } + paint_entry->source_id = surface->source_id; + paint_entry->box.p1.x = 0; + paint_entry->box.p1.y = 0; + paint_entry->box.p2.x = document->width; + paint_entry->box.p2.y = document->height; + _cairo_svg_paint_box_add_padding (&paint_entry->box); + _cairo_array_init (&paint_entry->paint_elements, sizeof (cairo_svg_paint_element_t)); + _cairo_svg_paint_init_key (paint_entry); + status = _cairo_hash_table_insert (document->paints, &paint_entry->base); + if (unlikely (status)) { + return status; + } + } + } + + _cairo_hash_table_foreach (document->paints, _cairo_svg_paint_compute_func, document); + + if (document->xml_node_filters.elements.num_elements > 0 || + document->xml_node_glyphs.elements.num_elements > 0 || + document->xml_node_defs.elements.num_elements > 0) { _cairo_output_stream_printf (output, "<defs>\n"); - if (_cairo_memory_stream_length (document->xml_node_glyphs) > 0) { + _cairo_svg_stream_copy_to_output_stream (&document->xml_node_filters, output, document->paints); + if (document->xml_node_glyphs.elements.num_elements > 0) { _cairo_output_stream_printf (output, "<g>\n"); - _cairo_memory_stream_copy (document->xml_node_glyphs, output); + _cairo_svg_stream_copy_to_output_stream (&document->xml_node_glyphs, output, document->paints); _cairo_output_stream_printf (output, "</g>\n"); } - _cairo_memory_stream_copy (document->xml_node_defs, output); + _cairo_svg_stream_copy_to_output_stream (&document->xml_node_defs, output, document->paints); _cairo_output_stream_printf (output, "</defs>\n"); } if (document->owner != NULL) { - cairo_svg_surface_t *surface; - - surface = (cairo_svg_surface_t *) _cairo_paginated_surface_get_target (document->owner); - if (surface->xml_node != NULL && - _cairo_memory_stream_length (surface->xml_node) > 0) { - if (unlikely (_cairo_svg_surface_store_page (surface) == NULL)) { - if (status == CAIRO_STATUS_SUCCESS) - status = _cairo_error (CAIRO_STATUS_NO_MEMORY); - } - } - - if (surface->page_set.num_elements > 1 && - _cairo_svg_version_has_page_set_support (document->svg_version)) { + if (surface->page_set.num_elements == 1) { + cairo_svg_page_t *page = _cairo_array_index (&surface->page_set, 0); + _cairo_svg_stream_copy_to_output_stream (&page->xml_node, output, document->paints); + } else if (surface->page_set.num_elements > 1) { _cairo_output_stream_printf (output, "<pageSet>\n"); - for (i = 0; i < surface->page_set.num_elements; i++) { - page = _cairo_array_index (&surface->page_set, i); + for (unsigned int i = 0; i < surface->page_set.num_elements; i++) { + cairo_svg_page_t *page = _cairo_array_index (&surface->page_set, i); _cairo_output_stream_printf (output, "<page>\n"); - _cairo_output_stream_printf (output, - "<g id=\"surface%d\">\n", - page->surface_id); - _cairo_memory_stream_copy (page->xml_node, output); - _cairo_output_stream_printf (output, "</g>\n</page>\n"); + _cairo_svg_stream_copy_to_output_stream (&page->xml_node, output, document->paints); + _cairo_output_stream_printf (output, "</page>\n"); } _cairo_output_stream_printf (output, "</pageSet>\n"); - } else if (surface->page_set.num_elements > 0) { - page = _cairo_array_index (&surface->page_set, surface->page_set.num_elements - 1); - _cairo_output_stream_printf (output, - "<g id=\"surface%d\">\n", - page->surface_id); - _cairo_memory_stream_copy (page->xml_node, output); - _cairo_output_stream_printf (output, "</g>\n"); } } _cairo_output_stream_printf (output, "</svg>\n"); - status2 = _cairo_output_stream_destroy (document->xml_node_glyphs); - if (status == CAIRO_STATUS_SUCCESS) - status = status2; + status = _cairo_svg_stream_destroy (&document->xml_node_defs); + if (final_status == CAIRO_STATUS_SUCCESS) { + final_status = status; + } - status2 = _cairo_output_stream_destroy (document->xml_node_defs); - if (status == CAIRO_STATUS_SUCCESS) - status = status2; + status = _cairo_svg_stream_destroy (&document->xml_node_glyphs); + if (final_status == CAIRO_STATUS_SUCCESS) { + final_status = status; + } - status2 = _cairo_output_stream_destroy (output); - if (status == CAIRO_STATUS_SUCCESS) - status = status2; + status = _cairo_svg_stream_destroy (&document->xml_node_filters); + if (final_status == CAIRO_STATUS_SUCCESS) { + final_status = status; + } - document->finished = TRUE; + _cairo_hash_table_foreach (document->paints, _cairo_svg_paint_pluck, document->paints); + _cairo_hash_table_destroy (document->paints); - return status; + status = _cairo_output_stream_destroy (output); + if (final_status == CAIRO_STATUS_SUCCESS) { + final_status = status; + } + + return final_status; } static cairo_int_status_t @@ -3070,17 +4407,9 @@ _cairo_svg_surface_set_paginated_mode (void *abstract_surface, } static cairo_bool_t -_cairo_svg_surface_supports_fine_grained_fallbacks (void *abstract_surface) +_cairo_svg_surface_supports_fine_grained_fallbacks (void *abstract_surface) { - cairo_svg_surface_t *surface = abstract_surface; - cairo_int_status_t status = CAIRO_INT_STATUS_UNSUPPORTED; - - if (surface->document->svg_version >= CAIRO_SVG_VERSION_1_2) { - status = _cairo_svg_surface_analyze_operator (surface, - CAIRO_OPERATOR_SOURCE); - } - - return status == CAIRO_INT_STATUS_SUCCESS; + return TRUE; } static const cairo_paginated_surface_backend_t cairo_svg_surface_paginated_backend = { @@ -3089,5 +4418,4 @@ static const cairo_paginated_surface_backend_t cairo_svg_surface_paginated_backe NULL, /* _cairo_svg_surface_set_bounding_box */ NULL, /* _cairo_svg_surface_set_fallback_images_required */ _cairo_svg_surface_supports_fine_grained_fallbacks, - }; diff --git a/gfx/cairo/cairo/src/cairo-svg.h b/gfx/cairo/cairo/src/cairo-svg.h index 4d24857bca..7745eec90a 100644 --- a/gfx/cairo/cairo/src/cairo-svg.h +++ b/gfx/cairo/cairo/src/cairo-svg.h @@ -55,7 +55,6 @@ typedef enum _cairo_svg_version { /** * cairo_svg_unit_t: - * * @CAIRO_SVG_UNIT_USER: User unit, a value in the current coordinate system. * If used in the root element for the initial coordinate systems it * corresponds to pixels. (Since 1.16) @@ -74,9 +73,9 @@ typedef enum _cairo_svg_version { * lengths in the SVG specification. * * See also: - * https://www.w3.org/TR/SVG/coords.html#Units - * https://www.w3.org/TR/SVG/types.html#DataTypeLength - * https://www.w3.org/TR/css-values-3/#lengths + * - [SVG Units](https://www.w3.org/TR/SVG/coords.html#Units) + * - [SVG Types](https://www.w3.org/TR/SVG/types.html#DataTypeLength) + * - [CSS Length](https://www.w3.org/TR/css-values-3/#lengths) * * Since: 1.16 **/ diff --git a/gfx/cairo/cairo/src/cairo-tag-attributes-private.h b/gfx/cairo/cairo/src/cairo-tag-attributes-private.h index 3f5fa5b64a..1b770aef9c 100644 --- a/gfx/cairo/cairo/src/cairo-tag-attributes-private.h +++ b/gfx/cairo/cairo/src/cairo-tag-attributes-private.h @@ -49,6 +49,15 @@ typedef enum { TAG_LINK_FILE, } cairo_tag_link_type_t; +typedef struct _cairo_content_attrs { + char *id; + char *tag_name; +} cairo_content_attrs_t; + +typedef struct _cairo_content_ref_attrs { + char *ref; +} cairo_content_ref_attrs_t; + typedef struct _cairo_link_attrs { cairo_tag_link_type_t link_type; cairo_array_t rects; @@ -58,6 +67,9 @@ typedef struct _cairo_link_attrs { int page; cairo_bool_t has_pos; cairo_point_double_t pos; + char *id; + char *ref; + int link_page; } cairo_link_attrs_t; typedef struct _cairo_dest_attrs { @@ -91,9 +103,27 @@ cairo_private cairo_int_status_t _cairo_tag_parse_dest_attributes (const char *attributes, cairo_dest_attrs_t *dest_attrs); cairo_private cairo_int_status_t +_cairo_tag_parse_content_attributes (const char *attributes, cairo_content_attrs_t *content_attrs); + +cairo_private cairo_int_status_t +_cairo_tag_parse_content_ref_attributes (const char *attributes, cairo_content_ref_attrs_t *content_ref_attrs); + +cairo_private cairo_int_status_t _cairo_tag_parse_ccitt_params (const char *attributes, cairo_ccitt_params_t *dest_attrs); cairo_private cairo_int_status_t _cairo_tag_parse_eps_params (const char *attributes, cairo_eps_params_t *dest_attrs); +cairo_private void +_cairo_tag_free_link_attributes (cairo_link_attrs_t *link_attrs); + +cairo_private void +_cairo_tag_free_dest_attributes (cairo_dest_attrs_t *link_attrs); + +cairo_private void +_cairo_tag_free_content_attributes (cairo_content_attrs_t *link_attrs); + +cairo_private void +_cairo_tag_free_content_ref_attributes (cairo_content_ref_attrs_t *link_attrs); + #endif /* CAIRO_TAG_ATTRIBUTES_PRIVATE_H */ diff --git a/gfx/cairo/cairo/src/cairo-tag-attributes.c b/gfx/cairo/cairo/src/cairo-tag-attributes.c index 6d0f63f119..4fde1b5b87 100644 --- a/gfx/cairo/cairo/src/cairo-tag-attributes.c +++ b/gfx/cairo/cairo/src/cairo-tag-attributes.c @@ -60,6 +60,25 @@ typedef struct _attribute_spec { } attribute_spec_t; /* + * id [optional] content id + * content [optional] One or more content ids + */ +static const attribute_spec_t _content_attrib_spec[] = { + { "tag_name", ATTRIBUTE_STRING }, + { "id", ATTRIBUTE_STRING }, + { NULL } +}; + +/* + * id [optional] content id + * content [optional] One or more content ids + */ +static const attribute_spec_t _content_ref_attrib_spec[] = { + { "ref", ATTRIBUTE_STRING }, + { NULL } +}; + +/* * name [required] Unique name of this destination (UTF-8) * x [optional] x coordinate of destination on page. Default is x coord of * extents of operations enclosed by the dest begin/end tags. @@ -68,7 +87,7 @@ typedef struct _attribute_spec { * internal [optional] If true, the name may be optimized out of the PDF where * possible. Default false. */ -static attribute_spec_t _dest_attrib_spec[] = { +static const attribute_spec_t _dest_attrib_spec[] = { { "name", ATTRIBUTE_STRING }, { "x", ATTRIBUTE_FLOAT }, { "y", ATTRIBUTE_FLOAT }, @@ -103,7 +122,7 @@ static attribute_spec_t _dest_attrib_spec[] = { * page - Page number in the PDF file to link to * pos - [optional] Position of destination on page. Default is 0,0. */ -static attribute_spec_t _link_attrib_spec[] = +static const attribute_spec_t _link_attrib_spec[] = { { "rect", ATTRIBUTE_FLOAT, -1 }, { "dest", ATTRIBUTE_STRING }, @@ -111,6 +130,9 @@ static attribute_spec_t _link_attrib_spec[] = { "file", ATTRIBUTE_STRING }, { "page", ATTRIBUTE_INT }, { "pos", ATTRIBUTE_FLOAT, 2 }, + { "id", ATTRIBUTE_STRING }, + { "ref", ATTRIBUTE_STRING }, + { "link_page", ATTRIBUTE_INT }, { NULL } }; @@ -131,7 +153,7 @@ static attribute_spec_t _link_attrib_spec[] = * DamagedRowsBeforeError - Number of damages rows tolerated before an error * occurs. Default: 0. */ -static attribute_spec_t _ccitt_params_spec[] = +static const attribute_spec_t _ccitt_params_spec[] = { { "Columns", ATTRIBUTE_INT }, { "Rows", ATTRIBUTE_INT }, @@ -152,7 +174,7 @@ static attribute_spec_t _ccitt_params_spec[] = * ury - upper right y xoordinate * all coordinates are in PostScript coordinates. */ -static attribute_spec_t _eps_params_spec[] = +static const attribute_spec_t _eps_params_spec[] = { { "bbox", ATTRIBUTE_FLOAT, 4 }, { NULL } @@ -362,16 +384,13 @@ parse_name (const char *attributes, const char *p, const char **end, char **s) attributes, p); p2 = p; - while (_cairo_isalpha (*p2) || _cairo_isdigit (*p2)) + while (_cairo_isalpha (*p2) || _cairo_isdigit (*p2) || *p2 == '_') p2++; len = p2 - p; - name = _cairo_malloc (len + 1); + name = _cairo_strndup (p, len); if (unlikely (name == NULL)) return _cairo_error (CAIRO_STATUS_NO_MEMORY); - - memcpy (name, p, len); - name[len] = 0; *s = name; *end = p2; @@ -379,9 +398,9 @@ parse_name (const char *attributes, const char *p, const char **end, char **s) } static cairo_int_status_t -parse_attributes (const char *attributes, attribute_spec_t *attrib_def, cairo_list_t *list) +parse_attributes (const char *attributes, const attribute_spec_t *attrib_def, cairo_list_t *list) { - attribute_spec_t *def; + const attribute_spec_t *def; attribute_t *attrib; char *name = NULL; cairo_int_status_t status; @@ -493,13 +512,79 @@ free_attributes_list (cairo_list_t *list) } cairo_int_status_t +_cairo_tag_parse_content_attributes (const char *attributes, cairo_content_attrs_t *content_attrs) +{ + cairo_list_t list; + cairo_int_status_t status; + attribute_t *attr; + + cairo_list_init (&list); + status = parse_attributes (attributes, _content_attrib_spec, &list); + if (unlikely (status)) + goto cleanup; + + memset (content_attrs, 0, sizeof (cairo_content_attrs_t)); + cairo_list_foreach_entry (attr, attribute_t, &list, link) + { + if (strcmp (attr->name, "tag_name") == 0) { + content_attrs->tag_name = strdup (attr->scalar.s); + } else if (strcmp (attr->name, "id") == 0) { + content_attrs->id = strdup (attr->scalar.s); + } + } + + if (! content_attrs->tag_name) { + status = _cairo_tag_error ("CONTENT attributes: \"%s\" missing tag_name attribute", + attributes); + } else if (! content_attrs->tag_name) { + status = _cairo_tag_error ("CONTENT attributes: \"%s\" missing id attribute", + attributes); + } + + cleanup: + free_attributes_list (&list); + + return status; +} + +cairo_int_status_t +_cairo_tag_parse_content_ref_attributes (const char *attributes, cairo_content_ref_attrs_t *content_ref_attrs) +{ + cairo_list_t list; + cairo_int_status_t status; + attribute_t *attr; + + cairo_list_init (&list); + status = parse_attributes (attributes, _content_ref_attrib_spec, &list); + if (unlikely (status)) + goto cleanup; + + memset (content_ref_attrs, 0, sizeof (cairo_content_ref_attrs_t)); + cairo_list_foreach_entry (attr, attribute_t, &list, link) + { + if (strcmp (attr->name, "ref") == 0) { + content_ref_attrs->ref = strdup (attr->scalar.s); + } + } + + if (! content_ref_attrs->ref) { + status = _cairo_tag_error ("CONTENT_REF attributes: \"%s\" missing ref attribute", + attributes); + } + + cleanup: + free_attributes_list (&list); + + return status; +} + +cairo_int_status_t _cairo_tag_parse_link_attributes (const char *attributes, cairo_link_attrs_t *link_attrs) { cairo_list_t list; cairo_int_status_t status; attribute_t *attr; attrib_val_t val; - cairo_bool_t has_rect = FALSE; cairo_bool_t invalid_combination = FALSE; cairo_list_init (&list); @@ -557,7 +642,16 @@ _cairo_tag_parse_link_attributes (const char *attributes, cairo_link_attrs_t *li if (unlikely (status)) goto cleanup; } - has_rect = TRUE; + } else if (strcmp (attr->name, "id") == 0) { + link_attrs->id = strdup (attr->scalar.s); + } else if (strcmp (attr->name, "ref") == 0) { + link_attrs->ref = strdup (attr->scalar.s); + } else if (strcmp (attr->name, "link_page") == 0) { + link_attrs->link_page = attr->scalar.i; + if (link_attrs->link_page < 1) { + status = _cairo_tag_error ("Link attributes: \"%s\" page must be >= 1", attributes); + goto cleanup; + } } } @@ -726,3 +820,33 @@ _cairo_tag_parse_eps_params (const char *attributes, cairo_eps_params_t *eps_par return status; } + +void +_cairo_tag_free_link_attributes (cairo_link_attrs_t *link_attrs) +{ + _cairo_array_fini (&link_attrs->rects); + free (link_attrs->dest); + free (link_attrs->uri); + free (link_attrs->file); + free (link_attrs->id); + free (link_attrs->ref); +} + +void +_cairo_tag_free_dest_attributes (cairo_dest_attrs_t *dest_attrs) +{ + free (dest_attrs->name); +} + +void +_cairo_tag_free_content_attributes (cairo_content_attrs_t *content_attrs) +{ + free (content_attrs->id); + free (content_attrs->tag_name); +} + +void +_cairo_tag_free_content_ref_attributes (cairo_content_ref_attrs_t *content_ref_attrs) +{ + free (content_ref_attrs->ref); +} diff --git a/gfx/cairo/cairo/src/cairo-tag-stack-private.h b/gfx/cairo/cairo/src/cairo-tag-stack-private.h index fbb2c0e25b..49145bf1d1 100644 --- a/gfx/cairo/cairo/src/cairo-tag-stack-private.h +++ b/gfx/cairo/cairo/src/cairo-tag-stack-private.h @@ -46,6 +46,9 @@ typedef enum { TAG_TYPE_STRUCTURE = 1, TAG_TYPE_LINK = 2, TAG_TYPE_DEST = 4, + TAG_TYPE_CONTENT = 8, + TAG_TYPE_CONTENT_REF = 16, + TAG_TYPE_ARTIFACT = 16, } cairo_tag_type_t; /* The type of the structure tree. */ @@ -99,6 +102,12 @@ cairo_private cairo_tag_stack_elem_t * _cairo_tag_stack_top_elem (cairo_tag_stack_t *stack); cairo_private void +_cairo_tag_stack_foreach (cairo_tag_stack_t *stack, + void (*func)(cairo_tag_stack_elem_t *elem, + void *closure), + void *closure); + +cairo_private void _cairo_tag_stack_free_elem (cairo_tag_stack_elem_t *elem); cairo_private cairo_tag_type_t diff --git a/gfx/cairo/cairo/src/cairo-tag-stack.c b/gfx/cairo/cairo/src/cairo-tag-stack.c index 095cd73f8d..f182b508b0 100644 --- a/gfx/cairo/cairo/src/cairo-tag-stack.c +++ b/gfx/cairo/cairo/src/cairo-tag-stack.c @@ -99,6 +99,9 @@ static const char * _cairo_tag_stack_struct_pdf_list[] = "Formula", "Form", + /* Section 14.8.2.2.2 - Artifacts */ + "Artifact", + NULL }; @@ -106,6 +109,8 @@ static const char * _cairo_tag_stack_struct_pdf_list[] = static const char * _cairo_tag_stack_cairo_tag_list[] = { CAIRO_TAG_DEST, + CAIRO_TAG_CONTENT, + CAIRO_TAG_CONTENT_REF, NULL }; @@ -166,6 +171,17 @@ _cairo_tag_stack_push (cairo_tag_stack_t *stack, return _cairo_tag_error ("Invalid tag: %s", name); } + cairo_tag_stack_elem_t *top = _cairo_tag_stack_top_elem (stack); + if (top && + (strcmp (top->name, CAIRO_TAG_CONTENT) == 0 || + strcmp (top->name, CAIRO_TAG_CONTENT_REF) == 0 || + strcmp (top->name, "Artifact") == 0)) + { + return _cairo_tag_error ("%s tag can not contain nested tags", + (strcmp (top->name, CAIRO_TAG_CONTENT) == 0) ? "CAIRO_TAG_CONTENT" : + ((strcmp (top->name, CAIRO_TAG_CONTENT_REF) == 0) ? "CAIRO_TAG_CONTENT_REF" : top->name)); + } + if (stack->type == TAG_TREE_TYPE_NO_TAGS) { if (name_in_list (name, _cairo_tag_stack_tagged_pdf_top_level_element_list)) stack->type = TAG_TREE_TYPE_TAGGED; @@ -259,6 +275,19 @@ _cairo_tag_stack_top_elem (cairo_tag_stack_t *stack) } void +_cairo_tag_stack_foreach (cairo_tag_stack_t *stack, + void (*func)(cairo_tag_stack_elem_t *elem, + void *closure), + void *closure) +{ + cairo_tag_stack_elem_t *elem; + + cairo_list_foreach_entry (elem, cairo_tag_stack_elem_t, &stack->list, link) { + func (elem, closure); + } +} + +void _cairo_tag_stack_free_elem (cairo_tag_stack_elem_t *elem) { free (elem->name); @@ -276,9 +305,15 @@ _cairo_tag_get_type (const char *name) if (strcmp(name, "Link") == 0) return (TAG_TYPE_LINK | TAG_TYPE_STRUCTURE); - if (strcmp(name, "cairo.dest") == 0) + if (strcmp(name, CAIRO_TAG_DEST) == 0) return TAG_TYPE_DEST; + if (strcmp(name, CAIRO_TAG_CONTENT) == 0) + return TAG_TYPE_CONTENT; + + if (strcmp(name, CAIRO_TAG_CONTENT_REF) == 0) + return TAG_TYPE_CONTENT_REF; + return TAG_TYPE_STRUCTURE; } diff --git a/gfx/cairo/cairo/src/cairo-tee-surface-private.h b/gfx/cairo/cairo/src/cairo-tee-surface-private.h deleted file mode 100644 index a83cfc959d..0000000000 --- a/gfx/cairo/cairo/src/cairo-tee-surface-private.h +++ /dev/null @@ -1,47 +0,0 @@ -/* cairo - a vector graphics library with display and print output - * - * Copyright © 2009 Chris Wilson - * - * 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., 51 Franklin Street, Suite 500, Boston, MA 02110-1335, USA - * You should have received a copy of the MPL along with this library - * in the file COPYING-MPL-1.1 - * - * The contents of this file are subject to the Mozilla Public License - * Version 1.1 (the "License"); you may not use this file except in - * compliance with the License. You may obtain a copy of the License at - * http://www.mozilla.org/MPL/ - * - * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY - * OF ANY KIND, either express or implied. See the LGPL or the MPL for - * the specific language governing rights and limitations. - * - * The Original Code is the cairo graphics library. - * - * The Initial Developer of the Original Code is University of Southern - * California. - * - * Contributor(s): - * Chris Wilson <chris@chris-wilson.co.uk> - */ - -#ifndef CAIRO_TEE_SURFACE_PRIVATE_H -#define CAIRO_TEE_SURFACE_PRIVATE_H - -#include "cairoint.h" - -cairo_private cairo_surface_t * -_cairo_tee_surface_find_match (void *abstract_surface, - const cairo_surface_backend_t *backend, - cairo_content_t content); - -#endif /* CAIRO_TEE_SURFACE_PRIVATE_H */ diff --git a/gfx/cairo/cairo/src/cairo-tee-surface.c b/gfx/cairo/cairo/src/cairo-tee-surface.c index 7a94c9bca4..35baa96096 100644 --- a/gfx/cairo/cairo/src/cairo-tee-surface.c +++ b/gfx/cairo/cairo/src/cairo-tee-surface.c @@ -35,8 +35,22 @@ * Chris Wilson <chris@chris-wilson.co.uk> */ -/* This surface supports redirecting all its input to multiple surfaces. - */ +/** + * SECTION:cairo-tee + * @Title: Tee surface + * @Short_Description: Redirect input to multiple surfaces + * @See_Also: #cairo_surface_t + * + * The "tee" surface supports redirecting all its input to multiple surfaces. + **/ + +/** + * CAIRO_HAS_TEE_SURFACE: + * + * Defined if the tee surface backend is available. + * + * Since: 1.10 + **/ #include "cairoint.h" @@ -44,7 +58,6 @@ #include "cairo-default-context-private.h" #include "cairo-error-private.h" -#include "cairo-tee-surface-private.h" #include "cairo-recording-surface-inline.h" #include "cairo-surface-wrapper-private.h" #include "cairo-array-private.h" @@ -53,13 +66,10 @@ typedef struct _cairo_tee_surface { cairo_surface_t base; - cairo_surface_wrapper_t master; - cairo_array_t slaves; + cairo_surface_wrapper_t primary; + cairo_array_t replicas; } cairo_tee_surface_t; -slim_hidden_proto (cairo_tee_surface_create); -slim_hidden_proto (cairo_tee_surface_add); - static cairo_surface_t * _cairo_tee_surface_create_similar (void *abstract_surface, cairo_content_t content, @@ -70,21 +80,21 @@ _cairo_tee_surface_create_similar (void *abstract_surface, cairo_tee_surface_t *other = abstract_surface; cairo_surface_t *similar; cairo_surface_t *surface; - cairo_surface_wrapper_t *slaves; - int n, num_slaves; + cairo_surface_wrapper_t *replicas; + int n, num_replicas; - similar = _cairo_surface_wrapper_create_similar (&other->master, + similar = _cairo_surface_wrapper_create_similar (&other->primary, content, width, height); surface = cairo_tee_surface_create (similar); cairo_surface_destroy (similar); if (unlikely (surface->status)) return surface; - num_slaves = _cairo_array_num_elements (&other->slaves); - slaves = _cairo_array_index (&other->slaves, 0); - for (n = 0; n < num_slaves; n++) { + num_replicas = _cairo_array_num_elements (&other->replicas); + replicas = _cairo_array_index (&other->replicas, 0); + for (n = 0; n < num_replicas; n++) { - similar = _cairo_surface_wrapper_create_similar (&slaves[n], + similar = _cairo_surface_wrapper_create_similar (&replicas[n], content, width, height); cairo_tee_surface_add (surface, similar); @@ -104,17 +114,17 @@ static cairo_status_t _cairo_tee_surface_finish (void *abstract_surface) { cairo_tee_surface_t *surface = abstract_surface; - cairo_surface_wrapper_t *slaves; - int n, num_slaves; + cairo_surface_wrapper_t *replicas; + int n, num_replicas; - _cairo_surface_wrapper_fini (&surface->master); + _cairo_surface_wrapper_fini (&surface->primary); - num_slaves = _cairo_array_num_elements (&surface->slaves); - slaves = _cairo_array_index (&surface->slaves, 0); - for (n = 0; n < num_slaves; n++) - _cairo_surface_wrapper_fini (&slaves[n]); + num_replicas = _cairo_array_num_elements (&surface->replicas); + replicas = _cairo_array_index (&surface->replicas, 0); + for (n = 0; n < num_replicas; n++) + _cairo_surface_wrapper_fini (&replicas[n]); - _cairo_array_fini (&surface->slaves); + _cairo_array_fini (&surface->replicas); return CAIRO_STATUS_SUCCESS; } @@ -124,7 +134,7 @@ _cairo_tee_surface_source (void *abstract_surface, cairo_rectangle_int_t *extents) { cairo_tee_surface_t *surface = abstract_surface; - return _cairo_surface_get_source (surface->master.target, extents); + return _cairo_surface_get_source (surface->primary.target, extents); } static cairo_status_t @@ -133,26 +143,26 @@ _cairo_tee_surface_acquire_source_image (void *abstract_surface, void **image_extra) { cairo_tee_surface_t *surface = abstract_surface; - cairo_surface_wrapper_t *slaves; - int num_slaves, n; + cairo_surface_wrapper_t *replicas; + int num_replicas, n; /* we prefer to use a real image surface if available */ - if (_cairo_surface_is_image (surface->master.target)) { - return _cairo_surface_wrapper_acquire_source_image (&surface->master, + if (_cairo_surface_is_image (surface->primary.target)) { + return _cairo_surface_wrapper_acquire_source_image (&surface->primary, image_out, image_extra); } - num_slaves = _cairo_array_num_elements (&surface->slaves); - slaves = _cairo_array_index (&surface->slaves, 0); - for (n = 0; n < num_slaves; n++) { - if (_cairo_surface_is_image (slaves[n].target)) { - return _cairo_surface_wrapper_acquire_source_image (&slaves[n], + num_replicas = _cairo_array_num_elements (&surface->replicas); + replicas = _cairo_array_index (&surface->replicas, 0); + for (n = 0; n < num_replicas; n++) { + if (_cairo_surface_is_image (replicas[n].target)) { + return _cairo_surface_wrapper_acquire_source_image (&replicas[n], image_out, image_extra); } } - return _cairo_surface_wrapper_acquire_source_image (&surface->master, + return _cairo_surface_wrapper_acquire_source_image (&surface->primary, image_out, image_extra); } @@ -163,7 +173,7 @@ _cairo_tee_surface_release_source_image (void *abstract_surface, { cairo_tee_surface_t *surface = abstract_surface; - _cairo_surface_wrapper_release_source_image (&surface->master, + _cairo_surface_wrapper_release_source_image (&surface->primary, image, image_extra); } @@ -171,21 +181,21 @@ static cairo_surface_t * _cairo_tee_surface_snapshot (void *abstract_surface) { cairo_tee_surface_t *surface = abstract_surface; - cairo_surface_wrapper_t *slaves; - int num_slaves, n; + cairo_surface_wrapper_t *replicas; + int num_replicas, n; /* we prefer to use a recording surface for our snapshots */ - if (_cairo_surface_is_recording (surface->master.target)) - return _cairo_surface_wrapper_snapshot (&surface->master); - - num_slaves = _cairo_array_num_elements (&surface->slaves); - slaves = _cairo_array_index (&surface->slaves, 0); - for (n = 0; n < num_slaves; n++) { - if (_cairo_surface_is_recording (slaves[n].target)) - return _cairo_surface_wrapper_snapshot (&slaves[n]); + if (_cairo_surface_is_recording (surface->primary.target)) + return _cairo_surface_wrapper_snapshot (&surface->primary); + + num_replicas = _cairo_array_num_elements (&surface->replicas); + replicas = _cairo_array_index (&surface->replicas, 0); + for (n = 0; n < num_replicas; n++) { + if (_cairo_surface_is_recording (replicas[n].target)) + return _cairo_surface_wrapper_snapshot (&replicas[n]); } - return _cairo_surface_wrapper_snapshot (&surface->master); + return _cairo_surface_wrapper_snapshot (&surface->primary); } static cairo_bool_t @@ -194,7 +204,7 @@ _cairo_tee_surface_get_extents (void *abstract_surface, { cairo_tee_surface_t *surface = abstract_surface; - return _cairo_surface_wrapper_get_extents (&surface->master, rectangle); + return _cairo_surface_wrapper_get_extents (&surface->primary, rectangle); } static void @@ -203,7 +213,7 @@ _cairo_tee_surface_get_font_options (void *abstract_surface, { cairo_tee_surface_t *surface = abstract_surface; - _cairo_surface_wrapper_get_font_options (&surface->master, options); + _cairo_surface_wrapper_get_font_options (&surface->primary, options); } static cairo_int_status_t @@ -213,19 +223,19 @@ _cairo_tee_surface_paint (void *abstract_surface, const cairo_clip_t *clip) { cairo_tee_surface_t *surface = abstract_surface; - cairo_surface_wrapper_t *slaves; - int n, num_slaves; + cairo_surface_wrapper_t *replicas; + int n, num_replicas; cairo_int_status_t status; - num_slaves = _cairo_array_num_elements (&surface->slaves); - slaves = _cairo_array_index (&surface->slaves, 0); - for (n = 0; n < num_slaves; n++) { - status = _cairo_surface_wrapper_paint (&slaves[n], op, source, clip); + num_replicas = _cairo_array_num_elements (&surface->replicas); + replicas = _cairo_array_index (&surface->replicas, 0); + for (n = 0; n < num_replicas; n++) { + status = _cairo_surface_wrapper_paint (&replicas[n], op, source, 0, clip); if (unlikely (status)) return status; } - return _cairo_surface_wrapper_paint (&surface->master, op, source, clip); + return _cairo_surface_wrapper_paint (&surface->primary, op, source, 0, clip); } static cairo_int_status_t @@ -236,21 +246,25 @@ _cairo_tee_surface_mask (void *abstract_surface, const cairo_clip_t *clip) { cairo_tee_surface_t *surface = abstract_surface; - cairo_surface_wrapper_t *slaves; + cairo_surface_wrapper_t *replicas; cairo_int_status_t status; - int n, num_slaves; - - num_slaves = _cairo_array_num_elements (&surface->slaves); - slaves = _cairo_array_index (&surface->slaves, 0); - for (n = 0; n < num_slaves; n++) { - status = _cairo_surface_wrapper_mask (&slaves[n], - op, source, mask, clip); + int n, num_replicas; + + num_replicas = _cairo_array_num_elements (&surface->replicas); + replicas = _cairo_array_index (&surface->replicas, 0); + for (n = 0; n < num_replicas; n++) { + status = _cairo_surface_wrapper_mask (&replicas[n], + op, source, 0, + mask, 0, + clip); if (unlikely (status)) return status; } - return _cairo_surface_wrapper_mask (&surface->master, - op, source, mask, clip); + return _cairo_surface_wrapper_mask (&surface->primary, + op, source, 0, + mask, 0, + clip); } static cairo_int_status_t @@ -266,15 +280,15 @@ _cairo_tee_surface_stroke (void *abstract_surface, const cairo_clip_t *clip) { cairo_tee_surface_t *surface = abstract_surface; - cairo_surface_wrapper_t *slaves; + cairo_surface_wrapper_t *replicas; cairo_int_status_t status; - int n, num_slaves; + int n, num_replicas; - num_slaves = _cairo_array_num_elements (&surface->slaves); - slaves = _cairo_array_index (&surface->slaves, 0); - for (n = 0; n < num_slaves; n++) { - status = _cairo_surface_wrapper_stroke (&slaves[n], - op, source, + num_replicas = _cairo_array_num_elements (&surface->replicas); + replicas = _cairo_array_index (&surface->replicas, 0); + for (n = 0; n < num_replicas; n++) { + status = _cairo_surface_wrapper_stroke (&replicas[n], + op, source, 0, path, style, ctm, ctm_inverse, tolerance, antialias, @@ -283,8 +297,8 @@ _cairo_tee_surface_stroke (void *abstract_surface, return status; } - return _cairo_surface_wrapper_stroke (&surface->master, - op, source, + return _cairo_surface_wrapper_stroke (&surface->primary, + op, source, 0, path, style, ctm, ctm_inverse, tolerance, antialias, @@ -302,15 +316,15 @@ _cairo_tee_surface_fill (void *abstract_surface, const cairo_clip_t *clip) { cairo_tee_surface_t *surface = abstract_surface; - cairo_surface_wrapper_t *slaves; + cairo_surface_wrapper_t *replicas; cairo_int_status_t status; - int n, num_slaves; + int n, num_replicas; - num_slaves = _cairo_array_num_elements (&surface->slaves); - slaves = _cairo_array_index (&surface->slaves, 0); - for (n = 0; n < num_slaves; n++) { - status = _cairo_surface_wrapper_fill (&slaves[n], - op, source, + num_replicas = _cairo_array_num_elements (&surface->replicas); + replicas = _cairo_array_index (&surface->replicas, 0); + for (n = 0; n < num_replicas; n++) { + status = _cairo_surface_wrapper_fill (&replicas[n], + op, source, 0, path, fill_rule, tolerance, antialias, clip); @@ -318,8 +332,8 @@ _cairo_tee_surface_fill (void *abstract_surface, return status; } - return _cairo_surface_wrapper_fill (&surface->master, - op, source, + return _cairo_surface_wrapper_fill (&surface->primary, + op, source, 0, path, fill_rule, tolerance, antialias, clip); @@ -346,9 +360,9 @@ _cairo_tee_surface_show_text_glyphs (void *abstract_surface, const cairo_clip_t *clip) { cairo_tee_surface_t *surface = abstract_surface; - cairo_surface_wrapper_t *slaves; + cairo_surface_wrapper_t *replicas; cairo_int_status_t status; - int n, num_slaves; + int n, num_replicas; cairo_glyph_t *glyphs_copy; /* XXX: This copying is ugly. */ @@ -356,12 +370,12 @@ _cairo_tee_surface_show_text_glyphs (void *abstract_surface, if (unlikely (glyphs_copy == NULL)) return _cairo_error (CAIRO_STATUS_NO_MEMORY); - num_slaves = _cairo_array_num_elements (&surface->slaves); - slaves = _cairo_array_index (&surface->slaves, 0); - for (n = 0; n < num_slaves; n++) { + num_replicas = _cairo_array_num_elements (&surface->replicas); + replicas = _cairo_array_index (&surface->replicas, 0); + for (n = 0; n < num_replicas; n++) { memcpy (glyphs_copy, glyphs, sizeof (cairo_glyph_t) * num_glyphs); - status = _cairo_surface_wrapper_show_text_glyphs (&slaves[n], op, - source, + status = _cairo_surface_wrapper_show_text_glyphs (&replicas[n], op, + source, 0, utf8, utf8_len, glyphs_copy, num_glyphs, clusters, num_clusters, @@ -373,8 +387,8 @@ _cairo_tee_surface_show_text_glyphs (void *abstract_surface, } memcpy (glyphs_copy, glyphs, sizeof (cairo_glyph_t) * num_glyphs); - status = _cairo_surface_wrapper_show_text_glyphs (&surface->master, op, - source, + status = _cairo_surface_wrapper_show_text_glyphs (&surface->primary, op, + source, 0, utf8, utf8_len, glyphs_copy, num_glyphs, clusters, num_clusters, @@ -420,13 +434,29 @@ static const cairo_surface_backend_t cairo_tee_surface_backend = { _cairo_tee_surface_show_text_glyphs }; +/** + * cairo_tee_surface_create: + * @primary: the primary #cairo_surface_t + * + * Creates a new "tee" surface. + * + * The @primary surface is used when querying surface options, like + * font options and extents. + * + * Operations performed on the tee surface will be replayed on any + * surface added to it. + * + * Returns: the newly created surface + * + * Since: 1.10 + **/ cairo_surface_t * -cairo_tee_surface_create (cairo_surface_t *master) +cairo_tee_surface_create (cairo_surface_t *primary) { cairo_tee_surface_t *surface; - if (unlikely (master->status)) - return _cairo_surface_create_in_error (master->status); + if (unlikely (primary->status)) + return _cairo_surface_create_in_error (primary->status); surface = _cairo_malloc (sizeof (cairo_tee_surface_t)); if (unlikely (surface == NULL)) @@ -434,24 +464,33 @@ cairo_tee_surface_create (cairo_surface_t *master) _cairo_surface_init (&surface->base, &cairo_tee_surface_backend, - master->device, - master->content, + primary->device, + primary->content, TRUE); /* is_vector */ - _cairo_surface_wrapper_init (&surface->master, master); + _cairo_surface_wrapper_init (&surface->primary, primary); - _cairo_array_init (&surface->slaves, sizeof (cairo_surface_wrapper_t)); + _cairo_array_init (&surface->replicas, sizeof (cairo_surface_wrapper_t)); return &surface->base; } -slim_hidden_def (cairo_tee_surface_create); +/** + * cairo_tee_surface_add: + * @abstract_surface: a #cairo_tee_surface_t + * @target: the surface to add + * + * Adds a new target surface to the list of replicas of a + * tee surface. + * + * Since: 1.10 + **/ void cairo_tee_surface_add (cairo_surface_t *abstract_surface, cairo_surface_t *target) { cairo_tee_surface_t *surface; - cairo_surface_wrapper_t slave; + cairo_surface_wrapper_t replica; cairo_status_t status; if (unlikely (abstract_surface->status)) @@ -475,22 +514,31 @@ cairo_tee_surface_add (cairo_surface_t *abstract_surface, surface = (cairo_tee_surface_t *) abstract_surface; - _cairo_surface_wrapper_init (&slave, target); - status = _cairo_array_append (&surface->slaves, &slave); + _cairo_surface_wrapper_init (&replica, target); + status = _cairo_array_append (&surface->replicas, &replica); if (unlikely (status)) { - _cairo_surface_wrapper_fini (&slave); + _cairo_surface_wrapper_fini (&replica); status = _cairo_surface_set_error (&surface->base, status); } } -slim_hidden_def (cairo_tee_surface_add); +/** + * cairo_tee_surface_remove: + * @abstract_surface: a #cairo_tee_surface_t + * @target: the surface to remove + * + * Removes the given surface from the list of replicas of a + * tee surface. + * + * Since: 1.10 + **/ void cairo_tee_surface_remove (cairo_surface_t *abstract_surface, cairo_surface_t *target) { cairo_tee_surface_t *surface; - cairo_surface_wrapper_t *slaves; - int n, num_slaves; + cairo_surface_wrapper_t *replicas; + int n, num_replicas; if (unlikely (abstract_surface->status)) return; @@ -507,31 +555,45 @@ cairo_tee_surface_remove (cairo_surface_t *abstract_surface, } surface = (cairo_tee_surface_t *) abstract_surface; - if (target == surface->master.target) { + if (target == surface->primary.target) { _cairo_surface_set_error (abstract_surface, _cairo_error (CAIRO_STATUS_INVALID_INDEX)); return; } - num_slaves = _cairo_array_num_elements (&surface->slaves); - slaves = _cairo_array_index (&surface->slaves, 0); - for (n = 0; n < num_slaves; n++) { - if (slaves[n].target == target) + num_replicas = _cairo_array_num_elements (&surface->replicas); + replicas = _cairo_array_index (&surface->replicas, 0); + for (n = 0; n < num_replicas; n++) { + if (replicas[n].target == target) break; } - if (n == num_slaves) { + if (n == num_replicas) { _cairo_surface_set_error (abstract_surface, _cairo_error (CAIRO_STATUS_INVALID_INDEX)); return; } - _cairo_surface_wrapper_fini (&slaves[n]); - for (n++; n < num_slaves; n++) - slaves[n-1] = slaves[n]; - surface->slaves.num_elements--; /* XXX: cairo_array_remove()? */ + _cairo_surface_wrapper_fini (&replicas[n]); + for (n++; n < num_replicas; n++) + replicas[n-1] = replicas[n]; + surface->replicas.num_elements--; /* XXX: cairo_array_remove()? */ } +/** + * cairo_tee_surface_index: + * @abstract_surface: a #cairo_tee_surface_t + * @index: the index of the replica to retrieve + * + * Retrieves the replica surface at the given index. + * + * The primary surface used to create the #cairo_tee_surface_t is + * always set at the zero index. + * + * Returns: the surface at the given index + * + * Since: 1.10 + **/ cairo_surface_t * cairo_tee_surface_index (cairo_surface_t *abstract_surface, unsigned int index) @@ -548,56 +610,16 @@ cairo_tee_surface_index (cairo_surface_t *abstract_surface, surface = (cairo_tee_surface_t *) abstract_surface; if (index == 0) { - return surface->master.target; + return surface->primary.target; } else { - cairo_surface_wrapper_t *slave; + cairo_surface_wrapper_t *replica; index--; - if (index >= _cairo_array_num_elements (&surface->slaves)) + if (index >= _cairo_array_num_elements (&surface->replicas)) return _cairo_surface_create_in_error (_cairo_error (CAIRO_STATUS_INVALID_INDEX)); - slave = _cairo_array_index (&surface->slaves, index); - return slave->target; - } -} - -cairo_surface_t * -_cairo_tee_surface_find_match (void *abstract_surface, - const cairo_surface_backend_t *backend, - cairo_content_t content) -{ - cairo_tee_surface_t *surface = abstract_surface; - cairo_surface_wrapper_t *slaves; - int num_slaves, n; - - /* exact match first */ - if (surface->master.target->backend == backend && - surface->master.target->content == content) - { - return surface->master.target; - } - - num_slaves = _cairo_array_num_elements (&surface->slaves); - slaves = _cairo_array_index (&surface->slaves, 0); - for (n = 0; n < num_slaves; n++) { - if (slaves[n].target->backend == backend && - slaves[n].target->content == content) - { - return slaves[n].target; - } - } - - /* matching backend? */ - if (surface->master.target->backend == backend) - return surface->master.target; - - num_slaves = _cairo_array_num_elements (&surface->slaves); - slaves = _cairo_array_index (&surface->slaves, 0); - for (n = 0; n < num_slaves; n++) { - if (slaves[n].target->backend == backend) - return slaves[n].target; + replica = _cairo_array_index (&surface->replicas, index); + return replica->target; } - - return NULL; } diff --git a/gfx/cairo/cairo/src/cairo-tee.h b/gfx/cairo/cairo/src/cairo-tee.h index 9125a3a4a2..58264ffff5 100644 --- a/gfx/cairo/cairo/src/cairo-tee.h +++ b/gfx/cairo/cairo/src/cairo-tee.h @@ -43,18 +43,18 @@ CAIRO_BEGIN_DECLS cairo_public cairo_surface_t * -cairo_tee_surface_create (cairo_surface_t *master); +cairo_tee_surface_create (cairo_surface_t *primary); cairo_public void -cairo_tee_surface_add (cairo_surface_t *surface, +cairo_tee_surface_add (cairo_surface_t *abstract_surface, cairo_surface_t *target); cairo_public void -cairo_tee_surface_remove (cairo_surface_t *surface, +cairo_tee_surface_remove (cairo_surface_t *abstract_surface, cairo_surface_t *target); cairo_public cairo_surface_t * -cairo_tee_surface_index (cairo_surface_t *surface, +cairo_tee_surface_index (cairo_surface_t *abstract_surface, unsigned int index); CAIRO_END_DECLS diff --git a/gfx/cairo/cairo/src/cairo-time.c b/gfx/cairo/cairo/src/cairo-time.c index a0003fbfc2..05b64e1571 100644 --- a/gfx/cairo/cairo/src/cairo-time.c +++ b/gfx/cairo/cairo/src/cairo-time.c @@ -61,36 +61,7 @@ _cairo_time_get (void) return mach_absolute_time (); } -#elif defined(__OS2__) -#define INCL_BASE -#include <os2.h> - -static cairo_always_inline double -_cairo_time_1s (void) -{ - ULONG freq; - - DosTmrQueryFreq (&freq); - - return freq; -} - -cairo_time_t -_cairo_time_get (void) -{ - QWORD t; - cairo_int64_t r; - - DosTmrQueryTime (&t); - - r = _cairo_int64_lsl (_cairo_int32_to_int64 (t.ulHi), 32); - r = _cairo_int64_add (r, _cairo_int32_to_int64 (t.ulLo)); - - return r; -} - #elif _WIN32 -#define WIN32_LEAN_AND_MEAN #include <windows.h> static cairo_always_inline double diff --git a/gfx/cairo/cairo/src/cairo-tor22-scan-converter.c b/gfx/cairo/cairo/src/cairo-tor22-scan-converter.c index 79c858e4e5..1e71a35b4e 100644 --- a/gfx/cairo/cairo/src/cairo-tor22-scan-converter.c +++ b/gfx/cairo/cairo/src/cairo-tor22-scan-converter.c @@ -623,16 +623,6 @@ cell_list_rewind (struct cell_list *cells) } inline static void -cell_list_maybe_rewind (struct cell_list *cells, int x) -{ - if (x < cells->cursor->x) { - cells->cursor = cells->rewind; - if (x < cells->cursor->x) - cells->cursor = &cells->head; - } -} - -inline static void cell_list_set_rewind (struct cell_list *cells) { cells->rewind = cells->cursor; diff --git a/gfx/cairo/cairo/src/cairo-toy-font-face.c b/gfx/cairo/cairo/src/cairo-toy-font-face.c index f51dab5ab7..24cd1c4d75 100644 --- a/gfx/cairo/cairo/src/cairo-toy-font-face.c +++ b/gfx/cairo/cairo/src/cairo-toy-font-face.c @@ -135,7 +135,7 @@ _cairo_toy_font_face_init_key (cairo_toy_font_face_t *key, cairo_font_slant_t slant, cairo_font_weight_t weight) { - unsigned long hash; + uintptr_t hash; key->family = family; key->owns_family = FALSE; @@ -145,8 +145,8 @@ _cairo_toy_font_face_init_key (cairo_toy_font_face_t *key, /* 1607 and 1451 are just a couple of arbitrary primes. */ hash = _cairo_hash_string (family); - hash += ((unsigned long) slant) * 1607; - hash += ((unsigned long) weight) * 1451; + hash += ((uintptr_t) slant) * 1607; + hash += ((uintptr_t) weight) * 1451; key->base.hash_entry.hash = hash; } @@ -235,7 +235,7 @@ _cairo_toy_font_face_keys_equal (const void *key_a, * @weight: the weight for the font * * Creates a font face from a triplet of family, slant, and weight. - * These font faces are used in implementation of the the #cairo_t "toy" + * These font faces are used in implementation of the #cairo_t "toy" * font API. * * If @family is the zero-length string "", the platform-specific default @@ -340,7 +340,6 @@ cairo_toy_font_face_create (const char *family, UNWIND: return (cairo_font_face_t*) &_cairo_font_face_nil; } -slim_hidden_def (cairo_toy_font_face_create); static cairo_bool_t _cairo_toy_font_face_destroy (void *abstract_face) @@ -469,7 +468,6 @@ cairo_toy_font_face_get_slant (cairo_font_face_t *font_face) } return toy_font_face->slant; } -slim_hidden_def (cairo_toy_font_face_get_slant); /** * cairo_toy_font_face_get_weight: @@ -496,7 +494,6 @@ cairo_toy_font_face_get_weight (cairo_font_face_t *font_face) } return toy_font_face->weight; } -slim_hidden_def (cairo_toy_font_face_get_weight); static const cairo_font_face_backend_t _cairo_toy_font_face_backend = { CAIRO_FONT_TYPE_TOY, diff --git a/gfx/cairo/cairo/src/cairo-truetype-subset.c b/gfx/cairo/cairo/src/cairo-truetype-subset.c index f5f06defc9..ce2e6ac6d2 100644 --- a/gfx/cairo/cairo/src/cairo-truetype-subset.c +++ b/gfx/cairo/cairo/src/cairo-truetype-subset.c @@ -1,3 +1,4 @@ +/* -*- Mode: c; tab-width: 8; c-basic-offset: 4; indent-tabs-mode: t; -*- */ /* cairo - a vector graphics library with display and print output * * Copyright © 2004 Red Hat, Inc @@ -1297,6 +1298,10 @@ _cairo_truetype_reverse_cmap (cairo_scaled_font_t *scaled_font, return CAIRO_INT_STATUS_UNSUPPORTED; size = be16_to_cpu (map_header.length); + /* minimum table size is 24 bytes */ + if (size < 24) + return CAIRO_INT_STATUS_UNSUPPORTED; + map = _cairo_malloc (size); if (unlikely (map == NULL)) return _cairo_error (CAIRO_STATUS_NO_MEMORY); @@ -1312,8 +1317,10 @@ _cairo_truetype_reverse_cmap (cairo_scaled_font_t *scaled_font, /* A Format 4 cmap contains 8 uint16_t numbers and 4 arrays of * uint16_t each num_segments long. */ - if (size < (8 + 4*num_segments)*sizeof(uint16_t)) - return CAIRO_INT_STATUS_UNSUPPORTED; + if (size < (8 + 4*num_segments)*sizeof(uint16_t)) { + status = CAIRO_INT_STATUS_UNSUPPORTED; + goto fail; + } end_code = map->endCount; start_code = &(end_code[num_segments + 1]); @@ -1350,8 +1357,10 @@ _cairo_truetype_reverse_cmap (cairo_scaled_font_t *scaled_font, int j; if (range_size > 0) { - if ((char*)glyph_ids + 2*range_size > (char*)map + size) - return CAIRO_INT_STATUS_UNSUPPORTED; + if ((char*)glyph_ids + 2*range_size > (char*)map + size) { + status = CAIRO_INT_STATUS_UNSUPPORTED; + goto fail; + } for (j = 0; j < range_size; j++) { if (glyph_ids[j] == g_id_be) { @@ -1438,17 +1447,17 @@ cleanup: #define MAX_FONT_NAME_LENGTH 127 static cairo_status_t -find_name (tt_name_t *name, int name_id, int platform, int encoding, int language, char **str_out) +find_name (tt_name_t *name, unsigned long size, int name_id, int platform, int encoding, int language, char **str_out) { tt_name_record_t *record; - int i, len; + unsigned int i, len; char *str; char *p; cairo_bool_t has_tag; cairo_status_t status; str = NULL; - for (i = 0; i < be16_to_cpu (name->num_records); i++) { + for (i = 0; i < MIN(be16_to_cpu (name->num_records), size / sizeof(name->records[0])); i++) { record = &(name->records[i]); if (be16_to_cpu (record->name) == name_id && be16_to_cpu (record->platform) == platform && @@ -1462,14 +1471,18 @@ find_name (tt_name_t *name, int name_id, int platform, int encoding, int languag if (len > MAX_FONT_NAME_LENGTH) break; + uint16_t offset = be16_to_cpu (name->strings_offset) + be16_to_cpu (record->offset); + if (offset + len > size) + return _cairo_error (CAIRO_STATUS_NO_MEMORY); + str = _cairo_malloc (len + 1); if (str == NULL) return _cairo_error (CAIRO_STATUS_NO_MEMORY); memcpy (str, - ((char*)name) + be16_to_cpu (name->strings_offset) + be16_to_cpu (record->offset), + ((char*)name) + offset, len); - str[be16_to_cpu (record->length)] = 0; + str[len] = 0; break; } } @@ -1483,7 +1496,7 @@ find_name (tt_name_t *name, int name_id, int platform, int encoding, int languag int size = 0; char *utf8; uint16_t *u = (uint16_t *) str; - int u_len = len/2; + unsigned int u_len = len/2; for (i = 0; i < u_len; i++) size += _cairo_ucs4_to_utf8 (be16_to_cpu(u[i]), NULL); @@ -1523,13 +1536,7 @@ find_name (tt_name_t *name, int name_id, int platform, int encoding, int languag } } if (has_tag) { - p = _cairo_malloc (len - 6); - if (unlikely (p == NULL)) { - status =_cairo_error (CAIRO_STATUS_NO_MEMORY); - goto fail; - } - memcpy (p, str + 7, len - 7); - p[len-7] = 0; + p = _cairo_strndup (str + 7, len - 7); free (str); str = p; } @@ -1581,35 +1588,35 @@ _cairo_truetype_read_font_name (cairo_scaled_font_t *scaled_font, /* Find PS Name (name_id = 6). OT spec says PS name must be one of * the following two encodings */ - status = find_name (name, 6, 3, 1, 0x409, &ps_name); /* win, unicode, english-us */ + status = find_name (name, size, 6, 3, 1, 0x409, &ps_name); /* win, unicode, english-us */ if (unlikely(status)) goto fail; if (!ps_name) { - status = find_name (name, 6, 1, 0, 0, &ps_name); /* mac, roman, english */ + status = find_name (name, size, 6, 1, 0, 0, &ps_name); /* mac, roman, english */ if (unlikely(status)) goto fail; } /* Find Family name (name_id = 1) */ - status = find_name (name, 1, 3, 1, 0x409, &family_name); /* win, unicode, english-us */ + status = find_name (name, size, 1, 3, 1, 0x409, &family_name); /* win, unicode, english-us */ if (unlikely(status)) goto fail; if (!family_name) { - status = find_name (name, 1, 3, 0, 0x409, &family_name); /* win, symbol, english-us */ + status = find_name (name, size, 1, 3, 0, 0x409, &family_name); /* win, symbol, english-us */ if (unlikely(status)) goto fail; } if (!family_name) { - status = find_name (name, 1, 1, 0, 0, &family_name); /* mac, roman, english */ + status = find_name (name, size, 1, 1, 0, 0, &family_name); /* mac, roman, english */ if (unlikely(status)) goto fail; } if (!family_name) { - status = find_name (name, 1, 3, 1, -1, &family_name); /* win, unicode, any language */ + status = find_name (name, size, 1, 3, 1, -1, &family_name); /* win, unicode, any language */ if (unlikely(status)) goto fail; } diff --git a/gfx/cairo/cairo/src/cairo-type1-fallback.c b/gfx/cairo/cairo/src/cairo-type1-fallback.c index 0b8e66cd0b..3a44c46661 100644 --- a/gfx/cairo/cairo/src/cairo-type1-fallback.c +++ b/gfx/cairo/cairo/src/cairo-type1-fallback.c @@ -1,3 +1,4 @@ +/* -*- Mode: c; tab-width: 8; c-basic-offset: 4; indent-tabs-mode: t; -*- */ /* cairo - a vector graphics library with display and print output * * Copyright © 2006 Red Hat, Inc @@ -354,6 +355,7 @@ cairo_type1_font_create_charstring (cairo_type1_font_t *font, glyph_index, CAIRO_SCALED_GLYPH_INFO_METRICS| CAIRO_SCALED_GLYPH_INFO_PATH, + NULL, /* foreground color */ &scaled_glyph); /* It is ok for the .notdef glyph to not have a path available. We @@ -363,6 +365,7 @@ cairo_type1_font_create_charstring (cairo_type1_font_t *font, status = _cairo_scaled_glyph_lookup (font->type1_scaled_font, glyph_index, CAIRO_SCALED_GLYPH_INFO_METRICS, + NULL, /* foreground color */ &scaled_glyph); } if (unlikely (status)) diff --git a/gfx/cairo/cairo/src/cairo-type1-subset.c b/gfx/cairo/cairo/src/cairo-type1-subset.c index c7ab367e84..0388f374eb 100644 --- a/gfx/cairo/cairo/src/cairo-type1-subset.c +++ b/gfx/cairo/cairo/src/cairo-type1-subset.c @@ -70,7 +70,7 @@ typedef struct _cairo_type1_font_subset { struct { unsigned int font_id; char *base_font; - unsigned int num_glyphs; + unsigned int num_glyphs; /* Num /CharStrings in font */ double x_min, y_min, x_max, y_max; double ascent, descent; double units_per_em; @@ -81,6 +81,9 @@ typedef struct _cairo_type1_font_subset { unsigned long trailer_size; } base; + /* Num glyphs in subset. May be greater than + * scaled_font_subset->num_glyphs due to glyphs required by the + * SEAC operator. */ int num_glyphs; /* The glyphs and glyph_names arrays are indexed by the order of @@ -89,12 +92,12 @@ typedef struct _cairo_type1_font_subset { * function is used to map the glyph index to the glyph order in * the Charstrings. */ - glyph_data_t *glyphs; - char **glyph_names; cairo_array_t glyphs_array; + glyph_data_t *glyphs; /* pointer to first element of above array */ cairo_array_t glyph_names_array; + char **glyph_names; /* pointer to first element of above array */ - int num_subrs; + int num_subrs; /* Num /Subrs routines in the font */ cairo_bool_t subset_subrs; struct { const char *subr_string; @@ -102,12 +105,17 @@ typedef struct _cairo_type1_font_subset { const char *np; int np_length; cairo_bool_t used; - } *subrs; + } *subrs; /* array with num_subrs elements */ - /* Indexed by subset_index this maps to the glyph order in the - * glyph_names and glyphs arrays. Has font->num_golyphs - * elements. */ - int *subset_index_to_glyphs; + /* Maps scaled_font_subset index to glyphs_array. + * Array size = scaled_font_subset->num_glyphs. */ + int *scaled_subset_index_to_glyphs; + + /* Keeps track of the glyphs that will be emitted in the subset. + * Allocated size = base.num_glyphs. Number of entries = num_glyphs. + * Array values are glyph_array indexes. + */ + int *type1_subset_index_to_glyphs; cairo_output_stream_t *output; cairo_array_t contents; @@ -159,7 +167,12 @@ _cairo_type1_font_subset_init (cairo_type1_font_subset_t *font, _cairo_array_init (&font->glyphs_array, sizeof (glyph_data_t)); _cairo_array_init (&font->glyph_names_array, sizeof (char *)); - font->subset_index_to_glyphs = NULL; + font->scaled_subset_index_to_glyphs = calloc (scaled_font_subset->num_glyphs, sizeof font->scaled_subset_index_to_glyphs[0]); + if (unlikely (font->scaled_subset_index_to_glyphs == NULL)) + return _cairo_error (CAIRO_STATUS_NO_MEMORY); + + + font->type1_subset_index_to_glyphs = NULL; font->base.num_glyphs = 0; font->num_subrs = 0; font->subset_subrs = TRUE; @@ -180,7 +193,7 @@ cairo_type1_font_subset_use_glyph (cairo_type1_font_subset_t *font, int glyph) return; font->glyphs[glyph].subset_index = font->num_glyphs; - font->subset_index_to_glyphs[font->num_glyphs] = glyph; + font->type1_subset_index_to_glyphs[font->num_glyphs] = glyph; font->num_glyphs++; } @@ -391,7 +404,7 @@ cairo_type1_font_subset_get_bbox (cairo_type1_font_subset_t *font) if (yy == 0.0) return CAIRO_INT_STATUS_UNSUPPORTED; - /* Freetype uses 1/yy to get units per EM */ + /* FreeType uses 1/yy to get units per EM */ font->base.units_per_em = 1.0/yy; /* If the FontMatrix is not a uniform scale the metrics we extract @@ -470,6 +483,7 @@ cairo_type1_font_subset_write_header (cairo_type1_font_subset_t *font, { const char *start, *end, *segment_end; unsigned int i; + int glyph; /* FIXME: * This function assumes that /FontName always appears @@ -550,13 +564,12 @@ cairo_type1_font_subset_write_header (cairo_type1_font_subset_t *font, } } } else { - for (i = 0; i < font->base.num_glyphs; i++) { - if (font->glyphs[i].subset_index <= 0) - continue; + for (i = 1; i < font->scaled_font_subset->num_glyphs; i++) { + glyph = font->scaled_subset_index_to_glyphs[i]; _cairo_output_stream_printf (font->output, "dup %d /%s put\n", - font->glyphs[i].subset_index, - font->glyph_names[i]); + i, + font->glyph_names[glyph]); } } _cairo_output_stream_printf (font->output, "readonly def"); @@ -630,7 +643,7 @@ cairo_type1_font_subset_decrypt_eexec_segment (cairo_type1_font_subset_t *font) unsigned char *in, *end; char *out; int c, p; - int i; + unsigned int i; in = (unsigned char *) font->eexec_segment; end = (unsigned char *) in + font->eexec_segment_size; @@ -1072,6 +1085,9 @@ cairo_type1_font_for_each_subr (cairo_type1_font_subset_t *font, /* Skip binary data and | or NP token. */ p = skip_token (subr_string + subr_length, cleartext_end); + if (p == NULL) + return CAIRO_INT_STATUS_UNSUPPORTED; + while (p < cleartext_end && _cairo_isspace(*p)) p++; @@ -1235,6 +1251,9 @@ cairo_type1_font_subset_for_each_glyph (cairo_type1_font_subset_t *font, /* Skip binary data and |- or ND token. */ p = skip_token (charstring + charstring_length, dict_end); + if (p == NULL) + return CAIRO_INT_STATUS_UNSUPPORTED; + while (p < dict_end && _cairo_isspace(*p)) p++; @@ -1391,8 +1410,8 @@ skip_subrs: font->glyphs = _cairo_array_index (&font->glyphs_array, 0); font->glyph_names = _cairo_array_index (&font->glyph_names_array, 0); font->base.num_glyphs = _cairo_array_num_elements (&font->glyphs_array); - font->subset_index_to_glyphs = calloc (font->base.num_glyphs, sizeof font->subset_index_to_glyphs[0]); - if (unlikely (font->subset_index_to_glyphs == NULL)) + font->type1_subset_index_to_glyphs = calloc (font->base.num_glyphs, sizeof font->type1_subset_index_to_glyphs[0]); + if (unlikely (font->type1_subset_index_to_glyphs == NULL)) return _cairo_error (CAIRO_STATUS_NO_MEMORY); backend = font->scaled_font_subset->scaled_font->backend; @@ -1414,6 +1433,7 @@ skip_subrs: return status; cairo_type1_font_subset_use_glyph (font, index); + font->scaled_subset_index_to_glyphs[i] = index; } /* Go through the charstring of each glyph in use, get the glyph @@ -1421,7 +1441,7 @@ skip_subrs: * seac operator (which may cause font->num_glyphs to increase * while this loop is executing). Also subset the Subrs. */ for (j = 0; j < font->num_glyphs; j++) { - glyph = font->subset_index_to_glyphs[j]; + glyph = font->type1_subset_index_to_glyphs[j]; font->build_stack.sp = 0; font->ps_stack.sp = 0; status = cairo_type1_font_subset_parse_charstring (font, @@ -1711,7 +1731,9 @@ _cairo_type1_font_subset_fini (cairo_type1_font_subset_t *font) free (font->base.base_font); - free (font->subset_index_to_glyphs); + free (font->scaled_subset_index_to_glyphs); + + free (font->type1_subset_index_to_glyphs); free (font->cleartext); @@ -1730,6 +1752,7 @@ _cairo_type1_subset_init (cairo_type1_subset_t *type1_subset, unsigned long length; unsigned int i; char buf[30]; + int glyph; /* We need to use a fallback font if this font differs from the type1 outlines. */ if (scaled_font_subset->scaled_font->backend->is_synthetic) { @@ -1759,14 +1782,13 @@ _cairo_type1_subset_init (cairo_type1_subset_t *type1_subset, if (unlikely (type1_subset->base_font == NULL)) goto fail1; - type1_subset->widths = calloc (sizeof (double), font.num_glyphs); + type1_subset->widths = calloc (sizeof (double), scaled_font_subset->num_glyphs); if (unlikely (type1_subset->widths == NULL)) goto fail2; - for (i = 0; i < font.base.num_glyphs; i++) { - if (font.glyphs[i].subset_index < 0) - continue; - type1_subset->widths[font.glyphs[i].subset_index] = - font.glyphs[i].width; + + for (i = 0; i < font.scaled_font_subset->num_glyphs; i++) { + glyph = font.scaled_subset_index_to_glyphs[i]; + type1_subset->widths[i] = font.glyphs[glyph].width; } type1_subset->x_min = font.base.x_min; diff --git a/gfx/cairo/cairo/src/cairo-type3-glyph-surface.c b/gfx/cairo/cairo/src/cairo-type3-glyph-surface.c index 6b21023190..53c029493e 100644 --- a/gfx/cairo/cairo/src/cairo-type3-glyph-surface.c +++ b/gfx/cairo/cairo/src/cairo-type3-glyph-surface.c @@ -182,7 +182,9 @@ _cairo_type3_glyph_surface_finish (void *abstract_surface) { cairo_type3_glyph_surface_t *surface = abstract_surface; - return _cairo_pdf_operators_fini (&surface->pdf_operators); + cairo_status_t status = _cairo_pdf_operators_fini (&surface->pdf_operators); + _cairo_surface_clipper_reset (&surface->clipper); + return status; } static cairo_int_status_t @@ -205,6 +207,9 @@ _cairo_type3_glyph_surface_paint (void *abstract_surface, return status; pattern = (const cairo_surface_pattern_t *) source; + if (pattern->surface->type == CAIRO_SURFACE_TYPE_RECORDING) + return CAIRO_INT_STATUS_IMAGE_FALLBACK; + status = _cairo_surface_acquire_source_image (pattern->surface, &image, &image_extra); if (unlikely (status)) @@ -289,33 +294,7 @@ _cairo_type3_glyph_surface_show_glyphs (void *abstract_surface, cairo_scaled_font_t *scaled_font, const cairo_clip_t *clip) { - cairo_type3_glyph_surface_t *surface = abstract_surface; - cairo_int_status_t status; - cairo_scaled_font_t *font; - cairo_matrix_t new_ctm; - - status = _cairo_surface_clipper_set_clip (&surface->clipper, clip); - if (unlikely (status)) - return status; - - cairo_matrix_multiply (&new_ctm, &surface->cairo_to_pdf, &scaled_font->ctm); - font = cairo_scaled_font_create (scaled_font->font_face, - &scaled_font->font_matrix, - &new_ctm, - &scaled_font->options); - if (unlikely (font->status)) - return font->status; - - status = _cairo_pdf_operators_show_text_glyphs (&surface->pdf_operators, - NULL, 0, - glyphs, num_glyphs, - NULL, 0, - FALSE, - font); - - cairo_scaled_font_destroy (font); - - return status; + return CAIRO_INT_STATUS_IMAGE_FALLBACK; } static const cairo_surface_backend_t cairo_type3_glyph_surface_backend = { @@ -373,6 +352,7 @@ _cairo_type3_glyph_surface_emit_fallback_image (cairo_type3_glyph_surface_t *sur glyph_index, CAIRO_SCALED_GLYPH_INFO_METRICS | CAIRO_SCALED_GLYPH_INFO_SURFACE, + NULL, /* foreground color */ &scaled_glyph); if (unlikely (status)) return status; @@ -428,6 +408,7 @@ _cairo_type3_glyph_surface_analyze_glyph (void *abstract_surface, status = _cairo_scaled_glyph_lookup (surface->scaled_font, glyph_index, CAIRO_SCALED_GLYPH_INFO_RECORDING_SURFACE, + NULL, /* foreground color */ &scaled_glyph); if (_cairo_int_status_is_error (status)) @@ -476,15 +457,27 @@ _cairo_type3_glyph_surface_emit_glyph (void *abstract_surface, _cairo_type3_glyph_surface_set_stream (surface, stream); _cairo_scaled_font_freeze_cache (surface->scaled_font); + + /* Check if this is a color glyph and bail out if it is */ status = _cairo_scaled_glyph_lookup (surface->scaled_font, glyph_index, - CAIRO_SCALED_GLYPH_INFO_METRICS | - CAIRO_SCALED_GLYPH_INFO_RECORDING_SURFACE, + CAIRO_SCALED_GLYPH_INFO_COLOR_SURFACE, + NULL, /* foreground color */ &scaled_glyph); + if (status == CAIRO_INT_STATUS_SUCCESS) { + status = CAIRO_INT_STATUS_UNSUPPORTED; + goto FAIL; + } status = _cairo_scaled_glyph_lookup (surface->scaled_font, + glyph_index, + CAIRO_SCALED_GLYPH_INFO_METRICS | + CAIRO_SCALED_GLYPH_INFO_RECORDING_SURFACE, + NULL, /* foreground color */ + &scaled_glyph); if (status == CAIRO_INT_STATUS_UNSUPPORTED) { status = _cairo_scaled_glyph_lookup (surface->scaled_font, glyph_index, CAIRO_SCALED_GLYPH_INFO_METRICS, + NULL, /* foreground color */ &scaled_glyph); if (status == CAIRO_INT_STATUS_SUCCESS) status = CAIRO_INT_STATUS_IMAGE_FALLBACK; diff --git a/gfx/cairo/cairo/src/cairo-types-private.h b/gfx/cairo/cairo/src/cairo-types-private.h index d47064a854..c121101c87 100644 --- a/gfx/cairo/cairo/src/cairo-types-private.h +++ b/gfx/cairo/cairo/src/cairo-types-private.h @@ -117,8 +117,8 @@ struct _cairo_observer { * * A #cairo_hash_entry_t contains both a key and a value for * #cairo_hash_table_t. User-derived types for #cairo_hash_entry_t must - * be type-compatible with this structure (eg. they must have an - * unsigned long as the first parameter. The easiest way to get this + * be type-compatible with this structure (eg. they must have a + * uintptr_t as the first parameter. The easiest way to get this * is to use: * * typedef _my_entry { @@ -147,7 +147,7 @@ struct _cairo_observer { * the entry need not be initialized if so desired. **/ struct _cairo_hash_entry { - unsigned long hash; + uintptr_t hash; }; struct _cairo_array { @@ -163,6 +163,11 @@ typedef enum _cairo_round_glyph_positions { CAIRO_ROUND_GLYPH_POS_OFF } cairo_round_glyph_positions_t; +typedef struct { + unsigned int index; + double red, green, blue, alpha; +} cairo_palette_color_t; + struct _cairo_font_options { cairo_antialias_t antialias; cairo_subpixel_order_t subpixel_order; @@ -171,6 +176,10 @@ struct _cairo_font_options { cairo_hint_metrics_t hint_metrics; cairo_round_glyph_positions_t round_glyph_positions; char *variations; + cairo_color_mode_t color_mode; + unsigned int palette_index; + cairo_palette_color_t *custom_palette; + unsigned int custom_palette_size; }; struct _cairo_glyph_text_info { @@ -230,7 +239,8 @@ typedef enum _cairo_internal_surface_type { CAIRO_INTERNAL_SURFACE_TYPE_TEST_PAGINATED, CAIRO_INTERNAL_SURFACE_TYPE_TEST_WRAPPING, CAIRO_INTERNAL_SURFACE_TYPE_NULL, - CAIRO_INTERNAL_SURFACE_TYPE_TYPE3_GLYPH + CAIRO_INTERNAL_SURFACE_TYPE_TYPE3_GLYPH, + CAIRO_INTERNAL_SURFACE_TYPE_QUARTZ_SNAPSHOT } cairo_internal_surface_type_t; typedef enum _cairo_internal_device_type { @@ -352,6 +362,8 @@ typedef struct _cairo_stroke_style { double *dash; unsigned int num_dashes; double dash_offset; + cairo_bool_t is_hairline; + double pre_hairline_line_width; } cairo_stroke_style_t; typedef struct _cairo_format_masks { @@ -401,6 +413,17 @@ typedef struct _cairo_unscaled_font { cairo_reference_count_t ref_count; const cairo_unscaled_font_backend_t *backend; } cairo_unscaled_font_t; + +typedef enum _cairo_analysis_source { + CAIRO_ANALYSIS_SOURCE_PAINT, + CAIRO_ANALYSIS_SOURCE_MASK, + CAIRO_ANALYSIS_MASK_MASK, + CAIRO_ANALYSIS_SOURCE_FILL, + CAIRO_ANALYSIS_SOURCE_STROKE, + CAIRO_ANALYSIS_SOURCE_SHOW_GLYPHS, + CAIRO_ANALYSIS_SOURCE_NONE /* Used when analysis_source is not applicable. */ +} cairo_analysis_source_t; + CAIRO_END_DECLS #endif /* CAIRO_TYPES_PRIVATE_H */ diff --git a/gfx/cairo/cairo/src/cairo-unicode.c b/gfx/cairo/cairo/src/cairo-unicode.c index 966ae84b59..b96a3a2351 100644 --- a/gfx/cairo/cairo/src/cairo-unicode.c +++ b/gfx/cairo/cairo/src/cairo-unicode.c @@ -99,9 +99,7 @@ #define UNICODE_VALID(Char) \ ((Char) < 0x110000 && \ - (((Char) & 0xFFFFF800) != 0xD800) && \ - ((Char) < 0xFDD0 || (Char) > 0xFDEF) && \ - ((Char) & 0xFFFE) != 0xFFFE) + (((Char) & 0xFFFFF800) != 0xD800)) static const char utf8_skip_data[256] = { 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, diff --git a/gfx/cairo/cairo/src/cairo-uninstalled.pc.in b/gfx/cairo/cairo/src/cairo-uninstalled.pc.in deleted file mode 100644 index 9dc3231ae4..0000000000 --- a/gfx/cairo/cairo/src/cairo-uninstalled.pc.in +++ /dev/null @@ -1,8 +0,0 @@ -Name: cairo -Description: Multi-platform 2D graphics library -Version: @VERSION@ - -@PKGCONFIG_REQUIRES@: @CAIRO_REQUIRES@ -Libs: ${pc_top_builddir}/${pcfiledir}/src/libcairo.la -Libs.private: @CAIRO_NONPKGCONFIG_LIBS@ -Cflags: -I${pc_top_builddir}/${pcfiledir}/@srcdir@/src diff --git a/gfx/cairo/cairo/src/cairo-user-font.c b/gfx/cairo/cairo/src/cairo-user-font.c index a26fb57ee1..37642cd1c1 100644 --- a/gfx/cairo/cairo/src/cairo-user-font.c +++ b/gfx/cairo/cairo/src/cairo-user-font.c @@ -1,3 +1,4 @@ +/* -*- Mode: c; tab-width: 8; c-basic-offset: 4; indent-tabs-mode: t; -*- */ /* cairo - a vector graphics library with display and print output * * Copyright © 2006, 2008 Red Hat, Inc @@ -44,7 +45,7 @@ * SECTION:cairo-user-fonts * @Title:User Fonts * @Short_Description: Font support with font data provided by the user - * + * * The user-font feature allows the cairo user to provide drawings for glyphs * in a font. This is most useful in implementing fonts in non-standard * formats, like SVG fonts and Flash fonts, but can also be used by games and @@ -64,6 +65,7 @@ typedef struct _cairo_user_scaled_font_methods { cairo_user_scaled_font_init_func_t init; + cairo_user_scaled_font_render_glyph_func_t render_color_glyph; cairo_user_scaled_font_render_glyph_func_t render_glyph; cairo_user_scaled_font_unicode_to_glyph_func_t unicode_to_glyph; cairo_user_scaled_font_text_to_glyphs_func_t text_to_glyphs; @@ -75,7 +77,7 @@ typedef struct _cairo_user_font_face { /* Set to true after first scaled font is created. At that point, * the scaled_font_methods cannot change anymore. */ cairo_bool_t immutable; - + cairo_bool_t has_color; cairo_user_scaled_font_methods_t scaled_font_methods; } cairo_user_font_face_t; @@ -93,26 +95,48 @@ typedef struct _cairo_user_scaled_font { double snap_x_scale; double snap_y_scale; + cairo_pattern_t *foreground_marker; + cairo_pattern_t *foreground_pattern; + cairo_bool_t foreground_marker_used; + cairo_bool_t foreground_colors_used; + } cairo_user_scaled_font_t; /* #cairo_user_scaled_font_t */ static cairo_surface_t * -_cairo_user_scaled_font_create_recording_surface (const cairo_user_scaled_font_t *scaled_font) +_cairo_user_scaled_font_create_recording_surface (cairo_user_scaled_font_t *scaled_font, + cairo_bool_t color, + const cairo_color_t *foreground_color) { cairo_content_t content; - content = scaled_font->base.options.antialias == CAIRO_ANTIALIAS_SUBPIXEL ? - CAIRO_CONTENT_COLOR_ALPHA : - CAIRO_CONTENT_ALPHA; + if (color) { + content = CAIRO_CONTENT_COLOR_ALPHA; + } else { + content = scaled_font->base.options.antialias == CAIRO_ANTIALIAS_SUBPIXEL ? + CAIRO_CONTENT_COLOR_ALPHA : + CAIRO_CONTENT_ALPHA; + } + + if (scaled_font->foreground_pattern) + cairo_pattern_destroy (scaled_font->foreground_pattern); + + scaled_font->foreground_marker_used = FALSE; + scaled_font->foreground_colors_used = FALSE; + if (foreground_color) { + scaled_font->foreground_pattern = _cairo_pattern_create_solid (foreground_color); + } else { + scaled_font->foreground_pattern = cairo_pattern_create_rgb (0, 0, 0); + } return cairo_recording_surface_create (content, NULL); } - static cairo_t * _cairo_user_scaled_font_create_recording_context (const cairo_user_scaled_font_t *scaled_font, - cairo_surface_t *recording_surface) + cairo_surface_t *recording_surface, + cairo_bool_t color) { cairo_t *cr; @@ -127,130 +151,264 @@ _cairo_user_scaled_font_create_recording_context (const cairo_user_scaled_font_t cairo_set_font_size (cr, 1.0); cairo_set_font_options (cr, &scaled_font->base.options); - cairo_set_source_rgb (cr, 1., 1., 1.); + if (!color) + cairo_set_source_rgb (cr, 1., 1., 1.); return cr; } static cairo_int_status_t -_cairo_user_scaled_glyph_init (void *abstract_font, - cairo_scaled_glyph_t *scaled_glyph, - cairo_scaled_glyph_info_t info) +_cairo_user_scaled_glyph_init_record_glyph (cairo_user_scaled_font_t *scaled_font, + cairo_scaled_glyph_t *scaled_glyph, + const cairo_color_t *foreground_color) { + cairo_user_font_face_t *face = + (cairo_user_font_face_t *) scaled_font->base.font_face; + cairo_text_extents_t extents = scaled_font->default_glyph_extents; + cairo_surface_t *recording_surface = NULL; cairo_int_status_t status = CAIRO_STATUS_SUCCESS; - cairo_user_scaled_font_t *scaled_font = abstract_font; - cairo_surface_t *recording_surface = scaled_glyph->recording_surface; + cairo_t *cr; + cairo_bool_t foreground_used = FALSE; + + if (!face->scaled_font_methods.render_color_glyph && !face->scaled_font_methods.render_glyph) + return CAIRO_STATUS_USER_FONT_NOT_IMPLEMENTED; + + /* special case for 0 rank matrix (as in _cairo_scaled_font_init): empty surface */ + if (_cairo_matrix_is_scale_0 (&scaled_font->base.scale)) { + recording_surface = _cairo_user_scaled_font_create_recording_surface (scaled_font, FALSE, foreground_color); + _cairo_scaled_glyph_set_recording_surface (scaled_glyph, + &scaled_font->base, + recording_surface, + NULL); + } else { + status = CAIRO_STATUS_USER_FONT_NOT_IMPLEMENTED; + + if (face->scaled_font_methods.render_color_glyph && + scaled_font->base.options.color_mode != CAIRO_COLOR_MODE_NO_COLOR) + { + recording_surface = _cairo_user_scaled_font_create_recording_surface (scaled_font, TRUE, foreground_color); + + cr = _cairo_user_scaled_font_create_recording_context (scaled_font, recording_surface, TRUE); + status = face->scaled_font_methods.render_color_glyph ((cairo_scaled_font_t *)scaled_font, + _cairo_scaled_glyph_index(scaled_glyph), + cr, &extents); + if (status == CAIRO_INT_STATUS_SUCCESS) { + status = cairo_status (cr); + scaled_glyph->color_glyph = TRUE; + scaled_glyph->color_glyph_set = TRUE; + } - if (!scaled_glyph->recording_surface) { - cairo_user_font_face_t *face = - (cairo_user_font_face_t *) scaled_font->base.font_face; - cairo_text_extents_t extents = scaled_font->default_glyph_extents; - cairo_t *cr; + cairo_destroy (cr); + foreground_used = scaled_font->foreground_marker_used || scaled_font->foreground_colors_used; + } - if (!face->scaled_font_methods.render_glyph) - return CAIRO_STATUS_USER_FONT_NOT_IMPLEMENTED; + if (status == (cairo_int_status_t)CAIRO_STATUS_USER_FONT_NOT_IMPLEMENTED && + face->scaled_font_methods.render_glyph) { + if (recording_surface) + cairo_surface_destroy (recording_surface); + recording_surface = _cairo_user_scaled_font_create_recording_surface (scaled_font, FALSE, foreground_color); + recording_surface->device_transform.x0 = .25 * _cairo_scaled_glyph_xphase (scaled_glyph); + recording_surface->device_transform.y0 = .25 * _cairo_scaled_glyph_yphase (scaled_glyph); - recording_surface = _cairo_user_scaled_font_create_recording_surface (scaled_font); + cr = _cairo_user_scaled_font_create_recording_context (scaled_font, recording_surface, FALSE); - /* special case for 0 rank matrix (as in _cairo_scaled_font_init): empty surface */ - if (!_cairo_matrix_is_scale_0 (&scaled_font->base.scale)) { - cr = _cairo_user_scaled_font_create_recording_context (scaled_font, recording_surface); status = face->scaled_font_methods.render_glyph ((cairo_scaled_font_t *)scaled_font, _cairo_scaled_glyph_index(scaled_glyph), cr, &extents); - if (status == CAIRO_INT_STATUS_SUCCESS) - status = cairo_status (cr); + if (status == CAIRO_INT_STATUS_SUCCESS) { + status = cairo_status (cr); + scaled_glyph->color_glyph = FALSE; + scaled_glyph->color_glyph_set = TRUE; + } cairo_destroy (cr); + foreground_used = FALSE; + } - if (unlikely (status)) { - cairo_surface_destroy (recording_surface); - return status; - } + if (status != CAIRO_INT_STATUS_SUCCESS) { + if (recording_surface) + cairo_surface_destroy (recording_surface); + return status; } _cairo_scaled_glyph_set_recording_surface (scaled_glyph, &scaled_font->base, - recording_surface); + recording_surface, + foreground_used ? foreground_color : NULL); + } + /* set metrics */ - /* set metrics */ + if (extents.width == 0.) { + cairo_box_t bbox; + double x1, y1, x2, y2; + double x_scale, y_scale; - if (extents.width == 0.) { - cairo_box_t bbox; - double x1, y1, x2, y2; - double x_scale, y_scale; + /* Compute extents.x/y/width/height from recording_surface, + * in font space. + */ + status = _cairo_recording_surface_get_bbox ((cairo_recording_surface_t *) recording_surface, + &bbox, + &scaled_font->extent_scale); + if (unlikely (status)) + return status; - /* Compute extents.x/y/width/height from recording_surface, - * in font space. - */ - status = _cairo_recording_surface_get_bbox ((cairo_recording_surface_t *) recording_surface, - &bbox, - &scaled_font->extent_scale); - if (unlikely (status)) - return status; + _cairo_box_to_doubles (&bbox, &x1, &y1, &x2, &y2); - _cairo_box_to_doubles (&bbox, &x1, &y1, &x2, &y2); + x_scale = scaled_font->extent_x_scale; + y_scale = scaled_font->extent_y_scale; + extents.x_bearing = x1 * x_scale; + extents.y_bearing = y1 * y_scale; + extents.width = (x2 - x1) * x_scale; + extents.height = (y2 - y1) * y_scale; + } - x_scale = scaled_font->extent_x_scale; - y_scale = scaled_font->extent_y_scale; - extents.x_bearing = x1 * x_scale; - extents.y_bearing = y1 * y_scale; - extents.width = (x2 - x1) * x_scale; - extents.height = (y2 - y1) * y_scale; - } + if (scaled_font->base.options.hint_metrics != CAIRO_HINT_METRICS_OFF) { + extents.x_advance = _cairo_lround (extents.x_advance / scaled_font->snap_x_scale) * scaled_font->snap_x_scale; + extents.y_advance = _cairo_lround (extents.y_advance / scaled_font->snap_y_scale) * scaled_font->snap_y_scale; + } - if (scaled_font->base.options.hint_metrics != CAIRO_HINT_METRICS_OFF) { - extents.x_advance = _cairo_lround (extents.x_advance / scaled_font->snap_x_scale) * scaled_font->snap_x_scale; - extents.y_advance = _cairo_lround (extents.y_advance / scaled_font->snap_y_scale) * scaled_font->snap_y_scale; - } + _cairo_scaled_glyph_set_metrics (scaled_glyph, + &scaled_font->base, + &extents); - _cairo_scaled_glyph_set_metrics (scaled_glyph, - &scaled_font->base, - &extents); - } + return status; +} - if (info & CAIRO_SCALED_GLYPH_INFO_SURFACE) { - cairo_surface_t *surface; - cairo_format_t format; - int width, height; - - /* TODO - * extend the glyph cache to support argb glyphs. - * need to figure out the semantics and interaction with subpixel - * rendering first. - */ +static cairo_int_status_t +_cairo_user_scaled_glyph_init_surface (cairo_user_scaled_font_t *scaled_font, + cairo_scaled_glyph_t *scaled_glyph, + cairo_scaled_glyph_info_t info, + const cairo_color_t *foreground_color) +{ + cairo_surface_t *surface; + cairo_format_t format; + int width, height; + cairo_int_status_t status = CAIRO_STATUS_SUCCESS; + cairo_bool_t foreground_used; - width = _cairo_fixed_integer_ceil (scaled_glyph->bbox.p2.x) - - _cairo_fixed_integer_floor (scaled_glyph->bbox.p1.x); - height = _cairo_fixed_integer_ceil (scaled_glyph->bbox.p2.y) - - _cairo_fixed_integer_floor (scaled_glyph->bbox.p1.y); + /* TODO + * extend the glyph cache to support argb glyphs. + * need to figure out the semantics and interaction with subpixel + * rendering first. + */ - switch (scaled_font->base.options.antialias) { - default: - case CAIRO_ANTIALIAS_DEFAULT: - case CAIRO_ANTIALIAS_FAST: - case CAIRO_ANTIALIAS_GOOD: - case CAIRO_ANTIALIAS_GRAY: format = CAIRO_FORMAT_A8; break; - case CAIRO_ANTIALIAS_NONE: format = CAIRO_FORMAT_A1; break; - case CAIRO_ANTIALIAS_BEST: - case CAIRO_ANTIALIAS_SUBPIXEL: format = CAIRO_FORMAT_ARGB32; break; - } - surface = cairo_image_surface_create (format, width, height); + /* Only one info type at a time handled in this function */ + assert (info == CAIRO_SCALED_GLYPH_INFO_COLOR_SURFACE || info == CAIRO_SCALED_GLYPH_INFO_SURFACE); - cairo_surface_set_device_offset (surface, - - _cairo_fixed_integer_floor (scaled_glyph->bbox.p1.x), - - _cairo_fixed_integer_floor (scaled_glyph->bbox.p1.y)); - status = _cairo_recording_surface_replay (recording_surface, surface); + width = _cairo_fixed_integer_ceil (scaled_glyph->bbox.p2.x) - + _cairo_fixed_integer_floor (scaled_glyph->bbox.p1.x); + height = _cairo_fixed_integer_ceil (scaled_glyph->bbox.p2.y) - + _cairo_fixed_integer_floor (scaled_glyph->bbox.p1.y); - if (unlikely (status)) { - cairo_surface_destroy(surface); - return status; + if (info == CAIRO_SCALED_GLYPH_INFO_COLOR_SURFACE) { + format = CAIRO_FORMAT_ARGB32; + } else { + switch (scaled_font->base.options.antialias) { + default: + case CAIRO_ANTIALIAS_DEFAULT: + case CAIRO_ANTIALIAS_FAST: + case CAIRO_ANTIALIAS_GOOD: + case CAIRO_ANTIALIAS_GRAY: + format = CAIRO_FORMAT_A8; + break; + case CAIRO_ANTIALIAS_NONE: + format = CAIRO_FORMAT_A1; + break; + case CAIRO_ANTIALIAS_BEST: + case CAIRO_ANTIALIAS_SUBPIXEL: + format = CAIRO_FORMAT_ARGB32; + break; } + } + surface = cairo_image_surface_create (format, width, height); + + cairo_surface_set_device_offset (surface, + - _cairo_fixed_integer_floor (scaled_glyph->bbox.p1.x), + - _cairo_fixed_integer_floor (scaled_glyph->bbox.p1.y)); + + if (info == CAIRO_SCALED_GLYPH_INFO_COLOR_SURFACE) { + status = _cairo_recording_surface_replay_with_foreground_color (scaled_glyph->recording_surface, + surface, + foreground_color, + &foreground_used); + + } else { + status = _cairo_recording_surface_replay (scaled_glyph->recording_surface, surface); + foreground_used = FALSE; + } + if (unlikely (status)) { + cairo_surface_destroy(surface); + return status; + } + foreground_used = foreground_used || scaled_glyph->recording_uses_foreground_color; + + if (info == CAIRO_SCALED_GLYPH_INFO_COLOR_SURFACE) { + _cairo_scaled_glyph_set_color_surface (scaled_glyph, + &scaled_font->base, + (cairo_image_surface_t *)surface, + foreground_used ? foreground_color : NULL); + surface = NULL; + } else { _cairo_scaled_glyph_set_surface (scaled_glyph, &scaled_font->base, (cairo_image_surface_t *) surface); + surface = NULL; + } + + if (surface) + cairo_surface_destroy (surface); + + return status; +} + +static void +_cairo_user_scaled_glyph_fini (void *abstract_font) +{ + cairo_user_scaled_font_t *scaled_font = abstract_font; + + if (scaled_font->foreground_pattern) + cairo_pattern_destroy (scaled_font->foreground_pattern); + + if (scaled_font->foreground_marker) + cairo_pattern_destroy (scaled_font->foreground_marker); +} + +static cairo_int_status_t +_cairo_user_scaled_glyph_init (void *abstract_font, + cairo_scaled_glyph_t *scaled_glyph, + cairo_scaled_glyph_info_t info, + const cairo_color_t *foreground_color) +{ + cairo_int_status_t status = CAIRO_STATUS_SUCCESS; + cairo_user_scaled_font_t *scaled_font = abstract_font; + + if (!scaled_glyph->recording_surface || (info & CAIRO_SCALED_GLYPH_INFO_RECORDING_SURFACE)) { + status = _cairo_user_scaled_glyph_init_record_glyph (scaled_font, scaled_glyph, foreground_color); + if (status) + return status; + } + + if (info & CAIRO_SCALED_GLYPH_INFO_COLOR_SURFACE) { + if (!scaled_glyph->color_glyph ) + return CAIRO_INT_STATUS_UNSUPPORTED; + + status = _cairo_user_scaled_glyph_init_surface (scaled_font, + scaled_glyph, + CAIRO_SCALED_GLYPH_INFO_COLOR_SURFACE, + foreground_color); + if (status) + return status; + } + + if (info & CAIRO_SCALED_GLYPH_INFO_SURFACE) { + status = _cairo_user_scaled_glyph_init_surface (scaled_font, + scaled_glyph, + CAIRO_SCALED_GLYPH_INFO_SURFACE, + NULL); + if (status) + return status; } if (info & CAIRO_SCALED_GLYPH_INFO_PATH) { @@ -258,7 +416,7 @@ _cairo_user_scaled_glyph_init (void *abstract_font, if (!path) return _cairo_error (CAIRO_STATUS_NO_MEMORY); - status = _cairo_recording_surface_get_path (recording_surface, path); + status = _cairo_recording_surface_get_path (scaled_glyph->recording_surface, path); if (unlikely (status)) { _cairo_path_fixed_destroy (path); return status; @@ -303,6 +461,16 @@ not_implemented: return glyph; } +static cairo_bool_t +_cairo_user_has_color_glyphs (void *abstract_font) +{ + cairo_user_scaled_font_t *scaled_font = abstract_font; + cairo_user_font_face_t *face = + (cairo_user_font_face_t *) scaled_font->base.font_face; + + return face->has_color; +} + static cairo_int_status_t _cairo_user_text_to_glyphs (void *abstract_font, double x, @@ -377,13 +545,16 @@ _cairo_user_font_face_create_for_toy (cairo_toy_font_face_t *toy_face, static const cairo_scaled_font_backend_t _cairo_user_scaled_font_backend = { CAIRO_FONT_TYPE_USER, - NULL, /* scaled_font_fini */ + _cairo_user_scaled_glyph_fini, _cairo_user_scaled_glyph_init, _cairo_user_text_to_glyphs, _cairo_user_ucs4_to_index, - NULL, /* show_glyphs */ NULL, /* load_truetype_table */ - NULL /* index_to_ucs4 */ + NULL, /* index_to_ucs4 */ + NULL, /* is_synthetic */ + NULL, /* index_to_glyph_name */ + NULL, /* load_type1_data */ + _cairo_user_has_color_glyphs, }; /* #cairo_user_font_face_t */ @@ -416,6 +587,9 @@ _cairo_user_font_face_scaled_font_create (void *abstract_ return status; } + user_scaled_font->foreground_pattern = NULL; + user_scaled_font->foreground_marker = _cairo_pattern_create_foreground_marker (); + /* XXX metrics hinting? */ /* compute a normalized version of font scale matrix to compute @@ -424,6 +598,8 @@ _cairo_user_font_face_scaled_font_create (void *abstract_ { double fixed_scale, x_scale, y_scale; + user_scaled_font->snap_x_scale = 1.0; + user_scaled_font->snap_y_scale = 1.0; user_scaled_font->extent_scale = user_scaled_font->base.scale_inverse; status = _cairo_matrix_compute_basis_scale_factors (&user_scaled_font->extent_scale, &x_scale, &y_scale, @@ -462,8 +638,8 @@ _cairo_user_font_face_scaled_font_create (void *abstract_ cairo_surface_t *recording_surface; cairo_t *cr; - recording_surface = _cairo_user_scaled_font_create_recording_surface (user_scaled_font); - cr = _cairo_user_scaled_font_create_recording_context (user_scaled_font, recording_surface); + recording_surface = _cairo_user_scaled_font_create_recording_surface (user_scaled_font, FALSE, NULL); + cr = _cairo_user_scaled_font_create_recording_context (user_scaled_font, recording_surface, FALSE); cairo_surface_destroy (recording_surface); status = font_face->scaled_font_methods.init (&user_scaled_font->base, @@ -553,11 +729,11 @@ cairo_user_font_face_create (void) _cairo_font_face_init (&font_face->base, &_cairo_user_font_face_backend); font_face->immutable = FALSE; + font_face->has_color = FALSE; memset (&font_face->scaled_font_methods, 0, sizeof (font_face->scaled_font_methods)); return &font_face->base; } -slim_hidden_def(cairo_user_font_face_create); /* User-font method setters */ @@ -598,7 +774,56 @@ cairo_user_font_face_set_init_func (cairo_font_face_t *font_fac } user_font_face->scaled_font_methods.init = init_func; } -slim_hidden_def(cairo_user_font_face_set_init_func); + +/** + * cairo_user_font_face_set_render_color_glyph_func: + * @font_face: A user font face + * @render_glyph_func: The render_glyph callback, or %NULL + * + * Sets the color glyph rendering function of a user-font. + * See #cairo_user_scaled_font_render_glyph_func_t for details of how the callback + * works. + * + * The font-face should not be immutable or a %CAIRO_STATUS_USER_FONT_IMMUTABLE + * error will occur. A user font-face is immutable as soon as a scaled-font + * is created from it. + * + * The render_glyph callback is the only mandatory callback of a + * user-font. At least one of + * cairo_user_font_face_set_render_color_glyph_func() or + * cairo_user_font_face_set_render_glyph_func() must be called to set + * a render callback. If both callbacks are set, the color glyph + * render callback is invoked first. If the color glyph render + * callback returns %CAIRO_STATUS_USER_FONT_NOT_IMPLEMENTED, the + * non-color version of the callback is invoked. + * + * If the callback is %NULL and a glyph is tried to be rendered using + * @font_face, a %CAIRO_STATUS_USER_FONT_ERROR will occur. + * + * Since: 1.18 + **/ +void +cairo_user_font_face_set_render_color_glyph_func (cairo_font_face_t *font_face, + cairo_user_scaled_font_render_glyph_func_t render_glyph_func) +{ + cairo_user_font_face_t *user_font_face; + + if (font_face->status) + return; + + if (! _cairo_font_face_is_user (font_face)) { + if (_cairo_font_face_set_error (font_face, CAIRO_STATUS_FONT_TYPE_MISMATCH)) + return; + } + + user_font_face = (cairo_user_font_face_t *) font_face; + if (user_font_face->immutable) { + if (_cairo_font_face_set_error (font_face, CAIRO_STATUS_USER_FONT_IMMUTABLE)) + return; + } + user_font_face->scaled_font_methods.render_color_glyph = render_glyph_func; + user_font_face->has_color = render_glyph_func ? TRUE : FALSE; +} /** * cairo_user_font_face_set_render_glyph_func: @@ -613,7 +838,15 @@ slim_hidden_def(cairo_user_font_face_set_init_func); * error will occur. A user font-face is immutable as soon as a scaled-font * is created from it. * - * The render_glyph callback is the only mandatory callback of a user-font. + * The render_glyph callback is the only mandatory callback of a + * user-font. At least one of + * cairo_user_font_face_set_render_color_glyph_func() or + * cairo_user_font_face_set_render_glyph_func() must be called to set + * a render callback. If both callbacks are set, the color glyph + * render callback is invoked first. If the color glyph render + * callback returns %CAIRO_STATUS_USER_FONT_NOT_IMPLEMENTED, the + * non-color version of the callback is invoked. + * * If the callback is %NULL and a glyph is tried to be rendered using * @font_face, a %CAIRO_STATUS_USER_FONT_ERROR will occur. * @@ -640,7 +873,6 @@ cairo_user_font_face_set_render_glyph_func (cairo_font_face_t } user_font_face->scaled_font_methods.render_glyph = render_glyph_func; } -slim_hidden_def(cairo_user_font_face_set_render_glyph_func); /** * cairo_user_font_face_set_text_to_glyphs_func: @@ -714,7 +946,6 @@ cairo_user_font_face_set_unicode_to_glyph_func (cairo_font_face_t } user_font_face->scaled_font_methods.unicode_to_glyph = unicode_to_glyph_func; } -slim_hidden_def(cairo_user_font_face_set_unicode_to_glyph_func); /* User-font method getters */ @@ -747,6 +978,34 @@ cairo_user_font_face_get_init_func (cairo_font_face_t *font_face) } /** + * cairo_user_font_face_get_render_color_glyph_func: + * @font_face: A user font face + * + * Gets the color glyph rendering function of a user-font. + * + * Return value: The render_glyph callback of @font_face + * or %NULL if none set or an error has occurred. + * + * Since: 1.18 + **/ +cairo_user_scaled_font_render_glyph_func_t +cairo_user_font_face_get_render_color_glyph_func (cairo_font_face_t *font_face) +{ + cairo_user_font_face_t *user_font_face; + + if (font_face->status) + return NULL; + + if (! _cairo_font_face_is_user (font_face)) { + if (_cairo_font_face_set_error (font_face, CAIRO_STATUS_FONT_TYPE_MISMATCH)) + return NULL; + } + + user_font_face = (cairo_user_font_face_t *) font_face; + return user_font_face->scaled_font_methods.render_color_glyph; +} + +/** * cairo_user_font_face_get_render_glyph_func: * @font_face: A user font face * @@ -829,3 +1088,119 @@ cairo_user_font_face_get_unicode_to_glyph_func (cairo_font_face_t *font_face) user_font_face = (cairo_user_font_face_t *) font_face; return user_font_face->scaled_font_methods.unicode_to_glyph; } + +/** + * cairo_user_scaled_font_get_foreground_marker: + * @scaled_font: A user scaled font + * + * Gets the foreground pattern of the glyph currently being + * rendered. A #cairo_user_scaled_font_render_glyph_func_t function + * that has been set with + * cairo_user_font_face_set_render_color_glyph_func() may call this + * function to retrieve the current foreground pattern for the glyph + * being rendered. The function should not be called outside of a + * cairo_user_font_face_set_render_color_glyph_func() callback. + * + * The foreground marker pattern contains an internal marker to + * indicate that it is to be substituted with the current source when + * rendered to a surface. Querying the foreground marker will reveal a + * solid black color, however this is not representative of the color + * that will actually be used. Similarly, setting a solid black color + * will render black, not the foreground pattern when the glyph is + * painted to a surface. Using the foreground marker as the source + * instead of cairo_user_scaled_font_get_foreground_source() in a + * color render callback has the following benefits: + * + * 1. Cairo only needs to call the render callback once as it can + * cache the recording. Cairo will substitute the actual foreground + * color when rendering the recording. + * + * 2. On backends that have the concept of a foreground color in fonts such as + * PDF, PostScript, and SVG, cairo can generate more optimal + * output. The glyph can be included in an embedded font. + * + * The one drawback of the using foreground marker is the render + * callback can not access the color components of the pattern as the + * actual foreground pattern is not available at the time the render + * callback is invoked. If the render callback needs to query the + * foreground pattern, use + * cairo_user_scaled_font_get_foreground_source(). + * + * If the render callback simply wants to call cairo_set_source() with + * the foreground pattern, + * cairo_user_scaled_font_get_foreground_marker() is the preferred + * function to use as it results in better performance than + * cairo_user_scaled_font_get_foreground_source(). + * + * Return value: the current foreground source marker pattern. This + * object is owned by cairo. This object must not be modified or used + * outside of a color render callback. To keep a reference to it, + * you must call cairo_pattern_reference(). + * + * Since: 1.18 + **/ +cairo_pattern_t * +cairo_user_scaled_font_get_foreground_marker (cairo_scaled_font_t *scaled_font) +{ + cairo_user_scaled_font_t *user_scaled_font; + + if (scaled_font->backend != &_cairo_user_scaled_font_backend) + return _cairo_pattern_create_in_error (CAIRO_STATUS_FONT_TYPE_MISMATCH); + + user_scaled_font = (cairo_user_scaled_font_t *)scaled_font; + return user_scaled_font->foreground_marker; +} + +/** + * cairo_user_scaled_font_get_foreground_source: + * @scaled_font: A user scaled font + * + * Gets the foreground pattern of the glyph currently being + * rendered. A #cairo_user_scaled_font_render_glyph_func_t function + * that has been set with + * cairo_user_font_face_set_render_color_glyph_func() may call this + * function to retrieve the current foreground pattern for the glyph + * being rendered. The function should not be called outside of a + * cairo_user_font_face_set_render_color_glyph_func() callback. + * + * This function returns the current source at the time the glyph is + * rendered. Compared with + * cairo_user_scaled_font_get_foreground_marker(), this function + * returns the actual source pattern that will be used to render the + * glyph. The render callback is free to query the pattern and + * extract color components or other pattern data. For example if the + * render callback wants to create a gradient stop based on colors in + * the foreground source pattern, it will need to use this function in + * order to be able to query the colors in the foreground pattern. + * + * While this function does not have the restrictions on using the + * pattern that cairo_user_scaled_font_get_foreground_marker() has, it + * does incur a performance penalty. If a render callback calls this + * function: + * + * 1. Cairo will call the render callback whenever the current pattern + * of the context in which the glyph is rendered changes. + * + * 2. On backends that support font embedding (PDF, PostScript, and + * SVG), cairo can not embed this glyph in a font. Instead the glyph + * will be emitted as an image or sequence of drawing operations each + * time it is used. + * + * Return value: the current foreground source pattern. This object is + * owned by cairo. To keep a reference to it, you must call + * cairo_pattern_reference(). + * + * Since: 1.18 + **/ +cairo_pattern_t * +cairo_user_scaled_font_get_foreground_source (cairo_scaled_font_t *scaled_font) +{ + cairo_user_scaled_font_t *user_scaled_font; + + if (scaled_font->backend != &_cairo_user_scaled_font_backend) + return _cairo_pattern_create_in_error (CAIRO_STATUS_FONT_TYPE_MISMATCH); + + user_scaled_font = (cairo_user_scaled_font_t *)scaled_font; + user_scaled_font->foreground_colors_used = TRUE; + return user_scaled_font->foreground_pattern; +} diff --git a/gfx/cairo/cairo/src/cairo-version.c b/gfx/cairo/cairo/src/cairo-version.c index 943e1cde02..0b0d2123c3 100644 --- a/gfx/cairo/cairo/src/cairo-version.c +++ b/gfx/cairo/cairo/src/cairo-version.c @@ -252,4 +252,3 @@ cairo_version_string (void) { return CAIRO_VERSION_STRING; } -slim_hidden_def (cairo_version_string); diff --git a/gfx/cairo/cairo/src/cairo-version.h b/gfx/cairo/cairo/src/cairo-version.h index 9fd69fb45e..1a7b569775 100644 --- a/gfx/cairo/cairo/src/cairo-version.h +++ b/gfx/cairo/cairo/src/cairo-version.h @@ -2,7 +2,7 @@ #define CAIRO_VERSION_H #define CAIRO_VERSION_MAJOR 1 -#define CAIRO_VERSION_MINOR 17 -#define CAIRO_VERSION_MICRO 4 +#define CAIRO_VERSION_MINOR 18 +#define CAIRO_VERSION_MICRO 0 #endif diff --git a/gfx/cairo/cairo/src/cairo-vg-surface.c b/gfx/cairo/cairo/src/cairo-vg-surface.c deleted file mode 100644 index cbff748fe6..0000000000 --- a/gfx/cairo/cairo/src/cairo-vg-surface.c +++ /dev/null @@ -1,1854 +0,0 @@ -/* -*- Mode: c; tab-width: 8; c-basic-offset: 4; indent-tabs-mode: t; -*- */ -/* cairo - a vector graphics library with display and print output - * - * Copyright © 2008 Opened Hand Ltd. - * Copyright © 2009 Chris Wilson - * - * 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., 51 Franklin Street, Suite 500, Boston, MA 02110-1335, 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.og/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. - * - * Contributor(s): - * Pierre Tardy <tardyp@gmail.com> - * Øyvind Kolås <pippin@gimp.org> - * Vladimi Vukicevic <vladimir@mozilla.com> (stubbed out base backend) - * Chris Wilson <chris@chris-wilson.co.uk> - */ - -#include "cairoint.h" - -#include "cairo-vg.h" - -#include "cairo-cache-private.h" -#include "cairo-default-context-private.h" -#include "cairo-error-private.h" -#include "cairo-image-surface-private.h" -#include "cairo-path-fixed-private.h" -#include "cairo-recording-surface-inline.h" -#include "cairo-surface-clipper-private.h" - -#include <pixman.h> -#include <VG/openvg.h> - -//#define OPENVG_DEBUG - -/* - * Work that needs to be done: - * - Glyph cache / proper font support - * - * - First-class paths - * Paths are expensive for OpenVG, reuse paths whenever possible. - * So add a path cache, and first class paths! - */ - -typedef struct _cairo_vg_surface cairo_vg_surface_t; - -/* XXX need GL specific context control. :( */ -struct _cairo_vg_context { - cairo_status_t status; - cairo_reference_count_t ref_count; - - unsigned long target_id; - - VGPaint paint; - cairo_vg_surface_t *source; - double alpha; - - cairo_cache_t snapshot_cache; - - void *display; - void *context; - - cairo_status_t (*create_target) (cairo_vg_context_t *, - cairo_vg_surface_t *); - cairo_status_t (*set_target) (cairo_vg_context_t *, - cairo_vg_surface_t *); - void (*destroy_target) (cairo_vg_context_t *, cairo_vg_surface_t *); -}; - -struct _cairo_vg_surface { - cairo_surface_t base; - - cairo_vg_context_t *context; - - VGImage image; - VGImageFormat format; - int width; - int height; - cairo_bool_t own_image; - - cairo_cache_entry_t snapshot_cache_entry; - - cairo_surface_clipper_t clipper; - - unsigned long target_id; -}; - -static const cairo_surface_backend_t cairo_vg_surface_backend; - -slim_hidden_proto (cairo_vg_surface_create); - -static cairo_surface_t * -_vg_surface_create_internal (cairo_vg_context_t *context, - VGImage image, - VGImageFormat format, - int width, int height); - -static cairo_vg_context_t * -_vg_context_reference (cairo_vg_context_t *context) -{ - assert (CAIRO_REFERENCE_COUNT_HAS_REFERENCE (&context->ref_count)); - - _cairo_reference_count_inc (&context->ref_count); - - return context; -} - -static cairo_vg_context_t * -_vg_context_lock (cairo_vg_context_t *context) -{ - /* XXX if we need to add locking, then it has to be recursive */ - return context; -} - -static cairo_int_status_t -_vg_context_set_target (cairo_vg_context_t *context, - cairo_vg_surface_t *surface) -{ - cairo_status_t status; - - if (surface->target_id == 0) { - status = context->create_target (context, surface); - if (unlikely (status)) - return status; - } - - if (context->target_id == surface->target_id) - return CAIRO_STATUS_SUCCESS; - - context->target_id = surface->target_id; - - return context->set_target (context, surface); -} - -static void -_vg_context_destroy_target (cairo_vg_context_t *context, - cairo_vg_surface_t *surface) -{ - if (surface->target_id == 0) - return; - - if (context->target_id == surface->target_id) - context->set_target (context, NULL); - - context->destroy_target (context, surface); -} - -static cairo_bool_t -_vg_snapshot_cache_can_remove (const void *entry) -{ - return TRUE; -} - -static void -_vg_snapshot_cache_remove (void *cache_entry) -{ - cairo_vg_surface_t *surface = cairo_container_of (cache_entry, - cairo_vg_surface_t, - snapshot_cache_entry); - surface->snapshot_cache_entry.hash = 0; - cairo_surface_destroy (&surface->base); -} - -static cairo_status_t -_vg_context_init (cairo_vg_context_t *context) -{ - cairo_status_t status; - - context->status = CAIRO_STATUS_SUCCESS; - CAIRO_REFERENCE_COUNT_INIT (&context->ref_count, 1); - - status = _cairo_cache_init (&context->snapshot_cache, - NULL, - _vg_snapshot_cache_can_remove, - _vg_snapshot_cache_remove, - 16*1024*1024); - if (unlikely (status)) - return status; - - context->target_id = 0; - context->source = NULL; - context->alpha = 1.0; - - context->paint = vgCreatePaint (); - vgLoadIdentity (); - - return CAIRO_STATUS_SUCCESS; -} - -static void -_vg_context_destroy (cairo_vg_context_t *context) -{ - assert (CAIRO_REFERENCE_COUNT_HAS_REFERENCE (&context->ref_count)); - - if (! _cairo_reference_count_dec_and_test (&context->ref_count)) - return; - - if (context->paint != VG_INVALID_HANDLE) - vgDestroyPaint (context->paint); - - _cairo_cache_fini (&context->snapshot_cache); - free (context); -} - -static void -_vg_context_unlock (cairo_vg_context_t *context) -{ -} - -#ifdef OPENVG_DEBUG -static void check_vg_errors(const char*function,int line) -{ - int err = vgGetError(); - if (err != VG_NO_ERROR){ - printf("%s+%d:vgError detected: 0x%08x.\n",function, line,err); - assert(err == VG_NO_ERROR); - } - -} -#define CHECK_VG_ERRORS() check_vg_errors(__FILE__,__LINE__) -#else -#define CHECK_VG_ERRORS() do{}while(0) -#endif //OPENVG_DEBUG - -static pixman_format_code_t -_vg_format_to_pixman (VGImageFormat format, - cairo_bool_t *needs_premult_fixup) -{ - *needs_premult_fixup = FALSE; - switch (format) { - /* RGB{A,X} channel ordering */ - case VG_sRGBX_8888: return PIXMAN_r8g8b8x8; - case VG_sRGBA_8888: *needs_premult_fixup = TRUE; return PIXMAN_r8g8b8a8; - case VG_sRGBA_8888_PRE: return PIXMAN_r8g8b8a8; - case VG_sRGB_565: return PIXMAN_r5g6b5; - case VG_sRGBA_5551: return 0; - case VG_sRGBA_4444: return 0; - case VG_sL_8: return PIXMAN_g8; - case VG_lRGBX_8888: return 0; - case VG_lRGBA_8888: return 0; - case VG_lRGBA_8888_PRE: return 0; - case VG_lL_8: return 0; - case VG_A_8: return PIXMAN_a8; - case VG_BW_1: return PIXMAN_a1; - case VG_A_1: return PIXMAN_a1; - case VG_A_4: return PIXMAN_a4; - - /* {A,X}RGB channel ordering */ - case VG_sXRGB_8888: return PIXMAN_x8r8g8b8; - case VG_sARGB_8888: *needs_premult_fixup = TRUE; return PIXMAN_a8r8g8b8; - case VG_sARGB_8888_PRE: return PIXMAN_a8r8g8b8; - case VG_sARGB_1555: return 0; - case VG_sARGB_4444: return 0; - case VG_lXRGB_8888: return 0; - case VG_lARGB_8888: return 0; - case VG_lARGB_8888_PRE: return 0; - - /* BGR{A,X} channel ordering */ - case VG_sBGRX_8888: return PIXMAN_b8g8r8x8; - case VG_sBGRA_8888: *needs_premult_fixup = TRUE; return PIXMAN_b8g8r8a8; - case VG_sBGRA_8888_PRE: return PIXMAN_b8g8r8a8; - case VG_sBGR_565: return PIXMAN_b5g6r5; - case VG_sBGRA_5551: return 0; - case VG_sBGRA_4444: return 0; - case VG_lBGRX_8888: return 0; - case VG_lBGRA_8888: return 0; - case VG_lBGRA_8888_PRE: return 0; - - /* {A,X}BGR channel ordering */ - case VG_sXBGR_8888: return PIXMAN_x8b8g8r8; - case VG_sABGR_8888: *needs_premult_fixup = TRUE; return PIXMAN_a8b8g8r8; - case VG_sABGR_8888_PRE: return PIXMAN_a8b8g8r8; - case VG_sABGR_1555: return 0; - case VG_sABGR_4444: return 0; - case VG_lXBGR_8888: return 0; - case VG_lABGR_8888: return 0; - case VG_lABGR_8888_PRE: return 0; - default: return 0; - } -} - -static pixman_format_code_t -_vg_format_to_content (VGImageFormat format) -{ - /* XXX could use more simple bit tests */ - switch (format) { - /* RGB{A,X} channel ordering */ - case VG_sRGBX_8888: return CAIRO_CONTENT_COLOR; - case VG_sRGBA_8888: return CAIRO_CONTENT_COLOR_ALPHA; - case VG_sRGBA_8888_PRE: return CAIRO_CONTENT_COLOR_ALPHA; - case VG_sRGB_565: return CAIRO_CONTENT_COLOR; - case VG_sRGBA_5551: return CAIRO_CONTENT_COLOR_ALPHA; - case VG_sRGBA_4444: return CAIRO_CONTENT_COLOR_ALPHA; - case VG_sL_8: return CAIRO_CONTENT_ALPHA; - case VG_lRGBX_8888: return CAIRO_CONTENT_COLOR; - case VG_lRGBA_8888: return CAIRO_CONTENT_COLOR_ALPHA; - case VG_lRGBA_8888_PRE: return CAIRO_CONTENT_COLOR_ALPHA; - case VG_lL_8: return CAIRO_CONTENT_ALPHA; - case VG_A_8: return CAIRO_CONTENT_ALPHA; - case VG_A_4: return CAIRO_CONTENT_ALPHA; - case VG_A_1: return CAIRO_CONTENT_ALPHA; - case VG_BW_1: return CAIRO_CONTENT_ALPHA; - - /* {A,X}RGB channel ordering */ - case VG_sXRGB_8888: return CAIRO_CONTENT_COLOR; - case VG_sARGB_8888: return CAIRO_CONTENT_COLOR_ALPHA; - case VG_sARGB_8888_PRE: return CAIRO_CONTENT_COLOR_ALPHA; - case VG_sARGB_1555: return CAIRO_CONTENT_COLOR_ALPHA; - case VG_sARGB_4444: return CAIRO_CONTENT_COLOR_ALPHA; - case VG_lXRGB_8888: return CAIRO_CONTENT_COLOR; - case VG_lARGB_8888: return CAIRO_CONTENT_COLOR_ALPHA; - case VG_lARGB_8888_PRE: return CAIRO_CONTENT_COLOR_ALPHA; - - /* BGR{A,X} channel ordering */ - case VG_sBGRX_8888: return CAIRO_CONTENT_COLOR; - case VG_sBGRA_8888: return CAIRO_CONTENT_COLOR_ALPHA; - case VG_sBGRA_8888_PRE: return CAIRO_CONTENT_COLOR_ALPHA; - case VG_sBGR_565: return CAIRO_CONTENT_COLOR; - case VG_sBGRA_5551: return CAIRO_CONTENT_COLOR_ALPHA; - case VG_sBGRA_4444: return CAIRO_CONTENT_COLOR_ALPHA; - case VG_lBGRX_8888: return CAIRO_CONTENT_COLOR; - case VG_lBGRA_8888: return CAIRO_CONTENT_COLOR_ALPHA; - case VG_lBGRA_8888_PRE: return CAIRO_CONTENT_COLOR_ALPHA; - - /* {A,X}BGR channel ordering */ - case VG_sXBGR_8888: return CAIRO_CONTENT_COLOR; - case VG_sABGR_8888: return CAIRO_CONTENT_COLOR_ALPHA; - case VG_sABGR_8888_PRE: return CAIRO_CONTENT_COLOR_ALPHA; - case VG_sABGR_1555: return CAIRO_CONTENT_COLOR_ALPHA; - case VG_sABGR_4444: return CAIRO_CONTENT_COLOR_ALPHA; - case VG_lXBGR_8888: return CAIRO_CONTENT_COLOR; - case VG_lABGR_8888: return CAIRO_CONTENT_COLOR_ALPHA; - case VG_lABGR_8888_PRE: return CAIRO_CONTENT_COLOR_ALPHA; - default: return 0; - } -} - -static VGImageFormat -_vg_format_from_pixman (pixman_format_code_t format) -{ - /* XXX _PRE needs fixup */ - switch ((int) format) { - case PIXMAN_r5g6b5: return VG_sRGB_565; - case PIXMAN_g8: return VG_sL_8; - case PIXMAN_a8: return VG_A_8; - case PIXMAN_a1: return VG_BW_1; - case PIXMAN_x8r8g8b8: return VG_sXRGB_8888; - case PIXMAN_a8r8g8b8: return VG_sARGB_8888; // _PRE - case PIXMAN_b8g8r8x8: return VG_sBGRX_8888; - case PIXMAN_b8g8r8a8: return VG_sBGRA_8888; // _PRE - case PIXMAN_b5g6r5: return VG_sBGR_565; - case PIXMAN_x8b8g8r8: return VG_sXBGR_8888; - case PIXMAN_a8b8g8r8: return VG_sABGR_8888; // _PRE - default: return 0; - } -} - -static VGImageFormat -_vg_format_for_content (cairo_content_t content) -{ - switch (content) { - case CAIRO_CONTENT_ALPHA: return VG_A_8; - case CAIRO_CONTENT_COLOR: return VG_sXRGB_8888; - default: ASSERT_NOT_REACHED; - case CAIRO_CONTENT_COLOR_ALPHA: return VG_sARGB_8888; // _PRE - } -} - -static cairo_surface_t * -_vg_surface_create_similar (void *abstract_surface, - cairo_content_t content, - int width, - int height) -{ - cairo_vg_surface_t *surface = abstract_surface; - - if (width > vgGeti (VG_MAX_IMAGE_WIDTH) || - height > vgGeti (VG_MAX_IMAGE_HEIGHT)) - { - return NULL; - } - - return cairo_vg_surface_create (surface->context, content, width, height); -} - -static cairo_status_t -_vg_surface_clipper_intersect_clip_path (cairo_surface_clipper_t *clipper, - cairo_path_fixed_t *path, - cairo_fill_rule_t fill_rule, - double tolerance, - cairo_antialias_t antialias) -{ - cairo_vg_surface_t *surface = cairo_container_of (clipper, - cairo_vg_surface_t, - clipper); - cairo_vg_surface_t *mask; - cairo_status_t status; - - if (path == NULL) { - vgMask (VG_INVALID_HANDLE, - VG_FILL_MASK, 0, 0, surface->width, surface->height); - vgSeti (VG_MASKING, VG_FALSE); - CHECK_VG_ERRORS(); - return CAIRO_STATUS_SUCCESS; - } - - mask = (cairo_vg_surface_t *) - _vg_surface_create_similar (surface, CAIRO_CONTENT_ALPHA, - surface->width, surface->height); - if (unlikely (mask == NULL)) - return CAIRO_INT_STATUS_UNSUPPORTED; - if (unlikely (mask->base.status)) - return mask->base.status; - - status = _cairo_surface_fill (&mask->base, - CAIRO_OPERATOR_SOURCE, - &_cairo_pattern_white.base, - path, fill_rule, tolerance, antialias, - NULL); - if (status) { - cairo_surface_destroy (&mask->base); - return status; - } - - vgSeti (VG_MASKING, VG_TRUE); - vgMask (mask->image, VG_INTERSECT_MASK, 0, 0, mask->width, mask->height); - - cairo_surface_destroy (&mask->base); - - CHECK_VG_ERRORS(); - return CAIRO_STATUS_SUCCESS; -} - -static cairo_bool_t -_vg_surface_get_extents (void *abstract_surface, - cairo_rectangle_int_t *extents) -{ - cairo_vg_surface_t *surface = abstract_surface; - - extents->x = 0; - extents->y = 0; - extents->width = surface->width; - extents->height = surface->height; - - return TRUE; -} - -#define MAX_SEG 16 /* max number of knots to upload in a batch */ - -typedef struct _vg_path { - VGPath path; - const cairo_matrix_t *ctm_inverse; - - VGubyte gseg[MAX_SEG]; - VGfloat gdata[MAX_SEG*3*2]; - int dcount; - int scount; -} vg_path_t; - -static cairo_status_t -_vg_move_to (void *closure, - const cairo_point_t *point) -{ - vg_path_t *path = closure; - double x = _cairo_fixed_to_double (point->x); - double y = _cairo_fixed_to_double (point->y); - - if (path->ctm_inverse) - cairo_matrix_transform_point (path->ctm_inverse, &x, &y); - - path->gseg[path->scount++] = VG_MOVE_TO; - path->gdata[path->dcount++] = x; - path->gdata[path->dcount++] = y; - - if (path->scount >= MAX_SEG-1) { - vgAppendPathData (path->path, path->scount, path->gseg, path->gdata); - path->scount = 0; - path->dcount = 0; - } - - CHECK_VG_ERRORS(); - return CAIRO_STATUS_SUCCESS; -} - -static cairo_status_t -_vg_line_to (void *closure, - const cairo_point_t *point) -{ - vg_path_t *path = closure; - double x = _cairo_fixed_to_double (point->x); - double y = _cairo_fixed_to_double (point->y); - - if (path->ctm_inverse) - cairo_matrix_transform_point (path->ctm_inverse, &x, &y); - - path->gseg[path->scount++] = VG_LINE_TO; - path->gdata[path->dcount++] = x; - path->gdata[path->dcount++] = y; - - if (path->scount >= MAX_SEG-1) { - vgAppendPathData (path->path, path->scount, path->gseg, path->gdata); - path->scount = 0; - path->dcount = 0; - } - - CHECK_VG_ERRORS(); - return CAIRO_STATUS_SUCCESS; -} - -static cairo_status_t -_vg_curve_to (void *closure, - const cairo_point_t *p0, - const cairo_point_t *p1, - const cairo_point_t *p2) -{ - vg_path_t *path = closure; - double x0 = _cairo_fixed_to_double (p0->x); - double y0 = _cairo_fixed_to_double (p0->y); - double x1 = _cairo_fixed_to_double (p1->x); - double y1 = _cairo_fixed_to_double (p1->y); - double x2 = _cairo_fixed_to_double (p2->x); - double y2 = _cairo_fixed_to_double (p2->y); - - if (path->ctm_inverse) { - cairo_matrix_transform_point (path->ctm_inverse, &x0, &y0); - cairo_matrix_transform_point (path->ctm_inverse, &x1, &y1); - cairo_matrix_transform_point (path->ctm_inverse, &x2, &y2); - } - - path->gseg[path->scount++] = VG_CUBIC_TO; - path->gdata[path->dcount++] = x0; - path->gdata[path->dcount++] = y0; - path->gdata[path->dcount++] = x1; - path->gdata[path->dcount++] = y1; - path->gdata[path->dcount++] = x2; - path->gdata[path->dcount++] = y2; - - if (path->scount >= MAX_SEG-1) { - vgAppendPathData(path->path, path->scount, path->gseg, path->gdata); - path->scount = 0; - path->dcount = 0; - } - - CHECK_VG_ERRORS(); - return CAIRO_STATUS_SUCCESS; -} - -static cairo_status_t -_vg_close_path (void *closure) -{ - vg_path_t *path = closure; - - path->gseg[path->scount++] = VG_CLOSE_PATH; - - if (path->scount >= MAX_SEG-1) { - vgAppendPathData (path->path, path->scount, path->gseg, path->gdata); - path->scount = 0; - path->dcount = 0; - } - - CHECK_VG_ERRORS(); - return CAIRO_STATUS_SUCCESS; -} - -static void -_vg_path_from_cairo (vg_path_t *vg_path, - const cairo_path_fixed_t *path) -{ - cairo_status_t status; - - vg_path->scount = 0; - vg_path->dcount = 0; - - status = _cairo_path_fixed_interpret (path, - _vg_move_to, - _vg_line_to, - _vg_curve_to, - _vg_close_path, - vg_path); - assert (status == CAIRO_STATUS_SUCCESS); - - vgAppendPathData (vg_path->path, - vg_path->scount, vg_path->gseg, vg_path->gdata); - CHECK_VG_ERRORS(); -} - -static cairo_bool_t -_vg_is_supported_operator (cairo_operator_t op) -{ - switch ((int) op) { - case CAIRO_OPERATOR_SOURCE: - case CAIRO_OPERATOR_OVER: - case CAIRO_OPERATOR_IN: - case CAIRO_OPERATOR_DEST_OVER: - case CAIRO_OPERATOR_DEST_IN: - case CAIRO_OPERATOR_ADD: - return TRUE; - - default: - return FALSE; - } -} - -static VGBlendMode -_vg_operator (cairo_operator_t op) -{ - switch ((int) op) { - case CAIRO_OPERATOR_SOURCE: - return VG_BLEND_SRC; - case CAIRO_OPERATOR_OVER: - return VG_BLEND_SRC_OVER; - case CAIRO_OPERATOR_IN: - return VG_BLEND_SRC_IN; - case CAIRO_OPERATOR_DEST_OVER: - return VG_BLEND_DST_OVER; - case CAIRO_OPERATOR_DEST_IN: - return VG_BLEND_DST_IN; - case CAIRO_OPERATOR_ADD: - return VG_BLEND_ADDITIVE; - default: - ASSERT_NOT_REACHED; - return VG_BLEND_SRC_OVER; - } -} - -static VGFillRule -_vg_fill_rule_from_cairo (cairo_fill_rule_t rule) -{ - switch (rule) { - case CAIRO_FILL_RULE_EVEN_ODD: return VG_EVEN_ODD; - case CAIRO_FILL_RULE_WINDING: return VG_NON_ZERO; - } - - ASSERT_NOT_REACHED; - return VG_NON_ZERO; -} - -static VGRenderingQuality -_vg_rendering_quality_from_cairo (cairo_antialias_t aa) -{ - switch (aa) { - case CAIRO_ANTIALIAS_DEFAULT: - case CAIRO_ANTIALIAS_SUBPIXEL: - case CAIRO_ANTIALIAS_GOOD: - case CAIRO_ANTIALIAS_BEST: - return VG_RENDERING_QUALITY_BETTER; - - case CAIRO_ANTIALIAS_GRAY: - case CAIRO_ANTIALIAS_FAST: - return VG_RENDERING_QUALITY_FASTER; - - case CAIRO_ANTIALIAS_NONE: - return VG_RENDERING_QUALITY_NONANTIALIASED; - } - - ASSERT_NOT_REACHED; - return VG_RENDERING_QUALITY_BETTER; -} - -static VGCapStyle -_vg_line_cap_from_cairo (cairo_line_cap_t cap) -{ - switch (cap) { - case CAIRO_LINE_CAP_BUTT: return VG_CAP_BUTT; - case CAIRO_LINE_CAP_ROUND: return VG_CAP_ROUND; - case CAIRO_LINE_CAP_SQUARE: return VG_CAP_SQUARE; - } - - ASSERT_NOT_REACHED; - return VG_CAP_BUTT; -} - -static VGJoinStyle -_vg_line_join_from_cairo (cairo_line_join_t join) -{ - switch (join) { - case CAIRO_LINE_JOIN_MITER: return VG_JOIN_MITER; - case CAIRO_LINE_JOIN_ROUND: return VG_JOIN_ROUND; - case CAIRO_LINE_JOIN_BEVEL: return VG_JOIN_BEVEL; - } - - ASSERT_NOT_REACHED; - return VG_JOIN_MITER; -} - -static void -_vg_matrix_from_cairo (VGfloat *dst, const cairo_matrix_t *src) -{ - dst[0] = /* sx */ src->xx; - dst[1] = /* shy */ src->yx; - dst[2] = /* w0 */ 0; - dst[3] = /* shx */ src->xy; - dst[4] = /* sy */ src->yy; - dst[5] = /* w1 */ 0; - dst[6] = /* tx */ src->x0; - dst[7] = /* ty */ src->y0; - dst[8] = /* w2 */ 0; -} - -static cairo_status_t -_vg_setup_gradient_stops (cairo_vg_context_t *context, - const cairo_gradient_pattern_t *pattern) -{ - VGint numstops = pattern->n_stops; - VGfloat *stops, stack_stops[CAIRO_STACK_ARRAY_LENGTH (VGfloat)]; - int i; - - if (numstops*5 < ARRAY_LENGTH (stack_stops)) { - stops = stack_stops; - } else { - stops = _cairo_malloc_ab (numstops, 5*sizeof (VGfloat)); - if (unlikely (stops == NULL)) - return _cairo_error (CAIRO_STATUS_NO_MEMORY); - } - - for (i = 0; i < numstops; i++) { - stops[i*5 + 0] = pattern->stops[i].offset; - stops[i*5 + 1] = pattern->stops[i].color.red; - stops[i*5 + 2] = pattern->stops[i].color.green; - stops[i*5 + 3] = pattern->stops[i].color.blue; - stops[i*5 + 4] = pattern->stops[i].color.alpha * context->alpha; - } - - vgSetParameterfv (context->paint, - VG_PAINT_COLOR_RAMP_STOPS, numstops * 5, stops); - - if (stops != stack_stops) - free (stops); - - CHECK_VG_ERRORS(); - return CAIRO_STATUS_SUCCESS; -} - -static void -_vg_set_source_matrix (const cairo_pattern_t *pat) -{ - cairo_matrix_t mat; - cairo_status_t status; - VGfloat vmat[9]; - - mat = pat->matrix; - status = cairo_matrix_invert (&mat); - assert (status == CAIRO_STATUS_SUCCESS); - - _vg_matrix_from_cairo (vmat, &mat); - - vgSeti (VG_MATRIX_MODE, VG_MATRIX_FILL_PAINT_TO_USER); - vgLoadMatrix (vmat); - vgSeti (VG_MATRIX_MODE, VG_MATRIX_STROKE_PAINT_TO_USER); - vgLoadMatrix (vmat); - vgSeti (VG_MATRIX_MODE, VG_MATRIX_PATH_USER_TO_SURFACE); - - CHECK_VG_ERRORS(); -} - -static cairo_status_t -_vg_setup_linear_source (cairo_vg_context_t *context, - const cairo_linear_pattern_t *lpat) -{ - VGfloat linear[4]; - - linear[0] = lpat->pd1.x; - linear[1] = lpat->pd1.y; - linear[2] = lpat->pd2.x; - linear[3] = lpat->pd2.y; - - vgSetParameteri (context->paint, - VG_PAINT_COLOR_RAMP_SPREAD_MODE, - VG_COLOR_RAMP_SPREAD_PAD); - vgSetParameteri (context->paint, - VG_PAINT_TYPE, - VG_PAINT_TYPE_LINEAR_GRADIENT); - vgSetParameterfv (context->paint, - VG_PAINT_LINEAR_GRADIENT, 4, linear); - - _vg_set_source_matrix (&lpat->base.base); - - CHECK_VG_ERRORS(); - return _vg_setup_gradient_stops (context, &lpat->base); - -} - -static cairo_status_t -_vg_setup_radial_source (cairo_vg_context_t *context, - const cairo_radial_pattern_t *rpat) -{ - VGfloat radial[5]; - - radial[0] = rpat->cd1.center.x; - radial[1] = rpat->cd1.center.y; - radial[2] = rpat->cd2.center.x; - radial[3] = rpat->cd2.center.y; - radial[4] = rpat->cd2.radius; - - vgSetParameteri (context->paint, - VG_PAINT_COLOR_RAMP_SPREAD_MODE, VG_COLOR_RAMP_SPREAD_PAD); - vgSetParameteri (context->paint, - VG_PAINT_TYPE, VG_PAINT_TYPE_RADIAL_GRADIENT); - vgSetParameterfv (context->paint, - VG_PAINT_RADIAL_GRADIENT, 5, radial); - - _vg_set_source_matrix (&rpat->base.base); - - /* FIXME: copy/adapt fixes from SVG backend to add inner radius */ - - CHECK_VG_ERRORS(); - return _vg_setup_gradient_stops (context, &rpat->base); -} - -static cairo_status_t -_vg_setup_solid_source (cairo_vg_context_t *context, - const cairo_solid_pattern_t *spat) -{ - VGfloat color[] = { - spat->color.red, - spat->color.green, - spat->color.blue, - spat->color.alpha * context->alpha - }; - - vgSetParameteri (context->paint, VG_PAINT_TYPE, VG_PAINT_TYPE_COLOR); - vgSetParameterfv (context->paint, VG_PAINT_COLOR, 4, color); - - CHECK_VG_ERRORS(); - return CAIRO_STATUS_SUCCESS; -} - -static cairo_vg_surface_t * -_vg_clone_recording_surface (cairo_vg_context_t *context, - cairo_surface_t *surface) -{ - VGImage vg_image; - VGImageFormat format; - cairo_status_t status; - cairo_rectangle_int_t extents; - cairo_vg_surface_t *clone; - - status = _cairo_surface_get_extents (surface, &extents); - if (status) - return NULL; - - if (extents.width > vgGeti (VG_MAX_IMAGE_WIDTH) || - extents.height > vgGeti (VG_MAX_IMAGE_HEIGHT)) - { - return NULL; - } - - format = _vg_format_for_content (surface->content); - - /* NONALIASED, FASTER, BETTER */ - vg_image = vgCreateImage (format, - extents.width, extents.height, - VG_IMAGE_QUALITY_FASTER); - clone = (cairo_vg_surface_t *) - _vg_surface_create_internal (context, vg_image, format, - extents.width, extents.height); - cairo_surface_set_device_offset (&clone->base, -extents.x, -extents.y); - - status = _cairo_recording_surface_replay (surface, &clone->base); - if (unlikely (status)) { - cairo_surface_destroy (&clone->base); - return (cairo_vg_surface_t *) _cairo_surface_create_in_error (status); - } - - return clone; -} - -static cairo_vg_surface_t * -_vg_clone_image_surface (cairo_vg_context_t *context, - cairo_surface_t *surface) -{ - cairo_image_surface_t *image; - void *image_extra; - cairo_status_t status; - VGImage vg_image; - VGImageFormat format; - cairo_rectangle_int_t extents; - cairo_vg_surface_t *clone; - - if (surface->backend->acquire_source_image == NULL) - return NULL; - - status = _cairo_surface_get_extents (surface, &extents); - if (status) - return NULL; - - if (extents.width > vgGeti (VG_MAX_IMAGE_WIDTH) || - extents.height > vgGeti (VG_MAX_IMAGE_HEIGHT)) - { - return NULL; - } - - status = _cairo_surface_acquire_source_image (surface, - &image, &image_extra); - if (unlikely (status)) - return (cairo_vg_surface_t *) _cairo_surface_create_in_error (status); - - format = _vg_format_from_pixman (image->pixman_format); - if (format == 0) - format = _vg_format_for_content (image->base.content); - - /* NONALIASED, FASTER, BETTER */ - vg_image = vgCreateImage (format, - image->width, image->height, - VG_IMAGE_QUALITY_FASTER); - clone = (cairo_vg_surface_t *) - _vg_surface_create_internal (context, vg_image, format, - image->width, image->height); - if (unlikely (clone->base.status)) - return clone; - - vgImageSubData (clone->image, - image->data, image->stride, - format, 0, 0, image->width, image->height); - - _cairo_surface_release_source_image (surface, image, image_extra); - - return clone; -} - -static void -_vg_surface_remove_from_cache (cairo_surface_t *abstract_surface) -{ - cairo_vg_surface_t *surface = (cairo_vg_surface_t *) abstract_surface; - - if (surface->snapshot_cache_entry.hash) { - cairo_vg_context_t *context; - - context = _vg_context_lock (surface->context); - _cairo_cache_remove (&context->snapshot_cache, - &surface->snapshot_cache_entry); - _vg_context_unlock (context); - - surface->snapshot_cache_entry.hash = 0; - } -} - -static cairo_status_t -_vg_setup_surface_source (cairo_vg_context_t *context, - const cairo_surface_pattern_t *spat) -{ - cairo_surface_t *snapshot; - cairo_vg_surface_t *clone; - cairo_status_t status; - - snapshot = _cairo_surface_has_snapshot (spat->surface, - &cairo_vg_surface_backend); - if (snapshot != NULL) { - clone = (cairo_vg_surface_t *) cairo_surface_reference (snapshot); - goto DONE; - } - - if (_cairo_surface_is_recording (spat->surface)) - clone = _vg_clone_recording_surface (context, spat->surface); - else - clone = _vg_clone_image_surface (context, spat->surface); - if (clone == NULL) - return CAIRO_INT_STATUS_UNSUPPORTED; - if (unlikely (clone->base.status)) - return clone->base.status; - - clone->snapshot_cache_entry.hash = clone->base.unique_id; - status = _cairo_cache_insert (&context->snapshot_cache, - &clone->snapshot_cache_entry); - if (unlikely (status)) { - clone->snapshot_cache_entry.hash = 0; - cairo_surface_destroy (&clone->base); - return status; - } - - _cairo_surface_attach_snapshot (spat->surface, &clone->base, - _vg_surface_remove_from_cache); - -DONE: - cairo_surface_destroy (&context->source->base); - context->source = clone; - - vgSetParameteri (context->paint, VG_PAINT_TYPE, VG_PAINT_TYPE_PATTERN); - - switch (spat->base.extend) { - case CAIRO_EXTEND_PAD: - vgSetParameteri (context->paint, - VG_PAINT_PATTERN_TILING_MODE, - VG_TILE_PAD); - break; - - case CAIRO_EXTEND_NONE: - vgSetParameteri (context->paint, - VG_PAINT_PATTERN_TILING_MODE, - VG_TILE_FILL); - { - VGfloat color[] = {0,0,0,0}; - vgSetfv (VG_TILE_FILL_COLOR, 4, color); - } - break; - - case CAIRO_EXTEND_REPEAT: - vgSetParameteri (context->paint, - VG_PAINT_PATTERN_TILING_MODE, - VG_TILE_REPEAT); - break; - - default: - ASSERT_NOT_REACHED; - case CAIRO_EXTEND_REFLECT: - vgSetParameteri (context->paint, - VG_PAINT_PATTERN_TILING_MODE, - VG_TILE_REFLECT); - break; - } - vgPaintPattern (context->paint, context->source->image); - - _vg_set_source_matrix (&spat->base); - - CHECK_VG_ERRORS(); - return CAIRO_STATUS_SUCCESS; -} - -static cairo_status_t -setup_source (cairo_vg_context_t *context, - const cairo_pattern_t *source) -{ - switch (source->type) { - case CAIRO_PATTERN_TYPE_SOLID: - return _vg_setup_solid_source (context, - (cairo_solid_pattern_t *) source); - case CAIRO_PATTERN_TYPE_LINEAR: - return _vg_setup_linear_source (context, - (cairo_linear_pattern_t *) source); - case CAIRO_PATTERN_TYPE_RADIAL: - return _vg_setup_radial_source (context, - (cairo_radial_pattern_t *) source); - case CAIRO_PATTERN_TYPE_SURFACE: - return _vg_setup_surface_source (context, - (cairo_surface_pattern_t *) source); - default: - ASSERT_NOT_REACHED; - return CAIRO_INT_STATUS_UNSUPPORTED; - } -} - -static cairo_int_status_t -_vg_surface_stroke (void *abstract_surface, - cairo_operator_t op, - const cairo_pattern_t *source, - const cairo_path_fixed_t *path, - const cairo_stroke_style_t *style, - const cairo_matrix_t *ctm, - const cairo_matrix_t *ctm_inverse, - double tolerance, - cairo_antialias_t antialias, - const cairo_clip_t *clip) -{ - cairo_vg_surface_t *surface = abstract_surface; - cairo_vg_context_t *context; - cairo_status_t status; - VGfloat state[9]; - VGfloat strokeTransform[9]; - vg_path_t vg_path; - - if (! _vg_is_supported_operator (op)) - return CAIRO_INT_STATUS_UNSUPPORTED; - - context = _vg_context_lock (surface->context); - status = _vg_context_set_target (context, surface); - if (status) { - _vg_context_unlock (context); - return status; - } - - status = setup_source (context, source); - if (status) { - _vg_context_unlock (context); - return status; - } - - status = _cairo_surface_clipper_set_clip (&surface->clipper, clip); - if (unlikely (status)) { - _vg_context_unlock (context); - return status; - } - - vg_path.path = vgCreatePath (VG_PATH_FORMAT_STANDARD, - VG_PATH_DATATYPE_F, - 1, 0, 0, 0, - VG_PATH_CAPABILITY_ALL); - - vgGetMatrix (state); - _vg_matrix_from_cairo (strokeTransform, ctm); - vgMultMatrix (strokeTransform); - - vg_path.ctm_inverse = ctm_inverse; - - _vg_path_from_cairo (&vg_path, path); - - /* XXX DASH_PATTERN, DASH_PHASE */ - vgSetf (VG_STROKE_LINE_WIDTH, style->line_width); - vgSetf (VG_STROKE_MITER_LIMIT, style->miter_limit); - vgSetf (VG_STROKE_JOIN_STYLE, _vg_line_join_from_cairo (style->line_join)); - vgSetf (VG_STROKE_CAP_STYLE, _vg_line_cap_from_cairo (style->line_cap)); - - vgSeti (VG_BLEND_MODE, _vg_operator (op)); - - vgSetPaint (context->paint, VG_STROKE_PATH); - - vgDrawPath (vg_path.path, VG_STROKE_PATH); - - vgDestroyPath (vg_path.path); - - vgLoadMatrix (state); - - CHECK_VG_ERRORS(); - _vg_context_unlock (context); - - return CAIRO_STATUS_SUCCESS; -} - -static cairo_int_status_t -_vg_surface_fill (void *abstract_surface, - cairo_operator_t op, - const cairo_pattern_t *source, - const cairo_path_fixed_t *path, - cairo_fill_rule_t fill_rule, - double tolerance, - cairo_antialias_t antialias, - const cairo_clip_t *clip) -{ - cairo_vg_surface_t *surface = abstract_surface; - cairo_vg_context_t *context; - cairo_status_t status; - vg_path_t vg_path; - - if (op == CAIRO_OPERATOR_DEST) - return CAIRO_STATUS_SUCCESS; - - if (! _vg_is_supported_operator (op)) - return CAIRO_INT_STATUS_UNSUPPORTED; - - context = _vg_context_lock (surface->context); - status = _vg_context_set_target (context, surface); - if (status) { - _vg_context_unlock (context); - return status; - } - - status = setup_source (context, source); - if (status) { - _vg_context_unlock (context); - return status; - } - - status = _cairo_surface_clipper_set_clip (&surface->clipper, clip); - if (unlikely (status)) { - _vg_context_unlock (context); - return status; - } - - vg_path.path = vgCreatePath (VG_PATH_FORMAT_STANDARD, - VG_PATH_DATATYPE_F, - 1, 0, - 0, 0, - VG_PATH_CAPABILITY_ALL); - vg_path.ctm_inverse = NULL; - - _vg_path_from_cairo (&vg_path, path); - - /* XXX tolerance */ - - vgSeti (VG_BLEND_MODE, _vg_operator (op)); - vgSetf (VG_FILL_RULE, _vg_fill_rule_from_cairo (fill_rule)); - vgSetf (VG_RENDERING_QUALITY, _vg_rendering_quality_from_cairo (antialias)); - - vgSetPaint (context->paint, VG_FILL_PATH); - - vgDrawPath (vg_path.path, VG_FILL_PATH); - - vgDestroyPath (vg_path.path); - - _vg_context_unlock (context); - - CHECK_VG_ERRORS(); - return CAIRO_STATUS_SUCCESS; -} - -static cairo_int_status_t -_vg_surface_paint (void *abstract_surface, - cairo_operator_t op, - const cairo_pattern_t *source, - const cairo_clip_t *clip) -{ - cairo_vg_surface_t *surface = abstract_surface; - cairo_vg_context_t *context; - cairo_status_t status; - - if (op == CAIRO_OPERATOR_DEST) - return CAIRO_STATUS_SUCCESS; - - if (! _vg_is_supported_operator (op)) - return CAIRO_INT_STATUS_UNSUPPORTED; - - context = _vg_context_lock (surface->context); - status = _vg_context_set_target (context, surface); - if (status) { - _vg_context_unlock (context); - return status; - } - - status = setup_source (context, source); - if (status) { - _vg_context_unlock (context); - return status; - } - - status = _cairo_surface_clipper_set_clip (&surface->clipper, clip); - if (unlikely (status)) { - _vg_context_unlock (context); - return status; - } - - vgSeti (VG_BLEND_MODE, _vg_operator (op)); - vgSetPaint (context->paint, VG_FILL_PATH); - - { /* creating a rectangular path that should cover the extent */ - VGubyte segs[] = { - VG_MOVE_TO_ABS, VG_LINE_TO_ABS, - VG_LINE_TO_ABS, VG_LINE_TO_ABS, - VG_CLOSE_PATH - }; - VGfloat data[] = { - 0, 0, - surface->width, 0, - surface->width, surface->height, - 0, surface->height - }; - VGPath fullext; - - fullext = vgCreatePath (VG_PATH_FORMAT_STANDARD, VG_PATH_DATATYPE_F, - 1,0,0,0, VG_PATH_CAPABILITY_ALL); - vgAppendPathData (fullext, sizeof(segs), segs, data); - - vgDrawPath (fullext, VG_FILL_PATH); - - vgDestroyPath (fullext); - } - - _vg_context_unlock (context); - - CHECK_VG_ERRORS(); - return CAIRO_STATUS_SUCCESS; -} - -static cairo_int_status_t -_vg_surface_mask (void *abstract_surface, - cairo_operator_t op, - const cairo_pattern_t *source, - const cairo_pattern_t *mask, - const cairo_clip_t *clip) -{ - cairo_vg_surface_t *surface = abstract_surface; - cairo_status_t status; - - if (! _vg_is_supported_operator (op)) - return CAIRO_INT_STATUS_UNSUPPORTED; - - /* Handle paint-with-alpha to do fades cheaply */ - if (mask->type == CAIRO_PATTERN_TYPE_SOLID) { - cairo_solid_pattern_t *solid = (cairo_solid_pattern_t *) mask; - cairo_vg_context_t *context = _vg_context_lock (surface->context); - double alpha = context->alpha; - - context->alpha = solid->color.alpha; - status = _vg_surface_paint (abstract_surface, op, source, clip); - context->alpha = alpha; - - _vg_context_unlock (context); - - return status; - } - - return CAIRO_INT_STATUS_UNSUPPORTED; -} - -static void -_vg_surface_get_font_options (void *abstract_surface, - cairo_font_options_t *options) -{ - _cairo_font_options_init_default (options); - - cairo_font_options_set_hint_metrics (options, CAIRO_HINT_METRICS_ON); - _cairo_font_options_set_round_glyph_positions (options, CAIRO_ROUND_GLYPH_POS_OFF); -} - -static cairo_int_status_t -_vg_surface_show_glyphs (void *abstract_surface, - cairo_operator_t op, - const cairo_pattern_t *source, - cairo_glyph_t *glyphs, - int num_glyphs, - cairo_scaled_font_t *scaled_font, - const cairo_clip_t *clip) -{ - cairo_status_t status = CAIRO_STATUS_SUCCESS; - cairo_path_fixed_t path; - - if (num_glyphs <= 0) - return CAIRO_STATUS_SUCCESS; - - _cairo_path_fixed_init (&path); - - /* XXX Glyph cache! OpenVG font support in 1.1? */ - - status = _cairo_scaled_font_glyph_path (scaled_font, - glyphs, num_glyphs, - &path); - if (unlikely (status)) - goto BAIL; - - status = _vg_surface_fill (abstract_surface, - op, source, &path, - CAIRO_FILL_RULE_WINDING, - CAIRO_GSTATE_TOLERANCE_DEFAULT, - CAIRO_ANTIALIAS_DEFAULT, - clip); -BAIL: - _cairo_path_fixed_fini (&path); - return status; -} - -static inline int -multiply_alpha (int alpha, int color) -{ - int temp = alpha * color + 0x80; - return (temp + (temp >> 8)) >> 8; -} - -static void -premultiply_argb (uint8_t *data, - int width, - int height, - int stride) -{ - int i; - - while (height --) { - uint32_t *row = (uint32_t *) data; - - for (i = 0; i < width; i++) { - uint32_t p = row[i]; - uint8_t alpha; - - alpha = p >> 24; - if (alpha == 0) { - row[i] = 0; - } else if (alpha != 0xff) { - uint8_t r = multiply_alpha (alpha, (p >> 16) & 0xff); - uint8_t g = multiply_alpha (alpha, (p >> 8) & 0xff); - uint8_t b = multiply_alpha (alpha, (p >> 0) & 0xff); - row[i] = ((uint32_t)alpha << 24) | (r << 16) | (g << 8) | (b << 0); - } - } - - data += stride; - } -} - -static cairo_int_status_t -_vg_get_image (cairo_vg_surface_t *surface, - int x, int y, - int width, int height, - cairo_image_surface_t **image_out) -{ - cairo_image_surface_t *image; - pixman_image_t *pixman_image; - pixman_format_code_t pixman_format; - cairo_bool_t needs_premultiply; - - pixman_format = _vg_format_to_pixman (surface->format, - &needs_premultiply); - if (pixman_format == 0) - return CAIRO_INT_STATUS_UNSUPPORTED; - - pixman_image = pixman_image_create_bits (pixman_format, - width, height, - NULL, 0); - if (unlikely (pixman_image == NULL)) - return _cairo_error (CAIRO_STATUS_NO_MEMORY); - - vgFinish (); - CHECK_VG_ERRORS(); - - vgGetImageSubData (surface->image, - pixman_image_get_data (pixman_image), - pixman_image_get_stride (pixman_image), - surface->format, - x, y, width, height); - - image = (cairo_image_surface_t *) - _cairo_image_surface_create_for_pixman_image (pixman_image, - pixman_format); - if (unlikely (image->base.status)) { - pixman_image_unref (pixman_image); - return image->base.status; - } - - if (needs_premultiply) - premultiply_argb (image->data, width, height, image->stride); - - *image_out = image; - return CAIRO_STATUS_SUCCESS; -} - -static cairo_status_t -_vg_surface_acquire_source_image (void *abstract_surface, - cairo_image_surface_t **image_out, - void **image_extra) -{ - cairo_vg_surface_t *surface = abstract_surface; - - CHECK_VG_ERRORS(); - *image_extra = NULL; - return _vg_get_image (surface, - 0, 0, surface->width, surface->height, - image_out); -} - -static void -_vg_surface_release_source_image (void *abstract_surface, - cairo_image_surface_t *image, - void *image_extra) -{ - cairo_surface_destroy (&image->base); -} - -static cairo_status_t -_vg_surface_finish (void *abstract_surface) -{ - cairo_vg_surface_t *surface = abstract_surface; - cairo_vg_context_t *context = _vg_context_lock (surface->context); - - if (surface->snapshot_cache_entry.hash) { - _cairo_cache_remove (&context->snapshot_cache, - &surface->snapshot_cache_entry); - - surface->snapshot_cache_entry.hash = 0; - } - - _cairo_surface_clipper_reset (&surface->clipper); - - if (surface->own_image) - vgDestroyImage (surface->image); - - _vg_context_destroy_target (context, surface); - - _vg_context_unlock (context); - _vg_context_destroy (context); - - CHECK_VG_ERRORS(); - return CAIRO_STATUS_SUCCESS; -} - -static const cairo_surface_backend_t cairo_vg_surface_backend = { - CAIRO_SURFACE_TYPE_VG, - _vg_surface_finish, - - _cairo_default_context_create, /* XXX */ - - _vg_surface_create_similar, - NULL, /* create similar image */ - NULL, /* map to image */ - NULL, /* unmap image */ - - _cairo_surface_default_source, - _vg_surface_acquire_source_image, - _vg_surface_release_source_image, - NULL, /* snapshot */ - - NULL, /* copy_page */ - NULL, /* show_page */ - - _vg_surface_get_extents, - _vg_surface_get_font_options, /* get_font_options */ - - NULL, /* flush */ - NULL, /* mark dirty */ - - _vg_surface_paint, - _vg_surface_mask, - _vg_surface_stroke, - _vg_surface_fill, - NULL, /* fill-stroke */ - _vg_surface_show_glyphs, -}; - -static cairo_surface_t * -_vg_surface_create_internal (cairo_vg_context_t *context, - VGImage image, - VGImageFormat format, - int width, int height) -{ - cairo_vg_surface_t *surface; - - surface = _cairo_malloc (sizeof (cairo_vg_surface_t)); - if (unlikely (surface == NULL)) - return _cairo_surface_create_in_error (_cairo_error (CAIRO_STATUS_NO_MEMORY)); - - surface->context = _vg_context_reference (context); - - surface->image = image; - surface->format = format; - - _cairo_surface_init (&surface->base, - &cairo_vg_surface_backend, - NULL, /* device */ - _vg_format_to_content (format), - FALSE); /* is_vector */ - - surface->width = width; - surface->height = height; - - _cairo_surface_clipper_init (&surface->clipper, - _vg_surface_clipper_intersect_clip_path); - - surface->snapshot_cache_entry.hash = 0; - - surface->target_id = 0; - - CHECK_VG_ERRORS(); - return &surface->base; -} - -cairo_surface_t * -cairo_vg_surface_create_for_image (cairo_vg_context_t *context, - VGImage image, - VGImageFormat format, - int width, int height) -{ - cairo_bool_t premult; - - if (context->status) - return _cairo_surface_create_in_error (context->status); - - if (image == VG_INVALID_HANDLE) - return _cairo_surface_create_in_error (_cairo_error (CAIRO_STATUS_NO_MEMORY)); - if (_vg_format_to_pixman (format, &premult) == 0) - return _cairo_surface_create_in_error (_cairo_error (CAIRO_STATUS_INVALID_FORMAT)); - - return _vg_surface_create_internal (context, image, format, width, height); -} - -cairo_surface_t * -cairo_vg_surface_create (cairo_vg_context_t *context, - cairo_content_t content, - int width, - int height) -{ - VGImage image; - VGImageFormat format; - cairo_surface_t *surface; - - if (context->status) - return _cairo_surface_create_in_error (context->status); - - if (! CAIRO_CONTENT_VALID (content)) - return _cairo_surface_create_in_error (_cairo_error (CAIRO_STATUS_INVALID_CONTENT)); - - if (width > vgGeti (VG_MAX_IMAGE_WIDTH) || - height > vgGeti (VG_MAX_IMAGE_HEIGHT)) - { - return _cairo_surface_create_in_error (_cairo_error (CAIRO_STATUS_INVALID_SIZE)); - } - - - format = _vg_format_for_content (content); - image = vgCreateImage (format, width, height, VG_IMAGE_QUALITY_BETTER); - if (image == VG_INVALID_HANDLE) - return _cairo_surface_create_in_error (_cairo_error (CAIRO_STATUS_NO_MEMORY)); - - surface = _vg_surface_create_internal (context, - image, format, width, height); - if (unlikely (surface->status)) - return surface; - - ((cairo_vg_surface_t *) surface)->own_image = TRUE; - return surface; -} -slim_hidden_def (cairo_vg_surface_create); - -VGImage -cairo_vg_surface_get_image (cairo_surface_t *abstract_surface) -{ - cairo_vg_surface_t *surface; - - if (abstract_surface->backend != &cairo_vg_surface_backend) { - _cairo_error_throw (CAIRO_STATUS_SURFACE_TYPE_MISMATCH); - return VG_INVALID_HANDLE; - } - - surface = (cairo_vg_surface_t *) abstract_surface; - return surface->image; -} - -int -cairo_vg_surface_get_width (cairo_surface_t *abstract_surface) -{ - cairo_vg_surface_t *surface; - - if (abstract_surface->backend != &cairo_vg_surface_backend) { - _cairo_error_throw (CAIRO_STATUS_SURFACE_TYPE_MISMATCH); - return 0; - } - - surface = (cairo_vg_surface_t *) abstract_surface; - return surface->width; -} - -int -cairo_vg_surface_get_height (cairo_surface_t *abstract_surface) -{ - cairo_vg_surface_t *surface; - - if (abstract_surface->backend != &cairo_vg_surface_backend) { - _cairo_error_throw (CAIRO_STATUS_SURFACE_TYPE_MISMATCH); - return 0; - } - - surface = (cairo_vg_surface_t *) abstract_surface; - return surface->height; -} - -VGImageFormat -cairo_vg_surface_get_format (cairo_surface_t *abstract_surface) -{ - cairo_vg_surface_t *surface; - - if (abstract_surface->backend != &cairo_vg_surface_backend) { - _cairo_error_throw (CAIRO_STATUS_SURFACE_TYPE_MISMATCH); - return 0; - } - - surface = (cairo_vg_surface_t *) abstract_surface; - return surface->format; -} - -/* GL specific context support :-( - * - * OpenVG like cairo defers creation of surface (and the necessary - * paraphernalia to the application. - */ - -static const cairo_vg_context_t _vg_context_nil = { - CAIRO_STATUS_NO_MEMORY, - CAIRO_REFERENCE_COUNT_INVALID -}; - -static const cairo_vg_context_t _vg_context_nil_invalid_visual = { - CAIRO_STATUS_INVALID_VISUAL, - CAIRO_REFERENCE_COUNT_INVALID -}; - -#if CAIRO_HAS_GLX_FUNCTIONS -#include <GL/glx.h> - -static cairo_status_t -glx_create_target (cairo_vg_context_t *context, - cairo_vg_surface_t *surface) -{ - /* XXX hmm, magic required for creating an FBO points to VGImage! */ - return CAIRO_INT_STATUS_UNSUPPORTED; -} - -static cairo_status_t -glx_set_target (cairo_vg_context_t *context, - cairo_vg_surface_t *surface) -{ -#if 0 - glXMakeContextCurrent (context->display, - (GLXDrawable) surface->target_id, - (GLXDrawable) surface->target_id, - context->context); -#else - return CAIRO_INT_STATUS_UNSUPPORTED; -#endif -} - -static void -glx_destroy_target (cairo_vg_context_t *context, - cairo_vg_surface_t *surface) -{ -} - -cairo_vg_context_t * -cairo_vg_context_create_for_glx (Display *dpy, GLXContext ctx) -{ - cairo_vg_context_t *context; - cairo_status_t status; - - context = _cairo_malloc (sizeof (*context)); - if (unlikely (context == NULL)) - return (cairo_vg_context_t *) &_vg_context_nil; - - context->display = dpy; - context->context = ctx; - - context->create_target = glx_create_target; - context->set_target = glx_set_target; - context->destroy_target = glx_destroy_target; - - status = _vg_context_init (context); - if (unlikely (status)) { - free (context); - return (cairo_vg_context_t *) &_vg_context_nil; - } - - return context; -} -#endif - -#if CAIRO_HAS_EGL_FUNCTIONS -static cairo_status_t -egl_create_target (cairo_vg_context_t *context, - cairo_vg_surface_t *surface) -{ - EGLSurface *egl_surface; -#define RED 1 -#define GREEN 3 -#define BLUE 5 -#define ALPHA 7 - int attribs[] = { - EGL_RED_SIZE, 0, - EGL_GREEN_SIZE, 0, - EGL_BLUE_SIZE, 0, - EGL_ALPHA_SIZE, 0, - EGL_SURFACE_TYPE, EGL_PBUFFER_BIT, - EGL_RENDERABLE_TYPE, EGL_OPENVG_BIT, - EGL_NONE - }; - pixman_format_code_t pixman_format; - EGLConfig config; - int num_configs = 0; - cairo_bool_t needs_premultiply; - - pixman_format = _vg_format_to_pixman (surface->format, &needs_premultiply); - if (pixman_format == 0) - return CAIRO_INT_STATUS_UNSUPPORTED; - - /* XXX no control over pixel ordering! */ - attribs[RED] = PIXMAN_FORMAT_R (pixman_format); - attribs[GREEN] = PIXMAN_FORMAT_G (pixman_format); - attribs[BLUE] = PIXMAN_FORMAT_B (pixman_format); - attribs[ALPHA] = PIXMAN_FORMAT_A (pixman_format); - - if (! eglChooseConfig (context->display, - attribs, - &config, 1, &num_configs) || - num_configs != 1) - { - fprintf(stderr, "Error: eglChooseConfig() failed.\n"); - return CAIRO_INT_STATUS_UNSUPPORTED; - } - - egl_surface = - eglCreatePbufferFromClientBuffer (context->display, - EGL_OPENVG_IMAGE, - (EGLClientBuffer) surface->image, - config, - NULL); - surface->target_id = (unsigned long) egl_surface; - - return CAIRO_STATUS_SUCCESS; -} - -static cairo_status_t -egl_set_target (cairo_vg_context_t *context, - cairo_vg_surface_t *surface) -{ - if (! eglMakeCurrent (context->display, - (EGLSurface *) surface->target_id, - (EGLSurface *) surface->target_id, - context->context)) - { - return _cairo_error (CAIRO_STATUS_NO_MEMORY); - } - - return CAIRO_STATUS_SUCCESS; -} - -static void -egl_destroy_target (cairo_vg_context_t *context, - cairo_vg_surface_t *surface) -{ - eglDestroySurface (context->display, - (EGLSurface *) surface->target_id); -} - -cairo_vg_context_t * -cairo_vg_context_create_for_egl (EGLDisplay egl_display, - EGLContext egl_context) -{ - cairo_vg_context_t *context; - cairo_status_t status; - - context = _cairo_malloc (sizeof (*context)); - if (unlikely (context == NULL)) - return (cairo_vg_context_t *) &_vg_context_nil; - - status = _vg_context_init (context); - if (unlikely (status)) { - free (context); - return (cairo_vg_context_t *) &_vg_context_nil; - } - - context->display = egl_display; - context->context = egl_context; - - context->create_target = egl_create_target; - context->set_target = egl_set_target; - context->destroy_target = egl_destroy_target; - - return context; -} -#endif - -cairo_status_t -cairo_vg_context_status (cairo_vg_context_t *context) -{ - return context->status; -} - -void -cairo_vg_context_destroy (cairo_vg_context_t *context) -{ - if (context == NULL || CAIRO_REFERENCE_COUNT_IS_INVALID (&context->ref_count)) - return; - - _vg_context_destroy (context); -} diff --git a/gfx/cairo/cairo/src/cairo-vg.h b/gfx/cairo/cairo/src/cairo-vg.h deleted file mode 100644 index a2701db3bd..0000000000 --- a/gfx/cairo/cairo/src/cairo-vg.h +++ /dev/null @@ -1,103 +0,0 @@ -/* -*- Mode: c; tab-width: 8; c-basic-offset: 4; indent-tabs-mode: t; -*- */ -/* cairo - a vector graphics library with display and print output - * - * Copyright © 2007 * Mozilla Corporation - * Copyright © 2009 Chris Wilson - * - * 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., 51 Franklin Street, Suite 500, Boston, MA 02110-1335, USA - * You should have received a copy of the MPL along with this library - * in the file COPYING-MPL-1.1 - * - * The contents of this file are subject to the Mozilla Public License - * Version 1.1 (the "License"); you may not use this file except in - * compliance with the License. You may obtain a copy of the License at - * http://www.mozilla.org/MPL/ - * - * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY - * OF ANY KIND, either express or implied. See the LGPL or the MPL for - * the specific language governing rights and limitations. - * - * The Original Code is the cairo graphics library. - * - * The Initial Developer of the Original Code is Mozilla Corporation. - * - * Contributor(s): - * Vladimir Vukicevic <vladimir@mozilla.com> - * Chris Wilson <chris@chris-wilson.co.uk> - */ - -#ifndef CAIRO_VG_H -#define CAIRO_VG_H - -#include "cairo.h" - -#if CAIRO_HAS_VG_SURFACE - -#include <VG/openvg.h> - -CAIRO_BEGIN_DECLS - -typedef struct _cairo_vg_context cairo_vg_context_t; - -#if CAIRO_HAS_GLX_FUNCTIONS -typedef struct __GLXcontextRec *GLXContext; -typedef struct _XDisplay Display; - -cairo_public cairo_vg_context_t * -cairo_vg_context_create_for_glx (Display *dpy, - GLXContext ctx); -#endif - -#if CAIRO_HAS_EGL_FUNCTIONS -#include <EGL/egl.h> - -cairo_public cairo_vg_context_t * -cairo_vg_context_create_for_egl (EGLDisplay egl_display, - EGLContext egl_context); -#endif - -cairo_public cairo_status_t -cairo_vg_context_status (cairo_vg_context_t *context); - -cairo_public void -cairo_vg_context_destroy (cairo_vg_context_t *context); - -cairo_public cairo_surface_t * -cairo_vg_surface_create (cairo_vg_context_t *context, - cairo_content_t content, int width, int height); - -cairo_public cairo_surface_t * -cairo_vg_surface_create_for_image (cairo_vg_context_t *context, - VGImage image, - VGImageFormat format, - int width, int height); - -cairo_public VGImage -cairo_vg_surface_get_image (cairo_surface_t *abstract_surface); - -cairo_public VGImageFormat -cairo_vg_surface_get_format (cairo_surface_t *abstract_surface); - -cairo_public int -cairo_vg_surface_get_height (cairo_surface_t *abstract_surface); - -cairo_public int -cairo_vg_surface_get_width (cairo_surface_t *abstract_surface); - -CAIRO_END_DECLS - -#else /* CAIRO_HAS_VG_SURFACE*/ -# error Cairo was not compiled with support for the OpenVG backend -#endif /* CAIRO_HAS_VG_SURFACE*/ - -#endif /* CAIRO_VG_H */ diff --git a/gfx/cairo/cairo/src/cairo-wgl-context.c b/gfx/cairo/cairo/src/cairo-wgl-context.c deleted file mode 100644 index 4872374464..0000000000 --- a/gfx/cairo/cairo/src/cairo-wgl-context.c +++ /dev/null @@ -1,261 +0,0 @@ -/* cairo - a vector graphics library with display and print output - * - * Copyright © 2009 Eric Anholt - * Copyright © 2009 Chris Wilson - * Copyright © 2005 Red Hat, Inc - * - * This library is free software; you can redistribute it and/or - * modify it either under the terms of the GNU Lesser General Public - * License version 2.1 as published by the Free Software Foundation - * (the "LGPL") or, at your option, under the terms of the Mozilla - * Public License Version 1.1 (the "MPL"). If you do not alter this - * notice, a recipient may use your version of this file under either - * the MPL or the LGPL. - * - * You should have received a copy of the LGPL along with this library - * in the file COPYING-LGPL-2.1; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Suite 500, Boston, MA 02110-1335, 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 Worth <cworth@cworth.org> - * Chris Wilson <chris@chris-wilson.co.uk> - * Zoxc <zoxc32@gmail.com> - */ - -#include "cairoint.h" - -#include "cairo-gl-private.h" - -#include "cairo-error-private.h" - -#define WIN32_LEAN_AND_MEAN -#include <windows.h> - -typedef struct _cairo_wgl_context { - cairo_gl_context_t base; - - HDC dummy_dc; - HWND dummy_wnd; - HGLRC rc; - - HDC prev_dc; - HGLRC prev_rc; -} cairo_wgl_context_t; - -typedef struct _cairo_wgl_surface { - cairo_gl_surface_t base; - - HDC dc; -} cairo_wgl_surface_t; - -static void -_wgl_acquire (void *abstract_ctx) -{ - cairo_wgl_context_t *ctx = abstract_ctx; - - HDC current_dc; - - ctx->prev_dc = wglGetCurrentDC (); - ctx->prev_rc = wglGetCurrentContext (); - - if (ctx->base.current_target == NULL || - _cairo_gl_surface_is_texture (ctx->base.current_target)) - { - current_dc = ctx->dummy_dc; - } - else - { - cairo_wgl_surface_t *surface = (cairo_wgl_surface_t *) ctx->base.current_target; - current_dc = surface->dc; - } - - if (ctx->prev_dc != current_dc || - (ctx->prev_rc != ctx->rc && - current_dc != ctx->dummy_dc)) - { - wglMakeCurrent (current_dc, ctx->rc); - } -} - -static void -_wgl_make_current (void *abstract_ctx, cairo_gl_surface_t *abstract_surface) -{ - cairo_wgl_context_t *ctx = abstract_ctx; - cairo_wgl_surface_t *surface = (cairo_wgl_surface_t *) abstract_surface; - - /* Set the window as the target of our context. */ - wglMakeCurrent (surface->dc, ctx->rc); -} - -static void -_wgl_release (void *abstract_ctx) -{ - cairo_wgl_context_t *ctx = abstract_ctx; - - if (ctx->prev_dc != wglGetCurrentDC () || - ctx->prev_rc != wglGetCurrentContext ()) - { - wglMakeCurrent (ctx->prev_dc, - ctx->prev_rc); - } -} - -static void -_wgl_swap_buffers (void *abstract_ctx, - cairo_gl_surface_t *abstract_surface) -{ - cairo_wgl_surface_t *surface = (cairo_wgl_surface_t *) abstract_surface; - - SwapBuffers (surface->dc); -} - -static void -_wgl_destroy (void *abstract_ctx) -{ - cairo_wgl_context_t *ctx = abstract_ctx; - - if (ctx->dummy_dc != 0) { - wglMakeCurrent (ctx->dummy_dc, 0); - ReleaseDC (ctx->dummy_wnd, ctx->dummy_dc); - DestroyWindow (ctx->dummy_wnd); - } -} - -static cairo_status_t -_wgl_dummy_ctx (cairo_wgl_context_t *ctx) -{ - WNDCLASSEXA wincl; - PIXELFORMATDESCRIPTOR pfd; - int format; - HDC dc; - - ZeroMemory (&wincl, sizeof (WNDCLASSEXA)); - wincl.cbSize = sizeof (WNDCLASSEXA); - wincl.hInstance = GetModuleHandle (0); - wincl.lpszClassName = "cairo_wgl_context_dummy"; - wincl.lpfnWndProc = DefWindowProcA; - wincl.style = CS_OWNDC; - - RegisterClassExA (&wincl); - - ctx->dummy_wnd = CreateWindowA ("cairo_wgl_context_dummy", 0, 0, 0, 0, 0, 0, 0, 0, 0, 0); - ctx->dummy_dc = GetDC (ctx->dummy_wnd); - - ZeroMemory (&pfd, sizeof (PIXELFORMATDESCRIPTOR)); - pfd.nSize = sizeof (PIXELFORMATDESCRIPTOR); - pfd.nVersion = 1; - pfd.dwFlags = PFD_DRAW_TO_WINDOW | PFD_SUPPORT_OPENGL | PFD_DOUBLEBUFFER; - pfd.iPixelType = PFD_TYPE_RGBA; - pfd.cColorBits = 24; - pfd.cDepthBits = 16; - pfd.iLayerType = PFD_MAIN_PLANE; - - format = ChoosePixelFormat (ctx->dummy_dc, &pfd); - SetPixelFormat (ctx->dummy_dc, format, &pfd); - - wglMakeCurrent(ctx->dummy_dc, ctx->rc); - - return CAIRO_STATUS_SUCCESS; -} - -cairo_device_t * -cairo_wgl_device_create (HGLRC rc) -{ - cairo_wgl_context_t *ctx; - cairo_status_t status; - - ctx = calloc (1, sizeof (cairo_wgl_context_t)); - if (unlikely (ctx == NULL)) - return _cairo_gl_context_create_in_error (CAIRO_STATUS_NO_MEMORY); - - ctx->rc = rc; - ctx->prev_dc = 0; - ctx->prev_rc = 0; - - status = _wgl_dummy_ctx (ctx); - if (unlikely (status)) { - free (ctx); - return _cairo_gl_context_create_in_error (status); - } - - ctx->base.acquire = _wgl_acquire; - ctx->base.release = _wgl_release; - ctx->base.make_current = _wgl_make_current; - ctx->base.swap_buffers = _wgl_swap_buffers; - ctx->base.destroy = _wgl_destroy; - - status = _cairo_gl_dispatch_init (&ctx->base.dispatch, - (cairo_gl_get_proc_addr_func_t) wglGetProcAddress); - if (unlikely (status)) { - free (ctx); - return _cairo_gl_context_create_in_error (status); - } - - status = _cairo_gl_context_init (&ctx->base); - if (unlikely (status)) { - free (ctx); - return _cairo_gl_context_create_in_error (status); - } - - ctx->base.release (ctx); - - return &ctx->base.base; -} - -HGLRC -cairo_wgl_device_get_context (cairo_device_t *device) -{ - cairo_wgl_context_t *ctx; - - if (device->backend->type != CAIRO_DEVICE_TYPE_GL) { - _cairo_error_throw (CAIRO_STATUS_DEVICE_TYPE_MISMATCH); - return NULL; - } - - ctx = (cairo_wgl_context_t *) device; - - return ctx->rc; -} - -cairo_surface_t * -cairo_gl_surface_create_for_dc (cairo_device_t *device, - HDC dc, - int width, - int height) -{ - cairo_wgl_surface_t *surface; - - if (unlikely (device->status)) - return _cairo_surface_create_in_error (device->status); - - if (device->backend->type != CAIRO_DEVICE_TYPE_GL) - return _cairo_surface_create_in_error (_cairo_error (CAIRO_STATUS_SURFACE_TYPE_MISMATCH)); - - if (width <= 0 || height <= 0) - return _cairo_surface_create_in_error (_cairo_error (CAIRO_STATUS_INVALID_SIZE)); - - surface = calloc (1, sizeof (cairo_wgl_surface_t)); - if (unlikely (surface == NULL)) - return _cairo_surface_create_in_error (_cairo_error (CAIRO_STATUS_NO_MEMORY)); - - _cairo_gl_surface_init (device, &surface->base, - CAIRO_CONTENT_COLOR_ALPHA, width, height); - surface->dc = dc; - - return &surface->base.base; -} diff --git a/gfx/cairo/cairo/src/cairo-wideint-type-private.h b/gfx/cairo/cairo/src/cairo-wideint-type-private.h index 84a3cbab0d..a1a2269f87 100644 --- a/gfx/cairo/cairo/src/cairo-wideint-type-private.h +++ b/gfx/cairo/cairo/src/cairo-wideint-type-private.h @@ -39,9 +39,7 @@ #include "cairo.h" -#if HAVE_CONFIG_H #include "config.h" -#endif #if HAVE_STDINT_H # include <stdint.h> diff --git a/gfx/cairo/cairo/src/cairo-win32.h b/gfx/cairo/cairo/src/cairo-win32.h index d11f9dec0d..a2576e2ad1 100644 --- a/gfx/cairo/cairo/src/cairo-win32.h +++ b/gfx/cairo/cairo/src/cairo-win32.h @@ -69,14 +69,16 @@ cairo_win32_surface_create_with_dib (cairo_format_t format, cairo_public HDC cairo_win32_surface_get_dc (cairo_surface_t *surface); -cairo_public HDC -cairo_win32_get_dc_with_clip (cairo_t *cr); - cairo_public cairo_surface_t * cairo_win32_surface_get_image (cairo_surface_t *surface); +cairo_public HDC +cairo_win32_get_dc_with_clip(cairo_t* cr); + cairo_public cairo_status_t -cairo_win32_surface_get_size (const cairo_surface_t *surface, int *width, int *height); +cairo_win32_surface_get_size(const cairo_surface_t* surface, + int* width, + int* height); #if CAIRO_HAS_WIN32_FONT @@ -111,33 +113,8 @@ cairo_public void cairo_win32_scaled_font_get_device_to_logical (cairo_scaled_font_t *scaled_font, cairo_matrix_t *device_to_logical); -cairo_public BYTE -cairo_win32_get_system_text_quality (void); - #endif /* CAIRO_HAS_WIN32_FONT */ -#if CAIRO_HAS_DWRITE_FONT - -/* - * Win32 DirectWrite font support - */ -cairo_public cairo_font_face_t * -cairo_dwrite_font_face_create_for_dwrite_fontface (void *dwrite_font, void *dwrite_font_face); - -void -cairo_dwrite_scaled_font_set_force_GDI_classic (cairo_scaled_font_t *dwrite_scaled_font, cairo_bool_t allowed); - -cairo_bool_t -cairo_dwrite_scaled_font_get_force_GDI_classic (cairo_scaled_font_t *dwrite_scaled_font); - -void -cairo_dwrite_set_cleartype_params (FLOAT gamma, FLOAT contrast, FLOAT level, int geometry, int mode); - -int -cairo_dwrite_get_cleartype_rendering_mode (); - -#endif /* CAIRO_HAS_DWRITE_FONT */ - CAIRO_END_DECLS #else /* CAIRO_HAS_WIN32_SURFACE */ diff --git a/gfx/cairo/cairo/src/cairo-xcb-connection-core.c b/gfx/cairo/cairo/src/cairo-xcb-connection-core.c index e01dc1a836..71d2e515b3 100644 --- a/gfx/cairo/cairo/src/cairo-xcb-connection-core.c +++ b/gfx/cairo/cairo/src/cairo-xcb-connection-core.c @@ -42,7 +42,7 @@ _cairo_xcb_connection_create_pixmap (cairo_xcb_connection_t *connection, uint16_t width, uint16_t height) { - xcb_pixmap_t pixmap = _cairo_xcb_connection_get_xid (connection); + xcb_pixmap_t pixmap = xcb_generate_id (connection->xcb_connection); assert (width > 0); assert (height > 0); @@ -52,35 +52,19 @@ _cairo_xcb_connection_create_pixmap (cairo_xcb_connection_t *connection, return pixmap; } -void -_cairo_xcb_connection_free_pixmap (cairo_xcb_connection_t *connection, - xcb_pixmap_t pixmap) -{ - xcb_free_pixmap (connection->xcb_connection, pixmap); - _cairo_xcb_connection_put_xid (connection, pixmap); -} - xcb_gcontext_t _cairo_xcb_connection_create_gc (cairo_xcb_connection_t *connection, xcb_drawable_t drawable, uint32_t value_mask, uint32_t *values) { - xcb_gcontext_t gc = _cairo_xcb_connection_get_xid (connection); + xcb_gcontext_t gc = xcb_generate_id (connection->xcb_connection); xcb_create_gc (connection->xcb_connection, gc, drawable, value_mask, values); return gc; } void -_cairo_xcb_connection_free_gc (cairo_xcb_connection_t *connection, - xcb_gcontext_t gc) -{ - xcb_free_gc (connection->xcb_connection, gc); - _cairo_xcb_connection_put_xid (connection, gc); -} - -void _cairo_xcb_connection_change_gc (cairo_xcb_connection_t *connection, xcb_gcontext_t gc, uint32_t value_mask, diff --git a/gfx/cairo/cairo/src/cairo-xcb-connection-render.c b/gfx/cairo/cairo/src/cairo-xcb-connection-render.c index 61119653e9..e27b2b3b2c 100644 --- a/gfx/cairo/cairo/src/cairo-xcb-connection-render.c +++ b/gfx/cairo/cairo/src/cairo-xcb-connection-render.c @@ -79,7 +79,6 @@ _cairo_xcb_connection_render_free_picture (cairo_xcb_connection_t *connection, { assert (connection->flags & CAIRO_XCB_HAS_RENDER); xcb_render_free_picture (connection->xcb_connection, picture); - _cairo_xcb_connection_put_xid (connection, picture); } void @@ -133,7 +132,6 @@ _cairo_xcb_connection_render_free_glyph_set (cairo_xcb_connection_t *connec { assert (connection->flags & CAIRO_XCB_HAS_RENDER); xcb_render_free_glyph_set (connection->xcb_connection, glyphset); - _cairo_xcb_connection_put_xid (connection, glyphset); } void diff --git a/gfx/cairo/cairo/src/cairo-xcb-connection-shm.c b/gfx/cairo/cairo/src/cairo-xcb-connection-shm.c index 7720bbbd25..140a73cd0c 100644 --- a/gfx/cairo/cairo/src/cairo-xcb-connection-shm.c +++ b/gfx/cairo/cairo/src/cairo-xcb-connection-shm.c @@ -43,7 +43,7 @@ _cairo_xcb_connection_shm_attach (cairo_xcb_connection_t *connection, uint32_t id, cairo_bool_t readonly) { - uint32_t segment = _cairo_xcb_connection_get_xid (connection); + uint32_t segment = xcb_generate_id (connection->xcb_connection); assert (connection->flags & CAIRO_XCB_HAS_SHM); xcb_shm_attach (connection->xcb_connection, segment, id, readonly); return segment; @@ -109,7 +109,6 @@ _cairo_xcb_connection_shm_detach (cairo_xcb_connection_t *connection, { assert (connection->flags & CAIRO_XCB_HAS_SHM); xcb_shm_detach (connection->xcb_connection, segment); - _cairo_xcb_connection_put_xid (connection, segment); } #endif /* CAIRO_HAS_XCB_SHM_FUNCTIONS */ diff --git a/gfx/cairo/cairo/src/cairo-xcb-connection.c b/gfx/cairo/cairo/src/cairo-xcb-connection.c index 51f5ee323c..daa7d4f659 100644 --- a/gfx/cairo/cairo/src/cairo-xcb-connection.c +++ b/gfx/cairo/cairo/src/cairo-xcb-connection.c @@ -255,7 +255,7 @@ pixmap_depths_usable (cairo_xcb_connection_t *connection, cairo_bool_t success = TRUE; int depth, i, j; - pixmap = _cairo_xcb_connection_get_xid (connection); + pixmap = xcb_generate_id (connection->xcb_connection); for (depth = 1, i = 0; depth <= 32; depth++) { if (missing & DEPTH_MASK(depth)) { @@ -275,8 +275,6 @@ pixmap_depths_usable (cairo_xcb_connection_t *connection, free (create_error); } - _cairo_xcb_connection_put_xid (connection, pixmap); - return success; } @@ -462,10 +460,9 @@ can_use_shm (cairo_xcb_connection_t *connection) return FALSE; } - shmseg = _cairo_xcb_connection_get_xid (connection); + shmseg = xcb_generate_id (connection->xcb_connection); cookie[0] = xcb_shm_attach_checked (c, shmseg, shmid, FALSE); cookie[1] = xcb_shm_detach_checked (c, shmseg); - _cairo_xcb_connection_put_xid (connection, shmseg); error = xcb_request_check (c, cookie[0]); if (error != NULL) @@ -586,8 +583,6 @@ _device_destroy (void *device) #endif _cairo_freepool_fini (&connection->shm_info_freelist); - _cairo_freepool_fini (&connection->xid_pool); - CAIRO_MUTEX_FINI (connection->shm_mutex); CAIRO_MUTEX_FINI (connection->screens_mutex); @@ -662,10 +657,6 @@ _cairo_xcb_connection_get (xcb_connection_t *xcb_connection) goto unlock; } - cairo_list_init (&connection->free_xids); - _cairo_freepool_init (&connection->xid_pool, - sizeof (cairo_xcb_xid_t)); - cairo_list_init (&connection->shm_pools); cairo_list_init (&connection->shm_pending); _cairo_freepool_init (&connection->shm_info_freelist, @@ -766,43 +757,6 @@ _cairo_xcb_connection_get_xrender_format_for_visual (cairo_xcb_connection_t *con return format ? format->xrender_format : XCB_NONE; } -void -_cairo_xcb_connection_put_xid (cairo_xcb_connection_t *connection, - uint32_t xid) -{ - cairo_xcb_xid_t *cache; - - assert (CAIRO_MUTEX_IS_LOCKED (connection->device.mutex)); - cache = _cairo_freepool_alloc (&connection->xid_pool); - if (likely (cache != NULL)) { - cache->xid = xid; - cairo_list_add (&cache->link, &connection->free_xids); - } -} - -uint32_t -_cairo_xcb_connection_get_xid (cairo_xcb_connection_t *connection) -{ - uint32_t xid; - - assert (CAIRO_MUTEX_IS_LOCKED (connection->device.mutex)); - if (! cairo_list_is_empty (&connection->free_xids)) { - cairo_xcb_xid_t *cache; - - cache = cairo_list_first_entry (&connection->free_xids, - cairo_xcb_xid_t, - link); - xid = cache->xid; - - cairo_list_del (&cache->link); - _cairo_freepool_free (&connection->xid_pool, cache); - } else { - xid = xcb_generate_id (connection->xcb_connection); - } - - return xid; -} - /** * cairo_xcb_device_get_connection: * @device: a #cairo_device_t for the XCB backend @@ -942,9 +896,6 @@ cairo_xcb_device_debug_cap_xrender_version (cairo_device_t *device, connection->flags &= ~CAIRO_XCB_RENDER_HAS_GRADIENTS; } } -#if CAIRO_HAS_XLIB_XCB_FUNCTIONS -slim_hidden_def (cairo_xcb_device_debug_cap_xrender_version); -#endif /** * cairo_xcb_device_debug_set_precision: @@ -972,9 +923,6 @@ cairo_xcb_device_debug_set_precision (cairo_device_t *device, ((cairo_xcb_connection_t *) device)->force_precision = precision; } -#if CAIRO_HAS_XLIB_XCB_FUNCTIONS -slim_hidden_def (cairo_xcb_device_debug_set_precision); -#endif /** * cairo_xcb_device_debug_get_precision: @@ -1001,6 +949,3 @@ cairo_xcb_device_debug_get_precision (cairo_device_t *device) return ((cairo_xcb_connection_t *) device)->force_precision; } -#if CAIRO_HAS_XLIB_XCB_FUNCTIONS -slim_hidden_def (cairo_xcb_device_debug_get_precision); -#endif diff --git a/gfx/cairo/cairo/src/cairo-xcb-private.h b/gfx/cairo/cairo/src/cairo-xcb-private.h index bdb82617b0..89b2e78462 100644 --- a/gfx/cairo/cairo/src/cairo-xcb-private.h +++ b/gfx/cairo/cairo/src/cairo-xcb-private.h @@ -226,9 +226,6 @@ struct _cairo_xcb_connection { const xcb_query_extension_reply_t *shm; xcb_render_sub_pixel_t *subpixel_orders; - cairo_list_t free_xids; - cairo_freepool_t xid_pool; - cairo_mutex_t shm_mutex; cairo_list_t shm_pools; cairo_list_t shm_pending; @@ -323,13 +320,6 @@ _cairo_xcb_connection_acquire (cairo_xcb_connection_t *connection) return cairo_device_acquire (&connection->device); } -cairo_private uint32_t -_cairo_xcb_connection_get_xid (cairo_xcb_connection_t *connection); - -cairo_private void -_cairo_xcb_connection_put_xid (cairo_xcb_connection_t *connection, - uint32_t xid); - static inline void _cairo_xcb_connection_release (cairo_xcb_connection_t *connection) { @@ -483,10 +473,6 @@ _cairo_xcb_connection_create_pixmap (cairo_xcb_connection_t *connection, uint16_t width, uint16_t height); -cairo_private void -_cairo_xcb_connection_free_pixmap (cairo_xcb_connection_t *connection, - xcb_pixmap_t pixmap); - cairo_private xcb_gcontext_t _cairo_xcb_connection_create_gc (cairo_xcb_connection_t *connection, xcb_drawable_t drawable, @@ -494,10 +480,6 @@ _cairo_xcb_connection_create_gc (cairo_xcb_connection_t *connection, uint32_t *values); cairo_private void -_cairo_xcb_connection_free_gc (cairo_xcb_connection_t *connection, - xcb_gcontext_t gc); - -cairo_private void _cairo_xcb_connection_change_gc (cairo_xcb_connection_t *connection, xcb_gcontext_t gc, uint32_t value_mask, @@ -784,16 +766,6 @@ _cairo_xcb_connection_render_create_conical_gradient (cairo_xcb_connection_t uint32_t num_stops, xcb_render_fixed_t *stops, xcb_render_color_t *colors); -#if CAIRO_HAS_XLIB_XCB_FUNCTIONS -slim_hidden_proto (cairo_xcb_surface_create); -slim_hidden_proto (cairo_xcb_surface_create_for_bitmap); -slim_hidden_proto (cairo_xcb_surface_create_with_xrender_format); -slim_hidden_proto (cairo_xcb_surface_set_size); -slim_hidden_proto (cairo_xcb_surface_set_drawable); -slim_hidden_proto (cairo_xcb_device_debug_get_precision); -slim_hidden_proto_no_warn (cairo_xcb_device_debug_set_precision); -slim_hidden_proto_no_warn (cairo_xcb_device_debug_cap_xrender_version); -#endif cairo_private void _cairo_xcb_resources_get (cairo_xcb_screen_t *screen, diff --git a/gfx/cairo/cairo/src/cairo-xcb-screen.c b/gfx/cairo/cairo/src/cairo-xcb-screen.c index 9ee7306bb8..66a8fbb993 100644 --- a/gfx/cairo/cairo/src/cairo-xcb-screen.c +++ b/gfx/cairo/cairo/src/cairo-xcb-screen.c @@ -169,7 +169,7 @@ _cairo_xcb_screen_finish (cairo_xcb_screen_t *screen) for (i = 0; i < ARRAY_LENGTH (screen->gc); i++) { if (screen->gc_depths[i] != 0) - _cairo_xcb_connection_free_gc (screen->connection, screen->gc[i]); + xcb_free_gc (screen->connection->xcb_connection, screen->gc[i]); } _cairo_cache_fini (&screen->linear_pattern_cache); @@ -350,7 +350,7 @@ _cairo_xcb_screen_put_gc (cairo_xcb_screen_t *screen, int depth, xcb_gcontext_t if (i == ARRAY_LENGTH (screen->gc)) { /* perform random substitution to ensure fair caching over depths */ i = rand () % ARRAY_LENGTH (screen->gc); - _cairo_xcb_connection_free_gc (screen->connection, screen->gc[i]); + xcb_free_gc (screen->connection->xcb_connection, screen->gc[i]); } screen->gc[i] = gc; diff --git a/gfx/cairo/cairo/src/cairo-xcb-shm.c b/gfx/cairo/cairo/src/cairo-xcb-shm.c index 763778ab2c..5bc64a6cfa 100644 --- a/gfx/cairo/cairo/src/cairo-xcb-shm.c +++ b/gfx/cairo/cairo/src/cairo-xcb-shm.c @@ -36,6 +36,15 @@ #include "cairoint.h" +/** + * CAIRO_HAS_XCB_SHM_FUNCTIONS: + * + * Defined if Cairo has SHM functions for XCB. + * This macro can be used to conditionally compile backend-specific code. + * + * Since: 1.10 + **/ + #if CAIRO_HAS_XCB_SHM_FUNCTIONS #include "cairo-xcb-private.h" diff --git a/gfx/cairo/cairo/src/cairo-xcb-surface-core.c b/gfx/cairo/cairo/src/cairo-xcb-surface-core.c index 91c0ff995e..f9f12f04bf 100644 --- a/gfx/cairo/cairo/src/cairo-xcb-surface-core.c +++ b/gfx/cairo/cairo/src/cairo-xcb-surface-core.c @@ -66,7 +66,7 @@ _cairo_xcb_pixmap_finish (void *abstract_surface) if (unlikely (status)) return status; - _cairo_xcb_connection_free_pixmap (surface->connection, + xcb_free_pixmap (surface->connection->xcb_connection, surface->pixmap); _cairo_xcb_connection_release (surface->connection); } diff --git a/gfx/cairo/cairo/src/cairo-xcb-surface-render.c b/gfx/cairo/cairo/src/cairo-xcb-surface-render.c index 2d6d110a6a..d68cb15f0a 100644 --- a/gfx/cairo/cairo/src/cairo-xcb-surface-render.c +++ b/gfx/cairo/cairo/src/cairo-xcb-surface-render.c @@ -128,7 +128,7 @@ _cairo_xcb_picture_create (cairo_xcb_screen_t *screen, cairo_list_add (&surface->link, &screen->pictures); surface->screen = screen; - surface->picture = _cairo_xcb_connection_get_xid (screen->connection); + surface->picture = xcb_generate_id (screen->connection->xcb_connection); surface->pixman_format = pixman_format; surface->xrender_format = xrender_format; @@ -308,7 +308,7 @@ _cairo_xcb_surface_ensure_picture (cairo_xcb_surface_t *surface) values[0] = surface->precision; } - surface->picture = _cairo_xcb_connection_get_xid (surface->connection); + surface->picture = xcb_generate_id (surface->connection->xcb_connection); _cairo_xcb_connection_render_create_picture (surface->connection, surface->picture, surface->drawable, @@ -382,7 +382,7 @@ _picture_from_image (cairo_xcb_surface_t *target, 0, 0); } - _cairo_xcb_connection_free_pixmap (target->connection, pixmap); + xcb_free_pixmap (target->connection->xcb_connection, pixmap); return picture; } @@ -640,7 +640,7 @@ _solid_picture (cairo_xcb_surface_t *target, _cairo_xcb_screen_put_gc (target->screen, 32, gc); } - _cairo_xcb_connection_free_pixmap (target->connection, pixmap); + xcb_free_pixmap (target->connection->xcb_connection, pixmap); } return picture; @@ -1242,12 +1242,6 @@ _cairo_xcb_surface_picture (cairo_xcb_surface_t *target, } } #endif -#if CAIRO_HAS_GL_FUNCTIONS - else if (source->type == CAIRO_SURFACE_TYPE_GL) - { - /* pixmap from texture */ - } -#endif else if (source->type == CAIRO_SURFACE_TYPE_RECORDING) { /* We have to skip the call to attach_snapshot() because we possibly @@ -1266,7 +1260,8 @@ _cairo_xcb_surface_picture (cairo_xcb_surface_t *target, if (unlikely (status)) return (cairo_xcb_picture_t *) _cairo_surface_create_in_error (status); - if (image->format != CAIRO_FORMAT_INVALID) { + if (image->format != CAIRO_FORMAT_INVALID && + image->format < ARRAY_LENGTH (target->screen->connection->standard_formats)) { xcb_render_pictformat_t format; format = target->screen->connection->standard_formats[image->format]; @@ -3994,6 +3989,7 @@ _can_composite_glyphs (cairo_xcb_surface_t *dst, status = _cairo_scaled_glyph_lookup (scaled_font, glyphs->index, CAIRO_SCALED_GLYPH_INFO_METRICS, + NULL, /* foreground color */ &glyph); if (unlikely (status)) break; @@ -4232,7 +4228,7 @@ _cairo_xcb_scaled_font_get_glyphset_info_for_format (cairo_xcb_connection_t *c, info = &priv->glyphset_info[glyphset_index]; if (info->glyphset == XCB_NONE) { - info->glyphset = _cairo_xcb_connection_get_xid (c); + info->glyphset = xcb_generate_id (c->xcb_connection); info->xrender_format = c->standard_formats[info->format]; _cairo_xcb_connection_render_create_glyph_set (c, @@ -4399,6 +4395,7 @@ _cairo_xcb_surface_add_glyph (cairo_xcb_connection_t *connection, glyph_index, CAIRO_SCALED_GLYPH_INFO_METRICS | CAIRO_SCALED_GLYPH_INFO_SURFACE, + NULL, /* foreground color */ scaled_glyph_out); if (unlikely (status)) return status; @@ -4692,6 +4689,7 @@ _composite_glyphs (void *closure, status = _cairo_scaled_glyph_lookup (info->font, glyph_index, CAIRO_SCALED_GLYPH_INFO_METRICS, + NULL, /* foreground color */ &glyph); if (unlikely (status)) { cairo_surface_destroy (&src->base); diff --git a/gfx/cairo/cairo/src/cairo-xcb-surface.c b/gfx/cairo/cairo/src/cairo-xcb-surface.c index 1b55ec8dea..0d060898e9 100644 --- a/gfx/cairo/cairo/src/cairo-xcb-surface.c +++ b/gfx/cairo/cairo/src/cairo-xcb-surface.c @@ -50,12 +50,6 @@ #include "cairo-surface-backend-private.h" #include "cairo-compositor-private.h" -#if CAIRO_HAS_XLIB_XCB_FUNCTIONS -slim_hidden_proto (cairo_xcb_surface_create); -slim_hidden_proto (cairo_xcb_surface_create_for_bitmap); -slim_hidden_proto (cairo_xcb_surface_create_with_xrender_format); -#endif - /** * SECTION:cairo-xcb * @Title: XCB Surfaces @@ -155,7 +149,7 @@ _cairo_xcb_surface_create_similar (void *abstract_other, } if (unlikely (surface->base.status)) - _cairo_xcb_connection_free_pixmap (connection, pixmap); + xcb_free_pixmap (connection->xcb_connection, pixmap); _cairo_xcb_connection_release (connection); @@ -220,7 +214,7 @@ _cairo_xcb_surface_finish (void *abstract_surface) } if (surface->owns_pixmap) - _cairo_xcb_connection_free_pixmap (surface->connection, surface->drawable); + xcb_free_pixmap (surface->connection->xcb_connection, surface->drawable); _cairo_xcb_connection_release (surface->connection); } @@ -423,7 +417,7 @@ _get_image (cairo_xcb_surface_t *surface, pixmap, 0, 0, width, height); - _cairo_xcb_connection_free_pixmap (connection, pixmap); + xcb_free_pixmap (connection->xcb_connection, pixmap); } if (unlikely (reply == NULL)) { @@ -1237,9 +1231,6 @@ cairo_xcb_surface_create (xcb_connection_t *connection, xrender_format, width, height); } -#if CAIRO_HAS_XLIB_XCB_FUNCTIONS -slim_hidden_def (cairo_xcb_surface_create); -#endif /** * cairo_xcb_surface_create_for_bitmap: @@ -1288,9 +1279,6 @@ cairo_xcb_surface_create_for_bitmap (xcb_connection_t *connection, cairo_xcb_screen->connection->standard_formats[CAIRO_FORMAT_A1], width, height); } -#if CAIRO_HAS_XLIB_XCB_FUNCTIONS -slim_hidden_def (cairo_xcb_surface_create_for_bitmap); -#endif /** * cairo_xcb_surface_create_with_xrender_format: @@ -1380,9 +1368,6 @@ cairo_xcb_surface_create_with_xrender_format (xcb_connection_t *connection, format->id, width, height); } -#if CAIRO_HAS_XLIB_XCB_FUNCTIONS -slim_hidden_def (cairo_xcb_surface_create_with_xrender_format); -#endif /* This does the necessary fixup when a surface's drawable or size changed. */ static void @@ -1452,9 +1437,6 @@ cairo_xcb_surface_set_size (cairo_surface_t *abstract_surface, surface->width = width; surface->height = height; } -#if CAIRO_HAS_XLIB_XCB_FUNCTIONS -slim_hidden_def (cairo_xcb_surface_set_size); -#endif /** * cairo_xcb_surface_set_drawable: @@ -1527,6 +1509,3 @@ cairo_xcb_surface_set_drawable (cairo_surface_t *abstract_surface, surface->width = width; surface->height = height; } -#if CAIRO_HAS_XLIB_XCB_FUNCTIONS -slim_hidden_def (cairo_xcb_surface_set_drawable); -#endif diff --git a/gfx/cairo/cairo/src/cairo-xlib-render-compositor.c b/gfx/cairo/cairo/src/cairo-xlib-render-compositor.c index bf8d20546b..c872f56807 100644 --- a/gfx/cairo/cairo/src/cairo-xlib-render-compositor.c +++ b/gfx/cairo/cairo/src/cairo-xlib-render-compositor.c @@ -1204,6 +1204,7 @@ _cairo_xlib_surface_add_glyph (cairo_xlib_display_t *display, glyph_index, CAIRO_SCALED_GLYPH_INFO_METRICS | CAIRO_SCALED_GLYPH_INFO_SURFACE, + NULL, /* foreground color */ pscaled_glyph); if (unlikely (status)) return status; @@ -1619,6 +1620,7 @@ composite_glyphs (void *surface, status = _cairo_scaled_glyph_lookup (info->font, glyphs[i].index, CAIRO_SCALED_GLYPH_INFO_METRICS, + NULL, /* foreground color */ &glyph); if (unlikely (status)) return status; diff --git a/gfx/cairo/cairo/src/cairo-xlib-surface.c b/gfx/cairo/cairo/src/cairo-xlib-surface.c index b37b21badb..84d536209b 100644 --- a/gfx/cairo/cairo/src/cairo-xlib-surface.c +++ b/gfx/cairo/cairo/src/cairo-xlib-surface.c @@ -47,6 +47,15 @@ #include "cairoint.h" +/** + * CAIRO_HAS_XLIB_XCB_FUNCTIONS: + * + * Defined if Cairo has support for XCB integration with Xlib. + * This macro can be used to conditionally compile backend-specific code. + * + * Since: 1.10 + **/ + #if !CAIRO_HAS_XLIB_XCB_FUNCTIONS #include "cairo-xlib-private.h" diff --git a/gfx/cairo/cairo/src/cairo-xml-surface.c b/gfx/cairo/cairo/src/cairo-xml-surface.c deleted file mode 100644 index 43cb6dddfa..0000000000 --- a/gfx/cairo/cairo/src/cairo-xml-surface.c +++ /dev/null @@ -1,1210 +0,0 @@ -/* -*- Mode: c; tab-width: 8; c-basic-offset: 4; indent-tabs-mode: t; -*- */ -/* cairo - a vector graphics library with display and print output - * - * Copyright © 2009 Chris Wilson - * - * 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., 51 Franklin Street, Suite 500, Boston, MA 02110-1335, 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 Chris Wilson. - * - * Contributor(s): - * Chris Wilson <chris@chris-wilson.co.uk> - */ - -/* This surface is intended to produce a verbose, hierarchical, DAG XML file - * representing a single surface. It is intended to be used by debuggers, - * such as cairo-sphinx, or by application test-suites that want a log of - * operations. - */ - -#include "cairoint.h" - -#include "cairo-xml.h" - -#include "cairo-clip-private.h" -#include "cairo-device-private.h" -#include "cairo-default-context-private.h" -#include "cairo-image-surface-private.h" -#include "cairo-error-private.h" -#include "cairo-output-stream-private.h" -#include "cairo-recording-surface-inline.h" - -#define static cairo_warn static - -typedef struct _cairo_xml_surface cairo_xml_surface_t; - -typedef struct _cairo_xml { - cairo_device_t base; - - cairo_output_stream_t *stream; - int indent; -} cairo_xml_t; - -struct _cairo_xml_surface { - cairo_surface_t base; - - double width, height; -}; - -slim_hidden_proto (cairo_xml_for_recording_surface); - -static const cairo_surface_backend_t _cairo_xml_surface_backend; - -static const char * -_operator_to_string (cairo_operator_t op) -{ - static const char *names[] = { - "CLEAR", /* CAIRO_OPERATOR_CLEAR */ - - "SOURCE", /* CAIRO_OPERATOR_SOURCE */ - "OVER", /* CAIRO_OPERATOR_OVER */ - "IN", /* CAIRO_OPERATOR_IN */ - "OUT", /* CAIRO_OPERATOR_OUT */ - "ATOP", /* CAIRO_OPERATOR_ATOP */ - - "DEST", /* CAIRO_OPERATOR_DEST */ - "DEST_OVER", /* CAIRO_OPERATOR_DEST_OVER */ - "DEST_IN", /* CAIRO_OPERATOR_DEST_IN */ - "DEST_OUT", /* CAIRO_OPERATOR_DEST_OUT */ - "DEST_ATOP", /* CAIRO_OPERATOR_DEST_ATOP */ - - "XOR", /* CAIRO_OPERATOR_XOR */ - "ADD", /* CAIRO_OPERATOR_ADD */ - "SATURATE", /* CAIRO_OPERATOR_SATURATE */ - - "MULTIPLY", /* CAIRO_OPERATOR_MULTIPLY */ - "SCREEN", /* CAIRO_OPERATOR_SCREEN */ - "OVERLAY", /* CAIRO_OPERATOR_OVERLAY */ - "DARKEN", /* CAIRO_OPERATOR_DARKEN */ - "LIGHTEN", /* CAIRO_OPERATOR_LIGHTEN */ - "DODGE", /* CAIRO_OPERATOR_COLOR_DODGE */ - "BURN", /* CAIRO_OPERATOR_COLOR_BURN */ - "HARD_LIGHT", /* CAIRO_OPERATOR_HARD_LIGHT */ - "SOFT_LIGHT", /* CAIRO_OPERATOR_SOFT_LIGHT */ - "DIFFERENCE", /* CAIRO_OPERATOR_DIFFERENCE */ - "EXCLUSION", /* CAIRO_OPERATOR_EXCLUSION */ - "HSL_HUE", /* CAIRO_OPERATOR_HSL_HUE */ - "HSL_SATURATION", /* CAIRO_OPERATOR_HSL_SATURATION */ - "HSL_COLOR", /* CAIRO_OPERATOR_HSL_COLOR */ - "HSL_LUMINOSITY" /* CAIRO_OPERATOR_HSL_LUMINOSITY */ - }; - assert (op < ARRAY_LENGTH (names)); - return names[op]; -} - -static const char * -_extend_to_string (cairo_extend_t extend) -{ - static const char *names[] = { - "EXTEND_NONE", /* CAIRO_EXTEND_NONE */ - "EXTEND_REPEAT", /* CAIRO_EXTEND_REPEAT */ - "EXTEND_REFLECT", /* CAIRO_EXTEND_REFLECT */ - "EXTEND_PAD" /* CAIRO_EXTEND_PAD */ - }; - assert (extend < ARRAY_LENGTH (names)); - return names[extend]; -} - -static const char * -_filter_to_string (cairo_filter_t filter) -{ - static const char *names[] = { - "FILTER_FAST", /* CAIRO_FILTER_FAST */ - "FILTER_GOOD", /* CAIRO_FILTER_GOOD */ - "FILTER_BEST", /* CAIRO_FILTER_BEST */ - "FILTER_NEAREST", /* CAIRO_FILTER_NEAREST */ - "FILTER_BILINEAR", /* CAIRO_FILTER_BILINEAR */ - "FILTER_GAUSSIAN", /* CAIRO_FILTER_GAUSSIAN */ - }; - assert (filter < ARRAY_LENGTH (names)); - return names[filter]; -} - -static const char * -_fill_rule_to_string (cairo_fill_rule_t rule) -{ - static const char *names[] = { - "WINDING", /* CAIRO_FILL_RULE_WINDING */ - "EVEN_ODD" /* CAIRO_FILL_RILE_EVEN_ODD */ - }; - assert (rule < ARRAY_LENGTH (names)); - return names[rule]; -} - -static const char * -_antialias_to_string (cairo_antialias_t antialias) -{ - static const char *names[] = { - "DEFAULT", /* CAIRO_ANTIALIAS_DEFAULT */ - "NONE", /* CAIRO_ANTIALIAS_NONE */ - "GRAY", /* CAIRO_ANTIALIAS_GRAY */ - "SUBPIXEL", /* CAIRO_ANTIALIAS_SUBPIXEL */ - "FAST", /* CAIRO_ANTIALIAS_FAST */ - "GOOD", /* CAIRO_ANTIALIAS_GOOD */ - "BEST", /* CAIRO_ANTIALIAS_BEST */ - }; - assert (antialias < ARRAY_LENGTH (names)); - return names[antialias]; -} - -static const char * -_line_cap_to_string (cairo_line_cap_t line_cap) -{ - static const char *names[] = { - "LINE_CAP_BUTT", /* CAIRO_LINE_CAP_BUTT */ - "LINE_CAP_ROUND", /* CAIRO_LINE_CAP_ROUND */ - "LINE_CAP_SQUARE" /* CAIRO_LINE_CAP_SQUARE */ - }; - assert (line_cap < ARRAY_LENGTH (names)); - return names[line_cap]; -} - -static const char * -_line_join_to_string (cairo_line_join_t line_join) -{ - static const char *names[] = { - "LINE_JOIN_MITER", /* CAIRO_LINE_JOIN_MITER */ - "LINE_JOIN_ROUND", /* CAIRO_LINE_JOIN_ROUND */ - "LINE_JOIN_BEVEL", /* CAIRO_LINE_JOIN_BEVEL */ - }; - assert (line_join < ARRAY_LENGTH (names)); - return names[line_join]; -} - -static const char * -_content_to_string (cairo_content_t content) -{ - switch (content) { - case CAIRO_CONTENT_ALPHA: return "ALPHA"; - case CAIRO_CONTENT_COLOR: return "COLOR"; - default: - case CAIRO_CONTENT_COLOR_ALPHA: return "COLOR_ALPHA"; - } -} - -static const char * -_format_to_string (cairo_format_t format) -{ - switch (format) { - case CAIRO_FORMAT_ARGB32: return "ARGB32"; - case CAIRO_FORMAT_RGB30: return "RGB30"; - case CAIRO_FORMAT_RGB24: return "RGB24"; - case CAIRO_FORMAT_RGB16_565: return "RGB16_565"; - case CAIRO_FORMAT_A8: return "A8"; - case CAIRO_FORMAT_A1: return "A1"; - case CAIRO_FORMAT_INVALID: return "INVALID"; - } - ASSERT_NOT_REACHED; - return "INVALID"; -} - -static cairo_status_t -_device_flush (void *abstract_device) -{ - cairo_xml_t *xml = abstract_device; - cairo_status_t status; - - status = _cairo_output_stream_flush (xml->stream); - - return status; -} - -static void -_device_destroy (void *abstract_device) -{ - cairo_xml_t *xml = abstract_device; - cairo_status_t status; - - status = _cairo_output_stream_destroy (xml->stream); - - free (xml); -} - -static const cairo_device_backend_t _cairo_xml_device_backend = { - CAIRO_DEVICE_TYPE_XML, - - NULL, NULL, /* lock, unlock */ - - _device_flush, - NULL, /* finish */ - _device_destroy -}; - -static cairo_device_t * -_cairo_xml_create_internal (cairo_output_stream_t *stream) -{ - cairo_xml_t *xml; - - xml = _cairo_malloc (sizeof (cairo_xml_t)); - if (unlikely (xml == NULL)) - return _cairo_device_create_in_error (CAIRO_STATUS_NO_MEMORY); - - memset (xml, 0, sizeof (cairo_xml_t)); - - _cairo_device_init (&xml->base, &_cairo_xml_device_backend); - - xml->indent = 0; - xml->stream = stream; - - return &xml->base; -} - -static void -_cairo_xml_indent (cairo_xml_t *xml, int indent) -{ - xml->indent += indent; - assert (xml->indent >= 0); -} - -static void CAIRO_PRINTF_FORMAT (2, 3) -_cairo_xml_printf (cairo_xml_t *xml, const char *fmt, ...) -{ - va_list ap; - char indent[80]; - int len; - - len = MIN (xml->indent, ARRAY_LENGTH (indent)); - memset (indent, ' ', len); - _cairo_output_stream_write (xml->stream, indent, len); - - va_start (ap, fmt); - _cairo_output_stream_vprintf (xml->stream, fmt, ap); - va_end (ap); - - _cairo_output_stream_write (xml->stream, "\n", 1); -} - -static void CAIRO_PRINTF_FORMAT (2, 3) -_cairo_xml_printf_start (cairo_xml_t *xml, const char *fmt, ...) -{ - char indent[80]; - int len; - - len = MIN (xml->indent, ARRAY_LENGTH (indent)); - memset (indent, ' ', len); - _cairo_output_stream_write (xml->stream, indent, len); - - if (fmt != NULL) { - va_list ap; - - va_start (ap, fmt); - _cairo_output_stream_vprintf (xml->stream, fmt, ap); - va_end (ap); - } -} - -static void CAIRO_PRINTF_FORMAT (2, 3) -_cairo_xml_printf_continue (cairo_xml_t *xml, const char *fmt, ...) -{ - va_list ap; - - va_start (ap, fmt); - _cairo_output_stream_vprintf (xml->stream, fmt, ap); - va_end (ap); -} - -static void CAIRO_PRINTF_FORMAT (2, 3) -_cairo_xml_printf_end (cairo_xml_t *xml, const char *fmt, ...) -{ - if (fmt != NULL) { - va_list ap; - - va_start (ap, fmt); - _cairo_output_stream_vprintf (xml->stream, fmt, ap); - va_end (ap); - } - - _cairo_output_stream_write (xml->stream, "\n", 1); -} - -static cairo_surface_t * -_cairo_xml_surface_create_similar (void *abstract_surface, - cairo_content_t content, - int width, - int height) -{ - cairo_rectangle_t extents; - - extents.x = extents.y = 0; - extents.width = width; - extents.height = height; - - return cairo_recording_surface_create (content, &extents); -} - -static cairo_bool_t -_cairo_xml_surface_get_extents (void *abstract_surface, - cairo_rectangle_int_t *rectangle) -{ - cairo_xml_surface_t *surface = abstract_surface; - - if (surface->width < 0 || surface->height < 0) - return FALSE; - - rectangle->x = 0; - rectangle->y = 0; - rectangle->width = surface->width; - rectangle->height = surface->height; - - return TRUE; -} - -static cairo_status_t -_cairo_xml_move_to (void *closure, - const cairo_point_t *p1) -{ - _cairo_xml_printf_continue (closure, " %f %f m", - _cairo_fixed_to_double (p1->x), - _cairo_fixed_to_double (p1->y)); - - return CAIRO_STATUS_SUCCESS; -} - -static cairo_status_t -_cairo_xml_line_to (void *closure, - const cairo_point_t *p1) -{ - _cairo_xml_printf_continue (closure, " %f %f l", - _cairo_fixed_to_double (p1->x), - _cairo_fixed_to_double (p1->y)); - - return CAIRO_STATUS_SUCCESS; -} - -static cairo_status_t -_cairo_xml_curve_to (void *closure, - const cairo_point_t *p1, - const cairo_point_t *p2, - const cairo_point_t *p3) -{ - _cairo_xml_printf_continue (closure, " %f %f %f %f %f %f c", - _cairo_fixed_to_double (p1->x), - _cairo_fixed_to_double (p1->y), - _cairo_fixed_to_double (p2->x), - _cairo_fixed_to_double (p2->y), - _cairo_fixed_to_double (p3->x), - _cairo_fixed_to_double (p3->y)); - - return CAIRO_STATUS_SUCCESS; -} - -static cairo_status_t -_cairo_xml_close_path (void *closure) -{ - _cairo_xml_printf_continue (closure, " h"); - - return CAIRO_STATUS_SUCCESS; -} - -static void -_cairo_xml_emit_path (cairo_xml_t *xml, - const cairo_path_fixed_t *path) -{ - cairo_status_t status; - - _cairo_xml_printf_start (xml, "<path>"); - status = _cairo_path_fixed_interpret (path, - _cairo_xml_move_to, - _cairo_xml_line_to, - _cairo_xml_curve_to, - _cairo_xml_close_path, - xml); - assert (status == CAIRO_STATUS_SUCCESS); - _cairo_xml_printf_end (xml, "</path>"); -} - -static void -_cairo_xml_emit_string (cairo_xml_t *xml, - const char *node, - const char *data) -{ - _cairo_xml_printf (xml, "<%s>%s</%s>", node, data, node); -} - -static void -_cairo_xml_emit_double (cairo_xml_t *xml, - const char *node, - double data) -{ - _cairo_xml_printf (xml, "<%s>%f</%s>", node, data, node); -} - -static cairo_xml_t * -to_xml (cairo_xml_surface_t *surface) -{ - return (cairo_xml_t *) surface->base.device; -} - -static cairo_status_t -_cairo_xml_surface_emit_clip_boxes (cairo_xml_surface_t *surface, - const cairo_clip_t *clip) -{ - cairo_box_t *box; - cairo_xml_t *xml; - int n; - - if (clip->num_boxes == 0) - return CAIRO_STATUS_SUCCESS; - - /* skip the trivial clip covering the surface extents */ - if (surface->width >= 0 && surface->height >= 0 && clip->num_boxes == 1) { - box = &clip->boxes[0]; - if (box->p1.x <= 0 && box->p1.y <= 0 && - box->p2.x - box->p1.x >= _cairo_fixed_from_double (surface->width) && - box->p2.y - box->p1.y >= _cairo_fixed_from_double (surface->height)) - { - return CAIRO_STATUS_SUCCESS; - } - } - - xml = to_xml (surface); - - _cairo_xml_printf (xml, "<clip>"); - _cairo_xml_indent (xml, 2); - - _cairo_xml_printf (xml, "<path>"); - _cairo_xml_indent (xml, 2); - for (n = 0; n < clip->num_boxes; n++) { - box = &clip->boxes[n]; - - _cairo_xml_printf_start (xml, "%f %f m", - _cairo_fixed_to_double (box->p1.x), - _cairo_fixed_to_double (box->p1.y)); - _cairo_xml_printf_continue (xml, " %f %f l", - _cairo_fixed_to_double (box->p2.x), - _cairo_fixed_to_double (box->p1.y)); - _cairo_xml_printf_continue (xml, " %f %f l", - _cairo_fixed_to_double (box->p2.x), - _cairo_fixed_to_double (box->p2.y)); - _cairo_xml_printf_continue (xml, " %f %f l", - _cairo_fixed_to_double (box->p1.x), - _cairo_fixed_to_double (box->p2.y)); - _cairo_xml_printf_end (xml, " h"); - } - _cairo_xml_indent (xml, -2); - _cairo_xml_printf (xml, "</path>"); - _cairo_xml_emit_double (xml, "tolerance", 1.0); - _cairo_xml_emit_string (xml, "antialias", - _antialias_to_string (CAIRO_ANTIALIAS_NONE)); - _cairo_xml_emit_string (xml, "fill-rule", - _fill_rule_to_string (CAIRO_FILL_RULE_WINDING)); - - _cairo_xml_indent (xml, -2); - _cairo_xml_printf (xml, "</clip>"); - - return CAIRO_STATUS_SUCCESS; -} - -static cairo_status_t -_cairo_xml_surface_emit_clip_path (cairo_xml_surface_t *surface, - const cairo_clip_path_t *clip_path) -{ - cairo_box_t box; - cairo_status_t status; - cairo_xml_t *xml; - - if (clip_path == NULL) - return CAIRO_STATUS_SUCCESS; - - status = _cairo_xml_surface_emit_clip_path (surface, clip_path->prev); - if (unlikely (status)) - return status; - - /* skip the trivial clip covering the surface extents */ - if (surface->width >= 0 && surface->height >= 0 && - _cairo_path_fixed_is_box (&clip_path->path, &box)) - { - if (box.p1.x <= 0 && box.p1.y <= 0 && - box.p2.x - box.p1.x >= _cairo_fixed_from_double (surface->width) && - box.p2.y - box.p1.y >= _cairo_fixed_from_double (surface->height)) - { - return CAIRO_STATUS_SUCCESS; - } - } - - xml = to_xml (surface); - - _cairo_xml_printf_start (xml, "<clip>"); - _cairo_xml_indent (xml, 2); - - _cairo_xml_emit_path (xml, &clip_path->path); - _cairo_xml_emit_double (xml, "tolerance", clip_path->tolerance); - _cairo_xml_emit_string (xml, "antialias", - _antialias_to_string (clip_path->antialias)); - _cairo_xml_emit_string (xml, "fill-rule", - _fill_rule_to_string (clip_path->fill_rule)); - - _cairo_xml_indent (xml, -2); - _cairo_xml_printf_end (xml, "</clip>"); - - return CAIRO_STATUS_SUCCESS; -} - -static cairo_status_t -_cairo_xml_surface_emit_clip (cairo_xml_surface_t *surface, - const cairo_clip_t *clip) -{ - cairo_status_t status; - - if (clip == NULL) - return CAIRO_STATUS_SUCCESS; - - status = _cairo_xml_surface_emit_clip_boxes (surface, clip); - if (unlikely (status)) - return status; - - return _cairo_xml_surface_emit_clip_path (surface, clip->path); -} - -static cairo_status_t -_cairo_xml_emit_solid (cairo_xml_t *xml, - const cairo_solid_pattern_t *solid) -{ - _cairo_xml_printf (xml, "<solid>%f %f %f %f</solid>", - solid->color.red, - solid->color.green, - solid->color.blue, - solid->color.alpha); - return CAIRO_STATUS_SUCCESS; -} - -static void -_cairo_xml_emit_matrix (cairo_xml_t *xml, - const cairo_matrix_t *matrix) -{ - if (! _cairo_matrix_is_identity (matrix)) { - _cairo_xml_printf (xml, "<matrix>%f %f %f %f %f %f</matrix>", - matrix->xx, matrix->yx, - matrix->xy, matrix->yy, - matrix->x0, matrix->y0); - } -} - -static void -_cairo_xml_emit_gradient (cairo_xml_t *xml, - const cairo_gradient_pattern_t *gradient) -{ - unsigned int i; - - for (i = 0; i < gradient->n_stops; i++) { - _cairo_xml_printf (xml, - "<color-stop>%f %f %f %f %f</color-stop>", - gradient->stops[i].offset, - gradient->stops[i].color.red, - gradient->stops[i].color.green, - gradient->stops[i].color.blue, - gradient->stops[i].color.alpha); - } -} - -static cairo_status_t -_cairo_xml_emit_linear (cairo_xml_t *xml, - const cairo_linear_pattern_t *linear) -{ - _cairo_xml_printf (xml, - "<linear x1='%f' y1='%f' x2='%f' y2='%f'>", - linear->pd1.x, linear->pd1.y, - linear->pd2.x, linear->pd2.y); - _cairo_xml_indent (xml, 2); - _cairo_xml_emit_gradient (xml, &linear->base); - _cairo_xml_indent (xml, -2); - _cairo_xml_printf (xml, "</linear>"); - return CAIRO_STATUS_SUCCESS; -} - -static cairo_status_t -_cairo_xml_emit_radial (cairo_xml_t *xml, - const cairo_radial_pattern_t *radial) -{ - _cairo_xml_printf (xml, - "<radial x1='%f' y1='%f' r1='%f' x2='%f' y2='%f' r2='%f'>", - radial->cd1.center.x, radial->cd1.center.y, radial->cd1.radius, - radial->cd2.center.x, radial->cd2.center.y, radial->cd2.radius); - _cairo_xml_indent (xml, 2); - _cairo_xml_emit_gradient (xml, &radial->base); - _cairo_xml_indent (xml, -2); - _cairo_xml_printf (xml, "</radial>"); - return CAIRO_STATUS_SUCCESS; -} - -static cairo_status_t -_write_func (void *closure, const unsigned char *data, unsigned len) -{ - _cairo_output_stream_write (closure, data, len); - return CAIRO_STATUS_SUCCESS; -} - -static cairo_status_t -_cairo_xml_emit_image (cairo_xml_t *xml, - cairo_image_surface_t *image) -{ - cairo_output_stream_t *stream; - cairo_status_t status; - - _cairo_xml_printf_start (xml, - "<image width='%d' height='%d' format='%s'>", - image->width, image->height, - _format_to_string (image->format)); - - stream = _cairo_base64_stream_create (xml->stream); - status = cairo_surface_write_to_png_stream (&image->base, - _write_func, stream); - assert (status == CAIRO_STATUS_SUCCESS); - status = _cairo_output_stream_destroy (stream); - if (unlikely (status)) - return status; - - _cairo_xml_printf_end (xml, "</image>"); - - return CAIRO_STATUS_SUCCESS; -} - -static cairo_status_t -_cairo_xml_emit_surface (cairo_xml_t *xml, - const cairo_surface_pattern_t *pattern) -{ - cairo_surface_t *source = pattern->surface; - cairo_status_t status; - - if (_cairo_surface_is_recording (source)) { - status = cairo_xml_for_recording_surface (&xml->base, source); - } else { - cairo_image_surface_t *image; - void *image_extra; - - status = _cairo_surface_acquire_source_image (source, - &image, &image_extra); - if (unlikely (status)) - return status; - - status = _cairo_xml_emit_image (xml, image); - - _cairo_surface_release_source_image (source, image, image_extra); - } - - return status; -} - -static cairo_status_t -_cairo_xml_emit_pattern (cairo_xml_t *xml, - const char *source_or_mask, - const cairo_pattern_t *pattern) -{ - cairo_status_t status; - - _cairo_xml_printf (xml, "<%s-pattern>", source_or_mask); - _cairo_xml_indent (xml, 2); - - switch (pattern->type) { - case CAIRO_PATTERN_TYPE_SOLID: - status = _cairo_xml_emit_solid (xml, (cairo_solid_pattern_t *) pattern); - break; - case CAIRO_PATTERN_TYPE_LINEAR: - status = _cairo_xml_emit_linear (xml, (cairo_linear_pattern_t *) pattern); - break; - case CAIRO_PATTERN_TYPE_RADIAL: - status = _cairo_xml_emit_radial (xml, (cairo_radial_pattern_t *) pattern); - break; - case CAIRO_PATTERN_TYPE_SURFACE: - status = _cairo_xml_emit_surface (xml, (cairo_surface_pattern_t *) pattern); - break; - default: - ASSERT_NOT_REACHED; - status = CAIRO_INT_STATUS_UNSUPPORTED; - break; - } - - if (pattern->type != CAIRO_PATTERN_TYPE_SOLID) { - _cairo_xml_emit_matrix (xml, &pattern->matrix); - _cairo_xml_printf (xml, - "<extend>%s</extend>", - _extend_to_string (pattern->extend)); - _cairo_xml_printf (xml, - "<filter>%s</filter>", - _filter_to_string (pattern->filter)); - } - - _cairo_xml_indent (xml, -2); - _cairo_xml_printf (xml, "</%s-pattern>", source_or_mask); - - return status; -} - -static cairo_int_status_t -_cairo_xml_surface_paint (void *abstract_surface, - cairo_operator_t op, - const cairo_pattern_t *source, - const cairo_clip_t *clip) -{ - cairo_xml_surface_t *surface = abstract_surface; - cairo_xml_t *xml = to_xml (surface); - cairo_status_t status; - - _cairo_xml_printf (xml, "<paint>"); - _cairo_xml_indent (xml, 2); - - _cairo_xml_emit_string (xml, "operator", _operator_to_string (op)); - - status = _cairo_xml_surface_emit_clip (surface, clip); - if (unlikely (status)) - return status; - - status = _cairo_xml_emit_pattern (xml, "source", source); - if (unlikely (status)) - return status; - - _cairo_xml_indent (xml, -2); - _cairo_xml_printf (xml, "</paint>"); - - return CAIRO_STATUS_SUCCESS; -} - -static cairo_int_status_t -_cairo_xml_surface_mask (void *abstract_surface, - cairo_operator_t op, - const cairo_pattern_t *source, - const cairo_pattern_t *mask, - const cairo_clip_t *clip) -{ - cairo_xml_surface_t *surface = abstract_surface; - cairo_xml_t *xml = to_xml (surface); - cairo_status_t status; - - _cairo_xml_printf (xml, "<mask>"); - _cairo_xml_indent (xml, 2); - - _cairo_xml_emit_string (xml, "operator", _operator_to_string (op)); - - status = _cairo_xml_surface_emit_clip (surface, clip); - if (unlikely (status)) - return status; - - status = _cairo_xml_emit_pattern (xml, "source", source); - if (unlikely (status)) - return status; - - status = _cairo_xml_emit_pattern (xml, "mask", mask); - if (unlikely (status)) - return status; - - _cairo_xml_indent (xml, -2); - _cairo_xml_printf (xml, "</mask>"); - - return CAIRO_STATUS_SUCCESS; -} - -static cairo_int_status_t -_cairo_xml_surface_stroke (void *abstract_surface, - cairo_operator_t op, - const cairo_pattern_t *source, - const cairo_path_fixed_t *path, - const cairo_stroke_style_t *style, - const cairo_matrix_t *ctm, - const cairo_matrix_t *ctm_inverse, - double tolerance, - cairo_antialias_t antialias, - const cairo_clip_t *clip) -{ - cairo_xml_surface_t *surface = abstract_surface; - cairo_xml_t *xml = to_xml (surface); - cairo_status_t status; - - _cairo_xml_printf (xml, "<stroke>"); - _cairo_xml_indent (xml, 2); - - _cairo_xml_emit_string (xml, "operator", _operator_to_string (op)); - _cairo_xml_emit_double (xml, "line-width", style->line_width); - _cairo_xml_emit_double (xml, "miter-limit", style->miter_limit); - _cairo_xml_emit_string (xml, "line-cap", _line_cap_to_string (style->line_cap)); - _cairo_xml_emit_string (xml, "line-join", _line_join_to_string (style->line_join)); - - status = _cairo_xml_surface_emit_clip (surface, clip); - if (unlikely (status)) - return status; - - status = _cairo_xml_emit_pattern (xml, "source", source); - if (unlikely (status)) - return status; - - if (style->num_dashes) { - unsigned int i; - - _cairo_xml_printf_start (xml, "<dash offset='%f'>", - style->dash_offset); - for (i = 0; i < style->num_dashes; i++) - _cairo_xml_printf_continue (xml, "%f ", style->dash[i]); - - _cairo_xml_printf_end (xml, "</dash>"); - } - - _cairo_xml_emit_path (xml, path); - _cairo_xml_emit_double (xml, "tolerance", tolerance); - _cairo_xml_emit_string (xml, "antialias", _antialias_to_string (antialias)); - - _cairo_xml_emit_matrix (xml, ctm); - - _cairo_xml_indent (xml, -2); - _cairo_xml_printf (xml, "</stroke>"); - - return CAIRO_STATUS_SUCCESS; -} - -static cairo_int_status_t -_cairo_xml_surface_fill (void *abstract_surface, - cairo_operator_t op, - const cairo_pattern_t *source, - const cairo_path_fixed_t*path, - cairo_fill_rule_t fill_rule, - double tolerance, - cairo_antialias_t antialias, - const cairo_clip_t *clip) -{ - cairo_xml_surface_t *surface = abstract_surface; - cairo_xml_t *xml = to_xml (surface); - cairo_status_t status; - - _cairo_xml_printf (xml, "<fill>"); - _cairo_xml_indent (xml, 2); - - _cairo_xml_emit_string (xml, "operator", _operator_to_string (op)); - - status = _cairo_xml_surface_emit_clip (surface, clip); - if (unlikely (status)) - return status; - - status = _cairo_xml_emit_pattern (xml, "source", source); - if (unlikely (status)) - return status; - - _cairo_xml_emit_path (xml, path); - _cairo_xml_emit_double (xml, "tolerance", tolerance); - _cairo_xml_emit_string (xml, "antialias", _antialias_to_string (antialias)); - _cairo_xml_emit_string (xml, "fill-rule", _fill_rule_to_string (fill_rule)); - - _cairo_xml_indent (xml, -2); - _cairo_xml_printf (xml, "</fill>"); - - return CAIRO_STATUS_SUCCESS; -} - -#if CAIRO_HAS_FT_FONT -#include "cairo-ft-private.h" -static cairo_status_t -_cairo_xml_emit_type42_font (cairo_xml_t *xml, - cairo_scaled_font_t *scaled_font) -{ - const cairo_scaled_font_backend_t *backend; - cairo_output_stream_t *base64_stream; - cairo_output_stream_t *zlib_stream; - cairo_status_t status, status2; - unsigned long size; - uint32_t len; - uint8_t *buf; - - backend = scaled_font->backend; - if (backend->load_truetype_table == NULL) - return CAIRO_INT_STATUS_UNSUPPORTED; - - size = 0; - status = backend->load_truetype_table (scaled_font, 0, 0, NULL, &size); - if (unlikely (status)) - return status; - - buf = _cairo_malloc (size); - if (unlikely (buf == NULL)) - return _cairo_error (CAIRO_STATUS_NO_MEMORY); - - status = backend->load_truetype_table (scaled_font, 0, 0, buf, &size); - if (unlikely (status)) { - free (buf); - return status; - } - - _cairo_xml_printf_start (xml, "<font type='42' flags='%d' index='0'>", - _cairo_ft_scaled_font_get_load_flags (scaled_font)); - - - base64_stream = _cairo_base64_stream_create (xml->stream); - len = size; - _cairo_output_stream_write (base64_stream, &len, sizeof (len)); - - zlib_stream = _cairo_deflate_stream_create (base64_stream); - - _cairo_output_stream_write (zlib_stream, buf, size); - free (buf); - - status2 = _cairo_output_stream_destroy (zlib_stream); - if (status == CAIRO_STATUS_SUCCESS) - status = status2; - - status2 = _cairo_output_stream_destroy (base64_stream); - if (status == CAIRO_STATUS_SUCCESS) - status = status2; - - _cairo_xml_printf_end (xml, "</font>"); - - return status; -} -#else -static cairo_status_t -_cairo_xml_emit_type42_font (cairo_xml_t *xml, - cairo_scaled_font_t *scaled_font) -{ - return CAIRO_INT_STATUS_UNSUPPORTED; -} -#endif - -static cairo_status_t -_cairo_xml_emit_type3_font (cairo_xml_t *xml, - cairo_scaled_font_t *scaled_font, - cairo_glyph_t *glyphs, - int num_glyphs) -{ - _cairo_xml_printf_start (xml, "<font type='3'>"); - _cairo_xml_printf_end (xml, "</font>"); - - return CAIRO_STATUS_SUCCESS; -} - -static cairo_status_t -_cairo_xml_emit_scaled_font (cairo_xml_t *xml, - cairo_scaled_font_t *scaled_font, - cairo_glyph_t *glyphs, - int num_glyphs) -{ - cairo_int_status_t status; - - _cairo_xml_printf (xml, "<scaled-font>"); - _cairo_xml_indent (xml, 2); - - status = _cairo_xml_emit_type42_font (xml, scaled_font); - if (status == CAIRO_INT_STATUS_UNSUPPORTED) { - status = _cairo_xml_emit_type3_font (xml, scaled_font, - glyphs, num_glyphs); - } - - _cairo_xml_indent (xml, -2); - _cairo_xml_printf (xml, "</scaled-font>"); - - return status; -} - -static cairo_int_status_t -_cairo_xml_surface_glyphs (void *abstract_surface, - cairo_operator_t op, - const cairo_pattern_t *source, - cairo_glyph_t *glyphs, - int num_glyphs, - cairo_scaled_font_t *scaled_font, - const cairo_clip_t *clip) -{ - cairo_xml_surface_t *surface = abstract_surface; - cairo_xml_t *xml = to_xml (surface); - cairo_status_t status; - int i; - - _cairo_xml_printf (xml, "<glyphs>"); - _cairo_xml_indent (xml, 2); - - _cairo_xml_emit_string (xml, "operator", _operator_to_string (op)); - - status = _cairo_xml_surface_emit_clip (surface, clip); - if (unlikely (status)) - return status; - - status = _cairo_xml_emit_pattern (xml, "source", source); - if (unlikely (status)) - return status; - - status = _cairo_xml_emit_scaled_font (xml, scaled_font, glyphs, num_glyphs); - if (unlikely (status)) - return status; - - for (i = 0; i < num_glyphs; i++) { - _cairo_xml_printf (xml, "<glyph index='%lu'>%f %f</glyph>", - glyphs[i].index, - glyphs[i].x, - glyphs[i].y); - } - - _cairo_xml_indent (xml, -2); - _cairo_xml_printf (xml, "</glyphs>"); - - return CAIRO_STATUS_SUCCESS; -} - -static const cairo_surface_backend_t -_cairo_xml_surface_backend = { - CAIRO_SURFACE_TYPE_XML, - NULL, - - _cairo_default_context_create, - - _cairo_xml_surface_create_similar, - NULL, /* create_similar_image */ - NULL, /* map_to_image */ - NULL, /* unmap_image */ - - _cairo_surface_default_source, - NULL, /* acquire source image */ - NULL, /* release source image */ - NULL, /* snapshot */ - - NULL, /* copy page */ - NULL, /* show page */ - - _cairo_xml_surface_get_extents, - NULL, /* get_font_options */ - - NULL, /* flush */ - NULL, /* mark_dirty_rectangle */ - - _cairo_xml_surface_paint, - _cairo_xml_surface_mask, - _cairo_xml_surface_stroke, - _cairo_xml_surface_fill, - NULL, /* fill_stroke */ - _cairo_xml_surface_glyphs, -}; - -static cairo_surface_t * -_cairo_xml_surface_create_internal (cairo_device_t *device, - cairo_content_t content, - double width, - double height) -{ - cairo_xml_surface_t *surface; - - surface = _cairo_malloc (sizeof (cairo_xml_surface_t)); - if (unlikely (surface == NULL)) - return _cairo_surface_create_in_error (_cairo_error (CAIRO_STATUS_NO_MEMORY)); - - _cairo_surface_init (&surface->base, - &_cairo_xml_surface_backend, - device, - content, - TRUE); /* is_vector */ - - surface->width = width; - surface->height = height; - - return &surface->base; -} - -cairo_device_t * -cairo_xml_create (const char *filename) -{ - cairo_output_stream_t *stream; - cairo_status_t status; - - stream = _cairo_output_stream_create_for_filename (filename); - if ((status = _cairo_output_stream_get_status (stream))) - return _cairo_device_create_in_error (status); - - return _cairo_xml_create_internal (stream); -} - -cairo_device_t * -cairo_xml_create_for_stream (cairo_write_func_t write_func, - void *closure) -{ - cairo_output_stream_t *stream; - cairo_status_t status; - - stream = _cairo_output_stream_create (write_func, NULL, closure); - if ((status = _cairo_output_stream_get_status (stream))) - return _cairo_device_create_in_error (status); - - return _cairo_xml_create_internal (stream); -} - -cairo_surface_t * -cairo_xml_surface_create (cairo_device_t *device, - cairo_content_t content, - double width, double height) -{ - if (unlikely (device->backend->type != CAIRO_DEVICE_TYPE_XML)) - return _cairo_surface_create_in_error (CAIRO_STATUS_DEVICE_TYPE_MISMATCH); - - if (unlikely (device->status)) - return _cairo_surface_create_in_error (device->status); - - return _cairo_xml_surface_create_internal (device, content, width, height); -} - -cairo_status_t -cairo_xml_for_recording_surface (cairo_device_t *device, - cairo_surface_t *recording_surface) -{ - cairo_box_t bbox; - cairo_rectangle_int_t extents; - cairo_surface_t *surface; - cairo_xml_t *xml; - cairo_status_t status; - - if (unlikely (device->status)) - return device->status; - - if (unlikely (recording_surface->status)) - return recording_surface->status; - - if (unlikely (device->backend->type != CAIRO_DEVICE_TYPE_XML)) - return _cairo_error (CAIRO_STATUS_DEVICE_TYPE_MISMATCH); - - if (unlikely (! _cairo_surface_is_recording (recording_surface))) - return _cairo_error (CAIRO_STATUS_SURFACE_TYPE_MISMATCH); - - status = _cairo_recording_surface_get_bbox ((cairo_recording_surface_t *) recording_surface, - &bbox, NULL); - if (unlikely (status)) - return status; - - _cairo_box_round_to_rectangle (&bbox, &extents); - surface = _cairo_xml_surface_create_internal (device, - recording_surface->content, - extents.width, - extents.height); - if (unlikely (surface->status)) - return surface->status; - - xml = (cairo_xml_t *) device; - - _cairo_xml_printf (xml, - "<surface content='%s' width='%d' height='%d'>", - _content_to_string (recording_surface->content), - extents.width, extents.height); - _cairo_xml_indent (xml, 2); - - cairo_surface_set_device_offset (surface, -extents.x, -extents.y); - status = _cairo_recording_surface_replay (recording_surface, surface); - cairo_surface_destroy (surface); - - _cairo_xml_indent (xml, -2); - _cairo_xml_printf (xml, "</surface>"); - - return status; -} -slim_hidden_def (cairo_xml_for_recording_surface); diff --git a/gfx/cairo/cairo/src/cairo.c b/gfx/cairo/cairo/src/cairo.c index b2bda657d2..00521f2641 100644 --- a/gfx/cairo/cairo/src/cairo.c +++ b/gfx/cairo/cairo/src/cairo.c @@ -371,8 +371,9 @@ static const cairo_t _cairo_nil[] = { DEFINE_NIL_CONTEXT (CAIRO_STATUS_PNG_ERROR), DEFINE_NIL_CONTEXT (CAIRO_STATUS_FREETYPE_ERROR), DEFINE_NIL_CONTEXT (CAIRO_STATUS_WIN32_GDI_ERROR), - DEFINE_NIL_CONTEXT (CAIRO_STATUS_TAG_ERROR) - + DEFINE_NIL_CONTEXT (CAIRO_STATUS_TAG_ERROR), + DEFINE_NIL_CONTEXT (CAIRO_STATUS_DWRITE_ERROR), + DEFINE_NIL_CONTEXT (CAIRO_STATUS_SVG_FONT_ERROR) }; COMPILE_TIME_ASSERT (ARRAY_LENGTH (_cairo_nil) == CAIRO_STATUS_LAST_STATUS - 1); @@ -457,7 +458,6 @@ cairo_create (cairo_surface_t *target) return target->backend->create_context (target); } -slim_hidden_def (cairo_create); void _cairo_init (cairo_t *cr, @@ -527,7 +527,6 @@ cairo_destroy (cairo_t *cr) cr->backend->destroy (cr); } -slim_hidden_def (cairo_destroy); /** * cairo_get_user_data: @@ -631,7 +630,6 @@ cairo_save (cairo_t *cr) if (unlikely (status)) _cairo_set_error (cr, status); } -slim_hidden_def(cairo_save); /** * cairo_restore: @@ -655,7 +653,6 @@ cairo_restore (cairo_t *cr) if (unlikely (status)) _cairo_set_error (cr, status); } -slim_hidden_def(cairo_restore); /** * cairo_push_group: @@ -738,7 +735,6 @@ cairo_push_group_with_content (cairo_t *cr, cairo_content_t content) if (unlikely (status)) _cairo_set_error (cr, status); } -slim_hidden_def(cairo_push_group_with_content); /** * cairo_pop_group: @@ -775,7 +771,6 @@ cairo_pop_group (cairo_t *cr) return group_pattern; } -slim_hidden_def(cairo_pop_group); /** * cairo_pop_group_to_source: @@ -839,7 +834,6 @@ cairo_set_operator (cairo_t *cr, cairo_operator_t op) if (unlikely (status)) _cairo_set_error (cr, status); } -slim_hidden_def (cairo_set_operator); #if 0 @@ -900,7 +894,6 @@ cairo_set_source_rgb (cairo_t *cr, double red, double green, double blue) if (unlikely (status)) _cairo_set_error (cr, status); } -slim_hidden_def (cairo_set_source_rgb); /** * cairo_set_source_rgba: @@ -918,6 +911,8 @@ slim_hidden_def (cairo_set_source_rgb); * range 0 to 1. If the values passed in are outside that range, they * will be clamped. * + * Note that the color and alpha values are not premultiplied. + * * The default source pattern is opaque black, (that is, it is * equivalent to cairo_set_source_rgba(cr, 0.0, 0.0, 0.0, 1.0)). * @@ -983,7 +978,6 @@ cairo_set_source_surface (cairo_t *cr, if (unlikely (status)) _cairo_set_error (cr, status); } -slim_hidden_def (cairo_set_source_surface); /** * cairo_set_source: @@ -1028,7 +1022,6 @@ cairo_set_source (cairo_t *cr, cairo_pattern_t *source) if (unlikely (status)) _cairo_set_error (cr, status); } -slim_hidden_def (cairo_set_source); /** * cairo_get_source: @@ -1081,7 +1074,6 @@ cairo_set_tolerance (cairo_t *cr, double tolerance) if (unlikely (status)) _cairo_set_error (cr, status); } -slim_hidden_def (cairo_set_tolerance); /** * cairo_set_antialias: @@ -1159,9 +1151,8 @@ cairo_set_fill_rule (cairo_t *cr, cairo_fill_rule_t fill_rule) * cairo_set_line_width() and ignore this note. * * As with the other stroke parameters, the current line width is - * examined by cairo_stroke(), cairo_stroke_extents(), and - * cairo_stroke_to_path(), but does not have any effect during path - * construction. + * examined by cairo_stroke(), and cairo_stroke_extents(), but does not have + * any effect during path construction. * * The default line width value is 2.0. * @@ -1182,7 +1173,46 @@ cairo_set_line_width (cairo_t *cr, double width) if (unlikely (status)) _cairo_set_error (cr, status); } -slim_hidden_def (cairo_set_line_width); + +/** + * cairo_set_hairline: + * @cr: a #cairo_t + * @set_hairline: whether or not to set hairline mode + * + * Sets lines within the cairo context to be hairlines. + * Hairlines are logically zero-width lines that are drawn at the + * thinnest renderable width possible in the current context. + * + * On surfaces with native hairline support, the native hairline + * functionality will be used. Surfaces that support hairlines include: + * - pdf/ps: Encoded as 0-width line. + * - win32_printing: Rendered with PS_COSMETIC pen. + * - svg: Encoded as 1px non-scaling-stroke. + * - script: Encoded with set-hairline function. + * + * Cairo will always render hairlines at 1 device unit wide, even if + * an anisotropic scaling was applied to the stroke width. In the wild, + * handling of this situation is not well-defined. Some PDF, PS, and SVG + * renderers match Cairo's output, but some very popular implementations + * (Acrobat, Chrome, rsvg) will scale the hairline unevenly. + * As such, best practice is to reset any anisotropic scaling before calling + * cairo_stroke(). See https://cairographics.org/cookbook/ellipses/ + * for an example. + * + * Since: 1.18 + **/ +void +cairo_set_hairline (cairo_t *cr, cairo_bool_t set_hairline) +{ + cairo_status_t status; + + if (unlikely (cr->status)) + return; + + status = cr->backend->set_hairline (cr, set_hairline); + if (unlikely (status)) + _cairo_set_error (cr, status); +} /** * cairo_set_line_cap: @@ -1194,9 +1224,8 @@ slim_hidden_def (cairo_set_line_width); * styles are drawn. * * As with the other stroke parameters, the current line cap style is - * examined by cairo_stroke(), cairo_stroke_extents(), and - * cairo_stroke_to_path(), but does not have any effect during path - * construction. + * examined by cairo_stroke(), and cairo_stroke_extents(), but does not have + * any effect during path construction. * * The default line cap style is %CAIRO_LINE_CAP_BUTT. * @@ -1214,7 +1243,6 @@ cairo_set_line_cap (cairo_t *cr, cairo_line_cap_t line_cap) if (unlikely (status)) _cairo_set_error (cr, status); } -slim_hidden_def (cairo_set_line_cap); /** * cairo_set_line_join: @@ -1226,9 +1254,8 @@ slim_hidden_def (cairo_set_line_cap); * styles are drawn. * * As with the other stroke parameters, the current line join style is - * examined by cairo_stroke(), cairo_stroke_extents(), and - * cairo_stroke_to_path(), but does not have any effect during path - * construction. + * examined by cairo_stroke(), and cairo_stroke_extents(), but does not have + * any effect during path construction. * * The default line join style is %CAIRO_LINE_JOIN_MITER. * @@ -1246,7 +1273,6 @@ cairo_set_line_join (cairo_t *cr, cairo_line_join_t line_join) if (unlikely (status)) _cairo_set_error (cr, status); } -slim_hidden_def (cairo_set_line_join); /** * cairo_set_dash: @@ -1362,9 +1388,8 @@ cairo_get_dash (cairo_t *cr, * converted to a bevel. * * As with the other stroke parameters, the current line miter limit is - * examined by cairo_stroke(), cairo_stroke_extents(), and - * cairo_stroke_to_path(), but does not have any effect during path - * construction. + * examined by cairo_stroke(), and cairo_stroke_extents(), but does not have + * any effect during path construction. * * The default miter limit value is 10.0, which will convert joins * with interior angles less than 11 degrees to bevels instead of @@ -1416,7 +1441,6 @@ cairo_translate (cairo_t *cr, double tx, double ty) if (unlikely (status)) _cairo_set_error (cr, status); } -slim_hidden_def (cairo_translate); /** * cairo_scale: @@ -1443,7 +1467,6 @@ cairo_scale (cairo_t *cr, double sx, double sy) if (unlikely (status)) _cairo_set_error (cr, status); } -slim_hidden_def (cairo_scale); /** * cairo_rotate: @@ -1496,7 +1519,6 @@ cairo_transform (cairo_t *cr, if (unlikely (status)) _cairo_set_error (cr, status); } -slim_hidden_def (cairo_transform); /** * cairo_set_matrix: @@ -1521,7 +1543,6 @@ cairo_set_matrix (cairo_t *cr, if (unlikely (status)) _cairo_set_error (cr, status); } -slim_hidden_def (cairo_set_matrix); /** * cairo_identity_matrix: @@ -1567,7 +1588,6 @@ cairo_user_to_device (cairo_t *cr, double *x, double *y) cr->backend->user_to_device (cr, x, y); } -slim_hidden_def (cairo_user_to_device); /** * cairo_user_to_device_distance: @@ -1590,7 +1610,6 @@ cairo_user_to_device_distance (cairo_t *cr, double *dx, double *dy) cr->backend->user_to_device_distance (cr, dx, dy); } -slim_hidden_def (cairo_user_to_device_distance); /** * cairo_device_to_user: @@ -1612,7 +1631,6 @@ cairo_device_to_user (cairo_t *cr, double *x, double *y) cr->backend->device_to_user (cr, x, y); } -slim_hidden_def (cairo_device_to_user); /** * cairo_device_to_user_distance: @@ -1657,7 +1675,6 @@ cairo_new_path (cairo_t *cr) if (unlikely (status)) _cairo_set_error (cr, status); } -slim_hidden_def(cairo_new_path); /** * cairo_new_sub_path: @@ -1713,8 +1730,6 @@ cairo_move_to (cairo_t *cr, double x, double y) if (unlikely (status)) _cairo_set_error (cr, status); } -slim_hidden_def(cairo_move_to); - /** * cairo_line_to: @@ -1743,7 +1758,6 @@ cairo_line_to (cairo_t *cr, double x, double y) if (unlikely (status)) _cairo_set_error (cr, status); } -slim_hidden_def (cairo_line_to); /** * cairo_curve_to: @@ -1784,7 +1798,6 @@ cairo_curve_to (cairo_t *cr, if (unlikely (status)) _cairo_set_error (cr, status); } -slim_hidden_def (cairo_curve_to); /** * cairo_arc: @@ -2003,7 +2016,6 @@ cairo_rel_line_to (cairo_t *cr, double dx, double dy) if (unlikely (status)) _cairo_set_error (cr, status); } -slim_hidden_def(cairo_rel_line_to); /** * cairo_rel_curve_to: @@ -2146,7 +2158,6 @@ cairo_close_path (cairo_t *cr) if (unlikely (status)) _cairo_set_error (cr, status); } -slim_hidden_def(cairo_close_path); /** * cairo_path_extents: @@ -2220,7 +2231,6 @@ cairo_paint (cairo_t *cr) if (unlikely (status)) _cairo_set_error (cr, status); } -slim_hidden_def (cairo_paint); /** * cairo_paint_with_alpha: @@ -2283,7 +2293,6 @@ cairo_mask (cairo_t *cr, if (unlikely (status)) _cairo_set_error (cr, status); } -slim_hidden_def (cairo_mask); /** * cairo_mask_surface: @@ -2367,7 +2376,6 @@ cairo_stroke (cairo_t *cr) if (unlikely (status)) _cairo_set_error (cr, status); } -slim_hidden_def(cairo_stroke); /** * cairo_stroke_preserve: @@ -2396,7 +2404,6 @@ cairo_stroke_preserve (cairo_t *cr) if (unlikely (status)) _cairo_set_error (cr, status); } -slim_hidden_def(cairo_stroke_preserve); /** * cairo_fill: @@ -2448,7 +2455,6 @@ cairo_fill_preserve (cairo_t *cr) if (unlikely (status)) _cairo_set_error (cr, status); } -slim_hidden_def(cairo_fill_preserve); /** * cairo_copy_page: @@ -2750,7 +2756,6 @@ cairo_clip_preserve (cairo_t *cr) if (unlikely (status)) _cairo_set_error (cr, status); } -slim_hidden_def(cairo_clip_preserve); /** * cairo_reset_clip: @@ -2883,7 +2888,7 @@ cairo_copy_clip_rectangle_list (cairo_t *cr) * CAIRO_TAG_DEST: * * Create a destination for a hyperlink. Destination tag attributes - * are detailed at [Destinations][dests]. + * are detailed at [Destinations][dest]. * * Since: 1.16 **/ @@ -2892,12 +2897,28 @@ cairo_copy_clip_rectangle_list (cairo_t *cr) * CAIRO_TAG_LINK: * * Create hyperlink. Link tag attributes are detailed at - * [Links][links]. + * [Links][link]. * * Since: 1.16 **/ /** + * CAIRO_TAG_CONTENT: + * + * Create a content tag. + * + * Since: 1.18 + **/ + +/** + * CAIRO_TAG_CONTENT_REF: + * + * Create a content reference tag. + * + * Since: 1.18 + **/ + +/** * cairo_tag_begin: * @cr: a cairo context * @tag_name: tag name @@ -3164,7 +3185,6 @@ cairo_set_font_size (cairo_t *cr, double size) if (unlikely (status)) _cairo_set_error (cr, status); } -slim_hidden_def (cairo_set_font_size); /** * cairo_set_font_matrix: @@ -3194,7 +3214,6 @@ cairo_set_font_matrix (cairo_t *cr, if (unlikely (status)) _cairo_set_error (cr, status); } -slim_hidden_def (cairo_set_font_matrix); /** * cairo_get_font_matrix: @@ -3249,7 +3268,6 @@ cairo_set_font_options (cairo_t *cr, if (unlikely (status)) _cairo_set_error (cr, status); } -slim_hidden_def (cairo_set_font_options); /** * cairo_get_font_options: @@ -3302,7 +3320,7 @@ cairo_set_scaled_font (cairo_t *cr, if (unlikely (cr->status)) return; - if ((scaled_font == NULL)) { + if (scaled_font == NULL) { _cairo_set_error (cr, _cairo_error (CAIRO_STATUS_NULL_POINTER)); return; } @@ -3346,7 +3364,6 @@ cairo_get_scaled_font (cairo_t *cr) return cr->backend->get_scaled_font (cr); } -slim_hidden_def (cairo_get_scaled_font); /** * cairo_text_extents: @@ -3884,7 +3901,7 @@ cairo_get_operator (cairo_t *cr) } #if 0 -/** +/* * cairo_get_opacity: * @cr: a cairo context * @@ -3922,7 +3939,6 @@ cairo_get_tolerance (cairo_t *cr) return cr->backend->get_tolerance (cr); } -slim_hidden_def (cairo_get_tolerance); /** * cairo_get_antialias: @@ -3985,7 +4001,7 @@ cairo_has_current_point (cairo_t *cr) * cairo_move_to(), cairo_line_to(), cairo_curve_to(), * cairo_rel_move_to(), cairo_rel_line_to(), cairo_rel_curve_to(), * cairo_arc(), cairo_arc_negative(), cairo_rectangle(), - * cairo_text_path(), cairo_glyph_path(), cairo_stroke_to_path(). + * cairo_text_path(), cairo_glyph_path(). * * Some functions use and alter the current point but do not * otherwise change current path: @@ -4013,7 +4029,6 @@ cairo_get_current_point (cairo_t *cr, double *x_ret, double *y_ret) if (y_ret) *y_ret = y; } -slim_hidden_def(cairo_get_current_point); /** * cairo_get_fill_rule: @@ -4055,7 +4070,25 @@ cairo_get_line_width (cairo_t *cr) return cr->backend->get_line_width (cr); } -slim_hidden_def (cairo_get_line_width); + +/** + * cairo_get_hairline: + * @cr: a cairo context + * + * Returns whether or not hairline mode is set, as set by cairo_set_hairline(). + * + * Return value: whether hairline mode is set. + * + * Since: 1.18 + **/ +cairo_bool_t +cairo_get_hairline (cairo_t *cr) +{ + if (unlikely (cr->status)) + return FALSE; + + return cr->backend->get_hairline (cr); +} /** * cairo_get_line_cap: @@ -4133,7 +4166,6 @@ cairo_get_matrix (cairo_t *cr, cairo_matrix_t *matrix) cr->backend->get_matrix (cr, matrix); } -slim_hidden_def (cairo_get_matrix); /** * cairo_get_target: @@ -4161,7 +4193,6 @@ cairo_get_target (cairo_t *cr) return cr->backend->get_original_target (cr); } -slim_hidden_def (cairo_get_target); /** * cairo_get_group_target: @@ -4338,4 +4369,3 @@ cairo_status (cairo_t *cr) { return cr->status; } -slim_hidden_def (cairo_status); diff --git a/gfx/cairo/cairo/src/cairo.h b/gfx/cairo/cairo/src/cairo.h index a2c54d4083..5758e34277 100644 --- a/gfx/cairo/cairo/src/cairo.h +++ b/gfx/cairo/cairo/src/cairo.h @@ -50,12 +50,25 @@ # define CAIRO_END_DECLS #endif +#if (defined(_WIN32) || defined(__CYGWIN__)) && !defined(CAIRO_WIN32_STATIC_BUILD) +# define _cairo_export __declspec(dllexport) +# define _cairo_import __declspec(dllimport) +#elif defined(__GNUC__) && (__GNUC__ >= 4) +# define _cairo_export __attribute__((__visibility__("default"))) +# define _cairo_import +#else +# define _cairo_export +# define _cairo_import +#endif + +#ifdef CAIRO_COMPILATION +# define _cairo_api _cairo_export +#else +# define _cairo_api _cairo_import +#endif + #ifndef cairo_public -# if defined (_MSC_VER) && ! defined (CAIRO_WIN32_STATIC_BUILD) -# define cairo_public __declspec(dllimport) -# else -# define cairo_public -# endif +#define cairo_public _cairo_api extern #endif CAIRO_BEGIN_DECLS @@ -157,9 +170,7 @@ typedef struct _cairo_surface cairo_surface_t; * * A #cairo_device_t represents the driver interface for drawing * operations to a #cairo_surface_t. There are different subtypes of - * #cairo_device_t for different drawing backends; for example, - * cairo_egl_device_create() creates a device that wraps an EGL display and - * context. + * #cairo_device_t for different drawing backends. * * The type of a device can be queried with cairo_device_get_type(). * @@ -296,6 +307,8 @@ typedef struct _cairo_user_data_key { * @CAIRO_STATUS_FREETYPE_ERROR: error occurred in libfreetype (Since 1.16) * @CAIRO_STATUS_WIN32_GDI_ERROR: error occurred in the Windows Graphics Device Interface (Since 1.16) * @CAIRO_STATUS_TAG_ERROR: invalid tag name, attributes, or nesting (Since 1.16) + * @CAIRO_STATUS_DWRITE_ERROR: error occurred in the Windows Direct Write API (Since 1.18) + * @CAIRO_STATUS_SVG_FONT_ERROR: error occurred in OpenType-SVG font rendering (Since 1.18) * @CAIRO_STATUS_LAST_STATUS: this is a special value indicating the number of * status values defined in this enumeration. When using this value, note * that the version of cairo at run-time may have additional status values @@ -356,6 +369,8 @@ typedef enum _cairo_status { CAIRO_STATUS_FREETYPE_ERROR, CAIRO_STATUS_WIN32_GDI_ERROR, CAIRO_STATUS_TAG_ERROR, + CAIRO_STATUS_DWRITE_ERROR, + CAIRO_STATUS_SVG_FONT_ERROR, CAIRO_STATUS_LAST_STATUS } cairo_status_t; @@ -427,6 +442,38 @@ typedef enum _cairo_format { CAIRO_FORMAT_RGBA128F = 7 } cairo_format_t; +/** + * cairo_dither_t: + * @CAIRO_DITHER_NONE: No dithering. + * @CAIRO_DITHER_DEFAULT: Default choice at cairo compile time. Currently NONE. + * @CAIRO_DITHER_FAST: Fastest dithering algorithm supported by the backend + * @CAIRO_DITHER_GOOD: An algorithm with smoother dithering than FAST + * @CAIRO_DITHER_BEST: Best algorithm available in the backend + * + * Dither is an intentionally applied form of noise used to randomize + * quantization error, preventing large-scale patterns such as color banding + * in images (e.g. for gradients). Ordered dithering applies a precomputed + * threshold matrix to spread the errors smoothly. + * + * #cairo_dither_t is modeled on pixman dithering algorithm choice. + * As of Pixman 0.40, FAST corresponds to a 8x8 ordered bayer noise and GOOD + * and BEST use an ordered 64x64 precomputed blue noise. + * + * Since: 1.18 + **/ +typedef enum _cairo_dither { + CAIRO_DITHER_NONE, + CAIRO_DITHER_DEFAULT, + CAIRO_DITHER_FAST, + CAIRO_DITHER_GOOD, + CAIRO_DITHER_BEST +} cairo_dither_t; + +cairo_public void +cairo_pattern_set_dither (cairo_pattern_t *pattern, cairo_dither_t dither); + +cairo_public cairo_dither_t +cairo_pattern_get_dither (cairo_pattern_t *pattern); /** * cairo_write_func_t: @@ -475,7 +522,7 @@ typedef cairo_status_t (*cairo_read_func_t) (void *closure, /** * cairo_rectangle_int_t: * @x: X coordinate of the left side of the rectangle - * @y: Y coordinate of the the top side of the rectangle + * @y: Y coordinate of the top side of the rectangle * @width: width of the rectangle * @height: height of the rectangle * @@ -765,6 +812,9 @@ cairo_set_fill_rule (cairo_t *cr, cairo_fill_rule_t fill_rule); cairo_public void cairo_set_line_width (cairo_t *cr, double width); +cairo_public void +cairo_set_hairline (cairo_t *cr, cairo_bool_t set_hairline); + /** * cairo_line_cap_t: * @CAIRO_LINE_CAP_BUTT: start(stop) the line exactly at the start(end) point (Since 1.0) @@ -995,7 +1045,7 @@ cairo_clip_extents (cairo_t *cr, /** * cairo_rectangle_t: * @x: X coordinate of the left side of the rectangle - * @y: Y coordinate of the the top side of the rectangle + * @y: Y coordinate of the top side of the rectangle * @width: width of the rectangle * @height: height of the rectangle * @@ -1034,6 +1084,8 @@ cairo_rectangle_list_destroy (cairo_rectangle_list_t *rectangle_list); #define CAIRO_TAG_DEST "cairo.dest" #define CAIRO_TAG_LINK "Link" +#define CAIRO_TAG_CONTENT "cairo.content" +#define CAIRO_TAG_CONTENT_REF "cairo.content_ref" cairo_public void cairo_tag_begin (cairo_t *cr, const char *tag_name, const char *attributes); @@ -1365,6 +1417,29 @@ typedef enum _cairo_hint_metrics { } cairo_hint_metrics_t; /** + * cairo_color_mode_t: + * @CAIRO_COLOR_MODE_DEFAULT: Use the default color mode for + * font backend and target device, since 1.18. + * @CAIRO_COLOR_MODE_NO_COLOR: Disable rendering color glyphs. Glyphs are + * always rendered as outline glyphs, since 1.18. + * @CAIRO_COLOR_MODE_COLOR: Enable rendering color glyphs. If the font + * contains a color presentation for a glyph, and when supported by + * the font backend, the glyph will be rendered in color, since 1.18. + * + * Specifies if color fonts are to be rendered using the color + * glyphs or outline glyphs. Glyphs that do not have a color + * presentation, and non-color fonts are not affected by this font + * option. + * + * Since: 1.18 + **/ +typedef enum _cairo_color_mode { + CAIRO_COLOR_MODE_DEFAULT, + CAIRO_COLOR_MODE_NO_COLOR, + CAIRO_COLOR_MODE_COLOR +} cairo_color_mode_t; + +/** * _cairo_lcd_filter: * @CAIRO_LCD_FILTER_DEFAULT: Use the default LCD filter for * font backend and target device @@ -1465,8 +1540,36 @@ cairo_public void cairo_font_options_set_variations (cairo_font_options_t *options, const char *variations); +#define CAIRO_COLOR_PALETTE_DEFAULT 0 + +cairo_public void +cairo_font_options_set_color_mode (cairo_font_options_t *options, + cairo_color_mode_t color_mode); + +cairo_public cairo_color_mode_t +cairo_font_options_get_color_mode (const cairo_font_options_t *options); + +cairo_public unsigned int +cairo_font_options_get_color_palette (const cairo_font_options_t *options); + +cairo_public void +cairo_font_options_set_color_palette (cairo_font_options_t *options, + unsigned int palette_index); + +cairo_public void +cairo_font_options_set_custom_palette_color (cairo_font_options_t *options, + unsigned int index, + double red, double green, + double blue, double alpha); + +cairo_public cairo_status_t +cairo_font_options_get_custom_palette_color (cairo_font_options_t *options, + unsigned int index, + double *red, double *green, + double *blue, double *alpha); + /* This interface is for dealing with text as text, not caring about the - font object inside the the cairo_t. */ + font object inside the cairo_t. */ cairo_public void cairo_select_font_face (cairo_t *cr, @@ -1573,6 +1676,7 @@ cairo_font_face_status (cairo_font_face_t *font_face); * @CAIRO_FONT_TYPE_QUARTZ: The font is of type Quartz (Since: 1.6, in 1.2 and * 1.4 it was named CAIRO_FONT_TYPE_ATSUI) * @CAIRO_FONT_TYPE_USER: The font was create using cairo's user font api (Since: 1.8) + * @CAIRO_FONT_TYPE_DWRITE: The font is of type Win32 DWrite (Since: 1.18) * * #cairo_font_type_t is used to describe the type of a given font * face or scaled font. The font types are also known as "font @@ -1778,13 +1882,24 @@ typedef cairo_status_t (*cairo_user_scaled_font_init_func_t) (cairo_scaled_font_ * * The callback is mandatory, and expected to draw the glyph with code @glyph to * the cairo context @cr. @cr is prepared such that the glyph drawing is done in - * font space. That is, the matrix set on @cr is the scale matrix of @scaled_font, + * font space. That is, the matrix set on @cr is the scale matrix of @scaled_font. * The @extents argument is where the user font sets the font extents for * @scaled_font. However, if user prefers to draw in user space, they can - * achieve that by changing the matrix on @cr. All cairo rendering operations - * to @cr are permitted, however, the result is undefined if any source other - * than the default source on @cr is used. That means, glyph bitmaps should - * be rendered using cairo_mask() instead of cairo_paint(). + * achieve that by changing the matrix on @cr. + * + * All cairo rendering operations to @cr are permitted. However, when + * this callback is set with + * cairo_user_font_face_set_render_glyph_func(), the result is + * undefined if any source other than the default source on @cr is + * used. That means, glyph bitmaps should be rendered using + * cairo_mask() instead of cairo_paint(). + * + * When this callback is set with + * cairo_user_font_face_set_render_color_glyph_func(), the default + * source is black. Setting the source is a valid + * operation. cairo_user_scaled_font_get_foreground_marker() or + * cairo_user_scaled_font_get_foreground_source() may be called to + * obtain the current source at the time the glyph is rendered. * * Other non-default settings on @cr include a font size of 1.0 (given that * it is set up to be in font space), and font options corresponding to @@ -1804,8 +1919,20 @@ typedef cairo_status_t (*cairo_user_scaled_font_init_func_t) (cairo_scaled_font_ * extents, it must be ink extents, and include the extents of all drawing * done to @cr in the callback. * - * Returns: %CAIRO_STATUS_SUCCESS upon success, or - * %CAIRO_STATUS_USER_FONT_ERROR or any other error status on error. + * Where both color and non-color callbacks has been set using + * cairo_user_font_face_set_render_color_glyph_func(), and + * cairo_user_font_face_set_render_glyph_func(), the color glyph + * callback will be called first. If the color glyph callback returns + * %CAIRO_STATUS_USER_FONT_NOT_IMPLEMENTED, any drawing operations are + * discarded and the non-color callback will be called. This is the + * only case in which the %CAIRO_STATUS_USER_FONT_NOT_IMPLEMENTED may + * be returned from a render callback. This fallback sequence allows a + * user font face to contain a combination of both color and non-color + * glyphs. + * + * Returns: %CAIRO_STATUS_SUCCESS upon success, + * %CAIRO_STATUS_USER_FONT_NOT_IMPLEMENTED if fallback options should be tried, + * or %CAIRO_STATUS_USER_FONT_ERROR or any other error status on error. * * Since: 1.8 **/ @@ -1941,6 +2068,10 @@ cairo_user_font_face_set_render_glyph_func (cairo_font_face_t cairo_user_scaled_font_render_glyph_func_t render_glyph_func); cairo_public void +cairo_user_font_face_set_render_color_glyph_func (cairo_font_face_t *font_face, + cairo_user_scaled_font_render_glyph_func_t render_glyph_func); + +cairo_public void cairo_user_font_face_set_text_to_glyphs_func (cairo_font_face_t *font_face, cairo_user_scaled_font_text_to_glyphs_func_t text_to_glyphs_func); @@ -1956,12 +2087,20 @@ cairo_user_font_face_get_init_func (cairo_font_face_t *font_face); cairo_public cairo_user_scaled_font_render_glyph_func_t cairo_user_font_face_get_render_glyph_func (cairo_font_face_t *font_face); +cairo_public cairo_user_scaled_font_render_glyph_func_t +cairo_user_font_face_get_render_color_glyph_func (cairo_font_face_t *font_face); + cairo_public cairo_user_scaled_font_text_to_glyphs_func_t cairo_user_font_face_get_text_to_glyphs_func (cairo_font_face_t *font_face); cairo_public cairo_user_scaled_font_unicode_to_glyph_func_t cairo_user_font_face_get_unicode_to_glyph_func (cairo_font_face_t *font_face); +cairo_public cairo_pattern_t * +cairo_user_scaled_font_get_foreground_marker (cairo_scaled_font_t *scaled_font); + +cairo_public cairo_pattern_t * +cairo_user_scaled_font_get_foreground_source (cairo_scaled_font_t *scaled_font); /* Query functions */ @@ -1989,6 +2128,9 @@ cairo_get_fill_rule (cairo_t *cr); cairo_public double cairo_get_line_width (cairo_t *cr); +cairo_public cairo_bool_t +cairo_get_hairline (cairo_t *cr); + cairo_public cairo_line_cap_t cairo_get_line_cap (cairo_t *cr); @@ -2291,6 +2433,16 @@ cairo_public cairo_surface_t * cairo_surface_create_observer (cairo_surface_t *target, cairo_surface_observer_mode_t mode); +/** + * cairo_surface_observer_callback_t: + * @observer: the #cairo_surface_observer_t + * @target: the observed surface + * @data: closure used when adding the callback + * + * A generic callback function for surface operations. + * + * Since: 1.12 + **/ typedef void (*cairo_surface_observer_callback_t) (cairo_surface_t *observer, cairo_surface_t *target, void *data); @@ -2331,34 +2483,34 @@ cairo_surface_observer_add_finish_callback (cairo_surface_t *abstract_surface, void *data); cairo_public cairo_status_t -cairo_surface_observer_print (cairo_surface_t *surface, +cairo_surface_observer_print (cairo_surface_t *abstract_surface, cairo_write_func_t write_func, void *closure); cairo_public double -cairo_surface_observer_elapsed (cairo_surface_t *surface); +cairo_surface_observer_elapsed (cairo_surface_t *abstract_surface); cairo_public cairo_status_t -cairo_device_observer_print (cairo_device_t *device, +cairo_device_observer_print (cairo_device_t *abstract_device, cairo_write_func_t write_func, void *closure); cairo_public double -cairo_device_observer_elapsed (cairo_device_t *device); +cairo_device_observer_elapsed (cairo_device_t *abstract_device); cairo_public double -cairo_device_observer_paint_elapsed (cairo_device_t *device); +cairo_device_observer_paint_elapsed (cairo_device_t *abstract_device); cairo_public double -cairo_device_observer_mask_elapsed (cairo_device_t *device); +cairo_device_observer_mask_elapsed (cairo_device_t *abstract_device); cairo_public double -cairo_device_observer_fill_elapsed (cairo_device_t *device); +cairo_device_observer_fill_elapsed (cairo_device_t *abstract_device); cairo_public double -cairo_device_observer_stroke_elapsed (cairo_device_t *device); +cairo_device_observer_stroke_elapsed (cairo_device_t *abstract_device); cairo_public double -cairo_device_observer_glyphs_elapsed (cairo_device_t *device); +cairo_device_observer_glyphs_elapsed (cairo_device_t *abstract_device); cairo_public cairo_surface_t * cairo_surface_reference (cairo_surface_t *surface); @@ -2385,26 +2537,37 @@ cairo_surface_status (cairo_surface_t *surface); * @CAIRO_SURFACE_TYPE_PS: The surface is of type ps, since 1.2 * @CAIRO_SURFACE_TYPE_XLIB: The surface is of type xlib, since 1.2 * @CAIRO_SURFACE_TYPE_XCB: The surface is of type xcb, since 1.2 - * @CAIRO_SURFACE_TYPE_GLITZ: The surface is of type glitz, since 1.2 + * @CAIRO_SURFACE_TYPE_GLITZ: The surface is of type glitz, since 1.2, deprecated 1.18 + * (glitz support have been removed, this surface type will never be set by cairo) * @CAIRO_SURFACE_TYPE_QUARTZ: The surface is of type quartz, since 1.2 * @CAIRO_SURFACE_TYPE_WIN32: The surface is of type win32, since 1.2 - * @CAIRO_SURFACE_TYPE_BEOS: The surface is of type beos, since 1.2 - * @CAIRO_SURFACE_TYPE_DIRECTFB: The surface is of type directfb, since 1.2 + * @CAIRO_SURFACE_TYPE_BEOS: The surface is of type beos, since 1.2, deprecated 1.18 + * (beos support have been removed, this surface type will never be set by cairo) + * @CAIRO_SURFACE_TYPE_DIRECTFB: The surface is of type directfb, since 1.2, deprecated 1.18 + * (directfb support have been removed, this surface type will never be set by cairo) * @CAIRO_SURFACE_TYPE_SVG: The surface is of type svg, since 1.2 - * @CAIRO_SURFACE_TYPE_OS2: The surface is of type os2, since 1.4 + * @CAIRO_SURFACE_TYPE_OS2: The surface is of type os2, since 1.4, deprecated 1.18 + * (os2 support have been removed, this surface type will never be set by cairo) * @CAIRO_SURFACE_TYPE_WIN32_PRINTING: The surface is a win32 printing surface, since 1.6 * @CAIRO_SURFACE_TYPE_QUARTZ_IMAGE: The surface is of type quartz_image, since 1.6 * @CAIRO_SURFACE_TYPE_SCRIPT: The surface is of type script, since 1.10 - * @CAIRO_SURFACE_TYPE_QT: The surface is of type Qt, since 1.10 + * @CAIRO_SURFACE_TYPE_QT: The surface is of type Qt, since 1.10, deprecated 1.18 + * (Ot support have been removed, this surface type will never be set by cairo) * @CAIRO_SURFACE_TYPE_RECORDING: The surface is of type recording, since 1.10 - * @CAIRO_SURFACE_TYPE_VG: The surface is a OpenVG surface, since 1.10 - * @CAIRO_SURFACE_TYPE_GL: The surface is of type OpenGL, since 1.10 - * @CAIRO_SURFACE_TYPE_DRM: The surface is of type Direct Render Manager, since 1.10 + * @CAIRO_SURFACE_TYPE_VG: The surface is a OpenVG surface, since 1.10, deprecated 1.18 + * (OpenVG support have been removed, this surface type will never be set by cairo) + * @CAIRO_SURFACE_TYPE_GL: The surface is of type OpenGL, since 1.10, deprecated 1.18 + * (OpenGL support have been removed, this surface type will never be set by cairo) + * @CAIRO_SURFACE_TYPE_DRM: The surface is of type Direct Render Manager, since 1.10, deprecated 1.18 + * (DRM support have been removed, this surface type will never be set by cairo) * @CAIRO_SURFACE_TYPE_TEE: The surface is of type 'tee' (a multiplexing surface), since 1.10 * @CAIRO_SURFACE_TYPE_XML: The surface is of type XML (for debugging), since 1.10 + * @CAIRO_SURFACE_TYPE_SKIA: The surface is of type Skia, since 1.10, deprecated 1.18 + * (Skia support have been removed, this surface type will never be set by cairo) * @CAIRO_SURFACE_TYPE_SUBSURFACE: The surface is a subsurface created with * cairo_surface_create_for_rectangle(), since 1.10 - * @CAIRO_SURFACE_TYPE_COGL: This surface is of type Cogl, since 1.12 + * @CAIRO_SURFACE_TYPE_COGL: This surface is of type Cogl, since 1.12, deprecated 1.18 + * (Cogl support have been removed, this surface type will never be set by cairo) * * #cairo_surface_type_t is used to describe the type of a given * surface. The surface types are also known as "backends" or "surface diff --git a/gfx/cairo/cairo/src/cairo.pc.in b/gfx/cairo/cairo/src/cairo.pc.in deleted file mode 100644 index b361edf18f..0000000000 --- a/gfx/cairo/cairo/src/cairo.pc.in +++ /dev/null @@ -1,13 +0,0 @@ -prefix=@prefix@ -exec_prefix=@exec_prefix@ -libdir=@libdir@ -includedir=@includedir@ - -Name: cairo -Description: Multi-platform 2D graphics library -Version: @VERSION@ - -@PKGCONFIG_REQUIRES@: @CAIRO_REQUIRES@ -Libs: -L${libdir} -lcairo -Libs.private: @CAIRO_NONPKGCONFIG_LIBS@ -Cflags: -I${includedir}/cairo diff --git a/gfx/cairo/cairo/src/cairoint.h b/gfx/cairo/cairo/src/cairoint.h index 576dba1331..5f053e0abc 100644 --- a/gfx/cairo/cairo/src/cairoint.h +++ b/gfx/cairo/cairo/src/cairoint.h @@ -1,3 +1,4 @@ +/* -*- Mode: c; tab-width: 8; c-basic-offset: 4; indent-tabs-mode: t; -*- */ /* cairo - a vector graphics library with display and print output * * Copyright © 2002 University of Southern California @@ -46,13 +47,7 @@ #ifndef _CAIROINT_H_ #define _CAIROINT_H_ -#if HAVE_CONFIG_H #include "config.h" -#endif - -#ifdef _MSC_VER -#define cairo_public __declspec(dllexport) -#endif #include <assert.h> #include <stdlib.h> @@ -75,8 +70,7 @@ #if CAIRO_HAS_PDF_SURFACE || \ CAIRO_HAS_PS_SURFACE || \ - CAIRO_HAS_SCRIPT_SURFACE || \ - CAIRO_HAS_XML_SURFACE + CAIRO_HAS_SCRIPT_SURFACE #define CAIRO_HAS_DEFLATE_STREAM 1 #endif @@ -277,33 +271,7 @@ static inline void put_unaligned_be32 (uint32_t v, unsigned char *p) p[3] = v & 0xff; } -/* The glibc versions of ispace() and isdigit() are slow in UTF-8 locales. - */ - -static inline int cairo_const -_cairo_isspace (int c) -{ - return (c == 0x20 || (c >= 0x09 && c <= 0x0d)); -} - -static inline int cairo_const -_cairo_isdigit (int c) -{ - return (c >= '0' && c <= '9'); -} - -static inline int cairo_const -_cairo_isxdigit (int c) -{ - return ((c >= '0' && c <= '9') || (c >= 'a' && c <= 'f') || (c >= 'A' && c <= 'F')); -} - -static inline int cairo_const -_cairo_isalpha (int c) -{ - return (c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z'); -} - +#include "cairo-ctype-inline.h" #include "cairo-types-private.h" #include "cairo-cache-private.h" #include "cairo-reference-count-private.h" @@ -357,10 +325,10 @@ static inline cairo_bool_t _cairo_rectangle_intersects (const cairo_rectangle_int_t *dst, const cairo_rectangle_int_t *src) { - return !(src->x >= dst->x + (int) dst->width || - src->x + (int) src->width <= dst->x || - src->y >= dst->y + (int) dst->height || - src->y + (int) src->height <= dst->y); + return !(src->x >= dst->x + dst->width || + src->x + src->width <= dst->x || + src->y >= dst->y + dst->height || + src->y + src->height <= dst->y); } static inline cairo_bool_t @@ -368,9 +336,9 @@ _cairo_rectangle_contains_rectangle (const cairo_rectangle_int_t *a, const cairo_rectangle_int_t *b) { return (a->x <= b->x && - a->x + (int) a->width >= b->x + (int) b->width && + a->x + a->width >= b->x + b->width && a->y <= b->y && - a->y + (int) a->height >= b->y + (int) b->height); + a->y + a->height >= b->y + b->height); } cairo_private void @@ -430,16 +398,20 @@ _cairo_user_data_array_foreach (cairo_user_data_array_t *array, #define _CAIRO_HASH_INIT_VALUE 5381 -cairo_private unsigned long +cairo_private uintptr_t _cairo_hash_string (const char *c); -cairo_private unsigned long -_cairo_hash_bytes (unsigned long hash, +cairo_private uintptr_t +_cairo_hash_bytes (uintptr_t hash, const void *bytes, unsigned int length); +cairo_private uintptr_t +_cairo_hash_uintptr (uintptr_t hash, + uintptr_t u); + /* We use bits 24-27 to store phases for subpixel positions */ -#define _cairo_scaled_glyph_index(g) ((g)->hash_entry.hash & 0xffffff) +#define _cairo_scaled_glyph_index(g) ((unsigned long)((g)->hash_entry.hash & 0xffffff)) #define _cairo_scaled_glyph_xphase(g) (int)(((g)->hash_entry.hash >> 24) & 3) #define _cairo_scaled_glyph_yphase(g) (int)(((g)->hash_entry.hash >> 26) & 3) #define _cairo_scaled_glyph_set_index(g, i) ((g)->hash_entry.hash = (i)) @@ -467,11 +439,6 @@ _cairo_ft_font_reset_static_data (void); cairo_private void _cairo_win32_font_reset_static_data (void); -#if CAIRO_HAS_COGL_SURFACE -void -_cairo_cogl_context_reset_static_data (void); -#endif - /* the font backend interface */ struct _cairo_unscaled_font_backend { @@ -525,10 +492,24 @@ struct _cairo_scaled_font_backend { void (*fini) (void *scaled_font); + /* + * Get the requested glyph info. + * @scaled_font: a #cairo_scaled_font_t + * @scaled_glyph: a #cairo_scaled_glyph_t the glyph + * @info: a #cairo_scaled_glyph_info_t which information to retrieve + * %CAIRO_SCALED_GLYPH_INFO_METRICS - glyph metrics and bounding box + * %CAIRO_SCALED_GLYPH_INFO_SURFACE - surface holding glyph image + * %CAIRO_SCALED_GLYPH_INFO_PATH - path holding glyph outline in device space + * %CAIRO_SCALED_GLYPH_INFO_RECORDING_SURFACE - surface holding recording of glyph + * %CAIRO_SCALED_GLYPH_INFO_COLOR_SURFACE - surface holding color glyph image + * @foreground_color - foreground color to use when rendering color fonts. Use NULL + * if not requesting CAIRO_SCALED_GLYPH_INFO_COLOR_SURFACE or foreground color is unknown. + */ cairo_warn cairo_int_status_t (*scaled_glyph_init) (void *scaled_font, cairo_scaled_glyph_t *scaled_glyph, - cairo_scaled_glyph_info_t info); + cairo_scaled_glyph_info_t info, + const cairo_color_t *foreground_color); /* A backend only needs to implement this or ucs4_to_index(), not * both. This allows the backend to do something more sophisticated @@ -546,6 +527,11 @@ struct _cairo_scaled_font_backend { int *num_clusters, cairo_text_cluster_flags_t *cluster_flags); + /* Get the glyph index for the given unicode code point. + * @scaled_font: a #cairo_scaled_font_t + * @ucs4: unicode code point + * Returns glyph index or 0 if not found. + */ unsigned long (*ucs4_to_index) (void *scaled_font, uint32_t ucs4); @@ -584,6 +570,9 @@ struct _cairo_scaled_font_backend { /* Determine if this scaled font differs from the outlines in the font tables. * eg synthesized bold/italic or a non default variant of a variable font. + * @scaled_font: font + * @is_sythetic: returns TRUE if scaled font is synthetic + * Returns cairo status */ cairo_warn cairo_int_status_t (*is_synthetic)(void *scaled_font, @@ -600,7 +589,6 @@ struct _cairo_scaled_font_backend { * @glyph_array_index: (index into glyph_names) the glyph name corresponding * to the glyph_index */ - cairo_warn cairo_int_status_t (*index_to_glyph_name)(void *scaled_font, char **glyph_names, @@ -628,6 +616,10 @@ struct _cairo_scaled_font_backend { unsigned char *buffer, unsigned long *length); + /* Check if font has any color glyphs. + * @scaled_font: font + * Returns TRUE if font contains any color glyphs + */ cairo_bool_t (*has_color_glyphs) (void *scaled_font); }; @@ -674,6 +666,12 @@ extern const cairo_private struct _cairo_font_face_backend _cairo_win32_font_fac #endif +#if CAIRO_HAS_DWRITE_FONT + +extern const cairo_private struct _cairo_font_face_backend _cairo_dwrite_font_face_backend; + +#endif + #if CAIRO_HAS_QUARTZ_FONT extern const cairo_private struct _cairo_font_face_backend _cairo_quartz_font_face_backend; @@ -702,11 +700,17 @@ struct _cairo_surface_attributes { #define CAIRO_FONT_WEIGHT_DEFAULT CAIRO_FONT_WEIGHT_NORMAL #define CAIRO_WIN32_FONT_FAMILY_DEFAULT "Arial" +#define CAIRO_DWRITE_FONT_FAMILY_DEFAULT "Arial" #define CAIRO_QUARTZ_FONT_FAMILY_DEFAULT "Helvetica" #define CAIRO_FT_FONT_FAMILY_DEFAULT "" #define CAIRO_USER_FONT_FAMILY_DEFAULT "@cairo:" -#if CAIRO_HAS_WIN32_FONT +#if CAIRO_HAS_DWRITE_FONT + +#define CAIRO_FONT_FAMILY_DEFAULT CAIRO_DWRITE_FONT_FAMILY_DEFAULT +#define CAIRO_FONT_FACE_BACKEND_DEFAULT &_cairo_dwrite_font_face_backend + +#elif CAIRO_HAS_WIN32_FONT #define CAIRO_FONT_FAMILY_DEFAULT CAIRO_WIN32_FONT_FAMILY_DEFAULT #define CAIRO_FONT_FACE_BACKEND_DEFAULT &_cairo_win32_font_face_backend @@ -893,6 +897,10 @@ cairo_private void _cairo_font_options_init_copy (cairo_font_options_t *options, const cairo_font_options_t *other); +cairo_private cairo_bool_t +_cairo_font_options_compare (const cairo_font_options_t *a, + const cairo_font_options_t *b); + cairo_private void _cairo_font_options_fini (cairo_font_options_t *options); @@ -936,6 +944,13 @@ _cairo_get_locale_decimal_point (void); cairo_private double _cairo_strtod (const char *nptr, char **endptr); +#ifdef HAVE_STRNDUP +#define _cairo_strndup strndup +#else +cairo_private char * +_cairo_strndup (const char *s, size_t n); +#endif + /* cairo-path-fixed.c */ cairo_private cairo_path_fixed_t * _cairo_path_fixed_create (void); @@ -1278,17 +1293,20 @@ _cairo_scaled_glyph_set_path (cairo_scaled_glyph_t *scaled_glyph, cairo_private void _cairo_scaled_glyph_set_recording_surface (cairo_scaled_glyph_t *scaled_glyph, cairo_scaled_font_t *scaled_font, - cairo_surface_t *recording_surface); + cairo_surface_t *recording_surface, + const cairo_color_t *foreground_color); cairo_private void _cairo_scaled_glyph_set_color_surface (cairo_scaled_glyph_t *scaled_glyph, cairo_scaled_font_t *scaled_font, - cairo_image_surface_t *surface); + cairo_image_surface_t *surface, + const cairo_color_t *foreground_color); cairo_private cairo_int_status_t _cairo_scaled_glyph_lookup (cairo_scaled_font_t *scaled_font, unsigned long index, cairo_scaled_glyph_info_t info, + const cairo_color_t *foreground_color, cairo_scaled_glyph_t **scaled_glyph_ret); cairo_private double @@ -1466,6 +1484,11 @@ _cairo_surface_tag (cairo_surface_t *surface, const char *tag_name, const char *attributes); +cairo_private cairo_bool_t +_cairo_surface_supports_color_glyph (cairo_surface_t *surface, + cairo_scaled_font_t *scaled_font, + unsigned long glyph_index); + cairo_private cairo_status_t _cairo_surface_acquire_source_image (cairo_surface_t *surface, cairo_image_surface_t **image_out, @@ -1580,6 +1603,7 @@ cairo_private cairo_bool_t _pixman_format_to_masks (pixman_format_code_t pixman_format, cairo_format_masks_t *masks); + cairo_private void _cairo_image_scaled_glyph_fini (cairo_scaled_font_t *scaled_font, cairo_scaled_glyph_t *scaled_glyph); @@ -1839,6 +1863,12 @@ _cairo_debug_print_matrix (FILE *file, const cairo_matrix_t *matrix); cairo_private void _cairo_debug_print_rect (FILE *file, const cairo_rectangle_int_t *rect); +cairo_private const char * +_cairo_debug_operator_to_string (cairo_operator_t op); + +cairo_private const char * +_cairo_debug_status_to_string (cairo_int_status_t status); + cairo_private cairo_status_t _cairo_bentley_ottmann_tessellate_rectilinear_polygon (cairo_traps_t *traps, const cairo_polygon_t *polygon, @@ -1878,13 +1908,6 @@ _cairo_trapezoid_array_translate_and_scale (cairo_trapezoid_t *offset_traps, double tx, double ty, double sx, double sy); -#if CAIRO_HAS_DRM_SURFACE - -cairo_private void -_cairo_drm_device_reset_static_data (void); - -#endif - cairo_private void _cairo_clip_reset_static_data (void); @@ -1911,7 +1934,7 @@ cairo_private int _cairo_ucs4_to_utf16 (uint32_t unicode, uint16_t *utf16); -#if CAIRO_HAS_WIN32_FONT || CAIRO_HAS_QUARTZ_FONT || CAIRO_HAS_PDF_OPERATORS +#if _WIN32 || CAIRO_HAS_WIN32_FONT || CAIRO_HAS_QUARTZ_FONT || CAIRO_HAS_PDF_OPERATORS # define CAIRO_HAS_UTF8_TO_UTF16 1 #endif #if CAIRO_HAS_UTF8_TO_UTF16 @@ -1936,176 +1959,6 @@ _cairo_observers_notify (cairo_list_t *observers, void *arg); cairo_private cairo_status_t _cairo_fopen (const char *filename, const char *mode, FILE **file_out); -/* Avoid unnecessary PLT entries. */ -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_get_user_data); -slim_hidden_proto_no_warn (cairo_font_face_reference); -slim_hidden_proto (cairo_font_face_set_user_data); -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_font_options_status); -slim_hidden_proto (cairo_format_stride_for_width); -slim_hidden_proto (cairo_get_current_point); -slim_hidden_proto (cairo_get_line_width); -slim_hidden_proto (cairo_get_matrix); -slim_hidden_proto (cairo_get_scaled_font); -slim_hidden_proto (cairo_get_target); -slim_hidden_proto (cairo_get_tolerance); -slim_hidden_proto (cairo_glyph_allocate); -slim_hidden_proto (cairo_glyph_free); -slim_hidden_proto (cairo_image_surface_create); -slim_hidden_proto (cairo_image_surface_create_for_data); -slim_hidden_proto (cairo_image_surface_get_data); -slim_hidden_proto (cairo_image_surface_get_format); -slim_hidden_proto (cairo_image_surface_get_height); -slim_hidden_proto (cairo_image_surface_get_stride); -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_add_color_stop_rgba); -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_mesh_pattern_curve_to); -slim_hidden_proto (cairo_mesh_pattern_get_control_point); -slim_hidden_proto (cairo_mesh_pattern_get_corner_color_rgba); -slim_hidden_proto (cairo_mesh_pattern_get_patch_count); -slim_hidden_proto (cairo_mesh_pattern_get_path); -slim_hidden_proto (cairo_mesh_pattern_line_to); -slim_hidden_proto (cairo_mesh_pattern_move_to); -slim_hidden_proto (cairo_mesh_pattern_set_corner_color_rgba); -slim_hidden_proto_no_warn (cairo_pattern_reference); -slim_hidden_proto (cairo_pattern_set_matrix); -slim_hidden_proto (cairo_pop_group); -slim_hidden_proto (cairo_push_group_with_content); -slim_hidden_proto_no_warn (cairo_path_destroy); -slim_hidden_proto (cairo_recording_surface_create); -slim_hidden_proto (cairo_rel_line_to); -slim_hidden_proto (cairo_restore); -slim_hidden_proto (cairo_save); -slim_hidden_proto (cairo_scale); -slim_hidden_proto (cairo_scaled_font_create); -slim_hidden_proto (cairo_scaled_font_destroy); -slim_hidden_proto (cairo_scaled_font_extents); -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_no_warn (cairo_scaled_font_reference); -slim_hidden_proto (cairo_scaled_font_status); -slim_hidden_proto (cairo_scaled_font_get_user_data); -slim_hidden_proto (cairo_scaled_font_set_user_data); -slim_hidden_proto (cairo_scaled_font_text_to_glyphs); -slim_hidden_proto (cairo_set_font_matrix); -slim_hidden_proto (cairo_set_font_options); -slim_hidden_proto (cairo_set_font_size); -slim_hidden_proto (cairo_set_line_cap); -slim_hidden_proto (cairo_set_line_join); -slim_hidden_proto (cairo_set_line_width); -slim_hidden_proto (cairo_set_matrix); -slim_hidden_proto (cairo_set_operator); -slim_hidden_proto (cairo_set_source); -slim_hidden_proto (cairo_set_source_rgb); -slim_hidden_proto (cairo_set_source_surface); -slim_hidden_proto (cairo_set_tolerance); -slim_hidden_proto (cairo_status); -slim_hidden_proto (cairo_stroke); -slim_hidden_proto (cairo_stroke_preserve); -slim_hidden_proto (cairo_surface_copy_page); -slim_hidden_proto (cairo_surface_create_similar_image); -slim_hidden_proto (cairo_surface_destroy); -slim_hidden_proto (cairo_surface_finish); -slim_hidden_proto (cairo_surface_flush); -slim_hidden_proto (cairo_surface_get_device_offset); -slim_hidden_proto (cairo_surface_get_device_scale); -slim_hidden_proto (cairo_surface_get_font_options); -slim_hidden_proto (cairo_surface_get_mime_data); -slim_hidden_proto (cairo_surface_has_show_text_glyphs); -slim_hidden_proto (cairo_surface_mark_dirty); -slim_hidden_proto (cairo_surface_mark_dirty_rectangle); -slim_hidden_proto_no_warn (cairo_surface_reference); -slim_hidden_proto (cairo_surface_set_device_offset); -slim_hidden_proto (cairo_surface_set_device_scale); -slim_hidden_proto (cairo_surface_set_fallback_resolution); -slim_hidden_proto (cairo_surface_set_mime_data); -slim_hidden_proto (cairo_surface_show_page); -slim_hidden_proto (cairo_surface_status); -slim_hidden_proto (cairo_surface_supports_mime_type); -slim_hidden_proto (cairo_text_cluster_allocate); -slim_hidden_proto (cairo_text_cluster_free); -slim_hidden_proto (cairo_toy_font_face_create); -slim_hidden_proto (cairo_toy_font_face_get_slant); -slim_hidden_proto (cairo_toy_font_face_get_weight); -slim_hidden_proto (cairo_translate); -slim_hidden_proto (cairo_transform); -slim_hidden_proto (cairo_user_font_face_create); -slim_hidden_proto (cairo_user_font_face_set_init_func); -slim_hidden_proto (cairo_user_font_face_set_render_glyph_func); -slim_hidden_proto (cairo_user_font_face_set_unicode_to_glyph_func); -slim_hidden_proto (cairo_device_to_user); -slim_hidden_proto (cairo_user_to_device); -slim_hidden_proto (cairo_user_to_device_distance); -slim_hidden_proto (cairo_version_string); -slim_hidden_proto (cairo_region_create); -slim_hidden_proto (cairo_region_create_rectangle); -slim_hidden_proto (cairo_region_create_rectangles); -slim_hidden_proto (cairo_region_copy); -slim_hidden_proto (cairo_region_reference); -slim_hidden_proto (cairo_region_destroy); -slim_hidden_proto (cairo_region_equal); -slim_hidden_proto (cairo_region_status); -slim_hidden_proto (cairo_region_get_extents); -slim_hidden_proto (cairo_region_num_rectangles); -slim_hidden_proto (cairo_region_get_rectangle); -slim_hidden_proto (cairo_region_is_empty); -slim_hidden_proto (cairo_region_contains_rectangle); -slim_hidden_proto (cairo_region_contains_point); -slim_hidden_proto (cairo_region_translate); -slim_hidden_proto (cairo_region_subtract); -slim_hidden_proto (cairo_region_subtract_rectangle); -slim_hidden_proto (cairo_region_intersect); -slim_hidden_proto (cairo_region_intersect_rectangle); -slim_hidden_proto (cairo_region_union); -slim_hidden_proto (cairo_region_union_rectangle); -slim_hidden_proto (cairo_region_xor); -slim_hidden_proto (cairo_region_xor_rectangle); - -#if CAIRO_HAS_PNG_FUNCTIONS - -slim_hidden_proto (cairo_surface_write_to_png_stream); - -#endif - -CAIRO_END_DECLS - #include "cairo-mutex-private.h" #include "cairo-fixed-private.h" #include "cairo-wideint-private.h" @@ -2147,4 +2000,6 @@ _cairo_debug_print_clip (FILE *stream, const cairo_clip_t *clip); #define TRACE_(x) #endif +CAIRO_END_DECLS + #endif diff --git a/gfx/cairo/cairo/src/check-def.sh b/gfx/cairo/cairo/src/check-def.sh deleted file mode 100755 index beefb46a33..0000000000 --- a/gfx/cairo/cairo/src/check-def.sh +++ /dev/null @@ -1,48 +0,0 @@ -#!/bin/sh - -LC_ALL=C -export LC_ALL - -if which nm 2>/dev/null >/dev/null; then - : -else - echo "'nm' not found; skipping test" - exit 0 -fi - -test -z "$srcdir" && srcdir=. -test -z "$MAKE" && MAKE=make -stat=0 - -$MAKE check-has-hidden-symbols.i > /dev/null || exit 1 -if tail -1 check-has-hidden-symbols.i | grep CAIRO_HAS_HIDDEN_SYMBOLS >/dev/null; then - echo "Compiler doesn't support symbol visibility; skipping test" - exit 0 -fi - -if [ "`uname -s`" = "Linux" ]; then - get_cairo_syms='( objdump -t "$so" | grep "^[^ ]* [^l.*]*[.]"; objdump -t "$so" | grep "[.]hidden.*\\<cairo"; ) | sed "s/.* //"' -else - get_cairo_syms='nm "$so" | grep " [BCDGINRSTVW] " | cut -d" " -f3' -fi - -defs="cairo.def" -$MAKE $defs > /dev/null -for def in $defs; do - lib=`echo "$def" | sed 's/[.]def$//'` - lib=`echo "$lib" | sed 's@.*/@@'` - so=.libs/lib${lib}.so - - test -f "$so" || continue - - echo Checking that $so has the same symbol list as $def - - { - echo EXPORTS - eval $get_cairo_syms | c++filt --no-params | grep -v '^_cairo_test_\|^_fini\|^_init\|^_save[fg]pr\|^_rest[fg]pr\|^_Z\|^__gnu\|^__bss\|^_edata\|^_end' | sort -u - # cheat: copy the last line from the def file! - tail -n1 "$def" - } | diff "$def" - >&2 || stat=1 -done - -exit $stat diff --git a/gfx/cairo/cairo/src/check-doc-syntax.sh b/gfx/cairo/cairo/src/check-doc-syntax.sh index 762a48429b..57bbc91fdc 100755 --- a/gfx/cairo/cairo/src/check-doc-syntax.sh +++ b/gfx/cairo/cairo/src/check-doc-syntax.sh @@ -28,7 +28,7 @@ enum_regexp="\([^%@']\|^\)\<\(FALSE\|TRUE\|NULL\|CAIRO_[0-9A-Z_]*\)\($\|[^(A-Za- if test "x$SGML_DOCS" = x; then enum_regexp='^[^:]*:[/ ][*]\(\|[ \t].*\)'$enum_regexp\($\|[^:]\) fi -if echo $FILES | xargs grep . /dev/null | sed -e '/<programlisting>/,/<\/programlisting>/d' | grep "$enum_regexp" | grep -v '#####'; then +if echo $FILES | xargs grep . /dev/null | sed -e '/<programlisting>/,/<\/programlisting>/d' -e '/\|\[/,/\]\|/d' | grep "$enum_regexp" | grep -v '#####'; then stat=1 echo Error: some macros in the docs are not prefixed by percent sign. echo Fix this by searching for the following regexp in the above files: @@ -42,7 +42,7 @@ else type_regexp='\(.'$type_regexp'\)\|\('$type_regexp'.\)' fi -if echo $FILES | xargs grep . /dev/null | sed -e '/<programlisting>/,/<\/programlisting>/d' | grep -v "@Title" | grep "$type_regexp" | grep -v '#####'; then +if echo $FILES | xargs grep . /dev/null | sed -e '/<programlisting>/,/<\/programlisting>/d' -e '/\|\[/,/\]\|/d' | grep -v "@Title" | grep "$type_regexp" | grep -v '#####'; then stat=1 echo Error: some type names in the docs are not prefixed by hash sign, echo neither are the only token in the doc line followed by colon. @@ -56,7 +56,7 @@ if test "x$SGML_DOCS" = x; then fi # We need to filter out gtk-doc markup errors for program listings. -if echo $FILES | xargs grep . /dev/null | sed -e '/<programlisting>/,/<\/programlisting>/d' | grep "$func_regexp" | grep -v '^[^:]*: [*] [a-z_0-9]*:$' | grep -v '#####'; then +if echo $FILES | xargs grep . /dev/null | sed -e '/<programlisting>/,/<\/programlisting>/d' -e '/\|\[/,/\]\|/d' | grep "$func_regexp" | grep -v '^[^:]*: [*] [a-z_0-9]*:$' | grep -v '#####'; then stat=1 echo Error: some function names in the docs are not followed by parentheses. echo Fix this by searching for the following regexp in the above files: diff --git a/gfx/cairo/cairo/src/check-has-hidden-symbols.c b/gfx/cairo/cairo/src/check-has-hidden-symbols.c deleted file mode 100644 index 1204127769..0000000000 --- a/gfx/cairo/cairo/src/check-has-hidden-symbols.c +++ /dev/null @@ -1,3 +0,0 @@ -#include "cairoint.h" - -CAIRO_HAS_HIDDEN_SYMBOLS diff --git a/gfx/cairo/cairo/src/check-headers.sh b/gfx/cairo/cairo/src/check-headers.sh index 61232954ba..b4f14571d8 100755 --- a/gfx/cairo/cairo/src/check-headers.sh +++ b/gfx/cairo/cairo/src/check-headers.sh @@ -11,7 +11,7 @@ echo Checking public headers for missing cairo_public decorators cd "$srcdir" FILES=$all_cairo_headers if test "x$FILES" = x; then - FILES=`find . -name 'cairo*.h' ! -name '*-private.h' ! -name 'cairoint.h'` + FILES=`find . -name 'cairo*.h' ! -name '*-private.h' ! -name 'cairoint.h' ! -name '*-inline.h'` fi grep -B 1 '^cairo_.*[ ]\+(' /dev/null $FILES | diff --git a/gfx/cairo/cairo/src/check-plt.sh b/gfx/cairo/cairo/src/check-plt.sh deleted file mode 100755 index 5a9dae1269..0000000000 --- a/gfx/cairo/cairo/src/check-plt.sh +++ /dev/null @@ -1,28 +0,0 @@ -#!/bin/sh - -LC_ALL=C -export LC_ALL - -if which readelf 2>/dev/null >/dev/null; then - : -else - echo "'readelf' not found; skipping test" - exit 0 -fi - -test -z "$srcdir" && srcdir=. -test -z "$MAKE" && MAKE=make -stat=0 - -$MAKE check-has-hidden-symbols.i > /dev/null || exit 1 -if tail -1 check-has-hidden-symbols.i | grep CAIRO_HAS_HIDDEN_SYMBOLS >/dev/null; then - echo "Compiler doesn't support symbol visibility; skipping test" - exit 0 -fi - -for so in .libs/lib*.so; do - echo Checking "$so" for local PLT entries - readelf -W -r "$so" | grep 'JU\?MP_SLO' | grep 'cairo' >&2 && stat=1 -done - -exit $stat diff --git a/gfx/cairo/cairo/src/check-preprocessor-syntax.sh b/gfx/cairo/cairo/src/check-preprocessor-syntax.sh index b718f604ee..fa0fa715ff 100755 --- a/gfx/cairo/cairo/src/check-preprocessor-syntax.sh +++ b/gfx/cairo/cairo/src/check-preprocessor-syntax.sh @@ -49,7 +49,7 @@ grep . >&2 && stat=1 echo 'Checking that there is no #include <cairo.*.h>' -grep '#.*\<include\>.*<.*cairo' $ALL >&2 && stat=1 +grep '^[^*]#.*\<include\>.*<.*cairo' $ALL >&2 && stat=1 echo 'Checking that feature conditionals are used with #if only (not #ifdef)' diff --git a/gfx/cairo/cairo/src/config.h b/gfx/cairo/cairo/src/config.h new file mode 100644 index 0000000000..67cfb52510 --- /dev/null +++ b/gfx/cairo/cairo/src/config.h @@ -0,0 +1,2 @@ +/* Dummy config.h file, because cairo 1.18.0 wants to #include it + * unconditionally, but the Gecko build doesn't use it. */ diff --git a/gfx/cairo/cairo/src/drm/cairo-drm-bo.c b/gfx/cairo/cairo/src/drm/cairo-drm-bo.c deleted file mode 100644 index c82f9331d8..0000000000 --- a/gfx/cairo/cairo/src/drm/cairo-drm-bo.c +++ /dev/null @@ -1,99 +0,0 @@ -/* Cairo - a vector graphics library with display and print output - * - * Copyright © 2009 Chris Wilson - * - * 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., 51 Franklin Street, Suite 500, Boston, MA 02110-1335, 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. - * - */ - -#include "cairoint.h" -#include "cairo-drm-private.h" -#include "cairo-error-private.h" - -#include <sys/ioctl.h> -#include <errno.h> -#include <libdrm/drm.h> - -#define ERR_DEBUG(x) x - -cairo_status_t -_cairo_drm_bo_open_for_name (const cairo_drm_device_t *dev, - cairo_drm_bo_t *bo, - uint32_t name) -{ - struct drm_gem_open open; - int ret; - - open.name = name; - open.handle = 0; - open.size = 0; - do { - ret = ioctl (dev->fd, DRM_IOCTL_GEM_OPEN, &open); - } while (ret == -1 && errno == EINTR); - if (ret == -1) { - ERR_DEBUG((fprintf (stderr, "Failed to open bo for name %d: %s\n", - name, strerror (errno)))); - return _cairo_error (CAIRO_STATUS_NO_MEMORY); - } - - bo->name = name; - bo->size = open.size; - bo->handle = open.handle; - - return CAIRO_STATUS_SUCCESS; -} - -cairo_status_t -_cairo_drm_bo_flink (const cairo_drm_device_t *dev, - cairo_drm_bo_t *bo) -{ - struct drm_gem_flink flink; - int ret; - - memset (&flink, 0, sizeof (flink)); - flink.handle = bo->handle; - ret = ioctl (dev->fd, DRM_IOCTL_GEM_FLINK, &flink); - if (ret == -1) { - ERR_DEBUG((fprintf (stderr, "Failed to flink bo: %s\n", - strerror (errno)))); - return _cairo_error (CAIRO_STATUS_NO_MEMORY); - } - - bo->name = flink.name; - - return CAIRO_STATUS_SUCCESS; -} - -void -_cairo_drm_bo_close (const cairo_drm_device_t *dev, - cairo_drm_bo_t *bo) -{ - struct drm_gem_close close; - int ret; - - close.handle = bo->handle; - do { - ret = ioctl (dev->fd, DRM_IOCTL_GEM_CLOSE, &close); - } while (ret == -1 && errno == EINTR); -} diff --git a/gfx/cairo/cairo/src/drm/cairo-drm-gallium-surface.c b/gfx/cairo/cairo/src/drm/cairo-drm-gallium-surface.c deleted file mode 100644 index ca18f7336c..0000000000 --- a/gfx/cairo/cairo/src/drm/cairo-drm-gallium-surface.c +++ /dev/null @@ -1,826 +0,0 @@ -/* Cairo - a vector graphics library with display and print output - * - * Copyright © 2009 Chris Wilson - * Copyright © 2009 Eric Anholt - * - * 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., 51 Franklin Street, Suite 500, Boston, MA 02110-1335, 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 Chris Wilson. - */ - -#include "cairoint.h" - -#include "cairo-drm-private.h" -#include "cairo-default-context-private.h" -#include "cairo-error-private.h" - -#include <dlfcn.h> - -#include <state_tracker/drm_api.h> -#include <pipe/p_format.h> -#include <pipe/p_screen.h> -#include <pipe/p_context.h> -#include <pipe/p_state.h> - -#include <util/u_inlines.h> - -typedef struct _gallium_surface gallium_surface_t; -typedef struct _gallium_device gallium_device_t; - -struct _gallium_device { - cairo_drm_device_t drm; - - void *dlhandle; - struct drm_api *api; - - struct pipe_screen *screen; - struct pipe_context *pipe; - - int max_size; -}; - -struct _gallium_surface { - cairo_drm_surface_t drm; - - enum pipe_format pipe_format; - - struct pipe_resource *texture; - struct pipe_transfer *map_transfer; - - cairo_surface_t *fallback; -}; - -static cairo_surface_t * -gallium_surface_create_internal (gallium_device_t *device, - enum pipe_format format, - int width, int height); - -static inline gallium_device_t * -gallium_device (gallium_surface_t *surface) -{ - return (gallium_device_t *) surface->drm.base.device; -} - -static cairo_format_t -_cairo_format_from_pipe_format (enum pipe_format format) -{ - switch ((int) format) { - case PIPE_FORMAT_A8_UNORM: - return CAIRO_FORMAT_A8; - case PIPE_FORMAT_A8R8G8B8_UNORM: - return CAIRO_FORMAT_ARGB32; - default: - return CAIRO_FORMAT_INVALID; - } -} - -static enum pipe_format -pipe_format_from_format (cairo_format_t format) -{ - switch ((int) format) { - case CAIRO_FORMAT_A8: - return PIPE_FORMAT_A8_UNORM; - case CAIRO_FORMAT_ARGB32: - return PIPE_FORMAT_A8R8G8B8_UNORM; - default: - return (enum pipe_format) -1; - } -} - -static enum pipe_format -pipe_format_from_content (cairo_content_t content) -{ - if (content == CAIRO_CONTENT_ALPHA) - return PIPE_FORMAT_A8_UNORM; - else - return PIPE_FORMAT_A8R8G8B8_UNORM; -} - -static cairo_bool_t -format_is_supported_destination (gallium_device_t *device, - enum pipe_format format) -{ - if (format == (enum pipe_format) -1) - return FALSE; - - return device->screen->is_format_supported (device->screen, - format, - 0, - PIPE_BIND_RENDER_TARGET, - 0); -} - -#if 0 -static cairo_bool_t -format_is_supported_source (gallium_device_t *device, - enum pipe_format format) -{ - return device->screen->is_format_supported (device->screen, - format, - 0, - PIPE_BIND_SAMPLER_VIEW, - 0); -} -#endif - -static cairo_surface_t * -gallium_surface_create_similar (void *abstract_src, - cairo_content_t content, - int width, - int height) -{ - gallium_surface_t *other = abstract_src; - gallium_device_t *device = gallium_device (other); - enum pipe_format pipe_format; - cairo_surface_t *surface = NULL; - cairo_status_t status; - - status = cairo_device_acquire (&device->drm.base); - if (unlikely (status)) - return _cairo_surface_create_in_error (status); - - if (MAX (width, height) > device->max_size) - goto RELEASE; - - if (content == other->drm.base.content) - pipe_format = other->pipe_format; - else - pipe_format = pipe_format_from_content (content); - - if (! format_is_supported_destination (device, pipe_format)) - goto RELEASE; - - surface = gallium_surface_create_internal (device, - pipe_format, - width, height); - -RELEASE: - cairo_device_release (&device->drm.base); - - return surface; -} - -static cairo_status_t -gallium_surface_finish (void *abstract_surface) -{ - gallium_surface_t *surface = abstract_surface; - gallium_device_t *device = gallium_device (surface); - cairo_status_t status; - - status = cairo_device_acquire (&device->drm.base); - if (likely (status == CAIRO_STATUS_SUCCESS)) { - pipe_resource_reference (&surface->texture, NULL); - cairo_device_release (&device->drm.base); - } - - return _cairo_drm_surface_finish (&surface->drm); -} - -static cairo_surface_t * -gallium_surface_map_to_image (gallium_surface_t *surface) -{ - gallium_device_t *device = gallium_device (surface); - cairo_status_t status; - void *ptr = NULL; - - status = cairo_device_acquire (&device->drm.base); - if (unlikely (status)) - return _cairo_surface_create_in_error (status); - - surface->map_transfer = - pipe_get_transfer (device->pipe, - surface->texture, 0, 0, 0, - PIPE_TRANSFER_MAP_DIRECTLY | - PIPE_TRANSFER_READ_WRITE, - 0, 0, - surface->drm.width, - surface->drm.height); - if (likely (surface->map_transfer != NULL)) - ptr = device->pipe->transfer_map (device->pipe, surface->map_transfer); - - cairo_device_release (&device->drm.base); - - if (unlikely (ptr == NULL)) { - if (surface->map_transfer != NULL) { - device->pipe->transfer_destroy (device->pipe, - surface->map_transfer); - surface->map_transfer = NULL; - } - return _cairo_surface_create_in_error (_cairo_error (CAIRO_STATUS_NO_MEMORY)); - } - - return cairo_image_surface_create_for_data (ptr, - surface->drm.format, - surface->drm.width, - surface->drm.height, - surface->map_transfer->stride); -} - -static cairo_status_t -gallium_surface_acquire_source_image (void *abstract_surface, - cairo_image_surface_t **image_out, - void **image_extra) -{ - gallium_surface_t *surface = abstract_surface; - gallium_device_t *device = gallium_device (surface); - cairo_format_t format; - cairo_surface_t *image; - cairo_status_t status; - struct pipe_transfer *transfer; - void *ptr; - - if (surface->fallback != NULL) { - *image_out = (cairo_image_surface_t *) - cairo_surface_reference (surface->fallback); - *image_extra = NULL; - return CAIRO_STATUS_SUCCESS; - } - - if (unlikely (surface->drm.width == 0 || surface->drm.height == 0)) { - image = cairo_image_surface_create (surface->drm.format, 0, 0); - if (unlikely (image->status)) - return image->status; - - *image_out = (cairo_image_surface_t *) image; - *image_extra = NULL; - return CAIRO_STATUS_SUCCESS; - } - - format = _cairo_format_from_pipe_format (surface->pipe_format); - if (format == CAIRO_FORMAT_INVALID) - return CAIRO_INT_STATUS_UNSUPPORTED; - - status = cairo_device_acquire (&device->drm.base); - if (unlikely (status)) - return status; - - transfer = pipe_get_transfer (device->pipe, - surface->texture, 0, 0, 0, - PIPE_TRANSFER_READ, - 0, 0, - surface->drm.width, - surface->drm.height); - ptr = device->pipe->transfer_map (device->pipe, transfer); - cairo_device_release (&device->drm.base); - - image = cairo_image_surface_create_for_data (ptr, format, - surface->drm.width, - surface->drm.height, - surface->drm.stride); - if (unlikely (image->status)) - return image->status; - - *image_out = (cairo_image_surface_t *) image; - *image_extra = transfer; - return CAIRO_STATUS_SUCCESS; -} - -static void -gallium_surface_release_source_image (void *abstract_surface, - cairo_image_surface_t *image, - void *image_extra) -{ - cairo_surface_destroy (&image->base); - - if (image_extra != NULL) { - gallium_device_t *device = gallium_device (abstract_surface); - - device->pipe->transfer_unmap (device->pipe, image_extra); - device->pipe->transfer_destroy (device->pipe, image_extra); - } -} - -static cairo_status_t -gallium_surface_flush (void *abstract_surface, - unsigned flags) -{ - gallium_surface_t *surface = abstract_surface; - gallium_device_t *device = gallium_device (surface); - cairo_status_t status; - - if (flags) - return CAIRO_STATUS_SUCCESS; - - if (surface->fallback == NULL) { - device->pipe->flush (device->pipe, - PIPE_FLUSH_RENDER_CACHE, - NULL); - return CAIRO_STATUS_SUCCESS; - } - - /* kill any outstanding maps */ - cairo_surface_finish (surface->fallback); - - status = cairo_device_acquire (&device->drm.base); - if (likely (status == CAIRO_STATUS_SUCCESS)) { - device->pipe->transfer_unmap (device->pipe, - surface->map_transfer); - device->pipe->transfer_destroy (device->pipe, - surface->map_transfer); - surface->map_transfer = NULL; - cairo_device_release (&device->drm.base); - } - - status = cairo_surface_status (surface->fallback); - cairo_surface_destroy (surface->fallback); - surface->fallback = NULL; - - return status; -} - -static cairo_int_status_t -gallium_surface_paint (void *abstract_surface, - cairo_operator_t op, - const cairo_pattern_t *source, - cairo_clip_t *clip) -{ - gallium_surface_t *surface = abstract_surface; - - if (surface->fallback == NULL) { - /* XXX insert magic */ - surface->fallback = gallium_surface_map_to_image (surface); - } - - return _cairo_surface_paint (surface->fallback, op, source, clip); -} - -static cairo_int_status_t -gallium_surface_mask (void *abstract_surface, - cairo_operator_t op, - const cairo_pattern_t *source, - const cairo_pattern_t *mask, - cairo_clip_t *clip) -{ - gallium_surface_t *surface = abstract_surface; - - if (surface->fallback == NULL) { - /* XXX insert magic */ - surface->fallback = gallium_surface_map_to_image (surface); - } - - return _cairo_surface_mask (surface->fallback, - op, source, mask, - clip); -} - -static cairo_int_status_t -gallium_surface_stroke (void *abstract_surface, - cairo_operator_t op, - const cairo_pattern_t *source, - cairo_path_fixed_t *path, - const cairo_stroke_style_t *style, - const cairo_matrix_t *ctm, - const cairo_matrix_t *ctm_inverse, - double tolerance, - cairo_antialias_t antialias, - cairo_clip_t *clip) -{ - gallium_surface_t *surface = abstract_surface; - - if (surface->fallback == NULL) { - /* XXX insert magic */ - surface->fallback = gallium_surface_map_to_image (surface); - } - - return _cairo_surface_stroke (surface->fallback, - op, source, - path, style, - ctm, ctm_inverse, - tolerance, antialias, - clip); -} - -static cairo_int_status_t -gallium_surface_fill (void *abstract_surface, - cairo_operator_t op, - const cairo_pattern_t *source, - cairo_path_fixed_t *path, - cairo_fill_rule_t fill_rule, - double tolerance, - cairo_antialias_t antialias, - cairo_clip_t *clip) -{ - gallium_surface_t *surface = abstract_surface; - - if (surface->fallback == NULL) { - /* XXX insert magic */ - surface->fallback = gallium_surface_map_to_image (surface); - } - - return _cairo_surface_fill (surface->fallback, - op, source, - path, fill_rule, - tolerance, antialias, - clip); -} - -static cairo_int_status_t -gallium_surface_glyphs (void *abstract_surface, - cairo_operator_t op, - const cairo_pattern_t *source, - cairo_glyph_t *glyphs, - int num_glyphs, - cairo_scaled_font_t *scaled_font, - cairo_clip_t *clip, - int *num_remaining) -{ - gallium_surface_t *surface = abstract_surface; - - *num_remaining = 0; - - if (surface->fallback == NULL) { - /* XXX insert magic */ - surface->fallback = gallium_surface_map_to_image (surface); - } - - return _cairo_surface_show_text_glyphs (surface->fallback, - op, source, - NULL, 0, - glyphs, num_glyphs, - NULL, 0, 0, - scaled_font, - clip); -} - -static const cairo_surface_backend_t gallium_surface_backend = { - CAIRO_SURFACE_TYPE_DRM, - _cairo_default_context_create, - - gallium_surface_create_similar, - gallium_surface_finish, - - NULL, - gallium_surface_acquire_source_image, - gallium_surface_release_source_image, - - NULL, //gallium_surface_acquire_dest_image, - NULL, //gallium_surface_release_dest_image, - NULL, //gallium_surface_clone_similar, - NULL, //gallium_surface_composite, - NULL, //gallium_surface_fill_rectangles, - NULL, //gallium_surface_composite_trapezoids, - NULL, //gallium_surface_create_span_renderer, - NULL, //gallium_surface_check_span_renderer, - NULL, /* copy_page */ - NULL, /* show_page */ - _cairo_drm_surface_get_extents, - NULL, /* old_show_glyphs */ - _cairo_drm_surface_get_font_options, - gallium_surface_flush, - NULL, /* mark_dirty_rectangle */ - NULL, //gallium_surface_scaled_font_fini, - NULL, //gallium_surface_scaled_glyph_fini, - - gallium_surface_paint, - gallium_surface_mask, - gallium_surface_stroke, - gallium_surface_fill, - gallium_surface_glyphs, - - NULL, /* snapshot */ - - NULL, /* is_similar */ - - NULL, /* reset */ -}; - -static int -gallium_format_stride_for_width (enum pipe_format format, int width) -{ - int stride; - - stride = 1024; /* XXX fugly */ - while (stride < width) - stride *= 2; - - if (format == PIPE_FORMAT_A8R8G8B8_UNORM) - stride *= 4; - - return stride; -} - -static cairo_drm_bo_t * -_gallium_fake_bo_create (uint32_t size, uint32_t name) -{ - cairo_drm_bo_t *bo; - - /* XXX integrate with winsys handle */ - - bo = _cairo_malloc (sizeof (cairo_drm_bo_t)); - - CAIRO_REFERENCE_COUNT_INIT (&bo->ref_count, 1); - bo->name = name; - bo->handle = 0; - bo->size = size; - - return bo; -} - -static void -_gallium_fake_bo_release (void *dev, void *bo) -{ - free (bo); -} - -static cairo_surface_t * -gallium_surface_create_internal (gallium_device_t *device, - enum pipe_format pipe_format, - int width, int height) -{ - gallium_surface_t *surface; - struct pipe_resource template; - cairo_status_t status; - cairo_format_t format; - int stride, size; - - surface = _cairo_malloc (sizeof (gallium_surface_t)); - if (unlikely (surface == NULL)) - return _cairo_surface_create_in_error (_cairo_error (CAIRO_STATUS_NO_MEMORY)); - - format = _cairo_format_from_pipe_format (pipe_format); - _cairo_surface_init (&surface->drm.base, - &gallium_surface_backend, - &device->drm.base, - _cairo_content_from_format (format)); - _cairo_drm_surface_init (&surface->drm, format, width, height); - - stride = gallium_format_stride_for_width (pipe_format, width); - size = stride * height; - - surface->drm.stride = stride; - surface->drm.bo = _gallium_fake_bo_create (size, 0); - - memset(&template, 0, sizeof(template)); - template.target = PIPE_TEXTURE_2D; - template.format = pipe_format; - template.width0 = width; - template.height0 = height; - template.depth0 = 1; - template.last_level = 0; - template.bind = PIPE_BIND_RENDER_TARGET; - surface->texture = device->screen->resource_create (device->screen, - &template); - - if (unlikely (surface->texture == NULL)) { - status = _cairo_drm_surface_finish (&surface->drm); - free (surface); - return _cairo_surface_create_in_error (_cairo_error (CAIRO_STATUS_NO_MEMORY)); - } - - surface->pipe_format = pipe_format; - surface->texture = NULL; - - return &surface->drm.base; -} - -static cairo_surface_t * -gallium_surface_create (cairo_drm_device_t *base_dev, - cairo_format_t format, - int width, int height) -{ - gallium_device_t *device = (gallium_device_t *) base_dev; - cairo_surface_t *surface; - enum pipe_format pipe_format; - cairo_status_t status; - - status = cairo_device_acquire (&device->drm.base); - - if (MAX (width, height) > device->max_size) { - surface = _cairo_surface_create_in_error (_cairo_error (CAIRO_STATUS_INVALID_SIZE)); - goto RELEASE; - } - - pipe_format = pipe_format_from_format (format); - if (! format_is_supported_destination (device, pipe_format)) { - surface = _cairo_surface_create_in_error (_cairo_error (CAIRO_STATUS_INVALID_FORMAT)); - goto RELEASE; - } - - surface = gallium_surface_create_internal (device, - pipe_format, - width, height); - -RELEASE: - cairo_device_release (&device->drm.base); - - return surface; -} - -#if 0 -static cairo_surface_t * -gallium_surface_create_for_name (cairo_drm_device_t *base_dev, - unsigned int name, - cairo_format_t format, - int width, int height, int stride) -{ - gallium_device_t *device; - gallium_surface_t *surface; - cairo_status_t status; - cairo_content_t content; - - surface = _cairo_malloc (sizeof (gallium_surface_t)); - if (unlikely (surface == NULL)) - return _cairo_surface_create_in_error (_cairo_error (CAIRO_STATUS_NO_MEMORY)); - - switch (format) { - default: - case CAIRO_FORMAT_INVALID: - case CAIRO_FORMAT_A1: - return _cairo_surface_create_in_error (_cairo_error (CAIRO_STATUS_INVALID_FORMAT)); - case CAIRO_FORMAT_A8: - surface->pipe_format = PIPE_FORMAT_A8_UNORM; - break; - case CAIRO_FORMAT_RGB24: - case CAIRO_FORMAT_ARGB32: - surface->pipe_format = PIPE_FORMAT_A8R8G8B8_UNORM; - break; - } - - status = cairo_device_acquire (&device->drm.base); - - if (MAX (width, height) > device->max_size) { - cairo_device_release (&device->drm.base); - free (surface); - return _cairo_surface_create_in_error (_cairo_error (CAIRO_STATUS_INVALID_SIZE)); - } - - if (! format_is_supported_destination (device, surface->pipe_format)) { - cairo_device_release (&device->drm.base); - free (surface); - return _cairo_surface_create_in_error (_cairo_error (CAIRO_STATUS_INVALID_FORMAT)); - } - - content = _cairo_content_from_format (format); - _cairo_surface_init (&surface->drm.base, - &gallium_surface_backend, - content); - _cairo_drm_surface_init (&surface->drm, base_dev); - - surface->drm.bo = _gallium_fake_bo_create (height * stride, name); - - surface->drm.width = width; - surface->drm.height = height; - surface->drm.stride = stride; - -#if 0 - /* XXX screen->create_from_handle */ - surface->buffer = device->api->buffer_from_handle (device->api, - device->screen, - "cairo-gallium alien", - name); - if (unlikely (surface->buffer == NULL)) { - status = _cairo_drm_surface_finish (&surface->drm); - cairo_device_release (&device->drm.base); - free (surface); - return _cairo_surface_create_in_error (_cairo_error (CAIRO_STATUS_NO_MEMORY)); - } -#endif - - surface->texture = NULL; - - surface->fallback = NULL; - - cairo_device_release (&device->drm.base); - - return &surface->drm.base; -} - -static cairo_int_status_t -gallium_surface_flink (void *abstract_surface) -{ - gallium_surface_t *surface = abstract_surface; - gallium_device_t *device; - cairo_status_t status = CAIRO_STATUS_SUCCESS; - - status = cairo_device_acquire (&device->drm.base); - if (! device->api->global_handle_from_buffer (device->api, - device->screen, - surface->buffer, - &surface->drm.bo->name)) - { - status = _cairo_error (CAIRO_STATUS_NO_MEMORY); - } - cairo_device_release (&device->drm.base); - - return status; -} -#endif - -static void -gallium_device_destroy (void *abstract_device) -{ - gallium_device_t *device = abstract_device; - - device->pipe->destroy (device->pipe); - device->screen->destroy (device->screen); - device->api->destroy (device->api); - - dlclose (device->dlhandle); - free (device); -} - -cairo_drm_device_t * -_cairo_drm_gallium_device_create (int fd, dev_t dev, int vendor_id, int chip_id) -{ - gallium_device_t *device; - cairo_status_t status; - void *handle; - const char *libdir; - char buf[4096]; - struct drm_api *(*ctor) (void); - - /* XXX need search path + probe */ - libdir = getenv ("CAIRO_GALLIUM_LIBDIR"); - if (libdir == NULL) - libdir = "/usr/lib/dri"; - buf[snprintf (buf, sizeof (buf)-1, "%s/i915_dri.so", libdir)] = '\0'; - - handle = dlopen (buf, RTLD_LAZY); - if (handle == NULL) - return NULL; - - ctor = dlsym (handle, "drm_api_create"); - if (ctor == NULL) { - dlclose (handle); - return NULL; - } - - device = _cairo_malloc (sizeof (gallium_device_t)); - if (device == NULL) { - dlclose (handle); - return _cairo_drm_device_create_in_error (_cairo_error (CAIRO_STATUS_NO_MEMORY)); - } - - device->dlhandle = handle; - - device->drm.surface.create = gallium_surface_create; - device->drm.surface.create_for_name = NULL; - //device->drm.surface.create_for_name = gallium_surface_create_for_name; - device->drm.surface.enable_scan_out = NULL; - //device->drm.surface.flink = gallium_surface_flink; - device->drm.surface.flink = NULL; - - device->drm.device.flush = NULL; - device->drm.device.throttle = NULL; - device->drm.device.destroy = gallium_device_destroy; - - device->drm.bo.release = _gallium_fake_bo_release; - - device->api = ctor (); - if (device->api == NULL) { - status = _cairo_error (CAIRO_STATUS_NO_MEMORY); - goto CLEANUP; - } - - device->screen = device->api->create_screen (device->api, fd, NULL); - if (device->screen == NULL) { - status = _cairo_error (CAIRO_STATUS_NO_MEMORY); - goto CLEANUP_API; - } - - device->max_size = 1 << device->screen->get_param (device->screen, - PIPE_CAP_MAX_TEXTURE_2D_LEVELS); - - device->pipe = device->screen->context_create (device->screen, device); - if (device->pipe == NULL) { - status = _cairo_error (CAIRO_STATUS_NO_MEMORY); - goto CLEANUP_SCREEN; - } - - return _cairo_drm_device_init (&device->drm, - fd, dev, - 0, 0, - device->max_size); - -CLEANUP_SCREEN: - device->screen->destroy (device->screen); -CLEANUP_API: - device->api->destroy (device->api); -CLEANUP: - free (device); - dlclose (handle); - return _cairo_drm_device_create_in_error (status); -} diff --git a/gfx/cairo/cairo/src/drm/cairo-drm-i915-glyphs.c b/gfx/cairo/cairo/src/drm/cairo-drm-i915-glyphs.c deleted file mode 100644 index 3b0efc2489..0000000000 --- a/gfx/cairo/cairo/src/drm/cairo-drm-i915-glyphs.c +++ /dev/null @@ -1,564 +0,0 @@ -/* cairo - a vector graphics library with display and print output - * - * Copyright © 2009 Intel Corporation - * - * This library is free software; you can redistribute it and/or - * modify it either under the terms of the GNU Lesser General Public - * License version 2.1 as published by the Free Software Foundation - * (the "LGPL") or, at your option, under the terms of the Mozilla - * Public License Version 1.1 (the "MPL"). If you do not alter this - * notice, a recipient may use your version of this file under either - * the MPL or the LGPL. - * - * You should have received a copy of the LGPL along with this library - * in the file COPYING-LGPL-2.1; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Suite 500, Boston, MA 02110-1335, 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): - * Chris Wilson <chris@chris-wilson.co.uk> - */ - -#include "cairoint.h" - -#include "cairo-composite-rectangles-private.h" -#include "cairo-drm-i915-private.h" -#include "cairo-error-private.h" -#include "cairo-rtree-private.h" -#include "cairo-clip-inline.h" - -static void -i915_emit_glyph_rectangle_zero (i915_device_t *device, - i915_shader_t *shader, - int x1, int y1, - int x2, int y2, - intel_glyph_t *glyph) -{ - float *v; - - /* Each vertex is: - * 2 vertex coordinates - */ - - v = i915_add_rectangle (device); - *v++ = x2; *v++ = y2; - *v++ = x1; *v++ = y2; - *v++ = x1; *v++ = y1; -} - -static void -i915_emit_glyph_rectangle_constant (i915_device_t *device, - i915_shader_t *shader, - int x1, int y1, - int x2, int y2, - intel_glyph_t *glyph) -{ - float *v; - - /* Each vertex is: - * 2 vertex coordinates - * 2 glyph texture coordinates - */ - - v = i915_add_rectangle (device); - - /* bottom right */ - *v++ = x2; *v++ = y2; - *v++ = glyph->texcoord[0]; - - /* bottom left */ - *v++ = x1; *v++ = y2; - *v++ = glyph->texcoord[1]; - - /* top left */ - *v++ = x1; *v++ = y1; - *v++ = glyph->texcoord[2]; -} - -static void -i915_emit_glyph_rectangle_general (i915_device_t *device, - i915_shader_t *shader, - int x1, int y1, - int x2, int y2, - intel_glyph_t *glyph) -{ - double s, t; - float *v; - - /* Each vertex is: - * 2 vertex coordinates - * [0-2] source texture coordinates - * 2 glyph texture coordinates - */ - - v = i915_add_rectangle (device); - - /* bottom right */ - *v++ = x2; *v++ = y2; - s = x2, t = y2; - switch (shader->source.type.vertex) { - case VS_ZERO: - case VS_CONSTANT: - break; - case VS_LINEAR: - *v++ = i915_shader_linear_texcoord (&shader->source.linear, s, t); - break; - case VS_TEXTURE: - cairo_matrix_transform_point (&shader->source.base.matrix, &s, &t); - *v++ = s; *v++ = t; - break; - case VS_TEXTURE_16: - cairo_matrix_transform_point (&shader->source.base.matrix, &s, &t); - *v++ = texcoord_2d_16 (s, t); - break; - } - *v++ = glyph->texcoord[0]; - - /* bottom left */ - *v++ = x1; *v++ = y2; - s = x1, t = y2; - switch (shader->source.type.vertex) { - case VS_ZERO: - case VS_CONSTANT: - break; - case VS_LINEAR: - *v++ = i915_shader_linear_texcoord (&shader->source.linear, s, t); - break; - case VS_TEXTURE: - cairo_matrix_transform_point (&shader->source.base.matrix, &s, &t); - *v++ = s; *v++ = t; - break; - case VS_TEXTURE_16: - cairo_matrix_transform_point (&shader->source.base.matrix, &s, &t); - *v++ = texcoord_2d_16 (s, t); - break; - } - *v++ = glyph->texcoord[1]; - - /* top left */ - *v++ = x1; *v++ = y1; - s = x1, t = y2; - switch (shader->source.type.vertex) { - case VS_ZERO: - case VS_CONSTANT: - break; - case VS_LINEAR: - *v++ = i915_shader_linear_texcoord (&shader->source.linear, s, t); - break; - case VS_TEXTURE: - cairo_matrix_transform_point (&shader->source.base.matrix, &s, &t); - *v++ = s; *v++ = t; - break; - case VS_TEXTURE_16: - cairo_matrix_transform_point (&shader->source.base.matrix, &s, &t); - *v++ = texcoord_2d_16 (s, t); - break; - } - *v++ = glyph->texcoord[2]; -} - -typedef void -(*i915_emit_glyph_rectangle_func_t) (i915_device_t *device, - i915_shader_t *shader, - int x1, int y1, - int x2, int y2, - intel_glyph_t *glyph); - -static cairo_status_t -i915_surface_mask_internal (i915_surface_t *dst, - cairo_operator_t op, - const cairo_pattern_t *source, - i915_surface_t *mask, - cairo_clip_t *clip, - const cairo_composite_rectangles_t *extents) -{ - i915_device_t *device; - i915_shader_t shader; - cairo_region_t *clip_region = NULL; - cairo_status_t status; - - i915_shader_init (&shader, dst, op, 1.); - - status = i915_shader_acquire_pattern (&shader, &shader.source, - source, &extents->bounded); - if (unlikely (status)) - return status; - - shader.mask.type.vertex = VS_TEXTURE_16; - shader.mask.type.pattern = PATTERN_TEXTURE; - shader.mask.type.fragment = FS_TEXTURE; - shader.mask.base.content = mask->intel.drm.base.content; - shader.mask.base.texfmt = TEXCOORDFMT_2D_16; - shader.mask.base.n_samplers = 1; - shader.mask.base.sampler[0] = - (MIPFILTER_NONE << SS2_MIP_FILTER_SHIFT) | - i915_texture_filter (CAIRO_FILTER_NEAREST); - shader.mask.base.sampler[1] = - SS3_NORMALIZED_COORDS | - i915_texture_extend (CAIRO_EXTEND_NONE); - - cairo_matrix_init_translate (&shader.mask.base.matrix, - -extents->bounded.x, - -extents->bounded.y); - cairo_matrix_scale (&shader.mask.base.matrix, - 1. / mask->intel.drm.width, - 1. / mask->intel.drm.height); - - shader.mask.base.bo = intel_bo_reference (to_intel_bo (mask->intel.drm.bo)); - shader.mask.base.offset[0] = 0; - shader.mask.base.map[0] = mask->map0; - shader.mask.base.map[1] = mask->map1; - - if (clip != NULL) { - status = _cairo_clip_get_region (clip, &clip_region); - - if (clip_region != NULL && cairo_region_num_rectangles (clip_region) == 1) - clip_region = NULL; - - if (status == CAIRO_INT_STATUS_UNSUPPORTED) - i915_shader_set_clip (&shader, clip); - } - - status = cairo_device_acquire (dst->intel.drm.base.device); - if (unlikely (status)) - goto CLEANUP_SHADER; - - device = i915_device (dst); - - status = i915_shader_commit (&shader, device); - if (unlikely (status)) - goto CLEANUP_DEVICE; - - if (clip_region != NULL) { - unsigned int n, num_rectangles; - - num_rectangles = cairo_region_num_rectangles (clip_region); - for (n = 0; n < num_rectangles; n++) { - cairo_rectangle_int_t rect; - - cairo_region_get_rectangle (clip_region, n, &rect); - - shader.add_rectangle (&shader, - rect.x, rect.y, - rect.x + rect.width, rect.y + rect.height); - } - } else { - shader.add_rectangle (&shader, - extents->bounded.x, extents->bounded.y, - extents->bounded.x + extents->bounded.width, - extents->bounded.y + extents->bounded.height); - } - - if (! extents->is_bounded) - status = i915_fixup_unbounded (dst, extents, clip); - -CLEANUP_DEVICE: - cairo_device_release (&device->intel.base.base); -CLEANUP_SHADER: - i915_shader_fini (&shader); - return status; -} - -cairo_int_status_t -i915_surface_glyphs (void *abstract_surface, - cairo_operator_t op, - const cairo_pattern_t *source, - cairo_glyph_t *glyphs, - int num_glyphs, - cairo_scaled_font_t *scaled_font, - cairo_clip_t *clip, - int *num_remaining) -{ - i915_surface_t *surface = abstract_surface; - i915_surface_t *mask = NULL; - i915_device_t *device; - i915_shader_t shader; - cairo_composite_rectangles_t extents; - cairo_clip_t local_clip; - cairo_bool_t have_clip = FALSE; - cairo_bool_t overlap; - cairo_region_t *clip_region = NULL; - intel_bo_t *last_bo = NULL; - i915_emit_glyph_rectangle_func_t emit_func; - cairo_scaled_glyph_t *glyph_cache[64]; - cairo_status_t status; - int mask_x = 0, mask_y = 0; - int i = 0; - - *num_remaining = 0; - status = _cairo_composite_rectangles_init_for_glyphs (&extents, - surface->intel.drm.width, - surface->intel.drm.height, - op, source, - scaled_font, - glyphs, num_glyphs, - clip, - &overlap); - if (unlikely (status)) - return status; - - if (_cairo_clip_contains_rectangle (clip, &extents.mask)) - clip = NULL; - - if (clip != NULL && extents.is_bounded) { - clip = _cairo_clip_init_copy (&local_clip, clip); - status = _cairo_clip_rectangle (clip, &extents.bounded); - if (unlikely (status)) - return status; - - have_clip = TRUE; - } - - if (clip != NULL) { - status = _cairo_clip_get_region (clip, &clip_region); - if (unlikely (_cairo_status_is_error (status) || - status == CAIRO_INT_STATUS_NOTHING_TO_DO)) - { - if (have_clip) - _cairo_clip_fini (&local_clip); - return status; - } - } - - if (i915_surface_needs_tiling (surface)) { - ASSERT_NOT_REACHED; - return CAIRO_INT_STATUS_UNSUPPORTED; - } - - if (overlap || ! extents.is_bounded) { - cairo_format_t format; - - format = CAIRO_FORMAT_A8; - if (scaled_font->options.antialias == CAIRO_ANTIALIAS_SUBPIXEL) - format = CAIRO_FORMAT_ARGB32; - - mask = (i915_surface_t *) - i915_surface_create_internal (&i915_device (surface)->intel.base, - format, - extents.bounded.width, - extents.bounded.height, - I915_TILING_DEFAULT, - TRUE); - if (unlikely (mask->intel.drm.base.status)) - return mask->intel.drm.base.status; - - status = i915_surface_clear (mask); - if (unlikely (status)) { - cairo_surface_destroy (&mask->intel.drm.base); - return status; - } - - i915_shader_init (&shader, mask, CAIRO_OPERATOR_ADD, 1.); - - status = i915_shader_acquire_pattern (&shader, &shader.source, - &_cairo_pattern_white.base, - &extents.bounded); - if (unlikely (status)) { - cairo_surface_destroy (&mask->intel.drm.base); - return status; - } - - mask_x = -extents.bounded.x; - mask_y = -extents.bounded.y; - } else { - i915_shader_init (&shader, surface, op, 1.); - - status = i915_shader_acquire_pattern (&shader, &shader.source, - source, &extents.bounded); - if (unlikely (status)) - return status; - - if (clip != NULL) { - status = _cairo_clip_get_region (clip, &clip_region); - - if (clip_region != NULL && cairo_region_num_rectangles (clip_region) == 1) - clip_region = NULL; - - if (status == CAIRO_INT_STATUS_UNSUPPORTED) - i915_shader_set_clip (&shader, clip); - } - } - - shader.mask.type.fragment = FS_TEXTURE; - shader.mask.base.content = CAIRO_CONTENT_ALPHA; /* XXX */ - shader.mask.base.texfmt = TEXCOORDFMT_2D_16; - shader.mask.base.n_samplers = 1; - shader.mask.base.sampler[0] = - (MIPFILTER_NONE << SS2_MIP_FILTER_SHIFT) | - i915_texture_filter (CAIRO_FILTER_NEAREST); - shader.mask.base.sampler[1] = - SS3_NORMALIZED_COORDS | - i915_texture_extend (CAIRO_EXTEND_NONE); - - switch (shader.source.type.vertex) { - case VS_ZERO: - emit_func = i915_emit_glyph_rectangle_zero; - break; - case VS_CONSTANT: - emit_func = i915_emit_glyph_rectangle_constant; - break; - default: - case VS_LINEAR: - case VS_TEXTURE: - case VS_TEXTURE_16: - emit_func = i915_emit_glyph_rectangle_general; - break; - } - - status = cairo_device_acquire (surface->intel.drm.base.device); - if (unlikely (status)) - goto CLEANUP_SHADER; - - device = i915_device (surface); - - _cairo_scaled_font_freeze_cache (scaled_font); - if (scaled_font->surface_private == NULL) { - scaled_font->surface_private = device; - scaled_font->surface_backend = surface->intel.drm.base.backend; - cairo_list_add (&scaled_font->link, &device->intel.fonts); - } - - memset (glyph_cache, 0, sizeof (glyph_cache)); - - for (i = 0; i < num_glyphs; i++) { - cairo_scaled_glyph_t *scaled_glyph; - int x, y, x1, x2, y1, y2; - int cache_index = glyphs[i].index % ARRAY_LENGTH (glyph_cache); - intel_glyph_t *glyph; - - scaled_glyph = glyph_cache[cache_index]; - if (scaled_glyph == NULL || - _cairo_scaled_glyph_index (scaled_glyph) != glyphs[i].index) - { - status = _cairo_scaled_glyph_lookup (scaled_font, - glyphs[i].index, - CAIRO_SCALED_GLYPH_INFO_METRICS, - &scaled_glyph); - if (unlikely (status)) - goto FINISH; - - glyph_cache[cache_index] = scaled_glyph; - } - - if (unlikely (scaled_glyph->metrics.width == 0 || - scaled_glyph->metrics.height == 0)) - { - continue; - } - - /* XXX glyph images are snapped to pixel locations */ - x = _cairo_lround (glyphs[i].x); - y = _cairo_lround (glyphs[i].y); - - x1 = x + _cairo_fixed_integer_floor (scaled_glyph->bbox.p1.x); - y1 = y + _cairo_fixed_integer_floor (scaled_glyph->bbox.p1.y); - x2 = x + _cairo_fixed_integer_ceil (scaled_glyph->bbox.p2.x); - y2 = y + _cairo_fixed_integer_ceil (scaled_glyph->bbox.p2.y); - - if (x2 < extents.bounded.x || - y2 < extents.bounded.y || - x1 > extents.bounded.x + extents.bounded.width || - y1 > extents.bounded.y + extents.bounded.height) - { - continue; - } - - if (scaled_glyph->surface_private == NULL) { - status = intel_get_glyph (&device->intel, scaled_font, scaled_glyph); - if (unlikely (status == CAIRO_INT_STATUS_NOTHING_TO_DO)) { - status = CAIRO_STATUS_SUCCESS; - continue; - } - if (unlikely (status)) - goto FINISH; - } - - glyph = intel_glyph_pin (scaled_glyph->surface_private); - if (glyph->cache->buffer.bo != last_bo) { - intel_buffer_cache_t *cache = glyph->cache; - - shader.mask.base.bo = cache->buffer.bo; - shader.mask.base.offset[0] = cache->buffer.offset; - shader.mask.base.map[0] = cache->buffer.map0; - shader.mask.base.map[1] = cache->buffer.map1; - shader.mask.base.content = CAIRO_CONTENT_ALPHA; /* XXX */ - - status = i915_shader_commit (&shader, device); - if (unlikely (status)) - goto FINISH; - - last_bo = cache->buffer.bo; - } - - x2 = x1 + glyph->width; - y2 = y1 + glyph->height; - - if (mask_x) - x1 += mask_x, x2 += mask_x; - if (mask_y) - y1 += mask_y, y2 += mask_y; - - /* XXX clip glyph */ - emit_func (device, &shader, x1, y1, x2, y2, glyph); - } - - status = CAIRO_STATUS_SUCCESS; - FINISH: - _cairo_scaled_font_thaw_cache (scaled_font); - cairo_device_release (surface->intel.drm.base.device); - CLEANUP_SHADER: - i915_shader_fini (&shader); - - if (unlikely (status == CAIRO_INT_STATUS_UNSUPPORTED)) { - cairo_path_fixed_t path; - - _cairo_path_fixed_init (&path); - status = _cairo_scaled_font_glyph_path (scaled_font, - glyphs + i, num_glyphs - i, - &path); - if (mask_x | mask_y) { - _cairo_path_fixed_translate (&path, - _cairo_fixed_from_int (mask_x), - _cairo_fixed_from_int (mask_y)); - } - if (likely (status == CAIRO_STATUS_SUCCESS)) { - status = surface->intel.drm.base.backend->fill (shader.target, - shader.op, - mask != NULL ? &_cairo_pattern_white.base : source, - &path, - CAIRO_FILL_RULE_WINDING, - 0, - scaled_font->options.antialias, - clip); - } - _cairo_path_fixed_fini (&path); - } - - if (mask != NULL) { - if (likely (status == CAIRO_STATUS_SUCCESS)) { - status = i915_surface_mask_internal (surface, op, source, mask, - clip, &extents); - } - cairo_surface_finish (&mask->intel.drm.base); - cairo_surface_destroy (&mask->intel.drm.base); - } - - if (have_clip) - _cairo_clip_fini (&local_clip); - - return status; -} diff --git a/gfx/cairo/cairo/src/drm/cairo-drm-i915-private.h b/gfx/cairo/cairo/src/drm/cairo-drm-i915-private.h deleted file mode 100644 index 7585756dc5..0000000000 --- a/gfx/cairo/cairo/src/drm/cairo-drm-i915-private.h +++ /dev/null @@ -1,1270 +0,0 @@ -/* - * Copyright © 2006, 2009 Intel Corporation - * - * Permission is hereby granted, free of charge, to any person obtaining a - * copy of this software and associated documentation files (the "Software"), - * to deal in the Software without restriction, including without limitation - * the rights to use, copy, modify, merge, publish, distribute, sublicense, - * and/or sell copies of the Software, and to permit persons to whom the - * Software is furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice (including the next - * paragraph) shall be included in all copies or substantial portions of the - * Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL - * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - * - * Authors: - * Eric Anholt <eric@anholt.net> - * Chris Wilson <chris@chris-wilson.co.uk> - */ - -#ifndef CAIRO_DRM_I915_PRIVATE_H -#define CAIRO_DRM_I915_PRIVATE_H - -#include "cairo-types-private.h" - -#include "cairo-drm-private.h" -#include "cairo-drm-intel-private.h" -#include "cairo-drm-intel-command-private.h" -#include "cairo-drm-intel-ioctl-private.h" -#include "cairo-freelist-private.h" - -#include <setjmp.h> - -#define I915_VERBOSE 1 - -#define I915_MAX_TEX_INDIRECT 4 -#define I915_MAX_TEX_INSN 32 -#define I915_MAX_ALU_INSN 64 -#define I915_MAX_DECL_INSN 27 -#define I915_MAX_TEMPORARY 16 - -/* Each instruction is 3 dwords long, though most don't require all - * this space. Maximum of 123 instructions. Smaller maxes per insn - * type. - */ -#define _3DSTATE_PIXEL_SHADER_PROGRAM (CMD_3D|(0x1d<<24)|(0x5<<16)) - -#define REG_TYPE_R 0 /* temporary regs, no need to - * dcl, must be written before - * read -- Preserved between - * phases. - */ -#define REG_TYPE_T 1 /* Interpolated values, must be - * dcl'ed before use. - * - * 0..7: texture coord, - * 8: diffuse spec, - * 9: specular color, - * 10: fog parameter in w. - */ -#define REG_TYPE_CONST 2 /* Restriction: only one const - * can be referenced per - * instruction, though it may be - * selected for multiple inputs. - * Constants not initialized - * default to zero. - */ -#define REG_TYPE_S 3 /* sampler */ -#define REG_TYPE_OC 4 /* output color (rgba) */ -#define REG_TYPE_OD 5 /* output depth (w), xyz are - * temporaries. If not written, - * interpolated depth is used? - */ -#define REG_TYPE_U 6 /* unpreserved temporaries */ -#define REG_TYPE_MASK 0x7 -#define REG_TYPE_SHIFT 4 -#define REG_NR_MASK 0xf - -/* REG_TYPE_T: - */ -#define T_TEX0 0 -#define T_TEX1 1 -#define T_TEX2 2 -#define T_TEX3 3 -#define T_TEX4 4 -#define T_TEX5 5 -#define T_TEX6 6 -#define T_TEX7 7 -#define T_DIFFUSE 8 -#define T_SPECULAR 9 -#define T_FOG_W 10 /* interpolated fog is in W coord */ - -/* Arithmetic instructions */ - -/* .replicate_swizzle == selection and replication of a particular - * scalar channel, ie., .xxxx, .yyyy, .zzzz or .wwww - */ -#define A0_NOP (0x0<<24) /* no operation */ -#define A0_ADD (0x1<<24) /* dst = src0 + src1 */ -#define A0_MOV (0x2<<24) /* dst = src0 */ -#define A0_MUL (0x3<<24) /* dst = src0 * src1 */ -#define A0_MAD (0x4<<24) /* dst = src0 * src1 + src2 */ -#define A0_DP2ADD (0x5<<24) /* dst.xyzw = src0.xy dot src1.xy + src2.replicate_swizzle */ -#define A0_DP3 (0x6<<24) /* dst.xyzw = src0.xyz dot src1.xyz */ -#define A0_DP4 (0x7<<24) /* dst.xyzw = src0.xyzw dot src1.xyzw */ -#define A0_FRC (0x8<<24) /* dst = src0 - floor(src0) */ -#define A0_RCP (0x9<<24) /* dst.xyzw = 1/(src0.replicate_swizzle) */ -#define A0_RSQ (0xa<<24) /* dst.xyzw = 1/(sqrt(abs(src0.replicate_swizzle))) */ -#define A0_EXP (0xb<<24) /* dst.xyzw = exp2(src0.replicate_swizzle) */ -#define A0_LOG (0xc<<24) /* dst.xyzw = log2(abs(src0.replicate_swizzle)) */ -#define A0_CMP (0xd<<24) /* dst = (src0 >= 0.0) ? src1 : src2 */ -#define A0_MIN (0xe<<24) /* dst = (src0 < src1) ? src0 : src1 */ -#define A0_MAX (0xf<<24) /* dst = (src0 >= src1) ? src0 : src1 */ -#define A0_FLR (0x10<<24) /* dst = floor(src0) */ -#define A0_MOD (0x11<<24) /* dst = src0 fmod 1.0 */ -#define A0_TRC (0x12<<24) /* dst = int(src0) */ -#define A0_SGE (0x13<<24) /* dst = src0 >= src1 ? 1.0 : 0.0 */ -#define A0_SLT (0x14<<24) /* dst = src0 < src1 ? 1.0 : 0.0 */ -#define A0_DEST_SATURATE (1<<22) -#define A0_DEST_TYPE_SHIFT 19 -/* Allow: R, OC, OD, U */ -#define A0_DEST_NR_SHIFT 14 -/* Allow R: 0..15, OC,OD: 0..0, U: 0..2 */ -#define A0_DEST_CHANNEL_X (1<<10) -#define A0_DEST_CHANNEL_Y (2<<10) -#define A0_DEST_CHANNEL_Z (4<<10) -#define A0_DEST_CHANNEL_W (8<<10) -#define A0_DEST_CHANNEL_ALL (0xf<<10) -#define A0_DEST_CHANNEL_SHIFT 10 -#define A0_SRC0_TYPE_SHIFT 7 -#define A0_SRC0_NR_SHIFT 2 - -#define A0_DEST_CHANNEL_XY (A0_DEST_CHANNEL_X|A0_DEST_CHANNEL_Y) -#define A0_DEST_CHANNEL_XYZ (A0_DEST_CHANNEL_XY|A0_DEST_CHANNEL_Z) - -#define SRC_X 0 -#define SRC_Y 1 -#define SRC_Z 2 -#define SRC_W 3 -#define SRC_ZERO 4 -#define SRC_ONE 5 - -#define A1_SRC0_CHANNEL_X_NEGATE ((int)(1u<<31)) -#define A1_SRC0_CHANNEL_X_SHIFT 28 -#define A1_SRC0_CHANNEL_Y_NEGATE (1<<27) -#define A1_SRC0_CHANNEL_Y_SHIFT 24 -#define A1_SRC0_CHANNEL_Z_NEGATE (1<<23) -#define A1_SRC0_CHANNEL_Z_SHIFT 20 -#define A1_SRC0_CHANNEL_W_NEGATE (1<<19) -#define A1_SRC0_CHANNEL_W_SHIFT 16 -#define A1_SRC1_TYPE_SHIFT 13 -#define A1_SRC1_NR_SHIFT 8 -#define A1_SRC1_CHANNEL_X_NEGATE (1<<7) -#define A1_SRC1_CHANNEL_X_SHIFT 4 -#define A1_SRC1_CHANNEL_Y_NEGATE (1<<3) -#define A1_SRC1_CHANNEL_Y_SHIFT 0 - -#define A2_SRC1_CHANNEL_Z_NEGATE ((int)(1u<<31)) -#define A2_SRC1_CHANNEL_Z_SHIFT 28 -#define A2_SRC1_CHANNEL_W_NEGATE (1<<27) -#define A2_SRC1_CHANNEL_W_SHIFT 24 -#define A2_SRC2_TYPE_SHIFT 21 -#define A2_SRC2_NR_SHIFT 16 -#define A2_SRC2_CHANNEL_X_NEGATE (1<<15) -#define A2_SRC2_CHANNEL_X_SHIFT 12 -#define A2_SRC2_CHANNEL_Y_NEGATE (1<<11) -#define A2_SRC2_CHANNEL_Y_SHIFT 8 -#define A2_SRC2_CHANNEL_Z_NEGATE (1<<7) -#define A2_SRC2_CHANNEL_Z_SHIFT 4 -#define A2_SRC2_CHANNEL_W_NEGATE (1<<3) -#define A2_SRC2_CHANNEL_W_SHIFT 0 - -/* Texture instructions */ -#define T0_TEXLD (0x15<<24) /* Sample texture using predeclared - * sampler and address, and output - * filtered texel data to destination - * register */ -#define T0_TEXLDP (0x16<<24) /* Same as texld but performs a - * perspective divide of the texture - * coordinate .xyz values by .w before - * sampling. */ -#define T0_TEXLDB (0x17<<24) /* Same as texld but biases the - * computed LOD by w. Only S4.6 two's - * comp is used. This implies that a - * float to fixed conversion is - * done. */ -#define T0_TEXKILL (0x18<<24) /* Does not perform a sampling - * operation. Simply kills the pixel - * if any channel of the address - * register is < 0.0. */ -#define T0_DEST_TYPE_SHIFT 19 -/* Allow: R, OC, OD, U */ -/* Note: U (unpreserved) regs do not retain their values between - * phases (cannot be used for feedback) - * - * Note: oC and OD registers can only be used as the destination of a - * texture instruction once per phase (this is an implementation - * restriction). - */ -#define T0_DEST_NR_SHIFT 14 -/* Allow R: 0..15, OC,OD: 0..0, U: 0..2 */ -#define T0_SAMPLER_NR_SHIFT 0 /* This field ignored for TEXKILL */ -#define T0_SAMPLER_NR_MASK (0xf<<0) - -#define T1_ADDRESS_REG_TYPE_SHIFT 24 /* Reg to use as texture coord */ -/* Allow R, T, OC, OD -- R, OC, OD are 'dependent' reads, new program phase */ -#define T1_ADDRESS_REG_NR_SHIFT 17 -#define T2_MBZ 0 - -/* Declaration instructions */ -#define D0_DCL (0x19<<24) /* Declare a t (interpolated attrib) - * register or an s (sampler) - * register. */ -#define D0_SAMPLE_TYPE_SHIFT 22 -#define D0_SAMPLE_TYPE_2D (0x0<<22) -#define D0_SAMPLE_TYPE_CUBE (0x1<<22) -#define D0_SAMPLE_TYPE_VOLUME (0x2<<22) -#define D0_SAMPLE_TYPE_MASK (0x3<<22) - -#define D0_TYPE_SHIFT 19 -/* Allow: T, S */ -#define D0_NR_SHIFT 14 -/* Allow T: 0..10, S: 0..15 */ -#define D0_CHANNEL_X (1<<10) -#define D0_CHANNEL_Y (2<<10) -#define D0_CHANNEL_Z (4<<10) -#define D0_CHANNEL_W (8<<10) -#define D0_CHANNEL_ALL (0xf<<10) -#define D0_CHANNEL_NONE (0<<10) - -#define D0_CHANNEL_XY (D0_CHANNEL_X|D0_CHANNEL_Y) -#define D0_CHANNEL_XYZ (D0_CHANNEL_XY|D0_CHANNEL_Z) - -/* I915 Errata: Do not allow (xz), (xw), (xzw) combinations for diffuse - * or specular declarations. - * - * For T dcls, only allow: (x), (xy), (xyz), (w), (xyzw) - * - * Must be zero for S (sampler) dcls - */ -#define D1_MBZ 0 -#define D2_MBZ 0 - - -/* MASK_* are the unshifted bitmasks of the destination mask in arithmetic - * operations - */ -#define MASK_X 0x1 -#define MASK_Y 0x2 -#define MASK_Z 0x4 -#define MASK_W 0x8 -#define MASK_XYZ (MASK_X | MASK_Y | MASK_Z) -#define MASK_XYZW (MASK_XYZ | MASK_W) -#define MASK_SATURATE 0x10 - -/* Temporary, undeclared regs. Preserved between phases */ -#define FS_R0 ((REG_TYPE_R << REG_TYPE_SHIFT) | 0) -#define FS_R1 ((REG_TYPE_R << REG_TYPE_SHIFT) | 1) -#define FS_R2 ((REG_TYPE_R << REG_TYPE_SHIFT) | 2) -#define FS_R3 ((REG_TYPE_R << REG_TYPE_SHIFT) | 3) - -/* Texture coordinate regs. Must be declared. */ -#define FS_T0 ((REG_TYPE_T << REG_TYPE_SHIFT) | 0) -#define FS_T1 ((REG_TYPE_T << REG_TYPE_SHIFT) | 1) -#define FS_T2 ((REG_TYPE_T << REG_TYPE_SHIFT) | 2) -#define FS_T3 ((REG_TYPE_T << REG_TYPE_SHIFT) | 3) -#define FS_T4 ((REG_TYPE_T << REG_TYPE_SHIFT) | 4) -#define FS_T5 ((REG_TYPE_T << REG_TYPE_SHIFT) | 5) -#define FS_T6 ((REG_TYPE_T << REG_TYPE_SHIFT) | 6) -#define FS_T7 ((REG_TYPE_T << REG_TYPE_SHIFT) | 7) -#define FS_T8 ((REG_TYPE_T << REG_TYPE_SHIFT) | 8) -#define FS_T9 ((REG_TYPE_T << REG_TYPE_SHIFT) | 9) -#define FS_T10 ((REG_TYPE_T << REG_TYPE_SHIFT) | 10) - -/* Constant values */ -#define FS_C0 ((REG_TYPE_CONST << REG_TYPE_SHIFT) | 0) -#define FS_C1 ((REG_TYPE_CONST << REG_TYPE_SHIFT) | 1) -#define FS_C2 ((REG_TYPE_CONST << REG_TYPE_SHIFT) | 2) -#define FS_C3 ((REG_TYPE_CONST << REG_TYPE_SHIFT) | 3) -#define FS_C4 ((REG_TYPE_CONST << REG_TYPE_SHIFT) | 4) -#define FS_C5 ((REG_TYPE_CONST << REG_TYPE_SHIFT) | 5) -#define FS_C6 ((REG_TYPE_CONST << REG_TYPE_SHIFT) | 6) -#define FS_C7 ((REG_TYPE_CONST << REG_TYPE_SHIFT) | 7) - -/* Sampler regs */ -#define FS_S0 ((REG_TYPE_S << REG_TYPE_SHIFT) | 0) -#define FS_S1 ((REG_TYPE_S << REG_TYPE_SHIFT) | 1) -#define FS_S2 ((REG_TYPE_S << REG_TYPE_SHIFT) | 2) -#define FS_S3 ((REG_TYPE_S << REG_TYPE_SHIFT) | 3) - -/* Output color */ -#define FS_OC ((REG_TYPE_OC << REG_TYPE_SHIFT) | 0) - -/* Output depth */ -#define FS_OD ((REG_TYPE_OD << REG_TYPE_SHIFT) | 0) - -/* Unpreserved temporary regs */ -#define FS_U0 ((REG_TYPE_U << REG_TYPE_SHIFT) | 0) -#define FS_U1 ((REG_TYPE_U << REG_TYPE_SHIFT) | 1) -#define FS_U2 ((REG_TYPE_U << REG_TYPE_SHIFT) | 2) -#define FS_U3 ((REG_TYPE_U << REG_TYPE_SHIFT) | 3) - -#define X_CHANNEL_SHIFT (REG_TYPE_SHIFT + 3) -#define Y_CHANNEL_SHIFT (X_CHANNEL_SHIFT + 4) -#define Z_CHANNEL_SHIFT (Y_CHANNEL_SHIFT + 4) -#define W_CHANNEL_SHIFT (Z_CHANNEL_SHIFT + 4) - -#define REG_CHANNEL_MASK 0xf - -#define REG_NR(reg) ((reg) & REG_NR_MASK) -#define REG_TYPE(reg) (((reg) >> REG_TYPE_SHIFT) & REG_TYPE_MASK) -#define REG_X(reg) (((reg) >> X_CHANNEL_SHIFT) & REG_CHANNEL_MASK) -#define REG_Y(reg) (((reg) >> Y_CHANNEL_SHIFT) & REG_CHANNEL_MASK) -#define REG_Z(reg) (((reg) >> Z_CHANNEL_SHIFT) & REG_CHANNEL_MASK) -#define REG_W(reg) (((reg) >> W_CHANNEL_SHIFT) & REG_CHANNEL_MASK) - -enum i915_fs_channel { - X_CHANNEL_VAL = 0, - Y_CHANNEL_VAL, - Z_CHANNEL_VAL, - W_CHANNEL_VAL, - ZERO_CHANNEL_VAL, - ONE_CHANNEL_VAL, - - NEG_X_CHANNEL_VAL = X_CHANNEL_VAL | 0x8, - NEG_Y_CHANNEL_VAL = Y_CHANNEL_VAL | 0x8, - NEG_Z_CHANNEL_VAL = Z_CHANNEL_VAL | 0x8, - NEG_W_CHANNEL_VAL = W_CHANNEL_VAL | 0x8, - NEG_ONE_CHANNEL_VAL = ONE_CHANNEL_VAL | 0x8 -}; - -#define i915_fs_operand(reg, x, y, z, w) \ - (reg) | \ - (x##_CHANNEL_VAL << X_CHANNEL_SHIFT) | \ - (y##_CHANNEL_VAL << Y_CHANNEL_SHIFT) | \ - (z##_CHANNEL_VAL << Z_CHANNEL_SHIFT) | \ - (w##_CHANNEL_VAL << W_CHANNEL_SHIFT) - -/* - * Construct an operand description for using a register with no swizzling - */ -#define i915_fs_operand_reg(reg) \ - i915_fs_operand(reg, X, Y, Z, W) - -#define i915_fs_operand_reg_negate(reg) \ - i915_fs_operand(reg, NEG_X, NEG_Y, NEG_Z, NEG_W) - -/* - * Returns an operand containing (0.0, 0.0, 0.0, 0.0). - */ -#define i915_fs_operand_zero() i915_fs_operand(FS_R0, ZERO, ZERO, ZERO, ZERO) - -/* - * Returns an unused operand - */ -#define i915_fs_operand_none() i915_fs_operand_zero() - -/* - * Returns an operand containing (1.0, 1.0, 1.0, 1.0). - */ -#define i915_fs_operand_one() i915_fs_operand(FS_R0, ONE, ONE, ONE, ONE) - -#define i915_get_hardware_channel_val(val, shift, negate) \ - (((val & 0x7) << shift) | ((val & 0x8) ? negate : 0)) - -/* - * Outputs a fragment shader command to declare a sampler or texture register. - */ -#define i915_fs_dcl(reg) \ -do { \ - OUT_DWORD (D0_DCL | \ - (REG_TYPE(reg) << D0_TYPE_SHIFT) | \ - (REG_NR(reg) << D0_NR_SHIFT) | \ - ((REG_TYPE(reg) != REG_TYPE_S) ? D0_CHANNEL_ALL : 0)); \ - OUT_DWORD (0); \ - OUT_DWORD (0); \ -} while (0) - -#define i915_fs_texld(dest_reg, sampler_reg, address_reg) \ -do { \ - OUT_DWORD (T0_TEXLD | \ - (REG_TYPE(dest_reg) << T0_DEST_TYPE_SHIFT) | \ - (REG_NR(dest_reg) << T0_DEST_NR_SHIFT) | \ - (REG_NR(sampler_reg) << T0_SAMPLER_NR_SHIFT)); \ - OUT_DWORD((REG_TYPE(address_reg) << T1_ADDRESS_REG_TYPE_SHIFT) | \ - (REG_NR(address_reg) << T1_ADDRESS_REG_NR_SHIFT)); \ - OUT_DWORD (0); \ -} while (0) - -#define i915_fs_arith_masked(op, dest_reg, dest_mask, operand0, operand1, operand2) \ - _i915_fs_arith_masked(A0_##op, dest_reg, dest_mask, operand0, operand1, operand2) - -#define i915_fs_arith(op, dest_reg, operand0, operand1, operand2) \ - _i915_fs_arith(A0_##op, dest_reg, operand0, operand1, operand2) - -#define _i915_fs_arith_masked(cmd, dest_reg, dest_mask, operand0, operand1, operand2) \ -do { \ - /* Set up destination register and write mask */ \ - OUT_DWORD (cmd | \ - (REG_TYPE(dest_reg) << A0_DEST_TYPE_SHIFT) | \ - (REG_NR(dest_reg) << A0_DEST_NR_SHIFT) | \ - (((dest_mask) & ~MASK_SATURATE) << A0_DEST_CHANNEL_SHIFT) | \ - (((dest_mask) & MASK_SATURATE) ? A0_DEST_SATURATE : 0) | \ - /* Set up operand 0 */ \ - (REG_TYPE(operand0) << A0_SRC0_TYPE_SHIFT) | \ - (REG_NR(operand0) << A0_SRC0_NR_SHIFT)); \ - OUT_DWORD (i915_get_hardware_channel_val(REG_X(operand0), \ - A1_SRC0_CHANNEL_X_SHIFT, \ - A1_SRC0_CHANNEL_X_NEGATE) | \ - i915_get_hardware_channel_val(REG_Y(operand0), \ - A1_SRC0_CHANNEL_Y_SHIFT, \ - A1_SRC0_CHANNEL_Y_NEGATE) | \ - i915_get_hardware_channel_val(REG_Z(operand0), \ - A1_SRC0_CHANNEL_Z_SHIFT, \ - A1_SRC0_CHANNEL_Z_NEGATE) | \ - i915_get_hardware_channel_val(REG_W(operand0), \ - A1_SRC0_CHANNEL_W_SHIFT, \ - A1_SRC0_CHANNEL_W_NEGATE) | \ - /* Set up operand 1 */ \ - (REG_TYPE(operand1) << A1_SRC1_TYPE_SHIFT) | \ - (REG_NR(operand1) << A1_SRC1_NR_SHIFT) | \ - i915_get_hardware_channel_val(REG_X(operand1), \ - A1_SRC1_CHANNEL_X_SHIFT, \ - A1_SRC1_CHANNEL_X_NEGATE) | \ - i915_get_hardware_channel_val(REG_Y(operand1), \ - A1_SRC1_CHANNEL_Y_SHIFT, \ - A1_SRC1_CHANNEL_Y_NEGATE)); \ - OUT_DWORD (i915_get_hardware_channel_val(REG_Z(operand1), \ - A2_SRC1_CHANNEL_Z_SHIFT, \ - A2_SRC1_CHANNEL_Z_NEGATE) | \ - i915_get_hardware_channel_val(REG_W(operand1), \ - A2_SRC1_CHANNEL_W_SHIFT, \ - A2_SRC1_CHANNEL_W_NEGATE) | \ - /* Set up operand 2 */ \ - (REG_TYPE(operand2) << A2_SRC2_TYPE_SHIFT) | \ - (REG_NR(operand2) << A2_SRC2_NR_SHIFT) | \ - i915_get_hardware_channel_val(REG_X(operand2), \ - A2_SRC2_CHANNEL_X_SHIFT, \ - A2_SRC2_CHANNEL_X_NEGATE) | \ - i915_get_hardware_channel_val(REG_Y(operand2), \ - A2_SRC2_CHANNEL_Y_SHIFT, \ - A2_SRC2_CHANNEL_Y_NEGATE) | \ - i915_get_hardware_channel_val(REG_Z(operand2), \ - A2_SRC2_CHANNEL_Z_SHIFT, \ - A2_SRC2_CHANNEL_Z_NEGATE) | \ - i915_get_hardware_channel_val(REG_W(operand2), \ - A2_SRC2_CHANNEL_W_SHIFT, \ - A2_SRC2_CHANNEL_W_NEGATE)); \ -} while (0) - -#define _i915_fs_arith(cmd, dest_reg, operand0, operand1, operand2) do {\ - /* Set up destination register and write mask */ \ - OUT_DWORD (cmd | \ - (REG_TYPE(dest_reg) << A0_DEST_TYPE_SHIFT) | \ - (REG_NR(dest_reg) << A0_DEST_NR_SHIFT) | \ - (A0_DEST_CHANNEL_ALL) | \ - /* Set up operand 0 */ \ - (REG_TYPE(operand0) << A0_SRC0_TYPE_SHIFT) | \ - (REG_NR(operand0) << A0_SRC0_NR_SHIFT)); \ - OUT_DWORD (i915_get_hardware_channel_val(REG_X(operand0), \ - A1_SRC0_CHANNEL_X_SHIFT, \ - A1_SRC0_CHANNEL_X_NEGATE) | \ - i915_get_hardware_channel_val(REG_Y(operand0), \ - A1_SRC0_CHANNEL_Y_SHIFT, \ - A1_SRC0_CHANNEL_Y_NEGATE) | \ - i915_get_hardware_channel_val(REG_Z(operand0), \ - A1_SRC0_CHANNEL_Z_SHIFT, \ - A1_SRC0_CHANNEL_Z_NEGATE) | \ - i915_get_hardware_channel_val(REG_W(operand0), \ - A1_SRC0_CHANNEL_W_SHIFT, \ - A1_SRC0_CHANNEL_W_NEGATE) | \ - /* Set up operand 1 */ \ - (REG_TYPE(operand1) << A1_SRC1_TYPE_SHIFT) | \ - (REG_NR(operand1) << A1_SRC1_NR_SHIFT) | \ - i915_get_hardware_channel_val(REG_X(operand1), \ - A1_SRC1_CHANNEL_X_SHIFT, \ - A1_SRC1_CHANNEL_X_NEGATE) | \ - i915_get_hardware_channel_val(REG_Y(operand1), \ - A1_SRC1_CHANNEL_Y_SHIFT, \ - A1_SRC1_CHANNEL_Y_NEGATE)); \ - OUT_DWORD (i915_get_hardware_channel_val(REG_Z(operand1), \ - A2_SRC1_CHANNEL_Z_SHIFT, \ - A2_SRC1_CHANNEL_Z_NEGATE) | \ - i915_get_hardware_channel_val(REG_W(operand1), \ - A2_SRC1_CHANNEL_W_SHIFT, \ - A2_SRC1_CHANNEL_W_NEGATE) | \ - /* Set up operand 2 */ \ - (REG_TYPE(operand2) << A2_SRC2_TYPE_SHIFT) | \ - (REG_NR(operand2) << A2_SRC2_NR_SHIFT) | \ - i915_get_hardware_channel_val(REG_X(operand2), \ - A2_SRC2_CHANNEL_X_SHIFT, \ - A2_SRC2_CHANNEL_X_NEGATE) | \ - i915_get_hardware_channel_val(REG_Y(operand2), \ - A2_SRC2_CHANNEL_Y_SHIFT, \ - A2_SRC2_CHANNEL_Y_NEGATE) | \ - i915_get_hardware_channel_val(REG_Z(operand2), \ - A2_SRC2_CHANNEL_Z_SHIFT, \ - A2_SRC2_CHANNEL_Z_NEGATE) | \ - i915_get_hardware_channel_val(REG_W(operand2), \ - A2_SRC2_CHANNEL_W_SHIFT, \ - A2_SRC2_CHANNEL_W_NEGATE)); \ -} while (0) - -#define i915_fs_mov(dest_reg, operand0) \ - i915_fs_arith(MOV, dest_reg, \ - operand0, \ - i915_fs_operand_none(), \ - i915_fs_operand_none()) - -#define i915_fs_mov_masked(dest_reg, dest_mask, operand0) \ - i915_fs_arith_masked (MOV, dest_reg, dest_mask, \ - operand0, \ - i915_fs_operand_none(), \ - i915_fs_operand_none()) - - -#define i915_fs_frc(dest_reg, operand0) \ - i915_fs_arith (FRC, dest_reg, \ - operand0, \ - i915_fs_operand_none(), \ - i915_fs_operand_none()) - -/* Add operand0 and operand1 and put the result in dest_reg */ -#define i915_fs_add(dest_reg, operand0, operand1) \ - i915_fs_arith (ADD, dest_reg, \ - operand0, operand1, \ - i915_fs_operand_none()) - -/* Multiply operand0 and operand1 and put the result in dest_reg */ -#define i915_fs_mul(dest_reg, operand0, operand1) \ - i915_fs_arith (MUL, dest_reg, \ - operand0, operand1, \ - i915_fs_operand_none()) - -/* Computes 1/sqrt(operand0.replicate_swizzle) puts the result in dest_reg */ -#define i915_fs_rsq(dest_reg, dest_mask, operand0) \ -do { \ - if (dest_mask) { \ - i915_fs_arith_masked (RSQ, dest_reg, dest_mask, \ - operand0, \ - i915_fs_operand_none (), \ - i915_fs_operand_none ()); \ - } else { \ - i915_fs_arith (RSQ, dest_reg, \ - operand0, \ - i915_fs_operand_none (), \ - i915_fs_operand_none ()); \ - } \ -} while (0) - -/* Puts the minimum of operand0 and operand1 in dest_reg */ -#define i915_fs_min(dest_reg, operand0, operand1) \ - i915_fs_arith (MIN, dest_reg, \ - operand0, operand1, \ - i915_fs_operand_none()) - -/* Puts the maximum of operand0 and operand1 in dest_reg */ -#define i915_fs_max(dest_reg, operand0, operand1) \ - i915_fs_arith (MAX, dest_reg, \ - operand0, operand1, \ - i915_fs_operand_none()) - -#define i915_fs_cmp(dest_reg, operand0, operand1, operand2) \ - i915_fs_arith (CMP, dest_reg, operand0, operand1, operand2) - -/* Perform operand0 * operand1 + operand2 and put the result in dest_reg */ -#define i915_fs_mad(dest_reg, dest_mask, op0, op1, op2) \ -do { \ - if (dest_mask) { \ - i915_fs_arith_masked (MAD, dest_reg, dest_mask, op0, op1, op2); \ - } else { \ - i915_fs_arith (MAD, dest_reg, op0, op1, op2); \ - } \ -} while (0) - -#define i915_fs_dp2add(dest_reg, dest_mask, op0, op1, op2) \ -do { \ - if (dest_mask) { \ - i915_fs_arith_masked (DP2ADD, dest_reg, dest_mask, op0, op1, op2); \ - } else { \ - i915_fs_arith (DP2ADD, dest_reg, op0, op1, op2); \ - } \ -} while (0) - -/* - * Perform a 3-component dot-product of operand0 and operand1 and put the - * resulting scalar in the channels of dest_reg specified by the dest_mask. - */ -#define i915_fs_dp3(dest_reg, dest_mask, op0, op1) \ -do { \ - if (dest_mask) { \ - i915_fs_arith_masked (DP3, dest_reg, dest_mask, \ - op0, op1,\ - i915_fs_operand_none()); \ - } else { \ - i915_fs_arith (DP3, dest_reg, op0, op1,\ - i915_fs_operand_none()); \ - } \ -} while (0) - -static inline uint32_t cairo_const -i915_fs_operand_pure_alpha (int pure) -{ - if (pure & (1 << 3)) - return i915_fs_operand_one (); - else - return i915_fs_operand_zero (); -} - -#define I915_TILING_DEFAULT I915_TILING_Y -#define I915_BO_CACHE_BUCKETS 13 /* cache surfaces up to 16 MiB */ - -typedef struct i915_surface i915_surface_t; -typedef struct i915_device i915_device_t; -typedef struct i915_shader i915_shader_t; - -typedef void (*i915_add_rectangle_func_t) (const i915_shader_t *shader, - int x, int y, - int w, int h); - -#define IMAGE_CACHE_WIDTH 1024 -#define IMAGE_CACHE_HEIGHT 1024 - -typedef struct i915_image_private { - cairo_rtree_node_t node; - intel_buffer_cache_t *container; -} i915_image_private_t; - -#define I915_BATCH_SIZE (128*1024) -#define I915_VBO_SIZE (512*1024) -#define I915_MAX_RELOCS 2048 - -enum { - I915_DEBUG_EXEC = 0x1, - I915_DEBUG_SYNC = 0x2, - I915_DEBUG_BATCH = 0x4, - I915_DEBUG_BUFFER = 0x8, - I915_DEBUG_BUFFER_CACHE = 0x10, - I915_DEBUG_BUFFER_ALLOC = 0x20, - I915_DEBUG_GLYPHS = 0x40, - I915_DEBUG_MAP = 0x80, - I915_DEBUG_THROTTLE = 0x100, -}; - -struct i915_device { - intel_device_t intel; - - cairo_bool_t debug; - - i915_shader_t *shader; /* note: only valid during geometry emission */ - - struct i915_batch { - intel_bo_t *target_bo[I915_MAX_RELOCS]; - size_t gtt_avail_size; - size_t est_gtt_size; - size_t total_gtt_size; - - uint16_t fences; - uint16_t fences_avail; - uint16_t reloc_count; - uint16_t exec_count; - uint16_t used; - - struct drm_i915_gem_exec_object2 exec[I915_MAX_RELOCS]; - struct drm_i915_gem_relocation_entry reloc[I915_MAX_RELOCS]; - } batch; - - uint32_t vbo; - uint32_t vbo_offset; - uint32_t vbo_used; - uint32_t vbo_max_index; - uint32_t vertex_index; - uint32_t vertex_count; - uint32_t floats_per_vertex; - uint32_t rectangle_size; - intel_bo_t *last_vbo; - uint32_t last_vbo_offset; - uint32_t last_vbo_space; - - i915_surface_t *current_target; - uint32_t current_size; - uint32_t current_diffuse; - uint32_t current_colorbuf; - uint32_t *current_source; - uint32_t *current_mask; - uint32_t *current_clip; - uint32_t current_program; - uint32_t current_texcoords; - uint32_t current_blend; - uint32_t current_constants[8*4]; - uint32_t current_n_constants; - uint32_t current_samplers[2*4]; - uint32_t current_maps[4*4]; - uint32_t current_n_samplers; - uint32_t current_n_maps; - uint32_t last_source_fragment; - uint32_t clear_alpha; - - cairo_list_t image_caches[2]; - - uint32_t batch_header[13]; - uint32_t batch_base[I915_BATCH_SIZE / sizeof (uint32_t)]; - uint8_t vbo_base[I915_VBO_SIZE]; -}; - -enum { - CURRENT_SOURCE = 0x1, - CURRENT_MASK = 0x2, - CURRENT_CLIP = 0x4 -}; - -typedef enum { - VS_ZERO, - VS_CONSTANT, - VS_LINEAR, - VS_TEXTURE, - VS_TEXTURE_16, -} i915_vertex_shader_t; - -typedef enum { - FS_ZERO, - FS_ONE, - FS_PURE, - FS_CONSTANT, - FS_DIFFUSE, - FS_LINEAR, - FS_RADIAL, - FS_TEXTURE, - FS_YUV, - FS_SPANS, -} i915_fragment_shader_t; - -#define FS_DETAILS_SHIFT 4 - -typedef enum { - PATTERN_BASE, - PATTERN_CONSTANT, - PATTERN_LINEAR, - PATTERN_RADIAL, - PATTERN_TEXTURE, -} i915_shader_channel_t; - -struct i915_surface { - intel_surface_t intel; - - uint32_t map0, map1; - uint32_t colorbuf; - - cairo_bool_t deferred_clear; - uint32_t offset; - uint32_t is_current_texture; - - i915_image_private_t *cache; - - intel_bo_t *stencil; - uint32_t stencil_stride; - uint32_t stencil_offset; -}; - -typedef enum { - NONE = 0, - YUV_I420, - /* XXX */ - YUV_YV12, - YUV_YUY2, - YUV_UYVY, -} i915_packed_pixel_t; - -/* read-only container */ -#define I915_PACKED_PIXEL_SURFACE_TYPE 0x1000 -typedef struct i915_packed_pixel_surface { - cairo_surface_t base; - - i915_packed_pixel_t pixel; - - i915_device_t *device; - intel_bo_t *bo; - uint32_t is_current_texture; - - uint32_t offset[4]; - uint32_t stride[4]; - uint32_t width[4]; - uint32_t height[4]; - uint32_t map0[4], map1[4]; -} i915_packed_pixel_surface_t; - -struct i915_shader { - i915_device_t *device; - i915_surface_t *target; - - cairo_operator_t op; - uint32_t blend; - float opacity; - cairo_content_t content; - - cairo_bool_t committed; - cairo_bool_t need_combine; - - i915_add_rectangle_func_t add_rectangle; - - union i915_shader_channel { - struct { - i915_vertex_shader_t vertex; - i915_fragment_shader_t fragment; - i915_shader_channel_t pattern; - } type; - struct i915_shader_base { - i915_vertex_shader_t vertex; - i915_fragment_shader_t fragment; - i915_shader_channel_t pattern; - uint32_t texfmt; - cairo_content_t content; - uint32_t mode; - intel_bo_t *bo; - uint32_t n_samplers; - uint32_t offset[4]; - uint32_t map[2*4]; - uint32_t sampler[2]; - cairo_matrix_t matrix; - } base; - struct i915_shader_solid { - struct i915_shader_base base; - cairo_color_t color; - int pure; - } solid; - struct i915_shader_linear { - struct i915_shader_base base; - struct { - float red, green, blue, alpha; - } color0, color1; - float dx, dy, offset; - } linear; - struct i915_shader_radial { - struct i915_shader_base base; - float constants[8]; - } radial; - struct i915_shader_surface { - struct i915_shader_base base; - i915_packed_pixel_t pixel; - } surface; - } source, mask, clip, dst; - - jmp_buf unwind; -}; - -enum i915_shader_linear_mode { - /* XXX REFLECT */ - LINEAR_TEXTURE, - LINEAR_NONE, - LINEAR_REPEAT, - LINEAR_PAD, -}; - -enum i915_shader_radial_mode { - RADIAL_ONE, - RADIAL_TWO -}; - -typedef cairo_status_t -(*i915_spans_func_t) (void *closure, - cairo_span_renderer_t *renderer, - const cairo_rectangle_int_t *extents); - -cairo_private cairo_status_t -i915_clip_and_composite_spans (i915_surface_t *dst, - cairo_operator_t op, - const cairo_pattern_t *pattern, - cairo_antialias_t antialias, - i915_spans_func_t draw_func, - void *draw_closure, - const cairo_composite_rectangles_t*extents, - cairo_clip_t *clip, - double opacity); - -cairo_private cairo_surface_t * -i915_surface_create_internal (cairo_drm_device_t *base_dev, - cairo_format_t format, - int width, int height, - uint32_t tiling, - cairo_bool_t gpu_target); - -cairo_private i915_surface_t * -i915_surface_create_from_cacheable_image_internal (i915_device_t *device, - cairo_image_surface_t *image); - -cairo_private void -i915_surface_scaled_font_fini (cairo_scaled_font_t *scaled_font); - -cairo_private cairo_int_status_t -i915_surface_glyphs (void *abstract_surface, - cairo_operator_t op, - const cairo_pattern_t *source, - cairo_glyph_t *glyphs, - int num_glyphs, - cairo_scaled_font_t *scaled_font, - cairo_clip_t *clip, - int *num_remaining); - -static inline int cairo_const -i915_tiling_height (uint32_t tiling, int height) -{ - switch (tiling) { - default: - case I915_TILING_NONE: return (height + 1) & -2; - case I915_TILING_X: return (height + 7) & -8; - case I915_TILING_Y: return (height + 31) & -32; - } -} - -static inline uint32_t cairo_const -i915_tiling_stride (int format, uint32_t stride) -{ - uint32_t tile_width; - - /* use 64B alignment so that the buffer may be used as a scanout */ - if (format == I915_TILING_NONE) - return (stride + 63) & -64; - - tile_width = 512; - /* XXX Currently the kernel enforces a tile_width of 512 for TILING_Y. - - <jbarnes> the docs are a bit confused on that front - <jbarnes> once we enable it on 915 we'll find out what the tile width size should be in the fence setup - <jbarnes> it could be that 915 has y tiling but that the minimum width is 512 or something - <jbarnes> yeah it's probably 128 on 915 also - <jbarnes> it's just that we haven't tested - <jbarnes> but I wasn't thinking that the tile widths were the same - <jbarnes> only that in order to fence y tiles on 915 you needed pitch to be a multiple of 4 y tiles (or something like that) - - tile_width = format == I915_TILING_Y ? 128 : 512; - */ - - /* needs a pot tile width */ - while (tile_width < stride) - tile_width <<= 1; - - return tile_width; -} - -static inline uint32_t cairo_const -i915_tiling_size (uint32_t tiling, uint32_t size) -{ - uint32_t fence; - - if (tiling == I915_TILING_NONE) - return (size + 4095) & -4096; - - fence = 1024 * 1024; /* 1 MiB */ - while (fence < size) - fence <<= 1; - - return fence; -} - -static inline cairo_bool_t cairo_const -i915_texture_filter_is_nearest (cairo_filter_t filter) -{ - switch (filter) { - case CAIRO_FILTER_BEST: - case CAIRO_FILTER_GOOD: - case CAIRO_FILTER_BILINEAR: - case CAIRO_FILTER_GAUSSIAN: - return FALSE; - default: - case CAIRO_FILTER_FAST: - case CAIRO_FILTER_NEAREST: - return TRUE; - } -} - -static inline uint32_t cairo_const -i915_texture_filter (cairo_filter_t filter) -{ - switch (filter) { - case CAIRO_FILTER_BEST: - case CAIRO_FILTER_GOOD: - case CAIRO_FILTER_BILINEAR: - case CAIRO_FILTER_GAUSSIAN: - return - (FILTER_LINEAR << SS2_MAG_FILTER_SHIFT) | - (FILTER_LINEAR << SS2_MIN_FILTER_SHIFT); - default: - case CAIRO_FILTER_FAST: - case CAIRO_FILTER_NEAREST: - return - (FILTER_NEAREST << SS2_MAG_FILTER_SHIFT) | - (FILTER_NEAREST << SS2_MIN_FILTER_SHIFT); - } -} - -static inline uint32_t cairo_const -i915_texture_extend (cairo_extend_t extend) -{ - switch (extend) { - default: - case CAIRO_EXTEND_NONE: - return - (TEXCOORDMODE_CLAMP_BORDER << SS3_TCX_ADDR_MODE_SHIFT) | - (TEXCOORDMODE_CLAMP_BORDER << SS3_TCY_ADDR_MODE_SHIFT); - case CAIRO_EXTEND_REPEAT: - return - (TEXCOORDMODE_WRAP << SS3_TCX_ADDR_MODE_SHIFT) | - (TEXCOORDMODE_WRAP << SS3_TCY_ADDR_MODE_SHIFT); - case CAIRO_EXTEND_PAD: - return - (TEXCOORDMODE_CLAMP_EDGE << SS3_TCX_ADDR_MODE_SHIFT) | - (TEXCOORDMODE_CLAMP_EDGE << SS3_TCY_ADDR_MODE_SHIFT); - case CAIRO_EXTEND_REFLECT: - return - (TEXCOORDMODE_MIRROR << SS3_TCX_ADDR_MODE_SHIFT) | - (TEXCOORDMODE_MIRROR << SS3_TCY_ADDR_MODE_SHIFT); - } -} - -static inline uint32_t cairo_const -BUF_tiling (uint32_t tiling) -{ - switch (tiling) { - default: - case I915_TILING_NONE: return 0; - case I915_TILING_X: return BUF_3D_TILED_SURFACE | BUF_3D_TILE_WALK_X; - case I915_TILING_Y: return BUF_3D_TILED_SURFACE | BUF_3D_TILE_WALK_Y; - } -} - -#define OUT_DWORD(dword) i915_batch_emit_dword (device, dword) -#define OUT_RELOC(surface, read, write) i915_batch_emit_reloc (device, to_intel_bo (surface->intel.drm.bo), surface->offset, read, write, FALSE) -#define OUT_RELOC_FENCED(surface, read, write) i915_batch_emit_reloc (device, to_intel_bo (surface->intel.drm.bo), surface->offset, read, write, TRUE) - -#define FS_LOCALS \ - uint32_t *_shader_start - -#define FS_BEGIN() \ -do { \ - _shader_start = BATCH_PTR (device); \ - OUT_DWORD (_3DSTATE_PIXEL_SHADER_PROGRAM); \ -} while (0) - -#define FS_END() \ -do { \ - *_shader_start |= BATCH_PTR (device) - _shader_start - 2; \ -} while (0); - -static inline int32_t -i915_batch_space (i915_device_t *device) -{ - /* leave room for RECTLIST(4) + MI_BUFFER_END + MI_NOOP */ - return sizeof (device->batch_base) - (device->batch.used << 2) - 32; -} - -static inline cairo_bool_t -i915_check_aperture_size (const i915_device_t *device, int relocs, size_t est_size, size_t size) -{ - return device->batch.reloc_count + relocs < I915_MAX_RELOCS - 2 && - device->batch.est_gtt_size + est_size <= device->batch.gtt_avail_size && - device->batch.total_gtt_size + size <= device->intel.gtt_avail_size; -} - -static inline cairo_bool_t -i915_check_aperture (const i915_device_t *device, intel_bo_t **bo_array, int count) -{ - uint32_t relocs = 0, est_size = 0, size = 0; - - while (count--) { - const intel_bo_t *bo = *bo_array++; - if (bo->exec == NULL) { - relocs++; - size += bo->base.size; - if (!bo->busy) - est_size += bo->base.size; - } - } - - return i915_check_aperture_size (device, relocs, est_size, size); -} - -static inline cairo_bool_t -i915_check_aperture_and_fences (const i915_device_t *device, intel_bo_t **bo_array, int count) -{ - uint32_t relocs = 0, est_size = 0, size = 0; - uint32_t fences = 0; - - while (count--) { - const intel_bo_t *bo = *bo_array++; - if (bo->exec == NULL) { - relocs++; - size += bo->base.size; - if (!bo->busy) - est_size += bo->base.size; - if (bo->tiling != I915_TILING_NONE) - fences++; - } else if (bo->tiling != I915_TILING_NONE) { - if ((bo->exec->flags & EXEC_OBJECT_NEEDS_FENCE) == 0) - fences++; - } - } - - return i915_check_aperture_size (device, relocs, est_size, size) && - device->batch.fences + fences <= device->batch.fences_avail; -} - -#define BATCH_PTR(device) &(device)->batch_base[(device)->batch.used] -static inline void -i915_batch_emit_dword (i915_device_t *device, uint32_t dword) -{ - device->batch_base[device->batch.used++] = dword; -} - -cairo_private void -i915_batch_add_reloc (i915_device_t *device, uint32_t pos, - intel_bo_t *bo, - uint32_t offset, - uint32_t read_domains, - uint32_t write_domain, - cairo_bool_t needs_fence); - -static inline void -i915_batch_fill_reloc (i915_device_t *device, uint32_t pos, - intel_bo_t *bo, - uint32_t offset, - uint32_t read_domains, - uint32_t write_domain) -{ - i915_batch_add_reloc (device, pos, - bo, offset, - read_domains, write_domain, - FALSE); - device->batch_base[pos] = bo->offset + offset; -} - -static inline void -i915_batch_emit_reloc (i915_device_t *device, - intel_bo_t *bo, - uint32_t offset, - uint32_t read_domains, - uint32_t write_domain, - cairo_bool_t needs_fence) -{ - i915_batch_add_reloc (device, device->batch.used, - bo, offset, - read_domains, write_domain, - needs_fence); - i915_batch_emit_dword (device, bo->offset + offset); -} - -cairo_private void -i915_vbo_flush (i915_device_t *device); - -cairo_private void -i915_vbo_finish (i915_device_t *device); - -cairo_private cairo_status_t -i915_batch_flush (i915_device_t *device); - -static inline float * -i915_add_rectangle (i915_device_t *device) -{ - float *vertices; - uint32_t size; - - assert (device->floats_per_vertex); - assert (device->rectangle_size == 3*device->floats_per_vertex*sizeof(float)); - - size = device->rectangle_size; - if (unlikely (device->vbo_offset + size > I915_VBO_SIZE)) - i915_vbo_finish (device); - - vertices = (float *) (device->vbo_base + device->vbo_offset); - device->vbo_used = device->vbo_offset += size; - device->vertex_count += 3; - return vertices; -} - -static inline i915_device_t * -i915_device (i915_surface_t *surface) -{ - return (i915_device_t *) surface->intel.drm.base.device; -} - -cairo_private cairo_status_t -i915_surface_clear (i915_surface_t *dst); - -cairo_private void -i915_set_dst (i915_device_t *device, i915_surface_t *dst); - -cairo_private void -i915_shader_init (i915_shader_t *shader, - i915_surface_t *dst, - cairo_operator_t op, - double opacity); - -cairo_private cairo_status_t -i915_shader_acquire_pattern (i915_shader_t *shader, - union i915_shader_channel *src, - const cairo_pattern_t *pattern, - const cairo_rectangle_int_t *extents); - -cairo_private void -i915_shader_set_clip (i915_shader_t *shader, - cairo_clip_t *clip); - -cairo_private int -i915_shader_num_texcoords (const i915_shader_t *shader); - -static inline double cairo_const -i915_shader_linear_texcoord (const struct i915_shader_linear *l, - double src_x, double src_y) -{ - return l->dx * src_x + l->dy * src_y + l->offset; -} - -cairo_private cairo_status_t -i915_shader_commit (i915_shader_t *shader, - i915_device_t *device); - -cairo_private void -i915_shader_fini (i915_shader_t *shader); - -cairo_private cairo_status_t -i915_fixup_unbounded (i915_surface_t *dst, - const cairo_composite_rectangles_t *extents, - cairo_clip_t *clip); - -static inline cairo_bool_t -i915_surface_needs_tiling (i915_surface_t *dst) -{ - return dst->intel.drm.width > 2048 || dst->intel.drm.height > 2048; -} - -cairo_private cairo_status_t -i915_surface_copy_subimage (i915_device_t *device, - i915_surface_t *src, - const cairo_rectangle_int_t *extents, - cairo_bool_t flush, - i915_surface_t **clone_out); - -static inline uint32_t -pack_float (float f) -{ - union { - float f; - uint32_t ui; - } t; - t.f = f; - return t.ui; -} - -static inline cairo_status_t -i915_surface_fallback_flush (i915_surface_t *surface) -{ - cairo_status_t status; - - if (unlikely (surface->intel.drm.fallback != NULL)) - return intel_surface_flush (&surface->intel, 0); - - status = CAIRO_STATUS_SUCCESS; - if (unlikely (surface->deferred_clear)) - status = i915_surface_clear (surface); - - return status; -} - -#endif /* CAIRO_DRM_I915_PRIVATE_H */ diff --git a/gfx/cairo/cairo/src/drm/cairo-drm-i915-shader.c b/gfx/cairo/cairo/src/drm/cairo-drm-i915-shader.c deleted file mode 100644 index a3f01fdf22..0000000000 --- a/gfx/cairo/cairo/src/drm/cairo-drm-i915-shader.c +++ /dev/null @@ -1,2859 +0,0 @@ -/* cairo - a vector graphics library with display and print output - * - * Copyright © 2009 Intel Corporation - * - * This library is free software; you can redistribute it and/or - * modify it either under the terms of the GNU Lesser General Public - * License version 2.1 as published by the Free Software Foundation - * (the "LGPL") or, at your option, under the terms of the Mozilla - * Public License Version 1.1 (the "MPL"). If you do not alter this - * notice, a recipient may use your version of this file under either - * the MPL or the LGPL. - * - * You should have received a copy of the LGPL along with this library - * in the file COPYING-LGPL-2.1; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Suite 500, Boston, MA 02110-1335, 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. - * - * Contributor(s): - * Chris Wilson <chris@chris-wilson.co.uk> - */ - -#include "cairoint.h" - -#include "cairo-error-private.h" -#include "cairo-drm-i915-private.h" -#include "cairo-surface-offset-private.h" -#include "cairo-surface-subsurface-private.h" -#include "cairo-surface-snapshot-private.h" -#include "cairo-image-surface-private.h" - -#if 0 -static cairo_status_t -i915_packed_pixel_surface_finish (void *abstract_surface) -{ - i915_packed_pixel_surface_t *surface = abstract_surface; - i915_device_t *device; - - device = i915_device_acquire (&surface->device->intel.base); - - intel_bo_destroy (&device->intel, surface->bo); - - if (surface->is_current_texture) { - if (surface->is_current_texture & CURRENT_SOURCE) - device->current_source = NULL; - if (surface->is_current_texture & CURRENT_MASK) - device->current_mask = NULL; - device->current_n_samplers = 0; - } - - i915_device_release (device); - - return CAIRO_STATUS_SUCCESS; -} - -static const cairo_surface_backend_t i915_packed_pixel_surface_backend = { - I915_PACKED_PIXEL_SURFACE_TYPE, - i915_packed_pixel_surface_finish, -}; - -static cairo_surface_t * -i915_packed_pixel_surface_create (i915_device_t *device, - i915_packed_pixel_t pixel, - const uint8_t *data, - uint32_t length, - uint32_t width, uint32_t height) -{ - i915_packed_pixel_surface_t *surface; - cairo_content_t content; - uint32_t tiling, size; - uint32_t stride, half_stride; - uint32_t i; - - if (width > 2048 || height > 2048) - return _cairo_surface_create_in_error (_cairo_error (CAIRO_STATUS_INVALID_SIZE)); - - surface = _cairo_malloc (sizeof (i915_packed_pixel_surface_t)); - if (unlikely (surface == NULL)) - return _cairo_surface_create_in_error (_cairo_error (CAIRO_STATUS_NO_MEMORY)); - - tiling = I915_TILING_NONE; /* XXX */ - half_stride = stride = i915_tiling_stride (tiling, width/2); - if (stride < width) - stride *= 2 ; - height = i915_tiling_height (tiling, height); - - switch (surface->pixel = pixel) { - case YUV_I420: - content = CAIRO_CONTENT_COLOR; - - surface->offset[0] = 0; - surface->width[0] = width; - surface->height[0] = height; - surface->stride[0] = stride; - surface->map0[0] = MAPSURF_8BIT | MT_8BIT_I8 | MS3_tiling (tiling); - surface->map0[0] |= ((height - 1) << MS3_HEIGHT_SHIFT) | - ((width - 1) << MS3_WIDTH_SHIFT); - surface->map1[0] = (stride / 4 - 1) << MS4_PITCH_SHIFT; - - surface->offset[1] = stride * height; - surface->width[1] = width / 2; - surface->height[1] = height / 2; - surface->stride[1] = half_stride; - surface->map0[1] = MAPSURF_8BIT | MT_8BIT_I8 | MS3_tiling (tiling); - surface->map0[1] |= ((height/2 - 1) << MS3_HEIGHT_SHIFT) | - ((width/2 - 1) << MS3_WIDTH_SHIFT); - surface->map1[1] = (half_stride / 4 - 1) << MS4_PITCH_SHIFT; - - if (width < half_stride) { - surface->offset[2] = stride * height + half_stride / 2; - size = stride * height + half_stride * height / 2; - } else { - surface->offset[2] = stride * height + half_stride * height / 2; - size = stride * height + half_stride * height; - } - surface->width[2] = width / 2; - surface->height[2] = height / 2; - surface->stride[2] = half_stride; - surface->map0[2] = MAPSURF_8BIT | MT_8BIT_I8 | MS3_tiling (tiling); - surface->map0[2] |= ((height/2 - 1) << MS3_HEIGHT_SHIFT) | - ((width/2 - 1) << MS3_WIDTH_SHIFT); - surface->map1[2] = (half_stride / 4 - 1) << MS4_PITCH_SHIFT; - break; - - case NONE: - case YUV_YV12: - case YUV_YUY2: - case YUV_UYVY: - ASSERT_NOT_REACHED; - break; - } - - _cairo_surface_init (&surface->base, - &i915_packed_pixel_surface_backend, - content); - - surface->bo = intel_bo_create (&device->intel, size, FALSE); - assert (surface->bo->tiling == I915_TILING_NONE); - if (unlikely (surface->bo == NULL)) { - free (surface); - return _cairo_surface_create_in_error (_cairo_error (CAIRO_STATUS_NO_MEMORY)); - } - - if (tiling == I915_TILING_NONE) { - intel_bo_t *bo = surface->bo; - uint32_t dst; - int uv; - - dst = surface->offset[0]; - if (width == stride) { - size = stride * height; - intel_bo_write (&device->intel, bo, dst, size, data); - data += size; - } else { - for (i = 0; i < height; i++) { - intel_bo_write (&device->intel, bo, dst, width, data); - dst += stride; - data += width; - } - } - - for (uv = 1; uv <= 2; uv++) { - dst = surface->offset[uv]; - if (width / 2 == half_stride) { - size = half_stride * height / 2; - intel_bo_write (&device->intel, bo, dst, size, data); - data += size; - } else { - size = width / 2; - for (i = 0; i < height / 2; i++) { - intel_bo_write (&device->intel, bo, dst, size, data); - dst += half_stride; - data += size; - } - } - } - } else { - uint8_t *dst, *base; - - base = intel_bo_map (&device->intel, surface->bo); - - dst = base + surface->offset[0]; - if (width == stride) { - size = stride * height; - memcpy (dst, data, size); - data += size; - } else { - for (i = 0; i < height; i++) { - memcpy (dst, data, width); - dst += stride; - data += width; - } - } - - dst = base + surface->offset[1]; - if (width / 2 == half_stride) { - size = half_stride * height / 2; - memcpy (dst, data, size); - data += size; - } else { - size = width / 2; - for (i = 0; i < height / 2; i++) { - memcpy (dst, data, size); - dst += half_stride; - data += size; - } - } - - dst = base + surface->offset[2]; - if (width / 2 == half_stride) { - size = half_stride * height / 2; - memcpy (dst, data, size); - data += size; - } else { - size = width / 2; - for (i = 0; i < height / 2; i++) { - memcpy (dst, data, size); - dst += half_stride; - data += size; - } - } - } - - surface->device = device; - surface->is_current_texture = 0; - - return &surface->base; -} - -static cairo_int_status_t -i915_clone_yuv (i915_surface_t *surface, - cairo_surface_t *source, - int width, int height, - cairo_surface_t **clone_out) -{ - const uint8_t *mime_data = NULL; - unsigned int mime_data_length; - cairo_surface_t *clone; - - cairo_surface_get_mime_data (source, "video/x-raw-yuv/i420", - &mime_data, &mime_data_length); - if (mime_data == NULL) - return CAIRO_INT_STATUS_UNSUPPORTED; - - clone = - i915_packed_pixel_surface_create ((i915_device_t *) surface->base.device, - YUV_I420, - mime_data, mime_data_length, - width, height); - if (clone == NULL) - return CAIRO_INT_STATUS_UNSUPPORTED; - if (unlikely (clone->status)) - return clone->status; - - *clone_out = clone; - return CAIRO_STATUS_SUCCESS; -} -#endif - -/* Max instruction count: 4 */ -static void -i915_shader_linear_color (i915_device_t *device, - enum i915_shader_linear_mode mode, - int in, int c0, int c1, int out) -{ - int tmp = FS_U0; - - switch (mode) { - case LINEAR_TEXTURE: - ASSERT_NOT_REACHED; - case LINEAR_NONE: - tmp = in; - break; - - case LINEAR_REPEAT: - i915_fs_frc (tmp, i915_fs_operand (in, X, X, X, X)); - break; -#if 0 - case LINEAR_REFLECT: - /* XXX needs an extra constant: C2 [0.5, 2.0, x, x] */ - i915_fs_mul (tmp, in, 0.5); - i915_fs_frc (tmp, i915_fs_operand_reg (tmp)); - i915_fs_mul (tmp, tmp, 2.0); - i915_fs_add (tmp, i915_fs_operand_one (), - i915_fs_operand_reg_negate (tmp)); - i915_fs_cmp (tmp, - i915_fs_operand_reg (tmp), - i915_fs_operand_reg (tmp), - i915_fs_operand_reg_negate (tmp)); - i915_fs_add (tmp, i915_fs_operand_one (), - i915_fs_operand_reg_negate (tmp)); -#endif - case LINEAR_PAD: - i915_fs_max (tmp, - i915_fs_operand_zero (), - i915_fs_operand (in, X, X, X, X)); - i915_fs_min (tmp, - i915_fs_operand_one (), - i915_fs_operand_reg (tmp)); - break; - } - - /* interpolate */ - i915_fs_mad (out, 0, - i915_fs_operand (tmp, NEG_X, NEG_X, NEG_X, NEG_X), - i915_fs_operand_reg (c0), - i915_fs_operand_reg (c0)); - i915_fs_mad (out, 0, - i915_fs_operand (tmp, X, X, X, X), - i915_fs_operand_reg (c1), - i915_fs_operand_reg (out)); -} - -static void -i915_shader_radial_init (struct i915_shader_radial *r, - const cairo_radial_pattern_t *radial) -{ - double dx, dy, dr, r1; - - dx = radial->cd2.center.x - radial->cd1.center.x; - dy = radial->cd2.center.y - radial->cd1.center.y; - dr = radial->cd2.radius - radial->cd1.radius; - - r1 = radial->cd1.radius; - - if (radial->cd2.center.x == radial->cd1.center.x && - radial->cd2.center.y == radial->cd1.center.y) - { - /* XXX dr == 0, meaningless with anything other than PAD */ - r->constants[0] = radial->cd1.center.x / dr; - r->constants[1] = radial->cd1.center.y / dr; - r->constants[2] = 1. / dr; - r->constants[3] = -r1 / dr; - - r->constants[4] = 0; - r->constants[5] = 0; - r->constants[6] = 0; - r->constants[7] = 0; - - r->base.mode = RADIAL_ONE; - } else { - r->constants[0] = -radial->cd1.center.x; - r->constants[1] = -radial->cd1.center.y; - r->constants[2] = r1; - r->constants[3] = -4 * (dx*dx + dy*dy - dr*dr); - - r->constants[4] = -2 * dx; - r->constants[5] = -2 * dy; - r->constants[6] = -2 * r1 * dr; - r->constants[7] = 1 / (2 * (dx*dx + dy*dy - dr*dr)); - - r->base.mode = RADIAL_TWO; - } - - r->base.matrix = radial->base.base.matrix; -} - -/* Max instruction count: 10 */ -static void -i915_shader_radial_coord (i915_device_t *device, - enum i915_shader_radial_mode mode, - int in, int g0, int g1, int out) -{ - switch (mode) { - case RADIAL_ONE: - /* - pdx = (x - c1x) / dr, pdy = (y - c1y) / dr; - r² = pdx*pdx + pdy*pdy - t = r²/sqrt(r²) - r1/dr; - */ - i915_fs_mad (FS_U0, MASK_X | MASK_Y, - i915_fs_operand (in, X, Y, ZERO, ZERO), - i915_fs_operand (g0, Z, Z, ZERO, ZERO), - i915_fs_operand (g0, NEG_X, NEG_Y, ZERO, ZERO)); - i915_fs_dp2add (FS_U0, MASK_X, - i915_fs_operand (FS_U0, X, Y, ZERO, ZERO), - i915_fs_operand (FS_U0, X, Y, ZERO, ZERO), - i915_fs_operand_zero ()); - i915_fs_rsq (out, MASK_X, i915_fs_operand (FS_U0, X, X, X, X)); - i915_fs_mad (out, MASK_X, - i915_fs_operand (FS_U0, X, ZERO, ZERO, ZERO), - i915_fs_operand (out, X, ZERO, ZERO, ZERO), - i915_fs_operand (g0, W, ZERO, ZERO, ZERO)); - break; - - case RADIAL_TWO: - /* - pdx = x - c1x, pdy = y - c1y; - A = dx² + dy² - dr² - B = -2*(pdx*dx + pdy*dy + r1*dr); - C = pdx² + pdy² - r1²; - det = B*B - 4*A*C; - t = (-B + sqrt (det)) / (2 * A) - */ - - /* u0.x = pdx, u0.y = pdy, u[0].z = r1; */ - i915_fs_add (FS_U0, - i915_fs_operand (in, X, Y, ZERO, ZERO), - i915_fs_operand (g0, X, Y, Z, ZERO)); - /* u0.x = pdx, u0.y = pdy, u[0].z = r1, u[0].w = B; */ - i915_fs_dp3 (FS_U0, MASK_W, - i915_fs_operand (FS_U0, X, Y, ONE, ZERO), - i915_fs_operand (g1, X, Y, Z, ZERO)); - /* u1.x = pdx² + pdy² - r1²; [C] */ - i915_fs_dp3 (FS_U1, MASK_X, - i915_fs_operand (FS_U0, X, Y, Z, ZERO), - i915_fs_operand (FS_U0, X, Y, NEG_Z, ZERO)); - /* u1.x = C, u1.y = B, u1.z=-4*A; */ - i915_fs_mov_masked (FS_U1, MASK_Y, i915_fs_operand (FS_U0, W, W, W, W)); - i915_fs_mov_masked (FS_U1, MASK_Z, i915_fs_operand (g0, W, W, W, W)); - /* u1.x = B² - 4*A*C */ - i915_fs_dp2add (FS_U1, MASK_X, - i915_fs_operand (FS_U1, X, Y, ZERO, ZERO), - i915_fs_operand (FS_U1, Z, Y, ZERO, ZERO), - i915_fs_operand_zero ()); - /* out.x = -B + sqrt (B² - 4*A*C), - * out.y = -B - sqrt (B² - 4*A*C), - */ - i915_fs_rsq (out, MASK_X, i915_fs_operand (FS_U1, X, X, X, X)); - i915_fs_mad (out, MASK_X | MASK_Y, - i915_fs_operand (out, X, X, ZERO, ZERO), - i915_fs_operand (FS_U1, X, NEG_X, ZERO, ZERO), - i915_fs_operand (FS_U0, NEG_W, NEG_W, ZERO, ZERO)); - /* out.x = (-B + sqrt (B² - 4*A*C)) / (2 * A), - * out.y = (-B - sqrt (B² - 4*A*C)) / (2 * A) - */ - i915_fs_mul (out, - i915_fs_operand (out, X, Y, ZERO, ZERO), - i915_fs_operand (g1, W, W, ZERO, ZERO)); - /* if (A > 0) - * out = (-B + sqrt (B² - 4*A*C)) / (2 * A), - * else - * out = (-B - sqrt (B² - 4*A*C)) / (2 * A) - */ - i915_fs_cmp (out, - i915_fs_operand (g1, W, ZERO, ZERO, ZERO), - i915_fs_operand (out, X, ZERO, ZERO, ZERO), - i915_fs_operand (out, Y, ZERO, ZERO, ZERO)); - break; - } -} - -/* Max instruction count: 7 */ -static inline void -i915_shader_yuv_color (i915_device_t *device, - int y, int u, int v, - int c0, int c1, int c2, - int out) -{ - i915_fs_mov_masked (FS_U0, MASK_X, i915_fs_operand_reg (y)); - i915_fs_mov_masked (FS_U0, MASK_Y, i915_fs_operand_reg (u)); - i915_fs_mov_masked (FS_U0, MASK_Z, i915_fs_operand_reg (v)); - - i915_fs_add (FS_U0, - i915_fs_operand_reg (FS_U0), - i915_fs_operand_reg (c0)); - i915_fs_dp3 (out, MASK_X, - i915_fs_operand_reg (FS_U0), - i915_fs_operand (c1, X, ZERO, Y, ZERO)); - i915_fs_dp3 (out, MASK_Z, - i915_fs_operand_reg (FS_U0), - i915_fs_operand (c1, Z, W, ZERO, ZERO)); - i915_fs_dp3 (out, MASK_Y, - i915_fs_operand_reg (FS_U0), - i915_fs_operand_reg (c2)); -} - -static inline uint32_t -i915_shader_channel_key (const union i915_shader_channel *channel) -{ - return (channel->type.fragment & 0x0f) | (channel->base.mode << FS_DETAILS_SHIFT); -} - -static uint32_t -i915_shader_channel_get_num_tex_coords (const union i915_shader_channel *channel) -{ - switch (channel->type.fragment) { - default: - case FS_ZERO: - case FS_ONE: - case FS_CONSTANT: - case FS_PURE: - case FS_DIFFUSE: - return 0; - - case FS_LINEAR: - case FS_RADIAL: - case FS_TEXTURE: - case FS_SPANS: - case FS_YUV: - return 1; - } -} - -static uint32_t -i915_shader_get_num_tex_coords (const i915_shader_t *shader) -{ - uint32_t num_tex_coords; - - num_tex_coords = 0; - - num_tex_coords += i915_shader_channel_get_num_tex_coords (&shader->source); - num_tex_coords += i915_shader_channel_get_num_tex_coords (&shader->mask); - num_tex_coords += i915_shader_channel_get_num_tex_coords (&shader->clip); - num_tex_coords += i915_shader_channel_get_num_tex_coords (&shader->dst); - - return num_tex_coords; -} - -#define i915_fs_operand_impure(reg, channel, pure) \ - (reg | \ - (((pure & (1 << 0)) ? channel##_CHANNEL_VAL : ZERO_CHANNEL_VAL) << X_CHANNEL_SHIFT) | \ - (((pure & (1 << 1)) ? channel##_CHANNEL_VAL : ZERO_CHANNEL_VAL) << Y_CHANNEL_SHIFT) | \ - (((pure & (1 << 2)) ? channel##_CHANNEL_VAL : ZERO_CHANNEL_VAL) << Z_CHANNEL_SHIFT) | \ - (((pure & (1 << 3)) ? channel##_CHANNEL_VAL : ZERO_CHANNEL_VAL) << W_CHANNEL_SHIFT)) - -#define i915_fs_operand_pure(pure) \ - (FS_R0 | \ - (((pure & (1 << 0)) ? ONE_CHANNEL_VAL : ZERO_CHANNEL_VAL) << X_CHANNEL_SHIFT) | \ - (((pure & (1 << 1)) ? ONE_CHANNEL_VAL : ZERO_CHANNEL_VAL) << Y_CHANNEL_SHIFT) | \ - (((pure & (1 << 2)) ? ONE_CHANNEL_VAL : ZERO_CHANNEL_VAL) << Z_CHANNEL_SHIFT) | \ - (((pure & (1 << 3)) ? ONE_CHANNEL_VAL : ZERO_CHANNEL_VAL) << W_CHANNEL_SHIFT)) - -static void -i915_set_shader_program (i915_device_t *device, - const i915_shader_t *shader) -{ - uint32_t num_tex_coords; - uint32_t num_samplers; - uint32_t n; - uint32_t texture_offset = 0; - uint32_t constant_offset = 0; - uint32_t sampler_offset = 0; - uint32_t source_reg; - uint32_t source_pure; - uint32_t mask_reg; - uint32_t out_reg; - uint32_t dest_reg; - FS_LOCALS; - - n = (i915_shader_channel_key (&shader->source) << 0) | - (i915_shader_channel_key (&shader->mask) << 8) | - (i915_shader_channel_key (&shader->clip) << 16) | - (shader->op << 24) | - ((shader->opacity < 1.) << 30) | - (((shader->content & CAIRO_CONTENT_ALPHA) == CAIRO_CONTENT_ALPHA) << 31); - if (n == device->current_program) - return; - device->current_program = n; - - FS_BEGIN (); - - if (shader->source.type.fragment == FS_ZERO) { - if (shader->clip.type.fragment == FS_TEXTURE) { - /* XXX need_combine */ - assert (shader->mask.type.fragment == (i915_fragment_shader_t) -1); - i915_fs_dcl (FS_T0); - i915_fs_texld (FS_U0, FS_S0, FS_T0); - if ((shader->content & CAIRO_CONTENT_COLOR) == 0) - i915_fs_mov (FS_OC, i915_fs_operand (FS_U0, W, W, W, W)); - else - i915_fs_mov (FS_OC, i915_fs_operand (FS_U0, ZERO, ZERO, ZERO, W)); - } else { - i915_fs_mov (FS_OC, i915_fs_operand_zero ()); - } - - FS_END (); - return; - } - - num_tex_coords = i915_shader_get_num_tex_coords (shader); - for (n = 0; n < num_tex_coords; n++) - i915_fs_dcl (FS_T0 + n); - - num_samplers = - shader->source.base.n_samplers + - shader->mask.base.n_samplers + - shader->clip.base.n_samplers + - shader->dst.base.n_samplers; - for (n = 0; n < num_samplers; n++) - i915_fs_dcl (FS_S0 + n); - - source_reg = ~0; - source_pure = 0; - out_reg = FS_R0; - if (! shader->need_combine && - shader->mask.type.fragment == (i915_fragment_shader_t) -1 && - shader->clip.type.fragment != FS_TEXTURE && - shader->content != CAIRO_CONTENT_ALPHA) - { - out_reg = FS_OC; - } - - switch (shader->source.type.fragment) { - default: - case FS_ZERO: - case FS_SPANS: - ASSERT_NOT_REACHED; - - case FS_PURE: - source_pure = shader->source.solid.pure; - case FS_ONE: - break; - - case FS_CONSTANT: - source_reg = FS_C0; - constant_offset += 1; - break; - - case FS_DIFFUSE: - i915_fs_dcl (FS_T8); - source_reg = FS_T8; - break; - - case FS_LINEAR: - i915_shader_linear_color (device, shader->source.base.mode, - FS_T0, /* input */ - FS_C0, FS_C1, /* colour ramp */ - FS_U3); /* unpremultiplied output */ - /* XXX can we defer premultiplication? */ - i915_fs_mul (out_reg, - i915_fs_operand_reg (FS_U3), - i915_fs_operand (FS_U3, W, W, W, ONE)); - - constant_offset += 2; - texture_offset += 1; - source_reg = out_reg; - break; - - case FS_RADIAL: - i915_shader_radial_coord (device, shader->source.base.mode, - FS_T0, /* input */ - FS_C0, FS_C1, /* gradient constants */ - FS_R0); /* coordinate */ - - i915_fs_texld (out_reg, FS_S0, FS_R0); - constant_offset += 2; - texture_offset += 1; - sampler_offset += 1; - source_reg = out_reg; - break; - - case FS_TEXTURE: - i915_fs_texld (out_reg, FS_S0, FS_T0); - texture_offset += 1; - sampler_offset += 1; - source_reg = out_reg; - break; - - case FS_YUV: - /* Load samplers to temporaries. */ - i915_fs_texld (FS_R0, FS_S0, FS_T0); - i915_fs_texld (FS_R1, FS_S1, FS_T0); - i915_fs_texld (FS_R2, FS_S2, FS_T0); - - i915_shader_yuv_color (device, - FS_R0, FS_R1, FS_R2, /* y, u, v */ - FS_C0, FS_C1, FS_C2, /* coefficients */ - out_reg); - - constant_offset += 3; - texture_offset += 1; - sampler_offset += 3; - source_reg = out_reg; - break; - } - - mask_reg = ~0; - switch (shader->mask.type.fragment) { - case FS_PURE: - case FS_ZERO: - case FS_YUV: - case FS_DIFFUSE: - ASSERT_NOT_REACHED; - case FS_ONE: - default: - break; - - case FS_SPANS: - mask_reg = FS_T0 + texture_offset; - texture_offset += 1; - break; - - case FS_CONSTANT: - mask_reg = FS_C0 + constant_offset; - constant_offset += 1; - break; - - case FS_LINEAR: - i915_shader_linear_color (device, shader->mask.base.mode, - FS_T0 + texture_offset, /* input */ - FS_C0 + constant_offset, - FS_C0 + constant_offset + 1, /* colour ramp */ - FS_R1); /* unpremultiplied output */ - constant_offset += 2; - texture_offset += 1; - mask_reg = FS_R1; - break; - - case FS_RADIAL: - i915_shader_radial_coord (device, shader->mask.base.mode, - FS_T0 + texture_offset, /* input */ - FS_C0 + constant_offset, - FS_C0 + constant_offset + 1, /* gradient constants */ - FS_R1); /* coordinate */ - - i915_fs_texld (FS_R1, FS_S0 + sampler_offset, FS_R1); - constant_offset += 2; - texture_offset += 1; - sampler_offset += 1; - mask_reg = FS_R1; - break; - - case FS_TEXTURE: - i915_fs_texld (FS_R1, FS_S0 + sampler_offset, FS_T0 + texture_offset); - texture_offset += 1; - sampler_offset += 1; - mask_reg = FS_R1; - break; - } - - if (mask_reg != ~0U) { - if (! shader->need_combine && - shader->clip.type.fragment != FS_TEXTURE && - (shader->content != CAIRO_CONTENT_ALPHA || source_reg == ~0U)) - { - out_reg = FS_OC; - } - if (source_reg == ~0U) { - if (source_pure) { - if (shader->mask.type.fragment == FS_SPANS) { - if (out_reg == FS_OC && shader->content == CAIRO_CONTENT_ALPHA) { - if (source_pure & (1 << 3)) - i915_fs_mov (out_reg, i915_fs_operand (mask_reg, X, X, X, X)); - else - i915_fs_mov (out_reg, i915_fs_operand_zero ()); - } else { - i915_fs_mov (out_reg, - i915_fs_operand_impure (mask_reg, X, source_pure)); - } - } else { - /* XXX ComponentAlpha - i915_fs_mov (out_reg, - i915_fs_operand_pure (mask_reg, - shader->source.solid.pure)); - */ - if (out_reg == FS_OC && shader->content == CAIRO_CONTENT_ALPHA) { - if (source_pure & (1 << 3)) - i915_fs_mov (out_reg, i915_fs_operand (mask_reg, W, W, W, W)); - else - i915_fs_mov (out_reg, i915_fs_operand_zero ()); - } else { - i915_fs_mov (out_reg, - i915_fs_operand_impure (mask_reg, W, source_pure)); - } - } - source_reg = out_reg; - } else if (shader->mask.type.fragment == FS_SPANS) { - i915_fs_mov (out_reg, - i915_fs_operand (mask_reg, X, X, X, X)); - source_reg = out_reg; - } else { - source_reg = mask_reg; - } - } else { - if (shader->mask.type.fragment == FS_SPANS) { - if (out_reg == FS_OC && shader->content == CAIRO_CONTENT_ALPHA) { - i915_fs_mul (out_reg, - i915_fs_operand (source_reg, W, W, W, W), - i915_fs_operand (mask_reg, X, X, X, X)); - } else { - i915_fs_mul (out_reg, - i915_fs_operand_reg (source_reg), - i915_fs_operand (mask_reg, X, X, X, X)); - } - } else { - /* XXX ComponentAlpha - i915_fs_mul (FS_R0, - i915_fs_operand_reg (source_reg), - i915_fs_operand_reg (mask_reg)); - */ - if (out_reg == FS_OC && shader->content == CAIRO_CONTENT_ALPHA) { - i915_fs_mul (out_reg, - i915_fs_operand (source_reg, W, W, W, W), - i915_fs_operand (mask_reg, W, W, W, W)); - } else { - i915_fs_mul (out_reg, - i915_fs_operand_reg (source_reg), - i915_fs_operand (mask_reg, W, W, W, W)); - } - } - - source_reg = out_reg; - } - } - - if (shader->opacity < 1.) { - i915_fs_mul (source_reg, - i915_fs_operand_reg (source_reg), - i915_fs_operand_reg (FS_C0 + constant_offset)); - constant_offset++; - } - - /* need to preserve order of src, mask, clip, dst */ - mask_reg = ~0; - if (shader->clip.type.fragment == FS_TEXTURE) { - i915_fs_texld (FS_R1, FS_S0 + sampler_offset, FS_T0 + texture_offset); - texture_offset += 1; - sampler_offset += 1; - mask_reg = FS_R1; - } - - if (shader->need_combine) { - assert (shader->dst.type.fragment == FS_TEXTURE); - - i915_fs_texld (FS_R2, FS_S0 + sampler_offset, FS_T0 + texture_offset); - texture_offset += 1; - sampler_offset += 1; - dest_reg = FS_R2; - - switch (shader->op) { - case CAIRO_OPERATOR_CLEAR: - case CAIRO_OPERATOR_SOURCE: - ASSERT_NOT_REACHED; - - case CAIRO_OPERATOR_OVER: - if (source_reg == ~0U) { - /* XXX shader->source.type.fragment == FS_PURE */ - dest_reg = FS_OC; - } else { - i915_fs_add (FS_U0, - i915_fs_operand (source_reg, NEG_W, NEG_W, NEG_W, NEG_W), - i915_fs_operand_one ()); - i915_fs_mul (FS_U0, - i915_fs_operand_reg (FS_U0), - dest_reg); - i915_fs_add (FS_R3, - i915_fs_operand_reg (source_reg), - i915_fs_operand_reg (FS_U0)); - source_reg = FS_R3; - } - break; - - case CAIRO_OPERATOR_IN: - if (source_reg == ~0U) { - /* XXX shader->source.type.fragment == FS_PURE */ - source_reg = dest_reg; - } else { - i915_fs_mul (FS_R3, - i915_fs_operand_reg (source_reg), - dest_reg); - source_reg = FS_R3; - } - break; - - case CAIRO_OPERATOR_OUT: - if (source_reg == ~0U) { - /* XXX shader->source.type.fragment == FS_PURE */ - i915_fs_mov (FS_R3, i915_fs_operand_zero ()); - source_reg = FS_R3; - } else { - i915_fs_add (FS_U0, - i915_fs_operand (source_reg, NEG_W, NEG_W, NEG_W, NEG_W), - i915_fs_operand_one ()); - i915_fs_mul (FS_R3, - i915_fs_operand_reg (FS_U0), - dest_reg); - source_reg = FS_R3; - } - break; - - case CAIRO_OPERATOR_ATOP: - - case CAIRO_OPERATOR_DEST: - case CAIRO_OPERATOR_DEST_OVER: - case CAIRO_OPERATOR_DEST_IN: - case CAIRO_OPERATOR_DEST_OUT: - case CAIRO_OPERATOR_DEST_ATOP: - - case CAIRO_OPERATOR_XOR: - case CAIRO_OPERATOR_ADD: - case CAIRO_OPERATOR_SATURATE: - - case CAIRO_OPERATOR_MULTIPLY: - case CAIRO_OPERATOR_SCREEN: - case CAIRO_OPERATOR_OVERLAY: - case CAIRO_OPERATOR_DARKEN: - case CAIRO_OPERATOR_LIGHTEN: - case CAIRO_OPERATOR_COLOR_DODGE: - case CAIRO_OPERATOR_COLOR_BURN: - case CAIRO_OPERATOR_HARD_LIGHT: - case CAIRO_OPERATOR_SOFT_LIGHT: - case CAIRO_OPERATOR_DIFFERENCE: - case CAIRO_OPERATOR_EXCLUSION: - case CAIRO_OPERATOR_HSL_HUE: - case CAIRO_OPERATOR_HSL_SATURATION: - case CAIRO_OPERATOR_HSL_COLOR: - case CAIRO_OPERATOR_HSL_LUMINOSITY: - ASSERT_NOT_REACHED; - break; - } - } - - if (shader->clip.type.fragment == FS_TEXTURE) { - assert (mask_reg != ~0U); - - if (! shader->need_combine) { - /* (source IN clip) */ - if (source_reg == ~0U) { - if (source_pure == 0) { - source_reg = mask_reg; - } else { - out_reg = FS_OC; - if ((shader->content & CAIRO_CONTENT_COLOR) == 0) { - if (source_pure & (1 << 3)) - i915_fs_mov (out_reg, i915_fs_operand (mask_reg, W, W, W, W)); - else - i915_fs_mov (out_reg, i915_fs_operand_zero ()); - } else { - i915_fs_mov (out_reg, - i915_fs_operand_impure (mask_reg, W, source_pure)); - } - source_reg = out_reg; - } - } else if (mask_reg) { - out_reg = FS_OC; - if ((shader->content & CAIRO_CONTENT_COLOR) == 0) { - i915_fs_mul (out_reg, - i915_fs_operand (source_reg, W, W, W, W), - i915_fs_operand (mask_reg, W, W, W, W)); - } else { - i915_fs_mul (out_reg, - i915_fs_operand_reg (source_reg), - i915_fs_operand (mask_reg, W, W, W, W)); - } - - source_reg = out_reg; - } - } else { - /* (source OP dest) LERP_clip dest */ - if (source_reg == ~0U) { - if (source_pure == 0) { - i915_fs_mov (FS_R3, - i915_fs_operand (mask_reg, W, W, W, W)); - } else { - i915_fs_mov (FS_R3, - i915_fs_operand_impure (mask_reg, W, source_pure)); - } - } else { - i915_fs_mul (FS_R3, - i915_fs_operand_reg (source_reg), - i915_fs_operand (mask_reg, W, W, W, W)); - } - - i915_fs_add (mask_reg, - i915_fs_operand_one (), - i915_fs_operand (mask_reg, NEG_W, NEG_W, NEG_W, NEG_W)); - - if (dest_reg != FS_OC) { - if (dest_reg == ~0U) { - assert (shader->dst.type.fragment == FS_TEXTURE); - - i915_fs_texld (FS_R2, FS_S0 + sampler_offset, FS_T0 + texture_offset); - texture_offset += 1; - sampler_offset += 1; - dest_reg = FS_R2; - } - - i915_fs_mul (FS_U1, - i915_fs_operand_reg (dest_reg), - i915_fs_operand_reg (mask_reg)); - mask_reg = FS_U1; - } - - source_reg = FS_OC; - if ((shader->content & CAIRO_CONTENT_COLOR) == 0) { - i915_fs_add (source_reg, - i915_fs_operand (FS_R3, W, W, W, W), - i915_fs_operand (mask_reg, W, W, W, W)); - } else { - i915_fs_add (source_reg, - i915_fs_operand_reg (FS_R3), - i915_fs_operand_reg (mask_reg)); - } - } - } - - if (source_reg != FS_OC) { - if (source_reg == ~0U) { - if (source_pure) { - if ((shader->content & CAIRO_CONTENT_COLOR) == 0) { - if (source_pure & (1 << 3)) - i915_fs_mov (FS_OC, i915_fs_operand_one ()); - else - i915_fs_mov (FS_OC, i915_fs_operand_zero ()); - } else - i915_fs_mov (FS_OC, i915_fs_operand_pure (source_pure)); - } else { - i915_fs_mov (FS_OC, i915_fs_operand_one ()); - } - } else if ((shader->content & CAIRO_CONTENT_COLOR) == 0) { - i915_fs_mov (FS_OC, i915_fs_operand (source_reg, W, W, W, W)); - } else { - i915_fs_mov (FS_OC, i915_fs_operand_reg (source_reg)); - } - } - - FS_END (); -} - -static cairo_bool_t -i915_shader_linear_init (struct i915_shader_linear *l, - const cairo_linear_pattern_t *linear) -{ - double x0, y0, sf; - double dx, dy, offset; - - dx = linear->pd2.x - linear->pd1.x; - dy = linear->pd2.y - linear->pd1.y; - sf = dx * dx + dy * dy; - if (sf <= 1e-5) - return FALSE; - - dx /= sf; - dy /= sf; - - x0 = linear->pd1.x; - y0 = linear->pd1.y; - offset = dx*x0 + dy*y0; - - if (_cairo_matrix_is_identity (&linear->base.base.matrix)) { - l->dx = dx; - l->dy = dy; - l->offset = -offset; - } else { - cairo_matrix_t m; - - cairo_matrix_init (&m, dx, 0, dy, 0, -offset, 0); - cairo_matrix_multiply (&m, &linear->base.base.matrix, &m); - l->dx = m.xx; - l->dy = m.xy; - l->offset = m.x0; - } - - return TRUE; -} - -static cairo_bool_t -i915_shader_linear_contains_rectangle (struct i915_shader_linear *l, - const cairo_rectangle_int_t *extents) -{ - double v; - - v = i915_shader_linear_texcoord (l, - extents->x, - extents->y); - if (v < 0.) - return FALSE; - if (v > 1.) - return FALSE; - - v = i915_shader_linear_texcoord (l, - extents->x + extents->width, - extents->y); - if (v < 0.) - return FALSE; - if (v > 1.) - return FALSE; - - v = i915_shader_linear_texcoord (l, - extents->x, - extents->y + extents->height); - if (v < 0.) - return FALSE; - if (v > 1.) - return FALSE; - - v = i915_shader_linear_texcoord (l, - extents->x + extents->width, - extents->y + extents->height); - if (v < 0.) - return FALSE; - if (v > 1.) - return FALSE; - - return TRUE; -} - -#define is_pure(C,mask) (((mask) == 0) || (C) <= 0x00ff || (C) >= 0xff00) -#define is_one(C,mask) (((mask) != 0) && (C) >= 0xff00) -#define is_zero(C,mask) (((mask) != 0) && (C) <= 0x00ff) - -static cairo_status_t -i915_shader_acquire_solid (i915_shader_t *shader, - union i915_shader_channel *src, - const cairo_solid_pattern_t *solid, - const cairo_rectangle_int_t *extents) -{ - cairo_content_t content; - - content = CAIRO_CONTENT_COLOR_ALPHA; - src->solid.color = solid->color; - if (content == 0 || solid->color.alpha_short <= 0x00ff) - { - src->base.content = CAIRO_CONTENT_ALPHA; - src->type.fragment = FS_ZERO; - } - else if ((((content & CAIRO_CONTENT_COLOR) == 0) || - (solid->color.red_short >= 0xff00 && - solid->color.green_short >= 0xff00 && - solid->color.blue_short >= 0xff00)) && - ((content & CAIRO_CONTENT_ALPHA) == 0 || - solid->color.alpha_short >= 0xff00)) - { - src->base.content = CAIRO_CONTENT_ALPHA; - src->type.fragment = FS_ONE; - } - else if (is_pure (solid->color.red_short, content & CAIRO_CONTENT_COLOR) && - is_pure (solid->color.green_short, content & CAIRO_CONTENT_COLOR) && - is_pure (solid->color.blue_short, content & CAIRO_CONTENT_COLOR) && - is_pure (solid->color.alpha_short, content & CAIRO_CONTENT_ALPHA)) - { - src->solid.pure = 0; - src->solid.pure |= is_one (solid->color.red_short, content & CAIRO_CONTENT_COLOR) << 0; - src->solid.pure |= is_one (solid->color.green_short, content & CAIRO_CONTENT_COLOR) << 1; - src->solid.pure |= is_one (solid->color.blue_short, content & CAIRO_CONTENT_COLOR) << 2; - src->solid.pure |= (! is_zero (solid->color.alpha_short, content & CAIRO_CONTENT_ALPHA)) << 3; - - if (src->solid.pure == 0) { - src->base.content = CAIRO_CONTENT_ALPHA; - src->type.fragment = FS_ZERO; - } else if (src->solid.pure == 0x7) { - src->base.content = CAIRO_CONTENT_ALPHA; - src->type.fragment = FS_ONE; - } else { - src->base.content = content; - src->type.fragment = FS_PURE; - src->base.mode = src->solid.pure; - } - } - else - { - src->base.content = content; - src->type.fragment = src == &shader->source ? FS_DIFFUSE : FS_CONSTANT; - } - src->type.vertex = src->type.fragment == FS_ZERO ? VS_ZERO : VS_CONSTANT; - src->type.pattern = PATTERN_CONSTANT; - - return CAIRO_STATUS_SUCCESS; -} - -static cairo_status_t -i915_shader_acquire_linear (i915_shader_t *shader, - union i915_shader_channel *src, - const cairo_linear_pattern_t *linear, - const cairo_rectangle_int_t *extents) -{ - cairo_bool_t mode = LINEAR_TEXTURE; - cairo_status_t status; - - if (i915_shader_linear_init (&src->linear, linear) && - linear->base.n_stops == 2 && - linear->base.stops[0].offset == 0.0 && - linear->base.stops[1].offset == 1.0) - { - if (i915_shader_linear_contains_rectangle (&src->linear, - extents)) - { - /* XXX can also lerp if contained within offset range */ - mode = LINEAR_NONE; - } - else switch (linear->base.base.extend) { - case CAIRO_EXTEND_REPEAT: - mode = LINEAR_REPEAT; - break; - case CAIRO_EXTEND_PAD: - mode = LINEAR_PAD; - break; - case CAIRO_EXTEND_NONE: - break; - case CAIRO_EXTEND_REFLECT: - break; - default: - ASSERT_NOT_REACHED; - break; - } - } - - src->type.vertex = VS_LINEAR; - src->type.pattern = PATTERN_LINEAR; - src->base.texfmt = TEXCOORDFMT_1D; - src->base.content = CAIRO_CONTENT_COLOR_ALPHA; - src->base.mode = mode; - if (mode == LINEAR_TEXTURE) { - intel_buffer_t buffer; - - status = intel_gradient_render ((intel_device_t *) shader->target->intel.drm.base.device, - &linear->base, &buffer); - if (unlikely (status)) - return status; - - src->type.fragment = FS_TEXTURE; - src->base.bo = intel_bo_reference (buffer.bo); - src->base.n_samplers = 1; - src->base.offset[0] = buffer.offset; - src->base.map[0] = buffer.map0; - src->base.map[1] = buffer.map1; - src->base.sampler[0] = - (MIPFILTER_NONE << SS2_MIP_FILTER_SHIFT) | - i915_texture_filter (CAIRO_FILTER_BILINEAR); - src->base.sampler[1] = - SS3_NORMALIZED_COORDS | - i915_texture_extend (linear->base.base.extend); - } else { - src->type.fragment = FS_LINEAR; - src->linear.color0.red = linear->base.stops[0].color.red; - src->linear.color0.green = linear->base.stops[0].color.green; - src->linear.color0.blue = linear->base.stops[0].color.blue; - src->linear.color0.alpha = linear->base.stops[0].color.alpha; - - src->linear.color1.red = linear->base.stops[1].color.red; - src->linear.color1.green = linear->base.stops[1].color.green; - src->linear.color1.blue = linear->base.stops[1].color.blue; - src->linear.color1.alpha = linear->base.stops[1].color.alpha; - } - - return CAIRO_STATUS_SUCCESS; -} - -static cairo_status_t -i915_shader_acquire_radial (i915_shader_t *shader, - union i915_shader_channel *src, - const cairo_radial_pattern_t *radial, - const cairo_rectangle_int_t *extents) -{ - intel_buffer_t buffer; - cairo_status_t status; - - status = intel_gradient_render ((intel_device_t *) shader->target->intel.drm.base.device, - &radial->base, &buffer); - if (unlikely (status)) - return status; - - i915_shader_radial_init (&src->radial, radial); - - src->type.vertex = VS_TEXTURE; - src->type.fragment = FS_RADIAL; - src->type.pattern = PATTERN_RADIAL; - src->base.texfmt = TEXCOORDFMT_2D; - - src->base.content = CAIRO_CONTENT_COLOR_ALPHA; - src->base.bo = intel_bo_reference (buffer.bo); - src->base.n_samplers = 1; - src->base.offset[0] = buffer.offset; - src->base.map[0] = buffer.map0; - src->base.map[1] = buffer.map1; - src->base.sampler[0] = - (MIPFILTER_NONE << SS2_MIP_FILTER_SHIFT) | - i915_texture_filter (CAIRO_FILTER_BILINEAR); - src->base.sampler[1] = - SS3_NORMALIZED_COORDS | - i915_texture_extend (radial->base.base.extend); - - return CAIRO_STATUS_SUCCESS; -} - -static cairo_status_t -i915_surface_clone (i915_device_t *device, - cairo_image_surface_t *image, - i915_surface_t **clone_out) -{ - i915_surface_t *clone; - cairo_status_t status; - -#if 0 - clone = - i915_surface_create_from_cacheable_image_internal (device, image); - if (unlikely (clone->intel.drm.base.status)) - return clone->intel.drm.base.status; -#else - cairo_format_t format; - - format = image->format; - if (format == CAIRO_FORMAT_A1) - format = CAIRO_FORMAT_A8; - - clone = (i915_surface_t *) - i915_surface_create_internal (&device->intel.base, - format, - image->width, - image->height, - I915_TILING_DEFAULT, - FALSE); - if (unlikely (clone->intel.drm.base.status)) - return clone->intel.drm.base.status; - - status = intel_bo_put_image (&device->intel, - to_intel_bo (clone->intel.drm.bo), - image, - 0, 0, - image->width, image->height, - 0, 0); - - if (unlikely (status)) - return status; -#endif - - *clone_out = clone; - return CAIRO_STATUS_SUCCESS; -} - -static cairo_status_t -i915_surface_clone_subimage (i915_device_t *device, - cairo_image_surface_t *image, - const cairo_rectangle_int_t *extents, - i915_surface_t **clone_out) -{ - i915_surface_t *clone; - cairo_status_t status; - cairo_format_t format; - - format = image->format; - if (format == CAIRO_FORMAT_A1) - format = CAIRO_FORMAT_A8; - - clone = (i915_surface_t *) - i915_surface_create_internal (&device->intel.base, - format, - extents->width, - extents->height, - I915_TILING_NONE, - FALSE); - if (unlikely (clone->intel.drm.base.status)) - return clone->intel.drm.base.status; - - status = intel_bo_put_image (&device->intel, - to_intel_bo (clone->intel.drm.bo), - image, - extents->x, extents->y, - extents->width, extents->height, - 0, 0); - - if (unlikely (status)) - return status; - - *clone_out = clone; - return CAIRO_STATUS_SUCCESS; -} - -static cairo_status_t -i915_surface_render_pattern (i915_device_t *device, - const cairo_surface_pattern_t *pattern, - const cairo_rectangle_int_t *extents, - i915_surface_t **clone_out) -{ - i915_surface_t *clone; - cairo_surface_t *image; - cairo_status_t status; - void *ptr; - - clone = (i915_surface_t *) - i915_surface_create_internal (&device->intel.base, - _cairo_format_from_content (pattern->surface->content), - extents->width, - extents->height, - I915_TILING_NONE, - FALSE); - if (unlikely (clone->intel.drm.base.status)) - return clone->intel.drm.base.status; - - ptr = intel_bo_map (&device->intel, - to_intel_bo (clone->intel.drm.bo)); - if (unlikely (ptr == NULL)) { - cairo_surface_destroy (&clone->intel.drm.base); - return _cairo_error (CAIRO_STATUS_NO_MEMORY); - } - - image = cairo_image_surface_create_for_data (ptr, - clone->intel.drm.format, - clone->intel.drm.width, - clone->intel.drm.height, - clone->intel.drm.stride); - if (unlikely (image->status)) { - cairo_surface_destroy (&clone->intel.drm.base); - return image->status; - } - - status = _cairo_surface_offset_paint (image, - extents->x, extents->y, - CAIRO_OPERATOR_SOURCE, - &pattern->base, - NULL); - cairo_surface_destroy (image); - - if (unlikely (status)) { - cairo_surface_destroy (&clone->intel.drm.base); - return status; - } - - *clone_out = clone; - return CAIRO_STATUS_SUCCESS; -} - -static cairo_status_t -i915_shader_acquire_solid_surface (i915_shader_t *shader, - union i915_shader_channel *src, - cairo_surface_t *surface, - const cairo_rectangle_int_t *extents) -{ - cairo_surface_pattern_t pattern; - cairo_surface_t *pixel; - cairo_image_surface_t *image; - void *image_extra; - cairo_status_t status; - uint32_t argb; - - status = _cairo_surface_acquire_source_image (surface, &image, &image_extra); - if (unlikely (status)) - return status; - - /* extract the pixel as argb32 */ - pixel = cairo_image_surface_create (CAIRO_FORMAT_ARGB32, 1, 1); - _cairo_pattern_init_for_surface (&pattern, &image->base); - cairo_matrix_init_translate (&pattern.base.matrix, extents->x, extents->y); - pattern.base.filter = CAIRO_FILTER_NEAREST; - status = _cairo_surface_paint (pixel, CAIRO_OPERATOR_SOURCE, &pattern.base, NULL); - _cairo_pattern_fini (&pattern.base); - - _cairo_surface_release_source_image (surface, image, image_extra); - - if (unlikely (status)) { - cairo_surface_destroy (pixel); - return status; - } - - image = (cairo_image_surface_t *) pixel; - argb = *(uint32_t *) image->data; - cairo_surface_destroy (pixel); - - if (argb >> 24 == 0) { - _cairo_color_init_rgba (&src->solid.color, 0, 0, 0, 0); - } else { - uint8_t alpha = argb >> 24; - - _cairo_color_init_rgba (&src->solid.color, - ((((argb >> 16) & 0xff) * 255 + alpha / 2) / alpha) / 255., - ((((argb >> 8) & 0xff) * 255 + alpha / 2) / alpha) / 255., - ((((argb >> 0) & 0xff) * 255 + alpha / 2) / alpha) / 255., - alpha / 255.); - } - - src->base.content = CAIRO_CONTENT_COLOR_ALPHA; - src->type.fragment = FS_CONSTANT; - src->type.vertex = VS_CONSTANT; - src->type.pattern = PATTERN_CONSTANT; - - return CAIRO_STATUS_SUCCESS; -} - -static cairo_status_t -i915_shader_acquire_surface (i915_shader_t *shader, - union i915_shader_channel *src, - const cairo_surface_pattern_t *pattern, - const cairo_rectangle_int_t *extents) -{ - int surface_width, surface_height; - cairo_surface_t *surface, *drm; - cairo_extend_t extend; - cairo_filter_t filter; - cairo_matrix_t m; - int src_x = 0, src_y = 0; - cairo_surface_t *free_me = NULL; - cairo_status_t status; - cairo_rectangle_int_t sample; - - assert (src->type.fragment == (i915_fragment_shader_t) -1); - drm = surface = pattern->surface; - - extend = pattern->base.extend; - src->base.matrix = pattern->base.matrix; - filter = pattern->base.filter; - _cairo_pattern_sampled_area(&pattern->base, extents, sample); - - if (surface->type == CAIRO_SURFACE_TYPE_DRM) { - if (surface->backend->type == CAIRO_SURFACE_TYPE_SUBSURFACE) { - drm = ((cairo_surface_subsurface_t *) surface)->target; - } else if (surface->backend->type == CAIRO_INTERNAL_SURFACE_TYPE_SNAPSHOT) { - drm = ((cairo_surface_snapshot_t *) surface)->target; - } - } - - if (drm->type == CAIRO_SURFACE_TYPE_DRM) { - i915_surface_t *s = (i915_surface_t *) drm; - - if (surface->backend->type == CAIRO_SURFACE_TYPE_SUBSURFACE) { - if (s->intel.drm.base.device == shader->target->intel.drm.base.device && - s != shader->target) - { - cairo_surface_subsurface_t *sub = (cairo_surface_subsurface_t *) surface; - int x; - - status = i915_surface_fallback_flush (s); - if (unlikely (status)) - return status; - - /* XXX blt subimage and cache snapshot */ - - if (to_intel_bo (s->intel.drm.bo)->batch_write_domain) { - /* XXX pipelined flush of RENDER/TEXTURE cache */ - } - - src->type.fragment = FS_TEXTURE; - src->surface.pixel = NONE; - surface_width = sub->extents.width; - surface_height = sub->extents.height; - - src->base.bo = intel_bo_reference (to_intel_bo (s->intel.drm.bo)); - src->base.n_samplers = 1; - - x = sub->extents.x; - if (s->intel.drm.format != CAIRO_FORMAT_A8) - x *= 4; - - /* XXX tiling restrictions upon offset? */ - src->base.offset[0] = s->offset + sub->extents.y * s->intel.drm.stride + x; - src->base.map[0] = s->map0; - src->base.map[0] &= ~((2047 << MS3_HEIGHT_SHIFT) | (2047 << MS3_WIDTH_SHIFT)); - src->base.map[0] |= - ((sub->extents.height - 1) << MS3_HEIGHT_SHIFT) | - ((sub->extents.width - 1) << MS3_WIDTH_SHIFT); - src->base.map[1] = (s->intel.drm.stride / 4 - 1) << MS4_PITCH_SHIFT; - } - } else { - /* XXX if s == shader->dst allow if FILTER_NEAREST, EXTEND_NONE? */ - if (s->intel.drm.base.device == shader->target->intel.drm.base.device) { - status = i915_surface_fallback_flush (s); - if (unlikely (status)) - return status; - - if (s == shader->target || i915_surface_needs_tiling (s)) { - status = i915_surface_copy_subimage (i915_device (shader->target), - s, &sample, TRUE, &s); - if (unlikely (status)) - return status; - - free_me = drm = &s->intel.drm.base; - } - - src->type.fragment = FS_TEXTURE; - src->surface.pixel = NONE; - - surface_width = s->intel.drm.width; - surface_height = s->intel.drm.height; - - src->base.bo = intel_bo_reference (to_intel_bo (s->intel.drm.bo)); - src->base.n_samplers = 1; - src->base.offset[0] = s->offset; - src->base.map[0] = s->map0; - src->base.map[1] = s->map1; - } - } - } - - if (src->type.fragment == (i915_fragment_shader_t) -1) { - i915_surface_t *s; - - if (extents->width == 1 && extents->height == 1) { - return i915_shader_acquire_solid_surface (shader, src, - surface, extents); - } - - s = (i915_surface_t *) - _cairo_surface_has_snapshot (surface, - shader->target->intel.drm.base.backend); - if (s == NULL) { - cairo_status_t status; - -#if 0 - /* XXX hackity hack hack */ - status = i915_clone_yuv (surface, src, - image->width, image->height, - clone_out); -#endif - - if (sample.width > 2048 || sample.height > 2048) { - status = i915_surface_render_pattern (i915_device (shader->target), - pattern, extents, - &s); - if (unlikely (status)) - return status; - - extend = CAIRO_EXTEND_NONE; - filter = CAIRO_FILTER_NEAREST; - cairo_matrix_init_translate (&src->base.matrix, - -extents->x, -extents->y); - } else { - cairo_image_surface_t *image; - void *image_extra; - - status = _cairo_surface_acquire_source_image (surface, &image, &image_extra); - if (unlikely (status)) - return status; - - if (image->width < 2048 && - image->height < 2048 && - sample.width >= image->width / 4 && - sample.height >= image->height /4) - { - - status = i915_surface_clone (i915_device (shader->target), - image, &s); - - if (likely (status == CAIRO_STATUS_SUCCESS)) { - _cairo_surface_attach_snapshot (surface, - &s->intel.drm.base, - intel_surface_detach_snapshot); - - status = intel_snapshot_cache_insert (&i915_device (shader->target)->intel, - &s->intel); - if (unlikely (status)) { - cairo_surface_finish (&s->intel.drm.base); - cairo_surface_destroy (&s->intel.drm.base); - } - } - } - else - { - status = i915_surface_clone_subimage (i915_device (shader->target), - image, &sample, &s); - src_x = -extents->x; - src_y = -extents->y; - } - - _cairo_surface_release_source_image (surface, image, image_extra); - if (unlikely (status)) - return status; - } - - free_me = &s->intel.drm.base; - } - - src->type.fragment = FS_TEXTURE; - src->surface.pixel = NONE; - - src->base.bo = intel_bo_reference (to_intel_bo (s->intel.drm.bo)); - src->base.n_samplers = 1; - src->base.offset[0] = s->offset; - src->base.map[0] = s->map0; - src->base.map[1] = s->map1; - - drm = &s->intel.drm.base; - - surface_width = s->intel.drm.width; - surface_height = s->intel.drm.height; - } - - /* XXX transform nx1 or 1xn surfaces to 1D */ - - src->type.pattern = PATTERN_TEXTURE; - if (extend != CAIRO_EXTEND_NONE && - sample.x >= 0 && sample.y >= 0 && - sample.x + sample.width <= surface_width && - sample.y + sample.height <= surface_height) - { - extend = CAIRO_EXTEND_NONE; - } - if (extend == CAIRO_EXTEND_NONE) { - src->type.vertex = VS_TEXTURE_16; - src->base.texfmt = TEXCOORDFMT_2D_16; - } else { - src->type.vertex = VS_TEXTURE; - src->base.texfmt = TEXCOORDFMT_2D; - } - src->base.content = drm->content; - - src->base.sampler[0] = - (MIPFILTER_NONE << SS2_MIP_FILTER_SHIFT) | - i915_texture_filter (filter); - src->base.sampler[1] = - SS3_NORMALIZED_COORDS | - i915_texture_extend (extend); - - /* tweak the src matrix to map from dst to texture coordinates */ - if (src_x | src_y) - cairo_matrix_translate (&src->base.matrix, src_x, src_x); - cairo_matrix_init_scale (&m, 1. / surface_width, 1. / surface_height); - cairo_matrix_multiply (&src->base.matrix, &src->base.matrix, &m); - - if (free_me != NULL) - cairo_surface_destroy (free_me); - - return CAIRO_STATUS_SUCCESS; -} - -cairo_status_t -i915_shader_acquire_pattern (i915_shader_t *shader, - union i915_shader_channel *src, - const cairo_pattern_t *pattern, - const cairo_rectangle_int_t *extents) -{ - switch (pattern->type) { - case CAIRO_PATTERN_TYPE_SOLID: - return i915_shader_acquire_solid (shader, src, - (cairo_solid_pattern_t *) pattern, - extents); - - case CAIRO_PATTERN_TYPE_LINEAR: - return i915_shader_acquire_linear (shader, src, - (cairo_linear_pattern_t *) pattern, - extents); - - case CAIRO_PATTERN_TYPE_RADIAL: - return i915_shader_acquire_radial (shader, src, - (cairo_radial_pattern_t *) pattern, - extents); - - case CAIRO_PATTERN_TYPE_SURFACE: - return i915_shader_acquire_surface (shader, src, - (cairo_surface_pattern_t *) pattern, - extents); - - default: - ASSERT_NOT_REACHED; - return CAIRO_STATUS_SUCCESS; - } -} - -static uint32_t -i915_get_blend (cairo_operator_t op, - i915_surface_t *dst) -{ -#define SBLEND(X) ((BLENDFACT_##X) << S6_CBUF_SRC_BLEND_FACT_SHIFT) -#define DBLEND(X) ((BLENDFACT_##X) << S6_CBUF_DST_BLEND_FACT_SHIFT) - static const struct blendinfo { - cairo_bool_t dst_alpha; - uint32_t src_blend; - uint32_t dst_blend; - enum { - BOUNDED, - SIMPLE, - XRENDER, - } kind; - } i915_blend_op[] = { - {0, SBLEND (ZERO), DBLEND (ZERO), BOUNDED}, /* Clear */ - {0, SBLEND (ONE), DBLEND (ZERO), BOUNDED}, /* Src */ - - {0, SBLEND (ONE), DBLEND (INV_SRC_ALPHA), SIMPLE}, /* Over */ - {1, SBLEND (DST_ALPHA), DBLEND (ZERO), XRENDER}, /* In */ - {1, SBLEND (INV_DST_ALPHA), DBLEND (ZERO), XRENDER}, /* Out */ - {1, SBLEND (DST_ALPHA), DBLEND (INV_SRC_ALPHA), SIMPLE}, /* Atop */ - - {0, SBLEND (ZERO), DBLEND (ONE), SIMPLE}, /* Dst */ - {1, SBLEND (INV_DST_ALPHA), DBLEND (ONE), SIMPLE}, /* OverReverse */ - {0, SBLEND (ZERO), DBLEND (SRC_ALPHA), XRENDER}, /* InReverse */ - {0, SBLEND (ZERO), DBLEND (INV_SRC_ALPHA), SIMPLE}, /* OutReverse */ - {1, SBLEND (INV_DST_ALPHA), DBLEND (SRC_ALPHA), XRENDER}, /* AtopReverse */ - - {1, SBLEND (INV_DST_ALPHA), DBLEND (INV_SRC_ALPHA), SIMPLE}, /* Xor */ - {0, SBLEND (ONE), DBLEND (ONE), SIMPLE}, /* Add */ - //{0, 0, SBLEND (SRC_ALPHA_SATURATE), DBLEND (ONE), SIMPLE}, /* XXX Saturate */ - }; - uint32_t sblend, dblend; - - if (op >= ARRAY_LENGTH (i915_blend_op)) - return 0; - - if (i915_blend_op[op].kind == BOUNDED) - return 0; - - sblend = i915_blend_op[op].src_blend; - dblend = i915_blend_op[op].dst_blend; - - /* If there's no dst alpha channel, adjust the blend op so that we'll treat - * it as always 1. - */ - if ((dst->intel.drm.base.content & CAIRO_CONTENT_ALPHA) == 0 && - i915_blend_op[op].dst_alpha) - { - if (sblend == SBLEND (DST_ALPHA)) - sblend = SBLEND (ONE); - else if (sblend == SBLEND (INV_DST_ALPHA)) - sblend = SBLEND (ZERO); - } - - /* i915 engine reads 8bit color buffer into green channel in cases - like color buffer blending etc., and also writes back green channel. - So with dst_alpha blend we should use color factor. See spec on - "8-bit rendering" */ - if (dst->intel.drm.format == CAIRO_FORMAT_A8 && i915_blend_op[op].dst_alpha) { - if (sblend == SBLEND (DST_ALPHA)) - sblend = SBLEND (DST_COLR); - else if (sblend == SBLEND (INV_DST_ALPHA)) - sblend = SBLEND (INV_DST_COLR); - } - - return sblend | dblend; -#undef SBLEND -#undef DBLEND -} - -static void -i915_shader_channel_init (union i915_shader_channel *channel) -{ - channel->type.vertex = (i915_vertex_shader_t) -1; - channel->type.fragment = (i915_fragment_shader_t) -1; - channel->type.pattern = (i915_shader_channel_t) -1; - channel->base.texfmt = TEXCOORDFMT_NOT_PRESENT; - channel->base.bo = NULL; - channel->base.n_samplers = 0; - channel->base.mode = 0; -} - -static void -i915_shader_channel_fini (i915_device_t *device, - union i915_shader_channel *channel) -{ - switch (channel->type.pattern) { - case PATTERN_TEXTURE: - case PATTERN_BASE: - case PATTERN_LINEAR: - case PATTERN_RADIAL: - if (channel->base.bo != NULL) - intel_bo_destroy (&device->intel, channel->base.bo); - break; - - default: - case PATTERN_CONSTANT: - break; - } -} - -static void -i915_shader_channel_reset (i915_device_t *device, - union i915_shader_channel *channel) -{ - i915_shader_channel_fini (device, channel); - i915_shader_channel_init (channel); -} - -void -i915_shader_init (i915_shader_t *shader, - i915_surface_t *dst, - cairo_operator_t op, - double opacity) -{ - shader->committed = FALSE; - shader->device = i915_device (dst); - shader->target = dst; - shader->op = op; - shader->opacity = opacity; - - shader->blend = i915_get_blend (op, dst); - shader->need_combine = FALSE; - - shader->content = dst->intel.drm.base.content; - - i915_shader_channel_init (&shader->source); - i915_shader_channel_init (&shader->mask); - i915_shader_channel_init (&shader->clip); - i915_shader_channel_init (&shader->dst); -} - -static void -i915_set_shader_samplers (i915_device_t *device, - const i915_shader_t *shader) -{ - uint32_t n_samplers, n_maps, n; - uint32_t samplers[2*4]; - uint32_t maps[4*4]; - uint32_t mask, s, m; - - n_maps = - shader->source.base.n_samplers + - shader->mask.base.n_samplers + - shader->clip.base.n_samplers + - shader->dst.base.n_samplers; - assert (n_maps <= 4); - - if (n_maps == 0) - return; - - n_samplers = - !! shader->source.base.bo + - !! shader->mask.base.bo + - !! shader->clip.base.bo + - !! shader->dst.base.bo; - - mask = (1 << n_maps) - 1; - - /* We check for repeated setting of sample state mainly to catch - * continuation of text strings across multiple show-glyphs. - */ - s = m = 0; - if (shader->source.base.bo != NULL) { - samplers[s++] = shader->source.base.sampler[0]; - samplers[s++] = shader->source.base.sampler[1]; - maps[m++] = shader->source.base.bo->base.handle; - for (n = 0; n < shader->source.base.n_samplers; n++) { - maps[m++] = shader->source.base.offset[n]; - maps[m++] = shader->source.base.map[2*n+0]; - maps[m++] = shader->source.base.map[2*n+1]; - } - } - if (shader->mask.base.bo != NULL) { - samplers[s++] = shader->mask.base.sampler[0]; - samplers[s++] = shader->mask.base.sampler[1]; - maps[m++] = shader->mask.base.bo->base.handle; - for (n = 0; n < shader->mask.base.n_samplers; n++) { - maps[m++] = shader->mask.base.offset[n]; - maps[m++] = shader->mask.base.map[2*n+0]; - maps[m++] = shader->mask.base.map[2*n+1]; - } - } - if (shader->clip.base.bo != NULL) { - samplers[s++] = shader->clip.base.sampler[0]; - samplers[s++] = shader->clip.base.sampler[1]; - maps[m++] = shader->clip.base.bo->base.handle; - for (n = 0; n < shader->clip.base.n_samplers; n++) { - maps[m++] = shader->clip.base.offset[n]; - maps[m++] = shader->clip.base.map[2*n+0]; - maps[m++] = shader->clip.base.map[2*n+1]; - } - } - if (shader->dst.base.bo != NULL) { - samplers[s++] = shader->dst.base.sampler[0]; - samplers[s++] = shader->dst.base.sampler[1]; - maps[m++] = shader->dst.base.bo->base.handle; - for (n = 0; n < shader->dst.base.n_samplers; n++) { - maps[m++] = shader->dst.base.offset[n]; - maps[m++] = shader->dst.base.map[2*n+0]; - maps[m++] = shader->dst.base.map[2*n+1]; - } - } - - if (n_maps > device->current_n_maps || - memcmp (device->current_maps, - maps, - m * sizeof (uint32_t))) - { - memcpy (device->current_maps, maps, m * sizeof (uint32_t)); - device->current_n_maps = n_maps; - - if (device->current_source != NULL) - *device->current_source = 0; - if (device->current_mask != NULL) - *device->current_mask = 0; - if (device->current_clip != NULL) - *device->current_clip = 0; - -#if 0 - if (shader->source.type.pattern == PATTERN_TEXTURE) { - switch ((int) shader->source.surface.surface->type) { - case CAIRO_SURFACE_TYPE_DRM: - { - i915_surface_t *surface = - (i915_surface_t *) shader->source.surface.surface; - device->current_source = &surface->is_current_texture; - surface->is_current_texture |= CURRENT_SOURCE; - break; - } - - case I915_PACKED_PIXEL_SURFACE_TYPE: - { - i915_packed_pixel_surface_t *surface = - (i915_packed_pixel_surface_t *) shader->source.surface.surface; - device->current_source = &surface->is_current_texture; - surface->is_current_texture |= CURRENT_SOURCE; - break; - } - - default: - device->current_source = NULL; - break; - } - } else - device->current_source = NULL; - - if (shader->mask.type.pattern == PATTERN_TEXTURE) { - switch ((int) shader->mask.surface.surface->type) { - case CAIRO_SURFACE_TYPE_DRM: - { - i915_surface_t *surface = - (i915_surface_t *) shader->mask.surface.surface; - device->current_mask = &surface->is_current_texture; - surface->is_current_texture |= CURRENT_MASK; - break; - } - - case I915_PACKED_PIXEL_SURFACE_TYPE: - { - i915_packed_pixel_surface_t *surface = - (i915_packed_pixel_surface_t *) shader->mask.surface.surface; - device->current_mask = &surface->is_current_texture; - surface->is_current_texture |= CURRENT_MASK; - break; - } - - default: - device->current_mask = NULL; - break; - } - } else - device->current_mask = NULL; -#endif - - OUT_DWORD (_3DSTATE_MAP_STATE | (3 * n_maps)); - OUT_DWORD (mask); - for (n = 0; n < shader->source.base.n_samplers; n++) { - i915_batch_emit_reloc (device, shader->source.base.bo, - shader->source.base.offset[n], - I915_GEM_DOMAIN_SAMPLER, 0, - FALSE); - OUT_DWORD (shader->source.base.map[2*n+0]); - OUT_DWORD (shader->source.base.map[2*n+1]); - } - for (n = 0; n < shader->mask.base.n_samplers; n++) { - i915_batch_emit_reloc (device, shader->mask.base.bo, - shader->mask.base.offset[n], - I915_GEM_DOMAIN_SAMPLER, 0, - FALSE); - OUT_DWORD (shader->mask.base.map[2*n+0]); - OUT_DWORD (shader->mask.base.map[2*n+1]); - } - for (n = 0; n < shader->clip.base.n_samplers; n++) { - i915_batch_emit_reloc (device, shader->clip.base.bo, - shader->clip.base.offset[n], - I915_GEM_DOMAIN_SAMPLER, 0, - FALSE); - OUT_DWORD (shader->clip.base.map[2*n+0]); - OUT_DWORD (shader->clip.base.map[2*n+1]); - } - for (n = 0; n < shader->dst.base.n_samplers; n++) { - i915_batch_emit_reloc (device, shader->dst.base.bo, - shader->dst.base.offset[n], - I915_GEM_DOMAIN_SAMPLER, 0, - FALSE); - OUT_DWORD (shader->dst.base.map[2*n+0]); - OUT_DWORD (shader->dst.base.map[2*n+1]); - } - } - - if (n_samplers > device->current_n_samplers || - memcmp (device->current_samplers, - samplers, - s * sizeof (uint32_t))) - { - device->current_n_samplers = s; - memcpy (device->current_samplers, samplers, s * sizeof (uint32_t)); - - OUT_DWORD (_3DSTATE_SAMPLER_STATE | (3 * n_maps)); - OUT_DWORD (mask); - s = 0; - for (n = 0; n < shader->source.base.n_samplers; n++) { - OUT_DWORD (shader->source.base.sampler[0]); - OUT_DWORD (shader->source.base.sampler[1] | - (s << SS3_TEXTUREMAP_INDEX_SHIFT)); - OUT_DWORD (0x0); - s++; - } - for (n = 0; n < shader->mask.base.n_samplers; n++) { - OUT_DWORD (shader->mask.base.sampler[0]); - OUT_DWORD (shader->mask.base.sampler[1] | - (s << SS3_TEXTUREMAP_INDEX_SHIFT)); - OUT_DWORD (0x0); - s++; - } - for (n = 0; n < shader->clip.base.n_samplers; n++) { - OUT_DWORD (shader->clip.base.sampler[0]); - OUT_DWORD (shader->clip.base.sampler[1] | - (s << SS3_TEXTUREMAP_INDEX_SHIFT)); - OUT_DWORD (0x0); - s++; - } - for (n = 0; n < shader->dst.base.n_samplers; n++) { - OUT_DWORD (shader->dst.base.sampler[0]); - OUT_DWORD (shader->dst.base.sampler[1] | - (s << SS3_TEXTUREMAP_INDEX_SHIFT)); - OUT_DWORD (0x0); - s++; - } - } -} - -static uint32_t -i915_shader_get_texcoords (const i915_shader_t *shader) -{ - uint32_t texcoords; - uint32_t tu; - - texcoords = S2_TEXCOORD_NONE; - tu = 0; - if (shader->source.base.texfmt != TEXCOORDFMT_NOT_PRESENT) { - texcoords &= ~S2_TEXCOORD_FMT (tu, S2_TEXCOORD_FMT0_MASK); - texcoords |= S2_TEXCOORD_FMT (tu, shader->source.base.texfmt); - tu++; - } - if (shader->mask.base.texfmt != TEXCOORDFMT_NOT_PRESENT) { - texcoords &= ~S2_TEXCOORD_FMT (tu, S2_TEXCOORD_FMT0_MASK); - texcoords |= S2_TEXCOORD_FMT (tu, shader->mask.base.texfmt); - tu++; - } - if (shader->clip.base.texfmt != TEXCOORDFMT_NOT_PRESENT) { - texcoords &= ~S2_TEXCOORD_FMT (tu, S2_TEXCOORD_FMT0_MASK); - texcoords |= S2_TEXCOORD_FMT (tu, shader->clip.base.texfmt); - tu++; - } - if (shader->dst.base.texfmt != TEXCOORDFMT_NOT_PRESENT) { - texcoords &= ~S2_TEXCOORD_FMT (tu, S2_TEXCOORD_FMT0_MASK); - texcoords |= S2_TEXCOORD_FMT (tu, shader->dst.base.texfmt); - tu++; - } - - return texcoords; -} - -static void -i915_set_shader_mode (i915_device_t *device, - const i915_shader_t *shader) -{ - uint32_t texcoords; - uint32_t mask, cnt; - - texcoords = i915_shader_get_texcoords (shader); - - mask = cnt = 0; - - if (device->current_texcoords != texcoords) - mask |= I1_LOAD_S (2), cnt++; - - if (device->current_blend != shader->blend) - mask |= I1_LOAD_S (6), cnt++; - - if (cnt == 0) - return; - - OUT_DWORD (_3DSTATE_LOAD_STATE_IMMEDIATE_1 | mask | (cnt-1)); - - if (device->current_texcoords != texcoords) { - OUT_DWORD (texcoords); - device->current_texcoords = texcoords; - } - - if (device->current_blend != shader->blend) { - if (shader->blend) { - OUT_DWORD (S6_CBUF_BLEND_ENABLE | S6_COLOR_WRITE_ENABLE | - (BLENDFUNC_ADD << S6_CBUF_BLEND_FUNC_SHIFT) | - shader->blend); - } else { - OUT_DWORD (S6_COLOR_WRITE_ENABLE); - } - - device->current_blend = shader->blend; - } -} - -static void -i915_set_constants (i915_device_t *device, - const uint32_t *constants, - uint32_t n_constants) -{ - uint32_t n; - - OUT_DWORD (_3DSTATE_PIXEL_SHADER_CONSTANTS | n_constants); - OUT_DWORD ((1 << (n_constants >> 2)) - 1); - - for (n = 0; n < n_constants; n++) - OUT_DWORD (constants[n]); - - device->current_n_constants = n_constants; - memcpy (device->current_constants, constants, n_constants*4); -} - -static uint32_t -pack_constants (const union i915_shader_channel *channel, - uint32_t *constants) -{ - uint32_t count = 0, n; - - switch (channel->type.fragment) { - case FS_ZERO: - case FS_ONE: - case FS_PURE: - case FS_DIFFUSE: - break; - - case FS_CONSTANT: - constants[count++] = pack_float (channel->solid.color.red); - constants[count++] = pack_float (channel->solid.color.green); - constants[count++] = pack_float (channel->solid.color.blue); - constants[count++] = pack_float (channel->solid.color.alpha); - break; - - case FS_LINEAR: - constants[count++] = pack_float (channel->linear.color0.red); - constants[count++] = pack_float (channel->linear.color0.green); - constants[count++] = pack_float (channel->linear.color0.blue); - constants[count++] = pack_float (channel->linear.color0.alpha); - - constants[count++] = pack_float (channel->linear.color1.red); - constants[count++] = pack_float (channel->linear.color1.green); - constants[count++] = pack_float (channel->linear.color1.blue); - constants[count++] = pack_float (channel->linear.color1.alpha); - break; - - case FS_RADIAL: - for (n = 0; n < ARRAY_LENGTH (channel->radial.constants); n++) - constants[count++] = pack_float (channel->radial.constants[n]); - break; - - case FS_TEXTURE: - case FS_YUV: - case FS_SPANS: - break; - } - - return count; -} - -static void -i915_set_shader_constants (i915_device_t *device, - const i915_shader_t *shader) -{ - uint32_t constants[4*4*3+4]; - unsigned n_constants; - - n_constants = 0; - if (shader->source.type.fragment == FS_DIFFUSE) { - uint32_t diffuse; - - diffuse = - ((uint32_t)(shader->source.solid.color.alpha_short >> 8) << 24) | - ((shader->source.solid.color.red_short >> 8) << 16) | - ((shader->source.solid.color.green_short >> 8) << 8) | - ((shader->source.solid.color.blue_short >> 8) << 0); - - if (diffuse != device->current_diffuse) { - OUT_DWORD (_3DSTATE_DFLT_DIFFUSE_CMD); - OUT_DWORD (diffuse); - device->current_diffuse = diffuse; - } - } else { - n_constants += pack_constants (&shader->source, constants + n_constants); - } - n_constants += pack_constants (&shader->mask, constants + n_constants); - - if (shader->opacity < 1.) { - constants[n_constants+0] = - constants[n_constants+1] = - constants[n_constants+2] = - constants[n_constants+3] = pack_float (shader->opacity); - n_constants += 4; - } - - if (n_constants != 0 && - (device->current_n_constants != n_constants || - memcmp (device->current_constants, constants, n_constants*4))) - { - i915_set_constants (device, constants, n_constants); - } -} - -static cairo_bool_t -i915_shader_needs_update (const i915_shader_t *shader, - const i915_device_t *device) -{ - uint32_t count, n; - uint32_t buf[64]; - - if (device->current_target != shader->target) - return TRUE; - - count = - !! shader->source.base.bo + - !! shader->mask.base.bo + - !! shader->clip.base.bo + - !! shader->dst.base.bo; - if (count > device->current_n_samplers) - return TRUE; - - count = - shader->source.base.n_samplers + - shader->mask.base.n_samplers + - shader->clip.base.n_samplers + - shader->dst.base.n_samplers; - if (count > device->current_n_maps) - return TRUE; - - if (count) { - count = 0; - if (shader->source.base.bo != NULL) { - buf[count++] = shader->source.base.sampler[0]; - buf[count++] = shader->source.base.sampler[1]; - } - if (shader->mask.base.bo != NULL) { - buf[count++] = shader->mask.base.sampler[0]; - buf[count++] = shader->mask.base.sampler[1]; - } - if (shader->clip.base.bo != NULL) { - buf[count++] = shader->clip.base.sampler[0]; - buf[count++] = shader->clip.base.sampler[1]; - } - if (shader->dst.base.bo != NULL) { - buf[count++] = shader->dst.base.sampler[0]; - buf[count++] = shader->dst.base.sampler[1]; - } - if (memcmp (device->current_samplers, buf, count * sizeof (uint32_t))) - return TRUE; - - count = 0; - if (shader->source.base.bo != NULL) { - buf[count++] = shader->source.base.bo->base.handle; - for (n = 0; n < shader->source.base.n_samplers; n++) { - buf[count++] = shader->source.base.offset[n]; - buf[count++] = shader->source.base.map[2*n+0]; - buf[count++] = shader->source.base.map[2*n+1]; - } - } - if (shader->mask.base.bo != NULL) { - buf[count++] = shader->mask.base.bo->base.handle; - for (n = 0; n < shader->mask.base.n_samplers; n++) { - buf[count++] = shader->mask.base.offset[n]; - buf[count++] = shader->mask.base.map[2*n+0]; - buf[count++] = shader->mask.base.map[2*n+1]; - } - } - if (shader->clip.base.bo != NULL) { - buf[count++] = shader->clip.base.bo->base.handle; - for (n = 0; n < shader->clip.base.n_samplers; n++) { - buf[count++] = shader->clip.base.offset[n]; - buf[count++] = shader->clip.base.map[2*n+0]; - buf[count++] = shader->clip.base.map[2*n+1]; - } - } - if (shader->dst.base.bo != NULL) { - buf[count++] = shader->dst.base.bo->base.handle; - for (n = 0; n < shader->dst.base.n_samplers; n++) { - buf[count++] = shader->dst.base.offset[n]; - buf[count++] = shader->dst.base.map[2*n+0]; - buf[count++] = shader->dst.base.map[2*n+1]; - } - } - if (memcmp (device->current_maps, buf, count * sizeof (uint32_t))) - return TRUE; - } - - if (i915_shader_get_texcoords (shader) != device->current_texcoords) - return TRUE; - if (device->current_blend != shader->blend) - return TRUE; - - count = 0; - if (shader->source.type.fragment == FS_DIFFUSE) { - uint32_t diffuse; - - diffuse = - ((uint32_t)(shader->source.solid.color.alpha_short >> 8) << 24) | - ((shader->source.solid.color.red_short >> 8) << 16) | - ((shader->source.solid.color.green_short >> 8) << 8) | - ((shader->source.solid.color.blue_short >> 8) << 0); - - if (diffuse != device->current_diffuse) - return TRUE; - } else { - count += pack_constants (&shader->source, buf + count); - } - count += pack_constants (&shader->mask, buf + count); - - if (count && - (device->current_n_constants != count || - memcmp (device->current_constants, buf, count*4))) - { - return TRUE; - } - - n = (i915_shader_channel_key (&shader->source) << 0) | - (i915_shader_channel_key (&shader->mask) << 8) | - (i915_shader_channel_key (&shader->clip) << 16) | - (shader->op << 24) | - ((shader->opacity < 1.) << 30) | - (((shader->content & CAIRO_CONTENT_ALPHA) == CAIRO_CONTENT_ALPHA) << 31); - return n != device->current_program; -} - -void -i915_set_dst (i915_device_t *device, i915_surface_t *dst) -{ - uint32_t size; - - if (device->current_target != dst) { - intel_bo_t *bo; - - bo = to_intel_bo (dst->intel.drm.bo); - assert (bo != NULL); - - OUT_DWORD (_3DSTATE_BUF_INFO_CMD); - OUT_DWORD (BUF_3D_ID_COLOR_BACK | - BUF_tiling (bo->tiling) | - BUF_3D_PITCH (dst->intel.drm.stride)); - OUT_RELOC (dst, I915_GEM_DOMAIN_RENDER, I915_GEM_DOMAIN_RENDER); - - device->current_target = dst; - } - - if (dst->colorbuf != device->current_colorbuf) { - OUT_DWORD (_3DSTATE_DST_BUF_VARS_CMD); - OUT_DWORD (dst->colorbuf); - device->current_colorbuf = dst->colorbuf; - } - - size = DRAW_YMAX (dst->intel.drm.height) | DRAW_XMAX (dst->intel.drm.width); - if (size != device->current_size) { - OUT_DWORD (_3DSTATE_DRAW_RECT_CMD); - OUT_DWORD (0); /* dither */ - OUT_DWORD (0); /* top-left */ - OUT_DWORD (size); - OUT_DWORD (0); /* origin */ - device->current_size = size; - } -} - -static void -i915_set_shader_target (i915_device_t *device, - const i915_shader_t *shader) -{ - i915_set_dst (device, shader->target); -} - -int -i915_shader_num_texcoords (const i915_shader_t *shader) -{ - int cnt = 0; - - switch (shader->source.base.texfmt) { - default: - ASSERT_NOT_REACHED; - case TEXCOORDFMT_NOT_PRESENT: break; - case TEXCOORDFMT_2D: cnt += 2; break; - case TEXCOORDFMT_3D: cnt += 3; break; - case TEXCOORDFMT_4D: cnt += 4; break; - case TEXCOORDFMT_1D: cnt += 1; break; - case TEXCOORDFMT_2D_16: cnt += 1; break; - } - - switch (shader->mask.base.texfmt) { - default: - ASSERT_NOT_REACHED; - case TEXCOORDFMT_NOT_PRESENT: break; - case TEXCOORDFMT_2D: cnt += 2; break; - case TEXCOORDFMT_3D: cnt += 3; break; - case TEXCOORDFMT_4D: cnt += 4; break; - case TEXCOORDFMT_1D: cnt += 1; break; - case TEXCOORDFMT_2D_16: cnt += 1; break; - } - - switch (shader->clip.base.texfmt) { - default: - ASSERT_NOT_REACHED; - case TEXCOORDFMT_NOT_PRESENT: break; - case TEXCOORDFMT_2D: cnt += 2; break; - case TEXCOORDFMT_3D: cnt += 3; break; - case TEXCOORDFMT_4D: cnt += 4; break; - case TEXCOORDFMT_1D: cnt += 1; break; - case TEXCOORDFMT_2D_16: cnt += 1; break; - } - - switch (shader->dst.base.texfmt) { - default: - ASSERT_NOT_REACHED; - case TEXCOORDFMT_NOT_PRESENT: break; - case TEXCOORDFMT_2D: cnt += 2; break; - case TEXCOORDFMT_3D: cnt += 3; break; - case TEXCOORDFMT_4D: cnt += 4; break; - case TEXCOORDFMT_1D: cnt += 1; break; - case TEXCOORDFMT_2D_16: cnt += 1; break; - } - - return cnt; -} - -void -i915_shader_fini (i915_shader_t *shader) -{ - i915_device_t *device = i915_device (shader->target); - - i915_shader_channel_fini (device, &shader->source); - i915_shader_channel_fini (device, &shader->mask); - i915_shader_channel_fini (device, &shader->clip); -} - -void -i915_shader_set_clip (i915_shader_t *shader, - cairo_clip_t *clip) -{ - cairo_surface_t *clip_surface; - int clip_x, clip_y; - union i915_shader_channel *channel; - i915_surface_t *s; - - clip_surface = _cairo_clip_get_surface (clip, &shader->target->intel.drm.base, &clip_x, &clip_y); - assert (clip_surface->status == CAIRO_STATUS_SUCCESS); - assert (clip_surface->type == CAIRO_SURFACE_TYPE_DRM); - - channel = &shader->clip; - channel->type.vertex = VS_TEXTURE_16; - channel->base.texfmt = TEXCOORDFMT_2D_16; - channel->base.content = CAIRO_CONTENT_ALPHA; - - channel->type.fragment = FS_TEXTURE; - channel->surface.pixel = NONE; - - s = (i915_surface_t *) clip_surface; - channel->base.bo = to_intel_bo (s->intel.drm.bo); - channel->base.n_samplers = 1; - channel->base.offset[0] = s->offset; - channel->base.map[0] = s->map0; - channel->base.map[1] = s->map1; - - channel->base.sampler[0] = - (MIPFILTER_NONE << SS2_MIP_FILTER_SHIFT) | - i915_texture_filter (CAIRO_FILTER_NEAREST); - channel->base.sampler[1] = - SS3_NORMALIZED_COORDS | - i915_texture_extend (CAIRO_EXTEND_NONE); - - cairo_matrix_init_scale (&shader->clip.base.matrix, - 1. / s->intel.drm.width, - 1. / s->intel.drm.height); - cairo_matrix_translate (&shader->clip.base.matrix, - -clip_x, -clip_y); -} - -static cairo_status_t -i915_shader_check_aperture (i915_shader_t *shader, - i915_device_t *device) -{ - cairo_status_t status; - intel_bo_t *bo_array[4]; - uint32_t n = 0; - - if (shader->target != device->current_target) - bo_array[n++] = to_intel_bo (shader->target->intel.drm.bo); - - if (shader->source.base.bo != NULL) - bo_array[n++] = shader->source.base.bo; - - if (shader->mask.base.bo != NULL) - bo_array[n++] = shader->mask.base.bo; - - if (shader->clip.base.bo != NULL) - bo_array[n++] = shader->clip.base.bo; - - if (n == 0 || i915_check_aperture (device, bo_array, n)) - return CAIRO_STATUS_SUCCESS; - - status = i915_batch_flush (device); - if (unlikely (status)) - return status; - - assert (i915_check_aperture (device, bo_array, n)); - return CAIRO_STATUS_SUCCESS; -} - -static void -i915_shader_combine_mask (i915_shader_t *shader, i915_device_t *device) -{ - if (shader->mask.type.fragment == (i915_fragment_shader_t) -1 || - shader->mask.type.fragment == FS_CONSTANT) - { - return; - } - - if (shader->mask.type.fragment == FS_PURE) { - if (shader->mask.solid.pure & (1<<3)) { - shader->mask.type.fragment = FS_ONE; - } else { - shader->mask.type.fragment = FS_ZERO; - } - } - - if (shader->mask.type.fragment == FS_ONE || - (shader->mask.base.content & CAIRO_CONTENT_ALPHA) == 0) - { - i915_shader_channel_reset (device, &shader->mask); - } - - if (shader->mask.type.fragment == FS_ZERO) { - i915_shader_channel_fini (device, &shader->source); - - shader->source.type.fragment = FS_ZERO; - shader->source.type.vertex = VS_ZERO; - shader->source.base.texfmt = TEXCOORDFMT_NOT_PRESENT; - shader->source.base.mode = 0; - shader->source.base.n_samplers = 0; - } - - if (shader->source.type.fragment == FS_ZERO) { - i915_shader_channel_reset (device, &shader->mask); - i915_shader_channel_reset (device, &shader->clip); - } -} - -static void -i915_shader_setup_dst (i915_shader_t *shader) -{ - union i915_shader_channel *channel; - i915_surface_t *s; - - /* We need to manual blending if we have a clip surface and an unbounded op, - * or an extended blend mode. - */ - if (shader->need_combine || - (shader->op < CAIRO_OPERATOR_SATURATE && - (shader->clip.type.fragment == (i915_fragment_shader_t) -1 || - _cairo_operator_bounded_by_mask (shader->op)))) - { - return; - } - - shader->need_combine = TRUE; - - channel = &shader->dst; - channel->type.vertex = VS_TEXTURE_16; - channel->base.texfmt = TEXCOORDFMT_2D_16; - channel->base.content = shader->content; - - channel->type.fragment = FS_TEXTURE; - channel->surface.pixel = NONE; - - s = shader->target; - channel->base.bo = to_intel_bo (s->intel.drm.bo); - channel->base.n_samplers = 1; - channel->base.offset[0] = s->offset; - channel->base.map[0] = s->map0; - channel->base.map[1] = s->map1; - - channel->base.sampler[0] = - (MIPFILTER_NONE << SS2_MIP_FILTER_SHIFT) | - i915_texture_filter (CAIRO_FILTER_NEAREST); - channel->base.sampler[1] = - SS3_NORMALIZED_COORDS | - i915_texture_extend (CAIRO_EXTEND_NONE); - - cairo_matrix_init_scale (&shader->dst.base.matrix, - 1. / s->intel.drm.width, - 1. / s->intel.drm.height); -} - -static void -i915_shader_combine_source (i915_shader_t *shader, - i915_device_t *device) -{ - if (device->last_source_fragment == shader->source.type.fragment) - return; - - if (device->last_source_fragment == FS_DIFFUSE) { - switch (shader->source.type.fragment) { - case FS_ONE: - case FS_PURE: - case FS_CONSTANT: - case FS_DIFFUSE: - shader->source.type.fragment = FS_DIFFUSE; - shader->source.base.mode = 0; - break; - case FS_ZERO: - case FS_LINEAR: - case FS_RADIAL: - case FS_TEXTURE: - case FS_YUV: - case FS_SPANS: - default: - break; - } - } - - device->last_source_fragment = shader->source.type.fragment; -} - -static inline float * -i915_composite_vertex (float *v, - const i915_shader_t *shader, - double x, double y) -{ - double s, t; - - /* Each vertex is: - * 2 vertex coordinates - * [0-2] source texture coordinates - * [0-2] mask texture coordinates - */ - - *v++ = x; *v++ = y; - switch (shader->source.type.vertex) { - case VS_ZERO: - case VS_CONSTANT: - break; - case VS_LINEAR: - *v++ = i915_shader_linear_texcoord (&shader->source.linear, x, y); - break; - case VS_TEXTURE: - s = x, t = y; - cairo_matrix_transform_point (&shader->source.base.matrix, &s, &t); - *v++ = s; *v++ = t; - break; - case VS_TEXTURE_16: - s = x, t = y; - cairo_matrix_transform_point (&shader->source.base.matrix, &s, &t); - *v++ = texcoord_2d_16 (s, t); - break; - } - switch (shader->mask.type.vertex) { - case VS_ZERO: - case VS_CONSTANT: - break; - case VS_LINEAR: - *v++ = i915_shader_linear_texcoord (&shader->mask.linear, x, y); - break; - case VS_TEXTURE: - s = x, t = y; - cairo_matrix_transform_point (&shader->mask.base.matrix, &s, &t); - *v++ = s; *v++ = t; - break; - case VS_TEXTURE_16: - s = x, t = y; - cairo_matrix_transform_point (&shader->mask.base.matrix, &s, &t); - *v++ = texcoord_2d_16 (s, t); - break; - } - - return v; -} - -static inline void -i915_shader_add_rectangle_general (const i915_shader_t *shader, - int x, int y, - int w, int h) -{ - float *vertices; - - vertices = i915_add_rectangle (shader->device); - vertices = i915_composite_vertex (vertices, shader, x + w, y + h); - vertices = i915_composite_vertex (vertices, shader, x, y + h); - vertices = i915_composite_vertex (vertices, shader, x, y); - /* XXX overflow! */ -} - -void -i915_vbo_flush (i915_device_t *device) -{ - assert (device->floats_per_vertex); - assert (device->vertex_count); - - if (device->vbo == 0) { - OUT_DWORD (_3DSTATE_LOAD_STATE_IMMEDIATE_1 | - I1_LOAD_S (0) | - I1_LOAD_S (1) | - 1); - device->vbo = device->batch.used++; - device->vbo_max_index = device->batch.used; - OUT_DWORD ((device->floats_per_vertex << S1_VERTEX_WIDTH_SHIFT) | - (device->floats_per_vertex << S1_VERTEX_PITCH_SHIFT)); - } - - OUT_DWORD (PRIM3D_RECTLIST | - PRIM3D_INDIRECT_SEQUENTIAL | - device->vertex_count); - OUT_DWORD (device->vertex_index); - - device->vertex_index += device->vertex_count; - device->vertex_count = 0; -} - -cairo_status_t -i915_shader_commit (i915_shader_t *shader, - i915_device_t *device) -{ - unsigned floats_per_vertex; - cairo_status_t status; - - assert (CAIRO_MUTEX_IS_LOCKED (device->intel.base.base.mutex)); - - if (! shader->committed) { - device->shader = shader; - - i915_shader_combine_mask (shader, device); - i915_shader_combine_source (shader, device); - i915_shader_setup_dst (shader); - - shader->add_rectangle = i915_shader_add_rectangle_general; - - if ((status = setjmp (shader->unwind))) - return status; - - shader->committed = TRUE; - } - - if (i915_shader_needs_update (shader, device)) { - if (i915_batch_space (device) < 256) { - status = i915_batch_flush (device); - if (unlikely (status)) - return status; - } - - if (device->vertex_count) - i915_vbo_flush (device); - - status = i915_shader_check_aperture (shader, device); - if (unlikely (status)) - return status; - - update_shader: - i915_set_shader_target (device, shader); - i915_set_shader_mode (device, shader); - i915_set_shader_samplers (device, shader); - i915_set_shader_constants (device, shader); - i915_set_shader_program (device, shader); - } - - floats_per_vertex = 2 + i915_shader_num_texcoords (shader); - if (device->floats_per_vertex == floats_per_vertex) - return CAIRO_STATUS_SUCCESS; - - if (i915_batch_space (device) < 8) { - status = i915_batch_flush (device); - if (unlikely (status)) - return status; - - goto update_shader; - } - - if (device->vertex_count) - i915_vbo_flush (device); - - if (device->vbo) { - device->batch_base[device->vbo_max_index] |= device->vertex_index; - OUT_DWORD (_3DSTATE_LOAD_STATE_IMMEDIATE_1 | I1_LOAD_S (1) | 0); - device->vbo_max_index = device->batch.used; - OUT_DWORD ((floats_per_vertex << S1_VERTEX_WIDTH_SHIFT) | - (floats_per_vertex << S1_VERTEX_PITCH_SHIFT)); - } - - device->floats_per_vertex = floats_per_vertex; - device->rectangle_size = floats_per_vertex * 3 * sizeof (float); - device->vertex_index = - (device->vbo_used + 4*floats_per_vertex - 1) / (4 * floats_per_vertex); - device->vbo_offset = 4 * device->vertex_index * floats_per_vertex; - - return CAIRO_STATUS_SUCCESS; -} diff --git a/gfx/cairo/cairo/src/drm/cairo-drm-i915-spans.c b/gfx/cairo/cairo/src/drm/cairo-drm-i915-spans.c deleted file mode 100644 index f40bb2f2ed..0000000000 --- a/gfx/cairo/cairo/src/drm/cairo-drm-i915-spans.c +++ /dev/null @@ -1,799 +0,0 @@ -/* cairo - a vector graphics library with display and print output - * - * Copyright © 2009 Intel Corporation - * - * This library is free software; you can redistribute it and/or - * modify it either under the terms of the GNU Lesser General Public - * License version 2.1 as published by the Free Software Foundation - * (the "LGPL") or, at your option, under the terms of the Mozilla - * Public License Version 1.1 (the "MPL"). If you do not alter this - * notice, a recipient may use your version of this file under either - * the MPL or the LGPL. - * - * You should have received a copy of the LGPL along with this library - * in the file COPYING-LGPL-2.1; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Suite 500, Boston, MA 02110-1335, 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): - * Chris Wilson <chris@chris-wilson.co.uk> - */ - -#include "cairoint.h" - -#include "cairo-composite-rectangles-private.h" -#include "cairo-boxes-private.h" -#include "cairo-error-private.h" -#include "cairo-drm-i915-private.h" - -/* Operates in either immediate or retained mode. - * When given a clip region we record the sequence of vbo and then - * replay them for each clip rectangle, otherwise we simply emit - * the vbo straight into the command stream. - */ - -typedef struct _i915_spans i915_spans_t; - -typedef float * -(*i915_get_rectangle_func_t) (i915_spans_t *spans); - -typedef void -(*i915_span_func_t) (i915_spans_t *spans, - int x0, int x1, int y0, int y1, - int alpha); - -struct _i915_spans { - cairo_span_renderer_t renderer; - - i915_device_t *device; - - int xmin, xmax; - cairo_bool_t is_bounded; - const cairo_rectangle_int_t *extents; - - i915_get_rectangle_func_t get_rectangle; - i915_span_func_t span; - i915_shader_t shader; - - cairo_region_t *clip_region; - cairo_bool_t need_clip_surface; - - struct vbo { - struct vbo *next; - intel_bo_t *bo; - unsigned int count; - } head, *tail; - - unsigned int vbo_offset; - float *vbo_base; -}; - -static float * -i915_emit_rectangle (i915_spans_t *spans) -{ - return i915_add_rectangle (spans->device); -} - -static float * -i915_accumulate_rectangle (i915_spans_t *spans) -{ - float *vertices; - uint32_t size; - - size = spans->device->rectangle_size; - if (unlikely (spans->vbo_offset + size > I915_VBO_SIZE)) { - struct vbo *vbo; - - vbo = _cairo_malloc (sizeof (struct vbo)); - if (unlikely (vbo == NULL)) { - /* throw error! */ - } - - spans->tail->next = vbo; - spans->tail = vbo; - - vbo->next = NULL; - vbo->bo = intel_bo_create (&spans->device->intel, - I915_VBO_SIZE, I915_VBO_SIZE, - FALSE, I915_TILING_NONE, 0); - vbo->count = 0; - - spans->vbo_offset = 0; - spans->vbo_base = intel_bo_map (&spans->device->intel, vbo->bo); - } - - vertices = spans->vbo_base + spans->vbo_offset; - spans->vbo_offset += size; - spans->tail->count += 3; - - return vertices; -} - -static void -i915_span_zero (i915_spans_t *spans, - int x0, int x1, int y0, int y1, - int alpha) -{ - float *vertices; - - vertices = spans->get_rectangle (spans); - - *vertices++ = x1; - *vertices++ = y1; - - *vertices++ = x0; - *vertices++ = y1; - - *vertices++ = x0; - *vertices++ = y0; -} - -static void -i915_span_constant (i915_spans_t *spans, - int x0, int x1, int y0, int y1, - int alpha) -{ - float *vertices; - float a = alpha / 255.; - - vertices = spans->get_rectangle (spans); - - *vertices++ = x1; - *vertices++ = y1; - *vertices++ = a; - - *vertices++ = x0; - *vertices++ = y1; - *vertices++ = a; - - *vertices++ = x0; - *vertices++ = y0; - *vertices++ = a; -} - -static void -i915_span_linear (i915_spans_t *spans, - int x0, int x1, int y0, int y1, - int alpha) -{ - float *vertices; - float a = alpha / 255.; - double s, t; - - vertices = spans->get_rectangle (spans); - - *vertices++ = x1; - *vertices++ = y1; - s = x0, t = y0; - *vertices++ = i915_shader_linear_texcoord (&spans->shader.source.linear, s, t); - *vertices++ = a; - - *vertices++ = x0; - *vertices++ = y1; - s = x1, t = y0; - *vertices++ = i915_shader_linear_texcoord (&spans->shader.source.linear, s, t); - *vertices++ = a; - - *vertices++ = x0; - *vertices++ = y0; - s = x1, t = y1; - *vertices++ = i915_shader_linear_texcoord (&spans->shader.source.linear, s, t); - *vertices++ = a; -} - -static void -i915_span_texture (i915_spans_t *spans, - int x0, int x1, int y0, int y1, - int alpha) -{ - float *vertices; - float a = alpha / 255.; - double s, t; - - vertices = spans->get_rectangle (spans); - - *vertices++ = x1; - *vertices++ = y1; - s = x0, t = y0; - cairo_matrix_transform_point (&spans->shader.source.base.matrix, &s, &t); - *vertices++ = s; *vertices++ = t; - *vertices++ = a; - - *vertices++ = x0; - *vertices++ = y1; - s = x1, t = y0; - cairo_matrix_transform_point (&spans->shader.source.base.matrix, &s, &t); - *vertices++ = s; *vertices++ = t; - *vertices++ = a; - - *vertices++ = x0; - *vertices++ = y0; - s = x1, t = y1; - cairo_matrix_transform_point (&spans->shader.source.base.matrix, &s, &t); - *vertices++ = s; *vertices++ = t; - *vertices++ = a; -} - -static void -i915_span_texture16 (i915_spans_t *spans, - int x0, int x1, int y0, int y1, int alpha) -{ - float *vertices; - float a = alpha / 255.; - double s, t; - - vertices = spans->get_rectangle (spans); - - *vertices++ = x1; - *vertices++ = y1; - s = x0, t = y0; - cairo_matrix_transform_point (&spans->shader.source.base.matrix, &s, &t); - *vertices++ = texcoord_2d_16 (s, t); - *vertices++ = a; - - *vertices++ = x0; - *vertices++ = y1; - s = x1, t = y0; - cairo_matrix_transform_point (&spans->shader.source.base.matrix, &s, &t); - *vertices++ = texcoord_2d_16 (s, t); - *vertices++ = a; - - *vertices++ = x0; - *vertices++ = y0; - s = x1, t = y1; - cairo_matrix_transform_point (&spans->shader.source.base.matrix, &s, &t); - *vertices++ = texcoord_2d_16 (s, t); - *vertices++ = a; -} - -static void -i915_span_generic (i915_spans_t *spans, - int x0, int x1, int y0, int y1, int alpha) -{ - double s, t; - float *vertices; - float a = alpha / 255.; - - /* Each vertex is: - * 2 vertex coordinates - * [0-2] source texture coordinates - * 1 alpha value. - * [0,2] clip mask coordinates - */ - - vertices = spans->get_rectangle (spans); - - /* bottom right */ - *vertices++ = x1; *vertices++ = y1; - s = x1, t = y1; - switch (spans->shader.source.type.vertex) { - case VS_ZERO: - case VS_CONSTANT: - break; - case VS_LINEAR: - *vertices++ = i915_shader_linear_texcoord (&spans->shader.source.linear, s, t); - break; - case VS_TEXTURE: - cairo_matrix_transform_point (&spans->shader.source.base.matrix, &s, &t); - *vertices++ = s; *vertices++ = t; - break; - case VS_TEXTURE_16: - cairo_matrix_transform_point (&spans->shader.source.base.matrix, &s, &t); - *vertices++ = texcoord_2d_16 (s, t); - break; - } - *vertices++ = a; - if (spans->need_clip_surface) { - s = x1, t = y1; - cairo_matrix_transform_point (&spans->shader.clip.base.matrix, &s, &t); - *vertices++ = texcoord_2d_16 (s, t); - } - if (spans->shader.need_combine) { - s = x1, t = y1; - cairo_matrix_transform_point (&spans->shader.dst.base.matrix, &s, &t); - *vertices++ = texcoord_2d_16 (s, t); - } - - /* bottom left */ - *vertices++ = x0; *vertices++ = y1; - s = x0, t = y1; - switch (spans->shader.source.type.vertex) { - case VS_ZERO: - case VS_CONSTANT: - break; - case VS_LINEAR: - *vertices++ = i915_shader_linear_texcoord (&spans->shader.source.linear, s, t); - break; - case VS_TEXTURE: - cairo_matrix_transform_point (&spans->shader.source.base.matrix, &s, &t); - *vertices++ = s; *vertices++ = t; - break; - case VS_TEXTURE_16: - cairo_matrix_transform_point (&spans->shader.source.base.matrix, &s, &t); - *vertices++ = texcoord_2d_16 (s, t); - break; - } - *vertices++ = a; - if (spans->need_clip_surface) { - s = x0, t = y1; - cairo_matrix_transform_point (&spans->shader.clip.base.matrix, &s, &t); - *vertices++ = texcoord_2d_16 (s, t); - } - if (spans->shader.need_combine) { - s = x0, t = y1; - cairo_matrix_transform_point (&spans->shader.dst.base.matrix, &s, &t); - *vertices++ = texcoord_2d_16 (s, t); - } - - /* top left */ - *vertices++ = x0; *vertices++ = y0; - s = x0, t = y0; - switch (spans->shader.source.type.vertex) { - case VS_ZERO: - case VS_CONSTANT: - break; - case VS_LINEAR: - *vertices++ = i915_shader_linear_texcoord (&spans->shader.source.linear, s, t); - break; - case VS_TEXTURE: - cairo_matrix_transform_point (&spans->shader.source.base.matrix, &s, &t); - *vertices++ = s; *vertices++ = t; - break; - case VS_TEXTURE_16: - cairo_matrix_transform_point (&spans->shader.source.base.matrix, &s, &t); - *vertices++ = texcoord_2d_16 (s, t); - break; - } - *vertices++ = a; - if (spans->need_clip_surface) { - s = x0, t = y0; - cairo_matrix_transform_point (&spans->shader.clip.base.matrix, &s, &t); - *vertices++ = texcoord_2d_16 (s, t); - } - if (spans->shader.need_combine) { - s = x0, t = y0; - cairo_matrix_transform_point (&spans->shader.dst.base.matrix, &s, &t); - *vertices++ = texcoord_2d_16 (s, t); - } -} - -static cairo_status_t -i915_zero_spans_mono (void *abstract_renderer, - int y, int height, - const cairo_half_open_span_t *half, - unsigned num_spans) -{ - i915_spans_t *spans = abstract_renderer; - int x0, x1; - - if (num_spans == 0) - return CAIRO_STATUS_SUCCESS; - - do { - while (num_spans && half[0].coverage < 128) - half++, num_spans--; - if (num_spans == 0) - break; - - x0 = x1 = half[0].x; - while (num_spans--) { - half++; - - x1 = half[0].x; - if (half[0].coverage < 128) - break; - } - - i915_span_zero (spans, - x0, x1, - y, y + height, - 0); - } while (num_spans); - - return CAIRO_STATUS_SUCCESS; -} - -static cairo_status_t -i915_zero_spans (void *abstract_renderer, - int y, int height, - const cairo_half_open_span_t *half, - unsigned num_spans) -{ - i915_spans_t *spans = abstract_renderer; - int x0, x1; - - if (num_spans == 0) - return CAIRO_STATUS_SUCCESS; - - do { - while (num_spans && half[0].coverage == 0) - half++, num_spans--; - if (num_spans == 0) - break; - - x0 = x1 = half[0].x; - while (num_spans--) { - half++; - - x1 = half[0].x; - if (half[0].coverage == 0) - break; - } - - i915_span_zero (spans, - x0, x1, - y, y + height, - 0); - } while (num_spans); - - return CAIRO_STATUS_SUCCESS; -} - -static cairo_status_t -i915_bounded_spans_mono (void *abstract_renderer, - int y, int height, - const cairo_half_open_span_t *half, - unsigned num_spans) -{ - i915_spans_t *spans = abstract_renderer; - - if (num_spans == 0) - return CAIRO_STATUS_SUCCESS; - - do { - if (half[0].coverage >= 128) { - spans->span (spans, - half[0].x, half[1].x, - y, y + height, - 255); - } - half++; - } while (--num_spans > 1); - - return CAIRO_STATUS_SUCCESS; -} - -static cairo_status_t -i915_bounded_spans (void *abstract_renderer, - int y, int height, - const cairo_half_open_span_t *half, - unsigned num_spans) -{ - i915_spans_t *spans = abstract_renderer; - - if (num_spans == 0) - return CAIRO_STATUS_SUCCESS; - - do { - if (half[0].coverage) { - spans->span (spans, - half[0].x, half[1].x, - y, y + height, - half[0].coverage); - } - half++; - } while (--num_spans > 1); - - return CAIRO_STATUS_SUCCESS; -} - -static cairo_status_t -i915_unbounded_spans (void *abstract_renderer, - int y, int height, - const cairo_half_open_span_t *half, - unsigned num_spans) -{ - i915_spans_t *spans = abstract_renderer; - - if (num_spans == 0) { - spans->span (spans, - spans->xmin, spans->xmax, - y, y + height, - 0); - return CAIRO_STATUS_SUCCESS; - } - - if (half[0].x != spans->xmin) { - spans->span (spans, - spans->xmin, half[0].x, - y, y + height, - 0); - } - - do { - spans->span (spans, - half[0].x, half[1].x, - y, y + height, - half[0].coverage); - half++; - } while (--num_spans > 1); - - if (half[0].x != spans->xmax) { - spans->span (spans, - half[0].x, spans->xmax, - y, y + height, - 0); - } - - return CAIRO_STATUS_SUCCESS; -} - -static cairo_status_t -i915_unbounded_spans_mono (void *abstract_renderer, - int y, int height, - const cairo_half_open_span_t *half, - unsigned num_spans) -{ - i915_spans_t *spans = abstract_renderer; - - if (num_spans == 0) { - spans->span (spans, - spans->xmin, spans->xmax, - y, y + height, - 0); - return CAIRO_STATUS_SUCCESS; - } - - if (half[0].x != spans->xmin) { - spans->span (spans, - spans->xmin, half[0].x, - y, y + height, - 0); - } - - do { - int alpha = 0; - if (half[0].coverage >= 128) - alpha = 255; - spans->span (spans, - half[0].x, half[1].x, - y, y + height, - alpha); - half++; - } while (--num_spans > 1); - - if (half[0].x != spans->xmax) { - spans->span (spans, - half[0].x, spans->xmax, - y, y + height, - 0); - } - - return CAIRO_STATUS_SUCCESS; -} - -static cairo_status_t -i915_spans_init (i915_spans_t *spans, - i915_surface_t *dst, - cairo_operator_t op, - const cairo_pattern_t *pattern, - cairo_antialias_t antialias, - cairo_clip_t *clip, - double opacity, - const cairo_composite_rectangles_t *extents) -{ - cairo_status_t status; - - spans->device = (i915_device_t *) dst->intel.drm.base.device; - - spans->is_bounded = extents->is_bounded; - if (extents->is_bounded) { - if (antialias == CAIRO_ANTIALIAS_NONE) - spans->renderer.render_rows = i915_bounded_spans_mono; - else - spans->renderer.render_rows = i915_bounded_spans; - - spans->extents = &extents->bounded; - } else { - if (antialias == CAIRO_ANTIALIAS_NONE) - spans->renderer.render_rows = i915_unbounded_spans_mono; - else - spans->renderer.render_rows = i915_unbounded_spans; - - spans->extents = &extents->unbounded; - } - spans->xmin = spans->extents->x; - spans->xmax = spans->extents->x + spans->extents->width; - - spans->clip_region = NULL; - spans->need_clip_surface = FALSE; - if (clip != NULL) { - cairo_region_t *clip_region = NULL; - - status = _cairo_clip_get_region (clip, &clip_region); - assert (status == CAIRO_STATUS_SUCCESS || status == CAIRO_INT_STATUS_UNSUPPORTED); - - if (clip_region != NULL && cairo_region_num_rectangles (clip_region) == 1) - clip_region = NULL; - - spans->clip_region = clip_region; - spans->need_clip_surface = status == CAIRO_INT_STATUS_UNSUPPORTED; - } - - spans->head.next = NULL; - spans->head.bo = NULL; - spans->head.count = 0; - spans->tail = &spans->head; - - if (spans->clip_region == NULL) { - spans->get_rectangle = i915_emit_rectangle; - } else { - assert (! extents->is_bounded); - spans->get_rectangle = i915_accumulate_rectangle; - spans->head.bo = intel_bo_create (&spans->device->intel, - I915_VBO_SIZE, I915_VBO_SIZE, - FALSE, I915_TILING_NONE, 0); - if (unlikely (spans->head.bo == NULL)) - return _cairo_error (CAIRO_STATUS_NO_MEMORY); - - spans->vbo_base = intel_bo_map (&spans->device->intel, spans->head.bo); - } - spans->vbo_offset = 0; - - i915_shader_init (&spans->shader, dst, op, opacity); - if (spans->need_clip_surface) - i915_shader_set_clip (&spans->shader, clip); - - status = i915_shader_acquire_pattern (&spans->shader, &spans->shader.source, - pattern, &extents->bounded); - if (unlikely (status)) - return status; - - return CAIRO_STATUS_SUCCESS; -} - -static void -i915_spans_fini (i915_spans_t *spans) -{ - i915_shader_fini (&spans->shader); - - if (spans->head.bo != NULL) { - struct vbo *vbo, *next; - - intel_bo_destroy (&spans->device->intel, spans->head.bo); - for (vbo = spans->head.next; vbo != NULL; vbo = next) { - next = vbo->next; - intel_bo_destroy (&spans->device->intel, vbo->bo); - free (vbo); - } - } -} - -cairo_status_t -i915_clip_and_composite_spans (i915_surface_t *dst, - cairo_operator_t op, - const cairo_pattern_t *pattern, - cairo_antialias_t antialias, - i915_spans_func_t draw_func, - void *draw_closure, - const cairo_composite_rectangles_t*extents, - cairo_clip_t *clip, - double opacity) -{ - i915_spans_t spans; - i915_device_t *device; - cairo_status_t status; - struct vbo *vbo; - - if (i915_surface_needs_tiling (dst)) { - ASSERT_NOT_REACHED; - return CAIRO_INT_STATUS_UNSUPPORTED; - } - - if (op == CAIRO_OPERATOR_CLEAR) { - pattern = &_cairo_pattern_white.base; - op = CAIRO_OPERATOR_DEST_OUT; - } - - status = i915_spans_init (&spans, dst, op, pattern, antialias, clip, opacity, extents); - if (unlikely (status)) - return status; - - spans.shader.mask.base.texfmt = TEXCOORDFMT_1D; - spans.shader.mask.base.content = CAIRO_CONTENT_ALPHA; - spans.shader.mask.type.fragment = FS_SPANS; - - status = cairo_device_acquire (dst->intel.drm.base.device); - if (unlikely (status)) - goto CLEANUP_SPANS; - - if (dst->deferred_clear) { - status = i915_surface_clear (dst); - if (unlikely (status)) - goto CLEANUP_SPANS; - } - - device = i915_device (dst); - status = i915_shader_commit (&spans.shader, device); - if (unlikely (status)) - goto CLEANUP_DEVICE; - - if (! spans.shader.need_combine && ! spans.need_clip_surface) { - switch (spans.shader.source.type.vertex) { - case VS_ZERO: - spans.span = i915_span_zero; - if (extents->is_bounded) { - if (antialias == CAIRO_ANTIALIAS_NONE) - spans.renderer.render_rows = i915_zero_spans_mono; - else - spans.renderer.render_rows = i915_zero_spans; - } - break; - case VS_CONSTANT: - spans.span = i915_span_constant; - break; - case VS_LINEAR: - spans.span = i915_span_linear; - break; - case VS_TEXTURE: - spans.span = i915_span_texture; - break; - case VS_TEXTURE_16: - spans.span = i915_span_texture16; - break; - default: - spans.span = i915_span_generic; - break; - } - } else { - spans.span = i915_span_generic; - } - - status = draw_func (draw_closure, &spans.renderer, spans.extents); - if (spans.clip_region != NULL && status == CAIRO_STATUS_SUCCESS) { - i915_vbo_finish (device); - - OUT_DWORD (_3DSTATE_SCISSOR_ENABLE_CMD | ENABLE_SCISSOR_RECT); - for (vbo = &spans.head; vbo != NULL; vbo = vbo->next) { - int i, num_rectangles; - - /* XXX require_space & batch_flush */ - - OUT_DWORD (_3DSTATE_LOAD_STATE_IMMEDIATE_1 | I1_LOAD_S (0) | I1_LOAD_S (1) | 1); - i915_batch_emit_reloc (device, vbo->bo, 0, - I915_GEM_DOMAIN_VERTEX, 0, - FALSE); - OUT_DWORD ((device->floats_per_vertex << S1_VERTEX_WIDTH_SHIFT) | - (device->floats_per_vertex << S1_VERTEX_PITCH_SHIFT) | - vbo->count); - - num_rectangles = cairo_region_num_rectangles (spans.clip_region); - for (i = 0; i < num_rectangles; i++) { - cairo_rectangle_int_t rect; - - cairo_region_get_rectangle (spans.clip_region, i, &rect); - - OUT_DWORD (_3DSTATE_SCISSOR_RECT_0_CMD); - OUT_DWORD (SCISSOR_RECT_0_XMIN (rect.x) | - SCISSOR_RECT_0_YMIN (rect.y)); - OUT_DWORD (SCISSOR_RECT_0_XMAX (rect.x + rect.width) | - SCISSOR_RECT_0_YMAX (rect.y + rect.height)); - - OUT_DWORD (PRIM3D_RECTLIST | PRIM3D_INDIRECT_SEQUENTIAL | vbo->count); - OUT_DWORD (0); - } - } - OUT_DWORD (_3DSTATE_SCISSOR_ENABLE_CMD | DISABLE_SCISSOR_RECT); - } - -CLEANUP_DEVICE: - cairo_device_release (dst->intel.drm.base.device); -CLEANUP_SPANS: - i915_spans_fini (&spans); - - return status; -} diff --git a/gfx/cairo/cairo/src/drm/cairo-drm-i915-surface.c b/gfx/cairo/cairo/src/drm/cairo-drm-i915-surface.c deleted file mode 100644 index 8fc5f7a9dd..0000000000 --- a/gfx/cairo/cairo/src/drm/cairo-drm-i915-surface.c +++ /dev/null @@ -1,2942 +0,0 @@ -/* Cairo - a vector graphics library with display and print output - * - * Copyright © 2009 Chris Wilson - * - * 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., 51 Franklin Street, Suite 500, Boston, MA 02110-1335, 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. - * - * ************************************************************************** - * This work was initially based upon xf86-video-intel/src/i915_render.c: - * Copyright © 2006 Intel Corporation - * - * Permission is hereby granted, free of charge, to any person obtaining a - * copy of this software and associated documentation files (the "Software"), - * to deal in the Software without restriction, including without limitation - * the rights to use, copy, modify, merge, publish, distribute, sublicense, - * and/or sell copies of the Software, and to permit persons to whom the - * Software is furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice (including the next - * paragraph) shall be included in all copies or substantial portions of the - * Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL - * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - * - * Authors: - * Wang Zhenyu <zhenyu.z.wang@intel.com> - * Eric Anholt <eric@anholt.net> - * - * ************************************************************************** - * and also upon libdrm/intel/intel_bufmgr_gem.c: - * Copyright © 2007 Red Hat Inc. - * Copyright © 2007 Intel Corporation - * Copyright 2006 Tungsten Graphics, Inc., Bismarck, ND., USA - * All Rights Reserved. - * - * Permission is hereby granted, free of charge, to any person obtaining a - * copy of this software and associated documentation files (the - * "Software"), to deal in the Software without restriction, including - * without limitation the rights to use, copy, modify, merge, publish, - * distribute, sub license, and/or sell copies of the Software, and to - * permit persons to whom the Software is furnished to do so, subject to - * the following conditions: - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL - * THE COPYRIGHT HOLDERS, AUTHORS AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, - * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR - * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE - * USE OR OTHER DEALINGS IN THE SOFTWARE. - * - * The above copyright notice and this permission notice (including the - * next paragraph) shall be included in all copies or substantial portions - * of the Software. - * - * Authors: Thomas Hellström <thomas-at-tungstengraphics-dot-com> - * Keith Whitwell <keithw-at-tungstengraphics-dot-com> - * Eric Anholt <eric@anholt.net> - * Dave Airlie <airlied@linux.ie> - */ - -/* XXX - * - * - Per thread context? Would it actually avoid many locks? - * - */ - -#include "cairoint.h" - -#include "cairo-drm-private.h" -#include "cairo-drm-intel-private.h" -#include "cairo-drm-intel-command-private.h" -#include "cairo-drm-intel-ioctl-private.h" -#include "cairo-drm-i915-private.h" - -#include "cairo-boxes-private.h" -#include "cairo-cache-private.h" -#include "cairo-composite-rectangles-private.h" -#include "cairo-default-context-private.h" -#include "cairo-error-private.h" -#include "cairo-freelist-private.h" -#include "cairo-list-private.h" -#include "cairo-path-fixed-private.h" -#include "cairo-region-private.h" -#include "cairo-surface-offset-private.h" -#include "cairo-image-surface-private.h" - -#include <sys/ioctl.h> -#include <sys/mman.h> -#include <errno.h> - -static const uint32_t i915_batch_setup[] = { - /* Disable line anti-aliasing */ - _3DSTATE_AA_CMD, - - /* Disable independent alpha blend */ - _3DSTATE_INDEPENDENT_ALPHA_BLEND_CMD | - IAB_MODIFY_ENABLE | - IAB_MODIFY_FUNC | (BLENDFUNC_ADD << IAB_FUNC_SHIFT) | - IAB_MODIFY_SRC_FACTOR | (BLENDFACT_ONE << IAB_SRC_FACTOR_SHIFT) | - IAB_MODIFY_DST_FACTOR | (BLENDFACT_ZERO << IAB_DST_FACTOR_SHIFT), - - /* Disable texture crossbar */ - _3DSTATE_COORD_SET_BINDINGS | - CSB_TCB (0, 0) | - CSB_TCB (1, 1) | - CSB_TCB (2, 2) | - CSB_TCB (3, 3) | - CSB_TCB (4, 4) | - CSB_TCB (5, 5) | - CSB_TCB (6, 6) | - CSB_TCB (7, 7), - - _3DSTATE_MODES_4_CMD | ENABLE_LOGIC_OP_FUNC | LOGIC_OP_FUNC (LOGICOP_COPY), - - _3DSTATE_LOAD_STATE_IMMEDIATE_1 | - I1_LOAD_S (2) | - I1_LOAD_S (3) | - I1_LOAD_S (4) | - I1_LOAD_S (5) | - I1_LOAD_S (6) | - 4, - S2_TEXCOORD_NONE, - 0, /* Disable texture coordinate wrap-shortest */ - (1 << S4_POINT_WIDTH_SHIFT) | - S4_LINE_WIDTH_ONE | - S4_FLATSHADE_ALPHA | - S4_FLATSHADE_FOG | - S4_FLATSHADE_SPECULAR | - S4_FLATSHADE_COLOR | - S4_CULLMODE_NONE | - S4_VFMT_XY, - 0, /* Disable stencil buffer */ - S6_COLOR_WRITE_ENABLE, - - _3DSTATE_SCISSOR_ENABLE_CMD | DISABLE_SCISSOR_RECT, - - /* disable indirect state */ - _3DSTATE_LOAD_INDIRECT, - 0, -}; - -static const cairo_surface_backend_t i915_surface_backend; - -static cairo_surface_t * -i915_surface_create_from_cacheable_image (cairo_drm_device_t *base_dev, - cairo_surface_t *source); - -static cairo_status_t -i915_bo_exec (i915_device_t *device, intel_bo_t *bo, uint32_t offset) -{ - struct drm_i915_gem_execbuffer2 execbuf; - int ret, cnt, i; - - /* Add the batch buffer to the validation list. */ - cnt = device->batch.exec_count; - if (cnt > 0 && bo->base.handle == device->batch.exec[cnt-1].handle) - i = cnt - 1; - else - i = device->batch.exec_count++; - device->batch.exec[i].handle = bo->base.handle; - device->batch.exec[i].relocation_count = device->batch.reloc_count; - device->batch.exec[i].relocs_ptr = (uintptr_t) device->batch.reloc; - device->batch.exec[i].alignment = 0; - device->batch.exec[i].offset = 0; - device->batch.exec[i].flags = 0; - device->batch.exec[i].rsvd1 = 0; - device->batch.exec[i].rsvd2 = 0; - - execbuf.buffers_ptr = (uintptr_t) device->batch.exec; - execbuf.buffer_count = device->batch.exec_count; - execbuf.batch_start_offset = offset; - execbuf.batch_len = (device->batch.used << 2) + sizeof (device->batch_header); - execbuf.DR1 = 0; - execbuf.DR4 = 0; - execbuf.num_cliprects = 0; - execbuf.cliprects_ptr = 0; - execbuf.flags = 0; - execbuf.rsvd1 = 0; - execbuf.rsvd2 = 0; - - do { - ret = ioctl (device->intel.base.fd, DRM_IOCTL_I915_GEM_EXECBUFFER2, &execbuf); - } while (ret != 0 && errno == EINTR); - - if (device->debug & I915_DEBUG_SYNC && ret == 0) - ret = ! intel_bo_wait (&device->intel, bo); - - if (0 && ret) { - int n, m; - - fprintf (stderr, "Batch submission failed: %d\n", errno); - fprintf (stderr, " relocation entries: %d/%d\n", - device->batch.reloc_count, I915_MAX_RELOCS); - fprintf (stderr, " gtt size: (%zd/%zd), (%zd/%zd)\n", - device->batch.est_gtt_size, device->batch.gtt_avail_size, - device->batch.total_gtt_size, device->intel.gtt_avail_size); - - fprintf (stderr, " buffers:\n"); - for (n = 0; n < device->batch.exec_count; n++) { - fprintf (stderr, " exec[%d] = %d, %d/%d bytes, gtt = %qx\n", - n, - device->batch.exec[n].handle, - n == device->batch.exec_count - 1 ? bo->base.size : device->batch.target_bo[n]->base.size, - n == device->batch.exec_count - 1 ? bo->full_size : device->batch.target_bo[n]->full_size, - device->batch.exec[n].offset); - } - for (n = 0; n < device->batch.reloc_count; n++) { - for (m = 0; m < device->batch.exec_count; m++) - if (device->batch.exec[m].handle == device->batch.reloc[n].target_handle) - break; - - fprintf (stderr, " reloc[%d] = %d @ %qx -> %qx + %qx\n", n, - device->batch.reloc[n].target_handle, - device->batch.reloc[n].offset, - (unsigned long long) device->batch.exec[m].offset, - (unsigned long long) device->batch.reloc[n].delta); - - device->batch_base[(device->batch.reloc[n].offset - sizeof (device->batch_header)) / 4] = - device->batch.exec[m].offset + device->batch.reloc[n].delta; - } - - intel_dump_batchbuffer (device->batch_header, - execbuf.batch_len, - device->intel.base.chip_id); - } - assert (ret == 0); - - VG (VALGRIND_MAKE_MEM_DEFINED (device->batch.exec, sizeof (device->batch.exec[0]) * i)); - - bo->offset = device->batch.exec[i].offset; - bo->busy = TRUE; - if (bo->virtual) - intel_bo_unmap (bo); - bo->cpu = FALSE; - - while (cnt--) { - intel_bo_t *bo = device->batch.target_bo[cnt]; - - bo->offset = device->batch.exec[cnt].offset; - bo->exec = NULL; - bo->busy = TRUE; - bo->batch_read_domains = 0; - bo->batch_write_domain = 0; - cairo_list_del (&bo->cache_list); - - if (bo->virtual) - intel_bo_unmap (bo); - bo->cpu = FALSE; - - intel_bo_destroy (&device->intel, bo); - } - assert (cairo_list_is_empty (&device->intel.bo_in_flight)); - - device->batch.exec_count = 0; - device->batch.reloc_count = 0; - device->batch.fences = 0; - - device->batch.est_gtt_size = I915_BATCH_SIZE; - device->batch.total_gtt_size = I915_BATCH_SIZE; - - return ret == 0 ? CAIRO_STATUS_SUCCESS : _cairo_error (CAIRO_STATUS_NO_MEMORY); -} - -void -i915_batch_add_reloc (i915_device_t *device, - uint32_t pos, - intel_bo_t *bo, - uint32_t offset, - uint32_t read_domains, - uint32_t write_domain, - cairo_bool_t needs_fence) -{ - int index; - - assert (offset < bo->base.size); - - if (bo->exec == NULL) { - device->batch.total_gtt_size += bo->base.size; - - if (! bo->busy) - device->batch.est_gtt_size += bo->base.size; - - assert (device->batch.exec_count < ARRAY_LENGTH (device->batch.exec)); - - index = device->batch.exec_count++; - device->batch.exec[index].handle = bo->base.handle; - device->batch.exec[index].relocation_count = 0; - device->batch.exec[index].relocs_ptr = 0; - device->batch.exec[index].alignment = 0; - device->batch.exec[index].offset = 0; - device->batch.exec[index].flags = 0; - device->batch.exec[index].rsvd1 = 0; - device->batch.exec[index].rsvd2 = 0; - - device->batch.target_bo[index] = intel_bo_reference (bo); - - bo->exec = &device->batch.exec[index]; - } - - if (bo->tiling != I915_TILING_NONE) { - uint32_t alignment; - -#if 0 - /* We presume that we will want to use a fence with X tiled objects... */ - if (needs_fence || bo->tiling == I915_TILING_X) - alignment = bo->full_size; - else - alignment = 2*((bo->stride + 4095) & -4096); -#else - alignment = bo->full_size; -#endif - if (bo->exec->alignment < alignment) - bo->exec->alignment = alignment; - - if (needs_fence && (bo->exec->flags & EXEC_OBJECT_NEEDS_FENCE) == 0) { - bo->exec->flags |= EXEC_OBJECT_NEEDS_FENCE; - device->batch.fences++; - - intel_bo_set_tiling (&device->intel, bo); - } - } - - assert (device->batch.reloc_count < ARRAY_LENGTH (device->batch.reloc)); - - index = device->batch.reloc_count++; - device->batch.reloc[index].offset = (pos << 2) + sizeof (device->batch_header); - device->batch.reloc[index].delta = offset; - device->batch.reloc[index].target_handle = bo->base.handle; - device->batch.reloc[index].read_domains = read_domains; - device->batch.reloc[index].write_domain = write_domain; - device->batch.reloc[index].presumed_offset = bo->offset; - - assert (write_domain == 0 || bo->batch_write_domain == 0 || bo->batch_write_domain == write_domain); - bo->batch_read_domains |= read_domains; - bo->batch_write_domain |= write_domain; -} - -void -i915_vbo_finish (i915_device_t *device) -{ - intel_bo_t *vbo; - - assert (CAIRO_MUTEX_IS_LOCKED (device->intel.base.base.mutex)); - assert (device->vbo_used); - - if (device->vertex_count) { - if (device->vbo == 0) { - OUT_DWORD (_3DSTATE_LOAD_STATE_IMMEDIATE_1 | - I1_LOAD_S (0) | - I1_LOAD_S (1) | - 1); - device->vbo = device->batch.used++; - device->vbo_max_index = device->batch.used; - OUT_DWORD ((device->floats_per_vertex << S1_VERTEX_WIDTH_SHIFT) | - (device->floats_per_vertex << S1_VERTEX_PITCH_SHIFT)); - } - - OUT_DWORD (PRIM3D_RECTLIST | - PRIM3D_INDIRECT_SEQUENTIAL | - device->vertex_count); - OUT_DWORD (device->vertex_index); - } - - if (device->last_vbo != NULL) { - intel_bo_in_flight_add (&device->intel, device->last_vbo); - intel_bo_destroy (&device->intel, device->last_vbo); - } - - device->batch_base[device->vbo_max_index] |= device->vertex_index + device->vertex_count; - - /* will include a few bytes of inter-array padding */ - vbo = intel_bo_create (&device->intel, - device->vbo_used, device->vbo_used, - FALSE, I915_TILING_NONE, 0); - i915_batch_fill_reloc (device, device->vbo, vbo, 0, - I915_GEM_DOMAIN_VERTEX, 0); - intel_bo_write (&device->intel, vbo, 0, device->vbo_used, device->vbo_base); - device->last_vbo = vbo; - device->last_vbo_offset = (device->vbo_used+7)&-8; - device->last_vbo_space = vbo->base.size - device->last_vbo_offset; - - device->vbo = 0; - - device->vbo_used = device->vbo_offset = 0; - device->vertex_index = device->vertex_count = 0; - - if (! i915_check_aperture_size (device, 1, I915_VBO_SIZE, I915_VBO_SIZE)) { - cairo_status_t status; - - status = i915_batch_flush (device); - if (unlikely (status)) - longjmp (device->shader->unwind, status); - - status = i915_shader_commit (device->shader, device); - if (unlikely (status)) - longjmp (device->shader->unwind, status); - } -} - -/* XXX improve state tracker/difference and flush state on vertex emission */ -static void -i915_device_reset (i915_device_t *device) -{ - if (device->current_source != NULL) - *device->current_source = 0; - if (device->current_mask != NULL) - *device->current_mask = 0; - if (device->current_clip != NULL) - *device->current_clip = 0; - - device->current_target = NULL; - device->current_size = 0; - device->current_source = NULL; - device->current_mask = NULL; - device->current_clip = NULL; - device->current_texcoords = ~0; - device->current_blend = 0; - device->current_n_constants = 0; - device->current_n_samplers = 0; - device->current_n_maps = 0; - device->current_colorbuf = 0; - device->current_diffuse = 0; - device->current_program = ~0; - device->clear_alpha = ~0; - - device->last_source_fragment = ~0; -} - -static void -i915_batch_cleanup (i915_device_t *device) -{ - int i; - - for (i = 0; i < device->batch.exec_count; i++) { - intel_bo_t *bo = device->batch.target_bo[i]; - - bo->exec = NULL; - bo->batch_read_domains = 0; - bo->batch_write_domain = 0; - cairo_list_del (&bo->cache_list); - - intel_bo_destroy (&device->intel, bo); - } - - device->batch.exec_count = 0; - device->batch.reloc_count = 0; -} - -static void -i915_batch_vbo_finish (i915_device_t *device) -{ - assert (CAIRO_MUTEX_IS_LOCKED (device->intel.base.base.mutex)); - - if (device->vbo || i915_batch_space (device) < (int32_t) device->vbo_used) { - intel_bo_t *vbo; - - if (device->vertex_count) { - if (device->vbo == 0) { - OUT_DWORD (_3DSTATE_LOAD_STATE_IMMEDIATE_1 | - I1_LOAD_S (0) | - I1_LOAD_S (1) | - 1); - device->vbo = device->batch.used++; - device->vbo_max_index = device->batch.used; - OUT_DWORD ((device->floats_per_vertex << S1_VERTEX_WIDTH_SHIFT) | - (device->floats_per_vertex << S1_VERTEX_PITCH_SHIFT)); - } - - OUT_DWORD (PRIM3D_RECTLIST | - PRIM3D_INDIRECT_SEQUENTIAL | - device->vertex_count); - OUT_DWORD (device->vertex_index); - } - - if (device->last_vbo != NULL) - intel_bo_destroy (&device->intel, device->last_vbo); - - device->batch_base[device->vbo_max_index] |= device->vertex_index + device->vertex_count; - - /* will include a few bytes of inter-array padding */ - vbo = intel_bo_create (&device->intel, - device->vbo_used, device->vbo_used, - FALSE, I915_TILING_NONE, 0); - i915_batch_fill_reloc (device, device->vbo, - vbo, 0, - I915_GEM_DOMAIN_VERTEX, 0); - intel_bo_write (&device->intel, vbo, 0, device->vbo_used, device->vbo_base); - device->last_vbo = vbo; - device->last_vbo_offset = (device->vbo_used+7)&-8; - device->last_vbo_space = vbo->base.size - device->last_vbo_offset; - - device->vbo = 0; - } - else - { - /* Only a single rectlist in this batch, and no active vertex buffer. */ - OUT_DWORD (PRIM3D_RECTLIST | (device->vbo_used / 4 - 1)); - - memcpy (BATCH_PTR (device), device->vbo_base, device->vbo_used); - device->batch.used += device->vbo_used >> 2; - } - - device->vbo_used = device->vbo_offset = 0; - device->vertex_index = device->vertex_count = 0; -} - -cairo_status_t -i915_batch_flush (i915_device_t *device) -{ - intel_bo_t *batch; - cairo_status_t status; - uint32_t length, offset; - int n; - - assert (CAIRO_MUTEX_IS_LOCKED (device->intel.base.base.mutex)); - - if (device->vbo_used) - i915_batch_vbo_finish (device); - - if (device->batch.used == 0) - return CAIRO_STATUS_SUCCESS; - - i915_batch_emit_dword (device, MI_BATCH_BUFFER_END); - if ((device->batch.used & 1) != ((sizeof (device->batch_header)>>2) & 1)) - i915_batch_emit_dword (device, MI_NOOP); - - length = (device->batch.used << 2) + sizeof (device->batch_header); - - /* NB: it is faster to copy the data then map/unmap the batch, - * presumably because we frequently only use a small part of the buffer. - */ - batch = NULL; - if (device->last_vbo) { - if (length <= device->last_vbo_space) { - batch = device->last_vbo; - offset = device->last_vbo_offset; - - /* fixup the relocations */ - for (n = 0; n < device->batch.reloc_count; n++) - device->batch.reloc[n].offset += offset; - } else - intel_bo_destroy (&device->intel, device->last_vbo); - device->last_vbo = NULL; - } - if (batch == NULL) { - batch = intel_bo_create (&device->intel, - length, length, - FALSE, I915_TILING_NONE, 0); - if (unlikely (batch == NULL)) { - status = _cairo_error (CAIRO_STATUS_NO_MEMORY); - i915_batch_cleanup (device); - goto BAIL; - } - - offset = 0; - } - intel_bo_write (&device->intel, batch, offset, length, device->batch_header); - status = i915_bo_exec (device, batch, offset); - intel_bo_destroy (&device->intel, batch); - -BAIL: - device->batch.used = 0; - - intel_glyph_cache_unpin (&device->intel); - intel_snapshot_cache_thaw (&device->intel); - - i915_device_reset (device); - - return status; -} - -#if 0 -static float * -i915_add_rectangles (i915_device_t *device, int num_rects, int *count) -{ - float *vertices; - uint32_t size; - int cnt; - - assert (device->floats_per_vertex); - - size = device->rectangle_size; - if (unlikely (device->vbo_offset + size > I915_VBO_SIZE)) - i915_vbo_finish (device); - - vertices = (float *) (device->vbo_base + device->vbo_offset); - cnt = (I915_VBO_SIZE - device->vbo_offset) / size; - if (cnt > num_rects) - cnt = num_rects; - device->vbo_used = device->vbo_offset += size * cnt; - device->vertex_count += 3 * cnt; - *count = cnt; - return vertices; -} -#endif - -static cairo_surface_t * -i915_surface_create_similar (void *abstract_other, - cairo_content_t content, - int width, int height) -{ - i915_surface_t *other; - cairo_format_t format; - uint32_t tiling = I915_TILING_DEFAULT; - - other = abstract_other; - if (content == other->intel.drm.base.content) - format = other->intel.drm.format; - else - format = _cairo_format_from_content (content); - - if (width * _cairo_format_bits_per_pixel (format) > 8 * 32*1024 || height > 64*1024) - return NULL; - - /* we presume that a similar surface will be used for blitting */ - if (i915_surface_needs_tiling (other)) - tiling = I915_TILING_X; - - return i915_surface_create_internal ((cairo_drm_device_t *) other->intel.drm.base.device, - format, - width, height, - tiling, TRUE); -} - -static cairo_status_t -i915_surface_finish (void *abstract_surface) -{ - i915_surface_t *surface = abstract_surface; - i915_device_t *device = i915_device (surface); - - if (surface->stencil != NULL) { - intel_bo_in_flight_add (&device->intel, surface->stencil); - intel_bo_destroy (&device->intel, surface->stencil); - } - - if (surface->is_current_texture) { - if (surface->is_current_texture & CURRENT_SOURCE) - device->current_source = NULL; - if (surface->is_current_texture & CURRENT_MASK) - device->current_mask = NULL; - if (surface->is_current_texture & CURRENT_CLIP) - device->current_clip = NULL; - device->current_n_samplers = 0; - } - - if (surface == device->current_target) - device->current_target = NULL; - - if (surface->cache != NULL) { - i915_image_private_t *node = surface->cache; - intel_buffer_cache_t *cache = node->container; - - if (--cache->ref_count == 0) { - intel_bo_in_flight_add (&device->intel, cache->buffer.bo); - intel_bo_destroy (&device->intel, cache->buffer.bo); - _cairo_rtree_fini (&cache->rtree); - cairo_list_del (&cache->link); - free (cache); - } else { - node->node.state = CAIRO_RTREE_NODE_AVAILABLE; - cairo_list_move (&node->node.link, &cache->rtree.available); - _cairo_rtree_node_collapse (&cache->rtree, node->node.parent); - } - } - - return intel_surface_finish (&surface->intel); -} - -static cairo_status_t -i915_surface_batch_flush (i915_surface_t *surface) -{ - cairo_status_t status; - intel_bo_t *bo; - - assert (surface->intel.drm.fallback == NULL); - - bo = to_intel_bo (surface->intel.drm.bo); - if (bo == NULL || bo->batch_write_domain == 0) - return CAIRO_STATUS_SUCCESS; - - status = cairo_device_acquire (surface->intel.drm.base.device); - if (unlikely (status)) - return status; - - status = i915_batch_flush (i915_device (surface)); - cairo_device_release (surface->intel.drm.base.device); - - return status; -} - -static cairo_status_t -i915_surface_flush (void *abstract_surface, - unsigned flags) -{ - i915_surface_t *surface = abstract_surface; - cairo_status_t status; - - if (flags) - return CAIRO_STATUS_SUCCESS; - - if (surface->intel.drm.fallback == NULL) { - if (surface->intel.drm.base.finished) { - /* Forgo flushing on finish as the user cannot access the surface directly. */ - return CAIRO_STATUS_SUCCESS; - } - - if (surface->deferred_clear) { - status = i915_surface_clear (surface); - if (unlikely (status)) - return status; - } - - return i915_surface_batch_flush (surface); - } - - return intel_surface_flush (abstract_surface, flags); -} - -/* rasterisation */ - -static cairo_status_t -_composite_boxes_spans (void *closure, - cairo_span_renderer_t *renderer, - const cairo_rectangle_int_t *extents) -{ - cairo_boxes_t *boxes = closure; - cairo_rectangular_scan_converter_t converter; - struct _cairo_boxes_chunk *chunk; - cairo_status_t status; - int i; - - _cairo_rectangular_scan_converter_init (&converter, extents); - for (chunk = &boxes->chunks; chunk != NULL; chunk = chunk->next) { - cairo_box_t *box = chunk->base; - for (i = 0; i < chunk->count; i++) { - status = _cairo_rectangular_scan_converter_add_box (&converter, &box[i], 1); - if (unlikely (status)) - goto CLEANUP; - } - } - - status = converter.base.generate (&converter.base, renderer); - -CLEANUP: - converter.base.destroy (&converter.base); - return status; -} - -cairo_status_t -i915_fixup_unbounded (i915_surface_t *dst, - const cairo_composite_rectangles_t *extents, - cairo_clip_t *clip) -{ - i915_shader_t shader; - i915_device_t *device; - cairo_status_t status; - - if (clip != NULL) { - cairo_region_t *clip_region = NULL; - - status = _cairo_clip_get_region (clip, &clip_region); - assert (status == CAIRO_STATUS_SUCCESS || status == CAIRO_INT_STATUS_UNSUPPORTED); - assert (clip_region == NULL); - - if (status != CAIRO_INT_STATUS_UNSUPPORTED) - clip = NULL; - } else { - if (extents->bounded.width == extents->unbounded.width && - extents->bounded.height == extents->unbounded.height) - { - return CAIRO_STATUS_SUCCESS; - } - } - - if (clip != NULL) { - i915_shader_init (&shader, dst, CAIRO_OPERATOR_DEST_OVER, 1.); - i915_shader_set_clip (&shader, clip); - status = i915_shader_acquire_pattern (&shader, - &shader.source, - &_cairo_pattern_white.base, - &extents->unbounded); - assert (status == CAIRO_STATUS_SUCCESS); - } else { - i915_shader_init (&shader, dst, CAIRO_OPERATOR_CLEAR, 1.); - status = i915_shader_acquire_pattern (&shader, - &shader.source, - &_cairo_pattern_clear.base, - &extents->unbounded); - assert (status == CAIRO_STATUS_SUCCESS); - } - - device = i915_device (dst); - status = cairo_device_acquire (&device->intel.base.base); - if (unlikely (status)) - return status; - - status = i915_shader_commit (&shader, device); - if (unlikely (status)) - goto BAIL; - - if (extents->bounded.width == 0 || extents->bounded.height == 0) { - shader.add_rectangle (&shader, - extents->unbounded.x, - extents->unbounded.y, - extents->unbounded.width, - extents->unbounded.height); - } else { - /* top */ - if (extents->bounded.y != extents->unbounded.y) { - shader.add_rectangle (&shader, - extents->unbounded.x, - extents->unbounded.y, - extents->unbounded.width, - extents->bounded.y - extents->unbounded.y); - } - - /* left */ - if (extents->bounded.x != extents->unbounded.x) { - shader.add_rectangle (&shader, - extents->unbounded.x, - extents->bounded.y, - extents->bounded.x - extents->unbounded.x, - extents->bounded.height); - } - - /* right */ - if (extents->bounded.x + extents->bounded.width != extents->unbounded.x + extents->unbounded.width) { - shader.add_rectangle (&shader, - extents->bounded.x + extents->bounded.width, - extents->bounded.y, - extents->unbounded.x + extents->unbounded.width - (extents->bounded.x + extents->bounded.width), - extents->bounded.height); - } - - /* bottom */ - if (extents->bounded.y + extents->bounded.height != extents->unbounded.y + extents->unbounded.height) { - shader.add_rectangle (&shader, - extents->unbounded.x, - extents->bounded.y + extents->bounded.height, - extents->unbounded.width, - extents->unbounded.y + extents->unbounded.height - (extents->bounded.y + extents->bounded.height)); - } - } - - i915_shader_fini (&shader); - BAIL: - cairo_device_release (&device->intel.base.base); - return status; -} - -static cairo_status_t -i915_fixup_unbounded_boxes (i915_surface_t *dst, - const cairo_composite_rectangles_t *extents, - cairo_clip_t *clip, - cairo_boxes_t *boxes) -{ - cairo_boxes_t clear; - cairo_box_t box; - cairo_region_t *clip_region = NULL; - cairo_status_t status; - struct _cairo_boxes_chunk *chunk; - int i; - - if (boxes->num_boxes <= 1) - return i915_fixup_unbounded (dst, extents, clip); - - _cairo_boxes_init (&clear); - - box.p1.x = _cairo_fixed_from_int (extents->unbounded.x + extents->unbounded.width); - box.p1.y = _cairo_fixed_from_int (extents->unbounded.y); - box.p2.x = _cairo_fixed_from_int (extents->unbounded.x); - box.p2.y = _cairo_fixed_from_int (extents->unbounded.y + extents->unbounded.height); - - if (clip != NULL) { - status = _cairo_clip_get_region (clip, &clip_region); - assert (status == CAIRO_STATUS_SUCCESS || status == CAIRO_INT_STATUS_UNSUPPORTED); - if (status != CAIRO_INT_STATUS_UNSUPPORTED) - clip = NULL; - } - - if (clip_region == NULL) { - cairo_boxes_t tmp; - - _cairo_boxes_init (&tmp); - - status = _cairo_boxes_add (&tmp, &box); - assert (status == CAIRO_STATUS_SUCCESS); - - tmp.chunks.next = &boxes->chunks; - tmp.num_boxes += boxes->num_boxes; - - status = _cairo_bentley_ottmann_tessellate_boxes (&tmp, - CAIRO_FILL_RULE_WINDING, - &clear); - - tmp.chunks.next = NULL; - } else { - pixman_box32_t *pbox; - - pbox = pixman_region32_rectangles (&clip_region->rgn, &i); - _cairo_boxes_limit (&clear, (cairo_box_t *) pbox, i); - - status = _cairo_boxes_add (&clear, &box); - assert (status == CAIRO_STATUS_SUCCESS); - - for (chunk = &boxes->chunks; chunk != NULL; chunk = chunk->next) { - for (i = 0; i < chunk->count; i++) { - status = _cairo_boxes_add (&clear, &chunk->base[i]); - if (unlikely (status)) { - _cairo_boxes_fini (&clear); - return status; - } - } - } - - status = _cairo_bentley_ottmann_tessellate_boxes (&clear, - CAIRO_FILL_RULE_WINDING, - &clear); - } - - if (likely (status == CAIRO_STATUS_SUCCESS && clear.num_boxes)) { - i915_shader_t shader; - i915_device_t *device; - - if (clip != NULL) { - i915_shader_init (&shader, dst, CAIRO_OPERATOR_DEST_OVER, 1.); - i915_shader_set_clip (&shader, clip); - status = i915_shader_acquire_pattern (&shader, - &shader.source, - &_cairo_pattern_white.base, - &extents->unbounded); - assert (status == CAIRO_STATUS_SUCCESS); - } else { - i915_shader_init (&shader, dst, CAIRO_OPERATOR_CLEAR, 1.); - status = i915_shader_acquire_pattern (&shader, - &shader.source, - &_cairo_pattern_clear.base, - &extents->unbounded); - assert (status == CAIRO_STATUS_SUCCESS); - } - - device = i915_device (dst); - status = cairo_device_acquire (&device->intel.base.base); - if (unlikely (status)) - goto err_shader; - - status = i915_shader_commit (&shader, device); - if (unlikely (status)) - goto err_device; - - for (chunk = &clear.chunks; chunk != NULL; chunk = chunk->next) { - for (i = 0; i < chunk->count; i++) { - int x1 = _cairo_fixed_integer_part (chunk->base[i].p1.x); - int y1 = _cairo_fixed_integer_part (chunk->base[i].p1.y); - int x2 = _cairo_fixed_integer_part (chunk->base[i].p2.x); - int y2 = _cairo_fixed_integer_part (chunk->base[i].p2.y); - - shader.add_rectangle (&shader, x1, y1, x2 - x1, y2 - y1); - } - } -err_device: - cairo_device_release (&device->intel.base.base); -err_shader: - i915_shader_fini (&shader); - } - - _cairo_boxes_fini (&clear); - - return status; -} - -static cairo_bool_t -i915_can_blt (i915_surface_t *dst, - const cairo_pattern_t *pattern) -{ - const cairo_surface_pattern_t *spattern; - i915_surface_t *src; - - spattern = (const cairo_surface_pattern_t *) pattern; - src = (i915_surface_t *) spattern->surface; - - if (src->intel.drm.base.device != dst->intel.drm.base.device) - return FALSE; - - if (! i915_surface_needs_tiling (dst)) - return FALSE; - - if (! _cairo_matrix_is_translation (&pattern->matrix)) - return FALSE; - - if (! (pattern->filter == CAIRO_FILTER_NEAREST || - pattern->filter == CAIRO_FILTER_FAST)) - { - if (! _cairo_fixed_is_integer (_cairo_fixed_from_double (pattern->matrix.x0)) || - ! _cairo_fixed_is_integer (_cairo_fixed_from_double (pattern->matrix.y0))) - { - return FALSE; - } - } - - return _cairo_format_bits_per_pixel (src->intel.drm.format) == - _cairo_format_bits_per_pixel (dst->intel.drm.format); -} - -static cairo_status_t -i915_blt (i915_surface_t *src, - i915_surface_t *dst, - int src_x, int src_y, - int width, int height, - int dst_x, int dst_y, - cairo_bool_t flush) -{ - i915_device_t *device; - intel_bo_t *bo_array[2]; - cairo_status_t status; - int br13, cmd; - - bo_array[0] = to_intel_bo (dst->intel.drm.bo); - bo_array[1] = to_intel_bo (src->intel.drm.bo); - - status = i915_surface_fallback_flush (src); - if (unlikely (status)) - return status; - - device = i915_device (dst); - status = cairo_device_acquire (&device->intel.base.base); - if (unlikely (status)) - return status; - - if (! i915_check_aperture_and_fences (device, bo_array, 2) || - i915_batch_space (device) < 9) - { - status = i915_batch_flush (device); - if (unlikely (status)) - goto CLEANUP; - } - - cmd = XY_SRC_COPY_BLT_CMD; - br13 = (0xCC << 16) | dst->intel.drm.stride; - switch (dst->intel.drm.format) { - default: - case CAIRO_FORMAT_INVALID: - case CAIRO_FORMAT_A1: - ASSERT_NOT_REACHED; - case CAIRO_FORMAT_A8: - break; - case CAIRO_FORMAT_RGB16_565: - br13 |= BR13_565; - break; - case CAIRO_FORMAT_RGB24: - case CAIRO_FORMAT_ARGB32: - br13 |= BR13_8888; - cmd |= XY_BLT_WRITE_ALPHA | XY_BLT_WRITE_RGB; - break; - } - - OUT_DWORD (cmd); - OUT_DWORD (br13); - OUT_DWORD ((dst_y << 16) | dst_x); - OUT_DWORD (((dst_y + height - 1) << 16) | (dst_x + width - 1)); - OUT_RELOC_FENCED (dst, I915_GEM_DOMAIN_RENDER, I915_GEM_DOMAIN_RENDER); - OUT_DWORD ((src_y << 16) | src_x); - OUT_DWORD (src->intel.drm.stride); - OUT_RELOC_FENCED (src, I915_GEM_DOMAIN_RENDER, 0); - /* require explicit RenderCache flush for 2D -> 3D sampler? */ - if (flush) - OUT_DWORD (MI_FLUSH); - -CLEANUP: - cairo_device_release (&device->intel.base.base); - return CAIRO_STATUS_SUCCESS; -} - -cairo_status_t -i915_surface_copy_subimage (i915_device_t *device, - i915_surface_t *src, - const cairo_rectangle_int_t *extents, - cairo_bool_t flush, - i915_surface_t **clone_out) -{ - i915_surface_t *clone; - cairo_status_t status; - - clone = (i915_surface_t *) - i915_surface_create_internal (&device->intel.base, - src->intel.drm.format, - extents->width, - extents->height, - I915_TILING_X, TRUE); - if (unlikely (clone->intel.drm.base.status)) - return clone->intel.drm.base.status; - - status = i915_blt (src, clone, - extents->x, extents->y, - extents->width, extents->height, - 0, 0, - flush); - - if (unlikely (status)) { - cairo_surface_destroy (&clone->intel.drm.base); - return status; - } - - *clone_out = clone; - return CAIRO_STATUS_SUCCESS; -} - -static cairo_status_t -i915_clear_boxes (i915_surface_t *dst, - const cairo_boxes_t *boxes) -{ - i915_device_t *device = i915_device (dst); - const struct _cairo_boxes_chunk *chunk; - cairo_status_t status; - intel_bo_t *bo_array[1] = { to_intel_bo (dst->intel.drm.bo) }; - int cmd, br13, clear = 0, i; - - cmd = XY_COLOR_BLT_CMD; - br13 = (0xCC << 16) | dst->intel.drm.stride; - switch (dst->intel.drm.format) { - default: - case CAIRO_FORMAT_INVALID: - case CAIRO_FORMAT_A1: - ASSERT_NOT_REACHED; - case CAIRO_FORMAT_A8: - break; - case CAIRO_FORMAT_RGB16_565: - br13 |= BR13_565; - break; - case CAIRO_FORMAT_RGB24: - clear = 0xff000000; - case CAIRO_FORMAT_ARGB32: - br13 |= BR13_8888; - cmd |= XY_BLT_WRITE_ALPHA | XY_BLT_WRITE_RGB; - break; - } - - status = cairo_device_acquire (&device->intel.base.base); - if (unlikely (status)) - return status; - - if (! i915_check_aperture_and_fences (device, bo_array, 1) || - i915_batch_space (device) < 6 * boxes->num_boxes) - { - status = i915_batch_flush (device); - if (unlikely (status)) - goto RELEASE; - } - - if (device->vertex_count) - i915_vbo_flush (device); - - for (chunk = &boxes->chunks; chunk != NULL; chunk = chunk->next) { - const cairo_box_t *box = chunk->base; - for (i = 0; i < chunk->count; i++) { - int x1 = _cairo_fixed_integer_round (box[i].p1.x); - int x2 = _cairo_fixed_integer_round (box[i].p2.x); - int y1 = _cairo_fixed_integer_round (box[i].p1.y); - int y2 = _cairo_fixed_integer_round (box[i].p2.y); - - if (x2 <= x1 || y2 <= y1) - continue; - - OUT_DWORD (cmd); - OUT_DWORD (br13); - OUT_DWORD ((y1 << 16) | x1); - OUT_DWORD (((y2 - 1) << 16) | (x2 - 1)); - OUT_RELOC_FENCED (dst, I915_GEM_DOMAIN_RENDER, I915_GEM_DOMAIN_RENDER); - OUT_DWORD (clear); - } - } - -RELEASE: - cairo_device_release (&device->intel.base.base); - return status; -} - -static cairo_status_t -i915_surface_extract_X_from_Y (i915_device_t *device, - i915_surface_t *src, - const cairo_rectangle_int_t *extents, - i915_surface_t **clone_out) -{ - i915_surface_t *clone; - i915_shader_t shader; - cairo_surface_pattern_t pattern; - cairo_rectangle_int_t rect; - cairo_status_t status; - - status = i915_surface_fallback_flush (src); - if (unlikely (status)) - return status; - - clone = (i915_surface_t *) - i915_surface_create_internal (&device->intel.base, - src->intel.drm.format, - extents->width, - extents->height, - I915_TILING_X, TRUE); - if (unlikely (clone->intel.drm.base.status)) - return clone->intel.drm.base.status; - - i915_shader_init (&shader, clone, CAIRO_OPERATOR_SOURCE, 1.); - - _cairo_pattern_init_for_surface (&pattern, &src->intel.drm.base); - pattern.base.filter = CAIRO_FILTER_NEAREST; - cairo_matrix_init_translate (&pattern.base.matrix, extents->x, extents->y); - - rect.x = rect.y = 0; - rect.width = extents->width; - rect.height = extents->height; - status = i915_shader_acquire_pattern (&shader, &shader.source, &pattern.base, &rect); - _cairo_pattern_fini (&pattern.base); - - if (unlikely (status)) - goto err_shader; - - status = cairo_device_acquire (&device->intel.base.base); - if (unlikely (status)) - goto err_shader; - - status = i915_shader_commit (&shader, device); - if (unlikely (status)) - goto err_device; - - shader.add_rectangle (&shader, 0, 0, extents->width, extents->height); - - cairo_device_release (&device->intel.base.base); - i915_shader_fini (&shader); - - *clone_out = clone; - return CAIRO_STATUS_SUCCESS; - -err_device: - cairo_device_release (&device->intel.base.base); -err_shader: - i915_shader_fini (&shader); - cairo_surface_destroy (&clone->intel.drm.base); - return status; -} - -static cairo_status_t -i915_blt_boxes (i915_surface_t *dst, - const cairo_pattern_t *pattern, - const cairo_rectangle_int_t *extents, - const cairo_boxes_t *boxes) -{ - const cairo_surface_pattern_t *spattern; - i915_device_t *device; - i915_surface_t *src; - cairo_surface_t *free_me = NULL; - const struct _cairo_boxes_chunk *chunk; - cairo_status_t status; - int br13, cmd, tx, ty; - intel_bo_t *bo_array[2]; - int i; - - if (! i915_can_blt (dst, pattern)) - return CAIRO_INT_STATUS_UNSUPPORTED; - - spattern = (const cairo_surface_pattern_t *) pattern; - src = (i915_surface_t *) spattern->surface; - - if (src->intel.drm.base.is_clear) - return i915_clear_boxes (dst, boxes); - - if (pattern->extend != CAIRO_EXTEND_NONE && - (extents->x + tx < 0 || - extents->y + ty < 0 || - extents->x + tx + extents->width > src->intel.drm.width || - extents->y + ty + extents->height > src->intel.drm.height)) - { - return CAIRO_INT_STATUS_UNSUPPORTED; - } - - status = i915_surface_fallback_flush (src); - if (unlikely (status)) - return status; - - tx = _cairo_lround (pattern->matrix.x0); - ty = _cairo_lround (pattern->matrix.y0); - - device = i915_device (dst); - if (to_intel_bo (src->intel.drm.bo)->tiling == I915_TILING_Y) { - cairo_rectangle_int_t extents; - - _cairo_boxes_extents (boxes, &extents); - extents.x += tx; - extents.y += ty; - - status = i915_surface_extract_X_from_Y (device, src, &extents, &src); - if (unlikely (status)) - return status; - - free_me = &src->intel.drm.base; - tx = -extents.x; - ty = -extents.y; - } - - bo_array[0] = to_intel_bo (dst->intel.drm.bo); - bo_array[1] = to_intel_bo (src->intel.drm.bo); - - status = cairo_device_acquire (&device->intel.base.base); - if (unlikely (status)) - goto CLEANUP_SURFACE; - - if (! i915_check_aperture_and_fences (device, bo_array, 2) || - i915_batch_space (device) < 8 * boxes->num_boxes) - { - status = i915_batch_flush (device); - if (unlikely (status)) - goto CLEANUP_DEVICE; - } - - cmd = XY_SRC_COPY_BLT_CMD; - br13 = (0xCC << 16) | dst->intel.drm.stride; - switch (dst->intel.drm.format) { - default: - case CAIRO_FORMAT_INVALID: - case CAIRO_FORMAT_A1: - ASSERT_NOT_REACHED; - case CAIRO_FORMAT_A8: - break; - case CAIRO_FORMAT_RGB16_565: - br13 |= BR13_565; - break; - case CAIRO_FORMAT_RGB24: - case CAIRO_FORMAT_ARGB32: - br13 |= BR13_8888; - cmd |= XY_BLT_WRITE_ALPHA | XY_BLT_WRITE_RGB; - break; - } - - for (chunk = &boxes->chunks; chunk != NULL; chunk = chunk->next) { - const cairo_box_t *box = chunk->base; - for (i = 0; i < chunk->count; i++) { - int x1 = _cairo_fixed_integer_round (box[i].p1.x); - int x2 = _cairo_fixed_integer_round (box[i].p2.x); - int y1 = _cairo_fixed_integer_round (box[i].p1.y); - int y2 = _cairo_fixed_integer_round (box[i].p2.y); - - if (x1 + tx < 0) - x1 = -tx; - if (x2 + tx > src->intel.drm.width) - x2 = src->intel.drm.width - tx; - - if (y1 + ty < 0) - y1 = -ty; - if (y2 + ty > src->intel.drm.height) - y2 = src->intel.drm.height - ty; - - if (x2 <= x1 || y2 <= y1) - continue; - if (x2 < 0 || y2 < 0) - continue; - if (x1 >= dst->intel.drm.width || y2 >= dst->intel.drm.height) - continue; - - OUT_DWORD (cmd); - OUT_DWORD (br13); - OUT_DWORD ((y1 << 16) | x1); - OUT_DWORD (((y2 - 1) << 16) | (x2 - 1)); - OUT_RELOC_FENCED (dst, I915_GEM_DOMAIN_RENDER, I915_GEM_DOMAIN_RENDER); - OUT_DWORD (((y1 + ty) << 16) | (x1 + tx)); - OUT_DWORD (src->intel.drm.stride); - OUT_RELOC_FENCED (src, I915_GEM_DOMAIN_RENDER, 0); - } - } - - /* XXX fixup blank portions */ - -CLEANUP_DEVICE: - cairo_device_release (&device->intel.base.base); -CLEANUP_SURFACE: - cairo_surface_destroy (free_me); - return status; -} - -static cairo_status_t -_upload_image_inplace (i915_surface_t *surface, - const cairo_pattern_t *source, - const cairo_rectangle_int_t *extents, - const cairo_boxes_t *boxes) -{ - i915_device_t *device; - const cairo_surface_pattern_t *pattern; - cairo_image_surface_t *image; - const struct _cairo_boxes_chunk *chunk; - intel_bo_t *bo; - int tx, ty, i; - - if (source->type != CAIRO_PATTERN_TYPE_SURFACE) - return CAIRO_INT_STATUS_UNSUPPORTED; - - pattern = (const cairo_surface_pattern_t *) source; - if (pattern->surface->type != CAIRO_SURFACE_TYPE_IMAGE) - return CAIRO_INT_STATUS_UNSUPPORTED; - - if (! _cairo_matrix_is_integer_translation (&source->matrix, &tx, &ty)) - return CAIRO_INT_STATUS_UNSUPPORTED; - - image = (cairo_image_surface_t *) pattern->surface; - if (source->extend != CAIRO_EXTEND_NONE && - (extents->x + tx < 0 || - extents->y + ty < 0 || - extents->x + tx + extents->width > image->width || - extents->y + ty + extents->height > image->height)) - { - return CAIRO_INT_STATUS_UNSUPPORTED; - } - - device = i915_device (surface); - bo = to_intel_bo (surface->intel.drm.bo); - if (bo->exec != NULL || ! intel_bo_is_inactive (&device->intel, bo)) { - intel_bo_t *new_bo; - cairo_bool_t need_clear = FALSE; - - if (boxes->num_boxes != 1 || - extents->width < surface->intel.drm.width || - extents->height < surface->intel.drm.height) - { - if (! surface->intel.drm.base.is_clear) - return CAIRO_INT_STATUS_UNSUPPORTED; - - need_clear = TRUE; - } - - new_bo = intel_bo_create (&device->intel, - bo->full_size, bo->base.size, - FALSE, bo->tiling, bo->stride); - if (unlikely (new_bo == NULL)) - return _cairo_error (CAIRO_STATUS_NO_MEMORY); - - intel_bo_in_flight_add (&device->intel, bo); - intel_bo_destroy (&device->intel, bo); - - bo = new_bo; - surface->intel.drm.bo = &bo->base; - - if (need_clear) { - memset (intel_bo_map (&device->intel, bo), 0, - bo->stride * surface->intel.drm.height); - } - } - - if (image->format == surface->intel.drm.format) { - for (chunk = &boxes->chunks; chunk != NULL; chunk = chunk->next) { - cairo_box_t *box = chunk->base; - for (i = 0; i < chunk->count; i++) { - int x1 = _cairo_fixed_integer_round (box[i].p1.x); - int x2 = _cairo_fixed_integer_round (box[i].p2.x); - int y1 = _cairo_fixed_integer_round (box[i].p1.y); - int y2 = _cairo_fixed_integer_round (box[i].p2.y); - cairo_status_t status; - - if (x1 + tx < 0) - x1 = -tx; - if (x2 + tx > image->width) - x2 = image->width - tx; - - if (y1 + ty < 0) - y1 = -ty; - if (y2 + ty > image->height) - y2 = image->height - ty; - - if (x2 <= x1 || y2 <= y1) - continue; - if (x2 < 0 || y2 < 0) - continue; - if (x1 >= surface->intel.drm.width || y2 >= surface->intel.drm.height) - continue; - - status = intel_bo_put_image (&device->intel, - bo, - image, - x1 + tx, y1 + ty, - x2 - x1, y2 - y1, - x1, y1); - if (unlikely (status)) - return status; - } - } - } else { - pixman_image_t *dst; - void *ptr; - - ptr = intel_bo_map (&device->intel, bo); - if (unlikely (ptr == NULL)) - return _cairo_error (CAIRO_STATUS_DEVICE_ERROR); - - dst = pixman_image_create_bits (_cairo_format_to_pixman_format_code (surface->intel.drm.format), - surface->intel.drm.width, - surface->intel.drm.height, - ptr, - surface->intel.drm.stride); - if (unlikely (dst == NULL)) - return _cairo_error (CAIRO_STATUS_NO_MEMORY); - - for (chunk = &boxes->chunks; chunk != NULL; chunk = chunk->next) { - cairo_box_t *box = chunk->base; - for (i = 0; i < chunk->count; i++) { - int x1 = _cairo_fixed_integer_round (box[i].p1.x); - int x2 = _cairo_fixed_integer_round (box[i].p2.x); - int y1 = _cairo_fixed_integer_round (box[i].p1.y); - int y2 = _cairo_fixed_integer_round (box[i].p2.y); - - if (x1 + tx < 0) - x1 = -tx; - if (x2 + tx > image->width) - x2 = image->width - tx; - - if (y1 + ty < 0) - y1 = -ty; - if (y2 + ty > image->height) - y2 = image->height - ty; - - if (x2 <= x1 || y2 <= y1) - continue; - if (x2 < 0 || y2 < 0) - continue; - if (x1 >= surface->intel.drm.width || y2 >= surface->intel.drm.height) - continue; - - pixman_image_composite32 (PIXMAN_OP_SRC, - image->pixman_image, NULL, dst, - x1 + tx, y1 + ty, - 0, 0, - x1, y1, - x2 - x1, y2 - y1); - } - } - - pixman_image_unref (dst); - } - - return CAIRO_STATUS_SUCCESS; -} - -static cairo_status_t -_composite_boxes (i915_surface_t *dst, - cairo_operator_t op, - const cairo_pattern_t *pattern, - cairo_boxes_t *boxes, - cairo_antialias_t antialias, - cairo_clip_t *clip, - double opacity, - const cairo_composite_rectangles_t *extents) -{ - cairo_bool_t need_clip_surface = FALSE; - cairo_region_t *clip_region = NULL; - const struct _cairo_boxes_chunk *chunk; - cairo_status_t status; - i915_shader_t shader; - i915_device_t *device; - int i; - - /* If the boxes are not pixel-aligned, we will need to compute a real mask */ - if (antialias != CAIRO_ANTIALIAS_NONE) { - if (! boxes->is_pixel_aligned) - return CAIRO_INT_STATUS_UNSUPPORTED; - } - - if (clip == NULL && op == CAIRO_OPERATOR_SOURCE && opacity == 1.) { - if (pattern->type == CAIRO_PATTERN_TYPE_SURFACE) { - status = i915_blt_boxes (dst, pattern, &extents->bounded, boxes); - if (status == CAIRO_INT_STATUS_UNSUPPORTED) { - status = _upload_image_inplace (dst, pattern, - &extents->bounded, boxes); - } - if (status != CAIRO_INT_STATUS_UNSUPPORTED) - return status; - } - } - - if (i915_surface_needs_tiling (dst)) { - ASSERT_NOT_REACHED; - return CAIRO_INT_STATUS_UNSUPPORTED; - } - - i915_shader_init (&shader, dst, op, opacity); - - status = i915_shader_acquire_pattern (&shader, - &shader.source, - pattern, - &extents->bounded); - if (unlikely (status)) - return status; - - if (clip != NULL) { - status = _cairo_clip_get_region (clip, &clip_region); - assert (status == CAIRO_STATUS_SUCCESS || status == CAIRO_INT_STATUS_UNSUPPORTED); - need_clip_surface = status == CAIRO_INT_STATUS_UNSUPPORTED; - if (need_clip_surface) - i915_shader_set_clip (&shader, clip); - } - - device = i915_device (dst); - status = cairo_device_acquire (&device->intel.base.base); - if (unlikely (status)) - goto err_shader; - - status = i915_shader_commit (&shader, device); - if (unlikely (status)) - goto err_device; - - for (chunk = &boxes->chunks; chunk != NULL; chunk = chunk->next) { - cairo_box_t *box = chunk->base; - for (i = 0; i < chunk->count; i++) { - int x1 = _cairo_fixed_integer_round (box[i].p1.x); - int y1 = _cairo_fixed_integer_round (box[i].p1.y); - int x2 = _cairo_fixed_integer_round (box[i].p2.x); - int y2 = _cairo_fixed_integer_round (box[i].p2.y); - - if (x2 > x1 && y2 > y1) - shader.add_rectangle (&shader, x1, y1, x2 - x1, y2 - y1); - } - } - - if (! extents->is_bounded) - status = i915_fixup_unbounded_boxes (dst, extents, clip, boxes); - - err_device: - cairo_device_release (&device->intel.base.base); - err_shader: - i915_shader_fini (&shader); - - return status; -} - -cairo_status_t -i915_surface_clear (i915_surface_t *dst) -{ - i915_device_t *device; - cairo_status_t status; - intel_bo_t *bo_array[1] = { to_intel_bo (dst->intel.drm.bo) }; - - device = i915_device (dst); - status = cairo_device_acquire (&device->intel.base.base); - if (unlikely (status)) - return status; - - if (i915_surface_needs_tiling (dst)) { - int cmd, br13, clear = 0; - - if (! i915_check_aperture_and_fences (device, bo_array, 1) || - i915_batch_space (device) < 6) - { - status = i915_batch_flush (device); - if (unlikely (status)) { - cairo_device_release (&device->intel.base.base); - return status; - } - } - - if (device->vertex_count) - i915_vbo_flush (device); - - cmd = XY_COLOR_BLT_CMD; - br13 = (0xCC << 16) | dst->intel.drm.stride; - switch (dst->intel.drm.format) { - default: - case CAIRO_FORMAT_INVALID: - case CAIRO_FORMAT_A1: - ASSERT_NOT_REACHED; - case CAIRO_FORMAT_A8: - break; - case CAIRO_FORMAT_RGB16_565: - br13 |= BR13_565; - break; - case CAIRO_FORMAT_RGB24: - clear = 0xff000000; - case CAIRO_FORMAT_ARGB32: - br13 |= BR13_8888; - cmd |= XY_BLT_WRITE_ALPHA | XY_BLT_WRITE_RGB; - break; - } - - OUT_DWORD (cmd); - OUT_DWORD (br13); - OUT_DWORD (0); - OUT_DWORD (((dst->intel.drm.height - 1) << 16) | - (dst->intel.drm.width - 1)); - OUT_RELOC_FENCED (dst, - I915_GEM_DOMAIN_RENDER, I915_GEM_DOMAIN_RENDER); - OUT_DWORD (clear); - } else { - if (! i915_check_aperture (device, bo_array, 1) || - i915_batch_space (device) < 24) - { - status = i915_batch_flush (device); - if (unlikely (status)) { - cairo_device_release (&device->intel.base.base); - return status; - } - } - - if (device->vertex_count) - i915_vbo_flush (device); - - i915_set_dst (device, dst); - - /* set clear parameters */ - if (device->clear_alpha != (dst->intel.drm.base.content & CAIRO_CONTENT_ALPHA)) { - device->clear_alpha = dst->intel.drm.base.content & CAIRO_CONTENT_ALPHA; - OUT_DWORD (_3DSTATE_CLEAR_PARAMETERS); - OUT_DWORD (CLEARPARAM_CLEAR_RECT | CLEARPARAM_WRITE_COLOR); - /* ZONE_INIT color */ - if (device->clear_alpha) /* XXX depends on pixel format, 16bit needs replication, 8bit? */ - OUT_DWORD (0x00000000); - else - OUT_DWORD (0xff000000); - OUT_DWORD (0); /* ZONE_INIT depth */ - /* CLEAR_RECT color */ - if (device->clear_alpha) - OUT_DWORD (0x00000000); - else - OUT_DWORD (0xff000000); - OUT_DWORD (0); /* CLEAR_RECT depth */ - OUT_DWORD (0); /* CLEAR_RECT stencil */ - } - - OUT_DWORD (PRIM3D_CLEAR_RECT | 5); - OUT_DWORD (pack_float (dst->intel.drm.width)); - OUT_DWORD (pack_float (dst->intel.drm.height)); - OUT_DWORD (0); - OUT_DWORD (pack_float (dst->intel.drm.height)); - OUT_DWORD (0); - OUT_DWORD (0); - } - - cairo_device_release (&device->intel.base.base); - - dst->deferred_clear = FALSE; - return status; -} - -static cairo_status_t -_clip_and_composite_boxes (i915_surface_t *dst, - cairo_operator_t op, - const cairo_pattern_t *src, - cairo_boxes_t *boxes, - cairo_antialias_t antialias, - const cairo_composite_rectangles_t *extents, - cairo_clip_t *clip, - double opacity) -{ - cairo_status_t status; - - if (boxes->num_boxes == 0) { - if (extents->is_bounded) - return CAIRO_STATUS_SUCCESS; - - return i915_fixup_unbounded (dst, extents, clip); - } - - if (clip == NULL && - (op == CAIRO_OPERATOR_SOURCE || (op == CAIRO_OPERATOR_OVER && dst->intel.drm.base.is_clear)) && - opacity == 1. && - boxes->num_boxes == 1 && - extents->bounded.width == dst->intel.drm.width && - extents->bounded.height == dst->intel.drm.height) - { - op = CAIRO_OPERATOR_SOURCE; - dst->deferred_clear = FALSE; - - status = _upload_image_inplace (dst, src, - &extents->bounded, boxes); - if (status != CAIRO_INT_STATUS_UNSUPPORTED) - return status; - } - - if (dst->deferred_clear) { - status = i915_surface_clear (dst); - if (unlikely (status)) - return status; - } - - /* Use a fast path if the boxes are pixel aligned */ - status = _composite_boxes (dst, op, src, boxes, antialias, clip, opacity, extents); - if (status != CAIRO_INT_STATUS_UNSUPPORTED) - return status; - - /* Otherwise render the boxes via an implicit mask and composite in the usual - * fashion. - */ - return i915_clip_and_composite_spans (dst, op, src, antialias, - _composite_boxes_spans, boxes, - extents, clip, opacity); -} - -static cairo_clip_path_t * -_clip_get_solitary_path (cairo_clip_t *clip) -{ - cairo_clip_path_t *iter = clip->path; - cairo_clip_path_t *path = NULL; - - do { - if ((iter->flags & CAIRO_CLIP_PATH_IS_BOX) == 0) { - if (path != NULL) - return FALSE; - - path = iter; - } - iter = iter->prev; - } while (iter != NULL); - - return path; -} - -typedef struct { - cairo_polygon_t polygon; - cairo_fill_rule_t fill_rule; - cairo_antialias_t antialias; -} composite_polygon_info_t; - -static cairo_status_t -_composite_polygon_spans (void *closure, - cairo_span_renderer_t *renderer, - const cairo_rectangle_int_t *extents) -{ - composite_polygon_info_t *info = closure; - cairo_botor_scan_converter_t converter; - cairo_status_t status; - cairo_box_t box; - - box.p1.x = _cairo_fixed_from_int (extents->x); - box.p1.y = _cairo_fixed_from_int (extents->y); - box.p2.x = _cairo_fixed_from_int (extents->x + extents->width); - box.p2.y = _cairo_fixed_from_int (extents->y + extents->height); - - _cairo_botor_scan_converter_init (&converter, &box, info->fill_rule); - - status = converter.base.add_polygon (&converter.base, &info->polygon); - if (likely (status == CAIRO_STATUS_SUCCESS)) - status = converter.base.generate (&converter.base, renderer); - - converter.base.destroy (&converter.base); - - return status; -} - -static cairo_int_status_t -i915_surface_fill_with_alpha (void *abstract_dst, - cairo_operator_t op, - const cairo_pattern_t *source, - cairo_path_fixed_t *path, - cairo_fill_rule_t fill_rule, - double tolerance, - cairo_antialias_t antialias, - cairo_clip_t *clip, - double opacity) -{ - i915_surface_t *dst = abstract_dst; - cairo_composite_rectangles_t extents; - composite_polygon_info_t info; - cairo_box_t boxes_stack[32], *clip_boxes = boxes_stack; - cairo_clip_t local_clip; - cairo_bool_t have_clip = FALSE; - int num_boxes = ARRAY_LENGTH (boxes_stack); - cairo_status_t status; - - status = _cairo_composite_rectangles_init_for_fill (&extents, - dst->intel.drm.width, - dst->intel.drm.height, - op, source, path, - clip); - if (unlikely (status)) - return status; - - if (_cairo_clip_contains_extents (clip, &extents)) - clip = NULL; - - if (extents.is_bounded && clip != NULL) { - cairo_clip_path_t *clip_path; - - if (((clip_path = _clip_get_solitary_path (clip)) != NULL) && - _cairo_path_fixed_equal (&clip_path->path, path)) - { - clip = NULL; - } - } - - if (clip != NULL) { - clip = _cairo_clip_init_copy (&local_clip, clip); - have_clip = TRUE; - } - - status = _cairo_clip_to_boxes (&clip, &extents, &clip_boxes, &num_boxes); - if (unlikely (status)) { - if (have_clip) - _cairo_clip_fini (&local_clip); - - return status; - } - - assert (! _cairo_path_fixed_fill_is_empty (path)); - - if (_cairo_path_fixed_fill_is_rectilinear (path)) { - cairo_boxes_t boxes; - - _cairo_boxes_init (&boxes); - _cairo_boxes_limit (&boxes, clip_boxes, num_boxes); - status = _cairo_path_fixed_fill_rectilinear_to_boxes (path, - fill_rule, - &boxes); - if (likely (status == CAIRO_STATUS_SUCCESS)) { - status = _clip_and_composite_boxes (dst, op, source, - &boxes, antialias, - &extents, clip, - opacity); - } - - _cairo_boxes_fini (&boxes); - - if (status != CAIRO_INT_STATUS_UNSUPPORTED) - goto CLEANUP_BOXES; - } - - _cairo_polygon_init (&info.polygon, clip_boxes, num_boxes); - - status = _cairo_path_fixed_fill_to_polygon (path, tolerance, &info.polygon); - if (unlikely (status)) - goto CLEANUP_POLYGON; - - if (extents.is_bounded) { - cairo_rectangle_int_t rect; - - _cairo_box_round_to_rectangle (&info.polygon.extents, &rect); - if (! _cairo_rectangle_intersect (&extents.bounded, &rect)) - goto CLEANUP_POLYGON; - } - - if (info.polygon.num_edges == 0) { - if (! extents.is_bounded) - status = i915_fixup_unbounded (dst, &extents, clip); - - goto CLEANUP_POLYGON; - } - - info.fill_rule = fill_rule; - info.antialias = antialias; - status = i915_clip_and_composite_spans (dst, op, source, antialias, - _composite_polygon_spans, &info, - &extents, clip, opacity); - -CLEANUP_POLYGON: - _cairo_polygon_fini (&info.polygon); - -CLEANUP_BOXES: - if (clip_boxes != boxes_stack) - free (clip_boxes); - - if (have_clip) - _cairo_clip_fini (&local_clip); - - return status; -} - -static cairo_int_status_t -i915_surface_paint_with_alpha (void *abstract_dst, - cairo_operator_t op, - const cairo_pattern_t *source, - cairo_clip_t *clip, - double opacity) -{ - i915_surface_t *dst = abstract_dst; - cairo_composite_rectangles_t extents; - cairo_clip_t local_clip; - cairo_bool_t have_clip = FALSE; - cairo_clip_path_t *clip_path; - cairo_boxes_t boxes; - int num_boxes = ARRAY_LENGTH (boxes.boxes_embedded); - cairo_box_t *clip_boxes = boxes.boxes_embedded; - cairo_status_t status; - - status = _cairo_composite_rectangles_init_for_paint (&extents, - dst->intel.drm.width, - dst->intel.drm.height, - op, source, - clip); - if (unlikely (status)) - return status; - - if (_cairo_clip_contains_extents (clip, &extents)) - clip = NULL; - - if (clip != NULL) { - clip = _cairo_clip_init_copy (&local_clip, clip); - have_clip = TRUE; - } - - status = _cairo_clip_to_boxes (&clip, &extents, &clip_boxes, &num_boxes); - if (unlikely (status)) { - if (have_clip) - _cairo_clip_fini (&local_clip); - - return status; - } - - /* If the clip cannot be reduced to a set of boxes, we will need to - * use a clipmask. Paint is special as it is the only operation that - * does not implicitly use a mask, so we may be able to reduce this - * operation to a fill... - */ - if (clip != NULL && - extents.is_bounded && - (clip_path = _clip_get_solitary_path (clip)) != NULL) - { - status = i915_surface_fill_with_alpha (dst, op, source, - &clip_path->path, - clip_path->fill_rule, - clip_path->tolerance, - clip_path->antialias, - NULL, opacity); - } - else - { - _cairo_boxes_init_for_array (&boxes, clip_boxes, num_boxes); - status = _clip_and_composite_boxes (dst, op, source, - &boxes, CAIRO_ANTIALIAS_DEFAULT, - &extents, clip, opacity); - } - if (clip_boxes != boxes.boxes_embedded) - free (clip_boxes); - - if (have_clip) - _cairo_clip_fini (&local_clip); - - return status; -} - -static cairo_int_status_t -i915_surface_paint (void *abstract_dst, - cairo_operator_t op, - const cairo_pattern_t *source, - cairo_clip_t *clip) -{ - i915_surface_t *dst = abstract_dst; - - /* XXX unsupported operators? use pixel shader blending, eventually */ - - if (op == CAIRO_OPERATOR_CLEAR && clip == NULL) { - dst->deferred_clear = TRUE; - return CAIRO_STATUS_SUCCESS; - } - - return i915_surface_paint_with_alpha (dst, op, source, clip, 1.); -} - -static cairo_int_status_t -i915_surface_mask (void *abstract_dst, - cairo_operator_t op, - const cairo_pattern_t *source, - const cairo_pattern_t *mask, - cairo_clip_t *clip) -{ - i915_surface_t *dst = abstract_dst; - i915_device_t *device; - cairo_composite_rectangles_t extents; - i915_shader_t shader; - cairo_clip_t local_clip; - cairo_region_t *clip_region = NULL; - cairo_bool_t need_clip_surface = FALSE; - cairo_bool_t have_clip = FALSE; - cairo_status_t status; - - if (mask->type == CAIRO_PATTERN_TYPE_SOLID) { - const cairo_solid_pattern_t *solid = (cairo_solid_pattern_t *) mask; - return i915_surface_paint_with_alpha (dst, op, source, clip, solid->color.alpha); - } - - status = _cairo_composite_rectangles_init_for_mask (&extents, - dst->intel.drm.width, - dst->intel.drm.height, - op, source, mask, clip); - if (unlikely (status)) - return status; - - if (_cairo_clip_contains_extents (clip, &extents)) - clip = NULL; - - if (clip != NULL && extents.is_bounded) { - clip = _cairo_clip_init_copy (&local_clip, clip); - status = _cairo_clip_rectangle (clip, &extents.bounded); - if (unlikely (status)) { - _cairo_clip_fini (&local_clip); - return status; - } - - have_clip = TRUE; - } - - i915_shader_init (&shader, dst, op, 1.); - - status = i915_shader_acquire_pattern (&shader, - &shader.source, - source, - &extents.bounded); - if (unlikely (status)) - goto err_shader; - - status = i915_shader_acquire_pattern (&shader, - &shader.mask, - mask, - &extents.bounded); - if (unlikely (status)) - goto err_shader; - - if (clip != NULL) { - status = _cairo_clip_get_region (clip, &clip_region); - if (unlikely (_cairo_status_is_error (status) || - status == CAIRO_INT_STATUS_NOTHING_TO_DO)) - { - goto err_shader; - } - - need_clip_surface = status == CAIRO_INT_STATUS_UNSUPPORTED; - if (need_clip_surface) - i915_shader_set_clip (&shader, clip); - - if (clip_region != NULL) { - cairo_rectangle_int_t rect; - cairo_bool_t is_empty; - - status = CAIRO_STATUS_SUCCESS; - cairo_region_get_extents (clip_region, &rect); - is_empty = ! _cairo_rectangle_intersect (&extents.unbounded, &rect); - if (unlikely (is_empty)) - goto err_shader; - - is_empty = ! _cairo_rectangle_intersect (&extents.bounded, &rect); - if (unlikely (is_empty && extents.is_bounded)) - goto err_shader; - - if (cairo_region_num_rectangles (clip_region) == 1) - clip_region = NULL; - } - } - - if (i915_surface_needs_tiling (dst)) { - ASSERT_NOT_REACHED; - return CAIRO_INT_STATUS_UNSUPPORTED; - } - - device = i915_device (dst); - status = cairo_device_acquire (&device->intel.base.base); - if (unlikely (status)) - goto err_shader; - - if (dst->deferred_clear) { - status = i915_surface_clear (dst); - if (unlikely (status)) - goto err_shader; - } - - status = i915_shader_commit (&shader, device); - if (unlikely (status)) - goto err_device; - - if (clip_region != NULL) { - unsigned int n, num_rectangles; - - num_rectangles = cairo_region_num_rectangles (clip_region); - for (n = 0; n < num_rectangles; n++) { - cairo_rectangle_int_t rect; - - cairo_region_get_rectangle (clip_region, n, &rect); - - shader.add_rectangle (&shader, - rect.x, rect.y, - rect.x + rect.width, rect.y + rect.height); - } - } else { - shader.add_rectangle (&shader, - extents.bounded.x, extents.bounded.y, - extents.bounded.x + extents.bounded.width, - extents.bounded.y + extents.bounded.height); - } - - if (! extents.is_bounded) - status = i915_fixup_unbounded (dst, &extents, clip); - - err_device: - cairo_device_release (&device->intel.base.base); - err_shader: - i915_shader_fini (&shader); - if (have_clip) - _cairo_clip_fini (&local_clip); - - return status; -} - -static cairo_int_status_t -i915_surface_stroke (void *abstract_dst, - cairo_operator_t op, - const cairo_pattern_t *source, - cairo_path_fixed_t *path, - const cairo_stroke_style_t *stroke_style, - const cairo_matrix_t *ctm, - const cairo_matrix_t *ctm_inverse, - double tolerance, - cairo_antialias_t antialias, - cairo_clip_t *clip) -{ - i915_surface_t *dst = abstract_dst; - cairo_composite_rectangles_t extents; - composite_polygon_info_t info; - cairo_box_t boxes_stack[32], *clip_boxes = boxes_stack; - int num_boxes = ARRAY_LENGTH (boxes_stack); - cairo_clip_t local_clip; - cairo_bool_t have_clip = FALSE; - cairo_status_t status; - - status = _cairo_composite_rectangles_init_for_stroke (&extents, - dst->intel.drm.width, - dst->intel.drm.height, - op, source, - path, stroke_style, ctm, - clip); - if (unlikely (status)) - return status; - - if (_cairo_clip_contains_extents (clip, &extents)) - clip = NULL; - - if (clip != NULL) { - clip = _cairo_clip_init_copy (&local_clip, clip); - have_clip = TRUE; - } - - status = _cairo_clip_to_boxes (&clip, &extents, &clip_boxes, &num_boxes); - if (unlikely (status)) { - if (have_clip) - _cairo_clip_fini (&local_clip); - - return status; - } - - if (_cairo_path_fixed_stroke_is_rectilinear (path)) { - cairo_boxes_t boxes; - - _cairo_boxes_init (&boxes); - _cairo_boxes_limit (&boxes, clip_boxes, num_boxes); - status = _cairo_path_fixed_stroke_rectilinear_to_boxes (path, - stroke_style, - ctm, - &boxes); - if (likely (status == CAIRO_STATUS_SUCCESS)) { - status = _clip_and_composite_boxes (dst, op, source, - &boxes, antialias, - &extents, clip, 1.); - } - - _cairo_boxes_fini (&boxes); - - if (status != CAIRO_INT_STATUS_UNSUPPORTED) - goto CLEANUP_BOXES; - } - - _cairo_polygon_init (&info.polygon, clip_boxes, num_boxes); - - status = _cairo_path_fixed_stroke_to_polygon (path, - stroke_style, - ctm, ctm_inverse, - tolerance, - &info.polygon); - if (unlikely (status)) - goto CLEANUP_POLYGON; - - if (extents.is_bounded) { - cairo_rectangle_int_t rect; - - _cairo_box_round_to_rectangle (&info.polygon.extents, &rect); - if (! _cairo_rectangle_intersect (&extents.bounded, &rect)) - goto CLEANUP_POLYGON; - } - - if (info.polygon.num_edges == 0) { - if (! extents.is_bounded) - status = i915_fixup_unbounded (dst, &extents, clip); - - goto CLEANUP_POLYGON; - } - - info.fill_rule = CAIRO_FILL_RULE_WINDING; - info.antialias = antialias; - status = i915_clip_and_composite_spans (dst, op, source, antialias, - _composite_polygon_spans, &info, - &extents, clip, 1.); - -CLEANUP_POLYGON: - _cairo_polygon_fini (&info.polygon); - -CLEANUP_BOXES: - if (clip_boxes != boxes_stack) - free (clip_boxes); - - if (have_clip) - _cairo_clip_fini (&local_clip); - - return status; -} - -static cairo_int_status_t -i915_surface_fill (void *abstract_dst, - cairo_operator_t op, - const cairo_pattern_t*source, - cairo_path_fixed_t *path, - cairo_fill_rule_t fill_rule, - double tolerance, - cairo_antialias_t antialias, - cairo_clip_t *clip) -{ - return i915_surface_fill_with_alpha (abstract_dst, op, source, path, fill_rule, tolerance, antialias, clip, 1.); -} - -static const cairo_surface_backend_t i915_surface_backend = { - CAIRO_SURFACE_TYPE_DRM, - _cairo_default_context_create, - - i915_surface_create_similar, - i915_surface_finish, - - NULL, - intel_surface_acquire_source_image, - intel_surface_release_source_image, - - NULL, NULL, NULL, - NULL, /* composite */ - NULL, /* fill */ - NULL, /* trapezoids */ - NULL, /* span */ - NULL, /* check-span */ - - NULL, /* copy_page */ - NULL, /* show_page */ - _cairo_drm_surface_get_extents, - NULL, /* old-glyphs */ - _cairo_drm_surface_get_font_options, - - i915_surface_flush, - NULL, /* mark_dirty */ - intel_scaled_font_fini, - intel_scaled_glyph_fini, - - i915_surface_paint, - i915_surface_mask, - i915_surface_stroke, - i915_surface_fill, - i915_surface_glyphs, -}; - -static void -i915_surface_init (i915_surface_t *surface, - cairo_drm_device_t *device, - cairo_format_t format, - int width, int height) -{ - intel_surface_init (&surface->intel, &i915_surface_backend, device, - format, width, height); - - switch (format) { - default: - case CAIRO_FORMAT_INVALID: - case CAIRO_FORMAT_A1: - ASSERT_NOT_REACHED; - case CAIRO_FORMAT_ARGB32: - surface->map0 = MAPSURF_32BIT | MT_32BIT_ARGB8888; - surface->colorbuf = COLR_BUF_ARGB8888 | DEPTH_FRMT_24_FIXED_8_OTHER; - break; - case CAIRO_FORMAT_RGB24: - surface->map0 = MAPSURF_32BIT | MT_32BIT_XRGB8888; - surface->colorbuf = COLR_BUF_ARGB8888 | DEPTH_FRMT_24_FIXED_8_OTHER; - break; - case CAIRO_FORMAT_RGB16_565: - surface->map0 = MAPSURF_16BIT | MT_16BIT_RGB565; - surface->colorbuf = COLR_BUF_RGB565; - break; - case CAIRO_FORMAT_A8: - surface->map0 = MAPSURF_8BIT | MT_8BIT_A8; - surface->colorbuf = COLR_BUF_8BIT | DEPTH_FRMT_24_FIXED_8_OTHER; - break; - } - surface->colorbuf |= DSTORG_HORT_BIAS (0x8) | DSTORG_VERT_BIAS (0x8); - surface->map0 |= ((height - 1) << MS3_HEIGHT_SHIFT) | - ((width - 1) << MS3_WIDTH_SHIFT); - surface->map1 = 0; - - surface->is_current_texture = 0; - surface->deferred_clear = FALSE; - - surface->offset = 0; - - surface->stencil = NULL; - surface->cache = NULL; -} - -cairo_surface_t * -i915_surface_create_internal (cairo_drm_device_t *base_dev, - cairo_format_t format, - int width, int height, - uint32_t tiling, - cairo_bool_t gpu_target) -{ - i915_surface_t *surface; - cairo_status_t status_ignored; - - surface = _cairo_malloc (sizeof (i915_surface_t)); - if (unlikely (surface == NULL)) - return _cairo_surface_create_in_error (_cairo_error (CAIRO_STATUS_NO_MEMORY)); - - i915_surface_init (surface, base_dev, format, width, height); - - if (width && height) { - uint32_t size, stride; - intel_bo_t *bo; - - width = (width + 3) & -4; - stride = cairo_format_stride_for_width (surface->intel.drm.format, width); - /* check for tiny surfaces for which tiling is irrelevant */ - if (height * stride <= 4096) - tiling = I915_TILING_NONE; - if (tiling != I915_TILING_NONE && stride <= 512) - tiling = I915_TILING_NONE; - if (tiling != I915_TILING_NONE) { - if (height <= 8) - tiling = I915_TILING_NONE; - else if (height <= 16) - tiling = I915_TILING_X; - } - /* large surfaces we need to blt, so force TILING_X */ - if (height > 2048) - tiling = I915_TILING_X; - /* but there is a maximum limit to the tiling pitch */ - if (tiling != I915_TILING_NONE && stride > 8192) - tiling = I915_TILING_NONE; - - stride = i915_tiling_stride (tiling, stride); - assert (stride >= (uint32_t) cairo_format_stride_for_width (surface->intel.drm.format, width)); - assert (tiling == I915_TILING_NONE || stride <= 8192); - height = i915_tiling_height (tiling, height); - if (height > 64*1024) { - free (surface); - cairo_device_destroy (&base_dev->base); - return _cairo_surface_create_in_error (_cairo_error (CAIRO_STATUS_INVALID_SIZE)); - } - - size = stride * height; - bo = intel_bo_create (to_intel_device (&base_dev->base), - i915_tiling_size (tiling, size), size, - gpu_target, tiling, stride); - if (bo == NULL) { - status_ignored = _cairo_drm_surface_finish (&surface->intel.drm); - free (surface); - return _cairo_surface_create_in_error (_cairo_error (CAIRO_STATUS_NO_MEMORY)); - } - assert (bo->base.size >= size); - - surface->intel.drm.bo = &bo->base; - surface->intel.drm.stride = stride; - - surface->map0 |= MS3_tiling (tiling); - surface->map1 = (stride/4 - 1) << MS4_PITCH_SHIFT; - } - - return &surface->intel.drm.base; -} - -static cairo_surface_t * -i915_surface_create (cairo_drm_device_t *base_dev, - cairo_format_t format, - int width, int height) -{ - switch (format) { - case CAIRO_FORMAT_ARGB32: - case CAIRO_FORMAT_RGB16_565: - case CAIRO_FORMAT_RGB24: - case CAIRO_FORMAT_A8: - break; - case CAIRO_FORMAT_INVALID: - default: - case CAIRO_FORMAT_A1: - return _cairo_surface_create_in_error (_cairo_error (CAIRO_STATUS_INVALID_FORMAT)); - } - - return i915_surface_create_internal (base_dev, format, width, height, - I915_TILING_DEFAULT, TRUE); -} - -static cairo_surface_t * -i915_surface_create_for_name (cairo_drm_device_t *base_dev, - unsigned int name, - cairo_format_t format, - int width, int height, int stride) -{ - i915_surface_t *surface; - - /* Vol I, p134: size restrictions for textures */ - /* Vol I, p129: destination surface stride must be a multiple of 32 bytes */ - if (stride < cairo_format_stride_for_width (format, (width + 3) & -4) || - stride & 31) - { - return _cairo_surface_create_in_error (_cairo_error (CAIRO_STATUS_INVALID_STRIDE)); - } - - switch (format) { - default: - case CAIRO_FORMAT_INVALID: - case CAIRO_FORMAT_A1: - return _cairo_surface_create_in_error (_cairo_error (CAIRO_STATUS_INVALID_FORMAT)); - case CAIRO_FORMAT_ARGB32: - case CAIRO_FORMAT_RGB16_565: - case CAIRO_FORMAT_RGB24: - case CAIRO_FORMAT_A8: - break; - } - - surface = _cairo_malloc (sizeof (i915_surface_t)); - if (unlikely (surface == NULL)) - return _cairo_surface_create_in_error (_cairo_error (CAIRO_STATUS_NO_MEMORY)); - - i915_surface_init (surface, base_dev, format, width, height); - - if (width && height) { - surface->intel.drm.stride = stride; - surface->map1 = (surface->intel.drm.stride/4 - 1) << MS4_PITCH_SHIFT; - - surface->intel.drm.bo = - &intel_bo_create_for_name (to_intel_device (&base_dev->base), - name)->base; - if (unlikely (surface->intel.drm.bo == NULL)) { - free (surface); - return _cairo_surface_create_in_error (_cairo_error (CAIRO_STATUS_NO_MEMORY)); - } - to_intel_bo (surface->intel.drm.bo)->stride = stride; - - surface->map0 |= MS3_tiling (to_intel_bo (surface->intel.drm.bo)->tiling); - } - - return &surface->intel.drm.base; -} - -static cairo_status_t -i915_buffer_cache_init (intel_buffer_cache_t *cache, - i915_device_t *device, - cairo_format_t format, - int width, int height) -{ - const uint32_t tiling = I915_TILING_DEFAULT; - uint32_t stride, size; - - assert ((width & 3) == 0); - assert ((height & 1) == 0); - cache->buffer.width = width; - cache->buffer.height = height; - - switch (format) { - case CAIRO_FORMAT_INVALID: - case CAIRO_FORMAT_A1: - case CAIRO_FORMAT_RGB24: - case CAIRO_FORMAT_RGB16_565: - ASSERT_NOT_REACHED; - case CAIRO_FORMAT_ARGB32: - cache->buffer.map0 = MAPSURF_32BIT | MT_32BIT_ARGB8888; - stride = width * 4; - break; - case CAIRO_FORMAT_A8: - cache->buffer.map0 = MAPSURF_8BIT | MT_8BIT_I8; - stride = width; - break; - } - assert ((stride & 7) == 0); - assert (i915_tiling_stride (tiling, stride) == stride); - assert (i915_tiling_height (tiling, height) == height); - - size = height * stride; - assert (i915_tiling_size (tiling, size) == size); - cache->buffer.bo = intel_bo_create (&device->intel, size, size, FALSE, tiling, stride); - if (unlikely (cache->buffer.bo == NULL)) - return _cairo_error (CAIRO_STATUS_NO_MEMORY); - - cache->buffer.stride = cache->buffer.bo->stride; - - cache->buffer.map0 |= ((height - 1) << MS3_HEIGHT_SHIFT) | - ((width - 1) << MS3_WIDTH_SHIFT); - cache->buffer.map0 |= MS3_tiling (tiling); - cache->buffer.map1 = ((stride / 4) - 1) << MS4_PITCH_SHIFT; - - cache->ref_count = 0; - cairo_list_init (&cache->link); - - return CAIRO_STATUS_SUCCESS; -} - -i915_surface_t * -i915_surface_create_from_cacheable_image_internal (i915_device_t *device, - cairo_image_surface_t *image) -{ - i915_surface_t *surface; - cairo_status_t status; - cairo_list_t *caches; - intel_buffer_cache_t *cache; - cairo_rtree_node_t *node; - cairo_format_t format; - int width, height, bpp; - - format = image->format; - if (format == CAIRO_FORMAT_A1) - format = CAIRO_FORMAT_A8; - - width = image->width; - height = image->height; - if (width > IMAGE_CACHE_WIDTH/2 || height > IMAGE_CACHE_HEIGHT/2) { - surface = (i915_surface_t *) - i915_surface_create_internal (&device->intel.base, - format, - width, height, - I915_TILING_NONE, FALSE); - if (unlikely (surface->intel.drm.base.status)) - return surface; - - status = intel_bo_put_image (&device->intel, - to_intel_bo (surface->intel.drm.bo), - image, - 0, 0, - width, height, - 0, 0); - - if (unlikely (status)) { - cairo_surface_destroy (&surface->intel.drm.base); - return (i915_surface_t *) _cairo_surface_create_in_error (status); - } - - return surface; - } - - status = cairo_device_acquire (&device->intel.base.base); - if (unlikely (status)) - return (i915_surface_t *) _cairo_surface_create_in_error (status); - - switch (image->format) { - case CAIRO_FORMAT_ARGB32: - case CAIRO_FORMAT_RGB24: - case CAIRO_FORMAT_RGB16_565: - caches = &device->image_caches[0]; - format = CAIRO_FORMAT_ARGB32; - bpp = 4; - break; - case CAIRO_FORMAT_A8: - case CAIRO_FORMAT_A1: - caches = &device->image_caches[1]; - format = CAIRO_FORMAT_A8; - bpp = 1; - break; - case CAIRO_FORMAT_INVALID: - default: - ASSERT_NOT_REACHED; - status = _cairo_error (CAIRO_STATUS_INVALID_FORMAT); - goto CLEANUP_DEVICE; - } - - node = NULL; - cairo_list_foreach_entry (cache, intel_buffer_cache_t, caches, link) { - if (! intel_bo_is_inactive (&device->intel, cache->buffer.bo)) - continue; - - status = _cairo_rtree_insert (&cache->rtree, width, height, &node); - if (unlikely (_cairo_status_is_error (status))) - goto CLEANUP_DEVICE; - if (status == CAIRO_STATUS_SUCCESS) - break; - } - if (node == NULL) { - cache = _cairo_malloc (sizeof (intel_buffer_cache_t)); - if (unlikely (cache == NULL)) { - status = _cairo_error (CAIRO_STATUS_NO_MEMORY); - goto CLEANUP_DEVICE; - } - - status = i915_buffer_cache_init (cache, device, format, - IMAGE_CACHE_WIDTH, - IMAGE_CACHE_HEIGHT); - if (unlikely (status)) { - free (cache); - goto CLEANUP_DEVICE; - } - - _cairo_rtree_init (&cache->rtree, - IMAGE_CACHE_WIDTH, - IMAGE_CACHE_HEIGHT, - 4, - sizeof (i915_image_private_t)); - - status = _cairo_rtree_insert (&cache->rtree, width, height, &node); - assert (status == CAIRO_STATUS_SUCCESS); - - cairo_list_init (&cache->link); - } - cairo_list_move (&cache->link, caches); - ((i915_image_private_t *) node)->container = cache; - - status = intel_bo_put_image (&device->intel, - cache->buffer.bo, - image, - 0, 0, - width, height, - node->x, node->y); - if (unlikely (status)) - goto CLEANUP_CACHE; - - surface = _cairo_malloc (sizeof (i915_surface_t)); - if (unlikely (surface == NULL)) { - status = _cairo_error (CAIRO_STATUS_NO_MEMORY); - goto CLEANUP_CACHE; - } - - i915_surface_init (surface, &device->intel.base, - format, width, height); - - surface->intel.drm.stride = cache->buffer.stride; - - surface->map0 |= MS3_tiling (cache->buffer.bo->tiling); - surface->map1 = (surface->intel.drm.stride/4 - 1) << MS4_PITCH_SHIFT; - - surface->intel.drm.bo = &intel_bo_reference (cache->buffer.bo)->base; - surface->offset = node->y * cache->buffer.stride + bpp * node->x; - - surface->cache = (i915_image_private_t *) node; - cache->ref_count++; - - cairo_device_release (&device->intel.base.base); - - return surface; - -CLEANUP_CACHE: - _cairo_rtree_node_destroy (&cache->rtree, node); - if (cache->ref_count == 0) { - intel_bo_destroy (&device->intel, cache->buffer.bo); - _cairo_rtree_fini (&cache->rtree); - cairo_list_del (&cache->link); - free (cache); - } -CLEANUP_DEVICE: - cairo_device_release (&device->intel.base.base); - return (i915_surface_t *) _cairo_surface_create_in_error (status); -} - -static cairo_surface_t * -i915_surface_create_from_cacheable_image (cairo_drm_device_t *device, - cairo_surface_t *source) -{ - i915_surface_t *surface; - cairo_image_surface_t *image; - void *image_extra; - cairo_status_t status; - - status = _cairo_surface_acquire_source_image (source, &image, &image_extra); - if (unlikely (status)) - return _cairo_surface_create_in_error (status); - - surface = i915_surface_create_from_cacheable_image_internal ((i915_device_t *) device, image); - - _cairo_surface_release_source_image (source, image, image_extra); - - return &surface->intel.drm.base; -} - -static cairo_status_t -i915_surface_enable_scan_out (void *abstract_surface) -{ - i915_surface_t *surface = abstract_surface; - intel_bo_t *bo; - cairo_status_t status; - - if (unlikely (surface->intel.drm.bo == NULL)) - return _cairo_error (CAIRO_STATUS_INVALID_SIZE); - - bo = to_intel_bo (surface->intel.drm.bo); - if (bo->tiling == I915_TILING_Y) { - status = i915_surface_batch_flush (surface); - if (unlikely (status)) - return status; - - bo->tiling = I915_TILING_X; - surface->map0 &= ~MS3_tiling (I915_TILING_Y); - surface->map0 |= MS3_tiling (I915_TILING_X); - } - - - return CAIRO_STATUS_SUCCESS; -} - -static cairo_int_status_t -i915_device_flush (cairo_drm_device_t *device) -{ - cairo_status_t status; - - if (unlikely (device->base.finished)) - return CAIRO_STATUS_SUCCESS; - - status = cairo_device_acquire (&device->base); - if (likely (status == CAIRO_STATUS_SUCCESS)) { - status = i915_batch_flush ((i915_device_t *) device); - cairo_device_release (&device->base); - } - - return status; -} - -static cairo_int_status_t -i915_device_throttle (cairo_drm_device_t *device) -{ - cairo_status_t status; - - status = cairo_device_acquire (&device->base); - if (unlikely (status)) - return status; - - status = i915_batch_flush ((i915_device_t *) device); - intel_throttle ((intel_device_t *) device); - - cairo_device_release (&device->base); - - return status; -} - -static void -i915_device_destroy (void *data) -{ - i915_device_t *device = data; - - if (device->last_vbo) - intel_bo_destroy (&device->intel, device->last_vbo); - - i915_batch_cleanup (device); - - intel_device_fini (&device->intel); - free (device); -} - -COMPILE_TIME_ASSERT (sizeof (i915_batch_setup) == sizeof (((i915_device_t *)0)->batch_header)); -COMPILE_TIME_ASSERT (offsetof (i915_device_t, batch_base) == offsetof (i915_device_t, batch_header) + sizeof (i915_batch_setup)); - -cairo_drm_device_t * -_cairo_drm_i915_device_create (int fd, dev_t dev_id, int vendor_id, int chip_id) -{ - i915_device_t *device; - cairo_status_t status; - uint64_t gtt_size; - int n; - - if (! intel_info (fd, >t_size)) - return NULL; - - device = _cairo_malloc (sizeof (i915_device_t)); - if (device == NULL) - return (cairo_drm_device_t *) _cairo_device_create_in_error (CAIRO_STATUS_NO_MEMORY); - - status = intel_device_init (&device->intel, fd); - if (unlikely (status)) { - free (device); - return (cairo_drm_device_t *) _cairo_device_create_in_error (status); - } - - device->debug = 0; - if (getenv ("CAIRO_DEBUG_DRM") != NULL) - device->debug = I915_DEBUG_SYNC; - - n = intel_get (fd, I915_PARAM_NUM_FENCES_AVAIL); - if (n == 0) - n = 8; - device->batch.fences_avail = n - 2; /* conservative */ - - device->batch.gtt_avail_size = device->intel.gtt_avail_size / 4; - device->batch.est_gtt_size = I915_BATCH_SIZE; - device->batch.total_gtt_size = I915_BATCH_SIZE; - device->batch.exec_count = 0; - device->batch.reloc_count = 0; - device->batch.used = 0; - device->batch.fences = 0; - - memcpy (device->batch_header, i915_batch_setup, sizeof (i915_batch_setup)); - device->vbo = 0; - device->vbo_offset = 0; - device->vbo_used = 0; - device->vertex_index = 0; - device->vertex_count = 0; - device->last_vbo = NULL; - - for (n = 0; n < ARRAY_LENGTH (device->image_caches); n++) - cairo_list_init (&device->image_caches[n]); - - device->intel.base.surface.create = i915_surface_create; - device->intel.base.surface.create_for_name = i915_surface_create_for_name; - device->intel.base.surface.create_from_cacheable_image = i915_surface_create_from_cacheable_image; - - device->intel.base.surface.flink = _cairo_drm_surface_flink; - device->intel.base.surface.enable_scan_out = i915_surface_enable_scan_out; - device->intel.base.surface.map_to_image = intel_surface_map_to_image; - - device->intel.base.device.flush = i915_device_flush; - device->intel.base.device.throttle = i915_device_throttle; - device->intel.base.device.destroy = i915_device_destroy; - - device->floats_per_vertex = 0; - device->current_source = NULL; - device->current_mask = NULL; - device->current_clip = NULL; - - i915_device_reset (device); - - return _cairo_drm_device_init (&device->intel.base, - fd, dev_id, vendor_id, chip_id, - 16*1024); -} diff --git a/gfx/cairo/cairo/src/drm/cairo-drm-i965-glyphs.c b/gfx/cairo/cairo/src/drm/cairo-drm-i965-glyphs.c deleted file mode 100644 index 1ef0a6f59e..0000000000 --- a/gfx/cairo/cairo/src/drm/cairo-drm-i965-glyphs.c +++ /dev/null @@ -1,504 +0,0 @@ -/* cairo - a vector graphics library with display and print output - * - * Copyright © 2009 Intel Corporation - * - * This library is free software; you can redistribute it and/or - * modify it either under the terms of the GNU Lesser General Public - * License version 2.1 as published by the Free Software Foundation - * (the "LGPL") or, at your option, under the terms of the Mozilla - * Public License Version 1.1 (the "MPL"). If you do not alter this - * notice, a recipient may use your version of this file under either - * the MPL or the LGPL. - * - * You should have received a copy of the LGPL along with this library - * in the file COPYING-LGPL-2.1; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Suite 500, Boston, MA 02110-1335, 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): - * Chris Wilson <chris@chris-wilson.co.uk> - */ - -#include "cairoint.h" - -#include "cairo-composite-rectangles-private.h" -#include "cairo-drm-i965-private.h" -#include "cairo-error-private.h" -#include "cairo-rtree-private.h" - -typedef struct _i965_glyphs i965_glyphs_t; - -typedef float * -(*i965_get_rectangle_func_t) (i965_glyphs_t *glyphs); - -struct _i965_glyphs { - i965_get_rectangle_func_t get_rectangle; - i965_shader_t shader; - - struct i965_vbo head, *tail; - - unsigned int vbo_offset; - float *vbo_base; -}; - -static float * -i965_glyphs_emit_rectangle (i965_glyphs_t *glyphs) -{ - return i965_add_rectangle (glyphs->shader.device); -} - -static float * -i965_glyphs_accumulate_rectangle (i965_glyphs_t *glyphs) -{ - float *vertices; - uint32_t size; - - size = glyphs->shader.device->rectangle_size; - if (unlikely (glyphs->vbo_offset + size > I965_VERTEX_SIZE)) { - struct i965_vbo *vbo; - - vbo = _cairo_malloc (sizeof (struct i965_vbo)); - if (unlikely (vbo == NULL)) { - /* throw error! */ - } - - glyphs->tail->next = vbo; - glyphs->tail = vbo; - - vbo->next = NULL; - vbo->bo = intel_bo_create (&glyphs->shader.device->intel, - I965_VERTEX_SIZE, I965_VERTEX_SIZE, - FALSE, I915_TILING_NONE, 0); - vbo->count = 0; - - glyphs->vbo_offset = 0; - glyphs->vbo_base = intel_bo_map (&glyphs->shader.device->intel, vbo->bo); - } - - vertices = glyphs->vbo_base + glyphs->vbo_offset; - glyphs->vbo_offset += size; - glyphs->tail->count += 3; - - return vertices; -} - -static void -i965_add_glyph_rectangle (i965_glyphs_t *glyphs, - int x1, int y1, - int x2, int y2, - intel_glyph_t *glyph) -{ - float *v; - - /* Each vertex is: - * 2 vertex coordinates - * 1 glyph texture coordinate - */ - - v = glyphs->get_rectangle (glyphs); - - /* bottom right */ - *v++ = x2; *v++ = y2; - *v++ = glyph->texcoord[0]; - - /* bottom left */ - *v++ = x1; *v++ = y2; - *v++ = glyph->texcoord[1]; - - /* top left */ - *v++ = x1; *v++ = y1; - *v++ = glyph->texcoord[2]; -} - -static cairo_status_t -i965_surface_mask_internal (i965_surface_t *dst, - cairo_operator_t op, - const cairo_pattern_t *source, - i965_surface_t *mask, - cairo_clip_t *clip, - const cairo_composite_rectangles_t *extents) -{ - i965_device_t *device; - i965_shader_t shader; - cairo_region_t *clip_region = NULL; - cairo_status_t status; - - i965_shader_init (&shader, dst, op); - - status = i965_shader_acquire_pattern (&shader, &shader.source, - source, &extents->bounded); - if (unlikely (status)) - return status; - - shader.mask.type.vertex = VS_NONE; - shader.mask.type.fragment = FS_SURFACE; - shader.mask.base.content = mask->intel.drm.base.content; - shader.mask.base.filter = i965_filter (CAIRO_FILTER_NEAREST); - shader.mask.base.extend = i965_extend (CAIRO_EXTEND_NONE); - - cairo_matrix_init_translate (&shader.mask.base.matrix, - -extents->bounded.x, - -extents->bounded.y); - cairo_matrix_scale (&shader.mask.base.matrix, - 1. / mask->intel.drm.width, - 1. / mask->intel.drm.height); - - shader.mask.base.bo = to_intel_bo (mask->intel.drm.bo); - shader.mask.base.format = mask->intel.drm.format; - shader.mask.base.width = mask->intel.drm.width; - shader.mask.base.height = mask->intel.drm.height; - shader.mask.base.stride = mask->intel.drm.stride; - - if (clip != NULL) { - status = _cairo_clip_get_region (clip, &clip_region); - assert (status == CAIRO_STATUS_SUCCESS || status == CAIRO_INT_STATUS_UNSUPPORTED); - - if (clip_region != NULL && cairo_region_num_rectangles (clip_region) == 1) - clip_region = NULL; - - if (status == CAIRO_INT_STATUS_UNSUPPORTED) - i965_shader_set_clip (&shader, clip); - } - - status = cairo_device_acquire (dst->intel.drm.base.device); - if (unlikely (status)) - goto CLEANUP_SHADER; - - device = i965_device (dst); - - status = i965_shader_commit (&shader, device); - if (unlikely (status)) - goto CLEANUP_DEVICE; - - if (clip_region != NULL) { - unsigned int n, num_rectangles; - - num_rectangles = cairo_region_num_rectangles (clip_region); - for (n = 0; n < num_rectangles; n++) { - cairo_rectangle_int_t rect; - - cairo_region_get_rectangle (clip_region, n, &rect); - - i965_shader_add_rectangle (&shader, - rect.x, rect.y, - rect.width, rect.height); - } - } else { - i965_shader_add_rectangle (&shader, - extents->bounded.x, - extents->bounded.y, - extents->bounded.width, - extents->bounded.height); - } - - if (! extents->is_bounded) - status = i965_fixup_unbounded (dst, extents, clip); - - CLEANUP_DEVICE: - cairo_device_release (&device->intel.base.base); - CLEANUP_SHADER: - i965_shader_fini (&shader); - return status; -} - -cairo_int_status_t -i965_surface_glyphs (void *abstract_surface, - cairo_operator_t op, - const cairo_pattern_t *source, - cairo_glyph_t *g, - int num_glyphs, - cairo_scaled_font_t *scaled_font, - cairo_clip_t *clip, - int *num_remaining) -{ - i965_surface_t *surface = abstract_surface; - i965_surface_t *mask = NULL; - i965_device_t *device; - i965_glyphs_t glyphs; - cairo_composite_rectangles_t extents; - cairo_clip_t local_clip; - cairo_bool_t have_clip = FALSE; - cairo_bool_t overlap; - cairo_region_t *clip_region = NULL; - intel_bo_t *last_bo = NULL; - cairo_scaled_glyph_t *glyph_cache[64]; - cairo_status_t status; - int mask_x = 0, mask_y = 0; - int i = 0; - - *num_remaining = 0; - status = _cairo_composite_rectangles_init_for_glyphs (&extents, - surface->intel.drm.width, - surface->intel.drm.height, - op, source, - scaled_font, - g, num_glyphs, - clip, - &overlap); - if (unlikely (status)) - return status; - - if (clip != NULL && _cairo_clip_contains_rectangle (clip, &extents.mask)) - clip = NULL; - - if (clip != NULL && extents.is_bounded) { - clip = _cairo_clip_init_copy (&local_clip, clip); - status = _cairo_clip_rectangle (clip, &extents.bounded); - if (unlikely (status)) - return status; - - have_clip = TRUE; - } - - if (overlap || ! extents.is_bounded) { - cairo_format_t format; - - format = CAIRO_FORMAT_A8; - if (scaled_font->options.antialias == CAIRO_ANTIALIAS_SUBPIXEL) - format = CAIRO_FORMAT_ARGB32; - - mask = (i965_surface_t *) - i965_surface_create_internal (&i965_device (surface)->intel.base, - format, - extents.bounded.width, - extents.bounded.height, - I965_TILING_DEFAULT, - TRUE); - if (unlikely (mask->intel.drm.base.status)) - return mask->intel.drm.base.status; - - status = _cairo_surface_paint (&mask->intel.drm.base, - CAIRO_OPERATOR_CLEAR, - &_cairo_pattern_clear.base, - NULL); - if (unlikely (status)) { - cairo_surface_destroy (&mask->intel.drm.base); - return status; - } - - i965_shader_init (&glyphs.shader, mask, CAIRO_OPERATOR_ADD); - - status = i965_shader_acquire_pattern (&glyphs.shader, &glyphs.shader.source, - &_cairo_pattern_white.base, - &extents.bounded); - if (unlikely (status)) { - cairo_surface_destroy (&mask->intel.drm.base); - return status; - } - - mask_x = -extents.bounded.x; - mask_y = -extents.bounded.y; - } else { - i965_shader_init (&glyphs.shader, surface, op); - - status = i965_shader_acquire_pattern (&glyphs.shader, &glyphs.shader.source, - source, &extents.bounded); - if (unlikely (status)) - return status; - - if (clip != NULL) { - status = _cairo_clip_get_region (clip, &clip_region); - assert (status == CAIRO_STATUS_SUCCESS || status == CAIRO_INT_STATUS_UNSUPPORTED); - - if (status == CAIRO_INT_STATUS_UNSUPPORTED) - i965_shader_set_clip (&glyphs.shader, clip); - } - } - - glyphs.head.next = NULL; - glyphs.head.bo = NULL; - glyphs.head.count = 0; - glyphs.tail = &glyphs.head; - - device = i965_device (surface); - if (mask != NULL || clip_region == NULL) { - glyphs.get_rectangle = i965_glyphs_emit_rectangle; - } else { - glyphs.get_rectangle = i965_glyphs_accumulate_rectangle; - glyphs.head.bo = intel_bo_create (&device->intel, - I965_VERTEX_SIZE, I965_VERTEX_SIZE, - FALSE, I915_TILING_NONE, 0); - if (unlikely (glyphs.head.bo == NULL)) - return _cairo_error (CAIRO_STATUS_NO_MEMORY); - - glyphs.vbo_base = intel_bo_map (&device->intel, glyphs.head.bo); - } - glyphs.vbo_offset = 0; - - status = cairo_device_acquire (&device->intel.base.base); - if (unlikely (status)) - goto CLEANUP_GLYPHS; - - _cairo_scaled_font_freeze_cache (scaled_font); - //private = _cairo_scaled_font_get_device (scaled_font, device); - if (scaled_font->surface_private == NULL) { - scaled_font->surface_private = device; - scaled_font->surface_backend = surface->intel.drm.base.backend; - cairo_list_add (&scaled_font->link, &device->intel.fonts); - } - - memset (glyph_cache, 0, sizeof (glyph_cache)); - - for (i = 0; i < num_glyphs; i++) { - cairo_scaled_glyph_t *scaled_glyph; - int x, y, x1, x2, y1, y2; - int cache_index = g[i].index % ARRAY_LENGTH (glyph_cache); - intel_glyph_t *glyph; - - scaled_glyph = glyph_cache[cache_index]; - if (scaled_glyph == NULL || - _cairo_scaled_glyph_index (scaled_glyph) != g[i].index) - { - status = _cairo_scaled_glyph_lookup (scaled_font, - g[i].index, - CAIRO_SCALED_GLYPH_INFO_METRICS, - &scaled_glyph); - if (unlikely (status)) - goto FINISH; - - glyph_cache[cache_index] = scaled_glyph; - } - - if (unlikely (scaled_glyph->metrics.width == 0 || - scaled_glyph->metrics.height == 0)) - { - continue; - } - - /* XXX glyph images are snapped to pixel locations */ - x = _cairo_lround (g[i].x); - y = _cairo_lround (g[i].y); - - x1 = x + _cairo_fixed_integer_floor (scaled_glyph->bbox.p1.x); - y1 = y + _cairo_fixed_integer_floor (scaled_glyph->bbox.p1.y); - x2 = x + _cairo_fixed_integer_ceil (scaled_glyph->bbox.p2.x); - y2 = y + _cairo_fixed_integer_ceil (scaled_glyph->bbox.p2.y); - - if (x2 < extents.bounded.x || - y2 < extents.bounded.y || - x1 > extents.bounded.x + extents.bounded.width || - y1 > extents.bounded.y + extents.bounded.height) - { - continue; - } - - if (scaled_glyph->surface_private == NULL) { - status = intel_get_glyph (&device->intel, scaled_font, scaled_glyph); - if (unlikely (status == CAIRO_INT_STATUS_NOTHING_TO_DO)) { - status = CAIRO_STATUS_SUCCESS; - continue; - } - if (unlikely (status)) - goto FINISH; - } - glyph = intel_glyph_pin (scaled_glyph->surface_private); - - if (glyph->cache->buffer.bo != last_bo) { - intel_buffer_cache_t *cache = glyph->cache; - - glyphs.shader.mask.type.vertex = VS_GLYPHS; - glyphs.shader.mask.type.fragment = FS_GLYPHS; - glyphs.shader.mask.type.pattern = PATTERN_BASE; - - glyphs.shader.mask.base.bo = cache->buffer.bo; - glyphs.shader.mask.base.format = cache->buffer.format; - glyphs.shader.mask.base.width = cache->buffer.width; - glyphs.shader.mask.base.height = cache->buffer.height; - glyphs.shader.mask.base.stride = cache->buffer.stride; - glyphs.shader.mask.base.filter = i965_filter (CAIRO_FILTER_NEAREST); - glyphs.shader.mask.base.extend = i965_extend (CAIRO_EXTEND_NONE); - glyphs.shader.mask.base.content = CAIRO_CONTENT_ALPHA; /* XXX */ - - glyphs.shader.committed = FALSE; - status = i965_shader_commit (&glyphs.shader, device); - if (unlikely (status)) - goto FINISH; - - last_bo = cache->buffer.bo; - } - - x2 = x1 + glyph->width; - y2 = y1 + glyph->height; - - if (mask_x) - x1 += mask_x, x2 += mask_x; - if (mask_y) - y1 += mask_y, y2 += mask_y; - - i965_add_glyph_rectangle (&glyphs, x1, y1, x2, y2, glyph); - } - - if (mask != NULL && clip_region != NULL) - i965_clipped_vertices (device, &glyphs.head, clip_region); - - status = CAIRO_STATUS_SUCCESS; - FINISH: - _cairo_scaled_font_thaw_cache (scaled_font); - cairo_device_release (surface->intel.drm.base.device); - CLEANUP_GLYPHS: - i965_shader_fini (&glyphs.shader); - - if (glyphs.head.bo != NULL) { - struct i965_vbo *vbo, *next; - - intel_bo_destroy (&device->intel, glyphs.head.bo); - for (vbo = glyphs.head.next; vbo != NULL; vbo = next) { - next = vbo->next; - intel_bo_destroy (&device->intel, vbo->bo); - free (vbo); - } - } - - if (unlikely (status == CAIRO_INT_STATUS_UNSUPPORTED)) { - cairo_path_fixed_t path; - - _cairo_path_fixed_init (&path); - status = _cairo_scaled_font_glyph_path (scaled_font, - g + i, num_glyphs - i, - &path); - if (mask_x | mask_y) { - _cairo_path_fixed_translate (&path, - _cairo_fixed_from_int (mask_x), - _cairo_fixed_from_int (mask_y)); - } - if (likely (status == CAIRO_STATUS_SUCCESS)) { - status = surface->intel.drm.base.backend->fill (glyphs.shader.target, - glyphs.shader.op, - mask != NULL ? &_cairo_pattern_white.base : source, - &path, - CAIRO_FILL_RULE_WINDING, - 0, - scaled_font->options.antialias, - clip); - } - _cairo_path_fixed_fini (&path); - } - - if (mask != NULL) { - if (likely (status == CAIRO_STATUS_SUCCESS)) { - status = i965_surface_mask_internal (surface, op, source, mask, - clip, &extents); - } - cairo_surface_finish (&mask->intel.drm.base); - cairo_surface_destroy (&mask->intel.drm.base); - } - - if (have_clip) - _cairo_clip_fini (&local_clip); - - return status; -} diff --git a/gfx/cairo/cairo/src/drm/cairo-drm-i965-private.h b/gfx/cairo/cairo/src/drm/cairo-drm-i965-private.h deleted file mode 100644 index 79568a63d7..0000000000 --- a/gfx/cairo/cairo/src/drm/cairo-drm-i965-private.h +++ /dev/null @@ -1,737 +0,0 @@ -#ifndef CAIRO_DRM_I965_PRIVATE_H -#define CAIRO_DRM_I965_PRIVATE_H - -#include "cairo-drm-intel-private.h" - -#include "cairo-hash-private.h" -#include "cairo-freelist-private.h" - -#include "cairo-drm-intel-brw-defines.h" - -#include <setjmp.h> - -#define BRW_MI_GLOBAL_SNAPSHOT_RESET (1 << 3) - -/* - * New regs for broadwater -- we need to split this file up sensibly somehow. - */ -#define BRW_3D(Pipeline,Opcode,Subopcode) ((3 << 29) | \ - ((Pipeline) << 27) | \ - ((Opcode) << 24) | \ - ((Subopcode) << 16)) - -#define BRW_URB_FENCE BRW_3D(0, 0, 0) -#define BRW_CS_URB_STATE BRW_3D(0, 0, 1) -#define BRW_CONSTANT_BUFFER BRW_3D(0, 0, 2) -#define BRW_STATE_PREFETCH BRW_3D(0, 0, 3) - -#define BRW_STATE_BASE_ADDRESS BRW_3D(0, 1, 1) -#define BRW_STATE_SIP BRW_3D(0, 1, 2) -#define BRW_PIPELINE_SELECT BRW_3D(0, 1, 4) - -#define NEW_PIPELINE_SELECT BRW_3D(1, 1, 4) - -#define BRW_MEDIA_STATE_POINTERS BRW_3D(2, 0, 0) -#define BRW_MEDIA_OBJECT BRW_3D(2, 1, 0) - -#define BRW_3DSTATE_PIPELINED_POINTERS BRW_3D(3, 0, 0) -#define BRW_3DSTATE_BINDING_TABLE_POINTERS BRW_3D(3, 0, 1) -#define BRW_3DSTATE_VERTEX_BUFFERS BRW_3D(3, 0, 8) -#define BRW_3DSTATE_VERTEX_ELEMENTS BRW_3D(3, 0, 9) -#define BRW_3DSTATE_INDEX_BUFFER BRW_3D(3, 0, 0xa) -#define BRW_3DSTATE_VF_STATISTICS BRW_3D(3, 0, 0xb) - -#define BRW_3DSTATE_DRAWING_RECTANGLE BRW_3D(3, 1, 0) -#define BRW_3DSTATE_CONSTANT_COLOR BRW_3D(3, 1, 1) -#define BRW_3DSTATE_SAMPLER_PALETTE_LOAD BRW_3D(3, 1, 2) -#define BRW_3DSTATE_CHROMA_KEY BRW_3D(3, 1, 4) -#define BRW_3DSTATE_DEPTH_BUFFER BRW_3D(3, 1, 5) -#define BRW_3DSTATE_POLY_STIPPLE_OFFSET BRW_3D(3, 1, 6) -#define BRW_3DSTATE_POLY_STIPPLE_PATTERN BRW_3D(3, 1, 7) -#define BRW_3DSTATE_LINE_STIPPLE BRW_3D(3, 1, 8) -#define BRW_3DSTATE_GLOBAL_DEPTH_OFFSET_CLAMP BRW_3D(3, 1, 9) -/* These two are BLC and CTG only, not BW or CL */ -#define BRW_3DSTATE_AA_LINE_PARAMS BRW_3D(3, 1, 0xa) -#define BRW_3DSTATE_GS_SVB_INDEX BRW_3D(3, 1, 0xb) - -#define BRW_PIPE_CONTROL BRW_3D(3, 2, 0) - -#define BRW_3DPRIMITIVE BRW_3D(3, 3, 0) - -#define PIPELINE_SELECT_3D 0 -#define PIPELINE_SELECT_MEDIA 1 - -#define UF0_CS_REALLOC (1 << 13) -#define UF0_VFE_REALLOC (1 << 12) -#define UF0_SF_REALLOC (1 << 11) -#define UF0_CLIP_REALLOC (1 << 10) -#define UF0_GS_REALLOC (1 << 9) -#define UF0_VS_REALLOC (1 << 8) -#define UF1_CLIP_FENCE_SHIFT 20 -#define UF1_GS_FENCE_SHIFT 10 -#define UF1_VS_FENCE_SHIFT 0 -#define UF2_CS_FENCE_SHIFT 20 -#define UF2_VFE_FENCE_SHIFT 10 -#define UF2_SF_FENCE_SHIFT 0 - -/* for BRW_STATE_BASE_ADDRESS */ -#define BASE_ADDRESS_MODIFY (1 << 0) - -/* for BRW_3DSTATE_PIPELINED_POINTERS */ -#define BRW_GS_DISABLE 0 -#define BRW_GS_ENABLE 1 -#define BRW_CLIP_DISABLE 0 -#define BRW_CLIP_ENABLE 1 - -/* for BRW_PIPE_CONTROL */ -#define BRW_PIPE_CONTROL_NOWRITE (0 << 14) -#define BRW_PIPE_CONTROL_WRITE_QWORD (1 << 14) -#define BRW_PIPE_CONTROL_WRITE_DEPTH (2 << 14) -#define BRW_PIPE_CONTROL_WRITE_TIME (3 << 14) -#define BRW_PIPE_CONTROL_DEPTH_STALL (1 << 13) -#define BRW_PIPE_CONTROL_WC_FLUSH (1 << 12) -#define BRW_PIPE_CONTROL_IS_FLUSH (1 << 11) -#define BRW_PIPE_CONTROL_NOTIFY_ENABLE (1 << 8) -#define BRW_PIPE_CONTROL_GLOBAL_GTT (1 << 2) -#define BRW_PIPE_CONTROL_LOCAL_PGTT (0 << 2) - -/* VERTEX_BUFFER_STATE Structure */ -#define VB0_BUFFER_INDEX_SHIFT 27 -#define VB0_VERTEXDATA (0 << 26) -#define VB0_INSTANCEDATA (1 << 26) -#define VB0_BUFFER_PITCH_SHIFT 0 - -/* VERTEX_ELEMENT_STATE Structure */ -#define VE0_VERTEX_BUFFER_INDEX_SHIFT 27 -#define VE0_VALID (1 << 26) -#define VE0_FORMAT_SHIFT 16 -#define VE0_OFFSET_SHIFT 0 -#define VE1_VFCOMPONENT_0_SHIFT 28 -#define VE1_VFCOMPONENT_1_SHIFT 24 -#define VE1_VFCOMPONENT_2_SHIFT 20 -#define VE1_VFCOMPONENT_3_SHIFT 16 -#define VE1_DESTINATION_ELEMENT_OFFSET_SHIFT 0 - -/* 3DPRIMITIVE bits */ -#define BRW_3DPRIMITIVE_VERTEX_SEQUENTIAL (0 << 15) -#define BRW_3DPRIMITIVE_VERTEX_RANDOM (1 << 15) -/* Primitive types are in brw_defines.h */ -#define BRW_3DPRIMITIVE_TOPOLOGY_SHIFT 10 - -#define BRW_SVG_CTL 0x7400 - -#define BRW_SVG_CTL_GS_BA (0 << 8) -#define BRW_SVG_CTL_SS_BA (1 << 8) -#define BRW_SVG_CTL_IO_BA (2 << 8) -#define BRW_SVG_CTL_GS_AUB (3 << 8) -#define BRW_SVG_CTL_IO_AUB (4 << 8) -#define BRW_SVG_CTL_SIP (5 << 8) - -#define BRW_SVG_RDATA 0x7404 -#define BRW_SVG_WORK_CTL 0x7408 - -#define BRW_VF_CTL 0x7500 - -#define BRW_VF_CTL_SNAPSHOT_COMPLETE (1 << 31) -#define BRW_VF_CTL_SNAPSHOT_MUX_SELECT_THREADID (0 << 8) -#define BRW_VF_CTL_SNAPSHOT_MUX_SELECT_VF_DEBUG (1 << 8) -#define BRW_VF_CTL_SNAPSHOT_TYPE_VERTEX_SEQUENCE (0 << 4) -#define BRW_VF_CTL_SNAPSHOT_TYPE_VERTEX_INDEX (1 << 4) -#define BRW_VF_CTL_SKIP_INITIAL_PRIMITIVES (1 << 3) -#define BRW_VF_CTL_MAX_PRIMITIVES_LIMIT_ENABLE (1 << 2) -#define BRW_VF_CTL_VERTEX_RANGE_LIMIT_ENABLE (1 << 1) -#define BRW_VF_CTL_SNAPSHOT_ENABLE (1 << 0) - -#define BRW_VF_STRG_VAL 0x7504 -#define BRW_VF_STR_VL_OVR 0x7508 -#define BRW_VF_VC_OVR 0x750c -#define BRW_VF_STR_PSKIP 0x7510 -#define BRW_VF_MAX_PRIM 0x7514 -#define BRW_VF_RDATA 0x7518 - -#define BRW_VS_CTL 0x7600 -#define BRW_VS_CTL_SNAPSHOT_COMPLETE (1 << 31) -#define BRW_VS_CTL_SNAPSHOT_MUX_VERTEX_0 (0 << 8) -#define BRW_VS_CTL_SNAPSHOT_MUX_VERTEX_1 (1 << 8) -#define BRW_VS_CTL_SNAPSHOT_MUX_VALID_COUNT (2 << 8) -#define BRW_VS_CTL_SNAPSHOT_MUX_VS_KERNEL_POINTER (3 << 8) -#define BRW_VS_CTL_SNAPSHOT_ALL_THREADS (1 << 2) -#define BRW_VS_CTL_THREAD_SNAPSHOT_ENABLE (1 << 1) -#define BRW_VS_CTL_SNAPSHOT_ENABLE (1 << 0) - -#define BRW_VS_STRG_VAL 0x7604 -#define BRW_VS_RDATA 0x7608 - -#define BRW_SF_CTL 0x7b00 -#define BRW_SF_CTL_SNAPSHOT_COMPLETE (1 << 31) -#define BRW_SF_CTL_SNAPSHOT_MUX_VERTEX_0_FF_ID (0 << 8) -#define BRW_SF_CTL_SNAPSHOT_MUX_VERTEX_0_REL_COUNT (1 << 8) -#define BRW_SF_CTL_SNAPSHOT_MUX_VERTEX_1_FF_ID (2 << 8) -#define BRW_SF_CTL_SNAPSHOT_MUX_VERTEX_1_REL_COUNT (3 << 8) -#define BRW_SF_CTL_SNAPSHOT_MUX_VERTEX_2_FF_ID (4 << 8) -#define BRW_SF_CTL_SNAPSHOT_MUX_VERTEX_2_REL_COUNT (5 << 8) -#define BRW_SF_CTL_SNAPSHOT_MUX_VERTEX_COUNT (6 << 8) -#define BRW_SF_CTL_SNAPSHOT_MUX_SF_KERNEL_POINTER (7 << 8) -#define BRW_SF_CTL_MIN_MAX_PRIMITIVE_RANGE_ENABLE (1 << 4) -#define BRW_SF_CTL_DEBUG_CLIP_RECTANGLE_ENABLE (1 << 3) -#define BRW_SF_CTL_SNAPSHOT_ALL_THREADS (1 << 2) -#define BRW_SF_CTL_THREAD_SNAPSHOT_ENABLE (1 << 1) -#define BRW_SF_CTL_SNAPSHOT_ENABLE (1 << 0) - -#define BRW_SF_STRG_VAL 0x7b04 -#define BRW_SF_RDATA 0x7b18 - -#define BRW_WIZ_CTL 0x7c00 -#define BRW_WIZ_CTL_SNAPSHOT_COMPLETE (1 << 31) -#define BRW_WIZ_CTL_SUBSPAN_INSTANCE_SHIFT 16 -#define BRW_WIZ_CTL_SNAPSHOT_MUX_WIZ_KERNEL_POINTER (0 << 8) -#define BRW_WIZ_CTL_SNAPSHOT_MUX_SUBSPAN_INSTANCE (1 << 8) -#define BRW_WIZ_CTL_SNAPSHOT_MUX_PRIMITIVE_SEQUENCE (2 << 8) -#define BRW_WIZ_CTL_SINGLE_SUBSPAN_DISPATCH (1 << 6) -#define BRW_WIZ_CTL_IGNORE_COLOR_SCOREBOARD_STALLS (1 << 5) -#define BRW_WIZ_CTL_ENABLE_SUBSPAN_INSTANCE_COMPARE (1 << 4) -#define BRW_WIZ_CTL_USE_UPSTREAM_SNAPSHOT_FLAG (1 << 3) -#define BRW_WIZ_CTL_SNAPSHOT_ALL_THREADS (1 << 2) -#define BRW_WIZ_CTL_THREAD_SNAPSHOT_ENABLE (1 << 1) -#define BRW_WIZ_CTL_SNAPSHOT_ENABLE (1 << 0) - -#define BRW_WIZ_STRG_VAL 0x7c04 -#define BRW_WIZ_RDATA 0x7c18 - -#define BRW_TS_CTL 0x7e00 -#define BRW_TS_CTL_SNAPSHOT_COMPLETE (1 << 31) -#define BRW_TS_CTL_SNAPSHOT_MESSAGE_ERROR (0 << 8) -#define BRW_TS_CTL_SNAPSHOT_INTERFACE_DESCRIPTOR (3 << 8) -#define BRW_TS_CTL_SNAPSHOT_ALL_CHILD_THREADS (1 << 2) -#define BRW_TS_CTL_SNAPSHOT_ALL_ROOT_THREADS (1 << 1) -#define BRW_TS_CTL_SNAPSHOT_ENABLE (1 << 0) - -#define BRW_TS_STRG_VAL 0x7e04 -#define BRW_TS_RDATA 0x7e08 - -#define BRW_TD_CTL 0x8000 -#define BRW_TD_CTL_MUX_SHIFT 8 -#define BRW_TD_CTL_EXTERNAL_HALT_R0_DEBUG_MATCH (1 << 7) -#define BRW_TD_CTL_FORCE_EXTERNAL_HALT (1 << 6) -#define BRW_TD_CTL_EXCEPTION_MASK_OVERRIDE (1 << 5) -#define BRW_TD_CTL_FORCE_THREAD_BREAKPOINT_ENABLE (1 << 4) -#define BRW_TD_CTL_BREAKPOINT_ENABLE (1 << 2) -#define BRW_TD_CTL2 0x8004 -#define BRW_TD_CTL2_ILLEGAL_OPCODE_EXCEPTION_OVERRIDE (1 << 28) -#define BRW_TD_CTL2_MASKSTACK_EXCEPTION_OVERRIDE (1 << 26) -#define BRW_TD_CTL2_SOFTWARE_EXCEPTION_OVERRIDE (1 << 25) -#define BRW_TD_CTL2_ACTIVE_THREAD_LIMIT_SHIFT 16 -#define BRW_TD_CTL2_ACTIVE_THREAD_LIMIT_ENABLE (1 << 8) -#define BRW_TD_CTL2_THREAD_SPAWNER_EXECUTION_MASK_ENABLE (1 << 7) -#define BRW_TD_CTL2_WIZ_EXECUTION_MASK_ENABLE (1 << 6) -#define BRW_TD_CTL2_SF_EXECUTION_MASK_ENABLE (1 << 5) -#define BRW_TD_CTL2_CLIPPER_EXECUTION_MASK_ENABLE (1 << 4) -#define BRW_TD_CTL2_GS_EXECUTION_MASK_ENABLE (1 << 3) -#define BRW_TD_CTL2_VS_EXECUTION_MASK_ENABLE (1 << 0) -#define BRW_TD_VF_VS_EMSK 0x8008 -#define BRW_TD_GS_EMSK 0x800c -#define BRW_TD_CLIP_EMSK 0x8010 -#define BRW_TD_SF_EMSK 0x8014 -#define BRW_TD_WIZ_EMSK 0x8018 -#define BRW_TD_0_6_EHTRG_VAL 0x801c -#define BRW_TD_0_7_EHTRG_VAL 0x8020 -#define BRW_TD_0_6_EHTRG_MSK 0x8024 -#define BRW_TD_0_7_EHTRG_MSK 0x8028 -#define BRW_TD_RDATA 0x802c -#define BRW_TD_TS_EMSK 0x8030 - -#define BRW_EU_CTL 0x8800 -#define BRW_EU_CTL_SELECT_SHIFT 16 -#define BRW_EU_CTL_DATA_MUX_SHIFT 8 -#define BRW_EU_ATT_0 0x8810 -#define BRW_EU_ATT_1 0x8814 -#define BRW_EU_ATT_DATA_0 0x8820 -#define BRW_EU_ATT_DATA_1 0x8824 -#define BRW_EU_ATT_CLR_0 0x8830 -#define BRW_EU_ATT_CLR_1 0x8834 -#define BRW_EU_RDATA 0x8840 - -typedef struct i965_device i965_device_t; -typedef struct i965_surface i965_surface_t; -typedef struct i965_shader i965_shader_t; -typedef struct i965_stream i965_stream_t; - -struct i965_sf_state { - cairo_hash_entry_t entry; - uint32_t offset; -}; - -cairo_private cairo_bool_t -i965_sf_state_equal (const void *, const void *); - -struct i965_cc_state { - cairo_hash_entry_t entry; - uint32_t offset; -}; - -cairo_private cairo_bool_t -i965_cc_state_equal (const void *, const void *); - -struct i965_wm_kernel { - cairo_hash_entry_t entry; - uint32_t offset; -}; - -struct i965_wm_state { - cairo_hash_entry_t entry; - uint32_t kernel; - uint32_t sampler; - uint32_t offset; -}; - -cairo_private cairo_bool_t -i965_wm_state_equal (const void *, const void *); - -struct i965_wm_binding { - cairo_hash_entry_t entry; - uint32_t table[4]; - int size; - uint32_t offset; -}; - -cairo_private cairo_bool_t -i965_wm_binding_equal (const void *, const void *); - -struct i965_sampler { - cairo_hash_entry_t entry; - uint32_t offset; -}; - -struct i965_vbo { - struct i965_vbo *next; - intel_bo_t *bo; - unsigned int count; -}; - -struct i965_surface { - intel_surface_t intel; - - uint32_t stream; - uint32_t offset; -}; - -struct i965_pending_relocation { - uint32_t offset; - uint32_t read_domains; - uint32_t write_domain; - uint32_t delta; -}; - -struct i965_stream { - uint32_t used; - uint32_t committed; - uint32_t size; - uint8_t *data; - uint32_t serial; - - int num_pending_relocations; - int max_pending_relocations; - struct i965_pending_relocation *pending_relocations; - - int num_relocations; - int max_relocations; - struct drm_i915_gem_relocation_entry *relocations; -}; - -#define I965_BATCH_SIZE (16 * 4096) -#define I965_GENERAL_SIZE (16 * 4096) -#define I965_SURFACE_SIZE (32 * 4096) -#define I965_VERTEX_SIZE (128 * 4096) - -#define I965_TILING_DEFAULT I915_TILING_Y - - -struct i965_device { - intel_device_t intel; - - cairo_bool_t is_g4x; - - i965_shader_t *shader; /* note: only valid during geometry emission */ - - /* track state changes */ - struct i965_sf_state sf_state; - struct i965_cc_state cc_state; - struct i965_wm_state wm_state; - struct i965_wm_binding wm_binding; - - i965_surface_t *target; - uint32_t target_offset; - - intel_bo_t *source; - uint32_t source_offset; - - intel_bo_t *mask; - uint32_t mask_offset; - - intel_bo_t *clip; - uint32_t clip_offset; - - uint32_t draw_rectangle; - - uint32_t vs_offset; - uint32_t border_color_offset; - cairo_hash_table_t *sf_states; - cairo_hash_table_t *cc_states; - cairo_hash_table_t *wm_kernels; - cairo_hash_table_t *wm_states; - cairo_hash_table_t *wm_bindings; - cairo_hash_table_t *samplers; - intel_bo_t *general_state; - - cairo_freelist_t sf_freelist; - cairo_freelist_t cc_freelist; - cairo_freelist_t wm_kernel_freelist; - cairo_freelist_t wm_state_freelist; - cairo_freelist_t wm_binding_freelist; - cairo_freelist_t sampler_freelist; - - uint32_t vertex_type; - uint32_t vertex_size; - uint32_t rectangle_size; - uint32_t last_vertex_size; - - float *constants; /* 4 x matrix + 2 x source */ - unsigned constants_size; - cairo_bool_t have_urb_fences; - - i965_stream_t batch; - uint8_t batch_base[I965_BATCH_SIZE]; - struct drm_i915_gem_relocation_entry batch_relocations[2048]; - - i965_stream_t surface; - uint8_t surface_base[I965_SURFACE_SIZE]; - struct i965_pending_relocation surface_pending_relocations[1]; - struct drm_i915_gem_relocation_entry surface_relocations[1024]; - - i965_stream_t general; - uint8_t general_base[I965_GENERAL_SIZE]; - struct i965_pending_relocation general_pending_relocations[1]; - - i965_stream_t vertex; - uint8_t vertex_base[I965_VERTEX_SIZE]; - struct i965_pending_relocation vertex_pending_relocations[512]; - - struct { - size_t gtt_size; - - intel_bo_t *bo[1024]; - int count; - - struct drm_i915_gem_exec_object2 exec[1024]; - } exec; - cairo_list_t flush; -}; - -typedef enum { - VS_NONE = 0, - VS_GLYPHS, - VS_SPANS, -} i965_vertex_shader_t; - -typedef enum { - FS_NONE = 0, - FS_CONSTANT, - FS_LINEAR, - FS_RADIAL, - FS_SURFACE, - FS_GLYPHS, - FS_SPANS, -} i965_fragment_shader_t; - -typedef enum { - PATTERN_BASE, - PATTERN_SOLID, - PATTERN_LINEAR, - PATTERN_RADIAL, - PATTERN_SURFACE, -} i965_shader_channel_t; -#define PATTERN_NONE (i965_shader_channel_t)-1 - -struct i965_shader { - i965_device_t *device; - i965_surface_t *target; - - cairo_operator_t op; - - cairo_bool_t committed; - cairo_bool_t need_combine; - - float constants[4*8 + 2*8]; /* 4 x matrix + 2 x source */ - unsigned constants_size; - - union i965_shader_channel { - struct { - i965_vertex_shader_t vertex; - i965_fragment_shader_t fragment; - i965_shader_channel_t pattern; - } type; - struct i965_shader_base { - i965_vertex_shader_t vertex; - i965_fragment_shader_t fragment; - i965_shader_channel_t pattern; - - uint32_t mode; - - float constants[8]; - unsigned constants_size; - - intel_bo_t *bo; - cairo_format_t format; - cairo_content_t content; - int width, height, stride; - int filter, extend; - cairo_matrix_t matrix; - cairo_bool_t has_component_alpha; - } base; - struct i965_shader_solid { - struct i965_shader_base base; - } solid; - struct i965_shader_linear { - struct i965_shader_base base; - } linear; - struct i965_shader_radial { - struct i965_shader_base base; - } radial; - struct i965_shader_surface { - struct i965_shader_base base; - cairo_surface_t *surface; - } surface; - } source, mask, clip, dst; - - jmp_buf unwind; -}; - -enum i965_shader_linear_mode { - /* XXX REFLECT */ - LINEAR_TEXTURE, - LINEAR_NONE, - LINEAR_REPEAT, - LINEAR_PAD, -}; - -enum i965_shader_radial_mode { - RADIAL_ONE, - RADIAL_TWO -}; - -typedef cairo_status_t -(*i965_spans_func_t) (void *closure, - cairo_span_renderer_t *renderer, - const cairo_rectangle_int_t *extents); - -static inline i965_device_t * -i965_device (i965_surface_t *surface) -{ - return (i965_device_t *) surface->intel.drm.base.device; -} - -cairo_private void -i965_emit_relocation (i965_device_t *device, - i965_stream_t *stream, - intel_bo_t *target, - uint32_t target_offset, - uint32_t read_domains, - uint32_t write_domain, - uint32_t offset); - -static cairo_always_inline uint32_t -i965_stream_emit (i965_stream_t *stream, const void *data, size_t size) -{ - uint32_t offset; - - offset = stream->used; - assert (offset + size <= stream->size); - memcpy (stream->data + offset, data, size); - stream->used += size; - - return offset; -} - -static cairo_always_inline void -i965_stream_align (i965_stream_t *stream, uint32_t size) -{ - stream->used = (stream->used + size - 1) & -size; -} - -static cairo_always_inline void * -i965_stream_alloc (i965_stream_t *stream, uint32_t align, uint32_t size) -{ - void *ptr; - - if (align) - i965_stream_align (stream, align); - - assert (stream->used + size <= stream->size); - ptr = stream->data + stream->used; - stream->used += size; - - return ptr; -} - -static cairo_always_inline uint32_t -i965_stream_offsetof (i965_stream_t *stream, const void *ptr) -{ - return (char *) ptr - (char *) stream->data; -} - -cairo_private void -i965_stream_commit (i965_device_t *device, - i965_stream_t *stream); - -cairo_private void -i965_general_state_reset (i965_device_t *device); - -static inline void -i965_batch_emit_dword (i965_device_t *device, uint32_t dword) -{ - *(uint32_t *) (device->batch.data + device->batch.used) = dword; - device->batch.used += 4; -} - -#define OUT_BATCH(dword) i965_batch_emit_dword(device, dword) - -cairo_private void -i965_clipped_vertices (i965_device_t *device, - struct i965_vbo *vbo, - cairo_region_t *clip_region); - -cairo_private void -i965_flush_vertices (i965_device_t *device); - -cairo_private void -i965_finish_vertices (i965_device_t *device); - -static inline float * -i965_add_rectangle (i965_device_t *device) -{ - float *vertices; - uint32_t size; - - size = device->rectangle_size; - if (unlikely (device->vertex.used + size > device->vertex.size)) - i965_finish_vertices (device); - - vertices = (float *) (device->vertex.data + device->vertex.used); - device->vertex.used += size; - - return vertices; -} - -static inline void -i965_shader_add_rectangle (const i965_shader_t *shader, - int x, int y, - int w, int h) -{ - float *v; - - v= i965_add_rectangle (shader->device); - - /* bottom-right */ - *v++ = x + w; - *v++ = y + h; - - /* bottom-left */ - *v++ = x; - *v++ = y + h; - - /* top-left */ - *v++ = x; - *v++ = y; -} - -cairo_private cairo_surface_t * -i965_surface_create_internal (cairo_drm_device_t *base_dev, - cairo_format_t format, - int width, int height, - uint32_t tiling, - cairo_bool_t gpu_target); - -cairo_private cairo_status_t -i965_clip_and_composite_spans (i965_surface_t *dst, - cairo_operator_t op, - const cairo_pattern_t *pattern, - cairo_antialias_t antialias, - i965_spans_func_t draw_func, - void *draw_closure, - const cairo_composite_rectangles_t*extents, - cairo_clip_t *clip); - -cairo_private cairo_int_status_t -i965_surface_glyphs (void *abstract_surface, - cairo_operator_t op, - const cairo_pattern_t *source, - cairo_glyph_t *glyphs, - int num_glyphs, - cairo_scaled_font_t *scaled_font, - cairo_clip_t *clip, - int *num_remaining); - -cairo_private void -i965_shader_init (i965_shader_t *shader, - i965_surface_t *dst, - cairo_operator_t op); - -cairo_private cairo_status_t -i965_shader_acquire_pattern (i965_shader_t *shader, - union i965_shader_channel *src, - const cairo_pattern_t *pattern, - const cairo_rectangle_int_t *extents); - -cairo_private void -i965_shader_set_clip (i965_shader_t *shader, - cairo_clip_t *clip); - -cairo_private cairo_status_t -i965_shader_commit (i965_shader_t *shader, - i965_device_t *device); - -cairo_private void -i965_shader_fini (i965_shader_t *shader); - -cairo_private cairo_status_t -i965_device_flush (i965_device_t *device); - -cairo_private cairo_status_t -i965_fixup_unbounded (i965_surface_t *dst, - const cairo_composite_rectangles_t *extents, - cairo_clip_t *clip); - -static inline int -i965_filter (cairo_filter_t filter) -{ - switch (filter) { - default: - case CAIRO_FILTER_FAST: - case CAIRO_FILTER_NEAREST: - return BRW_MAPFILTER_NEAREST; - - case CAIRO_FILTER_GOOD: - case CAIRO_FILTER_BEST: - case CAIRO_FILTER_BILINEAR: - case CAIRO_FILTER_GAUSSIAN: - return BRW_MAPFILTER_LINEAR; - } -} - -static inline int -i965_extend (cairo_extend_t extend) -{ - switch (extend) { - default: - case CAIRO_EXTEND_NONE: - return BRW_TEXCOORDMODE_CLAMP_BORDER; - case CAIRO_EXTEND_REPEAT: - return BRW_TEXCOORDMODE_WRAP; - case CAIRO_EXTEND_PAD: - return BRW_TEXCOORDMODE_CLAMP; - case CAIRO_EXTEND_REFLECT: - return BRW_TEXCOORDMODE_MIRROR; - } -} - -#endif /* CAIRO_DRM_I965_PRIVATE_H */ diff --git a/gfx/cairo/cairo/src/drm/cairo-drm-i965-shader.c b/gfx/cairo/cairo/src/drm/cairo-drm-i965-shader.c deleted file mode 100644 index 8fa3b4bd2c..0000000000 --- a/gfx/cairo/cairo/src/drm/cairo-drm-i965-shader.c +++ /dev/null @@ -1,2825 +0,0 @@ -/* cairo - a vector graphics library with display and print output - * - * Copyright © 2009 Kristian Høgsberg - * Copyright © 2009 Chris Wilson - * Copyright © 2009 Intel Corporation - * - * This library is free software; you can redistribute it and/or - * modify it either under the terms of the GNU Lesser General Public - * License version 2.1 as published by the Free Software Foundation - * (the "LGPL") or, at your option, under the terms of the Mozilla - * Public License Version 1.1 (the "MPL"). If you do not alter this - * notice, a recipient may use your version of this file under either - * the MPL or the LGPL. - * - * You should have received a copy of the LGPL along with this library - * in the file COPYING-LGPL-2.1; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Suite 500, Boston, MA 02110-1335, 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. - * - * Contributor(s): - * Chris Wilson <chris@chris-wilson.co.uk> - * Kristian Høgsberg <krh@bitplanet.net> - */ - -#include "cairoint.h" - -#include "cairo-error-private.h" -#include "cairo-drm-i965-private.h" -#include "cairo-surface-subsurface-private.h" -#include "cairo-surface-snapshot-private.h" - -#include "cairo-drm-intel-brw-eu.h" - -/* Theory of shaders: - * - * 3 types of rectangular inputs: - * (a) standard composite: x,y, use source, mask matrices to compute texcoords - * (b) spans: x,y, alpha, use source matrix - * (c) glyphs: x,y, s,t, use source matrix - * - * 5 types of pixel shaders: - * (a) Solid colour - * (b) Linear gradient (via 1D texture, with precomputed tex) - * (c) Radial gradient (per-pixel s computation, 1D texture) - * (d) Spans (mask only): apply opacity - * (e) Texture (includes glyphs). - * - * Clip masks are limited to 2D textures only. - */ - -/* XXX dual source blending for LERP + ComponentAlpha!!! */ - -#define BRW_GRF_BLOCKS(nreg) ((nreg + 15) / 16 - 1) - -#define SF_KERNEL_NUM_GRF 1 -#define SF_MAX_THREADS 24 - -#define PS_MAX_THREADS_CTG 50 -#define PS_MAX_THREADS_BRW 32 - -#define URB_CS_ENTRY_SIZE 3 /* We need 4 matrices + 2 sources */ -#define URB_CS_ENTRIES 4 /* 4x sets of CONSTANT_BUFFER */ - -#define URB_VS_ENTRY_SIZE 1 -#define URB_VS_ENTRIES 8 - -#define URB_GS_ENTRY_SIZE 0 -#define URB_GS_ENTRIES 0 - -#define URB_CLIP_ENTRY_SIZE 0 -#define URB_CLIP_ENTRIES 0 - -#define URB_SF_ENTRY_SIZE 1 -#define URB_SF_ENTRIES (SF_MAX_THREADS + 1) - -static void -i965_pipelined_flush (i965_device_t *device) -{ - intel_bo_t *bo, *next; - - if (device->batch.used == 0) - return; - - OUT_BATCH (BRW_PIPE_CONTROL | - BRW_PIPE_CONTROL_NOWRITE | - BRW_PIPE_CONTROL_WC_FLUSH | - 2); - OUT_BATCH(0); /* Destination address */ - OUT_BATCH(0); /* Immediate data low DW */ - OUT_BATCH(0); /* Immediate data high DW */ - - cairo_list_foreach_entry_safe (bo, next, intel_bo_t, &device->flush, link) { - bo->batch_write_domain = 0; - cairo_list_init (&bo->link); - } - cairo_list_init (&device->flush); -} - -static cairo_status_t -i965_shader_acquire_solid (i965_shader_t *shader, - union i965_shader_channel *src, - const cairo_solid_pattern_t *solid, - const cairo_rectangle_int_t *extents) -{ - src->type.fragment = FS_CONSTANT; - src->type.vertex = VS_NONE; - src->type.pattern = PATTERN_SOLID; - - src->base.content = _cairo_color_get_content (&solid->color); - src->base.constants[0] = solid->color.red * solid->color.alpha; - src->base.constants[1] = solid->color.green * solid->color.alpha; - src->base.constants[2] = solid->color.blue * solid->color.alpha; - src->base.constants[3] = solid->color.alpha; - src->base.constants_size = 4; - - return CAIRO_STATUS_SUCCESS; -} - -static cairo_status_t -i965_shader_acquire_linear (i965_shader_t *shader, - union i965_shader_channel *src, - const cairo_linear_pattern_t *linear, - const cairo_rectangle_int_t *extents) -{ - intel_buffer_t buffer; - cairo_status_t status; - double x0, y0, sf; - double dx, dy, offset; - - status = intel_gradient_render (&i965_device (shader->target)->intel, - &linear->base, &buffer); - if (unlikely (status)) - return status; - - src->type.vertex = VS_NONE; - src->type.pattern = PATTERN_LINEAR; - src->type.fragment = FS_LINEAR; - src->base.bo = buffer.bo; - src->base.content = CAIRO_CONTENT_COLOR_ALPHA; - src->base.format = buffer.format; - src->base.width = buffer.width; - src->base.height = buffer.height; - src->base.stride = buffer.stride; - src->base.filter = i965_filter (CAIRO_FILTER_BILINEAR); - src->base.extend = i965_extend (linear->base.base.extend); - - dx = linear->pd2.x - linear->pd1.x; - dy = linear->pd2.y - linear->pd1.y; - sf = 1. / (dx * dx + dy * dy); - dx *= sf; - dy *= sf; - - x0 = linear->pd1.x; - y0 = linear->pd1.y; - offset = dx*x0 + dy*y0; - - if (_cairo_matrix_is_identity (&linear->base.base.matrix)) { - src->base.matrix.xx = dx; - src->base.matrix.xy = dy; - src->base.matrix.x0 = -offset; - } else { - cairo_matrix_t m; - - cairo_matrix_init (&m, dx, 0, dy, 0, -offset, 0); - cairo_matrix_multiply (&src->base.matrix, &linear->base.base.matrix, &m); - } - src->base.matrix.yx = 0.; - src->base.matrix.yy = 1.; - src->base.matrix.y0 = 0.; - - return CAIRO_STATUS_SUCCESS; -} - -static cairo_status_t -i965_shader_acquire_radial (i965_shader_t *shader, - union i965_shader_channel *src, - const cairo_radial_pattern_t *radial, - const cairo_rectangle_int_t *extents) -{ - intel_buffer_t buffer; - cairo_status_t status; - double dx, dy, dr, r1; - - status = intel_gradient_render (&i965_device (shader->target)->intel, - &radial->base, &buffer); - if (unlikely (status)) - return status; - - src->type.vertex = VS_NONE; - src->type.pattern = PATTERN_RADIAL; - src->type.fragment = FS_RADIAL; - src->base.bo = buffer.bo; - src->base.content = CAIRO_CONTENT_COLOR_ALPHA; - src->base.format = buffer.format; - src->base.width = buffer.width; - src->base.height = buffer.height; - src->base.stride = buffer.stride; - src->base.filter = i965_filter (CAIRO_FILTER_BILINEAR); - src->base.extend = i965_extend (radial->base.base.extend); - - dx = radial->cd2.center.x - radial->cd1.center.x; - dy = radial->cd2.center.y - radial->cd1.center.y; - dr = radial->cd2.radius - radial->cd1.radius; - - r1 = radial->cd1.radius; - - if (FALSE && (radial->cd2.center.x == radial->cd1.center.x && - radial->cd2.center.y == radial->cd1.center.y)) - { - /* XXX dr == 0, meaningless with anything other than PAD */ - src->base.constants[0] = radial->cd1.center.x / dr; - src->base.constants[1] = radial->cd1.center.y / dr; - src->base.constants[2] = 1. / dr; - src->base.constants[3] = -r1 / dr; - - src->base.constants_size = 4; - src->base.mode = RADIAL_ONE; - } else { - src->base.constants[0] = -radial->cd1.center.x; - src->base.constants[1] = -radial->cd1.center.y; - src->base.constants[2] = r1; - src->base.constants[3] = -4 * (dx*dx + dy*dy - dr*dr); - - src->base.constants[4] = -2 * dx; - src->base.constants[5] = -2 * dy; - src->base.constants[6] = -2 * r1 * dr; - src->base.constants[7] = 1 / (2 * (dx*dx + dy*dy - dr*dr)); - - src->base.constants_size = 8; - src->base.mode = RADIAL_TWO; - } - - return CAIRO_STATUS_SUCCESS; -} - -static cairo_status_t -i965_surface_clone (i965_device_t *device, - cairo_image_surface_t *image, - i965_surface_t **clone_out) -{ - i965_surface_t *clone; - cairo_status_t status; - - clone = (i965_surface_t *) - i965_surface_create_internal (&device->intel.base, - image->base.content, - image->width, - image->height, - I965_TILING_DEFAULT, - FALSE); - if (unlikely (clone->intel.drm.base.status)) - return clone->intel.drm.base.status; - - status = intel_bo_put_image (&device->intel, - to_intel_bo (clone->intel.drm.bo), - image, - 0, 0, - image->width, image->height, - 0, 0); - - if (unlikely (status)) { - cairo_surface_destroy (&clone->intel.drm.base); - return status; - } - - status = intel_snapshot_cache_insert (&device->intel, &clone->intel); - if (unlikely (status)) { - cairo_surface_destroy (&clone->intel.drm.base); - return status; - } - - _cairo_surface_attach_snapshot (&image->base, - &clone->intel.drm.base, - intel_surface_detach_snapshot); - - *clone_out = clone; - return CAIRO_STATUS_SUCCESS; -} - -static cairo_status_t -i965_surface_clone_subimage (i965_device_t *device, - cairo_image_surface_t *image, - const cairo_rectangle_int_t *extents, - i965_surface_t **clone_out) -{ - i965_surface_t *clone; - cairo_status_t status; - - clone = (i965_surface_t *) - i965_surface_create_internal (&device->intel.base, - image->base.content, - extents->width, - extents->height, - I965_TILING_DEFAULT, - FALSE); - if (unlikely (clone->intel.drm.base.status)) - return clone->intel.drm.base.status; - - status = intel_bo_put_image (to_intel_device (clone->intel.drm.base.device), - to_intel_bo (clone->intel.drm.bo), - image, - extents->x, extents->y, - extents->width, extents->height, - 0, 0); - if (unlikely (status)) - return status; - - *clone_out = clone; - return CAIRO_STATUS_SUCCESS; -} - -static cairo_status_t -i965_shader_acquire_solid_surface (i965_shader_t *shader, - union i965_shader_channel *src, - cairo_surface_t *surface, - const cairo_rectangle_int_t *extents) -{ - cairo_image_surface_t *image; - void *image_extra; - cairo_status_t status; - uint32_t argb; - - status = _cairo_surface_acquire_source_image (surface, &image, &image_extra); - if (unlikely (status)) - return status; - - if (image->format != CAIRO_FORMAT_ARGB32) { - cairo_surface_t *pixel; - cairo_surface_pattern_t pattern; - - /* extract the pixel as argb32 */ - pixel = cairo_image_surface_create (CAIRO_FORMAT_ARGB32, 1, 1); - _cairo_pattern_init_for_surface (&pattern, &image->base); - cairo_matrix_init_translate (&pattern.base.matrix, extents->x, extents->y); - pattern.base.filter = CAIRO_FILTER_NEAREST; - status = _cairo_surface_paint (pixel, CAIRO_OPERATOR_SOURCE, &pattern.base, NULL); - _cairo_pattern_fini (&pattern.base); - - if (unlikely (status)) { - _cairo_surface_release_source_image (surface, image, image_extra); - cairo_surface_destroy (pixel); - return status; - } - - argb = *(uint32_t *) ((cairo_image_surface_t *) pixel)->data; - cairo_surface_destroy (pixel); - } else { - argb = ((uint32_t *) (image->data + extents->y * image->stride))[extents->x]; - } - - _cairo_surface_release_source_image (surface, image, image_extra); - - if (argb >> 24 == 0) - argb = 0; - - src->base.constants[0] = ((argb >> 16) & 0xff) / 255.; - src->base.constants[1] = ((argb >> 8) & 0xff) / 255.; - src->base.constants[2] = ((argb >> 0) & 0xff) / 255.; - src->base.constants[3] = ((argb >> 24) & 0xff) / 255.; - src->base.constants_size = 4; - - src->base.content = CAIRO_CONTENT_COLOR_ALPHA; - if (CAIRO_ALPHA_IS_OPAQUE(src->base.constants[3])) - src->base.content &= ~CAIRO_CONTENT_ALPHA; - src->type.fragment = FS_CONSTANT; - src->type.vertex = VS_NONE; - src->type.pattern = PATTERN_SOLID; - - return CAIRO_STATUS_SUCCESS; -} - -static cairo_status_t -i965_shader_acquire_surface (i965_shader_t *shader, - union i965_shader_channel *src, - const cairo_surface_pattern_t *pattern, - const cairo_rectangle_int_t *extents) -{ - cairo_surface_t *surface, *drm; - cairo_matrix_t m; - cairo_status_t status; - int src_x = 0, src_y = 0; - - assert (src->type.fragment == FS_NONE); - drm = surface = pattern->surface; - - if (surface->type == CAIRO_SURFACE_TYPE_DRM) { - if (surface->backend->type == CAIRO_SURFACE_TYPE_SUBSURFACE) { - drm = ((cairo_surface_subsurface_t *) surface)->target; - } else if (surface->backend->type == CAIRO_INTERNAL_SURFACE_TYPE_SNAPSHOT) { - drm = ((cairo_surface_snapshot_t *) surface)->target; - } - } - - src->type.pattern = PATTERN_SURFACE; - src->surface.surface = NULL; - if (drm->type == CAIRO_SURFACE_TYPE_DRM) { - i965_surface_t *s = (i965_surface_t *) drm; - - if (surface->backend->type == CAIRO_SURFACE_TYPE_SUBSURFACE) { - if (s->intel.drm.base.device == shader->target->intel.drm.base.device) { - cairo_surface_subsurface_t *sub = (cairo_surface_subsurface_t *) surface; - if (s != shader->target) { - int x; - - if (s->intel.drm.fallback != NULL) { - status = intel_surface_flush (s, 0); - if (unlikely (status)) - return status; - } - - if (to_intel_bo (s->intel.drm.bo)->batch_write_domain) - i965_pipelined_flush (i965_device (s)); - - src->type.fragment = FS_SURFACE; - - src->base.bo = to_intel_bo (s->intel.drm.bo); - src->base.format = s->intel.drm.format; - src->base.content = s->intel.drm.base.content; - src->base.width = sub->extents.width; - src->base.height = sub->extents.height; - src->base.stride = s->intel.drm.stride; - - x = sub->extents.x; - if (s->intel.drm.format != CAIRO_FORMAT_A8) - x *= 4; - - /* XXX tiling restrictions upon offset? */ - //src->base.offset[0] = s->offset + sub->extents.y * s->intel.drm.stride + x; - } else { - i965_surface_t *clone; - cairo_surface_pattern_t pattern; - - clone = (i965_surface_t *) - i965_surface_create_internal ((cairo_drm_device_t *) s->intel.drm.base.device, - s->intel.drm.base.content, - sub->extents.width, - sub->extents.height, - I965_TILING_DEFAULT, - TRUE); - if (unlikely (clone->intel.drm.base.status)) - return clone->intel.drm.base.status; - - _cairo_pattern_init_for_surface (&pattern, &s->intel.drm.base); - pattern.base.filter = CAIRO_FILTER_NEAREST; - cairo_matrix_init_translate (&pattern.base.matrix, - sub->extents.x, sub->extents.y); - - status = _cairo_surface_paint (&clone->intel.drm.base, - CAIRO_OPERATOR_SOURCE, - &pattern.base, - NULL); - - _cairo_pattern_fini (&pattern.base); - - if (unlikely (status)) { - cairo_surface_destroy (&clone->intel.drm.base); - return status; - } - - i965_pipelined_flush (i965_device (s)); - src->type.fragment = FS_SURFACE; - - src->base.bo = to_intel_bo (clone->intel.drm.bo); - src->base.format = clone->intel.drm.format; - src->base.content = clone->intel.drm.base.content; - src->base.width = clone->intel.drm.width; - src->base.height = clone->intel.drm.height; - src->base.stride = clone->intel.drm.stride; - - src->surface.surface = &clone->intel.drm.base; - } - - src_x = sub->extents.x; - src_y = sub->extents.y; - } - } else { - if (s->intel.drm.base.device == shader->target->intel.drm.base.device) { - if (s != shader->target) { - if (s->intel.drm.fallback != NULL) { - status = intel_surface_flush (s, 0); - if (unlikely (status)) - return status; - } - - if (to_intel_bo (s->intel.drm.bo)->batch_write_domain) - i965_pipelined_flush (i965_device (s)); - - src->type.fragment = FS_SURFACE; - - src->base.bo = to_intel_bo (s->intel.drm.bo); - src->base.format = s->intel.drm.format; - src->base.content = s->intel.drm.base.content; - src->base.width = s->intel.drm.width; - src->base.height = s->intel.drm.height; - src->base.stride = s->intel.drm.stride; - } else { - i965_surface_t *clone; - cairo_surface_pattern_t pattern; - - clone = (i965_surface_t *) - i965_surface_create_internal ((cairo_drm_device_t *) s->intel.drm.base.device, - s->intel.drm.base.content, - s->intel.drm.width, - s->intel.drm.height, - I965_TILING_DEFAULT, - TRUE); - if (unlikely (clone->intel.drm.base.status)) - return clone->intel.drm.base.status; - - _cairo_pattern_init_for_surface (&pattern, &s->intel.drm.base); - pattern.base.filter = CAIRO_FILTER_NEAREST; - status = _cairo_surface_paint (&clone->intel.drm.base, - CAIRO_OPERATOR_SOURCE, - &pattern.base, - NULL); - - _cairo_pattern_fini (&pattern.base); - - if (unlikely (status)) { - cairo_surface_destroy (&clone->intel.drm.base); - return status; - } - - i965_pipelined_flush (i965_device (s)); - src->type.fragment = FS_SURFACE; - - src->base.bo = to_intel_bo (clone->intel.drm.bo); - src->base.format = clone->intel.drm.format; - src->base.content = clone->intel.drm.base.content; - src->base.width = clone->intel.drm.width; - src->base.height = clone->intel.drm.height; - src->base.stride = clone->intel.drm.stride; - - src->surface.surface = &clone->intel.drm.base; - } - } - } - } - - if (src->type.fragment == FS_NONE) { - i965_surface_t *s; - - if (extents->width == 1 && extents->height == 1) { - return i965_shader_acquire_solid_surface (shader, src, - surface, extents); - } - - s = (i965_surface_t *) - _cairo_surface_has_snapshot (surface, - shader->target->intel.drm.base.backend); - if (s != NULL) { - i965_device_t *device = i965_device (shader->target); - intel_bo_t *bo = to_intel_bo (s->intel.drm.bo); - - if (bo->purgeable && - ! intel_bo_madvise (&device->intel, bo, I915_MADV_WILLNEED)) - { - _cairo_surface_detach_snapshot (&s->intel.drm.base); - s = NULL; - } - - if (s != NULL) - cairo_surface_reference (&s->intel.drm.base); - } - - if (s == NULL) { - cairo_image_surface_t *image; - void *image_extra; - cairo_status_t status; - - status = _cairo_surface_acquire_source_image (surface, &image, &image_extra); - if (unlikely (status)) - return status; - - if (image->width < 8192 && image->height < 8192) { - status = i965_surface_clone (i965_device (shader->target), image, &s); - } else { - status = i965_surface_clone_subimage (i965_device (shader->target), - image, extents, &s); - src_x = -extents->x; - src_y = -extents->y; - } - - _cairo_surface_release_source_image (surface, image, image_extra); - - if (unlikely (status)) - return status; - - /* XXX? */ - //intel_bo_mark_purgeable (to_intel_bo (s->intel.drm.bo), TRUE); - } - - src->type.fragment = FS_SURFACE; - - src->base.bo = to_intel_bo (s->intel.drm.bo); - src->base.content = s->intel.drm.base.content; - src->base.format = s->intel.drm.format; - src->base.width = s->intel.drm.width; - src->base.height = s->intel.drm.height; - src->base.stride = s->intel.drm.stride; - - src->surface.surface = &s->intel.drm.base; - - drm = &s->intel.drm.base; - } - - /* XXX transform nx1 or 1xn surfaces to 1D? */ - - src->type.vertex = VS_NONE; - - src->base.extend = i965_extend (pattern->base.extend); - if (pattern->base.extend == CAIRO_EXTEND_NONE && - extents->x >= 0 && extents->y >= 0 && - extents->x + extents->width <= src->base.width && - extents->y + extents->height <= src->base.height) - { - /* Convert a wholly contained NONE to a REFLECT as the contiguous sampler - * cannot not handle CLAMP_BORDER textures. - */ - src->base.extend = i965_extend (CAIRO_EXTEND_REFLECT); - /* XXX also need to check |u,v| < 3 */ - } - - src->base.filter = i965_filter (pattern->base.filter); - if (_cairo_matrix_is_pixel_exact (&pattern->base.matrix)) - src->base.filter = i965_filter (CAIRO_FILTER_NEAREST); - - /* tweak the src matrix to map from dst to texture coordinates */ - src->base.matrix = pattern->base.matrix; - if (src_x | src_y) - cairo_matrix_translate (&src->base.matrix, src_x, src_x); - cairo_matrix_init_scale (&m, 1. / src->base.width, 1. / src->base.height); - cairo_matrix_multiply (&src->base.matrix, &src->base.matrix, &m); - - return CAIRO_STATUS_SUCCESS; -} - -cairo_status_t -i965_shader_acquire_pattern (i965_shader_t *shader, - union i965_shader_channel *src, - const cairo_pattern_t *pattern, - const cairo_rectangle_int_t *extents) -{ - switch (pattern->type) { - case CAIRO_PATTERN_TYPE_SOLID: - return i965_shader_acquire_solid (shader, src, - (cairo_solid_pattern_t *) pattern, - extents); - - case CAIRO_PATTERN_TYPE_LINEAR: - return i965_shader_acquire_linear (shader, src, - (cairo_linear_pattern_t *) pattern, - extents); - - case CAIRO_PATTERN_TYPE_RADIAL: - return i965_shader_acquire_radial (shader, src, - (cairo_radial_pattern_t *) pattern, - extents); - - case CAIRO_PATTERN_TYPE_SURFACE: - return i965_shader_acquire_surface (shader, src, - (cairo_surface_pattern_t *) pattern, - extents); - - default: - ASSERT_NOT_REACHED; - return CAIRO_STATUS_SUCCESS; - } -} - -static void -i965_shader_channel_init (union i965_shader_channel *channel) -{ - channel->type.vertex = VS_NONE; - channel->type.fragment = FS_NONE; - channel->type.pattern = PATTERN_NONE; - - channel->base.mode = 0; - channel->base.bo = NULL; - channel->base.filter = i965_extend (CAIRO_FILTER_NEAREST); - channel->base.extend = i965_extend (CAIRO_EXTEND_NONE); - channel->base.has_component_alpha = 0; - channel->base.constants_size = 0; -} - -void -i965_shader_init (i965_shader_t *shader, - i965_surface_t *dst, - cairo_operator_t op) -{ - shader->committed = FALSE; - shader->device = i965_device (dst); - shader->target = dst; - shader->op = op; - shader->constants_size = 0; - - shader->need_combine = FALSE; - - i965_shader_channel_init (&shader->source); - i965_shader_channel_init (&shader->mask); - i965_shader_channel_init (&shader->clip); - i965_shader_channel_init (&shader->dst); -} - -void -i965_shader_fini (i965_shader_t *shader) -{ - if (shader->source.type.pattern == PATTERN_SURFACE) - cairo_surface_destroy (shader->source.surface.surface); - if (shader->mask.type.pattern == PATTERN_SURFACE) - cairo_surface_destroy (shader->mask.surface.surface); - if (shader->clip.type.pattern == PATTERN_SURFACE) - cairo_surface_destroy (shader->clip.surface.surface); - if (shader->dst.type.pattern == PATTERN_SURFACE) - cairo_surface_destroy (shader->dst.surface.surface); -} - -void -i965_shader_set_clip (i965_shader_t *shader, - cairo_clip_t *clip) -{ - cairo_surface_t *clip_surface; - int clip_x, clip_y; - union i965_shader_channel *channel; - i965_surface_t *s; - - clip_surface = _cairo_clip_get_surface (clip, &shader->target->intel.drm.base, &clip_x, &clip_y); - assert (clip_surface->status == CAIRO_STATUS_SUCCESS); - assert (clip_surface->type == CAIRO_SURFACE_TYPE_DRM); - s = (i965_surface_t *) clip_surface; - - if (to_intel_bo (s->intel.drm.bo)->batch_write_domain) - i965_pipelined_flush (i965_device (s)); - - channel = &shader->clip; - channel->type.pattern = PATTERN_BASE; - channel->type.vertex = VS_NONE; - channel->type.fragment = FS_SURFACE; - - channel->base.bo = to_intel_bo (s->intel.drm.bo); - channel->base.content = CAIRO_CONTENT_ALPHA; - channel->base.format = CAIRO_FORMAT_A8; - channel->base.width = s->intel.drm.width; - channel->base.height = s->intel.drm.height; - channel->base.stride = s->intel.drm.stride; - - channel->base.extend = i965_extend (CAIRO_EXTEND_NONE); - channel->base.filter = i965_filter (CAIRO_FILTER_NEAREST); - - cairo_matrix_init_scale (&shader->clip.base.matrix, - 1. / s->intel.drm.width, - 1. / s->intel.drm.height); - - cairo_matrix_translate (&shader->clip.base.matrix, - -clip_x, -clip_y); -} - -static cairo_bool_t -i965_shader_check_aperture (i965_shader_t *shader, - i965_device_t *device) -{ - uint32_t size = device->exec.gtt_size; - - if (shader->target != device->target) { - const intel_bo_t *bo = to_intel_bo (shader->target->intel.drm.bo); - if (bo->exec == NULL) - size += bo->base.size; - } - - if (shader->source.base.bo != NULL && shader->source.base.bo != device->source) { - const intel_bo_t *bo = to_intel_bo (shader->target->intel.drm.bo); - if (bo->exec == NULL) - size += bo->base.size; - } - - if (shader->mask.base.bo != NULL && shader->mask.base.bo != device->mask) { - const intel_bo_t *bo = to_intel_bo (shader->target->intel.drm.bo); - if (bo->exec == NULL) - size += bo->base.size; - } - - if (shader->clip.base.bo != NULL && shader->clip.base.bo != device->clip) { - const intel_bo_t *bo = to_intel_bo (shader->target->intel.drm.bo); - if (bo->exec == NULL) - size += bo->base.size; - } - - return size <= device->intel.gtt_avail_size; -} - -static cairo_status_t -i965_shader_setup_dst (i965_shader_t *shader) -{ - union i965_shader_channel *channel; - i965_surface_t *s, *clone; - - /* We need to manual blending if we have a clip surface and an unbounded op, - * or an extended blend mode. - */ - if (shader->need_combine || - (shader->op < CAIRO_OPERATOR_SATURATE && - (shader->clip.type.fragment == FS_NONE || - _cairo_operator_bounded_by_mask (shader->op)))) - { - return CAIRO_STATUS_SUCCESS; - } - - shader->need_combine = TRUE; - - s = shader->target; - - /* we need to allocate a new render target and use the original as a source */ - clone = (i965_surface_t *) - i965_surface_create_internal ((cairo_drm_device_t *) s->intel.drm.base.device, - s->intel.drm.base.content, - s->intel.drm.width, - s->intel.drm.height, - I965_TILING_DEFAULT, - TRUE); - if (unlikely (clone->intel.drm.base.status)) - return clone->intel.drm.base.status; - - if (to_intel_bo (s->intel.drm.bo)->batch_write_domain) - i965_pipelined_flush (i965_device (s)); - - channel = &shader->dst; - - channel->type.vertex = VS_NONE; - channel->type.fragment = FS_SURFACE; - channel->type.pattern = PATTERN_SURFACE; - - /* swap buffer objects */ - channel->base.bo = to_intel_bo (s->intel.drm.bo); - s->intel.drm.bo = ((cairo_drm_surface_t *) clone)->bo; - ((cairo_drm_surface_t *) clone)->bo = &channel->base.bo->base; - - channel->base.content = s->intel.drm.base.content; - channel->base.format = s->intel.drm.format; - channel->base.width = s->intel.drm.width; - channel->base.height = s->intel.drm.height; - channel->base.stride = s->intel.drm.stride; - - channel->base.filter = i965_filter (CAIRO_FILTER_NEAREST); - channel->base.extend = i965_extend (CAIRO_EXTEND_NONE); - - cairo_matrix_init_scale (&channel->base.matrix, - 1. / s->intel.drm.width, - 1. / s->intel.drm.height); - - channel->surface.surface = &clone->intel.drm.base; - - s->intel.drm.base.content = clone->intel.drm.base.content; - s->intel.drm.format = clone->intel.drm.format; - assert (s->intel.drm.width == clone->intel.drm.width); - assert (s->intel.drm.height == clone->intel.drm.height); - s->intel.drm.stride = clone->intel.drm.stride; - - return CAIRO_STATUS_SUCCESS; -} - -static inline void -constant_add_float (i965_shader_t *shader, float v) -{ - shader->constants[shader->constants_size++] = v; -} - -static inline void -i965_shader_copy_channel_constants (i965_shader_t *shader, - const union i965_shader_channel *channel) -{ - if (channel->base.constants_size) { - assert (shader->constants_size + channel->base.constants_size < ARRAY_LENGTH (shader->constants)); - - memcpy (shader->constants + shader->constants_size, - channel->base.constants, - sizeof (float) * channel->base.constants_size); - shader->constants_size += channel->base.constants_size; - } -} - -static void -i965_shader_setup_channel_constants (i965_shader_t *shader, - const union i965_shader_channel *channel) -{ - switch (channel->type.fragment) { - case FS_NONE: - case FS_CONSTANT: - /* no plane equations */ - break; - - case FS_LINEAR: - constant_add_float (shader, channel->base.matrix.xx); - constant_add_float (shader, channel->base.matrix.xy); - constant_add_float (shader, 0); - constant_add_float (shader, channel->base.matrix.x0); - break; - - case FS_RADIAL: - case FS_SURFACE: - constant_add_float (shader, channel->base.matrix.xx); - constant_add_float (shader, channel->base.matrix.xy); - constant_add_float (shader, 0); - constant_add_float (shader, channel->base.matrix.x0); - - constant_add_float (shader, channel->base.matrix.yx); - constant_add_float (shader, channel->base.matrix.yy); - constant_add_float (shader, 0); - constant_add_float (shader, channel->base.matrix.y0); - break; - - case FS_SPANS: - case FS_GLYPHS: - /* use pue from SF */ - break; - } - - i965_shader_copy_channel_constants (shader, channel); -} - -static void -i965_shader_setup_constants (i965_shader_t *shader) -{ - i965_shader_setup_channel_constants (shader, &shader->source); - i965_shader_setup_channel_constants (shader, &shader->mask); - i965_shader_setup_channel_constants (shader, &shader->clip); - i965_shader_setup_channel_constants (shader, &shader->dst); - assert (shader->constants_size < ARRAY_LENGTH (shader->constants)); -} - -/* - * Highest-valued BLENDFACTOR used in i965_blend_op. - * - * This leaves out BRW_BLENDFACTOR_INV_DST_COLOR, - * BRW_BLENDFACTOR_INV_CONST_{COLOR,ALPHA}, - * BRW_BLENDFACTOR_INV_SRC1_{COLOR,ALPHA} - */ -#define BRW_BLENDFACTOR_COUNT (BRW_BLENDFACTOR_INV_DST_ALPHA + 1) - -static void -i965_shader_get_blend_cntl (const i965_shader_t *shader, - uint32_t *sblend, uint32_t *dblend) -{ - static const struct blendinfo { - cairo_bool_t dst_alpha; - cairo_bool_t src_alpha; - uint32_t src_blend; - uint32_t dst_blend; - } i965_blend_op[] = { - /* CAIRO_OPERATOR_CLEAR treat as SOURCE with transparent */ - {0, 0, BRW_BLENDFACTOR_ONE, BRW_BLENDFACTOR_ZERO}, - /* CAIRO_OPERATOR_SOURCE */ - {0, 0, BRW_BLENDFACTOR_ONE, BRW_BLENDFACTOR_ZERO}, - /* CAIRO_OPERATOR_OVER */ - {0, 1, BRW_BLENDFACTOR_ONE, BRW_BLENDFACTOR_INV_SRC_ALPHA}, - /* CAIRO_OPERATOR_IN */ - {1, 0, BRW_BLENDFACTOR_DST_ALPHA, BRW_BLENDFACTOR_ZERO}, - /* CAIRO_OPERATOR_OUT */ - {1, 0, BRW_BLENDFACTOR_INV_DST_ALPHA, BRW_BLENDFACTOR_ZERO}, - /* CAIRO_OPERATOR_ATOP */ - {1, 1, BRW_BLENDFACTOR_DST_ALPHA, BRW_BLENDFACTOR_INV_SRC_ALPHA}, - - /* CAIRO_OPERATOR_DEST */ - {0, 0, BRW_BLENDFACTOR_ZERO, BRW_BLENDFACTOR_ONE}, - /* CAIRO_OPERATOR_DEST_OVER */ - {1, 0, BRW_BLENDFACTOR_INV_DST_ALPHA, BRW_BLENDFACTOR_ONE}, - /* CAIRO_OPERATOR_DEST_IN */ - {0, 1, BRW_BLENDFACTOR_ZERO, BRW_BLENDFACTOR_SRC_ALPHA}, - /* CAIRO_OPERATOR_DEST_OUT */ - {0, 1, BRW_BLENDFACTOR_ZERO, BRW_BLENDFACTOR_INV_SRC_ALPHA}, - /* CAIRO_OPERATOR_DEST_ATOP */ - {1, 1, BRW_BLENDFACTOR_INV_DST_ALPHA, BRW_BLENDFACTOR_SRC_ALPHA}, - /* CAIRO_OPERATOR_XOR */ - {1, 1, BRW_BLENDFACTOR_INV_DST_ALPHA, BRW_BLENDFACTOR_INV_SRC_ALPHA}, - /* CAIRO_OPERATOR_ADD */ - {0, 0, BRW_BLENDFACTOR_ONE, BRW_BLENDFACTOR_ONE}, - }; - const struct blendinfo *op = &i965_blend_op[shader->op]; - - *sblend = op->src_blend; - *dblend = op->dst_blend; - - /* If there's no dst alpha channel, adjust the blend op so that we'll treat - * it as always 1. - */ - if (shader->target->intel.drm.base.content == CAIRO_CONTENT_COLOR && - op->dst_alpha) - { - if (*sblend == BRW_BLENDFACTOR_DST_ALPHA) - *sblend = BRW_BLENDFACTOR_ONE; - else if (*sblend == BRW_BLENDFACTOR_INV_DST_ALPHA) - *sblend = BRW_BLENDFACTOR_ZERO; - } -} - -static void -emit_wm_subpans_to_pixels (struct brw_compile *compile, - int tmp) -{ - /* Inputs: - * R1.5 x/y of upper-left pixel of subspan 3 - * R1.4 x/y of upper-left pixel of subspan 2 - * R1.3 x/y of upper-left pixel of subspan 1 - * R1.2 x/y of upper-left pixel of subspan 0 - * - * Outputs: - * M1,2: u - * M3,4: v - * - * upper left, upper right, lower left, lower right. - */ - - /* compute pixel locations for each subspan */ - brw_set_compression_control (compile, BRW_COMPRESSION_NONE); - brw_ADD (compile, - brw_vec8_grf (tmp), - brw_reg (BRW_GENERAL_REGISTER_FILE, 1, 4, - BRW_REGISTER_TYPE_UW, - BRW_VERTICAL_STRIDE_2, - BRW_WIDTH_4, - BRW_HORIZONTAL_STRIDE_0, - BRW_SWIZZLE_NOOP, - WRITEMASK_XYZW), - brw_imm_vf4 (VF_ZERO, VF_ONE, VF_ZERO, VF_ONE)); - brw_ADD (compile, - brw_vec8_grf (tmp+1), - brw_reg (BRW_GENERAL_REGISTER_FILE, 1, 8, - BRW_REGISTER_TYPE_UW, - BRW_VERTICAL_STRIDE_2, - BRW_WIDTH_4, - BRW_HORIZONTAL_STRIDE_0, - BRW_SWIZZLE_NOOP, - WRITEMASK_XYZW), - brw_imm_vf4 (VF_ZERO, VF_ONE, VF_ZERO, VF_ONE)); - brw_ADD (compile, - brw_vec8_grf (tmp+2), - brw_reg (BRW_GENERAL_REGISTER_FILE, 1, 5, - BRW_REGISTER_TYPE_UW, - BRW_VERTICAL_STRIDE_2, - BRW_WIDTH_4, - BRW_HORIZONTAL_STRIDE_0, - BRW_SWIZZLE_NOOP, - WRITEMASK_XYZW), - brw_imm_vf4 (VF_ZERO, VF_ZERO, VF_ONE, VF_ONE)); - brw_ADD (compile, - brw_vec8_grf (tmp+3), - brw_reg (BRW_GENERAL_REGISTER_FILE, 1, 9, - BRW_REGISTER_TYPE_UW, - BRW_VERTICAL_STRIDE_2, - BRW_WIDTH_4, - BRW_HORIZONTAL_STRIDE_0, - BRW_SWIZZLE_NOOP, - WRITEMASK_XYZW), - brw_imm_vf4 (VF_ZERO, VF_ZERO, VF_ONE, VF_ONE)); - brw_set_compression_control (compile, BRW_COMPRESSION_COMPRESSED); -} - -static void -emit_wm_affine (struct brw_compile *compile, - int tmp, int reg, int msg) -{ - emit_wm_subpans_to_pixels (compile, tmp); - - brw_LINE (compile, - brw_null_reg (), - brw_vec1_grf (reg, 0), - brw_vec8_grf (tmp)); - brw_MAC (compile, - brw_message_reg (msg + 1), - brw_vec1_grf (reg, 1), - brw_vec8_grf (tmp+2)); - - brw_LINE (compile, - brw_null_reg (), - brw_vec1_grf (reg, 4), - brw_vec8_grf (tmp)); - brw_MAC (compile, - brw_message_reg (msg + 3), - brw_vec1_grf (reg, 5), - brw_vec8_grf (tmp+2)); -} - -static void -emit_wm_glyph (struct brw_compile *compile, - int tmp, int vue, int msg) -{ - emit_wm_subpans_to_pixels (compile, tmp); - - brw_MUL (compile, - brw_null_reg (), - brw_vec8_grf (tmp), - brw_imm_f (1./1024)); - brw_ADD (compile, - brw_message_reg (msg + 1), - brw_acc_reg (), - brw_vec1_grf (vue, 0)); - - brw_MUL (compile, - brw_null_reg (), - brw_vec8_grf (tmp + 2), - brw_imm_f (1./1024)); - brw_ADD (compile, - brw_message_reg (msg + 3), - brw_acc_reg (), - brw_vec1_grf (vue, 1)); -} - -static void -emit_wm_load_constant (struct brw_compile *compile, - int reg, - struct brw_reg *result) -{ - int n; - - for (n = 0; n < 4; n++) { - result[n] = result[n+4] = brw_reg (BRW_GENERAL_REGISTER_FILE, reg, n, - BRW_REGISTER_TYPE_F, - BRW_VERTICAL_STRIDE_0, - BRW_WIDTH_1, - BRW_HORIZONTAL_STRIDE_0, - BRW_SWIZZLE_XXXX, - WRITEMASK_XYZW); - } -} - -static void -emit_wm_load_opacity (struct brw_compile *compile, - int reg, - struct brw_reg *result) -{ - result[0] = result[1] = result[2] = result[3] = - result[4] = result[5] = result[6] = result[7] = - brw_reg (BRW_GENERAL_REGISTER_FILE, reg, 0, - BRW_REGISTER_TYPE_F, - BRW_VERTICAL_STRIDE_0, - BRW_WIDTH_1, - BRW_HORIZONTAL_STRIDE_1, - BRW_SWIZZLE_XXXX, - WRITEMASK_XYZW); -} - -static void -emit_wm_load_linear (struct brw_compile *compile, - int tmp, int reg, int msg) -{ - emit_wm_subpans_to_pixels (compile, tmp); - - brw_LINE (compile, - brw_null_reg(), - brw_vec1_grf (reg, 0), - brw_vec8_grf (tmp)); - brw_MAC (compile, - brw_message_reg(msg + 1), - brw_vec1_grf (reg, 1), - brw_vec8_grf (tmp + 2)); -} - -static void -emit_wm_load_radial (struct brw_compile *compile, - int reg, int msg) - -{ - struct brw_reg c1x = brw_vec1_grf (reg, 0); - struct brw_reg c1y = brw_vec1_grf (reg, 1); - struct brw_reg minus_r_sq = brw_vec1_grf (reg, 3); - struct brw_reg cdx = brw_vec1_grf (reg, 4); - struct brw_reg cdy = brw_vec1_grf (reg, 5); - struct brw_reg neg_4a = brw_vec1_grf (reg + 1, 0); - struct brw_reg inv_2a = brw_vec1_grf (reg + 1, 1); - - struct brw_reg tmp_x = brw_uw16_grf (30, 0); - struct brw_reg tmp_y = brw_uw16_grf (28, 0); - struct brw_reg det = brw_vec8_grf (22); - struct brw_reg b = brw_vec8_grf (20); - struct brw_reg c = brw_vec8_grf (18); - struct brw_reg pdx = brw_vec8_grf (16); - struct brw_reg pdy = brw_vec8_grf (14); - struct brw_reg t = brw_message_reg (msg + 1); - - /* cdx = (c₂x - c₁x) - * cdy = (c₂y - c₁y) - * dr = r₂-r₁ - * pdx = px - c₁x - * pdy = py - c₁y - * - * A = cdx² + cdy² - dr² - * B = -2·(pdx·cdx + pdy·cdy + r₁·dr) - * C = pdx² + pdy² - r₁² - * - * t = (-2·B ± ⎷(B² - 4·A·C)) / 2·A - */ - - brw_ADD (compile, pdx, vec8 (tmp_x), negate (c1x)); - brw_ADD (compile, pdy, vec8 (tmp_y), negate (c1y)); - - brw_LINE (compile, brw_null_reg (), cdx, pdx); - brw_MAC (compile, b, cdy, pdy); - - brw_MUL (compile, brw_null_reg (), pdx, pdx); - brw_MAC (compile, c, pdy, pdy); - brw_ADD (compile, c, c, minus_r_sq); - - brw_MUL (compile, brw_null_reg (), b, b); - brw_MAC (compile, det, neg_4a, c); - - /* XXX use rsqrt like i915?, it's faster and we need to mac anyway */ - brw_math (compile, - det, - BRW_MATH_FUNCTION_SQRT, - BRW_MATH_SATURATE_NONE, - 2, - det, - BRW_MATH_DATA_VECTOR, - BRW_MATH_PRECISION_FULL); - - /* XXX cmp, +- */ - - brw_ADD (compile, det, negate (det), negate (b)); - brw_ADD (compile, det, det, negate (b)); - brw_MUL (compile, t, det, inv_2a); -} - -static int -emit_wm_sample (struct brw_compile *compile, - union i965_shader_channel *channel, - int sampler, - int msg_base, int msg_len, - int dst, - struct brw_reg *result) -{ - int response_len, mask; - - if (channel->base.content == CAIRO_CONTENT_ALPHA) { - mask = 0x7000; - response_len = 2; - result[0] = result[1] = result[2] = result[3] = brw_vec8_grf (dst); - result[4] = result[5] = result[6] = result[7] = brw_vec8_grf (dst + 1); - } else { - mask = 0; - response_len = 8; - result[0] = brw_vec8_grf (dst + 0); - result[1] = brw_vec8_grf (dst + 2); - result[2] = brw_vec8_grf (dst + 4); - result[3] = brw_vec8_grf (dst + 6); - result[4] = brw_vec8_grf (dst + 1); - result[5] = brw_vec8_grf (dst + 3); - result[6] = brw_vec8_grf (dst + 5); - result[7] = brw_vec8_grf (dst + 7); - } - - brw_set_compression_control (compile, BRW_COMPRESSION_NONE); - - brw_set_mask_control (compile, BRW_MASK_DISABLE); - brw_MOV (compile, - get_element_ud (brw_vec8_grf (0), 2), - brw_imm_ud (mask)); - brw_set_mask_control (compile, BRW_MASK_ENABLE); - - brw_SAMPLE (compile, - brw_uw16_grf (dst, 0), - msg_base, - brw_uw8_grf (0, 0), - sampler + 1, /* binding table */ - sampler, - WRITEMASK_XYZW, - BRW_SAMPLER_MESSAGE_SIMD16_SAMPLE, - response_len, - msg_len, - 0 /* eot */); - - brw_set_compression_control (compile, BRW_COMPRESSION_COMPRESSED); - - return response_len; -} - -#define MAX_MSG_REGISTER 16 - -static void -emit_wm_load_channel (struct brw_compile *compile, - union i965_shader_channel *channel, - int *vue, - int *cue, - int *msg, - int *sampler, - int *grf, - struct brw_reg *result) -{ - switch (channel->type.fragment) { - case FS_NONE: - break; - - case FS_CONSTANT: - emit_wm_load_constant (compile, *cue, result); - *cue += 1; - break; - - case FS_RADIAL: - emit_wm_load_radial (compile, *cue, *msg); - *cue += 2; - - if (*msg + 3 > MAX_MSG_REGISTER) - *msg = 1; - - *grf += emit_wm_sample (compile, channel, *sampler, *msg, 3, *grf, result); - *sampler += 1; - *msg += 3; - break; - - case FS_LINEAR: - emit_wm_load_linear (compile, *grf, *cue, *msg); - *cue += 1; - - if (*msg + 3 > MAX_MSG_REGISTER) - *msg = 1; - - *grf += emit_wm_sample (compile, channel, *sampler, *msg, 3, *grf, result); - *sampler += 1; - *msg += 3; - break; - - case FS_SURFACE: - emit_wm_affine (compile, *grf, *cue, *msg); - *cue += 2; - - if (*msg + 5 > MAX_MSG_REGISTER) - *msg = 1; - - *grf += emit_wm_sample (compile, channel, *sampler, *msg, 5, *grf, result); - *sampler += 1; - *msg += 5; - break; - - case FS_SPANS: - emit_wm_load_opacity (compile, *vue, result); - *vue += 1; - break; - - case FS_GLYPHS: - emit_wm_glyph (compile, *grf, *vue, *msg); - *vue += 1; - - if (*msg + 5 > MAX_MSG_REGISTER) - *msg = 1; - - *grf += emit_wm_sample (compile, channel, *sampler, *msg, 5, *grf, result); - *sampler += 1; - *msg += 5; - break; - } -} - -static unsigned long -i965_wm_kernel_hash (const i965_shader_t *shader) -{ - unsigned long hash; - - hash = - (shader->source.type.fragment & 0xff) | - (shader->mask.type.fragment & 0xff) << 8 | - (shader->clip.type.fragment & 0xff) << 16; - if (shader->need_combine) - hash |= (1u + shader->op) << 24; - - return hash; -} - -static void -i965_wm_kernel_init (struct i965_wm_kernel *key, - const i965_shader_t *shader) -{ - key->entry.hash = i965_wm_kernel_hash (shader); -} - -static uint32_t -i965_shader_const_urb_length (i965_shader_t *shader) -{ - const int lengths[] = { 0, 1, 1, 4, 2, 0, 0 }; - int count = 0; /* 128-bit/16-byte increments */ - - count += lengths[shader->source.type.fragment]; - count += lengths[shader->mask.type.fragment]; - count += lengths[shader->clip.type.fragment]; - count += lengths[shader->dst.type.fragment]; - - return (count + 1) / 2; /* 256-bit/32-byte increments */ -} - -static uint32_t -i965_shader_pue_length (i965_shader_t *shader) -{ - return 1 + (shader->mask.type.vertex != VS_NONE); -} - -static uint32_t -create_wm_kernel (i965_device_t *device, - i965_shader_t *shader, - int *num_reg) -{ - struct brw_compile compile; - struct brw_reg source[8], mask[8], clip[8], dst[8]; - const uint32_t *program; - uint32_t size; - int msg, cue, vue, grf, sampler; - int i; - - struct i965_wm_kernel key, *cache; - cairo_status_t status; - uint32_t offset; - - i965_wm_kernel_init (&key, shader); - cache = _cairo_hash_table_lookup (device->wm_kernels, &key.entry); - if (cache != NULL) - return cache->offset; - - brw_compile_init (&compile, device->is_g4x); - - if (key.entry.hash == FS_CONSTANT && - to_intel_bo (shader->target->intel.drm.bo)->tiling) - { - struct brw_instruction *insn; - - assert (i965_shader_const_urb_length (shader) == 1); - brw_MOV (&compile, brw_message4_reg (2), brw_vec4_grf (2, 0)); - grf = 3; - - brw_push_insn_state (&compile); - brw_set_mask_control (&compile, BRW_MASK_DISABLE); /* ? */ - brw_MOV (&compile, - retype (brw_message_reg (1), BRW_REGISTER_TYPE_UD), - retype (brw_vec8_grf (1), BRW_REGISTER_TYPE_UD)); - brw_pop_insn_state (&compile); - - insn = brw_next_instruction (&compile, BRW_OPCODE_SEND); - insn->header.predicate_control = 0; - insn->header.compression_control = BRW_COMPRESSION_NONE; - insn->header.destreg__conditonalmod = 0; - - brw_instruction_set_destination (insn, - retype (vec16 (brw_acc_reg ()), - BRW_REGISTER_TYPE_UW)); - - brw_instruction_set_source0 (insn, - retype (brw_vec8_grf (0), - BRW_REGISTER_TYPE_UW)); - - brw_instruction_set_dp_write_message (insn, - 0, - BRW_DATAPORT_RENDER_TARGET_WRITE_SIMD16_SINGLE_SOURCE_REPLICATED, /* msg_control */ - BRW_DATAPORT_WRITE_MESSAGE_RENDER_TARGET_WRITE, /* msg_type */ - 3, - 1, /* pixel scoreboard */ - 0, - TRUE); - } - else - { - msg = 1; - cue = 2; - vue = cue + i965_shader_const_urb_length (shader); - grf = vue + i965_shader_pue_length (shader); - sampler = 0; - - brw_set_compression_control (&compile, BRW_COMPRESSION_COMPRESSED); - emit_wm_load_channel (&compile, &shader->source, - &vue, &cue, &msg, &sampler, &grf, - source); - emit_wm_load_channel (&compile, &shader->mask, - &vue, &cue, &msg, &sampler, &grf, - mask); - emit_wm_load_channel (&compile, &shader->clip, - &vue, &cue, &msg, &sampler, &grf, - clip); - emit_wm_load_channel (&compile, &shader->dst, - &vue, &cue, &msg, &sampler, &grf, - dst); - brw_set_compression_control (&compile, BRW_COMPRESSION_NONE); - - if (shader->need_combine) { - if (shader->mask.type.fragment != FS_NONE && - shader->clip.type.fragment != FS_NONE) - { - for (i = 0; i < 8; i++) - brw_MUL (&compile, mask[i], mask[i], clip[i]); - } - - /* XXX LERP ! */ - for (i = 0; i < 8; i++) - brw_MOV (&compile, brw_message_reg (2 + i), source[i]); - } else { - if (shader->mask.type.fragment != FS_NONE) { - if (shader->clip.type.fragment != FS_NONE) { - for (i = 0; i < 8; i++) - brw_MUL (&compile, mask[i], mask[i], clip[i]); - } - - for (i = 0; i < 8; i++) - brw_MUL (&compile, brw_message_reg (2 + i), source[i], mask[i]); - } else { - if (shader->clip.type.fragment != FS_NONE) { - for (i = 0; i < 8; i++) - brw_MUL (&compile, brw_message_reg (2 + i), source[i], clip[i]); - } else { - for (i = 0; i < 8; i++) - brw_MOV (&compile, brw_message_reg (2 + i), source[i]); - } - } - } - - brw_push_insn_state (&compile); - brw_set_mask_control (&compile, BRW_MASK_DISABLE); /* ? */ - brw_MOV (&compile, - retype (brw_message_reg (1), BRW_REGISTER_TYPE_UD), - retype (brw_vec8_grf (1), BRW_REGISTER_TYPE_UD)); - brw_pop_insn_state (&compile); - - brw_fb_WRITE (&compile, - retype (vec16 (brw_acc_reg ()), BRW_REGISTER_TYPE_UW), - 0, /* base reg */ - retype (brw_vec8_grf (0), BRW_REGISTER_TYPE_UW), - 0, /* binding table index */ - 2 + 8, /* msg length */ - 0, /* response length */ - TRUE); /* EOT */ - } - - program = brw_get_program (&compile, &size); - *num_reg = grf; - - i965_stream_align (&device->general, 64); - offset = i965_stream_emit (&device->general, program, size); - - cache = _cairo_freelist_alloc (&device->wm_kernel_freelist); - if (likely (cache != NULL)) { - i965_wm_kernel_init (cache, shader); - cache->offset = offset; - status = _cairo_hash_table_insert (device->wm_kernels, &cache->entry); - if (unlikely (status)) - _cairo_freelist_free (&device->wm_kernel_freelist, cache); - } - - return offset; -} - -static uint32_t -create_sf_kernel (i965_device_t *device, - i965_shader_t *shader) -{ - struct brw_compile compile; - const uint32_t *program; - uint32_t size; - int msg_len; - - brw_compile_init (&compile, device->is_g4x); - - switch (shader->mask.type.vertex) { - default: - case VS_NONE: - /* use curb plane eq in WM */ - msg_len = 1; - break; - - case VS_SPANS: - /* just a constant opacity */ - brw_MOV (&compile, - brw_message4_reg (1), - brw_vec4_grf (3, 0)); - msg_len = 2; - break; - - case VS_GLYPHS: - /* an offset+sf into the glyph cache */ - brw_MOV (&compile, - brw_acc_reg (), - brw_vec2_grf (3, 0)); - brw_MAC (&compile, - brw_message4_reg (1), - negate (brw_vec2_grf (1, 4)), - brw_imm_f (1./1024)); - msg_len = 2; - break; - } - - brw_urb_WRITE (&compile, - brw_null_reg (), - 0, - brw_vec8_grf (0), /* r0, will be copied to m0 */ - 0, /* allocate */ - 1, /* used */ - msg_len, - 0, /* response len */ - 1, /* eot */ - 1, /* writes complete */ - 0, /* offset */ - BRW_URB_SWIZZLE_NONE); - - program = brw_get_program (&compile, &size); - - i965_stream_align (&device->general, 64); - return i965_stream_emit (&device->general, program, size); -} - -static uint32_t -i965_sf_kernel (const i965_shader_t *shader) -{ - return shader->mask.type.vertex; -} - -static void -i965_sf_state_init (struct i965_sf_state *key, - const i965_shader_t *shader) -{ - key->entry.hash = i965_sf_kernel (shader); -} - -cairo_bool_t -i965_sf_state_equal (const void *A, const void *B) -{ - const cairo_hash_entry_t *a = A, *b = B; - return a->hash == b->hash; -} - -/* - * Sets up the SF state pointing at an SF kernel. - * - * The SF kernel does coord interp: for each attribute, - * calculate dA/dx and dA/dy. Hand these interpolation coefficients - * back to SF which then hands pixels off to WM. - */ -static uint32_t -gen4_create_sf_state (i965_device_t *device, - i965_shader_t *shader) -{ - struct brw_sf_unit_state *state; - struct i965_sf_state key, *cache; - cairo_status_t status; - uint32_t offset; - - i965_sf_state_init (&key, shader); - if (i965_sf_state_equal (&key, &device->sf_state)) - return device->sf_state.offset; - - cache = _cairo_hash_table_lookup (device->sf_states, &key.entry); - if (cache != NULL) { - offset = cache->offset; - goto DONE; - } - - offset = create_sf_kernel (device, shader); - - state = i965_stream_alloc (&device->general, 32, sizeof (*state)); - memset (state, 0, sizeof (*state)); - - state->thread0.grf_reg_count = BRW_GRF_BLOCKS (3); - assert ((offset & 63) == 0); - state->thread0.kernel_start_pointer = offset >> 6; - state->sf1.single_program_flow = 1; - state->thread3.urb_entry_read_length = 1; /* 1 URB per vertex */ - state->thread3.urb_entry_read_offset = 1; - state->thread3.dispatch_grf_start_reg = 3; - state->thread4.max_threads = SF_MAX_THREADS - 1; - state->thread4.urb_entry_allocation_size = URB_SF_ENTRY_SIZE - 1; - state->thread4.nr_urb_entries = URB_SF_ENTRIES; - state->sf6.dest_org_vbias = 0x8; - state->sf6.dest_org_hbias = 0x8; - - offset = i965_stream_offsetof (&device->general, state); - - cache = _cairo_freelist_alloc (&device->sf_freelist); - if (likely (cache != NULL)) { - i965_sf_state_init (cache, shader); - cache->offset = offset; - status = _cairo_hash_table_insert (device->sf_states, &cache->entry); - if (unlikely (status)) - _cairo_freelist_free (&device->sf_freelist, cache); - } - - DONE: - i965_sf_state_init (&device->sf_state, shader); - device->sf_state.offset = offset; - - return offset; -} - -static unsigned long -i965_shader_sampler_hash (const i965_shader_t *shader) -{ - unsigned long hash = 0; - unsigned int offset = 0; - - if (shader->source.base.bo != NULL) { - hash |= (shader->source.base.filter << offset) | - (shader->source.base.extend << (offset + 4)); - offset += 8; - } - - if (shader->mask.base.bo != NULL) { - hash |= (shader->mask.base.filter << offset) | - (shader->mask.base.extend << (offset + 4)); - offset += 8; - } - - if (shader->clip.base.bo != NULL) { - hash |= (shader->clip.base.filter << offset) | - (shader->clip.base.extend << (offset + 4)); - offset += 8; - } - - if (shader->dst.base.bo != NULL) { - hash |= (shader->dst.base.filter << offset) | - (shader->dst.base.extend << (offset + 4)); - offset += 8; - } - - return hash; -} - -static void -i965_sampler_init (struct i965_sampler *key, - const i965_shader_t *shader) -{ - key->entry.hash = i965_shader_sampler_hash (shader); -} - -static void -emit_sampler_channel (i965_device_t *device, - const union i965_shader_channel *channel, - uint32_t border_color) -{ - struct brw_sampler_state *state; - - state = i965_stream_alloc (&device->general, 0, sizeof (*state)); - memset (state, 0, sizeof (*state)); - - state->ss0.lod_preclamp = 1; /* GL mode */ - - state->ss0.border_color_mode = BRW_BORDER_COLOR_MODE_LEGACY; - - state->ss0.min_filter = channel->base.filter; - state->ss0.mag_filter = channel->base.filter; - - state->ss1.r_wrap_mode = channel->base.extend; - state->ss1.s_wrap_mode = channel->base.extend; - state->ss1.t_wrap_mode = channel->base.extend; - - assert ((border_color & 31) == 0); - state->ss2.border_color_pointer = border_color >> 5; -} - -static uint32_t -emit_sampler_state_table (i965_device_t *device, - i965_shader_t *shader) -{ - struct i965_sampler key, *cache; - cairo_status_t status; - uint32_t offset; - - if (device->border_color_offset == (uint32_t) -1) { - struct brw_sampler_legacy_border_color *border_color; - - border_color = i965_stream_alloc (&device->general, 32, - sizeof (*border_color)); - border_color->color[0] = 0; /* R */ - border_color->color[1] = 0; /* G */ - border_color->color[2] = 0; /* B */ - border_color->color[3] = 0; /* A */ - - device->border_color_offset = i965_stream_offsetof (&device->general, - border_color); - } else { - i965_sampler_init (&key, shader); - cache = _cairo_hash_table_lookup (device->samplers, &key.entry); - if (cache != NULL) - return cache->offset; - } - - i965_stream_align (&device->general, 32); - offset = device->general.used; - if (shader->source.base.bo != NULL) { - emit_sampler_channel (device, - &shader->source, - device->border_color_offset); - } - if (shader->mask.base.bo != NULL) { - emit_sampler_channel (device, - &shader->mask, - device->border_color_offset); - } - if (shader->clip.base.bo != NULL) { - emit_sampler_channel (device, - &shader->clip, - device->border_color_offset); - } - if (shader->dst.base.bo != NULL) { - emit_sampler_channel (device, - &shader->dst, - device->border_color_offset); - } - - cache = _cairo_freelist_alloc (&device->sampler_freelist); - if (likely (cache != NULL)) { - i965_sampler_init (cache, shader); - cache->offset = offset; - status = _cairo_hash_table_insert (device->samplers, &cache->entry); - if (unlikely (status)) - _cairo_freelist_free (&device->sampler_freelist, cache); - } - - return offset; -} - -static void -i965_cc_state_init (struct i965_cc_state *key, - const i965_shader_t *shader) -{ - uint32_t src_blend, dst_blend; - - if (shader->need_combine) - src_blend = dst_blend = 0; - else - i965_shader_get_blend_cntl (shader, &src_blend, &dst_blend); - - key->entry.hash = src_blend | ((dst_blend & 0xffff) << 16); -} - -cairo_bool_t -i965_cc_state_equal (const void *A, const void *B) -{ - const cairo_hash_entry_t *a = A, *b = B; - return a->hash == b->hash; -} - -static uint32_t -cc_state_emit (i965_device_t *device, i965_shader_t *shader) -{ - struct brw_cc_unit_state *state; - struct i965_cc_state key, *cache; - cairo_status_t status; - uint32_t src_blend, dst_blend; - uint32_t offset; - - i965_cc_state_init (&key, shader); - if (i965_cc_state_equal (&key, &device->cc_state)) - return device->cc_state.offset; - - cache = _cairo_hash_table_lookup (device->cc_states, &key.entry); - if (cache != NULL) { - offset = cache->offset; - goto DONE; - } - - if (shader->need_combine) - src_blend = dst_blend = 0; - else - i965_shader_get_blend_cntl (shader, &src_blend, &dst_blend); - - state = i965_stream_alloc (&device->general, 64, sizeof (*state)); - memset (state, 0, sizeof (*state)); - - /* XXX Note errata, need to flush render cache when blend_enable 0 -> 1 */ - /* XXX 2 source blend */ - state->cc3.blend_enable = ! shader->need_combine; - state->cc5.ia_blend_function = BRW_BLENDFUNCTION_ADD; - state->cc5.ia_src_blend_factor = src_blend; - state->cc5.ia_dest_blend_factor = dst_blend; - state->cc6.blend_function = BRW_BLENDFUNCTION_ADD; - state->cc6.clamp_post_alpha_blend = 1; - state->cc6.clamp_pre_alpha_blend = 1; - state->cc6.src_blend_factor = src_blend; - state->cc6.dest_blend_factor = dst_blend; - - offset = i965_stream_offsetof (&device->general, state); - - cache = _cairo_freelist_alloc (&device->cc_freelist); - if (likely (cache != NULL)) { - i965_cc_state_init (cache, shader); - cache->offset = offset; - status = _cairo_hash_table_insert (device->cc_states, &cache->entry); - if (unlikely (status)) - _cairo_freelist_free (&device->cc_freelist, cache); - } - - DONE: - i965_cc_state_init (&device->cc_state, shader); - device->cc_state.offset = offset; - - return offset; -} - -static void -i965_wm_state_init (struct i965_wm_state *key, - const i965_shader_t *shader) -{ - key->kernel = i965_wm_kernel_hash (shader); - key->sampler = i965_shader_sampler_hash (shader); - - key->entry.hash = key->kernel ^ ((key->sampler) << 16 | (key->sampler >> 16)); -} - -cairo_bool_t -i965_wm_state_equal (const void *A, const void *B) -{ - const struct i965_wm_state *a = A, *b = B; - - if (a->entry.hash != b->entry.hash) - return FALSE; - - return a->kernel == b->kernel && a->sampler == b->sampler; -} - -static int -i965_shader_binding_table_count (i965_shader_t *shader) -{ - int count; - - count = 1; - if (shader->source.type.fragment != FS_CONSTANT) - count++; - switch (shader->mask.type.fragment) { - case FS_NONE: - case FS_CONSTANT: - case FS_SPANS: - break; - case FS_LINEAR: - case FS_RADIAL: - case FS_SURFACE: - case FS_GLYPHS: - count++; - } - if (shader->clip.type.fragment == FS_SURFACE) - count++; - if (shader->dst.type.fragment == FS_SURFACE) - count++; - - return count; -} - -static uint32_t -gen4_create_wm_state (i965_device_t *device, - i965_shader_t *shader) -{ - struct brw_wm_unit_state *state; - uint32_t sampler; - uint32_t kernel; - - struct i965_wm_state key, *cache; - cairo_status_t status; - int num_reg; - - i965_wm_state_init (&key, shader); - if (i965_wm_state_equal (&key, &device->wm_state)) - return device->wm_state.offset; - - cache = _cairo_hash_table_lookup (device->wm_states, &key.entry); - if (cache != NULL) { - device->wm_state = *cache; - return cache->offset; - } - - kernel = create_wm_kernel (device, shader, &num_reg); - sampler = emit_sampler_state_table (device, shader); - - state = i965_stream_alloc (&device->general, 32, sizeof (*state)); - memset (state, 0, sizeof (*state)); - state->thread0.grf_reg_count = BRW_GRF_BLOCKS (num_reg); - assert ((kernel & 63) == 0); - state->thread0.kernel_start_pointer = kernel >> 6; - - state->thread3.dispatch_grf_start_reg = 2; - - state->wm4.sampler_count = 1; /* 1-4 samplers used */ - assert ((sampler & 31) == 0); - state->wm4.sampler_state_pointer = sampler >> 5; - if (device->is_g4x) - state->wm5.max_threads = PS_MAX_THREADS_CTG - 1; - else - state->wm5.max_threads = PS_MAX_THREADS_BRW - 1; - state->wm5.thread_dispatch_enable = 1; - - if (device->is_g4x) { - /* XXX contiguous 32 pixel dispatch */ - } - state->wm5.enable_16_pix = 1; - /* 8 pixel dispatch and friends */ - //state->wm5.early_depth_test = 1; - - state->thread1.binding_table_entry_count = i965_shader_binding_table_count(shader); - state->thread3.urb_entry_read_length = i965_shader_pue_length (shader); - state->thread3.const_urb_entry_read_length = i965_shader_const_urb_length (shader); - - key.offset = i965_stream_offsetof (&device->general, state); - - cache = _cairo_freelist_alloc (&device->wm_state_freelist); - if (likely (cache != NULL)) { - *cache = key; - status = _cairo_hash_table_insert (device->wm_states, &cache->entry); - if (unlikely (status)) - _cairo_freelist_free (&device->wm_state_freelist, cache); - } - - device->wm_state = key; - return key.offset; -} - -static uint32_t -vs_unit_state_emit (i965_device_t *device) -{ - if (device->vs_offset == (uint32_t) -1) { - struct brw_vs_unit_state *state; - - /* Set up the vertex shader to be disabled (passthrough) */ - state = i965_stream_alloc (&device->general, 32, sizeof (*state)); - memset (state, 0, sizeof (*state)); - - state->thread4.nr_urb_entries = URB_VS_ENTRIES; - state->thread4.urb_entry_allocation_size = URB_VS_ENTRY_SIZE - 1; - state->vs6.vert_cache_disable = 1; - - device->vs_offset = i965_stream_offsetof (&device->general, state); - } - - return device->vs_offset; -} - -static uint32_t -i965_get_card_format (cairo_format_t format) -{ - switch (format) { - case CAIRO_FORMAT_ARGB32: - return BRW_SURFACEFORMAT_B8G8R8A8_UNORM; - case CAIRO_FORMAT_RGB24: - return BRW_SURFACEFORMAT_B8G8R8X8_UNORM; - case CAIRO_FORMAT_RGB16_565: - return BRW_SURFACEFORMAT_B5G6R5_UNORM; - case CAIRO_FORMAT_A8: - return BRW_SURFACEFORMAT_A8_UNORM; - case CAIRO_FORMAT_A1: - case CAIRO_FORMAT_INVALID: - default: - ASSERT_NOT_REACHED; - return 0; - } -} - -static uint32_t -i965_get_dest_format (cairo_format_t format) -{ - switch (format) { - case CAIRO_FORMAT_ARGB32: - case CAIRO_FORMAT_RGB24: - return BRW_SURFACEFORMAT_B8G8R8A8_UNORM; - case CAIRO_FORMAT_RGB16_565: - return BRW_SURFACEFORMAT_B5G6R5_UNORM; - case CAIRO_FORMAT_A8: - return BRW_SURFACEFORMAT_A8_UNORM; - case CAIRO_FORMAT_A1: - case CAIRO_FORMAT_INVALID: - default: - ASSERT_NOT_REACHED; - return 0; - } -} - -/* XXX silly inline due to compiler bug... */ -static inline void -i965_stream_add_pending_relocation (i965_stream_t *stream, - uint32_t target_offset, - uint32_t read_domains, - uint32_t write_domain, - uint32_t delta) -{ - int n; - - n = stream->num_pending_relocations++; - assert (n < stream->max_pending_relocations); - - stream->pending_relocations[n].offset = target_offset; - stream->pending_relocations[n].read_domains = read_domains; - stream->pending_relocations[n].write_domain = write_domain; - stream->pending_relocations[n].delta = delta; -} - -static uint32_t -emit_surface_state (i965_device_t *device, - cairo_bool_t is_target, - intel_bo_t *bo, - cairo_format_t format, - int width, int height, int stride, - int type) -{ - struct brw_surface_state *state; - uint32_t write_domain, read_domains; - uint32_t offset; - - state = i965_stream_alloc (&device->surface, 32, sizeof (*state)); - memset (state, 0, sizeof (*state)); - - state->ss0.surface_type = type; - if (is_target) - state->ss0.surface_format = i965_get_dest_format (format); - else - state->ss0.surface_format = i965_get_card_format (format); - - state->ss0.data_return_format = BRW_SURFACERETURNFORMAT_FLOAT32; - state->ss0.color_blend = 1; - if (is_target && device->is_g4x) - state->ss0.render_cache_read_mode = 1; - - state->ss1.base_addr = bo->offset; - - state->ss2.height = height - 1; - state->ss2.width = width - 1; - state->ss3.pitch = stride - 1; - state->ss3.tile_walk = bo->tiling == I915_TILING_Y; - state->ss3.tiled_surface = bo->tiling != I915_TILING_NONE; - - if (is_target) { - read_domains = I915_GEM_DOMAIN_RENDER; - write_domain = I915_GEM_DOMAIN_RENDER; - } else { - read_domains = I915_GEM_DOMAIN_SAMPLER; - write_domain = 0; - } - - offset = i965_stream_offsetof (&device->surface, state); - i965_emit_relocation (device, &device->surface, - bo, 0, - read_domains, write_domain, - offset + offsetof (struct brw_surface_state, ss1.base_addr)); - return offset; -} - -static uint32_t -emit_surface_state_for_shader (i965_device_t *device, - const union i965_shader_channel *channel) -{ - int type = BRW_SURFACE_2D; - - assert (channel->type.fragment != FS_NONE); - assert (channel->type.fragment != FS_CONSTANT); - - if (channel->type.fragment != FS_SURFACE) - type = BRW_SURFACE_1D; - - return emit_surface_state (device, FALSE, - channel->base.bo, - channel->base.format, - channel->base.width, - channel->base.height, - channel->base.stride, - type); -} - -cairo_bool_t -i965_wm_binding_equal (const void *A, - const void *B) -{ - const struct i965_wm_binding *a = A, *b = B; - - if (a->entry.hash != b->entry.hash) - return FALSE; - - if (a->size != b->size) - return FALSE; - - return memcmp (a->table, b->table, sizeof (uint32_t) * a->size) == 0; -} - -static void -i965_wm_binding_init (struct i965_wm_binding *state, - const uint32_t *table, - int size) -{ - int n; - - state->entry.hash = size; - state->size = size; - - for (n = 0; n < size; n++) { - state->table[n] = table[n]; - state->entry.hash ^= (table[n] << (8 * n)) | - (table[n] >> (32 - (8*n))); - } -} - -static uint32_t -emit_binding_table (i965_device_t *device, - i965_shader_t *shader) -{ - intel_bo_t *bo; - struct i965_wm_binding key, *cache; - uint32_t *table; - int n = 0; - - table = i965_stream_alloc (&device->surface, 32, 5 * sizeof (uint32_t)); - if (shader->target->stream != device->surface.serial) { - shader->target->stream = device->surface.serial; - shader->target->offset = emit_surface_state (device, - TRUE, - to_intel_bo (shader->target->intel.drm.bo), - shader->target->intel.drm.format, - shader->target->intel.drm.width, - shader->target->intel.drm.height, - shader->target->intel.drm.stride, - BRW_SURFACE_2D); - } - table[n++] = shader->target->offset; - - bo = shader->source.base.bo; - if (bo != NULL) { - if (bo->opaque0 != device->surface.serial) { - bo->opaque0 = device->surface.serial; - bo->opaque1 = emit_surface_state_for_shader (device, &shader->source); - } - table[n++] = bo->opaque1; - } - - bo = shader->mask.base.bo; - if (bo != NULL) { - if (bo->opaque0 != device->surface.serial) { - bo->opaque0 = device->surface.serial; - bo->opaque1 = emit_surface_state_for_shader (device, &shader->mask); - } - table[n++] = bo->opaque1; - } - - bo = shader->clip.base.bo; - if (bo != NULL) { - if (bo->opaque0 != device->surface.serial) { - bo->opaque0 = device->surface.serial; - bo->opaque1 = emit_surface_state_for_shader (device, &shader->clip); - } - table[n++] = bo->opaque1; - } - - bo = shader->dst.base.bo; - if (bo != NULL) { - if (bo->opaque0 != device->surface.serial) { - bo->opaque0 = device->surface.serial; - bo->opaque1 = emit_surface_state_for_shader (device, &shader->dst); - } - table[n++] = bo->opaque1; - } - - i965_wm_binding_init (&key, table, n); - key.offset = i965_stream_offsetof (&device->surface, table); - - if (i965_wm_binding_equal (&key, &device->wm_binding)) { - device->surface.used = key.offset; - return device->wm_binding.offset; - } - - cache = _cairo_hash_table_lookup (device->wm_bindings, &key.entry); - if (cache != NULL) { - device->surface.used = key.offset; - key.offset = cache->offset; - } - - device->wm_binding = key; - return key.offset; -} - -static void -i965_emit_invariants (i965_device_t *device) -{ - OUT_BATCH (BRW_CS_URB_STATE | 0); - OUT_BATCH (((URB_CS_ENTRY_SIZE-1) << 4) | (URB_CS_ENTRIES << 0)); -} - -static void -i965_emit_urb_fences (i965_device_t *device) -{ - int urb_vs_start, urb_vs_size; - int urb_gs_start, urb_gs_size; - int urb_clip_start, urb_clip_size; - int urb_sf_start, urb_sf_size; - int urb_cs_start, urb_cs_size; - - if (device->have_urb_fences) - return; - - /* URB fence */ - urb_vs_start = 0; - urb_vs_size = URB_VS_ENTRIES * URB_VS_ENTRY_SIZE; - urb_gs_start = urb_vs_start + urb_vs_size; - urb_gs_size = URB_GS_ENTRIES * URB_GS_ENTRY_SIZE; - urb_clip_start = urb_gs_start + urb_gs_size; - urb_clip_size = URB_CLIP_ENTRIES * URB_CLIP_ENTRY_SIZE; - urb_sf_start = urb_clip_start + urb_clip_size; - urb_sf_size = URB_SF_ENTRIES * URB_SF_ENTRY_SIZE; - urb_cs_start = urb_sf_start + urb_sf_size; - urb_cs_size = URB_CS_ENTRIES * URB_CS_ENTRY_SIZE; - - /* erratum: URB_FENCE must not cross a 64-byte cache-line */ - while ((device->batch.used & 63) > 64-12) - OUT_BATCH (MI_NOOP); - OUT_BATCH (BRW_URB_FENCE | - UF0_CS_REALLOC | - UF0_SF_REALLOC | - UF0_CLIP_REALLOC | - UF0_GS_REALLOC | - UF0_VS_REALLOC | - 1); - OUT_BATCH (((urb_clip_start + urb_clip_size) << UF1_CLIP_FENCE_SHIFT) | - ((urb_gs_start + urb_gs_size) << UF1_GS_FENCE_SHIFT) | - ((urb_vs_start + urb_vs_size) << UF1_VS_FENCE_SHIFT)); - OUT_BATCH (((urb_cs_start + urb_cs_size) << UF2_CS_FENCE_SHIFT) | - ((urb_sf_start + urb_sf_size) << UF2_SF_FENCE_SHIFT)); - - device->have_urb_fences = TRUE; - device->constants_size = 0; -} - -static void -i965_emit_base (i965_device_t *device) -{ - OUT_BATCH (BRW_STATE_BASE_ADDRESS | 4); - if (likely (device->general.num_pending_relocations == 0)) { - i965_stream_add_pending_relocation (&device->general, - device->batch.used, - I915_GEM_DOMAIN_INSTRUCTION, 0, - BASE_ADDRESS_MODIFY); - } - OUT_BATCH (0); /* pending relocation */ - - if (likely (device->surface.num_pending_relocations == 0)) { - i965_stream_add_pending_relocation (&device->surface, - device->batch.used, - I915_GEM_DOMAIN_INSTRUCTION, 0, - BASE_ADDRESS_MODIFY); - } - OUT_BATCH (0); /* pending relocation */ - - OUT_BATCH (0 | BASE_ADDRESS_MODIFY); - /* general state max addr, disabled */ - OUT_BATCH (0x10000000 | BASE_ADDRESS_MODIFY); - /* media object state max addr, disabled */ - OUT_BATCH (0x10000000 | BASE_ADDRESS_MODIFY); -} - -static void -i965_emit_vertex_element (i965_device_t *device, - i965_shader_t *shader) -{ - uint32_t offset; - uint32_t type; - int nelem; - - type = 0; - nelem = 1; - if (shader->mask.type.vertex == VS_SPANS || - shader->mask.type.vertex == VS_GLYPHS) - { - type = shader->mask.type.vertex; - nelem++; - } - - if (type == device->vertex_type) - return; - device->vertex_type = type; - - offset = 0; - - OUT_BATCH (BRW_3DSTATE_VERTEX_ELEMENTS | ((2 * nelem) - 1)); - OUT_BATCH ((0 << VE0_VERTEX_BUFFER_INDEX_SHIFT) | - VE0_VALID | - (BRW_SURFACEFORMAT_R32G32_FLOAT << VE0_FORMAT_SHIFT) | - (offset << VE0_OFFSET_SHIFT)); - OUT_BATCH ((BRW_VFCOMPONENT_STORE_SRC << VE1_VFCOMPONENT_0_SHIFT) | - (BRW_VFCOMPONENT_STORE_SRC << VE1_VFCOMPONENT_1_SHIFT) | - (BRW_VFCOMPONENT_STORE_0 << VE1_VFCOMPONENT_2_SHIFT) | - (BRW_VFCOMPONENT_STORE_1_FLT << VE1_VFCOMPONENT_3_SHIFT) | - (4 << VE1_DESTINATION_ELEMENT_OFFSET_SHIFT)); - offset += 8; - - assert (shader->source.type.vertex == VS_NONE); - switch (shader->mask.type.vertex) { - default: - case VS_NONE: - break; - - case VS_SPANS: - OUT_BATCH((0 << VE0_VERTEX_BUFFER_INDEX_SHIFT) | - VE0_VALID | - (BRW_SURFACEFORMAT_R32_FLOAT << VE0_FORMAT_SHIFT) | - (offset << VE0_OFFSET_SHIFT)); - OUT_BATCH((BRW_VFCOMPONENT_STORE_SRC << VE1_VFCOMPONENT_0_SHIFT) | - (BRW_VFCOMPONENT_NOSTORE << VE1_VFCOMPONENT_1_SHIFT) | - (BRW_VFCOMPONENT_NOSTORE << VE1_VFCOMPONENT_2_SHIFT) | - (BRW_VFCOMPONENT_NOSTORE << VE1_VFCOMPONENT_3_SHIFT) | - (8 << VE1_DESTINATION_ELEMENT_OFFSET_SHIFT)); - - offset += 4; - break; - - case VS_GLYPHS: - OUT_BATCH((0 << VE0_VERTEX_BUFFER_INDEX_SHIFT) | - VE0_VALID | - (BRW_SURFACEFORMAT_R16G16_FLOAT << VE0_FORMAT_SHIFT) | - (offset << VE0_OFFSET_SHIFT)); - OUT_BATCH((BRW_VFCOMPONENT_STORE_SRC << VE1_VFCOMPONENT_0_SHIFT) | - (BRW_VFCOMPONENT_STORE_SRC << VE1_VFCOMPONENT_1_SHIFT) | - (BRW_VFCOMPONENT_NOSTORE << VE1_VFCOMPONENT_2_SHIFT) | - (BRW_VFCOMPONENT_NOSTORE << VE1_VFCOMPONENT_3_SHIFT) | - (8 << VE1_DESTINATION_ELEMENT_OFFSET_SHIFT)); - - offset += 4; - break; - } - assert (shader->clip.type.vertex == VS_NONE); - assert (shader->dst.type.vertex == VS_NONE); - - device->vertex_size = offset; - i965_stream_align (&device->vertex, device->vertex_size); - device->vertex.committed = device->vertex.used; - - device->rectangle_size = 3 * offset; -} - -static cairo_bool_t -i965_shader_needs_surface_update (const i965_shader_t *shader, - const i965_device_t *device) -{ - return device->target != shader->target || shader->target->stream == 0 || - (shader->source.base.bo != NULL && device->source != shader->source.base.bo) || - (shader->mask.base.bo != NULL && device->mask != shader->mask.base.bo) || - (shader->clip.base.bo != NULL && device->clip != shader->clip.base.bo); -} - -static cairo_bool_t -i965_shader_needs_constants_update (const i965_shader_t *shader, - const i965_device_t *device) -{ - if (shader->constants_size == 0) - return FALSE; - - if (device->constants_size != shader->constants_size) - return TRUE; - - return memcmp (device->constants, - shader->constants, - sizeof (float) * shader->constants_size); -} - -static cairo_bool_t -i965_shader_needs_state_update (const i965_shader_t *shader, - const i965_device_t *device) -{ - union { - struct i965_sf_state sf; - struct i965_wm_state wm; - struct i965_cc_state cc; - } state; - - i965_sf_state_init (&state.sf, shader); - if (! i965_sf_state_equal (&state.sf, &device->sf_state)) - return TRUE; - - i965_wm_state_init (&state.wm, shader); - if (! i965_wm_state_equal (&state.wm, &device->wm_state)) - return TRUE; - - i965_cc_state_init (&state.cc, shader); - if (! i965_cc_state_equal (&state.cc, &device->cc_state)) - return TRUE; - - return FALSE; -} - -static void -i965_emit_composite (i965_device_t *device, - i965_shader_t *shader) -{ - uint32_t draw_rectangle; - - if (i965_shader_needs_surface_update (shader, device)) { - uint32_t offset; - - offset = emit_binding_table (device, shader); - - /* Only the PS uses the binding table */ - OUT_BATCH (BRW_3DSTATE_BINDING_TABLE_POINTERS | 4); - OUT_BATCH (0); /* vs */ - OUT_BATCH (0); /* gs */ - OUT_BATCH (0); /* clip */ - OUT_BATCH (0); /* sf */ - OUT_BATCH (offset); - - device->target = shader->target; - device->source = shader->source.base.bo; - device->mask = shader->mask.base.bo; - device->clip = shader->clip.base.bo; - } - - /* The drawing rectangle clipping is always on. Set it to values that - * shouldn't do any clipping. - */ - draw_rectangle = DRAW_YMAX (shader->target->intel.drm.height) | - DRAW_XMAX (shader->target->intel.drm.width); - if (draw_rectangle != device->draw_rectangle) { - OUT_BATCH (BRW_3DSTATE_DRAWING_RECTANGLE | 2); - OUT_BATCH (0x00000000); /* ymin, xmin */ - OUT_BATCH (draw_rectangle); - OUT_BATCH (0x00000000); /* yorigin, xorigin */ - device->draw_rectangle = draw_rectangle; - } - - /* skip the depth buffer */ - /* skip the polygon stipple */ - /* skip the polygon stipple offset */ - /* skip the line stipple */ - - /* Set the pointers to the 3d pipeline state */ - if (i965_shader_needs_state_update (shader, device)) { - OUT_BATCH (BRW_3DSTATE_PIPELINED_POINTERS | 5); - OUT_BATCH (vs_unit_state_emit (device)); - OUT_BATCH (BRW_GS_DISABLE); - OUT_BATCH (BRW_CLIP_DISABLE); - OUT_BATCH (gen4_create_sf_state (device, shader)); - OUT_BATCH (gen4_create_wm_state (device, shader)); - OUT_BATCH (cc_state_emit (device, shader)); - - /* Once the units are initialized, we need to setup the fences */ - i965_emit_urb_fences (device); - } - - if (i965_shader_needs_constants_update (shader, device)) { - uint32_t size = (sizeof (float) * shader->constants_size + 63) & -64; - - /* XXX reuse clear/black/white - * ht! - */ - - /* XXX CONSTANT_BUFFER Address Offset Disable? INSTPM? */ - - assert (size <= 64 * URB_CS_ENTRY_SIZE); - assert (((sizeof (float) * shader->constants_size + 31) & -32) == 32 * i965_shader_const_urb_length (shader)); - - device->constants = i965_stream_alloc (&device->surface, 64, size); - memcpy (device->constants, shader->constants, size); - device->constants_size = shader->constants_size; - - OUT_BATCH (BRW_CONSTANT_BUFFER | (1 << 8)); - OUT_BATCH (i965_stream_offsetof (&device->surface, device->constants) + size / 64 - 1); - } - - i965_emit_vertex_element (device, shader); -} - -void -i965_flush_vertices (i965_device_t *device) -{ - int vertex_count, vertex_start; - - if (device->vertex.used == device->vertex.committed) - return; - - assert (device->vertex.used > device->vertex.committed); - - vertex_start = device->vertex.committed / device->vertex_size; - vertex_count = - (device->vertex.used - device->vertex.committed) / device->vertex_size; - - assert (vertex_count); - - if (device->vertex_size != device->last_vertex_size) { - i965_stream_add_pending_relocation (&device->vertex, - device->batch.used + 8, - I915_GEM_DOMAIN_VERTEX, 0, - 0); - - OUT_BATCH (BRW_3DSTATE_VERTEX_BUFFERS | 3); - OUT_BATCH ((0 << VB0_BUFFER_INDEX_SHIFT) | - VB0_VERTEXDATA | - (device->vertex_size << VB0_BUFFER_PITCH_SHIFT)); - OUT_BATCH (0); /* pending relocation */ - OUT_BATCH (0); - OUT_BATCH (0); - device->last_vertex_size = device->vertex_size; - } - - OUT_BATCH (BRW_3DPRIMITIVE | - BRW_3DPRIMITIVE_VERTEX_SEQUENTIAL | - (_3DPRIM_RECTLIST << BRW_3DPRIMITIVE_TOPOLOGY_SHIFT) | - (0 << 9) | - 4); - OUT_BATCH (vertex_count); /* vertex count per instance */ - OUT_BATCH (vertex_start); /* start vertex offset */ - OUT_BATCH (1); /* single instance */ - OUT_BATCH (0); - OUT_BATCH (0); - - device->vertex.committed = device->vertex.used; -} - -void -i965_finish_vertices (i965_device_t *device) -{ - cairo_status_t status; - - i965_flush_vertices (device); - - i965_stream_commit (device, &device->vertex); - - if (! i965_shader_check_aperture (device->shader, device)) { - status = i965_device_flush (device); - if (unlikely (status)) - longjmp (device->shader->unwind, status); - - status = i965_shader_commit (device->shader, device); - assert (status == CAIRO_STATUS_SUCCESS); - } - - device->last_vertex_size = 0; -} - -static cairo_bool_t -i965_shader_needs_update (const i965_shader_t *shader, - const i965_device_t *device) -{ - if (i965_shader_needs_surface_update (shader, device)) - return TRUE; - - if (i965_shader_needs_constants_update (shader, device)) - return TRUE; - - return i965_shader_needs_state_update (shader, device); -} - -static void -i965_shader_reduce (i965_shader_t *shader, - const i965_device_t *device) -{ - if (shader->op == CAIRO_OPERATOR_OVER && - (i965_wm_kernel_hash (shader) & ~0xff) == 0 && - (shader->source.base.content & CAIRO_CONTENT_ALPHA) == 0) - { - shader->op = CAIRO_OPERATOR_SOURCE; - } -} - -cairo_status_t -i965_shader_commit (i965_shader_t *shader, - i965_device_t *device) -{ - cairo_status_t status; - - if (! shader->committed) { - device->shader = shader; - - status = i965_shader_setup_dst (shader); - if (unlikely (status)) - return status; - - i965_shader_setup_constants (shader); - i965_shader_reduce (shader, device); - - if ((status = setjmp (shader->unwind))) - return status; - - shader->committed = TRUE; - } - - if (! i965_shader_needs_update (shader, device)) - return CAIRO_STATUS_SUCCESS; - - /* XXX too many guestimates about likely maximum sizes */ -recheck: - if (device->batch.used + 128 > device->batch.size || - ! i965_shader_check_aperture (shader, device)) - { - status = i965_device_flush (device); - if (unlikely (status)) - longjmp (shader->unwind, status); - } - - i965_flush_vertices (device); - - if (unlikely (device->surface.used + 128 > device->surface.size || - device->surface.num_relocations + 4 > device->surface.max_relocations)) - { - i965_stream_commit (device, &device->surface); - goto recheck; - } - - if (unlikely (device->general.used + 512 > device->general.size)) { - i965_stream_commit (device, &device->general); - i965_general_state_reset (device); - goto recheck; - } - - if (unlikely (device->batch.used == 0)) - i965_emit_invariants (device); - - if (unlikely (device->surface.num_pending_relocations == 0 || - device->general.num_pending_relocations == 0)) - { - i965_emit_base (device); - } - - i965_emit_composite (device, shader); - - return CAIRO_STATUS_SUCCESS; -} - -void -i965_clipped_vertices (i965_device_t *device, - struct i965_vbo *vbo, - cairo_region_t *clip_region) -{ - int i, num_rectangles, size; - cairo_status_t status; - - if (vbo->count == 0) - return; - - num_rectangles = cairo_region_num_rectangles (clip_region); - assert (num_rectangles); - - if (vbo->next || - vbo->count * device->vertex_size + device->vertex.used > device->vertex.size) - { - i965_finish_vertices (device); - - size = device->rectangle_size; - do { - for (i = 0; i < num_rectangles; i++) { - cairo_rectangle_int_t rect; - - cairo_region_get_rectangle (clip_region, i, &rect); - - if (unlikely (device->vertex.used + size > device->vertex.size || - device->batch.used + 64 > device->batch.size || - ! i965_shader_check_aperture (device->shader, device))) - { - status = i965_device_flush (device); - if (unlikely (status)) - longjmp (device->shader->unwind, status); - - status = i965_shader_commit (device->shader, device); - assert (status == CAIRO_STATUS_SUCCESS); - } - - i965_emit_relocation (device, &device->batch, - vbo->bo, 0, - I915_GEM_DOMAIN_VERTEX, 0, - device->batch.used + 8); - - OUT_BATCH (BRW_3DSTATE_VERTEX_BUFFERS | 3); - OUT_BATCH ((0 << VB0_BUFFER_INDEX_SHIFT) | - VB0_VERTEXDATA | - (device->vertex_size << VB0_BUFFER_PITCH_SHIFT)); - OUT_BATCH (vbo->bo->offset); - OUT_BATCH (0); - OUT_BATCH (0); - - /* XXX scissor? */ - OUT_BATCH (BRW_3DSTATE_DRAWING_RECTANGLE | 2); - OUT_BATCH (DRAW_YMIN (rect.y) | DRAW_XMIN (rect.x)); - OUT_BATCH (DRAW_YMAX (rect.y + rect.height) | - DRAW_XMAX (rect.x + rect.width)); - OUT_BATCH (0x00000000); /* yorigin, xorigin */ - - OUT_BATCH (BRW_3DPRIMITIVE | - BRW_3DPRIMITIVE_VERTEX_SEQUENTIAL | - (_3DPRIM_RECTLIST << BRW_3DPRIMITIVE_TOPOLOGY_SHIFT) | - (0 << 9) | - 4); - OUT_BATCH (vbo->count); /* vertex count per instance */ - OUT_BATCH (0); /* start vertex offset */ - OUT_BATCH (1); /* single instance */ - OUT_BATCH (0); - OUT_BATCH (0); - } - } while ((vbo = vbo->next) != NULL); - assert (device->last_vertex_size == 0); - } else { - int vertex_start, vertex_count; - void *ptr; - - vertex_start = device->vertex.committed / device->vertex_size; - vertex_count = vbo->count; - - size = vertex_count * device->vertex_size; - ptr = intel_bo_map (&device->intel, vbo->bo); - memcpy (device->vertex.data + device->vertex.used, ptr, size); - device->vertex.committed = device->vertex.used += size; - - for (i = 0; i < num_rectangles; i++) { - cairo_rectangle_int_t rect; - - cairo_region_get_rectangle (clip_region, i, &rect); - - /* XXX scissor? */ - OUT_BATCH (BRW_3DSTATE_DRAWING_RECTANGLE | 2); - OUT_BATCH (DRAW_YMIN (rect.y) | DRAW_XMIN (rect.x)); - OUT_BATCH (DRAW_YMAX (rect.y + rect.height) | - DRAW_XMAX (rect.x + rect.width)); - OUT_BATCH (0x00000000); /* yorigin, xorigin */ - - OUT_BATCH (BRW_3DPRIMITIVE | - BRW_3DPRIMITIVE_VERTEX_SEQUENTIAL | - (_3DPRIM_RECTLIST << BRW_3DPRIMITIVE_TOPOLOGY_SHIFT) | - (0 << 9) | - 4); - OUT_BATCH (vertex_count); /* vertex count per instance */ - OUT_BATCH (vertex_start); /* start vertex offset */ - OUT_BATCH (1); /* single instance */ - OUT_BATCH (0); - OUT_BATCH (0); - } - } - - device->draw_rectangle = 0; -} diff --git a/gfx/cairo/cairo/src/drm/cairo-drm-i965-spans.c b/gfx/cairo/cairo/src/drm/cairo-drm-i965-spans.c deleted file mode 100644 index 4d1f491fa2..0000000000 --- a/gfx/cairo/cairo/src/drm/cairo-drm-i965-spans.c +++ /dev/null @@ -1,407 +0,0 @@ -/* cairo - a vector graphics library with display and print output - * - * Copyright © 2009 Intel Corporation - * - * This library is free software; you can redistribute it and/or - * modify it either under the terms of the GNU Lesser General Public - * License version 2.1 as published by the Free Software Foundation - * (the "LGPL") or, at your option, under the terms of the Mozilla - * Public License Version 1.1 (the "MPL"). If you do not alter this - * notice, a recipient may use your version of this file under either - * the MPL or the LGPL. - * - * You should have received a copy of the LGPL along with this library - * in the file COPYING-LGPL-2.1; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Suite 500, Boston, MA 02110-1335, 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): - * Chris Wilson <chris@chris-wilson.co.uk> - */ - -#include "cairoint.h" - -#include "cairo-composite-rectangles-private.h" -#include "cairo-boxes-private.h" -#include "cairo-error-private.h" -#include "cairo-drm-i965-private.h" - -/* Operates in either immediate or retained mode. - * When given a clip region we record the sequence of vbo and then - * replay them for each clip rectangle, otherwise we simply emit - * the vbo straight into the command stream. - */ - -typedef struct _i965_spans i965_spans_t; - -typedef float * -(*i965_get_rectangle_func_t) (i965_spans_t *spans); - -struct _i965_spans { - cairo_span_renderer_t renderer; - - i965_device_t *device; - - int xmin, xmax; - cairo_bool_t is_bounded; - const cairo_rectangle_int_t *extents; - - i965_get_rectangle_func_t get_rectangle; - i965_shader_t shader; - - cairo_region_t *clip_region; - - struct i965_vbo head, *tail; - - unsigned int vbo_offset; - float *vbo_base; -}; - -static float * -i965_spans_emit_rectangle (i965_spans_t *spans) -{ - return i965_add_rectangle (spans->device); -} - -static float * -i965_spans_accumulate_rectangle (i965_spans_t *spans) -{ - float *vertices; - uint32_t size; - - size = spans->device->rectangle_size; - if (unlikely (spans->vbo_offset + size > I965_VERTEX_SIZE)) { - struct i965_vbo *vbo; - - vbo = _cairo_malloc (sizeof (struct i965_vbo)); - if (unlikely (vbo == NULL)) { - /* throw error! */ - } - - spans->tail->next = vbo; - spans->tail = vbo; - - vbo->next = NULL; - vbo->bo = intel_bo_create (&spans->device->intel, - I965_VERTEX_SIZE, I965_VERTEX_SIZE, - FALSE, I915_TILING_NONE, 0); - vbo->count = 0; - - spans->vbo_offset = 0; - spans->vbo_base = intel_bo_map (&spans->device->intel, vbo->bo); - } - - vertices = spans->vbo_base + spans->vbo_offset; - spans->vbo_offset += size; - spans->tail->count += 3; - - return vertices; -} - -static void -i965_span_rectangle (i965_spans_t *spans, - int x0, int x1, int y0, int y1, - int alpha) -{ - float *vertices; - float a = alpha / 255.; - - vertices = spans->get_rectangle (spans); - - *vertices++ = x1; - *vertices++ = y1; - *vertices++ = a; - - *vertices++ = x0; - *vertices++ = y1; - *vertices++ = a; - - *vertices++ = x0; - *vertices++ = y0; - *vertices++ = a; -} - -static cairo_status_t -i965_bounded_spans_mono (void *abstract_renderer, - int y, int height, - const cairo_half_open_span_t *half, - unsigned num_spans) -{ - i965_spans_t *spans = abstract_renderer; - - if (num_spans == 0) - return CAIRO_STATUS_SUCCESS; - - do { - if (half[0].coverage >= 128) { - i965_span_rectangle (spans, - half[0].x, half[1].x, - y, y + height, - 255); - } - half++; - } while (--num_spans > 1); - - return CAIRO_STATUS_SUCCESS; -} - -static cairo_status_t -i965_bounded_spans (void *abstract_renderer, - int y, int height, - const cairo_half_open_span_t *half, - unsigned num_spans) -{ - i965_spans_t *spans = abstract_renderer; - - if (num_spans == 0) - return CAIRO_STATUS_SUCCESS; - - do { - if (half[0].coverage) { - i965_span_rectangle (spans, - half[0].x, half[1].x, - y, y + height, - half[0].coverage); - } - half++; - } while (--num_spans > 1); - - return CAIRO_STATUS_SUCCESS; -} - -static cairo_status_t -i965_unbounded_spans (void *abstract_renderer, - int y, int height, - const cairo_half_open_span_t *half, - unsigned num_spans) -{ - i965_spans_t *spans = abstract_renderer; - - if (num_spans == 0) { - i965_span_rectangle (spans, - spans->xmin, spans->xmax, - y, y + height, - 0); - return CAIRO_STATUS_SUCCESS; - } - - if (half[0].x != spans->xmin) { - i965_span_rectangle (spans, - spans->xmin, half[0].x, - y, y + height, - 0); - } - - do { - i965_span_rectangle (spans, - half[0].x, half[1].x, - y, y + height, - half[0].coverage); - half++; - } while (--num_spans > 1); - - if (half[0].x != spans->xmax) { - i965_span_rectangle (spans, - half[0].x, spans->xmax, - y, y + height, - 0); - } - - return CAIRO_STATUS_SUCCESS; -} - -static cairo_status_t -i965_unbounded_spans_mono (void *abstract_renderer, - int y, int height, - const cairo_half_open_span_t *half, - unsigned num_spans) -{ - i965_spans_t *spans = abstract_renderer; - - if (num_spans == 0) { - i965_span_rectangle (spans, - spans->xmin, spans->xmax, - y, y + height, - 0); - return CAIRO_STATUS_SUCCESS; - } - - if (half[0].x != spans->xmin) { - i965_span_rectangle (spans, - spans->xmin, half[0].x, - y, y + height, - 0); - } - - do { - int alpha = 0; - if (half[0].coverage >= 128) - alpha = 255; - i965_span_rectangle (spans, - half[0].x, half[1].x, - y, y + height, - alpha); - half++; - } while (--num_spans > 1); - - if (half[0].x != spans->xmax) { - i965_span_rectangle (spans, - half[0].x, spans->xmax, - y, y + height, - 0); - } - - return CAIRO_STATUS_SUCCESS; -} - -static cairo_status_t -i965_spans_init (i965_spans_t *spans, - i965_surface_t *dst, - cairo_operator_t op, - const cairo_pattern_t *pattern, - cairo_antialias_t antialias, - cairo_clip_t *clip, - const cairo_composite_rectangles_t *extents) -{ - cairo_status_t status; - - spans->device = i965_device (dst); - i965_shader_init (&spans->shader, dst, op); - - spans->is_bounded = extents->is_bounded; - if (extents->is_bounded) { - if (antialias == CAIRO_ANTIALIAS_NONE) - spans->renderer.render_rows = i965_bounded_spans_mono; - else - spans->renderer.render_rows = i965_bounded_spans; - - spans->extents = &extents->bounded; - } else { - if (antialias == CAIRO_ANTIALIAS_NONE) - spans->renderer.render_rows = i965_unbounded_spans_mono; - else - spans->renderer.render_rows = i965_unbounded_spans; - - spans->extents = &extents->unbounded; - } - spans->xmin = spans->extents->x; - spans->xmax = spans->extents->x + spans->extents->width; - - spans->clip_region = NULL; - if (clip != NULL) { - cairo_region_t *clip_region = NULL; - - status = _cairo_clip_get_region (clip, &clip_region); - assert (status == CAIRO_STATUS_SUCCESS || status == CAIRO_INT_STATUS_UNSUPPORTED); - - if (clip_region != NULL && cairo_region_num_rectangles (clip_region) == 1) - clip_region = NULL; - - spans->clip_region = clip_region; - if (status == CAIRO_INT_STATUS_UNSUPPORTED) - i965_shader_set_clip (&spans->shader, clip); - } - - spans->head.next = NULL; - spans->head.bo = NULL; - spans->head.count = 0; - spans->tail = &spans->head; - - if (spans->clip_region == NULL) { - spans->get_rectangle = i965_spans_emit_rectangle; - } else { - spans->get_rectangle = i965_spans_accumulate_rectangle; - spans->head.bo = intel_bo_create (&spans->device->intel, - I965_VERTEX_SIZE, I965_VERTEX_SIZE, - FALSE, I915_TILING_NONE, 0); - if (unlikely (spans->head.bo == NULL)) - return _cairo_error (CAIRO_STATUS_NO_MEMORY); - - spans->vbo_base = intel_bo_map (&spans->device->intel, spans->head.bo); - } - spans->vbo_offset = 0; - - return i965_shader_acquire_pattern (&spans->shader, - &spans->shader.source, - pattern, &extents->bounded); -} - -static void -i965_spans_fini (i965_spans_t *spans) -{ - i965_shader_fini (&spans->shader); - - if (spans->head.bo != NULL) { - struct i965_vbo *vbo, *next; - - intel_bo_destroy (&spans->device->intel, spans->head.bo); - for (vbo = spans->head.next; vbo != NULL; vbo = next) { - next = vbo->next; - intel_bo_destroy (&spans->device->intel, vbo->bo); - free (vbo); - } - } -} - -cairo_status_t -i965_clip_and_composite_spans (i965_surface_t *dst, - cairo_operator_t op, - const cairo_pattern_t *pattern, - cairo_antialias_t antialias, - i965_spans_func_t draw_func, - void *draw_closure, - const cairo_composite_rectangles_t*extents, - cairo_clip_t *clip) -{ - i965_spans_t spans; - i965_device_t *device; - cairo_status_t status; - - if (op == CAIRO_OPERATOR_CLEAR) { - pattern = &_cairo_pattern_white.base; - op = CAIRO_OPERATOR_DEST_OUT; - } - - status = i965_spans_init (&spans, dst, op, pattern, antialias, clip, extents); - if (unlikely (status)) - return status; - - spans.shader.mask.base.content = CAIRO_CONTENT_ALPHA; - spans.shader.mask.type.fragment = FS_SPANS; - spans.shader.mask.type.vertex = VS_SPANS; - spans.shader.mask.type.pattern = PATTERN_BASE; - - status = cairo_device_acquire (dst->intel.drm.base.device); - if (unlikely (status)) - goto CLEANUP_SPANS; - - device = i965_device (dst); - status = i965_shader_commit (&spans.shader, device); - if (unlikely (status)) - goto CLEANUP_DEVICE; - - status = draw_func (draw_closure, &spans.renderer, spans.extents); - if (spans.clip_region != NULL && status == CAIRO_STATUS_SUCCESS) - i965_clipped_vertices (device, &spans.head, spans.clip_region); - - CLEANUP_DEVICE: - cairo_device_release (dst->intel.drm.base.device); - CLEANUP_SPANS: - i965_spans_fini (&spans); - - return status; -} diff --git a/gfx/cairo/cairo/src/drm/cairo-drm-i965-surface.c b/gfx/cairo/cairo/src/drm/cairo-drm-i965-surface.c deleted file mode 100644 index 9d29e4753b..0000000000 --- a/gfx/cairo/cairo/src/drm/cairo-drm-i965-surface.c +++ /dev/null @@ -1,1926 +0,0 @@ -/* Cairo - a vector graphics library with display and print output - * - * Copyright © 2009 Kristian Høgsberg - * Copyright © 2009 Chris Wilson - * Copyright © 2009 Intel Corporation - * - * This library is free software; you can redistribute it and/or - * modify it either under the terms of the GNU Lesser General Public - * License version 2.1 as published by the Free Software Foundation - * (the "LGPL") or, at your option, under the terms of the Mozilla - * Public License Version 1.1 (the "MPL"). If you do not alter this - * notice, a recipient may use your version of this file under either - * the MPL or the LGPL. - * - * You should have received a copy of the LGPL along with this library - * in the file COPYING-LGPL-2.1; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Suite 500, Boston, MA 02110-1335, 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 Kristian Høgsberg. - * - * Based on the xf86-intel-driver i965 render acceleration code, - * authored by: - * Wang Zhenyu <zhenyu.z.wang@intel.com> - * Eric Anholt <eric@anholt.net> - * Carl Worth <cworth@redhat.com> - * Keith Packard <keithp@keithp.com> - */ - -/* XXX - * - * FIXME: Use brw_PLN for [DevCTG-B+] - * - */ - -#include "cairoint.h" - -#include "cairo-drm-private.h" -#include "cairo-drm-intel-private.h" -#include "cairo-drm-intel-command-private.h" -#include "cairo-drm-intel-ioctl-private.h" -#include "cairo-drm-i965-private.h" - -#include "cairo-boxes-private.h" -#include "cairo-composite-rectangles-private.h" -#include "cairo-default-context-private.h" -#include "cairo-error-private.h" -#include "cairo-region-private.h" -#include "cairo-surface-offset-private.h" - -#include <sys/ioctl.h> -#include <errno.h> - -#define I965_MAX_SIZE 8192 - -static const cairo_surface_backend_t i965_surface_backend; - -static void -i965_stream_init (i965_stream_t *stream, - uint8_t *data, uint32_t size, - struct i965_pending_relocation *pending, int max_pending, - struct drm_i915_gem_relocation_entry *relocations, int max_relocations) - -{ - stream->used = stream->committed = 0; - stream->data = data; - stream->size = size; - stream->serial = 1; - - stream->num_pending_relocations = 0; - stream->max_pending_relocations = max_pending; - stream->pending_relocations = pending; - - stream->num_relocations = 0; - stream->max_relocations = max_relocations; - stream->relocations = relocations; -} - -static void -i965_add_relocation (i965_device_t *device, - intel_bo_t *bo, - uint32_t read_domains, - uint32_t write_domain) -{ - if (bo->exec == NULL) { - int i; - - device->exec.gtt_size += bo->base.size; - - i = device->exec.count++; - assert (i < ARRAY_LENGTH (device->exec.exec)); - - device->exec.exec[i].handle = bo->base.handle; - device->exec.exec[i].relocation_count = 0; - device->exec.exec[i].relocs_ptr = 0; - device->exec.exec[i].alignment = 0; - device->exec.exec[i].offset = 0; - device->exec.exec[i].flags = 0; - device->exec.exec[i].rsvd1 = 0; - device->exec.exec[i].rsvd2 = 0; - - device->exec.bo[i] = intel_bo_reference (bo); - bo->exec = &device->exec.exec[i]; - } - - if (cairo_list_is_empty (&bo->link)) - cairo_list_add_tail (&device->flush, &bo->link); - - assert (write_domain == 0 || bo->batch_write_domain == 0 || bo->batch_write_domain == write_domain); - bo->batch_read_domains |= read_domains; - bo->batch_write_domain |= write_domain; -} - -void -i965_emit_relocation (i965_device_t *device, - i965_stream_t *stream, - intel_bo_t *target, - uint32_t target_offset, - uint32_t read_domains, - uint32_t write_domain, - uint32_t offset) -{ - int n; - - assert (target_offset < target->base.size); - - i965_add_relocation (device, target, read_domains, write_domain); - - n = stream->num_relocations++; - assert (n < stream->max_relocations); - - stream->relocations[n].offset = offset; - stream->relocations[n].delta = target_offset; - stream->relocations[n].target_handle = target->base.handle; - stream->relocations[n].read_domains = read_domains; - stream->relocations[n].write_domain = write_domain; - stream->relocations[n].presumed_offset = target->offset; -} - -static void -i965_stream_reset (i965_stream_t *stream) -{ - stream->used = stream->committed = 0; - stream->num_relocations = 0; - stream->num_pending_relocations = 0; - if (++stream->serial == 0) - stream->serial = 1; -} - -void -i965_stream_commit (i965_device_t *device, - i965_stream_t *stream) -{ - intel_bo_t *bo; - int n; - - assert (stream->used); - - bo = intel_bo_create (&device->intel, - stream->used, stream->used, - FALSE, I915_TILING_NONE, 0); - - /* apply pending relocations */ - for (n = 0; n < stream->num_pending_relocations; n++) { - struct i965_pending_relocation *p = &stream->pending_relocations[n]; - - i965_emit_relocation (device, &device->batch, bo, - p->delta, - p->read_domains, - p->write_domain, - p->offset); - if (bo->offset) - *(uint32_t *) (device->batch.data + p->offset) = bo->offset + p->delta; - } - - intel_bo_write (&device->intel, bo, 0, stream->used, stream->data); - - if (stream->num_relocations) { - assert (bo->exec != NULL); - bo->exec->relocs_ptr = (uintptr_t) stream->relocations; - bo->exec->relocation_count = stream->num_relocations; - } - - intel_bo_destroy (&device->intel, bo); - - i965_stream_reset (stream); -} - -static void -sf_states_pluck (void *entry, void *closure) -{ - i965_device_t *device = closure; - - _cairo_hash_table_remove (device->sf_states, entry); - _cairo_freelist_free (&device->sf_freelist, entry); -} - -static void -cc_offsets_pluck (void *entry, void *closure) -{ - i965_device_t *device = closure; - - _cairo_hash_table_remove (device->cc_states, entry); - _cairo_freelist_free (&device->cc_freelist, entry); -} - -static void -wm_kernels_pluck (void *entry, void *closure) -{ - i965_device_t *device = closure; - - _cairo_hash_table_remove (device->wm_kernels, entry); - _cairo_freelist_free (&device->wm_kernel_freelist, entry); -} - -static void -wm_states_pluck (void *entry, void *closure) -{ - i965_device_t *device = closure; - - _cairo_hash_table_remove (device->wm_states, entry); - _cairo_freelist_free (&device->wm_state_freelist, entry); -} - -static void -wm_bindings_pluck (void *entry, void *closure) -{ - i965_device_t *device = closure; - - _cairo_hash_table_remove (device->wm_bindings, entry); - _cairo_freelist_free (&device->wm_binding_freelist, entry); -} - -static void -samplers_pluck (void *entry, void *closure) -{ - i965_device_t *device = closure; - - _cairo_hash_table_remove (device->samplers, entry); - _cairo_freelist_free (&device->sampler_freelist, entry); -} - -void -i965_general_state_reset (i965_device_t *device) -{ - _cairo_hash_table_foreach (device->sf_states, - sf_states_pluck, - device); - - _cairo_hash_table_foreach (device->cc_states, - cc_offsets_pluck, - device); - - _cairo_hash_table_foreach (device->wm_kernels, - wm_kernels_pluck, - device); - - _cairo_hash_table_foreach (device->wm_states, - wm_states_pluck, - device); - - _cairo_hash_table_foreach (device->wm_bindings, - wm_bindings_pluck, - device); - - _cairo_hash_table_foreach (device->samplers, - samplers_pluck, - device); - - device->vs_offset = (uint32_t) -1; - device->border_color_offset = (uint32_t) -1; - - if (device->general_state != NULL) { - intel_bo_destroy (&device->intel, device->general_state); - device->general_state = NULL; - } -} - -static void -i965_device_reset (i965_device_t *device) -{ - device->exec.count = 0; - device->exec.gtt_size = I965_VERTEX_SIZE + - I965_SURFACE_SIZE + - I965_GENERAL_SIZE + - I965_BATCH_SIZE; - - device->sf_state.entry.hash = (uint32_t) -1; - device->wm_state.entry.hash = (uint32_t) -1; - device->wm_binding.entry.hash = (uint32_t) -1; - device->cc_state.entry.hash = (uint32_t) -1; - - device->target = NULL; - device->source = NULL; - device->mask = NULL; - device->clip = NULL; - - device->draw_rectangle = (uint32_t) -1; - - device->vertex_type = (uint32_t) -1; - device->vertex_size = 0; - device->rectangle_size = 0; - device->last_vertex_size = 0; - - device->constants = NULL; - device->constants_size = 0; - - device->have_urb_fences = FALSE; -} - -static cairo_status_t -i965_exec (i965_device_t *device, uint32_t offset) -{ - struct drm_i915_gem_execbuffer2 execbuf; - cairo_status_t status = CAIRO_STATUS_SUCCESS; - int ret, i; - - execbuf.buffers_ptr = (uintptr_t) device->exec.exec; - execbuf.buffer_count = device->exec.count; - execbuf.batch_start_offset = offset; - execbuf.batch_len = device->batch.used; - execbuf.DR1 = 0; - execbuf.DR4 = 0; - execbuf.num_cliprects = 0; - execbuf.cliprects_ptr = 0; - execbuf.flags = I915_GEM_3D_PIPELINE; - execbuf.rsvd1 = 0; - execbuf.rsvd2 = 0; - -#if 0 - printf ("exec: offset=%d, length=%d, buffers=%d\n", - offset, device->batch.used, device->exec.count); - intel_dump_batchbuffer ((uint32_t *) device->batch.data, - device->batch.used, - device->intel.base.chip_id); -#endif - - ret = 0; - do { - ret = ioctl (device->intel.base.fd, DRM_IOCTL_I915_GEM_EXECBUFFER2, &execbuf); - } while (ret != 0 && errno == EINTR); - if (unlikely (ret)) { - if (errno == ENOMEM) - status = _cairo_error (CAIRO_STATUS_NO_MEMORY); - else - status = _cairo_error (CAIRO_STATUS_DEVICE_ERROR); - - fprintf (stderr, "Batch submission failed: %d\n", errno); - fprintf (stderr, " gtt size: %zd/%zd\n", - device->exec.gtt_size, device->intel.gtt_avail_size); - - fprintf (stderr, " %d buffers:\n", - device->exec.count); - for (i = 0; i < device->exec.count; i++) { - fprintf (stderr, " exec[%d] = %d\n", - i, device->exec.bo[i]->base.size); - } - - intel_dump_batchbuffer ((uint32_t *) device->batch.data, - device->batch.used, - device->intel.base.chip_id); - } - - /* XXX any write target within the batch should now be in error */ - for (i = 0; i < device->exec.count; i++) { - intel_bo_t *bo = device->exec.bo[i]; - cairo_bool_t ret; - - bo->offset = device->exec.exec[i].offset; - bo->exec = NULL; - bo->batch_read_domains = 0; - bo->batch_write_domain = 0; - - if (bo->virtual) - intel_bo_unmap (bo); - bo->cpu = FALSE; - - if (bo->purgeable) - ret = intel_bo_madvise (&device->intel, bo, I915_MADV_DONTNEED); - /* ignore immediate notification of purging */ - - cairo_list_del (&bo->cache_list); - cairo_list_init (&bo->link); - intel_bo_destroy (&device->intel, bo); - } - cairo_list_init (&device->flush); - - device->exec.count = 0; - - return status; -} - -static inline uint32_t -next_bo_size (uint32_t v) -{ - v = (v + 8191) / 8192; - - v--; - v |= v >> 1; - v |= v >> 2; - v |= v >> 4; - v |= v >> 8; - v |= v >> 16; - v++; - - return v * 8192; -} - -static void -_copy_to_bo_and_apply_relocations (i965_device_t *device, - intel_bo_t *bo, - i965_stream_t *stream, - uint32_t offset) -{ - int n; - - intel_bo_write (&device->intel, bo, - offset, stream->used, - stream->data); - - for (n = 0; n < stream->num_pending_relocations; n++) { - struct i965_pending_relocation *p = &stream->pending_relocations[n]; - - i965_emit_relocation (device, &device->batch, bo, - p->delta + offset, - p->read_domains, - p->write_domain, - p->offset); - - if (bo->offset) { - *(uint32_t *) (device->batch.data + p->offset) = - bo->offset + p->delta + offset; - } - } -} - -cairo_status_t -i965_device_flush (i965_device_t *device) -{ - cairo_status_t status; - uint32_t aligned, max; - intel_bo_t *bo; - int n; - - if (device->batch.used == 0) - return CAIRO_STATUS_SUCCESS; - - i965_flush_vertices (device); - - OUT_BATCH (MI_BATCH_BUFFER_END); - /* Emit a padding dword if we aren't going to be quad-word aligned. */ - if (device->batch.used & 4) - OUT_BATCH (MI_NOOP); - -#if 0 - printf ("device flush: vertex=%d, constant=%d, surface=%d, general=%d, batch=%d\n", - device->vertex.used, - device->constant.used, - device->surface.used, - device->general.used, - device->batch.used); -#endif - - /* can we pack the surface state into the tail of the general state? */ - if (device->general.used == device->general.committed) { - if (device->general.used) { - assert (device->general.num_pending_relocations == 1); - assert (device->general_state != NULL); - i965_emit_relocation (device, &device->batch, - device->general_state, - device->general.pending_relocations[0].delta, - device->general.pending_relocations[0].read_domains, - device->general.pending_relocations[0].write_domain, - device->general.pending_relocations[0].offset); - - if (device->general_state->offset) { - *(uint32_t *) (device->batch.data + - device->general.pending_relocations[0].offset) = - device->general_state->offset + - device->general.pending_relocations[0].delta; - } - } - } else { - assert (device->general.num_pending_relocations == 1); - if (device->general_state != NULL) { - intel_bo_destroy (&device->intel, device->general_state); - device->general_state = NULL; - } - - bo = intel_bo_create (&device->intel, - device->general.used, - device->general.used, - FALSE, I915_TILING_NONE, 0); - if (unlikely (bo == NULL)) - return _cairo_error (CAIRO_STATUS_NO_MEMORY); - - aligned = (device->general.used + 31) & -32; - if (device->surface.used && - aligned + device->surface.used <= bo->base.size) - { - _copy_to_bo_and_apply_relocations (device, bo, &device->general, 0); - _copy_to_bo_and_apply_relocations (device, bo, &device->surface, aligned); - - if (device->surface.num_relocations) { - for (n = 0; n < device->surface.num_relocations; n++) - device->surface.relocations[n].offset += aligned; - - assert (bo->exec != NULL); - bo->exec->relocs_ptr = (uintptr_t) device->surface.relocations; - bo->exec->relocation_count = device->surface.num_relocations; - } - - i965_stream_reset (&device->surface); - } - else - { - _copy_to_bo_and_apply_relocations (device, bo, &device->general, 0); - } - - /* Note we don't reset the general state, just mark what data we've committed. */ - device->general.committed = device->general.used; - device->general_state = bo; - } - device->general.num_pending_relocations = 0; - - /* Combine vertex+constant+surface+batch streams? */ - max = aligned = device->vertex.used; - if (device->surface.used) { - aligned = (aligned + 63) & -64; - aligned += device->surface.used; - if (device->surface.used > max) - max = device->surface.used; - } - aligned = (aligned + 63) & -64; - aligned += device->batch.used; - if (device->batch.used > max) - max = device->batch.used; - if (aligned <= next_bo_size (max)) { - int batch_num_relocations; - - if (aligned <= 8192) - max = aligned; - - bo = intel_bo_create (&device->intel, - max, max, - FALSE, I915_TILING_NONE, 0); - if (unlikely (bo == NULL)) - return _cairo_error (CAIRO_STATUS_NO_MEMORY); - - assert (aligned <= bo->base.size); - - if (device->vertex.used) - _copy_to_bo_and_apply_relocations (device, bo, &device->vertex, 0); - - aligned = device->vertex.used; - - batch_num_relocations = device->batch.num_relocations; - if (device->surface.used) { - aligned = (aligned + 63) & -64; - _copy_to_bo_and_apply_relocations (device, bo, &device->surface, aligned); - - batch_num_relocations = device->batch.num_relocations; - if (device->surface.num_relocations) { - assert (device->batch.num_relocations + device->surface.num_relocations < device->batch.max_relocations); - - memcpy (device->batch.relocations + device->batch.num_relocations, - device->surface.relocations, - sizeof (device->surface.relocations[0]) * device->surface.num_relocations); - - for (n = 0; n < device->surface.num_relocations; n++) - device->batch.relocations[device->batch.num_relocations + n].offset += aligned; - - device->batch.num_relocations += device->surface.num_relocations; - } - - aligned += device->surface.used; - } - - aligned = (aligned + 63) & -64; - intel_bo_write (&device->intel, bo, - aligned, device->batch.used, - device->batch.data); - - for (n = 0; n < batch_num_relocations; n++) - device->batch.relocations[n].offset += aligned; - - if (device->exec.bo[device->exec.count-1] == bo) { - assert (bo->exec == &device->exec.exec[device->exec.count-1]); - - bo->exec->relocation_count = device->batch.num_relocations; - bo->exec->relocs_ptr = (uintptr_t) device->batch.relocations; - intel_bo_destroy (&device->intel, bo); - } else { - assert (bo->exec == NULL); - - n = device->exec.count++; - device->exec.exec[n].handle = bo->base.handle; - device->exec.exec[n].relocation_count = device->batch.num_relocations; - device->exec.exec[n].relocs_ptr = (uintptr_t) device->batch.relocations; - device->exec.exec[n].alignment = 0; - device->exec.exec[n].offset = 0; - device->exec.exec[n].flags = 0; - device->exec.exec[n].rsvd1 = 0; - device->exec.exec[n].rsvd2 = 0; - - /* transfer ownership to the exec */ - device->exec.bo[n] = bo; - } - } else { - i965_stream_commit (device, &device->vertex); - if (device->surface.used) - i965_stream_commit (device, &device->surface); - - bo = intel_bo_create (&device->intel, - device->batch.used, device->batch.used, - FALSE, I915_TILING_NONE, 0); - if (unlikely (bo == NULL)) - return _cairo_error (CAIRO_STATUS_NO_MEMORY); - - intel_bo_write (&device->intel, bo, - 0, device->batch.used, - device->batch.data); - - n = device->exec.count++; - device->exec.exec[n].handle = bo->base.handle; - device->exec.exec[n].relocation_count = device->batch.num_relocations; - device->exec.exec[n].relocs_ptr = (uintptr_t) device->batch.relocations; - device->exec.exec[n].alignment = 0; - device->exec.exec[n].offset = 0; - device->exec.exec[n].flags = 0; - device->exec.exec[n].rsvd1 = 0; - device->exec.exec[n].rsvd2 = 0; - - /* transfer ownership to the exec */ - device->exec.bo[n] = bo; - aligned = 0; - } - - status = i965_exec (device, aligned); - - i965_stream_reset (&device->vertex); - i965_stream_reset (&device->surface); - i965_stream_reset (&device->batch); - - intel_glyph_cache_unpin (&device->intel); - intel_snapshot_cache_thaw (&device->intel); - - i965_device_reset (device); - - return status; -} - -static cairo_surface_t * -i965_surface_create_similar (void *abstract_other, - cairo_content_t content, - int width, int height) -{ - i965_surface_t *other; - cairo_format_t format; - - if (width > 8192 || height > 8192) - return NULL; - - other = abstract_other; - if (content == other->intel.drm.base.content) - format = other->intel.drm.format; - else - format = _cairo_format_from_content (content); - - return i965_surface_create_internal ((cairo_drm_device_t *) other->intel.drm.base.device, - format, - width, height, - I965_TILING_DEFAULT, TRUE); -} - -static cairo_status_t -i965_surface_finish (void *abstract_surface) -{ - i965_surface_t *surface = abstract_surface; - - return intel_surface_finish (&surface->intel); -} - -static cairo_status_t -i965_surface_flush (void *abstract_surface, unsigned flags) -{ - i965_surface_t *surface = abstract_surface; - cairo_status_t status = CAIRO_STATUS_SUCCESS; - - if (flags) - return CAIRO_STATUS_SUCCESS; - - if (surface->intel.drm.fallback != NULL) - return intel_surface_flush (abstract_surface); - - /* Forgo flushing on finish as the user cannot access the surface directly. */ - if (! surface->intel.drm.base.finished && - to_intel_bo (surface->intel.drm.bo)->exec != NULL) - { - status = cairo_device_acquire (surface->intel.drm.base.device); - if (likely (status == CAIRO_STATUS_SUCCESS)) { - i965_device_t *device; - - device = i965_device (surface); - status = i965_device_flush (device); - cairo_device_release (&device->intel.base.base); - } - } - - return status; -} - -/* rasterisation */ - -static cairo_status_t -_composite_boxes_spans (void *closure, - cairo_span_renderer_t *renderer, - const cairo_rectangle_int_t *extents) -{ - cairo_boxes_t *boxes = closure; - cairo_rectangular_scan_converter_t converter; - struct _cairo_boxes_chunk *chunk; - cairo_status_t status; - - _cairo_rectangular_scan_converter_init (&converter, extents); - for (chunk = &boxes->chunks; chunk != NULL; chunk = chunk->next) { - cairo_box_t *box = chunk->base; - int i; - - for (i = 0; i < chunk->count; i++) { - status = _cairo_rectangular_scan_converter_add_box (&converter, &box[i], 1); - if (unlikely (status)) - goto CLEANUP; - } - } - - status = converter.base.generate (&converter.base, renderer); - - CLEANUP: - converter.base.destroy (&converter.base); - return status; -} - -cairo_status_t -i965_fixup_unbounded (i965_surface_t *dst, - const cairo_composite_rectangles_t *extents, - cairo_clip_t *clip) -{ - i965_shader_t shader; - i965_device_t *device; - cairo_status_t status; - - i965_shader_init (&shader, dst, CAIRO_OPERATOR_CLEAR); - - if (clip != NULL) { - cairo_region_t *clip_region = NULL; - - status = _cairo_clip_get_region (clip, &clip_region); - assert (status == CAIRO_STATUS_SUCCESS || CAIRO_INT_STATUS_UNSUPPORTED); - assert (clip_region == NULL); - - if (status == CAIRO_INT_STATUS_UNSUPPORTED) - i965_shader_set_clip (&shader, clip); - } else { - if (extents->bounded.width == extents->unbounded.width && - extents->bounded.height == extents->unbounded.height) - { - return CAIRO_STATUS_SUCCESS; - } - } - - status = i965_shader_acquire_pattern (&shader, - &shader.source, - &_cairo_pattern_clear.base, - &extents->unbounded); - if (unlikely (status)) { - i965_shader_fini (&shader); - return status; - } - - device = i965_device (dst); - status = cairo_device_acquire (&device->intel.base.base); - if (unlikely (status)) - return status; - - status = i965_shader_commit (&shader, device); - if (unlikely (status)) { - goto BAIL; - } - - if (extents->bounded.width == 0 || extents->bounded.height == 0) { - i965_shader_add_rectangle (&shader, - extents->unbounded.x, - extents->unbounded.y, - extents->unbounded.width, - extents->unbounded.height); - } else { /* top */ - if (extents->bounded.y != extents->unbounded.y) { - cairo_rectangle_int_t rect; - - rect.x = extents->unbounded.x; - rect.y = extents->unbounded.y; - rect.width = extents->unbounded.width; - rect.height = extents->bounded.y - rect.y; - - i965_shader_add_rectangle (&shader, - rect.x, rect.y, - rect.width, rect.height); - } - - /* left */ - if (extents->bounded.x != extents->unbounded.x) { - cairo_rectangle_int_t rect; - - rect.x = extents->unbounded.x; - rect.y = extents->bounded.y; - rect.width = extents->bounded.x - extents->unbounded.x; - rect.height = extents->bounded.height; - - i965_shader_add_rectangle (&shader, - rect.x, rect.y, - rect.width, rect.height); - } - - /* right */ - if (extents->bounded.x + extents->bounded.width != extents->unbounded.x + extents->unbounded.width) { - cairo_rectangle_int_t rect; - - rect.x = extents->bounded.x + extents->bounded.width; - rect.y = extents->bounded.y; - rect.width = extents->unbounded.x + extents->unbounded.width - rect.x; - rect.height = extents->bounded.height; - - i965_shader_add_rectangle (&shader, - rect.x, rect.y, - rect.width, rect.height); - } - - /* bottom */ - if (extents->bounded.y + extents->bounded.height != extents->unbounded.y + extents->unbounded.height) { - cairo_rectangle_int_t rect; - - rect.x = extents->unbounded.x; - rect.y = extents->bounded.y + extents->bounded.height; - rect.width = extents->unbounded.width; - rect.height = extents->unbounded.y + extents->unbounded.height - rect.y; - - i965_shader_add_rectangle (&shader, - rect.x, rect.y, - rect.width, rect.height); - } - } - - i965_shader_fini (&shader); - BAIL: - cairo_device_release (&device->intel.base.base); - return status; -} - -static cairo_status_t -i965_fixup_unbounded_boxes (i965_surface_t *dst, - const cairo_composite_rectangles_t *extents, - cairo_clip_t *clip, - cairo_boxes_t *boxes) -{ - cairo_boxes_t clear; - cairo_box_t box; - cairo_region_t *clip_region = NULL; - cairo_status_t status; - struct _cairo_boxes_chunk *chunk; - i965_shader_t shader; - int i; - - if (boxes->num_boxes <= 1) - return i965_fixup_unbounded (dst, extents, clip); - - i965_shader_init (&shader, dst, CAIRO_OPERATOR_CLEAR); - if (clip != NULL) { - status = _cairo_clip_get_region (clip, &clip_region); - assert (status == CAIRO_STATUS_SUCCESS || CAIRO_INT_STATUS_UNSUPPORTED); - if (status == CAIRO_INT_STATUS_UNSUPPORTED) - i965_shader_set_clip (&shader, clip); - } - - status = i965_shader_acquire_pattern (&shader, - &shader.source, - &_cairo_pattern_clear.base, - &extents->unbounded); - if (unlikely (status)) { - i965_shader_fini (&shader); - return status; - } - - _cairo_boxes_init (&clear); - - box.p1.x = _cairo_fixed_from_int (extents->unbounded.x + extents->unbounded.width); - box.p1.y = _cairo_fixed_from_int (extents->unbounded.y); - box.p2.x = _cairo_fixed_from_int (extents->unbounded.x); - box.p2.y = _cairo_fixed_from_int (extents->unbounded.y + extents->unbounded.height); - - if (clip_region == NULL) { - cairo_boxes_t tmp; - - _cairo_boxes_init (&tmp); - - status = _cairo_boxes_add (&tmp, &box); - assert (status == CAIRO_STATUS_SUCCESS); - - tmp.chunks.next = &boxes->chunks; - tmp.num_boxes += boxes->num_boxes; - - status = _cairo_bentley_ottmann_tessellate_boxes (&tmp, - CAIRO_FILL_RULE_WINDING, - &clear); - - tmp.chunks.next = NULL; - } else { - pixman_box32_t *pbox; - - pbox = pixman_region32_rectangles (&clip_region->rgn, &i); - _cairo_boxes_limit (&clear, (cairo_box_t *) pbox, i); - - status = _cairo_boxes_add (&clear, &box); - assert (status == CAIRO_STATUS_SUCCESS); - - for (chunk = &boxes->chunks; chunk != NULL; chunk = chunk->next) { - for (i = 0; i < chunk->count; i++) { - status = _cairo_boxes_add (&clear, &chunk->base[i]); - if (unlikely (status)) { - _cairo_boxes_fini (&clear); - return status; - } - } - } - - status = _cairo_bentley_ottmann_tessellate_boxes (&clear, - CAIRO_FILL_RULE_WINDING, - &clear); - } - - if (likely (status == CAIRO_STATUS_SUCCESS && clear.num_boxes)) { - i965_device_t *device; - - device = i965_device (dst); - status = cairo_device_acquire (&device->intel.base.base); - if (unlikely (status)) - goto err_shader; - - status = i965_shader_commit (&shader, device); - if (unlikely (status)) - goto err_device; - - for (chunk = &clear.chunks; chunk != NULL; chunk = chunk->next) { - for (i = 0; i < chunk->count; i++) { - int x1 = _cairo_fixed_integer_part (chunk->base[i].p1.x); - int y1 = _cairo_fixed_integer_part (chunk->base[i].p1.y); - int x2 = _cairo_fixed_integer_part (chunk->base[i].p2.x); - int y2 = _cairo_fixed_integer_part (chunk->base[i].p2.y); - - i965_shader_add_rectangle (&shader, x1, y1, x2 - x1, y2 - y1); - } - } - -err_device: - cairo_device_release (&device->intel.base.base); -err_shader: - i965_shader_fini (&shader); - } - - _cairo_boxes_fini (&clear); - - return status; -} - -static cairo_status_t -_composite_boxes (i965_surface_t *dst, - cairo_operator_t op, - const cairo_pattern_t *pattern, - cairo_boxes_t *boxes, - cairo_antialias_t antialias, - cairo_clip_t *clip, - const cairo_composite_rectangles_t *extents) -{ - cairo_bool_t need_clip_surface = FALSE; - cairo_region_t *clip_region = NULL; - const struct _cairo_boxes_chunk *chunk; - cairo_status_t status; - i965_shader_t shader; - i965_device_t *device; - int i; - - /* If the boxes are not pixel-aligned, we will need to compute a real mask */ - if (antialias != CAIRO_ANTIALIAS_NONE) { - if (! boxes->is_pixel_aligned) - return CAIRO_INT_STATUS_UNSUPPORTED; - } - - i965_shader_init (&shader, dst, op); - - status = i965_shader_acquire_pattern (&shader, - &shader.source, - pattern, - &extents->bounded); - if (unlikely (status)) - return status; - - if (clip != NULL) { - status = _cairo_clip_get_region (clip, &clip_region); - assert (status == CAIRO_STATUS_SUCCESS || CAIRO_INT_STATUS_UNSUPPORTED); - need_clip_surface = status == CAIRO_INT_STATUS_UNSUPPORTED; - if (need_clip_surface) - i965_shader_set_clip (&shader, clip); - } - - device = i965_device (dst); - status = cairo_device_acquire (&device->intel.base.base); - if (unlikely (status)) - goto err_shader; - - status = i965_shader_commit (&shader, i965_device (dst)); - if (unlikely (status)) - goto err_device; - - for (chunk = &boxes->chunks; chunk != NULL; chunk = chunk->next) { - cairo_box_t *box = chunk->base; - for (i = 0; i < chunk->count; i++) { - int x1 = _cairo_fixed_integer_round (box[i].p1.x); - int y1 = _cairo_fixed_integer_round (box[i].p1.y); - int x2 = _cairo_fixed_integer_round (box[i].p2.x); - int y2 = _cairo_fixed_integer_round (box[i].p2.y); - - if (x2 > x1 && y2 > y1) - i965_shader_add_rectangle (&shader, x1, y1, x2 - x1, y2 - y1); - } - } - - if (! extents->is_bounded) - status = i965_fixup_unbounded_boxes (dst, extents, clip, boxes); - - err_device: - cairo_device_release (&device->intel.base.base); - err_shader: - i965_shader_fini (&shader); - - return status; -} - -static cairo_status_t -_clip_and_composite_boxes (i965_surface_t *dst, - cairo_operator_t op, - const cairo_pattern_t *src, - cairo_boxes_t *boxes, - cairo_antialias_t antialias, - const cairo_composite_rectangles_t *extents, - cairo_clip_t *clip) -{ - cairo_status_t status; - - if (boxes->num_boxes == 0) { - if (extents->is_bounded) - return CAIRO_STATUS_SUCCESS; - - return i965_fixup_unbounded (dst, extents, clip); - } - - /* Use a fast path if the boxes are pixel aligned */ - status = _composite_boxes (dst, op, src, boxes, antialias, clip, extents); - if (status != CAIRO_INT_STATUS_UNSUPPORTED) - return status; - - /* Otherwise render the boxes via an implicit mask and composite in the usual - * fashion. - */ - return i965_clip_and_composite_spans (dst, op, src, antialias, - _composite_boxes_spans, boxes, - extents, clip); -} - -static cairo_int_status_t -i965_surface_paint (void *abstract_dst, - cairo_operator_t op, - const cairo_pattern_t *source, - cairo_clip_t *clip) -{ - i965_surface_t *dst = abstract_dst; - cairo_composite_rectangles_t extents; - cairo_boxes_t boxes; - cairo_box_t *clip_boxes = boxes.boxes_embedded; - cairo_clip_t local_clip; - cairo_bool_t have_clip = FALSE; - int num_boxes = ARRAY_LENGTH (boxes.boxes_embedded); - cairo_status_t status; - - /* XXX unsupported operators? use pixel shader blending, eventually */ - - status = _cairo_composite_rectangles_init_for_paint (&extents, - dst->intel.drm.width, - dst->intel.drm.height, - op, source, - clip); - if (unlikely (status)) - return status; - - if (clip != NULL && _cairo_clip_contains_extents (clip, &extents)) - clip = NULL; - - if (clip != NULL) { - clip = _cairo_clip_init_copy (&local_clip, clip); - have_clip = TRUE; - } - - status = _cairo_clip_to_boxes (&clip, &extents, &clip_boxes, &num_boxes); - if (unlikely (status)) { - if (have_clip) - _cairo_clip_fini (&local_clip); - - return status; - } - - _cairo_boxes_init_for_array (&boxes, clip_boxes, num_boxes); - status = _clip_and_composite_boxes (dst, op, source, - &boxes, CAIRO_ANTIALIAS_DEFAULT, - &extents, clip); - if (clip_boxes != boxes.boxes_embedded) - free (clip_boxes); - - if (have_clip) - _cairo_clip_fini (&local_clip); - - return status; -} - -static cairo_int_status_t -i965_surface_mask (void *abstract_dst, - cairo_operator_t op, - const cairo_pattern_t *source, - const cairo_pattern_t *mask, - cairo_clip_t *clip) -{ - i965_surface_t *dst = abstract_dst; - cairo_composite_rectangles_t extents; - i965_shader_t shader; - i965_device_t *device; - cairo_clip_t local_clip; - cairo_region_t *clip_region = NULL; - cairo_bool_t need_clip_surface = FALSE; - cairo_bool_t have_clip = FALSE; - cairo_status_t status; - - status = _cairo_composite_rectangles_init_for_mask (&extents, - dst->intel.drm.width, - dst->intel.drm.height, - op, source, mask, clip); - if (unlikely (status)) - return status; - - if (clip != NULL && _cairo_clip_contains_extents (clip, &extents)) - clip = NULL; - - if (clip != NULL && extents.is_bounded) { - clip = _cairo_clip_init_copy (&local_clip, clip); - status = _cairo_clip_rectangle (clip, &extents.bounded); - if (unlikely (status)) { - _cairo_clip_fini (&local_clip); - return status; - } - - have_clip = TRUE; - } - - i965_shader_init (&shader, dst, op); - - status = i965_shader_acquire_pattern (&shader, - &shader.source, - source, - &extents.bounded); - if (unlikely (status)) - goto err_shader; - - status = i965_shader_acquire_pattern (&shader, - &shader.mask, - mask, - &extents.bounded); - if (unlikely (status)) - goto err_shader; - - if (clip != NULL) { - status = _cairo_clip_get_region (clip, &clip_region); - assert (status == CAIRO_STATUS_SUCCESS || CAIRO_INT_STATUS_UNSUPPORTED); - need_clip_surface = status == CAIRO_INT_STATUS_UNSUPPORTED; - if (need_clip_surface) - i965_shader_set_clip (&shader, clip); - } - - device = i965_device (dst); - status = cairo_device_acquire (&device->intel.base.base); - if (unlikely (status)) - goto err_shader; - - status = i965_shader_commit (&shader, device); - if (unlikely (status)) - goto err_device; - - if (clip_region != NULL) { - unsigned int n, num_rectangles; - - num_rectangles = cairo_region_num_rectangles (clip_region); - for (n = 0; n < num_rectangles; n++) { - cairo_rectangle_int_t rect; - - cairo_region_get_rectangle (clip_region, n, &rect); - - i965_shader_add_rectangle (&shader, - rect.x, rect.y, - rect.width, rect.height); - } - } else { - i965_shader_add_rectangle (&shader, - extents.bounded.x, - extents.bounded.y, - extents.bounded.width, - extents.bounded.height); - } - - if (! extents.is_bounded) - status = i965_fixup_unbounded (dst, &extents, clip); - - err_device: - cairo_device_release (&device->intel.base.base); - err_shader: - i965_shader_fini (&shader); - if (have_clip) - _cairo_clip_fini (&local_clip); - - return status; -} - -typedef struct { - cairo_polygon_t polygon; - cairo_fill_rule_t fill_rule; - cairo_antialias_t antialias; -} composite_polygon_info_t; - -static cairo_status_t -_composite_polygon_spans (void *closure, - cairo_span_renderer_t *renderer, - const cairo_rectangle_int_t *extents) -{ - composite_polygon_info_t *info = closure; - cairo_botor_scan_converter_t converter; - cairo_status_t status; - cairo_box_t box; - - box.p1.x = _cairo_fixed_from_int (extents->x); - box.p1.y = _cairo_fixed_from_int (extents->y); - box.p2.x = _cairo_fixed_from_int (extents->x + extents->width); - box.p2.y = _cairo_fixed_from_int (extents->y + extents->height); - - _cairo_botor_scan_converter_init (&converter, &box, info->fill_rule); - - status = converter.base.add_polygon (&converter.base, &info->polygon); - if (likely (status == CAIRO_STATUS_SUCCESS)) - status = converter.base.generate (&converter.base, renderer); - - converter.base.destroy (&converter.base); - - return status; -} - -static cairo_int_status_t -i965_surface_stroke (void *abstract_dst, - cairo_operator_t op, - const cairo_pattern_t *source, - cairo_path_fixed_t *path, - const cairo_stroke_style_t *stroke_style, - const cairo_matrix_t *ctm, - const cairo_matrix_t *ctm_inverse, - double tolerance, - cairo_antialias_t antialias, - cairo_clip_t *clip) -{ - i965_surface_t *dst = abstract_dst; - cairo_composite_rectangles_t extents; - composite_polygon_info_t info; - cairo_box_t boxes_stack[32], *clip_boxes = boxes_stack; - int num_boxes = ARRAY_LENGTH (boxes_stack); - cairo_clip_t local_clip; - cairo_bool_t have_clip = FALSE; - cairo_status_t status; - - status = _cairo_composite_rectangles_init_for_stroke (&extents, - dst->intel.drm.width, - dst->intel.drm.height, - op, source, - path, stroke_style, ctm, - clip); - if (unlikely (status)) - return status; - - if (clip != NULL && _cairo_clip_contains_extents (clip, &extents)) - clip = NULL; - - if (clip != NULL) { - clip = _cairo_clip_init_copy (&local_clip, clip); - have_clip = TRUE; - } - - status = _cairo_clip_to_boxes (&clip, &extents, &clip_boxes, &num_boxes); - if (unlikely (status)) { - if (have_clip) - _cairo_clip_fini (&local_clip); - - return status; - } - - if (_cairo_path_fixed_stroke_is_rectilinear (path)) { - cairo_boxes_t boxes; - - _cairo_boxes_init (&boxes); - _cairo_boxes_limit (&boxes, clip_boxes, num_boxes); - status = _cairo_path_fixed_stroke_rectilinear_to_boxes (path, - stroke_style, - ctm, - &boxes); - if (likely (status == CAIRO_STATUS_SUCCESS)) { - status = _clip_and_composite_boxes (dst, op, source, - &boxes, antialias, - &extents, clip); - } - - _cairo_boxes_fini (&boxes); - - if (status != CAIRO_INT_STATUS_UNSUPPORTED) - goto CLEANUP_BOXES; - } - - _cairo_polygon_init (&info.polygon, clip_boxes, num_boxes); - - status = _cairo_path_fixed_stroke_to_polygon (path, - stroke_style, - ctm, ctm_inverse, - tolerance, - &info.polygon); - if (unlikely (status)) - goto CLEANUP_POLYGON; - - if (extents.is_bounded) { - cairo_rectangle_int_t rect; - - _cairo_box_round_to_rectangle (&info.polygon.extents, &rect); - if (! _cairo_rectangle_intersect (&extents.bounded, &rect)) - goto CLEANUP_POLYGON; - } - - if (info.polygon.num_edges == 0) { - if (! extents.is_bounded) - status = i965_fixup_unbounded (dst, &extents, clip); - } else { - info.fill_rule = CAIRO_FILL_RULE_WINDING; - info.antialias = antialias; - status = i965_clip_and_composite_spans (dst, op, source, antialias, - _composite_polygon_spans, &info, - &extents, clip); - } - -CLEANUP_POLYGON: - _cairo_polygon_fini (&info.polygon); - -CLEANUP_BOXES: - if (clip_boxes != boxes_stack) - free (clip_boxes); - - if (have_clip) - _cairo_clip_fini (&local_clip); - - return status; -} - -static cairo_int_status_t -i965_surface_fill (void *abstract_dst, - cairo_operator_t op, - const cairo_pattern_t*source, - cairo_path_fixed_t *path, - cairo_fill_rule_t fill_rule, - double tolerance, - cairo_antialias_t antialias, - cairo_clip_t *clip) -{ - i965_surface_t *dst = abstract_dst; - cairo_composite_rectangles_t extents; - composite_polygon_info_t info; - cairo_box_t boxes_stack[32], *clip_boxes = boxes_stack; - cairo_clip_t local_clip; - cairo_bool_t have_clip = FALSE; - int num_boxes = ARRAY_LENGTH (boxes_stack); - cairo_status_t status; - - status = _cairo_composite_rectangles_init_for_fill (&extents, - dst->intel.drm.width, - dst->intel.drm.height, - op, source, path, - clip); - if (unlikely (status)) - return status; - - if (clip != NULL && _cairo_clip_contains_extents (clip, &extents)) - clip = NULL; - - if (clip != NULL) { - clip = _cairo_clip_init_copy (&local_clip, clip); - have_clip = TRUE; - } - - status = _cairo_clip_to_boxes (&clip, &extents, &clip_boxes, &num_boxes); - if (unlikely (status)) { - if (have_clip) - _cairo_clip_fini (&local_clip); - - return status; - } - - assert (! _cairo_path_fixed_fill_is_empty (path)); - - if (_cairo_path_fixed_fill_is_rectilinear (path)) { - cairo_boxes_t boxes; - - _cairo_boxes_init (&boxes); - _cairo_boxes_limit (&boxes, clip_boxes, num_boxes); - status = _cairo_path_fixed_fill_rectilinear_to_boxes (path, - fill_rule, - &boxes); - if (likely (status == CAIRO_STATUS_SUCCESS)) { - status = _clip_and_composite_boxes (dst, op, source, - &boxes, antialias, - &extents, clip); - } - - _cairo_boxes_fini (&boxes); - - if (status != CAIRO_INT_STATUS_UNSUPPORTED) - goto CLEANUP_BOXES; - } - - _cairo_polygon_init (&info.polygon, clip_boxes, num_boxes); - - status = _cairo_path_fixed_fill_to_polygon (path, tolerance, &info.polygon); - if (unlikely (status)) - goto CLEANUP_POLYGON; - - if (extents.is_bounded) { - cairo_rectangle_int_t rect; - - _cairo_box_round_to_rectangle (&info.polygon.extents, &rect); - if (! _cairo_rectangle_intersect (&extents.bounded, &rect)) - goto CLEANUP_POLYGON; - } - - if (info.polygon.num_edges == 0) { - if (! extents.is_bounded) - status = i965_fixup_unbounded (dst, &extents, clip); - } else { - info.fill_rule = fill_rule; - info.antialias = antialias; - status = i965_clip_and_composite_spans (dst, op, source, antialias, - _composite_polygon_spans, &info, - &extents, clip); - } - -CLEANUP_POLYGON: - _cairo_polygon_fini (&info.polygon); - -CLEANUP_BOXES: - if (clip_boxes != boxes_stack) - free (clip_boxes); - - if (have_clip) - _cairo_clip_fini (&local_clip); - - return status; -} - -static const cairo_surface_backend_t i965_surface_backend = { - CAIRO_SURFACE_TYPE_DRM, - _cairo_default_context_create, - - i965_surface_create_similar, - i965_surface_finish, - - NULL, - intel_surface_acquire_source_image, - intel_surface_release_source_image, - - NULL, NULL, NULL, - NULL, /* composite */ - NULL, /* fill */ - NULL, /* trapezoids */ - NULL, /* span */ - NULL, /* check-span */ - - NULL, /* copy_page */ - NULL, /* show_page */ - _cairo_drm_surface_get_extents, - NULL, /* old-glyphs */ - _cairo_drm_surface_get_font_options, - - i965_surface_flush, - NULL, /* mark_dirty */ - intel_scaled_font_fini, - intel_scaled_glyph_fini, - - i965_surface_paint, - i965_surface_mask, - i965_surface_stroke, - i965_surface_fill, - i965_surface_glyphs, -}; - -static void -i965_surface_init (i965_surface_t *surface, - cairo_drm_device_t *device, - cairo_format_t format, - int width, int height) -{ - intel_surface_init (&surface->intel, &i965_surface_backend, device, - format, width, height); - surface->stream = 0; -} - -static inline int cairo_const -i965_tiling_stride (uint32_t tiling, int stride) -{ - if (tiling == I915_TILING_NONE) - return stride; - - return (stride + 127) & -128; -} - -static inline int cairo_const -i965_tiling_height (uint32_t tiling, int height) -{ - switch (tiling) { - default: - case I915_TILING_NONE: return (height + 1) & -2; - case I915_TILING_X: return (height + 7) & -8; - case I915_TILING_Y: return (height + 31) & -32; - } -} - -cairo_surface_t * -i965_surface_create_internal (cairo_drm_device_t *base_dev, - cairo_format_t format, - int width, int height, - uint32_t tiling, - cairo_bool_t gpu_target) -{ - i965_surface_t *surface; - cairo_status_t status_ignored; - - surface = _cairo_malloc (sizeof (i965_surface_t)); - if (unlikely (surface == NULL)) - return _cairo_surface_create_in_error (_cairo_error (CAIRO_STATUS_NO_MEMORY)); - - i965_surface_init (surface, base_dev, format, width, height); - - if (width && height) { - uint32_t size, stride; - intel_bo_t *bo; - - width = (width + 3) & -4; - stride = cairo_format_stride_for_width (surface->intel.drm.format, width); - stride = (stride + 63) & ~63; - stride = i965_tiling_stride (tiling, stride); - surface->intel.drm.stride = stride; - - height = i965_tiling_height (tiling, height); - assert (height <= I965_MAX_SIZE); - - size = stride * height; - bo = intel_bo_create (to_intel_device (&base_dev->base), - size, size, - gpu_target, tiling, stride); - if (bo == NULL) { - status_ignored = _cairo_drm_surface_finish (&surface->intel.drm); - free (surface); - return _cairo_surface_create_in_error (_cairo_error (CAIRO_STATUS_NO_MEMORY)); - } - - bo->tiling = tiling; - bo->stride = stride; - surface->intel.drm.bo = &bo->base; - - assert (bo->base.size >= (size_t) stride*height); - } - - return &surface->intel.drm.base; -} - -static cairo_surface_t * -i965_surface_create (cairo_drm_device_t *device, - cairo_format_t format, int width, int height) -{ - switch (format) { - case CAIRO_FORMAT_ARGB32: - case CAIRO_FORMAT_RGB16_565: - case CAIRO_FORMAT_RGB24: - case CAIRO_FORMAT_A8: - break; - case CAIRO_FORMAT_INVALID: - default: - case CAIRO_FORMAT_A1: - return _cairo_surface_create_in_error (_cairo_error (CAIRO_STATUS_INVALID_FORMAT)); - } - - return i965_surface_create_internal (device, format, width, height, - I965_TILING_DEFAULT, TRUE); -} - -static cairo_surface_t * -i965_surface_create_for_name (cairo_drm_device_t *base_dev, - unsigned int name, - cairo_format_t format, - int width, int height, int stride) -{ - i965_device_t *device; - i965_surface_t *surface; - cairo_status_t status_ignored; - int min_stride; - - min_stride = cairo_format_stride_for_width (format, (width + 3) & -4); - if (stride < min_stride || stride & 63) - return _cairo_surface_create_in_error (_cairo_error (CAIRO_STATUS_INVALID_STRIDE)); - - if (format == CAIRO_FORMAT_A1) - return _cairo_surface_create_in_error (_cairo_error (CAIRO_STATUS_INVALID_FORMAT)); - - switch (format) { - case CAIRO_FORMAT_ARGB32: - case CAIRO_FORMAT_RGB16_565: - case CAIRO_FORMAT_RGB24: - case CAIRO_FORMAT_A8: - break; - case CAIRO_FORMAT_INVALID: - default: - case CAIRO_FORMAT_A1: - return _cairo_surface_create_in_error (_cairo_error (CAIRO_STATUS_INVALID_FORMAT)); - } - - surface = _cairo_malloc (sizeof (i965_surface_t)); - if (unlikely (surface == NULL)) - return _cairo_surface_create_in_error (_cairo_error (CAIRO_STATUS_NO_MEMORY)); - - i965_surface_init (surface, base_dev, format, width, height); - - device = (i965_device_t *) base_dev; - surface->intel.drm.bo = &intel_bo_create_for_name (&device->intel, name)->base; - if (unlikely (surface->intel.drm.bo == NULL)) { - status_ignored = _cairo_drm_surface_finish (&surface->intel.drm); - free (surface); - return _cairo_surface_create_in_error (_cairo_error (CAIRO_STATUS_NO_MEMORY)); - } - - surface->intel.drm.stride = stride; - - return &surface->intel.drm.base; -} - -static cairo_status_t -i965_surface_enable_scan_out (void *abstract_surface) -{ - i965_surface_t *surface = abstract_surface; - intel_bo_t *bo; - - if (unlikely (surface->intel.drm.bo == NULL)) - return _cairo_error (CAIRO_STATUS_INVALID_SIZE); - - bo = to_intel_bo (surface->intel.drm.bo); - if (bo->tiling != I915_TILING_X) { - i965_device_t *device = i965_device (surface); - cairo_surface_pattern_t pattern; - cairo_surface_t *clone; - cairo_status_t status; - - clone = i965_surface_create_internal (&device->intel.base, - surface->intel.drm.base.content, - surface->intel.drm.width, - surface->intel.drm.height, - I915_TILING_X, - TRUE); - if (unlikely (clone->status)) - return clone->status; - - /* 2D blit? */ - _cairo_pattern_init_for_surface (&pattern, &surface->intel.drm.base); - pattern.base.filter = CAIRO_FILTER_NEAREST; - - status = _cairo_surface_paint (clone, - CAIRO_OPERATOR_SOURCE, - &pattern.base, - NULL); - - _cairo_pattern_fini (&pattern.base); - - if (unlikely (status)) { - cairo_surface_destroy (clone); - return status; - } - - /* swap buffer objects */ - surface->intel.drm.bo = ((cairo_drm_surface_t *) clone)->bo; - ((cairo_drm_surface_t *) clone)->bo = &bo->base; - bo = to_intel_bo (surface->intel.drm.bo); - - cairo_surface_destroy (clone); - } - - if (unlikely (bo->tiling == I915_TILING_Y)) - return _cairo_error (CAIRO_STATUS_INVALID_FORMAT); /* XXX */ - - return CAIRO_STATUS_SUCCESS; -} - -static cairo_int_status_t -_i965_device_flush (cairo_drm_device_t *device) -{ - cairo_status_t status; - - if (unlikely (device->base.finished)) - return CAIRO_STATUS_SUCCESS; - - status = cairo_device_acquire (&device->base); - if (likely (status == CAIRO_STATUS_SUCCESS)) - status = i965_device_flush ((i965_device_t *) device); - - cairo_device_release (&device->base); - - return status; -} - -static cairo_int_status_t -_i965_device_throttle (cairo_drm_device_t *device) -{ - cairo_status_t status; - - status = cairo_device_acquire (&device->base); - if (unlikely (status)) - return status; - - status = i965_device_flush ((i965_device_t *) device); - intel_throttle ((intel_device_t *) device); - - cairo_device_release (&device->base); - - return status; -} - -static void -_i965_device_destroy (void *base) -{ - i965_device_t *device = base; - - i965_device_reset (device); - i965_general_state_reset (device); - - _cairo_hash_table_destroy (device->sf_states); - _cairo_hash_table_destroy (device->samplers); - _cairo_hash_table_destroy (device->cc_states); - _cairo_hash_table_destroy (device->wm_kernels); - _cairo_hash_table_destroy (device->wm_states); - _cairo_hash_table_destroy (device->wm_bindings); - - _cairo_freelist_fini (&device->sf_freelist); - _cairo_freelist_fini (&device->cc_freelist); - _cairo_freelist_fini (&device->wm_kernel_freelist); - _cairo_freelist_fini (&device->wm_state_freelist); - _cairo_freelist_fini (&device->wm_binding_freelist); - _cairo_freelist_fini (&device->sampler_freelist); - - intel_device_fini (&device->intel); - free (device); -} - -static cairo_bool_t -hash_equal (const void *A, const void *B) -{ - const cairo_hash_entry_t *a = A, *b = B; - return a->hash == b->hash; -} - -cairo_drm_device_t * -_cairo_drm_i965_device_create (int fd, dev_t dev, int vendor_id, int chip_id) -{ - i965_device_t *device; - uint64_t gtt_size; - cairo_status_t status; - - if (! intel_info (fd, >t_size)) - return NULL; - - device = _cairo_malloc (sizeof (i965_device_t)); - if (unlikely (device == NULL)) - return (cairo_drm_device_t *) _cairo_device_create_in_error (CAIRO_STATUS_NO_MEMORY); - - status = intel_device_init (&device->intel, fd); - if (unlikely (status)) - goto CLEANUP; - - device->is_g4x = IS_G4X (chip_id); - //device->is_g5x = IS_G5X (chip_id); - - device->intel.base.surface.create = i965_surface_create; - device->intel.base.surface.create_for_name = i965_surface_create_for_name; - device->intel.base.surface.create_from_cacheable_image = NULL; - device->intel.base.surface.enable_scan_out = i965_surface_enable_scan_out; - - device->intel.base.device.flush = _i965_device_flush; - device->intel.base.device.throttle = _i965_device_throttle; - device->intel.base.device.destroy = _i965_device_destroy; - - device->sf_states = _cairo_hash_table_create (i965_sf_state_equal); - if (unlikely (device->sf_states == NULL)) - goto CLEANUP_INTEL; - - _cairo_freelist_init (&device->sf_freelist, - sizeof (struct i965_sf_state)); - - - device->cc_states = _cairo_hash_table_create (i965_cc_state_equal); - if (unlikely (device->cc_states == NULL)) - goto CLEANUP_SF; - - _cairo_freelist_init (&device->cc_freelist, - sizeof (struct i965_cc_state)); - - - device->wm_kernels = _cairo_hash_table_create (hash_equal); - if (unlikely (device->wm_kernels == NULL)) - goto CLEANUP_CC; - - _cairo_freelist_init (&device->wm_kernel_freelist, - sizeof (struct i965_wm_kernel)); - - device->wm_states = _cairo_hash_table_create (i965_wm_state_equal); - if (unlikely (device->wm_states == NULL)) - goto CLEANUP_WM_KERNEL; - - _cairo_freelist_init (&device->wm_state_freelist, - sizeof (struct i965_wm_state)); - - - device->wm_bindings = _cairo_hash_table_create (i965_wm_binding_equal); - if (unlikely (device->wm_bindings == NULL)) - goto CLEANUP_WM_STATE; - - _cairo_freelist_init (&device->wm_binding_freelist, - sizeof (struct i965_wm_binding)); - - device->samplers = _cairo_hash_table_create (hash_equal); - if (unlikely (device->samplers == NULL)) - goto CLEANUP_WM_BINDING; - - _cairo_freelist_init (&device->sampler_freelist, - sizeof (struct i965_sampler)); - - i965_stream_init (&device->batch, - device->batch_base, sizeof (device->batch_base), - NULL, 0, - device->batch_relocations, - ARRAY_LENGTH (device->batch_relocations)); - - i965_stream_init (&device->surface, - device->surface_base, sizeof (device->surface_base), - device->surface_pending_relocations, - ARRAY_LENGTH (device->surface_pending_relocations), - device->surface_relocations, - ARRAY_LENGTH (device->surface_relocations)); - - i965_stream_init (&device->general, - device->general_base, sizeof (device->general_base), - device->general_pending_relocations, - ARRAY_LENGTH (device->general_pending_relocations), - NULL, 0); - - i965_stream_init (&device->vertex, - device->vertex_base, sizeof (device->vertex_base), - device->vertex_pending_relocations, - ARRAY_LENGTH (device->vertex_pending_relocations), - NULL, 0); - - cairo_list_init (&device->flush); - i965_device_reset (device); - device->vs_offset = (uint32_t) -1; - device->border_color_offset = (uint32_t) -1; - device->general_state = NULL; - - return _cairo_drm_device_init (&device->intel.base, - fd, dev, vendor_id, chip_id, - I965_MAX_SIZE); - - CLEANUP_WM_BINDING: - _cairo_hash_table_destroy (device->wm_bindings); - CLEANUP_WM_STATE: - _cairo_hash_table_destroy (device->wm_states); - CLEANUP_WM_KERNEL: - _cairo_hash_table_destroy (device->wm_kernels); - CLEANUP_CC: - _cairo_hash_table_destroy (device->cc_states); - CLEANUP_SF: - _cairo_hash_table_destroy (device->sf_states); - CLEANUP_INTEL: - intel_device_fini (&device->intel); - CLEANUP: - free (device); - return (cairo_drm_device_t *) _cairo_device_create_in_error (status); -} diff --git a/gfx/cairo/cairo/src/drm/cairo-drm-intel-brw-defines.h b/gfx/cairo/cairo/src/drm/cairo-drm-intel-brw-defines.h deleted file mode 100644 index b2be36f183..0000000000 --- a/gfx/cairo/cairo/src/drm/cairo-drm-intel-brw-defines.h +++ /dev/null @@ -1,824 +0,0 @@ -/************************************************************************** - * - * Copyright 2005 Tungsten Graphics, Inc., Cedar Park, Texas. - * All Rights Reserved. - * - * Permission is hereby granted, free of charge, to any person obtaining a - * copy of this software and associated documentation files (the - * "Software"), to deal in the Software without restriction, including - * without limitation the rights to use, copy, modify, merge, publish, - * distribute, sub license, and/or sell copies of the Software, and to - * permit persons to whom the Software is furnished to do so, subject to - * the following conditions: - * - * The above copyright notice and this permission notice (including the - * next paragraph) shall be included in all copies or substantial portions - * of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS - * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. - * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR - * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, - * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE - * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - * - **************************************************************************/ - -#ifndef CAIRO_DRM_INTEL_BRW_DEFINES_H -#define CAIRO_DRM_INTEL_BRW_DEFINES_H - -/* 3D state: */ -#define _3DOP_3DSTATE_PIPELINED 0x0 -#define _3DOP_3DSTATE_NONPIPELINED 0x1 -#define _3DOP_3DCONTROL 0x2 -#define _3DOP_3DPRIMITIVE 0x3 - -#define _3DSTATE_PIPELINED_POINTERS 0x00 -#define _3DSTATE_BINDING_TABLE_POINTERS 0x01 -#define _3DSTATE_VERTEX_BUFFERS 0x08 -#define _3DSTATE_VERTEX_ELEMENTS 0x09 -#define _3DSTATE_INDEX_BUFFER 0x0A -#define _3DSTATE_VF_STATISTICS 0x0B -#define _3DSTATE_DRAWING_RECTANGLE 0x00 -#define _3DSTATE_CONSTANT_COLOR 0x01 -#define _3DSTATE_SAMPLER_PALETTE_LOAD 0x02 -#define _3DSTATE_CHROMA_KEY 0x04 -#define _3DSTATE_DEPTH_BUFFER 0x05 -#define _3DSTATE_POLY_STIPPLE_OFFSET 0x06 -#define _3DSTATE_POLY_STIPPLE_PATTERN 0x07 -#define _3DSTATE_LINE_STIPPLE 0x08 -#define _3DSTATE_GLOBAL_DEPTH_OFFSET_CLAMP 0x09 -#define _3DCONTROL 0x00 -#define _3DPRIMITIVE 0x00 - -#define PIPE_CONTROL_NOWRITE 0x00 -#define PIPE_CONTROL_WRITEIMMEDIATE 0x01 -#define PIPE_CONTROL_WRITEDEPTH 0x02 -#define PIPE_CONTROL_WRITETIMESTAMP 0x03 - -#define PIPE_CONTROL_GTTWRITE_PROCESS_LOCAL 0x00 -#define PIPE_CONTROL_GTTWRITE_GLOBAL 0x01 - -#define BRW_3D(Pipeline,Opcode,Subopcode) ((3 << 29) | \ - ((Pipeline) << 27) | \ - ((Opcode) << 24) | \ - ((Subopcode) << 16)) - -#define BRW_PIPE_CONTROL BRW_3D(3, 2, 0) -#define BRW_PIPE_CONTROL_NOWRITE (0 << 14) -#define BRW_PIPE_CONTROL_WRITE_QWORD (1 << 14) -#define BRW_PIPE_CONTROL_WRITE_DEPTH (2 << 14) -#define BRW_PIPE_CONTROL_WRITE_TIME (3 << 14) -#define BRW_PIPE_CONTROL_DEPTH_STALL (1 << 13) -#define BRW_PIPE_CONTROL_WC_FLUSH (1 << 12) -#define BRW_PIPE_CONTROL_IS_FLUSH (1 << 11) -#define BRW_PIPE_CONTROL_NOTIFY_ENABLE (1 << 8) -#define BRW_PIPE_CONTROL_GLOBAL_GTT (1 << 2) -#define BRW_PIPE_CONTROL_LOCAL_PGTT (0 << 2) - -#define _3DPRIM_POINTLIST 0x01 -#define _3DPRIM_LINELIST 0x02 -#define _3DPRIM_LINESTRIP 0x03 -#define _3DPRIM_TRILIST 0x04 -#define _3DPRIM_TRISTRIP 0x05 -#define _3DPRIM_TRIFAN 0x06 -#define _3DPRIM_QUADLIST 0x07 -#define _3DPRIM_QUADSTRIP 0x08 -#define _3DPRIM_LINELIST_ADJ 0x09 -#define _3DPRIM_LINESTRIP_ADJ 0x0A -#define _3DPRIM_TRILIST_ADJ 0x0B -#define _3DPRIM_TRISTRIP_ADJ 0x0C -#define _3DPRIM_TRISTRIP_REVERSE 0x0D -#define _3DPRIM_POLYGON 0x0E -#define _3DPRIM_RECTLIST 0x0F -#define _3DPRIM_LINELOOP 0x10 -#define _3DPRIM_POINTLIST_BF 0x11 -#define _3DPRIM_LINESTRIP_CONT 0x12 -#define _3DPRIM_LINESTRIP_BF 0x13 -#define _3DPRIM_LINESTRIP_CONT_BF 0x14 -#define _3DPRIM_TRIFAN_NOSTIPPLE 0x15 - -#define _3DPRIM_VERTEXBUFFER_ACCESS_SEQUENTIAL 0 -#define _3DPRIM_VERTEXBUFFER_ACCESS_RANDOM 1 - -#define BRW_ANISORATIO_2 0 -#define BRW_ANISORATIO_4 1 -#define BRW_ANISORATIO_6 2 -#define BRW_ANISORATIO_8 3 -#define BRW_ANISORATIO_10 4 -#define BRW_ANISORATIO_12 5 -#define BRW_ANISORATIO_14 6 -#define BRW_ANISORATIO_16 7 - -#define BRW_BLENDFACTOR_ONE 0x1 -#define BRW_BLENDFACTOR_SRC_COLOR 0x2 -#define BRW_BLENDFACTOR_SRC_ALPHA 0x3 -#define BRW_BLENDFACTOR_DST_ALPHA 0x4 -#define BRW_BLENDFACTOR_DST_COLOR 0x5 -#define BRW_BLENDFACTOR_SRC_ALPHA_SATURATE 0x6 -#define BRW_BLENDFACTOR_CONST_COLOR 0x7 -#define BRW_BLENDFACTOR_CONST_ALPHA 0x8 -#define BRW_BLENDFACTOR_SRC1_COLOR 0x9 -#define BRW_BLENDFACTOR_SRC1_ALPHA 0x0A -#define BRW_BLENDFACTOR_ZERO 0x11 -#define BRW_BLENDFACTOR_INV_SRC_COLOR 0x12 -#define BRW_BLENDFACTOR_INV_SRC_ALPHA 0x13 -#define BRW_BLENDFACTOR_INV_DST_ALPHA 0x14 -#define BRW_BLENDFACTOR_INV_DST_COLOR 0x15 -#define BRW_BLENDFACTOR_INV_CONST_COLOR 0x17 -#define BRW_BLENDFACTOR_INV_CONST_ALPHA 0x18 -#define BRW_BLENDFACTOR_INV_SRC1_COLOR 0x19 -#define BRW_BLENDFACTOR_INV_SRC1_ALPHA 0x1A - -#define BRW_BLENDFUNCTION_ADD 0 -#define BRW_BLENDFUNCTION_SUBTRACT 1 -#define BRW_BLENDFUNCTION_REVERSE_SUBTRACT 2 -#define BRW_BLENDFUNCTION_MIN 3 -#define BRW_BLENDFUNCTION_MAX 4 - -#define BRW_ALPHATEST_FORMAT_UNORM8 0 -#define BRW_ALPHATEST_FORMAT_FLOAT32 1 - -#define BRW_CHROMAKEY_KILL_ON_ANY_MATCH 0 -#define BRW_CHROMAKEY_REPLACE_BLACK 1 - -#define BRW_CLIP_API_OGL 0 -#define BRW_CLIP_API_DX 1 - -#define BRW_CLIPMODE_NORMAL 0 -#define BRW_CLIPMODE_CLIP_ALL 1 -#define BRW_CLIPMODE_CLIP_NON_REJECTED 2 -#define BRW_CLIPMODE_REJECT_ALL 3 -#define BRW_CLIPMODE_ACCEPT_ALL 4 - -#define BRW_CLIP_NDCSPACE 0 -#define BRW_CLIP_SCREENSPACE 1 - -#define BRW_COMPAREFUNCTION_ALWAYS 0 -#define BRW_COMPAREFUNCTION_NEVER 1 -#define BRW_COMPAREFUNCTION_LESS 2 -#define BRW_COMPAREFUNCTION_EQUAL 3 -#define BRW_COMPAREFUNCTION_LEQUAL 4 -#define BRW_COMPAREFUNCTION_GREATER 5 -#define BRW_COMPAREFUNCTION_NOTEQUAL 6 -#define BRW_COMPAREFUNCTION_GEQUAL 7 - -#define BRW_COVERAGE_PIXELS_HALF 0 -#define BRW_COVERAGE_PIXELS_1 1 -#define BRW_COVERAGE_PIXELS_2 2 -#define BRW_COVERAGE_PIXELS_4 3 - -#define BRW_CULLMODE_BOTH 0 -#define BRW_CULLMODE_NONE 1 -#define BRW_CULLMODE_FRONT 2 -#define BRW_CULLMODE_BACK 3 - -#define BRW_DEFAULTCOLOR_R8G8B8A8_UNORM 0 -#define BRW_DEFAULTCOLOR_R32G32B32A32_FLOAT 1 - -#define BRW_DEPTHFORMAT_D32_FLOAT_S8X24_UINT 0 -#define BRW_DEPTHFORMAT_D32_FLOAT 1 -#define BRW_DEPTHFORMAT_D24_UNORM_S8_UINT 2 -#define BRW_DEPTHFORMAT_D16_UNORM 5 - -#define BRW_FLOATING_POINT_IEEE_754 0 -#define BRW_FLOATING_POINT_NON_IEEE_754 1 - -#define BRW_FRONTWINDING_CW 0 -#define BRW_FRONTWINDING_CCW 1 - -#define BRW_INDEX_BYTE 0 -#define BRW_INDEX_WORD 1 -#define BRW_INDEX_DWORD 2 - -#define BRW_LOGICOPFUNCTION_CLEAR 0 -#define BRW_LOGICOPFUNCTION_NOR 1 -#define BRW_LOGICOPFUNCTION_AND_INVERTED 2 -#define BRW_LOGICOPFUNCTION_COPY_INVERTED 3 -#define BRW_LOGICOPFUNCTION_AND_REVERSE 4 -#define BRW_LOGICOPFUNCTION_INVERT 5 -#define BRW_LOGICOPFUNCTION_XOR 6 -#define BRW_LOGICOPFUNCTION_NAND 7 -#define BRW_LOGICOPFUNCTION_AND 8 -#define BRW_LOGICOPFUNCTION_EQUIV 9 -#define BRW_LOGICOPFUNCTION_NOOP 10 -#define BRW_LOGICOPFUNCTION_OR_INVERTED 11 -#define BRW_LOGICOPFUNCTION_COPY 12 -#define BRW_LOGICOPFUNCTION_OR_REVERSE 13 -#define BRW_LOGICOPFUNCTION_OR 14 -#define BRW_LOGICOPFUNCTION_SET 15 - -#define BRW_MAPFILTER_NEAREST 0x0 -#define BRW_MAPFILTER_LINEAR 0x1 -#define BRW_MAPFILTER_ANISOTROPIC 0x2 - -#define BRW_MIPFILTER_NONE 0 -#define BRW_MIPFILTER_NEAREST 1 -#define BRW_MIPFILTER_LINEAR 3 - -#define BRW_POLYGON_FRONT_FACING 0 -#define BRW_POLYGON_BACK_FACING 1 - -#define BRW_PREFILTER_ALWAYS 0x0 -#define BRW_PREFILTER_NEVER 0x1 -#define BRW_PREFILTER_LESS 0x2 -#define BRW_PREFILTER_EQUAL 0x3 -#define BRW_PREFILTER_LEQUAL 0x4 -#define BRW_PREFILTER_GREATER 0x5 -#define BRW_PREFILTER_NOTEQUAL 0x6 -#define BRW_PREFILTER_GEQUAL 0x7 - -#define BRW_PROVOKING_VERTEX_0 0 -#define BRW_PROVOKING_VERTEX_1 1 -#define BRW_PROVOKING_VERTEX_2 2 - -#define BRW_RASTRULE_UPPER_LEFT 0 -#define BRW_RASTRULE_UPPER_RIGHT 1 - -#define BRW_RENDERTARGET_CLAMPRANGE_UNORM 0 -#define BRW_RENDERTARGET_CLAMPRANGE_SNORM 1 -#define BRW_RENDERTARGET_CLAMPRANGE_FORMAT 2 - -#define BRW_STENCILOP_KEEP 0 -#define BRW_STENCILOP_ZERO 1 -#define BRW_STENCILOP_REPLACE 2 -#define BRW_STENCILOP_INCRSAT 3 -#define BRW_STENCILOP_DECRSAT 4 -#define BRW_STENCILOP_INCR 5 -#define BRW_STENCILOP_DECR 6 -#define BRW_STENCILOP_INVERT 7 - -#define BRW_SURFACE_MIPMAPLAYOUT_BELOW 0 -#define BRW_SURFACE_MIPMAPLAYOUT_RIGHT 1 - -#define BRW_SURFACEFORMAT_R32G32B32A32_FLOAT 0x000 -#define BRW_SURFACEFORMAT_R32G32B32A32_SINT 0x001 -#define BRW_SURFACEFORMAT_R32G32B32A32_UINT 0x002 -#define BRW_SURFACEFORMAT_R32G32B32A32_UNORM 0x003 -#define BRW_SURFACEFORMAT_R32G32B32A32_SNORM 0x004 -#define BRW_SURFACEFORMAT_R64G64_FLOAT 0x005 -#define BRW_SURFACEFORMAT_R32G32B32X32_FLOAT 0x006 -#define BRW_SURFACEFORMAT_R32G32B32A32_SSCALED 0x007 -#define BRW_SURFACEFORMAT_R32G32B32A32_USCALED 0x008 -#define BRW_SURFACEFORMAT_R32G32B32_FLOAT 0x040 -#define BRW_SURFACEFORMAT_R32G32B32_SINT 0x041 -#define BRW_SURFACEFORMAT_R32G32B32_UINT 0x042 -#define BRW_SURFACEFORMAT_R32G32B32_UNORM 0x043 -#define BRW_SURFACEFORMAT_R32G32B32_SNORM 0x044 -#define BRW_SURFACEFORMAT_R32G32B32_SSCALED 0x045 -#define BRW_SURFACEFORMAT_R32G32B32_USCALED 0x046 -#define BRW_SURFACEFORMAT_R16G16B16A16_UNORM 0x080 -#define BRW_SURFACEFORMAT_R16G16B16A16_SNORM 0x081 -#define BRW_SURFACEFORMAT_R16G16B16A16_SINT 0x082 -#define BRW_SURFACEFORMAT_R16G16B16A16_UINT 0x083 -#define BRW_SURFACEFORMAT_R16G16B16A16_FLOAT 0x084 -#define BRW_SURFACEFORMAT_R32G32_FLOAT 0x085 -#define BRW_SURFACEFORMAT_R32G32_SINT 0x086 -#define BRW_SURFACEFORMAT_R32G32_UINT 0x087 -#define BRW_SURFACEFORMAT_R32_FLOAT_X8X24_TYPELESS 0x088 -#define BRW_SURFACEFORMAT_X32_TYPELESS_G8X24_UINT 0x089 -#define BRW_SURFACEFORMAT_L32A32_FLOAT 0x08A -#define BRW_SURFACEFORMAT_R32G32_UNORM 0x08B -#define BRW_SURFACEFORMAT_R32G32_SNORM 0x08C -#define BRW_SURFACEFORMAT_R64_FLOAT 0x08D -#define BRW_SURFACEFORMAT_R16G16B16X16_UNORM 0x08E -#define BRW_SURFACEFORMAT_R16G16B16X16_FLOAT 0x08F -#define BRW_SURFACEFORMAT_A32X32_FLOAT 0x090 -#define BRW_SURFACEFORMAT_L32X32_FLOAT 0x091 -#define BRW_SURFACEFORMAT_I32X32_FLOAT 0x092 -#define BRW_SURFACEFORMAT_R16G16B16A16_SSCALED 0x093 -#define BRW_SURFACEFORMAT_R16G16B16A16_USCALED 0x094 -#define BRW_SURFACEFORMAT_R32G32_SSCALED 0x095 -#define BRW_SURFACEFORMAT_R32G32_USCALED 0x096 -#define BRW_SURFACEFORMAT_B8G8R8A8_UNORM 0x0C0 -#define BRW_SURFACEFORMAT_B8G8R8A8_UNORM_SRGB 0x0C1 -#define BRW_SURFACEFORMAT_R10G10B10A2_UNORM 0x0C2 -#define BRW_SURFACEFORMAT_R10G10B10A2_UNORM_SRGB 0x0C3 -#define BRW_SURFACEFORMAT_R10G10B10A2_UINT 0x0C4 -#define BRW_SURFACEFORMAT_R10G10B10_SNORM_A2_UNORM 0x0C5 -#define BRW_SURFACEFORMAT_R8G8B8A8_UNORM 0x0C7 -#define BRW_SURFACEFORMAT_R8G8B8A8_UNORM_SRGB 0x0C8 -#define BRW_SURFACEFORMAT_R8G8B8A8_SNORM 0x0C9 -#define BRW_SURFACEFORMAT_R8G8B8A8_SINT 0x0CA -#define BRW_SURFACEFORMAT_R8G8B8A8_UINT 0x0CB -#define BRW_SURFACEFORMAT_R16G16_UNORM 0x0CC -#define BRW_SURFACEFORMAT_R16G16_SNORM 0x0CD -#define BRW_SURFACEFORMAT_R16G16_SINT 0x0CE -#define BRW_SURFACEFORMAT_R16G16_UINT 0x0CF -#define BRW_SURFACEFORMAT_R16G16_FLOAT 0x0D0 -#define BRW_SURFACEFORMAT_B10G10R10A2_UNORM 0x0D1 -#define BRW_SURFACEFORMAT_B10G10R10A2_UNORM_SRGB 0x0D2 -#define BRW_SURFACEFORMAT_R11G11B10_FLOAT 0x0D3 -#define BRW_SURFACEFORMAT_R32_SINT 0x0D6 -#define BRW_SURFACEFORMAT_R32_UINT 0x0D7 -#define BRW_SURFACEFORMAT_R32_FLOAT 0x0D8 -#define BRW_SURFACEFORMAT_R24_UNORM_X8_TYPELESS 0x0D9 -#define BRW_SURFACEFORMAT_X24_TYPELESS_G8_UINT 0x0DA -#define BRW_SURFACEFORMAT_L16A16_UNORM 0x0DF -#define BRW_SURFACEFORMAT_I24X8_UNORM 0x0E0 -#define BRW_SURFACEFORMAT_L24X8_UNORM 0x0E1 -#define BRW_SURFACEFORMAT_A24X8_UNORM 0x0E2 -#define BRW_SURFACEFORMAT_I32_FLOAT 0x0E3 -#define BRW_SURFACEFORMAT_L32_FLOAT 0x0E4 -#define BRW_SURFACEFORMAT_A32_FLOAT 0x0E5 -#define BRW_SURFACEFORMAT_B8G8R8X8_UNORM 0x0E9 -#define BRW_SURFACEFORMAT_B8G8R8X8_UNORM_SRGB 0x0EA -#define BRW_SURFACEFORMAT_R8G8B8X8_UNORM 0x0EB -#define BRW_SURFACEFORMAT_R8G8B8X8_UNORM_SRGB 0x0EC -#define BRW_SURFACEFORMAT_R9G9B9E5_SHAREDEXP 0x0ED -#define BRW_SURFACEFORMAT_B10G10R10X2_UNORM 0x0EE -#define BRW_SURFACEFORMAT_L16A16_FLOAT 0x0F0 -#define BRW_SURFACEFORMAT_R32_UNORM 0x0F1 -#define BRW_SURFACEFORMAT_R32_SNORM 0x0F2 -#define BRW_SURFACEFORMAT_R10G10B10X2_USCALED 0x0F3 -#define BRW_SURFACEFORMAT_R8G8B8A8_SSCALED 0x0F4 -#define BRW_SURFACEFORMAT_R8G8B8A8_USCALED 0x0F5 -#define BRW_SURFACEFORMAT_R16G16_SSCALED 0x0F6 -#define BRW_SURFACEFORMAT_R16G16_USCALED 0x0F7 -#define BRW_SURFACEFORMAT_R32_SSCALED 0x0F8 -#define BRW_SURFACEFORMAT_R32_USCALED 0x0F9 -#define BRW_SURFACEFORMAT_B5G6R5_UNORM 0x100 -#define BRW_SURFACEFORMAT_B5G6R5_UNORM_SRGB 0x101 -#define BRW_SURFACEFORMAT_B5G5R5A1_UNORM 0x102 -#define BRW_SURFACEFORMAT_B5G5R5A1_UNORM_SRGB 0x103 -#define BRW_SURFACEFORMAT_B4G4R4A4_UNORM 0x104 -#define BRW_SURFACEFORMAT_B4G4R4A4_UNORM_SRGB 0x105 -#define BRW_SURFACEFORMAT_R8G8_UNORM 0x106 -#define BRW_SURFACEFORMAT_R8G8_SNORM 0x107 -#define BRW_SURFACEFORMAT_R8G8_SINT 0x108 -#define BRW_SURFACEFORMAT_R8G8_UINT 0x109 -#define BRW_SURFACEFORMAT_R16_UNORM 0x10A -#define BRW_SURFACEFORMAT_R16_SNORM 0x10B -#define BRW_SURFACEFORMAT_R16_SINT 0x10C -#define BRW_SURFACEFORMAT_R16_UINT 0x10D -#define BRW_SURFACEFORMAT_R16_FLOAT 0x10E -#define BRW_SURFACEFORMAT_I16_UNORM 0x111 -#define BRW_SURFACEFORMAT_L16_UNORM 0x112 -#define BRW_SURFACEFORMAT_A16_UNORM 0x113 -#define BRW_SURFACEFORMAT_L8A8_UNORM 0x114 -#define BRW_SURFACEFORMAT_I16_FLOAT 0x115 -#define BRW_SURFACEFORMAT_L16_FLOAT 0x116 -#define BRW_SURFACEFORMAT_A16_FLOAT 0x117 -#define BRW_SURFACEFORMAT_R5G5_SNORM_B6_UNORM 0x119 -#define BRW_SURFACEFORMAT_B5G5R5X1_UNORM 0x11A -#define BRW_SURFACEFORMAT_B5G5R5X1_UNORM_SRGB 0x11B -#define BRW_SURFACEFORMAT_R8G8_SSCALED 0x11C -#define BRW_SURFACEFORMAT_R8G8_USCALED 0x11D -#define BRW_SURFACEFORMAT_R16_SSCALED 0x11E -#define BRW_SURFACEFORMAT_R16_USCALED 0x11F -#define BRW_SURFACEFORMAT_R8_UNORM 0x140 -#define BRW_SURFACEFORMAT_R8_SNORM 0x141 -#define BRW_SURFACEFORMAT_R8_SINT 0x142 -#define BRW_SURFACEFORMAT_R8_UINT 0x143 -#define BRW_SURFACEFORMAT_A8_UNORM 0x144 -#define BRW_SURFACEFORMAT_I8_UNORM 0x145 -#define BRW_SURFACEFORMAT_L8_UNORM 0x146 -#define BRW_SURFACEFORMAT_P4A4_UNORM 0x147 -#define BRW_SURFACEFORMAT_A4P4_UNORM 0x148 -#define BRW_SURFACEFORMAT_R8_SSCALED 0x149 -#define BRW_SURFACEFORMAT_R8_USCALED 0x14A -#define BRW_SURFACEFORMAT_R1_UINT 0x181 -#define BRW_SURFACEFORMAT_YCRCB_NORMAL 0x182 -#define BRW_SURFACEFORMAT_YCRCB_SWAPUVY 0x183 -#define BRW_SURFACEFORMAT_BC1_UNORM 0x186 -#define BRW_SURFACEFORMAT_BC2_UNORM 0x187 -#define BRW_SURFACEFORMAT_BC3_UNORM 0x188 -#define BRW_SURFACEFORMAT_BC4_UNORM 0x189 -#define BRW_SURFACEFORMAT_BC5_UNORM 0x18A -#define BRW_SURFACEFORMAT_BC1_UNORM_SRGB 0x18B -#define BRW_SURFACEFORMAT_BC2_UNORM_SRGB 0x18C -#define BRW_SURFACEFORMAT_BC3_UNORM_SRGB 0x18D -#define BRW_SURFACEFORMAT_MONO8 0x18E -#define BRW_SURFACEFORMAT_YCRCB_SWAPUV 0x18F -#define BRW_SURFACEFORMAT_YCRCB_SWAPY 0x190 -#define BRW_SURFACEFORMAT_DXT1_RGB 0x191 -#define BRW_SURFACEFORMAT_FXT1 0x192 -#define BRW_SURFACEFORMAT_R8G8B8_UNORM 0x193 -#define BRW_SURFACEFORMAT_R8G8B8_SNORM 0x194 -#define BRW_SURFACEFORMAT_R8G8B8_SSCALED 0x195 -#define BRW_SURFACEFORMAT_R8G8B8_USCALED 0x196 -#define BRW_SURFACEFORMAT_R64G64B64A64_FLOAT 0x197 -#define BRW_SURFACEFORMAT_R64G64B64_FLOAT 0x198 -#define BRW_SURFACEFORMAT_BC4_SNORM 0x199 -#define BRW_SURFACEFORMAT_BC5_SNORM 0x19A -#define BRW_SURFACEFORMAT_R16G16B16_UNORM 0x19C -#define BRW_SURFACEFORMAT_R16G16B16_SNORM 0x19D -#define BRW_SURFACEFORMAT_R16G16B16_SSCALED 0x19E -#define BRW_SURFACEFORMAT_R16G16B16_USCALED 0x19F - -#define BRW_SURFACERETURNFORMAT_FLOAT32 0 -#define BRW_SURFACERETURNFORMAT_S1 1 - -#define BRW_SURFACE_1D 0 -#define BRW_SURFACE_2D 1 -#define BRW_SURFACE_3D 2 -#define BRW_SURFACE_CUBE 3 -#define BRW_SURFACE_BUFFER 4 -#define BRW_SURFACE_NULL 7 - -#define BRW_BORDER_COLOR_MODE_DEFAULT 0 -#define BRW_BORDER_COLOR_MODE_LEGACY 1 - -#define BRW_TEXCOORDMODE_WRAP 0 -#define BRW_TEXCOORDMODE_MIRROR 1 -#define BRW_TEXCOORDMODE_CLAMP 2 -#define BRW_TEXCOORDMODE_CUBE 3 -#define BRW_TEXCOORDMODE_CLAMP_BORDER 4 -#define BRW_TEXCOORDMODE_MIRROR_ONCE 5 - -#define BRW_THREAD_PRIORITY_NORMAL 0 -#define BRW_THREAD_PRIORITY_HIGH 1 - -#define BRW_TILEWALK_XMAJOR 0 -#define BRW_TILEWALK_YMAJOR 1 - -#define BRW_VERTEX_SUBPIXEL_PRECISION_8BITS 0 -#define BRW_VERTEX_SUBPIXEL_PRECISION_4BITS 1 - -#define BRW_VERTEXBUFFER_ACCESS_VERTEXDATA 0 -#define BRW_VERTEXBUFFER_ACCESS_INSTANCEDATA 1 - -#define BRW_VFCOMPONENT_NOSTORE 0 -#define BRW_VFCOMPONENT_STORE_SRC 1 -#define BRW_VFCOMPONENT_STORE_0 2 -#define BRW_VFCOMPONENT_STORE_1_FLT 3 -#define BRW_VFCOMPONENT_STORE_1_INT 4 -#define BRW_VFCOMPONENT_STORE_VID 5 -#define BRW_VFCOMPONENT_STORE_IID 6 -#define BRW_VFCOMPONENT_STORE_PID 7 - - - -/* Execution Unit (EU) defines */ - -#define BRW_ALIGN_1 0 -#define BRW_ALIGN_16 1 - -#define BRW_ADDRESS_DIRECT 0 -#define BRW_ADDRESS_REGISTER_INDIRECT_REGISTER 1 - -#define BRW_CHANNEL_X 0 -#define BRW_CHANNEL_Y 1 -#define BRW_CHANNEL_Z 2 -#define BRW_CHANNEL_W 3 - -#define BRW_COMPRESSION_NONE 0 -#define BRW_COMPRESSION_2NDHALF 1 -#define BRW_COMPRESSION_COMPRESSED 2 - -#define BRW_CONDITIONAL_NONE 0 -#define BRW_CONDITIONAL_Z 1 -#define BRW_CONDITIONAL_NZ 2 -#define BRW_CONDITIONAL_EQ 1 /* Z */ -#define BRW_CONDITIONAL_NEQ 2 /* NZ */ -#define BRW_CONDITIONAL_G 3 -#define BRW_CONDITIONAL_GE 4 -#define BRW_CONDITIONAL_L 5 -#define BRW_CONDITIONAL_LE 6 -#define BRW_CONDITIONAL_C 7 -#define BRW_CONDITIONAL_O 8 - -#define BRW_DEBUG_NONE 0 -#define BRW_DEBUG_BREAKPOINT 1 - -#define BRW_DEPENDENCY_NORMAL 0 -#define BRW_DEPENDENCY_NOTCLEARED 1 -#define BRW_DEPENDENCY_NOTCHECKED 2 -#define BRW_DEPENDENCY_DISABLE 3 - -#define BRW_EXECUTE_1 0 -#define BRW_EXECUTE_2 1 -#define BRW_EXECUTE_4 2 -#define BRW_EXECUTE_8 3 -#define BRW_EXECUTE_16 4 -#define BRW_EXECUTE_32 5 - -#define BRW_HORIZONTAL_STRIDE_0 0 -#define BRW_HORIZONTAL_STRIDE_1 1 -#define BRW_HORIZONTAL_STRIDE_2 2 -#define BRW_HORIZONTAL_STRIDE_4 3 - -#define BRW_INSTRUCTION_NORMAL 0 -#define BRW_INSTRUCTION_SATURATE 1 - -#define BRW_MASK_ENABLE 0 -#define BRW_MASK_DISABLE 1 - -#define BRW_OPCODE_MOV 1 -#define BRW_OPCODE_SEL 2 -#define BRW_OPCODE_NOT 4 -#define BRW_OPCODE_AND 5 -#define BRW_OPCODE_OR 6 -#define BRW_OPCODE_XOR 7 -#define BRW_OPCODE_SHR 8 -#define BRW_OPCODE_SHL 9 -#define BRW_OPCODE_RSR 10 -#define BRW_OPCODE_RSL 11 -#define BRW_OPCODE_ASR 12 -#define BRW_OPCODE_CMP 16 -#define BRW_OPCODE_JMPI 32 -#define BRW_OPCODE_IF 34 -#define BRW_OPCODE_IFF 35 -#define BRW_OPCODE_ELSE 36 -#define BRW_OPCODE_ENDIF 37 -#define BRW_OPCODE_DO 38 -#define BRW_OPCODE_WHILE 39 -#define BRW_OPCODE_BREAK 40 -#define BRW_OPCODE_CONTINUE 41 -#define BRW_OPCODE_HALT 42 -#define BRW_OPCODE_MSAVE 44 -#define BRW_OPCODE_MRESTORE 45 -#define BRW_OPCODE_PUSH 46 -#define BRW_OPCODE_POP 47 -#define BRW_OPCODE_WAIT 48 -#define BRW_OPCODE_SEND 49 -#define BRW_OPCODE_ADD 64 -#define BRW_OPCODE_MUL 65 -#define BRW_OPCODE_AVG 66 -#define BRW_OPCODE_FRC 67 -#define BRW_OPCODE_RNDU 68 -#define BRW_OPCODE_RNDD 69 -#define BRW_OPCODE_RNDE 70 -#define BRW_OPCODE_RNDZ 71 -#define BRW_OPCODE_MAC 72 -#define BRW_OPCODE_MACH 73 -#define BRW_OPCODE_LZD 74 -#define BRW_OPCODE_SAD2 80 -#define BRW_OPCODE_SADA2 81 -#define BRW_OPCODE_DP4 84 -#define BRW_OPCODE_DPH 85 -#define BRW_OPCODE_DP3 86 -#define BRW_OPCODE_DP2 87 -#define BRW_OPCODE_DPA2 88 -#define BRW_OPCODE_LINE 89 -#define BRW_OPCODE_NOP 126 - -#define BRW_PREDICATE_NONE 0 -#define BRW_PREDICATE_NORMAL 1 -#define BRW_PREDICATE_ALIGN1_ANYV 2 -#define BRW_PREDICATE_ALIGN1_ALLV 3 -#define BRW_PREDICATE_ALIGN1_ANY2H 4 -#define BRW_PREDICATE_ALIGN1_ALL2H 5 -#define BRW_PREDICATE_ALIGN1_ANY4H 6 -#define BRW_PREDICATE_ALIGN1_ALL4H 7 -#define BRW_PREDICATE_ALIGN1_ANY8H 8 -#define BRW_PREDICATE_ALIGN1_ALL8H 9 -#define BRW_PREDICATE_ALIGN1_ANY16H 10 -#define BRW_PREDICATE_ALIGN1_ALL16H 11 -#define BRW_PREDICATE_ALIGN16_REPLICATE_X 2 -#define BRW_PREDICATE_ALIGN16_REPLICATE_Y 3 -#define BRW_PREDICATE_ALIGN16_REPLICATE_Z 4 -#define BRW_PREDICATE_ALIGN16_REPLICATE_W 5 -#define BRW_PREDICATE_ALIGN16_ANY4H 6 -#define BRW_PREDICATE_ALIGN16_ALL4H 7 - -#define BRW_ARCHITECTURE_REGISTER_FILE 0 -#define BRW_GENERAL_REGISTER_FILE 1 -#define BRW_MESSAGE_REGISTER_FILE 2 -#define BRW_IMMEDIATE_VALUE 3 - -#define BRW_REGISTER_TYPE_UD 0 -#define BRW_REGISTER_TYPE_D 1 -#define BRW_REGISTER_TYPE_UW 2 -#define BRW_REGISTER_TYPE_W 3 -#define BRW_REGISTER_TYPE_UB 4 -#define BRW_REGISTER_TYPE_B 5 -#define BRW_REGISTER_TYPE_VF 5 /* packed float vector, immediates only? */ -#define BRW_REGISTER_TYPE_HF 6 -#define BRW_REGISTER_TYPE_V 6 /* packed int vector, immediates only, uword dest only */ -#define BRW_REGISTER_TYPE_F 7 - -#define BRW_ARF_NULL 0x00 -#define BRW_ARF_ADDRESS 0x10 -#define BRW_ARF_ACCUMULATOR 0x20 -#define BRW_ARF_FLAG 0x30 -#define BRW_ARF_MASK 0x40 -#define BRW_ARF_MASK_STACK 0x50 -#define BRW_ARF_MASK_STACK_DEPTH 0x60 -#define BRW_ARF_STATE 0x70 -#define BRW_ARF_CONTROL 0x80 -#define BRW_ARF_NOTIFICATION_COUNT 0x90 -#define BRW_ARF_IP 0xA0 - -#define BRW_AMASK 0 -#define BRW_IMASK 1 -#define BRW_LMASK 2 -#define BRW_CMASK 3 - - - -#define BRW_THREAD_NORMAL 0 -#define BRW_THREAD_ATOMIC 1 -#define BRW_THREAD_SWITCH 2 - -#define BRW_VERTICAL_STRIDE_0 0 -#define BRW_VERTICAL_STRIDE_1 1 -#define BRW_VERTICAL_STRIDE_2 2 -#define BRW_VERTICAL_STRIDE_4 3 -#define BRW_VERTICAL_STRIDE_8 4 -#define BRW_VERTICAL_STRIDE_16 5 -#define BRW_VERTICAL_STRIDE_32 6 -#define BRW_VERTICAL_STRIDE_64 7 -#define BRW_VERTICAL_STRIDE_128 8 -#define BRW_VERTICAL_STRIDE_256 9 -#define BRW_VERTICAL_STRIDE_ONE_DIMENSIONAL 0xF - -#define BRW_WIDTH_1 0 -#define BRW_WIDTH_2 1 -#define BRW_WIDTH_4 2 -#define BRW_WIDTH_8 3 -#define BRW_WIDTH_16 4 - -#define BRW_STATELESS_BUFFER_BOUNDARY_1K 0 -#define BRW_STATELESS_BUFFER_BOUNDARY_2K 1 -#define BRW_STATELESS_BUFFER_BOUNDARY_4K 2 -#define BRW_STATELESS_BUFFER_BOUNDARY_8K 3 -#define BRW_STATELESS_BUFFER_BOUNDARY_16K 4 -#define BRW_STATELESS_BUFFER_BOUNDARY_32K 5 -#define BRW_STATELESS_BUFFER_BOUNDARY_64K 6 -#define BRW_STATELESS_BUFFER_BOUNDARY_128K 7 -#define BRW_STATELESS_BUFFER_BOUNDARY_256K 8 -#define BRW_STATELESS_BUFFER_BOUNDARY_512K 9 -#define BRW_STATELESS_BUFFER_BOUNDARY_1M 10 -#define BRW_STATELESS_BUFFER_BOUNDARY_2M 11 - -#define BRW_POLYGON_FACING_FRONT 0 -#define BRW_POLYGON_FACING_BACK 1 - -#define BRW_MESSAGE_TARGET_NULL 0 -#define BRW_MESSAGE_TARGET_MATH 1 -#define BRW_MESSAGE_TARGET_SAMPLER 2 -#define BRW_MESSAGE_TARGET_GATEWAY 3 -#define BRW_MESSAGE_TARGET_DATAPORT_READ 4 -#define BRW_MESSAGE_TARGET_DATAPORT_WRITE 5 -#define BRW_MESSAGE_TARGET_URB 6 -#define BRW_MESSAGE_TARGET_THREAD_SPAWNER 7 - -#define BRW_SAMPLER_RETURN_FORMAT_FLOAT32 0 -#define BRW_SAMPLER_RETURN_FORMAT_UINT32 2 -#define BRW_SAMPLER_RETURN_FORMAT_SINT32 3 - -#define BRW_SAMPLER_MESSAGE_SIMD8_SAMPLE 0 -#define BRW_SAMPLER_MESSAGE_SIMD16_SAMPLE 0 -#define BRW_SAMPLER_MESSAGE_SIMD16_SAMPLE_BIAS 0 -#define BRW_SAMPLER_MESSAGE_SIMD8_KILLPIX 1 -#define BRW_SAMPLER_MESSAGE_SIMD4X2_SAMPLE_LOD 1 -#define BRW_SAMPLER_MESSAGE_SIMD16_SAMPLE_LOD 1 -#define BRW_SAMPLER_MESSAGE_SIMD4X2_SAMPLE_GRADIENTS 2 -#define BRW_SAMPLER_MESSAGE_SIMD8_SAMPLE_GRADIENTS 2 -#define BRW_SAMPLER_MESSAGE_SIMD4X2_SAMPLE_COMPARE 0 -#define BRW_SAMPLER_MESSAGE_SIMD16_SAMPLE_COMPARE 2 -#define BRW_SAMPLER_MESSAGE_SIMD4X2_RESINFO 2 -#define BRW_SAMPLER_MESSAGE_SIMD8_RESINFO 2 -#define BRW_SAMPLER_MESSAGE_SIMD16_RESINFO 2 -#define BRW_SAMPLER_MESSAGE_SIMD4X2_LD 3 -#define BRW_SAMPLER_MESSAGE_SIMD8_LD 3 -#define BRW_SAMPLER_MESSAGE_SIMD16_LD 3 - -#define BRW_DATAPORT_OWORD_BLOCK_1_OWORDLOW 0 -#define BRW_DATAPORT_OWORD_BLOCK_1_OWORDHIGH 1 -#define BRW_DATAPORT_OWORD_BLOCK_2_OWORDS 2 -#define BRW_DATAPORT_OWORD_BLOCK_4_OWORDS 3 -#define BRW_DATAPORT_OWORD_BLOCK_8_OWORDS 4 - -#define BRW_DATAPORT_OWORD_DUAL_BLOCK_1OWORD 0 -#define BRW_DATAPORT_OWORD_DUAL_BLOCK_4OWORDS 2 - -#define BRW_DATAPORT_DWORD_SCATTERED_BLOCK_8DWORDS 2 -#define BRW_DATAPORT_DWORD_SCATTERED_BLOCK_16DWORDS 3 - -#define BRW_DATAPORT_READ_MESSAGE_OWORD_BLOCK_READ 0 -#define BRW_DATAPORT_READ_MESSAGE_OWORD_DUAL_BLOCK_READ 1 -#define BRW_DATAPORT_READ_MESSAGE_DWORD_BLOCK_READ 2 -#define BRW_DATAPORT_READ_MESSAGE_DWORD_SCATTERED_READ 3 - -#define BRW_DATAPORT_READ_TARGET_DATA_CACHE 0 -#define BRW_DATAPORT_READ_TARGET_RENDER_CACHE 1 -#define BRW_DATAPORT_READ_TARGET_SAMPLER_CACHE 2 - -#define BRW_DATAPORT_RENDER_TARGET_WRITE_SIMD16_SINGLE_SOURCE 0 -#define BRW_DATAPORT_RENDER_TARGET_WRITE_SIMD16_SINGLE_SOURCE_REPLICATED 1 -#define BRW_DATAPORT_RENDER_TARGET_WRITE_SIMD8_DUAL_SOURCE_SUBSPAN01 2 -#define BRW_DATAPORT_RENDER_TARGET_WRITE_SIMD8_DUAL_SOURCE_SUBSPAN23 3 -#define BRW_DATAPORT_RENDER_TARGET_WRITE_SIMD8_SINGLE_SOURCE_SUBSPAN01 4 - -#define BRW_DATAPORT_WRITE_MESSAGE_OWORD_BLOCK_WRITE 0 -#define BRW_DATAPORT_WRITE_MESSAGE_OWORD_DUAL_BLOCK_WRITE 1 -#define BRW_DATAPORT_WRITE_MESSAGE_DWORD_BLOCK_WRITE 2 -#define BRW_DATAPORT_WRITE_MESSAGE_DWORD_SCATTERED_WRITE 3 -#define BRW_DATAPORT_WRITE_MESSAGE_RENDER_TARGET_WRITE 4 -#define BRW_DATAPORT_WRITE_MESSAGE_STREAMED_VERTEX_BUFFER_WRITE 5 -#define BRW_DATAPORT_WRITE_MESSAGE_FLUSH_RENDER_CACHE 7 - -#define BRW_MATH_FUNCTION_INV 1 -#define BRW_MATH_FUNCTION_LOG 2 -#define BRW_MATH_FUNCTION_EXP 3 -#define BRW_MATH_FUNCTION_SQRT 4 -#define BRW_MATH_FUNCTION_RSQ 5 -#define BRW_MATH_FUNCTION_SIN 6 /* was 7 */ -#define BRW_MATH_FUNCTION_COS 7 /* was 8 */ -#define BRW_MATH_FUNCTION_SINCOS 8 /* was 6 */ -#define BRW_MATH_FUNCTION_TAN 9 -#define BRW_MATH_FUNCTION_POW 10 -#define BRW_MATH_FUNCTION_INT_DIV_QUOTIENT_AND_REMAINDER 11 -#define BRW_MATH_FUNCTION_INT_DIV_QUOTIENT 12 -#define BRW_MATH_FUNCTION_INT_DIV_REMAINDER 13 - -#define BRW_MATH_INTEGER_UNSIGNED 0 -#define BRW_MATH_INTEGER_SIGNED 1 - -#define BRW_MATH_PRECISION_FULL 0 -#define BRW_MATH_PRECISION_PARTIAL 1 - -#define BRW_MATH_SATURATE_NONE 0 -#define BRW_MATH_SATURATE_SATURATE 1 - -#define BRW_MATH_DATA_VECTOR 0 -#define BRW_MATH_DATA_SCALAR 1 - -#define BRW_URB_OPCODE_WRITE 0 - -#define BRW_URB_SWIZZLE_NONE 0 -#define BRW_URB_SWIZZLE_INTERLEAVE 1 -#define BRW_URB_SWIZZLE_TRANSPOSE 2 - -#define BRW_SCRATCH_SPACE_SIZE_1K 0 -#define BRW_SCRATCH_SPACE_SIZE_2K 1 -#define BRW_SCRATCH_SPACE_SIZE_4K 2 -#define BRW_SCRATCH_SPACE_SIZE_8K 3 -#define BRW_SCRATCH_SPACE_SIZE_16K 4 -#define BRW_SCRATCH_SPACE_SIZE_32K 5 -#define BRW_SCRATCH_SPACE_SIZE_64K 6 -#define BRW_SCRATCH_SPACE_SIZE_128K 7 -#define BRW_SCRATCH_SPACE_SIZE_256K 8 -#define BRW_SCRATCH_SPACE_SIZE_512K 9 -#define BRW_SCRATCH_SPACE_SIZE_1M 10 -#define BRW_SCRATCH_SPACE_SIZE_2M 11 - - - - -#define CMD_URB_FENCE 0x6000 -#define CMD_CONST_BUFFER_STATE 0x6001 -#define CMD_CONST_BUFFER 0x6002 - -#define CMD_STATE_BASE_ADDRESS 0x6101 -#define CMD_STATE_INSN_POINTER 0x6102 -#define CMD_PIPELINE_SELECT 0x6104 - -#define CMD_PIPELINED_STATE_POINTERS 0x7800 -#define CMD_BINDING_TABLE_PTRS 0x7801 -#define CMD_VERTEX_BUFFER 0x7808 -#define CMD_VERTEX_ELEMENT 0x7809 -#define CMD_INDEX_BUFFER 0x780a -#define CMD_VF_STATISTICS 0x780b - -#define CMD_DRAW_RECT 0x7900 -#define CMD_BLEND_CONSTANT_COLOR 0x7901 -#define CMD_CHROMA_KEY 0x7904 -#define CMD_DEPTH_BUFFER 0x7905 -#define CMD_POLY_STIPPLE_OFFSET 0x7906 -#define CMD_POLY_STIPPLE_PATTERN 0x7907 -#define CMD_LINE_STIPPLE_PATTERN 0x7908 -#define CMD_GLOBAL_DEPTH_OFFSET_CLAMP 0x7908 - -#define CMD_PIPE_CONTROL 0x7a00 - -#define CMD_3D_PRIM 0x7b00 - -#define CMD_MI_FLUSH 0x0200 - - -/* Various values from the R0 vertex header: - */ -#define R02_PRIM_END 0x1 -#define R02_PRIM_START 0x2 - -/* media pipeline */ - -#define BRW_VFE_MODE_GENERIC 0x0 -#define BRW_VFE_MODE_VLD_MPEG2 0x1 -#define BRW_VFE_MODE_IS 0x2 -#define BRW_VFE_MODE_AVC_MC 0x4 -#define BRW_VFE_MODE_AVC_IT 0x7 -#define BRW_VFE_MODE_VC1_IT 0xB - -#define BRW_VFE_DEBUG_COUNTER_FREE 0 -#define BRW_VFE_DEBUG_COUNTER_FROZEN 1 -#define BRW_VFE_DEBUG_COUNTER_ONCE 2 -#define BRW_VFE_DEBUG_COUNTER_ALWAYS 3 - -/* VLD_STATE */ -#define BRW_MPEG_TOP_FIELD 1 -#define BRW_MPEG_BOTTOM_FIELD 2 -#define BRW_MPEG_FRAME 3 -#define BRW_MPEG_QSCALE_LINEAR 0 -#define BRW_MPEG_QSCALE_NONLINEAR 1 -#define BRW_MPEG_ZIGZAG_SCAN 0 -#define BRW_MPEG_ALTER_VERTICAL_SCAN 1 -#define BRW_MPEG_I_PICTURE 1 -#define BRW_MPEG_P_PICTURE 2 -#define BRW_MPEG_B_PICTURE 3 - -#endif diff --git a/gfx/cairo/cairo/src/drm/cairo-drm-intel-brw-eu-emit.c b/gfx/cairo/cairo/src/drm/cairo-drm-intel-brw-eu-emit.c deleted file mode 100644 index f27b238048..0000000000 --- a/gfx/cairo/cairo/src/drm/cairo-drm-intel-brw-eu-emit.c +++ /dev/null @@ -1,1089 +0,0 @@ -/* - Copyright (C) Intel Corp. 2006. All Rights Reserved. - Intel funded Tungsten Graphics (http://www.tungstengraphics.com) to - develop this 3D driver. - - Permission is hereby granted, free of charge, to any person obtaining - a copy of this software and associated documentation files (the - "Software"), to deal in the Software without restriction, including - without limitation the rights to use, copy, modify, merge, publish, - distribute, sublicense, and/or sell copies of the Software, and to - permit persons to whom the Software is furnished to do so, subject to - the following conditions: - - The above copyright notice and this permission notice (including the - next paragraph) shall be included in all copies or substantial - portions of the Software. - - THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, - EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. - IN NO EVENT SHALL THE COPYRIGHT OWNER(S) AND/OR ITS SUPPLIERS BE - LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION - OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION - WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - - **********************************************************************/ -/* - * Authors: - * Keith Whitwell <keith@tungstengraphics.com> - */ - -#include "cairoint.h" -#include "cairo-drm-intel-brw-eu.h" - -#include <string.h> - -/*********************************************************************** - * Internal helper for constructing instructions - */ - -static void guess_execution_size( struct brw_instruction *insn, - struct brw_reg reg ) -{ - if (reg.width == BRW_WIDTH_8 && - insn->header.compression_control == BRW_COMPRESSION_COMPRESSED) - insn->header.execution_size = BRW_EXECUTE_16; - else - insn->header.execution_size = reg.width; /* note - definitions are compatible */ -} - - -void -brw_instruction_set_destination (struct brw_instruction *insn, - struct brw_reg dest) -{ - insn->bits1.da1.dest_reg_file = dest.file; - insn->bits1.da1.dest_reg_type = dest.type; - insn->bits1.da1.dest_address_mode = dest.address_mode; - - if (dest.address_mode == BRW_ADDRESS_DIRECT) { - insn->bits1.da1.dest_reg_nr = dest.nr; - - if (insn->header.access_mode == BRW_ALIGN_1) { - insn->bits1.da1.dest_subreg_nr = dest.subnr; - if (dest.hstride == BRW_HORIZONTAL_STRIDE_0) - dest.hstride = BRW_HORIZONTAL_STRIDE_1; - insn->bits1.da1.dest_horiz_stride = dest.hstride; - } else { - insn->bits1.da16.dest_subreg_nr = dest.subnr / 16; - insn->bits1.da16.dest_writemask = dest.dw1.bits.writemask; - } - } else { - insn->bits1.ia1.dest_subreg_nr = dest.subnr; - - /* These are different sizes in align1 vs align16: - */ - if (insn->header.access_mode == BRW_ALIGN_1) { - insn->bits1.ia1.dest_indirect_offset = dest.dw1.bits.indirect_offset; - if (dest.hstride == BRW_HORIZONTAL_STRIDE_0) - dest.hstride = BRW_HORIZONTAL_STRIDE_1; - insn->bits1.ia1.dest_horiz_stride = dest.hstride; - } else { - insn->bits1.ia16.dest_indirect_offset = dest.dw1.bits.indirect_offset; - } - } - - /* NEW: Set the execution size based on dest.width and - * insn->compression_control: - */ - guess_execution_size(insn, dest); -} - -void -brw_instruction_set_source0 (struct brw_instruction *insn, - struct brw_reg reg) -{ - assert(reg.file != BRW_MESSAGE_REGISTER_FILE); - - insn->bits1.da1.src0_reg_file = reg.file; - insn->bits1.da1.src0_reg_type = reg.type; - insn->bits2.da1.src0_abs = reg.abs; - insn->bits2.da1.src0_negate = reg.negate; - insn->bits2.da1.src0_address_mode = reg.address_mode; - - if (reg.file == BRW_IMMEDIATE_VALUE) { - insn->bits3.ud = reg.dw1.ud; - - /* Required to set some fields in src1 as well: - */ - insn->bits1.da1.src1_reg_file = 0; /* arf */ - insn->bits1.da1.src1_reg_type = reg.type; - } else { - if (reg.address_mode == BRW_ADDRESS_DIRECT) { - if (insn->header.access_mode == BRW_ALIGN_1) { - insn->bits2.da1.src0_subreg_nr = reg.subnr; - insn->bits2.da1.src0_reg_nr = reg.nr; - } else { - insn->bits2.da16.src0_subreg_nr = reg.subnr / 16; - insn->bits2.da16.src0_reg_nr = reg.nr; - } - } else { - insn->bits2.ia1.src0_subreg_nr = reg.subnr; - - if (insn->header.access_mode == BRW_ALIGN_1) { - insn->bits2.ia1.src0_indirect_offset = reg.dw1.bits.indirect_offset; - } else { - insn->bits2.ia16.src0_subreg_nr = reg.dw1.bits.indirect_offset; - } - } - - if (insn->header.access_mode == BRW_ALIGN_1) { - if (reg.width == BRW_WIDTH_1 && - insn->header.execution_size == BRW_EXECUTE_1) { - insn->bits2.da1.src0_horiz_stride = BRW_HORIZONTAL_STRIDE_0; - insn->bits2.da1.src0_width = BRW_WIDTH_1; - insn->bits2.da1.src0_vert_stride = BRW_VERTICAL_STRIDE_0; - } else { - insn->bits2.da1.src0_horiz_stride = reg.hstride; - insn->bits2.da1.src0_width = reg.width; - insn->bits2.da1.src0_vert_stride = reg.vstride; - } - } else { - insn->bits2.da16.src0_swz_x = BRW_GET_SWZ(reg.dw1.bits.swizzle, BRW_CHANNEL_X); - insn->bits2.da16.src0_swz_y = BRW_GET_SWZ(reg.dw1.bits.swizzle, BRW_CHANNEL_Y); - insn->bits2.da16.src0_swz_z = BRW_GET_SWZ(reg.dw1.bits.swizzle, BRW_CHANNEL_Z); - insn->bits2.da16.src0_swz_w = BRW_GET_SWZ(reg.dw1.bits.swizzle, BRW_CHANNEL_W); - - /* This is an oddity of the fact we're using the same - * descriptions for registers in align_16 as align_1: - */ - if (reg.vstride == BRW_VERTICAL_STRIDE_8) - insn->bits2.da16.src0_vert_stride = BRW_VERTICAL_STRIDE_4; - else - insn->bits2.da16.src0_vert_stride = reg.vstride; - } - } -} - - -void brw_set_src1( struct brw_instruction *insn, - struct brw_reg reg ) -{ - assert(reg.file != BRW_MESSAGE_REGISTER_FILE); - - insn->bits1.da1.src1_reg_file = reg.file; - insn->bits1.da1.src1_reg_type = reg.type; - insn->bits3.da1.src1_abs = reg.abs; - insn->bits3.da1.src1_negate = reg.negate; - - /* Only src1 can be immediate in two-argument instructions. - */ - assert(insn->bits1.da1.src0_reg_file != BRW_IMMEDIATE_VALUE); - - if (reg.file == BRW_IMMEDIATE_VALUE) { - insn->bits3.ud = reg.dw1.ud; - } - else { - /* This is a hardware restriction, which may or may not be lifted - * in the future: - */ - assert (reg.address_mode == BRW_ADDRESS_DIRECT); - //assert (reg.file == BRW_GENERAL_REGISTER_FILE); - - if (insn->header.access_mode == BRW_ALIGN_1) { - insn->bits3.da1.src1_subreg_nr = reg.subnr; - insn->bits3.da1.src1_reg_nr = reg.nr; - } - else { - insn->bits3.da16.src1_subreg_nr = reg.subnr / 16; - insn->bits3.da16.src1_reg_nr = reg.nr; - } - - if (insn->header.access_mode == BRW_ALIGN_1) { - if (reg.width == BRW_WIDTH_1 && - insn->header.execution_size == BRW_EXECUTE_1) { - insn->bits3.da1.src1_horiz_stride = BRW_HORIZONTAL_STRIDE_0; - insn->bits3.da1.src1_width = BRW_WIDTH_1; - insn->bits3.da1.src1_vert_stride = BRW_VERTICAL_STRIDE_0; - } - else { - insn->bits3.da1.src1_horiz_stride = reg.hstride; - insn->bits3.da1.src1_width = reg.width; - insn->bits3.da1.src1_vert_stride = reg.vstride; - } - } - else { - insn->bits3.da16.src1_swz_x = BRW_GET_SWZ(reg.dw1.bits.swizzle, BRW_CHANNEL_X); - insn->bits3.da16.src1_swz_y = BRW_GET_SWZ(reg.dw1.bits.swizzle, BRW_CHANNEL_Y); - insn->bits3.da16.src1_swz_z = BRW_GET_SWZ(reg.dw1.bits.swizzle, BRW_CHANNEL_Z); - insn->bits3.da16.src1_swz_w = BRW_GET_SWZ(reg.dw1.bits.swizzle, BRW_CHANNEL_W); - - /* This is an oddity of the fact we're using the same - * descriptions for registers in align_16 as align_1: - */ - if (reg.vstride == BRW_VERTICAL_STRIDE_8) - insn->bits3.da16.src1_vert_stride = BRW_VERTICAL_STRIDE_4; - else - insn->bits3.da16.src1_vert_stride = reg.vstride; - } - } -} - - - -static void brw_set_math_message( struct brw_instruction *insn, - uint32_t msg_length, - uint32_t response_length, - uint32_t function, - uint32_t integer_type, - int low_precision, - int saturate, - uint32_t dataType ) -{ - brw_set_src1 (insn, brw_imm_d (0)); - - insn->bits3.math.function = function; - insn->bits3.math.int_type = integer_type; - insn->bits3.math.precision = low_precision; - insn->bits3.math.saturate = saturate; - insn->bits3.math.data_type = dataType; - insn->bits3.math.response_length = response_length; - insn->bits3.math.msg_length = msg_length; - insn->bits3.math.msg_target = BRW_MESSAGE_TARGET_MATH; - insn->bits3.math.end_of_thread = 0; -} - -static void brw_set_urb_message( struct brw_instruction *insn, - int allocate, - int used, - uint32_t msg_length, - uint32_t response_length, - int end_of_thread, - int complete, - uint32_t offset, - uint32_t swizzle_control ) -{ - brw_set_src1 (insn, brw_imm_d (0)); - - insn->bits3.urb.opcode = 0; /* ? */ - insn->bits3.urb.offset = offset; - insn->bits3.urb.swizzle_control = swizzle_control; - insn->bits3.urb.allocate = allocate; - insn->bits3.urb.used = used; /* ? */ - insn->bits3.urb.complete = complete; - insn->bits3.urb.response_length = response_length; - insn->bits3.urb.msg_length = msg_length; - insn->bits3.urb.msg_target = BRW_MESSAGE_TARGET_URB; - insn->bits3.urb.end_of_thread = end_of_thread; -} - -void -brw_instruction_set_dp_write_message (struct brw_instruction *insn, - uint32_t binding_table_index, - uint32_t msg_control, - uint32_t msg_type, - uint32_t msg_length, - uint32_t pixel_scoreboard_clear, - uint32_t response_length, - uint32_t end_of_thread) -{ - brw_set_src1 (insn, brw_imm_d (0)); - - insn->bits3.dp_write.binding_table_index = binding_table_index; - insn->bits3.dp_write.msg_control = msg_control; - insn->bits3.dp_write.pixel_scoreboard_clear = pixel_scoreboard_clear; - insn->bits3.dp_write.msg_type = msg_type; - insn->bits3.dp_write.send_commit_msg = 0; - insn->bits3.dp_write.response_length = response_length; - insn->bits3.dp_write.msg_length = msg_length; - insn->bits3.dp_write.msg_target = BRW_MESSAGE_TARGET_DATAPORT_WRITE; - insn->bits3.urb.end_of_thread = end_of_thread; -} - -static void brw_set_dp_read_message( struct brw_instruction *insn, - uint32_t binding_table_index, - uint32_t msg_control, - uint32_t msg_type, - uint32_t target_cache, - uint32_t msg_length, - uint32_t response_length, - uint32_t end_of_thread ) -{ - brw_set_src1 (insn, brw_imm_d (0)); - - insn->bits3.dp_read.binding_table_index = binding_table_index; - insn->bits3.dp_read.msg_control = msg_control; - insn->bits3.dp_read.msg_type = msg_type; - insn->bits3.dp_read.target_cache = target_cache; - insn->bits3.dp_read.response_length = response_length; - insn->bits3.dp_read.msg_length = msg_length; - insn->bits3.dp_read.msg_target = BRW_MESSAGE_TARGET_DATAPORT_READ; - insn->bits3.dp_read.end_of_thread = end_of_thread; -} - -static void -brw_set_sampler_message (struct brw_instruction *insn, - cairo_bool_t is_g4x, - uint32_t binding_table_index, - uint32_t sampler, - uint32_t msg_type, - uint32_t response_length, - uint32_t msg_length, - cairo_bool_t eot) -{ - brw_set_src1 (insn, brw_imm_d (0)); - - if (is_g4x) { - /* XXX presume the driver is sane! */ - insn->bits3.sampler_g4x.binding_table_index = binding_table_index; - insn->bits3.sampler_g4x.sampler = sampler; - insn->bits3.sampler_g4x.msg_type = msg_type; - insn->bits3.sampler_g4x.response_length = response_length; - insn->bits3.sampler_g4x.msg_length = msg_length; - insn->bits3.sampler_g4x.end_of_thread = eot; - insn->bits3.sampler_g4x.msg_target = BRW_MESSAGE_TARGET_SAMPLER; - } else { - insn->bits3.sampler.binding_table_index = binding_table_index; - insn->bits3.sampler.sampler = sampler; - insn->bits3.sampler.msg_type = msg_type; - insn->bits3.sampler.return_format = BRW_SAMPLER_RETURN_FORMAT_FLOAT32; - insn->bits3.sampler.response_length = response_length; - insn->bits3.sampler.msg_length = msg_length; - insn->bits3.sampler.end_of_thread = eot; - insn->bits3.sampler.msg_target = BRW_MESSAGE_TARGET_SAMPLER; - } -} - -struct brw_instruction * -brw_next_instruction (struct brw_compile *p, - uint32_t opcode) -{ - struct brw_instruction *insn; - - assert(p->nr_insn + 1 < BRW_EU_MAX_INSN); - - insn = &p->store[p->nr_insn++]; - memcpy(insn, p->current, sizeof(*insn)); - - /* Reset this one-shot flag: */ - if (p->current->header.destreg__conditonalmod) { - p->current->header.destreg__conditonalmod = 0; - p->current->header.predicate_control = BRW_PREDICATE_NORMAL; - } - - insn->header.opcode = opcode; - return insn; -} - -static struct brw_instruction *brw_alu1( struct brw_compile *p, - uint32_t opcode, - struct brw_reg dest, - struct brw_reg src ) -{ - struct brw_instruction *insn = brw_next_instruction(p, opcode); - brw_instruction_set_destination(insn, dest); - brw_instruction_set_source0(insn, src); - return insn; -} - -static struct brw_instruction *brw_alu2(struct brw_compile *p, - uint32_t opcode, - struct brw_reg dest, - struct brw_reg src0, - struct brw_reg src1 ) -{ - struct brw_instruction *insn = brw_next_instruction(p, opcode); - brw_instruction_set_destination(insn, dest); - brw_instruction_set_source0(insn, src0); - brw_set_src1(insn, src1); - return insn; -} - - -/*********************************************************************** - * Convenience routines. - */ -#define ALU1(OP) \ - struct brw_instruction *brw_##OP(struct brw_compile *p, \ - struct brw_reg dest, \ - struct brw_reg src0) \ -{ \ - return brw_alu1(p, BRW_OPCODE_##OP, dest, src0); \ -} - -#define ALU2(OP) \ - struct brw_instruction *brw_##OP(struct brw_compile *p, \ - struct brw_reg dest, \ - struct brw_reg src0, \ - struct brw_reg src1) \ -{ \ - return brw_alu2(p, BRW_OPCODE_##OP, dest, src0, src1); \ -} - - - ALU1(MOV) - ALU2(SEL) - ALU1(NOT) - ALU2(AND) - ALU2(OR) - ALU2(XOR) - ALU2(SHR) - ALU2(SHL) - ALU2(RSR) - ALU2(RSL) - ALU2(ASR) - ALU2(ADD) - ALU2(MUL) - ALU1(FRC) - ALU1(RNDD) - ALU1(RNDZ) - ALU2(MAC) - ALU2(MACH) - ALU1(LZD) - ALU2(DP4) - ALU2(DPH) - ALU2(DP3) - ALU2(DP2) -ALU2(LINE) - - - - -void brw_NOP(struct brw_compile *p) -{ - struct brw_instruction *insn = brw_next_instruction(p, BRW_OPCODE_NOP); - brw_instruction_set_destination(insn, retype(brw_vec4_grf(0,0), BRW_REGISTER_TYPE_UD)); - brw_instruction_set_source0(insn, retype(brw_vec4_grf(0,0), BRW_REGISTER_TYPE_UD)); - brw_set_src1(insn, brw_imm_ud(0x0)); -} - - - - - -/*********************************************************************** - * Comparisons, if/else/endif - */ - -struct brw_instruction *brw_JMPI(struct brw_compile *p, - struct brw_reg dest, - struct brw_reg src0, - struct brw_reg src1) -{ - struct brw_instruction *insn = brw_alu2(p, BRW_OPCODE_JMPI, dest, src0, src1); - - p->current->header.predicate_control = BRW_PREDICATE_NONE; - - return insn; -} - -/* EU takes the value from the flag register and pushes it onto some - * sort of a stack (presumably merging with any flag value already on - * the stack). Within an if block, the flags at the top of the stack - * control execution on each channel of the unit, eg. on each of the - * 16 pixel values in our wm programs. - * - * When the matching 'else' instruction is reached (presumably by - * countdown of the instruction count patched in by our ELSE/ENDIF - * functions), the relevant flags are inverted. - * - * When the matching 'endif' instruction is reached, the flags are - * popped off. If the stack is now empty, normal execution resumes. - * - * No attempt is made to deal with stack overflow (14 elements?). - */ -struct brw_instruction *brw_IF(struct brw_compile *p, uint32_t execute_size) -{ - struct brw_instruction *insn; - - if (p->single_program_flow) { - assert(execute_size == BRW_EXECUTE_1); - - insn = brw_next_instruction(p, BRW_OPCODE_ADD); - insn->header.predicate_inverse = 1; - } else { - insn = brw_next_instruction(p, BRW_OPCODE_IF); - } - - /* Override the defaults for this instruction: - */ - brw_instruction_set_destination (insn, brw_ip_reg ()); - brw_instruction_set_source0 (insn, brw_ip_reg ()); - brw_set_src1 (insn, brw_imm_d (0)); - - insn->header.execution_size = execute_size; - insn->header.compression_control = BRW_COMPRESSION_NONE; - insn->header.predicate_control = BRW_PREDICATE_NORMAL; - insn->header.mask_control = BRW_MASK_ENABLE; - if (!p->single_program_flow) - insn->header.thread_control = BRW_THREAD_SWITCH; - - p->current->header.predicate_control = BRW_PREDICATE_NONE; - - return insn; -} - - -struct brw_instruction *brw_ELSE(struct brw_compile *p, - struct brw_instruction *if_insn) -{ - struct brw_instruction *insn; - - if (p->single_program_flow) { - insn = brw_next_instruction(p, BRW_OPCODE_ADD); - } else { - insn = brw_next_instruction(p, BRW_OPCODE_ELSE); - } - - brw_instruction_set_destination (insn, brw_ip_reg ()); - brw_instruction_set_source0 (insn, brw_ip_reg ()); - brw_set_src1 (insn, brw_imm_d (0)); - - insn->header.compression_control = BRW_COMPRESSION_NONE; - insn->header.execution_size = if_insn->header.execution_size; - insn->header.mask_control = BRW_MASK_ENABLE; - if (!p->single_program_flow) - insn->header.thread_control = BRW_THREAD_SWITCH; - - /* Patch the if instruction to point at this instruction. - */ - if (p->single_program_flow) { - assert(if_insn->header.opcode == BRW_OPCODE_ADD); - - if_insn->bits3.ud = (insn - if_insn + 1) * 16; - } else { - assert(if_insn->header.opcode == BRW_OPCODE_IF); - - if_insn->bits3.if_else.jump_count = insn - if_insn; - if_insn->bits3.if_else.pop_count = 1; - if_insn->bits3.if_else.pad0 = 0; - } - - return insn; -} - -void brw_ENDIF(struct brw_compile *p, - struct brw_instruction *patch_insn) -{ - if (p->single_program_flow) { - /* In single program flow mode, there's no need to execute an ENDIF, - * since we don't need to do any stack operations, and if we're executing - * currently, we want to just continue executing. - */ - struct brw_instruction *next = &p->store[p->nr_insn]; - - assert(patch_insn->header.opcode == BRW_OPCODE_ADD); - - patch_insn->bits3.ud = (next - patch_insn) * 16; - } else { - struct brw_instruction *insn = brw_next_instruction(p, BRW_OPCODE_ENDIF); - - brw_instruction_set_destination(insn, retype(brw_vec4_grf(0,0), BRW_REGISTER_TYPE_UD)); - brw_instruction_set_source0(insn, retype(brw_vec4_grf(0,0), BRW_REGISTER_TYPE_UD)); - brw_set_src1 (insn, brw_imm_d (0)); - - insn->header.compression_control = BRW_COMPRESSION_NONE; - insn->header.execution_size = patch_insn->header.execution_size; - insn->header.mask_control = BRW_MASK_ENABLE; - insn->header.thread_control = BRW_THREAD_SWITCH; - - assert(patch_insn->bits3.if_else.jump_count == 0); - - /* Patch the if or else instructions to point at this or the next - * instruction respectively. - */ - if (patch_insn->header.opcode == BRW_OPCODE_IF) { - /* Automagically turn it into an IFF: - */ - patch_insn->header.opcode = BRW_OPCODE_IFF; - patch_insn->bits3.if_else.jump_count = insn - patch_insn + 1; - patch_insn->bits3.if_else.pop_count = 0; - patch_insn->bits3.if_else.pad0 = 0; - } else if (patch_insn->header.opcode == BRW_OPCODE_ELSE) { - patch_insn->bits3.if_else.jump_count = insn - patch_insn + 1; - patch_insn->bits3.if_else.pop_count = 1; - patch_insn->bits3.if_else.pad0 = 0; - } else { - assert(0); - } - - /* Also pop item off the stack in the endif instruction: - */ - insn->bits3.if_else.jump_count = 0; - insn->bits3.if_else.pop_count = 1; - insn->bits3.if_else.pad0 = 0; - } -} - -struct brw_instruction *brw_BREAK(struct brw_compile *p) -{ - struct brw_instruction *insn; - insn = brw_next_instruction(p, BRW_OPCODE_BREAK); - brw_instruction_set_destination(insn, brw_ip_reg()); - brw_instruction_set_source0(insn, brw_ip_reg()); - brw_set_src1(insn, brw_imm_d (0)); - insn->header.compression_control = BRW_COMPRESSION_NONE; - insn->header.execution_size = BRW_EXECUTE_8; - /* insn->header.mask_control = BRW_MASK_DISABLE; */ - insn->bits3.if_else.pad0 = 0; - return insn; -} - -struct brw_instruction *brw_CONT(struct brw_compile *p) -{ - struct brw_instruction *insn; - insn = brw_next_instruction(p, BRW_OPCODE_CONTINUE); - brw_instruction_set_destination(insn, brw_ip_reg()); - brw_instruction_set_source0(insn, brw_ip_reg()); - brw_set_src1 (insn, brw_imm_d (0)); - insn->header.compression_control = BRW_COMPRESSION_NONE; - insn->header.execution_size = BRW_EXECUTE_8; - /* insn->header.mask_control = BRW_MASK_DISABLE; */ - insn->bits3.if_else.pad0 = 0; - return insn; -} - -/* DO/WHILE loop: -*/ -struct brw_instruction *brw_DO(struct brw_compile *p, uint32_t execute_size) -{ - if (p->single_program_flow) { - return &p->store[p->nr_insn]; - } else { - struct brw_instruction *insn = brw_next_instruction(p, BRW_OPCODE_DO); - - /* Override the defaults for this instruction: - */ - brw_instruction_set_destination(insn, brw_null_reg()); - brw_instruction_set_source0(insn, brw_null_reg()); - brw_set_src1(insn, brw_null_reg()); - - insn->header.compression_control = BRW_COMPRESSION_NONE; - insn->header.execution_size = execute_size; - insn->header.predicate_control = BRW_PREDICATE_NONE; - /* insn->header.mask_control = BRW_MASK_ENABLE; */ - /* insn->header.mask_control = BRW_MASK_DISABLE; */ - - return insn; - } -} - - - -struct brw_instruction *brw_WHILE(struct brw_compile *p, - struct brw_instruction *do_insn) -{ - struct brw_instruction *insn; - - if (p->single_program_flow) - insn = brw_next_instruction(p, BRW_OPCODE_ADD); - else - insn = brw_next_instruction(p, BRW_OPCODE_WHILE); - - brw_instruction_set_destination(insn, brw_ip_reg()); - brw_instruction_set_source0(insn, brw_ip_reg()); - brw_set_src1 (insn, brw_imm_d (0)); - - insn->header.compression_control = BRW_COMPRESSION_NONE; - - if (p->single_program_flow) { - insn->header.execution_size = BRW_EXECUTE_1; - - insn->bits3.d = (do_insn - insn) * 16; - } else { - insn->header.execution_size = do_insn->header.execution_size; - - assert(do_insn->header.opcode == BRW_OPCODE_DO); - insn->bits3.if_else.jump_count = do_insn - insn + 1; - insn->bits3.if_else.pop_count = 0; - insn->bits3.if_else.pad0 = 0; - } - - /* insn->header.mask_control = BRW_MASK_ENABLE; */ - - /* insn->header.mask_control = BRW_MASK_DISABLE; */ - p->current->header.predicate_control = BRW_PREDICATE_NONE; - return insn; -} - - -/* FORWARD JUMPS: -*/ -void brw_land_fwd_jump(struct brw_compile *p, - struct brw_instruction *jmp_insn) -{ - struct brw_instruction *landing = &p->store[p->nr_insn]; - - assert(jmp_insn->header.opcode == BRW_OPCODE_JMPI); - assert(jmp_insn->bits1.da1.src1_reg_file = BRW_IMMEDIATE_VALUE); - - jmp_insn->bits3.ud = (landing - jmp_insn) - 1; -} - - - -/* To integrate with the above, it makes sense that the comparison - * instruction should populate the flag register. It might be simpler - * just to use the flag reg for most WM tasks? - */ -void brw_CMP(struct brw_compile *p, - struct brw_reg dest, - uint32_t conditional, - struct brw_reg src0, - struct brw_reg src1) -{ - struct brw_instruction *insn = brw_next_instruction(p, BRW_OPCODE_CMP); - - insn->header.destreg__conditonalmod = conditional; - brw_instruction_set_destination(insn, dest); - brw_instruction_set_source0(insn, src0); - brw_set_src1(insn, src1); - - /* guess_execution_size(insn, src0); */ - - - /* Make it so that future instructions will use the computed flag - * value until brw_set_predicate_control_flag_value() is called - * again. - */ - if (dest.file == BRW_ARCHITECTURE_REGISTER_FILE && - dest.nr == 0) { - p->current->header.predicate_control = BRW_PREDICATE_NORMAL; - p->flag_value = 0xff; - } -} - - - -/*********************************************************************** - * Helpers for the various SEND message types: - */ - -/* Invert 8 values -*/ -void brw_math( struct brw_compile *p, - struct brw_reg dest, - uint32_t function, - uint32_t saturate, - uint32_t msg_reg_nr, - struct brw_reg src, - uint32_t data_type, - uint32_t precision ) -{ - struct brw_instruction *insn = brw_next_instruction(p, BRW_OPCODE_SEND); - uint32_t msg_length = (function == BRW_MATH_FUNCTION_POW) ? 2 : 1; - uint32_t response_length = (function == BRW_MATH_FUNCTION_SINCOS) ? 2 : 1; - - /* Example code doesn't set predicate_control for send - * instructions. - */ - insn->header.predicate_control = 0; - insn->header.destreg__conditonalmod = msg_reg_nr; - - response_length = 1; - - brw_instruction_set_destination(insn, dest); - brw_instruction_set_source0(insn, src); - brw_set_math_message(insn, - msg_length, response_length, - function, - BRW_MATH_INTEGER_UNSIGNED, - precision, - saturate, - data_type); -} - -/* Use 2 send instructions to invert 16 elements -*/ -void brw_math_16( struct brw_compile *p, - struct brw_reg dest, - uint32_t function, - uint32_t saturate, - uint32_t msg_reg_nr, - struct brw_reg src, - uint32_t precision ) -{ - struct brw_instruction *insn; - uint32_t msg_length = (function == BRW_MATH_FUNCTION_POW) ? 2 : 1; - uint32_t response_length = (function == BRW_MATH_FUNCTION_SINCOS) ? 2 : 1; - - /* First instruction: - */ - brw_push_insn_state(p); - brw_set_predicate_control_flag_value(p, 0xff); - brw_set_compression_control(p, BRW_COMPRESSION_NONE); - - insn = brw_next_instruction(p, BRW_OPCODE_SEND); - insn->header.destreg__conditonalmod = msg_reg_nr; - - brw_instruction_set_destination(insn, dest); - brw_instruction_set_source0(insn, src); - brw_set_math_message(insn, - msg_length, response_length, - function, - BRW_MATH_INTEGER_UNSIGNED, - precision, - saturate, - BRW_MATH_DATA_VECTOR); - - /* Second instruction: - */ - insn = brw_next_instruction(p, BRW_OPCODE_SEND); - insn->header.compression_control = BRW_COMPRESSION_2NDHALF; - insn->header.destreg__conditonalmod = msg_reg_nr+1; - - brw_instruction_set_destination(insn, offset(dest,1)); - brw_instruction_set_source0(insn, src); - brw_set_math_message(insn, - msg_length, response_length, - function, - BRW_MATH_INTEGER_UNSIGNED, - precision, - saturate, - BRW_MATH_DATA_VECTOR); - - brw_pop_insn_state(p); -} - - - - -void brw_dp_WRITE_16( struct brw_compile *p, - struct brw_reg src, - uint32_t msg_reg_nr, - uint32_t scratch_offset ) -{ - { - brw_push_insn_state(p); - brw_set_mask_control(p, BRW_MASK_DISABLE); - brw_set_compression_control(p, BRW_COMPRESSION_NONE); - - brw_MOV (p, - retype (brw_vec1_grf (0, 2), BRW_REGISTER_TYPE_D), - brw_imm_d (scratch_offset)); - - brw_pop_insn_state(p); - } - - { - uint32_t msg_length = 3; - struct brw_reg dest = retype(brw_null_reg(), BRW_REGISTER_TYPE_UW); - struct brw_instruction *insn = brw_next_instruction(p, BRW_OPCODE_SEND); - - insn->header.predicate_control = 0; /* XXX */ - insn->header.compression_control = BRW_COMPRESSION_NONE; - insn->header.destreg__conditonalmod = msg_reg_nr; - - brw_instruction_set_destination(insn, dest); - brw_instruction_set_source0(insn, src); - - brw_instruction_set_dp_write_message(insn, - 255, /* bti */ - BRW_DATAPORT_OWORD_BLOCK_4_OWORDS, /* msg_control */ - BRW_DATAPORT_WRITE_MESSAGE_OWORD_BLOCK_WRITE, /* msg_type */ - msg_length, - 0, /* pixel scoreboard */ - 0, /* response_length */ - 0); /* eot */ - } - -} - - -void brw_dp_READ_16( struct brw_compile *p, - struct brw_reg dest, - uint32_t msg_reg_nr, - uint32_t scratch_offset ) -{ - { - brw_push_insn_state(p); - brw_set_compression_control(p, BRW_COMPRESSION_NONE); - brw_set_mask_control(p, BRW_MASK_DISABLE); - - brw_MOV (p, - retype (brw_vec1_grf (0, 2), BRW_REGISTER_TYPE_D), - brw_imm_d (scratch_offset)); - - brw_pop_insn_state(p); - } - - { - struct brw_instruction *insn = brw_next_instruction(p, BRW_OPCODE_SEND); - - insn->header.predicate_control = 0; /* XXX */ - insn->header.compression_control = BRW_COMPRESSION_NONE; - insn->header.destreg__conditonalmod = msg_reg_nr; - - brw_instruction_set_destination(insn, dest); /* UW? */ - brw_instruction_set_source0(insn, retype(brw_vec8_grf(0), BRW_REGISTER_TYPE_UW)); - - brw_set_dp_read_message(insn, - 255, /* bti */ - 3, /* msg_control */ - BRW_DATAPORT_READ_MESSAGE_OWORD_BLOCK_READ, /* msg_type */ - 1, /* target cache */ - 1, /* msg_length */ - 2, /* response_length */ - 0); /* eot */ - } -} - - -void brw_fb_WRITE(struct brw_compile *p, - struct brw_reg dest, - uint32_t msg_reg_nr, - struct brw_reg src0, - uint32_t binding_table_index, - uint32_t msg_length, - uint32_t response_length, - int eot) -{ - struct brw_instruction *insn = brw_next_instruction(p, BRW_OPCODE_SEND); - - insn->header.predicate_control = 0; /* XXX */ - insn->header.compression_control = BRW_COMPRESSION_NONE; - insn->header.destreg__conditonalmod = msg_reg_nr; - - brw_instruction_set_destination(insn, dest); - brw_instruction_set_source0(insn, src0); - brw_instruction_set_dp_write_message(insn, - binding_table_index, - BRW_DATAPORT_RENDER_TARGET_WRITE_SIMD16_SINGLE_SOURCE, /* msg_control */ - BRW_DATAPORT_WRITE_MESSAGE_RENDER_TARGET_WRITE, /* msg_type */ - msg_length, - 1, /* pixel scoreboard */ - response_length, - eot); -} - - - -void brw_SAMPLE (struct brw_compile *p, - struct brw_reg dest, - uint32_t msg_reg_nr, - struct brw_reg src0, - uint32_t binding_table_index, - uint32_t sampler, - uint32_t writemask, - uint32_t msg_type, - uint32_t response_length, - uint32_t msg_length, - cairo_bool_t eot) -{ - int need_stall = 0; - - if(writemask == 0) { - /* printf("%s: zero writemask??\n", __FUNCTION__); */ - return; - } - - /* Hardware doesn't do destination dependency checking on send - * instructions properly. Add a workaround which generates the - * dependency by other means. In practice it seems like this bug - * only crops up for texture samples, and only where registers are - * written by the send and then written again later without being - * read in between. Luckily for us, we already track that - * information and use it to modify the writemask for the - * instruction, so that is a guide for whether a workaround is - * needed. - */ - if (writemask != WRITEMASK_XYZW) { - uint32_t dst_offset = 0; - uint32_t i, newmask = 0, len = 0; - - for (i = 0; i < 4; i++) { - if (writemask & (1<<i)) - break; - dst_offset += 2; - } - for (; i < 4; i++) { - if (!(writemask & (1<<i))) - break; - newmask |= 1<<i; - len++; - } - - if (newmask != writemask) { - need_stall = 1; - /* printf("need stall %x %x\n", newmask , writemask); */ - } - else { - struct brw_reg m1 = brw_message_reg(msg_reg_nr); - - newmask = ~newmask & WRITEMASK_XYZW; - - brw_push_insn_state(p); - - brw_set_compression_control(p, BRW_COMPRESSION_NONE); - brw_set_mask_control(p, BRW_MASK_DISABLE); - - brw_MOV(p, m1, brw_vec8_grf(0)); - brw_MOV(p, get_element_ud(m1, 2), brw_imm_ud(newmask << 12)); - - brw_pop_insn_state(p); - - src0 = retype(brw_null_reg(), BRW_REGISTER_TYPE_UW); - dest = offset(dest, dst_offset); - response_length = len * 2; - } - } - - { - struct brw_instruction *insn = brw_next_instruction(p, BRW_OPCODE_SEND); - - insn->header.predicate_control = 0; /* XXX */ - insn->header.compression_control = BRW_COMPRESSION_NONE; - insn->header.destreg__conditonalmod = msg_reg_nr; - - brw_instruction_set_destination(insn, dest); - brw_instruction_set_source0(insn, src0); - brw_set_sampler_message (insn, p->is_g4x, - binding_table_index, - sampler, - msg_type, - response_length, - msg_length, - eot); - } - - if (need_stall) - { - struct brw_reg reg = vec8(offset(dest, response_length-1)); - - /* mov (8) r9.0<1>:f r9.0<8;8,1>:f { Align1 } - */ - brw_push_insn_state(p); - brw_set_compression_control(p, 0); - brw_MOV(p, reg, reg); - brw_pop_insn_state(p); - } -} - -/* All these variables are pretty confusing - we might be better off - * using bitmasks and macros for this, in the old style. Or perhaps - * just having the caller instantiate the fields in dword3 itself. - */ -void brw_urb_WRITE(struct brw_compile *p, - struct brw_reg dest, - uint32_t msg_reg_nr, - struct brw_reg src0, - int allocate, - int used, - uint32_t msg_length, - uint32_t response_length, - int eot, - int writes_complete, - uint32_t offset, - uint32_t swizzle) -{ - struct brw_instruction *insn = brw_next_instruction(p, BRW_OPCODE_SEND); - - assert(msg_length < 16); - - brw_instruction_set_destination (insn, dest); - brw_instruction_set_source0 (insn, src0); - brw_set_src1 (insn, brw_imm_d (0)); - - insn->header.destreg__conditonalmod = msg_reg_nr; - - brw_set_urb_message (insn, - allocate, - used, - msg_length, - response_length, - eot, - writes_complete, - offset, - swizzle); -} diff --git a/gfx/cairo/cairo/src/drm/cairo-drm-intel-brw-eu-util.c b/gfx/cairo/cairo/src/drm/cairo-drm-intel-brw-eu-util.c deleted file mode 100644 index 592235b12b..0000000000 --- a/gfx/cairo/cairo/src/drm/cairo-drm-intel-brw-eu-util.c +++ /dev/null @@ -1,121 +0,0 @@ -/* - Copyright (C) Intel Corp. 2006. All Rights Reserved. - Intel funded Tungsten Graphics (http://www.tungstengraphics.com) to - develop this 3D driver. - - Permission is hereby granted, free of charge, to any person obtaining - a copy of this software and associated documentation files (the - "Software"), to deal in the Software without restriction, including - without limitation the rights to use, copy, modify, merge, publish, - distribute, sublicense, and/or sell copies of the Software, and to - permit persons to whom the Software is furnished to do so, subject to - the following conditions: - - The above copyright notice and this permission notice (including the - next paragraph) shall be included in all copies or substantial - portions of the Software. - - THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, - EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. - IN NO EVENT SHALL THE COPYRIGHT OWNER(S) AND/OR ITS SUPPLIERS BE - LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION - OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION - WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - - **********************************************************************/ -/* - * Authors: - * Keith Whitwell <keith@tungstengraphics.com> - */ - - -#include "cairoint.h" -#include "cairo-drm-intel-brw-eu.h" - - -void brw_math_invert( struct brw_compile *p, - struct brw_reg dst, - struct brw_reg src) -{ - brw_math( p, - dst, - BRW_MATH_FUNCTION_INV, - BRW_MATH_SATURATE_NONE, - 0, - src, - BRW_MATH_PRECISION_FULL, - BRW_MATH_DATA_VECTOR ); -} - - - -void brw_copy4(struct brw_compile *p, - struct brw_reg dst, - struct brw_reg src, - uint32_t count) -{ - uint32_t i; - - dst = vec4(dst); - src = vec4(src); - - for (i = 0; i < count; i++) - { - uint32_t delta = i*32; - brw_MOV(p, byte_offset(dst, delta), byte_offset(src, delta)); - brw_MOV(p, byte_offset(dst, delta+16), byte_offset(src, delta+16)); - } -} - - -void brw_copy8(struct brw_compile *p, - struct brw_reg dst, - struct brw_reg src, - uint32_t count) -{ - uint32_t i; - - dst = vec8(dst); - src = vec8(src); - - for (i = 0; i < count; i++) - { - uint32_t delta = i*32; - brw_MOV(p, byte_offset(dst, delta), byte_offset(src, delta)); - } -} - - -void brw_copy_indirect_to_indirect(struct brw_compile *p, - struct brw_indirect dst_ptr, - struct brw_indirect src_ptr, - uint32_t count) -{ - uint32_t i; - - for (i = 0; i < count; i++) - { - uint32_t delta = i*32; - brw_MOV(p, deref_4f(dst_ptr, delta), deref_4f(src_ptr, delta)); - brw_MOV(p, deref_4f(dst_ptr, delta+16), deref_4f(src_ptr, delta+16)); - } -} - - -void brw_copy_from_indirect(struct brw_compile *p, - struct brw_reg dst, - struct brw_indirect ptr, - uint32_t count) -{ - uint32_t i; - - dst = vec4(dst); - - for (i = 0; i < count; i++) - { - uint32_t delta = i*32; - brw_MOV(p, byte_offset(dst, delta), deref_4f(ptr, delta)); - brw_MOV(p, byte_offset(dst, delta+16), deref_4f(ptr, delta+16)); - } -} diff --git a/gfx/cairo/cairo/src/drm/cairo-drm-intel-brw-eu.c b/gfx/cairo/cairo/src/drm/cairo-drm-intel-brw-eu.c deleted file mode 100644 index 2b47d8c37e..0000000000 --- a/gfx/cairo/cairo/src/drm/cairo-drm-intel-brw-eu.c +++ /dev/null @@ -1,250 +0,0 @@ -/* - Copyright (C) Intel Corp. 2006. All Rights Reserved. - Intel funded Tungsten Graphics (http://www.tungstengraphics.com) to - develop this 3D driver. - - Permission is hereby granted, free of charge, to any person obtaining - a copy of this software and associated documentation files (the - "Software"), to deal in the Software without restriction, including - without limitation the rights to use, copy, modify, merge, publish, - distribute, sublicense, and/or sell copies of the Software, and to - permit persons to whom the Software is furnished to do so, subject to - the following conditions: - - The above copyright notice and this permission notice (including the - next paragraph) shall be included in all copies or substantial - portions of the Software. - - THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, - EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. - IN NO EVENT SHALL THE COPYRIGHT OWNER(S) AND/OR ITS SUPPLIERS BE - LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION - OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION - WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - - **********************************************************************/ -/* - * Authors: - * Keith Whitwell <keith@tungstengraphics.com> - */ - -#include "cairoint.h" -#include "cairo-drm-intel-brw-eu.h" - -#include <assert.h> -#include <stdlib.h> -#include <string.h> - - -/* How does predicate control work when execution_size != 8? Do I - * need to test/set for 0xffff when execution_size is 16? - */ -void brw_set_predicate_control_flag_value( struct brw_compile *p, uint32_t value ) -{ - p->current->header.predicate_control = BRW_PREDICATE_NONE; - - if (value != 0xff) { - if (value != p->flag_value) { - brw_push_insn_state(p); - brw_MOV(p, brw_flag_reg(), brw_imm_uw(value)); - p->flag_value = value; - brw_pop_insn_state(p); - } - - p->current->header.predicate_control = BRW_PREDICATE_NORMAL; - } -} - -void brw_set_predicate_control( struct brw_compile *p, uint32_t pc ) -{ - p->current->header.predicate_control = pc; -} - -void brw_set_conditionalmod( struct brw_compile *p, uint32_t conditional ) -{ - p->current->header.destreg__conditonalmod = conditional; -} - -void brw_set_access_mode( struct brw_compile *p, uint32_t access_mode ) -{ - p->current->header.access_mode = access_mode; -} - -void brw_set_compression_control( struct brw_compile *p, int compression_control ) -{ - p->current->header.compression_control = compression_control; -} - -void brw_set_mask_control( struct brw_compile *p, uint32_t value ) -{ - p->current->header.mask_control = value; -} - -void brw_set_saturate( struct brw_compile *p, uint32_t value ) -{ - p->current->header.saturate = value; -} - -void brw_push_insn_state( struct brw_compile *p ) -{ - assert(p->current != &p->stack[BRW_EU_MAX_INSN_STACK-1]); - memcpy(p->current+1, p->current, sizeof(struct brw_instruction)); - p->current++; -} - -void brw_pop_insn_state( struct brw_compile *p ) -{ - assert(p->current != p->stack); - p->current--; -} - -/************************************************************************/ -void -brw_compile_init (struct brw_compile *p, - cairo_bool_t is_g4x) -{ - p->nr_insn = 0; - p->current = p->stack; - memset (p->current, 0, sizeof (p->current[0])); - - p->is_g4x = is_g4x; - - /* Some defaults? */ - brw_set_mask_control (p, BRW_MASK_ENABLE); /* what does this do? */ - brw_set_saturate (p, 0); - brw_set_compression_control (p, BRW_COMPRESSION_NONE); - brw_set_predicate_control_flag_value (p, 0xff); -} - -const uint32_t * -brw_get_program (struct brw_compile *p, - uint32_t *sz) -{ - *sz = p->nr_insn * sizeof (struct brw_instruction); - return (const uint32_t *)p->store; -} - - - -/* - * Subroutine calls require special attention. - * Mesa instructions may be expanded into multiple hardware instructions - * so the prog_instruction::BranchTarget field can't be used as an index - * into the hardware instructions. - * - * The BranchTarget field isn't needed, however. Mesa's GLSL compiler - * emits CAL and BGNSUB instructions with labels that can be used to map - * subroutine calls to actual subroutine code blocks. - * - * The structures and function here implement patching of CAL instructions - * so they jump to the right subroutine code... - */ - - -/* - * For each OPCODE_BGNSUB we create one of these. - */ -struct brw_glsl_label -{ - const char *name; /*< the label string */ - uint32_t position; /*< the position of the brw instruction for this label */ - struct brw_glsl_label *next; /*< next in linked list */ -}; - - -/* - * For each OPCODE_CAL we create one of these. - */ -struct brw_glsl_call -{ - uint32_t call_inst_pos; /*< location of the CAL instruction */ - const char *sub_name; /*< name of subroutine to call */ - struct brw_glsl_call *next; /*< next in linked list */ -}; - - -/* - * Called for each OPCODE_BGNSUB. - */ - void -brw_save_label(struct brw_compile *c, const char *name, uint32_t position) -{ - struct brw_glsl_label *label = calloc(1, sizeof *label); - label->name = name; - label->position = position; - label->next = c->first_label; - c->first_label = label; -} - - -/* - * Called for each OPCODE_CAL. - */ - void -brw_save_call(struct brw_compile *c, const char *name, uint32_t call_pos) -{ - struct brw_glsl_call *call = calloc(1, sizeof *call); - call->call_inst_pos = call_pos; - call->sub_name = name; - call->next = c->first_call; - c->first_call = call; -} - - -/* - * Lookup a label, return label's position/offset. - */ - static uint32_t -brw_lookup_label(struct brw_compile *c, const char *name) -{ - const struct brw_glsl_label *label; - for (label = c->first_label; label; label = label->next) { - if (strcmp(name, label->name) == 0) { - return label->position; - } - } - abort(); /* should never happen */ - return ~0; -} - - -/* - * When we're done generating code, this function is called to resolve - * subroutine calls. - */ - void -brw_resolve_cals(struct brw_compile *c) -{ - const struct brw_glsl_call *call; - - for (call = c->first_call; call; call = call->next) { - const uint32_t sub_loc = brw_lookup_label(c, call->sub_name); - struct brw_instruction *brw_call_inst = &c->store[call->call_inst_pos]; - struct brw_instruction *brw_sub_inst = &c->store[sub_loc]; - int32_t offset = brw_sub_inst - brw_call_inst; - - /* patch brw_inst1 to point to brw_inst2 */ - brw_set_src1(brw_call_inst, brw_imm_d(offset * 16)); - } - - /* free linked list of calls */ - { - struct brw_glsl_call *call, *next; - for (call = c->first_call; call; call = next) { - next = call->next; - free(call); - } - c->first_call = NULL; - } - - /* free linked list of labels */ - { - struct brw_glsl_label *label, *next; - for (label = c->first_label; label; label = next) { - next = label->next; - free(label); - } - c->first_label = NULL; - } -} diff --git a/gfx/cairo/cairo/src/drm/cairo-drm-intel-brw-eu.h b/gfx/cairo/cairo/src/drm/cairo-drm-intel-brw-eu.h deleted file mode 100644 index ef6e9771e3..0000000000 --- a/gfx/cairo/cairo/src/drm/cairo-drm-intel-brw-eu.h +++ /dev/null @@ -1,1044 +0,0 @@ -/* - Copyright (C) Intel Corp. 2006. All Rights Reserved. - Intel funded Tungsten Graphics (http://www.tungstengraphics.com) to - develop this 3D driver. - - Permission is hereby granted, free of charge, to any person obtaining - a copy of this software and associated documentation files (the - "Software"), to deal in the Software without restriction, including - without limitation the rights to use, copy, modify, merge, publish, - distribute, sublicense, and/or sell copies of the Software, and to - permit persons to whom the Software is furnished to do so, subject to - the following conditions: - - The above copyright notice and this permission notice (including the - next paragraph) shall be included in all copies or substantial - portions of the Software. - - THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, - EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. - IN NO EVENT SHALL THE COPYRIGHT OWNER(S) AND/OR ITS SUPPLIERS BE - LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION - OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION - WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - - **********************************************************************/ -/* - * Authors: - * Keith Whitwell <keith@tungstengraphics.com> - */ - -#ifndef CAIRO_DRM_INTEL_BRW_EU_H -#define CAIRO_DRM_INTEL_BRW_EU_H - -#include "cairo.h" -#include "cairo-drm-intel-brw-structs.h" -#include "cairo-drm-intel-brw-defines.h" - -#include <assert.h> - - -/* - * Writemask values, 1 bit per component. - */ -#define WRITEMASK_X 0x1 -#define WRITEMASK_Y 0x2 -#define WRITEMASK_Z 0x4 -#define WRITEMASK_W 0x8 -#define WRITEMASK_XY (WRITEMASK_X | WRITEMASK_Y) -#define WRITEMASK_XZ (WRITEMASK_X | WRITEMASK_Z) -#define WRITEMASK_YZ (WRITEMASK_Y | WRITEMASK_Z) -#define WRITEMASK_XYZ (WRITEMASK_X | WRITEMASK_Y | WRITEMASK_Z) -#define WRITEMASK_XW (WRITEMASK_X | WRITEMASK_W) -#define WRITEMASK_YW (WRITEMASK_Y | WRITEMASK_W) -#define WRITEMASK_XYW (WRITEMASK_X | WRITEMASK_Y | WRITEMASK_W) -#define WRITEMASK_ZW (WRITEMASK_Z | WRITEMASK_W) -#define WRITEMASK_XZW (WRITEMASK_X | WRITEMASK_Z | WRITEMASK_W) -#define WRITEMASK_YZW (WRITEMASK_Y | WRITEMASK_Z | WRITEMASK_W) -#define WRITEMASK_XYZW (WRITEMASK_X | WRITEMASK_Y | WRITEMASK_Z | WRITEMASK_W) - -#define BRW_SWIZZLE4(a,b,c,d) (((a)<<0) | ((b)<<2) | ((c)<<4) | ((d)<<6)) -#define BRW_GET_SWZ(swz, idx) (((swz) >> ((idx)*2)) & 0x3) - -#define BRW_SWIZZLE_NOOP BRW_SWIZZLE4 (0,1,2,3) -#define BRW_SWIZZLE_XYZW BRW_SWIZZLE4 (0,1,2,3) -#define BRW_SWIZZLE_XXXX BRW_SWIZZLE4 (0,0,0,0) -#define BRW_SWIZZLE_XYXY BRW_SWIZZLE4 (0,1,0,1) - -#define REG_SIZE (8*4) - -/* These aren't hardware structs, just something useful for us to pass around: - * - * Align1 operation has a lot of control over input ranges. Used in - * WM programs to implement shaders decomposed into "channel serial" - * or "structure of array" form: - */ -struct brw_reg { - uint32_t type:4; - uint32_t file:2; - uint32_t nr:8; - uint32_t subnr:5; /* :1 in align16 */ - uint32_t negate:1; /* source only */ - uint32_t abs:1; /* source only */ - uint32_t vstride:4; /* source only */ - uint32_t width:3; /* src only, align1 only */ - uint32_t hstride:2; /* align1 only */ - uint32_t address_mode:1; /* relative addressing, hopefully! */ - uint32_t pad0:1; - - union { - struct { - uint32_t swizzle:8; /* src only, align16 only */ - uint32_t writemask:4; /* dest only, align16 only */ - int32_t indirect_offset:10; /* relative addressing offset */ - uint32_t pad1:10; /* two dwords total */ - } bits; - - float f; - int32_t d; - uint32_t ud; - } dw1; -}; - -struct brw_indirect { - uint32_t addr_subnr:4; - int32_t addr_offset:10; - uint32_t pad:18; -}; - -struct brw_glsl_label; -struct brw_glsl_call; - -#define BRW_EU_MAX_INSN_STACK 5 -#define BRW_EU_MAX_INSN 200 - -struct brw_compile { - struct brw_instruction store[BRW_EU_MAX_INSN]; - uint32_t nr_insn; - - cairo_bool_t is_g4x; - - /* Allow clients to push/pop instruction state: - */ - struct brw_instruction stack[BRW_EU_MAX_INSN_STACK]; - struct brw_instruction *current; - - uint32_t flag_value; - int single_program_flow; - struct brw_context *brw; - - struct brw_glsl_label *first_label; /*< linked list of labels */ - struct brw_glsl_call *first_call; /*< linked list of CALs */ -}; - -cairo_private void -brw_save_label (struct brw_compile *c, - const char *name, - uint32_t position); - -cairo_private void -brw_save_call (struct brw_compile *c, - const char *name, - uint32_t call_pos); - -cairo_private void -brw_resolve_cals (struct brw_compile *c); - -static cairo_always_inline int -type_sz (uint32_t type) -{ - switch (type) { - case BRW_REGISTER_TYPE_UD: - case BRW_REGISTER_TYPE_D: - case BRW_REGISTER_TYPE_F: - return 4; - case BRW_REGISTER_TYPE_HF: - case BRW_REGISTER_TYPE_UW: - case BRW_REGISTER_TYPE_W: - return 2; - case BRW_REGISTER_TYPE_UB: - case BRW_REGISTER_TYPE_B: - return 1; - default: - return 0; - } -} - -/* - * Construct a brw_reg. - * \param file one of the BRW_x_REGISTER_FILE values - * \param nr register number/index - * \param subnr register sub number - * \param type one of BRW_REGISTER_TYPE_x - * \param vstride one of BRW_VERTICAL_STRIDE_x - * \param width one of BRW_WIDTH_x - * \param hstride one of BRW_HORIZONTAL_STRIDE_x - * \param swizzle one of BRW_SWIZZLE_x - * \param writemask WRITEMASK_X/Y/Z/W bitfield - */ -static cairo_always_inline struct brw_reg -brw_reg (uint32_t file, - uint32_t nr, - uint32_t subnr, - uint32_t type, - uint32_t vstride, - uint32_t width, - uint32_t hstride, - uint32_t swizzle, - uint32_t writemask) -{ - struct brw_reg reg; - - if (type == BRW_GENERAL_REGISTER_FILE) - assert(nr < 128); - else if (type == BRW_MESSAGE_REGISTER_FILE) - assert(nr < 9); - else if (type == BRW_ARCHITECTURE_REGISTER_FILE) - assert(nr <= BRW_ARF_IP); - - reg.type = type; - reg.file = file; - reg.nr = nr; - reg.subnr = subnr * type_sz(type); - reg.negate = 0; - reg.abs = 0; - reg.vstride = vstride; - reg.width = width; - reg.hstride = hstride; - reg.address_mode = BRW_ADDRESS_DIRECT; - reg.pad0 = 0; - - /* Could do better: If the reg is r5.3<0;1,0>, we probably want to - * set swizzle and writemask to W, as the lower bits of subnr will - * be lost when converted to align16. This is probably too much to - * keep track of as you'd want it adjusted by suboffset(), etc. - * Perhaps fix up when converting to align16? - */ - reg.dw1.bits.swizzle = swizzle; - reg.dw1.bits.writemask = writemask; - reg.dw1.bits.indirect_offset = 0; - reg.dw1.bits.pad1 = 0; - - return reg; -} - -/* Construct float[16] register */ -static cairo_always_inline struct brw_reg -brw_vec16_reg (uint32_t file, - uint32_t nr, - uint32_t subnr) -{ - return brw_reg (file, nr, subnr, - BRW_REGISTER_TYPE_F, - BRW_VERTICAL_STRIDE_16, - BRW_WIDTH_16, - BRW_HORIZONTAL_STRIDE_1, - BRW_SWIZZLE_XYZW, - WRITEMASK_XYZW); -} - -/* Construct float[8] register */ -static cairo_always_inline struct brw_reg -brw_vec8_reg (uint32_t file, - uint32_t nr, - uint32_t subnr) -{ - return brw_reg (file, nr, subnr, - BRW_REGISTER_TYPE_F, - BRW_VERTICAL_STRIDE_8, - BRW_WIDTH_8, - BRW_HORIZONTAL_STRIDE_1, - BRW_SWIZZLE_XYZW, - WRITEMASK_XYZW); -} - -/* Construct float[4] register */ -static cairo_always_inline struct brw_reg -brw_vec4_reg (uint32_t file, - uint32_t nr, - uint32_t subnr) -{ - return brw_reg (file, nr, subnr, - BRW_REGISTER_TYPE_F, - BRW_VERTICAL_STRIDE_4, - BRW_WIDTH_4, - BRW_HORIZONTAL_STRIDE_1, - BRW_SWIZZLE_XYZW, - WRITEMASK_XYZW); -} - -/* Construct float[2] register */ -static cairo_always_inline struct brw_reg -brw_vec2_reg (uint32_t file, - uint32_t nr, - uint32_t subnr) -{ - return brw_reg (file, nr, subnr, - BRW_REGISTER_TYPE_F, - BRW_VERTICAL_STRIDE_2, - BRW_WIDTH_2, - BRW_HORIZONTAL_STRIDE_1, - BRW_SWIZZLE_XYXY, - WRITEMASK_XY); -} - -/* Construct float[1] register */ -static cairo_always_inline struct brw_reg -brw_vec1_reg (uint32_t file, - uint32_t nr, - uint32_t subnr) -{ - return brw_reg (file, nr, subnr, - BRW_REGISTER_TYPE_F, - BRW_VERTICAL_STRIDE_0, - BRW_WIDTH_1, - BRW_HORIZONTAL_STRIDE_0, - BRW_SWIZZLE_XXXX, - WRITEMASK_X); -} - -static cairo_always_inline struct brw_reg -retype (struct brw_reg reg, - uint32_t type) -{ - reg.type = type; - return reg; -} - -static cairo_always_inline struct brw_reg -suboffset (struct brw_reg reg, - uint32_t delta) -{ - reg.subnr += delta * type_sz (reg.type); - return reg; -} - -static cairo_always_inline struct brw_reg -offset (struct brw_reg reg, - uint32_t delta) -{ - reg.nr += delta; - return reg; -} - -static cairo_always_inline struct brw_reg -byte_offset (struct brw_reg reg, - uint32_t bytes) -{ - uint32_t newoffset = reg.nr * REG_SIZE + reg.subnr + bytes; - reg.nr = newoffset / REG_SIZE; - reg.subnr = newoffset % REG_SIZE; - return reg; -} - -/* Construct unsigned word[16] register */ -static cairo_always_inline struct brw_reg -brw_uw16_reg (uint32_t file, - uint32_t nr, - uint32_t subnr) -{ - return suboffset (retype (brw_vec16_reg (file, nr, 0), BRW_REGISTER_TYPE_UW), subnr); -} - -/* Construct unsigned word[8] register */ -static cairo_always_inline struct brw_reg -brw_uw8_reg (uint32_t file, - uint32_t nr, - uint32_t subnr) -{ - return suboffset (retype (brw_vec8_reg (file, nr, 0), BRW_REGISTER_TYPE_UW), subnr); -} - -/* Construct unsigned word[2] register */ -static cairo_always_inline struct brw_reg -brw_uw2_reg (uint32_t file, - uint32_t nr, - uint32_t subnr) -{ - return suboffset (retype (brw_vec2_reg (file, nr, 0), BRW_REGISTER_TYPE_UW), subnr); -} - -/* Construct unsigned word[1] register */ -static cairo_always_inline struct brw_reg -brw_uw1_reg (uint32_t file, - uint32_t nr, - uint32_t subnr) -{ - return suboffset (retype (brw_vec1_reg (file, nr, 0), BRW_REGISTER_TYPE_UW), subnr); -} - -static cairo_always_inline struct brw_reg -brw_imm_reg (uint32_t type) -{ - return brw_reg (BRW_IMMEDIATE_VALUE, - 0, - 0, - type, - BRW_VERTICAL_STRIDE_0, - BRW_WIDTH_1, - BRW_HORIZONTAL_STRIDE_0, - 0, - 0); -} - -/* Construct float immediate register */ -static cairo_always_inline struct brw_reg brw_imm_f( float f ) -{ - struct brw_reg imm = brw_imm_reg(BRW_REGISTER_TYPE_F); - imm.dw1.f = f; - return imm; -} - -/* Construct integer immediate register */ -static cairo_always_inline struct brw_reg brw_imm_d( int32_t d ) -{ - struct brw_reg imm = brw_imm_reg(BRW_REGISTER_TYPE_D); - imm.dw1.d = d; - return imm; -} - -/* Construct uint immediate register */ -static cairo_always_inline struct brw_reg brw_imm_ud( uint32_t ud ) -{ - struct brw_reg imm = brw_imm_reg(BRW_REGISTER_TYPE_UD); - imm.dw1.ud = ud; - return imm; -} - -/* Construct ushort immediate register */ -static cairo_always_inline struct brw_reg brw_imm_uw( uint16_t uw ) -{ - struct brw_reg imm = brw_imm_reg(BRW_REGISTER_TYPE_UW); - imm.dw1.ud = uw | (uw << 16); - return imm; -} - -/* Construct short immediate register */ -static cairo_always_inline struct brw_reg brw_imm_w( int16_t w ) -{ - struct brw_reg imm = brw_imm_reg(BRW_REGISTER_TYPE_W); - imm.dw1.d = w | (w << 16); - return imm; -} - -/* brw_imm_b and brw_imm_ub aren't supported by hardware - the type - * numbers alias with _V and _VF below: - */ - -/* Construct vector of eight signed half-byte values */ -static cairo_always_inline -struct brw_reg brw_imm_v (uint32_t v) -{ - struct brw_reg imm = brw_imm_reg(BRW_REGISTER_TYPE_V); - imm.vstride = BRW_VERTICAL_STRIDE_0; - imm.width = BRW_WIDTH_8; - imm.hstride = BRW_HORIZONTAL_STRIDE_1; - imm.dw1.ud = v; - return imm; -} - -/* Construct vector of four 8-bit float values */ -static cairo_always_inline struct brw_reg -brw_imm_vf (uint32_t v) -{ - struct brw_reg imm = brw_imm_reg(BRW_REGISTER_TYPE_VF); - imm.vstride = BRW_VERTICAL_STRIDE_0; - imm.width = BRW_WIDTH_4; - imm.hstride = BRW_HORIZONTAL_STRIDE_1; - imm.dw1.ud = v; - return imm; -} - -#define VF_ZERO 0x0 -#define VF_ONE 0x30 -#define VF_NEG (1<<7) - -static cairo_always_inline struct brw_reg -brw_imm_vf4 (uint32_t v0, - uint32_t v1, - uint32_t v2, - uint32_t v3) -{ - struct brw_reg imm = brw_imm_reg(BRW_REGISTER_TYPE_VF); - imm.vstride = BRW_VERTICAL_STRIDE_0; - imm.width = BRW_WIDTH_4; - imm.hstride = BRW_HORIZONTAL_STRIDE_1; - imm.dw1.ud = ((v0 << 0) | - (v1 << 8) | - (v2 << 16) | - (v3 << 24)); - return imm; -} - -static cairo_always_inline struct brw_reg -brw_address (struct brw_reg reg) -{ - return brw_imm_uw (reg.nr * REG_SIZE + reg.subnr); -} - -/* Construct float[1] general-purpose register */ -static cairo_always_inline struct brw_reg -brw_vec1_grf (uint32_t nr, uint32_t subnr) -{ - return brw_vec1_reg (BRW_GENERAL_REGISTER_FILE, nr, subnr); -} - -/* Construct float[2] general-purpose register */ -static cairo_always_inline struct brw_reg -brw_vec2_grf (uint32_t nr, uint32_t subnr) -{ - return brw_vec2_reg (BRW_GENERAL_REGISTER_FILE, nr, subnr); -} - -/* Construct float[4] general-purpose register */ -static cairo_always_inline struct brw_reg -brw_vec4_grf (uint32_t nr, uint32_t subnr) -{ - return brw_vec4_reg (BRW_GENERAL_REGISTER_FILE, nr, subnr); -} - -/* Construct float[8] general-purpose register */ -static cairo_always_inline struct brw_reg -brw_vec8_grf (uint32_t nr) -{ - return brw_vec8_reg (BRW_GENERAL_REGISTER_FILE, nr, 0); -} - -static cairo_always_inline struct brw_reg -brw_uw8_grf (uint32_t nr, uint32_t subnr) -{ - return brw_uw8_reg (BRW_GENERAL_REGISTER_FILE, nr, subnr); -} - -static cairo_always_inline struct brw_reg -brw_uw16_grf (uint32_t nr, uint32_t subnr) -{ - return brw_uw16_reg (BRW_GENERAL_REGISTER_FILE, nr, subnr); -} - -/* Construct null register (usually used for setting condition codes) */ -static cairo_always_inline struct brw_reg -brw_null_reg (void) -{ - return brw_vec8_reg (BRW_ARCHITECTURE_REGISTER_FILE, - BRW_ARF_NULL, - 0); -} - -static cairo_always_inline struct brw_reg -brw_address_reg (uint32_t subnr) -{ - return brw_uw1_reg (BRW_ARCHITECTURE_REGISTER_FILE, - BRW_ARF_ADDRESS, - subnr); -} - -/* If/else instructions break in align16 mode if writemask & swizzle - * aren't xyzw. This goes against the convention for other scalar - * regs: - */ -static cairo_always_inline struct brw_reg -brw_ip_reg (void) -{ - return brw_reg (BRW_ARCHITECTURE_REGISTER_FILE, - BRW_ARF_IP, - 0, - BRW_REGISTER_TYPE_UD, - BRW_VERTICAL_STRIDE_4, /* ? */ - BRW_WIDTH_1, - BRW_HORIZONTAL_STRIDE_0, - BRW_SWIZZLE_XYZW, - WRITEMASK_XYZW); -} - -static cairo_always_inline struct brw_reg -brw_acc_reg (void) -{ - return brw_vec8_reg (BRW_ARCHITECTURE_REGISTER_FILE, - BRW_ARF_ACCUMULATOR, - 0); -} - -static cairo_always_inline struct brw_reg -brw_flag_reg (void) -{ - return brw_uw1_reg (BRW_ARCHITECTURE_REGISTER_FILE, - BRW_ARF_FLAG, - 0); -} - -static cairo_always_inline struct brw_reg -brw_mask_reg (uint32_t subnr) -{ - return brw_uw1_reg (BRW_ARCHITECTURE_REGISTER_FILE, - BRW_ARF_MASK, - subnr); -} - -static cairo_always_inline struct brw_reg -brw_message4_reg (uint32_t nr) -{ - return brw_vec4_reg (BRW_MESSAGE_REGISTER_FILE, - nr, - 0); -} - -static cairo_always_inline struct brw_reg -brw_message_reg (uint32_t nr) -{ - return brw_vec8_reg (BRW_MESSAGE_REGISTER_FILE, - nr, - 0); -} - -/* This is almost always called with a numeric constant argument, so - * make things easy to evaluate at compile time: - */ -static cairo_always_inline uint32_t -cvt (uint32_t val) -{ - switch (val) { - case 0: return 0; - case 1: return 1; - case 2: return 2; - case 4: return 3; - case 8: return 4; - case 16: return 5; - case 32: return 6; - } - return 0; -} - -static cairo_always_inline struct brw_reg -stride (struct brw_reg reg, - uint32_t vstride, - uint32_t width, - uint32_t hstride) -{ - reg.vstride = cvt (vstride); - reg.width = cvt (width) - 1; - reg.hstride = cvt (hstride); - return reg; -} - -static cairo_always_inline struct brw_reg -vec16 (struct brw_reg reg) -{ - return stride (reg, 16,16,1); -} - -static cairo_always_inline struct brw_reg -vec8 (struct brw_reg reg) -{ - return stride (reg, 8,8,1); -} - -static cairo_always_inline struct brw_reg -vec4 (struct brw_reg reg) -{ - return stride (reg, 4,4,1); -} - -static cairo_always_inline struct brw_reg -vec2 (struct brw_reg reg) -{ - return stride (reg, 2,2,1); -} - -static cairo_always_inline struct brw_reg -vec1 (struct brw_reg reg) -{ - return stride (reg, 0,1,0); -} - -static cairo_always_inline struct brw_reg -get_element (struct brw_reg reg, uint32_t elt) -{ - return vec1 (suboffset (reg, elt)); -} - -static cairo_always_inline struct brw_reg -get_element_ud (struct brw_reg reg, uint32_t elt) -{ - return vec1 (suboffset (retype (reg, BRW_REGISTER_TYPE_UD), elt)); -} - -static cairo_always_inline struct brw_reg -brw_swizzle (struct brw_reg reg, - uint32_t x, - uint32_t y, - uint32_t z, - uint32_t w) -{ - reg.dw1.bits.swizzle = BRW_SWIZZLE4 (BRW_GET_SWZ (reg.dw1.bits.swizzle, x), - BRW_GET_SWZ (reg.dw1.bits.swizzle, y), - BRW_GET_SWZ (reg.dw1.bits.swizzle, z), - BRW_GET_SWZ (reg.dw1.bits.swizzle, w)); - return reg; -} - -static cairo_always_inline struct brw_reg -brw_swizzle1 (struct brw_reg reg, - uint32_t x) -{ - return brw_swizzle (reg, x, x, x, x); -} - -static cairo_always_inline struct brw_reg -brw_writemask (struct brw_reg reg, - uint32_t mask) -{ - reg.dw1.bits.writemask &= mask; - return reg; -} - -static cairo_always_inline struct brw_reg -brw_set_writemask (struct brw_reg reg, - uint32_t mask) -{ - reg.dw1.bits.writemask = mask; - return reg; -} - -static cairo_always_inline struct brw_reg -negate (struct brw_reg reg) -{ - reg.negate ^= 1; - return reg; -} - -static cairo_always_inline struct brw_reg -brw_abs (struct brw_reg reg) -{ - reg.abs = 1; - return reg; -} - -static cairo_always_inline struct brw_reg -brw_vec4_indirect (uint32_t subnr, - int32_t offset) -{ - struct brw_reg reg = brw_vec4_grf (0, 0); - reg.subnr = subnr; - reg.address_mode = BRW_ADDRESS_REGISTER_INDIRECT_REGISTER; - reg.dw1.bits.indirect_offset = offset; - return reg; -} - -static cairo_always_inline struct brw_reg -brw_vec1_indirect (uint32_t subnr, - int32_t offset) -{ - struct brw_reg reg = brw_vec1_grf (0, 0); - reg.subnr = subnr; - reg.address_mode = BRW_ADDRESS_REGISTER_INDIRECT_REGISTER; - reg.dw1.bits.indirect_offset = offset; - return reg; -} - -static cairo_always_inline struct brw_reg -deref_4f (struct brw_indirect ptr, int32_t offset) -{ - return brw_vec4_indirect (ptr.addr_subnr, ptr.addr_offset + offset); -} - -static cairo_always_inline struct brw_reg -deref_1f(struct brw_indirect ptr, int32_t offset) -{ - return brw_vec1_indirect (ptr.addr_subnr, ptr.addr_offset + offset); -} - -static cairo_always_inline struct brw_reg -deref_4b(struct brw_indirect ptr, int32_t offset) -{ - return retype (deref_4f (ptr, offset), BRW_REGISTER_TYPE_B); -} - -static cairo_always_inline struct brw_reg -deref_1uw(struct brw_indirect ptr, int32_t offset) -{ - return retype (deref_1f (ptr, offset), BRW_REGISTER_TYPE_UW); -} - -static cairo_always_inline struct brw_reg -deref_1d (struct brw_indirect ptr, int32_t offset) -{ - return retype (deref_1f (ptr, offset), BRW_REGISTER_TYPE_D); -} - -static cairo_always_inline struct brw_reg -deref_1ud (struct brw_indirect ptr, int32_t offset) -{ - return retype (deref_1f (ptr, offset), BRW_REGISTER_TYPE_UD); -} - -static cairo_always_inline struct brw_reg -get_addr_reg (struct brw_indirect ptr) -{ - return brw_address_reg (ptr.addr_subnr); -} - -static cairo_always_inline struct brw_indirect -brw_indirect_offset (struct brw_indirect ptr, int32_t offset) -{ - ptr.addr_offset += offset; - return ptr; -} - -static cairo_always_inline struct brw_indirect -brw_indirect (uint32_t addr_subnr, int32_t offset) -{ - struct brw_indirect ptr; - ptr.addr_subnr = addr_subnr; - ptr.addr_offset = offset; - ptr.pad = 0; - return ptr; -} - -static cairo_always_inline struct brw_instruction * -current_insn (struct brw_compile *p) -{ - return &p->store[p->nr_insn]; -} - -cairo_private void brw_pop_insn_state (struct brw_compile *p); -cairo_private void brw_push_insn_state (struct brw_compile *p); -cairo_private void brw_set_mask_control (struct brw_compile *p, uint32_t value); -cairo_private void brw_set_saturate (struct brw_compile *p, uint32_t value); -cairo_private void brw_set_access_mode (struct brw_compile *p, uint32_t access_mode); -cairo_private void brw_set_compression_control (struct brw_compile *p, int control); -cairo_private void brw_set_predicate_control_flag_value (struct brw_compile *p, uint32_t value); -cairo_private void brw_set_predicate_control (struct brw_compile *p, uint32_t pc); -cairo_private void brw_set_conditionalmod (struct brw_compile *p, uint32_t conditional); - -cairo_private void -brw_compile_init (struct brw_compile *p, - cairo_bool_t is_g4x); -cairo_private const uint32_t *brw_get_program (struct brw_compile *p, uint32_t *sz); - -/* Helpers for regular instructions: - */ -#define ALU1(OP) \ -cairo_private_no_warn struct brw_instruction * \ -brw_##OP(struct brw_compile *p, \ - struct brw_reg dest, \ - struct brw_reg src0); - -#define ALU2(OP) \ -cairo_private_no_warn struct brw_instruction * \ -brw_##OP(struct brw_compile *p, \ - struct brw_reg dest, \ - struct brw_reg src0, \ - struct brw_reg src1); - -ALU1(MOV) -ALU2(SEL) -ALU1(NOT) -ALU2(AND) -ALU2(OR) -ALU2(XOR) -ALU2(SHR) -ALU2(SHL) -ALU2(RSR) -ALU2(RSL) -ALU2(ASR) -ALU2(JMPI) -ALU2(ADD) -ALU2(MUL) -ALU1(FRC) -ALU1(RNDD) -ALU1(RNDZ) -ALU2(MAC) -ALU2(MACH) -ALU1(LZD) -ALU2(DP4) -ALU2(DPH) -ALU2(DP3) -ALU2(DP2) -ALU2(LINE) - -#undef ALU1 -#undef ALU2 - -/* Helpers for SEND instruction: */ -cairo_private void -brw_urb_WRITE (struct brw_compile *p, - struct brw_reg dest, - uint32_t msg_reg_nr, - struct brw_reg src0, - int allocate, - int used, - uint32_t msg_length, - uint32_t response_length, - int eot, - int writes_complete, - uint32_t offset, - uint32_t swizzle); - -cairo_private void -brw_fb_WRITE (struct brw_compile *p, - struct brw_reg dest, - uint32_t msg_reg_nr, - struct brw_reg src0, - uint32_t binding_table_index, - uint32_t msg_length, - uint32_t response_length, - int eot); - -cairo_private void -brw_SAMPLE (struct brw_compile *p, - struct brw_reg dest, - uint32_t msg_reg_nr, - struct brw_reg src0, - uint32_t binding_table_index, - uint32_t sampler, - uint32_t writemask, - uint32_t msg_type, - uint32_t response_length, - uint32_t msg_length, - cairo_bool_t eot); - -cairo_private void -brw_math_16 (struct brw_compile *p, - struct brw_reg dest, - uint32_t function, - uint32_t saturate, - uint32_t msg_reg_nr, - struct brw_reg src, - uint32_t precision); - -cairo_private void -brw_math (struct brw_compile *p, - struct brw_reg dest, - uint32_t function, - uint32_t saturate, - uint32_t msg_reg_nr, - struct brw_reg src, - uint32_t data_type, - uint32_t precision); - -cairo_private void -brw_dp_READ_16 (struct brw_compile *p, - struct brw_reg dest, - uint32_t msg_reg_nr, - uint32_t scratch_offset); - -cairo_private void -brw_dp_WRITE_16 (struct brw_compile *p, - struct brw_reg src, - uint32_t msg_reg_nr, - uint32_t scratch_offset); - -/* If/else/endif. Works by manipulating the execution flags on each - * channel. - */ -cairo_private struct brw_instruction * -brw_IF (struct brw_compile *p, - uint32_t execute_size); - -cairo_private struct brw_instruction * -brw_ELSE (struct brw_compile *p, - struct brw_instruction *if_insn); - -cairo_private void -brw_ENDIF (struct brw_compile *p, - struct brw_instruction *if_or_else_insn); - - -/* DO/WHILE loops: */ -cairo_private struct brw_instruction * -brw_DO (struct brw_compile *p, - uint32_t execute_size); - -cairo_private struct brw_instruction * -brw_WHILE (struct brw_compile *p, - struct brw_instruction *patch_insn); - -cairo_private struct brw_instruction * -brw_BREAK (struct brw_compile *p); - -cairo_private struct brw_instruction * -brw_CONT (struct brw_compile *p); - -/* Forward jumps: */ -cairo_private void -brw_land_fwd_jump (struct brw_compile *p, - struct brw_instruction *jmp_insn); - -cairo_private void -brw_NOP (struct brw_compile *p); - -/* Special case: there is never a destination, execution size will be - * taken from src0: - */ -cairo_private void -brw_CMP (struct brw_compile *p, - struct brw_reg dest, - uint32_t conditional, - struct brw_reg src0, - struct brw_reg src1); - -cairo_private void -brw_print_reg (struct brw_reg reg); - -cairo_private struct brw_instruction * -brw_next_instruction (struct brw_compile *p, - uint32_t opcode); - -cairo_private void -brw_instruction_set_destination (struct brw_instruction *insn, - struct brw_reg dest); - -cairo_private void -brw_instruction_set_source0 (struct brw_instruction *insn, - struct brw_reg reg); - -cairo_private void -brw_instruction_set_dp_write_message (struct brw_instruction *insn, - uint32_t binding_table_index, - uint32_t msg_control, - uint32_t msg_type, - uint32_t msg_length, - uint32_t pixel_scoreboard_clear, - uint32_t response_length, - uint32_t end_of_thread); - -/*********************************************************************** - * brw_eu_util.c: - */ - -cairo_private void -brw_copy_indirect_to_indirect (struct brw_compile *p, - struct brw_indirect dst_ptr, - struct brw_indirect src_ptr, - uint32_t count); - -cairo_private void -brw_copy_from_indirect (struct brw_compile *p, - struct brw_reg dst, - struct brw_indirect ptr, - uint32_t count); - -cairo_private void -brw_copy4 (struct brw_compile *p, - struct brw_reg dst, - struct brw_reg src, - uint32_t count); - -cairo_private void -brw_copy8 (struct brw_compile *p, - struct brw_reg dst, - struct brw_reg src, - uint32_t count); - -cairo_private void -brw_math_invert (struct brw_compile *p, - struct brw_reg dst, - struct brw_reg src); - -cairo_private void -brw_set_src1 (struct brw_instruction *insn, - struct brw_reg reg); - -#endif diff --git a/gfx/cairo/cairo/src/drm/cairo-drm-intel-brw-structs.h b/gfx/cairo/cairo/src/drm/cairo-drm-intel-brw-structs.h deleted file mode 100644 index 3ea9c6c362..0000000000 --- a/gfx/cairo/cairo/src/drm/cairo-drm-intel-brw-structs.h +++ /dev/null @@ -1,1329 +0,0 @@ -/************************************************************************** - * - * Copyright 2005 Tungsten Graphics, Inc., Cedar Park, Texas. - * All Rights Reserved. - * - * Permission is hereby granted, free of charge, to any person obtaining a - * copy of this software and associated documentation files (the - * "Software"), to deal in the Software without restriction, including - * without limitation the rights to use, copy, modify, merge, publish, - * distribute, sub license, and/or sell copies of the Software, and to - * permit persons to whom the Software is furnished to do so, subject to - * the following conditions: - * - * The above copyright notice and this permission notice (including the - * next paragraph) shall be included in all copies or substantial portions - * of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS - * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. - * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR - * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, - * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE - * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - * - **************************************************************************/ - -#ifndef CAIRO_DRM_INTEL_BRW_STRUCTS_H -#define CAIRO_DRM_INTEL_BRW_STRUCTS_H - -#include "cairo.h" -#include "cairo-types-private.h" - -/* Command packets: -*/ -struct header { - unsigned int length:16; - unsigned int opcode:16; -}; - -union header_union { - struct header bits; - unsigned int dword; -}; - -struct brw_3d_control { - struct { - unsigned int length:8; - unsigned int notify_enable:1; - unsigned int pad:3; - unsigned int wc_flush_enable:1; - unsigned int depth_stall_enable:1; - unsigned int operation:2; - unsigned int opcode:16; - } header; - - struct { - unsigned int pad:2; - unsigned int dest_addr_type:1; - unsigned int dest_addr:29; - } dest; - - unsigned int dword2; - unsigned int dword3; -}; - - -struct brw_3d_primitive { - struct { - unsigned int length:8; - unsigned int pad:2; - unsigned int topology:5; - unsigned int indexed:1; - unsigned int opcode:16; - } header; - - unsigned int verts_per_instance; - unsigned int start_vert_location; - unsigned int instance_count; - unsigned int start_instance_location; - unsigned int base_vert_location; -}; - -/* These seem to be passed around as function args, so it works out - * better to keep them as #defines: - */ -#define BRW_FLUSH_READ_CACHE 0x1 -#define BRW_FLUSH_STATE_CACHE 0x2 -#define BRW_INHIBIT_FLUSH_RENDER_CACHE 0x4 -#define BRW_FLUSH_SNAPSHOT_COUNTERS 0x8 - -struct brw_mi_flush { - unsigned int flags:4; - unsigned int pad:12; - unsigned int opcode:16; -}; - -struct brw_vf_statistics { - unsigned int statistics_enable:1; - unsigned int pad:15; - unsigned int opcode:16; -}; - - -struct brw_binding_table_pointers { - struct header header; - unsigned int vs; - unsigned int gs; - unsigned int clp; - unsigned int sf; - unsigned int wm; -}; - -struct brw_blend_constant_color { - struct header header; - float blend_constant_color[4]; -}; - -struct brw_depthbuffer { - union header_union header; - - union { - struct { - unsigned int pitch:18; - unsigned int format:3; - unsigned int pad:4; - unsigned int depth_offset_disable:1; - unsigned int tile_walk:1; - unsigned int tiled_surface:1; - unsigned int pad2:1; - unsigned int surface_type:3; - } bits; - unsigned int dword; - } dword1; - - unsigned int dword2_base_addr; - - union { - struct { - unsigned int pad:1; - unsigned int mipmap_layout:1; - unsigned int lod:4; - unsigned int width:13; - unsigned int height:13; - } bits; - unsigned int dword; - } dword3; - - union { - struct { - unsigned int pad:12; - unsigned int min_array_element:9; - unsigned int depth:11; - } bits; - unsigned int dword; - } dword4; -}; - -struct brw_drawrect { - struct header header; - unsigned int xmin:16; - unsigned int ymin:16; - unsigned int xmax:16; - unsigned int ymax:16; - unsigned int xorg:16; - unsigned int yorg:16; -}; - -struct brw_global_depth_offset_clamp { - struct header header; - float depth_offset_clamp; -}; - -struct brw_indexbuffer { - union { - struct { - unsigned int length:8; - unsigned int index_format:2; - unsigned int cut_index_enable:1; - unsigned int pad:5; - unsigned int opcode:16; - } bits; - unsigned int dword; - } header; - unsigned int buffer_start; - unsigned int buffer_end; -}; - - -struct brw_line_stipple { - struct header header; - - struct { - unsigned int pattern:16; - unsigned int pad:16; - } bits0; - - struct { - unsigned int repeat_count:9; - unsigned int pad:7; - unsigned int inverse_repeat_count:16; - } bits1; -}; - -struct brw_pipelined_state_pointers { - struct header header; - - struct { - unsigned int pad:5; - unsigned int offset:27; - } vs; - - struct { - unsigned int enable:1; - unsigned int pad:4; - unsigned int offset:27; - } gs; - - struct { - unsigned int enable:1; - unsigned int pad:4; - unsigned int offset:27; - } clp; - - struct { - unsigned int pad:5; - unsigned int offset:27; - } sf; - - struct { - unsigned int pad:5; - unsigned int offset:27; - } wm; - - struct { - unsigned int pad:6; - unsigned int offset:26; - } cc; -}; - -struct brw_polygon_stipple_offset { - struct header header; - - struct { - unsigned int y_offset:5; - unsigned int pad:3; - unsigned int x_offset:5; - unsigned int pad0:19; - } bits0; -}; - -struct brw_polygon_stipple { - struct header header; - unsigned int stipple[32]; -}; - -struct brw_pipeline_select { - struct { - unsigned int pipeline_select:1; - unsigned int pad:15; - unsigned int opcode:16; - } header; -}; - -struct brw_pipe_control { - struct { - unsigned int length:8; - unsigned int notify_enable:1; - unsigned int pad:2; - unsigned int instruction_state_cache_flush_enable:1; - unsigned int write_cache_flush_enable:1; - unsigned int depth_stall_enable:1; - unsigned int post_sync_operation:2; - - unsigned int opcode:16; - } header; - - struct { - unsigned int pad:2; - unsigned int dest_addr_type:1; - unsigned int dest_addr:29; - } bits1; - - unsigned int data0; - unsigned int data1; -}; - - -struct brw_urb_fence { - struct { - unsigned int length:8; - unsigned int vs_realloc:1; - unsigned int gs_realloc:1; - unsigned int clp_realloc:1; - unsigned int sf_realloc:1; - unsigned int vfe_realloc:1; - unsigned int cs_realloc:1; - unsigned int pad:2; - unsigned int opcode:16; - } header; - - struct { - unsigned int vs_fence:10; - unsigned int gs_fence:10; - unsigned int clp_fence:10; - unsigned int pad:2; - } bits0; - - struct { - unsigned int sf_fence:10; - unsigned int vf_fence:10; - unsigned int cs_fence:10; - unsigned int pad:2; - } bits1; -}; - -struct brw_constant_buffer_state { - struct header header; - - struct { - unsigned int nr_urb_entries:3; - unsigned int pad:1; - unsigned int urb_entry_size:5; - unsigned int pad0:23; - } bits0; -}; - -struct brw_constant_buffer { - struct { - unsigned int length:8; - unsigned int valid:1; - unsigned int pad:7; - unsigned int opcode:16; - } header; - - struct { - unsigned int buffer_length:6; - unsigned int buffer_address:26; - } bits0; -}; - -struct brw_state_base_address { - struct header header; - - struct { - unsigned int modify_enable:1; - unsigned int pad:4; - unsigned int general_state_address:27; - } bits0; - - struct { - unsigned int modify_enable:1; - unsigned int pad:4; - unsigned int surface_state_address:27; - } bits1; - - struct { - unsigned int modify_enable:1; - unsigned int pad:4; - unsigned int indirect_object_state_address:27; - } bits2; - - struct { - unsigned int modify_enable:1; - unsigned int pad:11; - unsigned int general_state_upper_bound:20; - } bits3; - - struct { - unsigned int modify_enable:1; - unsigned int pad:11; - unsigned int indirect_object_state_upper_bound:20; - } bits4; -}; - -struct brw_state_prefetch { - struct header header; - - struct { - unsigned int prefetch_count:3; - unsigned int pad:3; - unsigned int prefetch_pointer:26; - } bits0; -}; - -struct brw_system_instruction_pointer { - struct header header; - - struct { - unsigned int pad:4; - unsigned int system_instruction_pointer:28; - } bits0; -}; - - -/* State structs for the various fixed function units: -*/ - -struct thread0 { - unsigned int pad0:1; - unsigned int grf_reg_count:3; - unsigned int pad1:2; - unsigned int kernel_start_pointer:26; -}; - -struct thread1 { - unsigned int ext_halt_exception_enable:1; - unsigned int sw_exception_enable:1; - unsigned int mask_stack_exception_enable:1; - unsigned int timeout_exception_enable:1; - unsigned int illegal_op_exception_enable:1; - unsigned int pad0:3; - unsigned int depth_coef_urb_read_offset:6; /* WM only */ - unsigned int pad1:2; - unsigned int floating_point_mode:1; - unsigned int thread_priority:1; - unsigned int binding_table_entry_count:8; - unsigned int pad3:5; - unsigned int single_program_flow:1; -}; - -struct thread2 { - unsigned int per_thread_scratch_space:4; - unsigned int pad0:6; - unsigned int scratch_space_base_pointer:22; -}; - -struct thread3 { - unsigned int dispatch_grf_start_reg:4; - unsigned int urb_entry_read_offset:6; - unsigned int pad0:1; - unsigned int urb_entry_read_length:6; - unsigned int pad1:1; - unsigned int const_urb_entry_read_offset:6; - unsigned int pad2:1; - unsigned int const_urb_entry_read_length:6; - unsigned int pad3:1; -}; - -struct brw_clip_unit_state { - struct thread0 thread0; - struct thread1 thread1; - struct thread2 thread2; - struct thread3 thread3; - - struct { - unsigned int pad0:9; - unsigned int gs_output_stats:1; /* not always */ - unsigned int stats_enable:1; - unsigned int nr_urb_entries:7; - unsigned int pad1:1; - unsigned int urb_entry_allocation_size:5; - unsigned int pad2:1; - unsigned int max_threads:6; /* may be less */ - unsigned int pad3:1; - } thread4; - - struct { - unsigned int pad0:13; - unsigned int clip_mode:3; - unsigned int userclip_enable_flags:8; - unsigned int userclip_must_clip:1; - unsigned int pad1:1; - unsigned int guard_band_enable:1; - unsigned int viewport_z_clip_enable:1; - unsigned int viewport_xy_clip_enable:1; - unsigned int vertex_position_space:1; - unsigned int api_mode:1; - unsigned int pad2:1; - } clip5; - - struct { - unsigned int pad0:5; - unsigned int clipper_viewport_state_ptr:27; - } clip6; - - float viewport_xmin; - float viewport_xmax; - float viewport_ymin; - float viewport_ymax; -}; - -struct brw_cc_unit_state { - struct { - unsigned int pad0:3; - unsigned int bf_stencil_pass_depth_pass_op:3; - unsigned int bf_stencil_pass_depth_fail_op:3; - unsigned int bf_stencil_fail_op:3; - unsigned int bf_stencil_func:3; - unsigned int bf_stencil_enable:1; - unsigned int pad1:2; - unsigned int stencil_write_enable:1; - unsigned int stencil_pass_depth_pass_op:3; - unsigned int stencil_pass_depth_fail_op:3; - unsigned int stencil_fail_op:3; - unsigned int stencil_func:3; - unsigned int stencil_enable:1; - } cc0; - - struct { - unsigned int bf_stencil_ref:8; - unsigned int stencil_write_mask:8; - unsigned int stencil_test_mask:8; - unsigned int stencil_ref:8; - } cc1; - - struct { - unsigned int logicop_enable:1; - unsigned int pad0:10; - unsigned int depth_write_enable:1; - unsigned int depth_test_function:3; - unsigned int depth_test:1; - unsigned int bf_stencil_write_mask:8; - unsigned int bf_stencil_test_mask:8; - } cc2; - - struct { - unsigned int pad0:8; - unsigned int alpha_test_func:3; - unsigned int alpha_test:1; - unsigned int blend_enable:1; - unsigned int ia_blend_enable:1; - unsigned int pad1:1; - unsigned int alpha_test_format:1; - unsigned int pad2:16; - } cc3; - - struct { - unsigned int pad0:5; - unsigned int cc_viewport_state_offset:27; - } cc4; - - struct { - unsigned int pad0:2; - unsigned int ia_dest_blend_factor:5; - unsigned int ia_src_blend_factor:5; - unsigned int ia_blend_function:3; - unsigned int statistics_enable:1; - unsigned int logicop_func:4; - unsigned int pad1:11; - unsigned int dither_enable:1; - } cc5; - - struct { - unsigned int clamp_post_alpha_blend:1; - unsigned int clamp_pre_alpha_blend:1; - unsigned int clamp_range:2; - unsigned int pad0:11; - unsigned int y_dither_offset:2; - unsigned int x_dither_offset:2; - unsigned int dest_blend_factor:5; - unsigned int src_blend_factor:5; - unsigned int blend_function:3; - } cc6; - - struct { - union { - float f; - unsigned char ub[4]; - } alpha_ref; - } cc7; -}; - -struct brw_sf_unit_state { - struct thread0 thread0; - struct { - unsigned int pad0:7; - unsigned int sw_exception_enable:1; - unsigned int pad1:3; - unsigned int mask_stack_exception_enable:1; - unsigned int pad2:1; - unsigned int illegal_op_exception_enable:1; - unsigned int pad3:2; - unsigned int floating_point_mode:1; - unsigned int thread_priority:1; - unsigned int binding_table_entry_count:8; - unsigned int pad4:5; - unsigned int single_program_flow:1; - } sf1; - - struct thread2 thread2; - struct thread3 thread3; - - struct { - unsigned int pad0:10; - unsigned int stats_enable:1; - unsigned int nr_urb_entries:7; - unsigned int pad1:1; - unsigned int urb_entry_allocation_size:5; - unsigned int pad2:1; - unsigned int max_threads:6; - unsigned int pad3:1; - } thread4; - - struct { - unsigned int front_winding:1; - unsigned int viewport_transform:1; - unsigned int pad0:3; - unsigned int sf_viewport_state_offset:27; - } sf5; - - struct { - unsigned int pad0:9; - unsigned int dest_org_vbias:4; - unsigned int dest_org_hbias:4; - unsigned int scissor:1; - unsigned int disable_2x2_trifilter:1; - unsigned int disable_zero_pix_trifilter:1; - unsigned int point_rast_rule:2; - unsigned int line_endcap_aa_region_width:2; - unsigned int line_width:4; - unsigned int fast_scissor_disable:1; - unsigned int cull_mode:2; - unsigned int aa_enable:1; - } sf6; - - struct { - unsigned int point_size:11; - unsigned int use_point_size_state:1; - unsigned int subpixel_precision:1; - unsigned int sprite_point:1; - unsigned int pad0:11; - unsigned int trifan_pv:2; - unsigned int linestrip_pv:2; - unsigned int tristrip_pv:2; - unsigned int line_last_pixel_enable:1; - } sf7; -}; - -struct brw_gs_unit_state { - struct thread0 thread0; - struct thread1 thread1; - struct thread2 thread2; - struct thread3 thread3; - - struct { - unsigned int pad0:10; - unsigned int stats_enable:1; - unsigned int nr_urb_entries:7; - unsigned int pad1:1; - unsigned int urb_entry_allocation_size:5; - unsigned int pad2:1; - unsigned int max_threads:1; - unsigned int pad3:6; - } thread4; - - struct { - unsigned int sampler_count:3; - unsigned int pad0:2; - unsigned int sampler_state_pointer:27; - } gs5; - - struct { - unsigned int max_vp_index:4; - unsigned int pad0:26; - unsigned int reorder_enable:1; - unsigned int pad1:1; - } gs6; -}; - -struct brw_vs_unit_state { - struct thread0 thread0; - struct thread1 thread1; - struct thread2 thread2; - struct thread3 thread3; - - struct { - unsigned int pad0:10; - unsigned int stats_enable:1; - unsigned int nr_urb_entries:7; - unsigned int pad1:1; - unsigned int urb_entry_allocation_size:5; - unsigned int pad2:1; - unsigned int max_threads:4; - unsigned int pad3:3; - } thread4; - - struct { - unsigned int sampler_count:3; - unsigned int pad0:2; - unsigned int sampler_state_pointer:27; - } vs5; - - struct { - unsigned int vs_enable:1; - unsigned int vert_cache_disable:1; - unsigned int pad0:30; - } vs6; -}; - -struct brw_wm_unit_state { - struct thread0 thread0; - struct thread1 thread1; - struct thread2 thread2; - struct thread3 thread3; - - struct { - unsigned int stats_enable:1; - unsigned int pad0:1; - unsigned int sampler_count:3; - unsigned int sampler_state_pointer:27; - } wm4; - - struct { - unsigned int enable_8_pix:1; - unsigned int enable_16_pix:1; - unsigned int enable_32_pix:1; - unsigned int pad0:7; - unsigned int legacy_global_depth_bias:1; - unsigned int line_stipple:1; - unsigned int depth_offset:1; - unsigned int polygon_stipple:1; - unsigned int line_aa_region_width:2; - unsigned int line_endcap_aa_region_width:2; - unsigned int early_depth_test:1; - unsigned int thread_dispatch_enable:1; - unsigned int program_uses_depth:1; - unsigned int program_computes_depth:1; - unsigned int program_uses_killpixel:1; - unsigned int legacy_line_rast: 1; - unsigned int transposed_urb_read:1; - unsigned int max_threads:7; - } wm5; - - float global_depth_offset_constant; - float global_depth_offset_scale; -}; - -/* The hardware supports two different modes for border color. The - * default (OpenGL) mode uses floating-point color channels, while the - * legacy mode uses 4 bytes. - * - * More significantly, the legacy mode respects the components of the - * border color for channels not present in the source, (whereas the - * default mode will ignore the border color's alpha channel and use - * alpha==1 for an RGB source, for example). - * - * The legacy mode matches the semantics specified by the Render - * extension. - */ -struct brw_sampler_default_border_color { - float color[4]; -}; - -struct brw_sampler_legacy_border_color { - uint8_t color[4]; -}; - -struct brw_sampler_state { - struct { - unsigned int shadow_function:3; - unsigned int lod_bias:11; - unsigned int min_filter:3; - unsigned int mag_filter:3; - unsigned int mip_filter:2; - unsigned int base_level:5; - unsigned int pad:1; - unsigned int lod_preclamp:1; - unsigned int border_color_mode:1; - unsigned int pad0:1; - unsigned int disable:1; - } ss0; - - struct { - unsigned int r_wrap_mode:3; - unsigned int t_wrap_mode:3; - unsigned int s_wrap_mode:3; - unsigned int pad:3; - unsigned int max_lod:10; - unsigned int min_lod:10; - } ss1; - - struct { - unsigned int pad:5; - unsigned int border_color_pointer:27; - } ss2; - - struct { - unsigned int pad:19; - unsigned int max_aniso:3; - unsigned int chroma_key_mode:1; - unsigned int chroma_key_index:2; - unsigned int chroma_key_enable:1; - unsigned int monochrome_filter_width:3; - unsigned int monochrome_filter_height:3; - } ss3; -}; - -struct brw_clipper_viewport { - float xmin; - float xmax; - float ymin; - float ymax; -}; - -struct brw_cc_viewport { - float min_depth; - float max_depth; -}; - -struct brw_sf_viewport { - struct { - float m00; - float m11; - float m22; - float m30; - float m31; - float m32; - } viewport; - - struct { - short xmin; - short ymin; - short xmax; - short ymax; - } scissor; -}; - -/* Documented in the subsystem/shared-functions/sampler chapter... -*/ -struct brw_surface_state { - struct { - unsigned int cube_pos_z:1; - unsigned int cube_neg_z:1; - unsigned int cube_pos_y:1; - unsigned int cube_neg_y:1; - unsigned int cube_pos_x:1; - unsigned int cube_neg_x:1; - unsigned int pad:3; - unsigned int render_cache_read_mode:1; - unsigned int mipmap_layout_mode:1; - unsigned int vert_line_stride_ofs:1; - unsigned int vert_line_stride:1; - unsigned int color_blend:1; - unsigned int writedisable_blue:1; - unsigned int writedisable_green:1; - unsigned int writedisable_red:1; - unsigned int writedisable_alpha:1; - unsigned int surface_format:9; - unsigned int data_return_format:1; - unsigned int pad0:1; - unsigned int surface_type:3; - } ss0; - - struct { - unsigned int base_addr; - } ss1; - - struct { - unsigned int render_target_rotation:2; - unsigned int mip_count:4; - unsigned int width:13; - unsigned int height:13; - } ss2; - - struct { - unsigned int tile_walk:1; - unsigned int tiled_surface:1; - unsigned int pad:1; - unsigned int pitch:18; - unsigned int depth:11; - } ss3; - - struct { - unsigned int pad:19; - unsigned int min_array_elt:9; - unsigned int min_lod:4; - } ss4; - - struct { - unsigned int pad:20; - unsigned int y_offset:4; - unsigned int pad2:1; - unsigned int x_offset:7; - } ss5; -}; - -struct brw_vertex_buffer_state { - struct { - unsigned int pitch:11; - unsigned int pad:15; - unsigned int access_type:1; - unsigned int vb_index:5; - } vb0; - - unsigned int start_addr; - unsigned int max_index; -#if 1 - unsigned int instance_data_step_rate; /* not included for sequential/random vertices? */ -#endif -}; - -#define BRW_VBP_MAX 17 - -struct brw_vb_array_state { - struct header header; - struct brw_vertex_buffer_state vb[BRW_VBP_MAX]; -}; - -struct brw_vertex_element_state { - struct { - unsigned int src_offset:11; - unsigned int pad:5; - unsigned int src_format:9; - unsigned int pad0:1; - unsigned int valid:1; - unsigned int vertex_buffer_index:5; - } ve0; - - struct { - unsigned int dst_offset:8; - unsigned int pad:8; - unsigned int vfcomponent3:4; - unsigned int vfcomponent2:4; - unsigned int vfcomponent1:4; - unsigned int vfcomponent0:4; - } ve1; -}; - -#define BRW_VEP_MAX 18 - -struct brw_vertex_element_packet { - struct header header; - struct brw_vertex_element_state ve[BRW_VEP_MAX]; -}; - -struct brw_urb_immediate { - unsigned int opcode:4; - unsigned int offset:6; - unsigned int swizzle_control:2; - unsigned int pad:1; - unsigned int allocate:1; - unsigned int used:1; - unsigned int complete:1; - unsigned int response_length:4; - unsigned int msg_length:4; - unsigned int msg_target:4; - unsigned int pad1:3; - unsigned int end_of_thread:1; -}; - -/* Instruction format for the execution units: */ - -struct brw_instruction { - struct { - unsigned int opcode:7; - unsigned int pad:1; - unsigned int access_mode:1; - unsigned int mask_control:1; - unsigned int dependency_control:2; - unsigned int compression_control:2; - unsigned int thread_control:2; - unsigned int predicate_control:4; - unsigned int predicate_inverse:1; - unsigned int execution_size:3; - unsigned int destreg__conditonalmod:4; /* destreg - send, conditionalmod - others */ - unsigned int pad0:2; - unsigned int debug_control:1; - unsigned int saturate:1; - } header; - - union { - struct { - unsigned int dest_reg_file:2; - unsigned int dest_reg_type:3; - unsigned int src0_reg_file:2; - unsigned int src0_reg_type:3; - unsigned int src1_reg_file:2; - unsigned int src1_reg_type:3; - unsigned int pad:1; - unsigned int dest_subreg_nr:5; - unsigned int dest_reg_nr:8; - unsigned int dest_horiz_stride:2; - unsigned int dest_address_mode:1; - } da1; - - struct { - unsigned int dest_reg_file:2; - unsigned int dest_reg_type:3; - unsigned int src0_reg_file:2; - unsigned int src0_reg_type:3; - unsigned int pad:6; - int dest_indirect_offset:10; /* offset against the deref'd address reg */ - unsigned int dest_subreg_nr:3; /* subnr for the address reg a0.x */ - unsigned int dest_horiz_stride:2; - unsigned int dest_address_mode:1; - } ia1; - - struct { - unsigned int dest_reg_file:2; - unsigned int dest_reg_type:3; - unsigned int src0_reg_file:2; - unsigned int src0_reg_type:3; - unsigned int src1_reg_file:2; - unsigned int src1_reg_type:3; - unsigned int pad0:1; - unsigned int dest_writemask:4; - unsigned int dest_subreg_nr:1; - unsigned int dest_reg_nr:8; - unsigned int pad1:2; - unsigned int dest_address_mode:1; - } da16; - - struct { - unsigned int dest_reg_file:2; - unsigned int dest_reg_type:3; - unsigned int src0_reg_file:2; - unsigned int src0_reg_type:3; - unsigned int pad0:6; - unsigned int dest_writemask:4; - int dest_indirect_offset:6; - unsigned int dest_subreg_nr:3; - unsigned int pad1:2; - unsigned int dest_address_mode:1; - } ia16; - } bits1; - - - union { - struct { - unsigned int src0_subreg_nr:5; - unsigned int src0_reg_nr:8; - unsigned int src0_abs:1; - unsigned int src0_negate:1; - unsigned int src0_address_mode:1; - unsigned int src0_horiz_stride:2; - unsigned int src0_width:3; - unsigned int src0_vert_stride:4; - unsigned int flag_reg_nr:1; - unsigned int pad:6; - } da1; - - struct { - int src0_indirect_offset:10; - unsigned int src0_subreg_nr:3; - unsigned int src0_abs:1; - unsigned int src0_negate:1; - unsigned int src0_address_mode:1; - unsigned int src0_horiz_stride:2; - unsigned int src0_width:3; - unsigned int src0_vert_stride:4; - unsigned int flag_reg_nr:1; - unsigned int pad:6; - } ia1; - - struct { - unsigned int src0_swz_x:2; - unsigned int src0_swz_y:2; - unsigned int src0_subreg_nr:1; - unsigned int src0_reg_nr:8; - unsigned int src0_abs:1; - unsigned int src0_negate:1; - unsigned int src0_address_mode:1; - unsigned int src0_swz_z:2; - unsigned int src0_swz_w:2; - unsigned int pad0:1; - unsigned int src0_vert_stride:4; - unsigned int flag_reg_nr:1; - unsigned int pad1:6; - } da16; - - struct { - unsigned int src0_swz_x:2; - unsigned int src0_swz_y:2; - int src0_indirect_offset:6; - unsigned int src0_subreg_nr:3; - unsigned int src0_abs:1; - unsigned int src0_negate:1; - unsigned int src0_address_mode:1; - unsigned int src0_swz_z:2; - unsigned int src0_swz_w:2; - unsigned int pad0:1; - unsigned int src0_vert_stride:4; - unsigned int flag_reg_nr:1; - unsigned int pad1:6; - } ia16; - - } bits2; - - union { - struct { - unsigned int src1_subreg_nr:5; - unsigned int src1_reg_nr:8; - unsigned int src1_abs:1; - unsigned int src1_negate:1; - unsigned int pad:1; - unsigned int src1_horiz_stride:2; - unsigned int src1_width:3; - unsigned int src1_vert_stride:4; - unsigned int pad0:7; - } da1; - - struct { - unsigned int src1_swz_x:2; - unsigned int src1_swz_y:2; - unsigned int src1_subreg_nr:1; - unsigned int src1_reg_nr:8; - unsigned int src1_abs:1; - unsigned int src1_negate:1; - unsigned int pad0:1; - unsigned int src1_swz_z:2; - unsigned int src1_swz_w:2; - unsigned int pad1:1; - unsigned int src1_vert_stride:4; - unsigned int pad2:7; - } da16; - - struct { - int src1_indirect_offset:10; - unsigned int src1_subreg_nr:3; - unsigned int src1_abs:1; - unsigned int src1_negate:1; - unsigned int pad0:1; - unsigned int src1_horiz_stride:2; - unsigned int src1_width:3; - unsigned int src1_vert_stride:4; - unsigned int flag_reg_nr:1; - unsigned int pad1:6; - } ia1; - - struct { - unsigned int src1_swz_x:2; - unsigned int src1_swz_y:2; - int src1_indirect_offset:6; - unsigned int src1_subreg_nr:3; - unsigned int src1_abs:1; - unsigned int src1_negate:1; - unsigned int pad0:1; - unsigned int src1_swz_z:2; - unsigned int src1_swz_w:2; - unsigned int pad1:1; - unsigned int src1_vert_stride:4; - unsigned int flag_reg_nr:1; - unsigned int pad2:6; - } ia16; - - struct { - int jump_count:16; /* note: signed */ - unsigned int pop_count:4; - unsigned int pad0:12; - } if_else; - - struct { - unsigned int function:4; - unsigned int int_type:1; - unsigned int precision:1; - unsigned int saturate:1; - unsigned int data_type:1; - unsigned int pad0:8; - unsigned int response_length:4; - unsigned int msg_length:4; - unsigned int msg_target:4; - unsigned int pad1:3; - unsigned int end_of_thread:1; - } math; - - struct { - unsigned int binding_table_index:8; - unsigned int sampler:4; - unsigned int return_format:2; - unsigned int msg_type:2; - unsigned int response_length:4; - unsigned int msg_length:4; - unsigned int msg_target:4; - unsigned int pad1:3; - unsigned int end_of_thread:1; - } sampler; - - struct { - uint32_t binding_table_index:8; - uint32_t sampler:4; - uint32_t msg_type:4; - uint32_t response_length:4; - uint32_t msg_length:4; - uint32_t msg_target:4; - uint32_t pad1:3; - uint32_t end_of_thread:1; - } sampler_g4x; - - struct brw_urb_immediate urb; - - struct { - unsigned int binding_table_index:8; - unsigned int msg_control:4; - unsigned int msg_type:2; - unsigned int target_cache:2; - unsigned int response_length:4; - unsigned int msg_length:4; - unsigned int msg_target:4; - unsigned int pad1:3; - unsigned int end_of_thread:1; - } dp_read; - - struct { - unsigned int binding_table_index:8; - unsigned int msg_control:3; - unsigned int pixel_scoreboard_clear:1; - unsigned int msg_type:3; - unsigned int send_commit_msg:1; - unsigned int response_length:4; - unsigned int msg_length:4; - unsigned int msg_target:4; - unsigned int pad1:3; - unsigned int end_of_thread:1; - } dp_write; - - struct { - unsigned int pad:16; - unsigned int response_length:4; - unsigned int msg_length:4; - unsigned int msg_target:4; - unsigned int pad1:3; - unsigned int end_of_thread:1; - } generic; - - uint32_t ud; - int32_t d; - } bits3; -}; - -/* media pipeline */ - -struct brw_vfe_state { - struct { - unsigned int per_thread_scratch_space:4; - unsigned int pad3:3; - unsigned int extend_vfe_state_present:1; - unsigned int pad2:2; - unsigned int scratch_base:22; - } vfe0; - - struct { - unsigned int debug_counter_control:2; - unsigned int children_present:1; - unsigned int vfe_mode:4; - unsigned int pad2:2; - unsigned int num_urb_entries:7; - unsigned int urb_entry_alloc_size:9; - unsigned int max_threads:7; - } vfe1; - - struct { - unsigned int pad4:4; - unsigned int interface_descriptor_base:28; - } vfe2; -}; - -struct brw_vld_state { - struct { - unsigned int pad6:6; - unsigned int scan_order:1; - unsigned int intra_vlc_format:1; - unsigned int quantizer_scale_type:1; - unsigned int concealment_motion_vector:1; - unsigned int frame_predict_frame_dct:1; - unsigned int top_field_first:1; - unsigned int picture_structure:2; - unsigned int intra_dc_precision:2; - unsigned int f_code_0_0:4; - unsigned int f_code_0_1:4; - unsigned int f_code_1_0:4; - unsigned int f_code_1_1:4; - } vld0; - - struct { - unsigned int pad2:9; - unsigned int picture_coding_type:2; - unsigned int pad:21; - } vld1; - - struct { - unsigned int index_0:4; - unsigned int index_1:4; - unsigned int index_2:4; - unsigned int index_3:4; - unsigned int index_4:4; - unsigned int index_5:4; - unsigned int index_6:4; - unsigned int index_7:4; - } desc_remap_table0; - - struct { - unsigned int index_8:4; - unsigned int index_9:4; - unsigned int index_10:4; - unsigned int index_11:4; - unsigned int index_12:4; - unsigned int index_13:4; - unsigned int index_14:4; - unsigned int index_15:4; - } desc_remap_table1; -}; - -struct brw_interface_descriptor { - struct { - unsigned int grf_reg_blocks:4; - unsigned int pad:2; - unsigned int kernel_start_pointer:26; - } desc0; - - struct { - unsigned int pad:7; - unsigned int software_exception:1; - unsigned int pad2:3; - unsigned int maskstack_exception:1; - unsigned int pad3:1; - unsigned int illegal_opcode_exception:1; - unsigned int pad4:2; - unsigned int floating_point_mode:1; - unsigned int thread_priority:1; - unsigned int single_program_flow:1; - unsigned int pad5:1; - unsigned int const_urb_entry_read_offset:6; - unsigned int const_urb_entry_read_len:6; - } desc1; - - struct { - unsigned int pad:2; - unsigned int sampler_count:3; - unsigned int sampler_state_pointer:27; - } desc2; - - struct { - unsigned int binding_table_entry_count:5; - unsigned int binding_table_pointer:27; - } desc3; -}; - -#endif diff --git a/gfx/cairo/cairo/src/drm/cairo-drm-intel-command-private.h b/gfx/cairo/cairo/src/drm/cairo-drm-intel-command-private.h deleted file mode 100644 index a93ac12ab5..0000000000 --- a/gfx/cairo/cairo/src/drm/cairo-drm-intel-command-private.h +++ /dev/null @@ -1,909 +0,0 @@ -/************************************************************************** - * - * Copyright 2003 Tungsten Graphics, Inc., Cedar Park, Texas. - * All Rights Reserved. - * - * Permission is hereby granted, free of charge, to any person obtaining a - * copy of this software and associated documentation files (the - * "Software"), to deal in the Software without restriction, including - * without limitation the rights to use, copy, modify, merge, publish, - * distribute, sub license, and/or sell copies of the Software, and to - * permit persons to whom the Software is furnished to do so, subject to - * the following conditions: - * - * The above copyright notice and this permission notice (including the - * next paragraph) shall be included in all copies or substantial portions - * of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS - * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. - * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR - * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, - * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE - * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - * - **************************************************************************/ - -#ifndef CAIRO_DRM_INTEL_COMMAND_PRIVATE_H -#define CAIRO_DRM_INTEL_COMMAND_PRIVATE_H - -#include "cairo-types-private.h" - -#define CMD_MI (0x0 << 29) -#define CMD_misc (0x1 << 29) -#define CMD_2D (0x2 << 29) -#define CMD_3D (0x3 << 29) -/* 4-7 reserved */ - -#define MI_NOOP (CMD_MI | 0) -/* Batch */ -#define MI_BATCH_BUFFER (CMD_MI | (0x30 << 23) | 1) -#define MI_BATCH_BUFFER_START (CMD_MI | (0x31 << 23)) -#define MI_BATCH_BUFFER_END (CMD_MI | (0x0a << 23)) -#define MI_BATCH_NON_SECURE (1) -#define MI_BATCH_NON_SECURE_I965 (1 << 8) -/* Flush */ -#define MI_FLUSH (CMD_MI | (0x04 << 23)) -#define MI_WRITE_DIRTY_STATE (1<<4) -#define MI_END_SCENE (1<<3) -#define MI_GLOBAL_SNAPSHOT_COUNT_RESET (1<<3) -#define MI_INHIBIT_RENDER_CACHE_FLUSH (1<<2) -#define MI_STATE_INSTRUCTION_CACHE_FLUSH (1<<1) -#define MI_INVALIDATE_MAP_CACHE (1<<0) - -#define PRIM3D (CMD_3D | (0x1f<<24)) -#define PRIM3D_TRILIST (PRIM3D | (0x0<<18)) -#define PRIM3D_TRISTRIP (PRIM3D | (0x1<<18)) -#define PRIM3D_TRISTRIP_RVRSE (PRIM3D | (0x2<<18)) -#define PRIM3D_TRIFAN (PRIM3D | (0x3<<18)) -#define PRIM3D_POLY (PRIM3D | (0x4<<18)) -#define PRIM3D_LINELIST (PRIM3D | (0x5<<18)) -#define PRIM3D_LINESTRIP (PRIM3D | (0x6<<18)) -#define PRIM3D_RECTLIST (PRIM3D | (0x7<<18)) -#define PRIM3D_POINTLIST (PRIM3D | (0x8<<18)) -#define PRIM3D_DIB (PRIM3D | (0x9<<18)) -#define PRIM3D_CLEAR_RECT (PRIM3D | (0xa<<18)) -#define PRIM3D_ZONE_INIT (PRIM3D | (0xd<<18)) -#define PRIM3D_MASK (0x1f<<18) -#define PRIM3D_INDIRECT_SEQUENTIAL ((1<<23) | (0<<17)) -#define PRIM3D_INDIRECT_ELTS ((1<<23) | (1<<17)) - -/* p137 */ -#define _3DSTATE_AA_CMD (CMD_3D | (0x06<<24)) -#define AA_LINE_ECAAR_WIDTH_ENABLE (1<<16) -#define AA_LINE_ECAAR_WIDTH_0_5 0 -#define AA_LINE_ECAAR_WIDTH_1_0 (1<<14) -#define AA_LINE_ECAAR_WIDTH_2_0 (2<<14) -#define AA_LINE_ECAAR_WIDTH_4_0 (3<<14) -#define AA_LINE_REGION_WIDTH_ENABLE (1<<8) -#define AA_LINE_REGION_WIDTH_0_5 0 -#define AA_LINE_REGION_WIDTH_1_0 (1<<6) -#define AA_LINE_REGION_WIDTH_2_0 (2<<6) -#define AA_LINE_REGION_WIDTH_4_0 (3<<6) - -/* 3DSTATE_BACKFACE_STENCIL_OPS, p138*/ -#define _3DSTATE_BACKFACE_STENCIL_OPS (CMD_3D | (0x8<<24)) -#define BFO_ENABLE_STENCIL_REF (1<<23) -#define BFO_STENCIL_REF_SHIFT 15 -#define BFO_STENCIL_REF_MASK (0xff<<15) -#define BFO_ENABLE_STENCIL_FUNCS (1<<14) -#define BFO_STENCIL_TEST_SHIFT 11 -#define BFO_STENCIL_TEST_MASK (0x7<<11) -#define BFO_STENCIL_FAIL_SHIFT 8 -#define BFO_STENCIL_FAIL_MASK (0x7<<8) -#define BFO_STENCIL_PASS_Z_FAIL_SHIFT 5 -#define BFO_STENCIL_PASS_Z_FAIL_MASK (0x7<<5) -#define BFO_STENCIL_PASS_Z_PASS_SHIFT 2 -#define BFO_STENCIL_PASS_Z_PASS_MASK (0x7<<2) -#define BFO_ENABLE_STENCIL_TWO_SIDE (1<<1) -#define BFO_STENCIL_TWO_SIDE (1<<0) - -/* 3DSTATE_BACKFACE_STENCIL_MASKS, p140 */ -#define _3DSTATE_BACKFACE_STENCIL_MASKS (CMD_3D | (0x9<<24)) -#define BFM_ENABLE_STENCIL_TEST_MASK (1<<17) -#define BFM_ENABLE_STENCIL_WRITE_MASK (1<<16) -#define BFM_STENCIL_TEST_MASK_SHIFT 8 -#define BFM_STENCIL_TEST_MASK_MASK (0xff<<8) -#define BFM_STENCIL_WRITE_MASK_SHIFT 0 -#define BFM_STENCIL_WRITE_MASK_MASK (0xff<<0) - -/* 3DSTATE_BIN_CONTROL p141 */ - -/* p143 */ -#define _3DSTATE_BUF_INFO_CMD (CMD_3D | (0x1d<<24) | (0x8e<<16) | 1) -/* Dword 1 */ -#define BUF_3D_ID_COLOR_BACK (0x3<<24) -#define BUF_3D_ID_DEPTH (0x7<<24) -#define BUF_3D_USE_FENCE (1<<23) -#define BUF_3D_TILED_SURFACE (1<<22) -#define BUF_3D_TILE_WALK_X 0 -#define BUF_3D_TILE_WALK_Y (1<<21) -#define BUF_3D_PITCH(x) (x) -/* Dword 2 */ -#define BUF_3D_ADDR(x) ((x) & ~0x3) - -/* 3DSTATE_CHROMA_KEY */ - -/* 3DSTATE_CLEAR_PARAMETERS, p150 */ -#define _3DSTATE_CLEAR_PARAMETERS (CMD_3D | (0x1d<<24) | (0x9c<<16) | 5) -/* Dword 1 */ -#define CLEARPARAM_CLEAR_RECT (1 << 16) -#define CLEARPARAM_ZONE_INIT (0 << 16) -#define CLEARPARAM_WRITE_COLOR (1 << 2) -#define CLEARPARAM_WRITE_DEPTH (1 << 1) -#define CLEARPARAM_WRITE_STENCIL (1 << 0) - -/* 3DSTATE_CONSTANT_BLEND_COLOR, p153 */ -#define _3DSTATE_CONST_BLEND_COLOR_CMD (CMD_3D | (0x1d<<24) | (0x88<<16)) - -/* 3DSTATE_COORD_SET_BINDINGS, p154 */ -#define _3DSTATE_COORD_SET_BINDINGS (CMD_3D | (0x16<<24)) -#define CSB_TCB(iunit, eunit) ((eunit)<<(iunit*3)) - -/* p156 */ -#define _3DSTATE_DFLT_DIFFUSE_CMD (CMD_3D | (0x1d<<24) | (0x99<<16)) - -/* p157 */ -#define _3DSTATE_DFLT_SPEC_CMD (CMD_3D | (0x1d<<24) | (0x9a<<16)) - -/* p158 */ -#define _3DSTATE_DFLT_Z_CMD (CMD_3D | (0x1d<<24) | (0x98<<16)) - -/* 3DSTATE_DEPTH_OFFSET_SCALE, p159 */ -#define _3DSTATE_DEPTH_OFFSET_SCALE (CMD_3D | (0x1d<<24) | (0x97<<16)) -/* scale in dword 1 */ - -/* The depth subrectangle is not supported, but must be disabled. */ -/* 3DSTATE_DEPTH_SUBRECT_DISABLE, p160 */ -#define _3DSTATE_DEPTH_SUBRECT_DISABLE (CMD_3D | (0x1c<<24) | (0x11<<19) | (1 << 1) | (0 << 0)) - -/* p161 */ -#define _3DSTATE_DST_BUF_VARS_CMD (CMD_3D | (0x1d<<24) | (0x85<<16)) -/* Dword 1 */ -#define TEX_DEFAULT_COLOR_OGL (0<<30) -#define TEX_DEFAULT_COLOR_D3D (1<<30) -#define ZR_EARLY_DEPTH (1<<29) -#define LOD_PRECLAMP_OGL (1<<28) -#define LOD_PRECLAMP_D3D (0<<28) -#define DITHER_FULL_ALWAYS (0<<26) -#define DITHER_FULL_ON_FB_BLEND (1<<26) -#define DITHER_CLAMPED_ALWAYS (2<<26) -#define LINEAR_GAMMA_BLEND_32BPP (1<<25) -#define DEBUG_DISABLE_ENH_DITHER (1<<24) -#define DSTORG_HORT_BIAS(x) ((x)<<20) -#define DSTORG_VERT_BIAS(x) ((x)<<16) -#define COLOR_4_2_2_CHNL_WRT_ALL 0 -#define COLOR_4_2_2_CHNL_WRT_Y (1<<12) -#define COLOR_4_2_2_CHNL_WRT_CR (2<<12) -#define COLOR_4_2_2_CHNL_WRT_CB (3<<12) -#define COLOR_4_2_2_CHNL_WRT_CRCB (4<<12) -#define COLR_BUF_8BIT 0 -#define COLR_BUF_RGB555 (1<<8) -#define COLR_BUF_RGB565 (2<<8) -#define COLR_BUF_ARGB8888 (3<<8) -#define COLR_BUF_ARGB4444 (8<<8) -#define COLR_BUF_ARGB1555 (9<<8) -#define COLR_BUF_ARGB2AAA (0xa<<8) -#define DEPTH_FRMT_16_FIXED 0 -#define DEPTH_FRMT_16_FLOAT (1<<2) -#define DEPTH_FRMT_24_FIXED_8_OTHER (2<<2) -#define VERT_LINE_STRIDE_1 (1<<1) -#define VERT_LINE_STRIDE_0 (0<<1) -#define VERT_LINE_STRIDE_OFS_1 1 -#define VERT_LINE_STRIDE_OFS_0 0 - -/* p166 */ -#define _3DSTATE_DRAW_RECT_CMD (CMD_3D|(0x1d<<24)|(0x80<<16)|3) -/* Dword 1 */ -#define DRAW_RECT_DIS_DEPTH_OFS (1<<30) -#define DRAW_DITHER_OFS_X(x) ((x)<<26) -#define DRAW_DITHER_OFS_Y(x) ((x)<<24) -/* Dword 2 */ -#define DRAW_YMIN(x) ((x)<<16) -#define DRAW_XMIN(x) (x) -/* Dword 3 */ -#define DRAW_YMAX(x) ((x-1)<<16) -#define DRAW_XMAX(x) (x-1) -/* Dword 4 */ -#define DRAW_YORG(x) ((x)<<16) -#define DRAW_XORG(x) (x) - -/* 3DSTATE_FILTER_COEFFICIENTS_4X4, p170 */ - -/* 3DSTATE_FILTER_COEFFICIENTS_6X5, p172 */ - -/* _3DSTATE_FOG_COLOR, p173 */ -#define _3DSTATE_FOG_COLOR_CMD (CMD_3D|(0x15<<24)) -#define FOG_COLOR_RED(x) ((x)<<16) -#define FOG_COLOR_GREEN(x) ((x)<<8) -#define FOG_COLOR_BLUE(x) (x) - -/* _3DSTATE_FOG_MODE, p174 */ -#define _3DSTATE_FOG_MODE_CMD (CMD_3D|(0x1d<<24)|(0x89<<16)|2) -/* Dword 1 */ -#define FMC1_FOGFUNC_MODIFY_ENABLE (1<<31) -#define FMC1_FOGFUNC_VERTEX (0<<28) -#define FMC1_FOGFUNC_PIXEL_EXP (1<<28) -#define FMC1_FOGFUNC_PIXEL_EXP2 (2<<28) -#define FMC1_FOGFUNC_PIXEL_LINEAR (3<<28) -#define FMC1_FOGFUNC_MASK (3<<28) -#define FMC1_FOGINDEX_MODIFY_ENABLE (1<<27) -#define FMC1_FOGINDEX_Z (0<<25) -#define FMC1_FOGINDEX_W (1<<25) -#define FMC1_C1_C2_MODIFY_ENABLE (1<<24) -#define FMC1_DENSITY_MODIFY_ENABLE (1<<23) -#define FMC1_C1_ONE (1<<13) -#define FMC1_C1_MASK (0xffff<<4) -/* Dword 2 */ -#define FMC2_C2_ONE (1<<16) -/* Dword 3 */ -#define FMC3_D_ONE (1<<16) - -/* _3DSTATE_INDEPENDENT_ALPHA_BLEND, p177 */ -#define _3DSTATE_INDEPENDENT_ALPHA_BLEND_CMD (CMD_3D|(0x0b<<24)) -#define IAB_MODIFY_ENABLE (1<<23) -#define IAB_ENABLE (1<<22) -#define IAB_MODIFY_FUNC (1<<21) -#define IAB_FUNC_SHIFT 16 -#define IAB_MODIFY_SRC_FACTOR (1<<11) -#define IAB_SRC_FACTOR_SHIFT 6 -#define IAB_SRC_FACTOR_MASK (BLENDFACT_MASK<<6) -#define IAB_MODIFY_DST_FACTOR (1<<5) -#define IAB_DST_FACTOR_SHIFT 0 -#define IAB_DST_FACTOR_MASK (BLENDFACT_MASK<<0) - -#define BLENDFACT_ZERO 0x01 -#define BLENDFACT_ONE 0x02 -#define BLENDFACT_SRC_COLR 0x03 -#define BLENDFACT_INV_SRC_COLR 0x04 -#define BLENDFACT_SRC_ALPHA 0x05 -#define BLENDFACT_INV_SRC_ALPHA 0x06 -#define BLENDFACT_DST_ALPHA 0x07 -#define BLENDFACT_INV_DST_ALPHA 0x08 -#define BLENDFACT_DST_COLR 0x09 -#define BLENDFACT_INV_DST_COLR 0x0a -#define BLENDFACT_SRC_ALPHA_SATURATE 0x0b -#define BLENDFACT_CONST_COLOR 0x0c -#define BLENDFACT_INV_CONST_COLOR 0x0d -#define BLENDFACT_CONST_ALPHA 0x0e -#define BLENDFACT_INV_CONST_ALPHA 0x0f -#define BLENDFACT_MASK 0x0f - -#define BLENDFUNC_ADD 0x0 -#define BLENDFUNC_SUBTRACT 0x1 -#define BLENDFUNC_REVERSE_SUBTRACT 0x2 -#define BLENDFUNC_MIN 0x3 -#define BLENDFUNC_MAX 0x4 -#define BLENDFUNC_MASK 0x7 - -/* 3DSTATE_LOAD_INDIRECT, p180 */ - -#define _3DSTATE_LOAD_INDIRECT (CMD_3D|(0x1d<<24)|(0x7<<16)) -#define LI0_STATE_STATIC_INDIRECT (0x01<<8) -#define LI0_STATE_DYNAMIC_INDIRECT (0x02<<8) -#define LI0_STATE_SAMPLER (0x04<<8) -#define LI0_STATE_MAP (0x08<<8) -#define LI0_STATE_PROGRAM (0x10<<8) -#define LI0_STATE_CONSTANTS (0x20<<8) - -#define SIS0_BUFFER_ADDRESS(x) ((x)&~0x3) -#define SIS0_FORCE_LOAD (1<<1) -#define SIS0_BUFFER_VALID (1<<0) -#define SIS1_BUFFER_LENGTH(x) ((x)&0xff) - -#define DIS0_BUFFER_ADDRESS(x) ((x)&~0x3) -#define DIS0_BUFFER_RESET (1<<1) -#define DIS0_BUFFER_VALID (1<<0) - -#define SSB0_BUFFER_ADDRESS(x) ((x)&~0x3) -#define SSB0_FORCE_LOAD (1<<1) -#define SSB0_BUFFER_VALID (1<<0) -#define SSB1_BUFFER_LENGTH(x) ((x)&0xff) - -#define MSB0_BUFFER_ADDRESS(x) ((x)&~0x3) -#define MSB0_FORCE_LOAD (1<<1) -#define MSB0_BUFFER_VALID (1<<0) -#define MSB1_BUFFER_LENGTH(x) ((x)&0xff) - -#define PSP0_BUFFER_ADDRESS(x) ((x)&~0x3) -#define PSP0_FORCE_LOAD (1<<1) -#define PSP0_BUFFER_VALID (1<<0) -#define PSP1_BUFFER_LENGTH(x) ((x)&0xff) - -#define PSC0_BUFFER_ADDRESS(x) ((x)&~0x3) -#define PSC0_FORCE_LOAD (1<<1) -#define PSC0_BUFFER_VALID (1<<0) -#define PSC1_BUFFER_LENGTH(x) ((x)&0xff) - -/* _3DSTATE_RASTERIZATION_RULES */ -#define _3DSTATE_RASTER_RULES_CMD (CMD_3D|(0x07<<24)) -#define ENABLE_POINT_RASTER_RULE (1<<15) -#define OGL_POINT_RASTER_RULE (1<<13) -#define ENABLE_TEXKILL_3D_4D (1<<10) -#define TEXKILL_3D (0<<9) -#define TEXKILL_4D (1<<9) -#define ENABLE_LINE_STRIP_PROVOKE_VRTX (1<<8) -#define ENABLE_TRI_FAN_PROVOKE_VRTX (1<<5) -#define LINE_STRIP_PROVOKE_VRTX(x) ((x)<<6) -#define TRI_FAN_PROVOKE_VRTX(x) ((x)<<3) - -/* _3DSTATE_SCISSOR_ENABLE, p256 */ -#define _3DSTATE_SCISSOR_ENABLE_CMD (CMD_3D|(0x1c<<24)|(0x10<<19)) -#define ENABLE_SCISSOR_RECT ((1<<1) | 1) -#define DISABLE_SCISSOR_RECT (1<<1) - -/* _3DSTATE_SCISSOR_RECTANGLE_0, p257 */ -#define _3DSTATE_SCISSOR_RECT_0_CMD (CMD_3D|(0x1d<<24)|(0x81<<16)|1) -/* Dword 1 */ -#define SCISSOR_RECT_0_YMIN(x) ((x)<<16) -#define SCISSOR_RECT_0_XMIN(x) (x) -/* Dword 2 */ -#define SCISSOR_RECT_0_YMAX(x) ((x)<<16) -#define SCISSOR_RECT_0_XMAX(x) (x) - -/* p189 */ -#define _3DSTATE_LOAD_STATE_IMMEDIATE_1 (CMD_3D | (0x1d<<24) | (0x04<<16)) -#define I1_LOAD_S(n) (1<<(4+n)) - -#define S0_VB_OFFSET_MASK 0xffffffc -#define S0_AUTO_CACHE_INV_DISABLE (1<<0) - -#define S1_VERTEX_WIDTH_SHIFT 24 -#define S1_VERTEX_WIDTH_MASK (0x3f<<24) -#define S1_VERTEX_PITCH_SHIFT 16 -#define S1_VERTEX_PITCH_MASK (0x3f<<16) - -#define TEXCOORDFMT_2D 0x0 -#define TEXCOORDFMT_3D 0x1 -#define TEXCOORDFMT_4D 0x2 -#define TEXCOORDFMT_1D 0x3 -#define TEXCOORDFMT_2D_16 0x4 -#define TEXCOORDFMT_4D_16 0x5 -#define TEXCOORDFMT_NOT_PRESENT 0xf -#define S2_TEXCOORD_FMT0_MASK 0xf -#define S2_TEXCOORD_FMT1_SHIFT 4 -#define S2_TEXCOORD_FMT(unit, type) ((type)<<(unit*4)) -#define S2_TEXCOORD_NONE (~0U) - -#define TEXCOORD_WRAP_SHORTEST_TCX 8 -#define TEXCOORD_WRAP_SHORTEST_TCY 4 -#define TEXCOORD_WRAP_SHORTEST_TCZ 2 -#define TEXCOORD_PERSPECTIVE_DISABLE 1 - -#define S3_WRAP_SHORTEST_TCX(unit) (TEXCOORD_WRAP_SHORTEST_TCX << ((unit) * 4)) -#define S3_WRAP_SHORTEST_TCY(unit) (TEXCOORD_WRAP_SHORTEST_TCY << ((unit) * 4)) -#define S3_WRAP_SHORTEST_TCZ(unit) (TEXCOORD_WRAP_SHORTEST_TCZ << ((unit) * 4)) -#define S3_PERSPECTIVE_DISABLE(unit) (TEXCOORD_PERSPECTIVE_DISABLE << ((unit) * 4)) - -/* S3 not interesting */ - -#define S4_POINT_WIDTH_SHIFT 23 -#define S4_POINT_WIDTH_MASK (0x1ff<<23) -#define S4_LINE_WIDTH_SHIFT 19 -#define S4_LINE_WIDTH_ONE (0x2<<19) -#define S4_LINE_WIDTH_MASK (0xf<<19) -#define S4_FLATSHADE_ALPHA (1<<18) -#define S4_FLATSHADE_FOG (1<<17) -#define S4_FLATSHADE_SPECULAR (1<<16) -#define S4_FLATSHADE_COLOR (1<<15) -#define S4_CULLMODE_BOTH (0<<13) -#define S4_CULLMODE_NONE (1<<13) -#define S4_CULLMODE_CW (2<<13) -#define S4_CULLMODE_CCW (3<<13) -#define S4_CULLMODE_MASK (3<<13) -#define S4_VFMT_POINT_WIDTH (1<<12) -#define S4_VFMT_SPEC_FOG (1<<11) -#define S4_VFMT_COLOR (1<<10) -#define S4_VFMT_DEPTH_OFFSET (1<<9) -#define S4_VFMT_XYZ (1<<6) -#define S4_VFMT_XYZW (2<<6) -#define S4_VFMT_XY (3<<6) -#define S4_VFMT_XYW (4<<6) -#define S4_VFMT_XYZW_MASK (7<<6) -#define S4_FORCE_DEFAULT_DIFFUSE (1<<5) -#define S4_FORCE_DEFAULT_SPECULAR (1<<4) -#define S4_LOCAL_DEPTH_OFFSET_ENABLE (1<<3) -#define S4_VFMT_FOG_PARAM (1<<2) -#define S4_SPRITE_POINT_ENABLE (1<<1) -#define S4_LINE_ANTIALIAS_ENABLE (1<<0) - -#define S4_VFMT_MASK (S4_VFMT_POINT_WIDTH | \ - S4_VFMT_SPEC_FOG | \ - S4_VFMT_COLOR | \ - S4_VFMT_DEPTH_OFFSET | \ - S4_VFMT_XYZW_MASK | \ - S4_VFMT_FOG_PARAM) - -#define S5_WRITEDISABLE_ALPHA (1<<31) -#define S5_WRITEDISABLE_RED (1<<30) -#define S5_WRITEDISABLE_GREEN (1<<29) -#define S5_WRITEDISABLE_BLUE (1<<28) -#define S5_WRITEDISABLE_MASK (0xf<<28) -#define S5_FORCE_DEFAULT_POINT_SIZE (1<<27) -#define S5_LAST_PIXEL_ENABLE (1<<26) -#define S5_GLOBAL_DEPTH_OFFSET_ENABLE (1<<25) -#define S5_FOG_ENABLE (1<<24) -#define S5_STENCIL_REF_SHIFT 16 -#define S5_STENCIL_REF_MASK (0xff<<16) -#define S5_STENCIL_TEST_FUNC_SHIFT 13 -#define S5_STENCIL_TEST_FUNC_MASK (0x7<<13) -#define S5_STENCIL_FAIL_SHIFT 10 -#define S5_STENCIL_FAIL_MASK (0x7<<10) -#define S5_STENCIL_PASS_Z_FAIL_SHIFT 7 -#define S5_STENCIL_PASS_Z_FAIL_MASK (0x7<<7) -#define S5_STENCIL_PASS_Z_PASS_SHIFT 4 -#define S5_STENCIL_PASS_Z_PASS_MASK (0x7<<4) -#define S5_STENCIL_WRITE_ENABLE (1<<3) -#define S5_STENCIL_TEST_ENABLE (1<<2) -#define S5_COLOR_DITHER_ENABLE (1<<1) -#define S5_LOGICOP_ENABLE (1<<0) - -#define COMPAREFUNC_ALWAYS 0 -#define COMPAREFUNC_NEVER 0x1 -#define COMPAREFUNC_LESS 0x2 -#define COMPAREFUNC_EQUAL 0x3 -#define COMPAREFUNC_LEQUAL 0x4 -#define COMPAREFUNC_GREATER 0x5 -#define COMPAREFUNC_NOTEQUAL 0x6 -#define COMPAREFUNC_GEQUAL 0x7 - -#define STENCILOP_KEEP 0 -#define STENCILOP_ZERO 0x1 -#define STENCILOP_REPLACE 0x2 -#define STENCILOP_INCRSAT 0x3 -#define STENCILOP_DECRSAT 0x4 -#define STENCILOP_INCR 0x5 -#define STENCILOP_DECR 0x6 -#define STENCILOP_INVERT 0x7 - -#define S6_ALPHA_TEST_ENABLE (1<<31) -#define S6_ALPHA_TEST_FUNC_SHIFT 28 -#define S6_ALPHA_TEST_FUNC_MASK (0x7<<28) -#define S6_ALPHA_REF_SHIFT 20 -#define S6_ALPHA_REF_MASK (0xff<<20) -#define S6_DEPTH_TEST_ENABLE (1<<19) -#define S6_DEPTH_TEST_FUNC_SHIFT 16 -#define S6_DEPTH_TEST_FUNC_MASK (0x7<<16) -#define S6_CBUF_BLEND_ENABLE (1<<15) -#define S6_CBUF_BLEND_FUNC_SHIFT 12 -#define S6_CBUF_BLEND_FUNC_MASK (0x7<<12) -#define S6_CBUF_SRC_BLEND_FACT_SHIFT 8 -#define S6_CBUF_SRC_BLEND_FACT_MASK (0xf<<8) -#define S6_CBUF_DST_BLEND_FACT_SHIFT 4 -#define S6_CBUF_DST_BLEND_FACT_MASK (0xf<<4) -#define S6_DEPTH_WRITE_ENABLE (1<<3) -#define S6_COLOR_WRITE_ENABLE (1<<2) -#define S6_TRISTRIP_PV_SHIFT 0 -#define S6_TRISTRIP_PV_MASK (0x3<<0) - -#define S7_DEPTH_OFFSET_CONST_MASK ~0 - -/* 3DSTATE_MAP_DEINTERLACER_PARAMETERS */ -/* 3DSTATE_MAP_PALETTE_LOAD_32, p206 */ - -/* _3DSTATE_MODES_4, p218 */ -#define _3DSTATE_MODES_4_CMD (CMD_3D|(0x0d<<24)) -#define ENABLE_LOGIC_OP_FUNC (1<<23) -#define LOGIC_OP_FUNC(x) ((x)<<18) -#define LOGICOP_MASK (0xf<<18) -#define LOGICOP_COPY 0xc -#define MODE4_ENABLE_STENCIL_TEST_MASK ((1<<17)|(0xff00)) -#define ENABLE_STENCIL_TEST_MASK (1<<17) -#define STENCIL_TEST_MASK(x) ((x)<<8) -#define MODE4_ENABLE_STENCIL_WRITE_MASK ((1<<16)|(0x00ff)) -#define ENABLE_STENCIL_WRITE_MASK (1<<16) -#define STENCIL_WRITE_MASK(x) ((x)&0xff) - -/* _3DSTATE_MODES_5, p220 */ -#define _3DSTATE_MODES_5_CMD (CMD_3D|(0x0c<<24)) -#define PIPELINE_FLUSH_RENDER_CACHE (1<<18) -#define PIPELINE_FLUSH_TEXTURE_CACHE (1<<16) - -/* p221 */ -#define _3DSTATE_PIXEL_SHADER_CONSTANTS (CMD_3D|(0x1d<<24)|(0x6<<16)) -#define PS1_REG(n) (1<<(n)) -#define PS2_CONST_X(n) (n) -#define PS3_CONST_Y(n) (n) -#define PS4_CONST_Z(n) (n) -#define PS5_CONST_W(n) (n) - -/* p222 */ - -#define I915_MAX_TEX_INDIRECT 4 -#define I915_MAX_TEX_INSN 32 -#define I915_MAX_ALU_INSN 64 -#define I915_MAX_DECL_INSN 27 -#define I915_MAX_TEMPORARY 16 - -/* Each instruction is 3 dwords long, though most don't require all - * this space. Maximum of 123 instructions. Smaller maxes per insn - * type. - */ -#define _3DSTATE_PIXEL_SHADER_PROGRAM (CMD_3D|(0x1d<<24)|(0x5<<16)) - -#define REG_TYPE_R 0 /* temporary regs, no need to - * dcl, must be written before - * read -- Preserved between - * phases. - */ -#define REG_TYPE_T 1 /* Interpolated values, must be - * dcl'ed before use. - * - * 0..7: texture coord, - * 8: diffuse spec, - * 9: specular color, - * 10: fog parameter in w. - */ -#define REG_TYPE_CONST 2 /* Restriction: only one const - * can be referenced per - * instruction, though it may be - * selected for multiple inputs. - * Constants not initialized - * default to zero. - */ -#define REG_TYPE_S 3 /* sampler */ -#define REG_TYPE_OC 4 /* output color (rgba) */ -#define REG_TYPE_OD 5 /* output depth (w), xyz are - * temporaries. If not written, - * interpolated depth is used? - */ -#define REG_TYPE_U 6 /* unpreserved temporaries */ -#define REG_TYPE_MASK 0x7 -#define REG_NR_MASK 0xf - -/* REG_TYPE_T: - */ -#define T_TEX0 0 -#define T_TEX1 1 -#define T_TEX2 2 -#define T_TEX3 3 -#define T_TEX4 4 -#define T_TEX5 5 -#define T_TEX6 6 -#define T_TEX7 7 -#define T_DIFFUSE 8 -#define T_SPECULAR 9 -#define T_FOG_W 10 /* interpolated fog is in W coord */ - -/* Arithmetic instructions */ - -/* .replicate_swizzle == selection and replication of a particular - * scalar channel, ie., .xxxx, .yyyy, .zzzz or .wwww - */ -#define A0_NOP (0x0<<24) /* no operation */ -#define A0_ADD (0x1<<24) /* dst = src0 + src1 */ -#define A0_MOV (0x2<<24) /* dst = src0 */ -#define A0_MUL (0x3<<24) /* dst = src0 * src1 */ -#define A0_MAD (0x4<<24) /* dst = src0 * src1 + src2 */ -#define A0_DP2ADD (0x5<<24) /* dst.xyzw = src0.xy dot src1.xy + src2.replicate_swizzle */ -#define A0_DP3 (0x6<<24) /* dst.xyzw = src0.xyz dot src1.xyz */ -#define A0_DP4 (0x7<<24) /* dst.xyzw = src0.xyzw dot src1.xyzw */ -#define A0_FRC (0x8<<24) /* dst = src0 - floor(src0) */ -#define A0_RCP (0x9<<24) /* dst.xyzw = 1/(src0.replicate_swizzle) */ -#define A0_RSQ (0xa<<24) /* dst.xyzw = 1/(sqrt(abs(src0.replicate_swizzle))) */ -#define A0_EXP (0xb<<24) /* dst.xyzw = exp2(src0.replicate_swizzle) */ -#define A0_LOG (0xc<<24) /* dst.xyzw = log2(abs(src0.replicate_swizzle)) */ -#define A0_CMP (0xd<<24) /* dst = (src0 >= 0.0) ? src1 : src2 */ -#define A0_MIN (0xe<<24) /* dst = (src0 < src1) ? src0 : src1 */ -#define A0_MAX (0xf<<24) /* dst = (src0 >= src1) ? src0 : src1 */ -#define A0_FLR (0x10<<24) /* dst = floor(src0) */ -#define A0_MOD (0x11<<24) /* dst = src0 fmod 1.0 */ -#define A0_TRC (0x12<<24) /* dst = int(src0) */ -#define A0_SGE (0x13<<24) /* dst = src0 >= src1 ? 1.0 : 0.0 */ -#define A0_SLT (0x14<<24) /* dst = src0 < src1 ? 1.0 : 0.0 */ -#define A0_DEST_SATURATE (1<<22) -#define A0_DEST_TYPE_SHIFT 19 -/* Allow: R, OC, OD, U */ -#define A0_DEST_NR_SHIFT 14 -/* Allow R: 0..15, OC,OD: 0..0, U: 0..2 */ -#define A0_DEST_CHANNEL_X (1<<10) -#define A0_DEST_CHANNEL_Y (2<<10) -#define A0_DEST_CHANNEL_Z (4<<10) -#define A0_DEST_CHANNEL_W (8<<10) -#define A0_DEST_CHANNEL_ALL (0xf<<10) -#define A0_DEST_CHANNEL_SHIFT 10 -#define A0_SRC0_TYPE_SHIFT 7 -#define A0_SRC0_NR_SHIFT 2 - -#define A0_DEST_CHANNEL_XY (A0_DEST_CHANNEL_X|A0_DEST_CHANNEL_Y) -#define A0_DEST_CHANNEL_XYZ (A0_DEST_CHANNEL_XY|A0_DEST_CHANNEL_Z) - -#define SRC_X 0 -#define SRC_Y 1 -#define SRC_Z 2 -#define SRC_W 3 -#define SRC_ZERO 4 -#define SRC_ONE 5 - -#define A1_SRC0_CHANNEL_X_NEGATE (1<<31) -#define A1_SRC0_CHANNEL_X_SHIFT 28 -#define A1_SRC0_CHANNEL_Y_NEGATE (1<<27) -#define A1_SRC0_CHANNEL_Y_SHIFT 24 -#define A1_SRC0_CHANNEL_Z_NEGATE (1<<23) -#define A1_SRC0_CHANNEL_Z_SHIFT 20 -#define A1_SRC0_CHANNEL_W_NEGATE (1<<19) -#define A1_SRC0_CHANNEL_W_SHIFT 16 -#define A1_SRC1_TYPE_SHIFT 13 -#define A1_SRC1_NR_SHIFT 8 -#define A1_SRC1_CHANNEL_X_NEGATE (1<<7) -#define A1_SRC1_CHANNEL_X_SHIFT 4 -#define A1_SRC1_CHANNEL_Y_NEGATE (1<<3) -#define A1_SRC1_CHANNEL_Y_SHIFT 0 - -#define A2_SRC1_CHANNEL_Z_NEGATE (1<<31) -#define A2_SRC1_CHANNEL_Z_SHIFT 28 -#define A2_SRC1_CHANNEL_W_NEGATE (1<<27) -#define A2_SRC1_CHANNEL_W_SHIFT 24 -#define A2_SRC2_TYPE_SHIFT 21 -#define A2_SRC2_NR_SHIFT 16 -#define A2_SRC2_CHANNEL_X_NEGATE (1<<15) -#define A2_SRC2_CHANNEL_X_SHIFT 12 -#define A2_SRC2_CHANNEL_Y_NEGATE (1<<11) -#define A2_SRC2_CHANNEL_Y_SHIFT 8 -#define A2_SRC2_CHANNEL_Z_NEGATE (1<<7) -#define A2_SRC2_CHANNEL_Z_SHIFT 4 -#define A2_SRC2_CHANNEL_W_NEGATE (1<<3) -#define A2_SRC2_CHANNEL_W_SHIFT 0 - -/* Texture instructions */ -#define T0_TEXLD (0x15<<24) /* Sample texture using predeclared - * sampler and address, and output - * filtered texel data to destination - * register */ -#define T0_TEXLDP (0x16<<24) /* Same as texld but performs a - * perspective divide of the texture - * coordinate .xyz values by .w before - * sampling. */ -#define T0_TEXLDB (0x17<<24) /* Same as texld but biases the - * computed LOD by w. Only S4.6 two's - * comp is used. This implies that a - * float to fixed conversion is - * done. */ -#define T0_TEXKILL (0x18<<24) /* Does not perform a sampling - * operation. Simply kills the pixel - * if any channel of the address - * register is < 0.0. */ -#define T0_DEST_TYPE_SHIFT 19 -/* Allow: R, OC, OD, U */ -/* Note: U (unpreserved) regs do not retain their values between - * phases (cannot be used for feedback) - * - * Note: oC and OD registers can only be used as the destination of a - * texture instruction once per phase (this is an implementation - * restriction). - */ -#define T0_DEST_NR_SHIFT 14 -/* Allow R: 0..15, OC,OD: 0..0, U: 0..2 */ -#define T0_SAMPLER_NR_SHIFT 0 /* This field ignored for TEXKILL */ -#define T0_SAMPLER_NR_MASK (0xf<<0) - -#define T1_ADDRESS_REG_TYPE_SHIFT 24 /* Reg to use as texture coord */ -/* Allow R, T, OC, OD -- R, OC, OD are 'dependent' reads, new program phase */ -#define T1_ADDRESS_REG_NR_SHIFT 17 -#define T2_MBZ 0 - -/* Declaration instructions */ -#define D0_DCL (0x19<<24) /* Declare a t (interpolated attrib) - * register or an s (sampler) - * register. */ -#define D0_SAMPLE_TYPE_SHIFT 22 -#define D0_SAMPLE_TYPE_2D (0x0<<22) -#define D0_SAMPLE_TYPE_CUBE (0x1<<22) -#define D0_SAMPLE_TYPE_VOLUME (0x2<<22) -#define D0_SAMPLE_TYPE_MASK (0x3<<22) - -#define D0_TYPE_SHIFT 19 -/* Allow: T, S */ -#define D0_NR_SHIFT 14 -/* Allow T: 0..10, S: 0..15 */ -#define D0_CHANNEL_X (1<<10) -#define D0_CHANNEL_Y (2<<10) -#define D0_CHANNEL_Z (4<<10) -#define D0_CHANNEL_W (8<<10) -#define D0_CHANNEL_ALL (0xf<<10) -#define D0_CHANNEL_NONE (0<<10) - -#define D0_CHANNEL_XY (D0_CHANNEL_X|D0_CHANNEL_Y) -#define D0_CHANNEL_XYZ (D0_CHANNEL_XY|D0_CHANNEL_Z) - -/* I915 Errata: Do not allow (xz), (xw), (xzw) combinations for diffuse - * or specular declarations. - * - * For T dcls, only allow: (x), (xy), (xyz), (w), (xyzw) - * - * Must be zero for S (sampler) dcls - */ -#define D1_MBZ 0 -#define D2_MBZ 0 - -/* p207. - * The DWORD count is 3 times the number of bits set in MS1_MAPMASK_MASK - */ -#define _3DSTATE_MAP_STATE (CMD_3D|(0x1d<<24)|(0x0<<16)) - -#define MS1_MAPMASK_SHIFT 0 -#define MS1_MAPMASK_MASK (0x8fff<<0) - -#define MS2_UNTRUSTED_SURFACE (1<<31) -#define MS2_ADDRESS_MASK 0xfffffffc -#define MS2_VERTICAL_LINE_STRIDE (1<<1) -#define MS2_VERTICAL_OFFSET (1<<1) - -#define MS3_HEIGHT_SHIFT 21 -#define MS3_WIDTH_SHIFT 10 -#define MS3_PALETTE_SELECT (1<<9) -#define MS3_MAPSURF_FORMAT_SHIFT 7 -#define MS3_MAPSURF_FORMAT_MASK (0x7<<7) -#define MAPSURF_8BIT (1<<7) -#define MAPSURF_16BIT (2<<7) -#define MAPSURF_32BIT (3<<7) -#define MAPSURF_422 (5<<7) -#define MAPSURF_COMPRESSED (6<<7) -#define MAPSURF_4BIT_INDEXED (7<<7) -#define MS3_MT_FORMAT_MASK (0x7 << 3) -#define MS3_MT_FORMAT_SHIFT 3 -#define MT_4BIT_IDX_ARGB8888 (7<<3) /* SURFACE_4BIT_INDEXED */ -#define MT_8BIT_I8 (0<<3) /* SURFACE_8BIT */ -#define MT_8BIT_L8 (1<<3) -#define MT_8BIT_A8 (4<<3) -#define MT_8BIT_MONO8 (5<<3) -#define MT_16BIT_RGB565 (0<<3) /* SURFACE_16BIT */ -#define MT_16BIT_ARGB1555 (1<<3) -#define MT_16BIT_ARGB4444 (2<<3) -#define MT_16BIT_AY88 (3<<3) -#define MT_16BIT_88DVDU (5<<3) -#define MT_16BIT_BUMP_655LDVDU (6<<3) -#define MT_16BIT_I16 (7<<3) -#define MT_16BIT_L16 (8<<3) -#define MT_16BIT_A16 (9<<3) -#define MT_32BIT_ARGB8888 (0<<3) /* SURFACE_32BIT */ -#define MT_32BIT_ABGR8888 (1<<3) -#define MT_32BIT_XRGB8888 (2<<3) -#define MT_32BIT_XBGR8888 (3<<3) -#define MT_32BIT_QWVU8888 (4<<3) -#define MT_32BIT_AXVU8888 (5<<3) -#define MT_32BIT_LXVU8888 (6<<3) -#define MT_32BIT_XLVU8888 (7<<3) -#define MT_32BIT_ARGB2101010 (8<<3) -#define MT_32BIT_ABGR2101010 (9<<3) -#define MT_32BIT_AWVU2101010 (0xA<<3) -#define MT_32BIT_GR1616 (0xB<<3) -#define MT_32BIT_VU1616 (0xC<<3) -#define MT_32BIT_xI824 (0xD<<3) -#define MT_32BIT_xA824 (0xE<<3) -#define MT_32BIT_xL824 (0xF<<3) -#define MT_422_YCRCB_SWAPY (0<<3) /* SURFACE_422 */ -#define MT_422_YCRCB_NORMAL (1<<3) -#define MT_422_YCRCB_SWAPUV (2<<3) -#define MT_422_YCRCB_SWAPUVY (3<<3) -#define MT_COMPRESS_DXT1 (0<<3) /* SURFACE_COMPRESSED */ -#define MT_COMPRESS_DXT2_3 (1<<3) -#define MT_COMPRESS_DXT4_5 (2<<3) -#define MT_COMPRESS_FXT1 (3<<3) -#define MT_COMPRESS_DXT1_RGB (4<<3) -#define MS3_USE_FENCE_REGS (1<<2) -#define MS3_TILED_SURFACE (1<<1) -#define MS3_TILE_WALK (1<<0) - -/* The pitch is the pitch measured in DWORDS, minus 1 */ -#define MS4_PITCH_SHIFT 21 -#define MS4_CUBE_FACE_ENA_NEGX (1<<20) -#define MS4_CUBE_FACE_ENA_POSX (1<<19) -#define MS4_CUBE_FACE_ENA_NEGY (1<<18) -#define MS4_CUBE_FACE_ENA_POSY (1<<17) -#define MS4_CUBE_FACE_ENA_NEGZ (1<<16) -#define MS4_CUBE_FACE_ENA_POSZ (1<<15) -#define MS4_CUBE_FACE_ENA_MASK (0x3f<<15) -#define MS4_MAX_LOD_SHIFT 9 -#define MS4_MAX_LOD_MASK (0x3f<<9) -#define MS4_MIP_LAYOUT_LEGACY (0<<8) -#define MS4_MIP_LAYOUT_BELOW_LPT (0<<8) -#define MS4_MIP_LAYOUT_RIGHT_LPT (1<<8) -#define MS4_VOLUME_DEPTH_SHIFT 0 -#define MS4_VOLUME_DEPTH_MASK (0xff<<0) - -/* p244. - * The DWORD count is 3 times the number of bits set in SS1_MAPMASK_MASK. - */ -#define _3DSTATE_SAMPLER_STATE (CMD_3D|(0x1d<<24)|(0x1<<16)) - -#define SS1_MAPMASK_SHIFT 0 -#define SS1_MAPMASK_MASK (0x8fff<<0) - -#define SS2_REVERSE_GAMMA_ENABLE (1<<31) -#define SS2_PACKED_TO_PLANAR_ENABLE (1<<30) -#define SS2_COLORSPACE_CONVERSION (1<<29) -#define SS2_CHROMAKEY_SHIFT 27 -#define SS2_BASE_MIP_LEVEL_SHIFT 22 -#define SS2_BASE_MIP_LEVEL_MASK (0x1f<<22) -#define SS2_MIP_FILTER_SHIFT 20 -#define SS2_MIP_FILTER_MASK (0x3<<20) -#define MIPFILTER_NONE 0 -#define MIPFILTER_NEAREST 1 -#define MIPFILTER_LINEAR 3 -#define SS2_MAG_FILTER_SHIFT 17 -#define SS2_MAG_FILTER_MASK (0x7<<17) -#define FILTER_NEAREST 0 -#define FILTER_LINEAR 1 -#define FILTER_ANISOTROPIC 2 -#define FILTER_4X4_1 3 -#define FILTER_4X4_2 4 -#define FILTER_4X4_FLAT 5 -#define FILTER_6X5_MONO 6 /* XXX - check */ -#define SS2_MIN_FILTER_SHIFT 14 -#define SS2_MIN_FILTER_MASK (0x7<<14) -#define SS2_LOD_BIAS_SHIFT 5 -#define SS2_LOD_BIAS_ONE (0x10<<5) -#define SS2_LOD_BIAS_MASK (0x1ff<<5) -/* Shadow requires: - * MT_X8{I,L,A}24 or MT_{I,L,A}16 texture format - * FILTER_4X4_x MIN and MAG filters - */ -#define SS2_SHADOW_ENABLE (1<<4) -#define SS2_MAX_ANISO_MASK (1<<3) -#define SS2_MAX_ANISO_2 (0<<3) -#define SS2_MAX_ANISO_4 (1<<3) -#define SS2_SHADOW_FUNC_SHIFT 0 -#define SS2_SHADOW_FUNC_MASK (0x7<<0) -/* SS2_SHADOW_FUNC values: see COMPAREFUNC_* */ - -#define SS3_MIN_LOD_SHIFT 24 -#define SS3_MIN_LOD_ONE (0x10<<24) -#define SS3_MIN_LOD_MASK (0xff<<24) -#define SS3_KILL_PIXEL_ENABLE (1<<17) -#define SS3_TCX_ADDR_MODE_SHIFT 12 -#define SS3_TCX_ADDR_MODE_MASK (0x7<<12) -#define TEXCOORDMODE_WRAP 0 -#define TEXCOORDMODE_MIRROR 1 -#define TEXCOORDMODE_CLAMP_EDGE 2 -#define TEXCOORDMODE_CUBE 3 -#define TEXCOORDMODE_CLAMP_BORDER 4 -#define TEXCOORDMODE_MIRROR_ONCE 5 -#define SS3_TCY_ADDR_MODE_SHIFT 9 -#define SS3_TCY_ADDR_MODE_MASK (0x7<<9) -#define SS3_TCZ_ADDR_MODE_SHIFT 6 -#define SS3_TCZ_ADDR_MODE_MASK (0x7<<6) -#define SS3_NORMALIZED_COORDS (1<<5) -#define SS3_TEXTUREMAP_INDEX_SHIFT 1 -#define SS3_TEXTUREMAP_INDEX_MASK (0xf<<1) -#define SS3_DEINTERLACER_ENABLE (1<<0) - -#define SS4_BORDER_COLOR_MASK (~0) - -/* 3DSTATE_SPAN_STIPPLE, p258 - */ -#define _3DSTATE_STIPPLE ((0x3<<29)|(0x1d<<24)|(0x83<<16)) -#define ST1_ENABLE (1<<16) -#define ST1_MASK (0xffff) - -#define FLUSH_MAP_CACHE (1<<0) -#define FLUSH_RENDER_CACHE (1<<1) - -/* BLT commands */ -#define COLOR_BLT_CMD (CMD_2D | (0x40 << 22) | 3) -#define XY_COLOR_BLT_CMD (CMD_2D | (0x50 << 22) | 4) -#define XY_SETUP_CLIP_BLT_CMD (CMD_2D | (0x03 << 22) | 1) -#define XY_SRC_COPY_BLT_CMD (CMD_2D | (0x53 << 22) | 6) -#define SRC_COPY_BLT_CMD (CMD_2D | (0x43 << 22) | 4) - -#define XY_MONO_PAT_BLT_CMD (CMD_2D | (0x52<<22)|0x7) -#define XY_MONO_PAT_VERT_SEED ((1<<10) | (1<<9)|(1<<8)) -#define XY_MONO_PAT_HORT_SEED ((1<<14) | (1<<13)|(1<<12)) -#define XY_MONO_SRC_BLT_CMD (CMD_2D | (0x54<<22)|(0x6)) - -#define XY_SETUP_BLT_CMD (CMD_2D | (0x01 << 22) | 6) -#define XY_TEXT_IMMEDIATE_BLIT_CMD (CMD_2D | (0x31 << 22)) -#define XY_TEXT_BYTE_PACKED (1 << 16) - -/* BR00 */ -#define XY_BLT_WRITE_ALPHA (1 << 21) -#define XY_BLT_WRITE_RGB (1 << 20) -#define XY_SRC_TILED (1 << 15) -#define XY_DST_TILED (1 << 11) - -/* BR13 */ -#define BR13_565 (0x1 << 24) -#define BR13_8888 (0x3 << 24) - -#endif /* CAIRO_DRM_INTEL_COMMAND_PRIVATE_H */ diff --git a/gfx/cairo/cairo/src/drm/cairo-drm-intel-debug.c b/gfx/cairo/cairo/src/drm/cairo-drm-intel-debug.c deleted file mode 100644 index bfe5136675..0000000000 --- a/gfx/cairo/cairo/src/drm/cairo-drm-intel-debug.c +++ /dev/null @@ -1,1209 +0,0 @@ -/************************************************************************** - * - * Copyright 2003 Tungsten Graphics, Inc., Cedar Park, Texas. - * All Rights Reserved. - * - * Permission is hereby granted, free of charge, to any person obtaining a - * copy of this software and associated documentation files (the - * "Software"), to deal in the Software without restriction, including - * without limitation the rights to use, copy, modify, merge, publish, - * distribute, sub license, and/or sell copies of the Software, and to - * permit persons to whom the Software is furnished to do so, subject to - * the following conditions: - * - * The above copyright notice and this permission notice (including the - * next paragraph) shall be included in all copies or substantial portions - * of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS - * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. - * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR - * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, - * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE - * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - * - **************************************************************************/ - -#include "cairoint.h" -#include "cairo-drm-intel-private.h" - -struct debug_stream { - unsigned offset; /* current gtt offset */ - const char *ptr; /* pointer to gtt offset zero */ - const char *end; /* pointer to gtt offset zero */ -}; - -static cairo_bool_t -debug (struct debug_stream *stream, const char *name, uint32_t len) -{ - uint32_t i; - const uint32_t *ptr = (uint32_t *)(stream->ptr + stream->offset); - - if (len == 0) { - fprintf (stderr, "Error - zero length packet (0x%08x)\n", stream->ptr[0]); - ASSERT_NOT_REACHED; - return FALSE; - } - - fprintf (stderr, "%04x: ", stream->offset); - - fprintf (stderr, "%s (%d dwords):\n", name, len); - for (i = 0; i < len; i++) - fprintf (stderr, "\t0x%08x\n", ptr[i]); - fprintf (stderr, "\n"); - - stream->offset += len * sizeof(uint32_t); - return TRUE; -} - - -static const char * -get_prim_name (uint32_t val) -{ - switch (val & PRIM3D_MASK) { - case PRIM3D_TRILIST: return "TRILIST"; - case PRIM3D_TRISTRIP: return "TRISTRIP"; - case PRIM3D_TRISTRIP_RVRSE: return "TRISTRIP_RVRSE"; - case PRIM3D_TRIFAN: return "TRIFAN"; - case PRIM3D_POLY: return "POLY"; - case PRIM3D_LINELIST: return "LINELIST"; - case PRIM3D_LINESTRIP: return "LINESTRIP"; - case PRIM3D_RECTLIST: return "RECTLIST"; - case PRIM3D_POINTLIST: return "POINTLIST"; - case PRIM3D_DIB: return "DIB"; - case PRIM3D_CLEAR_RECT: return "CLEAR_RECT"; - case PRIM3D_ZONE_INIT: return "ZONE_INIT"; - default: return "????"; - } -} - -static cairo_bool_t -debug_prim (struct debug_stream *stream, - const char *name, - cairo_bool_t dump_floats, - uint32_t len) -{ - uint32_t *ptr = (uint32_t *)(stream->ptr + stream->offset); - const char *prim = get_prim_name( ptr[0] ); - uint32_t i; - - fprintf (stderr, "%04x: ", stream->offset); - fprintf (stderr, "%s %s (%d dwords):\n", name, prim, len); - fprintf (stderr, "\t0x%08x\n", ptr[0]); - for (i = 1; i < len; i++) { - if (dump_floats) - fprintf (stderr, "\t0x%08x // %f\n", ptr[i], *(float *)&ptr[i]); - else - fprintf (stderr, "\t0x%08x\n", ptr[i]); - } - - fprintf (stderr, "\n"); - - stream->offset += len * sizeof(uint32_t); - return TRUE; -} - -static const char *opcodes[] = { - "NOP", - "ADD", - "MOV", - "MUL", - "MAD", - "DP2ADD", - "DP3", - "DP4", - "FRC", - "RCP", - "RSQ", - "EXP", - "LOG", - "CMP", - "MIN", - "MAX", - "FLR", - "MOD", - "TRC", - "SGE", - "SLT", - "TEXLD", - "TEXLDP", - "TEXLDB", - "TEXKILL", - "DCL", - "0x1a", - "0x1b", - "0x1c", - "0x1d", - "0x1e", - "0x1f", -}; - -static const int args[] = { - 0, /* 0 nop */ - 2, /* 1 add */ - 1, /* 2 mov */ - 2, /* 3 m ul */ - 3, /* 4 mad */ - 3, /* 5 dp2add */ - 2, /* 6 dp3 */ - 2, /* 7 dp4 */ - 1, /* 8 frc */ - 1, /* 9 rcp */ - 1, /* a rsq */ - 1, /* b exp */ - 1, /* c log */ - 3, /* d cmp */ - 2, /* e min */ - 2, /* f max */ - 1, /* 10 flr */ - 1, /* 11 mod */ - 1, /* 12 trc */ - 2, /* 13 sge */ - 2, /* 14 slt */ - 1, - 1, - 1, - 1, - 0, - 0, - 0, - 0, - 0, - 0, - 0, -}; - -static const char *regname[] = { - "R", - "T", - "CONST", - "S", - "OC", - "OD", - "U", - "UNKNOWN", -}; - -static void -print_reg_type_nr(uint32_t type, uint32_t nr) -{ - switch (type) { - case REG_TYPE_T: - switch (nr) { - case T_DIFFUSE: - fprintf (stderr, "T_DIFFUSE"); - return; - case T_SPECULAR: - fprintf (stderr, "T_SPECULAR"); - return; - case T_FOG_W: - fprintf (stderr, "T_FOG_W"); - return; - default: - fprintf (stderr, "T_TEX%d", nr); - return; - } - case REG_TYPE_OC: - if (nr == 0) { - fprintf (stderr, "oC"); - return; - } - break; - case REG_TYPE_OD: - if (nr == 0) { - fprintf (stderr, "oD"); - return; - } - break; - default: - break; - } - - fprintf (stderr, "%s[%d]", regname[type], nr); -} - -#define REG_SWIZZLE_MASK 0x7777 -#define REG_NEGATE_MASK 0x8888 - -#define REG_SWIZZLE_XYZW ((SRC_X << A2_SRC2_CHANNEL_X_SHIFT) | \ - (SRC_Y << A2_SRC2_CHANNEL_Y_SHIFT) | \ - (SRC_Z << A2_SRC2_CHANNEL_Z_SHIFT) | \ - (SRC_W << A2_SRC2_CHANNEL_W_SHIFT)) - -static void -print_reg_neg_swizzle(uint32_t reg) -{ - int i; - - if ((reg & REG_SWIZZLE_MASK) == REG_SWIZZLE_XYZW && - (reg & REG_NEGATE_MASK) == 0) - return; - - fprintf (stderr, "."); - - for (i = 12; i >= 0; i -= 4) { - if (reg & (8 << i)) - fprintf (stderr, "-"); - - switch ((reg >> i) & 0x7) { - case 0: - fprintf (stderr, "x"); - break; - case 1: - fprintf (stderr, "y"); - break; - case 2: - fprintf (stderr, "z"); - break; - case 3: - fprintf (stderr, "w"); - break; - case 4: - fprintf (stderr, "0"); - break; - case 5: - fprintf (stderr, "1"); - break; - default: - fprintf (stderr, "?"); - break; - } - } -} - -static void -print_src_reg(uint32_t dword) -{ - uint32_t nr = (dword >> A2_SRC2_NR_SHIFT) & REG_NR_MASK; - uint32_t type = (dword >> A2_SRC2_TYPE_SHIFT) & REG_TYPE_MASK; - print_reg_type_nr(type, nr); - print_reg_neg_swizzle(dword); -} - -static void -print_dest_reg(uint32_t dword) -{ - uint32_t nr = (dword >> A0_DEST_NR_SHIFT) & REG_NR_MASK; - uint32_t type = (dword >> A0_DEST_TYPE_SHIFT) & REG_TYPE_MASK; - print_reg_type_nr(type, nr); - if ((dword & A0_DEST_CHANNEL_ALL) == A0_DEST_CHANNEL_ALL) - return; - fprintf (stderr, "."); - if (dword & A0_DEST_CHANNEL_X) - fprintf (stderr, "x"); - if (dword & A0_DEST_CHANNEL_Y) - fprintf (stderr, "y"); - if (dword & A0_DEST_CHANNEL_Z) - fprintf (stderr, "z"); - if (dword & A0_DEST_CHANNEL_W) - fprintf (stderr, "w"); -} - -#define GET_SRC0_REG(r0, r1) ((r0<<14)|(r1>>A1_SRC0_CHANNEL_W_SHIFT)) -#define GET_SRC1_REG(r0, r1) ((r0<<8)|(r1>>A2_SRC1_CHANNEL_W_SHIFT)) -#define GET_SRC2_REG(r) (r) - -static void -print_arith_op(uint32_t opcode, const uint32_t * program) -{ - if (opcode != A0_NOP) { - print_dest_reg(program[0]); - if (program[0] & A0_DEST_SATURATE) - fprintf (stderr, " = SATURATE "); - else - fprintf (stderr, " = "); - } - - fprintf (stderr, "%s ", opcodes[opcode]); - - print_src_reg(GET_SRC0_REG(program[0], program[1])); - if (args[opcode] == 1) { - fprintf (stderr, "\n"); - return; - } - - fprintf (stderr, ", "); - print_src_reg(GET_SRC1_REG(program[1], program[2])); - if (args[opcode] == 2) { - fprintf (stderr, "\n"); - return; - } - - fprintf (stderr, ", "); - print_src_reg(GET_SRC2_REG(program[2])); - fprintf (stderr, "\n"); - return; -} - -static void -print_tex_op(uint32_t opcode, const uint32_t * program) -{ - print_dest_reg(program[0] | A0_DEST_CHANNEL_ALL); - fprintf (stderr, " = "); - - fprintf (stderr, "%s ", opcodes[opcode]); - - fprintf (stderr, "S[%d],", program[0] & T0_SAMPLER_NR_MASK); - - print_reg_type_nr((program[1] >> T1_ADDRESS_REG_TYPE_SHIFT) & - REG_TYPE_MASK, - (program[1] >> T1_ADDRESS_REG_NR_SHIFT) & REG_NR_MASK); - fprintf (stderr, "\n"); -} - -static void -print_dcl_op(uint32_t opcode, const uint32_t * program) -{ - fprintf (stderr, "%s ", opcodes[opcode]); - print_dest_reg(program[0] | A0_DEST_CHANNEL_ALL); - fprintf (stderr, "\n"); -} - -static void -i915_disassemble_program (const uint32_t * program, uint32_t sz) -{ - uint32_t size = program[0] & 0x1ff; - uint32_t i; - - fprintf (stderr, "\tPROGRAM\n"); - - assert(size + 2 == sz); - - program++; - for (i = 1; i < sz; i += 3, program += 3) { - uint32_t opcode = program[0] & (0x1f << 24); - - fprintf (stderr, "\t\t"); - - if ((int) opcode >= A0_NOP && opcode <= A0_SLT) - print_arith_op(opcode >> 24, program); - else if (opcode >= T0_TEXLD && opcode <= T0_TEXKILL) - print_tex_op(opcode >> 24, program); - else if (opcode == D0_DCL) - print_dcl_op(opcode >> 24, program); - else - fprintf (stderr, "Unknown opcode 0x%x\n", opcode); - } - - fprintf (stderr, "\tEND-PROGRAM\n\n"); -} - -static cairo_bool_t -debug_program (struct debug_stream *stream, const char *name, uint32_t len) -{ - uint32_t *ptr = (uint32_t *)(stream->ptr + stream->offset); - - if (len == 0) { - fprintf (stderr, "Error - zero length packet (0x%08x)\n", stream->ptr[0]); - ASSERT_NOT_REACHED; - return FALSE; - } - - fprintf (stderr, "%04x: ", stream->offset); - fprintf (stderr, "%s (%d dwords):\n", name, len); - i915_disassemble_program (ptr, len); - - stream->offset += len * sizeof(uint32_t); - return TRUE; -} - -static cairo_bool_t -debug_chain (struct debug_stream *stream, const char *name, uint32_t len) -{ - uint32_t *ptr = (uint32_t *)(stream->ptr + stream->offset); - uint32_t old_offset = stream->offset + len * sizeof(uint32_t); - uint32_t i; - - fprintf (stderr, "%s (%d dwords):\n", name, len); - for (i = 0; i < len; i++) - fprintf (stderr, "\t0x%08x\n", ptr[i]); - - stream->offset = ptr[1] & ~0x3; - - if (stream->offset < old_offset) - fprintf (stderr, "\n... skipping backwards from 0x%x --> 0x%x ...\n\n", - old_offset, stream->offset ); - else - fprintf (stderr, "\n... skipping from 0x%x --> 0x%x ...\n\n", - old_offset, stream->offset ); - - return TRUE; -} - -static cairo_bool_t -debug_variable_length_prim (struct debug_stream *stream) -{ - uint32_t *ptr = (uint32_t *)(stream->ptr + stream->offset); - const char *prim = get_prim_name( ptr[0] ); - uint32_t i, len; - - uint16_t *idx = (uint16_t *)(ptr+1); - for (i = 0; idx[i] != 0xffff; i++) - ; - - len = 1+(i+2)/2; - - fprintf (stderr, "%04x: ", stream->offset); - fprintf (stderr, "3DPRIM, %s variable length %d indices (%d dwords):\n", prim, i, len); - for (i = 0; i < len; i++) - fprintf (stderr, "\t0x%08x\n", ptr[i]); - fprintf (stderr, "\n"); - - stream->offset += len * sizeof(uint32_t); - return TRUE; -} - -#define BITS(dw, hi, lo, ...) \ - do { \ - unsigned himask = 0xffffffffU >> (31 - (hi)); \ - fprintf (stderr, "\t\t "); \ - fprintf (stderr, __VA_ARGS__); \ - fprintf (stderr, ": 0x%x\n", ((dw) & himask) >> (lo)); \ - } while (0) - -#define MBZ(dw, hi, lo) do { \ - unsigned x = (dw) >> (lo); \ - unsigned lomask = (1 << (lo)) - 1; \ - unsigned himask; \ - himask = (1UL << (hi)) - 1; \ - assert ((x & himask & ~lomask) == 0); \ -} while (0) - -#define FLAG(dw, bit, ... ) \ - do { \ - if (((dw) >> (bit)) & 1) { \ - fprintf (stderr, "\t\t "); \ - fprintf (stderr, __VA_ARGS__); \ - fprintf (stderr, "\n"); \ - } \ - } while (0) - -static cairo_bool_t -debug_load_immediate (struct debug_stream *stream, - const char *name, - uint32_t len) -{ - uint32_t *ptr = (uint32_t *)(stream->ptr + stream->offset); - uint32_t bits = (ptr[0] >> 4) & 0xff; - uint32_t j = 0; - - fprintf (stderr, "%04x: ", stream->offset); - fprintf (stderr, "%s (%d dwords, flags: %x):\n", name, len, bits); - fprintf (stderr, "\t0x%08x\n", ptr[j++]); - - if (bits & (1<<0)) { - fprintf (stderr, "\t LIS0: 0x%08x\n", ptr[j]); - fprintf (stderr, "\t vb address: 0x%08x\n", (ptr[j] & ~0x3)); - BITS (ptr[j], 0, 0, "vb invalidate disable"); - j++; - } - if (bits & (1<<1)) { - fprintf (stderr, "\t LIS1: 0x%08x\n", ptr[j]); - BITS (ptr[j], 29, 24, "vb dword width"); - BITS (ptr[j], 21, 16, "vb dword pitch"); - BITS (ptr[j], 15, 0, "vb max index"); - j++; - } - if (bits & (1<<2)) { - int i; - fprintf (stderr, "\t LIS2: 0x%08x\n", ptr[j]); - for (i = 0; i < 8; i++) { - unsigned tc = (ptr[j] >> (i * 4)) & 0xf; - if (tc != 0xf) - BITS (tc, 3, 0, "tex coord %d", i); - } - j++; - } - if (bits & (1<<3)) { - fprintf (stderr, "\t LIS3: 0x%08x\n", ptr[j]); - j++; - } - if (bits & (1<<4)) { - fprintf (stderr, "\t LIS4: 0x%08x\n", ptr[j]); - BITS (ptr[j], 31, 23, "point width"); - BITS (ptr[j], 22, 19, "line width"); - FLAG (ptr[j], 18, "alpha flatshade"); - FLAG (ptr[j], 17, "fog flatshade"); - FLAG (ptr[j], 16, "spec flatshade"); - FLAG (ptr[j], 15, "rgb flatshade"); - BITS (ptr[j], 14, 13, "cull mode"); - FLAG (ptr[j], 12, "vfmt: point width"); - FLAG (ptr[j], 11, "vfmt: specular/fog"); - FLAG (ptr[j], 10, "vfmt: rgba"); - FLAG (ptr[j], 9, "vfmt: depth offset"); - BITS (ptr[j], 8, 6, "vfmt: position (2==xyzw)"); - FLAG (ptr[j], 5, "force dflt diffuse"); - FLAG (ptr[j], 4, "force dflt specular"); - FLAG (ptr[j], 3, "local depth offset enable"); - FLAG (ptr[j], 2, "vfmt: fp32 fog coord"); - FLAG (ptr[j], 1, "sprite point"); - FLAG (ptr[j], 0, "antialiasing"); - j++; - } - if (bits & (1<<5)) { - fprintf (stderr, "\t LIS5: 0x%08x\n", ptr[j]); - BITS (ptr[j], 31, 28, "rgba write disables"); - FLAG (ptr[j], 27, "force dflt point width"); - FLAG (ptr[j], 26, "last pixel enable"); - FLAG (ptr[j], 25, "global z offset enable"); - FLAG (ptr[j], 24, "fog enable"); - BITS (ptr[j], 23, 16, "stencil ref"); - BITS (ptr[j], 15, 13, "stencil test"); - BITS (ptr[j], 12, 10, "stencil fail op"); - BITS (ptr[j], 9, 7, "stencil pass z fail op"); - BITS (ptr[j], 6, 4, "stencil pass z pass op"); - FLAG (ptr[j], 3, "stencil write enable"); - FLAG (ptr[j], 2, "stencil test enable"); - FLAG (ptr[j], 1, "color dither enable"); - FLAG (ptr[j], 0, "logiop enable"); - j++; - } - if (bits & (1<<6)) { - fprintf (stderr, "\t LIS6: 0x%08x\n", ptr[j]); - FLAG (ptr[j], 31, "alpha test enable"); - BITS (ptr[j], 30, 28, "alpha func"); - BITS (ptr[j], 27, 20, "alpha ref"); - FLAG (ptr[j], 19, "depth test enable"); - BITS (ptr[j], 18, 16, "depth func"); - FLAG (ptr[j], 15, "blend enable"); - BITS (ptr[j], 14, 12, "blend func"); - BITS (ptr[j], 11, 8, "blend src factor"); - BITS (ptr[j], 7, 4, "blend dst factor"); - FLAG (ptr[j], 3, "depth write enable"); - FLAG (ptr[j], 2, "color write enable"); - BITS (ptr[j], 1, 0, "provoking vertex"); - j++; - } - - fprintf (stderr, "\n"); - - assert(j == len); - - stream->offset += len * sizeof(uint32_t); - return TRUE; -} - -static cairo_bool_t -debug_load_indirect (struct debug_stream *stream, - const char *name, - uint32_t len) -{ - uint32_t *ptr = (uint32_t *)(stream->ptr + stream->offset); - uint32_t bits = (ptr[0] >> 8) & 0x3f; - uint32_t i, j = 0; - - fprintf (stderr, "%04x: ", stream->offset); - fprintf (stderr, "%s (%d dwords):\n", name, len); - fprintf (stderr, "\t0x%08x\n", ptr[j++]); - - for (i = 0; i < 6; i++) { - if (bits & (1<<i)) { - switch (1<<(8+i)) { - case LI0_STATE_STATIC_INDIRECT: - fprintf (stderr, " STATIC: 0x%08x | %x\n", ptr[j]&~3, ptr[j]&3); j++; - fprintf (stderr, " 0x%08x\n", ptr[j++]); - break; - case LI0_STATE_DYNAMIC_INDIRECT: - fprintf (stderr, " DYNAMIC: 0x%08x | %x\n", ptr[j]&~3, ptr[j]&3); j++; - break; - case LI0_STATE_SAMPLER: - fprintf (stderr, " SAMPLER: 0x%08x | %x\n", ptr[j]&~3, ptr[j]&3); j++; - fprintf (stderr, " 0x%08x\n", ptr[j++]); - break; - case LI0_STATE_MAP: - fprintf (stderr, " MAP: 0x%08x | %x\n", ptr[j]&~3, ptr[j]&3); j++; - fprintf (stderr, " 0x%08x\n", ptr[j++]); - break; - case LI0_STATE_PROGRAM: - fprintf (stderr, " PROGRAM: 0x%08x | %x\n", ptr[j]&~3, ptr[j]&3); j++; - fprintf (stderr, " 0x%08x\n", ptr[j++]); - break; - case LI0_STATE_CONSTANTS: - fprintf (stderr, " CONSTANTS: 0x%08x | %x\n", ptr[j]&~3, ptr[j]&3); j++; - fprintf (stderr, " 0x%08x\n", ptr[j++]); - break; - default: - ASSERT_NOT_REACHED; - break; - } - } - } - - if (bits == 0) { - fprintf (stderr, "\t DUMMY: 0x%08x\n", ptr[j++]); - } - - fprintf (stderr, "\n"); - - assert(j == len); - stream->offset += len * sizeof(uint32_t); - return TRUE; -} - -static void -BR13 (struct debug_stream *stream, - uint32_t val) -{ - fprintf (stderr, "\t0x%08x\n", val); - FLAG (val, 30, "clipping enable"); - BITS (val, 25, 24, "color depth (3==32bpp)"); - BITS (val, 23, 16, "raster op"); - BITS (val, 15, 0, "dest pitch"); -} - -static void -BR2223 (struct debug_stream *stream, - uint32_t val22, uint32_t val23) -{ - union { uint32_t val; short field[2]; } BR22, BR23; - - BR22.val = val22; - BR23.val = val23; - - fprintf (stderr, "\t0x%08x\n", val22); - BITS (val22, 31, 16, "dest y1"); - BITS (val22, 15, 0, "dest x1"); - - fprintf (stderr, "\t0x%08x\n", val23); - BITS (val23, 31, 16, "dest y2"); - BITS (val23, 15, 0, "dest x2"); - - /* The blit engine may produce unexpected results when these aren't met */ - assert(BR22.field[0] < BR23.field[0]); - assert(BR22.field[1] < BR23.field[1]); -} - -static void -BR09 (struct debug_stream *stream, - uint32_t val) -{ - fprintf (stderr, "\t0x%08x -- dest address\n", val); -} - -static void -BR26 (struct debug_stream *stream, - uint32_t val) -{ - fprintf (stderr, "\t0x%08x\n", val); - BITS (val, 31, 16, "src y1"); - BITS (val, 15, 0, "src x1"); -} - -static void -BR11 (struct debug_stream *stream, - uint32_t val) -{ - fprintf (stderr, "\t0x%08x\n", val); - BITS (val, 15, 0, "src pitch"); -} - -static void -BR12 (struct debug_stream *stream, - uint32_t val) -{ - fprintf (stderr, "\t0x%08x -- src address\n", val); -} - -static void -BR16 (struct debug_stream *stream, - uint32_t val) -{ - fprintf (stderr, "\t0x%08x -- color\n", val); -} - -static cairo_bool_t -debug_copy_blit (struct debug_stream *stream, - const char *name, - uint32_t len) -{ - uint32_t *ptr = (uint32_t *)(stream->ptr + stream->offset); - uint32_t j = 0; - - fprintf (stderr, "%04x: ", stream->offset); - fprintf (stderr, "%s (%d dwords):\n", name, len); - fprintf (stderr, "\t0x%08x\n", ptr[j++]); - - BR13(stream, ptr[j++]); - BR2223(stream, ptr[j], ptr[j+1]); - j += 2; - BR09(stream, ptr[j++]); - BR26(stream, ptr[j++]); - BR11(stream, ptr[j++]); - BR12(stream, ptr[j++]); - - stream->offset += len * sizeof(uint32_t); - assert(j == len); - return TRUE; -} - -static cairo_bool_t -debug_color_blit (struct debug_stream *stream, - const char *name, - uint32_t len) -{ - uint32_t *ptr = (uint32_t *)(stream->ptr + stream->offset); - uint32_t j = 0; - - fprintf (stderr, "%04x: ", stream->offset); - fprintf (stderr, "%s (%d dwords):\n", name, len); - fprintf (stderr, "\t0x%08x\n", ptr[j++]); - - BR13(stream, ptr[j++]); - BR2223(stream, ptr[j], ptr[j+1]); - j += 2; - BR09(stream, ptr[j++]); - BR16(stream, ptr[j++]); - - stream->offset += len * sizeof(uint32_t); - assert(j == len); - return TRUE; -} - -static cairo_bool_t -debug_modes4 (struct debug_stream *stream, - const char *name, - uint32_t len) -{ - uint32_t *ptr = (uint32_t *)(stream->ptr + stream->offset); - uint32_t j = 0; - - fprintf (stderr, "%04x: ", stream->offset); - fprintf (stderr, "%s (%d dwords):\n", name, len); - fprintf (stderr, "\t0x%08x\n", ptr[j]); - BITS (ptr[j], 21, 18, "logicop func"); - FLAG (ptr[j], 17, "stencil test mask modify-enable"); - FLAG (ptr[j], 16, "stencil write mask modify-enable"); - BITS (ptr[j], 15, 8, "stencil test mask"); - BITS (ptr[j], 7, 0, "stencil write mask"); - fprintf (stderr, "\n"); - j++; - - stream->offset += len * sizeof(uint32_t); - assert(j == len); - return TRUE; -} - -static cairo_bool_t -debug_map_state (struct debug_stream *stream, - const char *name, - uint32_t len) -{ - uint32_t *ptr = (uint32_t *)(stream->ptr + stream->offset); - uint32_t j = 0; - - fprintf (stderr, "%04x: ", stream->offset); - fprintf (stderr, "%s (%d dwords):\n", name, len); - fprintf (stderr, "\t0x%08x\n", ptr[j++]); - - { - fprintf (stderr, "\t0x%08x\n", ptr[j]); - BITS (ptr[j], 15, 0, "map mask"); - j++; - } - - while (j < len) { - { - fprintf (stderr, "\t TMn.0: 0x%08x\n", ptr[j]); - fprintf (stderr, "\t map address: 0x%08x\n", (ptr[j] & ~0x3)); - FLAG (ptr[j], 1, "vertical line stride"); - FLAG (ptr[j], 0, "vertical line stride offset"); - j++; - } - - { - fprintf (stderr, "\t TMn.1: 0x%08x\n", ptr[j]); - BITS (ptr[j], 31, 21, "height"); - BITS (ptr[j], 20, 10, "width"); - BITS (ptr[j], 9, 7, "surface format"); - BITS (ptr[j], 6, 3, "texel format"); - FLAG (ptr[j], 2, "use fence regs"); - FLAG (ptr[j], 1, "tiled surface"); - FLAG (ptr[j], 0, "tile walk ymajor"); - j++; - } - { - fprintf (stderr, "\t TMn.2: 0x%08x\n", ptr[j]); - BITS (ptr[j], 31, 21, "dword pitch"); - BITS (ptr[j], 20, 15, "cube face enables"); - BITS (ptr[j], 14, 9, "max lod"); - FLAG (ptr[j], 8, "mip layout right"); - BITS (ptr[j], 7, 0, "depth"); - j++; - } - } - - stream->offset += len * sizeof(uint32_t); - assert(j == len); - return TRUE; -} - -static cairo_bool_t -debug_sampler_state (struct debug_stream *stream, - const char *name, - uint32_t len) -{ - uint32_t *ptr = (uint32_t *)(stream->ptr + stream->offset); - uint32_t j = 0; - - fprintf (stderr, "%04x: ", stream->offset); - fprintf (stderr, "%s (%d dwords):\n", name, len); - fprintf (stderr, "\t0x%08x\n", ptr[j++]); - - { - fprintf (stderr, "\t0x%08x\n", ptr[j]); - BITS (ptr[j], 15, 0, "sampler mask"); - j++; - } - - while (j < len) { - { - fprintf (stderr, "\t TSn.0: 0x%08x\n", ptr[j]); - FLAG (ptr[j], 31, "reverse gamma"); - FLAG (ptr[j], 30, "planar to packed"); - FLAG (ptr[j], 29, "yuv->rgb"); - BITS (ptr[j], 28, 27, "chromakey index"); - BITS (ptr[j], 26, 22, "base mip level"); - BITS (ptr[j], 21, 20, "mip mode filter"); - BITS (ptr[j], 19, 17, "mag mode filter"); - BITS (ptr[j], 16, 14, "min mode filter"); - BITS (ptr[j], 13, 5, "lod bias (s4.4)"); - FLAG (ptr[j], 4, "shadow enable"); - FLAG (ptr[j], 3, "max-aniso-4"); - BITS (ptr[j], 2, 0, "shadow func"); - j++; - } - - { - fprintf (stderr, "\t TSn.1: 0x%08x\n", ptr[j]); - BITS (ptr[j], 31, 24, "min lod"); - MBZ( ptr[j], 23, 18 ); - FLAG (ptr[j], 17, "kill pixel enable"); - FLAG (ptr[j], 16, "keyed tex filter mode"); - FLAG (ptr[j], 15, "chromakey enable"); - BITS (ptr[j], 14, 12, "tcx wrap mode"); - BITS (ptr[j], 11, 9, "tcy wrap mode"); - BITS (ptr[j], 8, 6, "tcz wrap mode"); - FLAG (ptr[j], 5, "normalized coords"); - BITS (ptr[j], 4, 1, "map (surface) index"); - FLAG (ptr[j], 0, "EAST deinterlacer enable"); - j++; - } - { - fprintf (stderr, "\t TSn.2: 0x%08x (default color)\n", ptr[j]); - j++; - } - } - - stream->offset += len * sizeof(uint32_t); - assert(j == len); - return TRUE; -} - -static cairo_bool_t -debug_dest_vars (struct debug_stream *stream, - const char *name, - uint32_t len) -{ - uint32_t *ptr = (uint32_t *)(stream->ptr + stream->offset); - uint32_t j = 0; - - fprintf (stderr, "%04x: ", stream->offset); - fprintf (stderr, "%s (%d dwords):\n", name, len); - fprintf (stderr, "\t0x%08x\n", ptr[j++]); - - { - fprintf (stderr, "\t0x%08x\n", ptr[j]); - FLAG (ptr[j], 31, "early classic ztest"); - FLAG (ptr[j], 30, "opengl tex default color"); - FLAG (ptr[j], 29, "bypass iz"); - FLAG (ptr[j], 28, "lod preclamp"); - BITS (ptr[j], 27, 26, "dither pattern"); - FLAG (ptr[j], 25, "linear gamma blend"); - FLAG (ptr[j], 24, "debug dither"); - BITS (ptr[j], 23, 20, "dstorg x"); - BITS (ptr[j], 19, 16, "dstorg y"); - MBZ (ptr[j], 15, 15 ); - BITS (ptr[j], 14, 12, "422 write select"); - BITS (ptr[j], 11, 8, "cbuf format"); - BITS (ptr[j], 3, 2, "zbuf format"); - FLAG (ptr[j], 1, "vert line stride"); - FLAG (ptr[j], 1, "vert line stride offset"); - j++; - } - - stream->offset += len * sizeof(uint32_t); - assert(j == len); - return TRUE; -} - -static cairo_bool_t debug_buf_info( struct debug_stream *stream, - const char *name, - uint32_t len ) -{ - uint32_t *ptr = (uint32_t *)(stream->ptr + stream->offset); - uint32_t j = 0; - - fprintf (stderr, "%04x: ", stream->offset); - fprintf (stderr, "%s (%d dwords):\n", name, len); - fprintf (stderr, "\t0x%08x\n", ptr[j++]); - - { - fprintf (stderr, "\t0x%08x\n", ptr[j]); - BITS (ptr[j], 28, 28, "aux buffer id"); - BITS (ptr[j], 27, 24, "buffer id (7=depth, 3=back)"); - FLAG (ptr[j], 23, "use fence regs"); - FLAG (ptr[j], 22, "tiled surface"); - FLAG (ptr[j], 21, "tile walk ymajor"); - MBZ (ptr[j], 20, 14); - BITS (ptr[j], 13, 2, "dword pitch"); - MBZ (ptr[j], 2, 0); - j++; - } - - fprintf (stderr, "\t0x%08x -- buffer base address\n", ptr[j++]); - - stream->offset += len * sizeof(uint32_t); - assert(j == len); - return TRUE; -} - -static cairo_bool_t -decode_3d_i915 (struct debug_stream *stream) -{ - uint32_t *ptr = (uint32_t *)(stream->ptr + stream->offset); - uint32_t cmd = *ptr; - - switch ((cmd >> 24) & 0x1f) { - case 0x6: - return debug (stream, "3DSTATE_ANTI_ALIASING", 1); - case 0x7: - return debug (stream, "3DSTATE_RASTERIZATION_RULES", 1); - case 0x8: - return debug (stream, "3DSTATE_BACKFACE_STENCIL_OPS", 1); - case 0x9: - return debug (stream, "3DSTATE_BACKFACE_STENCIL_MASKS", 1); - case 0xb: - return debug (stream, "3DSTATE_INDEPENDENT_ALPHA_BLEND", 1); - case 0xc: - return debug (stream, "3DSTATE_MODES5", 1); - case 0xd: - return debug_modes4(stream, "3DSTATE_MODES4", 1); - case 0x15: - return debug (stream, "3DSTATE_FOG_COLOR", 1); - case 0x16: - return debug (stream, "3DSTATE_COORD_SET_BINDINGS", 1); - case 0x1c: - /* 3DState16NP */ - switch((cmd >> 19) & 0x1f) { - case 0x10: - return debug (stream, "3DSTATE_SCISSOR_ENABLE", 1); - case 0x11: - return debug (stream, "3DSTATE_DEPTH_SUBRECTANGLE_DISABLE", 1); - default: - break; - } - break; - case 0x1d: - /* 3DStateMW */ - switch ((cmd >> 16) & 0xff) { - case 0x0: - return debug_map_state(stream, "3DSTATE_MAP_STATE", (cmd & 0x1f) + 2); - case 0x1: - return debug_sampler_state(stream, "3DSTATE_SAMPLER_STATE", (cmd & 0x1f) + 2); - case 0x4: - return debug_load_immediate(stream, "3DSTATE_LOAD_STATE_IMMEDIATE", (cmd & 0xf) + 2); - case 0x5: - return debug_program(stream, "3DSTATE_PIXEL_SHADER_PROGRAM", (cmd & 0x1ff) + 2); - case 0x6: - return debug (stream, "3DSTATE_PIXEL_SHADER_CONSTANTS", (cmd & 0xff) + 2); - case 0x7: - return debug_load_indirect(stream, "3DSTATE_LOAD_INDIRECT", (cmd & 0xff) + 2); - case 0x80: - return debug (stream, "3DSTATE_DRAWING_RECTANGLE", (cmd & 0xffff) + 2); - case 0x81: - return debug (stream, "3DSTATE_SCISSOR_RECTANGLE", (cmd & 0xffff) + 2); - case 0x83: - return debug (stream, "3DSTATE_SPAN_STIPPLE", (cmd & 0xffff) + 2); - case 0x85: - return debug_dest_vars(stream, "3DSTATE_DEST_BUFFER_VARS", (cmd & 0xffff) + 2); - case 0x88: - return debug (stream, "3DSTATE_CONSTANT_BLEND_COLOR", (cmd & 0xffff) + 2); - case 0x89: - return debug (stream, "3DSTATE_FOG_MODE", (cmd & 0xffff) + 2); - case 0x8e: - return debug_buf_info(stream, "3DSTATE_BUFFER_INFO", (cmd & 0xffff) + 2); - case 0x97: - return debug (stream, "3DSTATE_DEPTH_OFFSET_SCALE", (cmd & 0xffff) + 2); - case 0x98: - return debug (stream, "3DSTATE_DEFAULT_Z", (cmd & 0xffff) + 2); - case 0x99: - return debug (stream, "3DSTATE_DEFAULT_DIFFUSE", (cmd & 0xffff) + 2); - case 0x9a: - return debug (stream, "3DSTATE_DEFAULT_SPECULAR", (cmd & 0xffff) + 2); - case 0x9c: - return debug (stream, "3DSTATE_CLEAR_PARAMETERS", (cmd & 0xffff) + 2); - default: - ASSERT_NOT_REACHED; - return 0; - } - break; - case 0x1e: - if (cmd & (1 << 23)) - return debug (stream, "???", (cmd & 0xffff) + 1); - else - return debug (stream, "", 1); - break; - case 0x1f: - if ((cmd & (1 << 23)) == 0) { - return debug_prim (stream, "3DPRIM (inline)", 1, (cmd & 0x1ffff) + 2); - } else if (cmd & (1 << 17)) { - if ((cmd & 0xffff) == 0) - return debug_variable_length_prim (stream); - else - return debug_prim (stream, "3DPRIM (indexed)", 0, (((cmd & 0xffff) + 1) / 2) + 1); - } else - return debug_prim (stream, "3DPRIM (indirect sequential)", 0, 2); - break; - default: - return debug (stream, "", 0); - } - - return FALSE; -} - -static cairo_bool_t -decode_3d_i965 (struct debug_stream *stream) -{ - const uint32_t *data = (uint32_t *) (stream->ptr + stream->offset); - const uint32_t opcode = (data[0] & 0xffff0000) >> 16; - unsigned int idx; - const struct { - uint32_t opcode; - int min_len; - int max_len; - const char *name; - } opcodes_3d[] = { - { 0x6000, 3, 3, "URB_FENCE" }, - { 0x6001, 2, 2, "CS_URB_STATE" }, - { 0x6002, 2, 2, "CONSTANT_BUFFER" }, - { 0x6101, 6, 6, "STATE_BASE_ADDRESS" }, - { 0x6102, 2, 2 , "STATE_SIP" }, - { 0x6104, 1, 1, "3DSTATE_PIPELINE_SELECT" }, - { 0x680b, 1, 1, "3DSTATE_VF_STATISTICS" }, - { 0x6904, 1, 1, "3DSTATE_PIPELINE_SELECT" }, - { 0x7800, 7, 7, "3DSTATE_PIPELINED_POINTERS" }, - { 0x7801, 6, 6, "3DSTATE_BINDING_TABLE_POINTERS" }, - { 0x780b, 1, 1, "3DSTATE_VF_STATISTICS" }, - { 0x7808, 5, 257, "3DSTATE_VERTEX_BUFFERS" }, - { 0x7809, 3, 256, "3DSTATE_VERTEX_ELEMENTS" }, - { 0x780a, 3, 3, "3DSTATE_INDEX_BUFFER" }, - { 0x7900, 4, 4, "3DSTATE_DRAWING_RECTANGLE" }, - { 0x7901, 5, 5, "3DSTATE_CONSTANT_COLOR" }, - { 0x7905, 5, 7, "3DSTATE_DEPTH_BUFFER" }, - { 0x7906, 2, 2, "3DSTATE_POLY_STIPPLE_OFFSET" }, - { 0x7907, 33, 33, "3DSTATE_POLY_STIPPLE_PATTERN" }, - { 0x7908, 3, 3, "3DSTATE_LINE_STIPPLE" }, - { 0x7909, 2, 2, "3DSTATE_GLOBAL_DEPTH_OFFSET_CLAMP" }, - { 0x790a, 3, 3, "3DSTATE_AA_LINE_PARAMETERS" }, - { 0x7b00, 6, 6, "3DPRIMITIVE" }, - }, *opcode_3d; - - for (idx = 0; idx < ARRAY_LENGTH (opcodes_3d); idx++) { - opcode_3d = &opcodes_3d[idx]; - if (opcode == opcode_3d->opcode) { - unsigned int len = 1; - if (opcode_3d->max_len != 1) - len = (data[0] & 0x000000ff) + 2; - return debug (stream, opcode_3d->name, len); - } - } - - return FALSE; -} - -static cairo_bool_t -decode_3d_i830 (struct debug_stream *stream) -{ - ASSERT_NOT_REACHED; - return FALSE; -} - -static cairo_bool_t -i915_debug_packet (struct debug_stream *stream, - int devid) -{ - uint32_t *ptr = (uint32_t *)(stream->ptr + stream->offset); - uint32_t cmd = *ptr; - - switch (((cmd >> 29) & 0x7)) { - case 0x0: - switch ((cmd >> 23) & 0x3f) { - case 0x0: - return debug (stream, "MI_NOOP", 1); - case 0x3: - return debug (stream, "MI_WAIT_FOR_EVENT", 1); - case 0x4: - return debug (stream, "MI_FLUSH", 1); - case 0xA: - debug (stream, "MI_BATCH_BUFFER_END", 1); - return FALSE; - case 0x22: - return debug (stream, "MI_LOAD_REGISTER_IMM", 3); - case 0x31: - return debug_chain(stream, "MI_BATCH_BUFFER_START", 2); - default: - break; - } - break; - case 0x1: - break; - case 0x2: - switch ((cmd >> 22) & 0xff) { - case 0x50: - return debug_color_blit(stream, "XY_COLOR_BLT", (cmd & 0xff) + 2); - case 0x53: - return debug_copy_blit(stream, "XY_SRC_COPY_BLT", (cmd & 0xff) + 2); - default: - return debug (stream, "blit command", (cmd & 0xff) + 2); - } - break; - case 0x3: - if (IS_965(devid)) - return decode_3d_i965 (stream); - else if (IS_9XX(devid)) - return decode_3d_i915 (stream); - else - return decode_3d_i830 (stream); - default: - break; - } - - fprintf (stderr, "Bogus cmd: %x [%x]\n", (cmd >> 29) & 7, cmd); - ASSERT_NOT_REACHED; - return 0; -} - -void -intel_dump_batchbuffer (const void *batch, - uint32_t length, - int devid) -{ - struct debug_stream stream; - cairo_bool_t done = FALSE; - - fprintf (stderr, "\nBATCH: (%d dwords)\n", length / 4); - - stream.offset = 0; - stream.ptr = batch; - - while (! done && stream.offset < length) { - if (! i915_debug_packet (&stream, devid)) - break; - - assert (stream.offset <= length); - } - - fprintf (stderr, "END-BATCH\n\n"); - fflush (stderr); -} diff --git a/gfx/cairo/cairo/src/drm/cairo-drm-intel-ioctl-private.h b/gfx/cairo/cairo/src/drm/cairo-drm-intel-ioctl-private.h deleted file mode 100644 index 4a766d7e13..0000000000 --- a/gfx/cairo/cairo/src/drm/cairo-drm-intel-ioctl-private.h +++ /dev/null @@ -1,45 +0,0 @@ -/* Cairo - a vector graphics library with display and print output - * - * Copyright © 2009 Chris Wilson - * - * 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., 51 Franklin Street, Suite 500, Boston, MA 02110-1335, 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. - * - */ - -#ifndef CAIRO_DRM_INTEL_IOCTL_PRIVATE_H -#define CAIRO_DRM_INTEL_IOCTL_PRIVATE_H - -#include "cairo-drm-intel-command-private.h" - -#include <drm/i915_drm.h> - -struct drm_i915_gem_real_size { - uint32_t handle; - uint64_t size; -}; - -#define DRM_I915_GEM_REAL_SIZE 0x2a -#define DRM_IOCTL_I915_GEM_REAL_SIZE DRM_IOWR (DRM_COMMAND_BASE + DRM_I915_GEM_REAL_SIZE, struct drm_i915_gem_real_size) - -#endif /* CAIRO_DRM_INTEL_IOCTL_PRIVATE_H */ diff --git a/gfx/cairo/cairo/src/drm/cairo-drm-intel-private.h b/gfx/cairo/cairo/src/drm/cairo-drm-intel-private.h deleted file mode 100644 index 0cfded1bd8..0000000000 --- a/gfx/cairo/cairo/src/drm/cairo-drm-intel-private.h +++ /dev/null @@ -1,515 +0,0 @@ -/* Cairo - a vector graphics library with display and print output - * - * Copyright © 2009 Chris Wilson - * - * 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., 51 Franklin Street, Suite 500, Boston, MA 02110-1335, 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. - * - */ - -#ifndef CAIRO_DRM_INTEL_PRIVATE_H -#define CAIRO_DRM_INTEL_PRIVATE_H - -#include "cairoint.h" -#include "cairo-cache-private.h" -#include "cairo-compiler-private.h" -#include "cairo-drm-private.h" -#include "cairo-freelist-private.h" -#include "cairo-list-private.h" -#include "cairo-mutex-private.h" -#include "cairo-rtree-private.h" -#include "cairo-types-private.h" -#include "cairo-pattern-private.h" - -#include "cairo-drm-intel-ioctl-private.h" - -#define INTEL_TILING_DEFAULT I915_TILING_Y - -#define INTEL_BO_CACHE_BUCKETS 12 /* cache surfaces up to 16 MiB */ - -#define INTEL_GLYPH_CACHE_WIDTH 1024 -#define INTEL_GLYPH_CACHE_HEIGHT 1024 -#define INTEL_GLYPH_CACHE_MIN_SIZE 1 -#define INTEL_GLYPH_CACHE_MAX_SIZE 128 - -typedef struct _intel_bo { - cairo_drm_bo_t base; - - cairo_list_t link; - cairo_list_t cache_list; - - uint32_t offset; - uint32_t batch_read_domains; - uint32_t batch_write_domain; - - uint32_t opaque0; - uint32_t opaque1; - - uint32_t full_size; - uint16_t stride; - uint16_t _stride; - uint32_t tiling :4; - uint32_t _tiling :4; - uint32_t purgeable :1; - uint32_t busy :1; - uint32_t cpu :1; - - struct drm_i915_gem_exec_object2 *exec; - void *virtual; -} intel_bo_t; - -#define INTEL_BATCH_SIZE (64*1024) -#define INTEL_VERTEX_BUFFER_SIZE (512*1024) -#define INTEL_MAX_RELOCS 2048 - -static inline void -intel_bo_mark_purgeable (intel_bo_t *bo) -{ - if (bo->base.name == 0) - bo->purgeable = 1; -} - -typedef struct _intel_vertex_buffer intel_vertex_buffer_t; - -typedef void (*intel_vertex_buffer_new_func_t) (intel_vertex_buffer_t *vertex_buffer); -typedef void (*intel_vertex_buffer_start_rectangles_func_t) (intel_vertex_buffer_t *vertex_buffer, - uint32_t floats_per_vertex); -typedef void (*intel_vertex_buffer_flush_func_t) (intel_vertex_buffer_t *vertex_buffer); -typedef void (*intel_vertex_buffer_finish_func_t) (intel_vertex_buffer_t *vertex_buffer); - -struct _intel_vertex_buffer { - uint32_t vbo_batch; /* reloc position in batch, 0 -> not yet allocated */ - uint32_t vbo_offset; - uint32_t vbo_used; - - uint32_t vertex_index; - uint32_t vertex_count; - - uint32_t floats_per_vertex; - uint32_t rectangle_size; - - intel_bo_t *last_vbo; - uint32_t last_vbo_offset; - uint32_t last_vbo_space; - - intel_vertex_buffer_new_func_t new; - intel_vertex_buffer_start_rectangles_func_t start_rectangles; - intel_vertex_buffer_flush_func_t flush; - intel_vertex_buffer_finish_func_t finish; - - uint32_t base[INTEL_VERTEX_BUFFER_SIZE / sizeof (uint32_t)]; -}; - -typedef struct _intel_batch intel_batch_t; - -typedef void (*intel_batch_commit_func_t) (intel_batch_t *batch); -typedef void (*intel_batch_reset_func_t) (intel_batch_t *batch); - -struct _intel_batch { - size_t gtt_size; - size_t gtt_avail_size; - - intel_batch_commit_func_t commit; - intel_batch_reset_func_t reset; - - uint16_t exec_count; - uint16_t reloc_count; - uint16_t used; - uint16_t header; - - intel_bo_t *target_bo[INTEL_MAX_RELOCS]; - struct drm_i915_gem_exec_object2 exec[INTEL_MAX_RELOCS]; - struct drm_i915_gem_relocation_entry reloc[INTEL_MAX_RELOCS]; - - uint32_t base[INTEL_BATCH_SIZE / sizeof (uint32_t)]; - - intel_vertex_buffer_t vertex_buffer; -}; - -typedef struct _intel_buffer { - intel_bo_t *bo; - uint32_t offset; - cairo_format_t format; - uint32_t map0, map1; - uint32_t width; - uint32_t height; - uint32_t stride; -} intel_buffer_t; - -typedef struct _intel_buffer_cache { - int ref_count; - intel_buffer_t buffer; - cairo_rtree_t rtree; - cairo_list_t link; -} intel_buffer_cache_t; - -typedef struct _intel_glyph { - cairo_rtree_node_t node; - intel_buffer_cache_t *cache; - void **owner; - float texcoord[3]; - int width, height; -} intel_glyph_t; - -typedef struct _intel_gradient_cache { - cairo_pattern_union_t pattern; - intel_buffer_t buffer; -} intel_gradient_cache_t; -#define GRADIENT_CACHE_SIZE 16 - -typedef struct _intel_surface { - cairo_drm_surface_t drm; - - cairo_cache_entry_t snapshot_cache_entry; -} intel_surface_t; - -typedef void (*intel_reset_context_func_t) (void *device); - -typedef struct _intel_device { - cairo_drm_device_t base; - - size_t gtt_max_size; - size_t gtt_avail_size; - - cairo_freepool_t bo_pool; - cairo_list_t bo_in_flight; - - cairo_mutex_t mutex; - intel_batch_t batch; - - intel_buffer_cache_t glyph_cache[2]; - cairo_list_t fonts; - - struct { - intel_gradient_cache_t cache[GRADIENT_CACHE_SIZE]; - unsigned int size; - } gradient_cache; - - cairo_cache_t snapshot_cache; - size_t snapshot_cache_max_size; - - intel_reset_context_func_t reset_context; - - cairo_status_t (*flush) (struct _intel_device *); -} intel_device_t; - -static inline intel_device_t * -to_intel_device (cairo_device_t *base) -{ - return (intel_device_t *) base; -} - -static inline intel_bo_t * -to_intel_bo (cairo_drm_bo_t *base) -{ - return (intel_bo_t *) base; -} - -static inline intel_bo_t * -intel_bo_reference (intel_bo_t *bo) -{ - return to_intel_bo (cairo_drm_bo_reference (&bo->base)); -} - -cairo_private cairo_bool_t -intel_bo_madvise (intel_device_t *device, intel_bo_t *bo, int madv); - -static cairo_always_inline void -intel_bo_destroy (intel_device_t *device, intel_bo_t *bo) -{ - cairo_drm_bo_destroy (&device->base.base, &bo->base); -} - -static inline void -intel_bo_in_flight_add (intel_device_t *device, - intel_bo_t *bo) -{ - if (bo->base.name == 0 && bo->exec != NULL && cairo_list_is_empty (&bo->cache_list)) - cairo_list_add (&bo->cache_list, &device->bo_in_flight); -} - -cairo_private int -intel_get (int fd, int param); - -cairo_private cairo_bool_t -intel_info (int fd, uint64_t *gtt_size); - -cairo_private cairo_status_t -intel_device_init (intel_device_t *device, int fd); - -cairo_private void -intel_device_fini (intel_device_t *dev); - -cairo_private intel_bo_t * -intel_bo_create (intel_device_t *dev, - uint32_t max_size, - uint32_t real_size, - cairo_bool_t gpu_target, - uint32_t tiling, - uint32_t stride); - -cairo_private intel_bo_t * -intel_bo_create_for_name (intel_device_t *dev, uint32_t name); - -cairo_private void -intel_bo_set_tiling (const intel_device_t *dev, - intel_bo_t *bo); - -cairo_private cairo_bool_t -intel_bo_is_inactive (const intel_device_t *device, - intel_bo_t *bo); - -cairo_private cairo_bool_t -intel_bo_wait (const intel_device_t *device, const intel_bo_t *bo); - -cairo_private void -intel_bo_write (const intel_device_t *dev, - intel_bo_t *bo, - unsigned long offset, - unsigned long size, - const void *data); - -cairo_private void -intel_bo_read (const intel_device_t *dev, - intel_bo_t *bo, - unsigned long offset, - unsigned long size, - void *data); - -cairo_private void * -intel_bo_map (const intel_device_t *dev, intel_bo_t *bo); - -cairo_private void -intel_bo_unmap (intel_bo_t *bo); - -cairo_private cairo_status_t -intel_bo_init (const intel_device_t *dev, - intel_bo_t *bo, - uint32_t size, - uint32_t initial_domain); - -cairo_private cairo_status_t -intel_bo_init_for_name (const intel_device_t *dev, - intel_bo_t *bo, - uint32_t size, - uint32_t name); - -cairo_private cairo_status_t -intel_bo_put_image (intel_device_t *dev, - intel_bo_t *bo, - cairo_image_surface_t *src, - int src_x, int src_y, - int width, int height, - int dst_x, int dst_y); - -cairo_private void -intel_surface_init (intel_surface_t *surface, - const cairo_surface_backend_t *backend, - cairo_drm_device_t *device, - cairo_format_t format, - int width, int height); - -cairo_private cairo_status_t -intel_buffer_cache_init (intel_buffer_cache_t *cache, - intel_device_t *device, - cairo_format_t format, - int width, int height); - -cairo_private cairo_status_t -intel_gradient_render (intel_device_t *device, - const cairo_gradient_pattern_t *pattern, - intel_buffer_t *buffer); - -cairo_private cairo_int_status_t -intel_get_glyph (intel_device_t *device, - cairo_scaled_font_t *scaled_font, - cairo_scaled_glyph_t *scaled_glyph); - -cairo_private void -intel_scaled_glyph_fini (cairo_scaled_glyph_t *scaled_glyph, - cairo_scaled_font_t *scaled_font); - -cairo_private void -intel_scaled_font_fini (cairo_scaled_font_t *scaled_font); - -cairo_private void -intel_glyph_cache_unpin (intel_device_t *device); - -static inline intel_glyph_t * -intel_glyph_pin (intel_glyph_t *glyph) -{ - cairo_rtree_node_t *node = &glyph->node; - if (unlikely (node->pinned == 0)) - return _cairo_rtree_pin (&glyph->cache->rtree, node); - return glyph; -} - -cairo_private cairo_status_t -intel_snapshot_cache_insert (intel_device_t *device, - intel_surface_t *surface); - -cairo_private void -intel_surface_detach_snapshot (cairo_surface_t *abstract_surface); - -cairo_private void -intel_snapshot_cache_thaw (intel_device_t *device); - -cairo_private void -intel_throttle (intel_device_t *device); - -cairo_private cairo_status_t -intel_surface_acquire_source_image (void *abstract_surface, - cairo_image_surface_t **image_out, - void **image_extra); - -cairo_private void -intel_surface_release_source_image (void *abstract_surface, - cairo_image_surface_t *image, - void *image_extra); -cairo_private cairo_surface_t * -intel_surface_map_to_image (void *abstract_surface); - -cairo_private cairo_status_t -intel_surface_flush (void *abstract_surface, - unsigned flags); - -cairo_private cairo_status_t -intel_surface_finish (void *abstract_surface); - -cairo_private void -intel_dump_batchbuffer (const void *batch, - uint32_t length, - int devid); - -static inline uint32_t cairo_const -MS3_tiling (uint32_t tiling) -{ - switch (tiling) { - default: - case I915_TILING_NONE: return 0; - case I915_TILING_X: return MS3_TILED_SURFACE; - case I915_TILING_Y: return MS3_TILED_SURFACE | MS3_TILE_WALK; - } -} - -static inline float cairo_const -texcoord_2d_16 (double x, double y) -{ - union { - uint32_t ui; - float f; - } u; - u.ui = (_cairo_half_from_float (y) << 16) | _cairo_half_from_float (x); - return u.f; -} - -#define PCI_CHIP_I810 0x7121 -#define PCI_CHIP_I810_DC100 0x7123 -#define PCI_CHIP_I810_E 0x7125 -#define PCI_CHIP_I815 0x1132 - -#define PCI_CHIP_I830_M 0x3577 -#define PCI_CHIP_845_G 0x2562 -#define PCI_CHIP_I855_GM 0x3582 -#define PCI_CHIP_I865_G 0x2572 - -#define PCI_CHIP_I915_G 0x2582 -#define PCI_CHIP_E7221_G 0x258A -#define PCI_CHIP_I915_GM 0x2592 -#define PCI_CHIP_I945_G 0x2772 -#define PCI_CHIP_I945_GM 0x27A2 -#define PCI_CHIP_I945_GME 0x27AE - -#define PCI_CHIP_Q35_G 0x29B2 -#define PCI_CHIP_G33_G 0x29C2 -#define PCI_CHIP_Q33_G 0x29D2 - -#define PCI_CHIP_IGD_GM 0xA011 -#define PCI_CHIP_IGD_G 0xA001 - -#define IS_IGDGM(devid) (devid == PCI_CHIP_IGD_GM) -#define IS_IGDG(devid) (devid == PCI_CHIP_IGD_G) -#define IS_IGD(devid) (IS_IGDG(devid) || IS_IGDGM(devid)) - -#define PCI_CHIP_I965_G 0x29A2 -#define PCI_CHIP_I965_Q 0x2992 -#define PCI_CHIP_I965_G_1 0x2982 -#define PCI_CHIP_I946_GZ 0x2972 -#define PCI_CHIP_I965_GM 0x2A02 -#define PCI_CHIP_I965_GME 0x2A12 - -#define PCI_CHIP_GM45_GM 0x2A42 - -#define PCI_CHIP_IGD_E_G 0x2E02 -#define PCI_CHIP_Q45_G 0x2E12 -#define PCI_CHIP_G45_G 0x2E22 -#define PCI_CHIP_G41_G 0x2E32 - -#define PCI_CHIP_ILD_G 0x0042 -#define PCI_CHIP_ILM_G 0x0046 - -#define IS_MOBILE(devid) (devid == PCI_CHIP_I855_GM || \ - devid == PCI_CHIP_I915_GM || \ - devid == PCI_CHIP_I945_GM || \ - devid == PCI_CHIP_I945_GME || \ - devid == PCI_CHIP_I965_GM || \ - devid == PCI_CHIP_I965_GME || \ - devid == PCI_CHIP_GM45_GM || IS_IGD(devid)) - -#define IS_G45(devid) (devid == PCI_CHIP_IGD_E_G || \ - devid == PCI_CHIP_Q45_G || \ - devid == PCI_CHIP_G45_G || \ - devid == PCI_CHIP_G41_G) -#define IS_GM45(devid) (devid == PCI_CHIP_GM45_GM) -#define IS_G4X(devid) (IS_G45(devid) || IS_GM45(devid)) - -#define IS_ILD(devid) (devid == PCI_CHIP_ILD_G) -#define IS_ILM(devid) (devid == PCI_CHIP_ILM_G) -#define IS_IRONLAKE(devid) (IS_ILD(devid) || IS_ILM(devid)) - -#define IS_915(devid) (devid == PCI_CHIP_I915_G || \ - devid == PCI_CHIP_E7221_G || \ - devid == PCI_CHIP_I915_GM) - -#define IS_945(devid) (devid == PCI_CHIP_I945_G || \ - devid == PCI_CHIP_I945_GM || \ - devid == PCI_CHIP_I945_GME || \ - devid == PCI_CHIP_G33_G || \ - devid == PCI_CHIP_Q33_G || \ - devid == PCI_CHIP_Q35_G || IS_IGD(devid)) - -#define IS_965(devid) (devid == PCI_CHIP_I965_G || \ - devid == PCI_CHIP_I965_Q || \ - devid == PCI_CHIP_I965_G_1 || \ - devid == PCI_CHIP_I965_GM || \ - devid == PCI_CHIP_I965_GME || \ - devid == PCI_CHIP_I946_GZ || \ - IS_G4X(devid) || \ - IS_IRONLAKE(devid)) - -#define IS_9XX(devid) (IS_915(devid) || \ - IS_945(devid) || \ - IS_965(devid)) - - -#endif /* CAIRO_DRM_INTEL_PRIVATE_H */ diff --git a/gfx/cairo/cairo/src/drm/cairo-drm-intel-surface.c b/gfx/cairo/cairo/src/drm/cairo-drm-intel-surface.c deleted file mode 100644 index 8fe2c3ae3b..0000000000 --- a/gfx/cairo/cairo/src/drm/cairo-drm-intel-surface.c +++ /dev/null @@ -1,454 +0,0 @@ -/* Cairo - a vector graphics library with display and print output - * - * Copyright © 2009 Chris Wilson - * - * 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., 51 Franklin Street, Suite 500, Boston, MA 02110-1335, 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. - * - */ - -#include "cairoint.h" - -#include "cairo-drm-private.h" -#include "cairo-drm-intel-private.h" - -#include "cairo-default-context-private.h" -#include "cairo-error-private.h" -#include "cairo-image-surface-private.h" - -/* Basic generic/stub surface for intel chipsets */ - -#define MAX_SIZE 2048 - -static cairo_surface_t * -intel_surface_create_similar (void *abstract_surface, - cairo_content_t content, - int width, - int height) -{ - return cairo_image_surface_create (_cairo_format_from_content (content), - width, height); -} - -cairo_status_t -intel_surface_finish (void *abstract_surface) -{ - intel_surface_t *surface = abstract_surface; - - intel_bo_in_flight_add (to_intel_device (surface->drm.base.device), - to_intel_bo (surface->drm.bo)); - return _cairo_drm_surface_finish (&surface->drm); -} - -static void -surface_finish_and_destroy (cairo_surface_t *surface) -{ - cairo_surface_finish (surface); - cairo_surface_destroy (surface); -} - -cairo_status_t -intel_surface_acquire_source_image (void *abstract_surface, - cairo_image_surface_t **image_out, - void **image_extra) -{ - intel_surface_t *surface = abstract_surface; - cairo_surface_t *image; - cairo_status_t status; - void *ptr; - - if (surface->drm.fallback != NULL) { - image = surface->drm.fallback; - goto DONE; - } - - image = _cairo_surface_has_snapshot (&surface->drm.base, - &_cairo_image_surface_backend); - if (image != NULL) - goto DONE; - - if (surface->drm.base.backend->flush != NULL) { - status = surface->drm.base.backend->flush (surface); - if (unlikely (status)) - return status; - } - - ptr = intel_bo_map (to_intel_device (surface->drm.base.device), - to_intel_bo (surface->drm.bo)); - if (unlikely (ptr == NULL)) - return _cairo_error (CAIRO_STATUS_NO_MEMORY); - - image = cairo_image_surface_create_for_data (ptr, - surface->drm.format, - surface->drm.width, - surface->drm.height, - surface->drm.stride); - if (unlikely (image->status)) - return image->status; - - _cairo_surface_attach_snapshot (&surface->drm.base, image, surface_finish_and_destroy); - -DONE: - *image_out = (cairo_image_surface_t *) cairo_surface_reference (image); - *image_extra = NULL; - return CAIRO_STATUS_SUCCESS; -} - -void -intel_surface_release_source_image (void *abstract_surface, - cairo_image_surface_t *image, - void *image_extra) -{ - cairo_surface_destroy (&image->base); -} - -cairo_surface_t * -intel_surface_map_to_image (void *abstract_surface) -{ - intel_surface_t *surface = abstract_surface; - - if (surface->drm.fallback == NULL) { - cairo_surface_t *image; - cairo_status_t status; - void *ptr; - - if (surface->drm.base.backend->flush != NULL) { - status = surface->drm.base.backend->flush (surface); - if (unlikely (status)) - return _cairo_surface_create_in_error (status); - } - - ptr = intel_bo_map (to_intel_device (surface->drm.base.device), - to_intel_bo (surface->drm.bo)); - if (unlikely (ptr == NULL)) - return _cairo_surface_create_in_error (CAIRO_STATUS_NO_MEMORY); - - image = cairo_image_surface_create_for_data (ptr, - surface->drm.format, - surface->drm.width, - surface->drm.height, - surface->drm.stride); - if (unlikely (image->status)) - return image; - - surface->drm.fallback = image; - } - - return surface->drm.fallback; -} - -cairo_status_t -intel_surface_flush (void *abstract_surface, unsigned flags) -{ - intel_surface_t *surface = abstract_surface; - cairo_status_t status; - - if (flags) - return CAIRO_STATUS_SUCCESS; - - if (surface->drm.fallback == NULL) - return CAIRO_STATUS_SUCCESS; - - /* kill any outstanding maps */ - cairo_surface_finish (surface->drm.fallback); - - status = cairo_surface_status (surface->drm.fallback); - cairo_surface_destroy (surface->drm.fallback); - surface->drm.fallback = NULL; - - return status; -} - -static cairo_int_status_t -intel_surface_paint (void *abstract_surface, - cairo_operator_t op, - const cairo_pattern_t *source, - cairo_clip_t *clip) -{ - return _cairo_surface_paint (intel_surface_map_to_image (abstract_surface), - op, source, clip); -} - -static cairo_int_status_t -intel_surface_mask (void *abstract_surface, - cairo_operator_t op, - const cairo_pattern_t *source, - const cairo_pattern_t *mask, - cairo_clip_t *clip) -{ - return _cairo_surface_mask (intel_surface_map_to_image (abstract_surface), - op, source, mask, clip); -} - -static cairo_int_status_t -intel_surface_stroke (void *abstract_surface, - cairo_operator_t op, - const cairo_pattern_t *source, - cairo_path_fixed_t *path, - const cairo_stroke_style_t *stroke_style, - const cairo_matrix_t *ctm, - const cairo_matrix_t *ctm_inverse, - double tolerance, - cairo_antialias_t antialias, - cairo_clip_t *clip) -{ - return _cairo_surface_stroke (intel_surface_map_to_image (abstract_surface), - op, source, path, stroke_style, ctm, ctm_inverse, - tolerance, antialias, clip); -} - -static cairo_int_status_t -intel_surface_fill (void *abstract_surface, - cairo_operator_t op, - const cairo_pattern_t *source, - cairo_path_fixed_t *path, - cairo_fill_rule_t fill_rule, - double tolerance, - cairo_antialias_t antialias, - cairo_clip_t *clip) -{ - return _cairo_surface_fill (intel_surface_map_to_image (abstract_surface), - op, source, path, fill_rule, - tolerance, antialias, clip); -} - -static cairo_int_status_t -intel_surface_glyphs (void *abstract_surface, - cairo_operator_t op, - const cairo_pattern_t *source, - cairo_glyph_t *glyphs, - int num_glyphs, - cairo_scaled_font_t *scaled_font, - cairo_clip_t *clip, - int *num_remaining) -{ - *num_remaining = 0; - return _cairo_surface_show_text_glyphs (intel_surface_map_to_image (abstract_surface), - op, source, - NULL, 0, - glyphs, num_glyphs, - NULL, 0, 0, - scaled_font, clip); -} - -static const cairo_surface_backend_t intel_surface_backend = { - CAIRO_SURFACE_TYPE_DRM, - _cairo_default_context_create, - - intel_surface_create_similar, - intel_surface_finish, - - NULL, - intel_surface_acquire_source_image, - intel_surface_release_source_image, - - NULL, NULL, NULL, - NULL, /* composite */ - NULL, /* fill */ - NULL, /* trapezoids */ - NULL, /* span */ - NULL, /* check-span */ - - NULL, /* copy_page */ - NULL, /* show_page */ - _cairo_drm_surface_get_extents, - NULL, /* old-glyphs */ - _cairo_drm_surface_get_font_options, - - intel_surface_flush, - NULL, /* mark dirty */ - NULL, NULL, /* font/glyph fini */ - - intel_surface_paint, - intel_surface_mask, - intel_surface_stroke, - intel_surface_fill, - intel_surface_glyphs, -}; - -void -intel_surface_init (intel_surface_t *surface, - const cairo_surface_backend_t *backend, - cairo_drm_device_t *device, - cairo_format_t format, - int width, int height) -{ - _cairo_surface_init (&surface->drm.base, - backend, - &device->base, - _cairo_content_from_format (format), - FALSE); - - _cairo_drm_surface_init (&surface->drm, format, width, height); - - surface->snapshot_cache_entry.hash = 0; -} - -static cairo_surface_t * -intel_surface_create (cairo_drm_device_t *device, - cairo_format_t format, - int width, int height) -{ - intel_surface_t *surface; - cairo_status_t status; - - surface = _cairo_malloc (sizeof (intel_surface_t)); - if (unlikely (surface == NULL)) - return _cairo_surface_create_in_error (_cairo_error (CAIRO_STATUS_NO_MEMORY)); - - intel_surface_init (surface, &intel_surface_backend, device, - format, width, height); - - if (width && height) { - /* Vol I, p134: size restrictions for textures */ - width = (width + 3) & -4; - height = (height + 1) & -2; - surface->drm.stride = - cairo_format_stride_for_width (surface->drm.format, width); - surface->drm.bo = &intel_bo_create (to_intel_device (&device->base), - surface->drm.stride * height, - surface->drm.stride * height, - TRUE, I915_TILING_NONE, surface->drm.stride)->base; - if (surface->drm.bo == NULL) { - status = _cairo_drm_surface_finish (&surface->drm); - free (surface); - return _cairo_surface_create_in_error (_cairo_error (CAIRO_STATUS_NO_MEMORY)); - } - } - - return &surface->drm.base; -} - -static cairo_surface_t * -intel_surface_create_for_name (cairo_drm_device_t *device, - unsigned int name, - cairo_format_t format, - int width, int height, int stride) -{ - intel_surface_t *surface; - cairo_status_t status; - - switch (format) { - default: - case CAIRO_FORMAT_INVALID: - case CAIRO_FORMAT_A1: - return _cairo_surface_create_in_error (_cairo_error (CAIRO_STATUS_INVALID_FORMAT)); - case CAIRO_FORMAT_ARGB32: - case CAIRO_FORMAT_RGB16_565: - case CAIRO_FORMAT_RGB24: - case CAIRO_FORMAT_A8: - break; - } - - if (stride < cairo_format_stride_for_width (format, width)) - return _cairo_surface_create_in_error (_cairo_error (CAIRO_STATUS_INVALID_STRIDE)); - - surface = _cairo_malloc (sizeof (intel_surface_t)); - if (unlikely (surface == NULL)) - return _cairo_surface_create_in_error (_cairo_error (CAIRO_STATUS_NO_MEMORY)); - - intel_surface_init (surface, &intel_surface_backend, - device, format, width, height); - - if (width && height) { - surface->drm.stride = stride; - - surface->drm.bo = &intel_bo_create_for_name (to_intel_device (&device->base), - name)->base; - if (unlikely (surface->drm.bo == NULL)) { - status = _cairo_drm_surface_finish (&surface->drm); - free (surface); - return _cairo_surface_create_in_error (_cairo_error - (CAIRO_STATUS_NO_MEMORY)); - } - } - - return &surface->drm.base; -} - -static cairo_status_t -intel_surface_enable_scan_out (void *abstract_surface) -{ - intel_surface_t *surface = abstract_surface; - - if (unlikely (surface->drm.bo == NULL)) - return _cairo_error (CAIRO_STATUS_INVALID_SIZE); - - to_intel_bo (surface->drm.bo)->tiling = I915_TILING_X; - - return CAIRO_STATUS_SUCCESS; -} - -static cairo_int_status_t -intel_device_throttle (cairo_drm_device_t *device) -{ - intel_throttle (to_intel_device (&device->base)); - return CAIRO_STATUS_SUCCESS; -} - -static void -intel_device_destroy (void *data) -{ - intel_device_t *device = data; - - intel_device_fini (device); - - free (data); -} - -cairo_drm_device_t * -_cairo_drm_intel_device_create (int fd, dev_t dev, int vendor_id, int chip_id) -{ - intel_device_t *device; - cairo_status_t status; - - if (! intel_info (fd, NULL)) - return NULL; - - device = _cairo_malloc (sizeof (intel_device_t)); - if (unlikely (device == NULL)) - return (cairo_drm_device_t *) _cairo_device_create_in_error (CAIRO_STATUS_NO_MEMORY); - - status = intel_device_init (device, fd); - if (unlikely (status)) { - free (device); - return (cairo_drm_device_t *) _cairo_device_create_in_error (status); - } - - device->base.surface.create = intel_surface_create; - device->base.surface.create_for_name = intel_surface_create_for_name; - device->base.surface.create_from_cacheable_image = NULL; - device->base.surface.flink = _cairo_drm_surface_flink; - device->base.surface.enable_scan_out = intel_surface_enable_scan_out; - - device->base.surface.map_to_image = intel_surface_map_to_image; - - device->base.device.flush = NULL; - device->base.device.throttle = intel_device_throttle; - device->base.device.destroy = intel_device_destroy; - - return _cairo_drm_device_init (&device->base, - fd, dev, - vendor_id, chip_id, - MAX_SIZE); -} diff --git a/gfx/cairo/cairo/src/drm/cairo-drm-intel.c b/gfx/cairo/cairo/src/drm/cairo-drm-intel.c deleted file mode 100644 index e6fb83dd51..0000000000 --- a/gfx/cairo/cairo/src/drm/cairo-drm-intel.c +++ /dev/null @@ -1,1347 +0,0 @@ -/* Cairo - a vector graphics library with display and print output - * - * Copyright © 2009 Chris Wilson - * - * 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., 51 Franklin Street, Suite 500, Boston, MA 02110-1335, 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. - * - */ - -#include "cairoint.h" - -#include "cairo-drm-private.h" -#include "cairo-drm-intel-private.h" -#include "cairo-drm-intel-ioctl-private.h" - -#include "cairo-error-private.h" -#include "cairo-freelist-private.h" -#include "cairo-pattern-private.h" -#include "cairo-image-surface-private.h" - -#include <sys/ioctl.h> -#include <sys/mman.h> -#include <errno.h> -#include <drm/i915_drm.h> - -#define GLYPH_CACHE_WIDTH 1024 -#define GLYPH_CACHE_HEIGHT 1024 -#define GLYPH_CACHE_MIN_SIZE 1 -#define GLYPH_CACHE_MAX_SIZE 128 - -#define IMAGE_CACHE_WIDTH 1024 -#define IMAGE_CACHE_HEIGHT 1024 - -int -intel_get (int fd, int param) -{ - struct drm_i915_getparam gp; - int value; - - gp.param = param; - gp.value = &value; - if (ioctl (fd, DRM_IOCTL_I915_GETPARAM, &gp) < 0) - return 0; - - VG (VALGRIND_MAKE_MEM_DEFINED (&value, sizeof (value))); - - return value; -} - -cairo_bool_t -intel_info (int fd, uint64_t *gtt_size) -{ - struct drm_i915_gem_get_aperture info; - - if (! intel_get (fd, I915_PARAM_HAS_GEM)) - return FALSE; - - if (! intel_get (fd, I915_PARAM_HAS_EXECBUF2)) - return FALSE; - - if (ioctl (fd, DRM_IOCTL_I915_GEM_GET_APERTURE, &info) < 0) - return FALSE; - - VG (VALGRIND_MAKE_MEM_DEFINED (&info, sizeof (info))); - - if (gtt_size != NULL) - *gtt_size = info.aper_size; - - return TRUE; -} - -void -intel_bo_write (const intel_device_t *device, - intel_bo_t *bo, - unsigned long offset, - unsigned long size, - const void *data) -{ - struct drm_i915_gem_pwrite pwrite; - int ret; - - assert (bo->tiling == I915_TILING_NONE); - assert (size); - assert (offset < bo->base.size); - assert (size+offset <= bo->base.size); - - intel_bo_set_tiling (device, bo); - - assert (bo->_tiling == I915_TILING_NONE); - - memset (&pwrite, 0, sizeof (pwrite)); - pwrite.handle = bo->base.handle; - pwrite.offset = offset; - pwrite.size = size; - pwrite.data_ptr = (uint64_t) (uintptr_t) data; - do { - ret = ioctl (device->base.fd, DRM_IOCTL_I915_GEM_PWRITE, &pwrite); - } while (ret == -1 && errno == EINTR); - assert (ret == 0); - - bo->busy = FALSE; -} - -void -intel_bo_read (const intel_device_t *device, - intel_bo_t *bo, - unsigned long offset, - unsigned long size, - void *data) -{ - struct drm_i915_gem_pread pread; - int ret; - - assert (bo->tiling == I915_TILING_NONE); - assert (size); - assert (offset < bo->base.size); - assert (size+offset <= bo->base.size); - - intel_bo_set_tiling (device, bo); - - assert (bo->_tiling == I915_TILING_NONE); - - memset (&pread, 0, sizeof (pread)); - pread.handle = bo->base.handle; - pread.offset = offset; - pread.size = size; - pread.data_ptr = (uint64_t) (uintptr_t) data; - do { - ret = ioctl (device->base.fd, DRM_IOCTL_I915_GEM_PREAD, &pread); - } while (ret == -1 && errno == EINTR); - assert (ret == 0); - - bo->cpu = TRUE; - bo->busy = FALSE; -} - -void * -intel_bo_map (const intel_device_t *device, intel_bo_t *bo) -{ - struct drm_i915_gem_set_domain set_domain; - uint32_t domain; - int ret; - - intel_bo_set_tiling (device, bo); - - if (bo->virtual != NULL) - return bo->virtual; - - if (bo->cpu && bo->tiling == I915_TILING_NONE) { - struct drm_i915_gem_mmap mmap_arg; - - mmap_arg.handle = bo->base.handle; - mmap_arg.offset = 0; - mmap_arg.size = bo->base.size; - mmap_arg.addr_ptr = 0; - - do { - ret = ioctl (device->base.fd, DRM_IOCTL_I915_GEM_MMAP, &mmap_arg); - } while (ret == -1 && errno == EINTR); - if (unlikely (ret != 0)) { - _cairo_error_throw (CAIRO_STATUS_NO_MEMORY); - return NULL; - } - - bo->virtual = (void *) (uintptr_t) mmap_arg.addr_ptr; - domain = I915_GEM_DOMAIN_CPU; - } else { - struct drm_i915_gem_mmap_gtt mmap_arg; - void *ptr; - - /* Get the fake offset back... */ - mmap_arg.handle = bo->base.handle; - do { - ret = ioctl (device->base.fd, - DRM_IOCTL_I915_GEM_MMAP_GTT, &mmap_arg); - } while (ret == -1 && errno == EINTR); - if (unlikely (ret != 0)) { - _cairo_error_throw (CAIRO_STATUS_NO_MEMORY); - return NULL; - } - - /* and mmap it */ - ptr = mmap (0, bo->base.size, PROT_READ | PROT_WRITE, - MAP_SHARED, device->base.fd, - mmap_arg.offset); - if (unlikely (ptr == MAP_FAILED)) { - _cairo_error_throw (CAIRO_STATUS_NO_MEMORY); - return NULL; - } - - bo->virtual = ptr; - domain = I915_GEM_DOMAIN_GTT; - } - - VG (VALGRIND_MAKE_MEM_DEFINED (bo->virtual, bo->base.size)); - - set_domain.handle = bo->base.handle; - set_domain.read_domains = domain; - set_domain.write_domain = domain; - - do { - ret = ioctl (device->base.fd, - DRM_IOCTL_I915_GEM_SET_DOMAIN, - &set_domain); - } while (ret == -1 && errno == EINTR); - - if (ret != 0) { - intel_bo_unmap (bo); - _cairo_error_throw (CAIRO_STATUS_DEVICE_ERROR); - return NULL; - } - - bo->busy = FALSE; - return bo->virtual; -} - -void -intel_bo_unmap (intel_bo_t *bo) -{ - munmap (bo->virtual, bo->base.size); - bo->virtual = NULL; -} - -cairo_bool_t -intel_bo_is_inactive (const intel_device_t *device, intel_bo_t *bo) -{ - struct drm_i915_gem_busy busy; - - if (! bo->busy) - return TRUE; - - /* Is this buffer busy for our intended usage pattern? */ - busy.handle = bo->base.handle; - busy.busy = 1; - ioctl (device->base.fd, DRM_IOCTL_I915_GEM_BUSY, &busy); - - bo->busy = busy.busy; - return ! busy.busy; -} - -cairo_bool_t -intel_bo_wait (const intel_device_t *device, const intel_bo_t *bo) -{ - struct drm_i915_gem_set_domain set_domain; - int ret; - - set_domain.handle = bo->base.handle; - set_domain.read_domains = I915_GEM_DOMAIN_GTT; - set_domain.write_domain = 0; - - do { - ret = ioctl (device->base.fd, DRM_IOCTL_I915_GEM_SET_DOMAIN, &set_domain); - } while (ret == -1 && errno == EINTR); - - return ret == 0; -} - -static inline int -pot (int v) -{ - v--; - v |= v >> 1; - v |= v >> 2; - v |= v >> 4; - v |= v >> 8; - v |= v >> 16; - v++; - return v; -} - -cairo_bool_t -intel_bo_madvise (intel_device_t *device, - intel_bo_t *bo, - int advice) -{ - struct drm_i915_gem_madvise madv; - - madv.handle = bo->base.handle; - madv.madv = advice; - madv.retained = TRUE; - ioctl (device->base.fd, DRM_IOCTL_I915_GEM_MADVISE, &madv); - return madv.retained; -} - -static void -intel_bo_set_real_size (intel_device_t *device, - intel_bo_t *bo, - size_t size) -{ - struct drm_i915_gem_real_size arg; - int ret; - - return; - - if (size == bo->base.size) - return; - - arg.handle = bo->base.handle; - arg.size = size; - do { - ret = ioctl (device->base.fd, DRM_IOCTL_I915_GEM_REAL_SIZE, &arg); - } while (ret == -1 && errno == EINTR); - - if (ret == 0) { - if (size > bo->base.size) { - assert (bo->exec == NULL); - bo->cpu = TRUE; - bo->busy = FALSE; - } - - bo->base.size = size; - } -} - -intel_bo_t * -intel_bo_create (intel_device_t *device, - uint32_t max_size, - uint32_t real_size, - cairo_bool_t gpu_target, - uint32_t tiling, - uint32_t stride) -{ - intel_bo_t *bo; - uint32_t cache_size; - struct drm_i915_gem_create create; - int bucket; - int ret; - - max_size = (max_size + 4095) & -4096; - real_size = (real_size + 4095) & -4096; - cache_size = pot (max_size); - bucket = ffs (cache_size / 4096) - 1; - if (bucket >= INTEL_BO_CACHE_BUCKETS) - cache_size = max_size; - - if (gpu_target) { - intel_bo_t *first = NULL; - - cairo_list_foreach_entry (bo, intel_bo_t, - &device->bo_in_flight, - cache_list) - { - assert (bo->exec != NULL); - if (tiling && bo->_tiling && - (bo->_tiling != tiling || bo->_stride != stride)) - { - continue; - } - - if (real_size <= bo->base.size) { - if (real_size >= bo->base.size/2) { - cairo_list_del (&bo->cache_list); - bo = intel_bo_reference (bo); - goto DONE; - } - - if (first == NULL) - first = bo; - } - } - - if (first != NULL) { - cairo_list_del (&first->cache_list); - bo = intel_bo_reference (first); - goto DONE; - } - } - - /* no cached buffer available, allocate fresh */ - bo = _cairo_freepool_alloc (&device->bo_pool); - if (unlikely (bo == NULL)) { - _cairo_error_throw (CAIRO_STATUS_NO_MEMORY); - return bo; - } - - cairo_list_init (&bo->cache_list); - - bo->base.name = 0; - - bo->offset = 0; - bo->virtual = NULL; - bo->cpu = TRUE; - - bo->_tiling = I915_TILING_NONE; - bo->_stride = 0; - bo->purgeable = 0; - bo->busy = FALSE; - - bo->opaque0 = 0; - bo->opaque1 = 0; - - bo->exec = NULL; - bo->batch_read_domains = 0; - bo->batch_write_domain = 0; - cairo_list_init (&bo->link); - - create.size = cache_size; - create.handle = 0; - ret = ioctl (device->base.fd, DRM_IOCTL_I915_GEM_CREATE, &create); - if (unlikely (ret != 0)) { - _cairo_error_throw (CAIRO_STATUS_NO_MEMORY); - _cairo_freepool_free (&device->bo_pool, bo); - return NULL; - } - - bo->base.handle = create.handle; - bo->full_size = bo->base.size = create.size; - - intel_bo_set_real_size (device, bo, real_size); - CAIRO_REFERENCE_COUNT_INIT (&bo->base.ref_count, 1); -DONE: - bo->tiling = tiling; - bo->stride = stride; - return bo; -} - -intel_bo_t * -intel_bo_create_for_name (intel_device_t *device, uint32_t name) -{ - struct drm_i915_gem_get_tiling get_tiling; - cairo_status_t status; - intel_bo_t *bo; - int ret; - - bo = _cairo_freepool_alloc (&device->bo_pool); - if (unlikely (bo == NULL)) { - _cairo_error_throw (CAIRO_STATUS_NO_MEMORY); - return NULL; - } - - status = _cairo_drm_bo_open_for_name (&device->base, &bo->base, name); - if (unlikely (status)) - goto FAIL; - - CAIRO_REFERENCE_COUNT_INIT (&bo->base.ref_count, 1); - cairo_list_init (&bo->cache_list); - - bo->full_size = bo->base.size; - bo->offset = 0; - bo->virtual = NULL; - bo->purgeable = 0; - bo->busy = TRUE; - bo->cpu = FALSE; - - bo->opaque0 = 0; - bo->opaque1 = 0; - - bo->exec = NULL; - bo->batch_read_domains = 0; - bo->batch_write_domain = 0; - cairo_list_init (&bo->link); - - memset (&get_tiling, 0, sizeof (get_tiling)); - get_tiling.handle = bo->base.handle; - - ret = ioctl (device->base.fd, DRM_IOCTL_I915_GEM_GET_TILING, &get_tiling); - if (unlikely (ret != 0)) { - _cairo_error_throw (CAIRO_STATUS_DEVICE_ERROR); - _cairo_drm_bo_close (&device->base, &bo->base); - goto FAIL; - } - - bo->_tiling = bo->tiling = get_tiling.tiling_mode; - // bo->stride = get_tiling.stride; /* XXX not available from get_tiling */ - - return bo; - -FAIL: - _cairo_freepool_free (&device->bo_pool, bo); - return NULL; -} - -static void -intel_bo_release (void *_dev, void *_bo) -{ - intel_device_t *device = _dev; - intel_bo_t *bo = _bo; - - if (bo->virtual != NULL) - intel_bo_unmap (bo); - - assert (bo->exec == NULL); - assert (cairo_list_is_empty (&bo->cache_list)); - - _cairo_drm_bo_close (&device->base, &bo->base); - _cairo_freepool_free (&device->bo_pool, bo); -} - -void -intel_bo_set_tiling (const intel_device_t *device, - intel_bo_t *bo) -{ - struct drm_i915_gem_set_tiling set_tiling; - int ret; - - if (bo->tiling == bo->_tiling && - (bo->tiling == I915_TILING_NONE || bo->stride == bo->_stride)) - return; - - do { - set_tiling.handle = bo->base.handle; - set_tiling.tiling_mode = bo->tiling; - set_tiling.stride = bo->stride; - - ret = ioctl (device->base.fd, DRM_IOCTL_I915_GEM_SET_TILING, &set_tiling); - } while (ret == -1 && errno == EINTR); - - assert (ret == 0); - bo->_tiling = bo->tiling; - bo->_stride = bo->stride; -} - -static cairo_status_t -_intel_bo_put_a1_image (intel_device_t *device, - intel_bo_t *bo, - cairo_image_surface_t *src, - int src_x, int src_y, - int width, int height, - int dst_x, int dst_y) -{ - uint8_t buf[CAIRO_STACK_BUFFER_SIZE]; - uint8_t *a8 = buf; - uint8_t *data; - int x; - - data = src->data + src_y * src->stride; - - if (bo->tiling == I915_TILING_NONE && width == bo->stride) { - uint8_t *p; - int size; - - size = bo->stride * height; - if (size > (int) sizeof (buf)) { - a8 = _cairo_malloc_ab (bo->stride, height); - if (a8 == NULL) - return _cairo_error (CAIRO_STATUS_NO_MEMORY); - } - - p = a8; - while (height--) { - for (x = 0; x < width; x++) { - int i = src_x + x; - int byte = i / 8; - int bit = i % 8; - p[x] = data[byte] & (1 << bit) ? 0xff : 0x00; - } - - data += src->stride; - p += bo->stride; - } - - intel_bo_write (device, bo, - dst_y * bo->stride + dst_x, /* XXX bo_offset */ - size, a8); - } else { - uint8_t *dst; - - if (width > (int) sizeof (buf)) { - a8 = _cairo_malloc (width); - if (a8 == NULL) - return _cairo_error (CAIRO_STATUS_NO_MEMORY); - } - - dst = intel_bo_map (device, bo); - if (dst == NULL) { - if (a8 != buf) - free (a8); - return _cairo_error (CAIRO_STATUS_DEVICE_ERROR); - } - - dst += dst_y * bo->stride + dst_x; /* XXX bo_offset */ - while (height--) { - for (x = 0; x < width; x++) { - int i = src_x + x; - int byte = i / 8; - int bit = i % 8; - a8[x] = data[byte] & (1 << bit) ? 0xff : 0x00; - } - - memcpy (dst, a8, width); - dst += bo->stride; - data += src->stride; - } - } - - if (a8 != buf) - free (a8); - - return CAIRO_STATUS_SUCCESS; -} - -cairo_status_t -intel_bo_put_image (intel_device_t *device, - intel_bo_t *bo, - cairo_image_surface_t *src, - int src_x, int src_y, - int width, int height, - int dst_x, int dst_y) -{ - uint8_t *data; - int size; - int offset; - - intel_bo_set_tiling (device, bo); - - offset = dst_y * bo->stride; - data = src->data + src_y * src->stride; - switch (src->format) { - case CAIRO_FORMAT_ARGB32: - case CAIRO_FORMAT_RGB24: - offset += 4 * dst_x; - data += 4 * src_x; - size = 4 * width; - break; - case CAIRO_FORMAT_RGB16_565: - offset += 2 * dst_x; - data += 2 * src_x; - size = 2 * width; - break; - case CAIRO_FORMAT_A8: - offset += dst_x; - data += src_x; - size = width; - break; - case CAIRO_FORMAT_A1: - return _intel_bo_put_a1_image (device, bo, src, - src_x, src_y, - width, height, - dst_x, dst_y); - default: - case CAIRO_FORMAT_INVALID: - return _cairo_error (CAIRO_STATUS_INVALID_FORMAT); - } - - if (bo->tiling == I915_TILING_NONE && src->stride == bo->stride) { - intel_bo_write (device, bo, offset, bo->stride * height, data); - } else { - uint8_t *dst; - - dst = intel_bo_map (device, bo); - if (unlikely (dst == NULL)) - return _cairo_error (CAIRO_STATUS_DEVICE_ERROR); - - dst += offset; - while (height--) { - memcpy (dst, data, size); - dst += bo->stride; - data += src->stride; - } - } - - return CAIRO_STATUS_SUCCESS; -} - -static cairo_bool_t -_intel_snapshot_cache_entry_can_remove (const void *closure) -{ - return TRUE; -} - -static void -_intel_snapshot_cache_entry_destroy (void *closure) -{ - intel_surface_t *surface = cairo_container_of (closure, - intel_surface_t, - snapshot_cache_entry); - - surface->snapshot_cache_entry.hash = 0; -} - -cairo_status_t -intel_device_init (intel_device_t *device, int fd) -{ - struct drm_i915_gem_get_aperture aperture; - cairo_status_t status; - size_t size; - int ret; - int n; - - ret = ioctl (fd, DRM_IOCTL_I915_GEM_GET_APERTURE, &aperture); - if (ret != 0) - return _cairo_error (CAIRO_STATUS_DEVICE_ERROR); - - CAIRO_MUTEX_INIT (device->mutex); - - device->gtt_max_size = aperture.aper_size; - device->gtt_avail_size = aperture.aper_available_size; - device->gtt_avail_size -= device->gtt_avail_size >> 5; - - size = aperture.aper_size / 8; - device->snapshot_cache_max_size = size / 4; - status = _cairo_cache_init (&device->snapshot_cache, - NULL, - _intel_snapshot_cache_entry_can_remove, - _intel_snapshot_cache_entry_destroy, - size); - if (unlikely (status)) - return status; - - for (n = 0; n < ARRAY_LENGTH (device->glyph_cache); n++) { - device->glyph_cache[n].buffer.bo = NULL; - cairo_list_init (&device->glyph_cache[n].rtree.pinned); - } - cairo_list_init (&device->fonts); - - device->gradient_cache.size = 0; - - device->base.bo.release = intel_bo_release; - - return CAIRO_STATUS_SUCCESS; -} - -static void -_intel_gradient_cache_fini (intel_device_t *device) -{ - unsigned int n; - - for (n = 0; n < device->gradient_cache.size; n++) { - _cairo_pattern_fini (&device->gradient_cache.cache[n].pattern.base); - if (device->gradient_cache.cache[n].buffer.bo != NULL) - cairo_drm_bo_destroy (&device->base.base, - &device->gradient_cache.cache[n].buffer.bo->base); - } -} - -static void -_intel_glyph_cache_fini (intel_device_t *device, intel_buffer_cache_t *cache) -{ - if (cache->buffer.bo == NULL) - return; - - intel_bo_destroy (device, cache->buffer.bo); - _cairo_rtree_fini (&cache->rtree); -} - -void -intel_device_fini (intel_device_t *device) -{ - cairo_scaled_font_t *scaled_font, *next_scaled_font; - int n; - - cairo_list_foreach_entry_safe (scaled_font, - next_scaled_font, - cairo_scaled_font_t, - &device->fonts, - link) - { - _cairo_scaled_font_revoke_ownership (scaled_font); - } - - for (n = 0; n < ARRAY_LENGTH (device->glyph_cache); n++) - _intel_glyph_cache_fini (device, &device->glyph_cache[n]); - - _cairo_cache_fini (&device->snapshot_cache); - - _intel_gradient_cache_fini (device); - _cairo_freepool_fini (&device->bo_pool); - - _cairo_drm_device_fini (&device->base); -} - -void -intel_throttle (intel_device_t *device) -{ - ioctl (device->base.fd, DRM_IOCTL_I915_GEM_THROTTLE); -} - -void -intel_glyph_cache_unpin (intel_device_t *device) -{ - int n; - - for (n = 0; n < ARRAY_LENGTH (device->glyph_cache); n++) - _cairo_rtree_unpin (&device->glyph_cache[n].rtree); -} - -static cairo_status_t -intel_glyph_cache_add_glyph (intel_device_t *device, - intel_buffer_cache_t *cache, - cairo_scaled_glyph_t *scaled_glyph) -{ - cairo_image_surface_t *glyph_surface = scaled_glyph->surface; - intel_glyph_t *glyph; - cairo_rtree_node_t *node = NULL; - double sf_x, sf_y; - cairo_status_t status; - uint8_t *dst, *src; - int width, height; - - width = glyph_surface->width; - if (width < GLYPH_CACHE_MIN_SIZE) - width = GLYPH_CACHE_MIN_SIZE; - height = glyph_surface->height; - if (height < GLYPH_CACHE_MIN_SIZE) - height = GLYPH_CACHE_MIN_SIZE; - - /* search for an available slot */ - status = _cairo_rtree_insert (&cache->rtree, width, height, &node); - /* search for an unpinned slot */ - if (status == CAIRO_INT_STATUS_UNSUPPORTED) { - status = _cairo_rtree_evict_random (&cache->rtree, width, height, &node); - if (status == CAIRO_STATUS_SUCCESS) - status = _cairo_rtree_node_insert (&cache->rtree, node, width, height, &node); - } - if (unlikely (status)) - return status; - - /* XXX streaming upload? */ - - height = glyph_surface->height; - src = glyph_surface->data; - dst = cache->buffer.bo->virtual; - if (dst == NULL) { - dst = intel_bo_map (device, cache->buffer.bo); - if (unlikely (dst == NULL)) - return _cairo_error (CAIRO_STATUS_DEVICE_ERROR); - } - - dst += node->y * cache->buffer.stride; - switch (glyph_surface->format) { - case CAIRO_FORMAT_A1: { - uint8_t buf[CAIRO_STACK_BUFFER_SIZE]; - uint8_t *a8 = buf; - int x; - - if (width > (int) sizeof (buf)) { - a8 = _cairo_malloc (width); - if (unlikely (a8 == NULL)) - return _cairo_error (CAIRO_STATUS_NO_MEMORY); - } - - dst += node->x; - width = glyph_surface->width; - while (height--) { - for (x = 0; x < width; x++) - a8[x] = src[x>>3] & (1 << (x&7)) ? 0xff : 0x00; - - memcpy (dst, a8, width); - dst += cache->buffer.stride; - src += glyph_surface->stride; - } - - if (a8 != buf) - free (a8); - break; - } - - case CAIRO_FORMAT_A8: - dst += node->x; - width = glyph_surface->width; - while (height--) { - memcpy (dst, src, width); - dst += cache->buffer.stride; - src += glyph_surface->stride; - } - break; - - case CAIRO_FORMAT_ARGB32: - dst += 4*node->x; - width = 4*glyph_surface->width; - while (height--) { - memcpy (dst, src, width); - dst += cache->buffer.stride; - src += glyph_surface->stride; - } - break; - default: - case CAIRO_FORMAT_RGB16_565: - case CAIRO_FORMAT_RGB24: - case CAIRO_FORMAT_INVALID: - ASSERT_NOT_REACHED; - return _cairo_error (CAIRO_STATUS_INVALID_FORMAT); - } - - scaled_glyph->surface_private = node; - - glyph= (intel_glyph_t *) node; - glyph->node.owner = &scaled_glyph->surface_private; - glyph->cache = cache; - - /* compute tex coords: bottom-right, bottom-left, top-left */ - sf_x = 1. / cache->buffer.width; - sf_y = 1. / cache->buffer.height; - glyph->texcoord[0] = - texcoord_2d_16 (sf_x * (node->x + glyph_surface->width), - sf_y * (node->y + glyph_surface->height)); - glyph->texcoord[1] = - texcoord_2d_16 (sf_x * node->x, - sf_y * (node->y + glyph_surface->height)); - glyph->texcoord[2] = - texcoord_2d_16 (sf_x * node->x, - sf_y * node->y); - - glyph->width = glyph_surface->width; - glyph->height = glyph_surface->height; - - return CAIRO_STATUS_SUCCESS; -} - -void -intel_scaled_glyph_fini (cairo_scaled_glyph_t *scaled_glyph, - cairo_scaled_font_t *scaled_font) -{ - intel_glyph_t *glyph; - - glyph = scaled_glyph->surface_private; - if (glyph != NULL) { - /* XXX thread-safety? Probably ok due to the frozen scaled-font. */ - glyph->node.owner = NULL; - if (! glyph->node.pinned) - _cairo_rtree_node_remove (&glyph->cache->rtree, &glyph->node); - } -} - -void -intel_scaled_font_fini (cairo_scaled_font_t *scaled_font) -{ - cairo_list_del (&scaled_font->link); -} - -static cairo_status_t -intel_get_glyph_cache (intel_device_t *device, - cairo_format_t format, - intel_buffer_cache_t **out) -{ - intel_buffer_cache_t *cache; - cairo_status_t status; - - switch (format) { - case CAIRO_FORMAT_ARGB32: - cache = &device->glyph_cache[0]; - format = CAIRO_FORMAT_ARGB32; - break; - case CAIRO_FORMAT_A8: - case CAIRO_FORMAT_A1: - cache = &device->glyph_cache[1]; - format = CAIRO_FORMAT_A8; - break; - default: - case CAIRO_FORMAT_RGB16_565: - case CAIRO_FORMAT_RGB24: - case CAIRO_FORMAT_INVALID: - ASSERT_NOT_REACHED; - return _cairo_error (CAIRO_STATUS_INVALID_FORMAT); - } - - if (unlikely (cache->buffer.bo == NULL)) { - status = intel_buffer_cache_init (cache, device, format, - INTEL_GLYPH_CACHE_WIDTH, - INTEL_GLYPH_CACHE_HEIGHT); - if (unlikely (status)) - return status; - - _cairo_rtree_init (&cache->rtree, - INTEL_GLYPH_CACHE_WIDTH, - INTEL_GLYPH_CACHE_HEIGHT, - 0, sizeof (intel_glyph_t)); - } - - *out = cache; - return CAIRO_STATUS_SUCCESS; -} - -cairo_int_status_t -intel_get_glyph (intel_device_t *device, - cairo_scaled_font_t *scaled_font, - cairo_scaled_glyph_t *scaled_glyph) -{ - cairo_bool_t own_surface = FALSE; - intel_buffer_cache_t *cache; - cairo_status_t status; - - if (scaled_glyph->surface == NULL) { - status = - scaled_font->backend->scaled_glyph_init (scaled_font, - scaled_glyph, - CAIRO_SCALED_GLYPH_INFO_SURFACE); - if (unlikely (status)) - return status; - - if (unlikely (scaled_glyph->surface == NULL)) - return CAIRO_INT_STATUS_UNSUPPORTED; - - own_surface = TRUE; - } - - if (unlikely (scaled_glyph->surface->width == 0 || - scaled_glyph->surface->height == 0)) - { - return CAIRO_INT_STATUS_NOTHING_TO_DO; - } - - if (unlikely (scaled_glyph->surface->width > GLYPH_CACHE_MAX_SIZE || - scaled_glyph->surface->height > GLYPH_CACHE_MAX_SIZE)) - { - return CAIRO_INT_STATUS_UNSUPPORTED; - } - - status = intel_get_glyph_cache (device, - scaled_glyph->surface->format, - &cache); - if (unlikely (status)) - return status; - - status = intel_glyph_cache_add_glyph (device, cache, scaled_glyph); - if (unlikely (_cairo_status_is_error (status))) - return status; - - if (unlikely (status == CAIRO_INT_STATUS_UNSUPPORTED)) { - /* no room, replace entire cache */ - - assert (cache->buffer.bo->exec != NULL); - - _cairo_rtree_reset (&cache->rtree); - intel_bo_destroy (device, cache->buffer.bo); - cache->buffer.bo = NULL; - - status = intel_buffer_cache_init (cache, device, - scaled_glyph->surface->format, - GLYPH_CACHE_WIDTH, - GLYPH_CACHE_HEIGHT); - if (unlikely (status)) - return status; - - status = intel_glyph_cache_add_glyph (device, cache, scaled_glyph); - if (unlikely (status)) - return status; - } - - if (own_surface) { - /* and release the copy of the image from system memory */ - cairo_surface_destroy (&scaled_glyph->surface->base); - scaled_glyph->surface = NULL; - } - - return CAIRO_STATUS_SUCCESS; -} - -cairo_status_t -intel_buffer_cache_init (intel_buffer_cache_t *cache, - intel_device_t *device, - cairo_format_t format, - int width, int height) -{ - const uint32_t tiling = I915_TILING_Y; - uint32_t stride, size; - - assert ((width & 3) == 0); - assert ((height & 1) == 0); - cache->buffer.format = format; - cache->buffer.width = width; - cache->buffer.height = height; - - switch (format) { - default: - case CAIRO_FORMAT_A1: - case CAIRO_FORMAT_RGB16_565: - case CAIRO_FORMAT_RGB24: - case CAIRO_FORMAT_INVALID: - ASSERT_NOT_REACHED; - return _cairo_error (CAIRO_STATUS_INVALID_FORMAT); - case CAIRO_FORMAT_ARGB32: - cache->buffer.map0 = MAPSURF_32BIT | MT_32BIT_ARGB8888; - stride = width * 4; - break; - case CAIRO_FORMAT_A8: - cache->buffer.map0 = MAPSURF_8BIT | MT_8BIT_I8; - stride = width; - break; - } - - size = height * stride; - cache->buffer.bo = intel_bo_create (device, - size, size, - FALSE, tiling, stride); - if (unlikely (cache->buffer.bo == NULL)) - return _cairo_error (CAIRO_STATUS_NO_MEMORY); - - cache->buffer.stride = stride; - - cache->buffer.offset = 0; - cache->buffer.map0 |= MS3_tiling (tiling); - cache->buffer.map0 |= ((height - 1) << MS3_HEIGHT_SHIFT) | - ((width - 1) << MS3_WIDTH_SHIFT); - cache->buffer.map1 = ((stride / 4) - 1) << MS4_PITCH_SHIFT; - - cache->ref_count = 0; - cairo_list_init (&cache->link); - - return CAIRO_STATUS_SUCCESS; -} - -cairo_status_t -intel_snapshot_cache_insert (intel_device_t *device, - intel_surface_t *surface) -{ - cairo_status_t status; - - surface->snapshot_cache_entry.size = surface->drm.bo->size; - if (surface->snapshot_cache_entry.size > - device->snapshot_cache_max_size) - { - return CAIRO_STATUS_SUCCESS; - } - - if (device->snapshot_cache.freeze_count == 0) - _cairo_cache_freeze (&device->snapshot_cache); - - surface->snapshot_cache_entry.hash = (unsigned long) surface; - status = _cairo_cache_insert (&device->snapshot_cache, - &surface->snapshot_cache_entry); - if (unlikely (status)) { - surface->snapshot_cache_entry.hash = 0; - return status; - } - - return CAIRO_STATUS_SUCCESS; -} - -void -intel_surface_detach_snapshot (cairo_surface_t *abstract_surface) -{ - intel_surface_t *surface = (intel_surface_t *) abstract_surface; - - if (surface->snapshot_cache_entry.hash) { - intel_device_t *device; - - device = (intel_device_t *) surface->drm.base.device; - _cairo_cache_remove (&device->snapshot_cache, - &surface->snapshot_cache_entry); - assert (surface->snapshot_cache_entry.hash == 0); - } -} - -void -intel_snapshot_cache_thaw (intel_device_t *device) -{ - if (device->snapshot_cache.freeze_count) - _cairo_cache_thaw (&device->snapshot_cache); -} - -static cairo_bool_t -_gradient_color_stops_equal (const cairo_gradient_pattern_t *a, - const cairo_gradient_pattern_t *b) -{ - unsigned int n; - - if (a->n_stops != b->n_stops) - return FALSE; - - for (n = 0; n < a->n_stops; n++) { - if (_cairo_fixed_from_double (a->stops[n].offset) != - _cairo_fixed_from_double (b->stops[n].offset)) - { - return FALSE; - } - - if (! _cairo_color_stop_equal (&a->stops[n].color, &b->stops[n].color)) - return FALSE; - } - - return TRUE; -} - -static uint32_t -hars_petruska_f54_1_random (void) -{ -#define rol(x,k) ((x << k) | (x >> (32-k))) - static uint32_t x; - return x = (x ^ rol (x, 5) ^ rol (x, 24)) + 0x37798849; -#undef rol -} - -static int -intel_gradient_sample_width (const cairo_gradient_pattern_t *gradient) -{ - unsigned int n; - int width; - - width = 8; - for (n = 1; n < gradient->n_stops; n++) { - double dx = gradient->stops[n].offset - gradient->stops[n-1].offset; - double delta, max; - int ramp; - - if (dx == 0) - continue; - - max = gradient->stops[n].color.red - - gradient->stops[n-1].color.red; - - delta = gradient->stops[n].color.green - - gradient->stops[n-1].color.green; - if (delta > max) - max = delta; - - delta = gradient->stops[n].color.blue - - gradient->stops[n-1].color.blue; - if (delta > max) - max = delta; - - delta = gradient->stops[n].color.alpha - - gradient->stops[n-1].color.alpha; - if (delta > max) - max = delta; - - ramp = 128 * max / dx; - if (ramp > width) - width = ramp; - } - - width = (width + 7) & -8; - return MIN (width, 1024); -} - -cairo_status_t -intel_gradient_render (intel_device_t *device, - const cairo_gradient_pattern_t *pattern, - intel_buffer_t *buffer) -{ - pixman_image_t *gradient, *image; - pixman_gradient_stop_t pixman_stops_stack[32]; - pixman_gradient_stop_t *pixman_stops; - pixman_point_fixed_t p1, p2; - int width; - unsigned int i; - cairo_status_t status; - - for (i = 0; i < device->gradient_cache.size; i++) { - if (_gradient_color_stops_equal (pattern, - &device->gradient_cache.cache[i].pattern.gradient.base)) { - *buffer = device->gradient_cache.cache[i].buffer; - return CAIRO_STATUS_SUCCESS; - } - } - - pixman_stops = pixman_stops_stack; - if (unlikely (pattern->n_stops > ARRAY_LENGTH (pixman_stops_stack))) { - pixman_stops = _cairo_malloc_ab (pattern->n_stops, - sizeof (pixman_gradient_stop_t)); - if (unlikely (pixman_stops == NULL)) - return _cairo_error (CAIRO_STATUS_NO_MEMORY); - } - - for (i = 0; i < pattern->n_stops; i++) { - pixman_stops[i].x = _cairo_fixed_16_16_from_double (pattern->stops[i].offset); - pixman_stops[i].color.red = pattern->stops[i].color.red_short; - pixman_stops[i].color.green = pattern->stops[i].color.green_short; - pixman_stops[i].color.blue = pattern->stops[i].color.blue_short; - pixman_stops[i].color.alpha = pattern->stops[i].color.alpha_short; - } - - width = intel_gradient_sample_width (pattern); - - p1.x = 0; - p1.y = 0; - p2.x = width << 16; - p2.y = 0; - - gradient = pixman_image_create_linear_gradient (&p1, &p2, - pixman_stops, - pattern->n_stops); - if (pixman_stops != pixman_stops_stack) - free (pixman_stops); - - if (unlikely (gradient == NULL)) - return _cairo_error (CAIRO_STATUS_NO_MEMORY); - - pixman_image_set_filter (gradient, PIXMAN_FILTER_BILINEAR, NULL, 0); - pixman_image_set_repeat (gradient, PIXMAN_REPEAT_PAD); - - image = pixman_image_create_bits (PIXMAN_a8r8g8b8, width, 1, NULL, 0); - if (unlikely (image == NULL)) { - pixman_image_unref (gradient); - return _cairo_error (CAIRO_STATUS_NO_MEMORY); - } - - pixman_image_composite32 (PIXMAN_OP_SRC, - gradient, NULL, image, - 0, 0, - 0, 0, - 0, 0, - width, 1); - - pixman_image_unref (gradient); - - buffer->bo = intel_bo_create (device, - 4*width, 4*width, - FALSE, I915_TILING_NONE, 4*width); - if (unlikely (buffer->bo == NULL)) { - pixman_image_unref (image); - return _cairo_error (CAIRO_STATUS_NO_MEMORY); - } - - intel_bo_write (device, buffer->bo, 0, 4*width, pixman_image_get_data (image)); - pixman_image_unref (image); - - buffer->offset = 0; - buffer->width = width; - buffer->height = 1; - buffer->stride = 4*width; - buffer->format = CAIRO_FORMAT_ARGB32; - buffer->map0 = MAPSURF_32BIT | MT_32BIT_ARGB8888; - buffer->map0 |= ((width - 1) << MS3_WIDTH_SHIFT); - buffer->map1 = (width - 1) << MS4_PITCH_SHIFT; - - if (device->gradient_cache.size < GRADIENT_CACHE_SIZE) { - i = device->gradient_cache.size++; - } else { - i = hars_petruska_f54_1_random () % GRADIENT_CACHE_SIZE; - _cairo_pattern_fini (&device->gradient_cache.cache[i].pattern.base); - intel_bo_destroy (device, device->gradient_cache.cache[i].buffer.bo); - } - - status = _cairo_pattern_init_copy (&device->gradient_cache.cache[i].pattern.base, - &pattern->base); - if (unlikely (status)) { - intel_bo_destroy (device, buffer->bo); - /* Ensure the cache is correctly initialised for i965_device_destroy */ - _cairo_pattern_init_solid (&device->gradient_cache.cache[i].pattern.solid, - CAIRO_COLOR_TRANSPARENT); - return status; - } - - device->gradient_cache.cache[i].buffer = *buffer; - return CAIRO_STATUS_SUCCESS; -} diff --git a/gfx/cairo/cairo/src/drm/cairo-drm-private.h b/gfx/cairo/cairo/src/drm/cairo-drm-private.h deleted file mode 100644 index 2db7f38d6d..0000000000 --- a/gfx/cairo/cairo/src/drm/cairo-drm-private.h +++ /dev/null @@ -1,238 +0,0 @@ -/* Cairo - a vector graphics library with display and print output - * - * Copyright © 2009 Chris Wilson - * - * 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., 51 Franklin Street, Suite 500, Boston, MA 02110-1335, 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 Chris Wilson. - * - * Contributors(s): - * Chris Wilson <chris@chris-wilson.co.uk> - */ - -#ifndef CAIRO_DRM_PRIVATE_H -#define CAIRO_DRM_PRIVATE_H - -#include "cairo-drm.h" - -#include "cairo-device-private.h" -#include "cairo-reference-count-private.h" -#include "cairo-surface-private.h" - -#include <sys/types.h> /* dev_t */ - -typedef struct _cairo_drm_device cairo_drm_device_t; - -typedef cairo_drm_device_t * -(*cairo_drm_device_create_func_t) (int fd, - dev_t dev, - int vendor_id, - int chip_id); - -typedef cairo_int_status_t -(*cairo_drm_device_flush_func_t) (cairo_drm_device_t *device); - -typedef cairo_int_status_t -(*cairo_drm_device_throttle_func_t) (cairo_drm_device_t *device); - -typedef void -(*cairo_drm_device_destroy_func_t) (void *data); - -typedef cairo_surface_t * -(*cairo_drm_surface_create_func_t) (cairo_drm_device_t *device, - cairo_format_t format, - int width, int height); - -typedef cairo_surface_t * -(*cairo_drm_surface_create_for_name_func_t) (cairo_drm_device_t *device, - unsigned int name, - cairo_format_t format, - int width, int height, int stride); - -typedef cairo_surface_t * -(*cairo_drm_surface_create_from_cacheable_image_func_t) - (cairo_drm_device_t *device, cairo_surface_t *image); - -typedef cairo_int_status_t -(*cairo_drm_surface_flink_func_t) (void *surface); - -typedef cairo_status_t -(*cairo_drm_surface_enable_scan_out_func_t) (void *surface); - -typedef cairo_surface_t * -(*cairo_drm_surface_map_to_image_func_t) (void *surface); - -typedef struct _cairo_drm_bo_backend { - void (*release) (void *device, void *bo); -} cairo_drm_bo_backend_t; - -typedef struct _cairo_drm_device_backend { - cairo_drm_device_flush_func_t flush; - cairo_drm_device_throttle_func_t throttle; - cairo_drm_device_destroy_func_t destroy; -} cairo_drm_device_backend_t; - -typedef struct _cairo_drm_surface_backend { - cairo_drm_surface_create_func_t create; - cairo_drm_surface_create_for_name_func_t create_for_name; - cairo_drm_surface_create_from_cacheable_image_func_t create_from_cacheable_image; - cairo_drm_surface_flink_func_t flink; - cairo_drm_surface_enable_scan_out_func_t enable_scan_out; - cairo_drm_surface_map_to_image_func_t map_to_image; -} cairo_drm_surface_backend_t; - -typedef struct _cairo_drm_bo { - cairo_reference_count_t ref_count; - uint32_t name; - uint32_t handle; - uint32_t size; -} cairo_drm_bo_t; - -struct _cairo_drm_device { - cairo_device_t base; - - int vendor_id; - int chip_id; - dev_t id; - int fd; - - int max_surface_size; - - cairo_drm_bo_backend_t bo; - cairo_drm_surface_backend_t surface; - cairo_drm_device_backend_t device; - - cairo_drm_device_t *next, *prev; -}; - -typedef struct _cairo_drm_surface { - cairo_surface_t base; - - cairo_drm_bo_t *bo; - - cairo_format_t format; - int width, height, stride; - - cairo_surface_t *fallback; - uint32_t map_count; -} cairo_drm_surface_t; - -static inline cairo_drm_bo_t * -cairo_drm_bo_reference (cairo_drm_bo_t *bo) -{ - _cairo_reference_count_inc (&bo->ref_count); - return bo; -} - -static cairo_always_inline void -cairo_drm_bo_destroy (cairo_device_t *abstract_device, - cairo_drm_bo_t *bo) -{ - if (_cairo_reference_count_dec_and_test (&bo->ref_count)) { - cairo_drm_device_t *device = (cairo_drm_device_t *) abstract_device; - device->bo.release (device, bo); - } -} - -cairo_private cairo_status_t -_cairo_drm_bo_open_for_name (const cairo_drm_device_t *dev, - cairo_drm_bo_t *bo, - uint32_t name); - -cairo_private cairo_status_t -_cairo_drm_bo_flink (const cairo_drm_device_t *dev, - cairo_drm_bo_t *bo); - -cairo_private void -_cairo_drm_bo_close (const cairo_drm_device_t *dev, - cairo_drm_bo_t *bo); - -cairo_private void -_cairo_drm_surface_init (cairo_drm_surface_t *surface, - cairo_format_t format, - int width, int height); - -cairo_private cairo_status_t -_cairo_drm_surface_finish (cairo_drm_surface_t *surface); - -cairo_private void -_cairo_drm_surface_get_font_options (void *abstract_surface, - cairo_font_options_t *options); - -cairo_private cairo_bool_t -_cairo_drm_surface_get_extents (void *abstract_surface, - cairo_rectangle_int_t *rectangle); - -cairo_private cairo_int_status_t -_cairo_drm_surface_flink (void *abstract_surface); - -static inline cairo_drm_device_t * -_cairo_drm_device_create_in_error (cairo_status_t status) -{ - return (cairo_drm_device_t *) _cairo_device_create_in_error (CAIRO_STATUS_NO_MEMORY); -} - -cairo_private cairo_drm_device_t * -_cairo_drm_device_init (cairo_drm_device_t *device, - int fd, - dev_t devid, - int vendor_id, - int chip_id, - int max_surface_size); - -cairo_private void -_cairo_drm_device_fini (cairo_drm_device_t *device); - -/* h/w specific backends */ - -cairo_private cairo_drm_device_t * -_cairo_drm_intel_device_create (int fd, dev_t dev, int vendor_id, int chip_id); - -cairo_private cairo_drm_device_t * -_cairo_drm_i915_device_create (int fd, dev_t dev, int vendor_id, int chip_id); - -cairo_private cairo_drm_device_t * -_cairo_drm_i965_device_create (int fd, dev_t dev, int vendor_id, int chip_id); - -cairo_private cairo_drm_device_t * -_cairo_drm_radeon_device_create (int fd, dev_t dev, int vendor_id, int chip_id); - -#if CAIRO_HAS_GALLIUM_SURFACE -cairo_private cairo_drm_device_t * -_cairo_drm_gallium_device_create (int fd, dev_t dev, int vendor_id, int chip_id); -#endif - -slim_hidden_proto (cairo_drm_device_default); -slim_hidden_proto (cairo_drm_device_get); -slim_hidden_proto (cairo_drm_device_get_for_fd); - -slim_hidden_proto (cairo_drm_surface_create_for_name); - -cairo_private cairo_bool_t -_cairo_drm_size_is_valid (cairo_device_t *abstract_device, - int width, int height); - -#endif /* CAIRO_DRM_PRIVATE_H */ diff --git a/gfx/cairo/cairo/src/drm/cairo-drm-radeon-private.h b/gfx/cairo/cairo/src/drm/cairo-drm-radeon-private.h deleted file mode 100644 index 0768528359..0000000000 --- a/gfx/cairo/cairo/src/drm/cairo-drm-radeon-private.h +++ /dev/null @@ -1,103 +0,0 @@ -/* Cairo - a vector graphics library with display and print output - * - * Copyright © 2009 Chris Wilson - * - * 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., 51 Franklin Street, Suite 500, Boston, MA 02110-1335, 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. - * - */ - -#ifndef CAIRO_DRM_RADEON_PRIVATE_H -#define CAIRO_DRM_RADEON_PRIVATE_H - -#include "cairo-compiler-private.h" -#include "cairo-types-private.h" -#include "cairo-drm-private.h" -#include "cairo-freelist-private.h" - -typedef struct _radeon_bo { - cairo_drm_bo_t base; - - void *virtual; - - cairo_bool_t in_batch; - uint32_t read_domains; - uint32_t write_domain; -} radeon_bo_t; - -typedef struct _radeon_device { - cairo_drm_device_t base; - cairo_freepool_t bo_pool; - - uint64_t vram_limit; - uint64_t gart_limit; -} radeon_device_t; - -cairo_private cairo_status_t -radeon_device_init (radeon_device_t *device, int fd); - -cairo_private void -radeon_device_fini (radeon_device_t *device); - -cairo_private cairo_bool_t -radeon_info (int fd, - uint64_t *gart_size, - uint64_t *vram_size); - -cairo_private void -radeon_bo_write (const radeon_device_t *dev, - radeon_bo_t *bo, - unsigned long offset, - unsigned long size, - const void *data); - -cairo_private void -radeon_bo_read (const radeon_device_t *dev, - radeon_bo_t *bo, - unsigned long offset, - unsigned long size, - void *data); - -cairo_private void -radeon_bo_wait (const radeon_device_t *dev, radeon_bo_t *bo); - -cairo_private void * -radeon_bo_map (const radeon_device_t *dev, radeon_bo_t *bo); - -cairo_private void -radeon_bo_unmap (radeon_bo_t *bo); - -cairo_private cairo_drm_bo_t * -radeon_bo_create (radeon_device_t *dev, - uint32_t size, - uint32_t initial_domain); - -cairo_private cairo_drm_bo_t * -radeon_bo_create_for_name (radeon_device_t *dev, uint32_t name); - -cairo_private cairo_surface_t * -radeon_bo_get_image (const radeon_device_t *device, - radeon_bo_t *bo, - const cairo_drm_surface_t *surface); - -#endif /* CAIRO_DRM_RADEON_PRIVATE_H */ diff --git a/gfx/cairo/cairo/src/drm/cairo-drm-radeon-surface.c b/gfx/cairo/cairo/src/drm/cairo-drm-radeon-surface.c deleted file mode 100644 index 9c9f8526c6..0000000000 --- a/gfx/cairo/cairo/src/drm/cairo-drm-radeon-surface.c +++ /dev/null @@ -1,454 +0,0 @@ -/* Cairo - a vector graphics library with display and print output - * - * Copyright © 2009 Chris Wilson - * - * 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., 51 Franklin Street, Suite 500, Boston, MA 02110-1335, 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. - * - */ - -#include "cairoint.h" - -#include "cairo-drm-private.h" -#include "cairo-drm-radeon-private.h" - -#include "cairo-default-context-private.h" -#include "cairo-error-private.h" -#include "cairo-image-surface-private.h" - -#include <stddef.h> -#include <inttypes.h> /* workaround for broken <drm/radeon_drm.h> */ -#include <drm/radeon_drm.h> - -/* Basic stub surface for radeon chipsets */ - -#define MAX_SIZE 2048 - -typedef struct _radeon_surface { - cairo_drm_surface_t base; -} radeon_surface_t; - -static inline radeon_device_t * -to_radeon_device (cairo_device_t *device) -{ - return (radeon_device_t *) device; -} - -static inline radeon_bo_t * -to_radeon_bo (cairo_drm_bo_t *bo) -{ - return (radeon_bo_t *) bo; -} - -static cairo_surface_t * -radeon_surface_create_similar (void *abstract_surface, - cairo_content_t content, - int width, - int height) -{ - return cairo_image_surface_create (_cairo_format_from_content (content), - width, height); -} - -static cairo_status_t -radeon_surface_finish (void *abstract_surface) -{ - radeon_surface_t *surface = abstract_surface; - - return _cairo_drm_surface_finish (&surface->base); -} - -static cairo_status_t -radeon_surface_acquire_source_image (void *abstract_surface, - cairo_image_surface_t **image_out, - void **image_extra) -{ - radeon_surface_t *surface = abstract_surface; - cairo_surface_t *image; - cairo_status_t status; - - /* XXX batch flush */ - - if (surface->base.fallback != NULL) { - image = surface->base.fallback; - goto DONE; - } - - image = _cairo_surface_has_snapshot (&surface->base.base, - &_cairo_image_surface_backend); - if (image != NULL) - goto DONE; - - if (surface->base.base.backend->flush != NULL) { - status = surface->base.base.backend->flush (surface); - if (unlikely (status)) - return status; - } - - image = radeon_bo_get_image (to_radeon_device (surface->base.base.device), - to_radeon_bo (surface->base.bo), - &surface->base); - status = image->status; - if (unlikely (status)) - return status; - - _cairo_surface_attach_snapshot (&surface->base.base, image, cairo_surface_destroy); - -DONE: - *image_out = (cairo_image_surface_t *) cairo_surface_reference (image); - *image_extra = NULL; - return CAIRO_STATUS_SUCCESS; -} - -static void -radeon_surface_release_source_image (void *abstract_surface, - cairo_image_surface_t *image, - void *image_extra) -{ - cairo_surface_destroy (&image->base); -} - -static cairo_surface_t * -radeon_surface_map_to_image (radeon_surface_t *surface) -{ - if (surface->base.fallback == NULL) { - cairo_surface_t *image; - cairo_status_t status; - void *ptr; - - if (surface->base.base.backend->flush != NULL) { - status = surface->base.base.backend->flush (surface); - if (unlikely (status)) - return _cairo_surface_create_in_error (status); - } - - ptr = radeon_bo_map (to_radeon_device (surface->base.base.device), - to_radeon_bo (surface->base.bo)); - if (unlikely (ptr == NULL)) - return _cairo_surface_create_in_error (CAIRO_STATUS_NO_MEMORY); - - image = cairo_image_surface_create_for_data (ptr, - surface->base.format, - surface->base.width, - surface->base.height, - surface->base.stride); - if (unlikely (image->status)) { - radeon_bo_unmap (to_radeon_bo (surface->base.bo)); - return image; - } - - surface->base.fallback = image; - } - - return surface->base.fallback; -} - -static cairo_status_t -radeon_surface_flush (void *abstract_surface, - unsigned flags) -{ - radeon_surface_t *surface = abstract_surface; - cairo_status_t status; - - if (flags) - return CAIRO_STATUS_SUCCESS; - - if (surface->base.fallback == NULL) - return CAIRO_STATUS_SUCCESS; - - /* kill any outstanding maps */ - cairo_surface_finish (surface->base.fallback); - - status = cairo_surface_status (surface->base.fallback); - cairo_surface_destroy (surface->base.fallback); - surface->base.fallback = NULL; - - radeon_bo_unmap (to_radeon_bo (surface->base.bo)); - - return status; -} - -static cairo_int_status_t -radeon_surface_paint (void *abstract_surface, - cairo_operator_t op, - const cairo_pattern_t *source, - cairo_clip_t *clip) -{ - return _cairo_surface_paint (radeon_surface_map_to_image (abstract_surface), - op, source, clip); -} - -static cairo_int_status_t -radeon_surface_mask (void *abstract_surface, - cairo_operator_t op, - const cairo_pattern_t *source, - const cairo_pattern_t *mask, - cairo_clip_t *clip) -{ - return _cairo_surface_mask (radeon_surface_map_to_image (abstract_surface), - op, source, mask, clip); -} - -static cairo_int_status_t -radeon_surface_stroke (void *abstract_surface, - cairo_operator_t op, - const cairo_pattern_t *source, - cairo_path_fixed_t *path, - const cairo_stroke_style_t *stroke_style, - const cairo_matrix_t *ctm, - const cairo_matrix_t *ctm_inverse, - double tolerance, - cairo_antialias_t antialias, - cairo_clip_t *clip) -{ - return _cairo_surface_stroke (radeon_surface_map_to_image (abstract_surface), - op, source, path, stroke_style, ctm, ctm_inverse, - tolerance, antialias, clip); -} - -static cairo_int_status_t -radeon_surface_fill (void *abstract_surface, - cairo_operator_t op, - const cairo_pattern_t *source, - cairo_path_fixed_t *path, - cairo_fill_rule_t fill_rule, - double tolerance, - cairo_antialias_t antialias, - cairo_clip_t *clip) -{ - return _cairo_surface_fill (radeon_surface_map_to_image (abstract_surface), - op, source, path, fill_rule, - tolerance, antialias, clip); -} - -static cairo_int_status_t -radeon_surface_glyphs (void *abstract_surface, - cairo_operator_t op, - const cairo_pattern_t *source, - cairo_glyph_t *glyphs, - int num_glyphs, - cairo_scaled_font_t *scaled_font, - cairo_clip_t *clip, - int *num_remaining) -{ - *num_remaining = 0; - return _cairo_surface_show_text_glyphs (radeon_surface_map_to_image (abstract_surface), - op, source, - NULL, 0, - glyphs, num_glyphs, - NULL, 0, 0, - scaled_font, clip); -} - -static const cairo_surface_backend_t radeon_surface_backend = { - CAIRO_SURFACE_TYPE_DRM, - _cairo_default_context_create, - - radeon_surface_create_similar, - radeon_surface_finish, - - NULL, - radeon_surface_acquire_source_image, - radeon_surface_release_source_image, - - NULL, NULL, NULL, - NULL, /* composite */ - NULL, /* fill */ - NULL, /* trapezoids */ - NULL, /* span */ - NULL, /* check-span */ - - NULL, /* copy_page */ - NULL, /* show_page */ - _cairo_drm_surface_get_extents, - NULL, /* old-glyphs */ - _cairo_drm_surface_get_font_options, - - radeon_surface_flush, - NULL, /* mark dirty */ - NULL, NULL, /* font/glyph fini */ - - radeon_surface_paint, - radeon_surface_mask, - radeon_surface_stroke, - radeon_surface_fill, - radeon_surface_glyphs, -}; - -static void -radeon_surface_init (radeon_surface_t *surface, - cairo_drm_device_t *device, - cairo_format_t format, - int width, int height) -{ - _cairo_surface_init (&surface->base.base, - &radeon_surface_backend, - &device->base, - _cairo_content_from_format (format), - FALSE); - _cairo_drm_surface_init (&surface->base, format, width, height); -} - -static cairo_surface_t * -radeon_surface_create_internal (cairo_drm_device_t *device, - cairo_format_t format, - int width, int height) -{ - radeon_surface_t *surface; - cairo_status_t status; - - surface = _cairo_malloc (sizeof (radeon_surface_t)); - if (unlikely (surface == NULL)) - return _cairo_surface_create_in_error (_cairo_error (CAIRO_STATUS_NO_MEMORY)); - - radeon_surface_init (surface, device, format, width, height); - - if (width && height) { - surface->base.stride = - cairo_format_stride_for_width (surface->base.format, width); - - surface->base.bo = radeon_bo_create (to_radeon_device (&device->base), - surface->base.stride * height, - RADEON_GEM_DOMAIN_GTT); - - if (unlikely (surface->base.bo == NULL)) { - status = _cairo_drm_surface_finish (&surface->base); - free (surface); - return _cairo_surface_create_in_error (_cairo_error (CAIRO_STATUS_NO_MEMORY)); - } - } - - return &surface->base.base; -} - -static cairo_surface_t * -radeon_surface_create (cairo_drm_device_t *device, - cairo_format_t format, - int width, int height) -{ - switch (format) { - default: - case CAIRO_FORMAT_INVALID: - case CAIRO_FORMAT_A1: - case CAIRO_FORMAT_RGB16_565: - return _cairo_surface_create_in_error (_cairo_error (CAIRO_STATUS_INVALID_FORMAT)); - case CAIRO_FORMAT_ARGB32: - case CAIRO_FORMAT_RGB24: - case CAIRO_FORMAT_A8: - break; - } - - return radeon_surface_create_internal (device, format, width, height); -} - -static cairo_surface_t * -radeon_surface_create_for_name (cairo_drm_device_t *device, - unsigned int name, - cairo_format_t format, - int width, int height, int stride) -{ - radeon_surface_t *surface; - cairo_status_t status; - - switch (format) { - default: - case CAIRO_FORMAT_INVALID: - case CAIRO_FORMAT_A1: - case CAIRO_FORMAT_RGB16_565: - return _cairo_surface_create_in_error (_cairo_error (CAIRO_STATUS_INVALID_FORMAT)); - case CAIRO_FORMAT_ARGB32: - case CAIRO_FORMAT_RGB24: - case CAIRO_FORMAT_A8: - break; - } - - if (stride < cairo_format_stride_for_width (format, width)) - return _cairo_surface_create_in_error (_cairo_error (CAIRO_STATUS_INVALID_STRIDE)); - - surface = _cairo_malloc (sizeof (radeon_surface_t)); - if (unlikely (surface == NULL)) - return _cairo_surface_create_in_error (_cairo_error (CAIRO_STATUS_NO_MEMORY)); - - radeon_surface_init (surface, device, format, width, height); - - if (width && height) { - surface->base.stride = stride; - - surface->base.bo = radeon_bo_create_for_name (to_radeon_device (&device->base), - name); - - if (unlikely (surface->base.bo == NULL)) { - status = _cairo_drm_surface_finish (&surface->base); - free (surface); - return _cairo_surface_create_in_error (_cairo_error (CAIRO_STATUS_NO_MEMORY)); - } - } - - return &surface->base.base; -} - -static void -radeon_device_destroy (void *data) -{ - radeon_device_t *device = data; - - radeon_device_fini (device); - - free (data); -} - -cairo_drm_device_t * -_cairo_drm_radeon_device_create (int fd, dev_t dev, int vendor_id, int chip_id) -{ - radeon_device_t *device; - uint64_t gart_size, vram_size; - cairo_status_t status; - - if (! radeon_info (fd, &gart_size, &vram_size)) - return NULL; - - device = _cairo_malloc (sizeof (radeon_device_t)); - if (device == NULL) - return _cairo_drm_device_create_in_error (CAIRO_STATUS_NO_MEMORY); - - status = radeon_device_init (device, fd); - if (unlikely (status)) { - free (device); - return _cairo_drm_device_create_in_error (status); - } - - device->base.surface.create = radeon_surface_create; - device->base.surface.create_for_name = radeon_surface_create_for_name; - device->base.surface.create_from_cacheable_image = NULL; - device->base.surface.flink = _cairo_drm_surface_flink; - device->base.surface.enable_scan_out = NULL; - - device->base.device.flush = NULL; - device->base.device.throttle = NULL; - device->base.device.destroy = radeon_device_destroy; - - device->vram_limit = vram_size; - device->gart_limit = gart_size; - - return _cairo_drm_device_init (&device->base, fd, dev, vendor_id, chip_id, MAX_SIZE); -} diff --git a/gfx/cairo/cairo/src/drm/cairo-drm-radeon.c b/gfx/cairo/cairo/src/drm/cairo-drm-radeon.c deleted file mode 100644 index 8bc91bfe08..0000000000 --- a/gfx/cairo/cairo/src/drm/cairo-drm-radeon.c +++ /dev/null @@ -1,331 +0,0 @@ -/* Cairo - a vector graphics library with display and print output - * - * Copyright © 2009 Chris Wilson - * - * 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., 51 Franklin Street, Suite 500, Boston, MA 02110-1335, 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. - * - */ - -#include "cairoint.h" - -#include "cairo-drm-private.h" -#include "cairo-drm-radeon-private.h" - -#include "cairo-error-private.h" -#include "cairo-image-surface-private.h" - -#include <sys/ioctl.h> -#include <sys/mman.h> -#include <errno.h> -#include <drm/radeon_drm.h> - -cairo_bool_t -radeon_info (int fd, - uint64_t *gart_size, - uint64_t *vram_size) -{ - struct drm_radeon_gem_info info; - int ret; - - ret = ioctl (fd, DRM_IOCTL_RADEON_GEM_INFO, &info); - if (ret == -1) - return FALSE; - - if (gart_size != NULL) - *gart_size = info.gart_size; - - if (vram_size != NULL) - *vram_size = info.vram_size; - - return TRUE; -} - -void -radeon_bo_write (const radeon_device_t *device, - radeon_bo_t *bo, - unsigned long offset, - unsigned long size, - const void *data) -{ - struct drm_radeon_gem_pwrite pwrite; - int ret; - - memset (&pwrite, 0, sizeof (pwrite)); - pwrite.handle = bo->base.handle; - pwrite.offset = offset; - pwrite.size = size; - pwrite.data_ptr = (uint64_t) (uintptr_t) data; - do { - ret = ioctl (device->base.fd, DRM_IOCTL_RADEON_GEM_PWRITE, &pwrite); - } while (ret == -1 && errno == EINTR); - - /* XXX temporary workaround */ - if (ret == -1 && errno == ENOSYS) { - uint8_t *ptr; - - ptr = radeon_bo_map (device, bo); - if (ptr != NULL) { - memcpy (ptr + offset, data, size); - radeon_bo_unmap (bo); - } - } -} - -void -radeon_bo_read (const radeon_device_t *device, - radeon_bo_t *bo, - unsigned long offset, - unsigned long size, - void *data) -{ - struct drm_radeon_gem_pread pread; - int ret; - - memset (&pread, 0, sizeof (pread)); - pread.handle = bo->base.handle; - pread.offset = offset; - pread.size = size; - pread.data_ptr = (uint64_t) (uintptr_t) data; - do { - ret = ioctl (device->base.fd, DRM_IOCTL_RADEON_GEM_PREAD, &pread); - } while (ret == -1 && errno == EINTR); - - /* XXX temporary workaround */ - if (ret == -1 && errno == ENOSYS) { - uint8_t *ptr; - - ptr = radeon_bo_map (device, bo); - if (ptr != NULL) { - memcpy (data, ptr + offset, size); - radeon_bo_unmap (bo); - } - } - - VG (VALGRIND_MAKE_MEM_DEFINED (data, size)); -} - -void -radeon_bo_wait (const radeon_device_t *device, radeon_bo_t *bo) -{ - struct drm_radeon_gem_wait_idle wait; - int ret; - - wait.handle = bo->base.handle; - do { - ret = ioctl (device->base.fd, DRM_IOCTL_RADEON_GEM_WAIT_IDLE, &wait); - } while (ret == -1 && (errno == EINTR || errno == EBUSY)); -} - -void * -radeon_bo_map (const radeon_device_t *device, radeon_bo_t *bo) -{ - struct drm_radeon_gem_mmap mmap_arg; - void *ptr; - int ret; - - assert (bo->virtual == NULL); - - memset (&mmap_arg, 0, sizeof (mmap_arg)); - mmap_arg.handle = bo->base.handle; - mmap_arg.offset = 0; - mmap_arg.size = bo->base.size; - - do { - ret = ioctl (device->base.fd, DRM_IOCTL_RADEON_GEM_MMAP, &mmap_arg); - } while (ret == -1 && errno == EINTR); - if (unlikely (ret != 0)) { - _cairo_error_throw (CAIRO_STATUS_NO_MEMORY); - return NULL; - } - - VG (VALGRIND_MAKE_MEM_DEFINED (&mmap_arg, sizeof (mmap_arg))); - - /* and mmap it */ - ptr = mmap (0, bo->base.size, PROT_READ | PROT_WRITE, - MAP_SHARED, device->base.fd, - mmap_arg.addr_ptr); - if (unlikely (ptr == MAP_FAILED)) { - _cairo_error_throw (CAIRO_STATUS_NO_MEMORY); - return NULL; - } - - bo->virtual = ptr; - - /* XXX set_domain? */ - return bo->virtual; -} - -void -radeon_bo_unmap (radeon_bo_t *bo) -{ - assert (bo->virtual != NULL); - - munmap (bo->virtual, bo->base.size); - bo->virtual = NULL; -} - -cairo_drm_bo_t * -radeon_bo_create (radeon_device_t *device, - uint32_t size, - uint32_t initial_domain) -{ - struct drm_radeon_gem_create create; - radeon_bo_t *bo; - int ret; - - bo = _cairo_freepool_alloc (&device->bo_pool); - if (unlikely (bo == NULL)) - return NULL; - - create.size = size; - create.alignment = 0; - create.initial_domain = initial_domain; - create.flags = 0; - create.handle = 0; - - do { - ret = ioctl (device->base.fd, DRM_IOCTL_RADEON_GEM_CREATE, &create); - } while (ret == -1 && errno == EINTR); - if (ret == -1) { - _cairo_freepool_free (&device->bo_pool, bo); - return NULL; - } - - bo->base.handle = create.handle; - bo->base.size = size; - - bo->virtual = NULL; - - bo->in_batch = FALSE; - bo->read_domains = 0; - bo->write_domain = 0; - - CAIRO_REFERENCE_COUNT_INIT (&bo->base.ref_count, 1); - return &bo->base; -} - -cairo_drm_bo_t * -radeon_bo_create_for_name (radeon_device_t *device, - uint32_t name) -{ - radeon_bo_t *bo; - cairo_status_t status; - - bo = _cairo_freepool_alloc (&device->bo_pool); - if (unlikely (bo == NULL)) - return NULL; - - status = _cairo_drm_bo_open_for_name (&device->base, &bo->base, name); - if (unlikely (status)) { - _cairo_freepool_free (&device->bo_pool, bo); - return NULL; - } - - bo->virtual = NULL; - - bo->in_batch = FALSE; - bo->read_domains = 0; - bo->write_domain = 0; - - CAIRO_REFERENCE_COUNT_INIT (&bo->base.ref_count, 1); - return &bo->base; -} - -static void -radeon_bo_release (void *_dev, void *_bo) -{ - radeon_device_t *device = _dev; - radeon_bo_t *bo = _bo; - - _cairo_drm_bo_close (&device->base, &bo->base); - _cairo_freepool_free (&device->bo_pool, bo); -} - -cairo_surface_t * -radeon_bo_get_image (const radeon_device_t *device, - radeon_bo_t *bo, - const cairo_drm_surface_t *surface) -{ - cairo_image_surface_t *image; - uint8_t *dst; - int size, row; - - image = (cairo_image_surface_t *) - cairo_image_surface_create (surface->format, - surface->width, - surface->height); - if (unlikely (image->base.status)) - return &image->base; - - if (image->stride == surface->stride) { - size = surface->stride * surface->height; - radeon_bo_read (device, bo, 0, size, image->data); - } else { - int offset; - - size = surface->width; - if (surface->format != CAIRO_FORMAT_A8) - size *= 4; - - offset = 0; - row = surface->height; - dst = image->data; - while (row--) { - radeon_bo_read (device, bo, offset, size, dst); - offset += surface->stride; - dst += image->stride; - } - } - - return &image->base; -} - -static void -_radeon_device_init_bo_cache (radeon_device_t *device) -{ - _cairo_freepool_init (&device->bo_pool, sizeof (radeon_bo_t)); -} - -cairo_status_t -radeon_device_init (radeon_device_t *device, int fd) -{ - _radeon_device_init_bo_cache (device); - - device->base.bo.release = radeon_bo_release; - - return CAIRO_STATUS_SUCCESS; -} - -static void -_radeon_bo_cache_fini (radeon_device_t *device) -{ - _cairo_freepool_fini (&device->bo_pool); -} - -void -radeon_device_fini (radeon_device_t *device) -{ - _radeon_bo_cache_fini (device); - _cairo_drm_device_fini (&device->base); -} diff --git a/gfx/cairo/cairo/src/drm/cairo-drm-surface.c b/gfx/cairo/cairo/src/drm/cairo-drm-surface.c deleted file mode 100644 index 8c4dd0ee81..0000000000 --- a/gfx/cairo/cairo/src/drm/cairo-drm-surface.c +++ /dev/null @@ -1,369 +0,0 @@ -/* Cairo - a vector graphics library with display and print output - * - * Copyright © 2009 Chris Wilson - * - * 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., 51 Franklin Street, Suite 500, Boston, MA 02110-1335, 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 Chris Wilson. - */ - -#include "cairoint.h" - -#include "cairo-drm-private.h" - -#include "cairo-error-private.h" -#include "cairo-image-surface-inline.h" - -void -_cairo_drm_surface_init (cairo_drm_surface_t *surface, - cairo_format_t format, - int width, int height) -{ - surface->bo = NULL; - surface->format = format; - surface->width = width; - surface->height = height; - surface->stride = 0; - - surface->fallback = NULL; - surface->map_count = 0; -} - -cairo_status_t -_cairo_drm_surface_finish (cairo_drm_surface_t *surface) -{ - assert (surface->fallback == NULL); - - if (surface->bo != NULL) - cairo_drm_bo_destroy (surface->base.device, surface->bo); - - return CAIRO_STATUS_SUCCESS; -} - -void -_cairo_drm_surface_get_font_options (void *abstract_surface, - cairo_font_options_t *options) -{ - _cairo_font_options_init_default (options); - - cairo_font_options_set_hint_metrics (options, CAIRO_HINT_METRICS_ON); -} - -cairo_bool_t -_cairo_drm_surface_get_extents (void *abstract_surface, - cairo_rectangle_int_t *rectangle) -{ - cairo_drm_surface_t *surface = abstract_surface; - - rectangle->x = 0; - rectangle->y = 0; - rectangle->width = surface->width; - rectangle->height = surface->height; - - return TRUE; -} - -cairo_surface_t * -cairo_drm_surface_create (cairo_device_t *abstract_device, - cairo_format_t format, - int width, int height) -{ - cairo_drm_device_t *device = (cairo_drm_device_t *) abstract_device; - cairo_surface_t *surface; - - if (device != NULL && device->base.status) - { - surface = _cairo_surface_create_in_error (device->base.status); - } - else if (device == NULL || - device->surface.create == NULL || - width == 0 || width > device->max_surface_size || - height == 0 || height > device->max_surface_size) - { - surface = cairo_image_surface_create (format, width, height); - } - else if (device->base.finished) - { - surface = _cairo_surface_create_in_error (CAIRO_STATUS_SURFACE_FINISHED); - } - else - { - surface = device->surface.create (device, format, width, height); - if (surface->status == CAIRO_STATUS_INVALID_SIZE) - surface = cairo_image_surface_create (format, width, height); - } - - return surface; -} - -cairo_surface_t * -cairo_drm_surface_create_for_name (cairo_device_t *abstract_device, - unsigned int name, - cairo_format_t format, - int width, int height, int stride) -{ - cairo_drm_device_t *device = (cairo_drm_device_t *) abstract_device; - cairo_surface_t *surface; - - if (! CAIRO_FORMAT_VALID (format)) - return _cairo_surface_create_in_error (_cairo_error (CAIRO_STATUS_INVALID_FORMAT)); - - if (device != NULL && device->base.status) - { - surface = _cairo_surface_create_in_error (device->base.status); - } - else if (device == NULL || device->surface.create_for_name == NULL) - { - /* XXX invalid device! */ - surface = _cairo_surface_create_in_error (_cairo_error (CAIRO_STATUS_INVALID_FORMAT)); - } - else if (width == 0 || width > device->max_surface_size || - height == 0 || height > device->max_surface_size) - { - surface = _cairo_surface_create_in_error (_cairo_error (CAIRO_STATUS_INVALID_SIZE)); - } - else if (device->base.finished) - { - surface = _cairo_surface_create_in_error (CAIRO_STATUS_SURFACE_FINISHED); - } - else - { - surface = device->surface.create_for_name (device, - name, format, - width, height, stride); - } - - return surface; -} -slim_hidden_def (cairo_drm_surface_create_for_name); - -cairo_surface_t * -cairo_drm_surface_create_from_cacheable_image (cairo_device_t *abstract_device, - cairo_surface_t *surface) -{ - cairo_drm_device_t *device = (cairo_drm_device_t *) abstract_device; - - if (surface->status) { - surface = _cairo_surface_create_in_error (surface->status); - } else if (device != NULL && device->base.status) { - surface = _cairo_surface_create_in_error (device->base.status); - } else if (device == NULL || device->surface.create_from_cacheable_image == NULL) { - /* XXX invalid device! */ - surface = _cairo_surface_create_in_error (_cairo_error (CAIRO_STATUS_INVALID_FORMAT)); - } else if (device->base.finished) { - surface = _cairo_surface_create_in_error (CAIRO_STATUS_SURFACE_FINISHED); - } else { - surface = device->surface.create_from_cacheable_image (device, surface); - } - - return surface; -} - -static cairo_drm_surface_t * -_cairo_surface_as_drm (cairo_surface_t *abstract_surface) -{ - if (unlikely (abstract_surface->status)) - return NULL; - - if (abstract_surface->type != CAIRO_SURFACE_TYPE_DRM) - return NULL; - - return (cairo_drm_surface_t *) abstract_surface; -} - -cairo_status_t -cairo_drm_surface_enable_scan_out (cairo_surface_t *abstract_surface) -{ - cairo_drm_surface_t *surface; - cairo_drm_device_t *device; - - surface = _cairo_surface_as_drm (abstract_surface); - if (unlikely (surface == NULL)) - return _cairo_error (CAIRO_STATUS_SURFACE_TYPE_MISMATCH); - if (unlikely (surface->base.finished)) - return _cairo_error (CAIRO_STATUS_SURFACE_FINISHED); - - device = (cairo_drm_device_t *) surface->base.device; - if (device->surface.enable_scan_out == NULL) - return CAIRO_STATUS_SUCCESS; - - if (unlikely (device->base.finished)) - return _cairo_error (CAIRO_STATUS_SURFACE_FINISHED); - - return device->surface.enable_scan_out (abstract_surface); -} - -unsigned int -cairo_drm_surface_get_handle (cairo_surface_t *abstract_surface) -{ - cairo_drm_surface_t *surface; - - surface = _cairo_surface_as_drm (abstract_surface); - if (surface == NULL) { - _cairo_error_throw (CAIRO_STATUS_SURFACE_TYPE_MISMATCH); - return 0; - } - - return surface->bo->handle; -} - -cairo_int_status_t -_cairo_drm_surface_flink (void *abstract_surface) -{ - cairo_drm_surface_t *surface = abstract_surface; - - return _cairo_drm_bo_flink ((cairo_drm_device_t *) surface->base.device, - surface->bo); -} - -unsigned int -cairo_drm_surface_get_name (cairo_surface_t *abstract_surface) -{ - cairo_drm_surface_t *surface; - cairo_drm_device_t *device; - cairo_status_t status; - - surface = _cairo_surface_as_drm (abstract_surface); - if (surface == NULL) { - _cairo_error_throw (CAIRO_STATUS_SURFACE_TYPE_MISMATCH); - return 0; - } - - if (surface->bo->name) - return surface->bo->name; - - device = (cairo_drm_device_t *) surface->base.device; - if (device->surface.flink == NULL) - return 0; - - status = device->surface.flink (abstract_surface); - if (status) { - if (_cairo_status_is_error (status)) - status = _cairo_surface_set_error (abstract_surface, status); - - return 0; - } - - return surface->bo->name; -} - -cairo_format_t -cairo_drm_surface_get_format (cairo_surface_t *abstract_surface) -{ - cairo_drm_surface_t *surface; - - surface = _cairo_surface_as_drm (abstract_surface); - if (surface == NULL) - return cairo_image_surface_get_format (abstract_surface); - - return surface->format; -} - -int -cairo_drm_surface_get_width (cairo_surface_t *abstract_surface) -{ - cairo_drm_surface_t *surface; - - surface = _cairo_surface_as_drm (abstract_surface); - if (surface == NULL) - return cairo_image_surface_get_width (abstract_surface); - - return surface->width; -} - -int -cairo_drm_surface_get_height (cairo_surface_t *abstract_surface) -{ - cairo_drm_surface_t *surface; - - surface = _cairo_surface_as_drm (abstract_surface); - if (surface == NULL) - return cairo_image_surface_get_height (abstract_surface); - - return surface->height; -} - -int -cairo_drm_surface_get_stride (cairo_surface_t *abstract_surface) -{ - cairo_drm_surface_t *surface; - - surface = _cairo_surface_as_drm (abstract_surface); - if (surface == NULL) - return cairo_image_surface_get_stride (abstract_surface); - - return surface->stride; -} - -/* XXX drm or general surface layer? naming? */ -cairo_surface_t * -cairo_drm_surface_map_to_image (cairo_surface_t *abstract_surface) -{ - cairo_drm_surface_t *surface; - cairo_drm_device_t *device; - cairo_status_t status; - - if (unlikely (abstract_surface->status)) - return _cairo_surface_create_in_error (abstract_surface->status); - - surface = _cairo_surface_as_drm (abstract_surface); - if (surface == NULL) { - if (_cairo_surface_is_image (abstract_surface)) - return cairo_surface_reference (abstract_surface); - - status = _cairo_surface_set_error (abstract_surface, - CAIRO_STATUS_SURFACE_TYPE_MISMATCH); - return _cairo_surface_create_in_error (status); - } - - surface->map_count++; - device = (cairo_drm_device_t *) surface->base.device; - return cairo_surface_reference (device->surface.map_to_image (surface)); -} - -void -cairo_drm_surface_unmap (cairo_surface_t *abstract_surface, - cairo_surface_t *image) -{ - cairo_drm_surface_t *surface; - - surface = _cairo_surface_as_drm (abstract_surface); - if (surface == NULL) { - if (_cairo_surface_is_image (abstract_surface)) - cairo_surface_destroy (image); - else - _cairo_error_throw (CAIRO_STATUS_SURFACE_TYPE_MISMATCH); - return; - } - - /* XXX assert image belongs to drm */ - //assert (image == drm->fallback); - cairo_surface_destroy (image); - - assert (surface->map_count > 0); - if (--surface->map_count == 0) - cairo_surface_flush (&surface->base); -} diff --git a/gfx/cairo/cairo/src/drm/cairo-drm.c b/gfx/cairo/cairo/src/drm/cairo-drm.c deleted file mode 100644 index 661e181b62..0000000000 --- a/gfx/cairo/cairo/src/drm/cairo-drm.c +++ /dev/null @@ -1,390 +0,0 @@ -/* Cairo - a vector graphics library with display and print output - * - * Copyright © 2009 Chris Wilson - * - * 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., 51 Franklin Street, Suite 500, Boston, MA 02110-1335, 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 Chris Wilson. - */ - -#include "cairoint.h" - -#include "cairo-drm-private.h" - -#include "cairo-device-private.h" -#include "cairo-error-private.h" - -#define LIBUDEV_I_KNOW_THE_API_IS_SUBJECT_TO_CHANGE -#include <libudev.h> -#include <fcntl.h> -#include <unistd.h> /* open(), close() */ - -static cairo_drm_device_t *_cairo_drm_known_devices; -static cairo_drm_device_t *_cairo_drm_default_device; - -static const char * -get_udev_property(struct udev_device *device, const char *name) -{ - struct udev_list_entry *entry; - - udev_list_entry_foreach (entry, - udev_device_get_properties_list_entry (device)) - { - if (strcmp (udev_list_entry_get_name (entry), name) == 0) - return udev_list_entry_get_value (entry); - } - - return NULL; -} - -static void -_device_flush (void *abstract_device) -{ - cairo_drm_device_t *device = abstract_device; - - device->device.flush (device); -} - -static void -_device_finish (void *abstract_device) -{ - cairo_drm_device_t *device = abstract_device; - - CAIRO_MUTEX_LOCK (_cairo_drm_device_mutex); - if (device->prev != NULL) - device->prev->next = device->next; - else - _cairo_drm_known_devices = device->next; - if (device->next != NULL) - device->next->prev = device->prev; - - CAIRO_MUTEX_UNLOCK (_cairo_drm_device_mutex); - - if (_cairo_atomic_ptr_cmpxchg (&_cairo_drm_default_device, - device, NULL)) - { - cairo_device_destroy (&device->base); - } -} - -static void -_device_destroy (void *abstract_device) -{ - cairo_drm_device_t *device = abstract_device; - - device->device.destroy (device); -} - -static const cairo_device_backend_t _cairo_drm_device_backend = { - CAIRO_DEVICE_TYPE_DRM, - - NULL, NULL, /* lock, unlock */ - - _device_flush, - _device_finish, - _device_destroy, -}; - -cairo_drm_device_t * -_cairo_drm_device_init (cairo_drm_device_t *dev, - int fd, - dev_t devid, - int vendor_id, - int chip_id, - int max_surface_size) -{ - assert (CAIRO_MUTEX_IS_LOCKED (_cairo_drm_device_mutex)); - - _cairo_device_init (&dev->base, &_cairo_drm_device_backend); - - dev->id = devid; - dev->vendor_id = vendor_id; - dev->chip_id = chip_id; - dev->fd = fd; - - dev->max_surface_size = max_surface_size; - - dev->prev = NULL; - dev->next = _cairo_drm_known_devices; - if (_cairo_drm_known_devices != NULL) - _cairo_drm_known_devices->prev = dev; - _cairo_drm_known_devices = dev; - - if (_cairo_drm_default_device == NULL) - _cairo_drm_default_device = (cairo_drm_device_t *) cairo_device_reference (&dev->base); - - return dev; -} - -cairo_device_t * -cairo_drm_device_get (struct udev_device *device) -{ - static const struct dri_driver_entry { - uint32_t vendor_id; - uint32_t chip_id; - cairo_drm_device_create_func_t create_func; - } driver_map[] = { - { 0x8086, 0x29a2, _cairo_drm_i965_device_create }, /* I965_G */ - { 0x8086, 0x2982, _cairo_drm_i965_device_create }, /* G35_G */ - { 0x8086, 0x2992, _cairo_drm_i965_device_create }, /* I965_Q */ - { 0x8086, 0x2972, _cairo_drm_i965_device_create }, /* I946_GZ */ - { 0x8086, 0x2a02, _cairo_drm_i965_device_create }, /* I965_GM */ - { 0x8086, 0x2a12, _cairo_drm_i965_device_create }, /* I965_GME */ - { 0x8086, 0x2e02, _cairo_drm_i965_device_create }, /* IGD_E_G */ - { 0x8086, 0x2e22, _cairo_drm_i965_device_create }, /* G45_G */ - { 0x8086, 0x2e12, _cairo_drm_i965_device_create }, /* Q45_G */ - { 0x8086, 0x2e32, _cairo_drm_i965_device_create }, /* G41_G */ - { 0x8086, 0x2a42, _cairo_drm_i965_device_create }, /* GM45_GM */ - - { 0x8086, 0x2582, _cairo_drm_i915_device_create }, /* I915_G */ - { 0x8086, 0x2592, _cairo_drm_i915_device_create }, /* I915_GM */ - { 0x8086, 0x258a, _cairo_drm_i915_device_create }, /* E7221_G */ - { 0x8086, 0x2772, _cairo_drm_i915_device_create }, /* I945_G */ - { 0x8086, 0x27a2, _cairo_drm_i915_device_create }, /* I945_GM */ - { 0x8086, 0x27ae, _cairo_drm_i915_device_create }, /* I945_GME */ - { 0x8086, 0x29c2, _cairo_drm_i915_device_create }, /* G33_G */ - { 0x8086, 0x29b2, _cairo_drm_i915_device_create }, /* Q35_G */ - { 0x8086, 0x29d2, _cairo_drm_i915_device_create }, /* Q33_G */ - { 0x8086, 0xa011, _cairo_drm_i915_device_create }, /* IGD_GM */ - { 0x8086, 0xa001, _cairo_drm_i915_device_create }, /* IGD_G */ - - /* XXX i830 */ - - { 0x8086, ~0, _cairo_drm_intel_device_create }, - - { 0x1002, ~0, _cairo_drm_radeon_device_create }, -#if CAIRO_HAS_GALLIUM_SURFACE - { ~0, ~0, _cairo_drm_gallium_device_create }, -#endif - }; - - cairo_drm_device_t *dev; - dev_t devid; - struct udev_device *parent; - const char *pci_id; - uint32_t vendor_id, chip_id; - const char *path; - int i, fd; - - devid = udev_device_get_devnum (device); - - CAIRO_MUTEX_LOCK (_cairo_drm_device_mutex); - for (dev = _cairo_drm_known_devices; dev != NULL; dev = dev->next) { - if (dev->id == devid) { - dev = (cairo_drm_device_t *) cairo_device_reference (&dev->base); - goto DONE; - } - } - - parent = udev_device_get_parent (device); - pci_id = get_udev_property (parent, "PCI_ID"); - if (pci_id == NULL || sscanf (pci_id, "%x:%x", &vendor_id, &chip_id) != 2) { - dev = NULL; - goto DONE; - } - -#if CAIRO_HAS_GALLIUM_SURFACE - if (getenv ("CAIRO_GALLIUM_FORCE")) - { - i = ARRAY_LENGTH (driver_map) - 1; - } - else -#endif - { - for (i = 0; i < ARRAY_LENGTH (driver_map); i++) { - if (driver_map[i].vendor_id == ~0U) - break; - - if (driver_map[i].vendor_id == vendor_id && - (driver_map[i].chip_id == ~0U || driver_map[i].chip_id == chip_id)) - break; - } - - if (i == ARRAY_LENGTH (driver_map)) { - dev = (cairo_drm_device_t *) - _cairo_device_create_in_error (CAIRO_STATUS_DEVICE_ERROR); - goto DONE; - } - } - - path = udev_device_get_devnode (device); - if (path == NULL) - path = "/dev/dri/card0"; /* XXX buggy udev? */ - - fd = open (path, O_RDWR); - if (fd == -1) { - /* XXX more likely to be a permissions issue... */ - _cairo_error_throw (CAIRO_STATUS_FILE_NOT_FOUND); - dev = NULL; - goto DONE; - } - - dev = driver_map[i].create_func (fd, devid, vendor_id, chip_id); - if (dev == NULL) - close (fd); - - DONE: - CAIRO_MUTEX_UNLOCK (_cairo_drm_device_mutex); - - if (dev == NULL) - return _cairo_device_create_in_error (CAIRO_STATUS_DEVICE_ERROR); - else - return &dev->base; -} -slim_hidden_def (cairo_drm_device_get); - -cairo_device_t * -cairo_drm_device_get_for_fd (int fd) -{ - struct stat st; - struct udev *udev; - struct udev_device *device; - cairo_device_t *dev = NULL; - - if (fstat (fd, &st) < 0 || ! S_ISCHR (st.st_mode)) { - //_cairo_error_throw (CAIRO_STATUS_INVALID_DEVICE); - return _cairo_device_create_in_error (CAIRO_STATUS_NO_MEMORY); - } - - udev = udev_new (); - - device = udev_device_new_from_devnum (udev, 'c', st.st_rdev); - if (device != NULL) { - dev = cairo_drm_device_get (device); - udev_device_unref (device); - } - - udev_unref (udev); - - return dev; -} -slim_hidden_def (cairo_drm_device_get_for_fd); - -cairo_device_t * -cairo_drm_device_default (void) -{ - struct udev *udev; - struct udev_enumerate *e; - struct udev_list_entry *entry; - cairo_device_t *dev; - - /* optimistic atomic pointer read */ - dev = &_cairo_drm_default_device->base; - if (dev != NULL) - return dev; - - udev = udev_new(); - if (udev == NULL) - return _cairo_device_create_in_error (CAIRO_STATUS_NO_MEMORY); - - e = udev_enumerate_new (udev); - udev_enumerate_add_match_subsystem (e, "drm"); - udev_enumerate_scan_devices (e); - udev_list_entry_foreach (entry, udev_enumerate_get_list_entry (e)) { - struct udev_device *device; - - device = - udev_device_new_from_syspath (udev, - udev_list_entry_get_name (entry)); - - dev = cairo_drm_device_get (device); - - udev_device_unref (device); - - if (dev != NULL) { - if (((cairo_drm_device_t *) dev)->fd == -1) { - /* try again, we may find a usable card */ - cairo_device_destroy (dev); - dev = NULL; - } else - break; - } - } - udev_enumerate_unref (e); - udev_unref (udev); - - cairo_device_destroy (dev); /* owned by _cairo_drm_default_device */ - return dev; -} -slim_hidden_def (cairo_drm_device_default); - -void -_cairo_drm_device_reset_static_data (void) -{ - if (_cairo_drm_default_device != NULL) { - cairo_device_t *device = &_cairo_drm_default_device->base; - _cairo_drm_default_device = NULL; - cairo_device_destroy (device); - } -} - -int -cairo_drm_device_get_fd (cairo_device_t *abstract_device) -{ - cairo_drm_device_t *device = (cairo_drm_device_t *) abstract_device; - - if (device->base.status) - return -1; - - return device->fd; -} - -void -_cairo_drm_device_fini (cairo_drm_device_t *device) -{ - if (device->fd != -1) - close (device->fd); -} - -void -cairo_drm_device_throttle (cairo_device_t *abstract_device) -{ - cairo_drm_device_t *device = (cairo_drm_device_t *) abstract_device; - cairo_status_t status; - - if (unlikely (device->base.status)) - return; - - if (device->device.throttle == NULL) - return; - - status = device->device.throttle (device); - if (unlikely (status)) - _cairo_status_set_error (&device->base.status, status); -} - -cairo_bool_t -_cairo_drm_size_is_valid (cairo_device_t *abstract_device, - int width, int height) -{ - cairo_drm_device_t *device = (cairo_drm_device_t *) abstract_device; - - if (unlikely (device->base.status)) - return FALSE; - - return width <= device->max_surface_size && - height <= device->max_surface_size; -} diff --git a/gfx/cairo/cairo/src/meson.build b/gfx/cairo/cairo/src/meson.build index f5d741eaee..ac06ac61a0 100644 --- a/gfx/cairo/cairo/src/meson.build +++ b/gfx/cairo/cairo/src/meson.build @@ -114,6 +114,7 @@ cairo_sources = [ 'cairo-pdf-operators.c', 'cairo-pdf-shading.c', 'cairo-tag-attributes.c', + 'cairo-tag-stack.c', 'cairo-deflate-stream.c', ] @@ -129,6 +130,8 @@ cairo_feature_sources = { ], 'cairo-ft': [ 'cairo-ft-font.c', + 'cairo-colr-glyph-render.c', + 'cairo-svg-glyph-render.c' ], 'cairo-xlib': [ @@ -155,9 +158,6 @@ cairo_feature_sources = { 'cairo-xcb-surface-render.c', 'cairo-xcb-resources.c', ], - 'cairo-qt': [ - 'cairo-qt-surface.cpp', - ], 'cairo-quartz': [ 'cairo-quartz-surface.c', ], @@ -179,51 +179,8 @@ cairo_feature_sources = { 'cairo-win32-font': [ 'win32/cairo-win32-font.c', ], - 'cairo-drm': [ - 'drm/cairo-drm.c', - 'drm/cairo-drm-bo.c', - 'drm/cairo-drm-surface.c', - 'drm/cairo-drm-intel.c', - 'drm/cairo-drm-intel-debug.c', - 'drm/cairo-drm-intel-surface.c', - 'drm/cairo-drm-i915-surface.c', - 'drm/cairo-drm-i915-glyphs.c', - 'drm/cairo-drm-i915-shader.c', - 'drm/cairo-drm-i915-spans.c', - 'drm/cairo-drm-i965-surface.c', - 'drm/cairo-drm-i965-glyphs.c', - 'drm/cairo-drm-i965-shader.c', - 'drm/cairo-drm-i965-spans.c', - 'drm/cairo-drm-intel-brw-eu.c', - 'drm/cairo-drm-intel-brw-eu-emit.c', - 'drm/cairo-drm-intel-brw-eu-util.c', - 'drm/cairo-drm-radeon.c', - 'drm/cairo-drm-radeon-surface.c', - ], - 'cairo-gl': [ - 'cairo-gl-composite.c', - 'cairo-gl-device.c', - 'cairo-gl-dispatch.c', - 'cairo-gl-glyphs.c', - 'cairo-gl-gradient.c', - 'cairo-gl-info.c', - 'cairo-gl-msaa-compositor.c', - 'cairo-gl-operand.c', - 'cairo-gl-shaders.c', - 'cairo-gl-source.c', - 'cairo-gl-spans-compositor.c', - 'cairo-gl-surface.c', - 'cairo-gl-traps-compositor.c', - ], - 'cairo-cogl': [ - 'cairo-cogl-surface.c', - 'cairo-cogl-gradient.c', - ], - 'cairo-directfb': [ - 'cairo-directfb-surface.c', - ], - 'cairo-vg': [ - 'cairo-vg-surface.c', + 'cairo-dwrite-font': [ + 'win32/cairo-dwrite-font.cpp', ], 'cairo-script': [ 'cairo-script-surface.c', @@ -234,23 +191,10 @@ cairo_feature_sources = { 'cairo-pdf': [ 'cairo-pdf-surface.c', 'cairo-pdf-interchange.c', - 'cairo-tag-stack.c', ], 'cairo-svg': [ 'cairo-svg-surface.c', ], - 'cairo-egl': [ - 'cairo-egl-context.c', - ], - 'cairo-glx': [ - 'cairo-glx-context.c', - ], - 'cairo-wgl': [ - 'cairo-wgl-context.c', - ], - 'cairo-xml': [ - 'cairo-xml-surface.c', - ], 'cairo-tee': [ 'cairo-tee-surface.c', ], @@ -264,18 +208,14 @@ cairo_feature_headers = { 'cairo-xlib': ['cairo-xlib.h'], 'cairo-xlib-xrender': ['cairo-xlib-xrender.h'], 'cairo-xcb': ['cairo-xcb.h'], - 'cairo-qt': ['cairo-qt.h'], 'cairo-quartz': ['cairo-quartz.h'], 'cairo-quartz-image': ['cairo-quartz-image.h'], 'cairo-win32': ['cairo-win32.h'], + 'cairo-dwrite-font': ['cairo-dwrite.h'], 'cairo-gl': ['cairo-gl.h'], - 'cairo-directfb': ['cairo-directfb.h'], - 'cairo-drm': ['cairo-drm.h'], 'cairo-script': ['cairo-script.h'], 'cairo-tee': ['cairo-tee.h'], - 'cairo-xml': ['cairo-xml.h'], 'cairo-vg': ['cairo-vg.h'], - 'cairo-cogl': ['cairo-cogl.h'], } cairo_no_warn_c_args = cc.get_supported_arguments([ @@ -294,22 +234,32 @@ endforeach incsrc = include_directories('.') +cairo_static_args = [] +if get_option('default_library') == 'static' and host_machine.system() == 'windows' + cairo_static_args += ['-DCAIRO_WIN32_STATIC_BUILD'] + add_project_arguments('-DCAIRO_WIN32_STATIC_BUILD', language: 'c') +endif + libcairo = library('cairo', cairo_sources, dependencies: deps, - c_args: cairo_no_warn_c_args + pthread_c_args + ['-DHAVE_CONFIG_H'], - cpp_args: cairo_no_warn_c_args + pthread_c_args + ['-DHAVE_CONFIG_H'], + c_args: cairo_no_warn_c_args + pthread_c_args + ['-DCAIRO_COMPILATION'], + cpp_args: cairo_no_warn_c_args + pthread_c_args + ['-DCAIRO_COMPILATION'], link_args: extra_link_args, + gnu_symbol_visibility: 'hidden', soversion: cairo_version_sonum, version: cairo_libversion, install: true, include_directories: incbase, ) -cairo_headers += [configure_file(output: 'cairo-features.h', configuration: feature_conf)] +cairo_features_file = configure_file(output: 'cairo-features.h', configuration: feature_conf) +cairo_headers += [cairo_features_file] libcairo_dep = declare_dependency(link_with: libcairo, dependencies: deps, - include_directories: incsrc) + include_directories: incsrc, + compile_args: cairo_static_args, +) pkgmod.generate(libcairo, description: 'Multi-platform 2D graphics library', @@ -319,3 +269,19 @@ pkgmod.generate(libcairo, meson.override_dependency('cairo', libcairo_dep) install_headers(cairo_headers, subdir: 'cairo') + +shell = find_program('sh', required: false) +if shell.found() + test_scripts = [ + 'check-doc-syntax.sh', + 'check-headers.sh', + 'check-preprocessor-syntax.sh', + ] + + foreach test_script: test_scripts + test(test_script, shell, + args: [test_script], + suite: ['fast', 'lint'], + workdir: meson.current_source_dir()) + endforeach +endif diff --git a/gfx/cairo/cairo/src/test-base-compositor-surface.c b/gfx/cairo/cairo/src/test-base-compositor-surface.c index ff84b10aff..00e3d0c561 100644 --- a/gfx/cairo/cairo/src/test-base-compositor-surface.c +++ b/gfx/cairo/cairo/src/test-base-compositor-surface.c @@ -734,6 +734,7 @@ composite_glyphs (cairo_image_surface_t *dst, status = _cairo_scaled_glyph_lookup (info->font, glyph_index, CAIRO_SCALED_GLYPH_INFO_SURFACE, + NULL, /* foreground color */ &scaled_glyph); if (unlikely (status)) diff --git a/gfx/cairo/cairo/src/win32/cairo-dwrite-font.cpp b/gfx/cairo/cairo/src/win32/cairo-dwrite-font.cpp index a362007be1..cf516d41c3 100644 --- a/gfx/cairo/cairo/src/win32/cairo-dwrite-font.cpp +++ b/gfx/cairo/cairo/src/win32/cairo-dwrite-font.cpp @@ -41,12 +41,35 @@ #include "cairo-surface-private.h" #include "cairo-image-surface-private.h" #include "cairo-clip-private.h" -#include "cairo-win32-refptr.h" - -#include "cairo-dwrite-private.h" +#include "cairo-win32-refptr.hpp" +#include "cairo-dwrite-private.hpp" #include "cairo-truetype-subset-private.h" +#include "cairo-scaled-font-subsets-private.h" +#include "cairo-dwrite.h" + #include <float.h> +#include <wincodec.h> + +/** + * SECTION:cairo-dwrite-fonts + * @Title: DWrite Fonts + * @Short_Description: Font support for Microsoft DirectWrite + * @See_Also: #cairo_font_face_t + * + * The Microsoft DirectWrite font backend is primarily used to render text on + * Microsoft Windows systems. + **/ + +/** + * CAIRO_HAS_DWRITE_FONT: + * + * Defined if the Microsoft DWrite font backend is available. + * This macro can be used to conditionally compile backend-specific code. + * + * Since: 1.18 + **/ + typedef HRESULT (WINAPI*D2D1CreateFactoryFunc)( D2D1_FACTORY_TYPE factoryType, REFIID iid, @@ -64,7 +87,7 @@ _dwrite_draw_glyphs_to_gdi_surface_d2d(cairo_win32_surface_t *surface, COLORREF color, const RECT &area); -cairo_int_status_t +static cairo_int_status_t _dwrite_draw_glyphs_to_gdi_surface_gdi(cairo_win32_surface_t *surface, DWRITE_MATRIX *transform, DWRITE_GLYPH_RUN *run, @@ -72,14 +95,52 @@ _dwrite_draw_glyphs_to_gdi_surface_gdi(cairo_win32_surface_t *surface, cairo_dwrite_scaled_font_t *scaled_font, const RECT &area); +/** + * _cairo_dwrite_error: + * @hr HRESULT code + * @context: context string to display along with the error + * + * Helper function to print a human readable form a HRESULT. + * + * Return value: A cairo status code for the error code + **/ +static cairo_int_status_t +_cairo_dwrite_error (HRESULT hr, const char *context) +{ + void *lpMsgBuf; + + if (!FormatMessageW (FORMAT_MESSAGE_ALLOCATE_BUFFER | + FORMAT_MESSAGE_FROM_SYSTEM, + NULL, + hr, + MAKELANGID (LANG_NEUTRAL, SUBLANG_DEFAULT), + (LPWSTR) &lpMsgBuf, + 0, NULL)) { + fprintf (stderr, "%s: Unknown DWrite error HRESULT=0x%08lx\n", context, (unsigned long)hr); + } else { + fprintf (stderr, "%s: %S\n", context, (wchar_t *)lpMsgBuf); + LocalFree (lpMsgBuf); + } + fflush (stderr); + + return (cairo_int_status_t)_cairo_error (CAIRO_STATUS_DWRITE_ERROR); +} + class D2DFactory { public: - static ID2D1Factory *Instance() + static RefPtr<ID2D1Factory> Instance() { if (!mFactoryInstance) { +#ifdef __GNUC__ +#pragma GCC diagnostic push +#pragma GCC diagnostic ignored "-Wcast-function-type" +#endif D2D1CreateFactoryFunc createD2DFactory = (D2D1CreateFactoryFunc) GetProcAddress(LoadLibraryW(L"d2d1.dll"), "D2D1CreateFactory"); +#ifdef __GNUC__ +#pragma GCC diagnostic pop +#endif if (createD2DFactory) { D2D1_FACTORY_OPTIONS options; options.debugLevel = D2D1_DEBUG_LEVEL_NONE; @@ -92,7 +153,17 @@ public: return mFactoryInstance; } - static ID2D1DCRenderTarget *RenderTarget() + static RefPtr<IDWriteFactory4> Instance4() + { + if (!mFactoryInstance4) { + if (Instance()) { + Instance()->QueryInterface(&mFactoryInstance4); + } + } + return mFactoryInstance4; + } + + static RefPtr<ID2D1DCRenderTarget> RenderTarget() { if (!mRenderTarget) { if (!Instance()) { @@ -116,25 +187,145 @@ public: } private: - static ID2D1Factory *mFactoryInstance; - static ID2D1DCRenderTarget *mRenderTarget; + static RefPtr<ID2D1Factory> mFactoryInstance; + static RefPtr<IDWriteFactory4> mFactoryInstance4; + static RefPtr<ID2D1DCRenderTarget> mRenderTarget; +}; + +class WICImagingFactory +{ +public: + static RefPtr<IWICImagingFactory> Instance() + { + if (!mFactoryInstance) { + CoInitialize(NULL); + CoCreateInstance(CLSID_WICImagingFactory, + NULL, + CLSCTX_INPROC_SERVER, + IID_PPV_ARGS(&mFactoryInstance)); + } + return mFactoryInstance; + } +private: + static RefPtr<IWICImagingFactory> mFactoryInstance; }; -IDWriteFactory *DWriteFactory::mFactoryInstance = NULL; -IDWriteFontCollection *DWriteFactory::mSystemCollection = NULL; -IDWriteRenderingParams *DWriteFactory::mDefaultRenderingParams = NULL; -IDWriteRenderingParams *DWriteFactory::mCustomClearTypeRenderingParams = NULL; -IDWriteRenderingParams *DWriteFactory::mForceGDIClassicRenderingParams = NULL; -FLOAT DWriteFactory::mGamma = -1.0; -FLOAT DWriteFactory::mEnhancedContrast = -1.0; -FLOAT DWriteFactory::mClearTypeLevel = -1.0; -int DWriteFactory::mPixelGeometry = -1; -int DWriteFactory::mRenderingMode = -1; - -ID2D1Factory *D2DFactory::mFactoryInstance = NULL; -ID2D1DCRenderTarget *D2DFactory::mRenderTarget = NULL; - -/* Functions cairo_font_face_backend_t */ + +RefPtr<IDWriteFactory> DWriteFactory::mFactoryInstance; +RefPtr<IDWriteFactory1> DWriteFactory::mFactoryInstance1; +RefPtr<IDWriteFactory2> DWriteFactory::mFactoryInstance2; +RefPtr<IDWriteFactory3> DWriteFactory::mFactoryInstance3; +RefPtr<IDWriteFactory4> DWriteFactory::mFactoryInstance4; + +RefPtr<IWICImagingFactory> WICImagingFactory::mFactoryInstance; +RefPtr<IDWriteFontCollection> DWriteFactory::mSystemCollection; +RefPtr<IDWriteRenderingParams> DWriteFactory::mDefaultRenderingParams; + +RefPtr<ID2D1Factory> D2DFactory::mFactoryInstance; +RefPtr<ID2D1DCRenderTarget> D2DFactory::mRenderTarget; + +static int +_quality_from_antialias_mode(cairo_antialias_t antialias) +{ + switch (antialias) { + case CAIRO_ANTIALIAS_NONE: + return NONANTIALIASED_QUALITY; + case CAIRO_ANTIALIAS_FAST: + case CAIRO_ANTIALIAS_GRAY: + return ANTIALIASED_QUALITY; + default: + break; + } + return CLEARTYPE_QUALITY; +} + +static RefPtr<IDWriteRenderingParams> +_create_rendering_params(IDWriteRenderingParams *params, + const cairo_font_options_t *options, + cairo_antialias_t antialias) +{ + if (!params) + params = DWriteFactory::DefaultRenderingParams(); + FLOAT gamma = params->GetGamma(); + FLOAT enhanced_contrast = params->GetEnhancedContrast(); + FLOAT clear_type_level = params->GetClearTypeLevel(); + DWRITE_PIXEL_GEOMETRY pixel_geometry = params->GetPixelGeometry(); + DWRITE_RENDERING_MODE rendering_mode = params->GetRenderingMode(); + + cairo_bool_t modified = FALSE; + switch (antialias) { + case CAIRO_ANTIALIAS_NONE: + if (rendering_mode != DWRITE_RENDERING_MODE_ALIASED) { + rendering_mode = DWRITE_RENDERING_MODE_ALIASED; + modified = TRUE; + } + break; + case CAIRO_ANTIALIAS_FAST: + case CAIRO_ANTIALIAS_GRAY: + if (clear_type_level) { + clear_type_level = 0; + modified = TRUE; + } + break; + default: + break; + } + auto subpixel_order = cairo_font_options_get_subpixel_order (options); + switch (subpixel_order) { + case CAIRO_SUBPIXEL_ORDER_RGB: + if (pixel_geometry != DWRITE_PIXEL_GEOMETRY_RGB) { + pixel_geometry = DWRITE_PIXEL_GEOMETRY_RGB; + modified = TRUE; + } + break; + case CAIRO_SUBPIXEL_ORDER_BGR: + if (pixel_geometry != DWRITE_PIXEL_GEOMETRY_BGR) { + pixel_geometry = DWRITE_PIXEL_GEOMETRY_BGR; + modified = TRUE; + } + break; + default: + break; + } + if (!modified) + return params; + + HRESULT hr; + RefPtr<IDWriteRenderingParams1> params1; + hr = params->QueryInterface(¶ms1); + if (FAILED(hr)) { + RefPtr<IDWriteRenderingParams> ret; + DWriteFactory::Instance()->CreateCustomRenderingParams(gamma, enhanced_contrast, clear_type_level, pixel_geometry, rendering_mode, &ret); + return ret; + } + + FLOAT grayscaleEnhancedContrast = params1->GetGrayscaleEnhancedContrast(); + RefPtr<IDWriteRenderingParams2> params2; + hr = params->QueryInterface(¶ms2); + if (FAILED(hr)) { + RefPtr<IDWriteRenderingParams1> ret; + DWriteFactory::Instance1()->CreateCustomRenderingParams(gamma, enhanced_contrast, grayscaleEnhancedContrast, clear_type_level, pixel_geometry, rendering_mode, &ret); + return ret; + } + + DWRITE_GRID_FIT_MODE gridFitMode = params2->GetGridFitMode(); + RefPtr<IDWriteRenderingParams3> params3; + hr = params->QueryInterface(¶ms3); + if (FAILED(hr)) { + RefPtr<IDWriteRenderingParams2> ret; + DWriteFactory::Instance2()->CreateCustomRenderingParams(gamma, enhanced_contrast, grayscaleEnhancedContrast, clear_type_level, pixel_geometry, rendering_mode, gridFitMode, &ret); + return ret; + } + + DWRITE_RENDERING_MODE1 rendering_mode1 = params3->GetRenderingMode1(); + if (antialias == CAIRO_ANTIALIAS_NONE) + rendering_mode1 = DWRITE_RENDERING_MODE1_ALIASED; + RefPtr<IDWriteRenderingParams3> ret; + DWriteFactory::Instance3()->CreateCustomRenderingParams(gamma, enhanced_contrast, grayscaleEnhancedContrast, clear_type_level, pixel_geometry, rendering_mode1, gridFitMode, &ret); + return ret; +} + +/* Functions #cairo_font_face_backend_t */ static cairo_status_t _cairo_dwrite_font_face_create_for_toy (cairo_toy_font_face_t *toy_face, cairo_font_face_t **font_face); @@ -155,27 +346,35 @@ const cairo_font_face_backend_t _cairo_dwrite_font_face_backend = { _cairo_dwrite_font_face_scaled_font_create }; -/* Functions cairo_scaled_font_backend_t */ +/* Functions #cairo_scaled_font_backend_t */ -void _cairo_dwrite_scaled_font_fini(void *scaled_font); +static void _cairo_dwrite_scaled_font_fini(void *scaled_font); static cairo_warn cairo_int_status_t _cairo_dwrite_scaled_glyph_init(void *scaled_font, cairo_scaled_glyph_t *scaled_glyph, - cairo_scaled_glyph_info_t info); + cairo_scaled_glyph_info_t info, + const cairo_color_t *foreground_color); -cairo_int_status_t +static cairo_int_status_t _cairo_dwrite_load_truetype_table(void *scaled_font, unsigned long tag, long offset, unsigned char *buffer, unsigned long *length); -unsigned long -_cairo_dwrite_ucs4_to_index(void *scaled_font, - uint32_t ucs4); +static unsigned long +_cairo_dwrite_ucs4_to_index(void *scaled_font, + uint32_t ucs4); + +static cairo_int_status_t +_cairo_dwrite_is_synthetic(void *scaled_font, + cairo_bool_t *is_synthetic); + +static cairo_bool_t +_cairo_dwrite_has_color_glyphs(void *scaled_font); -const cairo_scaled_font_backend_t _cairo_dwrite_scaled_font_backend = { +static const cairo_scaled_font_backend_t _cairo_dwrite_scaled_font_backend = { CAIRO_FONT_TYPE_DWRITE, _cairo_dwrite_scaled_font_fini, _cairo_dwrite_scaled_glyph_init, @@ -183,23 +382,24 @@ const cairo_scaled_font_backend_t _cairo_dwrite_scaled_font_backend = { _cairo_dwrite_ucs4_to_index, _cairo_dwrite_load_truetype_table, NULL, /* index_to_ucs4 */ - NULL, /* is_synthetic */ + _cairo_dwrite_is_synthetic, NULL, /* index_to_glyph_name */ NULL, /* load_type1_data */ - NULL, /* has_color_glyphs */ + _cairo_dwrite_has_color_glyphs }; /* Helper conversion functions */ /** + * _cairo_dwrite_matrix_from_matrix: * Get a DirectWrite matrix from a cairo matrix. Note that DirectWrite uses row * vectors where cairo uses column vectors. Hence the transposition. * * \param Cairo matrix * \return DirectWrite matrix - */ -DWRITE_MATRIX + **/ +static DWRITE_MATRIX _cairo_dwrite_matrix_from_matrix(const cairo_matrix_t *matrix) { DWRITE_MATRIX dwmat; @@ -212,16 +412,21 @@ _cairo_dwrite_matrix_from_matrix(const cairo_matrix_t *matrix) return dwmat; } -/* Helper functions for cairo_dwrite_scaled_glyph_init */ -cairo_int_status_t -_cairo_dwrite_scaled_font_init_glyph_metrics +/* Helper functions for cairo_dwrite_scaled_glyph_init() */ +static cairo_int_status_t +_cairo_dwrite_scaled_font_init_glyph_metrics (cairo_dwrite_scaled_font_t *scaled_font, cairo_scaled_glyph_t *scaled_glyph); -cairo_int_status_t +static cairo_int_status_t +_cairo_dwrite_scaled_font_init_glyph_color_surface(cairo_dwrite_scaled_font_t *scaled_font, + cairo_scaled_glyph_t *scaled_glyph, + const cairo_color_t *foreground_color); + +static cairo_int_status_t _cairo_dwrite_scaled_font_init_glyph_surface (cairo_dwrite_scaled_font_t *scaled_font, cairo_scaled_glyph_t *scaled_glyph); -cairo_int_status_t +static cairo_int_status_t _cairo_dwrite_scaled_font_init_glyph_path (cairo_dwrite_scaled_font_t *scaled_font, cairo_scaled_glyph_t *scaled_glyph); @@ -242,11 +447,20 @@ _cairo_dwrite_font_face_create_for_toy (cairo_toy_font_face_t *toy_face, face_name = new WCHAR[face_name_len]; MultiByteToWideChar(CP_UTF8, 0, toy_face->family, -1, face_name, face_name_len); - IDWriteFontFamily *family = DWriteFactory::FindSystemFontFamily(face_name); - delete face_name; + RefPtr<IDWriteFontFamily> family = DWriteFactory::FindSystemFontFamily(face_name); + delete[] face_name; if (!family) { - *font_face = (cairo_font_face_t*)&_cairo_font_face_nil; - return CAIRO_STATUS_FONT_TYPE_MISMATCH; + /* If the family is not found, use the default that should always exist. */ + face_name_len = MultiByteToWideChar(CP_UTF8, 0, CAIRO_FONT_FAMILY_DEFAULT, -1, NULL, 0); + face_name = new WCHAR[face_name_len]; + MultiByteToWideChar(CP_UTF8, 0, CAIRO_FONT_FAMILY_DEFAULT, -1, face_name, face_name_len); + + family = DWriteFactory::FindSystemFontFamily(face_name); + delete[] face_name; + if (!family) { + *font_face = (cairo_font_face_t*)&_cairo_font_face_nil; + return (cairo_status_t)CAIRO_INT_STATUS_UNSUPPORTED; + } } DWRITE_FONT_WEIGHT weight; @@ -274,16 +488,17 @@ _cairo_dwrite_font_face_create_for_toy (cairo_toy_font_face_t *toy_face, break; } - cairo_dwrite_font_face_t *face = (cairo_dwrite_font_face_t*)malloc(sizeof(cairo_dwrite_font_face_t)); - HRESULT hr = family->GetFirstMatchingFont(weight, DWRITE_FONT_STRETCH_NORMAL, style, &face->font); - if (SUCCEEDED(hr)) { - // Cannot use C++ style new since cairo deallocates this. - *font_face = (cairo_font_face_t*)face; - _cairo_font_face_init (&(*(_cairo_dwrite_font_face**)font_face)->base, &_cairo_dwrite_font_face_backend); - } else { - free(face); - } + RefPtr<IDWriteFont> font; + HRESULT hr = family->GetFirstMatchingFont(weight, DWRITE_FONT_STRETCH_NORMAL, style, &font); + if (FAILED(hr)) + return (cairo_status_t)_cairo_dwrite_error (hr, "GetFirstMatchingFont failed"); + + RefPtr<IDWriteFontFace> dwriteface; + hr = font->CreateFontFace(&dwriteface); + if (FAILED(hr)) + return (cairo_status_t)_cairo_dwrite_error (hr, "CreateFontFace failed"); + *font_face = cairo_dwrite_font_face_create_for_dwrite_fontface(dwriteface); return CAIRO_STATUS_SUCCESS; } @@ -293,12 +508,11 @@ _cairo_dwrite_font_face_destroy (void *font_face) cairo_dwrite_font_face_t *dwrite_font_face = static_cast<cairo_dwrite_font_face_t*>(font_face); if (dwrite_font_face->dwriteface) dwrite_font_face->dwriteface->Release(); - if (dwrite_font_face->font) - dwrite_font_face->font->Release(); + if (dwrite_font_face->rendering_params) + dwrite_font_face->rendering_params->Release(); return TRUE; } - static inline unsigned short read_short(const char *buf) { @@ -326,7 +540,7 @@ _cairo_dwrite_glyph_run_from_glyphs(cairo_glyph_t *glyphs, run->isSideways = FALSE; if (scaled_font->mat.xy == 0 && scaled_font->mat.yx == 0 && - scaled_font->mat.xx == scaled_font->base.font_matrix.xx && + scaled_font->mat.xx == scaled_font->base.font_matrix.xx && scaled_font->mat.yy == scaled_font->base.font_matrix.yy) { // Fast route, don't actually use a transform but just // set the correct font size. @@ -421,17 +635,42 @@ _cairo_dwrite_font_face_scaled_font_create (void *abstract_face, const cairo_font_options_t *options, cairo_scaled_font_t **font) { + cairo_status_t status; cairo_dwrite_font_face_t *font_face = static_cast<cairo_dwrite_font_face_t*>(abstract_face); - // Must do malloc and not C++ new, since Cairo frees this. - cairo_dwrite_scaled_font_t *dwriteFont = (cairo_dwrite_scaled_font_t*)malloc(sizeof(cairo_dwrite_scaled_font_t)); - *font = reinterpret_cast<cairo_scaled_font_t*>(dwriteFont); - _cairo_scaled_font_init(&dwriteFont->base, &font_face->base, font_matrix, ctm, options, &_cairo_dwrite_scaled_font_backend); + /* Must do malloc and not C++ new, since Cairo frees this. */ + cairo_dwrite_scaled_font_t *dwrite_font = (cairo_dwrite_scaled_font_t*)_cairo_malloc( + sizeof(cairo_dwrite_scaled_font_t)); + if (unlikely(dwrite_font == NULL)) + return _cairo_error (CAIRO_STATUS_NO_MEMORY); + + *font = reinterpret_cast<cairo_scaled_font_t*>(dwrite_font); + status = _cairo_scaled_font_init (&dwrite_font->base, + &font_face->base, + font_matrix, + ctm, + options, + &_cairo_dwrite_scaled_font_backend); + if (status) { + free(dwrite_font); + return status; + } + + dwrite_font->mat = dwrite_font->base.ctm; + cairo_matrix_multiply(&dwrite_font->mat, &dwrite_font->mat, font_matrix); + dwrite_font->mat_inverse = dwrite_font->mat; + cairo_matrix_invert (&dwrite_font->mat_inverse); cairo_font_extents_t extents; DWRITE_FONT_METRICS metrics; - font_face->dwriteface->GetMetrics(&metrics); + if (dwrite_font->measuring_mode == DWRITE_MEASURING_MODE_GDI_CLASSIC || + dwrite_font->measuring_mode == DWRITE_MEASURING_MODE_GDI_NATURAL) { + DWRITE_MATRIX transform = _cairo_dwrite_matrix_from_matrix (&dwrite_font->mat); + font_face->dwriteface->GetGdiCompatibleMetrics(1, 1, &transform, &metrics); + } else { + font_face->dwriteface->GetMetrics(&metrics); + } extents.ascent = (FLOAT)metrics.ascent / metrics.designUnitsPerEm; extents.descent = (FLOAT)metrics.descent / metrics.designUnitsPerEm; @@ -439,15 +678,8 @@ _cairo_dwrite_font_face_scaled_font_create (void *abstract_face, extents.max_x_advance = 14.0; extents.max_y_advance = 0.0; - dwriteFont->mat = dwriteFont->base.ctm; - cairo_matrix_multiply(&dwriteFont->mat, &dwriteFont->mat, font_matrix); - dwriteFont->mat_inverse = dwriteFont->mat; - cairo_matrix_invert (&dwriteFont->mat_inverse); - cairo_antialias_t default_quality = CAIRO_ANTIALIAS_SUBPIXEL; - dwriteFont->measuring_mode = DWRITE_MEASURING_MODE_NATURAL; - // The following code detects the system quality at scaled_font creation time, // this means that if cleartype settings are changed but the scaled_fonts // are re-used, they might not adhere to the new system setting until re- @@ -458,12 +690,10 @@ _cairo_dwrite_font_face_scaled_font_create (void *abstract_face, break; case ANTIALIASED_QUALITY: default_quality = CAIRO_ANTIALIAS_GRAY; - dwriteFont->measuring_mode = DWRITE_MEASURING_MODE_GDI_CLASSIC; break; case DEFAULT_QUALITY: // _get_system_quality() seems to think aliased is default! default_quality = CAIRO_ANTIALIAS_NONE; - dwriteFont->measuring_mode = DWRITE_MEASURING_MODE_GDI_CLASSIC; break; } @@ -474,31 +704,34 @@ _cairo_dwrite_font_face_scaled_font_create (void *abstract_face, } if (options->antialias == CAIRO_ANTIALIAS_DEFAULT) { - dwriteFont->antialias_mode = default_quality; + dwrite_font->antialias_mode = default_quality; } else { - dwriteFont->antialias_mode = options->antialias; + dwrite_font->antialias_mode = options->antialias; } - dwriteFont->rendering_mode = - default_quality == CAIRO_ANTIALIAS_SUBPIXEL ? - cairo_dwrite_scaled_font_t::TEXT_RENDERING_NORMAL : cairo_dwrite_scaled_font_t::TEXT_RENDERING_NO_CLEARTYPE; + dwrite_font->rendering_params = _create_rendering_params(font_face->rendering_params, options, dwrite_font->antialias_mode).forget().drop(); + dwrite_font->measuring_mode = font_face->measuring_mode; return _cairo_scaled_font_set_metrics (*font, &extents); } -/* Implementation cairo_dwrite_scaled_font_backend_t */ -void +/* Implementation #cairo_dwrite_scaled_font_backend_t */ +static void _cairo_dwrite_scaled_font_fini(void *scaled_font) { + cairo_dwrite_scaled_font_t *dwrite_font = static_cast<cairo_dwrite_scaled_font_t*>(scaled_font); + if (dwrite_font->rendering_params) + dwrite_font->rendering_params->Release(); } static cairo_int_status_t _cairo_dwrite_scaled_glyph_init(void *scaled_font, cairo_scaled_glyph_t *scaled_glyph, - cairo_scaled_glyph_info_t info) + cairo_scaled_glyph_info_t info, + const cairo_color_t *foreground_color) { cairo_dwrite_scaled_font_t *scaled_dwrite_font = static_cast<cairo_dwrite_scaled_font_t*>(scaled_font); - cairo_int_status_t status; + cairo_int_status_t status = CAIRO_INT_STATUS_UNSUPPORTED; if ((info & CAIRO_SCALED_GLYPH_INFO_METRICS) != 0) { status = _cairo_dwrite_scaled_font_init_glyph_metrics (scaled_dwrite_font, scaled_glyph); @@ -506,6 +739,12 @@ _cairo_dwrite_scaled_glyph_init(void *scaled_font, return status; } + if (info & CAIRO_SCALED_GLYPH_INFO_COLOR_SURFACE) { + status = _cairo_dwrite_scaled_font_init_glyph_color_surface (scaled_dwrite_font, scaled_glyph, foreground_color); + if (status) + return status; + } + if (info & CAIRO_SCALED_GLYPH_INFO_SURFACE) { status = _cairo_dwrite_scaled_font_init_glyph_surface (scaled_dwrite_font, scaled_glyph); if (status) @@ -521,7 +760,7 @@ _cairo_dwrite_scaled_glyph_init(void *scaled_font, return CAIRO_INT_STATUS_SUCCESS; } -unsigned long +static unsigned long _cairo_dwrite_ucs4_to_index(void *scaled_font, uint32_t ucs4) { @@ -533,9 +772,9 @@ _cairo_dwrite_ucs4_to_index(void *scaled_font, return index; } -/* cairo_dwrite_scaled_glyph_init helper function bodies */ -cairo_int_status_t -_cairo_dwrite_scaled_font_init_glyph_metrics(cairo_dwrite_scaled_font_t *scaled_font, +/* cairo_dwrite_scaled_glyph_init() helper function bodies */ +static cairo_int_status_t +_cairo_dwrite_scaled_font_init_glyph_metrics(cairo_dwrite_scaled_font_t *scaled_font, cairo_scaled_glyph_t *scaled_glyph) { UINT16 charIndex = (UINT16)_cairo_scaled_glyph_index (scaled_glyph); @@ -544,17 +783,30 @@ _cairo_dwrite_scaled_font_init_glyph_metrics(cairo_dwrite_scaled_font_t *scaled_ DWRITE_GLYPH_METRICS metrics; DWRITE_FONT_METRICS fontMetrics; - font_face->dwriteface->GetMetrics(&fontMetrics); - HRESULT hr = font_face->dwriteface->GetDesignGlyphMetrics(&charIndex, 1, &metrics); + HRESULT hr; + if (font_face->measuring_mode == DWRITE_MEASURING_MODE_GDI_CLASSIC || + font_face->measuring_mode == DWRITE_MEASURING_MODE_GDI_NATURAL) { + DWRITE_MATRIX transform = _cairo_dwrite_matrix_from_matrix (&scaled_font->mat); + font_face->dwriteface->GetGdiCompatibleMetrics(1, 1, &transform, &fontMetrics); + BOOL natural = font_face->measuring_mode == DWRITE_MEASURING_MODE_GDI_NATURAL; + hr = font_face->dwriteface->GetGdiCompatibleGlyphMetrics (1, 1, &transform, natural, &charIndex, 1, &metrics, FALSE); + } else { + font_face->dwriteface->GetMetrics(&fontMetrics); + hr = font_face->dwriteface->GetDesignGlyphMetrics(&charIndex, 1, &metrics); + } if (FAILED(hr)) { return CAIRO_INT_STATUS_UNSUPPORTED; } + // GetGdiCompatibleMetrics may return a glyph metrics that yields a small nagative glyph height. + INT32 glyph_width = metrics.advanceWidth - metrics.leftSideBearing - metrics.rightSideBearing; + INT32 glyph_height = metrics.advanceHeight - metrics.topSideBearing - metrics.bottomSideBearing; + glyph_width = MAX(glyph_width, 0); + glyph_height = MAX(glyph_height, 0); + // TODO: Treat swap_xy. - extents.width = (FLOAT)(metrics.advanceWidth - metrics.leftSideBearing - metrics.rightSideBearing) / - fontMetrics.designUnitsPerEm; - extents.height = (FLOAT)(metrics.advanceHeight - metrics.topSideBearing - metrics.bottomSideBearing) / - fontMetrics.designUnitsPerEm; + extents.width = (FLOAT)glyph_width / fontMetrics.designUnitsPerEm; + extents.height = (FLOAT)glyph_height / fontMetrics.designUnitsPerEm; extents.x_advance = (FLOAT)metrics.advanceWidth / fontMetrics.designUnitsPerEm; extents.x_bearing = (FLOAT)metrics.leftSideBearing / fontMetrics.designUnitsPerEm; extents.y_advance = 0.0; @@ -564,10 +816,15 @@ _cairo_dwrite_scaled_font_init_glyph_metrics(cairo_dwrite_scaled_font_t *scaled_ // We pad the extents here because GetDesignGlyphMetrics returns "ideal" metrics // for the glyph outline, without accounting for hinting/gridfitting/antialiasing, // and therefore it does not always cover all pixels that will actually be touched. - if (scaled_font->base.options.antialias != CAIRO_ANTIALIAS_NONE && - extents.width > 0 && extents.height > 0) { - extents.width += scaled_font->mat_inverse.xx * 2; - extents.x_bearing -= scaled_font->mat_inverse.xx; + if (extents.width > 0 && extents.height > 0) { + double x = 1, y = 1; + cairo_matrix_transform_distance (&scaled_font->mat_inverse, &x, &y); + x = fabs(x); + y = fabs(y); + extents.width += x * 2; + extents.x_bearing -= x; + extents.height += y * 2; + extents.y_bearing -= y; } _cairo_scaled_glyph_set_metrics (scaled_glyph, @@ -576,7 +833,7 @@ _cairo_dwrite_scaled_font_init_glyph_metrics(cairo_dwrite_scaled_font_t *scaled_ return CAIRO_INT_STATUS_SUCCESS; } -/** +/* * Stack-based helper implementing IDWriteGeometrySink. * Used to determine the path of the glyphs. */ @@ -584,8 +841,9 @@ _cairo_dwrite_scaled_font_init_glyph_metrics(cairo_dwrite_scaled_font_t *scaled_ class GeometryRecorder : public IDWriteGeometrySink { public: - GeometryRecorder(cairo_path_fixed_t *aCairoPath) - : mCairoPath(aCairoPath) {} + GeometryRecorder(cairo_path_fixed_t *aCairoPath, const cairo_matrix_t &matrix) + : mCairoPath(aCairoPath) + , mMatrix(matrix) {} // IUnknown interface IFACEMETHOD(QueryInterface)(IID const& iid, OUT void** ppObject) @@ -622,38 +880,30 @@ public: { return; } - - cairo_fixed_t GetFixedX(const D2D1_POINT_2F &point) - { - unsigned int control_word; - _controlfp_s(&control_word, _CW_DEFAULT, MCW_PC); - return _cairo_fixed_from_double(point.x); - } - - cairo_fixed_t GetFixedY(const D2D1_POINT_2F &point) - { - unsigned int control_word; - _controlfp_s(&control_word, _CW_DEFAULT, MCW_PC); - return _cairo_fixed_from_double(point.y); - } IFACEMETHODIMP_(void) BeginFigure( - D2D1_POINT_2F startPoint, - D2D1_FIGURE_BEGIN figureBegin) + D2D1_POINT_2F startPoint, + D2D1_FIGURE_BEGIN figureBegin) { - mStartPoint = startPoint; - cairo_status_t status = _cairo_path_fixed_move_to(mCairoPath, - GetFixedX(startPoint), - GetFixedY(startPoint)); + double x = startPoint.x; + double y = startPoint.y; + cairo_matrix_transform_point(&mMatrix, &x, &y); + mStartPointX = _cairo_fixed_from_double(x); + mStartPointY = _cairo_fixed_from_double(y); + cairo_status_t status = _cairo_path_fixed_move_to(mCairoPath, + mStartPointX, + mStartPointY); + (void)status; /* squelch warning */ } - IFACEMETHODIMP_(void) EndFigure( - D2D1_FIGURE_END figureEnd) + IFACEMETHODIMP_(void) EndFigure( + D2D1_FIGURE_END figureEnd) { if (figureEnd == D2D1_FIGURE_END_CLOSED) { cairo_status_t status = _cairo_path_fixed_line_to(mCairoPath, - GetFixedX(mStartPoint), - GetFixedY(mStartPoint)); + mStartPointX, + mStartPointY); + (void)status; /* squelch warning */ } } @@ -662,14 +912,24 @@ public: UINT beziersCount) { for (unsigned int i = 0; i < beziersCount; i++) { + double x1 = beziers[i].point1.x; + double y1 = beziers[i].point1.y; + double x2 = beziers[i].point2.x; + double y2 = beziers[i].point2.y; + double x3 = beziers[i].point3.x; + double y3 = beziers[i].point3.y; + cairo_matrix_transform_point(&mMatrix, &x1, &y1); + cairo_matrix_transform_point(&mMatrix, &x2, &y2); + cairo_matrix_transform_point(&mMatrix, &x3, &y3); cairo_status_t status = _cairo_path_fixed_curve_to(mCairoPath, - GetFixedX(beziers[i].point1), - GetFixedY(beziers[i].point1), - GetFixedX(beziers[i].point2), - GetFixedY(beziers[i].point2), - GetFixedX(beziers[i].point3), - GetFixedY(beziers[i].point3)); - } + _cairo_fixed_from_double(x1), + _cairo_fixed_from_double(y1), + _cairo_fixed_from_double(x2), + _cairo_fixed_from_double(y2), + _cairo_fixed_from_double(x3), + _cairo_fixed_from_double(y3)); + (void)status; /* squelch warning */ + } } IFACEMETHODIMP_(void) AddLines( @@ -677,24 +937,31 @@ public: UINT pointsCount) { for (unsigned int i = 0; i < pointsCount; i++) { - cairo_status_t status = _cairo_path_fixed_line_to(mCairoPath, - GetFixedX(points[i]), - GetFixedY(points[i])); + double x = points[i].x; + double y = points[i].y; + cairo_matrix_transform_point(&mMatrix, &x, &y); + cairo_status_t status = _cairo_path_fixed_line_to(mCairoPath, + _cairo_fixed_from_double(x), + _cairo_fixed_from_double(y)); + (void)status; /* squelch warning */ } } private: cairo_path_fixed_t *mCairoPath; - D2D1_POINT_2F mStartPoint; + const cairo_matrix_t &mMatrix; + cairo_fixed_t mStartPointX; + cairo_fixed_t mStartPointY; }; -cairo_int_status_t -_cairo_dwrite_scaled_font_init_glyph_path(cairo_dwrite_scaled_font_t *scaled_font, +static cairo_int_status_t +_cairo_dwrite_scaled_font_init_glyph_path(cairo_dwrite_scaled_font_t *scaled_font, cairo_scaled_glyph_t *scaled_glyph) { + cairo_int_status_t status; cairo_path_fixed_t *path; path = _cairo_path_fixed_create(); - GeometryRecorder recorder(path); + GeometryRecorder recorder(path, scaled_font->base.scale); DWRITE_GLYPH_OFFSET offset; offset.advanceOffset = 0; @@ -702,67 +969,268 @@ _cairo_dwrite_scaled_font_init_glyph_path(cairo_dwrite_scaled_font_t *scaled_fon UINT16 glyphId = (UINT16)_cairo_scaled_glyph_index(scaled_glyph); FLOAT advance = 0.0; cairo_dwrite_font_face_t *dwriteff = (cairo_dwrite_font_face_t*)scaled_font->base.font_face; - dwriteff->dwriteface->GetGlyphRunOutline((FLOAT)scaled_font->base.font_matrix.yy, - &glyphId, - &advance, - &offset, - 1, - FALSE, - FALSE, - &recorder); - _cairo_path_fixed_close_path(path); - - /* Now apply our transformation to the drawn path. */ - _cairo_path_fixed_transform(path, &scaled_font->base.ctm); - + + HRESULT hr = dwriteff->dwriteface->GetGlyphRunOutline(1, + &glyphId, + &advance, + &offset, + 1, + FALSE, + FALSE, + &recorder); + if (!SUCCEEDED(hr)) + return _cairo_dwrite_error (hr, "GetGlyphRunOutline failed"); + + status = (cairo_int_status_t)_cairo_path_fixed_close_path(path); + _cairo_scaled_glyph_set_path (scaled_glyph, &scaled_font->base, path); - return CAIRO_INT_STATUS_SUCCESS; + return status; } -/* Helper function adapted from _compute_mask in cairo-win32-font.c */ - -/* Compute an alpha-mask from a monochrome RGB24 image - */ -static cairo_surface_t * -_compute_a8_mask (cairo_surface_t *surface) +static cairo_int_status_t +_cairo_dwrite_scaled_font_init_glyph_color_surface(cairo_dwrite_scaled_font_t *scaled_font, + cairo_scaled_glyph_t *scaled_glyph, + const cairo_color_t *foreground_color) { - cairo_image_surface_t *glyph; - cairo_image_surface_t *mask; - int i, j; + int width, height; + double x1, y1, x2, y2; + cairo_bool_t uses_foreground_color = FALSE; + + cairo_dwrite_font_face_t *dwrite_font_face = (cairo_dwrite_font_face_t *)scaled_font->base.font_face; + if (!dwrite_font_face->have_color) { + scaled_glyph->color_glyph = FALSE; + scaled_glyph->color_glyph_set = TRUE; + return CAIRO_INT_STATUS_UNSUPPORTED; + } - glyph = (cairo_image_surface_t *)cairo_surface_map_to_image (surface, NULL); - if (unlikely (glyph->base.status)) - return &glyph->base; + x1 = _cairo_fixed_integer_floor (scaled_glyph->bbox.p1.x); + y1 = _cairo_fixed_integer_floor (scaled_glyph->bbox.p1.y); + x2 = _cairo_fixed_integer_ceil (scaled_glyph->bbox.p2.x); + y2 = _cairo_fixed_integer_ceil (scaled_glyph->bbox.p2.y); + width = (int)(x2 - x1); + height = (int)(y2 - y1); - /* No quality param, just use the non-ClearType path */ + DWRITE_GLYPH_RUN run; + FLOAT advance = 0; + UINT16 index = (UINT16)_cairo_scaled_glyph_index (scaled_glyph); + DWRITE_GLYPH_OFFSET offset; + double x = -x1 + .25 * _cairo_scaled_glyph_xphase (scaled_glyph); + double y = -y1 + .25 * _cairo_scaled_glyph_yphase (scaled_glyph); + DWRITE_MATRIX matrix; + D2D1_POINT_2F origin = {0, 0}; + RefPtr<IDWriteColorGlyphRunEnumerator1> run_enumerator; + HRESULT hr; - /* Compute an alpha-mask by using the green channel of a (presumed monochrome) - * RGB24 image. + /* + * We transform by the inverse transformation here. This will put our glyph + * locations in the space in which we draw. Which is later transformed by + * the transformation matrix that we use. This will transform the + * glyph positions back to where they were before when drawing, but the + * glyph shapes will be transformed by the transformation matrix. */ - mask = (cairo_image_surface_t *) - cairo_image_surface_create (CAIRO_FORMAT_A8, glyph->width, glyph->height); - if (likely (mask->base.status == CAIRO_STATUS_SUCCESS)) { - for (i = 0; i < glyph->height; i++) { - uint32_t *p = (uint32_t *) (glyph->data + i * glyph->stride); - uint8_t *q = (uint8_t *) (mask->data + i * mask->stride); + cairo_matrix_transform_point(&scaled_font->mat_inverse, &x, &y); + offset.advanceOffset = (FLOAT)x; + /* Y-axis is inverted */ + offset.ascenderOffset = -(FLOAT)y; + + run.fontFace = dwrite_font_face->dwriteface; + run.fontEmSize = 1; + run.glyphCount = 1; + run.glyphIndices = &index; + run.glyphAdvances = &advance; + run.glyphOffsets = &offset; + run.isSideways = FALSE; + run.bidiLevel = 0; + + matrix = _cairo_dwrite_matrix_from_matrix(&scaled_font->mat); + + /* The list of glyph image formats this renderer is prepared to support. */ + DWRITE_GLYPH_IMAGE_FORMATS supported_formats = + DWRITE_GLYPH_IMAGE_FORMATS_COLR | + DWRITE_GLYPH_IMAGE_FORMATS_SVG | + DWRITE_GLYPH_IMAGE_FORMATS_PNG | + DWRITE_GLYPH_IMAGE_FORMATS_JPEG | + DWRITE_GLYPH_IMAGE_FORMATS_TIFF | + DWRITE_GLYPH_IMAGE_FORMATS_PREMULTIPLIED_B8G8R8A8; + + RefPtr<IDWriteFontFace2> fontFace2; + UINT32 palette_count = 0; + if (SUCCEEDED(dwrite_font_face->dwriteface->QueryInterface(&fontFace2))) + palette_count = fontFace2->GetColorPaletteCount(); + + UINT32 palette_index = CAIRO_COLOR_PALETTE_DEFAULT; + if (scaled_font->base.options.palette_index < palette_count) + palette_index = scaled_font->base.options.palette_index; + + hr = DWriteFactory::Instance4()->TranslateColorGlyphRun( + origin, + &run, + NULL, /* glyphRunDescription */ + supported_formats, + dwrite_font_face->measuring_mode, + &matrix, + palette_index, + &run_enumerator); + + if (hr == DWRITE_E_NOCOLOR) { + /* No color glyphs */ + scaled_glyph->color_glyph = FALSE; + scaled_glyph->color_glyph_set = TRUE; + return CAIRO_INT_STATUS_UNSUPPORTED; + } + + if (FAILED(hr)) + return _cairo_dwrite_error (hr, "TranslateColorGlyphRun failed"); + + /* We have a color glyph(s). Use Direct2D to render it to a bitmap */ + if (!WICImagingFactory::Instance() || !D2DFactory::Instance()) + return _cairo_dwrite_error (hr, "Instance failed"); + + RefPtr<IWICBitmap> bitmap; + hr = WICImagingFactory::Instance()->CreateBitmap ((UINT)width, + (UINT)height, + GUID_WICPixelFormat32bppPBGRA, + WICBitmapCacheOnLoad, + &bitmap); + if (FAILED(hr)) + return _cairo_dwrite_error (hr, "CreateBitmap failed"); + + D2D1_RENDER_TARGET_PROPERTIES properties = D2D1::RenderTargetProperties( + D2D1_RENDER_TARGET_TYPE_DEFAULT, + D2D1::PixelFormat( + DXGI_FORMAT_B8G8R8A8_UNORM, + D2D1_ALPHA_MODE_PREMULTIPLIED), + 0, + 0, + D2D1_RENDER_TARGET_USAGE_NONE, + D2D1_FEATURE_LEVEL_DEFAULT); + + RefPtr<ID2D1RenderTarget> rt; + hr = D2DFactory::Instance()->CreateWicBitmapRenderTarget (bitmap, properties, &rt); + if (FAILED(hr)) + return _cairo_dwrite_error (hr, "CreateWicBitmapRenderTarget failed"); + + RefPtr<ID2D1DeviceContext4> dc4; + hr = rt->QueryInterface(&dc4); + if (FAILED(hr)) + return _cairo_dwrite_error (hr, "QueryInterface(&dc4) failed"); + + RefPtr<ID2D1SolidColorBrush> foreground_color_brush; + dc4->CreateSolidColorBrush( + D2D1::ColorF(foreground_color->red, + foreground_color->green, + foreground_color->blue, + foreground_color->alpha), &foreground_color_brush); + + RefPtr<ID2D1SolidColorBrush> color_brush; + dc4->CreateSolidColorBrush(D2D1::ColorF(D2D1::ColorF::Black), &color_brush); + + dc4->SetDpi(96, 96); /* 1 unit = 1 pixel */ + rt->SetTransform(D2D1::Matrix3x2F(matrix.m11, + matrix.m12, + matrix.m21, + matrix.m22, + matrix.dx, + matrix.dy)); + + dc4->BeginDraw(); + dc4->Clear(NULL); /* Transparent black */ + + while (true) { + BOOL have_run; + hr = run_enumerator->MoveNext(&have_run); + if (FAILED(hr) || !have_run) + break; - for (j = 0; j < glyph->width; j++) - *q++ = 255 - ((*p++ & 0x0000ff00) >> 8); - } + DWRITE_COLOR_GLYPH_RUN1_WORKAROUND const* color_run; + hr = run_enumerator->GetCurrentRun(reinterpret_cast<const DWRITE_COLOR_GLYPH_RUN1**>(&color_run)); + if (FAILED(hr)) + return _cairo_dwrite_error (hr, "GetCurrentRun failed"); + + switch (color_run->glyphImageFormat) { + case DWRITE_GLYPH_IMAGE_FORMATS_PNG: + case DWRITE_GLYPH_IMAGE_FORMATS_JPEG: + case DWRITE_GLYPH_IMAGE_FORMATS_TIFF: + case DWRITE_GLYPH_IMAGE_FORMATS_PREMULTIPLIED_B8G8R8A8: + /* Bitmap glyphs */ + dc4->DrawColorBitmapGlyphRun(color_run->glyphImageFormat, + origin, + &color_run->glyphRun, + dwrite_font_face->measuring_mode, + D2D1_COLOR_BITMAP_GLYPH_SNAP_OPTION_DEFAULT); + break; + + case DWRITE_GLYPH_IMAGE_FORMATS_SVG: + /* SVG glyphs */ + dc4->DrawSvgGlyphRun(origin, + &color_run->glyphRun, + foreground_color_brush, + nullptr, + palette_index, + dwrite_font_face->measuring_mode); + uses_foreground_color = TRUE; + break; + case DWRITE_GLYPH_IMAGE_FORMATS_TRUETYPE: + case DWRITE_GLYPH_IMAGE_FORMATS_CFF: + case DWRITE_GLYPH_IMAGE_FORMATS_COLR: + /* Outline glyphs */ + if (color_run->paletteIndex == 0xFFFF) { + D2D1_COLOR_F color = foreground_color_brush->GetColor(); + color_brush->SetColor(&color); + uses_foreground_color = TRUE; + } else { + double red, green, blue, alpha; + cairo_status_t status; + status = cairo_font_options_get_custom_palette_color (&scaled_font->base.options, + color_run->paletteIndex, + &red, &blue, &green, &alpha); + if (status == CAIRO_STATUS_SUCCESS) { + color_brush->SetColor(D2D1::ColorF(red, blue, green, alpha)); + } else { + color_brush->SetColor(color_run->runColor); + } + } + + dc4->DrawGlyphRun(origin, + &color_run->glyphRun, + color_run->glyphRunDescription, + color_brush, + dwrite_font_face->measuring_mode); + case DWRITE_GLYPH_IMAGE_FORMATS_NONE: + break; + } } - cairo_surface_unmap_image (surface, &glyph->base); - return &mask->base; + hr = dc4->EndDraw(); + if (FAILED(hr)) + return _cairo_dwrite_error (hr, "EndDraw failed"); + + cairo_surface_t *image = cairo_image_surface_create (CAIRO_FORMAT_ARGB32, width, height); + int stride = cairo_image_surface_get_stride (image); + WICRect rect = { 0, 0, width, height }; + bitmap->CopyPixels(&rect, + stride, + height * stride, + cairo_image_surface_get_data (image)); + cairo_surface_mark_dirty (image); + cairo_surface_set_device_offset (image, -x1, -y1); + _cairo_scaled_glyph_set_color_surface (scaled_glyph, + &scaled_font->base, + (cairo_image_surface_t *) image, + uses_foreground_color ? foreground_color : NULL); + scaled_glyph->color_glyph = TRUE; + scaled_glyph->color_glyph_set = TRUE; + + return CAIRO_INT_STATUS_SUCCESS; } -cairo_int_status_t -_cairo_dwrite_scaled_font_init_glyph_surface(cairo_dwrite_scaled_font_t *scaled_font, +static cairo_int_status_t +_cairo_dwrite_scaled_font_init_glyph_surface(cairo_dwrite_scaled_font_t *scaled_font, cairo_scaled_glyph_t *scaled_glyph) { cairo_int_status_t status; - cairo_glyph_t glyph; cairo_win32_surface_t *surface; cairo_t *cr; cairo_surface_t *image; @@ -776,16 +1244,12 @@ _cairo_dwrite_scaled_font_init_glyph_surface(cairo_dwrite_scaled_font_t *scaled_ width = (int)(x2 - x1); height = (int)(y2 - y1); - glyph.index = _cairo_scaled_glyph_index (scaled_glyph); - glyph.x = -x1; - glyph.y = -y1; - DWRITE_GLYPH_RUN run; FLOAT advance = 0; - UINT16 index = (UINT16)glyph.index; + UINT16 index = (UINT16)_cairo_scaled_glyph_index (scaled_glyph); DWRITE_GLYPH_OFFSET offset; - double x = glyph.x; - double y = glyph.y; + double x = -x1 + .25 * _cairo_scaled_glyph_xphase (scaled_glyph); + double y = -y1 + .25 * _cairo_scaled_glyph_yphase (scaled_glyph); RECT area; DWRITE_MATRIX matrix; @@ -800,7 +1264,7 @@ _cairo_dwrite_scaled_font_init_glyph_surface(cairo_dwrite_scaled_font_t *scaled_ if (status) goto FAIL; - /** + /* * We transform by the inverse transformation here. This will put our glyph * locations in the space in which we draw. Which is later transformed by * the transformation matrix that we use. This will transform the @@ -809,7 +1273,7 @@ _cairo_dwrite_scaled_font_init_glyph_surface(cairo_dwrite_scaled_font_t *scaled_ */ cairo_matrix_transform_point(&scaled_font->mat_inverse, &x, &y); offset.advanceOffset = (FLOAT)x; - /** Y-axis is inverted */ + /* Y-axis is inverted */ offset.ascenderOffset = -(FLOAT)y; area.top = 0; @@ -835,7 +1299,7 @@ _cairo_dwrite_scaled_font_init_glyph_surface(cairo_dwrite_scaled_font_t *scaled_ GdiFlush(); - image = _compute_a8_mask (&surface->base); + image = _cairo_compute_glyph_mask (&surface->base, _quality_from_antialias_mode(scaled_font->antialias_mode)); status = (cairo_int_status_t)image->status; if (status) goto FAIL; @@ -851,7 +1315,7 @@ _cairo_dwrite_scaled_font_init_glyph_surface(cairo_dwrite_scaled_font_t *scaled_ return status; } -cairo_int_status_t +static cairo_int_status_t _cairo_dwrite_load_truetype_table(void *scaled_font, unsigned long tag, long offset, @@ -865,11 +1329,14 @@ _cairo_dwrite_load_truetype_table(void *scaled_font, UINT32 size; void *tableContext; BOOL exists; - face->dwriteface->TryGetFontTable(be32_to_cpu (tag), - &data, - &size, - &tableContext, - &exists); + HRESULT hr; + hr = face->dwriteface->TryGetFontTable (be32_to_cpu (tag), + &data, + &size, + &tableContext, + &exists); + if (FAILED(hr)) + return _cairo_dwrite_error (hr, "TryGetFontTable failed"); if (!exists) { return CAIRO_INT_STATUS_UNSUPPORTED; @@ -887,59 +1354,256 @@ _cairo_dwrite_load_truetype_table(void *scaled_font, return (cairo_int_status_t)CAIRO_STATUS_SUCCESS; } -// WIN32 Helper Functions -cairo_font_face_t* -cairo_dwrite_font_face_create_for_dwrite_fontface(void* dwrite_font, void* dwrite_font_face) +static cairo_int_status_t +_cairo_dwrite_is_synthetic(void *scaled_font, + cairo_bool_t *is_synthetic) +{ + cairo_dwrite_scaled_font_t *dwritesf = static_cast<cairo_dwrite_scaled_font_t*>(scaled_font); + cairo_dwrite_font_face_t *face = reinterpret_cast<cairo_dwrite_font_face_t*>(dwritesf->base.font_face); + HRESULT hr; + cairo_int_status_t status; + + if (face->dwriteface->GetSimulations() != DWRITE_FONT_SIMULATIONS_NONE) { + *is_synthetic = FALSE; + return CAIRO_INT_STATUS_SUCCESS; + } + + RefPtr<IDWriteFontFace5> fontFace5; + if (FAILED(face->dwriteface->QueryInterface(&fontFace5))) { + /* If IDWriteFontFace5 is not available, assume this version of + * DirectWrite does not support variations. + */ + *is_synthetic = FALSE; + return CAIRO_INT_STATUS_SUCCESS; + } + + if (!fontFace5->HasVariations()) { + *is_synthetic = FALSE; + return CAIRO_INT_STATUS_SUCCESS; + } + + RefPtr<IDWriteFontResource> fontResource; + hr = fontFace5->GetFontResource(&fontResource); + if (FAILED(hr)) + return _cairo_dwrite_error (hr, "GetFontResource failed"); + + UINT32 axis_count = fontResource->GetFontAxisCount(); + DWRITE_FONT_AXIS_VALUE *axis_defaults = new DWRITE_FONT_AXIS_VALUE[axis_count]; + DWRITE_FONT_AXIS_VALUE *axis_values = new DWRITE_FONT_AXIS_VALUE[axis_count]; + + hr = fontResource->GetDefaultFontAxisValues(axis_defaults, axis_count); + if (FAILED(hr)) { + status = _cairo_dwrite_error (hr, "GetDefaultFontAxisValues failed"); + goto cleanup; + } + + hr = fontFace5->GetFontAxisValues(axis_values, axis_count); + if (FAILED(hr)) { + status = _cairo_dwrite_error (hr, "GetFontAxisValues failed"); + goto cleanup; + } + + /* The DirectWrite documentation does not state if the tags of the returned + * defaults and values arrays are in the same order. So assume they are not. + */ + *is_synthetic = FALSE; + status = CAIRO_INT_STATUS_SUCCESS; + for (UINT32 i = 0; i< axis_count; i++) { + for (UINT32 j = 0; j < axis_count; j++) { + if (axis_values[i].axisTag == axis_defaults[j].axisTag) { + if (axis_values[i].value != axis_defaults[j].value) { + *is_synthetic = TRUE; + goto cleanup; + } + break; + } + } + } + + cleanup: + delete[] axis_defaults; + delete[] axis_values; + + return status; +} + +static cairo_bool_t +_cairo_dwrite_has_color_glyphs(void *scaled_font) +{ + cairo_dwrite_scaled_font_t *dwritesf = static_cast<cairo_dwrite_scaled_font_t*>(scaled_font); + + return ((cairo_dwrite_font_face_t *)dwritesf->base.font_face)->have_color; +} + +/** + * cairo_dwrite_font_face_create_for_dwrite_fontface: + * @dwrite_font_face: A pointer to an #IDWriteFontFace specifying the + * DWrite font to use. + * + * Creates a new font for the DWrite font backend based on a + * DWrite font face. This font can then be used with + * cairo_set_font_face() or cairo_scaled_font_create(). + * + * Here is an example of how this function might be used: + * <informalexample><programlisting><![CDATA[ + * #include <cairo-dwrite.h> + * #include <dwrite.h> + * + * IDWriteFactory* dWriteFactory = NULL; + * HRESULT hr = DWriteCreateFactory( + * DWRITE_FACTORY_TYPE_SHARED, + * __uuidof(IDWriteFactory), + * reinterpret_cast<IUnknown**>(&dWriteFactory)); + * + * IDWriteFontCollection *systemCollection; + * hr = dWriteFactory->GetSystemFontCollection(&systemCollection); + * + * UINT32 idx; + * BOOL found; + * systemCollection->FindFamilyName(L"Segoe UI Emoji", &idx, &found); + * + * IDWriteFontFamily *family; + * systemCollection->GetFontFamily(idx, &family); + * + * IDWriteFont *dwritefont; + * DWRITE_FONT_WEIGHT weight = DWRITE_FONT_WEIGHT_NORMAL; + * DWRITE_FONT_STYLE style = DWRITE_FONT_STYLE_NORMAL; + * hr = family->GetFirstMatchingFont(weight, DWRITE_FONT_STRETCH_NORMAL, style, &dwritefont); + * + * IDWriteFontFace *dwriteface; + * hr = dwritefont->CreateFontFace(&dwriteface); + * + * cairo_font_face_t *face; + * face = cairo_dwrite_font_face_create_for_dwrite_fontface(dwriteface); + * cairo_set_font_face(cr, face); + * cairo_set_font_size(cr, 70); + * cairo_move_to(cr, 100, 100); + * cairo_show_text(cr, "😃"); + * ]]></programlisting></informalexample> + * + * Note: When printing a DWrite font to a + * #CAIRO_SURFACE_TYPE_WIN32_PRINTING surface, the printing surface + * will substitute each DWrite font with a Win32 font created from the same + * underlying font file. If the matching font file can not be found, + * the #CAIRO_SURFACE_TYPE_WIN32_PRINTING surface will convert each + * glyph to a filled path. If a DWrite font was not created from a system + * font, it is recommended that the font used to create the DWrite + * font be made available to GDI to avoid the undesirable fallback + * to emitting paths. This can be achieved using the GDI font loading functions + * such as AddFontMemResourceEx(). + * + * Return value: a newly created #cairo_font_face_t. Free with + * cairo_font_face_destroy() when you are done using it. + * + * Since: 1.18 + **/ +cairo_font_face_t * +cairo_dwrite_font_face_create_for_dwrite_fontface (IDWriteFontFace *dwrite_font_face) { - IDWriteFont *dwritefont = static_cast<IDWriteFont*>(dwrite_font); IDWriteFontFace *dwriteface = static_cast<IDWriteFontFace*>(dwrite_font_face); - cairo_dwrite_font_face_t *face = new cairo_dwrite_font_face_t; - cairo_font_face_t *font_face; + // Must do malloc and not C++ new, since Cairo frees this. + cairo_dwrite_font_face_t *face = (cairo_dwrite_font_face_t *)_cairo_malloc(sizeof(cairo_dwrite_font_face_t)); + if (unlikely (face == NULL)) { + _cairo_error_throw (CAIRO_STATUS_NO_MEMORY); + return (cairo_font_face_t*)&_cairo_font_face_nil; + } dwriteface->AddRef(); - face->dwriteface = dwriteface; - face->font = NULL; + face->have_color = false; + face->rendering_params = NULL; + face->measuring_mode = DWRITE_MEASURING_MODE_NATURAL; + + /* Ensure IDWriteFactory4 is available before enabling color fonts */ + if (DWriteFactory::Instance4()) { + RefPtr<IDWriteFontFace2> fontFace2; + if (SUCCEEDED(dwriteface->QueryInterface(&fontFace2))) { + if (fontFace2->IsColorFont()) + face->have_color = true; + } + } + cairo_font_face_t *font_face; font_face = (cairo_font_face_t*)face; - _cairo_font_face_init (&((cairo_dwrite_font_face_t*)font_face)->base, &_cairo_dwrite_font_face_backend); return font_face; } -void -cairo_dwrite_scaled_font_set_force_GDI_classic(cairo_scaled_font_t *dwrite_scaled_font, cairo_bool_t force) +/** + * cairo_dwrite_font_face_get_rendering_params: + * @font_face: The #cairo_dwrite_font_face_t object to query + * + * Gets the #IDWriteRenderingParams object of @font_face. + * + * Return value: the #IDWriteRenderingParams object or %NULL if none. + * + * Since: 1.18 + **/ +IDWriteRenderingParams * +cairo_dwrite_font_face_get_rendering_params (cairo_font_face_t *font_face) { - cairo_dwrite_scaled_font_t *font = reinterpret_cast<cairo_dwrite_scaled_font_t*>(dwrite_scaled_font); - if (force && font->rendering_mode == cairo_dwrite_scaled_font_t::TEXT_RENDERING_NORMAL) { - font->rendering_mode = cairo_dwrite_scaled_font_t::TEXT_RENDERING_GDI_CLASSIC; - } else if (!force && font->rendering_mode == cairo_dwrite_scaled_font_t::TEXT_RENDERING_GDI_CLASSIC) { - font->rendering_mode = cairo_dwrite_scaled_font_t::TEXT_RENDERING_NORMAL; - } + cairo_dwrite_font_face_t *dwface = reinterpret_cast<cairo_dwrite_font_face_t *>(font_face); + return dwface->rendering_params; } -cairo_bool_t -cairo_dwrite_scaled_font_get_force_GDI_classic(cairo_scaled_font_t *dwrite_scaled_font) +/** + * cairo_dwrite_font_face_set_rendering_params: + * @font_face: The #cairo_dwrite_font_face_t object to modify + * @params: The #IDWriteRenderingParams object + * + * Sets the #IDWriteRenderingParams object to @font_face. + * This #IDWriteRenderingParams is used to render glyphs if default values of font options are used. + * If non-defalut values of font options are specified when creating a #cairo_scaled_font_t, + * cairo creates a new #IDWriteRenderingParams object for the #cairo_scaled_font_t object by overwriting the corresponding parameters. + * + * Since: 1.18 + **/ +void +cairo_dwrite_font_face_set_rendering_params (cairo_font_face_t *font_face, IDWriteRenderingParams *params) { - cairo_dwrite_scaled_font_t *font = reinterpret_cast<cairo_dwrite_scaled_font_t*>(dwrite_scaled_font); - return font->rendering_mode == cairo_dwrite_scaled_font_t::TEXT_RENDERING_GDI_CLASSIC; + cairo_dwrite_font_face_t *dwface = reinterpret_cast<cairo_dwrite_font_face_t *>(font_face); + if (dwface->rendering_params) + dwface->rendering_params->Release(); + dwface->rendering_params = params; + if (dwface->rendering_params) + dwface->rendering_params->AddRef(); } -void -cairo_dwrite_set_cleartype_params(FLOAT gamma, FLOAT contrast, FLOAT level, - int geometry, int mode) +/** + * cairo_dwrite_font_face_get_measuring_mode: + * @font_face: The #cairo_dwrite_font_face_t object to query + * + * Gets the #DWRITE_MEASURING_MODE enum of @font_face. + * + * Return value: The #DWRITE_MEASURING_MODE enum of @font_face. + * + * Since: 1.18 + **/ +DWRITE_MEASURING_MODE +cairo_dwrite_font_face_get_measuring_mode (cairo_font_face_t *font_face) { - DWriteFactory::SetRenderingParams(gamma, contrast, level, geometry, mode); + cairo_dwrite_font_face_t *dwface = reinterpret_cast<cairo_dwrite_font_face_t *>(font_face); + return dwface->measuring_mode; } -int -cairo_dwrite_get_cleartype_rendering_mode() +/** + * cairo_dwrite_font_face_set_measuring_mode: + * @font_face: The #cairo_dwrite_font_face_t object to modify + * @mode: The #DWRITE_MEASURING_MODE enum. + * + * Sets the #DWRITE_MEASURING_MODE enum to @font_face. + * + * Since: 1.18 + **/ +void +cairo_dwrite_font_face_set_measuring_mode (cairo_font_face_t *font_face, DWRITE_MEASURING_MODE mode) { - return DWriteFactory::GetClearTypeRenderingMode(); + cairo_dwrite_font_face_t *dwface = reinterpret_cast<cairo_dwrite_font_face_t *>(font_face); + dwface->measuring_mode = mode; } -cairo_int_status_t +static cairo_int_status_t _dwrite_draw_glyphs_to_gdi_surface_gdi(cairo_win32_surface_t *surface, DWRITE_MATRIX *transform, DWRITE_GLYPH_RUN *run, @@ -947,44 +1611,25 @@ _dwrite_draw_glyphs_to_gdi_surface_gdi(cairo_win32_surface_t *surface, cairo_dwrite_scaled_font_t *scaled_font, const RECT &area) { - IDWriteGdiInterop *gdiInterop; + RefPtr<IDWriteGdiInterop> gdiInterop; DWriteFactory::Instance()->GetGdiInterop(&gdiInterop); - IDWriteBitmapRenderTarget *rt; - HRESULT rv; - - cairo_dwrite_scaled_font_t::TextRenderingState renderingState = - scaled_font->rendering_mode; + RefPtr<IDWriteBitmapRenderTarget> rt; + HRESULT hr; - rv = gdiInterop->CreateBitmapRenderTarget(surface->dc, + hr = gdiInterop->CreateBitmapRenderTarget(surface->dc, area.right - area.left, area.bottom - area.top, &rt); - if (FAILED(rv)) { - if (rv == E_OUTOFMEMORY) { + if (FAILED(hr)) { + if (hr == E_OUTOFMEMORY) { return (cairo_int_status_t)CAIRO_STATUS_NO_MEMORY; } else { return CAIRO_INT_STATUS_UNSUPPORTED; } } - if ((renderingState == cairo_dwrite_scaled_font_t::TEXT_RENDERING_NORMAL || - renderingState == cairo_dwrite_scaled_font_t::TEXT_RENDERING_GDI_CLASSIC) && - !surface->base.permit_subpixel_antialiasing) { - renderingState = cairo_dwrite_scaled_font_t::TEXT_RENDERING_NO_CLEARTYPE; - IDWriteBitmapRenderTarget1* rt1; - rv = rt->QueryInterface(&rt1); - - if (SUCCEEDED(rv) && rt1) { - rt1->SetTextAntialiasMode(DWRITE_TEXT_ANTIALIAS_MODE_GRAYSCALE); - rt1->Release(); - } - } - - IDWriteRenderingParams *params = - DWriteFactory::RenderingParams(renderingState); - - /** + /* * We set the number of pixels per DIP to 1.0. This is because we always want * to draw in device pixels, and not device independent pixels. On high DPI * systems this value will be higher than 1.0 and automatically upscale @@ -992,35 +1637,29 @@ _dwrite_draw_glyphs_to_gdi_surface_gdi(cairo_win32_surface_t *surface, */ rt->SetPixelsPerDip(1.0); + float x = 0, y = 0; if (transform) { - rt->SetCurrentTransform(transform); + DWRITE_MATRIX matrix = *transform; + matrix.dx -= area.left; + matrix.dy -= area.top; + rt->SetCurrentTransform(&matrix); + } else { + x = (float) -area.left; + y = (float) -area.top; } BitBlt(rt->GetMemoryDC(), 0, 0, area.right - area.left, area.bottom - area.top, surface->dc, - area.left, area.top, + area.left, area.top, SRCCOPY | NOMIRRORBITMAP); - DWRITE_MEASURING_MODE measureMode; - switch (renderingState) { - case cairo_dwrite_scaled_font_t::TEXT_RENDERING_GDI_CLASSIC: - case cairo_dwrite_scaled_font_t::TEXT_RENDERING_NO_CLEARTYPE: - measureMode = DWRITE_MEASURING_MODE_GDI_CLASSIC; - break; - default: - measureMode = DWRITE_MEASURING_MODE_NATURAL; - break; - } - HRESULT hr = rt->DrawGlyphRun(0, 0, measureMode, run, params, color); + rt->DrawGlyphRun(x, y, scaled_font->measuring_mode, run, scaled_font->rendering_params, color); BitBlt(surface->dc, area.left, area.top, area.right - area.left, area.bottom - area.top, rt->GetMemoryDC(), - 0, 0, + 0, 0, SRCCOPY | NOMIRRORBITMAP); - params->Release(); - rt->Release(); - gdiInterop->Release(); return CAIRO_INT_STATUS_SUCCESS; } @@ -1031,33 +1670,26 @@ _dwrite_draw_glyphs_to_gdi_surface_d2d(cairo_win32_surface_t *surface, COLORREF color, const RECT &area) { - HRESULT rv; + HRESULT hr; - ID2D1DCRenderTarget *rt = D2DFactory::RenderTarget(); + RefPtr<ID2D1DCRenderTarget> rt = D2DFactory::RenderTarget(); // XXX don't we need to set RenderingParams on this RenderTarget? - rv = rt->BindDC(surface->dc, &area); - - printf("Rendering to surface: %p\n", surface->dc); - - if (FAILED(rv)) { - rt->Release(); + hr = rt->BindDC(surface->dc, &area); + if (FAILED(hr)) return CAIRO_INT_STATUS_UNSUPPORTED; - } // D2D uses 0x00RRGGBB not 0x00BBGGRR like COLORREF. color = (color & 0xFF) << 16 | (color & 0xFF00) | (color & 0xFF0000) >> 16; - ID2D1SolidColorBrush *brush; - rv = rt->CreateSolidColorBrush(D2D1::ColorF(color, 1.0), &brush); - - if (FAILED(rv)) { - rt->Release(); + RefPtr<ID2D1SolidColorBrush> brush; + hr = rt->CreateSolidColorBrush(D2D1::ColorF(color, 1.0), &brush); + if (FAILED(hr)) return CAIRO_INT_STATUS_UNSUPPORTED; - } + float x = 0, y = 0; if (transform) { rt->SetTransform(D2D1::Matrix3x2F(transform->m11, transform->m12, @@ -1068,14 +1700,12 @@ _dwrite_draw_glyphs_to_gdi_surface_d2d(cairo_win32_surface_t *surface, } rt->BeginDraw(); rt->DrawGlyphRun(D2D1::Point2F(0, 0), run, brush); - rt->EndDraw(); + hr = rt->EndDraw(); if (transform) { rt->SetTransform(D2D1::Matrix3x2F::Identity()); } - brush->Release(); - if (FAILED(rv)) { + if (FAILED(hr)) return CAIRO_INT_STATUS_UNSUPPORTED; - } return CAIRO_INT_STATUS_SUCCESS; } @@ -1108,15 +1738,6 @@ _cairo_dwrite_show_glyphs_on_surface(void *surface, if (op != CAIRO_OPERATOR_SOURCE && op != CAIRO_OPERATOR_OVER) return CAIRO_INT_STATUS_UNSUPPORTED; - /* If we have a fallback mask clip set on the dst, we have - * to go through the fallback path */ - if (!_cairo_surface_is_win32_printing (&dst->base)) { - if (clip != NULL) - _cairo_win32_display_surface_set_clip (to_win32_display_surface (dst), clip); - else - _cairo_win32_display_surface_unset_clip (to_win32_display_surface (dst)); - } - /* It is vital that dx values for dxy_buf are calculated from the delta of * _logical_ x coordinates (not user x coordinates) or else the sum of all * previous dx values may start to diverge from the current glyph's x @@ -1131,97 +1752,8 @@ _cairo_dwrite_show_glyphs_on_surface(void *surface, DWRITE_GLYPH_OFFSET *offsets = const_cast<DWRITE_GLYPH_OFFSET*>(run.glyphOffsets); BOOL transform = FALSE; - /* Needed to calculate bounding box for efficient blitting */ - INT32 smallestX = INT_MAX; - INT32 largestX = 0; - INT32 smallestY = INT_MAX; - INT32 largestY = 0; - for (int i = 0; i < num_glyphs; i++) { - if (glyphs[i].x < smallestX) { - smallestX = (INT32)glyphs[i].x; - } - if (glyphs[i].x > largestX) { - largestX = (INT32)glyphs[i].x; - } - if (glyphs[i].y < smallestY) { - smallestY = (INT32)glyphs[i].y; - } - if (glyphs[i].y > largestY) { - largestY = (INT32)glyphs[i].y; - } - } - /** - * Here we try to get a rough estimate of the area that this glyph run will - * cover on the surface. Since we use GDI interop to draw we will be copying - * data around the size of the area of the surface that we map. We will want - * to map an area as small as possible to prevent large surfaces to be - * copied around. We take the X/Y-size of the font as margin on the left/top - * twice the X/Y-size of the font as margin on the right/bottom. - * This should always cover the entire area where the glyphs are. - */ - RECT fontArea; - fontArea.left = (INT32)(smallestX - scaled_font->font_matrix.xx); - fontArea.right = (INT32)(largestX + scaled_font->font_matrix.xx * 2); - fontArea.top = (INT32)(smallestY - scaled_font->font_matrix.yy); - fontArea.bottom = (INT32)(largestY + scaled_font->font_matrix.yy * 2); - if (fontArea.left < 0) - fontArea.left = 0; - if (fontArea.top < 0) - fontArea.top = 0; - if (fontArea.bottom > dst->extents.height) { - fontArea.bottom = dst->extents.height; - } - if (fontArea.right > dst->extents.width) { - fontArea.right = dst->extents.width; - } - if (fontArea.right <= fontArea.left || - fontArea.bottom <= fontArea.top) { - return CAIRO_INT_STATUS_SUCCESS; - } - if (fontArea.right > dst->extents.width) { - fontArea.right = dst->extents.width; - } - if (fontArea.bottom > dst->extents.height) { - fontArea.bottom = dst->extents.height; - } + _cairo_dwrite_glyph_run_from_glyphs(glyphs, num_glyphs, dwritesf, &run, &transform); - run.bidiLevel = 0; - run.fontFace = dwriteff->dwriteface; - run.isSideways = FALSE; - if (dwritesf->mat.xy == 0 && dwritesf->mat.yx == 0 && - dwritesf->mat.xx == scaled_font->font_matrix.xx && - dwritesf->mat.yy == scaled_font->font_matrix.yy) { - - for (int i = 0; i < num_glyphs; i++) { - indices[i] = (WORD) glyphs[i].index; - // Since we will multiply by our ctm matrix later for rotation effects - // and such, adjust positions by the inverse matrix now. - offsets[i].ascenderOffset = (FLOAT)(fontArea.top - glyphs[i].y); - offsets[i].advanceOffset = (FLOAT)(glyphs[i].x - fontArea.left); - advances[i] = 0.0; - } - run.fontEmSize = (FLOAT)scaled_font->font_matrix.yy; - } else { - transform = TRUE; - // See comment about EPSILON in _cairo_dwrite_glyph_run_from_glyphs - const double EPSILON = 0.0001; - for (int i = 0; i < num_glyphs; i++) { - indices[i] = (WORD) glyphs[i].index; - double x = glyphs[i].x - fontArea.left + EPSILON; - double y = glyphs[i].y - fontArea.top; - cairo_matrix_transform_point(&dwritesf->mat_inverse, &x, &y); - /** - * Since we will multiply by our ctm matrix later for rotation effects - * and such, adjust positions by the inverse matrix now. The Y-axis - * is inverted so the offset becomes negative. - */ - offsets[i].ascenderOffset = -(FLOAT)y; - offsets[i].advanceOffset = (FLOAT)x; - advances[i] = 0.0; - } - run.fontEmSize = 1.0f; - } - cairo_solid_pattern_t *solid_pattern = (cairo_solid_pattern_t *)source; COLORREF color = RGB(((int)solid_pattern->color.red_short) >> 8, ((int)solid_pattern->color.green_short) >> 8, @@ -1236,18 +1768,31 @@ _cairo_dwrite_show_glyphs_on_surface(void *surface, mat = NULL; } - RECT area; - area.left = dst->extents.x; - area.top = dst->extents.y; - area.right = area.left + dst->extents.width; - area.bottom = area.top + dst->extents.height; + RefPtr<IDWriteGlyphRunAnalysis> runAnalysis; + HRESULT hr = DWriteFactory::Instance()-> + CreateGlyphRunAnalysis(&run, 1, mat, + DWRITE_RENDERING_MODE_ALIASED, + dwritesf->measuring_mode, + 0, // baselineOriginX, + 0, // baselineOriginY, + &runAnalysis); + if (FAILED(hr)) + return CAIRO_INT_STATUS_UNSUPPORTED; + RECT fontArea; + hr = runAnalysis->GetAlphaTextureBounds(DWRITE_TEXTURE_ALIASED_1x1, &fontArea); + if (FAILED(hr)) + return CAIRO_INT_STATUS_UNSUPPORTED; + InflateRect(&fontArea, 1, 1); + /* Needed to calculate bounding box for efficient blitting */ + RECT copyArea, dstArea = { 0, 0, dst->extents.width, dst->extents.height }; + IntersectRect(©Area, &fontArea, &dstArea); #ifdef CAIRO_TRY_D2D_TO_GDI status = _dwrite_draw_glyphs_to_gdi_surface_d2d(dst, mat, &run, color, - fontArea); + copyArea); if (status == (cairo_status_t)CAIRO_INT_STATUS_UNSUPPORTED) { #endif @@ -1256,7 +1801,7 @@ _cairo_dwrite_show_glyphs_on_surface(void *surface, &run, color, dwritesf, - fontArea); + copyArea); #ifdef CAIRO_TRY_D2D_TO_GDI } @@ -1265,104 +1810,100 @@ _cairo_dwrite_show_glyphs_on_surface(void *surface, return status; } -#define ENHANCED_CONTRAST_REGISTRY_KEY \ - HKEY_CURRENT_USER, "Software\\Microsoft\\Avalon.Graphics\\DISPLAY1\\EnhancedContrastLevel" - -void -DWriteFactory::CreateRenderingParams() +/* Check if a specific font table in a DWrite font and a scaled font is identical */ +static cairo_int_status_t +compare_font_tables (cairo_dwrite_font_face_t *dwface, + cairo_scaled_font_t *scaled_font, + unsigned long tag, + cairo_bool_t *match) { - if (!Instance()) { - return; + unsigned long size; + cairo_int_status_t status; + unsigned char *buffer = NULL; + const void *dw_data; + UINT32 dw_size; + void *dw_tableContext = NULL; + BOOL dw_exists = FALSE; + HRESULT hr; + + hr = dwface->dwriteface->TryGetFontTable(be32_to_cpu (tag), + &dw_data, + &dw_size, + &dw_tableContext, + &dw_exists); + if (FAILED(hr)) + return _cairo_dwrite_error (hr, "TryGetFontTable failed"); + + if (!dw_exists) { + *match = FALSE; + status = CAIRO_INT_STATUS_SUCCESS; + goto cleanup; } - Instance()->CreateRenderingParams(&mDefaultRenderingParams); + status = scaled_font->backend->load_truetype_table (scaled_font, tag, 0, NULL, &size); + if (unlikely(status)) + goto cleanup; - // For EnhancedContrast, we override the default if the user has not set it - // in the registry (by using the ClearType Tuner). - FLOAT contrast; - if (mEnhancedContrast >= 0.0 && mEnhancedContrast <= 10.0) { - contrast = mEnhancedContrast; - } else { - HKEY hKey; - if (RegOpenKeyExA(ENHANCED_CONTRAST_REGISTRY_KEY, - 0, KEY_READ, &hKey) == ERROR_SUCCESS) - { - contrast = mDefaultRenderingParams->GetEnhancedContrast(); - RegCloseKey(hKey); - } else { - contrast = 1.0; - } + if (size != dw_size) { + *match = FALSE; + status = CAIRO_INT_STATUS_SUCCESS; + goto cleanup; + } + + buffer = (unsigned char *) _cairo_malloc (size); + if (unlikely (buffer == NULL)) { + status = (cairo_int_status_t) _cairo_error (CAIRO_STATUS_NO_MEMORY); + goto cleanup; } - // For parameters that have not been explicitly set via the SetRenderingParams API, - // we copy values from default params (or our overridden value for contrast) - FLOAT gamma = - mGamma >= 1.0 && mGamma <= 2.2 ? - mGamma : mDefaultRenderingParams->GetGamma(); - FLOAT clearTypeLevel = - mClearTypeLevel >= 0.0 && mClearTypeLevel <= 1.0 ? - mClearTypeLevel : mDefaultRenderingParams->GetClearTypeLevel(); - DWRITE_PIXEL_GEOMETRY pixelGeometry = - mPixelGeometry >= DWRITE_PIXEL_GEOMETRY_FLAT && mPixelGeometry <= DWRITE_PIXEL_GEOMETRY_BGR ? - (DWRITE_PIXEL_GEOMETRY)mPixelGeometry : mDefaultRenderingParams->GetPixelGeometry(); - DWRITE_RENDERING_MODE renderingMode = - mRenderingMode >= DWRITE_RENDERING_MODE_DEFAULT && mRenderingMode <= DWRITE_RENDERING_MODE_CLEARTYPE_NATURAL_SYMMETRIC ? - (DWRITE_RENDERING_MODE)mRenderingMode : mDefaultRenderingParams->GetRenderingMode(); - Instance()->CreateCustomRenderingParams(gamma, contrast, clearTypeLevel, - pixelGeometry, renderingMode, - &mCustomClearTypeRenderingParams); - Instance()->CreateCustomRenderingParams(gamma, contrast, clearTypeLevel, - pixelGeometry, DWRITE_RENDERING_MODE_CLEARTYPE_GDI_CLASSIC, - &mForceGDIClassicRenderingParams); + status = scaled_font->backend->load_truetype_table (scaled_font, tag, 0, buffer, &size); + if (unlikely(status)) + goto cleanup; + + *match = memcmp (dw_data, buffer, size) == 0; + status = CAIRO_INT_STATUS_SUCCESS; + +cleanup: + free (buffer); + if (dw_tableContext) + dwface->dwriteface->ReleaseFontTable(dw_tableContext); + + return status; } -static cairo_bool_t -_name_tables_match (cairo_scaled_font_t *font1, - cairo_scaled_font_t *font2) +/* Check if a DWrite font and a scaled font areis identical + * + * DWrite does not allow accessing the entire font data using tag=0 so we compare + * two of the font tables: + * - 'name' table + * - 'head' table since this contains the checksum for the entire font + */ +static cairo_int_status_t +font_tables_match (cairo_dwrite_font_face_t *dwface, + cairo_scaled_font_t *scaled_font, + cairo_bool_t *match) { - unsigned long size1; - unsigned long size2; - cairo_int_status_t status1; - cairo_int_status_t status2; - unsigned char *buffer1; - unsigned char *buffer2; - cairo_bool_t result = false; - - if (!font1->backend || !font2->backend || - !font1->backend->load_truetype_table || - !font2->backend->load_truetype_table) - return false; - - status1 = font1->backend->load_truetype_table (font1, - TT_TAG_name, 0, NULL, &size1); - status2 = font2->backend->load_truetype_table (font2, - TT_TAG_name, 0, NULL, &size2); - if (status1 || status2) - return false; - if (size1 != size2) - return false; - - buffer1 = (unsigned char*)malloc (size1); - buffer2 = (unsigned char*)malloc (size2); - - if (buffer1 && buffer2) { - status1 = font1->backend->load_truetype_table (font1, - TT_TAG_name, 0, buffer1, &size1); - status2 = font2->backend->load_truetype_table (font2, - TT_TAG_name, 0, buffer2, &size2); - if (!status1 && !status2) { - result = memcmp (buffer1, buffer2, size1) == 0; - } - } - - free (buffer1); - free (buffer2); - return result; + cairo_int_status_t status; + + status = compare_font_tables (dwface, scaled_font, TT_TAG_name, match); + if (unlikely(status)) + return status; + + if (!*match) + return CAIRO_INT_STATUS_SUCCESS; + + status = compare_font_tables (dwface, scaled_font, TT_TAG_head, match); + if (unlikely(status)) + return status; + + return CAIRO_INT_STATUS_SUCCESS; } -// Helper for _cairo_win32_printing_surface_show_glyphs to create a win32 equivalent -// of a dwrite scaled_font so that we can print using ExtTextOut instead of drawing -// paths or blitting glyph bitmaps. +/* + * Helper for _cairo_win32_printing_surface_show_glyphs to create a win32 equivalent + * of a dwrite scaled_font so that we can print using ExtTextOut instead of drawing + * paths or blitting glyph bitmaps. + */ cairo_int_status_t _cairo_dwrite_scaled_font_create_win32_scaled_font (cairo_scaled_font_t *scaled_font, cairo_scaled_font_t **new_font) @@ -1372,6 +1913,16 @@ _cairo_dwrite_scaled_font_create_win32_scaled_font (cairo_scaled_font_t *scaled_ } cairo_font_face_t *face = cairo_scaled_font_get_font_face (scaled_font); + if (cairo_font_face_status (face) == CAIRO_STATUS_SUCCESS && + cairo_font_face_get_type (face) == CAIRO_FONT_TYPE_TOY) + { + face = ((cairo_toy_font_face_t *)face)->impl_face; + } + + if (face == NULL || cairo_font_face_get_type (face) != CAIRO_FONT_TYPE_DWRITE) { + return CAIRO_INT_STATUS_UNSUPPORTED; + } + cairo_dwrite_font_face_t *dwface = reinterpret_cast<cairo_dwrite_font_face_t*>(face); RefPtr<IDWriteGdiInterop> gdiInterop; @@ -1384,12 +1935,15 @@ _cairo_dwrite_scaled_font_create_win32_scaled_font (cairo_scaled_font_t *scaled_ if (FAILED(gdiInterop->ConvertFontFaceToLOGFONT (dwface->dwriteface, &logfont))) { return CAIRO_INT_STATUS_UNSUPPORTED; } - // DW must have been using an outline font, so we want GDI to use the same, - // even if there's also a bitmap face available + + /* DWrite must have been using an outline font, so we want GDI to use the same, + * even if there's also a bitmap face available + */ logfont.lfOutPrecision = OUT_OUTLINE_PRECIS; cairo_font_face_t *win32_face = cairo_win32_font_face_create_for_logfontw (&logfont); - if (!win32_face) { + if (cairo_font_face_status (win32_face)) { + cairo_font_face_destroy (win32_face); return CAIRO_INT_STATUS_UNSUPPORTED; } @@ -1400,6 +1954,7 @@ _cairo_dwrite_scaled_font_create_win32_scaled_font (cairo_scaled_font_t *scaled_ cairo_scaled_font_get_ctm (scaled_font, &ctm); cairo_font_options_t options; + _cairo_font_options_init_default (&options); cairo_scaled_font_get_font_options (scaled_font, &options); cairo_scaled_font_t *font = cairo_scaled_font_create (win32_face, @@ -1408,14 +1963,36 @@ _cairo_dwrite_scaled_font_create_win32_scaled_font (cairo_scaled_font_t *scaled_ &options); cairo_font_face_destroy (win32_face); - if (!font) { + if (cairo_scaled_font_status(font)) { + cairo_scaled_font_destroy (font); return CAIRO_INT_STATUS_UNSUPPORTED; } - if (!_name_tables_match (font, scaled_font)) { - // If the font name tables aren't equal, then GDI may have failed to - // find the right font and substituted a different font. - cairo_scaled_font_destroy (font); + cairo_bool_t match; + cairo_int_status_t status; + status = font_tables_match (dwface, font, &match); + if (status) { + cairo_scaled_font_destroy (font); + return status; + } + + /* If the font tables aren't equal, then GDI may have failed to + * find the right font and substituted a different font. + */ + if (!match) { +#if 0 + char *ps_name; + char *font_name; + status = _cairo_truetype_read_font_name (scaled_font, &ps_name, &font_name); + printf("dwrite fontname: %s PS name: %s\n", font_name, ps_name); + free (font_name); + free (ps_name); + status = _cairo_truetype_read_font_name (font, &ps_name, &font_name); + printf("win32 fontname: %s PS name: %s\n", font_name, ps_name); + free (font_name); + free (ps_name); +#endif + cairo_scaled_font_destroy (font); return CAIRO_INT_STATUS_UNSUPPORTED; } diff --git a/gfx/cairo/cairo/src/win32/cairo-dwrite-private.h b/gfx/cairo/cairo/src/win32/cairo-dwrite-private.hpp index 5f2994cbc0..c7a24822a7 100644 --- a/gfx/cairo/cairo/src/win32/cairo-dwrite-private.h +++ b/gfx/cairo/cairo/src/win32/cairo-dwrite-private.hpp @@ -33,9 +33,28 @@ * Contributor(s): * Bas Schouten <bschouten@mozilla.com> */ -#include <dwrite_1.h> + +#include "cairoint.h" +#include "cairo-win32-refptr.hpp" +#include <dwrite_3.h> #include <d2d1.h> +#ifdef __MINGW32__ +#include "dw-extra.h" +#else +typedef DWRITE_COLOR_GLYPH_RUN1 DWRITE_COLOR_GLYPH_RUN1_WORKAROUND; +#endif + +/* If d2d1_3.h header required for color fonts is not available, + * include our own version containing just the functions we need. + */ + +#if HAVE_D2D1_3_H +#include <d2d1_3.h> +#else +#include "d2d1-extra.h" +#endif + // DirectWrite is not available on all platforms. typedef HRESULT (WINAPI*DWriteCreateFactoryFunc)( DWRITE_FACTORY_TYPE factoryType, @@ -43,31 +62,32 @@ typedef HRESULT (WINAPI*DWriteCreateFactoryFunc)( IUnknown **factory ); -/* cairo_scaled_font_t implementation */ +/* #cairo_scaled_font_t implementation */ struct _cairo_dwrite_scaled_font { cairo_scaled_font_t base; cairo_matrix_t mat; cairo_matrix_t mat_inverse; cairo_antialias_t antialias_mode; + IDWriteRenderingParams *rendering_params; DWRITE_MEASURING_MODE measuring_mode; - enum TextRenderingState { - TEXT_RENDERING_UNINITIALIZED, - TEXT_RENDERING_NO_CLEARTYPE, - TEXT_RENDERING_NORMAL, - TEXT_RENDERING_GDI_CLASSIC - }; - TextRenderingState rendering_mode; }; typedef struct _cairo_dwrite_scaled_font cairo_dwrite_scaled_font_t; class DWriteFactory { public: - static IDWriteFactory *Instance() + static RefPtr<IDWriteFactory> Instance() { if (!mFactoryInstance) { +#ifdef __GNUC__ +#pragma GCC diagnostic push +#pragma GCC diagnostic ignored "-Wcast-function-type" +#endif DWriteCreateFactoryFunc createDWriteFactory = (DWriteCreateFactoryFunc) GetProcAddress(LoadLibraryW(L"dwrite.dll"), "DWriteCreateFactory"); +#ifdef __GNUC__ +#pragma GCC diagnostic pop +#endif if (createDWriteFactory) { HRESULT hr = createDWriteFactory( DWRITE_FACTORY_TYPE_SHARED, @@ -79,7 +99,47 @@ public: return mFactoryInstance; } - static IDWriteFontCollection *SystemCollection() + static RefPtr<IDWriteFactory1> Instance1() + { + if (!mFactoryInstance1) { + if (Instance()) { + Instance()->QueryInterface(&mFactoryInstance1); + } + } + return mFactoryInstance1; + } + + static RefPtr<IDWriteFactory2> Instance2() + { + if (!mFactoryInstance2) { + if (Instance()) { + Instance()->QueryInterface(&mFactoryInstance2); + } + } + return mFactoryInstance2; + } + + static RefPtr<IDWriteFactory3> Instance3() + { + if (!mFactoryInstance3) { + if (Instance()) { + Instance()->QueryInterface(&mFactoryInstance3); + } + } + return mFactoryInstance3; + } + + static RefPtr<IDWriteFactory4> Instance4() + { + if (!mFactoryInstance4) { + if (Instance()) { + Instance()->QueryInterface(&mFactoryInstance4); + } + } + return mFactoryInstance4; + } + + static RefPtr<IDWriteFontCollection> SystemCollection() { if (!mSystemCollection) { if (Instance()) { @@ -90,7 +150,7 @@ public: return mSystemCollection; } - static IDWriteFontFamily *FindSystemFontFamily(const WCHAR *aFamilyName) + static RefPtr<IDWriteFontFamily> FindSystemFontFamily(const WCHAR *aFamilyName) { UINT32 idx; BOOL found; @@ -102,76 +162,29 @@ public: return NULL; } - IDWriteFontFamily *family; + RefPtr<IDWriteFontFamily> family; SystemCollection()->GetFontFamily(idx, &family); return family; } - static IDWriteRenderingParams *RenderingParams(cairo_dwrite_scaled_font_t::TextRenderingState mode) - { - if (!mDefaultRenderingParams || - !mForceGDIClassicRenderingParams || - !mCustomClearTypeRenderingParams) - { - CreateRenderingParams(); - } - IDWriteRenderingParams *params; - if (mode == cairo_dwrite_scaled_font_t::TEXT_RENDERING_NO_CLEARTYPE) { - params = mDefaultRenderingParams; - } else if (mode == cairo_dwrite_scaled_font_t::TEXT_RENDERING_GDI_CLASSIC && mRenderingMode < 0) { - params = mForceGDIClassicRenderingParams; - } else { - params = mCustomClearTypeRenderingParams; - } - if (params) { - params->AddRef(); - } - return params; - } - - static void SetRenderingParams(FLOAT aGamma, - FLOAT aEnhancedContrast, - FLOAT aClearTypeLevel, - int aPixelGeometry, - int aRenderingMode) + static RefPtr<IDWriteRenderingParams> DefaultRenderingParams() { - mGamma = aGamma; - mEnhancedContrast = aEnhancedContrast; - mClearTypeLevel = aClearTypeLevel; - mPixelGeometry = aPixelGeometry; - mRenderingMode = aRenderingMode; - // discard any current RenderingParams objects - if (mCustomClearTypeRenderingParams) { - mCustomClearTypeRenderingParams->Release(); - mCustomClearTypeRenderingParams = NULL; - } - if (mForceGDIClassicRenderingParams) { - mForceGDIClassicRenderingParams->Release(); - mForceGDIClassicRenderingParams = NULL; - } - if (mDefaultRenderingParams) { - mDefaultRenderingParams->Release(); - mDefaultRenderingParams = NULL; + if (!mDefaultRenderingParams) { + if (Instance()) { + Instance()->CreateRenderingParams(&mDefaultRenderingParams); + } } - } - - static int GetClearTypeRenderingMode() { - return mRenderingMode; + return mDefaultRenderingParams; } private: - static void CreateRenderingParams(); - - static IDWriteFactory *mFactoryInstance; - static IDWriteFontCollection *mSystemCollection; - static IDWriteRenderingParams *mDefaultRenderingParams; - static IDWriteRenderingParams *mCustomClearTypeRenderingParams; - static IDWriteRenderingParams *mForceGDIClassicRenderingParams; - static FLOAT mGamma; - static FLOAT mEnhancedContrast; - static FLOAT mClearTypeLevel; - static int mPixelGeometry; - static int mRenderingMode; + static RefPtr<IDWriteFactory> mFactoryInstance; + static RefPtr<IDWriteFactory1> mFactoryInstance1; + static RefPtr<IDWriteFactory2> mFactoryInstance2; + static RefPtr<IDWriteFactory3> mFactoryInstance3; + static RefPtr<IDWriteFactory4> mFactoryInstance4; + static RefPtr<IDWriteFontCollection> mSystemCollection; + static RefPtr<IDWriteRenderingParams> mDefaultRenderingParams; }; class AutoDWriteGlyphRun : public DWRITE_GLYPH_RUN @@ -210,20 +223,12 @@ private: UINT16 mAutoIndices[kNumAutoGlyphs]; }; -/* cairo_font_face_t implementation */ +/* #cairo_font_face_t implementation */ struct _cairo_dwrite_font_face { cairo_font_face_t base; - IDWriteFont *font; - IDWriteFontFace *dwriteface; + IDWriteFontFace *dwriteface; /* Can't use RefPtr because this struct is malloc'd. */ + cairo_bool_t have_color; + IDWriteRenderingParams *rendering_params; /* Can't use RefPtr because this struct is malloc'd. */ + DWRITE_MEASURING_MODE measuring_mode; }; typedef struct _cairo_dwrite_font_face cairo_dwrite_font_face_t; - -DWRITE_MATRIX _cairo_dwrite_matrix_from_matrix(const cairo_matrix_t *matrix); - -// This will initialize a DWrite glyph run from cairo glyphs and a scaled_font. -void -_cairo_dwrite_glyph_run_from_glyphs(cairo_glyph_t *glyphs, - int num_glyphs, - cairo_dwrite_scaled_font_t *scaled_font, - AutoDWriteGlyphRun *run, - cairo_bool_t *transformed); diff --git a/gfx/cairo/cairo/src/win32/cairo-win32-debug.c b/gfx/cairo/cairo/src/win32/cairo-win32-debug.c index 5a971bd614..01410c8969 100644 --- a/gfx/cairo/cairo/src/win32/cairo-win32-debug.c +++ b/gfx/cairo/cairo/src/win32/cairo-win32-debug.c @@ -37,15 +37,6 @@ * Vladimir Vukicevic <vladimir@pobox.com> */ -#define WIN32_LEAN_AND_MEAN -/* We require Windows 2000 features such as ETO_PDY */ -#if !defined(WINVER) || (WINVER < 0x0500) -# define WINVER 0x0500 -#endif -#if !defined(_WIN32_WINNT) || (_WIN32_WINNT < 0x0500) -# define _WIN32_WINNT 0x0500 -#endif - #include "cairoint.h" #include "cairo-win32-private.h" diff --git a/gfx/cairo/cairo/src/win32/cairo-win32-device.c b/gfx/cairo/cairo/src/win32/cairo-win32-device.c index 6fce722ecf..781ee0cde1 100644 --- a/gfx/cairo/cairo/src/win32/cairo-win32-device.c +++ b/gfx/cairo/cairo/src/win32/cairo-win32-device.c @@ -37,15 +37,6 @@ * Vladimir Vukicevic <vladimir@pobox.com> */ -#define WIN32_LEAN_AND_MEAN -/* We require Windows 2000 features such as ETO_PDY */ -#if !defined(WINVER) || (WINVER < 0x0500) -# define WINVER 0x0500 -#endif -#if !defined(_WIN32_WINNT) || (_WIN32_WINNT < 0x0500) -# define _WIN32_WINNT 0x0500 -#endif - #include "cairoint.h" #include "cairo-atomic-private.h" diff --git a/gfx/cairo/cairo/src/win32/cairo-win32-display-surface.c b/gfx/cairo/cairo/src/win32/cairo-win32-display-surface.c index 304d34aea0..e3b3eec2fe 100644 --- a/gfx/cairo/cairo/src/win32/cairo-win32-display-surface.c +++ b/gfx/cairo/cairo/src/win32/cairo-win32-display-surface.c @@ -37,15 +37,6 @@ * Vladimir Vukicevic <vladimir@pobox.com> */ -#define WIN32_LEAN_AND_MEAN -/* We require Windows 2000 features such as ETO_PDY */ -#if !defined(WINVER) || (WINVER < 0x0500) -# define WINVER 0x0500 -#endif -#if !defined(_WIN32_WINNT) || (_WIN32_WINNT < 0x0500) -# define _WIN32_WINNT 0x0500 -#endif - #include "cairoint.h" #include "cairo-clip-private.h" @@ -129,6 +120,8 @@ _create_dc_and_bitmap (cairo_win32_display_surface_t *surface, case CAIRO_FORMAT_INVALID: case CAIRO_FORMAT_RGB16_565: case CAIRO_FORMAT_RGB30: + case CAIRO_FORMAT_RGB96F: + case CAIRO_FORMAT_RGBA128F: return _cairo_error (CAIRO_STATUS_INVALID_FORMAT); case CAIRO_FORMAT_ARGB32: case CAIRO_FORMAT_RGB24: @@ -164,6 +157,8 @@ _create_dc_and_bitmap (cairo_win32_display_surface_t *surface, case CAIRO_FORMAT_INVALID: case CAIRO_FORMAT_RGB16_565: case CAIRO_FORMAT_RGB30: + case CAIRO_FORMAT_RGB96F: + case CAIRO_FORMAT_RGBA128F: ASSERT_NOT_REACHED; /* We can't create real RGB24 bitmaps because something seems to * break if we do, especially if we don't set up an image @@ -242,6 +237,8 @@ _create_dc_and_bitmap (cairo_win32_display_surface_t *surface, case CAIRO_FORMAT_INVALID: case CAIRO_FORMAT_RGB16_565: case CAIRO_FORMAT_RGB30: + case CAIRO_FORMAT_RGB96F: + case CAIRO_FORMAT_RGBA128F: ASSERT_NOT_REACHED; case CAIRO_FORMAT_ARGB32: case CAIRO_FORMAT_RGB24: @@ -981,11 +978,18 @@ cairo_win32_surface_create_with_format (HDC hdc, cairo_format_t format) cairo_device_t *device; switch (format) { - default: - return _cairo_surface_create_in_error (_cairo_error (CAIRO_STATUS_INVALID_FORMAT)); - case CAIRO_FORMAT_ARGB32: - case CAIRO_FORMAT_RGB24: - break; + case CAIRO_FORMAT_INVALID: + case CAIRO_FORMAT_A8: + case CAIRO_FORMAT_A1: + case CAIRO_FORMAT_RGB16_565: + case CAIRO_FORMAT_RGB30: + case CAIRO_FORMAT_RGB96F: + case CAIRO_FORMAT_RGBA128F: + default: + return _cairo_surface_create_in_error (_cairo_error (CAIRO_STATUS_INVALID_FORMAT)); + case CAIRO_FORMAT_ARGB32: + case CAIRO_FORMAT_RGB24: + break; } surface = _cairo_malloc (sizeof (*surface)); @@ -1096,14 +1100,19 @@ cairo_win32_surface_create_with_ddb (HDC hdc, HBITMAP saved_dc_bitmap; switch (format) { - default: /* XXX handle these eventually */ - case CAIRO_FORMAT_A8: - case CAIRO_FORMAT_A1: - return _cairo_surface_create_in_error (_cairo_error (CAIRO_STATUS_INVALID_FORMAT)); - case CAIRO_FORMAT_ARGB32: - case CAIRO_FORMAT_RGB24: - break; + case CAIRO_FORMAT_INVALID: + case CAIRO_FORMAT_A8: + case CAIRO_FORMAT_A1: + case CAIRO_FORMAT_RGB16_565: + case CAIRO_FORMAT_RGB30: + case CAIRO_FORMAT_RGB96F: + case CAIRO_FORMAT_RGBA128F: + default: + return _cairo_surface_create_in_error (_cairo_error (CAIRO_STATUS_INVALID_FORMAT)); + case CAIRO_FORMAT_ARGB32: + case CAIRO_FORMAT_RGB24: + break; } if (!hdc) { diff --git a/gfx/cairo/cairo/src/win32/cairo-win32-font.c b/gfx/cairo/cairo/src/win32/cairo-win32-font.c index 3452c6cf4e..a561e74a44 100644 --- a/gfx/cairo/cairo/src/win32/cairo-win32-font.c +++ b/gfx/cairo/cairo/src/win32/cairo-win32-font.c @@ -33,15 +33,6 @@ * Contributor(s): */ -#define WIN32_LEAN_AND_MEAN -/* We require Windows 2000 features such as GetGlyphIndices */ -#if !defined(WINVER) || (WINVER < 0x0500) -# define WINVER 0x0500 -#endif -#if !defined(_WIN32_WINNT) || (_WIN32_WINNT < 0x0500) -# define _WIN32_WINNT 0x0500 -#endif - #include "cairoint.h" #include "cairo-win32-private.h" @@ -71,12 +62,15 @@ /** * SECTION:cairo-win32-fonts - * @Title: Win32 Fonts + * @Title: Win32 GDI Fonts * @Short_Description: Font support for Microsoft Windows * @See_Also: #cairo_font_face_t * * The Microsoft Windows font backend is primarily used to render text on * Microsoft Windows systems. + * + * Note: Win32 GDI fonts do not support color fonts. Use DWrite fonts + * if color font support is required. **/ /** @@ -650,226 +644,6 @@ _cairo_win32_scaled_font_fini (void *abstract_font) DeleteObject (scaled_font->unscaled_hfont); } -static cairo_int_status_t -_cairo_win32_scaled_font_type1_text_to_glyphs (cairo_win32_scaled_font_t *scaled_font, - double x, - double y, - const char *utf8, - cairo_glyph_t **glyphs, - int *num_glyphs) -{ - uint16_t *utf16; - int n16; - int i; - WORD *glyph_indices = NULL; - cairo_status_t status; - double x_pos, y_pos; - HDC hdc = NULL; - cairo_matrix_t mat; - - status = _cairo_utf8_to_utf16 (utf8, -1, &utf16, &n16); - if (status) - return status; - - glyph_indices = _cairo_malloc_ab (n16 + 1, sizeof (WORD)); - if (!glyph_indices) { - status = _cairo_error (CAIRO_STATUS_NO_MEMORY); - goto FAIL1; - } - - hdc = _get_global_font_dc (); - assert (hdc != NULL); - - status = cairo_win32_scaled_font_select_font (&scaled_font->base, hdc); - if (status) - goto FAIL2; - - if (GetGlyphIndicesW (hdc, utf16, n16, glyph_indices, 0) == GDI_ERROR) { - status = _cairo_win32_print_gdi_error ("_cairo_win32_scaled_font_type1_text_to_glyphs:GetGlyphIndicesW"); - goto FAIL3; - } - - *num_glyphs = n16; - *glyphs = _cairo_malloc_ab (n16, sizeof (cairo_glyph_t)); - if (!*glyphs) { - status = _cairo_error (CAIRO_STATUS_NO_MEMORY); - goto FAIL3; - } - - x_pos = x; - y_pos = y; - - mat = scaled_font->base.ctm; - status = cairo_matrix_invert (&mat); - assert (status == CAIRO_STATUS_SUCCESS); - - _cairo_scaled_font_freeze_cache (&scaled_font->base); - - for (i = 0; i < n16; i++) { - cairo_scaled_glyph_t *scaled_glyph; - - (*glyphs)[i].index = glyph_indices[i]; - (*glyphs)[i].x = x_pos; - (*glyphs)[i].y = y_pos; - - status = _cairo_scaled_glyph_lookup (&scaled_font->base, - glyph_indices[i], - CAIRO_SCALED_GLYPH_INFO_METRICS, - &scaled_glyph); - if (status) { - free (*glyphs); - *glyphs = NULL; - break; - } - - x = scaled_glyph->x_advance; - y = scaled_glyph->y_advance; - cairo_matrix_transform_distance (&mat, &x, &y); - x_pos += x; - y_pos += y; - } - - _cairo_scaled_font_thaw_cache (&scaled_font->base); - -FAIL3: - cairo_win32_scaled_font_done_font (&scaled_font->base); -FAIL2: - free (glyph_indices); -FAIL1: - free (utf16); - - return status; -} - -static cairo_int_status_t -_cairo_win32_scaled_font_text_to_glyphs (void *abstract_font, - double x, - double y, - const char *utf8, - cairo_glyph_t **glyphs, - int *num_glyphs) -{ - cairo_win32_scaled_font_t *scaled_font = abstract_font; - uint16_t *utf16; - int n16; - GCP_RESULTSW gcp_results; - unsigned int buffer_size, i; - WCHAR *glyph_indices = NULL; - int *dx = NULL; - cairo_status_t status; - double x_pos, y_pos; - double x_incr, y_incr; - HDC hdc = NULL; - - /* GetCharacterPlacement() returns utf16 instead of glyph indices - * for Type 1 fonts. Use GetGlyphIndices for Type 1 fonts. */ - if (scaled_font->is_type1) - return _cairo_win32_scaled_font_type1_text_to_glyphs (scaled_font, - x, - y, - utf8, - glyphs, - num_glyphs); - - /* Compute a vector in user space along the baseline of length one logical space unit */ - x_incr = 1; - y_incr = 0; - cairo_matrix_transform_distance (&scaled_font->base.font_matrix, &x_incr, &y_incr); - x_incr /= scaled_font->logical_scale; - y_incr /= scaled_font->logical_scale; - - status = _cairo_utf8_to_utf16 (utf8, -1, &utf16, &n16); - if (status) - return status; - - gcp_results.lStructSize = sizeof (GCP_RESULTS); - gcp_results.lpOutString = NULL; - gcp_results.lpOrder = NULL; - gcp_results.lpCaretPos = NULL; - gcp_results.lpClass = NULL; - - buffer_size = MAX (n16 * 1.2, 16); /* Initially guess number of chars plus a few */ - if (buffer_size > INT_MAX) { - status = _cairo_error (CAIRO_STATUS_NO_MEMORY); - goto FAIL1; - } - - hdc = _get_global_font_dc (); - assert (hdc != NULL); - - status = cairo_win32_scaled_font_select_font (&scaled_font->base, hdc); - if (status) - goto FAIL1; - - while (TRUE) { - free (glyph_indices); - glyph_indices = NULL; - - free (dx); - dx = NULL; - - glyph_indices = _cairo_malloc_ab (buffer_size, sizeof (WCHAR)); - dx = _cairo_malloc_ab (buffer_size, sizeof (int)); - if (!glyph_indices || !dx) { - status = _cairo_error (CAIRO_STATUS_NO_MEMORY); - goto FAIL2; - } - - gcp_results.nGlyphs = buffer_size; - gcp_results.lpDx = dx; - gcp_results.lpGlyphs = glyph_indices; - - if (!GetCharacterPlacementW (hdc, utf16, n16, - 0, - &gcp_results, - GCP_DIACRITIC | GCP_LIGATE | GCP_GLYPHSHAPE | GCP_REORDER)) { - status = _cairo_win32_print_gdi_error ("_cairo_win32_scaled_font_text_to_glyphs"); - goto FAIL2; - } - - if (gcp_results.lpDx && gcp_results.lpGlyphs) - break; - - /* Too small a buffer, try again */ - - buffer_size += buffer_size / 2; - if (buffer_size > INT_MAX) { - status = _cairo_error (CAIRO_STATUS_NO_MEMORY); - goto FAIL2; - } - } - - *num_glyphs = gcp_results.nGlyphs; - *glyphs = _cairo_malloc_ab (gcp_results.nGlyphs, sizeof (cairo_glyph_t)); - if (!*glyphs) { - status = _cairo_error (CAIRO_STATUS_NO_MEMORY); - goto FAIL2; - } - - x_pos = x; - y_pos = y; - - for (i = 0; i < gcp_results.nGlyphs; i++) { - (*glyphs)[i].index = glyph_indices[i]; - (*glyphs)[i].x = x_pos ; - (*glyphs)[i].y = y_pos; - - x_pos += x_incr * dx[i]; - y_pos += y_incr * dx[i]; - } - - FAIL2: - free (glyph_indices); - free (dx); - - cairo_win32_scaled_font_done_font (&scaled_font->base); - - FAIL1: - free (utf16); - - return status; -} - static unsigned long _cairo_win32_scaled_font_ucs4_to_index (void *abstract_font, uint32_t ucs4) @@ -1319,7 +1093,8 @@ _draw_glyphs_on_surface (cairo_win32_surface_t *surface, 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) + cairo_scaled_glyph_info_t info, + const cairo_color_t *foreground_color) { cairo_win32_scaled_font_t *scaled_font = abstract_font; cairo_status_t status; @@ -1330,6 +1105,12 @@ _cairo_win32_scaled_font_glyph_init (void *abstract_font, return status; } + if (info & CAIRO_SCALED_GLYPH_INFO_COLOR_SURFACE) { + scaled_glyph->color_glyph = FALSE; + scaled_glyph->color_glyph_set = TRUE; + return CAIRO_INT_STATUS_UNSUPPORTED; + } + if (info & CAIRO_SCALED_GLYPH_INFO_SURFACE) { status = _cairo_win32_scaled_font_init_glyph_surface (scaled_font, scaled_glyph); if (status) @@ -1554,9 +1335,9 @@ _cairo_win32_scaled_font_load_type1_data (void *abstract_font, length); } -static cairo_surface_t * -_compute_mask (cairo_surface_t *surface, - int quality) +cairo_surface_t * +_cairo_compute_glyph_mask (cairo_surface_t *surface, + int quality) { cairo_image_surface_t *glyph; cairo_image_surface_t *mask; @@ -1640,7 +1421,7 @@ _cairo_win32_scaled_font_init_glyph_surface (cairo_win32_scaled_font_t *scaled_f if (status) goto FAIL; - image = _compute_mask (surface, scaled_font->quality); + image = _cairo_compute_glyph_mask (surface, scaled_font->quality); status = image->status; if (status) goto FAIL; @@ -1843,7 +1624,7 @@ const cairo_scaled_font_backend_t _cairo_win32_scaled_font_backend = { CAIRO_FONT_TYPE_WIN32, _cairo_win32_scaled_font_fini, _cairo_win32_scaled_font_glyph_init, - NULL, /* _cairo_win32_scaled_font_text_to_glyphs, FIXME */ + NULL, /* _cairo_win32_scaled_font_text_to_glyphs */ _cairo_win32_scaled_font_ucs4_to_index, _cairo_win32_scaled_font_load_truetype_table, _cairo_win32_scaled_font_index_to_ucs4, @@ -1960,7 +1741,7 @@ _cairo_win32_font_face_init_key (cairo_win32_font_face_t *key, LOGFONTW *logfont, HFONT font) { - unsigned long hash = _CAIRO_HASH_INIT_VALUE; + uintptr_t hash = _CAIRO_HASH_INIT_VALUE; key->logfont = *logfont; key->hfont = font; @@ -2017,7 +1798,7 @@ _cairo_win32_font_face_scaled_font_create (void *abstract_face, if (font_face->hfont) { /* Check whether it's OK to go ahead and use the font-face's HFONT. */ if (_is_scale (ctm, 1.) && - _is_scale (font_matrix, -font_face->logfont.lfHeight)) { + _is_scale (font_matrix, -font_face->logfont.lfHeight * WIN32_FONT_LOGICAL_SCALE)) { hfont = font_face->hfont; } } diff --git a/gfx/cairo/cairo/src/win32/cairo-win32-gdi-compositor.c b/gfx/cairo/cairo/src/win32/cairo-win32-gdi-compositor.c index 1d1d7f8737..bc1f69e703 100644 --- a/gfx/cairo/cairo/src/win32/cairo-win32-gdi-compositor.c +++ b/gfx/cairo/cairo/src/win32/cairo-win32-gdi-compositor.c @@ -602,7 +602,8 @@ static cairo_bool_t check_glyphs (cairo_composite_rectangles_t *composite, if (! _cairo_clip_is_region (composite->clip)) return FALSE; - if (cairo_scaled_font_get_type (scaled_font) != CAIRO_FONT_TYPE_WIN32) + cairo_font_type_t type = cairo_scaled_font_get_type (scaled_font); + if (type != CAIRO_FONT_TYPE_WIN32 && type != CAIRO_FONT_TYPE_DWRITE) return FALSE; if (! _cairo_pattern_is_opaque_solid (&composite->source_pattern.base)) diff --git a/gfx/cairo/cairo/src/win32/cairo-win32-printing-surface.c b/gfx/cairo/cairo/src/win32/cairo-win32-printing-surface.c index 96e65893e0..a3dd907c2c 100644 --- a/gfx/cairo/cairo/src/win32/cairo-win32-printing-surface.c +++ b/gfx/cairo/cairo/src/win32/cairo-win32-printing-surface.c @@ -35,15 +35,6 @@ * Vladimir Vukicevic <vladimir@pobox.com> */ -#define WIN32_LEAN_AND_MEAN -/* We require Windows 2000 features such as ETO_PDY */ -#if !defined(WINVER) || (WINVER < 0x0500) -# define WINVER 0x0500 -#endif -#if !defined(_WIN32_WINNT) || (_WIN32_WINNT < 0x0500) -# define _WIN32_WINNT 0x0500 -#endif - #include "cairoint.h" #include "cairo-default-context-private.h" @@ -167,8 +158,15 @@ _cairo_win32_printing_surface_init_language_pack (cairo_win32_printing_surface_t module = GetModuleHandleW (L"GDI32.DLL"); if (module) { +#ifdef __GNUC__ +#pragma GCC diagnostic push +#pragma GCC diagnostic ignored "-Wcast-function-type" +#endif gdi_init_lang_pack = (gdi_init_lang_pack_func_t) GetProcAddress (module, "GdiInitializeLanguagePack"); +#ifdef __GNUC__ +#pragma GCC diagnostic pop +#endif if (gdi_init_lang_pack) gdi_init_lang_pack (0); } @@ -656,6 +654,7 @@ _cairo_win32_printing_surface_paint_recording_pattern (cairo_win32_printing_surf SaveDC (surface->win32.dc); /* Allow clip path to be reset during replay */ status = _cairo_recording_surface_replay_region (&recording_surface->base, + pattern->region_array_id, is_subsurface ? &recording_extents : NULL, &surface->win32.base, CAIRO_RECORDING_REGION_NATIVE); @@ -1521,7 +1520,7 @@ _cairo_win32_printing_surface_stroke (void *abstract_surface, cairo_matrix_multiply (&mat, stroke_ctm, &surface->ctm); _cairo_matrix_factor_out_scale (&mat, &scale); - pen_style = PS_GEOMETRIC; + pen_style = style->is_hairline ? PS_COSMETIC : PS_GEOMETRIC; dash_array = NULL; if (style->num_dashes) { pen_style |= PS_USERSTYLE; @@ -1547,10 +1546,12 @@ _cairo_win32_printing_surface_stroke (void *abstract_surface, brush.lbStyle = BS_SOLID; brush.lbColor = color; brush.lbHatch = 0; - pen_style |= _cairo_win32_line_cap (style->line_cap); - pen_style |= _cairo_win32_line_join (style->line_join); + if (!style->is_hairline) { + pen_style |= _cairo_win32_line_cap (style->line_cap); + pen_style |= _cairo_win32_line_join (style->line_join); + } pen = ExtCreatePen(pen_style, - scale * style->line_width, + style->is_hairline ? 1 : scale * style->line_width, &brush, style->num_dashes, dash_array); @@ -1871,6 +1872,7 @@ _cairo_win32_printing_surface_show_glyphs (void *abstract_surfac status = _cairo_scaled_glyph_lookup (scaled_font, glyphs[i].index, CAIRO_SCALED_GLYPH_INFO_PATH, + NULL, /* foreground color */ &scaled_glyph); if (status) break; @@ -1942,6 +1944,7 @@ _cairo_win32_printing_surface_show_glyphs (void *abstract_surfac status = _cairo_scaled_glyph_lookup (scaled_font, glyphs[i].index, CAIRO_SCALED_GLYPH_INFO_PATH, + NULL, /* foreground color */ &scaled_glyph); if (status) break; @@ -2151,6 +2154,9 @@ _cairo_win32_printing_surface_supports_fine_grained_fallbacks (void *abstract_su * provide correct complex rendering behaviour; cairo_surface_show_page() and * associated methods must be used for correct output. * + * The following mime types are supported on source patterns: + * %CAIRO_MIME_TYPE_JPEG, %CAIRO_MIME_TYPE_PNG. + * * Return value: the newly created surface * * Since: 1.6 diff --git a/gfx/cairo/cairo/src/win32/cairo-win32-private.h b/gfx/cairo/cairo/src/win32/cairo-win32-private.h index e6be49b032..6af09c0e1f 100644 --- a/gfx/cairo/cairo/src/win32/cairo-win32-private.h +++ b/gfx/cairo/cairo/src/win32/cairo-win32-private.h @@ -214,6 +214,10 @@ cairo_bool_t _cairo_win32_surface_get_extents (void *abstract_surface, cairo_rectangle_int_t *rectangle); +cairo_surface_t * +_cairo_compute_glyph_mask (cairo_surface_t *surface, + int quality); + uint32_t _cairo_win32_flags_for_dc (HDC dc, cairo_format_t format); @@ -253,7 +257,10 @@ _cairo_win32_scaled_font_is_type1 (cairo_scaled_font_t *scaled_font); cairo_bool_t _cairo_win32_scaled_font_is_bitmap (cairo_scaled_font_t *scaled_font); -#ifdef CAIRO_HAS_DWRITE_FONT +cairo_public BYTE +cairo_win32_get_system_text_quality (void); + +#if CAIRO_HAS_DWRITE_FONT cairo_int_status_t _cairo_dwrite_show_glyphs_on_surface (void *surface, diff --git a/gfx/cairo/cairo/src/win32/cairo-win32-refptr.h b/gfx/cairo/cairo/src/win32/cairo-win32-refptr.hpp index f045ddf627..e361e4cf7f 100644 --- a/gfx/cairo/cairo/src/win32/cairo-win32-refptr.h +++ b/gfx/cairo/cairo/src/win32/cairo-win32-refptr.hpp @@ -38,7 +38,7 @@ template<typename T> class TemporaryRef; -/** +/* * RefPtr points to a refcounted thing that has AddRef and Release * methods to increase/decrease the refcount, respectively. After a * RefPtr<T> is assigned a T*, the T* can be used through the RefPtr @@ -99,7 +99,7 @@ public: template<typename U> operator TemporaryRef<U>() { return TemporaryRef<U>(ptr); } - /** + /** * WARNING for ease of use, passing a reference will release/clear out ptr! * We null out the ptr before returning its address so people passing byref * as input will most likely get functions returning errors rather than accessing @@ -137,7 +137,7 @@ private: } }; -/** +/* * TemporaryRef<T> represents an object that holds a temporary * reference to a T. TemporaryRef objects can't be manually ref'd or * unref'd (being temporaries, not lvalues), so can only relinquish diff --git a/gfx/cairo/cairo/src/win32/cairo-win32-surface.c b/gfx/cairo/cairo/src/win32/cairo-win32-surface.c index e1e6494cce..9cd6f55fcc 100644 --- a/gfx/cairo/cairo/src/win32/cairo-win32-surface.c +++ b/gfx/cairo/cairo/src/win32/cairo-win32-surface.c @@ -37,15 +37,6 @@ * Vladimir Vukicevic <vladimir@pobox.com> */ -#define WIN32_LEAN_AND_MEAN -/* We require Windows 2000 features such as ETO_PDY */ -#if !defined(WINVER) || (WINVER < 0x0500) -# define WINVER 0x0500 -#endif -#if !defined(_WIN32_WINNT) || (_WIN32_WINNT < 0x0500) -# define _WIN32_WINNT 0x0500 -#endif - #include "cairoint.h" #include "cairo-backend-private.h" @@ -171,46 +162,50 @@ cairo_win32_surface_get_dc (cairo_surface_t *surface) return NULL; } +/** + * cairo_win32_get_dc_with_clip: + * (Mozilla addition) + */ HDC -cairo_win32_get_dc_with_clip (cairo_t *cr) +cairo_win32_get_dc_with_clip(cairo_t* cr) { - cairo_surface_t *surface = cairo_get_target (cr); - if (cr->backend->type == CAIRO_TYPE_DEFAULT) { - cairo_default_context_t *c = (cairo_default_context_t *) cr; - cairo_clip_t *clip = _cairo_clip_copy (_cairo_gstate_get_clip (c->gstate)); - if (_cairo_surface_is_win32 (surface)) { - cairo_win32_display_surface_t *winsurf = (cairo_win32_display_surface_t *) surface; + cairo_surface_t* surface = cairo_get_target(cr); + if (cr->backend->type == CAIRO_TYPE_DEFAULT) { + cairo_default_context_t* c = (cairo_default_context_t*)cr; + cairo_clip_t* clip = _cairo_clip_copy(_cairo_gstate_get_clip(c->gstate)); + if (_cairo_surface_is_win32(surface)) { + cairo_win32_display_surface_t* winsurf = (cairo_win32_display_surface_t*)surface; - _cairo_win32_display_surface_set_clip (winsurf, clip); + _cairo_win32_display_surface_set_clip(winsurf, clip); - _cairo_clip_destroy (clip); - return winsurf->win32.dc; - } + _cairo_clip_destroy(clip); + return winsurf->win32.dc; + } - if (_cairo_surface_is_paginated (surface)) { - cairo_surface_t *target; + if (_cairo_surface_is_paginated(surface)) { + cairo_surface_t* target; - target = _cairo_paginated_surface_get_target (surface); + target = _cairo_paginated_surface_get_target(surface); #ifndef CAIRO_OMIT_WIN32_PRINTING - if (_cairo_surface_is_win32_printing (target)) { - cairo_status_t status; - cairo_win32_printing_surface_t *psurf = (cairo_win32_printing_surface_t *) target; + if (_cairo_surface_is_win32_printing(target)) { + cairo_status_t status; + cairo_win32_printing_surface_t* psurf = (cairo_win32_printing_surface_t*)target; - status = _cairo_surface_clipper_set_clip (&psurf->clipper, clip); + status = _cairo_surface_clipper_set_clip(&psurf->clipper, clip); - _cairo_clip_destroy (clip); + _cairo_clip_destroy(clip); - if (status) - return NULL; + if (status) + return NULL; - return psurf->win32.dc; - } + return psurf->win32.dc; + } #endif - } - _cairo_clip_destroy (clip); } - return NULL; + _cairo_clip_destroy(clip); + } + return NULL; } /** @@ -390,16 +385,15 @@ _cairo_win32_surface_emit_glyphs (cairo_win32_surface_t *dst, #undef STACK_GLYPH_SIZE cairo_status_t -cairo_win32_surface_get_size (const cairo_surface_t *surface, int *width, int *height) +cairo_win32_surface_get_size(const cairo_surface_t* surface, int* width, int* height) { - if (surface->type != CAIRO_SURFACE_TYPE_WIN32) - return CAIRO_STATUS_SURFACE_TYPE_MISMATCH; + if (!_cairo_surface_is_win32(surface)) + return CAIRO_STATUS_SURFACE_TYPE_MISMATCH; - const cairo_win32_surface_t *winsurface = (const cairo_win32_surface_t *) surface; + const cairo_win32_surface_t* winsurface = (const cairo_win32_surface_t*)surface; - *width = winsurface->extents.width; - *height = winsurface->extents.height; - - return CAIRO_STATUS_SUCCESS; -} + *width = winsurface->extents.width; + *height = winsurface->extents.height; + return CAIRO_STATUS_SUCCESS; +}
\ No newline at end of file diff --git a/gfx/cairo/cairo/src/win32/cairo-win32-system.c b/gfx/cairo/cairo/src/win32/cairo-win32-system.c index 878553009f..01bbe89dfb 100644 --- a/gfx/cairo/cairo/src/win32/cairo-win32-system.c +++ b/gfx/cairo/cairo/src/win32/cairo-win32-system.c @@ -50,15 +50,6 @@ #if CAIRO_MUTEX_IMPL_WIN32 #if !CAIRO_WIN32_STATIC_BUILD -#define WIN32_LEAN_AND_MEAN -/* We require Windows 2000 features such as ETO_PDY */ -#if !defined(WINVER) || (WINVER < 0x0500) -# define WINVER 0x0500 -#endif -#if !defined(_WIN32_WINNT) || (_WIN32_WINNT < 0x0500) -# define _WIN32_WINNT 0x0500 -#endif - #include <windows.h> /* declare to avoid "no previous prototype for 'DllMain'" warning */ diff --git a/gfx/cairo/cairo/src/win32/d2d1-extra.h b/gfx/cairo/cairo/src/win32/d2d1-extra.h new file mode 100644 index 0000000000..7515a5c90f --- /dev/null +++ b/gfx/cairo/cairo/src/win32/d2d1-extra.h @@ -0,0 +1,122 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ + +/* Mingw-w64 does not have d2d1_2.h and d2d2_3.h. + * + * + * We only need the definitions of two functions: + * ID2D1DeviceContext4::DrawColorBitmapGlyphRun() + * ID2D1DeviceContext4::DrawSvgGlyphRun() + * + * But we need to include all the prior functions in the same struct, + * and parent structs, so that the functions are in the correct position + * in the vtable. The parameters of the unused functions are not + * required as we only need a function in the struct to create a + * function pointer in the vtable. + */ + +#ifndef D2D1_EXTRA_H +#define D2D1_EXTRA_H + +#include <d2d1_1.h> + +interface ID2D1DeviceContext1; +interface ID2D1DeviceContext2; +interface ID2D1DeviceContext3; +interface ID2D1DeviceContext4; +interface ID2D1SvgGlyphStyle; + +enum D2D1_COLOR_BITMAP_GLYPH_SNAP_OPTION { + D2D1_COLOR_BITMAP_GLYPH_SNAP_OPTION_DEFAULT, + D2D1_COLOR_BITMAP_GLYPH_SNAP_OPTION_DISABLE, + D2D1_COLOR_BITMAP_GLYPH_SNAP_OPTION_FORCE_DWORD +}; + +DEFINE_GUID(IID_ID2D1DeviceContext1, 0xd37f57e4, 0x6908, 0x459f, 0xa1, 0x99, 0xe7, 0x2f, 0x24, 0xf7, 0x99, 0x87); +MIDL_INTERFACE("d37f57e4-6908-459f-a199-e72f24f79987") +ID2D1DeviceContext1 : public ID2D1DeviceContext +{ + virtual void STDMETHODCALLTYPE CreateFilledGeometryRealization() = 0; + virtual void STDMETHODCALLTYPE CreateStrokedGeometryRealization() = 0; + virtual void STDMETHODCALLTYPE DrawGeometryRealization() = 0; +}; +#ifdef __CRT_UUID_DECL +__CRT_UUID_DECL(ID2D1DeviceContext1, 0xd37f57e4, 0x6908, 0x459f, 0xa1, 0x99, 0xe7, 0x2f, 0x24, 0xf7, 0x99, 0x87) +#endif + + +DEFINE_GUID(IID_ID2D1DeviceContext2, 0x394ea6a3, 0x0c34, 0x4321, 0x95, 0x0b, 0x6c, 0xa2, 0x0f, 0x0b, 0xe6, 0xc7); +MIDL_INTERFACE("394ea6a3-0c34-4321-950b-6ca20f0be6c7") +ID2D1DeviceContext2 : public ID2D1DeviceContext1 +{ + virtual void STDMETHODCALLTYPE CreateInk() = 0; + virtual void STDMETHODCALLTYPE CreateInkStyle() = 0; + virtual void STDMETHODCALLTYPE CreateGradientMesh() = 0; + virtual void STDMETHODCALLTYPE CreateImageSourceFromWic() = 0; + virtual void STDMETHODCALLTYPE CreateLookupTable3D() = 0; + virtual void STDMETHODCALLTYPE CreateImageSourceFromDxgi() = 0; + virtual void STDMETHODCALLTYPE GetGradientMeshWorldBounds() = 0; + virtual void STDMETHODCALLTYPE DrawInk() = 0; + virtual void STDMETHODCALLTYPE DrawGradientMesh() = 0; + virtual void STDMETHODCALLTYPE DrawGdiMetafile() = 0; + virtual void STDMETHODCALLTYPE CreateTransformedImageSource() = 0; +}; +#ifdef __CRT_UUID_DECL +__CRT_UUID_DECL(ID2D1DeviceContext2, 0x394ea6a3, 0x0c34, 0x4321, 0x95, 0x0b, 0x6c, 0xa2, 0x0f, 0x0b, 0xe6, 0xc7) +#endif + + +DEFINE_GUID(IID_ID2D1DeviceContext3, 0x235a7496, 0x8351, 0x414c, 0xbc, 0xd4, 0x66, 0x72, 0xab, 0x2d, 0x8e, 0x00); +MIDL_INTERFACE("235a7496-8351-414c-bcd4-6672ab2d8e00") +ID2D1DeviceContext3 : public ID2D1DeviceContext2 +{ + virtual void STDMETHODCALLTYPE CreateSpriteBatch() = 0; + virtual void STDMETHODCALLTYPE DrawSpriteBatch() = 0; +}; +#ifdef __CRT_UUID_DECL +__CRT_UUID_DECL(ID2D1DeviceContext3, 0x235a7496, 0x8351, 0x414c, 0xbc, 0xd4, 0x66, 0x72, 0xab, 0x2d, 0x8e, 0x00) +#endif + + +DEFINE_GUID(IID_ID2D1SvgGlyphStyle, 0xaf671749, 0xd241, 0x4db8, 0x8e, 0x41, 0xdc, 0xc2, 0xe5, 0xc1, 0xa4, 0x38); +MIDL_INTERFACE("af671749-d241-4db8-8e41-dcc2e5c1a438") +ID2D1SvgGlyphStyle : public ID2D1Resource +{ + virtual void STDMETHODCALLTYPE SetFill() = 0; + virtual void STDMETHODCALLTYPE GetFill() = 0; + virtual void STDMETHODCALLTYPE SetStroke() = 0; + virtual void STDMETHODCALLTYPE GetStrokeDashesCount() = 0; + virtual void STDMETHODCALLTYPE GetStroke() = 0; +}; +#ifdef __CRT_UUID_DECL +__CRT_UUID_DECL(ID2D1SvgGlyphStyle, 0xaf671749, 0xd241, 0x4db8, 0x8e, 0x41, 0xdc, 0xc2, 0xe5, 0xc1, 0xa4, 0x38) +#endif + + +DEFINE_GUID(IID_ID2D1DeviceContext4, 0x8c427831, 0x3d90, 0x4476, 0xb6, 0x47, 0xc4, 0xfa, 0xe3, 0x49, 0xe4, 0xdb); +MIDL_INTERFACE("8c427831-3d90-4476-b647-c4fae349e4db") +ID2D1DeviceContext4 : public ID2D1DeviceContext3 +{ + virtual void STDMETHODCALLTYPE CreateSvgGlyphStyle() = 0; + virtual void STDMETHODCALLTYPE DrawText() = 0; + virtual void STDMETHODCALLTYPE DrawTextLayout() = 0; + virtual void STDMETHODCALLTYPE DrawColorBitmapGlyphRun( + DWRITE_GLYPH_IMAGE_FORMATS glyphImageFormat, + D2D1_POINT_2F baselineOrigin, + const DWRITE_GLYPH_RUN *glyphRun, + DWRITE_MEASURING_MODE measuringMode, + D2D1_COLOR_BITMAP_GLYPH_SNAP_OPTION bitmapSnapOption) = 0; + + virtual void STDMETHODCALLTYPE DrawSvgGlyphRun( + D2D1_POINT_2F baselineOrigin, + const DWRITE_GLYPH_RUN *glyphRun, + ID2D1Brush *defaultFillBrush, + ID2D1SvgGlyphStyle *svgGlyphStyle, + UINT32 colorPaletteIndex, + DWRITE_MEASURING_MODE measuringMode) = 0; + +}; +#ifdef __CRT_UUID_DECL +__CRT_UUID_DECL(ID2D1DeviceContext4, 0x8c427831, 0x3d90, 0x4476, 0xb6, 0x47, 0xc4, 0xfa, 0xe3, 0x49, 0xe4, 0xdb) +#endif + +#endif diff --git a/gfx/cairo/cairo/src/win32/dw-extra.h b/gfx/cairo/cairo/src/win32/dw-extra.h new file mode 100644 index 0000000000..424fb606db --- /dev/null +++ b/gfx/cairo/cairo/src/win32/dw-extra.h @@ -0,0 +1,28 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ + +/* MinGW workarounds + * + * It doesn't define operators for DWRITE_GLYPH_IMAGE_FORMATS. + * The DWRITE_COLOR_GLYPH_RUN struct isn't valid. + * <https://sourceforge.net/p/mingw-w64/bugs/913/> + */ + +#ifndef DWRITE_EXTRA_H +#define DWRITE_EXTRA_H + +#if defined(__MINGW64_VERSION_MAJOR) && __MINGW64_VERSION_MAJOR < 10 + +typedef struct DWRITE_COLOR_GLYPH_RUN1_WORKAROUND DWRITE_COLOR_GLYPH_RUN1_WORKAROUND; +struct DWRITE_COLOR_GLYPH_RUN1_WORKAROUND : DWRITE_COLOR_GLYPH_RUN +{ + DWRITE_GLYPH_IMAGE_FORMATS glyphImageFormat; + DWRITE_MEASURING_MODE measuringMode; +}; + +#else +typedef DWRITE_COLOR_GLYPH_RUN1 DWRITE_COLOR_GLYPH_RUN1_WORKAROUND; +#endif + +DEFINE_ENUM_FLAG_OPERATORS(DWRITE_GLYPH_IMAGE_FORMATS); + +#endif /* DWRITE_EXTRA_H */ diff --git a/gfx/cairo/cairo/version.py b/gfx/cairo/cairo/version.py new file mode 100644 index 0000000000..aabc20593b --- /dev/null +++ b/gfx/cairo/cairo/version.py @@ -0,0 +1,53 @@ +#!/usr/bin/env python3 +# +# cairo version.py +# +# Extracts the version from cairo-version.h for the meson build files. +# +import os +import re +import sys + + +MAJOR_RE = re.compile( + r'^\s*#\s*define\s+CAIRO_VERSION_MAJOR\s+(?P<number>[0-9]+)\s*$', + re.UNICODE) + +MINOR_RE = re.compile( + r'^\s*#\s*define\s+CAIRO_VERSION_MINOR\s+(?P<number>[0-9]+)\s*$', + re.UNICODE) + +MICRO_RE = re.compile( + r'^\s*#\s*define\s+CAIRO_VERSION_MICRO\s+(?P<number>[0-9]+)\s*$', + re.UNICODE) + +version_major = None +version_minor = None +version_micro = None + +srcroot = os.path.dirname(__file__) +version_h = os.path.join(srcroot, "src", "cairo-version.h") + +with open(version_h, "r", encoding="utf-8") as f: + for line in f: + res = MAJOR_RE.match(line) + if res: + assert version_major is None + version_major = res.group('number') + continue + res = MINOR_RE.match(line) + if res: + assert version_minor is None + version_minor = res.group('number') + continue + res = MICRO_RE.match(line) + if res: + assert version_micro is None + version_micro = res.group('number') + continue + +if not (version_major and version_minor and version_micro): + print(f"ERROR: Could not extract version from cairo-version.h in {srcroot}", file=sys.stderr) # noqa + sys.exit(-1) + +print(f"{version_major}.{version_minor}.{version_micro}") diff --git a/gfx/cairo/libpixman/AUTHORS b/gfx/cairo/libpixman/AUTHORS deleted file mode 100644 index e69de29bb2..0000000000 --- a/gfx/cairo/libpixman/AUTHORS +++ /dev/null diff --git a/gfx/cairo/libpixman/INSTALL b/gfx/cairo/libpixman/INSTALL index 5458714e1e..582470441c 100644 --- a/gfx/cairo/libpixman/INSTALL +++ b/gfx/cairo/libpixman/INSTALL @@ -10,225 +10,29 @@ unlimited permission to copy, distribute and modify it. Basic Installation ================== -Briefly, the shell commands `./configure; make; make install' should -configure, build, and install this package. The following -more-detailed instructions are generic; see the `README' file for -instructions specific to this package. +Briefly, the shell commands `meson setup build/; ninja -C build; ninja +-C build install` should configure, build, and install this package. The +following more-detailed instructions are generic; see the `README` file +for instructions specific to this package. - The `configure' shell script attempts to guess correct values for -various system-dependent variables used during compilation. It uses -those values to create a `Makefile' in each directory of the package. -It may also create one or more `.h' files containing system-dependent -definitions. Finally, it creates a shell script `config.status' that -you can run in the future to recreate the current configuration, and a -file `config.log' containing compiler output (useful mainly for -debugging `configure'). - - It can also use an optional file (typically called `config.cache' -and enabled with `--cache-file=config.cache' or simply `-C') that saves -the results of its tests to speed up reconfiguring. Caching is -disabled by default to prevent problems with accidental use of stale -cache files. - - If you need to do unusual things to compile the package, please try -to figure out how `configure' could check whether to do them, and mail -diffs or instructions to the address given in the `README' so they can -be considered for the next release. If you are using the cache, and at -some point `config.cache' contains results you don't want to keep, you -may remove or edit it. - - The file `configure.ac' (or `configure.in') is used to create -`configure' by a program called `autoconf'. You need `configure.ac' if -you want to change it or regenerate `configure' using a newer version -of `autoconf'. + Running `meson setup` attempts to guess correct values for various +system-dependent variables used during compilation. The simplest way to compile this package is: - 1. `cd' to the directory containing the package's source code and type - `./configure' to configure the package for your system. + 1. `cd` to the directory containing the package's source code and type + `meson setup build/` to configure the package for your system. - Running `configure' might take a while. While running, it prints - some messages telling which features it is checking for. + While running, it prints some messages telling which features it + is checking for. - 2. Type `make' to compile the package. + 2. Type `ninja -C build` to compile the package. - 3. Optionally, type `make check' to run any self-tests that come with - the package. + 3. Optionally, type `ninja -C build test` to run any self-tests that + come with the package. - 4. Type `make install' to install the programs and any data files and - documentation. + 4. Type `ninja -C build install` to install the programs and any + data files and documentation. 5. You can remove the program binaries and object files from the - source code directory by typing `make clean'. To also remove the - files that `configure' created (so you can compile the package for - a different kind of computer), type `make distclean'. There is - also a `make maintainer-clean' target, but that is intended mainly - for the package's developers. If you use it, you may have to get - all sorts of other programs in order to regenerate files that came - with the distribution. - -Compilers and Options -===================== - -Some systems require unusual options for compilation or linking that the -`configure' script does not know about. Run `./configure --help' for -details on some of the pertinent environment variables. - - You can give `configure' initial values for configuration parameters -by setting variables in the command line or in the environment. Here -is an example: - - ./configure CC=c99 CFLAGS=-g LIBS=-lposix - - *Note Defining Variables::, for more details. - -Compiling For Multiple Architectures -==================================== - -You can compile the package for more than one kind of computer at the -same time, by placing the object files for each architecture in their -own directory. To do this, you can use GNU `make'. `cd' to the -directory where you want the object files and executables to go and run -the `configure' script. `configure' automatically checks for the -source code in the directory that `configure' is in and in `..'. - - With a non-GNU `make', it is safer to compile the package for one -architecture at a time in the source code directory. After you have -installed the package for one architecture, use `make distclean' before -reconfiguring for another architecture. - -Installation Names -================== - -By default, `make install' installs the package's commands under -`/usr/local/bin', include files under `/usr/local/include', etc. You -can specify an installation prefix other than `/usr/local' by giving -`configure' the option `--prefix=PREFIX'. - - You can specify separate installation prefixes for -architecture-specific files and architecture-independent files. If you -pass the option `--exec-prefix=PREFIX' to `configure', the package uses -PREFIX as the prefix for installing programs and libraries. -Documentation and other data files still use the regular prefix. - - In addition, if you use an unusual directory layout you can give -options like `--bindir=DIR' to specify different values for particular -kinds of files. Run `configure --help' for a list of the directories -you can set and what kinds of files go in them. - - If the package supports it, you can cause programs to be installed -with an extra prefix or suffix on their names by giving `configure' the -option `--program-prefix=PREFIX' or `--program-suffix=SUFFIX'. - -Optional Features -================= - -Some packages pay attention to `--enable-FEATURE' options to -`configure', where FEATURE indicates an optional part of the package. -They may also pay attention to `--with-PACKAGE' options, where PACKAGE -is something like `gnu-as' or `x' (for the X Window System). The -`README' should mention any `--enable-' and `--with-' options that the -package recognizes. - - For packages that use the X Window System, `configure' can usually -find the X include and library files automatically, but if it doesn't, -you can use the `configure' options `--x-includes=DIR' and -`--x-libraries=DIR' to specify their locations. - -Specifying the System Type -========================== - -There may be some features `configure' cannot figure out automatically, -but needs to determine by the type of machine the package will run on. -Usually, assuming the package is built to be run on the _same_ -architectures, `configure' can figure that out, but if it prints a -message saying it cannot guess the machine type, give it the -`--build=TYPE' option. TYPE can either be a short name for the system -type, such as `sun4', or a canonical name which has the form: - - CPU-COMPANY-SYSTEM - -where SYSTEM can have one of these forms: - - OS KERNEL-OS - - See the file `config.sub' for the possible values of each field. If -`config.sub' isn't included in this package, then this package doesn't -need to know the machine type. - - If you are _building_ compiler tools for cross-compiling, you should -use the option `--target=TYPE' to select the type of system they will -produce code for. - - If you want to _use_ a cross compiler, that generates code for a -platform different from the build platform, you should specify the -"host" platform (i.e., that on which the generated programs will -eventually be run) with `--host=TYPE'. - -Sharing Defaults -================ - -If you want to set default values for `configure' scripts to share, you -can create a site shell script called `config.site' that gives default -values for variables like `CC', `cache_file', and `prefix'. -`configure' looks for `PREFIX/share/config.site' if it exists, then -`PREFIX/etc/config.site' if it exists. Or, you can set the -`CONFIG_SITE' environment variable to the location of the site script. -A warning: not all `configure' scripts look for a site script. - -Defining Variables -================== - -Variables not defined in a site shell script can be set in the -environment passed to `configure'. However, some packages may run -configure again during the build, and the customized values of these -variables may be lost. In order to avoid this problem, you should set -them in the `configure' command line, using `VAR=value'. For example: - - ./configure CC=/usr/local2/bin/gcc - -causes the specified `gcc' to be used as the C compiler (unless it is -overridden in the site shell script). - -Unfortunately, this technique does not work for `CONFIG_SHELL' due to -an Autoconf bug. Until the bug is fixed you can use this workaround: - - CONFIG_SHELL=/bin/bash /bin/bash ./configure CONFIG_SHELL=/bin/bash - -`configure' Invocation -====================== - -`configure' recognizes the following options to control how it operates. - -`--help' -`-h' - Print a summary of the options to `configure', and exit. - -`--version' -`-V' - Print the version of Autoconf used to generate the `configure' - script, and exit. - -`--cache-file=FILE' - Enable the cache: use and save the results of the tests in FILE, - traditionally `config.cache'. FILE defaults to `/dev/null' to - disable caching. - -`--config-cache' -`-C' - Alias for `--cache-file=config.cache'. - -`--quiet' -`--silent' -`-q' - Do not print messages saying which checks are being made. To - suppress all normal output, redirect it to `/dev/null' (any error - messages will still be shown). - -`--srcdir=DIR' - Look for the package's source code in directory DIR. Usually - `configure' can determine that directory automatically. - -`configure' also accepts some other, not widely useful, options. Run -`configure --help' for more details. - + source code directory by typing `ninja -C build clean`. diff --git a/gfx/cairo/libpixman/README b/gfx/cairo/libpixman/README index 961a8529bd..e0e7dcae1c 100644 --- a/gfx/cairo/libpixman/README +++ b/gfx/cairo/libpixman/README @@ -97,14 +97,8 @@ following guidelines: You can run the test suite with - make check - - if you built pixman with autotools or - meson test -C builddir - if you built pixman with meson. - It will take around two minutes to run on a modern PC. - Follow the coding style described in the CODING_STYLE file diff --git a/gfx/cairo/libpixman/src/meson.build b/gfx/cairo/libpixman/src/meson.build index 652cda3418..62ec66bec3 100644 --- a/gfx/cairo/libpixman/src/meson.build +++ b/gfx/cairo/libpixman/src/meson.build @@ -20,7 +20,7 @@ config_h = configure_file( configuration : config, - output : 'config.h' + output : 'pixman-config.h' ) version_h = configure_file( @@ -31,7 +31,8 @@ version_h = configure_file( ) libpixman_extra_cargs = [] -if cc.has_function_attribute('dllexport') +default_library = get_option('default_library') +if default_library != 'static' and cc.has_function_attribute('dllexport') libpixman_extra_cargs = ['-DPIXMAN_API=__declspec(dllexport)'] endif diff --git a/gfx/cairo/libpixman/src/pixman-access.c b/gfx/cairo/libpixman/src/pixman-access.c index 7c5ce783f9..7bd7a5a258 100644 --- a/gfx/cairo/libpixman/src/pixman-access.c +++ b/gfx/cairo/libpixman/src/pixman-access.c @@ -25,7 +25,7 @@ */ #ifdef HAVE_CONFIG_H -#include <config.h> +#include <pixman-config.h> #endif #include <stdlib.h> @@ -465,7 +465,7 @@ convert_and_store_pixel (bits_image_t * image, image, bits, offset, PIXMAN_ ## format); \ } \ \ - static const void *const __dummy__ ## format + static const void *const __dummy__ ## format MAYBE_UNUSED MAKE_ACCESSORS(a8r8g8b8); MAKE_ACCESSORS(x8r8g8b8); @@ -610,6 +610,32 @@ fetch_scanline_a8r8g8b8_sRGB_float (bits_image_t * image, } } +static void +fetch_scanline_r8g8b8_sRGB_float (bits_image_t * image, + int x, + int y, + int width, + uint32_t * b, + const uint32_t *mask) +{ + const uint8_t *bits = (uint8_t *)(image->bits + y * image->rowstride); + argb_t *buffer = (argb_t *)b; + int i; + for (i = x; i < width; ++i) + { + uint32_t p = FETCH_24 (image, bits, i); + argb_t *argb = buffer; + + argb->a = 1.0f; + + argb->r = to_linear[(p >> 16) & 0xff]; + argb->g = to_linear[(p >> 8) & 0xff]; + argb->b = to_linear[(p >> 0) & 0xff]; + + buffer++; + } +} + /* Expects a float buffer */ static void fetch_scanline_a2r10g10b10_float (bits_image_t * image, @@ -981,6 +1007,24 @@ fetch_pixel_a8r8g8b8_sRGB_float (bits_image_t *image, return argb; } +static argb_t +fetch_pixel_r8g8b8_sRGB_float (bits_image_t *image, + int offset, + int line) +{ + uint8_t *bits = (uint8_t *)(image->bits + line * image->rowstride); + uint32_t p = FETCH_24 (image, bits, offset); + argb_t argb; + + argb.a = 1.0f; + + argb.r = to_linear[(p >> 16) & 0xff]; + argb.g = to_linear[(p >> 8) & 0xff]; + argb.b = to_linear[(p >> 0) & 0xff]; + + return argb; +} + static uint32_t fetch_pixel_yuy2 (bits_image_t *image, int offset, @@ -1205,6 +1249,31 @@ store_scanline_a8r8g8b8_sRGB_float (bits_image_t * image, } } +static void +store_scanline_r8g8b8_sRGB_float (bits_image_t * image, + int x, + int y, + int width, + const uint32_t *v) +{ + uint8_t *bits = (uint8_t *)(image->bits + image->rowstride * y) + 3 * x; + argb_t *values = (argb_t *)v; + int i; + + for (i = 0; i < width; ++i) + { + uint32_t r, g, b, rgb; + + r = to_srgb (values[i].r); + g = to_srgb (values[i].g); + b = to_srgb (values[i].b); + + rgb = (r << 16) | (g << 8) | b; + + STORE_24 (image, bits, i, rgb); + } +} + /* * Contracts a floating point image to 32bpp and then stores it using a * regular 32-bit store proc. Despite the type, this function expects an @@ -1283,6 +1352,37 @@ fetch_scanline_a8r8g8b8_32_sRGB (bits_image_t *image, } } +static void +fetch_scanline_r8g8b8_32_sRGB (bits_image_t *image, + int x, + int y, + int width, + uint32_t *buffer, + const uint32_t *mask) +{ + const uint8_t *bits = (uint8_t *)(image->bits + y * image->rowstride) + 3 * x; + uint32_t tmp; + int i; + + for (i = 0; i < width; ++i) + { + uint32_t a, r, g, b; + + tmp = FETCH_24 (image, bits, i); + + a = 0xff; + r = (tmp >> 16) & 0xff; + g = (tmp >> 8) & 0xff; + b = (tmp >> 0) & 0xff; + + r = to_linear[r] * 255.0f + 0.5f; + g = to_linear[g] * 255.0f + 0.5f; + b = to_linear[b] * 255.0f + 0.5f; + + *buffer++ = (a << 24) | (r << 16) | (g << 8) | (b << 0); + } +} + static uint32_t fetch_pixel_a8r8g8b8_32_sRGB (bits_image_t *image, int offset, @@ -1304,6 +1404,27 @@ fetch_pixel_a8r8g8b8_32_sRGB (bits_image_t *image, return (a << 24) | (r << 16) | (g << 8) | (b << 0); } +static uint32_t +fetch_pixel_r8g8b8_32_sRGB (bits_image_t *image, + int offset, + int line) +{ + uint8_t *bits = (uint8_t *)(image->bits + line * image->rowstride); + uint32_t tmp = FETCH_24 (image, bits, offset); + uint32_t a, r, g, b; + + a = 0xff; + r = (tmp >> 16) & 0xff; + g = (tmp >> 8) & 0xff; + b = (tmp >> 0) & 0xff; + + r = to_linear[r] * 255.0f + 0.5f; + g = to_linear[g] * 255.0f + 0.5f; + b = to_linear[b] * 255.0f + 0.5f; + + return (a << 24) | (r << 16) | (g << 8) | (b << 0); +} + static void store_scanline_a8r8g8b8_32_sRGB (bits_image_t *image, int x, @@ -1336,6 +1457,36 @@ store_scanline_a8r8g8b8_32_sRGB (bits_image_t *image, } } +static void +store_scanline_r8g8b8_32_sRGB (bits_image_t *image, + int x, + int y, + int width, + const uint32_t *v) +{ + uint8_t *bits = (uint8_t *)(image->bits + image->rowstride * y) + 3 * x; + uint64_t *values = (uint64_t *)v; + uint64_t tmp; + int i; + + for (i = 0; i < width; ++i) + { + uint32_t r, g, b; + + tmp = values[i]; + + r = (tmp >> 16) & 0xff; + g = (tmp >> 8) & 0xff; + b = (tmp >> 0) & 0xff; + + r = to_srgb (r * (1/255.0f)); + g = to_srgb (g * (1/255.0f)); + b = to_srgb (b * (1/255.0f)); + + STORE_24 (image, bits, i, (r << 16) | (g << 8) | (b << 0)); + } +} + static argb_t fetch_pixel_generic_float (bits_image_t *image, int offset, @@ -1409,6 +1560,11 @@ static const format_info_t accessors[] = fetch_pixel_a8r8g8b8_32_sRGB, fetch_pixel_a8r8g8b8_sRGB_float, store_scanline_a8r8g8b8_32_sRGB, store_scanline_a8r8g8b8_sRGB_float, }, + { PIXMAN_r8g8b8_sRGB, + fetch_scanline_r8g8b8_32_sRGB, fetch_scanline_r8g8b8_sRGB_float, + fetch_pixel_r8g8b8_32_sRGB, fetch_pixel_r8g8b8_sRGB_float, + store_scanline_r8g8b8_32_sRGB, store_scanline_r8g8b8_sRGB_float, + }, /* 24bpp formats */ FORMAT_INFO (r8g8b8), diff --git a/gfx/cairo/libpixman/src/pixman-arm-asm.h b/gfx/cairo/libpixman/src/pixman-arm-asm.h index e7093623e0..882789305b 100644 --- a/gfx/cairo/libpixman/src/pixman-arm-asm.h +++ b/gfx/cairo/libpixman/src/pixman-arm-asm.h @@ -25,6 +25,10 @@ * */ +#ifdef HAVE_CONFIG_H +#include "pixman-config.h" +#endif + /* Supplementary macro for setting function attributes */ .macro pixman_asm_function_impl fname #ifdef ASM_HAVE_FUNC_DIRECTIVE @@ -46,6 +50,12 @@ #endif .endm +.macro pixman_syntax_unified +#ifdef ASM_HAVE_SYNTAX_UNIFIED + .syntax unified +#endif +.endm + .macro pixman_end_asm_function #ifdef ASM_HAVE_FUNC_DIRECTIVE .endfunc diff --git a/gfx/cairo/libpixman/src/pixman-arm-neon-asm-bilinear.S b/gfx/cairo/libpixman/src/pixman-arm-neon-asm-bilinear.S index ce4d5f84e3..6bd27360aa 100644 --- a/gfx/cairo/libpixman/src/pixman-arm-neon-asm-bilinear.S +++ b/gfx/cairo/libpixman/src/pixman-arm-neon-asm-bilinear.S @@ -68,6 +68,8 @@ #include "pixman-arm-asm.h" #include "pixman-arm-neon-asm.h" +pixman_syntax_unified + /* * Bilinear macros from pixman-arm-neon-asm.S */ diff --git a/gfx/cairo/libpixman/src/pixman-arm-neon-asm.S b/gfx/cairo/libpixman/src/pixman-arm-neon-asm.S index 35eca116d1..0e092577f1 100644 --- a/gfx/cairo/libpixman/src/pixman-arm-neon-asm.S +++ b/gfx/cairo/libpixman/src/pixman-arm-neon-asm.S @@ -34,12 +34,6 @@ * - pixman_composite_over_n_8_0565_asm_neon */ -#ifdef __clang__ -#define ldrgeb ldrbge -#define subges subsge -#define subpls subspl -#endif - /* Prevent the stack from becoming executable for no reason... */ #if defined(__linux__) && defined(__ELF__) .section .note.GNU-stack,"",%progbits @@ -59,6 +53,8 @@ #include "pixman-arm-asm.h" #include "pixman-arm-neon-asm.h" + pixman_syntax_unified + /* Global configuration options and preferences */ /* @@ -287,12 +283,12 @@ PF subge, PF_X, PF_X, ORIG_W vrshr.u16 q3, q11, #8 vrshr.u16 q15, q12, #8 - PF subges, PF_CTL, PF_CTL, #0x10 + PF subsge, PF_CTL, PF_CTL, #0x10 vsri.u16 q14, q9, #11 - PF ldrgeb, DUMMY, [PF_SRC, SRC_STRIDE, lsl #src_bpp_shift]! + PF ldrbge, DUMMY, [PF_SRC, SRC_STRIDE, lsl #src_bpp_shift]! vraddhn.u16 d20, q10, q13 vraddhn.u16 d23, q11, q3 - PF ldrgeb, DUMMY, [PF_DST, DST_STRIDE, lsl #dst_bpp_shift]! + PF ldrbge, DUMMY, [PF_DST, DST_STRIDE, lsl #dst_bpp_shift]! vraddhn.u16 d22, q12, q15 vst1.16 {d28, d29}, [DST_W, :128]! .endm @@ -451,9 +447,9 @@ generate_composite_function \ vshll.u8 q8, d1, #8 vst1.16 {d28, d29}, [DST_W, :128]! PF subge, PF_X, PF_X, ORIG_W - PF subges, PF_CTL, PF_CTL, #0x10 + PF subsge, PF_CTL, PF_CTL, #0x10 vshll.u8 q14, d2, #8 - PF ldrgeb, DUMMY, [PF_SRC, SRC_STRIDE, lsl #src_bpp_shift]! + PF ldrbge, DUMMY, [PF_SRC, SRC_STRIDE, lsl #src_bpp_shift]! vshll.u8 q9, d0, #8 .endm @@ -525,10 +521,10 @@ generate_composite_function \ PF pld, [PF_SRC, PF_X, lsl #src_bpp_shift] PF pld, [PF_DST, PF_X, lsl #dst_bpp_shift] PF subge, PF_X, PF_X, ORIG_W - PF subges, PF_CTL, PF_CTL, #0x10 + PF subsge, PF_CTL, PF_CTL, #0x10 vqadd.u8 q14, q0, q2 - PF ldrgeb, DUMMY, [PF_SRC, SRC_STRIDE, lsl #src_bpp_shift]! - PF ldrgeb, DUMMY, [PF_DST, DST_STRIDE, lsl #dst_bpp_shift]! + PF ldrbge, DUMMY, [PF_SRC, SRC_STRIDE, lsl #src_bpp_shift]! + PF ldrbge, DUMMY, [PF_DST, DST_STRIDE, lsl #dst_bpp_shift]! vqadd.u8 q15, q1, q3 .endm @@ -557,10 +553,10 @@ generate_composite_function \ PF pld, [PF_SRC, PF_X, lsl #src_bpp_shift] PF pld, [PF_DST, PF_X, lsl #dst_bpp_shift] PF subge, PF_X, PF_X, ORIG_W - PF subges, PF_CTL, PF_CTL, #0x10 + PF subsge, PF_CTL, PF_CTL, #0x10 vqadd.u8 q14, q0, q2 - PF ldrgeb, DUMMY, [PF_SRC, SRC_STRIDE, lsl #src_bpp_shift]! - PF ldrgeb, DUMMY, [PF_DST, DST_STRIDE, lsl #dst_bpp_shift]! + PF ldrbge, DUMMY, [PF_SRC, SRC_STRIDE, lsl #src_bpp_shift]! + PF ldrbge, DUMMY, [PF_DST, DST_STRIDE, lsl #dst_bpp_shift]! vqadd.u8 q15, q1, q3 .endm @@ -631,9 +627,9 @@ generate_composite_function_single_scanline \ vmull.u8 q8, d22, d4 PF subsge, PF_CTL, PF_CTL, #0x10 vmull.u8 q9, d22, d5 - PF ldrgeb, DUMMY, [PF_SRC, SRC_STRIDE, lsl #src_bpp_shift]! + PF ldrbge, DUMMY, [PF_SRC, SRC_STRIDE, lsl #src_bpp_shift]! vmull.u8 q10, d22, d6 - PF ldrgeb, DUMMY, [PF_DST, DST_STRIDE, lsl #dst_bpp_shift]! + PF ldrbge, DUMMY, [PF_DST, DST_STRIDE, lsl #dst_bpp_shift]! vmull.u8 q11, d22, d7 .endm @@ -683,11 +679,11 @@ generate_composite_function_single_scanline \ vst4.8 {d28, d29, d30, d31}, [DST_W, :128]! PF subge, PF_X, PF_X, ORIG_W vmull.u8 q8, d22, d4 - PF subges, PF_CTL, PF_CTL, #0x10 + PF subsge, PF_CTL, PF_CTL, #0x10 vmull.u8 q9, d22, d5 - PF ldrgeb, DUMMY, [PF_SRC, SRC_STRIDE, lsl #src_bpp_shift]! + PF ldrbge, DUMMY, [PF_SRC, SRC_STRIDE, lsl #src_bpp_shift]! vmull.u8 q10, d22, d6 - PF ldrgeb, DUMMY, [PF_DST, DST_STRIDE, lsl #dst_bpp_shift]! + PF ldrbge, DUMMY, [PF_DST, DST_STRIDE, lsl #dst_bpp_shift]! vmull.u8 q11, d22, d7 .endm @@ -759,9 +755,9 @@ generate_composite_function_single_scanline \ vmull.u8 q9, d24, d5 PF subge, PF_X, PF_X, ORIG_W vmull.u8 q10, d24, d6 - PF subges, PF_CTL, PF_CTL, #0x10 + PF subsge, PF_CTL, PF_CTL, #0x10 vmull.u8 q11, d24, d7 - PF ldrgeb, DUMMY, [PF_DST, DST_STRIDE, lsl #dst_bpp_shift]! + PF ldrbge, DUMMY, [PF_DST, DST_STRIDE, lsl #dst_bpp_shift]! vst4.8 {d28, d29, d30, d31}, [DST_W, :128]! .endm @@ -810,10 +806,10 @@ generate_composite_function \ vst4.8 {d28, d29, d30, d31}, [DST_W, :128]! PF subge, PF_X, PF_X, ORIG_W vmull.u8 q8, d22, d4 - PF subges, PF_CTL, PF_CTL, #0x10 + PF subsge, PF_CTL, PF_CTL, #0x10 vmull.u8 q9, d22, d5 vmull.u8 q10, d22, d6 - PF ldrgeb, DUMMY, [PF_DST, DST_STRIDE, lsl #dst_bpp_shift]! + PF ldrbge, DUMMY, [PF_DST, DST_STRIDE, lsl #dst_bpp_shift]! vmull.u8 q11, d22, d7 .endm @@ -1265,9 +1261,9 @@ generate_composite_function \ vmull.u8 q9, d24, d1 PF subge, PF_X, PF_X, ORIG_W vmull.u8 q10, d24, d2 - PF subges, PF_CTL, PF_CTL, #0x10 + PF subsge, PF_CTL, PF_CTL, #0x10 vmull.u8 q11, d24, d3 - PF ldrgeb, DUMMY, [PF_MASK, MASK_STRIDE, lsl #mask_bpp_shift]! + PF ldrbge, DUMMY, [PF_MASK, MASK_STRIDE, lsl #mask_bpp_shift]! vst4.8 {d28, d29, d30, d31}, [DST_W, :128]! vrsra.u16 q8, q8, #8 vrsra.u16 q9, q9, #8 @@ -1334,9 +1330,9 @@ generate_composite_function \ vmull.u8 q1, d25, d16 PF subge, PF_X, PF_X, ORIG_W vmull.u8 q2, d26, d16 - PF subges, PF_CTL, PF_CTL, #0x10 + PF subsge, PF_CTL, PF_CTL, #0x10 vmull.u8 q3, d27, d16 - PF ldrgeb, DUMMY, [PF_MASK, MASK_STRIDE, lsl #mask_bpp_shift]! + PF ldrbge, DUMMY, [PF_MASK, MASK_STRIDE, lsl #mask_bpp_shift]! vst1.8 {d28, d29, d30, d31}, [DST_W, :128]! vrsra.u16 q0, q0, #8 vrsra.u16 q1, q1, #8 @@ -1430,11 +1426,11 @@ generate_composite_function \ vmull.u8 q7, d24, d9 PF subge, PF_X, PF_X, ORIG_W vmull.u8 q8, d24, d10 - PF subges, PF_CTL, PF_CTL, #0x10 + PF subsge, PF_CTL, PF_CTL, #0x10 vmull.u8 q9, d24, d11 - PF ldrgeb, DUMMY, [PF_DST, DST_STRIDE, lsl #dst_bpp_shift]! + PF ldrbge, DUMMY, [PF_DST, DST_STRIDE, lsl #dst_bpp_shift]! vqadd.u8 q14, q0, q14 - PF ldrgeb, DUMMY, [PF_MASK, MASK_STRIDE, lsl #mask_bpp_shift]! + PF ldrbge, DUMMY, [PF_MASK, MASK_STRIDE, lsl #mask_bpp_shift]! vqadd.u8 q15, q1, q15 vrshr.u16 q10, q6, #8 vrshr.u16 q11, q7, #8 @@ -2444,8 +2440,8 @@ generate_composite_function \ PF cmp, PF_X, ORIG_W PF pld, [PF_SRC, PF_X, lsl #src_bpp_shift] PF subge, PF_X, PF_X, ORIG_W - PF subges, PF_CTL, PF_CTL, #0x10 - PF ldrgeb, DUMMY, [PF_SRC, SRC_STRIDE, lsl #src_bpp_shift]! + PF subsge, PF_CTL, PF_CTL, #0x10 + PF ldrbge, DUMMY, [PF_SRC, SRC_STRIDE, lsl #src_bpp_shift]! .endm generate_composite_function \ @@ -2501,8 +2497,8 @@ generate_composite_function \ PF cmp, PF_X, ORIG_W PF pld, [PF_SRC, PF_X, lsl #src_bpp_shift] PF subge, PF_X, PF_X, ORIG_W - PF subges, PF_CTL, PF_CTL, #0x10 - PF ldrgeb, DUMMY, [PF_SRC, SRC_STRIDE, lsl #src_bpp_shift]! + PF subsge, PF_CTL, PF_CTL, #0x10 + PF ldrbge, DUMMY, [PF_SRC, SRC_STRIDE, lsl #src_bpp_shift]! .endm generate_composite_function \ @@ -3153,7 +3149,7 @@ pixman_asm_function \fname /* ensure good destination alignment */ cmp WIDTH, #1 blt 0f - tst OUT, #(1 << dst_bpp_shift) + tst OUT, #(1 << \dst_bpp_shift) beq 0f vshr.u16 q15, q12, #(16 - BILINEAR_INTERPOLATION_BITS) vadd.u16 q12, q12, q13 @@ -3166,7 +3162,7 @@ pixman_asm_function \fname cmp WIDTH, #2 blt 0f - tst OUT, #(1 << (dst_bpp_shift + 1)) + tst OUT, #(1 << (\dst_bpp_shift + 1)) beq 0f bilinear_interpolate_two_pixels \src_fmt, \dst_fmt sub WIDTH, WIDTH, #2 @@ -3175,7 +3171,7 @@ pixman_asm_function \fname /*********** 8 pixels per iteration *****************/ cmp WIDTH, #4 blt 0f - tst OUT, #(1 << (dst_bpp_shift + 2)) + tst OUT, #(1 << (\dst_bpp_shift + 2)) beq 0f bilinear_interpolate_four_pixels \src_fmt, \dst_fmt sub WIDTH, WIDTH, #4 @@ -3242,7 +3238,7 @@ pixman_asm_function \fname .unreq TMP3 .unreq TMP4 .unreq STRIDE -pixman_end_asm_function + pixman_end_asm_function .endm diff --git a/gfx/cairo/libpixman/src/pixman-arm-neon-asm.h b/gfx/cairo/libpixman/src/pixman-arm-neon-asm.h index 07a136234e..06318d9a93 100644 --- a/gfx/cairo/libpixman/src/pixman-arm-neon-asm.h +++ b/gfx/cairo/libpixman/src/pixman-arm-neon-asm.h @@ -213,24 +213,24 @@ .if \elem_size == 16 mov TMP1, VX, asr #16 adds VX, VX, UNIT_X -5: subpls VX, VX, SRC_WIDTH_FIXED +5: subspl VX, VX, SRC_WIDTH_FIXED bpl 5b add TMP1, \mem_operand, TMP1, asl #1 mov TMP2, VX, asr #16 adds VX, VX, UNIT_X -5: subpls VX, VX, SRC_WIDTH_FIXED +5: subspl VX, VX, SRC_WIDTH_FIXED bpl 5b add TMP2, \mem_operand, TMP2, asl #1 vld1.16 {d\()\reg1\()[0]}, [TMP1, :16] mov TMP1, VX, asr #16 adds VX, VX, UNIT_X -5: subpls VX, VX, SRC_WIDTH_FIXED +5: subspl VX, VX, SRC_WIDTH_FIXED bpl 5b add TMP1, \mem_operand, TMP1, asl #1 vld1.16 {d\()\reg1\()[1]}, [TMP2, :16] mov TMP2, VX, asr #16 adds VX, VX, UNIT_X -5: subpls VX, VX, SRC_WIDTH_FIXED +5: subspl VX, VX, SRC_WIDTH_FIXED bpl 5b add TMP2, \mem_operand, TMP2, asl #1 vld1.16 {d\()\reg1\()[2]}, [TMP1, :16] @@ -238,12 +238,12 @@ .elseif \elem_size == 32 mov TMP1, VX, asr #16 adds VX, VX, UNIT_X -5: subpls VX, VX, SRC_WIDTH_FIXED +5: subspl VX, VX, SRC_WIDTH_FIXED bpl 5b add TMP1, \mem_operand, TMP1, asl #2 mov TMP2, VX, asr #16 adds VX, VX, UNIT_X -5: subpls VX, VX, SRC_WIDTH_FIXED +5: subspl VX, VX, SRC_WIDTH_FIXED bpl 5b add TMP2, \mem_operand, TMP2, asl #2 vld1.32 {d\()\reg1\()[0]}, [TMP1, :32] @@ -281,14 +281,14 @@ .if \elem_size == 16 mov TMP1, VX, asr #16 adds VX, VX, UNIT_X -5: subpls VX, VX, SRC_WIDTH_FIXED +5: subspl VX, VX, SRC_WIDTH_FIXED bpl 5b add TMP1, \mem_operand, TMP1, asl #1 vld1.16 {d\()\reg1\()[\idx]}, [TMP1, :16] .elseif \elem_size == 32 mov TMP1, VX, asr #16 adds VX, VX, UNIT_X -5: subpls VX, VX, SRC_WIDTH_FIXED +5: subspl VX, VX, SRC_WIDTH_FIXED bpl 5b add TMP1, \mem_operand, TMP1, asl #2 vld1.32 {d\()\reg1\()[\idx]}, [TMP1, :32] @@ -420,15 +420,15 @@ PF pld, [PF_MASK, PF_X, lsl #mask_bpp_shift] .endif PF subge, PF_X, PF_X, ORIG_W - PF subges, PF_CTL, PF_CTL, #0x10 + PF subsge, PF_CTL, PF_CTL, #0x10 .if src_bpp_shift >= 0 - PF ldrgeb, DUMMY, [PF_SRC, SRC_STRIDE, lsl #src_bpp_shift]! + PF ldrbge, DUMMY, [PF_SRC, SRC_STRIDE, lsl #src_bpp_shift]! .endif .if dst_r_bpp != 0 - PF ldrgeb, DUMMY, [PF_DST, DST_STRIDE, lsl #dst_bpp_shift]! + PF ldrbge, DUMMY, [PF_DST, DST_STRIDE, lsl #dst_bpp_shift]! .endif .if mask_bpp_shift >= 0 - PF ldrgeb, DUMMY, [PF_MASK, MASK_STRIDE, lsl #mask_bpp_shift]! + PF ldrbge, DUMMY, [PF_MASK, MASK_STRIDE, lsl #mask_bpp_shift]! .endif .endif .endm @@ -465,9 +465,6 @@ beq 2f .irp lowbit, 1, 2, 4, 8, 16 -#ifndef __clang__ -local skip1 -#endif .if (dst_w_bpp <= (\lowbit * 8)) && ((\lowbit * 8) < (pixblock_size * dst_w_bpp)) .if \lowbit < 16 /* we don't need more than 16-byte alignment */ tst DST_R, #\lowbit diff --git a/gfx/cairo/libpixman/src/pixman-arm-neon.c b/gfx/cairo/libpixman/src/pixman-arm-neon.c index 62c944222d..103f1c2dbc 100644 --- a/gfx/cairo/libpixman/src/pixman-arm-neon.c +++ b/gfx/cairo/libpixman/src/pixman-arm-neon.c @@ -27,7 +27,7 @@ */ #ifdef HAVE_CONFIG_H -#include <config.h> +#include <pixman-config.h> #endif #include <string.h> diff --git a/gfx/cairo/libpixman/src/pixman-arm-simd-asm-scaled.S b/gfx/cairo/libpixman/src/pixman-arm-simd-asm-scaled.S index a06b5964ef..cc62c812c2 100644 --- a/gfx/cairo/libpixman/src/pixman-arm-simd-asm-scaled.S +++ b/gfx/cairo/libpixman/src/pixman-arm-simd-asm-scaled.S @@ -25,10 +25,6 @@ * */ -#ifdef __clang__ -#define subpls subspl -#endif - /* Prevent the stack from becoming executable */ #if defined(__linux__) && defined(__ELF__) .section .note.GNU-stack,"",%progbits @@ -43,6 +39,8 @@ #include "pixman-arm-asm.h" + pixman_syntax_unified + /* * Note: This code is only using armv5te instructions (not even armv6), * but is scheduled for ARM Cortex-A8 pipeline. So it might need to @@ -89,21 +87,21 @@ pixman_asm_function \fname and TMP2, VXMASK, VX, asr #(16 - \bpp_shift) adds VX, VX, UNIT_X str\()\t TMP1, [DST], #(1 << \bpp_shift) -9: subpls VX, VX, SRC_WIDTH_FIXED +9: subspl VX, VX, SRC_WIDTH_FIXED bpl 9b ldr\()\t TMP2, [SRC, TMP2] and TMP1, VXMASK, VX, asr #(16 - \bpp_shift) adds VX, VX, UNIT_X str\()\t TMP2, [DST], #(1 << \bpp_shift) -9: subpls VX, VX, SRC_WIDTH_FIXED +9: subspl VX, VX, SRC_WIDTH_FIXED bpl 9b .endm /* now do the scaling */ and TMP1, VXMASK, VX, asr #(16 - \bpp_shift) adds VX, VX, UNIT_X -9: subpls VX, VX, SRC_WIDTH_FIXED +9: subspl VX, VX, SRC_WIDTH_FIXED bpl 9b subs W, W, #(8 + \prefetch_braking_distance) blt 2f @@ -112,7 +110,7 @@ pixman_asm_function \fname mla PF_OFFS, UNIT_X, PF_OFFS, VX 1: /* main loop, process 8 pixels per iteration with prefetch */ pld [SRC, PF_OFFS, asr #(16 - \bpp_shift)] - add PF_OFFS, UNIT_X, lsl #3 + add PF_OFFS, PF_OFFS, UNIT_X, lsl #3 scale_2_pixels scale_2_pixels scale_2_pixels @@ -133,13 +131,8 @@ pixman_asm_function \fname scale_2_pixels 2: tst W, #1 -#ifdef __clang__ ldr\()\t\()ne TMP1, [SRC, TMP1] str\()\t\()ne TMP1, [DST] -#else - ldrne\()\t TMP1, [SRC, TMP1] - strne\()\t TMP1, [DST] -#endif /* cleanup helper macro */ .purgem scale_2_pixels .unreq DST @@ -155,7 +148,7 @@ pixman_asm_function \fname /* return */ pop {r4, r5, r6, r7, r8, r10} bx lr -pixman_end_asm_function + pixman_end_asm_function .endm generate_nearest_scanline_func \ diff --git a/gfx/cairo/libpixman/src/pixman-arm-simd-asm.S b/gfx/cairo/libpixman/src/pixman-arm-simd-asm.S index 48032183a3..34d38f1f05 100644 --- a/gfx/cairo/libpixman/src/pixman-arm-simd-asm.S +++ b/gfx/cairo/libpixman/src/pixman-arm-simd-asm.S @@ -25,11 +25,6 @@ * */ -#ifdef __clang__ -#define adceqs adcseq -#define ldmnedb ldmdbne -#endif - /* Prevent the stack from becoming executable */ #if defined(__linux__) && defined(__ELF__) .section .note.GNU-stack,"",%progbits @@ -45,6 +40,8 @@ #include "pixman-arm-asm.h" #include "pixman-arm-simd-asm.h" + pixman_syntax_unified + /* A head macro should do all processing which results in an output of up to * 16 bytes, as far as the final load instruction. The corresponding tail macro * should complete the processing of the up-to-16 bytes. The calling macro will @@ -127,7 +124,7 @@ generate_composite_function \ .macro src_n_0565_init ldrh SRC, [sp, #ARGS_STACK_OFFSET] - orr SRC, SRC, lsl #16 + orr SRC, SRC, SRC, lsl #16 mov STRIDE_S, SRC mov MASK, SRC mov STRIDE_M, SRC @@ -135,8 +132,8 @@ generate_composite_function \ .macro src_n_8_init ldrb SRC, [sp, #ARGS_STACK_OFFSET] - orr SRC, SRC, lsl #8 - orr SRC, SRC, lsl #16 + orr SRC, SRC, SRC, lsl #8 + orr SRC, SRC, SRC, lsl #16 mov STRIDE_S, SRC mov MASK, SRC mov STRIDE_M, SRC @@ -1025,7 +1022,7 @@ pixman_asm_function pixman_composite_over_n_8888_8888_ca_asm_armv6 cmp ip, #-1 beq pixman_composite_over_white_8888_8888_ca_asm_armv6 /* else drop through... */ - pixman_end_asm_function +pixman_end_asm_function generate_composite_function \ pixman_composite_over_n_8888_8888_ca_asm_armv6_helper, 0, 32, 32 \ FLAG_DST_READWRITE | FLAG_BRANCH_OVER | FLAG_PROCESS_CORRUPTS_PSR | FLAG_PROCESS_DOES_STORE | FLAG_SPILL_LINE_VARS | FLAG_PROCESS_CORRUPTS_SCRATCH | FLAG_PROCESS_CORRUPTS_WK0 \ @@ -1098,13 +1095,13 @@ generate_composite_function \ .elseif \numbytes == 8 teq ORIG_W, WK\()\reg1 teqeq ORIG_W, ORIG_W, asr #32 /* all 0 or all -1? */ - ldmnedb DST, {WK\()\reg1-WK\()\reg2} + ldmdbne DST, {WK\()\reg1-WK\()\reg2} .else teq ORIG_W, WK\()\reg1 teqeq ORIG_W, WK\()\reg2 teqeq ORIG_W, WK\()\reg3 teqeq ORIG_W, ORIG_W, asr #32 /* all 0 or all -1? */ - ldmnedb DST, {WK\()\reg1-WK\()\reg4} + ldmdbne DST, {WK\()\reg1-WK\()\reg4} .endif cmnne DST, #0 /* clear C if NE */ bcs 49f /* no writes to dest if source all -1 */ diff --git a/gfx/cairo/libpixman/src/pixman-arm-simd-asm.h b/gfx/cairo/libpixman/src/pixman-arm-simd-asm.h index 3e78e8a468..5ec19e0034 100644 --- a/gfx/cairo/libpixman/src/pixman-arm-simd-asm.h +++ b/gfx/cairo/libpixman/src/pixman-arm-simd-asm.h @@ -119,37 +119,21 @@ \op\()r\()\cond WK\()\reg2, [\base], #4 \op\()r\()\cond WK\()\reg3, [\base], #4 .else -#ifdef __clang__ \op\()mia\()\cond \base!, {WK\()\reg0,WK\()\reg1,WK\()\reg2,WK\()\reg3} -#else - \op\()m\()\cond\()ia \base!, {WK\()\reg0,WK\()\reg1,WK\()\reg2,WK\()\reg3} -#endif .endif .elseif \numbytes == 8 .if \unaligned == 1 \op\()r\()\cond WK\()\reg0, [\base], #4 \op\()r\()\cond WK\()\reg1, [\base], #4 .else -#ifdef __clang__ \op\()mia\()\cond \base!, {WK\()\reg0,WK\()\reg1} -#else - \op\()m\()\cond\()ia \base!, {WK\()\reg0,WK\()\reg1} -#endif .endif .elseif \numbytes == 4 \op\()r\()\cond WK\()\reg0, [\base], #4 .elseif \numbytes == 2 -#ifdef __clang__ \op\()rh\()\cond WK\()\reg0, [\base], #2 -#else - \op\()r\()\cond\()h WK\()\reg0, [\base], #2 -#endif .elseif \numbytes == 1 -#ifdef __clang__ \op\()rb\()\cond WK\()\reg0, [\base], #1 -#else - \op\()r\()\cond\()b WK\()\reg0, [\base], #1 -#endif .else .error "unsupported size: \numbytes" .endif @@ -157,31 +141,15 @@ .macro pixst_baseupdated cond, numbytes, reg0, reg1, reg2, reg3, base .if \numbytes == 16 -#ifdef __clang__ stm\()\cond\()db \base, {WK\()\reg0,WK\()\reg1,WK\()\reg2,WK\()\reg3} -#else - stmdb\()\cond \base, {WK\()\reg0,WK\()\reg1,WK\()\reg2,WK\()\reg3} -#endif .elseif \numbytes == 8 -#ifdef __clang__ stmdb\()\cond \base, {WK\()\reg0,WK\()\reg1} -#else - stm\()\cond\()db \base, {WK\()\reg0,WK\()\reg1} -#endif .elseif \numbytes == 4 str\()\cond WK\()\reg0, [\base, #-4] .elseif \numbytes == 2 -#ifdef __clang__ strh\()\cond WK\()\reg0, [\base, #-2] -#else - str\()\cond\()h WK\()\reg0, [\base, #-2] -#endif .elseif \numbytes == 1 -#ifdef __clang__ strb\()\cond WK\()\reg0, [\base, #-1] -#else - str\()\cond\()b WK\()\reg0, [\base, #-1] -#endif .else .error "unsupported size: \numbytes" .endif @@ -291,7 +259,7 @@ /* If exactly one fetch per block, then we need either 0, 1 or 2 extra preloads */ PF mov, SCRATCH, \base, lsl #32-5 PF adds, SCRATCH, SCRATCH, X, lsl #32-5+\bpp_shift - PF adceqs, SCRATCH, SCRATCH, #0 + PF adcseq, SCRATCH, SCRATCH, #0 /* The instruction above has two effects: ensures Z is only * set if C was clear (so Z indicates that both shifted quantities * were 0), and clears C if Z was set (so C indicates that the sum diff --git a/gfx/cairo/libpixman/src/pixman-arm-simd.c b/gfx/cairo/libpixman/src/pixman-arm-simd.c index f0d14540bc..40f3a9759b 100644 --- a/gfx/cairo/libpixman/src/pixman-arm-simd.c +++ b/gfx/cairo/libpixman/src/pixman-arm-simd.c @@ -24,7 +24,7 @@ * */ #ifdef HAVE_CONFIG_H -#include <config.h> +#include <pixman-config.h> #endif #include "pixman-private.h" diff --git a/gfx/cairo/libpixman/src/pixman-arm.c b/gfx/cairo/libpixman/src/pixman-arm.c index a164b7f6ca..288172b62d 100644 --- a/gfx/cairo/libpixman/src/pixman-arm.c +++ b/gfx/cairo/libpixman/src/pixman-arm.c @@ -20,7 +20,7 @@ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ #ifdef HAVE_CONFIG_H -#include <config.h> +#include <pixman-config.h> #endif #include "pixman-private.h" diff --git a/gfx/cairo/libpixman/src/pixman-bits-image.c b/gfx/cairo/libpixman/src/pixman-bits-image.c index f050f35316..20353cfd17 100644 --- a/gfx/cairo/libpixman/src/pixman-bits-image.c +++ b/gfx/cairo/libpixman/src/pixman-bits-image.c @@ -27,7 +27,7 @@ */ #ifdef HAVE_CONFIG_H -#include <config.h> +#include <pixman-config.h> #endif #include <stdio.h> #include <stdlib.h> @@ -209,15 +209,15 @@ static force_inline void reduce_32(unsigned int satot, unsigned int srtot, { uint32_t *ret = p; - satot = (satot + 0x8000) >> 16; - srtot = (srtot + 0x8000) >> 16; - sgtot = (sgtot + 0x8000) >> 16; - sbtot = (sbtot + 0x8000) >> 16; + satot = (int32_t)(satot + 0x8000) / 65536; + srtot = (int32_t)(srtot + 0x8000) / 65536; + sgtot = (int32_t)(sgtot + 0x8000) / 65536; + sbtot = (int32_t)(sbtot + 0x8000) / 65536; - satot = CLIP (satot, 0, 0xff); - srtot = CLIP (srtot, 0, 0xff); - sgtot = CLIP (sgtot, 0, 0xff); - sbtot = CLIP (sbtot, 0, 0xff); + satot = CLIP ((int32_t)satot, 0, 0xff); + srtot = CLIP ((int32_t)srtot, 0, 0xff); + sgtot = CLIP ((int32_t)sgtot, 0, 0xff); + sbtot = CLIP ((int32_t)sbtot, 0, 0xff); *ret = ((satot << 24) | (srtot << 16) | (sgtot << 8) | (sbtot)); } @@ -240,10 +240,10 @@ static force_inline void reduce_float(unsigned int satot, unsigned int srtot, { argb_t *ret = p; - ret->a = CLIP (satot / 65536.f, 0.f, 1.f); - ret->r = CLIP (srtot / 65536.f, 0.f, 1.f); - ret->g = CLIP (sgtot / 65536.f, 0.f, 1.f); - ret->b = CLIP (sbtot / 65536.f, 0.f, 1.f); + ret->a = CLIP ((int32_t)satot / 65536.f, 0.f, 1.f); + ret->r = CLIP ((int32_t)srtot / 65536.f, 0.f, 1.f); + ret->g = CLIP ((int32_t)sgtot / 65536.f, 0.f, 1.f); + ret->b = CLIP ((int32_t)sbtot / 65536.f, 0.f, 1.f); } typedef void (* accumulate_pixel_t) (unsigned int *satot, unsigned int *srtot, @@ -1270,7 +1270,7 @@ create_bits (pixman_format_code_t format, *rowstride_bytes = stride; if (clear) - return calloc (buf_size, 1); + return calloc (1, buf_size); else return malloc (buf_size); } diff --git a/gfx/cairo/libpixman/src/pixman-combine-float.c b/gfx/cairo/libpixman/src/pixman-combine-float.c index f5145bc9d7..27392d6089 100644 --- a/gfx/cairo/libpixman/src/pixman-combine-float.c +++ b/gfx/cairo/libpixman/src/pixman-combine-float.c @@ -26,7 +26,7 @@ */ #ifdef HAVE_CONFIG_H -#include <config.h> +#include <pixman-config.h> #endif #include <math.h> diff --git a/gfx/cairo/libpixman/src/pixman-combine32.c b/gfx/cairo/libpixman/src/pixman-combine32.c index 4a89384d9c..de51f64e16 100644 --- a/gfx/cairo/libpixman/src/pixman-combine32.c +++ b/gfx/cairo/libpixman/src/pixman-combine32.c @@ -22,7 +22,7 @@ * SOFTWARE. */ #ifdef HAVE_CONFIG_H -#include <config.h> +#include <pixman-config.h> #endif #include <math.h> diff --git a/gfx/cairo/libpixman/src/pixman-conical-gradient.c b/gfx/cairo/libpixman/src/pixman-conical-gradient.c index a39e20c4eb..37dfffd733 100644 --- a/gfx/cairo/libpixman/src/pixman-conical-gradient.c +++ b/gfx/cairo/libpixman/src/pixman-conical-gradient.c @@ -25,7 +25,7 @@ */ #ifdef HAVE_CONFIG_H -#include <config.h> +#include <pixman-config.h> #endif #include <stdlib.h> diff --git a/gfx/cairo/libpixman/src/pixman-edge.c b/gfx/cairo/libpixman/src/pixman-edge.c index ad6dfc4cfa..c324cd3d42 100644 --- a/gfx/cairo/libpixman/src/pixman-edge.c +++ b/gfx/cairo/libpixman/src/pixman-edge.c @@ -21,7 +21,7 @@ */ #ifdef HAVE_CONFIG_H -#include <config.h> +#include <pixman-config.h> #endif #include <string.h> diff --git a/gfx/cairo/libpixman/src/pixman-fast-path.c b/gfx/cairo/libpixman/src/pixman-fast-path.c index fa5ea03e59..d510cacbf8 100644 --- a/gfx/cairo/libpixman/src/pixman-fast-path.c +++ b/gfx/cairo/libpixman/src/pixman-fast-path.c @@ -24,7 +24,7 @@ */ #ifdef HAVE_CONFIG_H -#include <config.h> +#include <pixman-config.h> #endif #include <string.h> #include <stdlib.h> @@ -2836,11 +2836,7 @@ bits_image_fetch_separable_convolution_affine (pixman_image_t * image, sgtot = CLIP (sgtot, 0, 0xff); sbtot = CLIP (sbtot, 0, 0xff); -#ifdef WORDS_BIGENDIAN - buffer[k] = (satot << 0) | (srtot << 8) | (sgtot << 16) | (sbtot << 24); -#else buffer[k] = (satot << 24) | (srtot << 16) | (sgtot << 8) | (sbtot << 0); -#endif next: vx += ux; @@ -2848,7 +2844,7 @@ bits_image_fetch_separable_convolution_affine (pixman_image_t * image, } } -static const uint8_t zero[8] = { 0, 0, 0, 0, 0, 0, 0, 0 }; +static const uint32_t zero[2] = { 0, 0 }; static force_inline void bits_image_fetch_bilinear_affine (pixman_image_t * image, @@ -2948,7 +2944,7 @@ bits_image_fetch_bilinear_affine (pixman_image_t * image, if (y2 == 0) { - row1 = zero; + row1 = (const uint8_t *)zero; mask1 = 0; } else @@ -2961,7 +2957,7 @@ bits_image_fetch_bilinear_affine (pixman_image_t * image, if (y1 == height - 1) { - row2 = zero; + row2 = (const uint8_t *)zero; mask2 = 0; } else diff --git a/gfx/cairo/libpixman/src/pixman-filter.c b/gfx/cairo/libpixman/src/pixman-filter.c index 5f3b752f9b..33327df83a 100644 --- a/gfx/cairo/libpixman/src/pixman-filter.c +++ b/gfx/cairo/libpixman/src/pixman-filter.c @@ -29,7 +29,7 @@ #include <math.h> #include <assert.h> #ifdef HAVE_CONFIG_H -#include <config.h> +#include <pixman-config.h> #endif #include "pixman-private.h" @@ -237,11 +237,14 @@ create_1d_filter (int width, pixman_kernel_t sample, double scale, int n_phases, - pixman_fixed_t *p) + pixman_fixed_t *pstart, + pixman_fixed_t *pend + ) { + pixman_fixed_t *p = pstart; double step; int i; - + if(width <= 0) return; step = 1.0 / n_phases; for (i = 0; i < n_phases; ++i) @@ -258,7 +261,7 @@ create_1d_filter (int width, x1 = ceil (frac - width / 2.0 - 0.5); x2 = x1 + width; - + assert( p >= pstart && p + (x2 - x1) <= pend ); /* assert validity of the following loop */ total = 0; for (x = x1; x < x2; ++x) { @@ -287,8 +290,10 @@ create_1d_filter (int width, /* Normalize, with error diffusion */ p -= width; - total = 65536.0 / total; - new_total = 0; + assert(p >= pstart && p + (x2 - x1) <= pend); /* assert validity of the following loop */ + + total = 65536.0 / total; + new_total = 0; e = 0.0; for (x = x1; x < x2; ++x) { @@ -304,6 +309,8 @@ create_1d_filter (int width, * at the first sample, since that is the only one that * hasn't had any error diffused into it. */ + + assert(p - width >= pstart && p - width < pend); /* assert... */ *(p - width) += pixman_fixed_1 - new_total; } } @@ -465,10 +472,16 @@ pixman_filter_create_separable_convolution (int *n_values, params[2] = pixman_int_to_fixed (subsample_bits_x); params[3] = pixman_int_to_fixed (subsample_bits_y); - create_1d_filter (width, reconstruct_x, sample_x, sx, subsample_x, - params + 4); - create_1d_filter (height, reconstruct_y, sample_y, sy, subsample_y, - params + 4 + width * subsample_x); + { + pixman_fixed_t + *xparams = params+4, + *yparams = xparams + width*subsample_x, + *endparams = params + *n_values; + create_1d_filter(width, reconstruct_x, sample_x, sx, subsample_x, + xparams, yparams); + create_1d_filter(height, reconstruct_y, sample_y, sy, subsample_y, + yparams, endparams); + } #ifdef PIXMAN_GNUPLOT gnuplot_filter(width, subsample_x, params + 4); diff --git a/gfx/cairo/libpixman/src/pixman-general.c b/gfx/cairo/libpixman/src/pixman-general.c index 7e5a0d09cc..b4450cbec9 100644 --- a/gfx/cairo/libpixman/src/pixman-general.c +++ b/gfx/cairo/libpixman/src/pixman-general.c @@ -26,7 +26,7 @@ * SOFTWARE. */ #ifdef HAVE_CONFIG_H -#include <config.h> +#include <pixman-config.h> #endif #include <stdlib.h> #include <string.h> diff --git a/gfx/cairo/libpixman/src/pixman-glyph.c b/gfx/cairo/libpixman/src/pixman-glyph.c index 96a349ab47..dc9041180e 100644 --- a/gfx/cairo/libpixman/src/pixman-glyph.c +++ b/gfx/cairo/libpixman/src/pixman-glyph.c @@ -25,7 +25,7 @@ */ #ifdef HAVE_CONFIG_H -#include <config.h> +#include <pixman-config.h> #endif #include "pixman-private.h" diff --git a/gfx/cairo/libpixman/src/pixman-gradient-walker.c b/gfx/cairo/libpixman/src/pixman-gradient-walker.c index fb7f401dac..b31d5ad7a9 100644 --- a/gfx/cairo/libpixman/src/pixman-gradient-walker.c +++ b/gfx/cairo/libpixman/src/pixman-gradient-walker.c @@ -24,7 +24,7 @@ */ #ifdef HAVE_CONFIG_H -#include <config.h> +#include <pixman-config.h> #endif #include "pixman-private.h" diff --git a/gfx/cairo/libpixman/src/pixman-image.c b/gfx/cairo/libpixman/src/pixman-image.c index db29ff5b4f..72796fc9c9 100644 --- a/gfx/cairo/libpixman/src/pixman-image.c +++ b/gfx/cairo/libpixman/src/pixman-image.c @@ -21,7 +21,7 @@ */ #ifdef HAVE_CONFIG_H -#include <config.h> +#include <pixman-config.h> #endif #include <stdlib.h> @@ -567,7 +567,7 @@ _pixman_image_validate (pixman_image_t *image) PIXMAN_EXPORT pixman_bool_t pixman_image_set_clip_region32 (pixman_image_t * image, - pixman_region32_t *region) + const pixman_region32_t *region) { image_common_t *common = (image_common_t *)image; pixman_bool_t result; @@ -591,7 +591,7 @@ pixman_image_set_clip_region32 (pixman_image_t * image, PIXMAN_EXPORT pixman_bool_t pixman_image_set_clip_region (pixman_image_t * image, - pixman_region16_t *region) + const pixman_region16_t *region) { image_common_t *common = (image_common_t *)image; pixman_bool_t result; diff --git a/gfx/cairo/libpixman/src/pixman-implementation.c b/gfx/cairo/libpixman/src/pixman-implementation.c index 5a2cbfead5..69fa70bc38 100644 --- a/gfx/cairo/libpixman/src/pixman-implementation.c +++ b/gfx/cairo/libpixman/src/pixman-implementation.c @@ -22,7 +22,7 @@ */ #ifdef HAVE_CONFIG_H -#include <config.h> +#include <pixman-config.h> #endif #include <stdlib.h> #include "pixman-private.h" diff --git a/gfx/cairo/libpixman/src/pixman-linear-gradient.c b/gfx/cairo/libpixman/src/pixman-linear-gradient.c index 3f528508a1..014b69ceb0 100644 --- a/gfx/cairo/libpixman/src/pixman-linear-gradient.c +++ b/gfx/cairo/libpixman/src/pixman-linear-gradient.c @@ -26,7 +26,7 @@ */ #ifdef HAVE_CONFIG_H -#include <config.h> +#include <pixman-config.h> #endif #include <stdlib.h> #include "pixman-private.h" diff --git a/gfx/cairo/libpixman/src/pixman-matrix.c b/gfx/cairo/libpixman/src/pixman-matrix.c index 81b6e613ed..da5209cbee 100644 --- a/gfx/cairo/libpixman/src/pixman-matrix.c +++ b/gfx/cairo/libpixman/src/pixman-matrix.c @@ -25,7 +25,7 @@ */ #ifdef HAVE_CONFIG_H -#include <config.h> +#include <pixman-config.h> #endif #include <math.h> diff --git a/gfx/cairo/libpixman/src/pixman-mips-dspr2.c b/gfx/cairo/libpixman/src/pixman-mips-dspr2.c index 87969ae704..c43eb1e897 100644 --- a/gfx/cairo/libpixman/src/pixman-mips-dspr2.c +++ b/gfx/cairo/libpixman/src/pixman-mips-dspr2.c @@ -30,7 +30,7 @@ */ #ifdef HAVE_CONFIG_H -#include <config.h> +#include <pixman-config.h> #endif #include "pixman-private.h" diff --git a/gfx/cairo/libpixman/src/pixman-mips.c b/gfx/cairo/libpixman/src/pixman-mips.c index 304881383b..7479a08848 100644 --- a/gfx/cairo/libpixman/src/pixman-mips.c +++ b/gfx/cairo/libpixman/src/pixman-mips.c @@ -20,7 +20,7 @@ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ #ifdef HAVE_CONFIG_H -#include <config.h> +#include <pixman-config.h> #endif #include "pixman-private.h" diff --git a/gfx/cairo/libpixman/src/pixman-mmx.c b/gfx/cairo/libpixman/src/pixman-mmx.c index 80c3ad42a5..05d5f86bb5 100644 --- a/gfx/cairo/libpixman/src/pixman-mmx.c +++ b/gfx/cairo/libpixman/src/pixman-mmx.c @@ -30,7 +30,7 @@ */ #ifdef HAVE_CONFIG_H -#include <config.h> +#include <pixman-config.h> #endif #if defined USE_X86_MMX || defined USE_ARM_IWMMXT || defined USE_LOONGSON_MMI @@ -60,7 +60,7 @@ _mm_empty (void) #endif #ifdef USE_X86_MMX -# if (defined(__SUNPRO_C) || defined(_MSC_VER) || defined(_WIN64)) || defined(__MINGW32__) +# if (defined(__SSE2__) || defined(__SUNPRO_C) || defined(_MSC_VER) || defined(_WIN64)) # include <xmmintrin.h> # else /* We have to compile with -msse to use xmmintrin.h, but that causes SSE @@ -103,7 +103,7 @@ _mm_mulhi_pu16 (__m64 __A, __m64 __B) # endif #endif -#ifndef _MSC_VER +#ifndef _MM_SHUFFLE #define _MM_SHUFFLE(fp3,fp2,fp1,fp0) \ (((fp3) << 6) | ((fp2) << 4) | ((fp1) << 2) | (fp0)) #endif diff --git a/gfx/cairo/libpixman/src/pixman-noop.c b/gfx/cairo/libpixman/src/pixman-noop.c index e59890492f..e43199bc18 100644 --- a/gfx/cairo/libpixman/src/pixman-noop.c +++ b/gfx/cairo/libpixman/src/pixman-noop.c @@ -22,7 +22,7 @@ * DEALINGS IN THE SOFTWARE. */ #ifdef HAVE_CONFIG_H -#include <config.h> +#include <pixman-config.h> #endif #include <string.h> #include <stdlib.h> diff --git a/gfx/cairo/libpixman/src/pixman-ppc.c b/gfx/cairo/libpixman/src/pixman-ppc.c index 4d5506d25d..926eb445fa 100644 --- a/gfx/cairo/libpixman/src/pixman-ppc.c +++ b/gfx/cairo/libpixman/src/pixman-ppc.c @@ -20,7 +20,7 @@ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ #ifdef HAVE_CONFIG_H -#include <config.h> +#include <pixman-config.h> #endif #include "pixman-private.h" diff --git a/gfx/cairo/libpixman/src/pixman-private.h b/gfx/cairo/libpixman/src/pixman-private.h index 0adf9fa067..9db21f792d 100644 --- a/gfx/cairo/libpixman/src/pixman-private.h +++ b/gfx/cairo/libpixman/src/pixman-private.h @@ -865,11 +865,11 @@ pixman_contract_from_float (uint32_t *dst, /* Region Helpers */ pixman_bool_t pixman_region32_copy_from_region16 (pixman_region32_t *dst, - pixman_region16_t *src); + const pixman_region16_t *src); pixman_bool_t pixman_region16_copy_from_region32 (pixman_region16_t *dst, - pixman_region32_t *src); + const pixman_region32_t *src); /* Doubly linked lists */ typedef struct pixman_link_t pixman_link_t; @@ -1059,28 +1059,9 @@ float pixman_unorm_to_float (uint16_t u, int n_bits); * Various debugging code */ -#undef DEBUG - #define COMPILE_TIME_ASSERT(x) \ do { typedef int compile_time_assertion [(x)?1:-1]; } while (0) -/* Turn on debugging depending on what type of release this is - */ -#if (((PIXMAN_VERSION_MICRO % 2) == 0) && ((PIXMAN_VERSION_MINOR % 2) == 1)) - -/* Debugging gets turned on for development releases because these - * are the things that end up in bleeding edge distributions such - * as Rawhide etc. - * - * For performance reasons we don't turn it on for stable releases or - * random git checkouts. (Random git checkouts are often used for - * performance work). - */ - -# define DEBUG - -#endif - void _pixman_log_error (const char *function, const char *message); diff --git a/gfx/cairo/libpixman/src/pixman-radial-gradient.c b/gfx/cairo/libpixman/src/pixman-radial-gradient.c index e8e99c98b9..38e1052f32 100644 --- a/gfx/cairo/libpixman/src/pixman-radial-gradient.c +++ b/gfx/cairo/libpixman/src/pixman-radial-gradient.c @@ -28,7 +28,7 @@ */ #ifdef HAVE_CONFIG_H -#include <config.h> +#include <pixman-config.h> #endif #include <stdlib.h> #include <math.h> diff --git a/gfx/cairo/libpixman/src/pixman-region.c b/gfx/cairo/libpixman/src/pixman-region.c index a2daa279fa..537d5fbe46 100644 --- a/gfx/cairo/libpixman/src/pixman-region.c +++ b/gfx/cairo/libpixman/src/pixman-region.c @@ -2387,6 +2387,14 @@ PREFIX (_contains_point) (const region_type_t * region, } PIXMAN_EXPORT int +PREFIX (_empty) (const region_type_t * region) +{ + GOOD (region); + + return(PIXREGION_NIL (region)); +} + +PIXMAN_EXPORT int PREFIX (_not_empty) (const region_type_t * region) { GOOD (region); diff --git a/gfx/cairo/libpixman/src/pixman-region16.c b/gfx/cairo/libpixman/src/pixman-region16.c index d88d3380f8..da4719e7a8 100644 --- a/gfx/cairo/libpixman/src/pixman-region16.c +++ b/gfx/cairo/libpixman/src/pixman-region16.c @@ -23,7 +23,7 @@ * Author: Soren Sandmann <sandmann@redhat.com> */ #ifdef HAVE_CONFIG_H -#include <config.h> +#include <pixman-config.h> #endif #undef PIXMAN_DISABLE_DEPRECATED diff --git a/gfx/cairo/libpixman/src/pixman-region32.c b/gfx/cairo/libpixman/src/pixman-region32.c index abd6b1a937..68b456bf3c 100644 --- a/gfx/cairo/libpixman/src/pixman-region32.c +++ b/gfx/cairo/libpixman/src/pixman-region32.c @@ -23,7 +23,7 @@ * Author: Soren Sandmann <sandmann@redhat.com> */ #ifdef HAVE_CONFIG_H -#include <config.h> +#include <pixman-config.h> #endif #include "pixman-private.h" diff --git a/gfx/cairo/libpixman/src/pixman-solid-fill.c b/gfx/cairo/libpixman/src/pixman-solid-fill.c index 4694ebc700..44f4de07a8 100644 --- a/gfx/cairo/libpixman/src/pixman-solid-fill.c +++ b/gfx/cairo/libpixman/src/pixman-solid-fill.c @@ -22,7 +22,7 @@ */ #ifdef HAVE_CONFIG_H -#include <config.h> +#include <pixman-config.h> #endif #include "pixman-private.h" diff --git a/gfx/cairo/libpixman/src/pixman-sse2.c b/gfx/cairo/libpixman/src/pixman-sse2.c index ce4e75f247..9c9cff2450 100644 --- a/gfx/cairo/libpixman/src/pixman-sse2.c +++ b/gfx/cairo/libpixman/src/pixman-sse2.c @@ -27,7 +27,7 @@ * Based on work by Owen Taylor and Søren Sandmann */ #ifdef HAVE_CONFIG_H -#include <config.h> +#include <pixman-config.h> #endif /* PSHUFD is slow on a lot of old processors, and new processors have SSSE3 */ @@ -373,16 +373,6 @@ load_128_unaligned (const __m128i* src) return _mm_loadu_si128 (src); } -/* save 4 pixels using Write Combining memory on a 16-byte - * boundary aligned address - */ -static force_inline void -save_128_write_combining (__m128i* dst, - __m128i data) -{ - _mm_stream_si128 (dst, data); -} - /* save 4 pixels on a 16-byte boundary aligned address */ static force_inline void save_128_aligned (__m128i* dst, @@ -391,14 +381,6 @@ save_128_aligned (__m128i* dst, _mm_store_si128 (dst, data); } -/* save 4 pixels on a unaligned address */ -static force_inline void -save_128_unaligned (__m128i* dst, - __m128i data) -{ - _mm_storeu_si128 (dst, data); -} - static force_inline __m128i load_32_1x128 (uint32_t data) { diff --git a/gfx/cairo/libpixman/src/pixman-ssse3.c b/gfx/cairo/libpixman/src/pixman-ssse3.c index 680d6b95a0..0359895af9 100644 --- a/gfx/cairo/libpixman/src/pixman-ssse3.c +++ b/gfx/cairo/libpixman/src/pixman-ssse3.c @@ -24,7 +24,7 @@ * Author: Soren Sandmann (soren.sandmann@gmail.com) */ #ifdef HAVE_CONFIG_H -#include <config.h> +#include <pixman-config.h> #endif #include <stdlib.h> diff --git a/gfx/cairo/libpixman/src/pixman-timer.c b/gfx/cairo/libpixman/src/pixman-timer.c index f5ae18e89f..656d900175 100644 --- a/gfx/cairo/libpixman/src/pixman-timer.c +++ b/gfx/cairo/libpixman/src/pixman-timer.c @@ -20,7 +20,7 @@ */ #ifdef HAVE_CONFIG_H -#include <config.h> +#include <pixman-config.h> #endif #include <stdlib.h> diff --git a/gfx/cairo/libpixman/src/pixman-trap.c b/gfx/cairo/libpixman/src/pixman-trap.c index 7560405ee2..0ec73dc652 100644 --- a/gfx/cairo/libpixman/src/pixman-trap.c +++ b/gfx/cairo/libpixman/src/pixman-trap.c @@ -22,7 +22,7 @@ */ #ifdef HAVE_CONFIG_H -#include <config.h> +#include <pixman-config.h> #endif #include <stdio.h> diff --git a/gfx/cairo/libpixman/src/pixman-utils.c b/gfx/cairo/libpixman/src/pixman-utils.c index 2c2dddd64c..302cd0c290 100644 --- a/gfx/cairo/libpixman/src/pixman-utils.c +++ b/gfx/cairo/libpixman/src/pixman-utils.c @@ -23,7 +23,7 @@ */ #ifdef HAVE_CONFIG_H -#include <config.h> +#include <pixman-config.h> #endif #include <stdio.h> #include <stdlib.h> @@ -238,7 +238,7 @@ _pixman_iter_init_bits_stride (pixman_iter_t *iter, const pixman_iter_info_t *in pixman_bool_t pixman_region16_copy_from_region32 (pixman_region16_t *dst, - pixman_region32_t *src) + const pixman_region32_t *src) { int n_boxes, i; pixman_box32_t *boxes32; @@ -268,7 +268,7 @@ pixman_region16_copy_from_region32 (pixman_region16_t *dst, pixman_bool_t pixman_region32_copy_from_region16 (pixman_region32_t *dst, - pixman_region16_t *src) + const pixman_region16_t *src) { int n_boxes, i; pixman_box16_t *boxes16; diff --git a/gfx/cairo/libpixman/src/pixman-version.h b/gfx/cairo/libpixman/src/pixman-version.h index 0f39bf3400..e523db9838 100644 --- a/gfx/cairo/libpixman/src/pixman-version.h +++ b/gfx/cairo/libpixman/src/pixman-version.h @@ -32,10 +32,10 @@ #endif #define PIXMAN_VERSION_MAJOR 0 -#define PIXMAN_VERSION_MINOR 42 -#define PIXMAN_VERSION_MICRO 2 +#define PIXMAN_VERSION_MINOR 43 +#define PIXMAN_VERSION_MICRO 4 -#define PIXMAN_VERSION_STRING "0.42.2" +#define PIXMAN_VERSION_STRING "0.43.4" #define PIXMAN_VERSION_ENCODE(major, minor, micro) ( \ ((major) * 10000) \ diff --git a/gfx/cairo/libpixman/src/pixman-vmx.c b/gfx/cairo/libpixman/src/pixman-vmx.c index 52de37e69e..d4b5dc8e11 100644 --- a/gfx/cairo/libpixman/src/pixman-vmx.c +++ b/gfx/cairo/libpixman/src/pixman-vmx.c @@ -26,7 +26,7 @@ */ #ifdef HAVE_CONFIG_H -#include <config.h> +#include <pixman-config.h> #endif #include "pixman-private.h" #include "pixman-combine32.h" @@ -279,20 +279,9 @@ save_128_aligned (uint32_t* data, } static force_inline vector unsigned int -create_mask_1x32_128 (const uint32_t *src) -{ - vector unsigned int vsrc; - DECLARE_SRC_MASK_VAR; - - COMPUTE_SHIFT_MASK (src); - LOAD_VECTOR (src); - return vec_splat(vsrc, 0); -} - -static force_inline vector unsigned int create_mask_32_128 (uint32_t mask) { - return create_mask_1x32_128(&mask); + return (vector unsigned int) {mask, mask, mask, mask}; } static force_inline vector unsigned int @@ -2471,7 +2460,7 @@ vmx_fill (pixman_implementation_t *imp, return FALSE; } - vfiller = create_mask_1x32_128(&filler); + vfiller = create_mask_32_128(filler); while (height--) { @@ -2913,32 +2902,26 @@ scaled_nearest_scanline_vmx_8888_8888_OVER (uint32_t* pd, while (w >= 4) { - vector unsigned int tmp; - uint32_t tmp1, tmp2, tmp3, tmp4; + uint32_t tmp[4]; - tmp1 = *(ps + pixman_fixed_to_int (vx)); + tmp[0] = *(ps + pixman_fixed_to_int (vx)); vx += unit_x; while (vx >= 0) vx -= src_width_fixed; - tmp2 = *(ps + pixman_fixed_to_int (vx)); + tmp[1] = *(ps + pixman_fixed_to_int (vx)); vx += unit_x; while (vx >= 0) vx -= src_width_fixed; - tmp3 = *(ps + pixman_fixed_to_int (vx)); + tmp[2] = *(ps + pixman_fixed_to_int (vx)); vx += unit_x; while (vx >= 0) vx -= src_width_fixed; - tmp4 = *(ps + pixman_fixed_to_int (vx)); + tmp[3] = *(ps + pixman_fixed_to_int (vx)); vx += unit_x; while (vx >= 0) vx -= src_width_fixed; - tmp[0] = tmp1; - tmp[1] = tmp2; - tmp[2] = tmp3; - tmp[3] = tmp4; - - vsrc = combine4 ((const uint32_t *) &tmp, pm); + vsrc = combine4 (tmp, pm); if (is_opaque (vsrc)) { diff --git a/gfx/cairo/libpixman/src/pixman-x86.c b/gfx/cairo/libpixman/src/pixman-x86.c index 2c702e5c3b..d3c04385fc 100644 --- a/gfx/cairo/libpixman/src/pixman-x86.c +++ b/gfx/cairo/libpixman/src/pixman-x86.c @@ -20,7 +20,7 @@ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ #ifdef HAVE_CONFIG_H -#include <config.h> +#include <pixman-config.h> #endif #include "pixman-private.h" @@ -74,40 +74,9 @@ detect_cpu_features (void) #else -#define _PIXMAN_X86_64 \ - (defined(__amd64__) || defined(__x86_64__) || defined(_M_AMD64)) - -static pixman_bool_t -have_cpuid (void) -{ -#if _PIXMAN_X86_64 || defined (_MSC_VER) - - return TRUE; - -#elif defined (__GNUC__) - uint32_t result; - - __asm__ volatile ( - "pushf" "\n\t" - "pop %%eax" "\n\t" - "mov %%eax, %%ecx" "\n\t" - "xor $0x00200000, %%eax" "\n\t" - "push %%eax" "\n\t" - "popf" "\n\t" - "pushf" "\n\t" - "pop %%eax" "\n\t" - "xor %%ecx, %%eax" "\n\t" - "mov %%eax, %0" "\n\t" - : "=r" (result) - : - : "%eax", "%ecx"); - - return !!result; - -#else -#error "Unknown compiler" +#if defined (__GNUC__) +#include <cpuid.h> #endif -} #ifdef _MSC_VER #include <intrin.h> /* for __cpuid */ @@ -118,29 +87,8 @@ pixman_cpuid (uint32_t feature, uint32_t *a, uint32_t *b, uint32_t *c, uint32_t *d) { #if defined (__GNUC__) - -#if _PIXMAN_X86_64 - __asm__ volatile ( - "cpuid" "\n\t" - : "=a" (*a), "=b" (*b), "=c" (*c), "=d" (*d) - : "a" (feature)); -#else - /* On x86-32 we need to be careful about the handling of %ebx - * and %esp. We can't declare either one as clobbered - * since they are special registers (%ebx is the "PIC - * register" holding an offset to global data, %esp the - * stack pointer), so we need to make sure that %ebx is - * preserved, and that %esp has its original value when - * accessing the output operands. - */ - __asm__ volatile ( - "xchg %%ebx, %1" "\n\t" - "cpuid" "\n\t" - "xchg %%ebx, %1" "\n\t" - : "=a" (*a), "=r" (*b), "=c" (*c), "=d" (*d) - : "a" (feature)); -#endif - + *a = *b = *c = *d = 0; + __get_cpuid(feature, a, b, c, d); #elif defined (_MSC_VER) int info[4]; @@ -161,9 +109,6 @@ detect_cpu_features (void) uint32_t a, b, c, d; cpu_features_t features = 0; - if (!have_cpuid()) - return features; - /* Get feature bits */ pixman_cpuid (0x01, &a, &b, &c, &d); if (d & (1 << 15)) diff --git a/gfx/cairo/libpixman/src/pixman.c b/gfx/cairo/libpixman/src/pixman.c index c09b528083..82ec236a6f 100644 --- a/gfx/cairo/libpixman/src/pixman.c +++ b/gfx/cairo/libpixman/src/pixman.c @@ -24,7 +24,7 @@ */ #ifdef HAVE_CONFIG_H -#include <config.h> +#include <pixman-config.h> #endif #include "pixman-private.h" @@ -182,7 +182,7 @@ clip_general_image (pixman_region32_t * region, return FALSE; } } - else if (!pixman_region32_not_empty (clip)) + else if (pixman_region32_empty (clip)) { return FALSE; } @@ -277,7 +277,7 @@ _pixman_compute_composite_region32 (pixman_region32_t * region, { return FALSE; } - if (!pixman_region32_not_empty (region)) + if (pixman_region32_empty (region)) return FALSE; if (dest_image->common.alpha_map->common.have_clip_region) { @@ -1020,6 +1020,7 @@ pixman_format_supported_source (pixman_format_code_t format) case PIXMAN_x2r10g10b10: case PIXMAN_a8r8g8b8: case PIXMAN_a8r8g8b8_sRGB: + case PIXMAN_r8g8b8_sRGB: case PIXMAN_x8r8g8b8: case PIXMAN_a8b8g8r8: case PIXMAN_x8b8g8r8: diff --git a/gfx/cairo/libpixman/src/pixman.h b/gfx/cairo/libpixman/src/pixman.h index 858955554a..a5c51934ca 100644 --- a/gfx/cairo/libpixman/src/pixman.h +++ b/gfx/cairo/libpixman/src/pixman.h @@ -586,6 +586,9 @@ pixman_region_overlap_t pixman_region_contains_rectangle (const pixman_region16_ const pixman_box16_t *prect); PIXMAN_API +pixman_bool_t pixman_region_empty (const pixman_region16_t *region); + +PIXMAN_API pixman_bool_t pixman_region_not_empty (const pixman_region16_t *region); PIXMAN_API @@ -727,6 +730,9 @@ pixman_region_overlap_t pixman_region32_contains_rectangle (const pixman_region3 const pixman_box32_t *prect); PIXMAN_API +pixman_bool_t pixman_region32_empty (const pixman_region32_t *region); + +PIXMAN_API pixman_bool_t pixman_region32_not_empty (const pixman_region32_t *region); PIXMAN_API @@ -895,6 +901,7 @@ typedef enum { /* sRGB formats */ PIXMAN_a8r8g8b8_sRGB = PIXMAN_FORMAT(32,PIXMAN_TYPE_ARGB_SRGB,8,8,8,8), + PIXMAN_r8g8b8_sRGB = PIXMAN_FORMAT(24,PIXMAN_TYPE_ARGB_SRGB,0,8,8,8), /* 24bpp formats */ PIXMAN_r8g8b8 = PIXMAN_FORMAT(24,PIXMAN_TYPE_ARGB,0,8,8,8), @@ -1012,11 +1019,11 @@ void * pixman_image_get_destroy_data (pixman_image_t *image); /* Set properties */ PIXMAN_API pixman_bool_t pixman_image_set_clip_region (pixman_image_t *image, - pixman_region16_t *region); + const pixman_region16_t *region); PIXMAN_API pixman_bool_t pixman_image_set_clip_region32 (pixman_image_t *image, - pixman_region32_t *region); + const pixman_region32_t *region); PIXMAN_API void pixman_image_set_has_client_clip (pixman_image_t *image, diff --git a/gfx/cairo/pixman-arm32-clang.patch b/gfx/cairo/pixman-arm32-clang.patch deleted file mode 100644 index cd9d61e470..0000000000 --- a/gfx/cairo/pixman-arm32-clang.patch +++ /dev/null @@ -1,5205 +0,0 @@ -https://gitlab.freedesktop.org/pixman/pixman/-/issues/74 - -diff --git a/gfx/cairo/libpixman/src/pixman-arm-neon-asm-bilinear.S b/gfx/cairo/libpixman/src/pixman-arm-neon-asm-bilinear.S ---- a/gfx/cairo/libpixman/src/pixman-arm-neon-asm-bilinear.S -+++ b/gfx/cairo/libpixman/src/pixman-arm-neon-asm-bilinear.S -@@ -77,206 +77,206 @@ - * format conversion, and interpolation as separate macros which can be used - * as the basic building blocks for constructing bilinear scanline functions. - */ - - .macro bilinear_load_8888 reg1, reg2, tmp - mov TMP1, X, asr #16 - add X, X, UX - add TMP1, TOP, TMP1, asl #2 -- vld1.32 {reg1}, [TMP1], STRIDE -- vld1.32 {reg2}, [TMP1] -+ vld1.32 {\reg1}, [TMP1], STRIDE -+ vld1.32 {\reg2}, [TMP1] - .endm - - .macro bilinear_load_0565 reg1, reg2, tmp - mov TMP1, X, asr #16 - add X, X, UX - add TMP1, TOP, TMP1, asl #1 -- vld1.32 {reg2[0]}, [TMP1], STRIDE -- vld1.32 {reg2[1]}, [TMP1] -- convert_four_0565_to_x888_packed reg2, reg1, reg2, tmp -+ vld1.32 {\reg2[0]}, [TMP1], STRIDE -+ vld1.32 {\reg2[1]}, [TMP1] -+ convert_four_0565_to_x888_packed \reg2, \reg1, \reg2, \tmp - .endm - - .macro bilinear_load_and_vertical_interpolate_two_8888 \ - acc1, acc2, reg1, reg2, reg3, reg4, tmp1, tmp2 - -- bilinear_load_8888 reg1, reg2, tmp1 -- vmull.u8 acc1, reg1, d28 -- vmlal.u8 acc1, reg2, d29 -- bilinear_load_8888 reg3, reg4, tmp2 -- vmull.u8 acc2, reg3, d28 -- vmlal.u8 acc2, reg4, d29 -+ bilinear_load_8888 \reg1, \reg2, \tmp1 -+ vmull.u8 \acc1, \reg1, d28 -+ vmlal.u8 \acc1, \reg2, d29 -+ bilinear_load_8888 \reg3, \reg4, \tmp2 -+ vmull.u8 \acc2, \reg3, d28 -+ vmlal.u8 \acc2, \reg4, d29 - .endm - - .macro bilinear_load_and_vertical_interpolate_four_8888 \ - xacc1, xacc2, xreg1, xreg2, xreg3, xreg4, xacc2lo, xacc2hi \ - yacc1, yacc2, yreg1, yreg2, yreg3, yreg4, yacc2lo, yacc2hi - - bilinear_load_and_vertical_interpolate_two_8888 \ -- xacc1, xacc2, xreg1, xreg2, xreg3, xreg4, xacc2lo, xacc2hi -+ \xacc1, \xacc2, \xreg1, \xreg2, \xreg3, \xreg4, \xacc2lo, \xacc2hi - bilinear_load_and_vertical_interpolate_two_8888 \ -- yacc1, yacc2, yreg1, yreg2, yreg3, yreg4, yacc2lo, yacc2hi -+ \yacc1, \yacc2, \yreg1, \yreg2, \yreg3, \yreg4, \yacc2lo, \yacc2hi - .endm - - .macro bilinear_load_and_vertical_interpolate_two_0565 \ - acc1, acc2, reg1, reg2, reg3, reg4, acc2lo, acc2hi - - mov TMP1, X, asr #16 - add X, X, UX - add TMP1, TOP, TMP1, asl #1 - mov TMP2, X, asr #16 - add X, X, UX - add TMP2, TOP, TMP2, asl #1 -- vld1.32 {acc2lo[0]}, [TMP1], STRIDE -- vld1.32 {acc2hi[0]}, [TMP2], STRIDE -- vld1.32 {acc2lo[1]}, [TMP1] -- vld1.32 {acc2hi[1]}, [TMP2] -- convert_0565_to_x888 acc2, reg3, reg2, reg1 -- vzip.u8 reg1, reg3 -- vzip.u8 reg2, reg4 -- vzip.u8 reg3, reg4 -- vzip.u8 reg1, reg2 -- vmull.u8 acc1, reg1, d28 -- vmlal.u8 acc1, reg2, d29 -- vmull.u8 acc2, reg3, d28 -- vmlal.u8 acc2, reg4, d29 -+ vld1.32 {\acc2lo[0]}, [TMP1], STRIDE -+ vld1.32 {\acc2hi[0]}, [TMP2], STRIDE -+ vld1.32 {\acc2lo[1]}, [TMP1] -+ vld1.32 {\acc2hi[1]}, [TMP2] -+ convert_0565_to_x888 \acc2, \reg3, \reg2, \reg1 -+ vzip.u8 \reg1, \reg3 -+ vzip.u8 \reg2, \reg4 -+ vzip.u8 \reg3, \reg4 -+ vzip.u8 \reg1, \reg2 -+ vmull.u8 \acc1, \reg1, d28 -+ vmlal.u8 \acc1, \reg2, d29 -+ vmull.u8 \acc2, \reg3, d28 -+ vmlal.u8 \acc2, \reg4, d29 - .endm - - .macro bilinear_load_and_vertical_interpolate_four_0565 \ - xacc1, xacc2, xreg1, xreg2, xreg3, xreg4, xacc2lo, xacc2hi \ - yacc1, yacc2, yreg1, yreg2, yreg3, yreg4, yacc2lo, yacc2hi - - mov TMP1, X, asr #16 - add X, X, UX - add TMP1, TOP, TMP1, asl #1 - mov TMP2, X, asr #16 - add X, X, UX - add TMP2, TOP, TMP2, asl #1 -- vld1.32 {xacc2lo[0]}, [TMP1], STRIDE -- vld1.32 {xacc2hi[0]}, [TMP2], STRIDE -- vld1.32 {xacc2lo[1]}, [TMP1] -- vld1.32 {xacc2hi[1]}, [TMP2] -- convert_0565_to_x888 xacc2, xreg3, xreg2, xreg1 -+ vld1.32 {\xacc2lo[0]}, [TMP1], STRIDE -+ vld1.32 {\xacc2hi[0]}, [TMP2], STRIDE -+ vld1.32 {\xacc2lo[1]}, [TMP1] -+ vld1.32 {\xacc2hi[1]}, [TMP2] -+ convert_0565_to_x888 \xacc2, \xreg3, \xreg2, \xreg1 - mov TMP1, X, asr #16 - add X, X, UX - add TMP1, TOP, TMP1, asl #1 - mov TMP2, X, asr #16 - add X, X, UX - add TMP2, TOP, TMP2, asl #1 -- vld1.32 {yacc2lo[0]}, [TMP1], STRIDE -- vzip.u8 xreg1, xreg3 -- vld1.32 {yacc2hi[0]}, [TMP2], STRIDE -- vzip.u8 xreg2, xreg4 -- vld1.32 {yacc2lo[1]}, [TMP1] -- vzip.u8 xreg3, xreg4 -- vld1.32 {yacc2hi[1]}, [TMP2] -- vzip.u8 xreg1, xreg2 -- convert_0565_to_x888 yacc2, yreg3, yreg2, yreg1 -- vmull.u8 xacc1, xreg1, d28 -- vzip.u8 yreg1, yreg3 -- vmlal.u8 xacc1, xreg2, d29 -- vzip.u8 yreg2, yreg4 -- vmull.u8 xacc2, xreg3, d28 -- vzip.u8 yreg3, yreg4 -- vmlal.u8 xacc2, xreg4, d29 -- vzip.u8 yreg1, yreg2 -- vmull.u8 yacc1, yreg1, d28 -- vmlal.u8 yacc1, yreg2, d29 -- vmull.u8 yacc2, yreg3, d28 -- vmlal.u8 yacc2, yreg4, d29 -+ vld1.32 {\yacc2lo[0]}, [TMP1], STRIDE -+ vzip.u8 \xreg1, \xreg3 -+ vld1.32 {\yacc2hi[0]}, [TMP2], STRIDE -+ vzip.u8 \xreg2, \xreg4 -+ vld1.32 {\yacc2lo[1]}, [TMP1] -+ vzip.u8 \xreg3, \xreg4 -+ vld1.32 {\yacc2hi[1]}, [TMP2] -+ vzip.u8 \xreg1, \xreg2 -+ convert_0565_to_x888 \yacc2, \yreg3, \yreg2, \yreg1 -+ vmull.u8 \xacc1, \xreg1, d28 -+ vzip.u8 \yreg1, \yreg3 -+ vmlal.u8 \xacc1, \xreg2, d29 -+ vzip.u8 \yreg2, \yreg4 -+ vmull.u8 \xacc2, \xreg3, d28 -+ vzip.u8 \yreg3, \yreg4 -+ vmlal.u8 \xacc2, \xreg4, d29 -+ vzip.u8 \yreg1, \yreg2 -+ vmull.u8 \yacc1, \yreg1, d28 -+ vmlal.u8 \yacc1, \yreg2, d29 -+ vmull.u8 \yacc2, \yreg3, d28 -+ vmlal.u8 \yacc2, \yreg4, d29 - .endm - - .macro bilinear_store_8888 numpix, tmp1, tmp2 --.if numpix == 4 -+.if \numpix == 4 - vst1.32 {d0, d1}, [OUT]! --.elseif numpix == 2 -+.elseif \numpix == 2 - vst1.32 {d0}, [OUT]! --.elseif numpix == 1 -+.elseif \numpix == 1 - vst1.32 {d0[0]}, [OUT, :32]! - .else - .error bilinear_store_8888 numpix is unsupported - .endif - .endm - - .macro bilinear_store_0565 numpix, tmp1, tmp2 - vuzp.u8 d0, d1 - vuzp.u8 d2, d3 - vuzp.u8 d1, d3 - vuzp.u8 d0, d2 -- convert_8888_to_0565 d2, d1, d0, q1, tmp1, tmp2 --.if numpix == 4 -+ convert_8888_to_0565 d2, d1, d0, q1, \tmp1, \tmp2 -+.if \numpix == 4 - vst1.16 {d2}, [OUT]! --.elseif numpix == 2 -+.elseif \numpix == 2 - vst1.32 {d2[0]}, [OUT]! --.elseif numpix == 1 -+.elseif \numpix == 1 - vst1.16 {d2[0]}, [OUT]! - .else - .error bilinear_store_0565 numpix is unsupported - .endif - .endm - - - /* - * Macros for loading mask pixels into register 'mask'. - * vdup must be done in somewhere else. - */ - .macro bilinear_load_mask_x numpix, mask - .endm - - .macro bilinear_load_mask_8 numpix, mask --.if numpix == 4 -- vld1.32 {mask[0]}, [MASK]! --.elseif numpix == 2 -- vld1.16 {mask[0]}, [MASK]! --.elseif numpix == 1 -- vld1.8 {mask[0]}, [MASK]! -+.if \numpix == 4 -+ vld1.32 {\mask[0]}, [MASK]! -+.elseif \numpix == 2 -+ vld1.16 {\mask[0]}, [MASK]! -+.elseif \numpix == 1 -+ vld1.8 {\mask[0]}, [MASK]! - .else -- .error bilinear_load_mask_8 numpix is unsupported -+ .error bilinear_load_mask_8 \numpix is unsupported - .endif - pld [MASK, #prefetch_offset] - .endm - - .macro bilinear_load_mask mask_fmt, numpix, mask -- bilinear_load_mask_&mask_fmt numpix, mask -+ bilinear_load_mask_\()\mask_fmt \numpix, \mask - .endm - - - /* - * Macros for loading destination pixels into register 'dst0' and 'dst1'. - * Interleave should be done somewhere else. - */ - .macro bilinear_load_dst_0565_src numpix, dst0, dst1, dst01 - .endm - - .macro bilinear_load_dst_8888_src numpix, dst0, dst1, dst01 - .endm - - .macro bilinear_load_dst_8888 numpix, dst0, dst1, dst01 --.if numpix == 4 -- vld1.32 {dst0, dst1}, [OUT] --.elseif numpix == 2 -- vld1.32 {dst0}, [OUT] --.elseif numpix == 1 -- vld1.32 {dst0[0]}, [OUT] -+.if \numpix == 4 -+ vld1.32 {\dst0, \dst1}, [OUT] -+.elseif \numpix == 2 -+ vld1.32 {\dst0}, [OUT] -+.elseif \numpix == 1 -+ vld1.32 {\dst0[0]}, [OUT] - .else -- .error bilinear_load_dst_8888 numpix is unsupported -+ .error bilinear_load_dst_8888 \numpix is unsupported - .endif - pld [OUT, #(prefetch_offset * 4)] - .endm - - .macro bilinear_load_dst_8888_over numpix, dst0, dst1, dst01 -- bilinear_load_dst_8888 numpix, dst0, dst1, dst01 -+ bilinear_load_dst_8888 \numpix, \dst0, \dst1, \dst01 - .endm - - .macro bilinear_load_dst_8888_add numpix, dst0, dst1, dst01 -- bilinear_load_dst_8888 numpix, dst0, dst1, dst01 -+ bilinear_load_dst_8888 \numpix, \dst0, \dst1, \dst01 - .endm - - .macro bilinear_load_dst dst_fmt, op, numpix, dst0, dst1, dst01 -- bilinear_load_dst_&dst_fmt&_&op numpix, dst0, dst1, dst01 -+ bilinear_load_dst_\()\dst_fmt\()_\()\op \numpix, \dst0, \dst1, \dst01 - .endm - - /* - * Macros for duplicating partially loaded mask to fill entire register. - * We will apply mask to interleaved source pixels, that is - * (r0, r1, r2, r3, g0, g1, g2, g3) x (m0, m1, m2, m3, m0, m1, m2, m3) - * (b0, b1, b2, b3, a0, a1, a2, a3) x (m0, m1, m2, m3, m0, m1, m2, m3) - * So, we need to duplicate loaded mask into whole register. -@@ -285,79 +285,79 @@ - * (r0, r1, x, x, g0, g1, x, x) x (m0, m1, m0, m1, m0, m1, m0, m1) - * (b0, b1, x, x, a0, a1, x, x) x (m0, m1, m0, m1, m0, m1, m0, m1) - * We can do some optimizations for this including last pixel cases. - */ - .macro bilinear_duplicate_mask_x numpix, mask - .endm - - .macro bilinear_duplicate_mask_8 numpix, mask --.if numpix == 4 -- vdup.32 mask, mask[0] --.elseif numpix == 2 -- vdup.16 mask, mask[0] --.elseif numpix == 1 -- vdup.8 mask, mask[0] -+.if \numpix == 4 -+ vdup.32 \mask, \mask[0] -+.elseif \numpix == 2 -+ vdup.16 \mask, \mask[0] -+.elseif \numpix == 1 -+ vdup.8 \mask, \mask[0] - .else - .error bilinear_duplicate_mask_8 is unsupported - .endif - .endm - - .macro bilinear_duplicate_mask mask_fmt, numpix, mask -- bilinear_duplicate_mask_&mask_fmt numpix, mask -+ bilinear_duplicate_mask_\()\mask_fmt \numpix, \mask - .endm - - /* - * Macros for interleaving src and dst pixels to rrrr gggg bbbb aaaa form. - * Interleave should be done when maks is enabled or operator is 'over'. - */ - .macro bilinear_interleave src0, src1, dst0, dst1 -- vuzp.8 src0, src1 -- vuzp.8 dst0, dst1 -- vuzp.8 src0, src1 -- vuzp.8 dst0, dst1 -+ vuzp.8 \src0, \src1 -+ vuzp.8 \dst0, \dst1 -+ vuzp.8 \src0, \src1 -+ vuzp.8 \dst0, \dst1 - .endm - - .macro bilinear_interleave_src_dst_x_src \ - numpix, src0, src1, src01, dst0, dst1, dst01 - .endm - - .macro bilinear_interleave_src_dst_x_over \ - numpix, src0, src1, src01, dst0, dst1, dst01 - -- bilinear_interleave src0, src1, dst0, dst1 -+ bilinear_interleave \src0, \src1, \dst0, \dst1 - .endm - - .macro bilinear_interleave_src_dst_x_add \ - numpix, src0, src1, src01, dst0, dst1, dst01 - .endm - - .macro bilinear_interleave_src_dst_8_src \ - numpix, src0, src1, src01, dst0, dst1, dst01 - -- bilinear_interleave src0, src1, dst0, dst1 -+ bilinear_interleave \src0, \src1, \dst0, \dst1 - .endm - - .macro bilinear_interleave_src_dst_8_over \ - numpix, src0, src1, src01, dst0, dst1, dst01 - -- bilinear_interleave src0, src1, dst0, dst1 -+ bilinear_interleave \src0, \src1, \dst0, \dst1 - .endm - - .macro bilinear_interleave_src_dst_8_add \ - numpix, src0, src1, src01, dst0, dst1, dst01 - -- bilinear_interleave src0, src1, dst0, dst1 -+ bilinear_interleave \src0, \src1, \dst0, \dst1 - .endm - - .macro bilinear_interleave_src_dst \ - mask_fmt, op, numpix, src0, src1, src01, dst0, dst1, dst01 - -- bilinear_interleave_src_dst_&mask_fmt&_&op \ -- numpix, src0, src1, src01, dst0, dst1, dst01 -+ bilinear_interleave_src_dst_\()\mask_fmt\()_\()\op \ -+ \numpix, \src0, \src1, \src01, \dst0, \dst1, \dst01 - .endm - - - /* - * Macros for applying masks to src pixels. (see combine_mask_u() function) - * src, dst should be in interleaved form. - * mask register should be in form (m0, m1, m2, m3). - */ -@@ -365,217 +365,217 @@ - numpix, src0, src1, src01, mask, \ - tmp01, tmp23, tmp45, tmp67 - .endm - - .macro bilinear_apply_mask_to_src_8 \ - numpix, src0, src1, src01, mask, \ - tmp01, tmp23, tmp45, tmp67 - -- vmull.u8 tmp01, src0, mask -- vmull.u8 tmp23, src1, mask -+ vmull.u8 \tmp01, \src0, \mask -+ vmull.u8 \tmp23, \src1, \mask - /* bubbles */ -- vrshr.u16 tmp45, tmp01, #8 -- vrshr.u16 tmp67, tmp23, #8 -+ vrshr.u16 \tmp45, \tmp01, #8 -+ vrshr.u16 \tmp67, \tmp23, #8 - /* bubbles */ -- vraddhn.u16 src0, tmp45, tmp01 -- vraddhn.u16 src1, tmp67, tmp23 -+ vraddhn.u16 \src0, \tmp45, \tmp01 -+ vraddhn.u16 \src1, \tmp67, \tmp23 - .endm - - .macro bilinear_apply_mask_to_src \ - mask_fmt, numpix, src0, src1, src01, mask, \ - tmp01, tmp23, tmp45, tmp67 - -- bilinear_apply_mask_to_src_&mask_fmt \ -- numpix, src0, src1, src01, mask, \ -- tmp01, tmp23, tmp45, tmp67 -+ bilinear_apply_mask_to_src_\()\mask_fmt \ -+ \numpix, \src0, \src1, \src01, \mask, \ -+ \tmp01, \tmp23, \tmp45, \tmp67 - .endm - - - /* - * Macros for combining src and destination pixels. - * Interleave or not is depending on operator 'op'. - */ - .macro bilinear_combine_src \ - numpix, src0, src1, src01, dst0, dst1, dst01, \ - tmp01, tmp23, tmp45, tmp67, tmp8 - .endm - - .macro bilinear_combine_over \ - numpix, src0, src1, src01, dst0, dst1, dst01, \ - tmp01, tmp23, tmp45, tmp67, tmp8 - -- vdup.32 tmp8, src1[1] -+ vdup.32 \tmp8, \src1[1] - /* bubbles */ -- vmvn.8 tmp8, tmp8 -+ vmvn.8 \tmp8, \tmp8 - /* bubbles */ -- vmull.u8 tmp01, dst0, tmp8 -+ vmull.u8 \tmp01, \dst0, \tmp8 - /* bubbles */ -- vmull.u8 tmp23, dst1, tmp8 -+ vmull.u8 \tmp23, \dst1, \tmp8 - /* bubbles */ -- vrshr.u16 tmp45, tmp01, #8 -- vrshr.u16 tmp67, tmp23, #8 -+ vrshr.u16 \tmp45, \tmp01, #8 -+ vrshr.u16 \tmp67, \tmp23, #8 - /* bubbles */ -- vraddhn.u16 dst0, tmp45, tmp01 -- vraddhn.u16 dst1, tmp67, tmp23 -+ vraddhn.u16 \dst0, \tmp45, \tmp01 -+ vraddhn.u16 \dst1, \tmp67, \tmp23 - /* bubbles */ -- vqadd.u8 src01, dst01, src01 -+ vqadd.u8 \src01, \dst01, \src01 - .endm - - .macro bilinear_combine_add \ - numpix, src0, src1, src01, dst0, dst1, dst01, \ - tmp01, tmp23, tmp45, tmp67, tmp8 - -- vqadd.u8 src01, dst01, src01 -+ vqadd.u8 \src01, \dst01, \src01 - .endm - - .macro bilinear_combine \ - op, numpix, src0, src1, src01, dst0, dst1, dst01, \ - tmp01, tmp23, tmp45, tmp67, tmp8 - -- bilinear_combine_&op \ -- numpix, src0, src1, src01, dst0, dst1, dst01, \ -- tmp01, tmp23, tmp45, tmp67, tmp8 -+ bilinear_combine_\()\op \ -+ \numpix, \src0, \src1, \src01, \dst0, \dst1, \dst01, \ -+ \tmp01, \tmp23, \tmp45, \tmp67, \tmp8 - .endm - - /* - * Macros for final deinterleaving of destination pixels if needed. - */ - .macro bilinear_deinterleave numpix, dst0, dst1, dst01 -- vuzp.8 dst0, dst1 -+ vuzp.8 \dst0, \dst1 - /* bubbles */ -- vuzp.8 dst0, dst1 -+ vuzp.8 \dst0, \dst1 - .endm - - .macro bilinear_deinterleave_dst_x_src numpix, dst0, dst1, dst01 - .endm - - .macro bilinear_deinterleave_dst_x_over numpix, dst0, dst1, dst01 -- bilinear_deinterleave numpix, dst0, dst1, dst01 -+ bilinear_deinterleave \numpix, \dst0, \dst1, \dst01 - .endm - - .macro bilinear_deinterleave_dst_x_add numpix, dst0, dst1, dst01 - .endm - - .macro bilinear_deinterleave_dst_8_src numpix, dst0, dst1, dst01 -- bilinear_deinterleave numpix, dst0, dst1, dst01 -+ bilinear_deinterleave \numpix, \dst0, \dst1, \dst01 - .endm - - .macro bilinear_deinterleave_dst_8_over numpix, dst0, dst1, dst01 -- bilinear_deinterleave numpix, dst0, dst1, dst01 -+ bilinear_deinterleave \numpix, \dst0, \dst1, \dst01 - .endm - - .macro bilinear_deinterleave_dst_8_add numpix, dst0, dst1, dst01 -- bilinear_deinterleave numpix, dst0, dst1, dst01 -+ bilinear_deinterleave \numpix, \dst0, \dst1, \dst01 - .endm - - .macro bilinear_deinterleave_dst mask_fmt, op, numpix, dst0, dst1, dst01 -- bilinear_deinterleave_dst_&mask_fmt&_&op numpix, dst0, dst1, dst01 -+ bilinear_deinterleave_dst_\()\mask_fmt\()_\()\op \numpix, \dst0, \dst1, \dst01 - .endm - - - .macro bilinear_interpolate_last_pixel src_fmt, mask_fmt, dst_fmt, op -- bilinear_load_&src_fmt d0, d1, d2 -- bilinear_load_mask mask_fmt, 1, d4 -- bilinear_load_dst dst_fmt, op, 1, d18, d19, q9 -+ bilinear_load_\()\src_fmt d0, d1, d2 -+ bilinear_load_mask \mask_fmt, 1, d4 -+ bilinear_load_dst \dst_fmt, \op, 1, d18, d19, q9 - vmull.u8 q1, d0, d28 - vmlal.u8 q1, d1, d29 - /* 5 cycles bubble */ - vshll.u16 q0, d2, #BILINEAR_INTERPOLATION_BITS - vmlsl.u16 q0, d2, d30 - vmlal.u16 q0, d3, d30 - /* 5 cycles bubble */ -- bilinear_duplicate_mask mask_fmt, 1, d4 -+ bilinear_duplicate_mask \mask_fmt, 1, d4 - vshrn.u32 d0, q0, #(2 * BILINEAR_INTERPOLATION_BITS) - /* 3 cycles bubble */ - vmovn.u16 d0, q0 - /* 1 cycle bubble */ - bilinear_interleave_src_dst \ -- mask_fmt, op, 1, d0, d1, q0, d18, d19, q9 -+ \mask_fmt, \op, 1, d0, d1, q0, d18, d19, q9 - bilinear_apply_mask_to_src \ -- mask_fmt, 1, d0, d1, q0, d4, \ -+ \mask_fmt, 1, d0, d1, q0, d4, \ - q3, q8, q10, q11 - bilinear_combine \ -- op, 1, d0, d1, q0, d18, d19, q9, \ -+ \op, 1, d0, d1, q0, d18, d19, q9, \ - q3, q8, q10, q11, d5 -- bilinear_deinterleave_dst mask_fmt, op, 1, d0, d1, q0 -- bilinear_store_&dst_fmt 1, q2, q3 -+ bilinear_deinterleave_dst \mask_fmt, \op, 1, d0, d1, q0 -+ bilinear_store_\()\dst_fmt 1, q2, q3 - .endm - - .macro bilinear_interpolate_two_pixels src_fmt, mask_fmt, dst_fmt, op -- bilinear_load_and_vertical_interpolate_two_&src_fmt \ -+ bilinear_load_and_vertical_interpolate_two_\()\src_fmt \ - q1, q11, d0, d1, d20, d21, d22, d23 -- bilinear_load_mask mask_fmt, 2, d4 -- bilinear_load_dst dst_fmt, op, 2, d18, d19, q9 -+ bilinear_load_mask \mask_fmt, 2, d4 -+ bilinear_load_dst \dst_fmt, \op, 2, d18, d19, q9 - vshll.u16 q0, d2, #BILINEAR_INTERPOLATION_BITS - vmlsl.u16 q0, d2, d30 - vmlal.u16 q0, d3, d30 - vshll.u16 q10, d22, #BILINEAR_INTERPOLATION_BITS - vmlsl.u16 q10, d22, d31 - vmlal.u16 q10, d23, d31 - vshrn.u32 d0, q0, #(2 * BILINEAR_INTERPOLATION_BITS) - vshrn.u32 d1, q10, #(2 * BILINEAR_INTERPOLATION_BITS) -- bilinear_duplicate_mask mask_fmt, 2, d4 -+ bilinear_duplicate_mask \mask_fmt, 2, d4 - vshr.u16 q15, q12, #(16 - BILINEAR_INTERPOLATION_BITS) - vadd.u16 q12, q12, q13 - vmovn.u16 d0, q0 - bilinear_interleave_src_dst \ -- mask_fmt, op, 2, d0, d1, q0, d18, d19, q9 -+ \mask_fmt, \op, 2, d0, d1, q0, d18, d19, q9 - bilinear_apply_mask_to_src \ -- mask_fmt, 2, d0, d1, q0, d4, \ -+ \mask_fmt, 2, d0, d1, q0, d4, \ - q3, q8, q10, q11 - bilinear_combine \ -- op, 2, d0, d1, q0, d18, d19, q9, \ -+ \op, 2, d0, d1, q0, d18, d19, q9, \ - q3, q8, q10, q11, d5 -- bilinear_deinterleave_dst mask_fmt, op, 2, d0, d1, q0 -- bilinear_store_&dst_fmt 2, q2, q3 -+ bilinear_deinterleave_dst \mask_fmt, \op, 2, d0, d1, q0 -+ bilinear_store_\()\dst_fmt 2, q2, q3 - .endm - - .macro bilinear_interpolate_four_pixels src_fmt, mask_fmt, dst_fmt, op -- bilinear_load_and_vertical_interpolate_four_&src_fmt \ -+ bilinear_load_and_vertical_interpolate_four_\()\src_fmt \ - q1, q11, d0, d1, d20, d21, d22, d23 \ - q3, q9, d4, d5, d16, d17, d18, d19 - pld [TMP1, PF_OFFS] - sub TMP1, TMP1, STRIDE - vshll.u16 q0, d2, #BILINEAR_INTERPOLATION_BITS - vmlsl.u16 q0, d2, d30 - vmlal.u16 q0, d3, d30 - vshll.u16 q10, d22, #BILINEAR_INTERPOLATION_BITS - vmlsl.u16 q10, d22, d31 - vmlal.u16 q10, d23, d31 - vshr.u16 q15, q12, #(16 - BILINEAR_INTERPOLATION_BITS) - vshll.u16 q2, d6, #BILINEAR_INTERPOLATION_BITS - vmlsl.u16 q2, d6, d30 - vmlal.u16 q2, d7, d30 - vshll.u16 q8, d18, #BILINEAR_INTERPOLATION_BITS -- bilinear_load_mask mask_fmt, 4, d22 -- bilinear_load_dst dst_fmt, op, 4, d2, d3, q1 -+ bilinear_load_mask \mask_fmt, 4, d22 -+ bilinear_load_dst \dst_fmt, \op, 4, d2, d3, q1 - pld [TMP1, PF_OFFS] - vmlsl.u16 q8, d18, d31 - vmlal.u16 q8, d19, d31 - vadd.u16 q12, q12, q13 - vshrn.u32 d0, q0, #(2 * BILINEAR_INTERPOLATION_BITS) - vshrn.u32 d1, q10, #(2 * BILINEAR_INTERPOLATION_BITS) - vshrn.u32 d4, q2, #(2 * BILINEAR_INTERPOLATION_BITS) - vshrn.u32 d5, q8, #(2 * BILINEAR_INTERPOLATION_BITS) -- bilinear_duplicate_mask mask_fmt, 4, d22 -+ bilinear_duplicate_mask \mask_fmt, 4, d22 - vshr.u16 q15, q12, #(16 - BILINEAR_INTERPOLATION_BITS) - vmovn.u16 d0, q0 - vmovn.u16 d1, q2 - vadd.u16 q12, q12, q13 - bilinear_interleave_src_dst \ -- mask_fmt, op, 4, d0, d1, q0, d2, d3, q1 -+ \mask_fmt, \op, 4, d0, d1, q0, d2, d3, q1 - bilinear_apply_mask_to_src \ -- mask_fmt, 4, d0, d1, q0, d22, \ -+ \mask_fmt, 4, d0, d1, q0, d22, \ - q3, q8, q9, q10 - bilinear_combine \ -- op, 4, d0, d1, q0, d2, d3, q1, \ -+ \op, 4, d0, d1, q0, d2, d3, q1, \ - q3, q8, q9, q10, d23 -- bilinear_deinterleave_dst mask_fmt, op, 4, d0, d1, q0 -- bilinear_store_&dst_fmt 4, q2, q3 -+ bilinear_deinterleave_dst \mask_fmt, \op, 4, d0, d1, q0 -+ bilinear_store_\()\dst_fmt 4, q2, q3 - .endm - - .set BILINEAR_FLAG_USE_MASK, 1 - .set BILINEAR_FLAG_USE_ALL_NEON_REGS, 2 - - /* - * Main template macro for generating NEON optimized bilinear scanline functions. - * -@@ -605,24 +605,24 @@ - bilinear_process_four_pixels, \ - bilinear_process_pixblock_head, \ - bilinear_process_pixblock_tail, \ - bilinear_process_pixblock_tail_head, \ - pixblock_size, \ - prefetch_distance, \ - flags - --pixman_asm_function fname --.if pixblock_size == 8 --.elseif pixblock_size == 4 -+pixman_asm_function \fname -+.if \pixblock_size == 8 -+.elseif \pixblock_size == 4 - .else - .error unsupported pixblock size - .endif - --.if ((flags) & BILINEAR_FLAG_USE_MASK) == 0 -+.if ((\flags) & BILINEAR_FLAG_USE_MASK) == 0 - OUT .req r0 - TOP .req r1 - BOTTOM .req r2 - WT .req r3 - WB .req r4 - X .req r5 - UX .req r6 - WIDTH .req ip -@@ -630,17 +630,17 @@ pixman_asm_function fname - TMP2 .req r4 - PF_OFFS .req r7 - TMP3 .req r8 - TMP4 .req r9 - STRIDE .req r2 - - mov ip, sp - push {r4, r5, r6, r7, r8, r9} -- mov PF_OFFS, #prefetch_distance -+ mov PF_OFFS, #\prefetch_distance - ldmia ip, {WB, X, UX, WIDTH} - .else - OUT .req r0 - MASK .req r1 - TOP .req r2 - BOTTOM .req r3 - WT .req r4 - WB .req r5 -@@ -649,27 +649,27 @@ pixman_asm_function fname - WIDTH .req ip - TMP1 .req r4 - TMP2 .req r5 - PF_OFFS .req r8 - TMP3 .req r9 - TMP4 .req r10 - STRIDE .req r3 - -- .set prefetch_offset, prefetch_distance -+ .set prefetch_offset, \prefetch_distance - - mov ip, sp - push {r4, r5, r6, r7, r8, r9, r10, ip} -- mov PF_OFFS, #prefetch_distance -+ mov PF_OFFS, #\prefetch_distance - ldmia ip, {WT, WB, X, UX, WIDTH} - .endif - - mul PF_OFFS, PF_OFFS, UX - --.if ((flags) & BILINEAR_FLAG_USE_ALL_NEON_REGS) != 0 -+.if ((\flags) & BILINEAR_FLAG_USE_ALL_NEON_REGS) != 0 - vpush {d8-d15} - .endif - - sub STRIDE, BOTTOM, TOP - .unreq BOTTOM - - cmp WIDTH, #0 - ble 3f -@@ -678,76 +678,76 @@ pixman_asm_function fname - vdup.u16 q13, UX - vdup.u8 d28, WT - vdup.u8 d29, WB - vadd.u16 d25, d25, d26 - - /* ensure good destination alignment */ - cmp WIDTH, #1 - blt 0f -- tst OUT, #(1 << dst_bpp_shift) -+ tst OUT, #(1 << \dst_bpp_shift) - beq 0f - vshr.u16 q15, q12, #(16 - BILINEAR_INTERPOLATION_BITS) - vadd.u16 q12, q12, q13 -- bilinear_process_last_pixel -+ \bilinear_process_last_pixel - sub WIDTH, WIDTH, #1 - 0: - vadd.u16 q13, q13, q13 - vshr.u16 q15, q12, #(16 - BILINEAR_INTERPOLATION_BITS) - vadd.u16 q12, q12, q13 - - cmp WIDTH, #2 - blt 0f -- tst OUT, #(1 << (dst_bpp_shift + 1)) -+ tst OUT, #(1 << (\dst_bpp_shift + 1)) - beq 0f -- bilinear_process_two_pixels -+ \bilinear_process_two_pixels - sub WIDTH, WIDTH, #2 - 0: --.if pixblock_size == 8 -+.if \pixblock_size == 8 - cmp WIDTH, #4 - blt 0f -- tst OUT, #(1 << (dst_bpp_shift + 2)) -+ tst OUT, #(1 << (\dst_bpp_shift + 2)) - beq 0f -- bilinear_process_four_pixels -+ \bilinear_process_four_pixels - sub WIDTH, WIDTH, #4 - 0: - .endif -- subs WIDTH, WIDTH, #pixblock_size -+ subs WIDTH, WIDTH, #\pixblock_size - blt 1f -- mov PF_OFFS, PF_OFFS, asr #(16 - src_bpp_shift) -- bilinear_process_pixblock_head -- subs WIDTH, WIDTH, #pixblock_size -+ mov PF_OFFS, PF_OFFS, asr #(16 - \src_bpp_shift) -+ \bilinear_process_pixblock_head -+ subs WIDTH, WIDTH, #\pixblock_size - blt 5f - 0: -- bilinear_process_pixblock_tail_head -- subs WIDTH, WIDTH, #pixblock_size -+ \bilinear_process_pixblock_tail_head -+ subs WIDTH, WIDTH, #\pixblock_size - bge 0b - 5: -- bilinear_process_pixblock_tail -+ \bilinear_process_pixblock_tail - 1: --.if pixblock_size == 8 -+.if \pixblock_size == 8 - tst WIDTH, #4 - beq 2f -- bilinear_process_four_pixels -+ \bilinear_process_four_pixels - 2: - .endif - /* handle the remaining trailing pixels */ - tst WIDTH, #2 - beq 2f -- bilinear_process_two_pixels -+ \bilinear_process_two_pixels - 2: - tst WIDTH, #1 - beq 3f -- bilinear_process_last_pixel -+ \bilinear_process_last_pixel - 3: --.if ((flags) & BILINEAR_FLAG_USE_ALL_NEON_REGS) != 0 -+.if ((\flags) & BILINEAR_FLAG_USE_ALL_NEON_REGS) != 0 - vpop {d8-d15} - .endif - --.if ((flags) & BILINEAR_FLAG_USE_MASK) == 0 -+.if ((\flags) & BILINEAR_FLAG_USE_MASK) == 0 - pop {r4, r5, r6, r7, r8, r9} - .else - pop {r4, r5, r6, r7, r8, r9, r10, ip} - .endif - bx lr - - .unreq OUT - .unreq TOP -@@ -757,21 +757,21 @@ 3: - .unreq UX - .unreq WIDTH - .unreq TMP1 - .unreq TMP2 - .unreq PF_OFFS - .unreq TMP3 - .unreq TMP4 - .unreq STRIDE --.if ((flags) & BILINEAR_FLAG_USE_MASK) != 0 -+.if ((\flags) & BILINEAR_FLAG_USE_MASK) != 0 - .unreq MASK - .endif - --.endfunc -+pixman_end_asm_function - - .endm - - /* src_8888_8_8888 */ - .macro bilinear_src_8888_8_8888_process_last_pixel - bilinear_interpolate_last_pixel 8888, 8, 8888, src - .endm - -diff --git a/gfx/cairo/libpixman/src/pixman-arm-neon-asm.S b/gfx/cairo/libpixman/src/pixman-arm-neon-asm.S ---- a/gfx/cairo/libpixman/src/pixman-arm-neon-asm.S -+++ b/gfx/cairo/libpixman/src/pixman-arm-neon-asm.S -@@ -29,16 +29,22 @@ - * (those which are exposing some new or interesting features) are - * extensively commented and can be used as examples. - * - * You may want to have a look at the comments for following functions: - * - pixman_composite_over_8888_0565_asm_neon - * - pixman_composite_over_n_8_0565_asm_neon - */ - -+#ifdef __clang__ -+#define ldrgeb ldrbge -+#define subges subsge -+#define subpls subspl -+#endif -+ - /* Prevent the stack from becoming executable for no reason... */ - #if defined(__linux__) && defined(__ELF__) - .section .note.GNU-stack,"",%progbits - #endif - - .text - .fpu neon - .arch armv7a -@@ -255,43 +261,43 @@ - vqadd.u8 d16, d2, d20 - vld1.16 {d4, d5}, [DST_R, :128]! - vqadd.u8 q9, q0, q11 - vshrn.u16 d6, q2, #8 - fetch_src_pixblock - vshrn.u16 d7, q2, #3 - vsli.u16 q2, q2, #5 - vshll.u8 q14, d16, #8 -- PF add PF_X, PF_X, #8 -+ PF add, PF_X, PF_X, #8 - vshll.u8 q8, d19, #8 -- PF tst PF_CTL, #0xF -+ PF tst, PF_CTL, #0xF - vsri.u8 d6, d6, #5 -- PF addne PF_X, PF_X, #8 -+ PF addne, PF_X, PF_X, #8 - vmvn.8 d3, d3 -- PF subne PF_CTL, PF_CTL, #1 -+ PF subne, PF_CTL, PF_CTL, #1 - vsri.u8 d7, d7, #6 - vshrn.u16 d30, q2, #2 - vmull.u8 q10, d3, d6 - PF pld, [PF_SRC, PF_X, lsl #src_bpp_shift] - vmull.u8 q11, d3, d7 - vmull.u8 q12, d3, d30 - PF pld, [PF_DST, PF_X, lsl #dst_bpp_shift] - vsri.u16 q14, q8, #5 -- PF cmp PF_X, ORIG_W -+ PF cmp, PF_X, ORIG_W - vshll.u8 q9, d18, #8 - vrshr.u16 q13, q10, #8 -- PF subge PF_X, PF_X, ORIG_W -+ PF subge, PF_X, PF_X, ORIG_W - vrshr.u16 q3, q11, #8 - vrshr.u16 q15, q12, #8 -- PF subges PF_CTL, PF_CTL, #0x10 -+ PF subges, PF_CTL, PF_CTL, #0x10 - vsri.u16 q14, q9, #11 -- PF ldrgeb DUMMY, [PF_SRC, SRC_STRIDE, lsl #src_bpp_shift]! -+ PF ldrgeb, DUMMY, [PF_SRC, SRC_STRIDE, lsl #src_bpp_shift]! - vraddhn.u16 d20, q10, q13 - vraddhn.u16 d23, q11, q3 -- PF ldrgeb DUMMY, [PF_DST, DST_STRIDE, lsl #dst_bpp_shift]! -+ PF ldrgeb, DUMMY, [PF_DST, DST_STRIDE, lsl #dst_bpp_shift]! - vraddhn.u16 d22, q12, q15 - vst1.16 {d28, d29}, [DST_W, :128]! - .endm - - #else - - /* If we did not care much about the performance, we would just use this... */ - .macro pixman_composite_over_8888_0565_process_pixblock_tail_head -@@ -429,30 +435,30 @@ generate_composite_function \ - - .macro pixman_composite_src_8888_0565_process_pixblock_tail - vsri.u16 q14, q8, #5 - vsri.u16 q14, q9, #11 - .endm - - .macro pixman_composite_src_8888_0565_process_pixblock_tail_head - vsri.u16 q14, q8, #5 -- PF add PF_X, PF_X, #8 -- PF tst PF_CTL, #0xF -+ PF add, PF_X, PF_X, #8 -+ PF tst, PF_CTL, #0xF - fetch_src_pixblock -- PF addne PF_X, PF_X, #8 -- PF subne PF_CTL, PF_CTL, #1 -+ PF addne, PF_X, PF_X, #8 -+ PF subne, PF_CTL, PF_CTL, #1 - vsri.u16 q14, q9, #11 -- PF cmp PF_X, ORIG_W -+ PF cmp, PF_X, ORIG_W - PF pld, [PF_SRC, PF_X, lsl #src_bpp_shift] - vshll.u8 q8, d1, #8 - vst1.16 {d28, d29}, [DST_W, :128]! -- PF subge PF_X, PF_X, ORIG_W -- PF subges PF_CTL, PF_CTL, #0x10 -+ PF subge, PF_X, PF_X, ORIG_W -+ PF subges, PF_CTL, PF_CTL, #0x10 - vshll.u8 q14, d2, #8 -- PF ldrgeb DUMMY, [PF_SRC, SRC_STRIDE, lsl #src_bpp_shift]! -+ PF ldrgeb, DUMMY, [PF_SRC, SRC_STRIDE, lsl #src_bpp_shift]! - vshll.u8 q9, d0, #8 - .endm - - generate_composite_function \ - pixman_composite_src_8888_0565_asm_neon, 32, 0, 16, \ - FLAG_DST_WRITEONLY | FLAG_DEINTERLEAVE_32BPP, \ - 8, /* number of pixels, processed in a single block */ \ - 10, /* prefetch distance */ \ -@@ -504,30 +510,30 @@ generate_composite_function \ - vqadd.u8 q15, q1, q3 - .endm - - .macro pixman_composite_add_8_8_process_pixblock_tail - .endm - - .macro pixman_composite_add_8_8_process_pixblock_tail_head - fetch_src_pixblock -- PF add PF_X, PF_X, #32 -- PF tst PF_CTL, #0xF -+ PF add, PF_X, PF_X, #32 -+ PF tst, PF_CTL, #0xF - vld1.8 {d4, d5, d6, d7}, [DST_R, :128]! -- PF addne PF_X, PF_X, #32 -- PF subne PF_CTL, PF_CTL, #1 -+ PF addne, PF_X, PF_X, #32 -+ PF subne, PF_CTL, PF_CTL, #1 - vst1.8 {d28, d29, d30, d31}, [DST_W, :128]! -- PF cmp PF_X, ORIG_W -+ PF cmp, PF_X, ORIG_W - PF pld, [PF_SRC, PF_X, lsl #src_bpp_shift] - PF pld, [PF_DST, PF_X, lsl #dst_bpp_shift] -- PF subge PF_X, PF_X, ORIG_W -- PF subges PF_CTL, PF_CTL, #0x10 -+ PF subge, PF_X, PF_X, ORIG_W -+ PF subges, PF_CTL, PF_CTL, #0x10 - vqadd.u8 q14, q0, q2 -- PF ldrgeb DUMMY, [PF_SRC, SRC_STRIDE, lsl #src_bpp_shift]! -- PF ldrgeb DUMMY, [PF_DST, DST_STRIDE, lsl #dst_bpp_shift]! -+ PF ldrgeb, DUMMY, [PF_SRC, SRC_STRIDE, lsl #src_bpp_shift]! -+ PF ldrgeb, DUMMY, [PF_DST, DST_STRIDE, lsl #dst_bpp_shift]! - vqadd.u8 q15, q1, q3 - .endm - - generate_composite_function \ - pixman_composite_add_8_8_asm_neon, 8, 0, 8, \ - FLAG_DST_READWRITE, \ - 32, /* number of pixels, processed in a single block */ \ - 10, /* prefetch distance */ \ -@@ -536,30 +542,30 @@ generate_composite_function \ - pixman_composite_add_8_8_process_pixblock_head, \ - pixman_composite_add_8_8_process_pixblock_tail, \ - pixman_composite_add_8_8_process_pixblock_tail_head - - /******************************************************************************/ - - .macro pixman_composite_add_8888_8888_process_pixblock_tail_head - fetch_src_pixblock -- PF add PF_X, PF_X, #8 -- PF tst PF_CTL, #0xF -+ PF add, PF_X, PF_X, #8 -+ PF tst, PF_CTL, #0xF - vld1.32 {d4, d5, d6, d7}, [DST_R, :128]! -- PF addne PF_X, PF_X, #8 -- PF subne PF_CTL, PF_CTL, #1 -+ PF addne, PF_X, PF_X, #8 -+ PF subne, PF_CTL, PF_CTL, #1 - vst1.32 {d28, d29, d30, d31}, [DST_W, :128]! -- PF cmp PF_X, ORIG_W -+ PF cmp, PF_X, ORIG_W - PF pld, [PF_SRC, PF_X, lsl #src_bpp_shift] - PF pld, [PF_DST, PF_X, lsl #dst_bpp_shift] -- PF subge PF_X, PF_X, ORIG_W -- PF subges PF_CTL, PF_CTL, #0x10 -+ PF subge, PF_X, PF_X, ORIG_W -+ PF subges, PF_CTL, PF_CTL, #0x10 - vqadd.u8 q14, q0, q2 -- PF ldrgeb DUMMY, [PF_SRC, SRC_STRIDE, lsl #src_bpp_shift]! -- PF ldrgeb DUMMY, [PF_DST, DST_STRIDE, lsl #dst_bpp_shift]! -+ PF ldrgeb, DUMMY, [PF_SRC, SRC_STRIDE, lsl #src_bpp_shift]! -+ PF ldrgeb, DUMMY, [PF_DST, DST_STRIDE, lsl #dst_bpp_shift]! - vqadd.u8 q15, q1, q3 - .endm - - generate_composite_function \ - pixman_composite_add_8888_8888_asm_neon, 32, 0, 32, \ - FLAG_DST_READWRITE, \ - 8, /* number of pixels, processed in a single block */ \ - 10, /* prefetch distance */ \ -@@ -599,40 +605,40 @@ generate_composite_function_single_scanl - vraddhn.u16 d29, q15, q9 - vraddhn.u16 d30, q12, q10 - vraddhn.u16 d31, q13, q11 - .endm - - .macro pixman_composite_out_reverse_8888_8888_process_pixblock_tail_head - vld4.8 {d4, d5, d6, d7}, [DST_R, :128]! - vrshr.u16 q14, q8, #8 -- PF add PF_X, PF_X, #8 -- PF tst PF_CTL, #0xF -+ PF add, PF_X, PF_X, #8 -+ PF tst, PF_CTL, #0xF - vrshr.u16 q15, q9, #8 - vrshr.u16 q12, q10, #8 - vrshr.u16 q13, q11, #8 -- PF addne PF_X, PF_X, #8 -- PF subne PF_CTL, PF_CTL, #1 -+ PF addne, PF_X, PF_X, #8 -+ PF subne, PF_CTL, PF_CTL, #1 - vraddhn.u16 d28, q14, q8 - vraddhn.u16 d29, q15, q9 -- PF cmp PF_X, ORIG_W -+ PF cmp, PF_X, ORIG_W - vraddhn.u16 d30, q12, q10 - vraddhn.u16 d31, q13, q11 - fetch_src_pixblock - PF pld, [PF_SRC, PF_X, lsl #src_bpp_shift] - vmvn.8 d22, d3 - PF pld, [PF_DST, PF_X, lsl #dst_bpp_shift] - vst4.8 {d28, d29, d30, d31}, [DST_W, :128]! -- PF subge PF_X, PF_X, ORIG_W -+ PF subge, PF_X, PF_X, ORIG_W - vmull.u8 q8, d22, d4 -- PF subges PF_CTL, PF_CTL, #0x10 -+ PF subsge, PF_CTL, PF_CTL, #0x10 - vmull.u8 q9, d22, d5 -- PF ldrgeb DUMMY, [PF_SRC, SRC_STRIDE, lsl #src_bpp_shift]! -+ PF ldrgeb, DUMMY, [PF_SRC, SRC_STRIDE, lsl #src_bpp_shift]! - vmull.u8 q10, d22, d6 -- PF ldrgeb DUMMY, [PF_DST, DST_STRIDE, lsl #dst_bpp_shift]! -+ PF ldrgeb, DUMMY, [PF_DST, DST_STRIDE, lsl #dst_bpp_shift]! - vmull.u8 q11, d22, d7 - .endm - - generate_composite_function_single_scanline \ - pixman_composite_scanline_out_reverse_asm_neon, 32, 0, 32, \ - FLAG_DST_READWRITE | FLAG_DEINTERLEAVE_32BPP, \ - 8, /* number of pixels, processed in a single block */ \ - default_init, \ -@@ -651,42 +657,42 @@ generate_composite_function_single_scanl - pixman_composite_out_reverse_8888_8888_process_pixblock_tail - vqadd.u8 q14, q0, q14 - vqadd.u8 q15, q1, q15 - .endm - - .macro pixman_composite_over_8888_8888_process_pixblock_tail_head - vld4.8 {d4, d5, d6, d7}, [DST_R, :128]! - vrshr.u16 q14, q8, #8 -- PF add PF_X, PF_X, #8 -- PF tst PF_CTL, #0xF -+ PF add, PF_X, PF_X, #8 -+ PF tst, PF_CTL, #0xF - vrshr.u16 q15, q9, #8 - vrshr.u16 q12, q10, #8 - vrshr.u16 q13, q11, #8 -- PF addne PF_X, PF_X, #8 -- PF subne PF_CTL, PF_CTL, #1 -+ PF addne, PF_X, PF_X, #8 -+ PF subne, PF_CTL, PF_CTL, #1 - vraddhn.u16 d28, q14, q8 - vraddhn.u16 d29, q15, q9 -- PF cmp PF_X, ORIG_W -+ PF cmp, PF_X, ORIG_W - vraddhn.u16 d30, q12, q10 - vraddhn.u16 d31, q13, q11 - vqadd.u8 q14, q0, q14 - vqadd.u8 q15, q1, q15 - fetch_src_pixblock - PF pld, [PF_SRC, PF_X, lsl #src_bpp_shift] - vmvn.8 d22, d3 - PF pld, [PF_DST, PF_X, lsl #dst_bpp_shift] - vst4.8 {d28, d29, d30, d31}, [DST_W, :128]! -- PF subge PF_X, PF_X, ORIG_W -+ PF subge, PF_X, PF_X, ORIG_W - vmull.u8 q8, d22, d4 -- PF subges PF_CTL, PF_CTL, #0x10 -+ PF subges, PF_CTL, PF_CTL, #0x10 - vmull.u8 q9, d22, d5 -- PF ldrgeb DUMMY, [PF_SRC, SRC_STRIDE, lsl #src_bpp_shift]! -+ PF ldrgeb, DUMMY, [PF_SRC, SRC_STRIDE, lsl #src_bpp_shift]! - vmull.u8 q10, d22, d6 -- PF ldrgeb DUMMY, [PF_DST, DST_STRIDE, lsl #dst_bpp_shift]! -+ PF ldrgeb, DUMMY, [PF_DST, DST_STRIDE, lsl #dst_bpp_shift]! - vmull.u8 q11, d22, d7 - .endm - - generate_composite_function \ - pixman_composite_over_8888_8888_asm_neon, 32, 0, 32, \ - FLAG_DST_READWRITE | FLAG_DEINTERLEAVE_32BPP, \ - 8, /* number of pixels, processed in a single block */ \ - 5, /* prefetch distance */ \ -@@ -737,30 +743,30 @@ generate_composite_function_single_scanl - vrshr.u16 q2, q10, #8 - vrshr.u16 q3, q11, #8 - vraddhn.u16 d28, q14, q8 - vraddhn.u16 d29, q15, q9 - vraddhn.u16 d30, q2, q10 - vraddhn.u16 d31, q3, q11 - vld4.8 {d4, d5, d6, d7}, [DST_R, :128]! - vqadd.u8 q14, q0, q14 -- PF add PF_X, PF_X, #8 -- PF tst PF_CTL, #0x0F -- PF addne PF_X, PF_X, #8 -- PF subne PF_CTL, PF_CTL, #1 -+ PF add, PF_X, PF_X, #8 -+ PF tst, PF_CTL, #0x0F -+ PF addne, PF_X, PF_X, #8 -+ PF subne, PF_CTL, PF_CTL, #1 - vqadd.u8 q15, q1, q15 -- PF cmp PF_X, ORIG_W -+ PF cmp, PF_X, ORIG_W - vmull.u8 q8, d24, d4 - PF pld, [PF_DST, PF_X, lsl #dst_bpp_shift] - vmull.u8 q9, d24, d5 -- PF subge PF_X, PF_X, ORIG_W -+ PF subge, PF_X, PF_X, ORIG_W - vmull.u8 q10, d24, d6 -- PF subges PF_CTL, PF_CTL, #0x10 -+ PF subges, PF_CTL, PF_CTL, #0x10 - vmull.u8 q11, d24, d7 -- PF ldrgeb DUMMY, [PF_DST, DST_STRIDE, lsl #dst_bpp_shift]! -+ PF ldrgeb, DUMMY, [PF_DST, DST_STRIDE, lsl #dst_bpp_shift]! - vst4.8 {d28, d29, d30, d31}, [DST_W, :128]! - .endm - - .macro pixman_composite_over_n_8888_init - add DUMMY, sp, #ARGS_STACK_OFFSET - vld1.32 {d3[0]}, [DUMMY] - vdup.8 d0, d3[0] - vdup.8 d1, d3[1] -@@ -779,40 +785,40 @@ generate_composite_function \ - pixman_composite_over_8888_8888_process_pixblock_head, \ - pixman_composite_over_8888_8888_process_pixblock_tail, \ - pixman_composite_over_n_8888_process_pixblock_tail_head - - /******************************************************************************/ - - .macro pixman_composite_over_reverse_n_8888_process_pixblock_tail_head - vrshr.u16 q14, q8, #8 -- PF add PF_X, PF_X, #8 -- PF tst PF_CTL, #0xF -+ PF add, PF_X, PF_X, #8 -+ PF tst, PF_CTL, #0xF - vrshr.u16 q15, q9, #8 - vrshr.u16 q12, q10, #8 - vrshr.u16 q13, q11, #8 -- PF addne PF_X, PF_X, #8 -- PF subne PF_CTL, PF_CTL, #1 -+ PF addne, PF_X, PF_X, #8 -+ PF subne, PF_CTL, PF_CTL, #1 - vraddhn.u16 d28, q14, q8 - vraddhn.u16 d29, q15, q9 -- PF cmp PF_X, ORIG_W -+ PF cmp, PF_X, ORIG_W - vraddhn.u16 d30, q12, q10 - vraddhn.u16 d31, q13, q11 - vqadd.u8 q14, q0, q14 - vqadd.u8 q15, q1, q15 - vld4.8 {d0, d1, d2, d3}, [DST_R, :128]! - vmvn.8 d22, d3 - PF pld, [PF_DST, PF_X, lsl #dst_bpp_shift] - vst4.8 {d28, d29, d30, d31}, [DST_W, :128]! -- PF subge PF_X, PF_X, ORIG_W -+ PF subge, PF_X, PF_X, ORIG_W - vmull.u8 q8, d22, d4 -- PF subges PF_CTL, PF_CTL, #0x10 -+ PF subges, PF_CTL, PF_CTL, #0x10 - vmull.u8 q9, d22, d5 - vmull.u8 q10, d22, d6 -- PF ldrgeb DUMMY, [PF_DST, DST_STRIDE, lsl #dst_bpp_shift]! -+ PF ldrgeb, DUMMY, [PF_DST, DST_STRIDE, lsl #dst_bpp_shift]! - vmull.u8 q11, d22, d7 - .endm - - .macro pixman_composite_over_reverse_n_8888_init - add DUMMY, sp, #ARGS_STACK_OFFSET - vld1.32 {d7[0]}, [DUMMY] - vdup.8 d4, d7[0] - vdup.8 d5, d7[1] -@@ -1240,33 +1246,33 @@ generate_composite_function \ - vrshrn.u16 d28, q8, #8 - vrshrn.u16 d29, q9, #8 - vrshrn.u16 d30, q10, #8 - vrshrn.u16 d31, q11, #8 - .endm - - .macro pixman_composite_src_n_8_8888_process_pixblock_tail_head - fetch_mask_pixblock -- PF add PF_X, PF_X, #8 -+ PF add, PF_X, PF_X, #8 - vrshrn.u16 d28, q8, #8 -- PF tst PF_CTL, #0x0F -+ PF tst, PF_CTL, #0x0F - vrshrn.u16 d29, q9, #8 -- PF addne PF_X, PF_X, #8 -+ PF addne, PF_X, PF_X, #8 - vrshrn.u16 d30, q10, #8 -- PF subne PF_CTL, PF_CTL, #1 -+ PF subne, PF_CTL, PF_CTL, #1 - vrshrn.u16 d31, q11, #8 -- PF cmp PF_X, ORIG_W -+ PF cmp, PF_X, ORIG_W - vmull.u8 q8, d24, d0 - PF pld, [PF_MASK, PF_X, lsl #mask_bpp_shift] - vmull.u8 q9, d24, d1 -- PF subge PF_X, PF_X, ORIG_W -+ PF subge, PF_X, PF_X, ORIG_W - vmull.u8 q10, d24, d2 -- PF subges PF_CTL, PF_CTL, #0x10 -+ PF subges, PF_CTL, PF_CTL, #0x10 - vmull.u8 q11, d24, d3 -- PF ldrgeb DUMMY, [PF_MASK, MASK_STRIDE, lsl #mask_bpp_shift]! -+ PF ldrgeb, DUMMY, [PF_MASK, MASK_STRIDE, lsl #mask_bpp_shift]! - vst4.8 {d28, d29, d30, d31}, [DST_W, :128]! - vrsra.u16 q8, q8, #8 - vrsra.u16 q9, q9, #8 - vrsra.u16 q10, q10, #8 - vrsra.u16 q11, q11, #8 - .endm - - .macro pixman_composite_src_n_8_8888_init -@@ -1309,33 +1315,33 @@ generate_composite_function \ - vrshrn.u16 d28, q0, #8 - vrshrn.u16 d29, q1, #8 - vrshrn.u16 d30, q2, #8 - vrshrn.u16 d31, q3, #8 - .endm - - .macro pixman_composite_src_n_8_8_process_pixblock_tail_head - fetch_mask_pixblock -- PF add PF_X, PF_X, #8 -+ PF add, PF_X, PF_X, #8 - vrshrn.u16 d28, q0, #8 -- PF tst PF_CTL, #0x0F -+ PF tst, PF_CTL, #0x0F - vrshrn.u16 d29, q1, #8 -- PF addne PF_X, PF_X, #8 -+ PF addne, PF_X, PF_X, #8 - vrshrn.u16 d30, q2, #8 -- PF subne PF_CTL, PF_CTL, #1 -+ PF subne, PF_CTL, PF_CTL, #1 - vrshrn.u16 d31, q3, #8 -- PF cmp PF_X, ORIG_W -+ PF cmp, PF_X, ORIG_W - vmull.u8 q0, d24, d16 - PF pld, [PF_MASK, PF_X, lsl #mask_bpp_shift] - vmull.u8 q1, d25, d16 -- PF subge PF_X, PF_X, ORIG_W -+ PF subge, PF_X, PF_X, ORIG_W - vmull.u8 q2, d26, d16 -- PF subges PF_CTL, PF_CTL, #0x10 -+ PF subges, PF_CTL, PF_CTL, #0x10 - vmull.u8 q3, d27, d16 -- PF ldrgeb DUMMY, [PF_MASK, MASK_STRIDE, lsl #mask_bpp_shift]! -+ PF ldrgeb, DUMMY, [PF_MASK, MASK_STRIDE, lsl #mask_bpp_shift]! - vst1.8 {d28, d29, d30, d31}, [DST_W, :128]! - vrsra.u16 q0, q0, #8 - vrsra.u16 q1, q1, #8 - vrsra.u16 q2, q2, #8 - vrsra.u16 q3, q3, #8 - .endm - - .macro pixman_composite_src_n_8_8_init -@@ -1403,37 +1409,37 @@ generate_composite_function \ - .endm - - .macro pixman_composite_over_n_8_8888_process_pixblock_tail_head - vrshr.u16 q14, q8, #8 - vld4.8 {d4, d5, d6, d7}, [DST_R, :128]! - vrshr.u16 q15, q9, #8 - fetch_mask_pixblock - vrshr.u16 q6, q10, #8 -- PF add PF_X, PF_X, #8 -+ PF add, PF_X, PF_X, #8 - vrshr.u16 q7, q11, #8 -- PF tst PF_CTL, #0x0F -+ PF tst, PF_CTL, #0x0F - vraddhn.u16 d28, q14, q8 -- PF addne PF_X, PF_X, #8 -+ PF addne, PF_X, PF_X, #8 - vraddhn.u16 d29, q15, q9 -- PF subne PF_CTL, PF_CTL, #1 -+ PF subne, PF_CTL, PF_CTL, #1 - vraddhn.u16 d30, q6, q10 -- PF cmp PF_X, ORIG_W -+ PF cmp, PF_X, ORIG_W - vraddhn.u16 d31, q7, q11 - PF pld, [PF_DST, PF_X, lsl #dst_bpp_shift] - vmull.u8 q6, d24, d8 - PF pld, [PF_MASK, PF_X, lsl #mask_bpp_shift] - vmull.u8 q7, d24, d9 -- PF subge PF_X, PF_X, ORIG_W -+ PF subge, PF_X, PF_X, ORIG_W - vmull.u8 q8, d24, d10 -- PF subges PF_CTL, PF_CTL, #0x10 -+ PF subges, PF_CTL, PF_CTL, #0x10 - vmull.u8 q9, d24, d11 -- PF ldrgeb DUMMY, [PF_DST, DST_STRIDE, lsl #dst_bpp_shift]! -+ PF ldrgeb, DUMMY, [PF_DST, DST_STRIDE, lsl #dst_bpp_shift]! - vqadd.u8 q14, q0, q14 -- PF ldrgeb DUMMY, [PF_MASK, MASK_STRIDE, lsl #mask_bpp_shift]! -+ PF ldrgeb, DUMMY, [PF_MASK, MASK_STRIDE, lsl #mask_bpp_shift]! - vqadd.u8 q15, q1, q15 - vrshr.u16 q10, q6, #8 - vrshr.u16 q11, q7, #8 - vrshr.u16 q12, q8, #8 - vrshr.u16 q13, q9, #8 - vraddhn.u16 d0, q6, q10 - vraddhn.u16 d1, q7, q11 - vraddhn.u16 d2, q8, q12 -@@ -2420,31 +2426,31 @@ generate_composite_function \ - - .macro pixman_composite_src_pixbuf_8888_process_pixblock_tail_head - vrshr.u16 q11, q8, #8 - vswp d3, d31 - vrshr.u16 q12, q9, #8 - vrshr.u16 q13, q10, #8 - fetch_src_pixblock - vraddhn.u16 d30, q11, q8 -- PF add PF_X, PF_X, #8 -- PF tst PF_CTL, #0xF -- PF addne PF_X, PF_X, #8 -- PF subne PF_CTL, PF_CTL, #1 -+ PF add, PF_X, PF_X, #8 -+ PF tst, PF_CTL, #0xF -+ PF addne, PF_X, PF_X, #8 -+ PF subne, PF_CTL, PF_CTL, #1 - vraddhn.u16 d29, q12, q9 - vraddhn.u16 d28, q13, q10 - vmull.u8 q8, d3, d0 - vmull.u8 q9, d3, d1 - vmull.u8 q10, d3, d2 - vst4.8 {d28, d29, d30, d31}, [DST_W, :128]! -- PF cmp PF_X, ORIG_W -+ PF cmp, PF_X, ORIG_W - PF pld, [PF_SRC, PF_X, lsl #src_bpp_shift] -- PF subge PF_X, PF_X, ORIG_W -- PF subges PF_CTL, PF_CTL, #0x10 -- PF ldrgeb DUMMY, [PF_SRC, SRC_STRIDE, lsl #src_bpp_shift]! -+ PF subge, PF_X, PF_X, ORIG_W -+ PF subges, PF_CTL, PF_CTL, #0x10 -+ PF ldrgeb, DUMMY, [PF_SRC, SRC_STRIDE, lsl #src_bpp_shift]! - .endm - - generate_composite_function \ - pixman_composite_src_pixbuf_8888_asm_neon, 32, 0, 32, \ - FLAG_DST_WRITEONLY | FLAG_DEINTERLEAVE_32BPP, \ - 8, /* number of pixels, processed in a single block */ \ - 10, /* prefetch distance */ \ - default_init, \ -@@ -2477,31 +2483,31 @@ generate_composite_function \ - - .macro pixman_composite_src_rpixbuf_8888_process_pixblock_tail_head - vrshr.u16 q11, q8, #8 - vswp d3, d31 - vrshr.u16 q12, q9, #8 - vrshr.u16 q13, q10, #8 - fetch_src_pixblock - vraddhn.u16 d28, q11, q8 -- PF add PF_X, PF_X, #8 -- PF tst PF_CTL, #0xF -- PF addne PF_X, PF_X, #8 -- PF subne PF_CTL, PF_CTL, #1 -+ PF add, PF_X, PF_X, #8 -+ PF tst, PF_CTL, #0xF -+ PF addne, PF_X, PF_X, #8 -+ PF subne, PF_CTL, PF_CTL, #1 - vraddhn.u16 d29, q12, q9 - vraddhn.u16 d30, q13, q10 - vmull.u8 q8, d3, d0 - vmull.u8 q9, d3, d1 - vmull.u8 q10, d3, d2 - vst4.8 {d28, d29, d30, d31}, [DST_W, :128]! -- PF cmp PF_X, ORIG_W -+ PF cmp, PF_X, ORIG_W - PF pld, [PF_SRC, PF_X, lsl #src_bpp_shift] -- PF subge PF_X, PF_X, ORIG_W -- PF subges PF_CTL, PF_CTL, #0x10 -- PF ldrgeb DUMMY, [PF_SRC, SRC_STRIDE, lsl #src_bpp_shift]! -+ PF subge, PF_X, PF_X, ORIG_W -+ PF subges, PF_CTL, PF_CTL, #0x10 -+ PF ldrgeb, DUMMY, [PF_SRC, SRC_STRIDE, lsl #src_bpp_shift]! - .endm - - generate_composite_function \ - pixman_composite_src_rpixbuf_8888_asm_neon, 32, 0, 32, \ - FLAG_DST_WRITEONLY | FLAG_DEINTERLEAVE_32BPP, \ - 8, /* number of pixels, processed in a single block */ \ - 10, /* prefetch distance */ \ - default_init, \ -@@ -2836,182 +2842,182 @@ generate_composite_function_nearest_scan - * format conversion, and interpolation as separate macros which can be used - * as the basic building blocks for constructing bilinear scanline functions. - */ - - .macro bilinear_load_8888 reg1, reg2, tmp - mov TMP1, X, asr #16 - add X, X, UX - add TMP1, TOP, TMP1, asl #2 -- vld1.32 {reg1}, [TMP1], STRIDE -- vld1.32 {reg2}, [TMP1] -+ vld1.32 {\reg1}, [TMP1], STRIDE -+ vld1.32 {\reg2}, [TMP1] - .endm - - .macro bilinear_load_0565 reg1, reg2, tmp - mov TMP1, X, asr #16 - add X, X, UX - add TMP1, TOP, TMP1, asl #1 -- vld1.32 {reg2[0]}, [TMP1], STRIDE -- vld1.32 {reg2[1]}, [TMP1] -- convert_four_0565_to_x888_packed reg2, reg1, reg2, tmp -+ vld1.32 {\reg2[0]}, [TMP1], STRIDE -+ vld1.32 {\reg2[1]}, [TMP1] -+ convert_four_0565_to_x888_packed \reg2, \reg1, \reg2, \tmp - .endm - - .macro bilinear_load_and_vertical_interpolate_two_8888 \ - acc1, acc2, reg1, reg2, reg3, reg4, tmp1, tmp2 - -- bilinear_load_8888 reg1, reg2, tmp1 -- vmull.u8 acc1, reg1, d28 -- vmlal.u8 acc1, reg2, d29 -- bilinear_load_8888 reg3, reg4, tmp2 -- vmull.u8 acc2, reg3, d28 -- vmlal.u8 acc2, reg4, d29 -+ bilinear_load_8888 \reg1, \reg2, \tmp1 -+ vmull.u8 \acc1, \reg1, d28 -+ vmlal.u8 \acc1, \reg2, d29 -+ bilinear_load_8888 \reg3, \reg4, \tmp2 -+ vmull.u8 \acc2, \reg3, d28 -+ vmlal.u8 \acc2, \reg4, d29 - .endm - - .macro bilinear_load_and_vertical_interpolate_four_8888 \ - xacc1, xacc2, xreg1, xreg2, xreg3, xreg4, xacc2lo, xacc2hi \ - yacc1, yacc2, yreg1, yreg2, yreg3, yreg4, yacc2lo, yacc2hi - - bilinear_load_and_vertical_interpolate_two_8888 \ -- xacc1, xacc2, xreg1, xreg2, xreg3, xreg4, xacc2lo, xacc2hi -+ \xacc1, \xacc2, \xreg1, \xreg2, \xreg3, \xreg4, \xacc2lo, \xacc2hi - bilinear_load_and_vertical_interpolate_two_8888 \ -- yacc1, yacc2, yreg1, yreg2, yreg3, yreg4, yacc2lo, yacc2hi -+ \yacc1, \yacc2, \yreg1, \yreg2, \yreg3, \yreg4, \yacc2lo, \yacc2hi - .endm - - .macro bilinear_load_and_vertical_interpolate_two_0565 \ - acc1, acc2, reg1, reg2, reg3, reg4, acc2lo, acc2hi - - mov TMP1, X, asr #16 - add X, X, UX - add TMP1, TOP, TMP1, asl #1 - mov TMP2, X, asr #16 - add X, X, UX - add TMP2, TOP, TMP2, asl #1 -- vld1.32 {acc2lo[0]}, [TMP1], STRIDE -- vld1.32 {acc2hi[0]}, [TMP2], STRIDE -- vld1.32 {acc2lo[1]}, [TMP1] -- vld1.32 {acc2hi[1]}, [TMP2] -- convert_0565_to_x888 acc2, reg3, reg2, reg1 -- vzip.u8 reg1, reg3 -- vzip.u8 reg2, reg4 -- vzip.u8 reg3, reg4 -- vzip.u8 reg1, reg2 -- vmull.u8 acc1, reg1, d28 -- vmlal.u8 acc1, reg2, d29 -- vmull.u8 acc2, reg3, d28 -- vmlal.u8 acc2, reg4, d29 -+ vld1.32 {\acc2lo[0]}, [TMP1], STRIDE -+ vld1.32 {\acc2hi[0]}, [TMP2], STRIDE -+ vld1.32 {\acc2lo[1]}, [TMP1] -+ vld1.32 {\acc2hi[1]}, [TMP2] -+ convert_0565_to_x888 \acc2, \reg3, \reg2, \reg1 -+ vzip.u8 \reg1, \reg3 -+ vzip.u8 \reg2, \reg4 -+ vzip.u8 \reg3, \reg4 -+ vzip.u8 \reg1, \reg2 -+ vmull.u8 \acc1, \reg1, d28 -+ vmlal.u8 \acc1, \reg2, d29 -+ vmull.u8 \acc2, \reg3, d28 -+ vmlal.u8 \acc2, \reg4, d29 - .endm - - .macro bilinear_load_and_vertical_interpolate_four_0565 \ - xacc1, xacc2, xreg1, xreg2, xreg3, xreg4, xacc2lo, xacc2hi \ - yacc1, yacc2, yreg1, yreg2, yreg3, yreg4, yacc2lo, yacc2hi - - mov TMP1, X, asr #16 - add X, X, UX - add TMP1, TOP, TMP1, asl #1 - mov TMP2, X, asr #16 - add X, X, UX - add TMP2, TOP, TMP2, asl #1 -- vld1.32 {xacc2lo[0]}, [TMP1], STRIDE -- vld1.32 {xacc2hi[0]}, [TMP2], STRIDE -- vld1.32 {xacc2lo[1]}, [TMP1] -- vld1.32 {xacc2hi[1]}, [TMP2] -- convert_0565_to_x888 xacc2, xreg3, xreg2, xreg1 -+ vld1.32 {\xacc2lo[0]}, [TMP1], STRIDE -+ vld1.32 {\xacc2hi[0]}, [TMP2], STRIDE -+ vld1.32 {\xacc2lo[1]}, [TMP1] -+ vld1.32 {\xacc2hi[1]}, [TMP2] -+ convert_0565_to_x888 \xacc2, \xreg3, \xreg2, \xreg1 - mov TMP1, X, asr #16 - add X, X, UX - add TMP1, TOP, TMP1, asl #1 - mov TMP2, X, asr #16 - add X, X, UX - add TMP2, TOP, TMP2, asl #1 -- vld1.32 {yacc2lo[0]}, [TMP1], STRIDE -- vzip.u8 xreg1, xreg3 -- vld1.32 {yacc2hi[0]}, [TMP2], STRIDE -- vzip.u8 xreg2, xreg4 -- vld1.32 {yacc2lo[1]}, [TMP1] -- vzip.u8 xreg3, xreg4 -- vld1.32 {yacc2hi[1]}, [TMP2] -- vzip.u8 xreg1, xreg2 -- convert_0565_to_x888 yacc2, yreg3, yreg2, yreg1 -- vmull.u8 xacc1, xreg1, d28 -- vzip.u8 yreg1, yreg3 -- vmlal.u8 xacc1, xreg2, d29 -- vzip.u8 yreg2, yreg4 -- vmull.u8 xacc2, xreg3, d28 -- vzip.u8 yreg3, yreg4 -- vmlal.u8 xacc2, xreg4, d29 -- vzip.u8 yreg1, yreg2 -- vmull.u8 yacc1, yreg1, d28 -- vmlal.u8 yacc1, yreg2, d29 -- vmull.u8 yacc2, yreg3, d28 -- vmlal.u8 yacc2, yreg4, d29 -+ vld1.32 {\yacc2lo[0]}, [TMP1], STRIDE -+ vzip.u8 \xreg1, \xreg3 -+ vld1.32 {\yacc2hi[0]}, [TMP2], STRIDE -+ vzip.u8 \xreg2, \xreg4 -+ vld1.32 {\yacc2lo[1]}, [TMP1] -+ vzip.u8 \xreg3, \xreg4 -+ vld1.32 {\yacc2hi[1]}, [TMP2] -+ vzip.u8 \xreg1, \xreg2 -+ convert_0565_to_x888 \yacc2, \yreg3, \yreg2, \yreg1 -+ vmull.u8 \xacc1, \xreg1, d28 -+ vzip.u8 \yreg1, \yreg3 -+ vmlal.u8 \xacc1, \xreg2, d29 -+ vzip.u8 \yreg2, \yreg4 -+ vmull.u8 \xacc2, \xreg3, d28 -+ vzip.u8 \yreg3, \yreg4 -+ vmlal.u8 \xacc2, \xreg4, d29 -+ vzip.u8 \yreg1, \yreg2 -+ vmull.u8 \yacc1, \yreg1, d28 -+ vmlal.u8 \yacc1, \yreg2, d29 -+ vmull.u8 \yacc2, \yreg3, d28 -+ vmlal.u8 \yacc2, \yreg4, d29 - .endm - - .macro bilinear_store_8888 numpix, tmp1, tmp2 --.if numpix == 4 -+.if \numpix == 4 - vst1.32 {d0, d1}, [OUT, :128]! --.elseif numpix == 2 -+.elseif \numpix == 2 - vst1.32 {d0}, [OUT, :64]! --.elseif numpix == 1 -+.elseif \numpix == 1 - vst1.32 {d0[0]}, [OUT, :32]! - .else -- .error bilinear_store_8888 numpix is unsupported -+ .error bilinear_store_8888 \numpix is unsupported - .endif - .endm - - .macro bilinear_store_0565 numpix, tmp1, tmp2 - vuzp.u8 d0, d1 - vuzp.u8 d2, d3 - vuzp.u8 d1, d3 - vuzp.u8 d0, d2 -- convert_8888_to_0565 d2, d1, d0, q1, tmp1, tmp2 --.if numpix == 4 -+ convert_8888_to_0565 d2, d1, d0, q1, \tmp1, \tmp2 -+.if \numpix == 4 - vst1.16 {d2}, [OUT, :64]! --.elseif numpix == 2 -+.elseif \numpix == 2 - vst1.32 {d2[0]}, [OUT, :32]! --.elseif numpix == 1 -+.elseif \numpix == 1 - vst1.16 {d2[0]}, [OUT, :16]! - .else -- .error bilinear_store_0565 numpix is unsupported -+ .error bilinear_store_0565 \numpix is unsupported - .endif - .endm - - .macro bilinear_interpolate_last_pixel src_fmt, dst_fmt -- bilinear_load_&src_fmt d0, d1, d2 -+ bilinear_load_\()\src_fmt d0, d1, d2 - vmull.u8 q1, d0, d28 - vmlal.u8 q1, d1, d29 - /* 5 cycles bubble */ - vshll.u16 q0, d2, #BILINEAR_INTERPOLATION_BITS - vmlsl.u16 q0, d2, d30 - vmlal.u16 q0, d3, d30 - /* 5 cycles bubble */ - vshrn.u32 d0, q0, #(2 * BILINEAR_INTERPOLATION_BITS) - /* 3 cycles bubble */ - vmovn.u16 d0, q0 - /* 1 cycle bubble */ -- bilinear_store_&dst_fmt 1, q2, q3 -+ bilinear_store_\()\dst_fmt 1, q2, q3 - .endm - - .macro bilinear_interpolate_two_pixels src_fmt, dst_fmt -- bilinear_load_and_vertical_interpolate_two_&src_fmt \ -+ bilinear_load_and_vertical_interpolate_two_\()\src_fmt \ - q1, q11, d0, d1, d20, d21, d22, d23 - vshll.u16 q0, d2, #BILINEAR_INTERPOLATION_BITS - vmlsl.u16 q0, d2, d30 - vmlal.u16 q0, d3, d30 - vshll.u16 q10, d22, #BILINEAR_INTERPOLATION_BITS - vmlsl.u16 q10, d22, d31 - vmlal.u16 q10, d23, d31 - vshrn.u32 d0, q0, #(2 * BILINEAR_INTERPOLATION_BITS) - vshrn.u32 d1, q10, #(2 * BILINEAR_INTERPOLATION_BITS) - vshr.u16 q15, q12, #(16 - BILINEAR_INTERPOLATION_BITS) - vadd.u16 q12, q12, q13 - vmovn.u16 d0, q0 -- bilinear_store_&dst_fmt 2, q2, q3 -+ bilinear_store_\()\dst_fmt 2, q2, q3 - .endm - - .macro bilinear_interpolate_four_pixels src_fmt, dst_fmt -- bilinear_load_and_vertical_interpolate_four_&src_fmt \ -+ bilinear_load_and_vertical_interpolate_four_\()\src_fmt \ - q1, q11, d0, d1, d20, d21, d22, d23 \ - q3, q9, d4, d5, d16, d17, d18, d19 - pld [TMP1, PF_OFFS] - sub TMP1, TMP1, STRIDE - vshll.u16 q0, d2, #BILINEAR_INTERPOLATION_BITS - vmlsl.u16 q0, d2, d30 - vmlal.u16 q0, d3, d30 - vshll.u16 q10, d22, #BILINEAR_INTERPOLATION_BITS -@@ -3029,64 +3035,64 @@ generate_composite_function_nearest_scan - vshrn.u32 d0, q0, #(2 * BILINEAR_INTERPOLATION_BITS) - vshrn.u32 d1, q10, #(2 * BILINEAR_INTERPOLATION_BITS) - vshrn.u32 d4, q2, #(2 * BILINEAR_INTERPOLATION_BITS) - vshrn.u32 d5, q8, #(2 * BILINEAR_INTERPOLATION_BITS) - vshr.u16 q15, q12, #(16 - BILINEAR_INTERPOLATION_BITS) - vmovn.u16 d0, q0 - vmovn.u16 d1, q2 - vadd.u16 q12, q12, q13 -- bilinear_store_&dst_fmt 4, q2, q3 -+ bilinear_store_\()\dst_fmt 4, q2, q3 - .endm - - .macro bilinear_interpolate_four_pixels_head src_fmt, dst_fmt --.ifdef have_bilinear_interpolate_four_pixels_&src_fmt&_&dst_fmt -- bilinear_interpolate_four_pixels_&src_fmt&_&dst_fmt&_head -+.ifdef have_bilinear_interpolate_four_pixels_\()\src_fmt\()_\()\dst_fmt -+ bilinear_interpolate_four_pixels_\()\src_fmt\()_\()\dst_fmt\()_head - .else -- bilinear_interpolate_four_pixels src_fmt, dst_fmt -+ bilinear_interpolate_four_pixels \src_fmt, \dst_fmt - .endif - .endm - - .macro bilinear_interpolate_four_pixels_tail src_fmt, dst_fmt --.ifdef have_bilinear_interpolate_four_pixels_&src_fmt&_&dst_fmt -- bilinear_interpolate_four_pixels_&src_fmt&_&dst_fmt&_tail -+.ifdef have_bilinear_interpolate_four_pixels_\()\src_fmt\()_\()\dst_fmt -+ bilinear_interpolate_four_pixels_\()\src_fmt\()_\()\dst_fmt\()_tail - .endif - .endm - - .macro bilinear_interpolate_four_pixels_tail_head src_fmt, dst_fmt --.ifdef have_bilinear_interpolate_four_pixels_&src_fmt&_&dst_fmt -- bilinear_interpolate_four_pixels_&src_fmt&_&dst_fmt&_tail_head -+.ifdef have_bilinear_interpolate_four_pixels_\()\src_fmt\()_\()\dst_fmt -+ bilinear_interpolate_four_pixels_\()\src_fmt\()_\()\dst_fmt\()_tail_head - .else -- bilinear_interpolate_four_pixels src_fmt, dst_fmt -+ bilinear_interpolate_four_pixels \src_fmt, \dst_fmt - .endif - .endm - - .macro bilinear_interpolate_eight_pixels_head src_fmt, dst_fmt --.ifdef have_bilinear_interpolate_eight_pixels_&src_fmt&_&dst_fmt -- bilinear_interpolate_eight_pixels_&src_fmt&_&dst_fmt&_head -+.ifdef have_bilinear_interpolate_eight_pixels_\()\src_fmt\()_\()\dst_fmt -+ bilinear_interpolate_eight_pixels_\()\src_fmt\()_\()\dst_fmt\()_head - .else -- bilinear_interpolate_four_pixels_head src_fmt, dst_fmt -- bilinear_interpolate_four_pixels_tail_head src_fmt, dst_fmt -+ bilinear_interpolate_four_pixels_head \src_fmt, \dst_fmt -+ bilinear_interpolate_four_pixels_tail_head \src_fmt, \dst_fmt - .endif - .endm - - .macro bilinear_interpolate_eight_pixels_tail src_fmt, dst_fmt --.ifdef have_bilinear_interpolate_eight_pixels_&src_fmt&_&dst_fmt -- bilinear_interpolate_eight_pixels_&src_fmt&_&dst_fmt&_tail -+.ifdef have_bilinear_interpolate_eight_pixels_\()\src_fmt\()_\()\dst_fmt -+ bilinear_interpolate_eight_pixels_\()\src_fmt\()_\()\dst_fmt\()_tail - .else -- bilinear_interpolate_four_pixels_tail src_fmt, dst_fmt -+ bilinear_interpolate_four_pixels_tail \src_fmt, \dst_fmt - .endif - .endm - - .macro bilinear_interpolate_eight_pixels_tail_head src_fmt, dst_fmt --.ifdef have_bilinear_interpolate_eight_pixels_&src_fmt&_&dst_fmt -- bilinear_interpolate_eight_pixels_&src_fmt&_&dst_fmt&_tail_head -+.ifdef have_bilinear_interpolate_eight_pixels_\()\src_fmt\()_\()\dst_fmt -+ bilinear_interpolate_eight_pixels_\()\src_fmt\()_\()\dst_fmt\()_tail_head - .else -- bilinear_interpolate_four_pixels_tail_head src_fmt, dst_fmt -- bilinear_interpolate_four_pixels_tail_head src_fmt, dst_fmt -+ bilinear_interpolate_four_pixels_tail_head \src_fmt, \dst_fmt -+ bilinear_interpolate_four_pixels_tail_head \src_fmt, \dst_fmt - .endif - .endm - - .set BILINEAR_FLAG_UNROLL_4, 0 - .set BILINEAR_FLAG_UNROLL_8, 1 - .set BILINEAR_FLAG_USE_ALL_NEON_REGS, 2 - - /* -@@ -3101,17 +3107,17 @@ generate_composite_function_nearest_scan - * prefetch_distance - prefetch in the source image by that many - * pixels ahead - */ - - .macro generate_bilinear_scanline_func fname, src_fmt, dst_fmt, \ - src_bpp_shift, dst_bpp_shift, \ - prefetch_distance, flags - --pixman_asm_function fname -+pixman_asm_function \fname - OUT .req r0 - TOP .req r1 - BOTTOM .req r2 - WT .req r3 - WB .req r4 - X .req r5 - UX .req r6 - WIDTH .req ip -@@ -3119,21 +3125,21 @@ pixman_asm_function fname - TMP2 .req r4 - PF_OFFS .req r7 - TMP3 .req r8 - TMP4 .req r9 - STRIDE .req r2 - - mov ip, sp - push {r4, r5, r6, r7, r8, r9} -- mov PF_OFFS, #prefetch_distance -+ mov PF_OFFS, #\prefetch_distance - ldmia ip, {WB, X, UX, WIDTH} - mul PF_OFFS, PF_OFFS, UX - --.if ((flags) & BILINEAR_FLAG_USE_ALL_NEON_REGS) != 0 -+.if ((\flags) & BILINEAR_FLAG_USE_ALL_NEON_REGS) != 0 - vpush {d8-d15} - .endif - - sub STRIDE, BOTTOM, TOP - .unreq BOTTOM - - cmp WIDTH, #0 - ble 3f -@@ -3146,83 +3152,83 @@ pixman_asm_function fname - - /* ensure good destination alignment */ - cmp WIDTH, #1 - blt 0f - tst OUT, #(1 << dst_bpp_shift) - beq 0f - vshr.u16 q15, q12, #(16 - BILINEAR_INTERPOLATION_BITS) - vadd.u16 q12, q12, q13 -- bilinear_interpolate_last_pixel src_fmt, dst_fmt -+ bilinear_interpolate_last_pixel \src_fmt, \dst_fmt - sub WIDTH, WIDTH, #1 - 0: - vadd.u16 q13, q13, q13 - vshr.u16 q15, q12, #(16 - BILINEAR_INTERPOLATION_BITS) - vadd.u16 q12, q12, q13 - - cmp WIDTH, #2 - blt 0f - tst OUT, #(1 << (dst_bpp_shift + 1)) - beq 0f -- bilinear_interpolate_two_pixels src_fmt, dst_fmt -+ bilinear_interpolate_two_pixels \src_fmt, \dst_fmt - sub WIDTH, WIDTH, #2 - 0: --.if ((flags) & BILINEAR_FLAG_UNROLL_8) != 0 -+.if ((\flags) & BILINEAR_FLAG_UNROLL_8) != 0 - /*********** 8 pixels per iteration *****************/ - cmp WIDTH, #4 - blt 0f - tst OUT, #(1 << (dst_bpp_shift + 2)) - beq 0f -- bilinear_interpolate_four_pixels src_fmt, dst_fmt -+ bilinear_interpolate_four_pixels \src_fmt, \dst_fmt - sub WIDTH, WIDTH, #4 - 0: - subs WIDTH, WIDTH, #8 - blt 1f - mov PF_OFFS, PF_OFFS, asr #(16 - src_bpp_shift) -- bilinear_interpolate_eight_pixels_head src_fmt, dst_fmt -+ bilinear_interpolate_eight_pixels_head \src_fmt, \dst_fmt - subs WIDTH, WIDTH, #8 - blt 5f - 0: -- bilinear_interpolate_eight_pixels_tail_head src_fmt, dst_fmt -+ bilinear_interpolate_eight_pixels_tail_head \src_fmt, \dst_fmt - subs WIDTH, WIDTH, #8 - bge 0b - 5: -- bilinear_interpolate_eight_pixels_tail src_fmt, dst_fmt -+ bilinear_interpolate_eight_pixels_tail \src_fmt, \dst_fmt - 1: - tst WIDTH, #4 - beq 2f -- bilinear_interpolate_four_pixels src_fmt, dst_fmt -+ bilinear_interpolate_four_pixels \src_fmt, \dst_fmt - 2: - .else - /*********** 4 pixels per iteration *****************/ - subs WIDTH, WIDTH, #4 - blt 1f - mov PF_OFFS, PF_OFFS, asr #(16 - src_bpp_shift) -- bilinear_interpolate_four_pixels_head src_fmt, dst_fmt -+ bilinear_interpolate_four_pixels_head \src_fmt, \dst_fmt - subs WIDTH, WIDTH, #4 - blt 5f - 0: -- bilinear_interpolate_four_pixels_tail_head src_fmt, dst_fmt -+ bilinear_interpolate_four_pixels_tail_head \src_fmt, \dst_fmt - subs WIDTH, WIDTH, #4 - bge 0b - 5: -- bilinear_interpolate_four_pixels_tail src_fmt, dst_fmt -+ bilinear_interpolate_four_pixels_tail \src_fmt, \dst_fmt - 1: - /****************************************************/ - .endif - /* handle the remaining trailing pixels */ - tst WIDTH, #2 - beq 2f -- bilinear_interpolate_two_pixels src_fmt, dst_fmt -+ bilinear_interpolate_two_pixels \src_fmt, \dst_fmt - 2: - tst WIDTH, #1 - beq 3f -- bilinear_interpolate_last_pixel src_fmt, dst_fmt -+ bilinear_interpolate_last_pixel \src_fmt, \dst_fmt - 3: --.if ((flags) & BILINEAR_FLAG_USE_ALL_NEON_REGS) != 0 -+.if ((\flags) & BILINEAR_FLAG_USE_ALL_NEON_REGS) != 0 - vpop {d8-d15} - .endif - pop {r4, r5, r6, r7, r8, r9} - bx lr - - .unreq OUT - .unreq TOP - .unreq WT -@@ -3231,17 +3237,17 @@ 3: - .unreq UX - .unreq WIDTH - .unreq TMP1 - .unreq TMP2 - .unreq PF_OFFS - .unreq TMP3 - .unreq TMP4 - .unreq STRIDE --.endfunc -+pixman_end_asm_function - - .endm - - /*****************************************************************************/ - - .set have_bilinear_interpolate_four_pixels_8888_8888, 1 - - .macro bilinear_interpolate_four_pixels_8888_8888_head -diff --git a/gfx/cairo/libpixman/src/pixman-arm-neon-asm.h b/gfx/cairo/libpixman/src/pixman-arm-neon-asm.h ---- a/gfx/cairo/libpixman/src/pixman-arm-neon-asm.h -+++ b/gfx/cairo/libpixman/src/pixman-arm-neon-asm.h -@@ -69,303 +69,303 @@ - .set PREFETCH_TYPE_ADVANCED, 2 /* Advanced fine-grained prefetch */ - - /* - * Definitions of supplementary pixld/pixst macros (for partial load/store of - * pixel data). - */ - - .macro pixldst1 op, elem_size, reg1, mem_operand, abits --.if abits > 0 -- op&.&elem_size {d®1}, [&mem_operand&, :&abits&]! -+.if \abits > 0 -+ \op\().\()\elem_size {d\()\reg1}, [\()\mem_operand\(), :\()\abits\()]! - .else -- op&.&elem_size {d®1}, [&mem_operand&]! -+ \op\().\()\elem_size {d\()\reg1}, [\()\mem_operand\()]! - .endif - .endm - - .macro pixldst2 op, elem_size, reg1, reg2, mem_operand, abits --.if abits > 0 -- op&.&elem_size {d®1, d®2}, [&mem_operand&, :&abits&]! -+.if \abits > 0 -+ \op\().\()\elem_size {d\()\reg1, d\()\reg2}, [\()\mem_operand\(), :\()\abits\()]! - .else -- op&.&elem_size {d®1, d®2}, [&mem_operand&]! -+ \op\().\()\elem_size {d\()\reg1, d\()\reg2}, [\()\mem_operand\()]! - .endif - .endm - - .macro pixldst4 op, elem_size, reg1, reg2, reg3, reg4, mem_operand, abits --.if abits > 0 -- op&.&elem_size {d®1, d®2, d®3, d®4}, [&mem_operand&, :&abits&]! -+.if \abits > 0 -+ \op\().\()\elem_size {d\()\reg1, d\()\reg2, d\()\reg3, d\()\reg4}, [\()\mem_operand\(), :\()\abits\()]! - .else -- op&.&elem_size {d®1, d®2, d®3, d®4}, [&mem_operand&]! -+ \op\().\()\elem_size {d\()\reg1, d\()\reg2, d\()\reg3, d\()\reg4}, [\()\mem_operand\()]! - .endif - .endm - - .macro pixldst0 op, elem_size, reg1, idx, mem_operand, abits -- op&.&elem_size {d®1[idx]}, [&mem_operand&]! -+ \op\().\()\elem_size {d\()\reg1[\idx]}, [\()\mem_operand\()]! - .endm - - .macro pixldst3 op, elem_size, reg1, reg2, reg3, mem_operand -- op&.&elem_size {d®1, d®2, d®3}, [&mem_operand&]! -+ \op\().\()\elem_size {d\()\reg1, d\()\reg2, d\()\reg3}, [\()\mem_operand\()]! - .endm - - .macro pixldst30 op, elem_size, reg1, reg2, reg3, idx, mem_operand -- op&.&elem_size {d®1[idx], d®2[idx], d®3[idx]}, [&mem_operand&]! -+ \op\().\()\elem_size {d\()\reg1[\idx], d\()\reg2[\idx], d\()\reg3[\idx]}, [\()\mem_operand\()]! - .endm - - .macro pixldst numbytes, op, elem_size, basereg, mem_operand, abits --.if numbytes == 32 -- pixldst4 op, elem_size, %(basereg+4), %(basereg+5), \ -- %(basereg+6), %(basereg+7), mem_operand, abits --.elseif numbytes == 16 -- pixldst2 op, elem_size, %(basereg+2), %(basereg+3), mem_operand, abits --.elseif numbytes == 8 -- pixldst1 op, elem_size, %(basereg+1), mem_operand, abits --.elseif numbytes == 4 -- .if !RESPECT_STRICT_ALIGNMENT || (elem_size == 32) -- pixldst0 op, 32, %(basereg+0), 1, mem_operand, abits -- .elseif elem_size == 16 -- pixldst0 op, 16, %(basereg+0), 2, mem_operand, abits -- pixldst0 op, 16, %(basereg+0), 3, mem_operand, abits -+.if \numbytes == 32 -+ pixldst4 \op, \elem_size, %(\basereg+4), %(\basereg+5), \ -+ %(\basereg+6), %(\basereg+7), \mem_operand, \abits -+.elseif \numbytes == 16 -+ pixldst2 \op, \elem_size, %(\basereg+2), %(\basereg+3), \mem_operand, \abits -+.elseif \numbytes == 8 -+ pixldst1 \op, \elem_size, %(\basereg+1), \mem_operand, \abits -+.elseif \numbytes == 4 -+ .if !RESPECT_STRICT_ALIGNMENT || (\elem_size == 32) -+ pixldst0 \op, 32, %(\basereg+0), 1, \mem_operand, \abits -+ .elseif \elem_size == 16 -+ pixldst0 \op, 16, %(\basereg+0), 2, \mem_operand, \abits -+ pixldst0 \op, 16, %(\basereg+0), 3, \mem_operand, \abits - .else -- pixldst0 op, 8, %(basereg+0), 4, mem_operand, abits -- pixldst0 op, 8, %(basereg+0), 5, mem_operand, abits -- pixldst0 op, 8, %(basereg+0), 6, mem_operand, abits -- pixldst0 op, 8, %(basereg+0), 7, mem_operand, abits -+ pixldst0 \op, 8, %(\basereg+0), 4, \mem_operand, \abits -+ pixldst0 \op, 8, %(\basereg+0), 5, \mem_operand, \abits -+ pixldst0 \op, 8, %(\basereg+0), 6, \mem_operand, \abits -+ pixldst0 \op, 8, %(\basereg+0), 7, \mem_operand, \abits - .endif --.elseif numbytes == 2 -- .if !RESPECT_STRICT_ALIGNMENT || (elem_size == 16) -- pixldst0 op, 16, %(basereg+0), 1, mem_operand, abits -+.elseif \numbytes == 2 -+ .if !RESPECT_STRICT_ALIGNMENT || (\elem_size == 16) -+ pixldst0 \op, 16, %(\basereg+0), 1, \mem_operand, \abits - .else -- pixldst0 op, 8, %(basereg+0), 2, mem_operand, abits -- pixldst0 op, 8, %(basereg+0), 3, mem_operand, abits -+ pixldst0 \op, 8, %(\basereg+0), 2, \mem_operand, \abits -+ pixldst0 \op, 8, %(\basereg+0), 3, \mem_operand, \abits - .endif --.elseif numbytes == 1 -- pixldst0 op, 8, %(basereg+0), 1, mem_operand, abits -+.elseif \numbytes == 1 -+ pixldst0 \op, 8, %(\basereg+0), 1, \mem_operand, \abits - .else -- .error "unsupported size: numbytes" -+ .error "unsupported size: \numbytes" - .endif - .endm - - .macro pixld numpix, bpp, basereg, mem_operand, abits=0 --.if bpp > 0 --.if (bpp == 32) && (numpix == 8) && (DEINTERLEAVE_32BPP_ENABLED != 0) -- pixldst4 vld4, 8, %(basereg+4), %(basereg+5), \ -- %(basereg+6), %(basereg+7), mem_operand, abits --.elseif (bpp == 24) && (numpix == 8) -- pixldst3 vld3, 8, %(basereg+3), %(basereg+4), %(basereg+5), mem_operand --.elseif (bpp == 24) && (numpix == 4) -- pixldst30 vld3, 8, %(basereg+0), %(basereg+1), %(basereg+2), 4, mem_operand -- pixldst30 vld3, 8, %(basereg+0), %(basereg+1), %(basereg+2), 5, mem_operand -- pixldst30 vld3, 8, %(basereg+0), %(basereg+1), %(basereg+2), 6, mem_operand -- pixldst30 vld3, 8, %(basereg+0), %(basereg+1), %(basereg+2), 7, mem_operand --.elseif (bpp == 24) && (numpix == 2) -- pixldst30 vld3, 8, %(basereg+0), %(basereg+1), %(basereg+2), 2, mem_operand -- pixldst30 vld3, 8, %(basereg+0), %(basereg+1), %(basereg+2), 3, mem_operand --.elseif (bpp == 24) && (numpix == 1) -- pixldst30 vld3, 8, %(basereg+0), %(basereg+1), %(basereg+2), 1, mem_operand -+.if \bpp > 0 -+.if (\bpp == 32) && (\numpix == 8) && (DEINTERLEAVE_32BPP_ENABLED != 0) -+ pixldst4 vld4, 8, %(\basereg+4), %(\basereg+5), \ -+ %(\basereg+6), %(\basereg+7), \mem_operand, \abits -+.elseif (\bpp == 24) && (\numpix == 8) -+ pixldst3 vld3, 8, %(\basereg+3), %(\basereg+4), %(\basereg+5), \mem_operand -+.elseif (\bpp == 24) && (\numpix == 4) -+ pixldst30 vld3, 8, %(\basereg+0), %(\basereg+1), %(\basereg+2), 4, \mem_operand -+ pixldst30 vld3, 8, %(\basereg+0), %(\basereg+1), %(\basereg+2), 5, \mem_operand -+ pixldst30 vld3, 8, %(\basereg+0), %(\basereg+1), %(\basereg+2), 6, \mem_operand -+ pixldst30 vld3, 8, %(\basereg+0), %(\basereg+1), %(\basereg+2), 7, \mem_operand -+.elseif (\bpp == 24) && (\numpix == 2) -+ pixldst30 vld3, 8, %(\basereg+0), %(\basereg+1), %(\basereg+2), 2, \mem_operand -+ pixldst30 vld3, 8, %(\basereg+0), %(\basereg+1), %(\basereg+2), 3, \mem_operand -+.elseif (\bpp == 24) && (\numpix == 1) -+ pixldst30 vld3, 8, %(\basereg+0), %(\basereg+1), %(\basereg+2), 1, \mem_operand - .else -- pixldst %(numpix * bpp / 8), vld1, %(bpp), basereg, mem_operand, abits -+ pixldst %(\numpix * \bpp / 8), vld1, %(\bpp), \basereg, \mem_operand, \abits - .endif - .endif - .endm - - .macro pixst numpix, bpp, basereg, mem_operand, abits=0 --.if bpp > 0 --.if (bpp == 32) && (numpix == 8) && (DEINTERLEAVE_32BPP_ENABLED != 0) -- pixldst4 vst4, 8, %(basereg+4), %(basereg+5), \ -- %(basereg+6), %(basereg+7), mem_operand, abits --.elseif (bpp == 24) && (numpix == 8) -- pixldst3 vst3, 8, %(basereg+3), %(basereg+4), %(basereg+5), mem_operand --.elseif (bpp == 24) && (numpix == 4) -- pixldst30 vst3, 8, %(basereg+0), %(basereg+1), %(basereg+2), 4, mem_operand -- pixldst30 vst3, 8, %(basereg+0), %(basereg+1), %(basereg+2), 5, mem_operand -- pixldst30 vst3, 8, %(basereg+0), %(basereg+1), %(basereg+2), 6, mem_operand -- pixldst30 vst3, 8, %(basereg+0), %(basereg+1), %(basereg+2), 7, mem_operand --.elseif (bpp == 24) && (numpix == 2) -- pixldst30 vst3, 8, %(basereg+0), %(basereg+1), %(basereg+2), 2, mem_operand -- pixldst30 vst3, 8, %(basereg+0), %(basereg+1), %(basereg+2), 3, mem_operand --.elseif (bpp == 24) && (numpix == 1) -- pixldst30 vst3, 8, %(basereg+0), %(basereg+1), %(basereg+2), 1, mem_operand -+.if \bpp > 0 -+.if (\bpp == 32) && (\numpix == 8) && (DEINTERLEAVE_32BPP_ENABLED != 0) -+ pixldst4 vst4, 8, %(\basereg+4), %(\basereg+5), \ -+ %(\basereg+6), %(\basereg+7), \mem_operand, \abits -+.elseif (\bpp == 24) && (\numpix == 8) -+ pixldst3 vst3, 8, %(\basereg+3), %(\basereg+4), %(\basereg+5), \mem_operand -+.elseif (\bpp == 24) && (\numpix == 4) -+ pixldst30 vst3, 8, %(\basereg+0), %(\basereg+1), %(\basereg+2), 4, \mem_operand -+ pixldst30 vst3, 8, %(\basereg+0), %(\basereg+1), %(\basereg+2), 5, \mem_operand -+ pixldst30 vst3, 8, %(\basereg+0), %(\basereg+1), %(\basereg+2), 6, \mem_operand -+ pixldst30 vst3, 8, %(\basereg+0), %(\basereg+1), %(\basereg+2), 7, \mem_operand -+.elseif (\bpp == 24) && (\numpix == 2) -+ pixldst30 vst3, 8, %(\basereg+0), %(\basereg+1), %(\basereg+2), 2, \mem_operand -+ pixldst30 vst3, 8, %(\basereg+0), %(\basereg+1), %(\basereg+2), 3, \mem_operand -+.elseif (\bpp == 24) && (\numpix == 1) -+ pixldst30 vst3, 8, %(\basereg+0), %(\basereg+1), %(\basereg+2), 1, \mem_operand - .else -- pixldst %(numpix * bpp / 8), vst1, %(bpp), basereg, mem_operand, abits -+ pixldst %(\numpix * \bpp / 8), vst1, %(\bpp), \basereg, \mem_operand, \abits - .endif - .endif - .endm - - .macro pixld_a numpix, bpp, basereg, mem_operand --.if (bpp * numpix) <= 128 -- pixld numpix, bpp, basereg, mem_operand, %(bpp * numpix) -+.if (\bpp * \numpix) <= 128 -+ pixld \numpix, \bpp, \basereg, \mem_operand, %(\bpp * \numpix) - .else -- pixld numpix, bpp, basereg, mem_operand, 128 -+ pixld \numpix, \bpp, \basereg, \mem_operand, 128 - .endif - .endm - - .macro pixst_a numpix, bpp, basereg, mem_operand --.if (bpp * numpix) <= 128 -- pixst numpix, bpp, basereg, mem_operand, %(bpp * numpix) -+.if (\bpp * \numpix) <= 128 -+ pixst \numpix, \bpp, \basereg, \mem_operand, %(\bpp * \numpix) - .else -- pixst numpix, bpp, basereg, mem_operand, 128 -+ pixst \numpix, \bpp, \basereg, \mem_operand, 128 - .endif - .endm - - /* - * Pixel fetcher for nearest scaling (needs TMP1, TMP2, VX, UNIT_X register - * aliases to be defined) - */ - .macro pixld1_s elem_size, reg1, mem_operand --.if elem_size == 16 -+.if \elem_size == 16 - mov TMP1, VX, asr #16 - adds VX, VX, UNIT_X - 5: subpls VX, VX, SRC_WIDTH_FIXED - bpl 5b -- add TMP1, mem_operand, TMP1, asl #1 -+ add TMP1, \mem_operand, TMP1, asl #1 - mov TMP2, VX, asr #16 - adds VX, VX, UNIT_X - 5: subpls VX, VX, SRC_WIDTH_FIXED - bpl 5b -- add TMP2, mem_operand, TMP2, asl #1 -- vld1.16 {d®1&[0]}, [TMP1, :16] -+ add TMP2, \mem_operand, TMP2, asl #1 -+ vld1.16 {d\()\reg1\()[0]}, [TMP1, :16] - mov TMP1, VX, asr #16 - adds VX, VX, UNIT_X - 5: subpls VX, VX, SRC_WIDTH_FIXED - bpl 5b -- add TMP1, mem_operand, TMP1, asl #1 -- vld1.16 {d®1&[1]}, [TMP2, :16] -+ add TMP1, \mem_operand, TMP1, asl #1 -+ vld1.16 {d\()\reg1\()[1]}, [TMP2, :16] - mov TMP2, VX, asr #16 - adds VX, VX, UNIT_X - 5: subpls VX, VX, SRC_WIDTH_FIXED - bpl 5b -- add TMP2, mem_operand, TMP2, asl #1 -- vld1.16 {d®1&[2]}, [TMP1, :16] -- vld1.16 {d®1&[3]}, [TMP2, :16] --.elseif elem_size == 32 -+ add TMP2, \mem_operand, TMP2, asl #1 -+ vld1.16 {d\()\reg1\()[2]}, [TMP1, :16] -+ vld1.16 {d\()\reg1\()[3]}, [TMP2, :16] -+.elseif \elem_size == 32 - mov TMP1, VX, asr #16 - adds VX, VX, UNIT_X - 5: subpls VX, VX, SRC_WIDTH_FIXED - bpl 5b -- add TMP1, mem_operand, TMP1, asl #2 -+ add TMP1, \mem_operand, TMP1, asl #2 - mov TMP2, VX, asr #16 - adds VX, VX, UNIT_X - 5: subpls VX, VX, SRC_WIDTH_FIXED - bpl 5b -- add TMP2, mem_operand, TMP2, asl #2 -- vld1.32 {d®1&[0]}, [TMP1, :32] -- vld1.32 {d®1&[1]}, [TMP2, :32] -+ add TMP2, \mem_operand, TMP2, asl #2 -+ vld1.32 {d\()\reg1\()[0]}, [TMP1, :32] -+ vld1.32 {d\()\reg1\()[1]}, [TMP2, :32] - .else - .error "unsupported" - .endif - .endm - - .macro pixld2_s elem_size, reg1, reg2, mem_operand - .if 0 /* elem_size == 32 */ - mov TMP1, VX, asr #16 - add VX, VX, UNIT_X, asl #1 -- add TMP1, mem_operand, TMP1, asl #2 -+ add TMP1, \mem_operand, TMP1, asl #2 - mov TMP2, VX, asr #16 - sub VX, VX, UNIT_X -- add TMP2, mem_operand, TMP2, asl #2 -- vld1.32 {d®1&[0]}, [TMP1, :32] -+ add TMP2, \mem_operand, TMP2, asl #2 -+ vld1.32 {d\()\reg1\()[0]}, [TMP1, :32] - mov TMP1, VX, asr #16 - add VX, VX, UNIT_X, asl #1 -- add TMP1, mem_operand, TMP1, asl #2 -- vld1.32 {d®2&[0]}, [TMP2, :32] -+ add TMP1, \mem_operand, TMP1, asl #2 -+ vld1.32 {d\()\reg2\()[0]}, [TMP2, :32] - mov TMP2, VX, asr #16 - add VX, VX, UNIT_X -- add TMP2, mem_operand, TMP2, asl #2 -- vld1.32 {d®1&[1]}, [TMP1, :32] -- vld1.32 {d®2&[1]}, [TMP2, :32] -+ add TMP2, \mem_operand, TMP2, asl #2 -+ vld1.32 {d\()\reg1\()[1]}, [TMP1, :32] -+ vld1.32 {d\()\reg2\()[1]}, [TMP2, :32] - .else -- pixld1_s elem_size, reg1, mem_operand -- pixld1_s elem_size, reg2, mem_operand -+ pixld1_s \elem_size, \reg1, \mem_operand -+ pixld1_s \elem_size, \reg2, \mem_operand - .endif - .endm - - .macro pixld0_s elem_size, reg1, idx, mem_operand --.if elem_size == 16 -+.if \elem_size == 16 - mov TMP1, VX, asr #16 - adds VX, VX, UNIT_X - 5: subpls VX, VX, SRC_WIDTH_FIXED - bpl 5b -- add TMP1, mem_operand, TMP1, asl #1 -- vld1.16 {d®1&[idx]}, [TMP1, :16] --.elseif elem_size == 32 -+ add TMP1, \mem_operand, TMP1, asl #1 -+ vld1.16 {d\()\reg1\()[\idx]}, [TMP1, :16] -+.elseif \elem_size == 32 - mov TMP1, VX, asr #16 - adds VX, VX, UNIT_X - 5: subpls VX, VX, SRC_WIDTH_FIXED - bpl 5b -- add TMP1, mem_operand, TMP1, asl #2 -- vld1.32 {d®1&[idx]}, [TMP1, :32] -+ add TMP1, \mem_operand, TMP1, asl #2 -+ vld1.32 {d\()\reg1\()[\idx]}, [TMP1, :32] - .endif - .endm - - .macro pixld_s_internal numbytes, elem_size, basereg, mem_operand --.if numbytes == 32 -- pixld2_s elem_size, %(basereg+4), %(basereg+5), mem_operand -- pixld2_s elem_size, %(basereg+6), %(basereg+7), mem_operand -- pixdeinterleave elem_size, %(basereg+4) --.elseif numbytes == 16 -- pixld2_s elem_size, %(basereg+2), %(basereg+3), mem_operand --.elseif numbytes == 8 -- pixld1_s elem_size, %(basereg+1), mem_operand --.elseif numbytes == 4 -- .if elem_size == 32 -- pixld0_s elem_size, %(basereg+0), 1, mem_operand -- .elseif elem_size == 16 -- pixld0_s elem_size, %(basereg+0), 2, mem_operand -- pixld0_s elem_size, %(basereg+0), 3, mem_operand -+.if \numbytes == 32 -+ pixld2_s \elem_size, %(\basereg+4), %(\basereg+5), \mem_operand -+ pixld2_s \elem_size, %(\basereg+6), %(\basereg+7), \mem_operand -+ pixdeinterleave \elem_size, %(\basereg+4) -+.elseif \numbytes == 16 -+ pixld2_s \elem_size, %(\basereg+2), %(\basereg+3), \mem_operand -+.elseif \numbytes == 8 -+ pixld1_s \elem_size, %(\basereg+1), \mem_operand -+.elseif \numbytes == 4 -+ .if \elem_size == 32 -+ pixld0_s \elem_size, %(\basereg+0), 1, \mem_operand -+ .elseif \elem_size == 16 -+ pixld0_s \elem_size, %(\basereg+0), 2, \mem_operand -+ pixld0_s \elem_size, %(\basereg+0), 3, \mem_operand - .else -- pixld0_s elem_size, %(basereg+0), 4, mem_operand -- pixld0_s elem_size, %(basereg+0), 5, mem_operand -- pixld0_s elem_size, %(basereg+0), 6, mem_operand -- pixld0_s elem_size, %(basereg+0), 7, mem_operand -+ pixld0_s \elem_size, %(\basereg+0), 4, \mem_operand -+ pixld0_s \elem_size, %(\basereg+0), 5, \mem_operand -+ pixld0_s \elem_size, %(\basereg+0), 6, \mem_operand -+ pixld0_s \elem_size, %(\basereg+0), 7, \mem_operand - .endif --.elseif numbytes == 2 -- .if elem_size == 16 -- pixld0_s elem_size, %(basereg+0), 1, mem_operand -+.elseif \numbytes == 2 -+ .if \elem_size == 16 -+ pixld0_s \elem_size, %(\basereg+0), 1, \mem_operand - .else -- pixld0_s elem_size, %(basereg+0), 2, mem_operand -- pixld0_s elem_size, %(basereg+0), 3, mem_operand -+ pixld0_s \elem_size, %(\basereg+0), 2, \mem_operand -+ pixld0_s \elem_size, %(\basereg+0), 3, \mem_operand - .endif --.elseif numbytes == 1 -- pixld0_s elem_size, %(basereg+0), 1, mem_operand -+.elseif \numbytes == 1 -+ pixld0_s \elem_size, %(\basereg+0), 1, \mem_operand - .else -- .error "unsupported size: numbytes" -+ .error "unsupported size: \numbytes" - .endif - .endm - - .macro pixld_s numpix, bpp, basereg, mem_operand --.if bpp > 0 -- pixld_s_internal %(numpix * bpp / 8), %(bpp), basereg, mem_operand -+.if \bpp > 0 -+ pixld_s_internal %(\numpix * \bpp / 8), %(\bpp), \basereg, \mem_operand - .endif - .endm - - .macro vuzp8 reg1, reg2 -- vuzp.8 d®1, d®2 -+ vuzp.8 d\()\reg1, d\()\reg2 - .endm - - .macro vzip8 reg1, reg2 -- vzip.8 d®1, d®2 -+ vzip.8 d\()\reg1, d\()\reg2 - .endm - - /* deinterleave B, G, R, A channels for eight 32bpp pixels in 4 registers */ - .macro pixdeinterleave bpp, basereg --.if (bpp == 32) && (DEINTERLEAVE_32BPP_ENABLED != 0) -- vuzp8 %(basereg+0), %(basereg+1) -- vuzp8 %(basereg+2), %(basereg+3) -- vuzp8 %(basereg+1), %(basereg+3) -- vuzp8 %(basereg+0), %(basereg+2) -+.if (\bpp == 32) && (DEINTERLEAVE_32BPP_ENABLED != 0) -+ vuzp8 %(\basereg+0), %(\basereg+1) -+ vuzp8 %(\basereg+2), %(\basereg+3) -+ vuzp8 %(\basereg+1), %(\basereg+3) -+ vuzp8 %(\basereg+0), %(\basereg+2) - .endif - .endm - - /* interleave B, G, R, A channels for eight 32bpp pixels in 4 registers */ - .macro pixinterleave bpp, basereg --.if (bpp == 32) && (DEINTERLEAVE_32BPP_ENABLED != 0) -- vzip8 %(basereg+0), %(basereg+2) -- vzip8 %(basereg+1), %(basereg+3) -- vzip8 %(basereg+2), %(basereg+3) -- vzip8 %(basereg+0), %(basereg+1) -+.if (\bpp == 32) && (DEINTERLEAVE_32BPP_ENABLED != 0) -+ vzip8 %(\basereg+0), %(\basereg+2) -+ vzip8 %(\basereg+1), %(\basereg+3) -+ vzip8 %(\basereg+2), %(\basereg+3) -+ vzip8 %(\basereg+0), %(\basereg+1) - .endif - .endm - - /* - * This is a macro for implementing cache preload. The main idea is that - * cache preload logic is mostly independent from the rest of pixels - * processing code. It starts at the top left pixel and moves forward - * across pixels and can jump across scanlines. Prefetch distance is -@@ -389,51 +389,51 @@ 5: subpls VX, VX, SRC_WIDTH_FIXED - * for almost zero cost! - * - * (*) The overhead of the prefetcher is visible when running some trivial - * pixels processing like simple copy. Anyway, having prefetch is a must - * when working with the graphics data. - */ - .macro PF a, x:vararg - .if (PREFETCH_TYPE_CURRENT == PREFETCH_TYPE_ADVANCED) -- a x -+ \a \x - .endif - .endm - - .macro cache_preload std_increment, boost_increment - .if (src_bpp_shift >= 0) || (dst_r_bpp != 0) || (mask_bpp_shift >= 0) - .if regs_shortage -- PF ldr ORIG_W, [sp] /* If we are short on regs, ORIG_W is kept on stack */ -+ PF ldr, ORIG_W, [sp] /* If we are short on regs, ORIG_W is kept on stack */ - .endif --.if std_increment != 0 -- PF add PF_X, PF_X, #std_increment -+.if \std_increment != 0 -+ PF add, PF_X, PF_X, #\std_increment - .endif -- PF tst PF_CTL, #0xF -- PF addne PF_X, PF_X, #boost_increment -- PF subne PF_CTL, PF_CTL, #1 -- PF cmp PF_X, ORIG_W -+ PF tst, PF_CTL, #0xF -+ PF addne, PF_X, PF_X, #\boost_increment -+ PF subne, PF_CTL, PF_CTL, #1 -+ PF cmp, PF_X, ORIG_W - .if src_bpp_shift >= 0 - PF pld, [PF_SRC, PF_X, lsl #src_bpp_shift] - .endif - .if dst_r_bpp != 0 - PF pld, [PF_DST, PF_X, lsl #dst_bpp_shift] - .endif - .if mask_bpp_shift >= 0 - PF pld, [PF_MASK, PF_X, lsl #mask_bpp_shift] - .endif -- PF subge PF_X, PF_X, ORIG_W -- PF subges PF_CTL, PF_CTL, #0x10 -+ PF subge, PF_X, PF_X, ORIG_W -+ PF subges, PF_CTL, PF_CTL, #0x10 - .if src_bpp_shift >= 0 -- PF ldrgeb DUMMY, [PF_SRC, SRC_STRIDE, lsl #src_bpp_shift]! -+ PF ldrgeb, DUMMY, [PF_SRC, SRC_STRIDE, lsl #src_bpp_shift]! - .endif - .if dst_r_bpp != 0 -- PF ldrgeb DUMMY, [PF_DST, DST_STRIDE, lsl #dst_bpp_shift]! -+ PF ldrgeb, DUMMY, [PF_DST, DST_STRIDE, lsl #dst_bpp_shift]! - .endif - .if mask_bpp_shift >= 0 -- PF ldrgeb DUMMY, [PF_MASK, MASK_STRIDE, lsl #mask_bpp_shift]! -+ PF ldrgeb, DUMMY, [PF_MASK, MASK_STRIDE, lsl #mask_bpp_shift]! - .endif - .endif - .endm - - .macro cache_preload_simple - .if (PREFETCH_TYPE_CURRENT == PREFETCH_TYPE_SIMPLE) - .if src_bpp > 0 - pld [SRC, #(PREFETCH_DISTANCE_SIMPLE * src_bpp / 8)] -@@ -460,51 +460,53 @@ 5: subpls VX, VX, SRC_WIDTH_FIXED - .macro ensure_destination_ptr_alignment process_pixblock_head, \ - process_pixblock_tail, \ - process_pixblock_tail_head - .if dst_w_bpp != 24 - tst DST_R, #0xF - beq 2f - - .irp lowbit, 1, 2, 4, 8, 16 -+#ifndef __clang__ - local skip1 --.if (dst_w_bpp <= (lowbit * 8)) && ((lowbit * 8) < (pixblock_size * dst_w_bpp)) --.if lowbit < 16 /* we don't need more than 16-byte alignment */ -- tst DST_R, #lowbit -+#endif -+.if (dst_w_bpp <= (\lowbit * 8)) && ((\lowbit * 8) < (pixblock_size * dst_w_bpp)) -+.if \lowbit < 16 /* we don't need more than 16-byte alignment */ -+ tst DST_R, #\lowbit - beq 1f - .endif -- pixld_src (lowbit * 8 / dst_w_bpp), src_bpp, src_basereg, SRC -- pixld (lowbit * 8 / dst_w_bpp), mask_bpp, mask_basereg, MASK -+ pixld_src (\lowbit * 8 / dst_w_bpp), src_bpp, src_basereg, SRC -+ pixld (\lowbit * 8 / dst_w_bpp), mask_bpp, mask_basereg, MASK - .if dst_r_bpp > 0 -- pixld_a (lowbit * 8 / dst_r_bpp), dst_r_bpp, dst_r_basereg, DST_R -+ pixld_a (\lowbit * 8 / dst_r_bpp), dst_r_bpp, dst_r_basereg, DST_R - .else -- add DST_R, DST_R, #lowbit -+ add DST_R, DST_R, #\lowbit - .endif -- PF add PF_X, PF_X, #(lowbit * 8 / dst_w_bpp) -- sub W, W, #(lowbit * 8 / dst_w_bpp) -+ PF add, PF_X, PF_X, #(\lowbit * 8 / dst_w_bpp) -+ sub W, W, #(\lowbit * 8 / dst_w_bpp) - 1: - .endif - .endr - pixdeinterleave src_bpp, src_basereg - pixdeinterleave mask_bpp, mask_basereg - pixdeinterleave dst_r_bpp, dst_r_basereg - -- process_pixblock_head -+ \process_pixblock_head - cache_preload 0, pixblock_size - cache_preload_simple -- process_pixblock_tail -+ \process_pixblock_tail - - pixinterleave dst_w_bpp, dst_w_basereg - .irp lowbit, 1, 2, 4, 8, 16 --.if (dst_w_bpp <= (lowbit * 8)) && ((lowbit * 8) < (pixblock_size * dst_w_bpp)) --.if lowbit < 16 /* we don't need more than 16-byte alignment */ -- tst DST_W, #lowbit -+.if (dst_w_bpp <= (\lowbit * 8)) && ((\lowbit * 8) < (pixblock_size * dst_w_bpp)) -+.if \lowbit < 16 /* we don't need more than 16-byte alignment */ -+ tst DST_W, #\lowbit - beq 1f - .endif -- pixst_a (lowbit * 8 / dst_w_bpp), dst_w_bpp, dst_w_basereg, DST_W -+ pixst_a (\lowbit * 8 / dst_w_bpp), dst_w_bpp, dst_w_basereg, DST_W - 1: - .endif - .endr - .endif - 2: - .endm - - /* -@@ -525,51 +527,51 @@ 2: - .macro process_trailing_pixels cache_preload_flag, \ - dst_aligned_flag, \ - process_pixblock_head, \ - process_pixblock_tail, \ - process_pixblock_tail_head - tst W, #(pixblock_size - 1) - beq 2f - .irp chunk_size, 16, 8, 4, 2, 1 --.if pixblock_size > chunk_size -- tst W, #chunk_size -+.if pixblock_size > \chunk_size -+ tst W, #\chunk_size - beq 1f -- pixld_src chunk_size, src_bpp, src_basereg, SRC -- pixld chunk_size, mask_bpp, mask_basereg, MASK --.if dst_aligned_flag != 0 -- pixld_a chunk_size, dst_r_bpp, dst_r_basereg, DST_R -+ pixld_src \chunk_size, src_bpp, src_basereg, SRC -+ pixld \chunk_size, mask_bpp, mask_basereg, MASK -+.if \dst_aligned_flag != 0 -+ pixld_a \chunk_size, dst_r_bpp, dst_r_basereg, DST_R - .else -- pixld chunk_size, dst_r_bpp, dst_r_basereg, DST_R -+ pixld \chunk_size, dst_r_bpp, dst_r_basereg, DST_R - .endif --.if cache_preload_flag != 0 -- PF add PF_X, PF_X, #chunk_size -+.if \cache_preload_flag != 0 -+ PF add, PF_X, PF_X, #\chunk_size - .endif - 1: - .endif - .endr - pixdeinterleave src_bpp, src_basereg - pixdeinterleave mask_bpp, mask_basereg - pixdeinterleave dst_r_bpp, dst_r_basereg - -- process_pixblock_head --.if cache_preload_flag != 0 -+ \process_pixblock_head -+.if \cache_preload_flag != 0 - cache_preload 0, pixblock_size - cache_preload_simple - .endif -- process_pixblock_tail -+ \process_pixblock_tail - pixinterleave dst_w_bpp, dst_w_basereg - .irp chunk_size, 16, 8, 4, 2, 1 --.if pixblock_size > chunk_size -- tst W, #chunk_size -+.if pixblock_size > \chunk_size -+ tst W, #\chunk_size - beq 1f --.if dst_aligned_flag != 0 -- pixst_a chunk_size, dst_w_bpp, dst_w_basereg, DST_W -+.if \dst_aligned_flag != 0 -+ pixst_a \chunk_size, dst_w_bpp, dst_w_basereg, DST_W - .else -- pixst chunk_size, dst_w_bpp, dst_w_basereg, DST_W -+ pixst \chunk_size, dst_w_bpp, dst_w_basereg, DST_W - .endif - 1: - .endif - .endr - 2: - .endm - - /* -@@ -599,17 +601,17 @@ 2: - .if (mask_bpp != 24) && (mask_bpp != 0) - sub MASK, MASK, W, lsl #mask_bpp_shift - .endif - subs H, H, #1 - mov DST_R, DST_W - .if regs_shortage - str H, [sp, #4] /* save updated height to stack */ - .endif -- bge start_of_loop_label -+ bge \start_of_loop_label - .endm - - /* - * Registers are allocated in the following way by default: - * d0, d1, d2, d3 - reserved for loading source pixel data - * d4, d5, d6, d7 - reserved for loading destination pixel data - * d24, d25, d26, d27 - reserved for loading mask pixel data - * d28, d29, d30, d31 - final destination pixel data for writeback to memory -@@ -626,48 +628,48 @@ 2: - process_pixblock_head, \ - process_pixblock_tail, \ - process_pixblock_tail_head, \ - dst_w_basereg_ = 28, \ - dst_r_basereg_ = 4, \ - src_basereg_ = 0, \ - mask_basereg_ = 24 - -- pixman_asm_function fname -+ pixman_asm_function \fname - - push {r4-r12, lr} /* save all registers */ - - /* - * Select prefetch type for this function. If prefetch distance is - * set to 0 or one of the color formats is 24bpp, SIMPLE prefetch - * has to be used instead of ADVANCED. - */ - .set PREFETCH_TYPE_CURRENT, PREFETCH_TYPE_DEFAULT --.if prefetch_distance == 0 -+.if \prefetch_distance == 0 - .set PREFETCH_TYPE_CURRENT, PREFETCH_TYPE_NONE - .elseif (PREFETCH_TYPE_CURRENT > PREFETCH_TYPE_SIMPLE) && \ -- ((src_bpp_ == 24) || (mask_bpp_ == 24) || (dst_w_bpp_ == 24)) -+ ((\src_bpp_ == 24) || (\mask_bpp_ == 24) || (\dst_w_bpp_ == 24)) - .set PREFETCH_TYPE_CURRENT, PREFETCH_TYPE_SIMPLE - .endif - - /* - * Make some macro arguments globally visible and accessible - * from other macros - */ -- .set src_bpp, src_bpp_ -- .set mask_bpp, mask_bpp_ -- .set dst_w_bpp, dst_w_bpp_ -- .set pixblock_size, pixblock_size_ -- .set dst_w_basereg, dst_w_basereg_ -- .set dst_r_basereg, dst_r_basereg_ -- .set src_basereg, src_basereg_ -- .set mask_basereg, mask_basereg_ -+ .set src_bpp, \src_bpp_ -+ .set mask_bpp, \mask_bpp_ -+ .set dst_w_bpp, \dst_w_bpp_ -+ .set pixblock_size, \pixblock_size_ -+ .set dst_w_basereg, \dst_w_basereg_ -+ .set dst_r_basereg, \dst_r_basereg_ -+ .set src_basereg, \src_basereg_ -+ .set mask_basereg, \mask_basereg_ - - .macro pixld_src x:vararg -- pixld x -+ pixld \x - .endm - .macro fetch_src_pixblock - pixld_src pixblock_size, src_bpp, \ - (src_basereg - pixblock_size * src_bpp / 64), SRC - .endm - /* - * Assign symbolic names to registers - */ -@@ -750,38 +752,38 @@ 2: - .elseif dst_w_bpp == 16 - .set dst_bpp_shift, 1 - .elseif dst_w_bpp == 8 - .set dst_bpp_shift, 0 - .else - .error "requested dst bpp (dst_w_bpp) is not supported" - .endif - --.if (((flags) & FLAG_DST_READWRITE) != 0) -+.if (((\flags) & FLAG_DST_READWRITE) != 0) - .set dst_r_bpp, dst_w_bpp - .else - .set dst_r_bpp, 0 - .endif --.if (((flags) & FLAG_DEINTERLEAVE_32BPP) != 0) -+.if (((\flags) & FLAG_DEINTERLEAVE_32BPP) != 0) - .set DEINTERLEAVE_32BPP_ENABLED, 1 - .else - .set DEINTERLEAVE_32BPP_ENABLED, 0 - .endif - --.if prefetch_distance < 0 || prefetch_distance > 15 -- .error "invalid prefetch distance (prefetch_distance)" -+.if \prefetch_distance < 0 || \prefetch_distance > 15 -+ .error "invalid prefetch distance (\prefetch_distance)" - .endif - - .if src_bpp > 0 - ldr SRC, [sp, #40] - .endif - .if mask_bpp > 0 - ldr MASK, [sp, #48] - .endif -- PF mov PF_X, #0 -+ PF mov, PF_X, #0 - .if src_bpp > 0 - ldr SRC_STRIDE, [sp, #44] - .endif - .if mask_bpp > 0 - ldr MASK_STRIDE, [sp, #52] - .endif - mov DST_R, DST_W - -@@ -796,24 +798,24 @@ 2: - .if dst_w_bpp == 24 - sub DST_STRIDE, DST_STRIDE, W - sub DST_STRIDE, DST_STRIDE, W, lsl #1 - .endif - - /* - * Setup advanced prefetcher initial state - */ -- PF mov PF_SRC, SRC -- PF mov PF_DST, DST_R -- PF mov PF_MASK, MASK -+ PF mov, PF_SRC, SRC -+ PF mov, PF_DST, DST_R -+ PF mov, PF_MASK, MASK - /* PF_CTL = prefetch_distance | ((h - 1) << 4) */ -- PF mov PF_CTL, H, lsl #4 -- PF add PF_CTL, #(prefetch_distance - 0x10) -+ PF mov, PF_CTL, H, lsl #4 -+ PF add, PF_CTL, #(\prefetch_distance - 0x10) - -- init -+ \init - .if regs_shortage - push {r0, r1} - .endif - subs H, H, #1 - .if regs_shortage - str H, [sp, #4] /* save updated height to stack */ - .else - mov ORIG_W, W -@@ -821,84 +823,84 @@ 2: - blt 9f - cmp W, #(pixblock_size * 2) - blt 8f - /* - * This is the start of the pipelined loop, which if optimized for - * long scanlines - */ - 0: -- ensure_destination_ptr_alignment process_pixblock_head, \ -- process_pixblock_tail, \ -- process_pixblock_tail_head -+ ensure_destination_ptr_alignment \process_pixblock_head, \ -+ \process_pixblock_tail, \ -+ \process_pixblock_tail_head - - /* Implement "head (tail_head) ... (tail_head) tail" loop pattern */ - pixld_a pixblock_size, dst_r_bpp, \ - (dst_r_basereg - pixblock_size * dst_r_bpp / 64), DST_R - fetch_src_pixblock - pixld pixblock_size, mask_bpp, \ - (mask_basereg - pixblock_size * mask_bpp / 64), MASK -- PF add PF_X, PF_X, #pixblock_size -- process_pixblock_head -+ PF add, PF_X, PF_X, #pixblock_size -+ \process_pixblock_head - cache_preload 0, pixblock_size - cache_preload_simple - subs W, W, #(pixblock_size * 2) - blt 2f - 1: -- process_pixblock_tail_head -+ \process_pixblock_tail_head - cache_preload_simple - subs W, W, #pixblock_size - bge 1b - 2: -- process_pixblock_tail -+ \process_pixblock_tail - pixst_a pixblock_size, dst_w_bpp, \ - (dst_w_basereg - pixblock_size * dst_w_bpp / 64), DST_W - - /* Process the remaining trailing pixels in the scanline */ - process_trailing_pixels 1, 1, \ -- process_pixblock_head, \ -- process_pixblock_tail, \ -- process_pixblock_tail_head -+ \process_pixblock_head, \ -+ \process_pixblock_tail, \ -+ \process_pixblock_tail_head - advance_to_next_scanline 0b - - .if regs_shortage - pop {r0, r1} - .endif -- cleanup -+ \cleanup - pop {r4-r12, pc} /* exit */ - /* - * This is the start of the loop, designed to process images with small width - * (less than pixblock_size * 2 pixels). In this case neither pipelining - * nor prefetch are used. - */ - 8: - /* Process exactly pixblock_size pixels if needed */ - tst W, #pixblock_size - beq 1f - pixld pixblock_size, dst_r_bpp, \ - (dst_r_basereg - pixblock_size * dst_r_bpp / 64), DST_R - fetch_src_pixblock - pixld pixblock_size, mask_bpp, \ - (mask_basereg - pixblock_size * mask_bpp / 64), MASK -- process_pixblock_head -- process_pixblock_tail -+ \process_pixblock_head -+ \process_pixblock_tail - pixst pixblock_size, dst_w_bpp, \ - (dst_w_basereg - pixblock_size * dst_w_bpp / 64), DST_W - 1: - /* Process the remaining trailing pixels in the scanline */ - process_trailing_pixels 0, 0, \ -- process_pixblock_head, \ -- process_pixblock_tail, \ -- process_pixblock_tail_head -+ \process_pixblock_head, \ -+ \process_pixblock_tail, \ -+ \process_pixblock_tail_head - advance_to_next_scanline 8b - 9: - .if regs_shortage - pop {r0, r1} - .endif -- cleanup -+ \cleanup - pop {r4-r12, pc} /* exit */ - - .purgem fetch_src_pixblock - .purgem pixld_src - - .unreq SRC - .unreq MASK - .unreq DST_R -@@ -910,17 +912,17 @@ 9: - .unreq DST_STRIDE - .unreq MASK_STRIDE - .unreq PF_CTL - .unreq PF_X - .unreq PF_SRC - .unreq PF_DST - .unreq PF_MASK - .unreq DUMMY -- .endfunc -+ pixman_end_asm_function - .endm - - /* - * A simplified variant of function generation template for a single - * scanline processing (for implementing pixman combine functions) - */ - .macro generate_composite_function_scanline use_nearest_scaling, \ - fname, \ -@@ -934,49 +936,49 @@ 9: - process_pixblock_head, \ - process_pixblock_tail, \ - process_pixblock_tail_head, \ - dst_w_basereg_ = 28, \ - dst_r_basereg_ = 4, \ - src_basereg_ = 0, \ - mask_basereg_ = 24 - -- pixman_asm_function fname -+ pixman_asm_function \fname - - .set PREFETCH_TYPE_CURRENT, PREFETCH_TYPE_NONE - /* - * Make some macro arguments globally visible and accessible - * from other macros - */ -- .set src_bpp, src_bpp_ -- .set mask_bpp, mask_bpp_ -- .set dst_w_bpp, dst_w_bpp_ -- .set pixblock_size, pixblock_size_ -- .set dst_w_basereg, dst_w_basereg_ -- .set dst_r_basereg, dst_r_basereg_ -- .set src_basereg, src_basereg_ -- .set mask_basereg, mask_basereg_ -+ .set src_bpp, \src_bpp_ -+ .set mask_bpp, \mask_bpp_ -+ .set dst_w_bpp, \dst_w_bpp_ -+ .set pixblock_size, \pixblock_size_ -+ .set dst_w_basereg, \dst_w_basereg_ -+ .set dst_r_basereg, \dst_r_basereg_ -+ .set src_basereg, \src_basereg_ -+ .set mask_basereg, \mask_basereg_ - --.if use_nearest_scaling != 0 -+.if \use_nearest_scaling != 0 - /* - * Assign symbolic names to registers for nearest scaling - */ - W .req r0 - DST_W .req r1 - SRC .req r2 - VX .req r3 - UNIT_X .req ip - MASK .req lr - TMP1 .req r4 - TMP2 .req r5 - DST_R .req r6 - SRC_WIDTH_FIXED .req r7 - - .macro pixld_src x:vararg -- pixld_s x -+ pixld_s \x - .endm - - ldr UNIT_X, [sp] - push {r4-r8, lr} - ldr SRC_WIDTH_FIXED, [sp, #(24 + 4)] - .if mask_bpp != 0 - ldr MASK, [sp, #(24 + 8)] - .endif -@@ -986,89 +988,89 @@ 9: - */ - W .req r0 /* width (is updated during processing) */ - DST_W .req r1 /* destination buffer pointer for writes */ - SRC .req r2 /* source buffer pointer */ - DST_R .req ip /* destination buffer pointer for reads */ - MASK .req r3 /* mask pointer */ - - .macro pixld_src x:vararg -- pixld x -+ pixld \x - .endm - .endif - --.if (((flags) & FLAG_DST_READWRITE) != 0) -+.if (((\flags) & FLAG_DST_READWRITE) != 0) - .set dst_r_bpp, dst_w_bpp - .else - .set dst_r_bpp, 0 - .endif --.if (((flags) & FLAG_DEINTERLEAVE_32BPP) != 0) -+.if (((\flags) & FLAG_DEINTERLEAVE_32BPP) != 0) - .set DEINTERLEAVE_32BPP_ENABLED, 1 - .else - .set DEINTERLEAVE_32BPP_ENABLED, 0 - .endif - - .macro fetch_src_pixblock - pixld_src pixblock_size, src_bpp, \ - (src_basereg - pixblock_size * src_bpp / 64), SRC - .endm - -- init -+ \init - mov DST_R, DST_W - - cmp W, #pixblock_size - blt 8f - -- ensure_destination_ptr_alignment process_pixblock_head, \ -- process_pixblock_tail, \ -- process_pixblock_tail_head -+ ensure_destination_ptr_alignment \process_pixblock_head, \ -+ \process_pixblock_tail, \ -+ \process_pixblock_tail_head - - subs W, W, #pixblock_size - blt 7f - - /* Implement "head (tail_head) ... (tail_head) tail" loop pattern */ - pixld_a pixblock_size, dst_r_bpp, \ - (dst_r_basereg - pixblock_size * dst_r_bpp / 64), DST_R - fetch_src_pixblock - pixld pixblock_size, mask_bpp, \ - (mask_basereg - pixblock_size * mask_bpp / 64), MASK -- process_pixblock_head -+ \process_pixblock_head - subs W, W, #pixblock_size - blt 2f - 1: -- process_pixblock_tail_head -+ \process_pixblock_tail_head - subs W, W, #pixblock_size - bge 1b - 2: -- process_pixblock_tail -+ \process_pixblock_tail - pixst_a pixblock_size, dst_w_bpp, \ - (dst_w_basereg - pixblock_size * dst_w_bpp / 64), DST_W - 7: - /* Process the remaining trailing pixels in the scanline (dst aligned) */ - process_trailing_pixels 0, 1, \ -- process_pixblock_head, \ -- process_pixblock_tail, \ -- process_pixblock_tail_head -+ \process_pixblock_head, \ -+ \process_pixblock_tail, \ -+ \process_pixblock_tail_head - -- cleanup --.if use_nearest_scaling != 0 -+ \cleanup -+.if \use_nearest_scaling != 0 - pop {r4-r8, pc} /* exit */ - .else - bx lr /* exit */ - .endif - 8: - /* Process the remaining trailing pixels in the scanline (dst unaligned) */ - process_trailing_pixels 0, 0, \ -- process_pixblock_head, \ -- process_pixblock_tail, \ -- process_pixblock_tail_head -+ \process_pixblock_head, \ -+ \process_pixblock_tail, \ -+ \process_pixblock_tail_head - -- cleanup -+ \cleanup - --.if use_nearest_scaling != 0 -+.if \use_nearest_scaling != 0 - pop {r4-r8, pc} /* exit */ - - .unreq DST_R - .unreq SRC - .unreq W - .unreq VX - .unreq UNIT_X - .unreq TMP1 -@@ -1085,25 +1087,25 @@ 8: - .unreq DST_R - .unreq DST_W - .unreq W - .endif - - .purgem fetch_src_pixblock - .purgem pixld_src - -- .endfunc -+ pixman_end_asm_function - .endm - - .macro generate_composite_function_single_scanline x:vararg -- generate_composite_function_scanline 0, x -+ generate_composite_function_scanline 0, \x - .endm - - .macro generate_composite_function_nearest_scanline x:vararg -- generate_composite_function_scanline 1, x -+ generate_composite_function_scanline 1, \x - .endm - - /* Default prologue/epilogue, nothing special needs to be done */ - - .macro default_init - .endm - - .macro default_cleanup -@@ -1129,56 +1131,56 @@ 8: - * Conversion of 8 r5g6b6 pixels packed in 128-bit register (in) - * into a planar a8r8g8b8 format (with a, r, g, b color components - * stored into 64-bit registers out_a, out_r, out_g, out_b respectively). - * - * Warning: the conversion is destructive and the original - * value (in) is lost. - */ - .macro convert_0565_to_8888 in, out_a, out_r, out_g, out_b -- vshrn.u16 out_r, in, #8 -- vshrn.u16 out_g, in, #3 -- vsli.u16 in, in, #5 -- vmov.u8 out_a, #255 -- vsri.u8 out_r, out_r, #5 -- vsri.u8 out_g, out_g, #6 -- vshrn.u16 out_b, in, #2 -+ vshrn.u16 \out_r, \in, #8 -+ vshrn.u16 \out_g, \in, #3 -+ vsli.u16 \in, \in, #5 -+ vmov.u8 \out_a, #255 -+ vsri.u8 \out_r, \out_r, #5 -+ vsri.u8 \out_g, \out_g, #6 -+ vshrn.u16 \out_b, \in, #2 - .endm - - .macro convert_0565_to_x888 in, out_r, out_g, out_b -- vshrn.u16 out_r, in, #8 -- vshrn.u16 out_g, in, #3 -- vsli.u16 in, in, #5 -- vsri.u8 out_r, out_r, #5 -- vsri.u8 out_g, out_g, #6 -- vshrn.u16 out_b, in, #2 -+ vshrn.u16 \out_r, \in, #8 -+ vshrn.u16 \out_g, \in, #3 -+ vsli.u16 \in, \in, #5 -+ vsri.u8 \out_r, \out_r, #5 -+ vsri.u8 \out_g, \out_g, #6 -+ vshrn.u16 \out_b, \in, #2 - .endm - - /* - * Conversion from planar a8r8g8b8 format (with a, r, g, b color components - * in 64-bit registers in_a, in_r, in_g, in_b respectively) into 8 r5g6b6 - * pixels packed in 128-bit register (out). Requires two temporary 128-bit - * registers (tmp1, tmp2) - */ - .macro convert_8888_to_0565 in_r, in_g, in_b, out, tmp1, tmp2 -- vshll.u8 tmp1, in_g, #8 -- vshll.u8 out, in_r, #8 -- vshll.u8 tmp2, in_b, #8 -- vsri.u16 out, tmp1, #5 -- vsri.u16 out, tmp2, #11 -+ vshll.u8 \tmp1, \in_g, #8 -+ vshll.u8 \out, \in_r, #8 -+ vshll.u8 \tmp2, \in_b, #8 -+ vsri.u16 \out, \tmp1, #5 -+ vsri.u16 \out, \tmp2, #11 - .endm - - /* - * Conversion of four r5g6b5 pixels (in) to four x8r8g8b8 pixels - * returned in (out0, out1) registers pair. Requires one temporary - * 64-bit register (tmp). 'out1' and 'in' may overlap, the original - * value from 'in' is lost - */ - .macro convert_four_0565_to_x888_packed in, out0, out1, tmp -- vshl.u16 out0, in, #5 /* G top 6 bits */ -- vshl.u16 tmp, in, #11 /* B top 5 bits */ -- vsri.u16 in, in, #5 /* R is ready in top bits */ -- vsri.u16 out0, out0, #6 /* G is ready in top bits */ -- vsri.u16 tmp, tmp, #5 /* B is ready in top bits */ -- vshr.u16 out1, in, #8 /* R is in place */ -- vsri.u16 out0, tmp, #8 /* G & B is in place */ -- vzip.u16 out0, out1 /* everything is in place */ -+ vshl.u16 \out0, \in, #5 /* G top 6 bits */ -+ vshl.u16 \tmp, \in, #11 /* B top 5 bits */ -+ vsri.u16 \in, \in, #5 /* R is ready in top bits */ -+ vsri.u16 \out0, \out0, #6 /* G is ready in top bits */ -+ vsri.u16 \tmp, \tmp, #5 /* B is ready in top bits */ -+ vshr.u16 \out1, \in, #8 /* R is in place */ -+ vsri.u16 \out0, \tmp, #8 /* G & B is in place */ -+ vzip.u16 \out0, \out1 /* everything is in place */ - .endm -diff --git a/gfx/cairo/libpixman/src/pixman-arm-simd-asm-scaled.S b/gfx/cairo/libpixman/src/pixman-arm-simd-asm-scaled.S ---- a/gfx/cairo/libpixman/src/pixman-arm-simd-asm-scaled.S -+++ b/gfx/cairo/libpixman/src/pixman-arm-simd-asm-scaled.S -@@ -20,16 +20,20 @@ - * AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING - * OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS - * SOFTWARE. - * - * Author: Jeff Muizelaar (jeff@infidigm.net) - * - */ - -+#ifdef __clang__ -+#define subpls subspl -+#endif -+ - /* Prevent the stack from becoming executable */ - #if defined(__linux__) && defined(__ELF__) - .section .note.GNU-stack,"",%progbits - #endif - - .text - .arch armv6 - .object_arch armv4 -@@ -57,100 +61,105 @@ - * prefetch_braking_distance - stop prefetching when that many pixels are - * remaining before the end of scanline - */ - - .macro generate_nearest_scanline_func fname, bpp_shift, t, \ - prefetch_distance, \ - prefetch_braking_distance - --pixman_asm_function fname -+pixman_asm_function \fname - W .req r0 - DST .req r1 - SRC .req r2 - VX .req r3 - UNIT_X .req ip - TMP1 .req r4 - TMP2 .req r5 - VXMASK .req r6 - PF_OFFS .req r7 - SRC_WIDTH_FIXED .req r8 - - ldr UNIT_X, [sp] - push {r4, r5, r6, r7, r8, r10} -- mvn VXMASK, #((1 << bpp_shift) - 1) -+ mvn VXMASK, #((1 << \bpp_shift) - 1) - ldr SRC_WIDTH_FIXED, [sp, #28] - - /* define helper macro */ - .macro scale_2_pixels -- ldr&t TMP1, [SRC, TMP1] -- and TMP2, VXMASK, VX, asr #(16 - bpp_shift) -+ ldr\()\t TMP1, [SRC, TMP1] -+ and TMP2, VXMASK, VX, asr #(16 - \bpp_shift) - adds VX, VX, UNIT_X -- str&t TMP1, [DST], #(1 << bpp_shift) -+ str\()\t TMP1, [DST], #(1 << \bpp_shift) - 9: subpls VX, VX, SRC_WIDTH_FIXED - bpl 9b - -- ldr&t TMP2, [SRC, TMP2] -- and TMP1, VXMASK, VX, asr #(16 - bpp_shift) -+ ldr\()\t TMP2, [SRC, TMP2] -+ and TMP1, VXMASK, VX, asr #(16 - \bpp_shift) - adds VX, VX, UNIT_X -- str&t TMP2, [DST], #(1 << bpp_shift) -+ str\()\t TMP2, [DST], #(1 << \bpp_shift) - 9: subpls VX, VX, SRC_WIDTH_FIXED - bpl 9b - .endm - - /* now do the scaling */ -- and TMP1, VXMASK, VX, asr #(16 - bpp_shift) -+ and TMP1, VXMASK, VX, asr #(16 - \bpp_shift) - adds VX, VX, UNIT_X - 9: subpls VX, VX, SRC_WIDTH_FIXED - bpl 9b -- subs W, W, #(8 + prefetch_braking_distance) -+ subs W, W, #(8 + \prefetch_braking_distance) - blt 2f - /* calculate prefetch offset */ -- mov PF_OFFS, #prefetch_distance -+ mov PF_OFFS, #\prefetch_distance - mla PF_OFFS, UNIT_X, PF_OFFS, VX - 1: /* main loop, process 8 pixels per iteration with prefetch */ -- pld [SRC, PF_OFFS, asr #(16 - bpp_shift)] -+ pld [SRC, PF_OFFS, asr #(16 - \bpp_shift)] - add PF_OFFS, UNIT_X, lsl #3 - scale_2_pixels - scale_2_pixels - scale_2_pixels - scale_2_pixels - subs W, W, #8 - bge 1b - 2: -- subs W, W, #(4 - 8 - prefetch_braking_distance) -+ subs W, W, #(4 - 8 - \prefetch_braking_distance) - blt 2f - 1: /* process the remaining pixels */ - scale_2_pixels - scale_2_pixels - subs W, W, #4 - bge 1b - 2: - tst W, #2 - beq 2f - scale_2_pixels - 2: - tst W, #1 -- ldrne&t TMP1, [SRC, TMP1] -- strne&t TMP1, [DST] -+#ifdef __clang__ -+ ldr\()\t\()ne TMP1, [SRC, TMP1] -+ str\()\t\()ne TMP1, [DST] -+#else -+ ldrne\()\t TMP1, [SRC, TMP1] -+ strne\()\t TMP1, [DST] -+#endif - /* cleanup helper macro */ - .purgem scale_2_pixels - .unreq DST - .unreq SRC - .unreq W - .unreq VX - .unreq UNIT_X - .unreq TMP1 - .unreq TMP2 - .unreq VXMASK - .unreq PF_OFFS - .unreq SRC_WIDTH_FIXED - /* return */ - pop {r4, r5, r6, r7, r8, r10} - bx lr --.endfunc -+pixman_end_asm_function - .endm - - generate_nearest_scanline_func \ - pixman_scaled_nearest_scanline_0565_0565_SRC_asm_armv6, 1, h, 80, 32 - - generate_nearest_scanline_func \ - pixman_scaled_nearest_scanline_8888_8888_SRC_asm_armv6, 2, , 48, 32 -diff --git a/gfx/cairo/libpixman/src/pixman-arm-simd-asm.S b/gfx/cairo/libpixman/src/pixman-arm-simd-asm.S ---- a/gfx/cairo/libpixman/src/pixman-arm-simd-asm.S -+++ b/gfx/cairo/libpixman/src/pixman-arm-simd-asm.S -@@ -20,16 +20,21 @@ - * AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING - * OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS - * SOFTWARE. - * - * Author: Ben Avison (bavison@riscosopen.org) - * - */ - -+#ifdef __clang__ -+#define adceqs adcseq -+#define ldmnedb ldmdbne -+#endif -+ - /* Prevent the stack from becoming executable */ - #if defined(__linux__) && defined(__ELF__) - .section .note.GNU-stack,"",%progbits - #endif - - .text - .arch armv6 - .object_arch armv4 -@@ -52,26 +57,26 @@ - * preload If outputting 16 bytes causes 64 bytes to be read, whether an extra preload should be output - */ - - .macro blit_init - line_saved_regs STRIDE_D, STRIDE_S - .endm - - .macro blit_process_head cond, numbytes, firstreg, unaligned_src, unaligned_mask, preload -- pixld cond, numbytes, firstreg, SRC, unaligned_src -+ pixld \cond, \numbytes, \firstreg, SRC, \unaligned_src - .endm - - .macro blit_inner_loop process_head, process_tail, unaligned_src, unaligned_mask, dst_alignment - WK4 .req STRIDE_D - WK5 .req STRIDE_S - WK6 .req MASK - WK7 .req STRIDE_M --110: pixld , 16, 0, SRC, unaligned_src -- pixld , 16, 4, SRC, unaligned_src -+110: pixld , 16, 0, SRC, \unaligned_src -+ pixld , 16, 4, SRC, \unaligned_src - pld [SRC, SCRATCH] - pixst , 16, 0, DST - pixst , 16, 4, DST - subs X, X, #32*8/src_bpp - bhs 110b - .unreq WK4 - .unreq WK5 - .unreq WK6 -@@ -137,17 +142,17 @@ generate_composite_function \ - mov STRIDE_M, SRC - .endm - - .macro fill_process_tail cond, numbytes, firstreg - WK4 .req SRC - WK5 .req STRIDE_S - WK6 .req MASK - WK7 .req STRIDE_M -- pixst cond, numbytes, 4, DST -+ pixst \cond, \numbytes, 4, DST - .unreq WK4 - .unreq WK5 - .unreq WK6 - .unreq WK7 - .endm - - generate_composite_function \ - pixman_composite_src_n_8888_asm_armv6, 0, 0, 32, \ -@@ -177,30 +182,30 @@ generate_composite_function \ - nop_macro, /* newline */ \ - nop_macro /* cleanup */ \ - nop_macro /* process head */ \ - fill_process_tail - - /******************************************************************************/ - - .macro src_x888_8888_pixel, cond, reg -- orr&cond WK®, WK®, #0xFF000000 -+ orr\()\cond WK\()\reg, WK\()\reg, #0xFF000000 - .endm - - .macro pixman_composite_src_x888_8888_process_head cond, numbytes, firstreg, unaligned_src, unaligned_mask, preload -- pixld cond, numbytes, firstreg, SRC, unaligned_src -+ pixld \cond, \numbytes, \firstreg, SRC, \unaligned_src - .endm - - .macro pixman_composite_src_x888_8888_process_tail cond, numbytes, firstreg -- src_x888_8888_pixel cond, %(firstreg+0) -- .if numbytes >= 8 -- src_x888_8888_pixel cond, %(firstreg+1) -- .if numbytes == 16 -- src_x888_8888_pixel cond, %(firstreg+2) -- src_x888_8888_pixel cond, %(firstreg+3) -+ src_x888_8888_pixel \cond, %(\firstreg+0) -+ .if \numbytes >= 8 -+ src_x888_8888_pixel \cond, %(\firstreg+1) -+ .if \numbytes == 16 -+ src_x888_8888_pixel \cond, %(\firstreg+2) -+ src_x888_8888_pixel \cond, %(\firstreg+3) - .endif - .endif - .endm - - generate_composite_function \ - pixman_composite_src_x888_8888_asm_armv6, 32, 0, 32, \ - FLAG_DST_WRITEONLY | FLAG_COND_EXEC | FLAG_PROCESS_PRESERVES_SCRATCH, \ - 3, /* prefetch distance */ \ -@@ -217,83 +222,83 @@ generate_composite_function \ - ldr MASK, =0x07E007E0 - mov STRIDE_M, #0xFF000000 - /* Set GE[3:0] to 1010 so SEL instructions do what we want */ - ldr SCRATCH, =0x80008000 - uadd8 SCRATCH, SCRATCH, SCRATCH - .endm - - .macro src_0565_8888_2pixels, reg1, reg2 -- and SCRATCH, WK®1, MASK @ 00000GGGGGG0000000000gggggg00000 -- bic WK®2, WK®1, MASK @ RRRRR000000BBBBBrrrrr000000bbbbb -- orr SCRATCH, SCRATCH, SCRATCH, lsr #6 @ 00000GGGGGGGGGGGG0000ggggggggggg -- mov WK®1, WK®2, lsl #16 @ rrrrr000000bbbbb0000000000000000 -- mov SCRATCH, SCRATCH, ror #19 @ GGGG0000ggggggggggg00000GGGGGGGG -- bic WK®2, WK®2, WK®1, lsr #16 @ RRRRR000000BBBBB0000000000000000 -- orr WK®1, WK®1, WK®1, lsr #5 @ rrrrrrrrrr0bbbbbbbbbb00000000000 -- orr WK®2, WK®2, WK®2, lsr #5 @ RRRRRRRRRR0BBBBBBBBBB00000000000 -- pkhtb WK®1, WK®1, WK®1, asr #5 @ rrrrrrrr--------bbbbbbbb-------- -- sel WK®1, WK®1, SCRATCH @ rrrrrrrrggggggggbbbbbbbb-------- -- mov SCRATCH, SCRATCH, ror #16 @ ggg00000GGGGGGGGGGGG0000gggggggg -- pkhtb WK®2, WK®2, WK®2, asr #5 @ RRRRRRRR--------BBBBBBBB-------- -- sel WK®2, WK®2, SCRATCH @ RRRRRRRRGGGGGGGGBBBBBBBB-------- -- orr WK®1, STRIDE_M, WK®1, lsr #8 @ 11111111rrrrrrrrggggggggbbbbbbbb -- orr WK®2, STRIDE_M, WK®2, lsr #8 @ 11111111RRRRRRRRGGGGGGGGBBBBBBBB -+ and SCRATCH, WK\()\reg1, MASK @ 00000GGGGGG0000000000gggggg00000 -+ bic WK\()\reg2, WK\()\reg1, MASK @ RRRRR000000BBBBBrrrrr000000bbbbb -+ orr SCRATCH, SCRATCH, SCRATCH, lsr #6 @ 00000GGGGGGGGGGGG0000ggggggggggg -+ mov WK\()\reg1, WK\()\reg2, lsl #16 @ rrrrr000000bbbbb0000000000000000 -+ mov SCRATCH, SCRATCH, ror #19 @ GGGG0000ggggggggggg00000GGGGGGGG -+ bic WK\()\reg2, WK\()\reg2, WK\()\reg1, lsr #16 @ RRRRR000000BBBBB0000000000000000 -+ orr WK\()\reg1, WK\()\reg1, WK\()\reg1, lsr #5 @ rrrrrrrrrr0bbbbbbbbbb00000000000 -+ orr WK\()\reg2, WK\()\reg2, WK\()\reg2, lsr #5 @ RRRRRRRRRR0BBBBBBBBBB00000000000 -+ pkhtb WK\()\reg1, WK\()\reg1, WK\()\reg1, asr #5 @ rrrrrrrr--------bbbbbbbb-------- -+ sel WK\()\reg1, WK\()\reg1, SCRATCH @ rrrrrrrrggggggggbbbbbbbb-------- -+ mov SCRATCH, SCRATCH, ror #16 @ ggg00000GGGGGGGGGGGG0000gggggggg -+ pkhtb WK\()\reg2, WK\()\reg2, WK\()\reg2, asr #5 @ RRRRRRRR--------BBBBBBBB-------- -+ sel WK\()\reg2, WK\()\reg2, SCRATCH @ RRRRRRRRGGGGGGGGBBBBBBBB-------- -+ orr WK\()\reg1, STRIDE_M, WK\()\reg1, lsr #8 @ 11111111rrrrrrrrggggggggbbbbbbbb -+ orr WK\()\reg2, STRIDE_M, WK\()\reg2, lsr #8 @ 11111111RRRRRRRRGGGGGGGGBBBBBBBB - .endm - - /* This version doesn't need STRIDE_M, but is one instruction longer. - It would however be preferable for an XRGB target, since we could knock off the last 2 instructions, but is that a common case? -- and SCRATCH, WK®1, MASK @ 00000GGGGGG0000000000gggggg00000 -- bic WK®1, WK®1, MASK @ RRRRR000000BBBBBrrrrr000000bbbbb -- orr SCRATCH, SCRATCH, SCRATCH, lsr #6 @ 00000GGGGGGGGGGGG0000ggggggggggg -- mov WK®2, WK®1, lsr #16 @ 0000000000000000RRRRR000000BBBBB -- mov SCRATCH, SCRATCH, ror #27 @ GGGGGGGGGGGG0000ggggggggggg00000 -- bic WK®1, WK®1, WK®2, lsl #16 @ 0000000000000000rrrrr000000bbbbb -- mov WK®2, WK®2, lsl #3 @ 0000000000000RRRRR000000BBBBB000 -- mov WK®1, WK®1, lsl #3 @ 0000000000000rrrrr000000bbbbb000 -- orr WK®2, WK®2, WK®2, lsr #5 @ 0000000000000RRRRRRRRRR0BBBBBBBB -- orr WK®1, WK®1, WK®1, lsr #5 @ 0000000000000rrrrrrrrrr0bbbbbbbb -- pkhbt WK®2, WK®2, WK®2, lsl #5 @ --------RRRRRRRR--------BBBBBBBB -- pkhbt WK®1, WK®1, WK®1, lsl #5 @ --------rrrrrrrr--------bbbbbbbb -- sel WK®2, SCRATCH, WK®2 @ --------RRRRRRRRGGGGGGGGBBBBBBBB -- sel WK®1, SCRATCH, WK®1 @ --------rrrrrrrrggggggggbbbbbbbb -- orr WK®2, WK®2, #0xFF000000 @ 11111111RRRRRRRRGGGGGGGGBBBBBBBB -- orr WK®1, WK®1, #0xFF000000 @ 11111111rrrrrrrrggggggggbbbbbbbb -+ and SCRATCH, WK\()\reg1, MASK @ 00000GGGGGG0000000000gggggg00000 -+ bic WK\()\reg1, WK\()\reg1, MASK @ RRRRR000000BBBBBrrrrr000000bbbbb -+ orr SCRATCH, SCRATCH, SCRATCH, lsr #6 @ 00000GGGGGGGGGGGG0000ggggggggggg -+ mov WK\()\reg2, WK\()\reg1, lsr #16 @ 0000000000000000RRRRR000000BBBBB -+ mov SCRATCH, SCRATCH, ror #27 @ GGGGGGGGGGGG0000ggggggggggg00000 -+ bic WK\()\reg1, WK\()\reg1, WK\()\reg2, lsl #16 @ 0000000000000000rrrrr000000bbbbb -+ mov WK\()\reg2, WK\()\reg2, lsl #3 @ 0000000000000RRRRR000000BBBBB000 -+ mov WK\()\reg1, WK\()\reg1, lsl #3 @ 0000000000000rrrrr000000bbbbb000 -+ orr WK\()\reg2, WK\()\reg2, WK\()\reg2, lsr #5 @ 0000000000000RRRRRRRRRR0BBBBBBBB -+ orr WK\()\reg1, WK\()\reg1, WK\()\reg1, lsr #5 @ 0000000000000rrrrrrrrrr0bbbbbbbb -+ pkhbt WK\()\reg2, WK\()\reg2, WK\()\reg2, lsl #5 @ --------RRRRRRRR--------BBBBBBBB -+ pkhbt WK\()\reg1, WK\()\reg1, WK\()\reg1, lsl #5 @ --------rrrrrrrr--------bbbbbbbb -+ sel WK\()\reg2, SCRATCH, WK\()\reg2 @ --------RRRRRRRRGGGGGGGGBBBBBBBB -+ sel WK\()\reg1, SCRATCH, WK\()\reg1 @ --------rrrrrrrrggggggggbbbbbbbb -+ orr WK\()\reg2, WK\()\reg2, #0xFF000000 @ 11111111RRRRRRRRGGGGGGGGBBBBBBBB -+ orr WK\()\reg1, WK\()\reg1, #0xFF000000 @ 11111111rrrrrrrrggggggggbbbbbbbb - */ - - .macro src_0565_8888_1pixel, reg -- bic SCRATCH, WK®, MASK @ 0000000000000000rrrrr000000bbbbb -- and WK®, WK®, MASK @ 000000000000000000000gggggg00000 -- mov SCRATCH, SCRATCH, lsl #3 @ 0000000000000rrrrr000000bbbbb000 -- mov WK®, WK®, lsl #5 @ 0000000000000000gggggg0000000000 -- orr SCRATCH, SCRATCH, SCRATCH, lsr #5 @ 0000000000000rrrrrrrrrr0bbbbbbbb -- orr WK®, WK®, WK®, lsr #6 @ 000000000000000gggggggggggg00000 -- pkhbt SCRATCH, SCRATCH, SCRATCH, lsl #5 @ --------rrrrrrrr--------bbbbbbbb -- sel WK®, WK®, SCRATCH @ --------rrrrrrrrggggggggbbbbbbbb -- orr WK®, WK®, #0xFF000000 @ 11111111rrrrrrrrggggggggbbbbbbbb -+ bic SCRATCH, WK\()\reg, MASK @ 0000000000000000rrrrr000000bbbbb -+ and WK\()\reg, WK\()\reg, MASK @ 000000000000000000000gggggg00000 -+ mov SCRATCH, SCRATCH, lsl #3 @ 0000000000000rrrrr000000bbbbb000 -+ mov WK\()\reg, WK\()\reg, lsl #5 @ 0000000000000000gggggg0000000000 -+ orr SCRATCH, SCRATCH, SCRATCH, lsr #5 @ 0000000000000rrrrrrrrrr0bbbbbbbb -+ orr WK\()\reg, WK\()\reg, WK\()\reg, lsr #6 @ 000000000000000gggggggggggg00000 -+ pkhbt SCRATCH, SCRATCH, SCRATCH, lsl #5 @ --------rrrrrrrr--------bbbbbbbb -+ sel WK\()\reg, WK\()\reg, SCRATCH @ --------rrrrrrrrggggggggbbbbbbbb -+ orr WK\()\reg, WK\()\reg, #0xFF000000 @ 11111111rrrrrrrrggggggggbbbbbbbb - .endm - - .macro src_0565_8888_process_head cond, numbytes, firstreg, unaligned_src, unaligned_mask, preload -- .if numbytes == 16 -- pixldst ld,, 8, firstreg, %(firstreg+2),,, SRC, unaligned_src -- .elseif numbytes == 8 -- pixld , 4, firstreg, SRC, unaligned_src -- .elseif numbytes == 4 -- pixld , 2, firstreg, SRC, unaligned_src -+ .if \numbytes == 16 -+ pixldst ld,, 8, \firstreg, %(\firstreg+2),,, SRC, \unaligned_src -+ .elseif \numbytes == 8 -+ pixld , 4, \firstreg, SRC, \unaligned_src -+ .elseif \numbytes == 4 -+ pixld , 2, \firstreg, SRC, \unaligned_src - .endif - .endm - - .macro src_0565_8888_process_tail cond, numbytes, firstreg -- .if numbytes == 16 -- src_0565_8888_2pixels firstreg, %(firstreg+1) -- src_0565_8888_2pixels %(firstreg+2), %(firstreg+3) -- .elseif numbytes == 8 -- src_0565_8888_2pixels firstreg, %(firstreg+1) -+ .if \numbytes == 16 -+ src_0565_8888_2pixels \firstreg, %(\firstreg+1) -+ src_0565_8888_2pixels %(\firstreg+2), %(\firstreg+3) -+ .elseif \numbytes == 8 -+ src_0565_8888_2pixels \firstreg, %(\firstreg+1) - .else -- src_0565_8888_1pixel firstreg -+ src_0565_8888_1pixel \firstreg - .endif - .endm - - generate_composite_function \ - pixman_composite_src_0565_8888_asm_armv6, 16, 0, 32, \ - FLAG_DST_WRITEONLY | FLAG_BRANCH_OVER, \ - 3, /* prefetch distance */ \ - src_0565_8888_init, \ -@@ -306,67 +311,67 @@ generate_composite_function \ - - .macro src_x888_0565_init - /* Hold loop invariant in MASK */ - ldr MASK, =0x001F001F - line_saved_regs STRIDE_S, ORIG_W - .endm - - .macro src_x888_0565_1pixel s, d -- and WK&d, MASK, WK&s, lsr #3 @ 00000000000rrrrr00000000000bbbbb -- and STRIDE_S, WK&s, #0xFC00 @ 0000000000000000gggggg0000000000 -- orr WK&d, WK&d, WK&d, lsr #5 @ 00000000000-----rrrrr000000bbbbb -- orr WK&d, WK&d, STRIDE_S, lsr #5 @ 00000000000-----rrrrrggggggbbbbb -+ and WK\()\d, MASK, WK\()\s, lsr #3 @ 00000000000rrrrr00000000000bbbbb -+ and STRIDE_S, WK\()\s, #0xFC00 @ 0000000000000000gggggg0000000000 -+ orr WK\()\d, WK\()\d, WK\()\d, lsr #5 @ 00000000000-----rrrrr000000bbbbb -+ orr WK\()\d, WK\()\d, STRIDE_S, lsr #5 @ 00000000000-----rrrrrggggggbbbbb - /* Top 16 bits are discarded during the following STRH */ - .endm - - .macro src_x888_0565_2pixels slo, shi, d, tmp -- and SCRATCH, WK&shi, #0xFC00 @ 0000000000000000GGGGGG0000000000 -- and WK&tmp, MASK, WK&shi, lsr #3 @ 00000000000RRRRR00000000000BBBBB -- and WK&shi, MASK, WK&slo, lsr #3 @ 00000000000rrrrr00000000000bbbbb -- orr WK&tmp, WK&tmp, WK&tmp, lsr #5 @ 00000000000-----RRRRR000000BBBBB -- orr WK&tmp, WK&tmp, SCRATCH, lsr #5 @ 00000000000-----RRRRRGGGGGGBBBBB -- and SCRATCH, WK&slo, #0xFC00 @ 0000000000000000gggggg0000000000 -- orr WK&shi, WK&shi, WK&shi, lsr #5 @ 00000000000-----rrrrr000000bbbbb -- orr WK&shi, WK&shi, SCRATCH, lsr #5 @ 00000000000-----rrrrrggggggbbbbb -- pkhbt WK&d, WK&shi, WK&tmp, lsl #16 @ RRRRRGGGGGGBBBBBrrrrrggggggbbbbb -+ and SCRATCH, WK\()\shi, #0xFC00 @ 0000000000000000GGGGGG0000000000 -+ and WK\()\tmp, MASK, WK\()\shi, lsr #3 @ 00000000000RRRRR00000000000BBBBB -+ and WK\()\shi, MASK, WK\()\slo, lsr #3 @ 00000000000rrrrr00000000000bbbbb -+ orr WK\()\tmp, WK\()\tmp, WK\()\tmp, lsr #5 @ 00000000000-----RRRRR000000BBBBB -+ orr WK\()\tmp, WK\()\tmp, SCRATCH, lsr #5 @ 00000000000-----RRRRRGGGGGGBBBBB -+ and SCRATCH, WK\()\slo, #0xFC00 @ 0000000000000000gggggg0000000000 -+ orr WK\()\shi, WK\()\shi, WK\()\shi, lsr #5 @ 00000000000-----rrrrr000000bbbbb -+ orr WK\()\shi, WK\()\shi, SCRATCH, lsr #5 @ 00000000000-----rrrrrggggggbbbbb -+ pkhbt WK\()\d, WK\()\shi, WK\()\tmp, lsl #16 @ RRRRRGGGGGGBBBBBrrrrrggggggbbbbb - .endm - - .macro src_x888_0565_process_head cond, numbytes, firstreg, unaligned_src, unaligned_mask, preload - WK4 .req STRIDE_S - WK5 .req STRIDE_M - WK6 .req WK3 - WK7 .req ORIG_W -- .if numbytes == 16 -+ .if \numbytes == 16 - pixld , 16, 4, SRC, 0 - src_x888_0565_2pixels 4, 5, 0, 0 - pixld , 8, 4, SRC, 0 - src_x888_0565_2pixels 6, 7, 1, 1 - pixld , 8, 6, SRC, 0 - .else -- pixld , numbytes*2, 4, SRC, 0 -+ pixld , \numbytes*2, 4, SRC, 0 - .endif - .endm - - .macro src_x888_0565_process_tail cond, numbytes, firstreg -- .if numbytes == 16 -+ .if \numbytes == 16 - src_x888_0565_2pixels 4, 5, 2, 2 - src_x888_0565_2pixels 6, 7, 3, 4 -- .elseif numbytes == 8 -+ .elseif \numbytes == 8 - src_x888_0565_2pixels 4, 5, 1, 1 - src_x888_0565_2pixels 6, 7, 2, 2 -- .elseif numbytes == 4 -+ .elseif \numbytes == 4 - src_x888_0565_2pixels 4, 5, 1, 1 - .else - src_x888_0565_1pixel 4, 1 - .endif -- .if numbytes == 16 -- pixst , numbytes, 0, DST -+ .if \numbytes == 16 -+ pixst , \numbytes, 0, DST - .else -- pixst , numbytes, 1, DST -+ pixst , \numbytes, 1, DST - .endif - .unreq WK4 - .unreq WK5 - .unreq WK6 - .unreq WK7 - .endm - - generate_composite_function \ -@@ -377,47 +382,47 @@ generate_composite_function \ - nop_macro, /* newline */ \ - nop_macro, /* cleanup */ \ - src_x888_0565_process_head, \ - src_x888_0565_process_tail - - /******************************************************************************/ - - .macro add_8_8_8pixels cond, dst1, dst2 -- uqadd8&cond WK&dst1, WK&dst1, MASK -- uqadd8&cond WK&dst2, WK&dst2, STRIDE_M -+ uqadd8\()\cond WK\()\dst1, WK\()\dst1, MASK -+ uqadd8\()\cond WK\()\dst2, WK\()\dst2, STRIDE_M - .endm - - .macro add_8_8_4pixels cond, dst -- uqadd8&cond WK&dst, WK&dst, MASK -+ uqadd8\()\cond WK\()\dst, WK\()\dst, MASK - .endm - - .macro add_8_8_process_head cond, numbytes, firstreg, unaligned_src, unaligned_mask, preload - WK4 .req MASK - WK5 .req STRIDE_M -- .if numbytes == 16 -- pixld cond, 8, 4, SRC, unaligned_src -- pixld cond, 16, firstreg, DST, 0 -- add_8_8_8pixels cond, firstreg, %(firstreg+1) -- pixld cond, 8, 4, SRC, unaligned_src -+ .if \numbytes == 16 -+ pixld \cond, 8, 4, SRC, \unaligned_src -+ pixld \cond, 16, \firstreg, DST, 0 -+ add_8_8_8pixels \cond, \firstreg, %(\firstreg+1) -+ pixld \cond, 8, 4, SRC, \unaligned_src - .else -- pixld cond, numbytes, 4, SRC, unaligned_src -- pixld cond, numbytes, firstreg, DST, 0 -+ pixld \cond, \numbytes, 4, SRC, \unaligned_src -+ pixld \cond, \numbytes, \firstreg, DST, 0 - .endif - .unreq WK4 - .unreq WK5 - .endm - - .macro add_8_8_process_tail cond, numbytes, firstreg -- .if numbytes == 16 -- add_8_8_8pixels cond, %(firstreg+2), %(firstreg+3) -- .elseif numbytes == 8 -- add_8_8_8pixels cond, firstreg, %(firstreg+1) -+ .if \numbytes == 16 -+ add_8_8_8pixels \cond, %(\firstreg+2), %(\firstreg+3) -+ .elseif \numbytes == 8 -+ add_8_8_8pixels \cond, \firstreg, %(\firstreg+1) - .else -- add_8_8_4pixels cond, firstreg -+ add_8_8_4pixels \cond, \firstreg - .endif - .endm - - generate_composite_function \ - pixman_composite_add_8_8_asm_armv6, 8, 0, 8, \ - FLAG_DST_READWRITE | FLAG_BRANCH_OVER | FLAG_PROCESS_PRESERVES_SCRATCH, \ - 2, /* prefetch distance */ \ - nop_macro, /* init */ \ -@@ -436,82 +441,82 @@ generate_composite_function \ - line_saved_regs STRIDE_D, STRIDE_S, ORIG_W - .endm - - .macro over_8888_8888_process_head cond, numbytes, firstreg, unaligned_src, unaligned_mask, preload - WK4 .req STRIDE_D - WK5 .req STRIDE_S - WK6 .req STRIDE_M - WK7 .req ORIG_W -- pixld , numbytes, %(4+firstreg), SRC, unaligned_src -- pixld , numbytes, firstreg, DST, 0 -+ pixld , \numbytes, %(4+\firstreg), SRC, \unaligned_src -+ pixld , \numbytes, \firstreg, DST, 0 - .unreq WK4 - .unreq WK5 - .unreq WK6 - .unreq WK7 - .endm - - .macro over_8888_8888_check_transparent numbytes, reg0, reg1, reg2, reg3 - /* Since these colours a premultiplied by alpha, only 0 indicates transparent (any other colour with 0 in the alpha byte is luminous) */ -- teq WK®0, #0 -- .if numbytes > 4 -- teqeq WK®1, #0 -- .if numbytes > 8 -- teqeq WK®2, #0 -- teqeq WK®3, #0 -+ teq WK\()\reg0, #0 -+ .if \numbytes > 4 -+ teqeq WK\()\reg1, #0 -+ .if \numbytes > 8 -+ teqeq WK\()\reg2, #0 -+ teqeq WK\()\reg3, #0 - .endif - .endif - .endm - - .macro over_8888_8888_prepare next -- mov WK&next, WK&next, lsr #24 -+ mov WK\()\next, WK\()\next, lsr #24 - .endm - - .macro over_8888_8888_1pixel src, dst, offset, next - /* src = destination component multiplier */ -- rsb WK&src, WK&src, #255 -+ rsb WK\()\src, WK\()\src, #255 - /* Split even/odd bytes of dst into SCRATCH/dst */ -- uxtb16 SCRATCH, WK&dst -- uxtb16 WK&dst, WK&dst, ror #8 -+ uxtb16 SCRATCH, WK\()\dst -+ uxtb16 WK\()\dst, WK\()\dst, ror #8 - /* Multiply through, adding 0.5 to the upper byte of result for rounding */ -- mla SCRATCH, SCRATCH, WK&src, MASK -- mla WK&dst, WK&dst, WK&src, MASK -+ mla SCRATCH, SCRATCH, WK\()\src, MASK -+ mla WK\()\dst, WK\()\dst, WK\()\src, MASK - /* Where we would have had a stall between the result of the first MLA and the shifter input, - * reload the complete source pixel */ -- ldr WK&src, [SRC, #offset] -+ ldr WK\()\src, [SRC, #\offset] - /* Multiply by 257/256 to approximate 256/255 */ - uxtab16 SCRATCH, SCRATCH, SCRATCH, ror #8 - /* In this stall, start processing the next pixel */ -- .if offset < -4 -- mov WK&next, WK&next, lsr #24 -+ .if \offset < -4 -+ mov WK\()\next, WK\()\next, lsr #24 - .endif -- uxtab16 WK&dst, WK&dst, WK&dst, ror #8 -+ uxtab16 WK\()\dst, WK\()\dst, WK\()\dst, ror #8 - /* Recombine even/odd bytes of multiplied destination */ - mov SCRATCH, SCRATCH, ror #8 -- sel WK&dst, SCRATCH, WK&dst -+ sel WK\()\dst, SCRATCH, WK\()\dst - /* Saturated add of source to multiplied destination */ -- uqadd8 WK&dst, WK&dst, WK&src -+ uqadd8 WK\()\dst, WK\()\dst, WK\()\src - .endm - - .macro over_8888_8888_process_tail cond, numbytes, firstreg - WK4 .req STRIDE_D - WK5 .req STRIDE_S - WK6 .req STRIDE_M - WK7 .req ORIG_W -- over_8888_8888_check_transparent numbytes, %(4+firstreg), %(5+firstreg), %(6+firstreg), %(7+firstreg) -+ over_8888_8888_check_transparent \numbytes, %(4+\firstreg), %(5+\firstreg), %(6+\firstreg), %(7+\firstreg) - beq 10f -- over_8888_8888_prepare %(4+firstreg) -- .set PROCESS_REG, firstreg -- .set PROCESS_OFF, -numbytes -- .rept numbytes / 4 -+ over_8888_8888_prepare %(4+\firstreg) -+ .set PROCESS_REG, \firstreg -+ .set PROCESS_OFF, -\numbytes -+ .rept \numbytes / 4 - over_8888_8888_1pixel %(4+PROCESS_REG), %(0+PROCESS_REG), PROCESS_OFF, %(5+PROCESS_REG) - .set PROCESS_REG, PROCESS_REG+1 - .set PROCESS_OFF, PROCESS_OFF+4 - .endr -- pixst , numbytes, firstreg, DST -+ pixst , \numbytes, \firstreg, DST - 10: - .unreq WK4 - .unreq WK5 - .unreq WK6 - .unreq WK7 - .endm - - generate_composite_function \ -@@ -531,26 +536,26 @@ generate_composite_function \ - * word Register containing 4 bytes - * byte Register containing byte multiplier (bits 8-31 must be 0) - * tmp Scratch register - * half Register containing the constant 0x00800080 - * GE[3:0] bits must contain 0101 - */ - .macro mul_8888_8 word, byte, tmp, half - /* Split even/odd bytes of word apart */ -- uxtb16 tmp, word -- uxtb16 word, word, ror #8 -+ uxtb16 \tmp, \word -+ uxtb16 \word, \word, ror #8 - /* Multiply bytes together with rounding, then by 257/256 */ -- mla tmp, tmp, byte, half -- mla word, word, byte, half /* 1 stall follows */ -- uxtab16 tmp, tmp, tmp, ror #8 /* 1 stall follows */ -- uxtab16 word, word, word, ror #8 -+ mla \tmp, \tmp, \byte, \half -+ mla \word, \word, \byte, \half /* 1 stall follows */ -+ uxtab16 \tmp, \tmp, \tmp, ror #8 /* 1 stall follows */ -+ uxtab16 \word, \word, \word, ror #8 - /* Recombine bytes */ -- mov tmp, tmp, ror #8 -- sel word, tmp, word -+ mov \tmp, \tmp, ror #8 -+ sel \word, \tmp, \word - .endm - - /******************************************************************************/ - - .macro over_8888_n_8888_init - /* Mask is constant */ - ldr MASK, [sp, #ARGS_STACK_OFFSET+8] - /* Hold loop invariant in STRIDE_M */ -@@ -562,51 +567,51 @@ generate_composite_function \ - line_saved_regs Y, STRIDE_D, STRIDE_S, ORIG_W - .endm - - .macro over_8888_n_8888_process_head cond, numbytes, firstreg, unaligned_src, unaligned_mask, preload - WK4 .req Y - WK5 .req STRIDE_D - WK6 .req STRIDE_S - WK7 .req ORIG_W -- pixld , numbytes, %(4+(firstreg%2)), SRC, unaligned_src -- pixld , numbytes, firstreg, DST, 0 -+ pixld , \numbytes, %(4+(\firstreg%2)), SRC, \unaligned_src -+ pixld , \numbytes, \firstreg, DST, 0 - .unreq WK4 - .unreq WK5 - .unreq WK6 - .unreq WK7 - .endm - - .macro over_8888_n_8888_1pixel src, dst -- mul_8888_8 WK&src, MASK, SCRATCH, STRIDE_M -- sub WK7, WK6, WK&src, lsr #24 -- mul_8888_8 WK&dst, WK7, SCRATCH, STRIDE_M -- uqadd8 WK&dst, WK&dst, WK&src -+ mul_8888_8 WK\()\src, MASK, SCRATCH, STRIDE_M -+ sub WK7, WK6, WK\()\src, lsr #24 -+ mul_8888_8 WK\()\dst, WK7, SCRATCH, STRIDE_M -+ uqadd8 WK\()\dst, WK\()\dst, WK\()\src - .endm - - .macro over_8888_n_8888_process_tail cond, numbytes, firstreg - WK4 .req Y - WK5 .req STRIDE_D - WK6 .req STRIDE_S - WK7 .req ORIG_W -- over_8888_8888_check_transparent numbytes, %(4+(firstreg%2)), %(5+(firstreg%2)), %(6+firstreg), %(7+firstreg) -+ over_8888_8888_check_transparent \numbytes, %(4+(\firstreg%2)), %(5+(\firstreg%2)), %(6+\firstreg), %(7+\firstreg) - beq 10f - mov WK6, #255 -- .set PROCESS_REG, firstreg -- .rept numbytes / 4 -- .if numbytes == 16 && PROCESS_REG == 2 -+ .set PROCESS_REG, \firstreg -+ .rept \numbytes / 4 -+ .if \numbytes == 16 && PROCESS_REG == 2 - /* We're using WK6 and WK7 as temporaries, so half way through - * 4 pixels, reload the second two source pixels but this time - * into WK4 and WK5 */ - ldmdb SRC, {WK4, WK5} - .endif - over_8888_n_8888_1pixel %(4+(PROCESS_REG%2)), %(PROCESS_REG) - .set PROCESS_REG, PROCESS_REG+1 - .endr -- pixst , numbytes, firstreg, DST -+ pixst , \numbytes, \firstreg, DST - 10: - .unreq WK4 - .unreq WK5 - .unreq WK6 - .unreq WK7 - .endm - - generate_composite_function \ -@@ -637,47 +642,47 @@ generate_composite_function \ - ldr STRIDE_D, =0x00800080 - b 1f - .ltorg - 1: - .endm - - .macro over_n_8_8888_process_head cond, numbytes, firstreg, unaligned_src, unaligned_mask, preload - WK4 .req STRIDE_M -- pixld , numbytes/4, 4, MASK, unaligned_mask -- pixld , numbytes, firstreg, DST, 0 -+ pixld , \numbytes/4, 4, MASK, \unaligned_mask -+ pixld , \numbytes, \firstreg, DST, 0 - .unreq WK4 - .endm - - .macro over_n_8_8888_1pixel src, dst -- uxtb Y, WK4, ror #src*8 -+ uxtb Y, WK4, ror #\src*8 - /* Trailing part of multiplication of source */ - mla SCRATCH, STRIDE_S, Y, STRIDE_D - mla Y, SRC, Y, STRIDE_D - mov ORIG_W, #255 - uxtab16 SCRATCH, SCRATCH, SCRATCH, ror #8 - uxtab16 Y, Y, Y, ror #8 - mov SCRATCH, SCRATCH, ror #8 - sub ORIG_W, ORIG_W, Y, lsr #24 - sel Y, SCRATCH, Y - /* Then multiply the destination */ -- mul_8888_8 WK&dst, ORIG_W, SCRATCH, STRIDE_D -- uqadd8 WK&dst, WK&dst, Y -+ mul_8888_8 WK\()\dst, ORIG_W, SCRATCH, STRIDE_D -+ uqadd8 WK\()\dst, WK\()\dst, Y - .endm - - .macro over_n_8_8888_process_tail cond, numbytes, firstreg - WK4 .req STRIDE_M - teq WK4, #0 - beq 10f -- .set PROCESS_REG, firstreg -- .rept numbytes / 4 -- over_n_8_8888_1pixel %(PROCESS_REG-firstreg), %(PROCESS_REG) -+ .set PROCESS_REG, \firstreg -+ .rept \numbytes / 4 -+ over_n_8_8888_1pixel %(PROCESS_REG-\firstreg), %(PROCESS_REG) - .set PROCESS_REG, PROCESS_REG+1 - .endr -- pixst , numbytes, firstreg, DST -+ pixst , \numbytes, \firstreg, DST - 10: - .unreq WK4 - .endm - - generate_composite_function \ - pixman_composite_over_n_8_8888_asm_armv6, 0, 8, 32 \ - FLAG_DST_READWRITE | FLAG_BRANCH_OVER | FLAG_PROCESS_CORRUPTS_PSR | FLAG_PROCESS_DOES_STORE | FLAG_SPILL_LINE_VARS \ - 2, /* prefetch distance */ \ -@@ -700,64 +705,64 @@ generate_composite_function \ - line_saved_regs STRIDE_D, ORIG_W - .endm - - .macro over_reverse_n_8888_newline - mov STRIDE_D, #0xFF - .endm - - .macro over_reverse_n_8888_process_head cond, numbytes, firstreg, unaligned_src, unaligned_mask, preload -- pixld , numbytes, firstreg, DST, 0 -+ pixld , \numbytes, \firstreg, DST, 0 - .endm - - .macro over_reverse_n_8888_1pixel d, is_only -- teq WK&d, #0 -+ teq WK\()\d, #0 - beq 8f /* replace with source */ -- bics ORIG_W, STRIDE_D, WK&d, lsr #24 -- .if is_only == 1 -+ bics ORIG_W, STRIDE_D, WK\()\d, lsr #24 -+ .if \is_only == 1 - beq 49f /* skip store */ - .else - beq 9f /* write same value back */ - .endif - mla SCRATCH, STRIDE_S, ORIG_W, MASK /* red/blue */ - mla ORIG_W, STRIDE_M, ORIG_W, MASK /* alpha/green */ - uxtab16 SCRATCH, SCRATCH, SCRATCH, ror #8 - uxtab16 ORIG_W, ORIG_W, ORIG_W, ror #8 - mov SCRATCH, SCRATCH, ror #8 - sel ORIG_W, SCRATCH, ORIG_W -- uqadd8 WK&d, WK&d, ORIG_W -+ uqadd8 WK\()\d, WK\()\d, ORIG_W - b 9f --8: mov WK&d, SRC -+8: mov WK\()\d, SRC - 9: - .endm - - .macro over_reverse_n_8888_tail numbytes, reg1, reg2, reg3, reg4 -- .if numbytes == 4 -- over_reverse_n_8888_1pixel reg1, 1 -+ .if \numbytes == 4 -+ over_reverse_n_8888_1pixel \reg1, 1 - .else -- and SCRATCH, WK®1, WK®2 -- .if numbytes == 16 -- and SCRATCH, SCRATCH, WK®3 -- and SCRATCH, SCRATCH, WK®4 -+ and SCRATCH, WK\()\reg1, WK\()\reg2 -+ .if \numbytes == 16 -+ and SCRATCH, SCRATCH, WK\()\reg3 -+ and SCRATCH, SCRATCH, WK\()\reg4 - .endif - mvns SCRATCH, SCRATCH, asr #24 - beq 49f /* skip store if all opaque */ -- over_reverse_n_8888_1pixel reg1, 0 -- over_reverse_n_8888_1pixel reg2, 0 -- .if numbytes == 16 -- over_reverse_n_8888_1pixel reg3, 0 -- over_reverse_n_8888_1pixel reg4, 0 -+ over_reverse_n_8888_1pixel \reg1, 0 -+ over_reverse_n_8888_1pixel \reg2, 0 -+ .if \numbytes == 16 -+ over_reverse_n_8888_1pixel \reg3, 0 -+ over_reverse_n_8888_1pixel \reg4, 0 - .endif - .endif -- pixst , numbytes, reg1, DST -+ pixst , \numbytes, \reg1, DST - 49: - .endm - - .macro over_reverse_n_8888_process_tail cond, numbytes, firstreg -- over_reverse_n_8888_tail numbytes, firstreg, %(firstreg+1), %(firstreg+2), %(firstreg+3) -+ over_reverse_n_8888_tail \numbytes, \firstreg, %(\firstreg+1), %(\firstreg+2), %(\firstreg+3) - .endm - - generate_composite_function \ - pixman_composite_over_reverse_n_8888_asm_armv6, 0, 0, 32 \ - FLAG_DST_READWRITE | FLAG_BRANCH_OVER | FLAG_PROCESS_CORRUPTS_PSR | FLAG_PROCESS_DOES_STORE | FLAG_SPILL_LINE_VARS | FLAG_PROCESS_CORRUPTS_SCRATCH, \ - 3, /* prefetch distance */ \ - over_reverse_n_8888_init, \ - over_reverse_n_8888_newline, \ -@@ -789,30 +794,30 @@ generate_composite_function \ - .unreq TMP1 - .unreq TMP2 - .unreq TMP3 - .unreq WK4 - .endm - - .macro over_white_8888_8888_ca_combine m, d - uxtb16 TMP1, TMP0 /* rb_notmask */ -- uxtb16 TMP2, d /* rb_dest; 1 stall follows */ -+ uxtb16 TMP2, \d /* rb_dest; 1 stall follows */ - smlatt TMP3, TMP2, TMP1, HALF /* red */ - smlabb TMP2, TMP2, TMP1, HALF /* blue */ - uxtb16 TMP0, TMP0, ror #8 /* ag_notmask */ -- uxtb16 TMP1, d, ror #8 /* ag_dest; 1 stall follows */ -- smlatt d, TMP1, TMP0, HALF /* alpha */ -+ uxtb16 TMP1, \d, ror #8 /* ag_dest; 1 stall follows */ -+ smlatt \d, TMP1, TMP0, HALF /* alpha */ - smlabb TMP1, TMP1, TMP0, HALF /* green */ - pkhbt TMP0, TMP2, TMP3, lsl #16 /* rb; 1 stall follows */ -- pkhbt TMP1, TMP1, d, lsl #16 /* ag */ -+ pkhbt TMP1, TMP1, \d, lsl #16 /* ag */ - uxtab16 TMP0, TMP0, TMP0, ror #8 - uxtab16 TMP1, TMP1, TMP1, ror #8 - mov TMP0, TMP0, ror #8 -- sel d, TMP0, TMP1 -- uqadd8 d, d, m /* d is a late result */ -+ sel \d, TMP0, TMP1 -+ uqadd8 \d, \d, \m /* d is a late result */ - .endm - - .macro over_white_8888_8888_ca_1pixel_head - pixld , 4, 1, MASK, 0 - pixld , 4, 3, DST, 0 - .endm - - .macro over_white_8888_8888_ca_1pixel_tail -@@ -848,29 +853,29 @@ 02: mvn TMP0, WK2 - movcs WK4, WK2 - b 04f - 03: over_white_8888_8888_ca_combine WK2, WK4 - 04: pixst , 8, 3, DST - 05: - .endm - - .macro over_white_8888_8888_ca_process_head cond, numbytes, firstreg, unaligned_src, unaligned_mask, preload -- .if numbytes == 4 -+ .if \numbytes == 4 - over_white_8888_8888_ca_1pixel_head - .else -- .if numbytes == 16 -+ .if \numbytes == 16 - over_white_8888_8888_ca_2pixels_head - over_white_8888_8888_ca_2pixels_tail - .endif - over_white_8888_8888_ca_2pixels_head - .endif - .endm - - .macro over_white_8888_8888_ca_process_tail cond, numbytes, firstreg -- .if numbytes == 4 -+ .if \numbytes == 4 - over_white_8888_8888_ca_1pixel_tail - .else - over_white_8888_8888_ca_2pixels_tail - .endif - .endm - - generate_composite_function \ - pixman_composite_over_white_8888_8888_ca_asm_armv6, 0, 32, 32 \ -@@ -999,33 +1004,33 @@ 20: /* No simplifications possible - - uqadd8 WK0, WK1, WK2 /* followed by 1 stall */ - 30: /* The destination buffer is already in the L1 cache, so - * there's little point in amalgamating writes */ - pixst , 4, 0, DST - 40: - .endm - - .macro over_n_8888_8888_ca_process_head cond, numbytes, firstreg, unaligned_src, unaligned_mask, preload -- .rept (numbytes / 4) - 1 -+ .rept (\numbytes / 4) - 1 - over_n_8888_8888_ca_1pixel_head - over_n_8888_8888_ca_1pixel_tail - .endr - over_n_8888_8888_ca_1pixel_head - .endm - - .macro over_n_8888_8888_ca_process_tail cond, numbytes, firstreg - over_n_8888_8888_ca_1pixel_tail - .endm - - pixman_asm_function pixman_composite_over_n_8888_8888_ca_asm_armv6 - ldr ip, [sp] - cmp ip, #-1 - beq pixman_composite_over_white_8888_8888_ca_asm_armv6 - /* else drop through... */ -- .endfunc -+ pixman_end_asm_function - generate_composite_function \ - pixman_composite_over_n_8888_8888_ca_asm_armv6_helper, 0, 32, 32 \ - FLAG_DST_READWRITE | FLAG_BRANCH_OVER | FLAG_PROCESS_CORRUPTS_PSR | FLAG_PROCESS_DOES_STORE | FLAG_SPILL_LINE_VARS | FLAG_PROCESS_CORRUPTS_SCRATCH | FLAG_PROCESS_CORRUPTS_WK0 \ - 2, /* prefetch distance */ \ - over_n_8888_8888_ca_init, \ - nop_macro, /* newline */ \ - over_n_8888_8888_ca_cleanup, \ - over_n_8888_8888_ca_process_head, \ -@@ -1040,94 +1045,94 @@ generate_composite_function \ - uadd8 SCRATCH, MASK, MASK - /* Offset the source pointer: we only need the alpha bytes */ - add SRC, SRC, #3 - line_saved_regs ORIG_W - .endm - - .macro in_reverse_8888_8888_head numbytes, reg1, reg2, reg3 - ldrb ORIG_W, [SRC], #4 -- .if numbytes >= 8 -- ldrb WK®1, [SRC], #4 -- .if numbytes == 16 -- ldrb WK®2, [SRC], #4 -- ldrb WK®3, [SRC], #4 -+ .if \numbytes >= 8 -+ ldrb WK\()\reg1, [SRC], #4 -+ .if \numbytes == 16 -+ ldrb WK\()\reg2, [SRC], #4 -+ ldrb WK\()\reg3, [SRC], #4 - .endif - .endif -- add DST, DST, #numbytes -+ add DST, DST, #\numbytes - .endm - - .macro in_reverse_8888_8888_process_head cond, numbytes, firstreg, unaligned_src, unaligned_mask, preload -- in_reverse_8888_8888_head numbytes, firstreg, %(firstreg+1), %(firstreg+2) -+ in_reverse_8888_8888_head \numbytes, \firstreg, %(\firstreg+1), %(\firstreg+2) - .endm - - .macro in_reverse_8888_8888_1pixel s, d, offset, is_only -- .if is_only != 1 -- movs s, ORIG_W -- .if offset != 0 -- ldrb ORIG_W, [SRC, #offset] -+ .if \is_only != 1 -+ movs \s, ORIG_W -+ .if \offset != 0 -+ ldrb ORIG_W, [SRC, #\offset] - .endif - beq 01f - teq STRIDE_M, #0xFF - beq 02f - .endif -- uxtb16 SCRATCH, d /* rb_dest */ -- uxtb16 d, d, ror #8 /* ag_dest */ -- mla SCRATCH, SCRATCH, s, MASK -- mla d, d, s, MASK -+ uxtb16 SCRATCH, \d /* rb_dest */ -+ uxtb16 \d, \d, ror #8 /* ag_dest */ -+ mla SCRATCH, SCRATCH, \s, MASK -+ mla \d, \d, \s, MASK - uxtab16 SCRATCH, SCRATCH, SCRATCH, ror #8 -- uxtab16 d, d, d, ror #8 -+ uxtab16 \d, \d, \d, ror #8 - mov SCRATCH, SCRATCH, ror #8 -- sel d, SCRATCH, d -+ sel \d, SCRATCH, \d - b 02f -- .if offset == 0 -+ .if \offset == 0 - 48: /* Last mov d,#0 of the set - used as part of shortcut for - * source values all 0 */ - .endif --01: mov d, #0 -+01: mov \d, #0 - 02: - .endm - - .macro in_reverse_8888_8888_tail numbytes, reg1, reg2, reg3, reg4 -- .if numbytes == 4 -+ .if \numbytes == 4 - teq ORIG_W, ORIG_W, asr #32 -- ldrne WK®1, [DST, #-4] -- .elseif numbytes == 8 -- teq ORIG_W, WK®1 -+ ldrne WK\()\reg1, [DST, #-4] -+ .elseif \numbytes == 8 -+ teq ORIG_W, WK\()\reg1 - teqeq ORIG_W, ORIG_W, asr #32 /* all 0 or all -1? */ -- ldmnedb DST, {WK®1-WK®2} -+ ldmnedb DST, {WK\()\reg1-WK\()\reg2} - .else -- teq ORIG_W, WK®1 -- teqeq ORIG_W, WK®2 -- teqeq ORIG_W, WK®3 -+ teq ORIG_W, WK\()\reg1 -+ teqeq ORIG_W, WK\()\reg2 -+ teqeq ORIG_W, WK\()\reg3 - teqeq ORIG_W, ORIG_W, asr #32 /* all 0 or all -1? */ -- ldmnedb DST, {WK®1-WK®4} -+ ldmnedb DST, {WK\()\reg1-WK\()\reg4} - .endif - cmnne DST, #0 /* clear C if NE */ - bcs 49f /* no writes to dest if source all -1 */ - beq 48f /* set dest to all 0 if source all 0 */ -- .if numbytes == 4 -- in_reverse_8888_8888_1pixel ORIG_W, WK®1, 0, 1 -- str WK®1, [DST, #-4] -- .elseif numbytes == 8 -- in_reverse_8888_8888_1pixel STRIDE_M, WK®1, -4, 0 -- in_reverse_8888_8888_1pixel STRIDE_M, WK®2, 0, 0 -- stmdb DST, {WK®1-WK®2} -+ .if \numbytes == 4 -+ in_reverse_8888_8888_1pixel ORIG_W, WK\()\reg1, 0, 1 -+ str WK\()\reg1, [DST, #-4] -+ .elseif \numbytes == 8 -+ in_reverse_8888_8888_1pixel STRIDE_M, WK\()\reg1, -4, 0 -+ in_reverse_8888_8888_1pixel STRIDE_M, WK\()\reg2, 0, 0 -+ stmdb DST, {WK\()\reg1-WK\()\reg2} - .else -- in_reverse_8888_8888_1pixel STRIDE_M, WK®1, -12, 0 -- in_reverse_8888_8888_1pixel STRIDE_M, WK®2, -8, 0 -- in_reverse_8888_8888_1pixel STRIDE_M, WK®3, -4, 0 -- in_reverse_8888_8888_1pixel STRIDE_M, WK®4, 0, 0 -- stmdb DST, {WK®1-WK®4} -+ in_reverse_8888_8888_1pixel STRIDE_M, WK\()\reg1, -12, 0 -+ in_reverse_8888_8888_1pixel STRIDE_M, WK\()\reg2, -8, 0 -+ in_reverse_8888_8888_1pixel STRIDE_M, WK\()\reg3, -4, 0 -+ in_reverse_8888_8888_1pixel STRIDE_M, WK\()\reg4, 0, 0 -+ stmdb DST, {WK\()\reg1-WK\()\reg4} - .endif - 49: - .endm - - .macro in_reverse_8888_8888_process_tail cond, numbytes, firstreg -- in_reverse_8888_8888_tail numbytes, firstreg, %(firstreg+1), %(firstreg+2), %(firstreg+3) -+ in_reverse_8888_8888_tail \numbytes, \firstreg, %(\firstreg+1), %(\firstreg+2), %(\firstreg+3) - .endm - - generate_composite_function \ - pixman_composite_in_reverse_8888_8888_asm_armv6, 32, 0, 32 \ - FLAG_DST_READWRITE | FLAG_BRANCH_OVER | FLAG_PROCESS_CORRUPTS_PSR | FLAG_PROCESS_DOES_STORE | FLAG_SPILL_LINE_VARS | FLAG_PROCESS_CORRUPTS_SCRATCH | FLAG_NO_PRELOAD_DST \ - 2, /* prefetch distance */ \ - in_reverse_8888_8888_init, \ - nop_macro, /* newline */ \ -@@ -1144,31 +1149,31 @@ generate_composite_function \ - /* Hold multiplier for destination in STRIDE_M */ - mov STRIDE_M, #255 - sub STRIDE_M, STRIDE_M, SRC, lsr #24 - /* Set GE[3:0] to 0101 so SEL instructions do what we want */ - uadd8 SCRATCH, MASK, MASK - .endm - - .macro over_n_8888_process_head cond, numbytes, firstreg, unaligned_src, unaligned_mask, preload -- pixld , numbytes, firstreg, DST, 0 -+ pixld , \numbytes, \firstreg, DST, 0 - .endm - - .macro over_n_8888_1pixel dst -- mul_8888_8 WK&dst, STRIDE_M, SCRATCH, MASK -- uqadd8 WK&dst, WK&dst, SRC -+ mul_8888_8 WK\()\dst, STRIDE_M, SCRATCH, MASK -+ uqadd8 WK\()\dst, WK\()\dst, SRC - .endm - - .macro over_n_8888_process_tail cond, numbytes, firstreg -- .set PROCESS_REG, firstreg -- .rept numbytes / 4 -+ .set PROCESS_REG, \firstreg -+ .rept \numbytes / 4 - over_n_8888_1pixel %(PROCESS_REG) - .set PROCESS_REG, PROCESS_REG+1 - .endr -- pixst , numbytes, firstreg, DST -+ pixst , \numbytes, \firstreg, DST - .endm - - generate_composite_function \ - pixman_composite_over_n_8888_asm_armv6, 0, 0, 32 \ - FLAG_DST_READWRITE | FLAG_BRANCH_OVER | FLAG_PROCESS_DOES_STORE \ - 2, /* prefetch distance */ \ - over_n_8888_init, \ - nop_macro, /* newline */ \ -diff --git a/gfx/cairo/libpixman/src/pixman-arm-simd-asm.h b/gfx/cairo/libpixman/src/pixman-arm-simd-asm.h ---- a/gfx/cairo/libpixman/src/pixman-arm-simd-asm.h -+++ b/gfx/cairo/libpixman/src/pixman-arm-simd-asm.h -@@ -107,88 +107,120 @@ - .set PREFETCH_TYPE_NONE, 0 - .set PREFETCH_TYPE_STANDARD, 1 - - /* - * Definitions of macros for load/store of pixel data. - */ - - .macro pixldst op, cond=al, numbytes, reg0, reg1, reg2, reg3, base, unaligned=0 -- .if numbytes == 16 -- .if unaligned == 1 -- op&r&cond WK®0, [base], #4 -- op&r&cond WK®1, [base], #4 -- op&r&cond WK®2, [base], #4 -- op&r&cond WK®3, [base], #4 -+ .if \numbytes == 16 -+ .if \unaligned == 1 -+ \op\()r\()\cond WK\()\reg0, [\base], #4 -+ \op\()r\()\cond WK\()\reg1, [\base], #4 -+ \op\()r\()\cond WK\()\reg2, [\base], #4 -+ \op\()r\()\cond WK\()\reg3, [\base], #4 - .else -- op&m&cond&ia base!, {WK®0,WK®1,WK®2,WK®3} -+#ifdef __clang__ -+ \op\()mia\()\cond \base!, {WK\()\reg0,WK\()\reg1,WK\()\reg2,WK\()\reg3} -+#else -+ \op\()m\()\cond\()ia \base!, {WK\()\reg0,WK\()\reg1,WK\()\reg2,WK\()\reg3} -+#endif - .endif -- .elseif numbytes == 8 -- .if unaligned == 1 -- op&r&cond WK®0, [base], #4 -- op&r&cond WK®1, [base], #4 -+ .elseif \numbytes == 8 -+ .if \unaligned == 1 -+ \op\()r\()\cond WK\()\reg0, [\base], #4 -+ \op\()r\()\cond WK\()\reg1, [\base], #4 - .else -- op&m&cond&ia base!, {WK®0,WK®1} -+#ifdef __clang__ -+ \op\()mia\()\cond \base!, {WK\()\reg0,WK\()\reg1} -+#else -+ \op\()m\()\cond\()ia \base!, {WK\()\reg0,WK\()\reg1} -+#endif - .endif -- .elseif numbytes == 4 -- op&r&cond WK®0, [base], #4 -- .elseif numbytes == 2 -- op&r&cond&h WK®0, [base], #2 -- .elseif numbytes == 1 -- op&r&cond&b WK®0, [base], #1 -+ .elseif \numbytes == 4 -+ \op\()r\()\cond WK\()\reg0, [\base], #4 -+ .elseif \numbytes == 2 -+#ifdef __clang__ -+ \op\()rh\()\cond WK\()\reg0, [\base], #2 -+#else -+ \op\()r\()\cond\()h WK\()\reg0, [\base], #2 -+#endif -+ .elseif \numbytes == 1 -+#ifdef __clang__ -+ \op\()rb\()\cond WK\()\reg0, [\base], #1 -+#else -+ \op\()r\()\cond\()b WK\()\reg0, [\base], #1 -+#endif - .else -- .error "unsupported size: numbytes" -+ .error "unsupported size: \numbytes" - .endif - .endm - - .macro pixst_baseupdated cond, numbytes, reg0, reg1, reg2, reg3, base -- .if numbytes == 16 -- stm&cond&db base, {WK®0,WK®1,WK®2,WK®3} -- .elseif numbytes == 8 -- stm&cond&db base, {WK®0,WK®1} -- .elseif numbytes == 4 -- str&cond WK®0, [base, #-4] -- .elseif numbytes == 2 -- str&cond&h WK®0, [base, #-2] -- .elseif numbytes == 1 -- str&cond&b WK®0, [base, #-1] -+ .if \numbytes == 16 -+#ifdef __clang__ -+ stm\()\cond\()db \base, {WK\()\reg0,WK\()\reg1,WK\()\reg2,WK\()\reg3} -+#else -+ stmdb\()\cond \base, {WK\()\reg0,WK\()\reg1,WK\()\reg2,WK\()\reg3} -+#endif -+ .elseif \numbytes == 8 -+#ifdef __clang__ -+ stmdb\()\cond \base, {WK\()\reg0,WK\()\reg1} -+#else -+ stm\()\cond\()db \base, {WK\()\reg0,WK\()\reg1} -+#endif -+ .elseif \numbytes == 4 -+ str\()\cond WK\()\reg0, [\base, #-4] -+ .elseif \numbytes == 2 -+#ifdef __clang__ -+ strh\()\cond WK\()\reg0, [\base, #-2] -+#else -+ str\()\cond\()h WK\()\reg0, [\base, #-2] -+#endif -+ .elseif \numbytes == 1 -+#ifdef __clang__ -+ strb\()\cond WK\()\reg0, [\base, #-1] -+#else -+ str\()\cond\()b WK\()\reg0, [\base, #-1] -+#endif - .else -- .error "unsupported size: numbytes" -+ .error "unsupported size: \numbytes" - .endif - .endm - - .macro pixld cond, numbytes, firstreg, base, unaligned -- pixldst ld, cond, numbytes, %(firstreg+0), %(firstreg+1), %(firstreg+2), %(firstreg+3), base, unaligned -+ pixldst ld, \cond, \numbytes, %(\firstreg+0), %(\firstreg+1), %(\firstreg+2), %(\firstreg+3), \base, \unaligned - .endm - - .macro pixst cond, numbytes, firstreg, base - .if (flags) & FLAG_DST_READWRITE -- pixst_baseupdated cond, numbytes, %(firstreg+0), %(firstreg+1), %(firstreg+2), %(firstreg+3), base -+ pixst_baseupdated \cond, \numbytes, %(\firstreg+0), %(\firstreg+1), %(\firstreg+2), %(\firstreg+3), \base - .else -- pixldst st, cond, numbytes, %(firstreg+0), %(firstreg+1), %(firstreg+2), %(firstreg+3), base -+ pixldst st, \cond, \numbytes, %(\firstreg+0), %(\firstreg+1), %(\firstreg+2), %(\firstreg+3), \base - .endif - .endm - - .macro PF a, x:vararg - .if (PREFETCH_TYPE_CURRENT == PREFETCH_TYPE_STANDARD) -- a x -+ \a \x - .endif - .endm - - - .macro preload_leading_step1 bpp, ptr, base - /* If the destination is already 16-byte aligned, then we need to preload - * between 0 and prefetch_distance (inclusive) cache lines ahead so there - * are no gaps when the inner loop starts. - */ -- .if bpp > 0 -- PF bic, ptr, base, #31 -+ .if \bpp > 0 -+ PF bic, \ptr, \base, #31 - .set OFFSET, 0 - .rept prefetch_distance+1 -- PF pld, [ptr, #OFFSET] -+ PF pld, [\ptr, #OFFSET] - .set OFFSET, OFFSET+32 - .endr - .endif - .endm - - .macro preload_leading_step2 bpp, bpp_shift, ptr, base - /* However, if the destination is not 16-byte aligned, we may need to - * preload more cache lines than that. The question we need to ask is: -@@ -196,81 +228,81 @@ - * by which the source pointer will be rounded down for preloading, and if - * so, by how many cache lines? Effectively, we want to calculate - * leading_bytes = ((-dst)&15)*src_bpp/dst_bpp - * inner_loop_offset = (src+leading_bytes)&31 - * extra_needed = leading_bytes - inner_loop_offset - * and test if extra_needed is <= 0, <= 32, or > 32 (where > 32 is only - * possible when there are 4 src bytes for every 1 dst byte). - */ -- .if bpp > 0 -- .ifc base,DST -+ .if \bpp > 0 -+ .ifc \base,DST - /* The test can be simplified further when preloading the destination */ -- PF tst, base, #16 -+ PF tst, \base, #16 - PF beq, 61f - .else -- .if bpp/dst_w_bpp == 4 -- PF add, SCRATCH, base, WK0, lsl #bpp_shift-dst_bpp_shift -+ .if \bpp/dst_w_bpp == 4 -+ PF add, SCRATCH, \base, WK0, lsl #\bpp_shift-dst_bpp_shift - PF and, SCRATCH, SCRATCH, #31 -- PF rsb, SCRATCH, SCRATCH, WK0, lsl #bpp_shift-dst_bpp_shift -+ PF rsb, SCRATCH, SCRATCH, WK0, lsl #\bpp_shift-dst_bpp_shift - PF sub, SCRATCH, SCRATCH, #1 /* so now ranges are -16..-1 / 0..31 / 32..63 */ - PF movs, SCRATCH, SCRATCH, lsl #32-6 /* so this sets NC / nc / Nc */ - PF bcs, 61f - PF bpl, 60f - PF pld, [ptr, #32*(prefetch_distance+2)] - .else -- PF mov, SCRATCH, base, lsl #32-5 -- PF add, SCRATCH, SCRATCH, WK0, lsl #32-5+bpp_shift-dst_bpp_shift -- PF rsbs, SCRATCH, SCRATCH, WK0, lsl #32-5+bpp_shift-dst_bpp_shift -+ PF mov, SCRATCH, \base, lsl #32-5 -+ PF add, SCRATCH, SCRATCH, WK0, lsl #32-5+\bpp_shift-dst_bpp_shift -+ PF rsbs, SCRATCH, SCRATCH, WK0, lsl #32-5+\bpp_shift-dst_bpp_shift - PF bls, 61f - .endif - .endif --60: PF pld, [ptr, #32*(prefetch_distance+1)] -+60: PF pld, [\ptr, #32*(prefetch_distance+1)] - 61: - .endif - .endm - - #define IS_END_OF_GROUP(INDEX,SIZE) ((SIZE) < 2 || ((INDEX) & ~((INDEX)+1)) & ((SIZE)/2)) - .macro preload_middle bpp, base, scratch_holds_offset -- .if bpp > 0 -+ .if \bpp > 0 - /* prefetch distance = 256/bpp, stm distance = 128/dst_w_bpp */ -- .if IS_END_OF_GROUP(SUBBLOCK,256/128*dst_w_bpp/bpp) -- .if scratch_holds_offset -- PF pld, [base, SCRATCH] -+ .if IS_END_OF_GROUP(SUBBLOCK,256/128*dst_w_bpp/\bpp) -+ .if \scratch_holds_offset -+ PF pld, [\base, SCRATCH] - .else -- PF bic, SCRATCH, base, #31 -+ PF bic, SCRATCH, \base, #31 - PF pld, [SCRATCH, #32*prefetch_distance] - .endif - .endif - .endif - .endm - - .macro preload_trailing bpp, bpp_shift, base -- .if bpp > 0 -- .if bpp*pix_per_block > 256 -+ .if \bpp > 0 -+ .if \bpp*pix_per_block > 256 - /* Calculations are more complex if more than one fetch per block */ -- PF and, WK1, base, #31 -- PF add, WK1, WK1, WK0, lsl #bpp_shift -- PF add, WK1, WK1, #32*(bpp*pix_per_block/256-1)*(prefetch_distance+1) -- PF bic, SCRATCH, base, #31 -+ PF and, WK1, \base, #31 -+ PF add, WK1, WK1, WK0, lsl #\bpp_shift -+ PF add, WK1, WK1, #32*(\bpp*pix_per_block/256-1)*(prefetch_distance+1) -+ PF bic, SCRATCH, \base, #31 - 80: PF pld, [SCRATCH, #32*(prefetch_distance+1)] - PF add, SCRATCH, SCRATCH, #32 - PF subs, WK1, WK1, #32 - PF bhi, 80b - .else - /* If exactly one fetch per block, then we need either 0, 1 or 2 extra preloads */ -- PF mov, SCRATCH, base, lsl #32-5 -- PF adds, SCRATCH, SCRATCH, X, lsl #32-5+bpp_shift -+ PF mov, SCRATCH, \base, lsl #32-5 -+ PF adds, SCRATCH, SCRATCH, X, lsl #32-5+\bpp_shift - PF adceqs, SCRATCH, SCRATCH, #0 - /* The instruction above has two effects: ensures Z is only - * set if C was clear (so Z indicates that both shifted quantities - * were 0), and clears C if Z was set (so C indicates that the sum - * of the shifted quantities was greater and not equal to 32) */ - PF beq, 82f -- PF bic, SCRATCH, base, #31 -+ PF bic, SCRATCH, \base, #31 - PF bcc, 81f - PF pld, [SCRATCH, #32*(prefetch_distance+2)] - 81: PF pld, [SCRATCH, #32*(prefetch_distance+1)] - 82: - .endif - .endif - .endm - -@@ -283,97 +315,97 @@ 82: - * pixels) they cannot possibly straddle more than 2 32-byte cachelines, - * meaning there's no need for a loop. - * "bpp" - number of bits per pixel in the channel (source, mask or - * destination) that's being preloaded, or 0 if this channel is not used - * for reading - * "bpp_shift" - log2 of ("bpp"/8) (except if "bpp"=0 of course) - * "base" - base address register of channel to preload (SRC, MASK or DST) - */ -- .if bpp > 0 -- .if narrow_case && (bpp <= dst_w_bpp) -+ .if \bpp > 0 -+ .if \narrow_case && (\bpp <= dst_w_bpp) - /* In these cases, each line for each channel is in either 1 or 2 cache lines */ -- PF bic, WK0, base, #31 -+ PF bic, WK0, \base, #31 - PF pld, [WK0] -- PF add, WK1, base, X, LSL #bpp_shift -+ PF add, WK1, \base, X, LSL #\bpp_shift - PF sub, WK1, WK1, #1 - PF bic, WK1, WK1, #31 - PF cmp, WK1, WK0 - PF beq, 90f - PF pld, [WK1] - 90: - .else -- PF bic, WK0, base, #31 -+ PF bic, WK0, \base, #31 - PF pld, [WK0] -- PF add, WK1, base, X, lsl #bpp_shift -+ PF add, WK1, \base, X, lsl #\bpp_shift - PF sub, WK1, WK1, #1 - PF bic, WK1, WK1, #31 - PF cmp, WK1, WK0 - PF beq, 92f - 91: PF add, WK0, WK0, #32 - PF cmp, WK0, WK1 - PF pld, [WK0] - PF bne, 91b - 92: - .endif - .endif - .endm - - - .macro conditional_process1_helper cond, process_head, process_tail, numbytes, firstreg, unaligned_src, unaligned_mask, decrementx -- process_head cond, numbytes, firstreg, unaligned_src, unaligned_mask, 0 -- .if decrementx -- sub&cond X, X, #8*numbytes/dst_w_bpp -+ \process_head \cond, \numbytes, \firstreg, \unaligned_src, \unaligned_mask, 0 -+ .if \decrementx -+ sub\()\cond X, X, #8*\numbytes/dst_w_bpp - .endif -- process_tail cond, numbytes, firstreg -+ \process_tail \cond, \numbytes, \firstreg - .if !((flags) & FLAG_PROCESS_DOES_STORE) -- pixst cond, numbytes, firstreg, DST -+ pixst \cond, \numbytes, \firstreg, DST - .endif - .endm - - .macro conditional_process1 cond, process_head, process_tail, numbytes, firstreg, unaligned_src, unaligned_mask, decrementx - .if (flags) & FLAG_BRANCH_OVER -- .ifc cond,mi -+ .ifc \cond,mi - bpl 100f - .endif -- .ifc cond,cs -+ .ifc \cond,cs - bcc 100f - .endif -- .ifc cond,ne -+ .ifc \cond,ne - beq 100f - .endif -- conditional_process1_helper , process_head, process_tail, numbytes, firstreg, unaligned_src, unaligned_mask, decrementx -+ conditional_process1_helper , \process_head, \process_tail, \numbytes, \firstreg, \unaligned_src, \unaligned_mask, \decrementx - 100: - .else -- conditional_process1_helper cond, process_head, process_tail, numbytes, firstreg, unaligned_src, unaligned_mask, decrementx -+ conditional_process1_helper \cond, \process_head, \process_tail, \numbytes, \firstreg, \unaligned_src, \unaligned_mask, \decrementx - .endif - .endm - - .macro conditional_process2 test, cond1, cond2, process_head, process_tail, numbytes1, numbytes2, firstreg1, firstreg2, unaligned_src, unaligned_mask, decrementx - .if (flags) & (FLAG_DST_READWRITE | FLAG_BRANCH_OVER | FLAG_PROCESS_CORRUPTS_PSR | FLAG_PROCESS_DOES_STORE) - /* Can't interleave reads and writes */ -- test -- conditional_process1 cond1, process_head, process_tail, numbytes1, firstreg1, unaligned_src, unaligned_mask, decrementx -+ \test -+ conditional_process1 \cond1, \process_head, \process_tail, \numbytes1, \firstreg1, \unaligned_src, \unaligned_mask, \decrementx - .if (flags) & FLAG_PROCESS_CORRUPTS_PSR -- test -+ \test - .endif -- conditional_process1 cond2, process_head, process_tail, numbytes2, firstreg2, unaligned_src, unaligned_mask, decrementx -+ conditional_process1 \cond2, \process_head, \process_tail, \numbytes2, \firstreg2, \unaligned_src, \unaligned_mask, \decrementx - .else - /* Can interleave reads and writes for better scheduling */ -- test -- process_head cond1, numbytes1, firstreg1, unaligned_src, unaligned_mask, 0 -- process_head cond2, numbytes2, firstreg2, unaligned_src, unaligned_mask, 0 -- .if decrementx -- sub&cond1 X, X, #8*numbytes1/dst_w_bpp -- sub&cond2 X, X, #8*numbytes2/dst_w_bpp -+ \test -+ \process_head \cond1, \numbytes1, \firstreg1, \unaligned_src, \unaligned_mask, 0 -+ \process_head \cond2, \numbytes2, \firstreg2, \unaligned_src, \unaligned_mask, 0 -+ .if \decrementx -+ sub\()\cond1 X, X, #8*\numbytes1/dst_w_bpp -+ sub\()\cond2 X, X, #8*\numbytes2/dst_w_bpp - .endif -- process_tail cond1, numbytes1, firstreg1 -- process_tail cond2, numbytes2, firstreg2 -- pixst cond1, numbytes1, firstreg1, DST -- pixst cond2, numbytes2, firstreg2, DST -+ \process_tail \cond1, \numbytes1, \firstreg1 -+ \process_tail \cond2, \numbytes2, \firstreg2 -+ pixst \cond1, \numbytes1, \firstreg1, DST -+ pixst \cond2, \numbytes2, \firstreg2, DST - .endif - .endm - - - .macro test_bits_1_0_ptr - .if (flags) & FLAG_PROCESS_CORRUPTS_WK0 - movs SCRATCH, X, lsl #32-1 /* C,N = bits 1,0 of DST */ - .else -@@ -395,22 +427,22 @@ 100: - .if (flags) & FLAG_PROCESS_CORRUPTS_WK0 - .set DECREMENT_X, 0 - sub X, X, WK0, lsr #dst_bpp_shift - str X, [sp, #LINE_SAVED_REG_COUNT*4] - mov X, WK0 - .endif - /* Use unaligned loads in all cases for simplicity */ - .if dst_w_bpp == 8 -- conditional_process2 test_bits_1_0_ptr, mi, cs, process_head, process_tail, 1, 2, 1, 2, 1, 1, DECREMENT_X -+ conditional_process2 test_bits_1_0_ptr, mi, cs, \process_head, \process_tail, 1, 2, 1, 2, 1, 1, DECREMENT_X - .elseif dst_w_bpp == 16 - test_bits_1_0_ptr -- conditional_process1 cs, process_head, process_tail, 2, 2, 1, 1, DECREMENT_X -+ conditional_process1 cs, \process_head, \process_tail, 2, 2, 1, 1, DECREMENT_X - .endif -- conditional_process2 test_bits_3_2_ptr, mi, cs, process_head, process_tail, 4, 8, 1, 2, 1, 1, DECREMENT_X -+ conditional_process2 test_bits_3_2_ptr, mi, cs, \process_head, \process_tail, 4, 8, 1, 2, 1, 1, DECREMENT_X - .if (flags) & FLAG_PROCESS_CORRUPTS_WK0 - ldr X, [sp, #LINE_SAVED_REG_COUNT*4] - .endif - .endm - - .macro test_bits_3_2_pix - movs SCRATCH, X, lsl #dst_bpp_shift+32-3 - .endm -@@ -419,169 +451,169 @@ 100: - .if dst_w_bpp == 8 - movs SCRATCH, X, lsl #dst_bpp_shift+32-1 - .else - movs SCRATCH, X, lsr #1 - .endif - .endm - - .macro trailing_15bytes process_head, process_tail, unaligned_src, unaligned_mask -- conditional_process2 test_bits_3_2_pix, cs, mi, process_head, process_tail, 8, 4, 0, 2, unaligned_src, unaligned_mask, 0 -+ conditional_process2 test_bits_3_2_pix, cs, mi, \process_head, \process_tail, 8, 4, 0, 2, \unaligned_src, \unaligned_mask, 0 - .if dst_w_bpp == 16 - test_bits_1_0_pix -- conditional_process1 cs, process_head, process_tail, 2, 0, unaligned_src, unaligned_mask, 0 -+ conditional_process1 cs, \process_head, \process_tail, 2, 0, \unaligned_src, \unaligned_mask, 0 - .elseif dst_w_bpp == 8 -- conditional_process2 test_bits_1_0_pix, cs, mi, process_head, process_tail, 2, 1, 0, 1, unaligned_src, unaligned_mask, 0 -+ conditional_process2 test_bits_1_0_pix, cs, mi, \process_head, \process_tail, 2, 1, 0, 1, \unaligned_src, \unaligned_mask, 0 - .endif - .endm - - - .macro wide_case_inner_loop process_head, process_tail, unaligned_src, unaligned_mask, dst_alignment - 110: - .set SUBBLOCK, 0 /* this is a count of STMs; there can be up to 8 STMs per block */ - .rept pix_per_block*dst_w_bpp/128 -- process_head , 16, 0, unaligned_src, unaligned_mask, 1 -+ \process_head , 16, 0, \unaligned_src, \unaligned_mask, 1 - .if (src_bpp > 0) && (mask_bpp == 0) && ((flags) & FLAG_PROCESS_PRESERVES_SCRATCH) - preload_middle src_bpp, SRC, 1 - .elseif (src_bpp == 0) && (mask_bpp > 0) && ((flags) & FLAG_PROCESS_PRESERVES_SCRATCH) - preload_middle mask_bpp, MASK, 1 - .else - preload_middle src_bpp, SRC, 0 - preload_middle mask_bpp, MASK, 0 - .endif - .if (dst_r_bpp > 0) && ((SUBBLOCK % 2) == 0) && (((flags) & FLAG_NO_PRELOAD_DST) == 0) - /* Because we know that writes are 16-byte aligned, it's relatively easy to ensure that - * destination prefetches are 32-byte aligned. It's also the easiest channel to offset - * preloads for, to achieve staggered prefetches for multiple channels, because there are - * always two STMs per prefetch, so there is always an opposite STM on which to put the - * preload. Note, no need to BIC the base register here */ -- PF pld, [DST, #32*prefetch_distance - dst_alignment] -+ PF pld, [DST, #32*prefetch_distance - \dst_alignment] - .endif -- process_tail , 16, 0 -+ \process_tail , 16, 0 - .if !((flags) & FLAG_PROCESS_DOES_STORE) - pixst , 16, 0, DST - .endif - .set SUBBLOCK, SUBBLOCK+1 - .endr - subs X, X, #pix_per_block - bhs 110b - .endm - - .macro wide_case_inner_loop_and_trailing_pixels process_head, process_tail, process_inner_loop, exit_label, unaligned_src, unaligned_mask - /* Destination now 16-byte aligned; we have at least one block before we have to stop preloading */ - .if dst_r_bpp > 0 - tst DST, #16 - bne 111f -- process_inner_loop process_head, process_tail, unaligned_src, unaligned_mask, 16 + DST_PRELOAD_BIAS -+ \process_inner_loop \process_head, \process_tail, \unaligned_src, \unaligned_mask, 16 + DST_PRELOAD_BIAS - b 112f - 111: - .endif -- process_inner_loop process_head, process_tail, unaligned_src, unaligned_mask, 0 + DST_PRELOAD_BIAS -+ \process_inner_loop \process_head, \process_tail, \unaligned_src, \unaligned_mask, 0 + DST_PRELOAD_BIAS - 112: - /* Just before the final (prefetch_distance+1) 32-byte blocks, deal with final preloads */ - .if (src_bpp*pix_per_block > 256) || (mask_bpp*pix_per_block > 256) || (dst_r_bpp*pix_per_block > 256) - PF and, WK0, X, #pix_per_block-1 - .endif - preload_trailing src_bpp, src_bpp_shift, SRC - preload_trailing mask_bpp, mask_bpp_shift, MASK - .if ((flags) & FLAG_NO_PRELOAD_DST) == 0 - preload_trailing dst_r_bpp, dst_bpp_shift, DST - .endif - add X, X, #(prefetch_distance+2)*pix_per_block - 128/dst_w_bpp - /* The remainder of the line is handled identically to the medium case */ -- medium_case_inner_loop_and_trailing_pixels process_head, process_tail,, exit_label, unaligned_src, unaligned_mask -+ medium_case_inner_loop_and_trailing_pixels \process_head, \process_tail,, \exit_label, \unaligned_src, \unaligned_mask - .endm - - .macro medium_case_inner_loop_and_trailing_pixels process_head, process_tail, unused, exit_label, unaligned_src, unaligned_mask - 120: -- process_head , 16, 0, unaligned_src, unaligned_mask, 0 -- process_tail , 16, 0 -+ \process_head , 16, 0, \unaligned_src, \unaligned_mask, 0 -+ \process_tail , 16, 0 - .if !((flags) & FLAG_PROCESS_DOES_STORE) - pixst , 16, 0, DST - .endif - subs X, X, #128/dst_w_bpp - bhs 120b - /* Trailing pixels */ - tst X, #128/dst_w_bpp - 1 -- beq exit_label -- trailing_15bytes process_head, process_tail, unaligned_src, unaligned_mask -+ beq \exit_label -+ trailing_15bytes \process_head, \process_tail, \unaligned_src, \unaligned_mask - .endm - - .macro narrow_case_inner_loop_and_trailing_pixels process_head, process_tail, unused, exit_label, unaligned_src, unaligned_mask - tst X, #16*8/dst_w_bpp -- conditional_process1 ne, process_head, process_tail, 16, 0, unaligned_src, unaligned_mask, 0 -+ conditional_process1 ne, \process_head, \process_tail, 16, 0, \unaligned_src, \unaligned_mask, 0 - /* Trailing pixels */ - /* In narrow case, it's relatively unlikely to be aligned, so let's do without a branch here */ -- trailing_15bytes process_head, process_tail, unaligned_src, unaligned_mask -+ trailing_15bytes \process_head, \process_tail, \unaligned_src, \unaligned_mask - .endm - - .macro switch_on_alignment action, process_head, process_tail, process_inner_loop, exit_label - /* Note that if we're reading the destination, it's already guaranteed to be aligned at this point */ - .if mask_bpp == 8 || mask_bpp == 16 - tst MASK, #3 - bne 141f - .endif - .if src_bpp == 8 || src_bpp == 16 - tst SRC, #3 - bne 140f - .endif -- action process_head, process_tail, process_inner_loop, exit_label, 0, 0 -+ \action \process_head, \process_tail, \process_inner_loop, \exit_label, 0, 0 - .if src_bpp == 8 || src_bpp == 16 -- b exit_label -+ b \exit_label - 140: -- action process_head, process_tail, process_inner_loop, exit_label, 1, 0 -+ \action \process_head, \process_tail, \process_inner_loop, \exit_label, 1, 0 - .endif - .if mask_bpp == 8 || mask_bpp == 16 -- b exit_label -+ b \exit_label - 141: - .if src_bpp == 8 || src_bpp == 16 - tst SRC, #3 - bne 142f - .endif -- action process_head, process_tail, process_inner_loop, exit_label, 0, 1 -+ \action \process_head, \process_tail, \process_inner_loop, \exit_label, 0, 1 - .if src_bpp == 8 || src_bpp == 16 -- b exit_label -+ b \exit_label - 142: -- action process_head, process_tail, process_inner_loop, exit_label, 1, 1 -+ \action \process_head, \process_tail, \process_inner_loop, \exit_label, 1, 1 - .endif - .endif - .endm - - - .macro end_of_line restore_x, vars_spilled, loop_label, last_one -- .if vars_spilled -+ .if \vars_spilled - /* Sadly, GAS doesn't seem have an equivalent of the DCI directive? */ - /* This is ldmia sp,{} */ - .word 0xE89D0000 | LINE_SAVED_REGS - .endif - subs Y, Y, #1 -- .if vars_spilled -+ .if \vars_spilled - .if (LINE_SAVED_REGS) & (1<<1) - str Y, [sp] - .endif - .endif - add DST, DST, STRIDE_D - .if src_bpp > 0 - add SRC, SRC, STRIDE_S - .endif - .if mask_bpp > 0 - add MASK, MASK, STRIDE_M - .endif -- .if restore_x -+ .if \restore_x - mov X, ORIG_W - .endif -- bhs loop_label -- .ifc "last_one","" -- .if vars_spilled -+ bhs \loop_label -+ .ifc "\last_one","" -+ .if \vars_spilled - b 197f - .else - b 198f - .endif - .else -- .if (!vars_spilled) && ((flags) & FLAG_SPILL_LINE_VARS) -+ .if (!\vars_spilled) && ((flags) & FLAG_SPILL_LINE_VARS) - b 198f - .endif - .endif - .endm - - - .macro generate_composite_function fname, \ - src_bpp_, \ -@@ -591,27 +623,27 @@ 142: - prefetch_distance_, \ - init, \ - newline, \ - cleanup, \ - process_head, \ - process_tail, \ - process_inner_loop - -- pixman_asm_function fname -+ pixman_asm_function \fname - - /* - * Make some macro arguments globally visible and accessible - * from other macros - */ -- .set src_bpp, src_bpp_ -- .set mask_bpp, mask_bpp_ -- .set dst_w_bpp, dst_w_bpp_ -- .set flags, flags_ -- .set prefetch_distance, prefetch_distance_ -+ .set src_bpp, \src_bpp_ -+ .set mask_bpp, \mask_bpp_ -+ .set dst_w_bpp, \dst_w_bpp_ -+ .set flags, \flags_ -+ .set prefetch_distance, \prefetch_distance_ - - /* - * Select prefetch type for this function. - */ - .if prefetch_distance == 0 - .set PREFETCH_TYPE_CURRENT, PREFETCH_TYPE_NONE - .else - .set PREFETCH_TYPE_CURRENT, PREFETCH_TYPE_STANDARD -@@ -727,17 +759,17 @@ 142: - .endif - - #ifdef DEBUG_PARAMS - add Y, Y, #1 - stmia sp, {r0-r7,pc} - sub Y, Y, #1 - #endif - -- init -+ \init - - .if (flags) & FLAG_PROCESS_CORRUPTS_WK0 - /* Reserve a word in which to store X during leading pixels */ - sub sp, sp, #4 - .set ARGS_STACK_OFFSET, ARGS_STACK_OFFSET+4 - .set LOCALS_STACK_OFFSET, LOCALS_STACK_OFFSET+4 - .endif - -@@ -768,47 +800,47 @@ 142: - mov ORIG_W, X - .if (flags) & FLAG_SPILL_LINE_VARS_WIDE - /* This is stmdb sp!,{} */ - .word 0xE92D0000 | LINE_SAVED_REGS - .set ARGS_STACK_OFFSET, ARGS_STACK_OFFSET + LINE_SAVED_REG_COUNT*4 - .set LOCALS_STACK_OFFSET, LOCALS_STACK_OFFSET + LINE_SAVED_REG_COUNT*4 - .endif - 151: /* New line */ -- newline -+ \newline - preload_leading_step1 src_bpp, WK1, SRC - preload_leading_step1 mask_bpp, WK2, MASK - .if ((flags) & FLAG_NO_PRELOAD_DST) == 0 - preload_leading_step1 dst_r_bpp, WK3, DST - .endif - - ands WK0, DST, #15 - beq 154f - rsb WK0, WK0, #16 /* number of leading bytes until destination aligned */ - - preload_leading_step2 src_bpp, src_bpp_shift, WK1, SRC - preload_leading_step2 mask_bpp, mask_bpp_shift, WK2, MASK - .if ((flags) & FLAG_NO_PRELOAD_DST) == 0 - preload_leading_step2 dst_r_bpp, dst_bpp_shift, WK3, DST - .endif - -- leading_15bytes process_head, process_tail -+ leading_15bytes \process_head, \process_tail - - 154: /* Destination now 16-byte aligned; we have at least one prefetch on each channel as well as at least one 16-byte output block */ - .if (src_bpp > 0) && (mask_bpp == 0) && ((flags) & FLAG_PROCESS_PRESERVES_SCRATCH) - and SCRATCH, SRC, #31 - rsb SCRATCH, SCRATCH, #32*prefetch_distance - .elseif (src_bpp == 0) && (mask_bpp > 0) && ((flags) & FLAG_PROCESS_PRESERVES_SCRATCH) - and SCRATCH, MASK, #31 - rsb SCRATCH, SCRATCH, #32*prefetch_distance - .endif -- .ifc "process_inner_loop","" -- switch_on_alignment wide_case_inner_loop_and_trailing_pixels, process_head, process_tail, wide_case_inner_loop, 157f -+ .ifc "\process_inner_loop","" -+ switch_on_alignment wide_case_inner_loop_and_trailing_pixels, \process_head, \process_tail, wide_case_inner_loop, 157f - .else -- switch_on_alignment wide_case_inner_loop_and_trailing_pixels, process_head, process_tail, process_inner_loop, 157f -+ switch_on_alignment wide_case_inner_loop_and_trailing_pixels, \process_head, \process_tail, \process_inner_loop, 157f - .endif - - 157: /* Check for another line */ - end_of_line 1, %((flags) & FLAG_SPILL_LINE_VARS_WIDE), 151b - .if (flags) & FLAG_SPILL_LINE_VARS_WIDE - .set ARGS_STACK_OFFSET, ARGS_STACK_OFFSET - LINE_SAVED_REG_COUNT*4 - .set LOCALS_STACK_OFFSET, LOCALS_STACK_OFFSET - LINE_SAVED_REG_COUNT*4 - .endif -@@ -820,80 +852,80 @@ 160: /* Medium case */ - mov ORIG_W, X - .if (flags) & FLAG_SPILL_LINE_VARS_NON_WIDE - /* This is stmdb sp!,{} */ - .word 0xE92D0000 | LINE_SAVED_REGS - .set ARGS_STACK_OFFSET, ARGS_STACK_OFFSET + LINE_SAVED_REG_COUNT*4 - .set LOCALS_STACK_OFFSET, LOCALS_STACK_OFFSET + LINE_SAVED_REG_COUNT*4 - .endif - 161: /* New line */ -- newline -+ \newline - preload_line 0, src_bpp, src_bpp_shift, SRC /* in: X, corrupts: WK0-WK1 */ - preload_line 0, mask_bpp, mask_bpp_shift, MASK - .if ((flags) & FLAG_NO_PRELOAD_DST) == 0 - preload_line 0, dst_r_bpp, dst_bpp_shift, DST - .endif - - sub X, X, #128/dst_w_bpp /* simplifies inner loop termination */ - ands WK0, DST, #15 - beq 164f - rsb WK0, WK0, #16 /* number of leading bytes until destination aligned */ - -- leading_15bytes process_head, process_tail -+ leading_15bytes \process_head, \process_tail - - 164: /* Destination now 16-byte aligned; we have at least one 16-byte output block */ -- switch_on_alignment medium_case_inner_loop_and_trailing_pixels, process_head, process_tail,, 167f -+ switch_on_alignment medium_case_inner_loop_and_trailing_pixels, \process_head, \process_tail,, 167f - - 167: /* Check for another line */ - end_of_line 1, %((flags) & FLAG_SPILL_LINE_VARS_NON_WIDE), 161b - - .ltorg - - 170: /* Narrow case, less than 31 bytes, so no guarantee of at least one 16-byte block */ - .if dst_w_bpp < 32 - mov ORIG_W, X - .endif - .if (flags) & FLAG_SPILL_LINE_VARS_NON_WIDE - /* This is stmdb sp!,{} */ - .word 0xE92D0000 | LINE_SAVED_REGS - .endif - 171: /* New line */ -- newline -+ \newline - preload_line 1, src_bpp, src_bpp_shift, SRC /* in: X, corrupts: WK0-WK1 */ - preload_line 1, mask_bpp, mask_bpp_shift, MASK - .if ((flags) & FLAG_NO_PRELOAD_DST) == 0 - preload_line 1, dst_r_bpp, dst_bpp_shift, DST - .endif - - .if dst_w_bpp == 8 - tst DST, #3 - beq 174f - 172: subs X, X, #1 - blo 177f -- process_head , 1, 0, 1, 1, 0 -- process_tail , 1, 0 -+ \process_head , 1, 0, 1, 1, 0 -+ \process_tail , 1, 0 - .if !((flags) & FLAG_PROCESS_DOES_STORE) - pixst , 1, 0, DST - .endif - tst DST, #3 - bne 172b - .elseif dst_w_bpp == 16 - tst DST, #2 - beq 174f - subs X, X, #1 - blo 177f -- process_head , 2, 0, 1, 1, 0 -- process_tail , 2, 0 -+ \process_head , 2, 0, 1, 1, 0 -+ \process_tail , 2, 0 - .if !((flags) & FLAG_PROCESS_DOES_STORE) - pixst , 2, 0, DST - .endif - .endif - - 174: /* Destination now 4-byte aligned; we have 0 or more output bytes to go */ -- switch_on_alignment narrow_case_inner_loop_and_trailing_pixels, process_head, process_tail,, 177f -+ switch_on_alignment narrow_case_inner_loop_and_trailing_pixels, \process_head, \process_tail,, 177f - - 177: /* Check for another line */ - end_of_line %(dst_w_bpp < 32), %((flags) & FLAG_SPILL_LINE_VARS_NON_WIDE), 171b, last_one - .if (flags) & FLAG_SPILL_LINE_VARS_NON_WIDE - .set ARGS_STACK_OFFSET, ARGS_STACK_OFFSET - LINE_SAVED_REG_COUNT*4 - .set LOCALS_STACK_OFFSET, LOCALS_STACK_OFFSET - LINE_SAVED_REG_COUNT*4 - .endif - -@@ -903,17 +935,17 @@ 197: - .endif - 198: - .if (flags) & FLAG_PROCESS_CORRUPTS_WK0 - .set ARGS_STACK_OFFSET, ARGS_STACK_OFFSET-4 - .set LOCALS_STACK_OFFSET, LOCALS_STACK_OFFSET-4 - add sp, sp, #4 - .endif - -- cleanup -+ \cleanup - - #ifdef DEBUG_PARAMS - add sp, sp, #9*4 /* junk the debug copy of arguments */ - #endif - 199: - pop {r4-r11, pc} /* exit */ - - .ltorg -@@ -927,23 +959,23 @@ 199: - .unreq MASK - .unreq STRIDE_M - .unreq WK0 - .unreq WK1 - .unreq WK2 - .unreq WK3 - .unreq SCRATCH - .unreq ORIG_W -- .endfunc -+ pixman_end_asm_function - .endm - - .macro line_saved_regs x:vararg - .set LINE_SAVED_REGS, 0 - .set LINE_SAVED_REG_COUNT, 0 -- .irp SAVED_REG,x -+ .irp SAVED_REG,\x - .ifc "SAVED_REG","Y" - .set LINE_SAVED_REGS, LINE_SAVED_REGS | (1<<1) - .set LINE_SAVED_REG_COUNT, LINE_SAVED_REG_COUNT + 1 - .endif - .ifc "SAVED_REG","STRIDE_D" - .set LINE_SAVED_REGS, LINE_SAVED_REGS | (1<<3) - .set LINE_SAVED_REG_COUNT, LINE_SAVED_REG_COUNT + 1 - .endif diff --git a/gfx/cairo/pixman-arm64-clang.patch b/gfx/cairo/pixman-arm64-clang.patch deleted file mode 100644 index f059734531..0000000000 --- a/gfx/cairo/pixman-arm64-clang.patch +++ /dev/null @@ -1,3756 +0,0 @@ -https://gitlab.freedesktop.org/pixman/pixman/-/merge_requests/71 - -diff --git a/gfx/cairo/libpixman/src/pixman-arm-asm.h b/gfx/cairo/libpixman/src/pixman-arm-asm.h ---- a/gfx/cairo/libpixman/src/pixman-arm-asm.h -+++ b/gfx/cairo/libpixman/src/pixman-arm-asm.h -@@ -21,17 +21,33 @@ - * OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS - * SOFTWARE. - * - * Author: Jeff Muizelaar (jeff@infidigm.net) - * - */ - - /* Supplementary macro for setting function attributes */ --.macro pixman_asm_function fname -- .func fname -- .global fname -+.macro pixman_asm_function_impl fname -+#ifdef ASM_HAVE_FUNC_DIRECTIVE -+ .func \fname -+#endif -+ .global \fname - #ifdef __ELF__ -- .hidden fname -- .type fname, %function -+ .hidden \fname -+ .type \fname, %function - #endif --fname: -+\fname: - .endm -+ -+.macro pixman_asm_function fname -+#ifdef ASM_LEADING_UNDERSCORE -+ pixman_asm_function_impl _\fname -+#else -+ pixman_asm_function_impl \fname -+#endif -+.endm -+ -+.macro pixman_end_asm_function -+#ifdef ASM_HAVE_FUNC_DIRECTIVE -+ .endfunc -+#endif -+.endm -diff --git a/gfx/cairo/libpixman/src/pixman-arma64-neon-asm-bilinear.S b/gfx/cairo/libpixman/src/pixman-arma64-neon-asm-bilinear.S ---- a/gfx/cairo/libpixman/src/pixman-arma64-neon-asm-bilinear.S -+++ b/gfx/cairo/libpixman/src/pixman-arma64-neon-asm-bilinear.S -@@ -72,219 +72,219 @@ - * format conversion, and interpolation as separate macros which can be used - * as the basic building blocks for constructing bilinear scanline functions. - */ - - .macro bilinear_load_8888 reg1, reg2, tmp - asr WTMP1, X, #16 - add X, X, UX - add TMP1, TOP, TMP1, lsl #2 -- ld1 {®1&.2s}, [TMP1], STRIDE -- ld1 {®2&.2s}, [TMP1] -+ ld1 {\()\reg1\().2s}, [TMP1], STRIDE -+ ld1 {\()\reg2\().2s}, [TMP1] - .endm - - .macro bilinear_load_0565 reg1, reg2, tmp - asr WTMP1, X, #16 - add X, X, UX - add TMP1, TOP, TMP1, lsl #1 -- ld1 {®2&.s}[0], [TMP1], STRIDE -- ld1 {®2&.s}[1], [TMP1] -- convert_four_0565_to_x888_packed reg2, reg1, reg2, tmp -+ ld1 {\()\reg2\().s}[0], [TMP1], STRIDE -+ ld1 {\()\reg2\().s}[1], [TMP1] -+ convert_four_0565_to_x888_packed \reg2, \reg1, \reg2, \tmp - .endm - - .macro bilinear_load_and_vertical_interpolate_two_8888 \ - acc1, acc2, reg1, reg2, reg3, reg4, tmp1, tmp2 - -- bilinear_load_8888 reg1, reg2, tmp1 -- umull &acc1&.8h, ®1&.8b, v28.8b -- umlal &acc1&.8h, ®2&.8b, v29.8b -- bilinear_load_8888 reg3, reg4, tmp2 -- umull &acc2&.8h, ®3&.8b, v28.8b -- umlal &acc2&.8h, ®4&.8b, v29.8b -+ bilinear_load_8888 \reg1, \reg2, \tmp1 -+ umull \()\acc1\().8h, \()\reg1\().8b, v28.8b -+ umlal \()\acc1\().8h, \()\reg2\().8b, v29.8b -+ bilinear_load_8888 \reg3, \reg4, \tmp2 -+ umull \()\acc2\().8h, \()\reg3\().8b, v28.8b -+ umlal \()\acc2\().8h, \()\reg4\().8b, v29.8b - .endm - - .macro bilinear_load_and_vertical_interpolate_four_8888 \ -- xacc1, xacc2, xreg1, xreg2, xreg3, xreg4, xacc2lo, xacc2hi \ -+ xacc1, xacc2, xreg1, xreg2, xreg3, xreg4, xacc2lo, xacc2hi, \ - yacc1, yacc2, yreg1, yreg2, yreg3, yreg4, yacc2lo, yacc2hi - - bilinear_load_and_vertical_interpolate_two_8888 \ -- xacc1, xacc2, xreg1, xreg2, xreg3, xreg4, xacc2lo, xacc2hi -+ \xacc1, \xacc2, \xreg1, \xreg2, \xreg3, \xreg4, \xacc2lo, xacc2hi - bilinear_load_and_vertical_interpolate_two_8888 \ -- yacc1, yacc2, yreg1, yreg2, yreg3, yreg4, yacc2lo, yacc2hi -+ \yacc1, \yacc2, \yreg1, \yreg2, \yreg3, \yreg4, \yacc2lo, \yacc2hi - .endm - - .macro vzip reg1, reg2 -- zip1 v24.8b, reg1, reg2 -- zip2 reg2, reg1, reg2 -- mov reg1, v24.8b -+ zip1 v24.8b, \reg1, \reg2 -+ zip2 \reg2, \reg1, \reg2 -+ mov \reg1, v24.8b - .endm - - .macro vuzp reg1, reg2 -- uzp1 v24.8b, reg1, reg2 -- uzp2 reg2, reg1, reg2 -- mov reg1, v24.8b -+ uzp1 v24.8b, \reg1, \reg2 -+ uzp2 \reg2, \reg1, \reg2 -+ mov \reg1, v24.8b - .endm - - .macro bilinear_load_and_vertical_interpolate_two_0565 \ - acc1, acc2, reg1, reg2, reg3, reg4, acc2lo, acc2hi - asr WTMP1, X, #16 - add X, X, UX - add TMP1, TOP, TMP1, lsl #1 - asr WTMP2, X, #16 - add X, X, UX - add TMP2, TOP, TMP2, lsl #1 -- ld1 {&acc2&.s}[0], [TMP1], STRIDE -- ld1 {&acc2&.s}[2], [TMP2], STRIDE -- ld1 {&acc2&.s}[1], [TMP1] -- ld1 {&acc2&.s}[3], [TMP2] -- convert_0565_to_x888 acc2, reg3, reg2, reg1 -- vzip ®1&.8b, ®3&.8b -- vzip ®2&.8b, ®4&.8b -- vzip ®3&.8b, ®4&.8b -- vzip ®1&.8b, ®2&.8b -- umull &acc1&.8h, ®1&.8b, v28.8b -- umlal &acc1&.8h, ®2&.8b, v29.8b -- umull &acc2&.8h, ®3&.8b, v28.8b -- umlal &acc2&.8h, ®4&.8b, v29.8b -+ ld1 {\()\acc2\().s}[0], [TMP1], STRIDE -+ ld1 {\()\acc2\().s}[2], [TMP2], STRIDE -+ ld1 {\()\acc2\().s}[1], [TMP1] -+ ld1 {\()\acc2\().s}[3], [TMP2] -+ convert_0565_to_x888 \acc2, \reg3, \reg2, \reg1 -+ vzip \()\reg1\().8b, \()\reg3\().8b -+ vzip \()\reg2\().8b, \()\reg4\().8b -+ vzip \()\reg3\().8b, \()\reg4\().8b -+ vzip \()\reg1\().8b, \()\reg2\().8b -+ umull \()\acc1\().8h, \()\reg1\().8b, v28.8b -+ umlal \()\acc1\().8h, \()\reg2\().8b, v29.8b -+ umull \()\acc2\().8h, \()\reg3\().8b, v28.8b -+ umlal \()\acc2\().8h, \()\reg4\().8b, v29.8b - .endm - - .macro bilinear_load_and_vertical_interpolate_four_0565 \ -- xacc1, xacc2, xreg1, xreg2, xreg3, xreg4, xacc2lo, xacc2hi \ -+ xacc1, xacc2, xreg1, xreg2, xreg3, xreg4, xacc2lo, xacc2hi, \ - yacc1, yacc2, yreg1, yreg2, yreg3, yreg4, yacc2lo, yacc2hi - - asr WTMP1, X, #16 - add X, X, UX - add TMP1, TOP, TMP1, lsl #1 - asr WTMP2, X, #16 - add X, X, UX - add TMP2, TOP, TMP2, lsl #1 -- ld1 {&xacc2&.s}[0], [TMP1], STRIDE -- ld1 {&xacc2&.s}[2], [TMP2], STRIDE -- ld1 {&xacc2&.s}[1], [TMP1] -- ld1 {&xacc2&.s}[3], [TMP2] -- convert_0565_to_x888 xacc2, xreg3, xreg2, xreg1 -+ ld1 {\()\xacc2\().s}[0], [TMP1], STRIDE -+ ld1 {\()\xacc2\().s}[2], [TMP2], STRIDE -+ ld1 {\()\xacc2\().s}[1], [TMP1] -+ ld1 {\()\xacc2\().s}[3], [TMP2] -+ convert_0565_to_x888 \xacc2, \xreg3, \xreg2, \xreg1 - asr WTMP1, X, #16 - add X, X, UX - add TMP1, TOP, TMP1, lsl #1 - asr WTMP2, X, #16 - add X, X, UX - add TMP2, TOP, TMP2, lsl #1 -- ld1 {&yacc2&.s}[0], [TMP1], STRIDE -- vzip &xreg1&.8b, &xreg3&.8b -- ld1 {&yacc2&.s}[2], [TMP2], STRIDE -- vzip &xreg2&.8b, &xreg4&.8b -- ld1 {&yacc2&.s}[1], [TMP1] -- vzip &xreg3&.8b, &xreg4&.8b -- ld1 {&yacc2&.s}[3], [TMP2] -- vzip &xreg1&.8b, &xreg2&.8b -- convert_0565_to_x888 yacc2, yreg3, yreg2, yreg1 -- umull &xacc1&.8h, &xreg1&.8b, v28.8b -- vzip &yreg1&.8b, &yreg3&.8b -- umlal &xacc1&.8h, &xreg2&.8b, v29.8b -- vzip &yreg2&.8b, &yreg4&.8b -- umull &xacc2&.8h, &xreg3&.8b, v28.8b -- vzip &yreg3&.8b, &yreg4&.8b -- umlal &xacc2&.8h, &xreg4&.8b, v29.8b -- vzip &yreg1&.8b, &yreg2&.8b -- umull &yacc1&.8h, &yreg1&.8b, v28.8b -- umlal &yacc1&.8h, &yreg2&.8b, v29.8b -- umull &yacc2&.8h, &yreg3&.8b, v28.8b -- umlal &yacc2&.8h, &yreg4&.8b, v29.8b -+ ld1 {\()\yacc2\().s}[0], [TMP1], STRIDE -+ vzip \()\xreg1\().8b, \()\xreg3\().8b -+ ld1 {\()\yacc2\().s}[2], [TMP2], STRIDE -+ vzip \()\xreg2\().8b, \()\xreg4\().8b -+ ld1 {\()\yacc2\().s}[1], [TMP1] -+ vzip \()\xreg3\().8b, \()\xreg4\().8b -+ ld1 {\()\yacc2\().s}[3], [TMP2] -+ vzip \()\xreg1\().8b, \()\xreg2\().8b -+ convert_0565_to_x888 \yacc2, \yreg3, \yreg2, \yreg1 -+ umull \()\xacc1\().8h, \()\xreg1\().8b, v28.8b -+ vzip \()\yreg1\().8b, \()\yreg3\().8b -+ umlal \()\xacc1\().8h, \()\xreg2\().8b, v29.8b -+ vzip \()\yreg2\().8b, \()\yreg4\().8b -+ umull \()\xacc2\().8h, \()\xreg3\().8b, v28.8b -+ vzip \()\yreg3\().8b, \()\yreg4\().8b -+ umlal \()\xacc2\().8h, \()\xreg4\().8b, v29.8b -+ vzip \()\yreg1\().8b, \()\yreg2\().8b -+ umull \()\yacc1\().8h, \()\yreg1\().8b, v28.8b -+ umlal \()\yacc1\().8h, \()\yreg2\().8b, v29.8b -+ umull \()\yacc2\().8h, \()\yreg3\().8b, v28.8b -+ umlal \()\yacc2\().8h, \()\yreg4\().8b, v29.8b - .endm - - .macro bilinear_store_8888 numpix, tmp1, tmp2 --.if numpix == 4 -+.if \numpix == 4 - st1 {v0.2s, v1.2s}, [OUT], #16 --.elseif numpix == 2 -+.elseif \numpix == 2 - st1 {v0.2s}, [OUT], #8 --.elseif numpix == 1 -+.elseif \numpix == 1 - st1 {v0.s}[0], [OUT], #4 - .else -- .error bilinear_store_8888 numpix is unsupported -+ .error bilinear_store_8888 \numpix is unsupported - .endif - .endm - - .macro bilinear_store_0565 numpix, tmp1, tmp2 - vuzp v0.8b, v1.8b - vuzp v2.8b, v3.8b - vuzp v1.8b, v3.8b - vuzp v0.8b, v2.8b -- convert_8888_to_0565 v2, v1, v0, v1, tmp1, tmp2 --.if numpix == 4 -+ convert_8888_to_0565 v2, v1, v0, v1, \tmp1, \tmp2 -+.if \numpix == 4 - st1 {v1.4h}, [OUT], #8 --.elseif numpix == 2 -+.elseif \numpix == 2 - st1 {v1.s}[0], [OUT], #4 --.elseif numpix == 1 -+.elseif \numpix == 1 - st1 {v1.h}[0], [OUT], #2 - .else -- .error bilinear_store_0565 numpix is unsupported -+ .error bilinear_store_0565 \numpix is unsupported - .endif - .endm - - - /* - * Macros for loading mask pixels into register 'mask'. - * dup must be done in somewhere else. - */ - .macro bilinear_load_mask_x numpix, mask - .endm - - .macro bilinear_load_mask_8 numpix, mask --.if numpix == 4 -- ld1 {&mask&.s}[0], [MASK], #4 --.elseif numpix == 2 -- ld1 {&mask&.h}[0], [MASK], #2 --.elseif numpix == 1 -- ld1 {&mask&.b}[0], [MASK], #1 -+.if \numpix == 4 -+ ld1 {\()\mask\().s}[0], [MASK], #4 -+.elseif \numpix == 2 -+ ld1 {\()\mask\().h}[0], [MASK], #2 -+.elseif \numpix == 1 -+ ld1 {\()\mask\().b}[0], [MASK], #1 - .else -- .error bilinear_load_mask_8 numpix is unsupported -+ .error bilinear_load_mask_8 \numpix is unsupported - .endif -- prfm PREFETCH_MODE, [MASK, #prefetch_offset] -+ prfum PREFETCH_MODE, [MASK, #(prefetch_offset)] - .endm - - .macro bilinear_load_mask mask_fmt, numpix, mask -- bilinear_load_mask_&mask_fmt numpix, mask -+ bilinear_load_mask_\mask_fmt \numpix, \mask - .endm - - - /* - * Macros for loading destination pixels into register 'dst0' and 'dst1'. - * Interleave should be done somewhere else. - */ - .macro bilinear_load_dst_0565_src numpix, dst0, dst1, dst01 - .endm - - .macro bilinear_load_dst_8888_src numpix, dst0, dst1, dst01 - .endm - - .macro bilinear_load_dst_8888 numpix, dst0, dst1, dst01 --.if numpix == 4 -- ld1 {&dst0&.2s, &dst1&.2s}, [OUT] --.elseif numpix == 2 -- ld1 {&dst0&.2s}, [OUT] --.elseif numpix == 1 -- ld1 {&dst0&.s}[0], [OUT] -+.if \numpix == 4 -+ ld1 {\()\dst0\().2s, \()\dst1\().2s}, [OUT] -+.elseif \numpix == 2 -+ ld1 {\()\dst0\().2s}, [OUT] -+.elseif \numpix == 1 -+ ld1 {\()\dst0\().s}[0], [OUT] - .else -- .error bilinear_load_dst_8888 numpix is unsupported -+ .error bilinear_load_dst_8888 \numpix is unsupported - .endif -- mov &dst01&.d[0], &dst0&.d[0] -- mov &dst01&.d[1], &dst1&.d[0] -+ mov \()\dst01\().d[0], \()\dst0\().d[0] -+ mov \()\dst01\().d[1], \()\dst1\().d[0] - prfm PREFETCH_MODE, [OUT, #(prefetch_offset * 4)] - .endm - - .macro bilinear_load_dst_8888_over numpix, dst0, dst1, dst01 -- bilinear_load_dst_8888 numpix, dst0, dst1, dst01 -+ bilinear_load_dst_8888 \numpix, \dst0, \dst1, \dst01 - .endm - - .macro bilinear_load_dst_8888_add numpix, dst0, dst1, dst01 -- bilinear_load_dst_8888 numpix, dst0, dst1, dst01 -+ bilinear_load_dst_8888 \numpix, \dst0, \dst1, \dst01 - .endm - - .macro bilinear_load_dst dst_fmt, op, numpix, dst0, dst1, dst01 -- bilinear_load_dst_&dst_fmt&_&op numpix, dst0, dst1, dst01 -+ bilinear_load_dst_\()\dst_fmt\()_\()\op \numpix, \dst0, \dst1, \dst01 - .endm - - /* - * Macros for duplicating partially loaded mask to fill entire register. - * We will apply mask to interleaved source pixels, that is - * (r0, r1, r2, r3, g0, g1, g2, g3) x (m0, m1, m2, m3, m0, m1, m2, m3) - * (b0, b1, b2, b3, a0, a1, a2, a3) x (m0, m1, m2, m3, m0, m1, m2, m3) - * So, we need to duplicate loaded mask into whole register. -@@ -293,84 +293,85 @@ - * (r0, r1, x, x, g0, g1, x, x) x (m0, m1, m0, m1, m0, m1, m0, m1) - * (b0, b1, x, x, a0, a1, x, x) x (m0, m1, m0, m1, m0, m1, m0, m1) - * We can do some optimizations for this including last pixel cases. - */ - .macro bilinear_duplicate_mask_x numpix, mask - .endm - - .macro bilinear_duplicate_mask_8 numpix, mask --.if numpix == 4 -- dup &mask&.2s, &mask&.s[0] --.elseif numpix == 2 -- dup &mask&.4h, &mask&.h[0] --.elseif numpix == 1 -- dup &mask&.8b, &mask&.b[0] -+.if \numpix == 4 -+ dup \()\mask\().2s, \()\mask\().s[0] -+.elseif \numpix == 2 -+ dup \()\mask\().4h, \()\mask\().h[0] -+.elseif \numpix == 1 -+ dup \()\mask\().8b, \()\mask\().b[0] - .else -- .error bilinear_duplicate_mask_8 is unsupported -+ .error bilinear_duplicate_\mask_8 is unsupported - .endif - .endm - - .macro bilinear_duplicate_mask mask_fmt, numpix, mask -- bilinear_duplicate_mask_&mask_fmt numpix, mask -+ bilinear_duplicate_mask_\()\mask_fmt \numpix, \mask - .endm - - /* - * Macros for interleaving src and dst pixels to rrrr gggg bbbb aaaa form. - * Interleave should be done when maks is enabled or operator is 'over'. - */ - .macro bilinear_interleave src0, src1, src01, dst0, dst1, dst01 -- vuzp &src0&.8b, &src1&.8b -- vuzp &dst0&.8b, &dst1&.8b -- vuzp &src0&.8b, &src1&.8b -- vuzp &dst0&.8b, &dst1&.8b -- mov &src01&.d[1], &src1&.d[0] -- mov &src01&.d[0], &src0&.d[0] -- mov &dst01&.d[1], &dst1&.d[0] -- mov &dst01&.d[0], &dst0&.d[0] -+ vuzp \()\src0\().8b, \()\src1\().8b -+ vuzp \()\dst0\().8b, \()\dst1\().8b -+ vuzp \()\src0\().8b, \()\src1\().8b -+ vuzp \()\dst0\().8b, \()\dst1\().8b -+ mov \()\src01\().d[1], \()\src1\().d[0] -+ mov \()\src01\().d[0], \()\src0\().d[0] -+ mov \()\dst01\().d[1], \()\dst1\().d[0] -+ mov \()\dst01\().d[0], \()\dst0\().d[0] - .endm - - .macro bilinear_interleave_src_dst_x_src \ - numpix, src0, src1, src01, dst0, dst1, dst01 - .endm - - .macro bilinear_interleave_src_dst_x_over \ - numpix, src0, src1, src01, dst0, dst1, dst01 - -- bilinear_interleave src0, src1, src01, dst0, dst1, dst01 -+ bilinear_interleave \src0, \src1, \src01, \dst0, \dst1, \dst01 - .endm - - .macro bilinear_interleave_src_dst_x_add \ - numpix, src0, src1, src01, dst0, dst1, dst01 -- bilinear_interleave src0, src1, src01, dst0, dst1, dst01 -+ -+ bilinear_interleave \src0, \src1, \src01, \dst0, \dst1, \dst01 - .endm - - .macro bilinear_interleave_src_dst_8_src \ - numpix, src0, src1, src01, dst0, dst1, dst01 - -- bilinear_interleave src0, src1, src01, dst0, dst1, dst01 -+ bilinear_interleave \src0, \src1, \src01, \dst0, \dst1, \dst01 - .endm - - .macro bilinear_interleave_src_dst_8_over \ - numpix, src0, src1, src01, dst0, dst1, dst01 - -- bilinear_interleave src0, src1, src01, dst0, dst1, dst01 -+ bilinear_interleave \src0, \src1, \src01, \dst0, \dst1, \dst01 - .endm - - .macro bilinear_interleave_src_dst_8_add \ - numpix, src0, src1, src01, dst0, dst1, dst01 - -- bilinear_interleave src0, src1, src01, dst0, dst1, dst01 -+ bilinear_interleave \src0, \src1, \src01, \dst0, \dst1, \dst01 - .endm - - .macro bilinear_interleave_src_dst \ - mask_fmt, op, numpix, src0, src1, src01, dst0, dst1, dst01 - -- bilinear_interleave_src_dst_&mask_fmt&_&op \ -- numpix, src0, src1, src01, dst0, dst1, dst01 -+ bilinear_interleave_src_dst_\()\mask_fmt\()_\()\op \ -+ \numpix, \src0, \src1, \src01, \dst0, \dst1, \dst01 - .endm - - - /* - * Macros for applying masks to src pixels. (see combine_mask_u() function) - * src, dst should be in interleaved form. - * mask register should be in form (m0, m1, m2, m3). - */ -@@ -378,191 +379,191 @@ - numpix, src0, src1, src01, mask, \ - tmp01, tmp23, tmp45, tmp67 - .endm - - .macro bilinear_apply_mask_to_src_8 \ - numpix, src0, src1, src01, mask, \ - tmp01, tmp23, tmp45, tmp67 - -- umull &tmp01&.8h, &src0&.8b, &mask&.8b -- umull &tmp23&.8h, &src1&.8b, &mask&.8b -+ umull \()\tmp01\().8h, \()\src0\().8b, \()\mask\().8b -+ umull \()\tmp23\().8h, \()\src1\().8b, \()\mask\().8b - /* bubbles */ -- urshr &tmp45&.8h, &tmp01&.8h, #8 -- urshr &tmp67&.8h, &tmp23&.8h, #8 -+ urshr \()\tmp45\().8h, \()\tmp01\().8h, #8 -+ urshr \()\tmp67\().8h, \()\tmp23\().8h, #8 - /* bubbles */ -- raddhn &src0&.8b, &tmp45&.8h, &tmp01&.8h -- raddhn &src1&.8b, &tmp67&.8h, &tmp23&.8h -- mov &src01&.d[0], &src0&.d[0] -- mov &src01&.d[1], &src1&.d[0] -+ raddhn \()\src0\().8b, \()\tmp45\().8h, \()\tmp01\().8h -+ raddhn \()\src1\().8b, \()\tmp67\().8h, \()\tmp23\().8h -+ mov \()\src01\().d[0], \()\src0\().d[0] -+ mov \()\src01\().d[1], \()\src1\().d[0] - .endm - - .macro bilinear_apply_mask_to_src \ - mask_fmt, numpix, src0, src1, src01, mask, \ - tmp01, tmp23, tmp45, tmp67 - -- bilinear_apply_mask_to_src_&mask_fmt \ -- numpix, src0, src1, src01, mask, \ -- tmp01, tmp23, tmp45, tmp67 -+ bilinear_apply_mask_to_src_\()\mask_fmt \ -+ \numpix, \src0, \src1, \src01, \mask, \ -+ \tmp01, \tmp23, \tmp45, \tmp67 - .endm - - - /* - * Macros for combining src and destination pixels. - * Interleave or not is depending on operator 'op'. - */ - .macro bilinear_combine_src \ - numpix, src0, src1, src01, dst0, dst1, dst01, \ - tmp01, tmp23, tmp45, tmp67, tmp8 - .endm - - .macro bilinear_combine_over \ - numpix, src0, src1, src01, dst0, dst1, dst01, \ - tmp01, tmp23, tmp45, tmp67, tmp8 - -- dup &tmp8&.2s, &src1&.s[1] -+ dup \()\tmp8\().2s, \()\src1\().s[1] - /* bubbles */ -- mvn &tmp8&.8b, &tmp8&.8b -+ mvn \()\tmp8\().8b, \()\tmp8\().8b - /* bubbles */ -- umull &tmp01&.8h, &dst0&.8b, &tmp8&.8b -+ umull \()\tmp01\().8h, \()\dst0\().8b, \()\tmp8\().8b - /* bubbles */ -- umull &tmp23&.8h, &dst1&.8b, &tmp8&.8b -+ umull \()\tmp23\().8h, \()\dst1\().8b, \()\tmp8\().8b - /* bubbles */ -- urshr &tmp45&.8h, &tmp01&.8h, #8 -- urshr &tmp67&.8h, &tmp23&.8h, #8 -+ urshr \()\tmp45\().8h, \()\tmp01\().8h, #8 -+ urshr \()\tmp67\().8h, \()\tmp23\().8h, #8 - /* bubbles */ -- raddhn &dst0&.8b, &tmp45&.8h, &tmp01&.8h -- raddhn &dst1&.8b, &tmp67&.8h, &tmp23&.8h -- mov &dst01&.d[0], &dst0&.d[0] -- mov &dst01&.d[1], &dst1&.d[0] -+ raddhn \()\dst0\().8b, \()\tmp45\().8h, \()\tmp01\().8h -+ raddhn \()\dst1\().8b, \()\tmp67\().8h, \()\tmp23\().8h -+ mov \()\dst01\().d[0], \()\dst0\().d[0] -+ mov \()\dst01\().d[1], \()\dst1\().d[0] - /* bubbles */ -- uqadd &src0&.8b, &dst0&.8b, &src0&.8b -- uqadd &src1&.8b, &dst1&.8b, &src1&.8b -- mov &src01&.d[0], &src0&.d[0] -- mov &src01&.d[1], &src1&.d[0] -+ uqadd \()\src0\().8b, \()\dst0\().8b, \()\src0\().8b -+ uqadd \()\src1\().8b, \()\dst1\().8b, \()\src1\().8b -+ mov \()\src01\().d[0], \()\src0\().d[0] -+ mov \()\src01\().d[1], \()\src1\().d[0] - .endm - - .macro bilinear_combine_add \ - numpix, src0, src1, src01, dst0, dst1, dst01, \ - tmp01, tmp23, tmp45, tmp67, tmp8 - -- uqadd &src0&.8b, &dst0&.8b, &src0&.8b -- uqadd &src1&.8b, &dst1&.8b, &src1&.8b -- mov &src01&.d[0], &src0&.d[0] -- mov &src01&.d[1], &src1&.d[0] -+ uqadd \()\src0\().8b, \()\dst0\().8b, \()\src0\().8b -+ uqadd \()\src1\().8b, \()\dst1\().8b, \()\src1\().8b -+ mov \()\src01\().d[0], \()\src0\().d[0] -+ mov \()\src01\().d[1], \()\src1\().d[0] - .endm - - .macro bilinear_combine \ - op, numpix, src0, src1, src01, dst0, dst1, dst01, \ - tmp01, tmp23, tmp45, tmp67, tmp8 - -- bilinear_combine_&op \ -- numpix, src0, src1, src01, dst0, dst1, dst01, \ -- tmp01, tmp23, tmp45, tmp67, tmp8 -+ bilinear_combine_\()\op \ -+ \numpix, \src0, \src1, \src01, \dst0, \dst1, \dst01, \ -+ \tmp01, \tmp23, \tmp45, \tmp67, \tmp8 - .endm - - /* - * Macros for final deinterleaving of destination pixels if needed. - */ - .macro bilinear_deinterleave numpix, dst0, dst1, dst01 -- vuzp &dst0&.8b, &dst1&.8b -+ vuzp \()\dst0\().8b, \()\dst1\().8b - /* bubbles */ -- vuzp &dst0&.8b, &dst1&.8b -- mov &dst01&.d[0], &dst0&.d[0] -- mov &dst01&.d[1], &dst1&.d[0] -+ vuzp \()\dst0\().8b, \()\dst1\().8b -+ mov \()\dst01\().d[0], \()\dst0\().d[0] -+ mov \()\dst01\().d[1], \()\dst1\().d[0] - .endm - - .macro bilinear_deinterleave_dst_x_src numpix, dst0, dst1, dst01 - .endm - - .macro bilinear_deinterleave_dst_x_over numpix, dst0, dst1, dst01 -- bilinear_deinterleave numpix, dst0, dst1, dst01 -+ bilinear_deinterleave \numpix, \dst0, \dst1, \dst01 - .endm - - .macro bilinear_deinterleave_dst_x_add numpix, dst0, dst1, dst01 -- bilinear_deinterleave numpix, dst0, dst1, dst01 -+ bilinear_deinterleave \numpix, \dst0, \dst1, \dst01 - .endm - - .macro bilinear_deinterleave_dst_8_src numpix, dst0, dst1, dst01 -- bilinear_deinterleave numpix, dst0, dst1, dst01 -+ bilinear_deinterleave \numpix, \dst0, \dst1, \dst01 - .endm - - .macro bilinear_deinterleave_dst_8_over numpix, dst0, dst1, dst01 -- bilinear_deinterleave numpix, dst0, dst1, dst01 -+ bilinear_deinterleave \numpix, \dst0, \dst1, \dst01 - .endm - - .macro bilinear_deinterleave_dst_8_add numpix, dst0, dst1, dst01 -- bilinear_deinterleave numpix, dst0, dst1, dst01 -+ bilinear_deinterleave \numpix, \dst0, \dst1, \dst01 - .endm - - .macro bilinear_deinterleave_dst mask_fmt, op, numpix, dst0, dst1, dst01 -- bilinear_deinterleave_dst_&mask_fmt&_&op numpix, dst0, dst1, dst01 -+ bilinear_deinterleave_dst_\()\mask_fmt\()_\()\op \numpix, \dst0, \dst1, \dst01 - .endm - - - .macro bilinear_interpolate_last_pixel src_fmt, mask_fmt, dst_fmt, op -- bilinear_load_&src_fmt v0, v1, v2 -- bilinear_load_mask mask_fmt, 1, v4 -- bilinear_load_dst dst_fmt, op, 1, v18, v19, v9 -+ bilinear_load_\()\src_fmt v0, v1, v2 -+ bilinear_load_mask \mask_fmt, 1, v4 -+ bilinear_load_dst \dst_fmt, \op, 1, v18, v19, v9 - umull v2.8h, v0.8b, v28.8b - umlal v2.8h, v1.8b, v29.8b - /* 5 cycles bubble */ - ushll v0.4s, v2.4h, #BILINEAR_INTERPOLATION_BITS - umlsl v0.4s, v2.4h, v15.h[0] - umlal2 v0.4s, v2.8h, v15.h[0] - /* 5 cycles bubble */ -- bilinear_duplicate_mask mask_fmt, 1, v4 -+ bilinear_duplicate_mask \mask_fmt, 1, v4 - shrn v0.4h, v0.4s, #(2 * BILINEAR_INTERPOLATION_BITS) - /* 3 cycles bubble */ - xtn v0.8b, v0.8h - /* 1 cycle bubble */ - bilinear_interleave_src_dst \ -- mask_fmt, op, 1, v0, v1, v0, v18, v19, v9 -+ \mask_fmt, \op, 1, v0, v1, v0, v18, v19, v9 - bilinear_apply_mask_to_src \ -- mask_fmt, 1, v0, v1, v0, v4, \ -+ \mask_fmt, 1, v0, v1, v0, v4, \ - v3, v8, v10, v11 - bilinear_combine \ -- op, 1, v0, v1, v0, v18, v19, v9, \ -+ \op, 1, v0, v1, v0, v18, v19, v9, \ - v3, v8, v10, v11, v5 -- bilinear_deinterleave_dst mask_fmt, op, 1, v0, v1, v0 -- bilinear_store_&dst_fmt 1, v17, v18 -+ bilinear_deinterleave_dst \mask_fmt, \op, 1, v0, v1, v0 -+ bilinear_store_\()\dst_fmt 1, v17, v18 - .endm - - .macro bilinear_interpolate_two_pixels src_fmt, mask_fmt, dst_fmt, op -- bilinear_load_and_vertical_interpolate_two_&src_fmt \ -+ bilinear_load_and_vertical_interpolate_two_\()\src_fmt \ - v1, v11, v18, v19, v20, v21, v22, v23 -- bilinear_load_mask mask_fmt, 2, v4 -- bilinear_load_dst dst_fmt, op, 2, v18, v19, v9 -+ bilinear_load_mask \mask_fmt, 2, v4 -+ bilinear_load_dst \dst_fmt, \op, 2, v18, v19, v9 - ushll v0.4s, v1.4h, #BILINEAR_INTERPOLATION_BITS - umlsl v0.4s, v1.4h, v15.h[0] - umlal2 v0.4s, v1.8h, v15.h[0] - ushll v10.4s, v11.4h, #BILINEAR_INTERPOLATION_BITS - umlsl v10.4s, v11.4h, v15.h[4] - umlal2 v10.4s, v11.8h, v15.h[4] - shrn v0.4h, v0.4s, #(2 * BILINEAR_INTERPOLATION_BITS) - shrn2 v0.8h, v10.4s, #(2 * BILINEAR_INTERPOLATION_BITS) -- bilinear_duplicate_mask mask_fmt, 2, v4 -+ bilinear_duplicate_mask \mask_fmt, 2, v4 - ushr v15.8h, v12.8h, #(16 - BILINEAR_INTERPOLATION_BITS) - add v12.8h, v12.8h, v13.8h - xtn v0.8b, v0.8h - bilinear_interleave_src_dst \ -- mask_fmt, op, 2, v0, v1, v0, v18, v19, v9 -+ \mask_fmt, \op, 2, v0, v1, v0, v18, v19, v9 - bilinear_apply_mask_to_src \ -- mask_fmt, 2, v0, v1, v0, v4, \ -+ \mask_fmt, 2, v0, v1, v0, v4, \ - v3, v8, v10, v11 - bilinear_combine \ -- op, 2, v0, v1, v0, v18, v19, v9, \ -+ \op, 2, v0, v1, v0, v18, v19, v9, \ - v3, v8, v10, v11, v5 -- bilinear_deinterleave_dst mask_fmt, op, 2, v0, v1, v0 -- bilinear_store_&dst_fmt 2, v16, v17 -+ bilinear_deinterleave_dst \mask_fmt, \op, 2, v0, v1, v0 -+ bilinear_store_\()\dst_fmt 2, v16, v17 - .endm - - .macro bilinear_interpolate_four_pixels src_fmt, mask_fmt, dst_fmt, op -- bilinear_load_and_vertical_interpolate_four_&src_fmt \ -- v1, v11, v4, v5, v6, v7, v22, v23 \ -+ bilinear_load_and_vertical_interpolate_four_\()\src_fmt \ -+ v1, v11, v4, v5, v6, v7, v22, v23, \ - v3, v9, v16, v17, v20, v21, v18, v19 - prfm PREFETCH_MODE, [TMP1, PF_OFFS] - sub TMP1, TMP1, STRIDE - prfm PREFETCH_MODE, [TMP1, PF_OFFS] - ushll v0.4s, v1.4h, #BILINEAR_INTERPOLATION_BITS - umlsl v0.4s, v1.4h, v15.h[0] - umlal2 v0.4s, v1.8h, v15.h[0] - ushll v10.4s, v11.4h, #BILINEAR_INTERPOLATION_BITS -@@ -575,33 +576,33 @@ - ushll v8.4s, v9.4h, #BILINEAR_INTERPOLATION_BITS - umlsl v8.4s, v9.4h, v15.h[4] - umlal2 v8.4s, v9.8h, v15.h[4] - add v12.8h, v12.8h, v13.8h - shrn v0.4h, v0.4s, #(2 * BILINEAR_INTERPOLATION_BITS) - shrn2 v0.8h, v10.4s, #(2 * BILINEAR_INTERPOLATION_BITS) - shrn v2.4h, v2.4s, #(2 * BILINEAR_INTERPOLATION_BITS) - shrn2 v2.8h, v8.4s, #(2 * BILINEAR_INTERPOLATION_BITS) -- bilinear_load_mask mask_fmt, 4, v4 -- bilinear_duplicate_mask mask_fmt, 4, v4 -+ bilinear_load_mask \mask_fmt, 4, v4 -+ bilinear_duplicate_mask \mask_fmt, 4, v4 - ushr v15.8h, v12.8h, #(16 - BILINEAR_INTERPOLATION_BITS) - xtn v0.8b, v0.8h - xtn v1.8b, v2.8h - add v12.8h, v12.8h, v13.8h -- bilinear_load_dst dst_fmt, op, 4, v2, v3, v21 -+ bilinear_load_dst \dst_fmt, \op, 4, v2, v3, v21 - bilinear_interleave_src_dst \ -- mask_fmt, op, 4, v0, v1, v0, v2, v3, v11 -+ \mask_fmt, \op, 4, v0, v1, v0, v2, v3, v11 - bilinear_apply_mask_to_src \ -- mask_fmt, 4, v0, v1, v0, v4, \ -+ \mask_fmt, 4, v0, v1, v0, v4, \ - v6, v8, v9, v10 - bilinear_combine \ -- op, 4, v0, v1, v0, v2, v3, v1, \ -+ \op, 4, v0, v1, v0, v2, v3, v1, \ - v6, v8, v9, v10, v23 -- bilinear_deinterleave_dst mask_fmt, op, 4, v0, v1, v0 -- bilinear_store_&dst_fmt 4, v6, v7 -+ bilinear_deinterleave_dst \mask_fmt, \op, 4, v0, v1, v0 -+ bilinear_store_\()\dst_fmt 4, v6, v7 - .endm - - .set BILINEAR_FLAG_USE_MASK, 1 - .set BILINEAR_FLAG_USE_ALL_NEON_REGS, 2 - - /* - * Main template macro for generating NEON optimized bilinear scanline functions. - * -@@ -631,24 +632,24 @@ - bilinear_process_four_pixels, \ - bilinear_process_pixblock_head, \ - bilinear_process_pixblock_tail, \ - bilinear_process_pixblock_tail_head, \ - pixblock_size, \ - prefetch_distance, \ - flags - --pixman_asm_function fname --.if pixblock_size == 8 --.elseif pixblock_size == 4 -+pixman_asm_function \fname -+.if \pixblock_size == 8 -+.elseif \pixblock_size == 4 - .else - .error unsupported pixblock size - .endif - --.if ((flags) & BILINEAR_FLAG_USE_MASK) == 0 -+.if ((\flags) & BILINEAR_FLAG_USE_MASK) == 0 - OUT .req x0 - TOP .req x1 - BOTTOM .req x2 - WT .req x3 - WWT .req w3 - WB .req x4 - WWB .req w4 - X .req w5 -@@ -694,32 +695,32 @@ pixman_asm_function fname - PF_OFFS .req x12 - TMP3 .req x13 - WTMP3 .req w13 - TMP4 .req x14 - WTMP4 .req w14 - STRIDE .req x15 - DUMMY .req x30 - -- .set prefetch_offset, prefetch_distance -+ .set prefetch_offset, \prefetch_distance - - stp x29, x30, [sp, -16]! - mov x29, sp - sub x29, x29, 64 - st1 {v8.8b, v9.8b, v10.8b, v11.8b}, [x29], 32 - st1 {v12.8b, v13.8b, v14.8b, v15.8b}, [x29], 32 - stp x10, x11, [x29, -80] - stp x12, x13, [x29, -96] - stp x14, x15, [x29, -112] - str x8, [x29, -120] - ldr w8, [x29, 16] - sub sp, sp, 120 - .endif - -- mov WTMP1, #prefetch_distance -+ mov WTMP1, #\prefetch_distance - umull PF_OFFS, WTMP1, UX - - sub STRIDE, BOTTOM, TOP - .unreq BOTTOM - - cmp WIDTH, #0 - ble 300f - -@@ -730,73 +731,73 @@ pixman_asm_function fname - mov v25.d[0], v12.d[1] - mov v26.d[0], v13.d[0] - add v25.4h, v25.4h, v26.4h - mov v12.d[1], v25.d[0] - - /* ensure good destination alignment */ - cmp WIDTH, #1 - blt 100f -- tst OUT, #(1 << dst_bpp_shift) -+ tst OUT, #(1 << \dst_bpp_shift) - beq 100f - ushr v15.8h, v12.8h, #(16 - BILINEAR_INTERPOLATION_BITS) - add v12.8h, v12.8h, v13.8h -- bilinear_process_last_pixel -+ \bilinear_process_last_pixel - sub WIDTH, WIDTH, #1 - 100: - add v13.8h, v13.8h, v13.8h - ushr v15.8h, v12.8h, #(16 - BILINEAR_INTERPOLATION_BITS) - add v12.8h, v12.8h, v13.8h - - cmp WIDTH, #2 - blt 100f -- tst OUT, #(1 << (dst_bpp_shift + 1)) -+ tst OUT, #(1 << (\dst_bpp_shift + 1)) - beq 100f -- bilinear_process_two_pixels -+ \bilinear_process_two_pixels - sub WIDTH, WIDTH, #2 - 100: --.if pixblock_size == 8 -+.if \pixblock_size == 8 - cmp WIDTH, #4 - blt 100f -- tst OUT, #(1 << (dst_bpp_shift + 2)) -+ tst OUT, #(1 << (\dst_bpp_shift + 2)) - beq 100f -- bilinear_process_four_pixels -+ \bilinear_process_four_pixels - sub WIDTH, WIDTH, #4 - 100: - .endif -- subs WIDTH, WIDTH, #pixblock_size -+ subs WIDTH, WIDTH, #\pixblock_size - blt 100f -- asr PF_OFFS, PF_OFFS, #(16 - src_bpp_shift) -- bilinear_process_pixblock_head -- subs WIDTH, WIDTH, #pixblock_size -+ asr PF_OFFS, PF_OFFS, #(16 - \src_bpp_shift) -+ \bilinear_process_pixblock_head -+ subs WIDTH, WIDTH, #\pixblock_size - blt 500f - 0: -- bilinear_process_pixblock_tail_head -- subs WIDTH, WIDTH, #pixblock_size -+ \bilinear_process_pixblock_tail_head -+ subs WIDTH, WIDTH, #\pixblock_size - bge 0b - 500: -- bilinear_process_pixblock_tail -+ \bilinear_process_pixblock_tail - 100: --.if pixblock_size == 8 -+.if \pixblock_size == 8 - tst WIDTH, #4 - beq 200f -- bilinear_process_four_pixels -+ \bilinear_process_four_pixels - 200: - .endif - /* handle the remaining trailing pixels */ - tst WIDTH, #2 - beq 200f -- bilinear_process_two_pixels -+ \bilinear_process_two_pixels - 200: - tst WIDTH, #1 - beq 300f -- bilinear_process_last_pixel -+ \bilinear_process_last_pixel - 300: - --.if ((flags) & BILINEAR_FLAG_USE_MASK) == 0 -+.if ((\flags) & BILINEAR_FLAG_USE_MASK) == 0 - sub x29, x29, 64 - ld1 {v8.8b, v9.8b, v10.8b, v11.8b}, [x29], 32 - ld1 {v12.8b, v13.8b, v14.8b, v15.8b}, [x29], 32 - ldp x10, x11, [x29, -80] - ldp x12, x13, [x29, -96] - ldp x14, x15, [x29, -112] - mov sp, x29 - ldp x29, x30, [sp], 16 -@@ -824,21 +825,21 @@ 300: - .unreq WIDTH - .unreq TMP1 - .unreq WTMP1 - .unreq TMP2 - .unreq PF_OFFS - .unreq TMP3 - .unreq TMP4 - .unreq STRIDE --.if ((flags) & BILINEAR_FLAG_USE_MASK) != 0 -+.if ((\flags) & BILINEAR_FLAG_USE_MASK) != 0 - .unreq MASK - .endif - --.endfunc -+pixman_end_asm_function - - .endm - - /* src_8888_8_8888 */ - .macro bilinear_src_8888_8_8888_process_last_pixel - bilinear_interpolate_last_pixel 8888, 8, 8888, src - .endm - -diff --git a/gfx/cairo/libpixman/src/pixman-arma64-neon-asm.S b/gfx/cairo/libpixman/src/pixman-arma64-neon-asm.S ---- a/gfx/cairo/libpixman/src/pixman-arma64-neon-asm.S -+++ b/gfx/cairo/libpixman/src/pixman-arma64-neon-asm.S -@@ -262,64 +262,64 @@ - uqadd v18.8b, v0.8b, v22.8b - uqadd v19.8b, v1.8b, v23.8b - shrn v6.8b, v4.8h, #8 - fetch_src_pixblock - shrn v7.8b, v4.8h, #3 - sli v4.8h, v4.8h, #5 - ushll v14.8h, v17.8b, #7 - sli v14.8h, v14.8h, #1 -- PF add PF_X, PF_X, #8 -+ PF add, PF_X, PF_X, #8 - ushll v8.8h, v19.8b, #7 - sli v8.8h, v8.8h, #1 -- PF tst PF_CTL, #0xF -+ PF tst, PF_CTL, #0xF - sri v6.8b, v6.8b, #5 -- PF beq 10f -- PF add PF_X, PF_X, #8 -+ PF beq, 10f -+ PF add, PF_X, PF_X, #8 - 10: - mvn v3.8b, v3.8b -- PF beq 10f -- PF sub PF_CTL, PF_CTL, #1 -+ PF beq, 10f -+ PF sub, PF_CTL, PF_CTL, #1 - 10: - sri v7.8b, v7.8b, #6 - shrn v30.8b, v4.8h, #2 - umull v10.8h, v3.8b, v6.8b -- PF lsl DUMMY, PF_X, #src_bpp_shift -- PF prfm PREFETCH_MODE, [PF_SRC, DUMMY] -+ PF lsl, DUMMY, PF_X, #src_bpp_shift -+ PF prfm, PREFETCH_MODE, [PF_SRC, DUMMY] - umull v11.8h, v3.8b, v7.8b - umull v12.8h, v3.8b, v30.8b -- PF lsl DUMMY, PF_X, #dst_bpp_shift -- PF prfm PREFETCH_MODE, [PF_DST, DUMMY] -+ PF lsl, DUMMY, PF_X, #dst_bpp_shift -+ PF prfm, PREFETCH_MODE, [PF_DST, DUMMY] - sri v14.8h, v8.8h, #5 -- PF cmp PF_X, ORIG_W -+ PF cmp, PF_X, ORIG_W - ushll v9.8h, v18.8b, #7 - sli v9.8h, v9.8h, #1 - urshr v17.8h, v10.8h, #8 -- PF ble 10f -- PF sub PF_X, PF_X, ORIG_W -+ PF ble, 10f -+ PF sub, PF_X, PF_X, ORIG_W - 10: - urshr v19.8h, v11.8h, #8 - urshr v18.8h, v12.8h, #8 -- PF ble 10f -- PF subs PF_CTL, PF_CTL, #0x10 -+ PF ble, 10f -+ PF subs, PF_CTL, PF_CTL, #0x10 - 10: - sri v14.8h, v9.8h, #11 - mov v28.d[0], v14.d[0] - mov v29.d[0], v14.d[1] -- PF ble 10f -- PF lsl DUMMY, SRC_STRIDE, #src_bpp_shift -- PF ldrsb DUMMY, [PF_SRC, DUMMY] -- PF add PF_SRC, PF_SRC, #1 -+ PF ble, 10f -+ PF lsl, DUMMY, SRC_STRIDE, #src_bpp_shift -+ PF ldrsb, DUMMY, [PF_SRC, DUMMY] -+ PF add, PF_SRC, PF_SRC, #1 - 10: - raddhn v20.8b, v10.8h, v17.8h - raddhn v23.8b, v11.8h, v19.8h -- PF ble 10f -- PF lsl DUMMY, DST_STRIDE, #dst_bpp_shift -- PF ldrsb DUMMY, [PF_DST, DUMMY] -- PF add PF_DST, PF_SRC, #1 -+ PF ble, 10f -+ PF lsl, DUMMY, DST_STRIDE, #dst_bpp_shift -+ PF ldrsb, DUMMY, [PF_DST, DUMMY] -+ PF add, PF_DST, PF_SRC, #1 - 10: - raddhn v22.8b, v12.8h, v18.8h - st1 {v14.8h}, [DST_W], #16 - .endm - - #else - - /* If we did not care much about the performance, we would just use this... */ -@@ -469,42 +469,42 @@ generate_composite_function \ - sri v14.8h, v8.8h, #5 - sri v14.8h, v9.8h, #11 - mov v28.d[0], v14.d[0] - mov v29.d[0], v14.d[1] - .endm - - .macro pixman_composite_src_8888_0565_process_pixblock_tail_head - sri v14.8h, v8.8h, #5 -- PF add PF_X, PF_X, #8 -- PF tst PF_CTL, #0xF -+ PF add, PF_X, PF_X, #8 -+ PF tst, PF_CTL, #0xF - fetch_src_pixblock -- PF beq 10f -- PF add PF_X, PF_X, #8 -- PF sub PF_CTL, PF_CTL, #1 -+ PF beq, 10f -+ PF add, PF_X, PF_X, #8 -+ PF sub, PF_CTL, PF_CTL, #1 - 10: - sri v14.8h, v9.8h, #11 - mov v28.d[0], v14.d[0] - mov v29.d[0], v14.d[1] -- PF cmp PF_X, ORIG_W -- PF lsl DUMMY, PF_X, #src_bpp_shift -- PF prfm PREFETCH_MODE, [PF_SRC, DUMMY] -+ PF cmp, PF_X, ORIG_W -+ PF lsl, DUMMY, PF_X, #src_bpp_shift -+ PF prfm, PREFETCH_MODE, [PF_SRC, DUMMY] - ushll v8.8h, v1.8b, #7 - sli v8.8h, v8.8h, #1 - st1 {v14.8h}, [DST_W], #16 -- PF ble 10f -- PF sub PF_X, PF_X, ORIG_W -- PF subs PF_CTL, PF_CTL, #0x10 -+ PF ble, 10f -+ PF sub, PF_X, PF_X, ORIG_W -+ PF subs, PF_CTL, PF_CTL, #0x10 - 10: - ushll v14.8h, v2.8b, #7 - sli v14.8h, v14.8h, #1 -- PF ble 10f -- PF lsl DUMMY, SRC_STRIDE, #src_bpp_shift -- PF ldrsb DUMMY, [PF_SRC, DUMMY] -- PF add PF_SRC, PF_SRC, #1 -+ PF ble, 10f -+ PF lsl, DUMMY, SRC_STRIDE, #src_bpp_shift -+ PF ldrsb, DUMMY, [PF_SRC, DUMMY] -+ PF add, PF_SRC, PF_SRC, #1 - 10: - ushll v9.8h, v0.8b, #7 - sli v9.8h, v9.8h, #1 - .endm - - generate_composite_function \ - pixman_composite_src_8888_0565_asm_neon, 32, 0, 16, \ - FLAG_DST_WRITEONLY | FLAG_DEINTERLEAVE_32BPP, \ -@@ -561,41 +561,41 @@ generate_composite_function \ - uqadd v31.8b, v3.8b, v7.8b - .endm - - .macro pixman_composite_add_8_8_process_pixblock_tail - .endm - - .macro pixman_composite_add_8_8_process_pixblock_tail_head - fetch_src_pixblock -- PF add PF_X, PF_X, #32 -- PF tst PF_CTL, #0xF -+ PF add, PF_X, PF_X, #32 -+ PF tst, PF_CTL, #0xF - ld1 {v4.8b, v5.8b, v6.8b, v7.8b}, [DST_R], #32 -- PF beq 10f -- PF add PF_X, PF_X, #32 -- PF sub PF_CTL, PF_CTL, #1 -+ PF beq, 10f -+ PF add, PF_X, PF_X, #32 -+ PF sub, PF_CTL, PF_CTL, #1 - 10: - st1 {v28.8b, v29.8b, v30.8b, v31.8b}, [DST_W], #32 -- PF cmp PF_X, ORIG_W -- PF lsl DUMMY, PF_X, #src_bpp_shift -- PF prfm PREFETCH_MODE, [PF_SRC, DUMMY] -- PF lsl DUMMY, PF_X, #dst_bpp_shift -- PF prfm PREFETCH_MODE, [PF_DST, DUMMY] -- PF ble 10f -- PF sub PF_X, PF_X, ORIG_W -- PF subs PF_CTL, PF_CTL, #0x10 -+ PF cmp, PF_X, ORIG_W -+ PF lsl, DUMMY, PF_X, #src_bpp_shift -+ PF prfm, PREFETCH_MODE, [PF_SRC, DUMMY] -+ PF lsl, DUMMY, PF_X, #dst_bpp_shift -+ PF prfm, PREFETCH_MODE, [PF_DST, DUMMY] -+ PF ble, 10f -+ PF sub, PF_X, PF_X, ORIG_W -+ PF subs, PF_CTL, PF_CTL, #0x10 - 10: - uqadd v28.8b, v0.8b, v4.8b -- PF ble 10f -- PF lsl DUMMY, SRC_STRIDE, #src_bpp_shift -- PF ldrsb DUMMY, [PF_SRC, DUMMY] -- PF add PF_SRC, PF_SRC, #1 -- PF lsl DUMMY, DST_STRIDE, #dst_bpp_shift -- PF ldrsb DUMMY, [PF_DST, DUMMY] -- PF add PF_DST, PF_DST, #1 -+ PF ble, 10f -+ PF lsl, DUMMY, SRC_STRIDE, #src_bpp_shift -+ PF ldrsb, DUMMY, [PF_SRC, DUMMY] -+ PF add, PF_SRC, PF_SRC, #1 -+ PF lsl, DUMMY, DST_STRIDE, #dst_bpp_shift -+ PF ldrsb, DUMMY, [PF_DST, DUMMY] -+ PF add, PF_DST, PF_DST, #1 - 10: - uqadd v29.8b, v1.8b, v5.8b - uqadd v30.8b, v2.8b, v6.8b - uqadd v31.8b, v3.8b, v7.8b - .endm - - generate_composite_function \ - pixman_composite_add_8_8_asm_neon, 8, 0, 8, \ -@@ -607,41 +607,41 @@ generate_composite_function \ - pixman_composite_add_8_8_process_pixblock_head, \ - pixman_composite_add_8_8_process_pixblock_tail, \ - pixman_composite_add_8_8_process_pixblock_tail_head - - /******************************************************************************/ - - .macro pixman_composite_add_8888_8888_process_pixblock_tail_head - fetch_src_pixblock -- PF add PF_X, PF_X, #8 -- PF tst PF_CTL, #0xF -+ PF add, PF_X, PF_X, #8 -+ PF tst, PF_CTL, #0xF - ld1 {v4.8b, v5.8b, v6.8b, v7.8b}, [DST_R], #32 -- PF beq 10f -- PF add PF_X, PF_X, #8 -- PF sub PF_CTL, PF_CTL, #1 -+ PF beq, 10f -+ PF add, PF_X, PF_X, #8 -+ PF sub, PF_CTL, PF_CTL, #1 - 10: - st1 {v28.8b, v29.8b, v30.8b, v31.8b}, [DST_W], #32 -- PF cmp PF_X, ORIG_W -- PF lsl DUMMY, PF_X, #src_bpp_shift -- PF prfm PREFETCH_MODE, [PF_SRC, DUMMY] -- PF lsl DUMMY, PF_X, #dst_bpp_shift -- PF prfm PREFETCH_MODE, [PF_DST, DUMMY] -- PF ble 10f -- PF sub PF_X, PF_X, ORIG_W -- PF subs PF_CTL, PF_CTL, #0x10 -+ PF cmp, PF_X, ORIG_W -+ PF lsl, DUMMY, PF_X, #src_bpp_shift -+ PF prfm, PREFETCH_MODE, [PF_SRC, DUMMY] -+ PF lsl, DUMMY, PF_X, #dst_bpp_shift -+ PF prfm, PREFETCH_MODE, [PF_DST, DUMMY] -+ PF ble, 10f -+ PF sub, PF_X, PF_X, ORIG_W -+ PF subs, PF_CTL, PF_CTL, #0x10 - 10: - uqadd v28.8b, v0.8b, v4.8b -- PF ble 10f -- PF lsl DUMMY, SRC_STRIDE, #src_bpp_shift -- PF ldrsb DUMMY, [PF_SRC, DUMMY] -- PF add PF_SRC, PF_SRC, #1 -- PF lsl DUMMY, DST_STRIDE, #dst_bpp_shift -- PF ldrsb DUMMY, [PF_DST, DUMMY] -- PF add PF_DST, PF_DST, #1 -+ PF ble, 10f -+ PF lsl, DUMMY, SRC_STRIDE, #src_bpp_shift -+ PF ldrsb, DUMMY, [PF_SRC, DUMMY] -+ PF add, PF_SRC, PF_SRC, #1 -+ PF lsl, DUMMY, DST_STRIDE, #dst_bpp_shift -+ PF ldrsb, DUMMY, [PF_DST, DUMMY] -+ PF add, PF_DST, PF_DST, #1 - 10: - uqadd v29.8b, v1.8b, v5.8b - uqadd v30.8b, v2.8b, v6.8b - uqadd v31.8b, v3.8b, v7.8b - .endm - - generate_composite_function \ - pixman_composite_add_8888_8888_asm_neon, 32, 0, 32, \ -@@ -684,55 +684,55 @@ generate_composite_function_single_scanl - raddhn v29.8b, v15.8h, v9.8h - raddhn v30.8b, v16.8h, v10.8h - raddhn v31.8b, v17.8h, v11.8h - .endm - - .macro pixman_composite_out_reverse_8888_8888_process_pixblock_tail_head - ld4 {v4.8b, v5.8b, v6.8b, v7.8b}, [DST_R], #32 - urshr v14.8h, v8.8h, #8 -- PF add PF_X, PF_X, #8 -- PF tst PF_CTL, #0xF -+ PF add, PF_X, PF_X, #8 -+ PF tst, PF_CTL, #0xF - urshr v15.8h, v9.8h, #8 - urshr v16.8h, v10.8h, #8 - urshr v17.8h, v11.8h, #8 -- PF beq 10f -- PF add PF_X, PF_X, #8 -- PF sub PF_CTL, PF_CTL, #1 -+ PF beq, 10f -+ PF add, PF_X, PF_X, #8 -+ PF sub, PF_CTL, PF_CTL, #1 - 10: - raddhn v28.8b, v14.8h, v8.8h - raddhn v29.8b, v15.8h, v9.8h -- PF cmp PF_X, ORIG_W -+ PF cmp, PF_X, ORIG_W - raddhn v30.8b, v16.8h, v10.8h - raddhn v31.8b, v17.8h, v11.8h - fetch_src_pixblock -- PF lsl DUMMY, PF_X, #src_bpp_shift -- PF prfm PREFETCH_MODE, [PF_SRC, DUMMY] -+ PF lsl, DUMMY, PF_X, #src_bpp_shift -+ PF prfm, PREFETCH_MODE, [PF_SRC, DUMMY] - mvn v22.8b, v3.8b -- PF lsl DUMMY, PF_X, #dst_bpp_shift -- PF prfm PREFETCH_MODE, [PF_DST, DUMMY] -+ PF lsl, DUMMY, PF_X, #dst_bpp_shift -+ PF prfm, PREFETCH_MODE, [PF_DST, DUMMY] - st4 {v28.8b, v29.8b, v30.8b, v31.8b}, [DST_W], #32 -- PF ble 10f -- PF sub PF_X, PF_X, ORIG_W -+ PF ble, 10f -+ PF sub, PF_X, PF_X, ORIG_W - 10: - umull v8.8h, v22.8b, v4.8b -- PF ble 10f -- PF subs PF_CTL, PF_CTL, #0x10 -+ PF ble, 10f -+ PF subs, PF_CTL, PF_CTL, #0x10 - 10: - umull v9.8h, v22.8b, v5.8b -- PF ble 10f -- PF lsl DUMMY, SRC_STRIDE, #src_bpp_shift -- PF ldrsb DUMMY, [PF_SRC, DUMMY] -- PF add PF_SRC, PF_SRC, #1 -+ PF ble, 10f -+ PF lsl, DUMMY, SRC_STRIDE, #src_bpp_shift -+ PF ldrsb, DUMMY, [PF_SRC, DUMMY] -+ PF add, PF_SRC, PF_SRC, #1 - 10: - umull v10.8h, v22.8b, v6.8b -- PF ble 10f -- PF lsl DUMMY, DST_STRIDE, #dst_bpp_shift -- PF ldrsb DUMMY, [PF_DST, DUMMY] -- PF add PF_DST, PF_DST, #1 -+ PF ble, 10f -+ PF lsl, DUMMY, DST_STRIDE, #dst_bpp_shift -+ PF ldrsb, DUMMY, [PF_DST, DUMMY] -+ PF add, PF_DST, PF_DST, #1 - 10: - umull v11.8h, v22.8b, v7.8b - .endm - - generate_composite_function_single_scanline \ - pixman_composite_scanline_out_reverse_asm_neon, 32, 0, 32, \ - FLAG_DST_READWRITE | FLAG_DEINTERLEAVE_32BPP, \ - 8, /* number of pixels, processed in a single block */ \ -@@ -754,59 +754,59 @@ generate_composite_function_single_scanl - uqadd v29.8b, v1.8b, v29.8b - uqadd v30.8b, v2.8b, v30.8b - uqadd v31.8b, v3.8b, v31.8b - .endm - - .macro pixman_composite_over_8888_8888_process_pixblock_tail_head - ld4 {v4.8b, v5.8b, v6.8b, v7.8b}, [DST_R], #32 - urshr v14.8h, v8.8h, #8 -- PF add PF_X, PF_X, #8 -- PF tst PF_CTL, #0xF -+ PF add, PF_X, PF_X, #8 -+ PF tst, PF_CTL, #0xF - urshr v15.8h, v9.8h, #8 - urshr v16.8h, v10.8h, #8 - urshr v17.8h, v11.8h, #8 -- PF beq 10f -- PF add PF_X, PF_X, #8 -- PF sub PF_CTL, PF_CTL, #1 -+ PF beq, 10f -+ PF add, PF_X, PF_X, #8 -+ PF sub, PF_CTL, PF_CTL, #1 - 10: - raddhn v28.8b, v14.8h, v8.8h - raddhn v29.8b, v15.8h, v9.8h -- PF cmp PF_X, ORIG_W -+ PF cmp, PF_X, ORIG_W - raddhn v30.8b, v16.8h, v10.8h - raddhn v31.8b, v17.8h, v11.8h - uqadd v28.8b, v0.8b, v28.8b - uqadd v29.8b, v1.8b, v29.8b - uqadd v30.8b, v2.8b, v30.8b - uqadd v31.8b, v3.8b, v31.8b - fetch_src_pixblock -- PF lsl DUMMY, PF_X, #src_bpp_shift -- PF prfm PREFETCH_MODE, [PF_SRC, DUMMY] -+ PF lsl, DUMMY, PF_X, #src_bpp_shift -+ PF prfm, PREFETCH_MODE, [PF_SRC, DUMMY] - mvn v22.8b, v3.8b -- PF lsl DUMMY, PF_X, #dst_bpp_shift -- PF prfm PREFETCH_MODE, [PF_DST, DUMMY] -+ PF lsl, DUMMY, PF_X, #dst_bpp_shift -+ PF prfm, PREFETCH_MODE, [PF_DST, DUMMY] - st4 {v28.8b, v29.8b, v30.8b, v31.8b}, [DST_W], #32 -- PF ble 10f -- PF sub PF_X, PF_X, ORIG_W -+ PF ble, 10f -+ PF sub, PF_X, PF_X, ORIG_W - 10: - umull v8.8h, v22.8b, v4.8b -- PF ble 10f -- PF subs PF_CTL, PF_CTL, #0x10 -+ PF ble, 10f -+ PF subs, PF_CTL, PF_CTL, #0x10 - 10: - umull v9.8h, v22.8b, v5.8b -- PF ble 10f -- PF lsl DUMMY, SRC_STRIDE, #src_bpp_shift -- PF ldrsb DUMMY, [PF_SRC, DUMMY] -- PF add PF_SRC, PF_SRC, #1 -+ PF ble, 10f -+ PF lsl, DUMMY, SRC_STRIDE, #src_bpp_shift -+ PF ldrsb, DUMMY, [PF_SRC, DUMMY] -+ PF add, PF_SRC, PF_SRC, #1 - 10: - umull v10.8h, v22.8b, v6.8b -- PF ble 10f -- PF lsl DUMMY, DST_STRIDE, #dst_bpp_shift -- PF ldrsb DUMMY, [PF_DST, DUMMY] -- PF add PF_DST, PF_DST, #1 -+ PF ble, 10f -+ PF lsl, DUMMY, DST_STRIDE, #dst_bpp_shift -+ PF ldrsb, DUMMY, [PF_DST, DUMMY] -+ PF add, PF_DST, PF_DST, #1 - 10: - umull v11.8h, v22.8b, v7.8b - .endm - - generate_composite_function \ - pixman_composite_over_8888_8888_asm_neon, 32, 0, 32, \ - FLAG_DST_READWRITE | FLAG_DEINTERLEAVE_32BPP, \ - 8, /* number of pixels, processed in a single block */ \ -@@ -860,40 +860,40 @@ generate_composite_function_single_scanl - urshr v16.8h, v10.8h, #8 - urshr v17.8h, v11.8h, #8 - raddhn v28.8b, v14.8h, v8.8h - raddhn v29.8b, v15.8h, v9.8h - raddhn v30.8b, v16.8h, v10.8h - raddhn v31.8b, v17.8h, v11.8h - ld4 {v4.8b, v5.8b, v6.8b, v7.8b}, [DST_R], #32 - uqadd v28.8b, v0.8b, v28.8b -- PF add PF_X, PF_X, #8 -- PF tst PF_CTL, #0x0F -- PF beq 10f -- PF add PF_X, PF_X, #8 -- PF sub PF_CTL, PF_CTL, #1 -+ PF add, PF_X, PF_X, #8 -+ PF tst, PF_CTL, #0x0F -+ PF beq, 10f -+ PF add, PF_X, PF_X, #8 -+ PF sub, PF_CTL, PF_CTL, #1 - 10: - uqadd v29.8b, v1.8b, v29.8b - uqadd v30.8b, v2.8b, v30.8b - uqadd v31.8b, v3.8b, v31.8b -- PF cmp PF_X, ORIG_W -+ PF cmp, PF_X, ORIG_W - umull v8.8h, v24.8b, v4.8b -- PF lsl DUMMY, PF_X, #dst_bpp_shift -- PF prfm PREFETCH_MODE, [PF_DST, DUMMY] -+ PF lsl, DUMMY, PF_X, #dst_bpp_shift -+ PF prfm, PREFETCH_MODE, [PF_DST, DUMMY] - umull v9.8h, v24.8b, v5.8b -- PF ble 10f -- PF sub PF_X, PF_X, ORIG_W -+ PF ble, 10f -+ PF sub, PF_X, PF_X, ORIG_W - 10: - umull v10.8h, v24.8b, v6.8b -- PF subs PF_CTL, PF_CTL, #0x10 -+ PF subs, PF_CTL, PF_CTL, #0x10 - umull v11.8h, v24.8b, v7.8b -- PF ble 10f -- PF lsl DUMMY, DST_STRIDE, #dst_bpp_shift -- PF ldrsb DUMMY, [PF_DST, DUMMY] -- PF add PF_DST, PF_DST, #1 -+ PF ble, 10f -+ PF lsl, DUMMY, DST_STRIDE, #dst_bpp_shift -+ PF ldrsb, DUMMY, [PF_DST, DUMMY] -+ PF add, PF_DST, PF_DST, #1 - 10: - st4 {v28.8b, v29.8b, v30.8b, v31.8b}, [DST_W], #32 - .endm - - .macro pixman_composite_over_n_8888_init - mov v3.s[0], w4 - dup v0.8b, v3.b[0] - dup v1.8b, v3.b[1] -@@ -912,52 +912,52 @@ generate_composite_function \ - pixman_composite_over_8888_8888_process_pixblock_head, \ - pixman_composite_over_8888_8888_process_pixblock_tail, \ - pixman_composite_over_n_8888_process_pixblock_tail_head - - /******************************************************************************/ - - .macro pixman_composite_over_reverse_n_8888_process_pixblock_tail_head - urshr v14.8h, v8.8h, #8 -- PF add PF_X, PF_X, #8 -- PF tst PF_CTL, #0xF -+ PF add, PF_X, PF_X, #8 -+ PF tst, PF_CTL, #0xF - urshr v15.8h, v9.8h, #8 - urshr v12.8h, v10.8h, #8 - urshr v13.8h, v11.8h, #8 -- PF beq 10f -- PF add PF_X, PF_X, #8 -- PF sub PF_CTL, PF_CTL, #1 -+ PF beq, 10f -+ PF add, PF_X, PF_X, #8 -+ PF sub, PF_CTL, PF_CTL, #1 - 10: - raddhn v28.8b, v14.8h, v8.8h - raddhn v29.8b, v15.8h, v9.8h -- PF cmp PF_X, ORIG_W -+ PF cmp, PF_X, ORIG_W - raddhn v30.8b, v12.8h, v10.8h - raddhn v31.8b, v13.8h, v11.8h - uqadd v28.8b, v0.8b, v28.8b - uqadd v29.8b, v1.8b, v29.8b - uqadd v30.8b, v2.8b, v30.8b - uqadd v31.8b, v3.8b, v31.8b - ld4 {v0.8b, v1.8b, v2.8b, v3.8b}, [DST_R], #32 - mvn v22.8b, v3.8b -- PF lsl DUMMY, PF_X, #dst_bpp_shift -- PF prfm PREFETCH_MODE, [PF_DST, DUMMY] -+ PF lsl, DUMMY, PF_X, #dst_bpp_shift -+ PF prfm, PREFETCH_MODE, [PF_DST, DUMMY] - st4 {v28.8b, v29.8b, v30.8b, v31.8b}, [DST_W], #32 -- PF blt 10f -- PF sub PF_X, PF_X, ORIG_W -+ PF blt, 10f -+ PF sub, PF_X, PF_X, ORIG_W - 10: - umull v8.8h, v22.8b, v4.8b -- PF blt 10f -- PF subs PF_CTL, PF_CTL, #0x10 -+ PF blt, 10f -+ PF subs, PF_CTL, PF_CTL, #0x10 - 10: - umull v9.8h, v22.8b, v5.8b - umull v10.8h, v22.8b, v6.8b -- PF blt 10f -- PF lsl DUMMY, DST_STRIDE, #dst_bpp_shift -- PF ldrsb DUMMY, [PF_DST, DUMMY] -- PF add PF_DST, PF_DST, #1 -+ PF blt, 10f -+ PF lsl, DUMMY, DST_STRIDE, #dst_bpp_shift -+ PF ldrsb, DUMMY, [PF_DST, DUMMY] -+ PF add, PF_DST, PF_DST, #1 - 10: - umull v11.8h, v22.8b, v7.8b - .endm - - .macro pixman_composite_over_reverse_n_8888_init - mov v7.s[0], w4 - dup v4.8b, v7.b[0] - dup v5.8b, v7.b[1] -@@ -1405,45 +1405,45 @@ generate_composite_function \ - rshrn v28.8b, v8.8h, #8 - rshrn v29.8b, v9.8h, #8 - rshrn v30.8b, v10.8h, #8 - rshrn v31.8b, v11.8h, #8 - .endm - - .macro pixman_composite_src_n_8_8888_process_pixblock_tail_head - fetch_mask_pixblock -- PF add PF_X, PF_X, #8 -+ PF add, PF_X, PF_X, #8 - rshrn v28.8b, v8.8h, #8 -- PF tst PF_CTL, #0x0F -+ PF tst, PF_CTL, #0x0F - rshrn v29.8b, v9.8h, #8 -- PF beq 10f -- PF add PF_X, PF_X, #8 -+ PF beq, 10f -+ PF add, PF_X, PF_X, #8 - 10: - rshrn v30.8b, v10.8h, #8 -- PF beq 10f -- PF sub PF_CTL, PF_CTL, #1 -+ PF beq, 10f -+ PF sub, PF_CTL, PF_CTL, #1 - 10: - rshrn v31.8b, v11.8h, #8 -- PF cmp PF_X, ORIG_W -+ PF cmp, PF_X, ORIG_W - umull v8.8h, v24.8b, v0.8b -- PF lsl DUMMY, PF_X, #mask_bpp_shift -- PF prfm PREFETCH_MODE, [PF_MASK, DUMMY] -+ PF lsl, DUMMY, PF_X, #mask_bpp_shift -+ PF prfm, PREFETCH_MODE, [PF_MASK, DUMMY] - umull v9.8h, v24.8b, v1.8b -- PF ble 10f -- PF sub PF_X, PF_X, ORIG_W -+ PF ble, 10f -+ PF sub, PF_X, PF_X, ORIG_W - 10: - umull v10.8h, v24.8b, v2.8b -- PF ble 10f -- PF subs PF_CTL, PF_CTL, #0x10 -+ PF ble, 10f -+ PF subs, PF_CTL, PF_CTL, #0x10 - 10: - umull v11.8h, v24.8b, v3.8b -- PF ble 10f -- PF lsl DUMMY, MASK_STRIDE, #mask_bpp_shift -- PF ldrsb DUMMY, [PF_MASK, DUMMY] -- PF add PF_MASK, PF_MASK, #1 -+ PF ble, 10f -+ PF lsl, DUMMY, MASK_STRIDE, #mask_bpp_shift -+ PF ldrsb, DUMMY, [PF_MASK, DUMMY] -+ PF add, PF_MASK, PF_MASK, #1 - 10: - st4 {v28.8b, v29.8b, v30.8b, v31.8b}, [DST_W], #32 - ursra v8.8h, v8.8h, #8 - ursra v9.8h, v9.8h, #8 - ursra v10.8h, v10.8h, #8 - ursra v11.8h, v11.8h, #8 - .endm - -@@ -1486,45 +1486,45 @@ generate_composite_function \ - rshrn v28.8b, v0.8h, #8 - rshrn v29.8b, v1.8h, #8 - rshrn v30.8b, v2.8h, #8 - rshrn v31.8b, v3.8h, #8 - .endm - - .macro pixman_composite_src_n_8_8_process_pixblock_tail_head - fetch_mask_pixblock -- PF add PF_X, PF_X, #8 -+ PF add, PF_X, PF_X, #8 - rshrn v28.8b, v0.8h, #8 -- PF tst PF_CTL, #0x0F -+ PF tst, PF_CTL, #0x0F - rshrn v29.8b, v1.8h, #8 -- PF beq 10f -- PF add PF_X, PF_X, #8 -+ PF beq, 10f -+ PF add, PF_X, PF_X, #8 - 10: - rshrn v30.8b, v2.8h, #8 -- PF beq 10f -- PF sub PF_CTL, PF_CTL, #1 -+ PF beq, 10f -+ PF sub, PF_CTL, PF_CTL, #1 - 10: - rshrn v31.8b, v3.8h, #8 -- PF cmp PF_X, ORIG_W -+ PF cmp, PF_X, ORIG_W - umull v0.8h, v24.8b, v16.8b -- PF lsl DUMMY, PF_X, mask_bpp_shift -- PF prfm PREFETCH_MODE, [PF_MASK, DUMMY] -+ PF lsl, DUMMY, PF_X, mask_bpp_shift -+ PF prfm, PREFETCH_MODE, [PF_MASK, DUMMY] - umull v1.8h, v25.8b, v16.8b -- PF ble 10f -- PF sub PF_X, PF_X, ORIG_W -+ PF ble, 10f -+ PF sub, PF_X, PF_X, ORIG_W - 10: - umull v2.8h, v26.8b, v16.8b -- PF ble 10f -- PF subs PF_CTL, PF_CTL, #0x10 -+ PF ble, 10f -+ PF subs, PF_CTL, PF_CTL, #0x10 - 10: - umull v3.8h, v27.8b, v16.8b -- PF ble 10f -- PF lsl DUMMY, MASK_STRIDE, #mask_bpp_shift -- PF ldrsb DUMMY, [PF_MASK, DUMMY] -- PF add PF_MASK, PF_MASK, #1 -+ PF ble, 10f -+ PF lsl, DUMMY, MASK_STRIDE, #mask_bpp_shift -+ PF ldrsb, DUMMY, [PF_MASK, DUMMY] -+ PF add, PF_MASK, PF_MASK, #1 - 10: - st1 {v28.8b, v29.8b, v30.8b, v31.8b}, [DST_W], #32 - ursra v0.8h, v0.8h, #8 - ursra v1.8h, v1.8h, #8 - ursra v2.8h, v2.8h, #8 - ursra v3.8h, v3.8h, #8 - .endm - -@@ -1594,54 +1594,54 @@ generate_composite_function \ - .endm - - .macro pixman_composite_over_n_8_8888_process_pixblock_tail_head - urshr v16.8h, v12.8h, #8 - ld4 {v4.8b, v5.8b, v6.8b, v7.8b}, [DST_R], #32 - urshr v17.8h, v13.8h, #8 - fetch_mask_pixblock - urshr v18.8h, v14.8h, #8 -- PF add PF_X, PF_X, #8 -+ PF add, PF_X, PF_X, #8 - urshr v19.8h, v15.8h, #8 -- PF tst PF_CTL, #0x0F -+ PF tst, PF_CTL, #0x0F - raddhn v28.8b, v16.8h, v12.8h -- PF beq 10f -- PF add PF_X, PF_X, #8 -+ PF beq, 10f -+ PF add, PF_X, PF_X, #8 - 10: - raddhn v29.8b, v17.8h, v13.8h -- PF beq 10f -- PF sub PF_CTL, PF_CTL, #1 -+ PF beq, 10f -+ PF sub, PF_CTL, PF_CTL, #1 - 10: - raddhn v30.8b, v18.8h, v14.8h -- PF cmp PF_X, ORIG_W -+ PF cmp, PF_X, ORIG_W - raddhn v31.8b, v19.8h, v15.8h -- PF lsl DUMMY, PF_X, #dst_bpp_shift -- PF prfm PREFETCH_MODE, [PF_DST, DUMMY] -+ PF lsl, DUMMY, PF_X, #dst_bpp_shift -+ PF prfm, PREFETCH_MODE, [PF_DST, DUMMY] - umull v16.8h, v24.8b, v8.8b -- PF lsl DUMMY, PF_X, #mask_bpp_shift -- PF prfm PREFETCH_MODE, [PF_MASK, DUMMY] -+ PF lsl, DUMMY, PF_X, #mask_bpp_shift -+ PF prfm, PREFETCH_MODE, [PF_MASK, DUMMY] - umull v17.8h, v24.8b, v9.8b -- PF ble 10f -- PF sub PF_X, PF_X, ORIG_W -+ PF ble, 10f -+ PF sub, PF_X, PF_X, ORIG_W - 10: - umull v18.8h, v24.8b, v10.8b -- PF ble 10f -- PF subs PF_CTL, PF_CTL, #0x10 -+ PF ble, 10f -+ PF subs, PF_CTL, PF_CTL, #0x10 - 10: - umull v19.8h, v24.8b, v11.8b -- PF ble 10f -- PF lsl DUMMY, DST_STRIDE, #dst_bpp_shift -- PF ldrsb DUMMY, [PF_DST, DUMMY] -- PF add PF_DST, PF_DST, #1 -+ PF ble, 10f -+ PF lsl, DUMMY, DST_STRIDE, #dst_bpp_shift -+ PF ldrsb, DUMMY, [PF_DST, DUMMY] -+ PF add, PF_DST, PF_DST, #1 - 10: - uqadd v28.8b, v0.8b, v28.8b -- PF ble 10f -- PF lsl DUMMY, MASK_STRIDE, #mask_bpp_shift -- PF ldrsb DUMMY, [PF_MASK, DUMMY] -- PF add PF_MASK, PF_MASK, #1 -+ PF ble, 10f -+ PF lsl, DUMMY, MASK_STRIDE, #mask_bpp_shift -+ PF ldrsb, DUMMY, [PF_MASK, DUMMY] -+ PF add, PF_MASK, PF_MASK, #1 - 10: - uqadd v29.8b, v1.8b, v29.8b - uqadd v30.8b, v2.8b, v30.8b - uqadd v31.8b, v3.8b, v31.8b - urshr v12.8h, v16.8h, #8 - urshr v13.8h, v17.8h, #8 - urshr v14.8h, v18.8h, #8 - urshr v15.8h, v19.8h, #8 -@@ -2407,17 +2407,17 @@ generate_composite_function \ - generate_composite_function_single_scanline \ - pixman_composite_scanline_out_reverse_mask_asm_neon, 32, 32, 32, \ - FLAG_DST_READWRITE | FLAG_DEINTERLEAVE_32BPP, \ - 8, /* number of pixels, processed in a single block */ \ - default_init_need_all_regs, \ - default_cleanup_need_all_regs, \ - pixman_composite_out_reverse_8888_n_8888_process_pixblock_head, \ - pixman_composite_out_reverse_8888_n_8888_process_pixblock_tail, \ -- pixman_composite_out_reverse_8888_8888_8888_process_pixblock_tail_head \ -+ pixman_composite_out_reverse_8888_8888_8888_process_pixblock_tail_head, \ - 28, /* dst_w_basereg */ \ - 4, /* dst_r_basereg */ \ - 0, /* src_basereg */ \ - 12 /* mask_basereg */ - - /******************************************************************************/ - - .macro pixman_composite_over_8888_n_8888_process_pixblock_head -@@ -2482,31 +2482,31 @@ generate_composite_function \ - pixman_composite_over_8888_8888_8888_asm_neon, 32, 32, 32, \ - FLAG_DST_READWRITE | FLAG_DEINTERLEAVE_32BPP, \ - 8, /* number of pixels, processed in a single block */ \ - 5, /* prefetch distance */ \ - default_init_need_all_regs, \ - default_cleanup_need_all_regs, \ - pixman_composite_over_8888_n_8888_process_pixblock_head, \ - pixman_composite_over_8888_n_8888_process_pixblock_tail, \ -- pixman_composite_over_8888_8888_8888_process_pixblock_tail_head \ -+ pixman_composite_over_8888_8888_8888_process_pixblock_tail_head, \ - 28, /* dst_w_basereg */ \ - 4, /* dst_r_basereg */ \ - 0, /* src_basereg */ \ - 12 /* mask_basereg */ - - generate_composite_function_single_scanline \ - pixman_composite_scanline_over_mask_asm_neon, 32, 32, 32, \ - FLAG_DST_READWRITE | FLAG_DEINTERLEAVE_32BPP, \ - 8, /* number of pixels, processed in a single block */ \ - default_init_need_all_regs, \ - default_cleanup_need_all_regs, \ - pixman_composite_over_8888_n_8888_process_pixblock_head, \ - pixman_composite_over_8888_n_8888_process_pixblock_tail, \ -- pixman_composite_over_8888_8888_8888_process_pixblock_tail_head \ -+ pixman_composite_over_8888_8888_8888_process_pixblock_tail_head, \ - 28, /* dst_w_basereg */ \ - 4, /* dst_r_basereg */ \ - 0, /* src_basereg */ \ - 12 /* mask_basereg */ - - /******************************************************************************/ - - /* TODO: expand macros and do better instructions scheduling */ -@@ -2524,17 +2524,17 @@ generate_composite_function \ - pixman_composite_over_8888_8_8888_asm_neon, 32, 8, 32, \ - FLAG_DST_READWRITE | FLAG_DEINTERLEAVE_32BPP, \ - 8, /* number of pixels, processed in a single block */ \ - 5, /* prefetch distance */ \ - default_init_need_all_regs, \ - default_cleanup_need_all_regs, \ - pixman_composite_over_8888_n_8888_process_pixblock_head, \ - pixman_composite_over_8888_n_8888_process_pixblock_tail, \ -- pixman_composite_over_8888_8_8888_process_pixblock_tail_head \ -+ pixman_composite_over_8888_8_8888_process_pixblock_tail_head, \ - 28, /* dst_w_basereg */ \ - 4, /* dst_r_basereg */ \ - 0, /* src_basereg */ \ - 15 /* mask_basereg */ - - /******************************************************************************/ - - .macro pixman_composite_src_0888_0888_process_pixblock_head -@@ -2675,38 +2675,38 @@ generate_composite_function \ - urshr v11.8h, v8.8h, #8 - mov v30.8b, v31.8b - mov v31.8b, v3.8b - mov v3.8b, v31.8b - urshr v12.8h, v9.8h, #8 - urshr v13.8h, v10.8h, #8 - fetch_src_pixblock - raddhn v30.8b, v11.8h, v8.8h -- PF add PF_X, PF_X, #8 -- PF tst PF_CTL, #0xF -- PF beq 10f -- PF add PF_X, PF_X, #8 -- PF sub PF_CTL, PF_CTL, #1 -+ PF add, PF_X, PF_X, #8 -+ PF tst, PF_CTL, #0xF -+ PF beq, 10f -+ PF add, PF_X, PF_X, #8 -+ PF sub, PF_CTL, PF_CTL, #1 - 10: - raddhn v29.8b, v12.8h, v9.8h - raddhn v28.8b, v13.8h, v10.8h - umull v8.8h, v3.8b, v0.8b - umull v9.8h, v3.8b, v1.8b - umull v10.8h, v3.8b, v2.8b - st4 {v28.8b, v29.8b, v30.8b, v31.8b}, [DST_W], #32 -- PF cmp PF_X, ORIG_W -- PF lsl DUMMY, PF_X, src_bpp_shift -- PF prfm PREFETCH_MODE, [PF_SRC, DUMMY] -- PF ble 10f -- PF sub PF_X, PF_X, ORIG_W -- PF subs PF_CTL, PF_CTL, #0x10 -- PF ble 10f -- PF lsl DUMMY, SRC_STRIDE, #src_bpp_shift -- PF ldrsb DUMMY, [PF_SRC, DUMMY] -- PF add PF_SRC, PF_SRC, #1 -+ PF cmp, PF_X, ORIG_W -+ PF lsl, DUMMY, PF_X, src_bpp_shift -+ PF prfm, PREFETCH_MODE, [PF_SRC, DUMMY] -+ PF ble, 10f -+ PF sub, PF_X, PF_X, ORIG_W -+ PF subs, PF_CTL, PF_CTL, #0x10 -+ PF ble, 10f -+ PF lsl, DUMMY, SRC_STRIDE, #src_bpp_shift -+ PF ldrsb, DUMMY, [PF_SRC, DUMMY] -+ PF add, PF_SRC, PF_SRC, #1 - 10: - .endm - - generate_composite_function \ - pixman_composite_src_pixbuf_8888_asm_neon, 32, 0, 32, \ - FLAG_DST_WRITEONLY | FLAG_DEINTERLEAVE_32BPP, \ - 8, /* number of pixels, processed in a single block */ \ - 10, /* prefetch distance */ \ -@@ -2744,38 +2744,38 @@ generate_composite_function \ - urshr v11.8h, v8.8h, #8 - mov v30.8b, v31.8b - mov v31.8b, v3.8b - mov v3.8b, v30.8b - urshr v12.8h, v9.8h, #8 - urshr v13.8h, v10.8h, #8 - fetch_src_pixblock - raddhn v28.8b, v11.8h, v8.8h -- PF add PF_X, PF_X, #8 -- PF tst PF_CTL, #0xF -- PF beq 10f -- PF add PF_X, PF_X, #8 -- PF sub PF_CTL, PF_CTL, #1 -+ PF add, PF_X, PF_X, #8 -+ PF tst, PF_CTL, #0xF -+ PF beq, 10f -+ PF add, PF_X, PF_X, #8 -+ PF sub, PF_CTL, PF_CTL, #1 - 10: - raddhn v29.8b, v12.8h, v9.8h - raddhn v30.8b, v13.8h, v10.8h - umull v8.8h, v3.8b, v0.8b - umull v9.8h, v3.8b, v1.8b - umull v10.8h, v3.8b, v2.8b - st4 {v28.8b, v29.8b, v30.8b, v31.8b}, [DST_W], #32 -- PF cmp PF_X, ORIG_W -- PF lsl DUMMY, PF_X, src_bpp_shift -- PF prfm PREFETCH_MODE, [PF_SRC, DUMMY] -- PF ble 10f -- PF sub PF_X, PF_X, ORIG_W -- PF subs PF_CTL, PF_CTL, #0x10 -- PF ble 10f -- PF lsl DUMMY, SRC_STRIDE, #src_bpp_shift -- PF ldrsb DUMMY, [PF_SRC, DUMMY] -- PF add PF_SRC, PF_SRC, #1 -+ PF cmp, PF_X, ORIG_W -+ PF lsl, DUMMY, PF_X, src_bpp_shift -+ PF prfm, PREFETCH_MODE, [PF_SRC, DUMMY] -+ PF ble, 10f -+ PF sub, PF_X, PF_X, ORIG_W -+ PF subs, PF_CTL, PF_CTL, #0x10 -+ PF ble, 10f -+ PF lsl, DUMMY, SRC_STRIDE, #src_bpp_shift -+ PF ldrsb, DUMMY, [PF_SRC, DUMMY] -+ PF add, PF_SRC, PF_SRC, #1 - 10: - .endm - - generate_composite_function \ - pixman_composite_src_rpixbuf_8888_asm_neon, 32, 0, 32, \ - FLAG_DST_WRITEONLY | FLAG_DEINTERLEAVE_32BPP, \ - 8, /* number of pixels, processed in a single block */ \ - 10, /* prefetch distance */ \ -@@ -3126,197 +3126,197 @@ generate_composite_function_nearest_scan - * format conversion, and interpolation as separate macros which can be used - * as the basic building blocks for constructing bilinear scanline functions. - */ - - .macro bilinear_load_8888 reg1, reg2, tmp - asr TMP1, X, #16 - add X, X, UX - add TMP1, TOP, TMP1, lsl #2 -- ld1 {®1&.2s}, [TMP1], STRIDE -- ld1 {®2&.2s}, [TMP1] -+ ld1 {\()\reg1\().2s}, [TMP1], STRIDE -+ ld1 {\()\reg2\().2s}, [TMP1] - .endm - - .macro bilinear_load_0565 reg1, reg2, tmp - asr TMP1, X, #16 - add X, X, UX - add TMP1, TOP, TMP1, lsl #1 -- ld1 {®2&.s}[0], [TMP1], STRIDE -- ld1 {®2&.s}[1], [TMP1] -- convert_four_0565_to_x888_packed reg2, reg1, reg2, tmp -+ ld1 {\()\reg2\().s}[0], [TMP1], STRIDE -+ ld1 {\()\reg2\().s}[1], [TMP1] -+ convert_four_0565_to_x888_packed \reg2, \reg1, \reg2, \tmp - .endm - - .macro bilinear_load_and_vertical_interpolate_two_8888 \ - acc1, acc2, reg1, reg2, reg3, reg4, tmp1, tmp2 - -- bilinear_load_8888 reg1, reg2, tmp1 -- umull &acc1&.8h, ®1&.8b, v28.8b -- umlal &acc1&.8h, ®2&.8b, v29.8b -- bilinear_load_8888 reg3, reg4, tmp2 -- umull &acc2&.8h, ®3&.8b, v28.8b -- umlal &acc2&.8h, ®4&.8b, v29.8b -+ bilinear_load_8888 \reg1, \reg2, \tmp1 -+ umull \()\acc1\().8h, \()\reg1\().8b, v28.8b -+ umlal \()\acc1\().8h, \()\reg2\().8b, v29.8b -+ bilinear_load_8888 \reg3, \reg4, \tmp2 -+ umull \()\acc2\().8h, \()\reg3\().8b, v28.8b -+ umlal \()\acc2\().8h, \()\reg4\().8b, v29.8b - .endm - - .macro bilinear_load_and_vertical_interpolate_four_8888 \ -- xacc1, xacc2, xreg1, xreg2, xreg3, xreg4, xacc2lo, xacc2hi \ -+ xacc1, xacc2, xreg1, xreg2, xreg3, xreg4, xacc2lo, xacc2hi, \ - yacc1, yacc2, yreg1, yreg2, yreg3, yreg4, yacc2lo, yacc2hi - - bilinear_load_and_vertical_interpolate_two_8888 \ -- xacc1, xacc2, xreg1, xreg2, xreg3, xreg4, xacc2lo, xacc2hi -+ \xacc1, \xacc2, \xreg1, \xreg2, \xreg3, \xreg4, \xacc2lo, \xacc2hi - bilinear_load_and_vertical_interpolate_two_8888 \ -- yacc1, yacc2, yreg1, yreg2, yreg3, yreg4, yacc2lo, yacc2hi -+ \yacc1, \yacc2, \yreg1, \yreg2, \yreg3, \yreg4, \yacc2lo, \yacc2hi - .endm - - .macro vzip reg1, reg2 - umov TMP4, v31.d[0] -- zip1 v31.8b, reg1, reg2 -- zip2 reg2, reg1, reg2 -- mov reg1, v31.8b -+ zip1 v31.8b, \reg1, \reg2 -+ zip2 \reg2, \reg1, \reg2 -+ mov \reg1, v31.8b - mov v31.d[0], TMP4 - .endm - - .macro vuzp reg1, reg2 - umov TMP4, v31.d[0] -- uzp1 v31.8b, reg1, reg2 -- uzp2 reg2, reg1, reg2 -- mov reg1, v31.8b -+ uzp1 v31.8b, \reg1, \reg2 -+ uzp2 \reg2, \reg1, \reg2 -+ mov \reg1, v31.8b - mov v31.d[0], TMP4 - .endm - - .macro bilinear_load_and_vertical_interpolate_two_0565 \ - acc1, acc2, reg1, reg2, reg3, reg4, acc2lo, acc2hi - asr TMP1, X, #16 - add X, X, UX - add TMP1, TOP, TMP1, lsl #1 - asr TMP2, X, #16 - add X, X, UX - add TMP2, TOP, TMP2, lsl #1 -- ld1 {&acc2&.s}[0], [TMP1], STRIDE -- ld1 {&acc2&.s}[2], [TMP2], STRIDE -- ld1 {&acc2&.s}[1], [TMP1] -- ld1 {&acc2&.s}[3], [TMP2] -- convert_0565_to_x888 acc2, reg3, reg2, reg1 -- vzip ®1&.8b, ®3&.8b -- vzip ®2&.8b, ®4&.8b -- vzip ®3&.8b, ®4&.8b -- vzip ®1&.8b, ®2&.8b -- umull &acc1&.8h, ®1&.8b, v28.8b -- umlal &acc1&.8h, ®2&.8b, v29.8b -- umull &acc2&.8h, ®3&.8b, v28.8b -- umlal &acc2&.8h, ®4&.8b, v29.8b -+ ld1 {\()\acc2\().s}[0], [TMP1], STRIDE -+ ld1 {\()\acc2\().s}[2], [TMP2], STRIDE -+ ld1 {\()\acc2\().s}[1], [TMP1] -+ ld1 {\()\acc2\().s}[3], [TMP2] -+ convert_0565_to_x888 \acc2, \reg3, \reg2, \reg1 -+ vzip \()\reg1\().8b, \()\reg3\().8b -+ vzip \()\reg2\().8b, \()\reg4\().8b -+ vzip \()\reg3\().8b, \()\reg4\().8b -+ vzip \()\reg1\().8b, \()\reg2\().8b -+ umull \()\acc1\().8h, \()\reg1\().8b, v28.8b -+ umlal \()\acc1\().8h, \()\reg2\().8b, v29.8b -+ umull \()\acc2\().8h, \()\reg3\().8b, v28.8b -+ umlal \()\acc2\().8h, \()\reg4\().8b, v29.8b - .endm - - .macro bilinear_load_and_vertical_interpolate_four_0565 \ -- xacc1, xacc2, xreg1, xreg2, xreg3, xreg4, xacc2lo, xacc2hi \ -+ xacc1, xacc2, xreg1, xreg2, xreg3, xreg4, xacc2lo, xacc2hi, \ - yacc1, yacc2, yreg1, yreg2, yreg3, yreg4, yacc2lo, yacc2hi - asr TMP1, X, #16 - add X, X, UX - add TMP1, TOP, TMP1, lsl #1 - asr TMP2, X, #16 - add X, X, UX - add TMP2, TOP, TMP2, lsl #1 -- ld1 {&xacc2&.s}[0], [TMP1], STRIDE -- ld1 {&xacc2&.s}[2], [TMP2], STRIDE -- ld1 {&xacc2&.s}[1], [TMP1] -- ld1 {&xacc2&.s}[3], [TMP2] -- convert_0565_to_x888 xacc2, xreg3, xreg2, xreg1 -+ ld1 {\()\xacc2\().s}[0], [TMP1], STRIDE -+ ld1 {\()\xacc2\().s}[2], [TMP2], STRIDE -+ ld1 {\()\xacc2\().s}[1], [TMP1] -+ ld1 {\()\xacc2\().s}[3], [TMP2] -+ convert_0565_to_x888 \xacc2, \xreg3, \xreg2, \xreg1 - asr TMP1, X, #16 - add X, X, UX - add TMP1, TOP, TMP1, lsl #1 - asr TMP2, X, #16 - add X, X, UX - add TMP2, TOP, TMP2, lsl #1 -- ld1 {&yacc2&.s}[0], [TMP1], STRIDE -- vzip &xreg1&.8b, &xreg3&.8b -- ld1 {&yacc2&.s}[2], [TMP2], STRIDE -- vzip &xreg2&.8b, &xreg4&.8b -- ld1 {&yacc2&.s}[1], [TMP1] -- vzip &xreg3&.8b, &xreg4&.8b -- ld1 {&yacc2&.s}[3], [TMP2] -- vzip &xreg1&.8b, &xreg2&.8b -- convert_0565_to_x888 yacc2, yreg3, yreg2, yreg1 -- umull &xacc1&.8h, &xreg1&.8b, v28.8b -- vzip &yreg1&.8b, &yreg3&.8b -- umlal &xacc1&.8h, &xreg2&.8b, v29.8b -- vzip &yreg2&.8b, &yreg4&.8b -- umull &xacc2&.8h, &xreg3&.8b, v28.8b -- vzip &yreg3&.8b, &yreg4&.8b -- umlal &xacc2&.8h, &xreg4&.8b, v29.8b -- vzip &yreg1&.8b, &yreg2&.8b -- umull &yacc1&.8h, &yreg1&.8b, v28.8b -- umlal &yacc1&.8h, &yreg2&.8b, v29.8b -- umull &yacc2&.8h, &yreg3&.8b, v28.8b -- umlal &yacc2&.8h, &yreg4&.8b, v29.8b -+ ld1 {\()\yacc2\().s}[0], [TMP1], STRIDE -+ vzip \()\xreg1\().8b, \()\xreg3\().8b -+ ld1 {\()\yacc2\().s}[2], [TMP2], STRIDE -+ vzip \()\xreg2\().8b, \()\xreg4\().8b -+ ld1 {\()\yacc2\().s}[1], [TMP1] -+ vzip \()\xreg3\().8b, \()\xreg4\().8b -+ ld1 {\()\yacc2\().s}[3], [TMP2] -+ vzip \()\xreg1\().8b, \()\xreg2\().8b -+ convert_0565_to_x888 \yacc2, \yreg3, \yreg2, \yreg1 -+ umull \()\xacc1\().8h, \()\xreg1\().8b, v28.8b -+ vzip \()\yreg1\().8b, \()\yreg3\().8b -+ umlal \()\xacc1\().8h, \()\xreg2\().8b, v29.8b -+ vzip \()\yreg2\().8b, \()\yreg4\().8b -+ umull \()\xacc2\().8h, \()\xreg3\().8b, v28.8b -+ vzip \()\yreg3\().8b, \()\yreg4\().8b -+ umlal \()\xacc2\().8h, \()\xreg4\().8b, v29.8b -+ vzip \()\yreg1\().8b, \()\yreg2\().8b -+ umull \()\yacc1\().8h, \()\yreg1\().8b, v28.8b -+ umlal \()\yacc1\().8h, \()\yreg2\().8b, v29.8b -+ umull \()\yacc2\().8h, \()\yreg3\().8b, v28.8b -+ umlal \()\yacc2\().8h, \()\yreg4\().8b, v29.8b - .endm - - .macro bilinear_store_8888 numpix, tmp1, tmp2 --.if numpix == 4 -+.if \numpix == 4 - st1 {v0.2s, v1.2s}, [OUT], #16 --.elseif numpix == 2 -+.elseif \numpix == 2 - st1 {v0.2s}, [OUT], #8 --.elseif numpix == 1 -+.elseif \numpix == 1 - st1 {v0.s}[0], [OUT], #4 - .else -- .error bilinear_store_8888 numpix is unsupported -+ .error bilinear_store_8888 \numpix is unsupported - .endif - .endm - - .macro bilinear_store_0565 numpix, tmp1, tmp2 - vuzp v0.8b, v1.8b - vuzp v2.8b, v3.8b - vuzp v1.8b, v3.8b - vuzp v0.8b, v2.8b -- convert_8888_to_0565 v2, v1, v0, v1, tmp1, tmp2 --.if numpix == 4 -+ convert_8888_to_0565 v2, v1, v0, v1, \tmp1, \tmp2 -+.if \numpix == 4 - st1 {v1.4h}, [OUT], #8 --.elseif numpix == 2 -+.elseif \numpix == 2 - st1 {v1.s}[0], [OUT], #4 --.elseif numpix == 1 -+.elseif \numpix == 1 - st1 {v1.h}[0], [OUT], #2 - .else -- .error bilinear_store_0565 numpix is unsupported -+ .error bilinear_store_0565 \numpix is unsupported - .endif - .endm - - .macro bilinear_interpolate_last_pixel src_fmt, dst_fmt -- bilinear_load_&src_fmt v0, v1, v2 -+ bilinear_load_\()\src_fmt v0, v1, v2 - umull v2.8h, v0.8b, v28.8b - umlal v2.8h, v1.8b, v29.8b - /* 5 cycles bubble */ - ushll v0.4s, v2.4h, #BILINEAR_INTERPOLATION_BITS - umlsl v0.4s, v2.4h, v15.h[0] - umlal2 v0.4s, v2.8h, v15.h[0] - /* 5 cycles bubble */ - shrn v0.4h, v0.4s, #(2 * BILINEAR_INTERPOLATION_BITS) - /* 3 cycles bubble */ - xtn v0.8b, v0.8h - /* 1 cycle bubble */ -- bilinear_store_&dst_fmt 1, v3, v4 -+ bilinear_store_\()\dst_fmt 1, v3, v4 - .endm - - .macro bilinear_interpolate_two_pixels src_fmt, dst_fmt -- bilinear_load_and_vertical_interpolate_two_&src_fmt \ -+ bilinear_load_and_vertical_interpolate_two_\()\src_fmt \ - v1, v11, v2, v3, v20, v21, v22, v23 - ushll v0.4s, v1.4h, #BILINEAR_INTERPOLATION_BITS - umlsl v0.4s, v1.4h, v15.h[0] - umlal2 v0.4s, v1.8h, v15.h[0] - ushll v10.4s, v11.4h, #BILINEAR_INTERPOLATION_BITS - umlsl v10.4s, v11.4h, v15.h[4] - umlal2 v10.4s, v11.8h, v15.h[4] - shrn v0.4h, v0.4s, #(2 * BILINEAR_INTERPOLATION_BITS) - shrn2 v0.8h, v10.4s, #(2 * BILINEAR_INTERPOLATION_BITS) - ushr v15.8h, v12.8h, #(16 - BILINEAR_INTERPOLATION_BITS) - add v12.8h, v12.8h, v13.8h - xtn v0.8b, v0.8h -- bilinear_store_&dst_fmt 2, v3, v4 -+ bilinear_store_\()\dst_fmt 2, v3, v4 - .endm - - .macro bilinear_interpolate_four_pixels src_fmt, dst_fmt -- bilinear_load_and_vertical_interpolate_four_&src_fmt \ -- v1, v11, v14, v20, v16, v17, v22, v23 \ -+ bilinear_load_and_vertical_interpolate_four_\()\src_fmt \ -+ v1, v11, v14, v20, v16, v17, v22, v23, \ - v3, v9, v24, v25, v26, v27, v18, v19 - prfm PREFETCH_MODE, [TMP1, PF_OFFS] - sub TMP1, TMP1, STRIDE - ushll v0.4s, v1.4h, #BILINEAR_INTERPOLATION_BITS - umlsl v0.4s, v1.4h, v15.h[0] - umlal2 v0.4s, v1.8h, v15.h[0] - ushll v10.4s, v11.4h, #BILINEAR_INTERPOLATION_BITS - umlsl v10.4s, v11.4h, v15.h[4] -@@ -3333,64 +3333,64 @@ generate_composite_function_nearest_scan - shrn v0.4h, v0.4s, #(2 * BILINEAR_INTERPOLATION_BITS) - shrn2 v0.8h, v10.4s, #(2 * BILINEAR_INTERPOLATION_BITS) - shrn v2.4h, v2.4s, #(2 * BILINEAR_INTERPOLATION_BITS) - shrn2 v2.8h, v8.4s, #(2 * BILINEAR_INTERPOLATION_BITS) - ushr v15.8h, v12.8h, #(16 - BILINEAR_INTERPOLATION_BITS) - xtn v0.8b, v0.8h - xtn v1.8b, v2.8h - add v12.8h, v12.8h, v13.8h -- bilinear_store_&dst_fmt 4, v3, v4 -+ bilinear_store_\()\dst_fmt 4, v3, v4 - .endm - - .macro bilinear_interpolate_four_pixels_head src_fmt, dst_fmt --.ifdef have_bilinear_interpolate_four_pixels_&src_fmt&_&dst_fmt -- bilinear_interpolate_four_pixels_&src_fmt&_&dst_fmt&_head -+.ifdef have_bilinear_interpolate_four_pixels_\()\src_fmt\()_\()\dst_fmt -+ bilinear_interpolate_four_pixels_\()\src_fmt\()_\()\dst_fmt\()_head - .else -- bilinear_interpolate_four_pixels src_fmt, dst_fmt -+ bilinear_interpolate_four_pixels \src_fmt, \dst_fmt - .endif - .endm - - .macro bilinear_interpolate_four_pixels_tail src_fmt, dst_fmt --.ifdef have_bilinear_interpolate_four_pixels_&src_fmt&_&dst_fmt -- bilinear_interpolate_four_pixels_&src_fmt&_&dst_fmt&_tail -+.ifdef have_bilinear_interpolate_four_pixels_\()\src_fmt\()_\()\dst_fmt -+ bilinear_interpolate_four_pixels_\()\src_fmt\()_\()\dst_fmt\()_tail - .endif - .endm - - .macro bilinear_interpolate_four_pixels_tail_head src_fmt, dst_fmt --.ifdef have_bilinear_interpolate_four_pixels_&src_fmt&_&dst_fmt -- bilinear_interpolate_four_pixels_&src_fmt&_&dst_fmt&_tail_head -+.ifdef have_bilinear_interpolate_four_pixels_\()\src_fmt\()_\()\dst_fmt -+ bilinear_interpolate_four_pixels_\()\src_fmt\()_\()\dst_fmt\()_tail_head - .else -- bilinear_interpolate_four_pixels src_fmt, dst_fmt -+ bilinear_interpolate_four_pixels \src_fmt, \dst_fmt - .endif - .endm - - .macro bilinear_interpolate_eight_pixels_head src_fmt, dst_fmt --.ifdef have_bilinear_interpolate_eight_pixels_&src_fmt&_&dst_fmt -- bilinear_interpolate_eight_pixels_&src_fmt&_&dst_fmt&_head -+.ifdef have_bilinear_interpolate_eight_pixels_\()\src_fmt\()_\()\dst_fmt -+ bilinear_interpolate_eight_pixels_\()\src_fmt\()_\()\dst_fmt\()_head - .else -- bilinear_interpolate_four_pixels_head src_fmt, dst_fmt -- bilinear_interpolate_four_pixels_tail_head src_fmt, dst_fmt -+ bilinear_interpolate_four_pixels_head \src_fmt, \dst_fmt -+ bilinear_interpolate_four_pixels_tail_head \src_fmt, \dst_fmt - .endif - .endm - - .macro bilinear_interpolate_eight_pixels_tail src_fmt, dst_fmt --.ifdef have_bilinear_interpolate_eight_pixels_&src_fmt&_&dst_fmt -- bilinear_interpolate_eight_pixels_&src_fmt&_&dst_fmt&_tail -+.ifdef have_bilinear_interpolate_eight_pixels_\()\src_fmt\()_\()\dst_fmt -+ bilinear_interpolate_eight_pixels_\()\src_fmt\()_\()\dst_fmt\()_tail - .else -- bilinear_interpolate_four_pixels_tail src_fmt, dst_fmt -+ bilinear_interpolate_four_pixels_tail \src_fmt, \dst_fmt - .endif - .endm - - .macro bilinear_interpolate_eight_pixels_tail_head src_fmt, dst_fmt --.ifdef have_bilinear_interpolate_eight_pixels_&src_fmt&_&dst_fmt -- bilinear_interpolate_eight_pixels_&src_fmt&_&dst_fmt&_tail_head -+.ifdef have_bilinear_interpolate_eight_pixels_\()\src_fmt\()_\()\dst_fmt -+ bilinear_interpolate_eight_pixels_\()\src_fmt\()_\()\dst_fmt\()_tail_head - .else -- bilinear_interpolate_four_pixels_tail_head src_fmt, dst_fmt -- bilinear_interpolate_four_pixels_tail_head src_fmt, dst_fmt -+ bilinear_interpolate_four_pixels_tail_head \src_fmt, \dst_fmt -+ bilinear_interpolate_four_pixels_tail_head \src_fmt, \dst_fmt - .endif - .endm - - .set BILINEAR_FLAG_UNROLL_4, 0 - .set BILINEAR_FLAG_UNROLL_8, 1 - .set BILINEAR_FLAG_USE_ALL_NEON_REGS, 2 - - /* -@@ -3405,17 +3405,17 @@ generate_composite_function_nearest_scan - * prefetch_distance - prefetch in the source image by that many - * pixels ahead - */ - - .macro generate_bilinear_scanline_func fname, src_fmt, dst_fmt, \ - src_bpp_shift, dst_bpp_shift, \ - prefetch_distance, flags - --pixman_asm_function fname -+pixman_asm_function \fname - OUT .req x0 - TOP .req x1 - BOTTOM .req x2 - WT .req x3 - WB .req x4 - X .req x5 - UX .req x6 - WIDTH .req x7 -@@ -3437,17 +3437,17 @@ pixman_asm_function fname - sub sp, sp, 112 /* push all registers */ - sub x29, x29, 64 - st1 {v8.8b, v9.8b, v10.8b, v11.8b}, [x29], #32 - st1 {v12.8b, v13.8b, v14.8b, v15.8b}, [x29], #32 - stp x8, x9, [x29, -80] - stp x10, x11, [x29, -96] - stp x12, x13, [x29, -112] - -- mov PF_OFFS, #prefetch_distance -+ mov PF_OFFS, #\prefetch_distance - mul PF_OFFS, PF_OFFS, UX - - subs STRIDE, BOTTOM, TOP - .unreq BOTTOM - - cmp WIDTH, #0 - ble 300f - -@@ -3458,85 +3458,85 @@ pixman_asm_function fname - mov v25.d[0], v12.d[1] - mov v26.d[0], v13.d[0] - add v25.4h, v25.4h, v26.4h - mov v12.d[1], v25.d[0] - - /* ensure good destination alignment */ - cmp WIDTH, #1 - blt 100f -- tst OUT, #(1 << dst_bpp_shift) -+ tst OUT, #(1 << \dst_bpp_shift) - beq 100f - ushr v15.8h, v12.8h, #(16 - BILINEAR_INTERPOLATION_BITS) - add v12.8h, v12.8h, v13.8h -- bilinear_interpolate_last_pixel src_fmt, dst_fmt -+ bilinear_interpolate_last_pixel \src_fmt, \dst_fmt - sub WIDTH, WIDTH, #1 - 100: - add v13.8h, v13.8h, v13.8h - ushr v15.8h, v12.8h, #(16 - BILINEAR_INTERPOLATION_BITS) - add v12.8h, v12.8h, v13.8h - - cmp WIDTH, #2 - blt 100f -- tst OUT, #(1 << (dst_bpp_shift + 1)) -+ tst OUT, #(1 << (\dst_bpp_shift + 1)) - beq 100f -- bilinear_interpolate_two_pixels src_fmt, dst_fmt -+ bilinear_interpolate_two_pixels \src_fmt, \dst_fmt - sub WIDTH, WIDTH, #2 - 100: --.if ((flags) & BILINEAR_FLAG_UNROLL_8) != 0 -+.if ((\flags) & BILINEAR_FLAG_UNROLL_8) != 0 - /*********** 8 pixels per iteration *****************/ - cmp WIDTH, #4 - blt 100f -- tst OUT, #(1 << (dst_bpp_shift + 2)) -+ tst OUT, #(1 << (\dst_bpp_shift + 2)) - beq 100f -- bilinear_interpolate_four_pixels src_fmt, dst_fmt -+ bilinear_interpolate_four_pixels \src_fmt, \dst_fmt - sub WIDTH, WIDTH, #4 - 100: - subs WIDTH, WIDTH, #8 - blt 100f -- asr PF_OFFS, PF_OFFS, #(16 - src_bpp_shift) -- bilinear_interpolate_eight_pixels_head src_fmt, dst_fmt -+ asr PF_OFFS, PF_OFFS, #(16 - \src_bpp_shift) -+ bilinear_interpolate_eight_pixels_head \src_fmt, \dst_fmt - subs WIDTH, WIDTH, #8 - blt 500f - 1000: -- bilinear_interpolate_eight_pixels_tail_head src_fmt, dst_fmt -+ bilinear_interpolate_eight_pixels_tail_head \src_fmt, \dst_fmt - subs WIDTH, WIDTH, #8 - bge 1000b - 500: -- bilinear_interpolate_eight_pixels_tail src_fmt, dst_fmt -+ bilinear_interpolate_eight_pixels_tail \src_fmt, \dst_fmt - 100: - tst WIDTH, #4 - beq 200f -- bilinear_interpolate_four_pixels src_fmt, dst_fmt -+ bilinear_interpolate_four_pixels \src_fmt, \dst_fmt - 200: - .else - /*********** 4 pixels per iteration *****************/ - subs WIDTH, WIDTH, #4 - blt 100f -- asr PF_OFFS, PF_OFFS, #(16 - src_bpp_shift) -- bilinear_interpolate_four_pixels_head src_fmt, dst_fmt -+ asr PF_OFFS, PF_OFFS, #(16 - \src_bpp_shift) -+ bilinear_interpolate_four_pixels_head \src_fmt, \dst_fmt - subs WIDTH, WIDTH, #4 - blt 500f - 1000: -- bilinear_interpolate_four_pixels_tail_head src_fmt, dst_fmt -+ bilinear_interpolate_four_pixels_tail_head \src_fmt, \dst_fmt - subs WIDTH, WIDTH, #4 - bge 1000b - 500: -- bilinear_interpolate_four_pixels_tail src_fmt, dst_fmt -+ bilinear_interpolate_four_pixels_tail \src_fmt, \dst_fmt - 100: - /****************************************************/ - .endif - /* handle the remaining trailing pixels */ - tst WIDTH, #2 - beq 200f -- bilinear_interpolate_two_pixels src_fmt, dst_fmt -+ bilinear_interpolate_two_pixels \src_fmt, \dst_fmt - 200: - tst WIDTH, #1 - beq 300f -- bilinear_interpolate_last_pixel src_fmt, dst_fmt -+ bilinear_interpolate_last_pixel \src_fmt, \dst_fmt - 300: - sub x29, x29, 64 - ld1 {v8.8b, v9.8b, v10.8b, v11.8b}, [x29], #32 - ld1 {v12.8b, v13.8b, v14.8b, v15.8b}, [x29], #32 - ldp x8, x9, [x29, -80] - ldp x10, x11, [x29, -96] - ldp x12, x13, [x29, -104] - mov sp, x29 -@@ -3551,17 +3551,17 @@ 300: - .unreq UX - .unreq WIDTH - .unreq TMP1 - .unreq TMP2 - .unreq PF_OFFS - .unreq TMP3 - .unreq TMP4 - .unreq STRIDE --.endfunc -+pixman_end_asm_function - - .endm - - /*****************************************************************************/ - - .set have_bilinear_interpolate_four_pixels_8888_8888, 1 - - .macro bilinear_interpolate_four_pixels_8888_8888_head -diff --git a/gfx/cairo/libpixman/src/pixman-arma64-neon-asm.h b/gfx/cairo/libpixman/src/pixman-arma64-neon-asm.h ---- a/gfx/cairo/libpixman/src/pixman-arma64-neon-asm.h -+++ b/gfx/cairo/libpixman/src/pixman-arma64-neon-asm.h -@@ -75,340 +75,340 @@ - #define PREFETCH_MODE pldl1keep - - /* - * Definitions of supplementary pixld/pixst macros (for partial load/store of - * pixel data). - */ - - .macro pixldst1 op, elem_size, reg1, mem_operand, abits -- op {v®1&.&elem_size}, [&mem_operand&], #8 -+ \op {v\()\reg1\().\()\elem_size}, [\()\mem_operand\()], #8 - .endm - - .macro pixldst2 op, elem_size, reg1, reg2, mem_operand, abits -- op {v®1&.&elem_size, v®2&.&elem_size}, [&mem_operand&], #16 -+ \op {v\()\reg1\().\()\elem_size, v\()\reg2\().\()\elem_size}, [\()\mem_operand\()], #16 - .endm - - .macro pixldst4 op, elem_size, reg1, reg2, reg3, reg4, mem_operand, abits -- op {v®1&.&elem_size, v®2&.&elem_size, v®3&.&elem_size, v®4&.&elem_size}, [&mem_operand&], #32 -+ \op {v\()\reg1\().\()\elem_size, v\()\reg2\().\()\elem_size, v\()\reg3\().\()\elem_size, v\()\reg4\().\()\elem_size}, [\()\mem_operand\()], #32 - .endm - - .macro pixldst0 op, elem_size, reg1, idx, mem_operand, abits, bytes -- op {v®1&.&elem_size}[idx], [&mem_operand&], #&bytes& -+ \op {v\()\reg1\().\()\elem_size}[\idx], [\()\mem_operand\()], #\()\bytes\() - .endm - - .macro pixldst3 op, elem_size, reg1, reg2, reg3, mem_operand -- op {v®1&.&elem_size, v®2&.&elem_size, v®3&.&elem_size}, [&mem_operand&], #24 -+ \op {v\()\reg1\().\()\elem_size, v\()\reg2\().\()\elem_size, v\()\reg3\().\()\elem_size}, [\()\mem_operand\()], #24 - .endm - - .macro pixldst30 op, elem_size, reg1, reg2, reg3, idx, mem_operand -- op {v®1&.&elem_size, v®2&.&elem_size, v®3&.&elem_size}[idx], [&mem_operand&], #3 -+ \op {v\()\reg1\().\()\elem_size, v\()\reg2\().\()\elem_size, v\()\reg3\().\()\elem_size}[\idx], [\()\mem_operand\()], #3 - .endm - - .macro pixldst numbytes, op, elem_size, basereg, mem_operand, abits --.if numbytes == 32 -- .if elem_size==32 -- pixldst4 op, 2s, %(basereg+4), %(basereg+5), \ -- %(basereg+6), %(basereg+7), mem_operand, abits -- .elseif elem_size==16 -- pixldst4 op, 4h, %(basereg+4), %(basereg+5), \ -- %(basereg+6), %(basereg+7), mem_operand, abits -+.if \numbytes == 32 -+ .if \elem_size==32 -+ pixldst4 \op, 2s, %(\basereg+4), %(\basereg+5), \ -+ %(\basereg+6), %(\basereg+7), \mem_operand, \abits -+ .elseif \elem_size==16 -+ pixldst4 \op, 4h, %(\basereg+4), %(\basereg+5), \ -+ %(\basereg+6), %(\basereg+7), \mem_operand, \abits - .else -- pixldst4 op, 8b, %(basereg+4), %(basereg+5), \ -- %(basereg+6), %(basereg+7), mem_operand, abits -+ pixldst4 \op, 8b, %(\basereg+4), %(\basereg+5), \ -+ %(\basereg+6), %(\basereg+7), \mem_operand, \abits - .endif --.elseif numbytes == 16 -- .if elem_size==32 -- pixldst2 op, 2s, %(basereg+2), %(basereg+3), mem_operand, abits -- .elseif elem_size==16 -- pixldst2 op, 4h, %(basereg+2), %(basereg+3), mem_operand, abits -+.elseif \numbytes == 16 -+ .if \elem_size==32 -+ pixldst2 \op, 2s, %(\basereg+2), %(\basereg+3), \mem_operand, \abits -+ .elseif \elem_size==16 -+ pixldst2 \op, 4h, %(\basereg+2), %(\basereg+3), \mem_operand, \abits - .else -- pixldst2 op, 8b, %(basereg+2), %(basereg+3), mem_operand, abits -+ pixldst2 \op, 8b, %(\basereg+2), %(\basereg+3), \mem_operand, \abits - .endif --.elseif numbytes == 8 -- .if elem_size==32 -- pixldst1 op, 2s, %(basereg+1), mem_operand, abits -- .elseif elem_size==16 -- pixldst1 op, 4h, %(basereg+1), mem_operand, abits -+.elseif \numbytes == 8 -+ .if \elem_size==32 -+ pixldst1 \op, 2s, %(\basereg+1), \mem_operand, \abits -+ .elseif \elem_size==16 -+ pixldst1 \op, 4h, %(\basereg+1), \mem_operand, \abits - .else -- pixldst1 op, 8b, %(basereg+1), mem_operand, abits -+ pixldst1 \op, 8b, %(\basereg+1), \mem_operand, \abits - .endif --.elseif numbytes == 4 -- .if !RESPECT_STRICT_ALIGNMENT || (elem_size == 32) -- pixldst0 op, s, %(basereg+0), 1, mem_operand, abits, 4 -- .elseif elem_size == 16 -- pixldst0 op, h, %(basereg+0), 2, mem_operand, abits, 2 -- pixldst0 op, h, %(basereg+0), 3, mem_operand, abits, 2 -+.elseif \numbytes == 4 -+ .if !RESPECT_STRICT_ALIGNMENT || (\elem_size == 32) -+ pixldst0 \op, s, %(\basereg+0), 1, \mem_operand, \abits, 4 -+ .elseif \elem_size == 16 -+ pixldst0 \op, h, %(\basereg+0), 2, \mem_operand, \abits, 2 -+ pixldst0 \op, h, %(\basereg+0), 3, \mem_operand, \abits, 2 - .else -- pixldst0 op, b, %(basereg+0), 4, mem_operand, abits, 1 -- pixldst0 op, b, %(basereg+0), 5, mem_operand, abits, 1 -- pixldst0 op, b, %(basereg+0), 6, mem_operand, abits, 1 -- pixldst0 op, b, %(basereg+0), 7, mem_operand, abits, 1 -+ pixldst0 \op, b, %(\basereg+0), 4, \mem_operand, \abits, 1 -+ pixldst0 \op, b, %(\basereg+0), 5, \mem_operand, \abits, 1 -+ pixldst0 \op, b, %(\basereg+0), 6, \mem_operand, \abits, 1 -+ pixldst0 \op, b, %(\basereg+0), 7, \mem_operand, \abits, 1 - .endif --.elseif numbytes == 2 -- .if !RESPECT_STRICT_ALIGNMENT || (elem_size == 16) -- pixldst0 op, h, %(basereg+0), 1, mem_operand, abits, 2 -+.elseif \numbytes == 2 -+ .if !RESPECT_STRICT_ALIGNMENT || (\elem_size == 16) -+ pixldst0 \op, h, %(\basereg+0), 1, \mem_operand, \abits, 2 - .else -- pixldst0 op, b, %(basereg+0), 2, mem_operand, abits, 1 -- pixldst0 op, b, %(basereg+0), 3, mem_operand, abits, 1 -+ pixldst0 \op, b, %(\basereg+0), 2, \mem_operand, \abits, 1 -+ pixldst0 \op, b, %(\basereg+0), 3, \mem_operand, \abits, 1 - .endif --.elseif numbytes == 1 -- pixldst0 op, b, %(basereg+0), 1, mem_operand, abits, 1 -+.elseif \numbytes == 1 -+ pixldst0 \op, b, %(\basereg+0), 1, \mem_operand, \abits, 1 - .else -- .error "unsupported size: numbytes" -+ .error "unsupported size: \numbytes" - .endif - .endm - - .macro pixld numpix, bpp, basereg, mem_operand, abits=0 --.if bpp > 0 --.if (bpp == 32) && (numpix == 8) && (DEINTERLEAVE_32BPP_ENABLED != 0) -- pixldst4 ld4, 8b, %(basereg+4), %(basereg+5), \ -- %(basereg+6), %(basereg+7), mem_operand, abits --.elseif (bpp == 24) && (numpix == 8) -- pixldst3 ld3, 8b, %(basereg+3), %(basereg+4), %(basereg+5), mem_operand --.elseif (bpp == 24) && (numpix == 4) -- pixldst30 ld3, b, %(basereg+0), %(basereg+1), %(basereg+2), 4, mem_operand -- pixldst30 ld3, b, %(basereg+0), %(basereg+1), %(basereg+2), 5, mem_operand -- pixldst30 ld3, b, %(basereg+0), %(basereg+1), %(basereg+2), 6, mem_operand -- pixldst30 ld3, b, %(basereg+0), %(basereg+1), %(basereg+2), 7, mem_operand --.elseif (bpp == 24) && (numpix == 2) -- pixldst30 ld3, b, %(basereg+0), %(basereg+1), %(basereg+2), 2, mem_operand -- pixldst30 ld3, b, %(basereg+0), %(basereg+1), %(basereg+2), 3, mem_operand --.elseif (bpp == 24) && (numpix == 1) -- pixldst30 ld3, b, %(basereg+0), %(basereg+1), %(basereg+2), 1, mem_operand -+.if \bpp > 0 -+.if (\bpp == 32) && (\numpix == 8) && (DEINTERLEAVE_32BPP_ENABLED != 0) -+ pixldst4 ld4, 8b, %(\basereg+4), %(\basereg+5), \ -+ %(\basereg+6), %(\basereg+7), \mem_operand, \abits -+.elseif (\bpp == 24) && (\numpix == 8) -+ pixldst3 ld3, 8b, %(\basereg+3), %(\basereg+4), %(\basereg+5), \mem_operand -+.elseif (\bpp == 24) && (\numpix == 4) -+ pixldst30 ld3, b, %(\basereg+0), %(\basereg+1), %(\basereg+2), 4, \mem_operand -+ pixldst30 ld3, b, %(\basereg+0), %(\basereg+1), %(\basereg+2), 5, \mem_operand -+ pixldst30 ld3, b, %(\basereg+0), %(\basereg+1), %(\basereg+2), 6, \mem_operand -+ pixldst30 ld3, b, %(\basereg+0), %(\basereg+1), %(\basereg+2), 7, \mem_operand -+.elseif (\bpp == 24) && (\numpix == 2) -+ pixldst30 ld3, b, %(\basereg+0), %(\basereg+1), %(\basereg+2), 2, \mem_operand -+ pixldst30 ld3, b, %(\basereg+0), %(\basereg+1), %(\basereg+2), 3, \mem_operand -+.elseif (\bpp == 24) && (\numpix == 1) -+ pixldst30 ld3, b, %(\basereg+0), %(\basereg+1), %(\basereg+2), 1, \mem_operand - .else -- pixldst %(numpix * bpp / 8), ld1, %(bpp), basereg, mem_operand, abits -+ pixldst %(\numpix * \bpp / 8), ld1, %(\bpp), \basereg, \mem_operand, \abits - .endif - .endif - .endm - - .macro pixst numpix, bpp, basereg, mem_operand, abits=0 --.if bpp > 0 --.if (bpp == 32) && (numpix == 8) && (DEINTERLEAVE_32BPP_ENABLED != 0) -- pixldst4 st4, 8b, %(basereg+4), %(basereg+5), \ -- %(basereg+6), %(basereg+7), mem_operand, abits --.elseif (bpp == 24) && (numpix == 8) -- pixldst3 st3, 8b, %(basereg+3), %(basereg+4), %(basereg+5), mem_operand --.elseif (bpp == 24) && (numpix == 4) -- pixldst30 st3, b, %(basereg+0), %(basereg+1), %(basereg+2), 4, mem_operand -- pixldst30 st3, b, %(basereg+0), %(basereg+1), %(basereg+2), 5, mem_operand -- pixldst30 st3, b, %(basereg+0), %(basereg+1), %(basereg+2), 6, mem_operand -- pixldst30 st3, b, %(basereg+0), %(basereg+1), %(basereg+2), 7, mem_operand --.elseif (bpp == 24) && (numpix == 2) -- pixldst30 st3, b, %(basereg+0), %(basereg+1), %(basereg+2), 2, mem_operand -- pixldst30 st3, b, %(basereg+0), %(basereg+1), %(basereg+2), 3, mem_operand --.elseif (bpp == 24) && (numpix == 1) -- pixldst30 st3, b, %(basereg+0), %(basereg+1), %(basereg+2), 1, mem_operand --.elseif numpix * bpp == 32 && abits == 32 -- pixldst 4, st1, 32, basereg, mem_operand, abits --.elseif numpix * bpp == 16 && abits == 16 -- pixldst 2, st1, 16, basereg, mem_operand, abits -+.if \bpp > 0 -+.if (\bpp == 32) && (\numpix == 8) && (DEINTERLEAVE_32BPP_ENABLED != 0) -+ pixldst4 st4, 8b, %(\basereg+4), %(\basereg+5), \ -+ %(\basereg+6), %(\basereg+7), \mem_operand, \abits -+.elseif (\bpp == 24) && (\numpix == 8) -+ pixldst3 st3, 8b, %(\basereg+3), %(\basereg+4), %(\basereg+5), \mem_operand -+.elseif (\bpp == 24) && (\numpix == 4) -+ pixldst30 st3, b, %(\basereg+0), %(\basereg+1), %(\basereg+2), 4, \mem_operand -+ pixldst30 st3, b, %(\basereg+0), %(\basereg+1), %(\basereg+2), 5, \mem_operand -+ pixldst30 st3, b, %(\basereg+0), %(\basereg+1), %(\basereg+2), 6, \mem_operand -+ pixldst30 st3, b, %(\basereg+0), %(\basereg+1), %(\basereg+2), 7, \mem_operand -+.elseif (\bpp == 24) && (\numpix == 2) -+ pixldst30 st3, b, %(\basereg+0), %(\basereg+1), %(\basereg+2), 2, \mem_operand -+ pixldst30 st3, b, %(\basereg+0), %(\basereg+1), %(\basereg+2), 3, \mem_operand -+.elseif (\bpp == 24) && (\numpix == 1) -+ pixldst30 st3, b, %(\basereg+0), %(\basereg+1), %(\basereg+2), 1, \mem_operand -+.elseif \numpix * \bpp == 32 && \abits == 32 -+ pixldst 4, st1, 32, \basereg, \mem_operand, \abits -+.elseif \numpix * \bpp == 16 && \abits == 16 -+ pixldst 2, st1, 16, \basereg, \mem_operand, \abits - .else -- pixldst %(numpix * bpp / 8), st1, %(bpp), basereg, mem_operand, abits -+ pixldst %(\numpix * \bpp / 8), st1, %(\bpp), \basereg, \mem_operand, \abits - .endif - .endif - .endm - - .macro pixld_a numpix, bpp, basereg, mem_operand --.if (bpp * numpix) <= 128 -- pixld numpix, bpp, basereg, mem_operand, %(bpp * numpix) -+.if (\bpp * \numpix) <= 128 -+ pixld \numpix, \bpp, \basereg, \mem_operand, %(\bpp * \numpix) - .else -- pixld numpix, bpp, basereg, mem_operand, 128 -+ pixld \numpix, \bpp, \basereg, \mem_operand, 128 - .endif - .endm - - .macro pixst_a numpix, bpp, basereg, mem_operand --.if (bpp * numpix) <= 128 -- pixst numpix, bpp, basereg, mem_operand, %(bpp * numpix) -+.if (\bpp * \numpix) <= 128 -+ pixst \numpix, \bpp, \basereg, \mem_operand, %(\bpp * \numpix) - .else -- pixst numpix, bpp, basereg, mem_operand, 128 -+ pixst \numpix, \bpp, \basereg, \mem_operand, 128 - .endif - .endm - - /* - * Pixel fetcher for nearest scaling (needs TMP1, TMP2, VX, UNIT_X register - * aliases to be defined) - */ - .macro pixld1_s elem_size, reg1, mem_operand --.if elem_size == 16 -+.if \elem_size == 16 - asr TMP1, VX, #16 - adds VX, VX, UNIT_X - bmi 55f - 5: subs VX, VX, SRC_WIDTH_FIXED - bpl 5b - 55: -- add TMP1, mem_operand, TMP1, lsl #1 -+ add TMP1, \mem_operand, TMP1, lsl #1 - asr TMP2, VX, #16 - adds VX, VX, UNIT_X - bmi 55f - 5: subs VX, VX, SRC_WIDTH_FIXED - bpl 5b - 55: -- add TMP2, mem_operand, TMP2, lsl #1 -- ld1 {v®1&.h}[0], [TMP1] -+ add TMP2, \mem_operand, TMP2, lsl #1 -+ ld1 {v\()\reg1\().h}[0], [TMP1] - asr TMP1, VX, #16 - adds VX, VX, UNIT_X - bmi 55f - 5: subs VX, VX, SRC_WIDTH_FIXED - bpl 5b - 55: -- add TMP1, mem_operand, TMP1, lsl #1 -- ld1 {v®1&.h}[1], [TMP2] -+ add TMP1, \mem_operand, TMP1, lsl #1 -+ ld1 {v\()\reg1\().h}[1], [TMP2] - asr TMP2, VX, #16 - adds VX, VX, UNIT_X - bmi 55f - 5: subs VX, VX, SRC_WIDTH_FIXED - bpl 5b - 55: -- add TMP2, mem_operand, TMP2, lsl #1 -- ld1 {v®1&.h}[2], [TMP1] -- ld1 {v®1&.h}[3], [TMP2] --.elseif elem_size == 32 -+ add TMP2, \mem_operand, TMP2, lsl #1 -+ ld1 {v\()\reg1\().h}[2], [TMP1] -+ ld1 {v\()\reg1\().h}[3], [TMP2] -+.elseif \elem_size == 32 - asr TMP1, VX, #16 - adds VX, VX, UNIT_X - bmi 55f - 5: subs VX, VX, SRC_WIDTH_FIXED - bpl 5b - 55: -- add TMP1, mem_operand, TMP1, lsl #2 -+ add TMP1, \mem_operand, TMP1, lsl #2 - asr TMP2, VX, #16 - adds VX, VX, UNIT_X - bmi 55f - 5: subs VX, VX, SRC_WIDTH_FIXED - bpl 5b - 55: -- add TMP2, mem_operand, TMP2, lsl #2 -- ld1 {v®1&.s}[0], [TMP1] -- ld1 {v®1&.s}[1], [TMP2] -+ add TMP2, \mem_operand, TMP2, lsl #2 -+ ld1 {v\()\reg1\().s}[0], [TMP1] -+ ld1 {v\()\reg1\().s}[1], [TMP2] - .else - .error "unsupported" - .endif - .endm - - .macro pixld2_s elem_size, reg1, reg2, mem_operand --.if 0 /* elem_size == 32 */ -+.if 0 /* \elem_size == 32 */ - mov TMP1, VX, asr #16 - add VX, VX, UNIT_X, asl #1 -- add TMP1, mem_operand, TMP1, asl #2 -+ add TMP1, \mem_operand, TMP1, asl #2 - mov TMP2, VX, asr #16 - sub VX, VX, UNIT_X -- add TMP2, mem_operand, TMP2, asl #2 -- ld1 {v®1&.s}[0], [TMP1] -+ add TMP2, \mem_operand, TMP2, asl #2 -+ ld1 {v\()\reg1\().s}[0], [TMP1] - mov TMP1, VX, asr #16 - add VX, VX, UNIT_X, asl #1 -- add TMP1, mem_operand, TMP1, asl #2 -- ld1 {v®2&.s}[0], [TMP2, :32] -+ add TMP1, \mem_operand, TMP1, asl #2 -+ ld1 {v\()\reg2\().s}[0], [TMP2, :32] - mov TMP2, VX, asr #16 - add VX, VX, UNIT_X -- add TMP2, mem_operand, TMP2, asl #2 -- ld1 {v®1&.s}[1], [TMP1] -- ld1 {v®2&.s}[1], [TMP2] -+ add TMP2, \mem_operand, TMP2, asl #2 -+ ld1 {v\()\reg1\().s}[1], [TMP1] -+ ld1 {v\()\reg2\().s}[1], [TMP2] - .else -- pixld1_s elem_size, reg1, mem_operand -- pixld1_s elem_size, reg2, mem_operand -+ pixld1_s \elem_size, \reg1, \mem_operand -+ pixld1_s \elem_size, \reg2, \mem_operand - .endif - .endm - - .macro pixld0_s elem_size, reg1, idx, mem_operand --.if elem_size == 16 -+.if \elem_size == 16 - asr TMP1, VX, #16 - adds VX, VX, UNIT_X - bmi 55f - 5: subs VX, VX, SRC_WIDTH_FIXED - bpl 5b - 55: -- add TMP1, mem_operand, TMP1, lsl #1 -- ld1 {v®1&.h}[idx], [TMP1] --.elseif elem_size == 32 -+ add TMP1, \mem_operand, TMP1, lsl #1 -+ ld1 {v\()\reg1\().h}[\idx], [TMP1] -+.elseif \elem_size == 32 - asr DUMMY, VX, #16 - mov TMP1, DUMMY - adds VX, VX, UNIT_X - bmi 55f - 5: subs VX, VX, SRC_WIDTH_FIXED - bpl 5b - 55: -- add TMP1, mem_operand, TMP1, lsl #2 -- ld1 {v®1&.s}[idx], [TMP1] -+ add TMP1, \mem_operand, TMP1, lsl #2 -+ ld1 {v\()\reg1\().s}[\idx], [TMP1] - .endif - .endm - - .macro pixld_s_internal numbytes, elem_size, basereg, mem_operand --.if numbytes == 32 -- pixld2_s elem_size, %(basereg+4), %(basereg+5), mem_operand -- pixld2_s elem_size, %(basereg+6), %(basereg+7), mem_operand -- pixdeinterleave elem_size, %(basereg+4) --.elseif numbytes == 16 -- pixld2_s elem_size, %(basereg+2), %(basereg+3), mem_operand --.elseif numbytes == 8 -- pixld1_s elem_size, %(basereg+1), mem_operand --.elseif numbytes == 4 -- .if elem_size == 32 -- pixld0_s elem_size, %(basereg+0), 1, mem_operand -- .elseif elem_size == 16 -- pixld0_s elem_size, %(basereg+0), 2, mem_operand -- pixld0_s elem_size, %(basereg+0), 3, mem_operand -+.if \numbytes == 32 -+ pixld2_s \elem_size, %(\basereg+4), %(\basereg+5), \mem_operand -+ pixld2_s \elem_size, %(\basereg+6), %(\basereg+7), \mem_operand -+ pixdeinterleave \elem_size, %(\basereg+4) -+.elseif \numbytes == 16 -+ pixld2_s \elem_size, %(\basereg+2), %(\basereg+3), \mem_operand -+.elseif \numbytes == 8 -+ pixld1_s \elem_size, %(\basereg+1), \mem_operand -+.elseif \numbytes == 4 -+ .if \elem_size == 32 -+ pixld0_s \elem_size, %(\basereg+0), 1, \mem_operand -+ .elseif \elem_size == 16 -+ pixld0_s \elem_size, %(\basereg+0), 2, \mem_operand -+ pixld0_s \elem_size, %(\basereg+0), 3, \mem_operand - .else -- pixld0_s elem_size, %(basereg+0), 4, mem_operand -- pixld0_s elem_size, %(basereg+0), 5, mem_operand -- pixld0_s elem_size, %(basereg+0), 6, mem_operand -- pixld0_s elem_size, %(basereg+0), 7, mem_operand -+ pixld0_s \elem_size, %(\basereg+0), 4, \mem_operand -+ pixld0_s \elem_size, %(\basereg+0), 5, \mem_operand -+ pixld0_s \elem_size, %(\basereg+0), 6, \mem_operand -+ pixld0_s \elem_size, %(\basereg+0), 7, \mem_operand - .endif --.elseif numbytes == 2 -- .if elem_size == 16 -- pixld0_s elem_size, %(basereg+0), 1, mem_operand -+.elseif \numbytes == 2 -+ .if \elem_size == 16 -+ pixld0_s \elem_size, %(\basereg+0), 1, \mem_operand - .else -- pixld0_s elem_size, %(basereg+0), 2, mem_operand -- pixld0_s elem_size, %(basereg+0), 3, mem_operand -+ pixld0_s \elem_size, %(\basereg+0), 2, \mem_operand -+ pixld0_s \elem_size, %(\basereg+0), 3, \mem_operand - .endif --.elseif numbytes == 1 -- pixld0_s elem_size, %(basereg+0), 1, mem_operand -+.elseif \numbytes == 1 -+ pixld0_s \elem_size, %(\basereg+0), 1, \mem_operand - .else -- .error "unsupported size: numbytes" -+ .error "unsupported size: \numbytes" - .endif - .endm - - .macro pixld_s numpix, bpp, basereg, mem_operand --.if bpp > 0 -- pixld_s_internal %(numpix * bpp / 8), %(bpp), basereg, mem_operand -+.if \bpp > 0 -+ pixld_s_internal %(\numpix * \bpp / 8), %(\bpp), \basereg, \mem_operand - .endif - .endm - - .macro vuzp8 reg1, reg2 - umov DUMMY, v16.d[0] -- uzp1 v16.8b, v®1&.8b, v®2&.8b -- uzp2 v®2&.8b, v®1&.8b, v®2&.8b -- mov v®1&.8b, v16.8b -+ uzp1 v16.8b, v\()\reg1\().8b, v\()\reg2\().8b -+ uzp2 v\()\reg2\().8b, v\()\reg1\().8b, v\()\reg2\().8b -+ mov v\()\reg1\().8b, v16.8b - mov v16.d[0], DUMMY - .endm - - .macro vzip8 reg1, reg2 - umov DUMMY, v16.d[0] -- zip1 v16.8b, v®1&.8b, v®2&.8b -- zip2 v®2&.8b, v®1&.8b, v®2&.8b -- mov v®1&.8b, v16.8b -+ zip1 v16.8b, v\()\reg1\().8b, v\()\reg2\().8b -+ zip2 v\()\reg2\().8b, v\()\reg1\().8b, v\()\reg2\().8b -+ mov v\()\reg1\().8b, v16.8b - mov v16.d[0], DUMMY - .endm - - /* deinterleave B, G, R, A channels for eight 32bpp pixels in 4 registers */ - .macro pixdeinterleave bpp, basereg --.if (bpp == 32) && (DEINTERLEAVE_32BPP_ENABLED != 0) -- vuzp8 %(basereg+0), %(basereg+1) -- vuzp8 %(basereg+2), %(basereg+3) -- vuzp8 %(basereg+1), %(basereg+3) -- vuzp8 %(basereg+0), %(basereg+2) -+.if (\bpp == 32) && (DEINTERLEAVE_32BPP_ENABLED != 0) -+ vuzp8 %(\basereg+0), %(\basereg+1) -+ vuzp8 %(\basereg+2), %(\basereg+3) -+ vuzp8 %(\basereg+1), %(\basereg+3) -+ vuzp8 %(\basereg+0), %(\basereg+2) - .endif - .endm - - /* interleave B, G, R, A channels for eight 32bpp pixels in 4 registers */ - .macro pixinterleave bpp, basereg --.if (bpp == 32) && (DEINTERLEAVE_32BPP_ENABLED != 0) -- vzip8 %(basereg+0), %(basereg+2) -- vzip8 %(basereg+1), %(basereg+3) -- vzip8 %(basereg+2), %(basereg+3) -- vzip8 %(basereg+0), %(basereg+1) -+.if (\bpp == 32) && (DEINTERLEAVE_32BPP_ENABLED != 0) -+ vzip8 %(\basereg+0), %(\basereg+2) -+ vzip8 %(\basereg+1), %(\basereg+3) -+ vzip8 %(\basereg+2), %(\basereg+3) -+ vzip8 %(\basereg+0), %(\basereg+1) - .endif - .endm - - /* - * This is a macro for implementing cache preload. The main idea is that - * cache preload logic is mostly independent from the rest of pixels - * processing code. It starts at the top left pixel and moves forward - * across pixels and can jump across scanlines. Prefetch distance is -@@ -432,62 +432,62 @@ 55: - * for almost zero cost! - * - * (*) The overhead of the prefetcher is visible when running some trivial - * pixels processing like simple copy. Anyway, having prefetch is a must - * when working with the graphics data. - */ - .macro PF a, x:vararg - .if (PREFETCH_TYPE_CURRENT == PREFETCH_TYPE_ADVANCED) -- a x -+ \a \x - .endif - .endm - - .macro cache_preload std_increment, boost_increment - .if (src_bpp_shift >= 0) || (dst_r_bpp != 0) || (mask_bpp_shift >= 0) --.if std_increment != 0 -- PF add PF_X, PF_X, #std_increment -+.if \std_increment != 0 -+ PF add, PF_X, PF_X, #\std_increment - .endif -- PF tst PF_CTL, #0xF -- PF beq 71f -- PF add PF_X, PF_X, #boost_increment -- PF sub PF_CTL, PF_CTL, #1 -+ PF tst, PF_CTL, #0xF -+ PF beq, 71f -+ PF add, PF_X, PF_X, #\boost_increment -+ PF sub, PF_CTL, PF_CTL, #1 - 71: -- PF cmp PF_X, ORIG_W -+ PF cmp, PF_X, ORIG_W - .if src_bpp_shift >= 0 -- PF lsl DUMMY, PF_X, #src_bpp_shift -- PF prfm PREFETCH_MODE, [PF_SRC, DUMMY] -+ PF lsl, DUMMY, PF_X, #src_bpp_shift -+ PF prfm, PREFETCH_MODE, [PF_SRC, DUMMY] - .endif - .if dst_r_bpp != 0 -- PF lsl DUMMY, PF_X, #dst_bpp_shift -- PF prfm PREFETCH_MODE, [PF_DST, DUMMY] -+ PF lsl, DUMMY, PF_X, #dst_bpp_shift -+ PF prfm, PREFETCH_MODE, [PF_DST, DUMMY] - .endif - .if mask_bpp_shift >= 0 -- PF lsl DUMMY, PF_X, #mask_bpp_shift -- PF prfm PREFETCH_MODE, [PF_MASK, DUMMY] -+ PF lsl, DUMMY, PF_X, #mask_bpp_shift -+ PF prfm, PREFETCH_MODE, [PF_MASK, DUMMY] - .endif -- PF ble 71f -- PF sub PF_X, PF_X, ORIG_W -- PF subs PF_CTL, PF_CTL, #0x10 -+ PF ble, 71f -+ PF sub, PF_X, PF_X, ORIG_W -+ PF subs, PF_CTL, PF_CTL, #0x10 - 71: -- PF ble 72f -+ PF ble, 72f - .if src_bpp_shift >= 0 -- PF lsl DUMMY, SRC_STRIDE, #src_bpp_shift -- PF ldrsb DUMMY, [PF_SRC, DUMMY] -- PF add PF_SRC, PF_SRC, #1 -+ PF lsl, DUMMY, SRC_STRIDE, #src_bpp_shift -+ PF ldrsb, DUMMY, [PF_SRC, DUMMY] -+ PF add, PF_SRC, PF_SRC, #1 - .endif - .if dst_r_bpp != 0 -- PF lsl DUMMY, DST_STRIDE, #dst_bpp_shift -- PF ldrsb DUMMY, [PF_DST, DUMMY] -- PF add PF_DST, PF_DST, #1 -+ PF lsl, DUMMY, DST_STRIDE, #dst_bpp_shift -+ PF ldrsb, DUMMY, [PF_DST, DUMMY] -+ PF add, PF_DST, PF_DST, #1 - .endif - .if mask_bpp_shift >= 0 -- PF lsl DUMMY, MASK_STRIDE, #mask_bpp_shift -- PF ldrsb DUMMY, [PF_MASK, DUMMY] -- PF add PF_MASK, PF_MASK, #1 -+ PF lsl, DUMMY, MASK_STRIDE, #mask_bpp_shift -+ PF ldrsb, DUMMY, [PF_MASK, DUMMY] -+ PF add, PF_MASK, PF_MASK, #1 - .endif - 72: - .endif - .endm - - .macro cache_preload_simple - .if (PREFETCH_TYPE_CURRENT == PREFETCH_TYPE_SIMPLE) - .if src_bpp > 0 -@@ -516,56 +516,56 @@ 72: - process_pixblock_tail, \ - process_pixblock_tail_head - .if dst_w_bpp != 24 - tst DST_R, #0xF - beq 52f - - .if src_bpp > 0 || mask_bpp > 0 || dst_r_bpp > 0 - .irp lowbit, 1, 2, 4, 8, 16 --local skip1 --.if (dst_w_bpp <= (lowbit * 8)) && ((lowbit * 8) < (pixblock_size * dst_w_bpp)) --.if lowbit < 16 /* we don't need more than 16-byte alignment */ -- tst DST_R, #lowbit -+ -+.if (dst_w_bpp <= (\lowbit * 8)) && ((\lowbit * 8) < (pixblock_size * dst_w_bpp)) -+.if \lowbit < 16 /* we don't need more than 16-byte alignment */ -+ tst DST_R, #\lowbit - beq 51f - .endif -- pixld_src (lowbit * 8 / dst_w_bpp), src_bpp, src_basereg, SRC -- pixld (lowbit * 8 / dst_w_bpp), mask_bpp, mask_basereg, MASK -+ pixld_src (\lowbit * 8 / dst_w_bpp), src_bpp, src_basereg, SRC -+ pixld (\lowbit * 8 / dst_w_bpp), mask_bpp, mask_basereg, MASK - .if dst_r_bpp > 0 -- pixld_a (lowbit * 8 / dst_r_bpp), dst_r_bpp, dst_r_basereg, DST_R -+ pixld_a (\lowbit * 8 / dst_r_bpp), dst_r_bpp, dst_r_basereg, DST_R - .else -- add DST_R, DST_R, #lowbit -+ add DST_R, DST_R, #\lowbit - .endif -- PF add PF_X, PF_X, #(lowbit * 8 / dst_w_bpp) -- sub W, W, #(lowbit * 8 / dst_w_bpp) -+ PF add, PF_X, PF_X, #(\lowbit * 8 / dst_w_bpp) -+ sub W, W, #(\lowbit * 8 / dst_w_bpp) - 51: - .endif - .endr - .endif - pixdeinterleave src_bpp, src_basereg - pixdeinterleave mask_bpp, mask_basereg - pixdeinterleave dst_r_bpp, dst_r_basereg - -- process_pixblock_head -+ \process_pixblock_head - cache_preload 0, pixblock_size - cache_preload_simple -- process_pixblock_tail -+ \process_pixblock_tail - - pixinterleave dst_w_bpp, dst_w_basereg - - .irp lowbit, 1, 2, 4, 8, 16 --.if (dst_w_bpp <= (lowbit * 8)) && ((lowbit * 8) < (pixblock_size * dst_w_bpp)) --.if lowbit < 16 /* we don't need more than 16-byte alignment */ -- tst DST_W, #lowbit -+.if (dst_w_bpp <= (\lowbit * 8)) && ((\lowbit * 8) < (pixblock_size * dst_w_bpp)) -+.if \lowbit < 16 /* we don't need more than 16-byte alignment */ -+ tst DST_W, #\lowbit - beq 51f - .endif - .if src_bpp == 0 && mask_bpp == 0 && dst_r_bpp == 0 -- sub W, W, #(lowbit * 8 / dst_w_bpp) -+ sub W, W, #(\lowbit * 8 / dst_w_bpp) - .endif -- pixst_a (lowbit * 8 / dst_w_bpp), dst_w_bpp, dst_w_basereg, DST_W -+ pixst_a (\lowbit * 8 / dst_w_bpp), dst_w_bpp, dst_w_basereg, DST_W - 51: - .endif - .endr - .endif - 52: - .endm - - /* -@@ -587,52 +587,52 @@ 52: - dst_aligned_flag, \ - process_pixblock_head, \ - process_pixblock_tail, \ - process_pixblock_tail_head - tst W, #(pixblock_size - 1) - beq 52f - .if src_bpp > 0 || mask_bpp > 0 || dst_r_bpp > 0 - .irp chunk_size, 16, 8, 4, 2, 1 --.if pixblock_size > chunk_size -- tst W, #chunk_size -+.if pixblock_size > \chunk_size -+ tst W, #\chunk_size - beq 51f -- pixld_src chunk_size, src_bpp, src_basereg, SRC -- pixld chunk_size, mask_bpp, mask_basereg, MASK --.if dst_aligned_flag != 0 -- pixld_a chunk_size, dst_r_bpp, dst_r_basereg, DST_R -+ pixld_src \chunk_size, src_bpp, src_basereg, SRC -+ pixld \chunk_size, mask_bpp, mask_basereg, MASK -+.if \dst_aligned_flag != 0 -+ pixld_a \chunk_size, dst_r_bpp, dst_r_basereg, DST_R - .else -- pixld chunk_size, dst_r_bpp, dst_r_basereg, DST_R -+ pixld \chunk_size, dst_r_bpp, dst_r_basereg, DST_R - .endif --.if cache_preload_flag != 0 -- PF add PF_X, PF_X, #chunk_size -+.if \cache_preload_flag != 0 -+ PF add, PF_X, PF_X, #\chunk_size - .endif - 51: - .endif - .endr - .endif - pixdeinterleave src_bpp, src_basereg - pixdeinterleave mask_bpp, mask_basereg - pixdeinterleave dst_r_bpp, dst_r_basereg - -- process_pixblock_head --.if cache_preload_flag != 0 -+ \process_pixblock_head -+.if \cache_preload_flag != 0 - cache_preload 0, pixblock_size - cache_preload_simple - .endif -- process_pixblock_tail -+ \process_pixblock_tail - pixinterleave dst_w_bpp, dst_w_basereg - .irp chunk_size, 16, 8, 4, 2, 1 --.if pixblock_size > chunk_size -- tst W, #chunk_size -+.if pixblock_size > \chunk_size -+ tst W, #\chunk_size - beq 51f --.if dst_aligned_flag != 0 -- pixst_a chunk_size, dst_w_bpp, dst_w_basereg, DST_W -+.if \dst_aligned_flag != 0 -+ pixst_a \chunk_size, dst_w_bpp, dst_w_basereg, DST_W - .else -- pixst chunk_size, dst_w_bpp, dst_w_basereg, DST_W -+ pixst \chunk_size, dst_w_bpp, dst_w_basereg, DST_W - .endif - 51: - .endif - .endr - 52: - .endm - - /* -@@ -655,17 +655,17 @@ 52: - .if (src_bpp != 24) && (src_bpp != 0) - sub SRC, SRC, W, lsl #src_bpp_shift - .endif - .if (mask_bpp != 24) && (mask_bpp != 0) - sub MASK, MASK, W, lsl #mask_bpp_shift - .endif - subs H, H, #1 - mov DST_R, DST_W -- bge start_of_loop_label -+ bge \start_of_loop_label - .endm - - /* - * Registers are allocated in the following way by default: - * v0, v1, v2, v3 - reserved for loading source pixel data - * v4, v5, v6, v7 - reserved for loading destination pixel data - * v24, v25, v26, v27 - reserved for loading mask pixel data - * v28, v29, v30, v31 - final destination pixel data for writeback to memory -@@ -682,17 +682,17 @@ 52: - process_pixblock_head, \ - process_pixblock_tail, \ - process_pixblock_tail_head, \ - dst_w_basereg_ = 28, \ - dst_r_basereg_ = 4, \ - src_basereg_ = 0, \ - mask_basereg_ = 24 - -- pixman_asm_function fname -+ pixman_asm_function \fname - stp x29, x30, [sp, -16]! - mov x29, sp - sub sp, sp, 232 /* push all registers */ - sub x29, x29, 64 - st1 {v8.8b, v9.8b, v10.8b, v11.8b}, [x29], #32 - st1 {v12.8b, v13.8b, v14.8b, v15.8b}, [x29], #32 - stp x8, x9, [x29, -80] - stp x10, x11, [x29, -96] -@@ -707,38 +707,38 @@ 52: - str x28, [x29, -232] - - /* - * Select prefetch type for this function. If prefetch distance is - * set to 0 or one of the color formats is 24bpp, SIMPLE prefetch - * has to be used instead of ADVANCED. - */ - .set PREFETCH_TYPE_CURRENT, PREFETCH_TYPE_DEFAULT --.if prefetch_distance == 0 -+.if \prefetch_distance == 0 - .set PREFETCH_TYPE_CURRENT, PREFETCH_TYPE_NONE - .elseif (PREFETCH_TYPE_CURRENT > PREFETCH_TYPE_SIMPLE) && \ -- ((src_bpp_ == 24) || (mask_bpp_ == 24) || (dst_w_bpp_ == 24)) -+ ((\src_bpp_ == 24) || (\mask_bpp_ == 24) || (\dst_w_bpp_ == 24)) - .set PREFETCH_TYPE_CURRENT, PREFETCH_TYPE_SIMPLE - .endif - - /* - * Make some macro arguments globally visible and accessible - * from other macros - */ -- .set src_bpp, src_bpp_ -- .set mask_bpp, mask_bpp_ -- .set dst_w_bpp, dst_w_bpp_ -- .set pixblock_size, pixblock_size_ -- .set dst_w_basereg, dst_w_basereg_ -- .set dst_r_basereg, dst_r_basereg_ -- .set src_basereg, src_basereg_ -- .set mask_basereg, mask_basereg_ -+ .set src_bpp, \src_bpp_ -+ .set mask_bpp, \mask_bpp_ -+ .set dst_w_bpp, \dst_w_bpp_ -+ .set pixblock_size, \pixblock_size_ -+ .set dst_w_basereg, \dst_w_basereg_ -+ .set dst_r_basereg, \dst_r_basereg_ -+ .set src_basereg, \src_basereg_ -+ .set mask_basereg, \mask_basereg_ - - .macro pixld_src x:vararg -- pixld x -+ pixld \x - .endm - .macro fetch_src_pixblock - pixld_src pixblock_size, src_bpp, \ - (src_basereg - pixblock_size * src_bpp / 64), SRC - .endm - /* - * Assign symbolic names to registers - */ -@@ -805,32 +805,32 @@ 52: - .elseif dst_w_bpp == 16 - .set dst_bpp_shift, 1 - .elseif dst_w_bpp == 8 - .set dst_bpp_shift, 0 - .else - .error "requested dst bpp (dst_w_bpp) is not supported" - .endif - --.if (((flags) & FLAG_DST_READWRITE) != 0) -+.if (((\flags) & FLAG_DST_READWRITE) != 0) - .set dst_r_bpp, dst_w_bpp - .else - .set dst_r_bpp, 0 - .endif --.if (((flags) & FLAG_DEINTERLEAVE_32BPP) != 0) -+.if (((\flags) & FLAG_DEINTERLEAVE_32BPP) != 0) - .set DEINTERLEAVE_32BPP_ENABLED, 1 - .else - .set DEINTERLEAVE_32BPP_ENABLED, 0 - .endif - --.if prefetch_distance < 0 || prefetch_distance > 15 -- .error "invalid prefetch distance (prefetch_distance)" -+.if \prefetch_distance < 0 || \prefetch_distance > 15 -+ .error "invalid prefetch distance (\prefetch_distance)" - .endif - -- PF mov PF_X, #0 -+ PF mov, PF_X, #0 - mov DST_R, DST_W - - .if src_bpp == 24 - sub SRC_STRIDE, SRC_STRIDE, W - sub SRC_STRIDE, SRC_STRIDE, W, lsl #1 - .endif - .if mask_bpp == 24 - sub MASK_STRIDE, MASK_STRIDE, W -@@ -839,71 +839,71 @@ 52: - .if dst_w_bpp == 24 - sub DST_STRIDE, DST_STRIDE, W - sub DST_STRIDE, DST_STRIDE, W, lsl #1 - .endif - - /* - * Setup advanced prefetcher initial state - */ -- PF mov PF_SRC, SRC -- PF mov PF_DST, DST_R -- PF mov PF_MASK, MASK -- /* PF_CTL = prefetch_distance | ((h - 1) << 4) */ -- PF lsl DUMMY, H, #4 -- PF mov PF_CTL, DUMMY -- PF add PF_CTL, PF_CTL, #(prefetch_distance - 0x10) -+ PF mov, PF_SRC, SRC -+ PF mov, PF_DST, DST_R -+ PF mov, PF_MASK, MASK -+ /* PF_CTL = \prefetch_distance | ((h - 1) << 4) */ -+ PF lsl, DUMMY, H, #4 -+ PF mov, PF_CTL, DUMMY -+ PF add, PF_CTL, PF_CTL, #(\prefetch_distance - 0x10) - -- init -+ \init - subs H, H, #1 - mov ORIG_W, W - blt 9f - cmp W, #(pixblock_size * 2) - blt 800f - /* - * This is the start of the pipelined loop, which if optimized for - * long scanlines - */ - 0: -- ensure_destination_ptr_alignment process_pixblock_head, \ -- process_pixblock_tail, \ -- process_pixblock_tail_head -+ ensure_destination_ptr_alignment \process_pixblock_head, \ -+ \process_pixblock_tail, \ -+ \process_pixblock_tail_head - - /* Implement "head (tail_head) ... (tail_head) tail" loop pattern */ - pixld_a pixblock_size, dst_r_bpp, \ - (dst_r_basereg - pixblock_size * dst_r_bpp / 64), DST_R - fetch_src_pixblock - pixld pixblock_size, mask_bpp, \ - (mask_basereg - pixblock_size * mask_bpp / 64), MASK -- PF add PF_X, PF_X, #pixblock_size -- process_pixblock_head -+ PF add, PF_X, PF_X, #pixblock_size -+ \process_pixblock_head - cache_preload 0, pixblock_size - cache_preload_simple - subs W, W, #(pixblock_size * 2) - blt 200f - - 100: -- process_pixblock_tail_head -+ \process_pixblock_tail_head - cache_preload_simple - subs W, W, #pixblock_size - bge 100b - - 200: -- process_pixblock_tail -+ \process_pixblock_tail - pixst_a pixblock_size, dst_w_bpp, \ - (dst_w_basereg - pixblock_size * dst_w_bpp / 64), DST_W - - /* Process the remaining trailing pixels in the scanline */ - process_trailing_pixels 1, 1, \ -- process_pixblock_head, \ -- process_pixblock_tail, \ -- process_pixblock_tail_head -+ \process_pixblock_head, \ -+ \process_pixblock_tail, \ -+ \process_pixblock_tail_head - advance_to_next_scanline 0b - -- cleanup -+ \cleanup - 1000: - /* pop all registers */ - sub x29, x29, 64 - ld1 {v8.8b, v9.8b, v10.8b, v11.8b}, [x29], 32 - ld1 {v12.8b, v13.8b, v14.8b, v15.8b}, [x29], 32 - ldp x8, x9, [x29, -80] - ldp x10, x11, [x29, -96] - ldp x12, x13, [x29, -112] -@@ -920,48 +920,48 @@ 1000: - ret /* exit */ - /* - * This is the start of the loop, designed to process images with small width - * (less than pixblock_size * 2 pixels). In this case neither pipelining - * nor prefetch are used. - */ - 800: - .if src_bpp_shift >= 0 -- PF lsl DUMMY, SRC_STRIDE, #src_bpp_shift -- PF prfm PREFETCH_MODE, [SRC, DUMMY] -+ PF lsl, DUMMY, SRC_STRIDE, #src_bpp_shift -+ PF prfm, PREFETCH_MODE, [SRC, DUMMY] - .endif - .if dst_r_bpp != 0 -- PF lsl DUMMY, DST_STRIDE, #dst_bpp_shift -- PF prfm PREFETCH_MODE, [DST_R, DUMMY] -+ PF lsl, DUMMY, DST_STRIDE, #dst_bpp_shift -+ PF prfm, PREFETCH_MODE, [DST_R, DUMMY] - .endif - .if mask_bpp_shift >= 0 -- PF lsl DUMMY, MASK_STRIDE, #mask_bpp_shift -- PF prfm PREFETCH_MODE, [MASK, DUMMY] -+ PF lsl, DUMMY, MASK_STRIDE, #mask_bpp_shift -+ PF prfm, PREFETCH_MODE, [MASK, DUMMY] - .endif - /* Process exactly pixblock_size pixels if needed */ - tst W, #pixblock_size - beq 100f - pixld pixblock_size, dst_r_bpp, \ - (dst_r_basereg - pixblock_size * dst_r_bpp / 64), DST_R - fetch_src_pixblock - pixld pixblock_size, mask_bpp, \ - (mask_basereg - pixblock_size * mask_bpp / 64), MASK -- process_pixblock_head -- process_pixblock_tail -+ \process_pixblock_head -+ \process_pixblock_tail - pixst pixblock_size, dst_w_bpp, \ - (dst_w_basereg - pixblock_size * dst_w_bpp / 64), DST_W - 100: - /* Process the remaining trailing pixels in the scanline */ - process_trailing_pixels 0, 0, \ -- process_pixblock_head, \ -- process_pixblock_tail, \ -- process_pixblock_tail_head -+ \process_pixblock_head, \ -+ \process_pixblock_tail, \ -+ \process_pixblock_tail_head - advance_to_next_scanline 800b - 9: -- cleanup -+ \cleanup - /* pop all registers */ - sub x29, x29, 64 - ld1 {v8.8b, v9.8b, v10.8b, v11.8b}, [x29], 32 - ld1 {v12.8b, v13.8b, v14.8b, v15.8b}, [x29], 32 - ldp x8, x9, [x29, -80] - ldp x10, x11, [x29, -96] - ldp x12, x13, [x29, -112] - ldp x14, x15, [x29, -128] -@@ -990,17 +990,17 @@ 9: - .unreq DST_STRIDE - .unreq MASK_STRIDE - .unreq PF_CTL - .unreq PF_X - .unreq PF_SRC - .unreq PF_DST - .unreq PF_MASK - .unreq DUMMY -- .endfunc -+ pixman_end_asm_function - .endm - - /* - * A simplified variant of function generation template for a single - * scanline processing (for implementing pixman combine functions) - */ - .macro generate_composite_function_scanline use_nearest_scaling, \ - fname, \ -@@ -1014,50 +1014,50 @@ 9: - process_pixblock_head, \ - process_pixblock_tail, \ - process_pixblock_tail_head, \ - dst_w_basereg_ = 28, \ - dst_r_basereg_ = 4, \ - src_basereg_ = 0, \ - mask_basereg_ = 24 - -- pixman_asm_function fname -+ pixman_asm_function \fname - .set PREFETCH_TYPE_CURRENT, PREFETCH_TYPE_NONE - - /* - * Make some macro arguments globally visible and accessible - * from other macros - */ -- .set src_bpp, src_bpp_ -- .set mask_bpp, mask_bpp_ -- .set dst_w_bpp, dst_w_bpp_ -- .set pixblock_size, pixblock_size_ -- .set dst_w_basereg, dst_w_basereg_ -- .set dst_r_basereg, dst_r_basereg_ -- .set src_basereg, src_basereg_ -- .set mask_basereg, mask_basereg_ -+ .set src_bpp, \src_bpp_ -+ .set mask_bpp, \mask_bpp_ -+ .set dst_w_bpp, \dst_w_bpp_ -+ .set pixblock_size, \pixblock_size_ -+ .set dst_w_basereg, \dst_w_basereg_ -+ .set dst_r_basereg, \dst_r_basereg_ -+ .set src_basereg, \src_basereg_ -+ .set mask_basereg, \mask_basereg_ - --.if use_nearest_scaling != 0 -+.if \use_nearest_scaling != 0 - /* - * Assign symbolic names to registers for nearest scaling - */ - W .req x0 - DST_W .req x1 - SRC .req x2 - VX .req x3 - UNIT_X .req x4 - SRC_WIDTH_FIXED .req x5 - MASK .req x6 - TMP1 .req x8 - TMP2 .req x9 - DST_R .req x10 - DUMMY .req x30 - - .macro pixld_src x:vararg -- pixld_s x -+ pixld_s \x - .endm - - sxtw x0, w0 - sxtw x3, w3 - sxtw x4, w4 - sxtw x5, w5 - - stp x29, x30, [sp, -16]! -@@ -1075,84 +1075,84 @@ 9: - W .req x0 /* width (is updated during processing) */ - DST_W .req x1 /* destination buffer pointer for writes */ - SRC .req x2 /* source buffer pointer */ - MASK .req x3 /* mask pointer */ - DST_R .req x4 /* destination buffer pointer for reads */ - DUMMY .req x30 - - .macro pixld_src x:vararg -- pixld x -+ pixld \x - .endm - - sxtw x0, w0 - - stp x29, x30, [sp, -16]! - mov x29, sp - sub sp, sp, 64 - sub x29, x29, 64 - st1 {v8.8b, v9.8b, v10.8b, v11.8b}, [x29], 32 - st1 {v12.8b, v13.8b, v14.8b, v15.8b}, [x29], 32 - .endif - --.if (((flags) & FLAG_DST_READWRITE) != 0) -+.if (((\flags) & FLAG_DST_READWRITE) != 0) - .set dst_r_bpp, dst_w_bpp - .else - .set dst_r_bpp, 0 - .endif --.if (((flags) & FLAG_DEINTERLEAVE_32BPP) != 0) -+.if (((\flags) & FLAG_DEINTERLEAVE_32BPP) != 0) - .set DEINTERLEAVE_32BPP_ENABLED, 1 - .else - .set DEINTERLEAVE_32BPP_ENABLED, 0 - .endif - - .macro fetch_src_pixblock - pixld_src pixblock_size, src_bpp, \ - (src_basereg - pixblock_size * src_bpp / 64), SRC - .endm - -- init -+ \init - mov DST_R, DST_W - - cmp W, #pixblock_size - blt 800f - -- ensure_destination_ptr_alignment process_pixblock_head, \ -- process_pixblock_tail, \ -- process_pixblock_tail_head -+ ensure_destination_ptr_alignment \process_pixblock_head, \ -+ \process_pixblock_tail, \ -+ \process_pixblock_tail_head - - subs W, W, #pixblock_size - blt 700f - - /* Implement "head (tail_head) ... (tail_head) tail" loop pattern */ - pixld_a pixblock_size, dst_r_bpp, \ - (dst_r_basereg - pixblock_size * dst_r_bpp / 64), DST_R - fetch_src_pixblock - pixld pixblock_size, mask_bpp, \ - (mask_basereg - pixblock_size * mask_bpp / 64), MASK -- process_pixblock_head -+ \process_pixblock_head - subs W, W, #pixblock_size - blt 200f - 100: -- process_pixblock_tail_head -+ \process_pixblock_tail_head - subs W, W, #pixblock_size - bge 100b - 200: -- process_pixblock_tail -+ \process_pixblock_tail - pixst_a pixblock_size, dst_w_bpp, \ - (dst_w_basereg - pixblock_size * dst_w_bpp / 64), DST_W - 700: - /* Process the remaining trailing pixels in the scanline (dst aligned) */ - process_trailing_pixels 0, 1, \ -- process_pixblock_head, \ -- process_pixblock_tail, \ -- process_pixblock_tail_head -+ \process_pixblock_head, \ -+ \process_pixblock_tail, \ -+ \process_pixblock_tail_head - -- cleanup --.if use_nearest_scaling != 0 -+ \cleanup -+.if \use_nearest_scaling != 0 - sub x29, x29, 64 - ld1 {v8.8b, v9.8b, v10.8b, v11.8b}, [x29], 32 - ld1 {v12.8b, v13.8b, v14.8b, v15.8b}, [x29], 32 - ldp x8, x9, [x29, -80] - ldr x10, [x29, -96] - mov sp, x29 - ldp x29, x30, [sp], 16 - ret /* exit */ -@@ -1162,22 +1162,22 @@ 700: - ld1 {v12.8b, v13.8b, v14.8b, v15.8b}, [x29], 32 - mov sp, x29 - ldp x29, x30, [sp], 16 - ret /* exit */ - .endif - 800: - /* Process the remaining trailing pixels in the scanline (dst unaligned) */ - process_trailing_pixels 0, 0, \ -- process_pixblock_head, \ -- process_pixblock_tail, \ -- process_pixblock_tail_head -+ \process_pixblock_head, \ -+ \process_pixblock_tail, \ -+ \process_pixblock_tail_head - -- cleanup --.if use_nearest_scaling != 0 -+ \cleanup -+.if \use_nearest_scaling != 0 - sub x29, x29, 64 - ld1 {v8.8b, v9.8b, v10.8b, v11.8b}, [x29], 32 - ld1 {v12.8b, v13.8b, v14.8b, v15.8b}, [x29], 32 - ldp x8, x9, [x29, -80] - ldr x10, [x29, -88] - mov sp, x29 - ldp x29, x30, [sp], 16 - ret /* exit */ -@@ -1208,25 +1208,25 @@ 800: - .unreq DST_R - .unreq DST_W - .unreq W - .endif - - .purgem fetch_src_pixblock - .purgem pixld_src - -- .endfunc -+ pixman_end_asm_function - .endm - - .macro generate_composite_function_single_scanline x:vararg -- generate_composite_function_scanline 0, x -+ generate_composite_function_scanline 0, \x - .endm - - .macro generate_composite_function_nearest_scanline x:vararg -- generate_composite_function_scanline 1, x -+ generate_composite_function_scanline 1, \x - .endm - - /* Default prologue/epilogue, nothing special needs to be done */ - - .macro default_init - .endm - - .macro default_cleanup -@@ -1250,61 +1250,61 @@ 800: - * Conversion of 8 r5g6b6 pixels packed in 128-bit register (in) - * into a planar a8r8g8b8 format (with a, r, g, b color components - * stored into 64-bit registers out_a, out_r, out_g, out_b respectively). - * - * Warning: the conversion is destructive and the original - * value (in) is lost. - */ - .macro convert_0565_to_8888 in, out_a, out_r, out_g, out_b -- shrn &out_r&.8b, &in&.8h, #8 -- shrn &out_g&.8b, &in&.8h, #3 -- sli &in&.8h, &in&.8h, #5 -- movi &out_a&.8b, #255 -- sri &out_r&.8b, &out_r&.8b, #5 -- sri &out_g&.8b, &out_g&.8b, #6 -- shrn &out_b&.8b, &in&.8h, #2 -+ shrn \()\out_r\().8b, \()\in\().8h, #8 -+ shrn \()\out_g\().8b, \()\in\().8h, #3 -+ sli \()\in\().8h, \()\in\().8h, #5 -+ movi \()\out_a\().8b, #255 -+ sri \()\out_r\().8b, \()\out_r\().8b, #5 -+ sri \()\out_g\().8b, \()\out_g\().8b, #6 -+ shrn \()\out_b\().8b, \()\in\().8h, #2 - .endm - - .macro convert_0565_to_x888 in, out_r, out_g, out_b -- shrn &out_r&.8b, &in&.8h, #8 -- shrn &out_g&.8b, &in&.8h, #3 -- sli &in&.8h, &in&.8h, #5 -- sri &out_r&.8b, &out_r&.8b, #5 -- sri &out_g&.8b, &out_g&.8b, #6 -- shrn &out_b&.8b, &in&.8h, #2 -+ shrn \()\out_r\().8b, \()\in\().8h, #8 -+ shrn \()\out_g\().8b, \()\in\().8h, #3 -+ sli \()\in\().8h, \()\in\().8h, #5 -+ sri \()\out_r\().8b, \()\out_r\().8b, #5 -+ sri \()\out_g\().8b, \()\out_g\().8b, #6 -+ shrn \()\out_b\().8b, \()\in\().8h, #2 - .endm - - /* - * Conversion from planar a8r8g8b8 format (with a, r, g, b color components - * in 64-bit registers in_a, in_r, in_g, in_b respectively) into 8 r5g6b6 - * pixels packed in 128-bit register (out). Requires two temporary 128-bit - * registers (tmp1, tmp2) - */ - .macro convert_8888_to_0565 in_r, in_g, in_b, out, tmp1, tmp2 -- ushll &tmp1&.8h, &in_g&.8b, #7 -- shl &tmp1&.8h, &tmp1&.8h, #1 -- ushll &out&.8h, &in_r&.8b, #7 -- shl &out&.8h, &out&.8h, #1 -- ushll &tmp2&.8h, &in_b&.8b, #7 -- shl &tmp2&.8h, &tmp2&.8h, #1 -- sri &out&.8h, &tmp1&.8h, #5 -- sri &out&.8h, &tmp2&.8h, #11 -+ ushll \()\tmp1\().8h, \()\in_g\().8b, #7 -+ shl \()\tmp1\().8h, \()\tmp1\().8h, #1 -+ ushll \()\out\().8h, \()\in_r\().8b, #7 -+ shl \()\out\().8h, \()\out\().8h, #1 -+ ushll \()\tmp2\().8h, \()\in_b\().8b, #7 -+ shl \()\tmp2\().8h, \()\tmp2\().8h, #1 -+ sri \()\out\().8h, \()\tmp1\().8h, #5 -+ sri \()\out\().8h, \()\tmp2\().8h, #11 - .endm - - /* - * Conversion of four r5g6b5 pixels (in) to four x8r8g8b8 pixels - * returned in (out0, out1) registers pair. Requires one temporary - * 64-bit register (tmp). 'out1' and 'in' may overlap, the original - * value from 'in' is lost - */ - .macro convert_four_0565_to_x888_packed in, out0, out1, tmp -- shl &out0&.4h, &in&.4h, #5 /* G top 6 bits */ -- shl &tmp&.4h, &in&.4h, #11 /* B top 5 bits */ -- sri &in&.4h, &in&.4h, #5 /* R is ready in top bits */ -- sri &out0&.4h, &out0&.4h, #6 /* G is ready in top bits */ -- sri &tmp&.4h, &tmp&.4h, #5 /* B is ready in top bits */ -- ushr &out1&.4h, &in&.4h, #8 /* R is in place */ -- sri &out0&.4h, &tmp&.4h, #8 /* G & B is in place */ -- zip1 &tmp&.4h, &out0&.4h, &out1&.4h /* everything is in place */ -- zip2 &out1&.4h, &out0&.4h, &out1&.4h -- mov &out0&.d[0], &tmp&.d[0] -+ shl \()\out0\().4h, \()\in\().4h, #5 /* G top 6 bits */ -+ shl \()\tmp\().4h, \()\in\().4h, #11 /* B top 5 bits */ -+ sri \()\in\().4h, \()\in\().4h, #5 /* R is ready \in top bits */ -+ sri \()\out0\().4h, \()\out0\().4h, #6 /* G is ready \in top bits */ -+ sri \()\tmp\().4h, \()\tmp\().4h, #5 /* B is ready \in top bits */ -+ ushr \()\out1\().4h, \()\in\().4h, #8 /* R is \in place */ -+ sri \()\out0\().4h, \()\tmp\().4h, #8 /* G \() B is \in place */ -+ zip1 \()\tmp\().4h, \()\out0\().4h, \()\out1\().4h /* everything is \in place */ -+ zip2 \()\out1\().4h, \()\out0\().4h, \()\out1\().4h -+ mov \()\out0\().d[0], \()\tmp\().d[0] - .endm diff --git a/gfx/cairo/pixman-armasm.patch b/gfx/cairo/pixman-armasm.patch new file mode 100644 index 0000000000..0bf5a0a58e --- /dev/null +++ b/gfx/cairo/pixman-armasm.patch @@ -0,0 +1,25 @@ +diff --git a/gfx/cairo/libpixman/src/pixman-arm-asm.h b/gfx/cairo/libpixman/src/pixman-arm-asm.h +--- a/gfx/cairo/libpixman/src/pixman-arm-asm.h ++++ b/gfx/cairo/libpixman/src/pixman-arm-asm.h +@@ -20,19 +20,19 @@ + * AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING + * OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS + * SOFTWARE. + * + * Author: Jeff Muizelaar (jeff@infidigm.net) + * + */ + +- ++#ifdef HAVE_CONFIG_H + #include "pixman-config.h" +- ++#endif + + /* Supplementary macro for setting function attributes */ + .macro pixman_asm_function_impl fname + #ifdef ASM_HAVE_FUNC_DIRECTIVE + .func \fname + #endif + .global \fname + #ifdef __ELF__ diff --git a/gfx/cairo/pixman-intrin.patch b/gfx/cairo/pixman-intrin.patch index 66a4912cbd..1361f5c58e 100644 --- a/gfx/cairo/pixman-intrin.patch +++ b/gfx/cairo/pixman-intrin.patch @@ -1,14 +1,14 @@ diff --git a/gfx/cairo/libpixman/src/pixman-x86.c b/gfx/cairo/libpixman/src/pixman-x86.c --- a/gfx/cairo/libpixman/src/pixman-x86.c +++ b/gfx/cairo/libpixman/src/pixman-x86.c -@@ -104,16 +104,20 @@ have_cpuid (void) - - return !!result; +@@ -73,16 +73,20 @@ detect_cpu_features (void) + } #else - #error "Unknown compiler" + + #if defined (__GNUC__) + #include <cpuid.h> #endif - } +#ifdef _MSC_VER +#include <intrin.h> /* for __cpuid */ @@ -19,6 +19,6 @@ diff --git a/gfx/cairo/libpixman/src/pixman-x86.c b/gfx/cairo/libpixman/src/pixm uint32_t *a, uint32_t *b, uint32_t *c, uint32_t *d) { #if defined (__GNUC__) - - #if _PIXMAN_X86_64 - __asm__ volatile ( + *a = *b = *c = *d = 0; + __get_cpuid(feature, a, b, c, d); + #elif defined (_MSC_VER) diff --git a/gfx/cairo/pixman-mingw32.patch b/gfx/cairo/pixman-mingw32.patch deleted file mode 100644 index f2093904c3..0000000000 --- a/gfx/cairo/pixman-mingw32.patch +++ /dev/null @@ -1,26 +0,0 @@ -# HG changeset patch -# User Ryan VanderMeulen <ryanvm@gmail.com> -# Parent 6d9741f4bafc0e3ff3fc50009960966f03386af5 - -diff --git a/gfx/cairo/libpixman/src/pixman-mmx.c b/gfx/cairo/libpixman/src/pixman-mmx.c ---- a/gfx/cairo/libpixman/src/pixman-mmx.c -+++ b/gfx/cairo/libpixman/src/pixman-mmx.c -@@ -55,17 +55,17 @@ - extern __inline void __attribute__((__gnu_inline__, __always_inline__, __artificial__)) - _mm_empty (void) - { - - } - #endif - - #ifdef USE_X86_MMX --# if (defined(__SUNPRO_C) || defined(_MSC_VER) || defined(_WIN64)) -+# if (defined(__SUNPRO_C) || defined(_MSC_VER) || defined(_WIN64)) || defined(__MINGW32__) - # include <xmmintrin.h> - # else - /* We have to compile with -msse to use xmmintrin.h, but that causes SSE - * instructions to be generated that we don't want. Just duplicate the - * functions we want to use. */ - extern __inline int __attribute__((__gnu_inline__, __always_inline__, __artificial__)) - _mm_movemask_pi8 (__m64 __A) - { |