1. Win32 Font Metrics

Has anyone got Win32 code that returns the width of font characters?

I've written a routine (included at the end of this note), but I'm not sure
what the problem with it is... The values returned from the function are
suspicious, and I suspect that I in addition I have to scale the values by
converting logical units to physical units.

In the Win95 book, Petzold leaves this out. He "cheats" by using the average
character size. I need the character metrics so I can calculate the length
of a string, and be able to display justified text.

Even a pointer to some C or VB code that does this would be a great help.

Thanks.

-- David Cuny

-- begin code --

global constant xGetCharABCWidths =
   linkFunc(gdi32,  "GetCharABCWidthsA",
      {C_POINTER, C_LONG, C_LONG, C_POINTER}, C_POINTER )

-- Type ABC
global constant
    abcA                    = allot( Integer ),
    abcB                    = allot( Integer ),
    abcC                    = allot( Integer ),
    SIZEOF_ABC              = allotted_size()


global function getFontCharSize( integer id )

    sequence widths
    atom hdc, result, abc, ptr

    -- get the device context
    hdc = getDC( id )

    -- set the font
    putFontIntoHDC( hdc, id )

    -- array of chars 1-255
    abc = allocate_struct( SIZEOF_TEXTMETRIC * 255 )

    -- fill with zeros
    widths = repeat( 0, 255 )

    -- get ABC structures for chars 1 through 255
    if not c_func( xGetCharABCWidths, { hdc, 1, 255, abc } ) then
        warnErr( "GetCharABCWidths in getFontCharSize failed." )
    else

        -- starting char to retrieve
        ptr = abc

        -- retrieve values
        for i = 1 to 255 do

            -- width is sum of spacing
            widths[i] = ( fetch( ptr, abcA ) +
                          fetch( ptr, abcB ) +
                          fetch( ptr, abcC ) ) * xScale

            -- advance to next char
            ptr += SIZEOF_ABC

        end for

    end if


    -- cleanup: replace the font
    replaceObject( hdc, DefaultFontID, ForProgram )

    -- cleanup: release the device context
    releaseDC( id )

    -- cleanup: free the structure
    free( abc )

    return widths

end function

-- end code --

new topic     » topic index » view message » categorize

2. Re: Win32 Font Metrics

David

- David Cuny

-- begin code --

----  global constant xGetCharABCWidths =   linkFunc(gdi32,
----- "GetCharABCWidthsA",
-----      {C_POINTER, C_LONG, C_LONG, C_POINTER}, C_POINTER )


You are using two different names in your function ?
There are large number of functions in GDI32.dll
Some are used for fixed fonts.

This is how you get TRUE FONT INFORMATION

-- SYNTAX IS BOOL GetCharABCWidths( hdc, uFirstChar, uLastChar, lpabc )

----- Parameter --------- Type ----------- Description ----------

      hdc                 HDC              Device Context ( handle )

      uFirstChar          UNIT             First character in character
                                           range ( unsigned integer )

      uFirstChar           UNIT             Last character in character
                                           range  ( unsigned integer )

      lpabc               LPABC            Pointer to ABC data structure to
                                           receive the character widths
---------------------------------------------------------------------------

Discription: The GETCharABCWidths function retrieves the character widths of
             the characters for the current font in the range from
             uFirstChar to uFirstChar. lpabc points to a data structure
             of the type ABC that receives the character widths.

             typedef struct _ABC
                 {
                  short abcA;
                  short abcB;
                  short abcC;
                 } ABC;

             The abcA part of structure contains the distance that is added
             to the current position before drawing the character glyph.

             The abcB part of structure contains the the drawn portion
             of the character glyph.

             The abcC part of structure contains the white space on
             the right side of the character glyph.
-------------------------------------------------------------------







-- Type ABCglobal constant    abcA                    = allot( Integer ),
    abcB                    = allot( Integer ),
    abcC                    = allot( Integer ),
    SIZEOF_ABC              = allotted_size()

new topic     » goto parent     » topic index » view message » categorize

3. Re: Win32 Font Metrics

SORRY correcting some typing errors

This is how you get TRUETYPE FONT INFORMATION

-- SYNTAX IS BOOL GetCharABCWidths( hdc, uFirstChar, uLastChar, lpabc )

