Clipping working.

This commit is contained in:
Scott Duensing 2022-06-17 19:13:04 -05:00
parent 9155594947
commit 3c51c33430
4 changed files with 74 additions and 54 deletions

View file

@ -28,18 +28,19 @@ static ColorT _mouseTransparency;
void guiEventsDo(void) {
EventT event = { 0 };
// Read mouse & keyboard.
platformEventGet(&event);
// Paint desktop.
surfaceSet(__guiBackBuffer);
surfaceClear(GUI_CYAN);
// Paint GUI.
// Read mouse & keyboard.
platformEventGet(&event);
// Handle GUI window manager and widgets.
wmUpdate(&event);
// Paint mouse pointer.
surfaceBlitWithTransparency(__guiBackBuffer, event.x, event.y, _mousePointer, _mouseTransparency);
surfaceSet(__guiBackBuffer);
surfaceBlitWithTransparency(event.x, event.y, _mousePointer, _mouseTransparency);
// Copy to screen.
videoBlit(0, 0, __guiBackBuffer);
@ -118,11 +119,9 @@ uint8_t guiStartup(int16_t width, int16_t height, int16_t depth) {
__guiBaseColors[i] = surfaceColorMake(EGA[i][0], EGA[i][1], EGA[i][2]);
}
__guiBackBuffer = surfaceCreate(videoDisplayWidthGet(), videoDisplayHeightGet());
surfaceSet(__guiBackBuffer);
_mousePointer = imageLoad("mouse.png");
_mouseTransparency = surfacePixelGet(_mousePointer, surfaceWidthGet(_mousePointer) - 2, 0); // Find our transparency color.
_mousePointer = imageLoad("mouse.png");
surfaceSet(_mousePointer);
_mouseTransparency = surfacePixelGet(_mousePointer, surfaceWidthGet() - 2, 0); // Find our transparency color.
__guiFontVGA8x8 = fontLoad("vga8x8.dat");
__guiFontVGA8x14 = fontLoad("vga8x14.dat");
@ -130,6 +129,9 @@ uint8_t guiStartup(int16_t width, int16_t height, int16_t depth) {
fontSet(__guiFontVGA8x14);
fontColorSet(GUI_WHITE, GUI_BLACK);
__guiBackBuffer = surfaceCreate(videoDisplayWidthGet(), videoDisplayHeightGet());
surfaceSet(__guiBackBuffer);
wmStartup();
// Register all known widgets with the GUI.

View file

@ -19,52 +19,75 @@ static void surfacePixelSet8(uint16_t x, uint16_t y, ColorT color);
static void surfacePixelSet16(uint16_t x, uint16_t y, ColorT color);
static void surfacePixelSet32(uint16_t x, uint16_t y, ColorT color);
#include "gui.h"
void surfaceBlit(SurfaceT *target, int16_t targetX, int16_t targetY, SurfaceT *source) {
uint16_t y1;
void surfaceBlit(int16_t targetX, int16_t targetY, SurfaceT *source) {
int16_t y;
int16_t x1 = 0;
int16_t y1 = 0;
int16_t x2 = source->width;
int16_t y2 = source->height;
size_t bytes;
size_t offsetTarget;
size_t offsetSource;
if (targetX == 0 && targetY == 0 && target->width == source->width && target->height == source->height) {
// Clip on top and left. x1 & y1 are pixel locations inside the source bitmap.
if (targetX < 0) x1 = -targetX;
if (targetY < 0) y1 = -targetY;
// Clip on right and bottom.
if (targetX + x2 > __surfaceActive->width) x2 -= targetX + x2 - __surfaceActive->width;
if (targetY + y2 > __surfaceActive->height) y2 -= targetY + y2 - __surfaceActive->height;
// Are we still on the screen?
if (x1 < 0 || y1 < 0 || x2 < x1 || y2 < y1) return;
if (targetX == 0 && targetY == 0 && __surfaceActive->width == source->width && __surfaceActive->height == source->height) {
// Direct blit of entire surface.
memcpy(target->buffer.bits8, source->buffer.bits8, source->bytes);
memcpy(__surfaceActive->buffer.bits8, source->buffer.bits8, source->bytes);
} else {
// Blit into larger surface.
offsetTarget = targetY * __surfaceActive->scanline + targetX * __surfaceBytesPerPixel;
offsetSource = 0;
for (y1=targetY; y1<targetY+source->height; y1++) {
memcpy(&target->buffer.bits8[offsetTarget], &source->buffer.bits8[offsetSource], source->scanline);
offsetTarget += target->scanline;
offsetTarget = (targetY + y1) * __surfaceActive->scanline + (targetX + x1) * __surfaceBytesPerPixel;
offsetSource = y1 * source->scanline + x1 * __surfaceBytesPerPixel;
bytes = (x2 - x1) * __surfaceBytesPerPixel;
for (y=y1; y<y2; y++) {
memcpy(&__surfaceActive->buffer.bits8[offsetTarget], &source->buffer.bits8[offsetSource], bytes);
offsetTarget += __surfaceActive->scanline;
offsetSource += source->scanline;
}
}
}
void surfaceBlitWithTransparency(SurfaceT *target, int16_t targetX, int16_t targetY, SurfaceT *source, ColorT transparent) {
uint16_t x1;
uint16_t y1;
uint16_t x2 = source->width;
uint16_t y2 = source->height;
void surfaceBlitWithTransparency(int16_t targetX, int16_t targetY, SurfaceT *source, ColorT transparent) {
int16_t x;
int16_t y;
int16_t x1 = 0;
int16_t y1 = 0;
int16_t x2 = source->width;
int16_t y2 = source->height;
ColorT pixel;
SurfaceT *t = surfaceGet();
surfaceSet(target);
// Clip on top and left. x1 & y1 are pixel locations inside the source bitmap. ox & oy offset those into screen coordinates.
if (targetX < 0) x1 = -targetX;
if (targetY < 0) y1 = -targetY;
// Clip on right and bottom
if (targetX + x2 > target->width) x2 -= targetX + x2 - target->width;
if (targetY + y2 > target->height) y2 -= targetY + y2 - target->height;
// Clip on right and bottom.
if (targetX + x2 > __surfaceActive->width) x2 -= targetX + x2 - __surfaceActive->width;
if (targetY + y2 > __surfaceActive->height) y2 -= targetY + y2 - __surfaceActive->height;
for (y1=0; y1<y2; y1++) {
for (x1=0; x1<x2; x1++) {
pixel = surfacePixelGet(source, x1, y1);
// Are we still on the screen?
if (x1 < 0 || y1 < 0 || x2 < x1 || y2 < y1) return;
// Blit.
for (y=y1; y<y2; y++) {
for (x=x1; x<x2; x++) {
pixel = surfacePixelGet(source, x, y);
if (transparent != pixel) {
surfacePixelSet(targetX + x1, targetY + y1, pixel);
surfacePixelSet(targetX + x, targetY + y, pixel);
}
}
}
surfaceSet(t);
}
@ -179,8 +202,8 @@ SurfaceT *surfaceGet(void) {
}
int16_t surfaceHeightGet(SurfaceT *surface) {
return surface->height;
int16_t surfaceHeightGet(void) {
return __surfaceActive->height;
}
@ -381,8 +404,8 @@ void surfaceStartup(uint8_t bits) {
}
int16_t surfaceWidthGet(SurfaceT *surface) {
return surface->width;
int16_t surfaceWidthGet() {
return __surfaceActive->width;
}

View file

@ -45,8 +45,8 @@ extern ColorT (*surfacePixelGet)(SurfaceT *surface, int16_t x, int16_t y);
extern void (*surfacePixelSet)(uint16_t x, uint16_t y, ColorT color);
void surfaceBlit(SurfaceT *target, int16_t targetX, int16_t targetY, SurfaceT *source);
void surfaceBlitWithTransparency(SurfaceT *target, int16_t targetX, int16_t targetY, SurfaceT *source, ColorT transparent);
void surfaceBlit(int16_t targetX, int16_t targetY, SurfaceT *source);
void surfaceBlitWithTransparency(int16_t targetX, int16_t targetY, SurfaceT *source, ColorT transparent);
void surfaceClear(ColorT color);
ColorT surfaceColorMake(uint8_t r, uint8_t g, uint8_t b);
SurfaceT *surfaceCreate(int16_t width, int16_t height);
@ -55,14 +55,14 @@ void surfaceBoxFilled(int16_t x1, int16_t y1, int16_t x2, int16_t y2, Color
void surfaceBoxHighlight(int16_t x1, int16_t y1, int16_t x2, int16_t y2, ColorT highlight, ColorT shadow);
void surfaceDestroy(SurfaceT **surface);
SurfaceT *surfaceGet(void);
int16_t surfaceHeightGet(SurfaceT *surface);
int16_t surfaceHeightGet(void);
void surfaceLine(int16_t x1, int16_t y1, int16_t x2, int16_t y2, ColorT color);
void surfaceLineH(int16_t x1, int16_t x2, int16_t y, ColorT c);
void surfaceLineV(int16_t x, int16_t y1, int16_t y2, ColorT c);
void surfaceSet(SurfaceT *surface);
void surfaceShutdown(void);
void surfaceStartup(uint8_t bits);
int16_t surfaceWidthGet(SurfaceT *surface);
int16_t surfaceWidthGet(void);
#endif // SURFACE_H

View file

@ -3,9 +3,6 @@
#include "font.h"
#define USE_CACHING
uint8_t __MAGIC_WINDOW = 0;
static WindowT **_windowList = NULL;
@ -172,7 +169,6 @@ void windowPaint(struct WidgetS *widget, ...) {
target = surfaceGet();
w = (WindowT *)widget;
#ifdef USE_CACHING
// Do we need redrawn?
if (guiWidgetDirtyGet(widget)) {
guiWidgetDirtySet(widget, 0);
@ -186,7 +182,8 @@ void windowPaint(struct WidgetS *widget, ...) {
// Do we have a cached surface already?
if (w->cached) {
// Did the size change?
if ((surfaceWidthGet(w->cached) != w->base.r.w) || (surfaceHeightGet(w->cached) != w->base.r.h)) {
surfaceSet(w->cached);
if ((surfaceWidthGet() != w->base.r.w) || (surfaceHeightGet() != w->base.r.h)) {
// Yeah. We will recreate it.
surfaceDestroy(&w->cached);
}
@ -198,7 +195,6 @@ void windowPaint(struct WidgetS *widget, ...) {
// Draw into cache.
surfaceSet(w->cached);
#endif
// Determine some colors.
titleBackgroundColor = (w == _windowTop) ? GUI_DARKGRAY : GUI_LIGHTGRAY;
@ -314,14 +310,13 @@ void windowPaint(struct WidgetS *widget, ...) {
// Fake Window contents.
surfaceBoxFilled(w->bounds.x, w->bounds.y, w->bounds.x2, w->bounds.y2, GUI_BLACK);
#ifdef USE_CACHING
// Fixup all the widget coordinates.
windowMoveTo(w, originalX, originalY);
}
// By now we have a valid cached window. Blit it.
surfaceBlit(target, w->base.r.x, w->base.r.y, w->cached);
#endif
surfaceSet(target);
surfaceBlit(w->base.r.x, w->base.r.y, w->cached);
}
@ -359,8 +354,6 @@ void wmUpdate(EventT *event) {
widget->reg->paint(widget);
}
if (dragging) sleep(1);
// Get top window.
win = _windowList[arrlen(_windowList) - 1];
@ -373,6 +366,7 @@ void wmUpdate(EventT *event) {
// Is the left mouse button down?
if (event->buttons & BUTTON_LEFT) {
/*
// DEBUG - draw active regions. ***TODO*** No resize grabber here.
surfaceSet(__guiBackBuffer);
surfaceBox(win->base.r.x, win->base.r.y, x2, y2, GUI_YELLOW);
@ -381,6 +375,7 @@ void wmUpdate(EventT *event) {
surfaceBox(win->titlebar.x, win->titlebar.y, win->titlebar.x2, win->titlebar.y2, GUI_LIGHTCYAN);
surfaceBox(win->minimize.x, win->minimize.y, win->minimize.x2, win->minimize.y2, GUI_LIGHTGREEN);
surfaceBox(win->maximize.x, win->maximize.y, win->maximize.x2, win->maximize.y2, GUI_RED);
*/
// Are we currently dragging?
if (dragging) {