📄 pangocairo-font.c
字号:
/* Pango * pangocairo-font.c: Cairo font handling * * Copyright (C) 2000-2005 Red Hat Software * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Library General Public * License as published by the Free Software Foundation; either * version 2 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Library General Public License for more details. * * You should have received a copy of the GNU Library General Public * License along with this library; if not, write to the * Free Software Foundation, Inc., 59 Temple Place - Suite 330, * Boston, MA 02111-1307, USA. */#include <config.h>#include <math.h>#include "pangocairo.h"#include "pangocairo-private.h"#include "pango-impl-utils.h"#define PANGO_CAIRO_FONT_PRIVATE(font) \ ((PangoCairoFontPrivate *) \ (font == NULL ? NULL : \ G_STRUCT_MEMBER_P (font, \ PANGO_CAIRO_FONT_GET_IFACE(PANGO_CAIRO_FONT(font))->cf_priv_offset)))GTypepango_cairo_font_get_type (void){ static GType cairo_font_type = 0; if (! cairo_font_type) { const GTypeInfo cairo_font_info = { sizeof (PangoCairoFontIface), /* class_size */ NULL, /* base_init */ NULL, /* base_finalize */ NULL, NULL, /* class_finalize */ NULL, /* class_data */ 0, 0, NULL, NULL }; cairo_font_type = g_type_register_static (G_TYPE_INTERFACE, I_("PangoCairoFont"), &cairo_font_info, 0); g_type_interface_add_prerequisite (cairo_font_type, PANGO_TYPE_FONT); } return cairo_font_type;}static PangoCairoFontPrivateScaledFontData *_pango_cairo_font_private_scaled_font_data_create (void){ return g_slice_new (PangoCairoFontPrivateScaledFontData);}static void_pango_cairo_font_private_scaled_font_data_destroy (PangoCairoFontPrivateScaledFontData *data){ if (data) { cairo_font_options_destroy (data->options); g_slice_free (PangoCairoFontPrivateScaledFontData, data); }}cairo_scaled_font_t *_pango_cairo_font_private_get_scaled_font (PangoCairoFontPrivate *cf_priv){ cairo_font_face_t *font_face; if (G_LIKELY (cf_priv->scaled_font)) return cf_priv->scaled_font; /* need to create it */ if (G_UNLIKELY (cf_priv->data == NULL)) { /* we have tried to create and failed before */ return NULL; } font_face = (* PANGO_CAIRO_FONT_GET_IFACE (cf_priv->cfont)->create_font_face) (cf_priv->cfont); if (G_UNLIKELY (font_face == NULL)) goto done; cf_priv->scaled_font = cairo_scaled_font_create (font_face, &cf_priv->data->font_matrix, &cf_priv->data->ctm, cf_priv->data->options); cairo_font_face_destroy (font_face);done: if (G_UNLIKELY (cf_priv->scaled_font == NULL || cairo_scaled_font_status (cf_priv->scaled_font) != CAIRO_STATUS_SUCCESS)) { PangoFont *font = PANGO_FONT (cf_priv->cfont); static GQuark warned_quark = 0; if (!warned_quark) warned_quark = g_quark_from_static_string ("pangocairo-scaledfont-warned"); if (!g_object_get_qdata (G_OBJECT (font), warned_quark)) { PangoFontDescription *desc; char *s; desc = pango_font_describe (font); s = pango_font_description_to_string (desc); pango_font_description_free (desc); g_warning ("failed to create cairo %s, expect ugly output. the offending font is '%s'", font_face ? "scaled font" : "font face", s); g_free (s); g_object_set_qdata_full (G_OBJECT (font), warned_quark, GINT_TO_POINTER (1), NULL); } } _pango_cairo_font_private_scaled_font_data_destroy (cf_priv->data); cf_priv->data = NULL; return cf_priv->scaled_font;}/** * pango_cairo_font_get_scaled_font: * @font: a #PangoFont from a #PangoCairoFontMap * * Gets the #cairo_scaled_font_t used by @font. * The scaled font can be referenced and kept using * cairo_scaled_font_reference(). * * Return value: the #cairo_scaled_font_t used by @font, * or %NULL if @font is %NULL. * * Since: 1.18 **/cairo_scaled_font_t *pango_cairo_font_get_scaled_font (PangoCairoFont *cfont){ PangoCairoFontPrivate *cf_priv; if (G_UNLIKELY (!cfont)) return NULL; cf_priv = PANGO_CAIRO_FONT_PRIVATE (cfont); return _pango_cairo_font_private_get_scaled_font (cf_priv);}/** * _pango_cairo_font_install: * @font: a #PangoCairoFont * @cr: a #cairo_t * * Makes @font the current font for rendering in the specified * Cairo context. * * Return value: %TRUE if font was installed successfully, %FALSE otherwise. **/gboolean_pango_cairo_font_install (PangoFont *font, cairo_t *cr){ cairo_scaled_font_t *scaled_font = pango_cairo_font_get_scaled_font ((PangoCairoFont *)font); if (G_UNLIKELY (scaled_font == NULL || cairo_scaled_font_status (scaled_font) != CAIRO_STATUS_SUCCESS)) return FALSE; cairo_set_scaled_font (cr, scaled_font); return TRUE;}typedef struct _PangoCairoFontMetricsInfo{ const char *sample_str; PangoFontMetrics *metrics;} PangoCairoFontMetricsInfo;PangoFontMetrics *_pango_cairo_font_get_metrics (PangoFont *font, PangoLanguage *language){ PangoCairoFont *cfont = (PangoCairoFont *) font; PangoCairoFontPrivate *cf_priv = PANGO_CAIRO_FONT_PRIVATE (font); PangoCairoFontMetricsInfo *info = NULL; /* Quiet gcc */ GSList *tmp_list; const char *sample_str = pango_language_get_sample_string (language); tmp_list = cf_priv->metrics_by_lang; while (tmp_list) { info = tmp_list->data; if (info->sample_str == sample_str) /* We _don't_ need strcmp */ break; tmp_list = tmp_list->next; } if (!tmp_list) { PangoContext *context; cairo_font_options_t *font_options; int height, shift; info = g_slice_new0 (PangoCairoFontMetricsInfo); cf_priv->metrics_by_lang = g_slist_prepend (cf_priv->metrics_by_lang, info); info->sample_str = sample_str; context = pango_cairo_font_map_create_context ((PangoCairoFontMap *) pango_font_get_font_map (font)); pango_context_set_language (context, language); font_options = cairo_font_options_create (); cairo_scaled_font_get_font_options (_pango_cairo_font_private_get_scaled_font (cf_priv), font_options); pango_cairo_context_set_font_options (context, font_options); cairo_font_options_destroy (font_options); info->metrics = (* PANGO_CAIRO_FONT_GET_IFACE (font)->create_metrics_for_context) (cfont, context); /* We may actually reuse ascent/descent we got from cairo here. that's * in cf_priv->font_extents. */ height = info->metrics->ascent + info->metrics->descent; switch (cf_priv->gravity) { default: case PANGO_GRAVITY_AUTO: case PANGO_GRAVITY_SOUTH: break; case PANGO_GRAVITY_NORTH: info->metrics->ascent = info->metrics->descent; break; case PANGO_GRAVITY_EAST: case PANGO_GRAVITY_WEST: { int ascent = height / 2; if (cf_priv->is_hinted) ascent = PANGO_UNITS_ROUND (ascent); info->metrics->ascent = ascent; } } shift = (height - info->metrics->ascent) - info->metrics->descent; info->metrics->descent += shift; info->metrics->underline_position -= shift; info->metrics->strikethrough_position -= shift; info->metrics->ascent = height - info->metrics->descent; g_object_unref (context); } return pango_font_metrics_ref (info->metrics);}static PangoCairoFontHexBoxInfo *_pango_cairo_font_private_get_hex_box_info (PangoCairoFontPrivate *cf_priv){ static const char hexdigits[] = "0123456789ABCDEF"; char c[2] = {0, 0}; PangoFont *mini_font; PangoCairoFontHexBoxInfo *hbi; /* for metrics hinting */ double scale_x = 1., scale_x_inv = 1., scale_y = 1., scale_y_inv = 1.; gboolean is_hinted; int i; int rows; double pad; double width = 0; double height = 0; cairo_font_options_t *font_options; cairo_font_extents_t font_extents; double size, mini_size; PangoFontDescription *desc; cairo_scaled_font_t *scaled_font, *scaled_mini_font; PangoMatrix pango_ctm; cairo_matrix_t cairo_ctm; PangoGravity gravity; if (!cf_priv) return NULL; if (cf_priv->hbi) return cf_priv->hbi; scaled_font = _pango_cairo_font_private_get_scaled_font (cf_priv); if (G_UNLIKELY (scaled_font == NULL || cairo_scaled_font_status (scaled_font) != CAIRO_STATUS_SUCCESS)) return NULL; is_hinted = cf_priv->is_hinted; font_options = cairo_font_options_create (); desc = pango_font_describe_with_absolute_size ((PangoFont *)cf_priv->cfont); size = pango_font_description_get_size (desc) / (1.*PANGO_SCALE); gravity = pango_font_description_get_gravity (desc); cairo_scaled_font_get_ctm (scaled_font, &cairo_ctm); /* I started adding support for vertical hexboxes here, but it's too much * work. Easier to do with cairo user fonts and vertical writing mode * support in cairo. */ /*cairo_matrix_rotate (&cairo_ctm, pango_gravity_to_rotation (gravity));*/ pango_ctm.xx = cairo_ctm.xx; pango_ctm.yx = cairo_ctm.yx; pango_ctm.xy = cairo_ctm.xy; pango_ctm.yy = cairo_ctm.yy; pango_ctm.x0 = cairo_ctm.x0; pango_ctm.y0 = cairo_ctm.y0; if (is_hinted) { /* prepare for some hinting */ double x, y; x = 1.; y = 0.; cairo_matrix_transform_distance (&cairo_ctm, &x, &y); scale_x = sqrt (x*x + y*y); scale_x_inv = 1 / scale_x; x = 0.; y = 1.; cairo_matrix_transform_distance (&cairo_ctm, &x, &y); scale_y = sqrt (x*x + y*y); scale_y_inv = 1 / scale_y; }/* we hint to the nearest device units */#define HINT(value, scale, scale_inv) (ceil ((value-1e-5) * scale) * scale_inv)#define HINT_X(value) HINT ((value), scale_x, scale_x_inv)#define HINT_Y(value) HINT ((value), scale_y, scale_y_inv) /* create mini_font description */ { PangoContext *context; PangoFontMap *fontmap; fontmap = pango_font_get_font_map ((PangoFont *)cf_priv->cfont); /* we inherit most font properties for the mini font. just * change family and size. means, you get bold hex digits * in the hexbox for a bold font. */ /* We should rotate the box, not glyphs */ pango_font_description_unset_fields (desc, PANGO_FONT_MASK_GRAVITY); pango_font_description_set_family_static (desc, "monospace"); rows = 2;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -