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;
|
|
|
|
|
2015-09-25 03:50:46 +03:00
|
|
|
gfxPattern::gfxPattern(const Color& aColor)
|
2015-09-25 10:58:23 +03:00
|
|
|
: mExtend(ExtendMode::CLAMP)
|
2007-01-27 04:26:49 +03:00
|
|
|
{
|
2014-10-17 15:53:16 +04:00
|
|
|
mGfxPattern.InitColorPattern(ToDeviceColor(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)
|
2007-01-27 04:26:49 +03:00
|
|
|
{
|
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)
|
2007-01-27 04:26:49 +03:00
|
|
|
{
|
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
|
|
|
}
|
|
|
|
|
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)
|
2015-09-25 10:58:23 +03:00
|
|
|
, mExtend(ExtendMode::CLAMP)
|
2012-01-05 11:17:51 +04:00
|
|
|
{
|
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
|
|
|
}
|
|
|
|
|
|
|
|
void
|
2015-09-25 03:50:46 +03:00
|
|
|
gfxPattern::AddColorStop(gfxFloat offset, const Color& c)
|
2007-01-27 04:26:49 +03:00
|
|
|
{
|
2014-09-29 17:12:06 +04:00
|
|
|
if (mGfxPattern.GetPattern()->GetType() != PatternType::LINEAR_GRADIENT &&
|
|
|
|
mGfxPattern.GetPattern()->GetType() != PatternType::RADIAL_GRADIENT) {
|
2014-09-14 13:58:56 +04:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
mStops = nullptr;
|
|
|
|
|
|
|
|
GradientStop stop;
|
|
|
|
stop.offset = offset;
|
2014-10-17 15:53:15 +04:00
|
|
|
stop.color = ToDeviceColor(c);
|
2014-09-14 13:58:56 +04:00
|
|
|
mStopsList.AppendElement(stop);
|
2007-01-27 04:26:49 +03:00
|
|
|
}
|
|
|
|
|
2013-02-15 22:54:49 +04:00
|
|
|
void
|
2014-06-12 23:24:05 +04:00
|
|
|
gfxPattern::SetColorStops(GradientStops* aStops)
|
2013-02-15 22:54:49 +04:00
|
|
|
{
|
|
|
|
mStops = aStops;
|
|
|
|
}
|
|
|
|
|
2013-11-08 08:50:39 +04:00
|
|
|
void
|
2014-09-29 17:15:19 +04:00
|
|
|
gfxPattern::CacheColorStops(const DrawTarget *aDT)
|
2013-11-08 08:50:39 +04:00
|
|
|
{
|
2015-09-25 10:58:23 +03:00
|
|
|
mStops = gfxGradientCache::GetOrCreateGradientStops(aDT, mStopsList, mExtend);
|
2013-11-08 08:50:39 +04:00
|
|
|
}
|
|
|
|
|
2007-01-27 04:26:49 +03:00
|
|
|
void
|
2014-09-15 19:24:03 +04:00
|
|
|
gfxPattern::SetMatrix(const gfxMatrix& aPatternToUserSpace)
|
2007-01-27 04:26:49 +03:00
|
|
|
{
|
2014-09-15 19:24:03 +04:00
|
|
|
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
|
|
|
}
|
|
|
|
|
|
|
|
gfxMatrix
|
2007-03-03 03:18:34 +03:00
|
|
|
gfxPattern::GetMatrix() const
|
2007-01-27 04:26:49 +03:00
|
|
|
{
|
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
|
|
|
}
|
|
|
|
|
|
|
|
Pattern*
|
2014-09-29 17:26:15 +04:00
|
|
|
gfxPattern::GetPattern(const DrawTarget *aTarget,
|
2014-09-15 19:24:03 +04:00
|
|
|
Matrix *aOriginalUserToDevice)
|
|
|
|
{
|
|
|
|
Matrix patternToUser = mPatternToUserSpace;
|
|
|
|
|
|
|
|
if (aOriginalUserToDevice &&
|
|
|
|
*aOriginalUserToDevice != aTarget->GetTransform()) {
|
|
|
|
// 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
|
|
|
}
|
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
|
|
|
}
|
|
|
|
|
|
|
|
void
|
2015-09-25 10:58:23 +03:00
|
|
|
gfxPattern::SetExtend(ExtendMode aExtend)
|
2007-01-27 04:26:49 +03:00
|
|
|
{
|
2015-09-25 10:58:23 +03:00
|
|
|
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
|
|
|
}
|
|
|
|
|
|
|
|
void
|
2016-05-25 19:01:18 +03:00
|
|
|
gfxPattern::SetSamplingFilter(gfx::SamplingFilter filter)
|
2007-01-27 04:26:49 +03:00
|
|
|
{
|
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
|
2007-01-27 04:26:49 +03:00
|
|
|
{
|
2014-09-29 17:12:06 +04:00
|
|
|
if (mGfxPattern.GetPattern()->GetType() != PatternType::SURFACE) {
|
2016-05-25 19:01:18 +03:00
|
|
|
return 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
|
|
|
}
|
|
|
|
|
2011-09-29 10:19:26 +04:00
|
|
|
bool
|
2015-09-24 09:36:15 +03:00
|
|
|
gfxPattern::GetSolidColor(Color& aColorOut)
|
2007-01-27 04:26:49 +03:00
|
|
|
{
|
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
|
|
|
}
|