diff options
author | Paul Gilbert | 2014-08-17 18:56:05 -0400 |
---|---|---|
committer | Paul Gilbert | 2014-08-17 18:56:05 -0400 |
commit | 9393f6d7559653a28166fe74da9745e95b76f85b (patch) | |
tree | 23c8bba593a9f55a1ef3eaa06cf14468d0e2527f | |
parent | 4ea9339d183cb53f465d7752e739cf8a153a7978 (diff) | |
download | scummvm-rg350-9393f6d7559653a28166fe74da9745e95b76f85b.tar.gz scummvm-rg350-9393f6d7559653a28166fe74da9745e95b76f85b.tar.bz2 scummvm-rg350-9393f6d7559653a28166fe74da9745e95b76f85b.zip |
ACCESS: Implemented bubble box drawing code
-rw-r--r-- | engines/access/asurface.cpp | 12 | ||||
-rw-r--r-- | engines/access/asurface.h | 7 | ||||
-rw-r--r-- | engines/access/bubble_box.cpp | 167 | ||||
-rw-r--r-- | engines/access/bubble_box.h | 27 | ||||
-rw-r--r-- | engines/access/data.cpp | 85 | ||||
-rw-r--r-- | engines/access/data.h | 19 |
6 files changed, 271 insertions, 46 deletions
diff --git a/engines/access/asurface.cpp b/engines/access/asurface.cpp index 08caa8a3b2..99292278f3 100644 --- a/engines/access/asurface.cpp +++ b/engines/access/asurface.cpp @@ -115,6 +115,11 @@ int ASurface::_lastBoundsW; int ASurface::_lastBoundsH; int ASurface::_scrollX; int ASurface::_scrollY; +int ASurface::_orgX1; +int ASurface::_orgY1; +int ASurface::_orgX2; +int ASurface::_orgY2; +int ASurface::_lColor; void ASurface::init() { _leftSkip = _rightSkip = 0; @@ -123,6 +128,9 @@ void ASurface::init() { _lastBoundsX = _lastBoundsY = 0; _lastBoundsW = _lastBoundsH = 0; _scrollX = _scrollY = 0; + _orgX1 = _orgY1 = 0; + _orgX2 = _orgY2 = 0; + _lColor = 0; } ASurface::~ASurface() { @@ -329,4 +337,8 @@ void ASurface::restoreBlock() { } } +void ASurface::drawRect() { + Graphics::Surface::fillRect(Common::Rect(_orgX1, _orgY1, _orgX2, _orgY2), _lColor); +} + } // End of namespace Access diff --git a/engines/access/asurface.h b/engines/access/asurface.h index 85550d9eee..400dd07b4d 100644 --- a/engines/access/asurface.h +++ b/engines/access/asurface.h @@ -46,9 +46,14 @@ public: static int _lastBoundsX, _lastBoundsY; static int _lastBoundsW, _lastBoundsH; static int _scrollX, _scrollY; + static int _orgX1, _orgY1; + static int _orgX2, _orgY2; + static int _lColor; static void init(); public: + virtual void plotFrame(SpriteFrame *frame, const Common::Point &pt); +public: virtual ~ASurface(); void clearBuffer(); @@ -75,7 +80,7 @@ public: void restoreBlock(); - virtual void plotFrame(SpriteFrame *frame, const Common::Point &pt); + void drawRect(); }; class SpriteFrame : public ASurface { diff --git a/engines/access/bubble_box.cpp b/engines/access/bubble_box.cpp index 5f0cb9443b..f910028fc5 100644 --- a/engines/access/bubble_box.cpp +++ b/engines/access/bubble_box.cpp @@ -26,18 +26,15 @@ namespace Access { -Box::Box(AccessEngine *vm) : Manager(vm) { - _edgeSize = 0; -} - -void Box::doBox(int item, int box) { - error("TODO: doBox"); -} - -/*------------------------------------------------------------------------*/ - -BubbleBox::BubbleBox(AccessEngine *vm) : Box(vm) { +BubbleBox::BubbleBox(AccessEngine *vm) : Manager(vm) { + _type = TYPE_2; + _bounds = Common::Rect(64, 32, 64 + 130, 32 + 122); _bubblePtr = nullptr; + _fieldD = 0; + _fieldE = 0; + _fieldF = 0; + _field10 = 0; + _maxChars = 0; } @@ -69,7 +66,7 @@ void BubbleBox::placeBubble1(const Common::String &msg) { calcBubble(msg); - Common::Rect r = BubbleBox::_bubbles[0]; + Common::Rect r = _bubbles[0]; r.translate(-2, 0); _vm->_screen->saveBlock(r); printBubble(msg); @@ -81,7 +78,7 @@ void BubbleBox::calcBubble(const Common::String &msg) { Common::Point printStart = _vm->_fonts._printStart; // Figure out maximum width allowed - if (_edgeSize == 4) { + if (_type == TYPE_4) { _vm->_fonts._printMaxX = 110; } else { _vm->_fonts._printMaxX = _vm->_fonts._font2.stringWidth(_bubblePtr); @@ -96,14 +93,14 @@ void BubbleBox::calcBubble(const Common::String &msg) { int width = 0; bool lastLine; do { - lastLine = _vm->_fonts._font2.getLine(s, _vm->_fonts._printMaxX, line, width); - width = MIN(width, _vm->_fonts._printMaxX); + lastLine = _vm->_fonts._font2.getLine(s, _maxChars * 6, line, width); + width = MAX(width, _vm->_fonts._printMaxX); _vm->_fonts._printOrg.y += 6; _vm->_fonts._printOrg.x = _vm->_fonts._printStart.x; } while (!lastLine); - if (_edgeSize == 4) + if (_type == TYPE_4) ++_vm->_fonts._printOrg.y += 6; // Determine the width for the area @@ -114,17 +111,17 @@ void BubbleBox::calcBubble(const Common::String &msg) { // Determine the height for area int y = _vm->_fonts._printOrg.y + 6; - if (_edgeSize == 4) + if (_type == TYPE_4) y += 6; int height = y - bounds.top; bounds.setHeight(height); - height -= (_edgeSize == 4) ? 30 : 24; + height -= (_type == TYPE_4) ? 30 : 24; if (height >= 0) bounds.setHeight(bounds.height() + 13 - (height % 13)); // Add the new bounds to the bubbles list - BubbleBox::_bubbles.push_back(bounds); + _bubbles.push_back(bounds); // Restore points _vm->_fonts._printOrg = printOrg; @@ -132,13 +129,139 @@ void BubbleBox::calcBubble(const Common::String &msg) { } void BubbleBox::printBubble(const Common::String &msg) { - drawBubble(BubbleBox::_bubbles.size() - 1); - error("TODO: printBubble"); + drawBubble(_bubbles.size() - 1); + + // Loop through drawing the lines + Common::String s = msg; + Common::String line; + int width = 0; + bool lastLine; + do { + // Get next line + Font &font2 = _vm->_fonts._font2; + lastLine = font2.getLine(s, _maxChars * 6, line, width); + + // Set font colors + font2._fontColors[0] = 0; + font2._fontColors[1] = 0; + font2._fontColors[2] = 0; + font2._fontColors[3] = 0; + + int xp = _vm->_fonts._printOrg.x; + if (_type == TYPE_4) + xp = (_bounds.width() - width) / 2 + _bounds.left - 4; + + // Draw the text + font2.drawString(_vm->_screen, line, Common::Point(xp, _vm->_fonts._printOrg.y)); + + // Move print position + _vm->_fonts._printOrg.y += 6; + _vm->_fonts._printOrg.x = _vm->_fonts._printStart.x; + } while (!lastLine); } void BubbleBox::drawBubble(int index) { - _bounds = BubbleBox::_bubbles[index]; + _bounds = _bubbles[index]; doBox(0, 0); } +void BubbleBox::doBox(int item, int box) { + FontManager &fonts = _vm->_fonts; + ASurface &screen = *_vm->_screen; + + _startItem = item; + _startBox = box; + + // Save state information + FontVal charSet = fonts._charSet; + FontVal charFor = fonts._charFor; + Common::Point printOrg = fonts._printOrg; + Common::Point printStart = fonts._printStart; + int charCol = _charCol; + int rowOff = _rowOff; + + _vm->_screen->saveScreen(); + _vm->_screen->setDisplayScan(); + fonts._charFor._hi = 0xff; + fonts._charSet._lo = 1; + fonts._charSet._hi = 0; + + if (_type == TYPE_4) { + fonts._charFor._lo = 0xFF; + error("TODO: filename listing"); + return; + } + + // Get icons data + byte *iconData = _vm->_files->loadFile("ICONS.LZ"); + SpriteResource *icons = new SpriteResource(_vm, iconData, _vm->_files->_filesize); + delete[] iconData; + + // Set the up boundaries and color to use for the box background + _vm->_screen->_orgX1 = _bounds.left; + _vm->_screen->_orgY1 = _bounds.top; + _vm->_screen->_orgX2 = _bounds.right; + _vm->_screen->_orgY2 = _bounds.bottom; + _vm->_screen->_lColor = 1; + + int h = _bounds.height() - (_type == TYPE_4) ? 30 : 24; + int ySize = (h < 0) ? 0 : (h + 12) / 13; + int w = _bounds.width() - 24; + int xSize = (w < 0) ? 0 : (w + 19) / 20; + + // Draw a background for the entire area + screen.drawRect(); + + // Draw images to form the top border + int xp, yp; + screen.plotImage(icons, 20, Common::Point(screen._orgX1, screen._orgY1)); + xp = screen._orgX1 + 12; + for (int x = 0; x < xSize; ++x, xp += 20) + screen.plotImage(icons, 24 + x, Common::Point(xp, screen._orgY1)); + screen.plotImage(icons, 21, Common::Point(xp, screen._orgY1)); + + // Draw images to form the bottom border + yp = screen._orgY2 - (_type == TYPE_4) ? 18 : 12; + screen.plotImage(icons, (_type == TYPE_4) ? 72 : 22, + Common::Point(screen._orgX1, yp)); + xp = screen._orgX1 + 12; + yp += (_type == TYPE_4) ? 4 : 8; + + for (int x = 0; x < xSize; ++x, xp += 20) { + screen.plotImage(icons, (_type == TYPE_4 ? 62 : 34) + x, + Common::Point(xp, yp)); + } + + yp -= (_type == TYPE_4) ? 18 : 12; + screen.plotImage(icons, (_type == TYPE_4) ? 73 : 23, + Common::Point(screen._orgX1, yp)); + + if (_type == TYPE_4) { + // Further stuff + warning("YSIZE not yet used %d", ySize); + error("TODO: Box type 4"); + } + + // Handle drawing title + int titleWidth = _vm->_fonts._font2.stringWidth(_bubblePtr); + Font &font2 = _vm->_fonts._font2; + font2._fontColors[0] = 0; + font2._fontColors[1] = 3; + font2._fontColors[2] = 2; + font2._fontColors[3] = 1; + font2.drawString(_vm->_screen, _bubblePtr, Common::Point( + _bounds.left + (_bounds.width() / 2) - (titleWidth / 2), _bounds.top + 1)); + + // Restore positional state + fonts._charSet = charSet; + fonts._charFor = charFor; + fonts._printOrg = printOrg; + fonts._printStart = printStart; + _charCol = charCol; + _rowOff = rowOff; + + // Free icons data + delete icons; +} + } // End of namespace Access diff --git a/engines/access/bubble_box.h b/engines/access/bubble_box.h index 189e0b1c04..3ddb2f72e3 100644 --- a/engines/access/bubble_box.h +++ b/engines/access/bubble_box.h @@ -26,6 +26,7 @@ #include "common/scummsys.h" #include "common/array.h" #include "common/rect.h" +#include "common/str-array.h" #include "common/stream.h" #include "common/types.h" #include "graphics/surface.h" @@ -35,20 +36,24 @@ namespace Access { class AccessEngine; -class Box: public Manager { -public: - int _edgeSize; - Common::Rect _bounds; -public: - Box(AccessEngine *vm); - - void doBox(int item, int box); -}; +enum BoxType { TYPE_2 = 2, TYPE_4 = 4 }; -class BubbleBox: public Box { +class BubbleBox: public Manager { +private: + int _startItem, _startBox; + int _charCol, _rowOff; + Common::Point _fileStart; public: + BoxType _type; + Common::Rect _bounds; + Common::StringArray _nameIndex; Common::String _bubbleTitle; const char *_bubblePtr; + int _fieldD; + int _fieldE; + int _fieldF; + int _field10; + int _maxChars; Common::Array<Common::Rect> _bubbles; public: @@ -77,7 +82,7 @@ public: */ void drawBubble(int index); - + void doBox(int item, int box); }; } // End of namespace Access diff --git a/engines/access/data.cpp b/engines/access/data.cpp index 65702db9f1..1fba854f19 100644 --- a/engines/access/data.cpp +++ b/engines/access/data.cpp @@ -46,21 +46,57 @@ void TimerList::restoreTimers() { /*------------------------------------------------------------------------*/ +byte Font::_fontColors[4]; + Font::Font() { } +Font::~Font() { + for (uint i = 0; i < _chars.size(); ++i) + _chars[i].free(); +} + void Font::load(const int *index, const byte *data) { + assert(_chars.size() == 0); int count = index[0]; - _v1 = index[1]; - _v2 = index[2]; - - _chars.clear(); - for (int idx = 0; idx < count; ++idx) - _chars.push_back(data + index[idx + 3]); + _bitWidth = index[1]; + _height = index[2]; + + _chars.resize(count); + + for (int i = 0; i < count; ++i) { + const byte *pData = data + index[i + 3]; + _chars[i].create(*pData++, _height, Graphics::PixelFormat::createFormatCLUT8()); + + for (int y = 0; y < _height; ++y) { + int bitsLeft = 0; + byte srcByte = 0; + byte pixel; + + byte *pDest = (byte *)_chars[i].getBasePtr(0, y); + for (int x = 0; x < _chars[i].w; ++x, ++pDest) { + // Get the pixel + pixel = 0; + for (int pixelCtr = 0; pixelCtr < _bitWidth; ++pixelCtr) { + // No bits in current byte left, so get next byte + if (bitsLeft == 0) { + bitsLeft = 8; + srcByte = *pData++; + } + + pixel = (pixel << 1) | (srcByte >> 7); + srcByte <<= 1; + } + + // Write out the pixel + *pDest = pixel; + } + } + } } int Font::charWidth(char c) { - return *_chars[c - ' ']; + return _chars[c - ' '].w; } int Font::stringWidth(const Common::String &msg) { @@ -69,10 +105,11 @@ int Font::stringWidth(const Common::String &msg) { for (const char *c = msg.c_str(); *c != '\0'; ++c) total += charWidth(*c); - return 0; + return total; } bool Font::getLine(Common::String &s, int maxWidth, Common::String &line, int &width) { + assert(maxWidth > 0); width = 0; const char *src = s.c_str(); char c; @@ -92,7 +129,8 @@ bool Font::getLine(Common::String &s, int maxWidth, Common::String &line, int &w // Reached maximum allowed. Work backwards to find space at the // start of the current word as a point to split the line on - while (*src != ' ' && src >= s.c_str()) { + --src; + while (src >= s.c_str() && *src != ' ') { width -= charWidth(*src); --src; } @@ -111,10 +149,39 @@ bool Font::getLine(Common::String &s, int maxWidth, Common::String &line, int &w return true; } +void Font::drawString(Graphics::Surface *s, const Common::String &msg, const Common::Point &pt) { + Common::Point currPt = pt; + const char *msgP = msg.c_str(); + + while (*msgP) { + currPt.x += drawChar(s, *msgP, currPt); + ++msgP; + } +} + +int Font::drawChar(Graphics::Surface *s, char c, Common::Point &pt) { + Graphics::Surface &ch = _chars[c - ' ']; + + // Loop through the lines of the character + for (int y = 0; y < ch.h; ++y) { + byte *pSrc = (byte *)ch.getBasePtr(0, y); + byte *pDest = (byte *)s->getBasePtr(pt.x, pt.y + y); + + // Loop through the horizontal pixels of the line + for (int x = 0; x < ch.w; ++x, ++pSrc, ++pDest) { + if (*pSrc != 0) + *pDest = _fontColors[*pSrc]; + } + } + + return ch.w; +} + /*------------------------------------------------------------------------*/ FontManager::FontManager() { _printMaxX = 0; + Common::fill(&Font::_fontColors[0], &Font::_fontColors[4], 0); } } // End of namespace Access diff --git a/engines/access/data.h b/engines/access/data.h index 910e2523d1..fd3c889ddb 100644 --- a/engines/access/data.h +++ b/engines/access/data.h @@ -87,12 +87,16 @@ public: class Font { private: - int _v1; - int _v2; - Common::Array<const byte *> _chars; + int _bitWidth; + int _height; + Common::Array<Graphics::Surface> _chars; +public: + static byte _fontColors[4]; public: Font(); + ~Font(); + /** * Load the given font data */ @@ -118,6 +122,15 @@ public: */ bool getLine(Common::String &s, int maxWidth, Common::String &line, int &width); + /** + * Draw a string on a given surface + */ + void drawString(Graphics::Surface *s, const Common::String &msg, const Common::Point &pt); + + /** + * Draw a character on a given surface + */ + int drawChar(Graphics::Surface *s, char c, Common::Point &pt); }; class FontManager { |