Example #1
0
        internal IVertexSource GetGlyphForCharacter(char character)
        {
            if (ttfTypeFace != null)
            {
                // TODO: MAKE SURE THIS IS OFF!!!!!!! It is un-needed and only for debugging
                //glyphs.Clear();
            }

            IVertexSource vertexSource = null;
            // TODO: check for multi character glyphs (we don't currently support them in the reader).
            Glyph glyph = null;

            if (!glyphs.TryGetValue(character, out glyph))
            {
                // if we have a loaded ttf try to create the glyph data
                if (ttfTypeFace != null)
                {
                    glyph = new Glyph();
                    var translator = new VertexSourceGlyphTranslator(glyph.glyphData);
                    var glyphIndex = ttfTypeFace.LookupIndex(character);
                    var ttfGlyph   = ttfTypeFace.GetGlyphByIndex(glyphIndex);
                    translator.Read(ttfGlyph.GlyphPoints, ttfGlyph.EndPoints);
                    glyph.unicode     = character;
                    glyph.horiz_adv_x = ttfTypeFace.GetHAdvanceWidthFromGlyphIndex(glyphIndex);
                    glyphs.Add(character, glyph);
                    vertexSource = glyph.glyphData;
                }
            }
            else
            {
                vertexSource = glyph.glyphData;
            }

            return(vertexSource);
        }
        public static void CollectAllAssociateGlyphIndex(this TtfTypeface typeface, List <ushort> outputGlyphIndexList, ScriptLang scLang, UnicodeLangBits[] selectedRangs = null)
        {
            //-----------
            //general glyph index in the unicode range

            //if user dose not specific the unicode lanf bit ranges
            //the we try to select it ourself.
            UnicodeLangBits[] unicodeLangBitsRanges;
            if (ScriptLangs.TryGenUnicodeLangBitsArray(scLang.shortname, out unicodeLangBitsRanges))
            {
                //one lang may contains may ranges
                if (selectedRangs != null)
                {
                    //select only in range
                    unicodeLangBitsRanges = FilterOnlySelectedRange(unicodeLangBitsRanges, selectedRangs);
                }

                foreach (UnicodeLangBits unicodeLangBits in unicodeLangBitsRanges)
                {
                    UnicodeRangeInfo rngInfo = unicodeLangBits.ToUnicodeRangeInfo();
                    int endAt = rngInfo.EndAt;
                    for (int codePoint = rngInfo.StartAt; codePoint <= endAt; ++codePoint)
                    {
                        ushort glyghIndex = typeface.LookupIndex(codePoint);
                        if (glyghIndex > 0)
                        {
                            //add this glyph index
                            outputGlyphIndexList.Add(glyghIndex);
                        }
                    }
                }
            }

            //-----------
            var gsub = new GlyphSubstitution(typeface, scLang.shortname);

            gsub.CollectAdditionalSubstitutionGlyphIndices(outputGlyphIndexList);
        }
Example #3
0
        List <int> _codepoints = new List <int>();//not thread-safe***

        /// <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();
            }

            // 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.
            _codepoints.Clear();
            for (int i = 0; i < len; ++i)
            {
                char ch        = str[startAt + i];
                int  codepoint = ch;
                if (Char.IsHighSurrogate(ch) && i + 1 < len)
                {
                    char nextCh = str[startAt + i + 1];
                    if (Char.IsLowSurrogate(nextCh))
                    {
                        ++i;
                        codepoint = char.ConvertToUtf32(ch, nextCh);
                    }
                }
                _codepoints.Add(codepoint);
            }

            // clear before use
            _inputGlyphs.Clear();

            // convert codepoints to input glyphs
            for (int i = 0; i < _codepoints.Count; ++i)
            {
                int    codepoint  = _codepoints[i];
                ushort glyphIndex = _typeface.LookupIndex(codepoint);
                if (i + 1 < _codepoints.Count)
                {
                    // Maybe this is a UVS sequence; in that case, skip the second codepoint
                    int    nextCodepoint       = _codepoints[i + 1];
                    ushort variationGlyphIndex = _typeface.LookupIndex(codepoint, nextCodepoint);
                    if (variationGlyphIndex > 0)
                    {
                        ++i;
                        glyphIndex = variationGlyphIndex;
                    }
                }
                _inputGlyphs.AddGlyph(codepoint, glyphIndex);
            }

            //----------------------------------------------
            //glyph substitution
            if (_gsub != null & len > 0)
            {
                //TODO: review perf here
                _gsub.EnableLigation    = this.EnableLigature;
                _gsub.EnableComposition = this.EnableComposition;
                _gsub.DoSubstitution(_inputGlyphs);
                //
                _inputGlyphs.CreateMapFromUserCharToGlyphIndices();
            }
            //----------------------------------------------
            //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];
                //
                TtfGlyph 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
            //----------------------------------------------
        }