Пример #1
0
        /// <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);
            }
        }
Пример #2
0
        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;
            }
        }