本文整理汇总了C++中SkIRect::height方法的典型用法代码示例。如果您正苦于以下问题:C++ SkIRect::height方法的具体用法?C++ SkIRect::height怎么用?C++ SkIRect::height使用的例子?那么, 这里精选的方法代码示例或许可以为您提供帮助。您也可以进一步了解该方法所在类SkIRect
的用法示例。
在下文中一共展示了SkIRect::height方法的15个代码示例,这些例子默认根据受欢迎程度排序。您可以为喜欢或者感觉有用的代码点赞,您的评价将有助于系统推荐出更棒的C++代码示例。
示例1: check
static void check(skiatest::Reporter* r,
const char path[],
SkISize size,
bool supportsScanlineDecoding,
bool supportsSubsetDecoding,
bool supports565 = true) {
SkAutoTDelete<SkStream> stream(resource(path));
if (!stream) {
SkDebugf("Missing resource '%s'\n", path);
return;
}
SkAutoTDelete<SkCodec> codec(SkCodec::NewFromStream(stream.detach()));
if (!codec) {
ERRORF(r, "Unable to decode '%s'", path);
return;
}
// This test is used primarily to verify rewinding works properly. Using kN32 allows
// us to test this without the added overhead of creating different bitmaps depending
// on the color type (ex: building a color table for kIndex8). DM is where we test
// decodes to all possible destination color types.
SkImageInfo info = codec->getInfo().makeColorType(kN32_SkColorType);
REPORTER_ASSERT(r, info.dimensions() == size);
{
// Test decoding to 565
SkImageInfo info565 = info.makeColorType(kRGB_565_SkColorType);
SkCodec::Result expected = (supports565 && info.alphaType() == kOpaque_SkAlphaType) ?
SkCodec::kSuccess : SkCodec::kInvalidConversion;
test_info(r, codec, info565, expected, nullptr);
}
SkBitmap bm;
bm.allocPixels(info);
SkAutoLockPixels autoLockPixels(bm);
SkCodec::Result result =
codec->getPixels(info, bm.getPixels(), bm.rowBytes(), nullptr, nullptr, nullptr);
REPORTER_ASSERT(r, result == SkCodec::kSuccess);
SkMD5::Digest digest;
md5(bm, &digest);
// verify that re-decoding gives the same result.
test_info(r, codec, info, SkCodec::kSuccess, &digest);
{
// Check alpha type conversions
if (info.alphaType() == kOpaque_SkAlphaType) {
test_info(r, codec, info.makeAlphaType(kUnpremul_SkAlphaType),
SkCodec::kInvalidConversion, nullptr);
test_info(r, codec, info.makeAlphaType(kPremul_SkAlphaType),
SkCodec::kInvalidConversion, nullptr);
} else {
// Decoding to opaque should fail
test_info(r, codec, info.makeAlphaType(kOpaque_SkAlphaType),
SkCodec::kInvalidConversion, nullptr);
SkAlphaType otherAt = info.alphaType();
if (kPremul_SkAlphaType == otherAt) {
otherAt = kUnpremul_SkAlphaType;
} else {
otherAt = kPremul_SkAlphaType;
}
// The other non-opaque alpha type should always succeed, but not match.
test_info(r, codec, info.makeAlphaType(otherAt), SkCodec::kSuccess, nullptr);
}
}
// Scanline decoding follows.
stream.reset(resource(path));
SkAutoTDelete<SkScanlineDecoder> scanlineDecoder(
SkScanlineDecoder::NewFromStream(stream.detach()));
if (supportsScanlineDecoding) {
bm.eraseColor(SK_ColorYELLOW);
REPORTER_ASSERT(r, scanlineDecoder);
REPORTER_ASSERT(r, scanlineDecoder->start(info) == SkCodec::kSuccess);
for (int y = 0; y < info.height(); y++) {
result = scanlineDecoder->getScanlines(bm.getAddr(0, y), 1, 0);
REPORTER_ASSERT(r, result == SkCodec::kSuccess);
}
// verify that scanline decoding gives the same result.
if (SkScanlineDecoder::kTopDown_SkScanlineOrder == scanlineDecoder->getScanlineOrder()) {
compare_to_good_digest(r, digest, bm);
}
} else {
REPORTER_ASSERT(r, !scanlineDecoder);
}
// The rest of this function tests decoding subsets, and will decode an arbitrary number of
// random subsets.
// Do not attempt to decode subsets of an image of only once pixel, since there is no
// meaningful subset.
if (size.width() * size.height() == 1) {
return;
}
SkRandom rand;
SkIRect subset;
//.........这里部分代码省略.........
示例2:
// Get the margin (aka perimeter)
static inline uint32_t get_margin(const SkIRect& rect) {
return 2 * (rect.width() + rect.height());
}
示例3: SkASSERT
SkLatticeIter::SkLatticeIter(const SkCanvas::Lattice& lattice, const SkRect& dst) {
const int* xDivs = lattice.fXDivs;
const int origXCount = lattice.fXCount;
const int* yDivs = lattice.fYDivs;
const int origYCount = lattice.fYCount;
SkASSERT(lattice.fBounds);
const SkIRect src = *lattice.fBounds;
// In the x-dimension, the first rectangle always starts at x = 0 and is "scalable".
// If xDiv[0] is 0, it indicates that the first rectangle is degenerate, so the
// first real rectangle "scalable" in the x-direction.
//
// The same interpretation applies to the y-dimension.
//
// As we move left to right across the image, alternating patches will be "fixed" or
// "scalable" in the x-direction. Similarly, as move top to bottom, alternating
// patches will be "fixed" or "scalable" in the y-direction.
int xCount = origXCount;
int yCount = origYCount;
bool xIsScalable = (xCount > 0 && src.fLeft == xDivs[0]);
if (xIsScalable) {
// Once we've decided that the first patch is "scalable", we don't need the
// xDiv. It is always implied that we start at the edge of the bounds.
xDivs++;
xCount--;
}
bool yIsScalable = (yCount > 0 && src.fTop == yDivs[0]);
if (yIsScalable) {
// Once we've decided that the first patch is "scalable", we don't need the
// yDiv. It is always implied that we start at the edge of the bounds.
yDivs++;
yCount--;
}
// Count "scalable" and "fixed" pixels in each dimension.
int xCountScalable = count_scalable_pixels(xDivs, xCount, xIsScalable, src.fLeft, src.fRight);
int xCountFixed = src.width() - xCountScalable;
int yCountScalable = count_scalable_pixels(yDivs, yCount, yIsScalable, src.fTop, src.fBottom);
int yCountFixed = src.height() - yCountScalable;
fSrcX.reset(xCount + 2);
fDstX.reset(xCount + 2);
set_points(fDstX.begin(), fSrcX.begin(), xDivs, xCount, xCountFixed, xCountScalable,
src.fLeft, src.fRight, dst.fLeft, dst.fRight, xIsScalable);
fSrcY.reset(yCount + 2);
fDstY.reset(yCount + 2);
set_points(fDstY.begin(), fSrcY.begin(), yDivs, yCount, yCountFixed, yCountScalable,
src.fTop, src.fBottom, dst.fTop, dst.fBottom, yIsScalable);
fCurrX = fCurrY = 0;
fNumRectsInLattice = (xCount + 1) * (yCount + 1);
fNumRectsToDraw = fNumRectsInLattice;
if (lattice.fFlags) {
fFlags.push_back_n(fNumRectsInLattice);
const SkCanvas::Lattice::Flags* flags = lattice.fFlags;
bool hasPadRow = (yCount != origYCount);
bool hasPadCol = (xCount != origXCount);
if (hasPadRow) {
// The first row of rects are all empty, skip the first row of flags.
flags += origXCount + 1;
}
int i = 0;
for (int y = 0; y < yCount + 1; y++) {
for (int x = 0; x < origXCount + 1; x++) {
if (0 == x && hasPadCol) {
// The first column of rects are all empty. Skip a rect.
flags++;
continue;
}
fFlags[i] = *flags;
flags++;
i++;
}
}
for (int j = 0; j < fFlags.count(); j++) {
if (SkCanvas::Lattice::kTransparent_Flags == fFlags[j]) {
fNumRectsToDraw--;
}
}
}
}
示例4: draw_nine_clipped
static void draw_nine_clipped(const SkMask& mask, const SkIRect& outerR,
const SkIPoint& center, bool fillCenter,
const SkIRect& clipR, SkBlitter* blitter) {
int cx = center.x();
int cy = center.y();
SkMask m;
// top-left
m.fBounds = mask.fBounds;
m.fBounds.fRight = cx;
m.fBounds.fBottom = cy;
extractMaskSubset(mask, &m);
m.fBounds.offsetTo(outerR.left(), outerR.top());
blitClippedMask(blitter, m, m.fBounds, clipR);
// top-right
m.fBounds = mask.fBounds;
m.fBounds.fLeft = cx + 1;
m.fBounds.fBottom = cy;
extractMaskSubset(mask, &m);
m.fBounds.offsetTo(outerR.right() - m.fBounds.width(), outerR.top());
blitClippedMask(blitter, m, m.fBounds, clipR);
// bottom-left
m.fBounds = mask.fBounds;
m.fBounds.fRight = cx;
m.fBounds.fTop = cy + 1;
extractMaskSubset(mask, &m);
m.fBounds.offsetTo(outerR.left(), outerR.bottom() - m.fBounds.height());
blitClippedMask(blitter, m, m.fBounds, clipR);
// bottom-right
m.fBounds = mask.fBounds;
m.fBounds.fLeft = cx + 1;
m.fBounds.fTop = cy + 1;
extractMaskSubset(mask, &m);
m.fBounds.offsetTo(outerR.right() - m.fBounds.width(),
outerR.bottom() - m.fBounds.height());
blitClippedMask(blitter, m, m.fBounds, clipR);
SkIRect innerR;
innerR.set(outerR.left() + cx - mask.fBounds.left(),
outerR.top() + cy - mask.fBounds.top(),
outerR.right() + (cx + 1 - mask.fBounds.right()),
outerR.bottom() + (cy + 1 - mask.fBounds.bottom()));
if (fillCenter) {
blitClippedRect(blitter, innerR, clipR);
}
const int innerW = innerR.width();
size_t storageSize = (innerW + 1) * (sizeof(int16_t) + sizeof(uint8_t));
SkAutoSMalloc<4*1024> storage(storageSize);
int16_t* runs = (int16_t*)storage.get();
uint8_t* alpha = (uint8_t*)(runs + innerW + 1);
SkIRect r;
// top
r.set(innerR.left(), outerR.top(), innerR.right(), innerR.top());
if (r.intersect(clipR)) {
int startY = SkMax32(0, r.top() - outerR.top());
int stopY = startY + r.height();
int width = r.width();
for (int y = startY; y < stopY; ++y) {
runs[0] = width;
runs[width] = 0;
alpha[0] = *mask.getAddr8(cx, mask.fBounds.top() + y);
blitter->blitAntiH(r.left(), outerR.top() + y, alpha, runs);
}
}
// bottom
r.set(innerR.left(), innerR.bottom(), innerR.right(), outerR.bottom());
if (r.intersect(clipR)) {
int startY = outerR.bottom() - r.bottom();
int stopY = startY + r.height();
int width = r.width();
for (int y = startY; y < stopY; ++y) {
runs[0] = width;
runs[width] = 0;
alpha[0] = *mask.getAddr8(cx, mask.fBounds.bottom() - y - 1);
blitter->blitAntiH(r.left(), outerR.bottom() - y - 1, alpha, runs);
}
}
// left
r.set(outerR.left(), innerR.top(), innerR.left(), innerR.bottom());
if (r.intersect(clipR)) {
int startX = r.left() - outerR.left();
int stopX = startX + r.width();
int height = r.height();
for (int x = startX; x < stopX; ++x) {
blitter->blitV(outerR.left() + x, r.top(), height,
*mask.getAddr8(mask.fBounds.left() + x, mask.fBounds.top() + cy));
}
}
// right
r.set(innerR.right(), innerR.top(), outerR.right(), innerR.bottom());
if (r.intersect(clipR)) {
int startX = outerR.right() - r.right();
int stopX = startX + r.width();
int height = r.height();
for (int x = startX; x < stopX; ++x) {
//.........这里部分代码省略.........
示例5: filterImageGeneric
bool SkMorphologyImageFilter::filterImageGeneric(SkMorphologyImageFilter::Proc procX,
SkMorphologyImageFilter::Proc procY,
Proxy* proxy,
const SkBitmap& source,
const Context& ctx,
SkBitmap* dst,
SkIPoint* offset) const {
SkBitmap src = source;
SkIPoint srcOffset = SkIPoint::Make(0, 0);
if (getInput(0) && !getInput(0)->filterImage(proxy, source, ctx, &src, &srcOffset)) {
return false;
}
if (src.colorType() != kN32_SkColorType) {
return false;
}
SkIRect bounds;
if (!this->applyCropRect(ctx, proxy, src, &srcOffset, &bounds, &src)) {
return false;
}
SkAutoLockPixels alp(src);
if (!src.getPixels()) {
return false;
}
if (!dst->tryAllocPixels(src.info().makeWH(bounds.width(), bounds.height()))) {
return false;
}
SkVector radius = SkVector::Make(SkIntToScalar(this->radius().width()),
SkIntToScalar(this->radius().height()));
ctx.ctm().mapVectors(&radius, 1);
int width = SkScalarFloorToInt(radius.fX);
int height = SkScalarFloorToInt(radius.fY);
if (width < 0 || height < 0) {
return false;
}
SkIRect srcBounds = bounds;
srcBounds.offset(-srcOffset);
if (width == 0 && height == 0) {
src.extractSubset(dst, srcBounds);
offset->fX = bounds.left();
offset->fY = bounds.top();
return true;
}
SkBitmap temp;
if (!temp.tryAllocPixels(dst->info())) {
return false;
}
if (width > 0 && height > 0) {
callProcX(procX, src, &temp, width, srcBounds);
SkIRect tmpBounds = SkIRect::MakeWH(srcBounds.width(), srcBounds.height());
callProcY(procY, temp, dst, height, tmpBounds);
} else if (width > 0) {
callProcX(procX, src, dst, width, srcBounds);
} else if (height > 0) {
callProcY(procY, src, dst, height, srcBounds);
}
offset->fX = bounds.left();
offset->fY = bounds.top();
return true;
}
示例6: drawPattern
void Image::drawPattern(GraphicsContext* context,
const FloatRect& floatSrcRect,
const AffineTransform& patternTransform,
const FloatPoint& phase,
ColorSpace styleColorSpace,
CompositeOperator compositeOp,
const FloatRect& destRect)
{
FloatRect normSrcRect = normalizeRect(floatSrcRect);
if (destRect.isEmpty() || normSrcRect.isEmpty())
return; // nothing to draw
NativeImageSkia* bitmap = nativeImageForCurrentFrame();
if (!bitmap)
return;
SkIRect srcRect = enclosingIntRect(normSrcRect);
// Figure out what size the bitmap will be in the destination. The
// destination rect is the bounds of the pattern, we need to use the
// matrix to see how big it will be.
float destBitmapWidth, destBitmapHeight;
TransformDimensions(patternTransform, srcRect.width(), srcRect.height(),
&destBitmapWidth, &destBitmapHeight);
// Compute the resampling mode.
ResamplingMode resampling;
if (context->platformContext()->isAccelerated() || context->platformContext()->printing())
resampling = RESAMPLE_LINEAR;
else
resampling = computeResamplingMode(context->platformContext(), *bitmap, srcRect.width(), srcRect.height(), destBitmapWidth, destBitmapHeight);
// Load the transform WebKit requested.
SkMatrix matrix(patternTransform);
SkShader* shader;
if (resampling == RESAMPLE_AWESOME) {
// Do nice resampling.
int width = static_cast<int>(destBitmapWidth);
int height = static_cast<int>(destBitmapHeight);
SkBitmap resampled = bitmap->resizedBitmap(srcRect, width, height);
shader = SkShader::CreateBitmapShader(resampled, SkShader::kRepeat_TileMode, SkShader::kRepeat_TileMode);
// Since we just resized the bitmap, we need to undo the scale set in
// the image transform.
matrix.setScaleX(SkIntToScalar(1));
matrix.setScaleY(SkIntToScalar(1));
} else {
// No need to do nice resampling.
SkBitmap srcSubset;
bitmap->bitmap().extractSubset(&srcSubset, srcRect);
shader = SkShader::CreateBitmapShader(srcSubset, SkShader::kRepeat_TileMode, SkShader::kRepeat_TileMode);
}
// We also need to translate it such that the origin of the pattern is the
// origin of the destination rect, which is what WebKit expects. Skia uses
// the coordinate system origin as the base for the patter. If WebKit wants
// a shifted image, it will shift it from there using the patternTransform.
float adjustedX = phase.x() + normSrcRect.x() *
narrowPrecisionToFloat(patternTransform.a());
float adjustedY = phase.y() + normSrcRect.y() *
narrowPrecisionToFloat(patternTransform.d());
matrix.postTranslate(SkFloatToScalar(adjustedX),
SkFloatToScalar(adjustedY));
shader->setLocalMatrix(matrix);
SkPaint paint;
paint.setShader(shader)->unref();
paint.setXfermodeMode(WebCoreCompositeToSkiaComposite(compositeOp));
paint.setFilterBitmap(resampling == RESAMPLE_LINEAR);
context->platformContext()->paintSkPaint(destRect, paint);
}
示例7: unpremultiply_bitmap
static SkBitmap unpremultiply_bitmap(const SkBitmap& bitmap,
const SkIRect& srcRect) {
SkBitmap outBitmap;
outBitmap.allocPixels(bitmap.info().makeWH(srcRect.width(), srcRect.height()));
int dstRow = 0;
SkAutoLockPixels outBitmapPixelLock(outBitmap);
SkAutoLockPixels bitmapPixelLock(bitmap);
switch (bitmap.colorType()) {
case kARGB_4444_SkColorType: {
for (int y = srcRect.fTop; y < srcRect.fBottom; y++) {
uint16_t* dst = outBitmap.getAddr16(0, dstRow);
uint16_t* src = bitmap.getAddr16(0, y);
for (int x = srcRect.fLeft; x < srcRect.fRight; x++) {
uint8_t a = SkGetPackedA4444(src[x]);
// It is necessary to average the color component of
// transparent pixels with their surrounding neighbors
// since the PDF renderer may separately re-sample the
// alpha and color channels when the image is not
// displayed at its native resolution. Since an alpha of
// zero gives no information about the color component,
// the pathological case is a white image with sharp
// transparency bounds - the color channel goes to black,
// and the should-be-transparent pixels are rendered
// as grey because of the separate soft mask and color
// resizing.
if (a == (SK_AlphaTRANSPARENT & 0x0F)) {
*dst = get_argb4444_neighbor_avg_color(bitmap, x, y);
} else {
*dst = remove_alpha_argb4444(src[x]);
}
dst++;
}
dstRow++;
}
break;
}
case kN32_SkColorType: {
for (int y = srcRect.fTop; y < srcRect.fBottom; y++) {
uint32_t* dst = outBitmap.getAddr32(0, dstRow);
uint32_t* src = bitmap.getAddr32(0, y);
for (int x = srcRect.fLeft; x < srcRect.fRight; x++) {
uint8_t a = SkGetPackedA32(src[x]);
if (a == SK_AlphaTRANSPARENT) {
*dst = get_argb8888_neighbor_avg_color(bitmap, x, y);
} else {
*dst = remove_alpha_argb8888(src[x]);
}
dst++;
}
dstRow++;
}
break;
}
default:
SkASSERT(false);
}
outBitmap.setImmutable();
return outBitmap;
}
示例8: openLibResult
DEF_TEST(CanvasState_test_complex_clips, reporter) {
const int WIDTH = 400;
const int HEIGHT = 400;
const int SPACER = 10;
SkIRect layerRect = SkIRect::MakeWH(WIDTH, HEIGHT / 4);
layerRect.inset(2*SPACER, 2*SPACER);
SkIRect clipRect = layerRect;
clipRect.fRight = clipRect.fLeft + (clipRect.width() / 2) - (2*SPACER);
clipRect.outset(SPACER, SPACER);
SkIRect regionBounds = clipRect;
regionBounds.offset(clipRect.width() + (2*SPACER), 0);
SkIRect regionInterior = regionBounds;
regionInterior.inset(SPACER*3, SPACER*3);
SkRegion clipRegion;
clipRegion.setRect(regionBounds);
clipRegion.op(regionInterior, SkRegion::kDifference_Op);
const SkRegion::Op clipOps[] = { SkRegion::kIntersect_Op,
SkRegion::kIntersect_Op,
SkRegion::kReplace_Op,
};
const SkCanvas::SaveFlags flags[] = { SkCanvas::kARGB_NoClipLayer_SaveFlag,
SkCanvas::kARGB_ClipLayer_SaveFlag,
SkCanvas::kARGB_NoClipLayer_SaveFlag,
};
REPORTER_ASSERT(reporter, sizeof(clipOps) == sizeof(flags));
bool (*drawFn)(SkCanvasState* state, int32_t l, int32_t t,
int32_t r, int32_t b, int32_t clipOp,
int32_t regionRects, int32_t* rectCoords);
OpenLibResult openLibResult(reporter);
if (openLibResult.handle() != NULL) {
*(void**) (&drawFn) = dlsym(openLibResult.handle(),
"complex_clips_draw_from_canvas_state");
} else {
drawFn = complex_clips_draw_from_canvas_state;
}
REPORTER_ASSERT(reporter, drawFn);
if (!drawFn) {
return;
}
SkBitmap bitmaps[2];
for (int i = 0; i < 2; ++i) {
bitmaps[i].allocN32Pixels(WIDTH, HEIGHT);
SkCanvas canvas(bitmaps[i]);
canvas.drawColor(SK_ColorRED);
SkRegion localRegion = clipRegion;
for (size_t j = 0; j < SK_ARRAY_COUNT(flags); ++j) {
SkRect layerBounds = SkRect::Make(layerRect);
canvas.saveLayerAlpha(&layerBounds, 128, flags[j]);
if (i) {
SkCanvasState* state = SkCanvasStateUtils::CaptureCanvasState(&canvas);
REPORTER_ASSERT(reporter, state);
SkRegion::Iterator iter(localRegion);
SkTDArray<int32_t> rectCoords;
for (; !iter.done(); iter.next()) {
const SkIRect& rect = iter.rect();
*rectCoords.append() = rect.fLeft;
*rectCoords.append() = rect.fTop;
*rectCoords.append() = rect.fRight;
*rectCoords.append() = rect.fBottom;
}
bool success = drawFn(state, clipRect.fLeft, clipRect.fTop,
clipRect.fRight, clipRect.fBottom, clipOps[j],
rectCoords.count() / 4, rectCoords.begin());
REPORTER_ASSERT(reporter, success);
SkCanvasStateUtils::ReleaseCanvasState(state);
} else {
complex_clips_draw(&canvas, clipRect.fLeft, clipRect.fTop,
clipRect.fRight, clipRect.fBottom, clipOps[j],
localRegion);
}
canvas.restore();
// translate the canvas and region for the next iteration
canvas.translate(0, SkIntToScalar(2*(layerRect.height() + (SPACER))));
localRegion.translate(0, 2*(layerRect.height() + SPACER));
}
}
// now we memcmp the two bitmaps
REPORTER_ASSERT(reporter, bitmaps[0].getSize() == bitmaps[1].getSize());
REPORTER_ASSERT(reporter, !memcmp(bitmaps[0].getPixels(),
//.........这里部分代码省略.........
示例9: test_complex_clips
static void test_complex_clips(skiatest::Reporter* reporter) {
#ifdef SK_SUPPORT_LEGACY_CLIPTOLAYERFLAG
const int WIDTH = 400;
const int HEIGHT = 400;
const int SPACER = 10;
SkIRect layerRect = SkIRect::MakeWH(WIDTH, HEIGHT / 4);
layerRect.inset(2*SPACER, 2*SPACER);
SkIRect clipRect = layerRect;
clipRect.fRight = clipRect.fLeft + (clipRect.width() / 2) - (2*SPACER);
clipRect.outset(SPACER, SPACER);
SkIRect regionBounds = clipRect;
regionBounds.offset(clipRect.width() + (2*SPACER), 0);
SkIRect regionInterior = regionBounds;
regionInterior.inset(SPACER*3, SPACER*3);
SkRegion clipRegion;
clipRegion.setRect(regionBounds);
clipRegion.op(regionInterior, SkRegion::kDifference_Op);
const SkRegion::Op clipOps[] = { SkRegion::kIntersect_Op,
SkRegion::kIntersect_Op,
SkRegion::kReplace_Op,
};
const SkCanvas::SaveFlags flags[] = { SkCanvas::kARGB_NoClipLayer_SaveFlag,
SkCanvas::kARGB_ClipLayer_SaveFlag,
SkCanvas::kARGB_NoClipLayer_SaveFlag,
};
REPORTER_ASSERT(reporter, sizeof(clipOps) == sizeof(flags));
const int layerCombinations = sizeof(flags) / sizeof(SkCanvas::SaveFlags);
SkBitmap bitmaps[2];
for (int i = 0; i < 2; ++i) {
bitmaps[i].allocN32Pixels(WIDTH, HEIGHT);
SkCanvas canvas(bitmaps[i]);
canvas.drawColor(SK_ColorRED);
SkRegion localRegion = clipRegion;
for (int j = 0; j < layerCombinations; ++j) {
SkRect layerBounds = SkRect::Make(layerRect);
canvas.saveLayerAlpha(&layerBounds, 128, flags[j]);
SkCanvasState* state = NULL;
SkCanvas* tmpCanvas = NULL;
if (i) {
state = SkCanvasStateUtils::CaptureCanvasState(&canvas);
REPORTER_ASSERT(reporter, state);
tmpCanvas = SkCanvasStateUtils::CreateFromCanvasState(state);
REPORTER_ASSERT(reporter, tmpCanvas);
} else {
tmpCanvas = SkRef(&canvas);
}
tmpCanvas->save();
tmpCanvas->clipRect(SkRect::Make(clipRect), clipOps[j]);
tmpCanvas->drawColor(SK_ColorBLUE);
tmpCanvas->restore();
tmpCanvas->clipRegion(localRegion, clipOps[j]);
tmpCanvas->drawColor(SK_ColorBLUE);
tmpCanvas->unref();
SkCanvasStateUtils::ReleaseCanvasState(state);
canvas.restore();
// translate the canvas and region for the next iteration
canvas.translate(0, SkIntToScalar(2*(layerRect.height() + (SPACER))));
localRegion.translate(0, 2*(layerRect.height() + SPACER));
}
}
// now we memcmp the two bitmaps
REPORTER_ASSERT(reporter, bitmaps[0].getSize() == bitmaps[1].getSize());
REPORTER_ASSERT(reporter, !memcmp(bitmaps[0].getPixels(),
bitmaps[1].getPixels(),
bitmaps[0].getSize()));
#endif
}
示例10: test_image
// Basic test of the SkSpecialImage public API (e.g., peekTexture, peekPixels & draw)
static void test_image(const sk_sp<SkSpecialImage>& img, skiatest::Reporter* reporter,
GrContext* context, bool peekTextureSucceeds,
int offset, int size) {
const SkIRect subset = img->subset();
REPORTER_ASSERT(reporter, offset == subset.left());
REPORTER_ASSERT(reporter, offset == subset.top());
REPORTER_ASSERT(reporter, kSmallerSize == subset.width());
REPORTER_ASSERT(reporter, kSmallerSize == subset.height());
//--------------
// Test that peekTexture reports the correct backing type
REPORTER_ASSERT(reporter, peekTextureSucceeds == img->isTextureBacked());
#if SK_SUPPORT_GPU
//--------------
// Test getTextureAsRef - as long as there is a context this should succeed
if (context) {
sk_sp<GrTexture> texture(img->asTextureRef(context));
REPORTER_ASSERT(reporter, texture);
}
#endif
//--------------
// Test getROPixels - this should always succeed regardless of backing store
SkBitmap bitmap;
REPORTER_ASSERT(reporter, img->getROPixels(&bitmap));
if (context) {
REPORTER_ASSERT(reporter, kSmallerSize == bitmap.width());
REPORTER_ASSERT(reporter, kSmallerSize == bitmap.height());
} else {
REPORTER_ASSERT(reporter, size == bitmap.width());
REPORTER_ASSERT(reporter, size == bitmap.height());
}
//--------------
// Test that draw restricts itself to the subset
SkImageInfo info = SkImageInfo::MakeN32(kFullSize, kFullSize, kOpaque_SkAlphaType);
sk_sp<SkSpecialSurface> surf(img->makeSurface(info));
SkCanvas* canvas = surf->getCanvas();
canvas->clear(SK_ColorBLUE);
img->draw(canvas, SkIntToScalar(kPad), SkIntToScalar(kPad), nullptr);
SkBitmap bm;
bm.allocN32Pixels(kFullSize, kFullSize, true);
bool result = canvas->readPixels(bm.info(), bm.getPixels(), bm.rowBytes(), 0, 0);
SkASSERT_RELEASE(result);
// Only the center (red) portion should've been drawn into the canvas
REPORTER_ASSERT(reporter, SK_ColorBLUE == bm.getColor(kPad-1, kPad-1));
REPORTER_ASSERT(reporter, SK_ColorRED == bm.getColor(kPad, kPad));
REPORTER_ASSERT(reporter, SK_ColorRED == bm.getColor(kSmallerSize+kPad-1,
kSmallerSize+kPad-1));
REPORTER_ASSERT(reporter, SK_ColorBLUE == bm.getColor(kSmallerSize+kPad,
kSmallerSize+kPad));
//--------------
// Test that makeTightSubset & makeTightSurface return appropriately sized objects
// of the correct backing type
SkIRect newSubset = SkIRect::MakeWH(subset.width(), subset.height());
{
sk_sp<SkImage> tightImg(img->makeTightSubset(newSubset));
REPORTER_ASSERT(reporter, tightImg->width() == subset.width());
REPORTER_ASSERT(reporter, tightImg->height() == subset.height());
REPORTER_ASSERT(reporter, peekTextureSucceeds == !!tightImg->getTexture());
SkPixmap tmpPixmap;
REPORTER_ASSERT(reporter, peekTextureSucceeds != !!tightImg->peekPixels(&tmpPixmap));
}
{
SkImageInfo info = SkImageInfo::MakeN32(subset.width(), subset.height(),
kPremul_SkAlphaType);
sk_sp<SkSurface> tightSurf(img->makeTightSurface(info));
REPORTER_ASSERT(reporter, tightSurf->width() == subset.width());
REPORTER_ASSERT(reporter, tightSurf->height() == subset.height());
REPORTER_ASSERT(reporter, peekTextureSucceeds ==
!!tightSurf->getTextureHandle(SkSurface::kDiscardWrite_BackendHandleAccess));
SkPixmap tmpPixmap;
REPORTER_ASSERT(reporter, peekTextureSucceeds != !!tightSurf->peekPixels(&tmpPixmap));
}
}
示例11: onFilterImageDeprecated
bool SkBlurImageFilter::onFilterImageDeprecated(Proxy* proxy,
const SkBitmap& source, const Context& ctx,
SkBitmap* dst, SkIPoint* offset) const {
SkBitmap src = source;
SkIPoint srcOffset = SkIPoint::Make(0, 0);
if (!this->filterInputDeprecated(0, proxy, source, ctx, &src, &srcOffset)) {
return false;
}
if (src.colorType() != kN32_SkColorType) {
return false;
}
SkIRect srcBounds = src.bounds();
srcBounds.offset(srcOffset);
SkIRect dstBounds;
if (!this->applyCropRect(this->mapContext(ctx), srcBounds, &dstBounds)) {
return false;
}
if (!srcBounds.intersect(dstBounds)) {
return false;
}
SkVector sigma = map_sigma(fSigma, ctx.ctm());
int kernelSizeX, kernelSizeX3, lowOffsetX, highOffsetX;
int kernelSizeY, kernelSizeY3, lowOffsetY, highOffsetY;
getBox3Params(sigma.x(), &kernelSizeX, &kernelSizeX3, &lowOffsetX, &highOffsetX);
getBox3Params(sigma.y(), &kernelSizeY, &kernelSizeY3, &lowOffsetY, &highOffsetY);
if (kernelSizeX < 0 || kernelSizeY < 0) {
return false;
}
if (kernelSizeX == 0 && kernelSizeY == 0) {
src.extractSubset(dst, srcBounds);
offset->fX = srcBounds.x();
offset->fY = srcBounds.y();
return true;
}
SkAutoLockPixels alp(src);
if (!src.getPixels()) {
return false;
}
SkAutoTUnref<SkBaseDevice> device(proxy->createDevice(dstBounds.width(), dstBounds.height()));
if (!device) {
return false;
}
*dst = device->accessBitmap(false);
SkAutoLockPixels alp_dst(*dst);
SkAutoTUnref<SkBaseDevice> tempDevice(proxy->createDevice(dst->width(), dst->height()));
if (!tempDevice) {
return false;
}
SkBitmap temp = tempDevice->accessBitmap(false);
SkAutoLockPixels alpTemp(temp);
offset->fX = dstBounds.fLeft;
offset->fY = dstBounds.fTop;
SkPMColor* t = temp.getAddr32(0, 0);
SkPMColor* d = dst->getAddr32(0, 0);
int w = dstBounds.width(), h = dstBounds.height();
const SkPMColor* s = src.getAddr32(srcBounds.x() - srcOffset.x(), srcBounds.y() - srcOffset.y());
srcBounds.offset(-dstBounds.x(), -dstBounds.y());
dstBounds.offset(-dstBounds.x(), -dstBounds.y());
SkIRect srcBoundsT = SkIRect::MakeLTRB(srcBounds.top(), srcBounds.left(), srcBounds.bottom(), srcBounds.right());
SkIRect dstBoundsT = SkIRect::MakeWH(dstBounds.height(), dstBounds.width());
int sw = src.rowBytesAsPixels();
/**
*
* In order to make memory accesses cache-friendly, we reorder the passes to
* use contiguous memory reads wherever possible.
*
* For example, the 6 passes of the X-and-Y blur case are rewritten as
* follows. Instead of 3 passes in X and 3 passes in Y, we perform
* 2 passes in X, 1 pass in X transposed to Y on write, 2 passes in X,
* then 1 pass in X transposed to Y on write.
*
* +----+ +----+ +----+ +---+ +---+ +---+ +----+
* + AB + ----> | AB | ----> | AB | -----> | A | ----> | A | ----> | A | -----> | AB |
* +----+ blurX +----+ blurX +----+ blurXY | B | blurX | B | blurX | B | blurXY +----+
* +---+ +---+ +---+
*
* In this way, two of the y-blurs become x-blurs applied to transposed
* images, and all memory reads are contiguous.
*/
if (kernelSizeX > 0 && kernelSizeY > 0) {
SkOpts::box_blur_xx(s, sw, srcBounds, t, kernelSizeX, lowOffsetX, highOffsetX, w, h);
SkOpts::box_blur_xx(t, w, dstBounds, d, kernelSizeX, highOffsetX, lowOffsetX, w, h);
SkOpts::box_blur_xy(d, w, dstBounds, t, kernelSizeX3, highOffsetX, highOffsetX, w, h);
SkOpts::box_blur_xx(t, h, dstBoundsT, d, kernelSizeY, lowOffsetY, highOffsetY, h, w);
SkOpts::box_blur_xx(d, h, dstBoundsT, t, kernelSizeY, highOffsetY, lowOffsetY, h, w);
SkOpts::box_blur_xy(t, h, dstBoundsT, d, kernelSizeY3, highOffsetY, highOffsetY, h, w);
} else if (kernelSizeX > 0) {
SkOpts::box_blur_xx(s, sw, srcBounds, d, kernelSizeX, lowOffsetX, highOffsetX, w, h);
SkOpts::box_blur_xx(d, w, dstBounds, t, kernelSizeX, highOffsetX, lowOffsetX, w, h);
//.........这里部分代码省略.........
示例12: helper
sk_sp<GrTexture> GrClipMaskManager::CreateSoftwareClipMask(
GrTextureProvider* texProvider,
int32_t elementsGenID,
GrReducedClip::InitialState initialState,
const GrReducedClip::ElementList& elements,
const SkVector& clipToMaskOffset,
const SkIRect& clipSpaceIBounds) {
GrUniqueKey key;
GetClipMaskKey(elementsGenID, clipSpaceIBounds, &key);
if (GrTexture* texture = texProvider->findAndRefTextureByUniqueKey(key)) {
return sk_sp<GrTexture>(texture);
}
// The mask texture may be larger than necessary. We round out the clip space bounds and pin
// the top left corner of the resulting rect to the top left of the texture.
SkIRect maskSpaceIBounds = SkIRect::MakeWH(clipSpaceIBounds.width(), clipSpaceIBounds.height());
GrSWMaskHelper helper(texProvider);
// Set the matrix so that rendered clip elements are transformed to mask space from clip
// space.
SkMatrix translate;
translate.setTranslate(clipToMaskOffset);
helper.init(maskSpaceIBounds, &translate);
helper.clear(GrReducedClip::kAllIn_InitialState == initialState ? 0xFF : 0x00);
for (GrReducedClip::ElementList::Iter iter(elements.headIter()) ; iter.get(); iter.next()) {
const Element* element = iter.get();
SkRegion::Op op = element->getOp();
if (SkRegion::kIntersect_Op == op || SkRegion::kReverseDifference_Op == op) {
// Intersect and reverse difference require modifying pixels outside of the geometry
// that is being "drawn". In both cases we erase all the pixels outside of the geometry
// but leave the pixels inside the geometry alone. For reverse difference we invert all
// the pixels before clearing the ones outside the geometry.
if (SkRegion::kReverseDifference_Op == op) {
SkRect temp = SkRect::Make(clipSpaceIBounds);
// invert the entire scene
helper.drawRect(temp, SkRegion::kXOR_Op, false, 0xFF);
}
SkPath clipPath;
element->asPath(&clipPath);
clipPath.toggleInverseFillType();
GrShape shape(clipPath, GrStyle::SimpleFill());
helper.drawShape(shape, SkRegion::kReplace_Op, element->isAA(), 0x00);
continue;
}
// The other ops (union, xor, diff) only affect pixels inside
// the geometry so they can just be drawn normally
if (Element::kRect_Type == element->getType()) {
helper.drawRect(element->getRect(), op, element->isAA(), 0xFF);
} else {
SkPath path;
element->asPath(&path);
GrShape shape(path, GrStyle::SimpleFill());
helper.drawShape(shape, op, element->isAA(), 0xFF);
}
}
// Allocate clip mask texture
GrSurfaceDesc desc;
desc.fWidth = clipSpaceIBounds.width();
desc.fHeight = clipSpaceIBounds.height();
desc.fConfig = kAlpha_8_GrPixelConfig;
sk_sp<GrTexture> result(texProvider->createApproxTexture(desc));
if (!result) {
return nullptr;
}
result->resourcePriv().setUniqueKey(key);
helper.toTexture(result.get());
return result;
}
示例13: clip
sk_sp<GrTexture> GrClipMaskManager::CreateAlphaClipMask(GrContext* context,
int32_t elementsGenID,
GrReducedClip::InitialState initialState,
const GrReducedClip::ElementList& elements,
const SkVector& clipToMaskOffset,
const SkIRect& clipSpaceIBounds) {
GrResourceProvider* resourceProvider = context->resourceProvider();
GrUniqueKey key;
GetClipMaskKey(elementsGenID, clipSpaceIBounds, &key);
if (GrTexture* texture = resourceProvider->findAndRefTextureByUniqueKey(key)) {
return sk_sp<GrTexture>(texture);
}
// There's no texture in the cache. Let's try to allocate it then.
GrPixelConfig config = kRGBA_8888_GrPixelConfig;
if (context->caps()->isConfigRenderable(kAlpha_8_GrPixelConfig, false)) {
config = kAlpha_8_GrPixelConfig;
}
sk_sp<GrDrawContext> dc(context->newDrawContext(SkBackingFit::kApprox,
clipSpaceIBounds.width(),
clipSpaceIBounds.height(),
config));
if (!dc) {
return nullptr;
}
// The texture may be larger than necessary, this rect represents the part of the texture
// we populate with a rasterization of the clip.
SkIRect maskSpaceIBounds = SkIRect::MakeWH(clipSpaceIBounds.width(), clipSpaceIBounds.height());
// The scratch texture that we are drawing into can be substantially larger than the mask. Only
// clear the part that we care about.
dc->clear(&maskSpaceIBounds,
GrReducedClip::kAllIn_InitialState == initialState ? 0xffffffff : 0x00000000,
true);
// Set the matrix so that rendered clip elements are transformed to mask space from clip
// space.
const SkMatrix translate = SkMatrix::MakeTrans(clipToMaskOffset.fX, clipToMaskOffset.fY);
// It is important that we use maskSpaceIBounds as the stencil rect in the below loop.
// The second pass that zeros the stencil buffer renders the rect maskSpaceIBounds so the first
// pass must not set values outside of this bounds or stencil values outside the rect won't be
// cleared.
// walk through each clip element and perform its set op
for (GrReducedClip::ElementList::Iter iter = elements.headIter(); iter.get(); iter.next()) {
const Element* element = iter.get();
SkRegion::Op op = element->getOp();
bool invert = element->isInverseFilled();
if (invert || SkRegion::kIntersect_Op == op || SkRegion::kReverseDifference_Op == op) {
GrFixedClip clip(maskSpaceIBounds);
// draw directly into the result with the stencil set to make the pixels affected
// by the clip shape be non-zero.
static constexpr GrUserStencilSettings kStencilInElement(
GrUserStencilSettings::StaticInit<
0xffff,
GrUserStencilTest::kAlways,
0xffff,
GrUserStencilOp::kReplace,
GrUserStencilOp::kReplace,
0xffff>()
);
if (!stencil_element(dc.get(), clip, &kStencilInElement,
translate, element)) {
return nullptr;
}
// Draw to the exterior pixels (those with a zero stencil value).
static constexpr GrUserStencilSettings kDrawOutsideElement(
GrUserStencilSettings::StaticInit<
0x0000,
GrUserStencilTest::kEqual,
0xffff,
GrUserStencilOp::kZero,
GrUserStencilOp::kZero,
0xffff>()
);
if (!dc->drawContextPriv().drawAndStencilRect(clip, &kDrawOutsideElement,
op, !invert, false,
translate,
SkRect::Make(clipSpaceIBounds))) {
return nullptr;
}
} else {
// all the remaining ops can just be directly draw into the accumulation buffer
GrPaint paint;
paint.setAntiAlias(element->isAA());
paint.setCoverageSetOpXPFactory(op, false);
draw_element(dc.get(), GrNoClip(), paint, translate, element);
}
}
sk_sp<GrTexture> texture(dc->asTexture());
SkASSERT(texture);
texture->resourcePriv().setUniqueKey(key);
return texture;
//.........这里部分代码省略.........
示例14: NinePatch_Draw
void NinePatch_Draw(SkCanvas* canvas, const SkRect& bounds,
const SkBitmap& bitmap, const android::Res_png_9patch& chunk,
const SkPaint* paint, SkRegion** outRegion) {
if (canvas && canvas->quickReject(bounds, SkCanvas::kBW_EdgeType)) {
return;
}
// if our canvas is GL, draw this as a mesh, which will be faster than
// in parts (which is faster for raster)
if (canvas && canvas->getViewport(NULL)) {
SkNinePatch::DrawMesh(canvas, bounds, bitmap,
chunk.xDivs, chunk.numXDivs,
chunk.yDivs, chunk.numYDivs,
paint);
return;
}
#ifdef USE_TRACE
gTrace = true;
#endif
SkASSERT(canvas || outRegion);
#if 0
if (canvas) {
const SkMatrix& m = canvas->getTotalMatrix();
SkDebugf("ninepatch [%g %g %g] [%g %g %g]\n",
SkScalarToFloat(m[0]), SkScalarToFloat(m[1]), SkScalarToFloat(m[2]),
SkScalarToFloat(m[3]), SkScalarToFloat(m[4]), SkScalarToFloat(m[5]));
}
#endif
#ifdef USE_TRACE
if (gTrace) {
SkDEBUGF(("======== ninepatch bounds [%g %g]\n", SkScalarToFloat(bounds.width()), SkScalarToFloat(bounds.height())));
SkDEBUGF(("======== ninepatch paint bm [%d,%d]\n", bitmap.width(), bitmap.height()));
SkDEBUGF(("======== ninepatch xDivs [%d,%d]\n", chunk.xDivs[0], chunk.xDivs[1]));
SkDEBUGF(("======== ninepatch yDivs [%d,%d]\n", chunk.yDivs[0], chunk.yDivs[1]));
}
#endif
if (bounds.isEmpty() ||
bitmap.width() == 0 || bitmap.height() == 0 ||
(paint && paint->getXfermode() == NULL && paint->getAlpha() == 0))
{
#ifdef USE_TRACE
if (gTrace) SkDEBUGF(("======== abort ninepatch draw\n"));
#endif
return;
}
// should try a quick-reject test before calling lockPixels
SkAutoLockPixels alp(bitmap);
// after the lock, it is valid to check getPixels()
if (bitmap.getPixels() == NULL)
return;
SkPaint defaultPaint;
if (NULL == paint) {
paint = &defaultPaint;
}
const bool hasXfer = paint->getXfermode() != NULL;
SkRect dst;
SkIRect src;
const int32_t x0 = chunk.xDivs[0];
const int32_t y0 = chunk.yDivs[0];
const SkColor initColor = ((SkPaint*)paint)->getColor();
const uint8_t numXDivs = chunk.numXDivs;
const uint8_t numYDivs = chunk.numYDivs;
int i;
int j;
int colorIndex = 0;
uint32_t color;
bool xIsStretchable;
const bool initialXIsStretchable = (x0 == 0);
bool yIsStretchable = (y0 == 0);
const int bitmapWidth = bitmap.width();
const int bitmapHeight = bitmap.height();
SkScalar* dstRights = (SkScalar*) alloca((numXDivs + 1) * sizeof(SkScalar));
bool dstRightsHaveBeenCached = false;
int numStretchyXPixelsRemaining = 0;
for (i = 0; i < numXDivs; i += 2) {
numStretchyXPixelsRemaining += chunk.xDivs[i + 1] - chunk.xDivs[i];
}
int numFixedXPixelsRemaining = bitmapWidth - numStretchyXPixelsRemaining;
int numStretchyYPixelsRemaining = 0;
for (i = 0; i < numYDivs; i += 2) {
numStretchyYPixelsRemaining += chunk.yDivs[i + 1] - chunk.yDivs[i];
}
int numFixedYPixelsRemaining = bitmapHeight - numStretchyYPixelsRemaining;
#if 0
SkDebugf("NinePatch [%d %d] bounds [%g %g %g %g] divs [%d %d]\n",
bitmap.width(), bitmap.height(),
SkScalarToFloat(bounds.fLeft), SkScalarToFloat(bounds.fTop),
//.........这里部分代码省略.........
示例15: prepare_for_hoisting
// Create the layer information for the hoisted layer and secure the
// required texture/render target resources.
static void prepare_for_hoisting(GrLayerCache* layerCache,
const SkPicture* topLevelPicture,
const SkMatrix& initialMat,
const SkLayerInfo::BlockInfo& info,
const SkIRect& srcIR,
const SkIRect& dstIR,
SkTDArray<GrHoistedLayer>* needRendering,
SkTDArray<GrHoistedLayer>* recycled,
bool attemptToAtlas,
int numSamples) {
const SkPicture* pict = info.fPicture ? info.fPicture : topLevelPicture;
GrCachedLayer* layer = layerCache->findLayerOrCreate(topLevelPicture->uniqueID(),
SkToInt(info.fSaveLayerOpID),
SkToInt(info.fRestoreOpID),
srcIR,
dstIR,
initialMat,
info.fKey,
info.fKeySize,
info.fPaint);
GrSurfaceDesc desc;
desc.fFlags = kRenderTarget_GrSurfaceFlag;
desc.fWidth = srcIR.width();
desc.fHeight = srcIR.height();
desc.fConfig = kSkia8888_GrPixelConfig;
desc.fSampleCnt = numSamples;
bool locked, needsRendering;
if (attemptToAtlas) {
locked = layerCache->tryToAtlas(layer, desc, &needsRendering);
} else {
locked = layerCache->lock(layer, desc, &needsRendering);
}
if (!locked) {
// GPU resources could not be secured for the hoisting of this layer
return;
}
if (attemptToAtlas) {
SkASSERT(layer->isAtlased());
}
GrHoistedLayer* hl;
if (needsRendering) {
if (!attemptToAtlas) {
SkASSERT(!layer->isAtlased());
}
hl = needRendering->append();
} else {
hl = recycled->append();
}
layerCache->addUse(layer);
hl->fLayer = layer;
hl->fPicture = pict;
hl->fLocalMat = info.fLocalMat;
hl->fInitialMat = initialMat;
hl->fPreMat = initialMat;
hl->fPreMat.preConcat(info.fPreMat);
}