Chromium Code Reviews| OLD | NEW |
|---|---|
| 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 Loading... | |
| 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 Loading... | |
| 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 Loading... | |
| 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 |
| OLD | NEW |