public VxsTextPrinter(CanvasPainter canvasPainter, IFontLoader fontLoader) { this.canvasPainter = canvasPainter; this._fontLoader = fontLoader; _glyphMeshStore = new GlyphMeshStore(); // _pxScaleEngine = new PixelScaleLayoutEngine(); _pxScaleEngine.HintedFontStore = _glyphMeshStore;//share _glyphMeshStore with pixel-scale-layout-engine }
public VxsTextSpanPrinter(Painter painter, TextServiceClient txtClient) { _txtClient = txtClient; _painter = painter; _glyphMeshStore = new GlyphMeshStore() { FlipGlyphUpward = true }; _glyphBitmapStore = new GlyphBitmapStore(); }
public VxsTextPrinter(Painter painter, LayoutFarm.OpenFontTextService textService) { StartDrawOnLeftTop = true; // _painter = painter; _glyphMeshStore = new GlyphMeshStore(); _glyphMeshStore.FlipGlyphUpward = true; this.PositionTechnique = PositionTechnique.OpenFont; // _textServices = textService; ChangeFont(new RequestFont("tahoma", 10)); }
public VxsTextPrinter(Painter painter, OpenFontTextService textService) { // _painter = painter; _glyphMeshStore = new GlyphMeshStore(); _glyphMeshStore.FlipGlyphUpward = true; this.PositionTechnique = PositionTechnique.OpenFont; // _textServices = textService; ChangeFont(new RequestFont("Source Sans Pro", 10)); _glyphBitmapStore = new GlyphBitmapStore(); _glyphSvgStore = new BitmapCacheForSvgGlyph(); }
public VxsTextPrinter(Painter painter, IFontLoader fontLoader) { StartDrawOnLeftTop = true; // this._painter = painter; this._fontLoader = fontLoader; _glyphMeshStore = new GlyphMeshStore(); _glyphMeshStore.FlipGlyphUpward = true; // _pxScaleEngine = new PixelScaleLayoutEngine(); _pxScaleEngine.HintedFontStore = _glyphMeshStore;//share _glyphMeshStore with pixel-scale-layout-engine // //_glyphLayout.PxScaleLayout = _pxScaleEngine; //assign the pxscale-layout-engine to main glyphLayout engine this.PositionTechnique = PositionTechnique.OpenFont; }
private void TxtTestGlyph_KeyDown(object sender, KeyEventArgs e) { if (e.KeyCode != Keys.Enter) { return; } //--- string text = txtTestGlyph.Text.Trim(); if (text.Length == 0) { return; } char singleChar = text[0]; //1. read a single glyph from font file. //2. generate vxs from the glyph. var glyphMeshStore = new GlyphMeshStore(); glyphMeshStore.FlipGlyphUpward = false; //just example, not need to open-read everytime. Typeface typeface = null; //string fontpath = "Samples/SourceSansPro-Regular.ttf"; string fontpath = "Samples/Roboto-Regular.ttf"; using (FileStream fs = new FileStream(fontpath, FileMode.Open, FileAccess.Read)) { OpenFontReader fontReader = new OpenFontReader(); typeface = fontReader.Read(fs); glyphMeshStore.SetFont(typeface, 56); ushort glyphIndex = typeface.GetGlyphIndex(singleChar); VertexStore glyphVxs = glyphMeshStore.GetNewUnFlattenVxs(glyphIndex); //** //VertexStore glyphVxs = glyphMeshStore.GetGlyphMesh(glyphIndex);//org GenerateMsdf(glyphVxs); } }
void CreateTextureFontFromGlyphIndices( HintTechnique hintTechnique, SimpleBitmapAtlasBuilder atlasBuilder, ushort[] glyphIndices) { //sample: create sample msdf texture //------------------------------------------------------------- var outlineBuilder = new GlyphOutlineBuilder(_typeface); outlineBuilder.SetHintTechnique(hintTechnique); // AggGlyphTextureGen aggTextureGen = new AggGlyphTextureGen(); GlyphNotFoundHelper glyphNotFoundHelper = new GlyphNotFoundHelper(atlasBuilder, outlineBuilder, _onEachGlyphDel, aggTextureGen, _sizeInPoints); //create reusable agg painter*** //assume each glyph size= 2 * line height //TODO: review here again... //please note that DPI effect glyph size //*** int tmpMemBmpHeight = (int)(2 * _typeface.CalculateRecommendLineSpacing() * _px_scale); // if (atlasBuilder.TextureKind == TextureKind.Msdf) { var msdfGenParams = new Msdfgen.MsdfGenParams(); int j = glyphIndices.Length; if (MsdfGenVersion == 3) { Msdfgen.MsdfGen3 gen3 = new Msdfgen.MsdfGen3(); 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) var glyphToVxs = new GlyphTranslatorToVxs(); outlineBuilder.BuildFromGlyphIndex(gindex, -1, glyphToVxs); using (Tools.BorrowVxs(out var vxs)) { glyphToVxs.WriteUnFlattenOutput(vxs, _px_scale); BitmapAtlasItemSource glyphImg = gen3.GenerateMsdfTexture(vxs); glyphImg.UniqueInt16Name = gindex; _onEachGlyphDel?.Invoke(glyphImg); // atlasBuilder.AddItemSource(glyphImg); } } } else { //use gen3 Msdfgen.MsdfGen3 gen3 = new Msdfgen.MsdfGen3(); 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) var glyphToVxs = new GlyphTranslatorToVxs(); outlineBuilder.BuildFromGlyphIndex(gindex, -1, glyphToVxs); using (Tools.BorrowVxs(out var vxs)) { glyphToVxs.WriteUnFlattenOutput(vxs, _px_scale); BitmapAtlasItemSource glyphImg = gen3.GenerateMsdfTexture(vxs); glyphImg.UniqueInt16Name = gindex; _onEachGlyphDel?.Invoke(glyphImg); atlasBuilder.AddItemSource(glyphImg); } } } return; } else if (atlasBuilder.TextureKind == TextureKind.Bitmap) { //generate color bitmap atlas int j = glyphIndices.Length; GlyphMeshStore glyphMeshStore = new GlyphMeshStore(); glyphMeshStore.SetFont(_typeface, _sizeInPoints); aggTextureGen.TextureKind = TextureKind.Bitmap; using (PixelFarm.CpuBlit.MemBitmap tmpMemBmp = new PixelFarm.CpuBlit.MemBitmap(tmpMemBmpHeight, tmpMemBmpHeight)) //square { aggTextureGen.Painter = PixelFarm.CpuBlit.AggPainter.Create(tmpMemBmp); #if DEBUG tmpMemBmp._dbugNote = "CreateGlyphImage()"; #endif if (_typeface.HasColorTable()) { //outline glyph for (int i = 0; i < j; ++i) { ushort gindex = glyphIndices[i]; if (!_typeface.COLRTable.LayerIndices.TryGetValue(gindex, out ushort colorLayerStart)) { //not found, then render as normal //TODO: impl //create glyph img glyphNotFoundHelper.HandleNotFoundGlyph(gindex); } else { //TODO: review this again GlyphBitmap glyphBmp = GetGlyphBitmapFromColorOutlineGlyph(gindex, glyphMeshStore, colorLayerStart); if (glyphBmp == null) { glyphNotFoundHelper.HandleNotFoundGlyph(gindex); } else { int w = glyphBmp.Width; int h = glyphBmp.Height; BitmapAtlasItemSource glyphImage = new BitmapAtlasItemSource(glyphBmp.Width, glyphBmp.Height); glyphImage.TextureXOffset = (short)glyphBmp.ImageStartX; glyphImage.TextureYOffset = (short)glyphBmp.ImageStartY; // glyphImage.SetImageBuffer(MemBitmapExt.CopyImgBuffer(glyphBmp.Bitmap, w, h, true), false); glyphImage.UniqueInt16Name = gindex; _onEachGlyphDel?.Invoke(glyphImage); atlasBuilder.AddItemSource(glyphImage); //clear glyphBmp.Bitmap.Dispose(); glyphBmp.Bitmap = null; } } } } else if (_typeface.IsBitmapFont) { aggTextureGen.TextureKind = TextureKind.Bitmap; //test this with Noto Color Emoji for (int i = 0; i < j; ++i) { ushort gindex = glyphIndices[i]; GlyphBitmap glyphBmp = GetGlyphBitmapFromBitmapFont(gindex); if (glyphBmp == null) { glyphNotFoundHelper.HandleNotFoundGlyph(gindex); } else { int w = glyphBmp.Width; int h = glyphBmp.Height; BitmapAtlasItemSource glyphImage = new BitmapAtlasItemSource(glyphBmp.Width, glyphBmp.Height); glyphImage.TextureXOffset = (short)glyphBmp.ImageStartX; glyphImage.TextureYOffset = (short)glyphBmp.ImageStartY; // glyphImage.SetImageBuffer(MemBitmapExt.CopyImgBuffer(glyphBmp.Bitmap, w, h, true), false); glyphImage.UniqueInt16Name = gindex; _onEachGlyphDel?.Invoke(glyphImage); atlasBuilder.AddItemSource(glyphImage); //clear glyphBmp.Bitmap.Dispose(); glyphBmp.Bitmap = null; } } } else if (_typeface.HasSvgTable()) { aggTextureGen.TextureKind = TextureKind.Bitmap; //test this with TwitterEmoji //generate membitmap from svg #if DEBUG System.Diagnostics.Stopwatch sw1 = new System.Diagnostics.Stopwatch(); sw1.Start(); #endif for (int i = 0; i < j; ++i) { //TODO: add mutli-threads / async version ushort gindex = glyphIndices[i]; GlyphBitmap glyphBmp = GetGlyphBitmapFromSvg(gindex); if (glyphBmp == null) { glyphNotFoundHelper.HandleNotFoundGlyph(gindex); } else { int w = glyphBmp.Width; int h = glyphBmp.Height; BitmapAtlasItemSource glyphImage = new BitmapAtlasItemSource(glyphBmp.Width, glyphBmp.Height); glyphImage.TextureXOffset = (short)glyphBmp.ImageStartX; glyphImage.TextureYOffset = (short)glyphBmp.ImageStartY; // glyphImage.SetImageBuffer(MemBitmapExt.CopyImgBuffer(glyphBmp.Bitmap, w, h, true), false); glyphImage.UniqueInt16Name = gindex; _onEachGlyphDel?.Invoke(glyphImage); atlasBuilder.AddItemSource(glyphImage); //clear glyphBmp.Bitmap.Dispose(); glyphBmp.Bitmap = null; } } #if DEBUG sw1.Stop(); long ms = sw1.ElapsedMilliseconds; #endif } return; //NO go below //*** } //END using } //--------------------------- //OTHERS.... { aggTextureGen.TextureKind = atlasBuilder.TextureKind; //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]; outlineBuilder.BuildFromGlyphIndex(gindex, _sizeInPoints); BitmapAtlasItemSource glyphImg = aggTextureGen.CreateAtlasItem(outlineBuilder, 1); glyphImg.UniqueInt16Name = gindex; _onEachGlyphDel?.Invoke(glyphImg); atlasBuilder.AddItemSource(glyphImg); } } } }
GlyphBitmap GetGlyphBitmapFromColorOutlineGlyph(ushort glyphIndex, GlyphMeshStore glyphMeshStore, ushort colorLayerStart) { //not found=> create a newone Typography.OpenFont.Tables.COLR _colrTable = _typeface.COLRTable; Typography.OpenFont.Tables.CPAL _cpalTable = _typeface.CPALTable; Q1RectD totalBounds = Q1RectD.ZeroIntersection(); { //calculate bounds of this glyph ushort colorLayerCount = _colrTable.LayerCounts[glyphIndex]; for (int c = colorLayerStart; c < colorLayerStart + colorLayerCount; ++c) { BoundingRect.GetBoundingRect(glyphMeshStore.GetGlyphMesh(_colrTable.GlyphLayers[c]), ref totalBounds); } } //dbugExportCount++; var memBmp = new MemBitmap((int)Math.Round(totalBounds.Width), (int)Math.Round(totalBounds.Height));//??? int offset_x = 0; int offset_y = 0; using (Tools.BorrowAggPainter(memBmp, out AggPainter painter)) { painter.Clear(Color.Transparent); painter.SetOrigin(0, 0); offset_x = -(int)(totalBounds.Left); offset_y = -(int)(totalBounds.Bottom); ushort colorLayerCount = _colrTable.LayerCounts[glyphIndex]; int palette = 0; // FIXME: assume palette 0 for now for (int c = colorLayerStart; c < colorLayerStart + colorLayerCount; ++c) { _cpalTable.GetColor( _cpalTable.Palettes[palette] + _colrTable.GlyphPalettes[c], //index out byte r, out byte g, out byte b, out byte a); ushort gIndex = _colrTable.GlyphLayers[c]; VertexStore vxs = glyphMeshStore.GetGlyphMesh(gIndex); using (Tools.BorrowVxs(out var v1)) { vxs.TranslateToNewVxs(offset_x, offset_y, v1); painter.FillColor = new Color(r, g, b);//? a component painter.Fill(v1); } } //find ex #if DEBUG //memBmp.SaveImage("a0x" + (dbugExportCount) + ".png"); #endif } return(new GlyphBitmap { Bitmap = memBmp, Width = memBmp.Width, Height = memBmp.Height, ImageStartX = -offset_x, //offset back ImageStartY = -offset_y //offset back }); }