1 #include "Renderer_vga.h"
4 #define MIN(a, b) ((a) < (b) ? (a) : (b))
6 const unsigned char kCursorBits
[] = {
7 0x3f,0x3f,0x00,0x00,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
8 0x3f,0x3f,0x3f,0x3f,0x00,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
9 0xff,0x3f,0x3f,0x3f,0x3f,0x00,0x00,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
10 0xff,0x3f,0x3f,0x3f,0x3f,0x3f,0x3f,0x00,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
11 0xff,0xff,0x3f,0x3f,0x3f,0x3f,0x3f,0x3f,0x3f,0x00,0xff,0xff,0xff,0xff,0xff,0xff,
12 0xff,0xff,0xff,0x3f,0x3f,0x3f,0x3f,0x3f,0x3f,0x3f,0x00,0xff,0xff,0xff,0xff,0xff,
13 0xff,0xff,0xff,0x3f,0x3f,0x3f,0x3f,0x3f,0x3f,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
14 0xff,0xff,0xff,0xff,0x3f,0x3f,0x3f,0x3f,0x00,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
15 0xff,0xff,0xff,0xff,0x3f,0x3f,0x3f,0xff,0x3f,0x00,0xff,0xff,0xff,0xff,0xff,0xff,
16 0xff,0xff,0xff,0xff,0xff,0x3f,0xff,0xff,0xff,0x3f,0x00,0xff,0xff,0xff,0xff,0xff,
17 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x3f,0x00,0xff,0xff,0xff,0xff,
18 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x3f,0x00,0xff,0xff,0xff,
19 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x3f,0x00,0xff,0xff,
20 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x3f,0x00,0xff,
21 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x3f,0xff,
22 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff
25 Renderer_vga::Renderer_vga(char *baseAddress
, int width
, int height
, int bytesPerRow
)
26 : Renderer_8bpp(baseAddress
, width
, height
, bytesPerRow
)
29 fCursorY
= height
/ 2;
33 const unsigned kBottom
= 1;
34 const unsigned kTop
= 2;
35 const unsigned kLeft
= 4;
36 const unsigned kRight
= 8;
38 #define clipmask(x, y, rect) \
39 ({ unsigned mask = 0; \
40 if (x < rect.left) mask |= kLeft; \
41 else if (x > rect.right) mask |= kRight; \
42 if (y < rect.top) mask |= kTop; \
43 else if (y > rect.bottom) mask |= kBottom; \
46 inline int vert_intersection(int x1
, int y1
, int x2
, int y2
, int x
)
48 return y1
+ (y2
- y1
) * (x
- x1
) / (x2
- x1
);
51 inline int horz_intersection(int x1
, int y1
, int x2
, int y2
, int y
)
53 return x1
+ (x2
- x1
) * (y
- y1
) / (y2
- y1
);
56 void Renderer_vga::DrawLine(int x1
, int y1
, int x2
, int y2
, char color
)
58 Rect
cursorRect(fCursorX
, fCursorY
, fCursorX
+ 16, fCursorY
+ 16);
59 bool invalidateCursor
= true;
65 unsigned point1mask
= clipmask(clippedX1
, clippedY1
, cursorRect
);
66 unsigned point2mask
= clipmask(clippedX2
, clippedY2
, cursorRect
);
67 while (point1mask
!= 0 || point2mask
!= 0) {
68 if ((point1mask
& point2mask
) != 0) {
69 invalidateCursor
= false;
73 unsigned mask
= point1mask
? point1mask
: point2mask
;
77 y
= cursorRect
.bottom
;
78 x
= horz_intersection(clippedX1
, clippedY1
, clippedX2
, clippedY2
, y
);
79 } else if (mask
& kTop
) {
81 x
= horz_intersection(clippedX1
, clippedY1
, clippedX2
, clippedY2
, y
);
82 } else if (mask
& kRight
) {
84 y
= vert_intersection(clippedX1
, clippedY1
, clippedX2
, clippedY2
, x
);
85 } else if (mask
& kLeft
) {
87 y
= vert_intersection(clippedX1
, clippedY1
, clippedX2
, clippedY2
, x
);
92 point1mask
= clipmask(x
, y
, cursorRect
);
97 point2mask
= clipmask(x
, y
, cursorRect
);
103 if (invalidateCursor
)
106 Renderer_8bpp::DrawLine(x1
, y1
, x2
, y2
, color
);
108 if (invalidateCursor
)
112 void Renderer_vga::FillRect(int x1
, int y1
, int x2
, int y2
, char color
)
115 bool invalidateCursor
= false;
116 if (Rect(x1
, y1
, x2
, y2
).Intersects(Rect(fCursorX
, fCursorY
, fCursorX
+ 16,
118 invalidateCursor
= true;
122 Renderer_8bpp::FillRect(x1
, y1
, x2
, y2
, color
);
123 if (invalidateCursor
)
127 void Renderer_vga::Blit(int x
, int y
, char image
[], int imageWidth
,
128 int imageHeight
, int imageBytesPerRow
)
131 bool invalidateCursor
= false;
132 if (Rect(x
, y
, x
+ imageWidth
, y
+ imageHeight
).Intersects(Rect(fCursorX
,
133 fCursorY
, fCursorX
+ 16, fCursorY
+ 16))) {
134 invalidateCursor
= true;
138 Renderer_8bpp::Blit(x
, y
, image
, imageWidth
, imageHeight
, imageBytesPerRow
);
139 if (invalidateCursor
)
143 void Renderer_vga::StretchBlit(const Rect
&imageRect
, const Rect
&displayRect
, char image
[],
144 int imageBytesPerRow
)
147 bool invalidateCursor
= false;
148 if (displayRect
.Intersects(Rect(fCursorX
, fCursorY
, fCursorX
+ 16,
150 invalidateCursor
= true;
154 Renderer_8bpp::StretchBlit(imageRect
, displayRect
, image
, imageBytesPerRow
);
156 if (invalidateCursor
)
160 void Renderer_vga::CopyRect(const Rect
&source
, const Rect
&dest
)
162 bool invalidateCursor
= false;
163 Rect
cursorRect(fCursorX
, fCursorY
, fCursorX
+ 16, fCursorY
+ 16);
164 if (cursorRect
.Intersects(source
) || cursorRect
.Intersects(dest
)) {
165 invalidateCursor
= true;
169 Renderer_8bpp::CopyRect(source
, dest
);
170 if (invalidateCursor
)
174 void Renderer_vga::SetCursorPosition(int x
, int y
)
182 void Renderer_vga::EraseCursor()
184 char *screen_ptr
= BufferBaseAddress() + fCursorX
+ fCursorY
* BufferBytesPerRow();
185 char *saveBackground
= fSavedBackground
;
186 int cursorDisplayWidth
= MIN(16, BufferBytesPerRow() - fCursorX
);
187 int cursorDisplayHeight
= MIN(16, BufferHeight() - fCursorY
);
188 int stride
= BufferBytesPerRow() - cursorDisplayWidth
;
190 for (int y
= 0; y
< cursorDisplayHeight
; y
++) {
191 for (int x
= 0; x
< cursorDisplayWidth
; x
++) {
192 if ((unsigned char) *saveBackground
!= 0xff)
193 *screen_ptr
= *saveBackground
;
199 screen_ptr
+= stride
;
200 saveBackground
+= 16 - cursorDisplayWidth
;
204 void Renderer_vga::DrawCursor()
206 char *screen_ptr
= BufferBaseAddress() + fCursorX
+ fCursorY
* BufferBytesPerRow();
207 char *cursorImage
= (char *) kCursorBits
;
208 char *saveBackground
= fSavedBackground
;
209 int cursorDisplayWidth
= MIN(16, BufferBytesPerRow() - fCursorX
);
210 int cursorDisplayHeight
= MIN(16, BufferHeight() - fCursorY
);
211 int stride
= BufferBytesPerRow() - cursorDisplayWidth
;
213 for (int y
= 0; y
< cursorDisplayHeight
; y
++) {
214 for (int x
= 0; x
< cursorDisplayWidth
; x
++) {
215 if ((unsigned char) *cursorImage
!= 0xff) {
216 *saveBackground
= *screen_ptr
;
217 *screen_ptr
= *cursorImage
;
219 *saveBackground
= 0xff;
226 screen_ptr
+= stride
;
227 cursorImage
+= 16 - cursorDisplayWidth
;
228 saveBackground
+= 16 - cursorDisplayWidth
;