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
| Вернуться в корень Архива
|