public override void Draw(Painter p) { AggPainter painter = p as AggPainter; if (painter == null) { return; } painter.Clear(Color.White); int width = painter.Width; int height = painter.Height; //switch to alpha mask painter.TargetBufferName = TargetBufferName.AlphaMask; //draw white rect on the mask painter.FillColor = Color.White; painter.FillRect(20, 20, 50, 50); painter.FillRect(20, 5, 20, 10); //------------------------------------ //switch back to default color painter.TargetBufferName = TargetBufferName.Default; painter.FillColor = Color.Red; //enable mask composite painter.EnableBuiltInMaskComposite = true; painter.FillRect(0, 0, 100, 100); //disable mask buffer painter.EnableBuiltInMaskComposite = false; painter.FillColor = Color.Yellow; painter.FillRect(0, 0, 20, 20); //if (!_maskReady) //{ // SetupMaskPixelBlender(width, height); // _maskReady = true; //} //// ////painter.DestBitmapBlender.OutputPixelBlender = maskPixelBlender; //change to new blender //painter.DestBitmapBlender.OutputPixelBlender = maskPixelBlenderPerCompo; //change to new blender ////4. //painter.FillColor = Color.Black; ////this test lcd-effect => we need to draw it 3 times with different color component, on the same position ////(same as we do with OpenGLES rendering surface) //maskPixelBlenderPerCompo.SelectedMaskComponent = PixelBlenderColorComponent.B; //maskPixelBlenderPerCompo.EnableOutputColorComponent = EnableOutputColorComponent.B; //painter.FillRect(0, 0, 200, 100); //// //maskPixelBlenderPerCompo.SelectedMaskComponent = PixelBlenderColorComponent.G; //maskPixelBlenderPerCompo.EnableOutputColorComponent = EnableOutputColorComponent.G; //painter.FillRect(0, 0, 200, 100); //// //maskPixelBlenderPerCompo.SelectedMaskComponent = PixelBlenderColorComponent.R; //maskPixelBlenderPerCompo.EnableOutputColorComponent = EnableOutputColorComponent.R; //painter.FillRect(0, 0, 200, 100); }
public override void Draw(Painter p) { AggPainter painter = p as AggPainter; if (painter == null) { return; } // painter.Clear(Color.White); int width = painter.Width; int height = painter.Height; //change value *** if (!_maskReady) { SetupMaskPixelBlender(width, height); _maskReady = true; } // //painter.DestBitmapBlender.OutputPixelBlender = maskPixelBlender; //change to new blender painter.DestBitmapBlender.OutputPixelBlender = _maskPixelBlenderPerCompo; //change to new blender //4. painter.FillColor = Color.Black; //this test lcd-effect => we need to draw it 3 times with different color component, on the same position //(same as we do with OpenGLES rendering surface) _maskPixelBlenderPerCompo.SelectedMaskComponent = PixelBlenderColorComponent.B; _maskPixelBlenderPerCompo.EnableOutputColorComponent = EnableOutputColorComponent.B; painter.FillRect(0, 0, 200, 100); // _maskPixelBlenderPerCompo.SelectedMaskComponent = PixelBlenderColorComponent.G; _maskPixelBlenderPerCompo.EnableOutputColorComponent = EnableOutputColorComponent.G; painter.FillRect(0, 0, 200, 100); // _maskPixelBlenderPerCompo.SelectedMaskComponent = PixelBlenderColorComponent.R; _maskPixelBlenderPerCompo.EnableOutputColorComponent = EnableOutputColorComponent.R; painter.FillRect(0, 0, 200, 100); }
public override void Draw(Painter p) { AggPainter painter = p as AggPainter; if (painter == null) { return; } // painter.Clear(Color.White); int width = painter.Width; int height = painter.Height; //change value *** if (_isMaskSliderValueChanged) { SetupMaskPixelBlender(width, height); _isMaskSliderValueChanged = false; // //painter.DestBitmapBlender.OutputPixelBlender = maskPixelBlender; //change to new blender painter.DestBitmapBlender.OutputPixelBlender = maskPixelBlenderPerCompo; //change to new blender } //1. alpha mask... //p2.DrawImage(alphaBitmap, 0, 0); //2. painter.FillColor = Color.Black; painter.FillRect(0, 0, 200, 100); //3. painter.FillColor = Color.Blue; painter.FillCircle(300, 300, 100); painter.DrawImage(lionImg, 20, 20); ////4. //painter.FillColor = Color.Black; ////this test lcd-effect => we need to draw it 3 times with different color component, on the same position ////(same as we do with OpenGLES rendering surface) //maskPixelBlenderPerCompo.SelectedMaskComponent = PixelBlenderColorComponent.B; //maskPixelBlenderPerCompo.EnableOutputColorComponent = EnableOutputColorComponent.B; //painter.FillRect(0, 0, 200, 100); //maskPixelBlenderPerCompo.SelectedMaskComponent = PixelBlenderColorComponent.G; //maskPixelBlenderPerCompo.EnableOutputColorComponent = EnableOutputColorComponent.G; //painter.FillRect(0, 0, 200, 100); //maskPixelBlenderPerCompo.SelectedMaskComponent = PixelBlenderColorComponent.R; //maskPixelBlenderPerCompo.EnableOutputColorComponent = EnableOutputColorComponent.R; //painter.FillRect(0, 0, 200, 100); }
void RenderGrids(int width, int height, int sqSize, AggPainter p) { //render grid p.FillColor = PixelFarm.Drawing.Color.Gray; float pointW = (sqSize >= 100) ? 2 : 1; for (int y = 0; y < height;) { for (int x = 0; x < width;) { p.FillRect(x, y, pointW, pointW); x += sqSize; } y += sqSize; } }
void DrawStringToMemBitmap(RequestFont reqFont, string textOutput, float x_pos, float y_pos, int repeatLines = 1) { ResolvedFont resolvedFont = _textService.ResolveFont(reqFont); if (resolvedFont == null) { //we dont' have resolvedFont = _textService.ResolveFont(_defaultReqFont); if (resolvedFont == null) { throw new NotSupportedException(); } //use alternative typeface, but use reqFont's Size resolvedFont = new ResolvedFont(resolvedFont.Typeface, reqFont.SizeInPoints); } //check if reqFont has alternative or not _myAlternativeTypefaceSelector.SetCurrentReqFont(reqFont, _textService); PixelFarm.Drawing.VxsTextSpanPrinter _selectedTextPrinter = _devVxsTextPrinter; _painter.UseLcdEffectSubPixelRendering = true; _painter.FillColor = PixelFarm.Drawing.Color.Black; _selectedTextPrinter = _devVxsTextPrinter; _selectedTextPrinter.FontSizeInPoints = resolvedFont.SizeInPoints; _selectedTextPrinter.Typeface = resolvedFont.Typeface; _selectedTextPrinter.ScriptLang = new ScriptLang(ScriptTagDefs.Latin.Tag); _selectedTextPrinter.PositionTechnique = PositionTechnique.OpenFont; _selectedTextPrinter.HintTechnique = HintTechnique.None; _selectedTextPrinter.EnableLigature = true; _selectedTextPrinter.SimulateSlant = false; _selectedTextPrinter.EnableMultiTypefaces = true; //*** for auto typeface selection*** //_selectedTextPrinter.TextBaseline = PixelFarm.Drawing.TextBaseline.Alphabetic; //_selectedTextPrinter.TextBaseline = PixelFarm.Drawing.TextBaseline.Bottom; _selectedTextPrinter.TextBaseline = (Typography.Text.TextBaseline)PixelFarm.Drawing.TextBaseline.Top; //test print 3 lines //#if DEBUG // DynamicOutline.dbugTestNewGridFitting = _contourAnalysisOpts.EnableGridFit; // DynamicOutline.dbugActualPosToConsole = _contourAnalysisOpts.WriteFitOutputToConsole; // DynamicOutline.dbugUseHorizontalFitValue = _contourAnalysisOpts.UseHorizontalFitAlignment; //#endif char[] printTextBuffer = textOutput.ToCharArray(); float lineSpacingPx = _selectedTextPrinter.FontLineSpacingPx; const int REF_LINE_LEN = 300; for (int i = 0; i < repeatLines; ++i) { _selectedTextPrinter.DrawString(printTextBuffer, x_pos, y_pos); #if DEBUG //show debug info... var prevColor = _painter.FillColor; var prevStrokColor = _painter.StrokeColor; _painter.FillColor = PixelFarm.Drawing.Color.Red; _painter.FillRect(x_pos, y_pos, 5, 5); // start point //see //https://developer.mozilla.org/en-US/docs/Web/API/CanvasRenderingContext2D/textBaseline switch (_selectedTextPrinter.TextBaseline) { default: { System.Diagnostics.Debug.WriteLine("UNIMPLEMENTED" + _selectedTextPrinter.TextBaseline.ToString()); goto case Typography.Text.TextBaseline.Alphabetic; // } case Typography.Text.TextBaseline.Alphabetic: { //alphabetic baseline _painter.StrokeColor = _grayColor; _painter.DrawLine(x_pos, /**/ y_pos, x_pos + REF_LINE_LEN, y_pos); _painter.StrokeColor = PixelFarm.Drawing.Color.Blue; _painter.DrawLine(x_pos, /**/ y_pos - _selectedTextPrinter.FontDescedingPx, x_pos + REF_LINE_LEN, y_pos - _selectedTextPrinter.FontDescedingPx); //bottom most } break; case Typography.Text.TextBaseline.Top: { //alphabetic baseline _painter.StrokeColor = _grayColor; _painter.DrawLine(x_pos, /**/ y_pos + _selectedTextPrinter.FontAscendingPx, x_pos + REF_LINE_LEN, y_pos + _selectedTextPrinter.FontAscendingPx); //em bottom _painter.StrokeColor = PixelFarm.Drawing.Color.Blue; _painter.DrawLine(x_pos, /**/ y_pos + (_selectedTextPrinter.FontAscendingPx - _selectedTextPrinter.FontDescedingPx), x_pos + REF_LINE_LEN, y_pos + (_selectedTextPrinter.FontAscendingPx - _selectedTextPrinter.FontDescedingPx)); //bottom most } break; case Typography.Text.TextBaseline.Bottom: { //alphabetic baseline _painter.StrokeColor = _grayColor; _painter.DrawLine(x_pos, /**/ y_pos + _selectedTextPrinter.FontDescedingPx, x_pos + REF_LINE_LEN, y_pos + _selectedTextPrinter.FontDescedingPx); //em bottom _painter.StrokeColor = PixelFarm.Drawing.Color.Blue; _painter.DrawLine(x_pos, /**/ y_pos, x_pos + REF_LINE_LEN, y_pos); //bottom most } break; } _painter.FillColor = prevColor; _painter.StrokeColor = prevColor; #endif y_pos += (_selectedTextPrinter.FontAscendingPx - _selectedTextPrinter.FontDescedingPx); } //reset _myAlternativeTypefaceSelector.SetCurrentReqFont(null, null); }
public void DrawString(Painter p, char[] buffer, int startAt, int len, double x, double y) { AggPainter painter = p as AggPainter; if (painter == null) { return; } // int width = painter.Width; int height = painter.Height; if (!_pixelBlenderSetup) { SetupMaskPixelBlender(width, height); _pixelBlenderSetup = true; } int j = buffer.Length; //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 scale = 1;// _fontAtlas.TargetTextureScale; int recommendLineSpacing = (int)_font.LineSpacingInPixels; //-------------------------- //TODO: //if (x,y) is left top //we need to adjust y again y -= _font.LineSpacingInPixels; // float scaleFromTexture = _finalTextureScale; TextureKind textureKind = _fontAtlas.TextureKind; float gx = 0; float gy = 0; int baseY = (int)Math.Round(y); float acc_x = 0; float acc_y = 0; int lineHeight = (int)_font.LineSpacingInPixels;//temp //painter.DestBitmapBlender.OutputPixelBlender = maskPixelBlenderPerCompo; //change to new blender painter.DestBitmapBlender.OutputPixelBlender = _maskPixelBlenderPerCompo; //change to new blender int seqLen = glyphPlanSeq.Count; for (int i = 0; i < seqLen; ++i) { UnscaledGlyphPlan glyph = glyphPlanSeq[i]; 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 //-------------------------------------- int srcX, srcY, srcW, srcH; glyphData.GetRect(out srcX, out srcY, out srcW, out srcH); float ngx = acc_x + (float)Math.Round(glyph.OffsetX * scale); float ngy = acc_y + (float)Math.Round(glyph.OffsetY * scale); //NOTE: // -glyphData.TextureXOffset => restore to original pos // -glyphData.TextureYOffset => restore to original pos //-------------------------- gx = (float)(x + (ngx - glyphData.TextureXOffset) * scaleFromTexture); //ideal x gy = (float)(y + (ngy - glyphData.TextureYOffset - srcH + lineHeight) * scaleFromTexture); acc_x += (float)Math.Round(glyph.AdvanceX * scale); gy = (float)Math.Floor(gy) + lineHeight; //clear with solid black color //_maskBufferPainter.Clear(Color.Black); _maskBufferPainter.FillRect(gx - 1, gy - 1, srcW + 2, srcH + 2, Color.Black); //draw 'stencil' glyph on mask-buffer _maskBufferPainter.DrawImage(_fontBmp, gx, gy, srcX, _fontBmp.Height - (srcY), srcW, srcH); //select component to render this need to render 3 times for lcd technique //1. B _maskPixelBlenderPerCompo.SelectedMaskComponent = PixelBlenderColorComponent.B; _maskPixelBlenderPerCompo.EnableOutputColorComponent = EnableOutputColorComponent.B; painter.FillRect(gx + 1, gy, srcW, srcH); //2. G _maskPixelBlenderPerCompo.SelectedMaskComponent = PixelBlenderColorComponent.G; _maskPixelBlenderPerCompo.EnableOutputColorComponent = EnableOutputColorComponent.G; painter.FillRect(gx + 1, gy, srcW, srcH); //3. R _maskPixelBlenderPerCompo.SelectedMaskComponent = PixelBlenderColorComponent.R; _maskPixelBlenderPerCompo.EnableOutputColorComponent = EnableOutputColorComponent.R; painter.FillRect(gx + 1, gy, srcW, srcH); } }
void UpdateRenderOutput() { if (!_readyToRender) { return; } // if (_g == null) { InitGraphics(); } if (string.IsNullOrEmpty(this.txtInputChar.Text)) { return; } //test option use be used with lcd subpixel rendering. //this demonstrate how we shift a pixel for subpixel rendering tech if (_contourAnalysisOpts.SetupPrinterLayoutForLcdSubPix) { //TODO: set lcd or not here } else { //TODO: set lcd or not here } //1. read typeface from font file TypographyTest.RenderChoice renderChoice = _basicOptions.RenderChoice; switch (renderChoice) { case TypographyTest.RenderChoice.RenderWithGdiPlusPath: //not render in this example //see more at ... break; case TypographyTest.RenderChoice.RenderWithTextPrinterAndMiniAgg: { //clear previous draw _painter.Clear(PixelFarm.Drawing.Color.White); _painter.UseLcdEffectSubPixelRendering = _contourAnalysisOpts.LcdTechnique; _painter.FillColor = PixelFarm.Drawing.Color.Black; _selectedTextPrinter = _devVxsTextPrinter; _selectedTextPrinter.Typeface = _basicOptions.Typeface; _selectedTextPrinter.FontSizeInPoints = _basicOptions.FontSizeInPoints; _selectedTextPrinter.ScriptLang = _basicOptions.ScriptLang; _selectedTextPrinter.PositionTechnique = _basicOptions.PositionTech; if (_selectedTextPrinter is PixelFarm.Drawing.VxsTextSpanPrinter vxsTextPrinter) { vxsTextPrinter.HintTechnique = _glyphRenderOptions.HintTechnique; } _selectedTextPrinter.EnableLigature = _glyphRenderOptions.EnableLigature; _selectedTextPrinter.EnableMultiTypefaces = _basicOptions.EnableMultiTypefaces; _selectedTextPrinter.SimulateSlant = _contourAnalysisOpts.SimulateSlant; _selectedTextPrinter.TextBaseline = (Typography.Text.TextBaseline)(int) lstTextBaseline.SelectedItem; //test print 3 lines #if DEBUG DynamicOutline.dbugTestNewGridFitting = _contourAnalysisOpts.EnableGridFit; DynamicOutline.dbugActualPosToConsole = _contourAnalysisOpts.WriteFitOutputToConsole; DynamicOutline.dbugUseHorizontalFitValue = _contourAnalysisOpts.UseHorizontalFitAlignment; #endif char[] printTextBuffer = this.txtInputChar.Text.ToCharArray(); float x_pos = 0, y_pos = 0; float lineSpacingPx = _selectedTextPrinter.FontLineSpacingPx; const int REF_LINE_LEN = 300; for (int i = 0; i < 3; ++i) { _selectedTextPrinter.DrawString(printTextBuffer, x_pos, y_pos); #if DEBUG //show debug info... var prevColor = _painter.FillColor; var prevStrokColor = _painter.StrokeColor; _painter.FillColor = PixelFarm.Drawing.Color.Red; _painter.FillRect(x_pos, y_pos, 5, 5); // start point //see //https://developer.mozilla.org/en-US/docs/Web/API/CanvasRenderingContext2D/textBaseline switch (_selectedTextPrinter.TextBaseline) { default: { System.Diagnostics.Debug.WriteLine("UNIMPLEMENTED" + _selectedTextPrinter.TextBaseline.ToString()); goto case Typography.Text.TextBaseline.Alphabetic; // } case Typography.Text.TextBaseline.Alphabetic: { //alphabetic baseline _painter.StrokeColor = _grayColor; _painter.DrawLine(x_pos, /**/ y_pos, x_pos + REF_LINE_LEN, y_pos); _painter.StrokeColor = PixelFarm.Drawing.Color.Blue; _painter.DrawLine(x_pos, /**/ y_pos - _selectedTextPrinter.FontDescedingPx, x_pos + REF_LINE_LEN, y_pos - _selectedTextPrinter.FontDescedingPx); //bottom most } break; case Typography.Text.TextBaseline.Top: { //alphabetic baseline _painter.StrokeColor = _grayColor; _painter.DrawLine(x_pos, /**/ y_pos + _selectedTextPrinter.FontAscendingPx, x_pos + REF_LINE_LEN, y_pos + _selectedTextPrinter.FontAscendingPx); //em bottom _painter.StrokeColor = PixelFarm.Drawing.Color.Blue; _painter.DrawLine(x_pos, /**/ y_pos + (_selectedTextPrinter.FontAscendingPx - _selectedTextPrinter.FontDescedingPx), x_pos + REF_LINE_LEN, y_pos + (_selectedTextPrinter.FontAscendingPx - _selectedTextPrinter.FontDescedingPx)); //bottom most } break; case Typography.Text.TextBaseline.Bottom: { //alphabetic baseline _painter.StrokeColor = _grayColor; _painter.DrawLine(x_pos, /**/ y_pos + _selectedTextPrinter.FontDescedingPx, x_pos + REF_LINE_LEN, y_pos + _selectedTextPrinter.FontDescedingPx); //em bottom _painter.StrokeColor = PixelFarm.Drawing.Color.Blue; _painter.DrawLine(x_pos, /**/ y_pos, x_pos + REF_LINE_LEN, y_pos); //bottom most } break; } _painter.FillColor = prevColor; _painter.StrokeColor = prevColor; #endif y_pos += (_selectedTextPrinter.FontAscendingPx - _selectedTextPrinter.FontDescedingPx); } //copy from Agg's memory buffer to gdi PixelFarm.CpuBlit.BitmapHelper.CopyToGdiPlusBitmapSameSizeNotFlip(_destImg, _winBmp); _g.Clear(Color.White); _g.DrawImage(_winBmp, new Point(0, 0)); } break; //============================================== //render 1 glyph for debug and test case TypographyTest.RenderChoice.RenderWithMsdfGen: case TypographyTest.RenderChoice.RenderWithSdfGen: { char testChar = this.txtInputChar.Text[0]; Typeface typeFace = _basicOptions.Typeface; RenderWithMsdfImg(typeFace, testChar, _basicOptions.FontSizeInPoints); } break; case TypographyTest.RenderChoice.RenderWithMiniAgg_SingleGlyph: { _selectedTextPrinter = _devVxsTextPrinter; //for test only 1 char RenderSingleCharWithMiniAgg( _basicOptions.Typeface, this.txtInputChar.Text[0], _basicOptions.FontSizeInPoints); } break; default: throw new NotSupportedException(); } }
public override void DrawFromGlyphPlans(GlyphPlanSequence glyphPlanSeq, int startAt, int len, float left, float top) { Typeface typeface = _textServices.ResolveTypeface(_font); float scale = typeface.CalculateScaleToPixelFromPointSize(_font.SizeInPoints); int recommendLineSpacing = (int)_font.LineSpacingInPixels; //-------------------------- //TODO: //if (x,y) is left top //we need to adjust y again // TextureKind textureKind = _fontAtlas.TextureKind; float gx = 0; float gy = 0; int baseY = (int)Math.Round(top); float acc_x = 0; float acc_y = 0; int lineHeight = (int)_font.LineSpacingInPixels; //temp PixelBlender32 prevPxBlender = _painter.DestBitmapBlender.OutputPixelBlender; //save _painter.DestBitmapBlender.OutputPixelBlender = _maskPixelBlenderPerCompo; //change to new blender bool fillGlyphByGlyph = true; if (fillGlyphByGlyph) { //test... //fill glyph-by-glyh var aaTech = this.AntialiasTech; int seqLen = glyphPlanSeq.Count; for (int i = 0; i < seqLen; ++i) { UnscaledGlyphPlan unscaledGlyphPlan = glyphPlanSeq[i]; TextureGlyphMapData glyphData; if (!_fontAtlas.TryGetGlyphMapData(unscaledGlyphPlan.glyphIndex, out glyphData)) { //if no glyph data, we should render a missing glyph *** continue; } //-------------------------------------- //TODO: review precise height in float //-------------------------------------- int srcX, srcY, srcW, srcH; glyphData.GetRect(out srcX, out srcY, out srcW, out srcH); float ngx = acc_x + (float)Math.Round(unscaledGlyphPlan.OffsetX * scale); float ngy = acc_y + (float)Math.Round(unscaledGlyphPlan.OffsetY * scale); //NOTE: // -glyphData.TextureXOffset => restore to original pos // -glyphData.TextureYOffset => restore to original pos //-------------------------- //if (glyphData.TextureXOffset != 0) //{ //} gx = (float)(left + (ngx - glyphData.TextureXOffset)); //ideal x gy = (float)(top + (ngy + glyphData.TextureYOffset - srcH + lineHeight)); acc_x += (float)Math.Round(unscaledGlyphPlan.AdvanceX * scale); gy = (float)Math.Floor(gy);// + lineHeight; //clear with solid black color //_maskBufferPainter.Clear(Color.Black); //clear mask buffer at specific pos _maskBufferPainter.FillRect(gx - 1, gy - 1, srcW + 2, srcH + 2, Color.Black); //draw 'stencil' glyph on mask-buffer _maskBufferPainter.DrawImage(_fontBmp, gx, gy, srcX, _fontBmp.Height - (srcY + srcH), srcW, srcH); switch (aaTech) { default: { //select component to render this need to render 3 times for lcd technique //1. B _maskPixelBlenderPerCompo.SelectedMaskComponent = PixelBlenderColorComponent.B; _maskPixelBlenderPerCompo.EnableOutputColorComponent = EnableOutputColorComponent.B; _painter.FillRect(gx + 1, gy, srcW, srcH); //2. G _maskPixelBlenderPerCompo.SelectedMaskComponent = PixelBlenderColorComponent.G; _maskPixelBlenderPerCompo.EnableOutputColorComponent = EnableOutputColorComponent.G; _painter.FillRect(gx + 1, gy, srcW, srcH); //3. R _maskPixelBlenderPerCompo.SelectedMaskComponent = PixelBlenderColorComponent.R; _maskPixelBlenderPerCompo.EnableOutputColorComponent = EnableOutputColorComponent.R; _painter.FillRect(gx + 1, gy, srcW, srcH); } break; case AntialiasTechnique.GreyscaleStencil: { //fill once //we choose greeh channel (middle) _maskPixelBlenderPerCompo.SelectedMaskComponent = PixelBlenderColorComponent.G; _maskPixelBlenderPerCompo.EnableOutputColorComponent = EnableOutputColorComponent.EnableAll; _painter.FillRect(gx + 1, gy, srcW, srcH); } break; } } } else { //clear entire line _maskBufferPainter.FillRect(gx - 1, gy - 1, _maskBufferPainter.Width - gx + 2, lineHeight + 2, Color.Black); bool isFirst = true; int startX = 0, startY = 0; float lenW = 0; float lenH = 0; int seqLen = glyphPlanSeq.Count; for (int i = 0; i < seqLen; ++i) { UnscaledGlyphPlan glyph = glyphPlanSeq[i]; 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 //-------------------------------------- int srcX, srcY, srcW, srcH; glyphData.GetRect(out srcX, out srcY, out srcW, out srcH); float ngx = acc_x + (float)Math.Round(glyph.OffsetX * scale); float ngy = acc_y + (float)Math.Round(glyph.OffsetY * scale); //NOTE: // -glyphData.TextureXOffset => restore to original pos // -glyphData.TextureYOffset => restore to original pos //-------------------------- gx = (float)(left + (ngx - glyphData.TextureXOffset)); //ideal x gy = (float)(top + (ngy - glyphData.TextureYOffset - srcH + lineHeight)); acc_x += (float)Math.Round(glyph.AdvanceX * scale); gy = (float)Math.Floor(gy) + lineHeight; if (isFirst) { startX = (int)gx; startY = (int)gy; isFirst = false; } _maskBufferPainter.DrawImage(_fontBmp, gx + 1, gy, srcX, _fontBmp.Height - (srcY), srcW + 1, srcH); lenW = gx + srcW; if (srcH > lenH) { lenH = srcH; } } //-------------------------- //fill color on 'stencil' mask { //select component to render this need to render 3 times for lcd technique //1. B _maskPixelBlenderPerCompo.SelectedMaskComponent = PixelBlenderColorComponent.B; _maskPixelBlenderPerCompo.EnableOutputColorComponent = EnableOutputColorComponent.B; _painter.FillRect(startX + 1, startY, lenW, lenH); //2. G _maskPixelBlenderPerCompo.SelectedMaskComponent = PixelBlenderColorComponent.G; _maskPixelBlenderPerCompo.EnableOutputColorComponent = EnableOutputColorComponent.G; _painter.FillRect(startX + 1, startY, lenW, lenH); //3. R _maskPixelBlenderPerCompo.SelectedMaskComponent = PixelBlenderColorComponent.R; _maskPixelBlenderPerCompo.EnableOutputColorComponent = EnableOutputColorComponent.R; _painter.FillRect(startX + 1, startY, lenW, lenH); } } // _painter.DestBitmapBlender.OutputPixelBlender = prevPxBlender;//restore back }