/// <summary> /// Create a <see cref="VertexArrayObject"/> for rendering glyphs. /// </summary> private void LinkSharedResources(GraphicsContext ctx) { CheckCurrentContext(ctx); string resourceClassId = "OpenGL.Objects.FontPatch"; string resourceBaseId = String.Format("{0}.{1}-{2}-{3}", resourceClassId, Family, Size, Style); string vertexArrayId = resourceBaseId + ".VertexArray"; string glyphDbId = resourceBaseId + ".GlyphDb"; #region Vertex Arrays _VertexArrays = (VertexArrayObject)ctx.GetSharedResource(vertexArrayId); Dictionary <char, Glyph> glyphsDb = null; if (_VertexArrays == null) { _VertexArrays = new VertexArrayObject(); List <GlyphPolygons> glyphPolygons = GenerateGlyphs(Family, Size, Style); List <Vertex2f> glyphsVertices = new List <Vertex2f>(); GlyphPolygons gGlyph = null; uint gVertexIndex = 0; glyphsDb = new Dictionary <char, Glyph>(); using (Tessellator tessellator = new Tessellator()) { tessellator.Begin += delegate(object sender, TessellatorBeginEventArgs e) { gVertexIndex = (uint)glyphsVertices.Count; }; tessellator.End += delegate(object sender, EventArgs e) { // Create element (range) int glyphIndex = _VertexArrays.SetElementArray(PrimitiveType.Triangles, gVertexIndex, (uint)glyphsVertices.Count - gVertexIndex); glyphsDb.Add(gGlyph.GlyphChar, new Glyph(gGlyph.GlyphChar, gGlyph.GlyphSize, glyphIndex)); }; tessellator.Vertex += delegate(object sender, TessellatorVertexEventArgs e) { glyphsVertices.Add((Vertex2f)e.Vertex); }; // Tessellate all glyphs foreach (GlyphPolygons glyph in glyphPolygons) { gGlyph = glyph; if (glyph.Contours.Count == 0) { glyphsDb.Add(gGlyph.GlyphChar, new Glyph(gGlyph.GlyphChar, gGlyph.GlyphSize, -1)); continue; } tessellator.BeginPolygon(); foreach (List <Vertex2f> countour in glyph.Contours) { tessellator.AddContour(countour.ToArray(), Vertex3f.UnitZ); } tessellator.EndPolygon(); } } // Element vertices ArrayBufferObject <Vertex2f> gVertexPosition = new ArrayBufferObject <Vertex2f>(BufferObjectHint.StaticCpuDraw); gVertexPosition.Create(glyphsVertices.ToArray()); _VertexArrays.SetArray(gVertexPosition, VertexArraySemantic.Position); // Share ctx.SetSharedResource(vertexArrayId, _VertexArrays); } LinkResource(_VertexArrays); #endregion #region Glyph Metadata _Glyphs = (Dictionary <char, Glyph>)ctx.GetSharedResource(glyphDbId); if (glyphsDb != null) { _Glyphs = glyphsDb; } if (_Glyphs == null) { throw new InvalidProgramException("no glyph metadata"); } // Share ctx.SetSharedResource(glyphDbId, _Glyphs); #endregion }
/// <summary> /// Create a <see cref="VertexArrayObject"/> for rendering glyphs. /// </summary> /// <param name="fontFamily"></param> /// <param name="emSize"></param> /// <param name="glyphs"></param> /// <returns></returns> private static VertexArrayObject CreateVertexArray(GraphicsContext ctx, FontFamily fontFamily, uint emSize, FontStyle fontStyle, out Dictionary <char, Glyph> glyphs) { CheckCurrentContext(ctx); string resourceBaseId = String.Format("OpenGL.Objects.FontPatch.{0}-{1}-{2}", fontFamily, emSize, fontStyle); string vertexArrayId = resourceBaseId + ".VertexArray"; string glyphDbId = resourceBaseId + ".GlyphDb"; VertexArrayObject vertexArrays = (VertexArrayObject)ctx.GetSharedResource(vertexArrayId); Dictionary <char, Glyph> glyphsDb = (Dictionary <char, Glyph>)ctx.GetSharedResource(glyphDbId); if (vertexArrays != null && glyphsDb != null) { glyphs = glyphsDb; return(vertexArrays); } vertexArrays = new VertexArrayObject(); glyphsDb = new Dictionary <char, Glyph>(); List <GlyphPolygons> glyphPolygons = GenerateGlyphs(fontFamily, emSize, fontStyle); List <Vertex2f> glyphsVertices = new List <Vertex2f>(); GlyphPolygons gGlyph = null; uint gVertexIndex = 0; glyphs = new Dictionary <char, Glyph>(); using (Tessellator tessellator = new Tessellator()) { tessellator.Begin += delegate(object sender, TessellatorBeginEventArgs e) { gVertexIndex = (uint)glyphsVertices.Count; }; tessellator.End += delegate(object sender, EventArgs e) { // Create element (range) int glyphIndex = vertexArrays.SetElementArray(PrimitiveType.Triangles, gVertexIndex, (uint)glyphsVertices.Count - gVertexIndex); glyphsDb.Add(gGlyph.GlyphChar, new Glyph(gGlyph.GlyphChar, gGlyph.GlyphSize, glyphIndex)); }; tessellator.Vertex += delegate(object sender, TessellatorVertexEventArgs e) { glyphsVertices.Add((Vertex2f)e.Vertex); }; // Tessellate all glyphs foreach (GlyphPolygons glyph in glyphPolygons) { gGlyph = glyph; if (glyph.Contours.Count == 0) { glyphsDb.Add(gGlyph.GlyphChar, new Glyph(gGlyph.GlyphChar, gGlyph.GlyphSize, -1)); continue; } tessellator.BeginPolygon(); foreach (List <Vertex2f> countour in glyph.Contours) { tessellator.AddContour(countour.ToArray(), Vertex3f.UnitZ); } tessellator.EndPolygon(); } } // Element vertices ArrayBufferObject <Vertex2f> gVertexPosition = new ArrayBufferObject <Vertex2f>(BufferObjectHint.StaticCpuDraw); gVertexPosition.Create(glyphsVertices.ToArray()); vertexArrays.SetArray(gVertexPosition, VertexArraySemantic.Position); // Returns glyphs database glyphs = glyphsDb; // Share resources ctx.SetSharedResource(vertexArrayId, vertexArrays); ctx.SetSharedResource(glyphDbId, glyphsDb); return(vertexArrays); }