1/* GDK - The GIMP Drawing Kit
2 * Copyright (C) 2000 Red Hat, Inc.
3 *
4 * This library is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU Lesser General Public
6 * License as published by the Free Software Foundation; either
7 * version 2 of the License, or (at your option) any later version.
8 *
9 * This library is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 * Lesser General Public License for more details.
13 *
14 * You should have received a copy of the GNU Lesser General Public
15 * License along with this library. If not, see <http://www.gnu.org/licenses/>.
16 */
17
18#include "config.h"
19
20#include "gdkpango.h"
21
22#include "gdkintl.h"
23
24#include <math.h>
25#include <pango/pangocairo.h>
26
27
28/* Get a clip region to draw only part of a layout. index_ranges
29 * contains alternating range starts/stops. The region is the
30 * region which contains the given ranges, i.e. if you draw with the
31 * region as clip, only the given ranges are drawn.
32 */
33static cairo_region_t*
34layout_iter_get_line_clip_region (PangoLayoutIter *iter,
35 int x_origin,
36 int y_origin,
37 const int *index_ranges,
38 int n_ranges)
39{
40 PangoLayoutLine *line;
41 cairo_region_t *clip_region;
42 PangoRectangle logical_rect;
43 int baseline;
44 int i;
45
46 line = pango_layout_iter_get_line_readonly (iter);
47
48 clip_region = cairo_region_create ();
49
50 pango_layout_iter_get_line_extents (iter, NULL, logical_rect: &logical_rect);
51 baseline = pango_layout_iter_get_baseline (iter);
52
53 i = 0;
54 while (i < n_ranges)
55 {
56 int *pixel_ranges = NULL;
57 int n_pixel_ranges = 0;
58 int j;
59
60 /* Note that get_x_ranges returns layout coordinates
61 */
62 if (index_ranges[i*2+1] >= pango_layout_line_get_start_index (line) &&
63 index_ranges[i*2] < pango_layout_line_get_start_index (line) + pango_layout_line_get_length (line))
64 pango_layout_line_get_x_ranges (line,
65 start_index: index_ranges[i*2],
66 end_index: index_ranges[i*2+1],
67 ranges: &pixel_ranges, n_ranges: &n_pixel_ranges);
68
69 for (j = 0; j < n_pixel_ranges; j++)
70 {
71 GdkRectangle rect;
72 int x_off, y_off;
73
74 x_off = PANGO_PIXELS (pixel_ranges[2*j] - logical_rect.x);
75 y_off = PANGO_PIXELS (baseline - logical_rect.y);
76
77 rect.x = x_origin + x_off;
78 rect.y = y_origin - y_off;
79 rect.width = PANGO_PIXELS (pixel_ranges[2*j + 1] - logical_rect.x) - x_off;
80 rect.height = PANGO_PIXELS (baseline - logical_rect.y + logical_rect.height) - y_off;
81
82 cairo_region_union_rectangle (dst: clip_region, rectangle: &rect);
83 }
84
85 g_free (mem: pixel_ranges);
86 ++i;
87 }
88 return clip_region;
89}
90
91/**
92 * gdk_pango_layout_line_get_clip_region: (skip)
93 * @line: a `PangoLayoutLine`
94 * @x_origin: X pixel where you intend to draw the layout line with this clip
95 * @y_origin: baseline pixel where you intend to draw the layout line with this clip
96 * @index_ranges: (array): array of byte indexes into the layout, where even
97 * members of array are start indexes and odd elements are end indexes
98 * @n_ranges: number of ranges in @index_ranges, i.e. half the size of @index_ranges
99 *
100 * Obtains a clip region which contains the areas where the given
101 * ranges of text would be drawn.
102 *
103 * @x_origin and @y_origin are the top left position of the layout.
104 * @index_ranges should contain ranges of bytes in the layout’s text.
105 * The clip region will include space to the left or right of the line
106 * (to the layout bounding box) if you have indexes above or below the
107 * indexes contained inside the line. This is to draw the selection all
108 * the way to the side of the layout. However, the clip region is in line
109 * coordinates, not layout coordinates.
110 *
111 * Note that the regions returned correspond to logical extents of the text
112 * ranges, not ink extents. So the drawn line may in fact touch areas out of
113 * the clip region. The clip region is mainly useful for highlightling parts
114 * of text, such as when text is selected.
115 *
116 * Returns: a clip region containing the given ranges
117 */
118cairo_region_t*
119gdk_pango_layout_line_get_clip_region (PangoLayoutLine *line,
120 int x_origin,
121 int y_origin,
122 const int *index_ranges,
123 int n_ranges)
124{
125 cairo_region_t *clip_region;
126 PangoLayoutIter *iter;
127
128 g_return_val_if_fail (line != NULL, NULL);
129 g_return_val_if_fail (index_ranges != NULL, NULL);
130
131 iter = pango_layout_get_iter (layout: line->layout);
132 while (pango_layout_iter_get_line_readonly (iter) != line)
133 pango_layout_iter_next_line (iter);
134
135 clip_region = layout_iter_get_line_clip_region(iter, x_origin, y_origin, index_ranges, n_ranges);
136
137 pango_layout_iter_free (iter);
138
139 return clip_region;
140}
141
142/**
143 * gdk_pango_layout_get_clip_region: (skip)
144 * @layout: a `PangoLayout`
145 * @x_origin: X pixel where you intend to draw the layout with this clip
146 * @y_origin: Y pixel where you intend to draw the layout with this clip
147 * @index_ranges: array of byte indexes into the layout, where even members of array are start indexes and odd elements are end indexes
148 * @n_ranges: number of ranges in @index_ranges, i.e. half the size of @index_ranges
149 *
150 * Obtains a clip region which contains the areas where the given ranges
151 * of text would be drawn.
152 *
153 * @x_origin and @y_origin are the top left point to center the layout.
154 * @index_ranges should contain ranges of bytes in the layout’s text.
155 *
156 * Note that the regions returned correspond to logical extents of the text
157 * ranges, not ink extents. So the drawn layout may in fact touch areas out of
158 * the clip region. The clip region is mainly useful for highlightling parts
159 * of text, such as when text is selected.
160 *
161 * Returns: a clip region containing the given ranges
162 */
163cairo_region_t*
164gdk_pango_layout_get_clip_region (PangoLayout *layout,
165 int x_origin,
166 int y_origin,
167 const int *index_ranges,
168 int n_ranges)
169{
170 PangoLayoutIter *iter;
171 cairo_region_t *clip_region;
172
173 g_return_val_if_fail (PANGO_IS_LAYOUT (layout), NULL);
174 g_return_val_if_fail (index_ranges != NULL, NULL);
175
176 clip_region = cairo_region_create ();
177
178 iter = pango_layout_get_iter (layout);
179
180 do
181 {
182 PangoRectangle logical_rect;
183 cairo_region_t *line_region;
184 int baseline;
185
186 pango_layout_iter_get_line_extents (iter, NULL, logical_rect: &logical_rect);
187 baseline = pango_layout_iter_get_baseline (iter);
188
189 line_region = layout_iter_get_line_clip_region(iter,
190 x_origin: x_origin + PANGO_PIXELS (logical_rect.x),
191 y_origin: y_origin + PANGO_PIXELS (baseline),
192 index_ranges,
193 n_ranges);
194
195 cairo_region_union (dst: clip_region, other: line_region);
196 cairo_region_destroy (region: line_region);
197 }
198 while (pango_layout_iter_next_line (iter));
199
200 pango_layout_iter_free (iter);
201
202 return clip_region;
203}
204

source code of gtk/gdk/gdkpango.c