Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

String in negative #372

Open
dobraMorda opened this issue Jul 23, 2022 · 2 comments
Open

String in negative #372

dobraMorda opened this issue Jul 23, 2022 · 2 comments

Comments

@dobraMorda
Copy link

Hello!

Did you think anytime about add new feature to this library which can make draw string in negative like in below picture?
bez nazwy
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!

@dobraMorda
Copy link
Author

dobraMorda commented Jul 25, 2022

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!

@marcelstoer
Copy link
Member

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 inverseColor state flag to OLEDDisplay
  • add a void setInverseColor(bool inverseColor) to OLEDDisplay change the state
  • consider this flag inside the existing drawStringInternal function
  • adjust the existing functions that already have a bool inverse parameter (e.g. like drawIco16x16())

Alternative II:

  • add a bool inverse = false parameter to the various drawString functions (just like drawIco16x16() has)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants