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

Side by Side Diff: ui/gfx/render_text_win.cc

Issue 10315007: Detect missing glyphs as returned by Vista in RenderTextWin. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src/
Patch Set: Created 8 years, 7 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
« ui/gfx/render_text_win.h ('K') | « ui/gfx/render_text_win.h ('k') | no next file » | 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) 2012 The Chromium Authors. All rights reserved. 1 // Copyright (c) 2012 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/i18n/break_iterator.h" 9 #include "base/i18n/break_iterator.h"
10 #include "base/logging.h" 10 #include "base/logging.h"
(...skipping 589 matching lines...) Expand 10 before | Expand all | Expand 10 after
600 void RenderTextWin::LayoutVisualText() { 600 void RenderTextWin::LayoutVisualText() {
601 DCHECK(!runs_.empty()); 601 DCHECK(!runs_.empty());
602 602
603 if (!cached_hdc_) 603 if (!cached_hdc_)
604 cached_hdc_ = CreateCompatibleDC(NULL); 604 cached_hdc_ = CreateCompatibleDC(NULL);
605 605
606 HRESULT hr = E_FAIL; 606 HRESULT hr = E_FAIL;
607 string_size_.set_height(0); 607 string_size_.set_height(0);
608 for (size_t i = 0; i < runs_.size(); ++i) { 608 for (size_t i = 0; i < runs_.size(); ++i) {
609 internal::TextRun* run = runs_[i]; 609 internal::TextRun* run = runs_[i];
610 size_t run_length = run->range.length(); 610 const size_t run_length = run->range.length();
611 const wchar_t* run_text = &(text()[run->range.start()]); 611 const wchar_t* run_text = &(text()[run->range.start()]);
612 bool tried_fallback = false; 612 bool tried_fallback = false;
613 size_t linked_font_index = 0; 613 size_t linked_font_index = 0;
614 const std::vector<Font>* linked_fonts = NULL; 614 const std::vector<Font>* linked_fonts = NULL;
615 Font original_font = run->font; 615 Font original_font = run->font;
616 616
617 // Select the font desired for glyph generation. 617 // Select the font desired for glyph generation.
618 SelectObject(cached_hdc_, run->font.GetNativeFont()); 618 SelectObject(cached_hdc_, run->font.GetNativeFont());
619 619
620 SCRIPT_FONTPROPERTIES properties;
621 memset(&properties, 0, sizeof(properties));
622 properties.cBytes = sizeof(properties);
623
624 run->logical_clusters.reset(new WORD[run_length]); 620 run->logical_clusters.reset(new WORD[run_length]);
625 run->glyph_count = 0; 621 run->glyph_count = 0;
626 // Max glyph guess: http://msdn.microsoft.com/en-us/library/dd368564.aspx 622 // Max glyph guess: http://msdn.microsoft.com/en-us/library/dd368564.aspx
627 size_t max_glyphs = static_cast<size_t>(1.5 * run_length + 16); 623 size_t max_glyphs = static_cast<size_t>(1.5 * run_length + 16);
628 while (max_glyphs < kMaxGlyphs) { 624 while (max_glyphs < kMaxGlyphs) {
629 bool glyphs_missing = false; 625 bool glyphs_missing = false;
msw 2012/05/03 17:33:34 nit: move this down to usage; optionally nix and j
Alexei Svitkine (slow) 2012/05/03 17:47:50 Done.
630 run->glyphs.reset(new WORD[max_glyphs]); 626 run->glyphs.reset(new WORD[max_glyphs]);
631 run->visible_attributes.reset(new SCRIPT_VISATTR[max_glyphs]); 627 run->visible_attributes.reset(new SCRIPT_VISATTR[max_glyphs]);
632 hr = ScriptShape(cached_hdc_, 628 hr = ScriptShape(cached_hdc_,
633 &run->script_cache, 629 &run->script_cache,
634 run_text, 630 run_text,
635 run_length, 631 run_length,
636 max_glyphs, 632 max_glyphs,
637 &(run->script_analysis), 633 &(run->script_analysis),
638 run->glyphs.get(), 634 run->glyphs.get(),
639 run->logical_clusters.get(), 635 run->logical_clusters.get(),
640 run->visible_attributes.get(), 636 run->visible_attributes.get(),
641 &(run->glyph_count)); 637 &(run->glyph_count));
642 if (hr == E_OUTOFMEMORY) { 638 if (hr == E_OUTOFMEMORY) {
643 max_glyphs *= 2; 639 max_glyphs *= 2;
644 continue; 640 continue;
645 } else if (hr == USP_E_SCRIPT_NOT_IN_FONT) { 641 } else if (hr == USP_E_SCRIPT_NOT_IN_FONT) {
646 glyphs_missing = true; 642 glyphs_missing = true;
647 } else if (hr == S_OK) { 643 } else if (hr == S_OK) {
648 // If |hr| is S_OK, there could still be missing glyphs in the output, 644 // If |hr| is S_OK, there could still be missing glyphs in the output,
649 // see: http://msdn.microsoft.com/en-us/library/windows/desktop/dd368564 .aspx 645 // see: http://msdn.microsoft.com/en-us/library/windows/desktop/dd368564 .aspx
650 ScriptGetFontProperties(cached_hdc_, &run->script_cache, &properties); 646 glyphs_missing = HasMissingGlyphs(run);
651 for (int i = 0; i < run->glyph_count; ++i) {
652 if (run->glyphs[i] == properties.wgDefault) {
653 glyphs_missing = true;
654 break;
655 }
656 }
657 } 647 }
658 648
659 // Skip font substitution if there are no missing glyphs. 649 // Skip font substitution if there are no missing glyphs.
660 if (!glyphs_missing) 650 if (!glyphs_missing)
661 break; 651 break;
662 652
663 // If there are missing glyphs, first try finding a fallback font using a 653 // If there are missing glyphs, first try finding a fallback font using a
664 // meta file, if it hasn't yet been attempted for this run. 654 // meta file, if it hasn't yet been attempted for this run.
665 // TODO(msw|asvitkine): Support RenderText's font_list()? 655 // TODO(msw|asvitkine): Support RenderText's font_list()?
666 // TODO(msw|asvitkine): Cache previous successful replacement fonts? 656 // TODO(msw|asvitkine): Cache previous successful replacement fonts?
(...skipping 94 matching lines...) Expand 10 before | Expand all | Expand 10 after
761 void RenderTextWin::ApplySubstituteFont(internal::TextRun* run, 751 void RenderTextWin::ApplySubstituteFont(internal::TextRun* run,
762 const Font& font) { 752 const Font& font) {
763 const int font_size = run->font.GetFontSize(); 753 const int font_size = run->font.GetFontSize();
764 const int font_height = run->font.GetHeight(); 754 const int font_height = run->font.GetHeight();
765 run->font = font; 755 run->font = font;
766 DeriveFontIfNecessary(font_size, font_height, run->font_style, &run->font); 756 DeriveFontIfNecessary(font_size, font_height, run->font_style, &run->font);
767 ScriptFreeCache(&run->script_cache); 757 ScriptFreeCache(&run->script_cache);
768 SelectObject(cached_hdc_, run->font.GetNativeFont()); 758 SelectObject(cached_hdc_, run->font.GetNativeFont());
769 } 759 }
770 760
761 bool RenderTextWin::HasMissingGlyphs(internal::TextRun* run) const {
762 SCRIPT_FONTPROPERTIES properties;
763 memset(&properties, 0, sizeof(properties));
764 properties.cBytes = sizeof(properties);
765 ScriptGetFontProperties(cached_hdc_, &run->script_cache, &properties);
766
767 const wchar_t* run_text = &(text()[run->range.start()]);
768 for (size_t char_index = 0; char_index < run->range.length(); ++char_index) {
769 const int glyph_index = run->logical_clusters[char_index];
770 DCHECK_GE(glyph_index, 0);
771 DCHECK_LT(glyph_index, run->glyph_count);
772
773 if (run->glyphs[glyph_index] == properties.wgDefault)
774 return true;
775
776 // Windows Vista sometimes returns glyphs equal to wgBlank (instead of
777 // wgDefault), with fZeroWidth set. Treat such cases as having missing
778 // glyphs if the corresponding character is not whitespace.
779 // See: http://crbug.com/125629
780 if (run->glyphs[glyph_index] == properties.wgBlank &&
781 run->visible_attributes[glyph_index].fZeroWidth &&
782 !IsWhitespace(run_text[char_index])) {
783 return true;
784 }
785 }
786
787 return false;
788 }
789
771 const std::vector<Font>* RenderTextWin::GetLinkedFonts(const Font& font) const { 790 const std::vector<Font>* RenderTextWin::GetLinkedFonts(const Font& font) const {
772 const std::string& font_name = font.GetFontName(); 791 const std::string& font_name = font.GetFontName();
773 std::map<std::string, std::vector<Font> >::const_iterator it = 792 std::map<std::string, std::vector<Font> >::const_iterator it =
774 cached_linked_fonts_.find(font_name); 793 cached_linked_fonts_.find(font_name);
775 if (it != cached_linked_fonts_.end()) 794 if (it != cached_linked_fonts_.end())
776 return &it->second; 795 return &it->second;
777 796
778 cached_linked_fonts_[font_name] = std::vector<Font>(); 797 cached_linked_fonts_[font_name] = std::vector<Font>();
779 std::vector<Font>* linked_fonts = &cached_linked_fonts_[font_name]; 798 std::vector<Font>* linked_fonts = &cached_linked_fonts_[font_name];
780 QueryLinkedFontsFromRegistry(font, linked_fonts); 799 QueryLinkedFontsFromRegistry(font, linked_fonts);
(...skipping 16 matching lines...) Expand all
797 // Find the text run containing the argument point (assumed already offset). 816 // Find the text run containing the argument point (assumed already offset).
798 size_t run = 0; 817 size_t run = 0;
799 for (; run < runs_.size(); ++run) 818 for (; run < runs_.size(); ++run)
800 if (runs_[run]->preceding_run_widths <= point.x() && 819 if (runs_[run]->preceding_run_widths <= point.x() &&
801 runs_[run]->preceding_run_widths + runs_[run]->width > point.x()) 820 runs_[run]->preceding_run_widths + runs_[run]->width > point.x())
802 break; 821 break;
803 return run; 822 return run;
804 } 823 }
805 824
806 SelectionModel RenderTextWin::FirstSelectionModelInsideRun( 825 SelectionModel RenderTextWin::FirstSelectionModelInsideRun(
807 internal::TextRun* run) { 826 const internal::TextRun* run) {
808 size_t cursor = IndexOfAdjacentGrapheme(run->range.start(), CURSOR_FORWARD); 827 size_t cursor = IndexOfAdjacentGrapheme(run->range.start(), CURSOR_FORWARD);
809 return SelectionModel(cursor, CURSOR_BACKWARD); 828 return SelectionModel(cursor, CURSOR_BACKWARD);
810 } 829 }
811 830
812 SelectionModel RenderTextWin::LastSelectionModelInsideRun( 831 SelectionModel RenderTextWin::LastSelectionModelInsideRun(
813 internal::TextRun* run) { 832 const internal::TextRun* run) {
814 size_t caret = IndexOfAdjacentGrapheme(run->range.end(), CURSOR_BACKWARD); 833 size_t caret = IndexOfAdjacentGrapheme(run->range.end(), CURSOR_BACKWARD);
815 return SelectionModel(caret, CURSOR_FORWARD); 834 return SelectionModel(caret, CURSOR_FORWARD);
816 } 835 }
817 836
818 RenderText* RenderText::CreateRenderText() { 837 RenderText* RenderText::CreateRenderText() {
819 return new RenderTextWin; 838 return new RenderTextWin;
820 } 839 }
821 840
822 } // namespace gfx 841 } // namespace gfx
OLDNEW
« ui/gfx/render_text_win.h ('K') | « ui/gfx/render_text_win.h ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698