📄 pangox.c
字号:
if (font) metrics = pango_font_get_metrics (font, NULL); else metrics = NULL; if (metrics) { y1 = glyph_y - PANGO_PIXELS (metrics->ascent); y2 = y1 + PANGO_PIXELS (metrics->ascent + metrics->descent); } else { y2 = glyph_y; y1 = y2 - PANGO_UNKNOWN_GLYPH_HEIGHT; } x1 = glyph_x; x2 = x1 + PANGO_PIXELS (glyphs->glyphs[i].geometry.width); baseline = glyph_y; stroke_thick = MAX ((int) (0.5 + 0.075 * (y2 - y1)), 1); if (glyph & PANGO_GLYPH_UNKNOWN_FLAG) wc = glyph & (~PANGO_GLYPH_UNKNOWN_FLAG); else wc = 0; switch (wc) { case '\n': case '\r': case 0x2028: /* Line separator */ case 0x2029: /* Paragraph separator */ { /* Draw a carriage-return thingy */ PangoRectangle up_stroke; PangoRectangle across_stroke; int hborder = (x2 - x1) * 0.1; int arrow_height = 0.25 * (y2 - y1); int top_border = (y2 - y1) * 0.25; int arrow_x, arrow_width, tmp_height; /* Draw the arrow-head */ tmp_height = (stroke_thick % 2 == 0) ? 2 : 1; /* Starting height */ arrow_height = 2 * ((1 + arrow_height - tmp_height) / 2) + tmp_height; /* Force symmetry */ arrow_width = 2 + arrow_height - tmp_height; for (arrow_x = x1 + hborder; arrow_x < x1 + hborder + arrow_width; arrow_x++) { XDrawLine (display, d, gc, arrow_x, baseline - stroke_thick + (stroke_thick - tmp_height) / 2, arrow_x, baseline - stroke_thick + (stroke_thick - tmp_height) / 2 + tmp_height - 1); if ((arrow_x - x1 - hborder) % 2 == 1) tmp_height += 2; } across_stroke.x = arrow_x; across_stroke.width = x2 - hborder - arrow_x - stroke_thick; across_stroke.y = baseline - stroke_thick; across_stroke.height = stroke_thick; XFillRectangle (display, d, gc, across_stroke.x, across_stroke.y, across_stroke.width, across_stroke.height); up_stroke.x = across_stroke.x + across_stroke.width; up_stroke.width = stroke_thick; up_stroke.y = y1 + top_border; up_stroke.height = baseline - up_stroke.y; XFillRectangle (display, d, gc, up_stroke.x, up_stroke.y, up_stroke.width, up_stroke.height); } break; default: { /* Perhaps we should draw the box-with-numbers as in the * Xft backend, though we have no guarantee of having * an appropriate size of font. Right now, we just * draw an empty box. (To draw the box-with-numbers. * the backends would have to be changed to use * pango_x_font_get_unknown_glyph() rather than * pango_x_get_unknown_glyph(). */ int xspace = MAX ((int) (0.5 + 0.1 * (x2 - x1)), 1); int yspace = MAX ((int) (0.5 + 0.1 * (y2 - y1)), 1); x1 += xspace; x2 -= xspace; y1 += yspace; y2 -= yspace; XFillRectangle (display, d, gc, x1, y1, x2 - x1, stroke_thick); XFillRectangle (display, d, gc, x1, y1 + stroke_thick, stroke_thick, y2 - y1 - 2 * stroke_thick); XFillRectangle (display, d, gc, x2 - stroke_thick, y1 + stroke_thick, stroke_thick, y2 - y1 - 2 * stroke_thick); XFillRectangle (display, d, gc, x1, y2 - stroke_thick, x2 - x1, stroke_thick); break; } } pango_font_metrics_unref (metrics); } next_glyph: x_off += glyphs->glyphs[i].geometry.width; } FLUSH;}#undef FLUSHstatic voidpango_x_font_get_glyph_extents (PangoFont *font, PangoGlyph glyph, PangoRectangle *ink_rect, PangoRectangle *logical_rect){ XCharStruct *cs; PangoXSubfontInfo *subfont; if (glyph == PANGO_GLYPH_EMPTY) { if (ink_rect) ink_rect->x = ink_rect->width = ink_rect->y = ink_rect->height = 0; if (logical_rect) logical_rect->x = logical_rect->width = logical_rect->y = logical_rect->height = 0; return; } if ((glyph & PANGO_GLYPH_UNKNOWN_FLAG) == 0 && pango_x_find_glyph (font, glyph, &subfont, &cs)) { if (ink_rect) { ink_rect->x = PANGO_SCALE * cs->lbearing; ink_rect->width = PANGO_SCALE * (cs->rbearing - cs->lbearing); ink_rect->y = PANGO_SCALE * -cs->ascent; ink_rect->height = PANGO_SCALE * (cs->ascent + cs->descent); } if (logical_rect) { logical_rect->x = 0; logical_rect->width = PANGO_SCALE * cs->width; logical_rect->y = - PANGO_SCALE * subfont->font_struct->ascent; logical_rect->height = PANGO_SCALE * (subfont->font_struct->ascent + subfont->font_struct->descent); } } else { PangoFontMetrics *metrics; gunichar wc; gdouble width_factor; int w; if (glyph & PANGO_GLYPH_UNKNOWN_FLAG) wc = glyph & (~PANGO_GLYPH_UNKNOWN_FLAG); else wc = 0; switch (wc) { case '\n': case '\r': case 0x2028: /* Line separator */ case 0x2029: /* Paragraph separator */ {#define MAGIC_FACTOR 1.2 /* carriage-return thingy */ width_factor = MAGIC_FACTOR; break; } default: { /* Unknown glyph square */ width_factor = 1.0; } } metrics = pango_font_get_metrics (font, NULL); if (metrics) { w = metrics->approximate_char_width * width_factor; w = PANGO_SCALE * PANGO_PIXELS (w); if (ink_rect) { ink_rect->x = PANGO_SCALE; ink_rect->width = w - 2 * PANGO_SCALE; ink_rect->y = - (metrics->ascent - PANGO_SCALE); ink_rect->height = metrics->ascent + metrics->descent - 2 * PANGO_SCALE; } if (logical_rect) { logical_rect->x = 0; logical_rect->width = w; logical_rect->y = - metrics->ascent; logical_rect->height = metrics->ascent + metrics->descent; } pango_font_metrics_unref (metrics); } else { if (ink_rect) ink_rect->x = ink_rect->y = ink_rect->height = ink_rect->width = 0; if (logical_rect) logical_rect->x = logical_rect->y = logical_rect->height = logical_rect->width = 0; } }}static gbooleanget_int_prop (Atom atom, XFontStruct *fs, int *val){ int i; *val = 0; i = 0; while (i < fs->n_properties) { if (fs->properties[i].name == atom) { *val = fs->properties[i].card32; return TRUE; } ++i; } return FALSE;}/* Call @func with each glyph resulting from shaping @string with each * glyph. This duplicates quite a bit of code from pango_itemize. This * function should die and we should simply add the ability to specify * particular fonts when itemizing. */static voiditemize_string_foreach (PangoFont *font, PangoLanguage *language, const char *str, void (*func) (PangoFont *font, PangoGlyphInfo *glyph_info, gpointer data), gpointer data){ const char *start, *p; PangoGlyphString *glyph_str = pango_glyph_string_new (); PangoEngineShape *shaper, *last_shaper; int last_level; int i; guint8 *embedding_levels; PangoDirection base_dir = PANGO_DIRECTION_LTR; gboolean finished = FALSE; embedding_levels = pango_log2vis_get_embedding_levels (str, -1, &base_dir); last_shaper = NULL; last_level = 0; i = 0; p = start = str; while (*p || !finished) { gunichar wc; if (*p) { wc = g_utf8_get_char (p); shaper = pango_font_find_shaper (font, language, wc); } else { finished = TRUE; shaper = NULL; } if (p > start && (finished || (shaper != last_shaper || last_level != embedding_levels[i]))) { PangoAnalysis analysis; int j; analysis.shape_engine = last_shaper; analysis.lang_engine = NULL; analysis.font = font; analysis.language = language; analysis.level = last_level; analysis.extra_attrs = NULL; pango_shape (start, p - start, &analysis, glyph_str); for (j = 0; j < glyph_str->num_glyphs; j++) (*func) (font, &glyph_str->glyphs[j], data); start = p; } if (!finished) { p = g_utf8_next_char (p); last_shaper = shaper; last_level = embedding_levels[i]; i++; } } pango_glyph_string_free (glyph_str); g_free (embedding_levels);}/* Get composite font metrics for all subfonts in list */static voidget_font_metrics_from_subfonts (PangoFont *font, GSList *subfonts, PangoFontMetrics *metrics){ PangoXFont *xfont = (PangoXFont *)font; GSList *tmp_list = subfonts; gboolean first = TRUE; int total_avg_widths = 0; int n_avg_widths = 0; Atom avg_width_atom; avg_width_atom = pango_x_fontmap_atom_from_name (xfont->fontmap, "AVERAGE_WIDTH"); metrics->ascent = 0; metrics->descent = 0; while (tmp_list) { PangoXSubfontInfo *subfont = pango_x_find_subfont (font, GPOINTER_TO_UINT (tmp_list->data)); if (subfont) { XFontStruct *fs = pango_x_get_font_struct (font, subfont); gint avg_width = 0; if (fs) { if (first) { metrics->ascent = fs->ascent * PANGO_SCALE; metrics->descent = fs->descent * PANGO_SCALE; first = FALSE; } else { metrics->ascent = MAX (fs->ascent * PANGO_SCALE, metrics->ascent); metrics->descent = MAX (fs->descent * PANGO_SCALE, metrics->descent); } if (get_int_prop (avg_width_atom, fs, &avg_width)) { /* convert decipoints --> Pango units. * Resolution is in (points * PANGO_SCALE) / pixel, * avg_width in decipoints. * We want pixels * PANGO_SCALE */ /* Convert to points * PANGO_SCALE */ avg_width *= PANGO_SCALE / (double) 10.0; /* Convert to pixels * PANGO_SCALE */ avg_width *= (PANGO_SCALE / PANGO_X_FONT_MAP (PANGO_X_FONT (font)->fontmap)->resolution); } else { avg_width = PANGO_SCALE * ((fs->min_bounds.width + fs->max_bounds.width) / 2); } } if (avg_width) { total_avg_widths += avg_width; n_avg_widths += 1; } } else g_warning ("Invalid subfont %d in get_font_metrics_from_subfonts", GPOINTER_TO_UINT (tmp_list->data)); tmp_list = tmp_list->next; } /* This is pretty darn bogus. */ if (n_avg_widths) metrics->approximate_char_width = total_avg_widths / n_avg_widths; else metrics->approximate_char_width = PANGO_UNKNOWN_GLYPH_WIDTH * PANGO_SCALE; if (metrics->ascent + metrics->descent == 0) { metrics->ascent = PANGO_UNKNOWN_GLYPH_HEIGHT * PANGO_SCALE; metrics->descent = 0; }}static voidget_subfonts_foreach (PangoFont *font, PangoGlyphInfo *glyph_info, gpointer data){ GSList **subfonts = data; PangoGlyph glyph = glyph_info->glyph; PangoXSubfont subfont; if (glyph == PANGO_GLYPH_EMPTY) return; /* Use an arbitrary subfont for unknown glyphs...*/ if (glyph & PANGO_GLYPH_UNKNOWN_FLAG) { if (((PangoXFont *)font)->n_subfonts > 0) glyph = PANGO_X_MAKE_GLYPH (1, 0); else return; } subfont = PANGO_X_GLYPH_SUBFONT (glyph); if (!g_slist_find (*subfonts, GUINT_TO_POINTER ((guint)subfont))) *subfonts = g_slist_prepend (*subfonts, GUINT_TO_POINTER ((guint)subfont));}/* Get composite font metrics for all subfonts resulting from shaping * string str with the given font */static voidget_font_metrics_from_string (PangoFont *font, PangoLanguage *language,
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -