| OLD | NEW |
| 1 // Copyright (c) 2010 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2010 The Chromium Authors. All rights reserved. |
| 2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 #include "gfx/canvas_skia.h" | 5 #include "gfx/canvas_skia.h" |
| 6 | 6 |
| 7 #include <limits> | 7 #include <limits> |
| 8 | 8 |
| 9 #include "base/i18n/rtl.h" | 9 #include "base/i18n/rtl.h" |
| 10 #include "gfx/font.h" | 10 #include "gfx/font.h" |
| 11 #include "gfx/rect.h" | 11 #include "gfx/rect.h" |
| 12 #include "third_party/skia/include/core/SkShader.h" | 12 #include "third_party/skia/include/core/SkShader.h" |
| 13 | 13 |
| 14 namespace { | 14 namespace { |
| 15 | 15 |
| 16 // We make sure that LTR text we draw in an RTL context is modified | 16 // We make sure that LTR text we draw in an RTL context is modified |
| 17 // appropriately to make sure it maintains it LTR orientation. | 17 // appropriately to make sure it maintains it LTR orientation. |
| 18 void DoDrawText(HDC hdc, | 18 void DoDrawText(HDC hdc, |
| 19 const std::wstring& text, | 19 const string16& text, |
| 20 RECT* text_bounds, | 20 RECT* text_bounds, |
| 21 int flags) { | 21 int flags) { |
| 22 // Only adjust string directionality if both of the following are true: | 22 // Only adjust string directionality if both of the following are true: |
| 23 // 1. The current locale is RTL. | 23 // 1. The current locale is RTL. |
| 24 // 2. The string itself has RTL directionality. | 24 // 2. The string itself has RTL directionality. |
| 25 const wchar_t* string_ptr = text.c_str(); | 25 const wchar_t* string_ptr = text.c_str(); |
| 26 int string_size = static_cast<int>(text.length()); | 26 int string_size = static_cast<int>(text.length()); |
| 27 | 27 |
| 28 std::wstring localized_text; | 28 string16 localized_text; |
| 29 if (flags & DT_RTLREADING) { | 29 if (flags & DT_RTLREADING) { |
| 30 localized_text = text; | 30 localized_text = text; |
| 31 base::i18n::AdjustStringForLocaleDirection(&localized_text); | 31 base::i18n::AdjustStringForLocaleDirection(&localized_text); |
| 32 string_ptr = localized_text.c_str(); | 32 string_ptr = localized_text.c_str(); |
| 33 string_size = static_cast<int>(localized_text.length()); | 33 string_size = static_cast<int>(localized_text.length()); |
| 34 } | 34 } |
| 35 | 35 |
| 36 DrawText(hdc, string_ptr, string_size, text_bounds, flags); | 36 DrawText(hdc, string_ptr, string_size, text_bounds, flags); |
| 37 } | 37 } |
| 38 | 38 |
| 39 // Compute the windows flags necessary to implement the provided text Canvas | 39 // Compute the windows flags necessary to implement the provided text Canvas |
| 40 // flags. | 40 // flags. |
| 41 int ComputeFormatFlags(int flags, const std::wstring& text) { | 41 int ComputeFormatFlags(int flags, const string16& text) { |
| 42 // Setting the text alignment explicitly in case it hasn't already been set. | 42 // Setting the text alignment explicitly in case it hasn't already been set. |
| 43 // This will make sure that we don't align text to the left on RTL locales | 43 // This will make sure that we don't align text to the left on RTL locales |
| 44 // just because no alignment flag was passed to DrawStringInt(). | 44 // just because no alignment flag was passed to DrawStringInt(). |
| 45 if (!(flags & (gfx::Canvas::TEXT_ALIGN_CENTER | | 45 if (!(flags & (gfx::Canvas::TEXT_ALIGN_CENTER | |
| 46 gfx::Canvas::TEXT_ALIGN_RIGHT | | 46 gfx::Canvas::TEXT_ALIGN_RIGHT | |
| 47 gfx::Canvas::TEXT_ALIGN_LEFT))) { | 47 gfx::Canvas::TEXT_ALIGN_LEFT))) { |
| 48 flags |= gfx::CanvasSkia::DefaultCanvasTextAlignment(); | 48 flags |= gfx::CanvasSkia::DefaultCanvasTextAlignment(); |
| 49 } | 49 } |
| 50 | 50 |
| 51 // horizontal alignment | 51 // horizontal alignment |
| (...skipping 80 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 132 : skia::PlatformCanvas(width, height, is_opaque) { | 132 : skia::PlatformCanvas(width, height, is_opaque) { |
| 133 } | 133 } |
| 134 | 134 |
| 135 CanvasSkia::CanvasSkia() : skia::PlatformCanvas() { | 135 CanvasSkia::CanvasSkia() : skia::PlatformCanvas() { |
| 136 } | 136 } |
| 137 | 137 |
| 138 CanvasSkia::~CanvasSkia() { | 138 CanvasSkia::~CanvasSkia() { |
| 139 } | 139 } |
| 140 | 140 |
| 141 // static | 141 // static |
| 142 void CanvasSkia::SizeStringInt(const std::wstring& text, | 142 void CanvasSkia::SizeStringInt(const string16& text, |
| 143 const gfx::Font& font, | 143 const gfx::Font& font, |
| 144 int* width, int* height, | 144 int* width, int* height, |
| 145 int flags) { | 145 int flags) { |
| 146 // Clamp the max amount of text we'll measure to 2K. When the string is | 146 // Clamp the max amount of text we'll measure to 2K. When the string is |
| 147 // actually drawn, it will be clipped to whatever size box is provided, and | 147 // actually drawn, it will be clipped to whatever size box is provided, and |
| 148 // the time to do that doesn't depend on the length being clipped off. | 148 // the time to do that doesn't depend on the length being clipped off. |
| 149 const int kMaxStringLength = 2048 - 1; // So the trailing \0 fits in 2K. | 149 const int kMaxStringLength = 2048 - 1; // So the trailing \0 fits in 2K. |
| 150 std::wstring clamped_string(text.substr(0, kMaxStringLength)); | 150 string16 clamped_string(text.substr(0, kMaxStringLength)); |
| 151 | 151 |
| 152 if (*width == 0) { | 152 if (*width == 0) { |
| 153 // If multi-line + character break are on, the computed width will be one | 153 // If multi-line + character break are on, the computed width will be one |
| 154 // character wide (useless). Furthermore, if in this case the provided text | 154 // character wide (useless). Furthermore, if in this case the provided text |
| 155 // contains very long "words" (substrings without a word-breaking point), | 155 // contains very long "words" (substrings without a word-breaking point), |
| 156 // DrawText() can run extremely slowly (e.g. several seconds). So in this | 156 // DrawText() can run extremely slowly (e.g. several seconds). So in this |
| 157 // case, we turn character breaking off to get a more accurate "desired" | 157 // case, we turn character breaking off to get a more accurate "desired" |
| 158 // width and avoid the slowdown. | 158 // width and avoid the slowdown. |
| 159 if (flags & (gfx::Canvas::MULTI_LINE | gfx::Canvas::CHARACTER_BREAK)) | 159 if (flags & (gfx::Canvas::MULTI_LINE | gfx::Canvas::CHARACTER_BREAK)) |
| 160 flags &= ~gfx::Canvas::CHARACTER_BREAK; | 160 flags &= ~gfx::Canvas::CHARACTER_BREAK; |
| 161 | 161 |
| 162 // Weird undocumented behavior: if the width is 0, DoDrawText() won't | 162 // Weird undocumented behavior: if the width is 0, DoDrawText() won't |
| 163 // calculate a size at all. So set it to 1, which it will then change. | 163 // calculate a size at all. So set it to 1, which it will then change. |
| 164 if (!text.empty()) | 164 if (!text.empty()) |
| 165 *width = 1; | 165 *width = 1; |
| 166 } | 166 } |
| 167 RECT r = { 0, 0, *width, *height }; | 167 RECT r = { 0, 0, *width, *height }; |
| 168 | 168 |
| 169 HDC dc = GetDC(NULL); | 169 HDC dc = GetDC(NULL); |
| 170 HFONT old_font = static_cast<HFONT>(SelectObject(dc, font.GetNativeFont())); | 170 HFONT old_font = static_cast<HFONT>(SelectObject(dc, font.GetNativeFont())); |
| 171 DoDrawText(dc, clamped_string, &r, | 171 DoDrawText(dc, clamped_string, &r, |
| 172 ComputeFormatFlags(flags, clamped_string) | DT_CALCRECT); | 172 ComputeFormatFlags(flags, clamped_string) | DT_CALCRECT); |
| 173 SelectObject(dc, old_font); | 173 SelectObject(dc, old_font); |
| 174 ReleaseDC(NULL, dc); | 174 ReleaseDC(NULL, dc); |
| 175 | 175 |
| 176 *width = r.right; | 176 *width = r.right; |
| 177 *height = r.bottom; | 177 *height = r.bottom; |
| 178 } | 178 } |
| 179 | 179 |
| 180 void CanvasSkia::DrawStringInt(const std::wstring& text, | 180 void CanvasSkia::DrawStringInt(const string16& text, |
| 181 HFONT font, | 181 HFONT font, |
| 182 const SkColor& color, | 182 const SkColor& color, |
| 183 int x, int y, int w, int h, | 183 int x, int y, int w, int h, |
| 184 int flags) { | 184 int flags) { |
| 185 if (!IntersectsClipRectInt(x, y, w, h)) | 185 if (!IntersectsClipRectInt(x, y, w, h)) |
| 186 return; | 186 return; |
| 187 | 187 |
| 188 // Clamp the max amount of text we'll draw to 32K. There seem to be bugs in | 188 // Clamp the max amount of text we'll draw to 32K. There seem to be bugs in |
| 189 // DrawText() if you e.g. ask it to character-break a no-whitespace string of | 189 // DrawText() if you e.g. ask it to character-break a no-whitespace string of |
| 190 // length > 43680 (for which it draws nothing), and since we clamped to 2K in | 190 // length > 43680 (for which it draws nothing), and since we clamped to 2K in |
| 191 // SizeStringInt() we're unlikely to be able to display this much anyway. | 191 // SizeStringInt() we're unlikely to be able to display this much anyway. |
| 192 const int kMaxStringLength = 32768 - 1; // So the trailing \0 fits in 32K. | 192 const int kMaxStringLength = 32768 - 1; // So the trailing \0 fits in 32K. |
| 193 std::wstring clamped_string(text.substr(0, kMaxStringLength)); | 193 string16 clamped_string(text.substr(0, kMaxStringLength)); |
| 194 | 194 |
| 195 RECT text_bounds = { x, y, x + w, y + h }; | 195 RECT text_bounds = { x, y, x + w, y + h }; |
| 196 HDC dc = beginPlatformPaint(); | 196 HDC dc = beginPlatformPaint(); |
| 197 SetBkMode(dc, TRANSPARENT); | 197 SetBkMode(dc, TRANSPARENT); |
| 198 HFONT old_font = (HFONT)SelectObject(dc, font); | 198 HFONT old_font = (HFONT)SelectObject(dc, font); |
| 199 COLORREF brush_color = RGB(SkColorGetR(color), SkColorGetG(color), | 199 COLORREF brush_color = RGB(SkColorGetR(color), SkColorGetG(color), |
| 200 SkColorGetB(color)); | 200 SkColorGetB(color)); |
| 201 SetTextColor(dc, brush_color); | 201 SetTextColor(dc, brush_color); |
| 202 | 202 |
| 203 int f = ComputeFormatFlags(flags, clamped_string); | 203 int f = ComputeFormatFlags(flags, clamped_string); |
| 204 DoDrawText(dc, clamped_string, &text_bounds, f); | 204 DoDrawText(dc, clamped_string, &text_bounds, f); |
| 205 endPlatformPaint(); | 205 endPlatformPaint(); |
| 206 | 206 |
| 207 // Restore the old font. This way we don't have to worry if the caller | 207 // Restore the old font. This way we don't have to worry if the caller |
| 208 // deletes the font and the DC lives longer. | 208 // deletes the font and the DC lives longer. |
| 209 SelectObject(dc, old_font); | 209 SelectObject(dc, old_font); |
| 210 | 210 |
| 211 // Windows will have cleared the alpha channel of the text we drew. Assume | 211 // Windows will have cleared the alpha channel of the text we drew. Assume |
| 212 // we're drawing to an opaque surface, or at least the text rect area is | 212 // we're drawing to an opaque surface, or at least the text rect area is |
| 213 // opaque. | 213 // opaque. |
| 214 getTopPlatformDevice().makeOpaque(x, y, w, h); | 214 getTopPlatformDevice().makeOpaque(x, y, w, h); |
| 215 } | 215 } |
| 216 | 216 |
| 217 void CanvasSkia::DrawStringInt(const std::wstring& text, | 217 void CanvasSkia::DrawStringInt(const string16& text, |
| 218 const gfx::Font& font, | 218 const gfx::Font& font, |
| 219 const SkColor& color, | 219 const SkColor& color, |
| 220 int x, int y, int w, int h, | 220 int x, int y, int w, int h, |
| 221 int flags) { | 221 int flags) { |
| 222 DrawStringInt(text, font.GetNativeFont(), color, x, y, w, h, flags); | 222 DrawStringInt(text, font.GetNativeFont(), color, x, y, w, h, flags); |
| 223 } | 223 } |
| 224 | 224 |
| 225 // Checks each pixel immediately adjacent to the given pixel in the bitmap. If | 225 // Checks each pixel immediately adjacent to the given pixel in the bitmap. If |
| 226 // any of them are not the halo color, returns true. This defines the halo of | 226 // any of them are not the halo color, returns true. This defines the halo of |
| 227 // pixels that will appear around the text. Note that we have to check each | 227 // pixels that will appear around the text. Note that we have to check each |
| (...skipping 15 matching lines...) Expand all Loading... |
| 243 *bitmap.getAddr32(x, y - 1) != halo_color && | 243 *bitmap.getAddr32(x, y - 1) != halo_color && |
| 244 *bitmap.getAddr32(x, y - 1) != 0) | 244 *bitmap.getAddr32(x, y - 1) != 0) |
| 245 return true; // Touched pixel above. | 245 return true; // Touched pixel above. |
| 246 if (y < bitmap.height() - 1 && | 246 if (y < bitmap.height() - 1 && |
| 247 *bitmap.getAddr32(x, y + 1) != halo_color && | 247 *bitmap.getAddr32(x, y + 1) != halo_color && |
| 248 *bitmap.getAddr32(x, y + 1) != 0) | 248 *bitmap.getAddr32(x, y + 1) != 0) |
| 249 return true; // Touched pixel below. | 249 return true; // Touched pixel below. |
| 250 return false; | 250 return false; |
| 251 } | 251 } |
| 252 | 252 |
| 253 void CanvasSkia::DrawStringWithHalo(const std::wstring& text, | 253 void CanvasSkia::DrawStringWithHalo(const string16& text, |
| 254 const gfx::Font& font, | 254 const gfx::Font& font, |
| 255 const SkColor& text_color, | 255 const SkColor& text_color, |
| 256 const SkColor& halo_color_in, | 256 const SkColor& halo_color_in, |
| 257 int x, int y, int w, int h, | 257 int x, int y, int w, int h, |
| 258 int flags) { | 258 int flags) { |
| 259 // Some callers will have semitransparent halo colors, which we don't handle | 259 // Some callers will have semitransparent halo colors, which we don't handle |
| 260 // (since the resulting image can have 1-bit transparency only). | 260 // (since the resulting image can have 1-bit transparency only). |
| 261 SkColor halo_color = halo_color_in | 0xFF000000; | 261 SkColor halo_color = halo_color_in | 0xFF000000; |
| 262 | 262 |
| 263 // Create a temporary buffer filled with the halo color. It must leave room | 263 // Create a temporary buffer filled with the halo color. It must leave room |
| (...skipping 28 matching lines...) Expand all Loading... |
| 292 text_row[cur_x] |= 0xff << SK_A32_SHIFT; // Make opaque. | 292 text_row[cur_x] |= 0xff << SK_A32_SHIFT; // Make opaque. |
| 293 } | 293 } |
| 294 } | 294 } |
| 295 } | 295 } |
| 296 | 296 |
| 297 // Draw the halo bitmap with blur. | 297 // Draw the halo bitmap with blur. |
| 298 DrawBitmapInt(text_bitmap, x - 1, y - 1); | 298 DrawBitmapInt(text_bitmap, x - 1, y - 1); |
| 299 } | 299 } |
| 300 | 300 |
| 301 } // namespace gfx | 301 } // namespace gfx |
| OLD | NEW |