void OpenGLGraphicsManager::displayMessageOnOSD(const char *msg) { #ifdef USE_OSD // HACK: Actually no client code should use graphics functions from // another thread. But the MT-32 emulator still does, thus we need to // make sure this doesn't happen while a updateScreen call is done. Common::StackLock lock(_osdMutex); // Slip up the lines. Common::Array<Common::String> osdLines; Common::StringTokenizer tokenizer(msg, "\n"); while (!tokenizer.empty()) { osdLines.push_back(tokenizer.nextToken()); } // Do the actual drawing like the SDL backend. const Graphics::Font *font = getFontOSD(); Graphics::Surface *dst = _osd->getSurface(); _osd->fill(0); _osd->flagDirty(); // Determine a rect which would contain the message string (clipped to the // screen dimensions). const int vOffset = 6; const int lineSpacing = 1; const int lineHeight = font->getFontHeight() + 2 * lineSpacing; int width = 0; int height = lineHeight * osdLines.size() + 2 * vOffset; for (uint i = 0; i < osdLines.size(); i++) { width = MAX(width, font->getStringWidth(osdLines[i]) + 14); } // Clip the rect width = MIN<int>(width, dst->w); height = MIN<int>(height, dst->h); int dstX = (dst->w - width) / 2; int dstY = (dst->h - height) / 2; // Draw a dark gray rect. const uint32 color = dst->format.RGBToColor(40, 40, 40); dst->fillRect(Common::Rect(dstX, dstY, dstX + width, dstY + height), color); // Render the message, centered, and in white const uint32 white = dst->format.RGBToColor(255, 255, 255); for (uint i = 0; i < osdLines.size(); ++i) { font->drawString(dst, osdLines[i], dstX, dstY + i * lineHeight + vOffset + lineSpacing, width, white, Graphics::kTextAlignCenter); } // Init the OSD display parameters. _osdAlpha = kOSDInitialAlpha; _osdFadeStartTime = g_system->getMillis() + kOSDFadeOutDelay; #endif }
void OpenGLGraphicsManager::osdMessageUpdateSurface() { // Split up the lines. Common::Array<Common::String> osdLines; Common::StringTokenizer tokenizer(_osdMessageNextData, "\n"); while (!tokenizer.empty()) { osdLines.push_back(tokenizer.nextToken()); } // Do the actual drawing like the SDL backend. const Graphics::Font *font = getFontOSD(); // Determine a rect which would contain the message string (clipped to the // screen dimensions). const int vOffset = 6; const int lineSpacing = 1; const int lineHeight = font->getFontHeight() + 2 * lineSpacing; uint width = 0; uint height = lineHeight * osdLines.size() + 2 * vOffset; for (uint i = 0; i < osdLines.size(); i++) { width = MAX<uint>(width, font->getStringWidth(osdLines[i]) + 14); } // Clip the rect width = MIN<uint>(width, _displayWidth); height = MIN<uint>(height, _displayHeight); delete _osdMessageSurface; _osdMessageSurface = nullptr; _osdMessageSurface = createSurface(_defaultFormatAlpha); assert(_osdMessageSurface); // We always filter the osd with GL_LINEAR. This assures it's // readable in case it needs to be scaled and does not affect it // otherwise. _osdMessageSurface->enableLinearFiltering(true); _osdMessageSurface->allocate(width, height); Graphics::Surface *dst = _osdMessageSurface->getSurface(); // Draw a dark gray rect. const uint32 color = dst->format.RGBToColor(40, 40, 40); dst->fillRect(Common::Rect(0, 0, width, height), color); // Render the message in white const uint32 white = dst->format.RGBToColor(255, 255, 255); for (uint i = 0; i < osdLines.size(); ++i) { font->drawString(dst, osdLines[i], 0, i * lineHeight + vOffset + lineSpacing, width, white, Graphics::kTextAlignCenter); } _osdMessageSurface->updateGLTexture(); // Init the OSD display parameters. _osdMessageAlpha = kOSDMessageInitialAlpha; _osdMessageFadeStartTime = g_system->getMillis() + kOSDMessageFadeOutDelay; // Clear the text update request _osdMessageNextData.clear(); _osdMessageChangeRequest = false; }