| Index: components/favicon_base/fallback_icon_specs_builder.cc
|
| diff --git a/components/favicon_base/fallback_icon_specs_builder.cc b/components/favicon_base/fallback_icon_specs_builder.cc
|
| new file mode 100644
|
| index 0000000000000000000000000000000000000000..bea69a86878a6ab819dd0c39b2188588da02b061
|
| --- /dev/null
|
| +++ b/components/favicon_base/fallback_icon_specs_builder.cc
|
| @@ -0,0 +1,163 @@
|
| +// Copyright 2015 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 "components/favicon_base/fallback_icon_specs_builder.h"
|
| +
|
| +#include <string>
|
| +#include <vector>
|
| +
|
| +#include "base/strings/string_number_conversions.h"
|
| +#include "base/strings/string_split.h"
|
| +#include "ui/gfx/color_utils.h"
|
| +
|
| +namespace favicon_base {
|
| +
|
| +namespace {
|
| +
|
| +double kMaxFontSizeRatio = 1.0;
|
| +double kMaxCornerRadiusRatio = 0.5;
|
| +
|
| +// Luminance threshold for background color determine whether to use dark or
|
| +// light text color.
|
| +int kDarkTextLuminanceThreshold = 190;
|
| +
|
| +// Default values.
|
| +SkColor kDefaultBackgroundColor = SkColorSetRGB(0x80, 0x80, 0x80);
|
| +SkColor kDefaultTextColorDark = SK_ColorBLACK;
|
| +SkColor kDefaultTextColorLight = SK_ColorWHITE;
|
| +double kDefaultFontSizeRatio = 0.8;
|
| +double kDefaultCornerRadiusRatio = 0.0625; // 1 / 16.
|
| +
|
| +} // namespace
|
| +
|
| +FallbackIconSpecsBuilder::FallbackIconSpecsBuilder()
|
| + : is_init_(0U) {
|
| +}
|
| +
|
| +FallbackIconSpecsBuilder::~FallbackIconSpecsBuilder() {
|
| +}
|
| +
|
| +bool FallbackIconSpecsBuilder::Reset() {
|
| + is_init_ = 0U;
|
| + specs_ = FallbackIconSpecs();
|
| + return false; // This is to simplify Parse().
|
| +}
|
| +
|
| +bool FallbackIconSpecsBuilder::Has(DataMember mask) const {
|
| + return (is_init_ & mask) != 0;
|
| +}
|
| +
|
| +// Setters, which does not validate |value|.
|
| +void FallbackIconSpecsBuilder::SetBackgroundColor(SkColor value) {
|
| + is_init_ |= BACKGROUND_COLOR;
|
| + specs_.background_color = value;
|
| +}
|
| +
|
| +void FallbackIconSpecsBuilder::SetTextColor(SkColor value) {
|
| + is_init_ |= TEXT_COLOR;
|
| + specs_.text_color = value;
|
| +}
|
| +
|
| +void FallbackIconSpecsBuilder::SetFontSizeRatio(double value) {
|
| + is_init_ |= FONT_SIZE_RATIO;
|
| + specs_.font_size_ratio = value;
|
| +}
|
| +
|
| +void FallbackIconSpecsBuilder::SetCornerRadiusRatio(double value) {
|
| + is_init_ |= CORNER_RADIUS_RATIO;
|
| + specs_.corner_radius_ratio = value;
|
| +}
|
| +
|
| +// static
|
| +bool FallbackIconSpecsBuilder::ParseColor(const std::string& str,
|
| + SkColor* color) {
|
| + size_t len = str.length();
|
| + if (len != 3 && len != 6 && len != 8)
|
| + return false;
|
| + // Translate and validate each digits.
|
| + int d[8];
|
| + for (size_t i = 0; i < len; ++i) {
|
| + char ch = str[i];
|
| + if (ch >= '0' && ch <= '9')
|
| + d[i] = ch - '0';
|
| + else if (ch >= 'A' && ch <= 'F')
|
| + d[i] = (ch - 'A') + 10;
|
| + else if (ch >= 'a' && ch <= 'f')
|
| + d[i] = (ch - 'a') + 10;
|
| + else
|
| + return false;
|
| + }
|
| + if (len == 3) { // RGB.
|
| + *color = SkColorSetRGB(d[0] * 0x11, d[1] * 0x11, d[2] * 0x11);
|
| + } else if (len == 6) { // RRGGBB.
|
| + *color = SkColorSetRGB(
|
| + (d[0] << 4) | d[1], (d[2] << 4) | d[3], (d[4] << 4) | d[5]);
|
| + } else { // RRGGBBAA.
|
| + DCHECK(len == 8);
|
| + *color = SkColorSetARGB((d[6] << 4) | d[7], (d[0] << 4) | d[1],
|
| + (d[2] << 4) | d[3], (d[4] << 4) | d[5]);
|
| + }
|
| + return true;
|
| +}
|
| +
|
| +bool FallbackIconSpecsBuilder::Parse(const std::string& specs_str) {
|
| + Reset();
|
| + std::vector<std::string> tokens;
|
| + base::SplitStringDontTrim(specs_str, ',', &tokens);
|
| + if (tokens.size() > 4) // Too many fields.
|
| + return Reset(); // Returns false.
|
| +
|
| + SkColor temp_color;
|
| + double temp_double;
|
| + if (tokens.size() > 0 && !tokens[0].empty()) {
|
| + if (!ParseColor(tokens[0], &temp_color))
|
| + return Reset();
|
| + SetBackgroundColor(temp_color);
|
| + }
|
| + if (tokens.size() > 1 && !tokens[1].empty()) {
|
| + if (!ParseColor(tokens[1], &temp_color))
|
| + return Reset();
|
| + SetTextColor(temp_color);
|
| + }
|
| + if (tokens.size() > 2 && !tokens[2].empty()) {
|
| + if (!base::StringToDouble(tokens[2], &temp_double) ||
|
| + temp_double < 0.0 || temp_double > kMaxFontSizeRatio) {
|
| + return Reset();
|
| + }
|
| + SetFontSizeRatio(temp_double);
|
| + }
|
| + if (tokens.size() > 3 && !tokens[3].empty()) {
|
| + if (!base::StringToDouble(tokens[3], &temp_double) ||
|
| + temp_double < 0.0 || temp_double > kMaxCornerRadiusRatio) {
|
| + return Reset();
|
| + }
|
| + SetCornerRadiusRatio(temp_double);
|
| + }
|
| + return true;
|
| +}
|
| +
|
| +void FallbackIconSpecsBuilder::AssignDefaults() {
|
| + if (!Has(BACKGROUND_COLOR))
|
| + SetBackgroundColor(kDefaultBackgroundColor);
|
| +
|
| + // Uses dark/light text for background with high/low luminance.
|
| + if (!Has(TEXT_COLOR)) {
|
| + int luminance = color_utils::GetLuminanceForColor(specs_.background_color);
|
| + SetTextColor(luminance >= kDarkTextLuminanceThreshold ?
|
| + kDefaultTextColorDark : kDefaultTextColorLight);
|
| + }
|
| +
|
| + if (!Has(FONT_SIZE_RATIO))
|
| + SetFontSizeRatio(kDefaultFontSizeRatio);
|
| +
|
| + if (!Has(CORNER_RADIUS_RATIO))
|
| + SetCornerRadiusRatio(kDefaultCornerRadiusRatio);
|
| +}
|
| +
|
| +const FallbackIconSpecs& FallbackIconSpecsBuilder::Build() {
|
| + AssignDefaults();
|
| + return specs_;
|
| +}
|
| +
|
| +} // namespace favicon_base
|
|
|