📄 pangox.c
字号:
/* pangox.c: Routines for handling X fonts * * Copyright (C) 1999 Red Hat Software * Copyright (C) 2000 SuSE Linux Ltd * * 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 <string.h>#include <stdlib.h>#include <math.h>#include <X11/Xlib.h>#include "pango-impl-utils.h"#include "modules.h"#undef PANGO_DISABLE_DEPRECATED#include "pangox.h"#include "pangox-private.h"#define PANGO_TYPE_X_FONT (pango_x_font_get_type ())#define PANGO_X_FONT(object) (G_TYPE_CHECK_INSTANCE_CAST ((object), PANGO_TYPE_X_FONT, PangoXFont))#define PANGO_X_FONT_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), PANGO_TYPE_X_FONT, PangoXFontClass))#define PANGO_X_IS_FONT(object) (G_TYPE_CHECK_INSTANCE_TYPE ((object), PANGO_TYPE_X_FONT))#define PANGO_X_IS_FONT_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), PANGO_TYPE_X_FONT))#define PANGO_X_FONT_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), PANGO_TYPE_X_FONT, PangoXFontClass))typedef struct _PangoXFontClass PangoXFontClass;typedef struct _PangoXMetricsInfo PangoXMetricsInfo;typedef struct _PangoXContextInfo PangoXContextInfo;struct _PangoXSubfontInfo{ char *xlfd; XFontStruct *font_struct; gboolean is_1byte; int range_byte1; int range_byte2;};struct _PangoXMetricsInfo{ const char *sample_str; PangoFontMetrics *metrics;};struct _PangoXContextInfo{ PangoGetGCFunc get_gc_func; PangoFreeGCFunc free_gc_func;};struct _PangoXFontClass{ PangoFontClass parent_class;};static PangoFontClass *parent_class; /* Parent class structure for PangoXFont */static void pango_x_font_class_init (PangoXFontClass *class);static void pango_x_font_init (PangoXFont *xfont);static void pango_x_font_dispose (GObject *object);static void pango_x_font_finalize (GObject *object);static PangoFontDescription *pango_x_font_describe (PangoFont *font);static PangoCoverage * pango_x_font_get_coverage (PangoFont *font, PangoLanguage *language);static PangoEngineShape * pango_x_font_find_shaper (PangoFont *font, PangoLanguage *language, guint32 ch);static void pango_x_font_get_glyph_extents (PangoFont *font, PangoGlyph glyph, PangoRectangle *ink_rect, PangoRectangle *logical_rect);static PangoFontMetrics * pango_x_font_get_metrics (PangoFont *font, PangoLanguage *language);static PangoFontMap * pango_x_font_get_font_map (PangoFont *font);static PangoXSubfontInfo * pango_x_find_subfont (PangoFont *font, PangoXSubfont subfont_index);static XCharStruct * pango_x_get_per_char (PangoFont *font, PangoXSubfontInfo *subfont, guint16 char_index);static gboolean pango_x_find_glyph (PangoFont *font, PangoGlyph glyph, PangoXSubfontInfo **subfont_return, XCharStruct **charstruct_return);static XFontStruct * pango_x_get_font_struct (PangoFont *font, PangoXSubfontInfo *info);static void pango_x_get_item_properties (PangoItem *item, PangoUnderline *uline, PangoAttrColor *fg_color, gboolean *fg_set, PangoAttrColor *bg_color, gboolean *bg_set);static inline PangoXSubfontInfo *pango_x_find_subfont (PangoFont *font, PangoXSubfont subfont_index){ PangoXFont *xfont = (PangoXFont *)font; if (subfont_index < 1 || subfont_index > xfont->n_subfonts) { g_warning ("Invalid subfont %d", subfont_index); return NULL; } return xfont->subfonts[subfont_index-1];}static voidpango_x_make_font_struct (PangoFont *font, PangoXSubfontInfo *info){ PangoXFont *xfont = (PangoXFont *)font; PangoXFontCache *cache; cache = pango_x_font_map_get_font_cache (xfont->fontmap); info->font_struct = pango_x_font_cache_load (cache, info->xlfd); if (!info->font_struct) { g_warning ("Cannot load font for XLFD '%s\n", info->xlfd); /* Prevent a segfault, but probably not much more */ info->font_struct = pango_x_font_cache_load (cache, "fixed"); } info->is_1byte = (info->font_struct->min_byte1 == 0 && info->font_struct->max_byte1 == 0); info->range_byte1 = info->font_struct->max_byte1 - info->font_struct->min_byte1 + 1; info->range_byte2 = info->font_struct->max_char_or_byte2 - info->font_struct->min_char_or_byte2 + 1;}static inline XFontStruct *pango_x_get_font_struct (PangoFont *font, PangoXSubfontInfo *info){ if (!info->font_struct) pango_x_make_font_struct (font, info); return info->font_struct;}/** * pango_x_get_context: * @display: an X display (As returned by XOpenDisplay().) * * Retrieves a #PangoContext appropriate for rendering with X fonts on the * given display. * * Return value: the new #PangoContext. **/PangoContext *pango_x_get_context (Display *display){ PangoContext *result; PangoXContextInfo *info; int i; static gboolean registered_modules = FALSE; g_return_val_if_fail (display != NULL, NULL); if (!registered_modules) { registered_modules = TRUE; for (i = 0; _pango_included_x_modules[i].list; i++) pango_module_register (&_pango_included_x_modules[i]); } result = pango_context_new (); info = g_new (PangoXContextInfo, 1); info->get_gc_func = NULL; info->free_gc_func = NULL; g_object_set_qdata_full (G_OBJECT (result), g_quark_from_static_string ("pango-x-info"), info, (GDestroyNotify)g_free); pango_context_set_font_map (result, pango_x_font_map_for_display (display)); return result;}/** * pango_x_context_set_funcs: * @context: a #PangoContext. * @get_gc_func: function called to create a new GC for a given color. * @free_gc_func: function called to free a GC created with @get_gc_func. * * Sets the functions that will be used to get GC's in various colors when * rendering layouts with this context. **/voidpango_x_context_set_funcs (PangoContext *context, PangoGetGCFunc get_gc_func, PangoFreeGCFunc free_gc_func){ PangoXContextInfo *info; g_return_if_fail (context != NULL); info = g_object_get_qdata (G_OBJECT (context), g_quark_from_static_string ("pango-x-info")); info->get_gc_func = get_gc_func; info->free_gc_func = free_gc_func;}static GTypepango_x_font_get_type (void){ static GType object_type = 0; if (!object_type) { const GTypeInfo object_info = { sizeof (PangoXFontClass), (GBaseInitFunc) NULL, (GBaseFinalizeFunc) NULL, (GClassInitFunc) pango_x_font_class_init, NULL, /* class_finalize */ NULL, /* class_data */ sizeof (PangoXFont), 0, /* n_preallocs */ (GInstanceInitFunc) pango_x_font_init, NULL /* value_table */ }; object_type = g_type_register_static (PANGO_TYPE_FONT, I_("PangoXFont"), &object_info, 0); } return object_type;}static voidpango_x_font_init (PangoXFont *xfont){ xfont->subfonts_by_charset = g_hash_table_new (g_str_hash, g_str_equal); xfont->subfonts = g_new (PangoXSubfontInfo *, 1); xfont->n_subfonts = 0; xfont->max_subfonts = 1; xfont->metrics_by_lang = NULL; xfont->size = -1; xfont->xface = NULL;}static voidpango_x_font_class_init (PangoXFontClass *class){ GObjectClass *object_class = G_OBJECT_CLASS (class); PangoFontClass *font_class = PANGO_FONT_CLASS (class); parent_class = g_type_class_peek_parent (class); object_class->finalize = pango_x_font_finalize; object_class->dispose = pango_x_font_dispose; font_class->describe = pango_x_font_describe; font_class->get_coverage = pango_x_font_get_coverage; font_class->find_shaper = pango_x_font_find_shaper; font_class->get_glyph_extents = pango_x_font_get_glyph_extents; font_class->get_metrics = pango_x_font_get_metrics; font_class->get_font_map = pango_x_font_get_font_map;}PangoXFont *pango_x_font_new (PangoFontMap *fontmap, const char *spec, int size){ PangoXFont *result; g_return_val_if_fail (fontmap != NULL, NULL); g_return_val_if_fail (spec != NULL, NULL); result = g_object_new (PANGO_TYPE_X_FONT, NULL); result->fontmap = fontmap; g_object_ref (fontmap); result->display = pango_x_fontmap_get_display (fontmap); result->fonts = g_strsplit(spec, ",", -1); for (result->n_fonts = 0; result->fonts[result->n_fonts]; result->n_fonts++) ; /* Nothing */ result->size = size; return result;}/** * pango_x_load_font: * @display: the X display. * @spec: a comma-separated list of XLFD's. * * Loads up a logical font based on a "fontset" style text * specification. This is not remotely useful (Pango API's generally * work in terms of #PangoFontDescription) and the result may not * work correctly in all circumstances. Use of this function should * be avoided. * * Returns a new #PangoFont. */PangoFont *pango_x_load_font (Display *display, const char *spec){ PangoXFont *result; g_return_val_if_fail (display != NULL, NULL); g_return_val_if_fail (spec != NULL, NULL); result = pango_x_font_new (pango_x_font_map_for_display (display), spec, -1); return (PangoFont *)result;}#define FLUSH \ G_STMT_START { \ if (charcount) \ { \ XDrawString16 (display, d, gc, \ glyph_x0, glyph_y0, \ xcharbuffer, charcount); \ charcount = 0; \ } \ } G_STMT_END/** * pango_x_render: * @display: the X display. * @d: the drawable on which to draw string. * @gc: the graphics context. * @font: the font in which to draw the string. * @glyphs: the glyph string to draw. * @x: the x position of start of string (in pixels). * @y: the y position of baseline (in pixels). * * Renders a #PangoGlyphString onto an X drawable. */voidpango_x_render (Display *display, Drawable d, GC gc, PangoFont *font, PangoGlyphString *glyphs, int x, int y){ Font old_fid = None; XFontStruct *fs; int i; int x_off = 0; /* * We collect the characters in this buffer as long as the font does not * change. At that time, or when the buffer runs full, or at the end, * then we empty the buffer. */ XChar2b xcharbuffer[1000]; int glyph_x0 = 0, expected_x = 0; /* x/y initializations are to quiet GCC */ int glyph_y0 = 0; int charcount = 0; g_return_if_fail (display != NULL); g_return_if_fail (glyphs != NULL); for (i=0; i<glyphs->num_glyphs; i++) { PangoGlyph glyph = glyphs->glyphs[i].glyph; int glyph_x = x + PANGO_PIXELS (x_off + glyphs->glyphs[i].geometry.x_offset); int glyph_y = y + PANGO_PIXELS (glyphs->glyphs[i].geometry.y_offset); /* Clip glyphs into the X coordinate range; we really * want to clip glyphs with an ink rect outside the * [0,32767] x [0,32767] rectangle but looking up * the ink rect here would be a noticeable speed hit. * This is close enough. */ if (!(glyph != PANGO_GLYPH_EMPTY && glyph_x >= -16384 && glyph_x <= 32767 && glyph_y >= -16384 && glyph_y <= 32767)) goto next_glyph; if ((glyph & PANGO_GLYPH_UNKNOWN_FLAG) == 0) { guint16 index = PANGO_X_GLYPH_INDEX (glyph); guint16 subfont_index = PANGO_X_GLYPH_SUBFONT (glyph); PangoXSubfontInfo *subfont; subfont = pango_x_find_subfont (font, subfont_index); if (subfont) { fs = pango_x_get_font_struct (font, subfont); if (!fs) continue; if (fs->fid != old_fid) { FLUSH; XSetFont (display, gc, fs->fid); old_fid = fs->fid; } if (charcount == G_N_ELEMENTS (xcharbuffer) || (charcount > 0 && (glyph_y != glyph_y0 || glyph_x != expected_x))) FLUSH; if (charcount == 0) { glyph_x0 = glyph_x; glyph_y0 = glyph_y; } xcharbuffer[charcount].byte1 = index / 256; xcharbuffer[charcount].byte2 = index % 256; expected_x = glyph_x + XTextWidth16 (fs, &xcharbuffer[charcount], 1); charcount++; } else goto unknown_glyph; } else { PangoFontMetrics *metrics; int x1, y1, x2, y2; /* rectangle the character should go inside. */ int baseline; int stroke_thick; gunichar wc; unknown_glyph: FLUSH;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -