Remove GraphicsContext::drawConvexPolygon() and GraphicsContext::clipConvexPolygon()
[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 "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::DrawLineForDocumentMarker:
103         return sizeof(downcast<DrawLineForDocumentMarker>(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&)
330 {
331 //    ts.dumpProperty("path", item.path()); // FIXME: path logging.
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()); // FIXME: path logging.
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 #if USE(CAIRO)
368         result.add(m_glyphs[i].index, &m_font.get(), m_advances[i]);
369 #else
370         result.add(m_glyphs[i], &m_font.get(), m_advances[i]);
371 #endif
372     }
373     return result;
374 }
375
376 void DrawGlyphs::apply(GraphicsContext& context) const
377 {
378     FontCascade::drawGlyphs(context, m_font, generateGlyphBuffer(), 0, m_glyphs.size(), anchorPoint(), m_smoothingMode);
379 }
380
381 void DrawGlyphs::computeBounds()
382 {
383     // FIXME: This code doesn't actually take the extents of the glyphs into consideration. It assumes that
384     // the glyph lies entirely within its [(ascent + descent), advance] rect.
385     float ascent = m_font->fontMetrics().floatAscent();
386     float descent = m_font->fontMetrics().floatDescent();
387     FloatPoint current = toFloatPoint(localAnchor());
388     size_t numGlyphs = m_glyphs.size();
389     for (size_t i = 0; i < numGlyphs; ++i) {
390         GlyphBufferAdvance advance = m_advances[i];
391         FloatRect glyphRect = FloatRect(current.x(), current.y() - ascent, advance.width(), ascent + descent);
392         m_bounds.unite(glyphRect);
393
394         current += FloatSize(advance);
395     }
396 }
397
398 Optional<FloatRect> DrawGlyphs::localBounds(const GraphicsContext&) const
399 {
400     FloatRect localBounds = m_bounds;
401     localBounds.move(m_blockLocation.x(), m_blockLocation.y());
402     return localBounds;
403 }
404
405 static TextStream& operator<<(TextStream& ts, const DrawGlyphs& item)
406 {
407     ts << static_cast<const DrawingItem&>(item);
408     // FIXME: dump more stuff.
409     ts.dumpProperty("block-location", item.blockLocation());
410     ts.dumpProperty("local-anchor", item.localAnchor());
411     ts.dumpProperty("anchor-point", item.anchorPoint());
412     ts.dumpProperty("length", item.glyphs().size());
413
414     return ts;
415 }
416
417 DrawImage::DrawImage(Image& image, const FloatRect& destination, const FloatRect& source, const ImagePaintingOptions& imagePaintingOptions)
418     : DrawingItem(ItemType::DrawImage)
419     , m_image(image)
420     , m_destination(destination)
421     , m_source(source)
422     , m_imagePaintingOptions(imagePaintingOptions)
423 {
424 }
425
426 void DrawImage::apply(GraphicsContext& context) const
427 {
428     context.drawImage(m_image.get(), m_destination, m_source, m_imagePaintingOptions);
429 }
430
431 static TextStream& operator<<(TextStream& ts, const DrawImage& item)
432 {
433     ts << static_cast<const DrawingItem&>(item);
434     ts.dumpProperty("image", item.image());
435     ts.dumpProperty("source-rect", item.source());
436     ts.dumpProperty("dest-rect", item.destination());
437     return ts;
438 }
439
440 DrawTiledImage::DrawTiledImage(Image& image, const FloatRect& destination, const FloatPoint& source, const FloatSize& tileSize, const FloatSize& spacing, const ImagePaintingOptions& imagePaintingOptions)
441     : DrawingItem(ItemType::DrawTiledImage)
442     , m_image(image)
443     , m_destination(destination)
444     , m_source(source)
445     , m_tileSize(tileSize)
446     , m_spacing(spacing)
447     , m_imagePaintingOptions(imagePaintingOptions)
448 {
449 }
450
451 void DrawTiledImage::apply(GraphicsContext& context) const
452 {
453     context.drawTiledImage(m_image.get(), m_destination, m_source, m_tileSize, m_spacing, m_imagePaintingOptions);
454 }
455
456 static TextStream& operator<<(TextStream& ts, const DrawTiledImage& item)
457 {
458     ts << static_cast<const DrawingItem&>(item);
459     ts.dumpProperty("image", item.image());
460     ts.dumpProperty("source-point", item.source());
461     ts.dumpProperty("dest-rect", item.destination());
462     ts.dumpProperty("tile-size", item.tileSize());
463     ts.dumpProperty("spacing", item.spacing());
464     return ts;
465 }
466
467 DrawTiledScaledImage::DrawTiledScaledImage(Image& image, const FloatRect& destination, const FloatRect& source, const FloatSize& tileScaleFactor, Image::TileRule hRule, Image::TileRule vRule, const ImagePaintingOptions& imagePaintingOptions)
468     : DrawingItem(ItemType::DrawTiledScaledImage)
469     , m_image(image)
470     , m_destination(destination)
471     , m_source(source)
472     , m_tileScaleFactor(tileScaleFactor)
473     , m_hRule(hRule)
474     , m_vRule(vRule)
475     , m_imagePaintingOptions(imagePaintingOptions)
476 {
477 }
478
479 void DrawTiledScaledImage::apply(GraphicsContext& context) const
480 {
481     context.drawTiledImage(m_image.get(), m_destination, m_source, m_tileScaleFactor, m_hRule, m_vRule, m_imagePaintingOptions);
482 }
483
484 static TextStream& operator<<(TextStream& ts, const DrawTiledScaledImage& item)
485 {
486     ts << static_cast<const DrawingItem&>(item);
487     ts.dumpProperty("image", item.image());
488     ts.dumpProperty("source-rect", item.source());
489     ts.dumpProperty("dest-rect", item.destination());
490     return ts;
491 }
492
493 #if USE(CG) || USE(CAIRO)
494 DrawNativeImage::DrawNativeImage(PassNativeImagePtr imagePtr, const FloatSize& imageSize, const FloatRect& destRect, const FloatRect& srcRect, CompositeOperator op, BlendMode blendMode, ImageOrientation orientation)
495     : DrawingItem(ItemType::DrawNativeImage)
496 #if USE(CG)
497     // FIXME: Need to store an image for Cairo.
498     , m_imagePtr(imagePtr)
499 #endif
500     , m_imageSize(imageSize)
501     , m_destination(destRect)
502     , m_srcRect(srcRect)
503 #if USE(CG)
504     , m_op(op)
505     , m_blendMode(blendMode)
506 #endif
507     , m_orientation(orientation)
508 {
509 #if !USE(CG)
510     UNUSED_PARAM(imagePtr);
511     UNUSED_PARAM(op);
512     UNUSED_PARAM(blendMode);
513 #endif
514 }
515
516 void DrawNativeImage::apply(GraphicsContext& context) const
517 {
518 #if USE(CG)
519     context.drawNativeImage(m_imagePtr.get(), m_imageSize, m_destination, m_srcRect, m_op, m_blendMode, m_orientation);
520 #else
521     UNUSED_PARAM(context);
522 #endif
523 }
524
525 static TextStream& operator<<(TextStream& ts, const DrawNativeImage& item)
526 {
527     ts << static_cast<const DrawingItem&>(item);
528     // FIXME: dump more stuff.
529     ts.dumpProperty("source-rect", item.source());
530     ts.dumpProperty("dest-rect", item.destination());
531     return ts;
532 }
533 #endif
534
535 DrawPattern::DrawPattern(Image& image, const FloatRect& tileRect, const AffineTransform& patternTransform, const FloatPoint& phase, const FloatSize& spacing, CompositeOperator op, const FloatRect& destRect, BlendMode blendMode)
536     : DrawingItem(ItemType::DrawPattern)
537     , m_image(image)
538     , m_patternTransform(patternTransform)
539     , m_tileRect(tileRect)
540     , m_destination(destRect)
541     , m_phase(phase)
542     , m_spacing(spacing)
543     , m_op(op)
544     , m_blendMode(blendMode)
545 {
546 }
547
548 void DrawPattern::apply(GraphicsContext& context) const
549 {
550     context.drawPattern(m_image.get(), m_tileRect, m_patternTransform, m_phase, m_spacing, m_op, m_destination, m_blendMode);
551 }
552
553 static TextStream& operator<<(TextStream& ts, const DrawPattern& item)
554 {
555     ts << static_cast<const DrawingItem&>(item);
556     ts.dumpProperty("image", item.image());
557     ts.dumpProperty("pattern-transform", item.patternTransform());
558     ts.dumpProperty("tile-rect", item.tileRect());
559     ts.dumpProperty("dest-rect", item.destRect());
560     ts.dumpProperty("phase", item.phase());
561     ts.dumpProperty("spacing", item.spacing());
562     return ts;
563 }
564
565 void DrawRect::apply(GraphicsContext& context) const
566 {
567     context.drawRect(m_rect, m_borderThickness);
568 }
569
570 static TextStream& operator<<(TextStream& ts, const DrawRect& item)
571 {
572     ts << static_cast<const DrawingItem&>(item);
573     ts.dumpProperty("rect", item.rect());
574     ts.dumpProperty("border-thickness", item.borderThickness());
575     return ts;
576 }
577
578 Optional<FloatRect> DrawLine::localBounds(const GraphicsContext&) const
579 {
580     FloatRect bounds;
581     bounds.fitToPoints(m_point1, m_point2);
582     return bounds;
583 }
584
585 void DrawLine::apply(GraphicsContext& context) const
586 {
587     context.drawLine(m_point1, m_point2);
588 }
589
590 static TextStream& operator<<(TextStream& ts, const DrawLine& item)
591 {
592     ts << static_cast<const DrawingItem&>(item);
593     ts.dumpProperty("point-1", item.point1());
594     ts.dumpProperty("point-2", item.point2());
595     return ts;
596 }
597
598 void DrawLinesForText::apply(GraphicsContext& context) const
599 {
600     context.drawLinesForText(point(), m_widths, m_printing, m_doubleLines);
601 }
602
603 Optional<FloatRect> DrawLinesForText::localBounds(const GraphicsContext&) const
604 {
605     // This function needs to return a value equal to or enclosing what GraphicsContext::computeLineBoundsAndAntialiasingModeForText() returns.
606
607     if (!m_widths.size())
608         return FloatRect();
609
610     FloatRect result(point(), FloatSize(m_widths.last(), m_strokeWidth));
611     result.inflate(1); // Account for pixel snapping. FIXME: This isn't perfect, as it doesn't take the CTM into account.
612     return result;
613 }
614
615 static TextStream& operator<<(TextStream& ts, const DrawLinesForText& item)
616 {
617     ts << static_cast<const DrawingItem&>(item);
618     ts.dumpProperty("block-location", item.blockLocation());
619     ts.dumpProperty("local-anchor", item.localAnchor());
620     ts.dumpProperty("point", item.point());
621     ts.dumpProperty("double", item.doubleLines());
622     ts.dumpProperty("widths", item.widths());
623     ts.dumpProperty("is-printing", item.isPrinting());
624     ts.dumpProperty("double", item.doubleLines());
625     return ts;
626 }
627
628 void DrawLineForDocumentMarker::apply(GraphicsContext& context) const
629 {
630     context.drawLineForDocumentMarker(m_point, m_width, m_style);
631 }
632
633 Optional<FloatRect> DrawLineForDocumentMarker::localBounds(const GraphicsContext&) const
634 {
635     // This function needs to return a value equal to or enclosing what GraphicsContext::drawLineForDocumentMarker() returns.
636
637     FloatRect result(m_point, FloatSize(m_width, cMisspellingLineThickness));
638     result.inflate(cMisspellingLineThickness); // Account for "misspelling dot" snapping.
639     return result;
640 }
641
642 static TextStream& operator<<(TextStream& ts, const DrawLineForDocumentMarker& item)
643 {
644     ts << static_cast<const DrawingItem&>(item);
645     ts.dumpProperty("point", item.point());
646     ts.dumpProperty("width", item.width());
647     return ts;
648 }
649
650 void DrawEllipse::apply(GraphicsContext& context) const
651 {
652     context.drawEllipse(m_rect);
653 }
654
655 static TextStream& operator<<(TextStream& ts, const DrawEllipse& item)
656 {
657     ts.dumpProperty("rect", item.rect());
658     return ts;
659 }
660
661 void DrawPath::apply(GraphicsContext& context) const
662 {
663 #if USE(CG)
664     context.drawPath(m_path);
665 #else
666     UNUSED_PARAM(context);
667 #endif
668 }
669
670 static TextStream& operator<<(TextStream& ts, const DrawPath& item)
671 {
672     ts << static_cast<const DrawingItem&>(item);
673 //    ts.dumpProperty("path", item.path()); // FIXME: add logging for paths.
674     return ts;
675 }
676
677 void DrawFocusRingPath::apply(GraphicsContext& context) const
678 {
679     context.drawFocusRing(m_path, m_width, m_offset, m_color);
680 }
681
682 Optional<FloatRect> DrawFocusRingPath::localBounds(const GraphicsContext&) const
683 {
684     FloatRect result = m_path.fastBoundingRect();
685     result.inflate(platformFocusRingWidth);
686     return result;
687 }
688
689 static TextStream& operator<<(TextStream& ts, const DrawFocusRingPath& item)
690 {
691     ts << static_cast<const DrawingItem&>(item);
692 //    ts.dumpProperty("path", item.path()); // FIXME: add logging for paths.
693     ts.dumpProperty("width", item.width());
694     ts.dumpProperty("offset", item.offset());
695     ts.dumpProperty("color", item.color());
696     return ts;
697 }
698
699 void DrawFocusRingRects::apply(GraphicsContext& context) const
700 {
701     context.drawFocusRing(m_rects, m_width, m_offset, m_color);
702 }
703
704 Optional<FloatRect> DrawFocusRingRects::localBounds(const GraphicsContext&) const
705 {
706     FloatRect result;
707     for (auto& rect : m_rects)
708         result.unite(rect);
709     result.inflate(platformFocusRingWidth);
710     return result;
711 }
712
713 static TextStream& operator<<(TextStream& ts, const DrawFocusRingRects& item)
714 {
715     ts << static_cast<const DrawingItem&>(item);
716     ts.dumpProperty("rects", item.rects());
717     ts.dumpProperty("width", item.width());
718     ts.dumpProperty("offset", item.offset());
719     ts.dumpProperty("color", item.color());
720     return ts;
721 }
722
723 void FillRect::apply(GraphicsContext& context) const
724 {
725     context.fillRect(m_rect);
726 }
727
728 static TextStream& operator<<(TextStream& ts, const FillRect& item)
729 {
730     ts << static_cast<const DrawingItem&>(item);
731     ts.dumpProperty("rect", item.rect());
732     return ts;
733 }
734
735 void FillRectWithColor::apply(GraphicsContext& context) const
736 {
737     context.fillRect(m_rect, m_color);
738 }
739
740 static TextStream& operator<<(TextStream& ts, const FillRectWithColor& item)
741 {
742     ts << static_cast<const DrawingItem&>(item);
743     ts.dumpProperty("rect", item.rect());
744     ts.dumpProperty("color", item.color());
745     return ts;
746 }
747
748 void FillRectWithGradient::apply(GraphicsContext& context) const
749 {
750     context.fillRect(m_rect, m_gradient.get());
751 }
752
753 static TextStream& operator<<(TextStream& ts, const FillRectWithGradient& item)
754 {
755     ts << static_cast<const DrawingItem&>(item);
756     // FIXME: log gradient.
757     ts.dumpProperty("rect", item.rect());
758     return ts;
759 }
760
761 void FillCompositedRect::apply(GraphicsContext& context) const
762 {
763     context.fillRect(m_rect, m_color, m_op, m_blendMode);
764 }
765
766 static TextStream& operator<<(TextStream& ts, const FillCompositedRect& item)
767 {
768     ts << static_cast<const DrawingItem&>(item);
769     ts.dumpProperty("rect", item.rect());
770     ts.dumpProperty("color", item.color());
771     ts.dumpProperty("composite-operation", item.compositeOperator());
772     ts.dumpProperty("blend-mode", item.blendMode());
773     return ts;
774 }
775
776 void FillRoundedRect::apply(GraphicsContext& context) const
777 {
778     context.fillRoundedRect(m_rect, m_color, m_blendMode);
779 }
780
781 static TextStream& operator<<(TextStream& ts, const FillRoundedRect& item)
782 {
783     ts << static_cast<const DrawingItem&>(item);
784     ts.dumpProperty("rect", item.roundedRect());
785     ts.dumpProperty("color", item.color());
786     ts.dumpProperty("blend-mode", item.blendMode());
787     return ts;
788 }
789
790 void FillRectWithRoundedHole::apply(GraphicsContext& context) const
791 {
792     context.fillRectWithRoundedHole(m_rect, m_roundedHoleRect, m_color);
793 }
794
795 static TextStream& operator<<(TextStream& ts, const FillRectWithRoundedHole& item)
796 {
797     ts << static_cast<const DrawingItem&>(item);
798     ts.dumpProperty("rect", item.rect());
799     ts.dumpProperty("rounded-hole-rect", item.roundedHoleRect());
800     ts.dumpProperty("color", item.color());
801     return ts;
802 }
803
804 void FillPath::apply(GraphicsContext& context) const
805 {
806     context.fillPath(m_path);
807 }
808
809 static TextStream& operator<<(TextStream& ts, const FillPath& item)
810 {
811     ts << static_cast<const DrawingItem&>(item);
812 //    ts.dumpProperty("path", item.path()); // FIXME: path logging.
813     return ts;
814 }
815
816 void FillEllipse::apply(GraphicsContext& context) const
817 {
818     context.fillEllipse(m_rect);
819 }
820
821 static TextStream& operator<<(TextStream& ts, const FillEllipse& item)
822 {
823     ts << static_cast<const DrawingItem&>(item);
824     ts.dumpProperty("rect", item.rect());
825     return ts;
826 }
827
828 Optional<FloatRect> StrokeRect::localBounds(const GraphicsContext&) const
829 {
830     FloatRect bounds = m_rect;
831     bounds.expand(m_lineWidth, m_lineWidth);
832     return bounds;
833 }
834
835 void StrokeRect::apply(GraphicsContext& context) const
836 {
837     context.strokeRect(m_rect, m_lineWidth);
838 }
839
840 static TextStream& operator<<(TextStream& ts, const StrokeRect& item)
841 {
842     ts << static_cast<const DrawingItem&>(item);
843     ts.dumpProperty("rect", item.rect());
844     ts.dumpProperty("line-width", item.lineWidth());
845     return ts;
846 }
847
848 Optional<FloatRect> StrokePath::localBounds(const GraphicsContext& context) const
849 {
850     // FIXME: Need to take stroke thickness into account correctly, via CGPathByStrokingPath().
851     float strokeThickness = context.strokeThickness();
852
853     FloatRect bounds = m_path.boundingRect();
854     bounds.expand(strokeThickness, strokeThickness);
855     return bounds;
856 }
857
858 void StrokePath::apply(GraphicsContext& context) const
859 {
860     context.strokePath(m_path);
861 }
862
863 static TextStream& operator<<(TextStream& ts, const StrokePath& item)
864 {
865     ts << static_cast<const DrawingItem&>(item);
866 //    ts.dumpProperty("path", item.path()); // FIXME: path logging.
867     return ts;
868 }
869
870 Optional<FloatRect> StrokeEllipse::localBounds(const GraphicsContext& context) const
871 {
872     float strokeThickness = context.strokeThickness();
873
874     FloatRect bounds = m_rect;
875     bounds.expand(strokeThickness, strokeThickness);
876     return bounds;
877 }
878
879 void StrokeEllipse::apply(GraphicsContext& context) const
880 {
881     context.strokeEllipse(m_rect);
882 }
883
884 static TextStream& operator<<(TextStream& ts, const StrokeEllipse& item)
885 {
886     ts << static_cast<const DrawingItem&>(item);
887     ts.dumpProperty("rect", item.rect());
888     return ts;
889 }
890
891 void ClearRect::apply(GraphicsContext& context) const
892 {
893     context.clearRect(m_rect);
894 }
895
896 static TextStream& operator<<(TextStream& ts, const ClearRect& item)
897 {
898     ts << static_cast<const DrawingItem&>(item);
899     ts.dumpProperty("rect", item.rect());
900     return ts;
901 }
902
903 void BeginTransparencyLayer::apply(GraphicsContext& context) const
904 {
905     context.beginTransparencyLayer(m_opacity);
906 }
907
908 static TextStream& operator<<(TextStream& ts, const BeginTransparencyLayer& item)
909 {
910     ts << static_cast<const DrawingItem&>(item);
911     ts.dumpProperty("opacity", item.opacity());
912     return ts;
913 }
914
915 void EndTransparencyLayer::apply(GraphicsContext& context) const
916 {
917     context.endTransparencyLayer();
918 }
919
920 #if USE(CG)
921 void ApplyStrokePattern::apply(GraphicsContext& context) const
922 {
923     context.applyStrokePattern();
924 }
925
926 void ApplyFillPattern::apply(GraphicsContext& context) const
927 {
928     context.applyFillPattern();
929 }
930 #endif
931
932 void ApplyDeviceScaleFactor::apply(GraphicsContext& context) const
933 {
934     context.applyDeviceScaleFactor(m_scaleFactor);
935 }
936
937 static TextStream& operator<<(TextStream& ts, const ApplyDeviceScaleFactor& item)
938 {
939     ts.dumpProperty("scale-factor", item.scaleFactor());
940     return ts;
941 }
942
943 static TextStream& operator<<(TextStream& ts, const ItemType& type)
944 {
945     switch (type) {
946     case ItemType::Save: ts << "save"; break;
947     case ItemType::Restore: ts << "restore"; break;
948     case ItemType::Translate: ts << "translate"; break;
949     case ItemType::Rotate: ts << "rotate"; break;
950     case ItemType::Scale: ts << "scale"; break;
951     case ItemType::ConcatenateCTM: ts << "concatentate-ctm"; break;
952     case ItemType::SetState: ts << "set-state"; break;
953     case ItemType::SetLineCap: ts << "set-line-cap"; break;
954     case ItemType::SetLineDash: ts << "set-line-dash"; break;
955     case ItemType::SetLineJoin: ts << "set-line-join"; break;
956     case ItemType::SetMiterLimit: ts << "set-miter-limit"; break;
957     case ItemType::Clip: ts << "clip"; break;
958     case ItemType::ClipOut: ts << "clip-out"; break;
959     case ItemType::ClipOutToPath: ts << "clip-out-to-path"; break;
960     case ItemType::ClipPath: ts << "clip-path"; break;
961     case ItemType::DrawGlyphs: ts << "draw-glyphs"; break;
962     case ItemType::DrawImage: ts << "draw-image"; break;
963     case ItemType::DrawTiledImage: ts << "draw-tiled-image"; break;
964     case ItemType::DrawTiledScaledImage: ts << "draw-tiled-scaled-image"; break;
965 #if USE(CG) || USE(CAIRO)
966     case ItemType::DrawNativeImage: ts << "draw-native-image"; break;
967 #endif
968     case ItemType::DrawPattern: ts << "draw-pattern"; break;
969     case ItemType::DrawRect: ts << "draw-rect"; break;
970     case ItemType::DrawLine: ts << "draw-line"; break;
971     case ItemType::DrawLinesForText: ts << "draw-lines-for-text"; break;
972     case ItemType::DrawLineForDocumentMarker: ts << "draw-lines-for-document-marker"; break;
973     case ItemType::DrawEllipse: ts << "draw-ellipse"; break;
974     case ItemType::DrawPath: ts << "draw-path"; break;
975     case ItemType::DrawFocusRingPath: ts << "draw-focus-ring-path"; break;
976     case ItemType::DrawFocusRingRects: ts << "draw-focus-ring-rects"; break;
977     case ItemType::FillRect: ts << "fill-rect"; break;
978     case ItemType::FillRectWithColor: ts << "fill-rect-with-color"; break;
979     case ItemType::FillRectWithGradient: ts << "fill-rect-with-gradient"; break;
980     case ItemType::FillCompositedRect: ts << "fill-composited-rect"; break;
981     case ItemType::FillRoundedRect: ts << "fill-rounded-rect"; break;
982     case ItemType::FillRectWithRoundedHole: ts << "fill-rect-with-rounded-hole"; break;
983     case ItemType::FillPath: ts << "fill-path"; break;
984     case ItemType::FillEllipse: ts << "fill-ellipse"; break;
985     case ItemType::StrokeRect: ts << "stroke-rect"; break;
986     case ItemType::StrokePath: ts << "stroke-path"; break;
987     case ItemType::StrokeEllipse: ts << "stroke-ellipse"; break;
988     case ItemType::ClearRect: ts << "clear-rect"; break;
989     case ItemType::BeginTransparencyLayer: ts << "begin-transparency-layer"; break;
990     case ItemType::EndTransparencyLayer: ts << "end-transparency-layer"; break;
991 #if USE(CG)
992     case ItemType::ApplyStrokePattern: ts << "apply-stroke-pattern"; break;
993     case ItemType::ApplyFillPattern: ts << "apply-fill-pattern"; break;
994 #endif
995     case ItemType::ApplyDeviceScaleFactor: ts << "apply-device-scale-factor"; break;
996     case ItemType::ClearShadow: ts << "clear-shadow"; break;
997     }
998     return ts;
999 }
1000
1001 TextStream& operator<<(TextStream& ts, const Item& item)
1002 {
1003     TextStream::GroupScope group(ts);
1004     ts << item.type();
1005
1006     // FIXME: Make a macro which takes a macro for all these enumeration switches
1007     switch (item.type()) {
1008     case ItemType::Save:
1009         ts << downcast<Save>(item);
1010         break;
1011     case ItemType::Translate:
1012         ts << downcast<Translate>(item);
1013         break;
1014     case ItemType::Rotate:
1015         ts << downcast<Rotate>(item);
1016         break;
1017     case ItemType::Scale:
1018         ts << downcast<Scale>(item);
1019         break;
1020     case ItemType::ConcatenateCTM:
1021         ts << downcast<ConcatenateCTM>(item);
1022         break;
1023     case ItemType::SetState:
1024         ts << downcast<SetState>(item);
1025         break;
1026     case ItemType::SetLineCap:
1027         ts << downcast<SetLineCap>(item);
1028         break;
1029     case ItemType::SetLineDash:
1030         ts << downcast<SetLineDash>(item);
1031         break;
1032     case ItemType::SetLineJoin:
1033         ts << downcast<SetLineJoin>(item);
1034         break;
1035     case ItemType::SetMiterLimit:
1036         ts << downcast<SetMiterLimit>(item);
1037         break;
1038     case ItemType::Clip:
1039         ts << downcast<Clip>(item);
1040         break;
1041     case ItemType::ClipOut:
1042         ts << downcast<ClipOut>(item);
1043         break;
1044     case ItemType::ClipOutToPath:
1045         ts << downcast<ClipOutToPath>(item);
1046         break;
1047     case ItemType::ClipPath:
1048         ts << downcast<ClipPath>(item);
1049         break;
1050     case ItemType::DrawGlyphs:
1051         ts << downcast<DrawGlyphs>(item);
1052         break;
1053     case ItemType::DrawImage:
1054         ts << downcast<DrawImage>(item);
1055         break;
1056     case ItemType::DrawTiledImage:
1057         ts << downcast<DrawTiledImage>(item);
1058         break;
1059     case ItemType::DrawTiledScaledImage:
1060         ts << downcast<DrawTiledScaledImage>(item);
1061         break;
1062 #if USE(CG) || USE(CAIRO)
1063     case ItemType::DrawNativeImage:
1064         ts << downcast<DrawNativeImage>(item);
1065         break;
1066 #endif
1067     case ItemType::DrawPattern:
1068         ts << downcast<DrawPattern>(item);
1069         break;
1070     case ItemType::DrawRect:
1071         ts << downcast<DrawRect>(item);
1072         break;
1073     case ItemType::DrawLine:
1074         ts << downcast<DrawLine>(item);
1075         break;
1076     case ItemType::DrawLinesForText:
1077         ts << downcast<DrawLinesForText>(item);
1078         break;
1079     case ItemType::DrawLineForDocumentMarker:
1080         ts << downcast<DrawLineForDocumentMarker>(item);
1081         break;
1082     case ItemType::DrawEllipse:
1083         ts << downcast<DrawEllipse>(item);
1084         break;
1085     case ItemType::DrawPath:
1086         ts << downcast<DrawPath>(item);
1087         break;
1088     case ItemType::DrawFocusRingPath:
1089         ts << downcast<DrawFocusRingPath>(item);
1090         break;
1091     case ItemType::DrawFocusRingRects:
1092         ts << downcast<DrawFocusRingRects>(item);
1093         break;
1094     case ItemType::FillRect:
1095         ts << downcast<FillRect>(item);
1096         break;
1097     case ItemType::FillRectWithColor:
1098         ts << downcast<FillRectWithColor>(item);
1099         break;
1100     case ItemType::FillRectWithGradient:
1101         ts << downcast<FillRectWithGradient>(item);
1102         break;
1103     case ItemType::FillCompositedRect:
1104         ts << downcast<FillCompositedRect>(item);
1105         break;
1106     case ItemType::FillRoundedRect:
1107         ts << downcast<FillRoundedRect>(item);
1108         break;
1109     case ItemType::FillRectWithRoundedHole:
1110         ts << downcast<FillRectWithRoundedHole>(item);
1111         break;
1112     case ItemType::FillPath:
1113         ts << downcast<FillPath>(item);
1114         break;
1115     case ItemType::FillEllipse:
1116         ts << downcast<FillEllipse>(item);
1117         break;
1118     case ItemType::StrokeRect:
1119         ts << downcast<StrokeRect>(item);
1120         break;
1121     case ItemType::StrokePath:
1122         ts << downcast<StrokePath>(item);
1123         break;
1124     case ItemType::StrokeEllipse:
1125         ts << downcast<StrokeEllipse>(item);
1126         break;
1127     case ItemType::ClearRect:
1128         ts << downcast<ClearRect>(item);
1129         break;
1130     case ItemType::BeginTransparencyLayer:
1131         ts << downcast<BeginTransparencyLayer>(item);
1132         break;
1133     case ItemType::ApplyDeviceScaleFactor:
1134         ts << downcast<ApplyDeviceScaleFactor>(item);
1135         break;
1136
1137     // Items with no additional data.
1138     case ItemType::Restore:
1139     case ItemType::EndTransparencyLayer:
1140 #if USE(CG)
1141     case ItemType::ApplyStrokePattern:
1142     case ItemType::ApplyFillPattern:
1143 #endif
1144     case ItemType::ClearShadow:
1145         break;
1146     }
1147     return ts;
1148 }
1149
1150 }
1151 }