0

I am trying to get the proper glyphs for a given string with DirectWrite. I am trying to enable the OpenType features for testing, in this case font ligature substitutions. I am using a font that contains the OpenType 'liga' tag has a separate glyph for ll.

Here is my code:

        text = 'Hello'

        analyze = IDWriteTextAnalyzer()
        self.font.write_factory.CreateTextAnalyzer(byref(analyze))

        tags = [DWRITE_FONT_FEATURE_TAG_STANDARD_LIGATURES]

        num_feature = len(tags)
        if num_feature:
            typo_features = DWRITE_TYPOGRAPHIC_FEATURES()
            typo_features.featureCount = num_feature

            typo_features.features = (DWRITE_FONT_FEATURE * num_feature)()
            for i in range(num_feature):
                typo_features.features[i] = DWRITE_FONT_FEATURE(tags[i], 1)

            feature_range = (UINT32 * num_feature)(len(text))
        else:
            typo_features = None
            feature_range = None

        max_count = int(3 * len(text) / 2 + 16)

        length = len(text)
        clusters = (UINT16 * length)()
        text_props = (DWRITE_SHAPING_TEXT_PROPERTIES * length)()
        indices = (UINT16 * max_count)()
        glyph_props = (DWRITE_SHAPING_GLYPH_PROPERTIES * max_count)()
        actual_count = UINT32()

        analyze.GetGlyphs(text,
                          len(text),
                          self.font.font_face,
                          False,  # sideways
                          False,  # righttoleft
                          script,  # scriptAnalysis
                          None,  # localName
                          None,  # numberSub
                          typo_features,  # typo features
                          feature_range,  # feature range
                          1,  # count
                          max_count,
                          clusters, # cluster map
                          text_props, # text props
                          indices, # glyph indices
                          glyph_props, #glyph pops
                          byref(actual_count)#glyph count
                          )

However, upon checking the return values it has 5 glyphs total, and the ligature indice is not shown in the glyph indices, just the original two l's: [43, 72, 79, 79, 82, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]

I am not sure if I am understanding it correctly. Am I incorrect in thinking it would substitute the two l's in the string for the ll glyph? Or is there another process where this indice becomes the true ligature? Any input is helpful as I am new to this. Thanks

Charlie
  • 680
  • 4
  • 11

1 Answers1

1

There is a number of things to check:

  • how 'liga' is defined by the font, which script/language pair is expected for it, what kind of lookup is used;
  • try simple test program using IDirectWriteTextLayout with same font to see if you get this ligature by default. If you do, it means 'liga' is enabled by default and you don't need to specify it as a user feature;
  • check you test code in more conventional environment first, like C/C++.
bunglehead
  • 1,104
  • 1
  • 14
  • 22
  • 1) Would this affect how the analyzer parses the information? 2) Using the TextLayout produces the correct result with the proper ligatures. Unfortunately I don't believe the TextLayout actually gives you all of the glyph information I need. I am trying to get just the shaped glyph indices and advances without rendering first. 3) I will try this in another environment to see if the actual glyph output changes, but wanted to make sure I was on the right track before recoding everything. – Charlie Jul 07 '20 at 15:57
  • I think I found it, it was an issue in the analysis script, I didn't think that would affect the way ligature's are selected but it does. – Charlie Jul 07 '20 at 17:33
  • Layout performs no rendering itself, it's using callback interface to tell you what to render, with all glyph and positions information, derived from what analyzer provided. But sure, script analysis structure specifies script id from that script/language pair I mentioned. Language is derived from locale. – bunglehead Jul 07 '20 at 19:33
  • That makes sense, thank you. After investigation there is a bug somewhere in that `SetScriptAnalysis` is getting called back twice from within DirectWrite somehow. The first call gets the correct script id (49), but the second call is overwriting the correct one with an incorrect one (1). I am unsure what could trigger that, but maybe an incorrect implementation somewhere I am thinking. – Charlie Jul 08 '20 at 02:31
  • @Charlie: An aside: What language are you writing in? (I've only every tried calling DWrite using C++.) The lack of ";" and use of ":" for `if...else...` is like Python, but I've no idea how one could call DWrite using Python. – Peter Constable Jul 08 '20 at 03:17
  • @Charlie SetScriptAnalysis will be called as many times as script changes. So it solely depends on the text you're passing in. – bunglehead Jul 08 '20 at 21:27
  • @bunglehead Makes sense, I got it now. Thank you for the assistance in narrowing this down. – Charlie Jul 10 '20 at 15:27
  • @PeterConstable I am using Python which allows me to interact with DLL's using the com interfaces. Mostly a side project to try and replace the GDI version we currently use to allow for more font features. – Charlie Jul 10 '20 at 15:28
  • @Charlie: I'll have to learn how to interact with COM interfaces in Python. If your project is in GitHub or somewhere, I'd be interested in taking a look. – Peter Constable Jul 10 '20 at 22:01