summaryrefslogtreecommitdiffstats
path: root/chromium/third_party/WebKit/Source/core/rendering/shapes/Shape.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'chromium/third_party/WebKit/Source/core/rendering/shapes/Shape.cpp')
-rw-r--r--chromium/third_party/WebKit/Source/core/rendering/shapes/Shape.cpp161
1 files changed, 62 insertions, 99 deletions
diff --git a/chromium/third_party/WebKit/Source/core/rendering/shapes/Shape.cpp b/chromium/third_party/WebKit/Source/core/rendering/shapes/Shape.cpp
index ffe05053133..6e382254b9a 100644
--- a/chromium/third_party/WebKit/Source/core/rendering/shapes/Shape.cpp
+++ b/chromium/third_party/WebKit/Source/core/rendering/shapes/Shape.cpp
@@ -30,14 +30,16 @@
#include "config.h"
#include "core/rendering/shapes/Shape.h"
+#include "core/css/BasicShapeFunctions.h"
#include "core/fetch/ImageResource.h"
#include "core/rendering/shapes/BoxShape.h"
#include "core/rendering/shapes/PolygonShape.h"
#include "core/rendering/shapes/RasterShape.h"
#include "core/rendering/shapes/RectangleShape.h"
+#include "core/rendering/style/RenderStyle.h"
#include "platform/LengthFunctions.h"
-#include "platform/geometry/FloatRoundedRect.h"
#include "platform/geometry/FloatSize.h"
+#include "platform/graphics/GraphicsContext.h"
#include "platform/graphics/ImageBuffer.h"
#include "platform/graphics/WindRule.h"
#include "wtf/MathExtras.h"
@@ -45,18 +47,12 @@
namespace WebCore {
-static PassOwnPtr<Shape> createBoxShape(const FloatRoundedRect& bounds)
+static PassOwnPtr<Shape> createInsetShape(const FloatRoundedRect& bounds)
{
ASSERT(bounds.rect().width() >= 0 && bounds.rect().height() >= 0);
return adoptPtr(new BoxShape(bounds));
}
-static PassOwnPtr<Shape> createRectangleShape(const FloatRect& bounds, const FloatSize& radii)
-{
- ASSERT(bounds.width() >= 0 && bounds.height() >= 0 && radii.width() >= 0 && radii.height() >= 0);
- return adoptPtr(new RectangleShape(bounds, radii));
-}
-
static PassOwnPtr<Shape> createCircleShape(const FloatPoint& center, float radius)
{
ASSERT(radius >= 0);
@@ -99,55 +95,22 @@ static inline FloatSize physicalSizeToLogical(const FloatSize& size, WritingMode
return size.transposedSize();
}
-static inline void ensureRadiiDoNotOverlap(FloatRect &bounds, FloatSize &radii)
-{
- float widthRatio = bounds.width() / (2 * radii.width());
- float heightRatio = bounds.height() / (2 * radii.height());
- float reductionRatio = std::min<float>(widthRatio, heightRatio);
- if (reductionRatio < 1) {
- radii.setWidth(reductionRatio * radii.width());
- radii.setHeight(reductionRatio * radii.height());
- }
-}
-
-PassOwnPtr<Shape> Shape::createShape(const BasicShape* basicShape, const LayoutSize& logicalBoxSize, WritingMode writingMode, Length margin, Length padding)
+PassOwnPtr<Shape> Shape::createShape(const BasicShape* basicShape, const LayoutSize& logicalBoxSize, WritingMode writingMode, float margin)
{
ASSERT(basicShape);
bool horizontalWritingMode = isHorizontalWritingMode(writingMode);
- float boxWidth = horizontalWritingMode ? logicalBoxSize.width() : logicalBoxSize.height();
- float boxHeight = horizontalWritingMode ? logicalBoxSize.height() : logicalBoxSize.width();
+ float boxWidth = horizontalWritingMode ? logicalBoxSize.width().toFloat() : logicalBoxSize.height().toFloat();
+ float boxHeight = horizontalWritingMode ? logicalBoxSize.height().toFloat() : logicalBoxSize.width().toFloat();
OwnPtr<Shape> shape;
switch (basicShape->type()) {
- case BasicShape::BasicShapeRectangleType: {
- const BasicShapeRectangle* rectangle = static_cast<const BasicShapeRectangle*>(basicShape);
- FloatRect bounds(
- floatValueForLength(rectangle->x(), boxWidth),
- floatValueForLength(rectangle->y(), boxHeight),
- floatValueForLength(rectangle->width(), boxWidth),
- floatValueForLength(rectangle->height(), boxHeight));
- FloatSize cornerRadii(
- floatValueForLength(rectangle->cornerRadiusX(), boxWidth),
- floatValueForLength(rectangle->cornerRadiusY(), boxHeight));
- ensureRadiiDoNotOverlap(bounds, cornerRadii);
- FloatRect logicalBounds = physicalRectToLogical(bounds, logicalBoxSize.height(), writingMode);
-
- shape = createRectangleShape(logicalBounds, physicalSizeToLogical(cornerRadii, writingMode));
- break;
- }
-
case BasicShape::BasicShapeCircleType: {
const BasicShapeCircle* circle = static_cast<const BasicShapeCircle*>(basicShape);
- float centerX = floatValueForLength(circle->centerX(), boxWidth);
- float centerY = floatValueForLength(circle->centerY(), boxHeight);
- // This method of computing the radius is as defined in SVG
- // (http://www.w3.org/TR/SVG/coords.html#Units). It bases the radius
- // off of the diagonal of the box and ensures that if the box is
- // square, the radius is equal to half the diagonal.
- float radius = floatValueForLength(circle->radius(), sqrtf((boxWidth * boxWidth + boxHeight * boxHeight) / 2));
- FloatPoint logicalCenter = physicalPointToLogical(FloatPoint(centerX, centerY), logicalBoxSize.height(), writingMode);
+ FloatPoint center = floatPointForCenterCoordinate(circle->centerX(), circle->centerY(), FloatSize(boxWidth, boxHeight));
+ float radius = circle->floatValueForRadiusInBox(FloatSize(boxWidth, boxHeight));
+ FloatPoint logicalCenter = physicalPointToLogical(center, logicalBoxSize.height().toFloat(), writingMode);
shape = createCircleShape(logicalCenter, radius);
break;
@@ -155,14 +118,12 @@ PassOwnPtr<Shape> Shape::createShape(const BasicShape* basicShape, const LayoutS
case BasicShape::BasicShapeEllipseType: {
const BasicShapeEllipse* ellipse = static_cast<const BasicShapeEllipse*>(basicShape);
- float centerX = floatValueForLength(ellipse->centerX(), boxWidth);
- float centerY = floatValueForLength(ellipse->centerY(), boxHeight);
- float radiusX = floatValueForLength(ellipse->radiusX(), boxWidth);
- float radiusY = floatValueForLength(ellipse->radiusY(), boxHeight);
- FloatPoint logicalCenter = physicalPointToLogical(FloatPoint(centerX, centerY), logicalBoxSize.height(), writingMode);
- FloatSize logicalRadii = physicalSizeToLogical(FloatSize(radiusX, radiusY), writingMode);
-
- shape = createEllipseShape(logicalCenter, logicalRadii);
+ FloatPoint center = floatPointForCenterCoordinate(ellipse->centerX(), ellipse->centerY(), FloatSize(boxWidth, boxHeight));
+ float radiusX = ellipse->floatValueForRadiusInBox(ellipse->radiusX(), center.x(), boxWidth);
+ float radiusY = ellipse->floatValueForRadiusInBox(ellipse->radiusY(), center.y(), boxHeight);
+ FloatPoint logicalCenter = physicalPointToLogical(center, logicalBoxSize.height().toFloat(), writingMode);
+
+ shape = createEllipseShape(logicalCenter, FloatSize(radiusX, radiusY));
break;
}
@@ -176,28 +137,31 @@ PassOwnPtr<Shape> Shape::createShape(const BasicShape* basicShape, const LayoutS
FloatPoint vertex(
floatValueForLength(values.at(i), boxWidth),
floatValueForLength(values.at(i + 1), boxHeight));
- (*vertices)[i / 2] = physicalPointToLogical(vertex, logicalBoxSize.height(), writingMode);
+ (*vertices)[i / 2] = physicalPointToLogical(vertex, logicalBoxSize.height().toFloat(), writingMode);
}
shape = createPolygonShape(vertices.release(), polygon->windRule());
break;
}
- case BasicShape::BasicShapeInsetRectangleType: {
- const BasicShapeInsetRectangle* rectangle = static_cast<const BasicShapeInsetRectangle*>(basicShape);
- float left = floatValueForLength(rectangle->left(), boxWidth);
- float top = floatValueForLength(rectangle->top(), boxHeight);
- FloatRect bounds(
- left,
- top,
- boxWidth - left - floatValueForLength(rectangle->right(), boxWidth),
- boxHeight - top - floatValueForLength(rectangle->bottom(), boxHeight));
- FloatSize cornerRadii(
- floatValueForLength(rectangle->cornerRadiusX(), boxWidth),
- floatValueForLength(rectangle->cornerRadiusY(), boxHeight));
- ensureRadiiDoNotOverlap(bounds, cornerRadii);
- FloatRect logicalBounds = physicalRectToLogical(bounds, logicalBoxSize.height(), writingMode);
-
- shape = createRectangleShape(logicalBounds, physicalSizeToLogical(cornerRadii, writingMode));
+ case BasicShape::BasicShapeInsetType: {
+ const BasicShapeInset& inset = *static_cast<const BasicShapeInset*>(basicShape);
+ float left = floatValueForLength(inset.left(), boxWidth);
+ float top = floatValueForLength(inset.top(), boxHeight);
+ float right = floatValueForLength(inset.right(), boxWidth);
+ float bottom = floatValueForLength(inset.bottom(), boxHeight);
+ FloatRect rect(left, top, std::max<float>(boxWidth - left - right, 0), std::max<float>(boxHeight - top - bottom, 0));
+ FloatRect logicalRect = physicalRectToLogical(rect, logicalBoxSize.height().toFloat(), writingMode);
+
+ FloatSize boxSize(boxWidth, boxHeight);
+ FloatSize topLeftRadius = physicalSizeToLogical(floatSizeForLengthSize(inset.topLeftRadius(), boxSize), writingMode);
+ FloatSize topRightRadius = physicalSizeToLogical(floatSizeForLengthSize(inset.topRightRadius(), boxSize), writingMode);
+ FloatSize bottomLeftRadius = physicalSizeToLogical(floatSizeForLengthSize(inset.bottomLeftRadius(), boxSize), writingMode);
+ FloatSize bottomRightRadius = physicalSizeToLogical(floatSizeForLengthSize(inset.bottomRightRadius(), boxSize), writingMode);
+ FloatRoundedRect::Radii cornerRadii(topLeftRadius, topRightRadius, bottomLeftRadius, bottomRightRadius);
+
+ cornerRadii.scale(calcBorderRadiiConstraintScaleFor(logicalRect, cornerRadii));
+
+ shape = createInsetShape(FloatRoundedRect(logicalRect, cornerRadii));
break;
}
@@ -206,61 +170,60 @@ PassOwnPtr<Shape> Shape::createShape(const BasicShape* basicShape, const LayoutS
}
shape->m_writingMode = writingMode;
- shape->m_margin = floatValueForLength(margin, 0);
- shape->m_padding = floatValueForLength(padding, 0);
+ shape->m_margin = margin;
return shape.release();
}
-PassOwnPtr<Shape> Shape::createShape(const StyleImage* styleImage, float threshold, const LayoutSize&, WritingMode writingMode, Length margin, Length padding)
+PassOwnPtr<Shape> Shape::createRasterShape(Image* image, float threshold, const LayoutRect& imageR, const LayoutRect& marginR, WritingMode writingMode, float margin)
{
- ASSERT(styleImage && styleImage->isImageResource() && styleImage->cachedImage() && styleImage->cachedImage()->image());
+ IntRect imageRect = pixelSnappedIntRect(imageR);
+ IntRect marginRect = pixelSnappedIntRect(marginR);
+ OwnPtr<RasterShapeIntervals> intervals = adoptPtr(new RasterShapeIntervals(marginRect.height(), -marginRect.y()));
+ OwnPtr<ImageBuffer> imageBuffer = ImageBuffer::create(imageRect.size());
- Image* image = styleImage->cachedImage()->image();
- const IntSize& imageSize = image->size();
- OwnPtr<RasterShapeIntervals> intervals = adoptPtr(new RasterShapeIntervals(imageSize.height()));
- OwnPtr<ImageBuffer> imageBuffer = ImageBuffer::create(imageSize);
if (imageBuffer) {
GraphicsContext* graphicsContext = imageBuffer->context();
- graphicsContext->drawImage(image, IntPoint());
+ graphicsContext->drawImage(image, IntRect(IntPoint(), imageRect.size()));
- RefPtr<Uint8ClampedArray> pixelArray = imageBuffer->getUnmultipliedImageData(IntRect(IntPoint(), imageSize));
- unsigned pixelArrayLength = pixelArray->length();
+ RefPtr<Uint8ClampedArray> pixelArray = imageBuffer->getUnmultipliedImageData(IntRect(IntPoint(), imageRect.size()));
unsigned pixelArrayOffset = 3; // Each pixel is four bytes: RGBA.
uint8_t alphaPixelThreshold = threshold * 255;
- ASSERT(static_cast<unsigned>(imageSize.width() * imageSize.height() * 4) == pixelArrayLength);
+ ASSERT(static_cast<unsigned>(imageRect.width() * imageRect.height() * 4) == pixelArray->length());
+
+ int minBufferY = std::max(0, marginRect.y() - imageRect.y());
+ int maxBufferY = std::min(imageRect.height(), marginRect.maxY() - imageRect.y());
- for (int y = 0; y < imageSize.height(); ++y) {
+ for (int y = minBufferY; y < maxBufferY; ++y) {
int startX = -1;
- for (int x = 0; x < imageSize.width() && pixelArrayOffset < pixelArrayLength; ++x, pixelArrayOffset += 4) {
+ for (int x = 0; x < imageRect.width(); ++x, pixelArrayOffset += 4) {
uint8_t alpha = pixelArray->item(pixelArrayOffset);
- if ((startX == -1) && alpha > alphaPixelThreshold) {
+ bool alphaAboveThreshold = alpha > alphaPixelThreshold;
+ if (startX == -1 && alphaAboveThreshold) {
startX = x;
- } else if (startX != -1 && (alpha <= alphaPixelThreshold || x == imageSize.width() - 1)) {
- intervals->appendInterval(y, startX, x);
+ } else if (startX != -1 && (!alphaAboveThreshold || x == imageRect.width() - 1)) {
+ int endX = alphaAboveThreshold ? x + 1 : x;
+ intervals->intervalAt(y + imageRect.y()).unite(IntShapeInterval(startX + imageRect.x(), endX + imageRect.x()));
startX = -1;
}
}
}
}
- OwnPtr<RasterShape> rasterShape = adoptPtr(new RasterShape(intervals.release(), imageSize));
+ OwnPtr<RasterShape> rasterShape = adoptPtr(new RasterShape(intervals.release(), marginRect.size()));
rasterShape->m_writingMode = writingMode;
- rasterShape->m_margin = floatValueForLength(margin, 0);
- rasterShape->m_padding = floatValueForLength(padding, 0);
+ rasterShape->m_margin = margin;
return rasterShape.release();
}
-PassOwnPtr<Shape> Shape::createLayoutBoxShape(const LayoutSize& logicalSize, WritingMode writingMode, const Length& margin, const Length& padding)
+PassOwnPtr<Shape> Shape::createLayoutBoxShape(const RoundedRect& roundedRect, WritingMode writingMode, float margin)
{
- FloatRect rect(0, 0, logicalSize.width(), logicalSize.height());
- FloatSize radii(0, 0);
- FloatRoundedRect bounds(rect, radii, radii, radii, radii);
- OwnPtr<Shape> shape = createBoxShape(bounds);
+ FloatRect rect(0, 0, roundedRect.rect().width(), roundedRect.rect().height());
+ FloatRoundedRect bounds(rect, roundedRect.radii());
+ OwnPtr<Shape> shape = createInsetShape(bounds);
shape->m_writingMode = writingMode;
- shape->m_margin = floatValueForLength(margin, 0);
- shape->m_padding = floatValueForLength(padding, 0);
+ shape->m_margin = margin;
return shape.release();
}