esp8266-oled-ssd1306
esp8266-oled-ssd1306 copied to clipboard
String in negative
Hello!
Did you think anytime about add new feature to this library which can make draw string in negative like in below picture?
I think it will be great feature to making multi menus with scrolling screen to easy showing selected position in menu.I think it should be method like drawNegativeString(x, y, message). Maybe I can help with that for you?
Best Regards!
I made this feature in my local code. To avoid potential damage to the rest of the code, I wrote two separate methods. If someone want to use this feature you can add below methods to OLEDDisplay.cpp file:
void OLEDDisplay::drawStringInternalNegative( int16_t xMove, int16_t yMove, char* text, uint16_t textLength, uint16_t textWidth ) {
uint8_t textHeight = pgm_read_byte( fontData + HEIGHT_POS );
uint8_t firstChar = pgm_read_byte( fontData + FIRST_CHAR_POS );
uint16_t sizeOfJumpTable = pgm_read_byte( fontData + CHAR_NUM_POS ) * JUMPTABLE_BYTES;
uint16_t cursorX = 0;
uint16_t cursorY = 0;
switch ( textAlignment ) {
case TEXT_ALIGN_CENTER_BOTH:
yMove -= textHeight >> 1;
// Fallthrough
case TEXT_ALIGN_CENTER:
xMove -= textWidth >> 1; // divide by 2
break;
case TEXT_ALIGN_RIGHT:
xMove -= textWidth;
break;
case TEXT_ALIGN_LEFT:
break;
}
// Don't draw anything if it is not on the screen.
if ( xMove + textWidth < 0 || xMove > this->width( ) ) {
return;
}
if ( yMove + textHeight < 0 || yMove > this->width( ) ) {
return;
}
// inverse color again
setColor( WHITE );
// fill rect under text
fillRect( xMove, yMove + 2, textWidth, textHeight - 4 );
// inverse color
setColor( BLACK );
for ( uint16_t j = 0; j < textLength; j++ ) {
int16_t xPos = xMove + cursorX;
int16_t yPos = yMove + cursorY;
uint8_t code = text[ j ];
if ( code >= firstChar ) {
uint8_t charCode = code - firstChar;
// 4 Bytes per char code
uint8_t msbJumpToChar = pgm_read_byte( fontData + JUMPTABLE_START + charCode * JUMPTABLE_BYTES ); // MSB \ JumpAddress
uint8_t lsbJumpToChar = pgm_read_byte( fontData + JUMPTABLE_START + charCode * JUMPTABLE_BYTES + JUMPTABLE_LSB ); // LSB /
uint8_t charByteSize = pgm_read_byte( fontData + JUMPTABLE_START + charCode * JUMPTABLE_BYTES + JUMPTABLE_SIZE ); // Size
uint8_t currentCharWidth = pgm_read_byte( fontData + JUMPTABLE_START + charCode * JUMPTABLE_BYTES + JUMPTABLE_WIDTH ); // Width
// Test if the char is drawable
if ( !( msbJumpToChar == 255 && lsbJumpToChar == 255 ) ) {
// Get the position of the char data
uint16_t charDataPosition = JUMPTABLE_START + sizeOfJumpTable + ( ( msbJumpToChar << 8 ) + lsbJumpToChar );
drawInternal( xPos, yPos, currentCharWidth, textHeight, fontData, charDataPosition, charByteSize );
}
cursorX += currentCharWidth;
}
}
// inverse color again to back to normal mode
setColor( WHITE );
}
void OLEDDisplay::drawStringNegative( int16_t xMove, int16_t yMove, const String& strUser ) {
uint16_t lineHeight = pgm_read_byte( fontData + HEIGHT_POS );
// char* text must be freed!
char* text = utf8ascii( strUser );
uint16_t yOffset = 0;
// If the string should be centered vertically too
// we need to now how heigh the string is.
if ( textAlignment == TEXT_ALIGN_CENTER_BOTH ) {
uint16_t lb = 0;
// Find number of linebreaks in text
for ( uint16_t i = 0; text[ i ] != 0; i++ ) {
lb += ( text[ i ] == 10 );
}
// Calculate center
yOffset = ( lb * lineHeight ) / 2;
}
uint16_t line = 0;
char* textPart = strtok( text, "\n" );
while ( textPart != NULL ) {
uint16_t length = strlen( textPart );
drawStringInternalNegative( xMove, yMove - yOffset + ( line++ ) * lineHeight, textPart, length, getStringWidth( textPart, length ) );
textPart = strtok( NULL, "\n" );
}
free( text );
}
And then you need to add declare of methods in .h file:
in public section:
void drawStringNegative( int16_t xMove, int16_t yMove, const String& strUser );
in protected section:
void drawStringInternalNegative( int16_t xMove, int16_t yMove, char* text, uint16_t textLength, uint16_t textWidth );
@marcelstoer If You accept this feature and the code I wrote is correct for you, feel free to add it to your library!
Thanks for the proposal and your willingness to help the community. I like the idea, it sounds sane. However, I am not happy with the proposed implementation for two primary reasons:
- it's copy-paste of the existing function with only very minor changes thereby needlessly pumping up the code base
- it is based on the old 4.2 code rather than the 4.3 code
Alternative I:
- add a
bool inverseColorstate flag toOLEDDisplay - add a
void setInverseColor(bool inverseColor)toOLEDDisplaychange the state - consider this flag inside the existing
drawStringInternalfunction - adjust the existing functions that already have a
bool inverseparameter (e.g. likedrawIco16x16())
Alternative II:
- add a
bool inverse = falseparameter to the variousdrawStringfunctions (just likedrawIco16x16()has)