tor-browser

The Tor Browser
git clone https://git.dasho.dev/tor-browser.git
Log | Files | Refs | README | LICENSE

gfxPattern.cpp (6877B)


      1 /* -*- Mode: C++; tab-width: 20; indent-tabs-mode: nil; c-basic-offset: 2 -*-
      2 * This Source Code Form is subject to the terms of the Mozilla Public
      3 * License, v. 2.0. If a copy of the MPL was not distributed with this
      4 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
      5 
      6 #include "gfxPattern.h"
      7 
      8 #include "gfxUtils.h"
      9 #include "gfxTypes.h"
     10 #include "gfxPlatform.h"
     11 #include "gfx2DGlue.h"
     12 #include "gfxGradientCache.h"
     13 #include "mozilla/gfx/2D.h"
     14 
     15 #include "cairo.h"
     16 
     17 using namespace mozilla::gfx;
     18 
     19 gfxPattern::gfxPattern(const DeviceColor& aColor) : mExtend(ExtendMode::CLAMP) {
     20  mGfxPattern.InitColorPattern(aColor);
     21 }
     22 
     23 // linear
     24 gfxPattern::gfxPattern(gfxFloat x0, gfxFloat y0, gfxFloat x1, gfxFloat y1)
     25    : mExtend(ExtendMode::CLAMP) {
     26  mGfxPattern.InitLinearGradientPattern(Point(x0, y0), Point(x1, y1), nullptr);
     27 }
     28 
     29 // radial
     30 gfxPattern::gfxPattern(gfxFloat cx0, gfxFloat cy0, gfxFloat radius0,
     31                       gfxFloat cx1, gfxFloat cy1, gfxFloat radius1)
     32    : mExtend(ExtendMode::CLAMP) {
     33  mGfxPattern.InitRadialGradientPattern(Point(cx0, cy0), Point(cx1, cy1),
     34                                        radius0, radius1, nullptr);
     35 }
     36 
     37 // conic
     38 gfxPattern::gfxPattern(gfxFloat cx, gfxFloat cy, gfxFloat angle,
     39                       gfxFloat startOffset, gfxFloat endOffset)
     40    : mExtend(ExtendMode::CLAMP) {
     41  mGfxPattern.InitConicGradientPattern(Point(cx, cy), angle, startOffset,
     42                                       endOffset, nullptr);
     43 }
     44 
     45 // Azure
     46 gfxPattern::gfxPattern(SourceSurface* aSurface,
     47                       const Matrix& aPatternToUserSpace)
     48    : mPatternToUserSpace(aPatternToUserSpace), mExtend(ExtendMode::CLAMP) {
     49  mGfxPattern.InitSurfacePattern(
     50      aSurface, mExtend, Matrix(),  // matrix is overridden in GetPattern()
     51      mozilla::gfx::SamplingFilter::GOOD);
     52 }
     53 
     54 void gfxPattern::AddColorStop(gfxFloat offset, const DeviceColor& c) {
     55  if (mGfxPattern.GetPattern()->GetType() != PatternType::LINEAR_GRADIENT &&
     56      mGfxPattern.GetPattern()->GetType() != PatternType::RADIAL_GRADIENT &&
     57      mGfxPattern.GetPattern()->GetType() != PatternType::CONIC_GRADIENT) {
     58    return;
     59  }
     60 
     61  mStops = nullptr;
     62 
     63  GradientStop stop;
     64  stop.offset = offset;
     65  stop.color = c;
     66  mStopsList.AppendElement(stop);
     67 }
     68 
     69 void gfxPattern::SetColorStops(GradientStops* aStops) { mStops = aStops; }
     70 
     71 void gfxPattern::CacheColorStops(const DrawTarget* aDT) {
     72  mStops = gfxGradientCache::GetOrCreateGradientStops(aDT, mStopsList, mExtend);
     73 }
     74 
     75 void gfxPattern::SetMatrix(const gfxMatrix& aPatternToUserSpace) {
     76  mPatternToUserSpace = ToMatrix(aPatternToUserSpace);
     77  // Cairo-pattern matrices specify the conversion from DrawTarget to pattern
     78  // space. Azure pattern matrices specify the conversion from pattern to
     79  // DrawTarget space.
     80  mPatternToUserSpace.Invert();
     81 }
     82 
     83 gfxMatrix gfxPattern::GetMatrix() const {
     84  // invert at the higher precision of gfxMatrix
     85  // cause we need to convert at some point anyways
     86  gfxMatrix mat = ThebesMatrix(mPatternToUserSpace);
     87  mat.Invert();
     88  return mat;
     89 }
     90 
     91 gfxMatrix gfxPattern::GetInverseMatrix() const {
     92  return ThebesMatrix(mPatternToUserSpace);
     93 }
     94 
     95 Pattern* gfxPattern::GetPattern(const DrawTarget* aTarget,
     96                                const Matrix* aOriginalUserToDevice) {
     97  Matrix patternToUser = mPatternToUserSpace;
     98 
     99  if (aOriginalUserToDevice &&
    100      !aOriginalUserToDevice->FuzzyEquals(aTarget->GetTransform())) {
    101    // mPatternToUserSpace maps from pattern space to the original user space,
    102    // but aTarget now has a transform to a different user space.  In order for
    103    // the Pattern* that we return to be usable in aTarget's new user space we
    104    // need the Pattern's mMatrix to be the transform from pattern space to
    105    // aTarget's -new- user space.  That transform is equivalent to the
    106    // transform from pattern space to original user space (patternToUser),
    107    // multiplied by the transform from original user space to device space,
    108    // multiplied by the transform from device space to current user space.
    109 
    110    Matrix deviceToCurrentUser = aTarget->GetTransform();
    111    deviceToCurrentUser.Invert();
    112 
    113    patternToUser =
    114        patternToUser * *aOriginalUserToDevice * deviceToCurrentUser;
    115  }
    116  patternToUser.NudgeToIntegers();
    117 
    118  if (!mStops && !mStopsList.IsEmpty()) {
    119    mStops = aTarget->CreateGradientStops(mStopsList.Elements(),
    120                                          mStopsList.Length(), mExtend);
    121  }
    122 
    123  switch (mGfxPattern.GetPattern()->GetType()) {
    124    case PatternType::SURFACE: {
    125      SurfacePattern* surfacePattern =
    126          static_cast<SurfacePattern*>(mGfxPattern.GetPattern());
    127      surfacePattern->mMatrix = patternToUser;
    128      surfacePattern->mExtendMode = mExtend;
    129      break;
    130    }
    131    case PatternType::LINEAR_GRADIENT: {
    132      LinearGradientPattern* linearGradientPattern =
    133          static_cast<LinearGradientPattern*>(mGfxPattern.GetPattern());
    134      linearGradientPattern->mMatrix = patternToUser;
    135      linearGradientPattern->mStops = mStops;
    136      break;
    137    }
    138    case PatternType::RADIAL_GRADIENT: {
    139      RadialGradientPattern* radialGradientPattern =
    140          static_cast<RadialGradientPattern*>(mGfxPattern.GetPattern());
    141      radialGradientPattern->mMatrix = patternToUser;
    142      radialGradientPattern->mStops = mStops;
    143      break;
    144    }
    145    case PatternType::CONIC_GRADIENT: {
    146      ConicGradientPattern* conicGradientPattern =
    147          static_cast<ConicGradientPattern*>(mGfxPattern.GetPattern());
    148      conicGradientPattern->mMatrix = patternToUser;
    149      conicGradientPattern->mStops = mStops;
    150      break;
    151    }
    152    default:
    153      /* Reassure the compiler we are handling all the enum values.  */
    154      break;
    155  }
    156 
    157  return mGfxPattern.GetPattern();
    158 }
    159 
    160 void gfxPattern::SetExtend(ExtendMode aExtend) {
    161  mExtend = aExtend;
    162  mStops = nullptr;
    163 }
    164 
    165 bool gfxPattern::IsOpaque() {
    166  if (mGfxPattern.GetPattern()->GetType() != PatternType::SURFACE) {
    167    return false;
    168  }
    169 
    170  if (static_cast<SurfacePattern*>(mGfxPattern.GetPattern())
    171          ->mSurface->GetFormat() == SurfaceFormat::B8G8R8X8) {
    172    return true;
    173  }
    174  return false;
    175 }
    176 
    177 void gfxPattern::SetSamplingFilter(mozilla::gfx::SamplingFilter filter) {
    178  if (mGfxPattern.GetPattern()->GetType() != PatternType::SURFACE) {
    179    return;
    180  }
    181 
    182  static_cast<SurfacePattern*>(mGfxPattern.GetPattern())->mSamplingFilter =
    183      filter;
    184 }
    185 
    186 SamplingFilter gfxPattern::SamplingFilter() const {
    187  if (mGfxPattern.GetPattern()->GetType() != PatternType::SURFACE) {
    188    return mozilla::gfx::SamplingFilter::GOOD;
    189  }
    190  return static_cast<const SurfacePattern*>(mGfxPattern.GetPattern())
    191      ->mSamplingFilter;
    192 }
    193 
    194 bool gfxPattern::GetSolidColor(DeviceColor& aColorOut) {
    195  if (mGfxPattern.GetPattern()->GetType() == PatternType::COLOR) {
    196    aColorOut = static_cast<ColorPattern*>(mGfxPattern.GetPattern())->mColor;
    197    return true;
    198  }
    199 
    200  return false;
    201 }