DevMaster.net Forums
[[ Home | Forums | 3D Engines Database | Wiki | Articles/Tutorials | Game Dev Jobs | IRC Chat Network | Contact Us ]]

Go Back   DevMaster.net Forums > Site Discussions > Code & Snapshot Discussion
User Name
Password
Register FAQ Members List Search Today's Posts Mark Forums Read

Reply
 
Thread Tools Search this Thread Display Modes
Old 12-21-2006, 08:00 AM   #1
dave_
Senior Member
 
Join Date: Sep 2005
Location: Brighton, UK
Posts: 584
Default

Here is an OpenGL/GDI Font, inspired by D3DFont. Its pretty straight forward to use.
Just create the font object specifying the name of the typeface and the rest of the attributes and then call initialise.
When you're rendering you scene call render with your string and the coordinates you require.
As usual, I'm aiming for simplicity, and tried to keep dependencies down to a minimum.
I only really use this as a debugging tool so its not the most efficient possible. However its not bad, with very few tweaks you can use this in a more efficient way.
I havent bothered to do any checking for large font sizes. It will probably crash.

You could export the texture file (look at where the texture is uploaded at gluBuild2DMipmaps) and use that on non-windows platforms. Of course, you'd have to use public domain typeface.

Let me know what you think!

Here is the code which you can hopefully just drag and drop into your Windows/OpenGL project.

Font.h
Code:
#ifndef INCLUDE_FONT_H #define INCLUDE_FONT_H #include <Windows.h> #include <string> class Font { public: Font(const char* font, unsigned int size, bool bold, bool italic); ~Font(); bool initialise(); void render(const char* pstr, float x, float y); void getTextSize(const char* pstr, float &xOut, float &yOut) const; private: float renderChar (int ch, float x, float y) const; unsigned int width_; unsigned int height_; unsigned int spacing_; unsigned int texture_; unsigned int fontSize_; std::string name_; float texCoords_[128-32][4]; bool bold_; bool italic_; enum PaintResult { Fail, MoreData, Success, }; bool createGDIFont( HDC hDC, HFONT* pFont ); PaintResult paintAlphabet( HDC hDC, bool bMeasureOnly ); }; #endif

