Author Topic: gdi font engine problems  (Read 7100 times)

0 Members and 1 Guest are viewing this topic.

Offline ninogenio

  • Pentium
  • *****
  • Posts: 1668
  • Karma: 133
    • View Profile
gdi font engine problems
« on: September 28, 2007 »
hey guys sorry ive not posted much as of late but ive had a real lack of insparation going.

right i managed to cludge an example of of using the gdi font engine by looking through msn and peicing bits together, now when i put text on a double bufferd window it draws fine but blinks in and out like mad here is the code im using.

Code: [Select]
HFONT eFont, vFont;
LOGFONT LogFont;
       
LogFont.lfStrikeOut = 0;
LogFont.lfUnderline = 0;
LogFont.lfHeight = 42;
LogFont.lfEscapement = 0;
LogFont.lfItalic = FALSE;
LogFont.lfFaceName[0] = '\0';
LogFont.lfCharSet = DEFAULT_CHARSET;
strcpy( (LPSTR)&LogFont.lfFaceName, "Times New Roman" );
   
eFont = CreateFontIndirect(&LogFont);
vFont = (HFONT)SelectObject(hdc, eFont);
SetTextColor(hdc, 0x00000ff);
SetBkColor(hdc, 0x0000ff00);
TextOut(hdc ,20, 308, "My 2D Engine", 19);

SelectObject(hdc, vFont);
DeleteObject(eFont);

im calling this from wm_paint inside a begin/end paint just before flipping my buffers.

my question is can you guys see anything obviously wrong if not ill post my full code.
« Last Edit: September 28, 2007 by ninogenio »
Challenge Trophies Won:

Offline taj

  • Bytes hurt
  • DBF Aficionado
  • ******
  • Posts: 4810
  • Karma: 189
  • Scene there, done that.
    • View Profile
Re: gdi font engine problems
« Reply #1 on: September 28, 2007 »
I believe nothing is wrong, except for the concept. I think gdi cant be double buffered and can only draw to the front buffer.

Chris
Challenge Trophies Won:

Offline ninogenio

  • Pentium
  • *****
  • Posts: 1668
  • Karma: 133
    • View Profile
Re: gdi font engine problems
« Reply #2 on: September 28, 2007 »
yeah thats right, what i want to be able to do is layer my text on top of my double buffered window maybe because im sharing the same dc between my text and my blitter thats where its going funny ill try and make a compatible dc based on the paintstruct hdc and see if that fixes anything.

edit when i say double buffered window i mean fake double buffered using an area in system memory screenx*screeny in size as a back buffer and pushing that up to the screen as a big bitmap through the paintstruct hdc each frame.

