Add ARGB glyph support.

Change Bi-level glyph support to use A1 format.
Support bit/byte swapping of glyph image data in the Xlib backend.
reviewed by: cworth, otaylor
This commit is contained in:
Keith Packard 2005-07-21 14:31:28 +00:00
parent a3ad7dc0b9
commit 3c0bfb3975
4 changed files with 505 additions and 68 deletions

View file

@ -1,3 +1,27 @@
2005-07-21 Keith Packard <keithp@keithp.com>
reviewed by: cworth, otaylor
* src/cairo-ft-font.c: (_ft_font_cache_create_entry),
(_ft_unscaled_font_set_scale), (_native_byte_order_lsb),
(_get_bitmap_surface), (_render_glyph_outline),
(_render_glyph_bitmap), (_get_pattern_load_flags),
(_get_options_load_flags):
* src/cairo-xlib-surface.c: (cairo_xlib_surface_set_size),
(_native_byte_order_lsb), (_xlib_glyphset_cache_create_entry),
(_xlib_glyphset_cache_destroy_entry), (_get_glyphset_cache),
(_select_text_mask_format), (_cairo_xlib_surface_show_glyphs32),
(_cairo_xlib_surface_show_glyphs16),
(_cairo_xlib_surface_show_glyphs8):
* src/cairoint.h:
Add ARGB glyph support.
Change Bi-level glyph support to use A1 format.
Support bit/byte swapping of glyph image data in
the Xlib backend.
2005-07-21 Carl Worth <cworth@cworth.org>
* src/cairo-ft.h:

View file

