blob: cc2dc3b1b6c8758ec5d376f72aeab71cd7092529 [file] [log] [blame]
/**
* Copyright 2010 Google Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
// Copyright (C) 2000 and onwards Google, Inc.
//
// Author: Feng Hu
//
// .h for the HtmlColor class
// HtmlColor provides 'IsSimilar' for comparing HTML colors
// of different representations ( "#xxxxxx" or color names such as "white").
// Before doing comparison, check 'IsDefined' first, it's because
// that not all given HTML color strings are valid.
#ifndef WEBUTIL_HTML_HTMLCOLOR_H_
#define WEBUTIL_HTML_HTMLCOLOR_H_
#include <stdlib.h>
#include <string>
#include "string_using.h"
#include "strings/stringpiece.h"
class HtmlColor {
private:
unsigned char r_;
unsigned char g_;
unsigned char b_;
// a color is well defined if it is "#xxxxxx" ('x' is a hexdigit)
// or it's a known color name such as "black"
// or it was set from valid HSL values.
// 0: the RGB value is good!
// 1: bad (name) value, caused by bad color name
// 2: bad (hex) value, caused by bad hex string value
// -- the browser (Netscape Communicator 4.75, linux-2.2.14,
// shows that the color displayed is sometimes 'black' under case '2'.
// 3: bad HSL values
unsigned char is_bad_value_;
static const unsigned char kGoodColorValue = 0;
static const unsigned char kBadColorName = 1;
static const unsigned char kBadColorHex = 2;
static const unsigned char kBadColorHSL = 3;
void SetBadNameValue() {
r_ = g_ = b_ = 0;
is_bad_value_ = kBadColorName;
}
void SetBadHexValue() {
r_ = g_ = b_ = 0;
is_bad_value_ = kBadColorHex;
}
void SetBadHslValue() {
r_ = g_ = b_ = 0;
is_bad_value_ = kBadColorHSL;
}
void SetDefaultValue() {
r_ = g_ = b_ = 0;
is_bad_value_ = kGoodColorValue;
}
public:
enum TolerateLevel { EXACTLY_SAME = 0, HIGHLY_SIMILAR = 5, SIMILAR = 10 };
// These methods also accept a CSS shorthand string "#xyz" for convenience.
// "#xyz" is expanded to "#xxyyzz" before processing.
explicit HtmlColor(StringPiece colorstr);
HtmlColor(const char* colorstr, int colorstrlen);
HtmlColor(unsigned char r, unsigned char g, unsigned char b);
bool IsDefined() const { return is_bad_value_ == 0; }
bool IsSimilar(const HtmlColor& color, int level) const {
if (!IsDefined() || !color.IsDefined()) return false;
if ((abs(static_cast<int>(r_) - static_cast<int>(color.r_)) <= level) &&
(abs(static_cast<int>(g_) - static_cast<int>(color.g_)) <= level) &&
(abs(static_cast<int>(b_) - static_cast<int>(color.b_)) <= level))
return true;
return false;
}
// Compares color similarity in HSL (Hue, Saturation, Lightness) space.
// This is assumed to be more accurate based on human perception.
// Note the difference level is a float number and it may vary from 0.0 to
// 1.0, inclusive. A suggested value for level is 0.02.
// WARNING: this is more expensive than IsSimilar() as it involves float
// arithmetic and cosine operations.
// TODO(yian): may need to disintegrate it into a separate HSL class.
bool IsSimilarInHSL(const HtmlColor& color, double level) const;
// return the luminance (0-255) of the color.
// this corresponds to a human's perception of the color's brightness
int Luminance() const;
// Lighten or darken the color by a given factor (between 0 and 1)
// Lightening with factor 1.0 => white
// Darkening with factor 1.0 => black
void Lighten(float factor);
void Darken(float factor);
// Desaturate the color (0.0 = no change, 1.0 = equivalent shade of gray)
void Desaturate(float factor);
// Blend the color with a second color by a certain factor between 0 and 1
// 1.0 => original color
// 0.0 => other color
void BlendWithColor(float factor, const HtmlColor& c);
string ToString() const;
// hexstr is in form of "xxxxxx"
void SetValueFromHexStr(StringPiece hexstr);
// either a color name or a hex string "#xxxxxx"
// This method also accepts a CSS shorthand string "#xyz" for convenience.
// "#xyz" is expanded to "#xxyyzz" before processing.
void SetValueFromStr(StringPiece str);
// Set the html color object from rgb values
void SetValueFromRGB(unsigned char r, unsigned char g, unsigned char b);
// Set the html color object from hsl values, hue must be in [0, 1),
// saturation and lightness in [0, 1] otherwise IsDefined will return false.;
// WARNING: This is more expensive than SetValueFromRGB.
void SetValueFromHSL(double hue, double saturation, double lightness);
// Converts a valid number to HSL color space. hue is in [0, 1), saturation
// and lightness in [0, 1].
// When IsDefined is false this method does not modify the value of hue,
// saturation and lightness and returns false.
bool GetValueInHSL(double* hue, double* saturation, double* lightness) const;
// must be a color name. It can be one of 147 colors defined in CSS3 color
// module or SVG 1.0, which is supported by all major browsers. A reference
// can be found at:
// http://www.w3.org/TR/css3-color/#svg-color
void SetValueFromName(StringPiece str);
// Two IsDefined() colors are equal if their rgb()s are equal.
// An IsDefined() color is not equal to a !IsDefined() color.
// Two !IsDefined() colors are equal regardless of their rgb()s.
bool Equals(const HtmlColor& color) const;
int r() const { return static_cast<int>(r_); }
int g() const { return static_cast<int>(g_); }
int b() const { return static_cast<int>(b_); }
int rgb() const { return b() + (g() << 8) + (r() << 16); }
};
class HtmlColorUtils {
public:
// Converts a color into its shortest possible CSS representation.
// For 9 colors, that is their color name. Example: "#008000" returns "green".
// For colors in the form #rrggbb, where r=r, g=g, and b=b, that is #rgb.
// Example: "#aabbcc" returns "#abc".
// For all other colors, the six hex-digit representation is shortest.
// Example: "lightgoldenrodyellow" returns "#FAFAD2"
static string MaybeConvertToCssShorthand(const HtmlColor& color);
static string MaybeConvertToCssShorthand(StringPiece orig);
};
#endif // WEBUTIL_HTML_HTMLCOLOR_H_