Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

OpenGL glCallLists Drawing Incorrect Characters On Windows 7

I have an old application written in Visual C++ 6. Part of this app is drawing text into a bitmap. This works fine on Windows XP but when the same code is run on Windows 7 all the text is shifted by one place in the ASCII table.

For example, "Category" becomes "B'sdfnqx".

Any ideas what is causing this and how to fix it?

Edit: Sorry but the above is slightly incorrect. When I saw the DrawText function in the code I assumed it was the GDI function. When I step into it, it turns out that the author has created their own DrawText function which is using OpenGL. I don't know any OpenGL so this has now got out of hand. It calls glCallLists which passes the text (stored in a CString) into this function.

Full class code below. Note: it is the glCallLists function in the DrawText function causing the problem.

OGLFontClass::OGLFontClass()
{
    m_id = -1;
}

OGLFontClass::~OGLFontClass()
{
    Clear();
}

void OGLFontClass::Clear()
{
    if( m_id != -1 )
    {
        glDeleteLists(m_id,255);
        m_id = -1;
    }
}

void OGLFontClass::Initialise(CString fontname, int size, HDC hDC)
{
    m_HDC = hDC;
    m_id = glGenLists(255);
    ::DeleteObject( m_FONT );

    m_FONT = CreateFont(    -size,              // Height Of Font ( NEW )
                            0,              // Width Of Font
                            0,              // Angle Of Escapement
                            0,              // Orientation Angle
                            FW_NORMAL,          // Font Weight
                            FALSE,              // Italic
                            FALSE,              // Underline
                            FALSE,              // Strikeout
                            ANSI_CHARSET,           // Character Set Identifier
                            OUT_TT_PRECIS,          // Output Precision
                            CLIP_DEFAULT_PRECIS,        // Clipping Precision
                            ANTIALIASED_QUALITY,        // Output Quality
                            FF_DONTCARE|DEFAULT_PITCH,  // Family And Pitch
                            fontname);          // Font Name

    HFONT oldfont = (HFONT)SelectObject(hDC, m_FONT);       // Selects The Font We Want
    wglUseFontBitmaps(hDC, 0, 255, m_id );          // Builds 96 Characters Starting At Character 32
    ::SelectObject( hDC, oldfont );
}

void OGLFontClass::DrawText( float x, float y, CString str )
{
    glRasterPos3f(x,y, 0);

    glPushAttrib(GL_LIST_BIT);
        glListBase(m_id);
        glCallLists(str.GetLength(), GL_UNSIGNED_BYTE, str.GetBuffer(0));
    glPopAttrib();
}

void OGLFontClass::DrawText(int x, int y, int r, int g, int b, CString text)
{
    glMatrixMode(GL_PROJECTION);

    glPushMatrix();
    glLoadIdentity();// Reset The View

    HWND hWnd = ::WindowFromDC(wglGetCurrentDC() );

    RECT rc;
    ::GetClientRect( hWnd, &rc );

    int CX = rc.right;//::GetSystemMetrics( SM_CXSCREEN );
    int CY = rc.bottom;//::GetSystemMetrics( SM_CYSCREEN );

    gluOrtho2D (0,::GetSystemMetrics(SM_CXSCREEN),::GetSystemMetrics(SM_CYSCREEN), 0);

    glMatrixMode(GL_MODELVIEW);
    glPushMatrix();
    glLoadIdentity();

    glColor3ub(r,g,b);  

    glRasterPos2d( x, y );   // had to do this to get the text to line up where i want it

    //glDisable(GL_TEXTURE_2D);

    glPushAttrib(GL_LIST_BIT);      // Pushes The Display List Bits     ( NEW )
    glListBase(m_id);               // Sets The Base Character to 32    ( NEW )

    unsigned char* szTemp = new unsigned char[text.GetLength()+1];
    strcpy((char*)szTemp, text);

    glCallLists(strlen((char*)szTemp), GL_UNSIGNED_BYTE, szTemp);   // Draws The Display List Text  ( NEW )

    delete[] szTemp;

    glPopAttrib();                      // Pops The Display List Bits   ( NEW )

    glPopMatrix();

    glMatrixMode(GL_PROJECTION);

    glPopMatrix();

    glMatrixMode(GL_MODELVIEW);
}

