public BitmapAtlasManager(TextureKind textureKind, LoadNewBmpDelegate <SimpleBitmaptAtlas, B> _createNewDel) : this(textureKind) { //glyph cahce for specific atlas SetLoadNewBmpDel(_createNewDel); }
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); }
public SimpleBitmapAtlasBuilder CreateTextureFontFromInputChars( Typeface typeface, float sizeInPoint, TextureKind textureKind, char[] chars, OnEachGlyph onEachGlyphDel = null) { _onEachGlyphDel = onEachGlyphDel; //convert input chars into glyphIndex List <ushort> glyphIndices = new List <ushort>(chars.Length); int i = 0; foreach (char ch in chars) { glyphIndices.Add(typeface.GetGlyphIndex(ch)); i++; } //------------------------------------------------------------- var atlasBuilder = new SimpleBitmapAtlasBuilder(); atlasBuilder.SetAtlasInfo(textureKind, sizeInPoint); //------------------------------------------------------------- //we can specfic subset with special setting for each set CreateTextureFontFromGlyphIndices(typeface, sizeInPoint, HintTechnique.TrueTypeInstruction_VerticalOnly, atlasBuilder, GetUniqueGlyphIndexList(glyphIndices)); _onEachGlyphDel = null;//reset return(atlasBuilder); }
public BitmapFontManager(TextureKind textureKind, LayoutFarm.OpenFontTextService textServices, LoadNewBmpDelegate <SimpleFontAtlas, B> _createNewDel) : this(textureKind, textServices) { //glyph cahce for specific atlas SetLoadNewBmpDel(_createNewDel); }
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"); } } }); }
public MySimpleGLBitmapAtlasManager(TextureKind textureKind) : base(textureKind) { SetLoadNewBmpDel(atlas => { //create new one AtlasItemImage totalGlyphImg = atlas.TotalImg; //load to glbmp GLBitmap found = new GLBitmap(totalGlyphImg.Bitmap, false); found.IsYFlipped = false; return(found); }); }
public SimpleBitmapAtlasBuilder CreateTextureFontFromBuildDetail( Typeface typeface, float sizeInPoint, TextureKind textureKind, GlyphTextureBuildDetail[] details, OnEachGlyph onEachGlyphDel = null) { _onEachGlyphDel = onEachGlyphDel; //------------------------------------------------------------- var atlasBuilder = new SimpleBitmapAtlasBuilder(); 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, 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.OnlySelectedGlyphIndices ); } } _onEachGlyphDel = null;//reset return(atlasBuilder); }
public MySimpleGLBitmapFontManager(TextureKind textureKind, LayoutFarm.OpenFontTextService textServices) { this.textServices = textServices; //glyph cahce for specific atlas _loadedGlyphs = new GLBitmapCache <SimpleFontAtlas>(atlas => { //create new one Typography.Rendering.GlyphImage totalGlyphImg = atlas.TotalGlyph; //load to glbmp GLBitmap found = new GLBitmap(totalGlyphImg.Width, totalGlyphImg.Height, totalGlyphImg.GetImageBuffer(), false); found.IsInvert = false; return(found); }); _textureKind = textureKind; }
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++; } CreateTextureFontFromGlyphIndices(typeface, sizeInPoint, textureKind, GetUniqueGlyphIndexList(glyphIndices), onFinishTotal); }
public MySimpleGLBitmapFontManager(TextureKind textureKind, LayoutFarm.OpenFontTextService textServices) : base(textureKind, textServices) { SetLoadNewBmpDel(atlas => { //create new one GlyphImage totalGlyphImg = atlas.TotalGlyph; //load to glbmp GLBitmap found = new GLBitmap( PixelFarm.CpuBlit.MemBitmap.CreateFromCopy( totalGlyphImg.Width, totalGlyphImg.Height, totalGlyphImg.GetImageBuffer()), true); //set true=> glbmp is the original owner of the membmp, when glbmp is disposed => the membmp is disposed too found.IsYFlipped = false; return(found); }); }
public void CreateTextureFontFromScriptLangs( Typeface typeface, float sizeInPoint, TextureKind textureKind, ScriptLang[] scLangs, OnEachFinishTotal onFinishTotal) { //2. find associated glyph index base on input script langs List <ushort> outputGlyphIndexList = new List <ushort>(); // foreach (ScriptLang scLang in scLangs) { typeface.CollectAllAssociateGlyphIndex(outputGlyphIndexList, scLang); } // CreateTextureFontFromGlyphIndices(typeface, sizeInPoint, textureKind, GetUniqueGlyphIndexList(outputGlyphIndexList), onFinishTotal); }
public void AddSimpleAtlasFile(RequestFont reqFont, string bitmapAtlasFile, string imgFile, TextureKind textureKind) { //TODO: use 'File' provider to access system file var fontAtlasFile = new BitmapAtlasFile(); using (FileStream fs = new FileStream(bitmapAtlasFile, FileMode.Open)) { fontAtlasFile.Read(fs); } _atlasList.Add(new TempMergingAtlasInfo() { reqFont = reqFont, simpleFontAtlasFile = bitmapAtlasFile, imgFile = imgFile, fontAtlasFile = fontAtlasFile, textureKind = textureKind }); }
private static TextureKind Kind(string path) { TextureKind kind = TextureKind.None; foreach (var _temp in dictionary) { for (int i = 0; i < _temp.Value.Count; i++) { if (path.StartsWith(_temp.Value[i])) { kind = _temp.Key; break; } } if (kind != TextureKind.None) { break; } } return(kind); }
public static void Start(TextureImporter texture) { string path = AssetDatabase.GetAssetPath(texture); TextureKind kind = Kind(path); if (kind == TextureKind.None) { return; } switch (kind) { case TextureKind.Texture: case TextureKind.TexturePowerof2: texture.textureType = TextureImporterType.Default; texture.textureShape = TextureImporterShape.Texture2D; break; case TextureKind.Image: texture.textureType = TextureImporterType.Sprite; break; case TextureKind.NormalMap: texture.textureType = TextureImporterType.NormalMap; texture.textureShape = TextureImporterShape.Texture2D; break; } texture.sRGBTexture = true; bool alpha = texture.DoesSourceTextureHaveAlpha(); texture.alphaSource = alpha ? TextureImporterAlphaSource.FromInput : TextureImporterAlphaSource.None; texture.alphaIsTransparency = alpha; texture.npotScale = kind == TextureKind.TexturePowerof2 ? TextureImporterNPOTScale.ToNearest : TextureImporterNPOTScale.None; texture.isReadable = false; texture.mipmapEnabled = false; texture.crunchedCompression = true; PlatformSettings(texture, "ios"); PlatformSettings(texture, "android"); }
public void PrepareStringForRenderVx(RenderVxFormattedString renderVx, char[] buffer, int startAt, int len) { int j = buffer.Length; //create temp buffer span that describe the part of a whole char buffer TextBufferSpan textBufferSpan = new TextBufferSpan(buffer, startAt, len); //ask text service to parse user input char buffer and create a glyph-plan-sequence (list of glyph-plan) //with specific request font GlyphPlanSequence glyphPlanSeq = _textServices.CreateGlyphPlanSeq(ref textBufferSpan, font); float scale = _fontAtlas.TargetTextureScale; int recommendLineSpacing = _fontAtlas.OriginalRecommendLineSpacing; //-------------------------- //TODO: //if (x,y) is left top //we need to adjust y again float x = 0; float y = 0; y -= ((recommendLineSpacing) * scale); renderVx.RecommmendLineSpacing = (int)(recommendLineSpacing * scale); // float scaleFromTexture = _finalTextureScale; TextureKind textureKind = _fontAtlas.TextureKind; //-------------------------- //TODO: review render steps //NOTE: // -glyphData.TextureXOffset => restore to original pos // -glyphData.TextureYOffset => restore to original pos // ideal_x = (float)(x + (glyph.x * scale - glyphData.TextureXOffset) * scaleFromTexture); // ideal_y = (float)(y + (glyph.y * scale - glyphData.TextureYOffset + srcRect.Height) * scaleFromTexture); //-------------------------- float g_x = 0; float g_y = 0; int baseY = (int)Math.Round(y); int n = glyphPlanSeq.len; int endBefore = glyphPlanSeq.startAt + n; //*** _glsx.SetAssociatedTextureInfo(_glBmp); // vboBufferList2.Clear(); indexList2.Clear(); float acc_x = 0; float acc_y = 0; for (int i = glyphPlanSeq.startAt; i < endBefore; ++i) { UnscaledGlyphPlanList glyphPlanList = GlyphPlanSequence.UnsafeGetInteralGlyphPlanList(glyphPlanSeq); UnscaledGlyphPlan glyph = glyphPlanList[i]; Typography.Rendering.TextureFontGlyphData glyphData; if (!_fontAtlas.TryGetGlyphDataByGlyphIndex(glyph.glyphIndex, out glyphData)) { //if no glyph data, we should render a missing glyph *** continue; } //-------------------------------------- //TODO: review precise height in float //-------------------------------------- PixelFarm.Drawing.Rectangle srcRect = ConvToRect(glyphData.Rect); float ngx = acc_x + (float)Math.Round(glyph.OffsetX * scale); float ngy = acc_y + (float)Math.Round(glyph.OffsetY * scale); //NOTE: // -glyphData.TextureXOffset => restore to original pos // -glyphData.TextureYOffset => restore to original pos //-------------------------- g_x = (float)(x + (ngx - glyphData.TextureXOffset) * scaleFromTexture); //ideal x g_y = (float)(y + (ngy - glyphData.TextureYOffset + srcRect.Height) * scaleFromTexture); acc_x += (float)Math.Round(glyph.AdvanceX * scale); //g_x = (float)Math.Round(g_x); g_y = (float)Math.Floor(g_y); switch (textureKind) { case TextureKind.Msdf: _glsx.DrawSubImageWithMsdf(_glBmp, ref srcRect, g_x, g_y, scaleFromTexture); break; case TextureKind.StencilGreyScale: //stencil gray scale with fill-color _glsx.DrawGlyphImageWithStecil(_glBmp, ref srcRect, g_x, g_y, scaleFromTexture); break; case TextureKind.Bitmap: _glsx.DrawSubImage(_glBmp, ref srcRect, g_x, g_y, scaleFromTexture); break; case TextureKind.StencilLcdEffect: _glsx.WriteVboToList( vboBufferList2, indexList2, ref srcRect, g_x, g_y, scaleFromTexture); break; } } //--------- DrawingGL.GLRenderVxFormattedString renderVxFormattedString = (DrawingGL.GLRenderVxFormattedString)renderVx; renderVxFormattedString.IndexArray = indexList2.ToArray(); renderVxFormattedString.VertexCoords = vboBufferList2.ToArray(); renderVxFormattedString.VertexCount = indexList2.Count; }
public void DrawString(char[] buffer, int startAt, int len, double x, double y) { _glsx.FontFillColor = painter.FontFillColor; int j = buffer.Length; //create temp buffer span that describe the part of a whole char buffer TextBufferSpan textBufferSpan = new TextBufferSpan(buffer, startAt, len); //ask text service to parse user input char buffer and create a glyph-plan-sequence (list of glyph-plan) //with specific request font GlyphPlanSequence glyphPlanSeq = _textServices.CreateGlyphPlanSeq(ref textBufferSpan, font); float scale = _fontAtlas.TargetTextureScale; int recommendLineSpacing = _fontAtlas.OriginalRecommendLineSpacing; //-------------------------- //TODO: //if (x,y) is left top //we need to adjust y again y -= ((_fontAtlas.OriginalRecommendLineSpacing) * scale); EnsureLoadGLBmp(); // float scaleFromTexture = _finalTextureScale; TextureKind textureKind = _fontAtlas.TextureKind; float g_x = 0; float g_y = 0; int baseY = (int)Math.Round(y); int n = glyphPlanSeq.len; int endBefore = glyphPlanSeq.startAt + n; //------------------------------------- _glsx.LoadTexture1(_glBmp); //------------------------------------- _vboBufferList.Clear(); //clear before use _indexList.Clear(); //clear before use float acc_x = 0; float acc_y = 0; for (int i = glyphPlanSeq.startAt; i < endBefore; ++i) { UnscaledGlyphPlanList glyphPlanList = GlyphPlanSequence.UnsafeGetInteralGlyphPlanList(glyphPlanSeq); UnscaledGlyphPlan glyph = glyphPlanList[i]; Typography.Rendering.TextureFontGlyphData glyphData; if (!_fontAtlas.TryGetGlyphDataByGlyphIndex(glyph.glyphIndex, out glyphData)) { //if no glyph data, we should render a missing glyph *** continue; } //-------------------------------------- //TODO: review precise height in float //-------------------------------------- PixelFarm.Drawing.Rectangle srcRect = ConvToRect(glyphData.Rect); float ngx = acc_x + (float)Math.Round(glyph.OffsetX * scale); float ngy = acc_y + (float)Math.Round(glyph.OffsetY * scale); //NOTE: // -glyphData.TextureXOffset => restore to original pos // -glyphData.TextureYOffset => restore to original pos //-------------------------- g_x = (float)(x + (ngx - glyphData.TextureXOffset) * scaleFromTexture); //ideal x g_y = (float)(y + (ngy - glyphData.TextureYOffset + srcRect.Height) * scaleFromTexture); acc_x += (float)Math.Round(glyph.AdvanceX * scale); //g_x = (float)Math.Round(g_x); g_y = (float)Math.Floor(g_y); switch (textureKind) { case TextureKind.Msdf: _glsx.DrawSubImageWithMsdf(_glBmp, ref srcRect, g_x, g_y, scaleFromTexture); break; case TextureKind.StencilGreyScale: //stencil gray scale with fill-color _glsx.DrawGlyphImageWithStecil(_glBmp, ref srcRect, g_x, g_y, scaleFromTexture); break; case TextureKind.Bitmap: _glsx.DrawSubImage(_glBmp, ref srcRect, g_x, g_y, scaleFromTexture); break; case TextureKind.StencilLcdEffect: _glsx.WriteVboToList( _vboBufferList, _indexList, ref srcRect, g_x, g_y, scaleFromTexture); break; } } //------- //we create vbo first //then render _glsx.DrawGlyphImageWithSubPixelRenderingTechnique3(_vboBufferList.ToArray(), _indexList.ToArray()); }
public void DrawString(Painter p, char[] buffer, int startAt, int len, double x, double y) { //if (_stencilBmp == null) //{ // //create a stencil bmp // _stencilBmp = new ActualBitmap(p.Width, p.Height); // _stencilBlender = new PixelProcessing.SubBitmapBlender(_stencilBmp, new PixelProcessing.PixelBlenderBGRA()); // _backPainter = AggPainter.Create(_stencilBmp); // //------ //} int j = buffer.Length; //create temp buffer span that describe the part of a whole char buffer TextBufferSpan textBufferSpan = new TextBufferSpan(buffer, startAt, len); //ask text service to parse user input char buffer and create a glyph-plan-sequence (list of glyph-plan) //with specific request font GlyphPlanSequence glyphPlanSeq = _textServices.CreateGlyphPlanSeq(ref textBufferSpan, _font); Typeface typeface = _textServices.ResolveTypeface(_font); float scale = typeface.CalculateScaleToPixelFromPointSize(_font.SizeInPoints); int recommendLineSpacing = (int)_font.LineSpacingInPixels; //-------------------------- //TODO: //if (x,y) is left top //we need to adjust y again y -= _font.LineSpacingInPixels; // float scaleFromTexture = _finalTextureScale; TextureKind textureKind = _fontAtlas.TextureKind; float g_x = 0; float g_y = 0; int baseY = (int)Math.Round(y); //------------------------------------- //load texture //_pcx.LoadTexture1(_glBmp); //------------------------------------- float acc_x = 0; float acc_y = 0; p.DrawImage(_fontBmp, 100, 100); int seqLen = glyphPlanSeq.Count; for (int i = 0; i < seqLen; ++i) { UnscaledGlyphPlan glyph = glyphPlanSeq[i]; TextureGlyphMapData glyphData; if (!_fontAtlas.TryGetGlyphMapData(glyph.glyphIndex, out glyphData)) { //if no glyph data, we should render a missing glyph *** continue; } //-------------------------------------- //TODO: review precise height in float //-------------------------------------- int srcX, srcY, srcW, srcH; glyphData.GetRect(out srcX, out srcY, out srcW, out srcH); float ngx = acc_x + (float)Math.Round(glyph.OffsetX * scale); float ngy = acc_y + (float)Math.Round(glyph.OffsetY * scale); //NOTE: // -glyphData.TextureXOffset => restore to original pos // -glyphData.TextureYOffset => restore to original pos //-------------------------- g_x = (float)(x + (ngx - glyphData.TextureXOffset) * scaleFromTexture); //ideal x g_y = (float)(y + (ngy - glyphData.TextureYOffset + srcH) * scaleFromTexture); acc_x += (float)Math.Round(glyph.AdvanceX * scale); //g_x = (float)Math.Round(g_x); g_y = (float)Math.Floor(g_y); //p.RenderQuality = RenderQuality.Fast; //*** the atlas is inverted so... //p.DrawImage(_fontBmp, g_x, g_y, srcX, _fontBmp.Height - (srcY), srcW, srcH); //p.DrawImage(_fontBmp, g_x, g_y); //1. draw to back buffer //_backPainter.DrawImage(_fontBmp, g_x, g_y, srcX, _fontBmp.Height - (srcY), srcW, srcH); //2. then copy content to this //p.DrawImage(_stencilBmp, 100, 100); p.DrawImage(_fontBmp, g_x, g_y, srcX, _fontBmp.Height - (srcY + srcH), srcW, srcH); switch (textureKind) { default: break; case TextureKind.StencilLcdEffect: { } break; } //copy some part from the bitmap //switch (textureKind) //{ // case TextureKind.Msdf: // _pcx.DrawSubImageWithMsdf(_glBmp, // ref srcRect, // g_x, // g_y, // scaleFromTexture); // break; // case TextureKind.StencilGreyScale: // //stencil gray scale with fill-color // _pcx.DrawGlyphImageWithStecil(_glBmp, // ref srcRect, // g_x, // g_y, // scaleFromTexture); // break; // case TextureKind.Bitmap: // _pcx.DrawSubImage(_glBmp, // ref srcRect, // g_x, // g_y, // scaleFromTexture); // break; // case TextureKind.StencilLcdEffect: // _pcx.WriteVboToList( // _vboBufferList, // _indexList, // ref srcRect, // g_x, // g_y, // scaleFromTexture); // break; //} } //------- //we create vbo first //then render }
public void DrawImage(GLPainter glPainter, AtlasImageBinder atlasImgBinder, float left, float top) { if (atlasImgBinder.State == BinderState.Loaded && atlasImgBinder.LatestPainterId != _painterId) { atlasImgBinder.State = BinderState.Unload; atlasImgBinder.LatestPainterId = _painterId; } switch (atlasImgBinder.State) { case BinderState.Loaded: { if (PixelFarm.Drawing.ImageBinder.GetCacheInnerImage(atlasImgBinder) is GLBitmap glbmp) { AtlasItem atlasItem = atlasImgBinder.AtlasItem; Rectangle srcRect = new Rectangle(atlasItem.Left, atlasItem.Top, //diff from font atlas*** atlasItem.Width, atlasItem.Height); switch (atlasImgBinder.TextureKind) { default: case TextureKind.Msdf: throw new NotSupportedException(); case TextureKind.Bitmap: { //atlasImgBinder.State = BinderState.Loaded; //ImageBinder.SetCacheInnerImage(atlasImgBinder, glbmp, false); //atlasImgBinder.AtlasItem = atlasItem; glPainter.Core.DrawSubImage(glbmp, srcRect, left, top); } break; } } } break; case BinderState.Unload: { atlasImgBinder.LatestPainterId = _painterId; //load img first if (_bmpAtlas == null || _lastestImgFile != atlasImgBinder.AtlasName) { _bmpAtlas = _atlasManager.GetBitmapAtlas(atlasImgBinder.AtlasName, out _glBmp); if (_bmpAtlas == null) { //error atlasImgBinder.State = BinderState.Error; //not found return; } _lastestImgFile = atlasImgBinder.AtlasName; } //-------- if (_bmpAtlas.TryGetItem(atlasImgBinder.ImageName, out AtlasItem atlasItem)) { //found map data Rectangle srcRect = new Rectangle(atlasItem.Left, atlasItem.Top, //diff from font atlas*** atlasItem.Width, atlasItem.Height); TextureKind textureKind = _bmpAtlas.TextureKind; switch (textureKind) { default: case TextureKind.Msdf: throw new NotSupportedException(); case TextureKind.Bitmap: { atlasImgBinder.State = BinderState.Loaded; ImageBinder.SetCacheInnerImage(atlasImgBinder, _glBmp, false); atlasImgBinder.AtlasItem = atlasItem; atlasImgBinder.SetPreviewImageSize(atlasItem.Width, atlasItem.Height); atlasImgBinder.RaiseImageChanged(); atlasImgBinder.TextureKind = textureKind; glPainter.Core.DrawSubImage(_glBmp, srcRect, left, top); } break; } } else { atlasImgBinder.State = BinderState.Error; //not found } } break; } #if DEBUG if (atlasImgBinder.State == BinderState.Unload) { } #endif }
public void DrawString(Painter p, char[] buffer, int startAt, int len, double x, double y) { AggPainter painter = p as AggPainter; if (painter == null) { return; } // int width = painter.Width; int height = painter.Height; if (!_pixelBlenderSetup) { SetupMaskPixelBlender(width, height); _pixelBlenderSetup = true; } int j = buffer.Length; //create temp buffer span that describe the part of a whole char buffer TextBufferSpan textBufferSpan = new TextBufferSpan(buffer, startAt, len); //ask text service to parse user input char buffer and create a glyph-plan-sequence (list of glyph-plan) //with specific request font GlyphPlanSequence glyphPlanSeq = _textServices.CreateGlyphPlanSeq(ref textBufferSpan, _font); float scale = 1;// _fontAtlas.TargetTextureScale; int recommendLineSpacing = (int)_font.LineSpacingInPixels; //-------------------------- //TODO: //if (x,y) is left top //we need to adjust y again y -= _font.LineSpacingInPixels; // float scaleFromTexture = _finalTextureScale; TextureKind textureKind = _fontAtlas.TextureKind; float gx = 0; float gy = 0; int baseY = (int)Math.Round(y); float acc_x = 0; float acc_y = 0; int lineHeight = (int)_font.LineSpacingInPixels;//temp //painter.DestBitmapBlender.OutputPixelBlender = maskPixelBlenderPerCompo; //change to new blender painter.DestBitmapBlender.OutputPixelBlender = _maskPixelBlenderPerCompo; //change to new blender int seqLen = glyphPlanSeq.Count; for (int i = 0; i < seqLen; ++i) { UnscaledGlyphPlan glyph = glyphPlanSeq[i]; TextureGlyphMapData glyphData; if (!_fontAtlas.TryGetGlyphMapData(glyph.glyphIndex, out glyphData)) { //if no glyph data, we should render a missing glyph *** continue; } //-------------------------------------- //TODO: review precise height in float //-------------------------------------- int srcX, srcY, srcW, srcH; glyphData.GetRect(out srcX, out srcY, out srcW, out srcH); float ngx = acc_x + (float)Math.Round(glyph.OffsetX * scale); float ngy = acc_y + (float)Math.Round(glyph.OffsetY * scale); //NOTE: // -glyphData.TextureXOffset => restore to original pos // -glyphData.TextureYOffset => restore to original pos //-------------------------- gx = (float)(x + (ngx - glyphData.TextureXOffset) * scaleFromTexture); //ideal x gy = (float)(y + (ngy - glyphData.TextureYOffset - srcH + lineHeight) * scaleFromTexture); acc_x += (float)Math.Round(glyph.AdvanceX * scale); gy = (float)Math.Floor(gy) + lineHeight; //clear with solid black color //_maskBufferPainter.Clear(Color.Black); _maskBufferPainter.FillRect(gx - 1, gy - 1, srcW + 2, srcH + 2, Color.Black); //draw 'stencil' glyph on mask-buffer _maskBufferPainter.DrawImage(_fontBmp, gx, gy, srcX, _fontBmp.Height - (srcY), srcW, srcH); //select component to render this need to render 3 times for lcd technique //1. B _maskPixelBlenderPerCompo.SelectedMaskComponent = PixelBlenderColorComponent.B; _maskPixelBlenderPerCompo.EnableOutputColorComponent = EnableOutputColorComponent.B; painter.FillRect(gx + 1, gy, srcW, srcH); //2. G _maskPixelBlenderPerCompo.SelectedMaskComponent = PixelBlenderColorComponent.G; _maskPixelBlenderPerCompo.EnableOutputColorComponent = EnableOutputColorComponent.G; painter.FillRect(gx + 1, gy, srcW, srcH); //3. R _maskPixelBlenderPerCompo.SelectedMaskComponent = PixelBlenderColorComponent.R; _maskPixelBlenderPerCompo.EnableOutputColorComponent = EnableOutputColorComponent.R; painter.FillRect(gx + 1, gy, srcW, srcH); } }
public void WriteTotalImageInfo(ushort width, ushort height, byte colorComponent, TextureKind textureKind) { _writer.Write((ushort)FontTextureObjectKind.TotalImageInfo); _writer.Write(width); _writer.Write(height); _writer.Write(colorComponent); _writer.Write((byte)textureKind); }
public void SetAtlasInfo(TextureKind textureKind, float fontSizeInPts) { this.TextureKind = textureKind; this.FontSizeInPoints = fontSizeInPts; }
public BitmapFontManager(TextureKind textureKind, LayoutFarm.OpenFontTextService textServices) { _textServices = textServices; _textureKind = textureKind; }
public void DrawString(RenderVxFormattedString renderVx, double x, double y) { RenderVxGlyphPlan[] glyphPlans = renderVx.glyphList; int n = glyphPlans.Length; EnsureLoadGLBmp(); //PERF: //TODO: review here, can we cache the glbmp for later use //not to create it every time float scaleFromTexture = _finalTextureScale; TextureKind textureKind = _fontAtlas.TextureKind; float g_x = 0; float g_y = 0; int baseY = (int)Math.Round(y); float scale = 1; for (int i = 0; i < n; ++i) { //PERF: //TODO: //render a set of glyph instead of one glyph per time *** RenderVxGlyphPlan glyph = glyphPlans[i]; Typography.Rendering.TextureFontGlyphData glyphData; if (!_fontAtlas.TryGetGlyphDataByCodePoint(glyph.glyphIndex, out glyphData)) { //if no glyph data, we should render a missing glyph *** continue; } //-------------------------------------- //TODO: review precise height in float //-------------------------------------- PixelFarm.Drawing.Rectangle srcRect = ConvToRect(glyphData.Rect); //-------------------------- g_x = (float)(x + (glyph.x * scale - glyphData.TextureXOffset) * scaleFromTexture); //ideal x g_y = (float)((glyph.y * scale - glyphData.TextureYOffset + srcRect.Height) * scaleFromTexture); switch (textureKind) { case TextureKind.Msdf: _glsx.DrawSubImageWithMsdf(_glBmp, ref srcRect, g_x, g_y, scaleFromTexture); break; case TextureKind.StencilGreyScale: //stencil gray scale with fill-color _glsx.DrawGlyphImageWithStecil(_glBmp, ref srcRect, g_x, g_y, scaleFromTexture); break; case TextureKind.Bitmap: _glsx.DrawSubImage(_glBmp, ref srcRect, g_x, g_y, scaleFromTexture); break; case TextureKind.StencilLcdEffect: _glsx.DrawGlyphImageWithSubPixelRenderingTechnique(_glBmp, ref srcRect, g_x, g_y, scaleFromTexture); break; } } }
public DefVar(TextureKind kind, DestRegister reg) { this.kind = kind; this.reg = reg; }
//create new one //load to glbmp public MySimpleGLBitmapAtlasManager(TextureKind textureKind) : base(atlas => new GLBitmap(atlas.MainBitmap, false) { IsYFlipped = false }) { }
internal void DefineVar(TextureKind kind, DestRegister reg) { switch (reg.Kind) { case RegKind.Texture: if (tex0 != null) throw new Exception ("Cannot handle multiple texture registers"); if (reg.Number != 0) throw new Exception ("Only one texture register supported"); //FIXME since we only support 2d textures, is this the right thing? if (reg.WriteMask != DestRegister.MakeMask (true, true, false, false)) throw new Exception ("Cannot handle a texture register with a write mask different than rg"); tex0 = DeclareAndZeroLocal (typeof (Vector4f), "tex_" + reg.Number); //FIXME using a pair of floats would be faster break; case RegKind.SamplerState: if (kind != TextureKind.Text2d) throw new Exception ("Cannot handle non text2d samplers."); if (samplerMap.ContainsKey (reg.Number)) throw new Exception (String.Format ("sampler {0} already defined", reg.Number)); LocalBuilder lb = DeclareLocal (typeof (Sampler), "sampler_" + reg.Number); samplerMap [reg.Number] = lb; ilgen.Emit (OpCodes.Ldarg_0); ilgen.Emit (OpCodes.Ldc_I4, reg.Number); ilgen.Emit (OpCodes.Call, typeof (ShaderData).GetMethod ("GetSampler")); ilgen.Emit (OpCodes.Stloc, lb); break; } }
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); }
public void DrawString(char[] buffer, int startAt, int len, double left, double top) { _vboBuilder.Clear(); _vboBuilder.SetTextureInfo(_glBmp.Width, _glBmp.Height, _glBmp.IsYFlipped, _pcx.OriginKind); // _pcx.FontFillColor = _painter.FontFillColor; _pcx.LoadTexture(_glBmp); //create temp buffer span that describe the part of a whole char buffer TextBufferSpan textBufferSpan = new TextBufferSpan(buffer, startAt, len); //ask text service to parse user input char buffer and create a glyph-plan-sequence (list of glyph-plan) //with specific request font GlyphPlanSequence glyphPlanSeq = _textServices.CreateGlyphPlanSeq(ref textBufferSpan, _font); float px_scale = _px_scale; //-------------------------- //TODO: //if (x,y) is left top //we need to adjust y again float scaleFromTexture = 1; TextureKind textureKind = _fontAtlas.TextureKind; float g_left = 0; float g_top = 0; int baseLine = (int)Math.Round((float)top + _font.AscentInPixels); int bottom = (int)Math.Round((float)top + _font.AscentInPixels - _font.DescentInPixels); float acc_x = 0; //local accumulate x float acc_y = 0; //local accumulate y #if DEBUG if (s_dbugShowMarkers) { if (s_dbugShowGlyphTexture) { //show original glyph texture at top _pcx.DrawImage(_glBmp, 0, 0); } //draw red-line-marker for baseLine _painter.StrokeColor = Color.Red; _painter.DrawLine(left, baseLine, left + 200, baseLine); // //draw magenta-line-marker for bottom line _painter.StrokeColor = Color.Magenta; int bottomLine = (int)Math.Round((float)top + _font.LineSpacingInPixels); _painter.DrawLine(left, bottomLine, left + 200, bottomLine); //draw blue-line-marker for top line _painter.StrokeColor = Color.Blue; _painter.DrawLine(0, top, left + 200, top); } DrawingTechnique = s_dbugDrawTechnique; //for debug only UseVBO = s_dbugUseVBO; //for debug only #endif int seqLen = glyphPlanSeq.Count; for (int i = 0; i < seqLen; ++i) { UnscaledGlyphPlan glyph = glyphPlanSeq[i]; Typography.Rendering.TextureGlyphMapData glyphData; if (!_fontAtlas.TryGetGlyphMapData(glyph.glyphIndex, out glyphData)) { //if no glyph data, we should render a missing glyph *** continue; } //-------------------------------------- //TODO: review precise height in float //-------------------------------------- //paint src rect //temp fix, glyph texture img is not flipped //but the associate info is flipped => so //we need remap exact Y from the image Rectangle srcRect = new Rectangle(glyphData.Left, _glBmp.Height - (glyphData.Top + glyphData.Height), glyphData.Width, glyphData.Height); //offset length from 'base-line' float x_offset = acc_x + (float)Math.Round(glyph.OffsetX * px_scale - glyphData.TextureXOffset); float y_offset = acc_y + (float)Math.Round(glyph.OffsetY * px_scale - glyphData.TextureYOffset) + srcRect.Height; //*** //NOTE: // -glyphData.TextureXOffset => restore to original pos // -glyphData.TextureYOffset => restore to original pos //-------------------------- g_left = (float)(left + x_offset); g_top = (float)(bottom - y_offset); //*** acc_x += (float)Math.Round(glyph.AdvanceX * px_scale); //g_x = (float)Math.Round(g_x); //*** g_top = (float)Math.Floor(g_top);//adjust to integer num *** #if DEBUG if (s_dbugShowMarkers) { if (s_dbugShowGlyphTexture) { //draw yellow-rect-marker on original texture _painter.DrawRectangle(srcRect.X, srcRect.Y, srcRect.Width, srcRect.Height, Color.Yellow); } //draw debug-rect box at target glyph position _painter.DrawRectangle(g_left, g_top, srcRect.Width, srcRect.Height, Color.Black); _painter.StrokeColor = Color.Blue; //restore } #endif if (textureKind == TextureKind.Msdf) { _pcx.DrawSubImageWithMsdf(_glBmp, ref srcRect, g_left, g_top, scaleFromTexture); } else { switch (DrawingTechnique) { case GlyphTexturePrinterDrawingTechnique.Stencil: if (UseVBO) { _vboBuilder.WriteVboToList( ref srcRect, g_left, g_top); } else { //stencil gray scale with fill-color _pcx.DrawGlyphImageWithStecil(_glBmp, ref srcRect, g_left, g_top, scaleFromTexture); } break; case GlyphTexturePrinterDrawingTechnique.Copy: if (UseVBO) { _vboBuilder.WriteVboToList( ref srcRect, g_left, g_top); } else { _pcx.DrawSubImage(_glBmp, ref srcRect, g_left, g_top, 1); } break; case GlyphTexturePrinterDrawingTechnique.LcdSubPixelRendering: if (UseVBO) { _vboBuilder.WriteVboToList( ref srcRect, g_left, g_top); } else { _pcx.DrawGlyphImageWithSubPixelRenderingTechnique2_GlyphByGlyph( ref srcRect, g_left, g_top, 1); } break; } } } //------------------------------------------- // if (UseVBO) { switch (DrawingTechnique) { case GlyphTexturePrinterDrawingTechnique.Copy: _pcx.DrawGlyphImageWithCopy_VBO(_vboBuilder); break; case GlyphTexturePrinterDrawingTechnique.LcdSubPixelRendering: _pcx.DrawGlyphImageWithSubPixelRenderingTechnique3_DrawElements(_vboBuilder); break; case GlyphTexturePrinterDrawingTechnique.Stencil: _pcx.DrawGlyphImageWithStecil_VBO(_vboBuilder); break; } _vboBuilder.Clear(); } }
public void PrepareStringForRenderVx(GLRenderVxFormattedString renderVxFormattedString, char[] buffer, int startAt, int len) { int top = 0; //simulate top int left = 0; //simulate left _vboBuilder.Clear(); _vboBuilder.SetTextureInfo(_glBmp.Width, _glBmp.Height, _glBmp.IsYFlipped, _pcx.OriginKind); //create temp buffer span that describe the part of a whole char buffer TextBufferSpan textBufferSpan = new TextBufferSpan(buffer, startAt, len); //ask text service to parse user input char buffer and create a glyph-plan-sequence (list of glyph-plan) //with specific request font GlyphPlanSequence glyphPlanSeq = _textServices.CreateGlyphPlanSeq(ref textBufferSpan, _font); float px_scale = _px_scale; //-------------------------- TextureKind textureKind = _fontAtlas.TextureKind; float g_left = 0; float g_top = 0; int baseLine = (int)Math.Round((float)top + _font.AscentInPixels); int bottom = (int)Math.Round((float)top + _font.AscentInPixels - _font.DescentInPixels); float acc_x = 0; //local accumulate x float acc_y = 0; //local accumulate y int seqLen = glyphPlanSeq.Count; for (int i = 0; i < seqLen; ++i) { UnscaledGlyphPlan glyph = glyphPlanSeq[i]; Typography.Rendering.TextureGlyphMapData glyphData; if (!_fontAtlas.TryGetGlyphMapData(glyph.glyphIndex, out glyphData)) { //if no glyph data, we should render a missing glyph *** continue; } //-------------------------------------- //TODO: review precise height in float //-------------------------------------- //paint src rect //temp fix, glyph texture img is not flipped //but the associate info is flipped => so //we need remap exact Y from the image Rectangle srcRect = new Rectangle(glyphData.Left, _glBmp.Height - (glyphData.Top + glyphData.Height), glyphData.Width, glyphData.Height); //offset length from 'base-line' float x_offset = acc_x + (float)Math.Round(glyph.OffsetX * px_scale - glyphData.TextureXOffset); float y_offset = acc_y + (float)Math.Round(glyph.OffsetY * px_scale - glyphData.TextureYOffset) + srcRect.Height; //*** //NOTE: // -glyphData.TextureXOffset => restore to original pos // -glyphData.TextureYOffset => restore to original pos //-------------------------- g_left = (float)(left + x_offset); g_top = (float)(bottom - y_offset); //*** acc_x += (float)Math.Round(glyph.AdvanceX * px_scale); //g_x = (float)Math.Round(g_x); //*** g_top = (float)Math.Floor(g_top);//adjust to integer num *** // _vboBuilder.WriteVboToList(ref srcRect, g_left, g_top); } //--- //copy vbo result and store into renderVx float[] vertexList = _vboBuilder._buffer.ToArray(); ushort[] indexList = _vboBuilder._indexList.ToArray(); //--- renderVxFormattedString.IndexArrayCount = _vboBuilder._indexList.Count; renderVxFormattedString.IndexArray = _vboBuilder._indexList.ToArray(); renderVxFormattedString.VertexCoords = _vboBuilder._buffer.ToArray(); _vboBuilder.Clear(); }
public TextureKindAndDescription(TextureKind kind, string desc) { Kind = kind; Description = desc; }
public void DrawString(Painter p, char[] buffer, int startAt, int len, double x, double y) { //if (_stencilBmp == null) //{ // //create a stencil bmp // _stencilBmp = new ActualBitmap(p.Width, p.Height); // _stencilBlender = new PixelProcessing.SubBitmapBlender(_stencilBmp, new PixelProcessing.PixelBlenderBGRA()); // _backPainter = AggPainter.Create(_stencilBmp); // //------ //} int j = buffer.Length; //create temp buffer span that describe the part of a whole char buffer var textBufferSpan = new Typography.Text.TextBufferSpan(buffer, startAt, len); //ask text service to parse user input char buffer and create a glyph-plan-sequence (list of glyph-plan) //with specific request font GlyphPlanSequence glyphPlanSeq = _txtClient.CreateGlyphPlanSeq(textBufferSpan, _font); ResolvedFont resolvedFont = _textServices.ResolveFont(_font); Typeface typeface = resolvedFont.Typeface; float scale = typeface.CalculateScaleToPixelFromPointSize(_font.SizeInPoints); int recommendLineSpacing = resolvedFont.LineSpacingInPixels; //-------------------------- //TODO: //if (x,y) is left top //we need to adjust y again y -= resolvedFont.LineSpacingInPixels; // float scaleFromTexture = _finalTextureScale; TextureKind textureKind = _fontAtlas.TextureKind; float g_x = 0; float g_y = 0; int baseY = (int)Math.Round(y); //------------------------------------- //load texture //_pcx.LoadTexture1(_glBmp); //------------------------------------- float acc_x = 0; float acc_y = 0; p.DrawImage(_fontBmp, 100, 100); int seqLen = glyphPlanSeq.Count; for (int i = 0; i < seqLen; ++i) { UnscaledGlyphPlan glyph = glyphPlanSeq[i]; AtlasItem glyphData; if (!_fontAtlas.TryGetItem(glyph.glyphIndex, out glyphData)) { //if no glyph data, we should render a missing glyph *** continue; } //-------------------------------------- //TODO: review precise height in float //-------------------------------------- int srcX, srcY, srcW, srcH; glyphData.GetRect(out srcX, out srcY, out srcW, out srcH); float ngx = acc_x + (float)Math.Round(glyph.OffsetX * scale); float ngy = acc_y + (float)Math.Round(glyph.OffsetY * scale); //NOTE: // -glyphData.TextureXOffset => restore to original pos // -glyphData.TextureYOffset => restore to original pos //-------------------------- g_x = (float)(x + (ngx - glyphData.TextureXOffset) * scaleFromTexture); //ideal x g_y = (float)(y + (ngy - glyphData.TextureYOffset + srcH) * scaleFromTexture); acc_x += (float)Math.Round(glyph.AdvanceX * scale); //g_x = (float)Math.Round(g_x); g_y = (float)Math.Floor(g_y); p.DrawImage(_fontBmp, g_x, g_y, srcX, srcY, srcW, srcH); } //------- //we create vbo first //then render }