Font.cpp
Code:
#include "Font.h" #include <math.h> #include <gl/GLU.h> #include <fstream> Font::Font(const char* font, unsigned int size, bool bold, bool italic) : bold_(bold), italic_(italic), name_(font), texture_(0), width_(128), height_(128), fontSize_(size), spacing_(fontSize_ / 3) { } Font::~Font() { if (texture_) { glDeleteTextures(1, &texture_); } } bool Font::initialise() { HDC hDC = CreateCompatibleDC( NULL ); SetMapMode( hDC, MM_TEXT ); HFONT hFont = NULL; bool ok = createGDIFont( hDC, &hFont ); if (ok) { HFONT hFontOld = (HFONT) SelectObject( hDC, hFont ); PaintResult p; while( MoreData == (p = paintAlphabet( hDC, true )) ) { width_ *= 2; height_ *= 2; } ok = p == Success; if (ok) { // Prepare to create a bitmap DWORD* pBitmapBits; BITMAPINFO bmi; ZeroMemory( &bmi.bmiHeader, sizeof(BITMAPINFOHEADER) ); bmi.bmiHeader.biSize = sizeof(BITMAPINFOHEADER); bmi.bmiHeader.biWidth = (int)width_; bmi.bmiHeader.biHeight = -(int)height_; bmi.bmiHeader.biPlanes = 1; bmi.bmiHeader.biCompression = BI_RGB; bmi.bmiHeader.biBitCount = 32; // Create a bitmap for the font HBITMAP hbmBitmap = CreateDIBSection( hDC, &bmi, DIB_RGB_COLORS, (void**)&pBitmapBits, NULL, 0 ); HGDIOBJ hbmOld = SelectObject( hDC, hbmBitmap ); // Set text properties SetTextColor( hDC, RGB(255,255,255) ); SetBkColor( hDC, RGB(0,0,0) ); SetTextAlign( hDC, TA_TOP ); // Paint the alphabet onto the selected bitmap ok = paintAlphabet( hDC, false ) == Success; if (ok) { glGenTextures(1, &texture_); BITMAP bitmap; GetObject(hbmBitmap,sizeof(BITMAP), &bitmap); glBindTexture(GL_TEXTURE_2D, texture_); // Bind Our Texture glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER,GL_LINEAR); glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,GL_LINEAR_MIPMAP_LINEAR); // Its actually BGRA, but since we're rendering white... gluBuild2DMipmaps(GL_TEXTURE_2D, 4, width_, height_, GL_RGBA, GL_UNSIGNED_BYTE, bitmap.bmBits); } SelectObject( hDC, hbmOld ); SelectObject( hDC, hFontOld ); DeleteObject( hbmBitmap ); DeleteObject( hFont ); DeleteDC( hDC ); } } return ok; } bool Font::createGDIFont( HDC hDC, HFONT* pFont ) { int nHeight = fontSize_; DWORD dwBold = bold_ ? FW_BOLD : FW_NORMAL; DWORD dwItalic = italic_ ? TRUE : FALSE; *pFont = CreateFont( nHeight, 0, 0, 0, dwBold, dwItalic, FALSE, FALSE, DEFAULT_CHARSET, OUT_DEFAULT_PRECIS, CLIP_DEFAULT_PRECIS, ANTIALIASED_QUALITY, VARIABLE_PITCH, name_.c_str() ); return ( *pFont != NULL ); } Font::PaintResult Font::paintAlphabet( HDC hDC, bool bMeasureOnly ) { SIZE size; char str[2] = "x"; // Calculate the spacing between characters based on line height if( 0 == GetTextExtentPoint32( hDC, str, 1, &size ) ) return Fail; spacing_ = (int)ceil(size.cy * 0.3f); // Set the starting point for the drawing DWORD x = spacing_; DWORD y = 0; // For each character, draw text on the DC and advance the current position for( char c = 32; c < 127; c++ ) { str[0] = c; if( 0 == GetTextExtentPoint32( hDC, str, 1, &size ) ) return Fail; if( (DWORD)(x + size.cx + spacing_) > width_ ) { x = spacing_; y += size.cy + 1; } // Check to see if there's room to write the character here if( y + size.cy > height_ ) return MoreData; if( !bMeasureOnly ) { // Perform the actual drawing if( 0 == ExtTextOut( hDC, x+0, y+0, ETO_OPAQUE, NULL, str, 1, NULL ) ) return Fail; texCoords_[c-32][0] = ((FLOAT)(x))/width_; texCoords_[c-32][1] = ((FLOAT)(y))/height_; texCoords_[c-32][2] = ((FLOAT)(x + size.cx))/width_; texCoords_[c-32][3] = ((FLOAT)(y + size.cy))/height_; } x += size.cx + (2 * spacing_); } return Success; } float Font::renderChar (int ch, float x, float y) const { float tx1 = texCoords_[ch-32][0]; float ty1 = texCoords_[ch-32][1]; float tx2 = texCoords_[ch-32][2]; float ty2 = texCoords_[ch-32][3]; float w = (tx2-tx1) * width_ ; float h = (ty2-ty1) * height_; glTexCoord2f(tx1, ty2); glVertex2f(x, y); glTexCoord2f(tx2, ty2); glVertex2f(x+w, y); glTexCoord2f(tx2, ty1); glVertex2f(x+w, y+h); glTexCoord2f(tx1, ty1); glVertex2f(x, y+h); return w; } void Font::render(const char* pstr, float xs, float ys) { glEnable(GL_BLEND); glBlendFunc(GL_SRC_COLOR, GL_ONE); glEnable(GL_TEXTURE_2D); glBindTexture(GL_TEXTURE_2D, texture_); glBegin (GL_QUADS); float x = xs; float y = ys - fontSize_; for (const char *ptr = pstr; *ptr; ++ptr) { if (*ptr == ' ') { x += spacing_; } else if (*ptr == '\n') { y -= fontSize_; x = xs; } else if( (*ptr-32) < 0 || (*ptr-32) >= 128-32 ) { } else { x += renderChar(*ptr, x, y); } } glEnd(); glDisable(GL_TEXTURE_2D); glDisable(GL_BLEND); } void Font::getTextSize(const char* pstr, float &xOut, float &yOut) const { float x = 0; float y = 0; for (const char *ptr = pstr; *ptr; ++ptr { if (*ptr == ' ') { x += spacing_; } else if (*ptr == '\n') { y += fontSize_; xOut = std::max<float>(xOut, x); } else if( (*ptr-32) < 0 || (*ptr-32) >= 128-32 ) { } else { float tx1 = texCoords_[*ptr-32][0]; float tx2 = texCoords_[*ptr-32][2]; x += (tx2-tx1) * width_ ; } } yOut = y; }

