blob: 3fda6b1d1eeb3e77b076d9aa4fedb2d742c7aa71 [file] [log] [blame]
/*
* Copyright (C) 2011 Adobe Systems Incorporated. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* 1. Redistributions of source code must retain the above
* copyright notice, this list of conditions and the following
* disclaimer.
* 2. Redistributions in binary form must reproduce the above
* copyright notice, this list of conditions and the following
* disclaimer in the documentation and/or other materials
* provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDER “AS IS” AND ANY
* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER BE
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY,
* OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR
* TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF
* THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*/
#include "config.h"
#include "CSSBasicShapes.h"
#include <wtf/text/StringBuilder.h>
using namespace WTF;
namespace WebCore {
static String buildRectangleString(const String& x, const String& y, const String& width, const String& height, const String& radiusX, const String& radiusY)
{
char opening[] = "rectangle(";
char separator[] = ", ";
StringBuilder result;
// Compute the required capacity in advance to reduce allocations.
result.reserveCapacity((sizeof(opening) - 1) + (5 * (sizeof(separator) -1 )) + 1 + x.length() + y.length() + width.length() + height.length() + radiusX.length() + radiusY.length());
result.appendLiteral(opening);
result.append(x);
result.appendLiteral(separator);
result.append(y);
result.appendLiteral(separator);
result.append(width);
result.appendLiteral(separator);
result.append(height);
if (!radiusX.isNull()) {
result.appendLiteral(separator);
result.append(radiusX);
if (!radiusY.isNull()) {
result.appendLiteral(separator);
result.append(radiusY);
}
}
result.append(')');
return result.toString();
}
String CSSBasicShapeRectangle::cssText() const
{
return buildRectangleString(m_x->cssText(),
m_y->cssText(),
m_width->cssText(),
m_height->cssText(),
m_radiusX.get() ? m_radiusX->cssText() : String(),
m_radiusY.get() ? m_radiusY->cssText() : String());
}
#if ENABLE(CSS_VARIABLES)
String CSSBasicShapeRectangle::serializeResolvingVariables(const HashMap<AtomicString, String>& variables) const
{
return buildRectangleString(m_x->serializeResolvingVariables(variables),
m_y->serializeResolvingVariables(variables),
m_width->serializeResolvingVariables(variables),
m_height->serializeResolvingVariables(variables),
m_radiusX.get() ? m_radiusX->serializeResolvingVariables(variables) : String(),
m_radiusY.get() ? m_radiusY->serializeResolvingVariables(variables) : String());
}
bool CSSBasicShapeRectangle::hasVariableReference() const
{
return m_x->hasVariableReference()
|| m_y->hasVariableReference()
|| m_width->hasVariableReference()
|| m_height->hasVariableReference()
|| (m_radiusX.get() && m_radiusX->hasVariableReference())
|| (m_radiusY.get() && m_radiusY->hasVariableReference());
}
#endif
static String buildCircleString(const String& x, const String& y, const String& radius)
{
return "circle(" + x + ", " + y + ", " + radius + ')';
}
String CSSBasicShapeCircle::cssText() const
{
return buildCircleString(m_centerX->cssText(), m_centerY->cssText(), m_radius->cssText());
}
#if ENABLE(CSS_VARIABLES)
String CSSBasicShapeCircle::serializeResolvingVariables(const HashMap<AtomicString, String>& variables) const
{
return buildCircleString(m_centerX->serializeResolvingVariables(variables),
m_centerY->serializeResolvingVariables(variables),
m_radius->serializeResolvingVariables(variables));
}
bool CSSBasicShapeCircle::hasVariableReference() const
{
return m_centerX->hasVariableReference()
|| m_centerY->hasVariableReference()
|| m_radius->hasVariableReference();
}
#endif
static String buildEllipseString(const String& x, const String& y, const String& radiusX, const String& radiusY)
{
return "ellipse(" + x + ", " + y + ", " + radiusX + ", " + radiusY + ')';
}
String CSSBasicShapeEllipse::cssText() const
{
return buildEllipseString(m_centerX->cssText(), m_centerY->cssText(), m_radiusX->cssText(), m_radiusY->cssText());
}
#if ENABLE(CSS_VARIABLES)
String CSSBasicShapeEllipse::serializeResolvingVariables(const HashMap<AtomicString, String>& variables) const
{
return buildEllipseString(m_centerX->serializeResolvingVariables(variables),
m_centerY->serializeResolvingVariables(variables),
m_radiusX->serializeResolvingVariables(variables),
m_radiusY->serializeResolvingVariables(variables));
}
bool CSSBasicShapeEllipse::hasVariableReference() const
{
return m_centerX->hasVariableReference()
|| m_centerY->hasVariableReference()
|| m_radiusX->hasVariableReference()
|| m_radiusY->hasVariableReference();
}
#endif
static String buildPolygonString(const WindRule& windRule, const Vector<String>& points)
{
ASSERT(!(points.size() % 2));
StringBuilder result;
char evenOddOpening[] = "polygon(evenodd, ";
char nonZeroOpening[] = "polygon(nonzero, ";
char commaSeparator[] = ", ";
COMPILE_ASSERT(sizeof(evenOddOpening) == sizeof(nonZeroOpening), polygon_string_openings_have_same_length);
// Compute the required capacity in advance to reduce allocations.
size_t length = sizeof(evenOddOpening) - 1;
for (size_t i = 0; i < points.size(); i += 2) {
if (i)
length += (sizeof(commaSeparator) - 1);
// add length of two strings, plus one for the space separator.
length += points[i].length() + 1 + points[i + 1].length();
}
result.reserveCapacity(length);
if (windRule == RULE_EVENODD)
result.appendLiteral(evenOddOpening);
else
result.appendLiteral(nonZeroOpening);
for (size_t i = 0; i < points.size(); i += 2) {
if (i)
result.appendLiteral(commaSeparator);
result.append(points[i]);
result.append(' ');
result.append(points[i + 1]);
}
result.append(')');
return result.toString();
}
String CSSBasicShapePolygon::cssText() const
{
Vector<String> points;
points.reserveInitialCapacity(m_values.size());
for (size_t i = 0; i < m_values.size(); ++i)
points.append(m_values.at(i)->cssText());
return buildPolygonString(m_windRule, points);
}
#if ENABLE(CSS_VARIABLES)
String CSSBasicShapePolygon::serializeResolvingVariables(const HashMap<AtomicString, String>& variables) const
{
Vector<String> points;
points.reserveInitialCapacity(m_values.size());
for (size_t i = 0; i < m_values.size(); ++i)
points.append(m_values.at(i)->serializeResolvingVariables(variables));
return buildPolygonString(m_windRule, points);
}
bool CSSBasicShapePolygon::hasVariableReference() const
{
for (size_t i = 0; i < m_values.size(); ++i) {
if (m_values.at(i)->hasVariableReference())
return true;
}
return false;
}
#endif
} // namespace WebCore