void OGLFontClass::DrawRightText( int x, int y, int r, int g, int b, CString text )
{
    glMatrixMode(GL_PROJECTION);

    glPushMatrix();
    glLoadIdentity();// Reset The View

    HWND hWnd = ::WindowFromDC(wglGetCurrentDC() );

    RECT rc;
    ::GetClientRect( hWnd, &rc );

    float CX = (float)::GetSystemMetrics( SM_CXSCREEN );
    float CY = (float)::GetSystemMetrics( SM_CYSCREEN );
    float fMultiplier = CX / CY;

    gluOrtho2D (0,::GetSystemMetrics(SM_CXSCREEN),::GetSystemMetrics(SM_CYSCREEN), 0);

    glMatrixMode(GL_MODELVIEW);
    glPushMatrix();
    glLoadIdentity();

    int nPos = x;

    glColor3ub(r,g,b);  
    //glDisable(GL_TEXTURE_2D);

    glPushAttrib(GL_LIST_BIT);      // Pushes The Display List Bits     ( NEW )

    glListBase(m_id);               // Sets The Base Character to 32    ( NEW )

    for( int i = text.GetLength() - 1; i >= 0; i-- )
    {
        CString sChar = text.GetAt(i);

        glRasterPos2d(nPos,y);   // had to do this to get the text to line up where i want it
        glCallLists(1, GL_UNSIGNED_BYTE, sChar);    // Draws The Display List Text  ( NEW )

        if ( i > 0 )
        {
            CString sNextChar = text.GetAt(i-1);

            SIZE szWidth = GetTextExtent(sNextChar);
            szWidth.cx += 1;
            szWidth.cx *= fMultiplier;
            szWidth.cx += 1;

            nPos -= szWidth.cx;
        }
    }

    //glCallLists(strlen(text), GL_UNSIGNED_BYTE, text);    // Draws The Display List Text  ( NEW )

    glPopAttrib();                      // Pops The Display List Bits   ( NEW )

    glPopMatrix();

    glMatrixMode(GL_PROJECTION);

    glPopMatrix();

    glMatrixMode(GL_MODELVIEW);

}

CSize OGLFontClass::GetTextExtent(CString text, float fFactor)
{
    SIZE sz;
    HFONT oldfont = (HFONT) SelectObject(m_HDC, m_FONT);
    GetTextExtentPoint32(m_HDC,text,strlen(text),&sz);

    SelectObject(m_HDC, oldfont);

    sz.cx *= 0.2;
    sz.cy *= 0.2;

    return sz;
}

Now I don't know openGL at all but I'm assuming that as glCallLists just reinterprets the string as a byte array there is something going wrong in this between Windows XP and Windows 7. Perhaps a unicode issue or something? 32-bit Windows OS versus 64-bit OS maybe?

Does this now show up a more obvious problem?

like image 467
Jonnster Avatar asked May 28 '12 09:05

Jonnster


1 Answers

This line clearly doesn't do what its comment says:

wglUseFontBitmaps(hDC, 0, 255, m_id );          // Builds 96 Characters Starting At Character 32

Nor does this:

glListBase(m_id);               // Sets The Base Character to 32    ( NEW )

Somehow, your m_id variable is off by one from what it should be. Replace this line by

glListBase(m_id+1);

both places it occurs, and all should be well on Windows 7. But XP will break.

A better fix would be to actually generate only the printable characters, as the accompanying comments suggest. Then you'll not have issues if one of the computers is missing a non-printing character.

like image 161
Ben Voigt Avatar answered Nov 04 '22 18:11

Ben Voigt