~oem-solutions-group/unity-2d/clutter-1.0

« back to all changes in this revision

Viewing changes to clutter/pango/cogl-pango-render.c

  • Committer: Bazaar Package Importer
  • Author(s): Emilio Pozuelo Monfort
  • Date: 2010-03-21 13:27:56 UTC
  • mto: (2.1.3 experimental)
  • mto: This revision was merged to the branch mainline in revision 8.
  • Revision ID: james.westby@ubuntu.com-20100321132756-nf8yd30yxo3zzwcm
Tags: upstream-1.2.2
ImportĀ upstreamĀ versionĀ 1.2.2

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
/*
2
 
 * Clutter.
3
 
 *
4
 
 * An OpenGL based 'interactive canvas' library.
5
 
 *
6
 
 * Authored By Matthew Allum  <mallum@openedhand.com>
7
 
 *
8
 
 * Copyright (C) 2008 OpenedHand
9
 
 *
10
 
 * This library is free software; you can redistribute it and/or
11
 
 * modify it under the terms of the GNU Lesser General Public
12
 
 * License as published by the Free Software Foundation; either
13
 
 * version 2 of the License, or (at your option) any later version.
14
 
 *
15
 
 * This library is distributed in the hope that it will be useful,
16
 
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
17
 
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
18
 
 * Lesser General Public License for more details.
19
 
 *
20
 
 * You should have received a copy of the GNU Lesser General Public
21
 
 * License along with this library. If not, see <http://www.gnu.org/licenses/>.
22
 
 */
23
 
 
24
 
#ifdef HAVE_CONFIG_H
25
 
#include "config.h"
26
 
#endif
27
 
 
28
 
#ifndef PANGO_ENABLE_BACKEND
29
 
#define PANGO_ENABLE_BACKEND 1
30
 
#endif
31
 
 
32
 
#include <pango/pango-fontmap.h>
33
 
#include <pango/pangocairo.h>
34
 
#include <pango/pango-renderer.h>
35
 
#include <cairo.h>
36
 
 
37
 
#include "cogl-pango-private.h"
38
 
#include "cogl-pango-glyph-cache.h"
39
 
#include "cogl-pango-display-list.h"
40
 
 
41
 
struct _CoglPangoRenderer
42
 
{
43
 
  PangoRenderer parent_instance;
44
 
 
45
 
  /* The material used to texture from the glyph cache with */
46
 
  CoglHandle glyph_material;
47
 
  /* The material used for solid fills. (boxes, rectangles + trapezoids) */
48
 
  CoglHandle solid_material;
49
 
 
50
 
  /* Caches of glyphs as textures */
51
 
  CoglPangoGlyphCache *glyph_cache;
52
 
 
53
 
  /* The current display list that is being built */
54
 
  CoglPangoDisplayList *display_list;
55
 
};
56
 
 
57
 
struct _CoglPangoRendererClass
58
 
{
59
 
  PangoRendererClass class_instance;
60
 
};
61
 
 
62
 
typedef struct _CoglPangoRendererQdata CoglPangoRendererQdata;
63
 
 
64
 
/* An instance of this struct gets attached to each PangoLayout to
65
 
   cache the VBO and to detect changes to the layout */
66
 
struct _CoglPangoRendererQdata
67
 
{
68
 
  /* The cache of the geometry for the layout */
69
 
  CoglPangoDisplayList *display_list;
70
 
  /* A reference to the first line of the layout. This is just used to
71
 
     detect changes */
72
 
  PangoLayoutLine *first_line;
73
 
};
74
 
 
75
 
static void
76
 
cogl_pango_renderer_draw_glyph (CoglPangoRenderer        *priv,
77
 
                                CoglPangoGlyphCacheValue *cache_value,
78
 
                                float                     x1,
79
 
                                float                     y1)
80
 
{
81
 
  float x2, y2;
82
 
 
83
 
  g_return_if_fail (priv->display_list != NULL);
84
 
 
85
 
  x2 = x1 + (float) cache_value->draw_width;
86
 
  y2 = y1 + (float) cache_value->draw_height;
87
 
 
88
 
  _cogl_pango_display_list_add_texture (priv->display_list,
89
 
                                        cache_value->texture,
90
 
                                        x1, y1, x2, y2,
91
 
                                        cache_value->tx1,
92
 
                                        cache_value->ty1,
93
 
                                        cache_value->tx2,
94
 
                                        cache_value->ty2);
95
 
}
96
 
 
97
 
static void cogl_pango_renderer_finalize (GObject *object);
98
 
static void cogl_pango_renderer_draw_glyphs (PangoRenderer    *renderer,
99
 
                                             PangoFont        *font,
100
 
                                             PangoGlyphString *glyphs,
101
 
                                             int               x,
102
 
                                             int               y);
103
 
static void cogl_pango_renderer_draw_rectangle (PangoRenderer    *renderer,
104
 
                                                PangoRenderPart   part,
105
 
                                                int               x,
106
 
                                                int               y,
107
 
                                                int               width,
108
 
                                                int               height);
109
 
static void cogl_pango_renderer_draw_trapezoid (PangoRenderer    *renderer,
110
 
                                                PangoRenderPart   part,
111
 
                                                double            y1,
112
 
                                                double            x11,
113
 
                                                double            x21,
114
 
                                                double            y2,
115
 
                                                double            x12,
116
 
                                                double            x22);
117
 
 
118
 
G_DEFINE_TYPE (CoglPangoRenderer, cogl_pango_renderer, PANGO_TYPE_RENDERER);
119
 
 
120
 
static void
121
 
cogl_pango_renderer_init (CoglPangoRenderer *priv)
122
 
{
123
 
  priv->glyph_material = cogl_material_new ();
124
 
 
125
 
  /* The default combine mode of materials is to modulate (A x B) the texture
126
 
   * RGBA channels with the RGBA channels of the previous layer (which in our
127
 
   * case is just the font color)
128
 
   *
129
 
   * Since the RGB for an alpha texture is defined as 0, this gives us:
130
 
   *
131
 
   *  result.rgb = color.rgb * 0
132
 
   *  result.a = color.a * texture.a
133
 
   *
134
 
   * What we want is premultiplied rgba values:
135
 
   *
136
 
   *  result.rgba = color.rgb * texture.a
137
 
   *  result.a = color.a * texture.a
138
 
   */
139
 
  cogl_material_set_layer_combine (priv->glyph_material, 0, /* layer */
140
 
                                   "RGBA = MODULATE (PREVIOUS, TEXTURE[A])",
141
 
                                   NULL);
142
 
 
143
 
  priv->solid_material = cogl_material_new ();
144
 
 
145
 
  priv->glyph_cache = cogl_pango_glyph_cache_new ();
146
 
 
147
 
  _cogl_pango_renderer_set_use_mipmapping (priv, FALSE);
148
 
}
149
 
 
150
 
static void
151
 
cogl_pango_renderer_class_init (CoglPangoRendererClass *klass)
152
 
{
153
 
  GObjectClass *object_class = G_OBJECT_CLASS (klass);
154
 
  PangoRendererClass *renderer_class = PANGO_RENDERER_CLASS (klass);
155
 
 
156
 
  object_class->finalize = cogl_pango_renderer_finalize;
157
 
 
158
 
  renderer_class->draw_glyphs = cogl_pango_renderer_draw_glyphs;
159
 
  renderer_class->draw_rectangle = cogl_pango_renderer_draw_rectangle;
160
 
  renderer_class->draw_trapezoid = cogl_pango_renderer_draw_trapezoid;
161
 
}
162
 
 
163
 
static void
164
 
cogl_pango_renderer_finalize (GObject *object)
165
 
{
166
 
  CoglPangoRenderer *priv = COGL_PANGO_RENDERER (object);
167
 
 
168
 
  cogl_pango_glyph_cache_free (priv->glyph_cache);
169
 
 
170
 
  G_OBJECT_CLASS (cogl_pango_renderer_parent_class)->finalize (object);
171
 
}
172
 
 
173
 
static CoglPangoRenderer *
174
 
cogl_pango_get_renderer_from_context (PangoContext *context)
175
 
