42#include "freertos/FreeRTOS.h"
43#include "freertos/queue.h"
44#include "freertos/task.h"
60enum PrimitiveCmd : uint8_t {
235 RGB888(uint8_t red, uint8_t green, uint8_t blue) :
R(red),
G(green),
B(blue) { }
236} __attribute__ ((packed));
239inline bool operator==(RGB888
const& lhs, RGB888
const& rhs)
241 return lhs.R == rhs.R && lhs.G == rhs.G && lhs.B == rhs.B;
245inline bool operator!=(RGB888
const& lhs, RGB888
const& rhs)
247 return lhs.R != rhs.R || lhs.G != rhs.G || lhs.B == rhs.B;
264 RGBA8888(
int red,
int green,
int blue,
int alpha) :
R(red),
G(green),
B(blue),
A(alpha) { }
281 RGB222(uint8_t red, uint8_t green, uint8_t blue) :
R(red),
G(green),
B(blue) { }
282 RGB222(RGB888
const & value);
284 static bool lowBitOnly;
288inline bool operator==(RGB222
const& lhs, RGB222
const& rhs)
290 return lhs.R == rhs.R && lhs.G == rhs.G && lhs.B == rhs.B;
294inline bool operator!=(RGB222
const& lhs, RGB222
const& rhs)
296 return lhs.R != rhs.R || lhs.G != rhs.G || lhs.B == rhs.B;
311 RGBA2222(
int red,
int green,
int blue,
int alpha) :
R(red),
G(green),
B(blue),
A(alpha) { }
319uint8_t RGB888toPackedRGB222(RGB888
const & rgb);
335 Glyph(
int X_,
int Y_,
int width_,
int height_, uint8_t
const * data_) :
X(X_),
Y(Y_),
width(width_),
height(height_),
data(data_) { }
336} __attribute__ ((packed));
378} __attribute__ ((packed));
388#define GLYPHMAP_INDEX_BIT 0
389#define GLYPHMAP_BGCOLOR_BIT 8
390#define GLYPHMAP_FGCOLOR_BIT 12
391#define GLYPHMAP_OPTIONS_BIT 16
392#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))
394inline uint8_t glyphMapItem_getIndex(uint32_t
const volatile * mapItem) {
return *mapItem >> GLYPHMAP_INDEX_BIT & 0xFF; }
395inline uint8_t glyphMapItem_getIndex(uint32_t
const & mapItem) {
return mapItem >> GLYPHMAP_INDEX_BIT & 0xFF; }
397inline Color glyphMapItem_getBGColor(uint32_t
const volatile * mapItem) {
return (
Color)(*mapItem >> GLYPHMAP_BGCOLOR_BIT & 0x0F); }
398inline Color glyphMapItem_getBGColor(uint32_t
const & mapItem) {
return (
Color)(mapItem >> GLYPHMAP_BGCOLOR_BIT & 0x0F); }
400inline Color glyphMapItem_getFGColor(uint32_t
const volatile * mapItem) {
return (
Color)(*mapItem >> GLYPHMAP_FGCOLOR_BIT & 0x0F); }
401inline Color glyphMapItem_getFGColor(uint32_t
const & mapItem) {
return (
Color)(mapItem >> GLYPHMAP_FGCOLOR_BIT & 0x0F); }
403inline GlyphOptions glyphMapItem_getOptions(uint32_t
const volatile * mapItem) {
return (GlyphOptions){.value = (uint16_t)(*mapItem >> GLYPHMAP_OPTIONS_BIT & 0xFFFF)}; }
404inline GlyphOptions glyphMapItem_getOptions(uint32_t
const & mapItem) {
return (GlyphOptions){.value = (uint16_t)(mapItem >> GLYPHMAP_OPTIONS_BIT & 0xFFFF)}; }
406inline 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); }
410 int16_t glyphsHeight;
411 uint8_t
const * glyphsData;
418struct GlyphsBufferRenderInfo {
421 GlyphsBuffer
const * glyphsBuffer;
423 GlyphsBufferRenderInfo(
int itemX_,
int itemY_, GlyphsBuffer
const * glyphsBuffer_) : itemX(itemX_), itemY(itemY_), glyphsBuffer(glyphsBuffer_) { }
424} __attribute__ ((packed));
474 Bitmap(
int width_,
int height_,
void const * data_,
PixelFormat format_,
bool copy =
false);
475 Bitmap(
int width_,
int height_,
void const * data_,
PixelFormat format_,
RGB888 foregroundColor_,
bool copy =
false);
478 void setPixel(
int x,
int y,
int value);
479 void setPixel(
int x,
int y,
RGBA2222 value);
480 void setPixel(
int x,
int y,
RGBA8888 value);
482 int getAlpha(
int x,
int y);
486 void copyFrom(
void const * srcData);
490struct BitmapDrawingInfo {
493 Bitmap
const * bitmap;
495 BitmapDrawingInfo(
int X_,
int Y_, Bitmap
const * bitmap_) :
X(X_),
Y(Y_), bitmap(bitmap_) { }
496} __attribute__ ((packed));
535struct QuadTreeObject;
551 int16_t currentFrame;
554 int16_t savedBackgroundWidth;
555 int16_t savedBackgroundHeight;
556 uint8_t * savedBackground;
557 QuadTreeObject * collisionDetectorObject;
564 uint8_t allowDraw: 1;
569 Bitmap * getFrame() {
return frames ? frames[currentFrame] :
nullptr; }
570 int getFrameIndex() {
return currentFrame; }
571 void nextFrame() { ++currentFrame;
if (currentFrame >= framesCount) currentFrame = 0; }
572 Sprite * setFrame(
int frame) { currentFrame = frame;
return this; }
576 int getWidth() {
return frames[currentFrame]->
width; }
577 int getHeight() {
return frames[currentFrame]->
height; }
578 Sprite * moveBy(
int offsetX,
int offsetY);
579 Sprite * moveBy(
int offsetX,
int offsetY,
int wrapAroundWidth,
int wrapAroundHeight);
580 Sprite * moveTo(
int x,
int y);
585 Point const * points;
588} __attribute__ ((packed));
599} __attribute__ ((packed));
605} __attribute__ ((packed));
617 GlyphOptions glyphOptions;
618 PaintOptions paintOptions;
619 GlyphsBufferRenderInfo glyphsBufferRenderInfo;
620 BitmapDrawingInfo bitmapDrawingInfo;
624 TaskHandle_t notifyTask;
625 } __attribute__ ((packed));
628 Primitive(PrimitiveCmd cmd_) : cmd(cmd_) { }
629 Primitive(PrimitiveCmd cmd_, Rect
const & rect_) : cmd(cmd_), rect(rect_) { }
630} __attribute__ ((packed));
637 GlyphOptions glyphOptions;
638 PaintOptions paintOptions;
639 Rect scrollingRegion;
642 Rect absClippingRect;
666 virtual void setResolution(
char const * modeline,
int viewPortWidth = -1,
int viewPortHeight = -1,
bool doubleBuffered =
false) = 0;
668 virtual void begin() = 0;
718 int16_t m_screenWidth;
719 int16_t m_screenHeight;
720 volatile int16_t m_viewPortWidth;
721 volatile int16_t m_viewPortHeight;
735 virtual int getColumns() = 0;
736 virtual int getRows() = 0;
737 virtual void adjustMapSize(
int * columns,
int * rows) = 0;
738 virtual void setTextMap(uint32_t
const * map,
int rows) = 0;
739 virtual void enableCursor(
bool value) = 0;
740 virtual void setCursorPos(
int row,
int col) = 0;
741 virtual void setCursorForeground(
Color value) = 0;
742 virtual void setCursorBackground(
Color value) = 0;
743 virtual FontInfo
const * getFont() = 0;
767 PaintState & paintState() {
return m_paintState; }
769 void addPrimitive(Primitive & primitive);
771 void primitivesExecutionWait();
795 bool backgroundPrimitiveTimeoutEnabled() {
return m_backgroundPrimitiveTimeoutEnabled; }
845 template <
typename T>
900 virtual void readScreen(
Rect const & rect,
RGB888 * destBuf) = 0;
919 virtual void setPixelAt(PixelDesc
const & pixelDesc,
Rect & updateRect) = 0;
921 virtual void absDrawLine(
int X1,
int Y1,
int X2,
int Y2,
RGB888 color) = 0;
923 virtual void rawFillRow(
int y,
int x1,
int x2,
RGB888 color) = 0;
925 virtual void drawEllipse(
Size const & size,
Rect & updateRect) = 0;
927 virtual void clear(
Rect & updateRect) = 0;
929 virtual void VScroll(
int scroll,
Rect & updateRect) = 0;
931 virtual void HScroll(
int scroll,
Rect & updateRect) = 0;
935 virtual void invertRect(
Rect const & rect,
Rect & updateRect) = 0;
937 virtual void swapFGBG(
Rect const & rect,
Rect & updateRect) = 0;
939 virtual void copyRect(
Rect const & source,
Rect & updateRect) = 0;
941 virtual void swapBuffers() = 0;
943 virtual int getBitmapSavePixelSize() = 0;
945 virtual void rawDrawBitmap_Native(
int destX,
int destY,
Bitmap const * bitmap,
int X1,
int Y1,
int XCount,
int YCount) = 0;
947 virtual void rawDrawBitmap_Mask(
int destX,
int destY,
Bitmap const * bitmap,
void * saveBackground,
int X1,
int Y1,
int XCount,
int YCount) = 0;
949 virtual void rawDrawBitmap_RGBA2222(
int destX,
int destY,
Bitmap const * bitmap,
void * saveBackground,
int X1,
int Y1,
int XCount,
int YCount) = 0;
951 virtual void rawDrawBitmap_RGBA8888(
int destX,
int destY,
Bitmap const * bitmap,
void * saveBackground,
int X1,
int Y1,
int XCount,
int YCount) = 0;
955 void execPrimitive(Primitive
const & prim,
Rect & updateRect,
bool insideISR);
957 void updateAbsoluteClippingRect();
959 RGB888 getActualPenColor();
961 RGB888 getActualBrushColor();
963 void lineTo(
Point const & position,
Rect & updateRect);
965 void drawRect(
Rect const & rect,
Rect & updateRect);
967 void drawPath(Path
const & path,
Rect & updateRect);
969 void absDrawThickLine(
int X1,
int Y1,
int X2,
int Y2,
int penWidth,
RGB888 const & color);
971 void fillRect(
Rect const & rect,
RGB888 const & color,
Rect & updateRect);
973 void fillEllipse(
int centerX,
int centerY,
Size const & size,
RGB888 const & color,
Rect & updateRect);
975 void fillPath(Path
const & path,
RGB888 const & color,
Rect & updateRect);
977 void renderGlyphsBuffer(GlyphsBufferRenderInfo
const & glyphsBufferRenderInfo,
Rect & updateRect);
981 Sprite * getSprite(
int index);
983 int spritesCount() {
return m_spritesCount; }
985 void hideSprites(
Rect & updateRect);
987 void showSprites(
Rect & updateRect);
989 void drawBitmap(BitmapDrawingInfo
const & bitmapDrawingInfo,
Rect & updateRect);
991 void absDrawBitmap(
int destX,
int destY,
Bitmap const * bitmap,
void * saveBackground,
bool ignoreClippingRect);
993 void setDoubleBuffered(
bool value);
995 bool getPrimitive(Primitive * primitive,
int timeOutMS = 0);
997 bool getPrimitiveISR(Primitive * primitive);
999 void waitForPrimitives();
1001 Sprite * mouseCursor() {
return &m_mouseCursor; }
1003 void resetPaintState();
1007 void primitiveReplaceDynamicBuffers(Primitive & primitive);
1010 PaintState m_paintState;
1012 volatile bool m_doubleBuffered;
1013 volatile QueueHandle_t m_execQueue;
1015 bool m_backgroundPrimitiveExecutionEnabled;
1016 volatile bool m_backgroundPrimitiveTimeoutEnabled;
1021 bool m_spritesHidden;
1024 Sprite m_mouseCursor;
1025 int16_t m_mouseHotspotX;
1026 int16_t m_mouseHotspotY;
1029 LightMemoryPool m_primDynMemPool;
1041class GenericBitmappedDisplayController :
public BitmappedDisplayController {
1046 template <
typename TPreparePixel,
typename TRawSetPixel>
1047 void genericSetPixelAt(PixelDesc
const & pixelDesc, Rect & updateRect, TPreparePixel preparePixel, TRawSetPixel rawSetPixel)
1049 const int x = pixelDesc.pos.X + paintState().origin.X;
1050 const int y = pixelDesc.pos.Y + paintState().origin.Y;
1052 const int clipX1 = paintState().absClippingRect.X1;
1053 const int clipY1 = paintState().absClippingRect.Y1;
1054 const int clipX2 = paintState().absClippingRect.X2;
1055 const int clipY2 = paintState().absClippingRect.Y2;
1057 if (x >= clipX1 && x <= clipX2 && y >= clipY1 && y <= clipY2) {
1058 updateRect = updateRect.merge(Rect(x, y, x, y));
1059 hideSprites(updateRect);
1060 rawSetPixel(x, y, preparePixel(pixelDesc.color));
1067 template <
typename TPreparePixel,
typename TRawFillRow,
typename TRawInvertRow,
typename TRawSetPixel,
typename TRawInvertPixel>
1068 void genericAbsDrawLine(
int X1,
int Y1,
int X2,
int Y2, RGB888
const & color, TPreparePixel preparePixel, TRawFillRow rawFillRow, TRawInvertRow rawInvertRow, TRawSetPixel rawSetPixel, TRawInvertPixel rawInvertPixel)
1070 if (paintState().penWidth > 1) {
1071 absDrawThickLine(
X1,
Y1,
X2,
Y2, paintState().penWidth, color);
1074 auto pattern = preparePixel(color);
1077 if (
Y1 < paintState().absClippingRect.Y1 ||
Y1 > paintState().absClippingRect.Y2)
1081 if (
X1 > paintState().absClippingRect.X2 ||
X2 < paintState().absClippingRect.X1)
1083 X1 = iclamp(
X1, paintState().absClippingRect.X1, paintState().absClippingRect.X2);
1084 X2 = iclamp(
X2, paintState().absClippingRect.X1, paintState().absClippingRect.X2);
1085 if (paintState().paintOptions.NOT)
1086 rawInvertRow(
Y1,
X1,
X2);
1088 rawFillRow(
Y1,
X1,
X2, pattern);
1089 }
else if (
X1 ==
X2) {
1091 if (
X1 < paintState().absClippingRect.X1 ||
X1 > paintState().absClippingRect.X2)
1095 if (
Y1 > paintState().absClippingRect.Y2 ||
Y2 < paintState().absClippingRect.Y1)
1097 Y1 = iclamp(
Y1, paintState().absClippingRect.Y1, paintState().absClippingRect.Y2);
1098 Y2 = iclamp(
Y2, paintState().absClippingRect.Y1, paintState().absClippingRect.Y2);
1099 if (paintState().paintOptions.NOT) {
1100 for (
int y =
Y1; y <=
Y2; ++y)
1101 rawInvertPixel(
X1, y);
1103 for (
int y =
Y1; y <=
Y2; ++y)
1104 rawSetPixel(
X1, y, pattern);
1118 if (!clipLine(
X1,
Y1,
X2,
Y2, paintState().absClippingRect,
true))
1120 const int dx = abs(
X2 -
X1);
1121 const int dy = abs(
Y2 -
Y1);
1122 const int sx =
X1 <
X2 ? 1 : -1;
1123 const int sy =
Y1 <
Y2 ? 1 : -1;
1124 int err = (dx > dy ? dx : -dy) / 2;
1126 if (paintState().absClippingRect.contains(
X1,
Y1)) {
1127 if (paintState().paintOptions.NOT)
1128 rawInvertPixel(
X1,
Y1);
1130 rawSetPixel(
X1,
Y1, pattern);
1149 template <
typename TPreparePixel,
typename TRawSetPixel>
1150 void genericDrawEllipse(Size
const & size, Rect & updateRect, TPreparePixel preparePixel, TRawSetPixel rawSetPixel)
1152 auto pattern = preparePixel(getActualPenColor());
1154 const int clipX1 = paintState().absClippingRect.X1;
1155 const int clipY1 = paintState().absClippingRect.Y1;
1156 const int clipX2 = paintState().absClippingRect.X2;
1157 const int clipY2 = paintState().absClippingRect.Y2;
1159 const int centerX = paintState().position.X;
1160 const int centerY = paintState().position.Y;
1162 const int halfWidth = size.width / 2;
1163 const int halfHeight = size.height / 2;
1165 updateRect = updateRect.merge(Rect(centerX - halfWidth, centerY - halfHeight, centerX + halfWidth, centerY + halfHeight));
1166 hideSprites(updateRect);
1168 const int a2 = halfWidth * halfWidth;
1169 const int b2 = halfHeight * halfHeight;
1170 const int crit1 = -(a2 / 4 + halfWidth % 2 + b2);
1171 const int crit2 = -(b2 / 4 + halfHeight % 2 + a2);
1172 const int crit3 = -(b2 / 4 + halfHeight % 2);
1173 const int d2xt = 2 * b2;
1174 const int d2yt = 2 * a2;
1178 int dxt = 2 * b2 * x;
1179 int dyt = -2 * a2 * y;
1181 while (y >= 0 && x <= halfWidth) {
1182 const int col1 = centerX - x;
1183 const int col2 = centerX + x;
1184 const int row1 = centerY - y;
1185 const int row2 = centerY + y;
1187 if (col1 >= clipX1 && col1 <= clipX2) {
1188 if (row1 >= clipY1 && row1 <= clipY2)
1189 rawSetPixel(col1, row1, pattern);
1190 if (row2 >= clipY1 && row2 <= clipY2)
1191 rawSetPixel(col1, row2, pattern);
1193 if (col2 >= clipX1 && col2 <= clipX2) {
1194 if (row1 >= clipY1 && row1 <= clipY2)
1195 rawSetPixel(col2, row1, pattern);
1196 if (row2 >= clipY1 && row2 <= clipY2)
1197 rawSetPixel(col2, row2, pattern);
1200 if (t + b2 * x <= crit1 || t + a2 * y <= crit3) {
1204 }
else if (t - a2 * y > crit2) {
1220 template <
typename TPreparePixel,
typename TRawGetRow,
typename TRawSetPixelInRow>
1221 void genericDrawGlyph(Glyph
const & glyph, GlyphOptions glyphOptions, RGB888 penColor, RGB888 brushColor, Rect & updateRect, TPreparePixel preparePixel, TRawGetRow rawGetRow, TRawSetPixelInRow rawSetPixelInRow)
1223 if (!glyphOptions.bold && !glyphOptions.italic && !glyphOptions.blank && !glyphOptions.underline && !glyphOptions.doubleWidth && glyph.width <= 32)
1224 genericDrawGlyph_light(glyph, glyphOptions, penColor, brushColor, updateRect, preparePixel, rawGetRow, rawSetPixelInRow);
1226 genericDrawGlyph_full(glyph, glyphOptions, penColor, brushColor, updateRect, preparePixel, rawGetRow, rawSetPixelInRow);
1231 template <
typename TPreparePixel,
typename TRawGetRow,
typename TRawSetPixelInRow>
1232 void genericDrawGlyph_full(Glyph
const & glyph, GlyphOptions glyphOptions, RGB888 penColor, RGB888 brushColor, Rect & updateRect, TPreparePixel preparePixel, TRawGetRow rawGetRow, TRawSetPixelInRow rawSetPixelInRow)
1234 const int clipX1 = paintState().absClippingRect.X1;
1235 const int clipY1 = paintState().absClippingRect.Y1;
1236 const int clipX2 = paintState().absClippingRect.X2;
1237 const int clipY2 = paintState().absClippingRect.Y2;
1239 const int origX = paintState().origin.X;
1240 const int origY = paintState().origin.Y;
1242 const int glyphX = glyph.X + origX;
1243 const int glyphY = glyph.Y + origY;
1245 if (glyphX > clipX2 || glyphY > clipY2)
1248 int16_t glyphWidth = glyph.width;
1249 int16_t glyphHeight = glyph.height;
1250 uint8_t
const * glyphData = glyph.data;
1251 int16_t glyphWidthByte = (glyphWidth + 7) / 8;
1252 int16_t glyphSize = glyphHeight * glyphWidthByte;
1255 bool bold = glyphOptions.bold;
1256 bool italic = glyphOptions.italic;
1257 bool blank = glyphOptions.blank;
1258 bool underline = glyphOptions.underline;
1264 uint8_t * newGlyphData = (uint8_t*) alloca(glyphSize);
1266 int offset = (
doubleWidth == 2 ? 0 : (glyphHeight >> 1));
1267 for (
int y = 0; y < glyphHeight ; ++y)
1268 for (
int x = 0; x < glyphWidthByte; ++x)
1269 newGlyphData[x + y * glyphWidthByte] = glyphData[x + (offset + (y >> 1)) * glyphWidthByte];
1270 glyphData = newGlyphData;
1274 int skewAdder = 0, skewH1 = 0, skewH2 = 0;
1277 skewH1 = glyphHeight / 3;
1278 skewH2 = skewH1 * 2;
1282 int16_t XCount = glyphWidth;
1283 int16_t destX = glyphX;
1285 if (destX < clipX1) {
1289 if (
X1 >= glyphWidth)
1292 if (destX + XCount + skewAdder > clipX2 + 1)
1293 XCount = clipX2 + 1 - destX - skewAdder;
1294 if (
X1 + XCount > glyphWidth)
1295 XCount = glyphWidth -
X1;
1298 int16_t YCount = glyphHeight;
1301 if (destY < clipY1) {
1302 Y1 = clipY1 - destY;
1305 if (
Y1 >= glyphHeight)
1308 if (destY + YCount > clipY2 + 1)
1309 YCount = clipY2 + 1 - destY;
1310 if (
Y1 + YCount > glyphHeight)
1311 YCount = glyphHeight -
Y1;
1313 updateRect = updateRect.merge(Rect(destX, destY, destX + XCount + skewAdder - 1, destY + YCount - 1));
1314 hideSprites(updateRect);
1316 if (glyphOptions.invert ^ paintState().paintOptions.swapFGBG)
1317 tswap(penColor, brushColor);
1320 if (glyphOptions.reduceLuminosity) {
1321 if (penColor.R > 128) penColor.R = 128;
1322 if (penColor.G > 128) penColor.G = 128;
1323 if (penColor.B > 128) penColor.B = 128;
1326 auto penPattern = preparePixel(penColor);
1327 auto brushPattern = preparePixel(brushColor);
1328 auto boldPattern =
bold ? preparePixel(RGB888(penColor.R / 2 + 1,
1330 penColor.B / 2 + 1))
1331 : preparePixel(RGB888(0, 0, 0));
1333 for (
int y =
Y1; y <
Y1 + YCount; ++y, ++destY) {
1336 bool prevSet =
false;
1338 auto dstrow = rawGetRow(destY);
1339 auto srcrow = glyphData + y * glyphWidthByte;
1343 for (
int x =
X1, adestX = destX + skewAdder; x <
X1 + XCount && adestX <= clipX2; ++x, ++adestX) {
1344 rawSetPixelInRow(dstrow, adestX,
blank ? brushPattern : penPattern);
1347 if (adestX > clipX2)
1349 rawSetPixelInRow(dstrow, adestX,
blank ? brushPattern : penPattern);
1355 for (
int x =
X1, adestX = destX + skewAdder; x <
X1 + XCount && adestX <= clipX2; ++x, ++adestX) {
1356 if ((srcrow[x >> 3] << (x & 7)) & 0x80 && !
blank) {
1357 rawSetPixelInRow(dstrow, adestX, penPattern);
1359 }
else if (
bold && prevSet) {
1360 rawSetPixelInRow(dstrow, adestX, boldPattern);
1363 rawSetPixelInRow(dstrow, adestX, brushPattern);
1370 if (adestX > clipX2)
1373 rawSetPixelInRow(dstrow, adestX, prevSet ? penPattern : brushPattern);
1375 rawSetPixelInRow(dstrow, adestX, penPattern);
1381 if (
italic && (y == skewH1 || y == skewH2))
1395 template <
typename TPreparePixel,
typename TRawGetRow,
typename TRawSetPixelInRow>
1396 void genericDrawGlyph_light(Glyph
const & glyph, GlyphOptions glyphOptions, RGB888 penColor, RGB888 brushColor, Rect & updateRect, TPreparePixel preparePixel, TRawGetRow rawGetRow, TRawSetPixelInRow rawSetPixelInRow)
1398 const int clipX1 = paintState().absClippingRect.X1;
1399 const int clipY1 = paintState().absClippingRect.Y1;
1400 const int clipX2 = paintState().absClippingRect.X2;
1401 const int clipY2 = paintState().absClippingRect.Y2;
1403 const int origX = paintState().origin.X;
1404 const int origY = paintState().origin.Y;
1406 const int glyphX = glyph.X + origX;
1407 const int glyphY = glyph.Y + origY;
1409 if (glyphX > clipX2 || glyphY > clipY2)
1412 int16_t glyphWidth = glyph.width;
1413 int16_t glyphHeight = glyph.height;
1414 uint8_t
const * glyphData = glyph.data;
1415 int16_t glyphWidthByte = (glyphWidth + 7) / 8;
1418 int16_t XCount = glyphWidth;
1419 int16_t destX = glyphX;
1422 int16_t YCount = glyphHeight;
1425 if (destX < clipX1) {
1426 X1 = clipX1 - destX;
1429 if (
X1 >= glyphWidth)
1432 if (destX + XCount > clipX2 + 1)
1433 XCount = clipX2 + 1 - destX;
1434 if (
X1 + XCount > glyphWidth)
1435 XCount = glyphWidth -
X1;
1437 if (destY < clipY1) {
1438 Y1 = clipY1 - destY;
1441 if (
Y1 >= glyphHeight)
1444 if (destY + YCount > clipY2 + 1)
1445 YCount = clipY2 + 1 - destY;
1446 if (
Y1 + YCount > glyphHeight)
1447 YCount = glyphHeight -
Y1;
1449 updateRect = updateRect.merge(Rect(destX, destY, destX + XCount - 1, destY + YCount - 1));
1450 hideSprites(updateRect);
1452 if (glyphOptions.invert ^ paintState().paintOptions.swapFGBG)
1453 tswap(penColor, brushColor);
1456 if (glyphOptions.reduceLuminosity) {
1457 if (penColor.R > 128) penColor.R = 128;
1458 if (penColor.G > 128) penColor.G = 128;
1459 if (penColor.B > 128) penColor.B = 128;
1464 auto penPattern = preparePixel(penColor);
1465 auto brushPattern = preparePixel(brushColor);
1467 for (
int y =
Y1; y <
Y1 + YCount; ++y, ++destY) {
1468 auto dstrow = rawGetRow(destY);
1469 uint8_t
const * srcrow = glyphData + y * glyphWidthByte;
1471 uint32_t src = (srcrow[0] << 24) | (srcrow[1] << 16) | (srcrow[2] << 8) | (srcrow[3]);
1475 for (
int x =
X1, adestX = destX; x <
X1 + XCount; ++x, ++adestX, src <<= 1)
1476 rawSetPixelInRow(dstrow, adestX, src & 0x80000000 ? penPattern : brushPattern);
1479 for (
int x =
X1, adestX = destX; x <
X1 + XCount; ++x, ++adestX, src <<= 1)
1480 if (src & 0x80000000)
1481 rawSetPixelInRow(dstrow, adestX, penPattern);
1487 template <
typename TRawInvertRow>
1488 void genericInvertRect(Rect
const & rect, Rect & updateRect, TRawInvertRow rawInvertRow)
1490 const int origX = paintState().origin.X;
1491 const int origY = paintState().origin.Y;
1493 const int clipX1 = paintState().absClippingRect.X1;
1494 const int clipY1 = paintState().absClippingRect.Y1;
1495 const int clipX2 = paintState().absClippingRect.X2;
1496 const int clipY2 = paintState().absClippingRect.Y2;
1498 const int x1 = iclamp(rect.X1 + origX, clipX1, clipX2);
1499 const int y1 = iclamp(rect.Y1 + origY, clipY1, clipY2);
1500 const int x2 = iclamp(rect.X2 + origX, clipX1, clipX2);
1501 const int y2 = iclamp(rect.Y2 + origY, clipY1, clipY2);
1503 updateRect = updateRect.merge(Rect(x1, y1, x2, y2));
1504 hideSprites(updateRect);
1506 for (
int y = y1; y <= y2; ++y)
1507 rawInvertRow(y, x1, x2);
1511 template <
typename TPreparePixel,
typename TRawGetRow,
typename TRawGetPixelInRow,
typename TRawSetPixelInRow>
1512 void genericSwapFGBG(Rect
const & rect, Rect & updateRect, TPreparePixel preparePixel, TRawGetRow rawGetRow, TRawGetPixelInRow rawGetPixelInRow, TRawSetPixelInRow rawSetPixelInRow)
1514 auto penPattern = preparePixel(paintState().penColor);
1515 auto brushPattern = preparePixel(paintState().brushColor);
1517 int origX = paintState().origin.X;
1518 int origY = paintState().origin.Y;
1520 const int clipX1 = paintState().absClippingRect.X1;
1521 const int clipY1 = paintState().absClippingRect.Y1;
1522 const int clipX2 = paintState().absClippingRect.X2;
1523 const int clipY2 = paintState().absClippingRect.Y2;
1525 const int x1 = iclamp(rect.X1 + origX, clipX1, clipX2);
1526 const int y1 = iclamp(rect.Y1 + origY, clipY1, clipY2);
1527 const int x2 = iclamp(rect.X2 + origX, clipX1, clipX2);
1528 const int y2 = iclamp(rect.Y2 + origY, clipY1, clipY2);
1530 updateRect = updateRect.merge(Rect(x1, y1, x2, y2));
1531 hideSprites(updateRect);
1533 for (
int y = y1; y <= y2; ++y) {
1534 auto row = rawGetRow(y);
1535 for (
int x = x1; x <= x2; ++x) {
1536 auto px = rawGetPixelInRow(row, x);
1537 if (px == penPattern)
1538 rawSetPixelInRow(row, x, brushPattern);
1539 else if (px == brushPattern)
1540 rawSetPixelInRow(row, x, penPattern);
1546 template <
typename TRawGetRow,
typename TRawGetPixelInRow,
typename TRawSetPixelInRow>
1547 void genericCopyRect(Rect
const & source, Rect & updateRect, TRawGetRow rawGetRow, TRawGetPixelInRow rawGetPixelInRow, TRawSetPixelInRow rawSetPixelInRow)
1549 const int clipX1 = paintState().absClippingRect.X1;
1550 const int clipY1 = paintState().absClippingRect.Y1;
1551 const int clipX2 = paintState().absClippingRect.X2;
1552 const int clipY2 = paintState().absClippingRect.Y2;
1554 int origX = paintState().origin.X;
1555 int origY = paintState().origin.Y;
1557 int srcX = source.X1 + origX;
1558 int srcY = source.Y1 + origY;
1559 int width = source.X2 - source.X1 + 1;
1560 int height = source.Y2 - source.Y1 + 1;
1561 int destX = paintState().position.X;
1562 int destY = paintState().position.Y;
1563 int deltaX = destX - srcX;
1564 int deltaY = destY - srcY;
1566 int incX = deltaX < 0 ? 1 : -1;
1567 int incY = deltaY < 0 ? 1 : -1;
1569 int startX = deltaX < 0 ? destX : destX +
width - 1;
1570 int startY = deltaY < 0 ? destY : destY +
height - 1;
1572 updateRect = updateRect.merge(Rect(srcX, srcY, srcX +
width - 1, srcY +
height - 1));
1573 updateRect = updateRect.merge(Rect(destX, destY, destX +
width - 1, destY +
height - 1));
1574 hideSprites(updateRect);
1576 for (
int y = startY, i = 0; i <
height; y += incY, ++i) {
1577 if (y >= clipY1 && y <= clipY2) {
1578 auto srcRow = rawGetRow(y - deltaY);
1579 auto dstRow = rawGetRow(y);
1580 for (
int x = startX, j = 0; j <
width; x += incX, ++j) {
1581 if (x >= clipX1 && x <= clipX2)
1582 rawSetPixelInRow(dstRow, x, rawGetPixelInRow(srcRow, x - deltaX));
1589 template <
typename TRawGetRow,
typename TRawSetPixelInRow,
typename TDataType>
1590 void genericRawDrawBitmap_Native(
int destX,
int destY, TDataType *
data,
int width,
int X1,
int Y1,
int XCount,
int YCount,
1591 TRawGetRow rawGetRow, TRawSetPixelInRow rawSetPixelInRow)
1593 const int yEnd =
Y1 + YCount;
1594 const int xEnd =
X1 + XCount;
1595 for (
int y =
Y1; y < yEnd; ++y, ++destY) {
1596 auto dstrow = rawGetRow(destY);
1598 for (
int x =
X1, adestX = destX; x < xEnd; ++x, ++adestX, ++src)
1599 rawSetPixelInRow(dstrow, adestX, *src);
1605 template <
typename TRawGetRow,
typename TRawGetPixelInRow,
typename TRawSetPixelInRow,
typename TBackground>
1606 void genericRawDrawBitmap_Mask(
int destX,
int destY, Bitmap
const * bitmap, TBackground * saveBackground,
int X1,
int Y1,
int XCount,
int YCount,
1607 TRawGetRow rawGetRow, TRawGetPixelInRow rawGetPixelInRow, TRawSetPixelInRow rawSetPixelInRow)
1609 const int width = bitmap->width;
1610 const int yEnd =
Y1 + YCount;
1611 const int xEnd =
X1 + XCount;
1612 auto data = bitmap->data;
1613 const int rowlen = (bitmap->width + 7) / 8;
1615 if (saveBackground) {
1618 for (
int y =
Y1; y < yEnd; ++y, ++destY) {
1619 auto dstrow = rawGetRow(destY);
1620 auto savePx = saveBackground + y *
width +
X1;
1621 auto src =
data + y * rowlen;
1622 for (
int x =
X1, adestX = destX; x < xEnd; ++x, ++adestX, ++savePx) {
1623 *savePx = rawGetPixelInRow(dstrow, adestX);
1624 if ((src[x >> 3] << (x & 7)) & 0x80)
1625 rawSetPixelInRow(dstrow, adestX);
1632 for (
int y =
Y1; y < yEnd; ++y, ++destY) {
1633 auto dstrow = rawGetRow(destY);
1634 auto src =
data + y * rowlen;
1635 for (
int x =
X1, adestX = destX; x < xEnd; ++x, ++adestX) {
1636 if ((src[x >> 3] << (x & 7)) & 0x80)
1637 rawSetPixelInRow(dstrow, adestX);
1645 template <
typename TRawGetRow,
typename TRawGetPixelInRow,
typename TRawSetPixelInRow,
typename TBackground>
1646 void genericRawDrawBitmap_RGBA2222(
int destX,
int destY, Bitmap
const * bitmap, TBackground * saveBackground,
int X1,
int Y1,
int XCount,
int YCount,
1647 TRawGetRow rawGetRow, TRawGetPixelInRow rawGetPixelInRow, TRawSetPixelInRow rawSetPixelInRow)
1649 const int width = bitmap->width;
1650 const int yEnd =
Y1 + YCount;
1651 const int xEnd =
X1 + XCount;
1652 auto data = bitmap->data;
1654 if (saveBackground) {
1657 for (
int y =
Y1; y < yEnd; ++y, ++destY) {
1658 auto dstrow = rawGetRow(destY);
1659 auto savePx = saveBackground + y *
width +
X1;
1661 for (
int x =
X1, adestX = destX; x < xEnd; ++x, ++adestX, ++savePx, ++src) {
1662 *savePx = rawGetPixelInRow(dstrow, adestX);
1664 rawSetPixelInRow(dstrow, adestX, *src);
1671 for (
int y =
Y1; y < yEnd; ++y, ++destY) {
1672 auto dstrow = rawGetRow(destY);
1674 for (
int x =
X1, adestX = destX; x < xEnd; ++x, ++adestX, ++src) {
1676 rawSetPixelInRow(dstrow, adestX, *src);
1684 template <
typename TRawGetRow,
typename TRawGetPixelInRow,
typename TRawSetPixelInRow,
typename TBackground>
1685 void genericRawDrawBitmap_RGBA8888(
int destX,
int destY, Bitmap
const * bitmap, TBackground * saveBackground,
int X1,
int Y1,
int XCount,
int YCount,
1686 TRawGetRow rawGetRow, TRawGetPixelInRow rawGetPixelInRow, TRawSetPixelInRow rawSetPixelInRow)
1688 const int width = bitmap->width;
1689 const int yEnd =
Y1 + YCount;
1690 const int xEnd =
X1 + XCount;
1693 if (saveBackground) {
1696 for (
int y =
Y1; y < yEnd; ++y, ++destY) {
1697 auto dstrow = rawGetRow(destY);
1698 auto savePx = saveBackground + y *
width +
X1;
1700 for (
int x =
X1, adestX = destX; x < xEnd; ++x, ++adestX, ++savePx, ++src) {
1701 *savePx = rawGetPixelInRow(dstrow, adestX);
1703 rawSetPixelInRow(dstrow, adestX, *src);
1710 for (
int y =
Y1; y < yEnd; ++y, ++destY) {
1711 auto dstrow = rawGetRow(destY);
1713 for (
int x =
X1, adestX = destX; x < xEnd; ++x, ++adestX, ++src) {
1715 rawSetPixelInRow(dstrow, adestX, *src);
1726 template <
typename TRawCopyRow,
typename TRawFillRow>
1727 void genericVScroll(
int scroll, Rect & updateRect,
1728 TRawCopyRow rawCopyRow, TRawFillRow rawFillRow)
1730 hideSprites(updateRect);
1731 RGB888 color = getActualBrushColor();
1732 int Y1 = paintState().scrollingRegion.Y1;
1733 int Y2 = paintState().scrollingRegion.Y2;
1734 int X1 = paintState().scrollingRegion.X1;
1735 int X2 = paintState().scrollingRegion.X2;
1742 for (
int i = 0; i <
height + scroll; ++i) {
1744 rawCopyRow(
X1,
X2, (
Y1 + i - scroll), (
Y1 + i));
1748 rawFillRow(
Y1 + i,
X1,
X2, color);
1750 }
else if (scroll > 0) {
1753 for (
int i =
height - scroll - 1; i >= 0; --i) {
1755 rawCopyRow(
X1,
X2, (
Y1 + i), (
Y1 + i + scroll));
1759 for (
int i = 0; i < scroll; ++i)
1760 rawFillRow(
Y1 + i,
X1,
X2, color);
1769 template <
typename TSwapRowsCopying,
typename TSwapRowsPo
inters,
typename TRawFillRow>
1770 void genericVScroll(
int scroll, Rect & updateRect,
1771 TSwapRowsCopying swapRowsCopying, TSwapRowsPointers swapRowsPointers, TRawFillRow rawFillRow)
1773 hideSprites(updateRect);
1774 RGB888 color = getActualBrushColor();
1775 const int Y1 = paintState().scrollingRegion.Y1;
1776 const int Y2 = paintState().scrollingRegion.Y2;
1777 const int X1 = paintState().scrollingRegion.X1;
1778 const int X2 = paintState().scrollingRegion.X2;
1787 for (
int i = 0; i <
height + scroll; ++i) {
1791 swapRowsCopying(
Y1 + i,
Y1 + i - scroll, 0,
X1 - 1);
1792 if (
X2 < viewPortWidth - 1)
1793 swapRowsCopying(
Y1 + i,
Y1 + i - scroll,
X2 + 1, viewPortWidth - 1);
1796 swapRowsPointers(
Y1 + i,
Y1 + i - scroll);
1801 rawFillRow(
Y1 + i,
X1,
X2, color);
1803 }
else if (scroll > 0) {
1806 for (
int i =
height - scroll - 1; i >= 0; --i) {
1810 swapRowsCopying(
Y1 + i,
Y1 + i + scroll, 0,
X1 - 1);
1811 if (
X2 < viewPortWidth - 1)
1812 swapRowsCopying(
Y1 + i,
Y1 + i + scroll,
X2 + 1, viewPortWidth - 1);
1815 swapRowsPointers(
Y1 + i,
Y1 + i + scroll);
1819 for (
int i = 0; i < scroll; ++i)
1820 rawFillRow(
Y1 + i,
X1,
X2, color);
1830 template <
typename TPreparePixel,
typename TRawGetRow,
typename TRawGetPixelInRow,
typename TRawSetPixelInRow>
1831 void genericHScroll(
int scroll, Rect & updateRect,
1832 TPreparePixel preparePixel, TRawGetRow rawGetRow, TRawGetPixelInRow rawGetPixelInRow, TRawSetPixelInRow rawSetPixelInRow)
1834 hideSprites(updateRect);
1835 auto pattern = preparePixel(getActualBrushColor());
1837 int Y1 = paintState().scrollingRegion.Y1;
1838 int Y2 = paintState().scrollingRegion.Y2;
1839 int X1 = paintState().scrollingRegion.X1;
1840 int X2 = paintState().scrollingRegion.X2;
1844 for (
int y =
Y1; y <=
Y2; ++y) {
1845 auto row = rawGetRow(y);
1846 for (
int x =
X1; x <=
X2 + scroll; ++x) {
1847 auto c = rawGetPixelInRow(row, x - scroll);
1848 rawSetPixelInRow(row, x, c);
1851 for (
int x =
X2 + 1 + scroll; x <=
X2; ++x)
1852 rawSetPixelInRow(row, x, pattern);
1854 }
else if (scroll > 0) {
1856 for (
int y =
Y1; y <=
Y2; ++y) {
1857 auto row = rawGetRow(y);
1858 for (
int x =
X2 - scroll; x >=
X1; --x) {
1859 auto c = rawGetPixelInRow(row, x);
1860 rawSetPixelInRow(row, x + scroll, c);
1863 for (
int x =
X1; x <
X1 + scroll; ++x)
1864 rawSetPixelInRow(row, x, pattern);
int getScreenHeight()
Determines the screen height in pixels.
virtual int colorsCount()=0
Determines number of colors this display can provide.
int getViewPortHeight()
Determines vertical size of the viewport.
int getViewPortWidth()
Determines horizontal size of the viewport.
int getScreenWidth()
Determines the screen width in pixels.
virtual DisplayControllerType controllerType()=0
Determines the display controller type.
Represents the base abstract class for all display controllers.
void enableBackgroundPrimitiveTimeout(bool value)
Enables or disables execution time limitation inside vertical retracing interrupt.
DisplayControllerType controllerType()
Determines the display controller type.
bool isDoubleBuffered()
Determines whether BitmappedDisplayController is on double buffered mode.
virtual void suspendBackgroundPrimitiveExecution()=0
Suspends drawings.
virtual void resumeBackgroundPrimitiveExecution()=0
Resumes drawings after suspendBackgroundPrimitiveExecution().
static int queueSize
Size of display controller primitives queue.
void setSprites(T *sprites, int count)
Sets the list of active sprites.
void processPrimitives()
Draws immediately all primitives in the queue.
void setMouseCursor(Cursor *cursor)
Sets mouse cursor and make it visible.
void enableBackgroundPrimitiveExecution(bool value)
Enables or disables drawings inside vertical retracing time.
void removeSprites()
Empties the list of active sprites.
virtual NativePixelFormat nativePixelFormat()=0
Represents the native pixel format used by this display.
void setMouseCursorPos(int X, int Y)
Sets mouse cursor position.
void refreshSprites()
Forces the sprites to be updated.
Represents the base abstract class for bitmapped display controllers.
DisplayControllerType controllerType()
Determines the display controller type.
Represents the base abstract class for textual display controllers.
#define FABGLIB_UNDERLINE_POSITION
This file contains FabGL library configuration settings, like number of supported colors,...
This file contains some utility classes and functions.
NativePixelFormat
This enum defines the display controller native pixel format.
LineEnds
This enum defines line ends when pen width is greater than 1.
Color
This enum defines named colors.
CursorName
This enum defines a set of predefined mouse cursors.
@ CursorPointerSimpleReduced
DisplayControllerType
This enum defines types of display controllers.
PixelFormat
This enum defines a pixel format.
Represents a glyph position, size and binary data.
Specifies general paint options.
Represents the coordinate of a point.
Represents a 6 bit RGB color.
Represents a 24 bit RGB color.
Represents an 8 bit ABGR color.
Represents a 32 bit RGBA color.
Represents a bidimensional size.
GlyphOptions & DoubleWidth(uint8_t value)
Helper method to set or reset doubleWidth.
GlyphOptions & Blank(uint8_t value)
Helper method to set or reset foreground and background swapping.
uint16_t reduceLuminosity
GlyphOptions & FillBackground(bool value)
Helper method to set or reset fillBackground.
GlyphOptions & Italic(bool value)
Helper method to set or reset italic.
GlyphOptions & Bold(bool value)
Helper method to set or reset bold.
GlyphOptions & Underline(bool value)
Helper method to set or reset underlined.
GlyphOptions & Invert(uint8_t value)
Helper method to set or reset foreground and background swapping.
Specifies various glyph painting options.