本文整理汇总了C++中SkMask::computeImageSize方法的典型用法代码示例。如果您正苦于以下问题:C++ SkMask::computeImageSize方法的具体用法?C++ SkMask::computeImageSize怎么用?C++ SkMask::computeImageSize使用的例子?那么, 这里精选的方法代码示例或许可以为您提供帮助。您也可以进一步了解该方法所在类SkMask
的用法示例。
在下文中一共展示了SkMask::computeImageSize方法的11个代码示例,这些例子默认根据受欢迎程度排序。您可以为喜欢或者感觉有用的代码点赞,您的评价将有助于系统推荐出更棒的C++代码示例。
示例1: BoxBlur
bool SkBlurMask::BoxBlur(SkMask* dst, const SkMask& src, SkScalar sigma, SkBlurStyle style,
SkIPoint* margin) {
if (src.fFormat != SkMask::kA8_Format && src.fFormat != SkMask::kARGB32_Format) {
return false;
}
SkIPoint border;
SkMaskBlurFilter blurFilter{sigma, sigma};
if (blurFilter.hasNoBlur()) {
return false;
}
border = blurFilter.blur(src, dst);
// If src.fImage is null, then this call is only to calculate the border.
if (src.fImage != nullptr && dst->fImage == nullptr) {
return false;
}
if (src.fImage != nullptr) {
// if need be, alloc the "real" dst (same size as src) and copy/merge
// the blur into it (applying the src)
if (style == kInner_SkBlurStyle) {
// now we allocate the "real" dst, mirror the size of src
size_t srcSize = src.computeImageSize();
if (0 == srcSize) {
return false; // too big to allocate, abort
}
auto blur = dst->fImage;
dst->fImage = SkMask::AllocImage(srcSize);
auto blurStart = &blur[border.x() + border.y() * dst->fRowBytes];
merge_src_with_blur(dst->fImage, src.fRowBytes,
src.fImage, src.fRowBytes,
blurStart,
dst->fRowBytes,
src.fBounds.width(), src.fBounds.height());
SkMask::FreeImage(blur);
} else if (style != kNormal_SkBlurStyle) {
auto dstStart = &dst->fImage[border.x() + border.y() * dst->fRowBytes];
clamp_with_orig(dstStart,
dst->fRowBytes, src.fImage, src.fRowBytes,
src.fBounds.width(), src.fBounds.height(), style);
}
}
if (style == kInner_SkBlurStyle) {
dst->fBounds = src.fBounds; // restore trimmed bounds
dst->fRowBytes = src.fRowBytes;
}
if (margin != nullptr) {
*margin = border;
}
return true;
}
示例2: filterMask
bool SkEmbossMaskFilter::filterMask(SkMask* dst, const SkMask& src,
const SkMatrix& matrix, SkIPoint* margin) const {
SkScalar sigma = matrix.mapRadius(fBlurSigma);
if (!SkBlurMask::BoxBlur(dst, src, sigma, SkBlurMask::kInner_Style,
SkBlurMask::kLow_Quality)) {
return false;
}
dst->fFormat = SkMask::k3D_Format;
if (margin) {
margin->set(SkScalarCeilToInt(3*sigma), SkScalarCeilToInt(3*sigma));
}
if (src.fImage == NULL) {
return true;
}
// create a larger buffer for the other two channels (should force fBlur to do this for us)
{
uint8_t* alphaPlane = dst->fImage;
size_t planeSize = dst->computeImageSize();
if (0 == planeSize) {
return false; // too big to allocate, abort
}
dst->fImage = SkMask::AllocImage(planeSize * 3);
memcpy(dst->fImage, alphaPlane, planeSize);
SkMask::FreeImage(alphaPlane);
}
// run the light direction through the matrix...
Light light = fLight;
matrix.mapVectors((SkVector*)(void*)light.fDirection,
(SkVector*)(void*)fLight.fDirection, 1);
// now restore the length of the XY component
// cast to SkVector so we can call setLength (this double cast silences alias warnings)
SkVector* vec = (SkVector*)(void*)light.fDirection;
vec->setLength(light.fDirection[0],
light.fDirection[1],
SkPoint::Length(fLight.fDirection[0], fLight.fDirection[1]));
SkEmbossMask::Emboss(dst, light);
// restore original alpha
memcpy(dst->fImage, src.fImage, src.computeImageSize());
return true;
}
示例3: getImage
void SkScalerContext::getImage(const SkGlyph& origGlyph) {
const SkGlyph* glyph = &origGlyph;
SkGlyph tmpGlyph;
if (fMaskFilter) { // restore the prefilter bounds
tmpGlyph.init(origGlyph.fID);
// need the original bounds, sans our maskfilter
SkMaskFilter* mf = fMaskFilter;
fMaskFilter = NULL; // temp disable
this->getMetrics(&tmpGlyph);
fMaskFilter = mf; // restore
tmpGlyph.fImage = origGlyph.fImage;
// we need the prefilter bounds to be <= filter bounds
SkASSERT(tmpGlyph.fWidth <= origGlyph.fWidth);
SkASSERT(tmpGlyph.fHeight <= origGlyph.fHeight);
glyph = &tmpGlyph;
}
if (fRec.fFrameWidth > 0 || fPathEffect != NULL || fRasterizer != NULL) {
SkPath devPath, fillPath;
SkMatrix fillToDevMatrix;
this->internalGetPath(*glyph, &fillPath, &devPath, &fillToDevMatrix);
if (fRasterizer) {
SkMask mask;
glyph->toMask(&mask);
mask.fFormat = SkMask::kA8_Format;
sk_bzero(glyph->fImage, mask.computeImageSize());
if (!fRasterizer->rasterize(fillPath, fillToDevMatrix, NULL,
fMaskFilter, &mask,
SkMask::kJustRenderImage_CreateMode)) {
return;
}
} else {
SkBitmap bm;
SkBitmap::Config config;
SkMatrix matrix;
SkRegion clip;
SkPaint paint;
SkDraw draw;
if (SkMask::kA8_Format == fRec.fMaskFormat) {
config = SkBitmap::kA8_Config;
paint.setAntiAlias(true);
} else {
SkASSERT(SkMask::kBW_Format == fRec.fMaskFormat);
config = SkBitmap::kA1_Config;
paint.setAntiAlias(false);
}
clip.setRect(0, 0, glyph->fWidth, glyph->fHeight);
matrix.setTranslate(-SkIntToScalar(glyph->fLeft),
-SkIntToScalar(glyph->fTop));
bm.setConfig(config, glyph->fWidth, glyph->fHeight,
glyph->rowBytes());
bm.setPixels(glyph->fImage);
sk_bzero(glyph->fImage, bm.height() * bm.rowBytes());
draw.fClip = &clip;
draw.fMatrix = &matrix;
draw.fBitmap = &bm;
draw.fBounder = NULL;
draw.drawPath(devPath, paint);
}
} else {
this->getGlyphContext(*glyph)->generateImage(*glyph);
}
if (fMaskFilter) {
SkMask srcM, dstM;
SkMatrix matrix;
// the src glyph image shouldn't be 3D
SkASSERT(SkMask::k3D_Format != glyph->fMaskFormat);
glyph->toMask(&srcM);
fRec.getMatrixFrom2x2(&matrix);
if (fMaskFilter->filterMask(&dstM, srcM, matrix, NULL)) {
int width = SkFastMin32(origGlyph.fWidth, dstM.fBounds.width());
int height = SkFastMin32(origGlyph.fHeight, dstM.fBounds.height());
int dstRB = origGlyph.rowBytes();
int srcRB = dstM.fRowBytes;
const uint8_t* src = (const uint8_t*)dstM.fImage;
uint8_t* dst = (uint8_t*)origGlyph.fImage;
if (SkMask::k3D_Format == dstM.fFormat) {
// we have to copy 3 times as much
height *= 3;
}
// clean out our glyph, since it may be larger than dstM
//sk_bzero(dst, height * dstRB);
//.........这里部分代码省略.........
示例4: getImage
void SkScalerContext::getImage(const SkGlyph& origGlyph) {
const SkGlyph* glyph = &origGlyph;
SkGlyph tmpGlyph;
if (fMaskFilter) { // restore the prefilter bounds
tmpGlyph.init(origGlyph.fID);
// need the original bounds, sans our maskfilter
SkMaskFilter* mf = fMaskFilter;
fMaskFilter = NULL; // temp disable
this->getMetrics(&tmpGlyph);
fMaskFilter = mf; // restore
tmpGlyph.fImage = origGlyph.fImage;
// we need the prefilter bounds to be <= filter bounds
SkASSERT(tmpGlyph.fWidth <= origGlyph.fWidth);
SkASSERT(tmpGlyph.fHeight <= origGlyph.fHeight);
glyph = &tmpGlyph;
}
if (fGenerateImageFromPath) {
SkPath devPath, fillPath;
SkMatrix fillToDevMatrix;
SkMask mask;
this->internalGetPath(*glyph, &fillPath, &devPath, &fillToDevMatrix);
glyph->toMask(&mask);
if (fRasterizer) {
mask.fFormat = SkMask::kA8_Format;
sk_bzero(glyph->fImage, mask.computeImageSize());
if (!fRasterizer->rasterize(fillPath, fillToDevMatrix, NULL,
fMaskFilter, &mask,
SkMask::kJustRenderImage_CreateMode)) {
return;
}
} else {
generateMask(mask, devPath);
}
} else {
this->getGlyphContext(*glyph)->generateImage(*glyph);
}
if (fMaskFilter) {
SkMask srcM, dstM;
SkMatrix matrix;
// the src glyph image shouldn't be 3D
SkASSERT(SkMask::k3D_Format != glyph->fMaskFormat);
glyph->toMask(&srcM);
fRec.getMatrixFrom2x2(&matrix);
if (fMaskFilter->filterMask(&dstM, srcM, matrix, NULL)) {
int width = SkFastMin32(origGlyph.fWidth, dstM.fBounds.width());
int height = SkFastMin32(origGlyph.fHeight, dstM.fBounds.height());
int dstRB = origGlyph.rowBytes();
int srcRB = dstM.fRowBytes;
const uint8_t* src = (const uint8_t*)dstM.fImage;
uint8_t* dst = (uint8_t*)origGlyph.fImage;
if (SkMask::k3D_Format == dstM.fFormat) {
// we have to copy 3 times as much
height *= 3;
}
// clean out our glyph, since it may be larger than dstM
//sk_bzero(dst, height * dstRB);
while (--height >= 0) {
memcpy(dst, src, width);
src += srcRB;
dst += dstRB;
}
SkMask::FreeImage(dstM.fImage);
}
}
}
示例5: BlurGroundTruth
bool SkBlurMask::BlurGroundTruth(SkMask* dst, const SkMask& src, SkScalar provided_radius,
Style style, SkIPoint* margin) {
if (src.fFormat != SkMask::kA8_Format) {
return false;
}
float radius = SkScalarToFloat(SkScalarMul(provided_radius, kBlurRadiusFudgeFactor));
float stddev = SkScalarToFloat(radius) /2.0f;
float variance = stddev * stddev;
int windowSize = SkScalarCeil(stddev*4);
// round window size up to nearest odd number
windowSize |= 1;
SkAutoTMalloc<float> gaussWindow(windowSize);
int halfWindow = windowSize >> 1;
gaussWindow[halfWindow] = 1;
float windowSum = 1;
for (int x = 1 ; x <= halfWindow ; ++x) {
float gaussian = expf(-x*x / variance);
gaussWindow[halfWindow + x] = gaussWindow[halfWindow-x] = gaussian;
windowSum += 2*gaussian;
}
// leave the filter un-normalized for now; we will divide by the normalization
// sum later;
int pad = halfWindow;
if (margin) {
margin->set( pad, pad );
}
dst->fBounds = src.fBounds;
dst->fBounds.outset(pad, pad);
dst->fRowBytes = dst->fBounds.width();
dst->fFormat = SkMask::kA8_Format;
dst->fImage = NULL;
if (src.fImage) {
size_t dstSize = dst->computeImageSize();
if (0 == dstSize) {
return false; // too big to allocate, abort
}
int srcWidth = src.fBounds.width();
int srcHeight = src.fBounds.height();
int dstWidth = dst->fBounds.width();
const uint8_t* srcPixels = src.fImage;
uint8_t* dstPixels = SkMask::AllocImage(dstSize);
SkAutoTCallVProc<uint8_t, SkMask_FreeImage> autoCall(dstPixels);
// do the actual blur. First, make a padded copy of the source.
// use double pad so we never have to check if we're outside anything
int padWidth = srcWidth + 4*pad;
int padHeight = srcHeight;
int padSize = padWidth * padHeight;
SkAutoTMalloc<uint8_t> padPixels(padSize);
memset(padPixels, 0, padSize);
for (int y = 0 ; y < srcHeight; ++y) {
uint8_t* padptr = padPixels + y * padWidth + 2*pad;
const uint8_t* srcptr = srcPixels + y * srcWidth;
memcpy(padptr, srcptr, srcWidth);
}
// blur in X, transposing the result into a temporary floating point buffer.
// also double-pad the intermediate result so that the second blur doesn't
// have to do extra conditionals.
int tmpWidth = padHeight + 4*pad;
int tmpHeight = padWidth - 2*pad;
int tmpSize = tmpWidth * tmpHeight;
SkAutoTMalloc<float> tmpImage(tmpSize);
memset(tmpImage, 0, tmpSize*sizeof(tmpImage[0]));
for (int y = 0 ; y < padHeight ; ++y) {
uint8_t *srcScanline = padPixels + y*padWidth;
for (int x = pad ; x < padWidth - pad ; ++x) {
float *outPixel = tmpImage + (x-pad)*tmpWidth + y + 2*pad; // transposed output
uint8_t *windowCenter = srcScanline + x;
for (int i = -pad ; i <= pad ; ++i) {
*outPixel += gaussWindow[pad+i]*windowCenter[i];
}
*outPixel /= windowSum;
}
}
// blur in Y; now filling in the actual desired destination. We have to do
// the transpose again; these transposes guarantee that we read memory in
// linear order.
//.........这里部分代码省略.........
开发者ID:IllusionRom-deprecated,项目名称:android_platform_external_chromium_org_third_party_skia_src,代码行数:101,代码来源:SkBlurMask.cpp
示例6: Blur
bool SkBlurMask::Blur(SkMask* dst, const SkMask& src,
SkScalar radius, Style style, Quality quality,
SkIPoint* margin)
{
if (src.fFormat != SkMask::kA8_Format) {
return false;
}
// Force high quality off for small radii (performance)
if (radius < SkIntToScalar(3)) {
quality = kLow_Quality;
}
// highQuality: use three box blur passes as a cheap way
// to approximate a Gaussian blur
int passCount = (kHigh_Quality == quality) ? 3 : 1;
SkScalar passRadius = (kHigh_Quality == quality) ?
SkScalarMul( radius, kBlurRadiusFudgeFactor):
radius;
int rx = SkScalarCeil(passRadius);
int outerWeight = 255 - SkScalarRound((SkIntToScalar(rx) - passRadius) * 255);
SkASSERT(rx >= 0);
SkASSERT((unsigned)outerWeight <= 255);
if (rx <= 0) {
return false;
}
int ry = rx; // only do square blur for now
int padx = passCount * rx;
int pady = passCount * ry;
if (margin) {
margin->set(padx, pady);
}
dst->fBounds.set(src.fBounds.fLeft - padx, src.fBounds.fTop - pady,
src.fBounds.fRight + padx, src.fBounds.fBottom + pady);
dst->fRowBytes = dst->fBounds.width();
dst->fFormat = SkMask::kA8_Format;
dst->fImage = NULL;
if (src.fImage) {
size_t dstSize = dst->computeImageSize();
if (0 == dstSize) {
return false; // too big to allocate, abort
}
int sw = src.fBounds.width();
int sh = src.fBounds.height();
const uint8_t* sp = src.fImage;
uint8_t* dp = SkMask::AllocImage(dstSize);
SkAutoTCallVProc<uint8_t, SkMask_FreeImage> autoCall(dp);
// build the blurry destination
SkAutoTMalloc<uint8_t> tmpBuffer(dstSize);
uint8_t* tp = tmpBuffer.get();
int w = sw, h = sh;
if (outerWeight == 255) {
int loRadius, hiRadius;
get_adjusted_radii(passRadius, &loRadius, &hiRadius);
if (kHigh_Quality == quality) {
// Do three X blurs, with a transpose on the final one.
w = boxBlur(sp, src.fRowBytes, tp, loRadius, hiRadius, w, h, false);
w = boxBlur(tp, w, dp, hiRadius, loRadius, w, h, false);
w = boxBlur(dp, w, tp, hiRadius, hiRadius, w, h, true);
// Do three Y blurs, with a transpose on the final one.
h = boxBlur(tp, h, dp, loRadius, hiRadius, h, w, false);
h = boxBlur(dp, h, tp, hiRadius, loRadius, h, w, false);
h = boxBlur(tp, h, dp, hiRadius, hiRadius, h, w, true);
} else {
w = boxBlur(sp, src.fRowBytes, tp, rx, rx, w, h, true);
h = boxBlur(tp, h, dp, ry, ry, h, w, true);
}
} else {
if (kHigh_Quality == quality) {
// Do three X blurs, with a transpose on the final one.
w = boxBlurInterp(sp, src.fRowBytes, tp, rx, w, h, false, outerWeight);
w = boxBlurInterp(tp, w, dp, rx, w, h, false, outerWeight);
w = boxBlurInterp(dp, w, tp, rx, w, h, true, outerWeight);
// Do three Y blurs, with a transpose on the final one.
h = boxBlurInterp(tp, h, dp, ry, h, w, false, outerWeight);
h = boxBlurInterp(dp, h, tp, ry, h, w, false, outerWeight);
h = boxBlurInterp(tp, h, dp, ry, h, w, true, outerWeight);
} else {
w = boxBlurInterp(sp, src.fRowBytes, tp, rx, w, h, true, outerWeight);
h = boxBlurInterp(tp, h, dp, ry, h, w, true, outerWeight);
}
}
dst->fImage = dp;
// if need be, alloc the "real" dst (same size as src) and copy/merge
// the blur into it (applying the src)
if (style == kInner_Style) {
// now we allocate the "real" dst, mirror the size of src
size_t srcSize = src.computeImageSize();
//.........这里部分代码省略.........
开发者ID:IllusionRom-deprecated,项目名称:android_platform_external_chromium_org_third_party_skia_src,代码行数:101,代码来源:SkBlurMask.cpp
示例7: getImage
void SkScalerContext::getImage(const SkGlyph& origGlyph) {
const SkGlyph* glyph = &origGlyph;
SkGlyph tmpGlyph;
// in case we need to call generateImage on a mask-format that is different
// (i.e. larger) than what our caller allocated by looking at origGlyph.
SkAutoMalloc tmpGlyphImageStorage;
// If we are going to draw-from-path, then we cannot generate color, since
// the path only makes a mask. This case should have been caught up in
// generateMetrics().
SkASSERT(!fGenerateImageFromPath ||
SkMask::kARGB32_Format != origGlyph.fMaskFormat);
if (fMaskFilter) { // restore the prefilter bounds
tmpGlyph.initGlyphIdFrom(origGlyph);
// need the original bounds, sans our maskfilter
SkMaskFilter* mf = fMaskFilter;
fMaskFilter = nullptr; // temp disable
this->getMetrics(&tmpGlyph);
fMaskFilter = mf; // restore
// we need the prefilter bounds to be <= filter bounds
SkASSERT(tmpGlyph.fWidth <= origGlyph.fWidth);
SkASSERT(tmpGlyph.fHeight <= origGlyph.fHeight);
if (tmpGlyph.fMaskFormat == origGlyph.fMaskFormat) {
tmpGlyph.fImage = origGlyph.fImage;
} else {
tmpGlyphImageStorage.reset(tmpGlyph.computeImageSize());
tmpGlyph.fImage = tmpGlyphImageStorage.get();
}
glyph = &tmpGlyph;
}
if (fGenerateImageFromPath) {
SkPath devPath, fillPath;
SkMatrix fillToDevMatrix;
SkMask mask;
this->internalGetPath(*glyph, &fillPath, &devPath, &fillToDevMatrix);
glyph->toMask(&mask);
if (fRasterizer) {
mask.fFormat = SkMask::kA8_Format;
sk_bzero(glyph->fImage, mask.computeImageSize());
if (!fRasterizer->rasterize(fillPath, fillToDevMatrix, nullptr,
fMaskFilter, &mask,
SkMask::kJustRenderImage_CreateMode)) {
return;
}
if (fPreBlend.isApplicable()) {
applyLUTToA8Mask(mask, fPreBlend.fG);
}
} else {
SkASSERT(SkMask::kARGB32_Format != mask.fFormat);
generateMask(mask, devPath, fPreBlend);
}
} else {
generateImage(*glyph);
}
if (fMaskFilter) {
SkMask srcM, dstM;
SkMatrix matrix;
// the src glyph image shouldn't be 3D
SkASSERT(SkMask::k3D_Format != glyph->fMaskFormat);
SkAutoSMalloc<32*32> a8storage;
glyph->toMask(&srcM);
if (SkMask::kARGB32_Format == srcM.fFormat) {
// now we need to extract the alpha-channel from the glyph's image
// and copy it into a temp buffer, and then point srcM at that temp.
srcM.fFormat = SkMask::kA8_Format;
srcM.fRowBytes = SkAlign4(srcM.fBounds.width());
size_t size = srcM.computeImageSize();
a8storage.reset(size);
srcM.fImage = (uint8_t*)a8storage.get();
extract_alpha(srcM,
(const SkPMColor*)glyph->fImage, glyph->rowBytes());
}
fRec.getMatrixFrom2x2(&matrix);
if (fMaskFilter->filterMask(&dstM, srcM, matrix, nullptr)) {
int width = SkFastMin32(origGlyph.fWidth, dstM.fBounds.width());
int height = SkFastMin32(origGlyph.fHeight, dstM.fBounds.height());
int dstRB = origGlyph.rowBytes();
int srcRB = dstM.fRowBytes;
const uint8_t* src = (const uint8_t*)dstM.fImage;
uint8_t* dst = (uint8_t*)origGlyph.fImage;
if (SkMask::k3D_Format == dstM.fFormat) {
// we have to copy 3 times as much
height *= 3;
}
//.........这里部分代码省略.........
示例8: generateMask
static void generateMask(const SkMask& mask, const SkPath& path,
const SkMaskGamma::PreBlend& maskPreBlend) {
SkPaint paint;
int srcW = mask.fBounds.width();
int srcH = mask.fBounds.height();
int dstW = srcW;
int dstH = srcH;
int dstRB = mask.fRowBytes;
SkMatrix matrix;
matrix.setTranslate(-SkIntToScalar(mask.fBounds.fLeft),
-SkIntToScalar(mask.fBounds.fTop));
paint.setAntiAlias(SkMask::kBW_Format != mask.fFormat);
switch (mask.fFormat) {
case SkMask::kBW_Format:
dstRB = 0; // signals we need a copy
break;
case SkMask::kA8_Format:
break;
case SkMask::kLCD16_Format:
// TODO: trigger off LCD orientation
dstW = 4*dstW - 8;
matrix.setTranslate(-SkIntToScalar(mask.fBounds.fLeft + 1),
-SkIntToScalar(mask.fBounds.fTop));
matrix.postScale(SkIntToScalar(4), SK_Scalar1);
dstRB = 0; // signals we need a copy
break;
default:
SkDEBUGFAIL("unexpected mask format");
}
SkRasterClip clip;
clip.setRect(SkIRect::MakeWH(dstW, dstH));
const SkImageInfo info = SkImageInfo::MakeA8(dstW, dstH);
SkAutoPixmapStorage dst;
if (0 == dstRB) {
if (!dst.tryAlloc(info)) {
// can't allocate offscreen, so empty the mask and return
sk_bzero(mask.fImage, mask.computeImageSize());
return;
}
} else {
dst.reset(info, mask.fImage, dstRB);
}
sk_bzero(dst.writable_addr(), dst.getSafeSize());
SkDraw draw;
draw.fDst = dst;
draw.fRC = &clip;
draw.fClip = &clip.bwRgn();
draw.fMatrix = &matrix;
draw.drawPath(path, paint);
switch (mask.fFormat) {
case SkMask::kBW_Format:
packA8ToA1(mask, dst.addr8(0, 0), dst.rowBytes());
break;
case SkMask::kA8_Format:
if (maskPreBlend.isApplicable()) {
applyLUTToA8Mask(mask, maskPreBlend.fG);
}
break;
case SkMask::kLCD16_Format:
if (maskPreBlend.isApplicable()) {
pack4xHToLCD16<true>(dst, mask, maskPreBlend);
} else {
pack4xHToLCD16<false>(dst, mask, maskPreBlend);
}
break;
default:
break;
}
}
示例9: BoxBlur
bool SkBlurMask::BoxBlur(SkMask* dst, const SkMask& src,
SkScalar sigma, SkBlurStyle style, SkBlurQuality quality,
SkIPoint* margin, bool force_quality) {
if (src.fFormat != SkMask::kA8_Format) {
return false;
}
SkIPoint border;
#ifdef SK_SUPPORT_LEGACY_MASK_BLUR
auto get_adjusted_radii = [](SkScalar passRadius, int *loRadius, int *hiRadius) {
*loRadius = *hiRadius = SkScalarCeilToInt(passRadius);
if (SkIntToScalar(*hiRadius) - passRadius > 0.5f) {
*loRadius = *hiRadius - 1;
}
};
// Force high quality off for small radii (performance)
if (!force_quality && sigma <= SkIntToScalar(2)) {
quality = kLow_SkBlurQuality;
}
SkScalar passRadius;
if (kHigh_SkBlurQuality == quality) {
// For the high quality path the 3 pass box blur kernel width is
// 6*rad+1 while the full Gaussian width is 6*sigma.
passRadius = sigma - (1 / 6.0f);
} else {
// For the low quality path we only attempt to cover 3*sigma of the
// Gaussian blur area (1.5*sigma on each side). The single pass box
// blur's kernel size is 2*rad+1.
passRadius = 1.5f * sigma - 0.5f;
}
// highQuality: use three box blur passes as a cheap way
// to approximate a Gaussian blur
int passCount = (kHigh_SkBlurQuality == quality) ? 3 : 1;
int rx = SkScalarCeilToInt(passRadius);
int outerWeight = 255 - SkScalarRoundToInt((SkIntToScalar(rx) - passRadius) * 255);
SkASSERT(rx >= 0);
SkASSERT((unsigned)outerWeight <= 255);
if (rx <= 0) {
return false;
}
int ry = rx; // only do square blur for now
int padx = passCount * rx;
int pady = passCount * ry;
border = {padx, pady};
dst->fBounds.set(src.fBounds.fLeft - padx, src.fBounds.fTop - pady,
src.fBounds.fRight + padx, src.fBounds.fBottom + pady);
dst->fRowBytes = dst->fBounds.width();
dst->fFormat = SkMask::kA8_Format;
dst->fImage = nullptr;
if (src.fImage) {
size_t dstSize = dst->computeImageSize();
if (0 == dstSize) {
return false; // too big to allocate, abort
}
int sw = src.fBounds.width();
int sh = src.fBounds.height();
const uint8_t* sp = src.fImage;
uint8_t* dp = SkMask::AllocImage(dstSize);
SkAutoTCallVProc<uint8_t, SkMask_FreeImage> autoCall(dp);
// build the blurry destination
SkAutoTMalloc<uint8_t> tmpBuffer(dstSize);
uint8_t* tp = tmpBuffer.get();
int w = sw, h = sh;
if (outerWeight == 255) {
int loRadius, hiRadius;
get_adjusted_radii(passRadius, &loRadius, &hiRadius);
if (kHigh_SkBlurQuality == quality) {
// Do three X blurs, with a transpose on the final one.
w = boxBlur<false>(sp, src.fRowBytes, tp, loRadius, hiRadius, w, h);
w = boxBlur<false>(tp, w, dp, hiRadius, loRadius, w, h);
w = boxBlur<true>(dp, w, tp, hiRadius, hiRadius, w, h);
// Do three Y blurs, with a transpose on the final one.
h = boxBlur<false>(tp, h, dp, loRadius, hiRadius, h, w);
h = boxBlur<false>(dp, h, tp, hiRadius, loRadius, h, w);
h = boxBlur<true>(tp, h, dp, hiRadius, hiRadius, h, w);
} else {
w = boxBlur<true>(sp, src.fRowBytes, tp, rx, rx, w, h);
h = boxBlur<true>(tp, h, dp, ry, ry, h, w);
}
} else {
if (kHigh_SkBlurQuality == quality) {
// Do three X blurs, with a transpose on the final one.
w = boxBlurInterp<false>(sp, src.fRowBytes, tp, rx, w, h, outerWeight);
//.........这里部分代码省略.........
示例10: generateMask
static void generateMask(const SkMask& mask, const SkPath& path,
const SkMaskGamma::PreBlend& maskPreBlend) {
SkBitmap::Config config;
SkPaint paint;
int srcW = mask.fBounds.width();
int srcH = mask.fBounds.height();
int dstW = srcW;
int dstH = srcH;
int dstRB = mask.fRowBytes;
SkMatrix matrix;
matrix.setTranslate(-SkIntToScalar(mask.fBounds.fLeft),
-SkIntToScalar(mask.fBounds.fTop));
if (SkMask::kBW_Format == mask.fFormat) {
config = SkBitmap::kA1_Config;
paint.setAntiAlias(false);
} else {
config = SkBitmap::kA8_Config;
paint.setAntiAlias(true);
switch (mask.fFormat) {
case SkMask::kA8_Format:
break;
case SkMask::kLCD16_Format:
case SkMask::kLCD32_Format:
// TODO: trigger off LCD orientation
dstW *= 3;
matrix.postScale(SkIntToScalar(3), SK_Scalar1);
dstRB = 0; // signals we need a copy
break;
default:
SkDEBUGFAIL("unexpected mask format");
}
}
SkRasterClip clip;
clip.setRect(SkIRect::MakeWH(dstW, dstH));
SkBitmap bm;
bm.setConfig(config, dstW, dstH, dstRB);
if (0 == dstRB) {
if (!bm.allocPixels()) {
// can't allocate offscreen, so empty the mask and return
sk_bzero(mask.fImage, mask.computeImageSize());
return;
}
bm.lockPixels();
} else {
bm.setPixels(mask.fImage);
}
sk_bzero(bm.getPixels(), bm.getSafeSize());
SkDraw draw;
draw.fRC = &clip;
draw.fClip = &clip.bwRgn();
draw.fMatrix = &matrix;
draw.fBitmap = &bm;
draw.drawPath(path, paint);
switch (mask.fFormat) {
case SkMask::kA8_Format:
if (maskPreBlend.isApplicable()) {
applyLUTToA8Mask(mask, maskPreBlend.fG);
}
break;
case SkMask::kLCD16_Format:
if (maskPreBlend.isApplicable()) {
pack3xHToLCD16<true>(bm, mask, maskPreBlend);
} else {
pack3xHToLCD16<false>(bm, mask, maskPreBlend);
}
break;
case SkMask::kLCD32_Format:
if (maskPreBlend.isApplicable()) {
pack3xHToLCD32<true>(bm, mask, maskPreBlend);
} else {
pack3xHToLCD32<false>(bm, mask, maskPreBlend);
}
break;
default:
break;
}
}
示例11: Blur
bool SkBlurMask::Blur(SkMask* dst, const SkMask& src,
SkScalar radius, Style style, Quality quality,
SkIPoint* margin)
{
if (src.fFormat != SkMask::kA8_Format) {
return false;
}
// Force high quality off for small radii (performance)
if (radius < SkIntToScalar(3)) quality = kLow_Quality;
// highQuality: use three box blur passes as a cheap way to approximate a Gaussian blur
int passCount = (quality == kHigh_Quality) ? 3 : 1;
SkScalar passRadius = SkScalarDiv(radius, SkScalarSqrt(SkIntToScalar(passCount)));
int rx = SkScalarCeil(passRadius);
int outer_weight = 255 - SkScalarRound((SkIntToScalar(rx) - passRadius) * 255);
SkASSERT(rx >= 0);
SkASSERT((unsigned)outer_weight <= 255);
if (rx <= 0) {
return false;
}
int ry = rx; // only do square blur for now
int padx = passCount * rx;
int pady = passCount * ry;
if (margin) {
margin->set(padx, pady);
}
dst->fBounds.set(src.fBounds.fLeft - padx, src.fBounds.fTop - pady,
src.fBounds.fRight + padx, src.fBounds.fBottom + pady);
dst->fRowBytes = dst->fBounds.width();
dst->fFormat = SkMask::kA8_Format;
dst->fImage = NULL;
if (src.fImage) {
size_t dstSize = dst->computeImageSize();
if (0 == dstSize) {
return false; // too big to allocate, abort
}
int sw = src.fBounds.width();
int sh = src.fBounds.height();
const uint8_t* sp = src.fImage;
uint8_t* dp = SkMask::AllocImage(dstSize);
SkAutoTCallVProc<uint8_t, SkMask_FreeImage> autoCall(dp);
// build the blurry destination
{
const size_t storageW = sw + 2 * (passCount - 1) * rx + 1;
const size_t storageH = sh + 2 * (passCount - 1) * ry + 1;
SkAutoTMalloc<uint32_t> storage(storageW * storageH);
uint32_t* sumBuffer = storage.get();
//pass1: sp is source, dp is destination
build_sum_buffer(sumBuffer, sw, sh, sp, src.fRowBytes);
if (outer_weight == 255) {
apply_kernel(dp, rx, ry, sumBuffer, sw, sh);
} else {
apply_kernel_interp(dp, rx, ry, sumBuffer, sw, sh, outer_weight);
}
if (quality == kHigh_Quality) {
//pass2: dp is source, tmpBuffer is destination
int tmp_sw = sw + 2 * rx;
int tmp_sh = sh + 2 * ry;
SkAutoTMalloc<uint8_t> tmpBuffer(dstSize);
build_sum_buffer(sumBuffer, tmp_sw, tmp_sh, dp, tmp_sw);
if (outer_weight == 255)
apply_kernel(tmpBuffer.get(), rx, ry, sumBuffer, tmp_sw, tmp_sh);
else
apply_kernel_interp(tmpBuffer.get(), rx, ry, sumBuffer,
tmp_sw, tmp_sh, outer_weight);
//pass3: tmpBuffer is source, dp is destination
tmp_sw += 2 * rx;
tmp_sh += 2 * ry;
build_sum_buffer(sumBuffer, tmp_sw, tmp_sh, tmpBuffer.get(), tmp_sw);
if (outer_weight == 255)
apply_kernel(dp, rx, ry, sumBuffer, tmp_sw, tmp_sh);
else
apply_kernel_interp(dp, rx, ry, sumBuffer, tmp_sw, tmp_sh,
outer_weight);
}
}
dst->fImage = dp;
// if need be, alloc the "real" dst (same size as src) and copy/merge
// the blur into it (applying the src)
if (style == kInner_Style) {
// now we allocate the "real" dst, mirror the size of src
size_t srcSize = src.computeImageSize();
if (0 == srcSize) {
return false; // too big to allocate, abort
}
dst->fImage = SkMask::AllocImage(srcSize);
merge_src_with_blur(dst->fImage, src.fRowBytes,
//.........这里部分代码省略.........