ViewVC Help
View File | Revision Log | Show Annotations | Download File
/cvs/deliantra/Deliantra-Client/pango-render.c
Revision: 1.20
Committed: Sun Nov 18 03:06:13 2018 UTC (5 years, 5 months ago) by root
Content type: text/plain
Branch: MAIN
CVS Tags: HEAD
Changes since 1.19: +16 -17 lines
Log Message:
clumsy c++ification of rendercache

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