public MyLineSegment(ILineSegmentList owner, int startAt, int len) { _owner = owner; _startAt = startAt; _len = len; this.scriptLang = null; }
// public void CalculateUserCharGlyphAdvancePos(ref TextBufferSpan textBufferSpan, ILineSegmentList lineSegs, RequestFont font, int[] outputUserInputCharAdvance, out int outputTotalW, out int lineHeight) { //layout //from font //resolve for typeface // Typeface typeface = ResolveTypeface(font); _txtServices.SetCurrentFont(typeface, font.SizeInPoints); MyLineSegmentList mylineSegs = (MyLineSegmentList)lineSegs; float scale = typeface.CalculateScaleToPixelFromPointSize(font.SizeInPoints); outputTotalW = 0; int j = mylineSegs.Count; int pos = 0; //start at 0 _reusableTextBuffer.SetRawCharBuffer(textBufferSpan.GetRawCharBuffer()); for (int i = 0; i < j; ++i) { //get each segment MyLineSegment lineSeg = (MyLineSegment)mylineSegs.GetSegment(i); //each line seg may has different script lang _txtServices.CurrentScriptLang = lineSeg.scriptLang; // //CACHING ...., reduce number of GSUB/GPOS // //we cache used line segment for a while //we ask for caching context for a specific typeface and font size GlyphPlanSequence seq = _txtServices.GetUnscaledGlyphPlanSequence(_reusableTextBuffer, lineSeg.StartAt, lineSeg.Length); int seqLen = seq.Count; for (int s = 0; s < seqLen; ++s) { UnscaledGlyphPlan glyphPlan = seq[s]; double actualAdvX = glyphPlan.AdvanceX; outputTotalW += outputUserInputCharAdvance[pos + glyphPlan.input_cp_offset] += (int)Math.Round(actualAdvX * scale); } pos += lineSeg.Length; } // lineHeight = (int)Math.Round(typeface.CalculateRecommendLineSpacing() * scale); _reusableTextBuffer.SetRawCharBuffer(null); }
public void CalculateUserCharGlyphAdvancePos(ref TextBufferSpan textBufferSpan, ILineSegmentList lineSegs, RequestFont font, int[] glyphXAdvances, out int outputTotalW, out int outputLineHeight) { throw new NotImplementedException(); }
public override void UpdateRunWidth() { ITextService txServices = Root.TextServices; Size size; if (IsLineBreak) { //TODO: review here //we should not store this as a text run //if this is a linebreak it should be encoded at the end of this visual line size = new Size(0, (int)Math.Round(txServices.MeasureBlankLineHeight(GetFont()))); _outputUserCharAdvances = null; } else { //TODO: review here again //1. after GSUB process, output glyph may be more or less //than original input char buffer(mybuffer) if (txServices.SupportsWordBreak) { var textBufferSpan = new TextBufferSpan(_mybuffer); int len = _mybuffer.Length; if (_content_unparsed) { //parse the content first _lineSegs = txServices.BreakToLineSegments(ref textBufferSpan); } // _content_unparsed = false; //output glyph position _outputUserCharAdvances = new int[len]; int outputTotalW, outputLineHeight; txServices.CalculateUserCharGlyphAdvancePos(ref textBufferSpan, _lineSegs, GetFont(), _outputUserCharAdvances, out outputTotalW, out outputLineHeight); size = new Size(outputTotalW, outputLineHeight); } else { _content_unparsed = false; int len = _mybuffer.Length; _outputUserCharAdvances = new int[len]; int outputTotalW, outputLineHeight; var textBufferSpan = new TextBufferSpan(_mybuffer); txServices.CalculateUserCharGlyphAdvancePos(ref textBufferSpan, GetFont(), _outputUserCharAdvances, out outputTotalW, out outputLineHeight); size = new Size(outputTotalW, outputLineHeight); } } //--------- this.SetSize(size.Width, size.Height); MarkHasValidCalculateSize(); }
public void FindCurrentHitWord(out int startAt, out int len) { if (_currentTextRun == null) { startAt = 0; len = 0; return; } // //we read entire line //and send to line parser to parse a word StringBuilder stbuilder = new StringBuilder(); _currentLine.CopyLineContent(stbuilder); string lineContent = stbuilder.ToString(); //find char at TextBufferSpan textBufferSpan = new TextBufferSpan(lineContent.ToCharArray()); using (ILineSegmentList segmentList = this.RootGfx.TextServices.BreakToLineSegments(ref textBufferSpan)) { if (segmentList == null) { startAt = 0; len = 0; return; } int segcount = segmentList.Count; for (int i = 0; i < segcount; ++i) { ILineSegment seg = segmentList[i]; if (seg.StartAt + seg.Length >= caret_char_index) { //stop at this segment startAt = seg.StartAt; len = seg.Length; return; } } } //? startAt = 0; len = 0; }
public void CalculateUserCharGlyphAdvancePos(ref TextBufferSpan textBufferSpan, ILineSegmentList lineSegs, RequestFont font, int[] outputUserInputCharAdvance, out int outputTotalW, out int lineHeight) { //layout //from font //resolve for typeface // Typeface typeface = ResolveTypeface(font); _txtServices.SetCurrentFont(typeface, font.SizeInPoints); MyLineSegmentList mylineSegs = (MyLineSegmentList)lineSegs; float scale = typeface.CalculateScaleToPixelFromPointSize(font.SizeInPoints); outputTotalW = 0; int j = mylineSegs.Count; int pos = 0; //start at 0 _reusableTextBuffer.SetRawCharBuffer(textBufferSpan.GetRawCharBuffer()); for (int i = 0; i < j; ++i) { //userGlyphPlanList.Clear(); //userCharToGlyphMapList.Clear(); //get each segment MyLineSegment lineSeg = mylineSegs.GetSegment(i); //each line seg may has different script lang _txtServices.CurrentScriptLang = lineSeg.scriptLang; // //CACHING ...., reduce number of GSUB/GPOS // //we cache used line segment for a while //we ask for caching context for a specific typeface and font size GlyphPlanSequence seq = _txtServices.GetUnscaledGlyphPlanSequence(_reusableTextBuffer, lineSeg.StartAt, lineSeg.Length); //IMPORTANT //num of glyph may more or less than original user input char buffer // //float g_x = 0; //float g_y = 0; //int baseY = (int)Math.Round(y); //int n = glyphPlanSeq.len; //int endBefore = glyphPlanSeq.startAt + n; ////*** //_glsx.SetAssociatedTextureInfo(_glBmp); //List<float> vboBufferList = new List<float>(); //List<ushort> indexList = new List<ushort>(); //for (int i = glyphPlanSeq.startAt; i < endBefore; ++i) //{ // GlyphPlanList glyphPlanList = GlyphPlanSequence.UnsafeGetInteralGlyphPlanList(glyphPlanSeq); // GlyphPlan glyph = glyphPlanList[i]; // Typography.Rendering.TextureGlyphMapData glyphData; // if (!_fontAtlas.TryGetGlyphDataByCodePoint(glyph.glyphIndex, out glyphData)) // { // //if no glyph data, we should render a missing glyph *** // continue; // } // //if (scaleFromTexture != 1) // //{ // //} // //-------------------------------------- // //TODO: review precise height in float // //-------------------------------------- // PixelFarm.Drawing.Rectangle srcRect = ConvToRect(glyphData.Rect); // g_x = (float)(x + (glyph.ExactX * scale - glyphData.TextureXOffset) * scaleFromTexture); //ideal x // g_y = (float)(y + (glyph.ExactY * scale - glyphData.TextureYOffset + srcRect.Height) * scaleFromTexture); // //for sharp glyph // //we adjust g_x,g_y to integer value // //float g_y2 = (float)Math.Floor(g_y); // g_x = (float)Math.Round(g_x); // g_y = (float)Math.Floor(g_y); // switch (textureKind) // { // case TextureKind.Msdf: // _glsx.DrawSubImageWithMsdf(_glBmp, // ref srcRect, // g_x, // g_y, // scaleFromTexture); // break; // case TextureKind.StencilGreyScale: // //stencil gray scale with fill-color // _glsx.DrawGlyphImageWithStecil(_glBmp, // ref srcRect, // g_x, // g_y, // scaleFromTexture); // break; // case TextureKind.Bitmap: // _glsx.DrawSubImage(_glBmp, // ref srcRect, // g_x, // g_y, // scaleFromTexture); // break; // case TextureKind.StencilLcdEffect: // _glsx.WriteVboToList( // vboBufferList, // indexList, // ref srcRect, // g_x, // g_y, // scaleFromTexture); // break; // } //} ////--------- int seqLen = seq.Count; for (int s = 0; s < seqLen; ++s) { UnscaledGlyphPlan glyphPlan = seq[s]; double actualAdvX = glyphPlan.AdvanceX; outputTotalW += outputUserInputCharAdvance[pos + glyphPlan.input_cp_offset] += (int)Math.Round(actualAdvX * scale); } pos += lineSeg.Length; } // lineHeight = (int)Math.Round(typeface.CalculateRecommendLineSpacing() * scale); _reusableTextBuffer.SetRawCharBuffer(null); }
public void CalculateUserCharGlyphAdvancePos(ref TextBufferSpan textBufferSpan, ILineSegmentList lineSegs, RequestFont font, int[] outputUserInputCharAdvance, out int outputTotalW, out int lineHeight) { //layout //from font //resolve for typeface // Typeface typeface = ResolveTypeface(font); _typographyTxtServices.SetCurrentFont(typeface, font.SizeInPoints); MyLineSegmentList mylineSegs = (MyLineSegmentList)lineSegs; float scale = typeface.CalculateScaleToPixelFromPointSize(font.SizeInPoints); outputTotalW = 0; int j = mylineSegs.Count; int pos = 0; //start at 0 _reusableTextBuffer.SetRawCharBuffer(textBufferSpan.GetRawCharBuffer()); for (int i = 0; i < j; ++i) { //userGlyphPlanList.Clear(); //userCharToGlyphMapList.Clear(); //get each segment MyLineSegment lineSeg = mylineSegs.GetSegment(i); //each line seg may has different script lang _typographyTxtServices.CurrentScriptLang = lineSeg.scriptLang; // //CACHING ...., reduce number of GSUB/GPOS // //we cache used line segment for a while //we ask for caching context for a specific typeface and font size GlyphPlanSequence seq = _typographyTxtServices.GetUnscaledGlyphPlanSequence(_reusableTextBuffer, lineSeg.StartAt, lineSeg.Length); GlyphPlanList planList = GlyphPlanSequence.UnsafeGetInteralGlyphPlanList(seq); //IMPORTANT //num of glyph may more or less than original user input char buffer // int endAt = seq.startAt + seq.len; int seq_startAt = seq.startAt; for (int s = seq_startAt; s < endAt; ++s) { GlyphPlan glyphPlan = planList[s]; float tx = glyphPlan.ExactX; float ty = glyphPlan.ExactY; double actualAdvX = glyphPlan.AdvanceX; outputTotalW += outputUserInputCharAdvance[pos + glyphPlan.input_cp_offset] += (int)Math.Round(actualAdvX * scale); } pos += lineSeg.Length; } // lineHeight = (int)Math.Round(typeface.CalculateRecommendLineSpacing() * scale); _reusableTextBuffer.SetRawCharBuffer(null); }