public void Print(CanvasPainter painter, char[] buffer, double x, double y) { int j = buffer.Length; int buffsize = j * 2; //get kerning list ProperGlyph[] properGlyphs = new ProperGlyph[buffsize]; ActualFont implFont = actualFont; TextShapingService.GetGlyphPos(actualFont, buffer, 0, buffsize, properGlyphs); double xpos = x; for (int i = 0; i < buffsize; ++i) { uint codepoint = properGlyphs[i].codepoint; if (codepoint == 0) { break; } //------------------------------------------------------------- FontGlyph glyph = implFont.GetGlyphByIndex(codepoint); //var left = glyph.glyphMatrix.img_horiBearingX; //-------------------------------------------------------- //render with vector //var mat = Agg.Transform.Affine.NewMatix( //Agg.Transform.AffinePlan.Scale(0.30), //Agg.Transform.AffinePlan.Translate(xpos, y)); //var vxs1 = mat.TransformToVxs(glyph.flattenVxs); VertexStore vxs1 = Agg.Transform.Affine.TranslateToVxs( glyph.flattenVxs, (float)(xpos), (float)(y), vxsPool.GetFreeVxs()); painter.Fill(vxs1); vxsPool.Release(ref vxs1); //-------------------------------------------------------- ////render with bitmap //if (glyph.glyphImage32 != null) //{ // if (glyph.glyphImage32.Width > 0 && glyph.glyphImage32.Height > 0) // { // painter.DrawImage(glyph.glyphImage32, // (float)(xpos + (left >> 6)), // (float)(y + (glyph.exportGlyph.bboxYmin >> 6))); // } //} int w = (glyph.glyphMatrix.advanceX) >> 6; xpos += (w); //------------------------------------------------------------- } }
public static void GetGlyphPos(ActualFont actualFont, char[] buffer, int startAt, int len, ProperGlyph[] properGlyphs) { defaultSharpingService.GetGlyphPosImpl(actualFont, buffer, startAt, len, properGlyphs); }
protected abstract void GetGlyphPosImpl(ActualFont actualFont, char[] buffer, int startAt, int len, ProperGlyph[] properGlyphs);
public static unsafe extern int MyFtShaping(IntPtr my_hb_ft_font, char* text, int charCount, ProperGlyph* properGlyphs);
protected override void GetGlyphPosImpl(ActualFont actualFont, char[] buffer, int startAt, int len, ProperGlyph[] properGlyphs) { //do shaping and set text layout }
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 //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); }