So, I'm making progress on my Lyrics screen in OpenGL - it's still pretty poor overall, but things are coming along and I'm still trying to get the concept down correctly.
I'm displaying multiple layers of a background .JPG and scaling, translating and rotating them allowing them to blend nicely and provide a rather slow-moving (intentionally) calming background for Track Lyrics to be placed on top of. Here is an image of what it looks like...
I'm telling the text where to place itself using pixel coordinates... and the problem I'm having at the moment is how do I tell how wide (in pixels) the text string that I want to place on the screen is. The only way I could figure out was to go back to my normal Delphi graphics programming and use the Canvas of the main form, set up the font I think I'm using and then do a TextWidth on the string... but that is giving wrong results - as shown in the image above - possibly due to the fact that:
"Font.Size := FontSize;" and...
"Font := CreateFont (-FontSize,0,0,0,FW_BOLD,0,0,0,ANSI_CHARSET,OUT_TT_PRECIS,CLIP_DEFAULT_PRECIS,ANTIALIASED_QUALITY,FF_DONTCARE or DEFAULT_PITCH,FontFace);" are simply not the same thing.
The question then becomes... how it is possible to calculate the middle X position (in pixels) of an arbitrary string with bitmap fonts in OpenGL?
Here's the code so far, and the .zip can be downloaded from http://www.hmusiccentre.org.uk/download/Lyrics.zip if needed. Anyone who decides to provide input will notice the GetTextMiddleX inner function in my Draw procedure... that's where I'm trying to do this at the moment, but going wrong...
Font := CreateFont (-FontSize,0,0,0,FW_BOLD,0,0,0,ANSI_CHARSET,OUT_TT_PRECIS,CLIP_DEFAULT_PRECIS,ANTIALIASED_QUALITY,FF_DONTCARE or DEFAULT_PITCH,FontFace);
I now have two functions to get the size of my text string... my sample string is 'HMusicCentre Lyrics Line 1' and the font I've set up is: "CreateFont (-FontSize,0,0,0,FW_BOLD,0,0,0,ANSI_CHARSET,OUT_TT_PRECIS,CLIP_DEFAULT_PRECIS,ANTIALIASED_QUALITY,FF_DONTCARE or DEFAULT_PITCH,FontFace);" with FontSize being "40" (or really "-40") and FontFace being "Arial".
With this function, I get an answer of the string being 179 pixels wide... and the mid-point being way to the right of where I would expect:
With this function I get an answer of the string being 692 pixels wide... and the mid-point being way to the left of where I would expect:
Code:
function GetTextMiddleX ( pText :String
):Integer;
var
TWidth :Integer;
begin
with frmMain.Canvasdo
begin
Font.Name:= FontFace;
Font.Size:= FontSize;
Font.Style:= Font.Style+[fsBold];
TWidth := TextWidth (pText);
end;
GetTextMiddleX :=(frmMain.Width- TWidth)div2;
end;
...and, get this, actually measuring the actual pixels by taking a screenshot and cropping the image just to the text, tells me that the real width of the string is actually 508 pixels. So when I perform code along the lines of ShadowText (254,YOffset,CurrentLine); it is then perfectly centred on my screen.
Am I doing everything right with the usage of GetTextExtentPoint32? Do I need to tell it anything about the font I want it to measure, or does it already know about my font, 'cos I'm using it? Am I doing the correct thing in getting the DC? Is there another means of returning the width of my string in pixels?
Further investigation has brought some progress, not that good, but progress nevertheless - I don't know how useful this is for me, but it does calculate a string width correctly, seemingly.
I added GLUT to my project, and I used the glutBitmapLength API to calculate the correct width of the string, but I could only select from a subset of fonts. I used GLUT_BITMAP_HELVETICA_18 and I changed my BuiltFont code so that it used -18 and Helvetica. Then, when using the following line, the string was output in the middle X of the screen...
ShadowText ((frmMain.Width - glutBitmapLength (8,PChar (CurrentLine))) div 2,YOffset,CurrentLine);
...but I'll admit, even though it worked OK for this, and also when I tried GLUT_BITMAP_TIMES_ROMAN_24 I'm not happy using GLUT or its apparent limitations on the fonts that I can use. I would still like another way to work properly if that is possible.
With Times New Roman, 24 - the three methods of calculating the string width are now returning:
1) GetTextExtentPoint32 = 179 pixels.
2) frmMain.Canvas, Font, TextWidth = 390 pixels.
3) GLUT glutBitmapLength = 281 pixels, which is almost spot on.
OK... something's wrong with my usage of the GetTextExtentPoint32, that's for sure. It returns a width of 179 pixels regardless of what font I'm actually using to draw on my OpenGL DC. I have some global constants at the top of my program which are passed into the BuildFont procedure... when I change the values between:
Code:
const
FontFace ='Times New Roman';
FontSize =24;
Code:
const
FontFace ='Helvetica';
FontSize =18;
Code:
const
FontFace ='Arial';
FontSize =40;
...I always get 179 pixels from the following procedure:
...would it be possible for anyone to point out to me how I should be properly using GetTextExtentPoint32 in my program, so that it actually knows what font I'm referring to?
For instance, should I have a single DC defined in the program, as a global variable? Can the GetTextExtentPoint32 API refer to another DC that will provide details of my font being used?
And i have some other suggestions for you.
- You should use one global fDC and fRC member of your class. The Global DC should only once initialied with GetDC. So you can destroy your context if you dont needit anymore. And DCs you created with GetDC you allways should release with ReleaseDC.
Code:
procedure TfrmMain.FormClose( Sender :TObject;
var Action : TCloseAction
);
begin
KillFont;
wglMakeCurrent(0,0);
wglDeleteContext(fRC);
ReleaseDC(Handle, fDC);
end;
- You should order your draw function. I think its better when you set your set you perspective if you need it. Let me explain what i mean. You work like this.
// render perpective objects
// set orthomode
// render ortho objects
// set perspective
Yes it works but its better to understand if you work like this.
// set perspective
// render perpective objects
// set orthomode
// render ortho objects
In this case you dosnt need to set the perspective after you created the RC. In the first case you must set the perspective first.
- Last but not least. You should really use our OpenGL Header. The standard header from borland is really old and contains some from functions. glColor should has the Name glColor3f or some else.
PS: To your last post. If you want to use GetTextExtentPoint32 you must select the Font to the DC. Each DC has its own Fonts. But all points to the same window. Its confuse. But i dont know if GetTextExtentPoint32 could make some Problems. Because some fonts supports kerning (overlapping charcombinations). But if you created the chars with wglUseFontBitmaps the kerning couldnt be used. And with GetTextExtentPoint32 the kering will be applyed so the widthes will not be the same.
Registriert: Do Dez 05, 2002 10:35 Beiträge: 4234 Wohnort: Dortmund
You are to fast or im to slow.
But your last code. You should be careful. Every call you created an DC but you never release them. Sometimes you wont get an DC and maybe you memory will be full. Call ReleaseDC to release an DC. I have written it above but its importat so i write it again.
And GetTextExtentPoint32 could have some problems. Also from above. But i think on centered text it shouldnt be visible.
Cool. I have now added ReleaseDC where necessary; thanks. I will review your other post in more detail. I will also look into using the header you mention... I am a little bit in the dark about it all to be honest as I'm, quite obviously, just starting out with all this stuff.
Mitglieder in diesem Forum: 0 Mitglieder und 5 Gäste
Du darfst keine neuen Themen in diesem Forum erstellen. Du darfst keine Antworten zu Themen in diesem Forum erstellen. Du darfst deine Beiträge in diesem Forum nicht ändern. Du darfst deine Beiträge in diesem Forum nicht löschen. Du darfst keine Dateianhänge in diesem Forum erstellen.