void _drawImageRect(Image image, uiRect?src, uiRect dst, uiPaint paint) { D.assert(image != null && image.valid); if (image == null || !image.valid) { return; } if (src == null) { src = uiRectHelper.one; } else { src = uiRectHelper.scale(src.Value, 1f / image.width, 1f / image.height); } var layer = this._currentLayer; var state = layer.currentState; var mesh = ImageMeshGenerator.imageMesh(state.matrix, src.Value, dst); if (!this._applyClip(mesh.bounds)) { ObjectPool <uiMeshMesh> .release(mesh); return; } layer.draws.Add(CanvasShader.tex(layer, paint, mesh, image)); }
public void drawImageRect(Image image, Rect src, Rect dst, Paint paint) { D.assert(image != null); D.assert(dst != null); D.assert(paint != null); if (src == null) { src = Rect.one; } else { src = src.scale(1f / image.width, 1f / image.height); } var state = this._getState(); var mesh = ImageMeshGenerator.imageMesh(state.matrix, src, dst); if (!this._applyClip(mesh.bounds)) { return; } var layer = this._getLayer(); layer.draws.Add(CanvasShader.tex(layer, paint, mesh, image)); }
public void restore() { this._saveCount--; var layer = this._getLayer(); D.assert(layer.states.Count > 0); if (layer.states.Count > 1) { layer.states.RemoveAt(layer.states.Count - 1); layer.clipStack.restore(); return; } this._layers.RemoveAt(this._layers.Count - 1); var state = this._getState(); var mesh = ImageMeshGenerator.imageMesh(state.matrix, Rect.one, layer.layerBounds); if (!this._applyClip(mesh.bounds)) { return; } var renderDraw = CanvasShader.texRT(this._getLayer(), layer.layerPaint, mesh, layer); this._getLayer().draws.Add(renderDraw); }
void _drawImageNine(Image image, Rect src, Rect center, Rect dst, Paint paint) { D.assert(image != null); D.assert(center != null); D.assert(dst != null); D.assert(paint != null); var scaleX = 1f / image.width; var scaleY = 1f / image.height; if (src == null) { src = Rect.one; } else { src = src.scale(scaleX, scaleY); } center = center.scale(scaleX, scaleY); var layer = this._currentLayer; var state = layer.currentState; var mesh = ImageMeshGenerator.imageNineMesh(state.matrix, src, center, image.width, image.height, dst); if (!this._applyClip(mesh.bounds)) { return; } layer.draws.Add(CanvasShader.tex(layer, paint, mesh, image)); }
void _drawWithMaskFilter(uiRect meshBounds, uiPaint paint, uiMaskFilter maskFilter, uiMeshMesh fillMesh, uiMeshMesh strokeMesh, bool convex, float alpha, float strokeMult, Texture tex, uiRect texBound, TextBlobMesh textMesh, bool notEmoji, _drawPathDrawMeshCallbackDelegate drawCallback) { var layer = this._currentLayer; var clipBounds = layer.layerBounds; uiRect?stackBounds; bool iior; layer.clipStack.getBounds(out stackBounds, out iior); if (stackBounds != null) { clipBounds = uiRectHelper.intersect(clipBounds, stackBounds.Value); } if (clipBounds.isEmpty) { this._drawPathDrawMeshQuit(fillMesh, strokeMesh, textMesh); return; } var state = layer.currentState; float sigma = state.scale * maskFilter.sigma; if (sigma <= 0) { this._drawPathDrawMeshQuit(fillMesh, strokeMesh, textMesh); return; } float sigma3 = 3 * sigma; var maskBounds = uiRectHelper.inflate(meshBounds, sigma3); maskBounds = uiRectHelper.intersect(maskBounds, uiRectHelper.inflate(clipBounds, sigma3)); if (maskBounds.isEmpty) { this._drawPathDrawMeshQuit(fillMesh, strokeMesh, textMesh); return; } var maskLayer = this._createMaskLayer(layer, maskBounds, drawCallback, paint, convex, alpha, strokeMult, tex, texBound, textMesh, fillMesh, strokeMesh, notEmoji); var blurLayer = this._createBlurLayer(maskLayer, sigma, sigma, layer); var blurMesh = ImageMeshGenerator.imageMesh(null, uiRectHelper.one, maskBounds); if (!this._applyClip(blurMesh.bounds)) { ObjectPool <uiMeshMesh> .release(blurMesh); return; } layer.draws.Add(CanvasShader.texRT(layer, paint, blurMesh, blurLayer)); }
void _drawPathDrawMeshCallback(uiPaint p, uiMeshMesh fillMesh, uiMeshMesh strokeMesh, bool convex, float alpha, float strokeMult, Texture tex, uiRect textBlobBounds, TextBlobMesh textMesh, bool notEmoji) { if (!this._applyClip(fillMesh.bounds)) { ObjectPool <uiMeshMesh> .release(fillMesh); ObjectPool <uiMeshMesh> .release(strokeMesh); return; } var layer = this._currentLayer; if (convex) { layer.draws.Add(CanvasShader.convexFill(layer, p, fillMesh)); } else { layer.draws.Add(CanvasShader.fill0(layer, fillMesh)); layer.draws.Add(CanvasShader.fill1(layer, p, fillMesh.boundsMesh)); } if (strokeMesh != null) { layer.draws.Add(CanvasShader.strokeAlpha(layer, p, alpha, strokeMult, strokeMesh)); layer.draws.Add(CanvasShader.stroke1(layer, strokeMesh.duplicate())); } }
void _drawTextDrawMeshCallback(uiPaint p, uiMeshMesh fillMesh, uiMeshMesh strokeMesh, bool convex, float alpha, float strokeMult, Texture tex, uiRect textBlobBounds, TextBlobMesh textMesh, bool notEmoji) { if (!this._applyClip(textBlobBounds)) { ObjectPool <TextBlobMesh> .release(textMesh); return; } var layer = this._currentLayer; if (notEmoji) { layer.draws.Add(CanvasShader.texAlpha(layer, p, textMesh, tex)); } else { uiPaint paintWithWhite = new uiPaint(p); paintWithWhite.color = uiColor.white; if (EmojiUtils.image == null) { ObjectPool <TextBlobMesh> .release(textMesh); return; } var raw_mesh = textMesh.resolveMesh(); var meshmesh = raw_mesh.duplicate(); ObjectPool <TextBlobMesh> .release(textMesh); layer.draws.Add(CanvasShader.tex(layer, paintWithWhite, meshmesh, EmojiUtils.image)); } }
void _restore() { var layer = this._currentLayer; D.assert(layer.states.Count > 0); if (layer.states.Count > 1) { ObjectPool <State> .release(layer.states[layer.states.Count - 1]); layer.states.RemoveAt(layer.states.Count - 1); layer.currentState = layer.states[layer.states.Count - 1]; layer.clipStack.restore(); return; } this._layers.RemoveAt(this._layers.Count - 1); var currentLayer = this._currentLayer = this._layers[this._layers.Count - 1]; var state = currentLayer.currentState; var mesh = ImageMeshGenerator.imageMesh(state.matrix, uiRectHelper.one, layer.layerBounds); if (!this._applyClip(mesh.bounds)) { ObjectPool <uiMeshMesh> .release(mesh); return; } var renderDraw = CanvasShader.texRT(currentLayer, layer.layerPaint.Value, mesh, layer); currentLayer.draws.Add(renderDraw); }
void _drawImageNine(Image image, uiRect?src, uiRect center, uiRect dst, uiPaint paint) { D.assert(image != null); var scaleX = 1f / image.width; var scaleY = 1f / image.height; if (src == null) { src = uiRectHelper.one; } else { src = uiRectHelper.scale(src.Value, scaleX, scaleY); } center = uiRectHelper.scale(center, scaleX, scaleY); var layer = this._currentLayer; var state = layer.currentState; var mesh = ImageMeshGenerator.imageNineMesh(state.matrix, src.Value, center, image.width, image.height, dst); if (!this._applyClip(mesh.bounds)) { ObjectPool <uiMeshMesh> .release(mesh); return; } layer.draws.Add(CanvasShader.tex(layer, paint, mesh, image)); }
RenderLayer _createBlurLayer(RenderLayer maskLayer, float sigmaX, float sigmaY, RenderLayer parentLayer) { sigmaX = BlurUtils.adjustSigma(sigmaX, out var scaleFactorX, out var radiusX); sigmaY = BlurUtils.adjustSigma(sigmaY, out var scaleFactorY, out var radiusY); var textureWidth = Mathf.CeilToInt((float)maskLayer.width / scaleFactorX); if (textureWidth < 1) { textureWidth = 1; } var textureHeight = Mathf.CeilToInt((float)maskLayer.height / scaleFactorY); if (textureHeight < 1) { textureHeight = 1; } var blurXLayer = RenderLayer.create( rtID: Shader.PropertyToID(this._getNewRenderTextureKey()), width: textureWidth, height: textureHeight, layerBounds: maskLayer.layerBounds, filterMode: FilterMode.Bilinear, noMSAA: true ); parentLayer.addLayer(blurXLayer); var blurYLayer = RenderLayer.create( rtID: Shader.PropertyToID(this._getNewRenderTextureKey()), width: textureWidth, height: textureHeight, layerBounds: maskLayer.layerBounds, filterMode: FilterMode.Bilinear, noMSAA: true ); parentLayer.addLayer(blurYLayer); var blurMesh = ImageMeshGenerator.imageMesh(null, uiRectHelper.one, maskLayer.layerBounds); var kernelX = BlurUtils.get1DGaussianKernel(sigmaX, radiusX); var kernelY = BlurUtils.get1DGaussianKernel(sigmaY, radiusY); blurXLayer.draws.Add(CanvasShader.maskFilter( blurXLayer, blurMesh, maskLayer, radiusX, new Vector2(1f / textureWidth, 0), kernelX)); blurYLayer.draws.Add(CanvasShader.maskFilter( blurYLayer, blurMesh.duplicate(), blurXLayer, radiusY, new Vector2(0, -1f / textureHeight), kernelY)); return(blurYLayer); }
RenderLayer _createBlurLayer(RenderLayer maskLayer, float sigma, RenderLayer parentLayer) { sigma = BlurUtils.adjustSigma(sigma, out var scaleFactor, out var radius); var textureWidth = Mathf.CeilToInt((float)maskLayer.width / scaleFactor); if (textureWidth < 1) { textureWidth = 1; } var textureHeight = Mathf.CeilToInt((float)maskLayer.height / scaleFactor); if (textureHeight < 1) { textureHeight = 1; } var blurXLayer = new RenderLayer { rtID = Shader.PropertyToID("_rtID_" + this._layers.Count + "_" + parentLayer.layers.Count), width = textureWidth, height = textureHeight, layerBounds = maskLayer.layerBounds, filterMode = FilterMode.Bilinear, }; parentLayer.layers.Add(blurXLayer); var blurYLayer = new RenderLayer { rtID = Shader.PropertyToID("_rtID_" + this._layers.Count + "_" + parentLayer.layers.Count), width = textureWidth, height = textureHeight, layerBounds = maskLayer.layerBounds, filterMode = FilterMode.Bilinear, }; parentLayer.layers.Add(blurYLayer); var blurMesh = ImageMeshGenerator.imageMesh(null, Rect.one, maskLayer.layerBounds); var kernel = BlurUtils.get1DGaussianKernel(sigma, radius); blurXLayer.draws.Add(CanvasShader.maskFilter( blurXLayer, blurMesh, maskLayer, radius, new Vector2(1f / textureWidth, 0), kernel)); blurYLayer.draws.Add(CanvasShader.maskFilter( blurYLayer, blurMesh, blurXLayer, radius, new Vector2(0, -1f / textureHeight), kernel)); return(blurYLayer); }
void _drawWithMaskFilter(Rect meshBounds, Action <Paint> drawAction, Paint paint, MaskFilter maskFilter) { var layer = this._currentLayer; var clipBounds = layer.layerBounds; Rect stackBounds; bool iior; layer.clipStack.getBounds(out stackBounds, out iior); if (stackBounds != null) { clipBounds = clipBounds.intersect(stackBounds); } if (clipBounds.isEmpty) { return; } var state = layer.currentState; float sigma = state.scale * maskFilter.sigma; if (sigma <= 0) { return; } float sigma3 = 3 * sigma; var maskBounds = meshBounds.inflate(sigma3); maskBounds = maskBounds.intersect(clipBounds.inflate(sigma3)); if (maskBounds.isEmpty) { return; } var maskLayer = this._createMaskLayer(layer, maskBounds, drawAction, paint); var blurLayer = this._createBlurLayer(maskLayer, sigma, layer); var blurMesh = ImageMeshGenerator.imageMesh(null, Rect.one, maskBounds); if (!this._applyClip(blurMesh.bounds)) { return; } layer.draws.Add(CanvasShader.texRT(layer, paint, blurMesh, blurLayer)); }
void _drawPathDrawMeshCallback2(uiPaint p, uiMeshMesh mesh, bool convex, float alpha, Texture tex, uiRect textBlobBounds, TextBlobMesh textMesh, bool notEmoji) { if (!this._applyClip(mesh.bounds)) { ObjectPool <uiMeshMesh> .release(mesh); return; } var layer = this._currentLayer; layer.draws.Add(CanvasShader.stroke0(layer, p, alpha, mesh)); layer.draws.Add(CanvasShader.stroke1(layer, mesh.duplicate())); }
public void flush(uiPicture picture) { if (!CanvasShader.isReady()) { return; } this._reset(); this._resetRenderTextureId(); this._resetComputeBuffer(); this._drawUIPicture(picture, false); D.assert(this._layers.Count == 1); D.assert(this._layers[0].states.Count == 1); var layer = this._currentLayer; using (var cmdBuf = new CommandBuffer()) { cmdBuf.name = "CommandBufferCanvas"; this._lastRtID = -1; this._drawLayer(layer, cmdBuf); // this is necessary for webgl2. not sure why... just to be safe to disable the scissor. cmdBuf.DisableScissorRect(); this._bindComputeBuffer(); Graphics.ExecuteCommandBuffer(cmdBuf); } D.assert(this._layers.Count == 0 || (this._layers.Count == 1 && this._layers[0] == this._currentLayer)); if (this._currentLayer != null) { this._clearLayer(this._currentLayer); ObjectPool <RenderLayer> .release(this._currentLayer); this._currentLayer = null; this._lastScissor = null; this._layers.Clear(); } AllocDebugger.onFrameEnd(); }
void _drawTextBlob(TextBlob textBlob, Offset offset, Paint paint) { D.assert(textBlob != null); D.assert(offset != null); D.assert(paint != null); var state = this._currentLayer.currentState; var scale = state.scale * this._devicePixelRatio; var matrix = new Matrix3(state.matrix); matrix.preTranslate(offset.dx, offset.dy); var mesh = new TextBlobMesh(textBlob, scale, matrix); // request font texture so text mesh could be generated correctly var font = FontManager.instance.getOrCreate(textBlob.style.fontFamily).font; var style = textBlob.style; var fontSizeToLoad = Mathf.CeilToInt(style.UnityFontSize * scale); var subText = textBlob.text.Substring(textBlob.textOffset, textBlob.textSize); font.RequestCharactersInTexture(subText, fontSizeToLoad, style.UnityFontStyle); var tex = font.material.mainTexture; Action <Paint> drawMesh = (Paint p) => { if (!this._applyClip(textBlob.bounds)) { return; } var layer = this._currentLayer; layer.draws.Add(CanvasShader.texAlpha(layer, p, mesh, tex)); }; if (paint.maskFilter != null && paint.maskFilter.sigma != 0) { this._drawWithMaskFilter(textBlob.bounds, drawMesh, paint, paint.maskFilter); return; } drawMesh(paint); }
void _drawTextBlob(TextBlob textBlob, Offset offset, Paint paint) { D.assert(textBlob != null); D.assert(offset != null); D.assert(paint != null); var state = this._currentLayer.currentState; var scale = state.scale * this._devicePixelRatio; var matrix = new Matrix3(state.matrix); matrix.preTranslate(offset.dx, offset.dy); var mesh = MeshGenerator.generateMesh(textBlob, scale)?.transform(matrix); if (mesh == null) { return; } var font = FontManager.instance.getOrCreate(textBlob.style.fontFamily).font; var tex = font.material.mainTexture; Action <Paint> drawMesh = (Paint p) => { if (!this._applyClip(mesh.bounds)) { return; } var layer = this._currentLayer; layer.draws.Add(CanvasShader.texAlpha(layer, p, mesh, tex)); }; if (paint.maskFilter != null && paint.maskFilter.sigma != 0) { this._drawWithMaskFilter(mesh.bounds, drawMesh, paint, paint.maskFilter); return; } drawMesh(paint); }
void _drawPathDrawMeshCallback(uiPaint p, uiMeshMesh mesh, bool convex, float alpha, Texture tex, uiRect textBlobBounds, TextBlobMesh textMesh, bool notEmoji) { if (!this._applyClip(mesh.bounds)) { ObjectPool <uiMeshMesh> .release(mesh); return; } var layer = this._currentLayer; if (convex) { layer.draws.Add(CanvasShader.convexFill(layer, p, mesh)); } else { layer.draws.Add(CanvasShader.fill0(layer, mesh)); layer.draws.Add(CanvasShader.fill1(layer, p, mesh.boundsMesh)); } }
void _drawPath(Path path, Paint paint) { D.assert(path != null); D.assert(paint != null); if (paint.style == PaintingStyle.fill) { var state = this._currentLayer.currentState; var cache = path.flatten(state.scale * this._devicePixelRatio); bool convex; var mesh = cache.getFillMesh(out convex).transform(state.matrix); Action <Paint> drawMesh = p => { if (!this._applyClip(mesh.bounds)) { return; } var layer = this._currentLayer; if (convex) { layer.draws.Add(CanvasShader.convexFill(layer, p, mesh)); } else { layer.draws.Add(CanvasShader.fill0(layer, mesh)); layer.draws.Add(CanvasShader.fill1(layer, p, mesh.boundsMesh)); } }; if (paint.maskFilter != null && paint.maskFilter.sigma != 0) { this._drawWithMaskFilter(mesh.bounds, drawMesh, paint, paint.maskFilter); return; } drawMesh(paint); } else { var state = this._currentLayer.currentState; float strokeWidth = (paint.strokeWidth * state.scale).clamp(0, 200.0f); float alpha = 1.0f; if (strokeWidth == 0) { strokeWidth = this._fringeWidth; } else if (strokeWidth < this._fringeWidth) { // If the stroke width is less than pixel size, use alpha to emulate coverage. // Since coverage is area, scale by alpha*alpha. alpha = (strokeWidth / this._fringeWidth).clamp(0.0f, 1.0f); alpha *= alpha; strokeWidth = this._fringeWidth; } var cache = path.flatten(state.scale * this._devicePixelRatio); var mesh = cache.getStrokeMesh( strokeWidth / state.scale * 0.5f, paint.strokeCap, paint.strokeJoin, paint.strokeMiterLimit).transform(state.matrix); Action <Paint> drawMesh = p => { if (!this._applyClip(mesh.bounds)) { return; } var layer = this._currentLayer; layer.draws.Add(CanvasShader.stroke0(layer, p, alpha, mesh)); layer.draws.Add(CanvasShader.stroke1(layer, mesh)); }; if (paint.maskFilter != null && paint.maskFilter.sigma != 0) { this._drawWithMaskFilter(mesh.bounds, drawMesh, paint, paint.maskFilter); return; } drawMesh(paint); } }
bool _applyClip(uiRect?queryBounds) { if (queryBounds == null || queryBounds.Value.isEmpty) { return(false); } var layer = this._currentLayer; var layerBounds = layer.layerBounds; ReducedClip reducedClip = ReducedClip.create(layer.clipStack, layerBounds, queryBounds.Value); if (reducedClip.isEmpty()) { ObjectPool <ReducedClip> .release(reducedClip); return(false); } var scissor = reducedClip.scissor; var physicalRect = uiRectHelper.fromLTRB(0, 0, layer.width, layer.height); if (uiRectHelper.equals(scissor, layerBounds)) { this._tryAddScissor(layer, null); } else { var deviceScissor = uiRectHelper.fromLTRB( scissor.Value.left - layerBounds.left, layerBounds.bottom - scissor.Value.bottom, scissor.Value.right - layerBounds.left, layerBounds.bottom - scissor.Value.top ); deviceScissor = uiRectHelper.scale(deviceScissor, layer.width / layerBounds.width, layer.height / layerBounds.height); deviceScissor = uiRectHelper.roundOut(deviceScissor); deviceScissor = uiRectHelper.intersect(deviceScissor, physicalRect); if (deviceScissor.isEmpty) { ObjectPool <ReducedClip> .release(reducedClip); return(false); } this._tryAddScissor(layer, deviceScissor); } var maskGenID = reducedClip.maskGenID(); if (this._mustRenderClip(maskGenID, reducedClip.scissor.Value)) { if (maskGenID == ClipStack.wideOpenGenID) { layer.ignoreClip = true; } else { layer.ignoreClip = false; // need to inflate a bit to make sure all area is cleared. var inflatedScissor = uiRectHelper.inflate(reducedClip.scissor.Value, this._fringeWidth); var boundsMesh = uiMeshMesh.create(inflatedScissor); layer.draws.Add(CanvasShader.stencilClear(layer, boundsMesh)); foreach (var maskElement in reducedClip.maskElements) { layer.draws.Add(CanvasShader.stencil0(layer, maskElement.mesh.duplicate())); layer.draws.Add(CanvasShader.stencil1(layer, boundsMesh.duplicate())); } } this._setLastClipGenId(maskGenID, reducedClip.scissor.Value); } ObjectPool <ReducedClip> .release(reducedClip); return(true); }
bool _applyClip(Rect queryBounds) { var layer = this._currentLayer; var layerBounds = layer.layerBounds; ReducedClip reducedClip = new ReducedClip(layer.clipStack, layerBounds, queryBounds); if (reducedClip.isEmpty()) { return(false); } var scissor = reducedClip.scissor; var physicalRect = Rect.fromLTRB(0, 0, layer.width, layer.height); if (scissor == layerBounds) { this._tryAddScissor(layer, null); } else { var deviceScissor = Rect.fromLTRB( scissor.left - layerBounds.left, layerBounds.bottom - scissor.bottom, scissor.right - layerBounds.left, layerBounds.bottom - scissor.top ).scale(layer.width / layerBounds.width, layer.height / layerBounds.height); deviceScissor = deviceScissor.roundOut(); deviceScissor = deviceScissor.intersect(physicalRect); if (deviceScissor.isEmpty) { return(false); } this._tryAddScissor(layer, deviceScissor); } var maskGenID = reducedClip.maskGenID(); if (this._mustRenderClip(maskGenID, reducedClip.scissor)) { if (maskGenID == ClipStack.wideOpenGenID) { layer.ignoreClip = true; } else { layer.ignoreClip = false; var boundsMesh = new MeshMesh(reducedClip.scissor); layer.draws.Add(CanvasShader.stencilClear(layer, boundsMesh)); foreach (var maskElement in reducedClip.maskElements) { layer.draws.Add(CanvasShader.stencil0(layer, maskElement.mesh)); layer.draws.Add(CanvasShader.stencil1(layer, boundsMesh)); } } this._setLastClipGenId(maskGenID, reducedClip.scissor); } return(true); }
void _saveLayer(uiRect bounds, uiPaint paint) { D.assert(bounds.width > 0); D.assert(bounds.height > 0); var parentLayer = this._currentLayer; var state = parentLayer.currentState; var textureWidth = Mathf.CeilToInt( bounds.width * state.scale * this._devicePixelRatio); if (textureWidth < 1) { textureWidth = 1; } var textureHeight = Mathf.CeilToInt( bounds.height * state.scale * this._devicePixelRatio); if (textureHeight < 1) { textureHeight = 1; } var layer = RenderLayer.create( rtID: Shader.PropertyToID(this._getNewRenderTextureKey()), width: textureWidth, height: textureHeight, layerBounds: bounds, layerPaint: paint ); parentLayer.addLayer(layer); this._layers.Add(layer); this._currentLayer = layer; if (paint.backdrop != null) { if (paint.backdrop is _uiBlurImageFilter) { var filter = (_uiBlurImageFilter)paint.backdrop; if (!(filter.sigmaX == 0 && filter.sigmaY == 0)) { _cachedPoints[0] = bounds.topLeft; _cachedPoints[1] = bounds.bottomLeft; _cachedPoints[2] = bounds.bottomRight; _cachedPoints[3] = bounds.topRight; state.matrix.Value.mapPoints(ref _cachedPoints); var parentBounds = parentLayer.layerBounds; for (int i = 0; i < 4; i++) { _cachedPoints[i] = new uiOffset( (_cachedPoints[i].dx - parentBounds.left) / parentBounds.width, (_cachedPoints[i].dy - parentBounds.top) / parentBounds.height ); } var mesh = ImageMeshGenerator.imageMesh( null, _cachedPoints[0], _cachedPoints[1], _cachedPoints[2], _cachedPoints[3], bounds); var renderDraw = CanvasShader.texRT(layer, layer.layerPaint.Value, mesh, parentLayer); layer.draws.Add(renderDraw); var blurLayer = this._createBlurLayer(layer, filter.sigmaX, filter.sigmaY, layer); var blurMesh = ImageMeshGenerator.imageMesh(null, uiRectHelper.one, bounds); layer.draws.Add(CanvasShader.texRT(layer, paint, blurMesh, blurLayer)); } } else if (paint.backdrop is _uiMatrixImageFilter) { var filter = (_uiMatrixImageFilter)paint.backdrop; if (!filter.transform.isIdentity()) { layer.filterMode = filter.filterMode; _cachedPoints[0] = bounds.topLeft; _cachedPoints[1] = bounds.bottomLeft; _cachedPoints[2] = bounds.bottomRight; _cachedPoints[3] = bounds.topRight; state.matrix.Value.mapPoints(ref _cachedPoints); var parentBounds = parentLayer.layerBounds; for (int i = 0; i < 4; i++) { _cachedPoints[i] = new uiOffset( (_cachedPoints[i].dx - parentBounds.left) / parentBounds.width, (_cachedPoints[i].dy - parentBounds.top) / parentBounds.height ); } var matrix = uiMatrix3.makeTrans(-bounds.left, -bounds.top); matrix.postConcat(filter.transform); matrix.postTranslate(bounds.left, bounds.top); var mesh = ImageMeshGenerator.imageMesh( matrix, _cachedPoints[0], _cachedPoints[1], _cachedPoints[2], _cachedPoints[3], bounds); var renderDraw = CanvasShader.texRT(layer, layer.layerPaint.Value, mesh, parentLayer); layer.draws.Add(renderDraw); } } } }
void _drawRRectShadow(uiPath path, uiPaint paint) { D.assert(path.isNaiveRRect, () => "Cannot draw fast Shadow for non-NaiveRRect shapes"); D.assert(paint.style == PaintingStyle.fill, () => "Cannot draw fast Shadow for stroke lines"); var layer = this._currentLayer; var state = layer.currentState; var cache = path.flatten(state.scale * this._devicePixelRatio); bool convex; cache.computeFillMesh(this._fringeWidth, out convex); var fillMesh = cache.fillMesh; var meshBounds = fillMesh.transform(state.matrix); var clipBounds = layer.layerBounds; uiRect?stackBounds; bool iior; layer.clipStack.getBounds(out stackBounds, out iior); if (stackBounds != null) { clipBounds = uiRectHelper.intersect(clipBounds, stackBounds.Value); } if (clipBounds.isEmpty) { ObjectPool <uiMeshMesh> .release(meshBounds); return; } var maskBounds = meshBounds.bounds; maskBounds = uiRectHelper.intersect(maskBounds, clipBounds); if (maskBounds.isEmpty) { ObjectPool <uiMeshMesh> .release(meshBounds); return; } var blurMesh = ImageMeshGenerator.imageMesh(null, uiRectHelper.one, maskBounds); if (!this._applyClip(blurMesh.bounds)) { ObjectPool <uiMeshMesh> .release(meshBounds); ObjectPool <uiMeshMesh> .release(blurMesh); return; } var bound = path.getBounds(); var sigma = state.scale * paint.maskFilter.Value.sigma / 3f; var vertices = ObjectPool <uiList <Vector3> > .alloc(); vertices.SetCapacity(4); vertices.Add(new Vector2(0, 0)); vertices.Add(new Vector2(1, 0)); vertices.Add(new Vector2(0, 1)); vertices.Add(new Vector2(1, 1)); var _triangles = ObjectPool <uiList <int> > .alloc(); _triangles.SetCapacity(6); _triangles.Add(0); _triangles.Add(1); _triangles.Add(2); _triangles.Add(2); _triangles.Add(1); _triangles.Add(3); ObjectPool <uiMeshMesh> .release(meshBounds); ObjectPool <uiMeshMesh> .release(blurMesh); var mesh = uiMeshMesh.create(state.matrix, vertices, _triangles); var shadowColor = paint.color.withAlpha(128); layer.draws.Add(CanvasShader.fastShadow(layer, mesh, sigma, path.isRect, path.isCircle, path.rRectCorner, new Vector4(bound.left, bound.top, bound.right, bound.bottom), shadowColor)); }