Jonnster
Jonnster

Reputation: 3234

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?

Upvotes: 6

Views: 4124

Answers (4)

user2694067
user2694067

Reputation: 9

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.

the opengl32.dll from windows 7 and windows 8 have trouble with a display list call between glNewList/glEndList

see answer with sample "glCallLists(strlen(text), GL_UNSIGNED_BYTE, text);"

my solution:

simple copy the "old" opengl32.dll from XP (windows\system32) to your program folder

Upvotes: 0

user2694067
user2694067

Reputation: 1

I can confirm this bug after changing from XP to Windows 7. If you use the native opengl32.dll driver from windows (without drivers from your grahpicscard, like under RDP) then you have a problem with glCallLists() between glNewList/glEndList.

see Lession 13 von NeHe http://nehe.gamedev.net/tutorial/bitmap_fonts/17002 and change glPrint() to write a line shifted by one place in the ASCII table and a second correct line. (use Windows 7 with RDP Screen)

GLvoid glPrint(const char *fmt, ...)                    // Custom GL "Print" Routine
{
    char        text[256];                              // Holds Our String
    va_list     ap;                                     // Pointer To List Of Arguments

    if (fmt == NULL)                                    // If There's No Text
        return;                                         // Do Nothing

    va_start(ap, fmt);                                  // Parses The String For Variables
        vsprintf_s(text, fmt, ap);                      // And Converts Symbols To Actual Numbers
    va_end(ap);                                         // Results Are Stored In Text

    //first text line
    glRasterPos2f(-0.8f, 0);
    GLuint List1 = glGenLists (1);
    glNewList(List1, GL_COMPILE);
      glPushAttrib(GL_LIST_BIT);                            // Pushes The Display List Bits
      glListBase(base1);                                // Sets The Base Character to 32
      glCallLists(strlen(text), GL_UNSIGNED_BYTE, text);    // Draws The Display List Text
      glPopAttrib();                                        // Pops The Display List Bits
    glEndList();
    glCallList(List1);

    //second text line
    glRasterPos2f(-0.8f, -0.2f);
    glPushAttrib(GL_LIST_BIT);                          // Pushes The Display List Bits
    glListBase(base1);                              // Sets The Base Character
    glCallLists(strlen(text), GL_UNSIGNED_BYTE, text);  // Draws The Display List Text
    glPopAttrib();                                      // Pops The Display List Bits

}

An indication of this trouble: http://www.opengl.org/sdk/docs/man2/xhtml/glNewList.xml glCallList and glCallLists can be entered into display lists. Commands in the display list or lists executed by glCallList  or glCallLists are not included in the display list being created, even if the list creation mode is GL_COMPILE_AND_EXECUTE.

Upvotes: 0

Ben Voigt
Ben Voigt

Reputation: 283733

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.

Upvotes: 1

trumpetlicks
trumpetlicks

Reputation: 7065

I found this, as this is what I was suspecting. I actually suspect that it is a UNICODE thing. I noticed this years ago when I tried to move to a later version fo Visual C++. Problem is most likely that the compiler beyond 2003 automatically typedefs CStrings to wchar_t. Take a look at the linked item below.

http://social.msdn.microsoft.com/forums/en-US/vclanguage/thread/fa43f4aa-1822-405e-a95f-9b6377b64352

Upvotes: 0

Related Questions