mirror of
https://github.com/brl/mutter.git
synced 2024-11-30 03:50:47 -05:00
Render pango layouts with vertex buffers
When rendering a pango layout CoglPangoRenderer now records the operations into a list called a CoglPangoDisplayList. The entries in the list are either glyph renderings from a texture, rectangles or trapezoids. Multiple consecutive glyph renderings from the same glyph cache texture are combined into a single entry. Note the CoglPangoDisplayList has nothing to do with a GL display list. After the display list is built it is attached to the PangoLayout with g_object_set_qdata so that next time the layout is rendered it can bypass rebuilding it. The glyph rendering entries are drawn via a VBO. The VBO is attached to the display list so it can be used multiple times. This makes the common case of rendering a PangoLayout contained in a single texture subsequent times usually boil down to a single call to glDrawArrays with an already uploaded VBO. The VBOs are accessed via the cogl_vertex_buffer API so if VBOs are not available in GL it will resort to a fallback. Note this will fall apart if the pango layout is altered after the first render. I can't find a way to detect when the layout is altered. However this won't affect ClutterText because it creates a new PangoLayout whenever any properties are changed.
This commit is contained in:
parent
9fdc9ca583
commit
bb156970de
@ -1,4 +1,5 @@
|
|||||||
source_c = \
|
source_c = \
|
||||||
|
cogl-pango-display-list.c \
|
||||||
cogl-pango-fontmap.c \
|
cogl-pango-fontmap.c \
|
||||||
cogl-pango-render.c \
|
cogl-pango-render.c \
|
||||||
cogl-pango-glyph-cache.c
|
cogl-pango-glyph-cache.c
|
||||||
@ -6,6 +7,7 @@ source_c = \
|
|||||||
source_h = cogl-pango.h
|
source_h = cogl-pango.h
|
||||||
|
|
||||||
source_h_priv = \
|
source_h_priv = \
|
||||||
|
cogl-pango-display-list.h \
|
||||||
cogl-pango-private.h \
|
cogl-pango-private.h \
|
||||||
cogl-pango-glyph-cache.h
|
cogl-pango-glyph-cache.h
|
||||||
|
|
||||||
|
330
clutter/pango/cogl-pango-display-list.c
Normal file
330
clutter/pango/cogl-pango-display-list.c
Normal file
@ -0,0 +1,330 @@
|
|||||||
|
/*
|
||||||
|
* Clutter.
|
||||||
|
*
|
||||||
|
* An OpenGL based 'interactive canvas' library.
|
||||||
|
*
|
||||||
|
* Authored By Neil Roberts <neil@linux.intel.com>
|
||||||
|
*
|
||||||
|
* Copyright (C) 2009 Intel Corporation.
|
||||||
|
*
|
||||||
|
* This library is free software; you can redistribute it and/or
|
||||||
|
* modify it under the terms of the GNU Lesser General Public
|
||||||
|
* License as published by the Free Software Foundation; either
|
||||||
|
* version 2 of the License, or (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This library is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||||
|
* Lesser General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU Lesser General Public
|
||||||
|
* License along with this library. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifdef HAVE_CONFIG_H
|
||||||
|
#include "config.h"
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#include <glib.h>
|
||||||
|
#include <cogl/cogl.h>
|
||||||
|
#include <string.h>
|
||||||
|
|
||||||
|
#include "cogl-pango-display-list.h"
|
||||||
|
|
||||||
|
typedef enum
|
||||||
|
{
|
||||||
|
COGL_PANGO_DISPLAY_LIST_TEXTURE,
|
||||||
|
COGL_PANGO_DISPLAY_LIST_RECTANGLE,
|
||||||
|
COGL_PANGO_DISPLAY_LIST_TRAPEZOID
|
||||||
|
} CoglPangoDisplayListNodeType;
|
||||||
|
|
||||||
|
typedef struct _CoglPangoDisplayListNode CoglPangoDisplayListNode;
|
||||||
|
typedef struct _CoglPangoDisplayListVertex CoglPangoDisplayListVertex;
|
||||||
|
|
||||||
|
struct _CoglPangoDisplayList
|
||||||
|
{
|
||||||
|
CoglColor color;
|
||||||
|
GSList *nodes;
|
||||||
|
GSList *last_node;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct _CoglPangoDisplayListNode
|
||||||
|
{
|
||||||
|
CoglPangoDisplayListNodeType type;
|
||||||
|
|
||||||
|
CoglColor color;
|
||||||
|
|
||||||
|
union
|
||||||
|
{
|
||||||
|
struct
|
||||||
|
{
|
||||||
|
/* The texture to render these coords from */
|
||||||
|
CoglHandle texture;
|
||||||
|
/* Array of vertex data to render out of this texture */
|
||||||
|
GArray *verts;
|
||||||
|
/* A VBO representing those vertices */
|
||||||
|
CoglHandle vertex_buffer;
|
||||||
|
} texture;
|
||||||
|
|
||||||
|
struct
|
||||||
|
{
|
||||||
|
float x_1, y_1;
|
||||||
|
float x_2, y_2;
|
||||||
|
} rectangle;
|
||||||
|
|
||||||
|
struct
|
||||||
|
{
|
||||||
|
float y_1;
|
||||||
|
float x_11;
|
||||||
|
float x_21;
|
||||||
|
float y_2;
|
||||||
|
float x_12;
|
||||||
|
float x_22;
|
||||||
|
} trapezoid;
|
||||||
|
} d;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct _CoglPangoDisplayListVertex
|
||||||
|
{
|
||||||
|
float x, y, t_x, t_y;
|
||||||
|
};
|
||||||
|
|
||||||
|
CoglPangoDisplayList *
|
||||||
|
_cogl_pango_display_list_new (void)
|
||||||
|
{
|
||||||
|
return g_slice_new0 (CoglPangoDisplayList);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
_cogl_pango_display_list_append_node (CoglPangoDisplayList *dl,
|
||||||
|
CoglPangoDisplayListNode *node)
|
||||||
|
{
|
||||||
|
if (dl->last_node)
|
||||||
|
dl->last_node = dl->last_node->next = g_slist_prepend (NULL, node);
|
||||||
|
else
|
||||||
|
dl->last_node = dl->nodes = g_slist_prepend (NULL, node);
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
_cogl_pango_display_list_set_color (CoglPangoDisplayList *dl,
|
||||||
|
const CoglColor *color)
|
||||||
|
{
|
||||||
|
dl->color = *color;
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
_cogl_pango_display_list_add_texture (CoglPangoDisplayList *dl,
|
||||||
|
CoglHandle texture,
|
||||||
|
float x_1, float y_1,
|
||||||
|
float x_2, float y_2,
|
||||||
|
float tx_1, float ty_1,
|
||||||
|
float tx_2, float ty_2)
|
||||||
|
{
|
||||||
|
CoglPangoDisplayListNode *node;
|
||||||
|
CoglPangoDisplayListVertex *verts;
|
||||||
|
|
||||||
|
/* Add to the last node if it is a texture node with the same
|
||||||
|
target texture */
|
||||||
|
if (dl->last_node
|
||||||
|
&& (node = dl->last_node->data)->type == COGL_PANGO_DISPLAY_LIST_TEXTURE
|
||||||
|
&& node->d.texture.texture == texture
|
||||||
|
&& !memcmp (&dl->color, &node->color, sizeof (CoglColor)))
|
||||||
|
{
|
||||||
|
/* Get rid of the vertex buffer so that it will be recreated */
|
||||||
|
if (node->d.texture.vertex_buffer != COGL_INVALID_HANDLE)
|
||||||
|
{
|
||||||
|
cogl_vertex_buffer_unref (node->d.texture.vertex_buffer);
|
||||||
|
node->d.texture.vertex_buffer = COGL_INVALID_HANDLE;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
/* Otherwise create a new node */
|
||||||
|
node = g_slice_new (CoglPangoDisplayListNode);
|
||||||
|
|
||||||
|
node->type = COGL_PANGO_DISPLAY_LIST_TEXTURE;
|
||||||
|
node->color = dl->color;
|
||||||
|
node->d.texture.texture = cogl_texture_ref (texture);
|
||||||
|
node->d.texture.verts
|
||||||
|
= g_array_new (FALSE, FALSE, sizeof (CoglPangoDisplayListVertex));
|
||||||
|
node->d.texture.vertex_buffer = COGL_INVALID_HANDLE;
|
||||||
|
|
||||||
|
_cogl_pango_display_list_append_node (dl, node);
|
||||||
|
}
|
||||||
|
|
||||||
|
g_array_set_size (node->d.texture.verts,
|
||||||
|
node->d.texture.verts->len + 4);
|
||||||
|
verts = &g_array_index (node->d.texture.verts,
|
||||||
|
CoglPangoDisplayListVertex,
|
||||||
|
node->d.texture.verts->len - 4);
|
||||||
|
|
||||||
|
verts->x = x_1;
|
||||||
|
verts->y = y_1;
|
||||||
|
verts->t_x = tx_1;
|
||||||
|
verts->t_y = ty_1;
|
||||||
|
verts++;
|
||||||
|
verts->x = x_1;
|
||||||
|
verts->y = y_2;
|
||||||
|
verts->t_x = tx_1;
|
||||||
|
verts->t_y = ty_2;
|
||||||
|
verts++;
|
||||||
|
verts->x = x_2;
|
||||||
|
verts->y = y_2;
|
||||||
|
verts->t_x = tx_2;
|
||||||
|
verts->t_y = ty_2;
|
||||||
|
verts++;
|
||||||
|
verts->x = x_2;
|
||||||
|
verts->y = y_1;
|
||||||
|
verts->t_x = tx_2;
|
||||||
|
verts->t_y = ty_1;
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
_cogl_pango_display_list_add_rectangle (CoglPangoDisplayList *dl,
|
||||||
|
float x_1, float y_1,
|
||||||
|
float x_2, float y_2)
|
||||||
|
{
|
||||||
|
CoglPangoDisplayListNode *node = g_slice_new (CoglPangoDisplayListNode);
|
||||||
|
|
||||||
|
node->type = COGL_PANGO_DISPLAY_LIST_RECTANGLE;
|
||||||
|
node->color = dl->color;
|
||||||
|
node->d.rectangle.x_1 = x_1;
|
||||||
|
node->d.rectangle.y_1 = y_1;
|
||||||
|
node->d.rectangle.x_2 = x_2;
|
||||||
|
node->d.rectangle.y_2 = y_2;
|
||||||
|
|
||||||
|
_cogl_pango_display_list_append_node (dl, node);
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
_cogl_pango_display_list_add_trapezoid (CoglPangoDisplayList *dl,
|
||||||
|
float y_1,
|
||||||
|
float x_11,
|
||||||
|
float x_21,
|
||||||
|
float y_2,
|
||||||
|
float x_12,
|
||||||
|
float x_22)
|
||||||
|
{
|
||||||
|
CoglPangoDisplayListNode *node = g_slice_new (CoglPangoDisplayListNode);
|
||||||
|
|
||||||
|
node->type = COGL_PANGO_DISPLAY_LIST_TRAPEZOID;
|
||||||
|
node->color = dl->color;
|
||||||
|
node->d.trapezoid.y_1 = y_1;
|
||||||
|
node->d.trapezoid.x_11 = x_11;
|
||||||
|
node->d.trapezoid.x_21 = x_21;
|
||||||
|
node->d.trapezoid.y_2 = y_2;
|
||||||
|
node->d.trapezoid.x_12 = x_12;
|
||||||
|
node->d.trapezoid.x_22 = x_22;
|
||||||
|
|
||||||
|
_cogl_pango_display_list_append_node (dl, node);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
_cogl_pango_display_list_render_texture (CoglHandle material,
|
||||||
|
CoglPangoDisplayListNode *node)
|
||||||
|
{
|
||||||
|
cogl_material_set_layer (material, 0, node->d.texture.texture);
|
||||||
|
cogl_material_set_color (material, &node->color);
|
||||||
|
cogl_set_source (material);
|
||||||
|
|
||||||
|
if (node->d.texture.vertex_buffer == COGL_INVALID_HANDLE)
|
||||||
|
{
|
||||||
|
CoglHandle vb = cogl_vertex_buffer_new (node->d.texture.verts->len);
|
||||||
|
|
||||||
|
cogl_vertex_buffer_add (vb, "gl_Vertex", 2, GL_FLOAT, FALSE,
|
||||||
|
sizeof (CoglPangoDisplayListVertex),
|
||||||
|
&g_array_index (node->d.texture.verts,
|
||||||
|
CoglPangoDisplayListVertex, 0).x);
|
||||||
|
cogl_vertex_buffer_add (vb, "gl_MultiTexCoord0", 2, GL_FLOAT, FALSE,
|
||||||
|
sizeof (CoglPangoDisplayListVertex),
|
||||||
|
&g_array_index (node->d.texture.verts,
|
||||||
|
CoglPangoDisplayListVertex,
|
||||||
|
0).t_x);
|
||||||
|
cogl_vertex_buffer_submit (vb);
|
||||||
|
|
||||||
|
node->d.texture.vertex_buffer = vb;
|
||||||
|
}
|
||||||
|
|
||||||
|
cogl_vertex_buffer_draw (node->d.texture.vertex_buffer,
|
||||||
|
GL_QUADS, 0, node->d.texture.verts->len);
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
_cogl_pango_display_list_render (CoglPangoDisplayList *dl,
|
||||||
|
CoglHandle glyph_material,
|
||||||
|
CoglHandle solid_material)
|
||||||
|
{
|
||||||
|
GSList *l;
|
||||||
|
|
||||||
|
for (l = dl->nodes; l; l = l->next)
|
||||||
|
{
|
||||||
|
CoglPangoDisplayListNode *node = l->data;
|
||||||
|
|
||||||
|
switch (node->type)
|
||||||
|
{
|
||||||
|
case COGL_PANGO_DISPLAY_LIST_TEXTURE:
|
||||||
|
_cogl_pango_display_list_render_texture (glyph_material, node);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case COGL_PANGO_DISPLAY_LIST_RECTANGLE:
|
||||||
|
cogl_material_set_color (solid_material, &node->color);
|
||||||
|
cogl_set_source (solid_material);
|
||||||
|
cogl_rectangle (node->d.rectangle.x_1,
|
||||||
|
node->d.rectangle.y_1,
|
||||||
|
node->d.rectangle.x_2,
|
||||||
|
node->d.rectangle.y_2);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case COGL_PANGO_DISPLAY_LIST_TRAPEZOID:
|
||||||
|
{
|
||||||
|
float points[8];
|
||||||
|
|
||||||
|
points[0] = node->d.trapezoid.x_11;
|
||||||
|
points[1] = node->d.trapezoid.y_1;
|
||||||
|
points[2] = node->d.trapezoid.x_12;
|
||||||
|
points[3] = node->d.trapezoid.y_2;
|
||||||
|
points[4] = node->d.trapezoid.x_22;
|
||||||
|
points[5] = node->d.trapezoid.y_2;
|
||||||
|
points[6] = node->d.trapezoid.x_21;
|
||||||
|
points[7] = node->d.trapezoid.y_1;
|
||||||
|
|
||||||
|
cogl_material_set_color (solid_material, &node->color);
|
||||||
|
cogl_set_source (solid_material);
|
||||||
|
cogl_path_polygon (points, 4);
|
||||||
|
cogl_path_fill ();
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
_cogl_pango_display_list_node_free (CoglPangoDisplayListNode *node)
|
||||||
|
{
|
||||||
|
if (node->type == COGL_PANGO_DISPLAY_LIST_TEXTURE)
|
||||||
|
{
|
||||||
|
g_array_free (node->d.texture.verts, TRUE);
|
||||||
|
if (node->d.texture.texture != COGL_INVALID_HANDLE)
|
||||||
|
cogl_texture_unref (node->d.texture.texture);
|
||||||
|
if (node->d.texture.vertex_buffer != COGL_INVALID_HANDLE)
|
||||||
|
cogl_vertex_buffer_unref (node->d.texture.vertex_buffer);
|
||||||
|
}
|
||||||
|
|
||||||
|
g_slice_free (CoglPangoDisplayListNode, node);
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
_cogl_pango_display_list_clear (CoglPangoDisplayList *dl)
|
||||||
|
{
|
||||||
|
g_slist_foreach (dl->nodes, (GFunc) _cogl_pango_display_list_node_free, NULL);
|
||||||
|
g_slist_free (dl->nodes);
|
||||||
|
dl->nodes = NULL;
|
||||||
|
dl->last_node = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
_cogl_pango_display_list_free (CoglPangoDisplayList *dl)
|
||||||
|
{
|
||||||
|
_cogl_pango_display_list_clear (dl);
|
||||||
|
g_slice_free (CoglPangoDisplayList, dl);
|
||||||
|
}
|
68
clutter/pango/cogl-pango-display-list.h
Normal file
68
clutter/pango/cogl-pango-display-list.h
Normal file
@ -0,0 +1,68 @@
|
|||||||
|
/*
|
||||||
|
* Clutter.
|
||||||
|
*
|
||||||
|
* An OpenGL based 'interactive canvas' library.
|
||||||
|
*
|
||||||
|
* Authored By Neil Roberts <neil@linux.intel.com>
|
||||||
|
*
|
||||||
|
* Copyright (C) 2009 Intel Corporation.
|
||||||
|
*
|
||||||
|
* This library is free software; you can redistribute it and/or
|
||||||
|
* modify it under the terms of the GNU Lesser General Public
|
||||||
|
* License as published by the Free Software Foundation; either
|
||||||
|
* version 2 of the License, or (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This library is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||||
|
* Lesser General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU Lesser General Public
|
||||||
|
* License along with this library. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef __COGL_PANGO_DISPLAY_LIST_H__
|
||||||
|
#define __COGL_PANGO_DISPLAY_LIST_H__
|
||||||
|
|
||||||
|
#include <glib.h>
|
||||||
|
#include <cogl/cogl.h>
|
||||||
|
|
||||||
|
G_BEGIN_DECLS
|
||||||
|
|
||||||
|
typedef struct _CoglPangoDisplayList CoglPangoDisplayList;
|
||||||
|
|
||||||
|
CoglPangoDisplayList *_cogl_pango_display_list_new (void);
|
||||||
|
|
||||||
|
void _cogl_pango_display_list_set_color (CoglPangoDisplayList *dl,
|
||||||
|
const CoglColor *color);
|
||||||
|
|
||||||
|
void _cogl_pango_display_list_add_texture (CoglPangoDisplayList *dl,
|
||||||
|
CoglHandle texture,
|
||||||
|
float x_1, float y_1,
|
||||||
|
float x_2, float y_2,
|
||||||
|
float tx_1, float ty_1,
|
||||||
|
float tx_2, float ty_2);
|
||||||
|
|
||||||
|
void _cogl_pango_display_list_add_rectangle (CoglPangoDisplayList *dl,
|
||||||
|
float x_1, float y_1,
|
||||||
|
float x_2, float y_2);
|
||||||
|
|
||||||
|
void _cogl_pango_display_list_add_trapezoid (CoglPangoDisplayList *dl,
|
||||||
|
float y_1,
|
||||||
|
float x_11,
|
||||||
|
float x_21,
|
||||||
|
float y_2,
|
||||||
|
float x_12,
|
||||||
|
float x_22);
|
||||||
|
|
||||||
|
void _cogl_pango_display_list_render (CoglPangoDisplayList *dl,
|
||||||
|
CoglHandle glyph_material,
|
||||||
|
CoglHandle solid_material);
|
||||||
|
|
||||||
|
void _cogl_pango_display_list_clear (CoglPangoDisplayList *dl);
|
||||||
|
|
||||||
|
void _cogl_pango_display_list_free (CoglPangoDisplayList *dl);
|
||||||
|
|
||||||
|
G_END_DECLS
|
||||||
|
|
||||||
|
#endif /* __COGL_PANGO_DISPLAY_LIST_H__ */
|
@ -36,6 +36,7 @@
|
|||||||
|
|
||||||
#include "cogl-pango-private.h"
|
#include "cogl-pango-private.h"
|
||||||
#include "cogl-pango-glyph-cache.h"
|
#include "cogl-pango-glyph-cache.h"
|
||||||
|
#include "cogl-pango-display-list.h"
|
||||||
|
|
||||||
struct _CoglPangoRenderer
|
struct _CoglPangoRenderer
|
||||||
{
|
{
|
||||||
@ -55,9 +56,8 @@ struct _CoglPangoRenderer
|
|||||||
|
|
||||||
gboolean use_mipmapping;
|
gboolean use_mipmapping;
|
||||||
|
|
||||||
/* Array of rectangles to draw from the current texture */
|
/* The current display list that is being built */
|
||||||
GArray *glyph_rectangles;
|
CoglPangoDisplayList *display_list;
|
||||||
CoglHandle glyph_texture;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
struct _CoglPangoRendererClass
|
struct _CoglPangoRendererClass
|
||||||
@ -65,20 +65,6 @@ struct _CoglPangoRendererClass
|
|||||||
PangoRendererClass class_instance;
|
PangoRendererClass class_instance;
|
||||||
};
|
};
|
||||||
|
|
||||||
static void
|
|
||||||
cogl_pango_renderer_glyphs_end (CoglPangoRenderer *priv)
|
|
||||||
{
|
|
||||||
if (priv->glyph_rectangles->len > 0)
|
|
||||||
{
|
|
||||||
float *rectangles = (float *) priv->glyph_rectangles->data;
|
|
||||||
cogl_material_set_layer (priv->glyph_material, 0, priv->glyph_texture);
|
|
||||||
cogl_set_source (priv->glyph_material);
|
|
||||||
cogl_rectangles_with_texture_coords (rectangles,
|
|
||||||
priv->glyph_rectangles->len / 8);
|
|
||||||
g_array_set_size (priv->glyph_rectangles, 0);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
static void
|
static void
|
||||||
cogl_pango_renderer_draw_glyph (CoglPangoRenderer *priv,
|
cogl_pango_renderer_draw_glyph (CoglPangoRenderer *priv,
|
||||||
CoglPangoGlyphCacheValue *cache_value,
|
CoglPangoGlyphCacheValue *cache_value,
|
||||||
@ -86,25 +72,19 @@ cogl_pango_renderer_draw_glyph (CoglPangoRenderer *priv,
|
|||||||
float y1)
|
float y1)
|
||||||
{
|
{
|
||||||
float x2, y2;
|
float x2, y2;
|
||||||
float *p;
|
|
||||||
|
|
||||||
if (priv->glyph_rectangles->len > 0
|
g_return_if_fail (priv->display_list != NULL);
|
||||||
&& priv->glyph_texture != cache_value->texture)
|
|
||||||
cogl_pango_renderer_glyphs_end (priv);
|
|
||||||
|
|
||||||
priv->glyph_texture = cache_value->texture;
|
|
||||||
|
|
||||||
x2 = x1 + (float) cache_value->draw_width;
|
x2 = x1 + (float) cache_value->draw_width;
|
||||||
y2 = y1 + (float) cache_value->draw_height;
|
y2 = y1 + (float) cache_value->draw_height;
|
||||||
|
|
||||||
g_array_set_size (priv->glyph_rectangles, priv->glyph_rectangles->len + 8);
|
_cogl_pango_display_list_add_texture (priv->display_list,
|
||||||
p = &g_array_index (priv->glyph_rectangles, float,
|
cache_value->texture,
|
||||||
priv->glyph_rectangles->len - 8);
|
x1, y1, x2, y2,
|
||||||
|
cache_value->tx1,
|
||||||
*(p++) = x1; *(p++) = y1;
|
cache_value->ty1,
|
||||||
*(p++) = x2; *(p++) = y2;
|
cache_value->tx2,
|
||||||
*(p++) = cache_value->tx1; *(p++) = cache_value->ty1;
|
cache_value->ty2);
|
||||||
*(p++) = cache_value->tx2; *(p++) = cache_value->ty2;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static void cogl_pango_renderer_finalize (GObject *object);
|
static void cogl_pango_renderer_finalize (GObject *object);
|
||||||
@ -168,7 +148,6 @@ cogl_pango_renderer_init (CoglPangoRenderer *priv)
|
|||||||
priv->glyph_cache = cogl_pango_glyph_cache_new (FALSE);
|
priv->glyph_cache = cogl_pango_glyph_cache_new (FALSE);
|
||||||
priv->mipmapped_glyph_cache = cogl_pango_glyph_cache_new (TRUE);
|
priv->mipmapped_glyph_cache = cogl_pango_glyph_cache_new (TRUE);
|
||||||
priv->use_mipmapping = FALSE;
|
priv->use_mipmapping = FALSE;
|
||||||
priv->glyph_rectangles = g_array_new (FALSE, FALSE, sizeof (float));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
@ -191,7 +170,6 @@ cogl_pango_renderer_finalize (GObject *object)
|
|||||||
|
|
||||||
cogl_pango_glyph_cache_free (priv->mipmapped_glyph_cache);
|
cogl_pango_glyph_cache_free (priv->mipmapped_glyph_cache);
|
||||||
cogl_pango_glyph_cache_free (priv->glyph_cache);
|
cogl_pango_glyph_cache_free (priv->glyph_cache);
|
||||||
g_array_free (priv->glyph_rectangles, TRUE);
|
|
||||||
|
|
||||||
G_OBJECT_CLASS (cogl_pango_renderer_parent_class)->finalize (object);
|
G_OBJECT_CLASS (cogl_pango_renderer_parent_class)->finalize (object);
|
||||||
}
|
}
|
||||||
@ -213,6 +191,17 @@ cogl_pango_get_renderer_from_context (PangoContext *context)
|
|||||||
return COGL_PANGO_RENDERER (renderer);
|
return COGL_PANGO_RENDERER (renderer);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static GQuark
|
||||||
|
cogl_pango_render_get_display_list_key (void)
|
||||||
|
{
|
||||||
|
static GQuark key = 0;
|
||||||
|
|
||||||
|
if (G_UNLIKELY (key == 0))
|
||||||
|
key = g_quark_from_static_string ("CoglPangoDisplayList");
|
||||||
|
|
||||||
|
return key;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* cogl_pango_render_layout_subpixel:
|
* cogl_pango_render_layout_subpixel:
|
||||||
* @layout: a #PangoLayout
|
* @layout: a #PangoLayout
|
||||||
@ -234,15 +223,35 @@ cogl_pango_render_layout_subpixel (PangoLayout *layout,
|
|||||||
{
|
{
|
||||||
PangoContext *context;
|
PangoContext *context;
|
||||||
CoglPangoRenderer *priv;
|
CoglPangoRenderer *priv;
|
||||||
|
CoglPangoDisplayList *display_list;
|
||||||
|
|
||||||
context = pango_layout_get_context (layout);
|
context = pango_layout_get_context (layout);
|
||||||
priv = cogl_pango_get_renderer_from_context (context);
|
priv = cogl_pango_get_renderer_from_context (context);
|
||||||
if (G_UNLIKELY (!priv))
|
if (G_UNLIKELY (!priv))
|
||||||
return;
|
return;
|
||||||
|
|
||||||
priv->color = *color;
|
display_list = g_object_get_qdata (G_OBJECT (layout),
|
||||||
|
cogl_pango_render_get_display_list_key ());
|
||||||
|
|
||||||
pango_renderer_draw_layout (PANGO_RENDERER (priv), layout, x, y);
|
if (display_list == NULL)
|
||||||
|
{
|
||||||
|
priv->display_list = display_list =_cogl_pango_display_list_new ();
|
||||||
|
priv->color = *color;
|
||||||
|
g_object_set_qdata_full (G_OBJECT (layout),
|
||||||
|
cogl_pango_render_get_display_list_key (),
|
||||||
|
display_list,
|
||||||
|
(GDestroyNotify) _cogl_pango_display_list_free);
|
||||||
|
pango_renderer_draw_layout (PANGO_RENDERER (priv), layout, 0, 0);
|
||||||
|
|
||||||
|
priv->display_list = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
cogl_push_matrix ();
|
||||||
|
cogl_translate (x, y, 0);
|
||||||
|
_cogl_pango_display_list_render (display_list,
|
||||||
|
priv->glyph_material,
|
||||||
|
priv->solid_material);
|
||||||
|
cogl_pop_matrix ();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -296,9 +305,19 @@ cogl_pango_render_layout_line (PangoLayoutLine *line,
|
|||||||
if (G_UNLIKELY (!priv))
|
if (G_UNLIKELY (!priv))
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
priv->display_list = _cogl_pango_display_list_new ();
|
||||||
priv->color = *color;
|
priv->color = *color;
|
||||||
|
|
||||||
pango_renderer_draw_layout_line (PANGO_RENDERER (priv), line, x, y);
|
pango_renderer_draw_layout_line (PANGO_RENDERER (priv), line, x, y);
|
||||||
|
|
||||||
|
cogl_material_set_color (priv->glyph_material, color);
|
||||||
|
cogl_material_set_color (priv->solid_material, color);
|
||||||
|
_cogl_pango_display_list_render (priv->display_list,
|
||||||
|
priv->glyph_material,
|
||||||
|
priv->solid_material);
|
||||||
|
|
||||||
|
_cogl_pango_display_list_free (priv->display_list);
|
||||||
|
priv->display_list = NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
@ -444,8 +463,7 @@ cogl_pango_renderer_set_color_for_part (PangoRenderer *renderer,
|
|||||||
else
|
else
|
||||||
color = priv->color;
|
color = priv->color;
|
||||||
|
|
||||||
cogl_material_set_color (priv->solid_material, &color);
|
_cogl_pango_display_list_set_color (priv->display_list, &color);
|
||||||
cogl_material_set_color (priv->glyph_material, &color);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
@ -457,12 +475,13 @@ cogl_pango_renderer_draw_box (PangoRenderer *renderer,
|
|||||||
{
|
{
|
||||||
CoglPangoRenderer *priv = COGL_PANGO_RENDERER (renderer);
|
CoglPangoRenderer *priv = COGL_PANGO_RENDERER (renderer);
|
||||||
|
|
||||||
cogl_set_source (priv->solid_material);
|
g_return_if_fail (priv->display_list != NULL);
|
||||||
cogl_path_rectangle (x,
|
|
||||||
|
_cogl_pango_display_list_add_rectangle (priv->display_list,
|
||||||
|
x,
|
||||||
y - height,
|
y - height,
|
||||||
x + width,
|
x + width,
|
||||||
y);
|
y);
|
||||||
cogl_path_stroke ();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
@ -500,6 +519,8 @@ cogl_pango_renderer_draw_rectangle (PangoRenderer *renderer,
|
|||||||
CoglPangoRenderer *priv = COGL_PANGO_RENDERER (renderer);
|
CoglPangoRenderer *priv = COGL_PANGO_RENDERER (renderer);
|
||||||
float x1, x2, y1, y2;
|
float x1, x2, y1, y2;
|
||||||
|
|
||||||
|
g_return_if_fail (priv->display_list != NULL);
|
||||||
|
|
||||||
cogl_pango_renderer_set_color_for_part (renderer, part);
|
cogl_pango_renderer_set_color_for_part (renderer, part);
|
||||||
|
|
||||||
cogl_pango_renderer_get_device_units (renderer,
|
cogl_pango_renderer_get_device_units (renderer,
|
||||||
@ -509,8 +530,8 @@ cogl_pango_renderer_draw_rectangle (PangoRenderer *renderer,
|
|||||||
x + width, y + height,
|
x + width, y + height,
|
||||||
&x2, &y2);
|
&x2, &y2);
|
||||||
|
|
||||||
cogl_set_source (priv->solid_material);
|
_cogl_pango_display_list_add_rectangle (priv->display_list,
|
||||||
cogl_rectangle (x1, y1, x2, y2);
|
x1, y1, x2, y2);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
@ -526,6 +547,8 @@ cogl_pango_renderer_draw_trapezoid (PangoRenderer *renderer,
|
|||||||
CoglPangoRenderer *priv = COGL_PANGO_RENDERER (renderer);
|
CoglPangoRenderer *priv = COGL_PANGO_RENDERER (renderer);
|
||||||
float points[8];
|
float points[8];
|
||||||
|
|
||||||
|
g_return_if_fail (priv->display_list != NULL);
|
||||||
|
|
||||||
points[0] = (x11);
|
points[0] = (x11);
|
||||||
points[1] = (y1);
|
points[1] = (y1);
|
||||||
points[2] = (x12);
|
points[2] = (x12);
|
||||||
@ -537,9 +560,13 @@ cogl_pango_renderer_draw_trapezoid (PangoRenderer *renderer,
|
|||||||
|
|
||||||
cogl_pango_renderer_set_color_for_part (renderer, part);
|
cogl_pango_renderer_set_color_for_part (renderer, part);
|
||||||
|
|
||||||
cogl_set_source (priv->solid_material);
|
_cogl_pango_display_list_add_trapezoid (priv->display_list,
|
||||||
cogl_path_polygon (points, 4);
|
y1,
|
||||||
cogl_path_fill ();
|
x11,
|
||||||
|
x21,
|
||||||
|
y2,
|
||||||
|
x12,
|
||||||
|
x22);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
@ -570,8 +597,6 @@ cogl_pango_renderer_draw_glyphs (PangoRenderer *renderer,
|
|||||||
{
|
{
|
||||||
PangoFontMetrics *metrics;
|
PangoFontMetrics *metrics;
|
||||||
|
|
||||||
cogl_pango_renderer_glyphs_end (priv);
|
|
||||||
|
|
||||||
if (font == NULL ||
|
if (font == NULL ||
|
||||||
(metrics = pango_font_get_metrics (font, NULL)) == NULL)
|
(metrics = pango_font_get_metrics (font, NULL)) == NULL)
|
||||||
{
|
{
|
||||||
@ -603,15 +628,11 @@ cogl_pango_renderer_draw_glyphs (PangoRenderer *renderer,
|
|||||||
gi->glyph);
|
gi->glyph);
|
||||||
|
|
||||||
if (cache_value == NULL)
|
if (cache_value == NULL)
|
||||||
{
|
|
||||||
cogl_pango_renderer_glyphs_end (priv);
|
|
||||||
|
|
||||||
cogl_pango_renderer_draw_box (renderer,
|
cogl_pango_renderer_draw_box (renderer,
|
||||||
x,
|
x,
|
||||||
y,
|
y,
|
||||||
PANGO_UNKNOWN_GLYPH_WIDTH,
|
PANGO_UNKNOWN_GLYPH_WIDTH,
|
||||||
PANGO_UNKNOWN_GLYPH_HEIGHT);
|
PANGO_UNKNOWN_GLYPH_HEIGHT);
|
||||||
}
|
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
float width, height;
|
float width, height;
|
||||||
@ -628,6 +649,4 @@ cogl_pango_renderer_draw_glyphs (PangoRenderer *renderer,
|
|||||||
|
|
||||||
xi += gi->geometry.width;
|
xi += gi->geometry.width;
|
||||||
}
|
}
|
||||||
|
|
||||||
cogl_pango_renderer_glyphs_end (priv);
|
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user