summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMichele Calgaro <michele.calgaro@yahoo.it>2025-01-12 13:09:40 +0900
committerMichele Calgaro <michele.calgaro@yahoo.it>2025-01-12 23:34:08 +0900
commitb559abe7220b3d86edc427bcbf7db26f9f6f62d6 (patch)
tree83c6a8a483f629d23d12d93f210379f5c51281f4
parent1c9111b3795a3b87254cbac172dcc565c7f76a57 (diff)
downloadtqt-b559abe7220b3d86edc427bcbf7db26f9f6f62d6.tar.gz
tqt-b559abe7220b3d86edc427bcbf7db26f9f6f62d6.zip
Add support for Unicode surrogate characters and planes above zero.
If the selected font supports the required characters, the text will be displayed correctly. If the selected font does not support such characters, empty boxes will be displayed in place of the expected text. Part of the code changes comes from Qt4 code. Signed-off-by: Michele Calgaro <michele.calgaro@yahoo.it> (cherry picked from commit e0a38072cf48a6819a5cd788588267f3441d9d6a)
-rw-r--r--src/kernel/qfontengine_p.h12
-rw-r--r--src/kernel/qfontengine_x11.cpp83
-rw-r--r--src/kernel/qpainter.cpp8
-rw-r--r--src/kernel/qscriptengine.cpp8
-rw-r--r--src/kernel/qtextengine.cpp7
-rw-r--r--src/kernel/qtextengine_p.h60
-rw-r--r--src/kernel/qtextengine_unix.cpp5
7 files changed, 72 insertions, 111 deletions
diff --git a/src/kernel/qfontengine_p.h b/src/kernel/qfontengine_p.h
index e1fc58545..82f6d850d 100644
--- a/src/kernel/qfontengine_p.h
+++ b/src/kernel/qfontengine_p.h
@@ -48,16 +48,18 @@
#include "qtextengine_p.h"
-class TQPaintDevice;
+typedef unsigned int glyph_t;
+typedef int advance_t;
struct glyph_metrics_t;
-class TQChar;
-typedef unsigned short glyph_t;
struct qoffset_t;
-typedef int advance_t;
-class TQOpenType;
struct TransformedFont;
+class TQChar;
+class TQOpenType;
+class TQPaintDevice;
+
+
#if defined( TQ_WS_X11 ) || defined( TQ_WS_WIN) || defined( TQ_WS_MAC )
class TQFontEngine : public TQShared
{
diff --git a/src/kernel/qfontengine_x11.cpp b/src/kernel/qfontengine_x11.cpp
index 47ddb9367..539b14aed 100644
--- a/src/kernel/qfontengine_x11.cpp
+++ b/src/kernel/qfontengine_x11.cpp
@@ -488,7 +488,15 @@ TQFontEngine::Error TQFontEngineXLFD::stringToCMap( const TQChar *str, int len,
chars[i] = (str[i].unicode() == 0xa0 ? 0x20 :
(mirrored ? ::mirroredChar(str[i]).unicode() : str[i].unicode()));
}
- _codec->fromUnicodeInternal( chars, glyphs, len );
+ // XLFD does not support unicode characters above 0xFFFF, so casting to ushort
+ // does not cause real loss
+ ushort *us_glyphs = new ushort[len];
+ _codec->fromUnicodeInternal( chars, us_glyphs, len );
+ for ( int i = 0; i < len; ++i ) {
+ glyphs[i] = us_glyphs[i];
+ }
+ delete[] us_glyphs;
+
if (chars != str)
free( chars );
} else {
@@ -1523,6 +1531,18 @@ static glyph_t getAdobeCharIndex(XftFont *font, int cmap, uint ucs4)
return g;
}
+static uint getChar(const TQChar *str, int &i, const int len)
+{
+ uint uc = str[i].unicode();
+ if (uc >= 0xd800 && uc < 0xdc00 && i < len-1) {
+ uint low = str[++i].unicode();
+ if (low >= 0xdc00 && low < 0xe000) {
+ uc = (uc - 0xd800)*0x400 + (low - 0xdc00) + 0x10000;
+ }
+ }
+ return uc;
+}
+
TQFontEngine::Error TQFontEngineXft::stringToCMap( const TQChar *str, int len, glyph_t *glyphs, advance_t *advances, int *nglyphs, bool mirrored ) const
{
if ( *nglyphs < len ) {
@@ -1530,52 +1550,35 @@ TQFontEngine::Error TQFontEngineXft::stringToCMap( const TQChar *str, int len, g
return OutOfMemory;
}
- if (_cmap != -1) {
- for ( int i = 0; i < len; ++i ) {
- unsigned short uc = str[i].unicode();
- if (mirrored)
- uc = ::mirroredChar(str[i]).unicode();
- glyphs[i] = uc < cmapCacheSize ? cmapCache[uc] : 0;
- if ( !glyphs[i] ) {
- glyph_t glyph = XftCharIndex(0, _font, uc);
- if (!glyph)
- glyph = getAdobeCharIndex(_font, _cmap, uc);
- glyphs[i] = glyph;
- if ( uc < cmapCacheSize )
- ((TQFontEngineXft *)this)->cmapCache[uc] = glyph;
+ int glyph_pos = 0;
+ for ( int i = 0; i < len; ++i ) {
+ uint uc = getChar(str, i, len);
+ if ( uc == 0xa0 )
+ uc = 0x20;
+ if ( mirrored )
+ uc = ::mirroredChar(uc).unicode();
+ glyphs[glyph_pos] = uc < cmapCacheSize ? cmapCache[uc] : 0;
+ if ( !glyphs[glyph_pos] ) {
+ glyph_t glyph = 0;
+ if (XftCharExists(0, _font, uc)) {
+ glyph = XftCharIndex(0, _font, uc);
}
- }
- } else if ( mirrored ) {
- for ( int i = 0; i < len; ++i ) {
- unsigned short uc = ::mirroredChar(str[i]).unicode();
- glyphs[i] = uc < cmapCacheSize ? cmapCache[uc] : 0;
- if ( !glyphs[i] ) {
- if (uc == 0xa0)
- uc = 0x20;
- glyph_t glyph = XftCharIndex(0, _font, uc);
- glyphs[i] = glyph;
- if ( uc < cmapCacheSize )
- ((TQFontEngineXft *)this)->cmapCache[uc] = glyph;
+ if ( !glyph && _cmap != -1 ) {
+ glyph = getAdobeCharIndex(_font, _cmap, uc);
}
- }
- } else {
- for ( int i = 0; i < len; ++i ) {
- unsigned short uc = str[i].unicode();
- glyphs[i] = uc < cmapCacheSize ? cmapCache[uc] : 0;
- if ( !glyphs[i] ) {
- if (uc == 0xa0)
- uc = 0x20;
- glyph_t glyph = XftCharIndex(0, _font, uc);
- glyphs[i] = glyph;
- if ( uc < cmapCacheSize )
+ if ( glyph ) {
+ glyphs[glyph_pos] = glyph;
+ if ( uc < cmapCacheSize ) {
((TQFontEngineXft *)this)->cmapCache[uc] = glyph;
+ }
}
}
+ ++glyph_pos;
}
if ( advances ) {
- for ( int i = 0; i < len; i++ ) {
- FT_UInt glyph = *(glyphs + i);
+ for ( int i = 0; i < glyph_pos; i++ ) {
+ glyph_t glyph = *(glyphs + i);
advances[i] = (glyph < widthCacheSize) ? widthCache[glyph] : 0;
if ( !advances[i] ) {
XGlyphInfo gi;
@@ -1591,7 +1594,7 @@ TQFontEngine::Error TQFontEngineXft::stringToCMap( const TQChar *str, int len, g
}
}
- *nglyphs = len;
+ *nglyphs = glyph_pos;
return NoError;
}
diff --git a/src/kernel/qpainter.cpp b/src/kernel/qpainter.cpp
index 4868ffb00..23894b09f 100644
--- a/src/kernel/qpainter.cpp
+++ b/src/kernel/qpainter.cpp
@@ -2941,12 +2941,12 @@ void qt_format_text( const TQFont& font, const TQRect &_r,
int desc = fm.descent();
height = -leading;
- //tqDebug("\n\nbeginLayout: lw = %d, rectwidth=%d", lineWidth , r.width());
+ //tqDebug("beginLayout: lw = %d, rectwidth=%d", lineWidth , r.width());
while ( !textLayout.atEnd() ) {
height += leading;
- textLayout.beginLine( lineWidth == INT_MAX ? lineWidth : lineWidth );
+ textLayout.beginLine( lineWidth );
//tqDebug("-----beginLine( %d )-----", lineWidth );
- bool linesep = FALSE;
+ bool linesep = false;
while ( 1 ) {
TQTextItem ti = textLayout.currentItem();
//tqDebug("item: from=%d, ch=%x", ti.from(), text.unicode()[ti.from()].unicode() );
@@ -2971,7 +2971,7 @@ void qt_format_text( const TQFont& font, const TQRect &_r,
ti.setWidth( tw );
}
if ( ti.isObject() && text.unicode()[ti.from()] == TQChar_linesep )
- linesep = TRUE;
+ linesep = true;
if ( linesep || textLayout.addCurrentItem() != TQTextLayout::Ok || textLayout.atEnd() )
break;
diff --git a/src/kernel/qscriptengine.cpp b/src/kernel/qscriptengine.cpp
index 19ca36e97..cc454d72f 100644
--- a/src/kernel/qscriptengine.cpp
+++ b/src/kernel/qscriptengine.cpp
@@ -279,15 +279,13 @@ void qt_heuristicPosition(TQShaperItem *item)
-// set the glyph attributes heuristically. Assumes a 1 to 1 relationship between chars and glyphs
-// and no reordering.
-// also computes logClusters heuristically
+// Set the glyph attributes heuristically. Assumes no reordering.
+// Also computes logClusters heuristically
static void heuristicSetGlyphAttributes(TQShaperItem *item, const TQChar *uc, int length)
{
// justification is missing here!!!!!
- if ( item->num_glyphs != length )
- tqWarning("TQScriptEngine::heuristicSetGlyphAttributes: char length and num glyphs disagree" );
+ Q_ASSERT(item->num_glyphs <= length);
unsigned short *logClusters = item->log_clusters;
diff --git a/src/kernel/qtextengine.cpp b/src/kernel/qtextengine.cpp
index 48839b5c8..f527cd86a 100644
--- a/src/kernel/qtextengine.cpp
+++ b/src/kernel/qtextengine.cpp
@@ -150,7 +150,7 @@ static TQChar::Direction basicDirection( const TQString &str )
}
-static void tqAppendItems(TQTextEngine *engine, int &start, int &stop, BidiControl &control, TQChar::Direction dir )
+static void appendItems(TQTextEngine *engine, int &start, int &stop, BidiControl &control, TQChar::Direction dir )
{
TQScriptItemArray &items = engine->items;
const TQChar *text = engine->string.unicode();
@@ -243,9 +243,6 @@ static void tqAppendItems(TQTextEngine *engine, int &start, int &stop, BidiContr
start = stop;
}
-typedef void (* fAppendItems)(TQTextEngine *, int &start, int &stop, BidiControl &control, TQChar::Direction dir);
-static fAppendItems appendItems = tqAppendItems;
-
// creates the next TQScript items.
static void bidiItemize( TQTextEngine *engine, bool rightToLeft, int mode )
{
@@ -666,8 +663,6 @@ static void bidiItemize( TQTextEngine *engine, bool rightToLeft, int mode )
if ( sor <= eor )
appendItems(engine, sor, eor, control, dir);
-
-
}
void TQTextEngine::bidiReorder( int numItems, const TQ_UINT8 *levels, int *visualOrder )
diff --git a/src/kernel/qtextengine_p.h b/src/kernel/qtextengine_p.h
index 751cdf043..6b1b6fbaf 100644
--- a/src/kernel/qtextengine_p.h
+++ b/src/kernel/qtextengine_p.h
@@ -86,57 +86,28 @@ struct glyph_metrics_t
int yoff;
};
-#if defined( TQ_WS_X11 ) || defined ( TQ_WS_QWS )
-typedef unsigned short glyph_t;
-
-struct qoffset_t {
- short x;
- short y;
-};
-
+typedef unsigned int glyph_t;
typedef int advance_t;
-struct TQScriptAnalysis
-{
- unsigned short script : 7;
- unsigned short bidiLevel : 6; // Unicode Bidi algorithm embedding level (0-61)
- unsigned short override : 1; // Set when in LRO/RLO embedding
- unsigned short reserved : 2;
- bool operator == ( const TQScriptAnalysis &other ) {
- return
- script == other.script &&
- bidiLevel == other.bidiLevel;
- // ###
-// && override == other.override;
- }
+#if defined( TQ_WS_X11 ) || defined ( TQ_WS_QWS ) || defined( TQ_WS_MAC )
-};
-
-#elif defined( TQ_WS_MAC )
-
-typedef unsigned short glyph_t;
-
-struct qoffset_t {
+struct qoffset_t
+{
short x;
short y;
};
-typedef int advance_t;
-
struct TQScriptAnalysis
{
unsigned short script : 7;
unsigned short bidiLevel : 6; // Unicode Bidi algorithm embedding level (0-61)
unsigned short override : 1; // Set when in LRO/RLO embedding
unsigned short reserved : 2;
- bool operator == ( const TQScriptAnalysis &other ) {
- return
- script == other.script &&
- bidiLevel == other.bidiLevel;
- // ###
-// && override == other.override;
- }
+ bool operator== ( const TQScriptAnalysis &other )
+ {
+ return script == other.script && bidiLevel == other.bidiLevel;
+ }
};
#elif defined( TQ_WS_WIN )
@@ -144,15 +115,12 @@ struct TQScriptAnalysis
// do not change the definitions below unless you know what you are doing!
// it is designed to be compatible with the types found in uniscribe.
-typedef unsigned short glyph_t;
-
-struct qoffset_t {
+struct qoffset_t
+{
int x;
int y;
};
-typedef int advance_t;
-
struct TQScriptAnalysis {
unsigned short script :10;
unsigned short rtl :1;
@@ -174,13 +142,9 @@ struct TQScriptAnalysis {
unsigned short engineReserved :2;
};
-inline bool operator == ( const TQScriptAnalysis &sa1, const TQScriptAnalysis &sa2 )
+inline bool operator== ( const TQScriptAnalysis &sa1, const TQScriptAnalysis &sa2 )
{
- return
- sa1.script == sa2.script &&
- sa1.bidiLevel == sa2.bidiLevel;
- // ###
-// && override == other.override;
+ return sa1.script == sa2.script && sa1.bidiLevel == sa2.bidiLevel;
}
#endif
diff --git a/src/kernel/qtextengine_unix.cpp b/src/kernel/qtextengine_unix.cpp
index 0d5e3b920..0de67f04a 100644
--- a/src/kernel/qtextengine_unix.cpp
+++ b/src/kernel/qtextengine_unix.cpp
@@ -80,8 +80,8 @@ void TQTextEngine::shape( int item ) const
si.fontEngine = fnt->engineForScript( script );
si.fontEngine->ref();
- si.ascent = si.fontEngine->ascent();
- si.descent = si.fontEngine->descent();
+ si.ascent = si.fontEngine->ascent();
+ si.descent = si.fontEngine->descent();
si.num_glyphs = 0;
if ( si.fontEngine && si.fontEngine != (TQFontEngine*)-1 ) {
@@ -96,7 +96,6 @@ void TQTextEngine::shape( int item ) const
shaper_item.has_positioning = FALSE;
while (1) {
-// tqDebug(" . num_glyphs=%d, used=%d, item.num_glyphs=%d", num_glyphs, used, shaper_item.num_glyphs);
ensureSpace(shaper_item.num_glyphs);
shaper_item.num_glyphs = num_glyphs - used;
// tqDebug(" .. num_glyphs=%d, used=%d, item.num_glyphs=%d", num_glyphs, used, shaper_item.num_glyphs);