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

Unified Diff: ui/gfx/render_text_win.cc

Issue 8575020: Improve RenderTextWin font fallback. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src/
Patch Set: '' Created 9 years, 1 month 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 side-by-side diff with in-line comments
Download patch
Index: ui/gfx/render_text_win.cc
===================================================================
--- ui/gfx/render_text_win.cc (revision 112221)
+++ ui/gfx/render_text_win.cc (working copy)
@@ -291,10 +291,15 @@
EnsureLayout();
size_t cursor = base::i18n::IsRTL() ? text().length() : 0;
internal::TextRun* run = runs_[visual_to_logical_[0]];
- bool rtl = run->script_analysis.fRTL;
- size_t caret = rtl ? run->range.end() - 1 : run->range.start();
- SelectionModel::CaretPlacement placement =
- rtl ? SelectionModel::TRAILING : SelectionModel::LEADING;
+ size_t caret;
+ SelectionModel::CaretPlacement placement;
+ if (run->script_analysis.fRTL) {
+ caret = IndexOfAdjacentGrapheme(run->range.end(), false);
+ placement = SelectionModel::TRAILING;
+ } else {
+ caret = run->range.start();
+ placement = SelectionModel::LEADING;
+ }
return SelectionModel(cursor, caret, placement);
}
@@ -305,10 +310,15 @@
EnsureLayout();
size_t cursor = base::i18n::IsRTL() ? 0 : text().length();
internal::TextRun* run = runs_[visual_to_logical_[runs_.size() - 1]];
- bool rtl = run->script_analysis.fRTL;
- size_t caret = rtl ? run->range.start() : run->range.end() - 1;
- SelectionModel::CaretPlacement placement =
- rtl ? SelectionModel::LEADING : SelectionModel::TRAILING;
+ size_t caret;
+ SelectionModel::CaretPlacement placement;
+ if (run->script_analysis.fRTL) {
+ caret = run->range.start();
+ placement = SelectionModel::LEADING;
+ } else {
+ caret = IndexOfAdjacentGrapheme(run->range.end(), false);
+ placement = SelectionModel::TRAILING;
+ }
return SelectionModel(cursor, caret, placement);
}
@@ -461,21 +471,52 @@
size_t RenderTextWin::IndexOfAdjacentGrapheme(size_t index, bool next) {
EnsureLayout();
+
+ if (text().empty())
+ return 0;
+
+ if (index >= text().length()) {
+ if (next || index > text().length()) {
+ return text().length();
+ } else {
+ // If the requested |index| is past the end, use the index of the last
xji 2011/12/01 20:19:15 is the comment apply? till here, "index <= text()
Alexei Svitkine (slow) 2011/12/01 20:58:58 Good catch, the comment meant to say is "at the en
+ // character to find the grapheme.
+ index = text().length() - 1;
+ if (IsCursorablePosition(index))
+ return index;
+ }
+ }
+
size_t run_index = GetRunContainingPosition(index);
- internal::TextRun* run = run_index < runs_.size() ? runs_[run_index] : NULL;
- int start = run ? run->range.start() : 0;
- int length = run ? run->range.length() : text().length();
+ DCHECK(run_index < runs_.size());
+ internal::TextRun* run = runs_[run_index];
+ int start = run->range.start();
+ int length = run->range.length();
int ch = index - start;
- WORD cluster = run ? run->logical_clusters[ch] : 0;
+ WORD cluster = run->logical_clusters[ch];
if (!next) {
- do {
+ // If |ch| is the start of the run, use the preceding run, if any.
+ if (ch == 0) {
+ if (run_index == 0)
+ return 0;
+ run = runs_[run_index - 1];
+ start = run->range.start();
xji 2011/12/01 20:19:15 you did not seem to use the 'start'.
Alexei Svitkine (slow) 2011/12/01 20:58:58 It's used at the return point. Also, just keeping
+ length = run->range.length();
+ ch = length - 1;
+ } else if (run->logical_clusters[ch - 1] != run->logical_clusters[ch]) {
xji 2011/12/01 20:19:15 So, the old code does not handle 'ch==0' correctly
Alexei Svitkine (slow) 2011/12/01 20:58:58 Correct. This is covered by the unit test.
+ // If |ch| is at a grapheme boundary, use the previous grapheme.
ch--;
- } while (ch >= 0 && run && run->logical_clusters[ch] == cluster);
+ }
+
+ // Find the start of the grapheme.
+ while (ch > 0 && run->logical_clusters[ch - 1] == run->logical_clusters[ch])
xji 2011/12/01 20:19:15 Is the logic correct here? for example: ABCDE, wh
Alexei Svitkine (slow) 2011/12/01 20:58:58 Let me change your example to ABCD|e|f, since ABCD
xji 2011/12/01 22:56:06 Ah, my bad, mis-matched the index and its characte
+ ch--;
} else {
- while (ch < length && run && run->logical_clusters[ch] == cluster)
+ while (ch < length && run->logical_clusters[ch] == cluster)
ch++;
}
+
return std::max(std::min(ch, length) + start, 0);
}
@@ -545,6 +586,7 @@
internal::TextRun* run = *run_iter;
size_t run_length = run->range.length();
const wchar_t* run_text = &(text()[run->range.start()]);
+ bool tried_fallback = false;
// Select the font desired for glyph generation.
SelectObject(hdc, run->font.GetNativeFont());
@@ -569,12 +611,15 @@
if (hr == E_OUTOFMEMORY) {
max_glyphs *= 2;
} else if (hr == USP_E_SCRIPT_NOT_IN_FONT) {
- // TODO(msw): Don't use SCRIPT_UNDEFINED. Apparently Uniscribe can crash
- // on certain surrogate pairs with SCRIPT_UNDEFINED.
- // See https://bugzilla.mozilla.org/show_bug.cgi?id=341500
- // And http://maxradi.us/documents/uniscribe/
- if (run->script_analysis.eScript == SCRIPT_UNDEFINED)
- break;
+ // Only try font fallback if it hasn't yet been attempted for this run.
+ if (tried_fallback) {
+ // TODO(msw): Don't use SCRIPT_UNDEFINED. Apparently Uniscribe can
+ // crash on certain surrogate pairs with SCRIPT_UNDEFINED.
+ // See https://bugzilla.mozilla.org/show_bug.cgi?id=341500
+ // And http://maxradi.us/documents/uniscribe/
+ run->script_analysis.eScript = SCRIPT_UNDEFINED;
+ break;
+ }
// The run's font doesn't contain the required glyphs, use an alternate.
if (ChooseFallbackFont(hdc, run->font, run_text, run_length,
@@ -583,7 +628,7 @@
SelectObject(hdc, run->font.GetNativeFont());
}
- run->script_analysis.eScript = SCRIPT_UNDEFINED;
+ tried_fallback = true;
} else {
break;
}

Powered by Google App Engine
This is Rietveld 408576698