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 }