Skip to content

Commit f321471

Browse files
committed
Fix graphics-to-graphics VIEW clipping and WINDOW scaling support and add tests
1 parent 30d4ad3 commit f321471

3 files changed

Lines changed: 162 additions & 61 deletions

File tree

internal/c/libqb.cpp

Lines changed: 69 additions & 60 deletions
Original file line numberDiff line numberDiff line change
@@ -4675,6 +4675,15 @@ void sub__putimage(double f_dx1, double f_dy1, double f_dx2, double f_dy2, int32
46754675
//(decided not to throw error, QB64 will use linear filtering if/when available)
46764676
// if (passed&128){error(5); return;}//software surfaces do not support pixel _SMOOTHing yet
46774677

4678+
const int32 srcClipX1 = s->clipping_or_scaling ? s->view_x1 : 0;
4679+
const int32 srcClipY1 = s->clipping_or_scaling ? s->view_y1 : 0;
4680+
const int32 srcClipX2 = s->clipping_or_scaling ? s->view_x2 : (sw - 1);
4681+
const int32 srcClipY2 = s->clipping_or_scaling ? s->view_y2 : (sh - 1);
4682+
const int32 dstClipX1 = d->clipping_or_scaling ? d->view_x1 : 0;
4683+
const int32 dstClipY1 = d->clipping_or_scaling ? d->view_y1 : 0;
4684+
const int32 dstClipX2 = d->clipping_or_scaling ? d->view_x2 : (dw - 1);
4685+
const int32 dstClipY2 = d->clipping_or_scaling ? d->view_y2 : (dh - 1);
4686+
46784687
if ((passed & 4) && (passed & 512)) { // all co-ords given
46794688
// could be stretched
46804689
if ((abs(dx2 - dx1) == abs(sx2 - sx1)) && (abs(dy2 - dy1) == abs(sy2 - sy1))) { // non-stretched
@@ -4857,47 +4866,47 @@ void sub__putimage(double f_dx1, double f_dy1, double f_dx2, double f_dy2, int32
48574866
my = 0.0;
48584867
// note: mx & my represent the amount of change per dest pixel
48594868

4860-
// crop dest offscreen pixels
4861-
if (dx1 < 0) {
4869+
// crop dest pixels against destination clipping bounds
4870+
if (dx1 < dstClipX1) {
48624871
if (mirror)
4863-
fsx2 += ((double)dx1) * mx;
4872+
fsx2 += ((double)(dx1 - dstClipX1)) * mx;
48644873
else
4865-
fsx1 -= ((double)dx1) * mx;
4866-
dx1 = 0;
4874+
fsx1 -= ((double)(dx1 - dstClipX1)) * mx;
4875+
dx1 = dstClipX1;
48674876
}
4868-
if (dy1 < 0) {
4877+
if (dy1 < dstClipY1) {
48694878
if (flip)
4870-
fsy2 += ((double)dy1) * my;
4879+
fsy2 += ((double)(dy1 - dstClipY1)) * my;
48714880
else
4872-
fsy1 -= ((double)dy1) * my;
4873-
dy1 = 0;
4881+
fsy1 -= ((double)(dy1 - dstClipY1)) * my;
4882+
dy1 = dstClipY1;
48744883
}
4875-
if (dx2 >= dw) {
4884+
if (dx2 > dstClipX2) {
48764885
if (mirror)
4877-
fsx1 += ((double)(dx2 - dw + 1)) * mx;
4886+
fsx1 += ((double)(dx2 - dstClipX2)) * mx;
48784887
else
4879-
fsx2 -= ((double)(dx2 - dw + 1)) * mx;
4880-
dx2 = dw - 1;
4888+
fsx2 -= ((double)(dx2 - dstClipX2)) * mx;
4889+
dx2 = dstClipX2;
48814890
}
4882-
if (dy2 >= dh) {
4891+
if (dy2 > dstClipY2) {
48834892
if (flip)
4884-
fsy1 += ((double)(dy2 - dh + 1)) * my;
4893+
fsy1 += ((double)(dy2 - dstClipY2)) * my;
48854894
else
4886-
fsy2 -= ((double)(dy2 - dh + 1)) * my;
4887-
dy2 = dh - 1;
4895+
fsy2 -= ((double)(dy2 - dstClipY2)) * my;
4896+
dy2 = dstClipY2;
48884897
}
4889-
// crop source offscreen pixels
4898+
// crop source pixels against source clipping bounds
48904899
if (w) { // gradient cannot be 0
4891-
if (fsx1 < -0.4999999) {
4892-
x = (-fsx1 - 0.499999) / mx + 1.0;
4900+
if (fsx1 < (((double)srcClipX1) - 0.4999999)) {
4901+
x = ((((double)srcClipX1) - 0.499999) - fsx1) / mx + 1.0;
48934902
if (mirror)
48944903
dx2 -= x;
48954904
else
48964905
dx1 += x;
48974906
fsx1 += ((double)x) * mx;
48984907
}
4899-
if (fsx2 > (((double)sw) - 0.5000001)) {
4900-
x = (fsx2 - (((double)sw) - 0.500001)) / mx + 1.0;
4908+
if (fsx2 > (((double)srcClipX2) + 0.4999999)) {
4909+
x = (fsx2 - (((double)srcClipX2) + 0.499999)) / mx + 1.0;
49014910
if (mirror)
49024911
dx1 += x;
49034912
else
@@ -4906,16 +4915,16 @@ void sub__putimage(double f_dx1, double f_dy1, double f_dx2, double f_dy2, int32
49064915
}
49074916
} // w
49084917
if (h) { // gradient cannot be 0
4909-
if (fsy1 < -0.4999999) {
4910-
y = (-fsy1 - 0.499999) / my + 1.0;
4918+
if (fsy1 < (((double)srcClipY1) - 0.4999999)) {
4919+
y = ((((double)srcClipY1) - 0.499999) - fsy1) / my + 1.0;
49114920
if (flip)
49124921
dy2 -= y;
49134922
else
49144923
dy1 += y;
49154924
fsy1 += ((double)y) * my;
49164925
}
4917-
if (fsy2 > (((double)sh) - 0.5000001)) {
4918-
y = (fsy2 - (((double)sh) - 0.500001)) / my + 1.0;
4926+
if (fsy2 > (((double)srcClipY2) + 0.4999999)) {
4927+
y = (fsy2 - (((double)srcClipY2) + 0.499999)) / my + 1.0;
49194928
if (flip)
49204929
dy1 += y;
49214930
else
@@ -5258,63 +5267,63 @@ void sub__putimage(double f_dx1, double f_dy1, double f_dx2, double f_dy2, int32
52585267
}
52595268

52605269
clip:
5261-
// crop dest offscreen pixels
5262-
if (dx1 < 0) {
5270+
// crop destination against destination clipping bounds
5271+
if (dx1 < dstClipX1) {
52635272
if (mirror)
5264-
sx2 += dx1;
5273+
sx2 += (dx1 - dstClipX1);
52655274
else
5266-
sx1 -= dx1;
5267-
dx1 = 0;
5275+
sx1 -= (dx1 - dstClipX1);
5276+
dx1 = dstClipX1;
52685277
}
5269-
if (dy1 < 0) {
5278+
if (dy1 < dstClipY1) {
52705279
if (flip)
5271-
sy2 += dy1;
5280+
sy2 += (dy1 - dstClipY1);
52725281
else
5273-
sy1 -= dy1;
5274-
dy1 = 0;
5282+
sy1 -= (dy1 - dstClipY1);
5283+
dy1 = dstClipY1;
52755284
}
5276-
if (dx2 >= dw) {
5285+
if (dx2 > dstClipX2) {
52775286
if (mirror)
5278-
sx1 += (dx2 - dw + 1);
5287+
sx1 += (dx2 - dstClipX2);
52795288
else
5280-
sx2 -= (dx2 - dw + 1);
5281-
dx2 = dw - 1;
5289+
sx2 -= (dx2 - dstClipX2);
5290+
dx2 = dstClipX2;
52825291
}
5283-
if (dy2 >= dh) {
5292+
if (dy2 > dstClipY2) {
52845293
if (flip)
5285-
sy1 += (dy2 - dh + 1);
5294+
sy1 += (dy2 - dstClipY2);
52865295
else
5287-
sy2 -= (dy2 - dh + 1);
5288-
dy2 = dh - 1;
5296+
sy2 -= (dy2 - dstClipY2);
5297+
dy2 = dstClipY2;
52895298
}
5290-
// crop source offscreen pixels
5291-
if (sx1 < 0) {
5299+
// crop source against source clipping bounds
5300+
if (sx1 < srcClipX1) {
52925301
if (mirror)
5293-
dx2 += sx1;
5302+
dx2 += (sx1 - srcClipX1);
52945303
else
5295-
dx1 -= sx1;
5296-
sx1 = 0;
5304+
dx1 -= (sx1 - srcClipX1);
5305+
sx1 = srcClipX1;
52975306
}
5298-
if (sy1 < 0) {
5307+
if (sy1 < srcClipY1) {
52995308
if (flip)
5300-
dy2 += sy1;
5309+
dy2 += (sy1 - srcClipY1);
53015310
else
5302-
dy1 -= sy1;
5303-
sy1 = 0;
5311+
dy1 -= (sy1 - srcClipY1);
5312+
sy1 = srcClipY1;
53045313
}
5305-
if (sx2 >= sw) {
5314+
if (sx2 > srcClipX2) {
53065315
if (mirror)
5307-
dx1 += (sx2 - sw + 1);
5316+
dx1 += (sx2 - srcClipX2);
53085317
else
5309-
dx2 -= (sx2 - sw + 1);
5310-
sx2 = sw - 1;
5318+
dx2 -= (sx2 - srcClipX2);
5319+
sx2 = srcClipX2;
53115320
}
5312-
if (sy2 >= sh) {
5321+
if (sy2 > srcClipY2) {
53135322
if (flip)
5314-
dy1 += (sy2 - sh + 1);
5323+
dy1 += (sy2 - srcClipY2);
53155324
else
5316-
dy2 -= (sy2 - sh + 1);
5317-
sy2 = sh - 1;
5325+
dy2 -= (sy2 - srcClipY2);
5326+
sy2 = srcClipY2;
53185327
}
53195328
//<0-size/offscreen?
53205329
// note: <0-size will cause reversal of dest

tests/compile_tests/putimage/putimage_test.bas

Lines changed: 89 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,9 @@ TestTextToGraphics32Reversed
2727
TestTextToGraphics32Mirrored
2828
TestTextToGraphics32Flipped
2929
TestTextToGraphics32Clipping
30+
TestGraphicsToGraphics32ViewClip
31+
TestGraphicsToGraphics32WindowNoScale
32+
TestGraphicsToGraphics32SourceViewClip
3033

3134
TestTextToGraphics8Basic
3235
TestTextToGraphics8Mirrored
@@ -135,6 +138,18 @@ SUB PrepareGraphicsDestination32 (img AS LONG)
135138
_DEST oldDest
136139
END SUB
137140

141+
SUB PrepareGraphicsSource32 (img AS LONG)
142+
DIM oldDest AS LONG: oldDest = _DEST
143+
144+
_DEST img
145+
CLS , _RGB32(0, 0, 0)
146+
LINE (0, 0)-(_WIDTH(img) - 1, _HEIGHT(img) - 1), _RGB32(255, 64, 32), BF
147+
LINE (8, 8)-(_WIDTH(img) - 9, _HEIGHT(img) - 9), _RGB32(32, 192, 255), BF
148+
LINE (16, 16)-(_WIDTH(img) - 17, _HEIGHT(img) - 17), _RGB32(255, 255, 64), BF
149+
150+
_DEST oldDest
151+
END SUB
152+
138153
SUB PrepareGraphicsDestinationIndexed (img AS LONG)
139154
DIM oldDest AS LONG
140155
oldDest = _DEST
@@ -536,6 +551,80 @@ SUB TestTextToGraphics32Clipping
536551
_FREEIMAGE dst
537552
END SUB
538553

554+
SUB TestGraphicsToGraphics32ViewClip
555+
DIM src AS LONG: src = _NEWIMAGE(80, 80, 32)
556+
PrepareGraphicsSource32 src
557+
DIM dst AS LONG: dst = _NEWIMAGE(320, 200, 32)
558+
PrepareGraphicsDestination32 dst
559+
560+
_DEST dst
561+
VIEW (40, 40)-(99, 99)
562+
_PUTIMAGE (0, 0), src, dst
563+
VIEW
564+
'_SAVEIMAGE "TestGraphicsToGraphics32ViewClip", dst
565+
566+
DIM ok AS _BYTE: ok = _TRUE
567+
IF CountNonBlack32(dst, 40, 40, 99, 99) <= 0 THEN ok = _FALSE
568+
IF CountNonBlackOutsideRect32(dst, 40, 40, 99, 99) <> 0 THEN ok = _FALSE
569+
IF Pixel32(dst, 40, 40) <> _RGB32(255, 64, 32) THEN ok = _FALSE
570+
IF Pixel32(dst, 48, 48) <> _RGB32(32, 192, 255) THEN ok = _FALSE
571+
IF Pixel32(dst, 56, 56) <> _RGB32(255, 255, 64) THEN ok = _FALSE
572+
IF Pixel32(dst, 99, 99) <> _RGB32(255, 255, 64) THEN ok = _FALSE
573+
574+
ReportCheck "graphics->graphics 32bpp VIEW clip", ok
575+
_FREEIMAGE dst
576+
_FREEIMAGE src
577+
END SUB
578+
579+
SUB TestGraphicsToGraphics32WindowNoScale
580+
DIM src AS LONG: src = _NEWIMAGE(80, 80, 32)
581+
PrepareGraphicsSource32 src
582+
DIM dst AS LONG: dst = _NEWIMAGE(320, 200, 32)
583+
PrepareGraphicsDestination32 dst
584+
DIM ref AS LONG: ref = _NEWIMAGE(320, 200, 32)
585+
PrepareGraphicsDestination32 ref
586+
587+
_PUTIMAGE (80, 80), src, ref
588+
589+
_DEST dst
590+
VIEW (40, 40)-(199, 199)
591+
WINDOW SCREEN(0, 0)-(159, 159)
592+
_PUTIMAGE (40, 40), src, dst
593+
WINDOW
594+
VIEW
595+
'_SAVEIMAGE "TestGraphicsToGraphics32WindowNoScale", dst
596+
597+
DIM ok AS _BYTE: ok = _TRUE
598+
IF RegionsEqual32(ref, 80, 80, dst, 80, 80, 80, 80, 1, 1) = _FALSE THEN ok = _FALSE
599+
IF CountNonBlackOutsideRect32(dst, 80, 80, 159, 159) <> 0 THEN ok = _FALSE
600+
601+
ReportCheck "graphics->graphics 32bpp WINDOW", ok
602+
_FREEIMAGE ref
603+
_FREEIMAGE dst
604+
_FREEIMAGE src
605+
END SUB
606+
607+
SUB TestGraphicsToGraphics32SourceViewClip
608+
DIM src AS LONG: src = _NEWIMAGE(80, 80, 32)
609+
PrepareGraphicsSource32 src
610+
DIM dst AS LONG: dst = _NEWIMAGE(320, 200, 32)
611+
PrepareGraphicsDestination32 dst
612+
613+
_DEST src
614+
VIEW (20, 20)-(59, 59)
615+
_PUTIMAGE (30, 30), src, dst
616+
VIEW
617+
'_SAVEIMAGE "TestGraphicsToGraphics32SourceViewClip", dst
618+
619+
DIM ok AS _BYTE: ok = _TRUE
620+
IF CountNonBlack32(dst, 50, 50, 89, 89) <= 0 THEN ok = _FALSE
621+
IF CountNonBlackOutsideRect32(dst, 50, 50, 89, 89) <> 0 THEN ok = _FALSE
622+
623+
ReportCheck "graphics->graphics 32bpp source VIEW", ok
624+
_FREEIMAGE dst
625+
_FREEIMAGE src
626+
END SUB
627+
539628
SUB TestTextToGraphics8Basic
540629
DIM dst AS LONG: dst = _NEWIMAGE(320, 200, 256)
541630
PrepareGraphicsDestinationIndexed dst

tests/compile_tests/putimage/putimage_test.output

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,9 @@ PASS: text->graphics 32bpp reversed rect
1010
PASS: text->graphics 32bpp mirrored
1111
PASS: text->graphics 32bpp flipped
1212
PASS: text->graphics 32bpp clipping
13+
PASS: graphics->graphics 32bpp VIEW clip
14+
PASS: graphics->graphics 32bpp WINDOW
15+
PASS: graphics->graphics 32bpp source VIEW
1316
PASS: text->graphics 8bpp basic
1417
PASS: text->graphics 8bpp mirrored
1518
PASS: text->graphics 8bpp flipped
@@ -22,4 +25,4 @@ PASS: text->graphics scale illegal
2225
PASS: text->graphics 2bpp illegal
2326
PASS: graphics->text illegal
2427
PASS: text->graphics 32bpp TTF font
25-
ALL TESTS PASSED 24
28+
ALL TESTS PASSED 27

0 commit comments

Comments
 (0)