Font / Text rotation problem.
Bradley A. Burns -- bburns@sprynet.com Saturday, July 27, 1996 Environment: VC 4.0, Win95 Hello everyone... I seem to be having a problem with CFont and outputting rotated text in an owner-drawn listbox control. What I am trying to do should be quite simple, here is a sample code snippet implementation, but keep in mind that the display context in the DrawRotatedText(...) function is a global within the dialogbox class. I know for a fact that it's nothing to do with the ::CDC. void CMyDlg::OnDrawItem(int nIDCtl, LPDRAWITEMSTRUCT lpDrawItemStruct) { DrawRotatedText( lpDrawItemStruct->hDC ); CDialog::OnDrawItem( nIDCtl, lpDrawItemStruct ); } void CMyDlg::DrawRotatedText( HDC& hDC ) { char szBuffer[ 80 ]; strcpy( szBuffer, "Hi-there!!!" ); dc.Attach( hDC ); CFont* rotate_font = new CFont(); rotate_font->CreateFont( 8, 8, 1800, 1800, FW_DONTCARE, 0, 0, 0, DEFAULT_CHARSET, OUT_DEFAULT_PRECIS, CLIP_DEFAULT_PRECIS, PROOF_QUALITY, DEFAULT_PITCH|FF_DONTCARE, "MS Sans Serif" ); // Text output. dc.SetTextColor( RGB(0, 0, 128) ); CFont* oldfont = ( CFont* )dc.SelectObject( &rotate_font ); dc.TextOut( 100, 100, szBuffer, strlen(szBuffer) ); dc.SelectObject( &oldfont ); delete rotate_font; dc.Detach(); } The TextOut(...) works, but the text has not been rotated. In the online VC MFC documentation, it states that the font escapement and orientation should be set to the same value if developing for Win95. As you can see, that's what I did. This code seems as though it should rotate the text... it doesn't. Any help would be appreciated. Brad.
Tomasz Pawlowski -- tomasz@ix.netcom.com Wednesday, July 31, 1996 [Mini-digest: 10 responses] You can rotate only TrueType fonts. For an example follow OnLine Help: -Win32 SDK --Win32 Programmer's Reference ---Overviews ----Graphics Device Interface -----Fonts and Text ------Using the Font and Text Output Functions -------Rotating Lines of Text Tomasz tomasz@ix.netcom.com > From: Bradley A. Burns> To: mfc-l@netcom.com > Subject: Font / Text rotation problem. > Date: Friday, July 26, 1996 9:35 PM > > void CMyDlg::DrawRotatedText( HDC& hDC ) > { > "MS Sans Serif" ); > Any help would be appreciated. > Brad. > -----From: Qing Zhao It's long time ago. I did rotate text last year (VC2.0, Win95). Try to create rotate font with lfEscapement setting to 1800 and lfOrientation setting to 0. It should work. Good Luck! Qing Zhao "Syncro Development Corp" qzhao@syncro.com -----From: "Brad Wilson" My understanding was you can only rotate TrueType fonts. Have you tried this using Arial instead of MS Sans Serif? -- Brad Wilson, Objectivist philosopher, software engineer, web designer crucial@pobox.com http://pobox.com/~crucial Objectvst@Undernet "I'm never going to say I'm sorry for the essence of my soul" -----From: kkok@checkfree.com You are using MS Sans Serif which is not a True Type font, you will need to= use=20 a True Type Font, like Arial to see the text being rotated. Kennedy -----From: Joe Willcoxson "MS Sans Serif" is NOT a True-Type font. Try using a True-Type font instead. -- Joe Willcoxson (aka China Joe) http://users.aol.com/chinajoe #define STD_DISCLAIMER "I speak strictly for myself" -----From: "Alistair Israel" >I seem to be having a problem with CFont and outputting rotated text in an >owner-drawn listbox control. Maybe it's a syntax problem. You're passing the address of a CFont pointer, not the address of a CFont GDI object as require by CDC::SelectObject(). Note the ampersands in the ff. lines: > CFont* oldfont = ( CFont* )dc.SelectObject( &rotate_font ); > dc.SelectObject( &oldfont ); "Walk the earth, Surf the Net" - Alistair Israel (aisrael@hotmail.com) Developer Dude Pilipino Data Network, Inc. http://202.47.133.168 [0800-2000 GMT+0800 only] --------------------------------------------------------- Get Your *Web-Based* Free Email at http://www.hotmail.com --------------------------------------------------------- -----From: "Rowan Trollope" I ran into this once. You can only rotate truetype fonts. Try Helvetica. It should work. If you HAVE to have a non-truetype font, you will have to draw the text to a bitmap, and then rotate the bitmap (by getting the bits, and doing a rotate loop into a new bitmap). - Rowan -----From: "Mike Blaszczak" > Environment: VC 4.0, Win95 Your code has two problems. One is pretty big, the other is pretty small. This is the big one: > CFont* oldfont = ( CFont* )dc.SelectObject( &rotate_font ); > dc.TextOut( 100, 100, szBuffer, strlen(szBuffer) ); > dc.SelectObject( &oldfont ); You should have coded "dc.SelectObject(oldfont)" and "dc.SelectObject(rotate_font)" without the ampersand, I think. The first line (of the three above) compiles only because you hacked it with a questionable cast. I'm surprised that the last line compiles. I'm not sure why you're dynamically allocating your CFont, anyway: it's more efficient to create it on the stack since you're not saving it for use in subsequent paintings. But that's not a problem: that's just coding style. The other problem is that you're asking CreateFont() for a font that isn't a TrueType font. "MS Sans Serif" is a name of a font that usually isn't physicall installed on systems, and is instead logically mapped by the operating system. You have no control over what's going to happen, though, because you specify OUT_DEFAULT_PRECIS. You need to have a TrueType font if you want the text to be rotated. The combination of asking "MS Sans Serif" and OUT_DEFAULT_PRECIS is almost certain to result in the selection of a font that isn't a TrueType font. Baseline rotation only works on TrueType fonts. So, you've asked for something that you can't get and Windows does it's best: it draws the text without escapement for you. I changed your code to this: rotate_font->CreateFont( 8, 0, 900, 900, FW_DONTCARE, 0, 0, 0, DEFAULT_CHARSET, OUT_TT_PRECIS, CLIP_DEFAULT_PRECIS, PROOF_QUALITY, DEFAULT_PITCH|FF_DONTCARE, "Comic Sans MS" ); and it worked just fine. You can see I changed your 1800's to 900's, which just made it easier for my slightly different test program to draw. You can also see I changed the "Height" and "width" parameters. You probably don't want perfectly square characters, and a font size of eight is pretty small. I used OUT_TT_PRECIS to ask for a TrueType font. I also requested a TrueType font that I have on my system: it's named Comic Sans MS. (You can download it for free from http://www.microsoft.com--it's a part of the Web Site Font Pack.) It's important to know that you still might not get a TrueType font even if you ask for OUT_TT_PRECIS. When you call CreateFont(), you're engaging a part of Windows called "the font mapper". The mapper is a chunk of software that looks at the attributes you specify when you call CreateFont() and tries to find the closest match by looking through the list of fonts installed on the system. In you case, you asked for a font that didn't suit your needs: you asked for a font that ended up being a TrueType font. Even though you specifed non-zero rotation values, the font mapper ignored them because it thinks it is more important to match the exact name of the font that you specified. So, my call to CreateFont() above is pretty bad, too: if you don't have "Comic Sans MS" installed on your system, you might get a non-TrueType font and you'll end up not seeing rotated text. It is bad Bad BAD! programming style to hard code the name of a font. It's okay to do it in two situations: a) hacks on your own machine where you know the font exists and where you know that font has the attributes you need and you just want to see how something works and b) where you know, for absolutley certain, that the font _name_ you request is going to be on the machine. The font mapper almost completely ignores all of the other font attributes you specify if you ask for a font by name. Most programmers ask for fonts by name because that's how they see it done in the user interface of most programs. But the thing is that those programs are enumerating all the fonts installed on the machine and letting you chose from the resulting list. Those fonts are _known_ to exist. If you hard code the name, you haven't done any such enumeration and you're just guessing. Other people may or may not have the font that you hard coded. You might reboot one day and not have the font that you hard coded. Then, you'll come whining to the list saying that you didn't change anything and your program just stopped working. You should, instead, decide what kind of font you really want. Do you want a symbol font? Do you want a serif font? Do you want a monospaced font? How big should it be? You should set those flags for the font family and font flags values. For you, you want to rotate the font, so you'd better psecify OUT_TT_PRECIS so that Windows tries to get a TrueType font first. That will give you a far better chance at Windows matching what you want--a font that can be rotated, instead of asking that Windows give you what you don't want--a font where you don't care about the output style and don't care about the width and don't care about the face family. You should leave the font face name blank in your call to CreateFont() unless you're completely sure the font exists on the machine where you're running and you're certain that it does what you want. So, my call to CreateFont() was much better than yours. But it still isn't correct. Far closer to perfect is something like this: rotate_font->CreateFont( 8, 0, 900, 900, FW_NORMAL, 0, 0, 0, DEFAULT_CHARSET, OUT_TT_PRECIS, CLIP_DEFAULT_PRECIS, PROOF_QUALITY, VARIABLE_PITCH | FF_SWISS, NULL ); [Moderator's note: This may be the right thing to do, but I have had a couple of situations where this didn't work. I once specified a font very clearly, but on some users' machines the font that got used instead wasn't anything like what I specified. Sure, these machines were incorrectly set up, but real users pay the bills, and I had to specify a font by name.] There's still two more things wrong: we're not checking the return value. And, I'm almost positive that you don't mean that you want a font eight pixels high. You should read the documentation for CreateFont() to see an easy way to specify the size of the font you get in points. (Maybe you really do want eight pixels, but you didn't say anything about that in your question.) Charles Petzold's books come with a program that lets you specify different parameters to CreateFont() and then draws a sample of the font Windows selects for you based on those parameters. You really should spend some time with this sample so you can understand what I'm talking about. Petzold's description of the font mapper is very good, too: you should read through it so you _really_ know how to use CreateFont(). .B ekiM http://www.nwlink.com/~mikeblas/ -----From: "Bradley A. Burns" Environment: VC4.0; Win95 Hi there... I've figured out what my font / text rotation problem(S) were and everything works fine now. I got this email *just* after I get everything to work correctly and it confirmed my suspicions. Both David and Kennedy were right. I seem to have to use a truetype font for the text to rotate at all. I'm guessing that this is because the other system fonts are bitmapped. Also, I was using a CFont** (reference pointer) instead of just a CFont*. I have now made things much simpler by passing a PLOGFONT variable to the CreateFontIndirect(...) function. This seems to work much faster and has been more manageable, in terms of changing the font via the CFontDialog class. Thanks David and Kennedy. Bradley A. Burns bburns@sprynet.com -----From: Kostya Sebov Neither Win16 nor Win32 supports displaying BITMAPPED fonts rotated (except for some Far East versions). Both do support rotation of the TrueType fonts. Therefore, you must ensure that you're selecting TrueType to use this feature of OS. Alternatively you should 'TextOut' to the membory DC then scan-convert pixels of resulting bitmap on your own. Note, that small sized TT fonts then rotated to multiples of 90 deg. (including not rotated at all) use so called hints to adjust the character outlines to the pixel grids so the text appear quite nice. --- Kostya Sebov. ---------------------------------------------------------------------------- Tel: (38 044) 266-6387 | Fax: (38 044) 266-6195 | E-mail: sebov@is.kiev.ua
| Вернуться в корень Архива |