| OLD | NEW |
| 1 // Copyright (c) 2011 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2011 The Chromium Authors. All rights reserved. |
| 2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 #include "ui/gfx/canvas_skia.h" | 5 #include "ui/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 "base/logging.h" | 10 #include "base/logging.h" |
| (...skipping 120 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 131 (f & DT_RIGHT) && base::i18n::StringContainsStrongRTLChars(text))) { | 131 (f & DT_RIGHT) && base::i18n::StringContainsStrongRTLChars(text))) { |
| 132 f |= DT_RTLREADING; | 132 f |= DT_RTLREADING; |
| 133 } | 133 } |
| 134 | 134 |
| 135 return f; | 135 return f; |
| 136 } | 136 } |
| 137 | 137 |
| 138 // Changes the alpha of the given bitmap. | 138 // Changes the alpha of the given bitmap. |
| 139 // If |fade_to_right| is true then the rect fades from opaque to clear, | 139 // If |fade_to_right| is true then the rect fades from opaque to clear, |
| 140 // otherwise the rect fades from clear to opaque. | 140 // otherwise the rect fades from clear to opaque. |
| 141 void FadeBitmapRect(skia::BitmapPlatformDevice& bmp_device, | 141 void FadeBitmapRect(SkDevice& bmp_device, |
| 142 const gfx::Rect& rect, | 142 const gfx::Rect& rect, |
| 143 bool fade_to_right) { | 143 bool fade_to_right) { |
| 144 SkBitmap bmp = bmp_device.accessBitmap(true); | 144 SkBitmap bmp = bmp_device.accessBitmap(true); |
| 145 DCHECK_EQ(SkBitmap::kARGB_8888_Config, bmp.config()); | 145 DCHECK_EQ(SkBitmap::kARGB_8888_Config, bmp.config()); |
| 146 SkAutoLockPixels lock(bmp); | 146 SkAutoLockPixels lock(bmp); |
| 147 float total_width = static_cast<float>(rect.width()); | 147 float total_width = static_cast<float>(rect.width()); |
| 148 | 148 |
| 149 for (int x = rect.x(); x < rect.right(); x++) { | 149 for (int x = rect.x(); x < rect.right(); x++) { |
| 150 float cur_width = static_cast<float>(fade_to_right ? | 150 float cur_width = static_cast<float>(fade_to_right ? |
| 151 rect.right() - x : x - rect.x()); | 151 rect.right() - x : x - rect.x()); |
| 152 // We want the fade effect to go from 0.2 to 1.0. | 152 // We want the fade effect to go from 0.2 to 1.0. |
| 153 float alpha_percent = ((cur_width / total_width) * 0.8f) + 0.2f; | 153 float alpha_percent = ((cur_width / total_width) * 0.8f) + 0.2f; |
| 154 | 154 |
| 155 for (int y = rect.y(); y < rect.bottom(); y++) { | 155 for (int y = rect.y(); y < rect.bottom(); y++) { |
| 156 SkColor color = bmp.getColor(x, y); | 156 SkColor color = bmp.getColor(x, y); |
| 157 SkAlpha alpha = static_cast<SkAlpha>(SkColorGetA(color) * alpha_percent); | 157 SkAlpha alpha = static_cast<SkAlpha>(SkColorGetA(color) * alpha_percent); |
| 158 *bmp.getAddr32(x, y) = SkPreMultiplyColor(SkColorSetA(color, alpha)); | 158 *bmp.getAddr32(x, y) = SkPreMultiplyColor(SkColorSetA(color, alpha)); |
| 159 } | 159 } |
| 160 } | 160 } |
| 161 } | 161 } |
| 162 | 162 |
| 163 // DrawText() doesn't support alpha channels. To create a transparent background | 163 // DrawText() doesn't support alpha channels. To create a transparent background |
| 164 // this function draws black on white. It then uses the intensity of black | 164 // this function draws black on white. It then uses the intensity of black |
| 165 // to determine how much alpha to use. The text is drawn in |gfx_text_rect| and | 165 // to determine how much alpha to use. The text is drawn in |gfx_text_rect| and |
| 166 // clipped to |gfx_draw_rect|. | 166 // clipped to |gfx_draw_rect|. |
| 167 void DrawTextAndClearBackground(skia::BitmapPlatformDevice& bmp_device, | 167 void DrawTextAndClearBackground(SkDevice& bmp_device, |
| 168 HFONT font, | 168 HFONT font, |
| 169 COLORREF text_color, | 169 COLORREF text_color, |
| 170 const string16& text, | 170 const string16& text, |
| 171 int flags, | 171 int flags, |
| 172 const gfx::Rect& gfx_text_rect, | 172 const gfx::Rect& gfx_text_rect, |
| 173 const gfx::Rect& gfx_draw_rect) { | 173 const gfx::Rect& gfx_draw_rect) { |
| 174 HDC hdc = bmp_device.BeginPlatformPaint(); | 174 HDC hdc = skia::platform_util::BeginPlatformPaint(&bmp_device); |
| 175 | 175 |
| 176 // Clear the background by filling with white. | 176 // Clear the background by filling with white. |
| 177 HBRUSH fill_brush = static_cast<HBRUSH>(GetStockObject(WHITE_BRUSH)); | 177 HBRUSH fill_brush = static_cast<HBRUSH>(GetStockObject(WHITE_BRUSH)); |
| 178 HANDLE old_brush = SelectObject(hdc, fill_brush); | 178 HANDLE old_brush = SelectObject(hdc, fill_brush); |
| 179 RECT draw_rect = gfx_draw_rect.ToRECT(); | 179 RECT draw_rect = gfx_draw_rect.ToRECT(); |
| 180 FillRect(hdc, &draw_rect, fill_brush); | 180 FillRect(hdc, &draw_rect, fill_brush); |
| 181 SelectObject(hdc, old_brush); | 181 SelectObject(hdc, old_brush); |
| 182 | 182 |
| 183 // Set black text with trasparent background. | 183 // Set black text with trasparent background. |
| 184 SetBkMode(hdc, TRANSPARENT); | 184 SetBkMode(hdc, TRANSPARENT); |
| (...skipping 26 matching lines...) Expand all Loading... |
| 211 // using SkBitmap::getColor() won't work here. | 211 // using SkBitmap::getColor() won't work here. |
| 212 SkColor color = *bmp.getAddr32(x, y); | 212 SkColor color = *bmp.getAddr32(x, y); |
| 213 // Calculate the alpha using the luminance. Since this is black text | 213 // Calculate the alpha using the luminance. Since this is black text |
| 214 // on a white background the luminosity must be inverted. | 214 // on a white background the luminosity must be inverted. |
| 215 BYTE alpha = 0xFF - color_utils::GetLuminanceForColor(color); | 215 BYTE alpha = 0xFF - color_utils::GetLuminanceForColor(color); |
| 216 *bmp.getAddr32(x, y) = SkPreMultiplyColor( | 216 *bmp.getAddr32(x, y) = SkPreMultiplyColor( |
| 217 SkColorSetARGB(alpha, text_color_r, text_color_b, text_color_g)); | 217 SkColorSetARGB(alpha, text_color_r, text_color_b, text_color_g)); |
| 218 } | 218 } |
| 219 } | 219 } |
| 220 | 220 |
| 221 bmp_device.EndPlatformPaint(); | 221 skia::platform_util::EndPlatformPaint(&bmp_device); |
| 222 } | 222 } |
| 223 | 223 |
| 224 // Draws the given text with a fade out gradient. |bmp_device| is a bitmap | 224 // Draws the given text with a fade out gradient. |bmp_device| is a bitmap |
| 225 // that is used to temporary drawing. The text is drawn in |text_rect| and | 225 // that is used to temporary drawing. The text is drawn in |text_rect| and |
| 226 // clipped to |draw_rect|. | 226 // clipped to |draw_rect|. |
| 227 void DrawTextGradientPart(HDC hdc, | 227 void DrawTextGradientPart(HDC hdc, |
| 228 skia::BitmapPlatformDevice& bmp_device, | 228 SkDevice& bmp_device, |
| 229 const string16& text, | 229 const string16& text, |
| 230 const SkColor& color, | 230 const SkColor& color, |
| 231 HFONT font, | 231 HFONT font, |
| 232 const gfx::Rect& text_rect, | 232 const gfx::Rect& text_rect, |
| 233 const gfx::Rect& draw_rect, | 233 const gfx::Rect& draw_rect, |
| 234 bool fade_to_right, | 234 bool fade_to_right, |
| 235 int flags) { | 235 int flags) { |
| 236 DrawTextAndClearBackground(bmp_device, font, skia::SkColorToCOLORREF(color), | 236 DrawTextAndClearBackground(bmp_device, font, skia::SkColorToCOLORREF(color), |
| 237 text, flags, text_rect, draw_rect); | 237 text, flags, text_rect, draw_rect); |
| 238 FadeBitmapRect(bmp_device, draw_rect, fade_to_right); | 238 FadeBitmapRect(bmp_device, draw_rect, fade_to_right); |
| 239 BLENDFUNCTION blend = {AC_SRC_OVER, 0, 255, AC_SRC_ALPHA}; | 239 BLENDFUNCTION blend = {AC_SRC_OVER, 0, 255, AC_SRC_ALPHA}; |
| 240 | 240 |
| 241 HDC bmp_hdc = bmp_device.BeginPlatformPaint(); | 241 HDC bmp_hdc = skia::platform_util::BeginPlatformPaint(&bmp_device); |
| 242 AlphaBlend(hdc, draw_rect.x(), draw_rect.y(), draw_rect.width(), | 242 AlphaBlend(hdc, draw_rect.x(), draw_rect.y(), draw_rect.width(), |
| 243 draw_rect.height(), bmp_hdc, draw_rect.x(), draw_rect.y(), | 243 draw_rect.height(), bmp_hdc, draw_rect.x(), draw_rect.y(), |
| 244 draw_rect.width(), draw_rect.height(), blend); | 244 draw_rect.width(), draw_rect.height(), blend); |
| 245 bmp_device.EndPlatformPaint(); | 245 skia::platform_util::EndPlatformPaint(&bmp_device); |
| 246 } | 246 } |
| 247 | 247 |
| 248 enum PrimarySide { | 248 enum PrimarySide { |
| 249 PrimaryOnLeft, | 249 PrimaryOnLeft, |
| 250 PrimaryOnRight, | 250 PrimaryOnRight, |
| 251 }; | 251 }; |
| 252 | 252 |
| 253 // Divides |rect| horizontally into a |primary| of width |primary_width| and a | 253 // Divides |rect| horizontally into a |primary| of width |primary_width| and a |
| 254 // |secondary| taking up the remainder. | 254 // |secondary| taking up the remainder. |
| 255 void DivideRect(const gfx::Rect& rect, | 255 void DivideRect(const gfx::Rect& rect, |
| (...skipping 102 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 358 DoDrawText(dc, clamped_string, &text_bounds, f); | 358 DoDrawText(dc, clamped_string, &text_bounds, f); |
| 359 endPlatformPaint(); | 359 endPlatformPaint(); |
| 360 | 360 |
| 361 // Restore the old font. This way we don't have to worry if the caller | 361 // Restore the old font. This way we don't have to worry if the caller |
| 362 // deletes the font and the DC lives longer. | 362 // deletes the font and the DC lives longer. |
| 363 SelectObject(dc, old_font); | 363 SelectObject(dc, old_font); |
| 364 | 364 |
| 365 // Windows will have cleared the alpha channel of the text we drew. Assume | 365 // Windows will have cleared the alpha channel of the text we drew. Assume |
| 366 // we're drawing to an opaque surface, or at least the text rect area is | 366 // we're drawing to an opaque surface, or at least the text rect area is |
| 367 // opaque. | 367 // opaque. |
| 368 getTopPlatformDevice().makeOpaque(clip.fLeft, clip.fTop, | 368 skia::platform_util::MakeOpaque(&getTopDevice(), clip.fLeft, |
| 369 clip.width(), clip.height()); | 369 clip.fTop, clip.width(), clip.height()); |
| 370 } | 370 } |
| 371 | 371 |
| 372 void CanvasSkia::DrawStringInt(const string16& text, | 372 void CanvasSkia::DrawStringInt(const string16& text, |
| 373 const gfx::Font& font, | 373 const gfx::Font& font, |
| 374 const SkColor& color, | 374 const SkColor& color, |
| 375 int x, int y, int w, int h, | 375 int x, int y, int w, int h, |
| 376 int flags) { | 376 int flags) { |
| 377 DrawStringInt(text, font.GetNativeFont(), color, x, y, w, h, flags); | 377 DrawStringInt(text, font.GetNativeFont(), color, x, y, w, h, flags); |
| 378 } | 378 } |
| 379 | 379 |
| (...skipping 43 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 423 text_canvas.DrawRectInt(0, 0, w + 2, h + 2, bkgnd_paint); | 423 text_canvas.DrawRectInt(0, 0, w + 2, h + 2, bkgnd_paint); |
| 424 | 424 |
| 425 // Draw the text into the temporary buffer. This will have correct | 425 // Draw the text into the temporary buffer. This will have correct |
| 426 // ClearType since the background color is the same as the halo color. | 426 // ClearType since the background color is the same as the halo color. |
| 427 text_canvas.DrawStringInt(text, font, text_color, 1, 1, w, h, flags); | 427 text_canvas.DrawStringInt(text, font, text_color, 1, 1, w, h, flags); |
| 428 | 428 |
| 429 // Windows will have cleared the alpha channel for the pixels it drew. Make it | 429 // Windows will have cleared the alpha channel for the pixels it drew. Make it |
| 430 // opaque. We have to do this first since pixelShouldGetHalo will check for | 430 // opaque. We have to do this first since pixelShouldGetHalo will check for |
| 431 // 0 to see if a pixel has been modified to transparent, and black text that | 431 // 0 to see if a pixel has been modified to transparent, and black text that |
| 432 // Windows draw will look transparent to it! | 432 // Windows draw will look transparent to it! |
| 433 text_canvas.getTopPlatformDevice().makeOpaque(0, 0, w + 2, h + 2); | 433 skia::platform_util::MakeOpaque(&text_canvas.getTopDevice(), 0, 0, |
| 434 w + 2, h + 2); |
| 434 | 435 |
| 435 uint32_t halo_premul = SkPreMultiplyColor(halo_color); | 436 uint32_t halo_premul = SkPreMultiplyColor(halo_color); |
| 436 SkBitmap& text_bitmap = const_cast<SkBitmap&>( | 437 SkBitmap& text_bitmap = const_cast<SkBitmap&>( |
| 437 text_canvas.getTopPlatformDevice().accessBitmap(true)); | 438 text_canvas.getTopDevice().accessBitmap(true)); |
| 438 for (int cur_y = 0; cur_y < h + 2; cur_y++) { | 439 for (int cur_y = 0; cur_y < h + 2; cur_y++) { |
| 439 uint32_t* text_row = text_bitmap.getAddr32(0, cur_y); | 440 uint32_t* text_row = text_bitmap.getAddr32(0, cur_y); |
| 440 for (int cur_x = 0; cur_x < w + 2; cur_x++) { | 441 for (int cur_x = 0; cur_x < w + 2; cur_x++) { |
| 441 if (text_row[cur_x] == halo_premul) { | 442 if (text_row[cur_x] == halo_premul) { |
| 442 // This pixel was not touched by the text routines. See if it borders | 443 // This pixel was not touched by the text routines. See if it borders |
| 443 // a touched pixel in any of the 4 directions (not diagonally). | 444 // a touched pixel in any of the 4 directions (not diagonally). |
| 444 if (!pixelShouldGetHalo(text_bitmap, cur_x, cur_y, halo_premul)) | 445 if (!pixelShouldGetHalo(text_bitmap, cur_x, cur_y, halo_premul)) |
| 445 text_row[cur_x] = 0; // Make transparent. | 446 text_row[cur_x] = 0; // Make transparent. |
| 446 } else { | 447 } else { |
| 447 text_row[cur_x] |= 0xff << SK_A32_SHIFT; // Make opaque. | 448 text_row[cur_x] |= 0xff << SK_A32_SHIFT; // Make opaque. |
| (...skipping 98 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 546 DivideRect(solid_part, is_rtl ? PrimaryOnLeft : PrimaryOnRight, | 547 DivideRect(solid_part, is_rtl ? PrimaryOnLeft : PrimaryOnRight, |
| 547 gradient_width, &tail_part, &solid_part); | 548 gradient_width, &tail_part, &solid_part); |
| 548 | 549 |
| 549 // Grow |display_rect| by |offset_x|. | 550 // Grow |display_rect| by |offset_x|. |
| 550 gfx::Rect text_rect(gfx::Point(), display_rect.size()); | 551 gfx::Rect text_rect(gfx::Point(), display_rect.size()); |
| 551 if (!is_rtl) | 552 if (!is_rtl) |
| 552 text_rect.set_x(text_rect.x() - offset_x); | 553 text_rect.set_x(text_rect.x() - offset_x); |
| 553 text_rect.set_width(text_rect.width() + offset_x); | 554 text_rect.set_width(text_rect.width() + offset_x); |
| 554 | 555 |
| 555 // Create a temporary bitmap to draw the gradient to. | 556 // Create a temporary bitmap to draw the gradient to. |
| 556 scoped_ptr<skia::BitmapPlatformDevice> gradient_bitmap( | 557 scoped_ptr<SkDevice> gradient_bitmap( |
| 557 skia::BitmapPlatformDevice::create( | 558 skia::BitmapPlatformDevice::create( |
| 558 display_rect.width(), display_rect.height(), false, NULL)); | 559 display_rect.width(), display_rect.height(), false, NULL)); |
| 559 DCHECK(gradient_bitmap.get()); | 560 DCHECK(gradient_bitmap.get()); |
| 560 | 561 |
| 561 HDC hdc = beginPlatformPaint(); | 562 HDC hdc = beginPlatformPaint(); |
| 562 if (is_truncating_head) | 563 if (is_truncating_head) |
| 563 DrawTextGradientPart(hdc, *gradient_bitmap, text, color, | 564 DrawTextGradientPart(hdc, *gradient_bitmap, text, color, |
| 564 font.GetNativeFont(), text_rect, head_part, is_rtl, | 565 font.GetNativeFont(), text_rect, head_part, is_rtl, |
| 565 flags); | 566 flags); |
| 566 if (is_truncating_tail) | 567 if (is_truncating_tail) |
| 567 DrawTextGradientPart(hdc, *gradient_bitmap, text, color, | 568 DrawTextGradientPart(hdc, *gradient_bitmap, text, color, |
| 568 font.GetNativeFont(), text_rect, tail_part, !is_rtl, | 569 font.GetNativeFont(), text_rect, tail_part, !is_rtl, |
| 569 flags); | 570 flags); |
| 570 endPlatformPaint(); | 571 endPlatformPaint(); |
| 571 | 572 |
| 572 // Draw the solid part. | 573 // Draw the solid part. |
| 573 save(kClip_SaveFlag); | 574 save(kClip_SaveFlag); |
| 574 ClipRectInt(solid_part.x(), solid_part.y(), | 575 ClipRectInt(solid_part.x(), solid_part.y(), |
| 575 solid_part.width(), solid_part.height()); | 576 solid_part.width(), solid_part.height()); |
| 576 DrawStringInt(text, font, color, | 577 DrawStringInt(text, font, color, |
| 577 text_rect.x(), text_rect.y(), | 578 text_rect.x(), text_rect.y(), |
| 578 text_rect.width(), text_rect.height(), | 579 text_rect.width(), text_rect.height(), |
| 579 flags); | 580 flags); |
| 580 restore(); | 581 restore(); |
| 581 restore(); | 582 restore(); |
| 582 } | 583 } |
| 583 | 584 |
| 584 } // namespace gfx | 585 } // namespace gfx |
| OLD | NEW |