public override void Dispose() { if (_memBmp != null) { if (_isMemBmpOwner) { _memBmp.Dispose(); } _memBmp = null; } }
public override void Dispose() { ReleaseServerSideTexture(); if (_memBitmap != null) { //notify unused here? if (_isOwner) { _memBitmap.Dispose(); } _memBitmap = null; //*** } }
public ImageBinder(PixelFarm.CpuBlit.MemBitmap memBmp, bool isMemBmpOwner = false) { #if DEBUG if (memBmp == null) { throw new NotSupportedException(); } #endif //binder to image _localImg = memBmp; _isLocalImgOwner = isMemBmpOwner; //if true=> this binder will release a local cahed img this.State = BinderState.Loaded; }
public override Image LoadImage(string imgName, int reqW, int reqH) { if (!File.Exists(imgName)) //resolve to actual img { return(null); } //we support svg as src of img //... //THIS version => just check an extension of the request file string ext = System.IO.Path.GetExtension(imgName).ToLower(); switch (ext) { default: return(null); case ".svg": try { string svg_str = File.ReadAllText(imgName); VgVisualElement vgVisElem = VgVisualDocHelper.CreateVgVisualDocFromFile(imgName).VgRootElem; return(CreateBitmap(vgVisElem, reqW, reqH)); } catch (System.Exception ex) { return(null); } case ".png": case ".jpg": { try { using (System.Drawing.Bitmap gdiBmp = new System.Drawing.Bitmap(imgName)) { PixelFarm.CpuBlit.MemBitmap memBmp = new PixelFarm.CpuBlit.MemBitmap(gdiBmp.Width, gdiBmp.Height); #if DEBUG memBmp._dbugNote = "img" + imgName; #endif PixelFarm.CpuBlit.BitmapHelper.CopyFromGdiPlusBitmapSameSizeTo32BitsBuffer(gdiBmp, memBmp); return(memBmp); } } catch (System.Exception ex) { //return error img return(null); } } } }
static GlyphImage ReadGlyphImages(System.IO.Stream stream) { using (PixelFarm.CpuBlit.MemBitmap bmp = PixelFarm.CpuBlit.MemBitmap.LoadBitmap(stream)) { GlyphImage img = new GlyphImage(bmp.Width, bmp.Height); int[] buffer = new int[bmp.Width * bmp.Height]; unsafe { PixelFarm.CpuBlit.Imaging.TempMemPtr tmp = PixelFarm.CpuBlit.MemBitmap.GetBufferPtr(bmp); System.Runtime.InteropServices.Marshal.Copy(tmp.Ptr, buffer, 0, bmp.Width * bmp.Height); img.SetImageBuffer(buffer, true); } return(img); } }
static GlyphImage ReadGlyphImages(string filename) { using (PixelFarm.CpuBlit.MemBitmap bmp = StorageService.Provider.ReadPngBitmap(filename)) { GlyphImage img = new GlyphImage(bmp.Width, bmp.Height); int[] buffer = new int[bmp.Width * bmp.Height]; unsafe { PixelFarm.CpuBlit.Imaging.TempMemPtr tmp = PixelFarm.CpuBlit.MemBitmap.GetBufferPtr(bmp); System.Runtime.InteropServices.Marshal.Copy(tmp.Ptr, buffer, 0, bmp.Width * bmp.Height); img.SetImageBuffer(buffer, true); } return(img); } }
public static void Setup() { if (CommonTextServiceSetup.FontLoader == null) { InstalledTypefaceCollectionMx.Setup(); CommonTextServiceSetup.SetInstalledTypefaceCollection(InstalledTypefaceCollectionMx.GetDefaultInstalledTypefaceCollection()); } PixelFarm.DrawingGL.CachedBinaryShaderIO.SetActualImpl( () => new PixelFarm.DrawingGL.LocalFileCachedBinaryShaderIO(Application.CommonAppDataPath)); FrameworkInitGLES.SetupDefaultValues(); //TODO: review namespace*** var pars = new PixelFarm.Platforms.ImageIOSetupParameters(); pars.SaveToPng = (IntPtr imgBuffer, int stride, int width, int height, string filename) => { using (System.Drawing.Bitmap newBmp = new System.Drawing.Bitmap(width, height, System.Drawing.Imaging.PixelFormat.Format32bppArgb)) { PixelFarm.CpuBlit.BitmapHelper.CopyToGdiPlusBitmapSameSize(imgBuffer, newBmp); //save newBmp.Save(filename); } }; pars.ReadFromMemStream = (System.IO.MemoryStream ms, string kind) => { //read //TODO: review here again using (System.Drawing.Bitmap gdiBmp = new System.Drawing.Bitmap(ms)) { PixelFarm.CpuBlit.MemBitmap memBmp = new PixelFarm.CpuBlit.MemBitmap(gdiBmp.Width, gdiBmp.Height); //#if DEBUG // memBmp._dbugNote = "img; //#endif PixelFarm.CpuBlit.BitmapHelper.CopyFromGdiPlusBitmapSameSizeTo32BitsBuffer(gdiBmp, memBmp); return(memBmp); } }; PixelFarm.Platforms.ImageIOPortal.Setup(pars); //you can use your font loader YourImplementation.FrameworkInitWinGDI.SetupDefaultValues(); //default text breaker, this bridge between LayoutFarm.Composers.Default.TextBreaker = new LayoutFarm.Composers.MyManagedTextBreaker(); }
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 GdiPlusRenderSurface(int width, int height) { #if DEBUG debug_canvas_id = dbug_canvasCount + 1; dbug_canvasCount += 1; #endif //2. dimension _left = 0; _top = 0; _right = _left + width; _bottom = _top + height; _currentClipRect = new System.Drawing.Rectangle(0, 0, width, height); //-------------- _win32MemDc = new NativeWin32MemoryDC(width, height, false); _win32MemDc.PatBlt(NativeWin32MemoryDC.PatBltColor.White); _win32MemDc.SetBackTransparent(true); _win32MemDc.SetClipRect(0, 0, width, height); //-------------- _memBmp = new CpuBlit.MemBitmap(width, height, _win32MemDc.PPVBits); _originalHdc = _win32MemDc.DC; _gx = System.Drawing.Graphics.FromHdc(_win32MemDc.DC); //-------------- //TODO: review here how to set default font*** //set default font Win32.Win32Font font = Win32.FontHelper.CreateWin32Font("Tahoma", 10, false, false); _hFont = font.GetHFont(); _win32MemDc.SetFont(_hFont); //--------------------- //-------------- //set default font and default text color this.CurrentFont = new RequestFont("tahoma", 14); this.CurrentTextColor = Color.Black; //------------------------------------------------------- //managed object _internalPen = new System.Drawing.Pen(System.Drawing.Color.Black); _internalSolidBrush = new System.Drawing.SolidBrush(System.Drawing.Color.Black); this.StrokeWidth = 1; }
public override void Dispose() { if (TextureContainer != null) { //after unload-> //OwnerActiveTextureUnit will set OwnerActiveTextureUnit property to null TextureContainer.UnloadGLBitmap(); } ReleaseServerSideTexture(); if (_memBitmap != null) { //notify unused here? if (_isOwner) { _memBitmap.Dispose(); } _memBitmap = null; //*** } }
/// <summary> /// get from cache or create a new one /// </summary> /// <param name="reqFont"></param> /// <returns></returns> public SimpleBitmaptAtlas GetBitmapAtlas(string atlasName, out B outputBitmap) { #if DEBUG _dbugStopWatch.Reset(); _dbugStopWatch.Start(); #endif if (!_createdAtlases.TryGetValue(atlasName, out SimpleBitmaptAtlas foundAtlas)) { //check from pre-built cache (if availiable) string fontTextureInfoFile = atlasName + ".info"; string fontTextureImgFilename = atlasName + ".png"; //check if the file exist if (StorageService.Provider.DataExists(fontTextureInfoFile) && StorageService.Provider.DataExists(fontTextureImgFilename)) { SimpleBitmapAtlasBuilder atlasBuilder = new SimpleBitmapAtlasBuilder(); using (System.IO.Stream dataStream = StorageService.Provider.ReadDataStream(fontTextureInfoFile)) using (System.IO.Stream fontImgStream = StorageService.Provider.ReadDataStream(fontTextureImgFilename)) { try { foundAtlas = atlasBuilder.LoadAtlasInfo(dataStream); PixelFarm.CpuBlit.MemBitmap memBmp = PixelFarm.CpuBlit.MemBitmap.LoadBitmap(fontImgStream); AtlasItemImage atlasImg = new AtlasItemImage(memBmp.Width, memBmp.Height); //TODO: review new .ctor atlasImg.SetBitmap(memBmp, false); foundAtlas.TotalImg = atlasImg; _createdAtlases.Add(atlasName, foundAtlas); } catch (Exception ex) { throw ex; } } } } outputBitmap = _loadAtlases.GetOrCreateNewOne(foundAtlas); return(foundAtlas); }
PixelFarm.CpuBlit.MemBitmap CreateBitmap(VgVisualElement renderVx, int reqW, int reqH) { PixelFarm.CpuBlit.RectD bound = renderVx.GetRectBounds(); //create PixelFarm.CpuBlit.MemBitmap backingBmp = new PixelFarm.CpuBlit.MemBitmap((int)bound.Width + 10, (int)bound.Height + 10); #if DEBUG backingBmp._dbugNote = "renderVx"; #endif //PixelFarm.CpuBlit.AggPainter painter = PixelFarm.CpuBlit.AggPainter.Create(backingBmp); using (PixelFarm.CpuBlit.AggPainterPool.Borrow(backingBmp, out PixelFarm.CpuBlit.AggPainter painter)) using (VgPaintArgsPool.Borrow(painter, out VgPaintArgs paintArgs)) { double prevStrokeW = painter.StrokeWidth; renderVx.Paint(paintArgs); painter.StrokeWidth = prevStrokeW;//restore } return(backingBmp); }
protected override void OnReadyForInitGLShaderProgram() { //--------------------- var atlasBuilder = new Typography.Rendering.SimpleFontAtlasBuilder(); using (System.IO.FileStream fs = new System.IO.FileStream(RootDemoPath.Path + @"\a_total.xml", System.IO.FileMode.Open)) { _fontAtlas = atlasBuilder.LoadFontInfo(fs); } var actualImg = PixelFarm.CpuBlit.MemBitmap.LoadBitmap(RootDemoPath.Path + @"\a_total.png"); _totalBmp = actualImg; //var bmpdata = totalImg.LockBits(new System.Drawing.Rectangle(0, 0, totalImg.Width, totalImg.Height), System.Drawing.Imaging.ImageLockMode.ReadWrite, totalImg.PixelFormat); //var buffer = new int[totalImg.Width * totalImg.Height]; //System.Runtime.InteropServices.Marshal.Copy(bmpdata.Scan0, buffer, 0, buffer.Length); //totalImg.UnlockBits(bmpdata); var glyph = new Typography.Rendering.GlyphImage(_totalBmp.Width, _totalBmp.Height); glyph.SetImageBuffer(PixelFarm.CpuBlit.MemBitmap.CopyImgBuffer(actualImg), false); _fontAtlas.TotalGlyph = glyph; }
public static PixelFarm.CpuBlit.MemBitmap LoadImage(string imgName) { if (!System.IO.File.Exists(imgName)) { return(null); } using (System.Drawing.Bitmap gdiBmp = new System.Drawing.Bitmap(imgName)) { int w = gdiBmp.Width; int h = gdiBmp.Height; var bmpData = gdiBmp.LockBits(new System.Drawing.Rectangle(0, 0, w, h), System.Drawing.Imaging.ImageLockMode.ReadOnly, System.Drawing.Imaging.PixelFormat.Format32bppArgb); PixelFarm.CpuBlit.MemBitmap newBmp = PixelFarm.CpuBlit.MemBitmap.CreateFromCopy(w, h, w * h * 4, bmpData.Scan0); gdiBmp.UnlockBits(bmpData); return(newBmp); } }
protected override void PaintImp(PaintVisitor p) { #if DEBUG p.dbugEnterNewContext(this, PaintVisitor.PaintVisitorContextName.Init); #endif DrawBoard drawBoard = p.InnerDrawBoard; if (DisableBmpCache) { PixelFarm.CpuBlit.AggPainter painter = drawBoard.GetPainter() as PixelFarm.CpuBlit.AggPainter; if (painter == null) { return; } //TODO: review here //temp fix if (s_openfontTextService == null) { s_openfontTextService = new OpenFontTextService(); } //painter.CurrentFont = new RequestFont("tahoma", 14); //var textPrinter = new PixelFarm.Drawing.Fonts.VxsTextPrinter(painter, s_openfontTextService); //painter.TextPrinter = textPrinter; //painter.Clear(Color.White); // double prevStrokeW = painter.StrokeWidth; //Color fillColor = painter.FillColor; //painter.StrokeWidth = 1;//default //painter.FillColor = Color.Black; using (VgPaintArgsPool.Borrow(painter, out var paintArgs)) { if (_vgVisualElem.CoordTx != null) { } _vgVisualElem.Paint(paintArgs); } painter.StrokeWidth = prevStrokeW;//restore //painter.FillColor = fillColor;////restore return; } if (_vgVisualElem.HasBitmapSnapshot) { Image backimg = _vgVisualElem.BackingImage; drawBoard.DrawImage(backimg, new RectangleF(0, 0, backimg.Width, backimg.Height)); } else { PixelFarm.CpuBlit.RectD bound = _vgVisualElem.GetRectBounds(); //create PixelFarm.CpuBlit.MemBitmap backimg = new PixelFarm.CpuBlit.MemBitmap((int)bound.Width + 10, (int)bound.Height + 10); #if DEBUG backimg._dbugNote = "cssBoxSvgRoot"; #endif PixelFarm.CpuBlit.AggPainter painter = PixelFarm.CpuBlit.AggPainter.Create(backimg); //TODO: review here //temp fix if (s_openfontTextService == null) { s_openfontTextService = new OpenFontTextService(); } // double prevStrokeW = painter.StrokeWidth; using (VgPaintArgsPool.Borrow(painter, out VgPaintArgs paintArgs)) { if (_vgVisualElem.CoordTx != null) { } _vgVisualElem.Paint(paintArgs); } painter.StrokeWidth = prevStrokeW;//restore //painter.FillColor = fillColor;////restore #if DEBUG //test //PixelFarm.CpuBlit.Imaging.PngImageWriter.dbugSaveToPngFile(backimg, "d:\\WImageTest\\subimg1.png"); #endif _vgVisualElem.SetBitmapSnapshot(backimg, true); drawBoard.DrawImage(backimg, new RectangleF(0, 0, backimg.Width, backimg.Height)); } }
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); } } } }
static void Main() { PixelFarm.Platforms.StorageService.RegisterProvider(new YourImplementation.LocalFileStorageProvider("")); YourImplementation.FrameworkInitWinGDI.SetupDefaultValues(); YourImplementation.FrameworkInitGLES.SetupDefaultValues(); string icu_datadir = YourImplementation.RelativePathBuilder.SearchBackAndBuildFolderPath(System.IO.Directory.GetCurrentDirectory(), "HtmlRenderer", @"..\Typography\Typography.TextBreak\icu62\brkitr"); if (!System.IO.Directory.Exists(icu_datadir)) { throw new System.NotSupportedException("dic"); } var dicProvider = new Typography.TextBreak.IcuSimpleTextFileDictionaryProvider() { DataDir = icu_datadir }; Typography.TextBreak.CustomBreakerBuilder.Setup(dicProvider); PixelFarm.CpuBlit.MemBitmapExt.DefaultMemBitmapIO = new PixelFarm.Drawing.WinGdi.GdiBitmapIO(); YourImplementation.TestBedStartup.Setup(); PixelFarm.Platforms.ImageIOSetupParameters pars = new PixelFarm.Platforms.ImageIOSetupParameters(); pars.SaveToPng = (IntPtr imgBuffer, int stride, int width, int height, string filename) => { using (System.Drawing.Bitmap newBmp = new System.Drawing.Bitmap(width, height, System.Drawing.Imaging.PixelFormat.Format32bppArgb)) { PixelFarm.CpuBlit.BitmapHelper.CopyToGdiPlusBitmapSameSize(imgBuffer, newBmp); //save newBmp.Save(filename); } }; pars.ReadFromMemStream = (System.IO.MemoryStream ms, string kind) => { //read //TODO: review here again using (System.Drawing.Bitmap gdiBmp = new System.Drawing.Bitmap(ms)) { PixelFarm.CpuBlit.MemBitmap memBmp = new PixelFarm.CpuBlit.MemBitmap(gdiBmp.Width, gdiBmp.Height); //#if DEBUG // memBmp._dbugNote = "img; //#endif PixelFarm.CpuBlit.BitmapHelper.CopyFromGdiPlusBitmapSameSizeTo32BitsBuffer(gdiBmp, memBmp); return(memBmp); } }; PixelFarm.Platforms.ImageIOPortal.Setup(pars); //------------------------------- Application.EnableVisualStyles(); Application.SetCompatibleTextRenderingDefault(false); ////------------------------------- formDemoList = new LayoutFarm.Dev.FormDemoList(); formDemoList.LoadDemoList(typeof(Program).Assembly); LoadHtmlSamples(formDemoList.SamplesTreeView); Application.Run(formDemoList); }
protected override void OnReadyForInitGLShaderProgram() { //-------------------------------------------------------------------------- string vs = @" attribute vec4 a_position; attribute vec2 a_texCoord; uniform mat4 u_mvpMatrix; varying vec2 v_texCoord; void main() { gl_Position = u_mvpMatrix* a_position; v_texCoord = a_texCoord; } "; //in fs, angle on windows //we need to switch color component //because we store value in memory as BGRA //and gl expect input in RGBA string fs = @" precision mediump float; varying vec2 v_texCoord; uniform sampler2D s_texture; void main() { vec4 c = texture2D(s_texture, v_texCoord); gl_FragColor = vec4(c[2],c[1],c[0],c[3]); } "; mProgram = EsUtils.CompileProgram(vs, fs); if (mProgram == 0) { //return false } // Get the attribute locations mPositionLoc = GL.GetAttribLocation(mProgram, "a_position"); mTexCoordLoc = GL.GetAttribLocation(mProgram, "a_texCoord"); u_matrix = GL.GetUniformLocation(mProgram, "u_mvpMatrix"); // Get the sampler location mSamplerLoc = GL.GetUniformLocation(mProgram, "s_texture"); //// Load the texture PixelFarm.CpuBlit.MemBitmap bmp = PixelFarm.CpuBlit.MemBitmapExt.LoadBitmap(RootDemoPath.Path + @"\lion1.png"); int bmpW = bmp.Width; int bmpH = bmp.Height; mTexture = LoadTexture(bmp); GL.ClearColor(0, 0, 0, 0); //================================================================================ GL.Enable(EnableCap.Blend); GL.BlendFunc(BlendingFactorSrc.SrcAlpha, BlendingFactorDest.OneMinusSrcAlpha); GL.ClearColor(1, 1, 1, 1); //setup viewport size int max = Math.Max(this.Width, this.Height); orthoViewMat = MyMat4.ortho(0, max, 0, max, 0, 1).data; //square viewport GL.Viewport(0, 0, max, max); imgVertices = new float[] { 0, bmpH, 0, 0, 0, //--------------------- 0, 0, 0, 0, 1, //--------------------- bmpW, bmpH, 0, 1, 0, //--------------------- bmpW, 0, 0, 1, 1 }; }
public static MemBitmap ScaleImage(this PixelFarm.CpuBlit.MemBitmap bmp, float x_scale, float y_scale) { return(DefaultMemBitmapIO.ScaleImage(bmp, x_scale, y_scale)); }
public static GLBitmap LoadTexture(PixelFarm.CpuBlit.MemBitmap memBmp) { return(new GLBitmap(memBmp)); }
public abstract void SavePngBitmap(PixelFarm.CpuBlit.MemBitmap bmp, string filename);
public abstract PixelFarm.CpuBlit.MemBitmap ScaleImage(PixelFarm.CpuBlit.MemBitmap bmp, float x_scale, float y_scale);
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); } } } }
public MemBitmapBinder(PixelFarm.CpuBlit.MemBitmap memBmp, bool isMemBmpOwner) { _memBmp = memBmp; _isMemBmpOwner = isMemBmpOwner; }
/// <summary> /// get from cache or create a new one /// </summary> /// <param name="reqFont"></param> /// <returns></returns> public SimpleBitmapAtlas GetFontAtlas(RequestFont reqFont, out B outputBitmap) { #if DEBUG _dbugStopWatch.Reset(); _dbugStopWatch.Start(); #endif int fontKey = reqFont.FontKey; if (_createdAtlases.TryGetValue(fontKey, out SimpleBitmapAtlas fontAtlas)) { outputBitmap = _loadAtlases.GetOrCreateNewOne(fontAtlas); return(fontAtlas); } //check if we have small msdf texture or not if (_msdfTextureFonts.TryGetValue(reqFont.Name, out SimpleBitmapAtlas msdfTexture)) { //use this outputBitmap = _loadAtlases.GetOrCreateNewOne(msdfTexture); return(msdfTexture); } //-------------------------------- //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"; if (StorageService.Provider.DataExists(fontTextureInfoFile) && StorageService.Provider.DataExists(fontTextureImgFilename)) { //check local caching, if found then load-> create it SimpleBitmapAtlasBuilder atlasBuilder = new SimpleBitmapAtlasBuilder(); lock (s_loadDataLock) { using (System.IO.Stream textureInfoFileStream = StorageService.Provider.ReadDataStream(fontTextureInfoFile)) using (System.IO.Stream fontAtlasImgStream = StorageService.Provider.ReadDataStream(fontTextureImgFilename)) { try { //TODO: review here fontAtlas = atlasBuilder.LoadAtlasInfo(textureInfoFileStream)[0]; fontAtlas.SetMainBitmap(ReadGlyphImages(fontAtlasImgStream), true); fontAtlas.OriginalFontSizePts = reqFont.SizeInPoints; _createdAtlases.Add(fontKey, fontAtlas); } catch (Exception ex) { throw ex; } } } } else { //------------- //if not found the request font //we generate it realtime here, (add add the cache '_createdAtlases') //------------- //1. create glyph-texture-bitmap generator var glyphTextureGen = new GlyphTextureBitmapGenerator(); //2. generate the glyphs SimpleBitmapAtlasBuilder atlasBuilder = glyphTextureGen.CreateTextureFontFromBuildDetail( resolvedTypeface, reqFont.SizeInPoints, TextureKindForNewFont, GlyphTextureCustomConfigs.TryGetGlyphTextureBuildDetail(reqFont, false, false) ); //3. set information before write to font-info atlasBuilder.FontFilename = reqFont.Name;//TODO: review here, check if we need 'filename' or 'fontname' atlasBuilder.FontKey = reqFont.FontKey; 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); #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 totalGlyphsImg.SaveImage(fontTextureImgFilename); #endif //6. cache this in the memory, _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 //TODO: review here again //save font info to local disk cache using (System.IO.MemoryStream ms = new System.IO.MemoryStream()) { atlasBuilder.SaveAtlasInfo(ms); StorageService.Provider.SaveData(fontTextureInfoFile, ms.ToArray()); #if DEBUG //write temp debug info #if !__MOBILE__ System.IO.File.WriteAllBytes(fontTextureInfoFile, ms.ToArray()); System.IO.File.WriteAllText(fontTextureInfoFile + ".txt", reqFont.Name + ",size" + reqFont.SizeInPoints + "pts"); #endif #endif } } outputBitmap = _loadAtlases.GetOrCreateNewOne(fontAtlas); return(fontAtlas); }
void CreateTextureFontFromGlyphIndices( Typeface typeface, float sizeInPoint, HintTechnique hintTechnique, SimpleBitmapAtlasBuilder atlasBuilder, ushort[] glyphIndices) { //sample: create sample msdf texture //------------------------------------------------------------- var outlineBuilder = new GlyphOutlineBuilder(typeface); outlineBuilder.SetHintTechnique(hintTechnique); // if (atlasBuilder.TextureKind == TextureKind.Msdf) { float pxscale = typeface.CalculateScaleToPixelFromPointSize(sizeInPoint); 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) outlineBuilder.BuildFromGlyphIndex(gindex, -1); var glyphToVxs = new GlyphTranslatorToVxs(); outlineBuilder.ReadShapes(glyphToVxs); using (Tools.BorrowVxs(out var vxs)) { glyphToVxs.WriteUnFlattenOutput(vxs, pxscale); BitmapAtlasItemSource glyphImg = gen3.GenerateMsdfTexture(vxs); glyphImg.UniqueInt16Name = gindex; _onEachGlyphDel?.Invoke(glyphImg); // atlasBuilder.AddItemSource(glyphImg); } } } else { 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) outlineBuilder.BuildFromGlyphIndex(gindex, -1); var glyphToVxs = new GlyphTranslatorToVxs(); outlineBuilder.ReadShapes(glyphToVxs); using (Tools.BorrowVxs(out var vxs)) { glyphToVxs.WriteUnFlattenOutput(vxs, pxscale); BitmapAtlasItemSource glyphImg = gen3.GenerateMsdfTexture(vxs); glyphImg.UniqueInt16Name = gindex; _onEachGlyphDel?.Invoke(glyphImg); atlasBuilder.AddItemSource(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]; outlineBuilder.BuildFromGlyphIndex(gindex, sizeInPoint); BitmapAtlasItemSource glyphImg = aggTextureGen.CreateAtlasItem(outlineBuilder, 1); glyphImg.UniqueInt16Name = gindex; _onEachGlyphDel?.Invoke(glyphImg); atlasBuilder.AddItemSource(glyphImg); } } } }