Jump to content

[Like solved] GDI+ and .ttf files


Recommended Posts

Is it possible to load .ttf font files and use from GDI+?

This does NOT work:

$hFamily = _GDIPlus_FontFamilyCreate (@ScriptDir & "\VeraMoBd.ttf")
Edited by AdmiralAlkex
Link to comment
Share on other sites

  • Moderators

AdmiralAlkex,

Take a look here - does it help? :blink:

M23

Public_Domain.png.2d871819fcb9957cf44f4514551a2935.png Any of my own code posted anywhere on the forum is available for use by others without any restriction of any kind

Open spoiler to see my UDFs:

Spoiler

ArrayMultiColSort ---- Sort arrays on multiple columns
ChooseFileFolder ---- Single and multiple selections from specified path treeview listing
Date_Time_Convert -- Easily convert date/time formats, including the language used
ExtMsgBox --------- A highly customisable replacement for MsgBox
GUIExtender -------- Extend and retract multiple sections within a GUI
GUIFrame ---------- Subdivide GUIs into many adjustable frames
GUIListViewEx ------- Insert, delete, move, drag, sort, edit and colour ListView items
GUITreeViewEx ------ Check/clear parent and child checkboxes in a TreeView
Marquee ----------- Scrolling tickertape GUIs
NoFocusLines ------- Remove the dotted focus lines from buttons, sliders, radios and checkboxes
Notify ------------- Small notifications on the edge of the display
Scrollbars ----------Automatically sized scrollbars with a single command
StringSize ---------- Automatically size controls to fit text
Toast -------------- Small GUIs which pop out of the notification area

 

Link to comment
Share on other sites

You mean post #8, right? It sounds right but I can't get it to work. Could you give it a try with VeraMoBd.ttf from here?

Edit: I see that _GDIPlus_GraphicsDrawStringEx returns False but I don't know why :blink:

Edited by AdmiralAlkex
Link to comment
Share on other sites

Could you give it a try with VeraMoBd.ttf from here?

VeraMoBd.ttf is not present in the archive, but look at comments from the code.

#Include <GDIPlus.au3>

$hGUI = GUICreate('GDI+', 400, 200)
GUISetState()

$sString = 'Hello world'

_GDIPlus_Startup()
$hGraphic = _GDIPlus_GraphicsCreateFromHWND($hGUI)
$hBrush = _GDIPlus_BrushCreateSolid(0xFF00007F)
$hFormat = _GDIPlus_StringFormatCreate()
$hCollection = DllCall($ghGDIPDll, 'int', 'GdipNewPrivateFontCollection', 'ptr*', 0)
$hCollection = $hCollection[1]
DllCall($ghGDIPDll, 'int', 'GdipPrivateAddFontFile', 'ptr', $hCollection, 'wstr', @ScriptDir & '\FreeMonoBold.ttf')
$hFamily = DllCall($ghGDIPDll, 'int', 'GdipCreateFontFamilyFromName', 'wstr', 'FreeMono', 'ptr', $hCollection, 'ptr*', 0) ; (!) "FreeMono" - Font name
$hFamily = $hFamily[3]
$hFont = _GDIPlus_FontCreate($hFamily, 36, 1) ; (!) 1 - Bold
$tLayout = _GDIPlus_RectFCreate(28, 72, 0, 0)
_GDIPlus_GraphicsDrawStringEx($hGraphic, $sString, $hFont, $tLayout, $hFormat, $hBrush)
_GDIPlus_FontDispose($hFont)
_GDIPlus_FontFamilyDispose($hFamily)
DllCall($ghGDIPDll, 'int', 'GdipDeletePrivateFontCollection', 'ptr*', $hCollection)
_GDIPlus_StringFormatDispose($hFormat)
_GDIPlus_BrushDispose($hBrush)
_GDIPlus_GraphicsDispose($hGraphic)
_GDIPlus_Shutdown()

Do
Until GUIGetMsg() = -3
Edited by Yashied
Link to comment
Share on other sites

VeraMoBd.ttf is not present in the archive, but look at comments from the code.

Sorry I gave the wrong link. VeraMoBd.ttf is from Bitstream Vera Fonts.

I realize now what the error is, I didn't understand I had to manually set the Bold property in _GDIPlus_FontCreate() for using a "Bold" font. Adding that and it works here.

But this does give me another problem. My hope was to let the end-user choose font, but that seems impossible? Or can i somehow extract from the .ttf if it is bold etc?

FontGetStyle() Anyone?

Link to comment
Share on other sites

Link to comment
Share on other sites

Sorry I gave the wrong link. VeraMoBd.ttf is from Bitstream Vera Fonts.

I realize now what the error is, I didn't understand I had to manually set the Bold property in _GDIPlus_FontCreate() for using a "Bold" font. Adding that and it works here.

But this does give me another problem. My hope was to let the end-user choose font, but that seems impossible? Or can i somehow extract from the .ttf if it is bold etc?

FontGetStyle() Anyone?

Funny you ask that. I wrote this some time ago:

#include <Array.au3>


Global $sFontData = FileRead("FreeMono.ttf") ; <- your font here (full path maybe)

; FONT METRICS:
Global $aArray = _RH_TTF_GetFontMetrics($sFontData)

_ArrayDisplay($aArray)


; INFO:
$aArray = _RH_TTF_GetInfo($sFontData)

; Col 0 = Property Name
; Col 1 = ANSI
; Col 2 = Unicode
_ArrayDisplay($aArray)



Func _RH_TTF_GetInfo($bBinary)
    Local $tBinary = DllStructCreate("byte[" & BinaryLen($bBinary) & "]")
    DllStructSetData($tBinary, 1, $bBinary)
    Local $pBinary = DllStructGetPtr($tBinary)
    Local $pPointer = $pBinary
    Local $tTT_OFFSET_TABLE = DllStructCreate("word MajorVersion;" & _
            "word MinorVersion;" & _
            "word NumOfTables;" & _
            "word SearchRange;" & _
            "word EntrySelector;" & _
            "word RangeShift;", _
            $pPointer)
    $pPointer += 12
    If DllStructGetData($tTT_OFFSET_TABLE, "MajorVersion") <> 256 And DllStructGetData($tTT_OFFSET_TABLE, "MinorVersion") <> 0 Then
        Return SetError(1, 0, 0)
    EndIf
    Local $iNumOfTables = 265 * BitAND(DllStructGetData($tTT_OFFSET_TABLE, "NumOfTables"), 0xF) + BitShift(DllStructGetData($tTT_OFFSET_TABLE, "NumOfTables"), 8)
    Local $iOffset
    Local $tTT_TABLE_DIRECTORY
    For $i = 1 To $iNumOfTables
        $tTT_TABLE_DIRECTORY = DllStructCreate("char Tag[4];" & _
                "dword CheckSum;" & _
                "dword Offset;" & _
                "dword Length;", _
                $pPointer)
        $pPointer += 16
        If DllStructGetData($tTT_TABLE_DIRECTORY, "Tag") == "name" Then
            $iOffset = _RH_BigEndianToInt(DllStructGetData($tTT_TABLE_DIRECTORY, "Offset"), 4)
            ExitLoop
        EndIf
    Next
    If Not $iOffset Then Return SetError(2, 0, 0)
    $pPointer = $pBinary + $iOffset
    Local $pDir = $pPointer
    Local $tTT_NAME_TABLE_HEADER = DllStructCreate("word FSelector;" & _
            "word NRCount;" & _
            "word StorageOffset;", _
            $pPointer)
    $pPointer += 6
    Local $iNRCount = _RH_BigEndianToInt(DllStructGetData($tTT_NAME_TABLE_HEADER, "NRCount"), 2)
    Local $iStorageOffset = _RH_BigEndianToInt(DllStructGetData($tTT_NAME_TABLE_HEADER, "StorageOffset"), 2)
    Local $aInfo[28][3] = [["Copyright notice"],["Font Name"],["Subfamily Name"],["Identifier"],["Full Font Name"],["Version"],["Postscript Name"],["Trademark"],["Manufacturer"],["Designer"],["Description"],["URL Vendor"], _
            ["URL Designer"],["License Description"],["License Info URL"],["Reserved Field "],["Preferred Family"],["Preferred Subfamily"],["Compatible Full"],["Sample text"],["PostScript CID Findfont Name"],["WWS Family Name"],["WWS Subfamily Name"]]
    Local $tTT_NAME_RECORD, $bString, $iNameID, $iPlatform
    Local $iLangID = -1
    For $i = 1 To $iNRCount
        $tTT_NAME_RECORD = DllStructCreate("word PlatformID;" & _
                "word EncodingID;" & _
                "word LanguageID;" & _
                "word NameID;" & _
                "word StringLength;" & _
                "word StringOffset;", _
                $pPointer)
        $pPointer += 12 ; size of $tTT_NAME_RECORD
        $bString = DllStructGetData(DllStructCreate("byte[" & _RH_BigEndianToInt(DllStructGetData($tTT_NAME_RECORD, "StringLength"), 2) & "]", $pDir + $iStorageOffset + _RH_BigEndianToInt(DllStructGetData($tTT_NAME_RECORD, "StringOffset"), 2)), 1)
        $iNameID = _RH_BigEndianToInt(DllStructGetData($tTT_NAME_RECORD, "NameID"), 2)
        $iPlatform = _RH_BigEndianToInt(DllStructGetData($tTT_NAME_RECORD, "PlatformID"), 2)
        If $iNameID < 23 Then
            If $iPlatform = 1 Then
                $aInfo[$iNameID][1] = _RH_FormatStringEllipsis(BinaryToString($bString), 100)
            ElseIf $iPlatform = 3 Then
                If $iLangID = -1 And $iNameID = 0 Then $iLangID = _RH_BigEndianToInt(DllStructGetData($tTT_NAME_RECORD, "LanguageID"), 2)
                If _RH_BigEndianToInt(DllStructGetData($tTT_NAME_RECORD, "LanguageID"), 2) = $iLangID Then $aInfo[$iNameID][2] = _RH_FormatStringEllipsis(BinaryToString($bString, 3), 100)
            EndIf
        EndIf
    Next
    Return $aInfo
EndFunc   ;==>_RH_TTF_GetInfo

Func _RH_TTF_GetFontMetrics($bBinary)
    Local $tBinary = DllStructCreate("byte[" & BinaryLen($bBinary) & "]")
    DllStructSetData($tBinary, 1, $bBinary)
    Local $pBinary = DllStructGetPtr($tBinary)
    Local $pPointer = $pBinary
    Local $tTT_OFFSET_TABLE = DllStructCreate("word MajorVersion;" & _
            "word MinorVersion;" & _
            "word NumOfTables;" & _
            "word SearchRange;" & _
            "word EntrySelector;" & _
            "word RangeShift;", _
            $pPointer)
    $pPointer += 12
    If DllStructGetData($tTT_OFFSET_TABLE, "MajorVersion") <> 256 And DllStructGetData($tTT_OFFSET_TABLE, "MinorVersion") <> 0 Then Return SetError(1, 0, 0)
    Local $iNumOfTables = 265 * BitAND(DllStructGetData($tTT_OFFSET_TABLE, "NumOfTables"), 0xF) + BitShift(DllStructGetData($tTT_OFFSET_TABLE, "NumOfTables"), 8)
    Local $iOffset
    Local $tTT_TABLE_DIRECTORY
    For $i = 1 To $iNumOfTables
        $tTT_TABLE_DIRECTORY = DllStructCreate("char Tag[4];" & _
                "dword CheckSum;" & _
                "dword Offset;" & _
                "dword Length;", _
                $pPointer)
        $pPointer += 16
        If DllStructGetData($tTT_TABLE_DIRECTORY, "Tag") == "OS/2" Then
            $iOffset = _RH_BigEndianToInt(DllStructGetData($tTT_TABLE_DIRECTORY, "Offset"), 4)
            ExitLoop
        EndIf
    Next
    If Not $iOffset Then Return SetError(2, 0, 0)
    $pPointer = $pBinary + $iOffset
    Local $tFontMetrics = DllStructCreate("align 1;word Version;" & _
            "short AvgCharWidth;" & _
            "word WeightClass;" & _
            "word WidthClass;" & _
            "word Type;" & _
            "short SubscriptXSize;" & _
            "short SubscriptYSize;" & _
            "short SubscriptXOffset;" & _
            "short SubscriptYOffset;" & _
            "short SuperscriptXSize;" & _
            "short SuperscriptYSize;" & _
            "short SuperscriptXOffset;" & _
            "short SuperscriptYOffset;" & _
            "short StrikeoutSize;" & _
            "short StrikeoutPosition;" & _
            "short FamilyClass;" & _
            "byte Panose[10];" & _
            "dword UnicodeRange1;" & _ ;
            "dword UnicodeRange2;" & _
            "dword UnicodeRange3;" & _ ;
            "dword UnicodeRange4;" & _
            "char VendID[4];" & _
            "word Selection;" & _
            "word FirstCharIndex;" & _
            "word LastCharIndex;" & _
            "short TypoAscender;" & _
            "short TypoDescender;" & _
            "short TypoLineGap;" & _
            "word WinAscent;" & _
            "word WinDescent;" & _
            "dword CodePageRange1;" & _
            "dword CodePageRange2;", _
            $pPointer)
    Local $aArray[7][2] = [["Name", ""], _
            ["Height", 10], _ ; Height ; FIXME: Where is this data stored?
            ["Weight", _RH_BigEndianToInt(DllStructGetData($tFontMetrics, "WeightClass"))], _ ; Weight
            ["Italic", BitAND(DllStructGetData($tFontMetrics, "Selection"), 1) = True], _ ; Italic
            ["Underline", BitAND(BitShift(DllStructGetData($tFontMetrics, "Selection"), 1), 1) = True], _ ; Underline
            ["StrikeOut", BitAND(BitShift(DllStructGetData($tFontMetrics, "Selection"), 4), 1) = True], _ ; StrikeOut
            ["CharSet", 1]] ; CharSet ; Forcing default DEFAULT_CHARSET ; FIXME: Where is this data stored?
    Return $aArray
