bool SVGAnimateColorElement::updateAnimatedValue(EAnimationMode animationMode, float timePercentage, unsigned valueIndex, float percentagePast) { if (animationMode == TO_ANIMATION) // to-animations have a special equation: value = (to - base) * (time/duration) + base m_animatedColor = ColorDistance(m_baseColor, m_toColor).scaledDistance(timePercentage).addToColorAndClamp(m_baseColor); else m_animatedColor = ColorDistance(m_fromColor, m_toColor).scaledDistance(percentagePast).addToColorAndClamp(m_fromColor); return (m_animatedColor != m_baseColor); }
std::vector< types::color > GenerateRandomColorPalette( int how_many, const types::color& background_color, float distance_from_background ) { //int how_many_random = 25000; std::vector< types::color > random_colors; for( int i = 0; i < how_many || (int)random_colors.size() < how_many * 10; ++i ) { types::color random_color( ceng::Random( 0, 255 ), ceng::Random( 0, 255 ), ceng::Random( 0, 255 ) ); if( ColorDistance( random_color, background_color ) > distance_from_background ) random_colors.push_back( random_color ); } if( random_colors.empty() ) return random_colors; types::color rand_color = random_colors[ ceng::Random( 0, random_colors.size() - 1 ) ]; std::vector< types::color > result; result.push_back( rand_color ); for( int k = 0; k < how_many; ++k ) { float max_distance = 0; types::color max_color; for( unsigned int i = 0; i < random_colors.size(); ++i ) { float distance = ColorDistance( random_colors[ i ], result[ 0 ] ); for( unsigned int j = 1; j < result.size(); ++j ) { distance *= ColorDistance( random_colors[ i ], result[ j ] ); } if( distance > max_distance ) { max_distance = distance; max_color = random_colors[ i ]; } } result.push_back( max_color ); } return result; }
float SVGAnimatedColorAnimator::calculateDistance(const String& fromString, const String& toString) { ASSERT(m_contextElement); Color from = SVGColor::colorFromRGBColorString(fromString); if (!from.isValid()) return -1; Color to = SVGColor::colorFromRGBColorString(toString); if (!to.isValid()) return -1; return ColorDistance(from, to).distance(); }
static void OptimizePalette(uint32_t palette[], int num_colors) { uint32_t palette_orig[MAX_PALETTE_SIZE]; int score_orig = 0, score_new = 0; int i; // Compute original dispersion. assert(num_colors > 1 && num_colors <= MAX_PALETTE_SIZE); for (i = 1; i < num_colors; ++i) { score_orig += ColorDistance(palette[i], palette[i - 1]); } score_orig /= (num_colors - 1); // if score is already quite good, bail out at once. if (score_orig < 100) return; memcpy(palette_orig, palette, num_colors * sizeof(palette_orig[0])); // palette[0] contains the lowest ordered color already. Keep it. // Reorder subsequent palette colors by shortest distance to previous. for (i = 1; i < num_colors; ++i) { int j; int best_col = -1; int best_score = 0; const uint32_t prev_color = palette[i - 1]; for (j = i; j < num_colors; ++j) { const int score = ColorDistance(palette[j], prev_color); if (best_col < 0 || score < best_score) { best_col = j; best_score = score; } } score_new += best_score; SwapColor(&palette[best_col], &palette[i]); } // dispersion is typically in range ~[100-1000] score_new /= (num_colors - 1); if (ShouldRestoreSortedPalette(score_new, score_orig)) { memcpy(palette, palette_orig, num_colors * sizeof(palette[0])); } }
void SVGAnimatedColorAnimator::calculateAnimatedValue(float percentage, unsigned, OwnPtr<SVGAnimatedType>& from, OwnPtr<SVGAnimatedType>& to, OwnPtr<SVGAnimatedType>& animated) { ASSERT(m_animationElement); ASSERT(m_contextElement); SVGAnimateElement* animationElement = static_cast<SVGAnimateElement*>(m_animationElement); AnimationMode animationMode = animationElement->animationMode(); Color& fromColor = from->color(); Color& toColor = to->color(); Color& animatedColor = animated->color(); // To animation uses contributions from the lower priority animations as the base value. if (animationMode == ToAnimation) fromColor = animatedColor; // Replace 'currentColor' / 'inherit' by their computed property values. AnimatedPropertyValueType fromPropertyValueType = animationElement->fromPropertyValueType(); if (fromPropertyValueType == CurrentColorValue) animationElement->adjustForCurrentColor(m_contextElement, fromColor); else if (fromPropertyValueType == InheritValue) { String fromColorString; animationElement->adjustForInheritance(m_contextElement, animationElement->attributeName(), fromColorString); fromColor = SVGColor::colorFromRGBColorString(fromColorString); } AnimatedPropertyValueType toPropertyValueType = animationElement->toPropertyValueType(); if (toPropertyValueType == CurrentColorValue) animationElement->adjustForCurrentColor(m_contextElement, toColor); else if (toPropertyValueType == InheritValue) { String toColorString; animationElement->adjustForInheritance(m_contextElement, animationElement->attributeName(), toColorString); toColor = SVGColor::colorFromRGBColorString(toColorString); } Color color; if (animationElement->calcMode() == CalcModeDiscrete) color = percentage < 0.5 ? fromColor : toColor; else color = ColorDistance(fromColor, toColor).scaledDistance(percentage).addToColorAndClamp(fromColor); // FIXME: Accumulate colors. if (animationElement->isAdditive() && animationMode != ToAnimation) animatedColor = ColorDistance::addColorsAndClamp(animatedColor, color); else animatedColor = color; return; }
ColorDistance ColorDistance::scaledDistance(float scaleFactor) const { return ColorDistance(static_cast<int>(scaleFactor * m_redDiff), static_cast<int>(scaleFactor * m_greenDiff), static_cast<int>(scaleFactor * m_blueDiff)); }