319 Commits

Author SHA1 Message Date
Igor Khanin
889bdf1de4 QTextOption: Add flag for showing default ignorable characters
The presence of the flag instructs the text shaping engine to not
outright ignore normally non-printable code points, so that if the font
has glyphs for them, they will be rendered. This is useful when editing
plain text whose layout is affected by the presence of such characters
(primarily BiDi control characters), and for layout debugging in
general.

[ChangeLog][QtGui][Text] Added QTextOption::ShowDefaultIgnorables flag.

Change-Id: I610a30603f718254ab8e532083e65252351159f0
Reviewed-by: Eskil Abrahamsen Blomfeldt <eskil.abrahamsen-blomfeldt@qt.io>
Reviewed-by: Christian Ehrlicher <ch.ehrlicher@gmx.de>
2024-10-10 18:36:58 +03:00
Jari Helaakoski
30cc8a28de Fix test compilation issues with QtLite configuration
Now developer build tests compile, but some are not working.
Functional fix will come later via separate tasks.

Task-number: QTBUG-122999
Change-Id: I70487b46c1b32ba4279cb02a4978e4f55ac0d310
Reviewed-by:  Alexey Edelev <alexey.edelev@qt.io>
Reviewed-by: Thiago Macieira <thiago.macieira@intel.com>
2024-05-06 14:29:02 +00:00
Eskil Abrahamsen Blomfeldt
1593b1f6d6 Introduce optional smarter font merging with ContextFontMerging
This introduces an optional, slightly more expensive approach
to font merging which takes the full string into account,
instead of just going character by character.

This addresses the issue that you may sometimes get multiple fonts
to cover one string of text in a single language. With Chinese,
this is especially an issue because many fonts will only support
parts of the very large character set.

The new algorithm detects if the string was incompletely covered
by the font and tries the fallback fonts in order to find the best
match. This is obviously more expensive, especially if no perfect
match is found and we have to check all the fallbacks in the list,
but it is opt-in and only enabled if the ContextFontMerging flag
is set.

Task-number: QTBUG-121131
Change-Id: I8c7874d0918640bd83418e3c4726c89f43a220a3
Reviewed-by: Eirik Aavitsland <eirik.aavitsland@qt.io>
2024-04-26 12:30:53 +02:00
Paul Olav Tvete
7a84c58f55 Fix QTextEngine regression with large-ish texts
Change 997fd3b88ede8078af286da6ecc197e83a8cbb46 fixed integer overflows
with huge texts. This was done by using qsizetype for size calculations
instead of int. However, that change introduced a serious regression
due to an itermediate imultiplication result being "promoted" to unsigned,
and therefore a negative value being converted to a large positive.
The solution is to make sure all values in the expression are signed.

Fixes: QTBUG-123339
Task-number: QTBUG-119611
Pick-to: 6.7
Change-Id: I3f9189f77b383c6103cf5b35981cdb607b065f6f
Reviewed-by: Eskil Abrahamsen Blomfeldt <eskil.abrahamsen-blomfeldt@qt.io>
2024-03-15 20:46:39 +01:00
Paul Olav Tvete
997fd3b88e QTextEngine: Protect against integer overflow with huge texts
QPlainTextEdit would crash when adding a string of 136 348 169
characters, due to the integer overflow checks being done with int
variables.

Perform intermediate calculations and size checks with qsizetype
instead of int. This commit contains a slight modification of the fix
contributed by Adam Clarke in the bug report. Note that the size check
casts to size_t to cover the 32-bit case where qsizetype is qint32.

Fixes: QTBUG-119611
Pick-to: 6.7
Change-Id: I1cf7e1bc4c35276862f37aa6d01f37075fa11635
Reviewed-by: Eskil Abrahamsen Blomfeldt <eskil.abrahamsen-blomfeldt@qt.io>
2024-03-01 18:00:33 +00:00
Anton Kudryavtsev
793cfec941 qtextengine: use const methods more
to avoid implicit detach

Change-Id: I2fd36fef138eee23c12d413dfec3232ad1fa01df
Reviewed-by: Mårten Nordheim <marten.nordheim@qt.io>
2023-10-25 19:53:14 +03:00
Anton Kudryavtsev
621f7c8735 qtextengine: replace qlist with qvla
CoW is not required here

Change-Id: Ia0d55dd1e82a225e089ca50f0d3c72bfb52d44f4
Reviewed-by: Mårten Nordheim <marten.nordheim@qt.io>
2023-10-25 19:53:14 +03:00
Volker Hilsheimer
bde443801f QFont: add a tag type for features and other advanced properties
Instead of overloads and generic string literals with runtime checks,
use a dedicated Tag type for specifying the font feature. The Tag type
can only be instantiated with a string literal of exactly 4 characters
(plus the terminating null)l; longer or shorter literals result in a
compile time error.

Constructing a Tag from any other string type is possible through the
named fromString constructor, in which case we can only check the length
and warn at runtime.

The type's API is almost completely constexpr so that we can use it to
calculate e.g. enum values.

