/// <summary> /// do glyph shaping and glyph out /// </summary> /// <param name="str"></param> /// <param name="startAt"></param> /// <param name="len"></param> public void Layout( char[] str, int startAt, int len) { if (_needPlanUpdate) { UpdateLayoutPlan(); } Typeface typeface = this._typeface; //clear before use _inputGlyphs.Clear(); for (int i = 0; i < len; ++i) { //convert input char to input glyphs char c = str[startAt + i]; _inputGlyphs.AddGlyph(c, (ushort)typeface.LookupIndex(c)); } //---------------------------------------------- //glyph substitution if (_gsub != null & len > 0) { //TODO: review perf here _gsub.EnableLigation = this.EnableLigature; _gsub.DoSubstitution(_inputGlyphs); // _inputGlyphs.CreateMapFromUserCharToGlyphIndics(); } //---------------------------------------------- //after glyph substitution, //number of input glyph MAY changed (increase or decrease).*** //so count again. int finalGlyphCount = _inputGlyphs.Count; //---------------------------------------------- //glyph position _glyphPositions.Clear(); for (int i = 0; i < finalGlyphCount; ++i) { //at this stage _inputGlyphs and _glyphPositions //has member 1:1 ushort glyIndex = _inputGlyphs[i]; _glyphPositions.Add(new GlyphPos( glyIndex, typeface.GetGlyphByIndex(glyIndex).GlyphClass, typeface.GetHAdvanceWidthFromGlyphIndex(glyIndex)) ); } PositionTechnique posTech = this.PositionTechnique; if (_gpos != null && len > 1 && posTech == PositionTechnique.OpenFont) { _gpos.DoGlyphPosition(_glyphPositions); } }
/// <summary> /// do glyph shaping and glyph out /// </summary> /// <param name="str"></param> /// <param name="startAt"></param> /// <param name="len"></param> public void Layout( char[] str, int startAt, int len) { if (_needPlanUpdate) { UpdateLayoutPlan(); } Typeface typeface = this._typeface; //clear before use _inputGlyphs.Clear(); for (int i = 0; i < len; ++i) { //this is important! //----------------------- // from @samhocevar's PR: (https://github.com/LayoutFarm/Typography/pull/56/commits/b71c7cf863531ebf5caa478354d3249bde40b96e) //In many places, "char" is not a valid type to handle characters, because it //only supports 16 bits.In order to handle the full range of Unicode characters, //we need to use "int". //This allows characters such as 🙌 or 𐐷 or to be treated as single codepoints even //though they are encoded as two "char"s in a C# string. //----------------------- //convert input char to input glyphs char ch = str[startAt + i]; int codepoint = ch; if (ch >= 0xd800 && ch <= 0xdbff && i + 1 < len) { ++i; codepoint = char.ConvertToUtf32(ch, str[startAt + i]); } _inputGlyphs.AddGlyph(codepoint, typeface.LookupIndex(codepoint)); } //---------------------------------------------- //glyph substitution if (_gsub != null & len > 0) { //TODO: review perf here _gsub.EnableLigation = this.EnableLigature; _gsub.DoSubstitution(_inputGlyphs); // _inputGlyphs.CreateMapFromUserCharToGlyphIndics(); } //---------------------------------------------- //after glyph substitution, //number of input glyph MAY changed (increase or decrease).*** //so count again. int finalGlyphCount = _inputGlyphs.Count; //---------------------------------------------- //glyph position _glyphPositions.Clear(); _glyphPositions.Typeface = typeface; for (int i = 0; i < finalGlyphCount; ++i) { //at this stage _inputGlyphs and _glyphPositions //has member 1:1 ushort glyIndex = _inputGlyphs[i]; // Glyph orgGlyph = typeface.GetGlyphByIndex(glyIndex); //this is original value WITHOUT fit-to-grid adjust _glyphPositions.AddGlyph(glyIndex, orgGlyph); } PositionTechnique posTech = this.PositionTechnique; if (_gpos != null && len > 1 && posTech == PositionTechnique.OpenFont) { _gpos.DoGlyphPosition(_glyphPositions); } //---------------------------------------------- //at this point, all position is layout at original scale *** //then we will scale it to target scale later //---------------------------------------------- }