📄 cairo-xlib-surface.c
字号:
if (mask) _cairo_pattern_release_surface (mask_pattern, &mask->base, &mask_attr); _cairo_pattern_release_surface (src_pattern, &src->base, &src_attr); return status;}static cairo_int_status_t_cairo_xlib_surface_fill_rectangles (void *abstract_surface, cairo_operator_t op, const cairo_color_t *color, cairo_rectangle_int16_t *rects, int num_rects){ cairo_xlib_surface_t *surface = abstract_surface; XRenderColor render_color; if (!CAIRO_SURFACE_RENDER_HAS_FILL_RECTANGLE (surface)) return CAIRO_INT_STATUS_UNSUPPORTED; render_color.red = color->red_short; render_color.green = color->green_short; render_color.blue = color->blue_short; render_color.alpha = color->alpha_short; /* XXX: This XRectangle cast is evil... it needs to go away somehow. */ _cairo_xlib_surface_ensure_dst_picture (surface); XRenderFillRectangles (surface->dpy, _render_operator (op), surface->dst_picture, &render_color, (XRectangle *) rects, num_rects); return CAIRO_STATUS_SUCCESS;}/* Creates an A8 picture of size @width x @height, initialized with @color */static Picture_create_a8_picture (cairo_xlib_surface_t *surface, XRenderColor *color, int width, int height, cairo_bool_t repeat){ XRenderPictureAttributes pa; unsigned long mask = 0; Pixmap pixmap = XCreatePixmap (surface->dpy, surface->drawable, width <= 0 ? 1 : width, height <= 0 ? 1 : height, 8); Picture picture; if (repeat) { pa.repeat = TRUE; mask = CPRepeat; } picture = XRenderCreatePicture (surface->dpy, pixmap, XRenderFindStandardFormat (surface->dpy, PictStandardA8), mask, &pa); XRenderFillRectangle (surface->dpy, PictOpSrc, picture, color, 0, 0, width, height); XFreePixmap (surface->dpy, pixmap); return picture;}/* Creates a temporary mask for the trapezoids covering the area * [@dst_x, @dst_y, @width, @height] of the destination surface. */static Picture_create_trapezoid_mask (cairo_xlib_surface_t *dst, cairo_trapezoid_t *traps, int num_traps, int dst_x, int dst_y, int width, int height, XRenderPictFormat *pict_format){ XRenderColor transparent = { 0, 0, 0, 0 }; XRenderColor solid = { 0xffff, 0xffff, 0xffff, 0xffff }; Picture mask_picture, solid_picture; XTrapezoid *offset_traps; int i; /* This would be considerably simpler using XRenderAddTraps(), but since * we are only using this in the unbounded-operator case, we stick with * XRenderCompositeTrapezoids, which is available on older versions * of RENDER rather than conditionalizing. We should still hit an * optimization that avoids creating another intermediate surface on * the servers that have XRenderAddTraps(). */ mask_picture = _create_a8_picture (dst, &transparent, width, height, FALSE); solid_picture = _create_a8_picture (dst, &solid, width, height, TRUE); offset_traps = malloc (sizeof (XTrapezoid) * num_traps); if (!offset_traps) return None; for (i = 0; i < num_traps; i++) { offset_traps[i].top = traps[i].top - 0x10000 * dst_y; offset_traps[i].bottom = traps[i].bottom - 0x10000 * dst_y; offset_traps[i].left.p1.x = traps[i].left.p1.x - 0x10000 * dst_x; offset_traps[i].left.p1.y = traps[i].left.p1.y - 0x10000 * dst_y; offset_traps[i].left.p2.x = traps[i].left.p2.x - 0x10000 * dst_x; offset_traps[i].left.p2.y = traps[i].left.p2.y - 0x10000 * dst_y; offset_traps[i].right.p1.x = traps[i].right.p1.x - 0x10000 * dst_x; offset_traps[i].right.p1.y = traps[i].right.p1.y - 0x10000 * dst_y; offset_traps[i].right.p2.x = traps[i].right.p2.x - 0x10000 * dst_x; offset_traps[i].right.p2.y = traps[i].right.p2.y - 0x10000 * dst_y; } XRenderCompositeTrapezoids (dst->dpy, PictOpAdd, solid_picture, mask_picture, pict_format, 0, 0, offset_traps, num_traps); XRenderFreePicture (dst->dpy, solid_picture); free (offset_traps); return mask_picture;}static cairo_int_status_t_cairo_xlib_surface_composite_trapezoids (cairo_operator_t op, cairo_pattern_t *pattern, void *abstract_dst, cairo_antialias_t antialias, int src_x, int src_y, int dst_x, int dst_y, unsigned int width, unsigned int height, cairo_trapezoid_t *traps, int num_traps){ cairo_surface_attributes_t attributes; cairo_xlib_surface_t *dst = abstract_dst; cairo_xlib_surface_t *src; cairo_int_status_t status; composite_operation_t operation; int render_reference_x, render_reference_y; int render_src_x, render_src_y; XRenderPictFormat *pict_format; if (!CAIRO_SURFACE_RENDER_HAS_TRAPEZOIDS (dst)) return CAIRO_INT_STATUS_UNSUPPORTED; operation = _categorize_composite_operation (dst, op, pattern, TRUE); if (operation == DO_UNSUPPORTED) return CAIRO_INT_STATUS_UNSUPPORTED; status = _cairo_pattern_acquire_surface (pattern, &dst->base, src_x, src_y, width, height, (cairo_surface_t **) &src, &attributes); if (status) return status; operation = _recategorize_composite_operation (dst, op, src, &attributes, TRUE); if (operation == DO_UNSUPPORTED) { status = CAIRO_INT_STATUS_UNSUPPORTED; goto BAIL; } switch (antialias) { case CAIRO_ANTIALIAS_NONE: pict_format = XRenderFindStandardFormat (dst->dpy, PictStandardA1); break; default: pict_format = XRenderFindStandardFormat (dst->dpy, PictStandardA8); break; } if (traps[0].left.p1.y < traps[0].left.p2.y) { render_reference_x = _cairo_fixed_integer_floor (traps[0].left.p1.x); render_reference_y = _cairo_fixed_integer_floor (traps[0].left.p1.y); } else { render_reference_x = _cairo_fixed_integer_floor (traps[0].left.p2.x); render_reference_y = _cairo_fixed_integer_floor (traps[0].left.p2.y); } render_src_x = src_x + render_reference_x - dst_x; render_src_y = src_y + render_reference_y - dst_y; _cairo_xlib_surface_ensure_dst_picture (dst); status = _cairo_xlib_surface_set_attributes (src, &attributes); if (status) goto BAIL; if (!_cairo_operator_bounded_by_mask (op)) { /* XRenderCompositeTrapezoids() creates a mask only large enough for the * trapezoids themselves, but if the operator is unbounded, then we need * to actually composite all the way out to the bounds, so we create * the mask and composite ourselves. There actually would * be benefit to doing this in all cases, since RENDER implementations * will frequently create a too temporary big mask, ignoring destination * bounds and clip. (XRenderAddTraps() could be used to make creating * the mask somewhat cheaper.) */ Picture mask_picture = _create_trapezoid_mask (dst, traps, num_traps, dst_x, dst_y, width, height, pict_format); if (!mask_picture) { status = CAIRO_STATUS_NO_MEMORY; goto BAIL; } XRenderComposite (dst->dpy, _render_operator (op), src->src_picture, mask_picture, dst->dst_picture, src_x + attributes.x_offset, src_y + attributes.y_offset, 0, 0, dst_x, dst_y, width, height); XRenderFreePicture (dst->dpy, mask_picture); status = _cairo_surface_composite_shape_fixup_unbounded (&dst->base, &attributes, src->width, src->height, width, height, src_x, src_y, 0, 0, dst_x, dst_y, width, height); } else { /* XXX: The XTrapezoid cast is evil and needs to go away somehow. */ XRenderCompositeTrapezoids (dst->dpy, _render_operator (op), src->src_picture, dst->dst_picture, pict_format, render_src_x + attributes.x_offset, render_src_y + attributes.y_offset, (XTrapezoid *) traps, num_traps); } BAIL: _cairo_pattern_release_surface (pattern, &src->base, &attributes); return status;}static cairo_int_status_t_cairo_xlib_surface_set_clip_region (void *abstract_surface, pixman_region16_t *region){ cairo_xlib_surface_t *surface = (cairo_xlib_surface_t *) abstract_surface; if (surface->clip_rects) { free (surface->clip_rects); surface->clip_rects = NULL; } surface->have_clip_rects = FALSE; surface->num_clip_rects = 0; if (region == NULL) { if (surface->gc) XSetClipMask (surface->dpy, surface->gc, None); if (surface->xrender_format && surface->dst_picture) { XRenderPictureAttributes pa; pa.clip_mask = None; XRenderChangePicture (surface->dpy, surface->dst_picture, CPClipMask, &pa); } } else { pixman_box16_t *boxes; XRectangle *rects = NULL; int n_boxes, i; n_boxes = pixman_region_num_rects (region); if (n_boxes > 0) { rects = malloc (sizeof(XRectangle) * n_boxes); if (rects == NULL) return CAIRO_STATUS_NO_MEMORY; } else { rects = NULL; } boxes = pixman_region_rects (region); for (i = 0; i < n_boxes; i++) { rects[i].x = boxes[i].x1; rects[i].y = boxes[i].y1; rects[i].width = boxes[i].x2 - boxes[i].x1; rects[i].height = boxes[i].y2 - boxes[i].y1; } surface->have_clip_rects = TRUE; surface->clip_rects = rects; surface->num_clip_rects = n_boxes; if (surface->gc) _cairo_xlib_surface_set_gc_clip_rects (surface); if (surface->dst_picture) _cairo_xlib_surface_set_picture_clip_rects (surface); } return CAIRO_STATUS_SUCCESS;}static cairo_int_status_t_cairo_xlib_surface_get_extents (void *abstract_surface, cairo_rectangle_int16_t *rectangle){ cairo_xlib_surface_t *surface = abstract_surface; rectangle->x = 0; rectangle->y = 0; rectangle->width = surface->width; rectangle->height = surface->height; return CAIRO_STATUS_SUCCESS;}static void_cairo_xlib_surface_get_font_options (void *abstract_surface, cairo_font_options_t *options){ cairo_xlib_surface_t *surface = abstract_surface; *options = surface->screen_info->font_options;}static cairo_status_t_cairo_xlib_surface_flush (void *abstract_surface){ cairo_xlib_surface_t *surface = abstract_surface; XSync (surface->dpy, False); return CAIRO_STATUS_SUCCESS;}static void_cairo_xlib_surface_scaled_font_fini (cairo_scaled_font_t *scaled_font);static void_cairo_xlib_surface_scaled_glyph_fini (cairo_scaled_glyph_t *scaled_glyph, cairo_scaled_font_t *scaled_font);static const cairo_surface_backend_t cairo_xlib_surface_backend = { CAIRO_SURFACE_TYPE_XLIB, _cairo_xlib_surface_create_similar, _cairo_xlib_surface_finish, _cairo_xlib_surface_acquire_source_image, _cairo_xlib_surface_release_source_image, _cairo_xlib_surface_acquire_dest_image, _cairo_xlib_surface_release_dest_image, _cairo_xlib_surface_clone_similar, _cairo_xlib_surface_composite, _cairo_xlib_surface_fill_rectangles, _cairo_xlib_surface_composite_trapezoids, NULL, /* copy_page */ NULL, /* show_page */ _cairo_xlib_surface_set_clip_region, NULL, /* intersect_clip_path */ _cairo_xlib_surface_get_extents, NULL, /* old_show_glyphs */ _cairo_xlib_surface_get_font_options, _cairo_xlib_surface_flush, NULL, /* mark_dirty_rectangle */ _cairo_xlib_surface_scaled_font_fini, _cairo_xlib_surface_scaled_glyph_fini, NULL, /* paint */ NULL, /* mask */ NULL, /* stroke */ NULL, /* fill */ _cairo_xlib_surface_show_glyphs, NULL /* snapshot */};/** * _cairo_surface_is_xlib: * @surface: a #cairo_surface_t * * Checks if a surface is a #cairo_xlib_surface_t * * Return value: True if the surface is an xlib surface **/static cairo_bool_t_cairo_surface_is_xlib (cairo_surface_t *surface){ return surface->backend == &cairo_xlib_surface_backend;}static cairo_surface_t *_cairo_xlib_surface_create_internal (Display *dpy, Drawable drawable, Screen *screen, Visual *visual, XRenderPictFormat *xrender_format, int width, int height, int depth){ cairo_xlib_surface_t *surface; cairo_xlib_screen_info_t *screen_info; screen_info = _cairo_xlib_screen_info_get (dpy, screen); if (screen_info == NULL) { _cairo_error (CAIRO_STATUS_NO_MEMORY); return (cairo_surface_t*) &_cairo_surface_nil; } surface = malloc (sizeof (cairo_xlib_surface_t)); if (surface == NULL) { _cairo_error (CAIRO_STATUS_NO_MEMORY); return (cairo_surface_t*) &_cairo_surface_nil; } if (xrender_format) { depth = xrender_format->depth; } else if (visual) { int j, k; /* This is ugly, but we have to walk over all visuals * for the display to find the depth. */ for (j = 0; j < screen->ndepths; j++) { Depth *d = &screen->depths[j]; for (k = 0; k < d->nvisuals; k++) { if (&d->visuals[k] == visual) { depth = d->depth; goto found; } } } found: ; } if (cairo_xlib_render_disabled || ! XRenderQueryVersion (dpy, &surface->render_major, &surface->render_minor)) { surface->render_major = -1; surface->render_minor = -1; } if (CAIRO_SURFACE_RENDER_HAS_CREATE_PICTURE (surface)) { if (!xrender_format) { if (visual) xrender_format = XRenderFindVisualFormat (dpy, visual); else if (depth == 1) xrender_format = XRenderFindStandardFormat (dpy, PictStandardA1); } } else { xrender_format = NULL; } _cairo_surface_init (&surface->base, &cairo_xlib_surface_backend, _xrender_format_to_content (xrender_format)); surface->dpy = dpy;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -