Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Issue with application of OpenType features #88

Closed
yanone opened this issue Jan 18, 2017 · 19 comments
Closed

Issue with application of OpenType features #88

yanone opened this issue Jan 18, 2017 · 19 comments

Comments

@yanone
Copy link
Contributor

yanone commented Jan 18, 2017

Hi,

I’m having issues applying OpenType features to text in a PDF.
I’ve rewritten my own renderer to write original drawBot code so I can test it in the main DrawBot.app to rule out problems with my own code.

For instance, the sups feature doesn’t apply.
I’ve collected the files to test here.
The example with the sups feature is in line 408 (result shows on page 3 in the PDF).
The feature gets turned on beforehand and turned off afterwards. I found this to cause less confusion in the rendering than explicitly setting all available features at once.

What puzzles me:
If I reduce the code to just the necessary lines to render that text with the sups feature, it renders fine (never mind that the feature isn’t written professionally yet, as in all the glyphs in the example would get replaced at the moment, not contextually...).
That means that somewhere along the way someone got confused with the commands to the point where features don’t get applied properly anymore.

So this works, which is exactly the same code, only much less:

import os

newPage(595.275590551, 841.88976378)
installFont(os.path.join(os.path.dirname(__file__), 'NonameSans-Regular.otf'))
installFont(os.path.join(os.path.dirname(__file__), 'NonameSans-Bold.otf'))

########################

cmykFill(0.0, 0.0, 0.0, 1.0, 1.0)
stroke(None)
strokeWidth(None)
lineHeight(28.8)

font('NonameSans-Bold')
fontSize(24)
language(None)
textBox(u'''120m2''', (255.118110236, 501.732283465, 141.732283465, 56.6929133858), align = 'center')

########################

fill(1.0, 0.411764705882, 0.490196078431, 1.0)
stroke(None)
strokeWidth(None)
lineHeight(24.0)

font('NonameSans-Regular')
fontSize(20)
language(None)
textBox(u'''→''', (396.850393701, 527.811023622, 28.3464566929, 28.3464566929), align = 'center')

########################

cmykFill(0.0, 0.0, 0.0, 1.0, 1.0)
stroke(None)
strokeWidth(None)
lineHeight(28.8)

font('NonameSans-Bold')
fontSize(24)
openTypeFeatures(sups=True)
language(None)
textBox(u'''120m2''', (425.196850394, 501.732283465, 141.732283465, 56.6929133858), align = 'center')
openTypeFeatures(sups=False)
@justvanrossum
Copy link
Collaborator

It would be nice if you could reduce the failing code to something as small as possible.

@yanone
Copy link
Contributor Author

yanone commented Jan 19, 2017

I know, but that’s where it gets complicated.
The complete file in the download link in the OP wouldn’t produce the expected result, for instance in line 408.
But as soon as I reduce the code (attempt made also in OP), it suddenly works as expected.
:/

@justvanrossum
Copy link
Collaborator

justvanrossum commented Jan 19, 2017

For me it is currently just too much and too complex to deal with. Try to change/remove small things at a time and try to zoom into the moment when it goes from "not working" to "working".

@yanone
Copy link
Contributor Author

yanone commented Jan 19, 2017

Right, I just understood myself what you meant by that. I'll do that and get back.

@yanone
Copy link
Contributor Author

yanone commented Jan 19, 2017

Okay, I found it. Just not really sure what to make of it.

This code works:

import os

newPage(595.275590551, 841.88976378)
fontName = installFont(os.path.join(os.path.dirname(__file__), 'NonameSans-Bold.otf'))
font(fontName)
fontSize(24)

########################

openTypeFeatures(sinf=True)
textBox(u'''C20H25N3O''', (425.196850394, 558.42519685, 141.732283465, 56.6929133858), align = 'center')
openTypeFeatures(sinf=False)

########################

openTypeFeatures(sups=True)
textBox(u'''120m2''', (425.196850394, 501.732283465, 141.732283465, 56.6929133858), align = 'center')
openTypeFeatures(sups=False)

With the sinf feature for the first textBox() both lines work, with subs instead of sinf (like in my previous code) neither work. I’ve also tried that with Adobe fonts to the same result.
I’m guessing that it goes back to the CoreText implementation of the OpenType features and doesn’t really have anything to do with DrawBot. Quite some pitfalls here with Apple’s implementation. They even implement features which aren’t in the font.

Thanks for pointing out how to find the problem and sorry for bothering.

So here’s another insider question: One could use compositor for compositing the features as it seems to be completely standard-compliant. Could one print glyphs into PDFs with DrawBot that aren’t encoded, as real text and not Bezier paths?

@justvanrossum
Copy link
Collaborator

Thanks, that's a great reduction. There's indeed something fishy here, and it may well be a DB bug.

@yanone
Copy link
Contributor Author

yanone commented Jan 19, 2017

Okay, if you put it that way, here’s another one that I didn’t mention yet:

A second sample that didn’t work for me was the ordn feature.
So the in the below code the third textBox() only shows the correct ordn substitution if sups lines are commented out. Once they’re in, the ordn breaks.

import os

newPage(595.275590551, 841.88976378)
installFont(os.path.join(os.path.dirname(__file__), 'NonameSans-Bold.otf'))
font('NonameSans-Bold')
fontSize(24)

########################

openTypeFeatures(sinf=True)
textBox(u'''C20H25N3O''', (425.196850394, 558.42519685, 141.732283465, 56.6929133858), align = 'center')
openTypeFeatures(sinf=False)

########################

#openTypeFeatures(sups=True)
textBox(u'''120m2''', (425.196850394, 501.732283465, 141.732283465, 56.6929133858), align = 'center')
#openTypeFeatures(sups=False)

########################

openTypeFeatures(ordn=True)
textBox(u'''1a 2o''', (425.196850394, 388.346456693, 141.732283465, 56.6929133858), align = 'center')
openTypeFeatures(ordn=False)

@justvanrossum
Copy link
Collaborator

Btw. font() and friends also take a path to a font file, so you don't have to use installFont().

@justvanrossum
Copy link
Collaborator

There seems to be a weird interaction between these features. @typemytype, can you have a look when you have time?

@typemytype
Copy link
Owner

weird interaction!! will have a look

@typemytype
Copy link
Owner

setting openTypeFeatures(None) helps as this clears the whole stack of openTypeFeatures.

somehow the off attribute in coreText is not correct https://github.com/typemytype/drawbot/blob/master/drawBot/context/tools/openType.py#L438

(if got this map from @behdad 's harfbuzz see https://github.com/behdad/harfbuzz/blob/master/src/hb-coretext.cc#L445)

@yanone
Copy link
Contributor Author

yanone commented Jan 19, 2017

Indeed, the openTypeFeatures(None) solved my issue. Thanks for taking the time.

Right, the kNormalPositionSelector attribute shows up for exactly all the features that I had problems with.

I’ll leave the issue open in case you want to get back to changing the attributes.
Otherwise, thanks again and see you here or elsewhere :)

@behdad
Copy link

behdad commented Jan 19, 2017

Anything I need to fix? I got the table from Apple...

@typemytype
Copy link
Owner

typemytype commented Jan 20, 2017

@behdad this is a drawBot issue, I guess

The order of features toggled on and off are taken from a dict and it happens when the openTypeFeature dict is something like dict(sups=True, sinf=False)

as dict keys are not ordered drawBot could first set the feature tag for sinf and then set the sups back to kNormalPositionSelector

Im hoping sorting the openTypeFeature dict by value False first would solve this.

@typemytype
Copy link
Owner

should be fixed here: 853d42f

@yanone
Copy link
Contributor Author

yanone commented Jan 20, 2017

I can confirm that the features get applied correctly now without resetting them using openTypeFeatures(None).
So I’m closing this issue. Thank you.

@yanone yanone closed this as completed Jan 20, 2017
@typemytype
Copy link
Owner

well the fix should apply the features correctly by disabling the feature with "sups"=False

@yanone
Copy link
Contributor Author

yanone commented Jan 20, 2017

Yes, it does.

@typemytype
Copy link
Owner

typemytype commented Jan 20, 2017

thanks! oef

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

4 participants