public static void MeasureString( this GlyphLayout glyphLayout, char[] textBuffer, int startAt, int len, out MeasuredStringBox strBox, float scale = 1) { //TODO: consider extension method List <GlyphPlan> outputGlyphPlans = glyphLayout._myGlyphPlans; outputGlyphPlans.Clear(); glyphLayout.Layout(textBuffer, startAt, len, outputGlyphPlans); // int j = outputGlyphPlans.Count; Typeface currentTypeface = glyphLayout.Typeface; if (j == 0) { //not scale strBox = new MeasuredStringBox(0, currentTypeface.Ascender * scale, currentTypeface.Descender * scale, currentTypeface.LineGap * scale); } //get last one GlyphPlan lastOne = outputGlyphPlans[j - 1]; strBox = new MeasuredStringBox((lastOne.x + lastOne.advX) * scale, currentTypeface.Ascender * scale, currentTypeface.Descender * scale, currentTypeface.LineGap * scale); }
public void DoLeft() { int count = _charBuffer.Count; if (count == 0) { _caretCharIndex = 0; return; } else if (_caretCharIndex > 0) { //this is on the end _caretCharIndex--; //check if the caret can rest on this glyph? if (_caretCharIndex > 0) { //find its mapping to glyph index UserCharToGlyphIndexMap userCharToGlyphMap = _userCharToGlyphMap[_caretCharIndex]; int mapToGlyphIndex = userCharToGlyphMap.glyphIndexListOffset_plus1; // if (mapToGlyphIndex == 0) { //no map DoLeft(); //recursive *** return; } //------------------------- //we -1 *** GlyphPlan glyphPlan = _glyphPlans[userCharToGlyphMap.glyphIndexListOffset_plus1 - 1]; if (!glyphPlan.AdvanceMoveForward) { //caret can't rest here //so DoLeft(); //recursive *** return; } //--------------------- // } } else { } }
public void Append(GlyphPlan glyphPlan) { _glyphPlans.Add(glyphPlan); _accumAdvanceX += glyphPlan.AdvanceX; }
List <ushort> inputGlyphs = new List <ushort>(); //not thread safe*** public void Layout(Typeface typeface, float size, char[] str, List <GlyphPlan> glyphPlanBuffer) { //---------------------------------------------- //1. convert char[] to glyph[] //2. send to shaping engine //3. layout position of each glyph //---------------------------------------------- //check if we have created a glyph cache for the typeface GlyphsCache glyphCache; if (!_glyphCaches.TryGetValue(typeface, out glyphCache)) { //create new glyphCache = new GlyphsCache(typeface); _glyphCaches.Add(typeface, glyphCache); } //---------------------------------------------- int j = str.Length; inputGlyphs.Clear(); for (int i = 0; i < j; ++i) { //1. convert char[] to glyphIndex[] inputGlyphs.Add((ushort)typeface.LookupIndex(str[i])); } //---------------------------------------------- //glyph substitution if (j > 1) { GlyphSubStitution glyphSubstitution = new GlyphSubStitution(typeface, this.ScriptLang.shortname); glyphSubstitution.EnableLigation = this.EnableLigature; glyphSubstitution.DoSubstitution(inputGlyphs); } //---------------------------------------------- //glyph position j = inputGlyphs.Count; List <GlyphPos> glyphPositions = new List <GlyphPos>(j); for (int i = 0; i < j; ++i) { ushort glyIndex = inputGlyphs[i]; glyphPositions.Add(new GlyphPos( glyIndex, typeface.GetGlyphByIndex(glyIndex).GlyphClass, typeface.GetHAdvanceWidthFromGlyphIndex(glyIndex)) ); } PositionTecnhique posTech = this.PositionTechnique; if (j > 1 && posTech == PositionTecnhique.OpenFont) { GlyphSetPosition glyphSetPos = new GlyphSetPosition(typeface, ScriptLang.shortname); glyphSetPos.DoGlyphPosition(glyphPositions); } //-------------- float scale = typeface.CalculateFromPointToPixelScale(size); float cx = 0; float cy = 0; j = inputGlyphs.Count; for (int i = 0; i < j; ++i) { ushort glyIndex = inputGlyphs[i]; GlyphPlan glyphPlan = new GlyphPlan(glyIndex); glyphPlanBuffer.Add(glyphPlan); //this advWidth in font design unit float advWidth = typeface.GetHAdvanceWidthFromGlyphIndex(glyIndex) * scale; //---------------------------------- switch (posTech) { case PositionTecnhique.None: { glyphPlan.x = cx; glyphPlan.y = cy; glyphPlan.advX = advWidth; } break; case PositionTecnhique.OpenFont: { GlyphPos gpos_offset = glyphPositions[i]; glyphPlan.x = cx + (scale * gpos_offset.xoffset); glyphPlan.y = cy + (scale * gpos_offset.yoffset); glyphPlan.advX = advWidth; } break; case PositionTecnhique.Kerning: { glyphPlan.x = cx; glyphPlan.y = cy; glyphPlan.advX = advWidth; if (i > 0) { advWidth += typeface.GetKernDistance(glyphPlanBuffer[i - 1].glyphIndex, glyphPlanBuffer[i].glyphIndex) * scale; } } break; } cx += advWidth; } }