Exemplo n.º 1
0
        void InternalDrawString(char[] textBuffer, int startAt, int len, float x, float y)
        {
            UpdateGlyphLayoutSettings();
            //unscale layout, with design unit scale
            _glyphLayout.Layout(textBuffer, startAt, len);
            //
            //
            _outputGlyphPlans.Clear();
            //
            if (this._pxScaleEngine != null)
            {
                //scale to specific font size
                _pxScaleEngine.Layout(_glyphLayout.ResultUnscaledGlyphPositions, _outputGlyphPlans);
            }
            else
            {
                //no custom engine
                //then use default scale
                GlyphLayoutExtensions.GenerateGlyphPlans(
                    _glyphLayout.ResultUnscaledGlyphPositions,
                    _currentFontSizePxScale,
                    false,
                    _outputGlyphPlans);
            }

            DrawFromGlyphPlans(_outputGlyphPlans, x, y);
        }
Exemplo n.º 2
0
        public void MeasureString(char[] str, int startAt, int len, int limitWidth, out int charFit, out int charFitWidth)
        {
            //measure string
            if (str.Length < 1)
            {
                charFitWidth = 0;
            }

            _reusableMeasureBoxList.Clear(); //reset

            float pxscale = _currentTypeface.CalculateScaleToPixelFromPointSize(_fontSizeInPts);
            //NOET:at this moment, simple operation
            //may not be simple...
            //-------------------
            //input string may contain more than 1 script lang
            //user can parse it by other parser
            //but in this code, we use our Typography' parser
            //-------------------
            //user must setup the CustomBreakerBuilder before use

            int   cur_startAt = startAt;
            float accumW      = 0;

            foreach (BreakSpan breakSpan in BreakToLineSegments(str, startAt, len))
            {
                //measure string at specific px scale
                _glyphLayout.Layout(str, breakSpan.startAt, breakSpan.len);
                //
                _reusableGlyphPlanList.Clear();
                GlyphLayoutExtensions.GenerateGlyphPlans(
                    _glyphLayout.ResultUnscaledGlyphPositions,
                    pxscale,
                    true,
                    _reusableGlyphPlanList);
                //measure each glyph
                //limit at specific width
                int glyphCount = _reusableGlyphPlanList.Count;
                for (int i = 0; i < glyphCount; ++i)
                {
                    GlyphPlan glyphPlan = _reusableGlyphPlanList[i];
                    float     right     = glyphPlan.ExactRight * pxscale;
                    if (right >= accumW)
                    {
                        //stop here at this glyph
                        charFit = i - 1;
                        //TODO: review this
                        charFitWidth = (int)System.Math.Round(accumW);
                        return;
                    }
                    else
                    {
                        accumW = right;
                    }
                }
            }

            charFit      = 0;
            charFitWidth = 0;
        }
Exemplo n.º 3
0
        public void MeasureString(char[] str, int startAt, int len, out int w, out int h)
        {
            //measure string
            //check if we use cache feature or not

            if (str.Length < 1)
            {
                w = h = 0;
            }
            _reusableMeasureBoxList.Clear(); //reset

            float pxscale = _currentTypeface.CalculateScaleToPixelFromPointSize(_fontSizeInPts);
            //NOET:at this moment, simple operation
            //may not be simple...
            //-------------------
            //input string may contain more than 1 script lang
            //user can parse it by other parser
            //but in this code, we use our Typography' parser
            //-------------------
            //user must setup the CustomBreakerBuilder before use

            int   cur_startAt = startAt;
            float accumW      = 0;
            float accumH      = 0;

            foreach (BreakSpan breakSpan in BreakToLineSegments(str, startAt, len))
            {
                _glyphLayout.Layout(str, breakSpan.startAt, breakSpan.len);
                //
                _reusableGlyphPlanList.Clear();
                GlyphLayoutExtensions.GenerateGlyphPlans(
                    _glyphLayout.ResultUnscaledGlyphPositions,
                    pxscale,
                    true,
                    _reusableGlyphPlanList);
                //measure string size
                var result = new MeasuredStringBox(
                    _reusableGlyphPlanList.AccumAdvanceX * pxscale,
                    _currentTypeface.Ascender * pxscale,
                    _currentTypeface.Descender * pxscale,
                    _currentTypeface.LineGap * pxscale,
                    Typography.OpenFont.Extensions.TypefaceExtensions.CalculateRecommendLineSpacing(_currentTypeface) * pxscale);
                //
                ConcatMeasureBox(ref accumW, ref accumH, ref result);
            }

            w = (int)System.Math.Round(accumW);
            h = (int)System.Math.Round(accumH);
        }
