public static FontFace LoadFont(string fontfile, ScriptLang scriptLang, WriteDirection writeDirection, out SimpleFontAtlas fontAtlas) { //1. read font info ManagedFontFace openFont = (ManagedFontFace)OpenFontLoader.LoadFont(fontfile, scriptLang, writeDirection); //2. build texture font on the fly! OR load from prebuilt file // //2.1 test build texture on the fly SimpleFontAtlasBuilder atlas1 = CreateSampleMsdfTextureFont(fontfile, 14, 0, 255); GlyphImage glyphImg2 = atlas1.BuildSingleImage(); fontAtlas = atlas1.CreateSimpleFontAtlas(); fontAtlas.TotalGlyph = glyphImg2; //string xmlFontFileInfo = ""; //GlyphImage glyphImg = null; //MySimpleFontAtlasBuilder atlasBuilder = new MySimpleFontAtlasBuilder(); //SimpleFontAtlas fontAtlas = atlasBuilder.LoadFontInfo(xmlFontFileInfo); //glyphImg = atlasBuilder.BuildSingleImage(); //we can create a new glyph or load from prebuilt file //fontAtlas.TotalGlyph = glyphImg; var textureFontFace = new TextureFontFace(openFont, fontAtlas); return(textureFontFace); }
public void CreateTextureFontFromInputChars( Typeface typeface, float sizeInPoint, TextureKind textureKind, char[] chars, OnEachFinishTotal onFinishTotal) { //convert input chars into glyphIndex List <ushort> glyphIndices = new List <ushort>(chars.Length); int i = 0; foreach (char ch in chars) { glyphIndices.Add(typeface.LookupIndex(ch)); i++; } //------------------------------------------------------------- var atlasBuilder = new SimpleFontAtlasBuilder(); atlasBuilder.SetAtlasInfo(textureKind, sizeInPoint); //------------------------------------------------------------- //we can specfic subset with special setting for each set CreateTextureFontFromGlyphIndices(typeface, sizeInPoint, HintTechnique.TrueTypeInstruction_VerticalOnly, atlasBuilder, false, GetUniqueGlyphIndexList(glyphIndices)); onFinishTotal(0, null, atlasBuilder); }
static void CreateSampleMsdfTextureFont( string fontfile, float sizeInPoint, char[] chars, string outputFile) { //sample var reader = new OpenFontReader(); using (var fs = new FileStream(fontfile, FileMode.Open)) { //1. read typeface from font file Typeface typeface = reader.Read(fs); //sample: create sample msdf texture //------------------------------------------------------------- var builder = new GlyphPathBuilder(typeface); //builder.UseTrueTypeInterpreter = this.chkTrueTypeHint.Checked; //builder.UseVerticalHinting = this.chkVerticalHinting.Checked; //------------------------------------------------------------- var atlasBuilder = new SimpleFontAtlasBuilder(); MsdfGenParams msdfGenParams = new MsdfGenParams(); int j = chars.Length; for (int i = 0; i < j; ++i) { //build glyph ushort gindex = typeface.LookupIndex(chars[i]); builder.BuildFromGlyphIndex(gindex, -1); var glyphToContour = new GlyphContourBuilder(); //glyphToContour.Read(builder.GetOutputPoints(), builder.GetOutputContours()); builder.ReadShapes(glyphToContour); msdfGenParams.shapeScale = 1f / 64; GlyphImage glyphImg = MsdfGlyphGen.CreateMsdfImage(glyphToContour, msdfGenParams); atlasBuilder.AddGlyph(gindex, glyphImg); int w = glyphImg.Width; int h = glyphImg.Height; using (Bitmap bmp = new Bitmap(glyphImg.Width, glyphImg.Height, System.Drawing.Imaging.PixelFormat.Format32bppArgb)) { var bmpdata = bmp.LockBits(new System.Drawing.Rectangle(0, 0, w, h), System.Drawing.Imaging.ImageLockMode.ReadWrite, bmp.PixelFormat); int[] imgBuffer = glyphImg.GetImageBuffer(); System.Runtime.InteropServices.Marshal.Copy(imgBuffer, 0, bmpdata.Scan0, imgBuffer.Length); bmp.UnlockBits(bmpdata); bmp.Save("d:\\WImageTest\\a001_xn2_" + (chars[i]) + ".png"); } } var glyphImg2 = atlasBuilder.BuildSingleImage(); using (Bitmap bmp = new Bitmap(glyphImg2.Width, glyphImg2.Height, System.Drawing.Imaging.PixelFormat.Format32bppArgb)) { var bmpdata = bmp.LockBits(new System.Drawing.Rectangle(0, 0, glyphImg2.Width, glyphImg2.Height), System.Drawing.Imaging.ImageLockMode.ReadWrite, bmp.PixelFormat); int[] intBuffer = glyphImg2.GetImageBuffer(); System.Runtime.InteropServices.Marshal.Copy(intBuffer, 0, bmpdata.Scan0, intBuffer.Length); bmp.UnlockBits(bmpdata); bmp.Save("d:\\WImageTest\\a_total.png"); } atlasBuilder.SaveFontInfo("d:\\WImageTest\\a_info.xml"); } }
public static FontFace LoadFont( Typeface typeface, TextureFontCreationParams creationParams, out SimpleFontAtlas fontAtlas) { //1. read font info NOpenFontFace openFont = (NOpenFontFace)OpenFontLoader.LoadFont(typeface, creationParams.scriptLang, creationParams.writeDirection); //------------------------ SimpleFontAtlasBuilder atlas1 = null; switch (creationParams.textureKind) { default: throw new System.NotSupportedException(); case TextureKind.AggSubPixel: atlas1 = CreateAggSubPixelRenderingTextureFont( typeface, creationParams.originalFontSizeInPoint, creationParams.hintTechnique, GetGlyphIndexIter(typeface, creationParams.langBits) ); break; case TextureKind.AggGrayScale: atlas1 = CreateAggTextureFont( typeface, creationParams.originalFontSizeInPoint, creationParams.hintTechnique, GetGlyphIndexIter(typeface, creationParams.langBits) ); break; case TextureKind.Msdf: atlas1 = CreateSampleMsdfTextureFont( typeface, creationParams.originalFontSizeInPoint, creationParams.hintTechnique, GetGlyphIndexIter(typeface, creationParams.langBits) ); break; } GlyphImage glyphImg2 = atlas1.BuildSingleImage(); fontAtlas = atlas1.CreateSimpleFontAtlas(); fontAtlas.TotalGlyph = glyphImg2; //string xmlFontFileInfo = ""; //GlyphImage glyphImg = null; //MySimpleFontAtlasBuilder atlasBuilder = new MySimpleFontAtlasBuilder(); //SimpleFontAtlas fontAtlas = atlasBuilder.LoadFontInfo(xmlFontFileInfo); //glyphImg = atlasBuilder.BuildSingleImage(); //we can create a new glyph or load from prebuilt file //fontAtlas.TotalGlyph = glyphImg; return(openFont); //var textureFontFace = new TextureFontFace(openFont, fontAtlas); //return textureFontFace; }
void CreateTextureFontFromGlyphIndices( Typeface typeface, float sizeInPoint, HintTechnique hintTechnique, SimpleFontAtlasBuilder atlasBuilder, bool applyFilter, ushort[] glyphIndices) { //sample: create sample msdf texture //------------------------------------------------------------- var builder = new GlyphPathBuilder(typeface); builder.SetHintTechnique(hintTechnique); // if (atlasBuilder.TextureKind == TextureKind.Msdf) { MsdfGenParams msdfGenParams = new MsdfGenParams(); int j = glyphIndices.Length; for (int i = 0; i < j; ++i) { ushort gindex = glyphIndices[i]; //create picture with unscaled version set scale=-1 //(we will create glyph contours and analyze them) builder.BuildFromGlyphIndex(gindex, -1); var glyphToContour = new GlyphContourBuilder(); builder.ReadShapes(glyphToContour); //msdfgen with scale the glyph to specific shapescale msdfGenParams.shapeScale = 1f / 64; //as original GlyphImage glyphImg = MsdfGlyphGen.CreateMsdfImage(glyphToContour, msdfGenParams); // atlasBuilder.AddGlyph(gindex, glyphImg); } } else { AggGlyphTextureGen aggTextureGen = new AggGlyphTextureGen(); aggTextureGen.TextureKind = atlasBuilder.TextureKind; int j = glyphIndices.Length; for (int i = 0; i < j; ++i) { //build glyph ushort gindex = glyphIndices[i]; builder.BuildFromGlyphIndex(gindex, sizeInPoint); GlyphImage glyphImg = aggTextureGen.CreateGlyphImage(builder, 1); if (applyFilter) { glyphImg = Sharpen(glyphImg, 1); //TODO: //the filter make the image shift x and y 1 px //temp fix with this, glyphImg.TextureOffsetX += 1; glyphImg.TextureOffsetY += 1; } // atlasBuilder.AddGlyph(gindex, glyphImg); } } }
/// <summary> /// get from cache or create a new one /// </summary> /// <param name="reqFont"></param> /// <returns></returns> public SimpleFontAtlas GetFontAtlas(RequestFont reqFont, out GLBitmap glBmp) { int fontKey = reqFont.FontKey; SimpleFontAtlas fontAtlas; if (!_createdAtlases.TryGetValue(fontKey, out fontAtlas)) { Typeface resolvedTypeface = textServices.ResolveTypeface(reqFont); //if we don't have //the create it SimpleFontAtlasBuilder atlasBuilder = null; var textureGen = new GlyphTextureBitmapGenerator(); textureGen.CreateTextureFontFromScriptLangs( resolvedTypeface, reqFont.SizeInPoints, _textureKind, _currentScriptLangs, (glyphIndex, glyphImage, outputAtlasBuilder) => { if (outputAtlasBuilder != null) { //finish atlasBuilder = outputAtlasBuilder; } } ); GlyphImage totalGlyphsImg = atlasBuilder.BuildSingleImage(); //create atlas fontAtlas = atlasBuilder.CreateSimpleFontAtlas(); fontAtlas.TotalGlyph = totalGlyphsImg; #if DEBUG //save glyph image for debug //PixelFarm.Agg.ActualImage.SaveImgBufferToPngFile( // totalGlyphsImg.GetImageBuffer(), // totalGlyphsImg.Width * 4, // totalGlyphsImg.Width, totalGlyphsImg.Height, // "d:\\WImageTest\\total_" + reqFont.Name + "_" + reqFont.SizeInPoints + ".png"); #endif //cache the atlas _createdAtlases.Add(fontKey, fontAtlas); // //calculate some commonly used values fontAtlas.SetTextureScaleInfo( resolvedTypeface.CalculateScaleToPixelFromPointSize(fontAtlas.OriginalFontSizePts), resolvedTypeface.CalculateScaleToPixelFromPointSize(reqFont.SizeInPoints)); //TODO: review here, use scaled or unscaled values fontAtlas.SetCommonFontMetricValues( resolvedTypeface.Ascender, resolvedTypeface.Descender, resolvedTypeface.LineGap, resolvedTypeface.CalculateRecommendLineSpacing()); } glBmp = _loadedGlyphs.GetOrCreateNewOne(fontAtlas); return(fontAtlas); }
static SimpleFontAtlasBuilder CreateSampleMsdfTextureFont(string fontfile, float sizeInPoint, ushort startGlyphIndex, ushort endGlyphIndex) { //read type face from file Typeface typeface; using (var fs = new FileStream(fontfile, FileMode.Open, FileAccess.Read)) { var reader = new OpenFontReader(); //1. read typeface from font file typeface = reader.Read(fs); } //sample: create sample msdf texture //------------------------------------------------------------- var builder = new MyGlyphPathBuilder(typeface); //builder.UseTrueTypeInterpreter = this.chkTrueTypeHint.Checked; //builder.UseVerticalHinting = this.chkVerticalHinting.Checked; //------------------------------------------------------------- var atlasBuilder = new SimpleFontAtlasBuilder(); var msdfBuilder = new MsdfGlyphGen(); for (ushort n = startGlyphIndex; n <= endGlyphIndex; ++n) { //build glyph builder.BuildFromGlyphIndex(n, sizeInPoint); var msdfGlyphGen = new MsdfGlyphGen(); var actualImg = msdfGlyphGen.CreateMsdfImage( builder.GetOutputPoints(), builder.GetOutputContours(), builder.GetPixelScale()); atlasBuilder.AddGlyph((int)n, actualImg); //using (Bitmap bmp = new Bitmap(w, h, System.Drawing.Imaging.PixelFormat.Format32bppArgb)) //{ // var bmpdata = bmp.LockBits(new Rectangle(0, 0, w, h), System.Drawing.Imaging.ImageLockMode.ReadWrite, bmp.PixelFormat); // System.Runtime.InteropServices.Marshal.Copy(buffer, 0, bmpdata.Scan0, buffer.Length); // bmp.UnlockBits(bmpdata); // bmp.Save("d:\\WImageTest\\a001_xn2_" + n + ".png"); //} } return(atlasBuilder); //var glyphImg2 = atlasBuilder.BuildSingleImage(); //using (Bitmap bmp = new Bitmap(glyphImg2.Width, glyphImg2.Height, System.Drawing.Imaging.PixelFormat.Format32bppArgb)) //{ // var bmpdata = bmp.LockBits(new System.Drawing.Rectangle(0, 0, glyphImg2.Width, glyphImg2.Height), // System.Drawing.Imaging.ImageLockMode.ReadWrite, bmp.PixelFormat); // int[] intBuffer = glyphImg2.GetImageBuffer(); // System.Runtime.InteropServices.Marshal.Copy(intBuffer, 0, bmpdata.Scan0, intBuffer.Length); // bmp.UnlockBits(bmpdata); // bmp.Save("d:\\WImageTest\\a_total.png"); //} //atlasBuilder.SaveFontInfo("d:\\WImageTest\\a_info.xml"); }
static void CreateSampleMsdfTextureFont(string fontfile, float sizeInPoint, ushort startGlyphIndex, ushort endGlyphIndex, string outputFile) { //sample var reader = new OpenFontReader(); using (var fs = new FileStream(fontfile, FileMode.Open)) { //1. read typeface from font file Typeface typeface = reader.Read(fs); //sample: create sample msdf texture //------------------------------------------------------------- var builder = new GlyphPathBuilder(typeface); //builder.UseTrueTypeInterpreter = this.chkTrueTypeHint.Checked; //builder.UseVerticalHinting = this.chkVerticalHinting.Checked; //------------------------------------------------------------- var atlasBuilder = new SimpleFontAtlasBuilder(); for (ushort gindex = startGlyphIndex; gindex <= endGlyphIndex; ++gindex) { //build glyph builder.BuildFromGlyphIndex(gindex, sizeInPoint); var glyphToContour = new GlyphContourBuilder(); //glyphToContour.Read(builder.GetOutputPoints(), builder.GetOutputContours()); var genParams = new MsdfGenParams(); builder.ReadShapes(glyphToContour); genParams.shapeScale = 1f / 64; //we scale later (as original C++ code use 1/64) GlyphImage glyphImg = MsdfGlyphGen.CreateMsdfImage(glyphToContour, genParams); atlasBuilder.AddGlyph(gindex, glyphImg); //using (Bitmap bmp = new Bitmap(w, h, System.Drawing.Imaging.PixelFormat.Format32bppArgb)) //{ // var bmpdata = bmp.LockBits(new Rectangle(0, 0, w, h), System.Drawing.Imaging.ImageLockMode.ReadWrite, bmp.PixelFormat); // System.Runtime.InteropServices.Marshal.Copy(buffer, 0, bmpdata.Scan0, buffer.Length); // bmp.UnlockBits(bmpdata); // bmp.Save("d:\\WImageTest\\a001_xn2_" + n + ".png"); //} } var glyphImg2 = atlasBuilder.BuildSingleImage(); using (Bitmap bmp = new Bitmap(glyphImg2.Width, glyphImg2.Height, System.Drawing.Imaging.PixelFormat.Format32bppArgb)) { var bmpdata = bmp.LockBits(new System.Drawing.Rectangle(0, 0, glyphImg2.Width, glyphImg2.Height), System.Drawing.Imaging.ImageLockMode.ReadWrite, bmp.PixelFormat); int[] intBuffer = glyphImg2.GetImageBuffer(); System.Runtime.InteropServices.Marshal.Copy(intBuffer, 0, bmpdata.Scan0, intBuffer.Length); bmp.UnlockBits(bmpdata); bmp.Save("d:\\WImageTest\\a_total.png"); } atlasBuilder.SaveFontInfo("d:\\WImageTest\\a_info.xml"); } }
public void CreateTextureFontFromScriptLangs( Typeface typeface, float sizeInPoint, TextureKind textureKind, GlyphTextureBuildDetail[] details, OnEachFinishTotal onFinishTotal) { //------------------------------------------------------------- var atlasBuilder = new SimpleFontAtlasBuilder(); atlasBuilder.SetAtlasInfo(textureKind, sizeInPoint); //------------------------------------------------------------- int j = details.Length; for (int i = 0; i < j; ++i) { GlyphTextureBuildDetail detail = details[i]; if (detail.ScriptLang != null) { //skip those script lang=null //2. find associated glyph index base on input script langs List <ushort> outputGlyphIndexList = new List <ushort>(); typeface.CollectAllAssociateGlyphIndex(outputGlyphIndexList, detail.ScriptLang); CreateTextureFontFromGlyphIndices(typeface, sizeInPoint, detail.HintTechnique, atlasBuilder, detail.DoFilter, GetUniqueGlyphIndexList(outputGlyphIndexList) ); } } for (int i = 0; i < j; ++i) { GlyphTextureBuildDetail detail = details[i]; if (detail.OnlySelectedGlyphIndices != null) { //skip those script lang=null //2. find associated glyph index base on input script langs CreateTextureFontFromGlyphIndices(typeface, sizeInPoint, detail.HintTechnique, atlasBuilder, detail.DoFilter, detail.OnlySelectedGlyphIndices ); } } onFinishTotal(0, null, atlasBuilder); }
void CreateTextureFontFromGlyphIndices( Typeface typeface, float sizeInPoint, HintTechnique hintTechnique, SimpleFontAtlasBuilder atlasBuilder, bool applyFilter, char[] chars) { int j = chars.Length; ushort[] glyphIndices = new ushort[j]; for (int i = 0; i < j; ++i) { glyphIndices[i] = typeface.LookupIndex(chars[i]); } CreateTextureFontFromGlyphIndices(typeface, sizeInPoint, hintTechnique, atlasBuilder, applyFilter, glyphIndices); }
static SimpleFontAtlasBuilder CreateAggSubPixelRenderingTextureFont( Typeface typeface, float sizeInPoint, HintTechnique hintTech, IEnumerable <ushort> glyphIndexIter) { ////read type face from file //Typeface typeface; //using (var fs = new FileStream(fontfile, FileMode.Open, FileAccess.Read)) //{ // var reader = new OpenFontReader(); // //1. read typeface from font file // typeface = reader.Read(fs); //} //sample: create sample msdf texture //------------------------------------------------------------- var builder = new GlyphPathBuilder(typeface); builder.SetHintTechnique(hintTech); //------------------------------------------------------------- var atlasBuilder = new SimpleFontAtlasBuilder(); atlasBuilder.SetAtlasInfo(TextureKind.AggSubPixel, sizeInPoint); VertexStorePool vxsPool = new VertexStorePool(); //create agg cavnas foreach (ushort gindex in glyphIndexIter) { //build glyph builder.BuildFromGlyphIndex(gindex, sizeInPoint); var txToVxs = new GlyphTranslatorToVxs(); builder.ReadShapes(txToVxs); // //create new one var glyphVxs = new VertexStore(); txToVxs.WriteOutput(glyphVxs, vxsPool); //find bound //-------------------------------------------- //GlyphImage glyphImg = new GlyphImage() RectD bounds = new Agg.RectD(); BoundingRect.GetBoundingRect(new VertexStoreSnap(glyphVxs), ref bounds); //-------------------------------------------- int w = (int)System.Math.Ceiling(bounds.Width); int h = (int)System.Math.Ceiling(bounds.Height); if (w < 5) { w = 5; } if (h < 5) { h = 5; } //translate to positive quadrant double dx = (bounds.Left < 0) ? -bounds.Left : 0; double dy = (bounds.Bottom < 0) ? -bounds.Bottom : 0; w = w * 4; if (dx != 0 || dy != 0) { Agg.Transform.Affine transformMat = Agg.Transform.Affine.NewTranslation(dx, dy); VertexStore vxs2 = new VertexStore(); glyphVxs.TranslateToNewVxs(dx, dy, vxs2); glyphVxs = vxs2; } //-------------------------------------------- //create glyph img ActualImage img = new Agg.ActualImage(w, h, PixelFormat.ARGB32); ImageGraphics2D imgCanvas2d = new Agg.ImageGraphics2D(img); AggCanvasPainter painter = new Agg.AggCanvasPainter(imgCanvas2d); //we use white glyph on black bg for this texture painter.Clear(Color.Black); //fill with black painter.FillColor = Color.White; painter.StrokeColor = Color.White; //-------------------------------------------- painter.UseSubPixelRendering = true; //-------------------------------------------- //-------------------------------------------- painter.Fill(glyphVxs); //-------------------------------------------- var glyphImage = new GlyphImage(w, h); glyphImage.TextureOffsetX = dx; glyphImage.TextureOffsetY = dy; glyphImage.SetImageBuffer(ActualImage.GetBuffer2(img), false); //copy data from agg canvas to glyph image atlasBuilder.AddGlyph(gindex, glyphImage); //int[] buffer = glyphImage.GetImageBuffer(); //using (var bmp = new System.Drawing.Bitmap(glyphImage.Width, glyphImage.Height, System.Drawing.Imaging.PixelFormat.Format32bppArgb)) //{ // var bmpdata = bmp.LockBits(new System.Drawing.Rectangle(0, 0, glyphImage.Width, glyphImage.Height), // System.Drawing.Imaging.ImageLockMode.ReadWrite, bmp.PixelFormat); // System.Runtime.InteropServices.Marshal.Copy(buffer, 0, bmpdata.Scan0, buffer.Length); // bmp.UnlockBits(bmpdata); // bmp.Save("d:\\WImageTest\\a001_subpix_xn2_" + gindex + ".png"); //} } //var glyphImg2 = atlasBuilder.BuildSingleImage(); //using (var bmp = new System.Drawing.Bitmap(glyphImg2.Width, glyphImg2.Height, System.Drawing.Imaging.PixelFormat.Format32bppArgb)) //{ // var bmpdata = bmp.LockBits(new System.Drawing.Rectangle(0, 0, glyphImg2.Width, glyphImg2.Height), // System.Drawing.Imaging.ImageLockMode.ReadWrite, bmp.PixelFormat); // int[] intBuffer = glyphImg2.GetImageBuffer(); // System.Runtime.InteropServices.Marshal.Copy(intBuffer, 0, bmpdata.Scan0, intBuffer.Length); // bmp.UnlockBits(bmpdata); // bmp.Save("d:\\WImageTest\\a_total.png"); //} //atlasBuilder.SaveFontInfo("d:\\WImageTest\\a_info.xml"); return(atlasBuilder); }
static SimpleFontAtlasBuilder CreateSampleMsdfTextureFont( Typeface typeface, float sizeInPoint, HintTechnique hintTech, IEnumerable <ushort> glyphIndexIter) { ////read type face from file //Typeface typeface; //using (var fs = new FileStream(fontfile, FileMode.Open, FileAccess.Read)) //{ // var reader = new OpenFontReader(); // //1. read typeface from font file // typeface = reader.Read(fs); //} //sample: create sample msdf texture //------------------------------------------------------------- var builder = new GlyphPathBuilder(typeface); builder.SetHintTechnique(hintTech); MsdfGenParams genParams = new MsdfGenParams(); var atlasBuilder = new SimpleFontAtlasBuilder(); atlasBuilder.SetAtlasInfo(TextureKind.Msdf, sizeInPoint); foreach (ushort gindex in glyphIndexIter) { //build glyph builder.BuildFromGlyphIndex(gindex, -1); //use original glyph size (assign -1) var glyphToContour = new GlyphContourBuilder(); //glyphToContour.Read(builder.GetOutputPoints(), builder.GetOutputContours()); builder.ReadShapes(glyphToContour); genParams.shapeScale = 1f / 64; //we scale later (as original C++ code use 1/64) GlyphImage glyphImg = MsdfGlyphGen.CreateMsdfImage(glyphToContour, genParams); atlasBuilder.AddGlyph(gindex, glyphImg); //int[] buffer = glyphImage.GetImageBuffer(); //using (var bmp = new System.Drawing.Bitmap(glyphImage.Width, glyphImage.Height, System.Drawing.Imaging.PixelFormat.Format32bppArgb)) //{ // var bmpdata = bmp.LockBits(new System.Drawing.Rectangle(0, 0, glyphImage.Width, glyphImage.Height), // System.Drawing.Imaging.ImageLockMode.ReadWrite, bmp.PixelFormat); // System.Runtime.InteropServices.Marshal.Copy(buffer, 0, bmpdata.Scan0, buffer.Length); // bmp.UnlockBits(bmpdata); // bmp.Save("d:\\WImageTest\\a001_xn2_" + c + ".png"); //} } //var glyphImg2 = atlasBuilder.BuildSingleImage(); //using (var bmp = new System.Drawing.Bitmap(glyphImg2.Width, glyphImg2.Height, System.Drawing.Imaging.PixelFormat.Format32bppArgb)) //{ // var bmpdata = bmp.LockBits(new System.Drawing.Rectangle(0, 0, glyphImg2.Width, glyphImg2.Height), // System.Drawing.Imaging.ImageLockMode.ReadWrite, bmp.PixelFormat); // int[] intBuffer = glyphImg2.GetImageBuffer(); // System.Runtime.InteropServices.Marshal.Copy(intBuffer, 0, bmpdata.Scan0, intBuffer.Length); // bmp.UnlockBits(bmpdata); // bmp.Save("d:\\WImageTest\\a_total.png"); //} //atlasBuilder.SaveFontInfo("d:\\WImageTest\\a_info.xml"); return(atlasBuilder); }
void CreateTextureFontFromGlyphIndices( Typeface typeface, float sizeInPoint, HintTechnique hintTechnique, SimpleFontAtlasBuilder atlasBuilder, bool applyFilter, ushort[] glyphIndices) { //sample: create sample msdf texture //------------------------------------------------------------- var builder = new GlyphPathBuilder(typeface); builder.SetHintTechnique(hintTechnique); // if (atlasBuilder.TextureKind == TextureKind.Msdf) { MsdfGenParams msdfGenParams = new MsdfGenParams(); int j = glyphIndices.Length; for (int i = 0; i < j; ++i) { ushort gindex = glyphIndices[i]; //create picture with unscaled version set scale=-1 //(we will create glyph contours and analyze them) builder.BuildFromGlyphIndex(gindex, -1); var glyphToContour = new GlyphContourBuilder(); builder.ReadShapes(glyphToContour); //msdfgen with scale the glyph to specific shapescale msdfGenParams.shapeScale = 1f / 64; //as original GlyphImage glyphImg = MsdfGlyphGen.CreateMsdfImage(glyphToContour, msdfGenParams); // atlasBuilder.AddGlyph(gindex, glyphImg); } } else { AggGlyphTextureGen aggTextureGen = new AggGlyphTextureGen(); aggTextureGen.TextureKind = atlasBuilder.TextureKind; //create reusable agg painter*** //assume each glyph size= 2 * line height //TODO: review here again... int tmpMemBmpHeight = (int)(2 * typeface.CalculateRecommendLineSpacing() * typeface.CalculateScaleToPixelFromPointSize(sizeInPoint)); //create glyph img using (PixelFarm.CpuBlit.MemBitmap tmpMemBmp = new PixelFarm.CpuBlit.MemBitmap(tmpMemBmpHeight, tmpMemBmpHeight)) //square { //draw a glyph into tmpMemBmp and then copy to a GlyphImage aggTextureGen.Painter = PixelFarm.CpuBlit.AggPainter.Create(tmpMemBmp); #if DEBUG tmpMemBmp._dbugNote = "CreateGlyphImage()"; #endif int j = glyphIndices.Length; for (int i = 0; i < j; ++i) { //build glyph ushort gindex = glyphIndices[i]; builder.BuildFromGlyphIndex(gindex, sizeInPoint); GlyphImage glyphImg = aggTextureGen.CreateGlyphImage(builder, 1); if (applyFilter) { glyphImg = Sharpen(glyphImg, 1); //TODO: //the filter make the image shift x and y 1 px //temp fix with this, glyphImg.TextureOffsetX += 1; glyphImg.TextureOffsetY += 1; } // atlasBuilder.AddGlyph(gindex, glyphImg); } } } }
private void cmdTestFontAtlas_Click(object sender, EventArgs e) { //read string from txtSampleChars //please make sure all are unique. (TODO: check it) //then create a font atlas from the sample chars char[] sampleChars = txtSampleChars.Text.ToCharArray(); if (sampleChars.Length == 0) { return; } // GlyphImage totalGlyphsImg = null; SimpleFontAtlasBuilder atlasBuilder = null; var glyphTextureGen = new GlyphTextureBitmapGenerator(); // Typeface typeface = _basicOptions.Typeface; float fontSizeInPoints = _basicOptions.FontSizeInPoints; // glyphTextureGen.CreateTextureFontFromInputChars( typeface, fontSizeInPoints, TextureKind.StencilLcdEffect, sampleChars, (glyphIndex, glyphImage, outputAtlasBuilder) => { if (outputAtlasBuilder != null) { //finish atlasBuilder = outputAtlasBuilder; } } ); atlasBuilder.SpaceCompactOption = SimpleFontAtlasBuilder.CompactOption.ArrangeByHeight; totalGlyphsImg = atlasBuilder.BuildSingleImage(); string fontTextureImg = "d:\\WImageTest\\test_glyph_atlas.png"; //create atlas SimpleFontAtlas fontAtlas = atlasBuilder.CreateSimpleFontAtlas(); fontAtlas.TotalGlyph = totalGlyphsImg; // using (MemBitmap memBmp = MemBitmap.CreateFromCopy(totalGlyphsImg.Width, totalGlyphsImg.Height, totalGlyphsImg.GetImageBuffer())) using (System.Drawing.Bitmap bmp = new Bitmap(memBmp.Width, memBmp.Height)) { var bmpdata = bmp.LockBits(new System.Drawing.Rectangle(0, 0, memBmp.Width, memBmp.Height), System.Drawing.Imaging.ImageLockMode.ReadWrite, System.Drawing.Imaging.PixelFormat.Format32bppArgb); var tmpMem = MemBitmap.GetBufferPtr(memBmp); unsafe { PixelFarm.CpuBlit.NativeMemMx.MemCopy((byte *)bmpdata.Scan0, (byte *)tmpMem.Ptr, tmpMem.LengthInBytes); } bmp.UnlockBits(bmpdata); bmp.Save(fontTextureImg); } #if DEBUG //save glyph image for debug //PixelFarm.Agg.ActualImage.SaveImgBufferToPngFile( // totalGlyphsImg.GetImageBuffer(), // totalGlyphsImg.Width * 4, // totalGlyphsImg.Width, totalGlyphsImg.Height, // "d:\\WImageTest\\total_" + reqFont.Name + "_" + reqFont.SizeInPoints + ".png"); ////save image to cache //SaveImgBufferToFile(totalGlyphsImg, fontTextureImg); #endif //cache the atlas //_createdAtlases.Add(fontKey, fontAtlas); //// ////calculate some commonly used values //fontAtlas.SetTextureScaleInfo( // resolvedTypeface.CalculateScaleToPixelFromPointSize(fontAtlas.OriginalFontSizePts), // resolvedTypeface.CalculateScaleToPixelFromPointSize(reqFont.SizeInPoints)); ////TODO: review here, use scaled or unscaled values //fontAtlas.SetCommonFontMetricValues( // resolvedTypeface.Ascender, // resolvedTypeface.Descender, // resolvedTypeface.LineGap, // resolvedTypeface.CalculateRecommendLineSpacing()); /// }
void CreateTextureFontFromGlyphIndices( Typeface typeface, float sizeInPoint, TextureKind textureKind, ushort[] glyphIndices, OnEachFinishTotal onFinishTotal) { if (onFinishTotal == null) { return; } //sample: create sample msdf texture //------------------------------------------------------------- var builder = new GlyphPathBuilder(typeface); builder.UseTrueTypeInstructions = this.UseTrueTypeInstruction; //------------------------------------------------------------- var atlasBuilder = new SimpleFontAtlasBuilder(); atlasBuilder.SetAtlasInfo(textureKind, sizeInPoint); //------------------------------------------------------------- // MsdfGenParams msdfGenParams = null; AggGlyphTextureGen aggTextureGen = null; if (textureKind == TextureKind.Msdf) { msdfGenParams = new MsdfGenParams(); } else { aggTextureGen = new AggGlyphTextureGen(); } float pxscale = typeface.CalculateScaleToPixelFromPointSize(sizeInPoint); int j = glyphIndices.Length; for (int i = 0; i < j; ++i) { //build glyph ushort gindex = glyphIndices[i]; builder.BuildFromGlyphIndex(gindex, -1); GlyphImage glyphImg = null; if (textureKind == TextureKind.Msdf) { var glyphToContour = new GlyphContourBuilder(); //glyphToContour.Read(builder.GetOutputPoints(), builder.GetOutputContours()); builder.ReadShapes(glyphToContour); msdfGenParams.shapeScale = 1f / 64; //as original glyphImg = MsdfGlyphGen.CreateMsdfImage(glyphToContour, msdfGenParams); } else { //create alpha channel texture aggTextureGen.TextureKind = textureKind; glyphImg = aggTextureGen.CreateGlyphImage(builder, pxscale); } // atlasBuilder.AddGlyph(gindex, glyphImg); onFinishTotal(gindex, glyphImg, null); } onFinishTotal(0, null, atlasBuilder); }
/// <summary> /// get from cache or create a new one /// </summary> /// <param name="reqFont"></param> /// <returns></returns> public SimpleFontAtlas GetFontAtlas(RequestFont reqFont, out GLBitmap glBmp) { #if DEBUG _dbugStopWatch.Reset(); _dbugStopWatch.Start(); #endif int fontKey = reqFont.FontKey; SimpleFontAtlas fontAtlas; if (!_createdAtlases.TryGetValue(fontKey, out fontAtlas)) { //check from pre-built cache (if availiable) Typeface resolvedTypeface = textServices.ResolveTypeface(reqFont); string fontTextureFile = reqFont.Name + " " + fontKey; string resolveFontFile = fontTextureFile + ".info"; string fontTextureInfoFile = resolveFontFile; string fontTextureImg = fontTextureInfoFile + ".png"; if (StorageService.Provider.DataExists(fontTextureInfoFile)) { SimpleFontAtlasBuilder atlasBuilder2 = new SimpleFontAtlasBuilder(); using (System.IO.Stream dataStream = StorageService.Provider.ReadDataStream(fontTextureInfoFile)) { try { fontAtlas = atlasBuilder2.LoadAtlasInfo(dataStream); fontAtlas.TotalGlyph = ReadGlyphImages(fontTextureImg); fontAtlas.OriginalFontSizePts = reqFont.SizeInPoints; _createdAtlases.Add(fontKey, fontAtlas); // //calculate some commonly used values fontAtlas.SetTextureScaleInfo( resolvedTypeface.CalculateScaleToPixelFromPointSize(fontAtlas.OriginalFontSizePts), resolvedTypeface.CalculateScaleToPixelFromPointSize(reqFont.SizeInPoints)); //TODO: review here, use scaled or unscaled values fontAtlas.SetCommonFontMetricValues( resolvedTypeface.Ascender, resolvedTypeface.Descender, resolvedTypeface.LineGap, resolvedTypeface.CalculateRecommendLineSpacing()); } catch (Exception ex) { throw ex; } } } else { GlyphImage totalGlyphsImg = null; SimpleFontAtlasBuilder atlasBuilder = null; var textureGen = new GlyphTextureBitmapGenerator(); textureGen.CreateTextureFontFromScriptLangs( resolvedTypeface, reqFont.SizeInPoints, _textureKind, _textureBuildDetails, (glyphIndex, glyphImage, outputAtlasBuilder) => { if (outputAtlasBuilder != null) { //finish atlasBuilder = outputAtlasBuilder; } } ); // totalGlyphsImg = atlasBuilder.BuildSingleImage(); //if (reqFont.SizeInPoints == 14 && cacheImg != null) //{ // totalGlyphsImg = cacheImg; //} //totalGlyphsImg = Sharpen(totalGlyphsImg, 1); //test shapen primary image //- // //create atlas fontAtlas = atlasBuilder.CreateSimpleFontAtlas(); fontAtlas.TotalGlyph = totalGlyphsImg; #if DEBUG //save glyph image for debug //PixelFarm.Agg.ActualImage.SaveImgBufferToPngFile( // totalGlyphsImg.GetImageBuffer(), // totalGlyphsImg.Width * 4, // totalGlyphsImg.Width, totalGlyphsImg.Height, // "d:\\WImageTest\\total_" + reqFont.Name + "_" + reqFont.SizeInPoints + ".png"); ////save image to cache SaveImgBufferToFile(totalGlyphsImg, fontTextureImg); #endif //cache the atlas _createdAtlases.Add(fontKey, fontAtlas); // //calculate some commonly used values fontAtlas.SetTextureScaleInfo( resolvedTypeface.CalculateScaleToPixelFromPointSize(fontAtlas.OriginalFontSizePts), resolvedTypeface.CalculateScaleToPixelFromPointSize(reqFont.SizeInPoints)); //TODO: review here, use scaled or unscaled values fontAtlas.SetCommonFontMetricValues( resolvedTypeface.Ascender, resolvedTypeface.Descender, resolvedTypeface.LineGap, resolvedTypeface.CalculateRecommendLineSpacing()); /// #if DEBUG _dbugStopWatch.Stop(); System.Diagnostics.Debug.WriteLine("build font atlas: " + _dbugStopWatch.ElapsedMilliseconds + " ms"); #endif //save font info to cache using (System.IO.MemoryStream ms = new System.IO.MemoryStream()) { atlasBuilder.SaveAtlasInfo(ms); StorageService.Provider.SaveData(fontTextureInfoFile, ms.ToArray()); } } } glBmp = _loadedGlyphs.GetOrCreateNewOne(fontAtlas); return(fontAtlas); }