15 мая 2023 года "Исходники.РУ" отмечают своё 23-летие!
Поздравляем всех причастных и неравнодушных с этим событием!
И огромное спасибо всем, кто был и остаётся с нами все эти годы!

Главная Форум Журнал Wiki DRKB Discuz!ML Помощь проекту


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




| Вернуться в корень Архива |