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

Toolkit-independent Font class #609

Merged
merged 12 commits into from
Oct 12, 2021
Merged

Toolkit-independent Font class #609

merged 12 commits into from
Oct 12, 2021

Conversation

corranwebster
Copy link
Contributor

@corranwebster corranwebster commented Jul 18, 2020

This is the color font class from #520 pulled out into a separate PR.

This does not include any of the string parsing, trait type, or dialog classes.

@codecov-commenter
Copy link

codecov-commenter commented Jul 18, 2020

Codecov Report

Merging #609 into master will increase coverage by 0.31%.
The diff coverage is 83.82%.

Impacted file tree graph

@@            Coverage Diff             @@
##           master     #609      +/-   ##
==========================================
+ Coverage   38.97%   39.28%   +0.31%     
==========================================
  Files         487      490       +3     
  Lines       26798    27002     +204     
  Branches     4066     4110      +44     
==========================================
+ Hits        10445    10609     +164     
- Misses      15897    15921      +24     
- Partials      456      472      +16     
Impacted Files Coverage Δ
pyface/qt/QtGui.py 81.48% <50.00%> (-9.00%) ⬇️
pyface/ui/wx/font.py 76.08% <76.08%> (ø)
pyface/ui/qt4/font.py 77.27% <77.27%> (ø)
pyface/font.py 95.34% <95.34%> (ø)
pyface/ui/qt4/util/gui_test_assistant.py 77.87% <0.00%> (-2.66%) ⬇️
pyface/ui/wx/window.py 74.69% <0.00%> (-2.41%) ⬇️
pyface/wx/python_stc.py 9.14% <0.00%> (-1.22%) ⬇️

Continue to review full report at Codecov.

Legend - Click here to learn more
Δ = absolute <relative> (impact), ø = not affected, ? = missing data
Powered by Codecov. Last update 0f3202b...2e72b66. Read the comment docs.

Copy link
Contributor

@rahulporuri rahulporuri left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM. Most of my comments are around documentation and a few questions.

pyface/qt/QtGui.py Outdated Show resolved Hide resolved
pyface/font.py Outdated Show resolved Hide resolved
# Note: we don't support 'medium' as an alias for weight 500 because it
# conflicts with the usage of 'medium' as an alias for a 12pt font in the CSS
# specification for font attributes.
WEIGHTS.update({
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is there a resource which points out how/why this map is defined the way it is?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

this and other maps which define similar associations

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

These come from the CSS spec, Qt and Wx constant names, true/open type font conventions, and in some cases (originally) from "traditional" values from the typesetting world (eg. the font weights date back to the fonts used in phototypesetting systems).

The CSS spec is probably the simplest comprehensive reference.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looks like we have some extra weights here compared to the CSS spec: https://www.w3.org/TR/css-fonts-3/#propdef-font-weight

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

More specifically, these are the values from CSS: normal | bold | bolder | lighter | 100 | 200 | 300 | 400 | 500 | 600 | 700 | 800 | 900
Where do the other values come from?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

As mentioned above, this wasn't just from the CSS spec - in particular it should at least include the mappings that Enable has here https://github.com/enthought/enable/blob/db84efa4d031fd641ebe097301a56764634ce21d/kiva/fonttools/_constants.py#L90-L105
as well as the names that Qt uses for weight constants: https://doc.qt.io/qt-5/qfont.html#Weight-enum
and the names wx uses: https://wxpython.org/Phoenix/docs/html/wx.FontWeight.enumeration.html
and the OpenType font weights: https://docs.microsoft.com/en-us/typography/opentype/spec/os2#usweightclass

More info can be found here: https://bigelowandholmes.typepad.com/bigelow-holmes/2015/07/on-font-weight.html

This is all very fuzzy because the names predate computerized fonts and most font families don't supply all weights.

pyface/ui/qt4/font.py Show resolved Hide resolved
pyface/ui/qt4/font.py Show resolved Hide resolved
pyface/ui/wx/font.py Show resolved Hide resolved
pyface/ui/wx/font.py Show resolved Hide resolved
pyface/ui/wx/font.py Show resolved Hide resolved
pyface/ui/wx/font.py Outdated Show resolved Hide resolved
pyface/font.py Show resolved Hide resolved
@rahulporuri

This comment has been minimized.

@corranwebster
Copy link
Contributor Author

I'd rather not - the round-tripping test was going for "cheap-and-cheerful", but if it's not generic then it's not particularly useful.

Better in that case is to have toolkit-specific tests that allow more fine-grained tests for what works in each permutation of back-ends.

'extraexpanded': 150,
'ultra-expanded': 200,
'ultraexpanded': 200,
}
Copy link
Contributor

@kitchoi kitchoi Jul 21, 2020

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Same here, CSS has these values: normal | ultra-condensed | extra-condensed | condensed | semi-condensed | semi-expanded | expanded | extra-expanded | ultra-expanded

I don't think we need the extra ones here given we document the fact that these values follow CSS convention.

QFont.ExtraLight: 'extra-light',
QFont.Light: 'light',
QFont.Normal: 'normal',
QFont.Medium: 'medium',
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Isn't this "medium" not allowed in the weight trait?
In fact, could we map all of these to "100", "200" and so on? Then QFont.Medium will be mapped to "500", which is allowed.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Getting back to this after a year, since this is just the descriptions with no attempt at font-name parsing, 'medium' should be allowed both here and in the weight trait as there is no conflict with other uses of medium at this level.

@kitchoi kitchoi changed the title Tooolkit-independent Font class Toolkit-independent Font class Aug 4, 2020
@corranwebster corranwebster added this to the Release 7.4.0 milestone Sep 28, 2021
@corranwebster
Copy link
Contributor Author

There seem to be a few review comments from #520 for...

Looking through these, I have checked off the ones that have been addressed. Of the others:

  • keeping weights to round numbers for now (we can always allow any number later) because:
    • CSS 2.x (which is roughly what we are modelling right now) only supports round values
    • Qt's numeric weights are non-linear from 0 to 99 rather than 0-1000, which is awkward
    • most of the time it will get rounded to something, and most fonts we will encounter in scientific computing will have round weight values
    • I'd need to write a new trait type to support it, rather than relying on Map
    • it feels very YAGNI to me right now
  • there is an issue with specifying multiple font families on Qt < 5.13 (we simply take the first specified, plus the first default family as a backup). Making this work like other systems is complex (eg. Enable, where we have a whole subsystem for this) or require the app to be running. Again, if we need it we can do it, but this feels like overkill for an old version of Qt when new versions of Qt just do what we want. It is possible we could pull the Enable font system into Pyface, but that also doesn't feel right.
  • I want a simple human-readable string representation (having it CSS-ish is nice, because it is likely to be understood) because the end-goal of this is for things like font editors in TraitsUI or Enable, and we want to be able to display the selected font unambiguously. It could be a separate method or function, but __str__ feels OK and I am not terribly worried about subclassing (again, YAGNI here, I think)
  • we can't do round-tripping tests for the toolkit objects because of things like the issue with Qt < 5.13, but we have smoke tests and I'm adding a couple more tests for things that should work independent of toolkit.

Copy link
Contributor

@rahulporuri rahulporuri left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM with a couple of minor comments

pyface/font.py Outdated Show resolved Hide resolved
pyface/font.py Outdated Show resolved Hide resolved
@corranwebster corranwebster merged commit 8a67099 into main Oct 12, 2021
@corranwebster corranwebster deleted the feat/font-class branch October 12, 2021 10:23
@corranwebster corranwebster mentioned this pull request Dec 21, 2021
1 task
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

Successfully merging this pull request may close these issues.

4 participants