|
|
@ -11,68 +11,14 @@
|
|
|
|
#include <boost/lexical_cast.hpp>
|
|
|
|
#include <boost/lexical_cast.hpp>
|
|
|
|
#include <boost/range/adaptor/filtered.hpp>
|
|
|
|
#include <boost/range/adaptor/filtered.hpp>
|
|
|
|
#include <boost/range/algorithm/copy.hpp>
|
|
|
|
#include <boost/range/algorithm/copy.hpp>
|
|
|
|
#include <OgreUTFString.h>
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
#include <OgreUTFString.h>
|
|
|
|
#include <OgreResourceGroupManager.h>
|
|
|
|
#include <OgreResourceGroupManager.h>
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
#include <MyGUI_EditText.h>
|
|
|
|
|
|
|
|
|
|
|
|
namespace
|
|
|
|
namespace
|
|
|
|
{
|
|
|
|
{
|
|
|
|
int convertFromHex(std::string hex)
|
|
|
|
|
|
|
|
{
|
|
|
|
|
|
|
|
int value = 0;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
int a = 0;
|
|
|
|
|
|
|
|
int b = hex.length() - 1;
|
|
|
|
|
|
|
|
for (; b >= 0; a++, b--)
|
|
|
|
|
|
|
|
{
|
|
|
|
|
|
|
|
if (hex[b] >= '0' && hex[b] <= '9')
|
|
|
|
|
|
|
|
{
|
|
|
|
|
|
|
|
value += (hex[b] - '0') * (1 << (a * 4));
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
else
|
|
|
|
|
|
|
|
{
|
|
|
|
|
|
|
|
switch (hex[b])
|
|
|
|
|
|
|
|
{
|
|
|
|
|
|
|
|
case 'A':
|
|
|
|
|
|
|
|
case 'a':
|
|
|
|
|
|
|
|
value += 10 * (1 << (a * 4));
|
|
|
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
case 'B':
|
|
|
|
|
|
|
|
case 'b':
|
|
|
|
|
|
|
|
value += 11 * (1 << (a * 4));
|
|
|
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
case 'C':
|
|
|
|
|
|
|
|
case 'c':
|
|
|
|
|
|
|
|
value += 12 * (1 << (a * 4));
|
|
|
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
case 'D':
|
|
|
|
|
|
|
|
case 'd':
|
|
|
|
|
|
|
|
value += 13 * (1 << (a * 4));
|
|
|
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
case 'E':
|
|
|
|
|
|
|
|
case 'e':
|
|
|
|
|
|
|
|
value += 14 * (1 << (a * 4));
|
|
|
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
case 'F':
|
|
|
|
|
|
|
|
case 'f':
|
|
|
|
|
|
|
|
value += 15 * (1 << (a * 4));
|
|
|
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
default:
|
|
|
|
|
|
|
|
throw std::runtime_error("invalid character in hex number");
|
|
|
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
return value;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
Ogre::UTFString::unicode_char unicodeCharFromChar(char ch)
|
|
|
|
Ogre::UTFString::unicode_char unicodeCharFromChar(char ch)
|
|
|
|
{
|
|
|
|
{
|
|
|
|
std::string s;
|
|
|
|
std::string s;
|
|
|
@ -80,56 +26,56 @@ namespace
|
|
|
|
Ogre::UTFString string(s);
|
|
|
|
Ogre::UTFString string(s);
|
|
|
|
return string.getChar(0);
|
|
|
|
return string.getChar(0);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
bool is_not_empty(const std::string& s) {
|
|
|
|
|
|
|
|
std::string temp = s;
|
|
|
|
|
|
|
|
boost::algorithm::trim(temp);
|
|
|
|
|
|
|
|
return !temp.empty();
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
namespace MWGui
|
|
|
|
namespace MWGui
|
|
|
|
{
|
|
|
|
{
|
|
|
|
|
|
|
|
namespace Formatting
|
|
|
|
std::vector<std::string> BookTextParser::split(std::string utf8Text, const int width, const int height)
|
|
|
|
|
|
|
|
{
|
|
|
|
{
|
|
|
|
using Ogre::UTFString;
|
|
|
|
Paginator::Pages BookFormatter::markupToWidget(MyGUI::Widget * parent, std::string utf8Text, const int pageWidth, const int pageHeight)
|
|
|
|
std::vector<std::string> result;
|
|
|
|
{
|
|
|
|
|
|
|
|
using Ogre::UTFString;
|
|
|
|
|
|
|
|
|
|
|
|
MWScript::InterpreterContext interpreterContext(NULL, MWWorld::Ptr()); // empty arguments, because there is no locals or actor
|
|
|
|
MWScript::InterpreterContext interpreterContext(NULL, MWWorld::Ptr()); // empty arguments, because there is no locals or actor
|
|
|
|
utf8Text = Interpreter::fixDefinesBook(utf8Text, interpreterContext);
|
|
|
|
utf8Text = Interpreter::fixDefinesBook(utf8Text, interpreterContext);
|
|
|
|
|
|
|
|
|
|
|
|
boost::algorithm::replace_all(utf8Text, "\n", "");
|
|
|
|
boost::algorithm::replace_all(utf8Text, "\n", "");
|
|
|
|
boost::algorithm::replace_all(utf8Text, "\r", "");
|
|
|
|
boost::algorithm::replace_all(utf8Text, "\r", "");
|
|
|
|
boost::algorithm::replace_all(utf8Text, "<BR>", "\n");
|
|
|
|
boost::algorithm::replace_all(utf8Text, "<BR>", "\n");
|
|
|
|
boost::algorithm::replace_all(utf8Text, "<P>", "\n\n");
|
|
|
|
boost::algorithm::replace_all(utf8Text, "<P>", "\n\n");
|
|
|
|
|
|
|
|
|
|
|
|
UTFString text(utf8Text);
|
|
|
|
UTFString text(utf8Text);
|
|
|
|
const int spacing = 48;
|
|
|
|
UTFString plainText;
|
|
|
|
|
|
|
|
|
|
|
|
const UTFString::unicode_char LEFT_ANGLE = unicodeCharFromChar('<');
|
|
|
|
const UTFString::unicode_char LEFT_ANGLE = unicodeCharFromChar('<');
|
|
|
|
const UTFString::unicode_char NEWLINE = unicodeCharFromChar('\n');
|
|
|
|
const UTFString::unicode_char NEWLINE = unicodeCharFromChar('\n');
|
|
|
|
const UTFString::unicode_char SPACE = unicodeCharFromChar(' ');
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
while (!text.empty())
|
|
|
|
Paginator pag(pageWidth, pageHeight);
|
|
|
|
{
|
|
|
|
|
|
|
|
// read in characters until we have exceeded the size, or run out of text
|
|
|
|
|
|
|
|
int currentWidth = 0;
|
|
|
|
|
|
|
|
int currentHeight = 0;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
size_t currentWordStart = 0;
|
|
|
|
while (parent->getChildCount())
|
|
|
|
size_t index = 0;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
{
|
|
|
|
{
|
|
|
|
std::string texToTrim = text.asUTF8();
|
|
|
|
MyGUI::Gui::getInstance().destroyWidget(parent->getChildAt(0));
|
|
|
|
boost::algorithm::trim( texToTrim );
|
|
|
|
|
|
|
|
text = UTFString(texToTrim);
|
|
|
|
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
MyGUI::Widget * paper = parent->createWidget<MyGUI::Widget>("Widget", MyGUI::IntCoord(0, 0, pag.getPageWidth(), pag.getPageHeight()), MyGUI::Align::Left | MyGUI::Align::Top);
|
|
|
|
while (currentHeight <= height - spacing && index < text.size())
|
|
|
|
paper->setNeedMouseFocus(false);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
bool ignoreNewlines = true;
|
|
|
|
|
|
|
|
for (size_t index = 0; index < text.size(); ++index)
|
|
|
|
{
|
|
|
|
{
|
|
|
|
const UTFString::unicode_char ch = text.getChar(index);
|
|
|
|
const UTFString::unicode_char ch = text.getChar(index);
|
|
|
|
|
|
|
|
if (!plainText.empty() && (ch == LEFT_ANGLE || index == text.size() - 1))
|
|
|
|
|
|
|
|
{
|
|
|
|
|
|
|
|
// if there's a newline at the end of the box caption, remove it
|
|
|
|
|
|
|
|
if (plainText[plainText.size()-1] == NEWLINE)
|
|
|
|
|
|
|
|
plainText.erase(plainText.end()-1);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
TextElement elem(paper, pag, mTextStyle, plainText.asUTF8());
|
|
|
|
|
|
|
|
elem.paginate();
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
plainText.clear();
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
if (ch == LEFT_ANGLE)
|
|
|
|
if (ch == LEFT_ANGLE)
|
|
|
|
{
|
|
|
|
{
|
|
|
|
const size_t tagStart = index + 1;
|
|
|
|
const size_t tagStart = index + 1;
|
|
|
@ -140,263 +86,203 @@ namespace MWGui
|
|
|
|
|
|
|
|
|
|
|
|
if (boost::algorithm::starts_with(tag, "IMG"))
|
|
|
|
if (boost::algorithm::starts_with(tag, "IMG"))
|
|
|
|
{
|
|
|
|
{
|
|
|
|
const int h = mHeight;
|
|
|
|
ImageElement elem(paper, pag, mTextStyle, tag);
|
|
|
|
parseImage(tag, false);
|
|
|
|
elem.paginate();
|
|
|
|
currentHeight += (mHeight - h);
|
|
|
|
|
|
|
|
currentWidth = 0;
|
|
|
|
ignoreNewlines = false;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else if (boost::algorithm::starts_with(tag, "FONT"))
|
|
|
|
else if (boost::algorithm::starts_with(tag, "FONT"))
|
|
|
|
{
|
|
|
|
{
|
|
|
|
parseFont(tag);
|
|
|
|
parseFont(tag);
|
|
|
|
if (currentWidth != 0) {
|
|
|
|
|
|
|
|
currentHeight += currentFontHeight();
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
currentWidth = 0;
|
|
|
|
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else if (boost::algorithm::starts_with(tag, "DIV"))
|
|
|
|
else if (boost::algorithm::starts_with(tag, "DIV"))
|
|
|
|
{
|
|
|
|
{
|
|
|
|
parseDiv(tag);
|
|
|
|
parseDiv(tag);
|
|
|
|
if (currentWidth != 0) {
|
|
|
|
|
|
|
|
currentHeight += currentFontHeight();
|
|
|
|
|
|
|
|
currentWidth = 0;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
index = tagEnd;
|
|
|
|
index = tagEnd;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else if (ch == NEWLINE)
|
|
|
|
|
|
|
|
{
|
|
|
|
|
|
|
|
currentHeight += currentFontHeight();
|
|
|
|
|
|
|
|
currentWidth = 0;
|
|
|
|
|
|
|
|
currentWordStart = index;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
else if (ch == SPACE)
|
|
|
|
|
|
|
|
{
|
|
|
|
|
|
|
|
currentWidth += 3; // keep this in sync with the font's SpaceWidth property
|
|
|
|
|
|
|
|
currentWordStart = index;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
else
|
|
|
|
else
|
|
|
|
{
|
|
|
|
{
|
|
|
|
currentWidth += widthForCharGlyph(ch);
|
|
|
|
if (!ignoreNewlines || ch != NEWLINE)
|
|
|
|
}
|
|
|
|
{
|
|
|
|
|
|
|
|
plainText.push_back(ch);
|
|
|
|
if (currentWidth > width)
|
|
|
|
ignoreNewlines = false;
|
|
|
|
{
|
|
|
|
}
|
|
|
|
currentHeight += currentFontHeight();
|
|
|
|
|
|
|
|
currentWidth = 0;
|
|
|
|
|
|
|
|
// add size of the current word
|
|
|
|
|
|
|
|
UTFString word = text.substr(currentWordStart, index - currentWordStart);
|
|
|
|
|
|
|
|
for (UTFString::const_iterator it = word.begin(), end = word.end(); it != end; ++it)
|
|
|
|
|
|
|
|
currentWidth += widthForCharGlyph(it.getCharacter());
|
|
|
|
|
|
|
|
}
|
|
|
|
}
|
|
|
|
index += UTFString::_utf16_char_length(ch);
|
|
|
|
|
|
|
|
}
|
|
|
|
}
|
|
|
|
const size_t pageEnd = (currentHeight > height - spacing && currentWordStart != 0)
|
|
|
|
|
|
|
|
? currentWordStart : index;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
result.push_back(text.substr(0, pageEnd).asUTF8());
|
|
|
|
// insert last page
|
|
|
|
text.erase(0, pageEnd);
|
|
|
|
pag << Paginator::Page(pag.getStartTop(), pag.getStartTop() + pag.getPageHeight());
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
std::vector<std::string> nonEmptyPages;
|
|
|
|
|
|
|
|
boost::copy(result | boost::adaptors::filtered(is_not_empty), std::back_inserter(nonEmptyPages));
|
|
|
|
|
|
|
|
return nonEmptyPages;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
float BookTextParser::widthForCharGlyph(unsigned unicodeChar) const
|
|
|
|
|
|
|
|
{
|
|
|
|
|
|
|
|
std::string fontName(mTextStyle.mFont == "Default" ? MyGUI::FontManager::getInstance().getDefaultFont() : mTextStyle.mFont);
|
|
|
|
|
|
|
|
return MyGUI::FontManager::getInstance().getByName(fontName)
|
|
|
|
|
|
|
|
->getGlyphInfo(unicodeChar)->width;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
float BookTextParser::currentFontHeight() const
|
|
|
|
|
|
|
|
{
|
|
|
|
|
|
|
|
std::string fontName(mTextStyle.mFont == "Default" ? MyGUI::FontManager::getInstance().getDefaultFont() : mTextStyle.mFont);
|
|
|
|
|
|
|
|
return MyGUI::FontManager::getInstance().getByName(fontName)->getDefaultHeight();
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
MyGUI::IntSize BookTextParser::parsePage(std::string text, MyGUI::Widget* parent, const int width)
|
|
|
|
paper->setSize(paper->getWidth(), pag.getCurrentTop());
|
|
|
|
{
|
|
|
|
|
|
|
|
MWScript::InterpreterContext interpreterContext(NULL, MWWorld::Ptr()); // empty arguments, because there is no locals or actor
|
|
|
|
|
|
|
|
text = Interpreter::fixDefinesBook(text, interpreterContext);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
mParent = parent;
|
|
|
|
return pag.getPages();
|
|
|
|
mWidth = width;
|
|
|
|
}
|
|
|
|
mHeight = 0;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
assert(mParent);
|
|
|
|
Paginator::Pages BookFormatter::markupToWidget(MyGUI::Widget * parent, std::string utf8Text)
|
|
|
|
while (mParent->getChildCount())
|
|
|
|
|
|
|
|
{
|
|
|
|
{
|
|
|
|
MyGUI::Gui::getInstance().destroyWidget(mParent->getChildAt(0));
|
|
|
|
return markupToWidget(parent, utf8Text, parent->getWidth(), parent->getHeight());
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// remove trailing "
|
|
|
|
void BookFormatter::parseDiv(std::string tag)
|
|
|
|
if (text[text.size()-1] == '\"')
|
|
|
|
|
|
|
|
text.erase(text.size()-1);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
parseSubText(text);
|
|
|
|
|
|
|
|
return MyGUI::IntSize(mWidth, mHeight);
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
MyGUI::IntSize BookTextParser::parseScroll(std::string text, MyGUI::Widget* parent, const int width)
|
|
|
|
|
|
|
|
{
|
|
|
|
|
|
|
|
MWScript::InterpreterContext interpreterContext(NULL, MWWorld::Ptr()); // empty arguments, because there is no locals or actor
|
|
|
|
|
|
|
|
text = Interpreter::fixDefinesBook(text, interpreterContext);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
mParent = parent;
|
|
|
|
|
|
|
|
mWidth = width;
|
|
|
|
|
|
|
|
mHeight = 0;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
assert(mParent);
|
|
|
|
|
|
|
|
while (mParent->getChildCount())
|
|
|
|
|
|
|
|
{
|
|
|
|
{
|
|
|
|
MyGUI::Gui::getInstance().destroyWidget(mParent->getChildAt(0));
|
|
|
|
if (tag.find("ALIGN=") == std::string::npos)
|
|
|
|
|
|
|
|
return;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
int align_start = tag.find("ALIGN=")+7;
|
|
|
|
|
|
|
|
std::string align = tag.substr(align_start, tag.find('"', align_start)-align_start);
|
|
|
|
|
|
|
|
if (align == "CENTER")
|
|
|
|
|
|
|
|
mTextStyle.mTextAlign = MyGUI::Align::HCenter;
|
|
|
|
|
|
|
|
else if (align == "LEFT")
|
|
|
|
|
|
|
|
mTextStyle.mTextAlign = MyGUI::Align::Left;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
boost::algorithm::replace_all(text, "<BR>", "\n");
|
|
|
|
void BookFormatter::parseFont(std::string tag)
|
|
|
|
boost::algorithm::replace_all(text, "<P>", "\n\n");
|
|
|
|
{
|
|
|
|
boost::algorithm::trim_left(text);
|
|
|
|
if (tag.find("COLOR=") != std::string::npos)
|
|
|
|
|
|
|
|
{
|
|
|
|
// remove trailing "
|
|
|
|
int color_start = tag.find("COLOR=")+7;
|
|
|
|
if (text[text.size()-1] == '\"')
|
|
|
|
|
|
|
|
text.erase(text.size()-1);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
parseSubText(text);
|
|
|
|
|
|
|
|
return MyGUI::IntSize(mWidth, mHeight);
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
void BookTextParser::parseImage(std::string tag, bool createWidget)
|
|
|
|
int color;
|
|
|
|
{
|
|
|
|
std::stringstream ss;
|
|
|
|
int src_start = tag.find("SRC=")+5;
|
|
|
|
ss << tag.substr(color_start, tag.find('"', color_start)-color_start);
|
|
|
|
|
|
|
|
ss >> std::hex >> color;
|
|
|
|
|
|
|
|
|
|
|
|
int width_start = tag.find("WIDTH=")+7;
|
|
|
|
mTextStyle.mColour = MyGUI::Colour(
|
|
|
|
int width = boost::lexical_cast<int>(tag.substr(width_start, tag.find('"', width_start)-width_start));
|
|
|
|
(color>>16 & 0xFF) / 255.f,
|
|
|
|
|
|
|
|
(color>>8 & 0xFF) / 255.f,
|
|
|
|
|
|
|
|
(color & 0xFF) / 255.f);
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
if (tag.find("FACE=") != std::string::npos)
|
|
|
|
|
|
|
|
{
|
|
|
|
|
|
|
|
int face_start = tag.find("FACE=")+6;
|
|
|
|
|
|
|
|
std::string face = tag.substr(face_start, tag.find('"', face_start)-face_start);
|
|
|
|
|
|
|
|
|
|
|
|
int height_start = tag.find("HEIGHT=")+8;
|
|
|
|
if (face != "Magic Cards")
|
|
|
|
int height = boost::lexical_cast<int>(tag.substr(height_start, tag.find('"', height_start)-height_start));
|
|
|
|
mTextStyle.mFont = face;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
if (tag.find("SIZE=") != std::string::npos)
|
|
|
|
|
|
|
|
{
|
|
|
|
|
|
|
|
/// \todo
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
if (createWidget)
|
|
|
|
/* GraphicElement */
|
|
|
|
|
|
|
|
GraphicElement::GraphicElement(MyGUI::Widget * parent, Paginator & pag, const TextStyle & style)
|
|
|
|
|
|
|
|
: mParent(parent), mPaginator(pag), mStyle(style)
|
|
|
|
{
|
|
|
|
{
|
|
|
|
MyGUI::ImageBox* box = mParent->createWidget<MyGUI::ImageBox> ("ImageBox",
|
|
|
|
|
|
|
|
MyGUI::IntCoord(0, mHeight, width, height), MyGUI::Align::Left | MyGUI::Align::Top,
|
|
|
|
|
|
|
|
mParent->getName() + boost::lexical_cast<std::string>(mParent->getChildCount()));
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
std::string image = Misc::ResourceHelpers::correctBookartPath(tag.substr(src_start, tag.find('"', src_start)-src_start), width, height);
|
|
|
|
|
|
|
|
box->setImageTexture(image);
|
|
|
|
|
|
|
|
box->setProperty("NeedMouse", "false");
|
|
|
|
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
mWidth = std::max(mWidth, width);
|
|
|
|
void GraphicElement::paginate()
|
|
|
|
mHeight += height;
|
|
|
|
{
|
|
|
|
}
|
|
|
|
int newTop = mPaginator.getCurrentTop() + getHeight();
|
|
|
|
|
|
|
|
while (newTop-mPaginator.getStartTop() > mPaginator.getPageHeight())
|
|
|
|
|
|
|
|
{
|
|
|
|
|
|
|
|
int newStartTop = pageSplit();
|
|
|
|
|
|
|
|
mPaginator << Paginator::Page(mPaginator.getStartTop(), newStartTop);
|
|
|
|
|
|
|
|
mPaginator.setStartTop(newStartTop);
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void BookTextParser::parseDiv(std::string tag)
|
|
|
|
mPaginator.modifyCurrentTop(getHeight());
|
|
|
|
{
|
|
|
|
}
|
|
|
|
if (tag.find("ALIGN=") == std::string::npos)
|
|
|
|
|
|
|
|
return;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
int align_start = tag.find("ALIGN=")+7;
|
|
|
|
|
|
|
|
std::string align = tag.substr(align_start, tag.find('"', align_start)-align_start);
|
|
|
|
|
|
|
|
if (align == "CENTER")
|
|
|
|
|
|
|
|
mTextStyle.mTextAlign = MyGUI::Align::HCenter;
|
|
|
|
|
|
|
|
else if (align == "LEFT")
|
|
|
|
|
|
|
|
mTextStyle.mTextAlign = MyGUI::Align::Left;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
void BookTextParser::parseFont(std::string tag)
|
|
|
|
int GraphicElement::pageSplit()
|
|
|
|
{
|
|
|
|
|
|
|
|
if (tag.find("COLOR=") != std::string::npos)
|
|
|
|
|
|
|
|
{
|
|
|
|
{
|
|
|
|
int color_start = tag.find("COLOR=")+7;
|
|
|
|
return mPaginator.getStartTop() + mPaginator.getPageHeight();
|
|
|
|
std::string color = tag.substr(color_start, tag.find('"', color_start)-color_start);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
mTextStyle.mColour = MyGUI::Colour(
|
|
|
|
|
|
|
|
convertFromHex(color.substr(0, 2))/255.0,
|
|
|
|
|
|
|
|
convertFromHex(color.substr(2, 2))/255.0,
|
|
|
|
|
|
|
|
convertFromHex(color.substr(4, 2))/255.0);
|
|
|
|
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if (tag.find("FACE=") != std::string::npos)
|
|
|
|
|
|
|
|
|
|
|
|
int GraphicElement::currentFontHeight() const
|
|
|
|
{
|
|
|
|
{
|
|
|
|
int face_start = tag.find("FACE=")+6;
|
|
|
|
std::string fontName(mStyle.mFont == "Default" ? MyGUI::FontManager::getInstance().getDefaultFont() : mStyle.mFont);
|
|
|
|
std::string face = tag.substr(face_start, tag.find('"', face_start)-face_start);
|
|
|
|
return MyGUI::FontManager::getInstance().getByName(fontName)->getDefaultHeight();
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
if (face != "Magic Cards")
|
|
|
|
float GraphicElement::widthForCharGlyph(MyGUI::Char unicodeChar) const
|
|
|
|
mTextStyle.mFont = face;
|
|
|
|
{
|
|
|
|
|
|
|
|
std::string fontName(mStyle.mFont == "Default" ? MyGUI::FontManager::getInstance().getDefaultFont() : mStyle.mFont);
|
|
|
|
|
|
|
|
return MyGUI::FontManager::getInstance().getByName(fontName)
|
|
|
|
|
|
|
|
->getGlyphInfo(unicodeChar)->width;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if (tag.find("SIZE=") != std::string::npos)
|
|
|
|
|
|
|
|
|
|
|
|
/* TextElement */
|
|
|
|
|
|
|
|
TextElement::TextElement(MyGUI::Widget * parent, Paginator & pag, const TextStyle & style, const std::string & text)
|
|
|
|
|
|
|
|
: GraphicElement(parent, pag, style)
|
|
|
|
{
|
|
|
|
{
|
|
|
|
/// \todo
|
|
|
|
MyGUI::EditBox* box = parent->createWidget<MyGUI::EditBox>("NormalText",
|
|
|
|
|
|
|
|
MyGUI::IntCoord(0, pag.getCurrentTop(), pag.getPageWidth(), 0), MyGUI::Align::Left | MyGUI::Align::Top,
|
|
|
|
|
|
|
|
parent->getName() + boost::lexical_cast<std::string>(parent->getChildCount()));
|
|
|
|
|
|
|
|
box->setProperty("Static", "true");
|
|
|
|
|
|
|
|
box->setProperty("MultiLine", "true");
|
|
|
|
|
|
|
|
box->setProperty("WordWrap", "true");
|
|
|
|
|
|
|
|
box->setProperty("NeedMouse", "false");
|
|
|
|
|
|
|
|
box->setMaxTextLength(text.size());
|
|
|
|
|
|
|
|
box->setTextAlign(mStyle.mTextAlign);
|
|
|
|
|
|
|
|
box->setTextColour(mStyle.mColour);
|
|
|
|
|
|
|
|
box->setFontName(mStyle.mFont);
|
|
|
|
|
|
|
|
box->setCaption(MyGUI::TextIterator::toTagsString(text));
|
|
|
|
|
|
|
|
box->setSize(box->getSize().width, box->getTextSize().height);
|
|
|
|
|
|
|
|
mEditBox = box;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
void BookTextParser::parseSubText(std::string text)
|
|
|
|
int TextElement::getHeight()
|
|
|
|
{
|
|
|
|
|
|
|
|
if (text[0] == '<')
|
|
|
|
|
|
|
|
{
|
|
|
|
{
|
|
|
|
const size_t tagStart = 1;
|
|
|
|
return mEditBox->getTextSize().height;
|
|
|
|
const size_t tagEnd = text.find('>', tagStart);
|
|
|
|
|
|
|
|
if (tagEnd == std::string::npos)
|
|
|
|
|
|
|
|
throw std::runtime_error("BookTextParser Error: Tag is not terminated");
|
|
|
|
|
|
|
|
const std::string tag = text.substr(tagStart, tagEnd - tagStart);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if (boost::algorithm::starts_with(tag, "IMG"))
|
|
|
|
|
|
|
|
parseImage(tag);
|
|
|
|
|
|
|
|
if (boost::algorithm::starts_with(tag, "FONT"))
|
|
|
|
|
|
|
|
parseFont(tag);
|
|
|
|
|
|
|
|
if (boost::algorithm::starts_with(tag, "DIV"))
|
|
|
|
|
|
|
|
parseDiv(tag);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
text.erase(0, tagEnd + 1);
|
|
|
|
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
size_t tagStart = std::string::npos;
|
|
|
|
int TextElement::pageSplit()
|
|
|
|
std::string realText; // real text, without tags
|
|
|
|
|
|
|
|
for (size_t i = 0; i<text.size(); ++i)
|
|
|
|
|
|
|
|
{
|
|
|
|
{
|
|
|
|
char c = text[i];
|
|
|
|
// split lines
|
|
|
|
if (c == '<')
|
|
|
|
const int lineHeight = currentFontHeight();
|
|
|
|
|
|
|
|
unsigned int lastLine = (mPaginator.getStartTop() + mPaginator.getPageHeight() - mPaginator.getCurrentTop()) / lineHeight;
|
|
|
|
|
|
|
|
int ret = mPaginator.getCurrentTop() + lastLine * lineHeight;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// first empty lines that would go to the next page should be ignored
|
|
|
|
|
|
|
|
// unfortunately, getLineInfo method won't be available until 3.2.2
|
|
|
|
|
|
|
|
#if (MYGUI_VERSION >= MYGUI_DEFINE_VERSION(3, 2, 2))
|
|
|
|
|
|
|
|
const MyGUI::VectorLineInfo & lines = mEditBox->getSubWidgetText()->castType<MyGUI::EditText>()->getLineInfo();
|
|
|
|
|
|
|
|
for (unsigned int i = lastLine; i < lines.size(); ++i)
|
|
|
|
{
|
|
|
|
{
|
|
|
|
if ((i + 1 < text.size()) && text[i+1] == '/') // ignore closing tags
|
|
|
|
if (lines[i].width == 0)
|
|
|
|
{
|
|
|
|
ret += lineHeight;
|
|
|
|
while (c != '>')
|
|
|
|
|
|
|
|
{
|
|
|
|
|
|
|
|
if (i >= text.size())
|
|
|
|
|
|
|
|
throw std::runtime_error("BookTextParser Error: Tag is not terminated");
|
|
|
|
|
|
|
|
++i;
|
|
|
|
|
|
|
|
c = text[i];
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
continue;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
else
|
|
|
|
else
|
|
|
|
{
|
|
|
|
|
|
|
|
tagStart = i;
|
|
|
|
|
|
|
|
break;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else
|
|
|
|
#endif
|
|
|
|
realText += c;
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
MyGUI::EditBox* box = mParent->createWidget<MyGUI::EditBox>("NormalText",
|
|
|
|
/* ImageElement */
|
|
|
|
MyGUI::IntCoord(0, mHeight, mWidth, 24), MyGUI::Align::Left | MyGUI::Align::Top,
|
|
|
|
ImageElement::ImageElement(MyGUI::Widget * parent, Paginator & pag, const TextStyle & style, const std::string & tag)
|
|
|
|
mParent->getName() + boost::lexical_cast<std::string>(mParent->getChildCount()));
|
|
|
|
: GraphicElement(parent, pag, style),
|
|
|
|
box->setProperty("Static", "true");
|
|
|
|
mImageHeight(0)
|
|
|
|
box->setProperty("MultiLine", "true");
|
|
|
|
|
|
|
|
box->setProperty("WordWrap", "true");
|
|
|
|
|
|
|
|
box->setProperty("NeedMouse", "false");
|
|
|
|
|
|
|
|
box->setMaxTextLength(realText.size());
|
|
|
|
|
|
|
|
box->setTextAlign(mTextStyle.mTextAlign);
|
|
|
|
|
|
|
|
box->setTextColour(mTextStyle.mColour);
|
|
|
|
|
|
|
|
box->setFontName(mTextStyle.mFont);
|
|
|
|
|
|
|
|
box->setCaption(MyGUI::TextIterator::toTagsString(realText));
|
|
|
|
|
|
|
|
box->setSize(box->getSize().width, box->getTextSize().height);
|
|
|
|
|
|
|
|
mHeight += box->getTextSize().height;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if (tagStart != std::string::npos)
|
|
|
|
|
|
|
|
{
|
|
|
|
{
|
|
|
|
parseSubText(text.substr(tagStart, text.size()));
|
|
|
|
int src_start = tag.find("SRC=")+5;
|
|
|
|
|
|
|
|
std::string src = tag.substr(src_start, tag.find('"', src_start)-src_start);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
int width_start = tag.find("WIDTH=")+7;
|
|
|
|
|
|
|
|
int width = boost::lexical_cast<int>(tag.substr(width_start, tag.find('"', width_start)-width_start));
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
int height_start = tag.find("HEIGHT=")+8;
|
|
|
|
|
|
|
|
mImageHeight = boost::lexical_cast<int>(tag.substr(height_start, tag.find('"', height_start)-height_start));
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
mImageBox = parent->createWidget<MyGUI::ImageBox> ("ImageBox",
|
|
|
|
|
|
|
|
MyGUI::IntCoord(0, pag.getCurrentTop(), width, mImageHeight), MyGUI::Align::Left | MyGUI::Align::Top,
|
|
|
|
|
|
|
|
parent->getName() + boost::lexical_cast<std::string>(parent->getChildCount()));
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
std::string image = Misc::ResourceHelpers::correctBookartPath(src, width, mImageHeight);
|
|
|
|
|
|
|
|
mImageBox->setImageTexture(image);
|
|
|
|
|
|
|
|
mImageBox->setProperty("NeedMouse", "false");
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
int ImageElement::getHeight()
|
|
|
|
|
|
|
|
{
|
|
|
|
|
|
|
|
return mImageHeight;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
int ImageElement::pageSplit()
|
|
|
|
|
|
|
|
{
|
|
|
|
|
|
|
|
return mPaginator.getCurrentTop();
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|