7353d37afb1c1563260c190dabe913bcc4371615
[WebKit-https.git] / Source / WebCore / platform / graphics / displaylists / DisplayListItems.cpp
1 /*
2  * Copyright (C) 2015 Apple Inc. All rights reserved.
3  *
4  * Redistribution and use in source and binary forms, with or without
5  * modification, are permitted provided that the following conditions
6  * are met:
7  * 1. Redistributions of source code must retain the above copyright
8  *    notice, this list of conditions and the following disclaimer.
9  * 2. Redistributions in binary form must reproduce the above copyright
10  *    notice, this list of conditions and the following disclaimer in the
11  *    documentation and/or other materials provided with the distribution.
12  *
13  * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
14  * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
15  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
16  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL APPLE INC. OR
17  * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
18  * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
19  * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
20  * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
21  * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
22  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
23  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 
24  */
25
26 #include "config.h"
27 #include "DisplayListItems.h"
28
29 #include "FontCascade.h"
30 #include <wtf/text/TextStream.h>
31
32 namespace WebCore {
33 namespace DisplayList {
34
35 // Should match RenderTheme::platformFocusRingWidth()
36 static const float platformFocusRingWidth = 3;
37
38 #if !defined(NDEBUG) || !LOG_DISABLED
39 WTF::CString Item::description() const
40 {
41     TextStream ts;
42     ts << *this;
43     return ts.release().utf8();
44 }
45 #endif
46
47 size_t Item::sizeInBytes(const Item& item)
48 {
49     switch (item.type()) {
50     case ItemType::Save:
51         return sizeof(downcast<Save>(item));
52     case ItemType::Restore:
53         return sizeof(downcast<Restore>(item));
54     case ItemType::Translate:
55         return sizeof(downcast<Translate>(item));
56     case ItemType::Rotate:
57         return sizeof(downcast<Rotate>(item));
58     case ItemType::Scale:
59         return sizeof(downcast<Scale>(item));
60     case ItemType::ConcatenateCTM:
61         return sizeof(downcast<ConcatenateCTM>(item));
62     case ItemType::SetState:
63         return sizeof(downcast<SetState>(item));
64     case ItemType::SetLineCap:
65         return sizeof(downcast<SetLineCap>(item));
66     case ItemType::SetLineDash:
67         return sizeof(downcast<SetLineDash>(item));
68     case ItemType::SetLineJoin:
69         return sizeof(downcast<SetLineJoin>(item));
70     case ItemType::SetMiterLimit:
71         return sizeof(downcast<SetMiterLimit>(item));
72     case ItemType::ClearShadow:
73         return sizeof(downcast<ClearShadow>(item));
74     case ItemType::Clip:
75         return sizeof(downcast<Clip>(item));
76     case ItemType::ClipOut:
77         return sizeof(downcast<ClipOut>(item));
78     case ItemType::ClipOutToPath:
79         return sizeof(downcast<ClipOutToPath>(item));
80     case ItemType::ClipPath:
81         return sizeof(downcast<ClipPath>(item));
82     case ItemType::DrawGlyphs:
83         return sizeof(downcast<DrawGlyphs>(item));
84     case ItemType::DrawImage:
85         return sizeof(downcast<DrawImage>(item));
86     case ItemType::DrawTiledImage:
87         return sizeof(downcast<DrawTiledImage>(item));
88     case ItemType::DrawTiledScaledImage:
89         return sizeof(downcast<DrawTiledScaledImage>(item));
90 #if USE(CG) || USE(CAIRO)
91     case ItemType::DrawNativeImage:
92         return sizeof(downcast<DrawNativeImage>(item));
93 #endif
94     case ItemType::DrawPattern:
95         return sizeof(downcast<DrawPattern>(item));
96     case ItemType::DrawRect:
97         return sizeof(downcast<DrawRect>(item));
98     case ItemType::DrawLine:
99         return sizeof(downcast<DrawLine>(item));
100     case ItemType::DrawLinesForText:
101         return sizeof(downcast<DrawLinesForText>(item));
102     case ItemType::DrawDotsForDocumentMarker:
103         return sizeof(downcast<DrawDotsForDocumentMarker>(item));
104     case ItemType::DrawEllipse:
105         return sizeof(downcast<DrawEllipse>(item));
106     case ItemType::DrawPath:
107         return sizeof(downcast<DrawPath>(item));
108     case ItemType::DrawFocusRingPath:
109         return sizeof(downcast<DrawFocusRingPath>(item));
110     case ItemType::DrawFocusRingRects:
111         return sizeof(downcast<DrawFocusRingRects>(item));
112     case ItemType::FillRect:
113         return sizeof(downcast<FillRect>(item));
114     case ItemType::FillRectWithColor:
115         return sizeof(downcast<FillRectWithColor>(item));
116     case ItemType::FillRectWithGradient:
117         return sizeof(downcast<FillRectWithGradient>(item));
118     case ItemType::FillCompositedRect:
119         return sizeof(downcast<FillCompositedRect>(item));
120     case ItemType::FillRoundedRect:
121         return sizeof(downcast<FillRoundedRect>(item));
122     case ItemType::FillRectWithRoundedHole:
123         return sizeof(downcast<FillRectWithRoundedHole>(item));
124     case ItemType::FillPath:
125         return sizeof(downcast<FillPath>(item));
126     case ItemType::FillEllipse:
127         return sizeof(downcast<FillEllipse>(item));
128     case ItemType::StrokeRect:
129         return sizeof(downcast<StrokeRect>(item));
130     case ItemType::StrokePath:
131         return sizeof(downcast<StrokePath>(item));
132     case ItemType::StrokeEllipse:
133         return sizeof(downcast<StrokeEllipse>(item));
134     case ItemType::ClearRect:
135         return sizeof(downcast<ClearRect>(item));
136     case ItemType::BeginTransparencyLayer:
137         return sizeof(downcast<BeginTransparencyLayer>(item));
138     case ItemType::EndTransparencyLayer:
139         return sizeof(downcast<EndTransparencyLayer>(item));
140 #if USE(CG)
141     case ItemType::ApplyStrokePattern:
142         return sizeof(downcast<ApplyStrokePattern>(item));
143     case ItemType::ApplyFillPattern:
144         return sizeof(downcast<ApplyFillPattern>(item));
145 #endif
146     case ItemType::ApplyDeviceScaleFactor:
147         return sizeof(downcast<ApplyDeviceScaleFactor>(item));
148     }
149     return 0;
150 }
151
152 static TextStream& operator<<(TextStream& ts, const DrawingItem& item)
153 {
154     ts.startGroup();
155     ts << "extent ";
156     if (item.extentKnown())
157         ts << item.extent();
158     else
159         ts << "unknown";
160     
161     ts.endGroup();
162     return ts;
163 }
164
165 void Save::apply(GraphicsContext& context) const
166 {
167     context.save();
168 }
169
170 static TextStream& operator<<(TextStream& ts, const Save& item)
171 {
172     ts.dumpProperty("restore-index", item.restoreIndex());
173     return ts;
174 }
175
176 void Restore::apply(GraphicsContext& context) const
177 {
178     context.restore();
179 }
180
181 void Translate::apply(GraphicsContext& context) const
182 {
183     context.translate(m_x, m_y);
184 }
185
186 static TextStream& operator<<(TextStream& ts, const Translate& item)
187 {
188     ts.dumpProperty("x", item.x());
189     ts.dumpProperty("y", item.y());
190
191     return ts;
192 }
193
194 void Rotate::apply(GraphicsContext& context) const
195 {
196     context.rotate(m_angle);
197 }
198
199 static TextStream& operator<<(TextStream& ts, const Rotate& item)
200 {
201     ts.dumpProperty("angle", item.angle());
202
203     return ts;
204 }
205
206 void Scale::apply(GraphicsContext& context) const
207 {
208     context.scale(m_size);
209 }
210
211 static TextStream& operator<<(TextStream& ts, const Scale& item)
212 {
213     ts.dumpProperty("size", item.amount());
214
215     return ts;
216 }
217
218 ConcatenateCTM::ConcatenateCTM(const AffineTransform& transform)
219     : Item(ItemType::ConcatenateCTM)
220     , m_transform(transform)
221 {
222 }
223
224 void ConcatenateCTM::apply(GraphicsContext& context) const
225 {
226     context.concatCTM(m_transform);
227 }
228
229 static TextStream& operator<<(TextStream& ts, const ConcatenateCTM& item)
230 {
231     ts.dumpProperty("ctm", item.transform());
232
233     return ts;
234 }
235
236 void SetState::apply(GraphicsContext& context) const
237 {
238     m_state.apply(context);
239 }
240
241 void SetState::accumulate(const GraphicsContextState& state, GraphicsContextState::StateChangeFlags flags)
242 {
243     m_state.accumulate(state, flags);
244 }
245
246 static TextStream& operator<<(TextStream& ts, const SetState& state)
247 {
248     ts << state.state();
249     return ts;
250 }
251
252 void SetLineCap::apply(GraphicsContext& context) const
253 {
254     context.setLineCap(m_lineCap);
255 }
256
257 static TextStream& operator<<(TextStream& ts, const SetLineCap& lineCap)
258 {
259     ts.dumpProperty("line-cap", lineCap.lineCap());
260     return ts;
261 }
262
263 void SetLineDash::apply(GraphicsContext& context) const
264 {
265     context.setLineDash(m_dashArray, m_dashOffset);
266 }
267
268 static TextStream& operator<<(TextStream& ts, const SetLineDash& lineDash)
269 {
270     ts.dumpProperty("dash-array", lineDash.dashArray());
271     ts.dumpProperty("dash-offset", lineDash.dashOffset());
272     return ts;
273 }
274
275 void SetLineJoin::apply(GraphicsContext& context) const
276 {
277     context.setLineJoin(m_lineJoin);
278 }
279
280 static TextStream& operator<<(TextStream& ts, const SetLineJoin& lineJoin)
281 {
282     ts.dumpProperty("line-join", lineJoin.lineJoin());
283     return ts;
284 }
285
286 void SetMiterLimit::apply(GraphicsContext& context) const
287 {
288     context.setMiterLimit(m_miterLimit);
289 }
290
291 static TextStream& operator<<(TextStream& ts, const SetMiterLimit& miterLimit)
292 {
293     ts.dumpProperty("mitre-limit", miterLimit.miterLimit());
294     return ts;
295 }
296
297 void ClearShadow::apply(GraphicsContext& context) const
298 {
299     context.clearShadow();
300 }
301
302 void Clip::apply(GraphicsContext& context) const
303 {
304     context.clip(m_rect);
305 }
306
307 static TextStream& operator<<(TextStream& ts, const Clip& item)
308 {
309     ts.dumpProperty("rect", item.rect());
310     return ts;
311 }
312
313 void ClipOut::apply(GraphicsContext& context) const
314 {
315     context.clipOut(m_rect);
316 }
317
318 static TextStream& operator<<(TextStream& ts, const ClipOut& item)
319 {
320     ts.dumpProperty("rect", item.rect());
321     return ts;
322 }
323
324 void ClipOutToPath::apply(GraphicsContext& context) const
325 {
326     context.clipOut(m_path);
327 }
328
329 static TextStream& operator<<(TextStream& ts, const ClipOutToPath& item)
330 {
331     ts.dumpProperty("path", item.path());
332     return ts;
333 }
334
335 void ClipPath::apply(GraphicsContext& context) const
336 {
337     context.clipPath(m_path, m_windRule);
338 }
339
340 static TextStream& operator<<(TextStream& ts, const ClipPath& item)
341 {
342     ts.dumpProperty("path", item.path());
343     ts.dumpProperty("wind-rule", item.windRule());
344     return ts;
345 }
346
347 DrawGlyphs::DrawGlyphs(const Font& font, const GlyphBufferGlyph* glyphs, const GlyphBufferAdvance* advances, unsigned count, const FloatPoint& blockLocation, const FloatSize& localAnchor, FontSmoothingMode smoothingMode)
348     : DrawingItem(ItemType::DrawGlyphs)
349     , m_font(const_cast<Font&>(font))
350     , m_blockLocation(blockLocation)
351     , m_localAnchor(localAnchor)
352     , m_smoothingMode(smoothingMode)
353 {
354     m_glyphs.reserveInitialCapacity(count);
355     m_advances.reserveInitialCapacity(count);
356     for (unsigned i = 0; i < count; ++i) {
357         m_glyphs.uncheckedAppend(glyphs[i]);
358         m_advances.uncheckedAppend(advances[i]);
359     }
360     computeBounds();
361 }
362
363 inline GlyphBuffer DrawGlyphs::generateGlyphBuffer() const
364 {
365     GlyphBuffer result;
366     for (size_t i = 0; i < m_glyphs.size(); ++i) {
367         result.add(m_glyphs[i], &m_font.get(), m_advances[i]);
368     }
369     return result;
370 }
371
372 void DrawGlyphs::apply(GraphicsContext& context) const
373 {
374     context.drawGlyphs(m_font, generateGlyphBuffer(), 0, m_glyphs.size(), anchorPoint(), m_smoothingMode);
375 }
376
377 void DrawGlyphs::computeBounds()
378 {
379     // FIXME: This code doesn't actually take the extents of the glyphs into consideration. It assumes that
380     // the glyph lies entirely within its [(ascent + descent), advance] rect.
381     float ascent = m_font->fontMetrics().floatAscent();
382     float descent = m_font->fontMetrics().floatDescent();
383     FloatPoint current = toFloatPoint(localAnchor());
384     size_t numGlyphs = m_glyphs.size();
385     for (size_t i = 0; i < numGlyphs; ++i) {
386         GlyphBufferAdvance advance = m_advances[i];
387         FloatRect glyphRect = FloatRect(current.x(), current.y() - ascent, advance.width(), ascent + descent);
388         m_bounds.unite(glyphRect);
389
390         current.move(advance.width(), advance.height());
391     }
392 }
393
394 std::optional<FloatRect> DrawGlyphs::localBounds(const GraphicsContext&) const
395 {
396     FloatRect localBounds = m_bounds;
397     localBounds.move(m_blockLocation.x(), m_blockLocation.y());
398     return localBounds;
399 }
400
401 static TextStream& operator<<(TextStream& ts, const DrawGlyphs& item)
402 {
403     ts << static_cast<const DrawingItem&>(item);
404     // FIXME: dump more stuff.
405     ts.dumpProperty("block-location", item.blockLocation());
406     ts.dumpProperty("local-anchor", item.localAnchor());
407     ts.dumpProperty("anchor-point", item.anchorPoint());
408     ts.dumpProperty("length", item.glyphs().size());
409
410     return ts;
411 }
412
413 DrawImage::DrawImage(Image& image, const FloatRect& destination, const FloatRect& source, const ImagePaintingOptions& imagePaintingOptions)
414     : DrawingItem(ItemType::DrawImage)
415     , m_image(image)
416     , m_destination(destination)
417     , m_source(source)
418     , m_imagePaintingOptions(imagePaintingOptions)
419 {
420 }
421
422 void DrawImage::apply(GraphicsContext& context) const
423 {
424     context.drawImage(m_image.get(), m_destination, m_source, m_imagePaintingOptions);
425 }
426
427 static TextStream& operator<<(TextStream& ts, const DrawImage& item)
428 {
429     ts << static_cast<const DrawingItem&>(item);
430     ts.dumpProperty("image", item.image());
431     ts.dumpProperty("source-rect", item.source());
432     ts.dumpProperty("dest-rect", item.destination());
433     return ts;
434 }
435
436 DrawTiledImage::DrawTiledImage(Image& image, const FloatRect& destination, const FloatPoint& source, const FloatSize& tileSize, const FloatSize& spacing, const ImagePaintingOptions& imagePaintingOptions)
437     : DrawingItem(ItemType::DrawTiledImage)
438     , m_image(image)
439     , m_destination(destination)
440     , m_source(source)
441     , m_tileSize(tileSize)
442     , m_spacing(spacing)
443     , m_imagePaintingOptions(imagePaintingOptions)
444 {
445 }
446
447 void DrawTiledImage::apply(GraphicsContext& context) const
448 {
449     context.drawTiledImage(m_image.get(), m_destination, m_source, m_tileSize, m_spacing, m_imagePaintingOptions);
450 }
451
452 static TextStream& operator<<(TextStream& ts, const DrawTiledImage& item)
453 {
454     ts << static_cast<const DrawingItem&>(item);
455     ts.dumpProperty("image", item.image());
456     ts.dumpProperty("source-point", item.source());
457     ts.dumpProperty("dest-rect", item.destination());
458     ts.dumpProperty("tile-size", item.tileSize());
459     ts.dumpProperty("spacing", item.spacing());
460     return ts;
461 }
462
463 DrawTiledScaledImage::DrawTiledScaledImage(Image& image, const FloatRect& destination, const FloatRect& source, const FloatSize& tileScaleFactor, Image::TileRule hRule, Image::TileRule vRule, const ImagePaintingOptions& imagePaintingOptions)
464     : DrawingItem(ItemType::DrawTiledScaledImage)
465     , m_image(image)
466     , m_destination(destination)
467     , m_source(source)
468     , m_tileScaleFactor(tileScaleFactor)
469     , m_hRule(hRule)
470     , m_vRule(vRule)
471     , m_imagePaintingOptions(imagePaintingOptions)
472 {
473 }
474
475 void DrawTiledScaledImage::apply(GraphicsContext& context) const
476 {
477     context.drawTiledImage(m_image.get(), m_destination, m_source, m_tileScaleFactor, m_hRule, m_vRule, m_imagePaintingOptions);
478 }
479
480 static TextStream& operator<<(TextStream& ts, const DrawTiledScaledImage& item)
481 {
482     ts << static_cast<const DrawingItem&>(item);
483     ts.dumpProperty("image", item.image());
484     ts.dumpProperty("source-rect", item.source());
485     ts.dumpProperty("dest-rect", item.destination());
486     return ts;
487 }
488
489 #if USE(CG) || USE(CAIRO)
490 DrawNativeImage::DrawNativeImage(const NativeImagePtr& image, const FloatSize& imageSize, const FloatRect& destRect, const FloatRect& srcRect, CompositeOperator op, BlendMode blendMode, ImageOrientation orientation)
491     : DrawingItem(ItemType::DrawNativeImage)
492 #if USE(CG)
493     // FIXME: Need to store an image for Cairo.
494     , m_image(image)
495 #endif
496     , m_imageSize(imageSize)
497     , m_destination(destRect)
498     , m_srcRect(srcRect)
499 #if USE(CG)
500     , m_op(op)
501     , m_blendMode(blendMode)
502 #endif
503     , m_orientation(orientation)
504 {
505 #if !USE(CG)
506     UNUSED_PARAM(image);
507     UNUSED_PARAM(op);
508     UNUSED_PARAM(blendMode);
509 #endif
510 }
511
512 void DrawNativeImage::apply(GraphicsContext& context) const
513 {
514 #if USE(CG)
515     context.drawNativeImage(m_image, m_imageSize, m_destination, m_srcRect, m_op, m_blendMode, m_orientation);
516 #else
517     UNUSED_PARAM(context);
518 #endif
519 }
520
521 static TextStream& operator<<(TextStream& ts, const DrawNativeImage& item)
522 {
523     ts << static_cast<const DrawingItem&>(item);
524     // FIXME: dump more stuff.
525     ts.dumpProperty("source-rect", item.source());
526     ts.dumpProperty("dest-rect", item.destination());
527     return ts;
528 }
529 #endif
530
531 DrawPattern::DrawPattern(Image& image, const FloatRect& destRect, const FloatRect& tileRect, const AffineTransform& patternTransform, const FloatPoint& phase, const FloatSize& spacing, CompositeOperator op, BlendMode blendMode)
532     : DrawingItem(ItemType::DrawPattern)
533     , m_image(image)
534     , m_patternTransform(patternTransform)
535     , m_tileRect(tileRect)
536     , m_destination(destRect)
537     , m_phase(phase)
538     , m_spacing(spacing)
539     , m_op(op)
540     , m_blendMode(blendMode)
541 {
542 }
543
544 void DrawPattern::apply(GraphicsContext& context) const
545 {
546     context.drawPattern(m_image.get(), m_destination, m_tileRect, m_patternTransform, m_phase, m_spacing, m_op, m_blendMode);
547 }
548
549 static TextStream& operator<<(TextStream& ts, const DrawPattern& item)
550 {
551     ts << static_cast<const DrawingItem&>(item);
552     ts.dumpProperty("image", item.image());
553     ts.dumpProperty("pattern-transform", item.patternTransform());
554     ts.dumpProperty("tile-rect", item.tileRect());
555     ts.dumpProperty("dest-rect", item.destRect());
556     ts.dumpProperty("phase", item.phase());
557     ts.dumpProperty("spacing", item.spacing());
558     return ts;
559 }
560
561 void DrawRect::apply(GraphicsContext& context) const
562 {
563     context.drawRect(m_rect, m_borderThickness);
564 }
565
566 static TextStream& operator<<(TextStream& ts, const DrawRect& item)
567 {
568     ts << static_cast<const DrawingItem&>(item);
569     ts.dumpProperty("rect", item.rect());
570     ts.dumpProperty("border-thickness", item.borderThickness());
571     return ts;
572 }
573
574 std::optional<FloatRect> DrawLine::localBounds(const GraphicsContext&) const
575 {
576     FloatRect bounds;
577     bounds.fitToPoints(m_point1, m_point2);
578     return bounds;
579 }
580
581 void DrawLine::apply(GraphicsContext& context) const
582 {
583     context.drawLine(m_point1, m_point2);
584 }
585
586 static TextStream& operator<<(TextStream& ts, const DrawLine& item)
587 {
588     ts << static_cast<const DrawingItem&>(item);
589     ts.dumpProperty("point-1", item.point1());
590     ts.dumpProperty("point-2", item.point2());
591     return ts;
592 }
593
594 void DrawLinesForText::apply(GraphicsContext& context) const
595 {
596     context.drawLinesForText(point(), m_widths, m_printing, m_doubleLines);
597 }
598
599 std::optional<FloatRect> DrawLinesForText::localBounds(const GraphicsContext&) const
600 {
601     // This function needs to return a value equal to or enclosing what GraphicsContext::computeLineBoundsAndAntialiasingModeForText() returns.
602
603     if (!m_widths.size())
604         return FloatRect();
605
606     FloatRect result(point(), FloatSize(m_widths.last(), m_strokeWidth));
607     result.inflate(1); // Account for pixel snapping. FIXME: This isn't perfect, as it doesn't take the CTM into account.
608     return result;
609 }
610
611 static TextStream& operator<<(TextStream& ts, const DrawLinesForText& item)
612 {
613     ts << static_cast<const DrawingItem&>(item);
614     ts.dumpProperty("block-location", item.blockLocation());
615     ts.dumpProperty("local-anchor", item.localAnchor());
616     ts.dumpProperty("point", item.point());
617     ts.dumpProperty("double", item.doubleLines());
618     ts.dumpProperty("widths", item.widths());
619     ts.dumpProperty("is-printing", item.isPrinting());
620     ts.dumpProperty("double", item.doubleLines());
621     return ts;
622 }
623
624 void DrawDotsForDocumentMarker::apply(GraphicsContext& context) const
625 {
626     context.drawDotsForDocumentMarker(m_rect, m_style);
627 }
628
629 std::optional<FloatRect> DrawDotsForDocumentMarker::localBounds(const GraphicsContext&) const
630 {
631     return m_rect;
632 }
633
634 static TextStream& operator<<(TextStream& ts, const DrawDotsForDocumentMarker& item)
635 {
636     ts << static_cast<const DrawingItem&>(item);
637     ts.dumpProperty("rect", item.rect());
638     return ts;
639 }
640
641 void DrawEllipse::apply(GraphicsContext& context) const
642 {
643     context.drawEllipse(m_rect);
644 }
645
646 static TextStream& operator<<(TextStream& ts, const DrawEllipse& item)
647 {
648     ts.dumpProperty("rect", item.rect());
649     return ts;
650 }
651
652 void DrawPath::apply(GraphicsContext& context) const
653 {
654 #if USE(CG)
655     context.drawPath(m_path);
656 #else
657     UNUSED_PARAM(context);
658 #endif
659 }
660
661 static TextStream& operator<<(TextStream& ts, const DrawPath& item)
662 {
663     ts << static_cast<const DrawingItem&>(item);
664 //    ts.dumpProperty("path", item.path()); // FIXME: add logging for paths.
665     return ts;
666 }
667
668 void DrawFocusRingPath::apply(GraphicsContext& context) const
669 {
670     context.drawFocusRing(m_path, m_width, m_offset, m_color);
671 }
672
673 std::optional<FloatRect> DrawFocusRingPath::localBounds(const GraphicsContext&) const
674 {
675     FloatRect result = m_path.fastBoundingRect();
676     result.inflate(platformFocusRingWidth);
677     return result;
678 }
679
680 static TextStream& operator<<(TextStream& ts, const DrawFocusRingPath& item)
681 {
682     ts << static_cast<const DrawingItem&>(item);
683 //    ts.dumpProperty("path", item.path()); // FIXME: add logging for paths.
684     ts.dumpProperty("width", item.width());
685     ts.dumpProperty("offset", item.offset());
686     ts.dumpProperty("color", item.color());
687     return ts;
688 }
689
690 void DrawFocusRingRects::apply(GraphicsContext& context) const
691 {
692     context.drawFocusRing(m_rects, m_width, m_offset, m_color);
693 }
694
695 std::optional<FloatRect> DrawFocusRingRects::localBounds(const GraphicsContext&) const
696 {
697     FloatRect result;
698     for (auto& rect : m_rects)
699         result.unite(rect);
700     result.inflate(platformFocusRingWidth);
701     return result;
702 }
703
704 static TextStream& operator<<(TextStream& ts, const DrawFocusRingRects& item)
705 {
706     ts << static_cast<const DrawingItem&>(item);
707     ts.dumpProperty("rects", item.rects());
708     ts.dumpProperty("width", item.width());
709     ts.dumpProperty("offset", item.offset());
710     ts.dumpProperty("color", item.color());
711     return ts;
712 }
713
714 void FillRect::apply(GraphicsContext& context) const
715 {
716     context.fillRect(m_rect);
717 }
718
719 static TextStream& operator<<(TextStream& ts, const FillRect& item)
720 {
721     ts << static_cast<const DrawingItem&>(item);
722     ts.dumpProperty("rect", item.rect());
723     return ts;
724 }
725
726 void FillRectWithColor::apply(GraphicsContext& context) const
727 {
728     context.fillRect(m_rect, m_color);
729 }
730
731 static TextStream& operator<<(TextStream& ts, const FillRectWithColor& item)
732 {
733     ts << static_cast<const DrawingItem&>(item);
734     ts.dumpProperty("rect", item.rect());
735     ts.dumpProperty("color", item.color());
736     return ts;
737 }
738
739 void FillRectWithGradient::apply(GraphicsContext& context) const
740 {
741     context.fillRect(m_rect, m_gradient.get());
742 }
743
744 static TextStream& operator<<(TextStream& ts, const FillRectWithGradient& item)
745 {
746     ts << static_cast<const DrawingItem&>(item);
747     // FIXME: log gradient.
748     ts.dumpProperty("rect", item.rect());
749     return ts;
750 }
751
752 void FillCompositedRect::apply(GraphicsContext& context) const
753 {
754     context.fillRect(m_rect, m_color, m_op, m_blendMode);
755 }
756
757 static TextStream& operator<<(TextStream& ts, const FillCompositedRect& item)
758 {
759     ts << static_cast<const DrawingItem&>(item);
760     ts.dumpProperty("rect", item.rect());
761     ts.dumpProperty("color", item.color());
762     ts.dumpProperty("composite-operation", item.compositeOperator());
763     ts.dumpProperty("blend-mode", item.blendMode());
764     return ts;
765 }
766
767 void FillRoundedRect::apply(GraphicsContext& context) const
768 {
769     context.fillRoundedRect(m_rect, m_color, m_blendMode);
770 }
771
772 static TextStream& operator<<(TextStream& ts, const FillRoundedRect& item)
773 {
774     ts << static_cast<const DrawingItem&>(item);
775     ts.dumpProperty("rect", item.roundedRect());
776     ts.dumpProperty("color", item.color());
777     ts.dumpProperty("blend-mode", item.blendMode());
778     return ts;
779 }
780
781 void FillRectWithRoundedHole::apply(GraphicsContext& context) const
782 {
783     context.fillRectWithRoundedHole(m_rect, m_roundedHoleRect, m_color);
784 }
785
786 static TextStream& operator<<(TextStream& ts, const FillRectWithRoundedHole& item)
787 {
788     ts << static_cast<const DrawingItem&>(item);
789     ts.dumpProperty("rect", item.rect());
790     ts.dumpProperty("rounded-hole-rect", item.roundedHoleRect());
791     ts.dumpProperty("color", item.color());
792     return ts;
793 }
794
795 void FillPath::apply(GraphicsContext& context) const
796 {
797     context.fillPath(m_path);
798 }
799
800 static TextStream& operator<<(TextStream& ts, const FillPath& item)
801 {
802     ts << static_cast<const DrawingItem&>(item);
803     ts.dumpProperty("path", item.path());
804     return ts;
805 }
806
807 void FillEllipse::apply(GraphicsContext& context) const
808 {
809     context.fillEllipse(m_rect);
810 }
811
812 static TextStream& operator<<(TextStream& ts, const FillEllipse& item)
813 {
814     ts << static_cast<const DrawingItem&>(item);
815     ts.dumpProperty("rect", item.rect());
816     return ts;
817 }
818
819 std::optional<FloatRect> StrokeRect::localBounds(const GraphicsContext&) const
820 {
821     FloatRect bounds = m_rect;
822     bounds.expand(m_lineWidth, m_lineWidth);
823     return bounds;
824 }
825
826 void StrokeRect::apply(GraphicsContext& context) const
827 {
828     context.strokeRect(m_rect, m_lineWidth);
829 }
830
831 static TextStream& operator<<(TextStream& ts, const StrokeRect& item)
832 {
833     ts << static_cast<const DrawingItem&>(item);
834     ts.dumpProperty("rect", item.rect());
835     ts.dumpProperty("line-width", item.lineWidth());
836     return ts;
837 }
838
839 std::optional<FloatRect> StrokePath::localBounds(const GraphicsContext& context) const
840 {
841     // FIXME: Need to take stroke thickness into account correctly, via CGPathByStrokingPath().
842     float strokeThickness = context.strokeThickness();
843
844     FloatRect bounds = m_path.boundingRect();
845     bounds.expand(strokeThickness, strokeThickness);
846     return bounds;
847 }
848
849 void StrokePath::apply(GraphicsContext& context) const
850 {
851     context.strokePath(m_path);
852 }
853
854 static TextStream& operator<<(TextStream& ts, const StrokePath& item)
855 {
856     ts << static_cast<const DrawingItem&>(item);
857     ts.dumpProperty("path", item.path());
858     return ts;
859 }
860
861 std::optional<FloatRect> StrokeEllipse::localBounds(const GraphicsContext& context) const
862 {
863     float strokeThickness = context.strokeThickness();
864
865     FloatRect bounds = m_rect;
866     bounds.expand(strokeThickness, strokeThickness);
867     return bounds;
868 }
869
870 void StrokeEllipse::apply(GraphicsContext& context) const
871 {
872     context.strokeEllipse(m_rect);
873 }
874
875 static TextStream& operator<<(TextStream& ts, const StrokeEllipse& item)
876 {
877     ts << static_cast<const DrawingItem&>(item);
878     ts.dumpProperty("rect", item.rect());
879     return ts;
880 }
881
882 void ClearRect::apply(GraphicsContext& context) const
883 {
884     context.clearRect(m_rect);
885 }
886
887 static TextStream& operator<<(TextStream& ts, const ClearRect& item)
888 {
889     ts << static_cast<const DrawingItem&>(item);
890     ts.dumpProperty("rect", item.rect());
891     return ts;
892 }
893
894 void BeginTransparencyLayer::apply(GraphicsContext& context) const
895 {
896     context.beginTransparencyLayer(m_opacity);
897 }
898
899 static TextStream& operator<<(TextStream& ts, const BeginTransparencyLayer& item)
900 {
901     ts << static_cast<const DrawingItem&>(item);
902     ts.dumpProperty("opacity", item.opacity());
903     return ts;
904 }
905
906 void EndTransparencyLayer::apply(GraphicsContext& context) const
907 {
908     context.endTransparencyLayer();
909 }
910
911 #if USE(CG)
912 void ApplyStrokePattern::apply(GraphicsContext& context) const
913 {
914     context.applyStrokePattern();
915 }
916
917 void ApplyFillPattern::apply(GraphicsContext& context) const
918 {
919     context.applyFillPattern();
920 }
921 #endif
922
923 void ApplyDeviceScaleFactor::apply(GraphicsContext& context) const
924 {
925     context.applyDeviceScaleFactor(m_scaleFactor);
926 }
927
928 static TextStream& operator<<(TextStream& ts, const ApplyDeviceScaleFactor& item)
929 {
930     ts.dumpProperty("scale-factor", item.scaleFactor());
931     return ts;
932 }
933
934 static TextStream& operator<<(TextStream& ts, const ItemType& type)
935 {
936     switch (type) {
937     case ItemType::Save: ts << "save"; break;
938     case ItemType::Restore: ts << "restore"; break;
939     case ItemType::Translate: ts << "translate"; break;
940     case ItemType::Rotate: ts << "rotate"; break;
941     case ItemType::Scale: ts << "scale"; break;
942     case ItemType::ConcatenateCTM: ts << "concatentate-ctm"; break;
943     case ItemType::SetState: ts << "set-state"; break;
944     case ItemType::SetLineCap: ts << "set-line-cap"; break;
945     case ItemType::SetLineDash: ts << "set-line-dash"; break;
946     case ItemType::SetLineJoin: ts << "set-line-join"; break;
947     case ItemType::SetMiterLimit: ts << "set-miter-limit"; break;
948     case ItemType::Clip: ts << "clip"; break;
949     case ItemType::ClipOut: ts << "clip-out"; break;
950     case ItemType::ClipOutToPath: ts << "clip-out-to-path"; break;
951     case ItemType::ClipPath: ts << "clip-path"; break;
952     case ItemType::DrawGlyphs: ts << "draw-glyphs"; break;
953     case ItemType::DrawImage: ts << "draw-image"; break;
954     case ItemType::DrawTiledImage: ts << "draw-tiled-image"; break;
955     case ItemType::DrawTiledScaledImage: ts << "draw-tiled-scaled-image"; break;
956 #if USE(CG) || USE(CAIRO)
957     case ItemType::DrawNativeImage: ts << "draw-native-image"; break;
958 #endif
959     case ItemType::DrawPattern: ts << "draw-pattern"; break;
960     case ItemType::DrawRect: ts << "draw-rect"; break;
961     case ItemType::DrawLine: ts << "draw-line"; break;
962     case ItemType::DrawLinesForText: ts << "draw-lines-for-text"; break;
963     case ItemType::DrawDotsForDocumentMarker: ts << "draw-dots-for-document-marker"; break;
964     case ItemType::DrawEllipse: ts << "draw-ellipse"; break;
965     case ItemType::DrawPath: ts << "draw-path"; break;
966     case ItemType::DrawFocusRingPath: ts << "draw-focus-ring-path"; break;
967     case ItemType::DrawFocusRingRects: ts << "draw-focus-ring-rects"; break;
968     case ItemType::FillRect: ts << "fill-rect"; break;
969     case ItemType::FillRectWithColor: ts << "fill-rect-with-color"; break;
970     case ItemType::FillRectWithGradient: ts << "fill-rect-with-gradient"; break;
971     case ItemType::FillCompositedRect: ts << "fill-composited-rect"; break;
972     case ItemType::FillRoundedRect: ts << "fill-rounded-rect"; break;
973     case ItemType::FillRectWithRoundedHole: ts << "fill-rect-with-rounded-hole"; break;
974     case ItemType::FillPath: ts << "fill-path"; break;
975     case ItemType::FillEllipse: ts << "fill-ellipse"; break;
976     case ItemType::StrokeRect: ts << "stroke-rect"; break;
977     case ItemType::StrokePath: ts << "stroke-path"; break;
978     case ItemType::StrokeEllipse: ts << "stroke-ellipse"; break;
979     case ItemType::ClearRect: ts << "clear-rect"; break;
980     case ItemType::BeginTransparencyLayer: ts << "begin-transparency-layer"; break;
981     case ItemType::EndTransparencyLayer: ts << "end-transparency-layer"; break;
982 #if USE(CG)
983     case ItemType::ApplyStrokePattern: ts << "apply-stroke-pattern"; break;
984     case ItemType::ApplyFillPattern: ts << "apply-fill-pattern"; break;
985 #endif
986     case ItemType::ApplyDeviceScaleFactor: ts << "apply-device-scale-factor"; break;
987     case ItemType::ClearShadow: ts << "clear-shadow"; break;
988     }
989     return ts;
990 }
991
992 TextStream& operator<<(TextStream& ts, const Item& item)
993 {
994     TextStream::GroupScope group(ts);
995     ts << item.type();
996
997     // FIXME: Make a macro which takes a macro for all these enumeration switches
998     switch (item.type()) {
999     case ItemType::Save:
1000         ts << downcast<Save>(item);
1001         break;
1002     case ItemType::Translate:
1003         ts << downcast<Translate>(item);
1004         break;
1005     case ItemType::Rotate:
1006         ts << downcast<Rotate>(item);
1007         break;
1008     case ItemType::Scale:
1009         ts << downcast<Scale>(item);
1010         break;
1011     case ItemType::ConcatenateCTM:
1012         ts << downcast<ConcatenateCTM>(item);
1013         break;
1014     case ItemType::SetState:
1015         ts << downcast<SetState>(item);
1016         break;
1017     case ItemType::SetLineCap:
1018         ts << downcast<SetLineCap>(item);
1019         break;
1020     case ItemType::SetLineDash:
1021         ts << downcast<SetLineDash>(item);
1022         break;
1023     case ItemType::SetLineJoin:
1024         ts << downcast<SetLineJoin>(item);
1025         break;
1026     case ItemType::SetMiterLimit:
1027         ts << downcast<SetMiterLimit>(item);
1028         break;
1029     case ItemType::Clip:
1030         ts << downcast<Clip>(item);
1031         break;
1032     case ItemType::ClipOut:
1033         ts << downcast<ClipOut>(item);
1034         break;
1035     case ItemType::ClipOutToPath:
1036         ts << downcast<ClipOutToPath>(item);
1037         break;
1038     case ItemType::ClipPath:
1039         ts << downcast<ClipPath>(item);
1040         break;
1041     case ItemType::DrawGlyphs:
1042         ts << downcast<DrawGlyphs>(item);
1043         break;
1044     case ItemType::DrawImage:
1045         ts << downcast<DrawImage>(item);
1046         break;
1047     case ItemType::DrawTiledImage:
1048         ts << downcast<DrawTiledImage>(item);
1049         break;
1050     case ItemType::DrawTiledScaledImage:
1051         ts << downcast<DrawTiledScaledImage>(item);
1052         break;
1053 #if USE(CG) || USE(CAIRO)
1054     case ItemType::DrawNativeImage:
1055         ts << downcast<DrawNativeImage>(item);
1056         break;
1057 #endif
1058     case ItemType::DrawPattern:
1059         ts << downcast<DrawPattern>(item);
1060         break;
1061     case ItemType::DrawRect:
1062         ts << downcast<DrawRect>(item);
1063         break;
1064     case ItemType::DrawLine:
1065         ts << downcast<DrawLine>(item);
1066         break;
1067     case ItemType::DrawLinesForText:
1068         ts << downcast<DrawLinesForText>(item);
1069         break;
1070     case ItemType::DrawDotsForDocumentMarker:
1071         ts << downcast<DrawDotsForDocumentMarker>(item);
1072         break;
1073     case ItemType::DrawEllipse:
1074         ts << downcast<DrawEllipse>(item);
1075         break;
1076     case ItemType::DrawPath:
1077         ts << downcast<DrawPath>(item);
1078         break;
1079     case ItemType::DrawFocusRingPath:
1080         ts << downcast<DrawFocusRingPath>(item);
1081         break;
1082     case ItemType::DrawFocusRingRects:
1083         ts << downcast<DrawFocusRingRects>(item);
1084         break;
1085     case ItemType::FillRect:
1086         ts << downcast<FillRect>(item);
1087         break;
1088     case ItemType::FillRectWithColor:
1089         ts << downcast<FillRectWithColor>(item);
1090         break;
1091     case ItemType::FillRectWithGradient:
1092         ts << downcast<FillRectWithGradient>(item);
1093         break;
1094     case ItemType::FillCompositedRect:
1095         ts << downcast<FillCompositedRect>(item);
1096         break;
1097     case ItemType::FillRoundedRect:
1098         ts << downcast<FillRoundedRect>(item);
1099         break;
1100     case ItemType::FillRectWithRoundedHole:
1101         ts << downcast<FillRectWithRoundedHole>(item);
1102         break;
1103     case ItemType::FillPath:
1104         ts << downcast<FillPath>(item);
1105         break;
1106     case ItemType::FillEllipse:
1107         ts << downcast<FillEllipse>(item);
1108         break;
1109     case ItemType::StrokeRect:
1110         ts << downcast<StrokeRect>(item);
1111         break;
1112     case ItemType::StrokePath:
1113         ts << downcast<StrokePath>(item);
1114         break;
1115     case ItemType::StrokeEllipse:
1116         ts << downcast<StrokeEllipse>(item);
1117         break;
1118     case ItemType::ClearRect:
1119         ts << downcast<ClearRect>(item);
1120         break;
1121     case ItemType::BeginTransparencyLayer:
1122         ts << downcast<BeginTransparencyLayer>(item);
1123         break;
1124     case ItemType::ApplyDeviceScaleFactor:
1125         ts << downcast<ApplyDeviceScaleFactor>(item);
1126         break;
1127
1128     // Items with no additional data.
1129     case ItemType::Restore:
1130     case ItemType::EndTransparencyLayer:
1131 #if USE(CG)
1132     case ItemType::ApplyStrokePattern:
1133     case ItemType::ApplyFillPattern:
1134 #endif
1135     case ItemType::ClearShadow:
1136         break;
1137     }
1138     return ts;
1139 }
1140
1141 }
1142 }