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

# Content
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 int flags;
41 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 FT_Face face;
107
108 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 face = pango_opengl_font_get_face (font);
129
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 int generation;
153 } 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 glyph_info *g;
167 float x1, y1, x2, y2;
168
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 g = _pango_opengl_font_get_cache_glyph_data (font, glyph);
178
179 if (!g || g->generation != tc_generation)
180 {
181 Glyph bm;
182 font_render_glyph (&bm, font, glyph);
183
184 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
194 if (renderer->curtex)
195 glEnd ();
196
197 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
209 renderer->curtex = g->tex.name;
210 glBegin (GL_QUADS);
211 }
212
213 x += g->left;
214 y -= g->top;
215
216 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
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
229 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 glVertex2d (x21, y1);
261 glVertex2d (x22, y2);
262 glVertex2d (x12, y2);
263 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 float r, float g, float b, float a,
272 int flags)
273 {
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 PANGO_OPENGL_RENDERER (renderer)->flags = flags;
287
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 float r, float g, float b, float a,
295 int flags)
296 {
297 pango_opengl_render_layout_subpixel (layout, x * PANGO_SCALE, y * PANGO_SCALE, r, g, b, a, flags);
298 }
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 unsigned char r, g, b, a;
316
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 {
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 else
350 {
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 }
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