Can Psychtoolbox show installed custom fonts?

Dear Psychtoolbox community,

I am writing a simple script that draws different German words in different fonts. In total I downloaded and installed (C:/Windows/Fonts) 380 fonts from different website. I recently switched from Psychopy to Psychtoolbox. In Psychopy it was sufficient to type the fontname installed in C: to load the font so I thought the same could be done here. However, Psychtoolbox shows the default font (e.g., Arial or Verdana) without loading the correct font. Is there anything I have been doing wrong?

Please, find below my snippet of code. ‘fontname’ is a cell array that contains different fontnames; ‘trial’ is the index of the for loop; ‘german’ is a cell array that contains different german words. Consider that the scripts works fine, no errors are thrown, and I successfully downloaded and installed all supports for text rendering.

Screen('TextSize', w1, 100);
Screen('TextFont', w1, fontname{trial});
% Call a flip to get the right vbl before flipping the image on screen
%vbl = Screen('Flip', w1);
DrawFormattedText(w1, german{trial}, 'center', 'center', black);

Here some useful information:

Psychtoolbox Version
3.0.18 - Flavor: beta - Corresponds to SVN Revision 12719

MATLAB Version

Operating System

Could you please help me with this?
Thank you in advance

best wishes

Code looks correct. ‘TextFont’ expect the font family name (not neccessarily the same as the font file name in the fonts folder!). A call to actualFont = Screen('TextFont', w1) inserted after the first DrawFormattedText would tell you what font family name was actually chosen for text drawing.

Maybe the name you specified is wrong? Or the libfontconfig cache is somehow out of date / didn’t pick up the freshly installed font files? That’s the database used for finding the best matching font file for a given font specification. Happens occassionally on Windows or macOS for unknown reasons. See
for troubleshooting tips wrt. the fontconfig cache.


Hi Mario,

Thank you for your reply.
Using actualFont = Screen('TextFont', w1) as suggested return “Verdana”. This is wrong because I input other filenames. These are correct because they are the same ones that I used when piloting my online study in Pavlovia. I also went to Users/loris/AppData/Local/fontconfig/cache and deleted that folder. Inside the “cache” folder I have only two files though:

  • ef9c9ad8cc5857eb63cb3660bc8bd202-x86_64.cache-7

When I cancel them, they are re-created when re-running the task but nothing changed. It seems that Psychtoolbox does not pick the correct font.

Any other suggestios?
Thank you

Can you confirm the right text renderer is being used with Screen(‘Preference’,‘TextRenderer’)?
Can you provide an example font name as you used in the code you posted before?

Dear dcnieho,

Thank you for your kind reply.
I have inserted type = Screen(‘Preference’,‘TextRenderer’) after calling ‘DraFormattedText’ and it returns 1. According to the documentation “A ‘type’ of 1 means that the plugin based renderer is used” so this should be fine.

I downloaded various fonts from internet so the ones I would like to use are custom fonts.
Some of them are:
{‘Crystal’ }
{‘Ceviche One’ }
{‘Plasma Drip (BRK)’ }
{‘Mandingo’ }
{‘CF I Dont Want to Grow Up’}
{‘Kool’ }

They are all in a cell array. I am 100 per cent sure these are the correct fontnames since I extracted them through python and they worked elsewhere. However (and this can be the key) I have noticed that when I opened the .CACHE-7 files…these custom fonts are not listed there. It is like that that file is not updated with the new installed fonts. It only has the default ones (e.g., Verdana, Arial, Times New Roman). I do not know why that would be the case though.

Any suggestions?
Thank you

So they are in the Windows fonts folder? Do the fonts work in word or so?


Yes they are in “C:/Windows/Fonts” and they all appear in word.

