public override void UpdateRunWidth() { //*** var textBufferSpan = new Typography.Text.TextBufferSpan(_mybuffer); //TODO: review here, //1. if mybuffer lenght is not changed,we don't need to alloc new array? _outputUserCharAdvances = new int[_mybuffer.Length]; if (_renderVxFormattedString != null) { _renderVxFormattedString.Dispose(); _renderVxFormattedString = null; } var measureResult = new TextSpanMeasureResult(); measureResult.outputXAdvances = _outputUserCharAdvances; if (_content_unparsed) { //parse the content first if (_lineSegs == null) { _lineSegs = new TextPrinterLineSegmentList <TextPrinterLineSegment>(); } _lineSegs.Clear(); // if (s_wordVistor == null) { s_wordVistor = new TextPrinterWordVisitor(); } s_wordVistor.SetLineSegmentList(_lineSegs); RunStyle.BreakToLineSegments(textBufferSpan, s_wordVistor); s_wordVistor.SetLineSegmentList(null); //BreakToLineSegs(textBufferSpan); } _content_unparsed = false; RunStyle.CalculateUserCharGlyphAdvancePos(textBufferSpan, _lineSegs, ref measureResult); SetSize(measureResult.outputTotalW, measureResult.lineHeight); InvalidateGraphics(); }
public void DrawString(Painter p, char[] buffer, int startAt, int len, double x, double y) { //if (_stencilBmp == null) //{ // //create a stencil bmp // _stencilBmp = new ActualBitmap(p.Width, p.Height); // _stencilBlender = new PixelProcessing.SubBitmapBlender(_stencilBmp, new PixelProcessing.PixelBlenderBGRA()); // _backPainter = AggPainter.Create(_stencilBmp); // //------ //} int j = buffer.Length; //create temp buffer span that describe the part of a whole char buffer var textBufferSpan = new Typography.Text.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 = _txtClient.CreateGlyphPlanSeq(textBufferSpan, _font); ResolvedFont resolvedFont = _textServices.ResolveFont(_font); Typeface typeface = resolvedFont.Typeface; float scale = typeface.CalculateScaleToPixelFromPointSize(_font.SizeInPoints); int recommendLineSpacing = resolvedFont.LineSpacingInPixels; //-------------------------- //TODO: //if (x,y) is left top //we need to adjust y again y -= resolvedFont.LineSpacingInPixels; // float scaleFromTexture = _finalTextureScale; TextureKind textureKind = _fontAtlas.TextureKind; float g_x = 0; float g_y = 0; int baseY = (int)Math.Round(y); //------------------------------------- //load texture //_pcx.LoadTexture1(_glBmp); //------------------------------------- float acc_x = 0; float acc_y = 0; p.DrawImage(_fontBmp, 100, 100); int seqLen = glyphPlanSeq.Count; for (int i = 0; i < seqLen; ++i) { UnscaledGlyphPlan glyph = glyphPlanSeq[i]; AtlasItem glyphData; if (!_fontAtlas.TryGetItem(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 //-------------------------- g_x = (float)(x + (ngx - glyphData.TextureXOffset) * scaleFromTexture); //ideal x g_y = (float)(y + (ngy - glyphData.TextureYOffset + srcH) * scaleFromTexture); acc_x += (float)Math.Round(glyph.AdvanceX * scale); //g_x = (float)Math.Round(g_x); g_y = (float)Math.Floor(g_y); p.DrawImage(_fontBmp, g_x, g_y, srcX, srcY, srcW, srcH); } //------- //we create vbo first //then render }
public void DrawString(Painter p, char[] buffer, int startAt, int len, double x, double y) { if (!(p is AggPainter painter)) { 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 var textBufferSpan = new Typography.Text.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 ResolvedFont font = _textServices.ResolveFont(_font); GlyphPlanSequence glyphPlanSeq = _txtClient.CreateGlyphPlanSeq(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]; if (!_fontAtlas.TryGetItem(glyph.glyphIndex, out AtlasItem atlaItem)) { //if no glyph data, we should render a missing glyph *** continue; } //-------------------------------------- //TODO: review precise height in float //-------------------------------------- atlaItem.GetRect(out int srcX, out int srcY, out int srcW, out int 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 - atlaItem.TextureXOffset) * scaleFromTexture); //ideal x gy = (float)(y + (ngy - atlaItem.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); _maskBufferPainter.DrawImage(_fontBmp, gx, gy, srcX, 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); } }