QML font rendering incorrectly - missing fine details - qt

So as the title says, i have font rendering issue with QML project, using macOS.
Image example
The font is in assets/fonts (local folder), and it's being added in main.qml through FontLoader, like 3 other fonts. All fonts but this one are rendering correctly, and as you can see in screenshot above, my system reads font correctly. All fonts i've loaded are .otf, i don't know if that is relevant to my issue.
Expected result:
My sample QML code is:
Text {
id: welcomeMessageTop
color: "blue"
text: "ASDFGHJKLT"
font.family :
fontLoaded.name
font.pixelSize: 110
font.letterSpacing: -0.4
}
Thanks

I suspect this may have something to do with the default approach to efficienty render dynamically resizable text in QML, which is via distance fields. It is a great way to have smoothly resizing raster graphics and get almost vector graphics like results, but it does eat away small details that do not stand out enough relative to the character size.
You should try setting renderType: Text.NativeRendering for the Text element to see if that helps.
Also, IIRC native text rendering looks pretty bad if your text is dynamic - if it is animated, rotated or its size changes dynamically. It is mostly useful for static stuff, but I suppose the text can be rendered at a larger size to an invisible item, and that item can be used as a shader source which then you can apply dynamic behavior and get results that are not horrific.
In the case you are going to be resizing or rotating the text, note that there are also some env vars that can be modified to tweak the distance field generation and get a better result:
qputenv("QT_DISTANCEFIELD_DEFAULT_BASEFONTSIZE", "64");
qputenv("QT_DISTANCEFIELD_DEFAULT_SCALE", "16");
qputenv("QT_DISTANCEFIELD_DEFAULT_RADIUS", "80");
The problem with that is it doesn't seem to be possible to tweak on a per-font basis, so if you increase the distance field resolution, it will end up eating more memory even for fonts that don't need it.

Related

How to avoid adding excess 1 pixel spacing by Qt Designer

I'm working on application for embedded and we have 256x64 grayscale screen. Qt 5.3 perfectly renders on that screen with -platform linuxfb option. Obviously, we save every pixel of space, so I faced with trouble: Qt Designer adds excess 1 pixel spacing for every layout element deeper in hierarchy. So they accumulate for the most deep widgets. More precisely, for some reason child element of layout components gets coordinates (1,1) relative to parent. So, it's true for every widget except for root widget. Picture below demonstrates accumulated spacings (thin and thick red lines), and (1,1) coordinates of the very first child widget.
I believe it's Qt behavior itself, not just Qt Designer issue (not tested yet). But I can't work further even if it's shown in Designer only: I need to have pixel-exact view while designing.
Of course, every spacing and margin of every component in form set to 0.
Manual coordinates assigning (from code) eliminates the problem of course, but I need to generate code by uic.
So, my question is: how to avoid such spacings? Fixing Qt core sources can be (hard) option too, since anyway we recompile Qt for the project.
Mirror post on Qt forums
Thanks.
Ilia.
If you select Form > View Code, you can see that the geometry is not actually used for widgets which are inside a layout. So the numbers you see in the Property Editor are purely informational and have no relevance to the eventual code that is generated from the ui file (which is why they are greyed out).
The one pixel offset is there because Qt Designer needs space to draw the red boxes around layouts. They have to be be represented somehow, so I don't see how this can be avoided given the way Qt Designer currently works. If you want a more accurate reprentation of the final results, I suppose you will have to show a preview.
There is a facility in Settings > Preferences > Embedded Design that allows you to specify device profiles (which determine things like style, font, and screen resolution). This will add a new entry to the Preview In menu, which should allow you to refine the accuracy of the previews even further.

Poor text scaling with Qt Quick 1.1 / QML

I am developing a software application using Qt 4.8.4 (MSVC 2010) on a Windows 7 PC. I have just made the switch from the QWidget framework to the QML / QtQuick 1.1 declarative framework however I have noticed that in QtQuick/QML, text scaling is quite poor. Letters are often cut off or skewed slightly.
In the image below, the text has been scaled due to a window resize yet it looks different everytime.
Here is the scaling function that I used:
scale: paintedWidth > maxWidth ? Math.max((maxWidth / Math.max(paintedWidth, 1)), 0.1) : 1
Basically this scaling function scales the text down only if it is larger then the size of the container that it is in. It works as it should.
I was just wondering if there is any possible way to improve text scaling in QML/Qt Quick 1.1 and if anyone else has noticed this issue?
I know that some work has been done in regards to text scaling in QtQuick 2 but unfortunately upgrading our UI to QtQuick 2 is not a possibility right now due to compatibility issues.
The first thing to try is setting smooth: true
If you're animating the scaling then you may still notice irregularities due to hinting as the fonts are rendered at different sizes. You may have some success in forcing the Text element into a code path that caches the text to an image, which will then be scaled, rather than painting the text directly:
smooth: true
style: Text.Raised
styleColor: "transparent"
Another reason for the appearance you're getting may be that the text is not being positioned pixel aligned, i.e. y is not a whole number, or y of a parent element is not a whole number.

QPainter::rotate disables antialiasing of drawn text