EndFunc   ;==>_RH_TTF_GetFontMetrics

Func _RH_BigEndianToInt($iValue, $iSize = 2)
    Return Dec(Hex(BinaryMid($iValue, 1, $iSize)))
EndFunc   ;==>_RH_BigEndianToInt

Func _RH_FormatStringEllipsis($sString, $iNumChars)
    Local $iLen = StringLen($sString)
    If $iLen <= $iNumChars Then Return $sString
    Return StringLeft($sString, $iNumChars - 3) & "..."
EndFunc   ;==>_RH_FormatStringEllipsis

_RH_ means Resource Hacker. I should really update that script :blink:

... No, will wait more.

♡♡♡

.

eMyvnE

Link to comment
Share on other sites

@trancexx

Nice code!

:blink:

@AdmiralAlkex

Using Authenticity's GDIP.au3.

#Include <GDIP.au3>

$hGUI = GUICreate('GDI+', 500, 300)
GUISetState()

$sFont = FileOpenDialog('Browse', @ScriptDir, 'Font Files (*.ttf)|All Files (*.*)', 1 + 2, '', $hGUI)
If Not $sFont Then
    Exit
EndIf

_GDIPlus_Startup()
$hGraphic = _GDIPlus_GraphicsCreateFromHWND($hGUI)
$hBrush = _GDIPlus_BrushCreateSolid(0xFF00007F)
$hFormat = _GDIPlus_StringFormatCreate()
$hCollection = _GDIPlus_PrivateCollectionCreate()
_GDIPlus_PrivateCollectionAddFontFile($hCollection, $sFont)
$aList = _GDIPlus_FontCollectionGetFamilyList($hCollection)
$hFamily = DllCall($ghGDIPDll, 'int', 'GdipCreateFontFamilyFromName', 'wstr', _GDIPlus_FontFamilyGetFamilyName($aList[1]), 'ptr', $hCollection, 'ptr*', 0)
$hFamily = $hFamily[3]
$iStyle = 0
For $i = 0 To 2
    If _GDIPlus_FontFamilyIsStyleAvailable($hFamily, $i) Then
        $iStyle = $i
        ExitLoop
    EndIf
Next
$hFont = _GDIPlus_FontCreate($hFamily, 36, $iStyle)
$tLayout = _GDIPlus_RectFCreate(10, 10, 0, 0)
_GDIPlus_GraphicsDrawStringEx($hGraphic, 'Hello world', $hFont, $tLayout, $hFormat, $hBrush)
_GDIPlus_FontDispose($hFont)
_GDIPlus_FontFamilyDispose($hFamily)
;_GDIPlus_PrivateFontCollectionDispose($hCollection) ; (!) error, replace "hwnd" to "hwnd*"
_GDIPlus_StringFormatDispose($hFormat)
_GDIPlus_BrushDispose($hBrush)
_GDIPlus_GraphicsDispose($hGraphic)
_GDIPlus_Shutdown()

Do
Until GUIGetMsg() = -3
Edited by Yashied
Link to comment
Share on other sites

That's awesome of you two, just two questions:

1. arialbi.ttf (Arial Bold Italic (stole it from Windows\Fonts folder)) doesn't work with your script Yashied.

Okay that was just one question. Actually more a statement than a question.

_GDIPlus_FontFamilyIsStyleAvailable only returns 0 for some reason on that font. Any idea?

Link to comment
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now
 Share

  • Recently Browsing   0 members

    • No registered users viewing this page.
×
×
  • Create New...