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-paint-node-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_enable_accessibility = TRUE;
|
||||
@ -321,7 +321,7 @@ clutter_context_get_pango_fontmap (ClutterContext *context)
|
||||
backend = clutter_context_get_backend (context);
|
||||
cogl_context = clutter_backend_get_cogl_context (backend);
|
||||
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);
|
||||
pango_cairo_font_map_set_resolution (PANGO_CAIRO_FONT_MAP (font_map),
|
||||
|
@ -30,7 +30,7 @@
|
||||
#include <pango/pango.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-blur-private.h"
|
||||
#include "clutter/clutter-debug.h"
|
||||
|
@ -46,7 +46,7 @@
|
||||
|
||||
#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-actor-private.h"
|
||||
#include "clutter/clutter-animatable.h"
|
||||
|
@ -84,10 +84,10 @@ clutter_headers = [
|
||||
]
|
||||
|
||||
clutter_sources = [
|
||||
'pango/cogl-pango-display-list.c',
|
||||
'pango/cogl-pango-glyph-cache.c',
|
||||
'pango/cogl-pango-pipeline-cache.c',
|
||||
'pango/cogl-pango-render.c',
|
||||
'pango/clutter-pango-display-list.c',
|
||||
'pango/clutter-pango-glyph-cache.c',
|
||||
'pango/clutter-pango-pipeline-cache.c',
|
||||
'pango/clutter-pango-render.c',
|
||||
'clutter-accessibility.c',
|
||||
'clutter-action.c',
|
||||
'clutter-actor-box.c',
|
||||
@ -181,10 +181,10 @@ clutter_sources = [
|
||||
]
|
||||
|
||||
clutter_private_headers = [
|
||||
'pango/cogl-pango-display-list.h',
|
||||
'pango/cogl-pango-glyph-cache.h',
|
||||
'pango/cogl-pango-pipeline-cache.h',
|
||||
'pango/cogl-pango-private.h',
|
||||
'pango/clutter-pango-display-list.h',
|
||||
'pango/clutter-pango-glyph-cache.h',
|
||||
'pango/clutter-pango-pipeline-cache.h',
|
||||
'pango/clutter-pango-private.h',
|
||||
'clutter-accessibility-private.h',
|
||||
'clutter-actor-meta-private.h',
|
||||
'clutter-actor-private.h',
|
||||
|
@ -31,39 +31,36 @@
|
||||
#include <glib.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "clutter/pango/cogl-pango-display-list.h"
|
||||
#include "clutter/pango/cogl-pango-pipeline-cache.h"
|
||||
#include "clutter/pango/clutter-pango-display-list.h"
|
||||
#include "clutter/pango/clutter-pango-pipeline-cache.h"
|
||||
#include "cogl/cogl.h"
|
||||
|
||||
typedef enum
|
||||
{
|
||||
COGL_PANGO_DISPLAY_LIST_TEXTURE,
|
||||
COGL_PANGO_DISPLAY_LIST_RECTANGLE,
|
||||
COGL_PANGO_DISPLAY_LIST_TRAPEZOID
|
||||
} CoglPangoDisplayListNodeType;
|
||||
PANGO_DISPLAY_LIST_TEXTURE,
|
||||
PANGO_DISPLAY_LIST_RECTANGLE,
|
||||
PANGO_DISPLAY_LIST_TRAPEZOID
|
||||
} PangoDisplayListNodeType;
|
||||
|
||||
typedef struct _CoglPangoDisplayListNode CoglPangoDisplayListNode;
|
||||
typedef struct _CoglPangoDisplayListRectangle CoglPangoDisplayListRectangle;
|
||||
|
||||
struct _CoglPangoDisplayList
|
||||
struct _ClutterPangoDisplayList
|
||||
{
|
||||
gboolean color_override;
|
||||
CoglColor color;
|
||||
gboolean color_override;
|
||||
CoglColor color;
|
||||
GSList *nodes;
|
||||
GSList *last_node;
|
||||
CoglPangoPipelineCache *pipeline_cache;
|
||||
ClutterPangoPipelineCache *pipeline_cache;
|
||||
};
|
||||
|
||||
/* 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 s_1, t_1, s_2, t_2;
|
||||
};
|
||||
} PangoDisplayListRectangle;
|
||||
|
||||
struct _CoglPangoDisplayListNode
|
||||
typedef struct _PangoDisplayListNode
|
||||
{
|
||||
CoglPangoDisplayListNodeType type;
|
||||
PangoDisplayListNodeType type;
|
||||
|
||||
gboolean color_override;
|
||||
CoglColor color;
|
||||
@ -95,12 +92,12 @@ struct _CoglPangoDisplayListNode
|
||||
CoglPrimitive *primitive;
|
||||
} trapezoid;
|
||||
} d;
|
||||
};
|
||||
} PangoDisplayListNode;
|
||||
|
||||
CoglPangoDisplayList *
|
||||
_cogl_pango_display_list_new (CoglPangoPipelineCache *pipeline_cache)
|
||||
ClutterPangoDisplayList *
|
||||
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;
|
||||
|
||||
@ -108,8 +105,8 @@ _cogl_pango_display_list_new (CoglPangoPipelineCache *pipeline_cache)
|
||||
}
|
||||
|
||||
static void
|
||||
_cogl_pango_display_list_append_node (CoglPangoDisplayList *dl,
|
||||
CoglPangoDisplayListNode *node)
|
||||
clutter_pango_display_list_append_node (ClutterPangoDisplayList *dl,
|
||||
PangoDisplayListNode *node)
|
||||
{
|
||||
if (dl->last_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
|
||||
_cogl_pango_display_list_set_color_override (CoglPangoDisplayList *dl,
|
||||
const CoglColor *color)
|
||||
clutter_pango_display_list_set_color_override (ClutterPangoDisplayList *dl,
|
||||
const CoglColor *color)
|
||||
{
|
||||
dl->color_override = TRUE;
|
||||
dl->color = *color;
|
||||
}
|
||||
|
||||
void
|
||||
_cogl_pango_display_list_remove_color_override (CoglPangoDisplayList *dl)
|
||||
clutter_pango_display_list_remove_color_override (ClutterPangoDisplayList *dl)
|
||||
{
|
||||
dl->color_override = FALSE;
|
||||
}
|
||||
|
||||
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)
|
||||
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)
|
||||
{
|
||||
CoglPangoDisplayListNode *node;
|
||||
CoglPangoDisplayListRectangle *rectangle;
|
||||
PangoDisplayListNode *node;
|
||||
PangoDisplayListRectangle *rectangle;
|
||||
|
||||
/* Add to the last node if it is a texture node with the same
|
||||
target texture */
|
||||
if (dl->last_node
|
||||
&& (node = dl->last_node->data)->type == COGL_PANGO_DISPLAY_LIST_TEXTURE
|
||||
&& (node = dl->last_node->data)->type == PANGO_DISPLAY_LIST_TEXTURE
|
||||
&& node->d.texture.texture == texture
|
||||
&& (dl->color_override
|
||||
? (node->color_override && cogl_color_equal (&dl->color, &node->color))
|
||||
@ -157,24 +158,24 @@ _cogl_pango_display_list_add_texture (CoglPangoDisplayList *dl,
|
||||
else
|
||||
{
|
||||
/* 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 = dl->color;
|
||||
node->pipeline = NULL;
|
||||
node->d.texture.texture = g_object_ref (texture);
|
||||
node->d.texture.rectangles
|
||||
= g_array_new (FALSE, FALSE, sizeof (CoglPangoDisplayListRectangle));
|
||||
= g_array_new (FALSE, FALSE, sizeof (PangoDisplayListRectangle));
|
||||
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,
|
||||
node->d.texture.rectangles->len + 1);
|
||||
rectangle = &g_array_index (node->d.texture.rectangles,
|
||||
CoglPangoDisplayListRectangle,
|
||||
PangoDisplayListRectangle,
|
||||
node->d.texture.rectangles->len - 1);
|
||||
rectangle->x_1 = x_1;
|
||||
rectangle->y_1 = y_1;
|
||||
@ -187,13 +188,15 @@ _cogl_pango_display_list_add_texture (CoglPangoDisplayList *dl,
|
||||
}
|
||||
|
||||
void
|
||||
_cogl_pango_display_list_add_rectangle (CoglPangoDisplayList *dl,
|
||||
float x_1, float y_1,
|
||||
float x_2, float y_2)
|
||||
clutter_pango_display_list_add_rectangle (ClutterPangoDisplayList *dl,
|
||||
float x_1,
|
||||
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 = dl->color;
|
||||
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->pipeline = NULL;
|
||||
|
||||
_cogl_pango_display_list_append_node (dl, node);
|
||||
clutter_pango_display_list_append_node (dl, node);
|
||||
}
|
||||
|
||||
void
|
||||
_cogl_pango_display_list_add_trapezoid (CoglPangoDisplayList *dl,
|
||||
float y_1,
|
||||
float x_11,
|
||||
float x_21,
|
||||
float y_2,
|
||||
float x_12,
|
||||
float x_22)
|
||||
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)
|
||||
{
|
||||
CoglContext *ctx = dl->pipeline_cache->ctx;
|
||||
CoglPangoDisplayListNode *node = g_new0 (CoglPangoDisplayListNode, 1);
|
||||
PangoDisplayListNode *node = g_new0 (PangoDisplayListNode, 1);
|
||||
CoglVertexP2 vertices[4] = {
|
||||
{ x_11, y_1 },
|
||||
{ x_12, y_2 },
|
||||
@ -223,7 +226,7 @@ _cogl_pango_display_list_add_trapezoid (CoglPangoDisplayList *dl,
|
||||
{ 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 = dl->color;
|
||||
node->pipeline = NULL;
|
||||
@ -234,13 +237,13 @@ _cogl_pango_display_list_add_trapezoid (CoglPangoDisplayList *dl,
|
||||
4,
|
||||
vertices);
|
||||
|
||||
_cogl_pango_display_list_append_node (dl, node);
|
||||
clutter_pango_display_list_append_node (dl, node);
|
||||
}
|
||||
|
||||
static void
|
||||
emit_rectangles_through_journal (CoglFramebuffer *fb,
|
||||
CoglPipeline *pipeline,
|
||||
CoglPangoDisplayListNode *node)
|
||||
PangoDisplayListNode *node)
|
||||
{
|
||||
const float *rectangles = (const float *)node->d.texture.rectangles->data;
|
||||
|
||||
@ -253,7 +256,7 @@ emit_rectangles_through_journal (CoglFramebuffer *fb,
|
||||
static void
|
||||
emit_vertex_buffer_geometry (CoglFramebuffer *fb,
|
||||
CoglPipeline *pipeline,
|
||||
CoglPangoDisplayListNode *node)
|
||||
PangoDisplayListNode *node)
|
||||
{
|
||||
CoglContext *ctx = cogl_framebuffer_get_context (fb);
|
||||
|
||||
@ -297,9 +300,9 @@ emit_vertex_buffer_geometry (CoglFramebuffer *fb,
|
||||
vertices instead of just two */
|
||||
for (i = 0; i < node->d.texture.rectangles->len; i++)
|
||||
{
|
||||
const CoglPangoDisplayListRectangle *rectangle
|
||||
const PangoDisplayListRectangle *rectangle
|
||||
= &g_array_index (node->d.texture.rectangles,
|
||||
CoglPangoDisplayListRectangle, i);
|
||||
PangoDisplayListRectangle, i);
|
||||
|
||||
v->x = rectangle->x_1;
|
||||
v->y = rectangle->y_1;
|
||||
@ -373,7 +376,7 @@ emit_vertex_buffer_geometry (CoglFramebuffer *fb,
|
||||
static void
|
||||
_cogl_framebuffer_draw_display_list_texture (CoglFramebuffer *fb,
|
||||
CoglPipeline *pipeline,
|
||||
CoglPangoDisplayListNode *node)
|
||||
PangoDisplayListNode *node)
|
||||
{
|
||||
/* 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
|
||||
@ -387,30 +390,30 @@ _cogl_framebuffer_draw_display_list_texture (CoglFramebuffer *fb,
|
||||
}
|
||||
|
||||
void
|
||||
cogl_pango_display_list_render (CoglFramebuffer *fb,
|
||||
CoglPangoDisplayList *dl,
|
||||
ClutterColorState *color_state,
|
||||
ClutterColorState *target_color_state,
|
||||
const CoglColor *color)
|
||||
clutter_pango_display_list_render (CoglFramebuffer *fb,
|
||||
ClutterPangoDisplayList *dl,
|
||||
ClutterColorState *color_state,
|
||||
ClutterColorState *target_color_state,
|
||||
const CoglColor *color)
|
||||
{
|
||||
GSList *l;
|
||||
|
||||
for (l = dl->nodes; l; l = l->next)
|
||||
{
|
||||
CoglPangoDisplayListNode *node = l->data;
|
||||
PangoDisplayListNode *node = l->data;
|
||||
CoglColor draw_color;
|
||||
g_autoptr (CoglPipeline) pipeline = NULL;
|
||||
|
||||
if (node->pipeline == NULL)
|
||||
{
|
||||
if (node->type == COGL_PANGO_DISPLAY_LIST_TEXTURE)
|
||||
if (node->type == PANGO_DISPLAY_LIST_TEXTURE)
|
||||
node->pipeline =
|
||||
_cogl_pango_pipeline_cache_get (dl->pipeline_cache,
|
||||
node->d.texture.texture);
|
||||
clutter_pango_pipeline_cache_get (dl->pipeline_cache,
|
||||
node->d.texture.texture);
|
||||
else
|
||||
node->pipeline =
|
||||
_cogl_pango_pipeline_cache_get (dl->pipeline_cache,
|
||||
NULL);
|
||||
clutter_pango_pipeline_cache_get (dl->pipeline_cache,
|
||||
NULL);
|
||||
}
|
||||
|
||||
pipeline = cogl_pipeline_copy (node->pipeline);
|
||||
@ -437,11 +440,11 @@ cogl_pango_display_list_render (CoglFramebuffer *fb,
|
||||
|
||||
switch (node->type)
|
||||
{
|
||||
case COGL_PANGO_DISPLAY_LIST_TEXTURE:
|
||||
case PANGO_DISPLAY_LIST_TEXTURE:
|
||||
_cogl_framebuffer_draw_display_list_texture (fb, pipeline, node);
|
||||
break;
|
||||
|
||||
case COGL_PANGO_DISPLAY_LIST_RECTANGLE:
|
||||
case PANGO_DISPLAY_LIST_RECTANGLE:
|
||||
cogl_framebuffer_draw_rectangle (fb,
|
||||
pipeline,
|
||||
node->d.rectangle.x_1,
|
||||
@ -450,7 +453,7 @@ cogl_pango_display_list_render (CoglFramebuffer *fb,
|
||||
node->d.rectangle.y_2);
|
||||
break;
|
||||
|
||||
case COGL_PANGO_DISPLAY_LIST_TRAPEZOID:
|
||||
case PANGO_DISPLAY_LIST_TRAPEZOID:
|
||||
cogl_primitive_draw (node->d.trapezoid.primitive,
|
||||
fb,
|
||||
pipeline);
|
||||
@ -460,15 +463,15 @@ cogl_pango_display_list_render (CoglFramebuffer *fb,
|
||||
}
|
||||
|
||||
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_clear_object (&node->d.texture.texture);
|
||||
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->pipeline);
|
||||
@ -477,10 +480,10 @@ _cogl_pango_display_list_node_free (CoglPangoDisplayListNode *node)
|
||||
}
|
||||
|
||||
void
|
||||
_cogl_pango_display_list_free (CoglPangoDisplayList *dl)
|
||||
clutter_pango_display_list_free (ClutterPangoDisplayList *dl)
|
||||
{
|
||||
g_slist_free_full (dl->nodes, (GDestroyNotify)
|
||||
_cogl_pango_display_list_node_free);
|
||||
clutter_pango_display_list_node_free);
|
||||
dl->nodes = NULL;
|
||||
dl->last_node = NULL;
|
||||
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 "clutter/clutter-debug.h"
|
||||
#include "clutter/pango/cogl-pango-glyph-cache.h"
|
||||
#include "clutter/pango/cogl-pango-private.h"
|
||||
#include "clutter/pango/clutter-pango-glyph-cache.h"
|
||||
#include "clutter/pango/clutter-pango-private.h"
|
||||
|
||||
typedef struct _CoglPangoGlyphCacheKey CoglPangoGlyphCacheKey;
|
||||
|
||||
struct _CoglPangoGlyphCache
|
||||
struct _ClutterPangoGlyphCache
|
||||
{
|
||||
CoglContext *ctx;
|
||||
|
||||
@ -50,44 +48,43 @@ struct _CoglPangoGlyphCache
|
||||
GSList *atlases;
|
||||
|
||||
/* 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
|
||||
used to make sure we only register one callback to listen for
|
||||
global atlas reorganizations */
|
||||
gboolean using_global_atlas;
|
||||
gboolean using_global_atlas;
|
||||
|
||||
/* 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 */
|
||||
gboolean has_dirty_glyphs;
|
||||
gboolean has_dirty_glyphs;
|
||||
};
|
||||
|
||||
struct _CoglPangoGlyphCacheKey
|
||||
typedef struct _PangoGlyphCacheKey
|
||||
{
|
||||
PangoFont *font;
|
||||
PangoGlyph glyph;
|
||||
};
|
||||
PangoGlyph glyph;
|
||||
} PangoGlyphCacheKey;
|
||||
|
||||
static void
|
||||
cogl_pango_glyph_cache_value_free (CoglPangoGlyphCacheValue *value)
|
||||
clutter_pango_glyph_cache_value_free (PangoGlyphCacheValue *value)
|
||||
{
|
||||
g_clear_object (&value->texture);
|
||||
g_free (value);
|
||||
}
|
||||
|
||||
static void
|
||||
cogl_pango_glyph_cache_key_free (CoglPangoGlyphCacheKey *key)
|
||||
clutter_pango_glyph_cache_key_free (PangoGlyphCacheKey *key)
|
||||
{
|
||||
g_clear_object (&key->font);
|
||||
g_free (key);
|
||||
}
|
||||
|
||||
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 CoglPangoGlyphCacheKey *) key;
|
||||
const PangoGlyphCacheKey *cache_key = (const PangoGlyphCacheKey *) key;
|
||||
|
||||
/* Generate a number affected by both the font and the glyph
|
||||
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
|
||||
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 CoglPangoGlyphCacheKey *) a;
|
||||
const CoglPangoGlyphCacheKey *key_b
|
||||
= (const CoglPangoGlyphCacheKey *) b;
|
||||
const PangoGlyphCacheKey *key_a = (const PangoGlyphCacheKey *) a;
|
||||
const PangoGlyphCacheKey *key_b = (const PangoGlyphCacheKey *) b;
|
||||
|
||||
/* 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
|
||||
a different font will have the same memory address */
|
||||
return key_a->font == key_b->font
|
||||
&& key_a->glyph == key_b->glyph;
|
||||
&& key_a->glyph == key_b->glyph;
|
||||
}
|
||||
|
||||
CoglPangoGlyphCache *
|
||||
cogl_pango_glyph_cache_new (CoglContext *ctx)
|
||||
ClutterPangoGlyphCache *
|
||||
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
|
||||
* internally since */
|
||||
cache->ctx = ctx;
|
||||
|
||||
cache->hash_table = g_hash_table_new_full
|
||||
(cogl_pango_glyph_cache_hash_func,
|
||||
cogl_pango_glyph_cache_equal_func,
|
||||
(GDestroyNotify) cogl_pango_glyph_cache_key_free,
|
||||
(GDestroyNotify) cogl_pango_glyph_cache_value_free);
|
||||
(clutter_pango_glyph_cache_hash_func,
|
||||
clutter_pango_glyph_cache_equal_func,
|
||||
(GDestroyNotify) clutter_pango_glyph_cache_key_free,
|
||||
(GDestroyNotify) clutter_pango_glyph_cache_value_free);
|
||||
|
||||
cache->atlases = NULL;
|
||||
g_hook_list_init (&cache->reorganize_callbacks, sizeof (GHook));
|
||||
@ -139,21 +135,21 @@ cogl_pango_glyph_cache_new (CoglContext *ctx)
|
||||
}
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
void
|
||||
cogl_pango_glyph_cache_free (CoglPangoGlyphCache *cache)
|
||||
clutter_pango_glyph_cache_free (ClutterPangoGlyphCache *cache)
|
||||
{
|
||||
if (cache->using_global_atlas)
|
||||
{
|
||||
cogl_atlas_texture_remove_reorganize_callback (
|
||||
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);
|
||||
@ -169,11 +165,11 @@ cogl_pango_glyph_cache_free (CoglPangoGlyphCache *cache)
|
||||
}
|
||||
|
||||
static void
|
||||
cogl_pango_glyph_cache_update_position_cb (void *user_data,
|
||||
CoglTexture *new_texture,
|
||||
const MtkRectangle *rect)
|
||||
clutter_pango_glyph_cache_update_position_cb (void *user_data,
|
||||
CoglTexture *new_texture,
|
||||
const MtkRectangle *rect)
|
||||
{
|
||||
CoglPangoGlyphCacheValue *value = user_data;
|
||||
PangoGlyphCacheValue *value = user_data;
|
||||
float tex_width, tex_height;
|
||||
|
||||
g_clear_object (&value->texture);
|
||||
@ -195,10 +191,10 @@ cogl_pango_glyph_cache_update_position_cb (void *user_data,
|
||||
}
|
||||
|
||||
static gboolean
|
||||
cogl_pango_glyph_cache_add_to_global_atlas (CoglPangoGlyphCache *cache,
|
||||
PangoFont *font,
|
||||
PangoGlyph glyph,
|
||||
CoglPangoGlyphCacheValue *value)
|
||||
clutter_pango_glyph_cache_add_to_global_atlas (ClutterPangoGlyphCache *cache,
|
||||
PangoFont *font,
|
||||
PangoGlyph glyph,
|
||||
PangoGlyphCacheValue *value)
|
||||
{
|
||||
CoglTexture *texture;
|
||||
GError *ignore_error = NULL;
|
||||
@ -228,7 +224,7 @@ cogl_pango_glyph_cache_add_to_global_atlas (CoglPangoGlyphCache *cache,
|
||||
{
|
||||
cogl_atlas_texture_add_reorganize_callback
|
||||
(cache->ctx,
|
||||
cogl_pango_glyph_cache_reorganize_cb, cache);
|
||||
clutter_pango_glyph_cache_reorganize_cb, cache);
|
||||
cache->using_global_atlas = TRUE;
|
||||
}
|
||||
|
||||
@ -236,11 +232,11 @@ cogl_pango_glyph_cache_add_to_global_atlas (CoglPangoGlyphCache *cache,
|
||||
}
|
||||
|
||||
static gboolean
|
||||
cogl_pango_glyph_cache_add_to_local_atlas (CoglPangoGlyphCache *cache,
|
||||
CoglContext *context,
|
||||
PangoFont *font,
|
||||
PangoGlyph glyph,
|
||||
CoglPangoGlyphCacheValue *value)
|
||||
clutter_pango_glyph_cache_add_to_local_atlas (ClutterPangoGlyphCache *cache,
|
||||
CoglContext *context,
|
||||
PangoFont *font,
|
||||
PangoGlyph glyph,
|
||||
PangoGlyphCacheValue *value)
|
||||
{
|
||||
CoglAtlas *atlas = NULL;
|
||||
GSList *l;
|
||||
@ -263,7 +259,7 @@ cogl_pango_glyph_cache_add_to_local_atlas (CoglPangoGlyphCache *cache,
|
||||
COGL_PIXEL_FORMAT_A_8,
|
||||
COGL_ATLAS_CLEAR_TEXTURE |
|
||||
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);
|
||||
/* If we still can't reserve space then something has gone
|
||||
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
|
||||
(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);
|
||||
}
|
||||
@ -285,15 +281,15 @@ cogl_pango_glyph_cache_add_to_local_atlas (CoglPangoGlyphCache *cache,
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
CoglPangoGlyphCacheValue *
|
||||
cogl_pango_glyph_cache_lookup (CoglPangoGlyphCache *cache,
|
||||
CoglContext *context,
|
||||
gboolean create,
|
||||
PangoFont *font,
|
||||
PangoGlyph glyph)
|
||||
PangoGlyphCacheValue *
|
||||
clutter_pango_glyph_cache_lookup (ClutterPangoGlyphCache *cache,
|
||||
CoglContext *context,
|
||||
gboolean create,
|
||||
PangoFont *font,
|
||||
PangoGlyph glyph)
|
||||
{
|
||||
CoglPangoGlyphCacheKey lookup_key;
|
||||
CoglPangoGlyphCacheValue *value;
|
||||
PangoGlyphCacheKey lookup_key;
|
||||
PangoGlyphCacheValue *value;
|
||||
|
||||
lookup_key.font = font;
|
||||
lookup_key.glyph = glyph;
|
||||
@ -302,10 +298,10 @@ cogl_pango_glyph_cache_lookup (CoglPangoGlyphCache *cache,
|
||||
|
||||
if (create && value == NULL)
|
||||
{
|
||||
CoglPangoGlyphCacheKey *key;
|
||||
PangoGlyphCacheKey *key;
|
||||
PangoRectangle ink_rect;
|
||||
|
||||
value = g_new0 (CoglPangoGlyphCacheValue, 1);
|
||||
value = g_new0 (PangoGlyphCacheValue, 1);
|
||||
value->texture = NULL;
|
||||
|
||||
pango_font_get_glyph_extents (font, glyph, &ink_rect, NULL);
|
||||
@ -323,18 +319,18 @@ cogl_pango_glyph_cache_lookup (CoglPangoGlyphCache *cache,
|
||||
else
|
||||
{
|
||||
/* Try adding the glyph to the global atlas... */
|
||||
if (!cogl_pango_glyph_cache_add_to_global_atlas (cache,
|
||||
font,
|
||||
glyph,
|
||||
value) &&
|
||||
if (!clutter_pango_glyph_cache_add_to_global_atlas (cache,
|
||||
font,
|
||||
glyph,
|
||||
value) &&
|
||||
/* If it fails try the local atlas */
|
||||
!cogl_pango_glyph_cache_add_to_local_atlas (cache,
|
||||
context,
|
||||
font,
|
||||
glyph,
|
||||
value))
|
||||
!clutter_pango_glyph_cache_add_to_local_atlas (cache,
|
||||
context,
|
||||
font,
|
||||
glyph,
|
||||
value))
|
||||
{
|
||||
cogl_pango_glyph_cache_value_free (value);
|
||||
clutter_pango_glyph_cache_value_free (value);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
@ -342,7 +338,7 @@ cogl_pango_glyph_cache_lookup (CoglPangoGlyphCache *cache,
|
||||
cache->has_dirty_glyphs = TRUE;
|
||||
}
|
||||
|
||||
key = g_new0 (CoglPangoGlyphCacheKey, 1);
|
||||
key = g_new0 (PangoGlyphCacheKey, 1);
|
||||
key->font = g_object_ref (font);
|
||||
key->glyph = glyph;
|
||||
|
||||
@ -371,12 +367,12 @@ font_has_color_glyphs (const PangoFont *font)
|
||||
}
|
||||
|
||||
static void
|
||||
_cogl_pango_glyph_cache_set_dirty_glyphs_cb (void *key_ptr,
|
||||
void *value_ptr,
|
||||
void *user_data)
|
||||
clutter_pango_glyph_cache_set_dirty_glyphs_cb (void *key_ptr,
|
||||
void *value_ptr,
|
||||
void *user_data)
|
||||
{
|
||||
CoglPangoGlyphCacheKey *key = key_ptr;
|
||||
CoglPangoGlyphCacheValue *value = value_ptr;
|
||||
PangoGlyphCacheKey *key = key_ptr;
|
||||
PangoGlyphCacheValue *value = value_ptr;
|
||||
cairo_surface_t *surface;
|
||||
cairo_t *cr;
|
||||
cairo_scaled_font_t *scaled_font;
|
||||
@ -455,7 +451,7 @@ _cogl_pango_glyph_cache_set_dirty_glyphs_cb (void *key_ptr,
|
||||
}
|
||||
|
||||
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
|
||||
out early */
|
||||
@ -463,16 +459,16 @@ _cogl_pango_glyph_cache_set_dirty_glyphs (CoglPangoGlyphCache *cache)
|
||||
return;
|
||||
|
||||
g_hash_table_foreach (cache->hash_table,
|
||||
_cogl_pango_glyph_cache_set_dirty_glyphs_cb,
|
||||
clutter_pango_glyph_cache_set_dirty_glyphs_cb,
|
||||
NULL);
|
||||
|
||||
cache->has_dirty_glyphs = FALSE;
|
||||
}
|
||||
|
||||
void
|
||||
_cogl_pango_glyph_cache_add_reorganize_callback (CoglPangoGlyphCache *cache,
|
||||
GHookFunc func,
|
||||
void *user_data)
|
||||
clutter_pango_glyph_cache_add_reorganize_callback (ClutterPangoGlyphCache *cache,
|
||||
GHookFunc func,
|
||||
void *user_data)
|
||||
{
|
||||
GHook *hook = g_hook_alloc (&cache->reorganize_callbacks);
|
||||
hook->func = func;
|
||||
@ -481,9 +477,9 @@ _cogl_pango_glyph_cache_add_reorganize_callback (CoglPangoGlyphCache *cache,
|
||||
}
|
||||
|
||||
void
|
||||
_cogl_pango_glyph_cache_remove_reorganize_callback (CoglPangoGlyphCache *cache,
|
||||
GHookFunc func,
|
||||
void *user_data)
|
||||
clutter_pango_glyph_cache_remove_reorganize_callback (ClutterPangoGlyphCache *cache,
|
||||
GHookFunc func,
|
||||
void *user_data)
|
||||
{
|
||||
GHook *hook = g_hook_find_func_data (&cache->reorganize_callbacks,
|
||||
FALSE,
|
@ -35,10 +35,9 @@
|
||||
|
||||
G_BEGIN_DECLS
|
||||
|
||||
typedef struct _CoglPangoGlyphCache CoglPangoGlyphCache;
|
||||
typedef struct _CoglPangoGlyphCacheValue CoglPangoGlyphCacheValue;
|
||||
typedef struct _ClutterPangoGlyphCache ClutterPangoGlyphCache;
|
||||
|
||||
struct _CoglPangoGlyphCacheValue
|
||||
typedef struct
|
||||
{
|
||||
CoglTexture *texture;
|
||||
|
||||
@ -60,32 +59,32 @@ struct _CoglPangoGlyphCacheValue
|
||||
guint dirty : 1;
|
||||
/* Set to TRUE if the glyph has colors (eg. emoji) */
|
||||
guint has_color : 1;
|
||||
};
|
||||
} PangoGlyphCacheValue;
|
||||
|
||||
CoglPangoGlyphCache *
|
||||
cogl_pango_glyph_cache_new (CoglContext *ctx);
|
||||
ClutterPangoGlyphCache *
|
||||
clutter_pango_glyph_cache_new (CoglContext *ctx);
|
||||
|
||||
void
|
||||
cogl_pango_glyph_cache_free (CoglPangoGlyphCache *cache);
|
||||
clutter_pango_glyph_cache_free (ClutterPangoGlyphCache *cache);
|
||||
|
||||
CoglPangoGlyphCacheValue *
|
||||
cogl_pango_glyph_cache_lookup (CoglPangoGlyphCache *cache,
|
||||
CoglContext *context,
|
||||
gboolean create,
|
||||
PangoFont *font,
|
||||
PangoGlyph glyph);
|
||||
PangoGlyphCacheValue *
|
||||
clutter_pango_glyph_cache_lookup (ClutterPangoGlyphCache *cache,
|
||||
CoglContext *context,
|
||||
gboolean create,
|
||||
PangoFont *font,
|
||||
PangoGlyph glyph);
|
||||
|
||||
void
|
||||
_cogl_pango_glyph_cache_add_reorganize_callback (CoglPangoGlyphCache *cache,
|
||||
GHookFunc func,
|
||||
void *user_data);
|
||||
clutter_pango_glyph_cache_add_reorganize_callback (ClutterPangoGlyphCache *cache,
|
||||
GHookFunc func,
|
||||
void *user_data);
|
||||
|
||||
void
|
||||
_cogl_pango_glyph_cache_remove_reorganize_callback (CoglPangoGlyphCache *cache,
|
||||
GHookFunc func,
|
||||
void *user_data);
|
||||
clutter_pango_glyph_cache_remove_reorganize_callback (ClutterPangoGlyphCache *cache,
|
||||
GHookFunc func,
|
||||
void *user_data);
|
||||
|
||||
void
|
||||
_cogl_pango_glyph_cache_set_dirty_glyphs (CoglPangoGlyphCache *cache);
|
||||
clutter_pango_glyph_cache_set_dirty_glyphs (ClutterPangoGlyphCache *cache);
|
||||
|
||||
G_END_DECLS
|
@ -35,13 +35,11 @@
|
||||
|
||||
#include <glib.h>
|
||||
|
||||
#include "clutter/pango/cogl-pango-pipeline-cache.h"
|
||||
|
||||
typedef struct _CoglPangoPipelineCacheEntry CoglPangoPipelineCacheEntry;
|
||||
#include "clutter/pango/clutter-pango-pipeline-cache.h"
|
||||
|
||||
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
|
||||
pipeline used to render colors */
|
||||
@ -49,19 +47,19 @@ struct _CoglPangoPipelineCacheEntry
|
||||
|
||||
/* This will only take a weak reference */
|
||||
CoglPipeline *pipeline;
|
||||
};
|
||||
} PangoPipelineCacheEntry;
|
||||
|
||||
static void
|
||||
_cogl_pango_pipeline_cache_key_destroy (void *data)
|
||||
clutter_pango_pipeline_cache_key_destroy (void *data)
|
||||
{
|
||||
if (data)
|
||||
g_object_unref (data);
|
||||
}
|
||||
|
||||
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);
|
||||
|
||||
@ -71,10 +69,10 @@ _cogl_pango_pipeline_cache_value_destroy (void *data)
|
||||
g_free (cache_entry);
|
||||
}
|
||||
|
||||
CoglPangoPipelineCache *
|
||||
_cogl_pango_pipeline_cache_new (CoglContext *ctx)
|
||||
ClutterPangoPipelineCache *
|
||||
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);
|
||||
|
||||
@ -84,8 +82,8 @@ _cogl_pango_pipeline_cache_new (CoglContext *ctx)
|
||||
cache->hash_table =
|
||||
g_hash_table_new_full (g_direct_hash,
|
||||
g_direct_equal,
|
||||
_cogl_pango_pipeline_cache_key_destroy,
|
||||
_cogl_pango_pipeline_cache_value_destroy);
|
||||
clutter_pango_pipeline_cache_key_destroy,
|
||||
clutter_pango_pipeline_cache_value_destroy);
|
||||
|
||||
cache->base_texture_rgba_pipeline = NULL;
|
||||
cache->base_texture_alpha_pipeline = NULL;
|
||||
@ -94,7 +92,7 @@ _cogl_pango_pipeline_cache_new (CoglContext *ctx)
|
||||
}
|
||||
|
||||
static CoglPipeline *
|
||||
get_base_texture_rgba_pipeline (CoglPangoPipelineCache *cache)
|
||||
get_base_texture_rgba_pipeline (ClutterPangoPipelineCache *cache)
|
||||
{
|
||||
if (cache->base_texture_rgba_pipeline == NULL)
|
||||
{
|
||||
@ -112,7 +110,7 @@ get_base_texture_rgba_pipeline (CoglPangoPipelineCache *cache)
|
||||
}
|
||||
|
||||
static CoglPipeline *
|
||||
get_base_texture_alpha_pipeline (CoglPangoPipelineCache *cache)
|
||||
get_base_texture_alpha_pipeline (ClutterPangoPipelineCache *cache)
|
||||
{
|
||||
if (cache->base_texture_alpha_pipeline == NULL)
|
||||
{
|
||||
@ -146,7 +144,7 @@ get_base_texture_alpha_pipeline (CoglPangoPipelineCache *cache)
|
||||
|
||||
typedef struct
|
||||
{
|
||||
CoglPangoPipelineCache *cache;
|
||||
ClutterPangoPipelineCache *cache;
|
||||
CoglTexture *texture;
|
||||
} PipelineDestroyNotifyData;
|
||||
|
||||
@ -160,12 +158,12 @@ pipeline_destroy_notify_cb (void *user_data)
|
||||
}
|
||||
|
||||
CoglPipeline *
|
||||
_cogl_pango_pipeline_cache_get (CoglPangoPipelineCache *cache,
|
||||
CoglTexture *texture)
|
||||
clutter_pango_pipeline_cache_get (ClutterPangoPipelineCache *cache,
|
||||
CoglTexture *texture)
|
||||
{
|
||||
CoglPangoPipelineCacheEntry *entry;
|
||||
PangoPipelineCacheEntry *entry;
|
||||
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 */
|
||||
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);
|
||||
|
||||
/* No existing pipeline was found so let's create another */
|
||||
entry = g_new0 (CoglPangoPipelineCacheEntry, 1);
|
||||
entry = g_new0 (PangoPipelineCacheEntry, 1);
|
||||
|
||||
if (texture)
|
||||
{
|
||||
@ -218,7 +216,7 @@ _cogl_pango_pipeline_cache_get (CoglPangoPipelineCache *cache,
|
||||
}
|
||||
|
||||
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_alpha_pipeline);
|
@ -39,7 +39,7 @@
|
||||
|
||||
G_BEGIN_DECLS
|
||||
|
||||
typedef struct _CoglPangoPipelineCache
|
||||
typedef struct
|
||||
{
|
||||
CoglContext *ctx;
|
||||
|
||||
@ -47,20 +47,20 @@ typedef struct _CoglPangoPipelineCache
|
||||
|
||||
CoglPipeline *base_texture_alpha_pipeline;
|
||||
CoglPipeline *base_texture_rgba_pipeline;
|
||||
} CoglPangoPipelineCache;
|
||||
} ClutterPangoPipelineCache;
|
||||
|
||||
|
||||
CoglPangoPipelineCache *
|
||||
_cogl_pango_pipeline_cache_new (CoglContext *ctx);
|
||||
ClutterPangoPipelineCache *
|
||||
clutter_pango_pipeline_cache_new (CoglContext *ctx);
|
||||
|
||||
/* 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
|
||||
to unref it */
|
||||
CoglPipeline *
|
||||
_cogl_pango_pipeline_cache_get (CoglPangoPipelineCache *cache,
|
||||
CoglTexture *texture);
|
||||
clutter_pango_pipeline_cache_get (ClutterPangoPipelineCache *cache,
|
||||
CoglTexture *texture);
|
||||
|
||||
void
|
||||
_cogl_pango_pipeline_cache_free (CoglPangoPipelineCache *cache);
|
||||
clutter_pango_pipeline_cache_free (ClutterPangoPipelineCache *cache);
|
||||
|
||||
G_END_DECLS
|
@ -43,7 +43,7 @@
|
||||
G_BEGIN_DECLS
|
||||
|
||||
PangoRenderer *
|
||||
_cogl_pango_renderer_new (CoglContext *context);
|
||||
clutter_pango_renderer_new (CoglContext *context);
|
||||
|
||||
/**
|
||||
* 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