NinePieceImageGrid::NinePieceImageGrid(const NinePieceImage& ninePieceImage, IntSize imageSize, IntRect borderImageArea, const IntRectOutsets& borderWidths) : m_borderImageArea(borderImageArea) , m_imageSize(imageSize) , m_horizontalTileRule((Image::TileRule)ninePieceImage.horizontalRule()) , m_verticalTileRule((Image::TileRule)ninePieceImage.verticalRule()) , m_fill(ninePieceImage.fill()) { StyleImage* styleImage = ninePieceImage.image(); ASSERT(styleImage); float imageScaleFactor = styleImage->imageScaleFactor(); m_top.slice = computeEdgeSlice(ninePieceImage.imageSlices().top(), imageSize.height()) * imageScaleFactor; m_right.slice = computeEdgeSlice(ninePieceImage.imageSlices().right(), imageSize.width()) * imageScaleFactor; m_bottom.slice = computeEdgeSlice(ninePieceImage.imageSlices().bottom(), imageSize.height()) * imageScaleFactor; m_left.slice = computeEdgeSlice(ninePieceImage.imageSlices().left(), imageSize.width()) * imageScaleFactor; m_top.width = computeEdgeWidth(ninePieceImage.borderSlices().top(), borderWidths.top(), m_top.slice, borderImageArea.height()); m_right.width = computeEdgeWidth(ninePieceImage.borderSlices().right(), borderWidths.right(), m_right.slice, borderImageArea.width()); m_bottom.width = computeEdgeWidth(ninePieceImage.borderSlices().bottom(), borderWidths.bottom(), m_bottom.slice, borderImageArea.height()); m_left.width = computeEdgeWidth(ninePieceImage.borderSlices().left(), borderWidths.left(), m_left.slice, borderImageArea.width()); // The spec says: Given Lwidth as the width of the border image area, Lheight as its height, and Wside as the border // image width offset for the side, let f = min(Lwidth/(Wleft+Wright), Lheight/(Wtop+Wbottom)). If f < 1, then all W // are reduced by multiplying them by f. int borderSideWidth = std::max(1, m_left.width + m_right.width); int borderSideHeight = std::max(1, m_top.width + m_bottom.width); float borderSideScaleFactor = std::min((float)borderImageArea.width() / borderSideWidth, (float)borderImageArea.height() / borderSideHeight); if (borderSideScaleFactor < 1) { m_top.width *= borderSideScaleFactor; m_right.width *= borderSideScaleFactor; m_bottom.width *= borderSideScaleFactor; m_left.width *= borderSideScaleFactor; } }
void NinePieceImage::paint(GraphicsContext* graphicsContext, RenderElement* renderer, const RenderStyle& style, const LayoutRect& destination, const LayoutSize& source, bool intrinsicSource, float deviceScaleFactor, CompositeOperator op) const { StyleImage* styleImage = image(); ASSERT(styleImage && styleImage->isLoaded()); LayoutBoxExtent sourceSlices = computeSlices(source, imageSlices(), styleImage->imageScaleFactor()); LayoutBoxExtent destinationSlices = computeSlices(destination.size(), borderSlices(), style.borderWidth(), sourceSlices); scaleSlicesIfNeeded(destination.size(), destinationSlices, deviceScaleFactor); Vector<FloatRect> destinationRects = computeIntrinsicRects(destination, destinationSlices, deviceScaleFactor); Vector<FloatRect> sourceRects; Vector<FloatSize> tileScales; if (intrinsicSource) { sourceRects = computeIntrinsicRects(FloatRect(FloatPoint(), source), sourceSlices, deviceScaleFactor); tileScales = computeIntrinsicTileScales(destinationRects, sourceRects, horizontalRule(), verticalRule()); } else { sourceRects = computeNonIntrinsicRects(destinationRects, sourceSlices); tileScales = computeNonIntrinsicTileScales(); } RefPtr<Image> image = styleImage->image(renderer, source); ColorSpace colorSpace = style.colorSpace(); for (ImagePiece piece = MinPiece; piece < MaxPiece; ++piece) { if ((piece == MiddlePiece && !fill()) || isEmptyPieceRect(piece, destinationRects, sourceRects)) continue; if (isCornerPiece(piece)) { graphicsContext->drawImage(image.get(), colorSpace, destinationRects[piece], sourceRects[piece], op); continue; } Image::TileRule hRule = isHorizontalPiece(piece) ? static_cast<Image::TileRule>(horizontalRule()) : Image::StretchTile; Image::TileRule vRule = isVerticalPiece(piece) ? static_cast<Image::TileRule>(verticalRule()) : Image::StretchTile; graphicsContext->drawTiledImage(image.get(), colorSpace, destinationRects[piece], sourceRects[piece], tileScales[piece], hRule, vRule, op); } }