diff options
Diffstat (limited to 'engines/sci/graphics/paint32.cpp')
-rw-r--r-- | engines/sci/graphics/paint32.cpp | 167 |
1 files changed, 140 insertions, 27 deletions
diff --git a/engines/sci/graphics/paint32.cpp b/engines/sci/graphics/paint32.cpp index a210a469f1..bfd46484e9 100644 --- a/engines/sci/graphics/paint32.cpp +++ b/engines/sci/graphics/paint32.cpp @@ -20,49 +20,162 @@ * */ -#include "sci/sci.h" -#include "sci/engine/state.h" -#include "sci/engine/selector.h" -#include "sci/graphics/coordadjuster.h" -#include "sci/graphics/cache.h" +#include "graphics/primitives.h" +#include "sci/engine/seg_manager.h" #include "sci/graphics/paint32.h" -#include "sci/graphics/font.h" -#include "sci/graphics/picture.h" -#include "sci/graphics/view.h" -#include "sci/graphics/screen.h" -#include "sci/graphics/palette.h" +#include "sci/graphics/text32.h" namespace Sci { -GfxPaint32::GfxPaint32(ResourceManager *resMan, GfxCoordAdjuster *coordAdjuster, GfxScreen *screen, GfxPalette *palette) - : _resMan(resMan), _coordAdjuster(coordAdjuster), _screen(screen), _palette(palette) { +GfxPaint32::GfxPaint32(SegManager *segMan) : + _segMan(segMan) {} + +reg_t GfxPaint32::kernelAddLine(const reg_t planeObject, const Common::Point &startPoint, const Common::Point &endPoint, const int16 priority, const uint8 color, const LineStyle style, const uint16 pattern, const uint8 thickness) { + Plane *plane = g_sci->_gfxFrameout->getPlanes().findByObject(planeObject); + if (plane == nullptr) { + error("kAddLine: Plane %04x:%04x not found", PRINT_REG(planeObject)); + } + + Common::Rect gameRect; + BitmapResource bitmap = makeLineBitmap(startPoint, endPoint, priority, color, style, pattern, thickness, gameRect); + + CelInfo32 celInfo; + celInfo.type = kCelTypeMem; + celInfo.bitmap = bitmap.getObject(); + // SSCI stores the line color on `celInfo`, even though + // this is not a `kCelTypeColor`, as a hack so that + // `kUpdateLine` can get the originally used color + celInfo.color = color; + + ScreenItem *screenItem = new ScreenItem(planeObject, celInfo, Common::Rect(startPoint.x, startPoint.y, startPoint.x + bitmap.getWidth(), startPoint.y + bitmap.getHeight())); + screenItem->_priority = priority; + screenItem->_fixedPriority = true; + + plane->_screenItemList.add(screenItem); + + return screenItem->_object; +} + +void GfxPaint32::kernelUpdateLine(ScreenItem *screenItem, Plane *plane, const Common::Point &startPoint, const Common::Point &endPoint, const int16 priority, const uint8 color, const LineStyle style, const uint16 pattern, const uint8 thickness) { + + Common::Rect gameRect; + BitmapResource bitmap = makeLineBitmap(startPoint, endPoint, priority, color, style, pattern, thickness, gameRect); + + _segMan->freeHunkEntry(screenItem->_celInfo.bitmap); + screenItem->_celInfo.bitmap = bitmap.getObject(); + screenItem->_celInfo.color = color; + screenItem->_position = startPoint; + screenItem->_priority = priority; + screenItem->update(); } -GfxPaint32::~GfxPaint32() { +void GfxPaint32::kernelDeleteLine(const reg_t screenItemObject, const reg_t planeObject) { + Plane *plane = g_sci->_gfxFrameout->getPlanes().findByObject(planeObject); + if (plane == nullptr) { + return; + } + + ScreenItem *screenItem = plane->_screenItemList.findByObject(screenItemObject); + if (screenItem == nullptr) { + return; + } + + _segMan->freeHunkEntry(screenItem->_celInfo.bitmap); + g_sci->_gfxFrameout->deleteScreenItem(screenItem, plane); } -void GfxPaint32::fillRect(Common::Rect rect, byte color) { - int16 y, x; - Common::Rect clipRect = rect; +void GfxPaint32::plotter(int x, int y, int color, void *data) { + LineProperties &properties = *static_cast<LineProperties *>(data); + byte *pixels = properties.bitmap->getPixels(); + + const uint32 index = properties.bitmap->getWidth() * y + x; + + if (index < properties.bitmap->getDataSize()) { + if (properties.solid) { + pixels[index] = (uint8)color; + return; + } + + if (properties.horizontal && x != properties.lastAddress) { + properties.lastAddress = x; + ++properties.patternIndex; + } else if (!properties.horizontal && y != properties.lastAddress) { + properties.lastAddress = y; + ++properties.patternIndex; + } - clipRect.clip(_screen->getWidth(), _screen->getHeight()); + if (properties.pattern[properties.patternIndex]) { + pixels[index] = (uint8)color; + } - for (y = clipRect.top; y < clipRect.bottom; y++) { - for (x = clipRect.left; x < clipRect.right; x++) { - _screen->putPixel(x, y, GFX_SCREEN_MASK_VISUAL, color, 0, 0); + if (properties.patternIndex == ARRAYSIZE(properties.pattern)) { + properties.patternIndex = 0; } + } else { + warning("GfxPaint32::plotter: Attempted to write out of bounds (%u >= %u)", index, properties.bitmap->getDataSize()); } } -void GfxPaint32::kernelDrawPicture(GuiResourceId pictureId, int16 animationNr, bool animationBlackoutFlag, bool mirroredFlag, bool addToFlag, int16 EGApaletteNo) { - GfxPicture *picture = new GfxPicture(_resMan, _coordAdjuster, 0, _screen, _palette, pictureId, false); +BitmapResource 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 != 250 ? 250 : 0; - picture->draw(animationNr, mirroredFlag, addToFlag, EGApaletteNo); - delete picture; -} + // Thickness is expected to be 2n+1 + thickness = ((MAX((uint8)1, thickness) - 1) | 1); + const uint8 halfThickness = thickness >> 1; + + outRect.left = (startPoint.x < endPoint.x ? startPoint.x : endPoint.x) - halfThickness; + outRect.top = (startPoint.y < endPoint.y ? startPoint.y : endPoint.y) - halfThickness; + outRect.right = (startPoint.x > endPoint.x ? startPoint.x : endPoint.x) + halfThickness + 1; + outRect.bottom = (startPoint.y > endPoint.y ? startPoint.y : endPoint.y) + halfThickness + 1; + + BitmapResource bitmap(_segMan, outRect.width(), outRect.height(), skipColor, 0, 0, g_sci->_gfxFrameout->getCurrentBuffer().scriptWidth, g_sci->_gfxFrameout->getCurrentBuffer().scriptHeight, 0, false); + + 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; + } + + const Common::Rect drawRect( + startPoint.x - outRect.left, + startPoint.y - outRect.top, + endPoint.x - outRect.left, + endPoint.y - outRect.top + ); -void GfxPaint32::kernelGraphDrawLine(Common::Point startPoint, Common::Point endPoint, int16 color, int16 priority, int16 control) { - _screen->drawLine(startPoint.x, startPoint.y, endPoint.x, endPoint.y, color, priority, control); + 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(drawRect.right - drawRect.left) > ABS(drawRect.bottom - drawRect.top); + properties.lastAddress = properties.horizontal ? drawRect.left : drawRect.top; + } + + if (thickness <= 1) { + Graphics::drawLine(drawRect.left, drawRect.top, drawRect.right, drawRect.bottom, color, plotter, &properties); + } else { + Graphics::drawThickLine2(drawRect.left, drawRect.top, drawRect.right, drawRect.bottom, thickness, color, plotter, &properties); + } + + return bitmap; } + } // End of namespace Sci |