if (boxes->num_boxes == 1) { int x1 = _cairo_fixed_integer_part (boxes->chunks.base[0].p1.x); int y1 = _cairo_fixed_integer_part (boxes->chunks.base[0].p1.y); int x2 = _cairo_fixed_integer_part (boxes->chunks.base[0].p2.x); int y2 = _cairo_fixed_integer_part (boxes->chunks.base[0].p2.y);
XCopyArea (dst->dpy, d, dst->drawable, gc,
x1 + dx, y1 + dy,
x2 - x1, y2 - y1,
x1, y1);
} else { /* We can only have a single control for subwindow_mode on the *GC.IfwehaveaWindowdestination,weneedtosetClipByChildren, *butifwehaveaWindowsource,weneedIncludeInferiors.Ifwehave *bothaWindowdestinationandsource,wemustfallback.Thereis *noconvenientwaytodetectifadrawableisaPixmaporWindow, *thereforewecanonlyrelyonthosesurfacesthatwecreated *ourselvestobePixmaps,andtreateverythingelseasapotential *Window.
*/ if (src == dst || (!src->owns_pixmap && !dst->owns_pixmap)) { 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);
XCopyArea (dst->dpy, d, dst->drawable, gc,
x1 + dx, y1 + dy,
x2 - x1, y2 - y1,
x1, y1);
}
}
} else {
XRectangle stack_rects[CAIRO_STACK_ARRAY_LENGTH (XRectangle)];
XRectangle *rects = stack_rects;
case CAIRO_OPERATOR_SOURCE: return PictOpSrc; case CAIRO_OPERATOR_OVER: return PictOpOver; case CAIRO_OPERATOR_IN: return PictOpIn; case CAIRO_OPERATOR_OUT: return PictOpOut; case CAIRO_OPERATOR_ATOP: return PictOpAtop;
case CAIRO_OPERATOR_DEST: return PictOpDst; case CAIRO_OPERATOR_DEST_OVER: return PictOpOverReverse; case CAIRO_OPERATOR_DEST_IN: return PictOpInReverse; case CAIRO_OPERATOR_DEST_OUT: return PictOpOutReverse; case CAIRO_OPERATOR_DEST_ATOP: return PictOpAtopReverse;
case CAIRO_OPERATOR_XOR: return PictOpXor; case CAIRO_OPERATOR_ADD: return PictOpAdd; case CAIRO_OPERATOR_SATURATE: return PictOpSaturate;
case CAIRO_OPERATOR_MULTIPLY: return PictOpMultiply; case CAIRO_OPERATOR_SCREEN: return PictOpScreen; case CAIRO_OPERATOR_OVERLAY: return PictOpOverlay; case CAIRO_OPERATOR_DARKEN: return PictOpDarken; case CAIRO_OPERATOR_LIGHTEN: return PictOpLighten; case CAIRO_OPERATOR_COLOR_DODGE: return PictOpColorDodge; case CAIRO_OPERATOR_COLOR_BURN: return PictOpColorBurn; case CAIRO_OPERATOR_HARD_LIGHT: return PictOpHardLight; case CAIRO_OPERATOR_SOFT_LIGHT: return PictOpSoftLight; case CAIRO_OPERATOR_DIFFERENCE: return PictOpDifference; case CAIRO_OPERATOR_EXCLUSION: return PictOpExclusion; case CAIRO_OPERATOR_HSL_HUE: return PictOpHSLHue; case CAIRO_OPERATOR_HSL_SATURATION: return PictOpHSLSaturation; case CAIRO_OPERATOR_HSL_COLOR: return PictOpHSLColor; case CAIRO_OPERATOR_HSL_LUMINOSITY: return PictOpHSLLuminosity;
if (surface != NULL) {
i = _cairo_xlib_get_glyphset_index_for_format (surface->format); if (has_pending_free_glyph (&priv->glyphset[i], glyph_index)) return &priv->glyphset[i];
} else { for (i = 0; i < NUM_GLYPHSETS; i++) { if (has_pending_free_glyph (&priv->glyphset[i], glyph_index)) return &priv->glyphset[i];
}
}
/* check to see if we have a pending XRenderFreeGlyph for this glyph */
info = find_pending_free_glyph (display, font, glyph_index, glyph_surface); if (info != NULL) return _cairo_xlib_glyph_attach (display, glyph, info);
if (glyph_surface == NULL) {
status = _cairo_scaled_glyph_lookup (font,
glyph_index,
CAIRO_SCALED_GLYPH_INFO_METRICS |
CAIRO_SCALED_GLYPH_INFO_SURFACE,
NULL, /* foreground color */
pscaled_glyph); if (unlikely (status)) return status;
info = _cairo_xlib_font_get_glyphset_info_for_format (display, font,
glyph_surface->format);
#if0 /* If the glyph surface has zero height or width, we create *aclear1x1surface,toavoidvariousXserverbugs.
*/ if (glyph_surface->width == 0 || glyph_surface->height == 0) {
cairo_surface_t *tmp_surface;
tmp_surface = cairo_image_surface_create (info->format, 1, 1);
status = tmp_surface->status; if (unlikely (status)) goto BAIL;
/* If the glyph format does not match the font format, then we *createatemporarysurfacefortheglyphimagewiththefont's *format.
*/ if (glyph_surface->format != info->format) {
cairo_surface_pattern_t pattern;
cairo_surface_t *tmp_surface;
tmp_surface = cairo_image_surface_create (info->format,
glyph_surface->width,
glyph_surface->height);
status = tmp_surface->status; if (unlikely (status)) goto BAIL;
/* flip formats around */ switch (_cairo_xlib_get_glyphset_index_for_format (glyph->surface->format)) { case GLYPHSET_INDEX_A1: /* local bitmaps are always stored with bit == byte */ if (_cairo_is_little_endian() != (BitmapBitOrder (display->display) == LSBFirst)) { int c = glyph_surface->stride * glyph_surface->height; unsignedchar *d; unsignedchar *new, *n;
if (c == 0) break;
new = _cairo_malloc (c); if (!new) {
status = _cairo_error (CAIRO_STATUS_NO_MEMORY); goto BAIL;
}
n = new;
d = data; do { 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;
} while (--c);
data = new;
} break; case GLYPHSET_INDEX_A8: break; case GLYPHSET_INDEX_ARGB32: if (_cairo_is_little_endian() != (ImageByteOrder (display->display) == LSBFirst)) { unsignedint c = glyph_surface->stride * glyph_surface->height / 4; const uint32_t *d;
uint32_t *new, *n;
if (c == 0) break;
new = _cairo_malloc (4 * c); if (unlikely (new == NULL)) {
status = _cairo_error (CAIRO_STATUS_NO_MEMORY); goto BAIL;
}
n = new;
d = (uint32_t *) data; do {
*n++ = bswap_32 (*d);
d++;
} while (--c);
data = (uint8_t *) new;
} break; default:
ASSERT_NOT_REACHED; break;
} /* XXX assume X server wants pixman padding. Xft assumes this as well */
status = _cairo_xlib_glyph_attach (display, glyph, info);
BAIL: if (glyph_surface != glyph->surface)
cairo_surface_destroy (&glyph_surface->base);
/* if the scaled glyph didn't already have a surface attached *toit,releasethecreatedsurfacenowthatwehaveit *uploadedtotheXserver.Ifthesurfacehasalreadybeen *there(eg.becauseimagebackendrequestedit),leaveitin *thecache
*/ if (!already_had_glyph_surface)
_cairo_scaled_glyph_set_surface (glyph, font, NULL);
return status;
}
typedefvoid (*cairo_xrender_composite_text_func_t)
(Display *dpy, int op,
Picture src,
Picture dst,
_Xconst XRenderPictFormat *maskFormat, int xSrc, int ySrc, int xDst, int yDst,
_Xconst XGlyphElt8 *elts, int nelt);
/* Build a struct of the same size of #cairo_glyph_t that can be used both as *aninputglyphwithdoublecoordinates,andas"working"glyphwith
* integer from-current-point offsets. */ typedefunion {
cairo_glyph_t d; unsignedlong index; struct { unsignedlong index; int x; int y;
} i;
} cairo_xlib_glyph_t;
/* compile-time assert that #cairo_xlib_glyph_t is the same size as #cairo_glyph_t */
COMPILE_TIME_ASSERT (sizeof (cairo_xlib_glyph_t) == sizeof (cairo_glyph_t));
/* Start a new element for the first glyph, *orforanyglyphthathasunexpectedposition, *orifcurrentelementhastoomanyglyphs *(Xrenderlimitseachelementto252glyphs,welimitthemto128) * *Thesesameconditionsneedtobemirroredbetween *_cairo_xlib_surface_emit_glyphsand_emit_glyph_chunks
*/ #define _start_new_glyph_elt(count, glyph) \
(((count) & 127) == 0 || (glyph)->i.x || (glyph)->i.y)
static cairo_status_t
_emit_glyphs_chunk (cairo_xlib_display_t *display,
cairo_xlib_surface_t *dst, int dst_x, int dst_y,
cairo_xlib_glyph_t *glyphs, int num_glyphs,
cairo_scaled_font_t *font,
cairo_bool_t use_mask,
cairo_operator_t op,
cairo_xlib_source_t *src, int src_x, int src_y, /* info for this chunk */ int num_elts, int width,
cairo_xlib_font_glyphset_t *info)
{ /* Which XRenderCompositeText function to use */
cairo_xrender_composite_text_func_t composite_text_func; int size;
/* Element buffer stuff */
XGlyphElt8 *elts;
XGlyphElt8 stack_elts[CAIRO_STACK_ARRAY_LENGTH (XGlyphElt8)];
/* Fill them in */
nelt = 0;
n = 0;
j = 0; for (i = 0; i < num_glyphs; i++) { /* Start a new element for first output glyph, *orforanyglyphthathasunexpectedposition, *orifcurrentelementhastoomanyglyphs. * *Thesesameconditionsaremirroredin_cairo_xlib_surface_emit_glyphs()
*/ if (_start_new_glyph_elt (j, &glyphs[i])) { if (j) {
elts[nelt].nchars = n;
nelt++;
n = 0;
}
elts[nelt].chars = char8 + size * j;
elts[nelt].glyphset = info->glyphset;
elts[nelt].xOff = glyphs[i].i.x;
elts[nelt].yOff = glyphs[i].i.y;
}
if (! CAIRO_RENDER_SUPPORTS_OPERATOR (display, extents->op)) return CAIRO_INT_STATUS_UNSUPPORTED;
/* The glyph coordinates must be representable in an int16_t. *Whenpossible,theywillbeexpressedasanoffsetfromthe *previousglyph,otherwisetheywillbeanoffsetfromthe *surfaceorigin.Ifwecan'tguaranteethistobepossible, *fallback.
*/ if (extents->bounded.x + extents->bounded.width > INT16_MAX ||
extents->bounded.y + extents->bounded.height> INT16_MAX ||
extents->bounded.x < INT16_MIN ||
extents->bounded.y < INT16_MIN)
{ return CAIRO_INT_STATUS_UNSUPPORTED;
}
/* Approximate the size of the largest glyph and fallback if we can not *uploadittothexserver.
*/
size = ceil (font->max_scale);
size = 4 * size * size;
max_request_size = (XExtendedMaxRequestSize (display->display) ? XExtendedMaxRequestSize (display->display)
: XMaxRequestSize (display->display)) * 4 -
sz_xRenderAddGlyphsReq -
sz_xGlyphInfo - 8; if (size >= max_request_size) return CAIRO_INT_STATUS_UNSUPPORTED;
return CAIRO_STATUS_SUCCESS;
}
/* sz_xGlyphtElt required alignment to a 32-bit boundary, so ensure we have
* enough room for padding */ #define _cairo_sz_xGlyphElt (sz_xGlyphElt + 4)
static cairo_int_status_t
composite_glyphs (void *surface,
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_xlib_surface_t *dst = surface;
cairo_xlib_glyph_t *glyphs = (cairo_xlib_glyph_t *)info->glyphs;
cairo_xlib_source_t *src = (cairo_xlib_source_t *)_src;
cairo_xlib_display_t *display = dst->display;
cairo_int_status_t status = CAIRO_INT_STATUS_SUCCESS;
cairo_scaled_glyph_t *glyph;
cairo_fixed_t x = dst_x, y = dst_y;
cairo_xlib_font_glyphset_t *glyphset = NULL, *this_glyphset_info;
unsignedlong max_index = 0; int width = 1; int num_elts = 0; int num_out_glyphs = 0; int num_glyphs = info->num_glyphs;
int max_request_size = XMaxRequestSize (display->display) * 4
- MAX (sz_xRenderCompositeGlyphs8Req,
MAX(sz_xRenderCompositeGlyphs16Req,
sz_xRenderCompositeGlyphs32Req)); int request_size = 0; int i;
op = _render_operator (op),
_cairo_xlib_surface_ensure_picture (dst); for (i = 0; i < num_glyphs; i++) { unsignedlong xphase, yphase; int this_x, this_y; int old_width;
status = _cairo_scaled_glyph_lookup (info->font,
glyphs[i].index,
CAIRO_SCALED_GLYPH_INFO_METRICS,
NULL, /* foreground color */
&glyph); if (unlikely (status)) return status;
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) {
status = _cairo_xlib_surface_add_glyph (display, info->font, &glyph); if (unlikely (status)) return status;
}
this_glyphset_info = glyph->dev_private; if (!glyphset)
glyphset = this_glyphset_info;
/* The invariant here is that we can always flush the glyphs *accumulatedbeforethisone,usingold_width,andthey *wouldfitintherequest.
*/
old_width = width;
/* Update max glyph index */ if (glyphs[i].index > max_index) {
max_index = glyphs[i].index; if (max_index >= 65536)
width = 4; elseif (max_index >= 256)
width = 2; if (width != old_width)
request_size += (width - old_width) * num_out_glyphs;
}
/* If we will pass the max request size by adding this glyph, *flushcurrentglyphs.Notethatweaccountfora *possibleelementbeingaddedbelow. * *Alsoflushifchangingglyphsets,asXrenderlimitsonemask *formatperrequest,sowecaneitherbreakup,orusea *wide-enoughmaskformat.Wedotheformer.Onereasonto *preferthelatteristhefactthatXserverADDsallglyphs *tothemaskfirst,andthencomposesthattofinalsurface, *thoughit'snotabigdeal. * *Iftheglyphhasacoordinatewhichcannotberepresented *asa16-bitoffsetfromthepreviousglyph,flushthe *currentchunk.Thecurrentglyphwillbethefirstonein *thenextchunk,thusitscoordinateswillbeanoffsetfrom *thedestinationorigin.Thisoffsetisguaranteedtobe *representableas16-bitoffset(otherwisewewouldhave *fallenback).
*/ if (request_size + width > max_request_size - _cairo_sz_xGlyphElt ||
this_x - x > INT16_MAX || this_x - x < INT16_MIN ||
this_y - y > INT16_MAX || this_y - y < INT16_MIN ||
(this_glyphset_info != glyphset)) {
status = _emit_glyphs_chunk (display, dst, dst_x, dst_y,
glyphs, i, info->font, info->use_mask,
op, src, src_x, src_y,
num_elts, old_width, glyphset); if (unlikely (status)) return status;
/* Convert absolute glyph position to relative-to-current-point
* position */
glyphs[i].i.x = this_x - x;
glyphs[i].i.y = this_y - y;
/* Start a new element for the first glyph, *orforanyglyphthathasunexpectedposition, *orifcurrentelementhastoomanyglyphs. * *Thesesameconditionsaremirroredin_emit_glyphs_chunk().
*/ if (_start_new_glyph_elt (num_out_glyphs, &glyphs[i])) {
num_elts++;
request_size += _cairo_sz_xGlyphElt;
}
/* adjust current-position */
x = this_x + glyph->x_advance;
y = this_y + glyph->y_advance;
num_out_glyphs++;
request_size += width;
}
if (num_elts) {
status = _emit_glyphs_chunk (display, dst, dst_x, dst_y,
glyphs, i, info->font, info->use_mask,
op, src, src_x, src_y,
num_elts, width, glyphset);
}
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.