summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorBjörn Steinbrink <B.Steinbrink@gmx.de>2007-09-21 03:58:07 +0000
committerBjørn Lindeijer <bjorn@lindeijer.nl>2009-01-05 19:32:55 +0100
commit4e439b3115c487dc67dbe2cd5aaab1e15f3d09e8 (patch)
tree2d5fe06101f0b1b7177e3a3881a945bd117d7770
parent615b1bc6080a3418b18fd4ab93b4212470709731 (diff)
downloadmana-4e439b3115c487dc67dbe2cd5aaab1e15f3d09e8.tar.gz
mana-4e439b3115c487dc67dbe2cd5aaab1e15f3d09e8.tar.bz2
mana-4e439b3115c487dc67dbe2cd5aaab1e15f3d09e8.tar.xz
mana-4e439b3115c487dc67dbe2cd5aaab1e15f3d09e8.zip
Refactor the way in which browser box text is drawn and wrapped.
(cherry picked from mainline commit ecabe82d8720689905a6d035b0597d97037287c7) Conflicts: src/gui/browserbox.cpp
-rw-r--r--src/gui/browserbox.cpp139
1 files changed, 74 insertions, 65 deletions
diff --git a/src/gui/browserbox.cpp b/src/gui/browserbox.cpp
index 3e446928..80e41fc2 100644
--- a/src/gui/browserbox.cpp
+++ b/src/gui/browserbox.cpp
@@ -21,11 +21,8 @@
#include <algorithm>
-#include <guichan/graphics.hpp>
-#include <guichan/imagefont.hpp>
-#include <guichan/mouseinput.hpp>
-
#include "browserbox.h"
+
#include "linkhandler.h"
#include "truetypefont.h"
@@ -143,7 +140,7 @@ void BrowserBox::addRow(const std::string &row)
if (mMode == AUTO_WRAP)
{
- unsigned int j, y = 0;
+ unsigned int y = 0;
unsigned int nextChar;
const char *hyphen = "~";
int hyphenWidth = font->getWidth(hyphen);
@@ -152,7 +149,7 @@ void BrowserBox::addRow(const std::string &row)
for (TextRowIterator i = mTextRows.begin(); i != mTextRows.end(); i++)
{
std::string row = *i;
- for (j = 0; j < row.size(); j++)
+ for (unsigned int j = 0; j < row.size(); j++)
{
std::string character = row.substr(j, 1);
x += font->getWidth(character);
@@ -266,7 +263,6 @@ BrowserBox::draw(gcn::Graphics *graphics)
}
}
- unsigned int j;
int x = 0, y = 0;
int wrappedLines = 0;
TrueTypeFont *font = static_cast<TrueTypeFont*>(getFont());
@@ -277,17 +273,45 @@ BrowserBox::draw(gcn::Graphics *graphics)
int selColor = BLACK;
int prevColor = selColor;
std::string row = *(i);
+ bool wrapped = false;
x = 0;
- for (j = 0; j < row.size(); j++)
+ // Check for separator lines
+ if (row.find("---", 0) == 0)
+ {
+ for (x = 0; x < getWidth(); x++)
+ {
+ font->drawString(graphics, "-", x, y);
+ x += font->getWidth("-") - 2;
+ }
+ y += font->getHeight();
+ continue;
+ }
+
+ // TODO: Check if we must take texture size limits into account here
+ // TODO: Check if some of the O(n) calls can be removed
+ for (std::string::size_type start = 0, end = std::string::npos;
+ start != std::string::npos;
+ start = end, end = std::string::npos)
{
- if ( (mUseLinksAndUserColors && (j + 3) <= row.size()) ||
- (!mUseLinksAndUserColors && (j == 0)) )
+ // Wrapped line continuation shall be indented
+ if (wrapped)
+ {
+ y += font->getHeight();
+ x = 15;
+ }
+
+ // "Tokenize" the string at control sequences
+ if (mUseLinksAndUserColors)
+ end = row.find("##", start + 1);
+
+ if (mUseLinksAndUserColors ||
+ (!mUseLinksAndUserColors && (start == 0)))
{
// Check for color change in format "##x", x = [L,P,0..9]
- if ((row.at(j) == '#') && (row.at(j + 1) == '#'))
+ if (row.find("##", start) == start && row.size() > start + 2)
{
- switch (row.at(j + 2))
+ switch (row.at(start + 2))
{
case 'L': // Link color
prevColor = selColor;
@@ -337,72 +361,57 @@ BrowserBox::draw(gcn::Graphics *graphics)
prevColor = selColor;
selColor = BLACK;
}
- j += 3;
-
- if (j == row.size())
- {
- break;
- }
+ start += 3;
}
graphics->setColor(gcn::Color(selColor));
}
- // Check for line separators in format "---"
- if (row == "---")
- {
- for (x = 0; x < getWidth(); x++)
- {
- font->drawString(graphics, "-", x, y);
- x += font->getWidth("-") - 2;
- }
- break;
- }
- // Draw each char
- else
+ std::string::size_type len =
+ end == std::string::npos ? end : end - start;
+ std::string part = row.substr(start, len);
+
+ // Auto wrap mode
+ if (mMode == AUTO_WRAP &&
+ (x + font->getWidth(part.c_str()) + 10) > getWidth())
{
- std::string character = row.substr(j, 1);
- font->drawString(graphics, character, x, y);
- x += font->getWidth(character.c_str());
+ bool forced = false;
+ char const *hyphen = "~";
+ int hyphenWidth = font->getWidth(hyphen);
- // Auto wrap mode
- if (mMode == AUTO_WRAP)
+ do
{
- unsigned int nextChar = j + 1;
- const char *hyphen = "~";
- int hyphenWidth = font->getWidth(hyphen);
+ if (!forced)
+ end = row.rfind(" ", end);
- // Wraping between words (at blank spaces)
- if ((nextChar < row.size()) && (row.at(nextChar) == ' '))
+ // Check if we have to (stupidly) force-wrap
+ if (end == std::string::npos || end <= start)
{
- int nextSpacePos = row.find(" ", (nextChar + 1));
- if (nextSpacePos <= 0)
- {
- nextSpacePos = row.size() - 1;
- }
- int nextWordWidth = font->getWidth(
- row.substr(nextChar,
- (nextSpacePos - nextChar)));
-
- if ((x + nextWordWidth + 10) > getWidth())
- {
- x = 15; // Ident in new line
- y += font->getHeight();
- wrappedLines++;
- j++;
- }
+ forced = true;
+ end = row.size();
+ x += hyphenWidth * 2; // Account for the wrap-notifier
+ continue;
}
- // Wrapping looong lines (brutal force)
- else if ((x + 2 * hyphenWidth) > getWidth())
- {
- font->drawString(graphics, hyphen,
- getWidth() - hyphenWidth, y);
- x = 15; // Ident in new line
- y += font->getHeight();
- wrappedLines++;
- }
+ end--;
+
+ part = row.substr(start, end - start + 1);
+ } while ((x + font->getWidth(part.c_str()) + 10) > getWidth());
+
+ if (forced)
+ {
+ x -= hyphenWidth; // Remove the wrap-notifier accounting
+ font->drawString(graphics, hyphen,
+ getWidth() - hyphenWidth, y);
+ end++; // Skip to the next character
}
+ else
+ end += 2; // Skip to after the space
+
+ wrapped = true;
+ wrappedLines++;
}
+ font->drawString(graphics, part, x, y);
+ x += font->getWidth(part.c_str());
}
y += font->getHeight();
setHeight((mTextRows.size() + wrappedLines) * font->getHeight());