// ------------------------------------------------------------------ // Desc: // ------------------------------------------------------------------ private static float BuildLine(string _text, exISpriteFont _sprite, ref int _parsedVbIndex, float _top) { // cache property var letterSpacing = _sprite.letterSpacing; var wordSpacing = _sprite.wordSpacing; bool useKerning = _sprite.useKerning; exFont font = _sprite.font; // Vector2 pos = new Vector2(0.0f, _top); float lastAdvance = 0.0f; float lastWidth = 0.0f; for (int _charIndex = 0; _charIndex < _text.Length; ++_charIndex, _parsedVbIndex += 4, pos.x += letterSpacing) { char c = _text[_charIndex]; // if new line if (c == '\n' || c == '\r') { vertices.buffer[_parsedVbIndex + 0] = new Vector3(); vertices.buffer[_parsedVbIndex + 1] = new Vector3(); vertices.buffer[_parsedVbIndex + 2] = new Vector3(); vertices.buffer[_parsedVbIndex + 3] = new Vector3(); ++_charIndex; _parsedVbIndex += 4; break; } bool hasPreviousChar = _charIndex > 0; if (hasPreviousChar) { pos.x += lastAdvance; // kerning if (useKerning) { pos.x += font.GetKerning(_text[_charIndex - 1], c); } // wordSpacing if (c == ' ') { pos.x += wordSpacing; } } float width, advance; if (BuildChar(font, c, pos, _parsedVbIndex, out width, out advance)) { // advance x lastWidth = width; lastAdvance = advance; } } return(pos.x + lastWidth); }
// ------------------------------------------------------------------ // Desc: This only calculate result in one line // ------------------------------------------------------------------ public static bool CalcTextLine( out int _end_x, out int _end_index, StringBuilder _builder, string _text, int _index, int _maxWidth, exFont _font, int _wordSpacing, int _letterSpacing, bool _wrapWord, bool _collapseSpace, bool _collapseLinebreak ) { int cur_index = _index; int next_index = _index; int word_start_index = _index; int cur_x = 0; int word_start_x = 0; bool linebreak = false; bool trimWhitespace = true; bool beginningOfLine = true; char last_ch = '\0'; while ( cur_index < _text.Length ) { bool skipcpy = false; char ch = _text[cur_index]; next_index = cur_index+1; // if this is line-break if ( ch == '\n' || ch == '\r' ) { if ( _collapseLinebreak ) { ch = ' '; // turn it to space } else { linebreak = true; } } // if this is space if ( ch == ' ' || ch == '\t' || ch == '\f' ) { if ( _collapseSpace ) { while ( next_index < _text.Length ) { char next_ch = _text[next_index]; next_index = next_index + 1; // if next_ch is white-space, then collapse this char if ( next_ch == ' ' || next_ch == '\t' || next_ch == '\f' ) { cur_index = next_index-1; continue; } // if next_ch is line-break and collapseLinebreak is true, then collapse this char if ( next_ch == '\n' || next_ch == '\r' ) { if ( _collapseLinebreak ) { cur_index = next_index-1; continue; } } // break; } // skip first-time collapse if ( trimWhitespace ) { trimWhitespace = false; cur_index = next_index; continue; } // yes, must turn it to space to make sure only one space ch = ' '; } } // trimWhitespace = false; // process word-break, word-wrap if ( _wrapWord ) { word_start_index = cur_index; word_start_x = cur_x; // if this character can break if ( next_index >= _text.Length || CanWordBreak (ch) ) { // advanced character if ( last_ch != '\0' ) { cur_x += _font.GetKerning(last_ch, ch); } cur_x += _font.GetAdvance(ch); last_ch = ch; // check if the word exceed content width if ( cur_x > _maxWidth ) { if ( !beginningOfLine ) { linebreak = true; // skip copy the white-space if it is at the end of the wrap if ( ch == ' ' || ch == '\t' || ch == '\f' ) { skipcpy = true; } else { next_index = word_start_index; cur_x = word_start_x; } } } beginningOfLine = false; } else { // advanced current character if ( last_ch != '\0' ) { cur_x += _font.GetKerning(last_ch, ch); } cur_x += _font.GetAdvance(ch); last_ch = ch; while ( next_index < _text.Length ) { char next_ch = _text[next_index]; next_index = next_index + 1; // if this character can break if ( CanWordBreak (next_ch) ) { next_index -= 1; break; } // advanced character if ( last_ch != '\0' ) { cur_x += _font.GetKerning(last_ch, next_ch); } cur_x += _font.GetAdvance(next_ch); last_ch = next_ch; // TODO: process word-break // check if the word exceed content width if ( cur_x > _maxWidth ) { if ( !beginningOfLine ) { linebreak = true; next_index = word_start_index; cur_x = word_start_x; skipcpy = true; break; } } } } } else { // advanced character if ( last_ch != '\0' ) { cur_x += _font.GetKerning(last_ch, ch); } cur_x += _font.GetAdvance(ch); last_ch = ch; } // copy character to newtext_p if ( !skipcpy ) { int cpylen = next_index-cur_index; if ( cpylen > 0 ) { _builder.Append(_text, cur_index, cpylen ); } } // step cur_index = next_index; if ( linebreak ) { break; } } _end_x = cur_x; _end_index = cur_index; return linebreak; }
// ------------------------------------------------------------------ // Desc: This only calculate result in one line // ------------------------------------------------------------------ public static bool CalcTextLine(out int _end_x, out int _end_index, StringBuilder _builder, string _text, int _index, int _maxWidth, exFont _font, int _wordSpacing, int _letterSpacing, bool _wrapWord, bool _collapseSpace, bool _collapseLinebreak) { int cur_index = _index; int next_index = _index; int word_start_index = _index; int cur_x = 0; int word_start_x = 0; bool linebreak = false; bool trimWhitespace = true; bool beginningOfLine = true; char last_ch = '\0'; while (cur_index < _text.Length) { bool skipcpy = false; char ch = _text[cur_index]; next_index = cur_index + 1; // if this is line-break if (ch == '\n' || ch == '\r') { if (_collapseLinebreak) { ch = ' '; // turn it to space } else { linebreak = true; } } // if this is space if (ch == ' ' || ch == '\t' || ch == '\f') { if (_collapseSpace) { while (next_index < _text.Length) { char next_ch = _text[next_index]; next_index = next_index + 1; // if next_ch is white-space, then collapse this char if (next_ch == ' ' || next_ch == '\t' || next_ch == '\f') { cur_index = next_index - 1; continue; } // if next_ch is line-break and collapseLinebreak is true, then collapse this char if (next_ch == '\n' || next_ch == '\r') { if (_collapseLinebreak) { cur_index = next_index - 1; continue; } } // break; } // skip first-time collapse if (trimWhitespace) { trimWhitespace = false; cur_index = next_index; continue; } // yes, must turn it to space to make sure only one space ch = ' '; } } // trimWhitespace = false; // process word-break, word-wrap if (_wrapWord) { word_start_index = cur_index; word_start_x = cur_x; // if this character can break if (next_index >= _text.Length || CanWordBreak(ch)) { // advanced character if (last_ch != '\0') { cur_x += _font.GetKerning(last_ch, ch); } cur_x += _font.GetAdvance(ch); last_ch = ch; // check if the word exceed content width if (cur_x > _maxWidth) { if (!beginningOfLine) { linebreak = true; // skip copy the white-space if it is at the end of the wrap if (ch == ' ' || ch == '\t' || ch == '\f') { skipcpy = true; } else { next_index = word_start_index; cur_x = word_start_x; } } } beginningOfLine = false; } else { // advanced current character if (last_ch != '\0') { cur_x += _font.GetKerning(last_ch, ch); } cur_x += _font.GetAdvance(ch); last_ch = ch; while (next_index < _text.Length) { char next_ch = _text[next_index]; next_index = next_index + 1; // if this character can break if (CanWordBreak(next_ch)) { next_index -= 1; break; } // advanced character if (last_ch != '\0') { cur_x += _font.GetKerning(last_ch, next_ch); } cur_x += _font.GetAdvance(next_ch); last_ch = next_ch; // TODO: process word-break // check if the word exceed content width if (cur_x > _maxWidth) { if (!beginningOfLine) { linebreak = true; next_index = word_start_index; cur_x = word_start_x; skipcpy = true; break; } } } } } else { // advanced character if (last_ch != '\0') { cur_x += _font.GetKerning(last_ch, ch); } cur_x += _font.GetAdvance(ch); last_ch = ch; } // copy character to newtext_p if (!skipcpy) { int cpylen = next_index - cur_index; if (cpylen > 0) { _builder.Append(_text, cur_index, cpylen); } } // step cur_index = next_index; if (linebreak) { break; } } _end_x = cur_x; _end_index = cur_index; return(linebreak); }
// ------------------------------------------------------------------ // Desc: // ------------------------------------------------------------------ private static bool BuildChar(exFont _font, char _char, Vector2 _pos, int _vbIndex, out float charWidth, out float advance) { CharacterInfo ci; if (_font.GetCharInfo(_char, out ci) == false) { // character is not present, it will not display // Debug.Log("character is not present: " + c, this); vertices.buffer[_vbIndex + 0] = new Vector3(); vertices.buffer[_vbIndex + 1] = new Vector3(); vertices.buffer[_vbIndex + 2] = new Vector3(); vertices.buffer[_vbIndex + 3] = new Vector3(); charWidth = -1; advance = -1; return(false); } Vector3 min = new Vector3(_pos.x + ci.vert.xMin, _pos.y + ci.vert.yMin, 0.0f); Vector3 max = new Vector3(_pos.x + ci.vert.xMax, _pos.y + ci.vert.yMax, 0.0f); vertices.buffer[_vbIndex + 0] = new Vector3(min.x, max.y, 0.0f); vertices.buffer[_vbIndex + 1] = min; vertices.buffer[_vbIndex + 2] = new Vector3(max.x, min.y, 0.0f); vertices.buffer[_vbIndex + 3] = max; // advance x charWidth = ci.vert.width; advance = ci.width; // set uv if (uvs != null) { Vector2 start = new Vector2(ci.uv.xMin, ci.uv.yMin); Vector2 end = new Vector2(ci.uv.xMax, ci.uv.yMax); if (ci.flipped) { uvs.buffer[_vbIndex + 0] = start; uvs.buffer[_vbIndex + 1] = new Vector2(end.x, start.y); uvs.buffer[_vbIndex + 2] = end; uvs.buffer[_vbIndex + 3] = new Vector2(start.x, end.y); } else { uvs.buffer[_vbIndex + 0] = start; uvs.buffer[_vbIndex + 1] = new Vector2(start.x, end.y); uvs.buffer[_vbIndex + 2] = end; uvs.buffer[_vbIndex + 3] = new Vector2(end.x, start.y); } } // set color if (colors32 != null) { Color32 t = exMath.Lerp(topFinalColor, botFinalColor, -ci.vert.yMin); Color32 b = exMath.Lerp(topFinalColor, botFinalColor, -ci.vert.yMax); colors32.buffer[_vbIndex + 0] = b; colors32.buffer[_vbIndex + 1] = t; colors32.buffer[_vbIndex + 2] = t; colors32.buffer[_vbIndex + 3] = b; } return(true); }