/* 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; line = pango_layout_iter_get_line_readonly (iter); clip_region = cairo_region_create (); pango_layout_iter_get_line_extents (iter, NULL, &logical_rect); baseline = pango_layout_iter_get_baseline (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 */ 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); 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; cairo_region_union_rectangle (clip_region, &rect); } g_free (pixel_ranges); ++i; } return clip_region; }
static VALUE rg_get_x_ranges(VALUE self, VALUE start_index, VALUE end_index) { int* ranges; int i, n_ranges; VALUE ary; pango_layout_line_get_x_ranges(_SELF(self), NUM2INT(start_index), NUM2INT(end_index), &ranges, &n_ranges); ary = rb_ary_new(); for (i = 0; i < n_ranges; i++) { rb_ary_push(ary, INT2NUM(ranges[i])); } g_free(ranges); return ary; }
static GdkRegion * get_selected_clip (GtkTextRenderState *render_state, PangoLayout *layout, PangoLayoutLine *line, int x, int y, int height, int start_index, int end_index) { gint *ranges; gint n_ranges, i; GdkRegion *clip_region = gdk_region_new (); GdkRegion *tmp_region; pango_layout_line_get_x_ranges (line, start_index, end_index, &ranges, &n_ranges); for (i=0; i < n_ranges; i++) { GdkRectangle rect; rect.x = x + PANGO_PIXELS (ranges[2*i]); rect.y = y; rect.width = PANGO_PIXELS (ranges[2*i + 1]) - PANGO_PIXELS (ranges[2*i]); rect.height = height; gdk_region_union_with_rect (clip_region, &rect); } tmp_region = gdk_region_rectangle (&render_state->clip_rect); gdk_region_intersect (clip_region, tmp_region); gdk_region_destroy (tmp_region); g_free (ranges); return clip_region; }
static void cdtext(cdCtxCanvas *ctxcanvas, int x, int y, const char *s, int len) { PangoFontMetrics* metrics; int w, h, desc, dir = -1; int ox = x, oy = y; pango_layout_set_text(ctxcanvas->fontlayout, sStrConvertToUTF8(ctxcanvas, s, len), -1); pango_layout_get_pixel_size(ctxcanvas->fontlayout, &w, &h); metrics = pango_context_get_metrics(ctxcanvas->fontcontext, ctxcanvas->fontdesc, pango_context_get_language(ctxcanvas->fontcontext)); desc = (((pango_font_metrics_get_descent(metrics)) + PANGO_SCALE/2) / PANGO_SCALE); switch (ctxcanvas->canvas->text_alignment) { case CD_BASE_RIGHT: case CD_NORTH_EAST: case CD_EAST: case CD_SOUTH_EAST: x = x - w; break; case CD_BASE_CENTER: case CD_CENTER: case CD_NORTH: case CD_SOUTH: x = x - w/2; break; case CD_BASE_LEFT: case CD_NORTH_WEST: case CD_WEST: case CD_SOUTH_WEST: x = x; break; } if (ctxcanvas->canvas->invert_yaxis) dir = 1; switch (ctxcanvas->canvas->text_alignment) { case CD_BASE_LEFT: case CD_BASE_CENTER: case CD_BASE_RIGHT: y = y - (dir*h - desc); break; case CD_SOUTH_EAST: case CD_SOUTH_WEST: case CD_SOUTH: y = y - (dir*h); break; case CD_NORTH_EAST: case CD_NORTH: case CD_NORTH_WEST: y = y; break; case CD_CENTER: case CD_EAST: case CD_WEST: y = y - (dir*(h/2)); break; } if(!ctxcanvas->canvas->use_matrix) { ctxcanvas->fontmatrix.xx = 1; ctxcanvas->fontmatrix.xy = 0; ctxcanvas->fontmatrix.yx = 0; ctxcanvas->fontmatrix.yy = 1; ctxcanvas->fontmatrix.x0 = 0; ctxcanvas->fontmatrix.y0 = 0; } if (ctxcanvas->canvas->use_matrix || ctxcanvas->canvas->text_orientation) { PangoRectangle rect; double angle = ctxcanvas->canvas->text_orientation; if (ctxcanvas->canvas->text_orientation) pango_matrix_rotate(&ctxcanvas->fontmatrix, angle); pango_context_set_matrix (ctxcanvas->fontcontext, &ctxcanvas->fontmatrix); pango_layout_context_changed (ctxcanvas->fontlayout); pango_layout_get_pixel_extents(ctxcanvas->fontlayout, NULL, &rect); #if PANGO_VERSION_CHECK(1,16,0) pango_matrix_transform_pixel_rectangle(&ctxcanvas->fontmatrix, &rect); #endif if (ctxcanvas->canvas->text_orientation) { double cos_angle = cos(angle*CD_DEG2RAD); double sin_angle = sin(angle*CD_DEG2RAD); cdRotatePoint(ctxcanvas->canvas, x, y, ox, oy, &x, &y, sin_angle, cos_angle); } if (ctxcanvas->canvas->use_matrix) cdMatrixTransformPoint(ctxcanvas->xmatrix, x, y, &x, &y); /* Defines the new position (X,Y), considering the Pango rectangle transformed */ x += (int)rect.x; y += (int)rect.y; } cdgdkCheckSolidStyle(ctxcanvas, 1); if (ctxcanvas->canvas->new_region) { GdkRegion *rgn; gint *idx; gint range; pango_layout_line_get_x_ranges(pango_layout_get_line(ctxcanvas->fontlayout, 0), 0, len, &idx, &range); /* TODO: this is only the bounding box of the layout, not the text itself, must transform the text into a polygon. */ rgn = gdk_pango_layout_get_clip_region(ctxcanvas->fontlayout, x, y, idx, range); sCombineRegion(ctxcanvas, rgn); } else gdk_draw_layout(ctxcanvas->wnd, ctxcanvas->gc, x, y, ctxcanvas->fontlayout); pango_context_set_matrix(ctxcanvas->fontcontext, NULL); cdgdkCheckSolidStyle(ctxcanvas, 0); pango_font_metrics_unref(metrics); }