Page 1 of 2

CatchFont()

Posted: Sat Feb 27, 2016 12:20 am
by IdeasVacuum
We have:
CatchImage
CatchMusic
CatchSound
CatchSprite
CatchXML
CatchJSON

So why not CatchFont() too? It is sometimes the case that only a specific Font is just right, and 1000s of OpenSource fonts are freely available.

Re: CatchFont()

Posted: Sat Feb 27, 2016 7:51 am
by Bisonte
I agree since years ;)

+1

Re: CatchFont()

Posted: Sat Feb 27, 2016 8:16 am
by davido
+1
Perhaps there's a Catch?

Re: CatchFont()

Posted: Sat Feb 27, 2016 8:25 am
by Keya
is it possible to load a font if it's not an on disk file (do the os api support that)? that might be the catch

Re: CatchFont()

Posted: Sat Feb 27, 2016 1:12 pm
by IdeasVacuum
It's certainly possible on WindowsOS and MAC.

Re: CatchFont()

Posted: Sun Feb 28, 2016 8:28 am
by Danilo
IdeasVacuum wrote:It's certainly possible on WindowsOS and MAC.
Example code?

Re: CatchFont()

Posted: Sun Feb 28, 2016 8:47 am
by Fred
Seems not possible on Linux (just checked)

Re: CatchFont()

Posted: Sun Feb 28, 2016 8:53 am
by wilbert
Danilo wrote:
IdeasVacuum wrote:It's certainly possible on WindowsOS and MAC.
Example code?
I have no code example but on OSX you can use ATSFontActivateFromMemory() or on OSX 10.8+ the combination of CGFontCreateWithDataProvider() with CTFontManagerRegisterGraphicsFont()

Re: CatchFont()

Posted: Sun Feb 28, 2016 1:20 pm
by IdeasVacuum
For Windows see Rashad's example using AddFontMemResourceEx()

Re: CatchFont()

Posted: Sun Feb 28, 2016 1:35 pm
by Danilo
wilbert wrote:
Danilo wrote:
IdeasVacuum wrote:It's certainly possible on WindowsOS and MAC.
Example code?
I have no code example
Very helpful.

Re: CatchFont()

Posted: Sun Feb 28, 2016 3:32 pm
by wilbert
Danilo wrote:Very helpful.
Thanks :)

Here's also a code example; works for .ttf and .otf fonts.

Code: Select all

ImportC ""
  ATSFontActivateFromMemory(*data, length, context, format, reserved, options, *container)
  ATSFontDeactivate(container, refCon, options)
  ATSFontFindFromContainer(container, options, count, *oArray, *count)
  ATSFontGetPostScriptName(font, options, *name)
EndImport

