void BaseRenderOSystem::fadeToColor(byte r, byte g, byte b, byte a, Common::Rect *rect) { Common::Rect fillRect; if (rect) { fillRect.left = rect->left; fillRect.top = rect->top; fillRect.setWidth(rect->width()); fillRect.setHeight(rect->height()); } else { Rect32 rc; _gameRef->getCurrentViewportRect(&rc); fillRect.left = (int16)rc.left; fillRect.top = (int16)rc.top; fillRect.setWidth((int16)(rc.right - rc.left)); fillRect.setHeight((int16)(rc.bottom - rc.top)); } modTargetRect(&fillRect); //TODO: This is only here until I'm sure about the final pixelformat uint32 col = _renderSurface->format.ARGBToColor(a, r, g, b); Graphics::Surface surf; surf.create((uint16)fillRect.width(), (uint16)fillRect.height(), _renderSurface->format); Common::Rect sizeRect(fillRect); sizeRect.translate(-fillRect.top, -fillRect.left); surf.fillRect(fillRect, col); TransformStruct temp = TransformStruct(); temp._alphaDisable = false; drawSurface(nullptr, &surf, &sizeRect, &fillRect, temp); surf.free(); //SDL_SetRenderDrawColor(_renderer, r, g, b, a); //SDL_SetRenderDrawBlendMode(_renderer, SDL_BLENDMODE_BLEND); //SDL_RenderFillRect(_renderer, &fillRect); }
bool BaseSurfaceOSystem::drawSprite(int x, int y, Rect32 *rect, Rect32 *newRect, TransformStruct transform) { BaseRenderOSystem *renderer = static_cast<BaseRenderOSystem *>(_gameRef->_renderer); if (!_loaded) { finishLoad(); } if (renderer->_forceAlphaColor != 0) { transform._rgbaMod = renderer->_forceAlphaColor; } // TODO: This _might_ miss the intended behaviour by 1 in each direction // But I think it fits the model used in Wintermute. Common::Rect srcRect; srcRect.left = rect->left; srcRect.top = rect->top; srcRect.setWidth(rect->right - rect->left); srcRect.setHeight(rect->bottom - rect->top); Common::Rect position; if (newRect) { position.top = y; position.left = x; position.setWidth(newRect->width()); position.setHeight(newRect->height()); } else { Rect32 r; r.top = 0; r.left = 0; r.setWidth(rect->width()); r.setHeight(rect->height()); r = TransformTools::newRect(r, transform, 0); position.top = r.top + y + transform._offset.y; position.left = r.left + x + transform._offset.x; position.setWidth(r.width() * transform._numTimesX); position.setHeight(r.height() * transform._numTimesY); } renderer->modTargetRect(&position); // TODO: This actually requires us to have the SAME source-offsets every time, // But no checking is in place for that yet. // Optimize by not doing alpha-blits if we lack alpha if (_alphaType == TransparentSurface::ALPHA_OPAQUE && !transform._alphaDisable) { transform._alphaDisable = true; } renderer->drawSurface(this, _surface, &srcRect, &position, transform); return STATUS_OK; }
// Replacement for SDL2's SDL_RenderCopy void RenderTicket::drawToSurface(Graphics::Surface *_targetSurface) const { TransparentSurface src(*getSurface(), false); Common::Rect clipRect; clipRect.setWidth(getSurface()->w); clipRect.setHeight(getSurface()->h); if (_owner) { if (_transform._alphaDisable) { src.setAlphaMode(TransparentSurface::ALPHA_OPAQUE); } else { src.setAlphaMode(_owner->getAlphaType()); } } int y = _dstRect.top; int w = _dstRect.width() / _transform._numTimesX; int h = _dstRect.height() / _transform._numTimesY; for (int ry = 0; ry < _transform._numTimesY; ++ry) { int x = _dstRect.left; for (int rx = 0; rx < _transform._numTimesX; ++rx) { src.blit(*_targetSurface, x, y, _transform._flip, &clipRect, _transform._rgbaMod, clipRect.width(), clipRect.height()); x += w; } y += h; } }
Common::Rect GameModule::readRect(Common::SeekableReadStream &s) { Common::Rect r; r.left = s.readUint16LE(); r.top = s.readUint16LE(); r.setWidth(s.readUint16LE()); r.setHeight(s.readUint16LE()); return r; }
Common::Rect makeRect(int16 x, int16 y, int16 width, int16 height) { Common::Rect rect; rect.left = x; rect.top = y; rect.setWidth(width); rect.setHeight(height); return rect; }
void Animation::getFrameRect(Common::Rect &r) const { r.setWidth(0); r.setHeight(0); if (!gfxobj) { return; } gfxobj->getRect(_frame, r); r.translate(_left, _top); }
bool ASurface::clip(Common::Rect &r) { int skip; _leftSkip = _rightSkip = 0; _topSkip = _bottomSkip = 0; if (r.left > _clipWidth || r.left < 0) { if (r.left >= 0) return true; skip = -r.left; r.setWidth(r.width() - skip); _leftSkip = skip; r.moveTo(0, r.top); } int right = r.right - 1; if (right < 0) return true; else if (right > _clipWidth) { skip = right - _clipWidth; r.setWidth(r.width() - skip); _rightSkip = skip; } if (r.top > _clipHeight || r.top < 0) { if (r.top >= 0) return true; skip = -r.top; r.setHeight(r.height() - skip); _topSkip = skip; r.moveTo(r.left, 0); } int bottom = r.bottom - 1; if (bottom < 0) return true; else if (bottom > _clipHeight) { skip = bottom - _clipHeight; _bottomSkip = skip; r.setHeight(r.height() - skip); } return false; }
// Replacement for SDL2's SDL_RenderCopy void RenderTicket::drawToSurface(Graphics::Surface *_targetSurface) const { TransparentSurface src(*getSurface(), false); Common::Rect clipRect; clipRect.setWidth(getSurface()->w); clipRect.setHeight(getSurface()->h); src._enableAlphaBlit = !_transform._alphaDisable; src.blit(*_targetSurface, _dstRect.left, _dstRect.top, _transform._flip, &clipRect, _transform._rgbaMod, clipRect.width(), clipRect.height()); }
bool BaseRenderOSystem::setViewport(int left, int top, int right, int bottom) { Common::Rect rect; // TODO: Hopefully this is the same logic that ScummVM uses. rect.left = (int16)(left + _borderLeft); rect.top = (int16)(top + _borderTop); rect.setWidth((int16)((right - left) * _ratioX)); rect.setHeight((int16)((bottom - top) * _ratioY)); _renderRect = rect; return STATUS_OK; }
void InventoryRenderer::getItemRect(ItemPosition pos, Common::Rect &r) { r.setHeight(_props->_itemHeight); r.setWidth(_props->_itemWidth); uint16 line = pos / _props->_itemsPerLine; uint16 col = pos % _props->_itemsPerLine; r.moveTo(col * _props->_itemWidth, line * _props->_itemHeight); }
Common::Rect Cursor::getHotRectangle() const { if (!_cursorImage) { return Common::Rect(); } else { Common::Point hotSpot = _cursorImage->getHotspot(); Common::Rect hotRectangle; hotRectangle.setWidth(_cursorImage->getWidth()); hotRectangle.setHeight(_cursorImage->getHeight()); hotRectangle.translate(-hotSpot.x, -hotSpot.y); return hotRectangle; } }
// Replacement for SDL2's SDL_RenderCopy void RenderTicket::drawToSurface(Graphics::Surface *_targetSurface) const { TransparentSurface src(*getSurface(), false); Common::Rect clipRect; clipRect.setWidth(getSurface()->w); clipRect.setHeight(getSurface()->h); if (_owner) { if (_transform._alphaDisable) { src._alphaMode = TransparentSurface::ALPHA_OPAQUE; } else { src._alphaMode = _owner->getAlphaType(); } } src.blit(*_targetSurface, _dstRect.left, _dstRect.top, _transform._flip, &clipRect, _transform._rgbaMod, clipRect.width(), clipRect.height()); }
void Frame::playTransition(Score *score) { uint16 duration = _transDuration * 250; // _transDuration in 1/4 of sec duration = (duration == 0 ? 250 : duration); // director support transition duration = 0, but animation play like value = 1, idk. if (_transChunkSize == 0) _transChunkSize = 1; //equal 1 step uint16 stepDuration = duration / _transChunkSize; uint16 steps = duration / stepDuration; switch (_transType) { case kTransCoverDown: { uint16 stepSize = score->_movieRect.height() / steps; Common::Rect r = score->_movieRect; for (uint16 i = 1; i < steps; i++) { r.setHeight(stepSize * i); g_system->delayMillis(stepDuration); score->processEvents(); g_system->copyRectToScreen(score->_surface->getPixels(), score->_surface->pitch, 0, 0, r.width(), r.height()); g_system->updateScreen(); } } break; case kTransCoverUp: { uint16 stepSize = score->_movieRect.height() / steps; Common::Rect r = score->_movieRect; for (uint16 i = 1; i < steps; i++) { r.setHeight(stepSize * i); g_system->delayMillis(stepDuration); score->processEvents(); g_system->copyRectToScreen(score->_surface->getPixels(), score->_surface->pitch, 0, score->_movieRect.height() - stepSize * i, r.width(), r.height()); g_system->updateScreen(); } } break; case kTransCoverRight: { uint16 stepSize = score->_movieRect.width() / steps; Common::Rect r = score->_movieRect; for (uint16 i = 1; i < steps; i++) { r.setWidth(stepSize * i); g_system->delayMillis(stepDuration); score->processEvents(); g_system->copyRectToScreen(score->_surface->getPixels(), score->_surface->pitch, 0, 0, r.width(), r.height()); g_system->updateScreen(); } } break; case kTransCoverLeft: { uint16 stepSize = score->_movieRect.width() / steps; Common::Rect r = score->_movieRect; for (uint16 i = 1; i < steps; i++) { r.setWidth(stepSize * i); g_system->delayMillis(stepDuration); score->processEvents(); g_system->copyRectToScreen(score->_surface->getPixels(), score->_surface->pitch, score->_movieRect.width() - stepSize * i, 0, r.width(), r.height()); g_system->updateScreen(); } } break; case kTransCoverUpLeft: { uint16 stepSize = score->_movieRect.width() / steps; Common::Rect r = score->_movieRect; for (uint16 i = 1; i < steps; i++) { r.setWidth(stepSize * i); r.setHeight(stepSize * i); g_system->delayMillis(stepDuration); score->processEvents(); g_system->copyRectToScreen(score->_surface->getPixels(), score->_surface->pitch, score->_movieRect.width() - stepSize * i, score->_movieRect.height() - stepSize * i, r.width(), r.height()); g_system->updateScreen(); } } break; case kTransCoverUpRight: { uint16 stepSize = score->_movieRect.width() / steps; Common::Rect r = score->_movieRect; for (uint16 i = 1; i < steps; i++) { r.setWidth(stepSize * i); r.setHeight(stepSize * i); g_system->delayMillis(stepDuration); score->processEvents(); g_system->copyRectToScreen(score->_surface->getPixels(), score->_surface->pitch, 0, score->_movieRect.height() - stepSize * i, r.width(), r.height()); g_system->updateScreen(); } } break; case kTransCoverDownLeft: { uint16 stepSize = score->_movieRect.width() / steps; Common::Rect r = score->_movieRect; for (uint16 i = 1; i < steps; i++) { r.setWidth(stepSize * i); r.setHeight(stepSize * i); g_system->delayMillis(stepDuration); score->processEvents(); g_system->copyRectToScreen(score->_surface->getPixels(), score->_surface->pitch, score->_movieRect.width() - stepSize * i, 0, r.width(), r.height()); g_system->updateScreen(); } } break; case kTransCoverDownRight: { uint16 stepSize = score->_movieRect.width() / steps; Common::Rect r = score->_movieRect; for (uint16 i = 1; i < steps; i++) { r.setWidth(stepSize * i); r.setHeight(stepSize * i); g_system->delayMillis(stepDuration); score->processEvents(); g_system->copyRectToScreen(score->_surface->getPixels(), score->_surface->pitch, 0, 0, r.width(), r.height()); g_system->updateScreen(); } } break; default: warning("Unhandled transition type %d %d %d", _transType, duration, _transChunkSize); break; } }
bool UserInterface::getBounds(ScrCategory category, int v, Common::Rect &bounds) { int heightMultiplier, widthMultiplier; int leftStart, yOffset, widthAmt; switch (category) { case CAT_COMMAND: heightMultiplier = v % 5; widthMultiplier = v / 5; leftStart = 2; yOffset = 3; widthAmt = 32; break; case CAT_INV_LIST: if (v < _inventoryTopIndex || v >= (_inventoryTopIndex + 5)) return false; heightMultiplier = v - _inventoryTopIndex; widthMultiplier = 0; leftStart = 90; yOffset = 3; widthAmt = 69; break; case CAT_TALK_ENTRY: heightMultiplier = v; widthMultiplier = 0; leftStart = 2; yOffset = 3; widthAmt = 310; break; case CAT_INV_SCROLLER: heightMultiplier = 0; widthMultiplier = 0; yOffset = 0; widthAmt = 9; leftStart = (v != 73) ? 73 : 75; break; default: heightMultiplier = v; widthMultiplier = 0; leftStart = 240; yOffset = 3; widthAmt = 80; break; } bounds.left = (widthMultiplier > 0) ? widthMultiplier * widthAmt + leftStart : leftStart; bounds.setWidth(widthAmt); bounds.top = heightMultiplier * 8 + yOffset; bounds.setHeight(8); if (category == CAT_INV_SCROLLER) { switch (v) { case SCROLLBAR_UP: // Arrow up bounds.top = 4; bounds.setHeight(7); break; case SCROLLBAR_DOWN: // Arrow down bounds.top = 35; bounds.setHeight(7); break; case SCROLLBAR_ELEVATOR: // Scroller bounds.top = 12; bounds.setHeight(22); break; case SCROLLBAR_THUMB: // Thumb bounds.top = _scrollbarElevator + 14; bounds.setHeight(1); break; default: break; } } return true; }
bool BaseSurfaceOSystem::drawSprite(int x, int y, Rect32 *rect, float zoomX, float zoomY, uint32 alpha, bool alphaDisable, TSpriteBlendMode blendMode, bool mirrorX, bool mirrorY, int offsetX, int offsetY) { BaseRenderOSystem *renderer = static_cast<BaseRenderOSystem *>(_gameRef->_renderer); if (!_loaded) { finishLoad(); } if (renderer->_forceAlphaColor != 0) { alpha = renderer->_forceAlphaColor; } byte r = RGBCOLGetR(alpha); byte g = RGBCOLGetG(alpha); byte b = RGBCOLGetB(alpha); byte a = RGBCOLGetA(alpha); renderer->setAlphaMod(a); renderer->setColorMod(r, g, b); #if 0 // These are kept for reference if BlendMode is reimplemented at some point. if (alphaDisable) { SDL_SetTextureBlendMode(_texture, SDL_BLENDMODE_NONE); } else { SDL_SetTextureBlendMode(_texture, SDL_BLENDMODE_BLEND); } #endif // TODO: This _might_ miss the intended behaviour by 1 in each direction // But I think it fits the model used in Wintermute. Common::Rect srcRect; srcRect.left = rect->left; srcRect.top = rect->top; srcRect.setWidth(rect->right - rect->left); srcRect.setHeight(rect->bottom - rect->top); Common::Rect position; position.left = x + offsetX; position.top = y + offsetY; // Crop off-by-ones: if (position.left == -1) { position.left = 0; // TODO: Something is wrong } if (position.top == -1) { position.top = 0; // TODO: Something is wrong } position.setWidth((int16)((float)srcRect.width() * zoomX / 100.f)); position.setHeight((int16)((float)srcRect.height() * zoomX / 100.f)); renderer->modTargetRect(&position); /* position.left += offsetX; position.top += offsetY;*/ // TODO: This actually requires us to have the SAME source-offsets every time, // But no checking is in place for that yet. // TODO: Optimize by not doing alpha-blits if we lack or disable alpha bool hasAlpha; if (_hasAlpha && !alphaDisable) { hasAlpha = true; } else { hasAlpha = false; } if (alphaDisable) { warning("BaseSurfaceOSystem::drawSprite - AlphaDisable ignored"); } renderer->drawSurface(this, _surface, &srcRect, &position, mirrorX, mirrorY, !hasAlpha); return STATUS_OK; }
void RenderTicket::drawToSurface(Graphics::Surface *_targetSurface, Common::Rect *dstRect, Common::Rect *clipRect) const { TransparentSurface src(*getSurface(), false); bool doDelete = false; if (!clipRect) { doDelete = true; clipRect = new Common::Rect(); clipRect->setWidth(getSurface()->w * _transform._numTimesX); clipRect->setHeight(getSurface()->h * _transform._numTimesY); } if (_owner) { if (_transform._alphaDisable) { src.setAlphaMode(TransparentSurface::ALPHA_OPAQUE); } else { src.setAlphaMode(_owner->getAlphaType()); } } if (_transform._numTimesX * _transform._numTimesY == 1) { src.blit(*_targetSurface, dstRect->left, dstRect->top, _transform._flip, clipRect, _transform._rgbaMod, clipRect->width(), clipRect->height(), _transform._blendMode); } else { // clipRect is a subrect of the full numTimesX*numTimesY rect Common::Rect subRect; int y = 0; int w = getSurface()->w; int h = getSurface()->h; assert(w == _dstRect.width() / _transform._numTimesX); assert(h == _dstRect.height() / _transform._numTimesY); int basex = dstRect->left - clipRect->left; int basey = dstRect->top - clipRect->top; for (int ry = 0; ry < _transform._numTimesY; ++ry) { int x = 0; for (int rx = 0; rx < _transform._numTimesX; ++rx) { subRect.left = x; subRect.top = y; subRect.setWidth(w); subRect.setHeight(h); if (subRect.intersects(*clipRect)) { subRect.clip(*clipRect); subRect.translate(-x, -y); src.blit(*_targetSurface, basex + x + subRect.left, basey + y + subRect.top, _transform._flip, &subRect, _transform._rgbaMod, subRect.width(), subRect.height(), _transform._blendMode); } x += w; } y += h; } } if (doDelete) { delete clipRect; } }
void Sprite::blit(const Sprite &from, const Common::Rect &area, int32 x, int32 y, bool transp) { // Sanity checks assert((x >= 0) && (y >= 0) && (x <= 0x7FFF) && (y <= 0x7FFF)); if (!exists() || !from.exists()) return; Common::Rect toArea = getArea(true); toArea.left = x; toArea.top = y; if (toArea.isEmpty()) return; Common::Rect fromArea = from.getArea(); fromArea.clip(area); fromArea.setWidth (MIN(fromArea.width() , toArea.width())); fromArea.setHeight(MIN(fromArea.height(), toArea.height())); if (fromArea.isEmpty() || !fromArea.isValidRect()) return; int32 w = fromArea.width(); int32 h = fromArea.height(); const int32 fromTop = fracToInt(fromArea.top * from._scaleInverse); const int32 fromLeft = fracToInt(fromArea.left * from._scaleInverse); const byte *src = (const byte *) from._surfaceTrueColor.getBasePtr(fromLeft, fromTop); byte *dst = ( byte *) _surfaceTrueColor.getBasePtr(x, y); const uint8 *srcT = from._transparencyMap + fromTop * from._surfaceTrueColor.w + fromLeft; uint8 *dstT = _transparencyMap + y * _surfaceTrueColor.w + x; frac_t posW = 0, posH = 0; while (h-- > 0) { posW = 0; const byte *srcRow = src; byte *dstRow = dst; const uint8 *srcRowT = srcT; uint8 *dstRowT = dstT; for (int32 j = 0; j < w; j++, dstRow += _surfaceTrueColor.bytesPerPixel, dstRowT++) { if (!transp || (*srcRowT == 0)) { // Ignore transparency or source is solid => copy memcpy(dstRow, srcRow, _surfaceTrueColor.bytesPerPixel); *dstRowT = *srcRowT; } else if (*srcRowT == 2) { // Half-transparent if (*dstRowT == 1) // But destination is transparent => propagate memcpy(dstRow, srcRow, _surfaceTrueColor.bytesPerPixel); else // Destination is solid => mix ImgConv.mixTrueColor(dstRow, srcRow); *dstRowT = *srcRowT; } // Advance source data posW += from._scaleInverse; while (posW >= ((frac_t) FRAC_ONE)) { srcRow += from._surfaceTrueColor.bytesPerPixel; srcRowT++; posW -= FRAC_ONE; } } dst += _surfaceTrueColor.pitch; dstT += _surfaceTrueColor.w; // Advance source data posH += from._scaleInverse; while (posH >= ((frac_t) FRAC_ONE)) { src += from._surfaceTrueColor.pitch; srcT += from._surfaceTrueColor.w; posH -= FRAC_ONE; } } }
void Gfx::bltMaskScale(const Common::Rect& r, byte *data, Graphics::Surface *surf, uint16 z, uint scale, byte transparentColor) { if (scale == 100) { // use optimized path bltMaskNoScale(r, data, surf, z, transparentColor); return; } // unscaled rectangle size uint width = r.width(); uint height = r.height(); // scaled rectangle size uint scaledWidth = r.width() * scale / 100; uint scaledHeight = r.height() * scale / 100; // scaled rectangle origin uint scaledLeft = r.left + (width - scaledWidth) / 2; uint scaledTop = r.top + (height - scaledHeight); // clipped scaled destination rectangle Common::Rect dstRect(scaledWidth, scaledHeight); dstRect.moveTo(scaledLeft, scaledTop); Common::Rect clipper(surf->w, surf->h); dstRect.clip(clipper); if (!dstRect.isValidRect()) return; // clipped source rectangle Common::Rect srcRect; srcRect.left = (dstRect.left - scaledLeft) * 100 / scale; srcRect.top = (dstRect.top - scaledTop) * 100 / scale; srcRect.setWidth(dstRect.width() * 100 / scale); srcRect.setHeight(dstRect.height() * 100 / scale); if (!srcRect.isValidRect()) return; Common::Point dp; dp.x = dstRect.left; dp.y = dstRect.top; byte *s = data + srcRect.left + srcRect.top * width; byte *d = (byte *)surf->getBasePtr(dp.x, dp.y); uint line = 0, col = 0; uint xAccum = 0, yAccum = 0; uint inc = width * (100 - scale); uint thr = width * 100; for (uint16 i = 0; i < srcRect.height(); i++) { yAccum += inc; if (yAccum >= thr) { yAccum -= thr; s += width; continue; } xAccum = 0; byte *d2 = d; col = 0; for (uint16 j = 0; j < srcRect.width(); j++) { xAccum += inc; if (xAccum >= thr) { xAccum -= thr; s++; continue; } if (*s != transparentColor) { if (_backgroundInfo->hasMask()) { byte v = _backgroundInfo->_mask->getValue(dp.x + col, dp.y + line); if (z >= v) *d2 = *s; } else { *d2 = *s; } } s++; d2++; col++; } s += width - srcRect.width(); d += surf->w; line++; } }
void InventoryRenderer::getRect(Common::Rect& r) const { r.setWidth(_props->_width); r.setHeight(_props->_itemHeight * getNumLines()); r.moveTo(_pos); }