Task-number: QTBUG-117046
Change-Id: I31038c7c6fd2b843a105b032f021e506b0b60822
Reviewed-by: Qt CI Bot <qt_ci_bot@qt-project.org>
Reviewed-by: Eskil Abrahamsen Blomfeldt <eskil.abrahamsen-blomfeldt@qt.io>
2023-10-20 21:36:52 +02:00
Anton Kudryavtsev
02e2a3f123 qtextengine: use RAII more
replace new/delete with unique_ptr

Change-Id: Iac36885041ee15bd2ecf6bb487dacf613e126475
Reviewed-by: Mårten Nordheim <marten.nordheim@qt.io>
2023-09-07 16:05:05 +03:00
Anton Kudryavtsev
f74fd727e1 Tidy up qtextengine: use char16_t more
Change-Id: Idae892b7a6fa9d58ba154f9729e1d26ab1f6ea5e
Reviewed-by: Edward Welbourne <edward.welbourne@qt.io>
2023-09-06 22:36:06 +03:00
Eskil Abrahamsen Blomfeldt
baba1f1b39 Change QFont::fontFeatures() -> QFont::features()
The 'font' is redundant here, and we don't prefix any other
properties like that.

Change-Id: Iee1f492b232e5bbcae399b472d7478406d8a81ef
Reviewed-by: Tor Arne Vestbø <tor.arne.vestbo@qt.io>
2023-05-24 13:05:02 +02:00
Eskil Abrahamsen Blomfeldt
6160ea45b6 Implement API for enabling / disabling OpenType features
Similar to the font-features-settings in CSS, this is a low-level
API that allows you to pass the information to the shaper in order
to enable or disable specific font features by name.

[ChangeLog][QtGui][Text] Added an API to QFont which makes it
possible to enable and disable specific typographic features
in OpenType fonts.

Change-Id: Ib48c678f3b97a5a562b08ae34dc895800c8885c0
Reviewed-by: Lars Knoll <lars@knoll.priv.no>
2023-05-09 23:39:41 +02:00
Eskil Abrahamsen Blomfeldt
ca64365e3a Don't hide object replacement char except in rich text
The object replacement character (U+FFFC) is used to represent
inline objects such as images in rich-text. To enable this,
we have special handling of it in QTextEngine. For classes
where inline images are not supported, it will just be hidden
from the visual text, which is unexpected.

Instead of always special-casing it, we make this dependent
on whether the document layout has registered any object handlers.
If they have not, then there will be no visual representation of
the object, and it is better to show the glyph for it.

For anything based on QTextDocument, there will always be the
image handler, so U+FFFC will still have special handling there,
but for non-rich labels and plain text editors the glyph will
be shown instead.

Note that there was also a bug in QLineEdit, where the object
replacement character was always replaced by a space. This was
introduced in 2007, in a patch which replaced a !ch.isPrint()
with a check for "the most obvious non-printable characters"
to reduce the number of characters that were not shown. However,
U+FFFC is a printable character and would thus not have been
filtered by the !isPrint() condition, so I think this was a
mistake at the time. However, due to the special-casing of
the character in Qt, it would not have had any effect until
now.

This also changes the QTextLayout::cursorToXForInlineObject()
test to actually test proper inline objects, as this was
previously using a hack which depended on the inline object
code to be used even for plain QTextLayouts with no handlers
for these.

[ChangeLog][Text] The object replacement character (U+FFFC)
is now only filtered out in rich text controls, where they
represent inline objects. In other controls, its glyphs will
be shown as with other text.

Pick-to: 6.5
Fixes: QTBUG-101526
Change-Id: I7fcaf2b10918feb41589e1098016efbf79a0e62d
Reviewed-by: Lars Knoll <lars@knoll.priv.no>
Reviewed-by: Qt CI Bot <qt_ci_bot@qt-project.org>
2022-12-14 19:19:01 +01:00
Ziming Song
6b1044cc3f QTextEngine: also round x-offset for non-subpixel text render
If horizontal subpixel is not supported, both glyph advance and
x-offset should be rounded. Or the position of rendered glyph might
be fraction number.

Fixes: QTBUG-104895
Change-Id: Ia572764bb87db9712847ceea532d8d424ec7704b
Reviewed-by: Eskil Abrahamsen Blomfeldt <eskil.abrahamsen-blomfeldt@qt.io>
2022-12-09 04:33:57 +08:00
Eskil Abrahamsen Blomfeldt
c9d991de1f Fix missing text when Harfbuzz fails to shape a substring
This amends fccd419dd632306a4bd85928223e0a56a59510ef.

If Harfbuzz failed on one of the items in a string and returned
zero glyphs, then we would exit the shaping loop. The mentioned
change fixed a crash related to this when the ignored character
was the only character in the string, but it occurred in a
subitem of a longer string, then we would return and fail to
lay out the rest of the string.

This popped up recently because an update to Harfbuzz has caused
it to return zero glyphs when applying the Apple emoji font to
an isolated variant character (see bug report). When we matched
the symbol to the main font and only the variant character to
the emoji font, we would get in this situation, and end up
exiting the shaping early.

[ChangeLog][QtGui][Text] Fixed a regression which would
sometimes cause text to disappear if the string contained
an unmatched variation selector character.

