Coverage Report

Created: 2018-09-25 14:53

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