const SkSize scaledSize = [&]() {
SkSize size; // Use a rotation-invariant scale if (!totalM.decomposeScale(&size, nullptr)) {
SkPoint center = {bounds.centerX(), bounds.centerY()};
SkScalar area = SkMatrixPriv::DifferentialAreaScale(totalM, center); if (!SkIsFinite(area) || SkScalarNearlyZero(area)) {
size = {1, 1}; // ill-conditioned matrix
} else {
size.fWidth = size.fHeight = SkScalarSqrt(area);
}
}
size.fWidth *= bounds.width();
size.fHeight *= bounds.height();
// Clamp the tile size to about 4M pixels staticconst SkScalar kMaxTileArea = 2048 * 2048;
SkScalar tileArea = size.width() * size.height(); if (tileArea > kMaxTileArea) {
SkScalar clampScale = SkScalarSqrt(kMaxTileArea / tileArea);
size.set(size.width() * clampScale, size.height() * clampScale);
}
// Scale down the tile size if larger than maxTextureSize for GPU path // or it should fail on create texture if (maxTextureSize) { if (size.width() > maxTextureSize || size.height() > maxTextureSize) {
SkScalar downScale = maxTextureSize / std::max(size.width(), size.height());
size.set(SkScalarFloorToScalar(size.width() * downScale),
SkScalarFloorToScalar(size.height() * downScale));
}
} return size;
}();
// Returns a cached image shader, which wraps a single picture tile at the given // CTM/local matrix. Also adjusts the local matrix for tile scaling.
sk_sp<SkShader> SkPictureShader::rasterShader(const SkMatrix& totalM,
SkColorType dstColorType,
SkColorSpace* dstColorSpace, const SkSurfaceProps& propsIn) const { constint maxTextureSize_NotUsedForCPU = 0;
CachedImageInfo info = CachedImageInfo::Make(fTile,
totalM,
dstColorType, dstColorSpace,
maxTextureSize_NotUsedForCPU,
propsIn); if (!info.success) { return nullptr;
}
sk_sp<SkImage> image; if (!SkResourceCache::Find(key, ImageFromPictureRec::Visitor, &image)) {
image = info.makeImage(SkSurfaces::Raster(info.imageInfo, &info.props), fPicture.get()); if (!image) { return nullptr;
}
SkResourceCache::Add(new ImageFromPictureRec(key, image));
SkPicturePriv::AddedToCache(fPicture.get());
} // Scale the image to the original picture size. auto lm = SkMatrix::Scale(1.f/info.tileScale.width(), 1.f/info.tileScale.height()); return image->makeShader(fTmx, fTmy, SkSamplingOptions(fFilter), &lm);
}
bool SkPictureShader::appendStages(const SkStageRec& rec, const SkShaders::MatrixRec& mRec) const { // Keep bitmapShader alive by using alloc instead of stack memory auto& bitmapShader = *rec.fAlloc->make<sk_sp<SkShader>>(); // We don't check whether the total local matrix is valid here because we have to assume *some* // mapping to make an image. It could be wildly wrong if there is a runtime shader transforming // the coordinates in a manner we don't know about here. However, that is a fundamental problem // with the technique of converting a picture to an image to implement this shader.
bitmapShader = this->rasterShader(mRec.totalMatrix(),
rec.fDstColorType,
rec.fDstCS,
rec.fSurfaceProps); if (!bitmapShader) { returnfalse;
} return as_SB(bitmapShader)->appendStages(rec, mRec);
}
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.