* Boston, MA 02111-1307, USA.
*/
-#include "gdkcolor.h"
-#include "gdkgc.h"
-#include "gdkpango.h"
-#include "gdkrgb.h"
-#include "gdkprivate.h"
-
-#define GDK_INFO_KEY "gdk-info"
-
-typedef struct _GdkPangoContextInfo GdkPangoContextInfo;
-
-struct _GdkPangoContextInfo
-{
- GdkColormap *colormap;
-};
-
-static PangoAttrType gdk_pango_attr_stipple_type;
-static PangoAttrType gdk_pango_attr_embossed_type;
-
-static void gdk_pango_get_item_properties (PangoItem *item,
- PangoUnderline *uline,
- gboolean *strikethrough,
- gint *rise,
- PangoColor *fg_color,
- gboolean *fg_set,
- PangoColor *bg_color,
- gboolean *bg_set,
- gboolean *embossed,
- GdkBitmap **stipple,
- gboolean *shape_set,
- PangoRectangle *ink_rect,
- PangoRectangle *logical_rect);
-
-static void
-gdk_pango_context_destroy (GdkPangoContextInfo *info)
-{
- if (info->colormap)
- gdk_colormap_unref (info->colormap);
- g_free (info);
-}
+#include "config.h"
-static GdkPangoContextInfo *
-gdk_pango_context_get_info (PangoContext *context, gboolean create)
-{
- GdkPangoContextInfo *info =
- g_object_get_qdata (G_OBJECT (context),
- g_quark_try_string (GDK_INFO_KEY));
- if (!info && create)
- {
- info = g_new (GdkPangoContextInfo, 1);
- info->colormap = NULL;
-
- g_object_set_qdata_full (G_OBJECT (context),
- g_quark_from_static_string (GDK_INFO_KEY),
- info, (GDestroyNotify)gdk_pango_context_destroy);
- }
-
- return info;
-}
-
-static GdkGC *
-gdk_pango_get_gc (GdkDrawable *drawable,
- PangoContext *context,
- PangoColor *fg_color,
- GdkBitmap *stipple,
- GdkGC *base_gc)
-{
- GdkGC *result;
- GdkPangoContextInfo *info;
-
- g_return_val_if_fail (context != NULL, NULL);
-
- info = gdk_pango_context_get_info (context, FALSE);
-
- if (info == NULL || info->colormap == NULL)
- {
- g_warning ("you must set the colormap on a PangoContext before using it to draw a layout");
- return NULL;
- }
-
- result = gdk_gc_new (drawable);
- gdk_gc_copy (result, base_gc);
-
- if (fg_color)
- {
- GdkColor color;
-
- color.red = fg_color->red;
- color.green = fg_color->green;
- color.blue = fg_color->blue;
+#include "gdkpango.h"
- gdk_rgb_find_color (info->colormap, &color);
- gdk_gc_set_foreground (result, &color);
- }
+#include "gdkscreen.h"
+#include "gdkintl.h"
- if (stipple)
- {
- gdk_gc_set_fill (result, GDK_STIPPLED);
- gdk_gc_set_stipple (result, stipple);
- }
-
- return result;
-}
+#include <math.h>
+#include <pango/pangocairo.h>
-static void
-gdk_pango_free_gc (PangoContext *context,
- GdkGC *gc)
-{
- gdk_gc_unref (gc);
-}
/**
- * gdk_pango_context_set_colormap:
- * @context: a #PangoContext
- * @colormap: a #GdkColormap
+ * SECTION:pango_interaction
+ * @Short_description: Using Pango in GDK
+ * @Title: Pango Interaction
*
- * Sets the colormap to be used for drawing with @context.
- * If you obtained your context from gtk_widget_get_pango_context() or
- * gtk_widget_create_pango_context(), the colormap will already be set
- * to the colormap for the widget, so you shouldn't need this
- * function.
- *
- **/
-void
-gdk_pango_context_set_colormap (PangoContext *context,
- GdkColormap *colormap)
-{
- GdkPangoContextInfo *info;
-
- g_return_if_fail (context != NULL);
-
- info = gdk_pango_context_get_info (context, TRUE);
- g_return_if_fail (info != NULL);
-
- if (info->colormap != colormap)
- {
- if (info->colormap)
- gdk_colormap_unref (info->colormap);
-
- info->colormap = colormap;
-
- if (info->colormap)
- gdk_colormap_ref (info->colormap);
- }
-}
-
-/**
- * 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
+ * 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.
*
- * Render a #PangoLayoutLine onto a #GdkDrawable, overriding the
- * layout's normal colors with @foreground and/or @background.
- * @foreground and @background need not be allocated.
- */
-void
-gdk_draw_layout_line_with_colors (GdkDrawable *drawable,
- GdkGC *gc,
- gint x,
- gint y,
- PangoLayoutLine *line,
- GdkColor *foreground,
- GdkColor *background)
-{
- GSList *tmp_list = line->runs;
- PangoRectangle overall_rect;
- PangoRectangle logical_rect;
- PangoRectangle ink_rect;
- PangoContext *context;
- gint x_off = 0;
- gint rise = 0;
- gboolean embossed;
- GdkBitmap *stipple;
-
- g_return_if_fail (GDK_IS_DRAWABLE (drawable));
- g_return_if_fail (GDK_IS_GC (gc));
- g_return_if_fail (line != NULL);
-
- context = pango_layout_get_context (line->layout);
-
- pango_layout_line_get_extents (line,NULL, &overall_rect);
-
- while (tmp_list)
- {
- PangoUnderline uline = PANGO_UNDERLINE_NONE;
- PangoLayoutRun *run = tmp_list->data;
- PangoColor fg_color, bg_color;
- gboolean strike, fg_set, bg_set, shape_set;
- GdkGC *fg_gc;
- gint risen_y;
-
- tmp_list = tmp_list->next;
-
- gdk_pango_get_item_properties (run->item, &uline,
- &strike,
- &rise,
- &fg_color, &fg_set,
- &bg_color, &bg_set,
- &embossed,
- &stipple,
- &shape_set,
- &ink_rect,
- &logical_rect);
-
- /* we subtract the rise because X coordinates are upside down */
- risen_y = y - rise / PANGO_SCALE;
-
- if (!shape_set)
- {
- if (uline == PANGO_UNDERLINE_NONE)
- pango_glyph_string_extents (run->glyphs, run->item->analysis.font,
- NULL, &logical_rect);
- else
- pango_glyph_string_extents (run->glyphs, run->item->analysis.font,
- &ink_rect, &logical_rect);
- }
-
- if (bg_set || background)
- {
- GdkGC *bg_gc;
- PangoColor tmp = bg_color;
-
- if (background)
- {
- tmp.red = background->red;
- tmp.blue = background->blue;
- tmp.green = background->green;
- }
-
- bg_gc = gdk_pango_get_gc (drawable, context, &tmp, stipple, gc);
-
- gdk_draw_rectangle (drawable, bg_gc, TRUE,
- x + (x_off + logical_rect.x) / PANGO_SCALE,
- risen_y + overall_rect.y / PANGO_SCALE,
- logical_rect.width / PANGO_SCALE,
- overall_rect.height / PANGO_SCALE);
-
- if (stipple)
- gdk_gc_set_fill (bg_gc, GDK_SOLID);
-
- gdk_pango_free_gc (context, bg_gc);
- }
-
- if (fg_set || stipple || foreground)
- {
- PangoColor tmp = fg_color;
-
- if (foreground)
- {
- tmp.red = foreground->red;
- tmp.blue = foreground->blue;
- tmp.green = foreground->green;
- }
-
- fg_gc = gdk_pango_get_gc (drawable, context, (fg_set || foreground) ? &tmp : NULL,
- stipple, gc);
- }
- else
- fg_gc = gc;
-
- if (!shape_set)
- {
- gint gx, gy;
-
- gx = x + x_off / PANGO_SCALE;
- gy = risen_y;
-
- if (embossed)
- {
- PangoColor color = { 65535, 65535, 65535 };
- GdkGC *white_gc = gdk_pango_get_gc (drawable, context, &color, stipple, fg_gc);
- gdk_draw_glyphs (drawable, white_gc, run->item->analysis.font,
- gx + 1,
- gy + 1,
- run->glyphs);
- gdk_pango_free_gc (context, white_gc);
- }
-
- gdk_draw_glyphs (drawable, fg_gc, run->item->analysis.font,
- gx, gy,
- run->glyphs);
- }
-
- switch (uline)
- {
- case PANGO_UNDERLINE_NONE:
- break;
- case PANGO_UNDERLINE_DOUBLE:
- gdk_draw_line (drawable, fg_gc,
- x + (x_off + ink_rect.x) / PANGO_SCALE - 1,
- risen_y + 3,
- x + (x_off + ink_rect.x + ink_rect.width) / PANGO_SCALE,
- risen_y + 3);
- /* Fall through */
- case PANGO_UNDERLINE_SINGLE:
- gdk_draw_line (drawable, fg_gc,
- x + (x_off + ink_rect.x) / PANGO_SCALE - 1,
- risen_y + 1,
- x + (x_off + ink_rect.x + ink_rect.width) / PANGO_SCALE,
- risen_y + 1);
- break;
- case PANGO_UNDERLINE_LOW:
- gdk_draw_line (drawable, fg_gc,
- x + (x_off + ink_rect.x) / PANGO_SCALE - 1,
- risen_y + (ink_rect.y + ink_rect.height) / PANGO_SCALE + 1,
- x + (x_off + ink_rect.x + ink_rect.width) / PANGO_SCALE,
- risen_y + (ink_rect.y + ink_rect.height) / PANGO_SCALE + 1);
- break;
- }
-
- if (strike)
- {
- int centerline = logical_rect.y + logical_rect.height / 2;
-
- gdk_draw_line (drawable, fg_gc,
- x + (x_off + logical_rect.x) / PANGO_SCALE - 1,
- risen_y + centerline / PANGO_SCALE,
- x + (x_off + logical_rect.x + logical_rect.width) / PANGO_SCALE + 1,
- risen_y + centerline / PANGO_SCALE);
- }
-
- if (fg_gc != gc)
- gdk_pango_free_gc (context, fg_gc);
-
- x_off += logical_rect.width;
- }
-}
-
-/**
- * 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
+ * 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 <link
+ * linkend="PANGO-SCALE-CAPS">PANGO_SCALE</link> or the PANGO_PIXELS() macro.)
*
- * Render a #PangoLayout onto a #GdkDrawable, overriding the
- * layout's normal colors with @foreground and/or @background.
- * @foreground and @background need not be allocated.
- */
-void
-gdk_draw_layout_with_colors (GdkDrawable *drawable,
- GdkGC *gc,
- int x,
- int y,
- PangoLayout *layout,
- GdkColor *foreground,
- GdkColor *background)
-{
- PangoLayoutIter *iter;
-
- g_return_if_fail (GDK_IS_DRAWABLE (drawable));
- g_return_if_fail (GDK_IS_GC (gc));
- g_return_if_fail (PANGO_IS_LAYOUT (layout));
-
- iter = pango_layout_get_iter (layout);
-
- do
- {
- PangoRectangle logical_rect;
- PangoLayoutLine *line;
- int 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);
-
- gdk_draw_layout_line_with_colors (drawable, gc,
- x + logical_rect.x / PANGO_SCALE,
- y + baseline / PANGO_SCALE,
- line,
- foreground,
- background);
- }
- while (pango_layout_iter_next_line (iter));
-
- pango_layout_iter_free (iter);
-}
-
-/**
- * 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
+ * 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().
+ * <example id="rotated-example">
+ * <title>Draw transformed text with Pango and cairo</title>
+ * <!-- Note that this example is basically the same as
+ * demos/gtk-demo/rotated_text.c -->
+ * <programlisting>
+ * #define RADIUS 100
+ * #define N_WORDS 10
+ * #define FONT "Sans Bold 18"
+ *
+ * PangoContext *context;
+ * PangoLayout *layout;
+ * PangoFontDescription *desc;
+ *
+ * double radius;
+ * int width, height;
+ * int i;
+ *
+ * /<!---->* 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 *<!---->/
+ *
+ * width = gdk_window_get_width (window);
+ * height = gdk_window_get_height (window);
+ * radius = MIN (width, height) / 2.;
+ *
+ * cairo_translate (cr,
+ * radius + (width - 2 * radius) / 2,
+ * radius + (height - 2 * radius) / 2);
+ * cairo_scale (cr, radius / RADIUS, radius / RADIUS);
+ *
+ * /<!---->* 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);
+ *
+ * /<!---->* 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;
+ *
+ * cairo_save (cr);
+ *
+ * /<!---->* Gradient from red at angle == 60 to blue at angle == 300 *<!---->/
+ * red = (1 + cos (angle - 60)) / 2;
+ * green = 0;
+ * blue = 1 - red;
+ *
+ * cairo_set_source_rgb (cr, red, green, blue);
+ * cairo_rotate (cr, angle);
+ *
+ * /<!---->* Inform Pango to re-layout the text with the new transformation matrix *<!---->/
+ * pango_cairo_update_layout (cr, layout);
+ *
+ * pango_layout_get_size (layout, &width, &height);
+ *
+ * cairo_move_to (cr, - width / 2 / PANGO_SCALE, - DEFAULT_TEXT_RADIUS);
+ * pango_cairo_show_layout (cr, layout);
+ *
+ * cairo_restore (cr);
+ * }
*
- * Render a #PangoLayoutLine onto an GDK drawable
+ * g_object_unref (layout);
+ * g_object_unref (context);
+ * </programlisting>
+ * </example>
+ * <figure>
+ * <title>Output of <xref linkend="rotated-example"/></title>
+ * <graphic fileref="rotated-text.png" format="PNG"/>
+ * </figure>
*/
-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
- *
- * Render a #PangoLayout onto a GDK drawable
+/* 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.
*/
-void
-gdk_draw_layout (GdkDrawable *drawable,
- GdkGC *gc,
- int x,
- int y,
- PangoLayout *layout)
+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)
{
- 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);
-}
+ PangoLayoutLine *line;
+ cairo_region_t *clip_region;
+ PangoRectangle logical_rect;
+ gint baseline;
+ gint i;
-static void
-gdk_pango_get_item_properties (PangoItem *item,
- PangoUnderline *uline,
- gboolean *strikethrough,
- gint *rise,
- PangoColor *fg_color,
- gboolean *fg_set,
- PangoColor *bg_color,
- gboolean *bg_set,
- gboolean *embossed,
- GdkBitmap **stipple,
- gboolean *shape_set,
- PangoRectangle *ink_rect,
- PangoRectangle *logical_rect)
-{
- GSList *tmp_list = item->analysis.extra_attrs;
+ line = pango_layout_iter_get_line_readonly (iter);
- if (strikethrough)
- *strikethrough = FALSE;
-
- if (fg_set)
- *fg_set = FALSE;
-
- if (bg_set)
- *bg_set = FALSE;
+ clip_region = cairo_region_create ();
- if (shape_set)
- *shape_set = FALSE;
-
- if (rise)
- *rise = 0;
+ pango_layout_iter_get_line_extents (iter, NULL, &logical_rect);
+ baseline = pango_layout_iter_get_baseline (iter);
- if (embossed)
- *embossed = FALSE;
+ i = 0;
+ while (i < n_ranges)
+ {
+ gint *pixel_ranges = NULL;
+ gint n_pixel_ranges = 0;
+ gint j;
- if (stipple)
- *stipple = NULL;
+ /* 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);
- while (tmp_list)
- {
- PangoAttribute *attr = tmp_list->data;
-
- switch (attr->klass->type)
- {
- case PANGO_ATTR_UNDERLINE:
- if (uline)
- *uline = ((PangoAttrInt *)attr)->value;
- break;
-
- case PANGO_ATTR_STRIKETHROUGH:
- if (strikethrough)
- *strikethrough = ((PangoAttrInt *)attr)->value;
- break;
-
- case PANGO_ATTR_FOREGROUND:
- if (fg_color)
- *fg_color = ((PangoAttrColor *)attr)->color;
- if (fg_set)
- *fg_set = TRUE;
-
- break;
-
- case PANGO_ATTR_BACKGROUND:
- if (bg_color)
- *bg_color = ((PangoAttrColor *)attr)->color;
- if (bg_set)
- *bg_set = TRUE;
-
- break;
-
- case PANGO_ATTR_SHAPE:
- if (shape_set)
- *shape_set = TRUE;
- if (logical_rect)
- *logical_rect = ((PangoAttrShape *)attr)->logical_rect;
- if (ink_rect)
- *ink_rect = ((PangoAttrShape *)attr)->ink_rect;
- break;
-
- case PANGO_ATTR_RISE:
- if (rise)
- *rise = ((PangoAttrInt *)attr)->value;
- break;
+ for (j = 0; j < n_pixel_ranges; j++)
+ {
+ GdkRectangle rect;
+ int x_off, y_off;
- default:
- /* stipple_type and embossed_type aren't necessarily
- * initialized, but they are 0, which is an
- * invalid type so won't occur.
- */
- if (stipple && attr->klass->type == gdk_pango_attr_stipple_type)
- {
- *stipple = ((GdkPangoAttrStipple*)attr)->stipple;
- }
- else if (embossed && attr->klass->type == gdk_pango_attr_embossed_type)
- {
- *embossed = ((GdkPangoAttrEmbossed*)attr)->embossed;
- }
- break;
- }
- tmp_list = tmp_list->next;
- }
-}
+ x_off = PANGO_PIXELS (pixel_ranges[2*j] - logical_rect.x);
+ y_off = PANGO_PIXELS (baseline - logical_rect.y);
+ 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;
-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 (G_OBJECT (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
- *
- * Creates a new attribute containing a stipple bitmap to be used when
- * rendering the text.
- *
- * 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;
-}
-
-static PangoAttribute *
-gdk_pango_attr_embossed_copy (const PangoAttribute *attr)
-{
- const GdkPangoAttrEmbossed *e = (const GdkPangoAttrEmbossed*) attr;
-
- return gdk_pango_attr_embossed_new (e->embossed);
-}
-
-static void
-gdk_pango_attr_embossed_destroy (PangoAttribute *attr)
-{
- g_free (attr);
-}
-
-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;
-
- return e1->embossed == e2->embossed;
-}
-
-/**
- * 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
- **/
-
-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
- };
-
- 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:
* @line: a #PangoLayoutLine
* @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;
-
- /* 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);
- }
+ clip_region = layout_iter_get_line_clip_region(iter, x_origin, y_origin, index_ranges, n_ranges);
- g_free (pixel_ranges);
- ++i;
- }
+ pango_layout_iter_free (iter);
return clip_region;
}
* @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));
return clip_region;
}
+
+/**
+ * gdk_pango_context_get:
+ *
+ * Creates a #PangoContext for the default GDK 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 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: 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: 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_cairo_font_map_create_context (PANGO_CAIRO_FONT_MAP (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;
+}