[cairo-commit] 4 commits - src/cairo-ft-font.c src/cairo-image-compositor.c src/cairoint.h src/cairo-surface.c src/cairo-xlib-render-compositor.c test/Makefile.sources test/text-subpixel.c

GitLab Mirror gitlab-mirror at kemper.freedesktop.org
Thu Jul 18 21:48:59 UTC 2019


 src/cairo-ft-font.c                |   10 +++++
 src/cairo-image-compositor.c       |   13 +++++--
 src/cairo-surface.c                |   10 +++++
 src/cairo-xlib-render-compositor.c |   18 +++++++--
 src/cairoint.h                     |    5 ++
 test/Makefile.sources              |    1 
 test/text-subpixel.c               |   68 +++++++++++++++++++++++++++++++++++++
 7 files changed, 117 insertions(+), 8 deletions(-)

New commits:
commit aa263f881fb158202f32a7e3a8c6351dbe3626b8
Author: Matthias Clasen <mclasen at redhat.com>
Date:   Thu May 30 07:30:55 2019 -0400

    Fix a thinko in composite_color_glyphs
    
    We can't just move around the contents of the
    passed-in string, we need to make a copy. This
    was showing up as memory corruption in pango.
    
    See https://gitlab.gnome.org/GNOME/pango/issues/346

