Annotation of /trunk/mozilla-firefox/patches/mozilla-firefox-1.0.7-pango-selection.patch
Parent Directory | Revision Log
Revision 153 -
(hide annotations)
(download)
Tue May 8 20:52:56 2007 UTC (17 years, 4 months ago) by niro
File size: 28829 byte(s)
Tue May 8 20:52:56 2007 UTC (17 years, 4 months ago) by niro
File size: 28829 byte(s)
-import
1 | niro | 153 | --- mozilla/gfx/src/gtk/nsFontMetricsXft.cpp.foo 2004-12-16 13:12:54.000000000 -0500 |
2 | +++ mozilla/gfx/src/gtk/nsFontMetricsXft.cpp 2004-12-16 13:13:31.000000000 -0500 | ||
3 | @@ -831,6 +831,33 @@ | ||
4 | return NS_OK; | ||
5 | } | ||
6 | |||
7 | +nsresult | ||
8 | +nsFontMetricsXft::GetClusterInfo(const PRUnichar *aText, | ||
9 | + PRUint32 aLength, | ||
10 | + PRUint32 *aClusterStarts) | ||
11 | +{ | ||
12 | + return NS_ERROR_NOT_IMPLEMENTED; | ||
13 | +} | ||
14 | + | ||
15 | +nsresult | ||
16 | +nsFontMetricsXft::GetPosition(const PRUnichar *aText, | ||
17 | + PRUint32 aLength, | ||
18 | + nscoord aCoord, | ||
19 | + PRUint32 &aInx) | ||
20 | +{ | ||
21 | + return NS_ERROR_NOT_IMPLEMENTED; | ||
22 | +} | ||
23 | + | ||
24 | +nsresult | ||
25 | +nsFontMetricsXft::GetRangeWidth(const PRUnichar *aText, | ||
26 | + PRUint32 aLength, | ||
27 | + PRUint32 aStart, | ||
28 | + PRUint32 aEnd, | ||
29 | + PRUint32 &aWidth) | ||
30 | +{ | ||
31 | + return NS_ERROR_NOT_IMPLEMENTED; | ||
32 | +} | ||
33 | + | ||
34 | PRUint32 | ||
35 | nsFontMetricsXft::GetHints(void) | ||
36 | { | ||
37 | --- mozilla/gfx/src/gtk/nsFontMetricsPango.cpp.foo 2004-12-16 13:12:54.000000000 -0500 | ||
38 | +++ mozilla/gfx/src/gtk/nsFontMetricsPango.cpp 2004-12-16 13:13:31.000000000 -0500 | ||
39 | @@ -907,13 +907,222 @@ | ||
40 | return NS_OK; | ||
41 | } | ||
42 | |||
43 | +nsresult | ||
44 | +nsFontMetricsPango::GetClusterInfo(const PRUnichar *aText, | ||
45 | + PRUint32 aLength, | ||
46 | + PRUint32 *aClusterStarts) | ||
47 | +{ | ||
48 | + nsresult rv = NS_OK; | ||
49 | + PangoLogAttr *attrs = NULL; | ||
50 | + gint n_attrs = 0; | ||
51 | + PangoLayout *layout = pango_layout_new(mPangoContext); | ||
52 | + | ||
53 | + // Convert the incoming UTF-16 to UTF-8 | ||
54 | + gchar *text = g_utf16_to_utf8(aText, aLength, NULL, NULL, NULL); | ||
55 | + | ||
56 | + if (!text) { | ||
57 | +#ifdef DEBUG | ||
58 | + NS_WARNING("nsFontMetricsPango::GetWidth invalid unicode to follow"); | ||
59 | + DUMP_PRUNICHAR(aText, aLength) | ||
60 | +#endif | ||
61 | + rv = NS_ERROR_FAILURE; | ||
62 | + goto loser; | ||
63 | + } | ||
64 | + | ||
65 | + // Set up the pango layout | ||
66 | + pango_layout_set_text(layout, text, strlen(text)); | ||
67 | + | ||
68 | + // Convert back to UTF-16 while filling in the cluster info | ||
69 | + // structure. | ||
70 | + pango_layout_get_log_attrs(layout, &attrs, &n_attrs); | ||
71 | + | ||
72 | + for (PRUint32 pos = 0; pos < aLength; pos++) { | ||
73 | + if (IS_HIGH_SURROGATE(aText[pos])) { | ||
74 | + aClusterStarts[pos] = 1; | ||
75 | + pos++; | ||
76 | + } | ||
77 | + else { | ||
78 | + aClusterStarts[pos] = attrs[pos].is_cursor_position; | ||
79 | + } | ||
80 | + } | ||
81 | + | ||
82 | + loser: | ||
83 | + if (attrs) | ||
84 | + g_free(attrs); | ||
85 | + if (text) | ||
86 | + g_free(text); | ||
87 | + if (layout) | ||
88 | + g_object_unref(layout); | ||
89 | + | ||
90 | + return rv; | ||
91 | +} | ||
92 | + | ||
93 | +nsresult | ||
94 | +nsFontMetricsPango::GetPosition(const PRUnichar *aText, PRUint32 aLength, | ||
95 | + nscoord aCoord, PRUint32 &aInx) | ||
96 | +{ | ||
97 | + nsresult rv = NS_OK; | ||
98 | + int trailing = 0; | ||
99 | + int inx = 0; | ||
100 | + gboolean found = FALSE; | ||
101 | + const gchar *curChar; | ||
102 | + | ||
103 | + float f = mDeviceContext->AppUnitsToDevUnits(); | ||
104 | + | ||
105 | + PangoLayout *layout = pango_layout_new(mPangoContext); | ||
106 | + PRUint32 localCoord = (PRUint32)(aCoord * PANGO_SCALE * f); | ||
107 | + | ||
108 | + // Convert the incoming UTF-16 to UTF-8 | ||
109 | + gchar *text = g_utf16_to_utf8(aText, aLength, NULL, NULL, NULL); | ||
110 | + | ||
111 | + if (!text) { | ||
112 | +#ifdef DEBUG | ||
113 | + NS_WARNING("nsFontMetricsPango::GetWidth invalid unicode to follow"); | ||
114 | + DUMP_PRUNICHAR(aText, aLength) | ||
115 | +#endif | ||
116 | + rv = NS_ERROR_FAILURE; | ||
117 | + goto loser; | ||
118 | + } | ||
119 | + | ||
120 | + // Set up the pango layout | ||
121 | + pango_layout_set_text(layout, text, strlen(text)); | ||
122 | + | ||
123 | + found = pango_layout_xy_to_index(layout, localCoord, 0, | ||
124 | + &inx, &trailing); | ||
125 | + | ||
126 | + // Convert the index back to the utf-16 index | ||
127 | + curChar = text; | ||
128 | + aInx = 0; | ||
129 | + | ||
130 | + // Jump to the end if it's not found. | ||
131 | + if (!found) { | ||
132 | + if (inx = 0) | ||
133 | + aInx = 0; | ||
134 | + else if (trailing) | ||
135 | + aInx = aLength; | ||
136 | + | ||
137 | + goto loser; | ||
138 | + } | ||
139 | + | ||
140 | + for (PRUint32 curOffset=0; curOffset < aLength; | ||
141 | + curOffset++, curChar = g_utf8_find_next_char(curChar, NULL)) { | ||
142 | + | ||
143 | + // Check for a match before checking for a surrogate pair | ||
144 | + if (curChar - text == inx) { | ||
145 | + aInx = curOffset; | ||
146 | + break; | ||
147 | + } | ||
148 | + | ||
149 | + if (IS_HIGH_SURROGATE(aText[curOffset])) | ||
150 | + curOffset++; | ||
151 | + } | ||
152 | + | ||
153 | + // If there was a trailing result, advance the index pointer the | ||
154 | + // number of characters equal to the trailing result. | ||
155 | + while (trailing) { | ||
156 | + aInx++; | ||
157 | + // Yes, this can make aInx > length to indicate the end of the | ||
158 | + // string. | ||
159 | + if (aInx < aLength && IS_HIGH_SURROGATE(aText[aInx])) | ||
160 | + aInx++; | ||
161 | + trailing--; | ||
162 | + } | ||
163 | + | ||
164 | + loser: | ||
165 | + if (text) | ||
166 | + g_free(text); | ||
167 | + if (layout) | ||
168 | + g_object_unref(layout); | ||
169 | + | ||
170 | + return rv; | ||
171 | +} | ||
172 | + | ||
173 | +nsresult | ||
174 | +nsFontMetricsPango::GetRangeWidth(const PRUnichar *aText, | ||
175 | + PRUint32 aLength, | ||
176 | + PRUint32 aStart, | ||
177 | + PRUint32 aEnd, | ||
178 | + PRUint32 &aWidth) | ||
179 | +{ | ||
180 | + nsresult rv = NS_OK; | ||
181 | + int *ranges = NULL; | ||
182 | + int n_ranges = 0; | ||
183 | + PRUint32 utf8Start = 0; | ||
184 | + PRUint32 utf8End = 0; | ||
185 | + float f; | ||
186 | + | ||
187 | + aWidth = 0; | ||
188 | + | ||
189 | + // Convert the incoming UTF-16 to UTF-8 | ||
190 | + gchar *text = g_utf16_to_utf8(aText, aLength, NULL, NULL, NULL); | ||
191 | + gchar *curChar = text; | ||
192 | + | ||
193 | + PangoLayout *layout = pango_layout_new(mPangoContext); | ||
194 | + | ||
195 | + if (!text) { | ||
196 | +#ifdef DEBUG | ||
197 | + NS_WARNING("nsFontMetricsPango::GetWidth invalid unicode to follow"); | ||
198 | + DUMP_PRUNICHAR(aText, aLength) | ||
199 | +#endif | ||
200 | + rv = NS_ERROR_FAILURE; | ||
201 | + goto loser; | ||
202 | + } | ||
203 | + | ||
204 | + // Convert the utf16 offsets into utf8 offsets | ||
205 | + for (PRUint32 curOffset = 0; curOffset < aLength; | ||
206 | + curOffset++, curChar = g_utf8_find_next_char(curChar, NULL)) { | ||
207 | + | ||
208 | + if (curOffset == aStart) | ||
209 | + utf8Start = curChar - text; | ||
210 | + | ||
211 | + if (curOffset == aEnd) | ||
212 | + utf8End = curChar - text; | ||
213 | + | ||
214 | + if (IS_HIGH_SURROGATE(aText[curOffset])) | ||
215 | + curOffset++; | ||
216 | + } | ||
217 | + | ||
218 | + // Special case where the end index is the same as the length | ||
219 | + if (aLength == aEnd) | ||
220 | + utf8End = strlen(text); | ||
221 | + | ||
222 | + pango_layout_set_text(layout, text, strlen(text)); | ||
223 | + | ||
224 | + PangoLayoutLine *line; | ||
225 | + if (pango_layout_get_line_count(layout) != 1) { | ||
226 | + printf("Warning: more than one line!\n"); | ||
227 | + } | ||
228 | + line = pango_layout_get_line(layout, 0); | ||
229 | + | ||
230 | + pango_layout_line_get_x_ranges(line, utf8Start, utf8End, &ranges, &n_ranges); | ||
231 | + | ||
232 | + // Convert the width into app units | ||
233 | + for (int i = 0; i < n_ranges; i++) { | ||
234 | + aWidth += (ranges[(i * 2) + 1] - ranges[(i * 2)]) / PANGO_SCALE; | ||
235 | + } | ||
236 | + | ||
237 | + f = mDeviceContext-> DevUnitsToAppUnits(); | ||
238 | + aWidth = nscoord(aWidth * f); | ||
239 | + | ||
240 | + loser: | ||
241 | + if (ranges) | ||
242 | + g_free(ranges); | ||
243 | + if (text) | ||
244 | + g_free(text); | ||
245 | + if (layout) | ||
246 | + g_object_unref(layout); | ||
247 | + | ||
248 | + return rv; | ||
249 | +} | ||
250 | + | ||
251 | /* static */ | ||
252 | PRUint32 | ||
253 | nsFontMetricsPango::GetHints(void) | ||
254 | { | ||
255 | return (NS_RENDERING_HINT_BIDI_REORDERING | | ||
256 | NS_RENDERING_HINT_ARABIC_SHAPING | | ||
257 | - NS_RENDERING_HINT_FAST_MEASURE); | ||
258 | + NS_RENDERING_HINT_FAST_MEASURE | | ||
259 | + NS_RENDERING_HINT_TEXT_CLUSTERS); | ||
260 | } | ||
261 | |||
262 | /* static */ | ||
263 | @@ -1137,13 +1346,11 @@ | ||
264 | } | ||
265 | |||
266 | /* printf(" rendering at X coord %d\n", aX + offset); */ | ||
267 | - | ||
268 | - gdk_draw_glyphs(aDrawable, aGC, layoutRun->item->analysis.font, | ||
269 | - aX + (gint)(offset / PANGO_SCALE), aY, layoutRun->glyphs); | ||
270 | - | ||
271 | offset += tmpOffset; | ||
272 | } | ||
273 | |||
274 | + gdk_draw_layout_line(aDrawable, aGC, aX, aY, aLine); | ||
275 | + | ||
276 | delete[] utf8spacing; | ||
277 | } | ||
278 | |||
279 | --- mozilla/gfx/src/gtk/nsRenderingContextGTK.h.foo 2004-12-16 13:12:54.000000000 -0500 | ||
280 | +++ mozilla/gfx/src/gtk/nsRenderingContextGTK.h 2004-12-16 13:13:31.000000000 -0500 | ||
281 | @@ -195,6 +195,15 @@ | ||
282 | NS_IMETHOD RetrieveCurrentNativeGraphicData(PRUint32 * ngd); | ||
283 | |||
284 | NS_IMETHOD SetRightToLeftText(PRBool aIsRTL); | ||
285 | + NS_IMETHOD GetClusterInfo(const PRUnichar *aText, PRUint32 aLength, | ||
286 | + PRUint32 *aClusterStarts); | ||
287 | + NS_IMETHOD GetPosition(const PRUnichar *aText, PRUint32 aLength, | ||
288 | + nscoord aCoord, PRUint32 &aInx); | ||
289 | + NS_IMETHOD GetRangeWidth(const PRUnichar *aText, | ||
290 | + PRUint32 aLength, | ||
291 | + PRUint32 aStart, | ||
292 | + PRUint32 aEnd, | ||
293 | + PRUint32 &aWidth); | ||
294 | |||
295 | NS_IMETHOD DrawImage(imgIContainer *aImage, const nsRect * aSrcRect, const nsPoint * aDestPoint); | ||
296 | NS_IMETHOD DrawScaledImage(imgIContainer *aImage, const nsRect * aSrcRect, const nsRect * aDestRect); | ||
297 | --- mozilla/gfx/src/gtk/nsFontMetricsPango.h.foo 2004-12-16 13:12:54.000000000 -0500 | ||
298 | +++ mozilla/gfx/src/gtk/nsFontMetricsPango.h 2004-12-16 13:13:31.000000000 -0500 | ||
299 | @@ -195,6 +195,21 @@ | ||
300 | |||
301 | virtual nsresult SetRightToLeftText(PRBool aIsRTL); | ||
302 | |||
303 | + virtual nsresult GetClusterInfo(const PRUnichar *aText, | ||
304 | + PRUint32 aLength, | ||
305 | + PRUint32 *aClusterStarts); | ||
306 | + | ||
307 | + virtual nsresult GetPosition(const PRUnichar *aText, | ||
308 | + PRUint32 aLength, | ||
309 | + nscoord aCoord, | ||
310 | + PRUint32 &aInx); | ||
311 | + | ||
312 | + virtual nsresult GetRangeWidth(const PRUnichar *aText, | ||
313 | + PRUint32 aLength, | ||
314 | + PRUint32 aStart, | ||
315 | + PRUint32 aEnd, | ||
316 | + PRUint32 &aWidth); | ||
317 | + | ||
318 | // get hints for the font | ||
319 | static PRUint32 GetHints (void); | ||
320 | |||
321 | --- mozilla/gfx/src/gtk/nsIFontMetricsGTK.h.foo 2004-12-16 13:12:54.000000000 -0500 | ||
322 | +++ mozilla/gfx/src/gtk/nsIFontMetricsGTK.h 2004-12-16 13:13:31.000000000 -0500 | ||
323 | @@ -124,6 +124,21 @@ | ||
324 | // Set the direction of the text rendering | ||
325 | virtual nsresult SetRightToLeftText(PRBool aIsRTL) = 0; | ||
326 | |||
327 | + virtual nsresult GetClusterInfo(const PRUnichar *aText, | ||
328 | + PRUint32 aLength, | ||
329 | + PRUint32 *aClusterStarts) = 0; | ||
330 | + | ||
331 | + virtual nsresult GetPosition(const PRUnichar *aText, | ||
332 | + PRUint32 aLength, | ||
333 | + nscoord aCoord, | ||
334 | + PRUint32 &aInx) = 0; | ||
335 | + | ||
336 | + virtual nsresult GetRangeWidth(const PRUnichar *aText, | ||
337 | + PRUint32 aLength, | ||
338 | + PRUint32 aStart, | ||
339 | + PRUint32 aEnd, | ||
340 | + PRUint32 &aWidth) = 0; | ||
341 | + | ||
342 | }; | ||
343 | |||
344 | #endif /* __nsIFontMetricsGTK_h */ | ||
345 | --- mozilla/gfx/src/gtk/nsRenderingContextGTK.cpp.foo 2004-12-16 13:12:54.000000000 -0500 | ||
346 | +++ mozilla/gfx/src/gtk/nsRenderingContextGTK.cpp 2004-12-16 13:13:31.000000000 -0500 | ||
347 | @@ -1446,6 +1446,26 @@ | ||
348 | return mFontMetrics->SetRightToLeftText(aIsRTL); | ||
349 | } | ||
350 | |||
351 | +NS_IMETHODIMP nsRenderingContextGTK::GetClusterInfo(const PRUnichar *aText, | ||
352 | + PRUint32 aLength, | ||
353 | + PRUint32 *aClusterStarts) | ||
354 | +{ | ||
355 | + return mFontMetrics->GetClusterInfo(aText, aLength, aClusterStarts); | ||
356 | +} | ||
357 | + | ||
358 | +NS_IMETHODIMP nsRenderingContextGTK::GetPosition(const PRUnichar *aText, PRUint32 aLength, | ||
359 | + nscoord aCoord, PRUint32 &aInx) | ||
360 | +{ | ||
361 | + return mFontMetrics->GetPosition(aText, aLength, aCoord, aInx); | ||
362 | +} | ||
363 | + | ||
364 | +NS_IMETHODIMP nsRenderingContextGTK::GetRangeWidth(const PRUnichar *aText, PRUint32 aLength, | ||
365 | + PRUint32 aStart, PRUint32 aEnd, | ||
366 | + PRUint32 &aWidth) | ||
367 | +{ | ||
368 | + return mFontMetrics->GetRangeWidth(aText, aLength, aStart, aEnd, aWidth); | ||
369 | +} | ||
370 | + | ||
371 | NS_IMETHODIMP nsRenderingContextGTK::DrawImage(imgIContainer *aImage, const nsRect * aSrcRect, const nsPoint * aDestPoint) | ||
372 | { | ||
373 | UpdateGC(); | ||
374 | --- mozilla/gfx/src/gtk/nsFontMetricsGTK.cpp.foo 2004-12-16 13:12:54.000000000 -0500 | ||
375 | +++ mozilla/gfx/src/gtk/nsFontMetricsGTK.cpp 2004-12-16 13:13:31.000000000 -0500 | ||
376 | @@ -4606,6 +4606,34 @@ | ||
377 | return NS_OK; | ||
378 | } | ||
379 | |||
380 | +nsresult | ||
381 | +nsFontMetricsGTK::GetClusterInfo(const PRUnichar *aText, | ||
382 | + PRUint32 aLength, | ||
383 | + PRUint32 *aClusterStarts) | ||
384 | +{ | ||
385 | + return NS_ERROR_NOT_IMPLEMENTED; | ||
386 | +} | ||
387 | + | ||
388 | +nsresult | ||
389 | +nsFontMetricsGTK::GetPosition(const PRUnichar *aText, | ||
390 | + PRUint32 aLength, | ||
391 | + nscoord aCoord, | ||
392 | + PRUint32 &aInx) | ||
393 | +{ | ||
394 | + return NS_ERROR_NOT_IMPLEMENTED; | ||
395 | +} | ||
396 | + | ||
397 | + | ||
398 | +nsresult | ||
399 | +nsFontMetricsGTK::GetRangeWidth(const PRUnichar *aText, | ||
400 | + PRUint32 aLength, | ||
401 | + PRUint32 aStart, | ||
402 | + PRUint32 aEnd, | ||
403 | + PRUint32 &aWidth) | ||
404 | +{ | ||
405 | + return NS_ERROR_NOT_IMPLEMENTED; | ||
406 | +} | ||
407 | + | ||
408 | PR_BEGIN_EXTERN_C | ||
409 | static int | ||
410 | CompareSizes(const void* aArg1, const void* aArg2, void *data) | ||
411 | --- mozilla/gfx/src/gtk/nsFontMetricsXft.h.foo 2004-12-16 13:12:54.000000000 -0500 | ||
412 | +++ mozilla/gfx/src/gtk/nsFontMetricsXft.h 2004-12-16 13:13:31.000000000 -0500 | ||
413 | @@ -204,6 +204,21 @@ | ||
414 | |||
415 | virtual nsresult SetRightToLeftText(PRBool aIsRTL); | ||
416 | |||
417 | + virtual nsresult GetClusterInfo(const PRUnichar *aText, | ||
418 | + PRUint32 aLength, | ||
419 | + PRUint32 *aClusterStarts); | ||
420 | + | ||
421 | + virtual nsresult GetPosition(const PRUnichar *aText, | ||
422 | + PRUint32 aLength, | ||
423 | + nscoord aCoord, | ||
424 | + PRUint32 &aInx); | ||
425 | + | ||
426 | + virtual nsresult GetRangeWidth(const PRUnichar *aText, | ||
427 | + PRUint32 aLength, | ||
428 | + PRUint32 aStart, | ||
429 | + PRUint32 aEnd, | ||
430 | + PRUint32 &aWidth); | ||
431 | + | ||
432 | // get hints for the font | ||
433 | static PRUint32 GetHints (void); | ||
434 | |||
435 | --- mozilla/gfx/src/gtk/nsFontMetricsGTK.h.foo 2004-12-16 13:12:54.000000000 -0500 | ||
436 | +++ mozilla/gfx/src/gtk/nsFontMetricsGTK.h 2004-12-16 13:13:31.000000000 -0500 | ||
437 | @@ -346,6 +346,21 @@ | ||
438 | |||
439 | virtual nsresult SetRightToLeftText(PRBool aIsRTL); | ||
440 | |||
441 | + virtual nsresult GetClusterInfo(const PRUnichar *aText, | ||
442 | + PRUint32 aLength, | ||
443 | + PRUint32 *aClusterStarts); | ||
444 | + | ||
445 | + virtual nsresult GetPosition(const PRUnichar *aText, | ||
446 | + PRUint32 aLength, | ||
447 | + nscoord aCoord, | ||
448 | + PRUint32 &aInx); | ||
449 | + | ||
450 | + virtual nsresult GetRangeWidth(const PRUnichar *aText, | ||
451 | + PRUint32 aLength, | ||
452 | + PRUint32 aStart, | ||
453 | + PRUint32 aEnd, | ||
454 | + PRUint32 &aWidth); | ||
455 | + | ||
456 | static nsresult FamilyExists(nsIDeviceContext *aDevice, const nsString& aName); | ||
457 | static PRUint32 GetHints(void); | ||
458 | |||
459 | --- mozilla/gfx/src/shared/nsRenderingContextImpl.cpp.foo 2004-10-08 12:57:19.000000000 -0400 | ||
460 | +++ mozilla/gfx/src/shared/nsRenderingContextImpl.cpp 2004-12-16 13:13:31.000000000 -0500 | ||
461 | @@ -938,3 +938,32 @@ | ||
462 | { | ||
463 | return NS_OK; | ||
464 | } | ||
465 | + | ||
466 | +NS_IMETHODIMP | ||
467 | +nsRenderingContextImpl::GetClusterInfo(const PRUnichar *aText, | ||
468 | + PRUint32 aLength, | ||
469 | + PRUint32 *aClusterStarts) | ||
470 | +{ | ||
471 | + return NS_ERROR_NOT_IMPLEMENTED; | ||
472 | +} | ||
473 | + | ||
474 | +NS_IMETHODIMP | ||
475 | +nsRenderingContextImpl::GetPosition(const PRUnichar *aText, | ||
476 | + PRUint32 aLength, | ||
477 | + nscoord aCoord, | ||
478 | + PRUint32 &aInx) | ||
479 | +{ | ||
480 | + return NS_ERROR_NOT_IMPLEMENTED; | ||
481 | +} | ||
482 | + | ||
483 | +NS_IMETHODIMP | ||
484 | +nsRenderingContextImpl::GetRangeWidth(const PRUnichar *aText, | ||
485 | + PRUint32 aLength, | ||
486 | + PRUint32 aStart, | ||
487 | + PRUint32 aEnd, | ||
488 | + PRUint32 &aWidth) | ||
489 | +{ | ||
490 | + return NS_ERROR_NOT_IMPLEMENTED; | ||
491 | +} | ||
492 | + | ||
493 | + | ||
494 | --- mozilla/gfx/src/nsRenderingContextImpl.h.foo 2004-10-08 12:57:18.000000000 -0400 | ||
495 | +++ mozilla/gfx/src/nsRenderingContextImpl.h 2004-12-16 13:13:31.000000000 -0500 | ||
496 | @@ -138,6 +138,19 @@ | ||
497 | NS_IMETHOD DrawScaledImage(imgIContainer *aImage, const nsRect * aSrcRect, const nsRect * aDestRect); | ||
498 | NS_IMETHOD DrawTile(imgIContainer *aImage, nscoord aXOffset, nscoord aYOffset, const nsRect * aTargetRect); | ||
499 | |||
500 | + NS_IMETHOD GetClusterInfo(const PRUnichar *aText, | ||
501 | + PRUint32 aLength, | ||
502 | + PRUint32 *aClusterStarts); | ||
503 | + NS_IMETHOD GetPosition(const PRUnichar *aText, | ||
504 | + PRUint32 aLength, | ||
505 | + nscoord aCoord, | ||
506 | + PRUint32 &aInx); | ||
507 | + NS_IMETHOD GetRangeWidth(const PRUnichar *aText, | ||
508 | + PRUint32 aLength, | ||
509 | + PRUint32 aStart, | ||
510 | + PRUint32 aEnd, | ||
511 | + PRUint32 &aWidth); | ||
512 | + | ||
513 | protected: | ||
514 | virtual ~nsRenderingContextImpl(); | ||
515 | |||
516 | --- mozilla/gfx/public/nsIRenderingContext.h.foo 2004-10-08 12:57:18.000000000 -0400 | ||
517 | +++ mozilla/gfx/public/nsIRenderingContext.h 2004-12-16 13:13:31.000000000 -0500 | ||
518 | @@ -824,6 +824,66 @@ | ||
519 | NS_IMETHOD DrawTile(imgIContainer *aImage, | ||
520 | nscoord aXImageStart, nscoord aYImageStart, | ||
521 | const nsRect * aTargetRect) = 0; | ||
522 | + | ||
523 | + /** | ||
524 | + * Get cluster details for a chunk of text. | ||
525 | + * | ||
526 | + * This will fill in the aClusterStarts array with information about | ||
527 | + * what characters are the start of clusters for display. | ||
528 | + * | ||
529 | + * @param aText Text on which to get details. | ||
530 | + * @param aLength Length of the text. | ||
531 | + * @param aClusterStarts Array of ints that will be populated | ||
532 | + * with information about which characters are the starts | ||
533 | + * of clusters. | ||
534 | + * | ||
535 | + */ | ||
536 | + NS_IMETHOD GetClusterInfo(const PRUnichar *aText, | ||
537 | + PRUint32 aLength, | ||
538 | + PRUint32 *aClusterStarts) = 0; | ||
539 | + | ||
540 | + /** | ||
541 | + * Find the closest cursor position for a given x coordinate. | ||
542 | + * | ||
543 | + * This will find the closest byte index for a given x coordinate. | ||
544 | + * This takes into account grapheme clusters and bidi text. | ||
545 | + * | ||
546 | + * @param aText Text on which to operate. | ||
547 | + * @param aLength Length of the text. | ||
548 | + * @param aCoord The distance into the string to check. | ||
549 | + * @param aInx Index of character where the cursor falls - note that | ||
550 | + * this can be after the last character if the cursor happens to | ||
551 | + * the right of the last character in the text! | ||
552 | + * | ||
553 | + */ | ||
554 | + NS_IMETHOD GetPosition(const PRUnichar *aText, | ||
555 | + PRUint32 aLength, | ||
556 | + nscoord aCoord, | ||
557 | + PRUint32 &aInx) = 0; | ||
558 | + | ||
559 | + /** | ||
560 | + * Get the width for the specific range of a given string. | ||
561 | + * | ||
562 | + * This function is similar to other GetWidth functions, except that | ||
563 | + * it gets the width for a part of the string instead of the entire | ||
564 | + * string. This is useful when you're interested in finding out the | ||
565 | + * length of a chunk in the middle of the string. Lots of languages | ||
566 | + * require you to include surrounding information to accurately | ||
567 | + * determine the length of a substring. | ||
568 | + * | ||
569 | + * @param aText Text on which to operate | ||
570 | + * @param aLength Length of the text | ||
571 | + * @param aStart Start index into the string | ||
572 | + * @param aEnd End index into the string (inclusive) | ||
573 | + * @param aWidth Returned with in app coordinates | ||
574 | + * | ||
575 | + */ | ||
576 | + NS_IMETHOD GetRangeWidth(const PRUnichar *aText, | ||
577 | + PRUint32 aLength, | ||
578 | + PRUint32 aStart, | ||
579 | + PRUint32 aEnd, | ||
580 | + PRUint32 &aWidth) = 0; | ||
581 | + | ||
582 | }; | ||
583 | |||
584 | //modifiers for text rendering | ||
585 | @@ -866,6 +926,12 @@ | ||
586 | */ | ||
587 | #define NS_RENDERING_HINT_FAST_MEASURE 0x10 | ||
588 | |||
589 | +/** | ||
590 | + * This bit, when set, indicates that the gfx supports describing | ||
591 | + * cluster information in a string | ||
592 | + */ | ||
593 | +#define NS_RENDERING_HINT_TEXT_CLUSTERS 0x20 | ||
594 | + | ||
595 | //flags for copy CopyOffScreenBits | ||
596 | |||
597 | //when performing the blit, use the region, if any, | ||
598 | --- mozilla/layout/html/base/src/nsTextFrame.cpp.foo 2004-10-08 09:39:27.000000000 -0400 | ||
599 | +++ mozilla/layout/html/base/src/nsTextFrame.cpp 2004-12-16 13:14:23.000000000 -0500 | ||
600 | @@ -2339,6 +2339,24 @@ | ||
601 | #endif | ||
602 | sdptr = sdptr->mNext; | ||
603 | } | ||
604 | + | ||
605 | + /* | ||
606 | + * Text is drawn by drawing the entire string every time, but | ||
607 | + * using clip regions to control which part of the text is shown | ||
608 | + * (selected or unselected.) We do this because you can't | ||
609 | + * assume that the layout of a part of text will be the same | ||
610 | + * when it's drawn apart from the entire string. This is true | ||
611 | + * in languages like arabic, where shaping affects entire words. | ||
612 | + * Simply put: length("abcd") != length("ab") + length("cd") in | ||
613 | + * some languages. | ||
614 | + */ | ||
615 | + | ||
616 | + // See if this rendering backend supports getting cluster | ||
617 | + // information. | ||
618 | + PRUint32 clusterHint = 0; | ||
619 | + aRenderingContext.GetHints(clusterHint); | ||
620 | + clusterHint &= NS_RENDERING_HINT_TEXT_CLUSTERS; | ||
621 | + | ||
622 | //while we have substrings... | ||
623 | //PRBool drawn = PR_FALSE; | ||
624 | DrawSelectionIterator iter(content, details,text,(PRUint32)textLength,aTextStyle, selectionValue, aPresContext, mStyleContext); | ||
625 | @@ -2361,37 +2379,55 @@ | ||
626 | nscolor currentBKColor; | ||
627 | PRBool isCurrentBKColorTransparent; | ||
628 | |||
629 | -#ifdef IBMBIDI | ||
630 | - if (currentlength > 0 | ||
631 | - && NS_SUCCEEDED(aRenderingContext.GetWidth(currenttext, currentlength,newWidth)))//ADJUST FOR CHAR SPACING | ||
632 | + if (currentlength > 0) | ||
633 | { | ||
634 | - | ||
635 | - if (isRightToLeftOnBidiPlatform) | ||
636 | - currentX -= newWidth; | ||
637 | -#else // not IBMBIDI | ||
638 | - if (NS_SUCCEEDED(aRenderingContext.GetWidth(currenttext, currentlength,newWidth)))//ADJUST FOR CHAR SPACING | ||
639 | - { | ||
640 | -#endif | ||
641 | - if (iter.CurrentBackGroundColor(currentBKColor, &isCurrentBKColorTransparent) && !isPaginated) | ||
642 | - {//DRAW RECT HERE!!! | ||
643 | - if (!isCurrentBKColorTransparent) { | ||
644 | - aRenderingContext.SetColor(currentBKColor); | ||
645 | - aRenderingContext.FillRect(currentX, dy, newWidth, mRect.height); | ||
646 | + if (clusterHint) { | ||
647 | + PRUint32 tmpWidth; | ||
648 | + rv = aRenderingContext.GetRangeWidth(text, textLength, currenttext - text, | ||
649 | + (currenttext - text) + currentlength, | ||
650 | + tmpWidth); | ||
651 | + newWidth = nscoord(tmpWidth); | ||
652 | + } | ||
653 | + else { | ||
654 | + rv = aRenderingContext.GetWidth(currenttext, currentlength,newWidth); //ADJUST FOR CHAR SPACING | ||
655 | + } | ||
656 | + if (NS_SUCCEEDED(rv)) { | ||
657 | + if (isRightToLeftOnBidiPlatform) | ||
658 | + currentX -= newWidth; | ||
659 | + if (iter.CurrentBackGroundColor(currentBKColor, &isCurrentBKColorTransparent) && !isPaginated) | ||
660 | + {//DRAW RECT HERE!!! | ||
661 | + if (!isCurrentBKColorTransparent) { | ||
662 | + aRenderingContext.SetColor(currentBKColor); | ||
663 | + aRenderingContext.FillRect(currentX, dy, newWidth, mRect.height); | ||
664 | + } | ||
665 | + currentFGColor = EnsureDifferentColors(currentFGColor, currentBKColor); | ||
666 | } | ||
667 | - currentFGColor = EnsureDifferentColors(currentFGColor, currentBKColor); | ||
668 | + } | ||
669 | + else { | ||
670 | + newWidth = 0; | ||
671 | } | ||
672 | } | ||
673 | - else | ||
674 | - newWidth =0; | ||
675 | - | ||
676 | + else { | ||
677 | + newWidth = 0; | ||
678 | + } | ||
679 | + | ||
680 | + aRenderingContext.PushState(); | ||
681 | + | ||
682 | + nsRect rect(currentX, dy, newWidth, mRect.height); | ||
683 | + PRBool ignore; | ||
684 | + aRenderingContext.SetClipRect(rect, nsClipCombine_kIntersect, | ||
685 | + ignore); | ||
686 | + | ||
687 | if (isPaginated && !iter.IsBeforeOrAfter()) { | ||
688 | aRenderingContext.SetColor(nsCSSRendering::TransformColor(aTextStyle.mColor->mColor,canDarkenColor)); | ||
689 | - aRenderingContext.DrawString(currenttext, currentlength, currentX, dy + mAscent); | ||
690 | + aRenderingContext.DrawString(text, PRUint32(textLength), dx, dy + mAscent); | ||
691 | } else if (!isPaginated) { | ||
692 | aRenderingContext.SetColor(nsCSSRendering::TransformColor(currentFGColor,canDarkenColor)); | ||
693 | - aRenderingContext.DrawString(currenttext, currentlength, currentX, dy + mAscent); | ||
694 | + aRenderingContext.DrawString(text, PRUint32(textLength), dx, dy + mAscent); | ||
695 | } | ||
696 | |||
697 | + aRenderingContext.PopState(ignore); | ||
698 | + | ||
699 | #ifdef IBMBIDI | ||
700 | if (!isRightToLeftOnBidiPlatform) | ||
701 | #endif | ||
702 | @@ -3429,6 +3465,16 @@ | ||
703 | PRInt32 textWidth = 0; | ||
704 | PRUnichar* text = paintBuffer.mBuffer; | ||
705 | |||
706 | + // See if the font backend will do all the hard work for us. | ||
707 | + PRUint32 clusterHint = 0; | ||
708 | + acx->GetHints(clusterHint); | ||
709 | + clusterHint &= NS_RENDERING_HINT_TEXT_CLUSTERS; | ||
710 | + if (clusterHint) { | ||
711 | + PRUint32 tmpIndx = indx; | ||
712 | + acx->GetPosition(text, textLength, aPoint.x - origin.x, tmpIndx); | ||
713 | + indx = tmpIndx; | ||
714 | + } | ||
715 | + else { | ||
716 | #ifdef IBMBIDI | ||
717 | PRBool getReversedPos = PR_FALSE; | ||
718 | PRUint8 level = 0; | ||
719 | @@ -3465,6 +3511,7 @@ | ||
720 | indx++; | ||
721 | } | ||
722 | } | ||
723 | + } | ||
724 | |||
725 | aContentOffset = indx + mContentOffset; | ||
726 | //reusing wordBufMem | ||
727 | @@ -3916,6 +3963,12 @@ | ||
728 | } | ||
729 | PRInt32* ip = indexBuffer.mBuffer; | ||
730 | |||
731 | + nsAutoIndexBuffer clusterBuffer; | ||
732 | + rv = clusterBuffer.GrowTo(mContentLength + 1); | ||
733 | + if (NS_FAILED(rv)) { | ||
734 | + return rv; | ||
735 | + } | ||
736 | + | ||
737 | PRInt32 textLength; | ||
738 | nsresult result(NS_ERROR_FAILURE); | ||
739 | aPos->mResultContent = mContent;//do this right off | ||
740 | @@ -3981,8 +4034,32 @@ | ||
741 | aPos->mContentOffset = 0; | ||
742 | PRInt32 i; | ||
743 | |||
744 | + // Fill in the cluster hint information, if it's available. | ||
745 | + nsCOMPtr<nsIRenderingContext> acx; | ||
746 | + PRUint32 clusterHint = 0; | ||
747 | + | ||
748 | + nsIPresShell *shell = aPresContext->GetPresShell(); | ||
749 | + if (shell) { | ||
750 | + shell->CreateRenderingContext(this, getter_AddRefs(acx)); | ||
751 | + | ||
752 | + // Find the font metrics for this text | ||
753 | + SetFontFromStyle(acx, mStyleContext); | ||
754 | + | ||
755 | + if (acx) | ||
756 | + acx->GetHints(clusterHint); | ||
757 | + clusterHint &= NS_RENDERING_HINT_TEXT_CLUSTERS; | ||
758 | + } | ||
759 | + | ||
760 | + if (clusterHint) { | ||
761 | + acx->GetClusterInfo(paintBuffer.mBuffer, (PRUint32)textLength, (PRUint32 *)clusterBuffer.mBuffer); | ||
762 | + } | ||
763 | + else { | ||
764 | + memset(clusterBuffer.mBuffer, 1, sizeof(PRInt32) * textLength); | ||
765 | + } | ||
766 | + | ||
767 | for (i = aPos->mStartOffset -1 - mContentOffset; i >=0; i--){ | ||
768 | if ((ip[i] < ip[aPos->mStartOffset - mContentOffset]) && | ||
769 | + (clusterBuffer.mBuffer[ip[i] - mContentOffset]) && | ||
770 | (! IS_LOW_SURROGATE(paintBuffer.mBuffer[ip[i]-mContentOffset]))) | ||
771 | { | ||
772 | aPos->mContentOffset = i + mContentOffset; | ||
773 | @@ -4033,14 +4110,39 @@ | ||
774 | PRInt32 i; | ||
775 | aPos->mContentOffset = mContentLength; | ||
776 | |||
777 | - for (i = aPos->mStartOffset +1 - mContentOffset; i <= mContentLength; i++){ | ||
778 | + // Fill in the cluster hint information, if it's available. | ||
779 | + nsCOMPtr<nsIRenderingContext> acx; | ||
780 | + PRUint32 clusterHint = 0; | ||
781 | + | ||
782 | + nsIPresShell *shell = aPresContext->GetPresShell(); | ||
783 | + if (shell) { | ||
784 | + shell->CreateRenderingContext(this, getter_AddRefs(acx)); | ||
785 | + | ||
786 | + // Find the font metrics for this text | ||
787 | + SetFontFromStyle(acx, mStyleContext); | ||
788 | + | ||
789 | + if (acx) | ||
790 | + acx->GetHints(clusterHint); | ||
791 | + clusterHint &= NS_RENDERING_HINT_TEXT_CLUSTERS; | ||
792 | + } | ||
793 | + | ||
794 | + if (clusterHint) { | ||
795 | + acx->GetClusterInfo(paintBuffer.mBuffer, (PRUint32)textLength, (PRUint32 *)clusterBuffer.mBuffer); | ||
796 | + } | ||
797 | + else { | ||
798 | + memset(clusterBuffer.mBuffer, 1, sizeof(PRInt32) * textLength); | ||
799 | + } | ||
800 | + | ||
801 | + for (i = aPos->mStartOffset - mContentOffset; i <= mContentLength; i++) { | ||
802 | if ((ip[i] > ip[aPos->mStartOffset - mContentOffset]) && | ||
803 | - (! IS_LOW_SURROGATE(paintBuffer.mBuffer[ip[i]-mContentOffset]))) | ||
804 | - { | ||
805 | + ((i == mContentLength) || | ||
806 | + (!IS_LOW_SURROGATE(paintBuffer.mBuffer[ip[i] - mContentOffset])) && | ||
807 | + (clusterBuffer.mBuffer[ip[i] - mContentOffset]))) { | ||
808 | aPos->mContentOffset = i + mContentOffset; | ||
809 | break; | ||
810 | } | ||
811 | } | ||
812 | + | ||
813 | #ifdef SUNCTL | ||
814 | static NS_DEFINE_CID(kLECID, NS_ULE_CID); | ||
815 |