Home | History | Annotate | Download | only in common
      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