1 | /* |
2 | * Copyright (C) 2006 Apple Inc. All rights reserved. |
3 | * Copyright (C) 2007 Alp Toker <alp@atoker.com> |
4 | * Copyright (C) 2008, 2009 Dirk Schulze <krit@webkit.org> |
5 | * Copyright (C) 2008 Nuanti Ltd. |
6 | * Copyright (C) 2009 Brent Fulgham <bfulgham@webkit.org> |
7 | * Copyright (C) 2010, 2011 Igalia S.L. |
8 | * Copyright (C) Research In Motion Limited 2010. All rights reserved. |
9 | * Copyright (C) 2012, Intel Corporation |
10 | * |
11 | * Redistribution and use in source and binary forms, with or without |
12 | * modification, are permitted provided that the following conditions |
13 | * are met: |
14 | * 1. Redistributions of source code must retain the above copyright |
15 | * notice, this list of conditions and the following disclaimer. |
16 | * 2. Redistributions in binary form must reproduce the above copyright |
17 | * notice, this list of conditions and the following disclaimer in the |
18 | * documentation and/or other materials provided with the distribution. |
19 | * |
20 | * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY |
21 | * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE |
22 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR |
23 | * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR |
24 | * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, |
25 | * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, |
26 | * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR |
27 | * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY |
28 | * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT |
29 | * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE |
30 | * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
31 | */ |
32 | |
33 | #include "config.h" |
34 | #include "GraphicsContext.h" |
35 | |
36 | #if USE(CAIRO) |
37 | |
38 | #include "AffineTransform.h" |
39 | #include "CairoOperations.h" |
40 | #include "FloatRect.h" |
41 | #include "FloatRoundedRect.h" |
42 | #include "GraphicsContextImpl.h" |
43 | #include "GraphicsContextPlatformPrivateCairo.h" |
44 | #include "ImageBuffer.h" |
45 | #include "IntRect.h" |
46 | #include "NotImplemented.h" |
47 | #include "PlatformContextCairo.h" |
48 | #include "RefPtrCairo.h" |
49 | |
50 | #if PLATFORM(WIN) |
51 | #include <cairo-win32.h> |
52 | #endif |
53 | |
54 | |
55 | namespace WebCore { |
56 | |
57 | void GraphicsContext::platformInit(PlatformContextCairo* platformContext) |
58 | { |
59 | if (!platformContext) |
60 | return; |
61 | |
62 | m_data = new GraphicsContextPlatformPrivate(*platformContext); |
63 | m_data->platformContext.setGraphicsContextPrivate(m_data); |
64 | m_data->syncContext(platformContext->cr()); |
65 | } |
66 | |
67 | void GraphicsContext::platformDestroy() |
68 | { |
69 | if (m_data) { |
70 | m_data->platformContext.setGraphicsContextPrivate(nullptr); |
71 | delete m_data; |
72 | } |
73 | } |
74 | |
75 | AffineTransform GraphicsContext::getCTM(IncludeDeviceScale includeScale) const |
76 | { |
77 | if (paintingDisabled()) |
78 | return AffineTransform(); |
79 | |
80 | if (m_impl) |
81 | return m_impl->getCTM(includeScale); |
82 | |
83 | ASSERT(hasPlatformContext()); |
84 | return Cairo::State::getCTM(*platformContext()); |
85 | } |
86 | |
87 | PlatformContextCairo* GraphicsContext::platformContext() const |
88 | { |
89 | if (m_impl) |
90 | return m_impl->platformContext(); |
91 | return &m_data->platformContext; |
92 | } |
93 | |
94 | void GraphicsContext::savePlatformState() |
95 | { |
96 | ASSERT(hasPlatformContext()); |
97 | Cairo::save(*platformContext()); |
98 | } |
99 | |
100 | void GraphicsContext::restorePlatformState() |
101 | { |
102 | ASSERT(hasPlatformContext()); |
103 | Cairo::restore(*platformContext()); |
104 | } |
105 | |
106 | // Draws a filled rectangle with a stroked border. |
107 | void GraphicsContext::drawRect(const FloatRect& rect, float borderThickness) |
108 | { |
109 | if (paintingDisabled()) |
110 | return; |
111 | |
112 | if (m_impl) { |
113 | m_impl->drawRect(rect, borderThickness); |
114 | return; |
115 | } |
116 | |
117 | ASSERT(!rect.isEmpty()); |
118 | ASSERT(hasPlatformContext()); |
119 | auto& state = this->state(); |
120 | Cairo::drawRect(*platformContext(), rect, borderThickness, state.fillColor, state.strokeStyle, state.strokeColor); |
121 | } |
122 | |
123 | void GraphicsContext::drawNativeImage(const NativeImagePtr& image, const FloatSize& imageSize, const FloatRect& destRect, const FloatRect& srcRect, CompositeOperator compositeOperator, BlendMode blendMode, ImageOrientation orientation) |
124 | { |
125 | if (paintingDisabled()) |
126 | return; |
127 | |
128 | if (m_impl) { |
129 | m_impl->drawNativeImage(image, imageSize, destRect, srcRect, compositeOperator, blendMode, orientation); |
130 | return; |
131 | } |
132 | |
133 | ASSERT(hasPlatformContext()); |
134 | auto& state = this->state(); |
135 | Cairo::drawNativeImage(*platformContext(), image.get(), destRect, srcRect, compositeOperator, blendMode, orientation, state.imageInterpolationQuality, state.alpha, Cairo::ShadowState(state)); |
136 | } |
137 | |
138 | // This is only used to draw borders, so we should not draw shadows. |
139 | void GraphicsContext::drawLine(const FloatPoint& point1, const FloatPoint& point2) |
140 | { |
141 | if (paintingDisabled()) |
142 | return; |
143 | |
144 | if (strokeStyle() == NoStroke) |
145 | return; |
146 | |
147 | if (m_impl) { |
148 | m_impl->drawLine(point1, point2); |
149 | return; |
150 | } |
151 | |
152 | ASSERT(hasPlatformContext()); |
153 | auto& state = this->state(); |
154 | Cairo::drawLine(*platformContext(), point1, point2, state.strokeStyle, state.strokeColor, state.strokeThickness, state.shouldAntialias); |
155 | } |
156 | |
157 | // This method is only used to draw the little circles used in lists. |
158 | void GraphicsContext::drawEllipse(const FloatRect& rect) |
159 | { |
160 | if (paintingDisabled()) |
161 | return; |
162 | |
163 | if (m_impl) { |
164 | m_impl->drawEllipse(rect); |
165 | return; |
166 | } |
167 | |
168 | ASSERT(hasPlatformContext()); |
169 | auto& state = this->state(); |
170 | Cairo::drawEllipse(*platformContext(), rect, state.fillColor, state.strokeStyle, state.strokeColor, state.strokeThickness); |
171 | } |
172 | |
173 | void GraphicsContext::fillPath(const Path& path) |
174 | { |
175 | if (paintingDisabled() || path.isEmpty()) |
176 | return; |
177 | |
178 | if (m_impl) { |
179 | m_impl->fillPath(path); |
180 | return; |
181 | } |
182 | |
183 | ASSERT(hasPlatformContext()); |
184 | auto& state = this->state(); |
185 | Cairo::fillPath(*platformContext(), path, Cairo::FillSource(state), Cairo::ShadowState(state)); |
186 | } |
187 | |
188 | void GraphicsContext::strokePath(const Path& path) |
189 | { |
190 | if (paintingDisabled() || path.isEmpty()) |
191 | return; |
192 | |
193 | if (m_impl) { |
194 | m_impl->strokePath(path); |
195 | return; |
196 | } |
197 | |
198 | ASSERT(hasPlatformContext()); |
199 | auto& state = this->state(); |
200 | Cairo::strokePath(*platformContext(), path, Cairo::StrokeSource(state), Cairo::ShadowState(state)); |
201 | } |
202 | |
203 | void GraphicsContext::fillRect(const FloatRect& rect) |
204 | { |
205 | if (paintingDisabled()) |
206 | return; |
207 | |
208 | if (m_impl) { |
209 | m_impl->fillRect(rect); |
210 | return; |
211 | } |
212 | |
213 | ASSERT(hasPlatformContext()); |
214 | auto& state = this->state(); |
215 | Cairo::fillRect(*platformContext(), rect, Cairo::FillSource(state), Cairo::ShadowState(state)); |
216 | } |
217 | |
218 | void GraphicsContext::fillRect(const FloatRect& rect, const Color& color) |
219 | { |
220 | if (paintingDisabled()) |
221 | return; |
222 | |
223 | if (m_impl) { |
224 | m_impl->fillRect(rect, color); |
225 | return; |
226 | } |
227 | |
228 | ASSERT(hasPlatformContext()); |
229 | Cairo::fillRect(*platformContext(), rect, color, Cairo::ShadowState(state())); |
230 | } |
231 | |
232 | void GraphicsContext::clip(const FloatRect& rect) |
233 | { |
234 | if (paintingDisabled()) |
235 | return; |
236 | |
237 | if (m_impl) { |
238 | m_impl->clip(rect); |
239 | return; |
240 | } |
241 | |
242 | ASSERT(hasPlatformContext()); |
243 | Cairo::clip(*platformContext(), rect); |
244 | } |
245 | |
246 | void GraphicsContext::clipPath(const Path& path, WindRule clipRule) |
247 | { |
248 | if (paintingDisabled()) |
249 | return; |
250 | |
251 | if (m_impl) { |
252 | m_impl->clipPath(path, clipRule); |
253 | return; |
254 | } |
255 | |
256 | ASSERT(hasPlatformContext()); |
257 | Cairo::clipPath(*platformContext(), path, clipRule); |
258 | } |
259 | |
260 | void GraphicsContext::clipToImageBuffer(ImageBuffer& buffer, const FloatRect& destRect) |
261 | { |
262 | if (paintingDisabled()) |
263 | return; |
264 | |
265 | if (m_impl) { |
266 | m_impl->clipToImageBuffer(buffer, destRect); |
267 | return; |
268 | } |
269 | |
270 | RefPtr<Image> image = buffer.copyImage(DontCopyBackingStore); |
271 | if (!image) |
272 | return; |
273 | |
274 | ASSERT(hasPlatformContext()); |
275 | if (auto surface = image->nativeImageForCurrentFrame()) |
276 | Cairo::clipToImageBuffer(*platformContext(), surface.get(), destRect); |
277 | } |
278 | |
279 | IntRect GraphicsContext::clipBounds() const |
280 | { |
281 | if (paintingDisabled()) |
282 | return IntRect(); |
283 | |
284 | if (m_impl) |
285 | return m_impl->clipBounds(); |
286 | |
287 | ASSERT(hasPlatformContext()); |
288 | return Cairo::State::getClipBounds(*platformContext()); |
289 | } |
290 | |
291 | void GraphicsContext::drawFocusRing(const Path& path, float width, float offset, const Color& color) |
292 | { |
293 | if (paintingDisabled()) |
294 | return; |
295 | |
296 | if (m_impl) { |
297 | m_impl->drawFocusRing(path, width, offset, color); |
298 | return; |
299 | } |
300 | |
301 | ASSERT(hasPlatformContext()); |
302 | Cairo::drawFocusRing(*platformContext(), path, width, color); |
303 | } |
304 | |
305 | void GraphicsContext::drawFocusRing(const Vector<FloatRect>& rects, float width, float offset, const Color& color) |
306 | { |
307 | if (paintingDisabled()) |
308 | return; |
309 | |
310 | if (m_impl) { |
311 | m_impl->drawFocusRing(rects, width, offset, color); |
312 | return; |
313 | } |
314 | |
315 | ASSERT(hasPlatformContext()); |
316 | Cairo::drawFocusRing(*platformContext(), rects, width, color); |
317 | } |
318 | |
319 | void GraphicsContext::drawLineForText(const FloatRect& rect, bool printing, bool doubleUnderlines, StrokeStyle) |
320 | { |
321 | drawLinesForText(rect.location(), rect.height(), DashArray { 0, rect.width() }, printing, doubleUnderlines); |
322 | } |
323 | |
324 | void GraphicsContext::drawLinesForText(const FloatPoint& point, float thickness, const DashArray& widths, bool printing, bool doubleUnderlines, StrokeStyle) |
325 | { |
326 | if (paintingDisabled()) |
327 | return; |
328 | |
329 | if (widths.isEmpty()) |
330 | return; |
331 | |
332 | if (m_impl) { |
333 | m_impl->drawLinesForText(point, thickness, widths, printing, doubleUnderlines); |
334 | return; |
335 | } |
336 | |
337 | ASSERT(hasPlatformContext()); |
338 | Cairo::drawLinesForText(*platformContext(), point, thickness, widths, printing, doubleUnderlines, m_state.strokeColor); |
339 | } |
340 | |
341 | void GraphicsContext::drawDotsForDocumentMarker(const FloatRect& rect, DocumentMarkerLineStyle style) |
342 | { |
343 | if (paintingDisabled()) |
344 | return; |
345 | |
346 | if (m_impl) { |
347 | m_impl->drawDotsForDocumentMarker(rect, style); |
348 | return; |
349 | } |
350 | |
351 | ASSERT(hasPlatformContext()); |
352 | Cairo::drawDotsForDocumentMarker(*platformContext(), rect, style); |
353 | } |
354 | |
355 | FloatRect GraphicsContext::roundToDevicePixels(const FloatRect& rect, RoundingMode roundingMode) |
356 | { |
357 | if (paintingDisabled()) |
358 | return rect; |
359 | |
360 | if (m_impl) |
361 | return m_impl->roundToDevicePixels(rect, roundingMode); |
362 | |
363 | return Cairo::State::roundToDevicePixels(*platformContext(), rect); |
364 | } |
365 | |
366 | void GraphicsContext::translate(float x, float y) |
367 | { |
368 | if (paintingDisabled()) |
369 | return; |
370 | |
371 | if (m_impl) { |
372 | m_impl->translate(x, y); |
373 | return; |
374 | } |
375 | |
376 | ASSERT(hasPlatformContext()); |
377 | Cairo::translate(*platformContext(), x, y); |
378 | } |
379 | |
380 | void GraphicsContext::setPlatformFillColor(const Color&) |
381 | { |
382 | // Cairo contexts can't hold separate fill and stroke colors |
383 | // so we set them just before we actually fill or stroke |
384 | } |
385 | |
386 | void GraphicsContext::setPlatformStrokeColor(const Color&) |
387 | { |
388 | // Cairo contexts can't hold separate fill and stroke colors |
389 | // so we set them just before we actually fill or stroke |
390 | } |
391 | |
392 | void GraphicsContext::setPlatformStrokeThickness(float strokeThickness) |
393 | { |
394 | if (paintingDisabled()) |
395 | return; |
396 | |
397 | ASSERT(hasPlatformContext()); |
398 | Cairo::State::setStrokeThickness(*platformContext(), strokeThickness); |
399 | } |
400 | |
401 | void GraphicsContext::setPlatformStrokeStyle(StrokeStyle strokeStyle) |
402 | { |
403 | if (paintingDisabled()) |
404 | return; |
405 | |
406 | ASSERT(hasPlatformContext()); |
407 | Cairo::State::setStrokeStyle(*platformContext(), strokeStyle); |
408 | } |
409 | |
410 | void GraphicsContext::setURLForRect(const URL&, const FloatRect&) |
411 | { |
412 | notImplemented(); |
413 | } |
414 | |
415 | void GraphicsContext::concatCTM(const AffineTransform& transform) |
416 | { |
417 | if (paintingDisabled()) |
418 | return; |
419 | |
420 | if (m_impl) { |
421 | m_impl->concatCTM(transform); |
422 | return; |
423 | } |
424 | |
425 | ASSERT(hasPlatformContext()); |
426 | Cairo::concatCTM(*platformContext(), transform); |
427 | } |
428 | |
429 | void GraphicsContext::setCTM(const AffineTransform& transform) |
430 | { |
431 | if (paintingDisabled()) |
432 | return; |
433 | |
434 | if (m_impl) { |
435 | m_impl->setCTM(transform); |
436 | return; |
437 | } |
438 | |
439 | ASSERT(hasPlatformContext()); |
440 | Cairo::State::setCTM(*platformContext(), transform); |
441 | } |
442 | |
443 | void GraphicsContext::setPlatformShadow(const FloatSize& offset, float, const Color&) |
444 | { |
445 | if (m_state.shadowsIgnoreTransforms) { |
446 | // Meaning that this graphics context is associated with a CanvasRenderingContext |
447 | // We flip the height since CG and HTML5 Canvas have opposite Y axis |
448 | m_state.shadowOffset = { offset.width(), -offset.height() }; |
449 | } |
450 | } |
451 | |
452 | void GraphicsContext::clearPlatformShadow() |
453 | { |
454 | } |
455 | |
456 | void GraphicsContext::beginPlatformTransparencyLayer(float opacity) |
457 | { |
458 | if (paintingDisabled()) |
459 | return; |
460 | |
461 | ASSERT(hasPlatformContext()); |
462 | Cairo::beginTransparencyLayer(*platformContext(), opacity); |
463 | } |
464 | |
465 | void GraphicsContext::endPlatformTransparencyLayer() |
466 | { |
467 | if (paintingDisabled()) |
468 | return; |
469 | |
470 | ASSERT(hasPlatformContext()); |
471 | Cairo::endTransparencyLayer(*platformContext()); |
472 | } |
473 | |
474 | bool GraphicsContext::supportsTransparencyLayers() |
475 | { |
476 | return true; |
477 | } |
478 | |
479 | void GraphicsContext::clearRect(const FloatRect& rect) |
480 | { |
481 | if (paintingDisabled()) |
482 | return; |
483 | |
484 | if (m_impl) { |
485 | m_impl->clearRect(rect); |
486 | return; |
487 | } |
488 | |
489 | ASSERT(hasPlatformContext()); |
490 | Cairo::clearRect(*platformContext(), rect); |
491 | } |
492 | |
493 | void GraphicsContext::strokeRect(const FloatRect& rect, float lineWidth) |
494 | { |
495 | if (paintingDisabled()) |
496 | return; |
497 | |
498 | if (m_impl) { |
499 | m_impl->strokeRect(rect, lineWidth); |
500 | return; |
501 | } |
502 | |
503 | ASSERT(hasPlatformContext()); |
504 | auto& state = this->state(); |
505 | Cairo::strokeRect(*platformContext(), rect, lineWidth, Cairo::StrokeSource(state), Cairo::ShadowState(state)); |
506 | } |
507 | |
508 | void GraphicsContext::setLineCap(LineCap lineCap) |
509 | { |
510 | if (paintingDisabled()) |
511 | return; |
512 | |
513 | if (m_impl) { |
514 | m_impl->setLineCap(lineCap); |
515 | return; |
516 | } |
517 | |
518 | ASSERT(hasPlatformContext()); |
519 | Cairo::setLineCap(*platformContext(), lineCap); |
520 | } |
521 | |
522 | void GraphicsContext::setLineDash(const DashArray& dashes, float dashOffset) |
523 | { |
524 | if (paintingDisabled()) |
525 | return; |
526 | |
527 | if (m_impl) { |
528 | m_impl->setLineDash(dashes, dashOffset); |
529 | return; |
530 | } |
531 | |
532 | ASSERT(hasPlatformContext()); |
533 | Cairo::setLineDash(*platformContext(), dashes, dashOffset); |
534 | } |
535 | |
536 | void GraphicsContext::setLineJoin(LineJoin lineJoin) |
537 | { |
538 | if (paintingDisabled()) |
539 | return; |
540 | |
541 | if (m_impl) { |
542 | m_impl->setLineJoin(lineJoin); |
543 | return; |
544 | } |
545 | |
546 | ASSERT(hasPlatformContext()); |
547 | Cairo::setLineJoin(*platformContext(), lineJoin); |
548 | } |
549 | |
550 | void GraphicsContext::setMiterLimit(float miter) |
551 | { |
552 | if (paintingDisabled()) |
553 | return; |
554 | |
555 | if (m_impl) { |
556 | // Maybe this should be part of the state. |
557 | m_impl->setMiterLimit(miter); |
558 | return; |
559 | } |
560 | |
561 | ASSERT(hasPlatformContext()); |
562 | Cairo::setMiterLimit(*platformContext(), miter); |
563 | } |
564 | |
565 | void GraphicsContext::setPlatformAlpha(float) |
566 | { |
567 | } |
568 | |
569 | void GraphicsContext::setPlatformCompositeOperation(CompositeOperator compositeOperator, BlendMode blendMode) |
570 | { |
571 | if (paintingDisabled()) |
572 | return; |
573 | |
574 | ASSERT(hasPlatformContext()); |
575 | Cairo::State::setCompositeOperation(*platformContext(), compositeOperator, blendMode); |
576 | } |
577 | |
578 | void GraphicsContext::canvasClip(const Path& path, WindRule windRule) |
579 | { |
580 | clipPath(path, windRule); |
581 | } |
582 | |
583 | void GraphicsContext::clipOut(const Path& path) |
584 | { |
585 | if (paintingDisabled()) |
586 | return; |
587 | |
588 | if (m_impl) { |
589 | m_impl->clipOut(path); |
590 | return; |
591 | } |
592 | |
593 | ASSERT(hasPlatformContext()); |
594 | Cairo::clipOut(*platformContext(), path); |
595 | } |
596 | |
597 | void GraphicsContext::rotate(float radians) |
598 | { |
599 | if (paintingDisabled()) |
600 | return; |
601 | |
602 | if (m_impl) { |
603 | m_impl->rotate(radians); |
604 | return; |
605 | } |
606 | |
607 | ASSERT(hasPlatformContext()); |
608 | Cairo::rotate(*platformContext(), radians); |
609 | } |
610 | |
611 | void GraphicsContext::scale(const FloatSize& size) |
612 | { |
613 | if (paintingDisabled()) |
614 | return; |
615 | |
616 | if (m_impl) { |
617 | m_impl->scale(size); |
618 | return; |
619 | } |
620 | |
621 | ASSERT(hasPlatformContext()); |
622 | Cairo::scale(*platformContext(), size); |
623 | } |
624 | |
625 | void GraphicsContext::clipOut(const FloatRect& rect) |
626 | { |
627 | if (paintingDisabled()) |
628 | return; |
629 | |
630 | if (m_impl) { |
631 | m_impl->clipOut(rect); |
632 | return; |
633 | } |
634 | |
635 | ASSERT(hasPlatformContext()); |
636 | Cairo::clipOut(*platformContext(), rect); |
637 | } |
638 | |
639 | void GraphicsContext::platformFillRoundedRect(const FloatRoundedRect& rect, const Color& color) |
640 | { |
641 | if (paintingDisabled()) |
642 | return; |
643 | |
644 | ASSERT(hasPlatformContext()); |
645 | Cairo::fillRoundedRect(*platformContext(), rect, color, Cairo::ShadowState(state())); |
646 | } |
647 | |
648 | void GraphicsContext::fillRectWithRoundedHole(const FloatRect& rect, const FloatRoundedRect& roundedHoleRect, const Color& color) |
649 | { |
650 | if (paintingDisabled() || !color.isValid()) |
651 | return; |
652 | |
653 | if (m_impl) { |
654 | m_impl->fillRectWithRoundedHole(rect, roundedHoleRect, color); |
655 | return; |
656 | } |
657 | |
658 | ASSERT(hasPlatformContext()); |
659 | auto& state = this->state(); |
660 | Cairo::fillRectWithRoundedHole(*platformContext(), rect, roundedHoleRect, Cairo::FillSource(state), Cairo::ShadowState(state)); |
661 | } |
662 | |
663 | void GraphicsContext::drawPattern(Image& image, const FloatRect& destRect, const FloatRect& tileRect, const AffineTransform& patternTransform, const FloatPoint& phase, const FloatSize& spacing, CompositeOperator compositeOperator, BlendMode blendMode) |
664 | { |
665 | if (paintingDisabled()) |
666 | return; |
667 | |
668 | if (m_impl) { |
669 | m_impl->drawPattern(image, destRect, tileRect, patternTransform, phase, spacing, compositeOperator, blendMode); |
670 | return; |
671 | } |
672 | |
673 | ASSERT(hasPlatformContext()); |
674 | if (auto surface = image.nativeImageForCurrentFrame()) |
675 | Cairo::drawPattern(*platformContext(), surface.get(), IntSize(image.size()), destRect, tileRect, patternTransform, phase, compositeOperator, blendMode); |
676 | } |
677 | |
678 | void GraphicsContext::setPlatformShouldAntialias(bool enable) |
679 | { |
680 | if (paintingDisabled()) |
681 | return; |
682 | |
683 | ASSERT(hasPlatformContext()); |
684 | Cairo::State::setShouldAntialias(*platformContext(), enable); |
685 | } |
686 | |
687 | void GraphicsContext::setPlatformImageInterpolationQuality(InterpolationQuality) |
688 | { |
689 | } |
690 | |
691 | bool GraphicsContext::isAcceleratedContext() const |
692 | { |
693 | if (!hasPlatformContext()) |
694 | return false; |
695 | |
696 | return Cairo::State::isAcceleratedContext(*platformContext()); |
697 | } |
698 | |
699 | } // namespace WebCore |
700 | |
701 | #endif // USE(CAIRO) |
702 | |