{
176
 
  PangoFontMap      *font_map;
177
 
  PangoRenderer     *renderer;
178
 
  CoglPangoFontMap  *font_map_priv;
179
 
 
180
 
  font_map = pango_context_get_font_map (context);
181
 
  g_return_val_if_fail (COGL_PANGO_IS_FONT_MAP (font_map), NULL);
182
 
 
183
 
  font_map_priv = COGL_PANGO_FONT_MAP (font_map);
184
 
  renderer = cogl_pango_font_map_get_renderer (font_map_priv);
185
 
  g_return_val_if_fail (COGL_PANGO_IS_RENDERER (renderer), NULL);
186
 
 
187
 
  return COGL_PANGO_RENDERER (renderer);
188
 
}
189
 
 
190
 
static GQuark
191
 
cogl_pango_render_get_qdata_key (void)
192
 
{
193
 
  static GQuark key = 0;
194
 
 
195
 
  if (G_UNLIKELY (key == 0))
196
 
    key = g_quark_from_static_string ("CoglPangoDisplayList");
197
 
 
198
 
  return key;
199
 
}
200
 
 
201
 
static void
202
 
cogl_pango_render_qdata_destroy (CoglPangoRendererQdata *qdata)
203
 
{
204
 
  if (qdata->display_list)
205
 
    _cogl_pango_display_list_free (qdata->display_list);
206
 
  if (qdata->first_line)
207
 
    pango_layout_line_unref (qdata->first_line);
208
 
  g_slice_free (CoglPangoRendererQdata, qdata);
209
 
}
210
 
 
211
 
/**
212
 
 * cogl_pango_render_layout_subpixel:
213
 
 * @layout: a #PangoLayout
214
 
 * @x: FIXME
215
 
 * @y: FIXME
216
 
 * @color: color to use when rendering the layout
217
 
 * @flags: flags to pass to the renderer
218
 
 *
219
 
 * FIXME
220
 
 *
221
 
 * Since: 1.0
222
 
 */
223
 
void
224
 
cogl_pango_render_layout_subpixel (PangoLayout     *layout,
225
 
                                   int              x,
226
 
                                   int              y,
227
 
                                   const CoglColor *color,
228
 
                                   int              flags)
229
 
{
230
 
  PangoContext           *context;
231
 
  CoglPangoRenderer      *priv;
232
 
  CoglPangoRendererQdata *qdata;
233
 
 
234
 
  context = pango_layout_get_context (layout);
235
 
  priv = cogl_pango_get_renderer_from_context (context);
236
 
  if (G_UNLIKELY (!priv))
237
 
    return;
238
 
 
239
 
  qdata = g_object_get_qdata (G_OBJECT (layout),
240
 
                              cogl_pango_render_get_qdata_key ());
241
 
 
242
 
  if (qdata == NULL)
243
 
    {
244
 
      qdata = g_slice_new0 (CoglPangoRendererQdata);
245
 
      g_object_set_qdata_full (G_OBJECT (layout),
246
 
                               cogl_pango_render_get_qdata_key (),
247
 
                               qdata,
248
 
                               (GDestroyNotify)
249
 
                               cogl_pango_render_qdata_destroy);
250
 
    }
251
 
 
252
 
  /* Check if the layout has changed since the last build of the
253
 
     display list. This trick was suggested by Behdad Esfahbod here:
254
 
     http://mail.gnome.org/archives/gtk-i18n-list/2009-May/msg00019.html */
255
 
  if (qdata->display_list && qdata->first_line
256
 
      && qdata->first_line->layout != layout)
257
 
    {
258
 
      _cogl_pango_display_list_free (qdata->display_list);
259
 
      qdata->display_list = NULL;
260
 
    }
261
 
 
262
 
  if (qdata->display_list == NULL)
263
 
    {
264
 
      qdata->display_list = _cogl_pango_display_list_new ();
265
 
 
266
 
      priv->display_list = qdata->display_list;
267
 
      pango_renderer_draw_layout (PANGO_RENDERER (priv), layout, 0, 0);
268
 
      priv->display_list = NULL;
269
 
    }
270
 
 
271
 
  cogl_push_matrix ();
272
 
  cogl_translate (x / (gfloat) PANGO_SCALE, y / (gfloat) PANGO_SCALE, 0);
273
 
  _cogl_pango_display_list_render (qdata->display_list,
274
 
                                   color,
275
 
                                   priv->glyph_material,
276
 
                                   priv->solid_material);
277
 
  cogl_pop_matrix ();
278
 
 
279
 
  /* Keep a reference to the first line of the layout so we can detect
280
 
     changes */
281
 
  if (qdata->first_line)
282
 
    {
283
 
      pango_layout_line_unref (qdata->first_line);
284
 
      qdata->first_line = NULL;
285
 
    }
286
 
  if (pango_layout_get_line_count (layout) > 0)
287
 
    {
288
 
      qdata->first_line = pango_layout_get_line (layout, 0);
289
 
      pango_layout_line_ref (qdata->first_line);
290
 
    }
291
 
}
292
 
 
293
 
