Renderer_vga.cpp (6886B)
1 #include "Renderer_vga.h" 2 #include "assert.h" 3 4 #define MIN(a, b) ((a) < (b) ? (a) : (b)) 5 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 23 }; 24 25 Renderer_vga::Renderer_vga(char *baseAddress, int width, int height, int bytesPerRow) 26 : Renderer_8bpp(baseAddress, width, height, bytesPerRow) 27 { 28 fCursorX = width / 2; 29 fCursorY = height / 2; 30 DrawCursor(); 31 } 32 33 const unsigned kBottom = 1; 34 const unsigned kTop = 2; 35 const unsigned kLeft = 4; 36 const unsigned kRight = 8; 37 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; \ 44 mask;}) 45 46 inline int vert_intersection(int x1, int y1, int x2, int y2, int x) 47 { 48 return y1 + (y2 - y1) * (x - x1) / (x2 - x1); 49 } 50 51 inline int horz_intersection(int x1, int y1, int x2, int y2, int y) 52 { 53 return x1 + (x2 - x1) * (y - y1) / (y2 - y1); 54 } 55 56 void Renderer_vga::DrawLine(int x1, int y1, int x2, int y2, char color) 57 { 58 Rect cursorRect(fCursorX, fCursorY, fCursorX + 16, fCursorY + 16); 59 bool invalidateCursor = true; 60 61 int clippedX1 = x1; 62 int clippedY1 = y1; 63 int clippedX2 = x2; 64 int clippedY2 = y2; 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; 70 break; 71 } 72 73 unsigned mask = point1mask ? point1mask : point2mask; 74 int x = 0; 75 int y = 0; 76 if (mask & kBottom) { 77 y = cursorRect.bottom; 78 x = horz_intersection(clippedX1, clippedY1, clippedX2, clippedY2, y); 79 } else if (mask & kTop) { 80 y = cursorRect.top; 81 x = horz_intersection(clippedX1, clippedY1, clippedX2, clippedY2, y); 82 } else if (mask & kRight) { 83 x = cursorRect.right; 84 y = vert_intersection(clippedX1, clippedY1, clippedX2, clippedY2, x); 85 } else if (mask & kLeft) { 86 x = cursorRect.left; 87 y = vert_intersection(clippedX1, clippedY1, clippedX2, clippedY2, x); 88 } 89 90 if (point1mask) { 91 // Clip point 1 92 point1mask = clipmask(x, y, cursorRect); 93 clippedX1 = x; 94 clippedY1 = y; 95 } else { 96 // Clip point 2 97 point2mask = clipmask(x, y, cursorRect); 98 clippedX2 = x; 99 clippedY2 = y; 100 } 101 } 102 103 if (invalidateCursor) 104 EraseCursor(); 105 106 Renderer_8bpp::DrawLine(x1, y1, x2, y2, color); 107 108 if (invalidateCursor) 109 DrawCursor(); 110 } 111 112 void Renderer_vga::FillRect(int x1, int y1, int x2, int y2, char color) 113 { 114 115 bool invalidateCursor = false; 116 if (Rect(x1, y1, x2, y2).Intersects(Rect(fCursorX, fCursorY, fCursorX + 16, 117 fCursorY + 16))) { 118 invalidateCursor = true; 119 EraseCursor(); 120 } 121 122 Renderer_8bpp::FillRect(x1, y1, x2, y2, color); 123 if (invalidateCursor) 124 DrawCursor(); 125 } 126 127 void Renderer_vga::Blit(int x, int y, char image[], int imageWidth, 128 int imageHeight, int imageBytesPerRow) 129 { 130 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; 135 EraseCursor(); 136 } 137 138 Renderer_8bpp::Blit(x, y, image, imageWidth, imageHeight, imageBytesPerRow); 139 if (invalidateCursor) 140 DrawCursor(); 141 } 142 143 void Renderer_vga::StretchBlit(const Rect &imageRect, const Rect &displayRect, char image[], 144 int imageBytesPerRow) 145 { 146 147 bool invalidateCursor = false; 148 if (displayRect.Intersects(Rect(fCursorX, fCursorY, fCursorX + 16, 149 fCursorY + 16))) { 150 invalidateCursor = true; 151 EraseCursor(); 152 } 153 154 Renderer_8bpp::StretchBlit(imageRect, displayRect, image, imageBytesPerRow); 155 156 if (invalidateCursor) 157 DrawCursor(); 158 } 159 160 void Renderer_vga::CopyRect(const Rect &source, const Rect &dest) 161 { 162 bool invalidateCursor = false; 163 Rect cursorRect(fCursorX, fCursorY, fCursorX + 16, fCursorY + 16); 164 if (cursorRect.Intersects(source) || cursorRect.Intersects(dest)) { 165 invalidateCursor = true; 166 EraseCursor(); 167 } 168 169 Renderer_8bpp::CopyRect(source, dest); 170 if (invalidateCursor) 171 DrawCursor(); 172 } 173 174 void Renderer_vga::SetCursorPosition(int x, int y) 175 { 176 EraseCursor(); 177 fCursorX = x; 178 fCursorY = y; 179 DrawCursor(); 180 } 181 182 void Renderer_vga::EraseCursor() 183 { 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; 189 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; 194 195 screen_ptr++; 196 saveBackground++; 197 } 198 199 screen_ptr += stride; 200 saveBackground += 16 - cursorDisplayWidth; 201 } 202 } 203 204 void Renderer_vga::DrawCursor() 205 { 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; 212 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; 218 } else 219 *saveBackground = 0xff; 220 221 screen_ptr++; 222 cursorImage++; 223 saveBackground++; 224 } 225 226 screen_ptr += stride; 227 cursorImage += 16 - cursorDisplayWidth; 228 saveBackground += 16 - cursorDisplayWidth; 229 } 230 }