📄 cairo-xlib-surface.c
字号:
XRenderSetPictureTransform (surface->dpy, surface->src_picture, &xtransform); return CAIRO_STATUS_SUCCESS;}static cairo_status_t_cairo_xlib_surface_set_filter (cairo_xlib_surface_t *surface, cairo_filter_t filter){ char *render_filter; if (!surface->src_picture) return CAIRO_STATUS_SUCCESS; if (!CAIRO_SURFACE_RENDER_HAS_FILTERS (surface)) { if (filter == CAIRO_FILTER_FAST || filter == CAIRO_FILTER_NEAREST) return CAIRO_STATUS_SUCCESS; return CAIRO_INT_STATUS_UNSUPPORTED; } switch (filter) { case CAIRO_FILTER_FAST: render_filter = FilterFast; break; case CAIRO_FILTER_GOOD: render_filter = FilterGood; break; case CAIRO_FILTER_BEST: render_filter = FilterBest; break; case CAIRO_FILTER_NEAREST: render_filter = FilterNearest; break; case CAIRO_FILTER_BILINEAR: render_filter = FilterBilinear; break; default: render_filter = FilterBest; break; } XRenderSetPictureFilter (surface->dpy, surface->src_picture, render_filter, NULL, 0); return CAIRO_STATUS_SUCCESS;}static cairo_status_t_cairo_xlib_surface_set_repeat (cairo_xlib_surface_t *surface, int repeat){ XRenderPictureAttributes pa; unsigned long mask; if (!surface->src_picture) return CAIRO_STATUS_SUCCESS; mask = CPRepeat; pa.repeat = repeat; XRenderChangePicture (surface->dpy, surface->src_picture, mask, &pa); return CAIRO_STATUS_SUCCESS;}static cairo_int_status_t_cairo_xlib_surface_set_attributes (cairo_xlib_surface_t *surface, cairo_surface_attributes_t *attributes){ cairo_int_status_t status; _cairo_xlib_surface_ensure_src_picture (surface); status = _cairo_xlib_surface_set_matrix (surface, &attributes->matrix); if (status) return status; switch (attributes->extend) { case CAIRO_EXTEND_NONE: _cairo_xlib_surface_set_repeat (surface, 0); break; case CAIRO_EXTEND_REPEAT: _cairo_xlib_surface_set_repeat (surface, 1); break; case CAIRO_EXTEND_REFLECT: case CAIRO_EXTEND_PAD: return CAIRO_INT_STATUS_UNSUPPORTED; } status = _cairo_xlib_surface_set_filter (surface, attributes->filter); if (status) return status; return CAIRO_STATUS_SUCCESS;}/* Checks whether we can can directly draw from src to dst with * the core protocol: either with CopyArea or using src as a * a tile in a GC. */static cairo_bool_t_surfaces_compatible (cairo_xlib_surface_t *dst, cairo_xlib_surface_t *src){ /* same screen */ if (!_cairo_xlib_surface_same_screen (dst, src)) return FALSE; /* same depth (for core) */ if (src->depth != dst->depth) return FALSE; /* if Render is supported, match picture formats */ if (src->xrender_format != NULL && src->xrender_format == dst->xrender_format) return TRUE; /* Without Render, match visuals instead */ if (src->visual == dst->visual) return TRUE; return FALSE;}static cairo_bool_t_surface_has_alpha (cairo_xlib_surface_t *surface){ if (surface->xrender_format) { if (surface->xrender_format->type == PictTypeDirect && surface->xrender_format->direct.alphaMask != 0) return TRUE; else return FALSE; } else { /* In the no-render case, we never have alpha */ return FALSE; }}/* Returns true if the given operator and source-alpha combination * requires alpha compositing to complete. */static cairo_bool_t_operator_needs_alpha_composite (cairo_operator_t op, cairo_bool_t surface_has_alpha){ if (op == CAIRO_OPERATOR_SOURCE || (!surface_has_alpha && (op == CAIRO_OPERATOR_OVER || op == CAIRO_OPERATOR_ATOP || op == CAIRO_OPERATOR_IN))) return FALSE; return TRUE;}/* There is a bug in most older X servers with compositing using a * untransformed repeating source pattern when the source is in off-screen * video memory, and another with repeated transformed images using a * general tranform matrix. When these bugs could be triggered, we need a * fallback: in the common case where we have no transformation and the * source and destination have the same format/visual, we can do the * operation using the core protocol for the first bug, otherwise, we need * a software fallback. * * We can also often optimize a compositing operation by calling XCopyArea * for some common cases where there is no alpha compositing to be done. * We figure that out here as well. */typedef enum { DO_RENDER, /* use render */ DO_XCOPYAREA, /* core protocol XCopyArea optimization/fallback */ DO_XTILE, /* core protocol XSetTile optimization/fallback */ DO_UNSUPPORTED /* software fallback */} composite_operation_t;/* Initial check for the render bugs; we need to recheck for the * offscreen-memory bug after we turn patterns into surfaces, since that * may introduce a repeating pattern for gradient patterns. We don't need * to check for the repeat+transform bug because gradient surfaces aren't * transformed. * * All we do here is reject cases where we *know* are going to * hit the bug and won't be able to use a core protocol fallback. */static composite_operation_t_categorize_composite_operation (cairo_xlib_surface_t *dst, cairo_operator_t op, cairo_pattern_t *src_pattern, cairo_bool_t have_mask){ if (!dst->buggy_repeat) return DO_RENDER; if (src_pattern->type == CAIRO_PATTERN_TYPE_SURFACE) { cairo_surface_pattern_t *surface_pattern = (cairo_surface_pattern_t *)src_pattern; if (_cairo_matrix_is_integer_translation (&src_pattern->matrix, NULL, NULL) && src_pattern->extend == CAIRO_EXTEND_REPEAT) { /* This is the case where we have the bug involving * untransformed repeating source patterns with off-screen * video memory; reject some cases where a core protocol * fallback is impossible. */ if (have_mask || !(op == CAIRO_OPERATOR_SOURCE || op == CAIRO_OPERATOR_OVER)) return DO_UNSUPPORTED; if (_cairo_surface_is_xlib (surface_pattern->surface)) { cairo_xlib_surface_t *src = (cairo_xlib_surface_t *)surface_pattern->surface; if (op == CAIRO_OPERATOR_OVER && _surface_has_alpha (src)) return DO_UNSUPPORTED; /* If these are on the same screen but otherwise incompatible, * make a copy as core drawing can't cross depths and doesn't * work rightacross visuals of the same depth */ if (_cairo_xlib_surface_same_screen (dst, src) && !_surfaces_compatible (dst, src)) return DO_UNSUPPORTED; } } /* Check for the other bug involving repeat patterns with general * transforms. */ if (!_cairo_matrix_is_integer_translation (&src_pattern->matrix, NULL, NULL) && src_pattern->extend == CAIRO_EXTEND_REPEAT) return DO_UNSUPPORTED; } return DO_RENDER;}/* Recheck for composite-repeat once we've turned patterns into Xlib surfaces * If we end up returning DO_UNSUPPORTED here, we're throwing away work we * did to turn gradients into a pattern, but most of the time we can handle * that case with core protocol fallback. * * Also check here if we can just use XCopyArea, instead of going through * Render. */static composite_operation_t_recategorize_composite_operation (cairo_xlib_surface_t *dst, cairo_operator_t op, cairo_xlib_surface_t *src, cairo_surface_attributes_t *src_attr, cairo_bool_t have_mask){ cairo_bool_t is_integer_translation = _cairo_matrix_is_integer_translation (&src_attr->matrix, NULL, NULL); cairo_bool_t needs_alpha_composite = _operator_needs_alpha_composite (op, _surface_has_alpha (src)); if (!have_mask && is_integer_translation && src_attr->extend == CAIRO_EXTEND_NONE && !needs_alpha_composite && _surfaces_compatible(src, dst)) { return DO_XCOPYAREA; } if (!dst->buggy_repeat) return DO_RENDER; if (is_integer_translation && src_attr->extend == CAIRO_EXTEND_REPEAT && (src->width != 1 || src->height != 1)) { if (!have_mask && !needs_alpha_composite && _surfaces_compatible (dst, src)) { return DO_XTILE; } return DO_UNSUPPORTED; } return DO_RENDER;}static int_render_operator (cairo_operator_t op){ switch (op) { case CAIRO_OPERATOR_CLEAR: return PictOpClear; 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; default: return PictOpOver; }}static cairo_int_status_t_cairo_xlib_surface_composite (cairo_operator_t op, cairo_pattern_t *src_pattern, cairo_pattern_t *mask_pattern, void *abstract_dst, int src_x, int src_y, int mask_x, int mask_y, int dst_x, int dst_y, unsigned int width, unsigned int height){ cairo_surface_attributes_t src_attr, mask_attr; cairo_xlib_surface_t *dst = abstract_dst; cairo_xlib_surface_t *src; cairo_xlib_surface_t *mask; cairo_int_status_t status; composite_operation_t operation; int itx, ity; if (!CAIRO_SURFACE_RENDER_HAS_COMPOSITE (dst)) return CAIRO_INT_STATUS_UNSUPPORTED; operation = _categorize_composite_operation (dst, op, src_pattern, mask_pattern != NULL); if (operation == DO_UNSUPPORTED) return CAIRO_INT_STATUS_UNSUPPORTED; status = _cairo_pattern_acquire_surfaces (src_pattern, mask_pattern, &dst->base, src_x, src_y, mask_x, mask_y, width, height, (cairo_surface_t **) &src, (cairo_surface_t **) &mask, &src_attr, &mask_attr); if (status) return status; operation = _recategorize_composite_operation (dst, op, src, &src_attr, mask_pattern != NULL); if (operation == DO_UNSUPPORTED) { status = CAIRO_INT_STATUS_UNSUPPORTED; goto BAIL; } status = _cairo_xlib_surface_set_attributes (src, &src_attr); if (status) goto BAIL; switch (operation) { case DO_RENDER: _cairo_xlib_surface_ensure_dst_picture (dst); if (mask) { status = _cairo_xlib_surface_set_attributes (mask, &mask_attr); if (status) goto BAIL; XRenderComposite (dst->dpy, _render_operator (op), src->src_picture, mask->src_picture, dst->dst_picture, src_x + src_attr.x_offset, src_y + src_attr.y_offset, mask_x + mask_attr.x_offset, mask_y + mask_attr.y_offset, dst_x, dst_y, width, height); } else { XRenderComposite (dst->dpy, _render_operator (op), src->src_picture, 0, dst->dst_picture, src_x + src_attr.x_offset, src_y + src_attr.y_offset, 0, 0, dst_x, dst_y, width, height); } break; case DO_XCOPYAREA: _cairo_xlib_surface_ensure_gc (dst); XCopyArea (dst->dpy, src->drawable, dst->drawable, dst->gc, src_x + src_attr.x_offset, src_y + src_attr.y_offset, width, height, dst_x, dst_y); break; case DO_XTILE: /* This case is only used for bug fallbacks, though it is theoretically * applicable to the case where we don't have the RENDER extension as * well. * * We've checked that we have a repeating unscaled source in * _recategorize_composite_operation. */ _cairo_xlib_surface_ensure_gc (dst); _cairo_matrix_is_integer_translation (&src_attr.matrix, &itx, &ity); XSetTSOrigin (dst->dpy, dst->gc, - (itx + src_attr.x_offset), - (ity + src_attr.y_offset)); XSetTile (dst->dpy, dst->gc, src->drawable); XSetFillStyle (dst->dpy, dst->gc, FillTiled); XFillRectangle (dst->dpy, dst->drawable, dst->gc, dst_x, dst_y, width, height); break; default: ASSERT_NOT_REACHED; } if (!_cairo_operator_bounded_by_source (op)) status = _cairo_surface_composite_fixup_unbounded (&dst->base, &src_attr, src->width, src->height, mask ? &mask_attr : NULL, mask ? mask->width : 0, mask ? mask->height : 0, src_x, src_y, mask_x, mask_y, dst_x, dst_y, width, height); BAIL:
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -