ViewVC Help
View File | Revision Log | Show Annotations | Download File
/cvs/deliantra/Deliantra-Client/pango-render.c
Revision: 1.5
Committed: Wed Jul 5 01:53:24 2006 UTC (17 years, 10 months ago) by root
Content type: text/plain
Branch: MAIN
CVS Tags: rel-0_2
Changes since 1.4: +2 -2 lines
Log Message:
minor fixes and improvements

File Contents

# User Rev Content
1 root 1.1 /* Pango
2     * Rendering routines to OpenGL
3     *
4     * Copyright (C) 2006 Marc Lehmann <pcg@goof.com>
5     * Copyright (C) 2004 Red Hat Software
6     * Copyright (C) 2000 Tor Lillqvist
7     *
8     * This file is free software; you can redistribute it and/or
9     * modify it under the terms of the GNU Library General Public
10     * License as published by the Free Software Foundation; either
11     * version 2 of the License, or (at your option) any later version.
12     *
13     * This file is distributed in the hope that it will be useful,
14     * but WITHOUT ANY WARRANTY; without even the implied warranty of
15     * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16     * Library General Public License for more details.
17     *
18     * You should have received a copy of the GNU Library General Public
19     * License along with this library; if not, write to the
20     * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
21     * Boston, MA 02111-1307, USA.
22     */
23    
24     #include <math.h>
25    
26     #include "pangoopengl.h"
27    
28     #define PANGO_OPENGL_RENDERER_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), PANGO_TYPE_OPENGL_RENDERER, PangoOpenGLRendererClass))
29     #define PANGO_IS_OPENGL_RENDERER_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), PANGO_TYPE_OPENGL_RENDERER))
30     #define PANGO_OPENGL_RENDERER_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), PANGO_TYPE_OPENGL_RENDERER, PangoOpenGLRendererClass))
31    
32     typedef struct {
33     PangoRendererClass parent_class;
34     } PangoOpenGLRendererClass;
35    
36     struct _PangoOpenGLRenderer
37     {
38     PangoRenderer parent_instance;
39     float r, g, b, a; // modulate
40     GLuint curtex; // current texture
41     };
42    
43     G_DEFINE_TYPE (PangoOpenGLRenderer, pango_opengl_renderer, PANGO_TYPE_RENDERER)
44    
45     typedef struct
46     {
47     uint8_t *bitmap;
48     int width, stride, height, top, left;
49     } Glyph;
50    
51     static void *
52     temp_buffer (size_t size)
53     {
54     static char *buffer;
55     static size_t alloc;
56    
57     if (size > alloc)
58     {
59     size = (size + 4095) & ~4095;
60     free (buffer);
61     alloc = size;
62     buffer = malloc (size);
63     }
64    
65     return buffer;
66     }
67    
68     static void
69     render_box (Glyph *glyph, int width, int height, int top)
70     {
71     int i;
72     int left = 0;
73    
74     if (height > 2)
75     {
76     height -= 2;
77     top++;
78     }
79    
80     if (width > 2)
81     {
82     width -= 2;
83     left++;
84     }
85    
86     glyph->stride = (width + 3) & ~3;
87     glyph->width = width;
88     glyph->height = height;
89     glyph->top = top;
90     glyph->left = left;
91    
92     glyph->bitmap = temp_buffer (width * height);
93     memset (glyph->bitmap, 0, glyph->stride * height);
94    
95     for (i = width; i--; )
96     glyph->bitmap [i] = glyph->bitmap [i + (height - 1) * glyph->stride] = 0xff;
97    
98     for (i = height; i--; )
99     glyph->bitmap [i * glyph->stride] = glyph->bitmap [i * glyph->stride + (width - 1)] = 0xff;
100     }
101    
102     static void
103     font_render_glyph (Glyph *glyph, PangoFont *font, int glyph_index)
104     {
105 root 1.2 FT_Face face;
106    
107 root 1.1 if (glyph_index & PANGO_GLYPH_UNKNOWN_FLAG)
108     {
109     PangoFontMetrics *metrics;
110    
111     if (!font)
112     goto generic_box;
113    
114     metrics = pango_font_get_metrics (font, NULL);
115     if (!metrics)
116     goto generic_box;
117    
118     render_box (glyph, PANGO_PIXELS (metrics->approximate_char_width),
119     PANGO_PIXELS (metrics->ascent + metrics->descent),
120     PANGO_PIXELS (metrics->ascent));
121    
122     pango_font_metrics_unref (metrics);
123    
124     return;
125     }
126    
127 root 1.2 face = pango_opengl_font_get_face (font);
128 root 1.1
129     if (face)
130     {
131     PangoOpenGLFont *glfont = (PangoOpenGLFont *)font;
132    
133     FT_Load_Glyph (face, glyph_index, glfont->load_flags);
134     FT_Render_Glyph (face->glyph, ft_render_mode_normal);
135    
136     glyph->width = face->glyph->bitmap.width;
137     glyph->stride = face->glyph->bitmap.pitch;
138     glyph->height = face->glyph->bitmap.rows;
139     glyph->top = face->glyph->bitmap_top;
140     glyph->left = face->glyph->bitmap_left;
141     glyph->bitmap = face->glyph->bitmap.buffer;
142     }
143     else
144     generic_box:
145     render_box (glyph, PANGO_UNKNOWN_GLYPH_WIDTH, PANGO_UNKNOWN_GLYPH_HEIGHT, PANGO_UNKNOWN_GLYPH_HEIGHT);
146     }
147    
148     typedef struct glyph_info {
149     tc_area tex;
150     int left, top;
151 root 1.3 int generation;
152 root 1.1 } glyph_info;
153    
154     static void
155     free_glyph_info (glyph_info *g)
156     {
157     tc_put (&g->tex);
158     g_slice_free (glyph_info, g);
159     }
160    
161     static void
162     draw_glyph (PangoRenderer *renderer_, PangoFont *font, PangoGlyph glyph, double x, double y)
163     {
164     PangoOpenGLRenderer *renderer = PANGO_OPENGL_RENDERER (renderer_);
165 root 1.2 glyph_info *g;
166     float x1, y1, x2, y2;
167 root 1.1
168     if (glyph & PANGO_GLYPH_UNKNOWN_FLAG)
169     {
170     glyph = pango_opengl_get_unknown_glyph (font);
171    
172     if (glyph == PANGO_GLYPH_EMPTY)
173     glyph = PANGO_GLYPH_UNKNOWN_FLAG;
174     }
175    
176 root 1.2 g = _pango_opengl_font_get_cache_glyph_data (font, glyph);
177 root 1.1
178 root 1.3 if (!g || g->generation != tc_generation)
179 root 1.1 {
180     Glyph bm;
181     font_render_glyph (&bm, font, glyph);
182    
183 root 1.3 if (g)
184     g->generation = tc_generation;
185     else
186     {
187     g = g_slice_new (glyph_info);
188    
189     _pango_opengl_font_set_glyph_cache_destroy (font, (GDestroyNotify)free_glyph_info);
190     _pango_opengl_font_set_cache_glyph_data (font, glyph, g);
191     }
192 root 1.1
193 root 1.4 if (renderer->curtex)
194     glEnd ();
195    
196 root 1.1 tc_get (&g->tex, bm.width, bm.height);
197    
198     g->left = bm.left;
199     g->top = bm.top;
200    
201     glBindTexture (GL_TEXTURE_2D, g->tex.name);
202     glPixelStorei (GL_UNPACK_ROW_LENGTH, bm.stride);
203     glPixelStorei (GL_UNPACK_ALIGNMENT, 1);
204     glTexSubImage2D (GL_TEXTURE_2D, 0, g->tex.x, g->tex.y, bm.width, bm.height, GL_ALPHA, GL_UNSIGNED_BYTE, bm.bitmap);
205     glPixelStorei (GL_UNPACK_ROW_LENGTH, 0);
206     glPixelStorei (GL_UNPACK_ALIGNMENT, 4);
207 root 1.4
208     renderer->curtex = g->tex.name;
209     glBegin (GL_QUADS);
210 root 1.1 }
211    
212     x += g->left;
213     y -= g->top;
214    
215 root 1.2 x1 = g->tex.x * (1. / TC_WIDTH );
216     y1 = g->tex.y * (1. / TC_HEIGHT);
217     x2 = g->tex.w * (1. / TC_WIDTH ) + x1;
218     y2 = g->tex.h * (1. / TC_HEIGHT) + y1;
219 root 1.1
220     if (g->tex.name != renderer->curtex)
221     {
222     if (renderer->curtex)
223     glEnd ();
224    
225     glBindTexture (GL_TEXTURE_2D, g->tex.name);
226     renderer->curtex = g->tex.name;
227 root 1.4
228 root 1.1 glBegin (GL_QUADS);
229     }
230    
231     glTexCoord2f (x1, y1); glVertex2i (x , y );
232     glTexCoord2f (x2, y1); glVertex2i (x + g->tex.w, y );
233     glTexCoord2f (x2, y2); glVertex2i (x + g->tex.w, y + g->tex.h);
234     glTexCoord2f (x1, y2); glVertex2i (x , y + g->tex.h);
235     }
236    
237     static void
238     draw_trapezoid (PangoRenderer *renderer_,
239     PangoRenderPart part,
240     double y1,
241     double x11,
242     double x21,
243     double y2,
244     double x12,
245     double x22)
246     {
247     PangoOpenGLRenderer *renderer = (PangoOpenGLRenderer *)renderer_;
248    
249     if (renderer->curtex)
250     {
251     glEnd ();
252     renderer->curtex = 0;
253     }
254    
255     glDisable (GL_TEXTURE_2D);
256    
257     glBegin (GL_QUADS);
258     glVertex2d (x11, y1);
259 root 1.5 glVertex2d (x21, y1);
260 root 1.1 glVertex2d (x22, y2);
261 root 1.5 glVertex2d (x12, y2);
262 root 1.1 glEnd ();
263    
264     glEnable (GL_TEXTURE_2D);
265     }
266    
267     void
268     pango_opengl_render_layout_subpixel (PangoLayout *layout,
269     int x, int y,
270     float r, float g, float b, float a)
271     {
272     PangoContext *context;
273     PangoFontMap *fontmap;
274     PangoRenderer *renderer;
275    
276     context = pango_layout_get_context (layout);
277     fontmap = pango_context_get_font_map (context);
278     renderer = _pango_opengl_font_map_get_renderer (PANGO_OPENGL_FONT_MAP (fontmap));
279    
280     PANGO_OPENGL_RENDERER (renderer)->r = r;
281     PANGO_OPENGL_RENDERER (renderer)->g = g;
282     PANGO_OPENGL_RENDERER (renderer)->b = b;
283     PANGO_OPENGL_RENDERER (renderer)->a = a;
284    
285     pango_renderer_draw_layout (renderer, layout, x, y);
286     }
287    
288     void
289     pango_opengl_render_layout (PangoLayout *layout,
290     int x, int y,
291     float r, float g, float b, float a)
292     {
293     pango_opengl_render_layout_subpixel (layout, x * PANGO_SCALE, y * PANGO_SCALE, r, g, b, a);
294     }
295    
296     static void
297     pango_opengl_renderer_init (PangoOpenGLRenderer *renderer)
298     {
299     renderer->r = 1.;
300     renderer->g = 1.;
301     renderer->b = 1.;
302     renderer->a = 1.;
303     }
304    
305     static void
306     prepare_run (PangoRenderer *renderer, PangoLayoutRun *run)
307     {
308     PangoOpenGLRenderer *glrenderer = (PangoOpenGLRenderer *)renderer;
309     PangoColor *fg = 0;
310     GSList *l;
311    
312     renderer->underline = PANGO_UNDERLINE_NONE;
313     renderer->strikethrough = FALSE;
314    
315     for (l = run->item->analysis.extra_attrs; l; l = l->next)
316     {
317     PangoAttribute *attr = l->data;
318    
319     switch (attr->klass->type)
320     {
321     case PANGO_ATTR_UNDERLINE:
322     renderer->underline = ((PangoAttrInt *)attr)->value;
323     break;
324    
325     case PANGO_ATTR_STRIKETHROUGH:
326     renderer->strikethrough = ((PangoAttrInt *)attr)->value;
327     break;
328    
329     case PANGO_ATTR_FOREGROUND:
330     fg = &((PangoAttrColor *)attr)->color;
331     break;
332    
333     default:
334     break;
335     }
336     }
337    
338     if (fg)
339     glColor4f (fg->red / 65535., fg->green / 65535., fg->blue / 65535., glrenderer->a);
340     else
341     glColor4f (glrenderer->r, glrenderer->g, glrenderer->b, glrenderer->a);
342     }
343    
344     static void
345     draw_begin (PangoRenderer *renderer_)
346     {
347     PangoOpenGLRenderer *renderer = (PangoOpenGLRenderer *)renderer_;
348    
349     renderer->curtex = 0;
350    
351     glEnable (GL_TEXTURE_2D);
352     glTexEnvi (GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
353     glEnable (GL_BLEND);
354     gl_BlendFuncSeparate (GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA,
355     GL_ONE , GL_ONE_MINUS_SRC_ALPHA);
356     glEnable (GL_ALPHA_TEST);
357     glAlphaFunc (GL_GREATER, 0.01f);
358     }
359    
360     static void
361     draw_end (PangoRenderer *renderer_)
362     {
363     PangoOpenGLRenderer *renderer = (PangoOpenGLRenderer *)renderer_;
364    
365     if (renderer->curtex)
366     glEnd ();
367    
368     glDisable (GL_ALPHA_TEST);
369     glDisable (GL_BLEND);
370     glDisable (GL_TEXTURE_2D);
371     }
372    
373     static void
374     pango_opengl_renderer_class_init (PangoOpenGLRendererClass *klass)
375     {
376     PangoRendererClass *renderer_class = PANGO_RENDERER_CLASS (klass);
377    
378     renderer_class->draw_glyph = draw_glyph;
379     renderer_class->draw_trapezoid = draw_trapezoid;
380     renderer_class->prepare_run = prepare_run;
381     renderer_class->begin = draw_begin;
382     renderer_class->end = draw_end;
383     }
384