X-Git-Url: http://pileus.org/git/?a=blobdiff_plain;f=gdk%2Fgdkpango.c;h=ca5745beb27f012eb1d47b549f3e367d59df4c12;hb=e1efe3269cb7f5f09f9cb0dfc725fcbb50512f2c;hp=374d90d6d1d9ff5273d02811935be06adf17b102;hpb=3d737ee8bae66d3395ff7975fafea99f87f1ed40;p=~andy%2Fgtk diff --git a/gdk/gdkpango.c b/gdk/gdkpango.c index 374d90d6d..ca5745beb 100644 --- a/gdk/gdkpango.c +++ b/gdk/gdkpango.c @@ -12,1336 +12,234 @@ * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the - * Free Software Foundation, Inc., 59 Temple Place - Suite 330, - * Boston, MA 02111-1307, USA. + * License along with this library. If not, see . */ -#include -#include -#include "gdkalias.h" -#include "gdkcolor.h" -#include "gdkgc.h" -#include "gdkpango.h" -#include "gdkrgb.h" -#include "gdkprivate.h" -#include "gdkscreen.h" - -/* This is for P_() ... a bit non-kosher, but works fine */ -#include "gtk/gtkintl.h" - -#define GDK_INFO_KEY "gdk-info" - -/* We have various arrays indexed by render part; if PangoRenderPart - * is extended, we want to make sure not to overwrite the end of - * those arrays. - */ -#define MAX_RENDER_PART PANGO_RENDER_PART_STRIKETHROUGH - -struct _GdkPangoRendererPrivate -{ - GdkScreen *screen; - - /* GdkPangoRenderer specific state */ - PangoColor override_color[MAX_RENDER_PART + 1]; - gboolean override_color_set[MAX_RENDER_PART + 1]; - - GdkBitmap *stipple[MAX_RENDER_PART + 1]; - gboolean embossed; - - /* When switching between the normal and shadow copies when - * drawing shadows we can get unexpected recursion into the - * drawing functions; the 'in_emboss' flag guards against that. - */ - gboolean in_emboss; - - /* Current target */ - GdkDrawable *drawable; - GdkGC *base_gc; - - /* Cached GC, derived from base_gc */ - GdkGC *gc; - PangoColor gc_color; - gboolean gc_color_set; - GdkBitmap *gc_stipple; - - /* we accumulate trapezoids for the same PangoRenderPart */ - GArray *trapezoids; - PangoRenderPart trapezoid_part; -}; - -static PangoAttrType gdk_pango_attr_stipple_type; -static PangoAttrType gdk_pango_attr_embossed_type; - -static void flush_trapezoids (GdkPangoRenderer *gdk_renderer); - -enum { - PROP_0, - PROP_SCREEN -}; - -G_DEFINE_TYPE (GdkPangoRenderer, gdk_pango_renderer, PANGO_TYPE_RENDERER) - -static void -gdk_pango_renderer_finalize (GObject *object) -{ - GdkPangoRenderer *gdk_renderer = GDK_PANGO_RENDERER (object); - GdkPangoRendererPrivate *priv = gdk_renderer->priv; - int i; - - if (priv->gc) - g_object_unref (priv->gc); - if (priv->gc_stipple) - g_object_unref (priv->gc_stipple); - if (priv->base_gc) - g_object_unref (priv->base_gc); - if (priv->drawable) - g_object_unref (priv->drawable); - - for (i = 0; i <= MAX_RENDER_PART; i++) - if (priv->stipple[i]) - g_object_unref (priv->stipple[i]); - - g_array_free (priv->trapezoids, TRUE); - - G_OBJECT_CLASS (gdk_pango_renderer_parent_class)->finalize (object); -} - -static GObject* -gdk_pango_renderer_constructor (GType type, - guint n_construct_properties, - GObjectConstructParam *construct_params) -{ - GObject *object; - GdkPangoRenderer *gdk_renderer; +#include "config.h" - object = (* G_OBJECT_CLASS (gdk_pango_renderer_parent_class)->constructor) (type, - n_construct_properties, - construct_params); - - gdk_renderer = GDK_PANGO_RENDERER (object); - - if (!gdk_renderer->priv->screen) - { - g_warning ("Screen must be specified at construct time for GdkPangoRenderer"); - gdk_renderer->priv->screen = gdk_screen_get_default (); - } - - return object; -} - -/* Adjusts matrix and color for the renderer to draw the secondar - * "shadow" copy for embossed text */ -static void -emboss_renderer (PangoRenderer *renderer, - PangoRenderPart part, - PangoMatrix **save_matrix, - PangoColor **save_color) -{ - GdkPangoRendererPrivate *priv = GDK_PANGO_RENDERER(renderer)->priv; - static const PangoColor white = { 0xffff, 0xffff, 0xffff }; - PangoMatrix tmp_matrix = PANGO_MATRIX_INIT; - - priv->in_emboss = TRUE; - - *save_color = pango_renderer_get_color (renderer, part); - if (*save_color) - *save_color = pango_color_copy (*save_color); - - *save_matrix = renderer->matrix; - if (*save_matrix) - { - *save_matrix = pango_matrix_copy (*save_matrix); - tmp_matrix = **save_matrix; - } - - /* The gymnastics here to adjust the matrix are because we want - * to offset by +1,+1 in device-space, not in user-space, - * so we can't just draw the layout at x + 1, y + 1 - */ - tmp_matrix.x0 += 1; - tmp_matrix.y0 += 1; - - pango_renderer_set_matrix (renderer, &tmp_matrix); - pango_renderer_set_color (renderer, part, &white); -} - -/* Restores from emboss_renderer() */ -static void -unemboss_renderer (PangoRenderer *renderer, - PangoRenderPart part, - PangoMatrix **save_matrix, - PangoColor **save_color) -{ - GdkPangoRendererPrivate *priv = GDK_PANGO_RENDERER(renderer)->priv; - pango_renderer_set_matrix (renderer, *save_matrix); - pango_renderer_set_color (renderer, part, *save_color); - - if (*save_matrix) - pango_matrix_free (*save_matrix); - if (*save_color) - pango_color_free (*save_color); - - priv->in_emboss = FALSE; -} - -/* Gets the GC for drawing @part. This make involve copying the base GC - * for the renderer, in which case we keep a one-GC cache. */ -static GdkGC * -get_gc (GdkPangoRenderer *gdk_renderer, - PangoRenderPart part) -{ - PangoRenderer *renderer = PANGO_RENDERER (gdk_renderer); - PangoColor *color; - GdkBitmap *stipple; - GdkPangoRendererPrivate *priv = gdk_renderer->priv; - - color = pango_renderer_get_color (renderer, part); - - if (part <= MAX_RENDER_PART) - stipple = priv->stipple[part]; - else - stipple = NULL; - - if (!color && !stipple) /* nothing override, use base_gc */ - return priv->base_gc; - else - { - gboolean new_stipple = FALSE; - gboolean new_color = FALSE; - - if (stipple != priv->gc_stipple) - new_stipple = TRUE; - - if ((priv->gc_color_set && !color) || - (!priv->gc_color_set && color) || - priv->gc_color.red != color->red || - priv->gc_color.green != color->green || - priv->gc_color.blue != color->blue) - new_color = TRUE; - - if (!priv->gc) - { - priv->gc = gdk_gc_new (priv->drawable); - gdk_gc_copy (priv->gc, priv->base_gc); - } - else if (new_color && priv->gc_color_set && !color) - { - /* We have to recopy the original GC onto the cached GC - * to get the default color */ - new_stipple = TRUE; - gdk_gc_copy (priv->gc, priv->base_gc); - } - else if (new_stipple && priv->gc_stipple && !stipple) - { - /* Similarly, we need to make a new copy to restore to the - * default stipple state (the caller may have set a stipple - * on the GC, and even if not, gdk_gc_set_stipple (gc, NULL) - * doesn't work currently to restore to the default X stipple) */ - new_color = TRUE; - gdk_gc_copy (priv->gc, priv->base_gc); - } - - if (new_color) - { - if (color) - { - GdkColor gdk_color; - - gdk_color.red = color->red; - gdk_color.green = color->green; - gdk_color.blue = color->blue; - - gdk_gc_set_rgb_fg_color (priv->gc, &gdk_color); - - priv->gc_color = *color; - priv->gc_color_set = TRUE; - } - else - priv->gc_color_set = FALSE; - } - - if (new_stipple) - { - if (priv->gc_stipple) - g_object_unref (priv->gc_stipple); - - if (stipple) - { - gdk_gc_set_stipple (priv->gc, stipple); - gdk_gc_set_fill (priv->gc, GDK_STIPPLED); - priv->gc_stipple = g_object_ref (stipple); - } - else - priv->gc_stipple = NULL; - } - - return priv->gc; - } -} - -static void -gdk_pango_renderer_draw_glyphs (PangoRenderer *renderer, - PangoFont *font, - PangoGlyphString *glyphs, - int x, - int y) -{ - GdkPangoRenderer *gdk_renderer = GDK_PANGO_RENDERER (renderer); - GdkPangoRendererPrivate *priv = gdk_renderer->priv; - - flush_trapezoids (gdk_renderer); - - if (!priv->in_emboss && priv->embossed) - { - PangoMatrix *save_matrix; - PangoColor *save_color; - - emboss_renderer (renderer, PANGO_RENDER_PART_FOREGROUND, &save_matrix, &save_color); - gdk_draw_glyphs_transformed (priv->drawable, - get_gc (gdk_renderer, PANGO_RENDER_PART_FOREGROUND), - renderer->matrix, font, x, y, glyphs); - unemboss_renderer (renderer, PANGO_RENDER_PART_FOREGROUND, &save_matrix, &save_color); - } - - gdk_draw_glyphs_transformed (priv->drawable, - get_gc (gdk_renderer, PANGO_RENDER_PART_FOREGROUND), - renderer->matrix, font, x, y, glyphs); -} - -/* Outputs any pending trapezoids, we do this when the part or - * part color changes, when we are about to draw text, etc. */ -static void -flush_trapezoids (GdkPangoRenderer *gdk_renderer) -{ - GdkPangoRendererPrivate *priv = gdk_renderer->priv; - - if (!priv->trapezoids || priv->trapezoids->len == 0) - return; - - gdk_draw_trapezoids (priv->drawable, - get_gc (gdk_renderer, priv->trapezoid_part), - (GdkTrapezoid *)priv->trapezoids->data, - priv->trapezoids->len); - - g_array_set_size (priv->trapezoids, 0); -} - -/* Draws a single trapezoid ... we don't draw it immediately, but rather - * cache it to join together with other trapezoids that form part of the - * same logical shape */ -static void -gdk_pango_renderer_draw_trapezoid (PangoRenderer *renderer, - PangoRenderPart part, - double y1, - double x11, - double x21, - double y2, - double x12, - double x22) -{ - GdkPangoRenderer *gdk_renderer = GDK_PANGO_RENDERER (renderer); - GdkTrapezoid trap; - - if (!gdk_renderer->priv->trapezoids) - gdk_renderer->priv->trapezoids = g_array_new (FALSE, FALSE, - sizeof (GdkTrapezoid)); - - if (gdk_renderer->priv->trapezoids->len > 0 && - gdk_renderer->priv->trapezoid_part != part) - flush_trapezoids (gdk_renderer); - - gdk_renderer->priv->trapezoid_part = part; - - trap.y1 = y1; - trap.x11 = x11; - trap.x21 = x21; - trap.y2 = y2; - trap.x12 = x12; - trap.x22 = x22; - - g_array_append_val (gdk_renderer->priv->trapezoids, trap); -} - -/* We can't handle embossing at the level of trapezoids, because when an - * underline is split into multiple trapezoids, the normal and shadow - * trapezoids will be drawn mixed together. Instead, we have to emboss - * and entire rectangle or error underline - */ - -static void -gdk_pango_renderer_draw_rectangle (PangoRenderer *renderer, - PangoRenderPart part, - int x, - int y, - int width, - int height) -{ - GdkPangoRenderer *gdk_renderer = GDK_PANGO_RENDERER (renderer); - GdkPangoRendererPrivate *priv = gdk_renderer->priv; - - if (!priv->in_emboss && priv->embossed && part != PANGO_RENDER_PART_BACKGROUND) - { - PangoMatrix *save_matrix; - PangoColor *save_color; - - emboss_renderer (renderer, part, &save_matrix, &save_color); - PANGO_RENDERER_CLASS (gdk_pango_renderer_parent_class)->draw_rectangle (renderer, part, - x, y, width, height); - unemboss_renderer (renderer, part, &save_matrix, &save_color); - } - - PANGO_RENDERER_CLASS (gdk_pango_renderer_parent_class)->draw_rectangle (renderer, part, - x, y, width, height); -} - -static void -gdk_pango_renderer_draw_error_underline (PangoRenderer *renderer, - int x, - int y, - int width, - int height) -{ - GdkPangoRenderer *gdk_renderer = GDK_PANGO_RENDERER (renderer); - GdkPangoRendererPrivate *priv = gdk_renderer->priv; - - if (!priv->in_emboss && priv->embossed) - { - PangoMatrix *save_matrix; - PangoColor *save_color; - - emboss_renderer (renderer, PANGO_RENDER_PART_UNDERLINE, &save_matrix, &save_color); - PANGO_RENDERER_CLASS (gdk_pango_renderer_parent_class)->draw_error_underline (renderer, - x, y, width, height); - unemboss_renderer (renderer, PANGO_RENDER_PART_UNDERLINE, &save_matrix, &save_color); - } - - PANGO_RENDERER_CLASS (gdk_pango_renderer_parent_class)->draw_error_underline (renderer, - x, y, width, height); -} - -static void -gdk_pango_renderer_part_changed (PangoRenderer *renderer, - PangoRenderPart part) -{ - GdkPangoRenderer *gdk_renderer = GDK_PANGO_RENDERER (renderer); - - if (part == gdk_renderer->priv->trapezoid_part) - flush_trapezoids (gdk_renderer); -} - -static void -gdk_pango_renderer_begin (PangoRenderer *renderer) -{ - GdkPangoRenderer *gdk_renderer = GDK_PANGO_RENDERER (renderer); - - if (!gdk_renderer->priv->drawable || !gdk_renderer->priv->base_gc) - { - g_warning ("gdk_pango_renderer_set_drawable() and gdk_pango_renderer_set_drawable()" - "must be used to set the target drawable and GC before using the renderer\n"); - } -} - -static void -gdk_pango_renderer_end (PangoRenderer *renderer) -{ - GdkPangoRenderer *gdk_renderer = GDK_PANGO_RENDERER (renderer); - - flush_trapezoids (gdk_renderer); -} - -static void -gdk_pango_renderer_prepare_run (PangoRenderer *renderer, - PangoLayoutRun *run) -{ - GdkPangoRenderer *gdk_renderer = GDK_PANGO_RENDERER (renderer); - gboolean embossed = FALSE; - GdkBitmap *stipple = NULL; - GSList *l; - int i; - - embossed = FALSE; - stipple = NULL; - - for (l = run->item->analysis.extra_attrs; l; l = l->next) - { - PangoAttribute *attr = l->data; - - /* stipple_type and embossed_type aren't necessarily - * initialized, but they are 0, which is an - * invalid type so won't occur. - */ - if (attr->klass->type == gdk_pango_attr_stipple_type) - { - stipple = ((GdkPangoAttrStipple*)attr)->stipple; - } - else if (attr->klass->type == gdk_pango_attr_embossed_type) - { - embossed = ((GdkPangoAttrEmbossed*)attr)->embossed; - } - } - - gdk_pango_renderer_set_stipple (gdk_renderer, PANGO_RENDER_PART_FOREGROUND, stipple); - gdk_pango_renderer_set_stipple (gdk_renderer, PANGO_RENDER_PART_BACKGROUND, stipple); - gdk_pango_renderer_set_stipple (gdk_renderer, PANGO_RENDER_PART_UNDERLINE, stipple); - gdk_pango_renderer_set_stipple (gdk_renderer, PANGO_RENDER_PART_STRIKETHROUGH, stipple); - - if (embossed != gdk_renderer->priv->embossed) - { - gdk_renderer->priv->embossed = embossed; - pango_renderer_part_changed (renderer, PANGO_RENDER_PART_FOREGROUND); - } - - PANGO_RENDERER_CLASS (gdk_pango_renderer_parent_class)->prepare_run (renderer, run); - - for (i = 0; i <= MAX_RENDER_PART; i++) - { - if (gdk_renderer->priv->override_color_set[i]) - pango_renderer_set_color (renderer, i, &gdk_renderer->priv->override_color[i]); - } -} - -static void -gdk_pango_renderer_set_property (GObject *object, - guint prop_id, - const GValue *value, - GParamSpec *pspec) -{ - GdkPangoRenderer *gdk_renderer = GDK_PANGO_RENDERER (object); - - switch (prop_id) - { - case PROP_SCREEN: - gdk_renderer->priv->screen = g_value_get_object (value); - break; - default: - G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); - break; - } -} - -static void -gdk_pango_renderer_get_property (GObject *object, - guint prop_id, - GValue *value, - GParamSpec *pspec) -{ - GdkPangoRenderer *gdk_renderer = GDK_PANGO_RENDERER (object); - - switch (prop_id) - { - case PROP_SCREEN: - g_value_set_object (value, gdk_renderer->priv->screen); - break; - default: - G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); - break; - } -} - -static void -gdk_pango_renderer_init (GdkPangoRenderer *renderer) -{ - renderer->priv = G_TYPE_INSTANCE_GET_PRIVATE (renderer, - GDK_TYPE_PANGO_RENDERER, - GdkPangoRendererPrivate); -} - -static void -gdk_pango_renderer_class_init (GdkPangoRendererClass *klass) -{ - GObjectClass *object_class = G_OBJECT_CLASS (klass); - - PangoRendererClass *renderer_class = PANGO_RENDERER_CLASS (klass); - - renderer_class->draw_glyphs = gdk_pango_renderer_draw_glyphs; - renderer_class->draw_trapezoid = gdk_pango_renderer_draw_trapezoid; - renderer_class->draw_rectangle = gdk_pango_renderer_draw_rectangle; - renderer_class->draw_error_underline = gdk_pango_renderer_draw_error_underline; - renderer_class->part_changed = gdk_pango_renderer_part_changed; - renderer_class->begin = gdk_pango_renderer_begin; - renderer_class->end = gdk_pango_renderer_end; - renderer_class->prepare_run = gdk_pango_renderer_prepare_run; - - object_class->finalize = gdk_pango_renderer_finalize; - object_class->constructor = gdk_pango_renderer_constructor; - object_class->set_property = gdk_pango_renderer_set_property; - object_class->get_property = gdk_pango_renderer_get_property; - - g_object_class_install_property (object_class, - PROP_SCREEN, - g_param_spec_object ("screen", - P_("Screen"), - P_("the GdkScreen for the renderer"), - GDK_TYPE_SCREEN, - G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY)); +#include "gdkpango.h" - g_type_class_add_private (object_class, sizeof (GdkPangoRendererPrivate)); -} +#include "gdkscreen.h" +#include "gdkintl.h" -/** - * gdk_pango_renderer_new: - * @screen: a #GdkScreen - * - * Creates a new #PangoRenderer for @screen. Normally you can use the - * results of gdk_pango_renderer_get_default() rather than creating a new - * renderer. - * - * Return value: a newly created #PangoRenderer. Free with g_object_unref(). - * - * Since: 2.6 - **/ -PangoRenderer * -gdk_pango_renderer_new (GdkScreen *screen) -{ - g_return_val_if_fail (screen != NULL, NULL); - - return g_object_new (GDK_TYPE_PANGO_RENDERER, - "screen", screen, - NULL); -} +#include +#include -static void -on_renderer_display_closed (GdkDisplay *display, - GdkPangoRenderer *renderer) -{ - g_signal_handlers_disconnect_by_func (renderer->priv->screen, - (gpointer)on_renderer_display_closed, - renderer); - g_object_set_data (G_OBJECT (renderer->priv->screen), "gdk-pango-renderer", NULL); -} /** - * gdk_pango_renderer_get_default: - * @screen: a #GdkScreen - * - * Gets the default #PangoRenderer for a screen. This default renderer - * is shared by all users of the display, so properties such as the color - * or transformation matrix set for the renderer may be overwritten - * by functions such as gdk_draw_layout(). + * SECTION:pango_interaction + * @Short_description: Using Pango in GDK + * @Title: Pango Interaction * - * Before using the renderer, you need to call gdk_pango_renderer_set_drawable() - * and gdk_pango_renderer_set_drawable() to set the drawable and graphics context - * to use for drawing. - * - * Return value: the default #PangoRenderer for @screen. The - * renderer is owned by GTK+ and will be kept around until the - * screen is closed. + * Pango is the text layout system used by GDK and GTK+. The functions + * and types in this section are used to obtain clip regions for + * #PangoLayouts, and to get #PangoContexts that can be used with + * GDK. * - * Since: 2.6 - **/ -PangoRenderer * -gdk_pango_renderer_get_default (GdkScreen *screen) -{ - PangoRenderer *renderer; - - g_return_val_if_fail (GDK_IS_SCREEN (screen), NULL); - - renderer = g_object_get_data (G_OBJECT (screen), "gdk-pango-renderer"); - if (!renderer) - { - renderer = gdk_pango_renderer_new (screen); - g_object_set_data_full (G_OBJECT (screen), "gdk-pango-renderer", renderer, - (GDestroyNotify)g_object_unref); - - g_signal_connect (gdk_screen_get_display (screen), "closed", - G_CALLBACK (on_renderer_display_closed), renderer); - } - - return renderer; -} - -/** - * gdk_pango_renderer_set_drawable: - * @gdk_renderer: a #GdkPangoRenderer - * @drawable: the new target drawable, or %NULL - * - * Sets the drawable the renderer draws to. + * Creating a #PangoLayout object is the first step in rendering text, + * and requires getting a handle to a #PangoContext. For GTK+ programs, + * you'll usually want to use gtk_widget_get_pango_context(), or + * gtk_widget_create_pango_layout(), rather than using the lowlevel + * gdk_pango_context_get_for_screen(). Once you have a #PangoLayout, you + * can set the text and attributes of it with Pango functions like + * pango_layout_set_text() and get its size with pango_layout_get_size(). + * (Note that Pango uses a fixed point system internally, so converting + * between Pango units and pixels using PANGO_SCALE or the PANGO_PIXELS() macro.) * - * Since: 2.6 - **/ -void -gdk_pango_renderer_set_drawable (GdkPangoRenderer *gdk_renderer, - GdkDrawable *drawable) -{ - GdkPangoRendererPrivate *priv; - - g_return_if_fail (GDK_IS_PANGO_RENDERER (gdk_renderer)); - g_return_if_fail (drawable == NULL || GDK_IS_DRAWABLE (drawable)); - - priv = gdk_renderer->priv; - - flush_trapezoids (gdk_renderer); - - if (priv->drawable != drawable) - { - if (priv->drawable) - g_object_unref (priv->drawable); - priv->drawable = drawable; - if (priv->drawable) - g_object_ref (priv->drawable); - } -} - -/** - * gdk_pango_renderer_set_gc: - * @gdk_renderer: a #GdkPangoRenderer - * @gc: the new GC to use for drawing, or %NULL - * - * Sets the GC the renderer draws with. Note that the GC must not be - * modified until it is unset by calling the function again with - * %NULL for the @gc parameter, since GDK may make internal copies - * of the GC which won't be updated to follow changes to the - * original GC. + * Rendering a Pango layout is done most simply with pango_cairo_show_layout(); + * you can also draw pieces of the layout with pango_cairo_show_layout_line(). + * + * Draw transformed text with Pango and cairo + * + * + * #define RADIUS 100 + * #define N_WORDS 10 + * #define FONT "Sans Bold 18" * - * Since: 2.6 - **/ -void -gdk_pango_renderer_set_gc (GdkPangoRenderer *gdk_renderer, - GdkGC *gc) -{ - GdkPangoRendererPrivate *priv; - - g_return_if_fail (GDK_IS_PANGO_RENDERER (gdk_renderer)); - g_return_if_fail (gc == NULL || GDK_IS_GC (gc)); - - priv = gdk_renderer->priv; - - flush_trapezoids (gdk_renderer); - - if (priv->base_gc != gc) - { - if (priv->base_gc) - g_object_unref (priv->base_gc); - priv->base_gc = gc; - if (priv->base_gc) - g_object_ref (priv->base_gc); - - if (priv->gc) - { - g_object_unref (priv->gc); - priv->gc = NULL; - } - - priv->gc_color_set = FALSE; - - if (priv->gc_stipple) - { - g_object_unref (priv->gc_stipple); - priv->gc_stipple = NULL; - } - } -} - - -/** - * gdk_pango_renderer_set_stipple: - * @gdk_renderer: a #GdkPangoRenderer - * @part: the part to render with the stipple - * @stipple: the new stipple value. - * - * Sets the stipple for one render part (foreground, background, underline, - * etc.) Note that this is overwritten when iterating through the individual - * styled runs of a #PangoLayout or #PangoLayoutLine. This function is thus - * only useful when you call low level functions like pango_renderer_draw_glyphs() - * directly, or in the 'prepare_run' virtual function of a subclass of - * #GdkPangoRenderer. + * PangoContext *context; + * PangoLayout *layout; + * PangoFontDescription *desc; * - * Since: 2.6 - **/ -void -gdk_pango_renderer_set_stipple (GdkPangoRenderer *gdk_renderer, - PangoRenderPart part, - GdkBitmap *stipple) -{ - g_return_if_fail (GDK_IS_PANGO_RENDERER (gdk_renderer)); - - if (part > MAX_RENDER_PART) /* Silently ignore unknown parts */ - return; - - if (stipple != gdk_renderer->priv->stipple[part]) - { - if (gdk_renderer->priv->stipple[part]) - g_object_unref (gdk_renderer->priv->stipple[part]); - - gdk_renderer->priv->stipple[part] = stipple; - - if (gdk_renderer->priv->stipple[part]) - g_object_ref (gdk_renderer->priv->stipple[part]); - - pango_renderer_part_changed (PANGO_RENDERER (gdk_renderer), part); - } -} - -/** - * gdk_pango_renderer_set_override_color: - * @gdk_renderer: a #GdkPangoRenderer - * @part: the part to render to set the color of - * @color: the color to use, or %NULL to unset a previously - * set override color. - * - * Sets the color for a particular render part (foreground, - * background, underline, etc.), overriding any attributes on the layouts - * renderered with this renderer. - * - * Since: 2.6 - **/ -void -gdk_pango_renderer_set_override_color (GdkPangoRenderer *gdk_renderer, - PangoRenderPart part, - const GdkColor *color) -{ - GdkPangoRendererPrivate *priv; - - g_return_if_fail (GDK_IS_PANGO_RENDERER (gdk_renderer)); - - priv = gdk_renderer->priv; - - if (part > MAX_RENDER_PART) /* Silently ignore unknown parts */ - return; - - if (color) - { - priv->override_color[part].red = color->red; - priv->override_color[part].green = color->green; - priv->override_color[part].blue = color->blue; - priv->override_color_set[part] = TRUE; - } - else - priv->override_color_set[part] = FALSE; -} - -/** - * gdk_pango_context_set_colormap: - * @context: a #PangoContext - * @colormap: a #GdkColormap + * double radius; + * int width, height; + * int i; * - * This function used to set the colormap to be used for drawing with - * @context. The colormap is now always derived from the graphics - * context used for drawing, so calling this function is no longer - * necessary. - **/ -void -gdk_pango_context_set_colormap (PangoContext *context, - GdkColormap *colormap) -{ - g_return_if_fail (PANGO_IS_CONTEXT (context)); - g_return_if_fail (colormap == NULL || GDK_IS_COLORMAP (colormap)); -} - -/* Gets a renderer to draw with, setting the properties of the - * renderer and activating it. Note that since we activate the - * renderer here, the implicit setting of the matrix that - * pango_renderer_draw_layout_[line] normally do when they - * activate the renderer is suppressed. */ -static PangoRenderer * -get_renderer (GdkDrawable *drawable, - GdkGC *gc, - const GdkColor *foreground, - const GdkColor *background) -{ - GdkScreen *screen = gdk_drawable_get_screen (drawable); - PangoRenderer *renderer = gdk_pango_renderer_get_default (screen); - GdkPangoRenderer *gdk_renderer = GDK_PANGO_RENDERER (renderer); - - gdk_pango_renderer_set_drawable (gdk_renderer, drawable); - gdk_pango_renderer_set_gc (gdk_renderer, gc); - - gdk_pango_renderer_set_override_color (gdk_renderer, - PANGO_RENDER_PART_FOREGROUND, - foreground); - gdk_pango_renderer_set_override_color (gdk_renderer, - PANGO_RENDER_PART_UNDERLINE, - foreground); - gdk_pango_renderer_set_override_color (gdk_renderer, - PANGO_RENDER_PART_STRIKETHROUGH, - foreground); - - gdk_pango_renderer_set_override_color (gdk_renderer, - PANGO_RENDER_PART_BACKGROUND, - background); - - pango_renderer_activate (renderer); - - return renderer; -} - -/* Cleans up the renderer obtained with get_renderer() */ -static void -release_renderer (PangoRenderer *renderer) -{ - GdkPangoRenderer *gdk_renderer = GDK_PANGO_RENDERER (renderer); - - pango_renderer_deactivate (renderer); - - gdk_pango_renderer_set_override_color (gdk_renderer, - PANGO_RENDER_PART_FOREGROUND, - NULL); - gdk_pango_renderer_set_override_color (gdk_renderer, - PANGO_RENDER_PART_UNDERLINE, - NULL); - gdk_pango_renderer_set_override_color (gdk_renderer, - PANGO_RENDER_PART_STRIKETHROUGH, - NULL); - gdk_pango_renderer_set_override_color (gdk_renderer, - PANGO_RENDER_PART_BACKGROUND, - NULL); - - gdk_pango_renderer_set_drawable (gdk_renderer, NULL); - gdk_pango_renderer_set_gc (gdk_renderer, NULL); -} - -/** - * gdk_draw_layout_line_with_colors: - * @drawable: the drawable on which to draw the line - * @gc: base graphics to use - * @x: the x position of start of string (in pixels) - * @y: the y position of baseline (in pixels) - * @line: a #PangoLayoutLine - * @foreground: foreground override color, or %NULL for none - * @background: background override color, or %NULL for none + * /* Set up a transformation matrix so that the user space coordinates for + * * where we are drawing are [-RADIUS, RADIUS], [-RADIUS, RADIUS] + * * We first center, then change the scale */ * - * Render a #PangoLayoutLine onto a #GdkDrawable, overriding the - * layout's normal colors with @foreground and/or @background. - * @foreground and @background need not be allocated. + * width = gdk_window_get_width (window); + * height = gdk_window_get_height (window); + * radius = MIN (width, height) / 2.; * - * If the layout's #PangoContext has a transformation matrix set, then - * @x and @y specify the position of the left edge of the baseline - * (left is in before-tranform user coordinates) in after-transform - * device coordinates. - */ -void -gdk_draw_layout_line_with_colors (GdkDrawable *drawable, - GdkGC *gc, - gint x, - gint y, - PangoLayoutLine *line, - const GdkColor *foreground, - const GdkColor *background) -{ - PangoRenderer *renderer; - const PangoMatrix *matrix; - - g_return_if_fail (GDK_IS_DRAWABLE (drawable)); - g_return_if_fail (GDK_IS_GC (gc)); - g_return_if_fail (line != NULL); - - renderer = get_renderer (drawable, gc, foreground, background); - - /* When we have a matrix, we do positioning by adjusting the matrix, and - * clamp just pass x=0, y=0 to the lower levels. We don't want to introduce - * a matrix when the caller didn't provide one, however, since that adds - * lots of floating point arithmetic for each glyph. - */ - matrix = pango_context_get_matrix (pango_layout_get_context (line->layout)); - if (matrix) - { - PangoMatrix tmp_matrix; - - tmp_matrix = *matrix; - tmp_matrix.x0 = x; - tmp_matrix.y0 = y; - pango_renderer_set_matrix (renderer, &tmp_matrix); - - x = 0; - y = 0; - } - else - pango_renderer_set_matrix (renderer, NULL); - - pango_renderer_draw_layout_line (renderer, line, x * PANGO_SCALE, y * PANGO_SCALE); - - release_renderer (renderer); -} - -/* Gets the bounds of a layout in device coordinates. Note cut-and-paste - * between here and gtklabel.c */ -static void -get_rotated_layout_bounds (PangoLayout *layout, - GdkRectangle *rect) -{ - PangoContext *context = pango_layout_get_context (layout); - const PangoMatrix *matrix = pango_context_get_matrix (context); - gdouble x_min = 0, x_max = 0, y_min = 0, y_max = 0; /* quiet gcc */ - PangoRectangle logical_rect; - gint i, j; - - pango_layout_get_extents (layout, NULL, &logical_rect); - - for (i = 0; i < 2; i++) - { - gdouble x = (i == 0) ? logical_rect.x : logical_rect.x + logical_rect.width; - for (j = 0; j < 2; j++) - { - gdouble y = (j == 0) ? logical_rect.y : logical_rect.y + logical_rect.height; - - gdouble xt = (x * matrix->xx + y * matrix->xy) / PANGO_SCALE + matrix->x0; - gdouble yt = (x * matrix->yx + y * matrix->yy) / PANGO_SCALE + matrix->y0; - - if (i == 0 && j == 0) - { - x_min = x_max = xt; - y_min = y_max = yt; - } - else - { - if (xt < x_min) - x_min = xt; - if (yt < y_min) - y_min = yt; - if (xt > x_max) - x_max = xt; - if (yt > y_max) - y_max = yt; - } - } - } - - rect->x = floor (x_min); - rect->width = ceil (x_max) - rect->x; - rect->y = floor (y_min); - rect->height = floor (y_max) - rect->y; -} - -/** - * gdk_draw_layout_with_colors: - * @drawable: the drawable on which to draw string - * @gc: base graphics context to use - * @x: the X position of the left of the layout (in pixels) - * @y: the Y position of the top of the layout (in pixels) - * @layout: a #PangoLayout - * @foreground: foreground override color, or %NULL for none - * @background: background override color, or %NULL for none + * cairo_translate (cr, + * radius + (width - 2 * radius) / 2, + * radius + (height - 2 * radius) / 2); + * cairo_scale (cr, radius / RADIUS, radius / RADIUS); * - * Render a #PangoLayout onto a #GdkDrawable, overriding the - * layout's normal colors with @foreground and/or @background. - * @foreground and @background need not be allocated. + * /* Create a PangoLayout, set the font and text */ + * context = gdk_pango_context_get_for_screen (screen); + * layout = pango_layout_new (context); + * pango_layout_set_text (layout, "Text", -1); + * desc = pango_font_description_from_string (FONT); + * pango_layout_set_font_description (layout, desc); + * pango_font_description_free (desc); * - * If the layout's #PangoContext has a transformation matrix set, then - * @x and @y specify the position of the top left corner of the - * bounding box (in device space) of the transformed layout. + * /* Draw the layout N_WORDS times in a circle */ + * for (i = 0; i < N_WORDS; i++) + * { + * double red, green, blue; + * double angle = 2 * G_PI * i / n_words; * - * If you're using GTK+, the ususal way to obtain a #PangoLayout - * is gtk_widget_create_pango_layout(). - */ -void -gdk_draw_layout_with_colors (GdkDrawable *drawable, - GdkGC *gc, - int x, - int y, - PangoLayout *layout, - const GdkColor *foreground, - const GdkColor *background) -{ - PangoRenderer *renderer; - const PangoMatrix *matrix; - - g_return_if_fail (GDK_IS_DRAWABLE (drawable)); - g_return_if_fail (GDK_IS_GC (gc)); - g_return_if_fail (PANGO_IS_LAYOUT (layout)); - - renderer = get_renderer (drawable, gc, foreground, background); - - /* When we have a matrix, we do positioning by adjusting the matrix, and - * clamp just pass x=0, y=0 to the lower levels. We don't want to introduce - * a matrix when the caller didn't provide one, however, since that adds - * lots of floating point arithmetic for each glyph. - */ - matrix = pango_context_get_matrix (pango_layout_get_context (layout)); - if (matrix) - { - PangoMatrix tmp_matrix; - GdkRectangle rect; - - get_rotated_layout_bounds (layout, &rect); - - tmp_matrix = *matrix; - tmp_matrix.x0 += x - rect.x; - tmp_matrix.y0 += y - rect.y; - pango_renderer_set_matrix (renderer, &tmp_matrix); - - x = 0; - y = 0; - } - else - pango_renderer_set_matrix (renderer, NULL); - - pango_renderer_draw_layout (renderer, layout, x * PANGO_SCALE, y * PANGO_SCALE); - - release_renderer (renderer); -} - -/** - * gdk_draw_layout_line: - * @drawable: the drawable on which to draw the line - * @gc: base graphics to use - * @x: the x position of start of string (in pixels) - * @y: the y position of baseline (in pixels) - * @line: a #PangoLayoutLine + * cairo_save (cr); * - * Render a #PangoLayoutLine onto an GDK drawable + * /* Gradient from red at angle == 60 to blue at angle == 300 */ + * red = (1 + cos (angle - 60)) / 2; + * green = 0; + * blue = 1 - red; * - * If the layout's #PangoContext has a transformation matrix set, then - * @x and @y specify the position of the left edge of the baseline - * (left is in before-tranform user coordinates) in after-transform - * device coordinates. - */ -void -gdk_draw_layout_line (GdkDrawable *drawable, - GdkGC *gc, - gint x, - gint y, - PangoLayoutLine *line) -{ - g_return_if_fail (GDK_IS_DRAWABLE (drawable)); - g_return_if_fail (GDK_IS_GC (gc)); - g_return_if_fail (line != NULL); - - gdk_draw_layout_line_with_colors (drawable, gc, x, y, line, NULL, NULL); -} - -/** - * gdk_draw_layout: - * @drawable: the drawable on which to draw string - * @gc: base graphics context to use - * @x: the X position of the left of the layout (in pixels) - * @y: the Y position of the top of the layout (in pixels) - * @layout: a #PangoLayout + * cairo_set_source_rgb (cr, red, green, blue); + * cairo_rotate (cr, angle); * - * Render a #PangoLayout onto a GDK drawable + * /* Inform Pango to re-layout the text with the new transformation matrix */ + * pango_cairo_update_layout (cr, layout); * - * If the layout's #PangoContext has a transformation matrix set, then - * @x and @y specify the position of the top left corner of the - * bounding box (in device space) of the transformed layout. + * pango_layout_get_size (layout, &width, &height); * - * If you're using GTK+, the usual way to obtain a #PangoLayout - * is gtk_widget_create_pango_layout(). - */ -void -gdk_draw_layout (GdkDrawable *drawable, - GdkGC *gc, - int x, - int y, - PangoLayout *layout) -{ - g_return_if_fail (GDK_IS_DRAWABLE (drawable)); - g_return_if_fail (GDK_IS_GC (gc)); - g_return_if_fail (PANGO_IS_LAYOUT (layout)); - - gdk_draw_layout_with_colors (drawable, gc, x, y, layout, NULL, NULL); -} - -static PangoAttribute * -gdk_pango_attr_stipple_copy (const PangoAttribute *attr) -{ - const GdkPangoAttrStipple *src = (const GdkPangoAttrStipple*) attr; - - return gdk_pango_attr_stipple_new (src->stipple); -} - -static void -gdk_pango_attr_stipple_destroy (PangoAttribute *attr) -{ - GdkPangoAttrStipple *st = (GdkPangoAttrStipple*) attr; - - if (st->stipple) - g_object_unref (st->stipple); - - g_free (attr); -} - -static gboolean -gdk_pango_attr_stipple_compare (const PangoAttribute *attr1, - const PangoAttribute *attr2) -{ - const GdkPangoAttrStipple *a = (const GdkPangoAttrStipple*) attr1; - const GdkPangoAttrStipple *b = (const GdkPangoAttrStipple*) attr2; - - return a->stipple == b->stipple; -} - -/** - * gdk_pango_attr_stipple_new: - * @stipple: a bitmap to be set as stipple + * cairo_move_to (cr, - width / 2 / PANGO_SCALE, - DEFAULT_TEXT_RADIUS); + * pango_cairo_show_layout (cr, layout); * - * Creates a new attribute containing a stipple bitmap to be used when - * rendering the text. + * cairo_restore (cr); + * } * - * Return value: new #PangoAttribute - **/ - -PangoAttribute * -gdk_pango_attr_stipple_new (GdkBitmap *stipple) -{ - GdkPangoAttrStipple *result; - - static PangoAttrClass klass = { - 0, - gdk_pango_attr_stipple_copy, - gdk_pango_attr_stipple_destroy, - gdk_pango_attr_stipple_compare - }; - - if (!klass.type) - klass.type = gdk_pango_attr_stipple_type = - pango_attr_type_register ("GdkPangoAttrStipple"); - - result = g_new (GdkPangoAttrStipple, 1); - result->attr.klass = &klass; - - if (stipple) - g_object_ref (stipple); - - result->stipple = stipple; - - return (PangoAttribute *)result; -} + * g_object_unref (layout); + * g_object_unref (context); + * + * + *
+ * Output of <xref linkend="rotated-example"/> + * + *
+ */ -static PangoAttribute * -gdk_pango_attr_embossed_copy (const PangoAttribute *attr) -{ - const GdkPangoAttrEmbossed *e = (const GdkPangoAttrEmbossed*) attr; +/* Get a clip region to draw only part of a layout. index_ranges + * contains alternating range starts/stops. The region is the + * region which contains the given ranges, i.e. if you draw with the + * region as clip, only the given ranges are drawn. + */ +static cairo_region_t* +layout_iter_get_line_clip_region (PangoLayoutIter *iter, + gint x_origin, + gint y_origin, + const gint *index_ranges, + gint n_ranges) +{ + PangoLayoutLine *line; + cairo_region_t *clip_region; + PangoRectangle logical_rect; + gint baseline; + gint i; - return gdk_pango_attr_embossed_new (e->embossed); -} + line = pango_layout_iter_get_line_readonly (iter); -static void -gdk_pango_attr_embossed_destroy (PangoAttribute *attr) -{ - g_free (attr); -} + clip_region = cairo_region_create (); -static gboolean -gdk_pango_attr_embossed_compare (const PangoAttribute *attr1, - const PangoAttribute *attr2) -{ - const GdkPangoAttrEmbossed *e1 = (const GdkPangoAttrEmbossed*) attr1; - const GdkPangoAttrEmbossed *e2 = (const GdkPangoAttrEmbossed*) attr2; + pango_layout_iter_get_line_extents (iter, NULL, &logical_rect); + baseline = pango_layout_iter_get_baseline (iter); - return e1->embossed == e2->embossed; -} + i = 0; + while (i < n_ranges) + { + gint *pixel_ranges = NULL; + gint n_pixel_ranges = 0; + gint j; -/** - * gdk_pango_attr_embossed_new: - * @embossed: a bitmap to be set as embossed - * - * Creates a new attribute containing a embossed bitmap to be used when - * rendering the text. - * - * Return value: new #PangoAttribute - **/ + /* Note that get_x_ranges returns layout coordinates + */ + if (index_ranges[i*2+1] >= line->start_index && + index_ranges[i*2] < line->start_index + line->length) + pango_layout_line_get_x_ranges (line, + index_ranges[i*2], + index_ranges[i*2+1], + &pixel_ranges, &n_pixel_ranges); + + for (j = 0; j < n_pixel_ranges; j++) + { + GdkRectangle rect; + int x_off, y_off; + + x_off = PANGO_PIXELS (pixel_ranges[2*j] - logical_rect.x); + y_off = PANGO_PIXELS (baseline - logical_rect.y); -PangoAttribute * -gdk_pango_attr_embossed_new (gboolean embossed) -{ - GdkPangoAttrEmbossed *result; - - static PangoAttrClass klass = { - 0, - gdk_pango_attr_embossed_copy, - gdk_pango_attr_embossed_destroy, - gdk_pango_attr_embossed_compare - }; + rect.x = x_origin + x_off; + rect.y = y_origin - y_off; + rect.width = PANGO_PIXELS (pixel_ranges[2*j + 1] - logical_rect.x) - x_off; + rect.height = PANGO_PIXELS (baseline - logical_rect.y + logical_rect.height) - y_off; - if (!klass.type) - klass.type = gdk_pango_attr_embossed_type = - pango_attr_type_register ("GdkPangoAttrEmbossed"); + cairo_region_union_rectangle (clip_region, &rect); + } - result = g_new (GdkPangoAttrEmbossed, 1); - result->attr.klass = &klass; - result->embossed = embossed; - - return (PangoAttribute *)result; + g_free (pixel_ranges); + ++i; + } + return clip_region; } -/* Get a clip region to draw only part of a layout. index_ranges - * contains alternating range starts/stops. The region is the - * region which contains the given ranges, i.e. if you draw with the - * region as clip, only the given ranges are drawn. - */ - /** - * gdk_pango_layout_line_get_clip_region: + * gdk_pango_layout_line_get_clip_region: (skip) * @line: a #PangoLayoutLine * @x_origin: X pixel where you intend to draw the layout line with this clip * @y_origin: baseline pixel where you intend to draw the layout line with this clip - * @index_ranges: array of byte indexes into the layout, where even members of array are start indexes and odd elements are end indexes + * @index_ranges: (array): array of byte indexes into the layout, + * where even members of array are start indexes and odd elements + * are end indexes * @n_ranges: number of ranges in @index_ranges, i.e. half the size of @index_ranges * * Obtains a clip region which contains the areas where the given - * ranges of text would be drawn. @x_origin and @y_origin are the same - * position you would pass to gdk_draw_layout_line(). @index_ranges + * ranges of text would be drawn. @x_origin and @y_origin are the top left + * position of the layout. @index_ranges * should contain ranges of bytes in the layout's text. The clip * region will include space to the left or right of the line (to the * layout bounding box) if you have indexes above or below the indexes * contained inside the line. This is to draw the selection all the way * to the side of the layout. However, the clip region is in line coordinates, * not layout coordinates. + * + * Note that the regions returned correspond to logical extents of the text + * ranges, not ink extents. So the drawn line may in fact touch areas out of + * the clip region. The clip region is mainly useful for highlightling parts + * of text, such as when text is selected. * * Return value: a clip region containing the given ranges **/ -GdkRegion* +cairo_region_t* gdk_pango_layout_line_get_clip_region (PangoLayoutLine *line, gint x_origin, gint y_origin, - gint *index_ranges, + const gint *index_ranges, gint n_ranges) { - GdkRegion *clip_region; - gint i; - PangoRectangle logical_rect; + cairo_region_t *clip_region; PangoLayoutIter *iter; - gint baseline; g_return_val_if_fail (line != NULL, NULL); g_return_val_if_fail (index_ranges != NULL, NULL); - clip_region = gdk_region_new (); - iter = pango_layout_get_iter (line->layout); - while (pango_layout_iter_get_line (iter) != line) + while (pango_layout_iter_get_line_readonly (iter) != line) pango_layout_iter_next_line (iter); - pango_layout_iter_get_line_extents (iter, NULL, &logical_rect); - baseline = pango_layout_iter_get_baseline (iter); - - pango_layout_iter_free (iter); - - i = 0; - while (i < n_ranges) - { - gint *pixel_ranges = NULL; - gint n_pixel_ranges = 0; - gint j; + clip_region = layout_iter_get_line_clip_region(iter, x_origin, y_origin, index_ranges, n_ranges); - /* Note that get_x_ranges returns layout coordinates - */ - pango_layout_line_get_x_ranges (line, - index_ranges[i*2], - index_ranges[i*2+1], - &pixel_ranges, &n_pixel_ranges); - - for (j=0; j < n_pixel_ranges; j++) - { - GdkRectangle rect; - - rect.x = x_origin + pixel_ranges[2*j] / PANGO_SCALE - logical_rect.x / PANGO_SCALE; - rect.y = y_origin - (baseline / PANGO_SCALE - logical_rect.y / PANGO_SCALE); - rect.width = (pixel_ranges[2*j + 1] - pixel_ranges[2*j]) / PANGO_SCALE; - rect.height = logical_rect.height / PANGO_SCALE; - - gdk_region_union_with_rect (clip_region, &rect); - } - - g_free (pixel_ranges); - ++i; - } + pango_layout_iter_free (iter); return clip_region; } /** - * gdk_pango_layout_get_clip_region: + * gdk_pango_layout_get_clip_region: (skip) * @layout: a #PangoLayout * @x_origin: X pixel where you intend to draw the layout with this clip * @y_origin: Y pixel where you intend to draw the layout with this clip @@ -1349,49 +247,51 @@ gdk_pango_layout_line_get_clip_region (PangoLayoutLine *line, * @n_ranges: number of ranges in @index_ranges, i.e. half the size of @index_ranges * * Obtains a clip region which contains the areas where the given ranges - * of text would be drawn. @x_origin and @y_origin are the same position - * you would pass to gdk_draw_layout_line(). @index_ranges should contain + * of text would be drawn. @x_origin and @y_origin are the top left point + * to center the layout. @index_ranges should contain * ranges of bytes in the layout's text. * + * Note that the regions returned correspond to logical extents of the text + * ranges, not ink extents. So the drawn layout may in fact touch areas out of + * the clip region. The clip region is mainly useful for highlightling parts + * of text, such as when text is selected. + * * Return value: a clip region containing the given ranges **/ -GdkRegion* +cairo_region_t* gdk_pango_layout_get_clip_region (PangoLayout *layout, gint x_origin, gint y_origin, - gint *index_ranges, + const gint *index_ranges, gint n_ranges) { PangoLayoutIter *iter; - GdkRegion *clip_region; + cairo_region_t *clip_region; g_return_val_if_fail (PANGO_IS_LAYOUT (layout), NULL); g_return_val_if_fail (index_ranges != NULL, NULL); - clip_region = gdk_region_new (); + clip_region = cairo_region_create (); iter = pango_layout_get_iter (layout); do { PangoRectangle logical_rect; - PangoLayoutLine *line; - GdkRegion *line_region; + cairo_region_t *line_region; gint baseline; - line = pango_layout_iter_get_line (iter); - pango_layout_iter_get_line_extents (iter, NULL, &logical_rect); baseline = pango_layout_iter_get_baseline (iter); - line_region = gdk_pango_layout_line_get_clip_region (line, - x_origin + logical_rect.x / PANGO_SCALE, - y_origin + baseline / PANGO_SCALE, - index_ranges, - n_ranges); + line_region = layout_iter_get_line_clip_region(iter, + x_origin + PANGO_PIXELS (logical_rect.x), + y_origin + PANGO_PIXELS (baseline), + index_ranges, + n_ranges); - gdk_region_union (clip_region, line_region); - gdk_region_destroy (line_region); + cairo_region_union (clip_region, line_region); + cairo_region_destroy (line_region); } while (pango_layout_iter_next_line (iter)); @@ -1411,10 +311,60 @@ gdk_pango_layout_get_clip_region (PangoLayout *layout, * instead of this function, to get the appropriate context for * the widget you intend to render text onto. * - * Return value: a new #PangoContext for the default display + * The newly created context will have the default font options (see + * #cairo_font_options_t) for the default screen; if these options + * change it will not be updated. Using gtk_widget_get_pango_context() + * is more convenient if you want to keep a context around and track + * changes to the screen's font rendering settings. + * + * Return value: (transfer full): a new #PangoContext for the default display **/ PangoContext * gdk_pango_context_get (void) { return gdk_pango_context_get_for_screen (gdk_screen_get_default ()); } + +/** + * gdk_pango_context_get_for_screen: + * @screen: the #GdkScreen for which the context is to be created. + * + * Creates a #PangoContext for @screen. + * + * The context must be freed when you're finished with it. + * + * When using GTK+, normally you should use gtk_widget_get_pango_context() + * instead of this function, to get the appropriate context for + * the widget you intend to render text onto. + * + * The newly created context will have the default font options + * (see #cairo_font_options_t) for the screen; if these options + * change it will not be updated. Using gtk_widget_get_pango_context() + * is more convenient if you want to keep a context around and track + * changes to the screen's font rendering settings. + * + * Return value: (transfer full): a new #PangoContext for @screen + * + * Since: 2.2 + **/ +PangoContext * +gdk_pango_context_get_for_screen (GdkScreen *screen) +{ + PangoFontMap *fontmap; + PangoContext *context; + const cairo_font_options_t *options; + double dpi; + + g_return_val_if_fail (GDK_IS_SCREEN (screen), NULL); + + fontmap = pango_cairo_font_map_get_default (); + context = pango_font_map_create_context (fontmap); + + options = gdk_screen_get_font_options (screen); + pango_cairo_context_set_font_options (context, options); + + dpi = gdk_screen_get_resolution (screen); + pango_cairo_context_set_resolution (context, dpi); + + return context; +}