📄 viewer-render.c
字号:
/* viewer-render.c: Common code for rendering in viewers * * Copyright (C) 1999, 2004 Red Hat Software * Copyright (C) 2001 Sun Microsystems * * 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 <errno.h>#include <math.h>#include <stdarg.h>#include <stdlib.h>#include <stdio.h>#include <string.h>#include <glib.h>#include <glib/gprintf.h>#include <pango/pango.h>#include "viewer-render.h"#define DEFAULT_FONT_FAMILY "Sans"#define DEFAULT_FONT_SIZE 18#define _MAKE_FONT_NAME(family, size) family " " #size#define MAKE_FONT_NAME(family, size) _MAKE_FONT_NAME(family, size)const char *prog_name;gboolean opt_display = TRUE;int opt_dpi = 96;const char *opt_font = MAKE_FONT_NAME (DEFAULT_FONT_FAMILY, DEFAULT_FONT_SIZE);gboolean opt_header = FALSE;const char *opt_output = NULL;int opt_margin = 10;int opt_markup = FALSE;gboolean opt_rtl = FALSE;double opt_rotate = 0;gboolean opt_auto_dir = TRUE;const char *opt_text = NULL;gboolean opt_waterfall = FALSE;int opt_width = -1;int opt_indent = 0;int opt_runs = 1;PangoEllipsizeMode opt_ellipsize = PANGO_ELLIPSIZE_NONE;PangoGravity opt_gravity = PANGO_GRAVITY_SOUTH;PangoGravityHint opt_gravity_hint = PANGO_GRAVITY_HINT_NATURAL;HintMode opt_hinting = HINT_DEFAULT;PangoWrapMode opt_wrap = PANGO_WRAP_WORD_CHAR;gboolean opt_wrap_set = FALSE;const char *opt_pangorc = NULL;const PangoViewer *opt_viewer = NULL;/* Text (or markup) to render */static char *text;voidfail (const char *format, ...){ const char *msg; va_list vap; va_start (vap, format); msg = g_strdup_vprintf (format, vap); g_printerr ("%s: %s\n", prog_name, msg); exit (1);}static PangoFontDescription *get_font_description (void){ PangoFontDescription *font_description = pango_font_description_from_string (opt_font); if ((pango_font_description_get_set_fields (font_description) & PANGO_FONT_MASK_FAMILY) == 0) pango_font_description_set_family (font_description, DEFAULT_FONT_FAMILY); if ((pango_font_description_get_set_fields (font_description) & PANGO_FONT_MASK_SIZE) == 0) pango_font_description_set_size (font_description, DEFAULT_FONT_SIZE * PANGO_SCALE); return font_description;}static PangoLayout *make_layout(PangoContext *context, const char *text, double size){ static PangoFontDescription *font_description; PangoDirection base_dir; PangoLayout *layout; layout = pango_layout_new (context); if (opt_markup) pango_layout_set_markup (layout, text, -1); else pango_layout_set_text (layout, text, -1); pango_layout_set_auto_dir (layout, opt_auto_dir); pango_layout_set_ellipsize (layout, opt_ellipsize); font_description = get_font_description (); if (size > 0) pango_font_description_set_size (font_description, size * PANGO_SCALE); if (opt_width > 0) { pango_layout_set_wrap (layout, opt_wrap); pango_layout_set_width (layout, (opt_width * opt_dpi * PANGO_SCALE + 36) / 72); } if (opt_indent != 0) pango_layout_set_indent (layout, (opt_indent * opt_dpi * PANGO_SCALE + 36) / 72); base_dir = pango_context_get_base_dir (context); pango_layout_set_alignment (layout, base_dir == PANGO_DIRECTION_LTR ? PANGO_ALIGN_LEFT : PANGO_ALIGN_RIGHT); pango_layout_set_font_description (layout, font_description); pango_font_description_free (font_description); return layout;}gchar *get_options_string (void){ PangoFontDescription *font_description = get_font_description (); gchar *font_name; gchar *result; if (opt_waterfall) pango_font_description_unset_fields (font_description, PANGO_FONT_MASK_SIZE); font_name = pango_font_description_to_string (font_description); result = g_strdup_printf ("%s: %s (%d dpi)", opt_viewer->name, font_name, opt_dpi); pango_font_description_free (font_description); g_free (font_name); return result;}static voidoutput_body (PangoContext *context, const char *text, RenderCallback render_cb, gpointer cb_context, gpointer cb_data, int *width, int *height, gboolean supports_matrix){ PangoLayout *layout; PangoRectangle logical_rect; int size, start_size, end_size, increment; int x = 0, y = 0; if (!supports_matrix) { const PangoMatrix* matrix; const PangoMatrix identity = PANGO_MATRIX_INIT; matrix = pango_context_get_matrix (context); if (matrix) { x += matrix->x0; y += matrix->y0; } pango_context_set_matrix (context, &identity); } if (opt_waterfall) { start_size = 8; end_size = 48; increment = 4; } else { start_size = end_size = -1; increment = 1; } *width = 0; *height = 0; for (size = start_size; size <= end_size; size += increment) { layout = make_layout (context, text, size); pango_layout_get_extents (layout, NULL, &logical_rect); if (render_cb) (*render_cb) (layout, x, y+*height, cb_context, cb_data); *width = MAX (*width, PANGO_PIXELS (logical_rect.x + logical_rect.width)); *width = MAX (*width, PANGO_PIXELS (pango_layout_get_width (layout))); *height += PANGO_PIXELS (logical_rect.height); g_object_unref (layout); }}static voidset_transform (PangoContext *context, TransformCallback transform_cb, gpointer cb_context, gpointer cb_data, PangoMatrix *matrix){ pango_context_set_matrix (context, matrix); if (transform_cb) (*transform_cb) (context, matrix, cb_context, cb_data);}voiddo_output (PangoContext *context, RenderCallback render_cb, TransformCallback transform_cb, gpointer cb_context, gpointer cb_data, int *width_out, int *height_out){ PangoLayout *layout; PangoRectangle rect; PangoMatrix matrix = PANGO_MATRIX_INIT; PangoMatrix *orig_matrix; gboolean supports_matrix; int rotated_width, rotated_height; int x = opt_margin; int y = opt_margin; int width, height; width = 0; height = 0; orig_matrix = pango_matrix_copy (pango_context_get_matrix (context)); /* If the backend sets an all-zero matrix on the context, * means that it doesn't support transformations. */ supports_matrix = !orig_matrix || (orig_matrix->xx != 0. || orig_matrix->xy != 0. || orig_matrix->yx != 0. || orig_matrix->yy != 0. || orig_matrix->x0 != 0. || orig_matrix->y0 != 0.); set_transform (context, transform_cb, cb_context, cb_data, NULL); pango_context_set_language (context, pango_language_get_default ()); pango_context_set_base_dir (context, opt_rtl ? PANGO_DIRECTION_RTL : PANGO_DIRECTION_LTR); if (opt_header) { char *options_string = get_options_string (); pango_context_set_base_gravity (context, PANGO_GRAVITY_SOUTH); layout = make_layout (context, options_string, 10); pango_layout_get_extents (layout, NULL, &rect); width = MAX (width, PANGO_PIXELS (rect.width)); height += PANGO_PIXELS (rect.height); if (render_cb) (*render_cb) (layout, x, y, cb_context, cb_data); y += PANGO_PIXELS (rect.height); g_object_unref (layout); g_free (options_string); } if (opt_rotate != 0) { if (supports_matrix) pango_matrix_rotate (&matrix, opt_rotate); else g_printerr ("The backend does not support rotated text\n"); } pango_context_set_base_gravity (context, opt_gravity); pango_context_set_gravity_hint (context, opt_gravity_hint); set_transform (context, transform_cb, cb_context, cb_data, &matrix); output_body (context, text, NULL, NULL, NULL, &rotated_width, &rotated_height, supports_matrix); rect.x = rect.y = 0; rect.width = rotated_width; rect.height = rotated_height; pango_matrix_transform_pixel_rectangle (&matrix, &rect); matrix.x0 = x - rect.x; matrix.y0 = y - rect.y; set_transform (context, transform_cb, cb_context, cb_data, &matrix); if (render_cb) output_body (context, text, render_cb, cb_context, cb_data, &rotated_width, &rotated_height, supports_matrix); width = MAX (width, rect.width); height += rect.height; width += 2 * opt_margin; height += 2 * opt_margin; if (width_out) *width_out = width; if (height_out) *height_out = height; pango_context_set_matrix (context, orig_matrix); pango_matrix_free (orig_matrix);}static gbooleanparse_enum (GType type, int *value, const char *name,
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -