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

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

Powered by Google App Engine
This is Rietveld 408576698