diff options
author | brettw@chromium.org <brettw@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2009-03-02 21:49:12 +0000 |
---|---|---|
committer | brettw@chromium.org <brettw@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2009-03-02 21:49:12 +0000 |
commit | f00fa4d766ac76419a051345a496caecfbeddc78 (patch) | |
tree | b742fc1bdaa6dfd815e3b8ad719789572bb23398 /chrome/common | |
parent | 50d7d7283db42b531a9df9c6f5a34b8526d4d5b0 (diff) | |
download | chromium_src-f00fa4d766ac76419a051345a496caecfbeddc78.zip chromium_src-f00fa4d766ac76419a051345a496caecfbeddc78.tar.gz chromium_src-f00fa4d766ac76419a051345a496caecfbeddc78.tar.bz2 |
Fix bookmark and menu drag images by making a halo around them. This makes
the ClearType composited on the correct color to fix the semitransparent pixels
into 1-bit transparency pixels.
Remove some unnecessary header file dependencies on ChromeCanvas I noticed
when compiling this patch.
BUG=8258
Review URL: http://codereview.chromium.org/27321
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@10732 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'chrome/common')
-rw-r--r-- | chrome/common/gfx/chrome_canvas.h | 10 | ||||
-rw-r--r-- | chrome/common/gfx/chrome_canvas_win.cc | 75 |
2 files changed, 85 insertions, 0 deletions
diff --git a/chrome/common/gfx/chrome_canvas.h b/chrome/common/gfx/chrome_canvas.h index a78d85c..d6cf77f 100644 --- a/chrome/common/gfx/chrome_canvas.h +++ b/chrome/common/gfx/chrome_canvas.h @@ -147,6 +147,16 @@ class ChromeCanvas : public skia::PlatformCanvas { const SkColor& color, int x, int y, int w, int h, int flags); +#ifdef OS_WIN // Only implemented on Windows for now. + // Draws text with a 1-pixel halo around it of the given color. It allows + // ClearType to be drawn to an otherwise transparenct bitmap for drag images. + // Drag images have only 1-bit of transparency, so we don't do any fancy + // blurring. + void DrawStringWithHalo(const std::wstring& text, const ChromeFont& font, + const SkColor& text_color, const SkColor& halo_color, + int x, int y, int w, int h, int flags); +#endif + // Draws a dotted gray rectangle used for focus purposes. void DrawFocusRect(int x, int y, int width, int height); diff --git a/chrome/common/gfx/chrome_canvas_win.cc b/chrome/common/gfx/chrome_canvas_win.cc index 5e40ceb..376db65 100644 --- a/chrome/common/gfx/chrome_canvas_win.cc +++ b/chrome/common/gfx/chrome_canvas_win.cc @@ -195,3 +195,78 @@ void ChromeCanvas::DrawStringInt(const std::wstring& text, int x, int y, int w, int h, int flags) { DrawStringInt(text, font.hfont(), color, x, y, w, h, flags); } + +// Checks each pixel immediately adjacent to the given pixel in the bitmap. If +// any of them are not the halo color, returns true. This defines the halo of +// pixels that will appear around the text. Note that we have to check each +// pixel against both the halo color and transparent since DrawStringWithHalo +// will modify the bitmap as it goes, and clears pixels shouldn't count as +// changed. +static bool pixelShouldGetHalo(const SkBitmap& bitmap, int x, int y, + SkColor halo_color) { + if (x > 0 && + *bitmap.getAddr32(x - 1, y) != halo_color && + *bitmap.getAddr32(x - 1, y) != 0) + return true; // Touched pixel to the left. + if (x < bitmap.width() - 1 && + *bitmap.getAddr32(x + 1, y) != halo_color && + *bitmap.getAddr32(x + 1, y) != 0) + return true; // Touched pixel to the right. + if (y > 0 && + *bitmap.getAddr32(x, y - 1) != halo_color && + *bitmap.getAddr32(x, y - 1) != 0) + return true; // Touched pixel above. + if (y < bitmap.height() - 1 && + *bitmap.getAddr32(x, y + 1) != halo_color && + *bitmap.getAddr32(x, y + 1) != 0) + return true; // Touched pixel below. + return false; +} + +void ChromeCanvas::DrawStringWithHalo(const std::wstring& text, + const ChromeFont& font, + const SkColor& text_color, + const SkColor& halo_color_in, + int x, int y, int w, int h, + int flags) { + // Some callers will have semitransparent halo colors, which we don't handle + // (since the resulting image can have 1-bit transparency only). + SkColor halo_color = halo_color_in | 0xFF000000; + + // Create a temporary buffer filled with the halo color. It must leave room + // for the 1-pixel border around the text. + ChromeCanvas text_canvas(w + 2, h + 2, true); + SkPaint bkgnd_paint; + bkgnd_paint.setColor(halo_color); + text_canvas.FillRectInt(0, 0, w + 2, h + 2, bkgnd_paint); + + // Draw the text into the temporary buffer. This will have correct + // ClearType since the background color is the same as the halo color. + text_canvas.DrawStringInt(text, font, text_color, 1, 1, w, h, flags); + + // Windows will have cleared the alpha channel for the pixels it drew. Make it + // opaque. We have to do this first since pixelShouldGetHalo will check for + // 0 to see if a pixel has been modified to transparent, and black text that + // Windows draw will look transparent to it! + text_canvas.getTopPlatformDevice().makeOpaque(0, 0, w + 2, h + 2); + + uint32_t halo_premul = SkPreMultiplyColor(halo_color); + SkBitmap& text_bitmap = const_cast<SkBitmap&>( + text_canvas.getTopPlatformDevice().accessBitmap(true)); + for (int cur_y = 0; cur_y < h + 2; cur_y++) { + uint32_t* text_row = text_bitmap.getAddr32(0, cur_y); + for (int cur_x = 0; cur_x < w + 2; cur_x++) { + if (text_row[cur_x] == halo_premul) { + // This pixel was not touched by the text routines. See if it borders + // a touched pixel in any of the 4 directions (not diagonally). + if (!pixelShouldGetHalo(text_bitmap, cur_x, cur_y, halo_premul)) + text_row[cur_x] = 0; // Make transparent. + } else { + text_row[cur_x] |= 0xff << SK_A32_SHIFT; // Make opaque. + } + } + } + + // Draw the halo bitmap with blur. + drawBitmap(text_bitmap, SkIntToScalar(x - 1), SkIntToScalar(y - 1)); +} |