[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