this structure is incorrectly defined in windows.inc and on MSDN
updated definition...
typedef struct _OUTLINETEXTMETRIC {
UINT otmSize;
TEXTMETRIC otmTextMetrics;
BYTE otmMysteryBytes[4];
PANOSE otmPanoseNumber;
BYTE otmMysteryByte;
UINT otmfsSelection;
UINT otmfsType;
int otmsCharSlopeRise;
int otmsCharSlopeRun;
int otmItalicAngle;
UINT otmEMSquare;
int otmAscent;
int otmDescent;
UINT otmLineGap;
UINT otmsCapEmHeight;
UINT otmsXHeight;
RECT otmrcFontBox;
int otmMacAscent;
int otmMacDescent;
UINT otmMacLineGap;
UINT otmusMinimumPPEM;
POINT otmptSubscriptSize;
POINT otmptSubscriptOffset;
POINT otmptSuperscriptSize;
POINT otmptSuperscriptOffset;
UINT otmsStrikeoutSize;
int otmsStrikeoutPosition;
int otmsUnderscoreSize;
int otmsUnderscorePosition;
PSTR otmpFamilyName;
PSTR otmpFaceName;
PSTR otmpStyleName;
PSTR otmpFullName;
} OUTLINETEXTMETRIC, *POUTLINETEXTMETRIC;
i used the term "mystery byte" because they are filled with non-zero, undefined values
notice that the TEXTMETRIC structure will be different sizes for ANSI and UNICODE versions
also, it is worth noting that the otmSize value need not be filled prior to
calling the function as with the "cbSize" member of many structures
a few dumps to demonstrate the correct nature of the structure...
---------------------------------
ANSI, lfHeight = 11
---------------------------------
00000103 - otmSize dword
0000000D 0000000B 00000002 00000002 00000000 00000005 00000015 00000190 00000000 00000060 00000060 - TEXTMETRIC dwords (11)
1E FF 1F 20 - TEXTMETRIC ANSI tchars (4)
00 00 00 27 00 - TEXTMETRIC bytes (5)
00 00 00 68 - mystery bytes (4)
02 0B 06 04 03 05 04 04 02 04 - PANOSE bytes (10)
00 - mystery byte (1)
00000040 - otmfsSelection dword
00000008 00000001 00000000 00000000 00000800 00000008 FFFFFFFE 00000000 00000006 00000003 - misc dwords (30)
FFFFFFF9 0000000B 0000000F FFFFFFFE 0000000B FFFFFFFE 00000000 00000009 00000008 00000007
00000000 00000002 00000008 00000007 00000000 00000005 00000001 00000004 00000001 FFFFFFFF
000000D4 000000DB 000000E2 000000EA - string offsets (4)
54 61 68 6F 6D 61 00 - ANSI sz strings (4)
54 61 68 6F 6D 61 00
52 65 67 75 6C 61 72 00
4D 69 63 72 6F 73 6F 66 74 20 54 61 68 6F 6D 61 20 52 65 67 75 6C 61 72 00
---------------------------------
ANSI, lfHeight = 22
---------------------------------
00000103 - otmSize dword
0000001B 00000016 00000005 00000005 00000000 0000000A 0000002B 00000190 00000000 00000060 00000060 - TEXTMETRIC dwords (11)
1E FF 1F 20 - TEXTMETRIC ANSI tchars (4)
00 00 00 27 00 - TEXTMETRIC bytes (5)
4A 14 00 68 - mystery bytes (4)
02 0B 06 04 03 05 04 04 02 04 - PANOSE bytes (10)
02 - mystery byte (1)
00000040 - otmfsSelection dword
00000008 00000001 00000000 00000000 00000800 00000011 FFFFFFFB 00000001 0000000B 00000006 - misc dwords (30)
FFFFFFF3 00000017 0000001D FFFFFFFB 00000016 FFFFFFFB 00000000 00000009 0000000F 0000000E
00000000 00000003 0000000F 0000000E 00000000 0000000A 00000001 00000007 00000001 FFFFFFFE
000000D4 000000DB 000000E2 000000EA - string offsets (4)
54 61 68 6F 6D 61 00 - ANSI sz strings (4)
54 61 68 6F 6D 61 00
52 65 67 75 6C 61 72 00
4D 69 63 72 6F 73 6F 66 74 20 54 61 68 6F 6D 61 20 52 65 67 75 6C 61 72 00
---------------------------------
UNICODE, lfHeight = 11
---------------------------------
00000136 - otmSize dword
0000000D 0000000B 00000002 00000002 00000000 00000005 00000015 00000190 00000000 00000060 00000060 - TEXTMETRIC dwords (11)
0020 FFFC 001F 0020 - TEXTMETRIC UNICODE tchars (4)
00 00 00 27 00 - TEXTMETRIC bytes (5)
00 00 00 68 - mystery bytes (4)
02 0B 06 04 03 05 04 04 02 04 - PANOSE bytes (10)
00 - mystery byte (1)
00000040 - otmfsSelection dword
00000008 00000001 00000000 00000000 00000800 00000008 FFFFFFFE 00000000 00000006 00000003 - misc dwords (30)
FFFFFFF9 0000000B 0000000F FFFFFFFE 0000000B FFFFFFFE 00000000 00000009 00000008 00000007
00000000 00000002 00000008 00000007 00000000 00000005 00000001 00000004 00000001 FFFFFFFF
000000D8 000000E6 000000F4 00000104 - string offsets (4)
54 00 61 00 68 00 6F 00 6D 00 61 00 00 00 - UNICODE sz strings (4)
54 00 61 00 68 00 6F 00 6D 00 61 00 00 00
52 00 65 00 67 00 75 00 6C 00 61 00 72 00 00 00
4D 00 69 00 63 00 72 00 6F 00 73 00 6F 00 66 00 74 00 20 00 54 00 61 00 68 00 6F 00 6D 00 61 00 20 00 52 00 65 00 67 00 75 00 6C 00 61 00 72 00 00 00
---------------------------------
UNICODE, lfHeight = 22
---------------------------------
00000136 - otmSize dword
0000001B 00000016 00000005 00000005 00000000 0000000A 0000002B 00000190 00000000 00000060 00000060 - TEXTMETRIC dwords (11)
0020 FFFC 001F 0020 - TEXTMETRIC UNICODE tchars (4)
00 00 00 27 00 - TEXTMETRIC bytes (5)
00 00 00 68 - mystery bytes (4)
02 0B 06 04 03 05 04 04 02 04 - PANOSE bytes (10)
00 - mystery byte (1)
00000040 - otmfsSelection dword
00000008 00000001 00000000 00000000 00000800 00000011 FFFFFFFB 00000001 0000000B 00000006 - misc dwords (30)
FFFFFFF3 00000017 0000001D FFFFFFFB 00000016 FFFFFFFB 00000000 00000009 0000000F 0000000E
00000000 00000003 0000000F 0000000E 00000000 0000000A 00000001 00000007 00000001 FFFFFFFE
000000D8 000000E6 000000F4 00000104 - string offsets (4)
54 00 61 00 68 00 6F 00 6D 00 61 00 00 00 - UNICODE sz strings (4)
54 00 61 00 68 00 6F 00 6D 00 61 00 00 00
52 00 65 00 67 00 75 00 6C 00 61 00 72 00 00 00
4D 00 69 00 63 00 72 00 6F 00 73 00 6F 00 66 00 74 00 20 00 54 00 61 00 68 00 6F 00 6D 00 61 00 20 00 52 00 65 00 67 00 75 00 6C 00 61 00 72 00 00 00
---------------------------------
Alignment maybe?
that's what i thought, at first
but the PANOSE structure is always on an odd address - lol
plus, the otmMysteryBytes and otmMysteryByte all get filled with data
i read through a few miles of Panose documentation, and they don't appear to be related
at any rate, by the time you get to otmfsSelection, things ARE dword aligned
it looks like it was by accident :P
one thing i noticed - the GetOutlineTextMetrics function is hardly ever used
i searched the forum for references to the function and the structure - 0 hits
i guess noone could get any useful info out of it - lol
hi,
here the definition from japhet's WinInc -maybe it solves your mystery problem :P:
PANOSE struct
bFamilyType BYTE ?
bSerifStyle BYTE ?
bWeight BYTE ?
bProportion BYTE ?
bContrast BYTE ?
bStrokeVariation BYTE ?
bArmStyle BYTE ?
bLetterform BYTE ?
bMidline BYTE ?
bXHeight BYTE ?
PANOSE ends
TEXTMETRICA struct 8 ;v2.02: alignment changed from 4 to 8
tmHeight SDWORD ?
tmAscent SDWORD ?
tmDescent SDWORD ?
tmInternalLeading SDWORD ?
tmExternalLeading SDWORD ?
tmAveCharWidth SDWORD ?
tmMaxCharWidth SDWORD ?
tmWeight SDWORD ?
tmOverhang SDWORD ?
tmDigitizedAspectX SDWORD ?
tmDigitizedAspectY SDWORD ?
tmFirstChar BYTE ?
tmLastChar BYTE ?
tmDefaultChar BYTE ?
tmBreakChar BYTE ?
tmItalic BYTE ?
tmUnderlined BYTE ?
tmStruckOut BYTE ?
tmPitchAndFamily BYTE ?
tmCharSet BYTE ?
TEXTMETRICA ends
TEXTMETRICW struct 8 ;v2.02: alignment changed from 4 to 8
tmHeight SDWORD ?
tmAscent SDWORD ?
tmDescent SDWORD ?
tmInternalLeading SDWORD ?
tmExternalLeading SDWORD ?
tmAveCharWidth SDWORD ?
tmMaxCharWidth SDWORD ?
tmWeight SDWORD ?
tmOverhang SDWORD ?
tmDigitizedAspectX SDWORD ?
tmDigitizedAspectY SDWORD ?
tmFirstChar WCHAR ?
tmLastChar WCHAR ?
tmDefaultChar WCHAR ?
tmBreakChar WCHAR ?
tmItalic BYTE ?
tmUnderlined BYTE ?
tmStruckOut BYTE ?
tmPitchAndFamily BYTE ?
tmCharSet BYTE ?
TEXTMETRICW ends
OUTLINETEXTMETRICA struct
otmSize DWORD ?
otmTextMetrics TEXTMETRICA <>
otmFiller BYTE ?
otmPanoseNumber PANOSE <>
otmfsSelection DWORD ?
otmfsType DWORD ?
otmsCharSlopeRise DWORD ?
otmsCharSlopeRun DWORD ?
otmItalicAngle DWORD ?
otmEMSquare DWORD ?
otmAscent DWORD ?
otmDescent DWORD ?
otmLineGap DWORD ?
otmsCapEmHeight DWORD ?
otmsXHeight DWORD ?
otmrcFontBox RECT <>
otmMacAscent DWORD ?
otmMacDescent DWORD ?
otmMacLineGap DWORD ?
otmusMinimumPPEM DWORD ?
otmptSubscriptSize POINT <>
otmptSubscriptOffset POINT <>
otmptSuperscriptSize POINT <>
otmptSuperscriptOffset POINT <>
otmsStrikeoutSize DWORD ?
otmsStrikeoutPosition DWORD ?
otmsUnderscoreSize DWORD ?
otmsUnderscorePosition DWORD ?
otmpFamilyName PSTR ?
otmpFaceName PSTR ?
otmpStyleName PSTR ?
otmpFullName PSTR ?
OUTLINETEXTMETRICA ends
OUTLINETEXTMETRICW struct
otmSize DWORD ?
otmTextMetrics TEXTMETRICW <>
otmFiller BYTE ?
otmPanoseNumber PANOSE <>
otmfsSelection DWORD ?
otmfsType DWORD ?
otmsCharSlopeRise DWORD ?
otmsCharSlopeRun DWORD ?
otmItalicAngle DWORD ?
otmEMSquare DWORD ?
otmAscent DWORD ?
otmDescent DWORD ?
otmLineGap DWORD ?
otmsCapEmHeight DWORD ?
otmsXHeight DWORD ?
otmrcFontBox RECT <>
otmMacAscent DWORD ?
otmMacDescent DWORD ?
otmMacLineGap DWORD ?
otmusMinimumPPEM DWORD ?
otmptSubscriptSize POINT <>
otmptSubscriptOffset POINT <>
otmptSuperscriptSize POINT <>
otmptSuperscriptOffset POINT <>
otmsStrikeoutSize DWORD ?
otmsStrikeoutPosition DWORD ?
otmsUnderscoreSize DWORD ?
otmsUnderscorePosition DWORD ?
otmpFamilyName PSTR ?
otmpFaceName PSTR ?
otmpStyleName PSTR ?
otmpFullName PSTR ?
OUTLINETEXTMETRICW ends
qWord
i don't think that solves the problem
if you look at the dumps above, the last bytes of the TEXTMETRIC structure are accounted for
by changing the alignment of TEXTMETRIC, you may get correct results for some values
but, something is going to be out of whack
it is likely that Andreas' method has mis-aligned PANOSE bytes
because we rarely use these values (never), we would not notice the misalignment
You have an old structure,
This one is extrct from SDK 7.1
Quote
OUTLINETEXTMETRICA STRUCT
otmSize DWORD ?
otmTextMetrics TEXTMETRICA <>
otmFiller BYTE ?
otmPanoseNumber PANOSE <>
otmfsSelection DWORD ?
otmfsType DWORD ?
otmsCharSlopeRise DWORD ?
otmsCharSlopeRun DWORD ?
otmItalicAngle DWORD ?
otmEMSquare DWORD ?
otmAscent DWORD ?
otmDescent DWORD ?
otmLineGap DWORD ?
otmsCapEmHeight DWORD ?
otmsXHeight DWORD ?
otmrcFontBox RECT <>
otmMacAscent DWORD ?
otmMacDescent DWORD ?
otmMacLineGap DWORD ?
otmusMinimumPPEM DWORD ?
otmptSubscriptSize POINT <>
otmptSubscriptOffset POINT <>
otmptSuperscriptSize POINT <>
otmptSuperscriptOffset POINT <>
otmsStrikeoutSize DWORD ?
otmsStrikeoutPosition DWORD ?
otmsUnderscoreSize DWORD ?
otmsUnderscorePosition DWORD ?
otmpFamilyName DWORD ?
otmpFaceName DWORD ?
otmpStyleName DWORD ?
otmpFullName DWORD ?
OUTLINETEXTMETRICA ENDS
TEXTMETRICA STRUCT
tmHeight DWORD ?
tmAscent DWORD ?
tmDescent DWORD ?
tmInternalLeading DWORD ?
tmExternalLeading DWORD ?
tmAveCharWidth DWORD ?
tmMaxCharWidth DWORD ?
tmWeight DWORD ?
tmOverhang DWORD ?
tmDigitizedAspectX DWORD ?
tmDigitizedAspectY DWORD ?
tmFirstChar BYTE ?
tmLastChar BYTE ?
tmDefaultChar BYTE ?
tmBreakChar BYTE ?
tmItalic BYTE ?
tmUnderlined BYTE ?
tmStruckOut BYTE ?
tmPitchAndFamily BYTE ?
tmCharSet BYTE ?
TEXTMETRICA ENDS
PANOSE STRUCT
bFamilyType BYTE ?
bSerifStyle BYTE ?
bWeight BYTE ?
bProportion BYTE ?
bContrast BYTE ?
bStrokeVariation BYTE ?
bArmStyle BYTE ?
bLetterform BYTE ?
bMidline BYTE ?
bXHeight BYTE ?
PANOSE ENDS
that's not fixed, Yves :P
there is a real "hint" to notice with this structure
at the end of the struture, the function appends 4 sz strings (unicode or ansi)
the first string has an offset of 0D4h for ANSI and 0D8h for UNICODE
these correspond to structure sizes (the defined part) of 212 and 216 bytes, respectively
the difference is accounted for by the 4 TCHAR's in TEXTMETRIC
these 4 offsets are added to the beginning address of the structure to obtain the string addresses
a good test to see if your structure is properly defined is to display these 4 strings
however, it still may not be correct
display the 10 Panose bytes :U
they will all typically be less than 10h
none of the definitions you have shown me account for these 15 bytes
4A 14 00 68 - mystery bytes (4)
02 0B 06 04 03 05 04 04 02 04 - PANOSE bytes (10)
02 - mystery byte (1)
The structure have differents values with the system.
There is a NEWTEXTMETRICA
Give a function and i can see if there is a problem.
NEWTEXTMETRIC is used for font enumeration - a different structure with a similar name
if you guys don't want to believe me, it's ok :bg
I believe it with a little source code to see what append on different system.
There is also one different alignment for each structure
once you have selected the desired font/size into the hDC.....
INVOKE GetOutlineTextMetrics,hDC,0,0
add eax,3
and eax,-4
sub esp,eax
mov ebx,esp
xchg eax,esi
INVOKE GetOutlineTextMetrics,hDC,esi,ebx
;EBX = address of OUTLINETEXTMETRIC on the stack
;ESI = number of bytes to balance the stack
;use EBX to address and examine the structure here
add esp,esi ;balance the stack when done
if the pointer parm is 0, the function returns the number of bytes required
it's similar to reading a registry value - call it once to get the size, then again to get the data
Yves,
i cleaned up my test program a little bit :lol
it has all kinds of nonsence in it
EDIT: Updated the attachment to demonstrate that appending a dword alignment to the MASM32 structures causes the structure layout to exactly match the layout that the Microsoft C compilers implement.
devae,
the struct definition on msdn is OK - in this case the problem comes from the packing, which is 8 for 32Bit windows. This cause that the TEXTMETRICA-structure has 3 padding bytes at the end. Adding an ALIGN 4 before the member OUTLINETEXTMETRICA.otmFiller and before OUTLINETEXTMETRICA.otmfsSelection should solve the problem in masm.
i would very much like to believe that it is an alignment or packiing issue
however, that does not explain the presence of non-zero data returned in those bytes
4A 14 00 68 - mystery bytes (4)
02 0B 06 04 03 05 04 04 02 04 - PANOSE bytes (10)
02 - mystery byte (1)
according to Feng Yuan, it is an issue where 32-bit structures were carried over from 16-bit OS's (win3.1)
but, if packing was the issue, these bytes would remain unaltered
what it looks like - is that MS had some extra bytes lying around and decided to use them :lol
Quote from: dedndave on August 30, 2011, 06:57:32 PMbut, if packing was the issue, these bytes would remain unaltered
probably the function use internally a local buffer, which is then copied to your buffer.
i hadn't considered that :P
in fact, they may be remnants from the font mapper - matching Panose numbers with other fonts
Information on Windows data alignment, including structure and union layout, is here (http://msdn.microsoft.com/en-us/library/aa290049.aspx).
I updated my attachment here (http://www.masm32.com/board/index.php?topic=17324.msg145390#msg145390) to demonstrate that appending a dword alignment to the MASM32 structures causes the structure layout to exactly match the layout that the Microsoft C compilers implement.
ok - you guys convinced me :bg
Feng Yuan's book gives a pretty good explanation
but, it was more fun to use otmMysteryBytes and otmMysteryByte :P
after running additional tests, i see that these bytes are set to different values on each run
Here what I have made to see if it work ml /Zp4 and no problem
Quote
WndMini proc uses ebx esi edi hwnd:DWORD, uMsg, wParam, lParam
Local hauteur:DWORD,largeur:DWORD,fwSizeType:DWORD
Local Ps:PAINTSTRUCT
align 4
Local outline:OUTLINETEXTMETRIC
Local bufmetric[80h]:BYTE
Local hdc:DWORD,haut,returnsize
Local rect:RECT
Local posX:DWORD,posY:DWORD,hDcCompat,hOldFont
Local retour:DWORD
ZEROLOCALES
mov retour,0
.if uMsg == WM_CREATE
mov ebx,lParam
;mov eax, (CREATESTRUCT ptr [ebx]).hwnd
;mov edx,(CREATESTRUCT ptr [ebx]).hMenu
;suite
;-- la classe doit être en data
mov outline.otmSize,sizeof outline
invoke CreeFont
mov Hfont,eax
invoke SendMessage,hwnd,WM_SETFONT,Hfont,FALSE
INVOKE GetDC,hwnd
mov hDcCompat,eax
INVOKE SelectObject,hDcCompat,Hfont
mov hOldFont,eax
invoke GetOutlineTextMetrics,hDcCompat,0,0
.if eax == 0
invoke Retrieve_Error_Msg,SADR("GetOutlineTextMetrics size")
.endif
mov returnsize,eax
mov edx,0
mov ecx,sizeof outline
div ecx
mov edx,eax ;sizeof outline
invoke GetOutlineTextMetrics,hDcCompat,sizeof outline *2,addr outline
.if eax == 0
invoke Retrieve_Error_Msg,SADR("GetOutlineTextMetrics")
.endif
;get the adress of
lea ebx,outline
mov ecx,[ebx].OUTLINETEXTMETRIC.otmpFaceName
.if ecx != -1
mov eax,ebx
add eax,ecx
;eax adress of the FaceName
.endif
INVOKE ReleaseDC,hwnd,hDcCompat
invoke DeleteObject,Hfont