📄 cairo-glitz-surface.c
字号:
return CAIRO_STATUS_NO_MEMORY; } if (buffer) glitz_buffer_destroy (buffer); buffer = glitz_buffer_create_for_data (data); if (!buffer) { free (data); _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; } } offset += glitz_add_trapezoids (buffer, offset, size - offset, format.vertex.type, mask->surface, (glitz_trapezoid_t *) traps, n_traps, &n_trap_added); n_traps -= n_trap_added; traps += n_trap_added; size *= 2; } glitz_set_geometry (dst->surface, GLITZ_GEOMETRY_TYPE_VERTEX, &format, buffer); glitz_set_array (dst->surface, 0, 3, offset / format.vertex.bytes_per_vertex, 0, 0); } else { cairo_image_surface_t *image; unsigned char *ptr; int stride; stride = (width + 3) & -4; data = calloc (stride * height, 1); 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); return CAIRO_STATUS_NO_MEMORY; } /* using negative stride */ ptr = (unsigned char *) data + stride * (height - 1); image = (cairo_image_surface_t *) cairo_image_surface_create_for_data (ptr, CAIRO_FORMAT_A8, width, height, -stride); if (image->base.status) { cairo_surface_destroy (&src->base); free (data); return CAIRO_STATUS_NO_MEMORY; } pixman_add_trapezoids (image->pixman_image, -dst_x, -dst_y, (pixman_trapezoid_t *) traps, n_traps); mask = (cairo_glitz_surface_t *) _cairo_surface_create_similar_scratch (&dst->base, CAIRO_CONTENT_ALPHA, width, height); if (mask->base.status) { _cairo_glitz_pattern_release_surface (src_pattern, src, &attributes); free (data); cairo_surface_destroy (&image->base); return CAIRO_STATUS_NO_MEMORY; } _cairo_glitz_surface_set_image (mask, image, 0, 0); } _cairo_glitz_surface_set_attributes (src, &attributes); glitz_composite (_glitz_operator (op), src->surface, mask->surface, dst->surface, src_x + attributes.base.x_offset, src_y + attributes.base.y_offset, 0, 0, dst_x, dst_y, width, height); if (attributes.n_params) free (attributes.params); glitz_set_geometry (dst->surface, GLITZ_GEOMETRY_TYPE_NONE, NULL, NULL); if (buffer) glitz_buffer_destroy (buffer); free (data); _cairo_glitz_pattern_release_surface (src_pattern, src, &attributes); if (src_pattern == &tmp_src_pattern.base) _cairo_pattern_fini (&tmp_src_pattern.base); if (mask) cairo_surface_destroy (&mask->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_set_clip_region (void *abstract_surface, pixman_region16_t *region){ cairo_glitz_surface_t *surface = abstract_surface; if (region) { glitz_box_t *box; int n; if (!surface->clip) { surface->clip = pixman_region_create (); if (!surface->clip) return CAIRO_STATUS_NO_MEMORY; } pixman_region_copy (surface->clip, region); box = (glitz_box_t *) pixman_region_rects (surface->clip); n = pixman_region_num_rects (surface->clip); glitz_surface_set_clip_region (surface->surface, 0, 0, box, n); } else { glitz_surface_set_clip_region (surface->surface, 0, 0, NULL, 0); if (surface->clip) pixman_region_destroy (surface->clip); surface->clip = NULL; } return CAIRO_STATUS_SUCCESS;}static cairo_int_status_t_cairo_glitz_surface_get_extents (void *abstract_surface, cairo_rectangle_int16_t *rectangle){ cairo_glitz_surface_t *surface = abstract_surface; rectangle->x = 0; rectangle->y = 0; rectangle->width = glitz_surface_get_width (surface->surface); rectangle->height = glitz_surface_get_height (surface->surface); return CAIRO_STATUS_SUCCESS;}#define CAIRO_GLITZ_AREA_AVAILABLE 0#define CAIRO_GLITZ_AREA_DIVIDED 1#define CAIRO_GLITZ_AREA_OCCUPIED 2typedef struct _cairo_glitz_root_area cairo_glitz_root_area_t;typedef struct _cairo_glitz_area { int state; int level; int x, y; int width, height; struct _cairo_glitz_area *area[4]; cairo_glitz_root_area_t *root; void *closure;} cairo_glitz_area_t;static cairo_glitz_area_t _empty_area = { 0, 0, 0, 0, 0, 0, { NULL, NULL, NULL, NULL }, NULL, NULL};typedef struct _cairo_glitz_area_funcs { cairo_status_t (*move_in) (cairo_glitz_area_t *area, void *closure); void (*move_out) (cairo_glitz_area_t *area, void *closure); int (*compare_score) (cairo_glitz_area_t *area, void *closure1, void *closure2);} cairo_glitz_area_funcs_t;struct _cairo_glitz_root_area { int max_level; int width, height; cairo_glitz_area_t *area; const cairo_glitz_area_funcs_t *funcs;};static cairo_status_t_cairo_glitz_area_move_in (cairo_glitz_area_t *area, void *closure){ area->closure = closure; area->state = CAIRO_GLITZ_AREA_OCCUPIED; return (*area->root->funcs->move_in) (area, area->closure);}static void_cairo_glitz_area_move_out (cairo_glitz_area_t *area){ if (area->root) { (*area->root->funcs->move_out) (area, area->closure); area->closure = NULL; area->state = CAIRO_GLITZ_AREA_AVAILABLE; }}static cairo_glitz_area_t *_cairo_glitz_area_create (cairo_glitz_root_area_t *root, int level, int x, int y, int width, int height){ cairo_glitz_area_t *area; int n = 4; area = malloc (sizeof (cairo_glitz_area_t)); if (!area) return NULL; area->level = level; area->x = x; area->y = y; area->width = width; area->height = height; area->root = root; area->closure = NULL; area->state = CAIRO_GLITZ_AREA_AVAILABLE; while (n--) area->area[n] = NULL; return area;}static void_cairo_glitz_area_destroy (cairo_glitz_area_t *area){ if (area == NULL) return; if (area->state == CAIRO_GLITZ_AREA_OCCUPIED) { _cairo_glitz_area_move_out (area); } else { int n = 4; while (n--) _cairo_glitz_area_destroy (area->area[n]); } free (area);}static cairo_glitz_area_t *_cairo_glitz_area_get_top_scored_sub_area (cairo_glitz_area_t *area){ if (!area) return NULL; switch (area->state) { case CAIRO_GLITZ_AREA_OCCUPIED: return area; case CAIRO_GLITZ_AREA_AVAILABLE: break; case CAIRO_GLITZ_AREA_DIVIDED: { cairo_glitz_area_t *tmp, *top = NULL; int i; for (i = 0; i < 4; i++) { tmp = _cairo_glitz_area_get_top_scored_sub_area (area->area[i]); if (tmp && top) { if ((*area->root->funcs->compare_score) (tmp, tmp->closure, top->closure) > 0) top = tmp; } else if (tmp) { top = tmp; } } return top; } } return NULL;}static cairo_int_status_t_cairo_glitz_area_find (cairo_glitz_area_t *area, int width, int height, cairo_bool_t kick_out, void *closure){ cairo_status_t status; if (area->width < width || area->height < height) return CAIRO_INT_STATUS_UNSUPPORTED; switch (area->state) { case CAIRO_GLITZ_AREA_OCCUPIED: if (kick_out) { if ((*area->root->funcs->compare_score) (area, area->closure, closure) >= 0) return CAIRO_INT_STATUS_UNSUPPORTED; _cairo_glitz_area_move_out (area); } else { return CAIRO_INT_STATUS_UNSUPPORTED; } /* fall-through */ case CAIRO_GLITZ_AREA_AVAILABLE: { if (area->level == area->root->max_level || (area->width == width && area->height == height)) { return _cairo_glitz_area_move_in (area, closure); } else { int dx[4], dy[4], w[4], h[4], i; dx[0] = dx[2] = dy[0] = dy[1] = 0; w[0] = w[2] = dx[1] = dx[3] = width; h[0] = h[1] = dy[2] = dy[3] = height; w[1] = w[3] = area->width - width; h[2] = h[3] = area->height - height; for (i = 0; i < 2; i++) { if (w[i]) area->area[i] = _cairo_glitz_area_create (area->root, area->level + 1, area->x + dx[i], area->y + dy[i], w[i], h[i]); } for (; i < 4; i++) { if (w[i] && h[i]) area->area[i] = _cairo_glitz_area_create (area->root, area->level + 1, area->x + dx[i], area->y + dy[i], w[i], h[i]); } area->state = CAIRO_GLITZ_AREA_DIVIDED; status = _cairo_glitz_area_find (area->area[0], width, height, kick_out, closure); if (status == CAIRO_STATUS_SUCCESS) return CAIRO_STATUS_SUCCESS; } } break; case CAIRO_GLITZ_AREA_DIVIDED: { cairo_glitz_area_t *to_area; int i, rejected = FALSE; for (i = 0; i < 4; i++) { if (area->area[i]) { if (area->area[i]->width >= width && area->area[i]->height >= height) { status = _cairo_glitz_area_find (area->area[i], width, height, kick_out, closure); if (status == CAIRO_STATUS_SUCCESS) return CAIRO_STATUS_SUCCESS; rejected = TRUE; } } } if (rejected) return CAIRO_INT_STATUS_UNSUPPORTED; to_area = _cairo_glitz_area_get_top_scored_sub_area (area); if (to_area) { if (kick_out) { if ((*area->root->funcs->compare_score) (to_area, to_area->closure, closure) >= 0) return CAIRO_INT_STATUS_UNSUPPORTED; } else { return CAIRO_INT_STATUS_UNSUPPORTED; } } for (i = 0; i < 4; i++) { _cairo_glitz_area_destroy (area->area[i]); area->area[i] = NULL; } area->closure = NULL; area->state = CAIRO_GLITZ_AREA_AVAILABLE; status = _cairo_glitz_area_find (area, width, height, TRUE, closure); if (status == CAIRO_STATUS_SUCCESS) return CAIRO_STATUS_SUCCESS; } break; } return CAIRO_INT_STATUS_UNSUPPORTED;}static cairo_status_t_cairo_glitz_root_area_init (cairo_glitz_root_area_t *root, int max_level, int width, int height, const cairo_glitz_area_funcs_t *funcs){ root->max_level = max_level; root->funcs = funcs; root->area = _cairo_glitz_area_create (root, 0, 0, 0, width, height); if (!root->area) return CAIRO_STATUS_NO_MEMORY; return CAIRO_STATUS_SUCCESS;}static void_cairo_glitz_root_area_fini (cairo_glitz_root_area_t *root){ _cairo_glitz_area_destroy (root->area);}typedef struct _cairo_glitz_surface_font_private { cairo_glitz_root_area_t root; glitz_surface_t *surface;} cairo_glitz_surface_font_private_t;typedef struct _cairo_glitz_surface_glyph_private { cairo_glitz_area_t *area; cairo_bool_t locked; cairo_point_double_t p1, p2;} cairo_glitz_surface_glyph_private_t;static cairo_status_t_cairo_glitz_glyph_move_in (cairo_glitz_area_t *area, void *closure){ cairo_glitz_surface_glyph_private_t *glyph_private = closure; glyph_private->area = area; return CAIRO_STATUS_SUCCESS;}static void_cairo_glitz_glyph_move_out (cairo_glitz_area_t *area, void *closure){ cairo_glitz_surface_glyph_private_t *glyph_private = closure; glyph_private->area = NULL;}static int_cairo_glitz_glyph_compare (cairo_glitz_area_t *area, void *closure1, void *closure2){ cairo_glitz_surface_glyph_private_t *glyph_private = closure1; if (glyph_private->locked) return 1; return -1;}static const cairo_glitz_area_funcs_t _cairo_glitz_area_funcs = { _cairo_glitz_glyph_move_in, _cairo_glitz_glyph_move_out, _cairo_glitz_glyph_compare};#define GLYPH_CACHE_TEXTURE_SIZE 512#define GLYPH_CACHE_MAX_LEVEL 64#define GLYPH_CACHE_MAX_HEIGHT 72#define GLYPH_CACHE_MAX_WIDTH 72#define WRITE_VEC2(ptr, _x, _y) \ *(ptr)++ = (_x); \ *(ptr)++ = (_y)#define WRITE_BOX(ptr, _vx1, _vy1, _vx2, _vy2, p1, p2) \ WRITE_VEC2 (ptr, _vx1, _vy1); \ WRITE_VEC2 (ptr, (p1)->x, (p2)->y); \ WRITE_VEC2 (ptr, _vx2, _vy1); \ WRITE_VEC2 (ptr, (p2)->x, (p2)->y); \ WRITE_VEC2 (ptr, _vx2, _vy2); \ WRITE_VEC2 (ptr, (p2)->x, (p1)->y); \ WRITE_VEC2 (ptr, _vx1, _vy2); \
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -