Board index » cppbuilder » Problem about Text Metrics (tmInternalLeading)

Problem about Text Metrics (tmInternalLeading)


2006-01-20 06:20:05 PM
cppbuilder34
Hi,
i have problems about metrics. i'm using "GetTextMetrics" api command to
query metrics. the problem is, tmInternalLeading does not fit (especially at
rotation). i prepared a .jpg file to show that situation (it's hard to
mention it with characters :) )
www.proyatech.com/TextMetrics.jpg
i seached many sources, and found that;
Characteristics of a font;
}
} External Leading - space above the
font to the top of the text area
__________________}_______________________________________->Top Alignment
Line
**
} }
* ** } Internal Leading } }
} }
}
*
} }
**
} } Height
* * * *** } Ascent }
* * * *
} }
* ** *
} }
* *
} }
}
* }
}
but i couldn't fit a bounding box to written text... can someone pls help me
? what am i missing ? is there any other metrics should i use ?
Problem :
1. i can't make a exact bounding box (especially at rotation)
2. base line (+tmAscent) always stable bot top line (+tmInternalLeading)
is not stable
3. i really need to calculate base line & top line
i consider top & base lines as;
** *
* **
____________________ Top Line
* *
** *
* * * ***
* * * * *
* ** * *
* * ***------------------------- Base Line
*
*
thx so much for help...
________________________________________
Eyyub Volkan «ektimur
Proya Software & Trade Inc.
Head of Core Development Department
 
 

Re:Problem about Text Metrics (tmInternalLeading)

Eyyub Volkan «ektimur wrote:
Quote
i have problems about metrics. i'm using "GetTextMetrics" api command to
query metrics. the problem is, tmInternalLeading does not fit (especially at
rotation). i prepared a .jpg file to show that situation (it's hard to
mention it with characters :) )

www.proyatech.com/TextMetrics.jpg
I would suggest adding to that jpg, a graphic of what you want to do.
{incomprehensible ascii graphics sniped}
Quote
Problem :
1. i can't make a exact bounding box (especially at rotation)
2. base line (+tmAscent) always stable bot top line (+tmInternalLeading)
is not stable
3. i really need to calculate base line & top line
So you want to draw the yellow lines in your graphic?
What is your current code to do this?
(Show the 45 degree code if it is different)
Have you looked at GetTextExtentPoint32() ?
Maybe GetOutlineTextMetrics()
<quote>
An application can retrieve the physical dimensions of a TrueType font
by calling the GetOutlineTextMetrics function. An application can
retrieve the physical dimensions of any other font by calling the
GetTextMetrics function.</quote>
You might also be interested in the new members in NEWTEXTMETRIC.
 

Re:Problem about Text Metrics (tmInternalLeading)

i didn't used GetTextExtentPoint32. i used GetTextMetrics api to get text
metrics. and calculated text boundary with
tmAscent,tmInternalLeading,tmDescent values. Isn't GetOutlineTextMetrics
returns the same values with GetTextMetrics ? (except more info)
so, how can i get NEWTEXTMETRIC data ? i couldn't find a realated api
method...
--
________________________________________
Eyyub Volkan «ektimur
Proya Software & Trade Inc.
Head of Core Development Department
"Bob Gonder" < XXXX@XXXXX.COM >wrote in message
Quote
Have you looked at GetTextExtentPoint32() ?
Maybe GetOutlineTextMetrics()
<quote>
An application can retrieve the physical dimensions of a TrueType font
by calling the GetOutlineTextMetrics function. An application can
retrieve the physical dimensions of any other font by calling the
GetTextMetrics function.</quote>

You might also be interested in the new members in NEWTEXTMETRIC.


 

{smallsort}

Re:Problem about Text Metrics (tmInternalLeading)

Eyyub Volkan «ektimur wrote:
Quote
i didn't used GetTextExtentPoint32. i used GetTextMetrics api to get text
metrics. and calculated text boundary with
tmAscent,tmInternalLeading,tmDescent values. Isn't GetOutlineTextMetrics
returns the same values with GetTextMetrics ? (except more info)
For the 45 degree text, the question still remains if your code
correctly does the box drawing Trigonometry the same way that MS does
it.
That's why I asked to see the code. Something I can compile and play
with to try to figure it out.
Quote
so, how can i get NEWTEXTMETRIC data ? i couldn't find a realated api
method...
It is used in the callbacks to the EnumFont... group of functions.
See the help page "Enumerating the Installed Fonts"
I am also guessing that if you use it in a call to GetTextMetrics on a
TrueType font, that the extra members will be filled in, but that's
just a guess, and could be wrong.
 

