зеркало из https://github.com/mozilla/gecko-dev.git
Bug 1616587 - Implement conic-gradient for Skia graphics backend. r=lsalzman
Differential Revision: https://phabricator.services.mozilla.com/D63415 --HG-- extra : moz-landing-system : lando
This commit is contained in:
Родитель
712d386afe
Коммит
edf9be08c3
23
gfx/2d/2D.h
23
gfx/2d/2D.h
|
@ -290,6 +290,29 @@ class RadialGradientPattern : public Pattern {
|
|||
Matrix mMatrix; //!< A matrix that transforms the pattern into user space
|
||||
};
|
||||
|
||||
/**
|
||||
* This class is used for Conic Gradient Patterns, the gradient stops are
|
||||
* stored in a separate object and are backend dependent. This class itself
|
||||
* may be used on the stack.
|
||||
*/
|
||||
class ConicGradientPattern : public Pattern {
|
||||
public:
|
||||
/// For constructor parameter description, see member data documentation.
|
||||
ConicGradientPattern(const Point& aCenter, Float aAngle,
|
||||
GradientStops* aStops, const Matrix& aMatrix = Matrix())
|
||||
: mCenter(aCenter), mAngle(aAngle), mStops(aStops), mMatrix(aMatrix) {}
|
||||
|
||||
PatternType GetType() const override { return PatternType::CONIC_GRADIENT; }
|
||||
|
||||
Point mCenter; //!< Center of the gradient
|
||||
Float mAngle; //!< Start angle of gradient
|
||||
RefPtr<GradientStops>
|
||||
mStops; /**< GradientStops object for this gradient, this
|
||||
should match the backend type of the draw target
|
||||
this pattern will be used with. */
|
||||
Matrix mMatrix; //!< A matrix that transforms the pattern into user space
|
||||
};
|
||||
|
||||
/**
|
||||
* This class is used for Surface Patterns, they wrap a surface and a
|
||||
* repetition mode for the surface. This may be used on the stack.
|
||||
|
|
|
@ -68,6 +68,10 @@ class StoredPattern {
|
|||
new (mRadial) RadialGradientPattern(
|
||||
*static_cast<const RadialGradientPattern*>(&aPattern));
|
||||
return;
|
||||
case PatternType::CONIC_GRADIENT:
|
||||
new (mConic) ConicGradientPattern(
|
||||
*static_cast<const ConicGradientPattern*>(&aPattern));
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -98,6 +102,7 @@ class StoredPattern {
|
|||
char mColor[sizeof(ColorPattern)];
|
||||
char mLinear[sizeof(LinearGradientPattern)];
|
||||
char mRadial[sizeof(RadialGradientPattern)];
|
||||
char mConic[sizeof(ConicGradientPattern)];
|
||||
char mSurface[sizeof(SurfacePattern)];
|
||||
};
|
||||
};
|
||||
|
|
|
@ -184,6 +184,11 @@ static bool PatternIsCompatible(const Pattern& aPattern) {
|
|||
static_cast<const RadialGradientPattern&>(aPattern);
|
||||
return pattern.mStops->GetBackendType() == BackendType::CAIRO;
|
||||
}
|
||||
case PatternType::CONIC_GRADIENT: {
|
||||
const ConicGradientPattern& pattern =
|
||||
static_cast<const ConicGradientPattern&>(aPattern);
|
||||
return pattern.mStops->GetBackendType() == BackendType::CAIRO;
|
||||
}
|
||||
default:
|
||||
return true;
|
||||
}
|
||||
|
@ -521,6 +526,15 @@ static cairo_pattern_t* GfxPatternToCairoPattern(const Pattern& aPattern,
|
|||
|
||||
break;
|
||||
}
|
||||
case PatternType::CONIC_GRADIENT: {
|
||||
const ConicGradientPattern& pattern =
|
||||
static_cast<const ConicGradientPattern&>(aPattern);
|
||||
|
||||
// XXX(ntim): bug 1617039 - implement conic-gradient for Cairo
|
||||
pat = cairo_pattern_create_rgba(0.0, 0.0, 0.0, 0.0);
|
||||
|
||||
break;
|
||||
}
|
||||
default: {
|
||||
// We should support all pattern types!
|
||||
MOZ_ASSERT(false);
|
||||
|
|
|
@ -633,6 +633,13 @@ void DrawTargetRecording::EnsurePatternDependenciesStored(
|
|||
static_cast<const RadialGradientPattern*>(&aPattern)->mStops));
|
||||
return;
|
||||
}
|
||||
case PatternType::CONIC_GRADIENT: {
|
||||
MOZ_ASSERT_IF(
|
||||
static_cast<const ConicGradientPattern*>(&aPattern)->mStops,
|
||||
mRecorder->HasStoredObject(
|
||||
static_cast<const ConicGradientPattern*>(&aPattern)->mStops));
|
||||
return;
|
||||
}
|
||||
case PatternType::SURFACE: {
|
||||
const SurfacePattern* pat = static_cast<const SurfacePattern*>(&aPattern);
|
||||
EnsureSurfaceStoredRecording(mRecorder, pat->mSurface,
|
||||
|
|
|
@ -494,6 +494,42 @@ static void SetPaintPattern(SkPaint& aPaint, const Pattern& aPattern,
|
|||
}
|
||||
break;
|
||||
}
|
||||
case PatternType::CONIC_GRADIENT: {
|
||||
const ConicGradientPattern& pat =
|
||||
static_cast<const ConicGradientPattern&>(aPattern);
|
||||
GradientStopsSkia* stops =
|
||||
static_cast<GradientStopsSkia*>(pat.mStops.get());
|
||||
if (!stops || stops->mCount < 2 || !pat.mCenter.IsFinite() ||
|
||||
!IsFinite(pat.mAngle)) {
|
||||
aPaint.setColor(SK_ColorTRANSPARENT);
|
||||
} else {
|
||||
SkMatrix mat;
|
||||
GfxMatrixToSkiaMatrix(pat.mMatrix, mat);
|
||||
if (aMatrix) {
|
||||
mat.postConcat(*aMatrix);
|
||||
}
|
||||
|
||||
SkScalar cx = SkFloatToScalar(pat.mCenter.x);
|
||||
SkScalar cy = SkFloatToScalar(pat.mCenter.y);
|
||||
|
||||
// Skia's sweep gradient angles are relative to the x-axis, not the
|
||||
// y-axis.
|
||||
Float angle = (pat.mAngle * 180.0 / M_PI) - 90.0;
|
||||
if (angle != 0.0) {
|
||||
mat.preRotate(angle, cx, cy);
|
||||
}
|
||||
|
||||
sk_sp<SkShader> shader = SkGradientShader::MakeSweep(
|
||||
cx, cy, &stops->mColors.front(), &stops->mPositions.front(),
|
||||
stops->mCount, 0, &mat);
|
||||
if (shader) {
|
||||
aPaint.setShader(shader);
|
||||
} else {
|
||||
aPaint.setColor(SK_ColorTRANSPARENT);
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
case PatternType::SURFACE: {
|
||||
const SurfacePattern& pat = static_cast<const SurfacePattern&>(aPattern);
|
||||
sk_sp<SkImage> image =
|
||||
|
|
|
@ -258,6 +258,14 @@ struct AdjustedPattern final {
|
|||
radGradPat->mMatrix);
|
||||
return mPattern;
|
||||
}
|
||||
case PatternType::CONIC_GRADIENT: {
|
||||
ConicGradientPattern* conGradPat =
|
||||
static_cast<ConicGradientPattern*>(mOrigPattern);
|
||||
mPattern = new (mConGradPat) ConicGradientPattern(
|
||||
conGradPat->mCenter, conGradPat->mAngle,
|
||||
GetGradientStops(conGradPat->mStops), conGradPat->mMatrix);
|
||||
return mPattern;
|
||||
}
|
||||
default:
|
||||
return new (mColPat) ColorPattern(Color());
|
||||
}
|
||||
|
@ -269,6 +277,7 @@ struct AdjustedPattern final {
|
|||
char mColPat[sizeof(ColorPattern)];
|
||||
char mLinGradPat[sizeof(LinearGradientPattern)];
|
||||
char mRadGradPat[sizeof(RadialGradientPattern)];
|
||||
char mConGradPat[sizeof(ConicGradientPattern)];
|
||||
char mSurfPat[sizeof(SurfacePattern)];
|
||||
};
|
||||
|
||||
|
@ -717,6 +726,11 @@ void DrawTargetWrapAndRecord::EnsurePatternDependenciesStored(
|
|||
static_cast<const RadialGradientPattern*>(&aPattern)->mStops));
|
||||
return;
|
||||
}
|
||||
case PatternType::CONIC_GRADIENT: {
|
||||
MOZ_ASSERT(mRecorder->HasStoredObject(
|
||||
static_cast<const ConicGradientPattern*>(&aPattern)->mStops));
|
||||
return;
|
||||
}
|
||||
case PatternType::SURFACE: {
|
||||
const SurfacePattern* pat = static_cast<const SurfacePattern*>(&aPattern);
|
||||
EnsureSurfaceStored(mRecorder, pat->mSurface,
|
||||
|
|
|
@ -52,6 +52,10 @@ class GeneralPattern final {
|
|||
mPattern = new (mRadialGradientPattern.addr()) RadialGradientPattern(
|
||||
static_cast<const RadialGradientPattern&>(aPattern));
|
||||
break;
|
||||
case PatternType::CONIC_GRADIENT:
|
||||
mPattern = new (mConicGradientPattern.addr()) ConicGradientPattern(
|
||||
static_cast<const ConicGradientPattern&>(aPattern));
|
||||
break;
|
||||
case PatternType::SURFACE:
|
||||
mPattern = new (mSurfacePattern.addr())
|
||||
SurfacePattern(static_cast<const SurfacePattern&>(aPattern));
|
||||
|
@ -86,6 +90,15 @@ class GeneralPattern final {
|
|||
return mRadialGradientPattern.addr();
|
||||
}
|
||||
|
||||
ConicGradientPattern* InitConicGradientPattern(
|
||||
const Point& aCenter, Float aAngle, GradientStops* aStops,
|
||||
const Matrix& aMatrix = Matrix()) {
|
||||
MOZ_ASSERT(!mPattern);
|
||||
mPattern = new (mConicGradientPattern.addr())
|
||||
ConicGradientPattern(aCenter, aAngle, aStops, aMatrix);
|
||||
return mConicGradientPattern.addr();
|
||||
}
|
||||
|
||||
SurfacePattern* InitSurfacePattern(
|
||||
SourceSurface* aSourceSurface, ExtendMode aExtendMode,
|
||||
const Matrix& aMatrix = Matrix(),
|
||||
|
@ -113,6 +126,7 @@ class GeneralPattern final {
|
|||
AlignedStorage2<ColorPattern> mColorPattern;
|
||||
AlignedStorage2<LinearGradientPattern> mLinearGradientPattern;
|
||||
AlignedStorage2<RadialGradientPattern> mRadialGradientPattern;
|
||||
AlignedStorage2<ConicGradientPattern> mConicGradientPattern;
|
||||
AlignedStorage2<SurfacePattern> mSurfacePattern;
|
||||
};
|
||||
Pattern* mPattern = nullptr;
|
||||
|
|
|
@ -129,6 +129,13 @@ struct RadialGradientPatternStorage {
|
|||
Matrix mMatrix;
|
||||
};
|
||||
|
||||
struct ConicGradientPatternStorage {
|
||||
Point mCenter;
|
||||
Float mAngle;
|
||||
ReferencePtr mStops;
|
||||
Matrix mMatrix;
|
||||
};
|
||||
|
||||
struct SurfacePatternStorage {
|
||||
ExtendMode mExtend;
|
||||
SamplingFilter mSamplingFilter;
|
||||
|
@ -144,6 +151,7 @@ struct PatternStorage {
|
|||
char mColor[sizeof(ColorPatternStorage)];
|
||||
char mLinear[sizeof(LinearGradientPatternStorage)];
|
||||
char mRadial[sizeof(RadialGradientPatternStorage)];
|
||||
char mConic[sizeof(ConicGradientPatternStorage)];
|
||||
char mSurface[sizeof(SurfacePatternStorage)];
|
||||
};
|
||||
};
|
||||
|
|
|
@ -1564,6 +1564,12 @@ void RecordedEvent::RecordPatternData(S& aStream,
|
|||
&aPattern.mStorage));
|
||||
return;
|
||||
}
|
||||
case PatternType::CONIC_GRADIENT: {
|
||||
WriteElement(aStream,
|
||||
*reinterpret_cast<const ConicGradientPatternStorage*>(
|
||||
&aPattern.mStorage));
|
||||
return;
|
||||
}
|
||||
case PatternType::SURFACE: {
|
||||
WriteElement(aStream, *reinterpret_cast<const SurfacePatternStorage*>(
|
||||
&aPattern.mStorage));
|
||||
|
@ -1596,6 +1602,11 @@ void RecordedEvent::ReadPatternData(S& aStream,
|
|||
&aPattern.mStorage));
|
||||
return;
|
||||
}
|
||||
case PatternType::CONIC_GRADIENT: {
|
||||
ReadElement(aStream, *reinterpret_cast<ConicGradientPatternStorage*>(
|
||||
&aPattern.mStorage));
|
||||
return;
|
||||
}
|
||||
case PatternType::SURFACE: {
|
||||
SurfacePatternStorage* sps =
|
||||
reinterpret_cast<SurfacePatternStorage*>(&aPattern.mStorage);
|
||||
|
@ -1661,6 +1672,18 @@ inline void RecordedEvent::StorePattern(PatternStorage& aDestination,
|
|||
store->mStops = pat->mStops.get();
|
||||
return;
|
||||
}
|
||||
case PatternType::CONIC_GRADIENT: {
|
||||
ConicGradientPatternStorage* store =
|
||||
reinterpret_cast<ConicGradientPatternStorage*>(
|
||||
&aDestination.mStorage);
|
||||
const ConicGradientPattern* pat =
|
||||
static_cast<const ConicGradientPattern*>(&aSource);
|
||||
store->mCenter = pat->mCenter;
|
||||
store->mAngle = pat->mAngle;
|
||||
store->mMatrix = pat->mMatrix;
|
||||
store->mStops = pat->mStops.get();
|
||||
return;
|
||||
}
|
||||
case PatternType::SURFACE: {
|
||||
SurfacePatternStorage* store =
|
||||
reinterpret_cast<SurfacePatternStorage*>(&aDestination.mStorage);
|
||||
|
@ -1804,6 +1827,14 @@ inline void RecordedEvent::OutputSimplePatternInfo(
|
|||
<< store->mCenter2.y << ") Radius 2: " << store->mRadius2;
|
||||
return;
|
||||
}
|
||||
case PatternType::CONIC_GRADIENT: {
|
||||
const ConicGradientPatternStorage* store =
|
||||
reinterpret_cast<const ConicGradientPatternStorage*>(
|
||||
&aStorage.mStorage);
|
||||
aOutput << "ConicGradient (Center: (" << store->mCenter.x << ", "
|
||||
<< store->mCenter.y << ") Angle: " << store->mAngle;
|
||||
return;
|
||||
}
|
||||
case PatternType::SURFACE: {
|
||||
const SurfacePatternStorage* store =
|
||||
reinterpret_cast<const SurfacePatternStorage*>(&aStorage.mStorage);
|
||||
|
@ -2139,6 +2170,16 @@ struct GenericPattern {
|
|||
storage->mMatrix);
|
||||
return mPattern;
|
||||
}
|
||||
case PatternType::CONIC_GRADIENT: {
|
||||
ConicGradientPatternStorage* storage =
|
||||
reinterpret_cast<ConicGradientPatternStorage*>(&mStorage->mStorage);
|
||||
mPattern = new (mConGradPat) ConicGradientPattern(
|
||||
storage->mCenter, storage->mAngle,
|
||||
storage->mStops ? mTranslator->LookupGradientStops(storage->mStops)
|
||||
: nullptr,
|
||||
storage->mMatrix);
|
||||
return mPattern;
|
||||
}
|
||||
default:
|
||||
return new (mColPat) ColorPattern(Color());
|
||||
}
|
||||
|
@ -2150,6 +2191,7 @@ struct GenericPattern {
|
|||
char mColPat[sizeof(ColorPattern)];
|
||||
char mLinGradPat[sizeof(LinearGradientPattern)];
|
||||
char mRadGradPat[sizeof(RadialGradientPattern)];
|
||||
char mConGradPat[sizeof(ConicGradientPattern)];
|
||||
char mSurfPat[sizeof(SurfacePattern)];
|
||||
};
|
||||
|
||||
|
|
|
@ -414,7 +414,8 @@ enum class PatternType : int8_t {
|
|||
COLOR,
|
||||
SURFACE,
|
||||
LINEAR_GRADIENT,
|
||||
RADIAL_GRADIENT
|
||||
RADIAL_GRADIENT,
|
||||
CONIC_GRADIENT
|
||||
};
|
||||
|
||||
enum class JoinStyle : int8_t {
|
||||
|
|
|
@ -37,6 +37,12 @@ gfxPattern::gfxPattern(gfxFloat cx0, gfxFloat cy0, gfxFloat radius0,
|
|||
radius0, radius1, nullptr);
|
||||
}
|
||||
|
||||
// conic
|
||||
gfxPattern::gfxPattern(gfxFloat cx, gfxFloat cy, gfxFloat angle)
|
||||
: mExtend(ExtendMode::CLAMP) {
|
||||
mGfxPattern.InitConicGradientPattern(Point(cx, cy), angle, nullptr);
|
||||
}
|
||||
|
||||
// Azure
|
||||
gfxPattern::gfxPattern(SourceSurface* aSurface,
|
||||
const Matrix& aPatternToUserSpace)
|
||||
|
@ -48,7 +54,8 @@ gfxPattern::gfxPattern(SourceSurface* aSurface,
|
|||
|
||||
void gfxPattern::AddColorStop(gfxFloat offset, const Color& c) {
|
||||
if (mGfxPattern.GetPattern()->GetType() != PatternType::LINEAR_GRADIENT &&
|
||||
mGfxPattern.GetPattern()->GetType() != PatternType::RADIAL_GRADIENT) {
|
||||
mGfxPattern.GetPattern()->GetType() != PatternType::RADIAL_GRADIENT &&
|
||||
mGfxPattern.GetPattern()->GetType() != PatternType::CONIC_GRADIENT) {
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -136,6 +143,13 @@ Pattern* gfxPattern::GetPattern(const DrawTarget* aTarget,
|
|||
radialGradientPattern->mStops = mStops;
|
||||
break;
|
||||
}
|
||||
case PatternType::CONIC_GRADIENT: {
|
||||
ConicGradientPattern* conicGradientPattern =
|
||||
static_cast<ConicGradientPattern*>(mGfxPattern.GetPattern());
|
||||
conicGradientPattern->mMatrix = patternToUser;
|
||||
conicGradientPattern->mStops = mStops;
|
||||
break;
|
||||
}
|
||||
default:
|
||||
/* Reassure the compiler we are handling all the enum values. */
|
||||
break;
|
||||
|
|
|
@ -22,10 +22,11 @@ class gfxPattern final {
|
|||
|
||||
public:
|
||||
explicit gfxPattern(const mozilla::gfx::Color& aColor);
|
||||
// linear
|
||||
// gradients
|
||||
gfxPattern(gfxFloat x0, gfxFloat y0, gfxFloat x1, gfxFloat y1); // linear
|
||||
gfxPattern(gfxFloat cx0, gfxFloat cy0, gfxFloat radius0, gfxFloat cx1,
|
||||
gfxFloat cy1, gfxFloat radius1); // radial
|
||||
gfxFloat cy1, gfxFloat radius1); // radial
|
||||
gfxPattern(gfxFloat cx, gfxFloat cy, gfxFloat angle); // conic
|
||||
gfxPattern(mozilla::gfx::SourceSurface* aSurface,
|
||||
const mozilla::gfx::Matrix& aPatternToUserSpace);
|
||||
|
||||
|
|
|
@ -951,8 +951,7 @@ void nsCSSGradientRenderer::Paint(gfxContext& aContext, const nsRect& aDest,
|
|||
matrix.PreTranslate(-mLineStart);
|
||||
}
|
||||
} else {
|
||||
// conic-gradient is only implemented for WebRender
|
||||
return;
|
||||
gradientPattern = new gfxPattern(mCenter.x, mCenter.y, mAngle);
|
||||
}
|
||||
// Use a pattern transform to take account of source and dest rects
|
||||
matrix.PreTranslate(gfxPoint(mPresContext->CSSPixelsToDevPixels(aSrc.x),
|
||||
|
@ -962,7 +961,7 @@ void nsCSSGradientRenderer::Paint(gfxContext& aContext, const nsRect& aDest,
|
|||
gfxFloat(nsPresContext::CSSPixelsToAppUnits(aSrc.height)) / aDest.height);
|
||||
gradientPattern->SetMatrix(matrix);
|
||||
|
||||
if (stopDelta == 0.0) {
|
||||
if (!mGradient->IsConic() && stopDelta == 0.0) {
|
||||
// Non-repeating gradient with all stops in same place -> just add
|
||||
// first stop and last stop, both at position 0.
|
||||
// Repeating gradient with all stops in the same place, or radial
|
||||
|
|
Загрузка…
Ссылка в новой задаче