| OLD | NEW |
| 1 // Copyright (c) 2006-2008 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2006-2008 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 "app/gfx/chrome_canvas.h" | 5 #include "app/gfx/canvas.h" |
| 6 | 6 |
| 7 #include <limits> | 7 #include <limits> |
| 8 | 8 |
| 9 #include "app/gfx/chrome_font.h" | 9 #include "app/gfx/font.h" |
| 10 #include "app/l10n_util.h" | 10 #include "app/l10n_util.h" |
| 11 #include "base/gfx/rect.h" | 11 #include "base/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, const std::wstring& text, | 18 void DoDrawText(HDC hdc, const std::wstring& text, |
| 19 RECT* text_bounds, int flags) { | 19 RECT* text_bounds, int flags) { |
| 20 std::wstring localized_text; | 20 std::wstring localized_text; |
| 21 const wchar_t* string_ptr = text.c_str(); | 21 const wchar_t* string_ptr = text.c_str(); |
| 22 int string_size = static_cast<int>(text.length()); | 22 int string_size = static_cast<int>(text.length()); |
| 23 // Only adjust string directionality if both of the following are true: | 23 // Only adjust string directionality if both of the following are true: |
| 24 // 1. The current locale is RTL. | 24 // 1. The current locale is RTL. |
| 25 // 2. The string itself has RTL directionality. | 25 // 2. The string itself has RTL directionality. |
| 26 if (flags & DT_RTLREADING) { | 26 if (flags & DT_RTLREADING) { |
| 27 if (l10n_util::AdjustStringForLocaleDirection(text, &localized_text)) { | 27 if (l10n_util::AdjustStringForLocaleDirection(text, &localized_text)) { |
| 28 string_ptr = localized_text.c_str(); | 28 string_ptr = localized_text.c_str(); |
| 29 string_size = static_cast<int>(localized_text.length()); | 29 string_size = static_cast<int>(localized_text.length()); |
| 30 } | 30 } |
| 31 } | 31 } |
| 32 | 32 |
| 33 DrawText(hdc, string_ptr, string_size, text_bounds, flags); | 33 DrawText(hdc, string_ptr, string_size, text_bounds, flags); |
| 34 } | 34 } |
| 35 | 35 |
| 36 // Compute the windows flags necessary to implement the provided text | 36 // Compute the windows flags necessary to implement the provided text Canvas |
| 37 // ChromeCanvas flags. | 37 // flags. |
| 38 int ComputeFormatFlags(int flags, const std::wstring& text) { | 38 int ComputeFormatFlags(int flags, const std::wstring& text) { |
| 39 int f = 0; | 39 int f = 0; |
| 40 | 40 |
| 41 // Setting the text alignment explicitly in case it hasn't already been set. | 41 // Setting the text alignment explicitly in case it hasn't already been set. |
| 42 // This will make sure that we don't align text to the left on RTL locales | 42 // This will make sure that we don't align text to the left on RTL locales |
| 43 // just because no alignment flag was passed to DrawStringInt(). | 43 // just because no alignment flag was passed to DrawStringInt(). |
| 44 if (!(flags & (ChromeCanvas::TEXT_ALIGN_CENTER | | 44 if (!(flags & (gfx::Canvas::TEXT_ALIGN_CENTER | |
| 45 ChromeCanvas::TEXT_ALIGN_RIGHT | | 45 gfx::Canvas::TEXT_ALIGN_RIGHT | |
| 46 ChromeCanvas::TEXT_ALIGN_LEFT))) { | 46 gfx::Canvas::TEXT_ALIGN_LEFT))) { |
| 47 flags |= l10n_util::DefaultCanvasTextAlignment(); | 47 flags |= l10n_util::DefaultCanvasTextAlignment(); |
| 48 } | 48 } |
| 49 | 49 |
| 50 if (flags & ChromeCanvas::HIDE_PREFIX) | 50 if (flags & gfx::Canvas::HIDE_PREFIX) |
| 51 f |= DT_HIDEPREFIX; | 51 f |= DT_HIDEPREFIX; |
| 52 else if ((flags & ChromeCanvas::SHOW_PREFIX) == 0) | 52 else if ((flags & gfx::Canvas::SHOW_PREFIX) == 0) |
| 53 f |= DT_NOPREFIX; | 53 f |= DT_NOPREFIX; |
| 54 | 54 |
| 55 if (flags & ChromeCanvas::MULTI_LINE) { | 55 if (flags & gfx::Canvas::MULTI_LINE) { |
| 56 f |= DT_WORDBREAK; | 56 f |= DT_WORDBREAK; |
| 57 if (flags & ChromeCanvas::CHARACTER_BREAK) | 57 if (flags & gfx::Canvas::CHARACTER_BREAK) |
| 58 f |= DT_EDITCONTROL; | 58 f |= DT_EDITCONTROL; |
| 59 } else { | 59 } else { |
| 60 f |= DT_SINGLELINE | DT_VCENTER; | 60 f |= DT_SINGLELINE | DT_VCENTER; |
| 61 if (!(flags & ChromeCanvas::NO_ELLIPSIS)) | 61 if (!(flags & gfx::Canvas::NO_ELLIPSIS)) |
| 62 f |= DT_END_ELLIPSIS; | 62 f |= DT_END_ELLIPSIS; |
| 63 } | 63 } |
| 64 | 64 |
| 65 // vertical alignment | 65 // vertical alignment |
| 66 if (flags & ChromeCanvas::TEXT_VALIGN_TOP) | 66 if (flags & gfx::Canvas::TEXT_VALIGN_TOP) |
| 67 f |= DT_TOP; | 67 f |= DT_TOP; |
| 68 else if (flags & ChromeCanvas::TEXT_VALIGN_BOTTOM) | 68 else if (flags & gfx::Canvas::TEXT_VALIGN_BOTTOM) |
| 69 f |= DT_BOTTOM; | 69 f |= DT_BOTTOM; |
| 70 else | 70 else |
| 71 f |= DT_VCENTER; | 71 f |= DT_VCENTER; |
| 72 | 72 |
| 73 // horizontal alignment | 73 // horizontal alignment |
| 74 if (flags & ChromeCanvas::TEXT_ALIGN_CENTER) | 74 if (flags & gfx::Canvas::TEXT_ALIGN_CENTER) |
| 75 f |= DT_CENTER; | 75 f |= DT_CENTER; |
| 76 else if (flags & ChromeCanvas::TEXT_ALIGN_RIGHT) | 76 else if (flags & gfx::Canvas::TEXT_ALIGN_RIGHT) |
| 77 f |= DT_RIGHT; | 77 f |= DT_RIGHT; |
| 78 else | 78 else |
| 79 f |= DT_LEFT; | 79 f |= DT_LEFT; |
| 80 | 80 |
| 81 // In order to make sure RTL/BiDi strings are rendered correctly, we must | 81 // In order to make sure RTL/BiDi strings are rendered correctly, we must |
| 82 // pass the flag DT_RTLREADING to DrawText (when the locale's language is | 82 // pass the flag DT_RTLREADING to DrawText (when the locale's language is |
| 83 // a right-to-left language) so that Windows does the right thing. | 83 // a right-to-left language) so that Windows does the right thing. |
| 84 // | 84 // |
| 85 // In addition to correctly displaying text containing both RTL and LTR | 85 // In addition to correctly displaying text containing both RTL and LTR |
| 86 // elements (for example, a string containing a telephone number within a | 86 // elements (for example, a string containing a telephone number within a |
| (...skipping 23 matching lines...) Expand all Loading... |
| 110 (f & DT_RIGHT)) { | 110 (f & DT_RIGHT)) { |
| 111 if (l10n_util::StringContainsStrongRTLChars(text)) { | 111 if (l10n_util::StringContainsStrongRTLChars(text)) { |
| 112 f |= DT_RTLREADING; | 112 f |= DT_RTLREADING; |
| 113 } | 113 } |
| 114 } | 114 } |
| 115 return f; | 115 return f; |
| 116 } | 116 } |
| 117 | 117 |
| 118 } // anonymous namespace | 118 } // anonymous namespace |
| 119 | 119 |
| 120 ChromeCanvas::ChromeCanvas(int width, int height, bool is_opaque) | 120 namespace gfx { |
| 121 |
| 122 Canvas::Canvas(int width, int height, bool is_opaque) |
| 121 : skia::PlatformCanvasWin(width, height, is_opaque) { | 123 : skia::PlatformCanvasWin(width, height, is_opaque) { |
| 122 } | 124 } |
| 123 | 125 |
| 124 ChromeCanvas::ChromeCanvas() : skia::PlatformCanvasWin() { | 126 Canvas::Canvas() : skia::PlatformCanvasWin() { |
| 125 } | 127 } |
| 126 | 128 |
| 127 ChromeCanvas::~ChromeCanvas() { | 129 Canvas::~Canvas() { |
| 128 } | 130 } |
| 129 | 131 |
| 130 // static | 132 // static |
| 131 void ChromeCanvas::SizeStringInt(const std::wstring& text, | 133 void Canvas::SizeStringInt(const std::wstring& text, |
| 132 const gfx::Font& font, | 134 const gfx::Font& font, |
| 133 int *width, int *height, int flags) { | 135 int *width, int *height, int flags) { |
| 134 HDC dc = GetDC(NULL); | 136 HDC dc = GetDC(NULL); |
| 135 HFONT old_font = static_cast<HFONT>(SelectObject(dc, font.hfont())); | 137 HFONT old_font = static_cast<HFONT>(SelectObject(dc, font.hfont())); |
| 136 RECT b; | 138 RECT b; |
| 137 b.left = 0; | 139 b.left = 0; |
| 138 b.top = 0; | 140 b.top = 0; |
| 139 b.right = *width; | 141 b.right = *width; |
| 140 if (b.right == 0 && !text.empty()) { | 142 if (b.right == 0 && !text.empty()) { |
| 141 // Width needs to be at least 1 or else DoDrawText will not resize it. | 143 // Width needs to be at least 1 or else DoDrawText will not resize it. |
| 142 b.right = 1; | 144 b.right = 1; |
| 143 } | 145 } |
| 144 b.bottom = *height; | 146 b.bottom = *height; |
| 145 DoDrawText(dc, text, &b, ComputeFormatFlags(flags, text) | DT_CALCRECT); | 147 DoDrawText(dc, text, &b, ComputeFormatFlags(flags, text) | DT_CALCRECT); |
| 146 | 148 |
| 147 // Restore the old font. This way we don't have to worry if the caller | 149 // Restore the old font. This way we don't have to worry if the caller |
| 148 // deletes the font and the DC lives longer. | 150 // deletes the font and the DC lives longer. |
| 149 SelectObject(dc, old_font); | 151 SelectObject(dc, old_font); |
| 150 *width = b.right; | 152 *width = b.right; |
| 151 *height = b.bottom; | 153 *height = b.bottom; |
| 152 | 154 |
| 153 ReleaseDC(NULL, dc); | 155 ReleaseDC(NULL, dc); |
| 154 } | 156 } |
| 155 | 157 |
| 156 void ChromeCanvas::DrawStringInt(const std::wstring& text, HFONT font, | 158 void Canvas::DrawStringInt(const std::wstring& text, HFONT font, |
| 157 const SkColor& color, int x, int y, int w, | 159 const SkColor& color, int x, int y, int w, int h, |
| 158 int h, int flags) { | 160 int flags) { |
| 159 if (!IntersectsClipRectInt(x, y, w, h)) | 161 if (!IntersectsClipRectInt(x, y, w, h)) |
| 160 return; | 162 return; |
| 161 | 163 |
| 162 RECT text_bounds = { x, y, x + w, y + h }; | 164 RECT text_bounds = { x, y, x + w, y + h }; |
| 163 HDC dc = beginPlatformPaint(); | 165 HDC dc = beginPlatformPaint(); |
| 164 SetBkMode(dc, TRANSPARENT); | 166 SetBkMode(dc, TRANSPARENT); |
| 165 HFONT old_font = (HFONT)SelectObject(dc, font); | 167 HFONT old_font = (HFONT)SelectObject(dc, font); |
| 166 COLORREF brush_color = RGB(SkColorGetR(color), SkColorGetG(color), | 168 COLORREF brush_color = RGB(SkColorGetR(color), SkColorGetG(color), |
| 167 SkColorGetB(color)); | 169 SkColorGetB(color)); |
| 168 SetTextColor(dc, brush_color); | 170 SetTextColor(dc, brush_color); |
| 169 | 171 |
| 170 int f = ComputeFormatFlags(flags, text); | 172 int f = ComputeFormatFlags(flags, text); |
| 171 DoDrawText(dc, text, &text_bounds, f); | 173 DoDrawText(dc, text, &text_bounds, f); |
| 172 endPlatformPaint(); | 174 endPlatformPaint(); |
| 173 | 175 |
| 174 // Restore the old font. This way we don't have to worry if the caller | 176 // Restore the old font. This way we don't have to worry if the caller |
| 175 // deletes the font and the DC lives longer. | 177 // deletes the font and the DC lives longer. |
| 176 SelectObject(dc, old_font); | 178 SelectObject(dc, old_font); |
| 177 | 179 |
| 178 // Windows will have cleared the alpha channel of the text we drew. Assume | 180 // Windows will have cleared the alpha channel of the text we drew. Assume |
| 179 // we're drawing to an opaque surface, or at least the text rect area is | 181 // we're drawing to an opaque surface, or at least the text rect area is |
| 180 // opaque. | 182 // opaque. |
| 181 getTopPlatformDevice().makeOpaque(x, y, w, h); | 183 getTopPlatformDevice().makeOpaque(x, y, w, h); |
| 182 } | 184 } |
| 183 | 185 |
| 184 void ChromeCanvas::DrawStringInt(const std::wstring& text, | 186 void Canvas::DrawStringInt(const std::wstring& text, |
| 185 const gfx::Font& font, | 187 const gfx::Font& font, |
| 186 const SkColor& color, | 188 const SkColor& color, |
| 187 int x, int y, int w, int h, int flags) { | 189 int x, int y, int w, int h, int flags) { |
| 188 DrawStringInt(text, font.hfont(), color, x, y, w, h, flags); | 190 DrawStringInt(text, font.hfont(), color, x, y, w, h, flags); |
| 189 } | 191 } |
| 190 | 192 |
| 191 // Checks each pixel immediately adjacent to the given pixel in the bitmap. If | 193 // Checks each pixel immediately adjacent to the given pixel in the bitmap. If |
| 192 // any of them are not the halo color, returns true. This defines the halo of | 194 // any of them are not the halo color, returns true. This defines the halo of |
| 193 // pixels that will appear around the text. Note that we have to check each | 195 // pixels that will appear around the text. Note that we have to check each |
| 194 // pixel against both the halo color and transparent since DrawStringWithHalo | 196 // pixel against both the halo color and transparent since DrawStringWithHalo |
| 195 // will modify the bitmap as it goes, and clears pixels shouldn't count as | 197 // will modify the bitmap as it goes, and clears pixels shouldn't count as |
| 196 // changed. | 198 // changed. |
| 197 static bool pixelShouldGetHalo(const SkBitmap& bitmap, int x, int y, | 199 static bool pixelShouldGetHalo(const SkBitmap& bitmap, int x, int y, |
| (...skipping 10 matching lines...) Expand all Loading... |
| 208 *bitmap.getAddr32(x, y - 1) != halo_color && | 210 *bitmap.getAddr32(x, y - 1) != halo_color && |
| 209 *bitmap.getAddr32(x, y - 1) != 0) | 211 *bitmap.getAddr32(x, y - 1) != 0) |
| 210 return true; // Touched pixel above. | 212 return true; // Touched pixel above. |
| 211 if (y < bitmap.height() - 1 && | 213 if (y < bitmap.height() - 1 && |
| 212 *bitmap.getAddr32(x, y + 1) != halo_color && | 214 *bitmap.getAddr32(x, y + 1) != halo_color && |
| 213 *bitmap.getAddr32(x, y + 1) != 0) | 215 *bitmap.getAddr32(x, y + 1) != 0) |
| 214 return true; // Touched pixel below. | 216 return true; // Touched pixel below. |
| 215 return false; | 217 return false; |
| 216 } | 218 } |
| 217 | 219 |
| 218 void ChromeCanvas::DrawStringWithHalo(const std::wstring& text, | 220 void Canvas::DrawStringWithHalo(const std::wstring& text, |
| 219 const gfx::Font& font, | 221 const gfx::Font& font, |
| 220 const SkColor& text_color, | 222 const SkColor& text_color, |
| 221 const SkColor& halo_color_in, | 223 const SkColor& halo_color_in, |
| 222 int x, int y, int w, int h, | 224 int x, int y, int w, int h, |
| 223 int flags) { | 225 int flags) { |
| 224 // Some callers will have semitransparent halo colors, which we don't handle | 226 // Some callers will have semitransparent halo colors, which we don't handle |
| 225 // (since the resulting image can have 1-bit transparency only). | 227 // (since the resulting image can have 1-bit transparency only). |
| 226 SkColor halo_color = halo_color_in | 0xFF000000; | 228 SkColor halo_color = halo_color_in | 0xFF000000; |
| 227 | 229 |
| 228 // Create a temporary buffer filled with the halo color. It must leave room | 230 // Create a temporary buffer filled with the halo color. It must leave room |
| 229 // for the 1-pixel border around the text. | 231 // for the 1-pixel border around the text. |
| 230 ChromeCanvas text_canvas(w + 2, h + 2, true); | 232 Canvas text_canvas(w + 2, h + 2, true); |
| 231 SkPaint bkgnd_paint; | 233 SkPaint bkgnd_paint; |
| 232 bkgnd_paint.setColor(halo_color); | 234 bkgnd_paint.setColor(halo_color); |
| 233 text_canvas.FillRectInt(0, 0, w + 2, h + 2, bkgnd_paint); | 235 text_canvas.FillRectInt(0, 0, w + 2, h + 2, bkgnd_paint); |
| 234 | 236 |
| 235 // Draw the text into the temporary buffer. This will have correct | 237 // Draw the text into the temporary buffer. This will have correct |
| 236 // ClearType since the background color is the same as the halo color. | 238 // ClearType since the background color is the same as the halo color. |
| 237 text_canvas.DrawStringInt(text, font, text_color, 1, 1, w, h, flags); | 239 text_canvas.DrawStringInt(text, font, text_color, 1, 1, w, h, flags); |
| 238 | 240 |
| 239 // Windows will have cleared the alpha channel for the pixels it drew. Make it | 241 // Windows will have cleared the alpha channel for the pixels it drew. Make it |
| 240 // opaque. We have to do this first since pixelShouldGetHalo will check for | 242 // opaque. We have to do this first since pixelShouldGetHalo will check for |
| (...skipping 14 matching lines...) Expand all Loading... |
| 255 text_row[cur_x] = 0; // Make transparent. | 257 text_row[cur_x] = 0; // Make transparent. |
| 256 } else { | 258 } else { |
| 257 text_row[cur_x] |= 0xff << SK_A32_SHIFT; // Make opaque. | 259 text_row[cur_x] |= 0xff << SK_A32_SHIFT; // Make opaque. |
| 258 } | 260 } |
| 259 } | 261 } |
| 260 } | 262 } |
| 261 | 263 |
| 262 // Draw the halo bitmap with blur. | 264 // Draw the halo bitmap with blur. |
| 263 drawBitmap(text_bitmap, SkIntToScalar(x - 1), SkIntToScalar(y - 1)); | 265 drawBitmap(text_bitmap, SkIntToScalar(x - 1), SkIntToScalar(y - 1)); |
| 264 } | 266 } |
| 267 |
| 268 } // namespace gfx |
| OLD | NEW |