Font rendering overhaul. Work in progress.

svn-id: r33247
This commit is contained in:
Vicent Marti 2008-07-23 16:38:39 +00:00
parent c5d6738011
commit b5086559b8
6 changed files with 156 additions and 172 deletions

View file

@ -75,15 +75,6 @@ void VectorRenderer::drawStep(const Common::Rect &area, const DrawStep &step, ui
(this->*(step.drawingCall))(area, step); (this->*(step.drawingCall))(area, step);
} }
void VectorRenderer::textStep(const Common::String &text, const Common::Rect &area, const TextStep &step, GUI::Theme::TextAlign alignH) {
if (step.color.set)
setFgColor(step.color.r, step.color.g, step.color.b);
drawString(step.font, text.c_str(), area,
!step.hasAlign ? alignH : step.alignHorizontal,
!step.hasAlign ? GUI::Theme::kTextAlignVTop : step.alignVertical);
}
int VectorRenderer::stepGetRadius(const DrawStep &step, const Common::Rect &area) { int VectorRenderer::stepGetRadius(const DrawStep &step, const Common::Rect &area) {
int radius = 0; int radius = 0;

View file

@ -39,20 +39,6 @@ namespace Graphics {
class VectorRenderer; class VectorRenderer;
struct DrawStep; struct DrawStep;
struct TextStep {
struct {
uint8 r, g, b;
bool set;
}
color; /** text color */
GUI::Theme::TextAlign alignHorizontal;
GUI::Theme::TextAlignVertical alignVertical;
bool hasAlign;
char *text;
const Graphics::Font *font;
};
struct DrawStep { struct DrawStep {
struct { struct {
uint8 r, g, b; uint8 r, g, b;
@ -404,7 +390,6 @@ public:
* @param step Pointer to a DrawStep struct. * @param step Pointer to a DrawStep struct.
*/ */
virtual void drawStep(const Common::Rect &area, const DrawStep &step, uint32 extra = 0); virtual void drawStep(const Common::Rect &area, const DrawStep &step, uint32 extra = 0);
virtual void textStep(const Common::String &text, const Common::Rect &area, const TextStep &step, GUI::Theme::TextAlign alignH = GUI::Theme::kTextAlignLeft);
/** /**
* Copies the current surface to the system overlay * Copies the current surface to the system overlay
@ -422,8 +407,6 @@ public:
*/ */
virtual void blitSurface(Graphics::Surface *source, const Common::Rect &r) = 0; virtual void blitSurface(Graphics::Surface *source, const Common::Rect &r) = 0;
virtual uint32 buildColor(uint8 r, uint8 g, uint8 b) = 0;
virtual void drawString(const Graphics::Font *font, const Common::String &text, const Common::Rect &area, GUI::Theme::TextAlign alignH, GUI::Theme::TextAlignVertical alignV) = 0; virtual void drawString(const Graphics::Font *font, const Common::String &text, const Common::Rect &area, GUI::Theme::TextAlign alignH, GUI::Theme::TextAlignVertical alignV) = 0;
virtual void disableShadows() { _disableShadows = true; } virtual void disableShadows() { _disableShadows = true; }
@ -595,10 +578,6 @@ public:
src_ptr += src_pitch; src_ptr += src_pitch;
} }
} }
virtual uint32 buildColor(uint8 r, uint8 g, uint8 b) {
return RGBToColor<PixelFormat>(r, g, b);
}
protected: protected:

View file

@ -42,18 +42,20 @@ bool ThemeRenderer::loadDefaultXML() {
"<color name = 'red' rgb = '255, 0, 0' />" "<color name = 'red' rgb = '255, 0, 0' />"
"<color name = 'green' rgb = '0, 255, 0' />" "<color name = 'green' rgb = '0, 255, 0' />"
"<color name = 'blue' rgb = '0, 255, 255' />" "<color name = 'blue' rgb = '0, 255, 255' />"
"<color name = 'text_default' rgb = '0, 0, 0' />"
"<color name = 'text_hover' rgb = '255, 255, 255' />"
"<color name = 'text_disabled' rgb = '128, 128, 128' />"
"</palette>" "</palette>"
"<fonts>" "<fonts>"
"<font id = 'default' type = 'default' color = 'text_default' />" "<font id = 'text_default' type = 'default' color = '0, 0, 0' />"
"<font id = 'hover' type = 'default' color = 'text_hover' />" "<font id = 'text_hover' type = 'default' color = '255, 255, 255' />"
"<font id = 'disabled' type = 'default' color = 'text_disabled' />" "<font id = 'text_disabled' type = 'default' color = '128, 128, 128' />"
"<font id = 'text_inverted' type = 'default' color = '255, 0, 0' />"
"</fonts>" "</fonts>"
"<defaults fill = 'gradient' fg_color = '255, 255, 255' />" "<defaults fill = 'gradient' fg_color = '255, 255, 255' />"
"<drawdata id = 'text_selection' cache = false>"
"<drawstep func = 'square' fill = 'foreground' fg_color = '0, 255, 0' />"
"</drawdata>"
"<drawdata id = 'mainmenu_bg' cache = false>" "<drawdata id = 'mainmenu_bg' cache = false>"
"<drawstep func = 'fill' fill = 'gradient' gradient_start = '214, 113, 8' gradient_end = '240, 200, 25' />" "<drawstep func = 'fill' fill = 'gradient' gradient_start = '214, 113, 8' gradient_end = '240, 200, 25' />"
@ -68,12 +70,12 @@ bool ThemeRenderer::loadDefaultXML() {
"</drawdata>" "</drawdata>"
"<drawdata id = 'tab_active' cache = false>" "<drawdata id = 'tab_active' cache = false>"
"<text vertical_align = 'center' horizontal_align = 'center' color = '0, 0, 0' />" "<text font = 'text_default' vertical_align = 'center' horizontal_align = 'center' />"
"<drawstep func = 'tab' radius = '4' stroke = '2' fill = 'gradient' gradient_end = '255, 231, 140' gradient_start = '255, 243, 206' shadow = 3 />" "<drawstep func = 'tab' radius = '4' stroke = '2' fill = 'gradient' gradient_end = '255, 231, 140' gradient_start = '255, 243, 206' shadow = 3 />"
"</drawdata>" "</drawdata>"
"<drawdata id = 'tab_inactive' cache = false>" "<drawdata id = 'tab_inactive' cache = false>"
"<text vertical_align = 'center' horizontal_align = 'center' color = '128, 128, 128' />" "<text font = 'text_disabled' vertical_align = 'center' horizontal_align = 'center' />"
"<drawstep func = 'tab' radius = '4' stroke = '0' fill = 'foreground' fg_color = '206, 121, 99' shadow = 3 />" "<drawstep func = 'tab' radius = '4' stroke = '0' fill = 'foreground' fg_color = '206, 121, 99' shadow = 3 />"
"</drawdata>" "</drawdata>"
@ -95,7 +97,7 @@ bool ThemeRenderer::loadDefaultXML() {
"<drawdata id = 'popup_hover' cache = false>" "<drawdata id = 'popup_hover' cache = false>"
"<drawstep func = 'square' stroke = 0 fg_color = '0, 0, 0' fill = 'gradient' gradient_start = '214, 113, 8' gradient_end = '240, 200, 25' shadow = 0 />" "<drawstep func = 'square' stroke = 0 fg_color = '0, 0, 0' fill = 'gradient' gradient_start = '214, 113, 8' gradient_end = '240, 200, 25' shadow = 0 />"
"<drawstep func = 'triangle' fg_color = '0, 0, 0' fill = 'foreground' width = '12' height = '12' xpos = '-16' ypos = 'center' orientation = 'bottom' />" "<drawstep func = 'triangle' fg_color = '0, 0, 0' fill = 'foreground' width = '12' height = '12' xpos = '-16' ypos = 'center' orientation = 'bottom' />"
"<text vertical_align = 'center' horizontal_align = 'right' color = '255, 255, 255' />" "<text font = 'text_hover' vertical_align = 'center' horizontal_align = 'right' />"
"</drawdata>" "</drawdata>"
"<drawdata id = 'default_bg' cache = false>" "<drawdata id = 'default_bg' cache = false>"
@ -103,27 +105,27 @@ bool ThemeRenderer::loadDefaultXML() {
"</drawdata>" "</drawdata>"
"<drawdata id = 'button_idle' cache = false>" "<drawdata id = 'button_idle' cache = false>"
"<text vertical_align = 'center' horizontal_align = 'center' color = '173, 40, 8' />" "<text font = 'text_default' vertical_align = 'center' horizontal_align = 'center' />"
"<drawstep func = 'roundedsq' radius = '8' stroke = 0 fill = 'foreground' shadow = 3 />" "<drawstep func = 'roundedsq' radius = '8' stroke = 0 fill = 'foreground' shadow = 3 />"
"</drawdata>" "</drawdata>"
"<drawdata id = 'button_hover' cache = false>" "<drawdata id = 'button_hover' cache = false>"
"<text vertical_align = 'center' horizontal_align = 'center' color = '255, 255, 255' />" "<text font = 'text_hover' vertical_align = 'center' horizontal_align = 'center' />"
"<drawstep func = 'roundedsq' radius = '8' stroke = '1' fill = 'gradient' gradient_start = '206, 121, 99' gradient_end = '173, 40, 8' shadow = 0 />" "<drawstep func = 'roundedsq' radius = '8' stroke = '1' fill = 'gradient' gradient_start = '206, 121, 99' gradient_end = '173, 40, 8' shadow = 0 />"
"</drawdata>" "</drawdata>"
"<drawdata id = 'button_disabled' cache = false>" "<drawdata id = 'button_disabled' cache = false>"
"<text vertical_align = 'center' horizontal_align = 'center' color = '128, 128, 128' />" "<text font = 'text_disabled' vertical_align = 'center' horizontal_align = 'center' />"
"<drawstep func = 'roundedsq' radius = '8' stroke = 0 fill = 'foreground' fg_color = '200, 200, 200' shadow = 3 />" "<drawstep func = 'roundedsq' radius = '8' stroke = 0 fill = 'foreground' fg_color = '200, 200, 200' shadow = 3 />"
"</drawdata>" "</drawdata>"
"<drawdata id = 'checkbox_disabled' cache = false>" "<drawdata id = 'checkbox_disabled' cache = false>"
"<text vertical_align = 'top' horizontal_align = 'left' color = '0,0,0' />" "<text font = 'text_disabled' vertical_align = 'top' horizontal_align = 'left' />"
"<drawstep func = 'square' fill = 'gradient' gradient_start = '206, 121, 99' gradient_end = '173, 40, 8' shadow = 0 />" "<drawstep func = 'square' fill = 'gradient' gradient_start = '206, 121, 99' gradient_end = '173, 40, 8' shadow = 0 />"
"</drawdata>" "</drawdata>"
"<drawdata id = 'checkbox_enabled' cache = false>" "<drawdata id = 'checkbox_enabled' cache = false>"
"<text vertical_align = 'top' horizontal_align = 'left' color = '0,0,0' />" "<text font = 'text_default' vertical_align = 'top' horizontal_align = 'left' />"
"<drawstep func = 'square' fill = 'gradient' gradient_start = '206, 121, 99' gradient_end = '173, 40, 8' shadow = 0 />" "<drawstep func = 'square' fill = 'gradient' gradient_start = '206, 121, 99' gradient_end = '173, 40, 8' shadow = 0 />"
"<drawstep func = 'circle' radius = 'auto' fill = 'foreground' />" "<drawstep func = 'circle' radius = 'auto' fill = 'foreground' />"
"</drawdata>" "</drawdata>"

View file

@ -160,10 +160,6 @@ bool ThemeParser::parserCallback_font() {
if (!tNode->values.contains("type")) if (!tNode->values.contains("type"))
return parserError("Font definitions need a valid typename."); return parserError("Font definitions need a valid typename.");
// TODO: set typename on the drawstep.
Graphics::TextStep step;
if (tNode->values.contains("horizontal_align") || tNode->values.contains("vertical_align")) if (tNode->values.contains("horizontal_align") || tNode->values.contains("vertical_align"))
return parserError("Font definitions cannot contain alignments."); return parserError("Font definitions cannot contain alignments.");
@ -181,13 +177,7 @@ bool ThemeParser::parserCallback_font() {
return parserError("Cannot assign color in font definition."); return parserError("Cannot assign color in font definition.");
} }
step.color.r = red; if (!_theme->addFont(tNode->values["id"], red, green, blue))
step.color.g = green;
step.color.b = blue;
step.color.set = true;
step.hasAlign = false;
if (!_theme->addTextStep(tNode->values["id"], step))
return parserError("Error when loading Font in theme engine."); return parserError("Error when loading Font in theme engine.");
return true; return true;
@ -209,47 +199,29 @@ bool ThemeParser::parserCallback_text() {
if (parentNode == 0 || parentNode->name != "drawdata") if (parentNode == 0 || parentNode->name != "drawdata")
return parserError("Text Steps must be contained inside <drawdata> keys."); return parserError("Text Steps must be contained inside <drawdata> keys.");
Graphics::TextStep step; GUI::Theme::TextAlign alignH;
GUI::Theme::TextAlignVertical alignV;
if (tNode->values.contains("horizontal_align") == false || tNode->values.contains("vertical_align") == false) if (tNode->values.contains("horizontal_align") == false || tNode->values.contains("vertical_align") == false)
return parserError("Text inside widgets requires proper alignment keys."); return parserError("Text inside widgets requires proper alignment keys.");
if (tNode->values["horizontal_align"] == "left") if (tNode->values["horizontal_align"] == "left")
step.alignHorizontal = GUI::Theme::kTextAlignLeft; alignH = GUI::Theme::kTextAlignLeft;
else if (tNode->values["horizontal_align"] == "right") else if (tNode->values["horizontal_align"] == "right")
step.alignHorizontal = GUI::Theme::kTextAlignRight; alignH = GUI::Theme::kTextAlignRight;
else if (tNode->values["horizontal_align"] == "center") else if (tNode->values["horizontal_align"] == "center")
step.alignHorizontal = GUI::Theme::kTextAlignCenter; alignH = GUI::Theme::kTextAlignCenter;
else return parserError("Invalid value for text alignment."); else return parserError("Invalid value for text alignment.");
if (tNode->values["vertical_align"] == "top") if (tNode->values["vertical_align"] == "top")
step.alignVertical = GUI::Theme::kTextAlignVTop; alignV = GUI::Theme::kTextAlignVTop;
else if (tNode->values["vertical_align"] == "center") else if (tNode->values["vertical_align"] == "center")
step.alignVertical = GUI::Theme::kTextAlignVCenter; alignV = GUI::Theme::kTextAlignVCenter;
else if (tNode->values["vertical_align"] == "bottom") else if (tNode->values["vertical_align"] == "bottom")
step.alignVertical = GUI::Theme::kTextAlignVBottom; alignV = GUI::Theme::kTextAlignVBottom;
else return parserError("Invalid value for text alignment."); else return parserError("Invalid value for text alignment.");
int red, green, blue; return _theme->addTextData(parentNode->values["id"], tNode->values["font"], alignH, alignV);
if (tNode->values.contains("color")) {
if (_palette.contains(tNode->values["color"]))
getPaletteColor(tNode->values["color"], red, green, blue);
else if (!parseIntegerKey(tNode->values["color"].c_str(), 3, &red, &green, &blue))
return parserError("Error when parsing color value for text definition");
} else {
return parserError("Cannot assign color for text drawing.");
}
step.color.r = red;
step.color.g = green;
step.color.b = blue;
step.color.set = true;
step.hasAlign = true;
return _theme->addTextStep(parentNode->values["id"], step);
} }
bool ThemeParser::parserCallback_renderInfo() { bool ThemeParser::parserCallback_renderInfo() {

View file

@ -44,6 +44,7 @@ const ThemeRenderer::DrawDataInfo ThemeRenderer::kDrawDataDefaults[] = {
{kDDSpecialColorBackground, "special_bg", true, kDDNone}, {kDDSpecialColorBackground, "special_bg", true, kDDNone},
{kDDPlainColorBackground, "plain_bg", true, kDDNone}, {kDDPlainColorBackground, "plain_bg", true, kDDNone},
{kDDDefaultBackground, "default_bg", true, kDDNone}, {kDDDefaultBackground, "default_bg", true, kDDNone},
{kDDTextSelectionBackground, "text_selection", false, kDDNone},
{kDDWidgetBackgroundDefault, "widget_default", true, kDDNone}, {kDDWidgetBackgroundDefault, "widget_default", true, kDDNone},
{kDDWidgetBackgroundSmall, "widget_small", true, kDDNone}, {kDDWidgetBackgroundSmall, "widget_small", true, kDDNone},
@ -72,6 +73,13 @@ const ThemeRenderer::DrawDataInfo ThemeRenderer::kDrawDataDefaults[] = {
{kDDSeparator, "separator", true, kDDNone}, {kDDSeparator, "separator", true, kDDNone},
}; };
const ThemeRenderer::TextDataInfo ThemeRenderer::kTextDataDefaults[] = {
{kTextDataDefault, "text_default"},
{kTextDataHover, "text_hover"},
{kTextDataDisabled, "text_disabled"},
{kTextDataInverted, "text_inverted"}
};
ThemeRenderer::ThemeRenderer(Common::String themeName, GraphicsMode mode) : ThemeRenderer::ThemeRenderer(Common::String themeName, GraphicsMode mode) :
_vectorRenderer(0), _system(0), _graphicsMode(kGfxDisabled), _vectorRenderer(0), _system(0), _graphicsMode(kGfxDisabled),
@ -83,6 +91,10 @@ ThemeRenderer::ThemeRenderer(Common::String themeName, GraphicsMode mode) :
for (int i = 0; i < kDrawDataMAX; ++i) { for (int i = 0; i < kDrawDataMAX; ++i) {
_widgets[i] = 0; _widgets[i] = 0;
} }
for (int i = 0; i < kTextDataMAX; ++i) {
_texts[i] = 0;
}
_graphicsMode = mode; _graphicsMode = mode;
setGraphicsMode(_graphicsMode); setGraphicsMode(_graphicsMode);
@ -111,14 +123,6 @@ bool ThemeRenderer::init() {
Theme::loadTheme(_configFile, false, true); Theme::loadTheme(_configFile, false, true);
} }
if (_fontName.empty()) {
if (_screen->w >= 400 && _screen->h >= 300) {
_font = FontMan.getFontByUsage(Graphics::FontManager::kBigGUIFont);
} else {
_font = FontMan.getFontByUsage(Graphics::FontManager::kGUIFont);
}
}
return true; return true;
} }
@ -195,31 +199,45 @@ void ThemeRenderer::addDrawStep(const Common::String &drawDataId, Graphics::Draw
_widgets[id]->_steps.push_back(step); _widgets[id]->_steps.push_back(step);
} }
bool ThemeRenderer::addTextStep(const Common::String &drawDataId, Graphics::TextStep step) { bool ThemeRenderer::addTextData(const Common::String &drawDataId, const Common::String &textDataId, TextAlign alignH, TextAlignVertical alignV) {
DrawData id = getDrawDataId(drawDataId); DrawData id = getDrawDataId(drawDataId);
TextData textId = getTextDataId(textDataId);
step.font = 0; if (id == -1 || textId == -1 || !_widgets[id])
return false;
if (id != -1) { _widgets[id]->_textDataId = textId;
assert(_widgets[id] != 0); _widgets[id]->_textAlignH = alignH;
if (_widgets[id]->_hasText == true) _widgets[id]->_textAlignV = alignV;
return false;
_widgets[id]->_textStep = step;
_widgets[id]->_hasText = true;
} else {
if (drawDataId == "default") {
_texts[kTextColorDefault] = step;
} else if (drawDataId == "hover") {
_texts[kTextColorHover] = step;
} else if (drawDataId == "disabled") {
_texts[kTextColorDisabled] = step;
} else return false;
}
return true; return true;
} }
bool ThemeRenderer::addFont(const Common::String &fontId, int r, int g, int b) {
TextData textId = getTextDataId(fontId);
if (textId == -1)
return false;
if (_texts[textId] != 0)
return false;
_texts[textId] = new TextDrawData;
// TODO: Allow the user to specify the font he wants, instead of choosing based on resolution
if (_screen->w >= 400 && _screen->h >= 300) {
_texts[textId]->_fontPtr = FontMan.getFontByUsage(Graphics::FontManager::kBigGUIFont);
} else {
_texts[textId]->_fontPtr = FontMan.getFontByUsage(Graphics::FontManager::kGUIFont);
}
_texts[textId]->_color.r = r;
_texts[textId]->_color.g = g;
_texts[textId]->_color.b = b;
return true;
}
bool ThemeRenderer::addDrawData(const Common::String &data, bool cached) { bool ThemeRenderer::addDrawData(const Common::String &data, bool cached) {
DrawData data_id = getDrawDataId(data); DrawData data_id = getDrawDataId(data);
@ -230,7 +248,7 @@ bool ThemeRenderer::addDrawData(const Common::String &data, bool cached) {
_widgets[data_id]->_cached = cached; _widgets[data_id]->_cached = cached;
_widgets[data_id]->_buffer = kDrawDataDefaults[data_id].buffer; _widgets[data_id]->_buffer = kDrawDataDefaults[data_id].buffer;
_widgets[data_id]->_surfaceCache = 0; _widgets[data_id]->_surfaceCache = 0;
_widgets[data_id]->_hasText = false; _widgets[data_id]->_textDataId = -1;
return true; return true;
} }
@ -320,14 +338,19 @@ void ThemeRenderer::queueDD(DrawData type, const Common::Rect &r, uint32 dynamic
} }
} }
void ThemeRenderer::queueDDText(DrawData type, const Common::Rect &r, const Common::String &text, TextColor colorId, TextAlign align) { void ThemeRenderer::queueDDText(TextData type, const Common::Rect &r, const Common::String &text,
bool elipsis, TextAlign alignH, TextAlignVertical alignV) {
if (_texts[type] == 0)
return;
DrawQueueText q; DrawQueueText q;
q.type = type; q.type = type;
q.area = r; q.area = r;
q.area.clip(_screen->w, _screen->h); q.area.clip(_screen->w, _screen->h);
q.text = text; q.text = text;
q.colorId = colorId; q.alignH = alignH;
q.align = align; q.alignV = alignV;
if (_buffering) { if (_buffering) {
_textQueue.push_back(q); _textQueue.push_back(q);
@ -359,19 +382,11 @@ void ThemeRenderer::drawDD(const DrawQueue &q, bool draw, bool restore) {
} }
void ThemeRenderer::drawDDText(const DrawQueueText &q) { void ThemeRenderer::drawDDText(const DrawQueueText &q) {
if (q.type == kDDNone) { if (q.type != kTextDataInverted)
restoreBackground(q.area); restoreBackground(q.area);
if (_texts[q.colorId].font == 0)
_texts[q.colorId].font = _font;
_vectorRenderer->textStep(q.text, q.area, _texts[q.colorId], q.align);
} else {
if (_widgets[q.type]->_textStep.font == 0)
_widgets[q.type]->_textStep.font = _font;
_vectorRenderer->textStep(q.text, q.area, _widgets[q.type]->_textStep);
}
_vectorRenderer->setFgColor(_texts[q.type]->_color.r, _texts[q.type]->_color.g, _texts[q.type]->_color.b);
_vectorRenderer->drawString(_texts[q.type]->_fontPtr, q.text, q.area, q.alignH, q.alignV);
addDirtyRect(q.area); addDirtyRect(q.area);
} }
@ -405,7 +420,7 @@ void ThemeRenderer::drawButton(const Common::Rect &r, const Common::String &str,
dd = kDDButtonDisabled; dd = kDDButtonDisabled;
queueDD(dd, r); queueDD(dd, r);
queueDDText(dd, r, str); queueDDText(getTextData(dd), r, str, false, _widgets[dd]->_textAlignH, _widgets[dd]->_textAlignV);
} }
void ThemeRenderer::drawLineSeparator(const Common::Rect &r, WidgetStateInfo state) { void ThemeRenderer::drawLineSeparator(const Common::Rect &r, WidgetStateInfo state) {
@ -420,17 +435,18 @@ void ThemeRenderer::drawCheckbox(const Common::Rect &r, const Common::String &st
return; return;
Common::Rect r2 = r; Common::Rect r2 = r;
DrawData dd = checked ? kDDCheckboxEnabled : kDDCheckboxDisabled;
const int checkBoxSize = MIN((int)r.height(), getFontHeight()); const int checkBoxSize = MIN((int)r.height(), getFontHeight());
r2.bottom = r2.top + checkBoxSize; r2.bottom = r2.top + checkBoxSize;
r2.right = r2.left + checkBoxSize; r2.right = r2.left + checkBoxSize;
queueDD(checked ? kDDCheckboxEnabled : kDDCheckboxDisabled, r2); queueDD(dd, r2);
r2.left = r2.right + checkBoxSize; r2.left = r2.right + checkBoxSize;
r2.right = r.right; r2.right = r.right;
queueDDText(checked ? kDDCheckboxEnabled : kDDCheckboxDisabled, r2, str); queueDDText(getTextData(dd), r2, str, false, _widgets[dd]->_textAlignH, _widgets[dd]->_textAlignV);
} }
void ThemeRenderer::drawSlider(const Common::Rect &r, int width, WidgetStateInfo state) { void ThemeRenderer::drawSlider(const Common::Rect &r, int width, WidgetStateInfo state) {
@ -484,7 +500,7 @@ void ThemeRenderer::drawPopUpWidget(const Common::Rect &r, const Common::String
if (!sel.empty()) { if (!sel.empty()) {
Common::Rect text(r.left, r.top, r.right - 16, r.bottom); Common::Rect text(r.left, r.top, r.right - 16, r.bottom);
queueDDText(dd, text, sel); queueDDText(getTextData(dd), text, sel, false, _widgets[dd]->_textAlignH, _widgets[dd]->_textAlignV);
} }
} }
@ -530,7 +546,7 @@ void ThemeRenderer::drawTab(const Common::Rect &r, int tabHeight, int tabWidth,
Common::Rect tabRect(r.left + i * (tabWidth + tabOffset), r.top, r.left + i * (tabWidth + tabOffset) + tabWidth, r.top + tabHeight); Common::Rect tabRect(r.left + i * (tabWidth + tabOffset), r.top, r.left + i * (tabWidth + tabOffset) + tabWidth, r.top + tabHeight);
queueDD(kDDTabInactive, tabRect); queueDD(kDDTabInactive, tabRect);
queueDDText(kDDTabInactive, tabRect, tabs[i]); queueDDText(getTextData(kDDTabInactive), tabRect, tabs[i], false, _widgets[kDDTabInactive]->_textAlignH, _widgets[kDDTabInactive]->_textAlignV);
} }
if (active >= 0) { if (active >= 0) {
@ -538,15 +554,30 @@ void ThemeRenderer::drawTab(const Common::Rect &r, int tabHeight, int tabWidth,
const uint16 tabLeft = active * (tabWidth + tabOffset); const uint16 tabLeft = active * (tabWidth + tabOffset);
const uint16 tabRight = MAX(r.right - tabRect.right, 0); const uint16 tabRight = MAX(r.right - tabRect.right, 0);
queueDD(kDDTabActive, tabRect, (tabLeft << 16) | (tabRight & 0xFFFF)); queueDD(kDDTabActive, tabRect, (tabLeft << 16) | (tabRight & 0xFFFF));
queueDDText(kDDTabActive, tabRect, tabs[active]); queueDDText(getTextData(kDDTabActive), tabRect, tabs[active], false, _widgets[kDDTabActive]->_textAlignH, _widgets[kDDTabActive]->_textAlignV);
} }
} }
void ThemeRenderer::drawText(const Common::Rect &r, const Common::String &str, WidgetStateInfo state, TextAlign align, bool inverted, int deltax, bool useEllipsis, FontStyle font) { void ThemeRenderer::drawText(const Common::Rect &r, const Common::String &str, WidgetStateInfo state, TextAlign align, bool inverted, int deltax, bool useEllipsis, FontStyle font) {
if (!_initOk) if (!_initOk)
return; return;
queueDDText(kDDNone, r, str, getTextColor(state), align); if (inverted)
queueDD(kDDTextSelectionBackground, r);
switch (state) {
case kStateDisabled:
queueDDText(inverted ? kTextDataInverted : kTextDataDisabled, r, str, useEllipsis);
break;
case kStateHighlight:
queueDDText(inverted ? kTextDataInverted : kTextDataHover, r, str, useEllipsis);
break;
case kStateEnabled:
queueDDText(inverted ? kTextDataInverted : kTextDataDefault, r, str, useEllipsis);
break;
}
} }
void ThemeRenderer::debugWidgetPosition(const char *name, const Common::Rect &r) { void ThemeRenderer::debugWidgetPosition(const char *name, const Common::Rect &r) {

View file

@ -42,13 +42,21 @@ namespace GUI {
struct WidgetDrawData; struct WidgetDrawData;
struct DrawDataInfo; struct DrawDataInfo;
struct TextDrawData {
const Graphics::Font *_fontPtr;
struct {
uint8 r, g, b;
} _color;
};
struct WidgetDrawData { struct WidgetDrawData {
/** List of all the steps needed to draw this widget */ /** List of all the steps needed to draw this widget */
Common::List<Graphics::DrawStep> _steps; Common::List<Graphics::DrawStep> _steps;
/** Single step that defines the text shown inside the widget */ int _textDataId;
Graphics::TextStep _textStep; GUI::Theme::TextAlign _textAlignH;
bool _hasText; GUI::Theme::TextAlignVertical _textAlignV;
/** Extra space that the widget occupies when it's drawn. /** Extra space that the widget occupies when it's drawn.
E.g. when taking into account rounded corners, drop shadows, etc E.g. when taking into account rounded corners, drop shadows, etc
@ -97,6 +105,7 @@ protected:
kDDSpecialColorBackground, kDDSpecialColorBackground,
kDDPlainColorBackground, kDDPlainColorBackground,
kDDDefaultBackground, kDDDefaultBackground,
kDDTextSelectionBackground,
kDDWidgetBackgroundDefault, kDDWidgetBackgroundDefault,
kDDWidgetBackgroundSmall, kDDWidgetBackgroundSmall,
@ -149,21 +158,28 @@ protected:
uint32 dynData; /** Dynamic data which modifies the DrawData item (optional)*/ uint32 dynData; /** Dynamic data which modifies the DrawData item (optional)*/
}; };
enum TextColor { enum TextData {
kTextColorNone = -1, kTextDataNone = -1,
kTextColorDefault, kTextDataDefault = 0,
kTextColorHover, kTextDataHover,
kTextColorDisabled, kTextDataDisabled,
kTextColorInverted, kTextDataInverted,
kTextColorMAX kTextDataMAX
}; };
static const struct TextDataInfo {
TextData id;
const char *name;
} kTextDataDefaults[];
struct DrawQueueText { struct DrawQueueText {
DrawData type; TextData type;
Common::Rect area; Common::Rect area;
Common::String text; Common::String text;
TextColor colorId;
TextAlign align; GUI::Theme::TextAlign alignH;
GUI::Theme::TextAlignVertical alignV;
bool elipsis;
}; };
public: public:
@ -312,6 +328,14 @@ public:
return kDDNone; return kDDNone;
} }
TextData getTextDataId(const Common::String &name) {
for (int i = 0; i < kTextDataMAX; ++i)
if (name.compareToIgnoreCase(kTextDataDefaults[i].name) == 0)
return kTextDataDefaults[i].id;
return kTextDataNone;
}
/** /**
* Interface for ThemeParser class: Parsed DrawSteps are added via this function. * Interface for ThemeParser class: Parsed DrawSteps are added via this function.
@ -334,12 +358,13 @@ public:
* @param cached Whether this DD set will be cached beforehand. * @param cached Whether this DD set will be cached beforehand.
*/ */
bool addDrawData(const Common::String &data, bool cached); bool addDrawData(const Common::String &data, bool cached);
bool addFont(const Common::String &fontName, int r, int g, int b);
/** /**
* Adds a new TextStep from the ThemeParser. This will be deprecated/removed once the * Adds a new TextStep from the ThemeParser. This will be deprecated/removed once the
* new Font API is in place. * new Font API is in place.
*/ */
bool addTextStep(const Common::String &drawDataId, Graphics::TextStep step); bool addTextData(const Common::String &drawDataId, const Common::String &textDataId, TextAlign alignH, TextAlignVertical alignV);
/** Interface to the new Theme XML parser */ /** Interface to the new Theme XML parser */
ThemeParser *parser() { ThemeParser *parser() {
@ -414,6 +439,11 @@ protected:
delete _widgets[i]; delete _widgets[i];
_widgets[i] = 0; _widgets[i] = 0;
} }
for (int i = 0; i < kTextDataMAX; ++i) {
delete _texts[i];
_texts[i] = 0;
}
_themeOk = false; _themeOk = false;
} }
@ -461,14 +491,9 @@ protected:
_screen = 0; _screen = 0;
} }
} }
/** TextData getTextData(DrawData ddId) {
* Checks if the given widget type has a Text drawing step associated to it. return _widgets[ddId] ? (TextData)_widgets[ddId]->_textDataId : kTextDataNone;
*
* @param type DrawData type of the widget.
*/
bool hasWidgetText(DrawData type) {
return (_widgets[type] != 0 && _widgets[type]->_hasText);
} }
/** /**
@ -523,8 +548,8 @@ protected:
* This function is called from all the Widget Drawing methods. * This function is called from all the Widget Drawing methods.
*/ */
inline void queueDD(DrawData type, const Common::Rect &r, uint32 dynamic = 0); inline void queueDD(DrawData type, const Common::Rect &r, uint32 dynamic = 0);
inline void queueDDText(DrawData type, const Common::Rect &r, const Common::String &text, inline void queueDDText(TextData type, const Common::Rect &r, const Common::String &text,
TextColor colorId = kTextColorNone, TextAlign align = kTextAlignLeft); bool elipsis, TextAlign alignH = kTextAlignLeft, TextAlignVertical alignV = kTextAlignVTop);
/** /**
* DEBUG: Draws a white square around the given position and writes the given next to it. * DEBUG: Draws a white square around the given position and writes the given next to it.
@ -547,22 +572,6 @@ protected:
*/ */
int getTabSpacing() const { return 0; } int getTabSpacing() const { return 0; }
int getTabPadding() const { return 3; } int getTabPadding() const { return 3; }
/**
* Translates a WidgetStateInfo of a Text widget to the actual font color value.
*/
TextColor getTextColor(WidgetStateInfo state) {
switch (state) {
case kStateDisabled:
return kTextColorDisabled;
case kStateHighlight:
return kTextColorHover;
default:
return kTextColorDefault;
}
}
OSystem *_system; /** Global system object. */ OSystem *_system; /** Global system object. */
@ -597,7 +606,7 @@ protected:
WidgetDrawData *_widgets[kDrawDataMAX]; WidgetDrawData *_widgets[kDrawDataMAX];
/** Array of all the text fonts that can be drawn. */ /** Array of all the text fonts that can be drawn. */
Graphics::TextStep _texts[kTextColorMAX]; TextDrawData *_texts[kTextDataMAX];
/** List of all the dirty screens that must be blitted to the overlay. */ /** List of all the dirty screens that must be blitted to the overlay. */
Common::List<Common::Rect> _dirtyScreen; Common::List<Common::Rect> _dirtyScreen;