public GlyphTextureBitmapGenUserControl() { InitializeComponent(); _glyphTextureBitmapController = new GlyphTextureBitmapGenerator(); SelectedScriptLangs = new List <Typography.OpenFont.ScriptLang>(); FontSizeInPoints = 18;//default }
/// <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); }
public void Build( GlyphTextureBitmapGenerator glyphTextureGen, Typeface typeface, float fontSizeInPoints, TextureKind textureKind, GlyphTextureBuildDetail[] buildDetails) { #if DEBUG //overall, glyph atlas generation time System.Diagnostics.Stopwatch dbugStopWatch = new System.Diagnostics.Stopwatch(); dbugStopWatch.Start(); #endif var atlasBuilder = new SimpleBitmapAtlasBuilder(); glyphTextureGen.CreateTextureFontFromBuildDetail( atlasBuilder, typeface, fontSizeInPoints, textureKind, buildDetails); //3. set information before write to font-info atlasBuilder.SpaceCompactOption = SimpleBitmapAtlasBuilder.CompactOption.ArrangeByHeight; atlasBuilder.SetAtlasFontInfo(typeface.Name, fontSizeInPoints); //4. merge all glyph in the builder into a single image using (MemBitmap totalGlyphsImg = atlasBuilder.BuildSingleImage(true)) { if (TextureInfoFilename == null) { //use random suffix string random_suffix = Guid.NewGuid().ToString().Substring(0, 7); string textureName = typeface.Name.ToLower() + "_" + random_suffix + ".info"; string output_imgFilename = textureName + ".png"; TextureInfoFilename = textureName; OutputImgFilename = output_imgFilename; } //5. save atlas info to disk using (FileStream fs = new FileStream(TextureInfoFilename, FileMode.Create)) { atlasBuilder.SaveAtlasInfo(fs); } //6. save total-glyph-image to disk totalGlyphsImg.SaveImage(OutputImgFilename); } #if DEBUG dbugStopWatch.Stop(); dbugBuildTimeMillisec = dbugStopWatch.ElapsedMilliseconds; #endif }
private void cmdMakeFromScriptLangs_Click(object sender, EventArgs e) { //create a simple stencil texture font //string sampleFontFile = "../../../TestFonts/tahoma.ttf"; if (this.textBox1.Text == null || _typeface == null) { return; } if (SelectedScriptLangs.Count == 0) { return; } // string sampleFontFile = _typeface.Filename ?? ""; TextureKind selectedTextureKind = (TextureKind)lstTextureType.SelectedItem; char[] chars = this.textBox1.Text.ToCharArray(); string bitmapImgSaveFileName = "d:\\WImageTest\\sample_" + selectedTextureKind + "_" + System.IO.Path.GetFileNameWithoutExtension(sampleFontFile); bool saveEachGlyphSeparatly = chkSaveEachGlyph.Checked; var textureGen = new GlyphTextureBitmapGenerator(); textureGen.CreateTextureFontFromScriptLangs( _typeface, FontSizeInPoints, selectedTextureKind, SelectedScriptLangs.ToArray(), (gindex, glyphImg, atlasBuilder) => { if (atlasBuilder != null) { atlasBuilder.CompactGlyphSpace = chkCompactGlyphSpace.Checked; GlyphImage totalGlyphs = atlasBuilder.BuildSingleImage(); SaveImgBufferToFile(totalGlyphs, bitmapImgSaveFileName + ".png"); atlasBuilder.SaveFontInfo(bitmapImgSaveFileName + ".xml"); MessageBox.Show("glyph gen " + bitmapImgSaveFileName); } else { //save each glyph if (saveEachGlyphSeparatly) { SaveImgBufferToFile(glyphImg, bitmapImgSaveFileName + "_" + gindex + ".png"); } } }); }
protected override void OnReadyForInitGLShaderProgram() { //just an example //this is slow on init. //since we must wait until msdf texture generation is complete. //in real-world, we should use caching. using (System.IO.FileStream fs = new System.IO.FileStream("Samples\\SourceSansPro-Regular.ttf", System.IO.FileMode.Open)) { _typeface = new OpenFontReader().Read(fs); } var reqFont = new PixelFarm.Drawing.RequestFont("Source Sans Pro", 32); //1. create glyph-texture-bitmap generator var glyphTextureGen = new GlyphTextureBitmapGenerator(); glyphTextureGen.MsdfGenVersion = 3; //2. generate the glyphs var atlasBuilder = new SimpleBitmapAtlasBuilder(); glyphTextureGen.CreateTextureFontFromBuildDetail( atlasBuilder, _typeface, reqFont.SizeInPoints, TextureKind.Msdf, GlyphTextureCustomConfigs.TryGetGlyphTextureBuildDetail( Typography.Text.GlobalTextService.TxtClient.ResolveFont(reqFont), false, false) ); //3. set information before write to font-info atlasBuilder.SpaceCompactOption = SimpleBitmapAtlasBuilder.CompactOption.ArrangeByHeight; //4. merge all glyph in the builder into a single image PixelFarm.CpuBlit.MemBitmap totalGlyphsImg = atlasBuilder.BuildSingleImage(true); //------------------------------------------------------------- //5. create a simple font atlas from information inside this atlas builder. _fontAtlas = atlasBuilder.CreateSimpleBitmapAtlas(); _fontAtlas.SetMainBitmap(totalGlyphsImg, true); byte[] codepoint = System.Text.Encoding.UTF8.GetBytes("AB"); _glyphIndex_0 = _typeface.GetGlyphIndex(codepoint[0]); _glyphIndex_1 = _typeface.GetGlyphIndex(codepoint[1]); }
public static void BuildFontAtlas(AtlasProject atlasProj) { foreach (AtlasItemSourceFile atlasSourceFile in atlasProj.Items) { if (atlasSourceFile.Kind == AtlasItemSourceKind.FontAtlasConfig && atlasSourceFile.FontBuilderConfig != null) { FontBuilderConfig config = atlasSourceFile.FontBuilderConfig; foreach (FontBuilderTask builderTask in config.BuilderTasks) { //1. create glyph-texture-bitmap generator var glyphTextureGen = new GlyphTextureBitmapGenerator(); glyphTextureGen.SetSvgBmpBuilderFunc(SvgBuilderHelper.ParseAndRenderSvg); //2. generate the glyphs if (builderTask.TextureKind == TextureKind.Msdf) { glyphTextureGen.MsdfGenVersion = 3; } Typography.OpenFont.Typeface typeface = atlasProj.GetTypeface(config.FontFilename); //TODO: add other font styles RequestFont reqFont = new RequestFont(typeface.Name, builderTask.Size, FontStyle.Regular); string textureName = typeface.Name.ToLower() + "_" + reqFont.FontKey; string outputDir = Path.GetDirectoryName(atlasProj.OutputFilename); FontAtlasBuilderHelper builderHelper = new FontAtlasBuilderHelper(); builderHelper.TextureInfoFilename = outputDir + Path.DirectorySeparatorChar + textureName; builderHelper.OutputImgFilename = outputDir + Path.DirectorySeparatorChar + textureName + ".png"; builderHelper.Build(glyphTextureGen, typeface, builderTask.Size, builderTask.TextureKind, builderTask.TextureBuildDetails.ToArray(), reqFont.FontKey ); } } } }
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()); /// }
/// <summary> /// get from cache or create a new one /// </summary> /// <param name="reqFont"></param> /// <returns></returns> public SimpleFontAtlas GetFontAtlas(RequestFont reqFont, out B outputBitmap) { #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 fontTextureImgFilename = fontTextureInfoFile + ".png"; //check if the file exist if (StorageService.Provider.DataExists(fontTextureInfoFile) && StorageService.Provider.DataExists(fontTextureImgFilename)) { SimpleFontAtlasBuilder atlasBuilder = new SimpleFontAtlasBuilder(); using (System.IO.Stream dataStream = StorageService.Provider.ReadDataStream(fontTextureInfoFile)) { try { fontAtlas = atlasBuilder.LoadFontInfo(dataStream); fontAtlas.TotalGlyph = ReadGlyphImages(fontTextureImgFilename); fontAtlas.OriginalFontSizePts = reqFont.SizeInPoints; _createdAtlases.Add(fontKey, fontAtlas); } catch (Exception ex) { throw ex; } } } else { GlyphImage totalGlyphsImg = null; SimpleFontAtlasBuilder atlasBuilder = null; var glyphTextureGen = new GlyphTextureBitmapGenerator(); glyphTextureGen.CreateTextureFontBuildDetail( resolvedTypeface, reqFont.SizeInPoints, _textureKind, GlyphTextureCustomConfigs.TryGetGlyphTextureBuildDetail(reqFont), (glyphIndex, glyphImage, outputAtlasBuilder) => { if (outputAtlasBuilder != null) { //finish atlasBuilder = outputAtlasBuilder; } } ); atlasBuilder.SpaceCompactOption = SimpleFontAtlasBuilder.CompactOption.ArrangeByHeight; 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, fontTextureImgFilename); #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.SaveFontInfo(ms); //System.IO.File.WriteAllBytes(fontTextureInfoFile, ms.ToArray()); StorageService.Provider.SaveData(fontTextureInfoFile, ms.ToArray()); #if DEBUG //write temp debug info System.IO.File.WriteAllText(fontTextureInfoFile + ".txt", reqFont.Name + ",size" + reqFont.SizeInPoints + "pts"); #endif } } } outputBitmap = _loadedGlyphs.GetOrCreateNewOne(fontAtlas); return(fontAtlas); }
//----------------------------------------------------------------------------------------------- void BuiltAtlas_FromUserOptions(List <GlyphTextureBuildDetail> buildDetails) { //we can create font atlas by specific script-langs //------------------------------------------------------------------------------- //setting... Typeface typeface = _typeface; if (!float.TryParse(txtSelectedFontSize.Text, out float fontSizeInPoints)) { MessageBox.Show("err: selected font size " + txtSelectedFontSize.Text); return; } //create request font, indeed we need its 'FontKey' PixelFarm.Drawing.RequestFont reqFont = new PixelFarm.Drawing.RequestFont( typeface.Name, fontSizeInPoints ); //user may want only some script lang (not all script in the font) //and each script user may want different glyph-gen technique. //so we use GlyphTextureBuildDetail to describe that information. if (buildDetails.Count == 0) { MessageBox.Show("please select some script"); return; } //------------------------------------------------------------------------------- //1. create glyph-texture-bitmap generator var glyphTextureGen = new GlyphTextureBitmapGenerator(); glyphTextureGen.SetSvgBmpBuilderFunc(SvgBuilderHelper.ParseAndRenderSvg); //2. generate the glyphs TextureKindAndDescription textureKindAndDesc = (TextureKindAndDescription)this.cmbTextureKind.SelectedItem; if (textureKindAndDesc.Kind == TextureKind.Msdf) { glyphTextureGen.MsdfGenVersion = textureKindAndDesc.TechniqueDetail; } FontAtlasBuilderHelper helper = new FontAtlasBuilderHelper(); helper.Build(glyphTextureGen, typeface, fontSizeInPoints, textureKindAndDesc.Kind, buildDetails.ToArray()); #if DEBUG this.Text += ", finished: build time(ms)=" + helper.dbugBuildTimeMillisec; System.Diagnostics.Debug.WriteLine("font atlas build time (ms): " + helper.dbugBuildTimeMillisec); #endif ///------------------------------------------------ //lets view result ... SimpleUtils.DisposeExistingPictureBoxImage(picOutput); uiFontAtlasFileViewer1.LoadFontAtlasFile(helper.TextureInfoFilename, helper.OutputImgFilename); this.picOutput.Image = new Bitmap(helper.OutputImgFilename); this.lblOutput.Text = "Output: " + helper.OutputImgFilename; ////read .info back and convert to base64 //byte[] atlas_info_content = File.ReadAllBytes(textureName + ".info"); //string base64 = Convert.ToBase64String(atlas_info_content); ////create atlas //SimpleFontAtlas fontAtlas = atlasBuilder.CreateSimpleFontAtlas(); //fontAtlas.TotalGlyph = totalGlyphsImg; }
void BuildAtlas_FromInputChars() { if (!float.TryParse(txtSelectedFontSize.Text, out float fontSizeInPoints)) { MessageBox.Show("err: selected font size " + txtSelectedFontSize.Text); return; } //1. create glyph-texture-bitmap generator var glyphTextureGen = new GlyphTextureBitmapGenerator(); glyphTextureGen.SetSvgBmpBuilderFunc(SvgBuilderHelper.ParseAndRenderSvg); //2. generate the glyphs TextureKindAndDescription textureKindAndDesc = (TextureKindAndDescription)this.cmbTextureKind.SelectedItem; if (textureKindAndDesc.Kind == TextureKind.Msdf) { glyphTextureGen.MsdfGenVersion = textureKindAndDesc.TechniqueDetail; } var atlasBuilder = new SimpleBitmapAtlasBuilder(); glyphTextureGen.CreateTextureFontFromInputChars( atlasBuilder, _typeface, fontSizeInPoints, textureKindAndDesc.Kind, GetUniqueChars() ); //3. set information before write to font-info atlasBuilder.SpaceCompactOption = SimpleBitmapAtlasBuilder.CompactOption.ArrangeByHeight; //4. merge all glyph in the builder into a single image MemBitmap totalGlyphsImg = atlasBuilder.BuildSingleImage(true); string fontTextureImg = "test_glyph_atlas.png"; //5. save to png totalGlyphsImg.SaveImage(fontTextureImg); //----------------------------------------------- //let view result... SimpleUtils.DisposeExistingPictureBoxImage(picOutput); this.lblOutput.Text = "output: " + fontTextureImg; this.picOutput.Image = new Bitmap(fontTextureImg); #if DEBUG //save glyph image for debug //PixelFarm.Agg.ActualImage.SaveImgBufferToPngFile( // totalGlyphsImg.GetImageBuffer(), // totalGlyphsImg.Width * 4, // totalGlyphsImg.Width, totalGlyphsImg.Height, // "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()); /// }
private void cmdMakeFromScriptLangs_Click(object sender, EventArgs e) { //create a simple stencil texture font //string sampleFontFile = "../../../TestFonts/tahoma.ttf"; if (this.textBox1.Text == null || _typeface == null) { return; } if (SelectedScriptLangs.Count == 0) { return; } // string sampleFontFile = _typeface.Filename ?? ""; TextureKind selectedTextureKind = (TextureKind)lstTextureType.SelectedItem; char[] chars = this.textBox1.Text.ToCharArray(); string bitmapImgSaveFileName = "d:\\WImageTest\\sample_" + selectedTextureKind + "_" + System.IO.Path.GetFileNameWithoutExtension(sampleFontFile); //------------ //TODO: review here again, this is not a good way, //it is only temp fix for Tahoma. var _textureBuildDetails = new GlyphTextureBuildDetail[] { new GlyphTextureBuildDetail { ScriptLang = ScriptLangs.Latin, DoFilter = false, HintTechnique = Typography.Contours.HintTechnique.TrueTypeInstruction_VerticalOnly }, new GlyphTextureBuildDetail { OnlySelectedGlyphIndices = new char[] { 'x', 'X', '7' }, DoFilter = true, HintTechnique = Typography.Contours.HintTechnique.TrueTypeInstruction_VerticalOnly }, // new GlyphTextureBuildDetail { ScriptLang = ScriptLangs.Thai, DoFilter = true, HintTechnique = Typography.Contours.HintTechnique.None }, }; //------------ bool saveEachGlyphSeparatly = chkSaveEachGlyph.Checked; var textureGen = new GlyphTextureBitmapGenerator(); textureGen.CreateTextureFontFromScriptLangs( _typeface, FontSizeInPoints, selectedTextureKind, _textureBuildDetails, (gindex, glyphImg, atlasBuilder) => { if (atlasBuilder != null) { atlasBuilder.CompactGlyphSpace = chkCompactGlyphSpace.Checked; GlyphImage totalGlyphs = atlasBuilder.BuildSingleImage(); SaveImgBufferToFile(totalGlyphs, bitmapImgSaveFileName + ".png"); using (System.IO.FileStream fs = new System.IO.FileStream(bitmapImgSaveFileName + ".xml", System.IO.FileMode.Create)) { atlasBuilder.SaveAtlasInfo(fs); } MessageBox.Show("glyph gen " + bitmapImgSaveFileName); } else { //save each glyph if (saveEachGlyphSeparatly) { SaveImgBufferToFile(glyphImg, bitmapImgSaveFileName + "_" + gindex + ".png"); } } }); }