Hello,
The specific question: how/where is (QFontEngine *)fe->ctfont set that is read
in QFontDialogPrivate::setFont (qfontdialog_mac.mm around line 514)?
I have been looking into an issue with the selection of fonts in weights/styles
that don't follow the usual four suspects (Normal, Italic, Bold, Bold-Italic).
In stock Qt 4.8, selecting a Medium or Semi Bold weight (i.e. a weight between
normal and bold) works during the initial selection (say in qtconfig's default
font selection), but open the font dialog once more, or relaunch the
application, and that medium weight will have been replaced by standard bold.
I think I have a fix for this in Qt 4.8, which removes the "easy shortcut" I
found in 2 places ("there's Normal and anything heavier which becomes Bold")
and extends the weight string parser to support most of the font weights you'll
find on a typical OS X install.
It turns out that almost inevitably I came up with code that looks a lot like
what had already been done for Qt 5.4 (I swear, I didn't peak :)) except that I
didn't introduce additional const variables to complement the existing
QFont::DemiBold etc. styles.
We're getting to the question.
When opening the font dialog with an initial font, Qt 4 calls
QFontDialogPrivate::setFont() where Qt 5.4 uses
QCocoaFontPanel::setCurrentFont() . Both functions (can) use [NSFontManager
fontWithFamily:traits:weight:size], but the Qt4 version is actually called with
fe->ctfont already set to the appropriate NSFont*.
And that seems to work more reliably. I have several fonts on my system
(including the Apple-provided Avenir family) where
fontWithFamily:traits:weight:size does *not* return the requested typeface, as
if the weight parameter is ignored. And indeed the documentation for that
function suggests that the weight parameter is used as a hint only
(https://developer.apple.com/library/mac/documentation/Cocoa/Reference/ApplicationKit/Classes/NSFontManager_Class/index.html#//apple_ref/occ/instm/NSFontManager/fontWithFamily:traits:weight:size:)
though I *hope* that it's used as more than a hint when the requested weight
actually exists.
Hence my question: where is fe->ctfont initialised? Clearly this uses a
different method for obtaining the NSFont (or CFFontRef).
Note that I've already tried to put all chances on my side for weight: to be
used as more than a hint. I've analysed the weights in question for all fonts
on my system (Apple's documentation doesn't bother to document the exact value
mapping), and came up with the following
+ // RJVB
+ // Thin,Light -> 3, Book -> 4
+ // Normal/Regular -> 5
+ // Medium/SemiBold/Demibold -> 6,7,8
+ // Bold -> 9
+ // Ultra/Black/Heavy -> 10,11
+ QByteArray *weights = NULL;
+ switch (font.weight()) {
+ case QFont::Light:
+ weights = new QByteArray((const char[]){3,4});
+ break;
+ case QFont::Normal:
+ weights = new QByteArray((const char[]){5});
+ break;
+ case QFont::DemiBold:
+ weights = new QByteArray((const char[]){6,7,8});
+ break;
+ case QFont::Bold:
+ weights = new QByteArray((const char[]){9});
+ break;
+ case QFont::Black:
+ weights = new QByteArray((const char[]){10,11});
+ break;
}
(evidently I did the same for Apple's other scale, that goes from -1.0 to 1.0).
I then test each of the weights corresponding to font.weight():
+ if (weights) {
+ nsFont = NULL;
+ for (int i = 0 ; i < weights->size() && !nsFont ; ++i) {
+ weight = (int) (*weights)[i];
+ nsFont = [mgr
fontWithFamily:qt_mac_QStringToNSString(fontInfo.family())
+ traits:mask
+ weight:weight
+ size:fontInfo.pointSize()];
+ }
+ delete weights;
+ }
the only thing I haven't yet added is an additional check whether
fontWithFamily did indeed return the requested weight, and not the closest
lower match (which would let DemiBold downgrade to Normal, or Ultra to Bold).
Thanks for bearing with me, and (even more :)) for any feedback!
R.
_______________________________________________
Development mailing list
[email protected]
http://lists.qt-project.org/mailman/listinfo/development