2012-05-30 08:42:41 +04:00
|
|
|
/* -*- Mode: C++; tab-width: 20; indent-tabs-mode: nil; c-basic-offset: 2 -*-
|
2012-05-21 15:12:37 +04:00
|
|
|
* 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/. */
|
2007-01-27 04:26:49 +03:00
|
|
|
|
|
|
|
#include "gfxPattern.h"
|
2014-10-17 15:53:15 +04:00
|
|
|
|
|
|
|
#include "gfxUtils.h"
|
|
|
|
#include "gfxTypes.h"
|
2007-01-27 04:26:49 +03:00
|
|
|
#include "gfxASurface.h"
|
2007-11-09 21:14:59 +03:00
|
|
|
#include "gfxPlatform.h"
|
2013-10-08 03:15:59 +04:00
|
|
|
#include "gfx2DGlue.h"
|
2013-11-08 08:50:39 +04:00
|
|
|
#include "gfxGradientCache.h"
|
2014-09-14 13:58:56 +04:00
|
|
|
#include "mozilla/gfx/2D.h"
|
2007-01-27 04:26:49 +03:00
|
|
|
|
|
|
|
#include "cairo.h"
|
|
|
|
|
2012-01-05 11:17:51 +04:00
|
|
|
#include <vector>
|
|
|
|
|
|
|
|
using namespace mozilla::gfx;
|
|
|
|
|
2020-03-09 17:16:17 +03:00
|
|
|
gfxPattern::gfxPattern(const DeviceColor& aColor) : mExtend(ExtendMode::CLAMP) {
|
|
|
|
mGfxPattern.InitColorPattern(aColor);
|
2007-01-27 04:26:49 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
// linear
|
|
|
|
gfxPattern::gfxPattern(gfxFloat x0, gfxFloat y0, gfxFloat x1, gfxFloat y1)
|
2015-09-25 10:58:23 +03:00
|
|
|
: mExtend(ExtendMode::CLAMP) {
|
2014-09-29 17:12:06 +04:00
|
|
|
mGfxPattern.InitLinearGradientPattern(Point(x0, y0), Point(x1, y1), nullptr);
|
2007-01-27 04:26:49 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
// radial
|
|
|
|
gfxPattern::gfxPattern(gfxFloat cx0, gfxFloat cy0, gfxFloat radius0,
|
|
|
|
gfxFloat cx1, gfxFloat cy1, gfxFloat radius1)
|
2015-09-25 10:58:23 +03:00
|
|
|
: mExtend(ExtendMode::CLAMP) {
|
2014-09-29 17:12:06 +04:00
|
|
|
mGfxPattern.InitRadialGradientPattern(Point(cx0, cy0), Point(cx1, cy1),
|
|
|
|
radius0, radius1, nullptr);
|
2007-01-27 04:26:49 +03:00
|
|
|
}
|
|
|
|
|
2020-02-21 03:12:47 +03:00
|
|
|
// conic
|
2020-03-09 00:46:06 +03:00
|
|
|
gfxPattern::gfxPattern(gfxFloat cx, gfxFloat cy, gfxFloat angle,
|
|
|
|
gfxFloat startOffset, gfxFloat endOffset)
|
2020-02-21 03:12:47 +03:00
|
|
|
: mExtend(ExtendMode::CLAMP) {
|
2020-03-09 00:46:06 +03:00
|
|
|
mGfxPattern.InitConicGradientPattern(Point(cx, cy), angle, startOffset,
|
|
|
|
endOffset, nullptr);
|
2020-02-21 03:12:47 +03:00
|
|
|
}
|
|
|
|
|
2012-01-05 11:17:51 +04:00
|
|
|
// Azure
|
2014-09-15 19:24:03 +04:00
|
|
|
gfxPattern::gfxPattern(SourceSurface* aSurface,
|
|
|
|
const Matrix& aPatternToUserSpace)
|
|
|
|
: mPatternToUserSpace(aPatternToUserSpace), mExtend(ExtendMode::CLAMP) {
|
2015-09-25 10:58:23 +03:00
|
|
|
mGfxPattern.InitSurfacePattern(
|
|
|
|
aSurface, mExtend, Matrix(), // matrix is overridden in GetPattern()
|
2016-05-25 19:01:18 +03:00
|
|
|
mozilla::gfx::SamplingFilter::GOOD);
|
2007-01-27 04:26:49 +03:00
|
|
|
}
|
|
|
|
|
2020-03-09 17:16:17 +03:00
|
|
|
void gfxPattern::AddColorStop(gfxFloat offset, const DeviceColor& c) {
|
2014-09-29 17:12:06 +04:00
|
|
|
if (mGfxPattern.GetPattern()->GetType() != PatternType::LINEAR_GRADIENT &&
|
2020-02-21 03:12:47 +03:00
|
|
|
mGfxPattern.GetPattern()->GetType() != PatternType::RADIAL_GRADIENT &&
|
|
|
|
mGfxPattern.GetPattern()->GetType() != PatternType::CONIC_GRADIENT) {
|
2014-09-14 13:58:56 +04:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
mStops = nullptr;
|
|
|
|
|
|
|
|
GradientStop stop;
|
|
|
|
stop.offset = offset;
|
2020-03-09 17:16:17 +03:00
|
|
|
stop.color = c;
|
2014-09-14 13:58:56 +04:00
|
|
|
mStopsList.AppendElement(stop);
|
2007-01-27 04:26:49 +03:00
|
|
|
}
|
|
|
|
|
2014-06-12 23:24:05 +04:00
|
|
|
void gfxPattern::SetColorStops(GradientStops* aStops) { mStops = aStops; }
|
2013-02-15 22:54:49 +04:00
|
|
|
|
2014-09-29 17:15:19 +04:00
|
|
|
void gfxPattern::CacheColorStops(const DrawTarget* aDT) {
|
2015-09-25 10:58:23 +03:00
|
|
|
mStops = gfxGradientCache::GetOrCreateGradientStops(aDT, mStopsList, mExtend);
|
2013-11-08 08:50:39 +04:00
|
|
|
}
|
|
|
|
|
2014-09-15 19:24:03 +04:00
|
|
|
void gfxPattern::SetMatrix(const gfxMatrix& aPatternToUserSpace) {
|
|
|
|
mPatternToUserSpace = ToMatrix(aPatternToUserSpace);
|
2014-09-14 13:58:56 +04:00
|
|
|
// Cairo-pattern matrices specify the conversion from DrawTarget to pattern
|
|
|
|
// space. Azure pattern matrices specify the conversion from pattern to
|
|
|
|
// DrawTarget space.
|
2014-09-15 19:24:03 +04:00
|
|
|
mPatternToUserSpace.Invert();
|
2007-01-27 04:26:49 +03:00
|
|
|
}
|
|
|
|
|
2007-03-03 03:18:34 +03:00
|
|
|
gfxMatrix gfxPattern::GetMatrix() const {
|
2014-09-14 13:58:56 +04:00
|
|
|
// invert at the higher precision of gfxMatrix
|
|
|
|
// cause we need to convert at some point anyways
|
2014-09-15 19:24:03 +04:00
|
|
|
gfxMatrix mat = ThebesMatrix(mPatternToUserSpace);
|
2014-09-14 13:58:56 +04:00
|
|
|
mat.Invert();
|
|
|
|
return mat;
|
2013-06-21 22:55:24 +04:00
|
|
|
}
|
|
|
|
|
|
|
|
gfxMatrix gfxPattern::GetInverseMatrix() const {
|
2014-09-15 19:24:03 +04:00
|
|
|
return ThebesMatrix(mPatternToUserSpace);
|
2012-01-05 11:17:51 +04:00
|
|
|
}
|
|
|
|
|
2014-09-29 17:26:15 +04:00
|
|
|
Pattern* gfxPattern::GetPattern(const DrawTarget* aTarget,
|
2017-07-08 19:49:24 +03:00
|
|
|
const Matrix* aOriginalUserToDevice) {
|
2014-09-15 19:24:03 +04:00
|
|
|
Matrix patternToUser = mPatternToUserSpace;
|
|
|
|
|
|
|
|
if (aOriginalUserToDevice &&
|
2018-02-03 00:14:08 +03:00
|
|
|
!aOriginalUserToDevice->FuzzyEquals(aTarget->GetTransform())) {
|
2014-09-15 19:24:03 +04:00
|
|
|
// mPatternToUserSpace maps from pattern space to the original user space,
|
|
|
|
// but aTarget now has a transform to a different user space. In order for
|
|
|
|
// the Pattern* that we return to be usable in aTarget's new user space we
|
|
|
|
// need the Pattern's mMatrix to be the transform from pattern space to
|
|
|
|
// aTarget's -new- user space. That transform is equivalent to the
|
|
|
|
// transform from pattern space to original user space (patternToUser),
|
|
|
|
// multiplied by the transform from original user space to device space,
|
|
|
|
// multiplied by the transform from device space to current user space.
|
|
|
|
|
|
|
|
Matrix deviceToCurrentUser = aTarget->GetTransform();
|
|
|
|
deviceToCurrentUser.Invert();
|
|
|
|
|
|
|
|
patternToUser =
|
|
|
|
patternToUser * *aOriginalUserToDevice * deviceToCurrentUser;
|
|
|
|
}
|
|
|
|
patternToUser.NudgeToIntegers();
|
|
|
|
|
2014-09-14 13:58:56 +04:00
|
|
|
if (!mStops && !mStopsList.IsEmpty()) {
|
|
|
|
mStops = aTarget->CreateGradientStops(mStopsList.Elements(),
|
2015-09-25 10:58:23 +03:00
|
|
|
mStopsList.Length(), mExtend);
|
2012-01-05 11:17:51 +04:00
|
|
|
}
|
|
|
|
|
2014-09-29 17:12:06 +04:00
|
|
|
switch (mGfxPattern.GetPattern()->GetType()) {
|
|
|
|
case PatternType::SURFACE: {
|
|
|
|
SurfacePattern* surfacePattern =
|
|
|
|
static_cast<SurfacePattern*>(mGfxPattern.GetPattern());
|
|
|
|
surfacePattern->mMatrix = patternToUser;
|
2015-09-25 10:58:23 +03:00
|
|
|
surfacePattern->mExtendMode = mExtend;
|
2014-09-14 13:58:56 +04:00
|
|
|
break;
|
2014-09-29 17:12:06 +04:00
|
|
|
}
|
|
|
|
case PatternType::LINEAR_GRADIENT: {
|
|
|
|
LinearGradientPattern* linearGradientPattern =
|
|
|
|
static_cast<LinearGradientPattern*>(mGfxPattern.GetPattern());
|
|
|
|
linearGradientPattern->mMatrix = patternToUser;
|
|
|
|
linearGradientPattern->mStops = mStops;
|
2014-09-14 13:58:56 +04:00
|
|
|
break;
|
2014-09-29 17:12:06 +04:00
|
|
|
}
|
|
|
|
case PatternType::RADIAL_GRADIENT: {
|
|
|
|
RadialGradientPattern* radialGradientPattern =
|
|
|
|
static_cast<RadialGradientPattern*>(mGfxPattern.GetPattern());
|
|
|
|
radialGradientPattern->mMatrix = patternToUser;
|
|
|
|
radialGradientPattern->mStops = mStops;
|
2014-09-14 13:58:56 +04:00
|
|
|
break;
|
2014-09-29 17:12:06 +04:00
|
|
|
}
|
2020-02-21 03:12:47 +03:00
|
|
|
case PatternType::CONIC_GRADIENT: {
|
|
|
|
ConicGradientPattern* conicGradientPattern =
|
|
|
|
static_cast<ConicGradientPattern*>(mGfxPattern.GetPattern());
|
|
|
|
conicGradientPattern->mMatrix = patternToUser;
|
|
|
|
conicGradientPattern->mStops = mStops;
|
|
|
|
break;
|
|
|
|
}
|
2012-02-04 16:22:47 +04:00
|
|
|
default:
|
|
|
|
/* Reassure the compiler we are handling all the enum values. */
|
|
|
|
break;
|
2012-01-05 11:17:51 +04:00
|
|
|
}
|
|
|
|
|
2014-09-29 17:12:06 +04:00
|
|
|
return mGfxPattern.GetPattern();
|
2007-01-27 04:26:49 +03:00
|
|
|
}
|
|
|
|
|
2015-09-25 10:58:23 +03:00
|
|
|
void gfxPattern::SetExtend(ExtendMode aExtend) {
|
|
|
|
mExtend = aExtend;
|
2014-09-14 13:58:56 +04:00
|
|
|
mStops = nullptr;
|
2012-01-05 11:17:51 +04:00
|
|
|
}
|
|
|
|
|
|
|
|
bool gfxPattern::IsOpaque() {
|
2014-09-29 17:12:06 +04:00
|
|
|
if (mGfxPattern.GetPattern()->GetType() != PatternType::SURFACE) {
|
2014-09-14 13:58:55 +04:00
|
|
|
return false;
|
2012-01-05 11:17:51 +04:00
|
|
|
}
|
|
|
|
|
2014-09-29 17:12:06 +04:00
|
|
|
if (static_cast<SurfacePattern*>(mGfxPattern.GetPattern())
|
|
|
|
->mSurface->GetFormat() == SurfaceFormat::B8G8R8X8) {
|
2012-01-05 11:17:51 +04:00
|
|
|
return true;
|
|
|
|
}
|
|
|
|
return false;
|
2007-01-27 04:26:49 +03:00
|
|
|
}
|
|
|
|
|
2018-08-01 20:02:18 +03:00
|
|
|
void gfxPattern::SetSamplingFilter(mozilla::gfx::SamplingFilter filter) {
|
2014-09-29 17:12:06 +04:00
|
|
|
if (mGfxPattern.GetPattern()->GetType() != PatternType::SURFACE) {
|
2014-09-14 13:58:56 +04:00
|
|
|
return;
|
2012-01-05 11:17:51 +04:00
|
|
|
}
|
2014-09-14 13:58:56 +04:00
|
|
|
|
2016-05-25 19:01:18 +03:00
|
|
|
static_cast<SurfacePattern*>(mGfxPattern.GetPattern())->mSamplingFilter =
|
|
|
|
filter;
|
2007-01-27 04:26:49 +03:00
|
|
|
}
|
|
|
|
|
2016-05-25 19:01:18 +03:00
|
|
|
SamplingFilter gfxPattern::SamplingFilter() const {
|
2014-09-29 17:12:06 +04:00
|
|
|
if (mGfxPattern.GetPattern()->GetType() != PatternType::SURFACE) {
|
2018-08-01 20:02:18 +03:00
|
|
|
return mozilla::gfx::SamplingFilter::GOOD;
|
2012-01-05 11:17:51 +04:00
|
|
|
}
|
2016-05-25 19:01:18 +03:00
|
|
|
return static_cast<const SurfacePattern*>(mGfxPattern.GetPattern())
|
|
|
|
->mSamplingFilter;
|
2007-01-27 04:26:49 +03:00
|
|
|
}
|
|
|
|
|
2020-03-09 17:16:17 +03:00
|
|
|
bool gfxPattern::GetSolidColor(DeviceColor& aColorOut) {
|
2014-09-29 17:12:06 +04:00
|
|
|
if (mGfxPattern.GetPattern()->GetType() == PatternType::COLOR) {
|
2015-09-24 09:36:15 +03:00
|
|
|
aColorOut = static_cast<ColorPattern*>(mGfxPattern.GetPattern())->mColor;
|
2014-09-14 13:58:56 +04:00
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
return false;
|
2007-01-27 04:26:49 +03:00
|
|
|
}
|