📄 cairo-scaled-font.c
字号:
glyphs[i].index, CAIRO_SCALED_GLYPH_INFO_SURFACE, &scaled_glyph); if (status) goto CLEANUP_MASK; glyph_surface = scaled_glyph->surface; /* Create the mask using the format from the first glyph */ if (mask == NULL) { mask = cairo_image_surface_create (glyph_surface->format, width, height); if (mask->status) { status = mask->status; goto CLEANUP_MASK; } status = _cairo_surface_fill_rectangle (mask, CAIRO_OPERATOR_CLEAR, CAIRO_COLOR_TRANSPARENT, 0, 0, width, height); if (status) goto CLEANUP_MASK; if (glyph_surface->format == CAIRO_FORMAT_ARGB32) pixman_image_set_component_alpha (((cairo_image_surface_t*) mask)-> pixman_image, TRUE); } /* round glyph locations to the nearest pixel */ /* XXX: FRAGILE: We're ignoring device_transform scaling here. A bug? */ x = (int) floor (glyphs[i].x + glyph_surface->base.device_transform.x0 + 0.5); y = (int) floor (glyphs[i].y + glyph_surface->base.device_transform.y0 + 0.5); _cairo_pattern_init_for_surface (&glyph_pattern, &glyph_surface->base); status = _cairo_surface_composite (CAIRO_OPERATOR_ADD, &glyph_pattern.base, NULL, mask, 0, 0, 0, 0, x - dest_x, y - dest_y, glyph_surface->width, glyph_surface->height); _cairo_pattern_fini (&glyph_pattern.base); if (status) break; } if (mask != NULL) { cairo_surface_pattern_t mask_pattern; _cairo_pattern_init_for_surface (&mask_pattern, mask); status = _cairo_surface_composite (op, pattern, &mask_pattern.base, surface, source_x, source_y, 0, 0, dest_x, dest_y, width, height); _cairo_pattern_fini (&mask_pattern.base); }CLEANUP_MASK: _cairo_cache_thaw (scaled_font->glyphs); if (mask != NULL) cairo_surface_destroy (mask); return status;}typedef struct _cairo_scaled_glyph_path_closure { cairo_point_t offset; cairo_path_fixed_t *path;} cairo_scaled_glyph_path_closure_t;static cairo_status_t_scaled_glyph_path_move_to (void *abstract_closure, cairo_point_t *point){ cairo_scaled_glyph_path_closure_t *closure = abstract_closure; return _cairo_path_fixed_move_to (closure->path, point->x + closure->offset.x, point->y + closure->offset.y);}static cairo_status_t_scaled_glyph_path_line_to (void *abstract_closure, cairo_point_t *point){ cairo_scaled_glyph_path_closure_t *closure = abstract_closure; return _cairo_path_fixed_line_to (closure->path, point->x + closure->offset.x, point->y + closure->offset.y);}static cairo_status_t_scaled_glyph_path_curve_to (void *abstract_closure, cairo_point_t *p0, cairo_point_t *p1, cairo_point_t *p2){ cairo_scaled_glyph_path_closure_t *closure = abstract_closure; return _cairo_path_fixed_curve_to (closure->path, p0->x + closure->offset.x, p0->y + closure->offset.y, p1->x + closure->offset.x, p1->y + closure->offset.y, p2->x + closure->offset.x, p2->y + closure->offset.y);}static cairo_status_t_scaled_glyph_path_close_path (void *abstract_closure){ cairo_scaled_glyph_path_closure_t *closure = abstract_closure; return _cairo_path_fixed_close_path (closure->path);}cairo_status_t_cairo_scaled_font_glyph_path (cairo_scaled_font_t *scaled_font, const cairo_glyph_t *glyphs, int num_glyphs, cairo_path_fixed_t *path){ cairo_status_t status; int i; cairo_scaled_glyph_path_closure_t closure; if (scaled_font->status) return scaled_font->status; closure.path = path; for (i = 0; i < num_glyphs; i++) { cairo_scaled_glyph_t *scaled_glyph; status = _cairo_scaled_glyph_lookup (scaled_font, glyphs[i].index, CAIRO_SCALED_GLYPH_INFO_PATH, &scaled_glyph); if (status) return status; closure.offset.x = _cairo_fixed_from_double (glyphs[i].x); closure.offset.y = _cairo_fixed_from_double (glyphs[i].y); status = _cairo_path_fixed_interpret (scaled_glyph->path, CAIRO_DIRECTION_FORWARD, _scaled_glyph_path_move_to, _scaled_glyph_path_line_to, _scaled_glyph_path_curve_to, _scaled_glyph_path_close_path, &closure); } return CAIRO_STATUS_SUCCESS;}/** * cairo_scaled_glyph_set_metrics: * @scaled_glyph: a #cairo_scaled_glyph_t * @scaled_font: a #cairo_scaled_font_t * @fs_metrics: a #cairo_text_extents_t in font space * * _cairo_scaled_glyph_set_metrics() stores user space metrics * for the specified glyph given font space metrics. It is * called by the font backend when initializing a glyph with * CAIRO_SCALED_GLYPH_INFO_METRICS. **/void_cairo_scaled_glyph_set_metrics (cairo_scaled_glyph_t *scaled_glyph, cairo_scaled_font_t *scaled_font, cairo_text_extents_t *fs_metrics){ cairo_bool_t first = TRUE; double hm, wm; double min_user_x = 0.0, max_user_x = 0.0, min_user_y = 0.0, max_user_y = 0.0; double min_device_x = 0.0, max_device_x = 0.0, min_device_y = 0.0, max_device_y = 0.0; for (hm = 0.0; hm <= 1.0; hm += 1.0) for (wm = 0.0; wm <= 1.0; wm += 1.0) { double x, y; /* Transform this corner to user space */ x = fs_metrics->x_bearing + fs_metrics->width * wm; y = fs_metrics->y_bearing + fs_metrics->height * hm; cairo_matrix_transform_point (&scaled_font->font_matrix, &x, &y); if (first) { min_user_x = max_user_x = x; min_user_y = max_user_y = y; } else { if (x < min_user_x) min_user_x = x; if (x > max_user_x) max_user_x = x; if (y < min_user_y) min_user_y = y; if (y > max_user_y) max_user_y = y; } /* Transform this corner to device space from glyph origin */ x = fs_metrics->x_bearing + fs_metrics->width * wm; y = fs_metrics->y_bearing + fs_metrics->height * hm; cairo_matrix_transform_distance (&scaled_font->scale, &x, &y); if (first) { min_device_x = max_device_x = x; min_device_y = max_device_y = y; } else { if (x < min_device_x) min_device_x = x; if (x > max_device_x) max_device_x = x; if (y < min_device_y) min_device_y = y; if (y > max_device_y) max_device_y = y; } first = FALSE; } scaled_glyph->metrics.x_bearing = min_user_x; scaled_glyph->metrics.y_bearing = min_user_y; scaled_glyph->metrics.width = max_user_x - min_user_x; scaled_glyph->metrics.height = max_user_y - min_user_y; scaled_glyph->metrics.x_advance = fs_metrics->x_advance; scaled_glyph->metrics.y_advance = fs_metrics->y_advance; cairo_matrix_transform_point (&scaled_font->font_matrix, &scaled_glyph->metrics.x_advance, &scaled_glyph->metrics.y_advance); scaled_glyph->bbox.p1.x = _cairo_fixed_from_double (min_device_x); scaled_glyph->bbox.p1.y = _cairo_fixed_from_double (min_device_y); scaled_glyph->bbox.p2.x = _cairo_fixed_from_double (max_device_x); scaled_glyph->bbox.p2.y = _cairo_fixed_from_double (max_device_y);}void_cairo_scaled_glyph_set_surface (cairo_scaled_glyph_t *scaled_glyph, cairo_scaled_font_t *scaled_font, cairo_image_surface_t *surface){ if (scaled_glyph->surface != NULL) cairo_surface_destroy (&scaled_glyph->surface->base); scaled_glyph->surface = surface;}void_cairo_scaled_glyph_set_path (cairo_scaled_glyph_t *scaled_glyph, cairo_scaled_font_t *scaled_font, cairo_path_fixed_t *path){ if (scaled_glyph->path != NULL) _cairo_path_fixed_destroy (scaled_glyph->path); scaled_glyph->path = path;}/** * _cairo_scaled_glyph_lookup: * @scaled_font: a #cairo_scaled_font_t * @index: the glyph to create * @info: a #cairo_scaled_glyph_info_t marking which portions of * the glyph should be filled in. * @scaled_glyph_ret: a #cairo_scaled_glyph_t * where the glyph * is returned. * * Returns a glyph with the requested portions filled in. Glyph * lookup is cached and glyph will be automatically freed along * with the scaled_font so no explicit free is required. * @info can be one or more of: * %CAIRO_SCALED_GLYPH_INFO_METRICS - glyph metrics and bounding box * %CAIRO_SCALED_GLYPH_INFO_SURFACE - surface holding glyph image * %CAIRO_SCALED_GLYPH_INFO_PATH - path holding glyph outline in device space * * If the desired info is not available, (for example, when trying to * get INFO_PATH with a bitmapped font), this function will return * CAIRO_INT_STATUS_UNSUPPORTED. **/cairo_int_status_t_cairo_scaled_glyph_lookup (cairo_scaled_font_t *scaled_font, unsigned long index, cairo_scaled_glyph_info_t info, cairo_scaled_glyph_t **scaled_glyph_ret){ cairo_status_t status = CAIRO_STATUS_SUCCESS; cairo_cache_entry_t key; cairo_scaled_glyph_t *scaled_glyph; cairo_scaled_glyph_info_t need_info; if (scaled_font->status) return scaled_font->status; CAIRO_MUTEX_LOCK (cairo_scaled_font_map_mutex); key.hash = index; /* * Check cache for glyph */ info |= CAIRO_SCALED_GLYPH_INFO_METRICS; if (!_cairo_cache_lookup (scaled_font->glyphs, &key, (cairo_cache_entry_t **) &scaled_glyph)) { /* * On miss, create glyph and insert into cache */ scaled_glyph = malloc (sizeof (cairo_scaled_glyph_t)); if (scaled_glyph == NULL) { status = CAIRO_STATUS_NO_MEMORY; goto CLEANUP; } _cairo_scaled_glyph_set_index(scaled_glyph, index); scaled_glyph->cache_entry.size = 1; /* XXX */ scaled_glyph->scaled_font = scaled_font; scaled_glyph->surface = NULL; scaled_glyph->path = NULL; scaled_glyph->surface_private = NULL; /* ask backend to initialize metrics and shape fields */ status = (*scaled_font->backend-> scaled_glyph_init) (scaled_font, scaled_glyph, info); if (status) { _cairo_scaled_glyph_destroy (scaled_glyph); goto CLEANUP; } /* on success, the cache takes ownership of the scaled_glyph */ status = _cairo_cache_insert (scaled_font->glyphs, &scaled_glyph->cache_entry); if (status) { _cairo_scaled_glyph_destroy (scaled_glyph); goto CLEANUP; } } /* * Check and see if the glyph, as provided, * already has the requested data and ammend it if not */ need_info = 0; if ((info & CAIRO_SCALED_GLYPH_INFO_SURFACE) != 0 && scaled_glyph->surface == NULL) need_info |= CAIRO_SCALED_GLYPH_INFO_SURFACE; if (((info & CAIRO_SCALED_GLYPH_INFO_PATH) != 0 && scaled_glyph->path == NULL)) need_info |= CAIRO_SCALED_GLYPH_INFO_PATH; if (need_info) { status = (*scaled_font->backend-> scaled_glyph_init) (scaled_font, scaled_glyph, need_info); if (status) goto CLEANUP; } CLEANUP: if (status) { /* It's not an error for the backend to not support the info we want. */ if (status != CAIRO_INT_STATUS_UNSUPPORTED) _cairo_scaled_font_set_error (scaled_font, status); *scaled_glyph_ret = NULL; } else { *scaled_glyph_ret = scaled_glyph; } CAIRO_MUTEX_UNLOCK (cairo_scaled_font_map_mutex); return status;}/** * cairo_scaled_font_get_font_face: * @scaled_font: a #cairo_scaled_font_t * * Return value: The #cairo_font_face_t with which @scaled_font was * created. * * Since: 1.2 **/cairo_font_face_t *cairo_scaled_font_get_font_face (cairo_scaled_font_t *scaled_font){ if (scaled_font->status) return (cairo_font_face_t*) &_cairo_font_face_nil; return scaled_font->font_face;}/** * cairo_scaled_font_get_font_matrix: * @scaled_font: a #cairo_scaled_font_t * @font_matrix: return value for the matrix * * Stores the font matrix with which @scaled_font was created into * @matrix. * * Since: 1.2 **/voidcairo_scaled_font_get_font_matrix (cairo_scaled_font_t *scaled_font, cairo_matrix_t *font_matrix){ if (scaled_font->status) { cairo_matrix_init_identity (font_matrix); return; } *font_matrix = scaled_font->font_matrix;}/** * cairo_scaled_font_get_ctm: * @scaled_font: a #cairo_scaled_font_t * @ctm: return value for the CTM * * Stores the CTM with which @scaled_font was created into @ctm. * * Since: 1.2 **/voidcairo_scaled_font_get_ctm (cairo_scaled_font_t *scaled_font, cairo_matrix_t *ctm){ if (scaled_font->status) { cairo_matrix_init_identity (ctm); return; } *ctm = scaled_font->ctm;}/** * cairo_scaled_font_get_font_options: * @scaled_font: a #cairo_scaled_font_t * @options: return value for the font options * * Stores the font options with which @scaled_font was created into * @ctm. * * Since: 1.2 **/voidcairo_scaled_font_get_font_options (cairo_scaled_font_t *scaled_font, cairo_font_options_t *options){ if (scaled_font->status) { _cairo_font_options_init_default (options); return; } _cairo_font_options_init_copy (options, &scaled_font->options);}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -