diff options
author | Michele Calgaro <michele.calgaro@yahoo.it> | 2024-06-08 12:56:43 +0900 |
---|---|---|
committer | Michele Calgaro <michele.calgaro@yahoo.it> | 2024-06-08 12:56:43 +0900 |
commit | 0cf411b09cf5d8970b873a338a69eae98d5ce5d8 (patch) | |
tree | 107cf55759cc3138bb1e0035b479bcd92127403a /src/kernel/qtextengine.cpp | |
parent | e6077c30d14e9d662e8843c554db86c0d366d0b6 (diff) | |
download | tqt3-0cf411b09cf5d8970b873a338a69eae98d5ce5d8.tar.gz tqt3-0cf411b09cf5d8970b873a338a69eae98d5ce5d8.zip |
Rename text nt* related files to equivalent tq*
Signed-off-by: Michele Calgaro <michele.calgaro@yahoo.it>
Diffstat (limited to 'src/kernel/qtextengine.cpp')
-rw-r--r-- | src/kernel/qtextengine.cpp | 1180 |
1 files changed, 0 insertions, 1180 deletions
diff --git a/src/kernel/qtextengine.cpp b/src/kernel/qtextengine.cpp deleted file mode 100644 index e1a806f52..000000000 --- a/src/kernel/qtextengine.cpp +++ /dev/null @@ -1,1180 +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 "qtextengine_p.h" - -#include "qscriptengine_p.h" -#include <ntqfont.h> -#include "qfontdata_p.h" -#include "qfontengine_p.h" -#include <tqstring.h> -#include <private/qunicodetables_p.h> -#include <stdlib.h> - -// ----------------------------------------------------------------------------------------------------- -// -// 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 BidiStatus { - BidiStatus() { - 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.unicode() + 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.unicode(); - - if ( start > stop ) { - // #### the algorithm is currently not really safe against this. Still needs fixing. -// tqWarning( "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) - tqDebug("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].unicode(); - 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].unicode(); - 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 *unicode = engine->string.unicode(); - int current = 0; - - TQChar::Direction dir = rightToLeft ? TQChar::DirR : TQChar::DirL; - BidiStatus status; - TQChar::Direction sdir = direction( *unicode ); - 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) - tqDebug("---- bidiReorder --- '%s'", engine->string.utf8().data()); - tqDebug("rightToLeft = %d", rightToLeft); -#endif - - - while ( current <= length ) { - - TQChar::Direction dirCurrent; - if ( current == (int)length ) - dirCurrent = control.basicDirection(); - else - dirCurrent = direction( unicode[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( unicode[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( unicode[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.unicode.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.unicode(); - 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].unicode() >= 0xd800 && uc[i].unicode() < 0xdc00 && i < len-1 - && uc[i+1].unicode() >= 0xdc00 && uc[i+1].unicode() < 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); -// tqDebug("char = %c %04x, cls=%d, ncls=%d, brk=%d soft=%d", uc[i].cell(), uc[i].unicode(), 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_QWS ) -# include "qtextengine_unix.cpp" -#elif defined( TQ_WS_WIN ) -# include "qtextengine_win.cpp" -#elif defined( TQ_WS_MAC ) -# include "qtextengine_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 - Q_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 shape _before_ we split the item. - shape(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 shaped, 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; - } - -// tqDebug("split at position %d itempos=%d", pos, item ); -} - - -int TQTextEngine::width( int from, int len ) const -{ - int w = 0; - -// tqDebug("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 ); -// tqDebug("item %d: from %d len %d", i, pos, ilen ); - if ( pos >= from + len ) - break; - if ( pos + ilen > from ) { - if ( !si->num_glyphs ) - shape( 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]; - -// tqDebug("char: start=%d end=%d / glyph: start = %d, end = %d", charFrom, charEnd, glyphStart, glyphEnd ); - for ( int i = glyphStart; i < glyphEnd; i++ ) - w += advances[i]; - } - } - } -// tqDebug(" --> 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 ) - shape( 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; -} |