15821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Copyright (c) 2012 The Chromium Authors. All rights reserved.
25821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be
35821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// found in the LICENSE file.
45821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
55821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "ui/gfx/render_text_win.h"
65821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
75821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <algorithm>
85821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
95821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/i18n/break_iterator.h"
100f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles)#include "base/i18n/char_iterator.h"
115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/i18n/rtl.h"
125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/logging.h"
137d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)#include "base/strings/string_util.h"
14868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)#include "base/strings/utf_string_conversions.h"
155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/win/windows_version.h"
1658537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)#include "third_party/icu/source/common/unicode/uchar.h"
175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "ui/gfx/canvas.h"
185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "ui/gfx/font_fallback_win.h"
195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "ui/gfx/font_smoothing_win.h"
205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "ui/gfx/platform_font_win.h"
21d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)#include "ui/gfx/utf16_indexing.h"
225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace gfx {
245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace {
265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
27eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch// The maximum length of text supported for Uniscribe layout and display.
28eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch// This empirically chosen value should prevent major performance degradations.
29eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch// TODO(msw): Support longer text, partial layout/painting, etc.
30eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdochconst size_t kMaxUniscribeTextLength = 10000;
315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
32eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch// The initial guess and maximum supported number of runs; arbitrary values.
33eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch// TODO(msw): Support more runs, determine a better initial guess, etc.
34eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdochconst int kGuessRuns = 100;
35eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdochconst size_t kMaxRuns = 10000;
36eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
37eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch// The maximum number of glyphs per run; ScriptShape fails on larger values.
38eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdochconst size_t kMaxGlyphs = 65535;
395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Callback to |EnumEnhMetaFile()| to intercept font creation.
415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)int CALLBACK MetaFileEnumProc(HDC hdc,
425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                              HANDLETABLE* table,
435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                              CONST ENHMETARECORD* record,
445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                              int table_entries,
455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                              LPARAM log_font) {
465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (record->iType == EMR_EXTCREATEFONTINDIRECTW) {
475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const EMREXTCREATEFONTINDIRECTW* create_font_record =
485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        reinterpret_cast<const EMREXTCREATEFONTINDIRECTW*>(record);
495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    *reinterpret_cast<LOGFONT*>(log_font) = create_font_record->elfw.elfLogFont;
505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return 1;
525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Finds a fallback font to use to render the specified |text| with respect to
555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// an initial |font|. Returns the resulting font via out param |result|. Returns
565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// |true| if a fallback font was found.
575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Adapted from WebKit's |FontCache::GetFontDataForCharacters()|.
585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// TODO(asvitkine): This should be moved to font_fallback_win.cc.
595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool ChooseFallbackFont(HDC hdc,
605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                        const Font& font,
615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                        const wchar_t* text,
625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                        int text_length,
635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                        Font* result) {
645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Use a meta file to intercept the fallback font chosen by Uniscribe.
655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  HDC meta_file_dc = CreateEnhMetaFile(hdc, NULL, NULL, NULL);
665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!meta_file_dc)
675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return false;
685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  SelectObject(meta_file_dc, font.GetNativeFont());
705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  SCRIPT_STRING_ANALYSIS script_analysis;
725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  HRESULT hresult =
735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      ScriptStringAnalyse(meta_file_dc, text, text_length, 0, -1,
745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                          SSA_METAFILE | SSA_FALLBACK | SSA_GLYPHS | SSA_LINK,
755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                          0, NULL, NULL, NULL, NULL, NULL, &script_analysis);
765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (SUCCEEDED(hresult)) {
785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    hresult = ScriptStringOut(script_analysis, 0, 0, 0, NULL, 0, 0, FALSE);
795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    ScriptStringFree(&script_analysis);
805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  bool found_fallback = false;
835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  HENHMETAFILE meta_file = CloseEnhMetaFile(meta_file_dc);
845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (SUCCEEDED(hresult)) {
855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    LOGFONT log_font;
865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    log_font.lfFaceName[0] = 0;
875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    EnumEnhMetaFile(0, meta_file, MetaFileEnumProc, &log_font, NULL);
885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (log_font.lfFaceName[0]) {
895d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      *result = Font(base::UTF16ToUTF8(log_font.lfFaceName),
905d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                     font.GetFontSize());
915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      found_fallback = true;
925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DeleteEnhMetaFile(meta_file);
955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return found_fallback;
975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Changes |font| to have the specified |font_size| (or |font_height| on Windows
1005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// XP) and |font_style| if it is not the case already. Only considers bold and
1015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// italic styles, since the underlined style has no effect on glyph shaping.
1025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void DeriveFontIfNecessary(int font_size,
1035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                           int font_height,
1045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                           int font_style,
1055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                           Font* font) {
1065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const int kStyleMask = (Font::BOLD | Font::ITALIC);
1075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const int target_style = (font_style & kStyleMask);
1085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // On Windows XP, the font must be resized using |font_height| instead of
1105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // |font_size| to match GDI behavior.
1115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (base::win::GetVersion() < base::win::VERSION_VISTA) {
1125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    PlatformFontWin* platform_font =
1135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        static_cast<PlatformFontWin*>(font->platform_font());
1145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    *font = platform_font->DeriveFontWithHeight(font_height, target_style);
1155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return;
1165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const int current_style = (font->GetStyle() & kStyleMask);
1195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const int current_size = font->GetFontSize();
1205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (current_style != target_style || current_size != font_size)
1215d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    *font = font->Derive(font_size - current_size, target_style);
1225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Returns true if |c| is a Unicode BiDi control character.
1255d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)bool IsUnicodeBidiControlCharacter(base::char16 c) {
1265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return c == base::i18n::kRightToLeftMark ||
1275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)         c == base::i18n::kLeftToRightMark ||
1285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)         c == base::i18n::kLeftToRightEmbeddingMark ||
1295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)         c == base::i18n::kRightToLeftEmbeddingMark ||
1305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)         c == base::i18n::kPopDirectionalFormatting ||
1315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)         c == base::i18n::kLeftToRightOverride ||
1325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)         c == base::i18n::kRightToLeftOverride;
1335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
135558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch// Returns the corresponding glyph range of the given character range.
136558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch// |range| is in text-space (0 corresponds to |GetLayoutText()[0]|).
137558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch// Returned value is in run-space (0 corresponds to the first glyph in the run).
138d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)Range CharRangeToGlyphRange(const internal::TextRun& run,
139d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)                            const Range& range) {
140558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch  DCHECK(run.range.Contains(range));
141558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch  DCHECK(!range.is_reversed());
142558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch  DCHECK(!range.is_empty());
143d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)  const Range run_range(range.start() - run.range.start(),
144d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)                        range.end() - run.range.start());
145d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)  Range result;
146558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch  if (run.script_analysis.fRTL) {
147d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)    result = Range(run.logical_clusters[run_range.end() - 1],
148558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch        run_range.start() > 0 ? run.logical_clusters[run_range.start() - 1]
149558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch                              : run.glyph_count);
150558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch  } else {
151d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)    result = Range(run.logical_clusters[run_range.start()],
152558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch        run_range.end() < run.range.length() ?
153558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch            run.logical_clusters[run_range.end()] : run.glyph_count);
154558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch  }
155558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch  DCHECK(!result.is_reversed());
156d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)  DCHECK(Range(0, run.glyph_count).Contains(result));
157558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch  return result;
158558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch}
159558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch
160d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)// Starting from |start_char|, finds a suitable line break position at or before
161d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)// |available_width| using word break info from |breaks|. If |empty_line| is
162d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)// true, this function will not roll back to |start_char| and |*next_char| will
163a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)// be greater than |start_char| (to avoid constructing empty lines). Returns
164a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)// whether to skip the line before |*next_char|.
165d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)// TODO(ckocagil): Do not break ligatures and diacritics.
166d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)//                 TextRun::logical_clusters might help.
167d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)// TODO(ckocagil): We might have to reshape after breaking at ligatures.
168d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)//                 See whether resolving the TODO above resolves this too.
169d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)// TODO(ckocagil): Do not reserve width for whitespace at the end of lines.
170a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)bool BreakRunAtWidth(const wchar_t* text,
171a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)                     const internal::TextRun& run,
172d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)                     const BreakList<size_t>& breaks,
173d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)                     size_t start_char,
174d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)                     int available_width,
175d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)                     bool empty_line,
176d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)                     int* width,
177d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)                     size_t* next_char) {
178d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)  DCHECK(run.range.Contains(Range(start_char, start_char + 1)));
179d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)  BreakList<size_t>::const_iterator word = breaks.GetBreak(start_char);
180d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)  BreakList<size_t>::const_iterator next_word = word + 1;
181d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)  // Width from |std::max(word->first, start_char)| to the current character.
182d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)  int word_width = 0;
183d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)  *width = 0;
184d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)
185d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)  for (size_t i = start_char; i < run.range.end(); ++i) {
186a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)    if (U16_IS_SINGLE(text[i]) && text[i] == L'\n') {
187a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)      *next_char = i + 1;
188a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)      return true;
189a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)    }
190a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)
191d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)    // |word| holds the word boundary at or before |i|, and |next_word| holds
192d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)    // the word boundary right after |i|. Advance both |word| and |next_word|
193d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)    // when |i| reaches |next_word|.
194d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)    if (next_word != breaks.breaks().end() && i >= next_word->first) {
195d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)      word = next_word++;
196d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)      word_width = 0;
197d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)    }
198d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)
199d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)    Range glyph_range = CharRangeToGlyphRange(run, Range(i, i + 1));
200d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)    int char_width = 0;
201d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)    for (size_t j = glyph_range.start(); j < glyph_range.end(); ++j)
202d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)      char_width += run.advance_widths[j];
203d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)
204d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)    *width += char_width;
205d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)    word_width += char_width;
206d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)
207d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)    if (*width > available_width) {
208d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)      if (!empty_line || word_width < *width) {
209a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)        // Roll back one word.
210d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)        *width -= word_width;
211d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)        *next_char = std::max(word->first, start_char);
212d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)      } else if (char_width < *width) {
213a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)        // Roll back one character.
214d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)        *width -= char_width;
215d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)        *next_char = i;
216d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)      } else {
217a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)        // Continue from the next character.
218d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)        *next_char = i + 1;
219d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)      }
220d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)
221a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)      return true;
222d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)    }
223d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)  }
224d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)
225d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)  *next_char = run.range.end();
226a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  return false;
227d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)}
228d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)
229d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)// For segments in the same run, checks the continuity and order of |x_range|
230d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)// and |char_range| fields.
231d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)void CheckLineIntegrity(const std::vector<internal::Line>& lines,
232d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)                        const ScopedVector<internal::TextRun>& runs) {
233d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)  size_t previous_segment_line = 0;
234d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)  const internal::LineSegment* previous_segment = NULL;
235d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)
236d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)  for (size_t i = 0; i < lines.size(); ++i) {
237d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)    for (size_t j = 0; j < lines[i].segments.size(); ++j) {
238d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)      const internal::LineSegment* segment = &lines[i].segments[j];
239d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)      internal::TextRun* run = runs[segment->run];
240d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)
241d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)      if (!previous_segment) {
242d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)        previous_segment = segment;
243d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)      } else if (runs[previous_segment->run] != run) {
244d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)        previous_segment = NULL;
245d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)      } else {
246d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)        DCHECK_EQ(previous_segment->char_range.end(),
247d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)                  segment->char_range.start());
248d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)        if (!run->script_analysis.fRTL) {
249d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)          DCHECK_EQ(previous_segment->x_range.end(), segment->x_range.start());
250d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)        } else {
251d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)          DCHECK_EQ(segment->x_range.end(), previous_segment->x_range.start());
252d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)        }
253d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)
254d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)        previous_segment = segment;
255d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)        previous_segment_line = i;
256d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)      }
257d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)    }
258d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)  }
259d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)}
260d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)
261f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)// Returns true if characters of |block_code| may trigger font fallback.
262f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)bool IsUnusualBlockCode(const UBlockCode block_code) {
263f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  return block_code == UBLOCK_GEOMETRIC_SHAPES ||
264f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)         block_code == UBLOCK_MISCELLANEOUS_SYMBOLS;
265f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)}
266f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)
267f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)// Returns the index of the first unusual character after a usual character or
268f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)// vice versa. Unusual characters are defined by |IsUnusualBlockCode|.
269f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)size_t FindUnusualCharacter(const base::string16& text,
270f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)                            size_t run_start,
271f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)                            size_t run_break) {
272f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  const int32 run_length = static_cast<int32>(run_break - run_start);
273f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  base::i18n::UTF16CharIterator iter(text.c_str() + run_start,
274f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)                                     run_length);
275f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  const UBlockCode first_block_code = ublock_getCode(iter.get());
276f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  const bool first_block_unusual = IsUnusualBlockCode(first_block_code);
277f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  while (iter.Advance() && iter.array_pos() < run_length) {
278f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)    const UBlockCode current_block_code = ublock_getCode(iter.get());
279f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)    if (current_block_code != first_block_code &&
280f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)        (first_block_unusual || IsUnusualBlockCode(current_block_code))) {
281f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)      return run_start + iter.array_pos();
282f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)    }
283f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  }
284f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  return run_break;
285f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)}
286f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)
2875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}  // namespace
2885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace internal {
2905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)TextRun::TextRun()
292558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch  : font_style(0),
2935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    strike(false),
2945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    diagonal_strike(false),
2955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    underline(false),
2965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    width(0),
2975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    preceding_run_widths(0),
2985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    glyph_count(0),
2995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    script_cache(NULL) {
3005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  memset(&script_analysis, 0, sizeof(script_analysis));
3015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  memset(&abc_widths, 0, sizeof(abc_widths));
3025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
3035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)TextRun::~TextRun() {
3055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ScriptFreeCache(&script_cache);
3065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
3075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Returns the X coordinate of the leading or |trailing| edge of the glyph
3095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// starting at |index|, relative to the left of the text (not the view).
31090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)int GetGlyphXBoundary(const internal::TextRun* run,
31190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)                      size_t index,
31290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)                      bool trailing) {
3135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK_GE(index, run->range.start());
3145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK_LT(index, run->range.end() + (trailing ? 0 : 1));
3155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int x = 0;
3165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  HRESULT hr = ScriptCPtoX(
3175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      index - run->range.start(),
3185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      trailing,
3195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      run->range.length(),
3205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      run->glyph_count,
3215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      run->logical_clusters.get(),
3225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      run->visible_attributes.get(),
3235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      run->advance_widths.get(),
3245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      &run->script_analysis,
3255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      &x);
3265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(SUCCEEDED(hr));
3275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return run->preceding_run_widths + x;
3285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
3295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
330d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)// Internal class to generate Line structures. If |multiline| is true, the text
331d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)// is broken into lines at |words| boundaries such that each line is no longer
332d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)// than |max_width|. If |multiline| is false, only outputs a single Line from
333d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)// the given runs. |min_baseline| and |min_height| are the minimum baseline and
334d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)// height for each line.
335d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)// TODO(ckocagil): Expose the interface of this class in the header and test
336d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)//                 this class directly.
337d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)class LineBreaker {
338d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) public:
339d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)  LineBreaker(int max_width,
340d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)              int min_baseline,
341d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)              int min_height,
342d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)              bool multiline,
343a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)              const wchar_t* text,
344d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)              const BreakList<size_t>* words,
345d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)              const ScopedVector<TextRun>& runs)
346d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)      : max_width_(max_width),
347d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)        min_baseline_(min_baseline),
348d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)        min_height_(min_height),
349d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)        multiline_(multiline),
350a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)        text_(text),
351d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)        words_(words),
352d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)        runs_(runs),
353d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)        text_x_(0),
354d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)        line_x_(0),
355d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)        line_ascent_(0),
356d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)        line_descent_(0) {
357d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)    AdvanceLine();
358d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)  }
359d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)
360d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)  // Breaks the run at given |run_index| into Line structs.
361d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)  void AddRun(int run_index) {
362d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)    const TextRun* run = runs_[run_index];
363a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)    bool run_fits = !multiline_;
364a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)    if (multiline_ && line_x_ + run->width <= max_width_) {
365a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)      DCHECK(!run->range.is_empty());
366a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)      const wchar_t first_char = text_[run->range.start()];
367a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)      // Uniscribe always puts newline characters in their own runs.
368a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)      if (!U16_IS_SINGLE(first_char) || first_char != L'\n')
369a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)        run_fits = true;
370a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)    }
371a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)
372a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)    if (!run_fits)
373d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)      BreakRun(run_index);
374d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)    else
375d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)      AddSegment(run_index, run->range, run->width);
376d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)  }
377d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)
378d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)  // Finishes line breaking and outputs the results. Can be called at most once.
379d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)  void Finalize(std::vector<Line>* lines, Size* size) {
380d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)    DCHECK(!lines_.empty());
381d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)    // Add an empty line to finish the line size calculation and remove it.
382d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)    AdvanceLine();
383d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)    lines_.pop_back();
384d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)    *size = total_size_;
385d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)    lines->swap(lines_);
386d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)  }
387d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)
388d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) private:
389d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)  // A (line index, segment index) pair that specifies a segment in |lines_|.
390d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)  typedef std::pair<size_t, size_t> SegmentHandle;
391d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)
392d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)  LineSegment* SegmentFromHandle(const SegmentHandle& handle) {
393d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)    return &lines_[handle.first].segments[handle.second];
394d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)  }
395d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)
396d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)  // Breaks a run into segments that fit in the last line in |lines_| and adds
397d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)  // them. Adds a new Line to the back of |lines_| whenever a new segment can't
398d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)  // be added without the Line's width exceeding |max_width_|.
399d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)  void BreakRun(int run_index) {
400d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)    DCHECK(words_);
401d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)    const TextRun* const run = runs_[run_index];
402d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)    int width = 0;
403d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)    size_t next_char = run->range.start();
404d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)
405d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)    // Break the run until it fits the current line.
406d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)    while (next_char < run->range.end()) {
407d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)      const size_t current_char = next_char;
408a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)      const bool skip_line = BreakRunAtWidth(text_, *run, *words_, current_char,
409a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)          max_width_ - line_x_, line_x_ == 0, &width, &next_char);
410d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)      AddSegment(run_index, Range(current_char, next_char), width);
411a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)      if (skip_line)
412d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)        AdvanceLine();
413d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)    }
414d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)  }
415d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)
416d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)  // RTL runs are broken in logical order but displayed in visual order. To find
417d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)  // the text-space coordinate (where it would fall in a single-line text)
418d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)  // |x_range| of RTL segments, segment widths are applied in reverse order.
419d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)  // e.g. {[5, 10], [10, 40]} will become {[35, 40], [5, 35]}.
420d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)  void UpdateRTLSegmentRanges() {
421d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)    if (rtl_segments_.empty())
422d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)      return;
423d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)    int x = SegmentFromHandle(rtl_segments_[0])->x_range.start();
424d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)    for (size_t i = rtl_segments_.size(); i > 0; --i) {
425d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)      LineSegment* segment = SegmentFromHandle(rtl_segments_[i - 1]);
426d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)      const size_t segment_width = segment->x_range.length();
427d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)      segment->x_range = Range(x, x + segment_width);
428d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)      x += segment_width;
429d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)    }
430d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)    rtl_segments_.clear();
431d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)  }
432d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)
433d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)  // Finishes the size calculations of the last Line in |lines_|. Adds a new
434d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)  // Line to the back of |lines_|.
435d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)  void AdvanceLine() {
436d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)    if (!lines_.empty()) {
437d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)      Line* line = &lines_.back();
438d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)      // TODO(ckocagil): Determine optimal multiline height behavior.
439d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)      if (line_ascent_ + line_descent_ == 0) {
440d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)        line_ascent_ = min_baseline_;
441d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)        line_descent_ = min_height_ - min_baseline_;
442d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)      }
443d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)      // Set the single-line mode Line's metrics to be at least
444d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)      // |RenderText::font_list()| to not break the current single-line code.
445d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)      line_ascent_ = std::max(line_ascent_, min_baseline_);
446d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)      line_descent_ = std::max(line_descent_, min_height_ - min_baseline_);
447d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)
448d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)      line->baseline = line_ascent_;
449d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)      line->size.set_height(line_ascent_ + line_descent_);
450d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)      line->preceding_heights = total_size_.height();
451d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)      total_size_.set_height(total_size_.height() + line->size.height());
452d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)      total_size_.set_width(std::max(total_size_.width(), line->size.width()));
453d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)    }
454d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)    line_x_ = 0;
455d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)    line_ascent_ = 0;
456d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)    line_descent_ = 0;
457d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)    lines_.push_back(Line());
458d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)  }
459d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)
460d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)  // Adds a new segment with the given properties to |lines_.back()|.
461d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)  void AddSegment(int run_index, Range char_range, int width) {
462d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)    if (char_range.is_empty()) {
463d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)      DCHECK_EQ(width, 0);
464d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)      return;
465d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)    }
466d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)    const TextRun* run = runs_[run_index];
467d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)    line_ascent_ = std::max(line_ascent_, run->font.GetBaseline());
468d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)    line_descent_ = std::max(line_descent_,
469d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)                             run->font.GetHeight() - run->font.GetBaseline());
470d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)
471d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)    LineSegment segment;
472d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)    segment.run = run_index;
473d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)    segment.char_range = char_range;
474d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)    segment.x_range = Range(text_x_, text_x_ + width);
475d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)
476d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)    Line* line = &lines_.back();
477d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)    line->segments.push_back(segment);
478d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)    line->size.set_width(line->size.width() + segment.x_range.length());
479d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)    if (run->script_analysis.fRTL) {
480d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)      rtl_segments_.push_back(SegmentHandle(lines_.size() - 1,
481d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)                                            line->segments.size() - 1));
482d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)      // If this is the last segment of an RTL run, reprocess the text-space x
483d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)      // ranges of all segments from the run.
484d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)      if (char_range.end() == run->range.end())
485d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)        UpdateRTLSegmentRanges();
486d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)    }
487d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)    text_x_ += width;
488d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)    line_x_ += width;
489d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)  }
490d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)
491d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)  const int max_width_;
492d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)  const int min_baseline_;
493d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)  const int min_height_;
494d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)  const bool multiline_;
495a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  const wchar_t* text_;
496d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)  const BreakList<size_t>* const words_;
497d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)  const ScopedVector<TextRun>& runs_;
498d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)
499d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)  // Stores the resulting lines.
500d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)  std::vector<Line> lines_;
501d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)
502d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)  // Text space and line space x coordinates of the next segment to be added.
503d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)  int text_x_;
504d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)  int line_x_;
505d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)
506d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)  // Size of the multiline text, not including the currently processed line.
507d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)  Size total_size_;
508d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)
509d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)  // Ascent and descent values of the current line, |lines_.back()|.
510d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)  int line_ascent_;
511d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)  int line_descent_;
512d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)
513d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)  // The current RTL run segments, to be applied by |UpdateRTLSegmentRanges()|.
514d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)  std::vector<SegmentHandle> rtl_segments_;
515d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)
516d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)  DISALLOW_COPY_AND_ASSIGN(LineBreaker);
517d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)};
518d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)
5195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}  // namespace internal
5205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// static
5225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)HDC RenderTextWin::cached_hdc_ = NULL;
5235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// static
5255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)std::map<std::string, Font> RenderTextWin::successful_substitute_fonts_;
5265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
527010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)RenderTextWin::RenderTextWin() : RenderText(), needs_layout_(false) {
528eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  set_truncate_length(kMaxUniscribeTextLength);
5295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  memset(&script_control_, 0, sizeof(script_control_));
5305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  memset(&script_state_, 0, sizeof(script_state_));
5315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  MoveCursorTo(EdgeSelectionModel(CURSOR_LEFT));
5325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
5335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
534010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)RenderTextWin::~RenderTextWin() {}
5355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)Size RenderTextWin::GetStringSize() {
5375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EnsureLayout();
538d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)  return multiline_string_size_;
5395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
5405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)SelectionModel RenderTextWin::FindCursorPosition(const Point& point) {
5425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (text().empty())
5435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return SelectionModel();
5445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EnsureLayout();
5465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Find the run that contains the point and adjust the argument location.
54790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  int x = ToTextPoint(point).x();
54890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  size_t run_index = GetRunContainingXCoord(x);
549eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  if (run_index >= runs_.size())
55090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    return EdgeSelectionModel((x < 0) ? CURSOR_LEFT : CURSOR_RIGHT);
5515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  internal::TextRun* run = runs_[run_index];
5525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int position = 0, trailing = 0;
55490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  HRESULT hr = ScriptXtoCP(x - run->preceding_run_widths,
5555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                           run->range.length(),
5565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                           run->glyph_count,
5575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                           run->logical_clusters.get(),
5585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                           run->visible_attributes.get(),
5595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                           run->advance_widths.get(),
5605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                           &(run->script_analysis),
5615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                           &position,
5625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                           &trailing);
5635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(SUCCEEDED(hr));
5645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK_GE(trailing, 0);
5655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  position += run->range.start();
5665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const size_t cursor = LayoutIndexToTextIndex(position + trailing);
5675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK_LE(cursor, text().length());
5685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return SelectionModel(cursor, trailing ? CURSOR_BACKWARD : CURSOR_FORWARD);
5695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
5705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)std::vector<RenderText::FontSpan> RenderTextWin::GetFontSpansForTesting() {
5725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EnsureLayout();
5735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  std::vector<RenderText::FontSpan> spans;
5755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  for (size_t i = 0; i < runs_.size(); ++i) {
5765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    spans.push_back(RenderText::FontSpan(runs_[i]->font,
577d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)        Range(LayoutIndexToTextIndex(runs_[i]->range.start()),
578d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)              LayoutIndexToTextIndex(runs_[i]->range.end()))));
5795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
5805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return spans;
5825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
5835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5840f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles)int RenderTextWin::GetLayoutTextBaseline() {
5850f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles)  EnsureLayout();
5860f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles)  return lines()[0].baseline;
5870f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles)}
5880f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles)
5895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)SelectionModel RenderTextWin::AdjacentCharSelectionModel(
5905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const SelectionModel& selection,
5915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    VisualCursorDirection direction) {
5925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(!needs_layout_);
5935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  internal::TextRun* run;
5945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  size_t run_index = GetRunContainingCaret(selection);
5955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (run_index >= runs_.size()) {
5965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // The cursor is not in any run: we're at the visual and logical edge.
5975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    SelectionModel edge = EdgeSelectionModel(direction);
5985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (edge.caret_pos() == selection.caret_pos())
5995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return edge;
6005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    int visual_index = (direction == CURSOR_RIGHT) ? 0 : runs_.size() - 1;
6015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    run = runs_[visual_to_logical_[visual_index]];
6025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  } else {
6035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // If the cursor is moving within the current run, just move it by one
6045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // grapheme in the appropriate direction.
6055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    run = runs_[run_index];
6065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    size_t caret = selection.caret_pos();
6075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    bool forward_motion =
6085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        run->script_analysis.fRTL == (direction == CURSOR_LEFT);
6095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (forward_motion) {
6105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      if (caret < LayoutIndexToTextIndex(run->range.end())) {
6115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        caret = IndexOfAdjacentGrapheme(caret, CURSOR_FORWARD);
6125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        return SelectionModel(caret, CURSOR_BACKWARD);
6135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      }
6145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    } else {
6155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      if (caret > LayoutIndexToTextIndex(run->range.start())) {
6165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        caret = IndexOfAdjacentGrapheme(caret, CURSOR_BACKWARD);
6175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        return SelectionModel(caret, CURSOR_FORWARD);
6185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      }
6195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
6205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // The cursor is at the edge of a run; move to the visually adjacent run.
6215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    int visual_index = logical_to_visual_[run_index];
6225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    visual_index += (direction == CURSOR_LEFT) ? -1 : 1;
6235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (visual_index < 0 || visual_index >= static_cast<int>(runs_.size()))
6245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return EdgeSelectionModel(direction);
6255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    run = runs_[visual_to_logical_[visual_index]];
6265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
6275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  bool forward_motion = run->script_analysis.fRTL == (direction == CURSOR_LEFT);
6285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return forward_motion ? FirstSelectionModelInsideRun(run) :
6295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                          LastSelectionModelInsideRun(run);
6305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
6315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// TODO(msw): Implement word breaking for Windows.
6335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)SelectionModel RenderTextWin::AdjacentWordSelectionModel(
6345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const SelectionModel& selection,
6355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    VisualCursorDirection direction) {
6365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (obscured())
6375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return EdgeSelectionModel(direction);
6385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  base::i18n::BreakIterator iter(text(), base::i18n::BreakIterator::BREAK_WORD);
6405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  bool success = iter.Init();
6415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(success);
6425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!success)
6435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return selection;
6445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  size_t pos;
6465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (direction == CURSOR_RIGHT) {
6475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    pos = std::min(selection.caret_pos() + 1, text().length());
6485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    while (iter.Advance()) {
6495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      pos = iter.pos();
6505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      if (iter.IsWord() && pos > selection.caret_pos())
6515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        break;
6525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
6535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  } else {  // direction == CURSOR_LEFT
6545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // Notes: We always iterate words from the beginning.
6555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // This is probably fast enough for our usage, but we may
6565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // want to modify WordIterator so that it can start from the
6575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // middle of string and advance backwards.
6585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    pos = std::max<int>(selection.caret_pos() - 1, 0);
6595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    while (iter.Advance()) {
6605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      if (iter.IsWord()) {
6615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        size_t begin = iter.pos() - iter.GetString().length();
6625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        if (begin == selection.caret_pos()) {
6635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          // The cursor is at the beginning of a word.
6645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          // Move to previous word.
6655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          break;
6665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        } else if (iter.pos() >= selection.caret_pos()) {
6675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          // The cursor is in the middle or at the end of a word.
6685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          // Move to the top of current word.
6695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          pos = begin;
6705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          break;
6715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        } else {
6725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          pos = iter.pos() - iter.GetString().length();
6735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        }
6745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      }
6755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
6765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
6775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return SelectionModel(pos, CURSOR_FORWARD);
6785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
6795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
680d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)Range RenderTextWin::GetGlyphBounds(size_t index) {
681cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  EnsureLayout();
6825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const size_t run_index =
6835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      GetRunContainingCaret(SelectionModel(index, CURSOR_FORWARD));
684eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  // Return edge bounds if the index is invalid or beyond the layout text size.
685eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  if (run_index >= runs_.size())
686d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)    return Range(string_width_);
6875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  internal::TextRun* run = runs_[run_index];
6885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const size_t layout_index = TextIndexToLayoutIndex(index);
689d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)  return Range(GetGlyphXBoundary(run, layout_index, false),
690d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)               GetGlyphXBoundary(run, layout_index, true));
6915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
6925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
693d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)std::vector<Rect> RenderTextWin::GetSubstringBounds(const Range& range) {
6945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(!needs_layout_);
695d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)  DCHECK(Range(0, text().length()).Contains(range));
696d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)  Range layout_range(TextIndexToLayoutIndex(range.start()),
697d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)                     TextIndexToLayoutIndex(range.end()));
698d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)  DCHECK(Range(0, GetLayoutText().length()).Contains(layout_range));
6995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
700d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)  std::vector<Rect> rects;
7015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (layout_range.is_empty())
702d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)    return rects;
703d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)  std::vector<Range> bounds;
7045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
705d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)  // Add a Range for each run/selection intersection.
7065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // TODO(msw): The bounds should probably not always be leading the range ends.
7075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  for (size_t i = 0; i < runs_.size(); ++i) {
70890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    const internal::TextRun* run = runs_[visual_to_logical_[i]];
709d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)    Range intersection = run->range.Intersect(layout_range);
7105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (intersection.IsValid()) {
7115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      DCHECK(!intersection.is_reversed());
712d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)      Range range_x(GetGlyphXBoundary(run, intersection.start(), false),
713d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)                    GetGlyphXBoundary(run, intersection.end(), false));
714d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)      if (range_x.is_empty())
715d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)        continue;
716d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)      range_x = Range(range_x.GetMin(), range_x.GetMax());
717d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)      // Union this with the last range if they're adjacent.
718d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)      DCHECK(bounds.empty() || bounds.back().GetMax() <= range_x.GetMin());
719d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)      if (!bounds.empty() && bounds.back().GetMax() == range_x.GetMin()) {
720d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)        range_x = Range(bounds.back().GetMin(), range_x.GetMax());
7215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        bounds.pop_back();
7225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      }
723d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)      bounds.push_back(range_x);
7245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
7255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
726d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)  for (size_t i = 0; i < bounds.size(); ++i) {
727d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)    std::vector<Rect> current_rects = TextBoundsToViewBounds(bounds[i]);
728d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)    rects.insert(rects.end(), current_rects.begin(), current_rects.end());
729d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)  }
730d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)  return rects;
7315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
7325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)size_t RenderTextWin::TextIndexToLayoutIndex(size_t index) const {
7345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK_LE(index, text().length());
735010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  ptrdiff_t i = obscured() ? UTF16IndexToOffset(text(), 0, index) : index;
736eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  CHECK_GE(i, 0);
737eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  // Clamp layout indices to the length of the text actually used for layout.
738eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  return std::min<size_t>(GetLayoutText().length(), i);
7395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
7405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)size_t RenderTextWin::LayoutIndexToTextIndex(size_t index) const {
7425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!obscured())
7435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return index;
7445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK_LE(index, GetLayoutText().length());
746010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  const size_t text_index = UTF16OffsetToIndex(text(), 0, index);
7475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK_LE(text_index, text().length());
7485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return text_index;
7495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
7505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
751010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)bool RenderTextWin::IsValidCursorIndex(size_t index) {
752010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  if (index == 0 || index == text().length())
7535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return true;
754010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  if (!IsValidLogicalIndex(index))
755010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)    return false;
7565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EnsureLayout();
757010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  // Disallow indices amid multi-character graphemes by checking glyph bounds.
758010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  // These characters are not surrogate-pairs, but may yield a single glyph:
759010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  //   \x0915\x093f - (ki) - one of many Devanagari biconsonantal conjuncts.
760010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  //   \x0e08\x0e33 - (cho chan + sara am) - a Thai consonant and vowel pair.
761010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  return GetGlyphBounds(index) != GetGlyphBounds(index - 1);
7625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
7635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void RenderTextWin::ResetLayout() {
7655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Layout is performed lazily as needed for drawing/metrics.
7665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  needs_layout_ = true;
7675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
7685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void RenderTextWin::EnsureLayout() {
770d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)  if (needs_layout_) {
771d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)    // TODO(msw): Skip complex processing if ScriptIsComplex returns false.
772d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)    ItemizeLogicalText();
773d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)    if (!runs_.empty())
774d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)      LayoutVisualText();
775d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)    needs_layout_ = false;
776d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)    std::vector<internal::Line> lines;
777d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)    set_lines(&lines);
778d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)  }
779d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)
780d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)  // Compute lines if they're not valid. This is separate from the layout steps
781d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)  // above to avoid text layout and shaping when we resize |display_rect_|.
782d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)  if (lines().empty()) {
783d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)    DCHECK(!needs_layout_);
784d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)    std::vector<internal::Line> lines;
785d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)    internal::LineBreaker line_breaker(display_rect().width() - 1,
786d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)                                       font_list().GetBaseline(),
787d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)                                       font_list().GetHeight(), multiline(),
788a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)                                       GetLayoutText().c_str(),
789d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)                                       multiline() ? &GetLineBreaks() : NULL,
790d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)                                       runs_);
791d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)    for (size_t i = 0; i < runs_.size(); ++i)
792d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)      line_breaker.AddRun(visual_to_logical_[i]);
793d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)    line_breaker.Finalize(&lines, &multiline_string_size_);
794d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)    DCHECK(!lines.empty());
795d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)#ifndef NDEBUG
796d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)    CheckLineIntegrity(lines, runs_);
797d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)#endif
798d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)    set_lines(&lines);
799d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)  }
8005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
8015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
8025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void RenderTextWin::DrawVisualText(Canvas* canvas) {
8035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(!needs_layout_);
804d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)  DCHECK(!lines().empty());
8055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
8065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  std::vector<SkPoint> pos;
8075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
8085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  internal::SkiaTextRenderer renderer(canvas);
8095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ApplyFadeEffects(&renderer);
8105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ApplyTextShadows(&renderer);
8115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
8125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  bool smoothing_enabled;
8135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  bool cleartype_enabled;
8145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  GetCachedFontSmoothingSettings(&smoothing_enabled, &cleartype_enabled);
8155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Note that |cleartype_enabled| corresponds to Skia's |enable_lcd_text|.
8165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  renderer.SetFontSmoothingSettings(
8175d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      smoothing_enabled, cleartype_enabled && !background_is_transparent(),
8185d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      smoothing_enabled /* subpixel_positioning */);
8195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
820558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch  ApplyCompositionAndSelectionStyles();
821558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch
822d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)  for (size_t i = 0; i < lines().size(); ++i) {
823d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)    const internal::Line& line = lines()[i];
824d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)    const Vector2d line_offset = GetLineOffset(i);
8255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
826d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)    // Skip painting empty lines or lines outside the display rect area.
827d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)    if (!display_rect().Intersects(Rect(PointAtOffsetFromOrigin(line_offset),
828d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)                                        line.size)))
8295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      continue;
8305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
831d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)    const Vector2d text_offset = line_offset + Vector2d(0, line.baseline);
832d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)    int preceding_segment_widths = 0;
833d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)
834d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)    for (size_t j = 0; j < line.segments.size(); ++j) {
835d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)      const internal::LineSegment* segment = &line.segments[j];
836d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)      const int segment_width = segment->x_range.length();
837d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)      const internal::TextRun* run = runs_[segment->run];
838d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)      DCHECK(!segment->char_range.is_empty());
839d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)      DCHECK(run->range.Contains(segment->char_range));
840d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)      Range glyph_range = CharRangeToGlyphRange(*run, segment->char_range);
841d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)      DCHECK(!glyph_range.is_empty());
842d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)      // Skip painting segments outside the display rect area.
843d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)      if (!multiline()) {
844d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)        const Rect segment_bounds(PointAtOffsetFromOrigin(line_offset) +
845d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)                                      Vector2d(preceding_segment_widths, 0),
846d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)                                  Size(segment_width, line.size.height()));
847d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)        if (!display_rect().Intersects(segment_bounds)) {
848d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)          preceding_segment_widths += segment_width;
849d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)          continue;
850d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)        }
851d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)      }
8525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
853d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)      // |pos| contains the positions of glyphs. An extra terminal |pos| entry
854d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)      // is added to simplify width calculations.
855d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)      int segment_x = preceding_segment_widths;
856d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)      pos.resize(glyph_range.length() + 1);
857d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)      for (size_t k = glyph_range.start(); k < glyph_range.end(); ++k) {
858d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)        pos[k - glyph_range.start()].set(
859d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)            SkIntToScalar(text_offset.x() + run->offsets[k].du + segment_x),
860010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)            SkIntToScalar(text_offset.y() - run->offsets[k].dv));
861d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)        segment_x += run->advance_widths[k];
862d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)      }
863d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)      pos.back().set(SkIntToScalar(text_offset.x() + segment_x),
864d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)                     SkIntToScalar(text_offset.y()));
865d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)
866d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)      renderer.SetTextSize(run->font.GetFontSize());
867d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)      renderer.SetFontFamilyWithStyle(run->font.GetFontName(), run->font_style);
868d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)
869d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)      for (BreakList<SkColor>::const_iterator it =
870d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)               colors().GetBreak(segment->char_range.start());
871d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)           it != colors().breaks().end() &&
872d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)               it->first < segment->char_range.end();
873d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)           ++it) {
874d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)        const Range intersection =
875d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)            colors().GetRange(it).Intersect(segment->char_range);
876d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)        const Range colored_glyphs = CharRangeToGlyphRange(*run, intersection);
877010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)        // The range may be empty if a portion of a multi-character grapheme is
878010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)        // selected, yielding two colors for a single glyph. For now, this just
879010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)        // paints the glyph with a single style, but it should paint it twice,
880010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)        // clipped according to selection bounds. See http://crbug.com/366786
881010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)        if (colored_glyphs.is_empty())
882010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)          continue;
883d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)        DCHECK(glyph_range.Contains(colored_glyphs));
884d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)        const SkPoint& start_pos =
885d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)            pos[colored_glyphs.start() - glyph_range.start()];
886d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)        const SkPoint& end_pos =
887d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)            pos[colored_glyphs.end() - glyph_range.start()];
888d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)
889d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)        renderer.SetForegroundColor(it->second);
890d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)        renderer.DrawPosText(&start_pos, &run->glyphs[colored_glyphs.start()],
891d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)                             colored_glyphs.length());
892d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)        renderer.DrawDecorations(start_pos.x(), text_offset.y(),
893d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)                                 SkScalarCeilToInt(end_pos.x() - start_pos.x()),
894d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)                                 run->underline, run->strike,
895d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)                                 run->diagonal_strike);
896d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)      }
897d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)
898d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)      preceding_segment_widths += segment_width;
899d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)    }
900effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch
901effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch    renderer.EndDiagonalStrike();
9025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
903558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch
904558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch  UndoCompositionAndSelectionStyles();
9055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
9065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
9075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void RenderTextWin::ItemizeLogicalText() {
9085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  runs_.clear();
909d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)  string_width_ = 0;
910d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)  multiline_string_size_ = Size();
9115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
9125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Set Uniscribe's base text direction.
9135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  script_state_.uBidiLevel =
9145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      (GetTextDirection() == base::i18n::RIGHT_TO_LEFT) ? 1 : 0;
9155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
9160f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles)  const base::string16& layout_text = GetLayoutText();
9170f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles)  if (layout_text.empty())
9185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return;
9195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
9205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  HRESULT hr = E_OUTOFMEMORY;
9215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int script_items_count = 0;
9225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  std::vector<SCRIPT_ITEM> script_items;
9230f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles)  const size_t layout_text_length = layout_text.length();
924eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  // Ensure that |kMaxRuns| is attempted and the loop terminates afterward.
925eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  for (size_t runs = kGuessRuns; hr == E_OUTOFMEMORY && runs <= kMaxRuns;
926eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch       runs = std::max(runs + 1, std::min(runs * 2, kMaxRuns))) {
9275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // Derive the array of Uniscribe script items from the logical text.
928eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    // ScriptItemize always adds a terminal array item so that the length of
929eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    // the last item can be derived from the terminal SCRIPT_ITEM::iCharPos.
930eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    script_items.resize(runs);
9310f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles)    hr = ScriptItemize(layout_text.c_str(), layout_text_length, runs - 1,
9320f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles)                       &script_control_, &script_state_, &script_items[0],
9330f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles)                       &script_items_count);
9345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
9355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(SUCCEEDED(hr));
936eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  if (!SUCCEEDED(hr) || script_items_count <= 0)
9375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return;
9385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
9392a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // Temporarily apply composition underlines and selection colors.
9402a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  ApplyCompositionAndSelectionStyles();
9412a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
942558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch  // Build the list of runs from the script items and ranged styles. Use an
943558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch  // empty color BreakList to avoid breaking runs at color boundaries.
944558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch  BreakList<SkColor> empty_colors;
9450f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles)  empty_colors.SetMax(layout_text_length);
946558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch  internal::StyleIterator style(empty_colors, styles());
9475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  SCRIPT_ITEM* script_item = &script_items[0];
948eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  const size_t max_run_length = kMaxGlyphs / 2;
9492a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  for (size_t run_break = 0; run_break < layout_text_length;) {
9505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    internal::TextRun* run = new internal::TextRun();
9515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    run->range.set_start(run_break);
9525d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    run->font = font_list().GetPrimaryFont();
9532a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    run->font_style = (style.style(BOLD) ? Font::BOLD : 0) |
9542a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                      (style.style(ITALIC) ? Font::ITALIC : 0);
9555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    DeriveFontIfNecessary(run->font.GetFontSize(), run->font.GetHeight(),
9565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                          run->font_style, &run->font);
9572a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    run->strike = style.style(STRIKE);
9582a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    run->diagonal_strike = style.style(DIAGONAL_STRIKE);
9592a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    run->underline = style.style(UNDERLINE);
9605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    run->script_analysis = script_item->a;
9615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
9622a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    // Find the next break and advance the iterators as needed.
9632a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    const size_t script_item_break = (script_item + 1)->iCharPos;
9642a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    run_break = std::min(script_item_break,
9652a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                         TextIndexToLayoutIndex(style.GetRange().end()));
9660f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles)
967eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    // Clamp run lengths to avoid exceeding the maximum supported glyph count.
9680f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles)    if ((run_break - run->range.start()) > max_run_length) {
969eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch      run_break = run->range.start() + max_run_length;
9700f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles)      if (!IsValidCodePointIndex(layout_text, run_break))
9710f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles)        --run_break;
9720f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles)    }
9730f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles)
974f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    // Break runs adjacent to character substrings in certain code blocks.
9750f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles)    // This avoids using their fallback fonts for more characters than needed,
9760f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles)    // in cases like "\x25B6 Media Title", etc. http://crbug.com/278913
9770f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles)    if (run_break > run->range.start()) {
978f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)      run_break =
979f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)          FindUnusualCharacter(layout_text, run->range.start(), run_break);
9800f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles)    }
9810f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles)
9820f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles)    DCHECK(IsValidCodePointIndex(layout_text, run_break));
9830f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles)
9842a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    style.UpdatePosition(LayoutIndexToTextIndex(run_break));
9852a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    if (script_item_break == run_break)
9865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      script_item++;
9875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    run->range.set_end(run_break);
9885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    runs_.push_back(run);
9895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
9902a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
9912a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // Undo the temporarily applied composition underlines and selection colors.
9922a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  UndoCompositionAndSelectionStyles();
9935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
9945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
9955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void RenderTextWin::LayoutVisualText() {
9965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(!runs_.empty());
9975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
9985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!cached_hdc_)
9995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    cached_hdc_ = CreateCompatibleDC(NULL);
10005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
10015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  HRESULT hr = E_FAIL;
1002a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  // Ensure ascent and descent are not smaller than ones of the font list.
1003a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  // Keep them tall enough to draw often-used characters.
1004a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  // For example, if a text field contains a Japanese character, which is
1005a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  // smaller than Latin ones, and then later a Latin one is inserted, this
1006a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  // ensures that the text baseline does not shift.
1007bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdoch  int ascent = font_list().GetBaseline();
1008bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdoch  int descent = font_list().GetHeight() - font_list().GetBaseline();
10095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  for (size_t i = 0; i < runs_.size(); ++i) {
10105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    internal::TextRun* run = runs_[i];
10115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    LayoutTextRun(run);
10125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1013bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdoch    ascent = std::max(ascent, run->font.GetBaseline());
1014bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdoch    descent = std::max(descent,
1015bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdoch                       run->font.GetHeight() - run->font.GetBaseline());
10165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
10175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (run->glyph_count > 0) {
10185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      run->advance_widths.reset(new int[run->glyph_count]);
10195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      run->offsets.reset(new GOFFSET[run->glyph_count]);
10205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      hr = ScriptPlace(cached_hdc_,
10215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                       &run->script_cache,
10225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                       run->glyphs.get(),
10235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                       run->glyph_count,
10245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                       run->visible_attributes.get(),
10255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                       &(run->script_analysis),
10265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                       run->advance_widths.get(),
10275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                       run->offsets.get(),
10285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                       &(run->abc_widths));
10295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      DCHECK(SUCCEEDED(hr));
10305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
10315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
10325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
10335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Build the array of bidirectional embedding levels.
10342a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  scoped_ptr<BYTE[]> levels(new BYTE[runs_.size()]);
10355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  for (size_t i = 0; i < runs_.size(); ++i)
10365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    levels[i] = runs_[i]->script_analysis.s.uBidiLevel;
10375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
10385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Get the maps between visual and logical run indices.
10395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  visual_to_logical_.reset(new int[runs_.size()]);
10405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  logical_to_visual_.reset(new int[runs_.size()]);
10415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  hr = ScriptLayout(runs_.size(),
10425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                    levels.get(),
10435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                    visual_to_logical_.get(),
10445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                    logical_to_visual_.get());
10455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(SUCCEEDED(hr));
10465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
10475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Precalculate run width information.
10485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  size_t preceding_run_widths = 0;
10495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  for (size_t i = 0; i < runs_.size(); ++i) {
10505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    internal::TextRun* run = runs_[visual_to_logical_[i]];
10515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    run->preceding_run_widths = preceding_run_widths;
10525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const ABC& abc = run->abc_widths;
10535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    run->width = abc.abcA + abc.abcB + abc.abcC;
10545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    preceding_run_widths += run->width;
10555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1056d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)  string_width_ = preceding_run_widths;
10575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
10585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
10595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void RenderTextWin::LayoutTextRun(internal::TextRun* run) {
10605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const size_t run_length = run->range.length();
10615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const wchar_t* run_text = &(GetLayoutText()[run->range.start()]);
10625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  Font original_font = run->font;
10635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  LinkedFontsIterator fonts(original_font);
10645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  bool tried_cached_font = false;
10655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  bool tried_fallback = false;
10665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Keep track of the font that is able to display the greatest number of
10675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // characters for which ScriptShape() returned S_OK. This font will be used
10685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // in the case where no font is able to display the entire run.
10695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int best_partial_font_missing_char_count = INT_MAX;
10705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  Font best_partial_font = original_font;
10715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  Font current_font;
10725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
10735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  run->logical_clusters.reset(new WORD[run_length]);
10745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  while (fonts.NextFont(&current_font)) {
10755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    HRESULT hr = ShapeTextRunWithFont(run, current_font);
10765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
10775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    bool glyphs_missing = false;
10785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (hr == USP_E_SCRIPT_NOT_IN_FONT) {
10795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      glyphs_missing = true;
10805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    } else if (hr == S_OK) {
10815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      // If |hr| is S_OK, there could still be missing glyphs in the output.
10825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      // http://msdn.microsoft.com/en-us/library/windows/desktop/dd368564.aspx
10835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      const int missing_count = CountCharsWithMissingGlyphs(run);
10845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      // Track the font that produced the least missing glyphs.
10855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      if (missing_count < best_partial_font_missing_char_count) {
10865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        best_partial_font_missing_char_count = missing_count;
10875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        best_partial_font = run->font;
10885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      }
10895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      glyphs_missing = (missing_count != 0);
10905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    } else {
10915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      NOTREACHED() << hr;
10925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
10935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
10945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // Use the font if it had glyphs for all characters.
10955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (!glyphs_missing) {
10965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      // Save the successful fallback font that was chosen.
10975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      if (tried_fallback)
10985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        successful_substitute_fonts_[original_font.GetFontName()] = run->font;
10995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return;
11005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
11015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
11025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // First, try the cached font from previous runs, if any.
11035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (!tried_cached_font) {
11045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      tried_cached_font = true;
11055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
11065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      std::map<std::string, Font>::const_iterator it =
11075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          successful_substitute_fonts_.find(original_font.GetFontName());
11085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      if (it != successful_substitute_fonts_.end()) {
11095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        fonts.SetNextFont(it->second);
11105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        continue;
11115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      }
11125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
11135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
11145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // If there are missing glyphs, first try finding a fallback font using a
11155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // meta file, if it hasn't yet been attempted for this run.
11165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // TODO(msw|asvitkine): Support RenderText's font_list()?
11175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (!tried_fallback) {
11185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      tried_fallback = true;
11195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
11205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      Font fallback_font;
11215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      if (ChooseFallbackFont(cached_hdc_, run->font, run_text, run_length,
11225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                             &fallback_font)) {
11235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        fonts.SetNextFont(fallback_font);
11245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        continue;
11255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      }
11265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
11275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
11285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
11295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // If a font was able to partially display the run, use that now.
11305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (best_partial_font_missing_char_count < static_cast<int>(run_length)) {
11315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // Re-shape the run only if |best_partial_font| differs from the last font.
11325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (best_partial_font.GetNativeFont() != run->font.GetNativeFont())
11335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      ShapeTextRunWithFont(run, best_partial_font);
11345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return;
11355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
11365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
11375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // If no font was able to partially display the run, replace all glyphs
11385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // with |wgDefault| from the original font to ensure to they don't hold
11395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // garbage values.
11405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // First, clear the cache and select the original font on the HDC.
11415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ScriptFreeCache(&run->script_cache);
11425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  run->font = original_font;
11435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  SelectObject(cached_hdc_, run->font.GetNativeFont());
11445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
11455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Now, get the font's properties.
11465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  SCRIPT_FONTPROPERTIES properties;
11475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  memset(&properties, 0, sizeof(properties));
11485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  properties.cBytes = sizeof(properties);
11495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  HRESULT hr = ScriptGetFontProperties(cached_hdc_, &run->script_cache,
11505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                       &properties);
1151558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch
1152558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch  // The initial values for the "missing" glyph and the space glyph are taken
1153558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch  // from the recommendations section of the OpenType spec:
1154558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch  // https://www.microsoft.com/typography/otspec/recom.htm
1155558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch  WORD missing_glyph = 0;
1156558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch  WORD space_glyph = 3;
11575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (hr == S_OK) {
1158558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch    missing_glyph = properties.wgDefault;
1159558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch    space_glyph = properties.wgBlank;
1160558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch  }
1161558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch
1162558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch  // Finally, initialize |glyph_count|, |glyphs|, |visible_attributes| and
1163558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch  // |logical_clusters| on the run (since they may not have been set yet).
1164558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch  run->glyph_count = run_length;
1165558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch  memset(run->visible_attributes.get(), 0,
1166558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch         run->glyph_count * sizeof(SCRIPT_VISATTR));
1167558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch  for (int i = 0; i < run->glyph_count; ++i)
1168558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch    run->glyphs[i] = IsWhitespace(run_text[i]) ? space_glyph : missing_glyph;
1169558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch  for (size_t i = 0; i < run_length; ++i) {
1170558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch    run->logical_clusters[i] = run->script_analysis.fRTL ?
1171558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch        run_length - 1 - i : i;
11725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
11735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
11745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // TODO(msw): Don't use SCRIPT_UNDEFINED. Apparently Uniscribe can
11755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  //            crash on certain surrogate pairs with SCRIPT_UNDEFINED.
11765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  //            See https://bugzilla.mozilla.org/show_bug.cgi?id=341500
11775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  //            And http://maxradi.us/documents/uniscribe/
11785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  run->script_analysis.eScript = SCRIPT_UNDEFINED;
11795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
11805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
11815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)HRESULT RenderTextWin::ShapeTextRunWithFont(internal::TextRun* run,
11825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                            const Font& font) {
11835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Update the run's font only if necessary. If the two fonts wrap the same
11845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // PlatformFontWin object, their native fonts will have the same value.
11855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (run->font.GetNativeFont() != font.GetNativeFont()) {
11865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const int font_size = run->font.GetFontSize();
11875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const int font_height = run->font.GetHeight();
11885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    run->font = font;
11895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    DeriveFontIfNecessary(font_size, font_height, run->font_style, &run->font);
11905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    ScriptFreeCache(&run->script_cache);
11915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
11925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
11935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Select the font desired for glyph generation.
11945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  SelectObject(cached_hdc_, run->font.GetNativeFont());
11955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
11965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  HRESULT hr = E_OUTOFMEMORY;
11975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const size_t run_length = run->range.length();
11985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const wchar_t* run_text = &(GetLayoutText()[run->range.start()]);
1199eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  // Guess the expected number of glyphs from the length of the run.
1200eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  // MSDN suggests this at http://msdn.microsoft.com/en-us/library/dd368564.aspx
12015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  size_t max_glyphs = static_cast<size_t>(1.5 * run_length + 16);
1202eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  while (hr == E_OUTOFMEMORY && max_glyphs <= kMaxGlyphs) {
12035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    run->glyph_count = 0;
12045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    run->glyphs.reset(new WORD[max_glyphs]);
12055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    run->visible_attributes.reset(new SCRIPT_VISATTR[max_glyphs]);
1206eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    hr = ScriptShape(cached_hdc_, &run->script_cache, run_text, run_length,
1207eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch                     max_glyphs, &run->script_analysis, run->glyphs.get(),
1208eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch                     run->logical_clusters.get(), run->visible_attributes.get(),
12095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                     &run->glyph_count);
1210eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    // Ensure that |kMaxGlyphs| is attempted and the loop terminates afterward.
1211eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    max_glyphs = std::max(max_glyphs + 1, std::min(max_glyphs * 2, kMaxGlyphs));
12125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
12135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return hr;
12145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
12155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
12165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)int RenderTextWin::CountCharsWithMissingGlyphs(internal::TextRun* run) const {
12175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int chars_not_missing_glyphs = 0;
12185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  SCRIPT_FONTPROPERTIES properties;
12195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  memset(&properties, 0, sizeof(properties));
12205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  properties.cBytes = sizeof(properties);
12215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ScriptGetFontProperties(cached_hdc_, &run->script_cache, &properties);
12225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
12235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const wchar_t* run_text = &(GetLayoutText()[run->range.start()]);
12245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  for (size_t char_index = 0; char_index < run->range.length(); ++char_index) {
12255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const int glyph_index = run->logical_clusters[char_index];
12265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    DCHECK_GE(glyph_index, 0);
12275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    DCHECK_LT(glyph_index, run->glyph_count);
12285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
12295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (run->glyphs[glyph_index] == properties.wgDefault)
12305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      continue;
12315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
12325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // Windows Vista sometimes returns glyphs equal to wgBlank (instead of
12335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // wgDefault), with fZeroWidth set. Treat such cases as having missing
12345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // glyphs if the corresponding character is not whitespace.
12355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // See: http://crbug.com/125629
12365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (run->glyphs[glyph_index] == properties.wgBlank &&
12375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        run->visible_attributes[glyph_index].fZeroWidth &&
12385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        !IsWhitespace(run_text[char_index]) &&
12395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        !IsUnicodeBidiControlCharacter(run_text[char_index])) {
12405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      continue;
12415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
12425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
12435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    ++chars_not_missing_glyphs;
12445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
12455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
12465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK_LE(chars_not_missing_glyphs, static_cast<int>(run->range.length()));
12475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return run->range.length() - chars_not_missing_glyphs;
12485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
12495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
12505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)size_t RenderTextWin::GetRunContainingCaret(const SelectionModel& caret) const {
12515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(!needs_layout_);
12525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  size_t layout_position = TextIndexToLayoutIndex(caret.caret_pos());
12535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  LogicalCursorDirection affinity = caret.caret_affinity();
125490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  for (size_t run = 0; run < runs_.size(); ++run)
12555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (RangeContainsCaret(runs_[run]->range, layout_position, affinity))
125690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)      return run;
125790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  return runs_.size();
12585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
12595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
126090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)size_t RenderTextWin::GetRunContainingXCoord(int x) const {
12615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(!needs_layout_);
12625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Find the text run containing the argument point (assumed already offset).
126390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  for (size_t run = 0; run < runs_.size(); ++run) {
126490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    if ((runs_[run]->preceding_run_widths <= x) &&
126590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)        ((runs_[run]->preceding_run_widths + runs_[run]->width) > x))
126690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)      return run;
126790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  }
126890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  return runs_.size();
12695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
12705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
12715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)SelectionModel RenderTextWin::FirstSelectionModelInsideRun(
12725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const internal::TextRun* run) {
12735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  size_t position = LayoutIndexToTextIndex(run->range.start());
12745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  position = IndexOfAdjacentGrapheme(position, CURSOR_FORWARD);
12755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return SelectionModel(position, CURSOR_BACKWARD);
12765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
12775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
12785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)SelectionModel RenderTextWin::LastSelectionModelInsideRun(
12795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const internal::TextRun* run) {
12805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  size_t position = LayoutIndexToTextIndex(run->range.end());
12815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  position = IndexOfAdjacentGrapheme(position, CURSOR_BACKWARD);
12825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return SelectionModel(position, CURSOR_FORWARD);
12835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
12845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1285cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)RenderText* RenderText::CreateNativeInstance() {
12865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return new RenderTextWin;
12875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
12885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
12895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}  // namespace gfx
1290