ashb / windows-fonts

Python access to Windows Font catalog
MIT License
2 stars 0 forks source link

Some font can't be reached #6

Closed moi15moi closed 1 year ago

moi15moi commented 1 year ago

Problem

The PR #5 introduce GetMatchingFonts. The problem from this is that DWrite seems to, sometimes, use the nameID 16 (typographic family name), so it can create problem when you search a font by the name of the nameID 1 (family name).

Solution

You could use GetInformationalStrings with the style DWRITE_INFORMATIONAL_STRING_WIN32_FAMILY_NAMES.

Example:

Let's imagine you wanna search the font named Arial Narrow. Arial Narrow isn't considered a family by windows, but if you open the font with fonttools, you will see that it has a nameID 1 (which is font family) that is Arial narrow.

This mean that currently, it is impossible to find this font. It would be nice to have an alternative to find it.

Here is the NamingTable of Arial Narrow

  <name>
    <namerecord nameID="0" platformID="1" platEncID="0" langID="0x0" unicode="True">
      © 2008 The Monotype Corporation. All Rights Reserved.
    </namerecord>
    <namerecord nameID="1" platformID="1" platEncID="0" langID="0x0" unicode="True">
      Arial Narrow
    </namerecord>
    <namerecord nameID="2" platformID="1" platEncID="0" langID="0x0" unicode="True">
      Regular
    </namerecord>
    <namerecord nameID="3" platformID="1" platEncID="0" langID="0x0" unicode="True">
      Arial Narrow Regular : 2008
    </namerecord>
    <namerecord nameID="4" platformID="1" platEncID="0" langID="0x0" unicode="True">
      Arial Narrow
    </namerecord>
    <namerecord nameID="5" platformID="1" platEncID="0" langID="0x0" unicode="True">
      Version 2.40
    </namerecord>
    <namerecord nameID="6" platformID="1" platEncID="0" langID="0x0" unicode="True">
      ArialNarrow
    </namerecord>
    <namerecord nameID="7" platformID="1" platEncID="0" langID="0x0" unicode="True">
      Arial is a trademark of The Monotype Corporation in the United States and/or other countries.
    </namerecord>
    <namerecord nameID="8" platformID="1" platEncID="0" langID="0x0" unicode="True">
      The Monotype Corporation
    </namerecord>
    <namerecord nameID="9" platformID="1" platEncID="0" langID="0x0" unicode="True">
      Robin Nicholas, Patricia Saunders
    </namerecord>
    <namerecord nameID="13" platformID="1" platEncID="0" langID="0x0" unicode="True">
      You may use this font to display and print content as permitted by the license terms for the product in which this font is included. You may only (i) embed this font in content as permitted by the embedding restrictions included in this font; and (ii) temporarily download this font to a printer or other output device to help print content.
    </namerecord>
    <namerecord nameID="2" platformID="3" platEncID="1" langID="0x403">
      Normal
    </namerecord>
    <namerecord nameID="2" platformID="3" platEncID="1" langID="0x405">
      obyčejné
    </namerecord>
    <namerecord nameID="2" platformID="3" platEncID="1" langID="0x406">
      normal
    </namerecord>
    <namerecord nameID="2" platformID="3" platEncID="1" langID="0x407">
      Standard
    </namerecord>
    <namerecord nameID="2" platformID="3" platEncID="1" langID="0x408">
      Κανονικά
    </namerecord>
    <namerecord nameID="0" platformID="3" platEncID="1" langID="0x409">
      © 2008 The Monotype Corporation. All Rights Reserved.
    </namerecord>
    <namerecord nameID="1" platformID="3" platEncID="1" langID="0x409">
      Arial Narrow
    </namerecord>
    <namerecord nameID="2" platformID="3" platEncID="1" langID="0x409">
      Regular
    </namerecord>
    <namerecord nameID="3" platformID="3" platEncID="1" langID="0x409">
      Arial Narrow Regular : 2008
    </namerecord>
    <namerecord nameID="4" platformID="3" platEncID="1" langID="0x409">
      Arial Narrow
    </namerecord>
    <namerecord nameID="5" platformID="3" platEncID="1" langID="0x409">
      Version 2.40
    </namerecord>
    <namerecord nameID="6" platformID="3" platEncID="1" langID="0x409">
      ArialNarrow
    </namerecord>
    <namerecord nameID="7" platformID="3" platEncID="1" langID="0x409">
      Arial is a trademark of The Monotype Corporation in the United States and/or other countries.
    </namerecord>
    <namerecord nameID="8" platformID="3" platEncID="1" langID="0x409">
      The Monotype Corporation
    </namerecord>
    <namerecord nameID="9" platformID="3" platEncID="1" langID="0x409">
      Robin Nicholas, Patricia Saunders
    </namerecord>
    <namerecord nameID="10" platformID="3" platEncID="1" langID="0x409">
      Monotype Drawing Office 1982. A contemporary sans serif design, Arial contains more humanist characteristics than many of its predecessors and as such is more in tune with the mood of the last decades of the twentieth century. The overall treatment of curves is softer and fuller than in most industrial-style sans serif faces. Terminal strokes are cut on the diagonal which helps to give the face a less mechanical appearance. Arial is an extremely versatile family of typefaces which can be used with equal success for text setting in reports, presentations, magazines etc, and for display use in newspapers, advertising and promotions.
    </namerecord>
    <namerecord nameID="13" platformID="3" platEncID="1" langID="0x409">
      You may use this font to display and print content as permitted by the license terms for the product in which this font is included. You may only (i) embed this font in content as permitted by the embedding restrictions included in this font; and (ii) temporarily download this font to a printer or other output device to help print content.
    </namerecord>
    <namerecord nameID="16" platformID="3" platEncID="1" langID="0x409">
      Arial
    </namerecord>
    <namerecord nameID="17" platformID="3" platEncID="1" langID="0x409">
      Narrow
    </namerecord>
    <namerecord nameID="2" platformID="3" platEncID="1" langID="0x40a">
      Normal
    </namerecord>
    <namerecord nameID="2" platformID="3" platEncID="1" langID="0x40b">
      Normaali
    </namerecord>
    <namerecord nameID="2" platformID="3" platEncID="1" langID="0x40c">
      Normal
    </namerecord>
    <namerecord nameID="2" platformID="3" platEncID="1" langID="0x40e">
      Normál
    </namerecord>
    <namerecord nameID="2" platformID="3" platEncID="1" langID="0x410">
      Normale
    </namerecord>
    <namerecord nameID="2" platformID="3" platEncID="1" langID="0x413">
      Standaard
    </namerecord>
    <namerecord nameID="2" platformID="3" platEncID="1" langID="0x414">
      Normal
    </namerecord>
    <namerecord nameID="2" platformID="3" platEncID="1" langID="0x415">
      Normalny
    </namerecord>
    <namerecord nameID="2" platformID="3" platEncID="1" langID="0x416">
      Normal
    </namerecord>
    <namerecord nameID="2" platformID="3" platEncID="1" langID="0x419">
      Обычный
    </namerecord>
    <namerecord nameID="2" platformID="3" platEncID="1" langID="0x41b">
      Normálne
    </namerecord>
    <namerecord nameID="2" platformID="3" platEncID="1" langID="0x41d">
      Normal
    </namerecord>
    <namerecord nameID="2" platformID="3" platEncID="1" langID="0x41f">
      Normal
    </namerecord>
    <namerecord nameID="2" platformID="3" platEncID="1" langID="0x424">
      Navadno
    </namerecord>
    <namerecord nameID="2" platformID="3" platEncID="1" langID="0x42d">
      Arrunta
    </namerecord>
    <namerecord nameID="2" platformID="3" platEncID="1" langID="0x80a">
      Normal
    </namerecord>
    <namerecord nameID="2" platformID="3" platEncID="1" langID="0x816">
      Normal
    </namerecord>
    <namerecord nameID="2" platformID="3" platEncID="1" langID="0xc0a">
      Normal
    </namerecord>
    <namerecord nameID="2" platformID="3" platEncID="1" langID="0xc0c">
      Normal
    </namerecord>
  </name>
