📄 pangoft2-render.c
字号:
/* Pango * pangoft2-render.c: Rendering routines to FT_Bitmap objects * * Copyright (C) 2004 Red Hat Software * Copyright (C) 2000 Tor Lillqvist * * 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 <math.h>#include "pangoft2-private.h"/* for compatibility with older freetype versions */#ifndef FT_LOAD_TARGET_MONO#define FT_LOAD_TARGET_MONO FT_LOAD_MONOCHROME#endiftypedef struct _PangoFT2RendererClass PangoFT2RendererClass;#define PANGO_FT2_RENDERER_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), PANGO_TYPE_FT2_RENDERER, PangoFT2RendererClass))#define PANGO_IS_FT2_RENDERER_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), PANGO_TYPE_FT2_RENDERER))#define PANGO_FT2_RENDERER_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), PANGO_TYPE_FT2_RENDERER, PangoFT2RendererClass))struct _PangoFT2Renderer{ PangoRenderer parent_instance; FT_Bitmap *bitmap;};struct _PangoFT2RendererClass{ PangoRendererClass parent_class;};static void pango_ft2_renderer_draw_glyph (PangoRenderer *renderer, PangoFont *font, PangoGlyph glyph, double x, double y);static void pango_ft2_renderer_draw_trapezoid (PangoRenderer *renderer, PangoRenderPart part, double y1, double x11, double x21, double y2, double x12, double x22);G_DEFINE_TYPE (PangoFT2Renderer, pango_ft2_renderer, PANGO_TYPE_RENDERER)static voidpango_ft2_renderer_init (PangoFT2Renderer *renderer){}static voidpango_ft2_renderer_class_init (PangoFT2RendererClass *klass){ PangoRendererClass *renderer_class = PANGO_RENDERER_CLASS (klass); renderer_class->draw_glyph = pango_ft2_renderer_draw_glyph; renderer_class->draw_trapezoid = pango_ft2_renderer_draw_trapezoid;}static voidpango_ft2_renderer_set_bitmap (PangoFT2Renderer *renderer, FT_Bitmap *bitmap){ renderer->bitmap = bitmap;}typedef struct{ FT_Bitmap bitmap; int bitmap_left; int bitmap_top;} PangoFT2RenderedGlyph;static voidpango_ft2_free_rendered_glyph (PangoFT2RenderedGlyph *rendered){ g_free (rendered->bitmap.buffer); g_slice_free (PangoFT2RenderedGlyph, rendered);}static PangoFT2RenderedGlyph *pango_ft2_font_render_box_glyph (int width, int height, int top){ PangoFT2RenderedGlyph *box; int i, j, offset1, offset2, line_width; line_width = MAX ((height + 43) / 44, 1); if (width < 1 || height < 1) line_width = 0; box = g_slice_new (PangoFT2RenderedGlyph); box->bitmap_left = 0; box->bitmap_top = top; box->bitmap.pixel_mode = ft_pixel_mode_grays; box->bitmap.width = width; box->bitmap.rows = height; box->bitmap.pitch = height; box->bitmap.buffer = g_malloc0 (box->bitmap.rows * box->bitmap.pitch); /* draw the box */ for (j = 0; j < line_width; j++) { offset1 = box->bitmap.pitch * (MIN (1 + j, height - 1)); offset2 = box->bitmap.pitch * (MAX (box->bitmap.rows - 2 - j, 0)); for (i = 1; i < box->bitmap.width - 1; i++) { box->bitmap.buffer[offset1 + i] = 0xff; box->bitmap.buffer[offset2 + i] = 0xff; } } for (j = 0; j < line_width; j++) { offset1 = MIN (1 + j, width - 1); offset2 = MAX (box->bitmap.width - 2 - j, 0); for (i = box->bitmap.pitch; i < (box->bitmap.rows - 1) * box->bitmap.pitch; i += box->bitmap.pitch) { box->bitmap.buffer[offset1 + i] = 0xff; box->bitmap.buffer[offset2 + i] = 0xff; } } return box;}static PangoFT2RenderedGlyph *pango_ft2_font_render_glyph (PangoFont *font, int glyph_index){ FT_Face face; if (glyph_index & PANGO_GLYPH_UNKNOWN_FLAG) { PangoFT2RenderedGlyph *box; PangoFontMetrics *metrics; if (!font) goto generic_box; metrics = pango_font_get_metrics (font, NULL); if (!metrics) goto generic_box; box = pango_ft2_font_render_box_glyph (PANGO_PIXELS (metrics->approximate_char_width), PANGO_PIXELS (metrics->ascent + metrics->descent), PANGO_PIXELS (metrics->ascent)); pango_font_metrics_unref (metrics); return box; } face = pango_ft2_font_get_face (font); if (face) { PangoFT2RenderedGlyph *rendered; PangoFT2Font *ft2font = (PangoFT2Font *) font; rendered = g_slice_new (PangoFT2RenderedGlyph); /* Draw glyph */ FT_Load_Glyph (face, glyph_index, ft2font->load_flags); FT_Render_Glyph (face->glyph, (ft2font->load_flags & FT_LOAD_TARGET_MONO ? ft_render_mode_mono : ft_render_mode_normal)); rendered->bitmap = face->glyph->bitmap; rendered->bitmap.buffer = g_memdup (face->glyph->bitmap.buffer, face->glyph->bitmap.rows * face->glyph->bitmap.pitch); rendered->bitmap_left = face->glyph->bitmap_left; rendered->bitmap_top = face->glyph->bitmap_top; return rendered; } else {generic_box: return pango_ft2_font_render_box_glyph (PANGO_UNKNOWN_GLYPH_WIDTH, PANGO_UNKNOWN_GLYPH_HEIGHT, PANGO_UNKNOWN_GLYPH_HEIGHT); }}static voidpango_ft2_renderer_draw_glyph (PangoRenderer *renderer, PangoFont *font, PangoGlyph glyph, double x, double y){ FT_Bitmap *bitmap = PANGO_FT2_RENDERER (renderer)->bitmap; PangoFT2RenderedGlyph *rendered_glyph; gboolean add_glyph_to_cache; guchar *src, *dest; int x_start, x_limit; int y_start, y_limit; int ixoff = floor (x + 0.5); int iyoff = floor (y + 0.5); int ix, iy; if (glyph & PANGO_GLYPH_UNKNOWN_FLAG) { glyph = pango_ft2_get_unknown_glyph (font); if (glyph == PANGO_GLYPH_EMPTY) { /* No unknown glyph found for the font, draw a box */ /* Since we only draw an empty box for FT2 renderer, * we unify the rendered bitmaps in the cache. */ glyph = PANGO_GLYPH_UNKNOWN_FLAG; } } rendered_glyph = _pango_ft2_font_get_cache_glyph_data (font, glyph); add_glyph_to_cache = FALSE; if (rendered_glyph == NULL) { rendered_glyph = pango_ft2_font_render_glyph (font, glyph); add_glyph_to_cache = TRUE; } x_start = MAX (0, - (ixoff + rendered_glyph->bitmap_left)); x_limit = MIN (rendered_glyph->bitmap.width, bitmap->width - (ixoff + rendered_glyph->bitmap_left)); y_start = MAX (0, - (iyoff - rendered_glyph->bitmap_top)); y_limit = MIN (rendered_glyph->bitmap.rows, bitmap->rows - (iyoff - rendered_glyph->bitmap_top)); src = rendered_glyph->bitmap.buffer + y_start * rendered_glyph->bitmap.pitch; dest = bitmap->buffer + (y_start + iyoff - rendered_glyph->bitmap_top) * bitmap->pitch + x_start + ixoff + rendered_glyph->bitmap_left; switch (rendered_glyph->bitmap.pixel_mode) { case ft_pixel_mode_grays: src += x_start; for (iy = y_start; iy < y_limit; iy++) { guchar *s = src; guchar *d = dest; for (ix = x_start; ix < x_limit; ix++) { switch (*s) { case 0: break; case 0xff: *d = 0xff; default: *d = MIN ((gushort) *d + (gushort) *s, 0xff); break; } s++; d++; } dest += bitmap->pitch; src += rendered_glyph->bitmap.pitch; } break; case ft_pixel_mode_mono: src += x_start / 8; for (iy = y_start; iy < y_limit; iy++) { guchar *s = src; guchar *d = dest; for (ix = x_start; ix < x_limit; ix++) { if ((*s) & (1 << (7 - (ix % 8)))) *d |= 0xff; if ((ix % 8) == 7) s++; d++; } dest += bitmap->pitch; src += rendered_glyph->bitmap.pitch; } break; default: g_warning ("pango_ft2_render: " "Unrecognized glyph bitmap pixel mode %d\n", rendered_glyph->bitmap.pixel_mode); break; } if (add_glyph_to_cache) { _pango_ft2_font_set_glyph_cache_destroy (font, (GDestroyNotify) pango_ft2_free_rendered_glyph); _pango_ft2_font_set_cache_glyph_data (font, glyph, rendered_glyph); }}typedef struct { double y; double x1; double x2;} Position;static voiddraw_simple_trap (PangoRenderer *renderer, Position *t, Position *b){ FT_Bitmap *bitmap = PANGO_FT2_RENDERER (renderer)->bitmap; int iy = floor (t->y); int x1, x2, x; double dy = b->y - t->y; guchar *dest; if (iy < 0 || iy >= bitmap->rows) return;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -