Beispiel #1
0
        /// <summary>
        /// Function to perform word wrapping on a string based on this font.
        /// </summary>
        /// <param name="text">The text to word wrap.</param>
        /// <param name="wordWrapWidth">The maximum width, in pixels, that must be met for word wrapping to occur.</param>
        /// <returns>The string with word wrapping.</returns>
        /// <remarks>
        /// <para>
        /// The <paramref name="wordWrapWidth"/> is the maximum number of pixels required for word wrapping, if an individual font glyph cell width (the <see cref="GorgonGlyph.Offset"/> +
        /// <see cref="GorgonGlyph.Advance"/>) exceeds that of the <paramref name="wordWrapWidth"/>, then the parameter value is updated to glyph cell width.
        /// </para>
        /// </remarks>
        public string WordWrap(string text, float wordWrapWidth)
        {
            if (string.IsNullOrEmpty(text))
            {
                return(text);
            }

            var wordText = new StringBuilder(text);

            if (!Glyphs.TryGetValue(Info.DefaultCharacter, out GorgonGlyph defaultGlyph))
            {
                throw new GorgonException(GorgonResult.CannotEnumerate, string.Format(Resources.GORGFX_ERR_FONT_DEFAULT_CHAR_NOT_VALID, Info.DefaultCharacter));
            }

            int   maxLength = wordText.Length;
            int   index     = 0;
            float position  = 0.0f;
            bool  firstChar = true;

            while (index < maxLength)
            {
                char character = wordText[index];

                // Don't count newline or carriage return.
                if ((character == '\n') ||
                    (character == '\r'))
                {
                    firstChar = true;
                    position  = 0;
                    ++index;
                    continue;
                }


                if (!Glyphs.TryGetValue(character, out GorgonGlyph glyph))
                {
                    glyph = defaultGlyph;
                }

                float glyphCellWidth = glyph.Advance;

                if (firstChar)
                {
                    glyphCellWidth += glyph.Offset.X;
                    firstChar       = false;
                }

                // If we're using kerning, then adjust for the kerning value.
                if ((Info.UseKerningPairs) &&
                    (index < maxLength - 1))
                {
                    if (KerningPairs.TryGetValue(new GorgonKerningPair(character, wordText[index + 1]), out int kernValue))
                    {
                        glyphCellWidth += kernValue;
                    }
                }

                position += glyphCellWidth;

                // Update the word wrap boundary if the cell size exceeds it.
                if (glyphCellWidth > wordWrapWidth)
                {
                    wordWrapWidth = glyphCellWidth;
                }

                // We're not at the break yet.
                if (position < wordWrapWidth)
                {
                    ++index;
                    continue;
                }

                int whiteSpaceIndex = index;

                // If we hit the max width, then we need to find the previous whitespace and inject a newline.
                while ((whiteSpaceIndex <= index) && (whiteSpaceIndex >= 0))
                {
                    char breakChar = wordText[whiteSpaceIndex];

                    if ((char.IsWhiteSpace(breakChar)) &&
                        (breakChar != '\n') &&
                        (breakChar != '\r'))
                    {
                        index = whiteSpaceIndex;
                        break;
                    }

                    --whiteSpaceIndex;
                }

                // If we're at the beginning, then we cannot wrap this text, so we'll break it at the border specified.
                if (index != whiteSpaceIndex)
                {
                    if (index != 0)
                    {
                        wordText.Insert(index, '\n');
                        maxLength = wordText.Length;
                        ++index;
                    }
                    position  = 0;
                    firstChar = true;
                    // Move to next character.
                    ++index;
                    continue;
                }

                // Extract the space.
                wordText[whiteSpaceIndex] = '\n';
                position  = 0;
                firstChar = true;
                index     = whiteSpaceIndex + 1;
            }

            return(wordText.ToString());
        }
Beispiel #2
0
        /// <summary>
        /// Function to measure the width of an individual line of text.
        /// </summary>
        /// <param name="line">The line to measure.</param>
        /// <param name="useOutline"><b>true</b> to use the font outline, <b>false</b> to disregard it.</param>
        /// <returns>The width of the line.</returns>
        private float GetLineWidth(string line, bool useOutline)
        {
            float size      = 0;
            bool  firstChar = true;

            if (!Glyphs.TryGetValue(Info.DefaultCharacter, out GorgonGlyph defaultGlyph))
            {
                throw new GorgonException(GorgonResult.CannotEnumerate, string.Format(Resources.GORGFX_ERR_FONT_DEFAULT_CHAR_NOT_VALID, Info.DefaultCharacter));
            }

            for (int i = 0; i < line.Length; i++)
            {
                char character = line[i];

                if (!Glyphs.TryGetValue(character, out GorgonGlyph glyph))
                {
                    glyph = defaultGlyph;
                }

                // Skip out on carriage returns and newlines.
                if ((character == '\r') ||
                    (character == '\n'))
                {
                    continue;
                }

                // Whitespace will use the glyph width.
                if (char.IsWhiteSpace(character))
                {
                    size += glyph.Advance;
                    continue;
                }

                // Include the initial offset.
                if (firstChar)
                {
                    size     += (useOutline && glyph.OutlineCoordinates.Width > 0) ? glyph.OutlineOffset.X : glyph.Offset.X;
                    firstChar = false;
                }

                size += glyph.Advance;

                if (!Info.UseKerningPairs)
                {
                    continue;
                }

                if ((i == line.Length - 1) ||
                    (KerningPairs.Count == 0))
                {
                    continue;
                }

                var kerning = new GorgonKerningPair(character, line[i + 1]);

                if (KerningPairs.TryGetValue(kerning, out int kernAmount))
                {
                    size += kernAmount;
                }
            }

            return(size);
        }