CSSValue* valueForBasicShape(const ComputedStyle& style, const BasicShape* basicShape) { switch (basicShape->type()) { case BasicShape::BasicShapeCircleType: { const BasicShapeCircle* circle = toBasicShapeCircle(basicShape); CSSBasicShapeCircleValue* circleValue = CSSBasicShapeCircleValue::create(); circleValue->setCenterX(valueForCenterCoordinate(style, circle->centerX(), HORIZONTAL)); circleValue->setCenterY(valueForCenterCoordinate(style, circle->centerY(), VERTICAL)); circleValue->setRadius(basicShapeRadiusToCSSValue(style, circle->radius())); return circleValue; } case BasicShape::BasicShapeEllipseType: { const BasicShapeEllipse* ellipse = toBasicShapeEllipse(basicShape); CSSBasicShapeEllipseValue* ellipseValue = CSSBasicShapeEllipseValue::create(); ellipseValue->setCenterX(valueForCenterCoordinate(style, ellipse->centerX(), HORIZONTAL)); ellipseValue->setCenterY(valueForCenterCoordinate(style, ellipse->centerY(), VERTICAL)); ellipseValue->setRadiusX(basicShapeRadiusToCSSValue(style, ellipse->radiusX())); ellipseValue->setRadiusY(basicShapeRadiusToCSSValue(style, ellipse->radiusY())); return ellipseValue; } case BasicShape::BasicShapePolygonType: { const BasicShapePolygon* polygon = toBasicShapePolygon(basicShape); CSSBasicShapePolygonValue* polygonValue = CSSBasicShapePolygonValue::create(); polygonValue->setWindRule(polygon->getWindRule()); const Vector<Length>& values = polygon->values(); for (unsigned i = 0; i < values.size(); i += 2) polygonValue->appendPoint(CSSPrimitiveValue::create(values.at(i), style), CSSPrimitiveValue::create(values.at(i + 1), style)); return polygonValue; } case BasicShape::BasicShapeInsetType: { const BasicShapeInset* inset = toBasicShapeInset(basicShape); CSSBasicShapeInsetValue* insetValue = CSSBasicShapeInsetValue::create(); insetValue->setTop(CSSPrimitiveValue::create(inset->top(), style)); insetValue->setRight(CSSPrimitiveValue::create(inset->right(), style)); insetValue->setBottom(CSSPrimitiveValue::create(inset->bottom(), style)); insetValue->setLeft(CSSPrimitiveValue::create(inset->left(), style)); insetValue->setTopLeftRadius(CSSValuePair::create(inset->topLeftRadius(), style)); insetValue->setTopRightRadius(CSSValuePair::create(inset->topRightRadius(), style)); insetValue->setBottomRightRadius(CSSValuePair::create(inset->bottomRightRadius(), style)); insetValue->setBottomLeftRadius(CSSValuePair::create(inset->bottomLeftRadius(), style)); return insetValue; } default: return nullptr; } }
bool BasicShapeInset::operator==(const BasicShape& o) const { if (!isSameType(o)) return false; const BasicShapeInset& other = toBasicShapeInset(o); return m_right == other.m_right && m_top == other.m_top && m_bottom == other.m_bottom && m_left == other.m_left && m_topLeftRadius == other.m_topLeftRadius && m_topRightRadius == other.m_topRightRadius && m_bottomRightRadius == other.m_bottomRightRadius && m_bottomLeftRadius == other.m_bottomLeftRadius; }
PassRefPtr<BasicShape> BasicShapeInset::blend(const BasicShape* other, double progress) const { ASSERT(other && isSameType(*other)); const BasicShapeInset& otherInset = toBasicShapeInset(*other); RefPtr<BasicShapeInset> result = BasicShapeInset::create(); result->setTop(m_top.blend(otherInset.top(), progress, ValueRangeAll)); result->setRight(m_right.blend(otherInset.right(), progress, ValueRangeAll)); result->setBottom(m_bottom.blend(otherInset.bottom(), progress, ValueRangeAll)); result->setLeft(m_left.blend(otherInset.left(), progress, ValueRangeAll)); result->setTopLeftRadius(blendLengthSize(m_topLeftRadius, otherInset.topLeftRadius(), progress)); result->setTopRightRadius(blendLengthSize(m_topRightRadius, otherInset.topRightRadius(), progress)); result->setBottomRightRadius(blendLengthSize(m_bottomRightRadius, otherInset.bottomRightRadius(), progress)); result->setBottomLeftRadius(blendLengthSize(m_bottomLeftRadius, otherInset.bottomLeftRadius(), progress)); return result.release(); }
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().toFloat() : logicalBoxSize.height().toFloat(); float boxHeight = horizontalWritingMode ? logicalBoxSize.height().toFloat() : logicalBoxSize.width().toFloat(); OwnPtr<Shape> shape; switch (basicShape->type()) { case BasicShape::BasicShapeCircleType: { const BasicShapeCircle* circle = toBasicShapeCircle(basicShape); 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; } case BasicShape::BasicShapeEllipseType: { const BasicShapeEllipse* ellipse = toBasicShapeEllipse(basicShape); 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; } case BasicShape::BasicShapePolygonType: { const BasicShapePolygon* polygon = toBasicShapePolygon(basicShape); const Vector<Length>& values = polygon->values(); size_t valuesSize = values.size(); ASSERT(!(valuesSize % 2)); OwnPtr<Vector<FloatPoint>> vertices = adoptPtr(new Vector<FloatPoint>(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] = physicalPointToLogical(vertex, logicalBoxSize.height().toFloat(), writingMode); } shape = createPolygonShape(vertices.release(), polygon->windRule()); break; } case BasicShape::BasicShapeInsetType: { const BasicShapeInset& inset = *toBasicShapeInset(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); FloatRoundedRect finalRect(logicalRect, cornerRadii); finalRect.constrainRadii(); shape = createInsetShape(finalRect); break; } default: ASSERT_NOT_REACHED(); } shape->m_writingMode = writingMode; shape->m_margin = margin; return shape.release(); }