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(); }