Exemple #1
0
        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));
        }
Exemple #2
0
        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));
        }
Exemple #3
0
        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);
        }
Exemple #4
0
        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));
        }
Exemple #5
0
        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));
        }
Exemple #6
0
        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()));
            }
        }
Exemple #7
0
        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));
            }
        }
Exemple #8
0
        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);
        }
Exemple #9
0
        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));
        }
Exemple #10
0
        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);
        }
Exemple #11
0
        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);
        }
Exemple #12
0
        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));
        }
Exemple #13
0
        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()));
        }
Exemple #14
0
        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();
        }
Exemple #15
0
        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);
        }
Exemple #16
0
        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);
        }
Exemple #17
0
        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));
            }
        }
Exemple #18
0
        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);
            }
        }
Exemple #19
0
        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);
        }
Exemple #20
0
        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);
        }
Exemple #21
0
        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));
        }