public void DrawString(char[] text, int startAt, int len, double x, double y) { float ox = canvasPainter.OriginX; float oy = canvasPainter.OriginY; //1. update some props.. //2. update current type face UpdateTypefaceAndGlyphBuilder(); Typeface typeface = _glyphPathBuilder.Typeface; //3. layout glyphs with selected layout technique //TODO: review this again, we should use pixel? float fontSizePoint = this.FontSizeInPoints; float scale = typeface.CalculateToPixelScaleFromPointSize(fontSizePoint); _outputGlyphPlans.Clear(); _glyphLayout.Layout(typeface, text, startAt, len, _outputGlyphPlans); //4. render each glyph int j = _outputGlyphPlans.Count; //--------------------------------------------------- //consider use cached glyph, to increase performance hintGlyphCollection.SetCacheInfo(typeface, fontSizePoint, this.HintTechnique); //--------------------------------------------------- for (int i = 0; i < j; ++i) { GlyphPlan glyphPlan = _outputGlyphPlans[i]; //----------------------------------- //TODO: review here *** //PERFORMANCE revisit here //if we have create a vxs we can cache it for later use? //----------------------------------- VertexStore glyphVxs; if (!hintGlyphCollection.TryGetCacheGlyph(glyphPlan.glyphIndex, out glyphVxs)) { //if not found then create new glyph vxs and cache it _glyphPathBuilder.SetHintTechnique(this.HintTechnique); _glyphPathBuilder.BuildFromGlyphIndex(glyphPlan.glyphIndex, fontSizePoint); //----------------------------------- _tovxs.Reset(); _glyphPathBuilder.ReadShapes(_tovxs); //TODO: review here, //float pxScale = _glyphPathBuilder.GetPixelScale(); glyphVxs = new VertexStore(); _tovxs.WriteOutput(glyphVxs, _vxsPool); // hintGlyphCollection.RegisterCachedGlyph(glyphPlan.glyphIndex, glyphVxs); } canvasPainter.SetOrigin((float)(glyphPlan.x * scale + x), (float)(glyphPlan.y * scale + y)); canvasPainter.Fill(glyphVxs); } //restore prev origin canvasPainter.SetOrigin(ox, oy); }
public void PrepareStringForRenderVx(RenderVxFormattedString renderVx, char[] text, int startAt, int len) { //1. update some props.. //2. update current type face UpdateTypefaceAndGlyphBuilder(); Typeface typeface = _currentTypeface;// _glyphPathBuilder.Typeface; _glyphLayout.Typeface = typeface; _glyphLayout.Layout(text, startAt, len); // //3. scale from design unit to specific font size _outputGlyphPlans.Clear(); _pxScaleEngine.Layout(_glyphLayout.ResultUnscaledGlyphPositions, _outputGlyphPlans); TextPrinterHelper.CopyGlyphPlans(renderVx, _outputGlyphPlans, this._currentFontSizePxScale); }
public static void GenerateGlyphPlans(this GlyphLayout glyphLayout, char[] textBuffer, int startAt, int len, UnscaledGlyphPlanList list) { //generate glyph plan based on its current setting glyphLayout.Layout(textBuffer, startAt, len); ReadOutput(glyphLayout, list); }
public virtual void GenerateGlyphPlan( char[] textBuffer, int startAt, int len, IUnscaledGlyphPlanList unscaledGlyphPlan) { GlyphLayout glyphLayout = this.GlyphLayoutMan; glyphLayout.Layout(textBuffer, startAt, len); glyphLayout.GenerateUnscaledGlyphPlans(unscaledGlyphPlan); }
public MeasuredStringBox Measure(char[] textBuffer, int startAt, int len) { glyphLayout.Typeface = this.CurrentTypeFace; float pxscale = CurrentTypeFace.CalculateScaleToPixelFromPointSize(this.FontSizeInPoints); glyphLayout.Layout(textBuffer, startAt, len); _reusableGlyphPlanList.Clear(); IGlyphPositions glyphPositions = glyphLayout.ResultUnscaledGlyphPositions; GlyphLayoutExtensions.GenerateGlyphPlan(glyphLayout.ResultUnscaledGlyphPositions, pxscale, false, _reusableGlyphPlanList); return(new MeasuredStringBox( _reusableGlyphPlanList.AccumAdvanceX * pxscale, CurrentTypeFace.Ascender * pxscale, CurrentTypeFace.Descender * pxscale, CurrentTypeFace.LineGap * pxscale, Typography.OpenFont.Extensions.TypefaceExtensions.CalculateRecommendLineSpacing(CurrentTypeFace) * pxscale)); }
public override void DrawString(char[] textBuffer, int startAt, int len, float x, float y) { _reusableUnscaledGlyphPlanList.Clear(); //1. unscale layout, in design unit _glyphLayout.Layout(textBuffer, startAt, len); _glyphLayout.GenerateUnscaledGlyphPlans(_reusableUnscaledGlyphPlanList); //draw from the glyph plan seq DrawFromGlyphPlans( new GlyphPlanSequence(_reusableUnscaledGlyphPlanList), x, y); }
} // End Sub DrawFromGlyphPlans public override void DrawString(char[] textBuffer, int startAt, int len, float x, float y) { this.TargetGraphics.SetTextAndFont(new string(textBuffer), this.Typeface.Name, this.FontSizeInPoints); this.TargetGraphics.OpenGroup(); _reusableUnscaledGlyphPlanList.Clear(); //1. unscale layout, in design unit _glyphLayout.Layout(textBuffer, startAt, len); _glyphLayout.GenerateUnscaledGlyphPlans(_reusableUnscaledGlyphPlanList); //draw from the glyph plan seq DrawFromGlyphPlans(new GlyphPlanSequence(_reusableUnscaledGlyphPlanList), x, y); this.TargetGraphics.CloseGroup(); } // End Sub DrawString
public void PrepareStringForRenderVx(RenderVxFormattedString renderVx, char[] text, int startAt, int len) { //1. update some props.. //2. update current type face UpdateTypefaceAndGlyphBuilder(); Typeface typeface = _currentTypeface;// _glyphPathBuilder.Typeface; //3. layout glyphs with selected layout technique //TODO: review this again, we should use pixel? float pxscale = typeface.CalculateToPixelScaleFromPointSize(FontSizeInPoints); _outputGlyphPlans.Clear(); _glyphLayout.Layout(typeface, text, startAt, len, _outputGlyphPlans); TextPrinterHelper.CopyGlyphPlans(renderVx, _outputGlyphPlans, pxscale); }
public virtual void GenerateGlyphPlan( char[] textBuffer, int startAt, int len, GlyphPlanList outputGlyphPlanList, List <UserCodePointToGlyphIndex> charToGlyphMapList) { GlyphLayout glyphLayout = this.GlyphLayoutMan; glyphLayout.Layout(textBuffer, startAt, len); GlyphLayoutExtensions.GenerateGlyphPlans( glyphLayout.ResultUnscaledGlyphPositions, this.Typeface.CalculateScaleToPixelFromPointSize(this.FontSizeInPoints), false, outputGlyphPlanList); }
GlyphPlanSequence CreateGlyphPlanSeq(GlyphLayout glyphLayout, TextBuffer buffer, int startAt, int len) { GlyphPlanList planList = GlyphPlanBuffer.UnsafeGetGlyphPlanList(_glyphPlanBuffer); int pre_count = planList.Count; glyphLayout.Typeface = _typeface; glyphLayout.ScriptLang = _scLang; glyphLayout.Layout( TextBuffer.UnsafeGetCharBuffer(buffer), startAt, len); int post_count = planList.Count; return(new GlyphPlanSequence(_glyphPlanBuffer, pre_count, post_count - pre_count)); }
public GlyphPlanSequence GetUnscaledGlyphPlanSequence( GlyphLayout glyphLayout, TextBuffer buffer, int start, int seqLen) { //UNSCALED VERSION //use current typeface + scriptlang int seqHashValue = CalculateHash(buffer, start, seqLen); //this func get the raw char from buffer //and create glyph list //check if we have the string cache in specific value //--------- if (seqLen > _glyphPlanSeqSet.MaxCacheLen) { //layout string is too long to be cache //it need to split into small buffer } GlyphPlanSequence planSeq = GlyphPlanSequence.Empty; GlyphPlanSeqCollection seqCol = _glyphPlanSeqSet.GetSeqCollectionOrCreateIfNotExist(seqLen); if (!seqCol.TryGetCacheGlyphPlanSeq(seqHashValue, out planSeq)) { //create a new one if we don't has a cache //1. layout glyphLayout.Layout( buffer.UnsafeGetInternalBuffer(), start, seqLen); int pre_count = _reusableGlyphPlanList.Count; //create glyph-plan ( UnScaled version) and add it to planList glyphLayout.GenerateUnscaledGlyphPlans(_reusableGlyphPlanList); int post_count = _reusableGlyphPlanList.Count; planSeq = new GlyphPlanSequence(_reusableGlyphPlanList, pre_count, post_count - pre_count); // seqCol.Register(seqHashValue, planSeq); } return(planSeq); }
List <ushort> inputGlyphs = new List <ushort>(); //not thread safe*** public void Print(Typeface typeface, float size, char[] str, List <GlyphPlan> glyphPlanBuffer) { //1. layout _glyphLayout.Layout(typeface, size, str, glyphPlanBuffer); var glyphPathBuilder = new MyGlyphPathBuilder(typeface); int j = glyphPlanBuffer.Count; float pxScale = typeface.CalculateFromPointToPixelScale(size); for (int i = 0; i < j; ++i) { GlyphPlan glyphPlan = glyphPlanBuffer[i]; //----------------------------------- //check if we static vxs/bmp for this glyph //if not, create and cache //----------------------------------- glyphPathBuilder.BuildFromGlyphIndex(glyphPlan.glyphIndex, size); //----------------------------------- var vxsBuilder = new GlyphPathBuilderVxs(); glyphPathBuilder.ReadShapes(vxsBuilder); glyphPlan.vxs = vxsBuilder.GetVxs(pxScale); } }
public void DrawString(char[] buffer, int startAt, int len, double x, double y) { int j = buffer.Length; //resolve font from painter? glyphPlans.Clear(); _glyphLayout.Layout(_typeface, buffer, startAt, len, glyphPlans); float scale = _typeface.CalculateToPixelScaleFromPointSize(font.SizeInPoints); //-------------------------- //TODO: //if (x,y) is left top //we need to adjust y again y -= (_typeface.Ascender - _typeface.Descender + _typeface.LineGap) * scale; int n = glyphPlans.Count; EnsureLoadGLBmp(); // float scaleFromTexture = _finalTextureScale; Typography.Rendering.TextureKind textureKind = simpleFontAtlas.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); //-------------------------- GlyphPosPixelSnapKind x_snap = this.GlyphPosPixelSnapX; GlyphPosPixelSnapKind y_snap = this.GlyphPosPixelSnapY; float g_x = 0; float g_y = 0; int baseY = (int)Math.Round(y); for (int i = 0; i < n; ++i) { GlyphPlan glyph = glyphPlans[i]; Typography.Rendering.TextureFontGlyphData glyphData; if (!simpleFontAtlas.TryGetGlyphDataByCodePoint(glyph.glyphIndex, out glyphData)) { continue; } //-------------------------------------- //TODO: review precise height in float //-------------------------------------- PixelFarm.Drawing.Rectangle srcRect = ConvToRect(glyphData.Rect); switch (x_snap) { default: throw new NotSupportedException(); case GlyphPosPixelSnapKind.Integer: { g_x = (float)(x + (glyph.x * scale - glyphData.TextureXOffset) * scaleFromTexture); //ideal x int floor_x = (int)g_x; //round to int 0,1 if (g_x - floor_x >= (1f / 2f)) { g_x = floor_x + 1; } else { g_x = floor_x; } } break; case GlyphPosPixelSnapKind.Half: { g_x = (float)(x + (glyph.x * scale - glyphData.TextureXOffset) * scaleFromTexture); //ideal x //adjust int floor_x = (int)g_x; //round to int 0, 0.5,1.0 if (g_x - floor_x >= (2f / 3f)) { g_x = floor_x + 1; } else if (g_x - floor_x >= (1f / 3f)) { g_x = floor_x + 0.5f; } else { g_x = floor_x; } } break; case GlyphPosPixelSnapKind.None: g_x = (float)(x + (glyph.x * scale - glyphData.TextureXOffset) * scaleFromTexture); break; } // switch (y_snap) { default: throw new NotSupportedException(); case GlyphPosPixelSnapKind.Integer: //use baseY not y { g_y = (float)((glyph.y * scale - glyphData.TextureYOffset + srcRect.Height) * scaleFromTexture); int floor_y = (int)g_y; //round to int 0,1 if (g_y - floor_y >= (1f / 2f)) { g_y = floor_y + 1; } else { g_y = floor_y; } g_y = baseY + g_y; } break; case GlyphPosPixelSnapKind.Half: //review here //use baseY not y { g_y = (float)((glyph.y * scale - glyphData.TextureYOffset + srcRect.Height) * scaleFromTexture); int floor_y = (int)g_y; //round to int 0, 0.5,1.0 if (g_y - floor_y >= (2f / 3f)) { g_y = floor_y + 1; } else if (g_x - floor_y >= (1f / 3f)) { g_y = floor_y + 0.5f; } else { g_y = floor_y; } g_y = baseY + g_y; } break; case GlyphPosPixelSnapKind.None: //use Y not baseY g_y = (float)(y + (glyph.y * scale - glyphData.TextureYOffset + srcRect.Height) * scaleFromTexture); break; } switch (textureKind) { case Typography.Rendering.TextureKind.Msdf: canvas2d.DrawSubImageWithMsdf(_glBmp, ref srcRect, g_x, g_y, scaleFromTexture); break; case Typography.Rendering.TextureKind.AggGrayScale: canvas2d.DrawSubImage(_glBmp, ref srcRect, g_x, g_y, scaleFromTexture); break; case Typography.Rendering.TextureKind.AggSubPixel: canvas2d.DrawGlyphImageWithSubPixelRenderingTechnique(_glBmp, ref srcRect, g_x, g_y, scaleFromTexture); break; } } }
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(); // } }
private void button3_Click(object sender, EventArgs e) { //it should be faster if we use 'mesh' cache //instead of read-transform it every time like code above(button2_click) LoadFont(); float font_size_in_Point = 20; _glyphMeshStore.SetFont(_latinModernMathFont, font_size_in_Point);//20= font size _glyphMeshStore.FlipGlyphUpward = true; float px_scale = _latinModernMathFont.CalculateScaleToPixelFromPointSize(font_size_in_Point); using (Tools.BorrowAggPainter(_memBmp, out var p)) { p.Clear(PixelFarm.Drawing.Color.White); float prevX = p.OriginX; float prevY = p.OriginY; int line_left = 10; int line_top = 50; p.SetOrigin(line_left, line_top);//*** test //draw reference point p.FillRect(0, 0, 5, 5, PixelFarm.Drawing.Color.Red); char[] test_str = "‽_x‾".ToCharArray(); int inline_left = 0; int inline_top = 0; //---------- GlyphLayout glyphLayout = new GlyphLayout(); glyphLayout.ScriptLang = new ScriptLang("math"); glyphLayout.Typeface = _latinModernMathFont; //temp fix for some typeface glyphLayout.SetGlyphIndexNotFoundHandler((glyph_layout, codepoint, next_codepoint) => { switch (codepoint) { //overline unicode case 8254: return(2246); //overline-combine, this will break into 3 parts in math layout process } return(0); }); // glyphLayout.Layout(test_str, 0, test_str.Length); List <UnscaledGlyphPlan> glyphPlans = new List <UnscaledGlyphPlan>(); foreach (UnscaledGlyphPlan glypyPlan in glyphLayout.GetUnscaledGlyphPlanIter()) { glyphPlans.Add(glypyPlan); } //-------- for (int i = 0; i < glyphPlans.Count; ++i) { //ushort glyphIndex = _latinModernMathFont.GetGlyphIndex((int)test_str[i]); ////do some glyph-substitution //ushort advW = _latinModernMathFont.GetAdvanceWidth((int)test_str[i]);//unscale glyph width //now scale it to specific font size UnscaledGlyphPlan glyphPlan = glyphPlans[i]; int advW_s = (int)System.Math.Round(px_scale * glyphPlan.AdvanceX); VertexStore v1 = _glyphMeshStore.GetGlyphMesh(glyphPlan.glyphIndex); p.SetOrigin(line_left + inline_left, line_top + inline_top); p.Fill(v1, PixelFarm.Drawing.Color.Black); inline_left += advW_s;//move } //restore p.SetOrigin(prevX, prevY); } //----------- CopyBitmapToScreen(); }
void Issue118(PaintEventArgs e) { Text = "Issue 118 Demo"; const string s = "0123456789"; const float z = 80; const bool f = true; var m = GetType().Assembly; var t = new OpenFontReader().Read (m.GetManifestResourceStream (Array.Find(m.GetManifestResourceNames(), n => n.EndsWith("otf")))); t.UpdateAllCffGlyphBounds(); var c = t.CalculateScaleToPixelFromPointSize(z); var l = new GlyphLayout { Typeface = t }; var q = new GlyphLayout { Typeface = t }; l.Layout(s.ToCharArray(), 0, s.Length); var p = l.ResultUnscaledGlyphPositions; var b = new B(t); var r = new SampleWinForms.GlyphTranslatorToGdiPath(); var h = Pens.Black.Brush; var u = Pens.Blue; var v = Pens.Red; const bool _ = true; var j = true; using (var g = e.Graphics) { if (f) { g.ScaleTransform(1, -1); g.TranslateTransform(0, -Height / 2); } for (var i = 0; i < s.Length; i++, j ^= true) { var o = q.LayoutAndMeasureString(new[] { s[i] }, 0, 1, z); var n = p.GetGlyph(i, out var x, out var y, out var w); var a = g.Save(); var d = t.GetGlyphByIndex(n).Bounds; var k = R.FromLTRB(d.XMin * c, d.YMin * c, d.XMax * c, d.YMax * c); g.TranslateTransform(x * c, y * c); b.Build(s[i], z); b.ReadShapes(r); r.ResultGraphicsPath.CloseFigure(); g.FillPath(h, r.ResultGraphicsPath); if (_ || j) { g.DrawRectangle(u, 0, 0, o.width, o.ascending - o.descending); } if (_ || !j) { g.DrawRectangle(v, k.X, k.Y, k.Width, k.Height); } g.Restore(a); g.TranslateTransform(w * c, 0); } g.ResetTransform(); g.DrawString("Blue = LayoutAndMeasureString, Red = Glyph.Bounds", Font, h, 0, 0); } }