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;
 }