LoadFont / IsFont funktioniert nicht ...

Anfängerfragen zum Programmieren mit PureBasic.
DarkDragon
Beiträge: 6291
Registriert: 29.08.2004 08:37
Computerausstattung: Hoffentlich bald keine mehr
Kontaktdaten:

Re: LoadFont / IsFont funktioniert nicht ...

Beitrag von DarkDragon »

Borstensohn hat geschrieben: 01.11.2023 21:42 Dieser Thread ist zwar uralt, aber da ich eine sehr ähnliche Frage habe, möchte ich keinen neuen eröffnen.

Bei mir werden unter GNU/LInux, genauer: Xubuntu 23.10, Schriften nicht aus einem Ordner im Programmverzeichnis geladen, auch nicht aus dem Programmverzeichnis direkt (die Registrierung der Schrift funktioniert hingegen anscheinend). Es wird eine Ersatzschrift gewählt, vermutlich eine Standardschrift. Wenn eine der angebotenen Schriften jedoch auf dem System installiert ist, klappt das Laden (?!). Das erscheint mir völlig unlogisch, und ich kann den Fehler nicht finden.

Code: Alles auswählen

Procedure SchrArtifika()
	If RegisterFontFile(GetCurrentDirectory() + "fonts/Artifika-Regular.ttf")
		If SchrGr < 9
			SchrGr = 12
		EndIf
		If Artifika = LoadFont(#PB_Any, "Artifika Medium", SchrGr)
			SetGadgetFont(#edtAusgabe, FontID(Artifika))
		Else 
			MessageRequester("Schriftart", "Die Schrift „Artifika Medium“ konnte nicht geladen werden!", #PB_MessageRequester_Ok | #PB_MessageRequester_Error)
		EndIf
	Else
		MessageRequester("Schriftart", "Die Schrift „Artifika Medium“ konnte nicht registriert werden!", #PB_MessageRequester_Ok | #PB_MessageRequester_Error)
	EndIf
EndProcedure
Bei folgendem Code wird dann noch nicht mal meine Fehlermeldung ausgegeben:

Code: Alles auswählen

Procedure SchrArtifika()
	If RegisterFontFile(GetCurrentDirectory() + "fonts/Artifika-Regular.ttf")
		If SchrGr < 9
			SchrGr = 12
		EndIf
		If LoadFont(0, "Artifika Medium", SchrGr)
			SetGadgetFont(#edtAusgabe, FontID(0))
		Else 
			MessageRequester("Schriftart", "Die Schrift „Artifika Medium“ konnte nicht geladen werden!", #PB_MessageRequester_Ok | #PB_MessageRequester_Error)
		EndIf
	Else
		MessageRequester("Schriftart", "Die Schrift „Artifika Medium“ konnte nicht registriert werden!", #PB_MessageRequester_Ok | #PB_MessageRequester_Error)
	EndIf
EndProcedure
Und auch das misslingt:

Code: Alles auswählen

Procedure SchrArtifika()
	If RegisterFontFile(GetCurrentDirectory() + "fonts/Artifika-Regular.ttf")
		If SchrGr < 9
			SchrGr = 12
		EndIf
		LoadFont(0, "Artifika Medium", SchrGr)
		SetGadgetFont(#edtAusgabe, FontID(0))
	Else
		MessageRequester("Schriftart", "Die Schrift „Artifika Medium“ konnte nicht registriert werden!", #PB_MessageRequester_Ok | #PB_MessageRequester_Error)
	EndIf
EndProcedure
Die Prozedur wird aufgerufen, wenn im Menü des Anwendungsprogrammes die entsprechende Schrift ausgewählt wird, aber auch wenn sie beim Programmstart aus der zugehörigen Einstellungsdatei (.ini) gelesen wird. Alles andere klappt, also Schriftgröße oder Hintergrundfarbe, nur eben das Laden der Schriften aus dem Programmordner nicht.

Vielleicht hat jemand eine Idee, woran es liegen könnte.
Ich bin nicht mehr lange online, aber das erste Beispiel ist schon deswegen falsch:

Code: Alles auswählen

If Artifika = LoadFont(#PB_Any, "Artifika Medium", SchrGr)
Das ist keine Zuweisung sondern ein reiner Vergleich. Uninitialisierte Variable (somit 0) mit dem Ergebnis von LoadFont das mit PB_Any eine Nummer ungleich 0 zurück gibt. Also immer falsch, selbst bei Erfolg.

Desweiteren ist das Verhalten einen default Font zu laden der Namenstechnisch am verwandtesten ist wenn kein passender gefunden wurde glaube ich normal hier bei PB, vielleicht ist es unter Linux irgendein Font dann, damit das dort genauso wenig fehlschlägt wie auf den anderen Systemen:
On Windows and OS X the font mapper will always attempt to locate a font. If a font name which does not exist such as: "Tim Now Ronin", is used, then the font mapper will attempt to find the closest match. This will be based upon such criteria as: the font name, the font height, the style and so forth. Therefore, the assumption can not be made that a font will not be loaded, due only to an incorrect font name, size, ect
https://www.purebasic.com/documentation ... dfont.html

Bist du sicher, dass der Pfad richtig ist mit GetCurrentDirectory() + ...? Ist da ein Schrägstrich der fehlt o.ä.?
Angenommen es gäbe einen Algorithmus mit imaginärer Laufzeit O(i * n), dann gilt O((i * n)^2) = O(-1 * n^2) d.h. wenn man diesen Algorithmus verschachtelt ist er fertig, bevor er angefangen hat.
Benutzeravatar
Borstensohn
Beiträge: 10
Registriert: 07.11.2004 18:47
Wohnort: Remscheid, NRW

Re: LoadFont / IsFont funktioniert nicht ...

Beitrag von Borstensohn »

Erst einmal danke, DarkDragon, für die prompte Hilfe.

Ich habe jetzt eine Standardschrift angegeben, die auch geladen wird, aus einem Verzeichnis mit installierten Fonts. Das klappt. – Ähnlicher Code, der versucht, eine nicht installierte Schrift bzw. eine Schrift aus einem nicht standardgemäßen Fonts-Ordner zu laden, misslingt. Ich vermute also, dass nicht installierte Schriften enweder von PureBasic oder vom Betriebssystem blockiert werden.

Code: Alles auswählen

Procedure SchrStandard()
	If RegisterFontFile("/usr/share/fonts/truetype/liberation/LiberationMono-Regular.ttf") ;Muss vor Benutzunng registriert werden
		If SchrGr < 9
			SchrGr = 10
		EndIf
		If LoadFont(0, "Liberation Mono", SchrGr)
			SetGadgetFont(#edtAusgabe, FontID(0))
 		Else
 			MessageRequester("Schriftart", "Die Schrift „Liberation Mono“ konnte nicht geladen werden!", #PB_MessageRequester_Ok | #PB_MessageRequester_Error)
		EndIf
	Else
		MessageRequester("Schriftart", "Die Schrift „Liberation Mono“ konnte nicht registriert und geladen werden", #PB_MessageRequester_Ok | #PB_MessageRequester_Error)
	EndIf		
EndProcedure
ON ERROR GOTO BED
DarkDragon
Beiträge: 6291
Registriert: 29.08.2004 08:37
Computerausstattung: Hoffentlich bald keine mehr
Kontaktdaten:

Re: LoadFont / IsFont funktioniert nicht ...

Beitrag von DarkDragon »

Borstensohn hat geschrieben: 01.11.2023 22:23 Erst einmal danke, DarkDragon, für die prompte Hilfe.

Ich habe jetzt eine Standardschrift angegeben, die auch geladen wird, aus einem Verzeichnis mit installierten Fonts. Das klappt. – Ähnlicher Code, der versucht, eine nicht installierte Schrift bzw. eine Schrift aus einem nicht standardgemäßen Fonts-Ordner zu laden, misslingt. Ich vermute also, dass nicht installierte Schriften enweder von PureBasic oder vom Betriebssystem blockiert werden.

Code: Alles auswählen

Procedure SchrStandard()
	If RegisterFontFile("/usr/share/fonts/truetype/liberation/LiberationMono-Regular.ttf") ;Muss vor Benutzunng registriert werden
		If SchrGr < 9
			SchrGr = 10
		EndIf
		If LoadFont(0, "Liberation Mono", SchrGr)
			SetGadgetFont(#edtAusgabe, FontID(0))
 		Else
 			MessageRequester("Schriftart", "Die Schrift „Liberation Mono“ konnte nicht geladen werden!", #PB_MessageRequester_Ok | #PB_MessageRequester_Error)
		EndIf
	Else
		MessageRequester("Schriftart", "Die Schrift „Liberation Mono“ konnte nicht registriert und geladen werden", #PB_MessageRequester_Ok | #PB_MessageRequester_Error)
	EndIf		
EndProcedure
Also unter Linux hat es halt einen Font-Cache entsprechend dem freedesktop Standard. Der muss abundzu refresht werden.

https://man.archlinux.org/man/fc-cache.1.en
https://www.freedesktop.org/wiki/Software/fontconfig/

Da kommen für gewöhnlich alle Fonts für Anwendungen her unter Linux. Vielleicht geht das Registrieren da einfach nicht richtig mit PB.
Angenommen es gäbe einen Algorithmus mit imaginärer Laufzeit O(i * n), dann gilt O((i * n)^2) = O(-1 * n^2) d.h. wenn man diesen Algorithmus verschachtelt ist er fertig, bevor er angefangen hat.
Benutzeravatar
Shardik
Beiträge: 746
Registriert: 25.01.2005 12:19

Re: LoadFont / IsFont funktioniert nicht ...

Beitrag von Shardik »

freak hat in diesem Beispiel gezeigt, wie man in Linux den externen Font fontawesome-webfont.ttf anzeigt. Ich habe freaks Beispiel-Code gerade erfolgreich in Linux Mint 21.2 x64 'Victoria' ausprobiert, nachdem ich den Font heruntergeladen und den Pfad zum Font in Freaks Beispiel entsprechend angepasst hatte.
Benutzeravatar
Borstensohn
Beiträge: 10
Registriert: 07.11.2004 18:47
Wohnort: Remscheid, NRW

Re: LoadFont / IsFont funktioniert nicht ...

Beitrag von Borstensohn »

Shardik hat geschrieben: 02.11.2023 11:50 freak hat in diesem Beispiel gezeigt, wie man in Linux den externen Font fontawesome-webfont.ttf anzeigt. Ich habe freaks Beispiel-Code gerade erfolgreich in Linux Mint 21.2 x64 'Victoria' ausprobiert, nachdem ich den Font heruntergeladen und den Pfad zum Font in Freaks Beispiel entsprechend angepasst hatte.
Jetzt habe ich es hinbekommen, dass man Schriften auswählen kann, die nicht auf dem System installiert sein müssen, aber in einem Unterverzeichnis des Programmverzeichnisses als Schriften im True-Type-Format vorliegen müssen. Hier mein Code:

Code: Alles auswählen

EnableExplicit

;================
;– Programmbeginn
;================

Enumeration
	;– Window Constant
	#Window_Haupt
	;– Gadget Constants
	#btnBlokletters
	#btnTeen
	#edtAusgabe
	#cntContainer
EndEnumeration

;– Definitions
Global EventID
Global Blokletters, Teen ;Schriftart

;– Declarations of procedures
Declare Open_Main_Window()
Declare SchrBlokletters()
Declare SchrTeen()

;– Constants
#version = "0.1"

Procedure Open_Main_Window()
	If OpenWindow(#Window_Haupt, #PB_Ignore, #PB_Ignore, 480, 540, "Schrift laden " + #version, #PB_Window_SystemMenu | #PB_Window_MinimizeGadget | #PB_Window_TitleBar | #PB_Window_ScreenCentered)
		;– Create GadgetList
		ContainerGadget(#cntContainer, 0, 0, 480, 515, #PB_Container_Raised)
			ButtonGadget(#btnBlokletters, 10,  470, 95, 20, "Blokletters")
			ButtonGadget(#btnTeen, 120,  470, 95, 20, "Teen")
			;EditorGadgets
			EditorGadget(#edtAusgabe, 10, 165, 458, 295, #PB_Editor_WordWrap)
		CloseGadgetList()
			
		AddGadgetItem(#edtAusgabe, -1, "PureBasic soll sehr gut sein, habe ich mir sagen lassen.")
	EndIf ;OpenWindow
EndProcedure

ImportC "-lfontconfig"
	FcConfigAppFontAddFile(*config, file.p-ascii)
EndImport

FcConfigAppFontAddFile(#Null, GetCurrentDirectory() + "fonts/Blokletters-Balpen.ttf")
FcConfigAppFontAddFile(#Null, GetCurrentDirectory() + "fonts/teen.ttf")

;===========
;- Hauptteil
;===========

Open_Main_Window()

Repeat
	;– Ereignisse
	EventID = WindowEvent()
		
	;– Fenster
	If EventID = #PB_Event_CloseWindow
		If WindowID(#Window_Haupt)
			CloseWindow(#Window_Haupt)
			End
		EndIf
	Else
		Delay(1) ;Verhindert unnötige CPU-Auslastung
	EndIf
	
	If EventGadget()=#btnBlokletters
		SchrBlokletters()
	EndIf
	If EventGadget()=#btnTeen
		SchrTeen()
	EndIf	
Until EventID = #PB_Event_CloseWindow


;==============
;- Programmende
;==============

End


;=================
;- Unterprozeduren
;=================

Procedure SchrBlokletters()
	Blokletters = LoadFont(0, "Blokletters Balpen", 16)
	SetGadgetFont(#edtAusgabe, FontID(0))
EndProcedure

Procedure SchrTeen()
	Teen = LoadFont(1, "Teen", 16)
	SetGadgetFont(#edtAusgabe, FontID(1))
EndProcedure

Vielen Dank also an alle, die ihre Ideen hier beigesteuert haben, sodass ich endlich eine Lösung für meine Aufgabenstellung habe finden können.
ON ERROR GOTO BED
Antworten