| 1035 | } |
| 1036 | |
| 1037 | void inline OLEDDisplay::drawInternal(int16_t xMove, int16_t yMove, int16_t width, int16_t height, const uint8_t *data, uint16_t offset, uint16_t bytesInData) { |
| 1038 | if (width < 0 || height < 0) return; |
| 1039 | if (yMove + height < 0 || yMove > this->height()) return; |
| 1040 | if (xMove + width < 0 || xMove > this->width()) return; |
| 1041 | |
| 1042 | uint8_t rasterHeight = 1 + ((height - 1) >> 3); // fast ceil(height / 8.0) |
| 1043 | int8_t yOffset = yMove & 7; |
| 1044 | |
| 1045 | bytesInData = bytesInData == 0 ? width * rasterHeight : bytesInData; |
| 1046 | |
| 1047 | int16_t initYMove = yMove; |
| 1048 | int8_t initYOffset = yOffset; |
| 1049 | |
| 1050 | |
| 1051 | for (uint16_t i = 0; i < bytesInData; i++) { |
| 1052 | |
| 1053 | // Reset if next horizontal drawing phase is started. |
| 1054 | if ( i % rasterHeight == 0) { |
| 1055 | yMove = initYMove; |
| 1056 | yOffset = initYOffset; |
| 1057 | } |
| 1058 | |
| 1059 | uint8_t currentByte = pgm_read_byte(data + offset + i); |
| 1060 | |
| 1061 | int16_t xPos = xMove + (i / rasterHeight); |
| 1062 | int16_t yPos = ((yMove >> 3) + (i % rasterHeight)) * this->width(); |
| 1063 | |
| 1064 | // int16_t yScreenPos = yMove + yOffset; |
| 1065 | int16_t dataPos = xPos + yPos; |
| 1066 | |
| 1067 | if (dataPos >= 0 && dataPos < displayBufferSize && |
| 1068 | xPos >= 0 && xPos < this->width() ) { |
| 1069 | |
| 1070 | if (yOffset >= 0) { |
| 1071 | switch (this->color) { |
| 1072 | case WHITE: buffer[dataPos] |= currentByte << yOffset; break; |
| 1073 | case BLACK: buffer[dataPos] &= ~(currentByte << yOffset); break; |
| 1074 | case INVERSE: buffer[dataPos] ^= currentByte << yOffset; break; |
| 1075 | } |
| 1076 | |
| 1077 | if (dataPos < (displayBufferSize - this->width())) { |
| 1078 | switch (this->color) { |
| 1079 | case WHITE: buffer[dataPos + this->width()] |= currentByte >> (8 - yOffset); break; |
| 1080 | case BLACK: buffer[dataPos + this->width()] &= ~(currentByte >> (8 - yOffset)); break; |
| 1081 | case INVERSE: buffer[dataPos + this->width()] ^= currentByte >> (8 - yOffset); break; |
| 1082 | } |
| 1083 | } |
| 1084 | } else { |
| 1085 | // Make new offset position |
| 1086 | yOffset = -yOffset; |
| 1087 | |
| 1088 | switch (this->color) { |
| 1089 | case WHITE: buffer[dataPos] |= currentByte >> yOffset; break; |
| 1090 | case BLACK: buffer[dataPos] &= ~(currentByte >> yOffset); break; |
| 1091 | case INVERSE: buffer[dataPos] ^= currentByte >> yOffset; break; |
| 1092 | } |
| 1093 | |
| 1094 | // Prepare for next iteration by moving one block up |
nothing calls this directly
no test coverage detected