----- Parameter --------- Type ----------- Description ----------

      hdc                 HDC              Device Context ( handle )

      uFirstChar          UNIT             First character in character
                                           range ( unsigned integer )

      uLastChar           UNIT             Last character in character
                                           range  ( unsigned integer )

      lpabc               LPABC            Pointer to ABC data structure to
                                           receive the character widths
---------------------------------------------------------------------------

Discription: The GETCharABCWidths function retrieves the character widths of
             the characters for the current font in the range from
             uFirstChar to uLastChar. lpabc points to a data structure
             of the type ABC that receives the character widths.

Bernie

new topic     » goto parent     » topic index » view message » categorize

4. Re: Win32 Font Metrics

At 08:16 PM 25-02-1999 , you wrote:
>Has anyone got Win32 code that returns the width of font characters?
>
>I've written a routine (included at the end of this note), but I'm not sure
>what the problem with it is... The values returned from the function are
>suspicious, and I suspect that I in addition I have to scale the values by
>converting logical units to physical units.
>
>In the Win95 book, Petzold leaves this out. He "cheats" by using the average
>character size. I need the character metrics so I can calculate the length
>of a string, and be able to display justified text.
>
>Even a pointer to some C or VB code that does this would be a great help.
>
>Thanks.

Take a look to GetTextExtentPoint32 in gdi32.dll it may be the answer :)

Syntax:

BOOL GetTextExtentPoint32(
        HDC  DC,
        LPCTSTR  Str,
        int  Count,
        LPSIZE  Size
        );

Description:

This function retrieves the width and height of the string pointed by the
Str parameter, in logical units. The width and height are based on the
attributes of the string currently selected into the device context
identified by the DC parameter. The clipping region of the specified device
context does not affect the computed dimensions. In instances where a
string containing kerning pairs is output to a device supporting character
kerning, the dimernsions returned by this function may not match the sum of
the individual character dimensions in the string.


Parameters:

DC: A handle to the device context whose currently selected font is used to
determine the string's width and height.

Str: A pointer to a string whose width and height are to be retrieved. This
does not have to be a null-terminated string, as the Count parameter
specifies the string length.

Count: Specifies the number of characters in the string pointed to by the
Str parameter.

Size: A pointer to a SIZE structure that recieves the width and height of
the specified string based on the attributes of the font selected into the
specified device context.

Return value:

If the function succeeds, it return TRUE; otherwise it returns FALSE. To
get extended error information, call the GetLastError function.

The SIZE structure is as follows:

typedef struct tagSIZE {
        LONG cx;
        LONG cy;
} SIZE;

The SIZE structure specifies the width and height of a rectangle.

cx: Specifies the rectangle's width.
cy: Specifies the rectangle's height.


Here is an untested attemp (I assume your GDI functions, never have looked
at them):

[please wait for the beep... beeeep!]

global constant xGetTextExtentPoint32 =
        linkFunc(gdi32,  "GetTextExtentPoint32", -- Maybe need 'A' extension?
          {C_POINTER, C_POINTER, C_INT, C_POINTER}, C_INT )

global function getFontTextSize( integer id, sequence str )
        sequence size
        atom hdc, pstr, psize

        size = {0,0}

        -- Allocate LPSTRZ
        pstr = allocate_string(str)
        if not pstr then
                warnErr( "allocate_string in getFontTextSize failed." )
                return size
        end if

        -- Allocate SIZE structure
        psize = allocate(8)
        if not psize then
                warnErr( "allocate in getFontTextSize failed." )
                free(pstr)
                return size
        end if

        -- get the device context
        hdc = getDC( id )

        -- set the font
        putFontIntoHDC( hdc, id )

        -- Get text dimensions
if not c_func( xGetTextExtentPoint32, { hdc, pstr, length(str), psize }
        )
then
                warnErr( "GetTextExtentPoint32 in getFontTextSize failed." )
                size = peek4s({psize, 2})
        end if

        -- Cleanup
        replaceObject( hdc, DefaultFontID, ForProgram )
        releaseDC( id )
        free( psize )
        free( pstr )

        -- Return {cx,cy} sequence
        return size

end function

[tut, tut, tut...]

The returned dimensions are in logical units. Use the LPtoDP API function
to convert them to device units.

Hope this helps.


Regards,
         Daniel  Berstein
         [daber at pair.com]

new topic     » goto parent     » topic index » view message » categorize

Search



Quick Links

User menu

Not signed in.

Misc Menu