edit again nah that didnt work either :(
« Last Edit: September 28, 2007 by ninogenio »
Challenge Trophies Won:

Offline taj

  • Bytes hurt
  • DBF Aficionado
  • ******
  • Posts: 4810
  • Karma: 189
  • Scene there, done that.
    • View Profile
Challenge Trophies Won:

Offline ninogenio

  • Pentium
  • *****
  • Posts: 1668
  • Karma: 133
    • View Profile
Re: gdi font engine problems
« Reply #4 on: September 28, 2007 »
thats quite close to how my soft render works its all come from jims cdi fullscreen code, ill post it up.

the double buffering works fine as you can see the box moves just fine but the text screws up some how.

please excuse the mess of all this, it is just a mess around and also to teach myself c/gdi as im still a bit pants at it all.

http://dbfinteractive.com/index.php?action=tpmod;dl=item65
« Last Edit: September 28, 2007 by ninogenio »
Challenge Trophies Won:

Offline Jim

  • Founder Member
  • DBF Aficionado
  • ********
  • Posts: 5301
  • Karma: 402
    • View Profile
Re: gdi font engine problems
« Reply #5 on: September 28, 2007 »
Create a compatible DC of the same size as the window (using CreateCompatibleDC, CreateCompatibleBitmap, SelectObject), call it the offscreen DC.
http://msdn2.microsoft.com/en-us/library/ms532287.aspx

Draw your software rendered stuff whenever you like, and use SetDIBitsToDevice to draw it into the offscreen DC.  Then use TextOut to draw your text into the offscreen DC.

Inside WM_PAINT, just BitBlt the offscreen DC to the window.

Jim
Challenge Trophies Won:

Offline ninogenio

  • Pentium
  • *****
  • Posts: 1668
  • Karma: 133
    • View Profile
Re: gdi font engine problems
« Reply #6 on: September 29, 2007 »
cheers jim, i see how that should work but theres something wrong somewhere as now the program runs but all i see is my desktop instead of the window heres the modified wm_paint, im sending the offscreen hdc through to my main so the text and the software stuff all gets drawn on the offscreendc and then bitblting it to the paint.hdc.

can you see what ive done wrong?

Code: [Select]
PAINTSTRUCT paint;
memset(&paint, 0, sizeof paint);
paint.hdc = (HDC)wParam;
     
HDC OffScreenDC;
OffScreenDC = CreateCompatibleDC ( paint.hdc );
HBITMAP BufferStorage;
BufferStorage = CreateCompatibleBitmap( paint.hdc, SCREEN_X, SCREEN_Y );
SelectObject( OffScreenDC, BufferStorage );
     
GetUpdateRect(hwnd, &paint.rcPaint,TRUE);
BeginPaint(hwnd, &paint);
GenioMain(OffScreenDC);
BitBlt(paint.hdc, 0, 0, SCREEN_X, SCREEN_Y, OffScreenDC, 0, 0, SRCCOPY);
EndPaint(hwnd, &paint);
     
DeleteDC(OffScreenDC);
« Last Edit: September 29, 2007 by ninogenio »
Challenge Trophies Won:

Offline Jim

  • Founder Member
  • DBF Aficionado
  • ********
  • Posts: 5301
  • Karma: 402
    • View Profile
Re: gdi font engine problems
« Reply #7 on: September 29, 2007 »
Create the compatible DC and bitmap and the do the SelectObject only one time, outside WM_PAINT.
Use
Code: [Select]
HDC hdc = GetDC(my_window);
...
ReleaseDC(my_window, hdc);
to get a DC of your window after you create it.
See how that goes.

Jim
Challenge Trophies Won:

Offline ninogenio

  • Pentium
  • *****
  • Posts: 1668
  • Karma: 133
    • View Profile
Re: gdi font engine problems
« Reply #8 on: September 29, 2007 »
here is what i just had a pop at with no joy.

im doing the initialization stuff just on wm_create.

Code: [Select]
HDC OffScreenDC;
HBITMAP BufferStorage;
LRESULT CALLBACK WindowProc( HWND hwnd , UINT uMsg , WPARAM wParam , LPARAM lParam )
{
        switch (uMsg)
        {           
                case WM_CREATE:
                     
                     OffScreenDC = CreateCompatibleDC ( (HDC)wParam );
                     
                     BufferStorage = CreateCompatibleBitmap( (HDC)wParam, SCREEN_X, SCREEN_Y );
                     SelectObject( OffScreenDC, BufferStorage );
                     
                     GenioInit();
                     break; 
                case WM_DESTROY:
                        GenioCleanUp();
                        ChangeDisplaySettings( NULL , 0 );
                        ShowCursor(1);
                        PostQuitMessage(0);
                        quit = 1;
                        break;
                case WM_KEYDOWN:
                       switch (wParam)
                       {
                              case VK_ESCAPE:
                                   PostQuitMessage(0);
                                   quit = 1;
                                   break;

                        }
                        break;
                 case WM_PAINT:
                      PAINTSTRUCT paint;
                      memset(&paint, 0, sizeof paint);
      paint.hdc = (HDC)wParam;
     
                      GetUpdateRect(hwnd, &paint.rcPaint,TRUE);
      BeginPaint(hwnd, &paint);
      GenioMain(OffScreenDC);
      BitBlt(paint.hdc, 0, 0, SCREEN_X, SCREEN_Y, OffScreenDC, 0, 0, SRCCOPY);
      EndPaint(hwnd, &paint);
     
                      //DeleteDC(OffScreenDC);
                     
                      break;
                case WM_ERASEBKGND:
         return 1;
         break;
          case WM_TIMER:
         InvalidateRect(hwnd, NULL, 0);
         break;
                default:
                        return DefWindowProc(hwnd, uMsg, wParam, lParam);
        }
        return 0;
}
Challenge Trophies Won:

Offline Jim

  • Founder Member
  • DBF Aficionado
  • ********
  • Posts: 5301
  • Karma: 402
    • View Profile
Re: gdi font engine problems
« Reply #9 on: September 29, 2007 »
Why do you think wParam is an HDC?
http://msdn2.microsoft.com/en-us/library/ms632619.aspx
http://msdn2.microsoft.com/en-us/library/ms534901.aspx
You need the HWND returned by CreateWindow to get the HDC of the window, so you can't call this stuff inside WM_CREATE.
(For WM_PAINT, it's calling BeginPaint that sets up paint.hdc)

The plan is:
Previously, flip() called SetDIBitsToDevice to draw directly to the window.
What we're trying to do instead is draw it to an intermediate DC, and then let Windows draw fonts over the top of that, and then copy the whole result over.

If it's still not working, can you post a bit more of the source?

Jim

« Last Edit: September 29, 2007 by Jim »
Challenge Trophies Won:

Offline ninogenio

  • Pentium
  • *****
  • Posts: 1668
  • Karma: 133
    • View Profile
Re: gdi font engine problems
« Reply #10 on: September 29, 2007 »
right i think i get that, its all new to me :) but fun.

here is where the main file is at, the scene_window is the hwnd and im casting it like so ((HDC)scene_window) but still no luck.

if you replace the main.cpp file in my uploaded project you will have it in its current state with all the pixel plotting and textout stuff being put on to the offscreendc in genio main.

Code: [Select]
#include <windows.h>
#include <math.h>
#include <string.h>

#include "main.hpp"

HDC OffScreenDC;
HBITMAP BufferStorage;
LRESULT CALLBACK WindowProc( HWND hwnd , UINT uMsg , WPARAM wParam , LPARAM lParam )
{
        switch (uMsg)
        {           
                case WM_CREATE:
                     GenioInit();
                     break; 
                case WM_DESTROY:
                        GenioCleanUp();
                        ChangeDisplaySettings( NULL , 0 );
                        ShowCursor(1);
                        PostQuitMessage(0);
                        quit = 1;
                        break;
                case WM_KEYDOWN:
                       switch (wParam)
                       {
                              case VK_ESCAPE:
                                   PostQuitMessage(0);
                                   quit = 1;
                                   break;

                        }
                        break;
                 case WM_PAINT:
                      PAINTSTRUCT paint;
                      memset(&paint, 0, sizeof paint);
      paint.hdc = (HDC)wParam;
     
                      GetUpdateRect(hwnd, &paint.rcPaint,TRUE);
      BeginPaint(hwnd, &paint);
      GenioMain(OffScreenDC);
      BitBlt(paint.hdc, 0, 0, SCREEN_X, SCREEN_Y, OffScreenDC, 0, 0, SRCCOPY);
      EndPaint(hwnd, &paint);
                     
                      break;
                case WM_ERASEBKGND:
         return 1;
         break;
          case WM_TIMER:
         InvalidateRect(hwnd, NULL, 0);
         break;
                default:
                        return DefWindowProc(hwnd, uMsg, wParam, lParam);
        }
        return 0;
}


int APIENTRY WinMain( HINSTANCE hInstance , HINSTANCE hPrevInstance , LPSTR lpCmdLine , int nCmdShow )
{
        WNDCLASSEX clas;
        MSG msg;
       
        clas.cbSize = sizeof(WNDCLASSEX);
        clas.style = CS_HREDRAW | CS_VREDRAW;
        clas.lpfnWndProc = WindowProc;
        clas.cbClsExtra = 0;
        clas.cbWndExtra = 0;
        clas.hInstance = hInstance;
        clas.hIcon = NULL;
        clas.hCursor = NULL;
        clas.hbrBackground = 0;
        clas.lpszMenuName = NULL;
        clas.lpszClassName = scene_class;
        clas.hIconSm = 0;
        RegisterClassEx(&clas);
       
        DEVMODE dmScreenSettings;
        memset(&dmScreenSettings, 0, sizeof dmScreenSettings);
dmScreenSettings.dmSize = sizeof dmScreenSettings;
dmScreenSettings.dmPelsWidth = SCREEN_X;
dmScreenSettings.dmPelsHeight = SCREEN_Y;
dmScreenSettings.dmBitsPerPel = SCREEN_BPP;
dmScreenSettings.dmDisplayFrequency = 60;
dmScreenSettings.dmFields = DM_BITSPERPEL | DM_PELSWIDTH | DM_PELSHEIGHT | DM_DISPLAYFREQUENCY;
if (ChangeDisplaySettings (&dmScreenSettings, CDS_FULLSCREEN) == DISP_CHANGE_SUCCESSFUL) scene_window = CreateWindowEx(0, scene_class, "scene!", WS_POPUP, 0,0,SCREEN_X,SCREEN_Y, NULL, NULL, hInstance, 0);
       
        OffScreenDC = CreateCompatibleDC( (HDC)scene_window );
                     
        BufferStorage = CreateCompatibleBitmap( (HDC)scene_window, SCREEN_X, SCREEN_Y );
        SelectObject( OffScreenDC, BufferStorage ); 
       
        Sleep(1000);
        ShowWindow(scene_window, nCmdShow);
        UpdateWindow(scene_window);
        ShowCursor(0);
       
        timeBeginPeriod(1);

    //50Hz
    SetTimer(scene_window, 1, 0, NULL);
   
        do
        {
                while (!quit && GetMessage(&msg, scene_window, 0, 0) > 0)
                {
                        TranslateMessage(&msg);
                        DispatchMessage(&msg);
                } 
                   
        } while (!quit);
       
        timeEndPeriod(1);
        return 0;
}







void renderworld(HDC hdc)
{     
        BITMAPINFO bmi;
       
        bmi.bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
        bmi.bmiHeader.biWidth = SCREEN_X;
        bmi.bmiHeader.biHeight = -SCREEN_Y;
        bmi.bmiHeader.biPlanes = 1;
        bmi.bmiHeader.biBitCount = SCREEN_BPP;
        bmi.bmiHeader.biCompression = BI_RGB;
        bmi.bmiHeader.biSizeImage = 0;
        bmi.bmiHeader.biXPelsPerMeter = 75;
        bmi.bmiHeader.biYPelsPerMeter = 75;
        bmi.bmiHeader.biClrUsed = 0;
        bmi.bmiHeader.biClrImportant = 0;
         
        SetDIBitsToDevice(hdc, 0,0, SCREEN_X,SCREEN_Y, 0,0, 0,SCREEN_Y, screen_ptr, &bmi,  DIB_RGB_COLORS);
       
       
}



void clearworld(void)
{   
     memset( screen_ptr , 0 , SCREEN_X * SCREEN_Y * sizeof(unsigned int) );
}
Challenge Trophies Won:

Offline Jim

  • Founder Member
  • DBF Aficionado
  • ********
  • Posts: 5301
  • Karma: 402
    • View Profile
Re: gdi font engine problems
« Reply #11 on: September 30, 2007 »
You have to be far more careful with your type casting.  An HWND is not the same as an HDC.  HWND is a window, HDC is a device context.  If you tell the compiler that an HWND is an HDC by casting it, it will do what you asked, but there's no chance of it working :)  A good rule of thumb with C is to use as little casting as possible.

There's a function called GetDC that returns the HDC associated with an HWND.

Code: [Select]
        HDC scene_dc = GetDC(scene_window);
        OffScreenDC = CreateCompatibleDC( scene_dc );
                     
        BufferStorage = CreateCompatibleBitmap( scene_dc, SCREEN_X, SCREEN_Y );
        SelectObject( OffScreenDC, BufferStorage );
        ReleaseDC(scene_window, scene_dc);

I'll try to get this up and running myself today, but the above looks like it should work.

Jim
« Last Edit: September 30, 2007 by Jim »
Challenge Trophies Won:

Offline Jim

  • Founder Member
  • DBF Aficionado
  • ********
  • Posts: 5301
  • Karma: 402
    • View Profile
Re: gdi font engine problems
« Reply #12 on: September 30, 2007 »
Here's a standalone piece of code that shows it in action (you were soooo close).
Code: [Select]
#include <windows.h>
#include <math.h>
#include <string.h>

#define SCREEN_X 640
#define SCREEN_Y 480
#define SCREEN_BPP 32

void renderworld(HDC);

HDC OffScreenDC;
HBITMAP BufferStorage;
char scene_class[]="ninotest";
int quit = 0;
HWND scene_window;

LRESULT CALLBACK WindowProc( HWND hwnd , UINT uMsg , WPARAM wParam , LPARAM lParam )
{
        switch (uMsg)
        {           
                case WM_CREATE:                 
                     break; 
                case WM_DESTROY:
//                        ChangeDisplaySettings( NULL , 0 );
                        ShowCursor(1);
                        PostQuitMessage(0);
                        quit = 1;
                        break;
                case WM_KEYDOWN:
                       switch (wParam)
                       {
                              case VK_ESCAPE:
                                   PostQuitMessage(0);
                                   quit = 1;
                                   break;

                        }
                        break;
                 case WM_PAINT:
{
                      PAINTSTRUCT paint;
                      memset(&paint, 0, sizeof paint);      
                      GetUpdateRect(hwnd, &paint.rcPaint,TRUE);
      BeginPaint(hwnd, &paint);
                      renderworld(OffScreenDC);
      BitBlt(paint.hdc, 0, 0, SCREEN_X, SCREEN_Y, OffScreenDC, 0, 0, SRCCOPY);
      EndPaint(hwnd, &paint);
}
                      break;
                     
                case WM_ERASEBKGND:
         return 1;
         break;
          case WM_TIMER:
         InvalidateRect(hwnd, NULL, 0);
         break;
                default:
                        return DefWindowProc(hwnd, uMsg, wParam, lParam);
        }
        return 0;
}


int APIENTRY WinMain( HINSTANCE hInstance , HINSTANCE hPrevInstance , LPSTR lpCmdLine , int nCmdShow )
{
        WNDCLASSEX clas;
        MSG msg;
        HDC hdc;
               
        clas.cbSize = sizeof(WNDCLASSEX);
        clas.style = CS_HREDRAW | CS_VREDRAW;
        clas.lpfnWndProc = WindowProc;
        clas.cbClsExtra = 0;
        clas.cbWndExtra = 0;
        clas.hInstance = hInstance;
        clas.hIcon = NULL;
        clas.hCursor = NULL;
        clas.hbrBackground = 0;
        clas.lpszMenuName = NULL;
        clas.lpszClassName = scene_class;
        clas.hIconSm = 0;
        RegisterClassEx(&clas);
/*       
        DEVMODE dmScreenSettings;
        memset(&dmScreenSettings, 0, sizeof dmScreenSettings);
dmScreenSettings.dmSize = sizeof dmScreenSettings;
dmScreenSettings.dmPelsWidth = SCREEN_X;
dmScreenSettings.dmPelsHeight = SCREEN_Y;
dmScreenSettings.dmBitsPerPel = SCREEN_BPP;
dmScreenSettings.dmDisplayFrequency = 60;
dmScreenSettings.dmFields = DM_BITSPERPEL | DM_PELSWIDTH | DM_PELSHEIGHT | DM_DISPLAYFREQUENCY;
if (ChangeDisplaySettings (&dmScreenSettings, CDS_FULLSCREEN) == DISP_CHANGE_SUCCESSFUL)
*/
        scene_window = CreateWindowEx(0, scene_class, "scene!", WS_POPUP, 0,0,SCREEN_X,SCREEN_Y, NULL, NULL, hInstance, 0);
       
        hdc = GetDC(scene_window);
        OffScreenDC = CreateCompatibleDC( hdc );
                     
        BufferStorage = CreateCompatibleBitmap( hdc, SCREEN_X, SCREEN_Y );
        SelectObject( OffScreenDC, BufferStorage ); 
        ReleaseDC(scene_window, hdc);
       
        Sleep(1000);
        ShowWindow(scene_window, nCmdShow);
        UpdateWindow(scene_window);
        ShowCursor(0);
       
       //timeBeginPeriod(1);

    //50Hz
    SetTimer(scene_window, 1, 0, NULL);
   
        do
        {
                while (!quit && GetMessage(&msg, scene_window, 0, 0) > 0)
                {
                        TranslateMessage(&msg);
                        DispatchMessage(&msg);
                } 
                   
        } while (!quit);
       
        //timeEndPeriod(1);
        return 0;
}

static unsigned int screen_ptr[SCREEN_X*SCREEN_Y];

void clearworld(void)
{   
     memset( screen_ptr , 0 , SCREEN_X * SCREEN_Y * sizeof *screen_ptr );
}

void renderworld(HDC hdc)
{     
        BITMAPINFO bmi;
static int i;

        unsigned int x, y;
        unsigned int *p = screen_ptr;
       
        clearworld();
        for (y = 0; y < SCREEN_Y; y++)
        {
                for (x = 0; x < SCREEN_X; x++)
                {
                    *p++ = ((x+i)^y)|(((x+i+1)^(y+i))<<16);
                }
        }
i++;
       
        bmi.bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
        bmi.bmiHeader.biWidth = SCREEN_X;
        bmi.bmiHeader.biHeight = -SCREEN_Y;
        bmi.bmiHeader.biPlanes = 1;
        bmi.bmiHeader.biBitCount = SCREEN_BPP;
        bmi.bmiHeader.biCompression = BI_RGB;
        bmi.bmiHeader.biSizeImage = 0;
        bmi.bmiHeader.biXPelsPerMeter = 75;
        bmi.bmiHeader.biYPelsPerMeter = 75;
        bmi.bmiHeader.biClrUsed = 0;
        bmi.bmiHeader.biClrImportant = 0;
         
        SetDIBitsToDevice(hdc, 0,0, SCREEN_X,SCREEN_Y, 0,0, 0,SCREEN_Y, screen_ptr, &bmi,  DIB_RGB_COLORS);
 
SetBkMode(hdc, OPAQUE);
  TextOut(hdc, 10,10,"nino is cool!", 13);     
SetBkMode(hdc, TRANSPARENT);
  TextOut(hdc, 10,30,"nino is cool!", 13);     
}

Jim
Challenge Trophies Won:

Offline ninogenio

  • Pentium
  • *****
  • Posts: 1668
  • Karma: 133
    • View Profile
Re: gdi font engine problems
« Reply #13 on: September 30, 2007 »
cool it works! thanks jim.  :cheers:

will this be any slower than the way it was before as theres an extra step now im gussing not much as bitblt is really fast anyway.

and is there a way of specifying another path for the true type fonts rather than the default windows path so that i can include fonts in my project folder.
Challenge Trophies Won:

Offline Jim

  • Founder Member
  • DBF Aficionado
  • ********
  • Posts: 5301
  • Karma: 402
    • View Profile
Re: gdi font engine problems
« Reply #14 on: October 01, 2007 »
I doubt it will be noticeably slower.  The great thing is you're guaranteed no flicker.  In fact, I think Vista works like this always.
I also think you can put fonts in a resource file...but that might be guessing.

Jim
Challenge Trophies Won:

Offline ninogenio

  • Pentium
  • *****
  • Posts: 1668
  • Karma: 133
    • View Profile
Re: gdi font engine problems
« Reply #15 on: October 01, 2007 »
cheers jim.

does this look like it might work to you for changing font pickup paths.
http://books.google.com/books?id=-O92IIF1Bj4C&pg=RA10-PA884&lpg=RA10-PA884&dq=fonts+resource+file&source=web&ots=Sv2GDYbgod&sig=K3ZiqWQldp4r-e0e4q7xWxnOiYU

<edit just looked up a bit and this method can be used for installing fonts to the users system font table but isnt really what im after ill keep looking >
« Last Edit: October 01, 2007 by ninogenio »
Challenge Trophies Won: