/// <summary> /// Acquires a mesh for given resolution. /// </summary> /// <param name="resolution"></param> /// <returns></returns> public TriangleSoup2f AcquireFilled(float resolution) { // We first check the cache. if (filledCache != null) { ICacheable cacheable = filledCache.FindAndTouch(resolution); if (cacheable != null) { GlyphShapeCache data = cacheable as GlyphShapeCache; return(data.Data); } } // Otherwise not found, we create it. TriangleSoup2f soup = new TriangleSoup2f(); outline.Tesselate(resolution, soup); if (filledCache != null) { // We ignore if already there. filledCache.Add(resolution, new GlyphShapeCache(soup)); } return(soup); }
public void FillShape(IFill fill, IArea2f shape, IMapper mapper) { TriangleSoup2f soup = new TriangleSoup2f(); shape.Tesselate(-info.TesselationResolution, soup); FillShape(fill, soup, mapper); }
/// <summary> /// Acquires a tesselated outline. /// </summary> /// <param name="width">The width of outline.</param> /// <param name="resolution"></param> /// <returns></returns> public TriangleSoup2f AcquireOutline(float resolution, OutlineTesselation.TesselationOptionsf options) { // For now caching is not supported. TriangleSoup2f soup = new TriangleSoup2f(); outline.TesselateOutline(resolution, options, soup); return(soup); }
/// <summary> /// Render outlined characters. /// </summary> /// <param name="pen"></param> /// <param name="range"></param> public void Render(Pen pen, Vector2i range) { if (range.Y < range.X) { return; } ValidateRange(range); canvas.Begin(CanvasRenderFlags.SoftwarePositionTransform); try { for (int i = range.X; i <= range.Y; i++) { RenderGlyphInfo info = glyphs[i]; if (glyphs[i].RenderingData == null) { continue; } // We set transform. canvas.Transform = new LinearTransform( Matrix4x4f.CreateTranslate(info.LeftBottom.Vec3) * Matrix4x4f.CreateScale(new Vector3f(fontSize, fontSize, fontSize)) ); // We finally render. TriangleSoup2f soup = info.RenderingData.AcquireOutline(canvas.CanvasInfo.TesselationResolution, pen.ToOutlineTesselationOptions(canvas.CanvasInfo)); canvas.FillShape(pen.Fill, soup, info.AttachedMapper); } } finally { canvas.End(); } }
/// <summary> /// A glyph shape cache. /// </summary> /// <param name="soup"></param> public GlyphShapeCache(TriangleSoup2f soup) { this.soup = soup; }
public void FillShape(IFill fill, TriangleSoup2f mesh, IMapper mapper) { if (mapper == null) { mapper = new PositionMapper(); } // We first find "apropriate id" for instance independant fills uint fillID = uint.MaxValue; if (!fill.IsInstanceDependant) { for (int i = 0; i < fills.Count; i++) { if (fills[i].GetType() == fill.GetType()) { fillID = (uint)i; break; } } } else { int i; // We try to find exact (reference) match. for (i = 0; i < fills.Count; i++) { if (fills[i] == fill) { fillID = (uint)i; break; } } // If we found it. if (i >= fills.Count) { // We try to find compare match. for (int j = 0; j < fills.Count; j++) { if (fills[j].Equals(fills)) { fillID = (uint)j; break; } } } } // We now insert fill if no appropriate was found. if (fillID == uint.MaxValue) { // We add it and save id. fillID = (uint)fills.Count; fills.Add(fill); } // We extract indices and vertices. List <Vector2f> vertices = mesh.Vertices; List <uint> indices = mesh.Indices; // We go for each triangle. int vertexCount = vertices.Count; VertexData[] triangleData = new VertexData[vertices.Count]; // We prepare vertices. for (int i = 0; i < vertexCount; i++) { // We fill data. if (fill.CustomAttributeCount >= 1) { triangleData[i].CustomAttribute0 = fill.CalcCustomAttribute(0, mesh, vertices[i]); if (fill.CustomAttributeCount >= 2) { throw new NotSupportedException("Too many attributes."); } } else { triangleData[i].CustomAttribute0 = Vector3f.Zero; } // Fill ID. triangleData[i].FillID = fillID; // Positions. triangleData[i].Position = vertices[i]; } // We generate them. Vector2f[] mappingCoord = mapper.Generate(mesh, vertices.ToArray()); DataTransform ttransform = textureTransforms.Peek(); // We do preprocessing. if (ttransform.Transform.NeedsPreprocess) { mappingCoord = (Vector2f[])ttransform.Transform.Preprocess( PreprocessDataType.TextureCoordinates, mappingCoord); } if (ttransform.ProcessCPU) { Matrix4x4f matrix = ttransform.Transform.RuntimeForm; // We write them. for (int i = 0; i < vertexCount; i++) { triangleData[i].TexCoord0 = (matrix * mappingCoord[i].Vec3).Vec2; } } else { // We write them. for (int i = 0; i < vertexCount; i++) { triangleData[i].TexCoord0 = mappingCoord[i]; } } // We may need to transform. DataTransform vtransform = positionTransforms.Peek(); if (vtransform.ProcessCPU) { // We create matrix. Matrix4x4f matrix = Matrix4x4f.CreateTranslate(new Vector3f(-unitSize.X, -unitSize.Y, 0)) * Matrix4x4f.CreateScale(new Vector3f(2.0f, 2.0f, 2.0f)) * vtransform.Transform.RuntimeForm; // We transform all points. for (int i = 0; i < triangleData.Length; i++) { triangleData[i].Position = (matrix * new Vector4f(triangleData[i].Position.X, triangleData[i].Position.Y, 0, 1)).Vec2; } } // Send data to batch. ulong r = batch.AddVertices(triangleData); // If we cannot draw it, we flush and try again. // FIXME: this is far from optimal. if (r != (ulong)triangleData.LongLength) { Flush(true); if (batch.AddVertices(triangleData) != (ulong)triangleData.LongLength) { throw new NotSupportedException("Big vertex chunks not supported, consider creating bigger buffers."); } batch.AddVertices(triangleData); } // We now prepare indices. uint[] transIndices = new uint[indices.Count]; uint offset = (uint)batch.VertexCount - (uint)triangleData.Length; int indexCount = indices.Count; for (int i = 0; i < indexCount; i++) { transIndices[i] = indices[i] + offset; } batch.AddIndices(transIndices); }