diff options
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.cpp | 161 |
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(); } |