PDA

View Full Version : Odd Font Problem



okinrus
05-03-2004, 01:08 PM
I'm using a font class similar to Nehe's tutorial(see below) to print onto the screen, but nothing shows up until the window resized. Does anyone know the cause of this?


// Font.h

#pragma once

#include "stdafx.h"


class Font
{
enum
{
NUM_CHARACTER = 256
};

GLuint m_base;

void BuildFont(CDC& dc, CFont& font);
public:
Font(CDC& dc, CFont& font);


Font(CDC& dc, const char* name,
int point);

~Font();

void print(const std::string& str, GLdouble x, GLdouble y) const;
};
#include "stdafx.h"
#include "Font.h"

void Font::BuildFont(CDC& dc, CFont& font)
{

m_base = glGenLists(NUM_CHARACTER);


CFont* oldFont = dc.SelectObject(&font);


// build display list
wglUseFontBitmaps(dc.m_hDC, 0, NUM_CHARACTER,
m_base);

dc.SelectObject(oldFont);

}

Font::Font(CDC& dc,
CFont& font)
{
// glPushAttrib(GL_COLOR_BUFFER_BIT);
// glColor3d(r, g, b);
BuildFont(dc, font);

// glPopAttrib();
}

Font::Font(CDC& dc, const char* name, int point)
{
CFont font;

font.CreatePointFont(point, name, &dc);

BuildFont(dc, font);

font.DeleteObject();

}

Font::~Font()
{
glDeleteLists(m_base, NUM_CHARACTER);
}

void Font::print(const std::string& str, GLdouble x, GLdouble y) const
{
glRasterPos2d(x, y); // move raster position to (x, y)


glPushAttrib(GL_LIST_BIT); // push the display list bits
glListBase(m_base);

///////////////////////////////////////////
// WARNING! ASSUMES char is unsigned
///////////////////////////////////////////
glCallLists(static_cast<GLsizei>(str.length()),
GL_UNSIGNED_BYTE, str.c_str());

glPopAttrib();
}

Aeluned
05-03-2004, 01:24 PM
Are you issuing a draw after you print the text?

the OnSize handler repaints the screen, it sounds like you're leaving out a repaint somewhere.

okinrus
05-04-2004, 10:48 AM
Ok, I did a little clean up of the font code, since the CDC could be found by wglGetCurrentDC, but everything else is the same.



Are you issuing a draw after you print the text?
No, I'm drawing the text just before the call to glFlush.



the OnSize handler repaints the screen, it sounds like you're leaving out a repaint somewhere.
Yes, something to do with the first repaint not drawing the right font. In fact, it appears the first repaint is not creating the right font, but the triangle is being drawn.

Here is code from the view class that I think is relevant. This view is inherited by other views using different documents. It's more or less test code, however. It recreates the font each time in the repaint.


// UEditView.cpp : implementation of the UEditView class
//

#include "stdafx.h"
#include "Font.h"
#include "UEdit.h"

#include "UEditDoc.h"
#include "UEditView.h"
#include ".\ueditview.h"

#ifdef _DEBUG
#define new DEBUG_NEW
#endif

// UEditView

IMPLEMENT_DYNCREATE(UEditView, CScrollView)

BEGIN_MESSAGE_MAP(UEditView, CScrollView)
// Standard printing commands
ON_COMMAND(ID_FILE_PRINT, CScrollView::OnFilePrint)
ON_COMMAND(ID_FILE_PRINT_DIRECT, CScrollView::OnFilePrint)
ON_COMMAND(ID_FILE_PRINT_PREVIEW, CScrollView::OnFilePrintPreview)
ON_WM_CREATE()
ON_WM_SIZE()
ON_WM_ERASEBKGND()
ON_WM_DESTROY()
END_MESSAGE_MAP()

// UEditView construction/destruction

UEditView::UEditView()
: m_active(false),
m_fullscreen(false)
{
// TODO: add construction code here
m_font = 0;
}

UEditView::~UEditView()
{
}

