// Compute the source rect and return false if it is empty. static bool compute_source_rect(const SkLayerInfo::BlockInfo& info, const SkMatrix& initialMat, const SkIRect& dstIR, SkIRect* srcIR) { SkIRect clipBounds = dstIR; SkMatrix totMat = initialMat; totMat.preConcat(info.fPreMat); totMat.preConcat(info.fLocalMat); if (info.fPaint && info.fPaint->getImageFilter()) { info.fPaint->getImageFilter()->filterBounds(clipBounds, totMat, &clipBounds); } if (!info.fSrcBounds.isEmpty()) { SkRect r; totMat.mapRect(&r, info.fSrcBounds); r.roundOut(srcIR); if (!srcIR->intersect(clipBounds)) { return false; } } else { *srcIR = clipBounds; } return true; }
sk_sp<GrFragmentProcessor> SkPerlinNoiseShader::asFragmentProcessor(const AsFPArgs& args) const { SkASSERT(args.fContext); SkMatrix localMatrix = this->getLocalMatrix(); if (args.fLocalMatrix) { localMatrix.preConcat(*args.fLocalMatrix); } SkMatrix matrix = *args.fViewMatrix; matrix.preConcat(localMatrix); if (0 == fNumOctaves) { if (kFractalNoise_Type == fType) { // Extract the incoming alpha and emit rgba = (a/4, a/4, a/4, a/2) // TODO: Either treat the output of this shader as sRGB or allow client to specify a // color space of the noise. Either way, this case (and the GLSL) need to convert to // the destination. sk_sp<GrFragmentProcessor> inner( GrConstColorProcessor::Make(GrColor4f::FromGrColor(0x80404040), GrConstColorProcessor::kModulateRGBA_InputMode)); return GrFragmentProcessor::MulOutputByInputAlpha(std::move(inner)); } // Emit zero. return GrConstColorProcessor::Make(GrColor4f::TransparentBlack(), GrConstColorProcessor::kIgnore_InputMode); } // Either we don't stitch tiles, either we have a valid tile size SkASSERT(!fStitchTiles || !fTileSize.isEmpty()); SkPerlinNoiseShader::PaintingData* paintingData = new PaintingData(fTileSize, fSeed, fBaseFrequencyX, fBaseFrequencyY, matrix); sk_sp<GrTextureProxy> permutationsProxy(GrMakeCachedBitmapProxy( args.fContext->resourceProvider(), paintingData->getPermutationsBitmap())); sk_sp<GrTextureProxy> noiseProxy(GrMakeCachedBitmapProxy(args.fContext->resourceProvider(), paintingData->getNoiseBitmap())); SkMatrix m = *args.fViewMatrix; m.setTranslateX(-localMatrix.getTranslateX() + SK_Scalar1); m.setTranslateY(-localMatrix.getTranslateY() + SK_Scalar1); if (permutationsProxy && noiseProxy) { sk_sp<GrFragmentProcessor> inner( GrPerlinNoiseEffect::Make(args.fContext->resourceProvider(), fType, fNumOctaves, fStitchTiles, paintingData, std::move(permutationsProxy), std::move(noiseProxy), m)); return GrFragmentProcessor::MulOutputByInputAlpha(std::move(inner)); } delete paintingData; return nullptr; }
const GrFragmentProcessor* SkPerlinNoiseShader::asFragmentProcessor( GrContext* context, const SkMatrix& viewM, const SkMatrix* externalLocalMatrix, SkFilterQuality) const { SkASSERT(context); SkMatrix localMatrix = this->getLocalMatrix(); if (externalLocalMatrix) { localMatrix.preConcat(*externalLocalMatrix); } SkMatrix matrix = viewM; matrix.preConcat(localMatrix); if (0 == fNumOctaves) { if (kFractalNoise_Type == fType) { // Extract the incoming alpha and emit rgba = (a/4, a/4, a/4, a/2) SkAutoTUnref<const GrFragmentProcessor> inner( GrConstColorProcessor::Create(0x80404040, GrConstColorProcessor::kModulateRGBA_InputMode)); return GrFragmentProcessor::MulOutputByInputAlpha(inner); } // Emit zero. return GrConstColorProcessor::Create(0x0, GrConstColorProcessor::kIgnore_InputMode); } // Either we don't stitch tiles, either we have a valid tile size SkASSERT(!fStitchTiles || !fTileSize.isEmpty()); SkPerlinNoiseShader::PaintingData* paintingData = new PaintingData(fTileSize, fSeed, fBaseFrequencyX, fBaseFrequencyY, matrix); SkAutoTUnref<GrTexture> permutationsTexture( GrRefCachedBitmapTexture(context, paintingData->getPermutationsBitmap(), GrTextureParams::ClampNoFilter())); SkAutoTUnref<GrTexture> noiseTexture( GrRefCachedBitmapTexture(context, paintingData->getNoiseBitmap(), GrTextureParams::ClampNoFilter())); SkMatrix m = viewM; m.setTranslateX(-localMatrix.getTranslateX() + SK_Scalar1); m.setTranslateY(-localMatrix.getTranslateY() + SK_Scalar1); if ((permutationsTexture) && (noiseTexture)) { SkAutoTUnref<GrFragmentProcessor> inner( GrPerlinNoiseEffect::Create(fType, fNumOctaves, fStitchTiles, paintingData, permutationsTexture, noiseTexture, m)); return GrFragmentProcessor::MulOutputByInputAlpha(inner); } delete paintingData; return nullptr; }
SkPerlinNoiseShader::PerlinNoiseShaderContext::PerlinNoiseShaderContext( const SkPerlinNoiseShader& shader, const ContextRec& rec) : INHERITED(shader, rec) { SkMatrix newMatrix = *rec.fMatrix; newMatrix.preConcat(shader.getLocalMatrix()); if (rec.fLocalMatrix) { newMatrix.preConcat(*rec.fLocalMatrix); } // This (1,1) translation is due to WebKit's 1 based coordinates for the noise // (as opposed to 0 based, usually). The same adjustment is in the setData() function. fMatrix.setTranslate(-newMatrix.getTranslateX() + SK_Scalar1, -newMatrix.getTranslateY() + SK_Scalar1); fPaintingData = SkNEW_ARGS(PaintingData, (shader.fTileSize, shader.fSeed, shader.fBaseFrequencyX, shader.fBaseFrequencyY, newMatrix)); }
void GrBlurUtils::drawPathWithMaskFilter(GrContext* context, GrDrawContext* drawContext, const GrClip& clip, const SkPath& origPath, const SkPaint& paint, const SkMatrix& origViewMatrix, const SkMatrix* prePathMatrix, const SkIRect& clipBounds, bool pathIsMutable) { SkASSERT(!pathIsMutable || origPath.isVolatile()); GrStyle style(paint); // If we have a prematrix, apply it to the path, optimizing for the case // where the original path can in fact be modified in place (even though // its parameter type is const). const SkPath* path = &origPath; SkTLazy<SkPath> tmpPath; SkMatrix viewMatrix = origViewMatrix; if (prePathMatrix) { // Styling, blurs, and shading are supposed to be applied *after* the prePathMatrix. if (!paint.getMaskFilter() && !paint.getShader() && !style.applies()) { viewMatrix.preConcat(*prePathMatrix); } else { SkPath* result = pathIsMutable ? const_cast<SkPath*>(path) : tmpPath.init(); pathIsMutable = true; path->transform(*prePathMatrix, result); path = result; result->setIsVolatile(true); } } // at this point we're done with prePathMatrix SkDEBUGCODE(prePathMatrix = (const SkMatrix*)0x50FF8001;)
void Layer::localToAncestor(const Layer* ancestor, SkMatrix* matrix) const { if (this == ancestor) { matrix->setIdentity(); return; } getLocalTransform(matrix); // Fixed position layers simply use the root layer's transform. if (shouldInheritFromRootTransform()) { ASSERT(!ancestor); matrix->postConcat(getRootLayer()->getMatrix()); return; } // Apply the local and child transforms for every layer between this layer // and ancestor. ASSERT(isAncestor(ancestor)); for (const Layer* layer = this->fParent; layer != ancestor; layer = layer->fParent) { SkMatrix tmp; layer->getLocalTransform(&tmp); tmp.preConcat(layer->getChildrenMatrix()); matrix->postConcat(tmp); } // If ancestor is not the root layer, apply its child transformation too. if (ancestor) matrix->postConcat(ancestor->getChildrenMatrix()); }
// https://www.w3.org/TR/SVG/coords.html#TransformAttribute bool SkSVGAttributeParser::parseTransform(SkSVGTransformType* t) { SkMatrix matrix = SkMatrix::I(); bool parsed = false; while (true) { SkMatrix m; if (!( this->parseMatrixToken(&m) || this->parseTranslateToken(&m) || this->parseScaleToken(&m) || this->parseRotateToken(&m) || this->parseSkewXToken(&m) || this->parseSkewYToken(&m))) { break; } matrix.preConcat(m); parsed = true; } this->parseWSToken(); if (!parsed || !this->parseEOSToken()) { return false; } *t = SkSVGTransformType(matrix); return true; }
void GrSWMaskHelper::DrawToTargetWithPathMask(GrTexture* texture, GrDrawTarget* target, const SkIRect& rect) { GrDrawState* drawState = target->drawState(); GrDrawState::AutoViewMatrixRestore avmr; if (!avmr.setIdentity(drawState)) { return; } GrDrawState::AutoRestoreEffects are(drawState); SkRect dstRect = SkRect::MakeLTRB(SK_Scalar1 * rect.fLeft, SK_Scalar1 * rect.fTop, SK_Scalar1 * rect.fRight, SK_Scalar1 * rect.fBottom); // We want to use device coords to compute the texture coordinates. We set our matrix to be // equal to the view matrix followed by a translation so that the top-left of the device bounds // maps to 0,0, and then a scaling matrix to normalized coords. We apply this matrix to the // vertex positions rather than local coords. SkMatrix maskMatrix; maskMatrix.setIDiv(texture->width(), texture->height()); maskMatrix.preTranslate(SkIntToScalar(-rect.fLeft), SkIntToScalar(-rect.fTop)); maskMatrix.preConcat(drawState->getViewMatrix()); drawState->addCoverageEffect( GrSimpleTextureEffect::Create(texture, maskMatrix, GrTextureParams::kNone_FilterMode, kPosition_GrCoordSet))->unref(); target->drawSimpleRect(dstRect); }
static void flattenPaint(const SkDraw& d, SkPaint* paint) { if (paint->getShader()) { SkMatrix local = paint->getShader()->getLocalMatrix(); local.preConcat(*d.fMatrix); paint->getShader()->setLocalMatrix(local); } }
void GrSWMaskHelper::DrawToTargetWithShapeMask(sk_sp<GrTextureProxy> proxy, GrRenderTargetContext* renderTargetContext, GrPaint&& paint, const GrUserStencilSettings& userStencilSettings, const GrClip& clip, const SkMatrix& viewMatrix, const SkIPoint& textureOriginInDeviceSpace, const SkIRect& deviceSpaceRectToDraw) { SkMatrix invert; if (!viewMatrix.invert(&invert)) { return; } GrResourceProvider* resourceProvider = renderTargetContext->resourceProvider(); SkRect dstRect = SkRect::Make(deviceSpaceRectToDraw); // We use device coords to compute the texture coordinates. We take the device coords and apply // a translation so that the top-left of the device bounds maps to 0,0, and then a scaling // matrix to normalized coords. SkMatrix maskMatrix = SkMatrix::MakeTrans(SkIntToScalar(-textureOriginInDeviceSpace.fX), SkIntToScalar(-textureOriginInDeviceSpace.fY)); maskMatrix.preConcat(viewMatrix); std::unique_ptr<GrLegacyMeshDrawOp> op = GrRectOpFactory::MakeNonAAFill( paint.getColor(), SkMatrix::I(), dstRect, nullptr, &invert); paint.addCoverageFragmentProcessor(GrSimpleTextureEffect::Make( resourceProvider, std::move(proxy), nullptr, maskMatrix, GrSamplerParams::kNone_FilterMode)); GrPipelineBuilder pipelineBuilder(std::move(paint), GrAAType::kNone); pipelineBuilder.setUserStencil(&userStencilSettings); renderTargetContext->addLegacyMeshDrawOp(std::move(pipelineBuilder), clip, std::move(op)); }
void Matrix::NativePreConcat( /* [in] */ Int64 objHandle, /* [in] */ Int64 otherHandle) { SkMatrix* obj = reinterpret_cast<SkMatrix*>(objHandle); SkMatrix* other = reinterpret_cast<SkMatrix*>(otherHandle); obj->preConcat(*other); }
const GrFragmentProcessor* SkImageShader::asFragmentProcessor(GrContext* context, const SkMatrix& viewM, const SkMatrix* localMatrix, SkFilterQuality filterQuality, GrProcessorDataManager* mgr) const { SkMatrix matrix; matrix.setIDiv(fImage->width(), fImage->height()); SkMatrix lmInverse; if (!this->getLocalMatrix().invert(&lmInverse)) { return nullptr; } if (localMatrix) { SkMatrix inv; if (!localMatrix->invert(&inv)) { return nullptr; } lmInverse.postConcat(inv); } matrix.preConcat(lmInverse); SkShader::TileMode tm[] = { fTileModeX, fTileModeY }; // Must set wrap and filter on the sampler before requesting a texture. In two places below // we check the matrix scale factors to determine how to interpret the filter quality setting. // This completely ignores the complexity of the drawVertices case where explicit local coords // are provided by the caller. bool doBicubic; GrTextureParams::FilterMode textureFilterMode = GrSkFilterQualityToGrFilterMode(filterQuality, viewM, this->getLocalMatrix(), &doBicubic); GrTextureParams params(tm, textureFilterMode); SkImageUsageType usageType; if (kClamp_TileMode == fTileModeX && kClamp_TileMode == fTileModeY) { usageType = kUntiled_SkImageUsageType; } else if (GrTextureParams::kNone_FilterMode == textureFilterMode) { usageType = kTiled_Unfiltered_SkImageUsageType; } else { usageType = kTiled_Filtered_SkImageUsageType; } SkAutoTUnref<GrTexture> texture(as_IB(fImage)->asTextureRef(context, usageType)); if (!texture) { return nullptr; } SkAutoTUnref<GrFragmentProcessor> inner; if (doBicubic) { inner.reset(GrBicubicEffect::Create(mgr, texture, matrix, tm)); } else { inner.reset(GrSimpleTextureEffect::Create(mgr, texture, matrix, params)); } if (GrPixelConfigIsAlphaOnly(texture->config())) { return SkRef(inner.get()); } return GrFragmentProcessor::MulOuputByInputAlpha(inner); }
bool SkNormalMapSourceImpl::computeNormTotalInverse(const SkShaderBase::ContextRec& rec, SkMatrix* normTotalInverse) const { SkMatrix total = SkMatrix::Concat(*rec.fMatrix, fMapShader->getLocalMatrix()); if (rec.fLocalMatrix) { total.preConcat(*rec.fLocalMatrix); } return total.invert(normTotalInverse); }
void SkSVGDevice::drawBitmap(const SkDraw& draw, const SkBitmap& bitmap, const SkMatrix& matrix, const SkPaint& paint) { SkMatrix adjustedMatrix = *draw.fMatrix; adjustedMatrix.preConcat(matrix); SkDraw adjustedDraw(draw); adjustedDraw.fMatrix = &adjustedMatrix; drawBitmapCommon(adjustedDraw, bitmap, paint); }
bool SkBitmapProcShader::asFragmentProcessor(GrContext* context, const SkPaint& paint, const SkMatrix& viewM, const SkMatrix* localMatrix, GrColor* paintColor, GrProcessorDataManager* procDataManager, GrFragmentProcessor** fp) const { SkMatrix matrix; matrix.setIDiv(fRawBitmap.width(), fRawBitmap.height()); SkMatrix lmInverse; if (!this->getLocalMatrix().invert(&lmInverse)) { return false; } if (localMatrix) { SkMatrix inv; if (!localMatrix->invert(&inv)) { return false; } lmInverse.postConcat(inv); } matrix.preConcat(lmInverse); SkShader::TileMode tm[] = { (TileMode)fTileModeX, (TileMode)fTileModeY, }; // Must set wrap and filter on the sampler before requesting a texture. In two places below // we check the matrix scale factors to determine how to interpret the filter quality setting. // This completely ignores the complexity of the drawVertices case where explicit local coords // are provided by the caller. bool doBicubic; GrTextureParams::FilterMode textureFilterMode = GrSkFilterQualityToGrFilterMode(paint.getFilterQuality(), viewM, this->getLocalMatrix(), &doBicubic); GrTextureParams params(tm, textureFilterMode); SkAutoTUnref<GrTexture> texture(GrRefCachedBitmapTexture(context, fRawBitmap, ¶ms)); if (!texture) { SkErrorInternals::SetError( kInternalError_SkError, "Couldn't convert bitmap to texture."); return false; } *paintColor = (kAlpha_8_SkColorType == fRawBitmap.colorType()) ? SkColor2GrColor(paint.getColor()) : SkColor2GrColorJustAlpha(paint.getColor()); if (doBicubic) { *fp = GrBicubicEffect::Create(procDataManager, texture, matrix, tm); } else { *fp = GrSimpleTextureEffect::Create(procDataManager, texture, matrix, params); } return true; }
void SkMatrixClipStateMgr::writeDeltaMat(int currentMatID, int desiredMatID) { const SkMatrix& current = this->lookupMat(currentMatID); const SkMatrix& desired = this->lookupMat(desiredMatID); SkMatrix delta; bool result = current.invert(&delta); if (result) { delta.preConcat(desired); } fPicRecord->recordConcat(delta); }
SkMatrix Viewer::computeMatrix() { SkMatrix m; m.reset(); if (fZoomLevel) { SkPoint center; //m = this->getLocalMatrix();//.invert(&m); m.mapXY(fZoomCenterX, fZoomCenterY, ¢er); SkScalar cx = center.fX; SkScalar cy = center.fY; m.setTranslate(-cx, -cy); m.postScale(fZoomScale, fZoomScale); m.postTranslate(cx, cy); } m.preConcat(fGesture.localM()); m.preConcat(fGesture.globalM()); return m; }
SkShader* SkPictureShader::refBitmapShader(const SkMatrix& matrix, const SkMatrix* localM) const { SkASSERT(fPicture && fPicture->width() > 0 && fPicture->height() > 0); SkMatrix m; m.setConcat(matrix, this->getLocalMatrix()); if (localM) { m.preConcat(*localM); } // Use a rotation-invariant scale SkPoint scale; if (!SkDecomposeUpper2x2(m, NULL, &scale, NULL)) { // Decomposition failed, use an approximation. scale.set(SkScalarSqrt(m.getScaleX() * m.getScaleX() + m.getSkewX() * m.getSkewX()), SkScalarSqrt(m.getScaleY() * m.getScaleY() + m.getSkewY() * m.getSkewY())); } SkSize scaledSize = SkSize::Make(scale.x() * fPicture->width(), scale.y() * fPicture->height()); SkISize tileSize = scaledSize.toRound(); if (tileSize.isEmpty()) { return NULL; } // The actual scale, compensating for rounding. SkSize tileScale = SkSize::Make(SkIntToScalar(tileSize.width()) / fPicture->width(), SkIntToScalar(tileSize.height()) / fPicture->height()); SkAutoMutexAcquire ama(fCachedBitmapShaderMutex); if (!fCachedBitmapShader || tileScale != fCachedTileScale) { SkBitmap bm; if (!bm.allocN32Pixels(tileSize.width(), tileSize.height())) { return NULL; } bm.eraseColor(SK_ColorTRANSPARENT); SkCanvas canvas(bm); canvas.scale(tileScale.width(), tileScale.height()); canvas.drawPicture(fPicture); fCachedTileScale = tileScale; SkMatrix shaderMatrix = this->getLocalMatrix(); shaderMatrix.preScale(1 / tileScale.width(), 1 / tileScale.height()); fCachedBitmapShader.reset(CreateBitmapShader(bm, fTmx, fTmy, &shaderMatrix)); } // Increment the ref counter inside the mutex to ensure the returned pointer is still valid. // Otherwise, the pointer may have been overwritten on a different thread before the object's // ref count was incremented. fCachedBitmapShader.get()->ref(); return fCachedBitmapShader; }
void GrLayerHoister::DrawLayersToAtlas(GrContext* context, const SkTDArray<GrHoistedLayer>& atlased) { if (atlased.count() > 0) { // All the atlased layers are rendered into the same GrTexture SkAutoTUnref<SkSurface> surface(SkSurface::NewRenderTargetDirect( atlased[0].fLayer->texture()->asRenderTarget(), NULL)); SkCanvas* atlasCanvas = surface->getCanvas(); SkPaint clearPaint; clearPaint.setColor(SK_ColorTRANSPARENT); clearPaint.setXfermode(SkXfermode::Create(SkXfermode::kSrc_Mode))->unref(); for (int i = 0; i < atlased.count(); ++i) { const GrCachedLayer* layer = atlased[i].fLayer; const SkPicture* pict = atlased[i].fPicture; const SkIPoint offset = atlased[i].fOffset; SkDEBUGCODE(const SkPaint* layerPaint = layer->paint();) SkASSERT(!layerPaint || !layerPaint->getImageFilter()); atlasCanvas->save(); // Add a rect clip to make sure the rendering doesn't // extend beyond the boundaries of the atlased sub-rect SkRect bound = SkRect::MakeXYWH(SkIntToScalar(layer->rect().fLeft), SkIntToScalar(layer->rect().fTop), SkIntToScalar(layer->rect().width()), SkIntToScalar(layer->rect().height())); atlasCanvas->clipRect(bound); // Since 'clear' doesn't respect the clip we need to draw a rect atlasCanvas->drawRect(bound, clearPaint); // '-offset' maps the layer's top/left to the origin. // Since this layer is atlased, the top/left corner needs // to be offset to the correct location in the backing texture. SkMatrix initialCTM; initialCTM.setTranslate(SkIntToScalar(-offset.fX), SkIntToScalar(-offset.fY)); initialCTM.preTranslate(bound.fLeft, bound.fTop); initialCTM.preConcat(atlased[i].fPreMat); atlasCanvas->setMatrix(initialCTM); atlasCanvas->concat(atlased[i].fLocalMat); SkRecordPartialDraw(*pict->fRecord.get(), atlasCanvas, bound, layer->start() + 1, layer->stop(), initialCTM); atlasCanvas->restore(); } atlasCanvas->flush(); }
SkGLDevice::TexCache* SkGLDevice::setupGLPaintShader(const SkPaint& paint) { SkGL::SetPaint(paint); SkShader* shader = paint.getShader(); if (NULL == shader) { return NULL; } if (!shader->setContext(this->accessBitmap(false), paint, this->matrix())) { return NULL; } SkBitmap bitmap; SkMatrix matrix; SkShader::TileMode tileModes[2]; if (!shader->asABitmap(&bitmap, &matrix, tileModes)) { return NULL; } bitmap.lockPixels(); if (!bitmap.readyToDraw()) { return NULL; } // see if we've already cached the bitmap from the shader SkPoint max; GLuint name; TexCache* cache = SkGLDevice::LockTexCache(bitmap, &name, &max); // the lock has already called glBindTexture for us SkGL::SetTexParams(paint.isFilterBitmap(), tileModes[0], tileModes[1]); // since our texture coords will be in local space, we wack the texture // matrix to map them back into 0...1 before we load it SkMatrix localM; if (shader->getLocalMatrix(&localM)) { SkMatrix inverse; if (localM.invert(&inverse)) { matrix.preConcat(inverse); } } matrix.postScale(max.fX / bitmap.width(), max.fY / bitmap.height()); glMatrixMode(GL_TEXTURE); SkGL::LoadMatrix(matrix); glMatrixMode(GL_MODELVIEW); // since we're going to use a shader/texture, we don't want the color, // just its alpha SkGL::SetAlpha(paint.getAlpha()); // report that we have setup the texture return cache; }
static CGAffineTransform matrix_to_transform(CGContextRef cg, const SkMatrix& ctm) { SkMatrix matrix; matrix.setScale(1, -1); matrix.postTranslate(0, SkIntToScalar(CGBitmapContextGetHeight(cg))); matrix.preConcat(ctm); return CGAffineTransformMake(matrix[SkMatrix::kMScaleX], matrix[SkMatrix::kMSkewY], matrix[SkMatrix::kMSkewX], matrix[SkMatrix::kMScaleY], matrix[SkMatrix::kMTransX], matrix[SkMatrix::kMTransY]); }
bool SkPerlinNoiseShader::asFragmentProcessor(GrContext* context, const SkPaint& paint, const SkMatrix& viewM, const SkMatrix* externalLocalMatrix, GrColor* paintColor, GrFragmentProcessor** fp) const { SkASSERT(context); *paintColor = SkColor2GrColorJustAlpha(paint.getColor()); SkMatrix localMatrix = this->getLocalMatrix(); if (externalLocalMatrix) { localMatrix.preConcat(*externalLocalMatrix); } SkMatrix matrix = viewM; matrix.preConcat(localMatrix); if (0 == fNumOctaves) { if (kFractalNoise_Type == fType) { uint32_t alpha = paint.getAlpha() >> 1; uint32_t rgb = alpha >> 1; *paintColor = GrColorPackRGBA(rgb, rgb, rgb, alpha); } else {
static void testinvert() { SkMatrix matrix; const float vals[] = { 0,9,.000001,10000,0,0 }; setmatrix6(&matrix, vals); const float vals2[] = { 0,100,71,9,0,7 }; SkMatrix tmp; setmatrix6(&tmp, vals2); matrix.preConcat(tmp); matrix.dump(); SkMatrix inverse; matrix.invert(&inverse); inverse.dump(); matrix.preConcat(inverse); matrix.dump(); // o2dContext.setTransform(0,9,.000001,10000,0,0); // o2dContext.transform(0,100,71,9,0,7); // o2dContext.setTransform(0,6,95,4,1,0); }
void GrBlurUtils::drawPathWithMaskFilter(GrContext* context, GrDrawContext* drawContext, const GrClip& clip, const SkPath& origSrcPath, const SkPaint& paint, const SkMatrix& origViewMatrix, const SkMatrix* prePathMatrix, const SkIRect& clipBounds, bool pathIsMutable) { SkASSERT(!pathIsMutable || origSrcPath.isVolatile()); GrStrokeInfo strokeInfo(paint); // comment out the line below to determine if it is the reason that the chrome mac perf bot // has begun crashing // strokeInfo.setResScale(SkDraw::ComputeResScaleForStroking(origViewMatrix)); // If we have a prematrix, apply it to the path, optimizing for the case // where the original path can in fact be modified in place (even though // its parameter type is const). SkPath* pathPtr = const_cast<SkPath*>(&origSrcPath); SkTLazy<SkPath> tmpPath; SkTLazy<SkPath> effectPath; SkPathEffect* pathEffect = paint.getPathEffect(); SkMatrix viewMatrix = origViewMatrix; if (prePathMatrix) { // stroking, path effects, and blurs are supposed to be applied *after* the prePathMatrix. // The pre-path-matrix also should not affect shading. if (!paint.getMaskFilter() && !pathEffect && !paint.getShader() && (strokeInfo.isFillStyle() || strokeInfo.isHairlineStyle())) { viewMatrix.preConcat(*prePathMatrix); } else { SkPath* result = pathPtr; if (!pathIsMutable) { result = tmpPath.init(); result->setIsVolatile(true); pathIsMutable = true; } // should I push prePathMatrix on our MV stack temporarily, instead // of applying it here? See SkDraw.cpp pathPtr->transform(*prePathMatrix, result); pathPtr = result; } } // at this point we're done with prePathMatrix SkDEBUGCODE(prePathMatrix = (const SkMatrix*)0x50FF8001;)
void GrLayerHoister::DrawLayersToAtlas(GrContext* context, const SkTDArray<GrHoistedLayer>& atlased) { if (atlased.count() > 0) { // All the atlased layers are rendered into the same GrTexture SkSurfaceProps props(0, kUnknown_SkPixelGeometry); SkAutoTUnref<SkSurface> surface(SkSurface::NewRenderTargetDirect( atlased[0].fLayer->texture()->asRenderTarget(), &props)); SkCanvas* atlasCanvas = surface->getCanvas(); for (int i = 0; i < atlased.count(); ++i) { const GrCachedLayer* layer = atlased[i].fLayer; const SkBigPicture* pict = atlased[i].fPicture->asSkBigPicture(); if (!pict) { // TODO: can we assume / assert this? continue; } const SkIPoint offset = SkIPoint::Make(layer->srcIR().fLeft, layer->srcIR().fTop); SkDEBUGCODE(const SkPaint* layerPaint = layer->paint();) SkASSERT(!layerPaint || !layerPaint->getImageFilter()); SkASSERT(!layer->filter()); atlasCanvas->save(); // Add a rect clip to make sure the rendering doesn't // extend beyond the boundaries of the atlased sub-rect const SkRect bound = SkRect::Make(layer->rect()); atlasCanvas->clipRect(bound); atlasCanvas->clear(0); // '-offset' maps the layer's top/left to the origin. // Since this layer is atlased, the top/left corner needs // to be offset to the correct location in the backing texture. SkMatrix initialCTM; initialCTM.setTranslate(SkIntToScalar(-offset.fX), SkIntToScalar(-offset.fY)); initialCTM.preTranslate(bound.fLeft, bound.fTop); initialCTM.preConcat(atlased[i].fPreMat); atlasCanvas->setMatrix(initialCTM); atlasCanvas->concat(atlased[i].fLocalMat); pict->partialPlayback(atlasCanvas, layer->start() + 1, layer->stop(), initialCTM); atlasCanvas->restore(); } atlasCanvas->flush(); }
sk_sp<GrFragmentProcessor> SkImageShader::asFragmentProcessor(const AsFPArgs& args) const { SkMatrix matrix; matrix.setIDiv(fImage->width(), fImage->height()); SkMatrix lmInverse; if (!this->getLocalMatrix().invert(&lmInverse)) { return nullptr; } if (args.fLocalMatrix) { SkMatrix inv; if (!args.fLocalMatrix->invert(&inv)) { return nullptr; } lmInverse.postConcat(inv); } matrix.preConcat(lmInverse); SkShader::TileMode tm[] = { fTileModeX, fTileModeY }; // Must set wrap and filter on the sampler before requesting a texture. In two places below // we check the matrix scale factors to determine how to interpret the filter quality setting. // This completely ignores the complexity of the drawVertices case where explicit local coords // are provided by the caller. bool doBicubic; GrTextureParams::FilterMode textureFilterMode = GrSkFilterQualityToGrFilterMode(args.fFilterQuality, *args.fViewMatrix, this->getLocalMatrix(), &doBicubic); GrTextureParams params(tm, textureFilterMode); SkAutoTUnref<GrTexture> texture(as_IB(fImage)->asTextureRef(args.fContext, params, args.fGammaTreatment)); if (!texture) { return nullptr; } sk_sp<GrFragmentProcessor> inner; if (doBicubic) { inner = GrBicubicEffect::Make(texture, nullptr, matrix, tm); } else { inner = GrSimpleTextureEffect::Make(texture, nullptr, matrix, params); } if (GrPixelConfigIsAlphaOnly(texture->config())) { return inner; } return sk_sp<GrFragmentProcessor>(GrFragmentProcessor::MulOutputByInputAlpha(std::move(inner))); }
/* [0] 9.9999997e-005 float [1] 9.0000003e-006 float [2] 7.0000001e-006 float [3] 1000000.0 float [4] 90639.000 float [5] 70000.000 float [6] 0.00000000 float [7] 0.00000000 float [8] 1.0000000 float */ static void testinvert2() { const float val[] = { 9.9999997e-005, 9.0000003e-006, 7.0000001e-006, 1000000.0, 90639.000, 70000.000 }; SkMatrix matrix; setmatrix6(&matrix, val); matrix.dump(); SkMatrix inverse; matrix.invert(&inverse); inverse.dump(); matrix.preConcat(inverse); matrix.dump(); // result is that matrix[3] is 49550 instead of 0 :( }
sk_sp<SkShader> SkShader::makeWithLocalMatrix(const SkMatrix& localMatrix) const { if (localMatrix.isIdentity()) { return sk_ref_sp(const_cast<SkShader*>(this)); } const SkMatrix* lm = &localMatrix; SkShader* baseShader = const_cast<SkShader*>(this); SkMatrix otherLocalMatrix; SkAutoTUnref<SkShader> proxy(this->refAsALocalMatrixShader(&otherLocalMatrix)); if (proxy) { otherLocalMatrix.preConcat(localMatrix); lm = &otherLocalMatrix; baseShader = proxy.get(); } return sk_make_sp<SkLocalMatrixShader>(baseShader, *lm); }
void SkLayer::localToGlobal(SkMatrix* matrix) const { this->getLocalTransform(matrix); if (this->isInheritFromRootTransform()) { matrix->postConcat(this->getRootLayer()->getMatrix()); return; } const SkLayer* layer = this; while (layer->fParent != NULL) { layer = layer->fParent; SkMatrix tmp; layer->getLocalTransform(&tmp); tmp.preConcat(layer->getChildrenMatrix()); matrix->postConcat(tmp); } }
sk_sp<GrGeometryProcessor> GrDefaultGeoProcFactory::MakeForDeviceSpace( const Color& color, const Coverage& coverage, const LocalCoords& localCoords, const SkMatrix& viewMatrix) { SkMatrix invert = SkMatrix::I(); if (LocalCoords::kUnused_Type != localCoords.fType) { SkASSERT(LocalCoords::kUsePosition_Type == localCoords.fType); if (!viewMatrix.isIdentity() && !viewMatrix.invert(&invert)) { return nullptr; } if (localCoords.hasLocalMatrix()) { invert.preConcat(*localCoords.fMatrix); } } LocalCoords inverted(LocalCoords::kUsePosition_Type, &invert); return Make(color, coverage, inverted, SkMatrix::I()); }