Exemplo n.º 1
0
void ImagePainter::paintAreaElementFocusRing(const PaintInfo& paintInfo,
                                             const LayoutPoint& paintOffset) {
  Document& document = m_layoutImage.document();

  if (paintInfo.isPrinting() ||
      !document.frame()->selection().isFocusedAndActive())
    return;

  Element* focusedElement = document.focusedElement();
  if (!isHTMLAreaElement(focusedElement))
    return;

  HTMLAreaElement& areaElement = toHTMLAreaElement(*focusedElement);
  if (areaElement.imageElement() != m_layoutImage.node())
    return;

  // Even if the theme handles focus ring drawing for entire elements, it won't
  // do it for an area within an image, so we don't call
  // LayoutTheme::themeDrawsFocusRing here.

  const ComputedStyle& areaElementStyle = *areaElement.ensureComputedStyle();
  // If the outline width is 0 we want to avoid drawing anything even if we
  // don't use the value directly.
  if (!areaElementStyle.outlineWidth())
    return;

  Path path = areaElement.getPath(&m_layoutImage);
  if (path.isEmpty())
    return;

  LayoutPoint adjustedPaintOffset = paintOffset;
  adjustedPaintOffset.moveBy(m_layoutImage.location());
  path.translate(FloatSize(adjustedPaintOffset.x(), adjustedPaintOffset.y()));

  if (LayoutObjectDrawingRecorder::useCachedDrawingIfPossible(
          paintInfo.context, m_layoutImage, DisplayItem::kImageAreaFocusRing))
    return;

  LayoutRect focusRect = m_layoutImage.contentBoxRect();
  focusRect.moveBy(adjustedPaintOffset);
  LayoutObjectDrawingRecorder drawingRecorder(paintInfo.context, m_layoutImage,
                                              DisplayItem::kImageAreaFocusRing,
                                              focusRect);

  // FIXME: Clip path instead of context when Skia pathops is ready.
  // https://crbug.com/251206

  paintInfo.context.save();
  paintInfo.context.clip(pixelSnappedIntRect(focusRect));
  paintInfo.context.drawFocusRing(
      path, areaElementStyle.getOutlineStrokeWidthForFocusRing(),
      areaElementStyle.outlineOffset(),
      m_layoutImage.resolveColor(areaElementStyle, CSSPropertyOutlineColor));
  paintInfo.context.restore();
}
Exemplo n.º 2
0
void ImagePainter::paintReplaced(const PaintInfo& paintInfo, const LayoutPoint& paintOffset)
{
    LayoutUnit cWidth = m_layoutImage.contentWidth();
    LayoutUnit cHeight = m_layoutImage.contentHeight();

    GraphicsContext* context = paintInfo.context;

    if (!m_layoutImage.imageResource()->hasImage()) {
        if (paintInfo.phase == PaintPhaseSelection)
            return;
        if (cWidth > 2 && cHeight > 2) {
            if (LayoutObjectDrawingRecorder::useCachedDrawingIfPossible(*context, m_layoutImage, paintInfo.phase))
                return;
            // Draw an outline rect where the image should be.
            IntRect paintRect = pixelSnappedIntRect(LayoutRect(paintOffset.x() + m_layoutImage.borderLeft() + m_layoutImage.paddingLeft(), paintOffset.y() + m_layoutImage.borderTop() + m_layoutImage.paddingTop(), cWidth, cHeight));
            LayoutObjectDrawingRecorder drawingRecorder(*context, m_layoutImage, paintInfo.phase, paintRect);
            context->setStrokeStyle(SolidStroke);
            context->setStrokeColor(Color::lightGray);
            context->setFillColor(Color::transparent);
            context->drawRect(paintRect);
        }
    } else if (cWidth > 0 && cHeight > 0) {
        if (LayoutObjectDrawingRecorder::useCachedDrawingIfPossible(*context, m_layoutImage, paintInfo.phase))
            return;
        LayoutRect contentRect = m_layoutImage.contentBoxRect();
        contentRect.moveBy(paintOffset);
        LayoutRect paintRect = m_layoutImage.replacedContentRect();
        paintRect.moveBy(paintOffset);

        LayoutObjectDrawingRecorder drawingRecorder(*context, m_layoutImage, paintInfo.phase, contentRect);
        bool clip = !contentRect.contains(paintRect);
        if (clip) {
            context->save();
            context->clip(contentRect);
        }

        paintIntoRect(context, paintRect);

        if (clip)
            context->restore();
    }
}
void PartPainter::paint(const PaintInfo& paintInfo, const LayoutPoint& paintOffset)
{
    if (!m_layoutPart.shouldPaint(paintInfo, paintOffset))
        return;

    LayoutPoint adjustedPaintOffset = paintOffset + m_layoutPart.location();
    LayoutRect borderRect(adjustedPaintOffset, m_layoutPart.size());

    if (m_layoutPart.hasBoxDecorationBackground() && (paintInfo.phase == PaintPhaseForeground || paintInfo.phase == PaintPhaseSelection))
        BoxPainter(m_layoutPart).paintBoxDecorationBackground(paintInfo, adjustedPaintOffset);

    if (paintInfo.phase == PaintPhaseMask) {
        BoxPainter(m_layoutPart).paintMask(paintInfo, adjustedPaintOffset);
        return;
    }

    if ((paintInfo.phase == PaintPhaseOutline || paintInfo.phase == PaintPhaseSelfOutline) && m_layoutPart.style()->hasOutline())
        ObjectPainter(m_layoutPart).paintOutline(paintInfo, adjustedPaintOffset);

    if (paintInfo.phase != PaintPhaseForeground)
        return;

    {
        Optional<RoundedInnerRectClipper> clipper;
        if (m_layoutPart.style()->hasBorderRadius()) {
            if (borderRect.isEmpty())
                return;

            FloatRoundedRect roundedInnerRect = m_layoutPart.style()->getRoundedInnerBorderFor(borderRect,
                LayoutRectOutsets(
                    -(m_layoutPart.paddingTop() + m_layoutPart.borderTop()),
                    -(m_layoutPart.paddingRight() + m_layoutPart.borderRight()),
                    -(m_layoutPart.paddingBottom() + m_layoutPart.borderBottom()),
                    -(m_layoutPart.paddingLeft() + m_layoutPart.borderLeft())),
                true, true);
            clipper.emplace(m_layoutPart, paintInfo, borderRect, roundedInnerRect, ApplyToDisplayList);
        }

        if (m_layoutPart.widget())
            m_layoutPart.paintContents(paintInfo, paintOffset);
    }

    // Paint a partially transparent wash over selected widgets.
    if (isSelected() && !paintInfo.isPrinting() && !LayoutObjectDrawingRecorder::useCachedDrawingIfPossible(*paintInfo.context, m_layoutPart, paintInfo.phase, adjustedPaintOffset)) {
        LayoutRect rect = m_layoutPart.localSelectionRect();
        rect.moveBy(adjustedPaintOffset);
        IntRect selectionRect = pixelSnappedIntRect(rect);
        LayoutObjectDrawingRecorder drawingRecorder(*paintInfo.context, m_layoutPart, paintInfo.phase, selectionRect, adjustedPaintOffset);
        paintInfo.context->fillRect(selectionRect, m_layoutPart.selectionBackgroundColor());
    }

    if (m_layoutPart.canResize())
        ScrollableAreaPainter(*m_layoutPart.layer()->scrollableArea()).paintResizer(paintInfo.context, roundedIntPoint(adjustedPaintOffset), paintInfo.cullRect());
}
Exemplo n.º 4
0
void EmbeddedObjectPainter::paintReplaced(const PaintInfo& paintInfo,
                                          const LayoutPoint& paintOffset) {
  if (!m_layoutEmbeddedObject.showsUnavailablePluginIndicator())
    return;

  if (paintInfo.phase == PaintPhaseSelection)
    return;

  GraphicsContext& context = paintInfo.context;
  if (LayoutObjectDrawingRecorder::useCachedDrawingIfPossible(
          context, m_layoutEmbeddedObject, paintInfo.phase))
    return;

  LayoutRect contentRect(m_layoutEmbeddedObject.contentBoxRect());
  contentRect.moveBy(paintOffset);
  LayoutObjectDrawingRecorder drawingRecorder(context, m_layoutEmbeddedObject,
                                              paintInfo.phase, contentRect);
  GraphicsContextStateSaver stateSaver(context);
  context.clip(pixelSnappedIntRect(contentRect));

  Font font = replacementTextFont();
  const SimpleFontData* fontData = font.primaryFont();
  DCHECK(fontData);
  if (!fontData)
    return;

  TextRun textRun(m_layoutEmbeddedObject.unavailablePluginReplacementText());
  FloatSize textGeometry(font.width(textRun),
                         fontData->getFontMetrics().height());

  LayoutRect backgroundRect(
      0, 0,
      textGeometry.width() + 2 * replacementTextRoundedRectLeftRightTextMargin,
      replacementTextRoundedRectHeight);
  backgroundRect.move(contentRect.center() - backgroundRect.center());
  backgroundRect = LayoutRect(pixelSnappedIntRect(backgroundRect));
  Path roundedBackgroundRect;
  FloatRect floatBackgroundRect(backgroundRect);
  roundedBackgroundRect.addRoundedRect(
      floatBackgroundRect, FloatSize(replacementTextRoundedRectRadius,
                                     replacementTextRoundedRectRadius));
  context.setFillColor(
      scaleAlpha(Color::white, replacementTextRoundedRectOpacity));
  context.fillPath(roundedBackgroundRect);

  FloatRect textRect(FloatPoint(), textGeometry);
  textRect.move(FloatPoint(contentRect.center()) - textRect.center());
  TextRunPaintInfo runInfo(textRun);
  runInfo.bounds = floatBackgroundRect;
  context.setFillColor(scaleAlpha(Color::black, replacementTextTextOpacity));
  context.drawBidiText(
      font, runInfo,
      textRect.location() + FloatSize(0, fontData->getFontMetrics().ascent()));
}
Exemplo n.º 5
0
void ImagePainter::paintReplaced(const PaintInfo& paintInfo, const LayoutPoint& paintOffset)
{
    LayoutUnit cWidth = m_layoutImage.contentWidth();
    LayoutUnit cHeight = m_layoutImage.contentHeight();

    GraphicsContext* context = paintInfo.context;

    if (!m_layoutImage.imageResource()->hasImage()) {
        if (paintInfo.phase == PaintPhaseSelection)
            return;
        if (cWidth > 2 && cHeight > 2) {
            if (LayoutObjectDrawingRecorder::useCachedDrawingIfPossible(*context, m_layoutImage, paintInfo.phase, paintOffset))
                return;
            // Draw an outline rect where the image should be.
            IntRect paintRect = pixelSnappedIntRect(LayoutRect(paintOffset.x() + m_layoutImage.borderLeft() + m_layoutImage.paddingLeft(), paintOffset.y() + m_layoutImage.borderTop() + m_layoutImage.paddingTop(), cWidth, cHeight));
            LayoutObjectDrawingRecorder drawingRecorder(*context, m_layoutImage, paintInfo.phase, paintRect, paintOffset);
            context->setStrokeStyle(SolidStroke);
            context->setStrokeColor(Color::lightGray);
            context->setFillColor(Color::transparent);
            context->drawRect(paintRect);
        }
    } else if (cWidth > 0 && cHeight > 0) {
        LayoutRect contentRect = m_layoutImage.contentBoxRect();
        contentRect.moveBy(paintOffset);
        LayoutRect paintRect = m_layoutImage.replacedContentRect();
        paintRect.moveBy(paintOffset);

        Optional<ClipRecorder> clipRecorder;
        if (!contentRect.contains(paintRect)) {
            // TODO(fmalita): can we get rid of this clip and adjust the image src/dst rect instead?
            clipRecorder.emplace(*context, m_layoutImage, paintInfo.displayItemTypeForClipping(), contentRect);
        }

        if (LayoutObjectDrawingRecorder::useCachedDrawingIfPossible(*context, m_layoutImage, paintInfo.phase, paintOffset))
            return;

        LayoutObjectDrawingRecorder drawingRecorder(*context, m_layoutImage, paintInfo.phase, contentRect, paintOffset);
        paintIntoRect(context, paintRect);
    }
}
Exemplo n.º 6
0
void FramePainter::paintScrollCorner(GraphicsContext* context, const IntRect& cornerRect)
{
    if (m_frameView.scrollCorner()) {
        bool needsBackground = m_frameView.frame().isMainFrame();
        if (needsBackground) {
            DrawingRecorder drawingRecorder(*context, *m_frameView.layoutView(), DisplayItem::ScrollbarCorner, cornerRect);
            if (!drawingRecorder.canUseCachedDrawing())
                context->fillRect(cornerRect, m_frameView.baseBackgroundColor());
        }
        ScrollbarPainter::paintIntoRect(m_frameView.scrollCorner(), context, cornerRect.location(), LayoutRect(cornerRect));
        return;
    }

    ScrollbarTheme::theme()->paintScrollCorner(context, m_frameView, cornerRect);
}
Exemplo n.º 7
0
void FramePainter::paintScrollCorner(GraphicsContext& context, const IntRect& cornerRect)
{
    if (frameView().scrollCorner()) {
        bool needsBackground = frameView().frame().isMainFrame();
        if (needsBackground && !LayoutObjectDrawingRecorder::useCachedDrawingIfPossible(context, *frameView().layoutView(), DisplayItem::ScrollbarCorner, LayoutPoint())) {
            LayoutObjectDrawingRecorder drawingRecorder(context, *frameView().layoutView(), DisplayItem::ScrollbarCorner, FloatRect(cornerRect), LayoutPoint());
            context.fillRect(cornerRect, frameView().baseBackgroundColor());

        }
        ScrollbarPainter::paintIntoRect(*frameView().scrollCorner(), context, cornerRect.location(), LayoutRect(cornerRect));
        return;
    }

    ScrollbarTheme::theme().paintScrollCorner(context, *frameView().layoutView(), cornerRect);
}
Exemplo n.º 8
0
bool SVGClipPainter::drawClipAsMask(
    GraphicsContext& context,
    const LayoutObject& layoutObject,
    const FloatRect& targetBoundingBox,
    const FloatRect& targetPaintInvalidationRect,
    const AffineTransform& localTransform,
    const FloatPoint& layerPositionOffset) {
  if (LayoutObjectDrawingRecorder::useCachedDrawingIfPossible(
          context, layoutObject, DisplayItem::kSVGClip))
    return true;

  SkPictureBuilder maskPictureBuilder(targetPaintInvalidationRect, nullptr,
                                      &context);
  GraphicsContext& maskContext = maskPictureBuilder.context();
  {
    TransformRecorder recorder(maskContext, layoutObject, localTransform);

    // Apply any clip-path clipping this clipPath (nested shape/clipPath.)
    Optional<ClipPathClipper> nestedClipPathClipper;
    if (ClipPathOperation* clipPathOperation = m_clip.styleRef().clipPath())
      nestedClipPathClipper.emplace(maskContext, *clipPathOperation, m_clip,
                                    targetBoundingBox, layerPositionOffset);

    {
      AffineTransform contentTransform;
      if (m_clip.clipPathUnits() ==
          SVGUnitTypes::kSvgUnitTypeObjectboundingbox) {
        contentTransform.translate(targetBoundingBox.x(),
                                   targetBoundingBox.y());
        contentTransform.scaleNonUniform(targetBoundingBox.width(),
                                         targetBoundingBox.height());
      }
      SubtreeContentTransformScope contentTransformScope(contentTransform);

      TransformRecorder contentTransformRecorder(maskContext, layoutObject,
                                                 contentTransform);
      maskContext.getPaintController().createAndAppend<DrawingDisplayItem>(
          layoutObject, DisplayItem::kSVGClip, m_clip.createContentPicture());
    }
  }

  LayoutObjectDrawingRecorder drawingRecorder(context, layoutObject,
                                              DisplayItem::kSVGClip,
                                              targetPaintInvalidationRect);
  sk_sp<SkPicture> maskPicture = maskPictureBuilder.endRecording();
  context.drawPicture(maskPicture.get());
  return true;
}
Exemplo n.º 9
0
void SVGClipPainter::drawClipMaskContent(GraphicsContext* context, const LayoutObject& layoutObject, const FloatRect& targetBoundingBox, const FloatRect& targetPaintInvalidationRect)
{
    ASSERT(context);

    AffineTransform contentTransformation;
    RefPtr<const SkPicture> clipContentPicture = m_clip.createContentPicture(contentTransformation, targetBoundingBox, context);

    if (LayoutObjectDrawingRecorder::useCachedDrawingIfPossible(*context, layoutObject, DisplayItem::SVGClip, LayoutPoint()))
        return;

    LayoutObjectDrawingRecorder drawingRecorder(*context, layoutObject, DisplayItem::SVGClip, targetPaintInvalidationRect, LayoutPoint());
    context->save();
    context->concatCTM(contentTransformation);
    context->drawPicture(clipContentPicture.get());
    context->restore();
}
Exemplo n.º 10
0
void ImagePainter::paintAreaElementFocusRing(const PaintInfo& paintInfo, const LayoutPoint& paintOffset)
{
    // TODO(wangxianzhu): In other places, we just paint focus ring if outline style is auto.
    // We should also do that here to keep consistency.
    Document& document = m_layoutImage.document();

    if (paintInfo.isPrinting() || !document.frame()->selection().isFocusedAndActive())
        return;

    Element* focusedElement = document.focusedElement();
    if (!isHTMLAreaElement(focusedElement))
        return;

    HTMLAreaElement& areaElement = toHTMLAreaElement(*focusedElement);
    if (areaElement.imageElement() != m_layoutImage.node())
        return;

    // Even if the theme handles focus ring drawing for entire elements, it won't do it for
    // an area within an image, so we don't call LayoutTheme::themeDrawsFocusRing here.

    Path path = areaElement.computePath(&m_layoutImage);
    if (path.isEmpty())
        return;

    const ComputedStyle& areaElementStyle = *areaElement.ensureComputedStyle();
    int outlineWidth = areaElementStyle.outlineWidth();
    if (!outlineWidth)
        return;

    if (LayoutObjectDrawingRecorder::useCachedDrawingIfPossible(*paintInfo.context, m_layoutImage, paintInfo.phase, paintOffset))
        return;

    IntRect focusRect = m_layoutImage.absoluteContentBox();
    LayoutObjectDrawingRecorder drawingRecorder(*paintInfo.context, m_layoutImage, paintInfo.phase, focusRect, paintOffset);

    // FIXME: Clip path instead of context when Skia pathops is ready.
    // https://crbug.com/251206

    paintInfo.context->save();
    paintInfo.context->clip(focusRect);
    paintInfo.context->drawFocusRing(path, outlineWidth,
                                     areaElementStyle.outlineOffset(),
                                     m_layoutImage.resolveColor(areaElementStyle, CSSPropertyOutlineColor));
    paintInfo.context->restore();
}
Exemplo n.º 11
0
void CaretBase::paintCaret(Node* node,
                           GraphicsContext& context,
                           const LayoutPoint& paintOffset,
                           DisplayItem::Type displayItemType) const {
    if (DrawingRecorder::useCachedDrawingIfPossible(context, *this,
            displayItemType))
        return;

    LayoutRect drawingRect = localCaretRectWithoutUpdate();
    if (LayoutBlock* layoutObject = caretLayoutObject(node))
        layoutObject->flipForWritingMode(drawingRect);
    drawingRect.moveBy(paintOffset);

    const Color caretColor = node->layoutObject()->resolveColor(CSSPropertyColor);
    IntRect paintRect = pixelSnappedIntRect(drawingRect);
    DrawingRecorder drawingRecorder(context, *this, DisplayItem::kCaret,
                                    paintRect);
    context.fillRect(paintRect, caretColor);
}
Exemplo n.º 12
0
void ImagePainter::paintAreaElementFocusRing(const PaintInfo& paintInfo)
{
    Document& document = m_layoutImage.document();

    if (document.printing() || !document.frame()->selection().isFocusedAndActive())
        return;

    Element* focusedElement = document.focusedElement();
    if (!isHTMLAreaElement(focusedElement))
        return;

    HTMLAreaElement& areaElement = toHTMLAreaElement(*focusedElement);
    if (areaElement.imageElement() != m_layoutImage.node())
        return;

    // Even if the theme handles focus ring drawing for entire elements, it won't do it for
    // an area within an image, so we don't call LayoutTheme::supportsFocusRing here.

    Path path = areaElement.computePath(&m_layoutImage);
    if (path.isEmpty())
        return;

    const ComputedStyle& areaElementStyle = *areaElement.ensureComputedStyle();
    unsigned short outlineWidth = areaElementStyle.outlineWidth();
    if (!outlineWidth)
        return;

    IntRect focusRect = m_layoutImage.absoluteContentBox();

    LayoutObjectDrawingRecorder drawingRecorder(*paintInfo.context, m_layoutImage, paintInfo.phase, focusRect);
    if (drawingRecorder.canUseCachedDrawing())
        return;

    // FIXME: Clip path instead of context when Skia pathops is ready.
    // https://crbug.com/251206

    paintInfo.context->save();
    paintInfo.context->clip(focusRect);
    paintInfo.context->drawFocusRing(path, outlineWidth,
        areaElementStyle.outlineOffset(),
        m_layoutImage.resolveColor(areaElementStyle, CSSPropertyOutlineColor));
    paintInfo.context->restore();
}
bool SVGClipPainter::drawClipAsMask(GraphicsContext& context, const LayoutObject& layoutObject, const FloatRect& targetBoundingBox, const FloatRect& targetPaintInvalidationRect, const AffineTransform& localTransform)
{
    if (LayoutObjectDrawingRecorder::useCachedDrawingIfPossible(context, layoutObject, DisplayItem::SVGClip))
        return true;

    SkPictureBuilder maskPictureBuilder(targetPaintInvalidationRect, nullptr, &context);
    GraphicsContext& maskContext = maskPictureBuilder.context();
    {
        TransformRecorder recorder(maskContext, layoutObject, localTransform);

        // Create a clipPathClipper if this clipPath is clipped by another clipPath.
        SVGResources* resources = SVGResourcesCache::cachedResourcesForLayoutObject(&m_clip);
        LayoutSVGResourceClipper* clipPathClipper = resources ? resources->clipper() : nullptr;
        ClipperState clipPathClipperState = ClipperNotApplied;
        if (clipPathClipper && !SVGClipPainter(*clipPathClipper).prepareEffect(m_clip, targetBoundingBox, targetPaintInvalidationRect, maskContext, clipPathClipperState))
            return false;

        {
            AffineTransform contentTransform;
            if (m_clip.clipPathUnits() == SVGUnitTypes::SVG_UNIT_TYPE_OBJECTBOUNDINGBOX) {
                contentTransform.translate(targetBoundingBox.x(), targetBoundingBox.y());
                contentTransform.scaleNonUniform(targetBoundingBox.width(), targetBoundingBox.height());
            }
            SubtreeContentTransformScope contentTransformScope(contentTransform);

            TransformRecorder contentTransformRecorder(maskContext, layoutObject, contentTransform);
            RefPtr<const SkPicture> clipContentPicture = m_clip.createContentPicture();
            maskContext.getPaintController().createAndAppend<DrawingDisplayItem>(layoutObject, DisplayItem::SVGClip, clipContentPicture.get());
        }

        if (clipPathClipper)
            SVGClipPainter(*clipPathClipper).finishEffect(m_clip, maskContext, clipPathClipperState);
    }

    LayoutObjectDrawingRecorder drawingRecorder(context, layoutObject, DisplayItem::SVGClip, targetPaintInvalidationRect);
    RefPtr<SkPicture> maskPicture = maskPictureBuilder.endRecording();
    context.drawPicture(maskPicture.get());
    return true;
}
Exemplo n.º 14
0
void VideoPainter::paintReplaced(const PaintInfo& paintInfo, const LayoutPoint& paintOffset)
{
    WebMediaPlayer* mediaPlayer = m_layoutVideo.mediaElement()->webMediaPlayer();
    bool displayingPoster = m_layoutVideo.videoElement()->shouldDisplayPosterImage();
    if (!displayingPoster && !mediaPlayer)
        return;

    LayoutRect rect(m_layoutVideo.videoBox());
    if (rect.isEmpty())
        return;
    rect.moveBy(paintOffset);

    GraphicsContext& context = paintInfo.context;
    LayoutRect contentRect = m_layoutVideo.contentBoxRect();
    contentRect.moveBy(paintOffset);

    Optional<ClipRecorder> clipRecorder;
    if (!contentRect.contains(rect)) {
        clipRecorder.emplace(context, m_layoutVideo, paintInfo.displayItemTypeForClipping(), contentRect);
    }

    if (LayoutObjectDrawingRecorder::useCachedDrawingIfPossible(context, m_layoutVideo, paintInfo.phase, paintOffset))
        return;

    LayoutObjectDrawingRecorder drawingRecorder(context, m_layoutVideo, paintInfo.phase, contentRect, paintOffset);

    // Video frames are only painted in software for printing or capturing node images via web APIs.
    bool forceSoftwareVideoPaint = paintInfo.globalPaintFlags() & GlobalPaintFlattenCompositingLayers;

    if (displayingPoster || !forceSoftwareVideoPaint) {
        // This will display the poster image, if one is present, and otherwise paint nothing.
        ImagePainter(m_layoutVideo).paintIntoRect(context, rect);
    } else {
        SkPaint videoPaint = context.fillPaint();
        videoPaint.setColor(SK_ColorBLACK);
        m_layoutVideo.videoElement()->paintCurrentFrame(context.canvas(), pixelSnappedIntRect(rect), &videoPaint);
    }
}
Exemplo n.º 15
0
void VideoPainter::paintReplaced(const PaintInfo& paintInfo, const LayoutPoint& paintOffset)
{
    WebMediaPlayer* mediaPlayer = m_layoutVideo.mediaElement()->webMediaPlayer();
    bool displayingPoster = m_layoutVideo.videoElement()->shouldDisplayPosterImage();
    if (!displayingPoster && !mediaPlayer)
        return;

    LayoutRect rect(m_layoutVideo.videoBox());
    if (rect.isEmpty())
        return;
    rect.moveBy(paintOffset);

    GraphicsContext* context = paintInfo.context;
    if (LayoutObjectDrawingRecorder::useCachedDrawingIfPossible(*context, m_layoutVideo, paintInfo.phase))
        return;

    LayoutRect contentRect = m_layoutVideo.contentBoxRect();
    contentRect.moveBy(paintOffset);
    LayoutObjectDrawingRecorder drawingRecorder(*context, m_layoutVideo, paintInfo.phase, contentRect);

    bool clip = !contentRect.contains(rect);
    if (clip) {
        context->save();
        context->clip(contentRect);
    }

    if (displayingPoster) {
        ImagePainter(m_layoutVideo).paintIntoRect(context, rect);
    } else if ((m_layoutVideo.document().view() && m_layoutVideo.document().view()->paintBehavior() & PaintBehaviorFlattenCompositingLayers) || !m_layoutVideo.acceleratedRenderingInUse()) {
        SkPaint videoPaint = context->fillPaint();
        videoPaint.setColor(SK_ColorBLACK);
        m_layoutVideo.videoElement()->paintCurrentFrame(context->canvas(), pixelSnappedIntRect(rect), &videoPaint);
    }
    if (clip)
        context->restore();
}
Exemplo n.º 16
0
void WebFont::drawText(WebCanvas* canvas, const WebTextRun& run,
    const WebFloatPoint& leftBaseline, WebColor color, const WebRect& clip) const
{
    FontCachePurgePreventer fontCachePurgePreventer;
    FloatRect textClipRect(clip);
    TextRun textRun(run);
    TextRunPaintInfo runInfo(textRun);
    runInfo.bounds = textClipRect;

    IntRect intRect(clip);
    SkPictureBuilder pictureBuilder(intRect);
    GraphicsContext& context = pictureBuilder.context();

    {
        DrawingRecorder drawingRecorder(context, pictureBuilder, DisplayItem::WebFont, intRect);
        context.save();
        context.setFillColor(color);
        context.clip(textClipRect);
        context.drawText(m_private->getFont(), runInfo, leftBaseline);
        context.restore();
    }

    pictureBuilder.endRecording()->playback(canvas);
}
Exemplo n.º 17
0
void ReplacedPainter::paint(const PaintInfo& paintInfo, const LayoutPoint& paintOffset)
{
    if (!m_layoutReplaced.shouldPaint(paintInfo, paintOffset))
        return;

    LayoutPoint adjustedPaintOffset = paintOffset + m_layoutReplaced.location();
    LayoutRect borderRect(adjustedPaintOffset, m_layoutReplaced.size());

    if (m_layoutReplaced.hasBoxDecorationBackground() && (paintInfo.phase == PaintPhaseForeground || paintInfo.phase == PaintPhaseSelection))
        m_layoutReplaced.paintBoxDecorationBackground(paintInfo, adjustedPaintOffset);

    if (paintInfo.phase == PaintPhaseMask) {
        m_layoutReplaced.paintMask(paintInfo, adjustedPaintOffset);
        return;
    }

    if (paintInfo.phase == PaintPhaseClippingMask && (!m_layoutReplaced.hasLayer() || !m_layoutReplaced.layer()->hasCompositedClippingMask()))
        return;

    if (paintInfo.phase == PaintPhaseOutline || paintInfo.phase == PaintPhaseSelfOutline) {
        if (m_layoutReplaced.styleRef().outlineWidth())
            ObjectPainter(m_layoutReplaced).paintOutline(paintInfo, adjustedPaintOffset);
        return;
    }

    if (paintInfo.phase != PaintPhaseForeground && paintInfo.phase != PaintPhaseSelection && !m_layoutReplaced.canHaveChildren() && paintInfo.phase != PaintPhaseClippingMask)
        return;

    if (!paintInfo.shouldPaintWithinRoot(&m_layoutReplaced))
        return;

    if (paintInfo.phase == PaintPhaseSelection)
        if (m_layoutReplaced.selectionState() == SelectionNone)
            return;

    {
        Optional<RoundedInnerRectClipper> clipper;
        bool completelyClippedOut = false;
        if (m_layoutReplaced.style()->hasBorderRadius()) {
            if (borderRect.isEmpty()) {
                completelyClippedOut = true;
            } else if (shouldApplyViewportClip(m_layoutReplaced)) {
                // Push a clip if we have a border radius, since we want to round the foreground content that gets painted.
                FloatRoundedRect roundedInnerRect = m_layoutReplaced.style()->getRoundedInnerBorderFor(borderRect,
                    LayoutRectOutsets(
                        -(m_layoutReplaced.paddingTop() + m_layoutReplaced.borderTop()),
                        -(m_layoutReplaced.paddingRight() + m_layoutReplaced.borderRight()),
                        -(m_layoutReplaced.paddingBottom() + m_layoutReplaced.borderBottom()),
                        -(m_layoutReplaced.paddingLeft() + m_layoutReplaced.borderLeft())),
                    true, true);

                clipper.emplace(m_layoutReplaced, paintInfo, borderRect, roundedInnerRect, ApplyToDisplayList);
            }
        }

        if (!completelyClippedOut) {
            if (paintInfo.phase == PaintPhaseClippingMask) {
                BoxPainter(m_layoutReplaced).paintClippingMask(paintInfo, adjustedPaintOffset);
            } else {
                m_layoutReplaced.paintReplaced(paintInfo, adjustedPaintOffset);
            }
        }
    }

    // The selection tint never gets clipped by border-radius rounding, since we want it to run right up to the edges of
    // surrounding content.
    bool drawSelectionTint = paintInfo.phase == PaintPhaseForeground && m_layoutReplaced.selectionState() != SelectionNone && !paintInfo.isPrinting();
    if (drawSelectionTint && !LayoutObjectDrawingRecorder::useCachedDrawingIfPossible(paintInfo.context, m_layoutReplaced, DisplayItem::SelectionTint, adjustedPaintOffset)) {
        LayoutRect selectionPaintingRect = m_layoutReplaced.localSelectionRect();
        selectionPaintingRect.moveBy(adjustedPaintOffset);
        IntRect selectionPaintingIntRect = pixelSnappedIntRect(selectionPaintingRect);

        LayoutObjectDrawingRecorder drawingRecorder(paintInfo.context, m_layoutReplaced, DisplayItem::SelectionTint, selectionPaintingIntRect, adjustedPaintOffset);
        paintInfo.context.fillRect(selectionPaintingIntRect, m_layoutReplaced.selectionBackgroundColor());
    }
}
Exemplo n.º 18
0
void FramePainter::paintContents(GraphicsContext& context, const GlobalPaintFlags globalPaintFlags, const IntRect& rect)
{
    Document* document = frameView().frame().document();

#ifndef NDEBUG
    bool fillWithRed;
    if (document->printing())
        fillWithRed = false; // Printing, don't fill with red (can't remember why).
    else if (frameView().frame().owner())
        fillWithRed = false; // Subframe, don't fill with red.
    else if (frameView().isTransparent())
        fillWithRed = false; // Transparent, don't fill with red.
    else if (globalPaintFlags & GlobalPaintSelectionOnly)
        fillWithRed = false; // Selections are transparent, don't fill with red.
    else
        fillWithRed = true;

    if (fillWithRed && !LayoutObjectDrawingRecorder::useCachedDrawingIfPossible(context, *frameView().layoutView(), DisplayItem::DebugRedFill, LayoutPoint())) {
        IntRect contentRect(IntPoint(), frameView().contentsSize());
        LayoutObjectDrawingRecorder drawingRecorder(context, *frameView().layoutView(), DisplayItem::DebugRedFill, contentRect, LayoutPoint());
    }
#endif

    LayoutView* layoutView = frameView().layoutView();
    if (!layoutView) {
        WTF_LOG_ERROR("called FramePainter::paint with nil layoutObject");
        return;
    }

    if (!frameView().shouldThrottleRendering()) {
        RELEASE_ASSERT(!frameView().needsLayout());
        ASSERT(document->lifecycle().state() >= DocumentLifecycle::CompositingClean);
    }

    TRACE_EVENT1("devtools.timeline", "Paint", "data", InspectorPaintEvent::data(layoutView, LayoutRect(rect), 0));

    bool isTopLevelPainter = !s_inPaintContents;
    s_inPaintContents = true;

    FontCachePurgePreventer fontCachePurgePreventer;

    // TODO(jchaffraix): GlobalPaintFlags should be const during a paint
    // phase. Thus we should set this flag upfront (crbug.com/510280).
    GlobalPaintFlags localPaintFlags = globalPaintFlags;
    if (document->printing())
        localPaintFlags |= GlobalPaintFlattenCompositingLayers | GlobalPaintPrinting;

    PaintLayer* rootLayer = layoutView->layer();

#if ENABLE(ASSERT)
    if (!frameView().shouldThrottleRendering())
        layoutView->assertSubtreeIsLaidOut();
    LayoutObject::SetLayoutNeededForbiddenScope forbidSetNeedsLayout(*rootLayer->layoutObject());
#endif

    PaintLayerPainter layerPainter(*rootLayer);

    float deviceScaleFactor = blink::deviceScaleFactor(rootLayer->layoutObject()->frame());
    context.setDeviceScaleFactor(deviceScaleFactor);

    layerPainter.paint(context, LayoutRect(rect), localPaintFlags);

    if (rootLayer->containsDirtyOverlayScrollbars())
        layerPainter.paintOverlayScrollbars(context, LayoutRect(rect), localPaintFlags);

    // Regions may have changed as a result of the visibility/z-index of element changing.
    if (document->annotatedRegionsDirty())
        frameView().updateDocumentAnnotatedRegions();

    if (isTopLevelPainter) {
        // Everything that happens after paintContents completions is considered
        // to be part of the next frame.
        memoryCache()->updateFramePaintTimestamp();
        s_inPaintContents = false;
    }

    InspectorInstrumentation::didPaint(layoutView, 0, context, LayoutRect(rect));
}
Exemplo n.º 19
0
void PartPainter::paint(const PaintInfo& paintInfo,
                        const LayoutPoint& paintOffset) {
  LayoutPoint adjustedPaintOffset = paintOffset + m_layoutPart.location();
  if (!ReplacedPainter(m_layoutPart)
           .shouldPaint(paintInfo, adjustedPaintOffset))
    return;

  LayoutRect borderRect(adjustedPaintOffset, m_layoutPart.size());

  if (m_layoutPart.hasBoxDecorationBackground() &&
      (paintInfo.phase == PaintPhaseForeground ||
       paintInfo.phase == PaintPhaseSelection))
    BoxPainter(m_layoutPart)
        .paintBoxDecorationBackground(paintInfo, adjustedPaintOffset);

  if (paintInfo.phase == PaintPhaseMask) {
    BoxPainter(m_layoutPart).paintMask(paintInfo, adjustedPaintOffset);
    return;
  }

  if (shouldPaintSelfOutline(paintInfo.phase))
    ObjectPainter(m_layoutPart).paintOutline(paintInfo, adjustedPaintOffset);

  if (paintInfo.phase != PaintPhaseForeground)
    return;

  if (m_layoutPart.widget()) {
    // TODO(schenney) crbug.com/93805 Speculative release assert to verify that
    // the crashes we see in widget painting are due to a destroyed LayoutPart
    // object.
    CHECK(m_layoutPart.node());
    Optional<RoundedInnerRectClipper> clipper;
    if (m_layoutPart.style()->hasBorderRadius()) {
      if (borderRect.isEmpty())
        return;

      FloatRoundedRect roundedInnerRect =
          m_layoutPart.style()->getRoundedInnerBorderFor(
              borderRect,
              LayoutRectOutsets(
                  -(m_layoutPart.paddingTop() + m_layoutPart.borderTop()),
                  -(m_layoutPart.paddingRight() + m_layoutPart.borderRight()),
                  -(m_layoutPart.paddingBottom() + m_layoutPart.borderBottom()),
                  -(m_layoutPart.paddingLeft() + m_layoutPart.borderLeft())),
              true, true);
      clipper.emplace(m_layoutPart, paintInfo, borderRect, roundedInnerRect,
                      ApplyToDisplayList);
    }

    m_layoutPart.paintContents(paintInfo, paintOffset);
  }

  // Paint a partially transparent wash over selected widgets.
  if (isSelected() && !paintInfo.isPrinting() &&
      !LayoutObjectDrawingRecorder::useCachedDrawingIfPossible(
          paintInfo.context, m_layoutPart, paintInfo.phase)) {
    LayoutRect rect = m_layoutPart.localSelectionRect();
    rect.moveBy(adjustedPaintOffset);
    IntRect selectionRect = pixelSnappedIntRect(rect);
    LayoutObjectDrawingRecorder drawingRecorder(paintInfo.context, m_layoutPart,
                                                paintInfo.phase, selectionRect);
    paintInfo.context.fillRect(selectionRect,
                               m_layoutPart.selectionBackgroundColor());
  }

  if (m_layoutPart.canResize())
    ScrollableAreaPainter(*m_layoutPart.layer()->getScrollableArea())
        .paintResizer(paintInfo.context, roundedIntPoint(adjustedPaintOffset),
                      paintInfo.cullRect());
}
Exemplo n.º 20
0
void FramePainter::paintContents(GraphicsContext* context, const IntRect& rect)
{
    Document* document = m_frameView.frame().document();

#ifndef NDEBUG
    bool fillWithRed;
    if (document->printing())
        fillWithRed = false; // Printing, don't fill with red (can't remember why).
    else if (m_frameView.frame().owner())
        fillWithRed = false; // Subframe, don't fill with red.
    else if (m_frameView.isTransparent())
        fillWithRed = false; // Transparent, don't fill with red.
    else if (m_frameView.paintBehavior() & PaintBehaviorSelectionOnly)
        fillWithRed = false; // Selections are transparent, don't fill with red.
    else if (m_frameView.nodeToDraw())
        fillWithRed = false; // Element images are transparent, don't fill with red.
    else
        fillWithRed = true;

    if (fillWithRed) {
        IntRect contentRect(IntPoint(), m_frameView.contentsSize());
        DrawingRecorder drawingRecorder(*context, *m_frameView.layoutView(), DisplayItem::DebugRedFill, contentRect);
        if (!drawingRecorder.canUseCachedDrawing())
            context->fillRect(contentRect, Color(0xFF, 0, 0));
    }
#endif

    LayoutView* layoutView = m_frameView.layoutView();
    if (!layoutView) {
        WTF_LOG_ERROR("called FramePainter::paint with nil renderer");
        return;
    }

    RELEASE_ASSERT(!m_frameView.needsLayout());
    ASSERT(document->lifecycle().state() >= DocumentLifecycle::CompositingClean);

    TRACE_EVENT1(TRACE_DISABLED_BY_DEFAULT("devtools.timeline"), "Paint", "data", InspectorPaintEvent::data(layoutView, LayoutRect(rect), 0));

    bool isTopLevelPainter = !s_inPaintContents;
    s_inPaintContents = true;

    FontCachePurgePreventer fontCachePurgePreventer;

    PaintBehavior oldPaintBehavior = m_frameView.paintBehavior();

    if (FrameView* parentView = m_frameView.parentFrameView()) {
        if (parentView->paintBehavior() & PaintBehaviorFlattenCompositingLayers)
            m_frameView.setPaintBehavior(m_frameView.paintBehavior() | PaintBehaviorFlattenCompositingLayers);
    }

    if (m_frameView.paintBehavior() == PaintBehaviorNormal)
        document->markers().invalidateRenderedRectsForMarkersInRect(LayoutRect(rect));

    if (document->printing())
        m_frameView.setPaintBehavior(m_frameView.paintBehavior() | PaintBehaviorFlattenCompositingLayers);

    ASSERT(!m_frameView.isPainting());
    m_frameView.setIsPainting(true);

    // m_frameView.nodeToDraw() is used to draw only one element (and its descendants)
    LayoutObject* renderer = m_frameView.nodeToDraw() ? m_frameView.nodeToDraw()->layoutObject() : 0;
    DeprecatedPaintLayer* rootLayer = layoutView->layer();

#if ENABLE(ASSERT)
    layoutView->assertSubtreeIsLaidOut();
    LayoutObject::SetLayoutNeededForbiddenScope forbidSetNeedsLayout(*rootLayer->layoutObject());
#endif

    DeprecatedPaintLayerPainter layerPainter(*rootLayer);

    float deviceScaleFactor = blink::deviceScaleFactor(rootLayer->layoutObject()->frame());
    context->setDeviceScaleFactor(deviceScaleFactor);

    layerPainter.paint(context, LayoutRect(rect), m_frameView.paintBehavior(), renderer);

    if (rootLayer->containsDirtyOverlayScrollbars())
        layerPainter.paintOverlayScrollbars(context, LayoutRect(rect), m_frameView.paintBehavior(), renderer);

    m_frameView.setIsPainting(false);

    m_frameView.setPaintBehavior(oldPaintBehavior);
    m_frameView.setLastPaintTime(currentTime());

    // Regions may have changed as a result of the visibility/z-index of element changing.
    if (document->annotatedRegionsDirty())
        m_frameView.updateAnnotatedRegions();

    if (isTopLevelPainter) {
        // Everything that happens after paintContents completions is considered
        // to be part of the next frame.
        memoryCache()->updateFramePaintTimestamp();
        s_inPaintContents = false;
    }

    InspectorInstrumentation::didPaint(layoutView, 0, context, LayoutRect(rect));
}
Exemplo n.º 21
0
PassOwnPtr<DragImage> DragImage::create(const KURL& url, const String& inLabel, const FontDescription& systemFont, float deviceScaleFactor)
{
    const Font labelFont = deriveDragLabelFont(kDragLinkLabelFontSize, FontWeightBold, systemFont);
    const Font urlFont = deriveDragLabelFont(kDragLinkUrlFontSize, FontWeightNormal, systemFont);
    FontCachePurgePreventer fontCachePurgePreventer;

    bool drawURLString = true;
    bool clipURLString = false;
    bool clipLabelString = false;

    String urlString = url.string();
    String label = inLabel.stripWhiteSpace();
    if (label.isEmpty()) {
        drawURLString = false;
        label = urlString;
    }

    // First step is drawing the link drag image width.
    TextRun labelRun(label.impl());
    TextRun urlRun(urlString.impl());
    IntSize labelSize(labelFont.width(labelRun), labelFont.fontMetrics().ascent() + labelFont.fontMetrics().descent());

    if (labelSize.width() > kMaxDragLabelStringWidth) {
        labelSize.setWidth(kMaxDragLabelStringWidth);
        clipLabelString = true;
    }

    IntSize urlStringSize;
    IntSize imageSize(labelSize.width() + kDragLabelBorderX * 2, labelSize.height() + kDragLabelBorderY * 2);

    if (drawURLString) {
        urlStringSize.setWidth(urlFont.width(urlRun));
        urlStringSize.setHeight(urlFont.fontMetrics().ascent() + urlFont.fontMetrics().descent());
        imageSize.setHeight(imageSize.height() + urlStringSize.height());
        if (urlStringSize.width() > kMaxDragLabelStringWidth) {
            imageSize.setWidth(kMaxDragLabelWidth);
            clipURLString = true;
        } else
            imageSize.setWidth(std::max(labelSize.width(), urlStringSize.width()) + kDragLabelBorderX * 2);
    }

    // We now know how big the image needs to be, so we create and
    // fill the background
    IntSize scaledImageSize = imageSize;
    scaledImageSize.scale(deviceScaleFactor);
    OwnPtr<ImageBuffer> buffer(ImageBuffer::create(scaledImageSize));
    if (!buffer)
        return nullptr;

    OwnPtr<GraphicsContext> extraGraphicsContext;
    OwnPtr<DisplayItemList> displayItemList;
    GraphicsContext* context;
    if (RuntimeEnabledFeatures::slimmingPaintEnabled()) {
        displayItemList = DisplayItemList::create();
        extraGraphicsContext = adoptPtr(new GraphicsContext(0, displayItemList.get()));
        context = extraGraphicsContext.get();
    } else {
        context = buffer->context();
    }

    {
        IntRect rect(IntPoint(), imageSize);
        DrawingRecorder drawingRecorder(context, buffer->displayItemClient(), DisplayItem::DragImage, rect);
        context->scale(deviceScaleFactor, deviceScaleFactor);

        const float DragLabelRadius = 5;
        const IntSize radii(DragLabelRadius, DragLabelRadius);

        const Color backgroundColor(140, 140, 140);
        context->fillRoundedRect(rect, radii, radii, radii, radii, backgroundColor);

        // Draw the text
        if (drawURLString) {
            if (clipURLString)
                urlString = StringTruncator::centerTruncate(urlString, imageSize.width() - (kDragLabelBorderX * 2.0f), urlFont);
            IntPoint textPos(kDragLabelBorderX, imageSize.height() - (kLabelBorderYOffset + urlFont.fontMetrics().descent()));
            TextRun textRun(urlString);
            context->drawText(urlFont, TextRunPaintInfo(textRun), textPos);
        }

        if (clipLabelString)
            label = StringTruncator::rightTruncate(label, imageSize.width() - (kDragLabelBorderX * 2.0f), labelFont);

        bool hasStrongDirectionality;
        TextRun textRun = textRunWithDirectionality(label, hasStrongDirectionality);
        IntPoint textPos(kDragLabelBorderX, kDragLabelBorderY + labelFont.fontDescription().computedPixelSize());
        if (hasStrongDirectionality && textRun.direction() == RTL) {
            float textWidth = labelFont.width(textRun);
            int availableWidth = imageSize.width() - kDragLabelBorderX * 2;
            textPos.setX(availableWidth - ceilf(textWidth));
        }
        context->drawBidiText(labelFont, TextRunPaintInfo(textRun), FloatPoint(textPos));
    }

    if (RuntimeEnabledFeatures::slimmingPaintEnabled())
        displayItemList->replay(buffer->context());

    RefPtr<Image> image = buffer->copyImage();
    return DragImage::create(image.get(), DoNotRespectImageOrientation, deviceScaleFactor);
}