summaryrefslogtreecommitdiffstats
path: root/tqtinterface/qt4/src/kernel/tqtextengine.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'tqtinterface/qt4/src/kernel/tqtextengine.cpp')
-rw-r--r--tqtinterface/qt4/src/kernel/tqtextengine.cpp1186
1 files changed, 0 insertions, 1186 deletions
diff --git a/tqtinterface/qt4/src/kernel/tqtextengine.cpp b/tqtinterface/qt4/src/kernel/tqtextengine.cpp
deleted file mode 100644
index becf604..0000000
--- a/tqtinterface/qt4/src/kernel/tqtextengine.cpp
+++ /dev/null
@@ -1,1186 +0,0 @@
-/****************************************************************************
-**
-** Text engine classes
-**
-** Copyright (C) 2005-2008 Trolltech ASA. All rights reserved.
-**
-** This file is part of the kernel module of the TQt GUI Toolkit.
-**
-** This file may be used under the terms of the GNU General
-** Public License versions 2.0 or 3.0 as published by the Free
-** Software Foundation and appearing in the files LICENSE.GPL2
-** and LICENSE.GPL3 included in the packaging of this file.
-** Alternatively you may (at your option) use any later version
-** of the GNU General Public License if such license has been
-** publicly approved by Trolltech ASA (or its successors, if any)
-** and the KDE Free TQt Foundation.
-**
-** Please review the following information to ensure GNU General
-** Public Licensing requirements will be met:
-** http://trolltech.com/products/qt/licenses/licensing/opensource/.
-** If you are unsure which license is appropriate for your use, please
-** review the following information:
-** http://trolltech.com/products/qt/licenses/licensing/licensingoverview
-** or contact the sales department at sales@trolltech.com.
-**
-** This file may be used under the terms of the Q Public License as
-** defined by Trolltech ASA and appearing in the file LICENSE.TQPL
-** included in the packaging of this file. Licensees holding valid TQt
-** Commercial licenses may use this file in accordance with the TQt
-** Commercial License Agreement provided with the Software.
-**
-** This file is provided "AS IS" with NO WARRANTY OF ANY KIND,
-** INCLUDING THE WARRANTIES OF DESIGN, MERCHANTABILITY AND FITNESS FOR
-** A PARTICULAR PURPOSE. Trolltech reserves all rights not granted
-** herein.
-**
-**********************************************************************/
-
-#include "tqtextengine_p.h"
-
-#include "tqscriptengine_p.h"
-#include <tqfont.h>
-#include "tqfontdata_p.h"
-#include "tqfontengine_p.h"
-#include <tqstring.h>
-#include <private/tqunicodetables_p.h>
-#include <stdlib.h>
-
-#ifdef USE_QT4
-
-#else // USE_QT4
-
-// -----------------------------------------------------------------------------------------------------
-//
-// The BiDi algorithm
-//
-// -----------------------------------------------------------------------------------------------------
-
-
-#define BIDI_DEBUG 0//2
-#if (BIDI_DEBUG >= 1)
-#include <iostream>
-using namespace std;
-
-static const char *directions[] = {
- "DirL", "DirR", "DirEN", "DirES", "DirET", "DirAN", "DirCS", "DirB", "DirS", "DirWS", "DirON",
- "DirLRE", "DirLRO", "DirAL", "DirRLE", "DirRLO", "DirPDF", "DirNSM", "DirBN"
-};
-
-#endif
-
-struct BiditqStatus {
- BiditqStatus() {
- eor = TQChar::DirON;
- lastStrong = TQChar::DirON;
- last = TQChar:: DirON;
- dir = TQChar::DirON;
- }
- TQChar::Direction eor;
- TQChar::Direction lastStrong;
- TQChar::Direction last;
- TQChar::Direction dir;
-};
-
-struct BidiControl {
- struct Context {
- unsigned char level : 6;
- unsigned char override : 1;
- unsigned char unused : 1;
- };
-
- inline BidiControl( bool rtl )
- : cCtx( 0 ), singleLine( FALSE ) {
- ctx[0].level = (rtl ? 1 : 0);
- ctx[0].override = FALSE;
- }
-
- inline void embed( int level, bool override = FALSE ) {
- if ( ctx[cCtx].level < 61 && cCtx < 61 ) {
- (void) ++cCtx;
- ctx[cCtx].level = level;
- ctx[cCtx].override = override;
- }
- }
- inline void pdf() {
- if ( cCtx ) (void) --cCtx;
- }
-
- inline uchar level() const {
- return ctx[cCtx].level;
- }
- inline bool override() const {
- return ctx[cCtx].override;
- }
- inline TQChar::Direction basicDirection() {
- return (ctx[0].level ? TQChar::DirR : TQChar:: DirL );
- }
- inline uchar baseLevel() {
- return ctx[0].level;
- }
- inline TQChar::Direction direction() {
- return ((ctx[cCtx].level%2) ? TQChar::DirR : TQChar:: DirL );
- }
-
- Context ctx[63];
- unsigned int cCtx : 8;
- bool singleLine : 8;
-};
-
-static TQChar::Direction basicDirection( const TQString &str )
-{
- int len = str.length();
- int pos = 0;
- const TQChar *uc = str.tqunicode() + pos;
- while( pos < len ) {
- switch( direction( *uc ) )
- {
- case TQChar::DirL:
- case TQChar::DirLRO:
- case TQChar::DirLRE:
- return TQChar::DirL;
- case TQChar::DirR:
- case TQChar::DirAL:
- case TQChar::DirRLO:
- case TQChar::DirRLE:
- return TQChar::DirR;
- default:
- break;
- }
- ++pos;
- ++uc;
- }
- return TQChar::DirL;
-}
-
-
-static void tqAppendItems(TQTextEngine *engine, int &start, int &stop, BidiControl &control, TQChar::Direction dir )
-{
- TQScriptItemArray &items = engine->items;
- const TQChar *text = engine->string.tqunicode();
-
- if ( start > stop ) {
- // #### the algorithm is currently not really safe against this. Still needs fixing.
-// qWarning( "Bidi: appendItems() internal error" );
- return;
- }
-
- int level = control.level();
-
- if(dir != TQChar::DirON && !control.override()) {
- // add level of run (cases I1 & I2)
- if( level % 2 ) {
- if(dir == TQChar::DirL || dir == TQChar::DirAN || dir == TQChar::DirEN )
- level++;
- } else {
- if( dir == TQChar::DirR )
- level++;
- else if( dir == TQChar::DirAN || dir == TQChar::DirEN )
- level += 2;
- }
- }
-
-#if (BIDI_DEBUG >= 1)
- qDebug("new run: dir=%s from %d, to %d level = %d\n", directions[dir], start, stop, level);
-#endif
- TQFont::Script script = TQFont::NoScript;
- TQScriptItem item;
- item.position = start;
- item.analysis.script = script;
- item.analysis.bidiLevel = level;
- item.analysis.override = control.override();
- item.analysis.reserved = 0;
-
- if ( control.singleLine ) {
- for ( int i = start; i <= stop; i++ ) {
-
- unsigned short uc = text[i].tqunicode();
- TQFont::Script s = (TQFont::Script)scriptForChar( uc );
- if (s == TQFont::UnknownScript || s == TQFont::CombiningMarks)
- s = script;
-
- if (s != script) {
- item.analysis.script = s;
- item.analysis.bidiLevel = level;
- item.position = i;
- items.append( item );
- script = s;
- }
- }
- } else {
- for ( int i = start; i <= stop; i++ ) {
-
- unsigned short uc = text[i].tqunicode();
- TQFont::Script s = (TQFont::Script)scriptForChar( uc );
- if (s == TQFont::UnknownScript || s == TQFont::CombiningMarks)
- s = script;
-
- TQChar::Category category = ::category( uc );
- if ( uc == 0xfffcU || uc == 0x2028U ) {
- item.analysis.bidiLevel = level % 2 ? level-1 : level;
- item.analysis.script = TQFont::Latin;
- item.isObject = TRUE;
- s = TQFont::NoScript;
- } else if ((uc >= 9 && uc <=13) ||
- (category >= TQChar::Separator_Space && category <= TQChar::Separator_Paragraph)) {
- item.analysis.script = TQFont::Latin;
- item.isSpace = TRUE;
- item.isTab = ( uc == '\t' );
- item.analysis.bidiLevel = item.isTab ? control.baseLevel() : level;
- s = TQFont::NoScript;
- } else if ( s != script && (category != TQChar::Mark_NonSpacing || script == TQFont::NoScript)) {
- item.analysis.script = s;
- item.analysis.bidiLevel = level;
- } else {
- if (i - start < 32000)
- continue;
- start = i;
- }
-
- item.position = i;
- items.append( item );
- script = s;
- item.isSpace = item.isTab = item.isObject = FALSE;
- }
- }
- ++stop;
- 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 )
-{
- BidiControl control( rightToLeft );
- if ( mode & TQTextEngine::SingleLine )
- control.singleLine = TRUE;
-
- int sor = 0;
- int eor = -1;
-
- // ### should get rid of this!
- bool first = TRUE;
-
- int length = engine->string.length();
-
- if ( !length )
- return;
-
- const TQChar *tqunicode = engine->string.tqunicode();
- int current = 0;
-
- TQChar::Direction dir = rightToLeft ? TQChar::DirR : TQChar::DirL;
- BiditqStatus status;
- TQChar::Direction sdir = direction( *tqunicode );
- if ( sdir != TQChar::DirL && sdir != TQChar::DirR && sdir != TQChar::DirAL && sdir != TQChar::DirEN && sdir != TQChar::DirAN )
- sdir = TQChar::DirON;
- else
- dir = TQChar::DirON;
- status.eor = sdir;
- status.lastStrong = rightToLeft ? TQChar::DirR : TQChar::DirL;
- status.last = status.lastStrong;
- status.dir = sdir;
-#if (BIDI_DEBUG >= 2)
- qDebug("---- bidiReorder --- '%s'", engine->string.utf8().data());
- qDebug("rightToLeft = %d", rightToLeft);
-#endif
-
-
- while ( current <= length ) {
-
- TQChar::Direction dirCurrent;
- if ( current == (int)length )
- dirCurrent = control.basicDirection();
- else
- dirCurrent = direction( tqunicode[current] );
-
-#if (BIDI_DEBUG >= 2)
- cout << "pos=" << current << " dir=" << directions[dir]
- << " current=" << directions[dirCurrent] << " last=" << directions[status.last]
- << " eor=" << eor << "/" << directions[status.eor]
- << " sor=" << sor << " lastStrong="
- << directions[status.lastStrong]
- << " level=" << (int)control.level() << endl;
-#endif
-
- switch(dirCurrent) {
-
- // embedding and overrides (X1-X9 in the BiDi specs)
- case TQChar::DirRLE:
- case TQChar::DirRLO:
- case TQChar::DirLRE:
- case TQChar::DirLRO:
- {
- bool rtl = (dirCurrent == TQChar::DirRLE || dirCurrent == TQChar::DirRLO );
- bool override = (dirCurrent == TQChar::DirLRO || dirCurrent == TQChar::DirRLO );
-
- uchar level = control.level();
- if( (level%2 != 0) == rtl )
- level += 2;
- else
- level++;
- if(level < 61) {
- eor = current-1;
- appendItems(engine, sor, eor, control, dir);
- eor = current;
- control.embed( level, override );
- TQChar::Direction edir = (rtl ? TQChar::DirR : TQChar::DirL );
- dir = status.eor = edir;
- status.lastStrong = edir;
- }
- break;
- }
- case TQChar::DirPDF:
- {
- if (dir != control.direction()) {
- eor = current-1;
- appendItems(engine, sor, eor, control, dir);
- dir = control.direction();
- }
- eor = current;
- appendItems(engine, sor, eor, control, dir);
- dir = TQChar::DirON; status.eor = TQChar::DirON;
- status.last = control.direction();
- control.pdf();
- if ( control.override() )
- dir = control.direction();
- else
- dir = TQChar::DirON;
- status.lastStrong = control.direction();
- break;
- }
-
- // strong types
- case TQChar::DirL:
- if(dir == TQChar::DirON)
- dir = TQChar::DirL;
- switch(status.last)
- {
- case TQChar::DirL:
- eor = current; status.eor = TQChar::DirL; break;
- case TQChar::DirR:
- case TQChar::DirAL:
- case TQChar::DirEN:
- case TQChar::DirAN:
- if ( !first ) {
- appendItems(engine, sor, eor, control, dir);
- dir = eor < length ? direction( tqunicode[eor] ) : control.basicDirection();
- status.eor = dir;
- } else {
- eor = current; status.eor = dir;
- }
- break;
- case TQChar::DirES:
- case TQChar::DirET:
- case TQChar::DirCS:
- case TQChar::DirBN:
- case TQChar::DirB:
- case TQChar::DirS:
- case TQChar::DirWS:
- case TQChar::DirON:
- if(dir != TQChar::DirL) {
- //last stuff takes embedding dir
- if( control.direction() == TQChar::DirR ) {
- if(status.eor != TQChar::DirR) {
- // AN or EN
- appendItems(engine, sor, eor, control, dir);
- status.eor = TQChar::DirON;
- dir = TQChar::DirR;
- }
- eor = current - 1;
- appendItems(engine, sor, eor, control, dir);
- dir = eor < length ? direction( tqunicode[eor] ) : control.basicDirection();
- status.eor = dir;
- } else {
- if(status.eor != TQChar::DirL) {
- appendItems(engine, sor, eor, control, dir);
- status.eor = TQChar::DirON;
- dir = TQChar::DirL;
- } else {
- eor = current; status.eor = TQChar::DirL; break;
- }
- }
- } else {
- eor = current; status.eor = TQChar::DirL;
- }
- default:
- break;
- }
- status.lastStrong = TQChar::DirL;
- break;
- case TQChar::DirAL:
- case TQChar::DirR:
- if(dir == TQChar::DirON) dir = TQChar::DirR;
- switch(status.last)
- {
- case TQChar::DirL:
- case TQChar::DirEN:
- case TQChar::DirAN:
- if ( !first ) {
- appendItems(engine, sor, eor, control, dir);
- dir = TQChar::DirON; status.eor = TQChar::DirON;
- break;
- }
- case TQChar::DirR:
- case TQChar::DirAL:
- eor = current; status.eor = TQChar::DirR; break;
- case TQChar::DirES:
- case TQChar::DirET:
- case TQChar::DirCS:
- case TQChar::DirBN:
- case TQChar::DirB:
- case TQChar::DirS:
- case TQChar::DirWS:
- case TQChar::DirON:
- if( status.eor != TQChar::DirR && status.eor != TQChar::DirAL ) {
- //last stuff takes embedding dir
- if(control.direction() == TQChar::DirR
- || status.lastStrong == TQChar::DirR || status.lastStrong == TQChar::DirAL) {
- appendItems(engine, sor, eor, control, dir);
- dir = TQChar::DirON; status.eor = TQChar::DirON;
- dir = TQChar::DirR;
- eor = current;
- } else {
- eor = current - 1;
- appendItems(engine, sor, eor, control, dir);
- dir = TQChar::DirON; status.eor = TQChar::DirON;
- dir = TQChar::DirR;
- }
- } else {
- eor = current; status.eor = TQChar::DirR;
- }
- default:
- break;
- }
- status.lastStrong = dirCurrent;
- break;
-
- // weak types:
-
- case TQChar::DirNSM:
- if (eor == current-1)
- eor = current;
- break;
- case TQChar::DirEN:
- // if last strong was AL change EN to AN
- if(status.lastStrong != TQChar::DirAL) {
- if(dir == TQChar::DirON) {
- if(status.lastStrong == TQChar::DirL)
- dir = TQChar::DirL;
- else
- dir = TQChar::DirEN;
- }
- switch(status.last)
- {
- case TQChar::DirET:
- if ( status.lastStrong == TQChar::DirR || status.lastStrong == TQChar::DirAL ) {
- appendItems(engine, sor, eor, control, dir);
- status.eor = TQChar::DirON;
- dir = TQChar::DirAN;
- }
- // fall through
- case TQChar::DirEN:
- case TQChar::DirL:
- eor = current;
- status.eor = dirCurrent;
- break;
- case TQChar::DirR:
- case TQChar::DirAL:
- case TQChar::DirAN:
- if ( !first )
- appendItems(engine, sor, eor, control, dir);
- status.eor = TQChar::DirEN;
- dir = TQChar::DirAN; break;
- case TQChar::DirES:
- case TQChar::DirCS:
- if(status.eor == TQChar::DirEN || dir == TQChar::DirAN) {
- eor = current; break;
- }
- case TQChar::DirBN:
- case TQChar::DirB:
- case TQChar::DirS:
- case TQChar::DirWS:
- case TQChar::DirON:
- if(status.eor == TQChar::DirR) {
- // neutrals go to R
- eor = current - 1;
- appendItems(engine, sor, eor, control, dir);
- dir = TQChar::DirON; status.eor = TQChar::DirEN;
- dir = TQChar::DirAN;
- }
- else if( status.eor == TQChar::DirL ||
- (status.eor == TQChar::DirEN && status.lastStrong == TQChar::DirL)) {
- eor = current; status.eor = dirCurrent;
- } else {
- // numbers on both sides, neutrals get right to left direction
- if(dir != TQChar::DirL) {
- appendItems(engine, sor, eor, control, dir);
- dir = TQChar::DirON; status.eor = TQChar::DirON;
- eor = current - 1;
- dir = TQChar::DirR;
- appendItems(engine, sor, eor, control, dir);
- dir = TQChar::DirON; status.eor = TQChar::DirON;
- dir = TQChar::DirAN;
- } else {
- eor = current; status.eor = dirCurrent;
- }
- }
- default:
- break;
- }
- break;
- }
- case TQChar::DirAN:
- dirCurrent = TQChar::DirAN;
- if(dir == TQChar::DirON) dir = TQChar::DirAN;
- switch(status.last)
- {
- case TQChar::DirL:
- case TQChar::DirAN:
- eor = current; status.eor = TQChar::DirAN; break;
- case TQChar::DirR:
- case TQChar::DirAL:
- case TQChar::DirEN:
- if ( !first )
- appendItems(engine, sor, eor, control, dir);
- dir = TQChar::DirON; status.eor = TQChar::DirAN;
- break;
- case TQChar::DirCS:
- if(status.eor == TQChar::DirAN) {
- eor = current; break;
- }
- case TQChar::DirES:
- case TQChar::DirET:
- case TQChar::DirBN:
- case TQChar::DirB:
- case TQChar::DirS:
- case TQChar::DirWS:
- case TQChar::DirON:
- if(status.eor == TQChar::DirR) {
- // neutrals go to R
- eor = current - 1;
- appendItems(engine, sor, eor, control, dir);
- status.eor = TQChar::DirAN;
- dir = TQChar::DirAN;
- } else if( status.eor == TQChar::DirL ||
- (status.eor == TQChar::DirEN && status.lastStrong == TQChar::DirL)) {
- eor = current; status.eor = dirCurrent;
- } else {
- // numbers on both sides, neutrals get right to left direction
- if(dir != TQChar::DirL) {
- appendItems(engine, sor, eor, control, dir);
- status.eor = TQChar::DirON;
- eor = current - 1;
- dir = TQChar::DirR;
- appendItems(engine, sor, eor, control, dir);
- status.eor = TQChar::DirAN;
- dir = TQChar::DirAN;
- } else {
- eor = current; status.eor = dirCurrent;
- }
- }
- default:
- break;
- }
- break;
- case TQChar::DirES:
- case TQChar::DirCS:
- break;
- case TQChar::DirET:
- if(status.last == TQChar::DirEN) {
- dirCurrent = TQChar::DirEN;
- eor = current; status.eor = dirCurrent;
- }
- break;
-
- // boundary neutrals should be ignored
- case TQChar::DirBN:
- break;
- // neutrals
- case TQChar::DirB:
- // ### what do we do with newline and paragraph separators that come to here?
- break;
- case TQChar::DirS:
- // ### implement rule L1
- break;
- case TQChar::DirWS:
- case TQChar::DirON:
- break;
- default:
- break;
- }
-
- //cout << " after: dir=" << // dir << " current=" << dirCurrent << " last=" << status.last << " eor=" << status.eor << " lastStrong=" << status.lastStrong << " embedding=" << control.direction() << endl;
-
- if(current >= (int)length) break;
-
- // set status.last as needed.
- switch(dirCurrent) {
- case TQChar::DirET:
- case TQChar::DirES:
- case TQChar::DirCS:
- case TQChar::DirS:
- case TQChar::DirWS:
- case TQChar::DirON:
- switch(status.last)
- {
- case TQChar::DirL:
- case TQChar::DirR:
- case TQChar::DirAL:
- case TQChar::DirEN:
- case TQChar::DirAN:
- status.last = dirCurrent;
- break;
- default:
- status.last = TQChar::DirON;
- }
- break;
- case TQChar::DirNSM:
- case TQChar::DirBN:
- // ignore these
- break;
- case TQChar::DirLRO:
- case TQChar::DirLRE:
- status.last = TQChar::DirL;
- break;
- case TQChar::DirRLO:
- case TQChar::DirRLE:
- status.last = TQChar::DirR;
- break;
- case TQChar::DirEN:
- if ( status.last == TQChar::DirL ) {
- status.last = TQChar::DirL;
- break;
- }
- // fall through
- default:
- status.last = dirCurrent;
- }
-
- first = FALSE;
- ++current;
- }
-
-#if (BIDI_DEBUG >= 1)
- cout << "reached end of line current=" << current << ", eor=" << eor << endl;
-#endif
- eor = current - 1; // remove dummy char
-
- if ( sor <= eor )
- appendItems(engine, sor, eor, control, dir);
-
-
-}
-
-void TQTextEngine::bidiReorder( int numItems, const TQ_UINT8 *levels, int *visualOrder )
-{
-
- // first find highest and lowest levels
- uchar levelLow = 128;
- uchar levelHigh = 0;
- int i = 0;
- while ( i < numItems ) {
- //printf("level = %d\n", r->level);
- if ( levels[i] > levelHigh )
- levelHigh = levels[i];
- if ( levels[i] < levelLow )
- levelLow = levels[i];
- i++;
- }
-
- // implements reordering of the line (L2 according to BiDi spec):
- // L2. From the highest level found in the text to the lowest odd level on each line,
- // reverse any contiguous sequence of characters that are at that level or higher.
-
- // reversing is only done up to the lowest odd level
- if(!(levelLow%2)) levelLow++;
-
-#if (BIDI_DEBUG >= 1)
- cout << "reorderLine: lineLow = " << (uint)levelLow << ", lineHigh = " << (uint)levelHigh << endl;
-#endif
-
- int count = numItems - 1;
- for ( i = 0; i < numItems; i++ )
- visualOrder[i] = i;
-
- while(levelHigh >= levelLow) {
- int i = 0;
- while ( i < count ) {
- while(i < count && levels[i] < levelHigh) i++;
- int start = i;
- while(i <= count && levels[i] >= levelHigh) i++;
- int end = i-1;
-
- if(start != end) {
- //cout << "reversing from " << start << " to " << end << endl;
- for(int j = 0; j < (end-start+1)/2; j++) {
- int tmp = visualOrder[start+j];
- visualOrder[start+j] = visualOrder[end-j];
- visualOrder[end-j] = tmp;
- }
- }
- i++;
- }
- levelHigh--;
- }
-
-#if (BIDI_DEBUG >= 1)
- cout << "visual order is:" << endl;
- for ( i = 0; i < numItems; i++ )
- cout << visualOrder[i] << endl;
-#endif
-}
-
-
-// -----------------------------------------------------------------------------------------------------
-//
-// The line break algorithm. See http://www.tqunicode.org/reports/tr14/tr14-13.html
-//
-// -----------------------------------------------------------------------------------------------------
-
-/* The Unicode algorithm does in our opinion allow line breaks at some
- places they shouldn't be allowed. The following changes were thus
- made in comparison to the Unicode reference:
-
- CL->AL from Dbk to Ibk
- CL->PR from Dbk to Ibk
- EX->AL from Dbk to Ibk
- IS->AL from Dbk to Ibk
- PO->AL from Dbk to Ibk
- SY->AL from Dbk to Ibk
- SY->PO from Dbk to Ibk
- SY->PR from Dbk to Ibk
- SY->OP from Dbk to Ibk
- Al->OP from Dbk to Ibk
- AL->HY from Dbk to Ibk
- AL->PR from Dbk to Ibk
- AL->PO from Dbk to Ibk
- PR->PR from Dbk to Ibk
- PO->PO from Dbk to Ibk
- PR->PO from Dbk to Ibk
- PO->PR from Dbk to Ibk
- HY->PO from Dbk to Ibk
- HY->PR from Dbk to Ibk
- HY->OP from Dbk to Ibk
- PO->OP from Dbk to Ibk
- NU->EX from Dbk to Ibk
- NU->PR from Dbk to Ibk
- PO->NU from Dbk to Ibk
- EX->PO from Dbk to Ibk
-*/
-
-enum break_action {
- Dbk, // Direct break
- Ibk, // Indirect break; only allowed if space between the two chars
- Pbk // Prohibited break; no break allowed even if space between chars
-};
-
-// The following line break classes are not treated by the table:
-// SA, BK, CR, LF, SG, CB, SP
-static const TQ_UINT8 breakTable[TQUnicodeTables::LineBreak_CM+1][TQUnicodeTables::LineBreak_CM+1] =
-{
- // OP, CL, QU, GL, NS, EX, SY, IS, PR, PO, NU, AL, ID, IN, HY, BA, BB, B2, ZW, CM
- { Pbk, Pbk, Pbk, Pbk, Pbk, Pbk, Pbk, Pbk, Pbk, Pbk, Pbk, Pbk, Pbk, Pbk, Pbk, Pbk, Pbk, Pbk, Pbk, Pbk }, // OP
- { Dbk, Pbk, Ibk, Pbk, Pbk, Pbk, Pbk, Pbk, Ibk, Ibk, Dbk, Ibk, Dbk, Dbk, Ibk, Ibk, Pbk, Pbk, Pbk, Pbk }, // CL
- { Pbk, Pbk, Ibk, Pbk, Ibk, Pbk, Pbk, Pbk, Ibk, Ibk, Ibk, Ibk, Ibk, Ibk, Ibk, Ibk, Ibk, Ibk, Pbk, Pbk }, // QU
- { Ibk, Pbk, Ibk, Pbk, Ibk, Pbk, Pbk, Pbk, Ibk, Ibk, Ibk, Ibk, Ibk, Ibk, Ibk, Ibk, Ibk, Ibk, Pbk, Pbk }, // GL
- { Dbk, Pbk, Ibk, Pbk, Ibk, Pbk, Pbk, Pbk, Dbk, Dbk, Dbk, Dbk, Dbk, Dbk, Ibk, Ibk, Dbk, Dbk, Pbk, Ibk }, // NS
- { Dbk, Pbk, Ibk, Pbk, Ibk, Pbk, Pbk, Pbk, Dbk, Ibk, Ibk, Ibk, Dbk, Dbk, Ibk, Ibk, Dbk, Dbk, Pbk, Ibk }, // EX
- { Ibk, Pbk, Ibk, Pbk, Ibk, Pbk, Pbk, Pbk, Ibk, Ibk, Ibk, Ibk, Dbk, Dbk, Ibk, Ibk, Dbk, Dbk, Pbk, Ibk }, // SY
- { Dbk, Pbk, Ibk, Pbk, Ibk, Pbk, Pbk, Pbk, Dbk, Dbk, Ibk, Ibk, Dbk, Dbk, Ibk, Ibk, Dbk, Dbk, Pbk, Ibk }, // IS
- { Ibk, Pbk, Ibk, Pbk, Ibk, Pbk, Pbk, Pbk, Ibk, Ibk, Ibk, Ibk, Ibk, Dbk, Ibk, Ibk, Dbk, Dbk, Pbk, Pbk }, // PR
- { Ibk, Pbk, Ibk, Pbk, Ibk, Pbk, Pbk, Pbk, Ibk, Ibk, Ibk, Ibk, Dbk, Dbk, Ibk, Ibk, Dbk, Dbk, Pbk, Ibk }, // PO
- { Dbk, Pbk, Ibk, Pbk, Ibk, Pbk, Pbk, Pbk, Ibk, Ibk, Ibk, Ibk, Dbk, Ibk, Ibk, Ibk, Dbk, Dbk, Pbk, Pbk }, // NU
- { Ibk, Pbk, Ibk, Pbk, Ibk, Pbk, Pbk, Pbk, Ibk, Ibk, Ibk, Ibk, Dbk, Ibk, Ibk, Ibk, Dbk, Dbk, Pbk, Pbk }, // AL
- { Dbk, Pbk, Ibk, Pbk, Ibk, Pbk, Pbk, Pbk, Dbk, Ibk, Dbk, Dbk, Dbk, Ibk, Ibk, Ibk, Dbk, Dbk, Pbk, Ibk }, // ID
- { Dbk, Pbk, Ibk, Pbk, Ibk, Pbk, Pbk, Pbk, Dbk, Dbk, Dbk, Dbk, Dbk, Ibk, Ibk, Ibk, Dbk, Dbk, Pbk, Ibk }, // IN
- { Ibk, Pbk, Ibk, Pbk, Ibk, Pbk, Pbk, Pbk, Ibk, Ibk, Ibk, Ibk, Dbk, Dbk, Ibk, Ibk, Dbk, Dbk, Pbk, Ibk }, // HY
- { Dbk, Pbk, Ibk, Pbk, Ibk, Pbk, Pbk, Pbk, Dbk, Dbk, Dbk, Dbk, Dbk, Dbk, Ibk, Ibk, Dbk, Dbk, Pbk, Ibk }, // BA
- { Ibk, Pbk, Ibk, Pbk, Ibk, Pbk, Pbk, Pbk, Ibk, Ibk, Ibk, Ibk, Ibk, Ibk, Ibk, Ibk, Ibk, Ibk, Pbk, Ibk }, // BB
- { Dbk, Pbk, Ibk, Pbk, Ibk, Pbk, Pbk, Pbk, Dbk, Dbk, Dbk, Dbk, Dbk, Dbk, Ibk, Ibk, Dbk, Pbk, Pbk, Ibk }, // B2
- { Dbk, Dbk, Dbk, Dbk, Dbk, Dbk, Dbk, Dbk, Dbk, Dbk, Dbk, Dbk, Dbk, Dbk, Dbk, Dbk, Dbk, Dbk, Pbk, Ibk }, // ZW
- { Dbk, Pbk, Ibk, Pbk, Ibk, Pbk, Pbk, Pbk, Dbk, Ibk, Dbk, Dbk, Dbk, Ibk, Ibk, Ibk, Dbk, Dbk, Pbk, Pbk } // CM
-};
-
-// set the soft break flag at every possible line breaking point. This needs correct clustering information.
-static void calcLineBreaks(const TQString &str, TQCharAttributes *charAttributes)
-{
- int len = str.length();
- if (!len)
- return;
-
- const TQChar *uc = str.tqunicode();
- int cls = lineBreakClass(*uc);
- if (cls >= TQUnicodeTables::LineBreak_CM)
- cls = TQUnicodeTables::LineBreak_ID;
-
- charAttributes[0].softBreak = FALSE;
- charAttributes[0].whiteSpace = (cls == TQUnicodeTables::LineBreak_SP);
- charAttributes[0].charStop = TRUE;
-
- for (int i = 1; i < len; ++i) {
- int ncls = ::lineBreakClass(uc[i]);
- int category = ::category(uc[i]);
- if (category == TQChar::Mark_NonSpacing)
- goto nsm;
-
- if (category == TQChar::Other_Surrogate) {
- // char stop only on first pair
- if (uc[i].tqunicode() >= 0xd800 && uc[i].tqunicode() < 0xdc00 && i < len-1
- && uc[i+1].tqunicode() >= 0xdc00 && uc[i+1].tqunicode() < 0xe000)
- goto nsm;
- // ### correctly handle second surrogate
- }
-
- if (ncls == TQUnicodeTables::LineBreak_SP) {
- charAttributes[i].softBreak = FALSE;
- charAttributes[i].whiteSpace = TRUE;
- charAttributes[i].charStop = TRUE;
- cls = ncls;
- continue;
- }
-
-
- if (cls == TQUnicodeTables::LineBreak_SA && ncls == TQUnicodeTables::LineBreak_SA) {
- // two complex chars (thai or lao), thai_attributes might override, but here
- // we do a best guess
- charAttributes[i].softBreak = TRUE;
- charAttributes[i].whiteSpace = FALSE;
- charAttributes[i].charStop = TRUE;
- cls = ncls;
- continue;
- }
- {
- int tcls = ncls;
- if (tcls >= TQUnicodeTables::LineBreak_SA)
- tcls = TQUnicodeTables::LineBreak_ID;
- if (cls >= TQUnicodeTables::LineBreak_SA)
- cls = TQUnicodeTables::LineBreak_ID;
-
- bool softBreak;
- int brk = breakTable[cls][tcls];
- if (brk == Ibk)
- softBreak = (cls == TQUnicodeTables::LineBreak_SP);
- else
- softBreak = (brk == Dbk);
-// qDebug("char = %c %04x, cls=%d, ncls=%d, brk=%d soft=%d", uc[i].cell(), uc[i].tqunicode(), cls, ncls, brk, charAttributes[i].softBreak);
- charAttributes[i].softBreak = softBreak;
- charAttributes[i].whiteSpace = FALSE;
- charAttributes[i].charStop = TRUE;
- cls = ncls;
- }
- continue;
- nsm:
- charAttributes[i].softBreak = FALSE;
- charAttributes[i].whiteSpace = FALSE;
- charAttributes[i].charStop = FALSE;
- }
-}
-
-#if defined( TQ_WS_X11 ) || defined ( TQ_WS_TQWS )
-# include "tqtextengine_unix.cpp"
-#elif defined( TQ_WS_WIN )
-# include "tqtextengine_win.cpp"
-#elif defined( TQ_WS_MAC )
-# include "tqtextengine_mac.cpp"
-#endif
-
-
-
-TQTextEngine::TQTextEngine( const TQString &str, TQFontPrivate *f )
- : string( str ), fnt( f ), direction( TQChar::DirON ), haveCharAttributes( FALSE ), widthOnly( FALSE )
-{
-#ifdef TQ_WS_WIN
- if ( !resolvedUsp10 )
- resolveUsp10();
-#endif
- if ( fnt ) fnt->ref();
-
- num_glyphs = TQMAX( 16, str.length()*3/2 );
- int space_charAttributes = (sizeof(TQCharAttributes)*str.length()+sizeof(void*)-1)/sizeof(void*);
- int space_logClusters = (sizeof(unsigned short)*str.length()+sizeof(void*)-1)/sizeof(void*);
- int space_glyphs = (sizeof(glyph_t)*num_glyphs+sizeof(void*)-1)/sizeof(void*);
- int space_advances = (sizeof(advance_t)*num_glyphs+sizeof(void*)-1)/sizeof(void*);
- int space_offsets = (sizeof(qoffset_t)*num_glyphs+sizeof(void*)-1)/sizeof(void*);
- int space_glyphAttributes = (sizeof(GlyphAttributes)*num_glyphs+sizeof(void*)-1)/sizeof(void*);
-
- allocated = space_charAttributes + space_glyphs + space_advances +
- space_offsets + space_logClusters + space_glyphAttributes;
- memory = (void **)::malloc( allocated*sizeof( void * ) );
- memset( memory, 0, allocated*sizeof( void * ) );
-
- void **m = memory;
- m += space_charAttributes;
- logClustersPtr = (unsigned short *) m;
- m += space_logClusters;
- glyphPtr = (glyph_t *) m;
- m += space_glyphs;
- advancePtr = (advance_t *) m;
- m += space_advances;
- offsetsPtr = (qoffset_t *) m;
- m += space_offsets;
- glyphAttributesPtr = (GlyphAttributes *) m;
-
- used = 0;
-}
-
-TQTextEngine::~TQTextEngine()
-{
- if ( fnt && fnt->deref())
- delete fnt;
- free( memory );
- allocated = 0;
-}
-
-void TQTextEngine::reallocate( int totalGlyphs )
-{
- int new_num_glyphs = totalGlyphs;
- int space_charAttributes = (sizeof(TQCharAttributes)*string.length()+sizeof(void*)-1)/sizeof(void*);
- int space_logClusters = (sizeof(unsigned short)*string.length()+sizeof(void*)-1)/sizeof(void*);
- int space_glyphs = (sizeof(glyph_t)*new_num_glyphs+sizeof(void*)-1)/sizeof(void*);
- int space_advances = (sizeof(advance_t)*new_num_glyphs+sizeof(void*)-1)/sizeof(void*);
- int space_offsets = (sizeof(qoffset_t)*new_num_glyphs+sizeof(void*)-1)/sizeof(void*);
- int space_glyphAttributes = (sizeof(GlyphAttributes)*new_num_glyphs+sizeof(void*)-1)/sizeof(void*);
-
- int newAllocated = space_charAttributes + space_glyphs + space_advances +
- space_offsets + space_logClusters + space_glyphAttributes;
- void ** newMemory = (void **)::malloc( newAllocated*sizeof( void * ) );
-
- void **nm = newMemory;
- memcpy( nm, memory, string.length()*sizeof(TQCharAttributes) );
- nm += space_charAttributes;
- memcpy( nm, logClustersPtr, num_glyphs*sizeof(unsigned short) );
- logClustersPtr = (unsigned short *) nm;
- nm += space_logClusters;
- memcpy( nm, glyphPtr, num_glyphs*sizeof(glyph_t) );
- glyphPtr = (glyph_t *) nm;
- nm += space_glyphs;
- memcpy( nm, advancePtr, num_glyphs*sizeof(advance_t) );
- advancePtr = (advance_t *) nm;
- nm += space_advances;
- memcpy( nm, offsetsPtr, num_glyphs*sizeof(qoffset_t) );
- offsetsPtr = (qoffset_t *) nm;
- nm += space_offsets;
- memcpy( nm, glyphAttributesPtr, num_glyphs*sizeof(GlyphAttributes) );
- glyphAttributesPtr = (GlyphAttributes *) nm;
-
- free( memory );
- memory = newMemory;
- allocated = newAllocated;
- num_glyphs = new_num_glyphs;
-}
-
-const TQCharAttributes *TQTextEngine::attributes()
-{
- TQCharAttributes *charAttributes = (TQCharAttributes *) memory;
- if ( haveCharAttributes )
- return charAttributes;
-
- if ( !items.d )
- itemize();
-
- ensureSpace(string.length());
- charAttributes = (TQCharAttributes *) memory;
- calcLineBreaks(string, charAttributes);
-
- for ( int i = 0; i < items.size(); i++ ) {
- TQScriptItem &si = items[i];
-#ifdef TQ_WS_WIN
- int script = uspScriptForItem(this, i);
-#else
- int script = si.analysis.script;
-#endif
- TQ_ASSERT( script < TQFont::NScripts );
- AttributeFunction attributes = scriptEngines[script].charAttributes;
- if (!attributes)
- continue;
- int from = si.position;
- int len = length( i );
- attributes( script, string, from, len, charAttributes );
- }
-
- haveCharAttributes = TRUE;
- return charAttributes;
-}
-
-void TQTextEngine::splitItem( int item, int pos )
-{
- if ( pos <= 0 )
- return;
-
- // we have to ensure we get correct shaping for arabic and other
- // complex languages so we have to call tqshape _before_ we split the item.
- tqshape(item);
-
- if ( items.d->size == items.d->alloc )
- items.resize( items.d->size + 1 );
-
- int numMove = items.d->size - item-1;
- if ( numMove > 0 )
- memmove( items.d->items + item+2, items.d->items +item+1, numMove*sizeof( TQScriptItem ) );
- items.d->size++;
- TQScriptItem &newItem = items.d->items[item+1];
- TQScriptItem &oldItem = items.d->items[item];
- newItem = oldItem;
- items.d->items[item+1].position += pos;
- if ( newItem.fontEngine )
- newItem.fontEngine->ref();
-
- if (oldItem.num_glyphs) {
- // already tqshaped, break glyphs aswell
- int breakGlyph = logClusters(&oldItem)[pos];
-
- newItem.num_glyphs = oldItem.num_glyphs - breakGlyph;
- oldItem.num_glyphs = breakGlyph;
- newItem.glyph_data_offset = oldItem.glyph_data_offset + breakGlyph;
-
- for (int i = 0; i < newItem.num_glyphs; i++)
- logClusters(&newItem)[i] -= breakGlyph;
-
- int w = 0;
- const advance_t *a = advances(&oldItem);
- for(int j = 0; j < breakGlyph; ++j)
- w += *(a++);
-
- newItem.width = oldItem.width - w;
- oldItem.width = w;
- }
-
-// qDebug("split at position %d itempos=%d", pos, item );
-}
-
-
-int TQTextEngine::width( int from, int len ) const
-{
- int w = 0;
-
-// qDebug("TQTextEngine::width( from = %d, len = %d ), numItems=%d, strleng=%d", from, len, items.size(), string.length() );
- for ( int i = 0; i < items.size(); i++ ) {
- TQScriptItem *si = &items[i];
- int pos = si->position;
- int ilen = length( i );
-// qDebug("item %d: from %d len %d", i, pos, ilen );
- if ( pos >= from + len )
- break;
- if ( pos + ilen > from ) {
- if ( !si->num_glyphs )
- tqshape( i );
-
- advance_t *advances = this->advances( si );
- unsigned short *logClusters = this->logClusters( si );
-
-// fprintf( stderr, " logclusters:" );
-// for ( int k = 0; k < ilen; k++ )
-// fprintf( stderr, " %d", logClusters[k] );
-// fprintf( stderr, "\n" );
- // do the simple thing for now and give the first glyph in a cluster the full width, all other ones 0.
- int charFrom = from - pos;
- if ( charFrom < 0 )
- charFrom = 0;
- int glyphStart = logClusters[charFrom];
- if ( charFrom > 0 && logClusters[charFrom-1] == glyphStart )
- while ( charFrom < ilen && logClusters[charFrom] == glyphStart )
- charFrom++;
- if ( charFrom < ilen ) {
- glyphStart = logClusters[charFrom];
- int charEnd = from + len - 1 - pos;
- if ( charEnd >= ilen )
- charEnd = ilen-1;
- int glyphEnd = logClusters[charEnd];
- while ( charEnd < ilen && logClusters[charEnd] == glyphEnd )
- charEnd++;
- glyphEnd = (charEnd == ilen) ? si->num_glyphs : logClusters[charEnd];
-
-// qDebug("char: start=%d end=%d / glyph: start = %d, end = %d", charFrom, charEnd, glyphStart, glyphEnd );
- for ( int i = glyphStart; i < glyphEnd; i++ )
- w += advances[i];
- }
- }
- }
-// qDebug(" --> w= %d ", w );
- return w;
-}
-
-void TQTextEngine::itemize( int mode )
-{
- if ( !items.d ) {
- int size = 8;
- items.d = (TQScriptItemArrayPrivate *)malloc( sizeof( TQScriptItemArrayPrivate ) +
- sizeof( TQScriptItem ) * size );
- items.d->alloc = size;
- }
- items.d->size = 0;
- if ( string.length() == 0 )
- return;
-
- if ( !(mode & NoBidi) ) {
- if ( direction == TQChar::DirON )
- direction = basicDirection( string );
- bidiItemize( this, direction == TQChar::DirR, mode );
- } else {
- BidiControl control( FALSE );
- if ( mode & TQTextEngine::SingleLine )
- control.singleLine = TRUE;
- int start = 0;
- int stop = string.length() - 1;
- appendItems(this, start, stop, control, TQChar::DirL);
- }
- if ( (mode & WidthOnly) == WidthOnly )
- widthOnly = TRUE;
-}
-
-glyph_metrics_t TQTextEngine::boundingBox( int from, int len ) const
-{
- glyph_metrics_t gm;
-
- for ( int i = 0; i < items.size(); i++ ) {
- TQScriptItem *si = &items[i];
- int pos = si->position;
- int ilen = length( i );
- if ( pos > from + len )
- break;
- if ( pos + len > from ) {
- if ( !si->num_glyphs )
- tqshape( i );
- advance_t *advances = this->advances( si );
- unsigned short *logClusters = this->logClusters( si );
- glyph_t *glyphs = this->glyphs( si );
- qoffset_t *offsets = this->offsets( si );
-
- // do the simple thing for now and give the first glyph in a cluster the full width, all other ones 0.
- int charFrom = from - pos;
- if ( charFrom < 0 )
- charFrom = 0;
- int glyphStart = logClusters[charFrom];
- if ( charFrom > 0 && logClusters[charFrom-1] == glyphStart )
- while ( charFrom < ilen && logClusters[charFrom] == glyphStart )
- charFrom++;
- if ( charFrom < ilen ) {
- glyphStart = logClusters[charFrom];
- int charEnd = from + len - 1 - pos;
- if ( charEnd >= ilen )
- charEnd = ilen-1;
- int glyphEnd = logClusters[charEnd];
- while ( charEnd < ilen && logClusters[charEnd] == glyphEnd )
- charEnd++;
- glyphEnd = (charEnd == ilen) ? si->num_glyphs : logClusters[charEnd];
- if ( glyphStart <= glyphEnd ) {
- TQFontEngine *fe = si->fontEngine;
- glyph_metrics_t m = fe->boundingBox( glyphs+glyphStart, advances+glyphStart,
- offsets+glyphStart, glyphEnd-glyphStart );
- gm.x = TQMIN( gm.x, m.x + gm.xoff );
- gm.y = TQMIN( gm.y, m.y + gm.yoff );
- gm.width = TQMAX( gm.width, m.width+gm.xoff );
- gm.height = TQMAX( gm.height, m.height+gm.yoff );
- gm.xoff += m.xoff;
- gm.yoff += m.yoff;
- }
- }
- }
- }
- return gm;
-}
-
-#endif // USE_QT4 \ No newline at end of file