Sounds indeed like fontconfig is not picking up the fonts for some reason. Two things you can try:

  1. Does it work better with Octave-6.4? Octave ships its own libfontconfig with its own configuration file and so may behave differently from Matlab, whereas Matlab doesn’t ship it, so the libfontconfig from GStreamer is used - and its config file wrt. where to search for fonts. There’s probably a “somethingblahblah.fonts.conf” file or such somewhere inside GStreamer that determines this.

  2. Does the officially unsupported lower quality/performance/flexibility fallback text renderer 0 work via Screen(‘Preference’,‘TextRenderer’)?

Any further advice from myself - with no guarantee of problem resolution - will require buying at least one hour of priority support, possibly more.


Hi Mario,

I have now done Screen('Preference', 'TextRenderer', 0) and it works…I am even more confused now. Now I can see the different fonts…however, the rendering is very bad now, e.g., instructions are in low resolution, not centred, and some bits of the fonts/words are cut/missing. Could you explain me what it changed now?

I do not have Octave and it would be time consuming to go there since I can script it with PTB/or psychopy.

Well, if you think you can find a solution I d be more than happy to buy at least one hour of priority support.


your matlab code should just run in gnu octave, which is free. Just install and give a try. Octave is does not fully support all matlab does, but as long as you don’t use crazy classes or lots of toolboxes, you may well be fine

You use an old, no longer maintained text renderer, which enumerates fonts differently, but apparently isn’t up to the task of rendering your fonts properly.

I was able to reproduce your problem, and found the very likely solution, tested with one font downloaded from the internet, under Octave 6.4 with Windows 11, but should work with Matlab or Windows 10 as well.

Switching to Octave would not have helped in this case, the problem is elsewhere than Octave or PTB.

Anyway, it took me over 4 hours of lots of detective work, so if you can buy at least 4 memberships, better 5, and post the corresponding authentication tokens, I can invalidate them and then post the solution to your problem as soon as i have confirmation for the payment received and license keys activated, ie. Friday earliest if you buy today, otherwise probably sometime next week.


Hi Mario,

That’s great.

