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

Side by Side 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: sync Created 9 years 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_win.h" 5 #include "ui/gfx/render_text_win.h"
6 6
7 #include <algorithm> 7 #include <algorithm>
8 8
9 #include "base/logging.h" 9 #include "base/logging.h"
10 #include "base/stl_util.h" 10 #include "base/stl_util.h"
(...skipping 341 matching lines...) Expand 10 before | Expand all | Expand 10 after
352 if (!bounds.empty() && rect.SharesEdgeWith(bounds.back())) { 352 if (!bounds.empty() && rect.SharesEdgeWith(bounds.back())) {
353 rect = rect.Union(bounds.back()); 353 rect = rect.Union(bounds.back());
354 bounds.pop_back(); 354 bounds.pop_back();
355 } 355 }
356 bounds.push_back(rect); 356 bounds.push_back(rect);
357 } 357 }
358 } 358 }
359 return bounds; 359 return bounds;
360 } 360 }
361 361
362 bool RenderTextWin::IsCursorablePosition(size_t position) { 362 bool RenderTextWin::IsCursorablePosition(size_t position, bool is_trailing) {
363 if (position == 0 || position == text().length()) 363 if (position == 0 || position == text().length())
364 return true; 364 return true;
365 365
366 size_t run_index = GetRunContainingPosition(position); 366 size_t run_index = GetRunContainingPosition(position);
367 if (run_index >= runs_.size()) 367 if (run_index >= runs_.size())
368 return false; 368 return false;
369 369
370 internal::TextRun* run = runs_[run_index]; 370 internal::TextRun* run = runs_[run_index];
371 if (is_trailing && !run->script_analysis.fRTL)
msw 2011/11/29 20:42:00 Shouldn't this be done before |GetRunContainingPos
372 position++;
371 size_t start = run->range.start(); 373 size_t start = run->range.start();
372 if (position == start) 374 if (position == start)
373 return true; 375 return true;
374 return run->logical_clusters[position - start] != 376 return run->logical_clusters[position - start] !=
375 run->logical_clusters[position - start - 1]; 377 run->logical_clusters[position - start - 1];
376 } 378 }
377 379
378 void RenderTextWin::UpdateLayout() { 380 void RenderTextWin::UpdateLayout() {
379 // TODO(msw): Skip complex processing if ScriptIsComplex returns false. 381 // TODO(msw): Skip complex processing if ScriptIsComplex returns false.
380 ItemizeLogicalText(); 382 ItemizeLogicalText();
(...skipping 78 matching lines...) Expand 10 before | Expand all | Expand 10 after
459 } 461 }
460 462
461 void RenderTextWin::LayoutVisualText() { 463 void RenderTextWin::LayoutVisualText() {
462 HRESULT hr = E_FAIL; 464 HRESULT hr = E_FAIL;
463 base::win::ScopedCreateDC hdc(CreateCompatibleDC(NULL)); 465 base::win::ScopedCreateDC hdc(CreateCompatibleDC(NULL));
464 std::vector<internal::TextRun*>::const_iterator run_iter; 466 std::vector<internal::TextRun*>::const_iterator run_iter;
465 for (run_iter = runs_.begin(); run_iter < runs_.end(); ++run_iter) { 467 for (run_iter = runs_.begin(); run_iter < runs_.end(); ++run_iter) {
466 internal::TextRun* run = *run_iter; 468 internal::TextRun* run = *run_iter;
467 size_t run_length = run->range.length(); 469 size_t run_length = run->range.length();
468 const wchar_t* run_text = &(text()[run->range.start()]); 470 const wchar_t* run_text = &(text()[run->range.start()]);
471 bool tried_fallback = false;
469 472
470 // Select the font desired for glyph generation. 473 // Select the font desired for glyph generation.
471 SelectObject(hdc, run->font.GetNativeFont()); 474 SelectObject(hdc, run->font.GetNativeFont());
472 475
473 run->logical_clusters.reset(new WORD[run_length]); 476 run->logical_clusters.reset(new WORD[run_length]);
474 run->glyph_count = 0; 477 run->glyph_count = 0;
475 // Max glyph guess: http://msdn.microsoft.com/en-us/library/dd368564.aspx 478 // Max glyph guess: http://msdn.microsoft.com/en-us/library/dd368564.aspx
476 size_t max_glyphs = static_cast<size_t>(1.5 * run_length + 16); 479 size_t max_glyphs = static_cast<size_t>(1.5 * run_length + 16);
477 while (max_glyphs < kMaxGlyphs) { 480 while (max_glyphs < kMaxGlyphs) {
478 run->glyphs.reset(new WORD[max_glyphs]); 481 run->glyphs.reset(new WORD[max_glyphs]);
479 run->visible_attributes.reset(new SCRIPT_VISATTR[max_glyphs]); 482 run->visible_attributes.reset(new SCRIPT_VISATTR[max_glyphs]);
480 hr = ScriptShape(hdc, 483 hr = ScriptShape(hdc,
481 &run->script_cache, 484 &run->script_cache,
482 run_text, 485 run_text,
483 run_length, 486 run_length,
484 max_glyphs, 487 max_glyphs,
485 &(run->script_analysis), 488 &(run->script_analysis),
486 run->glyphs.get(), 489 run->glyphs.get(),
487 run->logical_clusters.get(), 490 run->logical_clusters.get(),
488 run->visible_attributes.get(), 491 run->visible_attributes.get(),
489 &(run->glyph_count)); 492 &(run->glyph_count));
490 if (hr == E_OUTOFMEMORY) { 493 if (hr == E_OUTOFMEMORY) {
491 max_glyphs *= 2; 494 max_glyphs *= 2;
492 } else if (hr == USP_E_SCRIPT_NOT_IN_FONT) { 495 } else if (hr == USP_E_SCRIPT_NOT_IN_FONT) {
493 // TODO(msw): Don't use SCRIPT_UNDEFINED. Apparently Uniscribe can crash 496 // Only try font fallback if it hasn't yet been attempted for this run.
494 // on certain surrogate pairs with SCRIPT_UNDEFINED. 497 if (tried_fallback) {
495 // See https://bugzilla.mozilla.org/show_bug.cgi?id=341500 498 // TODO(msw): Don't use SCRIPT_UNDEFINED. Apparently Uniscribe can
496 // And http://maxradi.us/documents/uniscribe/ 499 // crash on certain surrogate pairs with SCRIPT_UNDEFINED.
497 if (run->script_analysis.eScript == SCRIPT_UNDEFINED) 500 // See https://bugzilla.mozilla.org/show_bug.cgi?id=341500
498 break; 501 // And http://maxradi.us/documents/uniscribe/
502 run->script_analysis.eScript = SCRIPT_UNDEFINED;
503 break;
504 }
499 505
500 // The run's font doesn't contain the required glyphs, use an alternate. 506 // The run's font doesn't contain the required glyphs, use an alternate.
501 if (ChooseFallbackFont(hdc, run->font, run_text, run_length, 507 if (ChooseFallbackFont(hdc, run->font, run_text, run_length,
502 &run->font)) { 508 &run->font)) {
503 ScriptFreeCache(&run->script_cache); 509 ScriptFreeCache(&run->script_cache);
504 SelectObject(hdc, run->font.GetNativeFont()); 510 SelectObject(hdc, run->font.GetNativeFont());
505 } 511 }
506 512
507 run->script_analysis.eScript = SCRIPT_UNDEFINED; 513 tried_fallback = true;
508 } else { 514 } else {
509 break; 515 break;
510 } 516 }
511 } 517 }
512 DCHECK(SUCCEEDED(hr)); 518 DCHECK(SUCCEEDED(hr));
513 519
514 if (run->glyph_count > 0) { 520 if (run->glyph_count > 0) {
515 run->advance_widths.reset(new int[run->glyph_count]); 521 run->advance_widths.reset(new int[run->glyph_count]);
516 run->offsets.reset(new GOFFSET[run->glyph_count]); 522 run->offsets.reset(new GOFFSET[run->glyph_count]);
517 hr = ScriptPlace(hdc, 523 hr = ScriptPlace(hdc,
(...skipping 216 matching lines...) Expand 10 before | Expand all | Expand 10 after
734 Rect r(GetUpdatedCursorBounds()); 740 Rect r(GetUpdatedCursorBounds());
735 canvas->DrawRectInt(kCursorColor, r.x(), r.y(), r.width(), r.height()); 741 canvas->DrawRectInt(kCursorColor, r.x(), r.y(), r.width(), r.height());
736 } 742 }
737 } 743 }
738 744
739 RenderText* RenderText::CreateRenderText() { 745 RenderText* RenderText::CreateRenderText() {
740 return new RenderTextWin; 746 return new RenderTextWin;
741 } 747 }
742 748
743 } // namespace gfx 749 } // namespace gfx
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698