ashb commented 1 year ago

Oh interesting. (Sorry, didn't do a good job keeping on top of notifications)

I think https://learn.microsoft.com/en-us/windows/win32/api/dwrite_3/nf-dwrite_3-idwritefontcollection2-getmatchingfonts would might let us find this -- this interface only works on Windows 10 (everything else so far is Win7+)

The other option would be to expose GetInformationalStrings as font.information or simillar and then we can just filter in Python. I guess it depends on your usecase?

moi15moi commented 1 year ago

The other option would be to expose GetInformationalStrings as font.information or simillar and then we can just filter in Python. I guess it depends on your usecase?

Not really. For example, if I wanna get the font Arial Narrow, I would need to do something like that which doesn't make sense since I can't know that the family name is "Arial" to make it work:

from windows_fonts import FontCollection

fonts = FontCollection()
family = fonts['Arial']

for variant in family:
    if variant.information["DWRITE_INFORMATIONAL_STRING_WIN32_FAMILY_NAMES"] == "Arial Narrow":
        print(f"Found font at: {variant.filename}")
ashb commented 1 year ago

Got it. Using the GetMatchingFonts seems like the way to go then.

ashb commented 1 year ago

I've got some prototype code paths working (including my debug prints):

>>> c = __import__('windows_fonts').FontCollection()
>>> c.get_matching_fonts('Arial Narrow')
Set contains 4
Got font_ref IDWriteFontFaceReference(IUnknown(0x2332455d4a0))
Got font3 IDWriteFontFace3(IUnknown(0x233244f0a50))
Got ifamily IDWriteFontFamily(IUnknown(0x2332455e2b0))
Got family FontFamily(IDWriteFontFamily(IUnknown(0x2332455e2b0)))
<FontVariant name=Narrow, family=<FontFamily name="Arial">, style=Style.NORMAL weight=Weight.REGULAR>

The interface will likely be something like this once it's generalized:

c = FontCollection()
c.get_matching_variants(win32_family_names="Arial Narrow")

(I.e. you'll be able to search by any of the key names I added in #8 (one or more of them)

moi15moi commented 1 year ago

Cool :) Could you do an release on pypi?

ashb commented 1 year ago

v1.0.0 published on pypi btw.