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