Last edited by Reedbeta : 02-13-2007 at 10:40 AM.
dave_ is offline   Reply With Quote
Old 02-12-2007, 06:28 AM   #2
Lost
New Member
 
Join Date: Dec 2005
Posts: 27
Default Re: OpenGL/GDI Font

How about a simple demo using it?
Lost is offline   Reply With Quote
Old 02-12-2007, 03:29 PM   #3
dave_
Senior Member
 
Join Date: Sep 2005
Location: Brighton, UK
Posts: 584
Default Re: OpenGL/GDI Font

Its pretty simple, but just for you, I've adapted a glut example

Code:
// Dave Hillier, adapted from GLUT example /* Copyright (c) Mark J. Kilgard, 1994. */ /* This program is freely distributable without licensing fees and is provided without guarantee or warrantee expressed or implied. This program is -not- in the public domain. */ #include <string.h> #include <GL/glut.h> #include "Font.h" Font *font = NULL; Font *fonts[3]; char defaultMessage[] = "GLUT means OpenGL."; char *message = defaultMessage; void selectFont(int newfont) { font = fonts[newfont]; glutPostRedisplay(); } void selectMessage(int msg) { switch (msg) { case 1: message = "abcdefghijklmnop"; break; case 2: message = "ABCDEFGHIJKLMNOP"; break; } } void selectColor(int color) { switch (color) { case 1: glColor3f(0.0, 1.0, 0.0); break; case 2: glColor3f(1.0, 0.0, 0.0); break; case 3: glColor3f(1.0, 1.0, 1.0); break; } glutPostRedisplay(); } void tick(void) { glutPostRedisplay(); } void output(int x, int y, char *string) { font->render(string, x, 150-y); } void display(void) { glClear(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT); output(0, 0, "This is written in a GLUT bitmap font."); output(100, 65, message); output(50, 120, "(positioned in pixels blah blah)"); glutSwapBuffers(); } void reshape(int w, int h) { glViewport(0, 0, w, h); glMatrixMode(GL_PROJECTION); glLoadIdentity(); gluOrtho2D(0, w, 0, h); glMatrixMode(GL_MODELVIEW); } int main(int argc, char **argv) { int msg_submenu, color_submenu; glutInit(&argc, argv); glutInitDisplayMode(GLUT_DOUBLE | GLUT_RGB | GLUT_DEPTH); glutInitWindowSize(500, 150); glutCreateWindow("Font.cpp bitmap font example"); glClearColor(0.0, 0.0, 0.0, 1.0); fonts[0] = new Font("Arial", 15, false, false); fonts[1] = new Font("Times New Roman", 10, false, false); fonts[2] = new Font("Verdana", 24, false, false); for (int i = 0; i < 3; ++i) fonts[i]->initialise(); font = fonts[2]; glutDisplayFunc(display); glutReshapeFunc(reshape); glutIdleFunc(tick); msg_submenu = glutCreateMenu(selectMessage); glutAddMenuEntry("abc", 1); glutAddMenuEntry("ABC", 2); color_submenu = glutCreateMenu(selectColor); glutAddMenuEntry("Green", 1); glutAddMenuEntry("Red", 2); glutAddMenuEntry("White", 3); glutCreateMenu(selectFont); glutAddMenuEntry("Arial 15", 0); glutAddMenuEntry("Times New Roman 10", 1); glutAddMenuEntry("Verdana 24", 2); glutAddSubMenu("Messages", msg_submenu); glutAddSubMenu("Color", color_submenu); glutAttachMenu(GLUT_RIGHT_BUTTON); glutMainLoop(); for (int i = 0; i < 3; ++i) delete fonts[i]; return 0; /* ANSI C requires main to return int. */ }
dave_ is offline   Reply With Quote
Old 02-13-2007, 12:48 AM   #4
Lost
New Member
 
Join Date: Dec 2005
Posts: 27
Default Re: OpenGL/GDI Font

Do you know what's going on?



I just changed the background color of font and display to see outline of characters better.
Didn't change anything else.
Lost is offline   Reply With Quote
Old 02-13-2007, 01:22 AM   #5
dave_
Senior Member
 
Join Date: Sep 2005
Location: Brighton, UK
Posts: 584
Default Re: OpenGL/GDI Font

It should look like this:


If I change the background colour, like this:
dave_ is offline   Reply With Quote
Old 02-13-2007, 08:42 AM   #6
Lost
New Member
 
Join Date: Dec 2005
Posts: 27
Default Re: OpenGL/GDI Font

Ah, I think I see the problem. The posted code is bad.

You posted:
else if (*ptr == 'n')

and it should be:
else if (*ptr == '\n')

Code:
(*ptr == '\n')

Code tags work ok for me. Is there a reason why the code was posted bad?
Any other errors I miss?
Lost is offline   Reply With Quote
Old 02-13-2007, 10:23 AM   #7
dave_
Senior Member
 
Join Date: Sep 2005
Location: Brighton, UK
Posts: 584
Default Re: OpenGL/GDI Font

Very odd... I've not made any changes to the code since posting it.
Perhaps it was the way I cut and paste it.... maybe.
There are two instances of 'n' that need changing to '\n' (one in getTextSize, the other in render)
dave_ is offline   Reply With Quote
Old 02-13-2007, 10:41 AM   #8
Reedbeta
DevMaster Staff
 
Join Date: Oct 2004
Location: Seattle, WA
Posts: 3,707
Default Re: OpenGL/GDI Font

Hmm...I made the changes. I think this might have to do with the string not being properly MySQL escaped when submitted through the COTD form. I always have to add backslashes on quotes and things when I use it.
___________________________________________
Currently working at Sucker Punch
reedbeta.com - OpenGL demos and other projects
Luabridge - a lightweight, dependency-free C++/Lua binding library.
CD Lite - an unobtrusive, minimal CD player application for Windows.
Reedbeta is offline   Reply With Quote
Old 02-13-2007, 02:36 PM   #9
Lost
New Member
 
Join Date: Dec 2005
Posts: 27
Default Re: OpenGL/GDI Font

What I would find most useful in a OpenGL Font renderer, would be a function that
would mimic the parameters of TextOut(). Basically, an OpenGL version of TextOut().
Both functions should render text in the exactly the same location on screen, at
exactly the same scale and size.
Lost is offline   Reply With Quote
Old 02-13-2007, 03:29 PM   #10
Reedbeta
DevMaster Staff
 
Join Date: Oct 2004
Location: Seattle, WA
Posts: 3,707
Default Re: OpenGL/GDI Font

Lost, what does TextOut do that this sample does not? Both of them just take a string and a location at which to display it. The only other thing I can see that TextOut does is responds to left/center/right alignment settings, but that could easily be added to this class.

EDIT: another interesting extention I can think of is to let the render function take printf-style varargs...this would be pretty easy to glom on with vsnprintf
___________________________________________
Currently working at Sucker Punch
reedbeta.com - OpenGL demos and other projects
Luabridge - a lightweight, dependency-free C++/Lua binding library.
CD Lite - an unobtrusive, minimal CD player application for Windows.

Last edited by Reedbeta : 02-13-2007 at 04:30 PM.
Reedbeta is offline   Reply With Quote
Old 02-13-2007, 06:42 PM   #11
Lost
New Member
 
Join Date: Dec 2005
Posts: 27
Default Re: OpenGL/GDI Font

TexOut() takes logical coordinates, while the above code takes pixel coordinates,
so they don't render text at the same location on the screen.

The exact location, size and scale is important for me, because I might want
to print it out. In other words, you could use OpenGL's TextOut() as a preview,
and then use GDI's TextOut() for printing.

If I could, I would use TextOut() directly on the backbuffer, but you can't.
http://support.microsoft.com/kb/131024

Last edited by Lost : 02-13-2007 at 06:47 PM.
Lost is offline   Reply With Quote
Old 02-13-2007, 08:23 PM   #12
Lost
New Member
 
Join Date: Dec 2005
Posts: 27
Default Re: OpenGL/GDI Font

I rendered GDI's TextOut() on the top, and font.cpp on the bottom, same font style and font size,
spacing seems to be off by some pixels:



I am serious about trying to create an exact copy of GDI TextOut() down to the last pixel.

I'm not sure if this has to do with OpenGL's pixel rasterization?
Microsoft has some recommendations.

The rasterization rules are specific:
Quote:
To obtain exact two-dimensional rasterization, carefully specify both the orthographic projection and the vertices of the primitives that are to be rasterized. Specify the orthographic projection with integer coordinates, as shown in the following example:
gluOrtho2D(0, width, 0, height);
The parameters width and height are the dimensions of the viewport. Given this projection matrix, place polygon vertices and pixel image positions at integer coordinates to rasterize predictably. For example, glRecti(0, 0, 1, 1) reliably fills the lower-left pixel of the viewport, and glRasterPos2i(0, 0) reliably positions an unzoomed image at the lower-left pixel of the viewport. However, point vertices, line vertices, and bitmap positions should be placed at half-integer locations. For example, a line drawn from (x (1) , 0.5) to (x (2) , 0.5) will be reliably rendered along the bottom row of pixels in the viewport, and a point drawn at (0.5, 0.5) will reliably fill the same pixel as glRecti(0, 0, 1, 1).

An optimum compromise that allows all primitives to be specified at integer positions, while still ensuring predictable rasterization, is to translate x and y by 0.375, as shown in the following code sample. Such a translation keeps polygon and pixel image edges safely away from the centers of pixels, while moving line vertices close enough to the pixel centers.

glViewport(0, 0, width, height);
glMatrixMode(GL_PROJECTION);
glLoadIdentity( );
gluOrtho2D(0, width, 0, height);
glMatrixMode(GL_MODELVIEW);
glLoadIdentity( );
glTranslatef(0.375, 0.375, 0.0);
/* render all primitives at integer positions */

Last edited by Lost : 02-13-2007 at 09:02 PM.
Lost is offline   Reply With Quote
Old 02-13-2007, 10:28 PM   #13
Reedbeta
DevMaster Staff
 
Join Date: Oct 2004
Location: Seattle, WA
Posts: 3,707
Default Re: OpenGL/GDI Font

Well, I admit I'm "lost" as to why you would care so much about a few single-pixel errors - I don't see why you can't just use TextOut itself. But, if you want, feel free to take dave's code and modify it to fix the offsets.
___________________________________________
Currently working at Sucker Punch
reedbeta.com - OpenGL demos and other projects
Luabridge - a lightweight, dependency-free C++/Lua binding library.
CD Lite - an unobtrusive, minimal CD player application for Windows.
Reedbeta is offline   Reply With Quote
Old 02-14-2007, 01:42 AM   #14
dave_
Senior Member
 
Join Date: Sep 2005
Location: Brighton, UK
Posts: 584
Default Re: OpenGL/GDI Font

If you want an exact copy of what you get in text out, you should probably render the entire string to texture then display that instead of the technique I'm using. But in the case you've shown, it looks like the space is just 1 pixel to large. Perhaps spacing_ should be (fontSize_ / 3) - 1

The font probably renders the same as D3DFont.

Last edited by dave_ : 02-14-2007 at 01:45 AM.
dave_ is offline   Reply With Quote
Old 02-14-2007, 02:51 AM   #15
Lost
New Member
 
Join Date: Dec 2005
Posts: 27
Default Re: OpenGL/GDI Font

Quote:
Originally Posted by Reedbeta
Well, I admit I'm "lost" as to why you would care so much about a few single-pixel errors
A few pixel errors will probably turn into many pixel errors when the font size is enlarged.

Quote:
Originally Posted by Reedbeta
I don't see why you can't just use TextOut itself.
Because Microsoft won't let me do it. I posted a technical link above.

Quote:
Originally Posted by dave_
If you want an exact copy of what you get in text out, you should probably render the entire string to texture then display that instead of the technique I'm using. But in the case you've shown, it looks like the space is just 1 pixel to large. Perhaps spacing_ should be (fontSize_ / 3) - 1
Subtracting 1 worked for Arial and Verdana, but not for Times New Roman,
so spacing seems to be complicated. And rendering out an entire line is not
practical for me, as length will always be an issue. Per character is best.
Lost is offline   Reply With Quote
Old 02-14-2007, 08:43 AM   #16
Reedbeta
DevMaster Staff
 
Join Date: Oct 2004
Location: Seattle, WA
Posts: 3,707
Default Re: OpenGL/GDI Font

Quote:
Originally Posted by Lost
Because Microsoft won't let me do it. I posted a technical link above.

Right, but why would you want to use TextOut on an OpenGL backbuffer anyway? You mentioned using it to construct some screen preview for printing, but if that's the case all your printing has to be done using GDI anyway, so your screen preview can be done in GDI too, and you could just use TextOut itself.

And I don't get your point about multi-pixel errors when the text is enlarged. Proportional to the size of the text the errors will still be very, very small. Really, why bother worrying about such small offsets? It's not like TextOut is some paragon of typographical perfection anyway.
___________________________________________
Currently working at Sucker Punch
reedbeta.com - OpenGL demos and other projects
Luabridge - a lightweight, dependency-free C++/Lua binding library.
CD Lite - an unobtrusive, minimal CD player application for Windows.
Reedbeta is offline   Reply With Quote
Old 02-14-2007, 12:08 PM   #17
Lost
New Member
 
Join Date: Dec 2005
Posts: 27
Default Re: OpenGL/GDI Font

I want to use elements of OpenGL and TextOut() together (interactively), and the
only way to do that is to render TextOut() to the backbuffer. But this is prohibited.
The exact position, size and scale of the font is important. The OpenGL version
of TextOut() must match its GDI equivalent exactly.
Lost is offline   Reply With Quote
Old 02-14-2007, 02:09 PM   #18
Reedbeta
DevMaster Staff
 
Join Date: Oct 2004
Location: Seattle, WA
Posts: 3,707
Default Re: OpenGL/GDI Font

Quote:
Originally Posted by Lost
The exact position, size and scale of the font is important. The OpenGL version
of TextOut() must match its GDI equivalent exactly.

You still haven't answered my question: why is it so important? Honestly, I can't think of a good reason.
___________________________________________
Currently working at Sucker Punch
reedbeta.com - OpenGL demos and other projects
Luabridge - a lightweight, dependency-free C++/Lua binding library.
CD Lite - an unobtrusive, minimal CD player application for Windows.
Reedbeta is offline   Reply With Quote
Old 02-14-2007, 04:14 PM   #19
dave_
Senior Member
 
Join Date: Sep 2005
Location: Brighton, UK
Posts: 584
Default Re: OpenGL/GDI Font

Quote:
Originally Posted by Lost
only way to do that is to render TextOut() to the backbuffer.
It's not the only way, you can render to texture.
dave_ is offline   Reply With Quote
Old 02-15-2007, 12:18 AM   #20
Lost
New Member
 
Join Date: Dec 2005
Posts: 27
Default Re: OpenGL/GDI Font

Quote:
You still haven't answered my question: why is it so important? Honestly, I can't think of a good reason.
Needless to say, I need it, so let's just agree to that.
WYSIWYG. It doesn't make much sense to print something out
that doesn't look exactly what you created. I hope you understand that.

Quote:
It's not the only way, you can render to texture.

I could probably create a pbuffer the same size as the backbuffer, and copy it
over at the end of every render. It just depends on how much video memory is
available, as all buffers must be created in video memory.

I might have a screen display of 1024x768x32 or larger, and might also want to
create some extra pbuffers for other work in addition to the 3 buffers already
being used for flipping (font/back/pbuffer copy).

I'm guessing most 3D cards nowadays come with 128MB or more?

Last edited by Lost : 02-15-2007 at 12:34 AM.
Lost is offline   Reply With Quote
Old 02-15-2007, 12:41 AM   #21
Reedbeta
DevMaster Staff
 
Join Date: Oct 2004
Location: Seattle, WA
Posts: 3,707
Default Re: OpenGL/GDI Font

Quote:
Originally Posted by Lost
WYSIWYG. It doesn't make much sense to print something out
that doesn't look exactly what you created.

True, but my original points remain. Printers don't support OpenGL. Therefore, if you're printing something, either (a) you are using GDI to construct the printed image, in which case you could just use GDI to construct the screen preview as well and use TextOut in both cases, or (b) you're printing a bitmap rendered by OpenGL, in which case the bitmap would be a pixel-for-pixel copy (or maybe a high-res rerendering) of the bitmap on the screen including the text by whatever method it was drawn. So, your request still doesn't make any sense to me.
___________________________________________
Currently working at Sucker Punch
reedbeta.com - OpenGL demos and other projects
Luabridge - a lightweight, dependency-free C++/Lua binding library.
CD Lite - an unobtrusive, minimal CD player application for Windows.
Reedbeta is offline   Reply With Quote
Old 02-15-2007, 03:24 AM   #22
dave_
Senior Member
 
Join Date: Sep 2005
Location: Brighton, UK
Posts: 584
Default Re: OpenGL/GDI Font

Quote:
Originally Posted by Lost
I could probably create a pbuffer the same size as the backbuffer, and copy it
over at the end of every render. It just depends on how much video memory is
available, as all buffers must be created in video memory.

I might have a screen display of 1024x768x32 or larger, and might also want to
create some extra pbuffers for other work in addition to the 3 buffers already
being used for flipping (font/back/pbuffer copy).

I really dont understand what you're trying to do but I mean the other way round. I mean use GDI to draw your document/TextOut onto a bitmap then use that bitmap as a texture, like I'm doing with the fonts.

Last edited by dave_ : 02-15-2007 at 03:31 AM.
dave_ is offline   Reply With Quote
Old 02-15-2007, 12:36 PM   #23
Lost
New Member
 
Join Date: Dec 2005
Posts: 27
Default Re: OpenGL/GDI Font

Quote:
or (b) you're printing a bitmap rendered by OpenGL, in which case the bitmap would be a pixel-for-pixel copy (or maybe a high-res rerendering) of the bitmap on the screen including the text by whatever method it was drawn.

(c) Bitmap rendered by OpenGL and TextOut()

If I can get TextOut() to the backbuffer somehow, then my problems will be solved.


Quote:
I really dont understand what you're trying to do but I mean the other way round. I mean use GDI to draw your document/TextOut onto a bitmap then use that bitmap as a texture, like I'm doing with the fonts.

The problem is, the end result must be displayed interactively, so creating a buffer
in software, and then copying to video memory would be extremely slow. All buffers
should really be created in video memory. And also, there's an issue with layering
the elements of the scene. Text is generally the last element to be rendered, so
by that alone, it wouldn't work out very well.
Lost is offline   Reply With Quote
Old 02-15-2007, 05:29 PM   #24
Nils Pipenbrinck
Senior Member
 
Nils Pipenbrinck's Avatar
 
