private static void MakeVectorGraphics9SliceBackground(Vertex[] svgVertices, UInt16[] svgIndices, float svgWidth, float svgHeight, Rect targetRect, Vector4 sliceLTRB, bool stretch, Color tint, int settingIndexOffset, AllocMeshData meshAlloc)
        {
            var mwd = meshAlloc.alloc((uint)svgVertices.Length, (uint)svgIndices.Length, ref meshAlloc);

            mwd.SetAllIndices(svgIndices);

            if (!stretch)
            {
                throw new NotImplementedException("Support for repeating 9-slices is not done yet");
            }

            s_VectorGraphics9Slice.Begin();

            var     uvRegion      = mwd.uvRegion;
            int     vertsCount    = svgVertices.Length;
            Vector2 sliceInvSize  = new Vector2(1.0f / (svgWidth - sliceLTRB.z - sliceLTRB.x), 1.0f / (svgHeight - sliceLTRB.w - sliceLTRB.y));
            Vector2 stretchAmount = new Vector2(targetRect.width - svgWidth, targetRect.height - svgHeight);

            for (int i = 0; i < vertsCount; i++)
            {
                var     v = svgVertices[i];
                Vector2 skinWeight;
                skinWeight.x = Mathf.Clamp01((v.position.x - sliceLTRB.x) * sliceInvSize.x);
                skinWeight.y = Mathf.Clamp01((v.position.y - sliceLTRB.y) * sliceInvSize.y);

                v.position.x += skinWeight.x * stretchAmount.x;
                v.position.y += skinWeight.y * stretchAmount.y;
                v.uv.x        = v.uv.x * uvRegion.width + uvRegion.xMin;
                v.uv.y        = v.uv.y * uvRegion.height + uvRegion.yMin;
                v.tint       *= tint;
                uint settingIndex = (uint)(((v.opacityPageSVGSettingIndex.b << 8) | v.opacityPageSVGSettingIndex.a) + settingIndexOffset);
                v.opacityPageSVGSettingIndex.b = (byte)(settingIndex >> 8);
                v.opacityPageSVGSettingIndex.a = (byte)settingIndex;
                mwd.SetNextVertex(v);
            }

            s_VectorGraphics9Slice.End();
        }
        internal static void MakeVectorGraphicsStretchBackground(Vertex[] svgVertices, UInt16[] svgIndices, float svgWidth, float svgHeight, Rect targetRect, Rect sourceUV, ScaleMode scaleMode, Color tint, int settingIndexOffset, AllocMeshData meshAlloc, out int finalVertexCount, out int finalIndexCount)
        {
            // Determine position offset and scale according to scale mode
            Vector2 svgSubRectSize   = new Vector2(svgWidth * sourceUV.width, svgHeight * sourceUV.height);
            Vector2 svgSubRectOffset = new Vector2(sourceUV.xMin * svgWidth, sourceUV.yMin * svgHeight);
            Rect    svgSubRect       = new Rect(svgSubRectOffset, svgSubRectSize);

            bool    isSubRect = sourceUV.xMin != 0 || sourceUV.yMin != 0 || sourceUV.width != 1 || sourceUV.height != 1;
            float   srcAspect = svgSubRectSize.x / svgSubRectSize.y;
            float   destAspect = targetRect.width / targetRect.height;
            Vector2 posOffset, posScale;

            switch (scaleMode)
            {
            case ScaleMode.StretchToFill:
                posOffset  = new Vector2(0, 0);
                posScale.x = targetRect.width / svgSubRectSize.x;
                posScale.y = targetRect.height / svgSubRectSize.y;
                break;

            case ScaleMode.ScaleAndCrop:
                // ScaleAndCrop keeps the content centered to follow the same behavior as textures
                posOffset = new Vector2(0, 0);
                if (destAspect > srcAspect)
                {
                    // Fill on x and crop top/bottom sides
                    posScale.x = posScale.y = targetRect.width / svgSubRectSize.x;
                    var   height = targetRect.height / posScale.y;
                    float offset = svgSubRect.height / 2.0f - height / 2.0f;
                    posOffset.y      -= offset * posScale.y;
                    svgSubRect.y     += offset;
                    svgSubRect.height = height;
                    isSubRect         = true;
                }
                else if (destAspect < srcAspect)
                {
                    // Fill on y and crop left/right sides
                    posScale.x = posScale.y = targetRect.height / svgSubRectSize.y;
                    var   width  = targetRect.width / posScale.x;
                    float offset = svgSubRect.width / 2.0f - width / 2.0f;
                    posOffset.x     -= offset * posScale.x;
                    svgSubRect.x    += offset;
                    svgSubRect.width = width;
                    isSubRect        = true;
                }
                else
                {
                    posScale.x = posScale.y = targetRect.width / svgSubRectSize.x;      // Just scale, cropping is not involved
                }
                break;

            case ScaleMode.ScaleToFit:
                if (destAspect > srcAspect)
                {
                    // Fill on y and offset on x
                    posScale.x  = posScale.y = targetRect.height / svgSubRectSize.y;
                    posOffset.x = (targetRect.width - svgSubRectSize.x * posScale.x) * 0.5f;
                    posOffset.y = 0;
                }
                else
                {
                    // Fill on x and offset on y
                    posScale.x  = posScale.y = targetRect.width / svgSubRectSize.x;
                    posOffset.x = 0;
                    posOffset.y = (targetRect.height - svgSubRectSize.y * posScale.y) * 0.5f;
                }
                break;

            default:
                throw new NotImplementedException();
            }

            s_VectorGraphicsStretch.Begin();

            posOffset -= svgSubRectOffset * posScale;

            int        newVertexCount   = svgVertices.Length;
            int        newIndexCount    = svgIndices.Length;
            ClipCounts cc               = new ClipCounts();
            Vector4    svgSubRectMinMax = Vector4.zero;

            if (isSubRect)
            {
                if (svgSubRect.width <= 0 || svgSubRect.height <= 0)
                {
                    finalVertexCount = finalIndexCount = 0;
                    s_VectorGraphicsStretch.End();
                    return; // Totally clipped
                }
                svgSubRectMinMax = new Vector4(svgSubRect.xMin, svgSubRect.yMin, svgSubRect.xMax, svgSubRect.yMax);
                cc = UpperBoundApproximateRectClippingResults(svgVertices, svgIndices, svgSubRectMinMax);

                // We never kill vertices, just triangles.. so the clipper will only cause growth in the vertex count
                newVertexCount += cc.clippedTriangles * 6;    // 6 new vertices per clipped triangle
                newIndexCount  += cc.addedTriangles * 3;
                newIndexCount  -= cc.degenerateTriangles * 3; // We will not add the indices of degenerate triangles, so discount them
            }

            var mwd = meshAlloc.alloc((uint)newVertexCount, (uint)newIndexCount, ref meshAlloc);

            // Copy indices straight. If clipping is involved, perform clipping. This will fill all the indices
            // as well as register some new vertices at the end of the original set of vertices
            if (isSubRect)
            {
                RectClip(svgVertices, svgIndices, svgSubRectMinMax, mwd, cc, ref newVertexCount);
            }
            else
            {
                mwd.SetAllIndices(svgIndices);
            }

            // Transform all original vertices, vertices generated by clipping will use those directly
            var uvRegion   = mwd.uvRegion;
            int vertsCount = svgVertices.Length;

            for (int i = 0; i < vertsCount; i++)
            {
                var v = svgVertices[i];
                v.position.x = v.position.x * posScale.x + posOffset.x;
                v.position.y = v.position.y * posScale.y + posOffset.y;
                v.uv.x       = v.uv.x * uvRegion.width + uvRegion.xMin;
                v.uv.y       = v.uv.y * uvRegion.height + uvRegion.yMin;
                v.tint      *= tint;
                uint settingIndex = (uint)(((v.opacityPageSVGSettingIndex.b << 8) | v.opacityPageSVGSettingIndex.a) + settingIndexOffset);
                v.opacityPageSVGSettingIndex.b = (byte)(settingIndex >> 8);
                v.opacityPageSVGSettingIndex.a = (byte)settingIndex;
                mwd.SetNextVertex(v);
            }

            // Transform newely generated vertices as well (if any)
            for (int i = vertsCount; i < newVertexCount; i++)
            {
                var v = mwd.m_Vertices[i];
                v.position.x = v.position.x * posScale.x + posOffset.x;
                v.position.y = v.position.y * posScale.y + posOffset.y;
                v.uv.x       = v.uv.x * uvRegion.width + uvRegion.xMin;
                v.uv.y       = v.uv.y * uvRegion.height + uvRegion.yMin;
                v.tint      *= tint;
                uint settingIndex = (uint)(((v.opacityPageSVGSettingIndex.b << 8) | v.opacityPageSVGSettingIndex.a) + settingIndexOffset);
                v.opacityPageSVGSettingIndex.b = (byte)(settingIndex >> 8);
                v.opacityPageSVGSettingIndex.a = (byte)settingIndex;
                mwd.m_Vertices[i] = v;
            }

            finalVertexCount = mwd.vertexCount;
            finalIndexCount  = mwd.indexCount;

            s_VectorGraphicsStretch.End();
        }