Re:Problem about Text Metrics (tmInternalLeading)

here is some code (my real code is a bit different, i simplified it) ;
----------------------------------------------------------------------------
-----
TCanvas *Canvas=Im->Picture->Bitmap->Canvas; // Canvas
int W=Im->Width,H=Im->Height; // W:Width of
Canvas , H:Height of Canvas
int TextWidth; // Width of Text
TPoint Org(200,200); // origin
AnsiString Text="Bg‚¬j{}"; // Text
double RotMatrix[4]={1,0,0,1}; // Rotation
Matrix
double RotAngle=0; // Rotation
Angle
OUTLINETEXTMETRIC md; // text metrics
TPointd BoundingPoints[4]; // bounding
rect./polygon points
TPointd P; // temp. point
// Clear Screen
Canvas->Pen->Color=clWhite;
Canvas->Brush->Color=clWhite;
Canvas->Brush->Style=bsSolid;
Canvas->FillRect(TRect(0,0,W,H));
Canvas->Brush->Style=bsClear;
// Set Font
Canvas->Font->Name="Arial";
Canvas->Font->Size=50;
Canvas->Font->Color=clBlack;
SetTextAlign(Canvas->Handle,TA_TOP);
// Set Rotation
if (RotAngle!=0)
{
TLogFont lf;
double Radyan;
GetObject(Canvas->Font->Handle,sizeof(lf),&lf);
lf.lfOrientation=RotAngle*10;
lf.lfOrientation=lf.lfOrientation%(360*10);
lf.lfEscapement=lf.lfOrientation;
lf.lfQuality=PROOF_QUALITY;
lf.lfOutPrecision=OUT_DEVICE_PRECIS;
Canvas->Font->Handle=CreateFontIndirect(&lf);
// Prepare Rotation Matrix
Radyan=M_PI*RotAngle/180;
RotMatrix[0]=cos(Radyan); RotMatrix[1]=sin(Radyan);
RotMatrix[2]=-sin(Radyan); RotMatrix[3]=cos(Radyan);
}
// Query Font Metrics
GetOutlineTextMetrics(Canvas->Handle,sizeof(md),&md);
TextWidth=Canvas->TextWidth(Text);
// Calculate Bounding Box
BoundingPoints[0].Set(0,0);
BoundingPoints[1].Set(TextWidth,0);
BoundingPoints[2].Set(TextWidth,md.otmTextMetrics.tmAscent+md.otmTextMetrics
.tmDescent);
BoundingPoints[3].Set(0,md.otmTextMetrics.tmAscent+md.otmTextMetrics.tmDesce
nt);
// Apply Rotation Matrix to Points
for (int cx=0;cx<4;cx++)
{
P=BoundingPoints[cx];
BoundingPoints[cx].x=RotMatrix[0]*P.x+RotMatrix[1]*P.y;
BoundingPoints[cx].y=RotMatrix[2]*P.x+RotMatrix[3]*P.y;
}
// Write Text
Canvas->TextOut(Org.x,Org.y,Text);
// Draw Boundary
Canvas->Pen->Color=clRed;
Canvas->MoveTo(Org.x+BoundingPoints[0].x,Org.y+BoundingPoints[0].y);
Canvas->LineTo(Org.x+BoundingPoints[1].x,Org.y+BoundingPoints[1].y);
Canvas->LineTo(Org.x+BoundingPoints[2].x,Org.y+BoundingPoints[2].y);
Canvas->LineTo(Org.x+BoundingPoints[3].x,Org.y+BoundingPoints[3].y);
Canvas->LineTo(Org.x+BoundingPoints[0].x,Org.y+BoundingPoints[0].y);
----------------------------------------------------------------------------
-----
if you set "RotAngle" var. to rotation value (for exm. 45) , you'll see the
rotated Bounding Box. this is how i'm calculating bounding box. it's getting
growed after rotation. and that is my real problem. i want consistent
bounding box. thx for help...
________________________________________
Eyyub Volkan «ektimur
Proya Software & Trade Inc.
Head of Core Development Department
"Bob Gonder" < XXXX@XXXXX.COM >wrote in message
Quote
Eyyub Volkan «ektimur wrote:

