public void SetCustomPixelBlender(PixelBlender32 customPixelBlender)
 {
     _destBitmapBlender.OutputPixelBlender = (customPixelBlender != null) ? customPixelBlender : _pixelBlenderBGRA;
 }
        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
        }