I use QPainter::setRenderHint(QPainter::Antialiasing, true) to tell Qt that I want it to antialias any drawing I do (in this case, text drawn with drawText()).
This works fine and the text looks good, until I want to rotate the pixmap I'm drawing to e.g.
Painter.translate(0, height());
Painter.rotate(-90);
(to rotate the QPainter 90 degrees counterclockwise and bring it back into view)
The call to rotate() seems to disable antialiasing for any text drawn - the text is drawn at the correct rotation but without antialiasing. Other things seem unaffected - e.g. drawLine() still draws a nicely antialiased line.
Any idea what I'm doing wrong?
EDIT: Unsurprisingly, adding the text to a path and then filling that path gives me antialiased, rotatated text. I'd rather avoid this route if possible though.
EDIT (again): I've tried using QFont::setStyleStrategy(QFont::PreferAntialias) on the font I'm using, with no effect. However, some more experimentation shows that a basic font like Arial will still produce antialiased text when rotated, whereas my custom font (Swiss721 BlkCn BT for anyone who's interested) will not. Moreover, while this problem exists on Windows 7, I don't have the same issue when running on Ubuntu. This FAQ article would seem to suggest that Qt looks to the host OS to handle font antialiasing, so what kind of issues might Windows have in handling the rendering of this particular font (which is a TrueType, just like Arial)?
EDIT (last time, I promise): Upping the font size to 16pt or above kills the problem. It would seem that the issue is with rendering my particular font below 16pt - perhaps something to do with what was mentioned in the above blog article?:
On Windows 2000 fonts are usually not antialiased within a certain range (say sizes 8-16) to make text more crisp and readable.
I've actually had occasion to be in this part of the Qt code recently, and I think the behavior you are seeing is related to the following two bugs in Qt:
https://bugreports.qt.io/browse/QTBUG-21377
https://bugreports.qt.io/browse/QTBUG-20900
If I remember correctly (not 100%) sure, what you are actually seeing is the loss of the ClearType rendering on Windows. When there is a transformation applied, Qt gets the glyph pixels in a way that throws out the ClearType information, so things look more jagged.
If you wanted to look at the code yourself, the most likely place is /src/gui/text/qfontengine_win.cpp. You could also try turning off ClearType and see if they look similar.
One "guess" concerns your RenderHint. You use QPainter::Antialiasing here. Docu: "Indicates that the engine should antialias edges of primitives if possible." Primitives like lines, rects, etc. Try QPainter::TextAntialiasing instead.
Note: The RenderHints are flags, so you can bit-OR them if need be (and sounds like it is).

Large serifs in a font cause flash to measure size incorrectly

I have a textarea where I measure the textWidth and textHeight to make sure the user cannot enter more text than can fit in the text area. I also extended the textArea with a textHeightNow and textWidthNow that measure the textField's dimensions since they update w/out requiring validation. Now this works great for 90% of the embedded fonts I'm using but any fonts that have giant serifs are not measured properly, for instance look at the 'f's in this text area:
alt text http://img.skitch.com/20091101-xhm5jguma1qgukg6fxrymrwr3u.jpg
You can see they get cut off on both sides because textWidth and textWidthNow both return an incorrect size not taking into account the massive serifs. The font size, coords and dimensions of the text area are all integers so thats not the problem, any other suggestions? I looked to see if textArea has a clipContent argument but it doesn't (that would have been nice).
Thanks
I've run into this problem before and as far as I can tell you have two options, none of them very nice:
Use the new flash.text.engine in
Flash Player 10... its very hard to use but
I think it will measure such fonts
(and ligatures) properly.
Draw the textfield into a bitmapdata
and use getColorBoundsRect to
determine its real dimensions.
I ended up using the latter as changing the whole app to the new engine would have been much much harder. You will need to tweak margins and use a larger textfield (inside some container) to be able to draw it properly, but it should work.

Differing DPI [font sizes] in QWebView compared to all other QWidgets?

I have a QWebView which displays some HTML content and I used CSS to style the text:
body { font-size: 10pt; }
The window with the QWebView also has a QTextEdit field, for which I have set the font like this:
QFont newFont;
newfont.setPointSize(10);
myEditField->setFont(newFont);
Unfortunately, the text displayed in the QWebView is slightly larger than the text displayed in the QTextEdit. I have a feeling that this has something to do with DPI settings being different in the QWebView.
Is there a way to get the same font sizes displayed for both the QWebView and the QTextEdit?
Thanks!
Explanation of this behavior has been given on the bugreports:
It appears to be true that WebKit assumes 96 dpi as a fixed resolution. If this is how web content is designed then we have a problem changing that, because there are other people that expect WebKit to render web content like in web browsers.
See also https://www.webkit.org/blog/57/css-units/
They suggested two solutions:
QWebView provides setZoomFactor and setTextMultiplier which I believe could be used to get the desired behaviour (matching the QWidget ).
You can calculate zoom factor and text multiplier using current DPI:
QWidget* window = QApplication::desktop()->screen();
const int horizontalDpi = window->logicalDpiX();
m_view->setZoomFactor(horizontalDpi / 96.0);
Using QWebSettings::ZoomTextOnly you can apply zooming to the text only.
This is a little tricky. I found a good way to get accurate DPI measurements is from QApplication, example:
QWidget* window = QApplication::desktop()->screen();
int horizontalDpi = window->logicalDpiX();
As far as font goes, you can use QWidget::fontMetrics() to get a good font metrics information.
I think a combination of both will give you some consistency between your web view and text edit.
Good luck.

Resources