void DirectorEngine::loadSharedCastsFrom(Common::String filename) { Archive *shardcst; if (getVersion() < 4) { shardcst = new RIFFArchive(); } else { shardcst = new RIFXArchive(); } shardcst->openFile(filename); Score *castScore = new Score(this); Common::SeekableSubReadStreamEndian *castStream = shardcst->getResource(MKTAG('V','W','C','R'), 1024); castScore->loadCastData(*castStream); *_sharedCasts = castScore->_casts; Common::Array<uint16> dib = shardcst->getResourceIDList(MKTAG('D','I','B',' ')); if (dib.size() != 0) { Common::Array<uint16>::iterator iterator; for (iterator = dib.begin(); iterator != dib.end(); ++iterator) { debug(3, "Shared DIB %d", *iterator); _sharedDIB->setVal(*iterator, shardcst->getResource(MKTAG('D','I','B',' '), *iterator)); } } Common::Array<uint16> stxt = shardcst->getResourceIDList(MKTAG('S','T','X','T')); if (stxt.size() != 0) { Common::Array<uint16>::iterator iterator; for (iterator = stxt.begin(); iterator != stxt.end(); ++iterator) { debug(3, "Shared STXT %d", *iterator); _sharedSTXT->setVal(*iterator, shardcst->getResource(MKTAG('S','T','X','T'), *iterator)); } } Common::Array<uint16> bmp = shardcst->getResourceIDList(MKTAG('B','I','T','D')); if (bmp.size() != 0) { Common::Array<uint16>::iterator iterator; for (iterator = bmp.begin(); iterator != bmp.end(); ++iterator) { _sharedBMP->setVal(*iterator, shardcst->getResource(MKTAG('B','I','T','D'), *iterator)); } } Common::Array<uint16> sound = shardcst->getResourceIDList(MKTAG('S','N','D',' ')); if (stxt.size() != 0) { Common::Array<uint16>::iterator iterator; for (iterator = sound.begin(); iterator != sound.end(); ++iterator) { _sharedSound->setVal(*iterator, shardcst->getResource(MKTAG('S','N','D',' '), *iterator)); } } }
void DirectorEngine::loadSharedCastsFrom(Common::String filename) { Archive *shardcst = createArchive(); debugC(1, kDebugLoading, "Loading Shared cast '%s'", filename.c_str()); shardcst->openFile(filename); _sharedDIB = new Common::HashMap<int, Common::SeekableSubReadStreamEndian *>; _sharedSTXT = new Common::HashMap<int, Common::SeekableSubReadStreamEndian *>; _sharedSound = new Common::HashMap<int, Common::SeekableSubReadStreamEndian *>; _sharedBMP = new Common::HashMap<int, Common::SeekableSubReadStreamEndian *>; Score *castScore = new Score(this, shardcst); castScore->loadConfig(*shardcst->getResource(MKTAG('V','W','C','F'), 1024)); castScore->loadCastData(*shardcst->getResource(MKTAG('V','W','C','R'), 1024)); _sharedCasts = &castScore->_casts; Common::Array<uint16> dib = shardcst->getResourceIDList(MKTAG('D','I','B',' ')); if (dib.size() != 0) { debugC(3, kDebugLoading, "Loading %d DIBs", dib.size()); for (Common::Array<uint16>::iterator iterator = dib.begin(); iterator != dib.end(); ++iterator) { debugC(3, kDebugLoading, "Shared DIB %d", *iterator); _sharedDIB->setVal(*iterator, shardcst->getResource(MKTAG('D','I','B',' '), *iterator)); } } Common::Array<uint16> stxt = shardcst->getResourceIDList(MKTAG('S','T','X','T')); if (stxt.size() != 0) { debugC(3, kDebugLoading, "Loading %d STXTs", stxt.size()); for (Common::Array<uint16>::iterator iterator = stxt.begin(); iterator != stxt.end(); ++iterator) { debugC(3, kDebugLoading, "Shared STXT %d", *iterator); _sharedSTXT->setVal(*iterator, shardcst->getResource(MKTAG('S','T','X','T'), *iterator)); } } Common::Array<uint16> bmp = shardcst->getResourceIDList(MKTAG('B','I','T','D')); if (bmp.size() != 0) { debugC(3, kDebugLoading, "Loading %d BITDs", bmp.size()); for (Common::Array<uint16>::iterator iterator = bmp.begin(); iterator != bmp.end(); ++iterator) { _sharedBMP->setVal(*iterator, shardcst->getResource(MKTAG('B','I','T','D'), *iterator)); } } Common::Array<uint16> sound = shardcst->getResourceIDList(MKTAG('S','N','D',' ')); if (stxt.size() != 0) { debugC(3, kDebugLoading, "Loading %d SNDs", sound.size()); for (Common::Array<uint16>::iterator iterator = sound.begin(); iterator != sound.end(); ++iterator) { _sharedSound->setVal(*iterator, shardcst->getResource(MKTAG('S','N','D',' '), *iterator)); } } }
void listSavegames(Common::Array<SavegameDesc> &saves) { Common::SaveFileManager *saveFileMan = g_engine->getSaveFileManager(); // Load all saves Common::StringList saveNames = saveFileMan->listSavefiles(((SciEngine *)g_engine)->getSavegamePattern()); for (Common::StringList::const_iterator iter = saveNames.begin(); iter != saveNames.end(); ++iter) { Common::String filename = *iter; Common::SeekableReadStream *in; if ((in = saveFileMan->openForLoading(filename))) { SavegameMetadata meta; if (!get_savegame_metadata(in, &meta)) { // invalid delete in; continue; } delete in; SavegameDesc desc; desc.id = strtol(filename.end() - 3, NULL, 10); desc.date = meta.savegame_date; desc.time = meta.savegame_time; debug(3, "Savegame in file %s ok, id %d", filename.c_str(), desc.id); saves.push_back(desc); } } // Sort the list by creation date of the saves qsort(saves.begin(), saves.size(), sizeof(SavegameDesc), _savegame_index_struct_compare); }
bool SaveReader::getInfo(Common::SeekableReadStream &stream, SavePartInfo &info) { // Remeber the stream's starting position to seek back to uint32 startPos = stream.pos(); // Get parts' basic information Common::Array<SaveContainer::PartInfo> *partsInfo = getPartsInfo(stream); // No parts => fail if (!partsInfo) { stream.seek(startPos); return false; } bool result = false; // Iterate over all parts for (Common::Array<SaveContainer::PartInfo>::iterator it = partsInfo->begin(); it != partsInfo->end(); ++it) { // Check for the info part if (it->id == SavePartInfo::kID) { if (!stream.seek(it->offset)) break; // Read it result = info.read(stream); break; } } stream.seek(startPos); delete partsInfo; return result; }
// Print a list of all registered commands (and variables, if any), // nicely word-wrapped. bool Debugger::Cmd_Help(int argc, const char **argv) { #ifndef USE_TEXT_CONSOLE const int charsPerLine = _debuggerDialog->getCharsPerLine(); #elif defined(USE_READLINE) int charsPerLine, rows; rl_get_screen_size(&rows, &charsPerLine); #else // Can we do better? const int charsPerLine = 80; #endif int width, size; uint i; DebugPrintf("Commands are:\n"); // Obtain a list of sorted command names Common::Array<Common::String> cmds; CommandsMap::const_iterator iter, e = _cmds.end(); for (iter = _cmds.begin(); iter != e; ++iter) { cmds.push_back(iter->_key); } sort(cmds.begin(), cmds.end()); // Print them all width = 0; for (i = 0; i < cmds.size(); i++) { size = cmds[i].size() + 1; if ((width + size) >= charsPerLine) { DebugPrintf("\n"); width = size; } else width += size; DebugPrintf("%s ", cmds[i].c_str()); } DebugPrintf("\n"); if (!_dvars.empty()) { DebugPrintf("\n"); DebugPrintf("Variables are:\n"); width = 0; for (i = 0; i < _dvars.size(); i++) { size = _dvars[i].name.size() + 1; if ((width + size) >= charsPerLine) { DebugPrintf("\n"); width = size; } else width += size; DebugPrintf("%s ", _dvars[i].name.c_str()); } DebugPrintf("\n"); } return true; }
Node *Tree::aStarSearch_singlePass() { float currentT = 0.0; Node *retNode = NULL; static int maxTime = 0; if (_currentChildIndex == 1) { maxTime = _ai->getPlayerMaxTime(); } if (_currentChildIndex) { if (!(_currentMap->size())) { retNode = _currentNode; return retNode; } _currentNode = _currentMap->front()->node; _currentMap->erase(_currentMap->begin()); } if ((_currentNode->getDepth() < _maxDepth) && (Node::getNodeCount() < _maxNodes) && ((!maxTime) || (_ai->getTimerValue(3) < maxTime))) { // Generate nodes _currentChildIndex = _currentNode->generateChildren(); if (_currentChildIndex) { Common::Array<Node *> vChildren = _currentNode->getChildren(); if (!vChildren.size() && !_currentMap->size()) { _currentChildIndex = 0; retNode = _currentNode; } for (Common::Array<Node *>::iterator i = vChildren.begin(); i != vChildren.end(); i++) { IContainedObject *pTemp = (*i)->getContainedObject(); currentT = pTemp->calcT(); if (currentT == SUCCESS) { retNode = *i; i = vChildren.end() - 1; } else { _currentMap->insert(new TreeNode(currentT, (*i))); } } if (!(_currentMap->size()) && (currentT != SUCCESS)) { assert(_currentNode != NULL); retNode = _currentNode; } } } else { retNode = _currentNode; } return retNode; }
void run_gc(EngineState *s) { SegManager *segMan = s->_segMan; // Some debug stuff debugC(kDebugLevelGC, "[GC] Running..."); #ifdef GC_DEBUG_CODE const char *segnames[SEG_TYPE_MAX + 1]; int segcount[SEG_TYPE_MAX + 1]; memset(segnames, 0, sizeof(segnames)); memset(segcount, 0, sizeof(segcount)); #endif // Compute the set of all segments references currently in use. AddrSet *activeRefs = findAllActiveReferences(s); // Iterate over all segments, and check for each whether it // contains stuff that can be collected. const Common::Array<SegmentObj *> &heap = segMan->getSegments(); for (uint seg = 1; seg < heap.size(); seg++) { SegmentObj *mobj = heap[seg]; if (mobj != NULL) { #ifdef GC_DEBUG_CODE const SegmentType type = mobj->getType(); segnames[type] = segmentTypeNames[type]; #endif // Get a list of all deallocatable objects in this segment, // then free any which are not referenced from somewhere. const Common::Array<reg_t> tmp = mobj->listAllDeallocatable(seg); for (Common::Array<reg_t>::const_iterator it = tmp.begin(); it != tmp.end(); ++it) { const reg_t addr = *it; if (!activeRefs->contains(addr)) { // Not found -> we can free it mobj->freeAtAddress(segMan, addr); debugC(kDebugLevelGC, "[GC] Deallocating %04x:%04x", PRINT_REG(addr)); #ifdef GC_DEBUG_CODE segcount[type]++; #endif } } } } delete activeRefs; #ifdef GC_DEBUG_CODE // Output debug summary of garbage collection debugC(kDebugLevelGC, "[GC] Summary:"); for (int i = 0; i <= SEG_TYPE_MAX; i++) if (segcount[i]) debugC(kDebugLevelGC, "\t%d\t* %s", segcount[i], segnames[i]); #endif }
bool Console::Cmd_DumpKnowledge(int argc, const char **argv) { Resources::Level *level = StarkGlobal->getCurrent()->getLevel(); Resources::Location *location = StarkGlobal->getCurrent()->getLocation(); Common::Array<Resources::Knowledge *> knowledge = level->listChildrenRecursive<Resources::Knowledge>(); knowledge.insert_at(knowledge.size(), location->listChildrenRecursive<Resources::Knowledge>()); Common::Array<Resources::Knowledge *>::iterator it; for (it = knowledge.begin(); it != knowledge.end(); ++it) { (*it)->print(); } return true; }
bool GobConsole::cmd_listArchives(int argc, const char **argv) { Common::Array<ArchiveInfo> info; _vm->_dataIO->getArchiveInfo(info); DebugPrintf(" Archive | Base | FileCount\n"); DebugPrintf("--------------------------------\n"); for (Common::Array<ArchiveInfo>::const_iterator it = info.begin(); it != info.end(); ++it) if (!it->name.empty()) DebugPrintf("%13s | %d | %d\n", it->name.c_str(), it->base, it->fileCount); return true; }
virtual SaveStateList listSaves(const char *target) const { Common::SaveFileManager *saveFileMan = g_system->getSavefileManager(); Common::String pattern = Common::String::format("%s??", target); // Get list of savefiles for target game Common::StringArray filenames = saveFileMan->listSavefiles(pattern); Common::Array<int> slots; for (Common::StringArray::const_iterator file = filenames.begin(); file != filenames.end(); ++file) { // Obtain the last 2 digits of the filename, since they correspond to the save slot int slotNum = atoi(file->c_str() + file->size() - 2); // Ensure save slot is within valid range if (slotNum >= 1 && slotNum <= 10) { slots.push_back(slotNum); } } // Sort save slot ids Common::sort<int>(slots.begin(), slots.end()); // Load save index Common::String fileEpa = Common::String::format("%s.epa", target); Common::InSaveFile *epa = saveFileMan->openForLoading(fileEpa); // Get savegame names from index Common::String saveDesc; SaveStateList saveList; int line = 1; for (uint i = 0; i < slots.size(); i++) { // ignore lines corresponding to unused saveslots for (; line < slots[i]; line++) epa->readLine(); // copy the name in the line corresponding to the save slot and truncate to 22 characters saveDesc = Common::String(epa->readLine().c_str(), 22); // handle cases where the save directory and save index are detectably out of sync if (saveDesc == "*") saveDesc = "No name specified."; // increment line number to keep it in sync with slot number line++; // Insert savegame name into list saveList.push_back(SaveStateDescriptor(slots[i], saveDesc)); } delete epa; return saveList; }
static void initDijkstraNodes(DijkstraNode::Container &dijkstraNodes, const Region ®ion, const Vertex &start, const Common::Array<Vertex> &nodes) { // Allocate sufficient space in the array dijkstraNodes.resize(nodes.size()); // Initialize all the nodes which are visible from the starting node DijkstraNode::Iter dijkstraIter = dijkstraNodes.begin(); for (Common::Array<Vertex>::const_iterator nodesIter = nodes.begin(); nodesIter != nodes.end(); nodesIter++, dijkstraIter++) { (*dijkstraIter).parentIter = dijkstraNodes.end(); if (region.isLineOfSight(*nodesIter, start))(*dijkstraIter).cost = (*nodesIter).distance(start); } assert(dijkstraIter == dijkstraNodes.end()); }
BaseSurface *BaseFontTT::renderTextToTexture(const WideString &text, int width, TTextAlign align, int maxHeight, int &textOffset) { //TextLineList lines; // TODO: Use WideString-conversion here. //WrapText(text, width, maxHeight, lines); Common::Array<Common::String> lines; _font->wordWrapText(text, width, lines); while (maxHeight > 0 && lines.size() * _lineHeight > maxHeight) { lines.pop_back(); } if (lines.size() == 0) { return nullptr; } Graphics::TextAlign alignment = Graphics::kTextAlignInvalid; if (align == TAL_LEFT) { alignment = Graphics::kTextAlignLeft; } else if (align == TAL_CENTER) { alignment = Graphics::kTextAlignCenter; } else if (align == TAL_RIGHT) { alignment = Graphics::kTextAlignRight; } debugC(kWintermuteDebugFont, "%s %d %d %d %d", text.c_str(), RGBCOLGetR(_layers[0]->_color), RGBCOLGetG(_layers[0]->_color), RGBCOLGetB(_layers[0]->_color), RGBCOLGetA(_layers[0]->_color)); // void drawString(Surface *dst, const Common::String &str, int x, int y, int w, uint32 color, TextAlign align = kTextAlignLeft, int deltax = 0, bool useEllipsis = true) const; Graphics::Surface *surface = new Graphics::Surface(); if (_deletableFont) { // We actually have a TTF surface->create((uint16)width, (uint16)(_lineHeight * lines.size()), Graphics::PixelFormat(4, 8, 8, 8, 8, 16, 8, 0, 24)); } else { // We are using a fallback, they can't do 32bpp surface->create((uint16)width, (uint16)(_lineHeight * lines.size()), Graphics::PixelFormat(2, 5, 5, 5, 1, 11, 6, 1, 0)); } uint32 useColor = 0xffffffff; Common::Array<Common::String>::iterator it; int heightOffset = 0; for (it = lines.begin(); it != lines.end(); ++it) { _font->drawString(surface, *it, 0, heightOffset, width, useColor, alignment); heightOffset += (int)_lineHeight; } BaseSurface *retSurface = _gameRef->_renderer->createSurface(); Graphics::Surface *convertedSurface = surface->convertTo(Graphics::PixelFormat(4, 8, 8, 8, 8, 16, 8, 0, 24)); retSurface->putSurface(*convertedSurface, true); convertedSurface->free(); surface->free(); delete surface; delete convertedSurface; return retSurface; // TODO: _isUnderline, _isBold, _isItalic, _isStriked }
Node *Tree::aStarSearch() { Common::SortedArray<TreeNode *> mmfpOpen(compareTreeNodes); Node *currentNode = NULL; float currentT; Node *retNode = NULL; float temp = pBaseNode->getContainedObject()->calcT(); if (static_cast<int>(temp) != SUCCESS) { mmfpOpen.insert(new TreeNode(pBaseNode->getObjectT(), pBaseNode)); while (mmfpOpen.size() && (retNode == NULL)) { currentNode = mmfpOpen.front()->node; mmfpOpen.erase(mmfpOpen.begin()); if ((currentNode->getDepth() < _maxDepth) && (Node::getNodeCount() < _maxNodes)) { // Generate nodes Common::Array<Node *> vChildren = currentNode->getChildren(); for (Common::Array<Node *>::iterator i = vChildren.begin(); i != vChildren.end(); i++) { IContainedObject *pTemp = (*i)->getContainedObject(); currentT = pTemp->calcT(); if (currentT == SUCCESS) retNode = *i; else mmfpOpen.insert(new TreeNode(currentT, (*i))); } } else { retNode = currentNode; } } } else { retNode = pBaseNode; } return retNode; }
Graphics::Surface *TruetypeFont::drawTextToSurface(const Common::String &text, uint16 textColor, int maxWidth, int maxHeight, Graphics::TextAlign align, bool wrap) { if (text.equals("")) { return nullptr; } Graphics::Surface *surface = new Graphics::Surface(); if (!wrap) { int width = MIN(_font->getStringWidth(text), maxWidth); surface->create(width, _lineHeight, Graphics::PixelFormat(2, 5, 6, 5, 0, 11, 5, 0, 0)); // TODO: Add better alpha support by getting the pixels from the backbuffer. // However doing that requires some kind of caching system so future text doesn't try to use this text as it's alpha background. surface->fillRect(Common::Rect(0, 0, surface->w, surface->h), 0); _font->drawString(surface, text, 0, 0, maxWidth, textColor, align); return surface; } Common::Array<Common::String> lines; _font->wordWrapText(text, maxWidth, lines); while (maxHeight > 0 && (int)lines.size() * _lineHeight > maxHeight) { lines.pop_back(); } if (lines.size() == 0) { delete surface; return nullptr; } surface->create(maxWidth, lines.size() * _lineHeight, Graphics::PixelFormat(2, 5, 6, 5, 0, 11, 5, 0, 0)); surface->fillRect(Common::Rect(0, 0, surface->w, surface->h), 0); int heightOffset = 0; for (Common::Array<Common::String>::iterator it = lines.begin(); it != lines.end(); it++) { _font->drawString(surface, *it, 0, 0 + heightOffset, maxWidth, textColor, align); heightOffset += _lineHeight; } return surface; }
TestbedOptionsDialog::TestbedOptionsDialog(Common::Array<Testsuite *> &tsList, TestbedConfigManager *tsConfMan) : GUI::Dialog("Browser"), _testbedConfMan(tsConfMan) { new GUI::StaticTextWidget(this, "Browser.Headline", "Select Testsuites to Execute"); new GUI::StaticTextWidget(this, "Browser.Path", "Use Doubleclick to select/deselect"); // Construct a String Array Common::Array<Testsuite *>::const_iterator iter; Common::String description; uint selected = 0; for (iter = tsList.begin(); iter != tsList.end(); iter++) { _testSuiteArray.push_back(*iter); description = (*iter)->getDescription(); if ((*iter)->isEnabled()) { _testSuiteDescArray.push_back(description + "(selected)"); selected++; _colors.push_back(GUI::ThemeEngine::kFontColorNormal); } else { _testSuiteDescArray.push_back(description); _colors.push_back(GUI::ThemeEngine::kFontColorAlternate); } } _testListDisplay = new TestbedListWidget(this, "Browser.List", _testSuiteArray); _testListDisplay->setNumberingMode(GUI::kListNumberingOff); _testListDisplay->setList(_testSuiteDescArray, &_colors); // This list shouldn't be editable _testListDisplay->setEditable(false); if (selected > (tsList.size() - selected)) { _selectButton = new GUI::ButtonWidget(this, "Browser.Up", "Deselect All", 0, kTestbedDeselectAll, 0); } else { _selectButton = new GUI::ButtonWidget(this, "Browser.Up", "Select All", 0, kTestbedSelectAll, 0); } new GUI::ButtonWidget(this, "Browser.Cancel", "Run tests", 0, GUI::kCloseCmd); new GUI::ButtonWidget(this, "Browser.Choose", "Exit Testbed", 0, kTestbedQuitCmd); }
void TextRenderer::drawTextWithWordWrapping(const Common::String &text, Graphics::Surface &dest) { Common::Array<TextSurface> textSurfaces; Common::Array<uint> lineWidths; Common::Array<TextJustification> lineJustifications; // Create the initial text state TextStyleState currentState; // Create an empty font and bind it to the state StyledTTFont font(_engine); currentState.updateFontWithTextState(font); Common::String currentSentence; // Not a true 'grammatical' sentence. Rather, it's just a collection of words Common::String currentWord; int sentenceWidth = 0; int wordWidth = 0; int lineWidth = 0; int lineHeight = font.getFontHeight(); uint currentLineNumber = 0u; uint numSpaces = 0u; int spaceWidth = 0; // The pixel offset to the currentSentence Common::Point sentencePixelOffset; uint i = 0u; uint stringlen = text.size(); while (i < stringlen) { if (text[i] == '<') { // Flush the currentWord to the currentSentence currentSentence += currentWord; sentenceWidth += wordWidth; // Reset the word variables currentWord.clear(); wordWidth = 0; // Parse the style tag uint startTextPosition = i; while (i < stringlen && text[i] != '>') { ++i; } uint endTextPosition = i; uint32 textColor = currentState.getTextColor(_engine); uint stateChanges = 0u; if ((endTextPosition - startTextPosition - 1) > 0) { stateChanges = currentState.parseStyle(Common::String(text.c_str() + startTextPosition + 1), endTextPosition - startTextPosition - 1); } if (stateChanges & (TEXT_CHANGE_FONT_TYPE | TEXT_CHANGE_FONT_STYLE)) { // Use the last state to render out the current sentence // Styles apply to the text 'after' them if (!currentSentence.empty()) { textSurfaces.push_back(TextSurface(font.renderSolidText(currentSentence, textColor), sentencePixelOffset, currentLineNumber)); lineWidth += sentenceWidth; sentencePixelOffset.x += sentenceWidth; // Reset the sentence variables currentSentence.clear(); sentenceWidth = 0; } // Update the current state with the style information currentState.updateFontWithTextState(font); lineHeight = MAX(lineHeight, font.getFontHeight()); spaceWidth = font.getCharWidth(' '); } if (stateChanges & TEXT_CHANGE_NEWLINE) { // If the current sentence has content, render it out if (!currentSentence.empty()) { textSurfaces.push_back(TextSurface(font.renderSolidText(currentSentence, textColor), sentencePixelOffset, currentLineNumber)); } // Set line width lineWidths.push_back(lineWidth + sentenceWidth - (numSpaces * spaceWidth)); currentSentence.clear(); sentenceWidth = 0; // Update the offsets sentencePixelOffset.x = 0u; sentencePixelOffset.y += lineHeight; // Reset the line variables lineHeight = font.getFontHeight(); lineWidth = 0; ++currentLineNumber; lineJustifications.push_back(currentState._justification); } if (stateChanges & TEXT_CHANGE_HAS_STATE_BOX) { Common::String temp = Common::String::format("%d", _engine->getScriptManager()->getStateValue(currentState._statebox)); wordWidth += font.getStringWidth(temp); // If the word causes the line to overflow, render the sentence and start a new line if (lineWidth + sentenceWidth + wordWidth > dest.w) { textSurfaces.push_back(TextSurface(font.renderSolidText(currentSentence, textColor), sentencePixelOffset, currentLineNumber)); // Set line width lineWidths.push_back(lineWidth + sentenceWidth - (numSpaces * spaceWidth)); currentSentence.clear(); sentenceWidth = 0; // Update the offsets sentencePixelOffset.x = 0u; sentencePixelOffset.y += lineHeight; // Reset the line variables lineHeight = font.getFontHeight(); lineWidth = 0; ++currentLineNumber; lineJustifications.push_back(currentState._justification); } } } else { currentWord += text[i]; wordWidth += font.getCharWidth(text[i]); if (text[i] == ' ') { // When we hit the first space, flush the current word to the sentence if (!currentWord.empty()) { currentSentence += currentWord; sentenceWidth += wordWidth; currentWord.clear(); wordWidth = 0; } // We track the number of spaces so we can disregard their width in lineWidth calculations ++numSpaces; } else { // If the word causes the line to overflow, render the sentence and start a new line if (lineWidth + sentenceWidth + wordWidth > dest.w) { // Only render out content if (!currentSentence.empty()) { textSurfaces.push_back(TextSurface(font.renderSolidText(currentSentence, currentState.getTextColor(_engine)), sentencePixelOffset, currentLineNumber)); } // Set line width lineWidths.push_back(lineWidth + sentenceWidth - (numSpaces * spaceWidth)); currentSentence.clear(); sentenceWidth = 0; // Update the offsets sentencePixelOffset.x = 0u; sentencePixelOffset.y += lineHeight; // Reset the line variables lineHeight = font.getFontHeight(); lineWidth = 0; ++currentLineNumber; lineJustifications.push_back(currentState._justification); } numSpaces = 0u; } } i++; } // Render out any remaining words/sentences if (!currentWord.empty() || !currentSentence.empty()) { currentSentence += currentWord; sentenceWidth += wordWidth; textSurfaces.push_back(TextSurface(font.renderSolidText(currentSentence, currentState.getTextColor(_engine)), sentencePixelOffset, currentLineNumber)); } lineWidths.push_back(lineWidth + sentenceWidth); lineJustifications.push_back(currentState._justification); for (Common::Array<TextSurface>::iterator iter = textSurfaces.begin(); iter != textSurfaces.end(); ++iter) { Common::Rect empty; if (lineJustifications[iter->_lineNumber] == TEXT_JUSTIFY_LEFT) { _engine->getRenderManager()->blitSurfaceToSurface(*iter->_surface, empty, dest, iter->_surfaceOffset.x, iter->_surfaceOffset.y, 0); } else if (lineJustifications[iter->_lineNumber] == TEXT_JUSTIFY_CENTER) { _engine->getRenderManager()->blitSurfaceToSurface(*iter->_surface, empty, dest, ((dest.w - lineWidths[iter->_lineNumber]) / 2) + iter->_surfaceOffset.x, iter->_surfaceOffset.y, 0); } else if (lineJustifications[iter->_lineNumber] == TEXT_JUSTIFY_RIGHT) { _engine->getRenderManager()->blitSurfaceToSurface(*iter->_surface, empty, dest, dest.w - lineWidths[iter->_lineNumber] + iter->_surfaceOffset.x, iter->_surfaceOffset.y, 0); } // Release memory iter->_surface->free(); delete iter->_surface; } }
BaseSurface *BaseFontTT::renderTextToTexture(const WideString &text, int width, TTextAlign align, int maxHeight, int &textOffset) { //TextLineList lines; // TODO: Use WideString-conversion here. //WrapText(text, width, maxHeight, lines); Common::Array<WideString> lines; _font->wordWrapText(text, width, lines); while (maxHeight > 0 && lines.size() * _lineHeight > maxHeight) { lines.pop_back(); } if (lines.size() == 0) { return nullptr; } Graphics::TextAlign alignment = Graphics::kTextAlignInvalid; if (align == TAL_LEFT) { alignment = Graphics::kTextAlignLeft; } else if (align == TAL_CENTER) { alignment = Graphics::kTextAlignCenter; } else if (align == TAL_RIGHT) { alignment = Graphics::kTextAlignRight; } // TODO: This debug call does not work with WideString because text.c_str() returns an uint32 array. //debugC(kWintermuteDebugFont, "%s %d %d %d %d", text.c_str(), RGBCOLGetR(_layers[0]->_color), RGBCOLGetG(_layers[0]->_color), RGBCOLGetB(_layers[0]->_color), RGBCOLGetA(_layers[0]->_color)); // void drawString(Surface *dst, const Common::String &str, int x, int y, int w, uint32 color, TextAlign align = kTextAlignLeft, int deltax = 0, bool useEllipsis = true) const; Graphics::Surface *surface = new Graphics::Surface(); surface->create((uint16)width, (uint16)(_lineHeight * lines.size()), _gameRef->_renderer->getPixelFormat()); uint32 useColor = 0xffffffff; Common::Array<WideString>::iterator it; int heightOffset = 0; for (it = lines.begin(); it != lines.end(); ++it) { _font->drawString(surface, *it, 0, heightOffset, width, useColor, alignment); heightOffset += (int)_lineHeight; } BaseSurface *retSurface = _gameRef->_renderer->createSurface(); if (_deletableFont) { // Reconstruct the alpha channel of the font. // Since we painted it with color 0xFFFFFFFF onto a black background, // the alpha channel is gone, but the color value of each pixel corresponds // to its original alpha value. Graphics::PixelFormat format = _gameRef->_renderer->getPixelFormat(); uint32 *pixels = (uint32 *)surface->getPixels(); // This is a Surface we created ourselves, so no empty space between rows. for (int i = 0; i < surface->w * surface->h; ++i) { uint8 a, r, g, b; format.colorToRGB(*pixels, r, g, b); a = r; *pixels++ = format.ARGBToColor(a, r, g, b); } } retSurface->putSurface(*surface, true); surface->free(); delete surface; return retSurface; // TODO: _isUnderline, _isBold, _isItalic, _isStriked }
bool SXString::scCallMethod(ScScript *script, ScStack *stack, ScStack *thisStack, const char *name) { ////////////////////////////////////////////////////////////////////////// // Substring ////////////////////////////////////////////////////////////////////////// if (strcmp(name, "Substring") == 0) { stack->correctParams(2); int start = stack->pop()->getInt(); int end = stack->pop()->getInt(); if (end < start) { BaseUtils::swap(&start, &end); } //try { WideString str; if (_gameRef->_textEncoding == TEXT_UTF8) { str = StringUtil::utf8ToWide(_string); } else { str = StringUtil::ansiToWide(_string); } //WideString subStr = str.substr(start, end - start + 1); WideString subStr(str.c_str() + start, end - start + 1); if (_gameRef->_textEncoding == TEXT_UTF8) { stack->pushString(StringUtil::wideToUtf8(subStr).c_str()); } else { stack->pushString(StringUtil::wideToAnsi(subStr).c_str()); } // } catch (std::exception &) { // stack->pushNULL(); // } return STATUS_OK; } ////////////////////////////////////////////////////////////////////////// // Substr ////////////////////////////////////////////////////////////////////////// else if (strcmp(name, "Substr") == 0) { stack->correctParams(2); int start = stack->pop()->getInt(); ScValue *val = stack->pop(); int len = val->getInt(); if (!val->isNULL() && len <= 0) { stack->pushString(""); return STATUS_OK; } if (val->isNULL()) { len = strlen(_string) - start; } // try { WideString str; if (_gameRef->_textEncoding == TEXT_UTF8) { str = StringUtil::utf8ToWide(_string); } else { str = StringUtil::ansiToWide(_string); } // WideString subStr = str.substr(start, len); WideString subStr(str.c_str() + start, len); if (_gameRef->_textEncoding == TEXT_UTF8) { stack->pushString(StringUtil::wideToUtf8(subStr).c_str()); } else { stack->pushString(StringUtil::wideToAnsi(subStr).c_str()); } // } catch (std::exception &) { // stack->pushNULL(); // } return STATUS_OK; } ////////////////////////////////////////////////////////////////////////// // ToUpperCase ////////////////////////////////////////////////////////////////////////// else if (strcmp(name, "ToUpperCase") == 0) { stack->correctParams(0); WideString str; if (_gameRef->_textEncoding == TEXT_UTF8) { str = StringUtil::utf8ToWide(_string); } else { str = StringUtil::ansiToWide(_string); } str.toUppercase(); if (_gameRef->_textEncoding == TEXT_UTF8) { stack->pushString(StringUtil::wideToUtf8(str).c_str()); } else { stack->pushString(StringUtil::wideToAnsi(str).c_str()); } return STATUS_OK; } ////////////////////////////////////////////////////////////////////////// // ToLowerCase ////////////////////////////////////////////////////////////////////////// else if (strcmp(name, "ToLowerCase") == 0) { stack->correctParams(0); WideString str; if (_gameRef->_textEncoding == TEXT_UTF8) { str = StringUtil::utf8ToWide(_string); } else { str = StringUtil::ansiToWide(_string); } str.toLowercase(); if (_gameRef->_textEncoding == TEXT_UTF8) { stack->pushString(StringUtil::wideToUtf8(str).c_str()); } else { stack->pushString(StringUtil::wideToAnsi(str).c_str()); } return STATUS_OK; } ////////////////////////////////////////////////////////////////////////// // IndexOf ////////////////////////////////////////////////////////////////////////// else if (strcmp(name, "IndexOf") == 0) { stack->correctParams(2); const char *strToFind = stack->pop()->getString(); int index = stack->pop()->getInt(); WideString str; if (_gameRef->_textEncoding == TEXT_UTF8) { str = StringUtil::utf8ToWide(_string); } else { str = StringUtil::ansiToWide(_string); } WideString toFind; if (_gameRef->_textEncoding == TEXT_UTF8) { toFind = StringUtil::utf8ToWide(strToFind); } else { toFind = StringUtil::ansiToWide(strToFind); } int indexOf = StringUtil::indexOf(str, toFind, index); stack->pushInt(indexOf); return STATUS_OK; } ////////////////////////////////////////////////////////////////////////// // Split ////////////////////////////////////////////////////////////////////////// else if (strcmp(name, "Split") == 0) { stack->correctParams(1); ScValue *val = stack->pop(); char separators[MAX_PATH_LENGTH] = ","; if (!val->isNULL()) { strcpy(separators, val->getString()); } SXArray *array = new SXArray(_gameRef); if (!array) { stack->pushNULL(); return STATUS_OK; } WideString str; if (_gameRef->_textEncoding == TEXT_UTF8) { str = StringUtil::utf8ToWide(_string); } else { str = StringUtil::ansiToWide(_string); } WideString delims; if (_gameRef->_textEncoding == TEXT_UTF8) { delims = StringUtil::utf8ToWide(separators); } else { delims = StringUtil::ansiToWide(separators); } Common::Array<WideString> parts; uint32 start = 0; for(uint32 i = 0; i < str.size() + 1; i++) { char ch = str.c_str()[i]; if(ch=='\0' || delims.contains(ch)) { char *part = new char[i - start + 1]; if(i != start) { Common::strlcpy(part, str.c_str() + start, i - start + 1); part[i - start] = '\0'; } else { part[0] = '\0'; } val = new ScValue(_gameRef, part); array->push(val); delete[] part; delete val; val = nullptr; start = i + 1; } } for (Common::Array<WideString>::iterator it = parts.begin(); it != parts.end(); ++it) { WideString &part = (*it); if (_gameRef->_textEncoding == TEXT_UTF8) { val = new ScValue(_gameRef, StringUtil::wideToUtf8(part).c_str()); } else { val = new ScValue(_gameRef, StringUtil::wideToAnsi(part).c_str()); } array->push(val); delete val; val = nullptr; } stack->pushNative(array, false); return STATUS_OK; } else { return STATUS_FAILED; } }
bool T7GFont::load(Common::SeekableReadStream &stream) { // Read the mapping of characters to glyphs if (stream.read(_mapChar2Glyph, 128) < 128) { error("Groovie::T7GFont: Couldn't read the character to glyph map"); return false; } // Calculate the number of glyphs byte numGlyphs = 0; for (int i = 0; i < 128; i++) if (_mapChar2Glyph[i] >= numGlyphs) numGlyphs = _mapChar2Glyph[i] + 1; // Read the glyph offsets uint16 *glyphOffsets = new uint16[numGlyphs]; for (int i = 0; i < numGlyphs; i++) glyphOffsets[i] = stream.readUint16LE(); if (stream.eos()) { error("Groovie::T7GFont: Couldn't read the glyph offsets"); delete[] glyphOffsets; return false; } // Allocate the glyph data delete[] _glyphs; _glyphs = new Glyph[numGlyphs]; // Ensure we're ready to read the first glyph. (Most versions don't // need it, but the russian one does. This fixes bug #3095031.) stream.seek(glyphOffsets[0]); // Read the glyphs _maxHeight = _maxWidth = 0; for (int i = 0; (i < numGlyphs) && !stream.eos(); i++) { // Verify we're at the expected stream position if (stream.pos() != glyphOffsets[i]) { uint16 offset = glyphOffsets[i]; delete[] glyphOffsets; error("Groovie::T7GFont: Glyph %d starts at %d but the current " "offset is %d", i, offset, stream.pos()); return false; } // Read the glyph information Glyph *g = &_glyphs[i]; g->width = stream.readByte(); g->julia = stream.readByte(); // Read the pixels data into a dynamic array (we don't know its length) Common::Array<byte> data; data.reserve(300); byte b = stream.readByte(); while (!stream.eos() && (b != 0xFF)) { data.push_back(b); b = stream.readByte(); } // Verify the pixel data size assert (data.size() % g->width == 0); g->height = data.size() / g->width; // Copy the pixel data into the definitive static array g->pixels = new byte[data.size()]; memcpy(g->pixels, data.begin(), data.size()); // Update the max values if (g->width > _maxWidth) _maxWidth = g->width; if (g->height > _maxHeight) _maxHeight = g->height; } delete[] glyphOffsets; return true; }
void WorklistManager::pushArray(const Common::Array<reg_t> &tmp) { for (Common::Array<reg_t>::const_iterator it = tmp.begin(); it != tmp.end(); ++it) push(*it); }