Trolltech Home | Qt-interest Home | Recent Threads | All Threads | Author | Date
All threads index page 3

Qt-interest Archive, January 2007
Font point size on X11


Message 1 in thread

Hi,

I'm working on KOffice and there we use points for the document coordinate
system. We transform the document to the view system by using
QPainter::scale() and the dpi information from X11Info for the scaling
factors in order to match real world units on screen.

So far, so good. But QPainter also makes implicitly use of X's dpi
information. It converts the font's point size to pixels with this info.
So, now we scale the font twice. Fonts in the UI and in our canvas will get
different sizes (given an X dpi != 72 or 75).

I tried to hardcode the dpi setting by reimplementing
int QWidget::metric(PaintDeviceMetric metric) const,
but it seems to be ignored. Example code attached.

Could anyone explain me why it does not work?

Any other ideas to prevent the double scaling (while keeping the text's
correct position)? I already tried to rescale the point size by dividing it
by the y dpi, but it looks so unclean and one would have to do it in many
places.

Regards,
Stefan

#include <QApplication>
#include <QApplication>
#include <QMainWindow>
#include <QPainter>

class MainWindow : public QMainWindow
{
public:
    void paintEvent( QPaintEvent* event )
    {
        Q_UNUSED( event );
        QPainter painter( this );
        painter.drawText( QPointF( 10., 20. ), "Hello" );
    }

protected:
    int metric( PaintDeviceMetric metric ) const
    {
        switch( metric )
        {
            case QPaintDevice::PdmDpiX:
            case QPaintDevice::PdmDpiY:
            case QPaintDevice::PdmPhysicalDpiX:
            case QPaintDevice::PdmPhysicalDpiY:
                return 72;
            default:
                break;
        }
        return QMainWindow::metric( metric );
    }
};

int main(int argc, char **argv)
{
    QApplication app(argc, argv);
    MainWindow mainWin;
    mainWin.show();
    return app.exec();
}


Message 2 in thread

Hi,

Hi know that this is a faq, homewer i want to complete this faq with another
request :