Exemplo n.º 4
0
        public virtual void GenerateGlyphPlan(
            char[] textBuffer,
            int startAt,
            int len,
            GlyphPlanList outputGlyphPlanList,
            List <UserCodePointToGlyphIndex> charToGlyphMapList)
        {
            GlyphLayout glyphLayout = this.GlyphLayoutMan;

            glyphLayout.Layout(textBuffer, startAt, len);

            GlyphLayoutExtensions.GenerateGlyphPlans(
                glyphLayout.ResultUnscaledGlyphPositions,
                this.Typeface.CalculateScaleToPixelFromPointSize(this.FontSizeInPoints),
                false, outputGlyphPlanList);
        }
Exemplo n.º 5
0
        public GlyphPlanSequence GetUnscaledGlyphPlanSequence(GlyphLayout glyphLayout,
                                                              TextBuffer buffer, int start, int seqLen)
        {
            //UNSCALED VERSION
            //use current typeface + scriptlang
            int seqHashValue = CalculateHash(buffer, start, seqLen);

            //this func get the raw char from buffer
            //and create glyph list
            //check if we have the string cache in specific value
            //---------
            if (seqLen > _glyphPlanSeqSet.MaxCacheLen)
            {
                //layout string is too long to be cache
                //it need to split into small buffer
            }

            GlyphPlanSequence      planSeq = GlyphPlanSequence.Empty;
            GlyphPlanSeqCollection seqCol  = _glyphPlanSeqSet.GetSeqCollectionOrCreateIfNotExist(seqLen);

            if (!seqCol.TryGetCacheGlyphPlanSeq(seqHashValue, out planSeq))
            {
                //create a new one if we don't has a cache
                //1. layout
                glyphLayout.Layout(
                    buffer.UnsafeGetInternalBuffer(),
                    start,
                    seqLen);

                int pre_count = _planList.Count;
                //create glyph-plan ( UnScaled version) and add it to planList
                GlyphLayoutExtensions.GenerateGlyphPlans(glyphLayout.ResultUnscaledGlyphPositions, 1, false, _planList);
                int post_count = _planList.Count;
                planSeq = new GlyphPlanSequence(_planList, pre_count, post_count - pre_count);
                //
                seqCol.Register(seqHashValue, planSeq);
            }
            return(planSeq);
        }
Exemplo n.º 6
0
        public override void DrawString(char[] textBuffer, int startAt, int len, float x, float y)
        {
            //----------------
            //TODO: use typography text service
            //it should be faster since it has glyph-plan cache
            //----------------

            //1. update
            UpdateGlyphLayoutSettings();

            //2. unscale layout, in design unit
            this._glyphLayout.Layout(textBuffer, startAt, len);

            //3. scale  to specific font size
            _resuableGlyphPlanList.Clear();

            GlyphLayoutExtensions.GenerateGlyphPlans(
                _glyphLayout.ResultUnscaledGlyphPositions,
                _currentTypeface.CalculateScaleToPixelFromPointSize(this.FontSizeInPoints),
                false,
                _reusablePxScaleGlyphPlanList);

            DrawFromGlyphPlans(_resuableGlyphPlanList, x, y);
        }
        public void Layout(IGlyphPositions posStream, PxScaledGlyphPlanList outputGlyphPlanList)
        {
            float pxscale = _typeface.CalculateScaleToPixelFromPointSize(this._fontSizeInPoints);

            if (!UseWithLcdSubPixelRenderingTechnique)
            {
                //layout without fit to alignment direction
                GlyphLayoutExtensions.GenerateGlyphPlans(posStream, pxscale, false, outputGlyphPlanList);
                return; //early exit
            }
            //------------------------------
            int finalGlyphCount = posStream.Count;

#if DEBUG
            float dbug_onepx = 1 / pxscale;
#endif
            //
            int   cx = 0;
            short cy = 0;
            //
            //at this state, we need exact info at this specific pxscale
            //
            _glyphMeshStore.SetFont(_typeface, this._fontSizeInPoints);
            FineABC current_ABC = new FineABC();
            FineABC prev_ABC    = new FineABC();

            for (int i = 0; i < finalGlyphCount; ++i)
            {
                short  input_offset, offsetX, offsetY, advW; //all from pen-pos
                ushort glyphIndex = posStream.GetGlyph(i, out input_offset, out offsetX, out offsetY, out advW);
                GlyphControlParameters controlPars = _glyphMeshStore.GetControlPars(glyphIndex);
                current_ABC.SetData(pxscale, controlPars, offsetX, offsetY, (ushort)advW);
                //-------------------------------------------------------------

                if (i > 0)
                {
                    //inter-glyph space
                    //ideal space
                    float ideal_space = prev_ABC.s_c + current_ABC.s_a;
                    //actual space
                    float actual_space = prev_ABC.m_c + current_ABC.m_a;

                    if (ideal_space < 0)
                    {
                        //f-f
                        //f-o
                        if (prev_ABC.s_c < 0)
                        {
                            ideal_space = 0 + current_ABC.s_a;
                        }
                        if (ideal_space < 0)
                        {
                            ideal_space = 0;
                        }
                    }
                    if (ideal_space >= 0)
                    {
                        //m-a
                        //i-i
                        //o-p
                        if (actual_space > 1.5 && actual_space - 0.5 > ideal_space)
                        {
                            cx--;
                        }
                        else
                        {
                            if (actual_space < ideal_space)
                            {
                                if (prev_ABC.final_advW + prev_ABC.m_c_adjust < prev_ABC.m_max)
                                {
                                    cx += current_ABC.m_a_adjust;
                                }
                            }
                            else
                            {
                                if (prev_ABC.final_advW - prev_ABC.m_c + prev_ABC.m_c_adjust > prev_ABC.m_max)
                                {
                                    cx += prev_ABC.m_c_adjust;
                                }
                            }
                        }
                    }
                    else
                    {
                        //this should not occur?
                    }
                }
                //-------------------------------------------------------------

                //TODO: review here again***


                float exact_x = (float)(cx + current_ABC.s_offsetX);
                float exact_y = (float)(cy + current_ABC.s_offsetY);

                //check if the current position can create a sharp glyph
                int   exact_x_floor   = (int)exact_x;
                float x_offset_to_fit = current_ABC.s_avg_x_ToFit;

                float final_x = exact_x_floor + x_offset_to_fit;
                if (UseWithLcdSubPixelRenderingTechnique)
                {
                    final_x += 0.33f;
                }

                outputGlyphPlanList.Append(new PxScaledGlyphPlan(
                                               input_offset,
                                               glyphIndex,
                                               (short)current_ABC.final_advW,
                                               (short)Math.Round(current_ABC.s_offsetX),
                                               (short)Math.Round(current_ABC.s_offsetY)
                                               ));
                //
                //
                cx += current_ABC.final_advW;
                //-----------------------------------------------
                prev_ABC = current_ABC;//copy current to prev
#if DEBUG
                prev_ABC.dbugIsPrev = true;
#endif
                // Console.WriteLine(exact_x + "+" + (x_offset_to_fit) + "=>" + final_x);
            }
        }
