public void DrawString(RenderVxFormattedString renderVx, double x, double y) { RenderVxGlyphPlan[] glyphPlans = renderVx.glyphList; int n = glyphPlans.Length; EnsureLoadGLBmp(); //PERF: //TODO: review here, can we cache the glbmp for later use //not to create it every time float scaleFromTexture = _finalTextureScale; Typography.Rendering.TextureKind textureKind = simpleFontAtlas.TextureKind; float g_x = 0; float g_y = 0; int baseY = (int)Math.Round(y); float scale = 1; for (int i = 0; i < n; ++i) { //PERF: //TODO: //render a set of glyph instead of one glyph per time *** RenderVxGlyphPlan 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); //-------------------------- GlyphPosPixelSnapKind x_snap = this.GlyphPosPixelSnapX; GlyphPosPixelSnapKind y_snap = this.GlyphPosPixelSnapY; 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; } //----------- //backup //switch (textureKind) //{ // case Typography.Rendering.TextureKind.Msdf: // { // canvas2d.DrawSubImageWithMsdf(_glBmp, // ref srcRect, // (float)(x + (glyph.x - glyphData.TextureXOffset) * scaleFromTexture), // -glyphData.TextureXOffset => restore to original pos // (float)(y + (glyph.y - glyphData.TextureYOffset + srcRect.Height) * scaleFromTexture),// -glyphData.TextureYOffset => restore to original pos // scaleFromTexture); // } // break; // case Typography.Rendering.TextureKind.AggGrayScale: // { // canvas2d.DrawSubImage(_glBmp, // ref srcRect, // (float)(x + (glyph.x - glyphData.TextureXOffset) * scaleFromTexture), // -glyphData.TextureXOffset => restore to original pos // (float)(y + (glyph.y - glyphData.TextureYOffset + srcRect.Height) * scaleFromTexture),// -glyphData.TextureYOffset => restore to original pos // scaleFromTexture); // } // break; // case Typography.Rendering.TextureKind.AggSubPixel: // canvas2d.DrawGlyphImageWithSubPixelRenderingTechnique(_glBmp, // ref srcRect, // (float)(x + (glyph.x - glyphData.TextureXOffset) * scaleFromTexture), // -glyphData.TextureXOffset => restore to original pos // (float)(y + (glyph.y - glyphData.TextureYOffset + srcRect.Height) * scaleFromTexture),// -glyphData.TextureYOffset => restore to original pos // scaleFromTexture); // break; //} } }
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; } } }