本文整理汇总了C++中SkIRect::join方法的典型用法代码示例。如果您正苦于以下问题:C++ SkIRect::join方法的具体用法?C++ SkIRect::join怎么用?C++ SkIRect::join使用的例子?那么, 这里精选的方法代码示例或许可以为您提供帮助。您也可以进一步了解该方法所在类SkIRect
的用法示例。
在下文中一共展示了SkIRect::join方法的13个代码示例,这些例子默认根据受欢迎程度排序。您可以为喜欢或者感觉有用的代码点赞,您的评价将有助于系统推荐出更棒的C++代码示例。
示例1: onFilterBounds
bool SkImageFilter::onFilterBounds(const SkIRect& src, const SkMatrix& ctm,
SkIRect* dst) const {
if (fInputCount < 1) {
*dst = src;
return true;
}
SkIRect bounds;
for (int i = 0; i < fInputCount; ++i) {
SkImageFilter* filter = this->getInput(i);
SkIRect rect = src;
if (filter && !filter->filterBounds(src, ctm, &rect)) {
return false;
}
if (0 == i) {
bounds = rect;
} else {
bounds.join(rect);
}
}
// don't modify dst until now, so we don't accidentally change it in the
// loop, but then return false on the next filter.
*dst = bounds;
return true;
}
示例2: onFilterBounds
bool SkTileImageFilter::onFilterBounds(const SkIRect& src, const SkMatrix& ctm,
SkIRect* dst) const {
SkRect srcRect;
ctm.mapRect(&srcRect, fSrcRect);
SkIRect srcIRect;
srcRect.roundOut(&srcIRect);
srcIRect.join(src);
*dst = srcIRect;
return true;
}
示例3: computeVisiblePluginRect
void PluginWidgetAndroid::computeVisiblePluginRect() {
// ensure the visibleDocRect has been set (i.e. not equal to zero)
if (m_visibleDocRect.isEmpty() || !m_pluginWindow || m_requestedVisibleRectCount < 1)
return;
// create a rect that will contain as many of the rects that will fit on screen
SkIRect visibleRect;
visibleRect.setEmpty();
for (int counter = 0; counter < m_requestedVisibleRectCount; counter++) {
ANPRectI* rect = &m_requestedVisibleRects[counter];
// create skia rect for easier manipulation and convert it to page coordinates
SkIRect pluginRect;
pluginRect.set(rect->left, rect->top, rect->right, rect->bottom);
pluginRect.offset(m_pluginWindow->x, m_pluginWindow->y);
// ensure the rect falls within the plugin's bounds
if (!m_pluginBounds.contains(pluginRect)) {
#if DEBUG_VISIBLE_RECTS
PLUGIN_LOG("%s (%d,%d,%d,%d) !contain (%d,%d,%d,%d)", __FUNCTION__,
m_pluginBounds.fLeft, m_pluginBounds.fTop,
m_pluginBounds.fRight, m_pluginBounds.fBottom,
pluginRect.fLeft, pluginRect.fTop,
pluginRect.fRight, pluginRect.fBottom);
// assume that the desired outcome is to clamp to the container
if (pluginRect.intersect(m_pluginBounds)) {
visibleRect = pluginRect;
}
#endif
continue;
}
// combine this new rect with the higher priority rects
pluginRect.join(visibleRect);
// check to see if the new rect could be made to fit within the screen
// bounds. If this is the highest priority rect then attempt to center
// even if it doesn't fit on the screen.
if (counter > 0 && (m_visibleDocRect.width() < pluginRect.width() ||
m_visibleDocRect.height() < pluginRect.height()))
break;
// set the new visible rect
visibleRect = pluginRect;
}
m_requestedVisibleRect = visibleRect;
scrollToVisiblePluginRect();
}
示例4: onFilterBounds
bool SkDropShadowImageFilter::onFilterBounds(const SkIRect& src, const SkMatrix& ctm,
SkIRect* dst) const {
SkIRect bounds = src;
if (getInput(0) && !getInput(0)->filterBounds(src, ctm, &bounds)) {
return false;
}
SkVector offsetVec = SkVector::Make(fDx, fDy);
ctm.mapVectors(&offsetVec, 1);
bounds.offset(-SkScalarCeilToInt(offsetVec.x()),
-SkScalarCeilToInt(offsetVec.y()));
SkVector sigma = SkVector::Make(fSigmaX, fSigmaY);
ctm.mapVectors(&sigma, 1);
bounds.outset(SkScalarCeilToInt(SkScalarMul(sigma.x(), SkIntToScalar(3))),
SkScalarCeilToInt(SkScalarMul(sigma.y(), SkIntToScalar(3))));
bounds.join(src);
*dst = bounds;
return true;
}
示例5: onFilterNodeBounds
SkIRect SkDropShadowImageFilter::onFilterNodeBounds(const SkIRect& src, const SkMatrix& ctm,
MapDirection direction) const {
SkVector offsetVec = SkVector::Make(fDx, fDy);
if (kReverse_MapDirection == direction) {
offsetVec.negate();
}
ctm.mapVectors(&offsetVec, 1);
SkIRect dst = src.makeOffset(SkScalarCeilToInt(offsetVec.x()),
SkScalarCeilToInt(offsetVec.y()));
SkVector sigma = SkVector::Make(fSigmaX, fSigmaY);
ctm.mapVectors(&sigma, 1);
dst.outset(SkScalarCeilToInt(SkScalarMul(sigma.x(), SkIntToScalar(3))),
SkScalarCeilToInt(SkScalarMul(sigma.y(), SkIntToScalar(3))));
if (fShadowMode == kDrawShadowAndForeground_ShadowMode) {
dst.join(src);
}
return dst;
}
示例6: onFilterBounds
SkIRect SkImageFilter::onFilterBounds(const SkIRect& src, const SkMatrix& ctm,
MapDirection direction) const {
if (this->countInputs() < 1) {
return src;
}
SkIRect totalBounds;
for (int i = 0; i < this->countInputs(); ++i) {
SkImageFilter* filter = this->getInput(i);
SkIRect rect = filter ? filter->filterBounds(src, ctm, direction) : src;
if (0 == i) {
totalBounds = rect;
} else {
totalBounds.join(rect);
}
}
return totalBounds;
}
示例7: onFilterImage
bool SkOffsetImageFilter::onFilterImage(Proxy* proxy, const SkBitmap& source,
const Context& ctx,
SkBitmap* result,
SkIPoint* offset) const {
SkImageFilter* input = getInput(0);
SkBitmap src = source;
SkIPoint srcOffset = SkIPoint::Make(0, 0);
#ifdef SK_DISABLE_OFFSETIMAGEFILTER_OPTIMIZATION
if (false) {
#else
if (!cropRectIsSet()) {
#endif
if (input && !input->filterImage(proxy, source, ctx, &src, &srcOffset)) {
return false;
}
SkVector vec;
ctx.ctm().mapVectors(&vec, &fOffset, 1);
offset->fX = srcOffset.fX + SkScalarRoundToInt(vec.fX);
offset->fY = srcOffset.fY + SkScalarRoundToInt(vec.fY);
*result = src;
} else {
if (input && !input->filterImage(proxy, source, ctx, &src, &srcOffset)) {
return false;
}
SkIRect bounds;
if (!this->applyCropRect(ctx, src, srcOffset, &bounds)) {
return false;
}
SkAutoTUnref<SkBaseDevice> device(proxy->createDevice(bounds.width(), bounds.height()));
if (NULL == device.get()) {
return false;
}
SkCanvas canvas(device);
SkPaint paint;
paint.setXfermodeMode(SkXfermode::kSrc_Mode);
canvas.translate(SkIntToScalar(srcOffset.fX - bounds.fLeft),
SkIntToScalar(srcOffset.fY - bounds.fTop));
SkVector vec;
ctx.ctm().mapVectors(&vec, &fOffset, 1);
canvas.drawBitmap(src, vec.x(), vec.y(), &paint);
*result = device->accessBitmap(false);
offset->fX = bounds.fLeft;
offset->fY = bounds.fTop;
}
return true;
}
void SkOffsetImageFilter::computeFastBounds(const SkRect& src, SkRect* dst) const {
if (getInput(0)) {
getInput(0)->computeFastBounds(src, dst);
} else {
*dst = src;
}
SkRect copy = *dst;
dst->offset(fOffset.fX, fOffset.fY);
dst->join(copy);
}
bool SkOffsetImageFilter::onFilterBounds(const SkIRect& src, const SkMatrix& ctm,
SkIRect* dst) const {
SkVector vec;
ctm.mapVectors(&vec, &fOffset, 1);
SkIRect bounds = src;
bounds.offset(-SkScalarCeilToInt(vec.fX), -SkScalarCeilToInt(vec.fY));
bounds.join(src);
if (getInput(0)) {
return getInput(0)->filterBounds(bounds, ctm, dst);
}
*dst = bounds;
return true;
}
示例8: filterImageGPUDeprecated
bool SkXfermodeImageFilter::filterImageGPUDeprecated(Proxy* proxy,
const SkBitmap& src,
const Context& ctx,
SkBitmap* result,
SkIPoint* offset) const {
GrContext* context = nullptr;
SkBitmap background = src;
SkIPoint backgroundOffset = SkIPoint::Make(0, 0);
if (!this->filterInputGPUDeprecated(0, proxy, src, ctx, &background, &backgroundOffset)) {
background.reset();
}
GrTexture* backgroundTex = background.getTexture();
if (backgroundTex) {
context = backgroundTex->getContext();
}
SkBitmap foreground = src;
SkIPoint foregroundOffset = SkIPoint::Make(0, 0);
if (!this->filterInputGPUDeprecated(1, proxy, src, ctx, &foreground, &foregroundOffset)) {
foreground.reset();
}
GrTexture* foregroundTex = foreground.getTexture();
if (foregroundTex) {
context = foregroundTex->getContext();
}
if (!context) {
return false;
}
SkIRect bounds = background.bounds().makeOffset(backgroundOffset.x(), backgroundOffset.y());
bounds.join(foreground.bounds().makeOffset(foregroundOffset.x(), foregroundOffset.y()));
if (bounds.isEmpty()) {
return false;
}
GrSurfaceDesc desc;
desc.fFlags = kRenderTarget_GrSurfaceFlag;
desc.fWidth = bounds.width();
desc.fHeight = bounds.height();
desc.fConfig = kSkia8888_GrPixelConfig;
SkAutoTUnref<GrTexture> dst(context->textureProvider()->createApproxTexture(desc));
if (!dst) {
return false;
}
GrPaint paint;
SkAutoTUnref<const GrFragmentProcessor> bgFP;
if (backgroundTex) {
SkMatrix backgroundMatrix;
backgroundMatrix.setIDiv(backgroundTex->width(), backgroundTex->height());
backgroundMatrix.preTranslate(SkIntToScalar(-backgroundOffset.fX),
SkIntToScalar(-backgroundOffset.fY));
bgFP.reset(GrTextureDomainEffect::Create(
backgroundTex, backgroundMatrix,
GrTextureDomain::MakeTexelDomain(backgroundTex, background.bounds()),
GrTextureDomain::kDecal_Mode,
GrTextureParams::kNone_FilterMode));
} else {
bgFP.reset(GrConstColorProcessor::Create(GrColor_TRANSPARENT_BLACK,
GrConstColorProcessor::kIgnore_InputMode));
}
if (foregroundTex) {
SkMatrix foregroundMatrix;
foregroundMatrix.setIDiv(foregroundTex->width(), foregroundTex->height());
foregroundMatrix.preTranslate(SkIntToScalar(-foregroundOffset.fX),
SkIntToScalar(-foregroundOffset.fY));
SkAutoTUnref<const GrFragmentProcessor> foregroundFP;
foregroundFP.reset(GrTextureDomainEffect::Create(
foregroundTex, foregroundMatrix,
GrTextureDomain::MakeTexelDomain(foregroundTex, foreground.bounds()),
GrTextureDomain::kDecal_Mode,
GrTextureParams::kNone_FilterMode));
paint.addColorFragmentProcessor(foregroundFP.get());
// A null fMode is interpreted to mean kSrcOver_Mode (to match raster).
SkAutoTUnref<SkXfermode> mode(SkSafeRef(fMode.get()));
if (!mode) {
// It would be awesome to use SkXfermode::Create here but it knows better
// than us and won't return a kSrcOver_Mode SkXfermode. That means we
// have to get one the hard way.
struct ProcCoeff rec;
rec.fProc = SkXfermode::GetProc(SkXfermode::kSrcOver_Mode);
SkXfermode::ModeAsCoeff(SkXfermode::kSrcOver_Mode, &rec.fSC, &rec.fDC);
mode.reset(new SkProcCoeffXfermode(rec, SkXfermode::kSrcOver_Mode));
}
SkAutoTUnref<const GrFragmentProcessor> xferFP(mode->getFragmentProcessorForImageFilter(bgFP));
// A null 'xferFP' here means kSrc_Mode was used in which case we can just proceed
if (xferFP) {
paint.addColorFragmentProcessor(xferFP);
}
} else {
//.........这里部分代码省略.........
示例9: filterImageGPU
bool SkXfermodeImageFilter::filterImageGPU(Proxy* proxy,
const SkBitmap& src,
const Context& ctx,
SkBitmap* result,
SkIPoint* offset) const {
SkBitmap background = src;
SkIPoint backgroundOffset = SkIPoint::Make(0, 0);
if (!this->filterInputGPU(0, proxy, src, ctx, &background, &backgroundOffset)) {
return false;
}
GrTexture* backgroundTex = background.getTexture();
if (nullptr == backgroundTex) {
SkASSERT(false);
return false;
}
SkBitmap foreground = src;
SkIPoint foregroundOffset = SkIPoint::Make(0, 0);
if (!this->filterInputGPU(1, proxy, src, ctx, &foreground, &foregroundOffset)) {
return false;
}
GrTexture* foregroundTex = foreground.getTexture();
GrContext* context = foregroundTex->getContext();
SkIRect bounds = background.bounds().makeOffset(backgroundOffset.x(), backgroundOffset.y());
bounds.join(foreground.bounds().makeOffset(foregroundOffset.x(), foregroundOffset.y()));
if (bounds.isEmpty()) {
return false;
}
const GrFragmentProcessor* xferFP = nullptr;
GrSurfaceDesc desc;
desc.fFlags = kRenderTarget_GrSurfaceFlag;
desc.fWidth = bounds.width();
desc.fHeight = bounds.height();
desc.fConfig = kSkia8888_GrPixelConfig;
SkAutoTUnref<GrTexture> dst(context->textureProvider()->createApproxTexture(desc));
if (!dst) {
return false;
}
GrPaint paint;
SkMatrix backgroundMatrix;
backgroundMatrix.setIDiv(backgroundTex->width(), backgroundTex->height());
backgroundMatrix.preTranslate(SkIntToScalar(-backgroundOffset.fX),
SkIntToScalar(-backgroundOffset.fY));
SkAutoTUnref<const GrFragmentProcessor> bgFP(GrTextureDomainEffect::Create(
backgroundTex, backgroundMatrix,
GrTextureDomain::MakeTexelDomain(backgroundTex, background.bounds()),
GrTextureDomain::kDecal_Mode,
GrTextureParams::kNone_FilterMode)
);
if (!fMode || !fMode->asFragmentProcessor(&xferFP, bgFP)) {
// canFilterImageGPU() should've taken care of this
SkASSERT(false);
return false;
}
SkMatrix foregroundMatrix;
foregroundMatrix.setIDiv(foregroundTex->width(), foregroundTex->height());
foregroundMatrix.preTranslate(SkIntToScalar(-foregroundOffset.fX),
SkIntToScalar(-foregroundOffset.fY));
SkAutoTUnref<const GrFragmentProcessor> foregroundFP(GrTextureDomainEffect::Create(
foregroundTex, foregroundMatrix,
GrTextureDomain::MakeTexelDomain(foregroundTex, foreground.bounds()),
GrTextureDomain::kDecal_Mode,
GrTextureParams::kNone_FilterMode)
);
paint.addColorFragmentProcessor(foregroundFP.get());
if (xferFP) {
paint.addColorFragmentProcessor(xferFP)->unref();
}
paint.setPorterDuffXPFactory(SkXfermode::kSrc_Mode);
SkAutoTUnref<GrDrawContext> drawContext(context->drawContext(dst->asRenderTarget()));
if (!drawContext) {
return false;
}
SkMatrix matrix;
matrix.setTranslate(SkIntToScalar(-bounds.left()), SkIntToScalar(-bounds.top()));
drawContext->drawRect(GrClip::WideOpen(), paint, matrix, SkRect::Make(bounds));
offset->fX = bounds.left();
offset->fY = bounds.top();
GrWrapTextureInBitmap(dst, bounds.width(), bounds.height(), false, result);
return true;
}
示例10: onFilterImageDeprecated
bool SkMergeImageFilter::onFilterImageDeprecated(Proxy* proxy, const SkBitmap& src,
const Context& ctx,
SkBitmap* result, SkIPoint* offset) const {
int inputCount = this->countInputs();
if (inputCount < 1) {
return false;
}
SkIRect bounds;
SkAutoTDeleteArray<SkBitmap> inputs(new SkBitmap[inputCount]);
SkAutoTDeleteArray<SkIPoint> offsets(new SkIPoint[inputCount]);
bool didProduceResult = false;
// Filter all of the inputs.
for (int i = 0; i < inputCount; ++i) {
inputs[i] = src;
offsets[i].setZero();
if (!this->filterInputDeprecated(i, proxy, src, ctx, &inputs[i], &offsets[i])) {
inputs[i].reset();
continue;
}
SkIRect srcBounds;
inputs[i].getBounds(&srcBounds);
srcBounds.offset(offsets[i]);
if (!didProduceResult) {
bounds = srcBounds;
didProduceResult = true;
} else {
bounds.join(srcBounds);
}
}
if (!didProduceResult) {
return false;
}
// Apply the crop rect to the union of the inputs' bounds.
this->getCropRect().applyTo(bounds, ctx.ctm(), &bounds);
if (!bounds.intersect(ctx.clipBounds())) {
return false;
}
const int x0 = bounds.left();
const int y0 = bounds.top();
// Allocate the destination buffer.
SkAutoTUnref<SkBaseDevice> dst(proxy->createDevice(bounds.width(), bounds.height()));
if (nullptr == dst) {
return false;
}
SkCanvas canvas(dst);
// Composite all of the filter inputs.
for (int i = 0; i < inputCount; ++i) {
SkPaint paint;
if (fModes) {
paint.setXfermodeMode((SkXfermode::Mode)fModes[i]);
}
canvas.drawBitmap(inputs[i], SkIntToScalar(offsets[i].x() - x0),
SkIntToScalar(offsets[i].y() - y0), &paint);
}
offset->fX = bounds.left();
offset->fY = bounds.top();
*result = dst->accessBitmap(false);
return true;
}
示例11: SkMemoryStream
static void add_type3_font_info(SkPDFCanon* canon,
SkPDFDict* font,
SkTypeface* typeface,
const SkBitSet& subset,
SkGlyphID firstGlyphID,
SkGlyphID lastGlyphID) {
const SkAdvancedTypefaceMetrics* metrics = SkPDFFont::GetMetrics(typeface, canon);
SkASSERT(lastGlyphID >= firstGlyphID);
// Remove unused glyphs at the end of the range.
// Keep the lastGlyphID >= firstGlyphID invariant true.
while (lastGlyphID > firstGlyphID && !subset.has(lastGlyphID)) {
--lastGlyphID;
}
int unitsPerEm;
auto cache = SkPDFFont::MakeVectorCache(typeface, &unitsPerEm);
SkASSERT(cache);
SkScalar emSize = (SkScalar)unitsPerEm;
font->insertName("Subtype", "Type3");
// Flip about the x-axis and scale by 1/emSize.
SkMatrix fontMatrix;
fontMatrix.setScale(SkScalarInvert(emSize), -SkScalarInvert(emSize));
font->insertObject("FontMatrix", SkPDFUtils::MatrixToArray(fontMatrix));
auto charProcs = sk_make_sp<SkPDFDict>();
auto encoding = sk_make_sp<SkPDFDict>("Encoding");
auto encDiffs = sk_make_sp<SkPDFArray>();
// length(firstGlyphID .. lastGlyphID) == lastGlyphID - firstGlyphID + 1
// plus 1 for glyph 0;
SkASSERT(firstGlyphID > 0);
SkASSERT(lastGlyphID >= firstGlyphID);
int glyphCount = lastGlyphID - firstGlyphID + 2;
// one other entry for the index of first glyph.
encDiffs->reserve(glyphCount + 1);
encDiffs->appendInt(0); // index of first glyph
auto widthArray = sk_make_sp<SkPDFArray>();
widthArray->reserve(glyphCount);
SkIRect bbox = SkIRect::MakeEmpty();
sk_sp<SkPDFStream> emptyStream;
for (SkGlyphID gID : SingleByteGlyphIdIterator(firstGlyphID, lastGlyphID)) {
bool skipGlyph = gID != 0 && !subset.has(gID);
SkString characterName;
SkScalar advance = 0.0f;
SkIRect glyphBBox;
if (skipGlyph) {
characterName.set("g0");
} else {
characterName.printf("g%X", gID);
const SkGlyph& glyph = cache->getGlyphIDMetrics(gID);
advance = SkFloatToScalar(glyph.fAdvanceX);
glyphBBox = SkIRect::MakeXYWH(glyph.fLeft, glyph.fTop,
glyph.fWidth, glyph.fHeight);
bbox.join(glyphBBox);
const SkPath* path = cache->findPath(glyph);
if (path && !path->isEmpty()) {
SkDynamicMemoryWStream content;
setGlyphWidthAndBoundingBox(SkFloatToScalar(glyph.fAdvanceX), glyphBBox,
&content);
SkPDFUtils::EmitPath(*path, SkPaint::kFill_Style, &content);
SkPDFUtils::PaintPath(SkPaint::kFill_Style, path->getFillType(),
&content);
charProcs->insertObjRef(
characterName, sk_make_sp<SkPDFStream>(
std::unique_ptr<SkStreamAsset>(content.detachAsStream())));
} else {
if (!emptyStream) {
emptyStream = sk_make_sp<SkPDFStream>(
std::unique_ptr<SkStreamAsset>(
new SkMemoryStream((size_t)0)));
}
charProcs->insertObjRef(characterName, emptyStream);
}
}
encDiffs->appendName(characterName.c_str());
widthArray->appendScalar(advance);
}
encoding->insertObject("Differences", std::move(encDiffs));
font->insertInt("FirstChar", 0);
font->insertInt("LastChar", lastGlyphID - firstGlyphID + 1);
/* FontBBox: "A rectangle expressed in the glyph coordinate
system, specifying the font bounding box. This is the smallest
rectangle enclosing the shape that would result if all of the
glyphs of the font were placed with their origins coincident and
then filled." */
auto fontBBox = sk_make_sp<SkPDFArray>();
fontBBox->reserve(4);
fontBBox->appendInt(bbox.left());
fontBBox->appendInt(bbox.bottom());
fontBBox->appendInt(bbox.right());
fontBBox->appendInt(bbox.top());
font->insertObject("FontBBox", std::move(fontBBox));
font->insertName("CIDToGIDMap", "Identity");
if (metrics && metrics->fGlyphToUnicode.count() > 0) {
font->insertObjRef("ToUnicode",
SkPDFMakeToUnicodeCmap(metrics->fGlyphToUnicode,
&subset,
//.........这里部分代码省略.........
示例12: background
sk_sp<SkSpecialImage> SkXfermodeImageFilter::onFilterImage(SkSpecialImage* source,
const Context& ctx,
SkIPoint* offset) const {
SkIPoint backgroundOffset = SkIPoint::Make(0, 0);
sk_sp<SkSpecialImage> background(this->filterInput(0, source, ctx, &backgroundOffset));
SkIPoint foregroundOffset = SkIPoint::Make(0, 0);
sk_sp<SkSpecialImage> foreground(this->filterInput(1, source, ctx, &foregroundOffset));
SkIRect foregroundBounds = SkIRect::EmptyIRect();
if (foreground) {
foregroundBounds = SkIRect::MakeXYWH(foregroundOffset.x(), foregroundOffset.y(),
foreground->width(), foreground->height());
}
SkIRect srcBounds = SkIRect::EmptyIRect();
if (background) {
srcBounds = SkIRect::MakeXYWH(backgroundOffset.x(), backgroundOffset.y(),
background->width(), background->height());
}
srcBounds.join(foregroundBounds);
if (srcBounds.isEmpty()) {
return nullptr;
}
SkIRect bounds;
if (!this->applyCropRect(ctx, srcBounds, &bounds)) {
return nullptr;
}
offset->fX = bounds.left();
offset->fY = bounds.top();
#if SK_SUPPORT_GPU
if (source->isTextureBacked()) {
return this->filterImageGPU(source,
background, backgroundOffset,
foreground, foregroundOffset,
bounds);
}
#endif
const SkImageInfo info = SkImageInfo::MakeN32(bounds.width(), bounds.height(),
kPremul_SkAlphaType);
sk_sp<SkSpecialSurface> surf(source->makeSurface(info));
if (!surf) {
return nullptr;
}
SkCanvas* canvas = surf->getCanvas();
SkASSERT(canvas);
canvas->clear(0x0); // can't count on background to fully clear the background
canvas->translate(SkIntToScalar(-bounds.left()), SkIntToScalar(-bounds.top()));
SkPaint paint;
paint.setXfermodeMode(SkXfermode::kSrc_Mode);
if (background) {
background->draw(canvas,
SkIntToScalar(backgroundOffset.fX), SkIntToScalar(backgroundOffset.fY),
&paint);
}
paint.setXfermode(fMode);
if (foreground) {
foreground->draw(canvas,
SkIntToScalar(foregroundOffset.fX), SkIntToScalar(foregroundOffset.fY),
&paint);
}
canvas->clipRect(SkRect::Make(foregroundBounds), SkRegion::kDifference_Op);
paint.setColor(SK_ColorTRANSPARENT);
canvas->drawPaint(paint);
return surf->makeImageSnapshot();
}
示例13: inputs
sk_sp<SkSpecialImage> SkMergeImageFilter::onFilterImage(SkSpecialImage* source, const Context& ctx,
SkIPoint* offset) const {
int inputCount = this->countInputs();
if (inputCount < 1) {
return nullptr;
}
SkIRect bounds;
bounds.setEmpty();
SkAutoTDeleteArray<sk_sp<SkSpecialImage>> inputs(new sk_sp<SkSpecialImage>[inputCount]);
SkAutoTDeleteArray<SkIPoint> offsets(new SkIPoint[inputCount]);
// Filter all of the inputs.
for (int i = 0; i < inputCount; ++i) {
offsets[i].setZero();
inputs[i] = this->filterInput(i, source, ctx, &offsets[i]);
if (!inputs[i]) {
continue;
}
const SkIRect inputBounds = SkIRect::MakeXYWH(offsets[i].fX, offsets[i].fY,
inputs[i]->width(), inputs[i]->height());
bounds.join(inputBounds);
}
if (bounds.isEmpty()) {
return nullptr;
}
// Apply the crop rect to the union of the inputs' bounds.
// Note that the crop rect can only reduce the bounds, since this
// filter does not affect transparent black.
bool embiggen = false;
this->getCropRect().applyTo(bounds, ctx.ctm(), embiggen, &bounds);
if (!bounds.intersect(ctx.clipBounds())) {
return nullptr;
}
const int x0 = bounds.left();
const int y0 = bounds.top();
sk_sp<SkSpecialSurface> surf(source->makeSurface(ctx.outputProperties(), bounds.size()));
if (!surf) {
return nullptr;
}
SkCanvas* canvas = surf->getCanvas();
SkASSERT(canvas);
canvas->clear(0x0);
// Composite all of the filter inputs.
for (int i = 0; i < inputCount; ++i) {
if (!inputs[i]) {
continue;
}
SkPaint paint;
if (fModes) {
paint.setBlendMode((SkBlendMode)fModes[i]);
}
inputs[i]->draw(canvas,
SkIntToScalar(offsets[i].x() - x0), SkIntToScalar(offsets[i].y() - y0),
&paint);
}
offset->fX = bounds.left();
offset->fY = bounds.top();
return surf->makeImageSnapshot();
}