📄 pango-renderer.c
字号:
**/voidpango_renderer_draw_layout_line (PangoRenderer *renderer, PangoLayoutLine *line, int x, int y){ int x_off = 0; int glyph_string_width; LineState state; GSList *l; gboolean got_overall = FALSE; PangoRectangle overall_rect; g_return_if_fail (PANGO_IS_RENDERER_FAST (renderer)); /* We only change the matrix if the renderer isn't already * active. */ if (!renderer->active_count) { PangoContext *context = pango_layout_get_context (line->layout); pango_renderer_set_matrix (renderer, pango_context_get_matrix (context)); } pango_renderer_activate (renderer); renderer->priv->line = line; renderer->priv->line_state = &state; state.underline = PANGO_UNDERLINE_NONE; state.strikethrough = FALSE; for (l = line->runs; l; l = l->next) { PangoFontMetrics *metrics; gint rise; PangoLayoutRun *run = l->data; PangoAttrShape *shape_attr; PangoRectangle ink_rect, *ink = NULL; PangoRectangle logical_rect, *logical = NULL; if (run->item->analysis.flags & PANGO_ANALYSIS_FLAG_CENTERED_BASELINE) logical = &logical_rect; pango_renderer_prepare_run (renderer, run); get_item_properties (run->item, &rise, &shape_attr); if (shape_attr) { ink = &ink_rect; logical = &logical_rect; _pango_shape_get_extents (run->glyphs->num_glyphs, &shape_attr->ink_rect, &shape_attr->logical_rect, ink, logical); glyph_string_width = logical->width; } else { if (renderer->underline != PANGO_UNDERLINE_NONE || renderer->strikethrough) { ink = &ink_rect; logical = &logical_rect; } if (G_UNLIKELY (ink || logical)) pango_glyph_string_extents (run->glyphs, run->item->analysis.font, ink, logical); if (logical) glyph_string_width = logical_rect.width; else glyph_string_width = pango_glyph_string_get_width (run->glyphs); } state.logical_rect_end = x + x_off + glyph_string_width; if (run->item->analysis.flags & PANGO_ANALYSIS_FLAG_CENTERED_BASELINE) { gboolean is_hinted = ((logical_rect.y | logical_rect.height) & (PANGO_SCALE - 1)) == 0; int adjustment = logical_rect.y + logical_rect.height / 2; if (is_hinted) adjustment = PANGO_UNITS_ROUND (adjustment); rise += adjustment; } if (renderer->priv->color_set[PANGO_RENDER_PART_BACKGROUND]) { if (!got_overall) { pango_layout_line_get_extents (line, NULL, &overall_rect); got_overall = TRUE; } pango_renderer_draw_rectangle (renderer, PANGO_RENDER_PART_BACKGROUND, x + x_off, y + overall_rect.y, glyph_string_width, overall_rect.height); } if (shape_attr) { draw_shaped_glyphs (renderer, run->glyphs, shape_attr, x + x_off, y - rise); } else { pango_renderer_draw_glyphs (renderer, run->item->analysis.font, run->glyphs, x + x_off, y - rise); } if (renderer->underline != PANGO_UNDERLINE_NONE || renderer->strikethrough) { metrics = pango_font_get_metrics (run->item->analysis.font, run->item->analysis.language); if (renderer->underline != PANGO_UNDERLINE_NONE) add_underline (renderer, &state,metrics, x + x_off, y - rise, ink, logical); if (renderer->strikethrough) add_strikethrough (renderer, &state, metrics, x + x_off, y - rise, ink, logical); pango_font_metrics_unref (metrics); } if (renderer->underline == PANGO_UNDERLINE_NONE && state.underline != PANGO_UNDERLINE_NONE) draw_underline (renderer, &state); if (!renderer->strikethrough && state.strikethrough) draw_strikethrough (renderer, &state); x_off += glyph_string_width; } /* Finish off any remaining underlines */ draw_underline (renderer, &state); draw_strikethrough (renderer, &state); renderer->priv->line_state = NULL; renderer->priv->line = NULL; pango_renderer_deactivate (renderer);}/** * pango_renderer_draw_glyphs: * @renderer: a #PangoRenderer * @font: a #PangoFont * @glyphs: a #PangoGlyphString * @x: X position of left edge of baseline, in user space coordinates * in Pango units. * @y: Y position of left edge of baseline, in user space coordinates * in Pango units. * * Draws the glyphs in @glyphs with the specified #PangoRenderer. * * Since: 1.8 **/voidpango_renderer_draw_glyphs (PangoRenderer *renderer, PangoFont *font, PangoGlyphString *glyphs, int x, int y){ g_return_if_fail (PANGO_IS_RENDERER_FAST (renderer)); pango_renderer_activate (renderer); PANGO_RENDERER_GET_CLASS (renderer)->draw_glyphs (renderer, font, glyphs, x, y); pango_renderer_deactivate (renderer);}static voidpango_renderer_default_draw_glyphs (PangoRenderer *renderer, PangoFont *font, PangoGlyphString *glyphs, int x, int y){ int i; int x_position = 0; for (i = 0; i < glyphs->num_glyphs; i++) { PangoGlyphInfo *gi = &glyphs->glyphs[i]; Point p; to_device (renderer->matrix, x + x_position + gi->geometry.x_offset, y + gi->geometry.y_offset, &p); pango_renderer_draw_glyph (renderer, font, gi->glyph, p.x, p.y); x_position += gi->geometry.width; }}/** * pango_renderer_draw_rectangle: * @renderer: a #PangoRenderer * @part: type of object this rectangle is part of * @x: X position at which to draw rectangle, in user space coordinates in Pango units * @y: Y position at which to draw rectangle, in user space coordinates in Pango units * @width: width of rectangle in Pango units in user space coordinates * @height: height of rectangle in Pango units in user space coordinates * * Draws an axis-aligned rectangle in user space coordinates with the * specified #PangoRenderer. * * This should be called while @renderer is already active. Use * pango_renderer_activate() to activate a renderer. * * Since: 1.8 **/voidpango_renderer_draw_rectangle (PangoRenderer *renderer, PangoRenderPart part, int x, int y, int width, int height){ g_return_if_fail (PANGO_IS_RENDERER_FAST (renderer)); g_return_if_fail (IS_VALID_PART (part)); g_return_if_fail (renderer->active_count > 0); PANGO_RENDERER_GET_CLASS (renderer)->draw_rectangle (renderer, part, x, y, width, height);}static intcompare_points (const void *a, const void *b){ const Point *pa = a; const Point *pb = b; if (pa->y < pb->y) return -1; else if (pa->y > pb->y) return 1; else if (pa->x < pb->x) return -1; else if (pa->x > pb->x) return 1; else return 0;}static voiddraw_rectangle (PangoRenderer *renderer, PangoMatrix *matrix, PangoRenderPart part, int x, int y, int width, int height){ Point points[4]; /* Convert the points to device coordinates, and sort * in ascending Y order. (Ordering by X for ties) */ to_device (matrix, x, y, &points[0]); to_device (matrix, x + width, y, &points[1]); to_device (matrix, x, y + height, &points[2]); to_device (matrix, x + width, y + height, &points[3]); qsort (points, 4, sizeof (Point), compare_points); /* There are essentially three cases. (There is a fourth * case where trapezoid B is degenerate and we just have * two triangles, but we don't need to handle it separately.) * * 1 2 3 * * ______ /\ /\ * / / /A \ /A \ * / B / /____\ /____\ * /_____/ / B / \ B \ * /_____/ \_____\ * \ C / \ C / * \ / \ / * \/ \/ */ if (points[0].y == points[1].y) { /* Case 1 (pure shear) */ pango_renderer_draw_trapezoid (renderer, part, /* B */ points[0].y, points[0].x, points[1].x, points[2].y, points[2].x, points[3].x); } else if (points[1].x < points[2].x) { /* Case 2 */ double tmp_width = ((points[2].x - points[0].x) * (points[1].y - points[0].y)) / (points[2].y - points[0].y); double base_width = tmp_width + points[0].x - points[1].x; pango_renderer_draw_trapezoid (renderer, part, /* A */ points[0].y, points[0].x, points[0].x, points[1].y, points[1].x, points[1].x + base_width); pango_renderer_draw_trapezoid (renderer, part, /* B */ points[1].y, points[1].x, points[1].x + base_width, points[2].y, points[2].x - base_width, points[2].x); pango_renderer_draw_trapezoid (renderer, part, /* C */ points[2].y, points[2].x - base_width, points[2].x, points[3].y, points[3].x, points[3].x); } else { /* case 3 */ double tmp_width = ((points[0].x - points[2].x) * (points[1].y - points[0].y)) / (points[2].y - points[0].y); double base_width = tmp_width + points[1].x - points[0].x; pango_renderer_draw_trapezoid (renderer, part, /* A */ points[0].y, points[0].x, points[0].x, points[1].y, points[1].x - base_width, points[1].x); pango_renderer_draw_trapezoid (renderer, part, /* B */ points[1].y, points[1].x - base_width, points[1].x, points[2].y, points[2].x, points[2].x + base_width); pango_renderer_draw_trapezoid (renderer, part, /* C */ points[2].y, points[2].x, points[2].x + base_width, points[3].y, points[3].x, points[3].x); }}static voidpango_renderer_default_draw_rectangle (PangoRenderer *renderer, PangoRenderPart part, int x, int y, int width, int height){ draw_rectangle (renderer, renderer->matrix, part, x, y, width, height);}/** * pango_renderer_draw_error_underline: * @renderer: a #PangoRenderer * @x: X coordinate of underline, in Pango units in user coordinate system * @y: Y coordinate of underline, in Pango units in user coordinate system * @width: width of underline, in Pango units in user coordinate system * @height: height of underline, in Pango units in user coordinate system * * Draw a squiggly line that approximately covers the given rectangle * in the style of an underline used to indicate a spelling error. * (The width of the underline is rounded to an integer number * of up/down segments and the resulting rectangle is centered * in the original rectangle) * * This should be called while @renderer is already active. Use * pango_renderer_activate() to activate a renderer. * * Since: 1.8 **/voidpango_renderer_draw_error_underline (PangoRenderer *renderer, int x, int y, int width, int height){ g_return_if_fail (PANGO_IS_RENDERER_FAST (renderer)); g_return_if_fail (renderer->active_count > 0); PANGO_RENDERER_GET_CLASS (renderer)->draw_error_underline (renderer, x, y, width, height);}/* We are drawing an error underline that looks like one of: * * /\ /\ /\ /\ /\ - * / \ / \ / \ / \ / \ | * \ \ /\ \ / / \ \ /\ \ | * \ \/B \ \/ C / \ \/B \ \ | height = HEIGHT_SQUARES * square * \ A \ /\ A \ / \ A \ /\ A \ | * \ \/ \ \/ \ \/ \ \ | * \ / \ / \ / \ / | * \/ \/ \/ \/ - * |---| * unit_width = (HEIGHT_SQUARES - 1) * square * * To do this conveniently, we work in a coordinate system where A,B,C * are axis aligned rectangles. (If fonts were square, the diagrams * would be clearer) * * (0,0) * /\ /\ * / \ / \ * /\ /\ /\ / * / \/ \/ \/ * / \ /\ / * Y axis \/ \/ * \ /\ * \/ \ * \ X axis * * Note that the long side in this coordinate system is HEIGHT_SQUARES + 1 * units long * * The diagrams above are shown with HEIGHT_SQUARES an integer, but * that is actually incidental; the value 2.5 below seems better than * either HEIGHT_SQUARES=3 (a little long and skinny) or * HEIGHT_SQUARES=2 (a bit short and stubby) */#define HEIGHT_SQUARES 2.5static voidget_total_matrix (PangoMatrix *total, const PangoMatrix *global, int x, int y, int square){ PangoMatrix local; gdouble scale = 0.5 * square; /* The local matrix translates from the axis aligned coordinate system * to the original user space coordinate system. */ local.xx = scale; local.xy = - scale; local.yx = scale; local.yy = scale; local.x0 = 0; local.y0 = 0;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -