void RoundedIntRect::Radii::includeLogicalEdges(const RoundedIntRect::Radii& edges, bool isHorizontal, bool includeLogicalLeftEdge, bool includeLogicalRightEdge) { if (includeLogicalLeftEdge) { if (isHorizontal) m_bottomLeft = edges.bottomLeft(); else m_topRight = edges.topRight(); m_topLeft = edges.topLeft(); } if (includeLogicalRightEdge) { if (isHorizontal) m_topRight = edges.topRight(); else m_bottomLeft = edges.bottomLeft(); m_bottomRight = edges.bottomRight(); } }
void ShadowBlur::drawRectShadowWithoutTiling(GraphicsContext* graphicsContext, const FloatRect& shadowedRect, const RoundedIntRect::Radii& radii, const IntRect& layerRect) { GraphicsContext* shadowContext = beginShadowLayer(graphicsContext, layerRect); if (!shadowContext) return; Path path; path.addRoundedRect(shadowedRect, radii.topLeft(), radii.topRight(), radii.bottomLeft(), radii.bottomRight()); shadowContext->setFillColor(Color::black, ColorSpaceDeviceRGB); shadowContext->fillPath(path); endShadowLayer(graphicsContext); }
void ShadowBlur::drawRectShadowWithTiling(GraphicsContext* graphicsContext, const FloatRect& shadowedRect, const RoundedIntRect::Radii& radii, const IntSize& shadowTemplateSize) { const float roundedRadius = ceilf(m_blurRadius); const float twiceRadius = roundedRadius * 2; // Size of the tiling side. const int templateSideLength = 1; m_layerImage = ScratchBuffer::shared().getScratchBuffer(shadowTemplateSize); // Draw shadow into a new ImageBuffer. GraphicsContext* shadowContext = m_layerImage->context(); shadowContext->save(); shadowContext->clearRect(FloatRect(0, 0, shadowTemplateSize.width(), shadowTemplateSize.height())); // Draw the rectangle. FloatRect templateRect = FloatRect(roundedRadius, roundedRadius, shadowTemplateSize.width() - twiceRadius, shadowTemplateSize.height() - twiceRadius); Path path; path.addRoundedRect(templateRect, radii.topLeft(), radii.topRight(), radii.bottomLeft(), radii.bottomRight()); shadowContext->setFillColor(Color(.0f, .0f, .0f, 1.f), ColorSpaceDeviceRGB); shadowContext->fillPath(path); // Blur the image. { IntRect blurRect(IntPoint(), shadowTemplateSize); RefPtr<ByteArray> layerData = m_layerImage->getUnmultipliedImageData(blurRect); blurLayerImage(layerData->data(), blurRect.size(), blurRect.width() * 4); m_layerImage->putUnmultipliedImageData(layerData.get(), blurRect.size(), blurRect, IntPoint()); } // Mask the image with the shadow color. shadowContext->setCompositeOperation(CompositeSourceIn); shadowContext->setFillColor(m_color, m_colorSpace); shadowContext->fillRect(FloatRect(0, 0, shadowTemplateSize.width(), shadowTemplateSize.height())); shadowContext->restore(); FloatRect shadowRect = shadowedRect; shadowRect.inflate(roundedRadius); // FIXME: duplicating code with calculateLayerBoundingRect. shadowRect.move(m_offset.width(), m_offset.height()); // Fill the internal part of the shadow. shadowRect.inflate(-twiceRadius); if (!shadowRect.isEmpty()) { graphicsContext->save(); path.clear(); path.addRoundedRect(shadowRect, radii.topLeft(), radii.topRight(), radii.bottomLeft(), radii.bottomRight()); graphicsContext->setFillColor(m_color, m_colorSpace); graphicsContext->fillPath(path); graphicsContext->restore(); } shadowRect.inflate(twiceRadius); // Note that drawing the ImageBuffer is faster than creating a Image and drawing that, // because ImageBuffer::draw() knows that it doesn't have to copy the image bits. // Draw top side. FloatRect tileRect = FloatRect(twiceRadius + radii.topLeft().width(), 0, templateSideLength, twiceRadius); FloatRect destRect = tileRect; destRect.move(shadowRect.x(), shadowRect.y()); destRect.setWidth(shadowRect.width() - radii.topLeft().width() - radii.topRight().width() - roundedRadius * 4); graphicsContext->drawImageBuffer(m_layerImage, ColorSpaceDeviceRGB, destRect, tileRect); // Draw the bottom side. tileRect = FloatRect(twiceRadius + radii.bottomLeft().width(), shadowTemplateSize.height() - twiceRadius, templateSideLength, twiceRadius); destRect = tileRect; destRect.move(shadowRect.x(), shadowRect.y() + twiceRadius + shadowedRect.height() - shadowTemplateSize.height()); destRect.setWidth(shadowRect.width() - radii.bottomLeft().width() - radii.bottomRight().width() - roundedRadius * 4); graphicsContext->drawImageBuffer(m_layerImage, ColorSpaceDeviceRGB, destRect, tileRect); // Draw the right side. tileRect = FloatRect(shadowTemplateSize.width() - twiceRadius, twiceRadius + radii.topRight().height(), twiceRadius, templateSideLength); destRect = tileRect; destRect.move(shadowRect.x() + twiceRadius + shadowedRect.width() - shadowTemplateSize.width(), shadowRect.y()); destRect.setHeight(shadowRect.height() - radii.topRight().height() - radii.bottomRight().height() - roundedRadius * 4); graphicsContext->drawImageBuffer(m_layerImage, ColorSpaceDeviceRGB, destRect, tileRect); // Draw the left side. tileRect = FloatRect(0, twiceRadius + radii.topLeft().height(), twiceRadius, templateSideLength); destRect = tileRect; destRect.move(shadowRect.x(), shadowRect.y()); destRect.setHeight(shadowRect.height() - radii.topLeft().height() - radii.bottomLeft().height() - roundedRadius * 4); graphicsContext->drawImageBuffer(m_layerImage, ColorSpaceDeviceRGB, destRect, tileRect); // Draw the top left corner. tileRect = FloatRect(0, 0, twiceRadius + radii.topLeft().width(), twiceRadius + radii.topLeft().height()); destRect = tileRect; destRect.move(shadowRect.x(), shadowRect.y()); graphicsContext->drawImageBuffer(m_layerImage, ColorSpaceDeviceRGB, destRect, tileRect); // Draw the top right corner. tileRect = FloatRect(shadowTemplateSize.width() - twiceRadius - radii.topRight().width(), 0, twiceRadius + radii.topRight().width(), twiceRadius + radii.topRight().height()); destRect = tileRect; destRect.move(shadowRect.x() + shadowedRect.width() - shadowTemplateSize.width() + twiceRadius, shadowRect.y()); graphicsContext->drawImageBuffer(m_layerImage, ColorSpaceDeviceRGB, destRect, tileRect); // Draw the bottom right corner. tileRect = FloatRect(shadowTemplateSize.width() - twiceRadius - radii.bottomRight().width(), shadowTemplateSize.height() - twiceRadius - radii.bottomRight().height(), twiceRadius + radii.bottomRight().width(), twiceRadius + radii.bottomRight().height()); destRect = tileRect; destRect.move(shadowRect.x() + shadowedRect.width() - shadowTemplateSize.width() + twiceRadius, shadowRect.y() + shadowedRect.height() - shadowTemplateSize.height() + twiceRadius); graphicsContext->drawImageBuffer(m_layerImage, ColorSpaceDeviceRGB, destRect, tileRect); // Draw the bottom left corner. tileRect = FloatRect(0, shadowTemplateSize.height() - twiceRadius - radii.bottomLeft().height(), twiceRadius + radii.bottomLeft().width(), twiceRadius + radii.bottomLeft().height()); destRect = tileRect; destRect.move(shadowRect.x(), shadowRect.y() + shadowedRect.height() - shadowTemplateSize.height() + twiceRadius); graphicsContext->drawImageBuffer(m_layerImage, ColorSpaceDeviceRGB, destRect, tileRect); m_layerImage = 0; // Schedule a purge of the scratch buffer. ScratchBuffer::shared().scheduleScratchBufferPurge(); }
void ShadowBlur::drawInsetShadow(GraphicsContext* graphicsContext, const FloatRect& rect, const FloatRect& holeRect, const RoundedIntRect::Radii& holeRadii) { // FIXME: add a tiling code path here. IntRect layerRect = calculateLayerBoundingRect(graphicsContext, rect, graphicsContext->clipBounds()); GraphicsContext* shadowContext = beginShadowLayer(graphicsContext, layerRect); if (!shadowContext) return; Path path; path.addRect(rect); path.addRoundedRect(holeRect, holeRadii.topLeft(), holeRadii.topRight(), holeRadii.bottomLeft(), holeRadii.bottomRight()); shadowContext->setFillRule(RULE_EVENODD); shadowContext->setFillColor(Color::black, ColorSpaceDeviceRGB); shadowContext->fillPath(path); endShadowLayer(graphicsContext); }