BOOL UEditView::PreCreateWindow(CREATESTRUCT&amp; cs)
{
// OpenGL can only render to the client area.
// It cannot render to child windows or siblings
cs.style |= WS_CLIPSIBLINGS | WS_CLIPCHILDREN;

return CScrollView::PreCreateWindow(cs);
}

// UEditView drawing

void UEditView::OnDraw(CDC* pDC)
{
UEditDoc* pDoc = GetDocument();
ASSERT_VALID(pDoc);
if (!pDoc)
return;

// Select the palette
CPalette* oldPal = pDC-&amp;gt;SelectPalette(&amp;m_palette, false);
pDC-&amp;gt;RealizePalette();

if (!wglMakeCurrent(pDC-&amp;gt;m_hDC, m_hrc)) {
TRACE("wglMakeCurrent Failed %d\n", GetLastError());
return;
}

DrawScene();

SwapBuffers(pDC-&amp;gt;m_hDC);

if (oldPal)
{
pDC-&amp;gt;SelectPalette(oldPal, false);
}

}

void UEditView::DrawScene()
{
GLint vertices[] = {0, 0,
300, 300,
300, 0};
GLfloat colors[] = {1.0, 0.0, 0.0,
0.0, 1.0, 0.0,
0.0, 0.0, 1.0};




glClearColor(1.0, 1.0, 1.0, 0.0);
glClear(GL_COLOR_BUFFER_BIT);

glEnableClientState(GL_COLOR_ARRAY);
glEnableClientState(GL_VERTEX_ARRAY);

glColorPointer(3, GL_FLOAT, 0, colors);
glVertexPointer(2, GL_INT, 0, vertices);

glDrawArrays(GL_TRIANGLES, 0, 3);


glColor3d(1.0, 0.0, 0.0);


delete m_font;
m_font = new Font("Arial", 120);
m_font-&amp;gt;print("hello", 10, 100);
glFlush();
}

void UEditView::OnInitialUpdate()
{
CScrollView::OnInitialUpdate();
CSize sizeTotal;
// TODO: calculate the total size of this view
sizeTotal.cx = sizeTotal.cy = 100;
SetScrollSizes(MM_TEXT, sizeTotal);

}

// UEditView message handlers

int UEditView::OnCreate(LPCREATESTRUCT lpCreateStruct)
{
if (CScrollView::OnCreate(lpCreateStruct) == -1)
return -1;


// describe and set the pixel format
CClientDC dc(this);

// fill in the pixel format descriptor
PIXELFORMATDESCRIPTOR pfd;
ZeroMemory(&amp;pfd, sizeof pfd);
pfd.nSize = sizeof pfd;
pfd.nVersion = 1;

// PFD_DOUBLEBUFFER =&amp;gt; allow OpenGL to do double buffering
// PFD_SUPPORT_OPENGL =&amp;gt; use OpenGL on this surface
// PDF_DRAW_TO_WINDOW =&amp;gt; draw to a window instead of a bitmap
pfd.dwFlags = PFD_DOUBLEBUFFER |
PFD_SUPPORT_OPENGL |
PFD_DRAW_TO_WINDOW;
pfd.iPixelType = PFD_TYPE_RGBA; // specify colors using (R, G, B, A) format
pfd.cColorBits = 24; // bits per pixel

// OpenGL maintains a buffer called the depth buffer
// For each pixel, the depth buffer contains
// the distance distance between the pixel and the viewer.
// When OpenGL renders an object, it compares the position
// of each new pixel to the position of the old pixel. If
// the position of the new pixel is closer, it is placed on to
// the screen
pfd.cDepthBits = 24;
pfd.iLayerType = PFD_MAIN_PLANE;

// compare generic pixel formats supported by window's NT and
// hardware accelerators, returning the best match
int pixelFormat = ChoosePixelFormat(dc.m_hDC, &amp;pfd);
if (pixelFormat == 0)
{
TRACE("ChoosePixelFormat Failed %d\n", GetLastError());
return -1;
}

if (!SetPixelFormat(dc.m_hDC, pixelFormat, &amp;pfd))
{

TRACE("SetPixelFormat Failed %d\n", GetLastError());
return -1;
}

// now that we have set the pixel format, we must create an
// OpenGL rendering context(GLRC)
// A rendering context is not the same thing as a device context, for
// it includes information for OpenGL, while the device context includes
// information for the GDI
m_hrc = wglCreateContext(dc.m_hDC);
if (!m_hrc)
{
TRACE("wglCreateContext Failed %d\n", GetLastError());
return -1;
}


glShadeModel(GL_SMOOTH);

// make m_hrc the current OpenGL rendering context
if (!wglMakeCurrent(dc.m_hDC, m_hrc))
{
TRACE("wglMakeCurrent Failed%d\n", GetLastError());
return FALSE;
}

SizeOpenGL(lpCreateStruct-&amp;gt;cx, lpCreateStruct-&amp;gt;cy);

return 0;
}