* What is the best way for doing a single instance application ( answers
from the newsgroups don't seem to be the way i want to )
* How i can do to make my 2 instance communicate ? In fact, i need to ask to
first instance to open the file request by the second.

Thanks, P@sNox,

--
 [ signature omitted ] 

Message 3 in thread

Hi,

there are several ways for IPC. You could use shared memory or a file. 
I'd recommend QSingleInstanceApplication but as you said that doesn't 
satisfy you (probably an open-source user like I am, thus no access to 
the add-on classes :-).

Regards,
Thomas

Nox PasNox schrieb:
> Hi,
> 
> Hi know that this is a faq, homewer i want to complete this faq with another
> request :
> 
> * What is the best way for doing a single instance application ( answers
> from the newsgroups don't seem to be the way i want to )
> * How i can do to make my 2 instance communicate ? In fact, i need to ask to
> first instance to open the file request by the second.
> 
> Thanks, P@sNox,
> 
> --
> To unsubscribe - send a mail to qt-interest-request@xxxxxxxxxxxxx with "unsubscribe" in the subject or the body.
> List archive and information: http://lists.trolltech.com/qt-interest/
> 
> 

--
 [ signature omitted ] 

Message 4 in thread

besides that this has nothing to do with QT... Ill give you some feedback in the form of questions :-)
 
Are the two instances always on the same machine?  
How do the two instances know about each other?
How should they handle exceptions to the communication protocol?

I have used TCP sockets for this, I have used a lightweight WWW server for this, I have used files on the local filesystem.  I no longer create my own protocol, and rather simply use XML for it, but all these methods could use QT or not.
 
Scott
 

________________________________

From: Nox PasNox [mailto:pasnox@xxxxxxxxx]
Sent: Wed 1/17/2007 8:51 AM
To: qt-interest@xxxxxxxxxxxxx
Subject: Single Application Instance - Inter Application Messaging



Hi,

Hi know that this is a faq, homewer i want to complete this faq with another
request :

* What is the best way for doing a single instance application ( answers
from the newsgroups don't seem to be the way i want to )
* How i can do to make my 2 instance communicate ? In fact, i need to ask to
first instance to open the file request by the second.

Thanks, P@sNox,

--
 [ signature omitted ] 

Message 5 in thread

Thanks about this methods that are not bad ! 
I will try to implement this methods.

Cheers, P@sNox,

Scott Aron Bloom wrote:

> besides that this has nothing to do with QT... Ill give you some feedback
> in the form of questions :-)
>  
> Are the two instances always on the same machine?
> How do the two instances know about each other?
> How should they handle exceptions to the communication protocol?
> 
> I have used TCP sockets for this, I have used a lightweight WWW server for
> this, I have used files on the local filesystem.  I no longer create my
> own protocol, and rather simply use XML for it, but all these methods
> could use QT or not.
>  
> Scott
>  
> 
> ________________________________
> 
> From: Nox PasNox [mailto:pasnox@xxxxxxxxx]
> Sent: Wed 1/17/2007 8:51 AM
> To: qt-interest@xxxxxxxxxxxxx
> Subject: Single Application Instance - Inter Application Messaging
> 
> 
> 
> Hi,
> 
> Hi know that this is a faq, homewer i want to complete this faq with
> another request :
> 
> * What is the best way for doing a single instance application ( answers
> from the newsgroups don't seem to be the way i want to )
> * How i can do to make my 2 instance communicate ? In fact, i need to ask
> to first instance to open the file request by the second.
> 
> Thanks, P@sNox,
> 
> --
> To unsubscribe - send a mail to qt-interest-request@xxxxxxxxxxxxx with
> "unsubscribe" in the subject or the body. List archive and information:
> http://lists.trolltech.com/qt-interest/
> 
> 
> 
> --
> To unsubscribe - send a mail to qt-interest-request@xxxxxxxxxxxxx with
> "unsubscribe" in the subject or the body. List archive and information:
> http://lists.trolltech.com/qt-interest/

-- 
 [ signature omitted ] 

Message 6 in thread

Stefan Nikolaus wrote:

> I'm working on KOffice and there we use points for the document coordinate
> system. We transform the document to the view system by using
> QPainter::scale() and the dpi information from X11Info for the scaling
> factors in order to match real world units on screen.

What exactly do you pass to QPainter::scale() and how do you calculate the
scaling factors?

> So far, so good. But QPainter also makes implicitly use of X's dpi
> information.
> It converts the font's point size to pixels with this info.

Yes, it needs the information for each specific device to do this.

> So, now we scale the font twice.

Yes, it would appear so but, if your original units are points, why aren't
you using those when calling font rendering functions?

> Fonts in the UI and in our canvas will 
> get different sizes (given an X dpi != 72 or 75).

[...]

> Any other ideas to prevent the double scaling (while keeping the text's
> correct position)? I already tried to rescale the point size by dividing
> it by the y dpi, but it looks so unclean and one would have to do it in
> many places.

I'm confused about the overall rendering model you're using. If you can
supply code that illustrates the problem, it would be useful.

It seems to me that, since you're specifying document measurements in
points, you need to scale all these using the DPI information from QX11Info
(or using the widget's own metrics) to obtain values you can use in pixel-
based functions. If you are using font metrics, you need to pass the device
to the QFontMetrics[F] constructor to ensure that measurements are correct
for that device, but this normally only matters for tasks such as printing.

David

--
 [ signature omitted ] 

Message 7 in thread

David Boddie wrote:
> What exactly do you pass to QPainter::scale() and how do you calculate the
> scaling factors?

scale( QX11Info::appDpiX() / 72, QX11Info::appDpiY() / 72 );

These are pixel/point ratios (QX11Info gives us the pixels/inch and
1"=72pt).

>> So, now we scale the font twice.
> 
> Yes, it would appear so but, if your original units are points, why aren't
> you using those when calling font rendering functions?

The font size is set by using QFont::setPointSizeF(). Is this what you
meant?

> I'm confused about the overall rendering model you're using. If you can
> supply code that illustrates the problem, it would be useful.

Apply the above scaling factors to the code I posted. And then, use the same
font and size as you specified in your UI (qtconfig or kcontrol). If you
have X dpi values unequal 72 dpi (75 dpi), you'll notice, that the fonts
have different sizes. The more deviation the worse.

> It seems to me that, since you're specifying document measurements in
> points, you need to scale all these using the DPI information from
> QX11Info (or using the widget's own metrics) to obtain values you can use

Correct.

> in pixel- based functions. If you are using font metrics, you need to pass
> the device to the QFontMetrics[F] constructor to ensure that measurements
> are correct for that device, but this normally only matters for tasks such
> as printing.

I don't see the use case for QFontMetrics here. I want to set the font size,
so that the font after the QPainter::scaling matches that of the UI.

Stefan

--
 [ signature omitted ] 

Message 8 in thread

Stefan Nikolaus wrote:

> David Boddie wrote:
>> What exactly do you pass to QPainter::scale() and how do you calculate
>> the scaling factors?
> 
> scale( QX11Info::appDpiX() / 72, QX11Info::appDpiY() / 72 );
> 
> These are pixel/point ratios (QX11Info gives us the pixels/inch and
> 1"=72pt).

OK. Just out of interest, do the values returned by appDpiX() and appDpiY()
correspond to the physicalDpiX() and physicalDpiY() of the widget?

>>> So, now we scale the font twice.
>> 
>> Yes, it would appear so but, if your original units are points, why
>> aren't you using those when calling font rendering functions?
> 
> The font size is set by using QFont::setPointSizeF(). Is this what you
> meant?

Yes. Since you're already scaling the painter's output, so that you can
specify dimensions in points, you need to set the font size using
setPixelSize() instead. Otherwise, as you noticed, the value you specify
will be converted internally to a value (the pixel size) which would
normally be used unscaled. You are then scaling that again using
QPainter::scale(), causing the scaling to be applied twice.

The problem with using setPixelSize() is that there's no way to get the
precision you need for small font sizes.

>> I'm confused about the overall rendering model you're using. If you can
>> supply code that illustrates the problem, it would be useful.
> 
> Apply the above scaling factors to the code I posted. And then, use the
> same font and size as you specified in your UI (qtconfig or kcontrol). If
> you have X dpi values unequal 72 dpi (75 dpi), you'll notice, that the
> fonts have different sizes. The more deviation the worse.

I'm not sure that you should really be trying to override the metrics of the
widget like that, but maybe I've misunderstood what you're trying to
achieve. You should be able to get what you want by scaling the painter's
output (as you are doing) and pretending that the point size you supply is a
pixel size (since it will be scaled by the painter).

However, I think you might get better results when drawing text to avoid
scaling for the actual text drawing operations, though I do realize that
this might make the rendering model you have more complicated.

> I don't see the use case for QFontMetrics here. I want to set the font
> size, so that the font after the QPainter::scaling matches that of the UI.

It's just another issue you may encounter later.

David

--
 [ signature omitted ] 

Message 9 in thread

David Boddie wrote:
> OK. Just out of interest, do the values returned by appDpiX() and
> appDpiY() correspond to the physicalDpiX() and physicalDpiY() of the
> widget?

Yes, but they are used for both, physical and logical.

> Yes. Since you're already scaling the painter's output, so that you can
> specify dimensions in points, you need to set the font size using
> setPixelSize() instead. Otherwise, as you noticed, the value you specify
> will be converted internally to a value (the pixel size) which would
> normally be used unscaled. You are then scaling that again using
> QPainter::scale(), causing the scaling to be applied twice.

No, by using the QFont::setPointSizeF method I specify the device
independent size. And if I draw text with a QPainter and this font the
pixel size has to obey to the paint device metrics, i.e. the font size
should not use the X dpi setting in this case. And if I then scale it with
the X dpi based factors, I expect the font being the same size as on
unscaled painting on an unmodified (metrics) widget.

Regards,
Stefan

--
 [ signature omitted ] 

Message 10 in thread

On Wednesday 17 January 2007 17:41, Stefan Nikolaus wrote:
> Hi,
>
> I'm working on KOffice and there we use points for the document coordinate
> system. We transform the document to the view system by using
> QPainter::scale() and the dpi information from X11Info for the scaling
> factors in order to match real world units on screen.
>
> So far, so good. But QPainter also makes implicitly use of X's dpi
> information. It converts the font's point size to pixels with this info.
> So, now we scale the font twice. Fonts in the UI and in our canvas will get
> different sizes (given an X dpi != 72 or 75).
>
> I tried to hardcode the dpi setting by reimplementing
> int QWidget::metric(PaintDeviceMetric metric) const,
> but it seems to be ignored. Example code attached.
>
> Could anyone explain me why it does not work?
>
> Any other ideas to prevent the double scaling (while keeping the text's
> correct position)? I already tried to rescale the point size by dividing it
> by the y dpi, but it looks so unclean and one would have to do it in many
> places.

Your observation is correct. QPainter::drawText() always scales text where the 
corresponding font is specified in points to the device's resolution. You 
have to agree that this is sensible behavior :)

Your approach  of overriding metric() doesn't work when you paint onto a 
widget because of double-buffering. With double-buffering enabled (by 
default) you actually end up painting into a pixmap (the backing store) and 
Qt will copy that onto the screen in one go when painting finished, to 
prevent flicker.

If you set the Qt::WA_PaintOnScreen attribute on your widget you'll see that 
the metric() is used and you will also observe flicker.

With the use of the low-level QTextLayout class to draw text on your 
widget/device you have full control over the conversion from points to device 
pixels. That's what Thomas is using in KWord's text bits, too (for variables 
in KoVariable and counters in KoTextDocumentLayout). I think it's the best 
approach. Alternatively you can do the points to pixel conversion entirely 
yourself and set a pixel size on the QFont object for use with 
QPainter::drawText.


Simon

Attachment:

Attachment: pgpG306tV9Dme.pgp
Description: PGP signature


Message 11 in thread

Simon Hausmann wrote:

> With the use of the low-level QTextLayout class to draw text on your
> widget/device you have full control over the conversion from points to
> device pixels. That's what Thomas is using in KWord's text bits, too (for
> variables in KoVariable and counters in KoTextDocumentLayout). I think
> it's the best approach. Alternatively you can do the points to pixel
> conversion entirely yourself and set a pixel size on the QFont object for
> use with QPainter::drawText.

I haven't checked the code in detail yet, but as far as I can see on screen, 
it also scales the font twice. :(

I filed a bug meanwhile and attached a new test case, that shows a 36 pt
font aligned with a 36 pt line. I think, you have access to it ("[Issue
N147309] Fonts ignore paint device's metrics"). It does not take your
QTextLayout suggestion into account though.

Regards,
Stefan

--
 [ signature omitted ]