@ -1,5 +1,6 @@
/* cairo - a vector graphics library with display and print output
*
* Copyright © 2000 Keith Packard
* Copyright © 2005 Red Hat, Inc
*
* This library is free software; you can redistribute it and/or
@ -32,6 +33,8 @@
* Contributor(s):
* Graydon Hoare <graydon@redhat.com>
* Owen Taylor <otaylor@redhat.com>
* Keith Packard <keithp@keithp.com>
* Carl Worth <cworth@cworth.org>
*/
#include <float.h>
@ -238,7 +241,7 @@ _ft_font_cache_create_entry (void *cache,
void *key,
void **return_entry)
{
cairo_ft_cache_key_t *k = (cairo_ft_cache_key_t *) key;
cairo_ft_cache_key_t *k = key;
cairo_ft_cache_entry_t *entry;
entry = malloc (sizeof (cairo_ft_cache_entry_t));
@ -473,6 +476,7 @@ _ft_unscaled_font_set_scale (ft_unscaled_font_t *unscaled,
ft_font_transform_t sf;
FT_Matrix mat;
FT_UInt pixel_width, pixel_height;
FT_Error error;
assert (unscaled->face != NULL);
@ -506,9 +510,14 @@ _ft_unscaled_font_set_scale (ft_unscaled_font_t *unscaled,
if ((unscaled->face->face_flags & FT_FACE_FLAG_SCALABLE) != 0) {
pixel_width = sf.x_scale;
pixel_height = sf.y_scale;
error = FT_Set_Char_Size (unscaled->face,
sf.x_scale * 64.0,
sf.y_scale * 64.0,
0, 0);
} else {
double min_distance = DBL_MAX;
int i;
int best_i = 0;
pixel_width = pixel_height = 0;
@ -518,13 +527,20 @@ _ft_unscaled_font_set_scale (ft_unscaled_font_t *unscaled,
if (distance <= min_distance) {
min_distance = distance;
pixel_width = unscaled->face->available_sizes[i].x_ppem >> 6;
pixel_height = unscaled->face->available_sizes[i].y_ppem >> 6;
best_i = i;
}
}
error = FT_Set_Char_Size (unscaled->face,
unscaled->face->available_sizes[best_i].x_ppem,
unscaled->face->available_sizes[best_i].y_ppem,
0, 0);
if (error )
error = FT_Set_Pixel_Sizes (unscaled->face,
unscaled->face->available_sizes[best_i].width,
unscaled->face->available_sizes[best_i].height);
}
FT_Set_Pixel_Sizes (unscaled->face, pixel_width, pixel_height);
assert (error == 0);
}
static void
@ -564,16 +580,44 @@ _cairo_ft_unscaled_font_destroy (void *abstract_font)
}
}
/* Empirically-derived subpixel filtering values thanks to Keith
* Packard and libXft. */
static const int filters[3][3] = {
/* red */
#if 0
{ 65538*4/7,65538*2/7,65538*1/7 },
/* green */
{ 65536*1/4, 65536*2/4, 65537*1/4 },
/* blue */
{ 65538*1/7,65538*2/7,65538*4/7 },
#endif
{ 65538*9/13,65538*3/13,65538*1/13 },
/* green */
{ 65538*1/6, 65538*4/6, 65538*1/6 },
/* blue */
{ 65538*1/13,65538*3/13,65538*9/13 },
};
static cairo_bool_t
_native_byte_order_lsb (void)
{
int x = 1;
return *((char *) &x) == 1;
}
/* Fills in val->image with an image surface created from @bitmap
*/
static cairo_status_t
_get_bitmap_surface (cairo_image_glyph_cache_entry_t *val,
FT_Bitmap *bitmap,
cairo_bool_t own_buffer)
cairo_bool_t own_buffer,
int rgba)
{
int width, height, stride;
unsigned char *data;
int i, j;
int format = CAIRO_FORMAT_A8;
cairo_bool_t subpixel = FALSE;
width = bitmap->width;
height = bitmap->rows;
@ -586,27 +630,7 @@ _get_bitmap_surface (cairo_image_glyph_cache_entry_t *val,
} else {
switch (bitmap->pixel_mode) {
case FT_PIXEL_MODE_MONO:
stride = (width + 3) & ~3;
data = calloc (stride * height, 1);
if (!data)
return CAIRO_STATUS_NO_MEMORY;
for (j = 0; j < height; j++) {
const unsigned char *p = bitmap->buffer + j * bitmap->pitch;
unsigned char *q = data + j * stride;
for (i = 0; i < width; i++) {
/* FreeType bitmaps are always stored MSB */
unsigned char byte = p[i >> 3];
unsigned char bit = 1 << (7 - (i % 8));
if (byte & bit)
q[i] = 0xff;
}
}
if (own_buffer)
free (bitmap->buffer);
break;
case FT_PIXEL_MODE_GRAY:
stride = bitmap->pitch;
stride = (((width + 31) & ~31) >> 3);
if (own_buffer) {
data = bitmap->buffer;
} else {
@ -615,20 +639,138 @@ _get_bitmap_surface (cairo_image_glyph_cache_entry_t *val,
return CAIRO_STATUS_NO_MEMORY;
memcpy (data, bitmap->buffer, stride * height);
}
break;
if (_native_byte_order_lsb())
{
unsigned char *d = data, c;
int count = stride * height;
while (count--) {
c = *d;
c = ((c << 1) & 0xaa) | ((c >> 1) & 0x55);
c = ((c << 2) & 0xcc) | ((c >> 2) & 0x33);
c = ((c << 4) & 0xf0) | ((c >> 4) & 0x0f);
*d++ = c;
}
}
format = CAIRO_FORMAT_A1;
break;
case FT_PIXEL_MODE_LCD:
case FT_PIXEL_MODE_LCD_V:
case FT_PIXEL_MODE_GRAY:
if (rgba == FC_RGBA_NONE || rgba == FC_RGBA_UNKNOWN)
{
stride = bitmap->pitch;
if (own_buffer) {
data = bitmap->buffer;
} else {
data = malloc (stride * height);
if (!data)
return CAIRO_STATUS_NO_MEMORY;
memcpy (data, bitmap->buffer, stride * height);
}
format = CAIRO_FORMAT_A8;
} else {
int x, y;
unsigned char *in_line, *out_line, *in;
unsigned int *out;
unsigned int red, green, blue;
int rf, gf, bf;
int s;
int o, os;
unsigned char *data_rgba;
unsigned int width_rgba, stride_rgba;
int vmul = 1;
int hmul = 1;
switch (rgba) {
case FC_RGBA_RGB:
case FC_RGBA_BGR:
default:
width /= 3;
hmul = 3;
break;
case FC_RGBA_VRGB:
case FC_RGBA_VBGR:
vmul = 3;
height /= 3;
break;
}
subpixel = TRUE;
/*
* Filter the glyph to soften the color fringes
*/
width_rgba = width;
stride = bitmap->pitch;
stride_rgba = (width_rgba * 4 + 3) & ~3;
data_rgba = calloc (1, stride_rgba * height);
os = 1;
switch (rgba) {
case FC_RGBA_VRGB:
os = stride;
case FC_RGBA_RGB:
default:
rf = 0;
gf = 1;
bf = 2;
break;
case FC_RGBA_VBGR:
os = stride;
case FC_RGBA_BGR:
bf = 0;
gf = 1;
rf = 2;
break;
}
in_line = bitmap->buffer;
out_line = data_rgba;
for (y = 0; y < height; y++)
{
in = in_line;
out = (unsigned int *) out_line;
in_line += stride * vmul;
out_line += stride_rgba;
for (x = 0; x < width * hmul; x += hmul)
{
red = green = blue = 0;
o = 0;
for (s = 0; s < 3; s++)
{
red += filters[rf][s]*in[x+o];
green += filters[gf][s]*in[x+o];
blue += filters[bf][s]*in[x+o];
o += os;
}
red = red / 65536;
green = green / 65536;
blue = blue / 65536;
*out++ = (green << 24) | (red << 16) | (green << 8) | blue;
}
}
/* Images here are stored in native format. The
* backend must convert to its own format as needed
*/
if (own_buffer)
free (bitmap->buffer);
data = data_rgba;
stride = stride_rgba;
format = CAIRO_FORMAT_ARGB32;
}
break;
case FT_PIXEL_MODE_GRAY2:
case FT_PIXEL_MODE_GRAY4:
/* These could be triggered by very rare types of TrueType fonts */
case FT_PIXEL_MODE_LCD:
case FT_PIXEL_MODE_LCD_V:
/* These should never be triggered unless we ask for them */
default:
return CAIRO_STATUS_NO_MEMORY;
}
val->image = (cairo_image_surface_t *)
cairo_image_surface_create_for_data (data,
CAIRO_FORMAT_A8,
format,
width, height, stride);
if (val->image == NULL) {
free (data);
@ -636,6 +778,9 @@ _get_bitmap_surface (cairo_image_glyph_cache_entry_t *val,
return CAIRO_STATUS_NO_MEMORY;
}
if (subpixel)
pixman_image_set_component_alpha (val->image->pixman_image, TRUE);
_cairo_image_surface_assume_ownership_of_data (val->image);
}
@ -664,12 +809,18 @@ static cairo_status_t
_render_glyph_outline (FT_Face face,
cairo_image_glyph_cache_entry_t *val)
{
int rgba = FC_RGBA_UNKNOWN;
FT_GlyphSlot glyphslot = face->glyph;
FT_Outline *outline = &glyphslot->outline;
unsigned int width, height, stride;
FT_Bitmap bitmap;
FT_BBox cbox;
cairo_status_t status = CAIRO_STATUS_SUCCESS;
FT_Matrix matrix;
int hmul = 1;
int vmul = 1;
unsigned int width, height, stride;
cairo_format_t format;
cairo_bool_t subpixel = FALSE;
cairo_status_t status;
FT_Outline_Get_CBox (outline, &cbox);
@ -677,40 +828,84 @@ _render_glyph_outline (FT_Face face,
cbox.yMin &= -64;
cbox.xMax = (cbox.xMax + 63) & -64;
cbox.yMax = (cbox.yMax + 63) & -64;
width = (unsigned int) ((cbox.xMax - cbox.xMin) >> 6);
height = (unsigned int) ((cbox.yMax - cbox.yMin) >> 6);
stride = (width * hmul + 3) & ~3;
if (width * height == 0) {
val->image = NULL;
/* Looks like fb handles zero-sized images just fine */
if ((val->key.flags & FT_LOAD_MONOCHROME) != 0)
format = CAIRO_FORMAT_A8;
else if ((val->key.flags &
(FT_LOAD_TARGET_LCD | FT_LOAD_TARGET_LCD_V)) != 0)
format= CAIRO_FORMAT_ARGB32;
else
format = CAIRO_FORMAT_A8;
val->image = (cairo_image_surface_t *)
cairo_image_surface_create_for_data (NULL, format, 0, 0, 0);
} else {
matrix.xx = matrix.yy = 0x10000L;
matrix.xy = matrix.yx = 0;
if ((val->key.flags & FT_LOAD_MONOCHROME) != 0) {
bitmap.pixel_mode = FT_PIXEL_MODE_MONO;
bitmap.num_grays = 1;
stride = ((width + 31) & -32) >> 3;
} else {
/* XXX not a complete set of flags. This code
* will go away when cworth rewrites the glyph
* cache code */
if (val->key.flags & FT_LOAD_TARGET_LCD)
rgba = FC_RGBA_RGB;
else if (val->key.flags & FT_LOAD_TARGET_LCD_V)
rgba = FC_RGBA_VBGR;
switch (rgba) {
case FC_RGBA_RGB:
case FC_RGBA_BGR:
matrix.xx *= 3;
hmul = 3;
subpixel = TRUE;
break;
case FC_RGBA_VRGB:
case FC_RGBA_VBGR:
matrix.yy *= 3;
vmul = 3;
subpixel = TRUE;
break;
}
if (subpixel)
format = CAIRO_FORMAT_ARGB32;
else
format = CAIRO_FORMAT_A8;
if (subpixel)
FT_Outline_Transform (outline, &matrix);
bitmap.pixel_mode = FT_PIXEL_MODE_GRAY;
bitmap.num_grays = 256;
stride = (width + 3) & -4;
stride = (width * hmul + 3) & -4;
}
bitmap.pitch = stride;
bitmap.width = width;
bitmap.rows = height;
bitmap.width = width * hmul;
bitmap.rows = height * vmul;
bitmap.buffer = calloc (1, stride * height);
if (bitmap.buffer == NULL) {
return CAIRO_STATUS_NO_MEMORY;
}
FT_Outline_Translate (outline, -cbox.xMin, -cbox.yMin);
FT_Outline_Translate (outline, -cbox.xMin*hmul, -cbox.yMin*vmul);
if (FT_Outline_Get_Bitmap (glyphslot->library, outline, &bitmap) != 0) {
free (bitmap.buffer);
return CAIRO_STATUS_NO_MEMORY;
}
status = _get_bitmap_surface (val, &bitmap, TRUE);
status = _get_bitmap_surface (val, &bitmap, TRUE, rgba);
if (status)
return status;
}
@ -723,7 +918,7 @@ _render_glyph_outline (FT_Face face,
val->size.x = (short) (cbox.xMin >> 6);
val->size.y = - (short) (cbox.yMax >> 6);
return status;
return CAIRO_STATUS_SUCCESS;
}
/* Converts a bitmap (or other) FT_GlyphSlot into an image
@ -760,7 +955,7 @@ _render_glyph_bitmap (FT_Face face,
if (error)
return CAIRO_STATUS_NO_MEMORY;
_get_bitmap_surface (val, &glyphslot->bitmap, FALSE);
_get_bitmap_surface (val, &glyphslot->bitmap, FALSE, FC_RGBA_NONE);
val->size.x = - glyphslot->bitmap_left;
val->size.y = - glyphslot->bitmap_top;
@ -1001,6 +1196,7 @@ static int
_get_pattern_load_flags (FcPattern *pattern)
{
FcBool antialias, vertical_layout, hinting, autohint;
int rgba;
#ifdef FC_HINT_STYLE
int hintstyle;
#endif
@ -1048,6 +1244,25 @@ _get_pattern_load_flags (FcPattern *pattern)
load_flags |= FT_LOAD_NO_HINTING;
#endif /* FC_FHINT_STYLE */
if (FcPatternGetInteger (pattern,
FC_RGBA, 0, &rgba) != FcResultMatch)
rgba = FC_RGBA_UNKNOWN;
switch (rgba) {
case FC_RGBA_UNKNOWN:
case FC_RGBA_NONE:
default:
break;
case FC_RGBA_RGB:
case FC_RGBA_BGR:
load_flags |= FT_LOAD_TARGET_LCD;
break;
case FC_RGBA_VRGB:
case FC_RGBA_VBGR:
load_flags |= FT_LOAD_TARGET_LCD_V;
break;
}
/* force autohinting if requested */
if (FcPatternGetBool (pattern,
FC_AUTOHINT, 0, &autohint) != FcResultMatch)
@ -1072,10 +1287,28 @@ _get_options_load_flags (const cairo_font_options_t *options)
int load_flags = 0;
/* disable antialiasing if requested */
if (options->antialias == CAIRO_ANTIALIAS_NONE)
switch (options->antialias) {
case CAIRO_ANTIALIAS_NONE:
load_flags |= FT_LOAD_TARGET_MONO;
else
break;
case CAIRO_ANTIALIAS_SUBPIXEL:
switch (options->subpixel_order) {
case CAIRO_SUBPIXEL_ORDER_DEFAULT:
case CAIRO_SUBPIXEL_ORDER_RGB:
case CAIRO_SUBPIXEL_ORDER_BGR:
load_flags |= FT_LOAD_TARGET_LCD;
break;
case CAIRO_SUBPIXEL_ORDER_VRGB:
case CAIRO_SUBPIXEL_ORDER_VBGR:
load_flags |= FT_LOAD_TARGET_LCD_V;
break;
}
/* fall through ... */
case CAIRO_ANTIALIAS_DEFAULT:
case CAIRO_ANTIALIAS_GRAY:
load_flags |= FT_LOAD_NO_BITMAP;
break;
}
/* disable hinting if requested */
switch (options->hint_style) {

View file

@ -1,6 +1,7 @@
/* cairo - a vector graphics library with display and print output
*
* Copyright © 2002 University of Southern California
* 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
@ -1622,7 +1623,6 @@ cairo_xlib_surface_set_size (cairo_surface_t *surface,
xlib_surface->width = width;
xlib_surface->height = height;
}
/**
* cairo_xlib_surface_set_drawable:
* @surface: a #cairo_surface_t for the XLib backend
@ -1671,15 +1671,25 @@ cairo_xlib_surface_set_drawable (cairo_surface_t *abstract_surface,
typedef struct glyphset_cache {
cairo_cache_t base;
struct glyphset_cache *next;
Display *display;
XRenderPictFormat *a8_pict_format;
GlyphSet glyphset;
Glyph counter;
XRenderPictFormat *a1_pict_format;
GlyphSet a1_glyphset;
XRenderPictFormat *a8_pict_format;
GlyphSet a8_glyphset;
XRenderPictFormat *argb32_pict_format;
GlyphSet argb32_glyphset;
struct glyphset_cache *next;
} glyphset_cache_t;
typedef struct {
cairo_glyph_cache_key_t key;
GlyphSet glyphset;
Glyph glyph;
} glyphset_cache_entry_t;
@ -1689,6 +1699,14 @@ _next_xlib_glyph (glyphset_cache_t *cache)
return ++(cache->counter);
}
static cairo_bool_t
_native_byte_order_lsb (void)
{
int x = 1;
return *((char *) &x) == 1;
}
static cairo_status_t
_xlib_glyphset_cache_create_entry (void *abstract_cache,
void *abstract_key,
@ -1698,6 +1716,7 @@ _xlib_glyphset_cache_create_entry (void *abstract_cache,
cairo_glyph_cache_key_t *key = abstract_key;
glyphset_cache_entry_t *entry;
XGlyphInfo glyph_info;
unsigned char *data;
cairo_status_t status;
@ -1724,7 +1743,9 @@ _xlib_glyphset_cache_create_entry (void *abstract_cache,
entry->glyph = _next_xlib_glyph (cache);
glyph_info.width = im->image ? im->image->stride : im->size.width;
data = im->image->data;
glyph_info.width = im->size.width;
glyph_info.height = im->size.height;
/*
@ -1768,14 +1789,81 @@ _xlib_glyphset_cache_create_entry (void *abstract_cache,
glyph_info.xOff = 0;
glyph_info.yOff = 0;
XRenderAddGlyphs (cache->display, cache->glyphset,
&(entry->glyph), &(glyph_info), 1,
im->image ? (char *) im->image->data : NULL,
im->image ? glyph_info.height * glyph_info.width : 0);
switch (im->image->format) {
case CAIRO_FORMAT_A1:
/* local bitmaps are always stored with bit == byte */
if (_native_byte_order_lsb() !=
(BitmapBitOrder (cache->display) == LSBFirst))
{
int c = im->image->stride * im->size.height;
unsigned char *d;
unsigned char *new, *n;
new = malloc (c);
if (!new)
return CAIRO_STATUS_NO_MEMORY;
n = new;
d = data;
while (c--)
{
char b = *d++;
b = ((b << 1) & 0xaa) | ((b >> 1) & 0x55);
b = ((b << 2) & 0xcc) | ((b >> 2) & 0x33);
b = ((b << 4) & 0xf0) | ((b >> 4) & 0x0f);
*n++ = b;
}
data = new;
}
entry->glyphset = cache->a1_glyphset;
break;
case CAIRO_FORMAT_A8:
entry->glyphset = cache->a8_glyphset;
break;
case CAIRO_FORMAT_ARGB32:
if (_native_byte_order_lsb() !=
(ImageByteOrder (cache->display) == LSBFirst))
{
int c = im->image->stride * im->size.height;
unsigned char *d;
unsigned char *new, *n;
new = malloc (c);
if (!new)
return CAIRO_STATUS_NO_MEMORY;
n = new;
d = data;
while ((c -= 4) >= 0)
{
n[3] = d[0];
n[2] = d[1];
n[1] = d[2];
n[0] = d[3];
d += 4;
n += 4;
}
data = new;
}
entry->glyphset = cache->argb32_glyphset;
break;
case CAIRO_FORMAT_RGB24:
default:
ASSERT_NOT_REACHED;
break;
}
/* XXX assume X server wants pixman padding. Xft assumes this as well */
entry->key.base.memory = im->image ? im->image->width * im->image->stride : 0;
XRenderAddGlyphs (cache->display, entry->glyphset,
&(entry->glyph), &(glyph_info), 1,
(char *) data,
im->image->stride * glyph_info.height);
if (data != im->image->data)
free (data);
entry->key.base.memory = im->image->height * im->image->stride;
*return_entry = entry;
_cairo_unlock_global_image_glyph_cache ();
return CAIRO_STATUS_SUCCESS;
}
@ -1793,7 +1881,8 @@ _xlib_glyphset_cache_destroy_entry (void *abstract_cache,
glyphset_cache_entry_t *entry = abstract_entry;
_cairo_unscaled_font_destroy (entry->key.unscaled);
XRenderFreeGlyphs (cache->display, cache->glyphset, &(entry->glyph), 1);
XRenderFreeGlyphs (cache->display, entry->glyphset,
&(entry->glyph), 1);
free (entry);
}
@ -1831,9 +1920,10 @@ _get_glyphset_cache (Display *d)
* There should usually only be one, or a very small number, of
* displays. So we just do a linear scan.
*/
glyphset_cache_t *cache;
/* XXX: This is not thread-safe. Xft has example code to get
* per-display data via Xlib extension mechanisms. */
for (cache = _xlib_glyphset_caches; cache != NULL; cache = cache->next) {
if (cache->display == d)
return cache;
@ -1850,8 +1940,14 @@ _get_glyphset_cache (Display *d)
cache->display = d;
cache->counter = 0;
cache->a1_pict_format = XRenderFindStandardFormat (d, PictStandardA1);
cache->a1_glyphset = XRenderCreateGlyphSet (d, cache->a1_pict_format);
cache->a8_pict_format = XRenderFindStandardFormat (d, PictStandardA8);
cache->glyphset = XRenderCreateGlyphSet (d, cache->a8_pict_format);
cache->a8_glyphset = XRenderCreateGlyphSet (d, cache->a8_pict_format);
cache->argb32_pict_format = XRenderFindStandardFormat (d, PictStandardARGB32);
cache->argb32_glyphset = XRenderCreateGlyphSet (d, cache->argb32_pict_format);;
cache->next = _xlib_glyphset_caches;
_xlib_glyphset_caches = cache;
@ -1867,6 +1963,28 @@ _get_glyphset_cache (Display *d)
#define N_STACK_BUF 1024
static XRenderPictFormat *
_select_text_mask_format (glyphset_cache_t *cache,
cairo_bool_t have_a1_glyphs,
cairo_bool_t have_a8_glyphs,
cairo_bool_t have_argb32_glyphs)
{
if (have_a8_glyphs)
return cache->a8_pict_format;
if (have_a1_glyphs && have_argb32_glyphs)
return cache->a8_pict_format;
if (have_a1_glyphs)
return cache->a1_pict_format;
if (have_argb32_glyphs)
return cache->argb32_pict_format;
/* when there are no glyphs to draw, just pick something */
return cache->a8_pict_format;
}
static cairo_status_t
_cairo_xlib_surface_show_glyphs32 (cairo_scaled_font_t *scaled_font,
cairo_operator_t operator,
@ -1890,6 +2008,9 @@ _cairo_xlib_surface_show_glyphs32 (cairo_scaled_font_t *scaled_font,
int thisX, thisY;
int lastX = 0, lastY = 0;
cairo_bool_t have_a1, have_a8, have_argb32;
XRenderPictFormat *mask_format;
/* Acquire arrays of suitable sizes. */
if (num_glyphs < N_STACK_BUF) {
elts = stack_elts;
@ -1906,11 +2027,26 @@ _cairo_xlib_surface_show_glyphs32 (cairo_scaled_font_t *scaled_font,
}
have_a1 = FALSE;
have_a8 = FALSE;
have_argb32 = FALSE;
for (i = 0; i < num_glyphs; ++i) {
GlyphSet glyphset;
glyphset = entries[i]->glyphset;
if (glyphset == cache->a1_glyphset)
have_a1 = TRUE;
else if (glyphset == cache->a8_glyphset)
have_a8 = TRUE;
else if (glyphset == cache->argb32_glyphset)
have_argb32 = TRUE;
chars[i] = entries[i]->glyph;
elts[i].chars = &(chars[i]);
elts[i].nchars = 1;
elts[i].glyphset = cache->glyphset;
elts[i].glyphset = glyphset;
thisX = (int) floor (glyphs[i].x + 0.5);
thisY = (int) floor (glyphs[i].y + 0.5);
elts[i].xOff = thisX - lastX;
@ -1919,6 +2055,9 @@ _cairo_xlib_surface_show_glyphs32 (cairo_scaled_font_t *scaled_font,
lastY = thisY;
}
mask_format = _select_text_mask_format (cache,
have_a1, have_a8, have_argb32);
XRenderCompositeText32 (self->dpy,
_render_operator (operator),
src->src_picture,
@ -1967,6 +2106,9 @@ _cairo_xlib_surface_show_glyphs16 (cairo_scaled_font_t *scaled_font,
int thisX, thisY;
int lastX = 0, lastY = 0;
cairo_bool_t have_a1, have_a8, have_argb32;
XRenderPictFormat *mask_format;
/* Acquire arrays of suitable sizes. */
if (num_glyphs < N_STACK_BUF) {
elts = stack_elts;
@ -1983,11 +2125,26 @@ _cairo_xlib_surface_show_glyphs16 (cairo_scaled_font_t *scaled_font,
}
have_a1 = FALSE;
have_a8 = FALSE;
have_argb32 = FALSE;
for (i = 0; i < num_glyphs; ++i) {
GlyphSet glyphset;
glyphset = entries[i]->glyphset;
if (glyphset == cache->a1_glyphset)
have_a1 = TRUE;
else if (glyphset == cache->a8_glyphset)
have_a8 = TRUE;
else if (glyphset == cache->argb32_glyphset)
have_argb32 = TRUE;
chars[i] = entries[i]->glyph;
elts[i].chars = &(chars[i]);
elts[i].nchars = 1;
elts[i].glyphset = cache->glyphset;
elts[i].glyphset = glyphset;
thisX = (int) floor (glyphs[i].x + 0.5);
thisY = (int) floor (glyphs[i].y + 0.5);
elts[i].xOff = thisX - lastX;
@ -1996,11 +2153,14 @@ _cairo_xlib_surface_show_glyphs16 (cairo_scaled_font_t *scaled_font,
lastY = thisY;
}
mask_format = _select_text_mask_format (cache,
have_a1, have_a8, have_argb32);
XRenderCompositeText16 (self->dpy,
_render_operator (operator),
src->src_picture,
self->dst_picture,
cache->a8_pict_format,
mask_format,
source_x, source_y,
0, 0,
elts, num_glyphs);
@ -2043,6 +2203,12 @@ _cairo_xlib_surface_show_glyphs8 (cairo_scaled_font_t *scaled_font,
int thisX, thisY;
int lastX = 0, lastY = 0;
cairo_bool_t have_a1, have_a8, have_argb32;
XRenderPictFormat *mask_format;
if (num_glyphs == 0)
return CAIRO_STATUS_SUCCESS;
/* Acquire arrays of suitable sizes. */
if (num_glyphs < N_STACK_BUF) {
elts = stack_elts;
@ -2059,11 +2225,26 @@ _cairo_xlib_surface_show_glyphs8 (cairo_scaled_font_t *scaled_font,
}
have_a1 = FALSE;
have_a8 = FALSE;
have_argb32 = FALSE;
for (i = 0; i < num_glyphs; ++i) {
GlyphSet glyphset;
glyphset = entries[i]->glyphset;
if (glyphset == cache->a1_glyphset)
have_a1 = TRUE;
else if (glyphset == cache->a8_glyphset)
have_a8 = TRUE;
else if (glyphset == cache->argb32_glyphset)
have_argb32 = TRUE;
chars[i] = entries[i]->glyph;
elts[i].chars = &(chars[i]);
elts[i].nchars = 1;
elts[i].glyphset = cache->glyphset;
elts[i].glyphset = glyphset;
thisX = (int) floor (glyphs[i].x + 0.5);
thisY = (int) floor (glyphs[i].y + 0.5);
elts[i].xOff = thisX - lastX;
@ -2072,11 +2253,14 @@ _cairo_xlib_surface_show_glyphs8 (cairo_scaled_font_t *scaled_font,
lastY = thisY;
}
mask_format = _select_text_mask_format (cache,
have_a1, have_a8, have_argb32);
XRenderCompositeText8 (self->dpy,
_render_operator (operator),
src->src_picture,
self->dst_picture,
cache->a8_pict_format,
mask_format,
source_x, source_y,
0, 0,
elts, num_glyphs);

View file

@ -55,10 +55,6 @@
#include <string.h>
#include <stdarg.h>
#if HAVE_PTHREAD_H
#include <pthread.h>
#endif
#ifdef _MSC_VER
#define _USE_MATH_DEFINES
#endif