Mercurial > projects > dwt-win
changeset 278:3f53ebb05b5b
Fix: make MARK copy work correctly mit multiple chars.
Fix: getLocation, getOffset (codepoint vs. chars)
Fix: itemize() translation of utf16 to utf8 indices
author | Frank Benoit <benoit@tionex.de> |
---|---|
date | Tue, 05 Aug 2008 01:07:44 +0200 |
parents | f18872e0f232 |
children | e4b7af6b8e7e 4ec36c3a04a3 |
files | dwt/graphics/TextLayout.d |
diffstat | 1 files changed, 59 insertions(+), 24 deletions(-) [+] |
line wrap: on
line diff
--- a/dwt/graphics/TextLayout.d Tue Aug 05 00:54:11 2008 +0200 +++ b/dwt/graphics/TextLayout.d Tue Aug 05 01:07:44 2008 +0200 @@ -33,6 +33,7 @@ import dwt.graphics.TextStyle; import tango.text.convert.Format; +import Utf = tango.text.convert.Utf; import dwt.dwthelper.utils; import dwt.dwthelper.System; @@ -92,7 +93,9 @@ int[] lineOffset, lineY, lineWidth; void* mLangFontLink2; - static const wchar LTR_MARK = '\u200E', RTL_MARK = '\u200F'; + static const dchar LTR_MARK = '\u200E', RTL_MARK = '\u200F'; + static const String STR_LTR_MARK = "\u200E", STR_RTL_MARK = "\u200F"; + static const int MARK_SIZE = 3; static const int SCRIPT_VISATTR_SIZEOF = 2; static const int GOFFSET_SIZEOF = 8; private static byte[16] CLSID_CMultiLanguage; @@ -119,6 +122,7 @@ class StyleItem { TextStyle style; + // DWT: start, lenght relative to segmentsText int start, length; bool lineBreak, softBreak, tab; @@ -1791,7 +1795,8 @@ } else if (run.tab) { width = (trailing || (offset is length)) ? run.width : 0; } else { - int runOffset = offset - run.start; + // DWT: runOffset now in codepoints + int runOffset = segmentsText[ run.start .. $ ].indexToCodepointIndex( offset - run.start ); int cChars = run.length; int gGlyphs = run.glyphCount; int piX; @@ -1839,8 +1844,8 @@ if ((movement & DWT.MOVEMENT_CHAR) !is 0) return offset + step; length = segmentsText.length; offset = translateOffset(offset); - SCRIPT_LOGATTR* logAttr = new SCRIPT_LOGATTR(); - SCRIPT_PROPERTIES* properties = new SCRIPT_PROPERTIES(); + SCRIPT_LOGATTR* logAttr; + SCRIPT_PROPERTIES* properties; int i = forward ? 0 : allRuns.length - 1; offset = validadeOffset(offset, step); do { @@ -1848,12 +1853,12 @@ if (run.start <= offset && offset < run.start + run.length) { if (run.lineBreak && !run.softBreak) return untranslateOffset(run.start); if (run.tab) return untranslateOffset(run.start); - OS.MoveMemory(properties, device.scripts[run.analysis.eScript], SCRIPT_PROPERTIES.sizeof); + properties = device.scripts[run.analysis.eScript]; bool isComplex = properties.fNeedsCaretInfo || properties.fNeedsWordBreaking; if (isComplex) breakRun(run); while (run.start <= offset && offset < run.start + run.length) { if (isComplex) { - OS.MoveMemory(logAttr, run.psla + (offset - run.start), SCRIPT_LOGATTR.sizeof); + logAttr = run.psla + (offset - run.start); } switch (movement) { case DWT.MOVEMENT_CLUSTER: { @@ -1957,6 +1962,7 @@ checkLayout(); computeRuns(null); if (trailing !is null && trailing.length < 1) DWT.error(DWT.ERROR_INVALID_ARGUMENT); + int line; int lineCount = runs.length; for (line=0; line<lineCount; line++) { @@ -2002,7 +2008,10 @@ int* advances = run.justify !is null ? run.justify : run.advances; OS.ScriptXtoCP(xRun, cChars, cGlyphs, run.clusters, run.visAttrs, advances, &run.analysis, &piCP, &piTrailing); if (trailing !is null) trailing[0] = piTrailing; - return untranslateOffset(run.start + piCP); + + // DWT: back from codepoints to utf8 index + int offsetIndex = segmentsText[ run.start .. $ ].codepointIndexToIndex( piCP ); + return untranslateOffset(run.start + offsetIndex); } } if (trailing !is null) trailing[0] = 0; @@ -2104,21 +2113,28 @@ } char[] oldChars = new char[length_]; text.getChars(0, length_, oldChars, 0); - char[] newChars = new char[length_ + nSegments]; + // DWT: MARK is now 3 chars long + String separator = orientation is DWT.RIGHT_TO_LEFT ? STR_RTL_MARK : STR_LTR_MARK; + assert( separator.length is MARK_SIZE ); + char[] newChars = new char[length_ + nSegments*MARK_SIZE]; int charCount = 0, segmentCount = 0; - wchar separator = orientation is DWT.RIGHT_TO_LEFT ? RTL_MARK : LTR_MARK; while (charCount < length_) { if (segmentCount < nSegments && charCount is segments[segmentCount]) { - newChars[charCount + segmentCount++] = separator; + int start = charCount + (segmentCount*MARK_SIZE); + newChars[ start .. start + MARK_SIZE ] = separator; + segmentCount++; } else { - newChars[charCount + segmentCount] = oldChars[charCount++]; + newChars[charCount + (segmentCount*MARK_SIZE)] = oldChars[charCount]; + charCount++; } } if (segmentCount < nSegments) { segments[segmentCount] = charCount; - newChars[charCount + segmentCount++] = separator; + int start = charCount + (segmentCount*MARK_SIZE); + newChars[ start .. start + MARK_SIZE ] = separator; + segmentCount++; } - return newChars[ 0 .. Math.min(charCount + segmentCount, newChars.length)].dup; + return newChars[ 0 .. Math.min(charCount + (segmentCount*MARK_SIZE), newChars.length)].dup; } /** @@ -2252,6 +2268,7 @@ * Itemize the receiver text */ StyleItem[] itemize () { + // DWT: itemize is the process of finding changes in direction segmentsText = getSegmentsText(); int length = segmentsText.length; SCRIPT_CONTROL scriptControl; @@ -2273,17 +2290,35 @@ wchar[] chars = StrToWCHARs( segmentsText ); OS.ScriptItemize(chars.ptr, chars.length, MAX_ITEM, &scriptControl, &scriptState, pItems, &pcItems); // if (hr is E_OUTOFMEMORY) //TODO handle it + // DWT pcItems is not inclusive the trailing item // Translate the utf16 indices to utf8 indices int utf8idx = 0; + int utf16idx = 0; + int i = 0; SCRIPT_ITEM* si = pItems; - foreach( uint utf16idx, char c; chars ){ + while( utf16idx < chars.length ){ + if( si.iCharPos is utf16idx ){ si.iCharPos = utf8idx; + i++; si++; } - utf8idx++; + + // goto next codepoint + uint ate16; + dchar[1] buf32; + dchar[] res32 = Utf.toString32( chars[ utf16idx .. $ ], buf32, &ate16 ); + uint ate32; + char[4] buf8; + char[] res8 = Utf.toString( res32, buf8, &ate32 ); + utf16idx += ate16; + utf8idx += res8.length; } + assert( si.iCharPos is chars.length ); + si.iCharPos = utf8idx; + assert( si.iCharPos is segmentsText.length ); + assert( i is pcItems ); StyleItem[] runs = merge(pItems, pcItems); OS.HeapFree(hHeap, 0, pItems); @@ -2301,21 +2336,21 @@ } int count = 0, start = 0, end = segmentsText.length, itemIndex = 0, styleIndex = 0; StyleItem[] runs = new StyleItem[itemCount + stylesCount]; - SCRIPT_ITEM* scriptItem = new SCRIPT_ITEM(); + SCRIPT_ITEM* scriptItem; bool linkBefore = false; while (start < end) { StyleItem item = new StyleItem(); item.start = start; item.style = styles[styleIndex].style; runs[count++] = item; - OS.MoveMemory(scriptItem, (cast(void*)items) + itemIndex * SCRIPT_ITEM.sizeof, SCRIPT_ITEM.sizeof); + scriptItem = items + itemIndex; item.analysis = scriptItem.a; if (linkBefore) { item.analysis.fLinkBefore = true; linkBefore = false; } //scriptItem.a = new SCRIPT_ANALYSIS(); - OS.MoveMemory(scriptItem, (cast(void*)items) + (itemIndex + 1) * SCRIPT_ITEM.sizeof, SCRIPT_ITEM.sizeof); + scriptItem = items + (itemIndex + 1); int itemLimit = scriptItem.iCharPos; int styleLimit = translateOffset(styles[styleIndex + 1].start); if (styleLimit <= itemLimit) { @@ -2338,7 +2373,7 @@ } StyleItem item = new StyleItem(); item.start = end; - OS.MoveMemory(scriptItem, (cast(void*)items) + itemCount * SCRIPT_ITEM.sizeof, SCRIPT_ITEM.sizeof); + scriptItem = items + itemCount; item.analysis = scriptItem.a; runs[count++] = item; if (runs.length !is count) { @@ -2833,8 +2868,8 @@ * Generate glyphs for one Run. */ void shape (HDC hdc, StyleItem run) { - final int[] buffer = new int[1]; - final char[] chars = new char[run.length]; + int[1] buffer; + char[] chars = new char[run.length]; segmentsText.getChars(run.start, run.start + run.length, chars, 0); wchar[] wchars = StrToWCHARs( chars ); int maxGlyphs = (wchars.length * 3 / 2) + 16; @@ -2993,7 +3028,7 @@ } int validadeOffset(int offset, int step) { - offset += step; + offset += segmentsText.getRelativeCodePointOffset( offset, step ); if (segments !is null && segments.length > 2) { for (int i = 0; i < segments.length; i++) { if (translateOffset(segments[i]) - 1 is offset) { @@ -3026,7 +3061,7 @@ if (segments[0] is 0 && segments[1] is length) return offset; } for (int i = 0; i < nSegments && offset - i >= segments[i]; i++) { - offset++; + offset+=MARK_SIZE; } return offset; } @@ -3041,7 +3076,7 @@ if (segments[0] is 0 && segments[1] is length) return offset; } for (int i = 0; i < nSegments && offset > segments[i]; i++) { - offset--; + offset-=MARK_SIZE; } return offset; }