📄 cairo-glitz-surface.c
字号:
attr->acquired = FALSE; switch (pattern->type) { case CAIRO_PATTERN_TYPE_LINEAR: case CAIRO_PATTERN_TYPE_RADIAL: { cairo_gradient_pattern_t *gradient = (cairo_gradient_pattern_t *) pattern; char *data; glitz_fixed16_16_t *params; int n_params; unsigned int *pixels; int i, n_base_params; glitz_buffer_t *buffer; static glitz_pixel_format_t format = { GLITZ_FOURCC_RGB, { 32, 0xff000000, 0x00ff0000, 0x0000ff00, 0x000000ff }, 0, 0, 0, GLITZ_PIXEL_SCANLINE_ORDER_BOTTOM_UP }; /* XXX: the current color gradient acceleration provided by glitz is * experimental, it's been proven inappropriate in a number of ways, * most importantly, it's currently implemented as filters and * gradients are not filters. eventually, it will be replaced with * something more appropriate. */ if (gradient->n_stops < 2) break; if (!CAIRO_GLITZ_FEATURE_OK (dst->surface, FRAGMENT_PROGRAM)) break; if (pattern->type == CAIRO_PATTERN_TYPE_RADIAL) n_base_params = 6; else n_base_params = 4; n_params = gradient->n_stops * 3 + n_base_params; data = malloc (sizeof (glitz_fixed16_16_t) * n_params + sizeof (unsigned int) * gradient->n_stops); if (!data) return CAIRO_STATUS_NO_MEMORY; params = (glitz_fixed16_16_t *) data; pixels = (unsigned int *) (data + sizeof (glitz_fixed16_16_t) * n_params); buffer = glitz_buffer_create_for_data (pixels); if (!buffer) { free (data); return CAIRO_STATUS_NO_MEMORY; } src = (cairo_glitz_surface_t *) _cairo_surface_create_similar_scratch (&dst->base, CAIRO_CONTENT_COLOR_ALPHA, gradient->n_stops, 1); if (src->base.status) { glitz_buffer_destroy (buffer); free (data); return CAIRO_STATUS_NO_MEMORY; } for (i = 0; i < gradient->n_stops; i++) { pixels[i] = (((int) (gradient->stops[i].color.alpha >> 8)) << 24) | (((int) (gradient->stops[i].color.red >> 8)) << 16) | (((int) (gradient->stops[i].color.green >> 8)) << 8) | (((int) (gradient->stops[i].color.blue >> 8))); params[n_base_params + 3 * i + 0] = gradient->stops[i].x; params[n_base_params + 3 * i + 1] = i << 16; params[n_base_params + 3 * i + 2] = 0; } glitz_set_pixels (src->surface, 0, 0, gradient->n_stops, 1, &format, buffer); glitz_buffer_destroy (buffer); if (pattern->type == CAIRO_PATTERN_TYPE_LINEAR) { cairo_linear_pattern_t *grad = (cairo_linear_pattern_t *) pattern; params[0] = grad->gradient.p1.x; params[1] = grad->gradient.p1.y; params[2] = grad->gradient.p2.x; params[3] = grad->gradient.p2.y; attr->filter = GLITZ_FILTER_LINEAR_GRADIENT; } else { cairo_radial_pattern_t *grad = (cairo_radial_pattern_t *) pattern; params[0] = grad->gradient.inner.x; params[1] = grad->gradient.inner.y; params[2] = grad->gradient.inner.radius; params[3] = grad->gradient.outer.x; params[4] = grad->gradient.outer.y; params[5] = grad->gradient.outer.radius; attr->filter = GLITZ_FILTER_RADIAL_GRADIENT; } switch (pattern->extend) { case CAIRO_EXTEND_NONE: attr->fill = GLITZ_FILL_TRANSPARENT; break; case CAIRO_EXTEND_REPEAT: attr->fill = GLITZ_FILL_REPEAT; break; case CAIRO_EXTEND_REFLECT: attr->fill = GLITZ_FILL_REFLECT; break; case CAIRO_EXTEND_PAD: attr->fill = GLITZ_FILL_NEAREST; break; } attr->params = params; attr->n_params = n_params; attr->base.matrix = pattern->matrix; attr->base.x_offset = 0; attr->base.y_offset = 0; } break; default: break; } if (!src) { cairo_int_status_t status; status = _cairo_pattern_acquire_surface (pattern, &dst->base, x, y, width, height, (cairo_surface_t **) &src, &attr->base); if (status) return status; if (src) { switch (attr->base.extend) { case CAIRO_EXTEND_NONE: attr->fill = GLITZ_FILL_TRANSPARENT; break; case CAIRO_EXTEND_REPEAT: attr->fill = GLITZ_FILL_REPEAT; break; case CAIRO_EXTEND_REFLECT: attr->fill = GLITZ_FILL_REFLECT; break; case CAIRO_EXTEND_PAD: default: attr->fill = GLITZ_FILL_NEAREST; break; } switch (attr->base.filter) { case CAIRO_FILTER_FAST: case CAIRO_FILTER_NEAREST: attr->filter = GLITZ_FILTER_NEAREST; break; case CAIRO_FILTER_GOOD: case CAIRO_FILTER_BEST: case CAIRO_FILTER_BILINEAR: default: attr->filter = GLITZ_FILTER_BILINEAR; break; } attr->params = NULL; attr->n_params = 0; attr->acquired = TRUE; } } *surface_out = src; return CAIRO_STATUS_SUCCESS;}static void_cairo_glitz_pattern_release_surface (cairo_pattern_t *pattern, cairo_glitz_surface_t *surface, cairo_glitz_surface_attributes_t *attr){ if (attr->acquired) _cairo_pattern_release_surface (pattern, &surface->base, &attr->base); else cairo_surface_destroy (&surface->base);}static cairo_int_status_t_cairo_glitz_pattern_acquire_surfaces (cairo_pattern_t *src, cairo_pattern_t *mask, cairo_glitz_surface_t *dst, int src_x, int src_y, int mask_x, int mask_y, unsigned int width, unsigned int height, cairo_glitz_surface_t **src_out, cairo_glitz_surface_t **mask_out, cairo_glitz_surface_attributes_t *sattr, cairo_glitz_surface_attributes_t *mattr){ cairo_int_status_t status; cairo_pattern_union_t tmp; /* If src and mask are both solid, then the mask alpha can be * combined into src and mask can be ignored. */ /* XXX: This optimization assumes that there is no color * information in mask, so this will need to change when we * support RENDER-style 4-channel masks. */ if (src->type == CAIRO_PATTERN_TYPE_SOLID && mask->type == CAIRO_PATTERN_TYPE_SOLID) { cairo_color_t combined; cairo_solid_pattern_t *src_solid = (cairo_solid_pattern_t *) src; cairo_solid_pattern_t *mask_solid = (cairo_solid_pattern_t *) mask; combined = src_solid->color; _cairo_color_multiply_alpha (&combined, mask_solid->color.alpha); _cairo_pattern_init_solid (&tmp.solid, &combined); mask = NULL; } else { _cairo_pattern_init_copy (&tmp.base, src); } status = _cairo_glitz_pattern_acquire_surface (&tmp.base, dst, src_x, src_y, width, height, src_out, sattr); _cairo_pattern_fini (&tmp.base); if (status) return status; if (mask) { _cairo_pattern_init_copy (&tmp.base, mask); status = _cairo_glitz_pattern_acquire_surface (&tmp.base, dst, mask_x, mask_y, width, height, mask_out, mattr); if (status) _cairo_glitz_pattern_release_surface (&tmp.base, *src_out, sattr); _cairo_pattern_fini (&tmp.base); return status; } else { *mask_out = NULL; } return CAIRO_STATUS_SUCCESS;}static void_cairo_glitz_surface_set_attributes (cairo_glitz_surface_t *surface, cairo_glitz_surface_attributes_t *a){ _cairo_glitz_surface_set_matrix (surface, &a->base.matrix); glitz_surface_set_fill (surface->surface, a->fill); glitz_surface_set_filter (surface->surface, a->filter, a->params, a->n_params);}static cairo_int_status_t_cairo_glitz_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_glitz_surface_attributes_t src_attr, mask_attr; cairo_glitz_surface_t *dst = abstract_dst; cairo_glitz_surface_t *src; cairo_glitz_surface_t *mask; cairo_int_status_t status; if (op == CAIRO_OPERATOR_SATURATE) return CAIRO_INT_STATUS_UNSUPPORTED; if (_glitz_ensure_target (dst->surface)) return CAIRO_INT_STATUS_UNSUPPORTED; status = _cairo_glitz_pattern_acquire_surfaces (src_pattern, mask_pattern, dst, src_x, src_y, mask_x, mask_y, width, height, &src, &mask, &src_attr, &mask_attr); if (status) return status; _cairo_glitz_surface_set_attributes (src, &src_attr); if (mask) { _cairo_glitz_surface_set_attributes (mask, &mask_attr); glitz_composite (_glitz_operator (op), src->surface, mask->surface, dst->surface, src_x + src_attr.base.x_offset, src_y + src_attr.base.y_offset, mask_x + mask_attr.base.x_offset, mask_y + mask_attr.base.y_offset, dst_x, dst_y, width, height); if (mask_attr.n_params) free (mask_attr.params); _cairo_glitz_pattern_release_surface (mask_pattern, mask, &mask_attr); } else { glitz_composite (_glitz_operator (op), src->surface, NULL, dst->surface, src_x + src_attr.base.x_offset, src_y + src_attr.base.y_offset, 0, 0, dst_x, dst_y, width, height); } if (src_attr.n_params) free (src_attr.params); _cairo_glitz_pattern_release_surface (src_pattern, src, &src_attr); if (glitz_surface_get_status (dst->surface) == GLITZ_STATUS_NOT_SUPPORTED) return CAIRO_INT_STATUS_UNSUPPORTED; return CAIRO_STATUS_SUCCESS;}static cairo_int_status_t_cairo_glitz_surface_fill_rectangles (void *abstract_dst, cairo_operator_t op, const cairo_color_t *color, cairo_rectangle_int16_t *rects, int n_rects){ cairo_glitz_surface_t *dst = abstract_dst; if (op == CAIRO_OPERATOR_SOURCE) { glitz_color_t glitz_color; glitz_color.red = color->red_short; glitz_color.green = color->green_short; glitz_color.blue = color->blue_short; glitz_color.alpha = color->alpha_short; glitz_set_rectangles (dst->surface, &glitz_color, (glitz_rectangle_t *) rects, n_rects); } else { cairo_glitz_surface_t *src; if (op == CAIRO_OPERATOR_SATURATE) return CAIRO_INT_STATUS_UNSUPPORTED; if (_glitz_ensure_target (dst->surface)) return CAIRO_INT_STATUS_UNSUPPORTED; src = (cairo_glitz_surface_t *) _cairo_surface_create_similar_solid (&dst->base, CAIRO_CONTENT_COLOR_ALPHA, 1, 1, (cairo_color_t *) color); if (src->base.status) return CAIRO_STATUS_NO_MEMORY; glitz_surface_set_fill (src->surface, GLITZ_FILL_REPEAT); while (n_rects--) { glitz_composite (_glitz_operator (op), src->surface, NULL, dst->surface, 0, 0, 0, 0, rects->x, rects->y, rects->width, rects->height); rects++; } cairo_surface_destroy (&src->base); } if (glitz_surface_get_status (dst->surface) == GLITZ_STATUS_NOT_SUPPORTED) return CAIRO_INT_STATUS_UNSUPPORTED; return CAIRO_STATUS_SUCCESS;}static cairo_int_status_t_cairo_glitz_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 n_traps){ cairo_pattern_union_t tmp_src_pattern; cairo_pattern_t *src_pattern; cairo_glitz_surface_attributes_t attributes; cairo_glitz_surface_t *dst = abstract_dst; cairo_glitz_surface_t *src; cairo_glitz_surface_t *mask = NULL; glitz_buffer_t *buffer = NULL; void *data = NULL; cairo_int_status_t status; unsigned short alpha; if (antialias != CAIRO_ANTIALIAS_DEFAULT && antialias != CAIRO_ANTIALIAS_GRAY) return CAIRO_INT_STATUS_UNSUPPORTED; if (dst->base.status) return dst->base.status; if (op == CAIRO_OPERATOR_SATURATE) return CAIRO_INT_STATUS_UNSUPPORTED; if (_glitz_ensure_target (dst->surface)) return CAIRO_INT_STATUS_UNSUPPORTED; if (pattern->type == CAIRO_PATTERN_TYPE_SURFACE) { _cairo_pattern_init_copy (&tmp_src_pattern.base, pattern); status = _cairo_glitz_pattern_acquire_surface (&tmp_src_pattern.base, dst, src_x, src_y, width, height, &src, &attributes); src_pattern = &tmp_src_pattern.base; } else { status = _cairo_glitz_pattern_acquire_surface (pattern, dst, src_x, src_y, width, height, &src, &attributes); src_pattern = pattern; } alpha = 0xffff; if (status) return status; if (op == CAIRO_OPERATOR_ADD || n_traps <= 1) { static glitz_color_t clear_black = { 0, 0, 0, 0 }; glitz_color_t color; glitz_geometry_format_t format; int n_trap_added; int offset = 0; int data_size = 0; int size = 30 * n_traps; /* just a guess */ format.vertex.primitive = GLITZ_PRIMITIVE_QUADS; format.vertex.type = GLITZ_DATA_TYPE_FLOAT; format.vertex.bytes_per_vertex = 3 * sizeof (glitz_float_t); format.vertex.attributes = GLITZ_VERTEX_ATTRIBUTE_MASK_COORD_MASK; format.vertex.mask.type = GLITZ_DATA_TYPE_FLOAT; format.vertex.mask.size = GLITZ_COORDINATE_SIZE_X; format.vertex.mask.offset = 2 * sizeof (glitz_float_t); mask = (cairo_glitz_surface_t *) _cairo_glitz_surface_create_similar (&dst->base, CAIRO_CONTENT_ALPHA, 2, 1); if (mask->base.status) { _cairo_glitz_pattern_release_surface (src_pattern, src, &attributes); if (src_pattern == &tmp_src_pattern.base) _cairo_pattern_fini (&tmp_src_pattern.base); return CAIRO_STATUS_NO_MEMORY; } color.red = color.green = color.blue = color.alpha = 0xffff; glitz_set_rectangle (mask->surface, &clear_black, 0, 0, 1, 1); glitz_set_rectangle (mask->surface, &color, 1, 0, 1, 1); glitz_surface_set_fill (mask->surface, GLITZ_FILL_NEAREST); glitz_surface_set_filter (mask->surface, GLITZ_FILTER_BILINEAR, NULL, 0); size *= format.vertex.bytes_per_vertex; while (n_traps) { if (data_size < size) { data_size = size; data = realloc (data, data_size); if (!data) { _cairo_glitz_pattern_release_surface (src_pattern, src, &attributes); if (src_pattern == &tmp_src_pattern.base) _cairo_pattern_fini (&tmp_src_pattern.base);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -