gfx/2d/DrawTargetDual.cpp
author pyup-bot <github-bot@pyup.io>
Wed, 06 Mar 2019 16:53:25 +0000
changeset 522589 0b9ff65fb560cbf087eaa9b23e3377db31772f0d
parent 505383 6f3709b3878117466168c40affa7bca0b60cf75b
child 527951 884f5dc55873c9345ee945cd6d5427e8ab398071
permissions -rw-r--r--
Bug 1531372 [wpt PR 15543] - Update mozrunner to 7.4.0, a=testonly Automatic update from web-platform-tests Update mozrunner from 7.3.0 to 7.4.0 -- wpt-commits: 0f1c6e9b1f63e523eb241e8c0eba1cdc764fd180 wpt-pr: 15543

/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* vim: set ts=8 sts=2 et sw=2 tw=80: */
/* This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */

#include "DrawTargetDual.h"
#include "Tools.h"
#include "Logging.h"

namespace mozilla {
namespace gfx {

class DualSurface {
 public:
  inline explicit DualSurface(SourceSurface *aSurface) {
    if (!aSurface) {
      mA = mB = nullptr;
      return;
    }

    if (aSurface->GetType() != SurfaceType::DUAL_DT) {
      mA = mB = aSurface;
      return;
    }

    SourceSurfaceDual *ssDual = static_cast<SourceSurfaceDual *>(aSurface);
    mA = ssDual->mA;
    mB = ssDual->mB;
  }

  SourceSurface *mA;
  SourceSurface *mB;
};

/* This only needs to split patterns up for SurfacePatterns. Only in that
 * case can we be dealing with a 'dual' source (SourceSurfaceDual) and do
 * we need to pass separate patterns into our destination DrawTargets.
 */
class DualPattern {
 public:
  inline explicit DualPattern(const Pattern &aPattern)
      : mPatternsInitialized(false) {
    if (aPattern.GetType() != PatternType::SURFACE) {
      mA = mB = &aPattern;
      return;
    }

    const SurfacePattern *surfPat =
        static_cast<const SurfacePattern *>(&aPattern);

    if (surfPat->mSurface->GetType() != SurfaceType::DUAL_DT) {
      mA = mB = &aPattern;
      return;
    }

    const SourceSurfaceDual *ssDual =
        static_cast<const SourceSurfaceDual *>(surfPat->mSurface.get());
    mA = new (mSurfPatA.addr())
        SurfacePattern(ssDual->mA, surfPat->mExtendMode, surfPat->mMatrix,
                       surfPat->mSamplingFilter);
    mB = new (mSurfPatB.addr())
        SurfacePattern(ssDual->mB, surfPat->mExtendMode, surfPat->mMatrix,
                       surfPat->mSamplingFilter);
    mPatternsInitialized = true;
  }

  inline ~DualPattern() {
    if (mPatternsInitialized) {
      mA->~Pattern();
      mB->~Pattern();
    }
  }

  ClassStorage<SurfacePattern> mSurfPatA;
  ClassStorage<SurfacePattern> mSurfPatB;

  const Pattern *mA;
  const Pattern *mB;

