Contents of /trunk/mozilla-firefox/patches/mozilla-firefox-1.0.7-pango-selection.patch
Parent Directory | Revision Log
Revision 153 -
(show 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 | --- 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 |