[bb] Get TTF Font File Data by pantsonhead.com [ 1+ years ago ]

Started by BlitzBot, June 29, 2017, 00:28:42

Previous topic - Next topic

BlitzBot

Title : Get TTF Font File Data
Author : pantsonhead.com
Posted : 1+ years ago

Description : This include file will give you a function that lets you get data stored in any TTF file.

Now you can read the proper fontname directly from Blitz. :)


Code :
Code: blitzbasic
;   Example for BlitzPlus
;	Include "GetTTFdata.bb"
;	filename$=RequestFile$( "Select a TTF file","ttf" )
;	Print filename$
;	For x = 0 To 7
;		fontdata$=GetTTFdata$(filename$,x)
;		Print x+"="+fontdata$
;	Next
;	WaitKey()


;	datatypes
;   gfiCopyrightNotice = 0	; Copyright notice
;   gfiFontFamilyName = 1	; Font Family name
;   gfiFontSubfamilyName = 2	; Font Style (usually)
;   gfiUniqueFontIdentifier = 3 ; Some unique ID For this font.
;   gfiFullFontName = 4   	; combination of strings 1 And 2. Exception: 
;   gfiVersionString = 5  	; Version String (sometime includes a date). 
;   gfiPostscriptName = 6 	; Postscript name.
;   gfiTrademark = 7      	; Trademark notice/information.


Function GetTTFdata$(filename$, datatype=1)

	;Create Banks
	bnkTableOffsets = CreateBank(12)
	   
	; Open the file to read from 
	FontName$=""
	If Lower(Right(Trim(filename$),4))=".ttf" And FileType(filename$)=1 Then

		fontfile=ReadFile(filename$) 
		
		;Read the OffSetTable
		ReadBytes bnkTableOffsets,fontfile,0,12 
		For i = 0 To PeekShort(bnkTableOffsets,5)-1
			SeekFile(fontfile,12+i*16)
			word$=""
			For x = 1 To 4
				word$=word$+Chr$(ReadByte(fontfile))
			Next
			If Lower(word$)="name" Then
				ChkSum=Int_SwapEndian%(ReadInt(fontfile))
				Offset=Int_SwapEndian%(ReadInt(fontfile))
				Length=Int_SwapEndian%(ReadInt(fontfile))
			ElseIf Lower(word$)="cmap" Then
				cmapChkSum=Int_SwapEndian%(ReadInt(fontfile))
				cmapOffset=Int_SwapEndian%(ReadInt(fontfile))
				cmapLength=Int_SwapEndian%(ReadInt(fontfile))
				SeekFile(fontfile,cmapOffset)
				TableVersion = Short_SwapEndian%(ReadShort(fontfile))
				TableCount = Short_SwapEndian%(ReadShort(fontfile))
				PlatformID = Short_SwapEndian%(ReadShort(fontfile))
				EncodingID = Short_SwapEndian%(ReadShort(fontfile))
				cmapSubOffset=Int_SwapEndian%(ReadInt(fontfile))
				SeekFile(fontfile,cmapSubOffset)
				cmapFormat=Short_SwapEndian%(ReadShort(fontfile))
				words$=Words$+"|"+cmapOffset+">"+cmapFormat
			EndIf

			words$=Words$+"|"+word$
		Next
		
		
		;now we find the Correct Name Record
		SeekFile(fontfile,offset)
		FormatSelector=Short_SwapEndian%(ReadShort(fontfile))
		NumberNameRecords=Short_SwapEndian%(ReadShort(fontfile))
		StorageOffset= Short_SwapEndian%(ReadShort(fontfile))
		
		;loop thru NameRecords
		While (NameID<>datatype) And  (Eof(fontfile) <>1)
			PlatformID = Short_SwapEndian%(ReadShort(fontfile))
			EncodingID = Short_SwapEndian%(ReadShort(fontfile))
			LanguageID = Short_SwapEndian%(ReadShort(fontfile))
			NameID = Short_SwapEndian%(ReadShort(fontfile))
			
			If NameID=datatype	;This is what we're looking for
				NameLength = Short_SwapEndian%(ReadShort(fontfile))
				NameOffset = Short_SwapEndian%(ReadShort(fontfile))
			Else
				junk = ReadInt(fontfile) ;NameLength + NameOffset 
			EndIf
	 	Wend
 
		;Now we can get the data
		SeekFile(fontfile,offset+StorageOffset+NameOffset)
		For x = 1 To NameLength
			newChar=ReadByte(fontfile)
			If newChar<>0 Then fontdata$=fontdata$+ Chr$(newChar) ;filters unicode chr(0)s
		Next
		Return fontdata$
		CloseFile(fontfile)
	EndIf
	FreeBank bnkTableOffsets

End Function

; We use these for "ByteSwapping" since TTF format is other endian
Function Int_SwapEndian%(n%) 
	Return ((n And $FF) Shl 24) Or ((n And $FF00) Shl 8) Or ((n And $FF0000) Shr 8) Or ((n And $FF000000) Shr 24) 
End Function 

Function Short_SwapEndian%(n%) 
	Return ((n And $FF) Shl 8) Or ((n And $FF00) Shr 8) 
End Function


Comments :


big10p(Posted 1+ years ago)

 This has saved me a LOAD of work. Thanks a lot! :)[edit] This has a memory leak - you're returning from the function before closing the file and freeing the bank. Easily fixed, though. :)BTW, does datatype 0 (copyright notice) ever return anything?