However, I see in the website that one can only buy a single membership that is valid for up to 3 hours of work. So, if you worked 4/5 hours, then 2 quantities for 300 euros should be enough. Could you clarify this for me please`?

Thank you

The text says “…up to 3 times (or up to a total of 1 hour of our experts’ work time per key) within 12 months…” → Buying one such membership gives you 1 hour of my time in total, not 3 times one hour

So effectively the hourly rate is 1 membership or 150 Euros + sales tax for every started work hour.

I should mention that we have decided to raise prices substantially in the foreseeable future, because too few labs are willing to contribute financially and at the current price point, we are too cheap, barely cost covering and the membership program is not contributing a significant amount of money to the upkeep of PTB. A discount program will be put in place to reward loyal backers of PTB to make this attractive.

My boss pointed out to me just days ago that i am still way too generous with my time and free advice and that this is the path to complete project failure if i can’t be more strict about this.


Hi Mario,

Thank you for clarifying this.

I was ready to give my contribution for 2 memberships, i.e., 300 euros in total. However, this is not funded by my lab and I feel that paying 750 euros by myself goes beyond my possibilities. Unfortunately, I cannot afford it. It seems to much money for a single person if everyone would benefit for this post once the solution is made available.

I think that a fee that is regularly paid (either montly/annually) by everyone using this service would solve the problem.

Many thanks

That is something your lab absolutely should pay for, not yourself, unless they don’t care about the quality of their presumably tax-payer funded research, or how efficient the expensive time of their employees is used.

I guess your Windows specific problem will stay unsolved then and I have to write off the better part of an unpleasant work day and hundreds of Euros of damage done by this to the project as another personal learning experience to not trust what users say.

That’s the spirit! If it is a consolation, nobody except you ever encountered this problem to my knowledge, so almost nobody except you would benefit from its resolution.

We tried voluntary contributions for years and they don’t work at all - it almost bankrupted me personally. We continued it as a “Community membership” for the last 15 months as part of the business - almost nobody contributed, in total only a few hundred euros afaik, it was more costly to set it up than what it ever earned.

We intended exactly this what you proposed with the “Community membership with priority support”, as this was literally what many hundreds of labs in funding workshops and a survey with over thousand responses said they would absolutely support, no question asked, if we make a service available. It just needed to have some service attached, so it doesn’t count as a simple donation and labs can pay from their funds. The plan, explained in detail on our website, forum and in ptb itself, was that every able lab buys one of these for 150 euros/year and we are set, even if only a third or quarter of all labs that benefit from Psychtoolbox do it. We could have provided free service to most people, as the “community funding” would have paid for it. Less than 50 labs did contribute over a one year time-span, or way less than 10% of what our most pessimistic estimate predicted.

What we learned so far over many years of trying is that “voluntary” doesn’t work with the neuroscience community, and very few pay anything for anything unless forced to, regardless what they claimed they would do. I got feedback from the Python toolkit people that their users are no better. And even then some try to negotiate or wiggle their way out of actually paid services rendered, like in your case. Labs that have no qualms about spending thousands or ten-thousands of Euros on equipment that doesn’t work as it should, equipment that we recommend against, and operating systems and software that is unfit for the task, and then feel we should fix their problems for free, or that a few hundred Euros are asked too much. This general attitude is “penny wise, pound foolish” - everybody loses and will get no service at all, or worse service for their money.

We will do a survey soon, to see if we can learn anything about reasons that our models don’t work, despite the claims of support from many labs, or if it is just egotism. If you have specific suggestions for improvement, feel free to contribute to that survey, once it is out.

In the meantime, this issue here is another data point to prove that i should be less accommodating and not engage at all unless the first batch of money in on our bank account. Our services are too cheap already.


Hi Mario,

It is unfortunate that you point me out as a “user not to trust”. It is not the first time that I have paid for a service and it will not be the last one. Also, I am not trying to negotiate anything or wiggle out the service that you provided. I simply was not expecting the service to be this expensive (although you consider it cheap). I think that if everyone (as single users) paid a fee with more accessible prices (regardless of whether labs can pay or not), that would be more fair! Not every lab can afford paying 750 euros for 5 hours of work. I am not saying that this means underestimating the work you do. I appreciate a lot that there are some people like you that work to improve tools that the community use daily.

I just think that people are discouraged when the prices are high, especially since alternative solutions can always be found for free. Take my example: I could print the fonts on canvas and show them as pictures. Problem solved. The original issue will still be unsolved for me and for the other users interested in the future to do something similar (although you said I am the only one with the problem). As you said this is a war that everyone loses :).

Also, please do not let pass the message (at least in my case) that I do not want to support the work you people do with a first batch of money. If you think that your time has to be compensated with me buying at least some memberships in advance…that’s OK! But that should be done formally through the website, not on what people say. Then I could say that noone has formally seen you working for 5 hours…they could have been 4-3-2-1…how does the count work? On your word?

Said so, I am ready to acknowledge the job you did this time because it was my error not to read them carefully. And I would be more than happy to take part to the survey once it is out.

Best wishes

I’m not picking on you alone, but also the many other people who did this throughout the last year. It simply means i should not trust statements made by users and wait for confirmation that money has been paid for each hour of work done before i start working.

And yes, it is cheap. Common rates for people with my skills and experience, doing the work I do, from typical consultancies, would start in the ballpark of 500 Euros per billable hour, not 150 Euros. Do you know what an hour of your work time costs your employer? Does your lab factor that in if they aren’t paying such fees and leave it to you to pay yourself? Did you ask your PI to cover these costs, or share them with you?

Indeed, that would be more fair and better for everyone, I thought so too. That’s why I tried it for six years, after providing high quality work completely for free for over 10 years until i couldn’t afford it anymore, because I myself was paying a hefty price - it wasn’t free for me at all. And almost nobody paid anything and I almost went bankrupt.

That’s why we wanted labs to pay 150 Euros/year, still voluntary, each lab to their ability, so labs who really can’t even afford 150 Euros per year still get everything for free and the stronger ones pay for the weaker ones. Most labs in western countries should be easily able to pay a 150 Euros per year after all, as a flat rate for everything we provide. And we tried it for 15 months now, and the outcome was disappointing as well, pointing to failure.

So we tried all that you suggested and reality contradicts both your assumptions and mine and of various other people who gave input - essentially anybody who assumed good will, or long term thinking was wrong so far. That’s why we can’t afford to be that generous anymore, because it boils down to estimated 99.9% of our user base free riding. I know what an hour of my time costs, despite the fact that I am still severely underpaid atm., as is pointed out regularly by my boss.

I didn’t use the word “war”. If at least a meaningful fraction of lab heads would employ long term thinking, no lab would have to pay more than 150 euros/year. But clearly they don’t do that in the vast majority of cases.

And yes, free solutions exist, but they are not free to the people who provide those “free” solutions to you. And generally in the field of neuroscience, for technically non-trivial experiments, they are by far not as good, or only free if you have one specific problem. My girlfriend also used PsychoPy and Pavlovia throughout the pandemic, for simple student projects, and from her I have a pretty good impression how good our text rendering is compared to other “free” solutions, because she ranted a lot about the pain associated with that. So by all means, create canvases with text if you think that is a great free solution to your problem and an efficient use of your work time. Even PTB would have had a simple free solution to your problem if your lab would follow our system recommendations.

Our software is free to everyone, paid by an enormous amount of work time that somehow has to be financed by whatever income stream we have. Around 80 work hours per week on average over the last 10 years. The community memberships were supposed to pay for all this and for continuing mostly free support to users, but if nobody contributes anything voluntarily, then those who need extra work and support have to pay for that time and also the general maintenance of the software.

That is exactly how it formally works, you pay for all work hours upfront, or some hours and then increments, or you have a formal legal contract in place for the conditions of work and payment. That I worked on this without proof of payment first was just a courtesy, trying to save you some time, based on your statement that you would be willing to pay for it. No worries, i will try to stick to the “pay me first” model much stronger, because i also can’t afford to waste time on these kinds of back and forth.

Yes, except that my girlfriend could prove witness in this case. I run a clock whenever i work on paid or free user support, and I’m always generous towards counting less time than it took, e.g., if i think about a problem while not at the machine, but forgot to start the clock, i won’t count that. But of course you can also assume that somebody who spent 15 years of free work on PTB and user support will suddenly turn mischievous and try to cheat you. How does your employer know how many hours you worked exactly? On your word? I haven’t seen a punch clock for researchers in any lab i was ever affiliated with.

Generous of you. Anyway, if somebody wants this problem solved on Windows, proof of purchase of 5 memberships will be required, my generous “only pay for 4 out of the 5 hours” offer is hereby retracted.


Hi Mario,

Sure, no problem! I am not asking for discounts.
These are the 5 memberships requested:







The lesson is that my word count and people are not all the same.
I am looking forward to hearing from you and to understanding what the issue was so that I can start my fMRI experiment.

Best Regards

Ok, payment received, thanks for doing business with us.

So, the problem is a relatively recent design change in Microsoft Windows 10 Release 1809 in October 2018, apparently too quietly introduced in the middle of a stable OS release, which surprised many and so there’s a lot of software out there that isn’t prepared for this new way of handling fonts.

If you install your own non-system fonts into C:\Windows\Fonts, e.g., by going to that folder in the file explorer, then Windows gives you the illusion of installing fonts there, but in reality it installs your fonts into the (e.g., for a user with name “mario”) C:\Users\mario\AppData\Local\Microsoft\Windows\Fonts folder instead - it virtualizes the folder. So far so good, it allows to install new fonts as a regular non-admin users. Where “well intended, badly done” starts is that this illusion is only kept up for users interacting with the C:\Windows\Fonts folder via the GUI, not for applications actually operating on that folder, they need to be adapted to deal with this new way of doing things.

Software that uses some MS Windows proprietary api’s for font enumeration will be in on the illusion, e.g., software that uses the MS legacy GDI text renderer, like apparently PsychoPy or our old legacy GDI based text renderer. → Finds the fonts, but lower performance, lower quality, less flexibility and functionality, problems with not-quite standard fonts as you saw when trying this TextRenderer 0, and inconsistent text appearance across different operating systems and hardware. Any other software will not find these fonts in their special locations, unless updated/rewritten accordingly.

Our normal cross-platform high quality text renderer uses libfontconfig for more flexible font enumeration that is consistent across operating systems, and we use the libfontconfig dll included with Octave if PTB for Octave is used, or the one included with GStreamer if PTB for Matlab is used. libfontconfig, as shipping with those, doesn’t support searching the new font folder locations by default yet. Support for this + a couple related bug fixes and workarounds for MS-Windows problems, was added to libfontconfig version 2.13.96, released about a month ago as a beta release. See Fonts installed in the user directory are not detected (#144) · Issues · fontconfig / fontconfig · GitLab

Finding out what went wrong required going through the GStreamer repo git commit logs to find what libfontconfig version and config is used, the corresponding Octave repo, the source code of libfontconfig to understand how the MS-Windows implementation works and differs from the Linux and macOS method, the commit logs and bug trackers of libfontconfig to find clues what it could be. That MS-Windows doesn’t install fonts where it pretends to do and lies to the user about it and half-asses the virtualization, wasn’t the first hypothesis, so i had to explore various other way more plausible explanations first. The final clue came when installing a font in the Windows/Fonts folder myself, right clicking on its icon → Properties and finding the install path to be not Windows/Fonts. That made the connection for me to bug reports and commits in the libfontconfig git repository. Then correlating released fontconfig versions against what GStreamer/Octave are shipping, assessment of the likelihood of them fixing this in an update very soon themselves – not high. Then coming up with a potential workaround and testing on Octave 6.4 and GStreamer 1.18 on Windows-11 with custom installed font…

So this may explain to you why it took more than 4 hours to find the likely solution, which is to edit the fonts.conf file to manually add the path to the true font folder, until some future GStreamer updates will hopefully bundle an upgraded libfontconfig and the problem should resolve itself - or introduce new bugs, who knows?

If you are using Octave 6.4, edit the top section of:
C:\Program Files\GNU Octave\Octave-6.4.0\mingw64\etc\fonts\fonts.conf

If you are using Matlab, edit the top section of:

After the line…


… add the line …


… with “loris” replaced by your user name on your machine if that isn’t the correct one.

Then, and whenever you installed new fonts, quit Matlab/Octave and delete the …
…folder again, to force reenumeration of all fonts. The cache folder will contain an additional .cache-7 file with all your fonts.

You could install fonts wherever you wanted and add such extra dir entries, but ofc. other Windows apps may not find them there.

In the future, libfontconfig v2.13.96+ should have an additional default entry in its config file called <dir>WINDOWSUSERFONTDIR</dir> to automatically search fonts in that user specific path.

This also means that your fonts will only be available on your user account, not those of other users of the machine and one would need to add a proper entry for every users private folder location, and install those fonts again for every user, unless filesystem permissions are set to allow other accounts to read your own folder.

This problem wouldn’t have happened on Linux, btw., just like many other problems that go away when upgrading to Linux.


1 Like

Hi Mario,

Thank you for this.

I understood the problem and now I can see the fonts with high quality rendering. It is also amazing how smooth PTB shows them compared to PsychoPy that seems to struggle a lot with text (reason for which I still prefer this toolbox to any others around).

I did not want to sound polemic in the previous posts. I just think that it is a shame that the contribute has to be handled only by few people that are willing to do so, when the entire community could contribute by reducing each other’s monetary burden.

I hope it was a fruitful conversation for everyone and indeed a helpful collaboration for me :slight_smile: