Draw a single bitmap row. 'left' and 'width' do not need to be divisible by 8.
| 190 | |
| 191 | // Draw a single bitmap row. 'left' and 'width' do not need to be divisible by 8. |
| 192 | void MonoLcd::BitmapRow(PixelNumber top, PixelNumber left, PixelNumber width, const uint8_t data[], bool invert) noexcept |
| 193 | { |
| 194 | if (left + width > numCols) |
| 195 | { |
| 196 | width = numCols - left; // avoid overflowing the buffer |
| 197 | } |
| 198 | |
| 199 | if (width != 0 && top < numRows) // avoid possible arithmetic underflow or overflowing the buffer |
| 200 | { |
| 201 | const uint8_t inv = (invert) ? 0xFF : 0; |
| 202 | uint8_t firstColIndex = left/8; // column index of the first byte to write |
| 203 | const uint8_t lastColIndex = (left + width - 1)/8; // column index of the last byte to write |
| 204 | const unsigned int firstDataShift = left % 8; // number of bits in the first byte that we leave alone |
| 205 | uint8_t *_ecv_array p = image + (top * numCols/8) + firstColIndex; |
| 206 | |
| 207 | // Do all bytes except the last one |
| 208 | uint8_t accumulator = *p & (0xFF << (8 - firstDataShift)); // prime the accumulator |
| 209 | while (firstColIndex < lastColIndex) |
| 210 | { |
| 211 | const uint8_t invData = *data ^ inv; |
| 212 | const uint8_t newVal = accumulator | (invData >> firstDataShift); |
| 213 | if (newVal != *p) |
| 214 | { |
| 215 | *p = newVal; |
| 216 | SetPixelDirty(top, 8 * firstColIndex); |
| 217 | } |
| 218 | accumulator = invData << (8 - firstDataShift); |
| 219 | ++p; |
| 220 | ++data; |
| 221 | ++firstColIndex; |
| 222 | } |
| 223 | |
| 224 | // Do the last byte. 'accumulator' contains up to 'firstDataShift' of the most significant bits. |
| 225 | const unsigned int lastDataShift = 7 - ((left + width - 1) % 8); // number of trailing bits in the last byte that we leave alone, 0 to 7 |
| 226 | const uint8_t lastMask = (1u << lastDataShift) - 1; // mask for bits we want to keep; |
| 227 | accumulator |= (*data ^ inv) >> firstDataShift; |
| 228 | accumulator &= ~lastMask; |
| 229 | accumulator |= *p & lastMask; |
| 230 | if (accumulator != *p) |
| 231 | { |
| 232 | *p = accumulator; |
| 233 | SetPixelDirty(top, 8 * firstColIndex); |
| 234 | } |
| 235 | } |
| 236 | } |
| 237 | |
| 238 | #endif |
| 239 |