/**
294
 
 * cogl_pango_render_layout:
295
 
 * @layout: a #PangoLayout
296
 
 * @x: X coordinate to render the layout at
297
 
 * @y: Y coordinate to render the layout at
298
 
 * @color: color to use when rendering the layout
299
 
 * @flags: flags to pass to the renderer
300
 
 *
301
 
 * Renders @layout.
302
 
 *
303
 
 * Since: 1.0
304
 
 */
305
 
void
306
 
cogl_pango_render_layout (PangoLayout     *layout,
307
 
                          int              x,
308
 
                          int              y,
309
 
                          const CoglColor *color,
310
 
                          int              flags)
311
 
{
312
 
  cogl_pango_render_layout_subpixel (layout,
313
 
                                     x * PANGO_SCALE,
314
 
                                     y * PANGO_SCALE,
315
 
                                     color,
316
 
                                     flags);
317
 
}
318
 
 
319
 
/**
320
 
 * cogl_pango_render_layout_line:
321
 
 * @line: a #PangoLayoutLine
322
 
 * @x: X coordinate to render the line at
323
 
 * @y: Y coordinate to render the line at
324
 
 * @color: color to use when rendering the line
325
 
 *
326
 
 * Renders @line at the given coordinates using the given color.
327
 
 *
328
 
 * Since: 1.0
329
 
 */
330
 
void
331
 
cogl_pango_render_layout_line (PangoLayoutLine *line,
332
 
                               int              x,
333
 
                               int              y,
334
 
                               const CoglColor *color)
335
 
{
336
 
  PangoContext      *context;
337
 
  CoglPangoRenderer *priv;
338
 
 
339
 
  context = pango_layout_get_context (line->layout);
340
 
  priv = cogl_pango_get_renderer_from_context (context);
341
 
  if (G_UNLIKELY (!priv))
342
 
    return;
343
 
 
344
 
  priv->display_list = _cogl_pango_display_list_new ();
345
 
 
346
 
  pango_renderer_draw_layout_line (PANGO_RENDERER (priv), line, x, y);
347
 
 
348
 
  _cogl_pango_display_list_render (priv->display_list,
349
 
                                   color,
350
 
                                   priv->glyph_material,
351
 
                                   priv->solid_material);
352
 
 
353
 
  _cogl_pango_display_list_free (priv->display_list);
354
 
  priv->display_list = NULL;
355
 
}
356
 
 
357
 
void
358
 
_cogl_pango_renderer_clear_glyph_cache (CoglPangoRenderer *renderer)
359
 
{
360
 
  cogl_pango_glyph_cache_clear (renderer->glyph_cache);
361
 
}
362
 
 
363
 
void
364
 
_cogl_pango_renderer_set_use_mipmapping (CoglPangoRenderer *renderer,
365
 
                                         gboolean value)
366
 
{
367
 
  if (value)
368
 
    cogl_material_set_layer_filters (renderer->glyph_material, 0,
369
 
                                     COGL_MATERIAL_FILTER_LINEAR_MIPMAP_LINEAR,
370
 
                                     COGL_MATERIAL_FILTER_LINEAR);
371
 
  else
372
 
    cogl_material_set_layer_filters (renderer->glyph_material, 0,
373
 
                                     COGL_MATERIAL_FILTER_LINEAR,
374
 
                                     COGL_MATERIAL_FILTER_LINEAR);
375
 
}
376
 
 
377
 
gboolean
378
 
_cogl_pango_renderer_get_use_mipmapping (CoglPangoRenderer *renderer)
379
 
{
380
 
  const GList *layers = cogl_material_get_layers (renderer->glyph_material);
381
 
 
382
 
  g_return_val_if_fail (layers != NULL, FALSE);
383
 
 
384
 
  return (cogl_material_layer_get_min_filter (layers->data)
385
 
          == COGL_MATERIAL_FILTER_LINEAR_MIPMAP_LINEAR);
386
 
}
387
 
 
388
 
