2 * Copyright (C) 2003, 2004, 2005, 2006, 2009, 2013 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 "DisplayListRecorder.h"
32 #include "FloatRoundedRect.h"
34 #include "ImageBuffer.h"
36 #include "RoundedRect.h"
38 #include "TextStream.h"
42 class TextRunIterator {
50 TextRunIterator(const TextRun* textRun, unsigned offset)
56 TextRunIterator(const TextRunIterator& other)
57 : m_textRun(other.m_textRun)
58 , m_offset(other.m_offset)
62 unsigned offset() const { return m_offset; }
63 void increment() { m_offset++; }
64 bool atEnd() const { return !m_textRun || m_offset >= m_textRun->length(); }
65 UChar current() const { return (*m_textRun)[m_offset]; }
66 UCharDirection direction() const { return atEnd() ? U_OTHER_NEUTRAL : u_charDirection(current()); }
68 bool operator==(const TextRunIterator& other)
70 return m_offset == other.m_offset && m_textRun == other.m_textRun;
73 bool operator!=(const TextRunIterator& other) { return !operator==(other); }
76 const TextRun* m_textRun;
80 #define CHECK_FOR_CHANGED_PROPERTY(flag, property) \
81 if ((m_changeFlags & GraphicsContextState::flag) && (m_state.property != state.property)) \
82 changeFlags |= GraphicsContextState::flag;
84 GraphicsContextState::StateChangeFlags GraphicsContextStateChange::changesFromState(const GraphicsContextState& state) const
86 GraphicsContextState::StateChangeFlags changeFlags = GraphicsContextState::NoChange;
88 CHECK_FOR_CHANGED_PROPERTY(StrokeGradientChange, strokeGradient);
89 CHECK_FOR_CHANGED_PROPERTY(StrokePatternChange, strokePattern);
90 CHECK_FOR_CHANGED_PROPERTY(FillGradientChange, fillGradient);
91 CHECK_FOR_CHANGED_PROPERTY(FillPatternChange, fillPattern);
93 if ((m_changeFlags & GraphicsContextState::ShadowChange)
94 && (m_state.shadowOffset != state.shadowOffset
95 || m_state.shadowBlur != state.shadowBlur
96 || m_state.shadowColor != state.shadowColor))
97 changeFlags |= GraphicsContextState::ShadowChange;
99 CHECK_FOR_CHANGED_PROPERTY(StrokeThicknessChange, strokeThickness);
100 CHECK_FOR_CHANGED_PROPERTY(TextDrawingModeChange, textDrawingMode);
101 CHECK_FOR_CHANGED_PROPERTY(StrokeColorChange, strokeColor);
102 CHECK_FOR_CHANGED_PROPERTY(FillColorChange, fillColor);
103 CHECK_FOR_CHANGED_PROPERTY(StrokeStyleChange, strokeStyle);
104 CHECK_FOR_CHANGED_PROPERTY(FillRuleChange, fillRule);
105 CHECK_FOR_CHANGED_PROPERTY(AlphaChange, alpha);
107 if ((m_changeFlags & (GraphicsContextState::CompositeOperationChange | GraphicsContextState::BlendModeChange))
108 && (m_state.compositeOperator != state.compositeOperator || m_state.blendMode != state.blendMode))
109 changeFlags |= (GraphicsContextState::CompositeOperationChange | GraphicsContextState::BlendModeChange);
111 CHECK_FOR_CHANGED_PROPERTY(ShouldAntialiasChange, shouldAntialias);
112 CHECK_FOR_CHANGED_PROPERTY(ShouldSmoothFontsChange, shouldSmoothFonts);
113 CHECK_FOR_CHANGED_PROPERTY(ShouldSubpixelQuantizeFontsChange, shouldSubpixelQuantizeFonts);
114 CHECK_FOR_CHANGED_PROPERTY(ShadowsIgnoreTransformsChange, shadowsIgnoreTransforms);
115 CHECK_FOR_CHANGED_PROPERTY(DrawLuminanceMaskChange, drawLuminanceMask);
116 CHECK_FOR_CHANGED_PROPERTY(ImageInterpolationQualityChange, imageInterpolationQuality);
121 void GraphicsContextStateChange::accumulate(const GraphicsContextState& state, GraphicsContextState::StateChangeFlags flags)
123 // FIXME: This code should move to GraphicsContextState.
124 if (flags & GraphicsContextState::StrokeGradientChange)
125 m_state.strokeGradient = state.strokeGradient;
127 if (flags & GraphicsContextState::StrokePatternChange)
128 m_state.strokePattern = state.strokePattern;
130 if (flags & GraphicsContextState::FillGradientChange)
131 m_state.fillGradient = state.fillGradient;
133 if (flags & GraphicsContextState::FillPatternChange)
134 m_state.fillPattern = state.fillPattern;
136 if (flags & GraphicsContextState::ShadowChange) {
137 // FIXME: Deal with state.shadowsUseLegacyRadius.
138 m_state.shadowOffset = state.shadowOffset;
139 m_state.shadowBlur = state.shadowBlur;
140 m_state.shadowColor = state.shadowColor;
143 if (flags & GraphicsContextState::StrokeThicknessChange)
144 m_state.strokeThickness = state.strokeThickness;
146 if (flags & GraphicsContextState::TextDrawingModeChange)
147 m_state.textDrawingMode = state.textDrawingMode;
149 if (flags & GraphicsContextState::StrokeColorChange)
150 m_state.strokeColor = state.strokeColor;
152 if (flags & GraphicsContextState::FillColorChange)
153 m_state.fillColor = state.fillColor;
155 if (flags & GraphicsContextState::StrokeStyleChange)
156 m_state.strokeStyle = state.strokeStyle;
158 if (flags & GraphicsContextState::FillRuleChange)
159 m_state.fillRule = state.fillRule;
161 if (flags & GraphicsContextState::AlphaChange)
162 m_state.alpha = state.alpha;
164 if (flags & (GraphicsContextState::CompositeOperationChange | GraphicsContextState::BlendModeChange)) {
165 m_state.compositeOperator = state.compositeOperator;
166 m_state.blendMode = state.blendMode;
169 if (flags & GraphicsContextState::ShouldAntialiasChange)
170 m_state.shouldAntialias = state.shouldAntialias;
172 if (flags & GraphicsContextState::ShouldSmoothFontsChange)
173 m_state.shouldSmoothFonts = state.shouldSmoothFonts;
175 if (flags & GraphicsContextState::ShouldSubpixelQuantizeFontsChange)
176 m_state.shouldSubpixelQuantizeFonts = state.shouldSubpixelQuantizeFonts;
178 if (flags & GraphicsContextState::ShadowsIgnoreTransformsChange)
179 m_state.shadowsIgnoreTransforms = state.shadowsIgnoreTransforms;
181 if (flags & GraphicsContextState::DrawLuminanceMaskChange)
182 m_state.drawLuminanceMask = state.drawLuminanceMask;
184 if (flags & GraphicsContextState::ImageInterpolationQualityChange)
185 m_state.imageInterpolationQuality = state.imageInterpolationQuality;
187 m_changeFlags |= flags;
190 void GraphicsContextStateChange::apply(GraphicsContext& context) const
192 if (m_changeFlags & GraphicsContextState::StrokeGradientChange)
193 context.setStrokeGradient(*m_state.strokeGradient);
195 if (m_changeFlags & GraphicsContextState::StrokePatternChange)
196 context.setStrokePattern(*m_state.strokePattern);
198 if (m_changeFlags & GraphicsContextState::FillGradientChange)
199 context.setFillGradient(*m_state.fillGradient);
201 if (m_changeFlags & GraphicsContextState::FillPatternChange)
202 context.setFillPattern(*m_state.fillPattern);
204 if (m_changeFlags & GraphicsContextState::ShadowChange) {
206 if (m_state.shadowsUseLegacyRadius)
207 context.setLegacyShadow(m_state.shadowOffset, m_state.shadowBlur, m_state.shadowColor);
210 context.setShadow(m_state.shadowOffset, m_state.shadowBlur, m_state.shadowColor);
213 if (m_changeFlags & GraphicsContextState::StrokeThicknessChange)
214 context.setStrokeThickness(m_state.strokeThickness);
216 if (m_changeFlags & GraphicsContextState::TextDrawingModeChange)
217 context.setTextDrawingMode(m_state.textDrawingMode);
219 if (m_changeFlags & GraphicsContextState::StrokeColorChange)
220 context.setStrokeColor(m_state.strokeColor);
222 if (m_changeFlags & GraphicsContextState::FillColorChange)
223 context.setFillColor(m_state.fillColor);
225 if (m_changeFlags & GraphicsContextState::StrokeStyleChange)
226 context.setStrokeStyle(m_state.strokeStyle);
228 if (m_changeFlags & GraphicsContextState::FillRuleChange)
229 context.setFillRule(m_state.fillRule);
231 if (m_changeFlags & GraphicsContextState::AlphaChange)
232 context.setAlpha(m_state.alpha);
234 if (m_changeFlags & (GraphicsContextState::CompositeOperationChange | GraphicsContextState::BlendModeChange))
235 context.setCompositeOperation(m_state.compositeOperator, m_state.blendMode);
237 if (m_changeFlags & GraphicsContextState::ShouldAntialiasChange)
238 context.setShouldAntialias(m_state.shouldAntialias);
240 if (m_changeFlags & GraphicsContextState::ShouldSmoothFontsChange)
241 context.setShouldSmoothFonts(m_state.shouldSmoothFonts);
243 if (m_changeFlags & GraphicsContextState::ShouldSubpixelQuantizeFontsChange)
244 context.setShouldSubpixelQuantizeFonts(m_state.shouldSubpixelQuantizeFonts);
246 if (m_changeFlags & GraphicsContextState::ShadowsIgnoreTransformsChange)
247 context.setShadowsIgnoreTransforms(m_state.shadowsIgnoreTransforms);
249 if (m_changeFlags & GraphicsContextState::DrawLuminanceMaskChange)
250 context.setDrawLuminanceMask(m_state.drawLuminanceMask);
252 if (m_changeFlags & GraphicsContextState::ImageInterpolationQualityChange)
253 context.setImageInterpolationQuality(m_state.imageInterpolationQuality);
256 void GraphicsContextStateChange::dump(TextStream& ts) const
258 ts.dumpProperty("change-flags", m_changeFlags);
260 if (m_changeFlags & GraphicsContextState::StrokeGradientChange)
261 ts.dumpProperty("stroke-gradient", m_state.strokeGradient.get());
263 if (m_changeFlags & GraphicsContextState::StrokePatternChange)
264 ts.dumpProperty("stroke-pattern", m_state.strokePattern.get());
266 if (m_changeFlags & GraphicsContextState::FillGradientChange)
267 ts.dumpProperty("fill-gradient", m_state.fillGradient.get());
269 if (m_changeFlags & GraphicsContextState::FillPatternChange)
270 ts.dumpProperty("fill-pattern", m_state.fillPattern.get());
272 if (m_changeFlags & GraphicsContextState::ShadowChange) {
273 ts.dumpProperty("shadow-blur", m_state.shadowBlur);
274 ts.dumpProperty("shadow-offset", m_state.shadowOffset);
276 ts.dumpProperty("shadows-use-legacy-radius", m_state.shadowsUseLegacyRadius);
280 if (m_changeFlags & GraphicsContextState::StrokeThicknessChange)
281 ts.dumpProperty("stroke-thickness", m_state.strokeThickness);
283 if (m_changeFlags & GraphicsContextState::TextDrawingModeChange)
284 ts.dumpProperty("text-drawing-mode", m_state.textDrawingMode);
286 if (m_changeFlags & GraphicsContextState::StrokeColorChange)
287 ts.dumpProperty("stroke-color", m_state.strokeColor);
289 if (m_changeFlags & GraphicsContextState::FillColorChange)
290 ts.dumpProperty("fill-color", m_state.fillColor);
292 if (m_changeFlags & GraphicsContextState::StrokeStyleChange)
293 ts.dumpProperty("stroke-style", m_state.strokeStyle);
295 if (m_changeFlags & GraphicsContextState::FillRuleChange)
296 ts.dumpProperty("fill-rule", m_state.fillRule);
298 if (m_changeFlags & GraphicsContextState::AlphaChange)
299 ts.dumpProperty("alpha", m_state.alpha);
301 if (m_changeFlags & GraphicsContextState::CompositeOperationChange)
302 ts.dumpProperty("composite-operator", m_state.compositeOperator);
304 if (m_changeFlags & GraphicsContextState::BlendModeChange)
305 ts.dumpProperty("blend-mode", m_state.blendMode);
307 if (m_changeFlags & GraphicsContextState::ShouldAntialiasChange)
308 ts.dumpProperty("should-antialias", m_state.shouldAntialias);
310 if (m_changeFlags & GraphicsContextState::ShouldSmoothFontsChange)
311 ts.dumpProperty("should-smooth-fonts", m_state.shouldSmoothFonts);
313 if (m_changeFlags & GraphicsContextState::ShouldSubpixelQuantizeFontsChange)
314 ts.dumpProperty("should-subpixel-quantize-fonts", m_state.shouldSubpixelQuantizeFonts);
316 if (m_changeFlags & GraphicsContextState::ShadowsIgnoreTransformsChange)
317 ts.dumpProperty("shadows-ignore-transforms", m_state.shadowsIgnoreTransforms);
319 if (m_changeFlags & GraphicsContextState::DrawLuminanceMaskChange)
320 ts.dumpProperty("draw-luminance-mask", m_state.drawLuminanceMask);
323 TextStream& operator<<(TextStream& ts, const GraphicsContextStateChange& stateChange)
325 stateChange.dump(ts);
329 GraphicsContext::GraphicsContext(NonPaintingReasons nonPaintingReasons)
330 : m_nonPaintingReasons(nonPaintingReasons)
334 GraphicsContext::GraphicsContext(PlatformGraphicsContext* platformGraphicsContext)
336 platformInit(platformGraphicsContext);
339 GraphicsContext::~GraphicsContext()
341 ASSERT(m_stack.isEmpty());
342 ASSERT(!m_transparencyCount);
346 void GraphicsContext::save()
348 if (paintingDisabled())
351 m_stack.append(m_state);
354 m_displayListRecorder->save();
361 void GraphicsContext::restore()
363 if (paintingDisabled())
366 if (m_stack.isEmpty()) {
367 LOG_ERROR("ERROR void GraphicsContext::restore() stack is empty");
370 m_state = m_stack.last();
371 m_stack.removeLast();
373 // Make sure we deallocate the state stack buffer when it goes empty.
374 // Canvas elements will immediately save() again, but that goes into inline capacity.
375 if (m_stack.isEmpty())
379 m_displayListRecorder->restore();
383 restorePlatformState();
386 void GraphicsContext::drawRaisedEllipse(const FloatRect& rect, const Color& ellipseColor, const Color& shadowColor)
388 if (paintingDisabled())
393 setStrokeColor(shadowColor);
394 setFillColor(shadowColor);
396 drawEllipse(FloatRect(rect.x(), rect.y() + 1, rect.width(), rect.height()));
398 setStrokeColor(ellipseColor);
399 setFillColor(ellipseColor);
406 void GraphicsContext::setStrokeThickness(float thickness)
408 m_state.strokeThickness = thickness;
410 m_displayListRecorder->updateState(m_state, GraphicsContextState::StrokeThicknessChange);
414 setPlatformStrokeThickness(thickness);
417 void GraphicsContext::setStrokeStyle(StrokeStyle style)
419 m_state.strokeStyle = style;
421 m_displayListRecorder->updateState(m_state, GraphicsContextState::StrokeStyleChange);
424 setPlatformStrokeStyle(style);
427 void GraphicsContext::setStrokeColor(const Color& color)
429 m_state.strokeColor = color;
430 m_state.strokeGradient = nullptr;
431 m_state.strokePattern = nullptr;
433 m_displayListRecorder->updateState(m_state, GraphicsContextState::StrokeColorChange);
436 setPlatformStrokeColor(color);
439 void GraphicsContext::setShadow(const FloatSize& offset, float blur, const Color& color)
441 m_state.shadowOffset = offset;
442 m_state.shadowBlur = blur;
443 m_state.shadowColor = color;
445 m_state.shadowsUseLegacyRadius = false;
448 m_displayListRecorder->updateState(m_state, GraphicsContextState::ShadowChange);
451 setPlatformShadow(offset, blur, color);
454 void GraphicsContext::setLegacyShadow(const FloatSize& offset, float blur, const Color& color)
456 m_state.shadowOffset = offset;
457 m_state.shadowBlur = blur;
458 m_state.shadowColor = color;
460 m_state.shadowsUseLegacyRadius = true;
463 m_displayListRecorder->updateState(m_state, GraphicsContextState::ShadowChange);
466 setPlatformShadow(offset, blur, color);
469 void GraphicsContext::clearShadow()
471 m_state.shadowOffset = FloatSize();
472 m_state.shadowBlur = 0;
473 m_state.shadowColor = Color();
475 m_state.shadowsUseLegacyRadius = false;
479 m_displayListRecorder->clearShadow();
482 clearPlatformShadow();
485 bool GraphicsContext::getShadow(FloatSize& offset, float& blur, Color& color) const
487 offset = m_state.shadowOffset;
488 blur = m_state.shadowBlur;
489 color = m_state.shadowColor;
495 bool GraphicsContext::mustUseShadowBlur() const
497 // We can't avoid ShadowBlur if the shadow has blur.
498 if (hasBlurredShadow())
500 // We can avoid ShadowBlur and optimize, since we're not drawing on a
501 // canvas and box shadows are affected by the transformation matrix.
502 if (!m_state.shadowsIgnoreTransforms)
504 // We can avoid ShadowBlur, since there are no transformations to apply to the canvas.
505 if (getCTM().isIdentity())
507 // Otherwise, no chance avoiding ShadowBlur.
512 void GraphicsContext::setFillColor(const Color& color)
514 m_state.fillColor = color;
515 m_state.fillGradient = nullptr;
516 m_state.fillPattern = nullptr;
519 m_displayListRecorder->updateState(m_state, GraphicsContextState::FillColorChange);
523 setPlatformFillColor(color);
526 void GraphicsContext::setShadowsIgnoreTransforms(bool shadowsIgnoreTransforms)
528 m_state.shadowsIgnoreTransforms = shadowsIgnoreTransforms;
530 m_displayListRecorder->updateState(m_state, GraphicsContextState::ShadowsIgnoreTransformsChange);
533 void GraphicsContext::setShouldAntialias(bool shouldAntialias)
535 m_state.shouldAntialias = shouldAntialias;
538 m_displayListRecorder->updateState(m_state, GraphicsContextState::ShouldAntialiasChange);
542 setPlatformShouldAntialias(shouldAntialias);
545 void GraphicsContext::setShouldSmoothFonts(bool shouldSmoothFonts)
547 m_state.shouldSmoothFonts = shouldSmoothFonts;
550 m_displayListRecorder->updateState(m_state, GraphicsContextState::ShouldSmoothFontsChange);
554 setPlatformShouldSmoothFonts(shouldSmoothFonts);
557 void GraphicsContext::setShouldSubpixelQuantizeFonts(bool shouldSubpixelQuantizeFonts)
559 m_state.shouldSubpixelQuantizeFonts = shouldSubpixelQuantizeFonts;
561 m_displayListRecorder->updateState(m_state, GraphicsContextState::ShouldSubpixelQuantizeFontsChange);
564 void GraphicsContext::setImageInterpolationQuality(InterpolationQuality imageInterpolationQuality)
566 m_state.imageInterpolationQuality = imageInterpolationQuality;
568 if (paintingDisabled())
572 m_displayListRecorder->updateState(m_state, GraphicsContextState::ImageInterpolationQualityChange);
576 setPlatformImageInterpolationQuality(imageInterpolationQuality);
579 void GraphicsContext::setStrokePattern(Ref<Pattern>&& pattern)
581 m_state.strokeGradient = nullptr;
582 m_state.strokePattern = WTFMove(pattern);
584 m_displayListRecorder->updateState(m_state, GraphicsContextState::StrokePatternChange);
587 void GraphicsContext::setFillPattern(Ref<Pattern>&& pattern)
589 m_state.fillGradient = nullptr;
590 m_state.fillPattern = WTFMove(pattern);
592 m_displayListRecorder->updateState(m_state, GraphicsContextState::FillPatternChange);
595 void GraphicsContext::setStrokeGradient(Ref<Gradient>&& gradient)
597 m_state.strokeGradient = WTFMove(gradient);
598 m_state.strokePattern = nullptr;
600 m_displayListRecorder->updateState(m_state, GraphicsContextState::StrokeGradientChange);
603 void GraphicsContext::setFillRule(WindRule fillRule)
605 m_state.fillRule = fillRule;
607 m_displayListRecorder->updateState(m_state, GraphicsContextState::FillRuleChange);
610 void GraphicsContext::setFillGradient(Ref<Gradient>&& gradient)
612 m_state.fillGradient = WTFMove(gradient);
613 m_state.fillPattern = nullptr;
615 m_displayListRecorder->updateState(m_state, GraphicsContextState::FillGradientChange); // FIXME: also fill pattern?
618 void GraphicsContext::beginTransparencyLayer(float opacity)
621 m_displayListRecorder->beginTransparencyLayer(opacity);
624 beginPlatformTransparencyLayer(opacity);
625 ++m_transparencyCount;
628 void GraphicsContext::endTransparencyLayer()
631 m_displayListRecorder->endTransparencyLayer();
634 endPlatformTransparencyLayer();
635 ASSERT(m_transparencyCount > 0);
636 --m_transparencyCount;
639 float GraphicsContext::drawText(const FontCascade& font, const TextRun& run, const FloatPoint& point, int from, int to)
641 if (paintingDisabled())
644 // Display list recording for text content is done at glyphs level. See GraphicsContext::drawGlyphs.
645 return font.drawText(*this, run, point, from, to);
648 void GraphicsContext::drawGlyphs(const FontCascade& fontCascade, const Font& font, const GlyphBuffer& buffer, int from, int numGlyphs, const FloatPoint& point)
650 if (paintingDisabled())
654 m_displayListRecorder->drawGlyphs(font, buffer, from, numGlyphs, point, fontCascade.fontDescription().fontSmoothing());
658 fontCascade.drawGlyphs(*this, font, buffer, from, numGlyphs, point, fontCascade.fontDescription().fontSmoothing());
661 void GraphicsContext::drawEmphasisMarks(const FontCascade& font, const TextRun& run, const AtomicString& mark, const FloatPoint& point, int from, int to)
663 if (paintingDisabled())
666 font.drawEmphasisMarks(*this, run, mark, point, from, to);
669 void GraphicsContext::drawBidiText(const FontCascade& font, const TextRun& run, const FloatPoint& point, FontCascade::CustomFontNotReadyAction customFontNotReadyAction)
671 if (paintingDisabled())
674 BidiResolver<TextRunIterator, BidiCharacterRun> bidiResolver;
675 bidiResolver.setStatus(BidiStatus(run.direction(), run.directionalOverride()));
676 bidiResolver.setPositionIgnoringNestedIsolates(TextRunIterator(&run, 0));
678 // FIXME: This ownership should be reversed. We should pass BidiRunList
679 // to BidiResolver in createBidiRunsForLine.
680 BidiRunList<BidiCharacterRun>& bidiRuns = bidiResolver.runs();
681 bidiResolver.createBidiRunsForLine(TextRunIterator(&run, run.length()));
683 if (!bidiRuns.runCount())
686 FloatPoint currPoint = point;
687 BidiCharacterRun* bidiRun = bidiRuns.firstRun();
689 TextRun subrun = run.subRun(bidiRun->start(), bidiRun->stop() - bidiRun->start());
690 bool isRTL = bidiRun->level() % 2;
691 subrun.setDirection(isRTL ? RTL : LTR);
692 subrun.setDirectionalOverride(bidiRun->dirOverride(false));
694 float width = font.drawText(*this, subrun, currPoint, 0, -1, customFontNotReadyAction);
695 currPoint.move(width, 0);
697 bidiRun = bidiRun->next();
703 void GraphicsContext::drawImage(Image& image, const FloatPoint& destination, const ImagePaintingOptions& imagePaintingOptions)
705 drawImage(image, FloatRect(destination, image.size()), FloatRect(FloatPoint(), image.size()), imagePaintingOptions);
708 void GraphicsContext::drawImage(Image& image, const FloatRect& destination, const ImagePaintingOptions& imagePaintingOptions)
711 FloatRect srcRect(FloatPoint(), image.originalSize());
713 FloatRect srcRect(FloatPoint(), image.size());
716 drawImage(image, destination, srcRect, imagePaintingOptions);
719 void GraphicsContext::drawImage(Image& image, const FloatRect& destination, const FloatRect& source, const ImagePaintingOptions& imagePaintingOptions)
721 if (paintingDisabled())
725 m_displayListRecorder->drawImage(image, destination, source, imagePaintingOptions);
729 InterpolationQualityMaintainer interpolationQualityForThisScope(*this, imagePaintingOptions.m_interpolationQuality);
730 image.draw(*this, destination, source, imagePaintingOptions.m_compositeOperator, imagePaintingOptions.m_blendMode, imagePaintingOptions.m_orientationDescription);
733 void GraphicsContext::drawTiledImage(Image& image, const FloatRect& destination, const FloatPoint& source, const FloatSize& tileSize, const FloatSize& spacing, const ImagePaintingOptions& imagePaintingOptions)
735 if (paintingDisabled())
739 m_displayListRecorder->drawTiledImage(image, destination, source, tileSize, spacing, imagePaintingOptions);
743 InterpolationQualityMaintainer interpolationQualityForThisScope(*this, imagePaintingOptions.m_interpolationQuality);
744 image.drawTiled(*this, destination, source, tileSize, spacing, imagePaintingOptions.m_compositeOperator, imagePaintingOptions.m_blendMode);
747 void GraphicsContext::drawTiledImage(Image& image, const FloatRect& destination, const FloatRect& source, const FloatSize& tileScaleFactor,
748 Image::TileRule hRule, Image::TileRule vRule, const ImagePaintingOptions& imagePaintingOptions)
750 if (paintingDisabled())
754 m_displayListRecorder->drawTiledImage(image, destination, source, tileScaleFactor, hRule, vRule, imagePaintingOptions);
758 if (hRule == Image::StretchTile && vRule == Image::StretchTile) {
760 drawImage(image, destination, source, imagePaintingOptions);
764 InterpolationQualityMaintainer interpolationQualityForThisScope(*this, imagePaintingOptions.m_interpolationQuality);
765 image.drawTiled(*this, destination, source, tileScaleFactor, hRule, vRule, imagePaintingOptions.m_compositeOperator);
768 void GraphicsContext::drawImageBuffer(ImageBuffer& image, const FloatPoint& destination, const ImagePaintingOptions& imagePaintingOptions)
770 drawImageBuffer(image, FloatRect(destination, image.logicalSize()), FloatRect(FloatPoint(), image.logicalSize()), imagePaintingOptions);
773 void GraphicsContext::drawImageBuffer(ImageBuffer& image, const FloatRect& destination, const ImagePaintingOptions& imagePaintingOptions)
775 drawImageBuffer(image, destination, FloatRect(FloatPoint(), FloatSize(image.logicalSize())), imagePaintingOptions);
778 void GraphicsContext::drawImageBuffer(ImageBuffer& image, const FloatRect& destination, const FloatRect& source, const ImagePaintingOptions& imagePaintingOptions)
780 if (paintingDisabled())
783 InterpolationQualityMaintainer interpolationQualityForThisScope(*this, imagePaintingOptions.m_interpolationQuality);
784 image.draw(*this, destination, source, imagePaintingOptions.m_compositeOperator, imagePaintingOptions.m_blendMode);
787 void GraphicsContext::drawConsumingImageBuffer(std::unique_ptr<ImageBuffer> image, const FloatPoint& destination, const ImagePaintingOptions& imagePaintingOptions)
791 IntSize imageLogicalSize = image->logicalSize();
792 drawConsumingImageBuffer(WTFMove(image), FloatRect(destination, imageLogicalSize), FloatRect(FloatPoint(), imageLogicalSize), imagePaintingOptions);
795 void GraphicsContext::drawConsumingImageBuffer(std::unique_ptr<ImageBuffer> image, const FloatRect& destination, const ImagePaintingOptions& imagePaintingOptions)
799 IntSize imageLogicalSize = image->logicalSize();
800 drawConsumingImageBuffer(WTFMove(image), destination, FloatRect(FloatPoint(), FloatSize(imageLogicalSize)), imagePaintingOptions);
803 void GraphicsContext::drawConsumingImageBuffer(std::unique_ptr<ImageBuffer> image, const FloatRect& destination, const FloatRect& source, const ImagePaintingOptions& imagePaintingOptions)
805 if (paintingDisabled() || !image)
808 InterpolationQualityMaintainer interpolationQualityForThisScope(*this, imagePaintingOptions.m_interpolationQuality);
809 ImageBuffer::drawConsuming(WTFMove(image), *this, destination, source, imagePaintingOptions.m_compositeOperator, imagePaintingOptions.m_blendMode);
812 void GraphicsContext::clipRoundedRect(const FloatRoundedRect& rect)
814 if (paintingDisabled())
818 path.addRoundedRect(rect);
822 void GraphicsContext::clipOutRoundedRect(const FloatRoundedRect& rect)
824 if (paintingDisabled())
827 if (!rect.isRounded()) {
828 clipOut(rect.rect());
833 path.addRoundedRect(rect);
837 #if !USE(CG) && !USE(CAIRO)
838 IntRect GraphicsContext::clipBounds() const
840 ASSERT_NOT_REACHED();
845 void GraphicsContext::setTextDrawingMode(TextDrawingModeFlags mode)
847 m_state.textDrawingMode = mode;
848 if (paintingDisabled())
852 m_displayListRecorder->updateState(m_state, GraphicsContextState::TextDrawingModeChange);
855 setPlatformTextDrawingMode(mode);
858 void GraphicsContext::fillRect(const FloatRect& rect, Gradient& gradient)
860 if (paintingDisabled())
864 m_displayListRecorder->fillRect(rect, gradient);
868 gradient.fill(this, rect);
871 void GraphicsContext::fillRect(const FloatRect& rect, const Color& color, CompositeOperator op, BlendMode blendMode)
873 if (paintingDisabled())
877 m_displayListRecorder->fillRect(rect, color, op, blendMode);
881 CompositeOperator previousOperator = compositeOperation();
882 setCompositeOperation(op, blendMode);
883 fillRect(rect, color);
884 setCompositeOperation(previousOperator);
887 void GraphicsContext::fillRoundedRect(const FloatRoundedRect& rect, const Color& color, BlendMode blendMode)
889 if (paintingDisabled())
893 m_displayListRecorder->fillRoundedRect(rect, color, blendMode);
897 if (rect.isRounded()) {
898 setCompositeOperation(compositeOperation(), blendMode);
899 platformFillRoundedRect(rect, color);
900 setCompositeOperation(compositeOperation());
902 fillRect(rect.rect(), color, compositeOperation(), blendMode);
905 #if !USE(CG) && !USE(CAIRO)
906 void GraphicsContext::fillRectWithRoundedHole(const IntRect& rect, const FloatRoundedRect& roundedHoleRect, const Color& color)
908 if (paintingDisabled())
914 if (!roundedHoleRect.radii().isZero())
915 path.addRoundedRect(roundedHoleRect);
917 path.addRect(roundedHoleRect.rect());
919 WindRule oldFillRule = fillRule();
920 Color oldFillColor = fillColor();
922 setFillRule(RULE_EVENODD);
927 setFillRule(oldFillRule);
928 setFillColor(oldFillColor);
932 void GraphicsContext::setAlpha(float alpha)
934 m_state.alpha = alpha;
936 m_displayListRecorder->updateState(m_state, GraphicsContextState::AlphaChange);
939 setPlatformAlpha(alpha);
942 void GraphicsContext::setCompositeOperation(CompositeOperator compositeOperation, BlendMode blendMode)
944 m_state.compositeOperator = compositeOperation;
945 m_state.blendMode = blendMode;
947 m_displayListRecorder->updateState(m_state, GraphicsContextState::CompositeOperationChange);
950 setPlatformCompositeOperation(compositeOperation, blendMode);
953 void GraphicsContext::setDrawLuminanceMask(bool drawLuminanceMask)
955 m_state.drawLuminanceMask = drawLuminanceMask;
957 m_displayListRecorder->updateState(m_state, GraphicsContextState::DrawLuminanceMaskChange);
961 // Implement this if you want to go push the drawing mode into your native context immediately.
962 void GraphicsContext::setPlatformTextDrawingMode(TextDrawingModeFlags)
968 void GraphicsContext::setPlatformStrokeStyle(StrokeStyle)
974 void GraphicsContext::setPlatformShouldSmoothFonts(bool)
979 #if !USE(CG) && !USE(CAIRO)
980 bool GraphicsContext::isAcceleratedContext() const
986 void GraphicsContext::adjustLineToPixelBoundaries(FloatPoint& p1, FloatPoint& p2, float strokeWidth, StrokeStyle penStyle)
988 // For odd widths, we add in 0.5 to the appropriate x/y so that the float arithmetic
989 // works out. For example, with a border width of 3, WebKit will pass us (y1+y2)/2, e.g.,
990 // (50+53)/2 = 103/2 = 51 when we want 51.5. It is always true that an even width gave
991 // us a perfect position, but an odd width gave us a position that is off by exactly 0.5.
992 if (penStyle == DottedStroke || penStyle == DashedStroke) {
993 if (p1.x() == p2.x()) {
994 p1.setY(p1.y() + strokeWidth);
995 p2.setY(p2.y() - strokeWidth);
997 p1.setX(p1.x() + strokeWidth);
998 p2.setX(p2.x() - strokeWidth);
1002 if (static_cast<int>(strokeWidth) % 2) { //odd
1003 if (p1.x() == p2.x()) {
1004 // We're a vertical line. Adjust our x.
1005 p1.setX(p1.x() + 0.5f);
1006 p2.setX(p2.x() + 0.5f);
1008 // We're a horizontal line. Adjust our y.
1009 p1.setY(p1.y() + 0.5f);
1010 p2.setY(p2.y() + 0.5f);
1016 void GraphicsContext::platformApplyDeviceScaleFactor(float)
1021 void GraphicsContext::applyDeviceScaleFactor(float deviceScaleFactor)
1023 scale(FloatSize(deviceScaleFactor, deviceScaleFactor));
1025 if (isRecording()) {
1026 m_displayListRecorder->applyDeviceScaleFactor(deviceScaleFactor);
1030 platformApplyDeviceScaleFactor(deviceScaleFactor);
1033 FloatSize GraphicsContext::scaleFactor() const
1035 AffineTransform transform = getCTM(GraphicsContext::DefinitelyIncludeDeviceScale);
1036 return FloatSize(transform.xScale(), transform.yScale());
1039 void GraphicsContext::fillEllipse(const FloatRect& ellipse)
1041 platformFillEllipse(ellipse);
1044 void GraphicsContext::strokeEllipse(const FloatRect& ellipse)
1046 platformStrokeEllipse(ellipse);
1049 void GraphicsContext::fillEllipseAsPath(const FloatRect& ellipse)
1052 path.addEllipse(ellipse);
1056 void GraphicsContext::strokeEllipseAsPath(const FloatRect& ellipse)
1059 path.addEllipse(ellipse);
1064 void GraphicsContext::platformFillEllipse(const FloatRect& ellipse)
1066 if (paintingDisabled())
1069 fillEllipseAsPath(ellipse);
1072 void GraphicsContext::platformStrokeEllipse(const FloatRect& ellipse)
1074 if (paintingDisabled())
1077 strokeEllipseAsPath(ellipse);
1081 FloatRect GraphicsContext::computeUnderlineBoundsForText(const FloatPoint& point, float width, bool printing)
1084 return computeLineBoundsAndAntialiasingModeForText(point, width, printing, dummyColor);
1087 FloatRect GraphicsContext::computeLineBoundsAndAntialiasingModeForText(const FloatPoint& point, float width, bool printing, Color& color)
1089 FloatPoint origin = point;
1090 float thickness = std::max(strokeThickness(), 0.5f);
1092 return FloatRect(origin, FloatSize(width, thickness));
1094 AffineTransform transform = getCTM(GraphicsContext::DefinitelyIncludeDeviceScale);
1095 // Just compute scale in x dimension, assuming x and y scales are equal.
1096 float scale = transform.b() ? sqrtf(transform.a() * transform.a() + transform.b() * transform.b()) : transform.a();
1098 // This code always draws a line that is at least one-pixel line high,
1099 // which tends to visually overwhelm text at small scales. To counter this
1100 // effect, an alpha is applied to the underline color when text is at small scales.
1101 static const float minimumUnderlineAlpha = 0.4f;
1102 float shade = scale > minimumUnderlineAlpha ? scale : minimumUnderlineAlpha;
1103 int alpha = color.alpha() * shade;
1104 color = Color(color.red(), color.green(), color.blue(), alpha);
1107 FloatPoint devicePoint = transform.mapPoint(point);
1108 // Visual overflow might occur here due to integral roundf/ceilf. visualOverflowForDecorations adjusts the overflow value for underline decoration.
1109 FloatPoint deviceOrigin = FloatPoint(roundf(devicePoint.x()), ceilf(devicePoint.y()));
1110 if (auto inverse = transform.inverse())
1111 origin = inverse.value().mapPoint(deviceOrigin);
1112 return FloatRect(origin, FloatSize(width, thickness));
1115 void GraphicsContext::applyState(const GraphicsContextState& state)
1117 setPlatformShadow(state.shadowOffset, state.shadowBlur, state.shadowColor);
1118 setPlatformStrokeThickness(state.strokeThickness);
1119 setPlatformTextDrawingMode(state.textDrawingMode);
1120 setPlatformStrokeColor(state.strokeColor);
1121 setPlatformFillColor(state.fillColor);
1122 setPlatformStrokeStyle(state.strokeStyle);
1123 setPlatformAlpha(state.alpha);
1124 setPlatformCompositeOperation(state.compositeOperator, state.blendMode);
1125 setPlatformShouldAntialias(state.shouldAntialias);
1126 setPlatformShouldSmoothFonts(state.shouldSmoothFonts);