0.9.47 alpha: fixed crash in text processing (Qt pach updated).

This commit is contained in:
John Preston 2016-05-02 16:42:09 +03:00
parent 724ba9e429
commit dff5765f9f
11 changed files with 236 additions and 132 deletions

View File

@ -17,17 +17,19 @@ index eec9e1f..ec3015e 100644
QMAKE_CFLAGS_LTCG = -GL
QMAKE_CFLAGS_SSE2 = -arch:SSE2
diff --git a/src/corelib/io/qfilesystemengine_win.cpp b/src/corelib/io/qfilesystemengine_win.cpp
index f1a6019..a53a6c4 100644
index f1a6019..81ff6ef 100644
--- a/src/corelib/io/qfilesystemengine_win.cpp
+++ b/src/corelib/io/qfilesystemengine_win.cpp
@@ -1416,8 +1416,9 @@ bool QFileSystemEngine::copyFile(const QFileSystemEntry &source, const QFileSyst
@@ -1416,8 +1416,10 @@ bool QFileSystemEngine::copyFile(const QFileSystemEntry &source, const QFileSyst
COPYFILE2_EXTENDED_PARAMETERS copyParams = {
sizeof(copyParams), COPY_FILE_FAIL_IF_EXISTS, NULL, NULL, NULL
};
+ // CopyFile2 returns HRESULT, not BOOL, so it should be tested for S_OK, not 0.
bool ret = ::CopyFile2((const wchar_t*)source.nativeFilePath().utf16(),
- bool ret = ::CopyFile2((const wchar_t*)source.nativeFilePath().utf16(),
- (const wchar_t*)target.nativeFilePath().utf16(), &copyParams) != 0;
+ (const wchar_t*)target.nativeFilePath().utf16(), &copyParams) == S_OK;
+ // CopyFile2 returns HRESULT, not BOOL, so it should be tested for S_OK, not 0.
+ HRESULT hres = ::CopyFile2((const wchar_t*)source.nativeFilePath().utf16(),
+ (const wchar_t*)target.nativeFilePath().utf16(), &copyParams);
+ bool ret = SUCCEEDED(hres);
#endif // Q_OS_WINRT
if(!ret)
error = QSystemError(::GetLastError(), QSystemError::NativeError);
@ -114,7 +116,7 @@ index 39c228f..b72fdc0 100644
public:
inline QTextItemInt()
diff --git a/src/gui/text/qtextlayout.cpp b/src/gui/text/qtextlayout.cpp
index 9e2a23a..861f202 100644
index 9e2a23a..4466a4e 100644
--- a/src/gui/text/qtextlayout.cpp
+++ b/src/gui/text/qtextlayout.cpp
@@ -694,6 +694,9 @@ int QTextLayout::nextCursorPosition(int oldPos, CursorMode mode) const
@ -136,6 +138,47 @@ index 9e2a23a..861f202 100644
}
return oldPos;
@@ -1644,6 +1645,7 @@ namespace {
int maxGlyphs;
int currentPosition;
glyph_t previousGlyph;
+ QFontEngine *previousGlyphFontEngine;
QFixed minw;
QFixed softHyphenWidth;
@@ -1677,13 +1679,14 @@ namespace {
if (currentPosition > 0 &&
logClusters[currentPosition - 1] < glyphs.numGlyphs) {
previousGlyph = currentGlyph(); // needed to calculate right bearing later
+ previousGlyphFontEngine = fontEngine;
}
}
- inline void calculateRightBearing(glyph_t glyph)
+ inline void calculateRightBearing(QFontEngine *engine, glyph_t glyph)
{
qreal rb;
- fontEngine->getGlyphBearings(glyph, 0, &rb);
+ engine->getGlyphBearings(glyph, 0, &rb);
// We only care about negative right bearings, so we limit the range
// of the bearing here so that we can assume it's negative in the rest
@@ -1696,13 +1699,13 @@ namespace {
{
if (currentPosition <= 0)
return;
- calculateRightBearing(currentGlyph());
+ calculateRightBearing(fontEngine, currentGlyph());
}
inline void calculateRightBearingForPreviousGlyph()
{
if (previousGlyph > 0)
- calculateRightBearing(previousGlyph);
+ calculateRightBearing(previousGlyphFontEngine, previousGlyph);
}
static const QFixed RightBearingNotCalculated;
diff --git a/src/gui/text/qtextlayout.h b/src/gui/text/qtextlayout.h
index f74d4d4..57d449a 100644
--- a/src/gui/text/qtextlayout.h

View File

@ -34,8 +34,8 @@ IDI_ICON1 ICON "..\\art\\icon256.ico"
//
VS_VERSION_INFO VERSIONINFO
FILEVERSION 0,9,46,0
PRODUCTVERSION 0,9,46,0
FILEVERSION 0,9,47,0
PRODUCTVERSION 0,9,47,0
FILEFLAGSMASK 0x3fL
#ifdef _DEBUG
FILEFLAGS 0x1L
@ -51,10 +51,10 @@ BEGIN
BLOCK "040904b0"
BEGIN
VALUE "CompanyName", "Telegram Messenger LLP"
VALUE "FileVersion", "0.9.46.0"
VALUE "FileVersion", "0.9.47.0"
VALUE "LegalCopyright", "Copyright (C) 2014-2016"
VALUE "ProductName", "Telegram Desktop"
VALUE "ProductVersion", "0.9.46.0"
VALUE "ProductVersion", "0.9.47.0"
END
END
BLOCK "VarFileInfo"

View File

@ -25,8 +25,8 @@ LANGUAGE LANG_ENGLISH, SUBLANG_ENGLISH_US
//
VS_VERSION_INFO VERSIONINFO
FILEVERSION 0,9,46,0
PRODUCTVERSION 0,9,46,0
FILEVERSION 0,9,47,0
PRODUCTVERSION 0,9,47,0
FILEFLAGSMASK 0x3fL
#ifdef _DEBUG
FILEFLAGS 0x1L
@ -43,10 +43,10 @@ BEGIN
BEGIN
VALUE "CompanyName", "Telegram Messenger LLP"
VALUE "FileDescription", "Telegram Updater"
VALUE "FileVersion", "0.9.46.0"
VALUE "FileVersion", "0.9.47.0"
VALUE "LegalCopyright", "Copyright (C) 2014-2016"
VALUE "ProductName", "Telegram Desktop"
VALUE "ProductVersion", "0.9.46.0"
VALUE "ProductVersion", "0.9.47.0"
END
END
BLOCK "VarFileInfo"

View File

@ -24,7 +24,7 @@ Copyright (c) 2014-2016 John Preston, https://desktop.telegram.org
#define BETA_VERSION_MACRO (0ULL)
static constexpr int AppVersion = 9046;
static constexpr str_const AppVersionStr = "0.9.46";
static constexpr int AppVersion = 9047;
static constexpr str_const AppVersionStr = "0.9.47";
static constexpr bool AppAlphaVersion = true;
static constexpr uint64 AppBetaVersion = BETA_VERSION_MACRO;

View File

@ -944,10 +944,14 @@ namespace internal {
#ifdef Q_OS_WIN
internal::BreakpadExceptionHandler = new google_breakpad::ExceptionHandler(
dumpspath.toStdWString(),
/*FilterCallback*/ 0,
google_breakpad::ExceptionHandler::FilterCallback(nullptr),
internal::DumpCallback,
/*context*/ 0,
true
(void*)nullptr, // callback_context
google_breakpad::ExceptionHandler::HANDLER_ALL,
MINIDUMP_TYPE(MiniDumpNormal),
// MINIDUMP_TYPE(MiniDumpWithFullMemory | MiniDumpWithHandleData | MiniDumpWithThreadInfo | MiniDumpWithProcessThreadData | MiniDumpWithFullMemoryInfo | MiniDumpWithUnloadedModules | MiniDumpWithFullAuxiliaryState | MiniDumpIgnoreInaccessibleMemory | MiniDumpWithTokenInformation),
(const wchar_t*)nullptr, // pipe_name
(const google_breakpad::CustomClientInfo*)nullptr
);
#elif defined Q_OS_MAC // Q_OS_WIN
@ -968,11 +972,11 @@ namespace internal {
std::string handler = (cExeDir() + cExeName() + qsl("/Contents/Helpers/crashpad_handler")).toUtf8().constData();
std::string database = QFile::encodeName(dumpspath).constData();
if (crashpad_client.StartHandler(base::FilePath(handler),
base::FilePath(database),
std::string(),
ProcessAnnotations,
std::vector<std::string>(),
false)) {
base::FilePath(database),
std::string(),
ProcessAnnotations,
std::vector<std::string>(),
false)) {
crashpad_client.UseHandler();
}
#endif // else for MAC_USE_BREAKPAD

View File

@ -34,18 +34,14 @@ namespace {
const style::textStyle *_textStyle = nullptr;
void _initDefault() {
void initDefault() {
_textStyle = &st::defaultTextStyle;
}
inline int32 _blockHeight(const ITextBlock *b, const style::font &font) {
inline int32 countBlockHeight(const ITextBlock *b, const style::font &font) {
return (b->type() == TextBlockTSkip) ? static_cast<const SkipBlock*>(b)->height() : (_textStyle->lineHeight > font->height) ? _textStyle->lineHeight : font->height;
}
inline QFixed _blockRBearing(const ITextBlock *b) {
return (b->type() == TextBlockTText) ? static_cast<const TextBlock*>(b)->f_rbearing() : 0;
}
} // namespace
const style::textStyle *textstyleCurrent() {
@ -908,7 +904,7 @@ public:
if (_t->isEmpty()) return;
_blocksSize = _t->_blocks.size();
if (!_textStyle) _initDefault();
if (!_textStyle) initDefault();
if (_p) {
_p->setFont(_t->_font->f);
@ -955,8 +951,7 @@ public:
for (Text::TextBlocks::const_iterator i = _t->_blocks.cbegin(); i != e; ++i, ++blockIndex) {
ITextBlock *b = *i;
TextBlockType _btype = b->type();
int32 blockHeight = _blockHeight(b, _t->_font);
QFixed _rb = _blockRBearing(b);
int32 blockHeight = countBlockHeight(b, _t->_font);
if (_btype == TextBlockTNewline) {
if (!_lineHeight) _lineHeight = blockHeight;
@ -968,7 +963,7 @@ public:
_lineStart = nextStart;
_lineStartBlock = blockIndex + 1;
last_rBearing = _rb;
last_rBearing = b->f_rbearing();
last_rPadding = b->f_rpadding();
_wLeft = _w - (b->f_width() - last_rBearing);
if (_elideLast && _elideRemoveFromEnd > 0 && (_y + blockHeight >= _yToElide)) {
@ -983,10 +978,11 @@ public:
continue;
}
QFixed lpadding = b->f_lpadding();
QFixed newWidthLeft = _wLeft - lpadding - last_rBearing - (last_rPadding + b->f_width() - _rb);
auto b__f_lpadding = b->f_lpadding();
auto b__f_rbearing = b->f_rbearing();
QFixed newWidthLeft = _wLeft - b__f_lpadding - last_rBearing - (last_rPadding + b->f_width() - b__f_rbearing);
if (newWidthLeft >= 0) {
last_rBearing = _rb;
last_rBearing = b__f_rbearing;
last_rPadding = b->f_rpadding();
_wLeft = newWidthLeft;
@ -999,7 +995,7 @@ public:
if (_btype == TextBlockTText) {
TextBlock *t = static_cast<TextBlock*>(b);
if (t->_words.isEmpty()) { // no words in this block, spaces only => layout this block in the same line
last_rPadding += lpadding;
last_rPadding += b__f_lpadding;
_lineHeight = qMax(_lineHeight, blockHeight);
@ -1010,14 +1006,14 @@ public:
QFixed f_wLeft = _wLeft; // vars for saving state of the last word start
int32 f_lineHeight = _lineHeight; // f points to the last word-start element of t->_words
for (TextBlock::TextWords::const_iterator j = t->_words.cbegin(), en = t->_words.cend(), f = j; j != en; ++j) {
bool wordEndsHere = (j->width >= 0);
QFixed j_width = wordEndsHere ? j->width : -j->width;
bool wordEndsHere = (j->f_width() >= 0);
QFixed j_width = wordEndsHere ? j->f_width() : -j->f_width();
QFixed newWidthLeft = _wLeft - lpadding - last_rBearing - (last_rPadding + j_width - j->f_rbearing());
lpadding = 0;
QFixed newWidthLeft = _wLeft - b__f_lpadding - last_rBearing - (last_rPadding + j_width - j->f_rbearing());
b__f_lpadding = 0;
if (newWidthLeft >= 0) {
last_rBearing = j->f_rbearing();
last_rPadding = j->rpadding;
last_rPadding = j->f_rpadding();
_wLeft = newWidthLeft;
_lineHeight = qMax(_lineHeight, blockHeight);
@ -1042,16 +1038,16 @@ public:
j = f;
_wLeft = f_wLeft;
_lineHeight = f_lineHeight;
j_width = (j->width >= 0) ? j->width : -j->width;
j_width = (j->f_width() >= 0) ? j->f_width() : -j->f_width();
}
if (!drawLine(elidedLine ? ((j + 1 == en) ? _blockEnd(_t, i, e) : (j + 1)->from) : j->from, i, e)) return;
if (!drawLine(elidedLine ? ((j + 1 == en) ? _blockEnd(_t, i, e) : (j + 1)->from()) : j->from(), i, e)) return;
_y += _lineHeight;
_lineHeight = qMax(0, blockHeight);
_lineStart = j->from;
_lineStart = j->from();
_lineStartBlock = blockIndex;
last_rBearing = j->f_rbearing();
last_rPadding = j->rpadding;
last_rPadding = j->f_rpadding();
_wLeft = _w - (j_width - last_rBearing);
if (_elideLast && _elideRemoveFromEnd > 0 && (_y + blockHeight >= _yToElide)) {
_wLeft -= _elideRemoveFromEnd;
@ -1076,7 +1072,7 @@ public:
_lineStart = b->from();
_lineStartBlock = blockIndex;
last_rBearing = _rb;
last_rBearing = b__f_rbearing;
last_rPadding = b->f_rpadding();
_wLeft = _w - (b->f_width() - last_rBearing);
if (_elideLast && _elideRemoveFromEnd > 0 && (_y + blockHeight >= _yToElide)) {
@ -2404,7 +2400,7 @@ Text &Text::operator=(Text &&other) {
}
void Text::setText(style::font font, const QString &text, const TextParseOptions &options) {
if (!_textStyle) _initDefault();
if (!_textStyle) initDefault();
_font = font;
clear();
{
@ -2423,9 +2419,7 @@ void Text::recountNaturalSize(bool initial, Qt::LayoutDirection optionsDir) {
for (TextBlocks::const_iterator i = _blocks.cbegin(), e = _blocks.cend(); i != e; ++i) {
ITextBlock *b = *i;
TextBlockType _btype = b->type();
int32 blockHeight = _blockHeight(b, _font);
QFixed _rb = _blockRBearing(b);
int32 blockHeight = countBlockHeight(b, _font);
if (_btype == TextBlockTNewline) {
if (!lineHeight) lineHeight = blockHeight;
if (initial) {
@ -2444,7 +2438,7 @@ void Text::recountNaturalSize(bool initial, Qt::LayoutDirection optionsDir) {
_minHeight += lineHeight;
lineHeight = 0;
last_rBearing = _rb;
last_rBearing = b->f_rbearing();
last_rPadding = b->f_rpadding();
if (_maxWidth < _width) {
_maxWidth = _width;
@ -2453,11 +2447,13 @@ void Text::recountNaturalSize(bool initial, Qt::LayoutDirection optionsDir) {
continue;
}
auto b__f_rbearing = b->f_rbearing(); // cache
_width += b->f_lpadding();
_width += last_rBearing + (last_rPadding + b->f_width() - _rb);
_width += last_rBearing + (last_rPadding + b->f_width() - b__f_rbearing);
lineHeight = qMax(lineHeight, blockHeight);
last_rBearing = _rb;
last_rBearing = b__f_rbearing;
last_rPadding = b->f_rpadding();
continue;
}
@ -2473,7 +2469,7 @@ void Text::recountNaturalSize(bool initial, Qt::LayoutDirection optionsDir) {
}
}
if (_width > 0) {
if (!lineHeight) lineHeight = _blockHeight(_blocks.back(), _font);
if (!lineHeight) lineHeight = countBlockHeight(_blocks.back(), _font);
_minHeight += lineHeight;
if (_maxWidth < _width) {
_maxWidth = _width;
@ -2482,7 +2478,7 @@ void Text::recountNaturalSize(bool initial, Qt::LayoutDirection optionsDir) {
}
void Text::setMarkedText(style::font font, const QString &text, const EntitiesInText &entities, const TextParseOptions &options) {
if (!_textStyle) _initDefault();
if (!_textStyle) initDefault();
_font = font;
clear();
{
@ -2644,11 +2640,10 @@ int32 Text::countWidth(int32 w) const {
for (TextBlocks::const_iterator i = _blocks.cbegin(), e = _blocks.cend(); i != e; ++i) {
ITextBlock *b = *i;
TextBlockType _btype = b->type();
int32 blockHeight = _blockHeight(b, _font);
QFixed _rb = _blockRBearing(b);
int32 blockHeight = countBlockHeight(b, _font);
if (_btype == TextBlockTNewline) {
last_rBearing = _rb;
last_rBearing = b->f_rbearing();
last_rPadding = b->f_rpadding();
if (widthLeft < minWidthLeft) {
minWidthLeft = widthLeft;
@ -2658,10 +2653,11 @@ int32 Text::countWidth(int32 w) const {
longWordLine = true;
continue;
}
QFixed lpadding = b->f_lpadding();
QFixed newWidthLeft = widthLeft - lpadding - last_rBearing - (last_rPadding + b->f_width() - _rb);
auto b__f_lpadding = b->f_lpadding();
auto b__f_rbearing = b->f_rbearing(); // cache
QFixed newWidthLeft = widthLeft - b__f_lpadding - last_rBearing - (last_rPadding + b->f_width() - b__f_rbearing);
if (newWidthLeft >= 0) {
last_rBearing = _rb;
last_rBearing = b__f_rbearing;
last_rPadding = b->f_rpadding();
widthLeft = newWidthLeft;
@ -2672,7 +2668,7 @@ int32 Text::countWidth(int32 w) const {
if (_btype == TextBlockTText) {
TextBlock *t = static_cast<TextBlock*>(b);
if (t->_words.isEmpty()) { // no words in this block, spaces only => layout this block in the same line
last_rPadding += lpadding;
last_rPadding += b__f_lpadding;
longWordLine = false;
continue;
@ -2680,14 +2676,14 @@ int32 Text::countWidth(int32 w) const {
QFixed f_wLeft = widthLeft;
for (TextBlock::TextWords::const_iterator j = t->_words.cbegin(), e = t->_words.cend(), f = j; j != e; ++j) {
bool wordEndsHere = (j->width >= 0);
QFixed j_width = wordEndsHere ? j->width : -j->width;
bool wordEndsHere = (j->f_width() >= 0);
QFixed j_width = wordEndsHere ? j->f_width() : -j->f_width();
QFixed newWidthLeft = widthLeft - lpadding - last_rBearing - (last_rPadding + j_width - j->f_rbearing());
lpadding = 0;
QFixed newWidthLeft = widthLeft - b__f_lpadding - last_rBearing - (last_rPadding + j_width - j->f_rbearing());
b__f_lpadding = 0;
if (newWidthLeft >= 0) {
last_rBearing = j->f_rbearing();
last_rPadding = j->rpadding;
last_rPadding = j->f_rpadding();
widthLeft = newWidthLeft;
if (wordEndsHere) {
@ -2703,11 +2699,11 @@ int32 Text::countWidth(int32 w) const {
if (f != j) {
j = f;
widthLeft = f_wLeft;
j_width = (j->width >= 0) ? j->width : -j->width;
j_width = (j->f_width() >= 0) ? j->f_width() : -j->f_width();
}
last_rBearing = j->f_rbearing();
last_rPadding = j->rpadding;
last_rPadding = j->f_rpadding();
if (widthLeft < minWidthLeft) {
minWidthLeft = widthLeft;
}
@ -2720,7 +2716,7 @@ int32 Text::countWidth(int32 w) const {
continue;
}
last_rBearing = _rb;
last_rBearing = b__f_rbearing;
last_rPadding = b->f_rpadding();
if (widthLeft < minWidthLeft) {
minWidthLeft = widthLeft;
@ -2750,24 +2746,24 @@ int32 Text::countHeight(int32 w) const {
for (TextBlocks::const_iterator i = _blocks.cbegin(), e = _blocks.cend(); i != e; ++i) {
ITextBlock *b = *i;
TextBlockType _btype = b->type();
int32 blockHeight = _blockHeight(b, _font);
QFixed _rb = _blockRBearing(b);
int32 blockHeight = countBlockHeight(b, _font);
if (_btype == TextBlockTNewline) {
if (!lineHeight) lineHeight = blockHeight;
result += lineHeight;
lineHeight = 0;
last_rBearing = _rb;
last_rBearing = b->f_rbearing();
last_rPadding = b->f_rpadding();
widthLeft = width - (b->f_width() - last_rBearing);
longWordLine = true;
continue;
}
QFixed lpadding = b->f_lpadding();
QFixed newWidthLeft = widthLeft - lpadding - last_rBearing - (last_rPadding + b->f_width() - _rb);
auto b__f_lpadding = b->f_lpadding();
auto b__f_rbearing = b->f_rbearing();
QFixed newWidthLeft = widthLeft - b__f_lpadding - last_rBearing - (last_rPadding + b->f_width() - b__f_rbearing);
if (newWidthLeft >= 0) {
last_rBearing = _rb;
last_rBearing = b__f_rbearing;
last_rPadding = b->f_rpadding();
widthLeft = newWidthLeft;
@ -2780,7 +2776,7 @@ int32 Text::countHeight(int32 w) const {
if (_btype == TextBlockTText) {
TextBlock *t = static_cast<TextBlock*>(b);
if (t->_words.isEmpty()) { // no words in this block, spaces only => layout this block in the same line
last_rPadding += lpadding;
last_rPadding += b__f_lpadding;
lineHeight = qMax(lineHeight, blockHeight);
@ -2791,14 +2787,14 @@ int32 Text::countHeight(int32 w) const {
QFixed f_wLeft = widthLeft;
int32 f_lineHeight = lineHeight;
for (TextBlock::TextWords::const_iterator j = t->_words.cbegin(), e = t->_words.cend(), f = j; j != e; ++j) {
bool wordEndsHere = (j->width >= 0);
QFixed j_width = wordEndsHere ? j->width : -j->width;
bool wordEndsHere = (j->f_width() >= 0);
QFixed j_width = wordEndsHere ? j->f_width() : -j->f_width();
QFixed newWidthLeft = widthLeft - lpadding - last_rBearing - (last_rPadding + j_width - j->f_rbearing());
lpadding = 0;
QFixed newWidthLeft = widthLeft - b__f_lpadding - last_rBearing - (last_rPadding + j_width - j->f_rbearing());
b__f_lpadding = 0;
if (newWidthLeft >= 0) {
last_rBearing = j->f_rbearing();
last_rPadding = j->rpadding;
last_rPadding = j->f_rpadding();
widthLeft = newWidthLeft;
lineHeight = qMax(lineHeight, blockHeight);
@ -2818,13 +2814,13 @@ int32 Text::countHeight(int32 w) const {
j = f;
widthLeft = f_wLeft;
lineHeight = f_lineHeight;
j_width = (j->width >= 0) ? j->width : -j->width;
j_width = (j->f_width() >= 0) ? j->f_width() : -j->f_width();
}
result += lineHeight;
lineHeight = qMax(0, blockHeight);
last_rBearing = j->f_rbearing();
last_rPadding = j->rpadding;
last_rPadding = j->f_rpadding();
widthLeft = width - (j_width - last_rBearing);
longWordLine = true;
@ -2837,7 +2833,7 @@ int32 Text::countHeight(int32 w) const {
result += lineHeight;
lineHeight = qMax(0, blockHeight);
last_rBearing = _rb;
last_rBearing = b__f_rbearing;
last_rPadding = b->f_rpadding();
widthLeft = width - (b->f_width() - last_rBearing);

View File

@ -32,10 +32,11 @@ struct ScriptLine {
QFixed textWidth;
};
// All members finished with "_" are internal.
struct LineBreakHelper
{
LineBreakHelper()
: glyphCount(0), maxGlyphs(0), currentPosition(0), fontEngine(0), logClusters(0)
: glyphCount(0), maxGlyphs(INT_MAX), currentPosition(0), fontEngine(0), logClusters(0)
{
}
@ -48,7 +49,9 @@ struct LineBreakHelper
int glyphCount;
int maxGlyphs;
int currentPosition;
glyph_t previousGlyph;
glyph_t previousGlyph_ = 0;
QFontEngine *previousFontEngine_ = nullptr;
QFixed rightBearing;
@ -65,35 +68,71 @@ struct LineBreakHelper
inline void saveCurrentGlyph()
{
previousGlyph = 0;
if (currentPosition > 0 &&
logClusters[currentPosition - 1] < glyphs.numGlyphs) {
previousGlyph = currentGlyph(); // needed to calculate right bearing later
previousGlyph_ = currentGlyph(); // needed to calculate right bearing later
previousFontEngine_ = fontEngine;
} else {
previousGlyph_ = 0;
previousFontEngine_ = nullptr;
}
}
inline void adjustRightBearing(glyph_t glyph)
inline void calculateRightBearing(QFontEngine *engine, glyph_t glyph)
{
qreal rb;
fontEngine->getGlyphBearings(glyph, 0, &rb);
rightBearing = qMin(QFixed(), QFixed::fromReal(rb));
engine->getGlyphBearings(glyph, 0, &rb);
// We only care about negative right bearings, so we limit the range
// of the bearing here so that we can assume it's negative in the rest
// of the code, as well ase use QFixed(1) as a sentinel to represent
// the state where we have yet to compute the right bearing.
rightBearing = qMin(QFixed::fromReal(rb), QFixed(0));
}
inline void adjustRightBearing()
inline void calculateRightBearing()
{
if (currentPosition <= 0)
return;
adjustRightBearing(currentGlyph());
if (currentPosition > 0 &&
logClusters[currentPosition - 1] < glyphs.numGlyphs) {
calculateRightBearing(fontEngine, currentGlyph());
} else {
rightBearing = 0;
}
}
inline void adjustPreviousRightBearing()
inline void calculateRightBearingForPreviousGlyph()
{
if (previousGlyph > 0)
adjustRightBearing(previousGlyph);
if (previousGlyph_ > 0) {
calculateRightBearing(previousFontEngine_, previousGlyph_);
} else {
rightBearing = 0;
}
}
// We always calculate the right bearing right before it is needed.
// So we don't need caching / optimizations referred to delayed right bearing calculations.
//static const QFixed RightBearingNotCalculated;
//inline void resetRightBearing()
//{
// rightBearing = RightBearingNotCalculated;
//}
// We express the negative right bearing as an absolute number
// so that it can be applied to the width using addition.
inline QFixed negativeRightBearing() const
{
//if (rightBearing == RightBearingNotCalculated)
// return QFixed(0);
return qAbs(rightBearing);
}
};
//const QFixed LineBreakHelper::RightBearingNotCalculated = QFixed(1);
static inline void addNextCluster(int &pos, int end, ScriptLine &line, int &glyphCount,
const QScriptItem &current, const unsigned short *logClusters,
const QGlyphLayout &glyphs)
@ -127,8 +166,6 @@ public:
void parseWords(QFixed minResizeWidth, int32 blockFrom) {
LineBreakHelper lbh;
lbh.maxGlyphs = INT_MAX;
int item = -1;
int newItem = eng->findItem(0);
@ -137,10 +174,8 @@ public:
const QCharAttributes *attributes = eng->attributes();
if (!attributes)
return;
lbh.currentPosition = 0;
int end = 0;
lbh.logClusters = eng->layoutData->logClustersPtr;
lbh.previousGlyph = 0;
block->_lpadding = 0;
block->_words.clear();
@ -180,7 +215,7 @@ public:
if (block->_words.isEmpty()) {
block->_lpadding = lbh.spaceData.textWidth;
} else {
block->_words.back().rpadding += lbh.spaceData.textWidth;
block->_words.back().add_rpadding(lbh.spaceData.textWidth);
block->_width += lbh.spaceData.textWidth;
}
lbh.spaceData.length = 0;
@ -199,8 +234,8 @@ public:
if (lbh.currentPosition >= eng->layoutData->string.length()
|| attributes[lbh.currentPosition].whiteSpace
|| isLineBreak(attributes, lbh.currentPosition)) {
lbh.adjustRightBearing();
block->_words.push_back(TextWord(wordStart + blockFrom, lbh.tmpData.textWidth, qMin(QFixed(), lbh.rightBearing)));
lbh.calculateRightBearing();
block->_words.push_back(TextWord(wordStart + blockFrom, lbh.tmpData.textWidth, -lbh.negativeRightBearing()));
block->_width += lbh.tmpData.textWidth;
lbh.tmpData.textWidth = 0;
lbh.tmpData.length = 0;
@ -209,8 +244,8 @@ public:
} else if (attributes[lbh.currentPosition].graphemeBoundary) {
if (!addingEachGrapheme && lbh.tmpData.textWidth > minResizeWidth) {
if (lastGraphemeBoundaryPosition >= 0) {
lbh.adjustPreviousRightBearing();
block->_words.push_back(TextWord(wordStart + blockFrom, -lastGraphemeBoundaryLine.textWidth, qMin(QFixed(), lbh.rightBearing)));
lbh.calculateRightBearingForPreviousGlyph();
block->_words.push_back(TextWord(wordStart + blockFrom, -lastGraphemeBoundaryLine.textWidth, -lbh.negativeRightBearing()));
block->_width += lastGraphemeBoundaryLine.textWidth;
lbh.tmpData.textWidth -= lastGraphemeBoundaryLine.textWidth;
lbh.tmpData.length -= lastGraphemeBoundaryLine.length;
@ -219,8 +254,8 @@ public:
addingEachGrapheme = true;
}
if (addingEachGrapheme) {
lbh.adjustRightBearing();
block->_words.push_back(TextWord(wordStart + blockFrom, -lbh.tmpData.textWidth, qMin(QFixed(), lbh.rightBearing)));
lbh.calculateRightBearing();
block->_words.push_back(TextWord(wordStart + blockFrom, -lbh.tmpData.textWidth, -lbh.negativeRightBearing()));
block->_width += lbh.tmpData.textWidth;
lbh.tmpData.textWidth = 0;
lbh.tmpData.length = 0;
@ -239,7 +274,7 @@ public:
if (block->_words.isEmpty()) {
block->_rpadding = 0;
} else {
block->_rpadding = block->_words.back().rpadding;
block->_rpadding = block->_words.back().f_rpadding();
block->_width -= block->_rpadding;
block->_words.squeeze();
}
@ -261,6 +296,10 @@ private:
};
QFixed ITextBlock::f_rbearing() const {
return (type() == TextBlockTText) ? static_cast<const TextBlock*>(this)->real_f_rbearing() : 0;
}
TextBlock::TextBlock(const style::font &font, const QString &str, QFixed minResizeWidth, uint16 from, uint16 length, uchar flags, const style::color &color, uint16 lnkIndex) : ITextBlock(font, str, from, length, flags, color, lnkIndex) {
_flags |= ((TextBlockTText & 0x0F) << 8);
if (length) {

View File

@ -75,6 +75,9 @@ public:
return _rpadding;
}
// Should be virtual, but optimized throught type() call.
QFixed f_rbearing() const;
uint16 lnkIndex() const {
return (_flags >> 12) & 0xFFFF;
}
@ -132,27 +135,41 @@ private:
friend class TextPainter;
};
struct TextWord {
TextWord() {
class TextWord {
public:
TextWord() = default;
TextWord(uint16 from, QFixed width, QFixed rbearing, QFixed rpadding = 0)
: _from(from)
, _rbearing(rbearing.value() > 0x7FFF ? 0x7FFF : (rbearing.value() < -0x7FFF ? -0x7FFF : rbearing.value()))
, _width(width)
, _rpadding(rpadding) {
}
TextWord(uint16 from, QFixed width, QFixed rbearing, QFixed rpadding = 0) : from(from),
_rbearing(rbearing.value() > 0x7FFF ? 0x7FFF : (rbearing.value() < -0x7FFF ? -0x7FFF : rbearing.value())), width(width), rpadding(rpadding) {
uint16 from() const {
return _from;
}
QFixed f_rbearing() const {
return QFixed::fromFixed(_rbearing);
}
uint16 from;
int16 _rbearing;
QFixed width, rpadding;
QFixed f_width() const {
return _width;
}
QFixed f_rpadding() const {
return _rpadding;
}
void add_rpadding(QFixed padding) {
_rpadding += padding;
}
private:
uint16 _from = 0;
QFixed _width, _rpadding;
int16 _rbearing = 0;
};
class TextBlock : public ITextBlock {
public:
QFixed f_rbearing() const {
return _words.isEmpty() ? 0 : _words.back().f_rbearing();
}
ITextBlock *clone() const {
return new TextBlock(*this);
}
@ -161,6 +178,11 @@ private:
TextBlock(const style::font &font, const QString &str, QFixed minResizeWidth, uint16 from, uint16 length, uchar flags, const style::color &color, uint16 lnkIndex);
friend class ITextBlock;
QFixed real_f_rbearing() const {
return _words.isEmpty() ? 0 : _words.back().f_rbearing();
}
typedef QVector<TextWord> TextWords;
TextWords _words;

View File

@ -75,7 +75,7 @@
<PrecompiledHeaderOutputFile>$(IntDir)$(TargetName).pch</PrecompiledHeaderOutputFile>
<RuntimeLibrary>MultiThreadedDebug</RuntimeLibrary>
<Optimization>Disabled</Optimization>
<AdditionalOptions>/Zm152 %(AdditionalOptions)</AdditionalOptions>
<AdditionalOptions>/Zm152 /Zo </AdditionalOptions>
<WarningLevel>Level3</WarningLevel>
<TreatWarningAsError>true</TreatWarningAsError>
</ClCompile>
@ -107,7 +107,7 @@
<InlineFunctionExpansion>AnySuitable</InlineFunctionExpansion>
<IntrinsicFunctions>true</IntrinsicFunctions>
<FavorSizeOrSpeed>Speed</FavorSizeOrSpeed>
<AdditionalOptions>/Zm110 %(AdditionalOptions)</AdditionalOptions>
<AdditionalOptions>/Zm152 /Zo </AdditionalOptions>
<WarningLevel>Level3</WarningLevel>
<TreatWarningAsError>true</TreatWarningAsError>
</ClCompile>
@ -140,7 +140,7 @@
<InlineFunctionExpansion>AnySuitable</InlineFunctionExpansion>
<IntrinsicFunctions>true</IntrinsicFunctions>
<FavorSizeOrSpeed>Speed</FavorSizeOrSpeed>
<AdditionalOptions>/Zm110 %(AdditionalOptions)</AdditionalOptions>
<AdditionalOptions>/Zm152 /Zo </AdditionalOptions>
<WarningLevel>Level3</WarningLevel>
<TreatWarningAsError>true</TreatWarningAsError>
</ClCompile>

View File

@ -2023,7 +2023,7 @@
SDKROOT = macosx;
SYMROOT = ./../Mac;
TDESKTOP_MAJOR_VERSION = 0.9;
TDESKTOP_VERSION = 0.9.46;
TDESKTOP_VERSION = 0.9.47;
};
name = Release;
};
@ -2164,7 +2164,7 @@
SDKROOT = macosx;
SYMROOT = ./../Mac;
TDESKTOP_MAJOR_VERSION = 0.9;
TDESKTOP_VERSION = 0.9.46;
TDESKTOP_VERSION = 0.9.47;
};
name = Debug;
};

View File

@ -1,6 +1,6 @@
AppVersion 9046
AppVersion 9047
AppVersionStrMajor 0.9
AppVersionStrSmall 0.9.46
AppVersionStr 0.9.46
AppVersionStrSmall 0.9.47
AppVersionStr 0.9.47
AlphaChannel 1
BetaVersion 0