| /* |
| * Copyright (C) 2021 Apple Inc. All rights reserved. |
| * |
| * Redistribution and use in source and binary forms, with or without |
| * modification, are permitted provided that the following conditions |
| * are met: |
| * 1. Redistributions of source code must retain the above copyright |
| * notice, this list of conditions and the following disclaimer. |
| * 2. Redistributions in binary form must reproduce the above copyright |
| * notice, this list of conditions and the following disclaimer in the |
| * documentation and/or other materials provided with the distribution. |
| * |
| * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY |
| * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE |
| * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR |
| * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR |
| * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, |
| * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, |
| * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR |
| * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY |
| * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT |
| * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE |
| * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
| */ |
| |
| #include "config.h" |
| #include "BifurcatedGraphicsContext.h" |
| |
| namespace WebCore { |
| |
| BifurcatedGraphicsContext::BifurcatedGraphicsContext(GraphicsContext& primaryContext, GraphicsContext& secondaryContext) |
| : m_primaryContext(primaryContext) |
| , m_secondaryContext(secondaryContext) |
| { |
| } |
| |
| BifurcatedGraphicsContext::~BifurcatedGraphicsContext() |
| { |
| } |
| |
| bool BifurcatedGraphicsContext::hasPlatformContext() const |
| { |
| return m_primaryContext.hasPlatformContext(); |
| } |
| |
| PlatformGraphicsContext* BifurcatedGraphicsContext::platformContext() const |
| { |
| return m_primaryContext.platformContext(); |
| } |
| |
| void BifurcatedGraphicsContext::save() |
| { |
| // FIXME: Consider not using the BifurcatedGraphicsContext's state stack at all, |
| // and making all of the state getters and setters virtual. |
| GraphicsContext::save(); |
| m_primaryContext.save(); |
| m_secondaryContext.save(); |
| } |
| |
| void BifurcatedGraphicsContext::restore() |
| { |
| GraphicsContext::restore(); |
| m_primaryContext.restore(); |
| m_secondaryContext.restore(); |
| } |
| |
| void BifurcatedGraphicsContext::drawRect(const FloatRect& rect, float borderThickness) |
| { |
| m_primaryContext.drawRect(rect, borderThickness); |
| m_secondaryContext.drawRect(rect, borderThickness); |
| } |
| |
| void BifurcatedGraphicsContext::drawLine(const FloatPoint& from, const FloatPoint& to) |
| { |
| m_primaryContext.drawLine(from, to); |
| m_secondaryContext.drawLine(from, to); |
| } |
| |
| void BifurcatedGraphicsContext::drawEllipse(const FloatRect& rect) |
| { |
| m_primaryContext.drawEllipse(rect); |
| m_secondaryContext.drawEllipse(rect); |
| } |
| |
| #if USE(CG) || USE(DIRECT2D) |
| void BifurcatedGraphicsContext::applyStrokePattern() |
| { |
| m_primaryContext.applyStrokePattern(); |
| m_secondaryContext.applyStrokePattern(); |
| } |
| |
| void BifurcatedGraphicsContext::applyFillPattern() |
| { |
| m_primaryContext.applyFillPattern(); |
| m_secondaryContext.applyFillPattern(); |
| } |
| #endif |
| |
| void BifurcatedGraphicsContext::drawPath(const Path& path) |
| { |
| m_primaryContext.drawPath(path); |
| m_secondaryContext.drawPath(path); |
| } |
| |
| void BifurcatedGraphicsContext::fillPath(const Path& path) |
| { |
| m_primaryContext.fillPath(path); |
| m_secondaryContext.fillPath(path); |
| } |
| |
| void BifurcatedGraphicsContext::strokePath(const Path& path) |
| { |
| m_primaryContext.strokePath(path); |
| m_secondaryContext.strokePath(path); |
| } |
| |
| void BifurcatedGraphicsContext::beginTransparencyLayer(float opacity) |
| { |
| m_primaryContext.beginTransparencyLayer(opacity); |
| m_secondaryContext.beginTransparencyLayer(opacity); |
| } |
| |
| void BifurcatedGraphicsContext::endTransparencyLayer() |
| { |
| m_primaryContext.endTransparencyLayer(); |
| m_secondaryContext.endTransparencyLayer(); |
| } |
| |
| void BifurcatedGraphicsContext::applyDeviceScaleFactor(float factor) |
| { |
| m_primaryContext.applyDeviceScaleFactor(factor); |
| m_secondaryContext.applyDeviceScaleFactor(factor); |
| } |
| |
| void BifurcatedGraphicsContext::fillRect(const FloatRect& rect) |
| { |
| m_primaryContext.fillRect(rect); |
| m_secondaryContext.fillRect(rect); |
| } |
| |
| void BifurcatedGraphicsContext::fillRect(const FloatRect& rect, const Color& color) |
| { |
| m_primaryContext.fillRect(rect, color); |
| m_secondaryContext.fillRect(rect, color); |
| } |
| |
| void BifurcatedGraphicsContext::fillRoundedRectImpl(const FloatRoundedRect& rect, const Color& color) |
| { |
| m_primaryContext.fillRoundedRectImpl(rect, color); |
| m_secondaryContext.fillRoundedRectImpl(rect, color); |
| } |
| |
| void BifurcatedGraphicsContext::fillRectWithRoundedHole(const FloatRect& rect, const FloatRoundedRect& roundedHoleRect, const Color& color) |
| { |
| m_primaryContext.fillRectWithRoundedHole(rect, roundedHoleRect, color); |
| m_secondaryContext.fillRectWithRoundedHole(rect, roundedHoleRect, color); |
| } |
| |
| void BifurcatedGraphicsContext::clearRect(const FloatRect& rect) |
| { |
| m_primaryContext.clearRect(rect); |
| m_secondaryContext.clearRect(rect); |
| } |
| |
| void BifurcatedGraphicsContext::strokeRect(const FloatRect& rect, float lineWidth) |
| { |
| m_primaryContext.strokeRect(rect, lineWidth); |
| m_secondaryContext.strokeRect(rect, lineWidth); |
| } |
| |
| void BifurcatedGraphicsContext::fillEllipse(const FloatRect& ellipse) |
| { |
| m_primaryContext.fillEllipse(ellipse); |
| m_secondaryContext.fillEllipse(ellipse); |
| } |
| |
| void BifurcatedGraphicsContext::strokeEllipse(const FloatRect& ellipse) |
| { |
| m_primaryContext.strokeEllipse(ellipse); |
| m_secondaryContext.strokeEllipse(ellipse); |
| } |
| |
| #if USE(CG) || USE(DIRECT2D) |
| void BifurcatedGraphicsContext::setIsCALayerContext(bool isCALayerContext) |
| { |
| m_primaryContext.setIsCALayerContext(isCALayerContext); |
| m_secondaryContext.setIsCALayerContext(isCALayerContext); |
| } |
| |
| bool BifurcatedGraphicsContext::isCALayerContext() const |
| { |
| return m_primaryContext.isCALayerContext(); |
| } |
| |
| void BifurcatedGraphicsContext::setIsAcceleratedContext(bool isAcceleratedContext) |
| { |
| m_primaryContext.setIsAcceleratedContext(isAcceleratedContext); |
| m_secondaryContext.setIsAcceleratedContext(isAcceleratedContext); |
| } |
| #endif |
| |
| RenderingMode BifurcatedGraphicsContext::renderingMode() const |
| { |
| return m_primaryContext.renderingMode(); |
| } |
| |
| void BifurcatedGraphicsContext::clip(const FloatRect& rect) |
| { |
| m_primaryContext.clip(rect); |
| m_secondaryContext.clip(rect); |
| } |
| |
| void BifurcatedGraphicsContext::clipOut(const FloatRect& rect) |
| { |
| m_primaryContext.clipOut(rect); |
| m_secondaryContext.clipOut(rect); |
| } |
| |
| void BifurcatedGraphicsContext::clipOut(const Path& path) |
| { |
| m_primaryContext.clipOut(path); |
| m_secondaryContext.clipOut(path); |
| } |
| |
| void BifurcatedGraphicsContext::clipPath(const Path& path, WindRule windRule) |
| { |
| m_primaryContext.clipPath(path, windRule); |
| m_secondaryContext.clipPath(path, windRule); |
| } |
| |
| IntRect BifurcatedGraphicsContext::clipBounds() const |
| { |
| return m_primaryContext.clipBounds(); |
| } |
| |
| void BifurcatedGraphicsContext::setLineCap(LineCap lineCap) |
| { |
| m_primaryContext.setLineCap(lineCap); |
| m_secondaryContext.setLineCap(lineCap); |
| } |
| |
| void BifurcatedGraphicsContext::setLineDash(const DashArray& dashArray, float dashOffset) |
| { |
| m_primaryContext.setLineDash(dashArray, dashOffset); |
| m_secondaryContext.setLineDash(dashArray, dashOffset); |
| } |
| |
| void BifurcatedGraphicsContext::setLineJoin(LineJoin lineJoin) |
| { |
| m_primaryContext.setLineJoin(lineJoin); |
| m_secondaryContext.setLineJoin(lineJoin); |
| } |
| |
| void BifurcatedGraphicsContext::setMiterLimit(float miterLimit) |
| { |
| m_primaryContext.setMiterLimit(miterLimit); |
| m_secondaryContext.setMiterLimit(miterLimit); |
| } |
| |
| void BifurcatedGraphicsContext::drawNativeImage(NativeImage& nativeImage, const FloatSize& selfSize, const FloatRect& destRect, const FloatRect& srcRect, const ImagePaintingOptions& options) |
| { |
| m_primaryContext.drawNativeImage(nativeImage, selfSize, destRect, srcRect, options); |
| m_secondaryContext.drawNativeImage(nativeImage, selfSize, destRect, srcRect, options); |
| } |
| |
| void BifurcatedGraphicsContext::drawPattern(NativeImage& nativeImage, const FloatSize& imageSize, const FloatRect& destRect, const FloatRect& tileRect, const AffineTransform& patternTransform, const FloatPoint& phase, const FloatSize& spacing, const ImagePaintingOptions& options) |
| { |
| m_primaryContext.drawPattern(nativeImage, imageSize, destRect, tileRect, patternTransform, phase, spacing, options); |
| m_secondaryContext.drawPattern(nativeImage, imageSize, destRect, tileRect, patternTransform, phase, spacing, options); |
| } |
| |
| ImageDrawResult BifurcatedGraphicsContext::drawImage(Image& image, const FloatRect& destination, const FloatRect& source, const ImagePaintingOptions& options) |
| { |
| auto result = m_primaryContext.drawImage(image, destination, source, options); |
| m_secondaryContext.drawImage(image, destination, source, options); |
| return result; |
| } |
| |
| ImageDrawResult BifurcatedGraphicsContext::drawImageForCanvas(Image& image, const FloatRect& destination, const FloatRect& source, const ImagePaintingOptions& options, DestinationColorSpace canvasColorSpace) |
| { |
| auto result = m_primaryContext.drawImageForCanvas(image, destination, source, options, canvasColorSpace); |
| m_secondaryContext.drawImageForCanvas(image, destination, source, options, canvasColorSpace); |
| return result; |
| } |
| |
| ImageDrawResult BifurcatedGraphicsContext::drawTiledImage(Image& image, const FloatRect& destination, const FloatPoint& source, const FloatSize& tileSize, const FloatSize& spacing, const ImagePaintingOptions& options) |
| { |
| auto result = m_primaryContext.drawTiledImage(image, destination, source, tileSize, spacing, options); |
| m_secondaryContext.drawTiledImage(image, destination, source, tileSize, spacing, options); |
| return result; |
| } |
| |
| ImageDrawResult BifurcatedGraphicsContext::drawTiledImage(Image& image, const FloatRect& destination, const FloatRect& source, const FloatSize& tileScaleFactor, Image::TileRule hRule, Image::TileRule vRule, const ImagePaintingOptions& options) |
| { |
| auto result = m_primaryContext.drawTiledImage(image, destination, source, tileScaleFactor, hRule, vRule, options); |
| m_secondaryContext.drawTiledImage(image, destination, source, tileScaleFactor, hRule, vRule, options); |
| return result; |
| } |
| |
| #if ENABLE(VIDEO) |
| void BifurcatedGraphicsContext::paintFrameForMedia(MediaPlayer& player, const FloatRect& destination) |
| { |
| m_primaryContext.paintFrameForMedia(player, destination); |
| m_secondaryContext.paintFrameForMedia(player, destination); |
| } |
| #endif // ENABLE(VIDEO) |
| |
| void BifurcatedGraphicsContext::scale(const FloatSize& scale) |
| { |
| m_primaryContext.scale(scale); |
| m_secondaryContext.scale(scale); |
| } |
| |
| void BifurcatedGraphicsContext::rotate(float angleInRadians) |
| { |
| m_primaryContext.rotate(angleInRadians); |
| m_secondaryContext.rotate(angleInRadians); |
| } |
| |
| void BifurcatedGraphicsContext::translate(float x, float y) |
| { |
| m_primaryContext.translate(x, y); |
| m_secondaryContext.translate(x, y); |
| } |
| |
| void BifurcatedGraphicsContext::concatCTM(const AffineTransform& transform) |
| { |
| m_primaryContext.concatCTM(transform); |
| m_secondaryContext.concatCTM(transform); |
| } |
| |
| void BifurcatedGraphicsContext::setCTM(const AffineTransform& transform) |
| { |
| m_primaryContext.setCTM(transform); |
| m_secondaryContext.setCTM(transform); |
| } |
| |
| AffineTransform BifurcatedGraphicsContext::getCTM(IncludeDeviceScale includeDeviceScale) const |
| { |
| return m_primaryContext.getCTM(includeDeviceScale); |
| } |
| |
| FloatRect BifurcatedGraphicsContext::roundToDevicePixels(const FloatRect& rect, RoundingMode roundingMode) |
| { |
| return m_primaryContext.roundToDevicePixels(rect, roundingMode); |
| } |
| |
| void BifurcatedGraphicsContext::drawFocusRing(const Vector<FloatRect>& rects, float width, float offset, const Color& color) |
| { |
| m_primaryContext.drawFocusRing(rects, width, offset, color); |
| m_secondaryContext.drawFocusRing(rects, width, offset, color); |
| } |
| |
| void BifurcatedGraphicsContext::drawFocusRing(const Path& path, float width, float offset, const Color& color) |
| { |
| m_primaryContext.drawFocusRing(path, width, offset, color); |
| m_secondaryContext.drawFocusRing(path, width, offset, color); |
| } |
| |
| #if PLATFORM(MAC) |
| void BifurcatedGraphicsContext::drawFocusRing(const Path& path, double timeOffset, bool& needsRedraw, const Color& color) |
| { |
| m_primaryContext.drawFocusRing(path, timeOffset, needsRedraw, color); |
| m_secondaryContext.drawFocusRing(path, timeOffset, needsRedraw, color); |
| } |
| |
| void BifurcatedGraphicsContext::drawFocusRing(const Vector<FloatRect>& rects, double timeOffset, bool& needsRedraw, const Color& color) |
| { |
| m_primaryContext.drawFocusRing(rects, timeOffset, needsRedraw, color); |
| m_secondaryContext.drawFocusRing(rects, timeOffset, needsRedraw, color); |
| } |
| #endif |
| |
| FloatSize BifurcatedGraphicsContext::drawText(const FontCascade& cascade, const TextRun& run, const FloatPoint& point, unsigned from, std::optional<unsigned> to) |
| { |
| auto size = m_primaryContext.drawText(cascade, run, point, from, to); |
| m_secondaryContext.drawText(cascade, run, point, from, to); |
| return size; |
| } |
| |
| void BifurcatedGraphicsContext::drawGlyphs(const Font& font, const GlyphBufferGlyph* glyphs, const GlyphBufferAdvance* advances, unsigned numGlyphs, const FloatPoint& point, FontSmoothingMode fontSmoothingMode) |
| { |
| m_primaryContext.drawGlyphs(font, glyphs, advances, numGlyphs, point, fontSmoothingMode); |
| m_secondaryContext.drawGlyphs(font, glyphs, advances, numGlyphs, point, fontSmoothingMode); |
| } |
| |
| void BifurcatedGraphicsContext::drawEmphasisMarks(const FontCascade& cascade, const TextRun& run, const AtomString& mark, const FloatPoint& point, unsigned from, std::optional<unsigned> to) |
| { |
| m_primaryContext.drawEmphasisMarks(cascade, run, mark, point, from, to); |
| m_secondaryContext.drawEmphasisMarks(cascade, run, mark, point, from, to); |
| } |
| |
| void BifurcatedGraphicsContext::drawBidiText(const FontCascade& cascade, const TextRun& run, const FloatPoint& point, FontCascade::CustomFontNotReadyAction customFontNotReadyAction) |
| { |
| m_primaryContext.drawBidiText(cascade, run, point, customFontNotReadyAction); |
| m_secondaryContext.drawBidiText(cascade, run, point, customFontNotReadyAction); |
| } |
| |
| void BifurcatedGraphicsContext::drawLinesForText(const FloatPoint& point, float thickness, const DashArray& widths, bool printing, bool doubleLines, StrokeStyle strokeStyle) |
| { |
| m_primaryContext.drawLinesForText(point, thickness, widths, printing, doubleLines, strokeStyle); |
| m_secondaryContext.drawLinesForText(point, thickness, widths, printing, doubleLines, strokeStyle); |
| } |
| |
| void BifurcatedGraphicsContext::drawDotsForDocumentMarker(const FloatRect& rect, DocumentMarkerLineStyle markerStyle) |
| { |
| m_primaryContext.drawDotsForDocumentMarker(rect, markerStyle); |
| m_secondaryContext.drawDotsForDocumentMarker(rect, markerStyle); |
| } |
| |
| void BifurcatedGraphicsContext::setURLForRect(const URL& url, const FloatRect& rect) |
| { |
| m_primaryContext.setURLForRect(url, rect); |
| m_secondaryContext.setURLForRect(url, rect); |
| } |
| |
| void BifurcatedGraphicsContext::setDestinationForRect(const String& name, const FloatRect& rect) |
| { |
| m_primaryContext.setDestinationForRect(name, rect); |
| m_secondaryContext.setDestinationForRect(name, rect); |
| } |
| |
| void BifurcatedGraphicsContext::addDestinationAtPoint(const String& name, const FloatPoint& point) |
| { |
| m_primaryContext.addDestinationAtPoint(name, point); |
| m_secondaryContext.addDestinationAtPoint(name, point); |
| } |
| |
| bool BifurcatedGraphicsContext::supportsInternalLinks() const |
| { |
| return m_primaryContext.supportsInternalLinks(); |
| } |
| |
| void BifurcatedGraphicsContext::didUpdateState(const GraphicsContextState& state, GraphicsContextState::StateChangeFlags flags) |
| { |
| // This calls updateState() instead of didUpdateState() so that changes |
| // are also applied to each context's GraphicsContextState, so that code |
| // internal to the child contexts that reads from the state gets the right values. |
| m_primaryContext.updateState(state, flags); |
| m_secondaryContext.updateState(state, flags); |
| } |
| |
| #if OS(WINDOWS) && !USE(CAIRO) |
| GraphicsContextPlatformPrivate* BifurcatedGraphicsContext::deprecatedPrivateContext() const |
| { |
| return m_primaryContext.deprecatedPrivateContext(); |
| } |
| #endif |
| |
| } // namespace WebCore |
| |