public void DrawString(char[] buffer, int startAt, int len, double left, double top) { _vboBuilder.Clear(); _vboBuilder.SetTextureInfo(_glBmp.Width, _glBmp.Height, _glBmp.IsYFlipped, _pcx.OriginKind); // _pcx.FontFillColor = _painter.FontFillColor; _pcx.LoadTexture(_glBmp); //create temp buffer span that describe the part of a whole char buffer TextBufferSpan textBufferSpan = new TextBufferSpan(buffer, startAt, len); //ask text service to parse user input char buffer and create a glyph-plan-sequence (list of glyph-plan) //with specific request font GlyphPlanSequence glyphPlanSeq = _textServices.CreateGlyphPlanSeq(ref textBufferSpan, _font); float px_scale = _px_scale; //-------------------------- //TODO: //if (x,y) is left top //we need to adjust y again float scaleFromTexture = 1; TextureKind textureKind = _fontAtlas.TextureKind; float g_left = 0; float g_top = 0; int baseLine = (int)Math.Round((float)top + _font.AscentInPixels); int bottom = (int)Math.Round((float)top + _font.AscentInPixels - _font.DescentInPixels); float acc_x = 0; //local accumulate x float acc_y = 0; //local accumulate y #if DEBUG if (s_dbugShowMarkers) { if (s_dbugShowGlyphTexture) { //show original glyph texture at top _pcx.DrawImage(_glBmp, 0, 0); } //draw red-line-marker for baseLine _painter.StrokeColor = Color.Red; _painter.DrawLine(left, baseLine, left + 200, baseLine); // //draw magenta-line-marker for bottom line _painter.StrokeColor = Color.Magenta; int bottomLine = (int)Math.Round((float)top + _font.LineSpacingInPixels); _painter.DrawLine(left, bottomLine, left + 200, bottomLine); //draw blue-line-marker for top line _painter.StrokeColor = Color.Blue; _painter.DrawLine(0, top, left + 200, top); } DrawingTechnique = s_dbugDrawTechnique; //for debug only UseVBO = s_dbugUseVBO; //for debug only #endif int seqLen = glyphPlanSeq.Count; for (int i = 0; i < seqLen; ++i) { UnscaledGlyphPlan glyph = glyphPlanSeq[i]; Typography.Rendering.TextureGlyphMapData glyphData; if (!_fontAtlas.TryGetGlyphMapData(glyph.glyphIndex, out glyphData)) { //if no glyph data, we should render a missing glyph *** continue; } //-------------------------------------- //TODO: review precise height in float //-------------------------------------- //paint src rect //temp fix, glyph texture img is not flipped //but the associate info is flipped => so //we need remap exact Y from the image Rectangle srcRect = new Rectangle(glyphData.Left, _glBmp.Height - (glyphData.Top + glyphData.Height), glyphData.Width, glyphData.Height); //offset length from 'base-line' float x_offset = acc_x + (float)Math.Round(glyph.OffsetX * px_scale - glyphData.TextureXOffset); float y_offset = acc_y + (float)Math.Round(glyph.OffsetY * px_scale - glyphData.TextureYOffset) + srcRect.Height; //*** //NOTE: // -glyphData.TextureXOffset => restore to original pos // -glyphData.TextureYOffset => restore to original pos //-------------------------- g_left = (float)(left + x_offset); g_top = (float)(bottom - y_offset); //*** acc_x += (float)Math.Round(glyph.AdvanceX * px_scale); //g_x = (float)Math.Round(g_x); //*** g_top = (float)Math.Floor(g_top);//adjust to integer num *** #if DEBUG if (s_dbugShowMarkers) { if (s_dbugShowGlyphTexture) { //draw yellow-rect-marker on original texture _painter.DrawRectangle(srcRect.X, srcRect.Y, srcRect.Width, srcRect.Height, Color.Yellow); } //draw debug-rect box at target glyph position _painter.DrawRectangle(g_left, g_top, srcRect.Width, srcRect.Height, Color.Black); _painter.StrokeColor = Color.Blue; //restore } #endif if (textureKind == TextureKind.Msdf) { _pcx.DrawSubImageWithMsdf(_glBmp, ref srcRect, g_left, g_top, scaleFromTexture); } else { switch (DrawingTechnique) { case GlyphTexturePrinterDrawingTechnique.Stencil: if (UseVBO) { _vboBuilder.WriteVboToList( ref srcRect, g_left, g_top); } else { //stencil gray scale with fill-color _pcx.DrawGlyphImageWithStecil(_glBmp, ref srcRect, g_left, g_top, scaleFromTexture); } break; case GlyphTexturePrinterDrawingTechnique.Copy: if (UseVBO) { _vboBuilder.WriteVboToList( ref srcRect, g_left, g_top); } else { _pcx.DrawSubImage(_glBmp, ref srcRect, g_left, g_top, 1); } break; case GlyphTexturePrinterDrawingTechnique.LcdSubPixelRendering: if (UseVBO) { _vboBuilder.WriteVboToList( ref srcRect, g_left, g_top); } else { _pcx.DrawGlyphImageWithSubPixelRenderingTechnique2_GlyphByGlyph( ref srcRect, g_left, g_top, 1); } break; } } } //------------------------------------------- // if (UseVBO) { switch (DrawingTechnique) { case GlyphTexturePrinterDrawingTechnique.Copy: _pcx.DrawGlyphImageWithCopy_VBO(_vboBuilder); break; case GlyphTexturePrinterDrawingTechnique.LcdSubPixelRendering: _pcx.DrawGlyphImageWithSubPixelRenderingTechnique3_DrawElements(_vboBuilder); break; case GlyphTexturePrinterDrawingTechnique.Stencil: _pcx.DrawGlyphImageWithStecil_VBO(_vboBuilder); break; } _vboBuilder.Clear(); } }
protected override void OnGLRender(object sender, EventArgs args) { _pcx.SmoothMode = SmoothMode.Smooth; _pcx.StrokeColor = PixelFarm.Drawing.Color.Blue; _pcx.Clear(PixelFarm.Drawing.Color.White); //set clear color and clear all buffer _pcx.ClearColorBuffer(); //test , clear only color buffer //------------------------------- if (!_isInit) { _glbmp = DemoHelper.LoadTexture(RootDemoPath.Path + @"\logo-dark.jpg"); _isInit = true; } PixelFarm.Drawing.RenderSurfaceOrientation prevOrgKind = _pcx.OriginKind; //save switch (DrawSet) { default: case T107_1_DrawImageSet.Full: { _pcx.OriginKind = PixelFarm.Drawing.RenderSurfaceOrientation.LeftTop; for (int i = 0; i < 400;) { _pcx.DrawImage(_glbmp, i, i); //left,top (NOT x,y) i += 50; } // _pcx.OriginKind = PixelFarm.Drawing.RenderSurfaceOrientation.LeftBottom; for (int i = 0; i < 400;) { _pcx.DrawImage(_glbmp, i, i); //left,top (NOT x,y) i += 50; } } break; case T107_1_DrawImageSet.Half: { _pcx.OriginKind = PixelFarm.Drawing.RenderSurfaceOrientation.LeftTop; for (int i = 0; i < 400;) { //left,top (NOT x,y) _pcx.DrawImage(_glbmp, i, i, _glbmp.Width / 2, _glbmp.Height / 2); i += 50; } // _pcx.OriginKind = PixelFarm.Drawing.RenderSurfaceOrientation.LeftBottom; for (int i = 0; i < 400;) { _pcx.DrawImage(_glbmp, i, i, _glbmp.Width / 2, _glbmp.Height / 2); //left,top (NOT x,y) i += 50; } } break; case T107_1_DrawImageSet.ToRect: { _pcx.OriginKind = PixelFarm.Drawing.RenderSurfaceOrientation.LeftTop; for (int i = 0; i < 400;) { //left,top (NOT x,y) //PixelFarm.Drawing.RectangleF srcRect = new PixelFarm.Drawing.RectangleF(i, i, _glbmp.Width, _glbmp.Height); _pcx.DrawImage(_glbmp, i, i, _glbmp.Width / 2, _glbmp.Height / 2); i += 50; } // _pcx.OriginKind = PixelFarm.Drawing.RenderSurfaceOrientation.LeftBottom; for (int i = 0; i < 400;) { //PixelFarm.Drawing.RectangleF srcRect = new PixelFarm.Drawing.RectangleF(i, i, _glbmp.Width, _glbmp.Height); _pcx.DrawImage(_glbmp, i, i, _glbmp.Width / 2, _glbmp.Height / 2); i += 50; } } break; case T107_1_DrawImageSet.ToQuad1: { _pcx.OriginKind = PixelFarm.Drawing.RenderSurfaceOrientation.LeftTop; for (int i = 0; i < 400;) { //left,top (NOT x,y) _pcx.DrawImageToQuad(_glbmp, new PixelFarm.Drawing.PointF(i, i), new PixelFarm.Drawing.PointF(i + _glbmp.Width / 2, i), new PixelFarm.Drawing.PointF(i + _glbmp.Width / 2, i + _glbmp.Height / 2), new PixelFarm.Drawing.PointF(i, i + _glbmp.Height / 2)); i += 50; } // _pcx.OriginKind = PixelFarm.Drawing.RenderSurfaceOrientation.LeftBottom; for (int i = 0; i < 400;) { _pcx.DrawImageToQuad(_glbmp, new PixelFarm.Drawing.PointF(i, i), new PixelFarm.Drawing.PointF(i + _glbmp.Width / 2, i), new PixelFarm.Drawing.PointF(i + _glbmp.Width / 2, i + _glbmp.Height / 2), new PixelFarm.Drawing.PointF(i, i + _glbmp.Height / 2)); i += 50; } } break; case T107_1_DrawImageSet.ToQuad2: { _pcx.OriginKind = PixelFarm.Drawing.RenderSurfaceOrientation.LeftTop; float rotateDegree = 20; for (int i = 0; i < 400;) { //left,top (NOT x,y) float[] quad = new float[] { 0, 0, //left-top _glbmp.Width, 0, //right-top _glbmp.Width, _glbmp.Height, //right-bottom 0, _glbmp.Height //left bottom }; PixelFarm.CpuBlit.VertexProcessing.Affine aff = PixelFarm.CpuBlit.VertexProcessing.Affine.NewMatix2( PixelFarm.CpuBlit.VertexProcessing.AffinePlan.Translate(-_glbmp.Width / 2, -_glbmp.Height / 2), PixelFarm.CpuBlit.VertexProcessing.AffinePlan.RotateDeg(rotateDegree), PixelFarm.CpuBlit.VertexProcessing.AffinePlan.Translate(i + _glbmp.Width / 2, i + _glbmp.Height / 2)); aff.Transform(ref quad[0], ref quad[1]); aff.Transform(ref quad[2], ref quad[3]); aff.Transform(ref quad[4], ref quad[5]); aff.Transform(ref quad[6], ref quad[7]); _pcx.DrawImageToQuad(_glbmp, new PixelFarm.Drawing.PointF(quad[0], quad[1]), new PixelFarm.Drawing.PointF(quad[2], quad[3]), new PixelFarm.Drawing.PointF(quad[4], quad[5]), new PixelFarm.Drawing.PointF(quad[6], quad[7])); i += 50; } // _pcx.OriginKind = PixelFarm.Drawing.RenderSurfaceOrientation.LeftBottom; for (int i = 0; i < 400;) { //left,top (NOT x,y) float[] quad = new float[] { 0, 0, //left-top _glbmp.Width, 0, //right-top _glbmp.Width, -_glbmp.Height, //right-bottom 0, -_glbmp.Height //left bottom }; PixelFarm.CpuBlit.VertexProcessing.Affine aff = PixelFarm.CpuBlit.VertexProcessing.Affine.NewMatix2( PixelFarm.CpuBlit.VertexProcessing.AffinePlan.Translate(-_glbmp.Width / 2, -_glbmp.Height / 2), PixelFarm.CpuBlit.VertexProcessing.AffinePlan.RotateDeg(rotateDegree), PixelFarm.CpuBlit.VertexProcessing.AffinePlan.Translate(i + _glbmp.Width / 2, i + _glbmp.Height / 2)); aff.Transform(ref quad[0], ref quad[1]); aff.Transform(ref quad[2], ref quad[3]); aff.Transform(ref quad[4], ref quad[5]); aff.Transform(ref quad[6], ref quad[7]); _pcx.DrawImageToQuad(_glbmp, new PixelFarm.Drawing.PointF(quad[0], quad[1]), new PixelFarm.Drawing.PointF(quad[2], quad[3]), new PixelFarm.Drawing.PointF(quad[4], quad[5]), new PixelFarm.Drawing.PointF(quad[6], quad[7])); i += 50; } } break; case T107_1_DrawImageSet.ToQuad3: { _pcx.OriginKind = PixelFarm.Drawing.RenderSurfaceOrientation.LeftTop; float rotateDegree = 60; for (int i = 0; i < 400;) { PixelFarm.CpuBlit.VertexProcessing.Affine aff = PixelFarm.CpuBlit.VertexProcessing.Affine.NewMatix2( PixelFarm.CpuBlit.VertexProcessing.AffinePlan.Translate(-_glbmp.Width / 2, -_glbmp.Height / 2), PixelFarm.CpuBlit.VertexProcessing.AffinePlan.RotateDeg(rotateDegree), PixelFarm.CpuBlit.VertexProcessing.AffinePlan.Translate(i + _glbmp.Width / 2, i + _glbmp.Height / 2)); _pcx.DrawImageToQuad(_glbmp, aff); i += 50; } // _pcx.OriginKind = PixelFarm.Drawing.RenderSurfaceOrientation.LeftBottom; for (int i = 0; i < 400;) { PixelFarm.CpuBlit.VertexProcessing.Affine aff = PixelFarm.CpuBlit.VertexProcessing.Affine.NewMatix2( PixelFarm.CpuBlit.VertexProcessing.AffinePlan.Translate(-_glbmp.Width / 2, -_glbmp.Height / 2), PixelFarm.CpuBlit.VertexProcessing.AffinePlan.RotateDeg(rotateDegree), PixelFarm.CpuBlit.VertexProcessing.AffinePlan.Translate(i + _glbmp.Width / 2, i + _glbmp.Height / 2)); _pcx.DrawImageToQuad(_glbmp, aff); i += 50; } } break; case T107_1_DrawImageSet.SubImages0: { _pcx.OriginKind = PixelFarm.Drawing.RenderSurfaceOrientation.LeftTop; for (int i = 0; i < 400;) { //left,top (NOT x,y) PixelFarm.Drawing.Rectangle srcRect = new PixelFarm.Drawing.Rectangle(0, 0, _glbmp.Width, _glbmp.Height); _pcx.DrawSubImage(_glbmp, ref srcRect, i, i); i += 50; } // _pcx.OriginKind = PixelFarm.Drawing.RenderSurfaceOrientation.LeftBottom; for (int i = 0; i < 400;) { PixelFarm.Drawing.Rectangle srcRect = new PixelFarm.Drawing.Rectangle(0, 0, _glbmp.Width, _glbmp.Height); _pcx.DrawSubImage(_glbmp, ref srcRect, i, i); i += 50; } } break; case T107_1_DrawImageSet.SubImages1: { _pcx.OriginKind = PixelFarm.Drawing.RenderSurfaceOrientation.LeftTop; for (int i = 0; i < 400;) { //left,top (NOT x,y) PixelFarm.Drawing.Rectangle srcRect = new PixelFarm.Drawing.Rectangle(0, 0, _glbmp.Width / 2, _glbmp.Height / 2); _pcx.DrawSubImage(_glbmp, ref srcRect, i, i); i += 50; } // _pcx.OriginKind = PixelFarm.Drawing.RenderSurfaceOrientation.LeftBottom; for (int i = 0; i < 400;) { PixelFarm.Drawing.Rectangle srcRect = new PixelFarm.Drawing.Rectangle(0, 0, _glbmp.Width / 2, _glbmp.Height / 2); _pcx.DrawSubImage(_glbmp, ref srcRect, i, i); i += 50; } } break; case T107_1_DrawImageSet.SubImages2: { _pcx.OriginKind = PixelFarm.Drawing.RenderSurfaceOrientation.LeftTop; for (int i = 0; i < 400;) { //left,top (NOT x,y) PixelFarm.Drawing.Rectangle srcRect = new PixelFarm.Drawing.Rectangle(20, 20, 50, 50); _pcx.DrawSubImage(_glbmp, ref srcRect, i, i); i += 50; } // _pcx.OriginKind = PixelFarm.Drawing.RenderSurfaceOrientation.LeftBottom; for (int i = 0; i < 400;) { PixelFarm.Drawing.Rectangle srcRect = new PixelFarm.Drawing.Rectangle(20, 20, 50, 50); _pcx.DrawSubImage(_glbmp, ref srcRect, i, i); i += 50; } } break; case T107_1_DrawImageSet.SubImagesWithScale: { _pcx.OriginKind = PixelFarm.Drawing.RenderSurfaceOrientation.LeftTop; for (int i = 0; i < 400;) { //left,top (NOT x,y) PixelFarm.Drawing.Rectangle srcRect = new PixelFarm.Drawing.Rectangle(20, 20, 50, 50); _pcx.DrawSubImage(_glbmp, ref srcRect, i, i, 2f); i += 50; } // _pcx.OriginKind = PixelFarm.Drawing.RenderSurfaceOrientation.LeftBottom; for (int i = 0; i < 400;) { PixelFarm.Drawing.Rectangle srcRect = new PixelFarm.Drawing.Rectangle(20, 20, 50, 50); _pcx.DrawSubImage(_glbmp, ref srcRect, i, i, 2f); i += 50; } } break; case T107_1_DrawImageSet.SubImageWithBlurX: { _pcx.OriginKind = PixelFarm.Drawing.RenderSurfaceOrientation.LeftTop; for (int i = 0; i < 400;) { //left,top (NOT x,y) _pcx.DrawImageWithBlurX(_glbmp, i, i); i += 50; } // _pcx.OriginKind = PixelFarm.Drawing.RenderSurfaceOrientation.LeftBottom; for (int i = 0; i < 400;) { _pcx.DrawImageWithBlurX(_glbmp, i, i); i += 50; } } break; case T107_1_DrawImageSet.SubImageWithBlurY: { _pcx.OriginKind = PixelFarm.Drawing.RenderSurfaceOrientation.LeftTop; for (int i = 0; i < 400;) { //left,top (NOT x,y) _pcx.DrawImageWithBlurY(_glbmp, i, i); i += 50; } // _pcx.OriginKind = PixelFarm.Drawing.RenderSurfaceOrientation.LeftBottom; for (int i = 0; i < 400;) { _pcx.DrawImageWithBlurY(_glbmp, i, i); i += 50; } // } break; case T107_1_DrawImageSet.DrawWithConv3x3: { _pcx.OriginKind = PixelFarm.Drawing.RenderSurfaceOrientation.LeftTop; for (int i = 0; i < 400;) { //left,top (NOT x,y) _pcx.DrawImageWithConv3x3(_glbmp, Mat3x3ConvGen.sobelHorizontal, i, i); i += 50; } // _pcx.OriginKind = PixelFarm.Drawing.RenderSurfaceOrientation.LeftBottom; for (int i = 0; i < 400;) { _pcx.DrawImageWithConv3x3(_glbmp, Mat3x3ConvGen.emboss, i, i); i += 50; } } break; } _pcx.OriginKind = prevOrgKind;//restore }