void UEditView::SizeOpenGL(GLint cx, GLint cy)
{
CClientDC dc(this);

// make m_hrc the current OpenGL rendering context
if (!wglMakeCurrent(dc.m_hDC, m_hrc))
{
TRACE("wglMakeCurrent Failed%d\n", GetLastError());
return;
}

// avoid divide by 0
if (cy == 0) {
cy = 1;
}

glViewport(0, 0, cx, cy);
glMatrixMode(GL_PROJECTION);
glLoadIdentity();

// setup the OpenGL viewport
GLdouble aspect = (GLdouble)cx/cy;
gluOrtho2D(0.0, (GLdouble)cx, -100.0, (GLdouble)cy);

}

void UEditView::OnSize(UINT nType, int cx, int cy)
{
CScrollView::OnSize(nType, cx, cy);

CClientDC dc(this);

// make m_hrc the current OpenGL rendering context
if (!wglMakeCurrent(dc.m_hDC, m_hrc))
{
TRACE("wglMakeCurrent Failed%d\n", GetLastError());
return;
}

SizeOpenGL(cx, cy);

}

BOOL UEditView::OnEraseBkgnd(CDC* pDC)
{
return TRUE;
}

void UEditView::OnDestroy()
{
CScrollView::OnDestroy();

delete m_font;

if (m_fullscreen)
{
ToggleFullscreen();
}

wglMakeCurrent(NULL, NULL);

if (m_hrc)
{
wglDeleteContext(m_hrc);
m_hrc = NULL;
}
}

void UEditView::OnActivateView(BOOL bActivate, CView* pActivateView, CView* pDeactiveView)
{
m_active = bActivate;
CScrollView::OnActivateView(bActivate, pActivateView, pDeactiveView);

}

void UEditView::ToggleFullscreen()
{

CWnd* mainWnd = AfxGetMainWnd();
CRect fullRect;

if (!m_fullscreen) {
mainWnd-&amp;gt;GetWindowRect(&amp;m_windowRect);

GetDesktopWindow()-&amp;gt;GetWindowRect(&amp;fullRect);

AdjustWindowRectEx(&amp;fullRect, mainWnd-&amp;gt;GetStyle(), FALSE,
mainWnd-&amp;gt;GetExStyle());


mainWnd-&amp;gt;MoveWindow(&amp;fullRect);

m_fullscreen = true;
} else {
m_fullscreen = false;
mainWnd-&amp;gt;MoveWindow(&amp;m_windowRect);

}


}

okinrus
05-04-2004, 11:20 AM
I also checked the return on wglUseFontBitmaps, and it returns false. GetLastError() returns 87 which means the parameter is incorrect.

okinrus
05-04-2004, 11:46 AM
I managed to get the font code to work with
code

void Font::BuildFont(HDC hdc, CFont&amp; font)
{

m_base = glGenLists(NUM_CHARACTER);

CDC* dc;
dc = CDC::FromHandle(hdc);

CFont* oldFont = dc->SelectObject(&amp;font);


// build display list
while (!wglUseFontBitmaps(hdc, 0, NUM_CHARACTER,
m_base) &amp;&amp; GetLastError() == 87)
{

}

dc->SelectObject(oldFont);

}It's strange that wglUseBitmaps must be called multiple times like this though.