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;
    }
}
예제 #2
0
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);
    }
}