2 * Copyright (C) 2003, 2004, 2005, 2006, 2009 Apple Inc. All rights reserved.
4 * Redistribution and use in source and binary forms, with or without
5 * modification, are permitted provided that the following conditions
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.
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.
27 #include "GraphicsContext.h"
29 #include "BidiResolver.h"
30 #include "BitmapImage.h"
31 #include "Generator.h"
32 #include "ImageBuffer.h"
34 #include "RoundedRect.h"
43 class TextRunIterator {
51 TextRunIterator(const TextRun* textRun, unsigned offset)
57 TextRunIterator(const TextRunIterator& other)
58 : m_textRun(other.m_textRun)
59 , m_offset(other.m_offset)
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()); }
69 bool operator==(const TextRunIterator& other)
71 return m_offset == other.m_offset && m_textRun == other.m_textRun;
74 bool operator!=(const TextRunIterator& other) { return !operator==(other); }
77 const TextRun* m_textRun;
81 GraphicsContext::GraphicsContext(PlatformGraphicsContext* platformGraphicsContext)
82 : m_updatingControlTints(false)
83 , m_transparencyCount(0)
85 platformInit(platformGraphicsContext);
88 GraphicsContext::~GraphicsContext()
90 ASSERT(m_stack.isEmpty());
91 ASSERT(!m_transparencyCount);
95 void GraphicsContext::save()
97 if (paintingDisabled())
100 m_stack.append(m_state);
105 void GraphicsContext::restore()
107 if (paintingDisabled())
110 if (m_stack.isEmpty()) {
111 LOG_ERROR("ERROR void GraphicsContext::restore() stack is empty");
114 m_state = m_stack.last();
115 m_stack.removeLast();
117 restorePlatformState();
120 void GraphicsContext::setStrokeThickness(float thickness)
122 m_state.strokeThickness = thickness;
123 setPlatformStrokeThickness(thickness);
126 void GraphicsContext::setStrokeStyle(StrokeStyle style)
128 m_state.strokeStyle = style;
129 setPlatformStrokeStyle(style);
132 void GraphicsContext::setStrokeColor(const Color& color, ColorSpace colorSpace)
134 m_state.strokeColor = color;
135 m_state.strokeColorSpace = colorSpace;
136 m_state.strokeGradient.clear();
137 m_state.strokePattern.clear();
138 setPlatformStrokeColor(color, colorSpace);
141 void GraphicsContext::setShadow(const FloatSize& offset, float blur, const Color& color, ColorSpace colorSpace)
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);
150 void GraphicsContext::setLegacyShadow(const FloatSize& offset, float blur, const Color& color, ColorSpace colorSpace)
152 m_state.shadowOffset = offset;
153 m_state.shadowBlur = blur;
154 m_state.shadowColor = color;
155 m_state.shadowColorSpace = colorSpace;
157 m_state.shadowsUseLegacyRadius = true;
159 setPlatformShadow(offset, blur, color, colorSpace);
162 void GraphicsContext::clearShadow()
164 m_state.shadowOffset = FloatSize();
165 m_state.shadowBlur = 0;
166 m_state.shadowColor = Color();
167 m_state.shadowColorSpace = ColorSpaceDeviceRGB;
168 clearPlatformShadow();
171 bool GraphicsContext::hasShadow() const
173 return m_state.shadowColor.isValid() && m_state.shadowColor.alpha()
174 && (m_state.shadowBlur || m_state.shadowOffset.width() || m_state.shadowOffset.height());
177 bool GraphicsContext::getShadow(FloatSize& offset, float& blur, Color& color, ColorSpace& colorSpace) const
179 offset = m_state.shadowOffset;
180 blur = m_state.shadowBlur;
181 color = m_state.shadowColor;
182 colorSpace = m_state.shadowColorSpace;
187 float GraphicsContext::strokeThickness() const
189 return m_state.strokeThickness;
192 StrokeStyle GraphicsContext::strokeStyle() const
194 return m_state.strokeStyle;
197 Color GraphicsContext::strokeColor() const
199 return m_state.strokeColor;
202 ColorSpace GraphicsContext::strokeColorSpace() const
204 return m_state.strokeColorSpace;
207 WindRule GraphicsContext::fillRule() const
209 return m_state.fillRule;
212 void GraphicsContext::setFillRule(WindRule fillRule)
214 m_state.fillRule = fillRule;
217 void GraphicsContext::setFillColor(const Color& color, ColorSpace colorSpace)
219 m_state.fillColor = color;
220 m_state.fillColorSpace = colorSpace;
221 m_state.fillGradient.clear();
222 m_state.fillPattern.clear();
223 setPlatformFillColor(color, colorSpace);
226 Color GraphicsContext::fillColor() const
228 return m_state.fillColor;
231 ColorSpace GraphicsContext::fillColorSpace() const
233 return m_state.fillColorSpace;
236 void GraphicsContext::setShouldAntialias(bool b)
238 m_state.shouldAntialias = b;
239 setPlatformShouldAntialias(b);
242 bool GraphicsContext::shouldAntialias() const
244 return m_state.shouldAntialias;
247 void GraphicsContext::setShouldSmoothFonts(bool b)
249 m_state.shouldSmoothFonts = b;
250 setPlatformShouldSmoothFonts(b);
253 bool GraphicsContext::shouldSmoothFonts() const
255 return m_state.shouldSmoothFonts;
258 const GraphicsContextState& GraphicsContext::state() const
263 void GraphicsContext::setStrokePattern(PassRefPtr<Pattern> pattern)
267 setStrokeColor(Color::black, ColorSpaceDeviceRGB);
270 m_state.strokeGradient.clear();
271 m_state.strokePattern = pattern;
274 void GraphicsContext::setFillPattern(PassRefPtr<Pattern> pattern)
278 setFillColor(Color::black, ColorSpaceDeviceRGB);
281 m_state.fillGradient.clear();
282 m_state.fillPattern = pattern;
285 void GraphicsContext::setStrokeGradient(PassRefPtr<Gradient> gradient)
289 setStrokeColor(Color::black, ColorSpaceDeviceRGB);
292 m_state.strokeGradient = gradient;
293 m_state.strokePattern.clear();
296 void GraphicsContext::setFillGradient(PassRefPtr<Gradient> gradient)
300 setFillColor(Color::black, ColorSpaceDeviceRGB);
303 m_state.fillGradient = gradient;
304 m_state.fillPattern.clear();
307 Gradient* GraphicsContext::fillGradient() const
309 return m_state.fillGradient.get();
312 Gradient* GraphicsContext::strokeGradient() const
314 return m_state.strokeGradient.get();
317 Pattern* GraphicsContext::fillPattern() const
319 return m_state.fillPattern.get();
322 Pattern* GraphicsContext::strokePattern() const
324 return m_state.strokePattern.get();
327 void GraphicsContext::setShadowsIgnoreTransforms(bool ignoreTransforms)
329 m_state.shadowsIgnoreTransforms = ignoreTransforms;
332 bool GraphicsContext::shadowsIgnoreTransforms() const
334 return m_state.shadowsIgnoreTransforms;
337 void GraphicsContext::beginTransparencyLayer(float opacity)
339 beginPlatformTransparencyLayer(opacity);
340 ++m_transparencyCount;
343 void GraphicsContext::endTransparencyLayer()
345 endPlatformTransparencyLayer();
346 ASSERT(m_transparencyCount > 0);
347 --m_transparencyCount;
351 bool GraphicsContext::isInTransparencyLayer() const
353 return (m_transparencyCount > 0) && supportsTransparencyLayers();
357 bool GraphicsContext::updatingControlTints() const
359 return m_updatingControlTints;
362 void GraphicsContext::setUpdatingControlTints(bool b)
364 setPaintingDisabled(b);
365 m_updatingControlTints = b;
368 void GraphicsContext::setPaintingDisabled(bool f)
370 m_state.paintingDisabled = f;
373 bool GraphicsContext::paintingDisabled() const
375 return m_state.paintingDisabled;
378 #if !OS(WINCE) || (PLATFORM(QT) && !HAVE(QRAWFONT))
379 void GraphicsContext::drawText(const Font& font, const TextRun& run, const FloatPoint& point, int from, int to)
381 if (paintingDisabled())
384 font.drawText(this, run, point, from, to);
388 void GraphicsContext::drawEmphasisMarks(const Font& font, const TextRun& run, const AtomicString& mark, const FloatPoint& point, int from, int to)
390 if (paintingDisabled())
393 font.drawEmphasisMarks(this, run, mark, point, from, to);
396 void GraphicsContext::drawBidiText(const Font& font, const TextRun& run, const FloatPoint& point, Font::CustomFontNotReadyAction customFontNotReadyAction)
398 if (paintingDisabled())
401 BidiResolver<TextRunIterator, BidiCharacterRun> bidiResolver;
402 bidiResolver.setStatus(BidiStatus(run.direction(), run.directionalOverride()));
403 bidiResolver.setPositionIgnoringNestedIsolates(TextRunIterator(&run, 0));
405 // FIXME: This ownership should be reversed. We should pass BidiRunList
406 // to BidiResolver in createBidiRunsForLine.
407 BidiRunList<BidiCharacterRun>& bidiRuns = bidiResolver.runs();
408 bidiResolver.createBidiRunsForLine(TextRunIterator(&run, run.length()));
409 if (!bidiRuns.runCount())
412 FloatPoint currPoint = point;
413 BidiCharacterRun* bidiRun = bidiRuns.firstRun();
415 TextRun subrun = run;
416 subrun.setText(run.data(bidiRun->start()), bidiRun->stop() - bidiRun->start());
417 bool isRTL = bidiRun->level() % 2;
418 subrun.setDirection(isRTL ? RTL : LTR);
419 subrun.setDirectionalOverride(bidiRun->dirOverride(false));
421 font.drawText(this, subrun, currPoint, 0, -1, customFontNotReadyAction);
423 bidiRun = bidiRun->next();
424 // FIXME: Have Font::drawText return the width of what it drew so that we don't have to re-measure here.
426 currPoint.move(font.width(subrun), 0);
429 bidiRuns.deleteRuns();
432 void GraphicsContext::drawHighlightForText(const Font& font, const TextRun& run, const FloatPoint& point, int h, const Color& backgroundColor, ColorSpace colorSpace, int from, int to)
434 if (paintingDisabled())
437 fillRect(font.selectionRectForText(run, point, h, from, to), backgroundColor, colorSpace);
440 void GraphicsContext::drawImage(Image* image, ColorSpace styleColorSpace, const IntPoint& p, CompositeOperator op, RespectImageOrientationEnum shouldRespectImageOrientation)
442 drawImage(image, styleColorSpace, p, IntRect(0, 0, -1, -1), op, shouldRespectImageOrientation);
445 void GraphicsContext::drawImage(Image* image, ColorSpace styleColorSpace, const IntRect& r, CompositeOperator op, RespectImageOrientationEnum shouldRespectImageOrientation, bool useLowQualityScale)
447 drawImage(image, styleColorSpace, r, IntRect(0, 0, -1, -1), op, shouldRespectImageOrientation, useLowQualityScale);
450 void GraphicsContext::drawImage(Image* image, ColorSpace styleColorSpace, const IntPoint& dest, const IntRect& srcRect, CompositeOperator op, RespectImageOrientationEnum shouldRespectImageOrientation)
452 drawImage(image, styleColorSpace, IntRect(dest, srcRect.size()), srcRect, op, shouldRespectImageOrientation);
455 void GraphicsContext::drawImage(Image* image, ColorSpace styleColorSpace, const IntRect& dest, const IntRect& srcRect, CompositeOperator op, RespectImageOrientationEnum shouldRespectImageOrientation, bool useLowQualityScale)
457 drawImage(image, styleColorSpace, FloatRect(dest), srcRect, op, shouldRespectImageOrientation, useLowQualityScale);
460 void GraphicsContext::drawImage(Image* image, ColorSpace styleColorSpace, const FloatRect& dest, const FloatRect& src, CompositeOperator op, RespectImageOrientationEnum shouldRespectImageOrientation, bool useLowQualityScale)
462 if (paintingDisabled() || !image)
465 float tsw = src.width();
466 float tsh = src.height();
467 float tw = dest.width();
468 float th = dest.height();
471 tsw = image->width();
473 tsh = image->height();
478 th = image->height();
480 InterpolationQuality previousInterpolationQuality = InterpolationDefault;
482 if (useLowQualityScale) {
483 previousInterpolationQuality = imageInterpolationQuality();
484 #if PLATFORM(CHROMIUM)
485 setImageInterpolationQuality(InterpolationLow);
487 // FIXME (49002): Should be InterpolationLow
488 setImageInterpolationQuality(InterpolationNone);
492 image->draw(this, FloatRect(dest.location(), FloatSize(tw, th)), FloatRect(src.location(), FloatSize(tsw, tsh)), styleColorSpace, op, shouldRespectImageOrientation);
494 if (useLowQualityScale)
495 setImageInterpolationQuality(previousInterpolationQuality);
498 void GraphicsContext::drawTiledImage(Image* image, ColorSpace styleColorSpace, const IntRect& destRect, const IntPoint& srcPoint, const IntSize& tileSize, CompositeOperator op, bool useLowQualityScale)
500 if (paintingDisabled() || !image)
503 if (useLowQualityScale) {
504 InterpolationQuality previousInterpolationQuality = imageInterpolationQuality();
505 setImageInterpolationQuality(InterpolationLow);
506 image->drawTiled(this, destRect, srcPoint, tileSize, styleColorSpace, op);
507 setImageInterpolationQuality(previousInterpolationQuality);
509 image->drawTiled(this, destRect, srcPoint, tileSize, styleColorSpace, op);
512 void GraphicsContext::drawTiledImage(Image* image, ColorSpace styleColorSpace, const IntRect& dest, const IntRect& srcRect,
513 const FloatSize& tileScaleFactor, Image::TileRule hRule, Image::TileRule vRule, CompositeOperator op, bool useLowQualityScale)
515 if (paintingDisabled() || !image)
518 if (hRule == Image::StretchTile && vRule == Image::StretchTile) {
520 drawImage(image, styleColorSpace, dest, srcRect, op);
524 if (useLowQualityScale) {
525 InterpolationQuality previousInterpolationQuality = imageInterpolationQuality();
526 setImageInterpolationQuality(InterpolationLow);
527 image->drawTiled(this, dest, srcRect, tileScaleFactor, hRule, vRule, styleColorSpace, op);
528 setImageInterpolationQuality(previousInterpolationQuality);
530 image->drawTiled(this, dest, srcRect, tileScaleFactor, hRule, vRule, styleColorSpace, op);
533 void GraphicsContext::drawImageBuffer(ImageBuffer* image, ColorSpace styleColorSpace, const IntPoint& p, CompositeOperator op)
535 drawImageBuffer(image, styleColorSpace, p, IntRect(0, 0, -1, -1), op);
538 void GraphicsContext::drawImageBuffer(ImageBuffer* image, ColorSpace styleColorSpace, const IntRect& r, CompositeOperator op, bool useLowQualityScale)
540 drawImageBuffer(image, styleColorSpace, r, IntRect(0, 0, -1, -1), op, useLowQualityScale);
543 void GraphicsContext::drawImageBuffer(ImageBuffer* image, ColorSpace styleColorSpace, const IntPoint& dest, const IntRect& srcRect, CompositeOperator op)
545 drawImageBuffer(image, styleColorSpace, IntRect(dest, srcRect.size()), srcRect, op);
548 void GraphicsContext::drawImageBuffer(ImageBuffer* image, ColorSpace styleColorSpace, const IntRect& dest, const IntRect& srcRect, CompositeOperator op, bool useLowQualityScale)
550 drawImageBuffer(image, styleColorSpace, FloatRect(dest), srcRect, op, useLowQualityScale);
553 void GraphicsContext::drawImageBuffer(ImageBuffer* image, ColorSpace styleColorSpace, const FloatRect& dest, const FloatRect& src, CompositeOperator op, bool useLowQualityScale)
555 if (paintingDisabled() || !image)
558 float tsw = src.width();
559 float tsh = src.height();
560 float tw = dest.width();
561 float th = dest.height();
564 tsw = image->logicalSize().width();
566 tsh = image->logicalSize().height();
569 tw = image->logicalSize().width();
571 th = image->logicalSize().height();
573 if (useLowQualityScale) {
574 InterpolationQuality previousInterpolationQuality = imageInterpolationQuality();
575 #if PLATFORM(CHROMIUM)
576 setImageInterpolationQuality(InterpolationLow);
578 // FIXME (49002): Should be InterpolationLow
579 setImageInterpolationQuality(InterpolationNone);
581 image->draw(this, styleColorSpace, FloatRect(dest.location(), FloatSize(tw, th)), FloatRect(src.location(), FloatSize(tsw, tsh)), op, useLowQualityScale);
582 setImageInterpolationQuality(previousInterpolationQuality);
584 image->draw(this, styleColorSpace, FloatRect(dest.location(), FloatSize(tw, th)), FloatRect(src.location(), FloatSize(tsw, tsh)), op, useLowQualityScale);
588 void GraphicsContext::clip(const IntRect& rect)
590 clip(FloatRect(rect));
594 void GraphicsContext::addRoundedRectClip(const RoundedRect& rect)
596 if (paintingDisabled())
600 path.addRoundedRect(rect);
604 void GraphicsContext::clipOutRoundedRect(const RoundedRect& rect)
606 if (paintingDisabled())
610 path.addRoundedRect(rect);
614 void GraphicsContext::clipToImageBuffer(ImageBuffer* buffer, const FloatRect& rect)
616 if (paintingDisabled())
618 buffer->clip(this, rect);
621 #if !USE(CG) && !PLATFORM(QT) && !USE(CAIRO)
622 IntRect GraphicsContext::clipBounds() const
624 ASSERT_NOT_REACHED();
629 TextDrawingModeFlags GraphicsContext::textDrawingMode() const
631 return m_state.textDrawingMode;
634 void GraphicsContext::setTextDrawingMode(TextDrawingModeFlags mode)
636 m_state.textDrawingMode = mode;
637 if (paintingDisabled())
639 setPlatformTextDrawingMode(mode);
642 void GraphicsContext::fillRect(const FloatRect& rect, Generator& generator)
644 if (paintingDisabled())
646 generator.fill(this, rect);
649 void GraphicsContext::fillRect(const FloatRect& rect, const Color& color, ColorSpace styleColorSpace, CompositeOperator op)
651 if (paintingDisabled())
654 CompositeOperator previousOperator = compositeOperation();
655 setCompositeOperation(op);
656 fillRect(rect, color, styleColorSpace);
657 setCompositeOperation(previousOperator);
660 void GraphicsContext::fillRoundedRect(const RoundedRect& rect, const Color& color, ColorSpace colorSpace)
662 fillRoundedRect(rect.rect(), rect.radii().topLeft(), rect.radii().topRight(), rect.radii().bottomLeft(), rect.radii().bottomRight(), color, colorSpace);
666 void GraphicsContext::fillRectWithRoundedHole(const IntRect& rect, const RoundedRect& roundedHoleRect, const Color& color, ColorSpace colorSpace)
668 if (paintingDisabled())
674 if (!roundedHoleRect.radii().isZero())
675 path.addRoundedRect(roundedHoleRect);
677 path.addRect(roundedHoleRect.rect());
679 WindRule oldFillRule = fillRule();
680 Color oldFillColor = fillColor();
681 ColorSpace oldFillColorSpace = fillColorSpace();
683 setFillRule(RULE_EVENODD);
684 setFillColor(color, colorSpace);
688 setFillRule(oldFillRule);
689 setFillColor(oldFillColor, oldFillColorSpace);
693 void GraphicsContext::setCompositeOperation(CompositeOperator compositeOperation)
695 m_state.compositeOperator = compositeOperation;
696 setPlatformCompositeOperation(compositeOperation);
699 CompositeOperator GraphicsContext::compositeOperation() const
701 return m_state.compositeOperator;
704 #if !USE(CG) && !USE(SKIA)
705 // Implement this if you want to go ahead and push the drawing mode into your native context
707 void GraphicsContext::setPlatformTextDrawingMode(TextDrawingModeFlags mode)
712 #if !PLATFORM(QT) && !USE(CAIRO) && !USE(SKIA) && !PLATFORM(OPENVG)
713 void GraphicsContext::setPlatformStrokeStyle(StrokeStyle)
719 void GraphicsContext::setPlatformShouldSmoothFonts(bool)
724 #if !USE(SKIA) && !USE(CG)
725 bool GraphicsContext::isAcceleratedContext() const
731 void GraphicsContext::adjustLineToPixelBoundaries(FloatPoint& p1, FloatPoint& p2, float strokeWidth, StrokeStyle penStyle)
733 // For odd widths, we add in 0.5 to the appropriate x/y so that the float arithmetic
734 // works out. For example, with a border width of 3, WebKit will pass us (y1+y2)/2, e.g.,
735 // (50+53)/2 = 103/2 = 51 when we want 51.5. It is always true that an even width gave
736 // us a perfect position, but an odd width gave us a position that is off by exactly 0.5.
737 if (penStyle == DottedStroke || penStyle == DashedStroke) {
738 if (p1.x() == p2.x()) {
739 p1.setY(p1.y() + strokeWidth);
740 p2.setY(p2.y() - strokeWidth);
742 p1.setX(p1.x() + strokeWidth);
743 p2.setX(p2.x() - strokeWidth);
747 if (static_cast<int>(strokeWidth) % 2) { //odd
748 if (p1.x() == p2.x()) {
749 // We're a vertical line. Adjust our x.
750 p1.setX(p1.x() + 0.5f);
751 p2.setX(p2.x() + 0.5f);
753 // We're a horizontal line. Adjust our y.
754 p1.setY(p1.y() + 0.5f);
755 p2.setY(p2.y() + 0.5f);
760 static bool scalesMatch(AffineTransform a, AffineTransform b)
762 return a.xScale() == b.xScale() && a.yScale() == b.yScale();
765 PassOwnPtr<ImageBuffer> GraphicsContext::createCompatibleBuffer(const IntSize& size) const
767 // Make the buffer larger if the context's transform is scaling it so we need a higher
768 // resolution than one pixel per unit. Also set up a corresponding scale factor on the
771 AffineTransform transform = getCTM(DefinitelyIncludeDeviceScale);
772 IntSize scaledSize(static_cast<int>(ceil(size.width() * transform.xScale())), static_cast<int>(ceil(size.height() * transform.yScale())));
774 OwnPtr<ImageBuffer> buffer = ImageBuffer::create(scaledSize, 1, ColorSpaceDeviceRGB, isAcceleratedContext() ? Accelerated : Unaccelerated);
778 buffer->context()->scale(FloatSize(static_cast<float>(scaledSize.width()) / size.width(),
779 static_cast<float>(scaledSize.height()) / size.height()));
781 return buffer.release();
784 bool GraphicsContext::isCompatibleWithBuffer(ImageBuffer* buffer) const
786 GraphicsContext* bufferContext = buffer->context();
788 return scalesMatch(getCTM(), bufferContext->getCTM()) && isAcceleratedContext() == bufferContext->isAcceleratedContext();
792 void GraphicsContext::platformApplyDeviceScaleFactor(float)
797 void GraphicsContext::applyDeviceScaleFactor(float deviceScaleFactor)
799 scale(FloatSize(deviceScaleFactor, deviceScaleFactor));
800 platformApplyDeviceScaleFactor(deviceScaleFactor);
803 void GraphicsContext::fillEllipse(const FloatRect& ellipse)
805 platformFillEllipse(ellipse);
808 void GraphicsContext::strokeEllipse(const FloatRect& ellipse)
810 platformStrokeEllipse(ellipse);
813 void GraphicsContext::fillEllipseAsPath(const FloatRect& ellipse)
816 path.addEllipse(ellipse);
820 void GraphicsContext::strokeEllipseAsPath(const FloatRect& ellipse)
823 path.addEllipse(ellipse);
827 #if !USE(CG) && !USE(SKIA) // append && !USE(MYPLATFORM) here to optimize ellipses on your platform.
828 void GraphicsContext::platformFillEllipse(const FloatRect& ellipse)
830 if (paintingDisabled())
833 fillEllipseAsPath(ellipse);
836 void GraphicsContext::platformStrokeEllipse(const FloatRect& ellipse)
838 if (paintingDisabled())
841 strokeEllipseAsPath(ellipse);