  bool mPatternsInitialized;
};

void DrawTargetDual::DetachAllSnapshots() {
  mA->DetachAllSnapshots();
  mB->DetachAllSnapshots();
}

void DrawTargetDual::DrawSurface(SourceSurface *aSurface, const Rect &aDest,
                                 const Rect &aSource,
                                 const DrawSurfaceOptions &aSurfOptions,
                                 const DrawOptions &aOptions) {
  DualSurface surface(aSurface);
  mA->DrawSurface(surface.mA, aDest, aSource, aSurfOptions, aOptions);
  mB->DrawSurface(surface.mB, aDest, aSource, aSurfOptions, aOptions);
}

void DrawTargetDual::DrawSurfaceWithShadow(SourceSurface *aSurface,
                                           const Point &aDest,
                                           const Color &aColor,
                                           const Point &aOffset, Float aSigma,
                                           CompositionOp aOp) {
  DualSurface surface(aSurface);
  mA->DrawSurfaceWithShadow(surface.mA, aDest, aColor, aOffset, aSigma, aOp);
  mB->DrawSurfaceWithShadow(surface.mB, aDest, aColor, aOffset, aSigma, aOp);
}

void DrawTargetDual::MaskSurface(const Pattern &aSource, SourceSurface *aMask,
                                 Point aOffset, const DrawOptions &aOptions) {
  DualPattern source(aSource);
  DualSurface mask(aMask);
  mA->MaskSurface(*source.mA, mask.mA, aOffset, aOptions);
  mB->MaskSurface(*source.mB, mask.mB, aOffset, aOptions);
}

void DrawTargetDual::ClearRect(const Rect &aRect) {
  mA->FillRect(aRect, ColorPattern(Color(0.0, 0.0, 0.0, 1.0)));
  mB->FillRect(aRect, ColorPattern(Color(1.0, 1.0, 1.0, 1.0)));
}

void DrawTargetDual::CopySurface(SourceSurface *aSurface,
                                 const IntRect &aSourceRect,
                                 const IntPoint &aDestination) {
  DualSurface surface(aSurface);
  mA->CopySurface(surface.mA, aSourceRect, aDestination);
  mB->CopySurface(surface.mB, aSourceRect, aDestination);
}

void DrawTargetDual::FillRect(const Rect &aRect, const Pattern &aPattern,
                              const DrawOptions &aOptions) {
  DualPattern pattern(aPattern);
  mA->FillRect(aRect, *pattern.mA, aOptions);
  mB->FillRect(aRect, *pattern.mB, aOptions);
}

void DrawTargetDual::StrokeRect(const Rect &aRect, const Pattern &aPattern,
                                const StrokeOptions &aStrokeOptions,
                                const DrawOptions &aOptions) {
  DualPattern pattern(aPattern);
  mA->StrokeRect(aRect, *pattern.mA, aStrokeOptions, aOptions);
  mB->StrokeRect(aRect, *pattern.mB, aStrokeOptions, aOptions);
}

void DrawTargetDual::StrokeLine(const Point &aStart, const Point &aEnd,
                                const Pattern &aPattern,
                                const StrokeOptions &aStrokeOptions,
                                const DrawOptions &aOptions) {
  DualPattern pattern(aPattern);
  mA->StrokeLine(aStart, aEnd, *pattern.mA, aStrokeOptions, aOptions);
  mB->StrokeLine(aStart, aEnd, *pattern.mB, aStrokeOptions, aOptions);
}

void DrawTargetDual::Stroke(const Path *aPath, const Pattern &aPattern,
                            const StrokeOptions &aStrokeOptions,
                            const DrawOptions &aOptions) {
  DualPattern pattern(aPattern);
  mA->Stroke(aPath, *pattern.mA, aStrokeOptions, aOptions);
  mB->Stroke(aPath, *pattern.mB, aStrokeOptions, aOptions);
}

void DrawTargetDual::Fill(const Path *aPath, const Pattern &aPattern,
                          const DrawOptions &aOptions) {
  DualPattern pattern(aPattern);
  mA->Fill(aPath, *pattern.mA, aOptions);
  mB->Fill(aPath, *pattern.mB, aOptions);
}

void DrawTargetDual::FillGlyphs(ScaledFont *aScaledFont,
                                const GlyphBuffer &aBuffer,
                                const Pattern &aPattern,
                                const DrawOptions &aOptions) {
  DualPattern pattern(aPattern);
  mA->FillGlyphs(aScaledFont, aBuffer, *pattern.mA, aOptions);
  mB->FillGlyphs(aScaledFont, aBuffer, *pattern.mB, aOptions);
}

void DrawTargetDual::Mask(const Pattern &aSource, const Pattern &aMask,
                          const DrawOptions &aOptions) {
  DualPattern source(aSource);
  DualPattern mask(aMask);
  mA->Mask(*source.mA, *mask.mA, aOptions);
  mB->Mask(*source.mB, *mask.mB, aOptions);
}

void DrawTargetDual::PushLayer(bool aOpaque, Float aOpacity,
                               SourceSurface *aMask,
                               const Matrix &aMaskTransform,
                               const IntRect &aBounds, bool aCopyBackground) {
  DualSurface mask(aMask);
  mA->PushLayer(aOpaque, aOpacity, mask.mA, aMaskTransform, aBounds,
                aCopyBackground);
  mB->PushLayer(aOpaque, aOpacity, mask.mB, aMaskTransform, aBounds,
                aCopyBackground);
}

already_AddRefed<DrawTarget> DrawTargetDual::CreateSimilarDrawTarget(
    const IntSize &aSize, SurfaceFormat aFormat) const {
  /* Now that we have PushLayer there a very few cases where a user of
   * DrawTargetDual wants to have a DualTarget when creating a similar one. */
  return mA->CreateSimilarDrawTarget(aSize, aFormat);
}

bool DrawTargetDual::CanCreateSimilarDrawTarget(const IntSize &aSize,
                                                SurfaceFormat aFormat) const {
  return mA->CanCreateSimilarDrawTarget(aSize, aFormat);
}

}  // namespace gfx
}  // namespace mozilla