DXR is a code search and navigation tool aimed at making sense of large projects. It supports full-text and regex searches as well as structural queries.

Header

Mercurial (e67641c2e4cc)

VCS Links

Line Code
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199
/* -*- 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::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);
}

}  // namespace gfx
}  // namespace mozilla