private void RecalculateContentHeight() { _totalContentHeight = 0; foreach (var item in _itemList) { var itemHeight = 0f; if (item.Icon != null) { itemHeight = item.IconSize.Y; } itemHeight = Math.Max(itemHeight, ActualFont.GetHeight(UIScale)); itemHeight += ActualItemBackground.MinimumSize.Y; _totalContentHeight += (int)Math.Ceiling(itemHeight); } _scrollBar.MaxValue = Math.Max(_scrollBar.Page, _totalContentHeight); _updateScrollbarVisibility(); }
protected override void GetGlyphPosImpl(ActualFont actualFont, char[] buffer, int startAt, int len, List <GlyphPlan> glyphPlans) { NativeFont nativeFont = actualFont as NativeFont; if (nativeFont == null) { nativeFont = ResolveForNativeFont(actualFont); } unsafe { //TODO: review proper array size here int lim = len * 2; ProperGlyph *properGlyphArray = stackalloc ProperGlyph[lim]; fixed(char *head = &buffer[0]) { //we use font shaping engine here NativeMyFontsLib.MyFtShaping( nativeFont.NativeFontFace.HBFont, head, buffer.Length, properGlyphArray); } //copy from proper glyph to //create glyph plan for (int i = 0; i < lim; ++i) { ProperGlyph propGlyph = properGlyphArray[i]; if (propGlyph.codepoint == 0) { //finish , just return return; } glyphPlans.Add(new GlyphPlan((ushort)propGlyph.codepoint, 0, 0, (ushort)propGlyph.x_advance)); } } }
protected override void OnReadyForInitGLShaderProgram() { InstalledFontCollection collection = new InstalledFontCollection(); collection.LoadSystemFonts(); InstalledFont tahomaFont = collection.GetFont("tahoma", InstalledFontStyle.Normal); FontFace tahomaFace = OpenFontLoader.LoadFont(tahomaFont.FontPath); ActualFont actualFont = tahomaFace.GetFontAtPointSize(72); FontGlyph glyph = (FontGlyph)actualFont.GetGlyph('K'); //var svgFont = svgFontStore.LoadFont("svg-LiberationSansFont", 300); ////PathWriter p01 = new PathWriter(); ////p01.MoveTo(0, 0); ////p01.LineTo(50, 100); ////p01.LineTo(100, 0); //////- ////p01.MoveTo(220, 10); ////p01.LineTo(50, 75); ////p01.LineTo(25, 15); ////p01.CloseFigure(); ////p01.Stop(); ////m_pathVxs = p01.Vxs; //var m_pathVxs = svgFont.GetGlyph('K').originalVxs;// typeFaceForLargeA.GetGlyphForCharacter('a'); ////m_pathVxs = MergeFontSubFigures(m_pathVxs); //Affine shape_mtx = Affine.NewMatix(AffinePlan.Translate(150, 100)); //m_pathVxs = shape_mtx.TransformToVxs(m_pathVxs); //var curveFlattener = new CurveFlattener(); //var m_pathVxs2 = curveFlattener.MakeVxs(m_pathVxs); glyph_vx = painter.CreateRenderVx(tempSnap1 = new PixelFarm.Drawing.VertexStoreSnap(glyph.flattenVxs)); linearGrBrush2 = new LinearGradientBrush( new PointF(0, 0), Color.Red, new PointF(100, 100), Color.Black); //---------------------- }
static void BuildFontGlyph(ActualFont nativefont, Typography.Rendering.SimpleFontAtlasBuilder atlasBuilder, char c) { //font glyph for specific font face FontGlyph fontGlyph = nativefont.GetGlyph(c); GlyphImage glyphImg = NativeMsdfGen.BuildMsdfFontImage(fontGlyph); int w = glyphImg.Width; int h = glyphImg.Height; int[] buffer = glyphImg.GetImageBuffer(); NativeMsdfGen.SwapColorComponentFromBigEndianToWinGdi(buffer); glyphImg.SetImageBuffer(buffer, false); atlasBuilder.AddGlyph(0, glyphImg); //using (Bitmap bmp = new Bitmap(w, h, System.Drawing.Imaging.PixelFormat.Format32bppArgb)) //{ // var bmpdata = bmp.LockBits(new Rectangle(0, 0, w, h), System.Drawing.Imaging.ImageLockMode.ReadWrite, bmp.PixelFormat); // System.Runtime.InteropServices.Marshal.Copy(buffer, 0, bmpdata.Scan0, buffer.Length); // bmp.UnlockBits(bmpdata); // bmp.Save("d:\\WImageTest\\a001_x1_" + (int)c + ".png"); //} }
private void button6_Click(object sender, EventArgs e) { //1. load font ActualFont font = GetActualFont("tahoma", 28);// nativeFontStore.LoadFont("tahoma", 28); //2. get glyph var g1 = font.GetGlyph('C'); var plans = new List <Typography.TextLayout.GlyphPlan>(); PixelFarm.Drawing.Text.TextShapingService.GetGlyphPos(font, "ABC".ToCharArray(), 0, 3, plans); int[] glyphIndice = new int[] { 1076, 1127, 1164 }; int j = glyphIndice.Length; var atlasBuilder = new Typography.Rendering.SimpleFontAtlasBuilder(); for (int i = 0; i < j; ++i) { int codepoint = glyphIndice[i]; FontGlyph fontGlyph = font.GetGlyphByIndex((uint)codepoint); GlyphImage glyphImg = NativeMsdfGen.BuildMsdfFontImage(fontGlyph); int w = glyphImg.Width; int h = glyphImg.Height; int[] buffer = glyphImg.GetImageBuffer(); NativeMsdfGen.SwapColorComponentFromBigEndianToWinGdi(buffer); glyphImg.SetImageBuffer(buffer, false); atlasBuilder.AddGlyph(codepoint, glyphImg); using (Bitmap bmp = new Bitmap(w, h, System.Drawing.Imaging.PixelFormat.Format32bppArgb)) { var bmpdata = bmp.LockBits(new System.Drawing.Rectangle(0, 0, w, h), System.Drawing.Imaging.ImageLockMode.ReadWrite, bmp.PixelFormat); System.Runtime.InteropServices.Marshal.Copy(buffer, 0, bmpdata.Scan0, buffer.Length); bmp.UnlockBits(bmpdata); bmp.Save("d:\\WImageTest\\a001_y1_" + codepoint + ".png"); } } //---------------------------------------------------- GlyphImage totalImg = atlasBuilder.BuildSingleImage(); using (Bitmap bmp = new Bitmap(totalImg.Width, totalImg.Height, System.Drawing.Imaging.PixelFormat.Format32bppArgb)) { int[] buffer = totalImg.GetImageBuffer(); if (totalImg.IsBigEndian) { NativeMsdfGen.SwapColorComponentFromBigEndianToWinGdi(buffer); totalImg.SetImageBuffer(buffer, false); } var bmpdata = bmp.LockBits(new System.Drawing.Rectangle(0, 0, totalImg.Width, totalImg.Height), System.Drawing.Imaging.ImageLockMode.ReadWrite, bmp.PixelFormat); System.Runtime.InteropServices.Marshal.Copy(buffer, 0, bmpdata.Scan0, buffer.Length); bmp.UnlockBits(bmpdata); bmp.Save("d:\\WImageTest\\a_total.png"); } string fontfilename = "d:\\WImageTest\\a_total.xml"; atlasBuilder.SaveFontInfo(fontfilename); //---------------------------------- }
private void button3_Click(object sender, EventArgs e) { //1. load font string fontName = "tahoma"; int fontSizeInPts = 28; ActualFont font = GetActualFont(fontName, fontSizeInPts); //2. get glyph char[] fontChars = "ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789".ToCharArray(); int j = fontChars.Length; var atlasBuilder = new Typography.Rendering.SimpleFontAtlasBuilder(); atlasBuilder.SetAtlasInfo(TextureKind.Msdf, fontSizeInPts); for (int i = 0; i < j; ++i) { char c = fontChars[i]; FontGlyph fontGlyph = font.GetGlyph(c); GlyphImage glyphImg = NativeMsdfGen.BuildMsdfFontImage(fontGlyph); int w = glyphImg.Width; int h = glyphImg.Height; int[] buffer = glyphImg.GetImageBuffer(); NativeMsdfGen.SwapColorComponentFromBigEndianToWinGdi(buffer); glyphImg.SetImageBuffer(buffer, false); atlasBuilder.AddGlyph(0, glyphImg); using (Bitmap bmp = new Bitmap(w, h, System.Drawing.Imaging.PixelFormat.Format32bppArgb)) { var bmpdata = bmp.LockBits( new System.Drawing.Rectangle(0, 0, w, h), System.Drawing.Imaging.ImageLockMode.ReadWrite, bmp.PixelFormat); System.Runtime.InteropServices.Marshal.Copy(buffer, 0, bmpdata.Scan0, buffer.Length); bmp.UnlockBits(bmpdata); bmp.Save("d:\\WImageTest\\a001_x1_" + (int)c + ".png"); } } //---------------------------------------------------- GlyphImage totalImg = atlasBuilder.BuildSingleImage(); using (Bitmap bmp = new Bitmap(totalImg.Width, totalImg.Height, System.Drawing.Imaging.PixelFormat.Format32bppArgb)) { int[] buffer = totalImg.GetImageBuffer(); if (totalImg.IsBigEndian) { NativeMsdfGen.SwapColorComponentFromBigEndianToWinGdi(buffer); totalImg.SetImageBuffer(buffer, false); } var bmpdata = bmp.LockBits(new System.Drawing.Rectangle(0, 0, totalImg.Width, totalImg.Height), System.Drawing.Imaging.ImageLockMode.ReadWrite, bmp.PixelFormat); System.Runtime.InteropServices.Marshal.Copy(buffer, 0, bmpdata.Scan0, buffer.Length); bmp.UnlockBits(bmpdata); bmp.Save("d:\\WImageTest\\a_total.png"); } string fontfilename = "d:\\WImageTest\\a_total.xml"; atlasBuilder.SaveFontInfo(fontfilename); //---------------------------------- }
protected override void GetGlyphPosImpl(ActualFont actualFont, char[] buffer, int startAt, int len, List <GlyphPlan> properGlyphs) { //do shaping and set text layout }
protected abstract void GetGlyphPosImpl(ActualFont actualFont, char[] buffer, int startAt, int len, List <UnscaledGlyphPlan> properGlyphs);
public static void GetGlyphPos(ActualFont actualFont, char[] buffer, int startAt, int len, List <UnscaledGlyphPlan> properGlyphs) { defaultSharpingService.GetGlyphPosImpl(actualFont, buffer, startAt, len, properGlyphs); }
protected internal override void Draw(DrawingHandleScreen handle) { base.Draw(handle); var font = ActualFont; var listBg = ActualBackground; var iconBg = ActualItemBackground; var iconSelectedBg = ActualSelectedItemBackground; var iconDisabledBg = ActualDisabledItemBackground; var offset = -_scrollBar.Value; listBg.Draw(handle, PixelSizeBox); foreach (var item in _itemList) { var bg = iconBg; if (item.Disabled) { bg = iconDisabledBg; } if (item.Selected) { bg = iconSelectedBg; } var itemHeight = 0f; if (item.Icon != null) { itemHeight = item.IconSize.Y; } itemHeight = Math.Max(itemHeight, ActualFont.GetHeight(UIScale)); itemHeight += ActualItemBackground.MinimumSize.Y; item.Region = UIBox2.FromDimensions(0, offset, PixelWidth, itemHeight); bg.Draw(handle, item.Region.Value); var contentBox = bg.GetContentBox(item.Region.Value); var drawOffset = contentBox.TopLeft; if (item.Icon != null) { if (item.IconRegion.Size == Vector2.Zero) { handle.DrawTextureRect(item.Icon, UIBox2.FromDimensions(drawOffset, item.Icon.Size), false, item.IconModulate, item.IconTranspose); } else { handle.DrawTextureRectRegion(item.Icon, UIBox2.FromDimensions(drawOffset, item.Icon.Size), item.IconRegion, item.IconModulate); } } if (item.Text != null) { var textBox = new UIBox2(contentBox.Left + item.IconSize.X, contentBox.Top, contentBox.Right, contentBox.Bottom); DrawTextInternal(handle, item.Text, textBox); } offset += itemHeight; } }
public void DrawString(char[] buffer, double x, double y) { int j = buffer.Length; int buffsize = j * 2; //resolve font from painter? ActualFont fontImp = ff.GetFontAtPointsSize(font.SizeInPoints); var tt = (Typography.OpenFont.Typeface)ff.GetInternalTypeface(); List <GlyphPlan> glyphPlans = new List <GlyphPlan>(); _glyphLayout.Layout(tt, font.SizeInPoints, buffer, glyphPlans); // //un-test version //ActualFont fontImp = nativeFontStore.GetResolvedNativeFont(painter.CurrentFont); //if (properGlyphs == null) //{ // properGlyphs = new ProperGlyph[buffsize]; // TextShapingService.GetGlyphPos(fontImp, buffer, 0, buffsize, properGlyphs); //} //TODO: implement msdf texture //double xpos = x; //for (int i = 0; i < buffsize; ++i) //{ // uint codepoint = properGlyphs[i].codepoint; // if (codepoint == 0) // { // break; // } // //------------------------------------------------------------- // FontGlyph glyph = fontImp.GetGlyphByIndex(codepoint); // //glyph image32 // //------------------------------------------------------------- // GLBitmap bmp = new GLBitmap(new LazyAggBitmapBufferProvider(glyph.glyphImage32)); // var left = glyph.glyphMatrix.img_horiBearingX; // this.canvas2d.DrawImage(bmp, // (float)(xpos + (left >> 6)), // (float)(y + (glyph.glyphMatrix.bboxYmin >> 6))); // int w = (glyph.glyphMatrix.advanceX) >> 6; // xpos += (w); // bmp.Dispose(); //temp here // //------------------------------------------------------------- //} //------------------------------------- //msdf texture version double xpos = x; int n = glyphPlans.Count; Typography.Rendering.GlyphImage glyphImage = simpleFontAtlas.TotalGlyph; GLBitmap glBmp = new GLBitmap(glyphImage.Width, glyphImage.Height, glyphImage.GetImageBuffer(), false); float c_x = (float)x; float c_y = (float)y; //int left = ((int)(glyph.glyphMatrix.img_horiBearingX * scale) >> 6); int left = 0; //float baseline = c_y - 24;//eg line height= 24 //create a list float baseline = c_y - 24;//eg line height= 24 //create a list bool isFlipY = canvas2d.FlipY; if (!isFlipY) { canvas2d.FlipY = true; } for (int i = 0; i < n; ++i) { GlyphPlan glyph = glyphPlans[i]; Typography.Rendering.TextureFontGlyphData glyphData; if (!simpleFontAtlas.GetRectByCodePoint(glyph.glyphIndex, out glyphData)) { //Rectangle r = glyphData.Rect; //float x_min = glyphData.BBoxXMin / 64; ////draw each glyph at specific position ////_canvas.DrawSubImageWithMsdf(glBmp, ref r, c_x + x_min, (float)(baseline + r.Height)); //_canvas.DrawSubImageWithMsdf(glBmp, ref r, c_x + x_min, (float)(baseline + r.Height)); ////c_x += r.Width - 10; //c_x += (glyphData.AdvanceX / 64); continue; } //found PixelFarm.Drawing.Rectangle r = ConvToRect(glyphData.Rect); //test draw full msdf gen img //canvas2d.DrawImage(glBmp, c_x + left, (float)(baseline + ((int)(glyphData.ImgHeight)))); canvas2d.DrawSubImageWithMsdf(glBmp, ref r, c_x + left, (float)(baseline + ((int)(glyphData.ImgHeight))), 1.0f); c_x += glyph.advX; } canvas2d.FlipY = isFlipY; glBmp.Dispose(); //temp here //draw with texture printer *** //char[] chars = text.ToCharArray(); //int j = chars.Length; //int buffsize = j * 2; ////get kerning list ////get actual font for this canvas //TextureFont currentFont = _currentTextureFont; //SimpleFontAtlas fontAtlas = currentFont.FontAtlas; //ProperGlyph[] properGlyphs = new ProperGlyph[buffsize]; //TextShapingService.GetGlyphPos(currentFont, chars, 0, buffsize, properGlyphs); //GLBitmap glBmp = (GLBitmap)currentFont.GLBmp; //if (glBmp == null) //{ // //create glbmp // GlyphImage glyphImage = fontAtlas.TotalGlyph; // int[] buffer = glyphImage.GetImageBuffer(); // glBmp = new GLBitmap(glyphImage.Width, glyphImage.Height, buffer, false); //} ////int j = chars.Length; //// //float c_x = (float)x; //float c_y = (float)y; ////TODO: review here *** ////----------------- ////1. layout each glyph before render *** //// //float baseline = c_y - 24;//eg line height= 24 //create a list ////-------------- //List<float> coords = new List<float>(); //float scale = 1f; //for (int i = 0; i < buffsize; ++i) //{ // ProperGlyph glyph1 = properGlyphs[i]; // uint codepoint = properGlyphs[i].codepoint; // if (codepoint == 0) // { // break; // } // //-------------------------------- // //if (codepoint == 1173 && i > 1) // //{ // // //check prev code point // // codepoint = 1168; // //} // //-------------------------------- // TextureFontGlyphData glyphData; // if (!fontAtlas.GetRectByCodePoint((int)codepoint, out glyphData)) // { // //Rectangle r = glyphData.Rect; // //float x_min = glyphData.BBoxXMin / 64; // ////draw each glyph at specific position // ////_canvas.DrawSubImageWithMsdf(glBmp, ref r, c_x + x_min, (float)(baseline + r.Height)); // //_canvas.DrawSubImageWithMsdf(glBmp, ref r, c_x + x_min, (float)(baseline + r.Height)); // ////c_x += r.Width - 10; // //c_x += (glyphData.AdvanceX / 64); // continue; // } // FontGlyph glyph = currentFont.GetGlyphByIndex(codepoint); // int left = ((int)(glyph.glyphMatrix.img_horiBearingX * scale) >> 6); // Rectangle r = glyphData.Rect; // int adjustX = 0; // int bboxYMin = glyph.glyphMatrix.bboxYmin >> 6; // if (bboxYMin > 1 || bboxYMin < -1) // { // // adjustX = 3; // } // //scale down 0.8; // //_canvas.DrawSubImageWithMsdf(glBmp, ref r, adjustX + c_x + left, // // (float)(baseline + ((int)(glyphData.ImgHeight + glyph.glyphMatrix.bboxYmin) >> 6)), 1.1f); // coords.Add(r.Left); // coords.Add(r.Top); // coords.Add(r.Width); // coords.Add(r.Height); // //------------------------- // coords.Add(adjustX + c_x + left); // //coords.Add(baseline + ((int)((glyphData.ImgHeight + glyph.glyphMatrix.bboxYmin) * scale) >> 6)); // coords.Add(baseline + ((int)((glyphData.ImgHeight + glyphData.BBoxYMin) * scale) >> 6)); // //int w = (int)(glyph.glyphMatrix.advanceX * scale) >> 6; // int w = (int)(glyph.horiz_adv_x * scale) >> 6; // c_x += w; //} //_canvas.DrawSubImageWithMsdf(glBmp, coords.ToArray(), scale); //----------------------- //public override void DrawString(string text, double x, double y) //{ // char[] chars = text.ToCharArray(); // int j = chars.Length; // int buffsize = j * 2; // //get kerning list // TextureFont currentFont = this.CurrentFont as TextureFont; // SimpleFontAtlas fontAtlas = currentFont.FontAtlas; // ProperGlyph[] properGlyphs = new ProperGlyph[buffsize]; // currentFont.GetGlyphPos(chars, 0, buffsize, properGlyphs); // GLBitmap glBmp = currentFont.GLBmp; // if (glBmp == null) // { // //create glbmp // GlyphImage glyphImage = fontAtlas.TotalGlyph; // int[] buffer = glyphImage.GetImageBuffer(); // glBmp = new GLBitmap(glyphImage.Width, glyphImage.Height, buffer, false); // } // //int j = chars.Length; // // // float c_x = (float)x; // float c_y = (float)y; // //TODO: review here // //----------------- // //1. layout each glyph before render *** // float baseline = c_y - 24;//eg line height= 24 // //create a list // for (int i = 0; i < buffsize; ++i) // { // ProperGlyph glyph1 = properGlyphs[i]; // uint codepoint = properGlyphs[i].codepoint; // if (codepoint == 0) // { // break; // } // if (codepoint == 1173 && i > 1) // { // //check prev code point // codepoint = 1168; // } // TextureFontGlyphData glyphData; // if (!fontAtlas.GetRect((int)codepoint, out glyphData)) // { // //Rectangle r = glyphData.Rect; // //float x_min = glyphData.BBoxXMin / 64; // ////draw each glyph at specific position // ////_canvas.DrawSubImageWithMsdf(glBmp, ref r, c_x + x_min, (float)(baseline + r.Height)); // //_canvas.DrawSubImageWithMsdf(glBmp, ref r, c_x + x_min, (float)(baseline + r.Height)); // ////c_x += r.Width - 10; // //c_x += (glyphData.AdvanceX / 64); // continue; // } // //------------------------------------------------------------- // //FontGlyph glyph = this.currentFont.GetGlyphByIndex(codepoint); // FontGlyph glyph = currentFont.GetGlyphByIndex(codepoint); // int left = (glyph.glyphMatrix.img_horiBearingX >> 6); // Rectangle r = glyphData.Rect; // int adjustX = 0; // int bboxYMin = glyph.glyphMatrix.bboxYmin >> 6; // if (bboxYMin > 1 || bboxYMin < -1) // { // // adjustX = 3; // } // //scale down 0.8; // _canvas.DrawSubImageWithMsdf(glBmp, ref r, adjustX + c_x + left, // (float)(baseline + ((int)(glyphData.ImgHeight + glyph.glyphMatrix.bboxYmin) >> 6)), 1.1f); // int w = (glyph.glyphMatrix.advanceX) >> 6; // c_x += (w); // } //} // public override void DrawString(string text, double x, double y) // { // ////in this version we draw string to image // ////and the write the image back to gl surface // //_winGfx.Clear(System.Drawing.Color.White); // //_winGfx.DrawString(text, _winFont, _winGfxBrush, 0, 0); // ////_winGfxBackBmp.Save("d:\\WImageTest\\a00123.png"); // //System.Drawing.SizeF textAreaSize = _winGfx.MeasureString(text, _winFont); // //var bmpData = _winGfxBackBmp.LockBits(new System.Drawing.Rectangle(0, 0, _winGfxBackBmp.Width, _winGfxBackBmp.Height), System.Drawing.Imaging.ImageLockMode.ReadOnly, _winGfxBackBmp.PixelFormat); // //int width = (int)textAreaSize.Width; // //int height = (int)textAreaSize.Height; // //ActualImage actualImg = new ActualImage(width, height, Agg.Image.PixelFormat.ARGB32); // ////------------------------------------------------------ // ////copy bmp from specific bmp area // ////and convert to GLBmp // //int stride = bmpData.Stride; // //byte[] buffer = actualImg.GetBuffer(); // //unsafe // //{ // // byte* header = (byte*)bmpData.Scan0; // // fixed (byte* dest0 = &buffer[0]) // // { // // byte* dest = dest0; // // byte* rowHead = header; // // int rowLen = width * 4; // // for (int h = 0; h < height; ++h) // // { // // header = rowHead; // // for (int n = 0; n < rowLen;) // // { // // //move next // // *(dest + 0) = *(header + 0); // // *(dest + 1) = *(header + 1); // // *(dest + 2) = *(header + 2); // // *(dest + 3) = *(header + 3); // // header += 4; // // dest += 4; // // n += 4; // // } // // //finish one row // // rowHead += stride; // // } // // } // //} // //_winGfxBackBmp.UnlockBits(bmpData); // ////------------------------------------------------------ // //GLBitmap glBmp = new GLBitmap(width, height, buffer, false); // //_canvas.DrawImageWithWhiteTransparent(glBmp, (float)x, (float)y); // //glBmp.Dispose(); // } }