static CoglPangoGlyphCacheValue *
389
 
cogl_pango_renderer_get_cached_glyph (PangoRenderer *renderer,
390
 
                                      PangoFont     *font,
391
 
                                      PangoGlyph     glyph)
392
 
{
393
 
  CoglPangoRenderer *priv = COGL_PANGO_RENDERER (renderer);
394
 
  CoglPangoGlyphCacheValue *value;
395
 
 
396
 
  value = cogl_pango_glyph_cache_lookup (priv->glyph_cache, font, glyph);
397
 
  if (value == NULL)
398
 
    {
399
 
      cairo_surface_t *surface;
400
 
      cairo_t *cr;
401
 
      cairo_scaled_font_t *scaled_font;
402
 
      PangoRectangle ink_rect;
403
 
      cairo_glyph_t cairo_glyph;
404
 
 
405
 
      pango_font_get_glyph_extents (font, glyph, &ink_rect, NULL);
406
 
      pango_extents_to_pixels (&ink_rect, NULL);
407
 
 
408
 
      surface = cairo_image_surface_create (CAIRO_FORMAT_A8,
409
 
                                            ink_rect.width,
410
 
                                            ink_rect.height);
411
 
      cr = cairo_create (surface);
412
 
 
413
 
      scaled_font = pango_cairo_font_get_scaled_font (PANGO_CAIRO_FONT (font));
414
 
      cairo_set_scaled_font (cr, scaled_font);
415
 
 
416
 
      cairo_glyph.x = -ink_rect.x;
417
 
      cairo_glyph.y = -ink_rect.y;
418
 
      /* The PangoCairo glyph numbers directly map to Cairo glyph
419
 
         numbers */
420
 
      cairo_glyph.index = glyph;
421
 
      cairo_show_glyphs (cr, &cairo_glyph, 1);
422
 
 
423
 
      cairo_destroy (cr);
424
 
      cairo_surface_flush (surface);
425
 
 
426
 
      /* Copy the glyph to the cache */
427
 
      value =
428
 
        cogl_pango_glyph_cache_set (priv->glyph_cache, font, glyph,
429
 
                                    cairo_image_surface_get_data (surface),
430
 
                                    cairo_image_surface_get_width (surface),
431
 
                                    cairo_image_surface_get_height (surface),
432
 
                                    cairo_image_surface_get_stride (surface),
433
 
                                    ink_rect.x, ink_rect.y);
434
 
 
435
 
      cairo_surface_destroy (surface);
436
 
 
437
 
      COGL_NOTE (PANGO, "cache fail    %i", glyph);
438
 
    }
439
 
  else
440
 
    {
441
 
      COGL_NOTE (PANGO, "cache success %i", glyph);
442
 
    }
443
 
 
444
 
  return value;
445
 
}
446
 
 
447
 
void
448
 
cogl_pango_ensure_glyph_cache_for_layout (PangoLayout *layout)
449
 
{
450
 
  PangoContext    *context;
451
 
  PangoRenderer   *renderer;
452
 
  PangoLayoutIter *iter;
453
 
 
454
 
  g_return_if_fail (PANGO_IS_LAYOUT (layout));
455
 
 
456
 
  if ((iter = pango_layout_get_iter (layout)) == NULL)
457
 
    return;
458
 
 
459
 
  context = pango_layout_get_context (layout);
460
 
  renderer =
461
 
    PANGO_RENDERER (cogl_pango_get_renderer_from_context (context));
462
 
 
463
 
  do
464
 
    {
465
 
      PangoLayoutLine *line;
466
 
      GSList *l;
467
 
 
468
 
      line = pango_layout_iter_get_line_readonly (iter);
469
 
 
470
 
      for (l = line->runs; l; l = l->next)
471
 
        {
472
 
          PangoLayoutRun *run = l->data;
473
 
          PangoGlyphString *glyphs = run->glyphs;
474
 
          int i;
475
 
 
476
 
          for (i = 0; i < glyphs->num_glyphs; i++)
477
 
            {
478
 
              PangoGlyphInfo *gi = &glyphs->glyphs[i];
479
 
 
480
 
              cogl_pango_renderer_get_cached_glyph (renderer,
481
 
                                                    run->item->analysis.font,
482
 
                                                    gi->glyph);
483
 
            }
484
 
        }
485
 
    }
486
 
  while (pango_layout_iter_next_line (iter));
487
 
 
488
 
  pango_layout_iter_free (iter);
489
 
}
490
 
 
491
 
