add asAShadowBlur for android to drawlooper
BUG=skia: R=djsollen@google.com, scroggo@google.com Review URL: https://codereview.chromium.org/253633003 git-svn-id: http://skia.googlecode.com/svn/trunk@14431 2bbb7eff-a529-9590-31e7-b0007b416f81
This commit is contained in:
parent
ccb25c94c9
commit
daaafa6e81
@ -10,7 +10,10 @@
|
|||||||
#ifndef SkDrawLooper_DEFINED
|
#ifndef SkDrawLooper_DEFINED
|
||||||
#define SkDrawLooper_DEFINED
|
#define SkDrawLooper_DEFINED
|
||||||
|
|
||||||
|
#include "SkBlurTypes.h"
|
||||||
#include "SkFlattenable.h"
|
#include "SkFlattenable.h"
|
||||||
|
#include "SkPoint.h"
|
||||||
|
#include "SkColor.h"
|
||||||
|
|
||||||
class SkCanvas;
|
class SkCanvas;
|
||||||
class SkPaint;
|
class SkPaint;
|
||||||
@ -88,6 +91,24 @@ public:
|
|||||||
virtual void computeFastBounds(const SkPaint& paint,
|
virtual void computeFastBounds(const SkPaint& paint,
|
||||||
const SkRect& src, SkRect* dst) const;
|
const SkRect& src, SkRect* dst) const;
|
||||||
|
|
||||||
|
struct BlurShadowRec {
|
||||||
|
SkScalar fSigma;
|
||||||
|
SkVector fOffset;
|
||||||
|
SkColor fColor;
|
||||||
|
SkBlurStyle fStyle;
|
||||||
|
SkBlurQuality fQuality;
|
||||||
|
};
|
||||||
|
/**
|
||||||
|
* If this looper can be interpreted as having two layers, such that
|
||||||
|
* 1. The first layer (bottom most) just has a blur and translate
|
||||||
|
* 2. The second layer has no modifications to either paint or canvas
|
||||||
|
* 3. No other layers.
|
||||||
|
* then return true, and if not null, fill out the BlurShadowRec).
|
||||||
|
*
|
||||||
|
* If any of the above are not met, return false and ignore the BlurShadowRec parameter.
|
||||||
|
*/
|
||||||
|
virtual bool asABlurShadow(BlurShadowRec*) const;
|
||||||
|
|
||||||
SK_TO_STRING_PUREVIRT()
|
SK_TO_STRING_PUREVIRT()
|
||||||
SK_DEFINE_FLATTENABLE_TYPE(SkDrawLooper)
|
SK_DEFINE_FLATTENABLE_TYPE(SkDrawLooper)
|
||||||
|
|
||||||
|
@ -10,6 +10,7 @@
|
|||||||
#ifndef SkMaskFilter_DEFINED
|
#ifndef SkMaskFilter_DEFINED
|
||||||
#define SkMaskFilter_DEFINED
|
#define SkMaskFilter_DEFINED
|
||||||
|
|
||||||
|
#include "SkBlurTypes.h"
|
||||||
#include "SkFlattenable.h"
|
#include "SkFlattenable.h"
|
||||||
#include "SkMask.h"
|
#include "SkMask.h"
|
||||||
#include "SkPaint.h"
|
#include "SkPaint.h"
|
||||||
@ -138,6 +139,18 @@ public:
|
|||||||
*/
|
*/
|
||||||
virtual void computeFastBounds(const SkRect& src, SkRect* dest) const;
|
virtual void computeFastBounds(const SkRect& src, SkRect* dest) const;
|
||||||
|
|
||||||
|
struct BlurRec {
|
||||||
|
SkScalar fSigma;
|
||||||
|
SkBlurStyle fStyle;
|
||||||
|
SkBlurQuality fQuality;
|
||||||
|
};
|
||||||
|
/**
|
||||||
|
* If this filter can be represented by a BlurRec, return true and (if not null) fill in the
|
||||||
|
* provided BlurRec parameter. If this effect cannot be represented as a BlurRec, return false
|
||||||
|
* and ignore the BlurRec parameter.
|
||||||
|
*/
|
||||||
|
virtual bool asABlur(BlurRec*) const;
|
||||||
|
|
||||||
SK_TO_STRING_PUREVIRT()
|
SK_TO_STRING_PUREVIRT()
|
||||||
SK_DEFINE_FLATTENABLE_TYPE(SkMaskFilter)
|
SK_DEFINE_FLATTENABLE_TYPE(SkMaskFilter)
|
||||||
|
|
||||||
|
@ -61,10 +61,12 @@ protected:
|
|||||||
SkBlurDrawLooper(SkReadBuffer&);
|
SkBlurDrawLooper(SkReadBuffer&);
|
||||||
virtual void flatten(SkWriteBuffer&) const SK_OVERRIDE;
|
virtual void flatten(SkWriteBuffer&) const SK_OVERRIDE;
|
||||||
|
|
||||||
|
virtual bool asABlurShadow(BlurShadowRec*) const SK_OVERRIDE;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
SkMaskFilter* fBlur;
|
SkMaskFilter* fBlur;
|
||||||
SkColorFilter* fColorFilter;
|
SkColorFilter* fColorFilter;
|
||||||
SkScalar fDx, fDy;
|
SkScalar fDx, fDy, fSigma;
|
||||||
SkColor fBlurColor;
|
SkColor fBlurColor;
|
||||||
uint32_t fBlurFlags;
|
uint32_t fBlurFlags;
|
||||||
|
|
||||||
@ -86,6 +88,7 @@ private:
|
|||||||
};
|
};
|
||||||
|
|
||||||
void init(SkScalar sigma, SkScalar dx, SkScalar dy, SkColor color, uint32_t flags);
|
void init(SkScalar sigma, SkScalar dx, SkScalar dy, SkColor color, uint32_t flags);
|
||||||
|
void initEffects();
|
||||||
|
|
||||||
typedef SkDrawLooper INHERITED;
|
typedef SkDrawLooper INHERITED;
|
||||||
};
|
};
|
||||||
|
@ -23,9 +23,7 @@ public:
|
|||||||
uint8_t fSpecular; // exponent, 4.4 right now
|
uint8_t fSpecular; // exponent, 4.4 right now
|
||||||
};
|
};
|
||||||
|
|
||||||
static SkEmbossMaskFilter* Create(SkScalar blurSigma, const Light& light) {
|
static SkEmbossMaskFilter* Create(SkScalar blurSigma, const Light& light);
|
||||||
return SkNEW_ARGS(SkEmbossMaskFilter, (blurSigma, light));
|
|
||||||
}
|
|
||||||
|
|
||||||
// overrides from SkMaskFilter
|
// overrides from SkMaskFilter
|
||||||
// This method is not exported to java.
|
// This method is not exported to java.
|
||||||
|
@ -77,6 +77,8 @@ public:
|
|||||||
|
|
||||||
virtual size_t contextSize() const SK_OVERRIDE { return sizeof(LayerDrawLooperContext); }
|
virtual size_t contextSize() const SK_OVERRIDE { return sizeof(LayerDrawLooperContext); }
|
||||||
|
|
||||||
|
virtual bool asABlurShadow(BlurShadowRec* rec) const SK_OVERRIDE;
|
||||||
|
|
||||||
SK_TO_STRING_OVERRIDE()
|
SK_TO_STRING_OVERRIDE()
|
||||||
|
|
||||||
/// Implements Flattenable.
|
/// Implements Flattenable.
|
||||||
|
@ -59,3 +59,7 @@ void SkDrawLooper::computeFastBounds(const SkPaint& paint, const SkRect& src,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool SkDrawLooper::asABlurShadow(BlurShadowRec*) const {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
@ -26,6 +26,10 @@ bool SkMaskFilter::filterMask(SkMask*, const SkMask&, const SkMatrix&,
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool SkMaskFilter::asABlur(BlurRec*) const {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
static void extractMaskSubset(const SkMask& src, SkMask* dst) {
|
static void extractMaskSubset(const SkMask& src, SkMask* dst) {
|
||||||
SkASSERT(src.fBounds.contains(dst->fBounds));
|
SkASSERT(src.fBounds.contains(dst->fBounds));
|
||||||
|
|
||||||
|
@ -1,10 +1,10 @@
|
|||||||
|
|
||||||
/*
|
/*
|
||||||
* Copyright 2011 Google Inc.
|
* Copyright 2011 Google Inc.
|
||||||
*
|
*
|
||||||
* Use of this source code is governed by a BSD-style license that can be
|
* Use of this source code is governed by a BSD-style license that can be
|
||||||
* found in the LICENSE file.
|
* found in the LICENSE file.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include "SkBlurDrawLooper.h"
|
#include "SkBlurDrawLooper.h"
|
||||||
#include "SkBlurMask.h" // just for SkBlurMask::ConvertRadiusToSigma
|
#include "SkBlurMask.h" // just for SkBlurMask::ConvertRadiusToSigma
|
||||||
#include "SkBlurMaskFilter.h"
|
#include "SkBlurMaskFilter.h"
|
||||||
@ -29,32 +29,27 @@ SkBlurDrawLooper::SkBlurDrawLooper(SkColor color, SkScalar sigma,
|
|||||||
this->init(sigma, dx, dy, color, flags);
|
this->init(sigma, dx, dy, color, flags);
|
||||||
}
|
}
|
||||||
|
|
||||||
void SkBlurDrawLooper::init(SkScalar sigma, SkScalar dx, SkScalar dy,
|
// only call from constructor
|
||||||
SkColor color, uint32_t flags) {
|
void SkBlurDrawLooper::initEffects() {
|
||||||
fDx = dx;
|
SkASSERT(fBlurFlags <= kAll_BlurFlag);
|
||||||
fDy = dy;
|
if (fSigma > 0) {
|
||||||
fBlurColor = color;
|
uint32_t flags = fBlurFlags & kIgnoreTransform_BlurFlag ?
|
||||||
fBlurFlags = flags;
|
|
||||||
|
|
||||||
SkASSERT(flags <= kAll_BlurFlag);
|
|
||||||
if (sigma > 0) {
|
|
||||||
uint32_t blurFlags = flags & kIgnoreTransform_BlurFlag ?
|
|
||||||
SkBlurMaskFilter::kIgnoreTransform_BlurFlag :
|
SkBlurMaskFilter::kIgnoreTransform_BlurFlag :
|
||||||
SkBlurMaskFilter::kNone_BlurFlag;
|
SkBlurMaskFilter::kNone_BlurFlag;
|
||||||
|
|
||||||
blurFlags |= flags & kHighQuality_BlurFlag ?
|
flags |= fBlurFlags & kHighQuality_BlurFlag ?
|
||||||
SkBlurMaskFilter::kHighQuality_BlurFlag :
|
SkBlurMaskFilter::kHighQuality_BlurFlag :
|
||||||
SkBlurMaskFilter::kNone_BlurFlag;
|
SkBlurMaskFilter::kNone_BlurFlag;
|
||||||
|
|
||||||
fBlur = SkBlurMaskFilter::Create(kNormal_SkBlurStyle, sigma, blurFlags);
|
fBlur = SkBlurMaskFilter::Create(kNormal_SkBlurStyle, fSigma, flags);
|
||||||
} else {
|
} else {
|
||||||
fBlur = NULL;
|
fBlur = NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (flags & kOverrideColor_BlurFlag) {
|
if (fBlurFlags & kOverrideColor_BlurFlag) {
|
||||||
// Set alpha to 1 for the override since transparency will already
|
// Set alpha to 1 for the override since transparency will already
|
||||||
// be baked into the blurred mask.
|
// be baked into the blurred mask.
|
||||||
SkColor opaqueColor = SkColorSetA(color, 255);
|
SkColor opaqueColor = SkColorSetA(fBlurColor, 255);
|
||||||
//The SrcIn xfer mode will multiply 'color' by the incoming alpha
|
//The SrcIn xfer mode will multiply 'color' by the incoming alpha
|
||||||
fColorFilter = SkColorFilter::CreateModeFilter(opaqueColor,
|
fColorFilter = SkColorFilter::CreateModeFilter(opaqueColor,
|
||||||
SkXfermode::kSrcIn_Mode);
|
SkXfermode::kSrcIn_Mode);
|
||||||
@ -63,15 +58,35 @@ void SkBlurDrawLooper::init(SkScalar sigma, SkScalar dx, SkScalar dy,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
SkBlurDrawLooper::SkBlurDrawLooper(SkReadBuffer& buffer)
|
void SkBlurDrawLooper::init(SkScalar sigma, SkScalar dx, SkScalar dy,
|
||||||
: INHERITED(buffer) {
|
SkColor color, uint32_t flags) {
|
||||||
|
fSigma = sigma;
|
||||||
|
fDx = dx;
|
||||||
|
fDy = dy;
|
||||||
|
fBlurColor = color;
|
||||||
|
fBlurFlags = flags;
|
||||||
|
|
||||||
|
this->initEffects();
|
||||||
|
}
|
||||||
|
|
||||||
|
SkBlurDrawLooper::SkBlurDrawLooper(SkReadBuffer& buffer) : INHERITED(buffer) {
|
||||||
|
|
||||||
|
fSigma = buffer.readScalar();
|
||||||
fDx = buffer.readScalar();
|
fDx = buffer.readScalar();
|
||||||
fDy = buffer.readScalar();
|
fDy = buffer.readScalar();
|
||||||
fBlurColor = buffer.readColor();
|
fBlurColor = buffer.readColor();
|
||||||
fBlur = buffer.readMaskFilter();
|
|
||||||
fColorFilter = buffer.readColorFilter();
|
|
||||||
fBlurFlags = buffer.readUInt() & kAll_BlurFlag;
|
fBlurFlags = buffer.readUInt() & kAll_BlurFlag;
|
||||||
|
|
||||||
|
this->initEffects();
|
||||||
|
}
|
||||||
|
|
||||||
|
void SkBlurDrawLooper::flatten(SkWriteBuffer& buffer) const {
|
||||||
|
this->INHERITED::flatten(buffer);
|
||||||
|
buffer.writeScalar(fSigma);
|
||||||
|
buffer.writeScalar(fDx);
|
||||||
|
buffer.writeScalar(fDy);
|
||||||
|
buffer.writeColor(fBlurColor);
|
||||||
|
buffer.write32(fBlurFlags);
|
||||||
}
|
}
|
||||||
|
|
||||||
SkBlurDrawLooper::~SkBlurDrawLooper() {
|
SkBlurDrawLooper::~SkBlurDrawLooper() {
|
||||||
@ -79,16 +94,24 @@ SkBlurDrawLooper::~SkBlurDrawLooper() {
|
|||||||
SkSafeUnref(fColorFilter);
|
SkSafeUnref(fColorFilter);
|
||||||
}
|
}
|
||||||
|
|
||||||
void SkBlurDrawLooper::flatten(SkWriteBuffer& buffer) const {
|
bool SkBlurDrawLooper::asABlurShadow(BlurShadowRec* rec) const {
|
||||||
this->INHERITED::flatten(buffer);
|
if (fSigma <= 0 || (fBlurFlags & fBlurFlags & kIgnoreTransform_BlurFlag)) {
|
||||||
buffer.writeScalar(fDx);
|
return false;
|
||||||
buffer.writeScalar(fDy);
|
}
|
||||||
buffer.writeColor(fBlurColor);
|
|
||||||
buffer.writeFlattenable(fBlur);
|
if (rec) {
|
||||||
buffer.writeFlattenable(fColorFilter);
|
rec->fSigma = fSigma;
|
||||||
buffer.writeUInt(fBlurFlags);
|
rec->fColor = fBlurColor;
|
||||||
|
rec->fOffset.set(fDx, fDy);
|
||||||
|
rec->fStyle = kNormal_SkBlurStyle;
|
||||||
|
rec->fQuality = (fBlurFlags & kHighQuality_BlurFlag) ?
|
||||||
|
kHigh_SkBlurQuality : kLow_SkBlurQuality;
|
||||||
|
}
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
SkDrawLooper::Context* SkBlurDrawLooper::createContext(SkCanvas*, void* storage) const {
|
SkDrawLooper::Context* SkBlurDrawLooper::createContext(SkCanvas*, void* storage) const {
|
||||||
return SkNEW_PLACEMENT_ARGS(storage, BlurDrawLooperContext, (this));
|
return SkNEW_PLACEMENT_ARGS(storage, BlurDrawLooperContext, (this));
|
||||||
}
|
}
|
||||||
|
@ -13,17 +13,21 @@
|
|||||||
#include "SkEndian.h"
|
#include "SkEndian.h"
|
||||||
|
|
||||||
|
|
||||||
SkScalar SkBlurMask::ConvertRadiusToSigma(SkScalar radius) {
|
// This constant approximates the scaling done in the software path's
|
||||||
// This constant approximates the scaling done in the software path's
|
// "high quality" mode, in SkBlurMask::Blur() (1 / sqrt(3)).
|
||||||
// "high quality" mode, in SkBlurMask::Blur() (1 / sqrt(3)).
|
// IMHO, it actually should be 1: we blur "less" than we should do
|
||||||
// IMHO, it actually should be 1: we blur "less" than we should do
|
// according to the CSS and canvas specs, simply because Safari does the same.
|
||||||
// according to the CSS and canvas specs, simply because Safari does the same.
|
// Firefox used to do the same too, until 4.0 where they fixed it. So at some
|
||||||
// Firefox used to do the same too, until 4.0 where they fixed it. So at some
|
// point we should probably get rid of these scaling constants and rebaseline
|
||||||
// point we should probably get rid of these scaling constants and rebaseline
|
// all the blur tests.
|
||||||
// all the blur tests.
|
static const SkScalar kBLUR_SIGMA_SCALE = 0.57735f;
|
||||||
static const SkScalar kBLUR_SIGMA_SCALE = 0.57735f;
|
|
||||||
|
|
||||||
return radius ? kBLUR_SIGMA_SCALE * radius + 0.5f : 0.0f;
|
SkScalar SkBlurMask::ConvertRadiusToSigma(SkScalar radius) {
|
||||||
|
return radius > 0 ? kBLUR_SIGMA_SCALE * radius + 0.5f : 0.0f;
|
||||||
|
}
|
||||||
|
|
||||||
|
SkScalar SkBlurMask::ConvertSigmaToRadius(SkScalar sigma) {
|
||||||
|
return sigma > 0.5f ? (sigma - 0.5f) / kBLUR_SIGMA_SCALE : 0.0f;
|
||||||
}
|
}
|
||||||
|
|
||||||
#define UNROLL_SEPARABLE_LOOPS
|
#define UNROLL_SEPARABLE_LOOPS
|
||||||
|
@ -39,7 +39,10 @@ public:
|
|||||||
static bool BlurGroundTruth(SkScalar sigma, SkMask* dst, const SkMask& src, SkBlurStyle,
|
static bool BlurGroundTruth(SkScalar sigma, SkMask* dst, const SkMask& src, SkBlurStyle,
|
||||||
SkIPoint* margin = NULL);
|
SkIPoint* margin = NULL);
|
||||||
|
|
||||||
|
// If radius > 0, return the corresponding sigma, else return 0
|
||||||
static SkScalar ConvertRadiusToSigma(SkScalar radius);
|
static SkScalar ConvertRadiusToSigma(SkScalar radius);
|
||||||
|
// If sigma > 0.5, return the corresponding radius, else return 0
|
||||||
|
static SkScalar ConvertSigmaToRadius(SkScalar sigma);
|
||||||
|
|
||||||
/* Helper functions for analytic rectangle blurs */
|
/* Helper functions for analytic rectangle blurs */
|
||||||
|
|
||||||
|
@ -59,6 +59,7 @@ public:
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
virtual void computeFastBounds(const SkRect&, SkRect*) const SK_OVERRIDE;
|
virtual void computeFastBounds(const SkRect&, SkRect*) const SK_OVERRIDE;
|
||||||
|
virtual bool asABlur(BlurRec*) const SK_OVERRIDE;
|
||||||
|
|
||||||
SK_TO_STRING_OVERRIDE()
|
SK_TO_STRING_OVERRIDE()
|
||||||
SK_DECLARE_PUBLIC_FLATTENABLE_DESERIALIZATION_PROCS(SkBlurMaskFilterImpl)
|
SK_DECLARE_PUBLIC_FLATTENABLE_DESERIALIZATION_PROCS(SkBlurMaskFilterImpl)
|
||||||
@ -87,6 +88,11 @@ private:
|
|||||||
SkBlurStyle fBlurStyle;
|
SkBlurStyle fBlurStyle;
|
||||||
uint32_t fBlurFlags;
|
uint32_t fBlurFlags;
|
||||||
|
|
||||||
|
SkBlurQuality getQuality() const {
|
||||||
|
return (fBlurFlags & SkBlurMaskFilter::kHighQuality_BlurFlag) ?
|
||||||
|
kHigh_SkBlurQuality : kLow_SkBlurQuality;
|
||||||
|
}
|
||||||
|
|
||||||
SkBlurMaskFilterImpl(SkReadBuffer&);
|
SkBlurMaskFilterImpl(SkReadBuffer&);
|
||||||
virtual void flatten(SkWriteBuffer&) const SK_OVERRIDE;
|
virtual void flatten(SkWriteBuffer&) const SK_OVERRIDE;
|
||||||
|
|
||||||
@ -145,16 +151,24 @@ SkMask::Format SkBlurMaskFilterImpl::getFormat() const {
|
|||||||
return SkMask::kA8_Format;
|
return SkMask::kA8_Format;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool SkBlurMaskFilterImpl::asABlur(BlurRec* rec) const {
|
||||||
|
if (fBlurFlags & SkBlurMaskFilter::kIgnoreTransform_BlurFlag) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (rec) {
|
||||||
|
rec->fSigma = fSigma;
|
||||||
|
rec->fStyle = fBlurStyle;
|
||||||
|
rec->fQuality = this->getQuality();
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
bool SkBlurMaskFilterImpl::filterMask(SkMask* dst, const SkMask& src,
|
bool SkBlurMaskFilterImpl::filterMask(SkMask* dst, const SkMask& src,
|
||||||
const SkMatrix& matrix,
|
const SkMatrix& matrix,
|
||||||
SkIPoint* margin) const{
|
SkIPoint* margin) const{
|
||||||
SkScalar sigma = this->computeXformedSigma(matrix);
|
SkScalar sigma = this->computeXformedSigma(matrix);
|
||||||
|
return SkBlurMask::BoxBlur(dst, src, sigma, fBlurStyle, this->getQuality(), margin);
|
||||||
SkBlurQuality blurQuality =
|
|
||||||
(fBlurFlags & SkBlurMaskFilter::kHighQuality_BlurFlag) ?
|
|
||||||
kHigh_SkBlurQuality : kLow_SkBlurQuality;
|
|
||||||
|
|
||||||
return SkBlurMask::BoxBlur(dst, src, sigma, fBlurStyle, blurQuality, margin);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
bool SkBlurMaskFilterImpl::filterRectMask(SkMask* dst, const SkRect& r,
|
bool SkBlurMaskFilterImpl::filterRectMask(SkMask* dst, const SkRect& r,
|
||||||
|
@ -1,4 +1,3 @@
|
|||||||
|
|
||||||
/*
|
/*
|
||||||
* Copyright 2006 The Android Open Source Project
|
* Copyright 2006 The Android Open Source Project
|
||||||
*
|
*
|
||||||
@ -6,7 +5,6 @@
|
|||||||
* found in the LICENSE file.
|
* found in the LICENSE file.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
|
||||||
#include "SkEmbossMaskFilter.h"
|
#include "SkEmbossMaskFilter.h"
|
||||||
#include "SkBlurMaskFilter.h"
|
#include "SkBlurMaskFilter.h"
|
||||||
#include "SkBlurMask.h"
|
#include "SkBlurMask.h"
|
||||||
@ -15,6 +13,10 @@
|
|||||||
#include "SkWriteBuffer.h"
|
#include "SkWriteBuffer.h"
|
||||||
#include "SkString.h"
|
#include "SkString.h"
|
||||||
|
|
||||||
|
SkEmbossMaskFilter* SkEmbossMaskFilter::Create(SkScalar blurSigma, const Light& light) {
|
||||||
|
return SkNEW_ARGS(SkEmbossMaskFilter, (blurSigma, light));
|
||||||
|
}
|
||||||
|
|
||||||
static inline int pin2byte(int n) {
|
static inline int pin2byte(int n) {
|
||||||
if (n < 0) {
|
if (n < 0) {
|
||||||
n = 0;
|
n = 0;
|
||||||
|
@ -153,6 +153,50 @@ bool SkLayerDrawLooper::LayerDrawLooperContext::next(SkCanvas* canvas,
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool SkLayerDrawLooper::asABlurShadow(BlurShadowRec* bsRec) const {
|
||||||
|
if (fCount != 2) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
const Rec* rec = fRecs;
|
||||||
|
|
||||||
|
// bottom layer needs to be just blur(maskfilter)
|
||||||
|
if ((rec->fInfo.fPaintBits & ~kMaskFilter_Bit)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if (SkXfermode::kSrc_Mode != rec->fInfo.fColorMode) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
const SkMaskFilter* mf = rec->fPaint.getMaskFilter();
|
||||||
|
if (NULL == mf) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
SkMaskFilter::BlurRec maskBlur;
|
||||||
|
if (!mf->asABlur(&maskBlur)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
rec = rec->fNext;
|
||||||
|
// top layer needs to be "plain"
|
||||||
|
if (rec->fInfo.fPaintBits) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if (SkXfermode::kDst_Mode != rec->fInfo.fColorMode) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if (!rec->fInfo.fOffset.equals(0, 0)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (bsRec) {
|
||||||
|
bsRec->fSigma = maskBlur.fSigma;
|
||||||
|
bsRec->fOffset = fRecs->fInfo.fOffset;
|
||||||
|
bsRec->fColor = fRecs->fPaint.getColor();
|
||||||
|
bsRec->fStyle = maskBlur.fStyle;
|
||||||
|
bsRec->fQuality = maskBlur.fQuality;
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
///////////////////////////////////////////////////////////////////////////////
|
///////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
void SkLayerDrawLooper::flatten(SkWriteBuffer& buffer) const {
|
void SkLayerDrawLooper::flatten(SkWriteBuffer& buffer) const {
|
||||||
|
@ -1,12 +1,15 @@
|
|||||||
|
|
||||||
/*
|
/*
|
||||||
* Copyright 2011 Google Inc.
|
* Copyright 2011 Google Inc.
|
||||||
*
|
*
|
||||||
* Use of this source code is governed by a BSD-style license that can be
|
* Use of this source code is governed by a BSD-style license that can be
|
||||||
* found in the LICENSE file.
|
* found in the LICENSE file.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include "SkBlurMask.h"
|
#include "SkBlurMask.h"
|
||||||
#include "SkBlurMaskFilter.h"
|
#include "SkBlurMaskFilter.h"
|
||||||
|
#include "SkBlurDrawLooper.h"
|
||||||
|
#include "SkLayerDrawLooper.h"
|
||||||
|
#include "SkEmbossMaskFilter.h"
|
||||||
#include "SkCanvas.h"
|
#include "SkCanvas.h"
|
||||||
#include "SkMath.h"
|
#include "SkMath.h"
|
||||||
#include "SkPaint.h"
|
#include "SkPaint.h"
|
||||||
@ -380,7 +383,187 @@ static void test_sigma_range(skiatest::Reporter* reporter, GrContextFactory* fac
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
///////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
static SkBlurQuality blurMaskFilterFlags_as_quality(uint32_t blurMaskFilterFlags) {
|
||||||
|
return (blurMaskFilterFlags & SkBlurMaskFilter::kHighQuality_BlurFlag) ?
|
||||||
|
kHigh_SkBlurQuality : kLow_SkBlurQuality;
|
||||||
|
}
|
||||||
|
|
||||||
|
static uint32_t blurMaskFilterFlags_to_blurDrawLooperFlags(uint32_t bmf) {
|
||||||
|
const struct {
|
||||||
|
uint32_t fBlurMaskFilterFlag;
|
||||||
|
uint32_t fBlurDrawLooperFlag;
|
||||||
|
} pairs[] = {
|
||||||
|
{ SkBlurMaskFilter::kIgnoreTransform_BlurFlag, SkBlurDrawLooper::kIgnoreTransform_BlurFlag },
|
||||||
|
{ SkBlurMaskFilter::kHighQuality_BlurFlag, SkBlurDrawLooper::kHighQuality_BlurFlag },
|
||||||
|
};
|
||||||
|
|
||||||
|
uint32_t bdl = 0;
|
||||||
|
for (size_t i = 0; i < SK_ARRAY_COUNT(pairs); ++i) {
|
||||||
|
if (bmf & pairs[i].fBlurMaskFilterFlag) {
|
||||||
|
bdl |= pairs[i].fBlurDrawLooperFlag;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return bdl;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void test_blurDrawLooper(skiatest::Reporter* reporter, SkScalar sigma,
|
||||||
|
SkBlurStyle style, uint32_t blurMaskFilterFlags) {
|
||||||
|
if (kNormal_SkBlurStyle != style) {
|
||||||
|
return; // blurdrawlooper only supports normal
|
||||||
|
}
|
||||||
|
|
||||||
|
const SkColor color = 0xFF335577;
|
||||||
|
const SkScalar dx = 10;
|
||||||
|
const SkScalar dy = -5;
|
||||||
|
const SkBlurQuality quality = blurMaskFilterFlags_as_quality(blurMaskFilterFlags);
|
||||||
|
uint32_t flags = blurMaskFilterFlags_to_blurDrawLooperFlags(blurMaskFilterFlags);
|
||||||
|
|
||||||
|
SkAutoTUnref<SkDrawLooper> lp(SkBlurDrawLooper::Create(color, sigma, dx, dy, flags));
|
||||||
|
|
||||||
|
const bool expectSuccess = sigma > 0 &&
|
||||||
|
0 == (flags & SkBlurDrawLooper::kIgnoreTransform_BlurFlag);
|
||||||
|
|
||||||
|
if (NULL == lp.get()) {
|
||||||
|
REPORTER_ASSERT(reporter, sigma <= 0);
|
||||||
|
} else {
|
||||||
|
SkDrawLooper::BlurShadowRec rec;
|
||||||
|
bool success = lp->asABlurShadow(&rec);
|
||||||
|
REPORTER_ASSERT(reporter, success == expectSuccess);
|
||||||
|
if (success) {
|
||||||
|
REPORTER_ASSERT(reporter, rec.fSigma == sigma);
|
||||||
|
REPORTER_ASSERT(reporter, rec.fOffset.x() == dx);
|
||||||
|
REPORTER_ASSERT(reporter, rec.fOffset.y() == dy);
|
||||||
|
REPORTER_ASSERT(reporter, rec.fColor == color);
|
||||||
|
REPORTER_ASSERT(reporter, rec.fStyle == style);
|
||||||
|
REPORTER_ASSERT(reporter, rec.fQuality == quality);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void test_delete_looper(skiatest::Reporter* reporter, SkDrawLooper* lp, SkScalar sigma,
|
||||||
|
SkBlurStyle style, SkBlurQuality quality, bool expectSuccess) {
|
||||||
|
SkDrawLooper::BlurShadowRec rec;
|
||||||
|
bool success = lp->asABlurShadow(&rec);
|
||||||
|
REPORTER_ASSERT(reporter, success == expectSuccess);
|
||||||
|
if (success != expectSuccess) {
|
||||||
|
lp->asABlurShadow(&rec);
|
||||||
|
}
|
||||||
|
if (success) {
|
||||||
|
REPORTER_ASSERT(reporter, rec.fSigma == sigma);
|
||||||
|
REPORTER_ASSERT(reporter, rec.fStyle == style);
|
||||||
|
REPORTER_ASSERT(reporter, rec.fQuality == quality);
|
||||||
|
}
|
||||||
|
lp->unref();
|
||||||
|
}
|
||||||
|
|
||||||
|
static void make_noop_layer(SkLayerDrawLooper::Builder* builder) {
|
||||||
|
SkLayerDrawLooper::LayerInfo info;
|
||||||
|
|
||||||
|
info.fPaintBits = 0;
|
||||||
|
info.fColorMode = SkXfermode::kDst_Mode;
|
||||||
|
builder->addLayer(info);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void make_blur_layer(SkLayerDrawLooper::Builder* builder, SkMaskFilter* mf) {
|
||||||
|
SkLayerDrawLooper::LayerInfo info;
|
||||||
|
|
||||||
|
info.fPaintBits = SkLayerDrawLooper::kMaskFilter_Bit;
|
||||||
|
info.fColorMode = SkXfermode::kSrc_Mode;
|
||||||
|
SkPaint* paint = builder->addLayer(info);
|
||||||
|
paint->setMaskFilter(mf);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void test_layerDrawLooper(skiatest::Reporter* reporter, SkMaskFilter* mf, SkScalar sigma,
|
||||||
|
SkBlurStyle style, SkBlurQuality quality, bool expectSuccess) {
|
||||||
|
|
||||||
|
SkLayerDrawLooper::LayerInfo info;
|
||||||
|
SkLayerDrawLooper::Builder builder;
|
||||||
|
|
||||||
|
// 1 layer is too few
|
||||||
|
make_noop_layer(&builder);
|
||||||
|
test_delete_looper(reporter, builder.detachLooper(), sigma, style, quality, false);
|
||||||
|
|
||||||
|
// 2 layers is good, but need blur
|
||||||
|
make_noop_layer(&builder);
|
||||||
|
make_noop_layer(&builder);
|
||||||
|
test_delete_looper(reporter, builder.detachLooper(), sigma, style, quality, false);
|
||||||
|
|
||||||
|
// 2 layers is just right
|
||||||
|
make_noop_layer(&builder);
|
||||||
|
make_blur_layer(&builder, mf);
|
||||||
|
test_delete_looper(reporter, builder.detachLooper(), sigma, style, quality, expectSuccess);
|
||||||
|
|
||||||
|
// 3 layers is too many
|
||||||
|
make_noop_layer(&builder);
|
||||||
|
make_blur_layer(&builder, mf);
|
||||||
|
make_noop_layer(&builder);
|
||||||
|
test_delete_looper(reporter, builder.detachLooper(), sigma, style, quality, false);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void test_asABlur(skiatest::Reporter* reporter) {
|
||||||
|
const SkBlurStyle styles[] = {
|
||||||
|
kNormal_SkBlurStyle, kSolid_SkBlurStyle, kOuter_SkBlurStyle, kInner_SkBlurStyle
|
||||||
|
};
|
||||||
|
const SkScalar sigmas[] = {
|
||||||
|
// values <= 0 should not success for a blur
|
||||||
|
-1, 0, 0.5f, 2
|
||||||
|
};
|
||||||
|
|
||||||
|
// Test asABlur for SkBlurMaskFilter
|
||||||
|
//
|
||||||
|
for (size_t i = 0; i < SK_ARRAY_COUNT(styles); ++i) {
|
||||||
|
const SkBlurStyle style = (SkBlurStyle)styles[i];
|
||||||
|
for (size_t j = 0; j < SK_ARRAY_COUNT(sigmas); ++j) {
|
||||||
|
const SkScalar sigma = sigmas[j];
|
||||||
|
for (int flags = 0; flags <= SkBlurMaskFilter::kAll_BlurFlag; ++flags) {
|
||||||
|
const SkBlurQuality quality = blurMaskFilterFlags_as_quality(flags);
|
||||||
|
|
||||||
|
SkAutoTUnref<SkMaskFilter> mf(SkBlurMaskFilter::Create(style, sigma, flags));
|
||||||
|
if (NULL == mf.get()) {
|
||||||
|
REPORTER_ASSERT(reporter, sigma <= 0);
|
||||||
|
} else {
|
||||||
|
REPORTER_ASSERT(reporter, sigma > 0);
|
||||||
|
SkMaskFilter::BlurRec rec;
|
||||||
|
bool success = mf->asABlur(&rec);
|
||||||
|
if (flags & SkBlurMaskFilter::kIgnoreTransform_BlurFlag) {
|
||||||
|
REPORTER_ASSERT(reporter, !success);
|
||||||
|
} else {
|
||||||
|
REPORTER_ASSERT(reporter, success);
|
||||||
|
REPORTER_ASSERT(reporter, rec.fSigma == sigma);
|
||||||
|
REPORTER_ASSERT(reporter, rec.fStyle == style);
|
||||||
|
REPORTER_ASSERT(reporter, rec.fQuality == quality);
|
||||||
|
}
|
||||||
|
test_layerDrawLooper(reporter, mf, sigma, style, quality, success);
|
||||||
|
}
|
||||||
|
test_blurDrawLooper(reporter, sigma, style, flags);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Test asABlur for SkEmbossMaskFilter -- should never succeed
|
||||||
|
//
|
||||||
|
{
|
||||||
|
SkEmbossMaskFilter::Light light = {
|
||||||
|
{ 1, 1, 1 }, 0, 127, 127
|
||||||
|
};
|
||||||
|
for (size_t j = 0; j < SK_ARRAY_COUNT(sigmas); ++j) {
|
||||||
|
const SkScalar sigma = sigmas[j];
|
||||||
|
SkAutoTUnref<SkMaskFilter> mf(SkEmbossMaskFilter::Create(sigma, light));
|
||||||
|
if (mf.get()) {
|
||||||
|
SkMaskFilter::BlurRec rec;
|
||||||
|
bool success = mf->asABlur(&rec);
|
||||||
|
REPORTER_ASSERT(reporter, !success);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
///////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
DEF_GPUTEST(Blur, reporter, factory) {
|
DEF_GPUTEST(Blur, reporter, factory) {
|
||||||
test_blur_drawing(reporter);
|
test_blur_drawing(reporter);
|
||||||
test_sigma_range(reporter, factory);
|
test_sigma_range(reporter, factory);
|
||||||
|
test_asABlur(reporter);
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user