Files
scummvm-cursorfix/engines/agds/mjpgPlayer.cpp
2026-02-02 04:50:13 +01:00

140 lines
4.4 KiB
C++

/* ScummVM - Graphic Adventure Engine
*
* ScummVM is the legal property of its developers, whose names
* are too numerous to list here. Please refer to the COPYRIGHT
* file distributed with this source distribution.
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
*/
#include "agds/mjpgPlayer.h"
#include "agds/agds.h"
#include "agds/font.h"
#include "agds/object.h"
#include "agds/systemVariable.h"
#include "common/debug.h"
namespace AGDS {
MJPGPlayer::MJPGPlayer(Common::SeekableReadStream *stream, const Common::String &subtitles) : _stream(stream), _firstFramePos(_stream->pos()), _framesPlayed(0), _nextSubtitleIndex(0) {
uint pos = 0;
while (pos < subtitles.size()) {
auto next = subtitles.find('\n', pos);
if (next == subtitles.npos)
next = subtitles.size();
Common::String line = subtitles.substr(pos, next - pos);
uint begin, end;
int offset;
if (sscanf(line.c_str(), "{%u}{%u}%n", &begin, &end, &offset) != 2) {
warning("malformed subtitle line: %s", line.c_str());
pos = next + 1;
continue;
}
while (offset < static_cast<int>(line.size()) && line[offset] == ' ')
++offset;
line = line.substr(offset);
debug("subtitle line: %d-%d: %s", begin, end, line.c_str());
Text::Lines lines;
{
uint lineBegin = 0;
while (lineBegin < line.size()) {
uint lineEnd = line.find('|', lineBegin);
if (lineEnd == line.npos)
lineEnd = line.size();
lines.push_back(line.substr(lineBegin, lineEnd - lineBegin));
lineBegin = lineEnd + 1;
}
}
_subtitles.push_back({begin, end, lines});
pos = next + 1;
}
}
MJPGPlayer::~MJPGPlayer() {}
void MJPGPlayer::rewind() {
_framesPlayed = 0;
_nextSubtitleIndex = 0;
_stream->seek(_firstFramePos);
}
const Graphics::Surface *MJPGPlayer::decodeFrame() {
if (_stream->eos())
return NULL;
uint32 size = _stream->readSint32LE();
if (size == 0)
return NULL;
if (_stream->eos())
return NULL;
Common::ScopedPtr<Common::SeekableReadStream> stream(_stream->readStream(size));
const Graphics::Surface *surface = _decoder.decodeFrame(*stream);
++_framesPlayed;
return surface;
}
void MJPGPlayer::paint(AGDSEngine &engine, Graphics::Surface &backbuffer) {
auto *surface = decodeFrame();
if (surface) {
Common::ScopedPtr<Graphics::Surface> scaled;
{
Common::ScopedPtr<Graphics::Surface> converted(surface->convertTo(engine.pixelFormat()));
auto scaleW = 1.0f * backbuffer.w / converted->w;
auto scaleH = 1.0f * backbuffer.h / converted->h;
auto scale = MIN(scaleW, scaleH);
scaled.reset(converted->scale(converted->w * scale, converted->h * scale));
converted->free();
}
Common::Point dst((backbuffer.w - scaled->w) / 2, (backbuffer.h - scaled->h) / 2);
Common::Rect srcRect(scaled->getRect());
if (Common::Rect::getBlitRect(dst, srcRect, backbuffer.getRect()))
backbuffer.copyRectToSurface(*scaled, dst.x, dst.y, srcRect);
scaled->free();
}
if (_subtitles.empty())
return;
while (_nextSubtitleIndex < _subtitles.size() && _framesPlayed > _subtitles[_nextSubtitleIndex].end)
++_nextSubtitleIndex;
if (_nextSubtitleIndex >= _subtitles.size() || _framesPlayed < _subtitles[_nextSubtitleIndex].begin)
return;
auto font = engine.getFont(engine.getSystemVariable("tell_font")->getInteger());
int baseX = engine.getSystemVariable("subtitle_x")->getInteger();
int baseY = engine.getSystemVariable("subtitle_y")->getInteger();
int maxWidth = engine.getSystemVariable("subtitle_width")->getInteger();
auto &lines = _subtitles[_nextSubtitleIndex].lines;
for (auto &line : lines) {
Text::Lines sublines;
font->wordWrapText(line, maxWidth, sublines);
for (auto &subline : sublines) {
int w = font->getStringWidth(subline);
int x = baseX - w / 2;
font->drawString(&backbuffer, subline, x, baseY, backbuffer.w - x, 0);
baseY += font->getFontHeight();
}
}
}
} // namespace AGDS