📄 cairo-scaled-font.c
字号:
(cairo_hash_entry_t**) &scaled_font)) { _cairo_scaled_font_map_unlock (); return cairo_scaled_font_reference (scaled_font); } /* Otherwise create it and insert it into the hash table. */ status = font_face->backend->scaled_font_create (font_face, font_matrix, ctm, options, &scaled_font); if (status) goto UNWIND_FONT_MAP_LOCK; status = _cairo_hash_table_insert (font_map->hash_table, &scaled_font->hash_entry); if (status) goto UNWIND_SCALED_FONT_CREATE; _cairo_scaled_font_map_unlock (); return scaled_font;UNWIND_SCALED_FONT_CREATE: /* We can't call _cairo_scaled_font_destroy here since it expects * that the font has already been successfully inserted into the * hash table. */ _cairo_scaled_font_fini (scaled_font); free (scaled_font);UNWIND_FONT_MAP_LOCK: _cairo_scaled_font_map_unlock ();UNWIND: return NULL;}/** * cairo_scaled_font_reference: * @scaled_font: a #cairo_scaled_font_t, (may be NULL in which case * this function does nothing) * * Increases the reference count on @scaled_font by one. This prevents * @scaled_font from being destroyed until a matching call to * cairo_scaled_font_destroy() is made. * * Returns: the referenced #cairo_scaled_font_t **/cairo_scaled_font_t *cairo_scaled_font_reference (cairo_scaled_font_t *scaled_font){ cairo_scaled_font_map_t *font_map; if (scaled_font == NULL) return NULL; if (scaled_font->ref_count == (unsigned int)-1) return scaled_font; /* We would normally assert (scaled_font->ref_count > 0) here, but * we are using ref_count == 0 as a legitimate case for the * holdovers array. See below. */ /* cairo_scaled_font_t objects are cached and shared between * threads. This works because these objects are immutable. Except * that the reference count is mutable, so we have to do locking * around any modification of the reference count. */ font_map = _cairo_scaled_font_map_lock (); { /* If the original reference count is 0, then this font must have * been found in font_map->holdovers, (which means this caching is * actually working). So now we remove it from the holdovers * array. */ if (scaled_font->ref_count == 0) { int i; for (i = 0; i < font_map->num_holdovers; i++) if (font_map->holdovers[i] == scaled_font) break; assert (i < font_map->num_holdovers); font_map->num_holdovers--; memmove (&font_map->holdovers[i], &font_map->holdovers[i+1], (font_map->num_holdovers - i) * sizeof (cairo_scaled_font_t*)); } scaled_font->ref_count++; } _cairo_scaled_font_map_unlock (); return scaled_font;}/** * cairo_scaled_font_destroy: * @scaled_font: a #cairo_scaled_font_t * * Decreases the reference count on @font by one. If the result * is zero, then @font and all associated resources are freed. * See cairo_scaled_font_reference(). **/voidcairo_scaled_font_destroy (cairo_scaled_font_t *scaled_font){ cairo_scaled_font_map_t *font_map; if (scaled_font == NULL) return; if (scaled_font->ref_count == (unsigned int)-1) return; /* cairo_scaled_font_t objects are cached and shared between * threads. This works because these objects are immutable. Except * that the reference count is mutable, so we have to do locking * around any modification of the reference count. */ font_map = _cairo_scaled_font_map_lock (); { assert (font_map != NULL); assert (scaled_font->ref_count > 0); if (--(scaled_font->ref_count) == 0) { /* Rather than immediately destroying this object, we put it into * the font_map->holdovers array in case it will get used again * soon. To make room for it, we do actually destroy the * least-recently-used holdover. */ if (font_map->num_holdovers == CAIRO_SCALED_FONT_MAX_HOLDOVERS) { cairo_scaled_font_t *lru; lru = font_map->holdovers[0]; assert (lru->ref_count == 0); _cairo_hash_table_remove (font_map->hash_table, &lru->hash_entry); _cairo_scaled_font_fini (lru); free (lru); font_map->num_holdovers--; memmove (&font_map->holdovers[0], &font_map->holdovers[1], font_map->num_holdovers * sizeof (cairo_scaled_font_t*)); } font_map->holdovers[font_map->num_holdovers] = scaled_font; font_map->num_holdovers++; } } _cairo_scaled_font_map_unlock ();}/* Public font API follows. *//** * cairo_scaled_font_extents: * @scaled_font: a #cairo_scaled_font_t * @extents: a #cairo_font_extents_t which to store the retrieved extents. * * Gets the metrics for a #cairo_scaled_font_t. **/voidcairo_scaled_font_extents (cairo_scaled_font_t *scaled_font, cairo_font_extents_t *extents){ *extents = scaled_font->extents;}/** * cairo_scaled_font_text_extents: * @scaled_font: a #cairo_scaled_font_t * @utf8: a string of text, encoded in UTF-8 * @extents: a #cairo_text_extents_t which to store the retrieved extents. * * Gets the extents for a string of text. The extents describe a * user-space rectangle that encloses the "inked" portion of the text * drawn at the origin (0,0) (as it would be drawn by cairo_show_text() * if the cairo graphics state were set to the same font_face, * font_matrix, ctm, and font_options as @scaled_font). Additionally, * the x_advance and y_advance values indicate the amount by which the * current point would be advanced by cairo_show_text(). * * Note that whitespace characters do not directly contribute to the * size of the rectangle (extents.width and extents.height). They do * contribute indirectly by changing the position of non-whitespace * characters. In particular, trailing whitespace characters are * likely to not affect the size of the rectangle, though they will * affect the x_advance and y_advance values. * * Since: 1.2 **/voidcairo_scaled_font_text_extents (cairo_scaled_font_t *scaled_font, const char *utf8, cairo_text_extents_t *extents){ cairo_status_t status = CAIRO_STATUS_SUCCESS; cairo_glyph_t *glyphs; int num_glyphs; status = _cairo_scaled_font_text_to_glyphs (scaled_font, 0., 0., utf8, &glyphs, &num_glyphs); if (status) { _cairo_scaled_font_set_error (scaled_font, status); return; } cairo_scaled_font_glyph_extents (scaled_font, glyphs, num_glyphs, extents); free (glyphs);}/** * cairo_scaled_font_glyph_extents: * @scaled_font: a #cairo_scaled_font_t * @glyphs: an array of glyph IDs with X and Y offsets. * @num_glyphs: the number of glyphs in the @glyphs array * @extents: a #cairo_text_extents_t which to store the retrieved extents. * * Gets the extents for an array of glyphs. The extents describe a * user-space rectangle that encloses the "inked" portion of the * glyphs, (as they would be drawn by cairo_show_glyphs() if the cairo * graphics state were set to the same font_face, font_matrix, ctm, * and font_options as @scaled_font). Additionally, the x_advance and * y_advance values indicate the amount by which the current point * would be advanced by cairo_show_glyphs. * * Note that whitespace glyphs do not contribute to the size of the * rectangle (extents.width and extents.height). **/voidcairo_scaled_font_glyph_extents (cairo_scaled_font_t *scaled_font, cairo_glyph_t *glyphs, int num_glyphs, cairo_text_extents_t *extents){ cairo_status_t status = CAIRO_STATUS_SUCCESS; int i; double min_x = 0.0, min_y = 0.0, max_x = 0.0, max_y = 0.0; double x_pos = 0.0, y_pos = 0.0; if (scaled_font->status) return; if (!num_glyphs) { extents->x_bearing = 0.0; extents->y_bearing = 0.0; extents->width = 0.0; extents->height = 0.0; extents->x_advance = 0.0; extents->y_advance = 0.0; return; } for (i = 0; i < num_glyphs; i++) { cairo_scaled_glyph_t *scaled_glyph; double left, top, right, bottom; status = _cairo_scaled_glyph_lookup (scaled_font, glyphs[i].index, CAIRO_SCALED_GLYPH_INFO_METRICS, &scaled_glyph); if (status) { _cairo_scaled_font_set_error (scaled_font, status); return; } left = scaled_glyph->metrics.x_bearing + glyphs[i].x; right = left + scaled_glyph->metrics.width; top = scaled_glyph->metrics.y_bearing + glyphs[i].y; bottom = top + scaled_glyph->metrics.height; if (i == 0) { min_x = left; max_x = right; min_y = top; max_y = bottom; } else { if (left < min_x) min_x = left; if (right > max_x) max_x = right; if (top < min_y) min_y = top; if (bottom > max_y) max_y = bottom; } x_pos = glyphs[i].x + scaled_glyph->metrics.x_advance; y_pos = glyphs[i].y + scaled_glyph->metrics.y_advance; } extents->x_bearing = min_x - glyphs[0].x; extents->y_bearing = min_y - glyphs[0].y; extents->width = max_x - min_x; extents->height = max_y - min_y; extents->x_advance = x_pos - glyphs[0].x; extents->y_advance = y_pos - glyphs[0].y;}cairo_status_t_cairo_scaled_font_text_to_glyphs (cairo_scaled_font_t *scaled_font, double x, double y, const char *utf8, cairo_glyph_t **glyphs, int *num_glyphs){ size_t i; uint32_t *ucs4 = NULL; cairo_status_t status = CAIRO_STATUS_SUCCESS; cairo_scaled_glyph_t *scaled_glyph; if (scaled_font->backend->text_to_glyphs) { status = scaled_font->backend->text_to_glyphs (scaled_font, x, y, utf8, glyphs, num_glyphs); if (status != CAIRO_INT_STATUS_UNSUPPORTED) return status; } status = _cairo_utf8_to_ucs4 ((unsigned char*)utf8, -1, &ucs4, num_glyphs); if (status) return status; *glyphs = (cairo_glyph_t *) malloc ((*num_glyphs) * (sizeof (cairo_glyph_t))); if (*glyphs == NULL) { status = CAIRO_STATUS_NO_MEMORY; goto FAIL; } for (i = 0; i < *num_glyphs; i++) { (*glyphs)[i].index = (*scaled_font->backend-> ucs4_to_index) (scaled_font, ucs4[i]); (*glyphs)[i].x = x; (*glyphs)[i].y = y; status = _cairo_scaled_glyph_lookup (scaled_font, (*glyphs)[i].index, CAIRO_SCALED_GLYPH_INFO_METRICS, &scaled_glyph); if (status) { free (*glyphs); *glyphs = NULL; goto FAIL; } x += scaled_glyph->metrics.x_advance; y += scaled_glyph->metrics.y_advance; } FAIL: free (ucs4); return status;}/* * Compute a device-space bounding box for the glyphs. */cairo_status_t_cairo_scaled_font_glyph_device_extents (cairo_scaled_font_t *scaled_font, const cairo_glyph_t *glyphs, int num_glyphs, cairo_rectangle_int16_t *extents){ cairo_status_t status = CAIRO_STATUS_SUCCESS; int i; int min_x = INT16_MAX, max_x = INT16_MIN; int min_y = INT16_MAX, max_y = INT16_MAX; if (scaled_font->status) return scaled_font->status; for (i = 0; i < num_glyphs; i++) { cairo_scaled_glyph_t *scaled_glyph; int left, top; int right, bottom; int x, y; status = _cairo_scaled_glyph_lookup (scaled_font, glyphs[i].index, CAIRO_SCALED_GLYPH_INFO_METRICS, &scaled_glyph); if (status) { _cairo_scaled_font_set_error (scaled_font, status); return status; } /* glyph images are snapped to pixel locations */ x = (int) floor (glyphs[i].x + 0.5); y = (int) floor (glyphs[i].y + 0.5); left = x + _cairo_fixed_integer_floor(scaled_glyph->bbox.p1.x); top = y + _cairo_fixed_integer_floor (scaled_glyph->bbox.p1.y); right = x + _cairo_fixed_integer_ceil(scaled_glyph->bbox.p2.x); bottom = y + _cairo_fixed_integer_ceil (scaled_glyph->bbox.p2.y); if (left < min_x) min_x = left; if (right > max_x) max_x = right; if (top < min_y) min_y = top; if (bottom > max_y) max_y = bottom; } if (min_x < max_x && min_y < max_y) { extents->x = min_x; extents->width = max_x - min_x; extents->y = min_y; extents->height = max_y - min_y; } else { extents->x = extents->y = 0; extents->width = extents->height = 0; } return CAIRO_STATUS_SUCCESS;}cairo_status_t_cairo_scaled_font_show_glyphs (cairo_scaled_font_t *scaled_font, cairo_operator_t op, cairo_pattern_t *pattern, cairo_surface_t *surface, int source_x, int source_y, int dest_x, int dest_y, unsigned int width, unsigned int height, const cairo_glyph_t *glyphs, int num_glyphs){ cairo_status_t status; cairo_surface_t *mask = NULL; int i; /* These operators aren't interpreted the same way by the backends; * they are implemented in terms of other operators in cairo-gstate.c */ assert (op != CAIRO_OPERATOR_SOURCE && op != CAIRO_OPERATOR_CLEAR); if (scaled_font->status) return scaled_font->status; if (scaled_font->backend->show_glyphs != NULL) { status = scaled_font->backend->show_glyphs (scaled_font, op, pattern, surface, source_x, source_y, dest_x, dest_y, width, height, glyphs, num_glyphs); if (status != CAIRO_INT_STATUS_UNSUPPORTED) return status; } /* Font display routine either does not exist or failed. */ status = CAIRO_STATUS_SUCCESS; _cairo_cache_freeze (scaled_font->glyphs); for (i = 0; i < num_glyphs; i++) { int x, y; cairo_surface_pattern_t glyph_pattern; cairo_image_surface_t *glyph_surface; cairo_scaled_glyph_t *scaled_glyph; status = _cairo_scaled_glyph_lookup (scaled_font,
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -