Jump to content


OpenGL/GDI Font


31 replies to this topic

#21 Reedbeta

    DevMaster Staff

  • Administrators
  • 5311 posts
  • LocationSanta Clara, CA

Posted 15 February 2007 - 07:41 AM

Lost said:

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 (;) 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. :)
reedbeta.com - developer blog, OpenGL demos, and other projects

#22 dave_

    Senior Member

  • Members
  • PipPipPipPip
  • 584 posts

Posted 15 February 2007 - 10:24 AM

Lost said:

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.

#23 Lost

    New Member

  • Members
  • PipPip
  • 27 posts

Posted 15 February 2007 - 07:36 PM

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.

© 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.

#24 Nils Pipenbrinck

    Senior Member

  • Members
  • PipPipPipPip
  • 597 posts

Posted 16 February 2007 - 12:29 AM

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).


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;

}


#25 Lost

    New Member

  • Members
  • PipPip
  • 27 posts

Posted 16 February 2007 - 02:05 AM

Oops, got it compiled. Thanks.
Missing:

typedef unsigned char sU8;


GGO_GRAY8_BITMAP returns 65 levels of gray (0 to 64).
Shouldn't this line be:

glyphImg[j] = (255*(int)(glyphImg[j])) / 64;

to convert (0 to 64) into (0 to 255).

#26 Nils Pipenbrinck

    Senior Member

  • Members
  • PipPipPipPip
  • 597 posts

Posted 16 February 2007 - 10:45 AM

Lost said:

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

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

I use these sU an sI types since years so it's hard to spot them :-) But you figured it out. You're right with the gray scaling as well.

Don't worry to much about the glyph extraction code. The code here was just my experimental testbed when I wrote my font packing tool and font rendering class. The key element is really only the kerning information and the positional info inside the glyphs.

These should be extracted at asset generation time and stored in a file for later use. You don't want to call GetGlyphOutline inside your game.

#27 dave_

    Senior Member

  • Members
  • PipPipPipPip
  • 584 posts

Posted 16 February 2007 - 11:53 AM

If you do come up with a way that's consistent with text out, please post it here, in the spirit of sharing! :D

#28 Lost

    New Member

  • Members
  • PipPip
  • 27 posts

Posted 16 February 2007 - 05:13 PM

I'm no font expert, but the problem I see with the font.cpp code is how it does
its spacing. It seems to be constant for every character. While spacing obtained
from kerning has extra spacing info between two characters. Maybe somehow combine
your method + kerning spacing?

#29 Nils Pipenbrinck

    Senior Member

  • Members
  • PipPipPipPip
  • 597 posts

Posted 16 February 2007 - 09:36 PM

The code I've posted does exactly that: Pixel perfect placement as TextOut.

#30 Lost

    New Member

  • Members
  • PipPip
  • 27 posts

Posted 17 February 2007 - 11:56 AM

But, how to get it to an OpenGL backbuffer?
You are writing the fonts as per pixel.

Does glDrawPixels() write to the backbuffer?

And still need to position it correctly on the screen, with glRasterPos().

#31 Nils Pipenbrinck

    Senior Member

  • Members
  • PipPipPipPip
  • 597 posts

Posted 17 February 2007 - 12:31 PM

Lost said:

But, how to get it to an OpenGL backbuffer?
You are writing the fonts as per pixel.

Does glDrawPixels() write to the backbuffer?

And still need to position it correctly on the screen, with glRasterPos().

Well - my code is just a "proof of concept" thing to show how to do the positioning. It's not to be used in an application.

Put all the glyphs into a bitmap and extract the kerning tables using my code. Then you can draw the glyphs via textued quads.

#32 barman

    New Member

  • Members
  • Pip
  • 1 posts

Posted 23 December 2009 - 07:53 PM

I know this is an old post. But you you seem to be pretty fluent with this topic. I have some basic questions:

1. How do we know how many characters are there in a character set.
example: the number of asian characters is more than the number of characters in english.

2. I obtained the kerning pais using GetKerningPairs. Sometimes kerning amount is 0 which means there is no kerning. Why is it there then?
Why other pairs of first & second not there i nthe kerning pairs list?

Any pointers will be appreciated,
Barman





1 user(s) are reading this topic

0 members, 1 guests, 0 anonymous users