badge_util.cc revision 201ade2fbba22bfb27ae029f4d23fca6ded109a0
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 3// found in the LICENSE file. 4 5#include "chrome/common/badge_util.h" 6 7#include "app/resource_bundle.h" 8#include "base/utf_string_conversions.h" 9#include "gfx/canvas_skia.h" 10#include "gfx/font.h" 11#include "third_party/skia/include/core/SkPaint.h" 12#include "third_party/skia/include/core/SkTypeface.h" 13 14namespace badge_util { 15 16SkPaint* GetBadgeTextPaintSingleton() { 17#if defined(OS_MACOSX) 18 const char kPreferredTypeface[] = "Helvetica Bold"; 19#else 20 const char kPreferredTypeface[] = "Arial"; 21#endif 22 23 static SkPaint* text_paint = NULL; 24 if (!text_paint) { 25 text_paint = new SkPaint; 26 text_paint->setAntiAlias(true); 27 text_paint->setTextAlign(SkPaint::kLeft_Align); 28 29 SkTypeface* typeface = SkTypeface::CreateFromName( 30 kPreferredTypeface, SkTypeface::kBold); 31 // Skia doesn't do any font fallback---if the user is missing the font then 32 // typeface will be NULL. If we don't do manual fallback then we'll crash. 33 if (typeface) { 34 text_paint->setFakeBoldText(true); 35 } else { 36 // Fall back to the system font. We don't bold it because we aren't sure 37 // how it will look. 38 // For the most part this code path will only be hit on Linux systems 39 // that don't have Arial. 40 ResourceBundle& rb = ResourceBundle::GetSharedInstance(); 41 const gfx::Font& base_font = rb.GetFont(ResourceBundle::BaseFont); 42 typeface = SkTypeface::CreateFromName( 43 WideToUTF8(base_font.GetFontName()).c_str(), SkTypeface::kNormal); 44 } 45 46 text_paint->setTypeface(typeface); 47 // |text_paint| adds its own ref. Release the ref from CreateFontName. 48 typeface->unref(); 49 } 50 return text_paint; 51} 52 53SkBitmap DrawBadgeIconOverlay(const SkBitmap& icon, 54 float font_size, 55 const string16& text, 56 const string16& fallback) { 57 const int kMinPadding = 1; 58 59 // Calculate the proper style/text overlay to render on the badge. 60 SkPaint* paint = badge_util::GetBadgeTextPaintSingleton(); 61 paint->setTextSize(SkFloatToScalar(font_size)); 62 paint->setColor(SK_ColorWHITE); 63 64 std::string badge_text = UTF16ToUTF8(text); 65 66 // See if the text will fit - otherwise use a default. 67 SkScalar text_width = paint->measureText(badge_text.c_str(), 68 badge_text.size()); 69 70 if (SkScalarRound(text_width) > (icon.width() - kMinPadding * 2)) { 71 // String is too large - use the alternate text. 72 badge_text = UTF16ToUTF8(fallback); 73 text_width = paint->measureText(badge_text.c_str(), badge_text.size()); 74 } 75 76 // When centering the text, we need to make sure there are an equal number 77 // of pixels on each side as otherwise the text looks off-center. So if the 78 // padding would be uneven, clip one pixel off the right side. 79 int badge_width = icon.width(); 80 if ((SkScalarRound(text_width) % 1) != (badge_width % 1)) 81 badge_width--; 82 83 // Render the badge bitmap and overlay into a canvas. 84 scoped_ptr<gfx::CanvasSkia> canvas( 85 new gfx::CanvasSkia(badge_width, icon.height(), false)); 86 canvas->DrawBitmapInt(icon, 0, 0); 87 88 // Draw the text overlay centered horizontally and vertically. Skia expects 89 // us to specify the lower left coordinate of the text box, which is why we 90 // add 'font_size - 1' to the height. 91 SkScalar x = (badge_width - text_width)/2; 92 SkScalar y = (icon.height() - font_size)/2 + font_size - 1; 93 canvas->drawText(badge_text.c_str(), badge_text.size(), x, y, *paint); 94 95 // Return the generated image. 96 return canvas->ExtractBitmap(); 97} 98 99} // namespace badge_util 100