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

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: update comment about u_strToUTF8, exclude pango_util from win/mac Created 9 years, 3 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
« no previous file with comments | « ui/gfx/render_text_linux.h ('k') | ui/ui.gyp » ('j') | 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
9 #include <algorithm>
10
11 #include "base/logging.h"
12 #include "ui/gfx/canvas_skia.h"
13 #include "ui/gfx/pango_util.h"
14 #include "unicode/uchar.h"
15 #include "unicode/ustring.h"
16
17 namespace {
18
19 // TODO(xji): instead of converting each R or G or B from 8-bit to 16-bit,
20 // it should also massage A in the conversion.
21 int ConvertColorFrom8BitTo16Bit(int c) {
22 return c * (0xffff / 0xff);
markus.icu 2011/08/25 19:09:05 return c << 8;
xji 2011/08/25 19:22:19 changed to (c << 8 ) + c; Behdad suggested the sa
23 }
24
25 }
26
27 // TODO(xji): index saved in upper layer is utf16 index. Pango uses utf8 index.
28 // Since caret_pos is used internally, we could save utf8 index for caret_pos
29 // to avoid conversion.
30
7 namespace gfx { 31 namespace gfx {
8 32
9 RenderTextLinux::RenderTextLinux() 33 RenderTextLinux::RenderTextLinux()
10 : RenderText() { 34 : layout_(NULL),
35 layout_line_(NULL) {
11 } 36 }
12 37
13 RenderTextLinux::~RenderTextLinux() { 38 RenderTextLinux::~RenderTextLinux() {
39 ResetLayout();
14 } 40 }
15 41
16 RenderText* RenderText::CreateRenderText() { 42 RenderText* RenderText::CreateRenderText() {
17 return new RenderTextLinux; 43 return new RenderTextLinux;
18 } 44 }
19 45
46 void RenderTextLinux::SetText(const string16& text) {
47 RenderText::SetText(text);
48 ResetLayout();
49 }
50
51 void RenderTextLinux::SetDisplayRect(const Rect&r) {
52 RenderText::SetDisplayRect(r);
53 ResetLayout();
54 }
55
56 void RenderTextLinux::SetCompositionRange(const ui::Range& composition_range) {
57 RenderText::SetCompositionRange(composition_range);
58 ResetLayout();
59 }
60
61 void RenderTextLinux::ApplyStyleRange(StyleRange style_range) {
62 RenderText::ApplyStyleRange(style_range);
63 ResetLayout();
64 }
65
66 void RenderTextLinux::ApplyDefaultStyle() {
67 RenderText::ApplyDefaultStyle();
68 ResetLayout();
69 }
70
71 base::i18n::TextDirection RenderTextLinux::GetTextDirection() {
72 EnsureLayout();
73
74 const char* layout_text = pango_layout_get_text(layout_);
75 PangoDirection base_dir =
76 pango_find_base_dir(layout_text, strlen(layout_text));
77 if (base_dir == PANGO_DIRECTION_RTL || base_dir == PANGO_DIRECTION_WEAK_RTL)
78 return base::i18n::RIGHT_TO_LEFT;
79 return base::i18n::LEFT_TO_RIGHT;
80 }
81
82 int RenderTextLinux::GetStringWidth() {
83 PangoLayout* layout = EnsureLayout();
84 int width, height;
85 pango_layout_get_pixel_size(layout, &width, &height);
86 return width;
87 }
88
89 void RenderTextLinux::Draw(Canvas* canvas) {
90 PangoLayout* layout = EnsureLayout();
91 Rect bounds(display_rect());
92
93 // Clip the canvas to the text display area.
94 CanvasSkia* canvas_skia = canvas->AsCanvasSkia();
95 canvas_skia->ClipRectInt(
96 bounds.x(), bounds.y(), bounds.width(), bounds.height());
97
98 // TODO(xji): use ScopedPlatformPaint.
99 cairo_t* cr = skia::BeginPlatformPaint(canvas_skia);
100 cairo_save(cr);
101 cairo_rectangle(cr, bounds.x(), bounds.y(), bounds.width(), bounds.height());
102 cairo_clip(cr);
103
104 int text_width, text_height;
105 pango_layout_get_pixel_size(layout, &text_width, &text_height);
106 Point offset(ToViewPoint(Point()));
107 // Vertically centered.
108 int text_y = offset.y() + ((bounds.height() - text_height) / 2);
109 cairo_move_to(cr, offset.x(), text_y);
110 pango_cairo_show_layout(cr, layout);
111
112 // Destructor.
113 cairo_restore(cr);
114 skia::EndPlatformPaint(canvas_skia);
115
116 // Paint cursor.
117 bounds = GetUpdatedCursorBounds();
118 if (cursor_visible() && focused() && !bounds.IsEmpty()) {
119 if (!bounds.IsEmpty())
120 canvas->DrawRectInt(kCursorColor,
121 bounds.x(),
122 bounds.y(),
123 bounds.width(),
124 bounds.height());
125 }
126 }
127
128 SelectionModel RenderTextLinux::FindCursorPosition(const Point& point) {
129 // TODO(xji): when points outside of text, return HOME/END position.
130 PangoLayout* layout = EnsureLayout();
131
132 if (text().empty())
133 return SelectionModel(0, 0, SelectionModel::LEADING);
134
135 Point p(ToTextPoint(point));
136 int caret_pos, trailing;
137 pango_layout_xy_to_index(layout, p.x() * PANGO_SCALE, p.y() * PANGO_SCALE,
138 &caret_pos, &trailing);
139
140 size_t selection_end = caret_pos;
141 if (trailing > 0) {
142 const char* pango_text = pango_layout_get_text(layout);
143 const char* ch = g_utf8_offset_to_pointer(pango_text + caret_pos, trailing);
144 selection_end = ch - pango_text;
145 }
146
147 return SelectionModel(
148 Utf8IndexToUtf16Index(selection_end),
149 Utf8IndexToUtf16Index(caret_pos),
150 trailing > 0 ? SelectionModel::TRAILING : SelectionModel::LEADING);
151 }
152
153 Rect RenderTextLinux::GetCursorBounds(const SelectionModel& selection,
154 bool insert_mode) {
155 PangoLayout* layout = EnsureLayout();
156
157 size_t caret_pos = insert_mode ? selection.caret_pos() :
158 selection.selection_end();
159 PangoRectangle pos;
160 pango_layout_index_to_pos(layout, Utf16IndexToUtf8Index(caret_pos), &pos);
161
162 SelectionModel::CaretPlacement caret_placement = selection.caret_placement();
163 int x = pos.x;
164 if ((insert_mode && caret_placement == SelectionModel::TRAILING) ||
165 (!insert_mode && pos.width < 0))
166 x += pos.width;
167 x = x / PANGO_SCALE;
168
169 int h = std::min(display_rect().height(), pos.height / PANGO_SCALE);
170 Rect bounds(x, (display_rect().height() - h) / 2, 0, h);
171 bounds.set_origin(ToViewPoint(bounds.origin()));
172
173 if (!insert_mode)
174 bounds.set_width(std::abs(pos.width));
175
176 return bounds;
177 }
178
179 SelectionModel RenderTextLinux::GetLeftSelectionModel(
180 const SelectionModel& current,
181 BreakType break_type) {
182 EnsureLayout();
183
184 if (break_type == LINE_BREAK || text().empty())
185 return LeftEndSelectionModel();
186 if (break_type == CHARACTER_BREAK)
187 return LeftSelectionModel(current);
188 // TODO(xji): not implemented yet.
189 return RenderText::GetLeftSelectionModel(current, break_type);
190 }
191
192 SelectionModel RenderTextLinux::GetRightSelectionModel(
193 const SelectionModel& current,
194 BreakType break_type) {
195 EnsureLayout();
196
197 if (break_type == LINE_BREAK || text().empty())
198 return RightEndSelectionModel();
199 if (break_type == CHARACTER_BREAK)
200 return RightSelectionModel(current);
201 // TODO(xji): not implemented yet.
202 return RenderText::GetRightSelectionModel(current, break_type);
203 }
204
205 size_t RenderTextLinux::GetIndexOfPreviousGrapheme(size_t position) {
206 EnsureLayout();
207 return Utf16IndexOfAdjacentGrapheme(position, PREVIOUS);
208 }
209
210 SelectionModel RenderTextLinux::LeftEndSelectionModel() {
211 if (GetTextDirection() == base::i18n::RIGHT_TO_LEFT) {
212 GSList* first_visual_run = layout_line_->runs;
213 if (first_visual_run) {
214 PangoItem* item =
215 reinterpret_cast<PangoLayoutRun*>(first_visual_run->data)->item;
216 if (item->analysis.level % 2 == 0) { // LTR.
217 size_t caret = Utf8IndexToUtf16Index(item->offset);
218 return SelectionModel(text().length(), caret, SelectionModel::LEADING);
219 } else { // RTL.
220 size_t caret = Utf8IndexToUtf16Index(item->offset + item->length);
221 caret = Utf16IndexOfAdjacentGrapheme(caret, PREVIOUS);
222 return SelectionModel(text().length(), caret, SelectionModel::TRAILING);
223 }
224 }
225 }
226 return SelectionModel(0, 0, SelectionModel::LEADING);
227 }
228
229 SelectionModel RenderTextLinux::RightEndSelectionModel() {
230 if (GetTextDirection() == base::i18n::LEFT_TO_RIGHT) {
231 GSList* last_visual_run = GetLastRun();
232 if (last_visual_run) {
233 PangoItem* item =
234 reinterpret_cast<PangoLayoutRun*>(last_visual_run->data)->item;
235 if (item->analysis.level % 2 == 0) { // LTR.
236 size_t caret = Utf8IndexToUtf16Index(item->offset + item->length);
237 caret = Utf16IndexOfAdjacentGrapheme(caret, PREVIOUS);
238 return SelectionModel(text().length(), caret, SelectionModel::TRAILING);
239 } else { // RTL.
240 size_t caret = Utf8IndexToUtf16Index(item->offset);
241 return SelectionModel(text().length(), caret, SelectionModel::LEADING);
242 }
243 }
244 }
245 return SelectionModel(0, 0, SelectionModel::LEADING);
246 }
247
248 GSList* RenderTextLinux::GetRunContainingPosition(size_t position) const {
249 GSList* run = layout_line_->runs;
250 while (run) {
251 PangoItem* box = reinterpret_cast<PangoLayoutRun*>(run->data)->item;
252 size_t run_start = Utf8IndexToUtf16Index(box->offset);
253 size_t run_end = Utf8IndexToUtf16Index(box->offset + box->length);
254
255 if (position >= run_start && position < run_end)
256 return run;
257 run = run->next;
258 }
259 return NULL;
260 }
261
262 size_t RenderTextLinux::Utf8IndexOfAdjacentGrapheme(
263 size_t utf16_index_of_current_grapheme,
264 RelativeLogicalPosition pos) const {
265 PangoLogAttr* log_attrs;
266 gint n_attrs;
267 pango_layout_get_log_attrs(layout_, &log_attrs, &n_attrs);
268
269 const char* layout_text = pango_layout_get_text(layout_);
270 const char* ch = layout_text +
271 Utf16IndexToUtf8Index(utf16_index_of_current_grapheme);
272 int char_offset = static_cast<int>(g_utf8_pointer_to_offset(layout_text, ch));
273
274 if (pos == PREVIOUS) {
275 if (ch > layout_text) {
276 do {
277 ch = g_utf8_find_prev_char(layout_text, ch);
278 --char_offset;
279 } while (ch && *ch && !log_attrs[char_offset].is_cursor_position);
280 if (!ch)
281 ch = layout_text;
282 }
283 } else {
284 if (ch < layout_text + strlen(layout_text)) {
285 do {
286 ch = g_utf8_find_next_char(ch, NULL);
287 ++char_offset;
288 } while (ch && *ch && !log_attrs[char_offset].is_cursor_position);
289 if (!ch || ch >= layout_text + strlen(layout_text))
290 ch = layout_text + strlen(layout_text);
291 }
292 }
293
294 size_t utf8_index = static_cast<size_t>(ch - layout_text);
295 g_free(log_attrs);
296 return utf8_index;
297 }
298
299 size_t RenderTextLinux::Utf16IndexOfAdjacentGrapheme(
300 size_t utf16_index_of_current_grapheme,
301 RelativeLogicalPosition pos) const {
302 size_t utf8_index = Utf8IndexOfAdjacentGrapheme(
303 utf16_index_of_current_grapheme, pos);
304 return Utf8IndexToUtf16Index(utf8_index);
305 }
306
307 SelectionModel RenderTextLinux::FirstSelectionModelInsideRun(
308 const PangoItem* run) const {
309 size_t caret = Utf8IndexToUtf16Index(run->offset);
310 size_t cursor = Utf16IndexOfAdjacentGrapheme(caret, NEXT);
311 return SelectionModel(cursor, caret, SelectionModel::TRAILING);
312 }
313
314 SelectionModel RenderTextLinux::LastSelectionModelInsideRun(
315 const PangoItem* run) const {
316 size_t caret = Utf8IndexToUtf16Index(run->offset + run->length);
317 caret = Utf16IndexOfAdjacentGrapheme(caret, PREVIOUS);
318 return SelectionModel(caret, caret, SelectionModel::LEADING);
319 }
320
321 // Assume caret_pos in |current| is n, 'l' represents leading in
322 // caret_placement and 't' represents trailing in caret_placement. Following
323 // is the calculation from (caret_pos, caret_placement) in |current| to
324 // (selection_end, caret_pos, caret_placement) when moving cursor left by
325 // one grapheme (for simplicity, assume each grapheme is one character).
326 // If n is in LTR run,
327 // (n, t) ---> (n, n, l).
328 // (n, l) ---> (n-1, n-1, l) if n is inside run (not at boundary).
329 // (n, l) ---> goto across run case if n is at run boundary.
330 // If n is in RTL run,
331 // (n, l) --> (n+1, n, t).
332 // (n, t) --> (n+2, n+1, t) if n is inside run.
333 // (n, t) --> goto across run case if n is at run boundary.
334 // If n is at run boundary, get its visually left run,
335 // If left run is LTR run,
336 // (n, t) --> (left run's end, left run's end, l).
337 // If left run is RTL run,
338 // (n, t) --> (left run's begin + 1, left run's begin, t).
339 SelectionModel RenderTextLinux::LeftSelectionModel(
340 const SelectionModel& selection) {
341 size_t caret = selection.caret_pos();
342 SelectionModel::CaretPlacement caret_placement = selection.caret_placement();
343 GSList* run = GetRunContainingPosition(caret);
344 DCHECK(run);
345
346 PangoItem* box = reinterpret_cast<PangoLayoutRun*>(run->data)->item;
347 size_t run_start = Utf8IndexToUtf16Index(box->offset);
348 size_t run_end = Utf8IndexToUtf16Index(box->offset + box->length);
349
350 if (box->analysis.level % 2 == 0) { // LTR run.
351 if (caret_placement == SelectionModel::TRAILING)
352 return SelectionModel(caret, caret, SelectionModel::LEADING);
353 else if (caret > run_start) {
354 caret = Utf16IndexOfAdjacentGrapheme(caret, PREVIOUS);
355 return SelectionModel(caret, caret, SelectionModel::LEADING);
356 }
357 } else { // RTL run.
358 if (caret_placement == SelectionModel::LEADING) {
359 size_t cursor = Utf16IndexOfAdjacentGrapheme(caret, NEXT);
360 return SelectionModel(cursor, caret, SelectionModel::TRAILING);
361 } else if (selection.selection_end() < run_end) {
362 caret = Utf16IndexOfAdjacentGrapheme(caret, NEXT);
363 size_t cursor = Utf16IndexOfAdjacentGrapheme(caret, NEXT);
364 return SelectionModel(cursor, caret, SelectionModel::TRAILING);
365 }
366 }
367
368 // The character is at the begin of its run; advance to the previous visual
369 // run.
370 GSList* prev_run = GetPreviousRun(run);
371 if (!prev_run) // TODO(xji): check whether this is expected.
372 return LeftEndSelectionModel();
373
374 box = reinterpret_cast<PangoLayoutRun*>(prev_run->data)->item;
375 return (box->analysis.level % 2) ? FirstSelectionModelInsideRun(box) :
376 LastSelectionModelInsideRun(box);
377 }
378
379 // Assume caret_pos in |current| is n, 'l' represents leading in
380 // caret_placement and 't' represents trailing in caret_placement. Following
381 // is the calculation from (caret_pos, caret_placement) in |current| to
382 // (selection_end, caret_pos, caret_placement) when moving cursor right by
383 // one grapheme (for simplicity, assume each grapheme is one character).
384 // If n is in LTR run,
385 // (n, l) ---> (n+1, n, t).
386 // (n, t) ---> (n+2, n+1, t) if n is inside run (not at boundary).
387 // (n, t) ---> goto across run case if n is at run boundary.
388 // If n is in RTL run,
389 // (n, t) --> (n, n, l).
390 // (n, l) --> (n-1, n-1, l) if n is inside run.
391 // (n, l) --> goto across run case if n is at run boundary.
392 // If n is at run boundary, get its visually right run,
393 // If right run is LTR run,
394 // (n, t) --> (right run's begin + 1, right run's begin, t).
395 // If right run is RTL run,
396 // (n, t) --> (right run's end, right run's end, l).
397 SelectionModel RenderTextLinux::RightSelectionModel(
398 const SelectionModel& selection) {
399 size_t caret = selection.caret_pos();
400 SelectionModel::CaretPlacement caret_placement = selection.caret_placement();
401 GSList* run = GetRunContainingPosition(caret);
402 DCHECK(run);
403
404 PangoItem* box = reinterpret_cast<PangoLayoutRun*>(run->data)->item;
405 size_t run_start = Utf8IndexToUtf16Index(box->offset);
406 size_t run_end = Utf8IndexToUtf16Index(box->offset + box->length);
407
408 if (box->analysis.level % 2 == 0) { // LTR run.
409 if (caret_placement == SelectionModel::LEADING) {
410 size_t cursor = Utf16IndexOfAdjacentGrapheme(caret, NEXT);
411 return SelectionModel(cursor, caret, SelectionModel::TRAILING);
412 } else if (selection.selection_end() < run_end) {
413 caret = Utf16IndexOfAdjacentGrapheme(caret, NEXT);
414 size_t cursor = Utf16IndexOfAdjacentGrapheme(caret, NEXT);
415 return SelectionModel(cursor, caret, SelectionModel::TRAILING);
416 }
417 } else { // RTL run.
418 if (caret_placement == SelectionModel::TRAILING)
419 return SelectionModel(caret, caret, SelectionModel::LEADING);
420 else if (caret > run_start) {
421 caret = Utf16IndexOfAdjacentGrapheme(caret, PREVIOUS);
422 return SelectionModel(caret, caret, SelectionModel::LEADING);
423 }
424 }
425
426 // The character is at the end of its run; advance to the next visual run.
427 GSList* next_run = run->next;
428 if (!next_run) // TODO(xji): what is the expected behavior?
429 return RightEndSelectionModel();
430
431 box = reinterpret_cast<PangoLayoutRun*>(next_run->data)->item;
432 return (box->analysis.level % 2) ? LastSelectionModelInsideRun(box) :
433 FirstSelectionModelInsideRun(box);
434 }
435
436 PangoLayout* RenderTextLinux::EnsureLayout() {
437 if (layout_ == NULL) {
438 CanvasSkia canvas(display_rect().width(), display_rect().height(), false);
439 // TODO(xji): can use ScopedPlatformPaint ?
440 cairo_t* cr = skia::BeginPlatformPaint(&canvas);
441
442 layout_ = pango_cairo_create_layout(cr);
443 SetupPangoLayout(
444 layout_,
445 text(),
446 default_style().font,
447 display_rect().width(),
448 base::i18n::GetFirstStrongCharacterDirection(text()),
449 CanvasSkia::DefaultCanvasTextAlignment());
450
451 pango_layout_set_height(layout_, display_rect().height() * PANGO_SCALE);
452 SetupPangoAttributes(layout_);
453
454 skia::EndPlatformPaint(&canvas);
455
456 layout_line_ = pango_layout_get_line_readonly(layout_, 0);
457 pango_layout_line_ref(layout_line_);
458 }
459 return layout_;
460 }
461
462 void RenderTextLinux::ResetLayout() {
463 // set_cached_bounds_and_offset_valid(false) is done in RenderText for every
464 // operation that trigger ResetLayout().
465 if (layout_) {
466 g_object_unref(layout_);
467 layout_ = NULL;
468 }
469 if (layout_line_) {
470 pango_layout_line_unref(layout_line_);
471 layout_line_ = NULL;
472 }
473 }
474
475 void RenderTextLinux::SetupPangoAttributes(PangoLayout* layout) {
476 PangoAttrList* attrs = pango_attr_list_new();
477 // Set selection background color.
478 SkColor selection_color =
479 focused() ? kFocusedSelectionColor : kUnfocusedSelectionColor;
480 size_t start = std::min(MinOfSelection(), text().length());
481 size_t end = std::min(MaxOfSelection(), text().length());
482 PangoAttribute* pango_attr;
483 if (end > start) {
484 pango_attr = pango_attr_background_new(
485 ConvertColorFrom8BitTo16Bit(SkColorGetR(selection_color)),
486 ConvertColorFrom8BitTo16Bit(SkColorGetG(selection_color)),
487 ConvertColorFrom8BitTo16Bit(SkColorGetB(selection_color)));
488 AppendPangoAttribute(start, end, pango_attr, attrs);
489 }
490
491 StyleRanges ranges_of_style(style_ranges());
492 ApplyCompositionAndSelectionStyles(&ranges_of_style);
493
494 for (StyleRanges::const_iterator i = ranges_of_style.begin();
495 i < ranges_of_style.end(); ++i) {
496 start = std::min(i->range.start(), text().length());
497 end = std::min(i->range.end(), text().length());
498 if (start >= end)
499 continue;
500
501 const Font& font = !i->underline ? i->font :
502 i->font.DeriveFont(0, i->font.GetStyle() | Font::UNDERLINED);
503 PangoFontDescription* desc = font.GetNativeFont();
504 pango_attr = pango_attr_font_desc_new(desc);
505 AppendPangoAttribute(start, end, pango_attr, attrs);
506 pango_font_description_free(desc);
507
508 SkColor foreground = i->foreground;
509 pango_attr = pango_attr_foreground_new(
510 ConvertColorFrom8BitTo16Bit(SkColorGetR(foreground)),
511 ConvertColorFrom8BitTo16Bit(SkColorGetG(foreground)),
512 ConvertColorFrom8BitTo16Bit(SkColorGetB(foreground)));
513 AppendPangoAttribute(start, end, pango_attr, attrs);
514
515 if (i->strike) {
516 pango_attr = pango_attr_strikethrough_new(true);
517 AppendPangoAttribute(start, end, pango_attr, attrs);
518 }
519 }
520
521 pango_layout_set_attributes(layout, attrs);
522 pango_attr_list_unref(attrs);
523 }
524
525 void RenderTextLinux::AppendPangoAttribute(size_t start,
526 size_t end,
527 PangoAttribute* pango_attr,
528 PangoAttrList* attrs) {
529 pango_attr->start_index = Utf16IndexToUtf8Index(start);
530 size_t e = std::min(end, text().length());
531 pango_attr->end_index = Utf16IndexToUtf8Index(e);
532 pango_attr_list_insert(attrs, pango_attr);
533 }
534
535 GSList* RenderTextLinux::GetPreviousRun(GSList* run) const {
536 GSList* current = layout_line_->runs;
537 GSList* prev = NULL;
538 while (current) {
539 if (current == run)
540 return prev;
541 prev = current;
542 current = current->next;
543 }
544 return NULL;
545 }
546
547 GSList* RenderTextLinux::GetLastRun() const {
548 GSList* current = layout_line_->runs;
549 while (current && current->next) {
550 current = current->next;
551 }
552 return current;
553 }
554
555 size_t RenderTextLinux::Utf16IndexToUtf8Index(size_t index) const {
556 int32_t utf8_index = 0;
557 UErrorCode ec = U_ZERO_ERROR;
558 u_strToUTF8(NULL, 0, &utf8_index, text().data(), index, &ec);
559 // Even given a desination buffer as NULL and destination capacity as 0,
markus.icu 2011/08/25 19:09:05 destination (one t is missing)
xji 2011/08/25 19:22:19 Done.
560 // if the output length is equal to or greater than the capacity, then the
561 // UErrorCode is set to U_STRING_NOT_TERMINATED_WARNING or
562 // U_BUFFER_OVERFLOW_ERROR respectively.
563 // Please refer to
564 // http://userguide.icu-project.org/strings#TOC-Using-C-Strings:-NUL-Terminate d-vs
565 // for detail (search for "Note that" below "Preflighting").
566 DCHECK(ec != U_INVALID_CHAR_FOUND);
markus.icu 2011/08/25 19:09:05 DCHECK(ec == U_BUFFER_OVERFLOW_ERROR || ec == U_ST
xji 2011/08/25 19:22:19 Done.
567 return utf8_index;
568 }
569
570 size_t RenderTextLinux::Utf8IndexToUtf16Index(size_t index) const {
571 int32_t utf16_index = 0;
572 UErrorCode ec = U_ZERO_ERROR;
573 const char* layout_text = pango_layout_get_text(layout_);
574 u_strFromUTF8(NULL, 0, &utf16_index, layout_text, index, &ec);
575 DCHECK(ec != U_INVALID_CHAR_FOUND);
markus.icu 2011/08/25 19:09:05 ditto
xji 2011/08/25 19:22:19 Done.
576 return utf16_index;
577 }
578
20 } // namespace gfx 579 } // namespace gfx
OLDNEW
« no previous file with comments | « ui/gfx/render_text_linux.h ('k') | ui/ui.gyp » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698