I wanted to use a free TTF windows font to display the chess clock in the GUI display of NADYA3 Chess using an LCD font, and have it loading the font as a private font collection. During the process I found what I believe to be a bug in VIP, but I'll let you decide because I still often times feel like a complete beginner. In any case, I provide my workaround and have done the work to determine what I believe to be the problem. I could be doing something wrong, as I'm not a GDI/GDIPLUS/SDK Windows coder by any means, and I struggle through it.
This code loads a custom true-type font using gdi plus without having to globally install it on the users' windows OS.
Problem: I believe the code accessing the "families" property of the "fontCollection" interface is incorrect. I believe the return data from "gdipGetFontCollectionFamilyList" is a pointer to an array of
gpFontFamily pointers to the underlying structures.
The first example shows how I access the list of font families in a private font collection and successfully create the font, in two related, ways and then shows what throws an exception using VIP (if I am using VIP properly) The second example shows how I believe PDC intended for it to work.
ALSO: I'm not very good at all at writing "pretty" VIP prolog, and this looks kind of choppy to me, so feel free to show me how I could make it "prettier". Martin and others seems to be pretty helpful with people about that but I don't know if he works for PDC.
Example #1: Note Method #1 and Method #2 succeed, and Method #3 fails. The code is commented. (I borrowed a dialog constructor for my example). Please note, my custom TTF file only has a single font family and this code takes that into account.
Code: Select all
clauses
new(Parent) :-
dialog::new(Parent),
generatedInitialize(),
init_display(),
gdiplus_native::gdipNewPrivateFontCollection(PrivateFontCollection)=0,
gdiplus_native::gdipPrivateAddFontFile(PrivateFontCollection, "lcd.ttf")=0,
% I should be able to skip all the code between here and "Method #3"
gdiplus_native::gdipGetFontCollectionFamilyCount(PrivateFontCollection, Count)=0,
Array = memory::allocHeap(Count * sizeOfDomain(pointer), memory::contextType_gdiplus),
gdiplus_native::gdipGetFontCollectionFamilyList(PrivateFontCollection, Count, Array, Found)=0,
Ptr = uncheckedConvert(pointer, memory::getInteger64(Array)),
FontF = uncheckedConvert(gdiplus_native::gpFontFamily, Ptr),
% -- Method #1 (Works)
gdiplus_native::gdipCreateFont(FontF, 12, gdiplus_native::fontStyleRegular, gdiplus_native::unitPoint, NativeFont)=0,
Font1 = font::newNative(NativeFont),
% -- Method #2 (Works)
FontFamily = fontFamily::newNative(FontF),
Font2 = font::createFromFontFamily(FontFamily, 12, gdiplus_native::fontStyleRegular, gdiplus_native::unitPoint),
% -- Method #3 (Fails)
FontFamilies = fontCollection::newNative(PrivateFontCollection),
[FirstFamily|_] = FontFamilies:families, % <---- I believe the underlying code is accesing the pointer array incorrectly.
% THE NEXT LINE OF CODE THROWS THE EXCEPTION
Font3 = font::createFromFontFamily(FirstFamily, 12, gdiplus_native::fontStyleRegular, gdiplus_native::unitPoint),
% WISHLIST ITEM - Would be totally cool to be able to add an optional parameter to pass a single, or list of,
% "gpFontCollection" items (like my "PrivateFontCollection" variable) to vpiCommonDialogs::getFont predicate, as in:
% Font = vpiCommonDialogs::getFont(getFont(), [PrivateFontCollection]),
! ;
succeed.
Code: Select all
gdiplus_native::gdipNewPrivateFontCollection(PrivateFontCollection)=0,
gdiplus_native::gdipPrivateAddFontFile(PrivateFontCollection, "lcd.ttf")=0,
FontFamilies = fontCollection::newNative(PrivateFontCollection),
[FirstFamily|_] = FontFamilies:families,
Font = font::createFromFontFamily(FirstFamily, 12, gdiplus_native::fontStyleRegular, gdiplus_native::unitPoint),
Cheers,
Craig Hoibakk