|
|
@@ -173,310 +173,365 @@ void Font::begin()
|
|
|
{
|
|
|
_batch->begin();
|
|
|
}
|
|
|
-/*
|
|
|
-Font::TextBatch* Font::getTextBatch(const char* text, const Rectangle& area, const Vector4& color, unsigned int size, Justify justify,
|
|
|
- bool wrap, bool rightToLeft, const Rectangle* clip)
|
|
|
-{
|
|
|
|
|
|
-}
|
|
|
-*/
|
|
|
-void Font::drawText(const char* text, int x, int y, const Vector4& color, unsigned int size, bool rightToLeft)
|
|
|
+Font::Text* Font::createText(const char* text, const Rectangle& area, const Vector4& color, unsigned int size, Justify justify,
|
|
|
+ bool wrap, bool rightToLeft, const Rectangle* clip)
|
|
|
{
|
|
|
if (size == 0)
|
|
|
size = _size;
|
|
|
float scale = (float)size / _size;
|
|
|
- const char* cursor = NULL;
|
|
|
+ const int length = strlen(text);
|
|
|
+ int yPos = area.y;
|
|
|
+ const float areaHeight = area.height - size;
|
|
|
+ std::vector<int> xPositions;
|
|
|
+ std::vector<unsigned int> lineLengths;
|
|
|
|
|
|
- if (rightToLeft)
|
|
|
+ getMeasurementInfo(text, area, size, justify, wrap, rightToLeft, &xPositions, &yPos, &lineLengths);
|
|
|
+
|
|
|
+ Text* batch = new Text(text);
|
|
|
+
|
|
|
+ int xPos = area.x;
|
|
|
+ std::vector<int>::const_iterator xPositionsIt = xPositions.begin();
|
|
|
+ if (xPositionsIt != xPositions.end())
|
|
|
{
|
|
|
- cursor = text;
|
|
|
+ xPos = *xPositionsIt++;
|
|
|
}
|
|
|
|
|
|
- int xPos = x, yPos = y;
|
|
|
- bool done = false;
|
|
|
+ const char* token = text;
|
|
|
+ int iteration = 1;
|
|
|
+ unsigned int lineLength;
|
|
|
+ unsigned int currentLineLength = 0;
|
|
|
+ const char* lineStart;
|
|
|
+ std::vector<unsigned int>::const_iterator lineLengthsIt;
|
|
|
+ if (rightToLeft)
|
|
|
+ {
|
|
|
+ lineStart = token;
|
|
|
+ lineLengthsIt = lineLengths.begin();
|
|
|
+ lineLength = *lineLengthsIt++;
|
|
|
+ token += lineLength - 1;
|
|
|
+ iteration = -1;
|
|
|
+ }
|
|
|
|
|
|
- while (!done)
|
|
|
+ while (token[0] != 0)
|
|
|
{
|
|
|
- int length;
|
|
|
- int startIndex;
|
|
|
- int iteration;
|
|
|
- if (rightToLeft)
|
|
|
+ // Handle delimiters until next token.
|
|
|
+ if (!handleDelimiters(&token, size, iteration, area.x, &xPos, &yPos, ¤tLineLength, &xPositionsIt, xPositions.end()))
|
|
|
{
|
|
|
- char delimiter = cursor[0];
|
|
|
- while (!done &&
|
|
|
- (delimiter == ' ' ||
|
|
|
- delimiter == '\t' ||
|
|
|
- delimiter == '\r' ||
|
|
|
- delimiter == '\n' ||
|
|
|
- delimiter == 0))
|
|
|
- {
|
|
|
- switch (delimiter)
|
|
|
- {
|
|
|
- case ' ':
|
|
|
- xPos += size >> 1;
|
|
|
- break;
|
|
|
- case '\r':
|
|
|
- case '\n':
|
|
|
- yPos += size;
|
|
|
- xPos = x;
|
|
|
- break;
|
|
|
- case '\t':
|
|
|
- xPos += (size >> 1)*4;
|
|
|
- break;
|
|
|
- case 0:
|
|
|
- done = true;
|
|
|
- break;
|
|
|
- }
|
|
|
-
|
|
|
- if (!done)
|
|
|
- {
|
|
|
- ++cursor;
|
|
|
- delimiter = cursor[0];
|
|
|
- }
|
|
|
- }
|
|
|
+ break;
|
|
|
+ }
|
|
|
|
|
|
- length = strcspn(cursor, "\r\n");
|
|
|
- startIndex = length - 1;
|
|
|
+ bool truncated = false;
|
|
|
+ unsigned int tokenLength;
|
|
|
+ unsigned int tokenWidth;
|
|
|
+ unsigned int startIndex;
|
|
|
+ if (rightToLeft)
|
|
|
+ {
|
|
|
+ tokenLength = getReversedTokenLength(token, text);
|
|
|
+ currentLineLength += tokenLength;
|
|
|
+ token -= (tokenLength - 1);
|
|
|
+ tokenWidth = getTokenWidth(token, tokenLength, size, scale);
|
|
|
iteration = -1;
|
|
|
+ startIndex = tokenLength - 1;
|
|
|
}
|
|
|
else
|
|
|
{
|
|
|
- length = strlen(text);
|
|
|
- startIndex = 0;
|
|
|
+ tokenLength = strcspn(token, " \r\n\t");
|
|
|
+ tokenWidth = getTokenWidth(token, tokenLength, size, scale);
|
|
|
iteration = 1;
|
|
|
+ startIndex = 0;
|
|
|
}
|
|
|
|
|
|
- for (int i = startIndex; i < length && i >= 0; i += iteration)
|
|
|
+ // Wrap if necessary.
|
|
|
+ if (wrap &&
|
|
|
+ xPos + (int)tokenWidth > area.x + area.width ||
|
|
|
+ (rightToLeft && currentLineLength > lineLength))
|
|
|
{
|
|
|
- char c = 0;
|
|
|
- if (rightToLeft)
|
|
|
+ yPos += (int)size;
|
|
|
+ currentLineLength = tokenLength;
|
|
|
+
|
|
|
+ if (xPositionsIt != xPositions.end())
|
|
|
{
|
|
|
- c = cursor[i];
|
|
|
+ xPos = *xPositionsIt++;
|
|
|
}
|
|
|
else
|
|
|
{
|
|
|
- c = text[i];
|
|
|
- }
|
|
|
-
|
|
|
- // Draw this character.
|
|
|
- switch (c)
|
|
|
- {
|
|
|
- case ' ':
|
|
|
- xPos += size >> 1;
|
|
|
- break;
|
|
|
- case '\r':
|
|
|
- case '\n':
|
|
|
- yPos += size;
|
|
|
- xPos = x;
|
|
|
- break;
|
|
|
- case '\t':
|
|
|
- xPos += (size >> 1)*4;
|
|
|
- break;
|
|
|
- default:
|
|
|
- int index = c - 32; // HACK for ASCII
|
|
|
- if (index >= 0 && index < (int)_glyphCount)
|
|
|
- {
|
|
|
- Glyph& g = _glyphs[index];
|
|
|
- _batch->draw(xPos, yPos, g.width * scale, size, g.uvs[0], g.uvs[1], g.uvs[2], g.uvs[3], color);
|
|
|
- xPos += floor(g.width * scale + (float)(size >> 3));
|
|
|
- break;
|
|
|
- }
|
|
|
+ xPos = area.x;
|
|
|
}
|
|
|
}
|
|
|
|
|
|
- if (rightToLeft)
|
|
|
+ bool draw = true;
|
|
|
+ if (yPos < area.y)
|
|
|
{
|
|
|
- cursor += length;
|
|
|
+ // Skip drawing until line break or wrap.
|
|
|
+ draw = false;
|
|
|
}
|
|
|
- else
|
|
|
+ else if (yPos > area.y + areaHeight)
|
|
|
{
|
|
|
- done = true;
|
|
|
+ // Truncate below area's vertical limit.
|
|
|
+ break;
|
|
|
}
|
|
|
- }
|
|
|
-}
|
|
|
-
|
|
|
-void Font::drawText(const char* text, const Rectangle& area, const Vector4& color, unsigned int size, Justify justify, bool wrap, bool rightToLeft, const Rectangle* clip)
|
|
|
-{
|
|
|
- if (size == 0)
|
|
|
- size = _size;
|
|
|
- float scale = (float)size / _size;
|
|
|
- const char* token = text;
|
|
|
- const int length = strlen(text);
|
|
|
- int yPos = area.y;
|
|
|
- const float areaHeight = area.height - size;
|
|
|
-
|
|
|
- Justify vAlign = static_cast<Justify>(justify & 0xF0);
|
|
|
- if (vAlign == 0)
|
|
|
- {
|
|
|
- vAlign = ALIGN_TOP;
|
|
|
- }
|
|
|
|
|
|
- Justify hAlign = static_cast<Justify>(justify & 0x0F);
|
|
|
- if (hAlign == 0)
|
|
|
- {
|
|
|
- hAlign = ALIGN_LEFT;
|
|
|
- }
|
|
|
-
|
|
|
- // For alignments other than top-left, need to calculate the y position to begin drawing from
|
|
|
- // and the starting x position of each line. For right-to-left text, need to determine
|
|
|
- // the number of characters on each line.
|
|
|
- std::vector<int> xPositions;
|
|
|
- std::vector<unsigned int> lineLengths;
|
|
|
- if (vAlign != ALIGN_TOP || hAlign != ALIGN_LEFT || rightToLeft)
|
|
|
- {
|
|
|
- int lineWidth = 0;
|
|
|
- int delimWidth = 0;
|
|
|
-
|
|
|
- if (wrap)
|
|
|
+ for (int i = startIndex; i < (int)tokenLength && i >= 0; i += iteration)
|
|
|
{
|
|
|
- // Go a word at a time.
|
|
|
- bool reachedEOF = false;
|
|
|
- unsigned int lineLength = 0;
|
|
|
- while (token[0] != 0)
|
|
|
+ char c = token[i];
|
|
|
+ int glyphIndex = c - 32; // HACK for ASCII
|
|
|
+
|
|
|
+ if (glyphIndex >= 0 && glyphIndex < (int)_glyphCount)
|
|
|
{
|
|
|
- unsigned int tokenWidth = 0;
|
|
|
+ Glyph& g = _glyphs[glyphIndex];
|
|
|
|
|
|
- // Handle delimiters until next token.
|
|
|
- char delimiter = token[0];
|
|
|
- while (delimiter == ' ' ||
|
|
|
- delimiter == '\t' ||
|
|
|
- delimiter == '\r' ||
|
|
|
- delimiter == '\n' ||
|
|
|
- delimiter == 0)
|
|
|
+ if (xPos + (int)(g.width*scale) > area.x + area.width)
|
|
|
{
|
|
|
- switch (delimiter)
|
|
|
+ // Truncate this line and go on to the next one.
|
|
|
+ truncated = true;
|
|
|
+ break;
|
|
|
+ }
|
|
|
+ else if (xPos >= area.x)
|
|
|
+ {
|
|
|
+ // Draw this character.
|
|
|
+ if (draw)
|
|
|
{
|
|
|
- case ' ':
|
|
|
- delimWidth += size >> 1;
|
|
|
- lineLength++;
|
|
|
- break;
|
|
|
- case '\r':
|
|
|
- case '\n':
|
|
|
- yPos += size;
|
|
|
+ if (clip)
|
|
|
+ {
|
|
|
+ _batch->addSprite(xPos, yPos, g.width * scale, size, g.uvs[0], g.uvs[1], g.uvs[2], g.uvs[3], color, *clip, &batch->_vertices[batch->_vertexCount]);
|
|
|
+ }
|
|
|
+ else
|
|
|
+ {
|
|
|
+ _batch->addSprite(xPos, yPos, g.width * scale, size, g.uvs[0], g.uvs[1], g.uvs[2], g.uvs[3], color, &batch->_vertices[batch->_vertexCount]);
|
|
|
+ }
|
|
|
|
|
|
- if (lineWidth > 0)
|
|
|
+ if (batch->_vertexCount == 0)
|
|
|
+ {
|
|
|
+ // Simply copy values directly into the start of the index array
|
|
|
+ //memcpy(_indicesPtr, indices, indexCount * sizeof(unsigned short));
|
|
|
+ batch->_indices[batch->_vertexCount] = batch->_vertexCount++;
|
|
|
+ batch->_indices[batch->_vertexCount] = batch->_vertexCount++;
|
|
|
+ batch->_indices[batch->_vertexCount] = batch->_vertexCount++;
|
|
|
+ batch->_indices[batch->_vertexCount] = batch->_vertexCount++;
|
|
|
+ batch->_indexCount += 4;
|
|
|
+ }
|
|
|
+ else
|
|
|
+ {
|
|
|
+ // Create a degenerate triangle to connect separate triangle strips
|
|
|
+ // by duplicating the previous and next vertices.
|
|
|
+ batch->_indices[batch->_indexCount] = batch->_indices[batch->_indexCount - 1];
|
|
|
+ batch->_indices[batch->_indexCount + 1] = batch->_vertexCount;
|
|
|
+
|
|
|
+ // Loop through all indices and insert them, their their value offset by
|
|
|
+ // 'vertexCount' so that they are relative to the first newly insertted vertex
|
|
|
+ for (unsigned int i = 0; i < 4; ++i)
|
|
|
{
|
|
|
- addLineInfo(area, lineWidth, lineLength, hAlign, &xPositions, &lineLengths, rightToLeft);
|
|
|
+ batch->_indices[batch->_indexCount + 2 + i] = i + batch->_vertexCount;
|
|
|
}
|
|
|
|
|
|
- lineWidth = 0;
|
|
|
- lineLength = 0;
|
|
|
- delimWidth = 0;
|
|
|
- break;
|
|
|
- case '\t':
|
|
|
- delimWidth += (size >> 1)*4;
|
|
|
- lineLength++;
|
|
|
- break;
|
|
|
- case 0:
|
|
|
- reachedEOF = true;
|
|
|
- break;
|
|
|
- }
|
|
|
+ batch->_indexCount += 6;
|
|
|
+ batch->_vertexCount += 4;
|
|
|
+ }
|
|
|
|
|
|
- if (reachedEOF)
|
|
|
- {
|
|
|
- break;
|
|
|
}
|
|
|
-
|
|
|
- token++;
|
|
|
- delimiter = token[0];
|
|
|
}
|
|
|
+ xPos += (int)(g.width)*scale + (size >> 3);
|
|
|
+ }
|
|
|
+ }
|
|
|
|
|
|
- if (reachedEOF || token == NULL)
|
|
|
- {
|
|
|
- break;
|
|
|
- }
|
|
|
-
|
|
|
- unsigned int tokenLength = strcspn(token, " \r\n\t");
|
|
|
- tokenWidth += getTokenWidth(token, tokenLength, size, scale);
|
|
|
-
|
|
|
- // Wrap if necessary.
|
|
|
- if (lineWidth + tokenWidth + delimWidth > area.width)
|
|
|
+ if (!truncated)
|
|
|
+ {
|
|
|
+ if (rightToLeft)
|
|
|
+ {
|
|
|
+ if (token == lineStart)
|
|
|
{
|
|
|
- yPos += (int)size;
|
|
|
-
|
|
|
- // Push position of current line.
|
|
|
- if (lineLength)
|
|
|
+ token += lineLength;
|
|
|
+
|
|
|
+ // Now handle delimiters going forwards.
|
|
|
+ if (!handleDelimiters(&token, size, 1, area.x, &xPos, &yPos, ¤tLineLength, &xPositionsIt, xPositions.end()))
|
|
|
{
|
|
|
- addLineInfo(area, lineWidth, lineLength-1, hAlign, &xPositions, &lineLengths, rightToLeft);
|
|
|
+ break;
|
|
|
}
|
|
|
- else
|
|
|
+
|
|
|
+ if (lineLengthsIt != lineLengths.end())
|
|
|
{
|
|
|
- addLineInfo(area, lineWidth, tokenLength, hAlign, &xPositions, &lineLengths, rightToLeft);
|
|
|
+ lineLength = *lineLengthsIt++;
|
|
|
}
|
|
|
-
|
|
|
- // Move token to the next line.
|
|
|
- lineWidth = 0;
|
|
|
- lineLength = 0;
|
|
|
- delimWidth = 0;
|
|
|
+ lineStart = token;
|
|
|
+ token += lineLength-1;
|
|
|
}
|
|
|
else
|
|
|
{
|
|
|
- lineWidth += delimWidth;
|
|
|
- delimWidth = 0;
|
|
|
+ token--;
|
|
|
}
|
|
|
-
|
|
|
- lineWidth += tokenWidth;
|
|
|
- lineLength += tokenLength;
|
|
|
- token += tokenLength;
|
|
|
}
|
|
|
-
|
|
|
- // Final calculation of vertical position.
|
|
|
- int textHeight = yPos - area.y;
|
|
|
- int vWhiteSpace = areaHeight - textHeight;
|
|
|
- if (vAlign == ALIGN_VCENTER)
|
|
|
+ else
|
|
|
{
|
|
|
- yPos = area.y + vWhiteSpace / 2;
|
|
|
+ token += tokenLength;
|
|
|
}
|
|
|
- else if (vAlign == ALIGN_BOTTOM)
|
|
|
+ }
|
|
|
+ else
|
|
|
+ {
|
|
|
+ if (rightToLeft)
|
|
|
{
|
|
|
- yPos = area.y + vWhiteSpace;
|
|
|
+ token = lineStart + lineLength;
|
|
|
+
|
|
|
+ if (!handleDelimiters(&token, size, 1, area.x, &xPos, &yPos, ¤tLineLength, &xPositionsIt, xPositions.end()))
|
|
|
+ {
|
|
|
+ break;
|
|
|
+ }
|
|
|
+
|
|
|
+ if (lineLengthsIt != lineLengths.end())
|
|
|
+ {
|
|
|
+ lineLength = *lineLengthsIt++;
|
|
|
+ }
|
|
|
+ lineStart = token;
|
|
|
+ token += lineLength-1;
|
|
|
}
|
|
|
+ else
|
|
|
+ {
|
|
|
+ // Skip the rest of this line.
|
|
|
+ unsigned int tokenLength = strcspn(token, "\n");
|
|
|
|
|
|
- // Calculation of final horizontal position.
|
|
|
- addLineInfo(area, lineWidth, lineLength, hAlign, &xPositions, &lineLengths, rightToLeft);
|
|
|
+ if (tokenLength > 0)
|
|
|
+ {
|
|
|
+ // Get first token of next line.
|
|
|
+ token += tokenLength;
|
|
|
+ }
|
|
|
+ }
|
|
|
}
|
|
|
- else
|
|
|
+ }
|
|
|
+
|
|
|
+ return batch;
|
|
|
+}
|
|
|
+
|
|
|
+void Font::drawText(Text* textBatch)
|
|
|
+{
|
|
|
+ _batch->draw(textBatch->_vertices, textBatch->_vertexCount, textBatch->_indices, textBatch->_indexCount);
|
|
|
+}
|
|
|
+
|
|
|
+void Font::drawText(const char* text, int x, int y, const Vector4& color, unsigned int size, bool rightToLeft)
|
|
|
+{
|
|
|
+ if (size == 0)
|
|
|
+ size = _size;
|
|
|
+ float scale = (float)size / _size;
|
|
|
+ const char* cursor = NULL;
|
|
|
+
|
|
|
+ if (rightToLeft)
|
|
|
+ {
|
|
|
+ cursor = text;
|
|
|
+ }
|
|
|
+
|
|
|
+ int xPos = x, yPos = y;
|
|
|
+ bool done = false;
|
|
|
+
|
|
|
+ while (!done)
|
|
|
+ {
|
|
|
+ int length;
|
|
|
+ int startIndex;
|
|
|
+ int iteration;
|
|
|
+ if (rightToLeft)
|
|
|
{
|
|
|
- // Go a line at a time.
|
|
|
- while (token[0] != 0)
|
|
|
+ char delimiter = cursor[0];
|
|
|
+ while (!done &&
|
|
|
+ (delimiter == ' ' ||
|
|
|
+ delimiter == '\t' ||
|
|
|
+ delimiter == '\r' ||
|
|
|
+ delimiter == '\n' ||
|
|
|
+ delimiter == 0))
|
|
|
{
|
|
|
- char delimiter = token[0];
|
|
|
- while (delimiter == '\n')
|
|
|
+ switch (delimiter)
|
|
|
{
|
|
|
- yPos += (int)size;
|
|
|
- ++token;
|
|
|
- delimiter = token[0];
|
|
|
+ case ' ':
|
|
|
+ xPos += size >> 1;
|
|
|
+ break;
|
|
|
+ case '\r':
|
|
|
+ case '\n':
|
|
|
+ yPos += size;
|
|
|
+ xPos = x;
|
|
|
+ break;
|
|
|
+ case '\t':
|
|
|
+ xPos += (size >> 1)*4;
|
|
|
+ break;
|
|
|
+ case 0:
|
|
|
+ done = true;
|
|
|
+ break;
|
|
|
}
|
|
|
|
|
|
- unsigned int tokenLength = strcspn(token, "\n");
|
|
|
- if (tokenLength == 0)
|
|
|
+ if (!done)
|
|
|
{
|
|
|
- tokenLength = strlen(token);
|
|
|
+ ++cursor;
|
|
|
+ delimiter = cursor[0];
|
|
|
}
|
|
|
+ }
|
|
|
|
|
|
- int lineWidth = getTokenWidth(token, tokenLength, size, scale);
|
|
|
- addLineInfo(area, lineWidth, tokenLength, hAlign, &xPositions, &lineLengths, rightToLeft);
|
|
|
+ length = strcspn(cursor, "\r\n");
|
|
|
+ startIndex = length - 1;
|
|
|
+ iteration = -1;
|
|
|
+ }
|
|
|
+ else
|
|
|
+ {
|
|
|
+ length = strlen(text);
|
|
|
+ startIndex = 0;
|
|
|
+ iteration = 1;
|
|
|
+ }
|
|
|
|
|
|
- token += tokenLength;
|
|
|
+ for (int i = startIndex; i < length && i >= 0; i += iteration)
|
|
|
+ {
|
|
|
+ char c = 0;
|
|
|
+ if (rightToLeft)
|
|
|
+ {
|
|
|
+ c = cursor[i];
|
|
|
}
|
|
|
-
|
|
|
- int textHeight = yPos - area.y;
|
|
|
- int vWhiteSpace = areaHeight - textHeight;
|
|
|
- if (vAlign == ALIGN_VCENTER)
|
|
|
+ else
|
|
|
{
|
|
|
- yPos = area.y + vWhiteSpace / 2;
|
|
|
+ c = text[i];
|
|
|
}
|
|
|
- else if (vAlign == ALIGN_BOTTOM)
|
|
|
+
|
|
|
+ // Draw this character.
|
|
|
+ switch (c)
|
|
|
{
|
|
|
- yPos = area.y + vWhiteSpace;
|
|
|
+ case ' ':
|
|
|
+ xPos += size >> 1;
|
|
|
+ break;
|
|
|
+ case '\r':
|
|
|
+ case '\n':
|
|
|
+ yPos += size;
|
|
|
+ xPos = x;
|
|
|
+ break;
|
|
|
+ case '\t':
|
|
|
+ xPos += (size >> 1)*4;
|
|
|
+ break;
|
|
|
+ default:
|
|
|
+ int index = c - 32; // HACK for ASCII
|
|
|
+ if (index >= 0 && index < (int)_glyphCount)
|
|
|
+ {
|
|
|
+ Glyph& g = _glyphs[index];
|
|
|
+ _batch->draw(xPos, yPos, g.width * scale, size, g.uvs[0], g.uvs[1], g.uvs[2], g.uvs[3], color);
|
|
|
+ xPos += floor(g.width * scale + (float)(size >> 3));
|
|
|
+ break;
|
|
|
+ }
|
|
|
}
|
|
|
}
|
|
|
|
|
|
- if (vAlign == ALIGN_TOP)
|
|
|
+ if (rightToLeft)
|
|
|
+ {
|
|
|
+ cursor += length;
|
|
|
+ }
|
|
|
+ else
|
|
|
{
|
|
|
- yPos = area.y;
|
|
|
+ done = true;
|
|
|
}
|
|
|
}
|
|
|
+}
|
|
|
+
|
|
|
+void Font::drawText(const char* text, const Rectangle& area, const Vector4& color, unsigned int size, Justify justify, bool wrap, bool rightToLeft, const Rectangle* clip)
|
|
|
+{
|
|
|
+ if (size == 0)
|
|
|
+ size = _size;
|
|
|
+ float scale = (float)size / _size;
|
|
|
+ const int length = strlen(text);
|
|
|
+ int yPos = area.y;
|
|
|
+ const float areaHeight = area.height - size;
|
|
|
+ std::vector<int> xPositions;
|
|
|
+ std::vector<unsigned int> lineLengths;
|
|
|
+
|
|
|
+ getMeasurementInfo(text, area, size, justify, wrap, rightToLeft, &xPositions, &yPos, &lineLengths);
|
|
|
|
|
|
// Now we have the info we need in order to render.
|
|
|
int xPos = area.x;
|
|
|
@@ -486,8 +541,7 @@ void Font::drawText(const char* text, const Rectangle& area, const Vector4& colo
|
|
|
xPos = *xPositionsIt++;
|
|
|
}
|
|
|
|
|
|
- token = text;
|
|
|
-
|
|
|
+ const char* token = text;
|
|
|
int iteration = 1;
|
|
|
unsigned int lineLength;
|
|
|
unsigned int currentLineLength = 0;
|
|
|
@@ -1213,187 +1267,14 @@ int Font::getIndexOrLocation(const char* text, const Rectangle& area, unsigned i
|
|
|
|
|
|
// Essentially need to measure text until we reach inLocation.
|
|
|
float scale = (float)size / _size;
|
|
|
- const char* token = text;
|
|
|
const int length = strlen(text);
|
|
|
int yPos = area.y;
|
|
|
const float areaHeight = area.height - size;
|
|
|
-
|
|
|
- Justify vAlign = static_cast<Justify>(justify & 0xF0);
|
|
|
- if (vAlign == 0)
|
|
|
- {
|
|
|
- vAlign = ALIGN_TOP;
|
|
|
- }
|
|
|
-
|
|
|
- Justify hAlign = static_cast<Justify>(justify & 0x0F);
|
|
|
- if (hAlign == 0)
|
|
|
- {
|
|
|
- hAlign = ALIGN_LEFT;
|
|
|
- }
|
|
|
-
|
|
|
- token = text;
|
|
|
-
|
|
|
- // For alignments other than top-left, need to calculate the y position to begin drawing from
|
|
|
- // and the starting x position of each line. For right-to-left text, need to determine
|
|
|
- // the number of characters on each line.
|
|
|
std::vector<int> xPositions;
|
|
|
std::vector<unsigned int> lineLengths;
|
|
|
- if (vAlign != ALIGN_TOP || hAlign != ALIGN_LEFT || rightToLeft)
|
|
|
- {
|
|
|
- int lineWidth = 0;
|
|
|
- int delimWidth = 0;
|
|
|
-
|
|
|
- if (wrap)
|
|
|
- {
|
|
|
- // Go a word at a time.
|
|
|
- bool reachedEOF = false;
|
|
|
- unsigned int lineLength = 0;
|
|
|
- while (token[0] != 0)
|
|
|
- {
|
|
|
- unsigned int tokenWidth = 0;
|
|
|
-
|
|
|
- // Handle delimiters until next token.
|
|
|
- char delimiter = token[0];
|
|
|
- while (delimiter == ' ' ||
|
|
|
- delimiter == '\t' ||
|
|
|
- delimiter == '\r' ||
|
|
|
- delimiter == '\n' ||
|
|
|
- delimiter == 0)
|
|
|
- {
|
|
|
- switch (delimiter)
|
|
|
- {
|
|
|
- case ' ':
|
|
|
- delimWidth += size >> 1;
|
|
|
- lineLength++;
|
|
|
- break;
|
|
|
- case '\r':
|
|
|
- case '\n':
|
|
|
- yPos += size;
|
|
|
-
|
|
|
- if (lineWidth > 0)
|
|
|
- {
|
|
|
- addLineInfo(area, lineWidth, lineLength, hAlign, &xPositions, &lineLengths, rightToLeft);
|
|
|
- }
|
|
|
-
|
|
|
- lineWidth = 0;
|
|
|
- lineLength = 0;
|
|
|
- delimWidth = 0;
|
|
|
- break;
|
|
|
- case '\t':
|
|
|
- delimWidth += (size >> 1)*4;
|
|
|
- lineLength++;
|
|
|
- break;
|
|
|
- case 0:
|
|
|
- reachedEOF = true;
|
|
|
- break;
|
|
|
- }
|
|
|
-
|
|
|
- if (reachedEOF)
|
|
|
- {
|
|
|
- break;
|
|
|
- }
|
|
|
-
|
|
|
- token++;
|
|
|
- delimiter = token[0];
|
|
|
- }
|
|
|
-
|
|
|
- if (reachedEOF || token == NULL)
|
|
|
- {
|
|
|
- break;
|
|
|
- }
|
|
|
-
|
|
|
- unsigned int tokenLength = strcspn(token, " \r\n\t");
|
|
|
- tokenWidth += getTokenWidth(token, tokenLength, size, scale);
|
|
|
-
|
|
|
- // Wrap if necessary.
|
|
|
- if (lineWidth + tokenWidth + delimWidth > area.width)
|
|
|
- {
|
|
|
- yPos += size;
|
|
|
-
|
|
|
- // Push position of current line.
|
|
|
- if (lineLength)
|
|
|
- {
|
|
|
- addLineInfo(area, lineWidth, lineLength-1, hAlign, &xPositions, &lineLengths, rightToLeft);
|
|
|
- }
|
|
|
- else
|
|
|
- {
|
|
|
- addLineInfo(area, lineWidth, tokenLength, hAlign, &xPositions, &lineLengths, rightToLeft);
|
|
|
- }
|
|
|
-
|
|
|
- // Move token to the next line.
|
|
|
- lineWidth = 0;
|
|
|
- lineLength = 0;
|
|
|
- delimWidth = 0;
|
|
|
- }
|
|
|
- else
|
|
|
- {
|
|
|
- lineWidth += delimWidth;
|
|
|
- delimWidth = 0;
|
|
|
- }
|
|
|
-
|
|
|
- lineWidth += tokenWidth;
|
|
|
- lineLength += tokenLength;
|
|
|
- token += tokenLength;
|
|
|
- }
|
|
|
-
|
|
|
- // Final calculation of vertical position.
|
|
|
- int textHeight = yPos - area.y;
|
|
|
- int vWhiteSpace = areaHeight - textHeight;
|
|
|
- if (vAlign == ALIGN_VCENTER)
|
|
|
- {
|
|
|
- yPos = area.y + vWhiteSpace / 2;
|
|
|
- }
|
|
|
- else if (vAlign == ALIGN_BOTTOM)
|
|
|
- {
|
|
|
- yPos = area.y + vWhiteSpace;
|
|
|
- }
|
|
|
-
|
|
|
- // Calculation of final horizontal position.
|
|
|
- addLineInfo(area, lineWidth, lineLength, hAlign, &xPositions, &lineLengths, rightToLeft);
|
|
|
- }
|
|
|
- else
|
|
|
- {
|
|
|
- // Go a line at a time.
|
|
|
- while (token[0] != 0)
|
|
|
- {
|
|
|
- char delimiter = token[0];
|
|
|
- while (delimiter == '\n')
|
|
|
- {
|
|
|
- yPos += size;
|
|
|
- ++token;
|
|
|
- delimiter = token[0];
|
|
|
- }
|
|
|
-
|
|
|
- unsigned int tokenLength = strcspn(token, "\n");
|
|
|
- if (tokenLength == 0)
|
|
|
- {
|
|
|
- tokenLength = strlen(token);
|
|
|
- }
|
|
|
-
|
|
|
- int lineWidth = getTokenWidth(token, tokenLength, size, scale);
|
|
|
- addLineInfo(area, lineWidth, tokenLength, hAlign, &xPositions, &lineLengths, rightToLeft);
|
|
|
-
|
|
|
- token += tokenLength;
|
|
|
- }
|
|
|
-
|
|
|
- int textHeight = yPos - area.y;
|
|
|
- int vWhiteSpace = areaHeight - textHeight;
|
|
|
- if (vAlign == ALIGN_VCENTER)
|
|
|
- {
|
|
|
- yPos = area.y + vWhiteSpace / 2;
|
|
|
- }
|
|
|
- else if (vAlign == ALIGN_BOTTOM)
|
|
|
- {
|
|
|
- yPos = area.y + vWhiteSpace;
|
|
|
- }
|
|
|
- }
|
|
|
|
|
|
- if (vAlign == ALIGN_TOP)
|
|
|
- {
|
|
|
- yPos = area.y;
|
|
|
- }
|
|
|
- }
|
|
|
+ getMeasurementInfo(text, area, size, justify, wrap, rightToLeft, &xPositions, &yPos, &lineLengths);
|
|
|
|
|
|
- // Now we have the info we need in order to render.
|
|
|
int xPos = area.x;
|
|
|
std::vector<int>::const_iterator xPositionsIt = xPositions.begin();
|
|
|
if (xPositionsIt != xPositions.end())
|
|
|
@@ -1401,7 +1282,7 @@ int Font::getIndexOrLocation(const char* text, const Rectangle& area, unsigned i
|
|
|
xPos = *xPositionsIt++;
|
|
|
}
|
|
|
|
|
|
- token = text;
|
|
|
+ const char* token = text;
|
|
|
|
|
|
int iteration = 1;
|
|
|
unsigned int lineLength;
|
|
|
@@ -1833,4 +1714,23 @@ Font::Justify Font::getJustify(const char* justify)
|
|
|
return Font::ALIGN_TOP_LEFT;
|
|
|
}
|
|
|
|
|
|
+Font::Text::Text(const char* text) : _vertexCount(0), _indexCount(0)
|
|
|
+{
|
|
|
+ _text = text;
|
|
|
+ const int length = strlen(text);
|
|
|
+ _vertices = new SpriteBatch::SpriteVertex[length * 4];
|
|
|
+ _indices = new unsigned short[((length - 1) * 6) + 4];
|
|
|
+}
|
|
|
+
|
|
|
+Font::Text::~Text()
|
|
|
+{
|
|
|
+ SAFE_DELETE_ARRAY(_vertices);
|
|
|
+ SAFE_DELETE_ARRAY(_indices);
|
|
|
+}
|
|
|
+
|
|
|
+const char* Font::Text::getText()
|
|
|
+{
|
|
|
+ return _text.c_str();
|
|
|
+}
|
|
|
+
|
|
|
}
|