blob: 42668e86b3bfdfd56778cf556a1acefdddaf1a8c [file] [log] [blame]
// Copyright (c) 2012 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.h"
#include "ui/gfx/font.h"
#include "ui/gfx/size.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(
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::Canvas> canvas(new gfx::Canvas(
gfx::Size(badge_width, icon.height()), ui::SCALE_FACTOR_100P, false));
canvas->DrawImageInt(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->sk_canvas()->drawText(
badge_text.c_str(), badge_text.size(), x, y, *paint);
// Return the generated image.
return canvas->ExtractImageRep().sk_bitmap();
}
} // namespace badge_util