diff options
Diffstat (limited to 'app/gfx/canvas_win.cc')
-rw-r--r-- | app/gfx/canvas_win.cc | 94 |
1 files changed, 54 insertions, 40 deletions
diff --git a/app/gfx/canvas_win.cc b/app/gfx/canvas_win.cc index 8b5e685..f35fab8 100644 --- a/app/gfx/canvas_win.cc +++ b/app/gfx/canvas_win.cc @@ -1,4 +1,4 @@ -// Copyright (c) 2006-2008 The Chromium Authors. All rights reserved. +// Copyright (c) 2010 The Chromium Authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. @@ -36,8 +36,6 @@ void DoDrawText(HDC hdc, const std::wstring& text, // Compute the windows flags necessary to implement the provided text Canvas // flags. int ComputeFormatFlags(int flags, const std::wstring& text) { - int f = 0; - // Setting the text alignment explicitly in case it hasn't already been set. // This will make sure that we don't align text to the left on RTL locales // just because no alignment flag was passed to DrawStringInt(). @@ -47,20 +45,14 @@ int ComputeFormatFlags(int flags, const std::wstring& text) { flags |= l10n_util::DefaultCanvasTextAlignment(); } - if (flags & gfx::Canvas::HIDE_PREFIX) - f |= DT_HIDEPREFIX; - else if ((flags & gfx::Canvas::SHOW_PREFIX) == 0) - f |= DT_NOPREFIX; - - if (flags & gfx::Canvas::MULTI_LINE) { - f |= DT_WORDBREAK; - if (flags & gfx::Canvas::CHARACTER_BREAK) - f |= DT_EDITCONTROL; - } else { - f |= DT_SINGLELINE | DT_VCENTER; - if (!(flags & gfx::Canvas::NO_ELLIPSIS)) - f |= DT_END_ELLIPSIS; - } + // horizontal alignment + int f = 0; + if (flags & gfx::Canvas::TEXT_ALIGN_CENTER) + f |= DT_CENTER; + else if (flags & gfx::Canvas::TEXT_ALIGN_RIGHT) + f |= DT_RIGHT; + else + f |= DT_LEFT; // vertical alignment if (flags & gfx::Canvas::TEXT_VALIGN_TOP) @@ -70,13 +62,23 @@ int ComputeFormatFlags(int flags, const std::wstring& text) { else f |= DT_VCENTER; - // horizontal alignment - if (flags & gfx::Canvas::TEXT_ALIGN_CENTER) - f |= DT_CENTER; - else if (flags & gfx::Canvas::TEXT_ALIGN_RIGHT) - f |= DT_RIGHT; - else - f |= DT_LEFT; + if (flags & gfx::Canvas::MULTI_LINE) { + f |= DT_WORDBREAK; + if (flags & gfx::Canvas::CHARACTER_BREAK) + f |= DT_EDITCONTROL; // Turns on character breaking (not documented) + else if (!(flags & gfx::Canvas::NO_ELLIPSIS)) + f |= DT_WORD_ELLIPSIS; + } else { + f |= DT_SINGLELINE; + } + + if (flags & gfx::Canvas::HIDE_PREFIX) + f |= DT_HIDEPREFIX; + else if ((flags & gfx::Canvas::SHOW_PREFIX) == 0) + f |= DT_NOPREFIX; + + if (!(flags & gfx::Canvas::NO_ELLIPSIS)) + f |= DT_END_ELLIPSIS; // In order to make sure RTL/BiDi strings are rendered correctly, we must // pass the flag DT_RTLREADING to DrawText (when the locale's language is @@ -137,26 +139,38 @@ Canvas::~Canvas() { void Canvas::SizeStringInt(const std::wstring& text, const gfx::Font& font, int *width, int *height, int flags) { - HDC dc = GetDC(NULL); - HFONT old_font = static_cast<HFONT>(SelectObject(dc, font.hfont())); - RECT b; - b.left = 0; - b.top = 0; - b.right = *width; - if (b.right == 0 && !text.empty()) { - // Width needs to be at least 1 or else DoDrawText will not resize it. - b.right = 1; + // Clamp the max amount of text we'll measure to 2K. When the string is + // actually drawn, it will be clipped to whatever size box is provided, and + // the time to do that doesn't depend on the length being clipped off. + const int kMaxStringLength = 2048; + std::wstring clamped_string(text.substr(0, kMaxStringLength)); + + if (*width == 0) { + // If multi-line + character break are on, the computed width will be one + // character wide (useless). Furthermore, if in this case the provided text + // contains very long "words" (substrings without a word-breaking point), + // DrawText() can run extremely slowly (e.g. several seconds). So in this + // case, we turn character breaking off to get a more accurate "desired" + // width and avoid the slowdown. + if (flags & (gfx::Canvas::MULTI_LINE | gfx::Canvas::CHARACTER_BREAK)) + flags &= ~gfx::Canvas::CHARACTER_BREAK; + + // Weird undocumented behavior: if the width is 0, DoDrawText() won't + // calculate a size at all. So set it to 1, which it will then change. + if (!text.empty()) + *width = 1; } - b.bottom = *height; - DoDrawText(dc, text, &b, ComputeFormatFlags(flags, text) | DT_CALCRECT); + RECT r = { 0, 0, *width, *height }; - // Restore the old font. This way we don't have to worry if the caller - // deletes the font and the DC lives longer. + HDC dc = GetDC(NULL); + HFONT old_font = static_cast<HFONT>(SelectObject(dc, font.hfont())); + DoDrawText(dc, clamped_string, &r, + ComputeFormatFlags(flags, clamped_string) | DT_CALCRECT); SelectObject(dc, old_font); - *width = b.right; - *height = b.bottom; - ReleaseDC(NULL, dc); + + *width = r.right; + *height = r.bottom; } void Canvas::DrawStringInt(const std::wstring& text, HFONT font, |