Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(967)

Side by Side Diff: ui/gfx/render_text_linux.cc

Issue 7511029: Implement Pango RenderText for Linux. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src/
Patch Set: fix compilation error. using ICU functions for utf8/utf16 conversion Created 9 years, 4 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
« ui/gfx/render_text_linux.h ('K') | « ui/gfx/render_text_linux.h ('k') | no next file » | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright (c) 2011 The Chromium Authors. All rights reserved. 1 // Copyright (c) 2011 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #include "ui/gfx/render_text_linux.h" 5 #include "ui/gfx/render_text_linux.h"
6 6
7 #include <pango/pangocairo.h>
8 #include <algorithm>
9
10 #include "base/logging.h"
11 #include "ui/gfx/canvas_skia.h"
12 #include "ui/gfx/gtk_util.h"
13 #include "unicode/uchar.h"
14 #include "unicode/ustring.h"
15
16 // TODO(xji): instead of converting each R or G or B from 16-bite to 32-bit,
17 // it should also massage A in the conversion.
18 #define COLOR_16_TO_32_BIT(c) ((c)/0xff * 0xffff)
msw 2011/08/23 08:01:01 Can you make this a file local function instead of
xji 2011/08/23 23:52:52 changed to function in unnamed namespace. checked
19
20 // TODO(xji): index saved in upper layer is utf16 index. Pango uses utf8 index.
21 // Since caret_pos is used internally, we could save utf8 index for caret_pos
22 // to avoid conversion.
23
7 namespace gfx { 24 namespace gfx {
8 25
9 RenderTextLinux::RenderTextLinux() 26 RenderTextLinux::RenderTextLinux()
10 : RenderText() { 27 : layout_(NULL),
28 layout_line_(NULL) {
11 } 29 }
12 30
13 RenderTextLinux::~RenderTextLinux() { 31 RenderTextLinux::~RenderTextLinux() {
32 ResetLayout();
14 } 33 }
15 34
16 RenderText* RenderText::CreateRenderText() { 35 RenderText* RenderText::CreateRenderText() {
17 return new RenderTextLinux; 36 return new RenderTextLinux;
18 } 37 }
19 38
39 void RenderTextLinux::SetText(const string16& text) {
40 RenderText::SetText(text);
41 ResetLayout();
42 }
43
44 void RenderTextLinux::SetDisplayRect(const Rect&r) {
45 RenderText::SetDisplayRect(r);
46 ResetLayout();
47 }
48
49 void RenderTextLinux::ApplyStyleRange(StyleRange style_range) {
50 RenderText::ApplyStyleRange(style_range);
51 ResetLayout();
52 }
53
54 void RenderTextLinux::ApplyDefaultStyle() {
55 RenderText::ApplyDefaultStyle();
56 ResetLayout();
57 }
58
59 base::i18n::TextDirection RenderTextLinux::GetTextDirection() {
60 EnsureLayout();
61
62 const char* layout_text = pango_layout_get_text(layout_);
63 PangoDirection base_dir =
64 pango_find_base_dir(layout_text, strlen(layout_text));
65 if (base_dir == PANGO_DIRECTION_RTL || base_dir == PANGO_DIRECTION_WEAK_RTL)
66 return base::i18n::RIGHT_TO_LEFT;
67 return base::i18n::LEFT_TO_RIGHT;
68 }
69
70 int RenderTextLinux::GetStringWidth() {
71 PangoLayout* layout = EnsureLayout();
72 int width, height;
73 pango_layout_get_pixel_size(layout, &width, &height);
74 return width;
75 }
76
77 void RenderTextLinux::Draw(Canvas* canvas) {
78 PangoLayout* layout = EnsureLayout();
79 Rect bounds(display_rect());
80
81 // Clip the canvas to the text display area.
82 CanvasSkia* canvas_skia = canvas->AsCanvasSkia();
83 canvas_skia->ClipRectInt(
84 bounds.x(), bounds.y(), bounds.width(), bounds.height());
85
86 // TODO(xji): use ScopedPlatformPaing.
msw 2011/08/23 08:01:01 ScopedPlatformPain*t*
xji 2011/08/23 23:52:52 Done.
87 cairo_t* cr = skia::BeginPlatformPaint(canvas_skia);
88 cairo_save(cr);
89 cairo_rectangle(cr, bounds.x(), bounds.y(), bounds.width(), bounds.height());
90 cairo_clip(cr);
91
92 int text_width, text_height;
93 pango_layout_get_pixel_size(layout, &text_width, &text_height);
94 Point offset(ToViewPoint(Point()));
95 // Vertically centered.
96 int text_y = offset.y() + ((bounds.height() - text_height) / 2);
97 cairo_move_to(cr, offset.x(), text_y);
98 pango_cairo_show_layout(cr, layout);
99
100 // Destructor.
101 cairo_restore(cr);
102 skia::EndPlatformPaint(canvas_skia);
103
104 // Paint cursor.
105 bounds = GetUpdatedCursorBounds();
106 if (cursor_visible() && focused() && !bounds.IsEmpty()) {
107 if (!bounds.IsEmpty())
108 canvas->DrawRectInt(kCursorColor,
109 bounds.x(),
110 bounds.y(),
111 bounds.width(),
112 bounds.height());
113 }
114 }
115
116 SelectionModel RenderTextLinux::FindCursorPosition(const Point& point) {
117 // TODO(xji): when points outside of text, return HOME/END position.
118 PangoLayout* layout = EnsureLayout();
119
120 if (text().empty())
121 return SelectionModel(0, 0, SelectionModel::LEADING);
122
123 Point p(ToTextPoint(point));
124 int caret_pos, trailing;
125 pango_layout_xy_to_index(layout, p.x() * PANGO_SCALE, p.y() * PANGO_SCALE,
126 &caret_pos, &trailing);
127
128 size_t selection_end = caret_pos;
129 if (trailing > 0) {
130 const char* pango_text = pango_layout_get_text(layout);
131 const char* ch = g_utf8_offset_to_pointer(pango_text + caret_pos, trailing);
132 selection_end = ch - pango_text;
133 }
134
135 return SelectionModel(
136 Utf8IndexToUtf16Index(selection_end),
137 Utf8IndexToUtf16Index(caret_pos),
138 trailing > 0 ? SelectionModel::TRAILING : SelectionModel::LEADING);
139 }
140
141 Rect RenderTextLinux::GetCursorBounds(const SelectionModel& selection,
142 bool insert_mode) {
143 PangoLayout* layout = EnsureLayout();
144
145 size_t caret_pos = insert_mode ? selection.caret_pos() :
146 selection.selection_end();
147 PangoRectangle pos;
148 pango_layout_index_to_pos(layout, Utf16IndexToUtf8Index(caret_pos), &pos);
149
150 SelectionModel::CaretPlacement caret_placement = selection.caret_placement();
151 int x = pos.x;
152 if ((insert_mode && caret_placement == SelectionModel::TRAILING) ||
153 (!insert_mode && pos.width < 0))
154 x += pos.width;
155 x = x / PANGO_SCALE;
156
157 int h = std::min(display_rect().height(), pos.height/PANGO_SCALE);
msw 2011/08/23 08:01:01 spaces around '/' operator.
xji 2011/08/23 23:52:52 Done.
158 Rect bounds(x, (display_rect().height() - h) / 2, 0, h);
159 bounds.set_origin(ToViewPoint(bounds.origin()));
160
161 if (!insert_mode)
162 bounds.set_width(std::abs(pos.width));
163
164 return bounds;
165 }
166
167 SelectionModel RenderTextLinux::GetLeftSelectionModel(
168 const SelectionModel& current,
169 BreakType break_type) {
170 EnsureLayout();
171
172 if (break_type == LINE_BREAK || text().empty())
173 return LeftEndSelectionModel();
174 if (break_type == CHARACTER_BREAK)
175 return LeftSelectionModel(current);
176 // TODO(xji): not implemented yet.
177 return RenderText::GetLeftSelectionModel(current, break_type);
178 }
179
180 SelectionModel RenderTextLinux::GetRightSelectionModel(
181 const SelectionModel& current,
182 BreakType break_type) {
183 EnsureLayout();
184
185 if (break_type == LINE_BREAK || text().empty())
186 return RightEndSelectionModel();
187 if (break_type == CHARACTER_BREAK)
188 return RightSelectionModel(current);
189 // TODO(xji): not implemented yet.
190 return RenderText::GetRightSelectionModel(current, break_type);
191 }
192
193 size_t RenderTextLinux::GetIndexOfPreviousGrapheme(size_t position) {
194 EnsureLayout();
195 return Utf16IndexOfAdjacentGrapheme(position, PREVIOUS);
196 }
197
198 SelectionModel RenderTextLinux::LeftEndSelectionModel() {
199 if (GetTextDirection() == base::i18n::RIGHT_TO_LEFT) {
200 GSList* first_visual_run = layout_line_->runs;
201 if (first_visual_run) {
202 PangoItem* item =
203 reinterpret_cast<PangoLayoutRun*>(first_visual_run->data)->item;
204 if (item->analysis.level % 2 == 0) { // LTR.
205 size_t caret = Utf8IndexToUtf16Index(item->offset);
206 return SelectionModel(text().length(), caret, SelectionModel::LEADING);
207 } else { // RTL.
208 size_t caret = Utf8IndexToUtf16Index(item->offset + item->length);
209 caret = Utf16IndexOfAdjacentGrapheme(caret, PREVIOUS);
210 return SelectionModel(text().length(), caret, SelectionModel::TRAILING);
211 }
212 }
213 }
214 return SelectionModel(0, 0, SelectionModel::LEADING);
215 }
216
217 SelectionModel RenderTextLinux::RightEndSelectionModel() {
218 if (GetTextDirection() == base::i18n::LEFT_TO_RIGHT) {
219 GSList* last_visual_run = GetLastRun();
220 if (last_visual_run) {
221 PangoItem* item =
222 reinterpret_cast<PangoLayoutRun*>(last_visual_run->data)->item;
223 if (item->analysis.level % 2 == 0) { // LTR.
224 size_t caret = Utf8IndexToUtf16Index(item->offset + item->length);
225 caret = Utf16IndexOfAdjacentGrapheme(caret, PREVIOUS);
226 return SelectionModel(text().length(), caret, SelectionModel::TRAILING);
227 } else { // RTL.
228 size_t caret = Utf8IndexToUtf16Index(item->offset);
229 return SelectionModel(text().length(), caret, SelectionModel::LEADING);
230 }
231 }
232 }
233 return SelectionModel(0, 0, SelectionModel::LEADING);
234 }
235
236 GSList* RenderTextLinux::GetRunContainingPosition(size_t position) const {
237 GSList* run = layout_line_->runs;
238 while (run) {
239 PangoItem* box = reinterpret_cast<PangoLayoutRun*>(run->data)->item;
240 size_t run_start = Utf8IndexToUtf16Index(box->offset);
241 size_t run_end = Utf8IndexToUtf16Index(box->offset + box->length);
242
243 if (position >= run_start && position < run_end)
244 return run;
245 run = run->next;
246 }
247 return NULL;
248 }
249
250 size_t RenderTextLinux::Utf8IndexOfAdjacentGrapheme(
251 size_t utf16_index_of_current_grapheme,
252 RelativeLogicalPosition pos) const {
253 PangoLogAttr* log_attrs;
254 gint n_attrs;
255 pango_layout_get_log_attrs(layout_, &log_attrs, &n_attrs);
256
257 const char* layout_text = pango_layout_get_text(layout_);
258 const char* ch = layout_text +
259 Utf16IndexToUtf8Index(utf16_index_of_current_grapheme);
260 int char_offset = static_cast<int>(g_utf8_pointer_to_offset(layout_text, ch));
261
262 if (pos == PREVIOUS) {
263 if (ch > layout_text) {
264 do {
265 ch = g_utf8_find_prev_char(layout_text, ch);
266 --char_offset;
267 } while (ch && *ch && !log_attrs[char_offset].is_cursor_position);
268 if (!ch)
269 ch = layout_text;
270 }
271 } else {
272 if (ch < layout_text + strlen(layout_text)) {
273 do {
274 ch = g_utf8_find_next_char(ch, NULL);
275 ++char_offset;
276 } while (ch && *ch && !log_attrs[char_offset].is_cursor_position);
277 if (!ch || ch >= layout_text + strlen(layout_text))
278 ch = layout_text + strlen(layout_text);
279 }
280 }
281
282 size_t utf8_index = static_cast<size_t>(ch - layout_text);
283 g_free(log_attrs);
284 return utf8_index;
285 }
286
287 size_t RenderTextLinux::Utf16IndexOfAdjacentGrapheme(
288 size_t utf16_index_of_current_grapheme,
289 RelativeLogicalPosition pos) const {
290 size_t utf8_index = Utf8IndexOfAdjacentGrapheme(
291 utf16_index_of_current_grapheme, pos);
292 return Utf8IndexToUtf16Index(utf8_index);
293 }
294
295 SelectionModel RenderTextLinux::FirstSelectionModelInsideRun(
296 const PangoItem* run) const {
297 size_t caret = Utf8IndexToUtf16Index(run->offset);
298 size_t cursor = Utf16IndexOfAdjacentGrapheme(caret, NEXT);
299 return SelectionModel(cursor, caret, SelectionModel::TRAILING);
300 }
301
302 SelectionModel RenderTextLinux::LastSelectionModelInsideRun(
303 const PangoItem* run) const {
304 size_t caret = Utf8IndexToUtf16Index(run->offset + run->length);
305 caret = Utf16IndexOfAdjacentGrapheme(caret, PREVIOUS);
306 return SelectionModel(caret, caret, SelectionModel::LEADING);
307 }
308
309 // Assume caret_pos in |current| is n, 'l' represents leading in
310 // caret_placement and 't' represents trailing in caret_placement. Following
311 // is the calculation from (caret_pos, caret_placement) in |current| to
312 // (selection_end, caret_pos, caret_placement) when moving cursor left by
313 // one grapheme (for simplilcity, assume each grapheme is one character).
314 // If n is in LTR run,
315 // (n, t) ---> (n, n, l).
316 // (n, l) ---> (n-1, n-1, l) if n is inside run (not at boundary).
317 // (n, l) ---> goto across run case if n is at run boundary.
318 // If n is in RTL run,
319 // (n, l) --> (n+1, n, t).
320 // (n, t) --> (n+2, n+1, t) if n is inside run.
321 // (n, t) --> goto across run case if n is at run boundary.
322 // If n is at run boundary, get its visually left run,
323 // if left run is LTR run,
msw 2011/08/23 08:01:01 Capitalize "If"
xji 2011/08/23 23:52:52 Done.
324 // (n, t) --> (left run's end, left run's end, l).
325 // If rght run is RTL run,
msw 2011/08/23 08:01:01 Don't you mean left run?
xji 2011/08/23 23:52:52 yes. changed.
326 // (n, t) --> (left run's begin + 1, left run's begin, t).
327 SelectionModel RenderTextLinux::LeftSelectionModel(
328 const SelectionModel& selection) {
329 size_t caret = selection.caret_pos();
330 SelectionModel::CaretPlacement caret_placement = selection.caret_placement();
331 GSList* run = GetRunContainingPosition(caret);
332 DCHECK(run);
333
334 PangoItem* box = reinterpret_cast<PangoLayoutRun*>(run->data)->item;
335 size_t run_start = Utf8IndexToUtf16Index(box->offset);
336 size_t run_end = Utf8IndexToUtf16Index(box->offset + box->length);
337
338 if (box->analysis.level % 2 == 0) { // LTR run.
339 if (caret_placement == SelectionModel::TRAILING)
340 return SelectionModel(caret, caret, SelectionModel::LEADING);
341 else if (caret > run_start) {
342 caret = Utf16IndexOfAdjacentGrapheme(caret, PREVIOUS);
343 return SelectionModel(caret, caret, SelectionModel::LEADING);
344 }
345 } else { // RTL run.
346 if (caret_placement == SelectionModel::LEADING) {
347 size_t cursor = Utf16IndexOfAdjacentGrapheme(caret, NEXT);
348 return SelectionModel(cursor, caret, SelectionModel::TRAILING);
349 } else if (selection.selection_end() < run_end) {
350 caret = Utf16IndexOfAdjacentGrapheme(caret, NEXT);
351 size_t cursor = Utf16IndexOfAdjacentGrapheme(caret, NEXT);
352 return SelectionModel(cursor, caret, SelectionModel::TRAILING);
353 }
354 }
355
356 // The character is at the begin of its run; advance to the previous visual
357 // run.
358 GSList* prev_run = GetPreviousRun(run);
359 if (!prev_run) // TODO(xji): check whether this is expected.
360 return LeftEndSelectionModel();
361
362 box = reinterpret_cast<PangoLayoutRun*>(prev_run->data)->item;
363 return (box->analysis.level % 2) ? FirstSelectionModelInsideRun(box) :
364 LastSelectionModelInsideRun(box);
365 }
366
367 // Assume caret_pos in |current| is n, 'l' represents leading in
368 // caret_placement and 't' represents trailing in caret_placement. Following
369 // is the calculation from (caret_pos, caret_placement) in |current| to
370 // (selection_end, caret_pos, caret_placement) when moving cursor right by
371 // one grapheme (for simplilcity, assume each grapheme is one character).
372 // If n is in LTR run,
373 // (n, l) ---> (n+1, n, t).
374 // (n, t) ---> (n+2, n+1, t) if n is inside run (not at boundary).
375 // (n, t) ---> goto across run case if n is at run boundary.
376 // If n is in RTL run,
377 // (n, t) --> (n, n, l).
378 // (n, l) --> (n-1, n-1, l) if n is inside run.
379 // (n, l) --> goto across run case if n is at run boundary.
380 // If n is at run boundary, get its visually right run,
381 // if right run is LTR run,
msw 2011/08/23 08:01:01 Capitalize "If"
xji 2011/08/23 23:52:52 Done.
382 // (n, t) --> (right run's begin + 1, right run's begin, t).
383 // If rght run is RTL run,
msw 2011/08/23 08:01:01 r*i*ght
xji 2011/08/23 23:52:52 Done.
384 // (n, t) --> (right run's end, right run's end, l).
385 SelectionModel RenderTextLinux::RightSelectionModel(
386 const SelectionModel& selection) {
387 size_t caret = selection.caret_pos();
388 SelectionModel::CaretPlacement caret_placement = selection.caret_placement();
389 GSList* run = GetRunContainingPosition(caret);
390 DCHECK(run);
391
392 PangoItem* box = reinterpret_cast<PangoLayoutRun*>(run->data)->item;
393 size_t run_start = Utf8IndexToUtf16Index(box->offset);
394 size_t run_end = Utf8IndexToUtf16Index(box->offset + box->length);
395
396 if (box->analysis.level % 2 == 0) { // LTR run.
397 if (caret_placement == SelectionModel::LEADING) {
398 size_t cursor = Utf16IndexOfAdjacentGrapheme(caret, NEXT);
399 return SelectionModel(cursor, caret, SelectionModel::TRAILING);
400 } else if (selection.selection_end() < run_end) {
401 caret = Utf16IndexOfAdjacentGrapheme(caret, NEXT);
402 size_t cursor = Utf16IndexOfAdjacentGrapheme(caret, NEXT);
403 return SelectionModel(cursor, caret, SelectionModel::TRAILING);
404 }
405 } else { // RTL run.
406 if (caret_placement == SelectionModel::TRAILING)
407 return SelectionModel(caret, caret, SelectionModel::LEADING);
408 else if (caret > run_start)
409 return SelectionModel(caret - 1, caret - 1, SelectionModel::LEADING);
msw 2011/08/23 08:01:01 Do you mean to get Utf16IndexOfAdjacentGrapheme(ca
xji 2011/08/23 23:52:52 YES! thanks for catching it. Also,
msw 2011/08/24 08:55:30 Okay, then if the callers are trying to get the pr
xji 2011/08/25 03:15:18 To match the restrictions you added to selection m
410 }
411
412 // The character is at the end of its run; advance to the next visual run.
413 GSList* next_run = run->next;
414 if (!next_run) // TODO(xji): what is the expected behavior?
415 return RightEndSelectionModel();
416
417 box = reinterpret_cast<PangoLayoutRun*>(next_run->data)->item;
418 return (box->analysis.level % 2) ? LastSelectionModelInsideRun(box) :
419 FirstSelectionModelInsideRun(box);
420 }
421
422 PangoLayout* RenderTextLinux::EnsureLayout() {
423 if (layout_ == NULL) {
424 CanvasSkia canvas(display_rect().width(), display_rect().height(), false);
425 // TODO(xji): can use ScopedPlatformPaint ?
426 cairo_t* cr = skia::BeginPlatformPaint(&canvas);
427
428 layout_ = pango_cairo_create_layout(cr);
429 SetupPangoLayout(
430 layout_,
431 text(),
432 default_style().font,
433 display_rect().width(),
434 base::i18n::GetFirstStrongCharacterDirection(text()),
435 CanvasSkia::DefaultCanvasTextAlignment());
436
437 pango_layout_set_height(layout_, display_rect().height() * PANGO_SCALE);
438 SetupPangoAttributes(layout_);
439
440 skia::EndPlatformPaint(&canvas);
441
442 layout_line_ = pango_layout_get_line_readonly(layout_, 0);
443 pango_layout_line_ref(layout_line_);
444 }
445 return layout_;
446 }
447
448 void RenderTextLinux::ResetLayout() {
449 // set_cached_bounds_and_offset_valid(false) is done in RenderText for every
450 // operation that trigger ResetLayout().
451 if (layout_) {
452 g_object_unref(layout_);
453 layout_ = NULL;
454 }
455 if (layout_line_) {
456 pango_layout_line_unref(layout_line_);
457 layout_line_ = NULL;
458 }
459 }
460
461 void RenderTextLinux::SetupPangoAttributes(PangoLayout* layout) {
462 PangoAttrList* attrs = pango_attr_list_new();
463 // Set selection background color.
464 SkColor selection_color =
465 focused() ? kFocusedSelectionColor : kUnfocusedSelectionColor;
466 PangoAttribute* pango_attr = pango_attr_background_new(
467 COLOR_16_TO_32_BIT(SkColorGetR(selection_color)),
468 COLOR_16_TO_32_BIT(SkColorGetG(selection_color)),
469 COLOR_16_TO_32_BIT(SkColorGetB(selection_color)));
470 AppendPangoAttribute(MinOfSelection(), MaxOfSelection(),
471 pango_attr, attrs);
472
473 StyleRanges ranges_of_style(style_ranges());
474 ApplyCompositionAndSelectionStyles(&ranges_of_style);
475
476 for (StyleRanges::const_iterator i = ranges_of_style.begin();
477 i < ranges_of_style.end(); ++i) {
478 const Font& font = !i->underline ? i->font :
479 i->font.DeriveFont(0, i->font.GetStyle() | Font::UNDERLINED);
480 pango_attr = pango_attr_font_desc_new(
481 reinterpret_cast<PangoFontDescription*>(font.GetNativeFont()));
482 AppendPangoAttribute(i->range.start(), i->range.end(), pango_attr, attrs);
483
484 SkColor foreground = i->foreground;
485 pango_attr = pango_attr_foreground_new(
486 COLOR_16_TO_32_BIT(SkColorGetR(foreground)),
487 COLOR_16_TO_32_BIT(SkColorGetG(foreground)),
488 COLOR_16_TO_32_BIT(SkColorGetB(foreground)));
489 AppendPangoAttribute(i->range.start(), i->range.end(), pango_attr, attrs);
490
491 if (i->strike) {
492 pango_attr = pango_attr_strikethrough_new(true);
493 AppendPangoAttribute(i->range.start(), i->range.end(), pango_attr, attrs);
494 }
495 }
496
497 pango_layout_set_attributes(layout, attrs);
498 pango_attr_list_unref(attrs);
499 }
500
501 void RenderTextLinux::AppendPangoAttribute(size_t start,
502 size_t end,
503 PangoAttribute* pango_attr,
504 PangoAttrList* attrs) {
505 pango_attr->start_index = Utf16IndexToUtf8Index(start);
506 pango_attr->end_index = Utf16IndexToUtf8Index(end);
507 pango_attr_list_insert(attrs, pango_attr);
508 }
509
510 GSList* RenderTextLinux::GetPreviousRun(GSList* run) const {
511 GSList* current = layout_line_->runs;
512 GSList* prev = NULL;
513 while (current) {
514 if (current == run)
515 return prev;
516 prev = current;
517 current = current->next;
518 }
519 return NULL;
520 }
521
522 GSList* RenderTextLinux::GetLastRun() const {
523 GSList* current = layout_line_->runs;
524 while (current && current->next) {
525 current = current->next;
526 }
527 return current;
528 }
529
530 size_t RenderTextLinux::Utf16IndexToUtf8Index(size_t index) const {
531 int32_t utf8_index = 0;
532 int32_t num_of_substitions = 0;
533 UErrorCode ec = U_ZERO_ERROR;
534 u_strToUTF8WithSub(NULL, 0, &utf8_index, text().data(), index,
msw 2011/08/23 08:01:01 I'm worried by the potential performance losses in
xji 2011/08/23 23:52:52 I have the same concern. I checked with Markus who
markus.icu 2011/08/25 19:09:03 Well, I wrote and rewrote these functions :-) They
535 0xFFFD, &num_of_substitions, &ec);
536 return utf8_index;
msw 2011/08/23 08:01:01 I think you're supposed to check ec for U_FAILURE
xji 2011/08/23 23:52:52 From doc "If the input string is not well-formed,
msw 2011/08/24 08:55:30 Sounds like you should add a DCHECK_EQ(ec, U_ZERO_
xji 2011/08/25 03:15:18 Done.
537 }
538
539 size_t RenderTextLinux::Utf8IndexToUtf16Index(size_t index) const {
540 int32_t utf16_index = 0;
541 int32_t num_of_substitions = 0;
542 UErrorCode ec = U_ZERO_ERROR;
543 const char* layout_text = pango_layout_get_text(layout_);
544 u_strFromUTF8WithSub(NULL, 0, &utf16_index, layout_text, index,
545 0xFFFD, &num_of_substitions, &ec);
546 return utf16_index;
547 }
548
20 } // namespace gfx 549 } // namespace gfx
OLDNEW
« ui/gfx/render_text_linux.h ('K') | « ui/gfx/render_text_linux.h ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698