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; }
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(); }