>i didn't used GetTextExtentPoint32. i used GetTextMetrics api to get text
>metrics. and calculated text boundary with
>tmAscent,tmInternalLeading,tmDescent values. Isn't GetOutlineTextMetrics
>returns the same values with GetTextMetrics ? (except more info)

For the 45 degree text, the question still remains if your code
correctly does the box drawing Trigonometry the same way that MS does
it.
That's why I asked to see the code. Something I can compile and play
with to try to figure it out.

>so, how can i get NEWTEXTMETRIC data ? i couldn't find a realated api
>method...

It is used in the callbacks to the EnumFont... group of functions.
See the help page "Enumerating the Installed Fonts"

I am also guessing that if you use it in a call to GetTextMetrics on a
TrueType font, that the extra members will be filled in, but that's
just a guess, and could be wrong.


 

Re:Problem about Text Metrics (tmInternalLeading)

Eyyub Volkan «ektimur wrote:
I don't do VCL, so it'll take a while to translate to Winapi.
But off hand, this looks suspicious...
Quote
double RotAngle=0;
double Radyan;
Radyan=M_PI*RotAngle/180;
Would prefere to see
Radyan = (M_PI * RotAngle) / 180.0;
Also, rather than
Quote
lf.lfOrientation=RotAngle*10;
lf.lfOrientation=lf.lfOrientation%(360*10);
Would prefer to see
RotAngle = RotAngle%360;
// Set Rotation
if (RotAngle!=0)
{ {....}
lf.lfOrientation = RotAngle * 10;
That would also catch errors for Radyan
 

Re:Problem about Text Metrics (tmInternalLeading)

Ok, here's what I found.
MS fudges the text height when rotated.
The rotated text height on screen is actually the same as non-rotated.
So get the non-rotated height, and adjust the box.
This is complicated by you using TA_TOP because you need to adjust the
start location of the box. If you used TA_BOTTOM, you'd just need to
use the correct height I think (and change the box calc for negative
Y).
This isn't perfect, but seems to be pretty close, at least at normal
font sizes. Change Dy,Dx to 50,50, and it's off.
POINT BoundingPoints[5] = {0};
POINT P;
HFONT Font = CreateFont(
0,0,//Dy,Dx,
RotAngle*10, // angle of escapement
RotAngle*10, // base-line orientation angle
FW_NORMAL, // font weight
FALSE, // italic attribute flag
FALSE, // underline attribute flag
FALSE, // strikeout attribute flag
DEFAULT_CHARSET, // character set identifier
OUT_DEVICE_PRECIS, // output precision
CLIP_DEFAULT_PRECIS, // clipping precision
PROOF_QUALITY, // output quality
VARIABLE_PITCH+FF_DONTCARE, // pitch and family
"Arial" // typeface name string
);
SelectObject(hdc,(HGDIOBJ)Font);
SetTextAlign( hdc, TA_TOP );
SetBkMode( hdc, OPAQUE ); /* shows full size of text field */
TextOut( hdc, Org.x, Org.y, Text, lstrlen(Text) );
SIZE lpSize;
GetTextExtentPoint32( hdc, Text, lstrlen(Text), &lpSize );
TextWidth = lpSize.cx;
GetTextMetrics( hdc, &tm );
switch( type )
{case 0: // non-rotated
TextHeight = lpSize.cy;
OldTextHeight = TextHeight;
OldAscent = tm.tmAscent;
break;
case 2: // 135 degrees
TextHeight = OldTextHeight;
Org.x += (tm.tmAscent - OldAscent);
Org.y -= (tm.tmAscent - OldAscent);
break;
case 1: // 45 degrees
TextHeight = OldTextHeight;
Org.x += (tm.tmAscent - OldAscent);
Org.y += (tm.tmAscent - OldAscent);
break;
case other:
write the code for 225 and 315
};
BoundingPoints[1].x = TextWidth;
BoundingPoints[2].x = TextWidth;
BoundingPoints[2].y = TextHeight;
BoundingPoints[3].y = TextHeight;
// Apply Rotation Matrix to Points
for( cx=0; cx<4; ++cx)
{
P=BoundingPoints[cx];
BoundingPoints[cx].x = Org.x + (RotMatrix[0] * P.x) +
(RotMatrix[1] * P.y);
BoundingPoints[cx].y = Org.y + (RotMatrix[2] * P.x) +
(RotMatrix[3] * P.y);
};
BoundingPoints[4] = BoundingPoints[0]; //Close the poly
// Draw Boundary
Polyline( hdc, BoundingPoints, 5 );
Entire test code available if you need it.
 

Re:Problem about Text Metrics (tmInternalLeading)

Hi,
thx for youyr effort. i got your point and tried to get metrics without
rotation. it seems it's working (with TA_BASELINE). i want to ask that are
your sure about is bounding box always as the same with non-rotated one ? i
tried with Arial & Verdana fonts and seems that they are same. as you said
windows fudges text height when the font rotated.
thx again so much. that really helped me...
P.S. : sorry , my first post gone wrong to your personal mail addr...
--
________________________________________
Eyyub Volkan «ektimur
Proya Software & Trade Inc.
Head of Core Development Department
"Bob Gonder" < XXXX@XXXXX.COM >wrote in message
Quote

Ok, here's what I found.
MS fudges the text height when rotated.
The rotated text height on screen is actually the same as non-rotated.
So get the non-rotated height, and adjust the box.
This is complicated by you using TA_TOP because you need to adjust the
start location of the box. If you used TA_BOTTOM, you'd just need to
use the correct height I think (and change the box calc for negative
Y).
This isn't perfect, but seems to be pretty close, at least at normal
font sizes. Change Dy,Dx to 50,50, and it's off.

POINT BoundingPoints[5] = {0};
POINT P;

HFONT Font = CreateFont(
0,0,//Dy,Dx,
RotAngle*10, // angle of escapement
RotAngle*10, // base-line orientation angle
FW_NORMAL, // font weight
FALSE, // italic attribute flag
FALSE, // underline attribute flag
FALSE, // strikeout attribute flag
DEFAULT_CHARSET, // character set identifier
OUT_DEVICE_PRECIS, // output precision
CLIP_DEFAULT_PRECIS, // clipping precision
PROOF_QUALITY, // output quality
VARIABLE_PITCH+FF_DONTCARE, // pitch and family
"Arial" // typeface name string
);
SelectObject(hdc,(HGDIOBJ)Font);
SetTextAlign( hdc, TA_TOP );
SetBkMode( hdc, OPAQUE ); /* shows full size of text field */
TextOut( hdc, Org.x, Org.y, Text, lstrlen(Text) );

SIZE lpSize;
GetTextExtentPoint32( hdc, Text, lstrlen(Text), &lpSize );
TextWidth = lpSize.cx;

GetTextMetrics( hdc, &tm );

switch( type )
{case 0: // non-rotated
TextHeight = lpSize.cy;
OldTextHeight = TextHeight;
OldAscent = tm.tmAscent;
break;
case 2: // 135 degrees
TextHeight = OldTextHeight;
Org.x += (tm.tmAscent - OldAscent);
Org.y -= (tm.tmAscent - OldAscent);
break;
case 1: // 45 degrees
TextHeight = OldTextHeight;
Org.x += (tm.tmAscent - OldAscent);
Org.y += (tm.tmAscent - OldAscent);
break;
case other:
write the code for 225 and 315
};

BoundingPoints[1].x = TextWidth;
BoundingPoints[2].x = TextWidth;
BoundingPoints[2].y = TextHeight;
BoundingPoints[3].y = TextHeight;

// Apply Rotation Matrix to Points
for( cx=0; cx<4; ++cx)
{
P=BoundingPoints[cx];
BoundingPoints[cx].x = Org.x + (RotMatrix[0] * P.x) +
(RotMatrix[1] * P.y);
BoundingPoints[cx].y = Org.y + (RotMatrix[2] * P.x) +
(RotMatrix[3] * P.y);
};
BoundingPoints[4] = BoundingPoints[0]; //Close the poly

// Draw Boundary
Polyline( hdc, BoundingPoints, 5 );


Entire test code available if you need it.