Remove remaining PLATFORM(CHROMIUM)-guarded code in WebCore
[WebKit-https.git] / Source / WebCore / platform / graphics / GraphicsContext.cpp
1 /*
2  * Copyright (C) 2003, 2004, 2005, 2006, 2009 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. AND ITS CONTRIBUTORS ``AS IS''
14  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
15  * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
16  * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS
17  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
18  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
19  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
20  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
21  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
22  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
23  * THE POSSIBILITY OF SUCH DAMAGE.
24  */
25
26 #include "config.h"
27 #include "GraphicsContext.h"
28
29 #include "BidiResolver.h"
30 #include "BitmapImage.h"
31 #include "Generator.h"
32 #include "ImageBuffer.h"
33 #include "IntRect.h"
34 #include "RoundedRect.h"
35 #include "TextRun.h"
36
37 #include "stdio.h"
38
39 using namespace std;
40
41 namespace WebCore {
42
43 class TextRunIterator {
44 public:
45     TextRunIterator()
46         : m_textRun(0)
47         , m_offset(0)
48     {
49     }
50
51     TextRunIterator(const TextRun* textRun, unsigned offset)
52         : m_textRun(textRun)
53         , m_offset(offset)
54     {
55     }
56
57     TextRunIterator(const TextRunIterator& other)
58         : m_textRun(other.m_textRun)
59         , m_offset(other.m_offset)
60     {
61     }
62
63     unsigned offset() const { return m_offset; }
64     void increment() { m_offset++; }
65     bool atEnd() const { return !m_textRun || m_offset >= m_textRun->length(); }
66     UChar current() const { return (*m_textRun)[m_offset]; }
67     WTF::Unicode::Direction direction() const { return atEnd() ? WTF::Unicode::OtherNeutral : WTF::Unicode::direction(current()); }
68
69     bool operator==(const TextRunIterator& other)
70     {
71         return m_offset == other.m_offset && m_textRun == other.m_textRun;
72     }
73
74     bool operator!=(const TextRunIterator& other) { return !operator==(other); }
75
76 private:
77     const TextRun* m_textRun;
78     int m_offset;
79 };
80
81 GraphicsContext::GraphicsContext(PlatformGraphicsContext* platformGraphicsContext)
82     : m_updatingControlTints(false)
83     , m_transparencyCount(0)
84 {
85     platformInit(platformGraphicsContext);
86 }
87
88 GraphicsContext::~GraphicsContext()
89 {
90     ASSERT(m_stack.isEmpty());
91     ASSERT(!m_transparencyCount);
92     platformDestroy();
93 }
94
95 void GraphicsContext::save()
96 {
97     if (paintingDisabled())
98         return;
99
100     m_stack.append(m_state);
101
102     savePlatformState();
103 }
104
105 void GraphicsContext::restore()
106 {
107     if (paintingDisabled())
108         return;
109
110     if (m_stack.isEmpty()) {
111         LOG_ERROR("ERROR void GraphicsContext::restore() stack is empty");
112         return;
113     }
114     m_state = m_stack.last();
115     m_stack.removeLast();
116
117     restorePlatformState();
118 }
119
120 void GraphicsContext::setStrokeThickness(float thickness)
121 {
122     m_state.strokeThickness = thickness;
123     setPlatformStrokeThickness(thickness);
124 }
125
126 void GraphicsContext::setStrokeStyle(StrokeStyle style)
127 {
128     m_state.strokeStyle = style;
129     setPlatformStrokeStyle(style);
130 }
131
132 void GraphicsContext::setStrokeColor(const Color& color, ColorSpace colorSpace)
133 {
134     m_state.strokeColor = color;
135     m_state.strokeColorSpace = colorSpace;
136     m_state.strokeGradient.clear();
137     m_state.strokePattern.clear();
138     setPlatformStrokeColor(color, colorSpace);
139 }
140
141 void GraphicsContext::setShadow(const FloatSize& offset, float blur, const Color& color, ColorSpace colorSpace)
142 {
143     m_state.shadowOffset = offset;
144     m_state.shadowBlur = blur;
145     m_state.shadowColor = color;
146     m_state.shadowColorSpace = colorSpace;
147     setPlatformShadow(offset, blur, color, colorSpace);
148 }
149
150 void GraphicsContext::setLegacyShadow(const FloatSize& offset, float blur, const Color& color, ColorSpace colorSpace)
151 {
152     m_state.shadowOffset = offset;
153     m_state.shadowBlur = blur;
154     m_state.shadowColor = color;
155     m_state.shadowColorSpace = colorSpace;
156 #if USE(CG)
157     m_state.shadowsUseLegacyRadius = true;
158 #endif
159     setPlatformShadow(offset, blur, color, colorSpace);
160 }
161
162 void GraphicsContext::clearShadow()
163 {
164     m_state.shadowOffset = FloatSize();
165     m_state.shadowBlur = 0;
166     m_state.shadowColor = Color();
167     m_state.shadowColorSpace = ColorSpaceDeviceRGB;
168     clearPlatformShadow();
169 }
170
171 bool GraphicsContext::hasShadow() const
172 {
173     return m_state.shadowColor.isValid() && m_state.shadowColor.alpha()
174            && (m_state.shadowBlur || m_state.shadowOffset.width() || m_state.shadowOffset.height());
175 }
176
177 bool GraphicsContext::getShadow(FloatSize& offset, float& blur, Color& color, ColorSpace& colorSpace) const
178 {
179     offset = m_state.shadowOffset;
180     blur = m_state.shadowBlur;
181     color = m_state.shadowColor;
182     colorSpace = m_state.shadowColorSpace;
183
184     return hasShadow();
185 }
186
187 bool GraphicsContext::hasBlurredShadow() const
188 {
189     return m_state.shadowColor.isValid() && m_state.shadowColor.alpha() && m_state.shadowBlur;
190 }
191
192 #if PLATFORM(QT) || USE(CAIRO)
193 bool GraphicsContext::mustUseShadowBlur() const
194 {
195     // We can't avoid ShadowBlur if the shadow has blur.
196     if (hasBlurredShadow())
197         return true;
198     // We can avoid ShadowBlur and optimize, since we're not drawing on a
199     // canvas and box shadows are affected by the transformation matrix.
200     if (!m_state.shadowsIgnoreTransforms)
201         return false;
202     // We can avoid ShadowBlur, since there are no transformations to apply to the canvas.
203     if (getCTM().isIdentity())
204         return false;
205     // Otherwise, no chance avoiding ShadowBlur.
206     return true;
207 }
208 #endif
209
210 float GraphicsContext::strokeThickness() const
211 {
212     return m_state.strokeThickness;
213 }
214
215 StrokeStyle GraphicsContext::strokeStyle() const
216 {
217     return m_state.strokeStyle;
218 }
219
220 Color GraphicsContext::strokeColor() const
221 {
222     return m_state.strokeColor;
223 }
224
225 ColorSpace GraphicsContext::strokeColorSpace() const
226 {
227     return m_state.strokeColorSpace;
228 }
229
230 WindRule GraphicsContext::fillRule() const
231 {
232     return m_state.fillRule;
233 }
234
235 void GraphicsContext::setFillRule(WindRule fillRule)
236 {
237     m_state.fillRule = fillRule;
238 }
239
240 void GraphicsContext::setFillColor(const Color& color, ColorSpace colorSpace)
241 {
242     m_state.fillColor = color;
243     m_state.fillColorSpace = colorSpace;
244     m_state.fillGradient.clear();
245     m_state.fillPattern.clear();
246     setPlatformFillColor(color, colorSpace);
247 }
248
249 Color GraphicsContext::fillColor() const
250 {
251     return m_state.fillColor;
252 }
253
254 ColorSpace GraphicsContext::fillColorSpace() const
255 {
256     return m_state.fillColorSpace;
257 }
258
259 void GraphicsContext::setShouldAntialias(bool b)
260 {
261     m_state.shouldAntialias = b;
262     setPlatformShouldAntialias(b);
263 }
264
265 bool GraphicsContext::shouldAntialias() const
266 {
267     return m_state.shouldAntialias;
268 }
269
270 void GraphicsContext::setShouldSmoothFonts(bool b)
271 {
272     m_state.shouldSmoothFonts = b;
273     setPlatformShouldSmoothFonts(b);
274 }
275
276 bool GraphicsContext::shouldSmoothFonts() const
277 {
278     return m_state.shouldSmoothFonts;
279 }
280
281 void GraphicsContext::setShouldSubpixelQuantizeFonts(bool b)
282 {
283     m_state.shouldSubpixelQuantizeFonts = b;
284 }
285
286 bool GraphicsContext::shouldSubpixelQuantizeFonts() const
287 {
288     return m_state.shouldSubpixelQuantizeFonts;
289 }
290
291 const GraphicsContextState& GraphicsContext::state() const
292 {
293     return m_state;
294 }
295
296 void GraphicsContext::setStrokePattern(PassRefPtr<Pattern> pattern)
297 {
298     ASSERT(pattern);
299     if (!pattern) {
300         setStrokeColor(Color::black, ColorSpaceDeviceRGB);
301         return;
302     }
303     m_state.strokeGradient.clear();
304     m_state.strokePattern = pattern;
305 }
306
307 void GraphicsContext::setFillPattern(PassRefPtr<Pattern> pattern)
308 {
309     ASSERT(pattern);
310     if (!pattern) {
311         setFillColor(Color::black, ColorSpaceDeviceRGB);
312         return;
313     }
314     m_state.fillGradient.clear();
315     m_state.fillPattern = pattern;
316 }
317
318 void GraphicsContext::setStrokeGradient(PassRefPtr<Gradient> gradient)
319 {
320     ASSERT(gradient);
321     if (!gradient) {
322         setStrokeColor(Color::black, ColorSpaceDeviceRGB);
323         return;
324     }
325     m_state.strokeGradient = gradient;
326     m_state.strokePattern.clear();
327 }
328
329 void GraphicsContext::setFillGradient(PassRefPtr<Gradient> gradient)
330 {
331     ASSERT(gradient);
332     if (!gradient) {
333         setFillColor(Color::black, ColorSpaceDeviceRGB);
334         return;
335     }
336     m_state.fillGradient = gradient;
337     m_state.fillPattern.clear();
338 }
339
340 Gradient* GraphicsContext::fillGradient() const
341 {
342     return m_state.fillGradient.get();
343 }
344
345 Gradient* GraphicsContext::strokeGradient() const
346 {
347     return m_state.strokeGradient.get();
348 }
349
350 Pattern* GraphicsContext::fillPattern() const
351 {
352     return m_state.fillPattern.get();
353 }
354
355 Pattern* GraphicsContext::strokePattern() const
356 {
357     return m_state.strokePattern.get();
358 }
359
360 void GraphicsContext::setShadowsIgnoreTransforms(bool ignoreTransforms)
361 {
362     m_state.shadowsIgnoreTransforms = ignoreTransforms;
363 }
364
365 bool GraphicsContext::shadowsIgnoreTransforms() const
366 {
367     return m_state.shadowsIgnoreTransforms;
368 }
369
370 void GraphicsContext::beginTransparencyLayer(float opacity)
371 {
372     beginPlatformTransparencyLayer(opacity);
373     ++m_transparencyCount;
374 }
375
376 void GraphicsContext::endTransparencyLayer()
377 {
378     endPlatformTransparencyLayer();
379     ASSERT(m_transparencyCount > 0);
380     --m_transparencyCount;
381 }
382
383 #if !PLATFORM(QT)
384 bool GraphicsContext::isInTransparencyLayer() const
385 {
386     return (m_transparencyCount > 0) && supportsTransparencyLayers();
387 }
388 #endif
389
390 bool GraphicsContext::updatingControlTints() const
391 {
392     return m_updatingControlTints;
393 }
394
395 void GraphicsContext::setUpdatingControlTints(bool b)
396 {
397     setPaintingDisabled(b);
398     m_updatingControlTints = b;
399 }
400
401 void GraphicsContext::setPaintingDisabled(bool f)
402 {
403     m_state.paintingDisabled = f;
404 }
405
406 bool GraphicsContext::paintingDisabled() const
407 {
408     return m_state.paintingDisabled;
409 }
410
411 #if !OS(WINCE) || PLATFORM(QT)
412 void GraphicsContext::drawText(const Font& font, const TextRun& run, const FloatPoint& point, int from, int to)
413 {
414     if (paintingDisabled())
415         return;
416
417     font.drawText(this, run, point, from, to);
418 }
419 #endif
420
421 void GraphicsContext::drawEmphasisMarks(const Font& font, const TextRun& run, const AtomicString& mark, const FloatPoint& point, int from, int to)
422 {
423     if (paintingDisabled())
424         return;
425
426     font.drawEmphasisMarks(this, run, mark, point, from, to);
427 }
428
429 void GraphicsContext::drawBidiText(const Font& font, const TextRun& run, const FloatPoint& point, Font::CustomFontNotReadyAction customFontNotReadyAction)
430 {
431     if (paintingDisabled())
432         return;
433
434     BidiResolver<TextRunIterator, BidiCharacterRun> bidiResolver;
435     bidiResolver.setStatus(BidiStatus(run.direction(), run.directionalOverride()));
436     bidiResolver.setPositionIgnoringNestedIsolates(TextRunIterator(&run, 0));
437
438     // FIXME: This ownership should be reversed. We should pass BidiRunList
439     // to BidiResolver in createBidiRunsForLine.
440     BidiRunList<BidiCharacterRun>& bidiRuns = bidiResolver.runs();
441     bidiResolver.createBidiRunsForLine(TextRunIterator(&run, run.length()));
442     if (!bidiRuns.runCount())
443         return;
444
445     FloatPoint currPoint = point;
446     BidiCharacterRun* bidiRun = bidiRuns.firstRun();
447     while (bidiRun) {
448         TextRun subrun = run.subRun(bidiRun->start(), bidiRun->stop() - bidiRun->start());
449         bool isRTL = bidiRun->level() % 2;
450         subrun.setDirection(isRTL ? RTL : LTR);
451         subrun.setDirectionalOverride(bidiRun->dirOverride(false));
452
453         font.drawText(this, subrun, currPoint, 0, -1, customFontNotReadyAction);
454
455         bidiRun = bidiRun->next();
456         // FIXME: Have Font::drawText return the width of what it drew so that we don't have to re-measure here.
457         if (bidiRun)
458             currPoint.move(font.width(subrun), 0);
459     }
460
461     bidiRuns.deleteRuns();
462 }
463
464 void GraphicsContext::drawHighlightForText(const Font& font, const TextRun& run, const FloatPoint& point, int h, const Color& backgroundColor, ColorSpace colorSpace, int from, int to)
465 {
466     if (paintingDisabled())
467         return;
468
469     fillRect(font.selectionRectForText(run, point, h, from, to), backgroundColor, colorSpace);
470 }
471
472 void GraphicsContext::drawImage(Image* image, ColorSpace styleColorSpace, const IntPoint& p, CompositeOperator op, RespectImageOrientationEnum shouldRespectImageOrientation)
473 {
474     if (!image)
475         return;
476     drawImage(image, styleColorSpace, FloatRect(IntRect(p, image->size())), FloatRect(FloatPoint(), FloatSize(image->size())), op, shouldRespectImageOrientation);
477 }
478
479 void GraphicsContext::drawImage(Image* image, ColorSpace styleColorSpace, const IntRect& r, CompositeOperator op, RespectImageOrientationEnum shouldRespectImageOrientation, bool useLowQualityScale)
480 {
481     if (!image)
482         return;
483     drawImage(image, styleColorSpace, FloatRect(r), FloatRect(FloatPoint(), FloatSize(image->size())), op, shouldRespectImageOrientation, useLowQualityScale);
484 }
485
486 void GraphicsContext::drawImage(Image* image, ColorSpace styleColorSpace, const IntPoint& dest, const IntRect& srcRect, CompositeOperator op, RespectImageOrientationEnum shouldRespectImageOrientation)
487 {
488     drawImage(image, styleColorSpace, FloatRect(IntRect(dest, srcRect.size())), FloatRect(srcRect), op, shouldRespectImageOrientation);
489 }
490
491 void GraphicsContext::drawImage(Image* image, ColorSpace styleColorSpace, const FloatRect& dest, const FloatRect& src, CompositeOperator op, RespectImageOrientationEnum shouldRespectImageOrientation, bool useLowQualityScale)
492 {
493     drawImage(image, styleColorSpace, dest, src, op, BlendModeNormal, shouldRespectImageOrientation, useLowQualityScale);
494 }
495
496 void GraphicsContext::drawImage(Image* image, ColorSpace styleColorSpace, const FloatRect& dest)
497 {
498     if (!image)
499         return;
500     drawImage(image, styleColorSpace, dest, FloatRect(IntRect(IntPoint(), image->size())));
501 }
502
503 void GraphicsContext::drawImage(Image* image, ColorSpace styleColorSpace, const FloatRect& dest, const FloatRect& src, CompositeOperator op, BlendMode blendMode, RespectImageOrientationEnum shouldRespectImageOrientation, bool useLowQualityScale)
504 {    if (paintingDisabled() || !image)
505         return;
506
507     InterpolationQuality previousInterpolationQuality = InterpolationDefault;
508
509     if (useLowQualityScale) {
510         previousInterpolationQuality = imageInterpolationQuality();
511         // FIXME (49002): Should be InterpolationLow
512         setImageInterpolationQuality(InterpolationNone);
513     }
514
515     image->draw(this, dest, src, styleColorSpace, op, blendMode, shouldRespectImageOrientation);
516
517     if (useLowQualityScale)
518         setImageInterpolationQuality(previousInterpolationQuality);
519 }
520
521 void GraphicsContext::drawTiledImage(Image* image, ColorSpace styleColorSpace, const IntRect& destRect, const IntPoint& srcPoint, const IntSize& tileSize, CompositeOperator op, bool useLowQualityScale, BlendMode blendMode)
522 {
523     if (paintingDisabled() || !image)
524         return;
525
526     if (useLowQualityScale) {
527         InterpolationQuality previousInterpolationQuality = imageInterpolationQuality();
528         setImageInterpolationQuality(InterpolationLow);
529         image->drawTiled(this, destRect, srcPoint, tileSize, styleColorSpace, op, blendMode);
530         setImageInterpolationQuality(previousInterpolationQuality);
531     } else
532         image->drawTiled(this, destRect, srcPoint, tileSize, styleColorSpace, op, blendMode);
533 }
534
535 void GraphicsContext::drawTiledImage(Image* image, ColorSpace styleColorSpace, const IntRect& dest, const IntRect& srcRect,
536     const FloatSize& tileScaleFactor, Image::TileRule hRule, Image::TileRule vRule, CompositeOperator op, bool useLowQualityScale)
537 {
538     if (paintingDisabled() || !image)
539         return;
540
541     if (hRule == Image::StretchTile && vRule == Image::StretchTile) {
542         // Just do a scale.
543         drawImage(image, styleColorSpace, dest, srcRect, op);
544         return;
545     }
546
547     if (useLowQualityScale) {
548         InterpolationQuality previousInterpolationQuality = imageInterpolationQuality();
549         setImageInterpolationQuality(InterpolationLow);
550         image->drawTiled(this, dest, srcRect, tileScaleFactor, hRule, vRule, styleColorSpace, op);
551         setImageInterpolationQuality(previousInterpolationQuality);
552     } else
553         image->drawTiled(this, dest, srcRect, tileScaleFactor, hRule, vRule, styleColorSpace, op);
554 }
555
556 void GraphicsContext::drawImageBuffer(ImageBuffer* image, ColorSpace styleColorSpace, const IntPoint& p, CompositeOperator op, BlendMode blendMode)
557 {
558     if (!image)
559         return;
560     drawImageBuffer(image, styleColorSpace, FloatRect(IntRect(p, image->logicalSize())), FloatRect(FloatPoint(), FloatSize(image->logicalSize())), op, blendMode);
561 }
562
563 void GraphicsContext::drawImageBuffer(ImageBuffer* image, ColorSpace styleColorSpace, const IntRect& r, CompositeOperator op, BlendMode blendMode, bool useLowQualityScale)
564 {
565     if (!image)
566         return;
567     drawImageBuffer(image, styleColorSpace, FloatRect(r), FloatRect(FloatPoint(), FloatSize(image->logicalSize())), op, blendMode, useLowQualityScale);
568 }
569
570 void GraphicsContext::drawImageBuffer(ImageBuffer* image, ColorSpace styleColorSpace, const IntPoint& dest, const IntRect& srcRect, CompositeOperator op, BlendMode blendMode)
571 {
572     drawImageBuffer(image, styleColorSpace, FloatRect(IntRect(dest, srcRect.size())), FloatRect(srcRect), op, blendMode);
573 }
574
575 void GraphicsContext::drawImageBuffer(ImageBuffer* image, ColorSpace styleColorSpace, const IntRect& dest, const IntRect& srcRect, CompositeOperator op, BlendMode blendMode, bool useLowQualityScale)
576 {
577     drawImageBuffer(image, styleColorSpace, FloatRect(dest), FloatRect(srcRect), op, blendMode, useLowQualityScale);
578 }
579
580 void GraphicsContext::drawImageBuffer(ImageBuffer* image, ColorSpace styleColorSpace, const FloatRect& dest)
581 {
582     if (!image)
583         return;
584     drawImageBuffer(image, styleColorSpace, dest, FloatRect(IntRect(IntPoint(), image->logicalSize())));
585 }
586
587 void GraphicsContext::drawImageBuffer(ImageBuffer* image, ColorSpace styleColorSpace, const FloatRect& dest, const FloatRect& src, CompositeOperator op, BlendMode blendMode, bool useLowQualityScale)
588 {
589     if (paintingDisabled() || !image)
590         return;
591
592     if (useLowQualityScale) {
593         InterpolationQuality previousInterpolationQuality = imageInterpolationQuality();
594         // FIXME (49002): Should be InterpolationLow
595         setImageInterpolationQuality(InterpolationNone);
596         image->draw(this, styleColorSpace, dest, src, op, blendMode, useLowQualityScale);
597         setImageInterpolationQuality(previousInterpolationQuality);
598     } else
599         image->draw(this, styleColorSpace, dest, src, op, blendMode, useLowQualityScale);
600 }
601
602 #if !PLATFORM(QT)
603 void GraphicsContext::clip(const IntRect& rect)
604 {
605     clip(FloatRect(rect));
606 }
607 #endif
608
609 #if !USE(SKIA)
610 void GraphicsContext::clipRoundedRect(const RoundedRect& rect)
611 {
612     if (paintingDisabled())
613         return;
614
615     if (!rect.isRounded()) {
616         clip(rect.rect());
617         return;
618     }
619
620     Path path;
621     path.addRoundedRect(rect);
622     clip(path);
623 }
624 #endif
625
626 void GraphicsContext::clipOutRoundedRect(const RoundedRect& rect)
627 {
628     if (paintingDisabled())
629         return;
630
631     if (!rect.isRounded()) {
632         clipOut(rect.rect());
633         return;
634     }
635
636     Path path;
637     path.addRoundedRect(rect);
638     clipOut(path);
639 }
640
641 void GraphicsContext::clipToImageBuffer(ImageBuffer* buffer, const FloatRect& rect)
642 {
643     if (paintingDisabled())
644         return;
645     buffer->clip(this, rect);
646 }
647
648 #if !USE(CG) && !PLATFORM(QT) && !USE(CAIRO)
649 IntRect GraphicsContext::clipBounds() const
650 {
651     ASSERT_NOT_REACHED();
652     return IntRect();
653 }
654 #endif
655
656 TextDrawingModeFlags GraphicsContext::textDrawingMode() const
657 {
658     return m_state.textDrawingMode;
659 }
660
661 void GraphicsContext::setTextDrawingMode(TextDrawingModeFlags mode)
662 {
663     m_state.textDrawingMode = mode;
664     if (paintingDisabled())
665         return;
666     setPlatformTextDrawingMode(mode);
667 }
668
669 void GraphicsContext::fillRect(const FloatRect& rect, Generator& generator)
670 {
671     if (paintingDisabled())
672         return;
673     generator.fill(this, rect);
674 }
675
676 void GraphicsContext::fillRect(const FloatRect& rect, const Color& color, ColorSpace styleColorSpace, CompositeOperator op)
677 {
678     if (paintingDisabled())
679         return;
680
681     CompositeOperator previousOperator = compositeOperation();
682     setCompositeOperation(op);
683     fillRect(rect, color, styleColorSpace);
684     setCompositeOperation(previousOperator);
685 }
686
687 void GraphicsContext::fillRoundedRect(const RoundedRect& rect, const Color& color, ColorSpace colorSpace)
688 {
689     if (rect.isRounded())
690         fillRoundedRect(rect.rect(), rect.radii().topLeft(), rect.radii().topRight(), rect.radii().bottomLeft(), rect.radii().bottomRight(), color, colorSpace);
691     else
692         fillRect(rect.rect(), color, colorSpace);
693 }
694
695 #if !USE(CG) && !PLATFORM(QT)
696 void GraphicsContext::fillRectWithRoundedHole(const IntRect& rect, const RoundedRect& roundedHoleRect, const Color& color, ColorSpace colorSpace)
697 {
698     if (paintingDisabled())
699         return;
700
701     Path path;
702     path.addRect(rect);
703
704     if (!roundedHoleRect.radii().isZero())
705         path.addRoundedRect(roundedHoleRect);
706     else
707         path.addRect(roundedHoleRect.rect());
708
709     WindRule oldFillRule = fillRule();
710     Color oldFillColor = fillColor();
711     ColorSpace oldFillColorSpace = fillColorSpace();
712     
713     setFillRule(RULE_EVENODD);
714     setFillColor(color, colorSpace);
715
716     fillPath(path);
717     
718     setFillRule(oldFillRule);
719     setFillColor(oldFillColor, oldFillColorSpace);
720 }
721 #endif
722
723 void GraphicsContext::setCompositeOperation(CompositeOperator compositeOperation, BlendMode blendMode)
724 {
725     m_state.compositeOperator = compositeOperation;
726     m_state.blendMode = blendMode;
727     setPlatformCompositeOperation(compositeOperation, blendMode);
728 }
729
730 CompositeOperator GraphicsContext::compositeOperation() const
731 {
732     return m_state.compositeOperator;
733 }
734
735 BlendMode GraphicsContext::blendModeOperation() const
736 {
737     return m_state.blendMode;
738 }
739
740 #if !USE(CG) && !USE(SKIA)
741 // Implement this if you want to go ahead and push the drawing mode into your native context
742 // immediately.
743 void GraphicsContext::setPlatformTextDrawingMode(TextDrawingModeFlags)
744 {
745 }
746 #endif
747
748 #if !PLATFORM(QT) && !USE(CAIRO) && !USE(SKIA) && !PLATFORM(OPENVG)
749 void GraphicsContext::setPlatformStrokeStyle(StrokeStyle)
750 {
751 }
752 #endif
753
754 #if !USE(CG)
755 void GraphicsContext::setPlatformShouldSmoothFonts(bool)
756 {
757 }
758 #endif
759
760 #if !USE(SKIA) && !USE(CG)
761 bool GraphicsContext::isAcceleratedContext() const
762 {
763     return false;
764 }
765 #endif
766
767 void GraphicsContext::adjustLineToPixelBoundaries(FloatPoint& p1, FloatPoint& p2, float strokeWidth, StrokeStyle penStyle)
768 {
769     // For odd widths, we add in 0.5 to the appropriate x/y so that the float arithmetic
770     // works out.  For example, with a border width of 3, WebKit will pass us (y1+y2)/2, e.g.,
771     // (50+53)/2 = 103/2 = 51 when we want 51.5.  It is always true that an even width gave
772     // us a perfect position, but an odd width gave us a position that is off by exactly 0.5.
773     if (penStyle == DottedStroke || penStyle == DashedStroke) {
774         if (p1.x() == p2.x()) {
775             p1.setY(p1.y() + strokeWidth);
776             p2.setY(p2.y() - strokeWidth);
777         } else {
778             p1.setX(p1.x() + strokeWidth);
779             p2.setX(p2.x() - strokeWidth);
780         }
781     }
782
783     if (static_cast<int>(strokeWidth) % 2) { //odd
784         if (p1.x() == p2.x()) {
785             // We're a vertical line.  Adjust our x.
786             p1.setX(p1.x() + 0.5f);
787             p2.setX(p2.x() + 0.5f);
788         } else {
789             // We're a horizontal line. Adjust our y.
790             p1.setY(p1.y() + 0.5f);
791             p2.setY(p2.y() + 0.5f);
792         }
793     }
794 }
795
796 static bool scalesMatch(AffineTransform a, AffineTransform b)
797 {
798     return a.xScale() == b.xScale() && a.yScale() == b.yScale();
799 }
800
801 PassOwnPtr<ImageBuffer> GraphicsContext::createCompatibleBuffer(const IntSize& size, bool hasAlpha) const
802 {
803     // Make the buffer larger if the context's transform is scaling it so we need a higher
804     // resolution than one pixel per unit. Also set up a corresponding scale factor on the
805     // graphics context.
806
807     AffineTransform transform = getCTM(DefinitelyIncludeDeviceScale);
808     IntSize scaledSize(static_cast<int>(ceil(size.width() * transform.xScale())), static_cast<int>(ceil(size.height() * transform.yScale())));
809
810     OwnPtr<ImageBuffer> buffer = ImageBuffer::createCompatibleBuffer(scaledSize, 1, ColorSpaceDeviceRGB, this, hasAlpha);
811     if (!buffer)
812         return nullptr;
813
814     buffer->context()->scale(FloatSize(static_cast<float>(scaledSize.width()) / size.width(),
815         static_cast<float>(scaledSize.height()) / size.height()));
816
817     return buffer.release();
818 }
819
820 bool GraphicsContext::isCompatibleWithBuffer(ImageBuffer* buffer) const
821 {
822     GraphicsContext* bufferContext = buffer->context();
823
824     return scalesMatch(getCTM(), bufferContext->getCTM()) && isAcceleratedContext() == bufferContext->isAcceleratedContext();
825 }
826
827 #if !USE(CG)
828 void GraphicsContext::platformApplyDeviceScaleFactor(float)
829 {
830 }
831 #endif
832
833 void GraphicsContext::applyDeviceScaleFactor(float deviceScaleFactor)
834 {
835     scale(FloatSize(deviceScaleFactor, deviceScaleFactor));
836     platformApplyDeviceScaleFactor(deviceScaleFactor);
837 }
838
839 void GraphicsContext::fillEllipse(const FloatRect& ellipse)
840 {
841     platformFillEllipse(ellipse);
842 }
843
844 void GraphicsContext::strokeEllipse(const FloatRect& ellipse)
845 {
846     platformStrokeEllipse(ellipse);
847 }
848
849 void GraphicsContext::fillEllipseAsPath(const FloatRect& ellipse)
850 {
851     Path path;
852     path.addEllipse(ellipse);
853     fillPath(path);
854 }
855
856 void GraphicsContext::strokeEllipseAsPath(const FloatRect& ellipse)
857 {
858     Path path;
859     path.addEllipse(ellipse);
860     strokePath(path);
861 }
862
863 #if !USE(CG) && !USE(SKIA) // append && !USE(MYPLATFORM) here to optimize ellipses on your platform.
864 void GraphicsContext::platformFillEllipse(const FloatRect& ellipse)
865 {
866     if (paintingDisabled())
867         return;
868
869     fillEllipseAsPath(ellipse);
870 }
871
872 void GraphicsContext::platformStrokeEllipse(const FloatRect& ellipse)
873 {
874     if (paintingDisabled())
875         return;
876
877     strokeEllipseAsPath(ellipse);
878 }
879 #endif
880
881 }