summaryrefslogtreecommitdiffstats
path: root/src/gui/text
Commit message (Collapse)AuthorAgeFilesLines
* QFontEngine: Replace divisions by bitshiftsRobert Löhning37 hours1-3/+3
| | | | | | | | | | | ...so static code checkers will not complain about ignoring remainders or fractional parts of the division anymore. Change-Id: If57e1d3a9229424ac382c5f1f6aee8ddba481714 Coverity-Id: 898602 Coverity-Id: 898603 Pick-to: 6.11 6.10 6.8 6.5 Reviewed-by: Edward Welbourne <edward.welbourne@qt.io>
* Doc: Qt Gui: Mark private APIs \internalTopi Reinio37 hours4-3/+8
| | | | | | | | | | Resolves multiple QDoc warnings of type "No output generated for X::Y because X is undocumented." Pick-to: 6.11 Task-number: QTBUG-141665 Change-Id: I6a597f6979151565fcee36964f892976964be75d Reviewed-by: Topi Reinio <topi.reinio@qt.io>
* QWindowsFontDatabase: Fix build issues when disabling DirectWriteKenji Mouri3 days2-0/+8
| | | | | | | Pick-to: 6.11 Change-Id: I0b2bf2983edb2f95b134f6812dab05bc633b52fc Reviewed-by: Zhao Yuhang <2546789017@qq.com> Reviewed-by: Joerg Bornemann <joerg.bornemann@qt.io>
* QFont: fix operator<() pt.2: comparing QMapsMarc Mutz4 days1-27/+6
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | While the first patch fixed the obvious issue of lexicographically comparing an unordered container, this one might or might not fix something. But this author requires the peace of mind of having a known-good STL algorithm do the heavy lifting instead of being forced to analyze a raw loop, so this patch replaces said raw loops (and the suspicious size check that preceded them) with std::lexicographical_compare() calls, which, despite its name, implements op< semantics, and is proven by way-more-capable programmers than yours truly (i.e. Alex Stepanov and David Musser) to yield a strict weak ordering when the parametrized comparator is one (which it is, in this case, recursively, as std::pair's op< is also defined to use lexicographical ordering). As such, it's only now that I feel comfortable in saying that this operator is a strict weak ordering again. [ChangeLog][QtGui][QFont] Fixed a Qt 6.7 regression in the stability of the less-than operator. If you use QFont as keys in a QMap/std::map, or otherwise use QFont ordering (equality is ok), then we strongly recommend to update. Amends 6160ea45b689e9d26795a18f155053ac4dc4dd6b. Pick-to: 6.11 6.10 6.8 Fixes: QTBUG-142246 Change-Id: I1c96289af9326c7020f67674c148beca78791304 Reviewed-by: Volker Hilsheimer <volker.hilsheimer@qt.io>
* gui: fix build with -qreal floatNick Shaforostov5 days2-4/+4
| | | | | | | | | | | | | | | in several places INT_MAX was implicitly converted to qreal. when qreal is float, the compiler warns: implicit conversion from 'int' to 'float' changes value from 2147483647 to 2147483648 [-Wimplicit-const-int-float-conversion] the conversion is made explicit now also in qfontengine.cpp operands are reordered to let compiler pre-calculate part of the expression Pick-to: 6.11 6.10 6.8 6.5 Change-Id: I7cba0f95e38d10f661dca9f085cf024a6f8a5f52 Reviewed-by: Eirik Aavitsland <eirik.aavitsland@qt.io>
* src/gui/text: port away from QPairAhmad Samir5 days5-9/+13
| | | | | | | Pick-to: 6.11 6.10 6.8 6.5 Task-number: QTBUG-115841 Change-Id: I0d5bd83090b951dc3b6b53c875404201823751dd Reviewed-by: Marc Mutz <marc.mutz@qt.io>
* Use quint32 for QRawFont::glyphCount() return typeTor Arne Vestbø8 days2-2/+2
| | | | | | | Aligns with the existing APIs in the class. Change-Id: Ia9f11138d93b37995c8084fd9a25070554cec7db Reviewed-by: Marc Mutz <marc.mutz@qt.io>
* QTextEngine: fix Coverity warning about overflowing an uintMarc Mutz8 days1-1/+1
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | Coverity complained that the while loop being changed by this patch overflowed last_cluster from its initial ~0u value in the post-increment operation. It's correct that we overflow, but the old code wasn't wrong: unsigned overflow is well-defined as mod 2^n, n = bit-width of the type, so we overflow to zero, but then, two lines further down, unconditionally overwrite said zero again. If we overflowed, that means that last_cluster was still at ~0u, so cannot possibly have compared < that `cluster`, another uint variable, so we couldn't get into the situation that the loop continues because of 0 < cluster. So this doesn't _need_ fixing, but in the spirit of "if Coverity doesn't understand it, a human won't, either", let's improve the code nonetheless. Observe that last_cluster is being used both as the loop counter as well as to hold the value across an outer loop. Separating the two roles by introducing a dedicated loop counter shows that this is just your typical run-of-the-mill for loop, so rewrite it as such. Amends c77222c0e711d584bec880222412fc50d044005f (5.3). Pick-to: 6.10 6.8 6.5 Coverity-Id: 898027 Change-Id: I8184bddc88e24a4a6612309ae59b64b99ca4c2d7 Reviewed-by: Edward Welbourne <edward.welbourne@qt.io>
* Remove Qt 2 compatibility code in QFont::fromString()Vlad Zahorodnii10 days1-12/+3
| | | | | | | | | | | | 37c68503cbada547291ec4c4873dc054a8b82510 added the "count == 9" guard, which effectively disabled the Qt 2 compatibility code. Given that that compatibility code has been off for almost 5 years, there is probably little point in fixing it now, so we might as well remove it to simplify the QFont::fromString() function. Change-Id: I677a033c74616c4cb5f24b750f47837d3ab75da8 Reviewed-by: Eskil Abrahamsen Blomfeldt <eskil.abrahamsen-blomfeldt@qt.io>
* Include variable axes in QFont::toString()Vlad Zahorodnii11 days1-12/+53
| | | | | | | | With this change, variable axes can be saved and loaded from settings. Task-number: QTBUG-141412 Change-Id: I0744d05cc38ac47d89f3e4314311906c28c0ec63 Reviewed-by: Eskil Abrahamsen Blomfeldt <eskil.abrahamsen-blomfeldt@qt.io>
* QFont: cut out the QMap sorter in toString()Marc Mutz11 days1-5/+1
| | | | | | | | | | | | | The QMap shouldn't have been used as a sort() replacement, but now that 'features' is itself a QMap, we can skip this step. Amends 8fe6ad3eed40a8c851bf5d49e322f9794b9f7dcf. Task-number: QTBUG-141412 Task-number: QTBUG-142246 Change-Id: Ia40f82a776758a18ce057b49769ac38f3d2fdddb Reviewed-by: Eskil Abrahamsen Blomfeldt <eskil.abrahamsen-blomfeldt@qt.io> Reviewed-by: Vlad Zahorodnii <vlad.zahorodnii@kde.org>
* QFont: fix operator<()Marc Mutz11 days3-4/+4
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | Even though the docs try to dismiss any guarantees as to the behavior of the operator, they do mention it's there to make QFont usable as keys in QMap. QMap, being a wrapper around std::map, requires the key type to be sorted using a strict weak ordering. The current QFont::operator<() is not a strict weak ordering. In particular, because of the way the `features` QHash is compared (lexicographically, as far as I can make out), and due to the nature of QHash as an unordered container, it can easily happen that two QFont objects compare equal, but one is _also_ less than the other, according to this operator. To see this, consider that two QHash objects are equal if their linearizations are permutations of each other, but that doesn't mean that these linearizations need to be lexicograpically equal: {{1, 2}, {2, 4}} is a permutation of {{2, 4}, {1, 2}}, but the former is lexicographically strictly less the latter. The minimal fix is to use a QMap instead of a QHash. QMaps are ordered, so their linearizations are stable. A more comprehensive fix would kick out the QMap for either the std::map original, which, unlike QMap, already provides operator< that we could just use, or QFlatMap, depending on how many elements we expect in this container. Due to the leakage of of these types into other parts of the code, including public API in QTextFormat, that would be a larger undertaking, so is left for another day. I am not, yet, fully convinced that the preceding size() check does not also break strict-weak-ordering'ness, but at least it will not cause _equal_ fonts to be reported as strictly less, too. A port to lexicographical comparison would remove the last doubt, but is left for a follow-up patch. Amends 6160ea45b689e9d26795a18f155053ac4dc4dd6b. Task-number: QTBUG-142246 Pick-to: 6.10 6.8 Change-Id: I3db7b370592e100efaf5148e4c0e91d1d1925830 Reviewed-by: Eskil Abrahamsen Blomfeldt <eskil.abrahamsen-blomfeldt@qt.io> Reviewed-by: Vlad Zahorodnii <vlad.zahorodnii@kde.org>
* QRawFont: de-inline two-arg advancesForGlyphIndexes()Marc Mutz12 days2-11/+11
| | | | | | | | | | | | | | | | | Functions in which owning containers allocate should not be defined inline, because of the amount of code generated. Unlike similar changes in the past, this wasn't found by Clang -ftime-trace, but highlighted by adding GCC -Wnrvo to headersclean. Instead of rewriting the function, pull it behind the ABI boundary. Can't pick back, because it adds an exported symbol (on Unix, Windows already had it, due to the wholesale export of the class), so isn't forwards-BC. Change-Id: I0d7ac417e129023f9688028685e818e7ab6ab7e2 Reviewed-by: Allan Sandfeld Jensen <allan.jensen@qt.io>
* QFont: fix a QT_ASCII_CAST_WARNMarc Mutz2025-11-281-1/+1
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | Says GCC: qfont.cpp:2202:81: required from here 2202 | fontDescription += comma + tag.toString() + u'=' + QString::number(value); | ^ qstringbuilder.h:403:37: warning: ‘static void QConcatenable<QByteArray>::appendTo(const QByteArray&, QChar*&)’ is deprecated: Use fromUtf8, QStringLiteral, or QLatin1StringView [-Wdeprecated-declarations] 403 | QConcatenableEx<B>::appendTo(p.b, out); | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~^~~~~~~~~~ qstringbuilder.h:372:43: note: declared here 372 | QT_ASCII_CAST_WARN static inline void appendTo(const QByteArray &ba, QChar *&out) | ^~~~~~~~ This is because Tag::toString() returns QByteArray, not QString. To fix, wrap the toString() result in QLatin1StringView. This is safe, because the temporary QByteArray will be kept alive until the end of the full-expression, so until after op+= has executed. It does change the serialization vis-a-vis the old code, but a) only for non-US-ASCII tags, which are not really valid, and b) we make it more robust now, because each random 4-octet sequence is a valid L1 string, but many are not valid UTF-8, so their interpretation as U8 by the old code (QByteArray → QString assumes U8) depends on behavior of Qt outside its spec. GIGO applies, of course, but we don't tend to specify the GO for any given GI, so it's better to use an algorithm for which no input is "garbage". Amends 8fe6ad3eed40a8c851bf5d49e322f9794b9f7dcf. Task-number: QTBUG-141412 Change-Id: Ic45f9147ca54201a33d953da57b768d2a5d115e4 Reviewed-by: Ahmad Samir <a.samirh78@gmail.com>
* QFont: add a code comment about an op<() observationMarc Mutz2025-11-281-0/+2
| | | | | | | | | | | | | | | | | The code consistently treats the op<() argument as the LHS and *this as the RHS, so it actually implements greater-than. Nothing that needs changing, as the docs don't promise anything and it's perfectly fine to implement op< using greater-than semantics, if done consistently, but worth nothing, because it may raise eyebrows, as it did in this author. Amends the start of the public history. Pick-to: 6.10 6.8 6.5 Task-number: QTBUG-142246 Change-Id: If5aafa4e01a963e622c1ad72deb265477855ec48 Reviewed-by: Eskil Abrahamsen Blomfeldt <eskil.abrahamsen-blomfeldt@qt.io>
* QTextDocument: fix repeated calls of unit testsTim Blechmann2025-11-251-1/+1
| | | | | | | | | | | | Tests may set the default resource provider. Calling the test multiple times results in a heap-use-after-free error/crash. So we need to unset the default resource provider. Amends ccf1a1a9536be7b904494f5b3243202d71a33b06. Pick-to: 6.10 Change-Id: I6bc1d67af54534e85fe95dc57236499bc2e7b923 Reviewed-by: Volker Hilsheimer <volker.hilsheimer@qt.io>
* Include font features in QFont::toString()Vlad Zahorodnii2025-11-211-8/+45
| | | | | | | | | | | | | | | | | This ensures that font features, for example calt or liga, can be saved in QSettings using QFont::toString() and QFont::fromSettings() as expected. With the proposed change, QFont::toString() will append the number of font features followed by a list of key=value pairs specifying feature settings. The corresponding tests have been reworked a little bit because following the established patterns was slightly challenging. Task-number: QTBUG-141412 Change-Id: I7a80d5fe1d120b514797bfb515c3a6b0867a6ee5 Reviewed-by: Eskil Abrahamsen Blomfeldt <eskil.abrahamsen-blomfeldt@qt.io>
* QFont: fix potential "Integer division by zero" in QFontCache::decreaseCache()Vladimir Belyavsky2025-11-201-4/+8
| | | | | | | | | | | | | | | QFontCache::decreaseCache() may crash with "Integer division by zero" in case when an engine is missed in engineCacheCount for some reason. It still not clear how this may happen, but we see this in user's crash reports. This change simply prevents crashes, but the underlying cause of such cache inconsistency needs to be investigated and fixed further. Task-number: QTBUG-138455 Change-Id: I6d81c23a67a883b9c00094a8fcd5394bb86b39ea Reviewed-by: Eskil Abrahamsen Blomfeldt <eskil.abrahamsen-blomfeldt@qt.io> Reviewed-by: Konstantin Ritt <ritt.ks@gmail.com>
* Build with QT_NO_URL_CAST_FROM_STRINGAhmad Samir2025-11-202-3/+3
| | | | | | | | | | | Can't mark the whole repo with that macro, because in corelib that would take out the QString conversion operator which is BiC. Add a hard build-time error if QT_NO_URL_CAST_FROM_STRING is defined in corelib, as requested in code review. Change-Id: Ia0e302a2f82b86800e84d15e86ab138f78d45e4d Reviewed-by: Thiago Macieira <thiago.macieira@intel.com>
* QTextHtmlParser: Support "del" tagKai Uwe Broulik2025-11-172-0/+3
| | | | | | | | | | | | | Indicates that text has been removed from a document and is rendered with strike-through like the "s" tag. It was supported by Qt Quick's style text parser but not QTextDocument. Change-Id: I7312dbba2b2066a74033b607688eef17cc380559 Reviewed-by: <carl@carlschwan.eu> Reviewed-by: Eskil Abrahamsen Blomfeldt <eskil.abrahamsen-blomfeldt@qt.io> Reviewed-by: Sune Vuorela <sune@vuorela.dk>
* QFontMetrics: DRY engine lookup for single charactersMarc Mutz2025-11-073-37/+27
| | | | | | | | | | | | | | Extract Method QFontPrivate::engineForCharacter() and use it in inFont() and the single-char overloads of left/rightBearing(), boundingBox() and horizontalAdvance(). As a drive-by, receive QChar::script()'s result in an auto variable, to avoid converting to and from int. Pick-to: 6.10 6.8 6.5 Change-Id: Id2cf1a1781c4b3fb9657902fb065c6ec7f4d70c3 Reviewed-by: Ahmad Samir <a.samirh78@gmail.com> Reviewed-by: Volker Hilsheimer <volker.hilsheimer@qt.io>
* Doc: Add missing property docsPaul Wicking2025-11-061-0/+38
| | | | | | Task-number: QTBUG-140629 Change-Id: I8e032655d6a211c042d86baa8bab27cc0b34cb9f Reviewed-by: David Boddie <david.boddie@qt.io>
* QTextEngine: avoid an unnecessary temporary QHashAurélien Brooke2025-11-041-18/+19
| | | | | | | | | | | | | | | Build the HarfBuzz feature list directly without a temporary QHash. Use a small flat map with inline storage to keep features contiguous and pass features.values() straight to hb_shape_full(), avoiding extra allocations. Note that QHash::insert has insert_or_assign semantics while QFlatMap::insert is try_emplace. We therefore insert fontFeatures first so that user-provided values take precedence over defaults. Change-Id: I4393f55a6c397be59e638be41e4f0ea27aaee1f9 Reviewed-by: Volker Hilsheimer <volker.hilsheimer@qt.io>
* QTextEngine: keep the hb_buffer_t across shapeTextWithHarfbuzzNG callsAurélien Brooke2025-11-042-10/+18
| | | | | | | | | | We can spare the hb_buffer_t allocation and creation on each shaping by storing it in QTextEngine, and reusing it the next time. The member variable is named "buffer" to minimize code changes. Change-Id: I1dd2da7b39270b17ef7e39c3a7c108be7ffaf048 Reviewed-by: Volker Hilsheimer <volker.hilsheimer@qt.io>
* QFontPrivate: properly delete the assignment operatorMarc Mutz2025-11-021-3/+1
| | | | | | | | | | | | | | | Before, it was implemented as a private no-op(!). This looks overly dangerous. The typical pattern in C++98 was to declare it private, but _not_ implement it, so one would get a linker error at least. This, OTOH, will just compile and fail to work. Picking to all active branches to ensure it's not inadvertently used. Pick-to: 6.10 6.8 6.5 Change-Id: I6c2223a605665f1f0bade488fe9794d62ee335c6 Reviewed-by: Thiago Macieira <thiago.macieira@intel.com> Reviewed-by: Ivan Solovev <ivan.solovev@qt.io> Reviewed-by: Mårten Nordheim <marten.nordheim@qt.io>
* Doc: Clarify usage of QTextFormat::FontSizeAdjustmentDheerendra Purohit2025-10-151-2/+2
| | | | | | | | | | Specify that the value is an integer and is added to the base font size. Pick-to: 6.10 6.9 Fixes: QTBUG-130805 Change-Id: I4093fed2412cf009049fa28152a0d71ee2f81844 Reviewed-by: Leena Miettinen <riitta-leena.miettinen@qt.io> Reviewed-by: Marcus Tillmanns <marcus.tillmanns@qt.io>
* appendNodeText: Don't split emojis with surrogate chars in twoAlbert Astals Cid2025-10-141-4/+8
| | | | | | | | | | | | | | | When parsing a document that assigns an anchor to text, we assign this anchor to the next immediate character. If this character was the low surrogate in a pair, we would end up splitting the surrogate and messing up the text. We use QStringIterator to make sure we always process surrogate pairs together and add the full pair to the resulting text. Fixes: QTBUG-140929 Pick-to: 6.10 Change-Id: I63ee03c251004d1a138f97462723fcc3798b9147 Reviewed-by: Albert Astals Cid <aacid@kde.org> Reviewed-by: Eskil Abrahamsen Blomfeldt <eskil.abrahamsen-blomfeldt@qt.io>
* Doc: Add missing property declarationsDavid Boddie2025-10-101-0/+5
| | | | | | Task-number: QTBUG-139560 Change-Id: Id71b79cc88e5db5e3996e29332f91b388e7d7e4f Reviewed-by: Topi Reiniö <topi.reinio@qt.io>
* Fix artifacts on distance fields with overlapping linesEskil Abrahamsen Blomfeldt2025-10-101-6/+8
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | The latest version of Noto Sans CJK JP has some very small bugs where a tiny line segments extend from the outline and then return immediately with an overlapping line (e.g. one line with a normal of (0, 1) first and then another line with a normal of (0, -1) right after it). The way distance field generation works is that it will first flatten curves into line segments. Then it will gradient fill rectangles around these line segments, aligned with the normals. If there is an angle between the line segments, there will be gaps between these rectangles, so we then need to fill these in with triangles. There are two different code paths for the triangles: One if the angle between the two line segments is convex and one if not. For parallel lines, there is no gap to fill, but we would still execute the triangle pass for concave in this case, as parallel lines were considered non-convex. This broke down for these overlapping lines, causing large smudges of fully interior pixels to be drawn over the position of the overlapping lines. Since we know that parallel lines will not require the fill triangles, we can bypass this step entirely if the line segments are parallel, which eliminates this issue. Pick-to: 6.10 Fixes: QTBUG-139610 Change-Id: I18c5480630ae667f511843881b1243628d9a17c5 Reviewed-by: Eirik Aavitsland <eirik.aavitsland@qt.io>
* Fix text offset when drawing a QPictureEskil Abrahamsen Blomfeldt2025-10-101-1/+1
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | When replaying text in a QPicture, it would try to detect the baseline of the text by taking the ascent of the selected font. In most cases this will work, but if the text contains characters from other fonts (due to font merging) then we need to take the ascents of these fonts into account as well, since the actual distance to the baseline will be the maximum ascent of all fonts. To enable this, we implement support for Qt::AlignBaseline in qt_format_text() so that it can apply the correct offset by actually looking at the ascent of the first text line. There is a complication though: Since Qt::TextSingleLine and Qt::AlignBaseline share the same value, they cannot be combined in a single flags field. So we expand the qt_format_text() to allow passing text flags and alignment separately. To avoid accidentally enabling AlignBaseline for normal drawText() calls, we mask this out when passing the alignment in. The code has been this way since 2007, so applications may have worked around this bug for years. Therefore, we only enable the changed behavior for the latest QPicture format. By setting an older format you can still get the old behavior. [ChangeLog][QtGui] Fixed an issue where text drawn into a QPicture might be offset vertically when replayed. Fixes: QTBUG-139243 Change-Id: I5fe7edc561bd5f666c8c64fb2ed603011ddded47 Reviewed-by: Eirik Aavitsland <eirik.aavitsland@qt.io>
* (QtGui) doc: Add alt text for \image tagsEren Bursali2025-09-292-4/+9
| | | | | | | | | Adding alt texts that were needed for QDoc Fixes: QTBUG-135119 Pick-to: 6.10 Change-Id: Id330b1933f56ff845fa02d91680cec27855e56e3 Reviewed-by: Kai Köhne <kai.koehne@qt.io>
* Add QRawFont::glyphName()Tor Arne Vestbø2025-09-292-0/+15
| | | | | | | | [ChangeLog][Gui] Added QRawFont::glyphName() for inspecting glyph names. Change-Id: Ie8f8cb0097feb509d4d1e9621f224b1c5a008235 Reviewed-by: Eskil Abrahamsen Blomfeldt <eskil.abrahamsen-blomfeldt@qt.io>
* Add QRawFont::glyphCount()Tor Arne Vestbø2025-09-292-0/+12
| | | | | | | | | | So that users can iterate the glyphs in the font. [ChangeLog][Gui] Added QRawFont::glyphCount() for iterating the glyphs in a font. Change-Id: I230ee45cce486a6538d0d9f92afa08d812d11773 Reviewed-by: Eskil Abrahamsen Blomfeldt <eskil.abrahamsen-blomfeldt@qt.io>
* Add QCoreTextFontEngine::glyphCount overrideTor Arne Vestbø2025-09-294-0/+12
| | | | | | | | | | The base QFontEngine::glyphCount was reporting 0 glyphs. Possibly due to not working on instances of QFontEngineMulti. But in any case it makes sense to use the CoreText implementation if we can. Pick-to: 6.10 6.8 6.5 Change-Id: I267b699b7cb71a7fc6758a375b783044a0b618b0 Reviewed-by: Eskil Abrahamsen Blomfeldt <eskil.abrahamsen-blomfeldt@qt.io>
* Fix possible assert when inserting columns in QTextDocumentEskil Abrahamsen Blomfeldt2025-09-081-1/+1
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | In certain tables which have cells that contain row spans in beginning of a row, we could get into an inconsistent state which would leave cells in the table unmapped/invalid. Specifically, this happened when inserting a new left-most column. The algorithm has two data structures: A "logical cells map" which gives the row span and col span of each cell, and then a grid which maps the logical index of each (x,y) to a cell. What happened in this case was that we were inserting at pos == 0. For each row, we would then search for an insertion point in that row by looking at the grid and finding the logical index of the first slot in this particular row of the grid. Then we would insert a new cell directly before this index in cells and continue. If we find a logical index which actually belongs to a prior row than the one we are inserting into, since a previous cell has a row span, we need to continue searching. Otherwise we end up inserting the new column into this previous row, which we have already handled. This is where it went wrong: There was logic to handle this by checking the logical index we found against the logical index of the last grid slot in the previous row, and it is even documented in a comment. But when pos==0, then we would *always* set "logicalGridPositionBeforePosition" to -1, thus we would never actually apply this condition for pos==0. Setting logicalGridPositionBeforePosition to -1 is correct for the first row, since there is no previous grid slot to look at, but for subsequent rows we can still do this look up even for pos == 0. Pick-to: 6.5 6.8 6.9 6.10 Fixes: QTBUG-138678 Change-Id: I6094e7d0f41611b6d8b0952eac876bf2e41dfe9c Reviewed-by: Eirik Aavitsland <eirik.aavitsland@qt.io>
* util/unicode: assert no mirrored pairs exist outside BMPMarc Mutz2025-09-021-0/+1
| | | | | | | | | | | | | | | QTextEngine implicitly assumes this (it's looking up mirrored characters in UTF-16 space, without first decoding surrogates). Add a comment there, too. Amends 7f504283ef44c35dfca7198a80742063a940fabd. Fixes: QTBUG-139456 Pick-to: 6.10 6.9 6.8 6.5 Change-Id: Ie79b33907e71cc455434127c1752898c40b128f9 Reviewed-by: Edward Welbourne <edward.welbourne@qt.io> Reviewed-by: Thiago Macieira <thiago.macieira@intel.com>
* Fix memory leak in QCoreTextFontDatabase::addApplicationFontIgor Khanin2025-08-271-2/+2
| | | | | | | | | | | | | The return value of CTFontDescriptorCreateCopyWithAttributes already has retain count 1, and CFArrayAppendValue retains it again - so it leaks. Due to this, memory is leaked every time an application font is added on macOS from a data buffer. Wrap the the value in a QCFType to ensure the local reference gets released. Fixes: QTBUG-139600 Pick-to: 6.8 6.9 6.10 Change-Id: Iaedfea977627d214fe229ee675f321ad8255775a Reviewed-by: Tor Arne Vestbø <tor.arne.vestbo@qt.io>
* Teach QImage::toCGImage() about most of our image formatsTor Arne Vestbø2025-08-251-3/+8
| | | | | | | | | | | | | | | | | | | | | | | | | | | | Instead of hard-coding the mapping between QImage formats and the corresponding CGBitmapInfo we now build up the individual bits of the bitmap info based on the pixel format of the image. This gives us support for formats like RGB30 and the various float formats that are important for HDR. The qt_mac_cgImageFormatForImage helper now also resolves the correct bits per component, as well as the color space, so that consumers can't make any mistakes in what it passes to the CoreGraphics APIs. The validity of the format mappings has been tested by saving both the QImage and the CGImage to a PNG file, and comparing the results visually. Once we have the same support for converting CGImageRefs to QImage we can do this round-trip-verification in a test. [ChangeLog][QtGui] QImage::toCGImage() now supports most of the QImage formats. If a format is not supported the function will return a null CGImageRef. Change-Id: I3378ca00f7321e0c2c9d9a88a0dd25f5a893c56b Reviewed-by: Volker Hilsheimer <volker.hilsheimer@qt.io>
* Doc: Tie documentation to where QDoc locates functionsDavid Boddie2025-08-251-3/+2
| | | | | | | | | | | | Although the original \fn declarations may represent the intent behind the operator functions, QDoc sees these functions as child nodes of QFont::Tag, so giving fully-qualified names ensures that the documentation will be tied to their nodes in the hierarchy. Fixes: QTBUG-139263 Pick-to: 6.10 Change-Id: I1c1f717658d03ffa43101475f6b913bd066d4ca1 Reviewed-by: Paul Wicking <paul.wicking@qt.io>
* Fix crash in QFont::exactMatch() with different family countsEskil Abrahamsen Blomfeldt2025-08-221-0/+3
| | | | | | | | | | | | | | | | | | | | | | | | | | | This amends d8602ce58b6ef268be84b9aa0166b0c3fa6a96e8. This change prepared for removing the singular family from the QFontDef, making the families list the only way to store family names. Before this, there was some intricate logic here to support when both family and families were set. The idea was to make it possible to match a QFont where family was set to a QFont where a single family had been added to families. For all other cases where the families lists had different lengths, we would return false. Since this was no longer needed, the code was removed, but it also accidentally introduced a crash when the sizes of the two families lists were different. This simply puts back the check for different family counts and returns false if they are different like before. Pick-to: 6.5 6.8 6.9 6.10 Fixes: QTBUG-138561 Change-Id: I864c19105dc5d582a43023e71e46b1efb29cbc21 Reviewed-by: Andy Shaw <andy.shaw@qt.io>
* Freetype: Fix setting variable axes on named instancesEskil Abrahamsen Blomfeldt2025-08-221-8/+9
| | | | | | | | | | | | | | If you give explicit values for variable axes, these should take precedence, even if the initial values are from a named instance. cc128d802c6d9c87a1e00a8a88d5e6590a7195f4 reordered the operations so that the named instance was selected after setting the values, thus overwriting them. Pick-to: 6.9 6.10 Fixes: QTBUG-139106 Change-Id: I07b44718fd97c0c12c2cd65d0d7313580d9d6aa3 Reviewed-by: Eirik Aavitsland <eirik.aavitsland@qt.io>
* QTextEngine: Pass expanded context to HarfBuzz for shapingJonathan Clark2025-08-202-23/+23
| | | | | | | | | | | | | | | | | | | | | | | | | | | | Previously, when laying out text using harfbuzz-ng, QTextEngine would only populate the HarfBuzz buffer with the substring associated with a single item at a time - in effect, semantically breaking the string at format boundaries. While this approach doesn't have obvious effects for some languages, it can make text illegible in languages that have different character forms depending on word position (such as Arabic). This change updates QTextEngine to instead pass the full string to HarfBuzz. By doing so, HarfBuzz can inspect the contents of the string around the current item, and substitute the correct characters at the item boundaries. Note that this change isn't a complete fix for QTBUG-54350. In particular, ligatures will not form across item boundaries, which may cause incorrect text rendering in some situations. However, this fix should address some of the more painful cases, such as label mnemonics breaking Arabic text rendering. [ChangeLog][Text] Improved text shaping with mnemonics in certain languages, such as Arabic. Pick-to: 6.10 Fixes: QTBUG-93371 Change-Id: I3639e50b809269836cd5480609d22328f9deaf82 Reviewed-by: Eskil Abrahamsen Blomfeldt <eskil.abrahamsen-blomfeldt@qt.io>
* Avoid returning invalidated fonts from freetype cacheEskil Abrahamsen Blomfeldt2025-08-151-4/+39
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | If fonts were invalidated, for instance because the application fonts were cleared, we would sometimes still return the old freetype faces. This could happen if there were still references to the fonts when they were invalidated, in particular on the render thread where we need to purge the old references after the fact. If the same key was requested before the last reference to the stale font had been deleted, we would create new references to it. For memory fonts, we use the generic ":qmemoryfonts/0" as cache key, so we can easily get into the situation that we already had a match for this in the stale cache. As a result, we could end up with different fonts in the main thread and render thread when using the font from Qt Quick, and the glyph indexes would be from a different font than the one used for rendering. This would show as apparently random glyphs. The patch introduces a secondary list of "stale" freetype faces. These are the ones that have been invalidated but cannot yet be deleted. We never look anything up in this, so we don't risk returning any stale fonts. We also make sure we purge the list whenever we can, similar to the main faces list. Pick-to: 6.10 Task-number: QTBUG-132108 Change-Id: I40adfdbb9aeddfffb4baed6c2f627bce9bd74ad1 Reviewed-by: Eirik Aavitsland <eirik.aavitsland@qt.io>
* QHashCombine: add a way to make combining results with seed in Qt 6.xThiago Macieira2025-07-041-1/+1
| | | | | | | | | | | Complements commit c05ae82efb33507959ae2082483fb9425ccca8a0, which added the support for Qt 7, but neglected to provide a solution for the cases where the qHash() function of a type was never inline and therefore can be updated to properly hash using the seed. Pick-to: 6.10 Change-Id: I5fb0ed9a2c92440ec0f8fffd0f38568f28cc4363 Reviewed-by: Edward Welbourne <edward.welbourne@qt.io>
* QFontDatabase: eradicate goto useMarc Mutz2025-07-021-28/+15
| | | | | | | | | | | | | | None of these are necessary, so replace them by early returns. Qt does not subscribe to SESE. Mercifully amends the start of the public history. Picking all the way back, because goto's deserve it and this makes the code easier to understand and safer. Pick-to: 6.10 6.9 6.8 6.5 Change-Id: I7b38795a2434f09fba7990e1267cb1a9127e37eb Reviewed-by: Volker Hilsheimer <volker.hilsheimer@qt.io>
* QTextCharFormat: improve documentation for font()David Faure2025-07-011-0/+11
| | | | | | | | | | | | | It can be quite confusing to find out that fontItalic() == false but font().italic() == true, or vice-versa. Or worse, the fact that fontPointSize() returns 0 if the size comes from the default font. Fixes: QTBUG-49564 Pick-to: 6.10 6.9 6.8 6.5 Change-Id: I05239ed80e82080ea942524f289b953f806c8196 Reviewed-by: Eskil Abrahamsen Blomfeldt <eskil.abrahamsen-blomfeldt@qt.io>
* Use QPainter::brushOriginF() where appropriateChristian Ehrlicher2025-06-251-1/+1
| | | | | | | | Replace QPainter::brushOrigin() with brushOriginF() to not loose precision. Change-Id: I86f9e4c3399d32755f0b2b062ad7654149edab1b Reviewed-by: Axel Spoerl <axel.spoerl@qt.io>
* Doc: Remove redundant "see also" linkDavid Boddie2025-06-121-1/+1
| | | | | | Pick-to: 6.9 6.10 Change-Id: Id48d97a171b55f3dbf8d1fa32e23b82d28e5552d Reviewed-by: Eskil Abrahamsen Blomfeldt <eskil.abrahamsen-blomfeldt@qt.io>
* Add support for font features and variable axes to QTextCharFormatEskil Abrahamsen Blomfeldt2025-06-062-9/+113
| | | | | | | | | | These can be set on the font directly, but had not been added to QTextCharFormat, so there would be no way to override them by formatting in a rich text document. Fixes: QTBUG-134060 Change-Id: I4494e24cb9b99d84fb376ba895e2461fc3cd054b Reviewed-by: Eirik Aavitsland <eirik.aavitsland@qt.io>
* Fix regression in drawing table cell border when border-collapse enabledSanthosh Kumar2025-06-051-1/+1
| | | | | | | | | | | | | | The patch 732962d604e7469f9a9f02fe0cd3d1fd04caddb8 enables drawing a border around cells within the table when set through CSS styling. But this caused a regression when border-collapse is enabled without setting the cell border. This patch enables drawing borders for table cells when either of those conditions is satisfied. Fixes: QTBUG-136590 Pick-to: 6.10 6.9 6.8 Change-Id: Ibf43c404439c9fee1cfd2b40789150edb76c6971 Reviewed-by: Nils Jeisecke <nils.jeisecke@saltation.com> Reviewed-by: Christian Ehrlicher <ch.ehrlicher@gmx.de>