38 #include "freertos/FreeRTOS.h" 39 #include "freertos/queue.h" 40 #include "freertos/task.h" 56 enum PrimitiveCmd : uint8_t {
231 RGB888(uint8_t red, uint8_t green, uint8_t blue) :
R(red),
G(green),
B(blue) { }
232 } __attribute__ ((packed));
235 inline bool operator==(RGB888
const& lhs, RGB888
const& rhs)
237 return lhs.R == rhs.R && lhs.G == rhs.G && lhs.B == rhs.B;
241 inline bool operator!=(RGB888
const& lhs, RGB888
const& rhs)
243 return lhs.R != rhs.R || lhs.G != rhs.G || lhs.B == rhs.B;
260 RGBA8888(
int red,
int green,
int blue,
int alpha) :
R(red),
G(green),
B(blue),
A(alpha) { }
277 RGB222(uint8_t red, uint8_t green, uint8_t blue) :
R(red),
G(green),
B(blue) { }
278 RGB222(RGB888
const & value);
280 static bool lowBitOnly;
284 inline bool operator==(RGB222
const& lhs, RGB222
const& rhs)
286 return lhs.R == rhs.R && lhs.G == rhs.G && lhs.B == rhs.B;
290 inline bool operator!=(RGB222
const& lhs, RGB222
const& rhs)
292 return lhs.R != rhs.R || lhs.G != rhs.G || lhs.B == rhs.B;
307 RGBA2222(
int red,
int green,
int blue,
int alpha) :
R(red),
G(green),
B(blue),
A(alpha) { }
315 uint8_t RGB888toPackedRGB222(RGB888
const & rgb);
331 Glyph(
int X_,
int Y_,
int width_,
int height_, uint8_t
const * data_) :
X(X_),
Y(Y_),
width(width_),
height(height_),
data(data_) { }
332 } __attribute__ ((packed));
374 } __attribute__ ((packed));
384 #define GLYPHMAP_INDEX_BIT 0 385 #define GLYPHMAP_BGCOLOR_BIT 8 386 #define GLYPHMAP_FGCOLOR_BIT 12 387 #define GLYPHMAP_OPTIONS_BIT 16 388 #define GLYPHMAP_ITEM_MAKE(index, bgColor, fgColor, options) (((uint32_t)(index) << GLYPHMAP_INDEX_BIT) | ((uint32_t)(bgColor) << GLYPHMAP_BGCOLOR_BIT) | ((uint32_t)(fgColor) << GLYPHMAP_FGCOLOR_BIT) | ((uint32_t)((options).value) << GLYPHMAP_OPTIONS_BIT)) 390 inline uint8_t glyphMapItem_getIndex(uint32_t
const volatile * mapItem) {
return *mapItem >> GLYPHMAP_INDEX_BIT & 0xFF; }
391 inline uint8_t glyphMapItem_getIndex(uint32_t
const & mapItem) {
return mapItem >> GLYPHMAP_INDEX_BIT & 0xFF; }
393 inline Color glyphMapItem_getBGColor(uint32_t
const volatile * mapItem) {
return (
Color)(*mapItem >> GLYPHMAP_BGCOLOR_BIT & 0x0F); }
394 inline Color glyphMapItem_getBGColor(uint32_t
const & mapItem) {
return (
Color)(mapItem >> GLYPHMAP_BGCOLOR_BIT & 0x0F); }
396 inline Color glyphMapItem_getFGColor(uint32_t
const volatile * mapItem) {
return (
Color)(*mapItem >> GLYPHMAP_FGCOLOR_BIT & 0x0F); }
397 inline Color glyphMapItem_getFGColor(uint32_t
const & mapItem) {
return (
Color)(mapItem >> GLYPHMAP_FGCOLOR_BIT & 0x0F); }
399 inline GlyphOptions glyphMapItem_getOptions(uint32_t
const volatile * mapItem) {
return (GlyphOptions){.value = (uint16_t)(*mapItem >> GLYPHMAP_OPTIONS_BIT & 0xFFFF)}; }
400 inline GlyphOptions glyphMapItem_getOptions(uint32_t
const & mapItem) {
return (GlyphOptions){.value = (uint16_t)(mapItem >> GLYPHMAP_OPTIONS_BIT & 0xFFFF)}; }
402 inline void glyphMapItem_setOptions(uint32_t
volatile * mapItem, GlyphOptions
const & options) { *mapItem = (*mapItem & ~((uint32_t)0xFFFF << GLYPHMAP_OPTIONS_BIT)) | ((uint32_t)(options.value) << GLYPHMAP_OPTIONS_BIT); }
404 struct GlyphsBuffer {
406 int16_t glyphsHeight;
407 uint8_t
const * glyphsData;
414 struct GlyphsBufferRenderInfo {
417 GlyphsBuffer
const * glyphsBuffer;
419 GlyphsBufferRenderInfo(
int itemX_,
int itemY_, GlyphsBuffer
const * glyphsBuffer_) : itemX(itemX_), itemY(itemY_), glyphsBuffer(glyphsBuffer_) { }
420 } __attribute__ ((packed));
470 Bitmap(
int width_,
int height_,
void const * data_,
PixelFormat format_,
bool copy =
false);
471 Bitmap(
int width_,
int height_,
void const * data_,
PixelFormat format_,
RGB888 foregroundColor_,
bool copy =
false);
474 void setPixel(
int x,
int y,
int value);
475 void setPixel(
int x,
int y,
RGBA2222 value);
476 void setPixel(
int x,
int y,
RGBA8888 value);
478 int getAlpha(
int x,
int y);
482 void copyFrom(
void const * srcData);
486 struct BitmapDrawingInfo {
489 Bitmap
const * bitmap;
491 BitmapDrawingInfo(
int X_,
int Y_, Bitmap
const * bitmap_) :
X(X_),
Y(Y_), bitmap(bitmap_) { }
492 } __attribute__ ((packed));
531 struct QuadTreeObject;
547 int16_t currentFrame;
550 int16_t savedBackgroundWidth;
551 int16_t savedBackgroundHeight;
552 uint8_t * savedBackground;
553 QuadTreeObject * collisionDetectorObject;
560 uint8_t allowDraw: 1;
565 Bitmap * getFrame() {
return frames ? frames[currentFrame] :
nullptr; }
566 int getFrameIndex() {
return currentFrame; }
567 void nextFrame() { ++currentFrame;
if (currentFrame >= framesCount) currentFrame = 0; }
568 Sprite * setFrame(
int frame) { currentFrame = frame;
return this; }
572 int getWidth() {
return frames[currentFrame]->
width; }
573 int getHeight() {
return frames[currentFrame]->
height; }
574 Sprite * moveBy(
int offsetX,
int offsetY);
575 Sprite * moveBy(
int offsetX,
int offsetY,
int wrapAroundWidth,
int wrapAroundHeight);
576 Sprite * moveTo(
int x,
int y);
581 Point const * points;
584 } __attribute__ ((packed));
595 } __attribute__ ((packed));
601 } __attribute__ ((packed));
613 GlyphOptions glyphOptions;
614 PaintOptions paintOptions;
615 GlyphsBufferRenderInfo glyphsBufferRenderInfo;
616 BitmapDrawingInfo bitmapDrawingInfo;
620 TaskHandle_t notifyTask;
621 } __attribute__ ((packed));
624 Primitive(PrimitiveCmd cmd_) : cmd(cmd_) { }
625 Primitive(PrimitiveCmd cmd_, Rect
const & rect_) : cmd(cmd_), rect(rect_) { }
626 } __attribute__ ((packed));
633 GlyphOptions glyphOptions;
634 PaintOptions paintOptions;
635 Rect scrollingRegion;
638 Rect absClippingRect;
662 virtual void setResolution(
char const * modeline,
int viewPortWidth = -1,
int viewPortHeight = -1,
bool doubleBuffered =
false) = 0;
664 virtual void begin() = 0;
695 int16_t m_screenWidth;
696 int16_t m_screenHeight;
710 virtual int getColumns() = 0;
711 virtual int getRows() = 0;
712 virtual void adjustMapSize(
int * columns,
int * rows) = 0;
713 virtual void setTextMap(uint32_t
const * map,
int rows) = 0;
714 virtual void enableCursor(
bool value) = 0;
715 virtual void setCursorPos(
int row,
int col) = 0;
716 virtual void setCursorForeground(
Color value) = 0;
717 virtual void setCursorBackground(
Color value) = 0;
756 PaintState & paintState() {
return m_paintState; }
758 void addPrimitive(Primitive & primitive);
760 void primitivesExecutionWait();
784 bool backgroundPrimitiveTimeoutEnabled() {
return m_backgroundPrimitiveTimeoutEnabled; }
834 template <
typename T>
889 virtual void readScreen(
Rect const & rect,
RGB888 * destBuf) = 0;
908 virtual void setPixelAt(PixelDesc
const & pixelDesc,
Rect & updateRect) = 0;
910 virtual void absDrawLine(
int X1,
int Y1,
int X2,
int Y2,
RGB888 color) = 0;
912 virtual void rawFillRow(
int y,
int x1,
int x2,
RGB888 color) = 0;
914 virtual void drawEllipse(
Size const & size,
Rect & updateRect) = 0;
916 virtual void clear(
Rect & updateRect) = 0;
918 virtual void VScroll(
int scroll,
Rect & updateRect) = 0;
920 virtual void HScroll(
int scroll,
Rect & updateRect) = 0;
924 virtual void invertRect(
Rect const & rect,
Rect & updateRect) = 0;
926 virtual void swapFGBG(
Rect const & rect,
Rect & updateRect) = 0;
928 virtual void copyRect(
Rect const & source,
Rect & updateRect) = 0;
930 virtual void swapBuffers() = 0;
932 virtual int getBitmapSavePixelSize() = 0;
934 virtual void rawDrawBitmap_Native(
int destX,
int destY,
Bitmap const * bitmap,
int X1,
int Y1,
int XCount,
int YCount) = 0;
936 virtual void rawDrawBitmap_Mask(
int destX,
int destY,
Bitmap const * bitmap,
void * saveBackground,
int X1,
int Y1,
int XCount,
int YCount) = 0;
938 virtual void rawDrawBitmap_RGBA2222(
int destX,
int destY,
Bitmap const * bitmap,
void * saveBackground,
int X1,
int Y1,
int XCount,
int YCount) = 0;
940 virtual void rawDrawBitmap_RGBA8888(
int destX,
int destY,
Bitmap const * bitmap,
void * saveBackground,
int X1,
int Y1,
int XCount,
int YCount) = 0;
944 void execPrimitive(Primitive
const & prim,
Rect & updateRect,
bool insideISR);
946 void updateAbsoluteClippingRect();
948 RGB888 getActualPenColor();
950 RGB888 getActualBrushColor();
952 void lineTo(
Point const & position,
Rect & updateRect);
954 void drawRect(
Rect const & rect,
Rect & updateRect);
956 void drawPath(Path
const & path,
Rect & updateRect);
958 void absDrawThickLine(
int X1,
int Y1,
int X2,
int Y2,
int penWidth,
RGB888 const & color);
960 void fillRect(
Rect const & rect,
RGB888 const & color,
Rect & updateRect);
962 void fillEllipse(
int centerX,
int centerY,
Size const & size,
RGB888 const & color,
Rect & updateRect);
964 void fillPath(Path
const & path,
RGB888 const & color,
Rect & updateRect);
966 void renderGlyphsBuffer(GlyphsBufferRenderInfo
const & glyphsBufferRenderInfo,
Rect & updateRect);
970 Sprite * getSprite(
int index);
972 int spritesCount() {
return m_spritesCount; }
974 void hideSprites(
Rect & updateRect);
976 void showSprites(
Rect & updateRect);
978 void drawBitmap(BitmapDrawingInfo
const & bitmapDrawingInfo,
Rect & updateRect);
980 void absDrawBitmap(
int destX,
int destY,
Bitmap const * bitmap,
void * saveBackground,
bool ignoreClippingRect);
982 void setDoubleBuffered(
bool value);
984 bool getPrimitive(Primitive * primitive,
int timeOutMS = 0);
986 bool getPrimitiveISR(Primitive * primitive);
988 void waitForPrimitives();
990 Sprite * mouseCursor() {
return &m_mouseCursor; }
992 void resetPaintState();
996 void primitiveReplaceDynamicBuffers(Primitive & primitive);
999 PaintState m_paintState;
1001 volatile bool m_doubleBuffered;
1002 volatile QueueHandle_t m_execQueue;
1004 bool m_backgroundPrimitiveExecutionEnabled;
1005 volatile bool m_backgroundPrimitiveTimeoutEnabled;
1010 bool m_spritesHidden;
1013 Sprite m_mouseCursor;
1014 int16_t m_mouseHotspotX;
1015 int16_t m_mouseHotspotY;
1018 LightMemoryPool m_primDynMemPool;
1030 class GenericBitmappedDisplayController :
public BitmappedDisplayController {
1035 template <
typename TPreparePixel,
typename TRawSetPixel>
1036 void genericSetPixelAt(PixelDesc
const & pixelDesc, Rect & updateRect, TPreparePixel preparePixel, TRawSetPixel rawSetPixel)
1038 const int x = pixelDesc.pos.X + paintState().origin.X;
1039 const int y = pixelDesc.pos.Y + paintState().origin.Y;
1041 const int clipX1 = paintState().absClippingRect.X1;
1042 const int clipY1 = paintState().absClippingRect.Y1;
1043 const int clipX2 = paintState().absClippingRect.X2;
1044 const int clipY2 = paintState().absClippingRect.Y2;
1046 if (x >= clipX1 && x <= clipX2 && y >= clipY1 && y <= clipY2) {
1047 updateRect = updateRect.merge(Rect(x, y, x, y));
1048 hideSprites(updateRect);
1049 rawSetPixel(x, y, preparePixel(pixelDesc.color));
1056 template <
typename TPreparePixel,
typename TRawFillRow,
typename TRawInvertRow,
typename TRawSetPixel,
typename TRawInvertPixel>
1057 void genericAbsDrawLine(
int X1,
int Y1,
int X2,
int Y2, RGB888
const & color, TPreparePixel preparePixel, TRawFillRow rawFillRow, TRawInvertRow rawInvertRow, TRawSetPixel rawSetPixel, TRawInvertPixel rawInvertPixel)
1059 if (paintState().penWidth > 1) {
1060 absDrawThickLine(
X1,
Y1,
X2,
Y2, paintState().penWidth, color);
1063 auto pattern = preparePixel(color);
1066 if (
Y1 < paintState().absClippingRect.Y1 ||
Y1 > paintState().absClippingRect.Y2)
1070 if (
X1 > paintState().absClippingRect.X2 ||
X2 < paintState().absClippingRect.X1)
1072 X1 = iclamp(
X1, paintState().absClippingRect.X1, paintState().absClippingRect.X2);
1073 X2 = iclamp(
X2, paintState().absClippingRect.X1, paintState().absClippingRect.X2);
1074 if (paintState().paintOptions.NOT)
1075 rawInvertRow(
Y1,
X1,
X2);
1077 rawFillRow(
Y1,
X1,
X2, pattern);
1078 }
else if (
X1 ==
X2) {
1080 if (
X1 < paintState().absClippingRect.X1 ||
X1 > paintState().absClippingRect.X2)
1084 if (
Y1 > paintState().absClippingRect.Y2 ||
Y2 < paintState().absClippingRect.Y1)
1086 Y1 = iclamp(
Y1, paintState().absClippingRect.Y1, paintState().absClippingRect.Y2);
1087 Y2 = iclamp(
Y2, paintState().absClippingRect.Y1, paintState().absClippingRect.Y2);
1088 if (paintState().paintOptions.NOT) {
1089 for (
int y =
Y1; y <=
Y2; ++y)
1090 rawInvertPixel(
X1, y);
1092 for (
int y =
Y1; y <=
Y2; ++y)
1093 rawSetPixel(
X1, y, pattern);
1107 if (!clipLine(
X1,
Y1,
X2,
Y2, paintState().absClippingRect,
true))
1109 const int dx = abs(
X2 -
X1);
1110 const int dy = abs(
Y2 -
Y1);
1111 const int sx =
X1 <
X2 ? 1 : -1;
1112 const int sy =
Y1 <
Y2 ? 1 : -1;
1113 int err = (dx > dy ? dx : -dy) / 2;
1115 if (paintState().absClippingRect.contains(
X1,
Y1)) {
1116 if (paintState().paintOptions.NOT)
1117 rawInvertPixel(
X1,
Y1);
1119 rawSetPixel(
X1,
Y1, pattern);
1138 template <
typename TPreparePixel,
typename TRawSetPixel>
1139 void genericDrawEllipse(Size
const & size, Rect & updateRect, TPreparePixel preparePixel, TRawSetPixel rawSetPixel)
1141 auto pattern = preparePixel(getActualPenColor());
1143 const int clipX1 = paintState().absClippingRect.X1;
1144 const int clipY1 = paintState().absClippingRect.Y1;
1145 const int clipX2 = paintState().absClippingRect.X2;
1146 const int clipY2 = paintState().absClippingRect.Y2;
1148 const int centerX = paintState().position.X;
1149 const int centerY = paintState().position.Y;
1151 const int halfWidth = size.width / 2;
1152 const int halfHeight = size.height / 2;
1154 updateRect = updateRect.merge(Rect(centerX - halfWidth, centerY - halfHeight, centerX + halfWidth, centerY + halfHeight));
1155 hideSprites(updateRect);
1157 const int a2 = halfWidth * halfWidth;
1158 const int b2 = halfHeight * halfHeight;
1159 const int crit1 = -(a2 / 4 + halfWidth % 2 + b2);
1160 const int crit2 = -(b2 / 4 + halfHeight % 2 + a2);
1161 const int crit3 = -(b2 / 4 + halfHeight % 2);
1162 const int d2xt = 2 * b2;
1163 const int d2yt = 2 * a2;
1167 int dxt = 2 * b2 * x;
1168 int dyt = -2 * a2 * y;
1170 while (y >= 0 && x <= halfWidth) {
1171 const int col1 = centerX - x;
1172 const int col2 = centerX + x;
1173 const int row1 = centerY - y;
1174 const int row2 = centerY + y;
1176 if (col1 >= clipX1 && col1 <= clipX2) {
1177 if (row1 >= clipY1 && row1 <= clipY2)
1178 rawSetPixel(col1, row1, pattern);
1179 if (row2 >= clipY1 && row2 <= clipY2)
1180 rawSetPixel(col1, row2, pattern);
1182 if (col2 >= clipX1 && col2 <= clipX2) {
1183 if (row1 >= clipY1 && row1 <= clipY2)
1184 rawSetPixel(col2, row1, pattern);
1185 if (row2 >= clipY1 && row2 <= clipY2)
1186 rawSetPixel(col2, row2, pattern);
1189 if (t + b2 * x <= crit1 || t + a2 * y <= crit3) {
1193 }
else if (t - a2 * y > crit2) {
1209 template <
typename TPreparePixel,
typename TRawGetRow,
typename TRawSetPixelInRow>
1210 void genericDrawGlyph(Glyph
const & glyph, GlyphOptions glyphOptions, RGB888 penColor, RGB888 brushColor, Rect & updateRect, TPreparePixel preparePixel, TRawGetRow rawGetRow, TRawSetPixelInRow rawSetPixelInRow)
1212 if (!glyphOptions.bold && !glyphOptions.italic && !glyphOptions.blank && !glyphOptions.underline && !glyphOptions.doubleWidth && glyph.width <= 32)
1213 genericDrawGlyph_light(glyph, glyphOptions, penColor, brushColor, updateRect, preparePixel, rawGetRow, rawSetPixelInRow);
1215 genericDrawGlyph_full(glyph, glyphOptions, penColor, brushColor, updateRect, preparePixel, rawGetRow, rawSetPixelInRow);
1220 template <
typename TPreparePixel,
typename TRawGetRow,
typename TRawSetPixelInRow>
1221 void genericDrawGlyph_full(Glyph
const & glyph, GlyphOptions glyphOptions, RGB888 penColor, RGB888 brushColor, Rect & updateRect, TPreparePixel preparePixel, TRawGetRow rawGetRow, TRawSetPixelInRow rawSetPixelInRow)
1223 const int clipX1 = paintState().absClippingRect.X1;
1224 const int clipY1 = paintState().absClippingRect.Y1;
1225 const int clipX2 = paintState().absClippingRect.X2;
1226 const int clipY2 = paintState().absClippingRect.Y2;
1228 const int origX = paintState().origin.X;
1229 const int origY = paintState().origin.Y;
1231 const int glyphX = glyph.X + origX;
1232 const int glyphY = glyph.Y + origY;
1234 if (glyphX > clipX2 || glyphY > clipY2)
1237 int16_t glyphWidth = glyph.width;
1238 int16_t glyphHeight = glyph.height;
1239 uint8_t
const * glyphData = glyph.data;
1240 int16_t glyphWidthByte = (glyphWidth + 7) / 8;
1241 int16_t glyphSize = glyphHeight * glyphWidthByte;
1244 bool bold = glyphOptions.bold;
1245 bool italic = glyphOptions.italic;
1246 bool blank = glyphOptions.blank;
1247 bool underline = glyphOptions.underline;
1253 uint8_t * newGlyphData = (uint8_t*) alloca(glyphSize);
1255 int offset = (
doubleWidth == 2 ? 0 : (glyphHeight >> 1));
1256 for (
int y = 0; y < glyphHeight ; ++y)
1257 for (
int x = 0; x < glyphWidthByte; ++x)
1258 newGlyphData[x + y * glyphWidthByte] = glyphData[x + (offset + (y >> 1)) * glyphWidthByte];
1259 glyphData = newGlyphData;
1263 int skewAdder = 0, skewH1 = 0, skewH2 = 0;
1266 skewH1 = glyphHeight / 3;
1267 skewH2 = skewH1 * 2;
1271 int16_t XCount = glyphWidth;
1272 int16_t destX = glyphX;
1274 if (destX < clipX1) {
1278 if (
X1 >= glyphWidth)
1281 if (destX + XCount + skewAdder > clipX2 + 1)
1282 XCount = clipX2 + 1 - destX - skewAdder;
1283 if (
X1 + XCount > glyphWidth)
1284 XCount = glyphWidth -
X1;
1287 int16_t YCount = glyphHeight;
1290 if (destY < clipY1) {
1291 Y1 = clipY1 - destY;
1294 if (
Y1 >= glyphHeight)
1297 if (destY + YCount > clipY2 + 1)
1298 YCount = clipY2 + 1 - destY;
1299 if (
Y1 + YCount > glyphHeight)
1300 YCount = glyphHeight -
Y1;
1302 updateRect = updateRect.merge(Rect(destX, destY, destX + XCount + skewAdder - 1, destY + YCount - 1));
1303 hideSprites(updateRect);
1305 if (glyphOptions.invert ^ paintState().paintOptions.swapFGBG)
1306 tswap(penColor, brushColor);
1309 if (glyphOptions.reduceLuminosity) {
1310 if (penColor.R > 128) penColor.R = 128;
1311 if (penColor.G > 128) penColor.G = 128;
1312 if (penColor.B > 128) penColor.B = 128;
1315 auto penPattern = preparePixel(penColor);
1316 auto brushPattern = preparePixel(brushColor);
1317 auto boldPattern =
bold ? preparePixel(RGB888(penColor.R / 2 + 1,
1319 penColor.B / 2 + 1))
1320 : preparePixel(RGB888(0, 0, 0));
1322 for (
int y =
Y1; y <
Y1 + YCount; ++y, ++destY) {
1325 bool prevSet =
false;
1327 auto dstrow = rawGetRow(destY);
1328 auto srcrow = glyphData + y * glyphWidthByte;
1330 if (
underline && y == glyphHeight - FABGLIB_UNDERLINE_POSITION - 1) {
1332 for (
int x =
X1, adestX = destX + skewAdder; x <
X1 + XCount && adestX <= clipX2; ++x, ++adestX) {
1333 rawSetPixelInRow(dstrow, adestX,
blank ? brushPattern : penPattern);
1336 if (adestX > clipX2)
1338 rawSetPixelInRow(dstrow, adestX,
blank ? brushPattern : penPattern);
1344 for (
int x =
X1, adestX = destX + skewAdder; x <
X1 + XCount && adestX <= clipX2; ++x, ++adestX) {
1345 if ((srcrow[x >> 3] << (x & 7)) & 0x80 && !
blank) {
1346 rawSetPixelInRow(dstrow, adestX, penPattern);
1348 }
else if (
bold && prevSet) {
1349 rawSetPixelInRow(dstrow, adestX, boldPattern);
1352 rawSetPixelInRow(dstrow, adestX, brushPattern);
1359 if (adestX > clipX2)
1362 rawSetPixelInRow(dstrow, adestX, prevSet ? penPattern : brushPattern);
1364 rawSetPixelInRow(dstrow, adestX, penPattern);
1370 if (
italic && (y == skewH1 || y == skewH2))
1384 template <
typename TPreparePixel,
typename TRawGetRow,
typename TRawSetPixelInRow>
1385 void genericDrawGlyph_light(Glyph
const & glyph, GlyphOptions glyphOptions, RGB888 penColor, RGB888 brushColor, Rect & updateRect, TPreparePixel preparePixel, TRawGetRow rawGetRow, TRawSetPixelInRow rawSetPixelInRow)
1387 const int clipX1 = paintState().absClippingRect.X1;
1388 const int clipY1 = paintState().absClippingRect.Y1;
1389 const int clipX2 = paintState().absClippingRect.X2;
1390 const int clipY2 = paintState().absClippingRect.Y2;
1392 const int origX = paintState().origin.X;
1393 const int origY = paintState().origin.Y;
1395 const int glyphX = glyph.X + origX;
1396 const int glyphY = glyph.Y + origY;
1398 if (glyphX > clipX2 || glyphY > clipY2)
1401 int16_t glyphWidth = glyph.width;
1402 int16_t glyphHeight = glyph.height;
1403 uint8_t
const * glyphData = glyph.data;
1404 int16_t glyphWidthByte = (glyphWidth + 7) / 8;
1407 int16_t XCount = glyphWidth;
1408 int16_t destX = glyphX;
1411 int16_t YCount = glyphHeight;
1414 if (destX < clipX1) {
1415 X1 = clipX1 - destX;
1418 if (
X1 >= glyphWidth)
1421 if (destX + XCount > clipX2 + 1)
1422 XCount = clipX2 + 1 - destX;
1423 if (
X1 + XCount > glyphWidth)
1424 XCount = glyphWidth -
X1;
1426 if (destY < clipY1) {
1427 Y1 = clipY1 - destY;
1430 if (
Y1 >= glyphHeight)
1433 if (destY + YCount > clipY2 + 1)
1434 YCount = clipY2 + 1 - destY;
1435 if (
Y1 + YCount > glyphHeight)
1436 YCount = glyphHeight -
Y1;
1438 updateRect = updateRect.merge(Rect(destX, destY, destX + XCount - 1, destY + YCount - 1));
1439 hideSprites(updateRect);
1441 if (glyphOptions.invert ^ paintState().paintOptions.swapFGBG)
1442 tswap(penColor, brushColor);
1445 if (glyphOptions.reduceLuminosity) {
1446 if (penColor.R > 128) penColor.R = 128;
1447 if (penColor.G > 128) penColor.G = 128;
1448 if (penColor.B > 128) penColor.B = 128;
1453 auto penPattern = preparePixel(penColor);
1454 auto brushPattern = preparePixel(brushColor);
1456 for (
int y =
Y1; y <
Y1 + YCount; ++y, ++destY) {
1457 auto dstrow = rawGetRow(destY);
1458 uint8_t
const * srcrow = glyphData + y * glyphWidthByte;
1460 uint32_t src = (srcrow[0] << 24) | (srcrow[1] << 16) | (srcrow[2] << 8) | (srcrow[3]);
1464 for (
int x =
X1, adestX = destX; x <
X1 + XCount; ++x, ++adestX, src <<= 1)
1465 rawSetPixelInRow(dstrow, adestX, src & 0x80000000 ? penPattern : brushPattern);
1468 for (
int x =
X1, adestX = destX; x <
X1 + XCount; ++x, ++adestX, src <<= 1)
1469 if (src & 0x80000000)
1470 rawSetPixelInRow(dstrow, adestX, penPattern);
1476 template <
typename TRawInvertRow>
1477 void genericInvertRect(Rect
const & rect, Rect & updateRect, TRawInvertRow rawInvertRow)
1479 const int origX = paintState().origin.X;
1480 const int origY = paintState().origin.Y;
1482 const int clipX1 = paintState().absClippingRect.X1;
1483 const int clipY1 = paintState().absClippingRect.Y1;
1484 const int clipX2 = paintState().absClippingRect.X2;
1485 const int clipY2 = paintState().absClippingRect.Y2;
1487 const int x1 = iclamp(rect.X1 + origX, clipX1, clipX2);
1488 const int y1 = iclamp(rect.Y1 + origY, clipY1, clipY2);
1489 const int x2 = iclamp(rect.X2 + origX, clipX1, clipX2);
1490 const int y2 = iclamp(rect.Y2 + origY, clipY1, clipY2);
1492 updateRect = updateRect.merge(Rect(x1, y1, x2, y2));
1493 hideSprites(updateRect);
1495 for (
int y = y1; y <= y2; ++y)
1496 rawInvertRow(y, x1, x2);
1500 template <
typename TPreparePixel,
typename TRawGetRow,
typename TRawGetPixelInRow,
typename TRawSetPixelInRow>
1501 void genericSwapFGBG(Rect
const & rect, Rect & updateRect, TPreparePixel preparePixel, TRawGetRow rawGetRow, TRawGetPixelInRow rawGetPixelInRow, TRawSetPixelInRow rawSetPixelInRow)
1503 auto penPattern = preparePixel(paintState().penColor);
1504 auto brushPattern = preparePixel(paintState().brushColor);
1506 int origX = paintState().origin.X;
1507 int origY = paintState().origin.Y;
1509 const int clipX1 = paintState().absClippingRect.X1;
1510 const int clipY1 = paintState().absClippingRect.Y1;
1511 const int clipX2 = paintState().absClippingRect.X2;
1512 const int clipY2 = paintState().absClippingRect.Y2;
1514 const int x1 = iclamp(rect.X1 + origX, clipX1, clipX2);
1515 const int y1 = iclamp(rect.Y1 + origY, clipY1, clipY2);
1516 const int x2 = iclamp(rect.X2 + origX, clipX1, clipX2);
1517 const int y2 = iclamp(rect.Y2 + origY, clipY1, clipY2);
1519 updateRect = updateRect.merge(Rect(x1, y1, x2, y2));
1520 hideSprites(updateRect);
1522 for (
int y = y1; y <= y2; ++y) {
1523 auto row = rawGetRow(y);
1524 for (
int x = x1; x <= x2; ++x) {
1525 auto px = rawGetPixelInRow(row, x);
1526 if (px == penPattern)
1527 rawSetPixelInRow(row, x, brushPattern);
1528 else if (px == brushPattern)
1529 rawSetPixelInRow(row, x, penPattern);
1535 template <
typename TRawGetRow,
typename TRawGetPixelInRow,
typename TRawSetPixelInRow>
1536 void genericCopyRect(Rect
const & source, Rect & updateRect, TRawGetRow rawGetRow, TRawGetPixelInRow rawGetPixelInRow, TRawSetPixelInRow rawSetPixelInRow)
1538 const int clipX1 = paintState().absClippingRect.X1;
1539 const int clipY1 = paintState().absClippingRect.Y1;
1540 const int clipX2 = paintState().absClippingRect.X2;
1541 const int clipY2 = paintState().absClippingRect.Y2;
1543 int origX = paintState().origin.X;
1544 int origY = paintState().origin.Y;
1546 int srcX = source.X1 + origX;
1547 int srcY = source.Y1 + origY;
1548 int width = source.X2 - source.X1 + 1;
1549 int height = source.Y2 - source.Y1 + 1;
1550 int destX = paintState().position.X;
1551 int destY = paintState().position.Y;
1552 int deltaX = destX - srcX;
1553 int deltaY = destY - srcY;
1555 int incX = deltaX < 0 ? 1 : -1;
1556 int incY = deltaY < 0 ? 1 : -1;
1558 int startX = deltaX < 0 ? destX : destX +
width - 1;
1559 int startY = deltaY < 0 ? destY : destY +
height - 1;
1561 updateRect = updateRect.merge(Rect(srcX, srcY, srcX +
width - 1, srcY +
height - 1));
1562 updateRect = updateRect.merge(Rect(destX, destY, destX +
width - 1, destY +
height - 1));
1563 hideSprites(updateRect);
1565 for (
int y = startY, i = 0; i <
height; y += incY, ++i) {
1566 if (y >= clipY1 && y <= clipY2) {
1567 auto srcRow = rawGetRow(y - deltaY);
1568 auto dstRow = rawGetRow(y);
1569 for (
int x = startX, j = 0; j <
width; x += incX, ++j) {
1570 if (x >= clipX1 && x <= clipX2)
1571 rawSetPixelInRow(dstRow, x, rawGetPixelInRow(srcRow, x - deltaX));
1578 template <
typename TRawGetRow,
typename TRawSetPixelInRow,
typename TDataType>
1579 void genericRawDrawBitmap_Native(
int destX,
int destY, TDataType *
data,
int width,
int X1,
int Y1,
int XCount,
int YCount,
1580 TRawGetRow rawGetRow, TRawSetPixelInRow rawSetPixelInRow)
1582 const int yEnd =
Y1 + YCount;
1583 const int xEnd =
X1 + XCount;
1584 for (
int y =
Y1; y < yEnd; ++y, ++destY) {
1585 auto dstrow = rawGetRow(destY);
1587 for (
int x =
X1, adestX = destX; x < xEnd; ++x, ++adestX, ++src)
1588 rawSetPixelInRow(dstrow, adestX, *src);
1594 template <
typename TRawGetRow,
typename TRawGetPixelInRow,
typename TRawSetPixelInRow,
typename TBackground>
1595 void genericRawDrawBitmap_Mask(
int destX,
int destY, Bitmap
const * bitmap, TBackground * saveBackground,
int X1,
int Y1,
int XCount,
int YCount,
1596 TRawGetRow rawGetRow, TRawGetPixelInRow rawGetPixelInRow, TRawSetPixelInRow rawSetPixelInRow)
1598 const int width = bitmap->width;
1599 const int yEnd =
Y1 + YCount;
1600 const int xEnd =
X1 + XCount;
1601 auto data = bitmap->data;
1602 const int rowlen = (bitmap->width + 7) / 8;
1604 if (saveBackground) {
1607 for (
int y =
Y1; y < yEnd; ++y, ++destY) {
1608 auto dstrow = rawGetRow(destY);
1609 auto savePx = saveBackground + y *
width +
X1;
1610 auto src =
data + y * rowlen;
1611 for (
int x =
X1, adestX = destX; x < xEnd; ++x, ++adestX, ++savePx) {
1612 *savePx = rawGetPixelInRow(dstrow, adestX);
1613 if ((src[x >> 3] << (x & 7)) & 0x80)
1614 rawSetPixelInRow(dstrow, adestX);
1621 for (
int y =
Y1; y < yEnd; ++y, ++destY) {
1622 auto dstrow = rawGetRow(destY);
1623 auto src =
data + y * rowlen;
1624 for (
int x =
X1, adestX = destX; x < xEnd; ++x, ++adestX) {
1625 if ((src[x >> 3] << (x & 7)) & 0x80)
1626 rawSetPixelInRow(dstrow, adestX);
1634 template <
typename TRawGetRow,
typename TRawGetPixelInRow,
typename TRawSetPixelInRow,
typename TBackground>
1635 void genericRawDrawBitmap_RGBA2222(
int destX,
int destY, Bitmap
const * bitmap, TBackground * saveBackground,
int X1,
int Y1,
int XCount,
int YCount,
1636 TRawGetRow rawGetRow, TRawGetPixelInRow rawGetPixelInRow, TRawSetPixelInRow rawSetPixelInRow)
1638 const int width = bitmap->width;
1639 const int yEnd =
Y1 + YCount;
1640 const int xEnd =
X1 + XCount;
1641 auto data = bitmap->data;
1643 if (saveBackground) {
1646 for (
int y =
Y1; y < yEnd; ++y, ++destY) {
1647 auto dstrow = rawGetRow(destY);
1648 auto savePx = saveBackground + y *
width +
X1;
1650 for (
int x =
X1, adestX = destX; x < xEnd; ++x, ++adestX, ++savePx, ++src) {
1651 *savePx = rawGetPixelInRow(dstrow, adestX);
1653 rawSetPixelInRow(dstrow, adestX, *src);
1660 for (
int y =
Y1; y < yEnd; ++y, ++destY) {
1661 auto dstrow = rawGetRow(destY);
1663 for (
int x =
X1, adestX = destX; x < xEnd; ++x, ++adestX, ++src) {
1665 rawSetPixelInRow(dstrow, adestX, *src);
1673 template <
typename TRawGetRow,
typename TRawGetPixelInRow,
typename TRawSetPixelInRow,
typename TBackground>
1674 void genericRawDrawBitmap_RGBA8888(
int destX,
int destY, Bitmap
const * bitmap, TBackground * saveBackground,
int X1,
int Y1,
int XCount,
int YCount,
1675 TRawGetRow rawGetRow, TRawGetPixelInRow rawGetPixelInRow, TRawSetPixelInRow rawSetPixelInRow)
1677 const int width = bitmap->width;
1678 const int yEnd =
Y1 + YCount;
1679 const int xEnd =
X1 + XCount;
1682 if (saveBackground) {
1685 for (
int y =
Y1; y < yEnd; ++y, ++destY) {
1686 auto dstrow = rawGetRow(destY);
1687 auto savePx = saveBackground + y *
width +
X1;
1689 for (
int x =
X1, adestX = destX; x < xEnd; ++x, ++adestX, ++savePx, ++src) {
1690 *savePx = rawGetPixelInRow(dstrow, adestX);
1692 rawSetPixelInRow(dstrow, adestX, *src);
1699 for (
int y =
Y1; y < yEnd; ++y, ++destY) {
1700 auto dstrow = rawGetRow(destY);
1702 for (
int x =
X1, adestX = destX; x < xEnd; ++x, ++adestX, ++src) {
1704 rawSetPixelInRow(dstrow, adestX, *src);
1715 template <
typename TRawCopyRow,
typename TRawFillRow>
1716 void genericVScroll(
int scroll, Rect & updateRect,
1717 TRawCopyRow rawCopyRow, TRawFillRow rawFillRow)
1719 hideSprites(updateRect);
1720 RGB888 color = getActualBrushColor();
1721 int Y1 = paintState().scrollingRegion.Y1;
1722 int Y2 = paintState().scrollingRegion.Y2;
1723 int X1 = paintState().scrollingRegion.X1;
1724 int X2 = paintState().scrollingRegion.X2;
1731 for (
int i = 0; i <
height + scroll; ++i) {
1733 rawCopyRow(
X1,
X2, (
Y1 + i - scroll), (
Y1 + i));
1737 rawFillRow(
Y1 + i,
X1,
X2, color);
1739 }
else if (scroll > 0) {
1742 for (
int i =
height - scroll - 1; i >= 0; --i) {
1744 rawCopyRow(
X1,
X2, (
Y1 + i), (
Y1 + i + scroll));
1748 for (
int i = 0; i < scroll; ++i)
1749 rawFillRow(
Y1 + i,
X1,
X2, color);
1758 template <
typename TSwapRowsCopying,
typename TSwapRowsPo
inters,
typename TRawFillRow>
1759 void genericVScroll(
int scroll, Rect & updateRect,
1760 TSwapRowsCopying swapRowsCopying, TSwapRowsPointers swapRowsPointers, TRawFillRow rawFillRow)
1762 hideSprites(updateRect);
1763 RGB888 color = getActualBrushColor();
1764 const int Y1 = paintState().scrollingRegion.Y1;
1765 const int Y2 = paintState().scrollingRegion.Y2;
1766 const int X1 = paintState().scrollingRegion.X1;
1767 const int X2 = paintState().scrollingRegion.X2;
1776 for (
int i = 0; i <
height + scroll; ++i) {
1780 swapRowsCopying(
Y1 + i,
Y1 + i - scroll, 0,
X1 - 1);
1781 if (
X2 < viewPortWidth - 1)
1782 swapRowsCopying(
Y1 + i,
Y1 + i - scroll,
X2 + 1, viewPortWidth - 1);
1785 swapRowsPointers(
Y1 + i,
Y1 + i - scroll);
1790 rawFillRow(
Y1 + i,
X1,
X2, color);
1792 }
else if (scroll > 0) {
1795 for (
int i =
height - scroll - 1; i >= 0; --i) {
1799 swapRowsCopying(
Y1 + i,
Y1 + i + scroll, 0,
X1 - 1);
1800 if (
X2 < viewPortWidth - 1)
1801 swapRowsCopying(
Y1 + i,
Y1 + i + scroll,
X2 + 1, viewPortWidth - 1);
1804 swapRowsPointers(
Y1 + i,
Y1 + i + scroll);
1808 for (
int i = 0; i < scroll; ++i)
1809 rawFillRow(
Y1 + i,
X1,
X2, color);
1819 template <
typename TPreparePixel,
typename TRawGetRow,
typename TRawGetPixelInRow,
typename TRawSetPixelInRow>
1820 void genericHScroll(
int scroll, Rect & updateRect,
1821 TPreparePixel preparePixel, TRawGetRow rawGetRow, TRawGetPixelInRow rawGetPixelInRow, TRawSetPixelInRow rawSetPixelInRow)
1823 hideSprites(updateRect);
1824 auto pattern = preparePixel(getActualBrushColor());
1826 int Y1 = paintState().scrollingRegion.Y1;
1827 int Y2 = paintState().scrollingRegion.Y2;
1828 int X1 = paintState().scrollingRegion.X1;
1829 int X2 = paintState().scrollingRegion.X2;
1833 for (
int y =
Y1; y <=
Y2; ++y) {
1834 auto row = rawGetRow(y);
1835 for (
int x =
X1; x <=
X2 + scroll; ++x) {
1836 auto c = rawGetPixelInRow(row, x - scroll);
1837 rawSetPixelInRow(row, x, c);
1840 for (
int x =
X2 + 1 + scroll; x <=
X2; ++x)
1841 rawSetPixelInRow(row, x, pattern);
1843 }
else if (scroll > 0) {
1845 for (
int y =
Y1; y <=
Y2; ++y) {
1846 auto row = rawGetRow(y);
1847 for (
int x =
X2 - scroll; x >=
X1; --x) {
1848 auto c = rawGetPixelInRow(row, x);
1849 rawSetPixelInRow(row, x + scroll, c);
1852 for (
int x =
X1; x <
X1 + scroll; ++x)
1853 rawSetPixelInRow(row, x, pattern);
Represents a 24 bit RGB color.
void setSprites(T *sprites, int count)
Sets the list of active sprites.
virtual void resumeBackgroundPrimitiveExecution()=0
Resumes drawings after suspendBackgroundPrimitiveExecution().
uint16_t reduceLuminosity
Color
This enum defines named colors.
Represents the base abstract class for bitmapped display controllers.
GlyphOptions & Invert(uint8_t value)
Helper method to set or reset foreground and background swapping.
LineEnds
This enum defines line ends when pen width is greater than 1.
GlyphOptions & DoubleWidth(uint8_t value)
Helper method to set or reset doubleWidth.
GlyphOptions & Italic(bool value)
Helper method to set or reset italic.
int getScreenWidth()
Determines the screen width in pixels.
virtual int getViewPortWidth()=0
Determines horizontal size of the viewport.
virtual int getViewPortHeight()=0
Determines vertical size of the viewport.
PixelFormat
This enum defines a pixel format.
DisplayControllerType controllerType()
Determines the display controller type.
Represents a glyph position, size and binary data.
Represents the coordinate of a point.
void refreshSprites()
Forces the sprites to be updated.
This file contains some utility classes and functions.
int getScreenHeight()
Determines the screen height in pixels.
GlyphOptions & Underline(bool value)
Helper method to set or reset underlined.
NativePixelFormat
This enum defines the display controller native pixel format.
void enableBackgroundPrimitiveExecution(bool value)
Enables or disables drawings inside vertical retracing time.
Represents a 32 bit RGBA color.
virtual DisplayControllerType controllerType()=0
Determines the display controller type.
Specifies various glyph painting options.
CursorName
This enum defines a set of predefined mouse cursors.
void setMouseCursor(Cursor *cursor)
Sets mouse cursor and make it visible.
This file contains FabGL library configuration settings, like number of supported colors...
static int queueSize
Size of display controller primitives queue.
virtual void suspendBackgroundPrimitiveExecution()=0
Suspends drawings.
Represents a bidimensional size.
DisplayControllerType controllerType()
Determines the display controller type.
void setMouseCursorPos(int X, int Y)
Sets mouse cursor position.
void processPrimitives()
Draws immediately all primitives in the queue.
bool isDoubleBuffered()
Determines whether BitmappedDisplayController is on double buffered mode.
Represents an 8 bit ABGR color.
DisplayControllerType
This enum defines types of display controllers.
void removeSprites()
Empties the list of active sprites.
Represents a 6 bit RGB color.
GlyphOptions & Bold(bool value)
Helper method to set or reset bold.
Represents the base abstract class for all display controllers.
Represents the base abstract class for textual display controllers.
GlyphOptions & Blank(uint8_t value)
Helper method to set or reset foreground and background swapping.
void enableBackgroundPrimitiveTimeout(bool value)
Enables or disables execution time limitation inside vertical retracing interrupt.
Specifies general paint options.
virtual NativePixelFormat nativePixelFormat()=0
Represents the native pixel format used by this display.
GlyphOptions & FillBackground(bool value)
Helper method to set or reset fillBackground.