Procedure CatchFont(Font, *MemoryAddress, Size, Height = 12)
  Protected.i result, container, count, atsfont, name
  ATSFontActivateFromMemory(*MemoryAddress, Size, 0, 0, 0, 0, @container)
  If container = 0
    ProcedureReturn 0
  EndIf
  ATSFontFindFromContainer(container, 0, 0, 0, @count)
  If count = 0
    ATSFontDeactivate(container, 0, 0)
    ProcedureReturn 0
  EndIf
  ATSFontFindFromContainer(container, 0, 1, @atsfont, 0)
  If atsfont = 0
    ATSFontDeactivate(container, 0, 0)
    ProcedureReturn 0
  Else
    ATSFontGetPostScriptName(atsfont, 0, @name)
    result = LoadFont(Font, PeekS(CocoaMessage(0, name, "UTF8String"), -1, #PB_UTF8), Height)
    CFRelease_(name)
    ProcedureReturn result
  EndIf
EndProcedure


DataSection
  FontStart:
  IncludeBinary "OpenSans-LightItalic.ttf"
  FontEnd:
EndDataSection

myFont = CatchFont(#PB_Any, ?FontStart, ?FontEnd - ?FontStart)
Debug myFont

End

Re: CatchFont()

Posted: Mon Feb 29, 2016 2:53 am
by IdeasVacuum
I really don't know anything about Linux OS. The following code can be used to extract the embedded font to the hard drive. On Windows OS, the Font Mapper is updated with function AddFontResource(). Does Linux have a similar mechanism? Could the drive be a small ram disc created via API?
http://www.fontsquirrel.com

Code: Select all

Enumeration
#Win
#Ed
#FontFile
#Font
EndEnumeration

Define  sThisApp.s = ProgramFilename()
Define     sPath.s = GetPathPart(sThisApp)  ;or other path specifically required by OS
Define sFontFile.s = sPath + "BRUSHSTP.ttf"

If OpenFile(#FontFile, sFontFile)

       WriteData(#FontFile, ?FontStart, (?FontEnd - ?FontStart))
       CloseFile(#FontFile)

       ;Windows API
       AddFontResource_(sFontFile)
           SendMessage_(#HWND_BROADCAST,#WM_FONTCHANGE, #Null, #Null)
EndIf

LoadFont(#Font, "Brushstroke Plain", 36, #PB_Font_HighQuality)

If OpenWindow(#Win, 0, 0, 400, 200, "Embedded Font", #PB_Window_SystemMenu | #PB_Window_ScreenCentered)

        EditorGadget(#Ed, 10, 10, 380, 180)
       SetGadgetFont(#Ed, FontID(#Font))

       SetGadgetText(#Ed, "Brushstroke Plain True Type Font")

       Repeat
       Until WaitWindowEvent(1) = #PB_Event_CloseWindow
EndIf

DataSection
FontStart:
  IncludeBinary "C:\OpenSourceFonts\BRUSHSTP.ttf"
FontEnd:
EndDataSection

Re: CatchFont()

Posted: Mon Feb 29, 2016 7:06 am
by tj1010
Not without some format loaders and some weird licensing conflicts which fonts are long known for.

There is such thing as bitmap fonts though.

Re: CatchFont()

Posted: Tue Mar 01, 2016 5:53 am
by Danilo
wilbert wrote:Here's also a code example; works for .ttf and .otf fonts.

Code: Select all

ImportC ""
  ATSFontActivateFromMemory(*data, length, context, format, reserved, options, *container)
  ATSFontDeactivate(container, refCon, options)
  ATSFontFindFromContainer(container, options, count, *oArray, *count)
  ATSFontGetPostScriptName(font, options, *name)
EndImport

Procedure CatchFont(Font, *MemoryAddress, Size, Height = 12)
  Protected.i result, container, count, atsfont, name
  ATSFontActivateFromMemory(*MemoryAddress, Size, 0, 0, 0, 0, @container)
  If container = 0
    ProcedureReturn 0
  EndIf
  ATSFontFindFromContainer(container, 0, 0, 0, @count)
  If count = 0
    ATSFontDeactivate(container, 0, 0)
    ProcedureReturn 0
  EndIf
  ATSFontFindFromContainer(container, 0, 1, @atsfont, 0)
  If atsfont = 0
    ATSFontDeactivate(container, 0, 0)
    ProcedureReturn 0
  Else
    ATSFontGetPostScriptName(atsfont, 0, @name)
    result = LoadFont(Font, PeekS(CocoaMessage(0, name, "UTF8String"), -1, #PB_UTF8), Height)
    CFRelease_(name)
    ProcedureReturn result
  EndIf
EndProcedure


DataSection
  FontStart:
  IncludeBinary "OpenSans-LightItalic.ttf"
  FontEnd:
EndDataSection

myFont = CatchFont(#PB_Any, ?FontStart, ?FontEnd - ?FontStart)
Debug myFont

End
Thanks, wilbert! Unfortunately it seems to have some (typical) problems with font names.
Example font: http://www.fontspace.com/allen-r-walden/crystal

ATSFontGetPostScriptName() returns "CrystalItalic-" and it does not work.
ATSFontGetName() returns "Crystal Italic" and it does not work.

In both cases a valid ID is returned, but the standard font is used instead.

If I change your procedure to use the string "Crystal" for LoadFont(), it's okay.
Maybe it's better to add a new parameter 'fontName.s' to CatchFont().

Re: CatchFont()

Posted: Tue Mar 01, 2016 7:10 am
by wilbert
Danilo wrote:If I change your procedure to use the string "Crystal" for LoadFont(), it's okay.
Maybe it's better to add a new parameter 'fontName.s' to CatchFont().
I wanted to simulate the Catch procedure like other Catch procedures PB offers.
You are right it doesn't work with this font. :(
I also tried it with the OSX 10.8+ CTFontManagerRegisterGraphicsFont approach but same results.
Unfortunately I don't know what function Fred uses to load the font.
Adding a name to the procedure would be possible but in that case it's easier just to register the font and use LoadFont after that.
In that case the only required function would be ATSFontActivateFromMemory.