/* * Copyright (C) 2012 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 HOLDERS AND CONTRIBUTORS * "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 OR CONTRIBUTORS 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 "ExclusionShape.h" #include "BasicShapeFunctions.h" #include "ExclusionPolygon.h" #include "ExclusionRectangle.h" #include "FloatSize.h" #include "LengthFunctions.h" #include "WindRule.h" #include #include #include namespace WebCore { static PassOwnPtr createExclusionRectangle(const FloatRect& bounds, const FloatSize& radii) { ASSERT(bounds.width() >= 0 && bounds.height() >= 0 && radii.width() >= 0 && radii.height() >= 0); return adoptPtr(new ExclusionRectangle(bounds, radii)); } static PassOwnPtr createExclusionCircle(const FloatPoint& center, float radius) { ASSERT(radius >= 0); return adoptPtr(new ExclusionRectangle(FloatRect(center.x() - radius, center.y() - radius, radius*2, radius*2), FloatSize(radius, radius))); } static PassOwnPtr createExclusionEllipse(const FloatPoint& center, const FloatSize& radii) { ASSERT(radii.width() >= 0 && radii.height() >= 0); return adoptPtr(new ExclusionRectangle(FloatRect(center.x() - radii.width(), center.y() - radii.height(), radii.width()*2, radii.height()*2), radii)); } static PassOwnPtr createExclusionPolygon(PassOwnPtr > vertices, WindRule fillRule) { return adoptPtr(new ExclusionPolygon(vertices, fillRule)); } // If the writingMode is vertical, then the BasicShape's (physical) x and y coordinates are swapped, so that // line segments are parallel to the internal coordinate system's X axis. PassOwnPtr ExclusionShape::createExclusionShape(const BasicShape* basicShape, float logicalBoxWidth, float logicalBoxHeight, WritingMode writingMode) { ASSERT(basicShape); bool horizontalWritingMode = isHorizontalWritingMode(writingMode); float boxWidth = horizontalWritingMode ? logicalBoxWidth : logicalBoxHeight; float boxHeight = horizontalWritingMode ? logicalBoxHeight : logicalBoxWidth; OwnPtr exclusionShape; switch (basicShape->type()) { case BasicShape::BASIC_SHAPE_RECTANGLE: { const BasicShapeRectangle* rectangle = static_cast(basicShape); FloatRect bounds( floatValueForLength(rectangle->x(), boxWidth), floatValueForLength(rectangle->y(), boxHeight), floatValueForLength(rectangle->width(), boxWidth), floatValueForLength(rectangle->height(), boxHeight)); Length radiusXLength = rectangle->cornerRadiusX(); Length radiusYLength = rectangle->cornerRadiusY(); FloatSize cornerRadii( radiusXLength.isUndefined() ? 0 : floatValueForLength(radiusXLength, boxWidth), radiusYLength.isUndefined() ? 0 : floatValueForLength(radiusYLength, boxHeight)); exclusionShape = horizontalWritingMode ? createExclusionRectangle(bounds, cornerRadii) : createExclusionRectangle(bounds.transposedRect(), cornerRadii.transposedSize()); exclusionShape->m_boundingBox = bounds; break; } case BasicShape::BASIC_SHAPE_CIRCLE: { const BasicShapeCircle* circle = static_cast(basicShape); float centerX = floatValueForLength(circle->centerX(), boxWidth); float centerY = floatValueForLength(circle->centerY(), boxHeight); float radius = floatValueForLength(circle->radius(), std::max(boxHeight, boxWidth)); exclusionShape = horizontalWritingMode ? createExclusionCircle(FloatPoint(centerX, centerY), radius) : createExclusionCircle(FloatPoint(centerY, centerX), radius); exclusionShape->m_boundingBox = FloatRect(centerX - radius, centerY - radius, radius * 2, radius * 2); break; } case BasicShape::BASIC_SHAPE_ELLIPSE: { const BasicShapeEllipse* ellipse = static_cast(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); exclusionShape = horizontalWritingMode ? createExclusionEllipse(FloatPoint(centerX, centerY), FloatSize(radiusX, radiusY)) : createExclusionEllipse(FloatPoint(centerY, centerX), FloatSize(radiusY, radiusX)); exclusionShape->m_boundingBox = FloatRect(centerX - radiusX, centerY - radiusY, radiusX * 2, radiusY * 2); break; } case BasicShape::BASIC_SHAPE_POLYGON: { const BasicShapePolygon* polygon = static_cast(basicShape); const Vector& values = polygon->values(); size_t valuesSize = values.size(); ASSERT(!(valuesSize % 2)); FloatRect boundingBox; Vector* vertices = new Vector(valuesSize / 2); for (unsigned i = 0; i < valuesSize; i += 2) { FloatPoint vertex( floatValueForLength(values.at(i), boxWidth), floatValueForLength(values.at(i + 1), boxHeight)); (*vertices)[i / 2] = horizontalWritingMode ? vertex : vertex.transposedPoint(); if (!i) boundingBox.setLocation(vertex); else boundingBox.extend(vertex); } exclusionShape = createExclusionPolygon(adoptPtr(vertices), polygon->windRule()); exclusionShape->m_boundingBox = boundingBox; break; } default: ASSERT_NOT_REACHED(); } exclusionShape->m_logicalBoxWidth = logicalBoxWidth; exclusionShape->m_logicalBoxHeight = logicalBoxHeight; exclusionShape->m_writingMode = writingMode; return exclusionShape.release(); } } // namespace WebCore