diff --git a/src/cairo-surface.c b/src/cairo-surface.c
index c30f84087..e112b660a 100644
--- a/src/cairo-surface.c
+++ b/src/cairo-surface.c
@@ -2820,6 +2820,7 @@ _cairo_surface_show_text_glyphs (cairo_surface_t	    *surface,
 				 const cairo_clip_t		*clip)
 {
     cairo_int_status_t status;
+    char *utf8_copy = NULL;
 
     TRACE ((stderr, "%s\n", __FUNCTION__));
     if (unlikely (surface->status))
@@ -2847,6 +2848,10 @@ _cairo_surface_show_text_glyphs (cairo_surface_t	    *surface,
     status = CAIRO_INT_STATUS_UNSUPPORTED;
 
     if (_cairo_scaled_font_has_color_glyphs (scaled_font)) {
+        utf8_copy = malloc (sizeof (char) * utf8_len);
+        memcpy (utf8_copy, utf8, sizeof (char) * utf8_len);
+        utf8 = utf8_copy;
+
         status = composite_color_glyphs (surface, op,
                                          source,
                                          (char *)utf8, &utf8_len,
@@ -2861,6 +2866,8 @@ _cairo_surface_show_text_glyphs (cairo_surface_t	    *surface,
         if (num_glyphs == 0)
             goto DONE;
     }
+    else
+      utf8_copy = NULL;
 
     /* The logic here is duplicated in _cairo_analysis_surface show_glyphs and
      * show_text_glyphs.  Keep in synch. */
@@ -2918,6 +2925,9 @@ DONE:
 	surface->serial++;
     }
 
+    if (utf8_copy)
+        free (utf8_copy);
+
     return _cairo_surface_set_error (surface, status);
 }
 
commit e4a79db0108be6a2b06dfce51a44bcbdead66ebd
Author: Matthias Clasen <mclasen at redhat.com>
Date:   Sat May 25 00:35:04 2019 +0000

    xlib compositor: Support subpixel positioning
    
    As for the image compository, support a 4x4
    subpixel grid.

diff --git a/src/cairo-xlib-render-compositor.c b/src/cairo-xlib-render-compositor.c
index 0db59a8a6..bce0ff6db 100644
--- a/src/cairo-xlib-render-compositor.c
+++ b/src/cairo-xlib-render-compositor.c
@@ -1074,8 +1074,7 @@ _cairo_xlib_glyph_fini (cairo_scaled_glyph_private_t *glyph_private,
 	    to_free->count = 0;
 	}
 
-	to_free->indices[to_free->count++] =
-	    _cairo_scaled_glyph_index (glyph);
+	to_free->indices[to_free->count++] = glyph->hash_entry.hash;
     }
 
     cairo_list_del (&glyph_private->link);
@@ -1193,7 +1192,7 @@ _cairo_xlib_surface_add_glyph (cairo_xlib_display_t *display,
     cairo_bool_t already_had_glyph_surface;
     cairo_xlib_font_glyphset_t *info;
 
-    glyph_index = _cairo_scaled_glyph_index (glyph);
+    glyph_index = glyph->hash_entry.hash;
 
     /* check to see if we have a pending XRenderFreeGlyph for this glyph */
     info = find_pending_free_glyph (display, font, glyph_index, glyph_surface);
@@ -1570,6 +1569,9 @@ check_composite_glyphs (const cairo_composite_rectangles_t *extents,
  * enough room for padding */
 #define _cairo_sz_xGlyphElt (sz_xGlyphElt + 4)
 
+#define PHASE(x) ((int)(floor (4 * (x + 0.125)) - 4 * floor (x + 0.125)))
+#define POSITION(x) ((int) floor (x + 0.125))
+
 static cairo_int_status_t
 composite_glyphs (void				*surface,
 		  cairo_operator_t		 op,
@@ -1605,9 +1607,15 @@ composite_glyphs (void				*surface,
     op = _render_operator (op),
     _cairo_xlib_surface_ensure_picture (dst);
     for (i = 0; i < num_glyphs; i++) {
+        int xphase, yphase;
 	int this_x, this_y;
 	int old_width;
 
+        xphase = PHASE(glyphs[i].d.x);
+        yphase = PHASE(glyphs[i].d.y);
+
+        glyphs[i].index |= (xphase << 24) | (yphase << 26);
+
 	status = _cairo_scaled_glyph_lookup (info->font,
 					     glyphs[i].index,
 					     CAIRO_SCALED_GLYPH_INFO_METRICS,
@@ -1615,8 +1623,8 @@ composite_glyphs (void				*surface,
 	if (unlikely (status))
 	    return status;
 
-	this_x = _cairo_lround (glyphs[i].d.x);
-	this_y = _cairo_lround (glyphs[i].d.y);
+	this_x = POSITION (glyphs[i].d.x);
+	this_y = POSITION (glyphs[i].d.y);
 
 	/* Send unsent glyphs to the server */
 	if (glyph->dev_private_key != display) {
commit 6fd4222ab00c3b93f038172a8c9d48375c5f86f0
Author: Matthias Clasen <mclasen at redhat.com>
Date:   Fri May 24 20:40:00 2019 +0000

    Add a testcase for subpixel positioning
    
    With the image compositor, you can see different
    phases. The XLib compositor always uses the same
    glyph rendering.

diff --git a/test/Makefile.sources b/test/Makefile.sources
index 3451125f9..ce5971cfb 100644
--- a/test/Makefile.sources
+++ b/test/Makefile.sources
@@ -357,6 +357,7 @@ test_sources = \
 	text-glyph-range.c				\
 	text-pattern.c					\
 	text-rotate.c					\
+	text-subpixel.c					\
 	text-transform.c				\
 	text-unhinted-metrics.c				\
 	text-zero-len.c					\
diff --git a/test/text-subpixel.c b/test/text-subpixel.c
new file mode 100644
index 000000000..3ea63b950
--- /dev/null
+++ b/test/text-subpixel.c
@@ -0,0 +1,68 @@
+/*
+ * Copyright © 2019 Matthias Clasen
+ *
+ * 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
+ * Red Hat, Inc. not be used in advertising or publicity pertaining to
+ * distribution of the software without specific, written prior
+ * permission. Red Hat, Inc. makes no representations about the
+ * suitability of this software for any purpose.  It is provided "as
+ * is" without express or implied warranty.
+ *
+ * RED HAT, INC. DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS
+ * SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND
+ * FITNESS, IN NO EVENT SHALL RED HAT, INC. 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: Adrian Johnson <ajohnson at redneon.com>
+ */
+
+#include "cairo-test.h"
+
+#define WIDTH  300
+#define HEIGHT 200
+
+static cairo_test_status_t
+draw (cairo_t *cr, int width, int height)
+{
+    cairo_font_options_t *font_options;
+    double size, y;
+
+    cairo_set_source_rgb (cr, 1, 1, 1);
+    cairo_paint (cr);
+
+    cairo_select_font_face (cr, CAIRO_TEST_FONT_FAMILY "DejaVu Sans Mono",
+			    CAIRO_FONT_SLANT_NORMAL,
+			    CAIRO_FONT_WEIGHT_NORMAL);
+
+    font_options = cairo_font_options_create();
+    cairo_get_font_options (cr, font_options);
+    cairo_font_options_set_hint_metrics (font_options, CAIRO_HINT_METRICS_OFF);
+    cairo_font_options_set_hint_style (font_options, CAIRO_HINT_STYLE_NONE);
+    cairo_set_font_options (cr, font_options);
+    cairo_font_options_destroy (font_options);
+
+    y = 0.0;
+    cairo_set_source_rgb (cr, 0, 0, 0);
+    for (size = 10.0; size <= 40.0; size += 3.3) {
+	cairo_set_font_size (cr, size);
+	y += size + 2.3;
+	cairo_move_to (cr, 5, y);
+	cairo_show_text (cr, "aaaaaaaaaa");
+    }
+
+    return CAIRO_TEST_SUCCESS;
+}
+
+CAIRO_TEST (text_subpixel_positioning,
+	    "Test subpixel positioning",
+	    "text, font", /* keywords */
+	    NULL, /* requirements */
+	    WIDTH, HEIGHT,
+	    NULL, draw)
commit ea9329215d3431ded51a71b724baf0edc25ad633
Author: Matthias Clasen <mclasen at redhat.com>
Date:   Sat Jul 28 12:25:47 2018 +0000

    image compositor: Support subpixel positioning
    
    Support subpixel positioning with a 4x4 subpixel grid.
    
    When compositing glyphs in the image compositor,
    we store the subpixel phases in the high bits of the
    glyph index. The _cairo_scaled_glyph_index() macro
    has been updated to discard these bits. By storing
    the phases in the glyph index, the glyph cache just
    keeps working. When loading a glyph, the Freetype
    font backend shifts the outline according to the
    phases.

diff --git a/src/cairo-ft-font.c b/src/cairo-ft-font.c
index 6b2af3713..7db16e8bd 100644
--- a/src/cairo-ft-font.c
+++ b/src/cairo-ft-font.c
@@ -2455,6 +2455,16 @@ _cairo_ft_scaled_glyph_load_glyph (cairo_ft_scaled_font_t *scaled_font,
     if (vertical_layout)
 	_cairo_ft_scaled_glyph_vertical_layout_bearing_fix (scaled_font, face->glyph);
 
+
+    if (face->glyph->format == FT_GLYPH_FORMAT_OUTLINE) {
+        FT_Pos xshift, yshift;
+
+        xshift = _cairo_scaled_glyph_xphase (scaled_glyph) << 4;
+        yshift = _cairo_scaled_glyph_yphase (scaled_glyph) << 4;
+
+        FT_Outline_Translate (&face->glyph->outline, xshift, yshift);
+    }
+
     return CAIRO_STATUS_SUCCESS;
 }
 
diff --git a/src/cairo-image-compositor.c b/src/cairo-image-compositor.c
index 434f67e59..6fccb79f1 100644
--- a/src/cairo-image-compositor.c
+++ b/src/cairo-image-compositor.c
@@ -847,6 +847,9 @@ _cairo_image_scaled_glyph_fini (cairo_scaled_font_t *scaled_font,
     CAIRO_MUTEX_UNLOCK (_cairo_glyph_cache_mutex);
 }
 
+#define PHASE(x) ((int)(floor (4 * (x + 0.125)) - 4 * floor (x + 0.125)))
+#define POSITION(x) ((int) floor (x + 0.125))
+
 static cairo_int_status_t
 composite_glyphs (void				*_dst,
 		  cairo_operator_t		 op,
@@ -888,6 +891,12 @@ composite_glyphs (void				*_dst,
     for (i = 0; i < info->num_glyphs; i++) {
 	unsigned long index = info->glyphs[i].index;
 	const void *glyph;
+        int xphase, yphase;
+
+        xphase = PHASE(info->glyphs[i].x);
+        yphase = PHASE(info->glyphs[i].y);
+
+	index = index | (xphase << 24) | (yphase << 26);
 
 	glyph = pixman_glyph_cache_lookup (glyph_cache, info->font, (void *)index);
 	if (!glyph) {
@@ -917,8 +926,8 @@ composite_glyphs (void				*_dst,
 	    }
 	}
 
-	pg->x = _cairo_lround (info->glyphs[i].x);
-	pg->y = _cairo_lround (info->glyphs[i].y);
+	pg->x = POSITION (info->glyphs[i].x);
+	pg->y = POSITION (info->glyphs[i].y);
 	pg->glyph = glyph;
 	pg++;
     }
diff --git a/src/cairoint.h b/src/cairoint.h
index 29b844d3a..7c1000556 100644
--- a/src/cairoint.h
+++ b/src/cairoint.h
@@ -428,7 +428,10 @@ _cairo_hash_bytes (unsigned long hash,
 		   const void *bytes,
 		   unsigned int length);
 
-#define _cairo_scaled_glyph_index(g) ((g)->hash_entry.hash)
+/* 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_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))
 
 #include "cairo-scaled-font-private.h"


More information about the cairo-commit mailing list