summaryrefslogtreecommitdiffstats
path: root/chrome/common/badge_util.cc
blob: 464972675bc1b580653dbc9c6eae0c67430cd6e7 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
// Copyright (c) 2011 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "chrome/common/badge_util.h"

#include "base/logging.h"
#include "base/utf_string_conversions.h"
#include "third_party/skia/include/core/SkPaint.h"
#include "third_party/skia/include/core/SkTypeface.h"
#include "ui/base/resource/resource_bundle.h"
#include "ui/gfx/canvas_skia.h"
#include "ui/gfx/font.h"

namespace badge_util {

SkPaint* GetBadgeTextPaintSingleton() {
#if defined(OS_MACOSX)
  const char kPreferredTypeface[] = "Helvetica Bold";
#else
  const char kPreferredTypeface[] = "Arial";
#endif

  static SkPaint* text_paint = NULL;
  if (!text_paint) {
    text_paint = new SkPaint;
    text_paint->setAntiAlias(true);
    text_paint->setTextAlign(SkPaint::kLeft_Align);

    SkTypeface* typeface = SkTypeface::CreateFromName(
        kPreferredTypeface, SkTypeface::kBold);
    // Skia doesn't do any font fallback---if the user is missing the font then
    // typeface will be NULL. If we don't do manual fallback then we'll crash.
    if (typeface) {
      text_paint->setFakeBoldText(true);
    } else {
      // Fall back to the system font. We don't bold it because we aren't sure
      // how it will look.
      // For the most part this code path will only be hit on Linux systems
      // that don't have Arial.
      ResourceBundle& rb = ResourceBundle::GetSharedInstance();
      const gfx::Font& base_font = rb.GetFont(ResourceBundle::BaseFont);
      typeface = SkTypeface::CreateFromName(
          UTF16ToUTF8(base_font.GetFontName()).c_str(), SkTypeface::kNormal);
      DCHECK(typeface);
    }

    text_paint->setTypeface(typeface);
    // |text_paint| adds its own ref. Release the ref from CreateFontName.
    typeface->unref();
  }
  return text_paint;
}

SkBitmap DrawBadgeIconOverlay(const SkBitmap& icon,
                              float font_size,
                              const string16& text,
                              const string16& fallback) {
  const int kMinPadding = 1;

  // Calculate the proper style/text overlay to render on the badge.
  SkPaint* paint = badge_util::GetBadgeTextPaintSingleton();
  paint->setTextSize(SkFloatToScalar(font_size));
  paint->setColor(SK_ColorWHITE);

  std::string badge_text = UTF16ToUTF8(text);

  // See if the text will fit - otherwise use a default.
  SkScalar text_width = paint->measureText(badge_text.c_str(),
                                           badge_text.size());

  if (SkScalarRound(text_width) > (icon.width() - kMinPadding * 2)) {
    // String is too large - use the alternate text.
    badge_text = UTF16ToUTF8(fallback);
    text_width = paint->measureText(badge_text.c_str(), badge_text.size());
  }

  // When centering the text, we need to make sure there are an equal number
  // of pixels on each side as otherwise the text looks off-center. So if the
  // padding would be uneven, clip one pixel off the right side.
  int badge_width = icon.width();
  if ((SkScalarRound(text_width) % 1) != (badge_width % 1))
    badge_width--;

  // Render the badge bitmap and overlay into a canvas.
  scoped_ptr<gfx::CanvasSkia> canvas(
      new gfx::CanvasSkia(badge_width, icon.height(), false));
  canvas->DrawBitmapInt(icon, 0, 0);

  // Draw the text overlay centered horizontally and vertically. Skia expects
  // us to specify the lower left coordinate of the text box, which is why we
  // add 'font_size - 1' to the height.
  SkScalar x = (badge_width - text_width)/2;
  SkScalar y = (icon.height() - font_size)/2 + font_size - 1;
  canvas->drawText(badge_text.c_str(), badge_text.size(), x, y, *paint);

  // Return the generated image.
  return canvas->ExtractBitmap();
}

}  // namespace badge_util