public void DrawString(char[] text, int startAt, int len, double x, double y) { if (this.UseSubPixelRendering) { //1. clear prev drawing result _aggPainter.Clear(Drawing.Color.FromArgb(0, 0, 0, 0)); //aggPainter.Clear(Drawing.Color.White); //aggPainter.Clear(Drawing.Color.FromArgb(0, 0, 0, 0)); //2. print text span into Agg Canvas textPrinter.DrawString(text, startAt, len, 0, 0); //3.copy to gl bitmap byte[] buffer = PixelFarm.Agg.ActualImage.GetBuffer(actualImage); //------------------------------------------------------ GLBitmap glBmp = new GLBitmap(bmpWidth, bmpHeight, buffer, true); glBmp.IsInvert = false; //TODO: review font height canvas.DrawGlyphImageWithSubPixelRenderingTechnique(glBmp, (float)x, (float)y + 40); glBmp.Dispose(); } else { //1. clear prev drawing result _aggPainter.Clear(Drawing.Color.FromArgb(0, 0, 0, 0)); //2. print text span into Agg Canvas textPrinter.DrawString(text, startAt, len, 0, 0); //3.copy to gl bitmap byte[] buffer = PixelFarm.Agg.ActualImage.GetBuffer(actualImage); //------------------------------------------------------ GLBitmap glBmp = new GLBitmap(bmpWidth, bmpHeight, buffer, true); glBmp.IsInvert = false; //TODO: review font height canvas.DrawGlyphImage(glBmp, (float)x, (float)y + 40); glBmp.Dispose(); } }
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; } } }