Pick-to: 6.4
Fixes: QTBUG-108799
Change-Id: I616ab1b2d33c2df731419c5ce06fbc578a625a32
Reviewed-by: Tor Arne Vestbø <tor.arne.vestbo@qt.io>
2022-12-05 07:55:43 +01:00
Eskil Abrahamsen Blomfeldt
0dcd640a1f Don't return a visual glyph for ignorable characters
When Harfbuzz returns zero glyphs, this will typically be because
the character is ignored. We currently have no way to differentiate
this from actual error cases, so to avoid return the error glyph
for cases which are not really errors, we set the dontPrint flag
for this.

When we add a way to differentiate between error cases and non-error
cases later, we should revert this for the actual errors.

Pick-to: 6.4
Task-number: QTBUG-108799
Change-Id: I2a910d951b71c705fb4dd761fcfe3a942b3afa7c
Reviewed-by: Tor Arne Vestbø <tor.arne.vestbo@qt.io>
2022-12-05 07:55:25 +01:00
Vladimir Belyavsky
991c056438 QTextLayout: fix maximumWidth() for a text containing line separator
This is improved version of previous fix
013c346a8dcbd618febb07884c64c740daf9754d that was reverted because it
broke some tests for Quick Text. The problem was that it did not work
correctly in the case the text was wrapped to a fixed width.
To deal with this we'll accumulate current line full width (as if it
hadn't been wrapped) in layout data (layoutData->currentMaxWidth).
Then when the next line is explicitly wrapped by line or paragraph
separator, this accumulated width will be used to adjust layout's
maximum width.

Change-Id: Iad7119d9808e1db15fe1fbc5db049c3db928529f
Fixes: QTBUG-89557
Fixes: QTBUG-104986
Reviewed-by: Eskil Abrahamsen Blomfeldt <eskil.abrahamsen-blomfeldt@qt.io>
2022-11-19 18:03:32 +03:00
Marc Mutz
1c6bf3e09e Port from container::count() and length() to size() - V5
This is a semantic patch using ClangTidyTransformator as in
qtbase/df9d882d41b741fef7c5beeddb0abe9d904443d8, but extended to
handle typedefs and accesses through pointers, too:

    const std::string o = "object";

    auto hasTypeIgnoringPointer = [](auto type) { return anyOf(hasType(type), hasType(pointsTo(type))); };

    auto derivedFromAnyOfClasses = [&](ArrayRef<StringRef> classes) {
        auto exprOfDeclaredType = [&](auto decl) {
            return expr(hasTypeIgnoringPointer(hasUnqualifiedDesugaredType(recordType(hasDeclaration(decl))))).bind(o);
        };
        return exprOfDeclaredType(cxxRecordDecl(isSameOrDerivedFrom(hasAnyName(classes))));
    };

    auto renameMethod = [&] (ArrayRef<StringRef> classes,
                            StringRef from, StringRef to) {
        return makeRule(cxxMemberCallExpr(on(derivedFromAnyOfClasses(classes)),
                            callee(cxxMethodDecl(hasName(from), parameterCountIs(0)))),
                        changeTo(cat(access(o, cat(to)), "()")),
                        cat("use '", to, "' instead of '", from, "'"));
    };

    renameMethod(<classes>, "count", "size");
    renameMethod(<classes>, "length", "size");

except that the on() matcher has been replaced by one that doesn't
ignoreParens().

a.k.a qt-port-to-std-compatible-api V5 with config Scope: 'Container'.

Added two NOLINTNEXTLINEs in tst_qbitarray and tst_qcontiguouscache,
to avoid porting calls that explicitly test count().

Change-Id: Icfb8808c2ff4a30187e9935a51cad26987451c22
Reviewed-by: Ivan Solovev <ivan.solovev@qt.io>
Reviewed-by: Qt CI Bot <qt_ci_bot@qt-project.org>
2022-11-03 14:59:24 +01:00
Marc Mutz
fc76767692 Long live Q_UNREACHABLE_RETURN()!
This is a combination of Q_UNREACHABLE() with a return statement.

ATM, the return statement is unconditionally included. If we notice
that some compilers warn about return after __builtin_unreachable(),
then we can map Q_UNREACHABLE_RETURN(...) to Q_UNREACHABLE() without
having to touch all the code that uses explicit Q_UNREACHABLE() +
return.

The fact that Boost has BOOST_UNREACHABLE_RETURN() indicates that
there are compilers that complain about a lack of return after
Q_UNREACHABLE (we know that MSVC, ICC, and GHS are among them), as
well as compilers that complained about a return being present
(Coverity). Take this opportunity to properly adapt to Coverity, by
leaving out the return statement on this compiler.

