InlineFlowBoxPainter::BorderPaintingType InlineFlowBoxPainter::getBorderPaintType(const LayoutRect& adjustedFrameRect, IntRect& adjustedClipRect) const
{
    adjustedClipRect = pixelSnappedIntRect(adjustedFrameRect);
    if (m_inlineFlowBox.parent() && m_inlineFlowBox.lineLayoutItem().style()->hasBorderDecoration()) {
        const NinePieceImage& borderImage = m_inlineFlowBox.lineLayoutItem().style()->borderImage();
        StyleImage* borderImageSource = borderImage.image();
        bool hasBorderImage = borderImageSource && borderImageSource->canRender();
        if (hasBorderImage && !borderImageSource->isLoaded())
            return DontPaintBorders;

        // The simple case is where we either have no border image or we are the only box for this object.
        // In those cases only a single call to draw is required.
        if (!hasBorderImage || (!m_inlineFlowBox.prevLineBox() && !m_inlineFlowBox.nextLineBox()))
            return PaintBordersWithoutClip;

        // We have a border image that spans multiple lines.
        adjustedClipRect = pixelSnappedIntRect(clipRectForNinePieceImageStrip(m_inlineFlowBox, borderImage, adjustedFrameRect));
        return PaintBordersWithClip;
    }
    return DontPaintBorders;
}
Beispiel #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);
    }
}
Image* FixedBackgroundImageLayerAndroid::GetCachedImage(PassRefPtr<RenderStyle> aStyle)
{
    RefPtr<RenderStyle> style = aStyle;
    if (!style)
        return 0;

    if (!style->hasFixedBackgroundImage())
        return 0;

    FillLayer* layers = style->accessBackgroundLayers();
    StyleImage* styleImage = layers->image();

    if (!styleImage)
        return 0;

    if (!styleImage->isLoaded())
        return 0;

    if (!styleImage->isCachedImage())
        return 0;

    CachedImage* cachedImage = static_cast<StyleCachedImage*>(styleImage)->cachedImage();

    Image* image = cachedImage->image();
    bool willPaintBrokenImage = cachedImage->willPaintBrokenImage();   //SAMSUNG_CHANGES -- MPSG6322 & MPSG6356

    if (image && !image->nativeImageForCurrentFrame())
        return 0;

    //SAMSUNG_CHANGES -- MPSG6322 & MPSG6356
    //WAS: if (image == Image::nullImage())
    if (image == Image::nullImage() || willPaintBrokenImage)
        return 0;

    return image;
}
void InlineFlowBoxPainter::paintMask(const PaintInfo& paintInfo, const LayoutPoint& paintOffset)
{
    if (m_inlineFlowBox.lineLayoutItem().style()->visibility() != VISIBLE || paintInfo.phase != PaintPhaseMask)
        return;

    LayoutRect frameRect = frameRectClampedToLineTopAndBottomIfNeeded();

    // Move x/y to our coordinates.
    LayoutRect localRect(frameRect);
    m_inlineFlowBox.flipForWritingMode(localRect);
    LayoutPoint adjustedPaintOffset = paintOffset + localRect.location();

    const NinePieceImage& maskNinePieceImage = m_inlineFlowBox.lineLayoutItem().style()->maskBoxImage();
    StyleImage* maskBoxImage = m_inlineFlowBox.lineLayoutItem().style()->maskBoxImage().image();

    // Figure out if we need to push a transparency layer to render our mask.
    bool pushTransparencyLayer = false;
    bool compositedMask = m_inlineFlowBox.lineLayoutItem().hasLayer() && m_inlineFlowBox.boxModelObject().layer()->hasCompositedMask();
    bool flattenCompositingLayers = paintInfo.globalPaintFlags() & GlobalPaintFlattenCompositingLayers;
    SkXfermode::Mode compositeOp = SkXfermode::kSrcOver_Mode;
    if (!compositedMask || flattenCompositingLayers) {
        if ((maskBoxImage && m_inlineFlowBox.lineLayoutItem().style()->maskLayers().hasImage()) || m_inlineFlowBox.lineLayoutItem().style()->maskLayers().next()) {
            pushTransparencyLayer = true;
            paintInfo.context.beginLayer(1.0f, SkXfermode::kDstIn_Mode);
        } else {
            // TODO(fmalita): passing a dst-in xfer mode down to paintFillLayers/paintNinePieceImage
            //   seems dangerous: it is only correct if applied atomically (single draw call). While
            //   the heuristic above presumably ensures that is the case, this approach seems super
            //   fragile. We should investigate dropping this optimization in favour of the more
            //   robust layer branch above.
            compositeOp = SkXfermode::kDstIn_Mode;
        }
    }

    LayoutRect paintRect = LayoutRect(adjustedPaintOffset, frameRect.size());
    paintFillLayers(paintInfo, Color::transparent, m_inlineFlowBox.lineLayoutItem().style()->maskLayers(), paintRect, compositeOp);

    bool hasBoxImage = maskBoxImage && maskBoxImage->canRender();
    if (!hasBoxImage || !maskBoxImage->isLoaded()) {
        if (pushTransparencyLayer)
            paintInfo.context.endLayer();
        return; // Don't paint anything while we wait for the image to load.
    }

    LayoutBoxModelObject* boxModel = toLayoutBoxModelObject(LineLayoutAPIShim::layoutObjectFrom(m_inlineFlowBox.boxModelObject()));
    // The simple case is where we are the only box for this object. In those
    // cases only a single call to draw is required.
    if (!m_inlineFlowBox.prevLineBox() && !m_inlineFlowBox.nextLineBox()) {
        BoxPainter::paintNinePieceImage(*boxModel, paintInfo.context, paintRect, m_inlineFlowBox.lineLayoutItem().styleRef(), maskNinePieceImage, compositeOp);
    } else {
        // We have a mask image that spans multiple lines.
        // FIXME: What the heck do we do with RTL here? The math we're using is obviously not right,
        // but it isn't even clear how this should work at all.
        LayoutRect imageStripPaintRect = paintRectForImageStrip(adjustedPaintOffset, frameRect.size(), LTR);
        FloatRect clipRect(clipRectForNinePieceImageStrip(m_inlineFlowBox, maskNinePieceImage, paintRect));
        GraphicsContextStateSaver stateSaver(paintInfo.context);
        // TODO(chrishtr): this should be pixel-snapped.
        paintInfo.context.clip(clipRect);
        BoxPainter::paintNinePieceImage(*boxModel, paintInfo.context, imageStripPaintRect, m_inlineFlowBox.lineLayoutItem().styleRef(), maskNinePieceImage, compositeOp);
    }

    if (pushTransparencyLayer)
        paintInfo.context.endLayer();
}