Ejemplo n.º 1
0
        /// <summary>
        /// Breaks the specified text into lines. Only the sub-string will be used.<br/>
        /// White space is stripped at the beginning of the rows, the text is split at word boundaries or when new-line characters are encountered.<br/>
        /// Words longer than the max width are slit at nearest character (i.e. no hyphenation).
        /// </summary>
        public static int TextBreakLines(this Nvg nvg, string @string, string end, float breakRowWidth, out TextRow[] rows, int maxRows)
        {
            rows = new TextRow[maxRows];

            Fontstash fons = nvg.fontManager.Fontstash;

            State         state = nvg.stateStack.CurrentState;
            float         scale = nvg.fontManager.GetFontScale() * nvg.pixelRatio.DevicePxRatio;
            float         invscale = 1.0f / scale;
            FonsQuad      q = new();
            int           nrows = 0;
            float         rowStartX = 0.0f;
            float         rowWidth = 0.0f;
            float         rowMinX = 0.0f;
            float         rowMaxX = 0.0f;
            string        rowStart = null;
            string        rowEnd = null;
            string        wordStart = null;
            float         wordStartX = 0.0f;
            float         wordMinX = 0.0f;
            string        breakEnd = null;
            float         breakWidth = 0.0f;
            float         breakMaxX = 0.0f;
            CodepointType type, pType = CodepointType.Space;
            uint          pCodepoint = 0;

            if (maxRows == 0)
            {
                return(0);
            }

            if (state.FontId == Fontstash.INVALID)
            {
                return(0);
            }

            if (@string == end || @string.Length == 0)
            {
                return(0);
            }

            fons.SetSize(state.FontSize * scale);
            fons.SetSpacing(state.LetterSpacing * scale);
            fons.SetBlur(state.FontBlur * scale);
            fons.SetAlign((int)state.TextAlign);
            fons.SetFont(state.FontId);

            breakRowWidth *= scale;

            fons.TextIterInit(out FonsTextIter iter, 0, 0, @string, end, FonsGlyphBitmap.Optional);
            FonsTextIter prevIter = iter;

            while (fons.TextIterNext(ref iter, ref q))
            {
                if (iter.prevGlyphIndex < 0 && nvg.fontManager.AllocTextAtlas())
                {
                    iter = prevIter;
                    fons.TextIterNext(ref iter, ref q);
                }
                prevIter = iter;
                switch (iter.codepoint)
                {
                case 9:      // \t
                case 11:     // \v
                case 12:     // \f
                case 32:     // \space
                case 0x00a0: // NBSP
                    type = CodepointType.Space;
                    break;

                case 10:     // \n
                    type = pCodepoint == 13 ? CodepointType.Space : CodepointType.Newline;
                    break;

                case 13:     // \r
                    type = pCodepoint == 10 ? CodepointType.Space : CodepointType.Newline;
                    break;

                case 0x0085:     // NEL
                    type = CodepointType.Newline;
                    break;

                default:
                    if ((iter.codepoint >= 0x4E00 && iter.codepoint <= 0x9FFF) ||
                        (iter.codepoint >= 0x3000 && iter.codepoint <= 0x30FF) ||
                        (iter.codepoint >= 0xFF00 && iter.codepoint <= 0xFFEF) ||
                        (iter.codepoint >= 0x1100 && iter.codepoint <= 0x11FF) ||
                        (iter.codepoint >= 0x3130 && iter.codepoint <= 0x318F) ||
                        (iter.codepoint >= 0xAC00 && iter.codepoint <= 0xD7AF))
                    {
                        type = CodepointType.CJKChar;
                    }
                    else
                    {
                        type = CodepointType.Char;
                    }
                    break;
                }

                if (type == CodepointType.Newline)
                {
                    rows[nrows++] = new TextRow()
                    {
                        Start = rowStart ?? iter.str,
                        End   = rowEnd ?? iter.str,
                        Width = rowWidth * invscale,
                        MinX  = rowMinX * invscale,
                        MaxX  = rowMaxX * invscale,
                        Next  = iter.next
                    };

                    if (nrows >= maxRows)
                    {
                        return(nrows);
                    }

                    breakEnd   = rowStart;
                    breakWidth = 0.0f;
                    breakMaxX  = 0.0f;

                    rowStart = null;
                    rowEnd   = null;
                    rowWidth = 0.0f;
                    rowMinX  = rowMaxX = 0.0f;
                }
                else
                {
                    if (rowStart == null)
                    {
                        if (type == CodepointType.Char || type == CodepointType.CJKChar)
                        {
                            rowStartX  = iter.x;
                            rowStart   = iter.str;
                            rowEnd     = iter.next;
                            rowWidth   = iter.nextx - rowStartX;
                            rowMinX    = q.x0 - rowStartX;
                            rowMaxX    = q.x1 - rowStartX;
                            wordStart  = iter.str;
                            wordStartX = iter.x;
                            wordMinX   = q.x0 - rowStartX;

                            breakEnd   = rowStart;
                            breakWidth = 0.0f;
                            breakMaxX  = 0.0f;
                        }
                    }
                    else
                    {
                        float nextWidth = iter.nextx - rowStartX;

                        if (type == CodepointType.Char || type == CodepointType.CJKChar)
                        {
                            rowEnd   = iter.next;
                            rowWidth = iter.nextx - rowStartX;
                            rowMaxX  = q.x1 - rowStartX;
                        }

                        if (((pType == CodepointType.Char || pType == CodepointType.CJKChar) && type == CodepointType.Space) || type == CodepointType.CJKChar)
                        {
                            breakEnd   = iter.str;
                            breakWidth = rowWidth;
                            breakMaxX  = rowMaxX;
                        }

                        if ((pType == CodepointType.Space && (type == CodepointType.Char || type == CodepointType.CJKChar)) || type == CodepointType.CJKChar)
                        {
                            wordStart  = iter.str;
                            wordStartX = iter.x;
                            wordMinX   = q.x0;
                        }

                        if ((type == CodepointType.Char || type == CodepointType.CJKChar) && nextWidth > breakRowWidth)
                        {
                            if (breakEnd == rowStart)
                            {
                                rows[nrows++] = new TextRow()
                                {
                                    Start = rowStart,
                                    End   = iter.str,
                                    Width = rowWidth * invscale,
                                    MinX  = rowMinX * invscale,
                                    MaxX  = rowMaxX * invscale,
                                    Next  = iter.str
                                };

                                if (nrows >= maxRows)
                                {
                                    return(nrows);
                                }

                                rowStartX  = iter.x;
                                rowStart   = iter.str;
                                rowEnd     = iter.next;
                                rowWidth   = iter.nextx - rowStartX;
                                rowMinX    = q.x0 - rowStartX;
                                rowMaxX    = q.x1 - rowStartX;
                                wordStart  = iter.str;
                                wordStartX = iter.x;
                                wordMinX   = q.x0 - rowStartX;
                            }
                            else
                            {
                                rows[nrows++] = new TextRow()
                                {
                                    Start = rowStart,
                                    End   = breakEnd,
                                    Width = breakWidth * invscale,
                                    MinX  = rowMinX * invscale,
                                    MaxX  = breakMaxX * invscale,
                                    Next  = wordStart
                                };

                                if (nrows >= maxRows)
                                {
                                    return(nrows);
                                }

                                rowStartX = wordStartX;
                                rowStart  = wordStart;
                                rowEnd    = iter.next;
                                rowWidth  = iter.nextx - rowStartX;
                                rowMinX   = wordMinX - rowStartX;
                                rowMaxX   = q.x1 - rowStartX;
                            }

                            breakEnd   = rowStart;
                            breakWidth = 0.0f;
                            breakMaxX  = 0.0f;
                        }
                    }
                }

                pCodepoint = iter.codepoint;
                pType      = type;
            }

            if (rowStart != null)
            {
                rows[nrows++] = new TextRow()
                {
                    Start = rowStart,
                    End   = rowEnd,
                    Width = rowWidth * invscale,
                    MinX  = rowMinX * invscale,
                    MaxX  = rowMaxX * invscale,
                    Next  = end
                };
            }

            return(nrows);
        }
Ejemplo n.º 2
0
        private static string ProcessStyleSheet(string codepointFile, string injectNamespace, string injectType, CodepointType codepoint)
        {
            var characters = new StringBuilder();

            switch (codepoint)
            {
            case CodepointType.codepoints:
                ParseCodepoints(codepointFile, characters);
                break;

            case CodepointType.css:
            default:
                ParseCssCodepoints(codepointFile, characters);
                break;
            }

            // create the source file
            return(Template
                   .Replace("{{inject-namespace}}", injectNamespace)
                   .Replace("{{inject-type}}", injectType)
                   .Replace("{{inject-characters}}", characters.ToString()));
        }