clutter/pango: Rename types post merge
The rename didnt happen as part of the merge as various bits were removed the commits after, reducing the amount of required changes Part-of: <https://gitlab.gnome.org/GNOME/mutter/-/merge_requests/4004>
This commit is contained in:
parent
f60e9e5e0d
commit
463c36880e
@ -31,7 +31,7 @@
|
|||||||
#include "clutter/clutter-private.h"
|
#include "clutter/clutter-private.h"
|
||||||
#include "clutter/clutter-paint-node-private.h"
|
#include "clutter/clutter-paint-node-private.h"
|
||||||
#include "clutter/clutter-settings-private.h"
|
#include "clutter/clutter-settings-private.h"
|
||||||
#include "clutter/pango/cogl-pango-private.h"
|
#include "clutter/pango/clutter-pango-private.h"
|
||||||
|
|
||||||
static gboolean clutter_show_fps = FALSE;
|
static gboolean clutter_show_fps = FALSE;
|
||||||
static gboolean clutter_enable_accessibility = TRUE;
|
static gboolean clutter_enable_accessibility = TRUE;
|
||||||
@ -321,7 +321,7 @@ clutter_context_get_pango_fontmap (ClutterContext *context)
|
|||||||
backend = clutter_context_get_backend (context);
|
backend = clutter_context_get_backend (context);
|
||||||
cogl_context = clutter_backend_get_cogl_context (backend);
|
cogl_context = clutter_backend_get_cogl_context (backend);
|
||||||
font_map = pango_cairo_font_map_new ();
|
font_map = pango_cairo_font_map_new ();
|
||||||
font_renderer = _cogl_pango_renderer_new (cogl_context);
|
font_renderer = clutter_pango_renderer_new (cogl_context);
|
||||||
|
|
||||||
resolution = clutter_backend_get_resolution (context->backend);
|
resolution = clutter_backend_get_resolution (context->backend);
|
||||||
pango_cairo_font_map_set_resolution (PANGO_CAIRO_FONT_MAP (font_map),
|
pango_cairo_font_map_set_resolution (PANGO_CAIRO_FONT_MAP (font_map),
|
||||||
|
@ -30,7 +30,7 @@
|
|||||||
#include <pango/pango.h>
|
#include <pango/pango.h>
|
||||||
|
|
||||||
#include "cogl/cogl.h"
|
#include "cogl/cogl.h"
|
||||||
#include "clutter/pango/cogl-pango-private.h"
|
#include "clutter/pango/clutter-pango-private.h"
|
||||||
#include "clutter/clutter-actor-private.h"
|
#include "clutter/clutter-actor-private.h"
|
||||||
#include "clutter/clutter-blur-private.h"
|
#include "clutter/clutter-blur-private.h"
|
||||||
#include "clutter/clutter-debug.h"
|
#include "clutter/clutter-debug.h"
|
||||||
|
@ -46,7 +46,7 @@
|
|||||||
|
|
||||||
#include "clutter/clutter-text.h"
|
#include "clutter/clutter-text.h"
|
||||||
|
|
||||||
#include "clutter/pango/cogl-pango-private.h"
|
#include "clutter/pango/clutter-pango-private.h"
|
||||||
#include "clutter/clutter-text-accessible-private.h"
|
#include "clutter/clutter-text-accessible-private.h"
|
||||||
#include "clutter/clutter-actor-private.h"
|
#include "clutter/clutter-actor-private.h"
|
||||||
#include "clutter/clutter-animatable.h"
|
#include "clutter/clutter-animatable.h"
|
||||||
|
@ -84,10 +84,10 @@ clutter_headers = [
|
|||||||
]
|
]
|
||||||
|
|
||||||
clutter_sources = [
|
clutter_sources = [
|
||||||
'pango/cogl-pango-display-list.c',
|
'pango/clutter-pango-display-list.c',
|
||||||
'pango/cogl-pango-glyph-cache.c',
|
'pango/clutter-pango-glyph-cache.c',
|
||||||
'pango/cogl-pango-pipeline-cache.c',
|
'pango/clutter-pango-pipeline-cache.c',
|
||||||
'pango/cogl-pango-render.c',
|
'pango/clutter-pango-render.c',
|
||||||
'clutter-accessibility.c',
|
'clutter-accessibility.c',
|
||||||
'clutter-action.c',
|
'clutter-action.c',
|
||||||
'clutter-actor-box.c',
|
'clutter-actor-box.c',
|
||||||
@ -181,10 +181,10 @@ clutter_sources = [
|
|||||||
]
|
]
|
||||||
|
|
||||||
clutter_private_headers = [
|
clutter_private_headers = [
|
||||||
'pango/cogl-pango-display-list.h',
|
'pango/clutter-pango-display-list.h',
|
||||||
'pango/cogl-pango-glyph-cache.h',
|
'pango/clutter-pango-glyph-cache.h',
|
||||||
'pango/cogl-pango-pipeline-cache.h',
|
'pango/clutter-pango-pipeline-cache.h',
|
||||||
'pango/cogl-pango-private.h',
|
'pango/clutter-pango-private.h',
|
||||||
'clutter-accessibility-private.h',
|
'clutter-accessibility-private.h',
|
||||||
'clutter-actor-meta-private.h',
|
'clutter-actor-meta-private.h',
|
||||||
'clutter-actor-private.h',
|
'clutter-actor-private.h',
|
||||||
|
@ -31,39 +31,36 @@
|
|||||||
#include <glib.h>
|
#include <glib.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
|
|
||||||
#include "clutter/pango/cogl-pango-display-list.h"
|
#include "clutter/pango/clutter-pango-display-list.h"
|
||||||
#include "clutter/pango/cogl-pango-pipeline-cache.h"
|
#include "clutter/pango/clutter-pango-pipeline-cache.h"
|
||||||
#include "cogl/cogl.h"
|
#include "cogl/cogl.h"
|
||||||
|
|
||||||
typedef enum
|
typedef enum
|
||||||
{
|
{
|
||||||
COGL_PANGO_DISPLAY_LIST_TEXTURE,
|
PANGO_DISPLAY_LIST_TEXTURE,
|
||||||
COGL_PANGO_DISPLAY_LIST_RECTANGLE,
|
PANGO_DISPLAY_LIST_RECTANGLE,
|
||||||
COGL_PANGO_DISPLAY_LIST_TRAPEZOID
|
PANGO_DISPLAY_LIST_TRAPEZOID
|
||||||
} CoglPangoDisplayListNodeType;
|
} PangoDisplayListNodeType;
|
||||||
|
|
||||||
typedef struct _CoglPangoDisplayListNode CoglPangoDisplayListNode;
|
struct _ClutterPangoDisplayList
|
||||||
typedef struct _CoglPangoDisplayListRectangle CoglPangoDisplayListRectangle;
|
|
||||||
|
|
||||||
struct _CoglPangoDisplayList
|
|
||||||
{
|
{
|
||||||
gboolean color_override;
|
gboolean color_override;
|
||||||
CoglColor color;
|
CoglColor color;
|
||||||
GSList *nodes;
|
GSList *nodes;
|
||||||
GSList *last_node;
|
GSList *last_node;
|
||||||
CoglPangoPipelineCache *pipeline_cache;
|
ClutterPangoPipelineCache *pipeline_cache;
|
||||||
};
|
};
|
||||||
|
|
||||||
/* This matches the format expected by cogl_rectangles_with_texture_coords */
|
/* This matches the format expected by cogl_rectangles_with_texture_coords */
|
||||||
struct _CoglPangoDisplayListRectangle
|
typedef struct _PangoDisplayListRectangle
|
||||||
{
|
{
|
||||||
float x_1, y_1, x_2, y_2;
|
float x_1, y_1, x_2, y_2;
|
||||||
float s_1, t_1, s_2, t_2;
|
float s_1, t_1, s_2, t_2;
|
||||||
};
|
} PangoDisplayListRectangle;
|
||||||
|
|
||||||
struct _CoglPangoDisplayListNode
|
typedef struct _PangoDisplayListNode
|
||||||
{
|
{
|
||||||
CoglPangoDisplayListNodeType type;
|
PangoDisplayListNodeType type;
|
||||||
|
|
||||||
gboolean color_override;
|
gboolean color_override;
|
||||||
CoglColor color;
|
CoglColor color;
|
||||||
@ -95,12 +92,12 @@ struct _CoglPangoDisplayListNode
|
|||||||
CoglPrimitive *primitive;
|
CoglPrimitive *primitive;
|
||||||
} trapezoid;
|
} trapezoid;
|
||||||
} d;
|
} d;
|
||||||
};
|
} PangoDisplayListNode;
|
||||||
|
|
||||||
CoglPangoDisplayList *
|
ClutterPangoDisplayList *
|
||||||
_cogl_pango_display_list_new (CoglPangoPipelineCache *pipeline_cache)
|
clutter_pango_display_list_new (ClutterPangoPipelineCache *pipeline_cache)
|
||||||
{
|
{
|
||||||
CoglPangoDisplayList *dl = g_new0 (CoglPangoDisplayList, 1);
|
ClutterPangoDisplayList *dl = g_new0 (ClutterPangoDisplayList, 1);
|
||||||
|
|
||||||
dl->pipeline_cache = pipeline_cache;
|
dl->pipeline_cache = pipeline_cache;
|
||||||
|
|
||||||
@ -108,8 +105,8 @@ _cogl_pango_display_list_new (CoglPangoPipelineCache *pipeline_cache)
|
|||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
_cogl_pango_display_list_append_node (CoglPangoDisplayList *dl,
|
clutter_pango_display_list_append_node (ClutterPangoDisplayList *dl,
|
||||||
CoglPangoDisplayListNode *node)
|
PangoDisplayListNode *node)
|
||||||
{
|
{
|
||||||
if (dl->last_node)
|
if (dl->last_node)
|
||||||
dl->last_node = dl->last_node->next = g_slist_prepend (NULL, node);
|
dl->last_node = dl->last_node->next = g_slist_prepend (NULL, node);
|
||||||
@ -118,34 +115,38 @@ _cogl_pango_display_list_append_node (CoglPangoDisplayList *dl,
|
|||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
_cogl_pango_display_list_set_color_override (CoglPangoDisplayList *dl,
|
clutter_pango_display_list_set_color_override (ClutterPangoDisplayList *dl,
|
||||||
const CoglColor *color)
|
const CoglColor *color)
|
||||||
{
|
{
|
||||||
dl->color_override = TRUE;
|
dl->color_override = TRUE;
|
||||||
dl->color = *color;
|
dl->color = *color;
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
_cogl_pango_display_list_remove_color_override (CoglPangoDisplayList *dl)
|
clutter_pango_display_list_remove_color_override (ClutterPangoDisplayList *dl)
|
||||||
{
|
{
|
||||||
dl->color_override = FALSE;
|
dl->color_override = FALSE;
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
_cogl_pango_display_list_add_texture (CoglPangoDisplayList *dl,
|
clutter_pango_display_list_add_texture (ClutterPangoDisplayList *dl,
|
||||||
CoglTexture *texture,
|
CoglTexture *texture,
|
||||||
float x_1, float y_1,
|
float x_1,
|
||||||
float x_2, float y_2,
|
float y_1,
|
||||||
float tx_1, float ty_1,
|
float x_2,
|
||||||
float tx_2, float ty_2)
|
float y_2,
|
||||||
|
float tx_1,
|
||||||
|
float ty_1,
|
||||||
|
float tx_2,
|
||||||
|
float ty_2)
|
||||||
{
|
{
|
||||||
CoglPangoDisplayListNode *node;
|
PangoDisplayListNode *node;
|
||||||
CoglPangoDisplayListRectangle *rectangle;
|
PangoDisplayListRectangle *rectangle;
|
||||||
|
|
||||||
/* Add to the last node if it is a texture node with the same
|
/* Add to the last node if it is a texture node with the same
|
||||||
target texture */
|
target texture */
|
||||||
if (dl->last_node
|
if (dl->last_node
|
||||||
&& (node = dl->last_node->data)->type == COGL_PANGO_DISPLAY_LIST_TEXTURE
|
&& (node = dl->last_node->data)->type == PANGO_DISPLAY_LIST_TEXTURE
|
||||||
&& node->d.texture.texture == texture
|
&& node->d.texture.texture == texture
|
||||||
&& (dl->color_override
|
&& (dl->color_override
|
||||||
? (node->color_override && cogl_color_equal (&dl->color, &node->color))
|
? (node->color_override && cogl_color_equal (&dl->color, &node->color))
|
||||||
@ -157,24 +158,24 @@ _cogl_pango_display_list_add_texture (CoglPangoDisplayList *dl,
|
|||||||
else
|
else
|
||||||
{
|
{
|
||||||
/* Otherwise create a new node */
|
/* Otherwise create a new node */
|
||||||
node = g_new0 (CoglPangoDisplayListNode, 1);
|
node = g_new0 (PangoDisplayListNode, 1);
|
||||||
|
|
||||||
node->type = COGL_PANGO_DISPLAY_LIST_TEXTURE;
|
node->type = PANGO_DISPLAY_LIST_TEXTURE;
|
||||||
node->color_override = dl->color_override;
|
node->color_override = dl->color_override;
|
||||||
node->color = dl->color;
|
node->color = dl->color;
|
||||||
node->pipeline = NULL;
|
node->pipeline = NULL;
|
||||||
node->d.texture.texture = g_object_ref (texture);
|
node->d.texture.texture = g_object_ref (texture);
|
||||||
node->d.texture.rectangles
|
node->d.texture.rectangles
|
||||||
= g_array_new (FALSE, FALSE, sizeof (CoglPangoDisplayListRectangle));
|
= g_array_new (FALSE, FALSE, sizeof (PangoDisplayListRectangle));
|
||||||
node->d.texture.primitive = NULL;
|
node->d.texture.primitive = NULL;
|
||||||
|
|
||||||
_cogl_pango_display_list_append_node (dl, node);
|
clutter_pango_display_list_append_node (dl, node);
|
||||||
}
|
}
|
||||||
|
|
||||||
g_array_set_size (node->d.texture.rectangles,
|
g_array_set_size (node->d.texture.rectangles,
|
||||||
node->d.texture.rectangles->len + 1);
|
node->d.texture.rectangles->len + 1);
|
||||||
rectangle = &g_array_index (node->d.texture.rectangles,
|
rectangle = &g_array_index (node->d.texture.rectangles,
|
||||||
CoglPangoDisplayListRectangle,
|
PangoDisplayListRectangle,
|
||||||
node->d.texture.rectangles->len - 1);
|
node->d.texture.rectangles->len - 1);
|
||||||
rectangle->x_1 = x_1;
|
rectangle->x_1 = x_1;
|
||||||
rectangle->y_1 = y_1;
|
rectangle->y_1 = y_1;
|
||||||
@ -187,13 +188,15 @@ _cogl_pango_display_list_add_texture (CoglPangoDisplayList *dl,
|
|||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
_cogl_pango_display_list_add_rectangle (CoglPangoDisplayList *dl,
|
clutter_pango_display_list_add_rectangle (ClutterPangoDisplayList *dl,
|
||||||
float x_1, float y_1,
|
float x_1,
|
||||||
float x_2, float y_2)
|
float y_1,
|
||||||
|
float x_2,
|
||||||
|
float y_2)
|
||||||
{
|
{
|
||||||
CoglPangoDisplayListNode *node = g_new0 (CoglPangoDisplayListNode, 1);
|
PangoDisplayListNode *node = g_new0 (PangoDisplayListNode, 1);
|
||||||
|
|
||||||
node->type = COGL_PANGO_DISPLAY_LIST_RECTANGLE;
|
node->type = PANGO_DISPLAY_LIST_RECTANGLE;
|
||||||
node->color_override = dl->color_override;
|
node->color_override = dl->color_override;
|
||||||
node->color = dl->color;
|
node->color = dl->color;
|
||||||
node->d.rectangle.x_1 = x_1;
|
node->d.rectangle.x_1 = x_1;
|
||||||
@ -202,20 +205,20 @@ _cogl_pango_display_list_add_rectangle (CoglPangoDisplayList *dl,
|
|||||||
node->d.rectangle.y_2 = y_2;
|
node->d.rectangle.y_2 = y_2;
|
||||||
node->pipeline = NULL;
|
node->pipeline = NULL;
|
||||||
|
|
||||||
_cogl_pango_display_list_append_node (dl, node);
|
clutter_pango_display_list_append_node (dl, node);
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
_cogl_pango_display_list_add_trapezoid (CoglPangoDisplayList *dl,
|
clutter_pango_display_list_add_trapezoid (ClutterPangoDisplayList *dl,
|
||||||
float y_1,
|
float y_1,
|
||||||
float x_11,
|
float x_11,
|
||||||
float x_21,
|
float x_21,
|
||||||
float y_2,
|
float y_2,
|
||||||
float x_12,
|
float x_12,
|
||||||
float x_22)
|
float x_22)
|
||||||
{
|
{
|
||||||
CoglContext *ctx = dl->pipeline_cache->ctx;
|
CoglContext *ctx = dl->pipeline_cache->ctx;
|
||||||
CoglPangoDisplayListNode *node = g_new0 (CoglPangoDisplayListNode, 1);
|
PangoDisplayListNode *node = g_new0 (PangoDisplayListNode, 1);
|
||||||
CoglVertexP2 vertices[4] = {
|
CoglVertexP2 vertices[4] = {
|
||||||
{ x_11, y_1 },
|
{ x_11, y_1 },
|
||||||
{ x_12, y_2 },
|
{ x_12, y_2 },
|
||||||
@ -223,7 +226,7 @@ _cogl_pango_display_list_add_trapezoid (CoglPangoDisplayList *dl,
|
|||||||
{ x_21, y_1 }
|
{ x_21, y_1 }
|
||||||
};
|
};
|
||||||
|
|
||||||
node->type = COGL_PANGO_DISPLAY_LIST_TRAPEZOID;
|
node->type = PANGO_DISPLAY_LIST_TRAPEZOID;
|
||||||
node->color_override = dl->color_override;
|
node->color_override = dl->color_override;
|
||||||
node->color = dl->color;
|
node->color = dl->color;
|
||||||
node->pipeline = NULL;
|
node->pipeline = NULL;
|
||||||
@ -234,13 +237,13 @@ _cogl_pango_display_list_add_trapezoid (CoglPangoDisplayList *dl,
|
|||||||
4,
|
4,
|
||||||
vertices);
|
vertices);
|
||||||
|
|
||||||
_cogl_pango_display_list_append_node (dl, node);
|
clutter_pango_display_list_append_node (dl, node);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
emit_rectangles_through_journal (CoglFramebuffer *fb,
|
emit_rectangles_through_journal (CoglFramebuffer *fb,
|
||||||
CoglPipeline *pipeline,
|
CoglPipeline *pipeline,
|
||||||
CoglPangoDisplayListNode *node)
|
PangoDisplayListNode *node)
|
||||||
{
|
{
|
||||||
const float *rectangles = (const float *)node->d.texture.rectangles->data;
|
const float *rectangles = (const float *)node->d.texture.rectangles->data;
|
||||||
|
|
||||||
@ -253,7 +256,7 @@ emit_rectangles_through_journal (CoglFramebuffer *fb,
|
|||||||
static void
|
static void
|
||||||
emit_vertex_buffer_geometry (CoglFramebuffer *fb,
|
emit_vertex_buffer_geometry (CoglFramebuffer *fb,
|
||||||
CoglPipeline *pipeline,
|
CoglPipeline *pipeline,
|
||||||
CoglPangoDisplayListNode *node)
|
PangoDisplayListNode *node)
|
||||||
{
|
{
|
||||||
CoglContext *ctx = cogl_framebuffer_get_context (fb);
|
CoglContext *ctx = cogl_framebuffer_get_context (fb);
|
||||||
|
|
||||||
@ -297,9 +300,9 @@ emit_vertex_buffer_geometry (CoglFramebuffer *fb,
|
|||||||
vertices instead of just two */
|
vertices instead of just two */
|
||||||
for (i = 0; i < node->d.texture.rectangles->len; i++)
|
for (i = 0; i < node->d.texture.rectangles->len; i++)
|
||||||
{
|
{
|
||||||
const CoglPangoDisplayListRectangle *rectangle
|
const PangoDisplayListRectangle *rectangle
|
||||||
= &g_array_index (node->d.texture.rectangles,
|
= &g_array_index (node->d.texture.rectangles,
|
||||||
CoglPangoDisplayListRectangle, i);
|
PangoDisplayListRectangle, i);
|
||||||
|
|
||||||
v->x = rectangle->x_1;
|
v->x = rectangle->x_1;
|
||||||
v->y = rectangle->y_1;
|
v->y = rectangle->y_1;
|
||||||
@ -373,7 +376,7 @@ emit_vertex_buffer_geometry (CoglFramebuffer *fb,
|
|||||||
static void
|
static void
|
||||||
_cogl_framebuffer_draw_display_list_texture (CoglFramebuffer *fb,
|
_cogl_framebuffer_draw_display_list_texture (CoglFramebuffer *fb,
|
||||||
CoglPipeline *pipeline,
|
CoglPipeline *pipeline,
|
||||||
CoglPangoDisplayListNode *node)
|
PangoDisplayListNode *node)
|
||||||
{
|
{
|
||||||
/* For small runs of text like icon labels, we can get better performance
|
/* For small runs of text like icon labels, we can get better performance
|
||||||
* going through the Cogl journal since text may then be batched together
|
* going through the Cogl journal since text may then be batched together
|
||||||
@ -387,30 +390,30 @@ _cogl_framebuffer_draw_display_list_texture (CoglFramebuffer *fb,
|
|||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
cogl_pango_display_list_render (CoglFramebuffer *fb,
|
clutter_pango_display_list_render (CoglFramebuffer *fb,
|
||||||
CoglPangoDisplayList *dl,
|
ClutterPangoDisplayList *dl,
|
||||||
ClutterColorState *color_state,
|
ClutterColorState *color_state,
|
||||||
ClutterColorState *target_color_state,
|
ClutterColorState *target_color_state,
|
||||||
const CoglColor *color)
|
const CoglColor *color)
|
||||||
{
|
{
|
||||||
GSList *l;
|
GSList *l;
|
||||||
|
|
||||||
for (l = dl->nodes; l; l = l->next)
|
for (l = dl->nodes; l; l = l->next)
|
||||||
{
|
{
|
||||||
CoglPangoDisplayListNode *node = l->data;
|
PangoDisplayListNode *node = l->data;
|
||||||
CoglColor draw_color;
|
CoglColor draw_color;
|
||||||
g_autoptr (CoglPipeline) pipeline = NULL;
|
g_autoptr (CoglPipeline) pipeline = NULL;
|
||||||
|
|
||||||
if (node->pipeline == NULL)
|
if (node->pipeline == NULL)
|
||||||
{
|
{
|
||||||
if (node->type == COGL_PANGO_DISPLAY_LIST_TEXTURE)
|
if (node->type == PANGO_DISPLAY_LIST_TEXTURE)
|
||||||
node->pipeline =
|
node->pipeline =
|
||||||
_cogl_pango_pipeline_cache_get (dl->pipeline_cache,
|
clutter_pango_pipeline_cache_get (dl->pipeline_cache,
|
||||||
node->d.texture.texture);
|
node->d.texture.texture);
|
||||||
else
|
else
|
||||||
node->pipeline =
|
node->pipeline =
|
||||||
_cogl_pango_pipeline_cache_get (dl->pipeline_cache,
|
clutter_pango_pipeline_cache_get (dl->pipeline_cache,
|
||||||
NULL);
|
NULL);
|
||||||
}
|
}
|
||||||
|
|
||||||
pipeline = cogl_pipeline_copy (node->pipeline);
|
pipeline = cogl_pipeline_copy (node->pipeline);
|
||||||
@ -437,11 +440,11 @@ cogl_pango_display_list_render (CoglFramebuffer *fb,
|
|||||||
|
|
||||||
switch (node->type)
|
switch (node->type)
|
||||||
{
|
{
|
||||||
case COGL_PANGO_DISPLAY_LIST_TEXTURE:
|
case PANGO_DISPLAY_LIST_TEXTURE:
|
||||||
_cogl_framebuffer_draw_display_list_texture (fb, pipeline, node);
|
_cogl_framebuffer_draw_display_list_texture (fb, pipeline, node);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case COGL_PANGO_DISPLAY_LIST_RECTANGLE:
|
case PANGO_DISPLAY_LIST_RECTANGLE:
|
||||||
cogl_framebuffer_draw_rectangle (fb,
|
cogl_framebuffer_draw_rectangle (fb,
|
||||||
pipeline,
|
pipeline,
|
||||||
node->d.rectangle.x_1,
|
node->d.rectangle.x_1,
|
||||||
@ -450,7 +453,7 @@ cogl_pango_display_list_render (CoglFramebuffer *fb,
|
|||||||
node->d.rectangle.y_2);
|
node->d.rectangle.y_2);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case COGL_PANGO_DISPLAY_LIST_TRAPEZOID:
|
case PANGO_DISPLAY_LIST_TRAPEZOID:
|
||||||
cogl_primitive_draw (node->d.trapezoid.primitive,
|
cogl_primitive_draw (node->d.trapezoid.primitive,
|
||||||
fb,
|
fb,
|
||||||
pipeline);
|
pipeline);
|
||||||
@ -460,15 +463,15 @@ cogl_pango_display_list_render (CoglFramebuffer *fb,
|
|||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
_cogl_pango_display_list_node_free (CoglPangoDisplayListNode *node)
|
clutter_pango_display_list_node_free (PangoDisplayListNode *node)
|
||||||
{
|
{
|
||||||
if (node->type == COGL_PANGO_DISPLAY_LIST_TEXTURE)
|
if (node->type == PANGO_DISPLAY_LIST_TEXTURE)
|
||||||
{
|
{
|
||||||
g_array_free (node->d.texture.rectangles, TRUE);
|
g_array_free (node->d.texture.rectangles, TRUE);
|
||||||
g_clear_object (&node->d.texture.texture);
|
g_clear_object (&node->d.texture.texture);
|
||||||
g_clear_object (&node->d.texture.primitive);
|
g_clear_object (&node->d.texture.primitive);
|
||||||
}
|
}
|
||||||
else if (node->type == COGL_PANGO_DISPLAY_LIST_TRAPEZOID)
|
else if (node->type == PANGO_DISPLAY_LIST_TRAPEZOID)
|
||||||
g_clear_object (&node->d.trapezoid.primitive);
|
g_clear_object (&node->d.trapezoid.primitive);
|
||||||
|
|
||||||
g_clear_object (&node->pipeline);
|
g_clear_object (&node->pipeline);
|
||||||
@ -477,10 +480,10 @@ _cogl_pango_display_list_node_free (CoglPangoDisplayListNode *node)
|
|||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
_cogl_pango_display_list_free (CoglPangoDisplayList *dl)
|
clutter_pango_display_list_free (ClutterPangoDisplayList *dl)
|
||||||
{
|
{
|
||||||
g_slist_free_full (dl->nodes, (GDestroyNotify)
|
g_slist_free_full (dl->nodes, (GDestroyNotify)
|
||||||
_cogl_pango_display_list_node_free);
|
clutter_pango_display_list_node_free);
|
||||||
dl->nodes = NULL;
|
dl->nodes = NULL;
|
||||||
dl->last_node = NULL;
|
dl->last_node = NULL;
|
||||||
g_free (dl);
|
g_free (dl);
|
89
clutter/clutter/pango/clutter-pango-display-list.h
Normal file
89
clutter/clutter/pango/clutter-pango-display-list.h
Normal file
@ -0,0 +1,89 @@
|
|||||||
|
/*
|
||||||
|
* Clutter.
|
||||||
|
*
|
||||||
|
* An OpenGL based 'interactive canvas' library.
|
||||||
|
*
|
||||||
|
* Copyright (C) 2009 Intel Corporation.
|
||||||
|
*
|
||||||
|
* Permission is hereby granted, free of charge, to any person
|
||||||
|
* obtaining a copy of this software and associated documentation
|
||||||
|
* files (the "Software"), to deal in the Software without
|
||||||
|
* restriction, including without limitation the rights to use, copy,
|
||||||
|
* modify, merge, publish, distribute, sublicense, and/or sell copies
|
||||||
|
* of the Software, and to permit persons to whom the Software is
|
||||||
|
* furnished to do so, subject to the following conditions:
|
||||||
|
*
|
||||||
|
* The above copyright notice and this permission notice shall be
|
||||||
|
* included in all copies or substantial portions of the Software.
|
||||||
|
*
|
||||||
|
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||||
|
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||||
|
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||||
|
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
|
||||||
|
* BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
|
||||||
|
* ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||||
|
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||||
|
* SOFTWARE.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <glib.h>
|
||||||
|
|
||||||
|
#include "clutter/pango/clutter-pango-pipeline-cache.h"
|
||||||
|
#include "clutter/clutter-color-state.h"
|
||||||
|
|
||||||
|
|
||||||
|
G_BEGIN_DECLS
|
||||||
|
|
||||||
|
typedef struct _ClutterPangoDisplayList ClutterPangoDisplayList;
|
||||||
|
|
||||||
|
ClutterPangoDisplayList *
|
||||||
|
clutter_pango_display_list_new (ClutterPangoPipelineCache *pipeline_cache);
|
||||||
|
|
||||||
|
void
|
||||||
|
clutter_pango_display_list_set_color_override (ClutterPangoDisplayList *dl,
|
||||||
|
const CoglColor *color);
|
||||||
|
|
||||||
|
void
|
||||||
|
clutter_pango_display_list_remove_color_override (ClutterPangoDisplayList *dl);
|
||||||
|
|
||||||
|
void
|
||||||
|
clutter_pango_display_list_add_texture (ClutterPangoDisplayList *dl,
|
||||||
|
CoglTexture *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
|
||||||
|
clutter_pango_display_list_add_rectangle (ClutterPangoDisplayList *dl,
|
||||||
|
float x_1,
|
||||||
|
float y_1,
|
||||||
|
float x_2,
|
||||||
|
float y_2);
|
||||||
|
|
||||||
|
void
|
||||||
|
clutter_pango_display_list_add_trapezoid (ClutterPangoDisplayList *dl,
|
||||||
|
float y_1,
|
||||||
|
float x_11,
|
||||||
|
float x_21,
|
||||||
|
float y_2,
|
||||||
|
float x_12,
|
||||||
|
float x_22);
|
||||||
|
|
||||||
|
void
|
||||||
|
clutter_pango_display_list_render (CoglFramebuffer *framebuffer,
|
||||||
|
ClutterPangoDisplayList *dl,
|
||||||
|
ClutterColorState *color_state,
|
||||||
|
ClutterColorState *target_color_state,
|
||||||
|
const CoglColor *color);
|
||||||
|
|
||||||
|
void
|
||||||
|
clutter_pango_display_list_free (ClutterPangoDisplayList *dl);
|
||||||
|
|
||||||
|
G_END_DECLS
|
@ -33,12 +33,10 @@
|
|||||||
#include <pango/pangocairo.h>
|
#include <pango/pangocairo.h>
|
||||||
|
|
||||||
#include "clutter/clutter-debug.h"
|
#include "clutter/clutter-debug.h"
|
||||||
#include "clutter/pango/cogl-pango-glyph-cache.h"
|
#include "clutter/pango/clutter-pango-glyph-cache.h"
|
||||||
#include "clutter/pango/cogl-pango-private.h"
|
#include "clutter/pango/clutter-pango-private.h"
|
||||||
|
|
||||||
typedef struct _CoglPangoGlyphCacheKey CoglPangoGlyphCacheKey;
|
struct _ClutterPangoGlyphCache
|
||||||
|
|
||||||
struct _CoglPangoGlyphCache
|
|
||||||
{
|
{
|
||||||
CoglContext *ctx;
|
CoglContext *ctx;
|
||||||
|
|
||||||
@ -50,44 +48,43 @@ struct _CoglPangoGlyphCache
|
|||||||
GSList *atlases;
|
GSList *atlases;
|
||||||
|
|
||||||
/* List of callbacks to invoke when an atlas is reorganized */
|
/* List of callbacks to invoke when an atlas is reorganized */
|
||||||
GHookList reorganize_callbacks;
|
GHookList reorganize_callbacks;
|
||||||
|
|
||||||
/* TRUE if we've ever stored a texture in the global atlas. This is
|
/* TRUE if we've ever stored a texture in the global atlas. This is
|
||||||
used to make sure we only register one callback to listen for
|
used to make sure we only register one callback to listen for
|
||||||
global atlas reorganizations */
|
global atlas reorganizations */
|
||||||
gboolean using_global_atlas;
|
gboolean using_global_atlas;
|
||||||
|
|
||||||
/* True if some of the glyphs are dirty. This is used as an
|
/* True if some of the glyphs are dirty. This is used as an
|
||||||
optimization in _cogl_pango_glyph_cache_set_dirty_glyphs to avoid
|
optimization in clutter_pango_glyph_cache_set_dirty_glyphs to avoid
|
||||||
iterating the hash table if we know none of them are dirty */
|
iterating the hash table if we know none of them are dirty */
|
||||||
gboolean has_dirty_glyphs;
|
gboolean has_dirty_glyphs;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct _CoglPangoGlyphCacheKey
|
typedef struct _PangoGlyphCacheKey
|
||||||
{
|
{
|
||||||
PangoFont *font;
|
PangoFont *font;
|
||||||
PangoGlyph glyph;
|
PangoGlyph glyph;
|
||||||
};
|
} PangoGlyphCacheKey;
|
||||||
|
|
||||||
static void
|
static void
|
||||||
cogl_pango_glyph_cache_value_free (CoglPangoGlyphCacheValue *value)
|
clutter_pango_glyph_cache_value_free (PangoGlyphCacheValue *value)
|
||||||
{
|
{
|
||||||
g_clear_object (&value->texture);
|
g_clear_object (&value->texture);
|
||||||
g_free (value);
|
g_free (value);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
cogl_pango_glyph_cache_key_free (CoglPangoGlyphCacheKey *key)
|
clutter_pango_glyph_cache_key_free (PangoGlyphCacheKey *key)
|
||||||
{
|
{
|
||||||
g_clear_object (&key->font);
|
g_clear_object (&key->font);
|
||||||
g_free (key);
|
g_free (key);
|
||||||
}
|
}
|
||||||
|
|
||||||
static unsigned int
|
static unsigned int
|
||||||
cogl_pango_glyph_cache_hash_func (const void *key)
|
clutter_pango_glyph_cache_hash_func (const void *key)
|
||||||
{
|
{
|
||||||
const CoglPangoGlyphCacheKey *cache_key
|
const PangoGlyphCacheKey *cache_key = (const PangoGlyphCacheKey *) key;
|
||||||
= (const CoglPangoGlyphCacheKey *) key;
|
|
||||||
|
|
||||||
/* Generate a number affected by both the font and the glyph
|
/* Generate a number affected by both the font and the glyph
|
||||||
number. We can safely directly compare the pointers because the
|
number. We can safely directly compare the pointers because the
|
||||||
@ -97,36 +94,35 @@ cogl_pango_glyph_cache_hash_func (const void *key)
|
|||||||
}
|
}
|
||||||
|
|
||||||
static gboolean
|
static gboolean
|
||||||
cogl_pango_glyph_cache_equal_func (const void *a, const void *b)
|
clutter_pango_glyph_cache_equal_func (const void *a,
|
||||||
|
const void *b)
|
||||||
{
|
{
|
||||||
const CoglPangoGlyphCacheKey *key_a
|
const PangoGlyphCacheKey *key_a = (const PangoGlyphCacheKey *) a;
|
||||||
= (const CoglPangoGlyphCacheKey *) a;
|
const PangoGlyphCacheKey *key_b = (const PangoGlyphCacheKey *) b;
|
||||||
const CoglPangoGlyphCacheKey *key_b
|
|
||||||
= (const CoglPangoGlyphCacheKey *) b;
|
|
||||||
|
|
||||||
/* We can safely directly compare the pointers for the fonts because
|
/* We can safely directly compare the pointers for the fonts because
|
||||||
the key holds a reference to the font so it is not possible that
|
the key holds a reference to the font so it is not possible that
|
||||||
a different font will have the same memory address */
|
a different font will have the same memory address */
|
||||||
return key_a->font == key_b->font
|
return key_a->font == key_b->font
|
||||||
&& key_a->glyph == key_b->glyph;
|
&& key_a->glyph == key_b->glyph;
|
||||||
}
|
}
|
||||||
|
|
||||||
CoglPangoGlyphCache *
|
ClutterPangoGlyphCache *
|
||||||
cogl_pango_glyph_cache_new (CoglContext *ctx)
|
clutter_pango_glyph_cache_new (CoglContext *ctx)
|
||||||
{
|
{
|
||||||
CoglPangoGlyphCache *cache;
|
ClutterPangoGlyphCache *cache;
|
||||||
|
|
||||||
cache = g_malloc (sizeof (CoglPangoGlyphCache));
|
cache = g_malloc (sizeof (ClutterPangoGlyphCache));
|
||||||
|
|
||||||
/* Note: as a rule we don't take references to a CoglContext
|
/* Note: as a rule we don't take references to a CoglContext
|
||||||
* internally since */
|
* internally since */
|
||||||
cache->ctx = ctx;
|
cache->ctx = ctx;
|
||||||
|
|
||||||
cache->hash_table = g_hash_table_new_full
|
cache->hash_table = g_hash_table_new_full
|
||||||
(cogl_pango_glyph_cache_hash_func,
|
(clutter_pango_glyph_cache_hash_func,
|
||||||
cogl_pango_glyph_cache_equal_func,
|
clutter_pango_glyph_cache_equal_func,
|
||||||
(GDestroyNotify) cogl_pango_glyph_cache_key_free,
|
(GDestroyNotify) clutter_pango_glyph_cache_key_free,
|
||||||
(GDestroyNotify) cogl_pango_glyph_cache_value_free);
|
(GDestroyNotify) clutter_pango_glyph_cache_value_free);
|
||||||
|
|
||||||
cache->atlases = NULL;
|
cache->atlases = NULL;
|
||||||
g_hook_list_init (&cache->reorganize_callbacks, sizeof (GHook));
|
g_hook_list_init (&cache->reorganize_callbacks, sizeof (GHook));
|
||||||
@ -139,21 +135,21 @@ cogl_pango_glyph_cache_new (CoglContext *ctx)
|
|||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
cogl_pango_glyph_cache_reorganize_cb (void *user_data)
|
clutter_pango_glyph_cache_reorganize_cb (void *user_data)
|
||||||
{
|
{
|
||||||
CoglPangoGlyphCache *cache = user_data;
|
ClutterPangoGlyphCache *cache = user_data;
|
||||||
|
|
||||||
g_hook_list_invoke (&cache->reorganize_callbacks, FALSE);
|
g_hook_list_invoke (&cache->reorganize_callbacks, FALSE);
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
cogl_pango_glyph_cache_free (CoglPangoGlyphCache *cache)
|
clutter_pango_glyph_cache_free (ClutterPangoGlyphCache *cache)
|
||||||
{
|
{
|
||||||
if (cache->using_global_atlas)
|
if (cache->using_global_atlas)
|
||||||
{
|
{
|
||||||
cogl_atlas_texture_remove_reorganize_callback (
|
cogl_atlas_texture_remove_reorganize_callback (
|
||||||
cache->ctx,
|
cache->ctx,
|
||||||
cogl_pango_glyph_cache_reorganize_cb, cache);
|
clutter_pango_glyph_cache_reorganize_cb, cache);
|
||||||
}
|
}
|
||||||
|
|
||||||
g_slist_foreach (cache->atlases, (GFunc) g_object_unref, NULL);
|
g_slist_foreach (cache->atlases, (GFunc) g_object_unref, NULL);
|
||||||
@ -169,11 +165,11 @@ cogl_pango_glyph_cache_free (CoglPangoGlyphCache *cache)
|
|||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
cogl_pango_glyph_cache_update_position_cb (void *user_data,
|
clutter_pango_glyph_cache_update_position_cb (void *user_data,
|
||||||
CoglTexture *new_texture,
|
CoglTexture *new_texture,
|
||||||
const MtkRectangle *rect)
|
const MtkRectangle *rect)
|
||||||
{
|
{
|
||||||
CoglPangoGlyphCacheValue *value = user_data;
|
PangoGlyphCacheValue *value = user_data;
|
||||||
float tex_width, tex_height;
|
float tex_width, tex_height;
|
||||||
|
|
||||||
g_clear_object (&value->texture);
|
g_clear_object (&value->texture);
|
||||||
@ -195,10 +191,10 @@ cogl_pango_glyph_cache_update_position_cb (void *user_data,
|
|||||||
}
|
}
|
||||||
|
|
||||||
static gboolean
|
static gboolean
|
||||||
cogl_pango_glyph_cache_add_to_global_atlas (CoglPangoGlyphCache *cache,
|
clutter_pango_glyph_cache_add_to_global_atlas (ClutterPangoGlyphCache *cache,
|
||||||
PangoFont *font,
|
PangoFont *font,
|
||||||
PangoGlyph glyph,
|
PangoGlyph glyph,
|
||||||
CoglPangoGlyphCacheValue *value)
|
PangoGlyphCacheValue *value)
|
||||||
{
|
{
|
||||||
CoglTexture *texture;
|
CoglTexture *texture;
|
||||||
GError *ignore_error = NULL;
|
GError *ignore_error = NULL;
|
||||||
@ -228,7 +224,7 @@ cogl_pango_glyph_cache_add_to_global_atlas (CoglPangoGlyphCache *cache,
|
|||||||
{
|
{
|
||||||
cogl_atlas_texture_add_reorganize_callback
|
cogl_atlas_texture_add_reorganize_callback
|
||||||
(cache->ctx,
|
(cache->ctx,
|
||||||
cogl_pango_glyph_cache_reorganize_cb, cache);
|
clutter_pango_glyph_cache_reorganize_cb, cache);
|
||||||
cache->using_global_atlas = TRUE;
|
cache->using_global_atlas = TRUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -236,11 +232,11 @@ cogl_pango_glyph_cache_add_to_global_atlas (CoglPangoGlyphCache *cache,
|
|||||||
}
|
}
|
||||||
|
|
||||||
static gboolean
|
static gboolean
|
||||||
cogl_pango_glyph_cache_add_to_local_atlas (CoglPangoGlyphCache *cache,
|
clutter_pango_glyph_cache_add_to_local_atlas (ClutterPangoGlyphCache *cache,
|
||||||
CoglContext *context,
|
CoglContext *context,
|
||||||
PangoFont *font,
|
PangoFont *font,
|
||||||
PangoGlyph glyph,
|
PangoGlyph glyph,
|
||||||
CoglPangoGlyphCacheValue *value)
|
PangoGlyphCacheValue *value)
|
||||||
{
|
{
|
||||||
CoglAtlas *atlas = NULL;
|
CoglAtlas *atlas = NULL;
|
||||||
GSList *l;
|
GSList *l;
|
||||||
@ -263,7 +259,7 @@ cogl_pango_glyph_cache_add_to_local_atlas (CoglPangoGlyphCache *cache,
|
|||||||
COGL_PIXEL_FORMAT_A_8,
|
COGL_PIXEL_FORMAT_A_8,
|
||||||
COGL_ATLAS_CLEAR_TEXTURE |
|
COGL_ATLAS_CLEAR_TEXTURE |
|
||||||
COGL_ATLAS_DISABLE_MIGRATION,
|
COGL_ATLAS_DISABLE_MIGRATION,
|
||||||
cogl_pango_glyph_cache_update_position_cb);
|
clutter_pango_glyph_cache_update_position_cb);
|
||||||
CLUTTER_NOTE (PANGO, "Created new atlas for glyphs: %p", atlas);
|
CLUTTER_NOTE (PANGO, "Created new atlas for glyphs: %p", atlas);
|
||||||
/* If we still can't reserve space then something has gone
|
/* If we still can't reserve space then something has gone
|
||||||
seriously wrong so we'll just give up */
|
seriously wrong so we'll just give up */
|
||||||
@ -277,7 +273,7 @@ cogl_pango_glyph_cache_add_to_local_atlas (CoglPangoGlyphCache *cache,
|
|||||||
}
|
}
|
||||||
|
|
||||||
cogl_atlas_add_reorganize_callback
|
cogl_atlas_add_reorganize_callback
|
||||||
(atlas, cogl_pango_glyph_cache_reorganize_cb, NULL, cache);
|
(atlas, clutter_pango_glyph_cache_reorganize_cb, NULL, cache);
|
||||||
|
|
||||||
cache->atlases = g_slist_prepend (cache->atlases, atlas);
|
cache->atlases = g_slist_prepend (cache->atlases, atlas);
|
||||||
}
|
}
|
||||||
@ -285,15 +281,15 @@ cogl_pango_glyph_cache_add_to_local_atlas (CoglPangoGlyphCache *cache,
|
|||||||
return TRUE;
|
return TRUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
CoglPangoGlyphCacheValue *
|
PangoGlyphCacheValue *
|
||||||
cogl_pango_glyph_cache_lookup (CoglPangoGlyphCache *cache,
|
clutter_pango_glyph_cache_lookup (ClutterPangoGlyphCache *cache,
|
||||||
CoglContext *context,
|
CoglContext *context,
|
||||||
gboolean create,
|
gboolean create,
|
||||||
PangoFont *font,
|
PangoFont *font,
|
||||||
PangoGlyph glyph)
|
PangoGlyph glyph)
|
||||||
{
|
{
|
||||||
CoglPangoGlyphCacheKey lookup_key;
|
PangoGlyphCacheKey lookup_key;
|
||||||
CoglPangoGlyphCacheValue *value;
|
PangoGlyphCacheValue *value;
|
||||||
|
|
||||||
lookup_key.font = font;
|
lookup_key.font = font;
|
||||||
lookup_key.glyph = glyph;
|
lookup_key.glyph = glyph;
|
||||||
@ -302,10 +298,10 @@ cogl_pango_glyph_cache_lookup (CoglPangoGlyphCache *cache,
|
|||||||
|
|
||||||
if (create && value == NULL)
|
if (create && value == NULL)
|
||||||
{
|
{
|
||||||
CoglPangoGlyphCacheKey *key;
|
PangoGlyphCacheKey *key;
|
||||||
PangoRectangle ink_rect;
|
PangoRectangle ink_rect;
|
||||||
|
|
||||||
value = g_new0 (CoglPangoGlyphCacheValue, 1);
|
value = g_new0 (PangoGlyphCacheValue, 1);
|
||||||
value->texture = NULL;
|
value->texture = NULL;
|
||||||
|
|
||||||
pango_font_get_glyph_extents (font, glyph, &ink_rect, NULL);
|
pango_font_get_glyph_extents (font, glyph, &ink_rect, NULL);
|
||||||
@ -323,18 +319,18 @@ cogl_pango_glyph_cache_lookup (CoglPangoGlyphCache *cache,
|
|||||||
else
|
else
|
||||||
{
|
{
|
||||||
/* Try adding the glyph to the global atlas... */
|
/* Try adding the glyph to the global atlas... */
|
||||||
if (!cogl_pango_glyph_cache_add_to_global_atlas (cache,
|
if (!clutter_pango_glyph_cache_add_to_global_atlas (cache,
|
||||||
font,
|
font,
|
||||||
glyph,
|
glyph,
|
||||||
value) &&
|
value) &&
|
||||||
/* If it fails try the local atlas */
|
/* If it fails try the local atlas */
|
||||||
!cogl_pango_glyph_cache_add_to_local_atlas (cache,
|
!clutter_pango_glyph_cache_add_to_local_atlas (cache,
|
||||||
context,
|
context,
|
||||||
font,
|
font,
|
||||||
glyph,
|
glyph,
|
||||||
value))
|
value))
|
||||||
{
|
{
|
||||||
cogl_pango_glyph_cache_value_free (value);
|
clutter_pango_glyph_cache_value_free (value);
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -342,7 +338,7 @@ cogl_pango_glyph_cache_lookup (CoglPangoGlyphCache *cache,
|
|||||||
cache->has_dirty_glyphs = TRUE;
|
cache->has_dirty_glyphs = TRUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
key = g_new0 (CoglPangoGlyphCacheKey, 1);
|
key = g_new0 (PangoGlyphCacheKey, 1);
|
||||||
key->font = g_object_ref (font);
|
key->font = g_object_ref (font);
|
||||||
key->glyph = glyph;
|
key->glyph = glyph;
|
||||||
|
|
||||||
@ -371,12 +367,12 @@ font_has_color_glyphs (const PangoFont *font)
|
|||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
_cogl_pango_glyph_cache_set_dirty_glyphs_cb (void *key_ptr,
|
clutter_pango_glyph_cache_set_dirty_glyphs_cb (void *key_ptr,
|
||||||
void *value_ptr,
|
void *value_ptr,
|
||||||
void *user_data)
|
void *user_data)
|
||||||
{
|
{
|
||||||
CoglPangoGlyphCacheKey *key = key_ptr;
|
PangoGlyphCacheKey *key = key_ptr;
|
||||||
CoglPangoGlyphCacheValue *value = value_ptr;
|
PangoGlyphCacheValue *value = value_ptr;
|
||||||
cairo_surface_t *surface;
|
cairo_surface_t *surface;
|
||||||
cairo_t *cr;
|
cairo_t *cr;
|
||||||
cairo_scaled_font_t *scaled_font;
|
cairo_scaled_font_t *scaled_font;
|
||||||
@ -455,7 +451,7 @@ _cogl_pango_glyph_cache_set_dirty_glyphs_cb (void *key_ptr,
|
|||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
_cogl_pango_glyph_cache_set_dirty_glyphs (CoglPangoGlyphCache *cache)
|
clutter_pango_glyph_cache_set_dirty_glyphs (ClutterPangoGlyphCache *cache)
|
||||||
{
|
{
|
||||||
/* If we know that there are no dirty glyphs then we can shortcut
|
/* If we know that there are no dirty glyphs then we can shortcut
|
||||||
out early */
|
out early */
|
||||||
@ -463,16 +459,16 @@ _cogl_pango_glyph_cache_set_dirty_glyphs (CoglPangoGlyphCache *cache)
|
|||||||
return;
|
return;
|
||||||
|
|
||||||
g_hash_table_foreach (cache->hash_table,
|
g_hash_table_foreach (cache->hash_table,
|
||||||
_cogl_pango_glyph_cache_set_dirty_glyphs_cb,
|
clutter_pango_glyph_cache_set_dirty_glyphs_cb,
|
||||||
NULL);
|
NULL);
|
||||||
|
|
||||||
cache->has_dirty_glyphs = FALSE;
|
cache->has_dirty_glyphs = FALSE;
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
_cogl_pango_glyph_cache_add_reorganize_callback (CoglPangoGlyphCache *cache,
|
clutter_pango_glyph_cache_add_reorganize_callback (ClutterPangoGlyphCache *cache,
|
||||||
GHookFunc func,
|
GHookFunc func,
|
||||||
void *user_data)
|
void *user_data)
|
||||||
{
|
{
|
||||||
GHook *hook = g_hook_alloc (&cache->reorganize_callbacks);
|
GHook *hook = g_hook_alloc (&cache->reorganize_callbacks);
|
||||||
hook->func = func;
|
hook->func = func;
|
||||||
@ -481,9 +477,9 @@ _cogl_pango_glyph_cache_add_reorganize_callback (CoglPangoGlyphCache *cache,
|
|||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
_cogl_pango_glyph_cache_remove_reorganize_callback (CoglPangoGlyphCache *cache,
|
clutter_pango_glyph_cache_remove_reorganize_callback (ClutterPangoGlyphCache *cache,
|
||||||
GHookFunc func,
|
GHookFunc func,
|
||||||
void *user_data)
|
void *user_data)
|
||||||
{
|
{
|
||||||
GHook *hook = g_hook_find_func_data (&cache->reorganize_callbacks,
|
GHook *hook = g_hook_find_func_data (&cache->reorganize_callbacks,
|
||||||
FALSE,
|
FALSE,
|
@ -35,10 +35,9 @@
|
|||||||
|
|
||||||
G_BEGIN_DECLS
|
G_BEGIN_DECLS
|
||||||
|
|
||||||
typedef struct _CoglPangoGlyphCache CoglPangoGlyphCache;
|
typedef struct _ClutterPangoGlyphCache ClutterPangoGlyphCache;
|
||||||
typedef struct _CoglPangoGlyphCacheValue CoglPangoGlyphCacheValue;
|
|
||||||
|
|
||||||
struct _CoglPangoGlyphCacheValue
|
typedef struct
|
||||||
{
|
{
|
||||||
CoglTexture *texture;
|
CoglTexture *texture;
|
||||||
|
|
||||||
@ -60,32 +59,32 @@ struct _CoglPangoGlyphCacheValue
|
|||||||
guint dirty : 1;
|
guint dirty : 1;
|
||||||
/* Set to TRUE if the glyph has colors (eg. emoji) */
|
/* Set to TRUE if the glyph has colors (eg. emoji) */
|
||||||
guint has_color : 1;
|
guint has_color : 1;
|
||||||
};
|
} PangoGlyphCacheValue;
|
||||||
|
|
||||||
CoglPangoGlyphCache *
|
ClutterPangoGlyphCache *
|
||||||
cogl_pango_glyph_cache_new (CoglContext *ctx);
|
clutter_pango_glyph_cache_new (CoglContext *ctx);
|
||||||
|
|
||||||
void
|
void
|
||||||
cogl_pango_glyph_cache_free (CoglPangoGlyphCache *cache);
|
clutter_pango_glyph_cache_free (ClutterPangoGlyphCache *cache);
|
||||||
|
|
||||||
CoglPangoGlyphCacheValue *
|
PangoGlyphCacheValue *
|
||||||
cogl_pango_glyph_cache_lookup (CoglPangoGlyphCache *cache,
|
clutter_pango_glyph_cache_lookup (ClutterPangoGlyphCache *cache,
|
||||||
CoglContext *context,
|
CoglContext *context,
|
||||||
gboolean create,
|
gboolean create,
|
||||||
PangoFont *font,
|
PangoFont *font,
|
||||||
PangoGlyph glyph);
|
PangoGlyph glyph);
|
||||||
|
|
||||||
void
|
void
|
||||||
_cogl_pango_glyph_cache_add_reorganize_callback (CoglPangoGlyphCache *cache,
|
clutter_pango_glyph_cache_add_reorganize_callback (ClutterPangoGlyphCache *cache,
|
||||||
GHookFunc func,
|
GHookFunc func,
|
||||||
void *user_data);
|
void *user_data);
|
||||||
|
|
||||||
void
|
void
|
||||||
_cogl_pango_glyph_cache_remove_reorganize_callback (CoglPangoGlyphCache *cache,
|
clutter_pango_glyph_cache_remove_reorganize_callback (ClutterPangoGlyphCache *cache,
|
||||||
GHookFunc func,
|
GHookFunc func,
|
||||||
void *user_data);
|
void *user_data);
|
||||||
|
|
||||||
void
|
void
|
||||||
_cogl_pango_glyph_cache_set_dirty_glyphs (CoglPangoGlyphCache *cache);
|
clutter_pango_glyph_cache_set_dirty_glyphs (ClutterPangoGlyphCache *cache);
|
||||||
|
|
||||||
G_END_DECLS
|
G_END_DECLS
|
@ -35,13 +35,11 @@
|
|||||||
|
|
||||||
#include <glib.h>
|
#include <glib.h>
|
||||||
|
|
||||||
#include "clutter/pango/cogl-pango-pipeline-cache.h"
|
#include "clutter/pango/clutter-pango-pipeline-cache.h"
|
||||||
|
|
||||||
typedef struct _CoglPangoPipelineCacheEntry CoglPangoPipelineCacheEntry;
|
|
||||||
|
|
||||||
static GQuark pipeline_destroy_notify_key = 0;
|
static GQuark pipeline_destroy_notify_key = 0;
|
||||||
|
|
||||||
struct _CoglPangoPipelineCacheEntry
|
typedef struct _PangoPipelineCacheEntry
|
||||||
{
|
{
|
||||||
/* This will take a reference or it can be NULL to represent the
|
/* This will take a reference or it can be NULL to represent the
|
||||||
pipeline used to render colors */
|
pipeline used to render colors */
|
||||||
@ -49,19 +47,19 @@ struct _CoglPangoPipelineCacheEntry
|
|||||||
|
|
||||||
/* This will only take a weak reference */
|
/* This will only take a weak reference */
|
||||||
CoglPipeline *pipeline;
|
CoglPipeline *pipeline;
|
||||||
};
|
} PangoPipelineCacheEntry;
|
||||||
|
|
||||||
static void
|
static void
|
||||||
_cogl_pango_pipeline_cache_key_destroy (void *data)
|
clutter_pango_pipeline_cache_key_destroy (void *data)
|
||||||
{
|
{
|
||||||
if (data)
|
if (data)
|
||||||
g_object_unref (data);
|
g_object_unref (data);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
_cogl_pango_pipeline_cache_value_destroy (void *data)
|
clutter_pango_pipeline_cache_value_destroy (void *data)
|
||||||
{
|
{
|
||||||
CoglPangoPipelineCacheEntry *cache_entry = data;
|
PangoPipelineCacheEntry *cache_entry = data;
|
||||||
|
|
||||||
g_clear_object (&cache_entry->texture);
|
g_clear_object (&cache_entry->texture);
|
||||||
|
|
||||||
@ -71,10 +69,10 @@ _cogl_pango_pipeline_cache_value_destroy (void *data)
|
|||||||
g_free (cache_entry);
|
g_free (cache_entry);
|
||||||
}
|
}
|
||||||
|
|
||||||
CoglPangoPipelineCache *
|
ClutterPangoPipelineCache *
|
||||||
_cogl_pango_pipeline_cache_new (CoglContext *ctx)
|
clutter_pango_pipeline_cache_new (CoglContext *ctx)
|
||||||
{
|
{
|
||||||
CoglPangoPipelineCache *cache = g_new (CoglPangoPipelineCache, 1);
|
ClutterPangoPipelineCache *cache = g_new (ClutterPangoPipelineCache, 1);
|
||||||
|
|
||||||
cache->ctx = g_object_ref (ctx);
|
cache->ctx = g_object_ref (ctx);
|
||||||
|
|
||||||
@ -84,8 +82,8 @@ _cogl_pango_pipeline_cache_new (CoglContext *ctx)
|
|||||||
cache->hash_table =
|
cache->hash_table =
|
||||||
g_hash_table_new_full (g_direct_hash,
|
g_hash_table_new_full (g_direct_hash,
|
||||||
g_direct_equal,
|
g_direct_equal,
|
||||||
_cogl_pango_pipeline_cache_key_destroy,
|
clutter_pango_pipeline_cache_key_destroy,
|
||||||
_cogl_pango_pipeline_cache_value_destroy);
|
clutter_pango_pipeline_cache_value_destroy);
|
||||||
|
|
||||||
cache->base_texture_rgba_pipeline = NULL;
|
cache->base_texture_rgba_pipeline = NULL;
|
||||||
cache->base_texture_alpha_pipeline = NULL;
|
cache->base_texture_alpha_pipeline = NULL;
|
||||||
@ -94,7 +92,7 @@ _cogl_pango_pipeline_cache_new (CoglContext *ctx)
|
|||||||
}
|
}
|
||||||
|
|
||||||
static CoglPipeline *
|
static CoglPipeline *
|
||||||
get_base_texture_rgba_pipeline (CoglPangoPipelineCache *cache)
|
get_base_texture_rgba_pipeline (ClutterPangoPipelineCache *cache)
|
||||||
{
|
{
|
||||||
if (cache->base_texture_rgba_pipeline == NULL)
|
if (cache->base_texture_rgba_pipeline == NULL)
|
||||||
{
|
{
|
||||||
@ -112,7 +110,7 @@ get_base_texture_rgba_pipeline (CoglPangoPipelineCache *cache)
|
|||||||
}
|
}
|
||||||
|
|
||||||
static CoglPipeline *
|
static CoglPipeline *
|
||||||
get_base_texture_alpha_pipeline (CoglPangoPipelineCache *cache)
|
get_base_texture_alpha_pipeline (ClutterPangoPipelineCache *cache)
|
||||||
{
|
{
|
||||||
if (cache->base_texture_alpha_pipeline == NULL)
|
if (cache->base_texture_alpha_pipeline == NULL)
|
||||||
{
|
{
|
||||||
@ -146,7 +144,7 @@ get_base_texture_alpha_pipeline (CoglPangoPipelineCache *cache)
|
|||||||
|
|
||||||
typedef struct
|
typedef struct
|
||||||
{
|
{
|
||||||
CoglPangoPipelineCache *cache;
|
ClutterPangoPipelineCache *cache;
|
||||||
CoglTexture *texture;
|
CoglTexture *texture;
|
||||||
} PipelineDestroyNotifyData;
|
} PipelineDestroyNotifyData;
|
||||||
|
|
||||||
@ -160,12 +158,12 @@ pipeline_destroy_notify_cb (void *user_data)
|
|||||||
}
|
}
|
||||||
|
|
||||||
CoglPipeline *
|
CoglPipeline *
|
||||||
_cogl_pango_pipeline_cache_get (CoglPangoPipelineCache *cache,
|
clutter_pango_pipeline_cache_get (ClutterPangoPipelineCache *cache,
|
||||||
CoglTexture *texture)
|
CoglTexture *texture)
|
||||||
{
|
{
|
||||||
CoglPangoPipelineCacheEntry *entry;
|
PangoPipelineCacheEntry *entry;
|
||||||
PipelineDestroyNotifyData *destroy_data;
|
PipelineDestroyNotifyData *destroy_data;
|
||||||
pipeline_destroy_notify_key = g_quark_from_static_string ("-cogl-pango-pipeline-cache-key");
|
pipeline_destroy_notify_key = g_quark_from_static_string ("-clutter-pango-pipeline-cache-key");
|
||||||
|
|
||||||
/* Look for an existing entry */
|
/* Look for an existing entry */
|
||||||
entry = g_hash_table_lookup (cache->hash_table, texture);
|
entry = g_hash_table_lookup (cache->hash_table, texture);
|
||||||
@ -174,7 +172,7 @@ _cogl_pango_pipeline_cache_get (CoglPangoPipelineCache *cache,
|
|||||||
return g_object_ref (entry->pipeline);
|
return g_object_ref (entry->pipeline);
|
||||||
|
|
||||||
/* No existing pipeline was found so let's create another */
|
/* No existing pipeline was found so let's create another */
|
||||||
entry = g_new0 (CoglPangoPipelineCacheEntry, 1);
|
entry = g_new0 (PangoPipelineCacheEntry, 1);
|
||||||
|
|
||||||
if (texture)
|
if (texture)
|
||||||
{
|
{
|
||||||
@ -218,7 +216,7 @@ _cogl_pango_pipeline_cache_get (CoglPangoPipelineCache *cache,
|
|||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
_cogl_pango_pipeline_cache_free (CoglPangoPipelineCache *cache)
|
clutter_pango_pipeline_cache_free (ClutterPangoPipelineCache *cache)
|
||||||
{
|
{
|
||||||
g_clear_object (&cache->base_texture_rgba_pipeline);
|
g_clear_object (&cache->base_texture_rgba_pipeline);
|
||||||
g_clear_object (&cache->base_texture_alpha_pipeline);
|
g_clear_object (&cache->base_texture_alpha_pipeline);
|
@ -39,7 +39,7 @@
|
|||||||
|
|
||||||
G_BEGIN_DECLS
|
G_BEGIN_DECLS
|
||||||
|
|
||||||
typedef struct _CoglPangoPipelineCache
|
typedef struct
|
||||||
{
|
{
|
||||||
CoglContext *ctx;
|
CoglContext *ctx;
|
||||||
|
|
||||||
@ -47,20 +47,20 @@ typedef struct _CoglPangoPipelineCache
|
|||||||
|
|
||||||
CoglPipeline *base_texture_alpha_pipeline;
|
CoglPipeline *base_texture_alpha_pipeline;
|
||||||
CoglPipeline *base_texture_rgba_pipeline;
|
CoglPipeline *base_texture_rgba_pipeline;
|
||||||
} CoglPangoPipelineCache;
|
} ClutterPangoPipelineCache;
|
||||||
|
|
||||||
|
|
||||||
CoglPangoPipelineCache *
|
ClutterPangoPipelineCache *
|
||||||
_cogl_pango_pipeline_cache_new (CoglContext *ctx);
|
clutter_pango_pipeline_cache_new (CoglContext *ctx);
|
||||||
|
|
||||||
/* Returns a pipeline that can be used to render glyphs in the given
|
/* Returns a pipeline that can be used to render glyphs in the given
|
||||||
texture. The pipeline has a new reference so it is up to the caller
|
texture. The pipeline has a new reference so it is up to the caller
|
||||||
to unref it */
|
to unref it */
|
||||||
CoglPipeline *
|
CoglPipeline *
|
||||||
_cogl_pango_pipeline_cache_get (CoglPangoPipelineCache *cache,
|
clutter_pango_pipeline_cache_get (ClutterPangoPipelineCache *cache,
|
||||||
CoglTexture *texture);
|
CoglTexture *texture);
|
||||||
|
|
||||||
void
|
void
|
||||||
_cogl_pango_pipeline_cache_free (CoglPangoPipelineCache *cache);
|
clutter_pango_pipeline_cache_free (ClutterPangoPipelineCache *cache);
|
||||||
|
|
||||||
G_END_DECLS
|
G_END_DECLS
|
@ -43,7 +43,7 @@
|
|||||||
G_BEGIN_DECLS
|
G_BEGIN_DECLS
|
||||||
|
|
||||||
PangoRenderer *
|
PangoRenderer *
|
||||||
_cogl_pango_renderer_new (CoglContext *context);
|
clutter_pango_renderer_new (CoglContext *context);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* clutter_ensure_glyph_cache_for_layout:
|
* clutter_ensure_glyph_cache_for_layout:
|
655
clutter/clutter/pango/clutter-pango-render.c
Normal file
655
clutter/clutter/pango/clutter-pango-render.c
Normal file
@ -0,0 +1,655 @@
|
|||||||
|
/*
|
||||||
|
* Clutter.
|
||||||
|
*
|
||||||
|
* An OpenGL based 'interactive canvas' library.
|
||||||
|
*
|
||||||
|
* Copyright (C) 2008 OpenedHand
|
||||||
|
* Copyright (C) 2012 Intel Corporation.
|
||||||
|
*
|
||||||
|
* Permission is hereby granted, free of charge, to any person
|
||||||
|
* obtaining a copy of this software and associated documentation
|
||||||
|
* files (the "Software"), to deal in the Software without
|
||||||
|
* restriction, including without limitation the rights to use, copy,
|
||||||
|
* modify, merge, publish, distribute, sublicense, and/or sell copies
|
||||||
|
* of the Software, and to permit persons to whom the Software is
|
||||||
|
* furnished to do so, subject to the following conditions:
|
||||||
|
*
|
||||||
|
* The above copyright notice and this permission notice shall be
|
||||||
|
* included in all copies or substantial portions of the Software.
|
||||||
|
*
|
||||||
|
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||||
|
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||||
|
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||||
|
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
|
||||||
|
* BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
|
||||||
|
* ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||||
|
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||||
|
* SOFTWARE.
|
||||||
|
*
|
||||||
|
*
|
||||||
|
* Authors:
|
||||||
|
* Neil Roberts <neil@linux.intel.com>
|
||||||
|
* Robert Bragg <robert@linux.intel.com>
|
||||||
|
* Matthew Allum <mallum@openedhand.com>
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "config.h"
|
||||||
|
|
||||||
|
#include <pango/pango-fontmap.h>
|
||||||
|
#include <pango/pangocairo.h>
|
||||||
|
#include <pango/pango-renderer.h>
|
||||||
|
#include <cairo.h>
|
||||||
|
#include <cairo-ft.h>
|
||||||
|
|
||||||
|
#include "clutter/clutter-debug.h"
|
||||||
|
#include "clutter/clutter-context-private.h"
|
||||||
|
#include "clutter/clutter-private.h"
|
||||||
|
#include "clutter/pango/clutter-pango-private.h"
|
||||||
|
#include "clutter/pango/clutter-pango-glyph-cache.h"
|
||||||
|
#include "clutter/pango/clutter-pango-display-list.h"
|
||||||
|
#include "cogl/cogl.h"
|
||||||
|
|
||||||
|
#define PANGO_UNKNOWN_GLYPH_WIDTH 10
|
||||||
|
#define PANGO_UNKNOWN_GLYPH_HEIGHT 14
|
||||||
|
|
||||||
|
enum
|
||||||
|
{
|
||||||
|
PROP_0,
|
||||||
|
|
||||||
|
PROP_COGL_CONTEXT,
|
||||||
|
PROP_LAST
|
||||||
|
};
|
||||||
|
|
||||||
|
struct _ClutterPangoRenderer
|
||||||
|
{
|
||||||
|
PangoRenderer parent_instance;
|
||||||
|
|
||||||
|
CoglContext *ctx;
|
||||||
|
|
||||||
|
ClutterPangoGlyphCache *glyph_cache;
|
||||||
|
ClutterPangoPipelineCache *pipeline_cache;
|
||||||
|
|
||||||
|
/* The current display list that is being built */
|
||||||
|
ClutterPangoDisplayList *display_list;
|
||||||
|
};
|
||||||
|
|
||||||
|
G_DECLARE_FINAL_TYPE (ClutterPangoRenderer,
|
||||||
|
clutter_pango_renderer,
|
||||||
|
CLUTTER_PANGO,
|
||||||
|
RENDERER,
|
||||||
|
PangoRenderer)
|
||||||
|
|
||||||
|
G_DEFINE_FINAL_TYPE (ClutterPangoRenderer, clutter_pango_renderer, PANGO_TYPE_RENDERER);
|
||||||
|
|
||||||
|
/* An instance of this struct gets attached to each PangoLayout to
|
||||||
|
cache the VBO and to detect changes to the layout */
|
||||||
|
typedef struct _PangoLayoutQdata
|
||||||
|
{
|
||||||
|
ClutterPangoRenderer *renderer;
|
||||||
|
/* The cache of the geometry for the layout */
|
||||||
|
ClutterPangoDisplayList *display_list;
|
||||||
|
/* A reference to the first line of the layout. This is just used to
|
||||||
|
detect changes */
|
||||||
|
PangoLayoutLine *first_line;
|
||||||
|
} PangoLayoutQdata;
|
||||||
|
|
||||||
|
typedef struct
|
||||||
|
{
|
||||||
|
ClutterPangoDisplayList *display_list;
|
||||||
|
float x1, y1, x2, y2;
|
||||||
|
} PangoRendererSliceCbData;
|
||||||
|
|
||||||
|
PangoRenderer *
|
||||||
|
clutter_pango_renderer_new (CoglContext *context)
|
||||||
|
{
|
||||||
|
return PANGO_RENDERER (g_object_new (clutter_pango_renderer_get_type (),
|
||||||
|
"context", context, NULL));
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
clutter_pango_renderer_slice_cb (CoglTexture *texture,
|
||||||
|
const float *slice_coords,
|
||||||
|
const float *virtual_coords,
|
||||||
|
void *user_data)
|
||||||
|
{
|
||||||
|
PangoRendererSliceCbData *data = user_data;
|
||||||
|
|
||||||
|
/* Note: this assumes that there is only one slice containing the
|
||||||
|
whole texture and it doesn't attempt to split up the vertex
|
||||||
|
coordinates based on the virtual_coords */
|
||||||
|
|
||||||
|
clutter_pango_display_list_add_texture (data->display_list,
|
||||||
|
texture,
|
||||||
|
data->x1,
|
||||||
|
data->y1,
|
||||||
|
data->x2,
|
||||||
|
data->y2,
|
||||||
|
slice_coords[0],
|
||||||
|
slice_coords[1],
|
||||||
|
slice_coords[2],
|
||||||
|
slice_coords[3]);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
clutter_pango_renderer_draw_glyph (ClutterPangoRenderer *renderer,
|
||||||
|
PangoGlyphCacheValue *cache_value,
|
||||||
|
float x1,
|
||||||
|
float y1)
|
||||||
|
{
|
||||||
|
PangoRendererSliceCbData data;
|
||||||
|
|
||||||
|
g_return_if_fail (renderer->display_list != NULL);
|
||||||
|
|
||||||
|
data.display_list = renderer->display_list;
|
||||||
|
data.x1 = x1;
|
||||||
|
data.y1 = y1;
|
||||||
|
data.x2 = x1 + (float) cache_value->draw_width;
|
||||||
|
data.y2 = y1 + (float) cache_value->draw_height;
|
||||||
|
|
||||||
|
/* We iterate the internal sub textures of the texture so that we
|
||||||
|
can get a pointer to the base texture even if the texture is in
|
||||||
|
the global atlas. That way the display list can recognise that
|
||||||
|
the neighbouring glyphs are coming from the same atlas and bundle
|
||||||
|
them together into a single VBO */
|
||||||
|
|
||||||
|
cogl_meta_texture_foreach_in_region (cache_value->texture,
|
||||||
|
cache_value->tx1,
|
||||||
|
cache_value->ty1,
|
||||||
|
cache_value->tx2,
|
||||||
|
cache_value->ty2,
|
||||||
|
COGL_PIPELINE_WRAP_MODE_REPEAT,
|
||||||
|
COGL_PIPELINE_WRAP_MODE_REPEAT,
|
||||||
|
clutter_pango_renderer_slice_cb,
|
||||||
|
&data);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
clutter_pango_renderer_init (ClutterPangoRenderer *renderer)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
clutter_pango_renderer_constructed (GObject *gobject)
|
||||||
|
{
|
||||||
|
ClutterPangoRenderer *renderer = CLUTTER_PANGO_RENDERER (gobject);
|
||||||
|
CoglContext *ctx = renderer->ctx;
|
||||||
|
|
||||||
|
renderer->pipeline_cache = clutter_pango_pipeline_cache_new (ctx);
|
||||||
|
renderer->glyph_cache = clutter_pango_glyph_cache_new (ctx);
|
||||||
|
|
||||||
|
G_OBJECT_CLASS (clutter_pango_renderer_parent_class)->constructed (gobject);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
clutter_pango_renderer_set_property (GObject *object,
|
||||||
|
unsigned int prop_id,
|
||||||
|
const GValue *value,
|
||||||
|
GParamSpec *pspec)
|
||||||
|
{
|
||||||
|
ClutterPangoRenderer *renderer = CLUTTER_PANGO_RENDERER (object);
|
||||||
|
|
||||||
|
switch (prop_id)
|
||||||
|
{
|
||||||
|
case PROP_COGL_CONTEXT:
|
||||||
|
renderer->ctx = g_value_get_object (value);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
clutter_pango_renderer_dispose (GObject *object)
|
||||||
|
{
|
||||||
|
ClutterPangoRenderer *renderer = CLUTTER_PANGO_RENDERER (object);
|
||||||
|
|
||||||
|
g_clear_object (&renderer->ctx);
|
||||||
|
|
||||||
|
G_OBJECT_CLASS (clutter_pango_renderer_parent_class)->dispose (object);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
clutter_pango_renderer_finalize (GObject *object)
|
||||||
|
{
|
||||||
|
ClutterPangoRenderer *renderer = CLUTTER_PANGO_RENDERER (object);
|
||||||
|
|
||||||
|
clutter_pango_glyph_cache_free (renderer->glyph_cache);
|
||||||
|
clutter_pango_pipeline_cache_free (renderer->pipeline_cache);
|
||||||
|
|
||||||
|
G_OBJECT_CLASS (clutter_pango_renderer_parent_class)->finalize (object);
|
||||||
|
}
|
||||||
|
|
||||||
|
static GQuark
|
||||||
|
clutter_pango_layout_get_qdata_key (void)
|
||||||
|
{
|
||||||
|
static GQuark key = 0;
|
||||||
|
|
||||||
|
if (G_UNLIKELY (key == 0))
|
||||||
|
key = g_quark_from_static_string ("ClutterPangoDisplayList");
|
||||||
|
|
||||||
|
return key;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
clutter_pango_layout_qdata_forget_display_list (PangoLayoutQdata *qdata)
|
||||||
|
{
|
||||||
|
if (qdata->display_list)
|
||||||
|
{
|
||||||
|
clutter_pango_glyph_cache_remove_reorganize_callback
|
||||||
|
(qdata->renderer->glyph_cache,
|
||||||
|
(GHookFunc) clutter_pango_layout_qdata_forget_display_list,
|
||||||
|
qdata);
|
||||||
|
|
||||||
|
clutter_pango_display_list_free (qdata->display_list);
|
||||||
|
|
||||||
|
qdata->display_list = NULL;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
clutter_pango_render_qdata_destroy (PangoLayoutQdata *qdata)
|
||||||
|
{
|
||||||
|
clutter_pango_layout_qdata_forget_display_list (qdata);
|
||||||
|
if (qdata->first_line)
|
||||||
|
pango_layout_line_unref (qdata->first_line);
|
||||||
|
g_free (qdata);
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
clutter_show_layout (CoglFramebuffer *fb,
|
||||||
|
PangoLayout *layout,
|
||||||
|
float x,
|
||||||
|
float y,
|
||||||
|
const CoglColor *color,
|
||||||
|
ClutterColorState *color_state,
|
||||||
|
ClutterColorState *target_color_state)
|
||||||
|
{
|
||||||
|
ClutterPangoRenderer *renderer;
|
||||||
|
PangoLayoutQdata *qdata;
|
||||||
|
ClutterContext *context;
|
||||||
|
|
||||||
|
context = _clutter_context_get_default ();
|
||||||
|
renderer = CLUTTER_PANGO_RENDERER (clutter_context_get_font_renderer (context));
|
||||||
|
if (G_UNLIKELY (!renderer))
|
||||||
|
return;
|
||||||
|
|
||||||
|
qdata = g_object_get_qdata (G_OBJECT (layout),
|
||||||
|
clutter_pango_layout_get_qdata_key ());
|
||||||
|
|
||||||
|
if (qdata == NULL)
|
||||||
|
{
|
||||||
|
qdata = g_new0 (PangoLayoutQdata, 1);
|
||||||
|
qdata->renderer = renderer;
|
||||||
|
g_object_set_qdata_full (G_OBJECT (layout),
|
||||||
|
clutter_pango_layout_get_qdata_key (),
|
||||||
|
qdata,
|
||||||
|
(GDestroyNotify)
|
||||||
|
clutter_pango_render_qdata_destroy);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Check if the layout has changed since the last build of the
|
||||||
|
display list. This trick was suggested by Behdad Esfahbod here:
|
||||||
|
http://mail.gnome.org/archives/gtk-i18n-list/2009-May/msg00019.html */
|
||||||
|
if (qdata->display_list &&
|
||||||
|
((qdata->first_line &&
|
||||||
|
qdata->first_line->layout != layout)))
|
||||||
|
clutter_pango_layout_qdata_forget_display_list (qdata);
|
||||||
|
|
||||||
|
if (qdata->display_list == NULL)
|
||||||
|
{
|
||||||
|
clutter_ensure_glyph_cache_for_layout (layout);
|
||||||
|
|
||||||
|
qdata->display_list =
|
||||||
|
clutter_pango_display_list_new (renderer->pipeline_cache);
|
||||||
|
|
||||||
|
/* Register for notification of when the glyph cache changes so
|
||||||
|
we can rebuild the display list */
|
||||||
|
clutter_pango_glyph_cache_add_reorganize_callback
|
||||||
|
(renderer->glyph_cache,
|
||||||
|
(GHookFunc) clutter_pango_layout_qdata_forget_display_list,
|
||||||
|
qdata);
|
||||||
|
|
||||||
|
renderer->display_list = qdata->display_list;
|
||||||
|
pango_renderer_draw_layout (PANGO_RENDERER (renderer), layout, 0, 0);
|
||||||
|
renderer->display_list = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
cogl_framebuffer_push_matrix (fb);
|
||||||
|
cogl_framebuffer_translate (fb, x, y, 0);
|
||||||
|
|
||||||
|
clutter_pango_display_list_render (fb,
|
||||||
|
qdata->display_list,
|
||||||
|
color_state, target_color_state,
|
||||||
|
color);
|
||||||
|
|
||||||
|
cogl_framebuffer_pop_matrix (fb);
|
||||||
|
|
||||||
|
/* Keep a reference to the first line of the layout so we can detect
|
||||||
|
changes */
|
||||||
|
if (qdata->first_line)
|
||||||
|
{
|
||||||
|
pango_layout_line_unref (qdata->first_line);
|
||||||
|
qdata->first_line = NULL;
|
||||||
|
}
|
||||||
|
if (pango_layout_get_line_count (layout) > 0)
|
||||||
|
{
|
||||||
|
qdata->first_line = pango_layout_get_line (layout, 0);
|
||||||
|
pango_layout_line_ref (qdata->first_line);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static PangoGlyphCacheValue *
|
||||||
|
clutter_pango_renderer_get_cached_glyph (PangoRenderer *renderer,
|
||||||
|
gboolean create,
|
||||||
|
PangoFont *font,
|
||||||
|
PangoGlyph glyph)
|
||||||
|
{
|
||||||
|
ClutterPangoRenderer *priv = CLUTTER_PANGO_RENDERER (renderer);
|
||||||
|
|
||||||
|
return clutter_pango_glyph_cache_lookup (priv->glyph_cache,
|
||||||
|
priv->ctx,
|
||||||
|
create, font, glyph);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
clutter_pango_ensure_glyph_cache_for_layout_line_internal (PangoLayoutLine *line)
|
||||||
|
{
|
||||||
|
ClutterContext *context;
|
||||||
|
PangoRenderer *renderer;
|
||||||
|
GSList *l;
|
||||||
|
|
||||||
|
context = _clutter_context_get_default ();
|
||||||
|
renderer = clutter_context_get_font_renderer (context);
|
||||||
|
|
||||||
|
for (l = line->runs; l; l = l->next)
|
||||||
|
{
|
||||||
|
PangoLayoutRun *run = l->data;
|
||||||
|
PangoGlyphString *glyphs = run->glyphs;
|
||||||
|
int i;
|
||||||
|
|
||||||
|
for (i = 0; i < glyphs->num_glyphs; i++)
|
||||||
|
{
|
||||||
|
PangoGlyphInfo *gi = &glyphs->glyphs[i];
|
||||||
|
|
||||||
|
/* If the glyph isn't cached then this will reserve
|
||||||
|
space for it now. We won't actually draw the glyph
|
||||||
|
yet because reserving space could cause all of the
|
||||||
|
other glyphs to be moved so we might as well redraw
|
||||||
|
them all later once we know that the position is
|
||||||
|
settled */
|
||||||
|
clutter_pango_renderer_get_cached_glyph (renderer, TRUE,
|
||||||
|
run->item->analysis.font,
|
||||||
|
gi->glyph);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
clutter_ensure_glyph_cache_for_layout (PangoLayout *layout)
|
||||||
|
{
|
||||||
|
ClutterContext *context;
|
||||||
|
ClutterPangoRenderer *renderer;
|
||||||
|
PangoLayoutIter *iter;
|
||||||
|
|
||||||
|
context = _clutter_context_get_default ();
|
||||||
|
renderer = CLUTTER_PANGO_RENDERER (clutter_context_get_font_renderer (context));
|
||||||
|
|
||||||
|
g_return_if_fail (PANGO_IS_LAYOUT (layout));
|
||||||
|
|
||||||
|
if ((iter = pango_layout_get_iter (layout)) == NULL)
|
||||||
|
return;
|
||||||
|
|
||||||
|
do
|
||||||
|
{
|
||||||
|
PangoLayoutLine *line;
|
||||||
|
|
||||||
|
line = pango_layout_iter_get_line_readonly (iter);
|
||||||
|
|
||||||
|
clutter_pango_ensure_glyph_cache_for_layout_line_internal (line);
|
||||||
|
}
|
||||||
|
while (pango_layout_iter_next_line (iter));
|
||||||
|
|
||||||
|
pango_layout_iter_free (iter);
|
||||||
|
|
||||||
|
/* Now that we know all of the positions are settled we'll fill in
|
||||||
|
any dirty glyphs */
|
||||||
|
clutter_pango_glyph_cache_set_dirty_glyphs (renderer->glyph_cache);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
clutter_pango_renderer_set_color_for_part (PangoRenderer *renderer,
|
||||||
|
PangoRenderPart part)
|
||||||
|
{
|
||||||
|
PangoColor *pango_color = pango_renderer_get_color (renderer, part);
|
||||||
|
uint16_t alpha = pango_renderer_get_alpha (renderer, part);
|
||||||
|
ClutterPangoRenderer *priv = CLUTTER_PANGO_RENDERER (renderer);
|
||||||
|
|
||||||
|
if (pango_color)
|
||||||
|
{
|
||||||
|
CoglColor color;
|
||||||
|
|
||||||
|
cogl_color_init_from_4f (&color,
|
||||||
|
pango_color->red / 65535.0f,
|
||||||
|
pango_color->green / 65535.0f,
|
||||||
|
pango_color->blue / 65535.0f,
|
||||||
|
alpha ? alpha / 65535.0f : 1.0f);
|
||||||
|
|
||||||
|
clutter_pango_display_list_set_color_override (priv->display_list, &color);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
clutter_pango_display_list_remove_color_override (priv->display_list);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
clutter_pango_renderer_draw_box (PangoRenderer *renderer,
|
||||||
|
int x,
|
||||||
|
int y,
|
||||||
|
int width,
|
||||||
|
int height)
|
||||||
|
{
|
||||||
|
ClutterPangoRenderer *priv = CLUTTER_PANGO_RENDERER (renderer);
|
||||||
|
|
||||||
|
g_return_if_fail (priv->display_list != NULL);
|
||||||
|
|
||||||
|
clutter_pango_display_list_add_rectangle (priv->display_list,
|
||||||
|
x,
|
||||||
|
y - height,
|
||||||
|
x + width,
|
||||||
|
y);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
clutter_pango_renderer_get_device_units (PangoRenderer *renderer,
|
||||||
|
int xin,
|
||||||
|
int yin,
|
||||||
|
float *xout,
|
||||||
|
float *yout)
|
||||||
|
{
|
||||||
|
const PangoMatrix *matrix;
|
||||||
|
|
||||||
|
if ((matrix = pango_renderer_get_matrix (renderer)))
|
||||||
|
{
|
||||||
|
/* Convert user-space coords to device coords */
|
||||||
|
*xout = (float) ((xin * matrix->xx + yin * matrix->xy) /
|
||||||
|
PANGO_SCALE + matrix->x0);
|
||||||
|
*yout = (float) ((yin * matrix->yy + xin * matrix->yx) /
|
||||||
|
PANGO_SCALE + matrix->y0);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
*xout = PANGO_PIXELS (xin);
|
||||||
|
*yout = PANGO_PIXELS (yin);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
clutter_pango_renderer_draw_rectangle (PangoRenderer *renderer,
|
||||||
|
PangoRenderPart part,
|
||||||
|
int x,
|
||||||
|
int y,
|
||||||
|
int width,
|
||||||
|
int height)
|
||||||
|
{
|
||||||
|
ClutterPangoRenderer *priv = CLUTTER_PANGO_RENDERER (renderer);
|
||||||
|
float x1, x2, y1, y2;
|
||||||
|
|
||||||
|
g_return_if_fail (priv->display_list != NULL);
|
||||||
|
|
||||||
|
clutter_pango_renderer_set_color_for_part (renderer, part);
|
||||||
|
|
||||||
|
clutter_pango_renderer_get_device_units (renderer,
|
||||||
|
x, y,
|
||||||
|
&x1, &y1);
|
||||||
|
clutter_pango_renderer_get_device_units (renderer,
|
||||||
|
x + width, y + height,
|
||||||
|
&x2, &y2);
|
||||||
|
|
||||||
|
clutter_pango_display_list_add_rectangle (priv->display_list,
|
||||||
|
x1, y1, x2, y2);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
clutter_pango_renderer_draw_trapezoid (PangoRenderer *renderer,
|
||||||
|
PangoRenderPart part,
|
||||||
|
double y1,
|
||||||
|
double x11,
|
||||||
|
double x21,
|
||||||
|
double y2,
|
||||||
|
double x12,
|
||||||
|
double x22)
|
||||||
|
{
|
||||||
|
ClutterPangoRenderer *priv = CLUTTER_PANGO_RENDERER (renderer);
|
||||||
|
|
||||||
|
g_return_if_fail (priv->display_list != NULL);
|
||||||
|
|
||||||
|
clutter_pango_renderer_set_color_for_part (renderer, part);
|
||||||
|
|
||||||
|
clutter_pango_display_list_add_trapezoid (priv->display_list,
|
||||||
|
(float) y1,
|
||||||
|
(float) x11,
|
||||||
|
(float) x21,
|
||||||
|
(float) y2,
|
||||||
|
(float) x12,
|
||||||
|
(float) x22);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
clutter_pango_renderer_draw_glyphs (PangoRenderer *renderer,
|
||||||
|
PangoFont *font,
|
||||||
|
PangoGlyphString *glyphs,
|
||||||
|
int xi,
|
||||||
|
int yi)
|
||||||
|
{
|
||||||
|
ClutterPangoRenderer *priv = CLUTTER_PANGO_RENDERER (renderer);
|
||||||
|
PangoGlyphCacheValue *cache_value;
|
||||||
|
int i;
|
||||||
|
|
||||||
|
for (i = 0; i < glyphs->num_glyphs; i++)
|
||||||
|
{
|
||||||
|
PangoGlyphInfo *gi = glyphs->glyphs + i;
|
||||||
|
float x, y;
|
||||||
|
|
||||||
|
clutter_pango_renderer_set_color_for_part (renderer,
|
||||||
|
PANGO_RENDER_PART_FOREGROUND);
|
||||||
|
clutter_pango_renderer_get_device_units (renderer,
|
||||||
|
xi + gi->geometry.x_offset,
|
||||||
|
yi + gi->geometry.y_offset,
|
||||||
|
&x, &y);
|
||||||
|
|
||||||
|
if ((gi->glyph & PANGO_GLYPH_UNKNOWN_FLAG))
|
||||||
|
{
|
||||||
|
if (font == NULL)
|
||||||
|
{
|
||||||
|
clutter_pango_renderer_draw_box (renderer,
|
||||||
|
(int) x,
|
||||||
|
(int) y,
|
||||||
|
PANGO_UNKNOWN_GLYPH_WIDTH,
|
||||||
|
PANGO_UNKNOWN_GLYPH_HEIGHT);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
PangoRectangle ink_rect;
|
||||||
|
|
||||||
|
pango_font_get_glyph_extents (font, gi->glyph, &ink_rect, NULL);
|
||||||
|
pango_extents_to_pixels (&ink_rect, NULL);
|
||||||
|
|
||||||
|
clutter_pango_renderer_draw_box (renderer,
|
||||||
|
(int) (x + ink_rect.x),
|
||||||
|
(int) (y + ink_rect.y + ink_rect.height),
|
||||||
|
ink_rect.width,
|
||||||
|
ink_rect.height);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
/* Get the texture containing the glyph */
|
||||||
|
cache_value =
|
||||||
|
clutter_pango_renderer_get_cached_glyph (renderer,
|
||||||
|
FALSE,
|
||||||
|
font,
|
||||||
|
gi->glyph);
|
||||||
|
|
||||||
|
/* clutter_ensure_glyph_cache_for_layout should always be
|
||||||
|
called before rendering a layout so we should never have
|
||||||
|
a dirty glyph here */
|
||||||
|
g_assert (cache_value == NULL || !cache_value->dirty);
|
||||||
|
|
||||||
|
if (cache_value == NULL)
|
||||||
|
{
|
||||||
|
clutter_pango_renderer_draw_box (renderer,
|
||||||
|
(int) x,
|
||||||
|
(int) y,
|
||||||
|
PANGO_UNKNOWN_GLYPH_WIDTH,
|
||||||
|
PANGO_UNKNOWN_GLYPH_HEIGHT);
|
||||||
|
}
|
||||||
|
else if (cache_value->texture)
|
||||||
|
{
|
||||||
|
x += (float)(cache_value->draw_x);
|
||||||
|
y += (float)(cache_value->draw_y);
|
||||||
|
|
||||||
|
/* Do not override color if the glyph/font provide its own */
|
||||||
|
if (cache_value->has_color)
|
||||||
|
{
|
||||||
|
CoglColor color;
|
||||||
|
uint16_t alpha;
|
||||||
|
|
||||||
|
alpha = pango_renderer_get_alpha (renderer,
|
||||||
|
PANGO_RENDER_PART_FOREGROUND);
|
||||||
|
cogl_color_init_from_4f (&color, 1.0f, 1.0f, 1.0f,
|
||||||
|
alpha ? (alpha >> 8) / 255.0f : 1.0f);
|
||||||
|
clutter_pango_display_list_set_color_override (priv->display_list, &color);
|
||||||
|
}
|
||||||
|
|
||||||
|
clutter_pango_renderer_draw_glyph (priv, cache_value, x, y);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
xi += gi->geometry.width;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
clutter_pango_renderer_class_init (ClutterPangoRendererClass *klass)
|
||||||
|
{
|
||||||
|
GObjectClass *object_class = G_OBJECT_CLASS (klass);
|
||||||
|
PangoRendererClass *renderer_class = PANGO_RENDERER_CLASS (klass);
|
||||||
|
GParamSpec *pspec;
|
||||||
|
|
||||||
|
object_class->set_property = clutter_pango_renderer_set_property;
|
||||||
|
object_class->constructed = clutter_pango_renderer_constructed;
|
||||||
|
object_class->dispose = clutter_pango_renderer_dispose;
|
||||||
|
object_class->finalize = clutter_pango_renderer_finalize;
|
||||||
|
|
||||||
|
pspec = g_param_spec_object ("context", NULL, NULL,
|
||||||
|
COGL_TYPE_CONTEXT,
|
||||||
|
G_PARAM_WRITABLE |
|
||||||
|
G_PARAM_STATIC_STRINGS |
|
||||||
|
G_PARAM_CONSTRUCT_ONLY);
|
||||||
|
|
||||||
|
g_object_class_install_property (object_class, PROP_COGL_CONTEXT, pspec);
|
||||||
|
|
||||||
|
renderer_class->draw_glyphs = clutter_pango_renderer_draw_glyphs;
|
||||||
|
renderer_class->draw_rectangle = clutter_pango_renderer_draw_rectangle;
|
||||||
|
renderer_class->draw_trapezoid = clutter_pango_renderer_draw_trapezoid;
|
||||||
|
}
|
@ -1,83 +0,0 @@
|
|||||||
/*
|
|
||||||
* Clutter.
|
|
||||||
*
|
|
||||||
* An OpenGL based 'interactive canvas' library.
|
|
||||||
*
|
|
||||||
* Copyright (C) 2009 Intel Corporation.
|
|
||||||
*
|
|
||||||
* Permission is hereby granted, free of charge, to any person
|
|
||||||
* obtaining a copy of this software and associated documentation
|
|
||||||
* files (the "Software"), to deal in the Software without
|
|
||||||
* restriction, including without limitation the rights to use, copy,
|
|
||||||
* modify, merge, publish, distribute, sublicense, and/or sell copies
|
|
||||||
* of the Software, and to permit persons to whom the Software is
|
|
||||||
* furnished to do so, subject to the following conditions:
|
|
||||||
*
|
|
||||||
* The above copyright notice and this permission notice shall be
|
|
||||||
* included in all copies or substantial portions of the Software.
|
|
||||||
*
|
|
||||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
|
||||||
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
|
||||||
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
|
||||||
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
|
|
||||||
* BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
|
|
||||||
* ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
|
||||||
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
||||||
* SOFTWARE.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#pragma once
|
|
||||||
|
|
||||||
#include <glib.h>
|
|
||||||
|
|
||||||
#include "clutter/pango/cogl-pango-pipeline-cache.h"
|
|
||||||
#include "clutter/pango/cogl-pango-private.h"
|
|
||||||
|
|
||||||
|
|
||||||
G_BEGIN_DECLS
|
|
||||||
|
|
||||||
typedef struct _CoglPangoDisplayList CoglPangoDisplayList;
|
|
||||||
|
|
||||||
CoglPangoDisplayList *
|
|
||||||
_cogl_pango_display_list_new (CoglPangoPipelineCache *);
|
|
||||||
|
|
||||||
void
|
|
||||||
_cogl_pango_display_list_set_color_override (CoglPangoDisplayList *dl,
|
|
||||||
const CoglColor *color);
|
|
||||||
|
|
||||||
void
|
|
||||||
_cogl_pango_display_list_remove_color_override (CoglPangoDisplayList *dl);
|
|
||||||
|
|
||||||
void
|
|
||||||
_cogl_pango_display_list_add_texture (CoglPangoDisplayList *dl,
|
|
||||||
CoglTexture *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 (CoglFramebuffer *framebuffer,
|
|
||||||
CoglPangoDisplayList *dl,
|
|
||||||
ClutterColorState *color_state,
|
|
||||||
ClutterColorState *target_color_state,
|
|
||||||
const CoglColor *color);
|
|
||||||
|
|
||||||
void
|
|
||||||
_cogl_pango_display_list_free (CoglPangoDisplayList *dl);
|
|
||||||
|
|
||||||
G_END_DECLS
|
|
@ -1,656 +0,0 @@
|
|||||||
/*
|
|
||||||
* Clutter.
|
|
||||||
*
|
|
||||||
* An OpenGL based 'interactive canvas' library.
|
|
||||||
*
|
|
||||||
* Copyright (C) 2008 OpenedHand
|
|
||||||
* Copyright (C) 2012 Intel Corporation.
|
|
||||||
*
|
|
||||||
* Permission is hereby granted, free of charge, to any person
|
|
||||||
* obtaining a copy of this software and associated documentation
|
|
||||||
* files (the "Software"), to deal in the Software without
|
|
||||||
* restriction, including without limitation the rights to use, copy,
|
|
||||||
* modify, merge, publish, distribute, sublicense, and/or sell copies
|
|
||||||
* of the Software, and to permit persons to whom the Software is
|
|
||||||
* furnished to do so, subject to the following conditions:
|
|
||||||
*
|
|
||||||
* The above copyright notice and this permission notice shall be
|
|
||||||
* included in all copies or substantial portions of the Software.
|
|
||||||
*
|
|
||||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
|
||||||
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
|
||||||
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
|
||||||
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
|
|
||||||
* BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
|
|
||||||
* ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
|
||||||
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
||||||
* SOFTWARE.
|
|
||||||
*
|
|
||||||
*
|
|
||||||
* Authors:
|
|
||||||
* Neil Roberts <neil@linux.intel.com>
|
|
||||||
* Robert Bragg <robert@linux.intel.com>
|
|
||||||
* Matthew Allum <mallum@openedhand.com>
|
|
||||||
*/
|
|
||||||
|
|
||||||
#include "config.h"
|
|
||||||
|
|
||||||
#include <pango/pango-fontmap.h>
|
|
||||||
#include <pango/pangocairo.h>
|
|
||||||
#include <pango/pango-renderer.h>
|
|
||||||
#include <cairo.h>
|
|
||||||
#include <cairo-ft.h>
|
|
||||||
|
|
||||||
#include "clutter/clutter-debug.h"
|
|
||||||
#include "clutter/clutter-context-private.h"
|
|
||||||
#include "clutter/clutter-private.h"
|
|
||||||
#include "clutter/pango/cogl-pango-private.h"
|
|
||||||
#include "clutter/pango/cogl-pango-glyph-cache.h"
|
|
||||||
#include "clutter/pango/cogl-pango-display-list.h"
|
|
||||||
#include "cogl/cogl.h"
|
|
||||||
|
|
||||||
#define PANGO_UNKNOWN_GLYPH_WIDTH 10
|
|
||||||
#define PANGO_UNKNOWN_GLYPH_HEIGHT 14
|
|
||||||
|
|
||||||
enum
|
|
||||||
{
|
|
||||||
PROP_0,
|
|
||||||
|
|
||||||
PROP_COGL_CONTEXT,
|
|
||||||
PROP_LAST
|
|
||||||
};
|
|
||||||
|
|
||||||
struct _CoglPangoRenderer
|
|
||||||
{
|
|
||||||
PangoRenderer parent_instance;
|
|
||||||
|
|
||||||
CoglContext *ctx;
|
|
||||||
|
|
||||||
CoglPangoGlyphCache *glyph_cache;
|
|
||||||
CoglPangoPipelineCache *pipeline_cache;
|
|
||||||
|
|
||||||
/* The current display list that is being built */
|
|
||||||
CoglPangoDisplayList *display_list;
|
|
||||||
};
|
|
||||||
|
|
||||||
G_DECLARE_FINAL_TYPE (CoglPangoRenderer,
|
|
||||||
cogl_pango_renderer,
|
|
||||||
COGL_PANGO,
|
|
||||||
RENDERER,
|
|
||||||
PangoRenderer)
|
|
||||||
|
|
||||||
|
|
||||||
G_DEFINE_FINAL_TYPE (CoglPangoRenderer, cogl_pango_renderer, PANGO_TYPE_RENDERER);
|
|
||||||
|
|
||||||
/* An instance of this struct gets attached to each PangoLayout to
|
|
||||||
cache the VBO and to detect changes to the layout */
|
|
||||||
typedef struct _CoglPangoLayoutQdata
|
|
||||||
{
|
|
||||||
CoglPangoRenderer *renderer;
|
|
||||||
/* The cache of the geometry for the layout */
|
|
||||||
CoglPangoDisplayList *display_list;
|
|
||||||
/* A reference to the first line of the layout. This is just used to
|
|
||||||
detect changes */
|
|
||||||
PangoLayoutLine *first_line;
|
|
||||||
} CoglPangoLayoutQdata;
|
|
||||||
|
|
||||||
typedef struct
|
|
||||||
{
|
|
||||||
CoglPangoDisplayList *display_list;
|
|
||||||
float x1, y1, x2, y2;
|
|
||||||
} CoglPangoRendererSliceCbData;
|
|
||||||
|
|
||||||
PangoRenderer *
|
|
||||||
_cogl_pango_renderer_new (CoglContext *context)
|
|
||||||
{
|
|
||||||
return PANGO_RENDERER (g_object_new (cogl_pango_renderer_get_type (),
|
|
||||||
"context", context, NULL));
|
|
||||||
}
|
|
||||||
|
|
||||||
static void
|
|
||||||
cogl_pango_renderer_slice_cb (CoglTexture *texture,
|
|
||||||
const float *slice_coords,
|
|
||||||
const float *virtual_coords,
|
|
||||||
void *user_data)
|
|
||||||
{
|
|
||||||
CoglPangoRendererSliceCbData *data = user_data;
|
|
||||||
|
|
||||||
/* Note: this assumes that there is only one slice containing the
|
|
||||||
whole texture and it doesn't attempt to split up the vertex
|
|
||||||
coordinates based on the virtual_coords */
|
|
||||||
|
|
||||||
_cogl_pango_display_list_add_texture (data->display_list,
|
|
||||||
texture,
|
|
||||||
data->x1,
|
|
||||||
data->y1,
|
|
||||||
data->x2,
|
|
||||||
data->y2,
|
|
||||||
slice_coords[0],
|
|
||||||
slice_coords[1],
|
|
||||||
slice_coords[2],
|
|
||||||
slice_coords[3]);
|
|
||||||
}
|
|
||||||
|
|
||||||
static void
|
|
||||||
cogl_pango_renderer_draw_glyph (CoglPangoRenderer *priv,
|
|
||||||
CoglPangoGlyphCacheValue *cache_value,
|
|
||||||
float x1,
|
|
||||||
float y1)
|
|
||||||
{
|
|
||||||
CoglPangoRendererSliceCbData data;
|
|
||||||
|
|
||||||
g_return_if_fail (priv->display_list != NULL);
|
|
||||||
|
|
||||||
data.display_list = priv->display_list;
|
|
||||||
data.x1 = x1;
|
|
||||||
data.y1 = y1;
|
|
||||||
data.x2 = x1 + (float) cache_value->draw_width;
|
|
||||||
data.y2 = y1 + (float) cache_value->draw_height;
|
|
||||||
|
|
||||||
/* We iterate the internal sub textures of the texture so that we
|
|
||||||
can get a pointer to the base texture even if the texture is in
|
|
||||||
the global atlas. That way the display list can recognise that
|
|
||||||
the neighbouring glyphs are coming from the same atlas and bundle
|
|
||||||
them together into a single VBO */
|
|
||||||
|
|
||||||
cogl_meta_texture_foreach_in_region (cache_value->texture,
|
|
||||||
cache_value->tx1,
|
|
||||||
cache_value->ty1,
|
|
||||||
cache_value->tx2,
|
|
||||||
cache_value->ty2,
|
|
||||||
COGL_PIPELINE_WRAP_MODE_REPEAT,
|
|
||||||
COGL_PIPELINE_WRAP_MODE_REPEAT,
|
|
||||||
cogl_pango_renderer_slice_cb,
|
|
||||||
&data);
|
|
||||||
}
|
|
||||||
|
|
||||||
static void
|
|
||||||
cogl_pango_renderer_init (CoglPangoRenderer *priv)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
static void
|
|
||||||
_cogl_pango_renderer_constructed (GObject *gobject)
|
|
||||||
{
|
|
||||||
CoglPangoRenderer *renderer = COGL_PANGO_RENDERER (gobject);
|
|
||||||
CoglContext *ctx = renderer->ctx;
|
|
||||||
|
|
||||||
renderer->pipeline_cache = _cogl_pango_pipeline_cache_new (ctx);
|
|
||||||
renderer->glyph_cache = cogl_pango_glyph_cache_new (ctx);
|
|
||||||
|
|
||||||
G_OBJECT_CLASS (cogl_pango_renderer_parent_class)->constructed (gobject);
|
|
||||||
}
|
|
||||||
|
|
||||||
static void
|
|
||||||
cogl_pango_renderer_set_property (GObject *object,
|
|
||||||
unsigned int prop_id,
|
|
||||||
const GValue *value,
|
|
||||||
GParamSpec *pspec)
|
|
||||||
{
|
|
||||||
CoglPangoRenderer *renderer = COGL_PANGO_RENDERER (object);
|
|
||||||
|
|
||||||
switch (prop_id)
|
|
||||||
{
|
|
||||||
case PROP_COGL_CONTEXT:
|
|
||||||
renderer->ctx = g_value_get_object (value);
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
static void
|
|
||||||
cogl_pango_renderer_dispose (GObject *object)
|
|
||||||
{
|
|
||||||
CoglPangoRenderer *priv = COGL_PANGO_RENDERER (object);
|
|
||||||
|
|
||||||
g_clear_object (&priv->ctx);
|
|
||||||
|
|
||||||
G_OBJECT_CLASS (cogl_pango_renderer_parent_class)->dispose (object);
|
|
||||||
}
|
|
||||||
|
|
||||||
static void
|
|
||||||
cogl_pango_renderer_finalize (GObject *object)
|
|
||||||
{
|
|
||||||
CoglPangoRenderer *priv = COGL_PANGO_RENDERER (object);
|
|
||||||
|
|
||||||
cogl_pango_glyph_cache_free (priv->glyph_cache);
|
|
||||||
_cogl_pango_pipeline_cache_free (priv->pipeline_cache);
|
|
||||||
|
|
||||||
G_OBJECT_CLASS (cogl_pango_renderer_parent_class)->finalize (object);
|
|
||||||
}
|
|
||||||
|
|
||||||
static GQuark
|
|
||||||
cogl_pango_layout_get_qdata_key (void)
|
|
||||||
{
|
|
||||||
static GQuark key = 0;
|
|
||||||
|
|
||||||
if (G_UNLIKELY (key == 0))
|
|
||||||
key = g_quark_from_static_string ("CoglPangoDisplayList");
|
|
||||||
|
|
||||||
return key;
|
|
||||||
}
|
|
||||||
|
|
||||||
static void
|
|
||||||
cogl_pango_layout_qdata_forget_display_list (CoglPangoLayoutQdata *qdata)
|
|
||||||
{
|
|
||||||
if (qdata->display_list)
|
|
||||||
{
|
|
||||||
_cogl_pango_glyph_cache_remove_reorganize_callback
|
|
||||||
(qdata->renderer->glyph_cache,
|
|
||||||
(GHookFunc) cogl_pango_layout_qdata_forget_display_list,
|
|
||||||
qdata);
|
|
||||||
|
|
||||||
_cogl_pango_display_list_free (qdata->display_list);
|
|
||||||
|
|
||||||
qdata->display_list = NULL;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
static void
|
|
||||||
cogl_pango_render_qdata_destroy (CoglPangoLayoutQdata *qdata)
|
|
||||||
{
|
|
||||||
cogl_pango_layout_qdata_forget_display_list (qdata);
|
|
||||||
if (qdata->first_line)
|
|
||||||
pango_layout_line_unref (qdata->first_line);
|
|
||||||
g_free (qdata);
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
|
||||||
clutter_show_layout (CoglFramebuffer *fb,
|
|
||||||
PangoLayout *layout,
|
|
||||||
float x,
|
|
||||||
float y,
|
|
||||||
const CoglColor *color,
|
|
||||||
ClutterColorState *color_state,
|
|
||||||
ClutterColorState *target_color_state)
|
|
||||||
{
|
|
||||||
CoglPangoRenderer *renderer;
|
|
||||||
CoglPangoLayoutQdata *qdata;
|
|
||||||
ClutterContext *context;
|
|
||||||
|
|
||||||
context = _clutter_context_get_default ();
|
|
||||||
renderer = COGL_PANGO_RENDERER (clutter_context_get_font_renderer (context));
|
|
||||||
if (G_UNLIKELY (!renderer))
|
|
||||||
return;
|
|
||||||
|
|
||||||
qdata = g_object_get_qdata (G_OBJECT (layout),
|
|
||||||
cogl_pango_layout_get_qdata_key ());
|
|
||||||
|
|
||||||
if (qdata == NULL)
|
|
||||||
{
|
|
||||||
qdata = g_new0 (CoglPangoLayoutQdata, 1);
|
|
||||||
qdata->renderer = renderer;
|
|
||||||
g_object_set_qdata_full (G_OBJECT (layout),
|
|
||||||
cogl_pango_layout_get_qdata_key (),
|
|
||||||
qdata,
|
|
||||||
(GDestroyNotify)
|
|
||||||
cogl_pango_render_qdata_destroy);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Check if the layout has changed since the last build of the
|
|
||||||
display list. This trick was suggested by Behdad Esfahbod here:
|
|
||||||
http://mail.gnome.org/archives/gtk-i18n-list/2009-May/msg00019.html */
|
|
||||||
if (qdata->display_list &&
|
|
||||||
((qdata->first_line &&
|
|
||||||
qdata->first_line->layout != layout)))
|
|
||||||
cogl_pango_layout_qdata_forget_display_list (qdata);
|
|
||||||
|
|
||||||
if (qdata->display_list == NULL)
|
|
||||||
{
|
|
||||||
clutter_ensure_glyph_cache_for_layout (layout);
|
|
||||||
|
|
||||||
qdata->display_list =
|
|
||||||
_cogl_pango_display_list_new (renderer->pipeline_cache);
|
|
||||||
|
|
||||||
/* Register for notification of when the glyph cache changes so
|
|
||||||
we can rebuild the display list */
|
|
||||||
_cogl_pango_glyph_cache_add_reorganize_callback
|
|
||||||
(renderer->glyph_cache,
|
|
||||||
(GHookFunc) cogl_pango_layout_qdata_forget_display_list,
|
|
||||||
qdata);
|
|
||||||
|
|
||||||
renderer->display_list = qdata->display_list;
|
|
||||||
pango_renderer_draw_layout (PANGO_RENDERER (renderer), layout, 0, 0);
|
|
||||||
renderer->display_list = NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
cogl_framebuffer_push_matrix (fb);
|
|
||||||
cogl_framebuffer_translate (fb, x, y, 0);
|
|
||||||
|
|
||||||
cogl_pango_display_list_render (fb,
|
|
||||||
qdata->display_list,
|
|
||||||
color_state, target_color_state,
|
|
||||||
color);
|
|
||||||
|
|
||||||
cogl_framebuffer_pop_matrix (fb);
|
|
||||||
|
|
||||||
/* Keep a reference to the first line of the layout so we can detect
|
|
||||||
changes */
|
|
||||||
if (qdata->first_line)
|
|
||||||
{
|
|
||||||
pango_layout_line_unref (qdata->first_line);
|
|
||||||
qdata->first_line = NULL;
|
|
||||||
}
|
|
||||||
if (pango_layout_get_line_count (layout) > 0)
|
|
||||||
{
|
|
||||||
qdata->first_line = pango_layout_get_line (layout, 0);
|
|
||||||
pango_layout_line_ref (qdata->first_line);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
static CoglPangoGlyphCacheValue *
|
|
||||||
cogl_pango_renderer_get_cached_glyph (PangoRenderer *renderer,
|
|
||||||
gboolean create,
|
|
||||||
PangoFont *font,
|
|
||||||
PangoGlyph glyph)
|
|
||||||
{
|
|
||||||
CoglPangoRenderer *priv = COGL_PANGO_RENDERER (renderer);
|
|
||||||
|
|
||||||
return cogl_pango_glyph_cache_lookup (priv->glyph_cache,
|
|
||||||
priv->ctx,
|
|
||||||
create, font, glyph);
|
|
||||||
}
|
|
||||||
|
|
||||||
static void
|
|
||||||
_cogl_pango_ensure_glyph_cache_for_layout_line_internal (PangoLayoutLine *line)
|
|
||||||
{
|
|
||||||
ClutterContext *context;
|
|
||||||
PangoRenderer *renderer;
|
|
||||||
GSList *l;
|
|
||||||
|
|
||||||
context = _clutter_context_get_default ();
|
|
||||||
renderer = clutter_context_get_font_renderer (context);
|
|
||||||
|
|
||||||
for (l = line->runs; l; l = l->next)
|
|
||||||
{
|
|
||||||
PangoLayoutRun *run = l->data;
|
|
||||||
PangoGlyphString *glyphs = run->glyphs;
|
|
||||||
int i;
|
|
||||||
|
|
||||||
for (i = 0; i < glyphs->num_glyphs; i++)
|
|
||||||
{
|
|
||||||
PangoGlyphInfo *gi = &glyphs->glyphs[i];
|
|
||||||
|
|
||||||
/* If the glyph isn't cached then this will reserve
|
|
||||||
space for it now. We won't actually draw the glyph
|
|
||||||
yet because reserving space could cause all of the
|
|
||||||
other glyphs to be moved so we might as well redraw
|
|
||||||
them all later once we know that the position is
|
|
||||||
settled */
|
|
||||||
cogl_pango_renderer_get_cached_glyph (renderer, TRUE,
|
|
||||||
run->item->analysis.font,
|
|
||||||
gi->glyph);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
|
||||||
clutter_ensure_glyph_cache_for_layout (PangoLayout *layout)
|
|
||||||
{
|
|
||||||
ClutterContext *context;
|
|
||||||
CoglPangoRenderer *renderer;
|
|
||||||
PangoLayoutIter *iter;
|
|
||||||
|
|
||||||
context = _clutter_context_get_default ();
|
|
||||||
renderer = COGL_PANGO_RENDERER (clutter_context_get_font_renderer (context));
|
|
||||||
|
|
||||||
g_return_if_fail (PANGO_IS_LAYOUT (layout));
|
|
||||||
|
|
||||||
if ((iter = pango_layout_get_iter (layout)) == NULL)
|
|
||||||
return;
|
|
||||||
|
|
||||||
do
|
|
||||||
{
|
|
||||||
PangoLayoutLine *line;
|
|
||||||
|
|
||||||
line = pango_layout_iter_get_line_readonly (iter);
|
|
||||||
|
|
||||||
_cogl_pango_ensure_glyph_cache_for_layout_line_internal (line);
|
|
||||||
}
|
|
||||||
while (pango_layout_iter_next_line (iter));
|
|
||||||
|
|
||||||
pango_layout_iter_free (iter);
|
|
||||||
|
|
||||||
/* Now that we know all of the positions are settled we'll fill in
|
|
||||||
any dirty glyphs */
|
|
||||||
_cogl_pango_glyph_cache_set_dirty_glyphs (renderer->glyph_cache);
|
|
||||||
}
|
|
||||||
|
|
||||||
static void
|
|
||||||
cogl_pango_renderer_set_color_for_part (PangoRenderer *renderer,
|
|
||||||
PangoRenderPart part)
|
|
||||||
{
|
|
||||||
PangoColor *pango_color = pango_renderer_get_color (renderer, part);
|
|
||||||
uint16_t alpha = pango_renderer_get_alpha (renderer, part);
|
|
||||||
CoglPangoRenderer *priv = COGL_PANGO_RENDERER (renderer);
|
|
||||||
|
|
||||||
if (pango_color)
|
|
||||||
{
|
|
||||||
CoglColor color;
|
|
||||||
|
|
||||||
cogl_color_init_from_4f (&color,
|
|
||||||
pango_color->red / 65535.0f,
|
|
||||||
pango_color->green / 65535.0f,
|
|
||||||
pango_color->blue / 65535.0f,
|
|
||||||
alpha ? alpha / 65535.0f : 1.0f);
|
|
||||||
|
|
||||||
_cogl_pango_display_list_set_color_override (priv->display_list, &color);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
_cogl_pango_display_list_remove_color_override (priv->display_list);
|
|
||||||
}
|
|
||||||
|
|
||||||
static void
|
|
||||||
cogl_pango_renderer_draw_box (PangoRenderer *renderer,
|
|
||||||
int x,
|
|
||||||
int y,
|
|
||||||
int width,
|
|
||||||
int height)
|
|
||||||
{
|
|
||||||
CoglPangoRenderer *priv = COGL_PANGO_RENDERER (renderer);
|
|
||||||
|
|
||||||
g_return_if_fail (priv->display_list != NULL);
|
|
||||||
|
|
||||||
_cogl_pango_display_list_add_rectangle (priv->display_list,
|
|
||||||
x,
|
|
||||||
y - height,
|
|
||||||
x + width,
|
|
||||||
y);
|
|
||||||
}
|
|
||||||
|
|
||||||
static void
|
|
||||||
cogl_pango_renderer_get_device_units (PangoRenderer *renderer,
|
|
||||||
int xin,
|
|
||||||
int yin,
|
|
||||||
float *xout,
|
|
||||||
float *yout)
|
|
||||||
{
|
|
||||||
const PangoMatrix *matrix;
|
|
||||||
|
|
||||||
if ((matrix = pango_renderer_get_matrix (renderer)))
|
|
||||||
{
|
|
||||||
/* Convert user-space coords to device coords */
|
|
||||||
*xout = (float) ((xin * matrix->xx + yin * matrix->xy) /
|
|
||||||
PANGO_SCALE + matrix->x0);
|
|
||||||
*yout = (float) ((yin * matrix->yy + xin * matrix->yx) /
|
|
||||||
PANGO_SCALE + matrix->y0);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
*xout = PANGO_PIXELS (xin);
|
|
||||||
*yout = PANGO_PIXELS (yin);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
static void
|
|
||||||
cogl_pango_renderer_draw_rectangle (PangoRenderer *renderer,
|
|
||||||
PangoRenderPart part,
|
|
||||||
int x,
|
|
||||||
int y,
|
|
||||||
int width,
|
|
||||||
int height)
|
|
||||||
{
|
|
||||||
CoglPangoRenderer *priv = COGL_PANGO_RENDERER (renderer);
|
|
||||||
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_get_device_units (renderer,
|
|
||||||
x, y,
|
|
||||||
&x1, &y1);
|
|
||||||
cogl_pango_renderer_get_device_units (renderer,
|
|
||||||
x + width, y + height,
|
|
||||||
&x2, &y2);
|
|
||||||
|
|
||||||
_cogl_pango_display_list_add_rectangle (priv->display_list,
|
|
||||||
x1, y1, x2, y2);
|
|
||||||
}
|
|
||||||
|
|
||||||
static void
|
|
||||||
cogl_pango_renderer_draw_trapezoid (PangoRenderer *renderer,
|
|
||||||
PangoRenderPart part,
|
|
||||||
double y1,
|
|
||||||
double x11,
|
|
||||||
double x21,
|
|
||||||
double y2,
|
|
||||||
double x12,
|
|
||||||
double x22)
|
|
||||||
{
|
|
||||||
CoglPangoRenderer *priv = COGL_PANGO_RENDERER (renderer);
|
|
||||||
|
|
||||||
g_return_if_fail (priv->display_list != NULL);
|
|
||||||
|
|
||||||
cogl_pango_renderer_set_color_for_part (renderer, part);
|
|
||||||
|
|
||||||
_cogl_pango_display_list_add_trapezoid (priv->display_list,
|
|
||||||
(float) y1,
|
|
||||||
(float) x11,
|
|
||||||
(float) x21,
|
|
||||||
(float) y2,
|
|
||||||
(float) x12,
|
|
||||||
(float) x22);
|
|
||||||
}
|
|
||||||
|
|
||||||
static void
|
|
||||||
cogl_pango_renderer_draw_glyphs (PangoRenderer *renderer,
|
|
||||||
PangoFont *font,
|
|
||||||
PangoGlyphString *glyphs,
|
|
||||||
int xi,
|
|
||||||
int yi)
|
|
||||||
{
|
|
||||||
CoglPangoRenderer *priv = (CoglPangoRenderer *) renderer;
|
|
||||||
CoglPangoGlyphCacheValue *cache_value;
|
|
||||||
int i;
|
|
||||||
|
|
||||||
for (i = 0; i < glyphs->num_glyphs; i++)
|
|
||||||
{
|
|
||||||
PangoGlyphInfo *gi = glyphs->glyphs + i;
|
|
||||||
float x, y;
|
|
||||||
|
|
||||||
cogl_pango_renderer_set_color_for_part (renderer,
|
|
||||||
PANGO_RENDER_PART_FOREGROUND);
|
|
||||||
cogl_pango_renderer_get_device_units (renderer,
|
|
||||||
xi + gi->geometry.x_offset,
|
|
||||||
yi + gi->geometry.y_offset,
|
|
||||||
&x, &y);
|
|
||||||
|
|
||||||
if ((gi->glyph & PANGO_GLYPH_UNKNOWN_FLAG))
|
|
||||||
{
|
|
||||||
if (font == NULL)
|
|
||||||
{
|
|
||||||
cogl_pango_renderer_draw_box (renderer,
|
|
||||||
(int) x,
|
|
||||||
(int) y,
|
|
||||||
PANGO_UNKNOWN_GLYPH_WIDTH,
|
|
||||||
PANGO_UNKNOWN_GLYPH_HEIGHT);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
PangoRectangle ink_rect;
|
|
||||||
|
|
||||||
pango_font_get_glyph_extents (font, gi->glyph, &ink_rect, NULL);
|
|
||||||
pango_extents_to_pixels (&ink_rect, NULL);
|
|
||||||
|
|
||||||
cogl_pango_renderer_draw_box (renderer,
|
|
||||||
(int) (x + ink_rect.x),
|
|
||||||
(int) (y + ink_rect.y + ink_rect.height),
|
|
||||||
ink_rect.width,
|
|
||||||
ink_rect.height);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
/* Get the texture containing the glyph */
|
|
||||||
cache_value =
|
|
||||||
cogl_pango_renderer_get_cached_glyph (renderer,
|
|
||||||
FALSE,
|
|
||||||
font,
|
|
||||||
gi->glyph);
|
|
||||||
|
|
||||||
/* clutter_ensure_glyph_cache_for_layout should always be
|
|
||||||
called before rendering a layout so we should never have
|
|
||||||
a dirty glyph here */
|
|
||||||
g_assert (cache_value == NULL || !cache_value->dirty);
|
|
||||||
|
|
||||||
if (cache_value == NULL)
|
|
||||||
{
|
|
||||||
cogl_pango_renderer_draw_box (renderer,
|
|
||||||
(int) x,
|
|
||||||
(int) y,
|
|
||||||
PANGO_UNKNOWN_GLYPH_WIDTH,
|
|
||||||
PANGO_UNKNOWN_GLYPH_HEIGHT);
|
|
||||||
}
|
|
||||||
else if (cache_value->texture)
|
|
||||||
{
|
|
||||||
x += (float)(cache_value->draw_x);
|
|
||||||
y += (float)(cache_value->draw_y);
|
|
||||||
|
|
||||||
/* Do not override color if the glyph/font provide its own */
|
|
||||||
if (cache_value->has_color)
|
|
||||||
{
|
|
||||||
CoglColor color;
|
|
||||||
uint16_t alpha;
|
|
||||||
|
|
||||||
alpha = pango_renderer_get_alpha (renderer,
|
|
||||||
PANGO_RENDER_PART_FOREGROUND);
|
|
||||||
cogl_color_init_from_4f (&color, 1.0f, 1.0f, 1.0f,
|
|
||||||
alpha ? (alpha >> 8) / 255.0f : 1.0f);
|
|
||||||
_cogl_pango_display_list_set_color_override (priv->display_list, &color);
|
|
||||||
}
|
|
||||||
|
|
||||||
cogl_pango_renderer_draw_glyph (priv, cache_value, x, y);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
xi += gi->geometry.width;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
static void
|
|
||||||
cogl_pango_renderer_class_init (CoglPangoRendererClass *klass)
|
|
||||||
{
|
|
||||||
GObjectClass *object_class = G_OBJECT_CLASS (klass);
|
|
||||||
PangoRendererClass *renderer_class = PANGO_RENDERER_CLASS (klass);
|
|
||||||
GParamSpec *pspec;
|
|
||||||
|
|
||||||
object_class->set_property = cogl_pango_renderer_set_property;
|
|
||||||
object_class->constructed = _cogl_pango_renderer_constructed;
|
|
||||||
object_class->dispose = cogl_pango_renderer_dispose;
|
|
||||||
object_class->finalize = cogl_pango_renderer_finalize;
|
|
||||||
|
|
||||||
pspec = g_param_spec_object ("context", NULL, NULL,
|
|
||||||
COGL_TYPE_CONTEXT,
|
|
||||||
G_PARAM_WRITABLE |
|
|
||||||
G_PARAM_STATIC_STRINGS |
|
|
||||||
G_PARAM_CONSTRUCT_ONLY);
|
|
||||||
|
|
||||||
g_object_class_install_property (object_class, PROP_COGL_CONTEXT, pspec);
|
|
||||||
|
|
||||||
renderer_class->draw_glyphs = cogl_pango_renderer_draw_glyphs;
|
|
||||||
renderer_class->draw_rectangle = cogl_pango_renderer_draw_rectangle;
|
|
||||||
renderer_class->draw_trapezoid = cogl_pango_renderer_draw_trapezoid;
|
|
||||||
}
|
|
Loading…
x
Reference in New Issue
Block a user