diff --git a/src/cairo-gstate.c b/src/cairo-gstate.c index 46d95f346..274a02a56 100644 --- a/src/cairo-gstate.c +++ b/src/cairo-gstate.c @@ -66,7 +66,8 @@ _cairo_gstate_transform_glyphs_to_backend (cairo_gstate_t *gstate, cairo_text_cluster_flags_t cluster_flags, cairo_glyph_t *transformed_glyphs, int *num_transformed_glyphs, - cairo_text_cluster_t *transformed_clusters); + cairo_text_cluster_t *transformed_clusters, + cairo_bool_t perform_early_clip); static void _cairo_gstate_update_device_transform (cairo_observer_t *observer, @@ -2035,14 +2036,16 @@ _cairo_gstate_show_text_glyphs (cairo_gstate_t *gstate, info->cluster_flags, transformed_glyphs, &num_glyphs, - transformed_clusters); + transformed_clusters, + TRUE); } else { _cairo_gstate_transform_glyphs_to_backend (gstate, glyphs, num_glyphs, NULL, 0, 0, transformed_glyphs, &num_glyphs, - NULL); + NULL, + TRUE); } if (num_glyphs == 0) @@ -2144,7 +2147,7 @@ _cairo_gstate_glyph_path (cairo_gstate_t *gstate, glyphs, num_glyphs, NULL, 0, 0, transformed_glyphs, - &num_glyphs, NULL); + &num_glyphs, NULL, FALSE); status = _cairo_scaled_font_glyph_path (gstate->scaled_font, transformed_glyphs, num_glyphs, @@ -2198,7 +2201,8 @@ _cairo_gstate_transform_glyphs_to_backend (cairo_gstate_t *gstate, cairo_text_cluster_flags_t cluster_flags, cairo_glyph_t *transformed_glyphs, int *num_transformed_glyphs, - cairo_text_cluster_t *transformed_clusters) + cairo_text_cluster_t *transformed_clusters, + cairo_bool_t perform_early_clip) { cairo_rectangle_int_t surface_extents; cairo_matrix_t *ctm = &gstate->ctm; @@ -2209,7 +2213,7 @@ _cairo_gstate_transform_glyphs_to_backend (cairo_gstate_t *gstate, int i, j, k; drop = TRUE; - if (! _cairo_gstate_int_clip_extents (gstate, &surface_extents)) { + if (!perform_early_clip || !_cairo_gstate_int_clip_extents (gstate, &surface_extents)) { drop = FALSE; /* unbounded surface */ } else { double scale10 = 10 * _cairo_scaled_font_get_max_scale (gstate->scaled_font); diff --git a/test/glyph-path.c b/test/glyph-path.c new file mode 100644 index 000000000..b61f193a1 --- /dev/null +++ b/test/glyph-path.c @@ -0,0 +1,82 @@ +/* + * Copyright © 2024 worldiety GmbH + * + * Permission to use, copy, modify, distribute, and sell this software + * and its documentation for any purpose is hereby granted without + * fee, provided that the above copyright notice appear in all copies + * and that both that copyright notice and this permission notice + * appear in supporting documentation, and that the name of + * worldiety not be used in advertising or publicity pertaining to + * distribution of the software without specific, written prior + * permission. worldiety makes no representations about the + * suitability of this software for any purpose. It is provided "as + * is" without express or implied warranty. + * + * WORLDIETY DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS + * SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND + * FITNESS, IN NO EVENT SHALL WORLDIETY BE LIABLE FOR ANY SPECIAL, + * INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER + * RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION + * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR + * IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + * + * Author: Heiko Lewin + */ +#include "cairo-test.h" + +#define WIDTH 128 +#define HEIGHT 64 + + +static cairo_test_status_t +draw(cairo_t *cr, int width, int height) { + cairo_glyph_t *glyphs = NULL; + int num_glyphs = 0; + cairo_path_t *path = NULL, *path2 = NULL; + (void)width; + (void)height; + + /* black on white color */ + cairo_set_source_rgb(cr, 1., 1., 1.); + cairo_paint(cr); + cairo_set_source_rgb(cr, 0, 0, 0); + + + /* translate to some point well outside the surface */ + cairo_translate(cr, -width * 100, 0); + + /* create a simple path to illustrate the correct behaviour */ + cairo_rectangle(cr, 0, 0, width/2.0, 2); + path = cairo_copy_path(cr); + cairo_new_path(cr); + + /* create another path from glyphs - this is broken when clipping to early */ + { + cairo_set_font_size(cr, 32); + cairo_scaled_font_t *sf = cairo_get_scaled_font(cr); + cairo_scaled_font_text_to_glyphs(sf, 0, 0, "Test", 4, &glyphs, &num_glyphs, 0, 0, 0); + cairo_glyph_path(cr, glyphs, num_glyphs); + path2 = cairo_copy_path(cr); + } + + /* translate to a visible point and draw both paths */ + cairo_identity_matrix(cr); + cairo_translate(cr, width/4.0, 48); + + cairo_append_path(cr, path); + cairo_append_path(cr, path2); + cairo_fill(cr); + + cairo_path_destroy(path); + cairo_path_destroy(path2); + free(glyphs); + + return CAIRO_TEST_SUCCESS; +} + +CAIRO_TEST (glyph_path, + "Tests cairo_glyph_path", + "text, glyph, path", /* keywords */ + "target=raster", /* should be enough */ + WIDTH, HEIGHT, + NULL, draw) diff --git a/test/meson.build b/test/meson.build index b4f799c77..786ac2a84 100644 --- a/test/meson.build +++ b/test/meson.build @@ -154,6 +154,7 @@ test_sources = [ 'font-matrix-translation.c', 'font-options.c', 'glyph-cache-pressure.c', + 'glyph-path.c', 'get-and-set.c', 'get-clip.c', 'get-group-target.c', diff --git a/test/reference/glyph-path.image.argb32.ref.png b/test/reference/glyph-path.image.argb32.ref.png new file mode 100644 index 000000000..bf61b6581 Binary files /dev/null and b/test/reference/glyph-path.image.argb32.ref.png differ diff --git a/test/reference/glyph-path.image.rgb24.ref.png b/test/reference/glyph-path.image.rgb24.ref.png new file mode 100644 index 000000000..bf61b6581 Binary files /dev/null and b/test/reference/glyph-path.image.rgb24.ref.png differ diff --git a/test/reference/glyph-path.image16.rgb24.ref.png b/test/reference/glyph-path.image16.rgb24.ref.png new file mode 100644 index 000000000..be94f8463 Binary files /dev/null and b/test/reference/glyph-path.image16.rgb24.ref.png differ