ViewVC Help
View File | Revision Log | Show Annotations | Download File
/cvs/deliantra/Deliantra-Client/pango-render.c
Revision: 1.6
Committed: Sun Aug 13 15:14:17 2006 UTC (17 years, 9 months ago) by root
Content type: text/plain
Branch: MAIN
CVS Tags: rel-0_97, rel-0_98, rel-0_52, rel-0_53, rel-0_51, rel-0_5
Changes since 1.5: +29 -5 lines
Log Message:
*** empty log message ***

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 root 1.6 int flags;
41 root 1.1 GLuint curtex; // current texture
42     };
43    
44     G_DEFINE_TYPE (PangoOpenGLRenderer, pango_opengl_renderer, PANGO_TYPE_RENDERER)
45    
46     typedef struct
47     {
48     uint8_t *bitmap;
49     int width, stride, height, top, left;
50     } Glyph;
51    
52     static void *
53     temp_buffer (size_t size)
54     {
55     static char *buffer;
56     static size_t alloc;
57    
58     if (size > alloc)
59     {
60     size = (size + 4095) & ~4095;
61     free (buffer);
62     alloc = size;
63     buffer = malloc (size);
64     }
65    
66     return buffer;
67     }
68    
69     static void
70     render_box (Glyph *glyph, int width, int height, int top)
71     {
72     int i;
73     int left = 0;
74    
75     if (height > 2)
76     {
77     height -= 2;
78     top++;
79     }
80    
81     if (width > 2)
82     {
83     width -= 2;
84     left++;
85     }
86    
87     glyph->stride = (width + 3) & ~3;
88     glyph->width = width;
89     glyph->height = height;
90     glyph->top = top;
91     glyph->left = left;
92    
93     glyph->bitmap = temp_buffer (width * height);
94     memset (glyph->bitmap, 0, glyph->stride * height);
95    
96     for (i = width; i--; )
97     glyph->bitmap [i] = glyph->bitmap [i + (height - 1) * glyph->stride] = 0xff;
98    
99     for (i = height; i--; )
100     glyph->bitmap [i * glyph->stride] = glyph->bitmap [i * glyph->stride + (width - 1)] = 0xff;
101     }
102    
103     static void
104     font_render_glyph (Glyph *glyph, PangoFont *font, int glyph_index)
105     {
106 root 1.2 FT_Face face;
107    
108 root 1.1 if (glyph_index & PANGO_GLYPH_UNKNOWN_FLAG)
109     {
110     PangoFontMetrics *metrics;
111    
112     if (!font)
113     goto generic_box;
114    
115     metrics = pango_font_get_metrics (font, NULL);
116     if (!metrics)
117     goto generic_box;
118    
119     render_box (glyph, PANGO_PIXELS (metrics->approximate_char_width),
120     PANGO_PIXELS (metrics->ascent + metrics->descent),
121     PANGO_PIXELS (metrics->ascent));
122    
123     pango_font_metrics_unref (metrics);
124    
125     return;
126     }
127    
128 root 1.2 face = pango_opengl_font_get_face (font);
129 root 1.1
130     if (face)
131     {
132     PangoOpenGLFont *glfont = (PangoOpenGLFont *)font;
133    
134     FT_Load_Glyph (face, glyph_index, glfont->load_flags);
135     FT_Render_Glyph (face->glyph, ft_render_mode_normal);
136    
137     glyph->width = face->glyph->bitmap.width;
138     glyph->stride = face->glyph->bitmap.pitch;
139     glyph->height = face->glyph->bitmap.rows;
140     glyph->top = face->glyph->bitmap_top;
141     glyph->left = face->glyph->bitmap_left;
142     glyph->bitmap = face->glyph->bitmap.buffer;
143     }
144     else
145     generic_box:
146     render_box (glyph, PANGO_UNKNOWN_GLYPH_WIDTH, PANGO_UNKNOWN_GLYPH_HEIGHT, PANGO_UNKNOWN_GLYPH_HEIGHT);
147     }
148    
149     typedef struct glyph_info {
150     tc_area tex;
151     int left, top;
152 root 1.3 int generation;
153 root 1.1 } glyph_info;
154    
155     static void
156     free_glyph_info (glyph_info *g)
157     {
158     tc_put (&g->tex);
159     g_slice_free (glyph_info, g);
160     }
161    
162     static void
163     draw_glyph (PangoRenderer *renderer_, PangoFont *font, PangoGlyph glyph, double x, double y)
164     {
165     PangoOpenGLRenderer *renderer = PANGO_OPENGL_RENDERER (renderer_);
166 root 1.2 glyph_info *g;
167     float x1, y1, x2, y2;
168 root 1.1
169     if (glyph & PANGO_GLYPH_UNKNOWN_FLAG)
170     {
171     glyph = pango_opengl_get_unknown_glyph (font);
172    
173     if (glyph == PANGO_GLYPH_EMPTY)
174     glyph = PANGO_GLYPH_UNKNOWN_FLAG;
175     }
176    
177 root 1.2 g = _pango_opengl_font_get_cache_glyph_data (font, glyph);
178 root 1.1
179 root 1.3 if (!g || g->generation != tc_generation)
180 root 1.1 {
181     Glyph bm;
182     font_render_glyph (&bm, font, glyph);
183    
184 root 1.3 if (g)
185     g->generation = tc_generation;
186     else
187     {
188     g = g_slice_new (glyph_info);
189    
190     _pango_opengl_font_set_glyph_cache_destroy (font, (GDestroyNotify)free_glyph_info);
191     _pango_opengl_font_set_cache_glyph_data (font, glyph, g);
192     }
193 root 1.1
194 root 1.4 if (renderer->curtex)
195     glEnd ();
196    
197 root 1.1 tc_get (&g->tex, bm.width, bm.height);
198    
199     g->left = bm.left;
200     g->top = bm.top;
201    
202     glBindTexture (GL_TEXTURE_2D, g->tex.name);
203     glPixelStorei (GL_UNPACK_ROW_LENGTH, bm.stride);
204     glPixelStorei (GL_UNPACK_ALIGNMENT, 1);
205     glTexSubImage2D (GL_TEXTURE_2D, 0, g->tex.x, g->tex.y, bm.width, bm.height, GL_ALPHA, GL_UNSIGNED_BYTE, bm.bitmap);
206     glPixelStorei (GL_UNPACK_ROW_LENGTH, 0);
207     glPixelStorei (GL_UNPACK_ALIGNMENT, 4);
208 root 1.4
209     renderer->curtex = g->tex.name;
210     glBegin (GL_QUADS);
211 root 1.1 }
212    
213     x += g->left;
214     y -= g->top;
215    
216 root 1.2 x1 = g->tex.x * (1. / TC_WIDTH );
217     y1 = g->tex.y * (1. / TC_HEIGHT);
218     x2 = g->tex.w * (1. / TC_WIDTH ) + x1;
219     y2 = g->tex.h * (1. / TC_HEIGHT) + y1;
220 root 1.1
221     if (g->tex.name != renderer->curtex)
222     {
223     if (renderer->curtex)
224     glEnd ();
225    
226     glBindTexture (GL_TEXTURE_2D, g->tex.name);
227     renderer->curtex = g->tex.name;
228 root 1.4
229 root 1.1 glBegin (GL_QUADS);
230     }
231    
232     glTexCoord2f (x1, y1); glVertex2i (x , y );
233     glTexCoord2f (x2, y1); glVertex2i (x + g->tex.w, y );
234     glTexCoord2f (x2, y2); glVertex2i (x + g->tex.w, y + g->tex.h);
235     glTexCoord2f (x1, y2); glVertex2i (x , y + g->tex.h);
236     }
237    
238     static void
239     draw_trapezoid (PangoRenderer *renderer_,
240     PangoRenderPart part,
241     double y1,
242     double x11,
243     double x21,
244     double y2,
245     double x12,
246     double x22)
247     {
248     PangoOpenGLRenderer *renderer = (PangoOpenGLRenderer *)renderer_;
249    
250     if (renderer->curtex)
251     {
252     glEnd ();
253     renderer->curtex = 0;
254     }
255    
256     glDisable (GL_TEXTURE_2D);
257    
258     glBegin (GL_QUADS);
259     glVertex2d (x11, y1);
260 root 1.5 glVertex2d (x21, y1);
261 root 1.1 glVertex2d (x22, y2);
262 root 1.5 glVertex2d (x12, y2);
263 root 1.1 glEnd ();
264    
265     glEnable (GL_TEXTURE_2D);
266     }
267    
268     void
269     pango_opengl_render_layout_subpixel (PangoLayout *layout,
270     int x, int y,
271 root 1.6 float r, float g, float b, float a,
272     int flags)
273 root 1.1 {
274     PangoContext *context;
275     PangoFontMap *fontmap;
276     PangoRenderer *renderer;
277    
278     context = pango_layout_get_context (layout);
279     fontmap = pango_context_get_font_map (context);
280     renderer = _pango_opengl_font_map_get_renderer (PANGO_OPENGL_FONT_MAP (fontmap));
281    
282     PANGO_OPENGL_RENDERER (renderer)->r = r;
283     PANGO_OPENGL_RENDERER (renderer)->g = g;
284     PANGO_OPENGL_RENDERER (renderer)->b = b;
285     PANGO_OPENGL_RENDERER (renderer)->a = a;
286 root 1.6 PANGO_OPENGL_RENDERER (renderer)->flags = flags;
287 root 1.1
288     pango_renderer_draw_layout (renderer, layout, x, y);
289     }
290    
291     void
292     pango_opengl_render_layout (PangoLayout *layout,
293     int x, int y,
294 root 1.6 float r, float g, float b, float a,
295     int flags)
296 root 1.1 {
297 root 1.6 pango_opengl_render_layout_subpixel (layout, x * PANGO_SCALE, y * PANGO_SCALE, r, g, b, a, flags);
298 root 1.1 }
299    
300     static void
301     pango_opengl_renderer_init (PangoOpenGLRenderer *renderer)
302     {
303     renderer->r = 1.;
304     renderer->g = 1.;
305     renderer->b = 1.;
306     renderer->a = 1.;
307     }
308    
309     static void
310     prepare_run (PangoRenderer *renderer, PangoLayoutRun *run)
311     {
312     PangoOpenGLRenderer *glrenderer = (PangoOpenGLRenderer *)renderer;
313     PangoColor *fg = 0;
314     GSList *l;
315 root 1.6 unsigned char r, g, b, a;
316 root 1.1
317     renderer->underline = PANGO_UNDERLINE_NONE;
318     renderer->strikethrough = FALSE;
319    
320     for (l = run->item->analysis.extra_attrs; l; l = l->next)
321     {
322     PangoAttribute *attr = l->data;
323    
324     switch (attr->klass->type)
325     {
326     case PANGO_ATTR_UNDERLINE:
327     renderer->underline = ((PangoAttrInt *)attr)->value;
328     break;
329    
330     case PANGO_ATTR_STRIKETHROUGH:
331     renderer->strikethrough = ((PangoAttrInt *)attr)->value;
332     break;
333    
334     case PANGO_ATTR_FOREGROUND:
335     fg = &((PangoAttrColor *)attr)->color;
336     break;
337    
338     default:
339     break;
340     }
341     }
342    
343     if (fg)
344 root 1.6 {
345     r = fg->red * (255.f / 65535.f);
346     g = fg->green * (255.f / 65535.f);
347     b = fg->blue * (255.f / 65535.f);
348     }
349 root 1.1 else
350 root 1.6 {
351     r = glrenderer->r * 255.f;
352     g = glrenderer->g * 255.f;
353     b = glrenderer->b * 255.f;
354     }
355    
356     a = glrenderer->a * 255.f;
357    
358     if (glrenderer->flags & FLAG_INVERSE)
359     {
360     r ^= 0xffU;
361     g ^= 0xffU;
362     b ^= 0xffU;
363     }
364    
365     glColor4ub (r, g, b, a);
366 root 1.1 }
367    
368     static void
369     draw_begin (PangoRenderer *renderer_)
370     {
371     PangoOpenGLRenderer *renderer = (PangoOpenGLRenderer *)renderer_;
372    
373     renderer->curtex = 0;
374    
375     glEnable (GL_TEXTURE_2D);
376     glTexEnvi (GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
377     glEnable (GL_BLEND);
378     gl_BlendFuncSeparate (GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA,
379     GL_ONE , GL_ONE_MINUS_SRC_ALPHA);
380     glEnable (GL_ALPHA_TEST);
381     glAlphaFunc (GL_GREATER, 0.01f);
382     }
383    
384     static void
385     draw_end (PangoRenderer *renderer_)
386     {
387     PangoOpenGLRenderer *renderer = (PangoOpenGLRenderer *)renderer_;
388    
389     if (renderer->curtex)
390     glEnd ();
391    
392     glDisable (GL_ALPHA_TEST);
393     glDisable (GL_BLEND);
394     glDisable (GL_TEXTURE_2D);
395     }
396    
397     static void
398     pango_opengl_renderer_class_init (PangoOpenGLRendererClass *klass)
399     {
400     PangoRendererClass *renderer_class = PANGO_RENDERER_CLASS (klass);
401    
402     renderer_class->draw_glyph = draw_glyph;
403     renderer_class->draw_trapezoid = draw_trapezoid;
404     renderer_class->prepare_run = prepare_run;
405     renderer_class->begin = draw_begin;
406     renderer_class->end = draw_end;
407     }
408