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

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