1

I'm trying to render text with a QPainter and I do not want anti-aliasing applied. I am fairly new to QT, so might be doing something wrong here. No matter what i've tried there is always some sort of antialiasing. I'll share my code below, which contains some commented lines on various different things that haven't worked

class TextExample : public QMainWindow {
protected:
    void paintEvent(QPaintEvent* aEvent) override {
        QPainter painter(this);

        painter.setRenderHint(QPainter::Antialiasing, false);
        painter.setRenderHint(QPainter::TextAntialiasing, false);
        painter.setRenderHint(QPainter::SmoothPixmapTransform, false);
        painter.setBrush(Qt::black);

        QFont myFont{"Times New Roman", 12};
        myFont.setStyleStrategy(QFont::NoAntialias);
        painter.setFont(myFont);

        // painter.drawStaticText(QPoint{0,0}, QStaticText{"Hello, world!"});

        painter.drawText(10, 50, "Hello, world!");

        // QTextDocument td;
        // td.setHtml("Hello, world!");
        // td.drawContents(&painter);
    }
};

int main(int aArgc, char *aArgv[]) {
    QApplication myApplication{aArgc, aArgv};

    // QFont myFont{"Informal Roman", 12};
    // myFont.setStyleStrategy(QFont::NoAntialias);
    // myFont.setStyleStrategy(QFont::NoSubpixelAntialias);
    // QApplication::setFont(myFont);

    for (const auto myStr : QFontDatabase::families()) {
        qDebug() << myStr;
    }

    TextExample myMainWindow;
    myMainWindow.setWindowTitle("Text Example");
    myMainWindow.resize(800, 600);
    myMainWindow.show();

    return myApplication.exec();
}

I am running this in qt 6.4.0 if that matters on windows 10

Something to note it does actually work with QPainterPath , but i'd prefer to avoid that since its more expensive and also seems to have other issues drawing text.

Another thing to note, is some fonts have no antialiasing so far as I can see, a good example is 'MS Sans Serif'. But produces for me a nice not-so-friendly warning, and similarly QT isn't respecting by strategies in enabling me to add antialiasing for these,

DirectWrite: CreateFontFaceFromHDC() failed (Indicates an error in an input file such as a font file.) for QFontDef(Family="MS Sans Serif", pointsize=12, pixelsize=16, styleHint=5, weight=400, stretch=100, hintingPreference=0) LOGFONT("MS Sans Serif", lfWidth=0, lfHeight=-16) dpi=144

Any help would be infinitely appreciated

NightShade
  • 422
  • 5
  • 19
  • The first answer to [this question](https://stackoverflow.com/questions/641401/disable-antialiasing-for-a-specific-gdi-device-context) would seem to indicate you're out of luck. Windows doesn't support it, so QT can't support it. Why the need, anyway? – Paul Sanders Mar 25 '23 at 00:29
  • Interesting, is that to say it just won't work for system fonts? As in if I get some custom TTF file will this work or am I completely misunderstanding? Thanks for the prompt response by the way @PaulSanders – NightShade Mar 25 '23 at 00:35
  • Okay thanks , what I want is probably beyond the scope of what you do know, and might be a whole different question in itself. Trying to find some times New Roman font that won't have this anti aliasing applied. Turns out not to be the easiest thing to search about either – NightShade Mar 25 '23 at 00:40
  • 1
    Sorry, I just read that answer more carefullly. In WIN32 land, you can write `my_logfont.lfQuality = NONANTIALIASED_QUALITY;`, which, you would have thought, QT would do for you with your code as written. If you build yourself a Debug version of QT (along with the corresponding PDB files) then you could walk it through in the debugger to see what it's getting up to. – Paul Sanders Mar 25 '23 at 00:41
  • Feel free to write a solution up with an example code snippet there and provided it all works I'll happily accept it – NightShade Mar 25 '23 at 00:48
  • I don't think I feel qualified. I know how you'd do it in pure WIN32, but I don't know QT, and presumably that's what you need, – Paul Sanders Mar 25 '23 at 00:51
  • 1
    Was able to finally get working in QT6 , will post an answer below for those who happen to run into in the future – NightShade Mar 25 '23 at 05:20

2 Answers2

3

Finally was able to determine the issue. The font strategies were being respected, but in Qt6 we have high DPI scaling unlike QT5 , of course you can disable that by setting the environment variable QT_ENABLE_HIGHDPI_SCALING to 0 (which also fixes it for me). However if you want to keep the DPI scaling, this is the solution I was able to find to work.

The reason it didn't work before is because the text is scaled to this higher resolution DPI and the scaling has the antialiasing automatically applied.

We need to tell Qt6 to try to choose its font sizing based on the target windows resolution. I was using a High DPI monitor, which is why I was never able to initially even see my posted solution works on a regular scaled monitor.

Just a warning, from reading the documentation this might not work on OSX, but feel free to add below if it did for the sake of others! This solutions works for Windows:

class TextExample : public QMainWindow {
    void paintEvent(QPaintEvent*) final {
        QFont myFont{"Times New Roman", 16};
        myFont.setStyleStrategy(QFont::NoAntialias);

        // THIS is the key line:
        myFont.setHintingPreference(QFont::HintingPreference::PreferFullHinting);

        QPainter myPainter{this};
        myPainter.setFont(myFont);
        myPainter.drawText(10, 50, "Hello, world!");
    }
};

int main(int aArgc, char *aArgv[]) {
    QApplication myApplication{aArgc, aArgv};

    TextExample myMainWindow;
    myMainWindow.setWindowTitle("Text Example");
    myMainWindow.resize(800, 600);
    myMainWindow.show();

    return myApplication.exec();
}

I really hope this helps someone someday, since this caused me a world of pain.

NightShade
  • 422
  • 5
  • 19
0

This is a bug in Qt.

The issue is unique to the DirectWrite back-end on Windows.

There is an alternate workaround, which is to disable DirectWrite by running the application with the -platform windows:nodirectwrite command line parameters:

your_application.exe -platform windows:nodirectwrite

Running the application this way will produce non-antialiased fonts as specified in the font strategy.

Jason C
  • 38,729
  • 14
  • 126
  • 182