static void
492
 
cogl_pango_renderer_set_color_for_part (PangoRenderer   *renderer,
493
 
                                        PangoRenderPart  part)
494
 
{
495
 
  PangoColor *pango_color = pango_renderer_get_color (renderer, part);
496
 
  CoglPangoRenderer *priv = COGL_PANGO_RENDERER (renderer);
497
 
 
498
 
  if (pango_color)
499
 
    {
500
 
      CoglColor color;
501
 
 
502
 
      cogl_color_set_from_4ub (&color,
503
 
                               pango_color->red >> 8,
504
 
                               pango_color->green >> 8,
505
 
                               pango_color->blue >> 8,
506
 
                               0xff);
507
 
 
508
 
      _cogl_pango_display_list_set_color_override (priv->display_list, &color);
509
 
    }
510
 
  else
511
 
    _cogl_pango_display_list_remove_color_override (priv->display_list);
512
 
}
513
 
 
514
 
static void
515
 
cogl_pango_renderer_draw_box (PangoRenderer *renderer,
516
 
                              int            x,
517
 
                              int            y,
518
 
                              int            width,
519
 
                              int            height)
520
 
{
521
 
  CoglPangoRenderer *priv = COGL_PANGO_RENDERER (renderer);
522
 
 
523
 
  g_return_if_fail (priv->display_list != NULL);
524
 
 
525
 
  _cogl_pango_display_list_add_rectangle (priv->display_list,
526
 
                                          x,
527
 
                                          y - height,
528
 
                                          x + width,
529
 
                                          y);
530
 
}
531
 
 
532
 
static void
533
 
cogl_pango_renderer_get_device_units (PangoRenderer *renderer,
534
 
                                      int            xin,
535
 
                                      int            yin,
536
 
                                      float     *xout,
537
 
                                      float     *yout)
538
 
{
539
 
  const PangoMatrix *matrix;
540
 
 
541
 
  if ((matrix = pango_renderer_get_matrix (renderer)))
542
 
    {
543
 
      /* Convert user-space coords to device coords */
544
 
      *xout =  ((xin * matrix->xx + yin * matrix->xy)
545
 
                                     / PANGO_SCALE + matrix->x0);
546
 
      *yout =  ((yin * matrix->yy + xin * matrix->yx)
547
 
                                     / PANGO_SCALE + matrix->y0);
548
 
    }
549
 
  else
550
 
    {
551
 
      *xout = PANGO_PIXELS (xin);
552
 
      *yout = PANGO_PIXELS (yin);
553
 
    }
554
 
}
555
 
 
556
 
static void
557
 
cogl_pango_renderer_draw_rectangle (PangoRenderer   *renderer,
558
 
                                    PangoRenderPart  part,
559
 
                                    int              x,
560
 
                                    int              y,
561
 
                                    int              width,
562
 
                                    int              height)
563
 
{
564
 
  CoglPangoRenderer *priv = COGL_PANGO_RENDERER (renderer);
565
 
  float x1, x2, y1, y2;
566
 
 
567
 
  g_return_if_fail (priv->display_list != NULL);
568
 
 
569
 
  cogl_pango_renderer_set_color_for_part (renderer, part);
570
 
 
571
 
  cogl_pango_renderer_get_device_units (renderer,
572
 
                                        x, y,
573
 
                                        &x1, &y1);
574
 
  cogl_pango_renderer_get_device_units (renderer,
575
 
                                        x + width, y + height,
576
 
                                        &x2, &y2);
577
 
 
578
 
  _cogl_pango_display_list_add_rectangle (priv->display_list,
579
 
                                          x1, y1, x2, y2);
580
 
}
581
 
 
582
 
static void
583
 
cogl_pango_renderer_draw_trapezoid (PangoRenderer   *renderer,
584
 
                                    PangoRenderPart  part,
585
 
                                    double           y1,
586
 
                                    double           x11,
587
 
                                    double           x21,
588
 
                                    double           y2,
589
 
                                    double           x12,
590
 
                                    double           x22)
591
 
