blob: 72fc6d1a734461425f0ce567f6b80c04722c0aa1 [file] [log] [blame]
/*
* Copyright (C) 2015-2021 Apple Inc. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
* OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include "config.h"
#include "DisplayListItems.h"
#include "DisplayListReplayer.h"
#include "FontCascade.h"
#include "ImageBuffer.h"
#include "MediaPlayer.h"
#include "SharedBuffer.h"
#include <wtf/text/TextStream.h>
#if USE(CG)
#include "GraphicsContextPlatformPrivateCG.h"
#endif
namespace WebCore {
namespace DisplayList {
// Should match RenderTheme::platformFocusRingWidth()
static const float platformFocusRingWidth = 3;
void Save::apply(GraphicsContext& context) const
{
context.save();
}
void Restore::apply(GraphicsContext& context) const
{
context.restore();
}
void Translate::apply(GraphicsContext& context) const
{
context.translate(m_x, m_y);
}
static TextStream& operator<<(TextStream& ts, const Translate& item)
{
ts.dumpProperty("x", item.x());
ts.dumpProperty("y", item.y());
return ts;
}
void Rotate::apply(GraphicsContext& context) const
{
context.rotate(m_angle);
}
static TextStream& operator<<(TextStream& ts, const Rotate& item)
{
ts.dumpProperty("angle", item.angle());
return ts;
}
void Scale::apply(GraphicsContext& context) const
{
context.scale(m_size);
}
static TextStream& operator<<(TextStream& ts, const Scale& item)
{
ts.dumpProperty("size", item.amount());
return ts;
}
void SetCTM::apply(GraphicsContext& context) const
{
context.setCTM(m_transform);
}
static TextStream& operator<<(TextStream& ts, const SetCTM& item)
{
ts.dumpProperty("set-ctm", item.transform());
return ts;
}
void ConcatenateCTM::apply(GraphicsContext& context) const
{
context.concatCTM(m_transform);
}
static TextStream& operator<<(TextStream& ts, const ConcatenateCTM& item)
{
ts.dumpProperty("ctm", item.transform());
return ts;
}
void SetInlineFillColor::apply(GraphicsContext& context) const
{
context.setFillColor(color());
}
static TextStream& operator<<(TextStream& ts, const SetInlineFillColor& state)
{
ts.dumpProperty("color", state.color());
return ts;
}
void SetInlineStrokeColor::apply(GraphicsContext& context) const
{
context.setStrokeColor(color());
}
static TextStream& operator<<(TextStream& ts, const SetInlineStrokeColor& state)
{
ts.dumpProperty("color", state.color());
return ts;
}
void SetStrokeThickness::apply(GraphicsContext& context) const
{
context.setStrokeThickness(m_thickness);
}
static TextStream& operator<<(TextStream& ts, const SetStrokeThickness& state)
{
ts.dumpProperty("thickness", state.thickness());
return ts;
}
SetState::SetState(const GraphicsContextState& state, GraphicsContextState::StateChangeFlags flags)
: m_stateChange(state, flags)
{
}
SetState::SetState(const GraphicsContextStateChange& stateChange, const PatternData& strokePattern, const PatternData& fillPattern)
: m_stateChange(stateChange)
, m_strokePattern(strokePattern)
, m_fillPattern(fillPattern)
{
}
void SetState::apply(GraphicsContext& context, NativeImage* strokePatternImage, NativeImage* fillPatternImage)
{
if (m_stateChange.m_changeFlags.contains(GraphicsContextState::StrokePatternChange) && strokePatternImage)
m_stateChange.m_state.strokePattern = Pattern::create(*strokePatternImage, m_strokePattern.parameters);
if (m_stateChange.m_changeFlags.contains(GraphicsContextState::FillPatternChange) && fillPatternImage)
m_stateChange.m_state.fillPattern = Pattern::create(*fillPatternImage, m_fillPattern.parameters);
m_stateChange.apply(context);
}
static TextStream& operator<<(TextStream& ts, const SetState& state)
{
ts << state.stateChange();
return ts;
}
void SetLineCap::apply(GraphicsContext& context) const
{
context.setLineCap(m_lineCap);
}
static TextStream& operator<<(TextStream& ts, const SetLineCap& lineCap)
{
ts.dumpProperty("line-cap", lineCap.lineCap());
return ts;
}
void SetLineDash::apply(GraphicsContext& context) const
{
context.setLineDash(m_dashArray, m_dashOffset);
}
static TextStream& operator<<(TextStream& ts, const SetLineDash& lineDash)
{
ts.dumpProperty("dash-array", lineDash.dashArray());
ts.dumpProperty("dash-offset", lineDash.dashOffset());
return ts;
}
void SetLineJoin::apply(GraphicsContext& context) const
{
context.setLineJoin(m_lineJoin);
}
static TextStream& operator<<(TextStream& ts, const SetLineJoin& lineJoin)
{
ts.dumpProperty("line-join", lineJoin.lineJoin());
return ts;
}
void SetMiterLimit::apply(GraphicsContext& context) const
{
context.setMiterLimit(m_miterLimit);
}
static TextStream& operator<<(TextStream& ts, const SetMiterLimit& miterLimit)
{
ts.dumpProperty("mitre-limit", miterLimit.miterLimit());
return ts;
}
void ClearShadow::apply(GraphicsContext& context) const
{
context.clearShadow();
}
void Clip::apply(GraphicsContext& context) const
{
context.clip(m_rect);
}
static TextStream& operator<<(TextStream& ts, const Clip& item)
{
ts.dumpProperty("rect", item.rect());
return ts;
}
void ClipOut::apply(GraphicsContext& context) const
{
context.clipOut(m_rect);
}
static TextStream& operator<<(TextStream& ts, const ClipOut& item)
{
ts.dumpProperty("rect", item.rect());
return ts;
}
NO_RETURN_DUE_TO_ASSERT void ClipToImageBuffer::apply(GraphicsContext&) const
{
ASSERT_NOT_REACHED();
}
void ClipToImageBuffer::apply(GraphicsContext& context, WebCore::ImageBuffer& imageBuffer) const
{
context.clipToImageBuffer(imageBuffer, m_destinationRect);
}
static TextStream& operator<<(TextStream& ts, const ClipToImageBuffer& item)
{
ts.dumpProperty("image-buffer-identifier", item.imageBufferIdentifier());
ts.dumpProperty("dest-rect", item.destinationRect());
return ts;
}
void ClipOutToPath::apply(GraphicsContext& context) const
{
context.clipOut(m_path);
}
static TextStream& operator<<(TextStream& ts, const ClipOutToPath& item)
{
ts.dumpProperty("path", item.path());
return ts;
}
void ClipPath::apply(GraphicsContext& context) const
{
context.clipPath(m_path, m_windRule);
}
static TextStream& operator<<(TextStream& ts, const ClipPath& item)
{
ts.dumpProperty("path", item.path());
ts.dumpProperty("wind-rule", item.windRule());
return ts;
}
static TextStream& operator<<(TextStream& ts, const BeginClipToDrawingCommands& item)
{
ts.dumpProperty("destination", item.destination());
ts.dumpProperty("color-space", item.colorSpace());
return ts;
}
static TextStream& operator<<(TextStream& ts, const EndClipToDrawingCommands& item)
{
ts.dumpProperty("destination", item.destination());
return ts;
}
DrawGlyphs::DrawGlyphs(RenderingResourceIdentifier fontIdentifier, Vector<GlyphBufferGlyph, 128>&& glyphs, Vector<GlyphBufferAdvance, 128>&& advances, const FloatRect& bounds, const FloatPoint& localAnchor, FontSmoothingMode smoothingMode)
: m_fontIdentifier(fontIdentifier)
, m_glyphs(WTFMove(glyphs))
, m_advances(WTFMove(advances))
, m_bounds(bounds)
, m_localAnchor(localAnchor)
, m_smoothingMode(smoothingMode)
{
}
DrawGlyphs::DrawGlyphs(const Font& font, const GlyphBufferGlyph* glyphs, const GlyphBufferAdvance* advances, unsigned count, const FloatPoint& localAnchor, FontSmoothingMode smoothingMode)
: m_fontIdentifier(font.renderingResourceIdentifier())
, m_localAnchor(localAnchor)
, m_smoothingMode(smoothingMode)
{
m_glyphs.reserveInitialCapacity(count);
m_advances.reserveInitialCapacity(count);
for (unsigned i = 0; i < count; ++i) {
m_glyphs.uncheckedAppend(glyphs[i]);
m_advances.uncheckedAppend(advances[i]);
}
computeBounds(font);
}
void DrawGlyphs::apply(GraphicsContext& context, const Font& font) const
{
context.drawGlyphs(font, m_glyphs.data(), m_advances.data(), m_glyphs.size(), anchorPoint(), m_smoothingMode);
}
void DrawGlyphs::computeBounds(const Font& font)
{
// FIXME: This code doesn't actually take the extents of the glyphs into consideration. It assumes that
// the glyph lies entirely within its [(ascent + descent), advance] rect.
float ascent = font.fontMetrics().floatAscent();
float descent = font.fontMetrics().floatDescent();
FloatPoint current = localAnchor();
size_t numGlyphs = m_glyphs.size();
for (size_t i = 0; i < numGlyphs; ++i) {
GlyphBufferAdvance advance = m_advances[i];
FloatRect glyphRect = FloatRect(current.x(), current.y() - ascent, width(advance), ascent + descent);
m_bounds.unite(glyphRect);
current.move(width(advance), height(advance));
}
}
static TextStream& operator<<(TextStream& ts, const DrawGlyphs& item)
{
// FIXME: dump more stuff.
ts.dumpProperty("local-anchor", item.localAnchor());
ts.dumpProperty("anchor-point", item.anchorPoint());
ts.dumpProperty("length", item.glyphs().size());
return ts;
}
NO_RETURN_DUE_TO_ASSERT void DrawImageBuffer::apply(GraphicsContext&) const
{
ASSERT_NOT_REACHED();
}
void DrawImageBuffer::apply(GraphicsContext& context, WebCore::ImageBuffer& imageBuffer) const
{
context.drawImageBuffer(imageBuffer, m_destinationRect, m_srcRect, m_options);
}
static TextStream& operator<<(TextStream& ts, const DrawImageBuffer& item)
{
ts.dumpProperty("image-buffer-identifier", item.imageBufferIdentifier());
ts.dumpProperty("source-rect", item.source());
ts.dumpProperty("dest-rect", item.destinationRect());
return ts;
}
NO_RETURN_DUE_TO_ASSERT void DrawNativeImage::apply(GraphicsContext&) const
{
ASSERT_NOT_REACHED();
}
void DrawNativeImage::apply(GraphicsContext& context, NativeImage& image) const
{
context.drawNativeImage(image, m_imageSize, m_destinationRect, m_srcRect, m_options);
}
static TextStream& operator<<(TextStream& ts, const DrawNativeImage& item)
{
// FIXME: dump more stuff.
ts.dumpProperty("image-identifier", item.imageIdentifier());
ts.dumpProperty("source-rect", item.source());
ts.dumpProperty("dest-rect", item.destinationRect());
return ts;
}
DrawPattern::DrawPattern(RenderingResourceIdentifier imageIdentifier, const FloatSize& imageSize, const FloatRect& destRect, const FloatRect& tileRect, const AffineTransform& patternTransform, const FloatPoint& phase, const FloatSize& spacing, const ImagePaintingOptions& options)
: m_imageIdentifier(imageIdentifier)
, m_imageSize(imageSize)
, m_destination(destRect)
, m_tileRect(tileRect)
, m_patternTransform(patternTransform)
, m_phase(phase)
, m_spacing(spacing)
, m_options(options)
{
}
NO_RETURN_DUE_TO_ASSERT void DrawPattern::apply(GraphicsContext&) const
{
ASSERT_NOT_REACHED();
}
void DrawPattern::apply(GraphicsContext& context, NativeImage& image) const
{
context.drawPattern(image, m_imageSize, m_destination, m_tileRect, m_patternTransform, m_phase, m_spacing, m_options);
}
static TextStream& operator<<(TextStream& ts, const DrawPattern& item)
{
ts.dumpProperty("image-identifier", item.imageIdentifier());
ts.dumpProperty("pattern-transform", item.patternTransform());
ts.dumpProperty("tile-rect", item.tileRect());
ts.dumpProperty("dest-rect", item.destRect());
ts.dumpProperty("phase", item.phase());
ts.dumpProperty("spacing", item.spacing());
return ts;
}
void DrawRect::apply(GraphicsContext& context) const
{
context.drawRect(m_rect, m_borderThickness);
}
static TextStream& operator<<(TextStream& ts, const DrawRect& item)
{
ts.dumpProperty("rect", item.rect());
ts.dumpProperty("border-thickness", item.borderThickness());
return ts;
}
std::optional<FloatRect> DrawLine::localBounds(const GraphicsContext&) const
{
FloatRect bounds;
bounds.fitToPoints(m_point1, m_point2);
return bounds;
}
void DrawLine::apply(GraphicsContext& context) const
{
context.drawLine(m_point1, m_point2);
}
static TextStream& operator<<(TextStream& ts, const DrawLine& item)
{
ts.dumpProperty("point-1", item.point1());
ts.dumpProperty("point-2", item.point2());
return ts;
}
DrawLinesForText::DrawLinesForText(const FloatPoint& blockLocation, const FloatSize& localAnchor, float thickness, const DashArray& widths, bool printing, bool doubleLines)
: m_blockLocation(blockLocation)
, m_localAnchor(localAnchor)
, m_widths(widths)
, m_thickness(thickness)
, m_printing(printing)
, m_doubleLines(doubleLines)
{
}
void DrawLinesForText::apply(GraphicsContext& context) const
{
context.drawLinesForText(point(), m_thickness, m_widths, m_printing, m_doubleLines);
}
std::optional<FloatRect> DrawLinesForText::localBounds(const GraphicsContext&) const
{
// This function needs to return a value equal to or enclosing what GraphicsContext::computeLineBoundsAndAntialiasingModeForText() returns.
if (!m_widths.size())
return FloatRect();
FloatRect result(point(), FloatSize(m_widths.last(), m_thickness));
result.inflate(1); // Account for pixel snapping. FIXME: This isn't perfect, as it doesn't take the CTM into account.
return result;
}
static TextStream& operator<<(TextStream& ts, const DrawLinesForText& item)
{
ts.dumpProperty("block-location", item.blockLocation());
ts.dumpProperty("local-anchor", item.localAnchor());
ts.dumpProperty("point", item.point());
ts.dumpProperty("thickness", item.thickness());
ts.dumpProperty("double", item.doubleLines());
ts.dumpProperty("widths", item.widths());
ts.dumpProperty("is-printing", item.isPrinting());
ts.dumpProperty("double", item.doubleLines());
return ts;
}
void DrawDotsForDocumentMarker::apply(GraphicsContext& context) const
{
context.drawDotsForDocumentMarker(m_rect, {
static_cast<DocumentMarkerLineStyle::Mode>(m_styleMode),
m_styleShouldUseDarkAppearance,
});
}
std::optional<FloatRect> DrawDotsForDocumentMarker::localBounds(const GraphicsContext&) const
{
return m_rect;
}
static TextStream& operator<<(TextStream& ts, const DrawDotsForDocumentMarker& item)
{
ts.dumpProperty("rect", item.rect());
return ts;
}
void DrawEllipse::apply(GraphicsContext& context) const
{
context.drawEllipse(m_rect);
}
static TextStream& operator<<(TextStream& ts, const DrawEllipse& item)
{
ts.dumpProperty("rect", item.rect());
return ts;
}
void DrawPath::apply(GraphicsContext& context) const
{
context.drawPath(m_path);
}
static TextStream& operator<<(TextStream& ts, const DrawPath&)
{
// FIXME: add logging for paths.
return ts;
}
void DrawFocusRingPath::apply(GraphicsContext& context) const
{
context.drawFocusRing(m_path, m_width, m_offset, m_color);
}
std::optional<FloatRect> DrawFocusRingPath::localBounds(const GraphicsContext&) const
{
FloatRect result = m_path.fastBoundingRect();
result.inflate(platformFocusRingWidth);
return result;
}
static TextStream& operator<<(TextStream& ts, const DrawFocusRingPath& item)
{
// ts.dumpProperty("path", item.path()); // FIXME: add logging for paths.
ts.dumpProperty("width", item.width());
ts.dumpProperty("offset", item.offset());
ts.dumpProperty("color", item.color());
return ts;
}
DrawFocusRingRects::DrawFocusRingRects(const Vector<FloatRect>& rects, float width, float offset, const Color& color)
: m_rects(rects)
, m_width(width)
, m_offset(offset)
, m_color(color)
{
}
void DrawFocusRingRects::apply(GraphicsContext& context) const
{
context.drawFocusRing(m_rects, m_width, m_offset, m_color);
}
std::optional<FloatRect> DrawFocusRingRects::localBounds(const GraphicsContext&) const
{
FloatRect result;
for (auto& rect : m_rects)
result.unite(rect);
result.inflate(platformFocusRingWidth);
return result;
}
static TextStream& operator<<(TextStream& ts, const DrawFocusRingRects& item)
{
ts.dumpProperty("rects", item.rects());
ts.dumpProperty("width", item.width());
ts.dumpProperty("offset", item.offset());
ts.dumpProperty("color", item.color());
return ts;
}
void FillRect::apply(GraphicsContext& context) const
{
context.fillRect(m_rect);
}
static TextStream& operator<<(TextStream& ts, const FillRect& item)
{
ts.dumpProperty("rect", item.rect());
return ts;
}
void FillRectWithColor::apply(GraphicsContext& context) const
{
context.fillRect(m_rect, m_color);
}
static TextStream& operator<<(TextStream& ts, const FillRectWithColor& item)
{
ts.dumpProperty("rect", item.rect());
ts.dumpProperty("color", item.color());
return ts;
}
FillRectWithGradient::FillRectWithGradient(const FloatRect& rect, Gradient& gradient)
: m_rect(rect)
, m_gradient(gradient)
{
}
void FillRectWithGradient::apply(GraphicsContext& context) const
{
context.fillRect(m_rect, m_gradient.get());
}
static TextStream& operator<<(TextStream& ts, const FillRectWithGradient& item)
{
// FIXME: log gradient.
ts.dumpProperty("rect", item.rect());
return ts;
}
void FillCompositedRect::apply(GraphicsContext& context) const
{
context.fillRect(m_rect, m_color, m_op, m_blendMode);
}
static TextStream& operator<<(TextStream& ts, const FillCompositedRect& item)
{
ts.dumpProperty("rect", item.rect());
ts.dumpProperty("color", item.color());
ts.dumpProperty("composite-operation", item.compositeOperator());
ts.dumpProperty("blend-mode", item.blendMode());
return ts;
}
void FillRoundedRect::apply(GraphicsContext& context) const
{
context.fillRoundedRect(m_rect, m_color, m_blendMode);
}
static TextStream& operator<<(TextStream& ts, const FillRoundedRect& item)
{
ts.dumpProperty("rect", item.roundedRect());
ts.dumpProperty("color", item.color());
ts.dumpProperty("blend-mode", item.blendMode());
return ts;
}
void FillRectWithRoundedHole::apply(GraphicsContext& context) const
{
context.fillRectWithRoundedHole(m_rect, m_roundedHoleRect, m_color);
}
static TextStream& operator<<(TextStream& ts, const FillRectWithRoundedHole& item)
{
ts.dumpProperty("rect", item.rect());
ts.dumpProperty("rounded-hole-rect", item.roundedHoleRect());
ts.dumpProperty("color", item.color());
return ts;
}
#if ENABLE(INLINE_PATH_DATA)
void FillLine::apply(GraphicsContext& context) const
{
context.fillPath(path());
}
static TextStream& operator<<(TextStream& ts, const FillLine& item)
{
ts.dumpProperty("path", item.path());
return ts;
}
void FillArc::apply(GraphicsContext& context) const
{
context.fillPath(path());
}
static TextStream& operator<<(TextStream& ts, const FillArc& item)
{
ts.dumpProperty("path", item.path());
return ts;
}
void FillQuadCurve::apply(GraphicsContext& context) const
{
context.fillPath(path());
}
static TextStream& operator<<(TextStream& ts, const FillQuadCurve& item)
{
ts.dumpProperty("path", item.path());
return ts;
}
void FillBezierCurve::apply(GraphicsContext& context) const
{
context.fillPath(path());
}
static TextStream& operator<<(TextStream& ts, const FillBezierCurve& item)
{
ts.dumpProperty("path", item.path());
return ts;
}
#endif // ENABLE(INLINE_PATH_DATA)
void FillPath::apply(GraphicsContext& context) const
{
context.fillPath(m_path);
}
static TextStream& operator<<(TextStream& ts, const FillPath& item)
{
ts.dumpProperty("path", item.path());
return ts;
}
void FillEllipse::apply(GraphicsContext& context) const
{
context.fillEllipse(m_rect);
}
static TextStream& operator<<(TextStream& ts, const FillEllipse& item)
{
ts.dumpProperty("rect", item.rect());
return ts;
}
static TextStream& operator<<(TextStream& ts, const GetPixelBuffer& item)
{
ts.dumpProperty("outputFormat", item.outputFormat());
ts.dumpProperty("srcRect", item.srcRect());
return ts;
}
PutPixelBuffer::PutPixelBuffer(const PixelBuffer& pixelBuffer, const IntRect& srcRect, const IntPoint& destPoint, AlphaPremultiplication destFormat)
: m_srcRect(srcRect)
, m_destPoint(destPoint)
, m_pixelBuffer(pixelBuffer.deepClone()) // This copy is actually required to preserve the semantics of putPixelBuffer().
, m_destFormat(destFormat)
{
}
PutPixelBuffer::PutPixelBuffer(PixelBuffer&& pixelBuffer, const IntRect& srcRect, const IntPoint& destPoint, AlphaPremultiplication destFormat)
: m_srcRect(srcRect)
, m_destPoint(destPoint)
, m_pixelBuffer(WTFMove(pixelBuffer))
, m_destFormat(destFormat)
{
}
PutPixelBuffer::PutPixelBuffer(const PutPixelBuffer& other)
: m_srcRect(other.m_srcRect)
, m_destPoint(other.m_destPoint)
, m_pixelBuffer(other.m_pixelBuffer.deepClone())
, m_destFormat(other.m_destFormat)
{
}
PutPixelBuffer& PutPixelBuffer::operator=(const PutPixelBuffer& other)
{
PutPixelBuffer copy { other };
swap(copy);
return *this;
}
void PutPixelBuffer::swap(PutPixelBuffer& other)
{
std::swap(m_srcRect, other.m_srcRect);
std::swap(m_destPoint, other.m_destPoint);
std::swap(m_pixelBuffer, other.m_pixelBuffer);
std::swap(m_destFormat, other.m_destFormat);
}
static TextStream& operator<<(TextStream& ts, const PutPixelBuffer& item)
{
ts.dumpProperty("pixelBufferSize", item.pixelBuffer().size());
ts.dumpProperty("srcRect", item.srcRect());
ts.dumpProperty("destPoint", item.destPoint());
ts.dumpProperty("destFormat", item.destFormat());
return ts;
}
#if ENABLE(VIDEO)
PaintFrameForMedia::PaintFrameForMedia(MediaPlayer& player, const FloatRect& destination)
: m_identifier(player.identifier())
, m_destination(destination)
{
}
NO_RETURN_DUE_TO_ASSERT void PaintFrameForMedia::apply(GraphicsContext&) const
{
// Should be handled by the delegate.
ASSERT_NOT_REACHED();
}
static TextStream& operator<<(TextStream& ts, const PaintFrameForMedia& item)
{
ts.dumpProperty("destination", item.destination());
return ts;
}
#endif
std::optional<FloatRect> StrokeRect::localBounds(const GraphicsContext&) const
{
FloatRect bounds = m_rect;
bounds.expand(m_lineWidth, m_lineWidth);
return bounds;
}
void StrokeRect::apply(GraphicsContext& context) const
{
context.strokeRect(m_rect, m_lineWidth);
}
static TextStream& operator<<(TextStream& ts, const StrokeRect& item)
{
ts.dumpProperty("rect", item.rect());
ts.dumpProperty("line-width", item.lineWidth());
return ts;
}
std::optional<FloatRect> StrokePath::localBounds(const GraphicsContext& context) const
{
// FIXME: Need to take stroke thickness into account correctly, via CGPathByStrokingPath().
float strokeThickness = context.strokeThickness();
FloatRect bounds = m_path.fastBoundingRect();
bounds.expand(strokeThickness, strokeThickness);
return bounds;
}
void StrokePath::apply(GraphicsContext& context) const
{
context.strokePath(m_path);
}
static TextStream& operator<<(TextStream& ts, const StrokePath& item)
{
ts.dumpProperty("path", item.path());
return ts;
}
std::optional<FloatRect> StrokeEllipse::localBounds(const GraphicsContext& context) const
{
float strokeThickness = context.strokeThickness();
FloatRect bounds = m_rect;
bounds.expand(strokeThickness, strokeThickness);
return bounds;
}
void StrokeEllipse::apply(GraphicsContext& context) const
{
context.strokeEllipse(m_rect);
}
static TextStream& operator<<(TextStream& ts, const StrokeEllipse& item)
{
ts.dumpProperty("rect", item.rect());
return ts;
}
std::optional<FloatRect> StrokeLine::localBounds(const GraphicsContext& context) const
{
float strokeThickness = context.strokeThickness();
FloatRect bounds;
bounds.fitToPoints(start(), end());
bounds.expand(strokeThickness, strokeThickness);
return bounds;
}
void StrokeLine::apply(GraphicsContext& context) const
{
#if ENABLE(INLINE_PATH_DATA)
auto path = Path::from(InlinePathData { LineData { start(), end() } });
#else
Path path;
path.moveTo(start());
path.addLineTo(end());
#endif
context.strokePath(path);
}
static TextStream& operator<<(TextStream& ts, const StrokeLine& item)
{
ts.dumpProperty("start", item.start());
ts.dumpProperty("end", item.end());
return ts;
}
#if ENABLE(INLINE_PATH_DATA)
std::optional<FloatRect> StrokeArc::localBounds(const GraphicsContext& context) const
{
// FIXME: Need to take stroke thickness into account correctly, via CGPathByStrokingPath().
float strokeThickness = context.strokeThickness();
auto bounds = path().fastBoundingRect();
bounds.expand(strokeThickness, strokeThickness);
return bounds;
}
void StrokeArc::apply(GraphicsContext& context) const
{
context.strokePath(path());
}
static TextStream& operator<<(TextStream& ts, const StrokeArc& item)
{
ts.dumpProperty("path", item.path());
return ts;
}
std::optional<FloatRect> StrokeQuadCurve::localBounds(const GraphicsContext& context) const
{
// FIXME: Need to take stroke thickness into account correctly, via CGPathByStrokingPath().
float strokeThickness = context.strokeThickness();
auto bounds = path().fastBoundingRect();
bounds.expand(strokeThickness, strokeThickness);
return bounds;
}
void StrokeQuadCurve::apply(GraphicsContext& context) const
{
context.strokePath(path());
}
static TextStream& operator<<(TextStream& ts, const StrokeQuadCurve& item)
{
ts.dumpProperty("path", item.path());
return ts;
}
std::optional<FloatRect> StrokeBezierCurve::localBounds(const GraphicsContext& context) const
{
// FIXME: Need to take stroke thickness into account correctly, via CGPathByStrokingPath().
float strokeThickness = context.strokeThickness();
auto bounds = path().fastBoundingRect();
bounds.expand(strokeThickness, strokeThickness);
return bounds;
}
void StrokeBezierCurve::apply(GraphicsContext& context) const
{
context.strokePath(path());
}
static TextStream& operator<<(TextStream& ts, const StrokeBezierCurve& item)
{
ts.dumpProperty("path", item.path());
return ts;
}
#endif // ENABLE(INLINE_PATH_DATA)
void ClearRect::apply(GraphicsContext& context) const
{
context.clearRect(m_rect);
}
static TextStream& operator<<(TextStream& ts, const ClearRect& item)
{
ts.dumpProperty("rect", item.rect());
return ts;
}
void BeginTransparencyLayer::apply(GraphicsContext& context) const
{
context.beginTransparencyLayer(m_opacity);
}
static TextStream& operator<<(TextStream& ts, const BeginTransparencyLayer& item)
{
ts.dumpProperty("opacity", item.opacity());
return ts;
}
void EndTransparencyLayer::apply(GraphicsContext& context) const
{
if (context.isInTransparencyLayer())
context.endTransparencyLayer();
}
#if USE(CG)
void ApplyStrokePattern::apply(GraphicsContext& context) const
{
context.applyStrokePattern();
}
void ApplyFillPattern::apply(GraphicsContext& context) const
{
context.applyFillPattern();
}
#endif
void ApplyDeviceScaleFactor::apply(GraphicsContext& context) const
{
context.applyDeviceScaleFactor(m_scaleFactor);
}
static TextStream& operator<<(TextStream& ts, const ApplyDeviceScaleFactor& item)
{
ts.dumpProperty("scale-factor", item.scaleFactor());
return ts;
}
void FlushContext::apply(GraphicsContext&) const
{
// Handled by client.
}
static TextStream& operator<<(TextStream& ts, const FlushContext& item)
{
ts.dumpProperty("identifier", item.identifier());
return ts;
}
static TextStream& operator<<(TextStream& ts, ItemType type)
{
switch (type) {
case ItemType::Save: ts << "save"; break;
case ItemType::Restore: ts << "restore"; break;
case ItemType::Translate: ts << "translate"; break;
case ItemType::Rotate: ts << "rotate"; break;
case ItemType::Scale: ts << "scale"; break;
case ItemType::SetCTM: ts << "set-ctm"; break;
case ItemType::ConcatenateCTM: ts << "concatentate-ctm"; break;
case ItemType::SetInlineFillColor: ts << "set-inline-fill-color"; break;
case ItemType::SetInlineStrokeColor: ts << "set-inline-stroke-color"; break;
case ItemType::SetStrokeThickness: ts << "set-stroke-thickness"; break;
case ItemType::SetState: ts << "set-state"; break;
case ItemType::SetLineCap: ts << "set-line-cap"; break;
case ItemType::SetLineDash: ts << "set-line-dash"; break;
case ItemType::SetLineJoin: ts << "set-line-join"; break;
case ItemType::SetMiterLimit: ts << "set-miter-limit"; break;
case ItemType::Clip: ts << "clip"; break;
case ItemType::ClipOut: ts << "clip-out"; break;
case ItemType::ClipToImageBuffer: ts << "clip-to-image-buffer"; break;
case ItemType::ClipOutToPath: ts << "clip-out-to-path"; break;
case ItemType::ClipPath: ts << "clip-path"; break;
case ItemType::BeginClipToDrawingCommands: ts << "begin-clip-to-drawing-commands:"; break;
case ItemType::EndClipToDrawingCommands: ts << "end-clip-to-drawing-commands"; break;
case ItemType::DrawGlyphs: ts << "draw-glyphs"; break;
case ItemType::DrawImageBuffer: ts << "draw-image-buffer"; break;
case ItemType::DrawNativeImage: ts << "draw-native-image"; break;
case ItemType::DrawPattern: ts << "draw-pattern"; break;
case ItemType::DrawRect: ts << "draw-rect"; break;
case ItemType::DrawLine: ts << "draw-line"; break;
case ItemType::DrawLinesForText: ts << "draw-lines-for-text"; break;
case ItemType::DrawDotsForDocumentMarker: ts << "draw-dots-for-document-marker"; break;
case ItemType::DrawEllipse: ts << "draw-ellipse"; break;
case ItemType::DrawPath: ts << "draw-path"; break;
case ItemType::DrawFocusRingPath: ts << "draw-focus-ring-path"; break;
case ItemType::DrawFocusRingRects: ts << "draw-focus-ring-rects"; break;
case ItemType::FillRect: ts << "fill-rect"; break;
case ItemType::FillRectWithColor: ts << "fill-rect-with-color"; break;
case ItemType::FillRectWithGradient: ts << "fill-rect-with-gradient"; break;
case ItemType::FillCompositedRect: ts << "fill-composited-rect"; break;
case ItemType::FillRoundedRect: ts << "fill-rounded-rect"; break;
case ItemType::FillRectWithRoundedHole: ts << "fill-rect-with-rounded-hole"; break;
#if ENABLE(INLINE_PATH_DATA)
case ItemType::FillLine: ts << "fill-line"; break;
case ItemType::FillArc: ts << "fill-arc"; break;
case ItemType::FillQuadCurve: ts << "fill-quad-curve"; break;
case ItemType::FillBezierCurve: ts << "fill-bezier-curve"; break;
#endif
case ItemType::FillPath: ts << "fill-path"; break;
case ItemType::FillEllipse: ts << "fill-ellipse"; break;
case ItemType::FlushContext: ts << "flush-context"; break;
case ItemType::GetPixelBuffer: ts << "get-pixel-buffer"; break;
case ItemType::PutPixelBuffer: ts << "put-pixel-buffer"; break;
#if ENABLE(VIDEO)
case ItemType::PaintFrameForMedia: ts << "paint-frame-for-media"; break;
#endif
case ItemType::StrokeRect: ts << "stroke-rect"; break;
case ItemType::StrokeLine: ts << "stroke-line"; break;
#if ENABLE(INLINE_PATH_DATA)
case ItemType::StrokeArc: ts << "stroke-arc"; break;
case ItemType::StrokeQuadCurve: ts << "stroke-quad-curve"; break;
case ItemType::StrokeBezierCurve: ts << "stroke-bezier-curve"; break;
#endif
case ItemType::StrokePath: ts << "stroke-path"; break;
case ItemType::StrokeEllipse: ts << "stroke-ellipse"; break;
case ItemType::ClearRect: ts << "clear-rect"; break;
case ItemType::BeginTransparencyLayer: ts << "begin-transparency-layer"; break;
case ItemType::EndTransparencyLayer: ts << "end-transparency-layer"; break;
#if USE(CG)
case ItemType::ApplyStrokePattern: ts << "apply-stroke-pattern"; break;
case ItemType::ApplyFillPattern: ts << "apply-fill-pattern"; break;
#endif
case ItemType::ApplyDeviceScaleFactor: ts << "apply-device-scale-factor"; break;
case ItemType::ClearShadow: ts << "clear-shadow"; break;
}
return ts;
}
TextStream& operator<<(TextStream& ts, ItemHandle item)
{
ts << item.type();
switch (item.type()) {
case ItemType::Translate:
ts << item.get<Translate>();
break;
case ItemType::Rotate:
ts << item.get<Rotate>();
break;
case ItemType::Scale:
ts << item.get<Scale>();
break;
case ItemType::SetCTM:
ts << item.get<SetCTM>();
break;
case ItemType::ConcatenateCTM:
ts << item.get<ConcatenateCTM>();
break;
case ItemType::SetInlineFillColor:
ts << item.get<SetInlineFillColor>();
break;
case ItemType::SetInlineStrokeColor:
ts << item.get<SetInlineStrokeColor>();
break;
case ItemType::SetStrokeThickness:
ts << item.get<SetStrokeThickness>();
break;
case ItemType::SetState:
ts << item.get<SetState>();
break;
case ItemType::SetLineCap:
ts << item.get<SetLineCap>();
break;
case ItemType::SetLineDash:
ts << item.get<SetLineDash>();
break;
case ItemType::SetLineJoin:
ts << item.get<SetLineJoin>();
break;
case ItemType::SetMiterLimit:
ts << item.get<SetMiterLimit>();
break;
case ItemType::Clip:
ts << item.get<Clip>();
break;
case ItemType::ClipOut:
ts << item.get<ClipOut>();
break;
case ItemType::ClipToImageBuffer:
ts << item.get<ClipToImageBuffer>();
break;
case ItemType::ClipOutToPath:
ts << item.get<ClipOutToPath>();
break;
case ItemType::ClipPath:
ts << item.get<ClipPath>();
break;
case ItemType::BeginClipToDrawingCommands:
ts << item.get<BeginClipToDrawingCommands>();
break;
case ItemType::EndClipToDrawingCommands:
ts << item.get<EndClipToDrawingCommands>();
break;
case ItemType::DrawGlyphs:
ts << item.get<DrawGlyphs>();
break;
case ItemType::DrawImageBuffer:
ts << item.get<DrawImageBuffer>();
break;
case ItemType::DrawNativeImage:
ts << item.get<DrawNativeImage>();
break;
case ItemType::DrawPattern:
ts << item.get<DrawPattern>();
break;
case ItemType::DrawRect:
ts << item.get<DrawRect>();
break;
case ItemType::DrawLine:
ts << item.get<DrawLine>();
break;
case ItemType::DrawLinesForText:
ts << item.get<DrawLinesForText>();
break;
case ItemType::DrawDotsForDocumentMarker:
ts << item.get<DrawDotsForDocumentMarker>();
break;
case ItemType::DrawEllipse:
ts << item.get<DrawEllipse>();
break;
case ItemType::DrawPath:
ts << item.get<DrawPath>();
break;
case ItemType::DrawFocusRingPath:
ts << item.get<DrawFocusRingPath>();
break;
case ItemType::DrawFocusRingRects:
ts << item.get<DrawFocusRingRects>();
break;
case ItemType::FillRect:
ts << item.get<FillRect>();
break;
case ItemType::FillRectWithColor:
ts << item.get<FillRectWithColor>();
break;
case ItemType::FillRectWithGradient:
ts << item.get<FillRectWithGradient>();
break;
case ItemType::FillCompositedRect:
ts << item.get<FillCompositedRect>();
break;
case ItemType::FillRoundedRect:
ts << item.get<FillRoundedRect>();
break;
case ItemType::FillRectWithRoundedHole:
ts << item.get<FillRectWithRoundedHole>();
break;
#if ENABLE(INLINE_PATH_DATA)
case ItemType::FillLine:
ts << item.get<FillLine>();
break;
case ItemType::FillArc:
ts << item.get<FillArc>();
break;
case ItemType::FillQuadCurve:
ts << item.get<FillQuadCurve>();
break;
case ItemType::FillBezierCurve:
ts << item.get<FillBezierCurve>();
break;
#endif
case ItemType::FillPath:
ts << item.get<FillPath>();
break;
case ItemType::FillEllipse:
ts << item.get<FillEllipse>();
break;
case ItemType::FlushContext:
ts << item.get<FlushContext>();
break;
case ItemType::GetPixelBuffer:
ts << item.get<GetPixelBuffer>();
break;
case ItemType::PutPixelBuffer:
ts << item.get<PutPixelBuffer>();
break;
#if ENABLE(VIDEO)
case ItemType::PaintFrameForMedia:
ts << item.get<PaintFrameForMedia>();
break;
#endif
case ItemType::StrokeRect:
ts << item.get<StrokeRect>();
break;
case ItemType::StrokeLine:
ts << item.get<StrokeLine>();
break;
#if ENABLE(INLINE_PATH_DATA)
case ItemType::StrokeArc:
ts << item.get<StrokeArc>();
break;
case ItemType::StrokeQuadCurve:
ts << item.get<StrokeQuadCurve>();
break;
case ItemType::StrokeBezierCurve:
ts << item.get<StrokeBezierCurve>();
break;
#endif
case ItemType::StrokePath:
ts << item.get<StrokePath>();
break;
case ItemType::StrokeEllipse:
ts << item.get<StrokeEllipse>();
break;
case ItemType::ClearRect:
ts << item.get<ClearRect>();
break;
case ItemType::BeginTransparencyLayer:
ts << item.get<BeginTransparencyLayer>();
break;
case ItemType::ApplyDeviceScaleFactor:
ts << item.get<ApplyDeviceScaleFactor>();
break;
// Items with no additional data.
case ItemType::Save:
case ItemType::Restore:
case ItemType::EndTransparencyLayer:
#if USE(CG)
case ItemType::ApplyStrokePattern:
case ItemType::ApplyFillPattern:
#endif
case ItemType::ClearShadow:
break;
}
return ts;
}
}
}