Apply the macro around the code base, using a clang-tidy transformer
rule:

    const std::string unr = "unr", val = "val", ret = "ret";
    auto makeUnreachableReturn = cat("Q_UNREACHABLE_RETURN(",
                                    ifBound(val, cat(node(val)), cat("")),
                                    ")");
    auto ignoringSwitchCases = [](auto stmt) {
        return anyOf(stmt, switchCase(subStmt(stmt)));
    };

    makeRule(
       stmt(ignoringSwitchCases(stmt(isExpandedFromMacro("Q_UNREACHABLE")).bind(unr)),
            nextStmt(returnStmt(optionally(hasReturnValue(expr().bind(val)))).bind(ret))),
       {changeTo(node(unr), cat(makeUnreachableReturn,
                                ";")),  // TODO: why is the ; lost w/o this?
        changeTo(node(ret), cat(""))},
       cat("use ", makeUnreachableReturn))
    );

where nextStmt() is copied from some upstream clang-tidy check's
private implementation and subStmt() is a private matcher that gives
access to SwitchCase's SubStmt.

A.k.a. qt-use-unreachable-return.

There were some false positives, suppressed them with NOLINTNEXTLINE.

They're not really false positiives, it's just that Clang sees the
world in one way and if conditonal compilation (#if) differs for other
compilers, Clang doesn't know better. This is an artifact of matching
two consecutive statements.

I haven't figured out how to remove the empty line left by the
deletion of the return statement, if it, indeed, was on a separate
line, so post-processed the patch to remove all the lines matching
^\+ *$ from the diff:

  git commit -am meep
  git reset --hard HEAD^
  git diff HEAD..HEAD@{1} | sed '/^\+ *$/d' | recountdiff - | patch -p1

[ChangeLog][QtCore][QtAssert] Added Q_UNREACHABLE_RETURN() macro.

Change-Id: I9782939f16091c964f25b7826e1c0dbd13a71305
Reviewed-by: Marc Mutz <marc.mutz@qt.io>
Reviewed-by: Thiago Macieira <thiago.macieira@intel.com>
2022-10-15 22:11:47 +02:00
Marc Mutz
aa37e67ef7 Port from qAsConst() to std::as_const()
We've been requiring C++17 since Qt 6.0, and our qAsConst use finally
starts to bother us (QTBUG-99313), so time to port away from it
now.

Since qAsConst has exactly the same semantics as std::as_const (down
to rvalue treatment, constexpr'ness and noexcept'ness), there's really
nothing more to it than a global search-and-replace, with manual
unstaging of the actual definition and documentation in dist/,
src/corelib/doc/ and src/corelib/global/.

Task-number: QTBUG-99313
Change-Id: I4c7114444a325ad4e62d0fcbfd347d2bbfb21541
Reviewed-by: Ivan Solovev <ivan.solovev@qt.io>
2022-10-11 23:17:18 +02:00
Marc Mutz
df9d882d41 Port from container.count()/length() to size()
This is semantic patch using ClangTidyTransformator:

  auto QtContainerClass = expr(hasType(namedDecl(hasAnyName(<classes>)))).bind(o)
  makeRule(cxxMemberCallExpr(on(QtContainerClass),
                             callee(cxxMethodDecl(hasAnyName({"count", "length"),
                                                  parameterCountIs(0))))),
           changeTo(cat(access(o, cat("size"), "()"))),
           cat("use 'size()' instead of 'count()/length()'"))

a.k.a qt-port-to-std-compatible-api with config Scope: 'Container'.

<classes> are:

    // sequential:
    "QByteArray",
    "QList",
    "QQueue",
    "QStack",
    "QString",
    "QVarLengthArray",
    "QVector",
    // associative:
    "QHash",
    "QMultiHash",
    "QMap",
    "QMultiMap",
    "QSet",
    // Qt has no QMultiSet

Change-Id: Ibe8837be96e8d30d1846881ecd65180c1bc459af
Reviewed-by: Qt CI Bot <qt_ci_bot@qt-project.org>
Reviewed-by: Volker Hilsheimer <volker.hilsheimer@qt.io>
2022-10-04 07:40:08 +02:00
Eskil Abrahamsen Blomfeldt
ce4c26c8d1 Revert "QTextLayout: fix maximumWidth() for a text containing line separator"
This reverts commit 013c346a8dcbd618febb07884c64c740daf9754d. It was
determined to cause a regression in Qt Quick: QTBUG-106899.

In order to unblock integrations, we need to revert the change. It
can be re-committed later when the problem has been analyzed and
addressed.

Pick-to: 6.2 6.4
Fixes: QTBUG-106899
Task-number: QTBUG-89557
Task-number: QTBUG-104986
Change-Id: I04054587f68ab39fdb038b02fc69ebfa3dc7d197
Reviewed-by: Volker Hilsheimer <volker.hilsheimer@qt.io>
2022-09-23 20:08:56 +02:00
Vladimir Belyavsky
013c346a8d QTextLayout: fix maximumWidth() for a text containing line separator
When laying out, we need to increase layout's maximum width _only_
if the previous line was not explicitly wrapped by a line or paragraph
separator, or if the current line's width is greater than the
previously accumulated layout's maximum width.

Fixes: QTBUG-89557
Fixes: QTBUG-104986
Pick-to: 6.2 6.4
Change-Id: Ib7cc4b9dda8f20166dcbd5cfd3b56424bb33d14a
Reviewed-by: Konstantin Ritt <ritt.ks@gmail.com>
Reviewed-by: Eskil Abrahamsen Blomfeldt <eskil.abrahamsen-blomfeldt@qt.io>
2022-09-20 06:52:21 +00:00
Marc Mutz
f8976a3e31 Port qt_getJustfication* functions to qsizetype
They're self-contained; callers passing ints will not cause warnings.

Pick-to: 6.4
Task-number: QTBUG-104820
Change-Id: I1dcc1b178b7d72d23dd0596835ab2868c0c6f8c1
Reviewed-by: Sona Kurazyan <sona.kurazyan@qt.io>
2022-07-20 12:56:18 +02:00
Marc Mutz
0a1fe50d0b Pass QFixed by value
It's a glorified int, so pass it by value instead of cref.

Pick-to: 6.4
Change-Id: I1c7a37614cd0d2dac63d2d549563600d401d6dad
Reviewed-by: Sérgio Martins <sergio.martins@kdab.com>
Reviewed-by: Lars Knoll <lars.knoll@gmail.com>
2022-07-08 22:14:52 +02:00
Eskil Abrahamsen Blomfeldt
81fdfcfc4a Fix font rendering when Qt is configured with -no-harfbuzz
When Qt was configured with -no-harfbuzz, we would get overlapping
glyphs, because we skipped the shaping step but did not set up things
correctly before that. Instead, we force the PreferNoShaping code path
when there is no shaper available.

[ChangeLog][Text] Fixed font layouts when Qt was configured without
Harfbuzz.

Pick-to: 6.2 6.3 6.4
Fixes: QTBUG-100361
Change-Id: I1c54dbc457dbb235548b9d70324d607a0ee6d501
Reviewed-by: Lars Knoll <lars.knoll@qt.io>
2022-06-14 14:58:09 +02:00
Lucie Gérard
05fc3aef53 Use SPDX license identifiers
Replace the current license disclaimer in files by
a SPDX-License-Identifier.
Files that have to be modified by hand are modified.
License files are organized under LICENSES directory.

Task-number: QTBUG-67283
Change-Id: Id880c92784c40f3bbde861c0d93f58151c18b9f1
Reviewed-by: Qt CI Bot <qt_ci_bot@qt-project.org>
Reviewed-by: Lars Knoll <lars.knoll@qt.io>
Reviewed-by: Jörg Bornemann <joerg.bornemann@qt.io>
2022-05-16 16:37:38 +02:00
Thiago Macieira
5302857f5a Atomics: workaround GCC 12 warning about overflowing d->state
I don't see a way this can be anything but a bogus warning.

In member function ‘std::__atomic_base<_IntTp>::__int_type std::__atomic_base<_IntTp>::fetch_or(__int_type, std::memory_order) [with _ITp = int]’,
    inlined from ‘static T QAtomicOps<X>::fetchAndOrRelaxed(std::atomic<T>&, typename QAtomicAdditiveType<T>::AdditiveT) [with T = int; X = int]’ at qatomic_cxx11.h:449:33,
    inlined from ‘T QBasicAtomicInteger<T>::fetchAndOrRelaxed(T) [with T = int]’ at qbasicatomic.h:168:36,
    inlined from ‘int switch_on(QAtomicInt&, int)’ at qfutureinterface.cpp:97:31,
    inlined from ‘void QFutureInterfaceBase::setThrottled(bool)’ at qfutureinterface.cpp:194:18:
atomic_base.h:648:33: warning: ‘unsigned int __atomic_or_fetch_4(volatile void*, unsigned int, int)’ writing 4 bytes into a region of size 0 overflows the destination [-Wstringop-overflow=]

A few more of those appear in other modules. I'm not fixing them all,
assuming GCC will soon fix the warning.

Pick-to: 6.2 6.3
Change-Id: I7fb65b80b7844c8d8f26fffd16e93f68e278d048
Reviewed-by: Marc Mutz <marc.mutz@qt.io>
2022-05-11 12:50:08 -07:00
Thiago Macieira
54eae2d610 QTextEngine: don't pass empty data to bidiReorder
The algorithm in QTextEngine::bidiReorder() doesn't like an empty level
and visual order list. Found by GCC 12's slightly misleading warning:

qtextengine.cpp:3838:29: error: ‘levels’ may be used uninitialized [-Werror=maybe-uninitialized]
qtextengine.cpp:1174:6: note: by argument 2 of type ‘const quint8*’ {aka ‘const unsigned char*’} to ‘static void QTextEngine::bidiReorder(int, const quint8*, int*)’ declared here
qtextengine.cpp:3835:28: note: ‘levels’ declared here
 3835 |     QVarLengthArray<uchar> levels(nItems);
      |                            ^~~~~~

Pick-to: 6.2 6.3
Change-Id: If05aeeb7176e4f13af9afffd16e8490f131f160e
Reviewed-by: Lars Knoll <lars.knoll@qt.io>
2022-04-25 16:54:01 -07:00
Eskil Abrahamsen Blomfeldt
7fa2a1a479 Remove last traces of old Harfbuzz
In Qt 6, we removed the "old" Harfbuzz and Harfbuzz-NG became the
only option. But the QT_HARFBUZZ=old environment variable would
still be read and would disable certain parts of the code path.

This has caused some confusion when porting older applications,
where QT_HARFBUZZ=old was used to work around issues with the
earlier versions of Harfbuzz-NG. Setting it now causes text to
disappear completely.

To avoid this confusion, we remove traces of the QT_HARFBUZZ
environment variable as well.

[ChangeLog][Text] Fixed an issue where setting the legacy
environment variable QT_HARFBUZZ=old would cause text to
disappear from the application.

Fixes: QTBUG-102774
Change-Id: I0f07cdb2418202fc36b82e766ad9547c34477175
Reviewed-by: Konstantin Ritt <ritt.ks@gmail.com>
2022-04-22 13:10:59 +02:00
Sona Kurazyan
a5b9600356 QtGui: stop using QLatin1Char constructor for creating char literals
Required for porting away from QLatin1Char/QLatin1String in scope of
QTBUG-98434.

Change-Id: I308d86cefcbfd126929b68f9a853d420840c965f
Reviewed-by: Qt CI Bot <qt_ci_bot@qt-project.org>
Reviewed-by: Marc Mutz <marc.mutz@qt.io>
2022-04-13 18:34:15 +02:00
Mårten Nordheim
6eda249402 Fix deprecated use of QBA/Q*String::count
'Use size() or length() instead'

Change-Id: I284fce29727c4c1ec9ea38a4e8ea13a9e0af5390
Reviewed-by: Sona Kurazyan <sona.kurazyan@qt.io>
2022-03-15 20:18:56 +01:00
Eskil Abrahamsen Blomfeldt
413cd06c88 Fix crash when text shaping fails
If text shaping failed for some reason (for example if the
string passed to Harfbuzz contains ignorables only), we
would return a single glyph for the whole string. But we
forgot to initialize the log clusters array, which could
cause crashes later when this was read. We initialize a
single cluster consisting of the "missing glyph" glyph to
be consistent.

Amends fccd419dd632306a4bd85928223e0a56a59510ef.

[ChangeLog][QtGui][Text] Fixed a possible crash with certain fonts
when shaping strings consisting only of control characters.

Pick-to: 5.15 6.2 6.3
Task-number: QTBUG-89155
Fixes: QTBUG-92358
Change-Id: I1ec0237d99b48be2a8bb340f0feb056bca4fdffe
Reviewed-by: Lars Knoll <lars.knoll@qt.io>
Reviewed-by: Konstantin Ritt <ritt.ks@gmail.com>
Reviewed-by: Qt CI Bot <qt_ci_bot@qt-project.org>
2022-01-14 18:57:41 +01:00
Allan Sandfeld Jensen
4748369eb2 Fix inconsistencies between advanceWidth and bounding rects
Unify the logic in QTextEngine

Ensure tightBoundingRect, and the FreeType boundingRect, calculates from
the shaped x offset when calculating the max x coordinate for a glyph.

Fixes: QTBUG-7768
Task-number: QTBUG-70184
Task-number: QTBUG-85936
Task-number: QTBUG-94023
Change-Id: I6daafb25c79158dc7e777529abb5e8d3a284dac0
Reviewed-by: Qt CI Bot <qt_ci_bot@qt-project.org>
Reviewed-by: Lars Knoll <lars.knoll@qt.io>
Reviewed-by: Shawn Rutledge <shawn.rutledge@qt.io>
2021-10-21 12:37:22 +02:00
Jonas Kvinge
651d7debe1 gui: Fix typos in source code comments
Pick-to: 5.15 6.2
Change-Id: Ie53e5542a8f93856470982939ecd8ec90b323d69
Reviewed-by: Eirik Aavitsland <eirik.aavitsland@qt.io>
2021-10-12 12:52:02 +02:00
Fan RuiJie
586d9e6013 Fix text ellipsis not implemented in Tibetan
The original code checks the existence of an ellipsis character first.If
this does not exist (glyph == 0,which is an invalid glyph index), then
it falls back to looking up '.'. But in the Tibetan environment,the
glyphIndex('.') also returns 0, so that it simply doesn't add any form
of "...", and cuts the text instead.

If both the attempts at getting something from the main font fails,
we can do a third pass on the "multi" font engine.

Fixes: QTBUG-95942
Pick-to: 6.1 6.2
Done-with: Eskil Abrahamsen Blomfeldt <eskil.abrahamsen-blomfeldt@qt.io>
Change-Id: I251de3fe92e19be0462c58c2059ecf7d354bfbb0
Reviewed-by: Eskil Abrahamsen Blomfeldt <eskil.abrahamsen-blomfeldt@qt.io>
2021-08-31 14:53:45 +00:00
Robert Löhning
b4c44bd0fa QTextEngine: Style fix
Change-Id: I4269dd40eb4ad536f3ce8bde599241bacd898da7
Reviewed-by: Konstantin Ritt <ritt.ks@gmail.com>
2021-07-26 13:14:34 +02:00
Allan Sandfeld Jensen
d93fac3290 Fix unaligned specialData formats
Handle the case were a format was applied that does not align with
the fragments.

Pick-to: 6.2 6.1 5.15
Change-Id: I27593a50c587a5ec0290ff9d0a7a9767a3981cac
Reviewed-by: Konstantin Ritt <ritt.ks@gmail.com>
2021-06-11 09:44:20 +00:00
Allan Sandfeld Jensen
5fa80f6cd7 Apply specialData font capitalization to non-rawFont text
We were not using the capitalization details from specialData in the
regular path of QTextEngine::itemize() causing it to be ignored.

Pick-to: 6.1 5.15
Fixes: QTBUG-90840
Change-Id: I7bb71fad4009f6d0685905a946c36ac1d24d8d3c
Reviewed-by: Mårten Nordheim <marten.nordheim@qt.io>
Reviewed-by: Eskil Abrahamsen Blomfeldt <eskil.abrahamsen-blomfeldt@qt.io>
2021-05-06 22:01:23 +02:00
Volker Hilsheimer
6c3599460c Assert that engine isn't nullptr before dereferencing
Various checks for "engine" in the previous code suggested that
engine might be nullptr by the time we want to populate the
out-parameters.

This must not be the case, and QFontDatabase::load asserts
already that a valid engine is loaded and returned.

Fix static analyzer warning 7f68daa282c72e8cc172c681eb02f559 by
asserting it here as well.

As a drive-by, change the tested out-parameter to the last one
in the list of optional parameters.

Pick-to: 6.1
Change-Id: I3d9ff0f5f7c4740014301c073480d14fef54e2fb
Reviewed-by: Jonas Karlsson <jonas.karlsson@qt.io>
Reviewed-by: Eskil Abrahamsen Blomfeldt <eskil.abrahamsen-blomfeldt@qt.io>
2021-04-19 15:18:46 +02:00
Edward Welbourne
aeeaab1a5a Fix handling of surrogates in QBidiAlgorithm
Prior code was naively assuming the character after a high surrogate
would necessarily be a low surrogate, which is buggy.
Fixes oss-fuzz issue 29718.

Pick-to: 6.0 6.1 5.15
Change-Id: I10f023c4b5024a0d76fea0a3672001063591ec6d
Reviewed-by: Konstantin Ritt <ritt.ks@gmail.com>
Reviewed-by: Robert Löhning <robert.loehning@qt.io>
Reviewed-by: Lars Knoll <lars.knoll@qt.io>
2021-04-16 15:49:28 +01:00
Allan Sandfeld Jensen
0ffdbb2126 Handle macOS 11 issues in softHyphens test
Calculate the effective width of the hyphen better, and compare with
ceiled sizes.

Pick-to: 6.1 6.0
Fixes: QTBUG-90698
Change-Id: I7ed2eb44c54240ecb2f8a38e5acf1f32608b2bfb
Reviewed-by: Eskil Abrahamsen Blomfeldt <eskil.abrahamsen-blomfeldt@qt.io>
2021-02-08 11:22:08 +01:00
Eskil Abrahamsen Blomfeldt
fccd419dd6 Remove false Q_UNREACHABLE from shaping code
This was added by 9ff76c27b9031ae7c49c4c9e8b5a3bea1e0e3c78 on
the basis that it signifies a shaping error and would later assert
or crash.

But the line is easily reachable by user code. If Harfbuzz returns
0 glyphs, it just means it is unable to shape the string, for instance
if the input string only contains default ignorables (like a ZWJ)
and does not have any appropriate glyph to use for replacement.

Qt expects there to always be at least one glyph in the output
(num_glyphs == 0 is used to indicate shaping is not yet done), so
to avoid asserts later on, we simply populate the output with a
single 0 token, which is a required entry in the font that is
reserved for representing unrepresentable characters.

This also adds a test and therefore a zero-width joiner to the test
font to reproduce the issue.

[ChangeLog][QtGui][Text] Fixed a possible crash with certain fonts
when shaping strings consisting only of control characters.

Fixes: QTBUG-89155
Pick-to: 5.15
Pick-to: 6.0
Change-Id: Ia0dd6a04844c9be90dcab6c464bebe339a3dab11
Reviewed-by: Konstantin Ritt <ritt.ks@gmail.com>
2021-02-03 09:44:44 +01:00
Eskil Abrahamsen Blomfeldt
d79a9b1a4f Implement vertical subpixel positioning where available
For some use cases, vertical subpixel positioning may be
useful, as it allows you to vertically align text with
other painting primitives. This does impose an overhead,
so we make it opt-int with a render hint on the painter.

Note that this is only supported on Freetype currently.
It might be possible to support on older macOS versions,
prior to Mojave (which has disabled subpixel positioning
entirely), but since it would have limited usefulness
and Freetype is cross-platform anyway, I skipped that.

Note: This drive-by-fixes an issue with subpixel
positioning where glyphs would always be offset by 1/64,
because we added the aliasing offset *after* we had
determined the closest subpixel position. The idea of
this, as far as I can understand, is rather to snap to
nearest subpixel position upwards, not to add an offset
to all glyphs, so it should be added before finding the
correct position. It had a subtle visual effect when
animating the position. It might be that we could get
rid of it entirely, as I haven't been able to reproduce
any issues with that, but I have moved it instead, to
match what I believe the intention was.

[ChangeLog][QtGui][Text] Added render hint flag
QPainter::VerticalSubpixelPositioning which will position
text at subpixel positions vertically whenever supported.
In absence of this, text position will be rounded
vertically as before.

Fixes: QTBUG-35682
Change-Id: I8ce7a72a64e5a0924dac7c244e3e07c2938bfd09
Reviewed-by: Qt CI Bot <qt_ci_bot@qt-project.org>
Reviewed-by: Allan Sandfeld Jensen <allan.jensen@qt.io>
2021-01-25 15:56:50 +01:00
Zhang Sheng
e13173c112 Adjust code format, add space after 'if'
Change-Id: Ice081c891ff7f4b766f49dd4bd5cf18c30237acf
Reviewed-by: Allan Sandfeld Jensen <allan.jensen@qt.io>
Reviewed-by: hjk <hjk@qt.io>
2020-11-16 12:53:37 +00:00
Allan Sandfeld Jensen
94dd2cebdc Remove Qt4Compatible painting
Change-Id: Ie54206ca9b509875568f2158e229fca9cb1860a2
Reviewed-by: Lars Knoll <lars.knoll@qt.io>
2020-11-12 08:31:18 +01:00
Lars Knoll
0ae5b8af9c Clean up QTextBoundaryFinder and qunicodetools
Make QTBF ready for Qt6 by using qsizetype in the API and use
QStringView where it makes sense.

Change the exported API of qunicodetools to use QStringView as
well and use char16_t internally.

Change-Id: I853537bcabf40546a8e60fdf2ee7d751bc371761
Reviewed-by: Mårten Nordheim <marten.nordheim@qt.io>
2020-09-07 09:09:55 +02:00
Edward Welbourne
1aa412987f Remove QUnicodeTools::DefaultOptionsCompat
Used in only one place, declared in a private header with a comment
saying to remove it. All callers of the one function that had it as
default parameter value are passing a value for the parameter.

Task-number: QTBUG-85700
Change-Id: Ic72e4df730740a4023b0a43be6bf7acf33a3166b
Reviewed-by: Thiago Macieira <thiago.macieira@intel.com>
2020-08-28 21:29:45 +02:00
Friedemann Kleint
ae5d021f45 Fix some MSVC int conversion warnings
kernel\qmetaobjectbuilder.cpp(1279): warning C4267: 'initializing': conversion from 'size_t' to 'int', possible loss of data
kernel\qmetaobjectbuilder.cpp(1432): warning C4267: '+=': conversion from 'size_t' to 'int', possible loss of data
sax\qxml.cpp(1275): warning C4267: 'argument': conversion from 'size_t' to 'int', possible loss of data
text\qfontsubset.cpp(920): warning C4267: 'initializing': conversion from 'size_t' to 'int', possible loss of data
text\qfontsubset.cpp(920): warning C4267: 'initializing': conversion from 'size_t' to 'const int', possible loss of data
text\qtextengine.cpp(2664): warning C4267: 'initializing': conversion from 'size_t' to 'int', possible loss of data
text\qtextengine.cpp(2665): warning C4267: 'initializing': conversion from 'size_t' to 'int', possible loss of data
text\qtextengine.cpp(2706): warning C4267: 'initializing': conversion from 'size_t' to 'int', possible loss of data
text\qtextengine.cpp(2707): warning C4267: 'initializing': conversion from 'size_t' to 'int', possible loss of data
itemviews\qbsptree.cpp(60): warning C4334: '<<': result of 32-bit shift implicitly converted to 64 bits (was 64-bit shift intended?)
kernel\qprintengine_win.cpp(1558): warning C4267: 'initializing': conversion from 'size_t' to 'int', possible loss of data
qsql_odbc.cpp(804): warning C4267: 'argument': conversion from 'size_t' to 'SQLINTEGER', possible loss of data
qsql_odbc.cpp(822): warning C4267: 'argument': conversion from 'size_t' to 'SQLINTEGER', possible loss of data
qsql_odbc.cpp(1585): warning C4267: 'initializing': conversion from 'size_t' to 'int', possible loss of data
qsql_odbc.cpp(1602): warning C4267: 'argument': conversion from 'size_t' to 'int', possible loss of data
qwindowsmime.cpp(770): warning C4267: '+=': conversion from 'size_t' to 'int', possible loss of data
windows\qwindowsmime.cpp(770): warning C4267: '+=': conversion from 'size_t' to 'int', possible loss of data

Change-Id: I04fbe17b9782f4c2704933fc005449b1e992475e
Reviewed-by: Thiago Macieira <thiago.macieira@intel.com>
2020-07-17 22:14:43 +02:00
Jarek Kobus
471e4fcb22 Use QList instead of QVector in gui implementation
Task-number: QTBUG-84469
Change-Id: I366e845249203d80d640355a7780ac2f91a762f1
Reviewed-by: Tor Arne Vestbø <tor.arne.vestbo@qt.io>
Reviewed-by: Friedemann Kleint <Friedemann.Kleint@qt.io>
2020-07-07 20:35:05 +02:00