Join Date: Sep 2005
Location: Hamburg / Germany
Posts: 597
Default Re: OpenGL/GDI Font

If you need the same kerning as Win32 TextOut I might have what you need.

This litte test-code generates the same output. You can use it to extract the kerning tables from ttf-fonts. Note that most fonts have different kerning tables for different font sizes, so you can't just extract one table and use it for scaled fonts (it will look like shit).

Code:
char * img; void putpixel (int x, int y, int a) { img[1024*y+x] = a; } void PlacingTest (void) { HDC dc = CreateCompatibleDC(0); int size = 32; img = new char[1024*1024]; memset (img, 0, 1024*1024); wchar_t * string = L"This is a test"; GLYPHMETRICS gm; MAT2 mat; mat.eM11.fract = 0; mat.eM11.value = 1; mat.eM21.fract = 0; mat.eM21.value = 0; mat.eM12.fract = 0; mat.eM12.value = 0; mat.eM22.fract = 0; mat.eM22.value = 1; HFONT fnt = CreateFont(size,0,0,0,FW_NORMAL,0,0,0,ANSI_CHARSET,OUT_TT_PRECIS,CLIP_DEFAULT_PRECIS,PROOF_QUALITY,FF_DONTCARE,"Arial"); SelectObject (dc, fnt); int nKerningPairs = GetKerningPairs(dc, 0, 0); KERNINGPAIR * kerningpairs = new KERNINGPAIR[nKerningPairs]; GetKerningPairs(dc, nKerningPairs, kerningpairs); int xpos = 0; int ypos = 40; wchar_t last = 0; for (int i=0; i<wcslen(string); i++) { // get image from gdi DWORD BytesReq = GetGlyphOutlineW(dc, string[i], GGO_GRAY8_BITMAP, &gm, 0, 0, &mat); sU8 * glyphImg= new sU8[BytesReq]; DWORD r = GetGlyphOutlineW(dc, string[i], GGO_GRAY8_BITMAP, &gm, BytesReq, glyphImg, &mat); for (int j=0; j<BytesReq; j++) glyphImg[j]= 255*int(glyphImg[j])/65; // apply kerning for (int k=0; k<nKerningPairs; k++) { if ((kerningpairs[k].wFirst == last) && (kerningpairs[k].wSecond == string[i])) { xpos += kerningpairs[k].iKernAmount; break; } } // blit glyph onto bitmap: if (string[i]!= ' ') { int w = (gm.gmBlackBoxX+3)&~3; int h = gm.gmBlackBoxY; for (int y=0; y<gm.gmBlackBoxY; y++) for (int x=0; x<gm.gmBlackBoxX; x++) putpixel (x+xpos+gm.gmptGlyphOrigin.x, y+ypos-gm.gmptGlyphOrigin.y, glyphImg[y*w+x]); } delete [] glyphImg; xpos += gm.gmCellIncX; last = string[i]; } delete [] kerningpairs; // save the image (so you can test it) FILE *f = fopen ("c://test.raw","wb"); if (f) { fwrite (img, 1024,1024,f); fclose (f); } delete [] img; }
Nils Pipenbrinck is offline   Reply With Quote
Old 02-15-2007, 07:05 PM   #25
Lost
New Member
 
Join Date: Dec 2005
Posts: 27
Default Re: OpenGL/GDI Font

Oops, got it compiled. Thanks.
Missing:
Code:
typedef unsigned char sU8;

GGO_GRAY8_BITMAP returns 65 levels of gray (0 to 64).
Shouldn't this line be:
Code:
glyphImg[j] = (255*(int)(glyphImg[j])) / 64;
to convert (0 to 64) into (0 to 255).

Last edited by Lost : 02-15-2007 at 08:23 PM.
Lost is offline   Reply With Quote
Reply


Thread Tools Search this Thread
Search this Thread:

Advanced Search
Display Modes

Forum Jump


All times are GMT -7. The time now is 10:53 AM.


Powered by vBulletin
Copyright ©2000 - 2009, Jelsoft Enterprises Ltd.