Exemplo n.º 8
0
        public void MeasureString(char[] str, int startAt, int len, int limitWidth, out int charFit, out int charFitWidth)
        {
            //measure string
            if (str.Length < 1)
            {
                charFitWidth = 0;
            }

            _reusableMeasureBoxList.Clear(); //reset

            float pxscale = _currentTypeface.CalculateScaleToPixelFromPointSize(_fontSizeInPts);
            //NOET:at this moment, simple operation
            //may not be simple...
            //-------------------
            //input string may contain more than 1 script lang
            //user can parse it by other parser
            //but in this code, we use our Typography' parser
            //-------------------
            //user must setup the CustomBreakerBuilder before use

            int   cur_startAt = startAt;
            float accumW      = 0;

            foreach (BreakSpan breakSpan in BreakToLineSegments(str, startAt, len))
            {
                //measure string at specific px scale
                _glyphLayout.Layout(str, breakSpan.startAt, breakSpan.len);
                //

                _reusableScaledGlyphPlanList.Clear();
                GlyphLayoutExtensions.GenerateGlyphPlans(
                    _glyphLayout.ResultUnscaledGlyphPositions,
                    pxscale,
                    true,
                    _reusableScaledGlyphPlanList);
                //measure each glyph
                //limit at specific width
                int glyphCount = _reusableGlyphPlanList.Count;


                float acc_x = 0; //accum_x
                float acc_y = 0; //accum_y
                float g_x   = 0;
                float g_y   = 0;
                float x     = 0;
                float y     = 0;
                for (int i = 0; i < glyphCount; ++i)
                {
                    UnscaledGlyphPlan glyphPlan = _reusableGlyphPlanList[i];

                    float ngx = acc_x + (float)Math.Round(glyphPlan.OffsetX * pxscale);
                    float ngy = acc_y + (float)Math.Round(glyphPlan.OffsetY * pxscale);
                    //NOTE:
                    // -glyphData.TextureXOffset => restore to original pos
                    // -glyphData.TextureYOffset => restore to original pos
                    //--------------------------
                    g_x = (float)(x + (ngx)); //ideal x
                    g_y = (float)(y + (ngy));
                    float g_w = (float)Math.Round(glyphPlan.AdvanceX * pxscale);
                    acc_x += g_w;
                    //g_x = (float)Math.Round(g_x);
                    g_y = (float)Math.Floor(g_y);

                    float right = g_x + g_w;

                    if (right >= accumW)
                    {
                        //stop here at this glyph
                        charFit = i - 1;
                        //TODO: review this
                        charFitWidth = (int)System.Math.Round(accumW);
                        return;
                    }
                    else
                    {
                        accumW = right;
                    }
                }
            }

            charFit      = 0;
            charFitWidth = 0;
        }