{
592
 
  CoglPangoRenderer *priv = COGL_PANGO_RENDERER (renderer);
593
 
  float points[8];
594
 
 
595
 
  g_return_if_fail (priv->display_list != NULL);
596
 
 
597
 
  points[0] =  (x11);
598
 
  points[1] =  (y1);
599
 
  points[2] =  (x12);
600
 
  points[3] =  (y2);
601
 
  points[4] =  (x22);
602
 
  points[5] = points[3];
603
 
  points[6] =  (x21);
604
 
  points[7] = points[1];
605
 
 
606
 
  cogl_pango_renderer_set_color_for_part (renderer, part);
607
 
 
608
 
  _cogl_pango_display_list_add_trapezoid (priv->display_list,
609
 
                                          y1,
610
 
                                          x11,
611
 
                                          x21,
612
 
                                          y2,
613
 
                                          x12,
614
 
                                          x22);
615
 
}
616
 
 
617
 
static void
618
 
cogl_pango_renderer_draw_glyphs (PangoRenderer    *renderer,
619
 
                                 PangoFont        *font,
620
 
                                 PangoGlyphString *glyphs,
621
 
                                 int               xi,
622
 
                                 int               yi)
623
 
{
624
 
  CoglPangoRenderer *priv = (CoglPangoRenderer *) renderer;
625
 
  CoglPangoGlyphCacheValue *cache_value;
626
 
  int i;
627
 
 
628
 
  cogl_pango_renderer_set_color_for_part (renderer,
629
 
                                          PANGO_RENDER_PART_FOREGROUND);
630
 
 
631
 
  for (i = 0; i < glyphs->num_glyphs; i++)
632
 
    {
633
 
      PangoGlyphInfo *gi = glyphs->glyphs + i;
634
 
      float x, y;
635
 
 
636
 
      cogl_pango_renderer_get_device_units (renderer,
637
 
                                            xi + gi->geometry.x_offset,
638
 
                                            yi + gi->geometry.y_offset,
639
 
                                            &x, &y);
640
 
 
641
 
      if ((gi->glyph & PANGO_GLYPH_UNKNOWN_FLAG))
642
 
        {
643
 
          PangoFontMetrics *metrics;
644
 
 
645
 
          if (font == NULL ||
646
 
              (metrics = pango_font_get_metrics (font, NULL)) == NULL)
647
 
            {
648
 
              cogl_pango_renderer_draw_box (renderer,
649
 
                                            x,
650
 
                                            y,
651
 
                                            PANGO_UNKNOWN_GLYPH_WIDTH,
652
 
                                            PANGO_UNKNOWN_GLYPH_HEIGHT);
653
 
            }
654
 
          else
655
 
            {
656
 
              cogl_pango_renderer_draw_box (renderer,
657
 
                                            x,
658
 
                                            y,
659
 
                                            metrics->approximate_char_width
660
 
                                            / PANGO_SCALE,
661
 
                                            metrics->ascent / PANGO_SCALE);
662
 
 
663
 
              pango_font_metrics_unref (metrics);
664
 
            }
665
 
        }
666
 
      else
667
 
        {
668
 
          /* Get the texture containing the glyph. This will create
669
 
             the cache entry if there isn't already one */
670
 
          cache_value =
671
 
            cogl_pango_renderer_get_cached_glyph (renderer,
672
 
                                                  font,
673
 
                                                  gi->glyph);
674
 
 
675
 
          if (cache_value == NULL)
676
 
            cogl_pango_renderer_draw_box (renderer,
677
 
                                          x,
678
 
                                          y,
679
 
                                          PANGO_UNKNOWN_GLYPH_WIDTH,
680
 
                                          PANGO_UNKNOWN_GLYPH_HEIGHT);
681
 
          else
682
 
            {
683
 
              float width, height;
684
 
 
685
 
              x += (float)(cache_value->draw_x);
686
 
              y += (float)(cache_value->draw_y);
687
 
 
688
 
              width = x + (float)(cache_value->draw_width);
689
 
              height = y + (float)(cache_value->draw_height);
690
 
 
691
 
              cogl_pango_renderer_draw_glyph (priv, cache_value, x, y);
692
 
            }
693
 
        }
694
 
 
695
 
      xi += gi->geometry.width;
696
 
    }
697
 
}