Re: [Development] font selection and weight/style support on OS X: (possible regression from Qt 4 to Qt 5

2015-04-23 Thread Konstantin Ritt
In case you're on Qt 4.x, look at QFont - QString and QFont -
QDataStream (|de)serialization. I recall there was a bug fixed in ~5.3,
though I don't know if it was backported to 4.x.


Konstantin

2015-04-18 14:34 GMT+04:00 René J.V. rjvber...@gmail.com:

 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
 Development@qt-project.org
 http://lists.qt-project.org/mailman/listinfo/development

___
Development mailing list
Development@qt-project.org
http://lists.qt-project.org/mailman/listinfo/development


[Development] font selection and weight/style support on OS X: (possible regression from Qt 4 to Qt 5

2015-04-18 Thread René J . V . Bertin
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
Development@qt-project.org
http://lists.qt-project.org/mailman/listinfo/development