int TextObject::getTextCharPosition(int pos) { int width = 0; Common::String msg = parseMsgText(_textID, NULL); for (int i = 0; (msg[i] != '\0') && (i < pos); ++i) { width += _font->getCharWidth(msg[i]); } return width; }
void Lua_V2::LocalizeString() { char msgId[50], buf[1000]; lua_Object strObj = lua_getparam(1); msgId[0] = 0; if (lua_isstring(strObj)) { const char *str = lua_getstring(strObj); Common::String msg = parseMsgText(str, msgId); sprintf(buf, "/%s/%s", msgId, msg.c_str()); lua_pushstring(buf); } }
void Lua_V1::LocalizeString() { char msgId[50], buf[1000]; lua_Object strObj = lua_getparam(1); if (lua_isstring(strObj)) { const char *str = lua_getstring(strObj); // If the string that we're passed isn't localized yet then // construct the localized string, otherwise spit back what // we've been given if (str[0] == '/' && str[strlen(str) - 1] == '/') { Common::String msg = parseMsgText(str, msgId); sprintf(buf, "/%s/%s", msgId, msg.c_str()); str = buf; } lua_pushstring(str); } }
void Lua_V1::PrintLine() { int vol = 127, buffer = 64, /*paramId = 1, */x = -1, y = -1; bool background = true; char msgId[50]; Common::String msg; lua_Object param1Obj = lua_getparam(0); lua_Object param2Obj = lua_getparam(1); if ((lua_isstring(param1Obj) || lua_isnil(param1Obj)) && (lua_istable(param2Obj) || lua_isnil(param2Obj))) { if (lua_istable(param2Obj)) { setTextObjectParams(&g_grim->_printLineDefaults, param2Obj); parseSayLineTable(param2Obj, &background, &vol, &buffer, &x, &y); } if (lua_isstring(param1Obj)) { const char *tmpstr = lua_getstring(param1Obj); msg = parseMsgText(tmpstr, msgId); } if (!msg.empty()) { // actor->sayLine(msg.c_str(), msgId); //background, vol, pan, x, y } } }
void TextObject::createBitmap() { if (_created) destroyBitmap(); Common::String msg = parseMsgText(_textID, NULL); Common::String message; const char *c = msg.c_str(); // remove spaces (NULL_TEXT) from the end of the string, // while this helps make the string unique it screws up // text justification for (int i = (int)msg.size() - 1; c[i] == TEXT_NULL; i--) msg.deleteLastChar(); // remove char of id 13 from the end of the string, for (int i = (int)msg.size() - 1; c[i] == 13; i--) msg.deleteLastChar(); // format the output message to incorporate line wrapping // (if necessary) for the text object const int SCREEN_WIDTH = _width ? _width : 640; const int SCREEN_MARGIN = 75; // If the speaker is too close to the edge of the screen we have to make // some room for the subtitles. if (_isSpeech){ if (_x < SCREEN_MARGIN) { _x = SCREEN_MARGIN; } else if (SCREEN_WIDTH - _x < SCREEN_MARGIN) { _x = SCREEN_WIDTH - SCREEN_MARGIN; } } // The maximum width for any line of text is determined by the justification // mode. Note that there are no left/right margins -- this is consistent // with GrimE. int maxWidth; if (_justify == CENTER) { maxWidth = 2 * MIN(_x, SCREEN_WIDTH - _x); } else if (_justify == LJUSTIFY) { maxWidth = SCREEN_WIDTH - _x; } else if (_justify == RJUSTIFY) { maxWidth = _x; } // We break the message to lines not longer than maxWidth _numberLines = 1; int lineWidth = 0; int maxLineWidth = 0; for (int i = 0; i < (int)msg.size(); i++) { lineWidth += MAX(_font->getCharWidth(msg[i]), _font->getCharDataWidth(msg[i])); if (lineWidth > maxWidth) { if (message.contains(' ')) { while (msg[i] != ' ' && i > 0) { lineWidth -= MAX(_font->getCharWidth(msg[i]), _font->getCharDataWidth(msg[i])); message.deleteLastChar(); --i; } } else if (msg[i] != ' ') { // if it is a unique word int dashWidth = MAX(_font->getCharWidth('-'), _font->getCharDataWidth('-')); while (lineWidth + dashWidth > maxWidth) { lineWidth -= MAX(_font->getCharWidth(msg[i]), _font->getCharDataWidth(msg[i])); message.deleteLastChar(); --i; } message += '-'; } message += '\n'; _numberLines++; if (lineWidth > maxLineWidth) { maxLineWidth = lineWidth; } lineWidth = 0; continue; // don't add the space back } if (lineWidth > maxLineWidth) maxLineWidth = lineWidth; message += msg[i]; } // If the text object is a speech subtitle, the y parameter is the // coordinate of the bottom of the text block (instead of the top). It means // that every extra line pushes the previous lines up, instead of being // printed further down the screen. const int SCREEN_TOP_MARGIN = 16; if (_isSpeech) { _y -= _numberLines * _font->getHeight(); if (_y < SCREEN_TOP_MARGIN) { _y = SCREEN_TOP_MARGIN; } } _textObjectHandle = (GfxBase::TextObjectHandle **)malloc(sizeof(long) * _numberLines); _bitmapWidthPtr = new int[_numberLines]; for (int j = 0; j < _numberLines; j++) { int nextLinePos, cutLen; const char *pos = strchr(message.c_str(), '\n'); if (pos) { nextLinePos = pos - message.c_str(); cutLen = nextLinePos + 1; } else { nextLinePos = message.size(); cutLen = nextLinePos; } Common::String currentLine(message.c_str(), message.c_str() + nextLinePos); _bitmapWidthPtr[j] = 0; for (unsigned int i = 0; i < currentLine.size(); ++i) { _bitmapWidthPtr[j] += MAX(_font->getCharWidth(currentLine[i]), _font->getCharDataWidth(currentLine[i])); } _textBitmap = new uint8[_font->getHeight() * (_bitmapWidthPtr[j] + 1)]; memset(_textBitmap, 0, _font->getHeight() * (_bitmapWidthPtr[j] + 1)); // Fill bitmap int startOffset = 0; for (unsigned int d = 0; d < currentLine.size(); d++) { int ch = currentLine[d]; int8 startingLine = _font->getCharStartingLine(ch) + _font->getBaseOffsetY(); int32 charDataWidth = _font->getCharDataWidth(ch); int32 charWidth = _font->getCharWidth(ch); int8 startingCol = _font->getCharStartingCol(ch); for (int line = 0; line < _font->getCharDataHeight(ch); line++) { int offset = startOffset + ((_bitmapWidthPtr[j] + 1) * (line + startingLine)); for (int r = 0; r < charDataWidth; r++) { const byte pixel = *(_font->getCharData(ch) + r + (charDataWidth * line)); byte *dst = _textBitmap + offset + startingCol + r; if (*dst == 0 && pixel != 0) _textBitmap[offset + startingCol + r] = pixel; } if (line + startingLine >= _font->getHeight()) break; } startOffset += charWidth; } _textObjectHandle[j] = g_driver->createTextBitmap(_textBitmap, _bitmapWidthPtr[j] + 1, _font->getHeight(), _fgColor); delete[] _textBitmap; for (int count = 0; count < cutLen; count++) message.deleteChar(0); } _created = true; }