void InlineFlowBoxPainter::paintFillLayer(const PaintInfo& paintInfo, const Color& c, const FillLayer& fillLayer, const LayoutRect& rect, SkXfermode::Mode op) { StyleImage* img = fillLayer.image(); bool hasFillImage = img && img->canRender(m_inlineFlowBox.layoutObject(), m_inlineFlowBox.layoutObject().style()->effectiveZoom()); if ((!hasFillImage && !m_inlineFlowBox.layoutObject().style()->hasBorderRadius()) || (!m_inlineFlowBox.prevLineBox() && !m_inlineFlowBox.nextLineBox()) || !m_inlineFlowBox.parent()) { BoxPainter::paintFillLayerExtended(*m_inlineFlowBox.boxModelObject(), paintInfo, c, fillLayer, rect, BackgroundBleedNone, &m_inlineFlowBox, rect.size(), op); } else if (m_inlineFlowBox.layoutObject().style()->boxDecorationBreak() == DCLONE) { GraphicsContextStateSaver stateSaver(*paintInfo.context); paintInfo.context->clip(LayoutRect(rect.x(), rect.y(), m_inlineFlowBox.width(), m_inlineFlowBox.height())); BoxPainter::paintFillLayerExtended(*m_inlineFlowBox.boxModelObject(), paintInfo, c, fillLayer, rect, BackgroundBleedNone, &m_inlineFlowBox, rect.size(), op); } else { // We have a fill image that spans multiple lines. // FIXME: frameSize ought to be the same as rect.size(). LayoutSize frameSize(m_inlineFlowBox.width().toLayoutUnit(), m_inlineFlowBox.height().toLayoutUnit()); LayoutRect imageStripPaintRect = paintRectForImageStrip(rect.location(), frameSize, m_inlineFlowBox.layoutObject().style()->direction()); GraphicsContextStateSaver stateSaver(*paintInfo.context); paintInfo.context->clip(LayoutRect(rect.x(), rect.y(), m_inlineFlowBox.width(), m_inlineFlowBox.height())); BoxPainter::paintFillLayerExtended(*m_inlineFlowBox.boxModelObject(), paintInfo, c, fillLayer, imageStripPaintRect, BackgroundBleedNone, &m_inlineFlowBox, rect.size(), op); } }
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 InlineFlowBoxPainter::paintFillLayer(const PaintInfo& paintInfo, const Color& c, const FillLayer& fillLayer, const LayoutRect& rect, SkXfermode::Mode op) { LayoutBoxModelObject* boxModel = toLayoutBoxModelObject(LineLayoutAPIShim::layoutObjectFrom(m_inlineFlowBox.boxModelObject())); StyleImage* img = fillLayer.image(); bool hasFillImage = img && img->canRender(); if ((!hasFillImage && !m_inlineFlowBox.lineLayoutItem().style()->hasBorderRadius()) || (!m_inlineFlowBox.prevLineBox() && !m_inlineFlowBox.nextLineBox()) || !m_inlineFlowBox.parent()) { BoxPainter::paintFillLayer(*boxModel, paintInfo, c, fillLayer, rect, BackgroundBleedNone, &m_inlineFlowBox, rect.size(), op); } else if (m_inlineFlowBox.lineLayoutItem().style()->boxDecorationBreak() == DCLONE) { GraphicsContextStateSaver stateSaver(paintInfo.context); paintInfo.context.clip(pixelSnappedIntRect(rect)); BoxPainter::paintFillLayer(*boxModel, paintInfo, c, fillLayer, rect, BackgroundBleedNone, &m_inlineFlowBox, rect.size(), op); } else { // We have a fill image that spans multiple lines. // FIXME: frameSize ought to be the same as rect.size(). LayoutSize frameSize(m_inlineFlowBox.width(), m_inlineFlowBox.height()); LayoutRect imageStripPaintRect = paintRectForImageStrip(rect.location(), frameSize, m_inlineFlowBox.lineLayoutItem().style()->direction()); GraphicsContextStateSaver stateSaver(paintInfo.context); // TODO(chrishtr): this should likely be pixel-snapped. paintInfo.context.clip(pixelSnappedIntRect(rect)); BoxPainter::paintFillLayer(*boxModel, paintInfo, c, fillLayer, imageStripPaintRect, BackgroundBleedNone, &m_inlineFlowBox, rect.size(), op); } }
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(); }