void GfxControls16::kernelDrawText(Common::Rect rect, reg_t obj, const char *text, int16 fontId, TextAlignment alignment, int16 style, bool hilite) { if (!hilite) { rect.grow(1); _paint16->eraseRect(rect); rect.grow(-1); //20140521 std::map<std::string, std::string>::iterator iter; if(g_sci->_ScriptData) { _ShouterInfo* pInfo = g_sci->_ScriptData->GetShouterInfo(); iter = pInfo->SentenceList.find(text); if(iter == pInfo->SentenceList.end()) _text16->Box(text, false, rect, alignment, fontId); else _text16->Box(iter->second.c_str(), false, rect, alignment, fontId); } else { _text16->Box(text, false, rect, alignment, fontId); } if (style & SCI_CONTROLS_STYLE_SELECTED) { _paint16->frameRect(rect); } if (!getPicNotValid()) _paint16->bitsShow(rect); } else { _paint16->invertRect(rect); _paint16->bitsShow(rect); } }
void GfxControls16::drawListControl(Common::Rect rect, reg_t obj, int16 maxChars, int16 count, const char **entries, GuiResourceId fontId, int16 upperPos, int16 cursorPos, bool isAlias) { Common::Rect workerRect = rect; GuiResourceId oldFontId = _text16->GetFontId(); int16 oldPenColor = _ports->_curPort->penClr; uint16 fontSize = 0; int16 i; const char *listEntry; int16 listEntryLen; int16 lastYpos; // draw basic window _paint16->eraseRect(workerRect); workerRect.grow(1); _paint16->frameRect(workerRect); // draw UP/DOWN arrows // we draw UP arrow one pixel lower than sierra did, because it looks nicer. Also the DOWN arrow has one pixel // line inbetween as well // They "fixed" this in SQ4 by having the arrow character start one pixel line later, we don't adjust there if (g_sci->getGameId() != GID_SQ4) workerRect.top++; _text16->Box(controlListUpArrow, false, workerRect, SCI_TEXT16_ALIGNMENT_CENTER, 0); workerRect.top = workerRect.bottom - 10; _text16->Box(controlListDownArrow, false, workerRect, SCI_TEXT16_ALIGNMENT_CENTER, 0); // Draw inner lines workerRect.top = rect.top + 9; workerRect.bottom -= 10; _paint16->frameRect(workerRect); workerRect.grow(-1); _text16->SetFont(fontId); fontSize = _ports->_curPort->fontHeight; _ports->penColor(_ports->_curPort->penClr); _ports->backColor(_ports->_curPort->backClr); workerRect.bottom = workerRect.top + fontSize; lastYpos = rect.bottom - fontSize; // Write actual text for (i = upperPos; i < count; i++) { _paint16->eraseRect(workerRect); listEntry = entries[i]; if (listEntry[0]) { _ports->moveTo(workerRect.left, workerRect.top); listEntryLen = strlen(listEntry); _text16->Draw(listEntry, 0, MIN(maxChars, listEntryLen), oldFontId, oldPenColor); if ((!isAlias) && (i == cursorPos)) { _paint16->invertRect(workerRect); } } workerRect.translate(0, fontSize); if (workerRect.bottom > lastYpos) break; } _text16->SetFont(oldFontId); }
void GfxControls16::kernelDrawButton(Common::Rect rect, reg_t obj, const char *text, int16 fontId, int16 style, bool hilite) { int16 sci0EarlyPen = 0, sci0EarlyBack = 0; if (!hilite) { if (getSciVersion() == SCI_VERSION_0_EARLY) { // SCI0early actually used hardcoded green/black buttons instead of using the port colors sci0EarlyPen = _ports->_curPort->penClr; sci0EarlyBack = _ports->_curPort->backClr; _ports->penColor(0); _ports->backColor(2); } rect.grow(1); _paint16->eraseRect(rect); _paint16->frameRect(rect); rect.grow(-2); _ports->textGreyedOutput(!(style & SCI_CONTROLS_STYLE_ENABLED)); //20140521 //_text16->Box(text, false, rect, SCI_TEXT16_ALIGNMENT_CENTER, fontId); std::map<std::string, std::string>::iterator iter; if(g_sci->_ScriptData) { _ShouterInfo* pInfo = g_sci->_ScriptData->GetShouterInfo(); iter = pInfo->SentenceList.find(text); if(iter == pInfo->SentenceList.end()) _text16->Box(text, false, rect, SCI_TEXT16_ALIGNMENT_CENTER, fontId, true); else _text16->Box(iter->second.c_str(), false, rect, SCI_TEXT16_ALIGNMENT_CENTER, fontId, true); } else { _text16->Box(text, false, rect, SCI_TEXT16_ALIGNMENT_CENTER, fontId); } //End _ports->textGreyedOutput(false); rect.grow(1); if (style & SCI_CONTROLS_STYLE_SELECTED) _paint16->frameRect(rect); if (!getPicNotValid()) { rect.grow(1); _paint16->bitsShow(rect); } if (getSciVersion() == SCI_VERSION_0_EARLY) { _ports->penColor(sci0EarlyPen); _ports->backColor(sci0EarlyBack); } } else { // SCI0early used xor to invert button rectangles resulting in pink/white buttons if (getSciVersion() == SCI_VERSION_0_EARLY) _paint16->invertRectViaXOR(rect); else _paint16->invertRect(rect); _paint16->bitsShow(rect); } }
void GfxControls16::kernelDrawText(Common::Rect rect, reg_t obj, const char *text, uint16 languageSplitter, int16 fontId, TextAlignment alignment, int16 style, bool hilite) { if (!hilite) { rect.grow(1); _paint16->eraseRect(rect); rect.grow(-1); _text16->Box(text, languageSplitter, false, rect, alignment, fontId); if (style & SCI_CONTROLS_STYLE_SELECTED) { _paint16->frameRect(rect); } if (!getPicNotValid()) _paint16->bitsShow(rect); } else { _paint16->invertRect(rect); _paint16->bitsShow(rect); } }
void GfxControls16::kernelDrawList(Common::Rect rect, reg_t obj, int16 maxChars, int16 count, const char **entries, GuiResourceId fontId, int16 style, int16 upperPos, int16 cursorPos, bool isAlias, bool hilite) { if (!hilite) { drawListControl(rect, obj, maxChars, count, entries, fontId, upperPos, cursorPos, isAlias); rect.grow(1); if (isAlias && (style & SCI_CONTROLS_STYLE_SELECTED)) { _paint16->frameRect(rect); } if (!getPicNotValid()) _paint16->bitsShow(rect); } }
void GfxControls16::kernelDrawTextEdit(Common::Rect rect, reg_t obj, const char *text, int16 fontId, int16 mode, int16 style, int16 cursorPos, int16 maxChars, bool hilite) { Common::Rect textRect = rect; uint16 oldFontId = _text16->GetFontId(); rect.grow(1); _texteditCursorVisible = false; texteditCursorErase(); _paint16->eraseRect(rect); _text16->Box(text, false, textRect, SCI_TEXT16_ALIGNMENT_LEFT, fontId); _paint16->frameRect(rect); if (style & SCI_CONTROLS_STYLE_SELECTED) { _text16->SetFont(fontId); rect.grow(-1); texteditCursorDraw(rect, text, cursorPos); _text16->SetFont(oldFontId); rect.grow(1); } if (!getPicNotValid()) _paint16->bitsShow(rect); }
void DropHighlight::draw(const Common::Rect &) { Graphics::Surface *screen = ((PegasusEngine *)g_engine)->_gfx->getWorkArea(); // Since this is only used in two different ways, I'm only // going to implement it in those two ways. Deal with it. Common::Rect rect = _bounds; rect.grow(-_thickness); screen->frameRect(rect, _highlightColor); rect.grow(1); screen->frameRect(rect, _highlightColor); if (_cornerDiameter == 8 && _thickness == 4) { rect.grow(1); screen->frameRect(rect, _highlightColor); screen->hLine(rect.left + 1, rect.top - 1, rect.right - 2, _highlightColor); screen->hLine(rect.left + 1, rect.bottom, rect.right - 2, _highlightColor); screen->vLine(rect.left - 1, rect.top + 1, rect.bottom - 2, _highlightColor); screen->vLine(rect.right, rect.top + 1, rect.bottom - 2, _highlightColor); } }
void WidgetBase::drawBackground() { TattooEngine &vm = *(TattooEngine *)_vm; Screen &screen = *_vm->_screen; TattooUserInterface &ui = *(TattooUserInterface *)_vm->_ui; Common::Rect bounds = _bounds; if (vm._transparentMenus) { ui.makeBGArea(bounds); } else { bounds.grow(-3); screen._backBuffer1.fillRect(bounds, MENU_BACKGROUND); } }
void GfxControls16::kernelDrawButton(Common::Rect rect, reg_t obj, const char *text, uint16 languageSplitter, int16 fontId, int16 style, bool hilite) { int16 sci0EarlyPen = 0, sci0EarlyBack = 0; if (!hilite) { if (getSciVersion() == SCI_VERSION_0_EARLY) { // SCI0early actually used hardcoded green/black buttons instead of using the port colors sci0EarlyPen = _ports->_curPort->penClr; sci0EarlyBack = _ports->_curPort->backClr; _ports->penColor(0); _ports->backColor(2); } rect.grow(1); _paint16->eraseRect(rect); _paint16->frameRect(rect); rect.grow(-2); _ports->textGreyedOutput(!(style & SCI_CONTROLS_STYLE_ENABLED)); _text16->Box(text, languageSplitter, false, rect, SCI_TEXT16_ALIGNMENT_CENTER, fontId); _ports->textGreyedOutput(false); rect.grow(1); if (style & SCI_CONTROLS_STYLE_SELECTED) _paint16->frameRect(rect); if (!getPicNotValid()) { rect.grow(1); _paint16->bitsShow(rect); } if (getSciVersion() == SCI_VERSION_0_EARLY) { _ports->penColor(sci0EarlyPen); _ports->backColor(sci0EarlyBack); } } else { // SCI0early used xor to invert button rectangles resulting in pink/white buttons if (getSciVersion() == SCI_VERSION_0_EARLY) _paint16->invertRectViaXOR(rect); else _paint16->invertRect(rect); _paint16->bitsShow(rect); } }
void CSTimeModule::bubbleTextDrawProc(Feature *feature) { Common::Rect bounds = feature->_data.bounds; bounds.grow(-5); const Graphics::Font &font = _vm->getInterface()->getDialogFont(); uint height = font.getFontHeight(); Common::Array<Common::String> lines; font.wordWrapText(_vm->getInterface()->getCurrBubbleText(), bounds.width(), lines); Graphics::Surface *screen = _vm->_system->lockScreen(); for (int x = -2; x < 2; x++) for (int y = -1; y < 3; y++) for (uint i = 0; i < lines.size(); i++) font.drawString(screen, lines[i], bounds.left + x, bounds.top + y + i*height, bounds.width(), 241, Graphics::kTextAlignCenter); for (uint i = 0; i < lines.size(); i++) font.drawString(screen, lines[i], bounds.left, bounds.top + i*height, bounds.width(), 32, Graphics::kTextAlignCenter); _vm->_system->unlockScreen(); }
Common::Rect MystAreaSlider::boundingBox() { Common::Rect bb; bb.top = _rect.top; bb.bottom = _rect.bottom; bb.left = _rect.left; bb.right = _rect.right; if (_flagHV & 1) { bb.left = _minH - _sliderWidth / 2; bb.right = _maxH + _sliderWidth / 2; } if (_flagHV & 2) { bb.top = _minV - _sliderHeight / 2; bb.bottom = _maxV + _sliderHeight / 2; } bb.grow(1); return bb; }
void WidgetVerbs::highlightVerbControls() { Events &events = *_vm->_events; Screen &screen = *_vm->_screen; Common::Point mousePos = events.mousePos(); // Get highlighted verb _selector = -1; Common::Rect bounds = _bounds; bounds.grow(-3); if (bounds.contains(mousePos)) _selector = (mousePos.y - bounds.top) / (screen.fontHeight() + 7); // See if a new verb is being pointed at if (_selector != _oldSelector) { // Redraw the verb list for (int idx = 0; idx < (int)_verbCommands.size(); ++idx) { byte color = (idx == _selector) ? (byte)COMMAND_HIGHLIGHTED : (byte)INFO_TOP; _surface.writeString(_verbCommands[idx], Common::Point((_bounds.width() - screen.stringWidth(_verbCommands[idx])) / 2, (screen.fontHeight() + 7) * idx + 5), color); } _oldSelector = _selector; } }
void GfxPorts::drawWindow(Window *pWnd) { if (pWnd->bDrawn) return; int16 wndStyle = pWnd->wndStyle; pWnd->bDrawn = true; Port *oldport = setPort(_wmgrPort); penColor(0); if ((wndStyle & SCI_WINDOWMGR_STYLE_TRANSPARENT) == 0) { pWnd->hSaved1 = _paint16->bitsSave(pWnd->restoreRect, GFX_SCREEN_MASK_VISUAL); if (pWnd->saveScreenMask & GFX_SCREEN_MASK_PRIORITY) { pWnd->hSaved2 = _paint16->bitsSave(pWnd->restoreRect, GFX_SCREEN_MASK_PRIORITY); if ((wndStyle & SCI_WINDOWMGR_STYLE_USER) == 0) _paint16->fillRect(pWnd->restoreRect, GFX_SCREEN_MASK_PRIORITY, 0, 15); } } // drawing frame,shadow and title if ((getSciVersion() >= SCI_VERSION_1_LATE) ? !(wndStyle & _styleUser) : wndStyle != _styleUser) { Common::Rect r = pWnd->dims; if (!(wndStyle & SCI_WINDOWMGR_STYLE_NOFRAME)) { r.top++; r.left++; _paint16->frameRect(r);// draw shadow r.translate(-1, -1); _paint16->frameRect(r);// draw actual window frame if (wndStyle & SCI_WINDOWMGR_STYLE_TITLE) { if (getSciVersion() <= SCI_VERSION_0_LATE) { // draw a black line between titlebar and actual window content for SCI0 r.bottom = r.top + 10; _paint16->frameRect(r); } r.grow(-1); if (getSciVersion() <= SCI_VERSION_0_LATE) _paint16->fillRect(r, GFX_SCREEN_MASK_VISUAL, 8); // grey titlebar for SCI0 else _paint16->fillRect(r, GFX_SCREEN_MASK_VISUAL, 0); // black titlebar for SCI01+ if (!pWnd->title.empty()) { int16 oldcolor = getPort()->penClr; penColor(_screen->getColorWhite()); _text16->Box(pWnd->title.c_str(), true, r, SCI_TEXT16_ALIGNMENT_CENTER, 0); penColor(oldcolor); } r.grow(+1); r.bottom = pWnd->dims.bottom - 1; r.top += 9; } r.grow(-1); } if (!(wndStyle & SCI_WINDOWMGR_STYLE_TRANSPARENT)) _paint16->fillRect(r, GFX_SCREEN_MASK_VISUAL, pWnd->backClr); _paint16->bitsShow(pWnd->dims); } setPort(oldport); }
Window *GfxPorts::addWindow(const Common::Rect &dims, const Common::Rect *restoreRect, const char *title, uint16 style, int16 priority, bool draw) { // Find an unused window/port id uint id = PORTS_FIRSTWINDOWID; while (id < _windowsById.size() && _windowsById[id]) { if (_windowsById[id]->counterTillFree) { // port that is already disposed, but not freed yet freeWindow((Window *)_windowsById[id]); _freeCounter--; break; // reuse the handle // we do this especially for sq4cd. it creates and disposes the // inventory window all the time, but reuses old handles as well // this worked somewhat under the original interpreter, because // it put the new window where the old was. } ++id; } if (id == _windowsById.size()) _windowsById.push_back(0); assert(0 < id && id < 0xFFFF); Window *pwnd = new Window(id); Common::Rect r; if (!pwnd) { error("Can't open window"); return 0; } _windowsById[id] = pwnd; // KQ1sci, KQ4, iceman, QfG2 always add windows to the back of the list. // KQ5CD checks style. // Hoyle3-demo also always adds to the back (#3036763). bool forceToBack = (getSciVersion() <= SCI_VERSION_1_EGA_ONLY) || (g_sci->getGameId() == GID_HOYLE3 && g_sci->isDemo()); if (!forceToBack && (style & SCI_WINDOWMGR_STYLE_TOPMOST)) _windowList.push_front(pwnd); else _windowList.push_back(pwnd); openPort(pwnd); r = dims; // This looks fishy, but it's exactly what Sierra did. They removed last // bit of the left dimension in their interpreter. It seems Sierra did it // for EGA byte alignment (EGA uses 1 byte for 2 pixels) and left it in // their interpreter even in the newer VGA games. r.left = r.left & 0xFFFE; if (r.width() > _screen->getWidth()) { // We get invalid dimensions at least at the end of sq3 (script bug!). // Same happens very often in lsl5, sierra sci didnt fix it but it looked awful. // Also happens frequently in the demo of GK1. warning("Fixing too large window, left: %d, right: %d", dims.left, dims.right); r.left = 0; r.right = _screen->getWidth() - 1; if ((style != _styleUser) && !(style & SCI_WINDOWMGR_STYLE_NOFRAME)) r.right--; } pwnd->rect = r; if (restoreRect) pwnd->restoreRect = *restoreRect; pwnd->wndStyle = style; pwnd->hSaved1 = pwnd->hSaved2 = NULL_REG; pwnd->bDrawn = false; if ((style & SCI_WINDOWMGR_STYLE_TRANSPARENT) == 0) pwnd->saveScreenMask = (priority == -1 ? GFX_SCREEN_MASK_VISUAL : GFX_SCREEN_MASK_VISUAL | GFX_SCREEN_MASK_PRIORITY); if (title && (style & SCI_WINDOWMGR_STYLE_TITLE)) { pwnd->title = title; } r = pwnd->rect; if ((style != _styleUser) && !(style & SCI_WINDOWMGR_STYLE_NOFRAME)) { r.grow(1); if (style & SCI_WINDOWMGR_STYLE_TITLE) { r.top -= 10; r.bottom++; } } pwnd->dims = r; // Clip window, if needed Common::Rect wmprect = _wmgrPort->rect; // Handle a special case for Dr. Brain 1 Mac. When hovering the mouse cursor // over the status line on top, the game scripts try to draw the game's icon // bar above the current port, by specifying a negative window top, so that // the end result will be drawn 10 pixels above the current port. This is a // hack by Sierra, and is only limited to user style windows. Normally, we // should not clip, same as what Sierra does. However, this will result in // having invalid rectangles with negative coordinates. For this reason, we // adjust the containing rectangle instead. if (pwnd->dims.top < 0 && g_sci->getPlatform() == Common::kPlatformMacintosh && (style & SCI_WINDOWMGR_STYLE_USER) && _wmgrPort->top + pwnd->dims.top >= 0) { // Offset the final rect top by the requested pixels wmprect.top += pwnd->dims.top; } int16 oldtop = pwnd->dims.top; int16 oldleft = pwnd->dims.left; // WORKAROUND: We also adjust the restore rect when adjusting the window // rect. // SSCI does not do this. It wasn't necessary in the original interpreter, // but it is needed for Freddy Pharkas CD. This version does not normally // have text, but we allow this by modifying the text/speech setting // according to what is set in the ScummVM GUI (refer to syncIngameAudioOptions() // in sci.cpp). Since the text used in Freddy Pharkas CD is quite large in // some cases, it ends up being offset in order to fit inside the screen, // but the associated restore rect isn't adjusted accordingly, leading to // artifacts being left on screen when some text boxes are removed. The // fact that the restore rect wasn't ever adjusted doesn't make sense, and // adjusting it shouldn't have any negative side-effects (it *should* be // adjusted, normally, but SCI doesn't do it). The big text boxes are still // odd-looking, because the text rect is drawn outside the text window rect, // but at least there aren't any leftover textbox artifacts left when the // boxes are removed. Adjusting the text window rect would require more // invasive changes than this one, thus it's not really worth the effort // for a feature that was not present in the original game, and its // implementation is buggy in the first place. // Adjusting the restore rect properly fixes bug #3575276. if (wmprect.top > pwnd->dims.top) { pwnd->dims.moveTo(pwnd->dims.left, wmprect.top); if (restoreRect) pwnd->restoreRect.moveTo(pwnd->restoreRect.left, wmprect.top); } if (wmprect.bottom < pwnd->dims.bottom) { pwnd->dims.moveTo(pwnd->dims.left, wmprect.bottom - pwnd->dims.bottom + pwnd->dims.top); if (restoreRect) pwnd->restoreRect.moveTo(pwnd->restoreRect.left, wmprect.bottom - pwnd->restoreRect.bottom + pwnd->restoreRect.top); } if (wmprect.right < pwnd->dims.right) { pwnd->dims.moveTo(wmprect.right + pwnd->dims.left - pwnd->dims.right, pwnd->dims.top); if (restoreRect) pwnd->restoreRect.moveTo(wmprect.right + pwnd->restoreRect.left - pwnd->restoreRect.right, pwnd->restoreRect.top); } if (wmprect.left > pwnd->dims.left) { pwnd->dims.moveTo(wmprect.left, pwnd->dims.top); if (restoreRect) pwnd->restoreRect.moveTo(wmprect.left, pwnd->restoreRect.top); } pwnd->rect.moveTo(pwnd->rect.left + pwnd->dims.left - oldleft, pwnd->rect.top + pwnd->dims.top - oldtop); if (restoreRect == 0) pwnd->restoreRect = pwnd->dims; if (pwnd->restoreRect.top < 0 && g_sci->getPlatform() == Common::kPlatformMacintosh && (style & SCI_WINDOWMGR_STYLE_USER) && _wmgrPort->top + pwnd->restoreRect.top >= 0) { // Special case for Dr. Brain 1 Mac (check above), applied to the // restore rectangle. pwnd->restoreRect.moveTo(pwnd->restoreRect.left, wmprect.top); } if (draw) drawWindow(pwnd); setPort((Port *)pwnd); // All SCI0 games till kq4 .502 (not including) did not adjust against _wmgrPort, we set _wmgrPort->top to 0 in that case setOrigin(pwnd->rect.left, pwnd->rect.top + _wmgrPort->top); pwnd->rect.moveTo(0, 0); return pwnd; }
void TattooUserInterface::drawInterface(int bufferNum) { TattooScene &scene = *(TattooScene *)_vm->_scene; Screen &screen = *_vm->_screen; TattooEngine &vm = *(TattooEngine *)_vm; if (_invMenuBuffer != nullptr) { Common::Rect r = _invMenuBounds; r.grow(-3); r.translate(-_currentScroll.x, 0); _grayAreas.clear(); _grayAreas.push_back(r); drawGrayAreas(); screen._backBuffer1.transBlitFrom(*_invMenuBuffer, Common::Point(_invMenuBounds.left, _invMenuBounds.top)); } if (_menuBuffer != nullptr) { Common::Rect r = _menuBounds; r.grow(-3); r.translate(-_currentScroll.x, 0); _grayAreas.clear(); _grayAreas.push_back(r); drawGrayAreas(); screen._backBuffer1.transBlitFrom(*_menuBuffer, Common::Point(_invMenuBounds.left, _invMenuBounds.top)); } // See if we need to draw a Text Tag floating with the cursor if (_tagBuffer != nullptr) screen._backBuffer1.transBlitFrom(*_tagBuffer, Common::Point(_tagBounds.left, _tagBounds.top)); // See if we need to draw an Inventory Item Graphic floating with the cursor if (_invGraphic != nullptr) screen._backBuffer1.transBlitFrom(*_invGraphic, Common::Point(_invGraphicBounds.left, _invGraphicBounds.top)); if (vm._creditsActive) vm.drawCredits(); // Bring the widgets to the screen if (scene._mask != nullptr) screen._flushScreen = true; if (screen._flushScreen) screen.blockMove(_currentScroll); // If there are UI widgets open, slam the areas they were drawn on to the physical screen if (_menuBuffer != nullptr) screen.slamArea(_menuBounds.left - _currentScroll.x, _menuBounds.top, _menuBounds.width(), _menuBounds.height()); if (_invMenuBuffer != nullptr) screen.slamArea(_invMenuBounds.left - _currentScroll.x, _invMenuBounds.top, _invMenuBounds.width(), _invMenuBounds.height()); // If therea re widgets being cleared, then restore that area of the screen if (_oldMenuBounds.right) { screen.slamArea(_oldMenuBounds.left - _currentScroll.x, _oldMenuBounds.top, _oldMenuBounds.width(), _oldMenuBounds.height()); _oldMenuBounds.left = _oldMenuBounds.top = _oldMenuBounds.right = _oldMenuBounds.bottom = 0; } if (_oldInvMenuBounds.left) { screen.slamArea(_oldInvMenuBounds.left - _currentScroll.x, _oldInvMenuBounds.top, _oldInvMenuBounds.width(), _oldInvMenuBounds.height()); _oldInvMenuBounds.left = _oldInvMenuBounds.top = _oldInvMenuBounds.right = _oldInvMenuBounds.bottom = 0; } // See if need to clear any tags if (_oldTagBounds.right) { screen.slamArea(_oldTagBounds.left - _currentScroll.x, _oldTagBounds.top, _oldTagBounds.width(), _oldTagBounds.height()); // If there's no tag actually being displayed, then reset bounds so we don't keep restoring the area if (_tagBuffer == nullptr) { _tagBounds.left = _tagBounds.top = _tagBounds.right = _tagBounds.bottom = 0; _oldTagBounds.left = _oldTagBounds.top = _oldTagBounds.right = _oldTagBounds.bottom = 0; } } if (_tagBuffer != nullptr) screen.slamArea(_tagBounds.left - _currentScroll.x, _tagBounds.top, _tagBounds.width(), _tagBounds.height()); // See if we need to flush areas assocaited with the inventory graphic if (_oldInvGraphicBounds.right) { screen.slamArea(_oldInvGraphicBounds.left - _currentScroll.x, _oldInvGraphicBounds.top, _oldInvGraphicBounds.width(), _oldInvGraphicBounds.height()); // If there's no graphic actually being displayed, then reset bounds so we don't keep restoring the area if (_invGraphic == nullptr) { _invGraphicBounds.left = _invGraphicBounds.top = _invGraphicBounds.right = _invGraphicBounds.bottom = 0; _oldInvGraphicBounds.left = _oldInvGraphicBounds.top = _oldInvGraphicBounds.right = _oldInvGraphicBounds.bottom = 0; } } if (_invGraphic != nullptr) screen.slamArea(_invGraphicBounds.left - _currentScroll.x, _invGraphicBounds.top, _invGraphicBounds.width(), _invGraphicBounds.height()); }
reg_t GfxPaint32::makeLineBitmap(const Common::Point &startPoint, const Common::Point &endPoint, const int16 priority, const uint8 color, const LineStyle style, uint16 pattern, uint8 thickness, Common::Rect &outRect) { const uint8 skipColor = color != kDefaultSkipColor ? kDefaultSkipColor : 0; // Line thickness is expected to be 2 * thickness + 1 thickness = (MAX<uint8>(1, thickness) - 1) | 1; const uint8 halfThickness = thickness >> 1; const uint16 scriptWidth = g_sci->_gfxFrameout->getCurrentBuffer().scriptWidth; const uint16 scriptHeight = g_sci->_gfxFrameout->getCurrentBuffer().scriptHeight; outRect.left = MIN<int16>(startPoint.x, endPoint.x); outRect.top = MIN<int16>(startPoint.y, endPoint.y); outRect.right = MAX<int16>(startPoint.x, endPoint.x) + 1 + 1; // rect lower edge + thickness offset outRect.bottom = MAX<int16>(startPoint.y, endPoint.y) + 1 + 1; // rect lower edge + thickness offset outRect.grow(halfThickness); outRect.clip(Common::Rect(scriptWidth, scriptHeight)); reg_t bitmapId; SciBitmap &bitmap = *_segMan->allocateBitmap(&bitmapId, outRect.width(), outRect.height(), skipColor, 0, 0, scriptWidth, scriptHeight, 0, false, true); byte *pixels = bitmap.getPixels(); memset(pixels, skipColor, bitmap.getWidth() * bitmap.getHeight()); LineProperties properties; properties.bitmap = &bitmap; switch (style) { case kLineStyleSolid: pattern = 0xFFFF; properties.solid = true; break; case kLineStyleDashed: pattern = 0xFF00; properties.solid = false; break; case kLineStylePattern: properties.solid = pattern == 0xFFFF; break; } // Change coordinates to be relative to the bitmap const int16 x1 = startPoint.x - outRect.left; const int16 y1 = startPoint.y - outRect.top; const int16 x2 = endPoint.x - outRect.left; const int16 y2 = endPoint.y - outRect.top; if (!properties.solid) { for (int i = 0; i < ARRAYSIZE(properties.pattern); ++i) { properties.pattern[i] = (pattern & 0x8000); pattern <<= 1; } properties.patternIndex = 0; properties.horizontal = ABS(x2 - x1) > ABS(y2 - y1); properties.lastAddress = properties.horizontal ? x1 : y1; } if (thickness <= 1) { Graphics::drawLine(x1, y1, x2, y2, color, plotter, &properties); } else { Graphics::drawThickLine2(x1, y1, x2, y2, thickness, color, plotter, &properties); } return bitmapId; }