📄 pango-renderer.c
字号:
/* Pango * pango-renderer.h: Base class for rendering * * Copyright (C) 2004 Red Hat, Inc. * * 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 <stdlib.h>#include "pango-renderer.h"#include "pango-impl-utils.h"#define N_RENDER_PARTS 4#define PANGO_IS_RENDERER_FAST(renderer) (renderer != NULL)#define IS_VALID_PART(part) ((guint)part < N_RENDER_PARTS)typedef struct _LineState LineState;typedef struct _Point Point;struct _Point{ double x, y;};struct _LineState{ PangoUnderline underline; PangoRectangle underline_rect; gboolean strikethrough; PangoRectangle strikethrough_rect; int logical_rect_end;};struct _PangoRendererPrivate{ PangoColor color[N_RENDER_PARTS]; gboolean color_set[N_RENDER_PARTS]; PangoLayoutLine *line; LineState *line_state;};static void pango_renderer_finalize (GObject *gobject);static void pango_renderer_default_draw_glyphs (PangoRenderer *renderer, PangoFont *font, PangoGlyphString *glyphs, int x, int y);static void pango_renderer_default_draw_rectangle (PangoRenderer *renderer, PangoRenderPart part, int x, int y, int width, int height);static void pango_renderer_default_draw_error_underline (PangoRenderer *renderer, int x, int y, int width, int height);static void pango_renderer_default_prepare_run (PangoRenderer *renderer, PangoLayoutRun *run);static void pango_renderer_prepare_run (PangoRenderer *renderer, PangoLayoutRun *run);static voidto_device (PangoMatrix *matrix, double x, double y, Point *result){ if (matrix) { result->x = (x * matrix->xx + y * matrix->xy) / PANGO_SCALE + matrix->x0; result->y = (x * matrix->yx + y * matrix->yy) / PANGO_SCALE + matrix->y0; } else { result->x = x / PANGO_SCALE; result->y = y / PANGO_SCALE; }}G_DEFINE_ABSTRACT_TYPE (PangoRenderer, pango_renderer, G_TYPE_OBJECT)static voidpango_renderer_class_init (PangoRendererClass *klass){ GObjectClass *gobject_class = G_OBJECT_CLASS (klass); klass->draw_glyphs = pango_renderer_default_draw_glyphs; klass->draw_rectangle = pango_renderer_default_draw_rectangle; klass->draw_error_underline = pango_renderer_default_draw_error_underline; klass->prepare_run = pango_renderer_default_prepare_run; gobject_class->finalize = pango_renderer_finalize; g_type_class_add_private (gobject_class, sizeof (PangoRendererPrivate));}static voidpango_renderer_init (PangoRenderer *renderer){ renderer->priv = G_TYPE_INSTANCE_GET_PRIVATE (renderer, PANGO_TYPE_RENDERER, PangoRendererPrivate); renderer->matrix = NULL;}static voidpango_renderer_finalize (GObject *gobject){ PangoRenderer *renderer = PANGO_RENDERER (gobject); if (renderer->matrix) pango_matrix_free (renderer->matrix);}/** * pango_renderer_draw_layout: * @renderer: a #PangoRenderer * @layout: a #PangoLayout * @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 @layout with the specified #PangoRenderer. * * Since: 1.8 **/voidpango_renderer_draw_layout (PangoRenderer *renderer, PangoLayout *layout, int x, int y){ PangoLayoutIter *iter; g_return_if_fail (PANGO_IS_RENDERER (renderer)); g_return_if_fail (PANGO_IS_LAYOUT (layout)); /* We only change the matrix if the renderer isn't already * active. */ if (!renderer->active_count) { PangoContext *context = pango_layout_get_context (layout); pango_renderer_set_matrix (renderer, pango_context_get_matrix (context)); } pango_renderer_activate (renderer); iter = pango_layout_get_iter (layout); do { PangoRectangle logical_rect; PangoLayoutLine *line; int baseline; line = pango_layout_iter_get_line_readonly (iter); pango_layout_iter_get_line_extents (iter, NULL, &logical_rect); baseline = pango_layout_iter_get_baseline (iter); pango_renderer_draw_layout_line (renderer, line, x + logical_rect.x, y + baseline); } while (pango_layout_iter_next_line (iter)); pango_layout_iter_free (iter); pango_renderer_deactivate (renderer);}static voiddraw_underline (PangoRenderer *renderer, LineState *state){ PangoRectangle *rect = &state->underline_rect; PangoUnderline underline = state->underline; state->underline = PANGO_UNDERLINE_NONE; switch (underline) { case PANGO_UNDERLINE_NONE: break; case PANGO_UNDERLINE_DOUBLE: pango_renderer_draw_rectangle (renderer, PANGO_RENDER_PART_UNDERLINE, rect->x, rect->y + 2 * rect->height, rect->width, rect->height); /* Fall through */ case PANGO_UNDERLINE_SINGLE: case PANGO_UNDERLINE_LOW: pango_renderer_draw_rectangle (renderer, PANGO_RENDER_PART_UNDERLINE, rect->x, rect->y, rect->width, rect->height); break; case PANGO_UNDERLINE_ERROR: pango_renderer_draw_error_underline (renderer, rect->x, rect->y, rect->width, 3 * rect->height); break; }}static voiddraw_strikethrough (PangoRenderer *renderer, LineState *state){ PangoRectangle *rect = &state->strikethrough_rect; gboolean strikethrough = state->strikethrough; state->strikethrough = FALSE; if (strikethrough) pango_renderer_draw_rectangle (renderer, PANGO_RENDER_PART_STRIKETHROUGH, rect->x, rect->y, rect->width, rect->height);}static voidhandle_line_state_change (PangoRenderer *renderer, PangoRenderPart part){ LineState *state = renderer->priv->line_state; if (!state) return; if (part == PANGO_RENDER_PART_UNDERLINE && state->underline != PANGO_UNDERLINE_NONE) { PangoRectangle *rect = &state->underline_rect; rect->width = state->logical_rect_end - rect->x; draw_underline (renderer, state); state->underline = renderer->underline; rect->x = state->logical_rect_end; rect->width = 0; } if (part == PANGO_RENDER_PART_STRIKETHROUGH && state->strikethrough) { PangoRectangle *rect = &state->strikethrough_rect; rect->width = state->logical_rect_end - rect->x; draw_strikethrough (renderer, state); state->strikethrough = renderer->strikethrough; rect->x = state->logical_rect_end; rect->width = 0; }}static voidadd_underline (PangoRenderer *renderer, LineState *state, PangoFontMetrics *metrics, int base_x, int base_y, PangoRectangle *ink_rect, PangoRectangle *logical_rect){ PangoRectangle *current_rect = &state->underline_rect; PangoRectangle new_rect; int underline_thickness = pango_font_metrics_get_underline_thickness (metrics); int underline_position = pango_font_metrics_get_underline_position (metrics); new_rect.x = base_x + logical_rect->x; new_rect.width = logical_rect->width; new_rect.height = underline_thickness; new_rect.y = base_y; switch (renderer->underline) { case PANGO_UNDERLINE_NONE: g_assert_not_reached (); break; case PANGO_UNDERLINE_SINGLE: case PANGO_UNDERLINE_DOUBLE: case PANGO_UNDERLINE_ERROR: new_rect.y -= underline_position; break; case PANGO_UNDERLINE_LOW: new_rect.y += ink_rect->y + ink_rect->height + underline_thickness; break; } if (renderer->underline == state->underline && new_rect.y == current_rect->y && new_rect.height == current_rect->height) { current_rect->width = new_rect.x + new_rect.width - current_rect->x; } else { draw_underline (renderer, state); *current_rect = new_rect; state->underline = renderer->underline; }}static voidadd_strikethrough (PangoRenderer *renderer, LineState *state, PangoFontMetrics *metrics, int base_x, int base_y, PangoRectangle *ink_rect, PangoRectangle *logical_rect){ PangoRectangle *current_rect = &state->strikethrough_rect; PangoRectangle new_rect; int strikethrough_thickness = pango_font_metrics_get_strikethrough_thickness (metrics); int strikethrough_position = pango_font_metrics_get_strikethrough_position (metrics); new_rect.x = base_x + logical_rect->x; new_rect.width = logical_rect->width; new_rect.y = base_y - strikethrough_position; new_rect.height = strikethrough_thickness; if (state->strikethrough && new_rect.y == current_rect->y && new_rect.height == current_rect->height) { current_rect->width = new_rect.x + new_rect.width - current_rect->x; } else { draw_strikethrough (renderer, state); *current_rect = new_rect; state->strikethrough = TRUE; }}static voidget_item_properties (PangoItem *item, gint *rise, PangoAttrShape **shape_attr){ GSList *l; if (rise) *rise = 0; if (shape_attr) *shape_attr = NULL; for (l = item->analysis.extra_attrs; l; l = l->next) { PangoAttribute *attr = l->data; switch (attr->klass->type) { case PANGO_ATTR_SHAPE: if (shape_attr) *shape_attr = (PangoAttrShape *)attr; break; case PANGO_ATTR_RISE: if (rise) *rise = ((PangoAttrInt *)attr)->value; break; default: break; } }}static voiddraw_shaped_glyphs (PangoRenderer *renderer, PangoGlyphString *glyphs, PangoAttrShape *attr, int x, int y){ PangoRendererClass *class = PANGO_RENDERER_GET_CLASS (renderer); int i; if (!class->draw_shape) return; for (i = 0; i < glyphs->num_glyphs; i++) { PangoGlyphInfo *gi = &glyphs->glyphs[i]; class->draw_shape (renderer, attr, x, y); x += gi->geometry.width; }}/** * pango_renderer_draw_layout_line: * @renderer: a #PangoRenderer * @line: a #PangoLayoutLine * @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 @line with the specified #PangoRenderer. * * Since: 1.8
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -