From cb5f661596df2a03a33fe065ac1c9fb5d40fe1ce Mon Sep 17 00:00:00 2001 From: MiroslavR Date: Sat, 27 Sep 2014 13:31:59 +0200 Subject: [PATCH 1/6] Book formatter: Support FONT closing tag, minor code cleanup --- apps/openmw/mwgui/formatting.cpp | 33 ++++++++++++++++++++++++++++---- apps/openmw/mwgui/formatting.hpp | 19 +++++++++++------- 2 files changed, 41 insertions(+), 11 deletions(-) diff --git a/apps/openmw/mwgui/formatting.cpp b/apps/openmw/mwgui/formatting.cpp index d838ae8af..8cca621b8 100644 --- a/apps/openmw/mwgui/formatting.cpp +++ b/apps/openmw/mwgui/formatting.cpp @@ -21,7 +21,7 @@ namespace MWGui { /* BookTextParser */ BookTextParser::BookTextParser(const std::string & text) - : mIndex(0), mText(text), mIgnoreNewlineTags(true), mIgnoreLineEndings(true) + : mIndex(0), mText(text), mIgnoreNewlineTags(true), mIgnoreLineEndings(true), mClosingTag(false) { MWScript::InterpreterContext interpreterContext(NULL, MWWorld::Ptr()); // empty arguments, because there is no locals or actor mText = Interpreter::fixDefinesBook(mText, interpreterContext); @@ -40,7 +40,7 @@ namespace MWGui mTagTypes[tag] = type; } - std::string BookTextParser::getReadyText() + std::string BookTextParser::getReadyText() const { return mReadyText; } @@ -117,12 +117,27 @@ namespace MWGui return mAttributes; } + bool BookTextParser::isClosingTag() const + { + return mClosingTag; + } + void BookTextParser::parseTag(std::string tag) { size_t tagNameEndPos = tag.find(' '); + mAttributes.clear(); mTag = tag.substr(0, tagNameEndPos); Misc::StringUtils::toLower(mTag); - mAttributes.clear(); + if (mTag.empty()) + return; + + mClosingTag = (mTag[0] == '/'); + if (mClosingTag) + { + mTag.erase(mTag.begin()); + return; + } + if (tagNameEndPos == std::string::npos) return; tag.erase(0, tagNameEndPos+1); @@ -232,7 +247,10 @@ namespace MWGui break; } case BookTextParser::Event_FontTag: - handleFont(parser.getAttributes()); + if (parser.isClosingTag()) + resetFontProperties(); + else + handleFont(parser.getAttributes()); break; case BookTextParser::Event_DivTag: handleDiv(parser.getAttributes()); @@ -256,6 +274,13 @@ namespace MWGui return markupToWidget(parent, markup, parent->getWidth(), parent->getHeight()); } + void BookFormatter::resetFontProperties() + { + MyGUI::Align align = mTextStyle.mTextAlign; + mTextStyle = TextStyle(); + mTextStyle.mTextAlign = align; + } + void BookFormatter::handleDiv(const BookTextParser::Attributes & attr) { if (attr.find("align") == attr.end()) diff --git a/apps/openmw/mwgui/formatting.hpp b/apps/openmw/mwgui/formatting.hpp index cf55b36fb..64764a13b 100644 --- a/apps/openmw/mwgui/formatting.hpp +++ b/apps/openmw/mwgui/formatting.hpp @@ -40,15 +40,18 @@ namespace MWGui }; BookTextParser(const std::string & text); - void registerTag(const std::string & tag, Events type); - std::string getReadyText(); Events next(); - void flushBuffer(); + const Attributes & getAttributes() const; - void parseTag(std::string tag); + std::string getReadyText() const; + bool isClosingTag() const; private: + void registerTag(const std::string & tag, Events type); + void flushBuffer(); + void parseTag(std::string tag); + size_t mIndex; std::string mText; std::string mReadyText; @@ -57,6 +60,7 @@ namespace MWGui bool mIgnoreLineEndings; Attributes mAttributes; std::string mTag; + bool mClosingTag; std::map mTagTypes; std::string mBuffer; }; @@ -101,11 +105,12 @@ namespace MWGui Paginator::Pages markupToWidget(MyGUI::Widget * parent, const std::string & markup, const int pageWidth, const int pageHeight); Paginator::Pages markupToWidget(MyGUI::Widget * parent, const std::string & markup); - protected: - void handleImg(const BookTextParser::Attributes & attr); + private: + void resetFontProperties(); + void handleDiv(const BookTextParser::Attributes & attr); void handleFont(const BookTextParser::Attributes & attr); - private: + TextStyle mTextStyle; }; From 1c4e52a0e560fbd5e8b399b14b5754e92e1d67a0 Mon Sep 17 00:00:00 2001 From: MiroslavR Date: Sat, 27 Sep 2014 17:35:57 +0200 Subject: [PATCH 2/6] Book formatter: Fix an excessive line break case --- apps/openmw/mwgui/formatting.cpp | 32 ++++++++++++++++++++++++++------ 1 file changed, 26 insertions(+), 6 deletions(-) diff --git a/apps/openmw/mwgui/formatting.cpp b/apps/openmw/mwgui/formatting.cpp index 8cca621b8..47b73c248 100644 --- a/apps/openmw/mwgui/formatting.cpp +++ b/apps/openmw/mwgui/formatting.cpp @@ -199,6 +199,8 @@ namespace MWGui BookTextParser parser(markup); BookTextParser::Events event; + + bool brBeforeLastTag = false; for (;;) { event = parser.next(); @@ -206,11 +208,26 @@ namespace MWGui continue; std::string plainText = parser.getReadyText(); - if (!plainText.empty()) + if (plainText.empty()) + brBeforeLastTag = false; + else { - // if there's a newline at the end of the box caption, remove it - if (plainText[plainText.size()-1] == '\n') - plainText.erase(plainText.end()-1); + // Each block of text (between two tags / boundary and tag) will be displayed in a separate editbox widget, + // which means an additonal linebreak will be created. + // ^ This is not the case in vanilla MW (though having multiple tags in one line seems to result in undefined behavior). + // We must deal with linebreaks around tags appropriately. + { + bool brAtStart = (plainText[0] == '\n'); + bool brAtEnd = (plainText[plainText.size()-1] == '\n'); + + if (!brBeforeLastTag && brAtStart) + plainText.erase(plainText.begin()); + + if (plainText.size() && brAtEnd) + plainText.erase(plainText.end()-1); + + brBeforeLastTag = brAtEnd; + } #if (MYGUI_VERSION < MYGUI_DEFINE_VERSION(3, 2, 2)) // splitting won't be fully functional until 3.2.2 (see TextElement::pageSplit()) @@ -222,8 +239,11 @@ namespace MWGui } #endif - TextElement elem(paper, pag, mTextStyle, plainText); - elem.paginate(); + if (!plainText.empty()) + { + TextElement elem(paper, pag, mTextStyle, plainText); + elem.paginate(); + } } if (event == BookTextParser::Event_EOF) From 3287d0b6efcd087ca89c4773a452a91be9283290 Mon Sep 17 00:00:00 2001 From: MiroslavR Date: Fri, 3 Oct 2014 21:08:52 +0200 Subject: [PATCH 3/6] Fix line breaks around IMG tags. --- apps/openmw/mwgui/formatting.cpp | 29 ++++++++++++++--------------- 1 file changed, 14 insertions(+), 15 deletions(-) diff --git a/apps/openmw/mwgui/formatting.cpp b/apps/openmw/mwgui/formatting.cpp index 1adda1e24..efeed88c7 100644 --- a/apps/openmw/mwgui/formatting.cpp +++ b/apps/openmw/mwgui/formatting.cpp @@ -81,7 +81,6 @@ namespace MWGui if (type == Event_ImgTag) { - mIgnoreLineEndings = false; mIgnoreNewlineTags = false; } @@ -200,6 +199,7 @@ namespace MWGui BookTextParser parser(markup); bool brBeforeLastTag = false; + bool isPrevImg = false; for (;;) { BookTextParser::Events event = parser.next(); @@ -212,21 +212,16 @@ namespace MWGui else { // Each block of text (between two tags / boundary and tag) will be displayed in a separate editbox widget, - // which means an additonal linebreak will be created. - // ^ This is not the case in vanilla MW (though having multiple tags in one line seems to result in undefined behavior). - // We must deal with linebreaks around tags appropriately. - { - bool brAtStart = (plainText[0] == '\n'); - bool brAtEnd = (plainText[plainText.size()-1] == '\n'); + // which means an additonal linebreak will be created between them. + // ^ This is not what vanilla MW assumes, so we must deal with line breaks around tags appropriately. + bool brAtStart = (plainText[0] == '\n'); + bool brAtEnd = (plainText[plainText.size()-1] == '\n'); - if (!brBeforeLastTag && brAtStart) - plainText.erase(plainText.begin()); + if (brAtStart && !brBeforeLastTag && !isPrevImg) + plainText.erase(plainText.begin()); - if (plainText.size() && brAtEnd) - plainText.erase(plainText.end()-1); - - brBeforeLastTag = brAtEnd; - } + if (plainText.size() && brAtEnd) + plainText.erase(plainText.end()-1); #if (MYGUI_VERSION < MYGUI_DEFINE_VERSION(3, 2, 2)) // splitting won't be fully functional until 3.2.2 (see TextElement::pageSplit()) @@ -238,16 +233,20 @@ namespace MWGui } #endif - if (!plainText.empty()) + if (!plainText.empty() || brBeforeLastTag || isPrevImg) { TextElement elem(paper, pag, mTextStyle, plainText); elem.paginate(); } + + brBeforeLastTag = brAtEnd; } if (event == BookTextParser::Event_EOF) break; + isPrevImg = (event == BookTextParser::Event_ImgTag); + switch (event) { case BookTextParser::Event_ImgTag: From a13039ad1fd8967698e546dd35364641712df928 Mon Sep 17 00:00:00 2001 From: MiroslavR Date: Fri, 3 Oct 2014 21:36:45 +0200 Subject: [PATCH 4/6] Allow alignment for images in books --- apps/openmw/mwgui/formatting.cpp | 40 ++++++++++++++++---------------- apps/openmw/mwgui/formatting.hpp | 28 +++++++++++++++------- 2 files changed, 40 insertions(+), 28 deletions(-) diff --git a/apps/openmw/mwgui/formatting.cpp b/apps/openmw/mwgui/formatting.cpp index efeed88c7..f932d2356 100644 --- a/apps/openmw/mwgui/formatting.cpp +++ b/apps/openmw/mwgui/formatting.cpp @@ -235,7 +235,8 @@ namespace MWGui if (!plainText.empty() || brBeforeLastTag || isPrevImg) { - TextElement elem(paper, pag, mTextStyle, plainText); + TextElement elem(paper, pag, mBlockStyle, + mTextStyle, plainText); elem.paginate(); } @@ -260,7 +261,8 @@ namespace MWGui int width = boost::lexical_cast(attr.at("width")); int height = boost::lexical_cast(attr.at("height")); - ImageElement elem(paper, pag, src, width, height); + ImageElement elem(paper, pag, mBlockStyle, + src, width, height); elem.paginate(); break; } @@ -294,9 +296,7 @@ namespace MWGui void BookFormatter::resetFontProperties() { - MyGUI::Align align = mTextStyle.mTextAlign; mTextStyle = TextStyle(); - mTextStyle.mTextAlign = align; } void BookFormatter::handleDiv(const BookTextParser::Attributes & attr) @@ -307,9 +307,9 @@ namespace MWGui std::string align = attr.at("align"); if (Misc::StringUtils::ciEqual(align, "center")) - mTextStyle.mTextAlign = MyGUI::Align::HCenter; + mBlockStyle.mAlign = MyGUI::Align::HCenter; else if (Misc::StringUtils::ciEqual(align, "left")) - mTextStyle.mTextAlign = MyGUI::Align::Left; + mBlockStyle.mAlign = MyGUI::Align::Left; } void BookFormatter::handleFont(const BookTextParser::Attributes & attr) @@ -321,7 +321,7 @@ namespace MWGui ss << attr.at("color"); ss >> std::hex >> color; - mTextStyle.mColour = MyGUI::Colour( + mTextStyle.mColor = MyGUI::Colour( (color>>16 & 0xFF) / 255.f, (color>>8 & 0xFF) / 255.f, (color & 0xFF) / 255.f); @@ -340,8 +340,8 @@ namespace MWGui } /* GraphicElement */ - GraphicElement::GraphicElement(MyGUI::Widget * parent, Paginator & pag) - : mParent(parent), mPaginator(pag) + GraphicElement::GraphicElement(MyGUI::Widget * parent, Paginator & pag, const BlockStyle & blockStyle) + : mParent(parent), mPaginator(pag), mBlockStyle(blockStyle) { } @@ -364,10 +364,10 @@ namespace MWGui } /* TextElement */ - TextElement::TextElement(MyGUI::Widget * parent, Paginator & pag, - const TextStyle & style, const std::string & text) - : GraphicElement(parent, pag), - mStyle(style) + TextElement::TextElement(MyGUI::Widget * parent, Paginator & pag, const BlockStyle & blockStyle, + const TextStyle & textStyle, const std::string & text) + : GraphicElement(parent, pag, blockStyle), + mTextStyle(textStyle) { MyGUI::EditBox* box = parent->createWidget("NormalText", MyGUI::IntCoord(0, pag.getCurrentTop(), pag.getPageWidth(), 0), MyGUI::Align::Left | MyGUI::Align::Top, @@ -377,9 +377,9 @@ namespace MWGui 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->setTextAlign(mBlockStyle.mAlign); + box->setTextColour(mTextStyle.mColor); + box->setFontName(mTextStyle.mFont); box->setCaption(MyGUI::TextIterator::toTagsString(text)); box->setSize(box->getSize().width, box->getTextSize().height); mEditBox = box; @@ -387,7 +387,7 @@ namespace MWGui int TextElement::currentFontHeight() const { - std::string fontName(mStyle.mFont == "Default" ? MyGUI::FontManager::getInstance().getDefaultFont() : mStyle.mFont); + std::string fontName(mTextStyle.mFont == "Default" ? MyGUI::FontManager::getInstance().getDefaultFont() : mTextStyle.mFont); return MyGUI::FontManager::getInstance().getByName(fontName)->getDefaultHeight(); } @@ -419,13 +419,13 @@ namespace MWGui } /* ImageElement */ - ImageElement::ImageElement(MyGUI::Widget * parent, Paginator & pag, + ImageElement::ImageElement(MyGUI::Widget * parent, Paginator & pag, const BlockStyle & blockStyle, const std::string & src, int width, int height) - : GraphicElement(parent, pag), + : GraphicElement(parent, pag, blockStyle), mImageHeight(height) { mImageBox = parent->createWidget ("ImageBox", - MyGUI::IntCoord(0, pag.getCurrentTop(), width, mImageHeight), MyGUI::Align::Left | MyGUI::Align::Top, + MyGUI::IntCoord(0, pag.getCurrentTop(), width, mImageHeight), mBlockStyle.mAlign | MyGUI::Align::Top, parent->getName() + boost::lexical_cast(parent->getChildCount())); std::string image = Misc::ResourceHelpers::correctBookartPath(src, width, mImageHeight); diff --git a/apps/openmw/mwgui/formatting.hpp b/apps/openmw/mwgui/formatting.hpp index 64764a13b..cfc6ec121 100644 --- a/apps/openmw/mwgui/formatting.hpp +++ b/apps/openmw/mwgui/formatting.hpp @@ -11,17 +11,25 @@ namespace MWGui struct TextStyle { TextStyle() : - mColour(0,0,0) + mColor(0,0,0) , mFont("Default") , mTextSize(16) - , mTextAlign(MyGUI::Align::Left | MyGUI::Align::Top) { } - MyGUI::Colour mColour; + MyGUI::Colour mColor; std::string mFont; int mTextSize; - MyGUI::Align mTextAlign; + }; + + struct BlockStyle + { + BlockStyle() : + mAlign(MyGUI::Align::Left | MyGUI::Align::Top) + { + } + + MyGUI::Align mAlign; }; class BookTextParser @@ -112,12 +120,13 @@ namespace MWGui void handleFont(const BookTextParser::Attributes & attr); TextStyle mTextStyle; + BlockStyle mBlockStyle; }; class GraphicElement { public: - GraphicElement(MyGUI::Widget * parent, Paginator & pag); + GraphicElement(MyGUI::Widget * parent, Paginator & pag, const BlockStyle & blockStyle); virtual int getHeight() = 0; virtual void paginate(); virtual int pageSplit(); @@ -125,24 +134,27 @@ namespace MWGui protected: MyGUI::Widget * mParent; Paginator & mPaginator; + BlockStyle mBlockStyle; }; class TextElement : public GraphicElement { public: - TextElement(MyGUI::Widget * parent, Paginator & pag, const TextStyle & style, const std::string & text); + TextElement(MyGUI::Widget * parent, Paginator & pag, const BlockStyle & blockStyle, + const TextStyle & textStyle, const std::string & text); virtual int getHeight(); virtual int pageSplit(); private: int currentFontHeight() const; - TextStyle mStyle; + TextStyle mTextStyle; MyGUI::EditBox * mEditBox; }; class ImageElement : public GraphicElement { public: - ImageElement(MyGUI::Widget * parent, Paginator & pag, const std::string & src, int width, int height); + ImageElement(MyGUI::Widget * parent, Paginator & pag, const BlockStyle & blockStyle, + const std::string & src, int width, int height); virtual int getHeight(); virtual int pageSplit(); From 4829b1f9cc81daef801789447797c19d50dcb200 Mon Sep 17 00:00:00 2001 From: MiroslavR Date: Fri, 3 Oct 2014 22:30:46 +0200 Subject: [PATCH 5/6] Support "right" alignment in books --- apps/openmw/mwgui/formatting.cpp | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) diff --git a/apps/openmw/mwgui/formatting.cpp b/apps/openmw/mwgui/formatting.cpp index f932d2356..cc45b328b 100644 --- a/apps/openmw/mwgui/formatting.cpp +++ b/apps/openmw/mwgui/formatting.cpp @@ -310,6 +310,8 @@ namespace MWGui mBlockStyle.mAlign = MyGUI::Align::HCenter; else if (Misc::StringUtils::ciEqual(align, "left")) mBlockStyle.mAlign = MyGUI::Align::Left; + else if (Misc::StringUtils::ciEqual(align, "right")) + mBlockStyle.mAlign = MyGUI::Align::Right; } void BookFormatter::handleFont(const BookTextParser::Attributes & attr) @@ -424,8 +426,16 @@ namespace MWGui : GraphicElement(parent, pag, blockStyle), mImageHeight(height) { + int left = 0; + if (mBlockStyle.mAlign.isHCenter()) + left += (pag.getPageWidth() - width) / 2; + else if (mBlockStyle.mAlign.isLeft()) + left = 0; + else if (mBlockStyle.mAlign.isRight()) + left += pag.getPageWidth() - width; + mImageBox = parent->createWidget ("ImageBox", - MyGUI::IntCoord(0, pag.getCurrentTop(), width, mImageHeight), mBlockStyle.mAlign | MyGUI::Align::Top, + MyGUI::IntCoord(left, pag.getCurrentTop(), width, mImageHeight), MyGUI::Align::Left | MyGUI::Align::Top, parent->getName() + boost::lexical_cast(parent->getChildCount())); std::string image = Misc::ResourceHelpers::correctBookartPath(src, width, mImageHeight); From 95be7ea73809b00c0b7c628cd3e6f618dbde9516 Mon Sep 17 00:00:00 2001 From: MiroslavR Date: Fri, 3 Oct 2014 22:38:06 +0200 Subject: [PATCH 6/6] Revert spelling change to preserve consistency, fix a typo --- apps/openmw/mwgui/formatting.cpp | 6 +++--- apps/openmw/mwgui/formatting.hpp | 4 ++-- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/apps/openmw/mwgui/formatting.cpp b/apps/openmw/mwgui/formatting.cpp index cc45b328b..c55650c45 100644 --- a/apps/openmw/mwgui/formatting.cpp +++ b/apps/openmw/mwgui/formatting.cpp @@ -212,7 +212,7 @@ namespace MWGui else { // Each block of text (between two tags / boundary and tag) will be displayed in a separate editbox widget, - // which means an additonal linebreak will be created between them. + // which means an additional linebreak will be created between them. // ^ This is not what vanilla MW assumes, so we must deal with line breaks around tags appropriately. bool brAtStart = (plainText[0] == '\n'); bool brAtEnd = (plainText[plainText.size()-1] == '\n'); @@ -323,7 +323,7 @@ namespace MWGui ss << attr.at("color"); ss >> std::hex >> color; - mTextStyle.mColor = MyGUI::Colour( + mTextStyle.mColour = MyGUI::Colour( (color>>16 & 0xFF) / 255.f, (color>>8 & 0xFF) / 255.f, (color & 0xFF) / 255.f); @@ -380,7 +380,7 @@ namespace MWGui box->setProperty("NeedMouse", "false"); box->setMaxTextLength(text.size()); box->setTextAlign(mBlockStyle.mAlign); - box->setTextColour(mTextStyle.mColor); + box->setTextColour(mTextStyle.mColour); box->setFontName(mTextStyle.mFont); box->setCaption(MyGUI::TextIterator::toTagsString(text)); box->setSize(box->getSize().width, box->getTextSize().height); diff --git a/apps/openmw/mwgui/formatting.hpp b/apps/openmw/mwgui/formatting.hpp index cfc6ec121..3e21b62e2 100644 --- a/apps/openmw/mwgui/formatting.hpp +++ b/apps/openmw/mwgui/formatting.hpp @@ -11,13 +11,13 @@ namespace MWGui struct TextStyle { TextStyle() : - mColor(0,0,0) + mColour(0,0,0) , mFont("Default") , mTextSize(16) { } - MyGUI::Colour mColor; + MyGUI::Colour mColour; std::string mFont; int mTextSize; };