Changeset 287:35d730fb5e9f

Show
Ignore:
Timestamp:
08/21/08 03:57:23 (3 months ago)
Author:
Frank Benoit <benoit@tionex.de>
branch:
default
Message:

TextLayout? with wchar[] segments text and translation tables

Files:

Legend:

Unmodified
Added
Removed
Modified
Copied
Moved
  • dwt/dwthelper/utils.d

    r283 r287  
    422422    return res[0]; 
    423423} 
     424dchar firstCodePoint( wchar[] str, out int consumed ){ 
     425    dchar[1] buf; 
     426    uint ate; 
     427    dchar[] res = str.toString32( buf, &ate ); 
     428    consumed = ate; 
     429    if( ate is 0 || res.length is 0 ){ 
     430        Trace.formatln( "dwthelper.utils {}: str.length={} str={:X2}", __LINE__, str.length, cast(ubyte[])str ); 
     431    } 
     432    assert( ate > 0 ); 
     433    assert( res.length is 1 ); 
     434    return res[0]; 
     435} 
    424436 
    425437String dcharToString( dchar key ){ 
     
    441453 
    442454int getRelativeCodePointOffset( String str, int startIndex, int searchRelCp ){ 
     455    return getAbsoluteCodePointOffset( str, startIndex, searchRelCp ) - startIndex; 
     456} 
     457int getAbsoluteCodePointOffset( String str, int startIndex, int searchRelCp ){ 
    443458    int ignore; 
    444459    int i = startIndex; 
     
    484499                i--; 
    485500                if( i < 0 ){ 
    486                     return -1; 
     501                    return startIndex-1; 
    487502                    //Trace.formatln( "dwthelper.utils getRelativeCodePointOffset {}: str={}, startIndex={}, searchRelCp={}", __LINE__, str, startIndex, searchRelCp ); 
    488503                    //tango.text.convert.Utf.onUnicodeError( "invalid utf8 input", i ); 
     
    492507        } 
    493508    } 
    494     return i - startIndex; 
     509    return i; 
     510
     511int getAbsoluteCodePointOffset( wchar[] str, int startIndex, int searchRelCp ){ 
     512    int ignore; 
     513    int i = startIndex; 
     514    if( searchRelCp > 0 ){ 
     515        while( searchRelCp !is 0 ){ 
     516 
     517            if( ( i < str.length ) 
     518                && ( str[i] & 0xD800 ) !is 0xD800 ) 
     519            { 
     520                i+=1; 
     521            } 
     522            else if( ( i+1 < str.length ) 
     523                && (( str[i+1] & 0xDC00 ) is 0xDC00 ) 
     524                && (( str[i  ] & 0xDC00 ) is 0xD800 )) 
     525            { 
     526                i+=2; 
     527            } 
     528            else{ 
     529                Trace.formatln( "invalid utf8 characters:  {:X2}", cast(ubyte[]) str ); 
     530                tango.text.convert.Utf.onUnicodeError( "invalid utf8 input", i ); 
     531            } 
     532            searchRelCp--; 
     533        } 
     534    } 
     535    else if( searchRelCp < 0 ){ 
     536        while( searchRelCp !is 0 ){ 
     537            do{ 
     538                i--; 
     539                if( i < 0 ){ 
     540                    return startIndex-1; 
     541                    //Trace.formatln( "dwthelper.utils getRelativeCodePointOffset {}: str={}, startIndex={}, searchRelCp={}", __LINE__, str, startIndex, searchRelCp ); 
     542                    //tango.text.convert.Utf.onUnicodeError( "invalid utf8 input", i ); 
     543                } 
     544            } while(( str[i] & 0xDC00 ) is 0xDC00 ); 
     545            searchRelCp++; 
     546        } 
     547    } 
     548    return i; 
    495549} 
    496550dchar getRelativeCodePoint( String str, int startIndex, int searchRelCp, out int relIndex ){ 
  • dwt/graphics/TextLayout.d

    r278 r287  
    1212 *******************************************************************************/ 
    1313module dwt.graphics.TextLayout; 
     14 
     15import tango.util.log.Trace; 
    1416 
    1517import dwt.DWT; 
     
    7678 
    7779    Font font; 
    78     String text, segmentsText; 
     80    String  text; 
     81    wchar[] wtext; 
     82    char[]  segmentsText; 
     83    wchar[] segmentsWText; // DWT 
     84    int[]   index8to16; // DWT 
     85    int[]   index16to8; // DWT 
    7986    int lineSpacing; 
    8087    int ascent, descent; 
     
    8592    bool justify; 
    8693    int[] tabs; 
    87     int[] segments; 
     94    int[] segments; // indices in 'text' 
     95    int[] wsegments; // DWT indices in 'wtext' 
    8896    StyleItem[] styles; 
    8997    int stylesCount; 
     
    95103 
    96104    static const dchar LTR_MARK = '\u200E', RTL_MARK = '\u200F'; 
     105    static const wchar LTR_MARKw = '\u200E', RTL_MARKw = '\u200F'; 
    97106    static const String STR_LTR_MARK = "\u200E", STR_RTL_MARK = "\u200F"; 
     107    static const wchar[] WSTR_LTR_MARK = "\u200E"w, WSTR_RTL_MARK = "\u200F"w; 
    98108    static const int MARK_SIZE = 3; 
     109    static const int WMARK_SIZE = 1; 
    99110    static const int SCRIPT_VISATTR_SIZEOF = 2; 
    100111    static const int GOFFSET_SIZEOF = 8; 
     
    232243    stylesCount = 2; 
    233244    text = ""; //$NON-NLS-1$ 
     245    wtext = ""w; 
    234246    void* ppv; 
    235247    OS.OleInitialize(null); 
     
    242254void breakRun(StyleItem run) { 
    243255    if (run.psla !is null) return; 
    244     wchar[] chars = StrToWCHARs( 0, segmentsText[ run.start .. run.start + run.length ] )
     256    wchar[] chars = segmentsWText[ index8to16[ run.start ] .. index8to16[ run.start + run.length ] ]
    245257    auto hHeap = OS.GetProcessHeap(); 
    246258    run.psla = cast(SCRIPT_LOGATTR*)OS.HeapAlloc(hHeap, OS.HEAP_ZERO_MEMORY, SCRIPT_LOGATTR.sizeof * chars.length); 
     
    499511    font = null; 
    500512    text = null; 
     513    wtext = null; 
    501514    segmentsText = null; 
     515    segmentsWText = null; 
    502516    tabs = null; 
    503517    styles = null; 
     
    614628    if (selectionBackground !is null && selectionBackground.isDisposed()) DWT.error(DWT.ERROR_INVALID_ARGUMENT); 
    615629    int length = text.length; 
     630    int wlength = wtext.length; 
    616631    if (length is 0 && flags is 0) return; 
    617632    auto hdc = gc.handle; 
     
    756771            if (drawX + run.width >= clip.x) { 
    757772                if (!run.lineBreak || run.softBreak) { 
    758                     int end = run.start + run.length - 1
     773                    int end = segmentsText.getAbsoluteCodePointOffset( run.start + run.length, -1 )
    759774                    bool fullSelection = hasSelection && selectionStart <= run.start && selectionEnd >= end; 
    760775                    if (fullSelection) { 
     
    787802                            int selStart = Math.max(selectionStart, run.start) - run.start; 
    788803                            int selEnd = Math.min(selectionEnd, end) - run.start; 
    789                             int cChars = run.length; 
     804                            int cChars = index8to16[run.start+run.length] - index8to16[run.start]; // make it wchar 
    790805                            int gGlyphs = run.glyphCount; 
    791806                            int piX; 
    792807                            int* advances = run.justify !is null ? run.justify : run.advances; 
    793                             OS.ScriptCPtoX(selStart, false, cChars, gGlyphs, run.clusters, run.visAttrs, advances, &run.analysis, &piX); 
     808                            OS.ScriptCPtoX(index8to16[selStart], false, cChars, gGlyphs, run.clusters, run.visAttrs, advances, &run.analysis, &piX); 
    794809                            int runX = (orientation & DWT.RIGHT_TO_LEFT) !is 0 ? run.width - piX : piX; 
    795810                            rect.left = drawX + runX; 
    796811                            rect.top = drawY; 
    797                             OS.ScriptCPtoX(selEnd, true, cChars, gGlyphs, run.clusters, run.visAttrs, advances, &run.analysis, &piX); 
     812                            OS.ScriptCPtoX(index8to16[selEnd], true, cChars, gGlyphs, run.clusters, run.visAttrs, advances, &run.analysis, &piX); 
    798813                            runX = (orientation & DWT.RIGHT_TO_LEFT) !is 0 ? run.width - piX : piX; 
    799814                            rect.right = drawX + runX; 
     
    830845                    int drawRunY = drawY + (baseline - run.ascent); 
    831846                    if (partialSelection) { 
    832                         int selStart = Math.max(selectionStart, run.start) - run.start
    833                         int selEnd = Math.min(selectionEnd, end) - run.start
    834                         int cChars = run.length; 
     847                        int selStart = Math.max(index8to16[selectionStart], index8to16[run.start]) - index8to16[run.start]
     848                        int selEnd = Math.min(index8to16[selectionEnd], index8to16[end]) - index8to16[run.start]
     849                        int cChars = index8to16[run.start+run.length] - index8to16[run.start]; // make it wchar 
    835850                        int gGlyphs = run.glyphCount; 
    836851                        int piX; 
     
    13311346    runs = null; 
    13321347    segmentsText = null; 
     1348    segmentsWText = null; 
    13331349} 
    13341350 
     
    14341450            if (run.style !is null && run.style.metrics !is null) { 
    14351451                GlyphMetrics metrics = run.style.metrics; 
    1436                 cx = metrics.width * (start - run.start); 
     1452                cx = metrics.width * (index8to16[start] - index8to16[run.start]); 
    14371453            } else if (!run.tab) { 
    14381454                int piX; 
    14391455                int* advances = run.justify !is null ? run.justify : run.advances; 
    1440                 OS.ScriptCPtoX(start - run.start, false, run.length, run.glyphCount, run.clusters, run.visAttrs, advances, &run.analysis, &piX); 
     1456                int wlength = index8to16[ run.start+run.length] - index8to16[run.start]; 
     1457                OS.ScriptCPtoX(index8to16[start] - index8to16[run.start], false, wlength, run.glyphCount, run.clusters, run.visAttrs, advances, &run.analysis, &piX); 
    14411458                cx = isRTL ? run.width - piX : piX; 
    14421459            } 
     
    14511468            if (run.style !is null && run.style.metrics !is null) { 
    14521469                GlyphMetrics metrics = run.style.metrics; 
    1453                 cx = metrics.width * (end - run.start + 1); 
     1470                cx = metrics.width * (index8to16[end] - index8to16[run.start] + 1); 
    14541471            } else if (!run.tab) { 
    14551472                int piX; 
    14561473                int* advances = run.justify !is null ? run.justify : run.advances; 
    1457                 OS.ScriptCPtoX(end - run.start, true, run.length, run.glyphCount, run.clusters, run.visAttrs, advances, &run.analysis, &piX); 
     1474                int wlength = index8to16[ run.start+run.length] - index8to16[run.start]; 
     1475                OS.ScriptCPtoX(index8to16[end] - index8to16[run.start], true, wlength, run.glyphCount, run.clusters, run.visAttrs, advances, &run.analysis, &piX); 
    14581476                cx = isRTL ? run.width - piX : piX; 
    14591477            } 
     
    17961814                width = (trailing || (offset is length)) ? run.width : 0; 
    17971815            } else { 
    1798                 // DWT: runOffset now in codepoints 
    1799                 int runOffset = segmentsText[ run.start .. $ ].indexToCodepointIndex( offset - run.start ); 
    1800                 int cChars = run.length; 
     1816                int runOffset = index8to16[offset] - index8to16[run.start]; 
     1817                int cChars = index8to16[run.start+run.length] - index8to16[run.start]; // make it wchar 
    18011818                int gGlyphs = run.glyphCount; 
    18021819                int piX; 
     
    18591876            while (run.start <= offset && offset < run.start + run.length) { 
    18601877                if (isComplex) { 
    1861                     logAttr = run.psla + (offset - run.start); 
     1878                    logAttr = run.psla + (index8to16[offset] - index8to16[run.start]); 
    18621879                } 
    18631880                switch (movement) { 
     
    18791896                                bool previousLetterOrDigit = Compatibility.isLetterOrDigit(segmentsText.charAt(offset - 1)); 
    18801897                                if (letterOrDigit !is previousLetterOrDigit || !letterOrDigit) { 
    1881                                     if (!Compatibility.isWhitespace(segmentsText.charAt(offset))) { 
     1898                                    if (!Compatibility.isWhitespace(segmentsText[offset..$].firstCodePoint())) { 
    18821899                                        return untranslateOffset(offset); 
    18831900                                    } 
     
    18901907                        if (offset > 0) { 
    18911908                            bool isLetterOrDigit = Compatibility.isLetterOrDigit(segmentsText.charAt(offset)); 
    1892                             bool previousLetterOrDigit = Compatibility.isLetterOrDigit(segmentsText.charAt(offset - 1)); 
     1909                            bool previousLetterOrDigit = Compatibility.isLetterOrDigit(segmentsText[offset - 1.. $].firstCodePoint()); 
    18931910                            if (!isLetterOrDigit && previousLetterOrDigit) { 
    18941911                                return untranslateOffset(offset); 
     
    19992016                return untranslateOffset(run.start); 
    20002017            } 
    2001             int cChars = run.length; 
     2018            int cChars = index8to16[run.start+run.length] - index8to16[run.start]; // make it wchar 
    20022019            int cGlyphs = run.glyphCount; 
    20032020            int piCP; 
     
    21032120} 
    21042121 
    2105 String getSegmentsText() { 
    2106     if (segments is null) return text; 
     2122void getSegmentsText( out char[] resUtf8, out wchar[] resUtf16 ) { 
     2123 
     2124    void buildIndexTables() { // build the index translation tables. 
     2125        index8to16.length = resUtf8.length + 1; 
     2126        index16to8.length = resUtf16.length + 1; 
     2127 
     2128        int idx8, idx16; 
     2129        while( idx8 < resUtf8.length ){ 
     2130            int ate8, ate16; 
     2131            dchar d8 = resUtf8[ idx8 .. $ ].firstCodePoint( ate8 ); 
     2132            dchar d16 = resUtf16[ idx16 .. $ ].firstCodePoint( ate16 ); 
     2133            assert( d8 is d16 ); 
     2134            index16to8[ idx16 .. idx16 +ate16 ] = idx8; 
     2135            index8to16[ idx8  .. idx8  +ate8  ] = idx16; 
     2136            idx8  += ate8; 
     2137            idx16 += ate16; 
     2138        } 
     2139        index16to8[ resUtf16.length ] = resUtf8.length; 
     2140        index8to16[ resUtf8.length  ] = resUtf16.length; 
     2141    } 
     2142 
     2143    if (segments is null) { 
     2144        resUtf8 = text; 
     2145        resUtf16 = wtext; 
     2146        buildIndexTables(); 
     2147        return; 
     2148    } 
    21072149    int nSegments = segments.length; 
    2108     if (nSegments <= 1) return text; 
     2150    if (nSegments <= 1) { 
     2151        resUtf8 = text; 
     2152        resUtf16 = wtext; 
     2153        buildIndexTables(); 
     2154        return; 
     2155    } 
    21092156    int length_ = text.length; 
    2110     if (length_ is 0) return text; 
     2157    int wlength_ = wtext.length; 
     2158    if (length_ is 0) { 
     2159        resUtf8 = text; 
     2160        resUtf16 = wtext; 
     2161        buildIndexTables(); 
     2162        return; 
     2163    } 
    21112164    if (nSegments is 2) { 
    2112         if (segments[0] is 0 && segments[1] is length_) return text; 
    2113     } 
    2114     char[] oldChars = new char[length_]; 
    2115     text.getChars(0, length_, oldChars, 0); 
    2116     // DWT: MARK is now 3 chars long 
    2117     String separator = orientation is DWT.RIGHT_TO_LEFT ? STR_RTL_MARK : STR_LTR_MARK; 
    2118     assert( separator.length is MARK_SIZE ); 
    2119     char[] newChars = new char[length_ + nSegments*MARK_SIZE]; 
    2120     int charCount = 0, segmentCount = 0; 
    2121     while (charCount < length_) { 
    2122         if (segmentCount < nSegments && charCount is segments[segmentCount]) { 
     2165        if (segments[0] is 0 && segments[1] is length_) { 
     2166            resUtf8 = text; 
     2167            resUtf16 = wtext; 
     2168            buildIndexTables(); 
     2169            return; 
     2170        } 
     2171    } 
     2172    { 
     2173        char[] oldChars = text; 
     2174        // DWT: MARK is now 3 chars long 
     2175        String separator = orientation is DWT.RIGHT_TO_LEFT ? STR_RTL_MARK : STR_LTR_MARK; 
     2176        assert( separator.length is MARK_SIZE ); 
     2177        char[] newChars = new char[length_ + nSegments*MARK_SIZE]; 
     2178 
     2179        int charCount = 0, segmentCount = 0; 
     2180        while (charCount < length_) { 
     2181            if (segmentCount < nSegments && charCount is segments[segmentCount]) { 
     2182                int start = charCount + (segmentCount*MARK_SIZE); 
     2183                newChars[ start .. start + MARK_SIZE ] = separator; 
     2184                segmentCount++; 
     2185            } else { 
     2186                newChars[charCount + (segmentCount*MARK_SIZE)] = oldChars[charCount]; 
     2187                charCount++; 
     2188            } 
     2189        } 
     2190        if (segmentCount < nSegments) { 
     2191            segments[segmentCount] = charCount; 
    21232192            int start = charCount + (segmentCount*MARK_SIZE); 
    21242193            newChars[ start .. start + MARK_SIZE ] = separator; 
    21252194            segmentCount++; 
    2126         } else { 
    2127             newChars[charCount + (segmentCount*MARK_SIZE)] = oldChars[charCount]; 
    2128             charCount++; 
    2129         } 
    2130     } 
    2131     if (segmentCount < nSegments) { 
    2132         segments[segmentCount] = charCount; 
    2133         int start = charCount + (segmentCount*MARK_SIZE); 
    2134         newChars[ start .. start + MARK_SIZE ] = separator; 
    2135         segmentCount++; 
    2136     } 
    2137     return newChars[ 0 .. Math.min(charCount + (segmentCount*MARK_SIZE), newChars.length)].dup; 
     2195        } 
     2196        resUtf8 = newChars[ 0 .. Math.min(charCount + (segmentCount*MARK_SIZE), newChars.length)]; 
     2197    } 
     2198    // now for the wide chars 
     2199    { 
     2200        wchar[] oldWChars = wtext; 
     2201        wchar[] wseparator = orientation is DWT.RIGHT_TO_LEFT ? WSTR_RTL_MARK : WSTR_LTR_MARK; 
     2202        assert( wseparator.length is 1 ); 
     2203        wchar[] newWChars = new wchar[wlength_ + nSegments]; 
     2204 
     2205        int charCount = 0, segmentCount = 0; 
     2206        while (charCount < wlength_) { 
     2207            if (segmentCount < nSegments && charCount is wsegments[segmentCount]) { 
     2208                int start = charCount + (segmentCount*WMARK_SIZE); 
     2209                newWChars[ start .. start + WMARK_SIZE ] = wseparator; 
     2210                segmentCount++; 
     2211            } else { 
     2212                newWChars[charCount + (segmentCount*WMARK_SIZE)] = oldWChars[charCount]; 
     2213                charCount++; 
     2214            } 
     2215        } 
     2216        if (segmentCount < nSegments) { 
     2217            wsegments[segmentCount] = charCount; 
     2218            int start = charCount + (segmentCount*WMARK_SIZE); 
     2219            newWChars[ start .. start + WMARK_SIZE ] = wseparator; 
     2220            segmentCount++; 
     2221        } 
     2222        resUtf16 = newWChars[ 0 .. Math.min(charCount + (segmentCount*WMARK_SIZE), newWChars.length)]; 
     2223    } 
     2224    buildIndexTables(); 
    21382225} 
    21392226 
     
    22702357StyleItem[] itemize () { 
    22712358    // DWT: itemize is the process of finding changes in direction 
    2272     segmentsText = getSegmentsText(); 
     2359    getSegmentsText(segmentsText, segmentsWText ); 
    22732360    int length = segmentsText.length; 
    22742361    SCRIPT_CONTROL scriptControl; 
     
    22882375    if (pItems is null) DWT.error(DWT.ERROR_NO_HANDLES); 
    22892376    int pcItems; 
    2290     wchar[] chars = StrToWCHARs( segmentsText )
     2377    wchar[] chars = segmentsWText
    22912378    OS.ScriptItemize(chars.ptr, chars.length, MAX_ITEM, &scriptControl, &scriptState, pItems, &pcItems); 
    22922379//  if (hr is E_OUTOFMEMORY) //TODO handle it 
    22932380    // DWT pcItems is not inclusive the trailing item 
    2294  
    2295     // Translate the utf16 indices to utf8 indices 
    2296     int utf8idx = 0; 
    2297     int utf16idx = 0; 
    2298     int i = 0; 
    2299     SCRIPT_ITEM* si = pItems; 
    2300     while( utf16idx < chars.length ){ 
    2301  
    2302         if( si.iCharPos is utf16idx ){ 
    2303             si.iCharPos = utf8idx; 
    2304             i++; 
    2305             si++; 
    2306         } 
    2307  
    2308         // goto next codepoint 
    2309         uint ate16; 
    2310         dchar[1] buf32; 
    2311         dchar[] res32 = Utf.toString32( chars[ utf16idx .. $ ], buf32, &ate16 ); 
    2312         uint ate32; 
    2313         char[4] buf8; 
    2314         char[] res8 = Utf.toString( res32, buf8, &ate32 ); 
    2315         utf16idx += ate16; 
    2316         utf8idx += res8.length; 
    2317     } 
    2318     assert( si.iCharPos is chars.length ); 
    2319     si.iCharPos = utf8idx; 
    2320     assert( si.iCharPos is segmentsText.length ); 
    2321     assert( i is pcItems ); 
    23222381 
    23232382    StyleItem[] runs = merge(pItems, pcItems); 
     
    23522411        //scriptItem.a = new SCRIPT_ANALYSIS(); 
    23532412        scriptItem = items + (itemIndex + 1); 
    2354         int itemLimit = scriptItem.iCharPos
     2413        int itemLimit = index16to8[scriptItem.iCharPos]
    23552414        int styleLimit = translateOffset(styles[styleIndex + 1].start); 
    23562415        if (styleLimit <= itemLimit) { 
     
    23582417            start = styleLimit; 
    23592418            if (start < itemLimit && 0 < start && start < end) { 
    2360                 char pChar = segmentsText.charAt(start - 1); 
    2361                 char tChar = segmentsText.charAt(start); 
     2419                dchar pChar = segmentsText[ segmentsText.getAbsoluteCodePointOffset(start, -1) ..$].firstCodePoint(); 
     2420                dchar tChar = segmentsText[start     ..$].firstCodePoint(); 
    23622421                if (Compatibility.isLetter(pChar) && Compatibility.isLetter(tChar)) { 
    23632422                    item.analysis.fLinkAfter = true; 
     
    26212680    } 
    26222681    freeRuns(); 
    2623     this.segments = segments; 
     2682    this.segments  = segments.dup; 
     2683 
     2684    // DWT: create the wsegments ... 
     2685    this.wsegments.length = segments.length; 
     2686    uint index8, index16; 
     2687    uint segIndex = 1; 
     2688    while(index8 < text.length ){ 
     2689        int ate8; 
     2690        int ate16; 
     2691        dchar d8 = text[ index8 .. $ ].firstCodePoint( ate8 ); 
     2692        dchar d16 = wtext[ index16 .. $ ].firstCodePoint( ate16 ); 
     2693        assert( d8 is d16 ); 
     2694        assert( ate8 > 0 ); 
     2695        assert( ate16 > 0 ); 
     2696        index8 += ate8; 
     2697        index16 += ate16; 
     2698        if( segments[segIndex] is index8 ){ 
     2699            wsegments[segIndex] = index16; 
     2700        } 
     2701    } 
     2702    assert( index16 is wtext.length ); 
     2703    assert( segIndex is segments.length ); 
    26242704} 
    26252705 
     
    27842864    if (text.equals(this.text)) return; 
    27852865    freeRuns(); 
    2786     this.text = text; 
     2866    this.text  = text.dup; 
     2867    this.wtext = StrToWCHARs(text); 
    27872868    styles = new StyleItem[2]; 
    27882869    styles[0] = new StyleItem(); 
     
    28172898 
    28182899bool shape (HDC hdc, StyleItem run, wchar[] wchars, int[] glyphCount, int maxGlyphs, SCRIPT_PROPERTIES* sp) { 
    2819     //wchar[] wchars = StrToWCHARs( chars ); 
    28202900    bool useCMAPcheck = !sp.fComplex && !run.analysis.fNoGlyphIndex; 
    28212901    if (useCMAPcheck) { 
    28222902        ushort[] glyphs = new ushort[wchars.length]; 
    2823         scope(exit) delete glyphs; 
    28242903        if (OS.ScriptGetCMap(hdc, run.psc, wchars.ptr, wchars.length, 0, glyphs.ptr) !is OS.S_OK) { 
    28252904            if (run.psc !is null) { 
    28262905                OS.ScriptFreeCache(run.psc); 
    28272906                glyphCount[0] = 0; 
    2828                 *cast(int*)run.psc = 1; 
     2907                int[1] one = 1; 
     2908        //        OS.MoveMemory( run.psc, one.ptr, (void*).sizeof ); 
     2909        // DWT: FIXME This should be checked, it works in Java with the MoveMemory 
    28292910            } 
    28302911            return false; 
    28312912        } 
     2913        //delete glyphs; 
    28322914    } 
    28332915    auto hr = OS.ScriptShape(hdc, run.psc, wchars.ptr, wchars.length, maxGlyphs, &run.analysis, run.glyphs, run.clusters, run.visAttrs, glyphCount.ptr); 
     
    28502932        OS.ScriptFreeCache(run.psc); 
    28512933        glyphCount[0] = 0; 
    2852         *cast(int*)run.psc = 0; 
     2934        int[1] one = 1; 
     2935        OS.MoveMemory( run.psc, one.ptr, (void*).sizeof ); 
    28532936    } 
    28542937    run.glyphCount = 0; 
     
    28562939} 
    28572940 
    2858 struct CallbackDataEnumFontFamExProc { 
    2859     int delegate ( ENUMLOGFONTEX* lpelfe, NEWTEXTMETRICEX* lpntme, int FontType, int lParam) EnumFontFamExProc; 
    2860     int lParam; 
    2861 } 
    2862 extern(Windows) private static int EnumFontFamExProcFunc( ENUMLOGFONTEX* lpelfe, NEWTEXTMETRICEX* lpntme, int FontType, int lParam) { 
    2863     auto cb = cast(CallbackDataEnumFontFamExProc*)cast(void*)lParam; 
    2864     return cb.EnumFontFamExProc( lpelfe, lpntme, FontType, cb.lParam ); 
    2865 } 
    28662941 
    28672942/* 
     
    28702945void shape (HDC hdc, StyleItem run) { 
    28712946    int[1] buffer; 
    2872     char[] chars = new char[run.length]; 
    2873     segmentsText.getChars(run.start, run.start + run.length, chars, 0); 
    2874     wchar[] wchars = StrToWCHARs( chars ); 
     2947    wchar[] wchars = segmentsWText[ index8to16[ run.start ] .. index8to16[ run.start + run.length ] ]; 
    28752948    int maxGlyphs = (wchars.length * 3 / 2) + 16; 
    28762949    auto hHeap = OS.GetProcessHeap(); 
     
    28842957    if (run.psc is null) DWT.error(DWT.ERROR_NO_HANDLES); 
    28852958    short script = run.analysis.eScript; 
    2886     auto sp = device.scripts[script]; 
    2887     bool shapeSucceed = shape(hdc, run, wchars, buffer,  maxGlyphs, sp); 
     2959    SCRIPT_PROPERTIES sp = *device.scripts[script]; 
     2960    bool shapeSucceed = shape(hdc, run, wchars, buffer,  maxGlyphs, &sp); 
     2961int res; 
    28882962    if (!shapeSucceed) { 
    28892963        auto hFont = OS.GetCurrentObject(hdc, OS.OBJ_FONT); 
     
    28932967        int flags = OS.SSA_METAFILE | OS.SSA_FALLBACK | OS.SSA_GLYPHS | OS.SSA_LINK; 
    28942968        if (OS.ScriptStringAnalyse(metaFileDc, wchars.ptr, wchars.length, 0, -1, flags, 0, null, null, null, null, null, ssa) is OS.S_OK) { 
    2895             OS.ScriptStringOut(ssa, 0, 0, 0, null, 0, 0, false); 
     2969            OS.ScriptStringOut(*ssa, 0, 0, 0, null, 0, 0, false); 
    28962970            OS.ScriptStringFree(ssa); 
    28972971        } 
     
    28992973        OS.SelectObject(metaFileDc, oldMetaFont); 
    29002974        auto metaFile = OS.CloseEnhMetaFile(metaFileDc); 
    2901         EMREXTCREATEFONTINDIRECTW emr; 
    29022975        static extern(Windows) int metaFileEnumProc (HDC hDC, HANDLETABLE* table, ENHMETARECORD* record, int nObj, LPARAM lpData) { 
    2903             EMREXTCREATEFONTINDIRECTW* emr_
     2976            EMREXTCREATEFONTINDIRECTW* emr_ = cast(EMREXTCREATEFONTINDIRECTW*)lpData
    29042977            OS.MoveMemory(&emr_.emr, record, EMR.sizeof); 
    29052978            switch (emr_.emr.iType) { 
     
    29092982                case OS.EMR_EXTTEXTOUTW: 
    29102983                    return 0; 
     2984                default: 
    29112985            } 
    29122986            return 1; 
    29132987        } 
     2988 
     2989        EMREXTCREATEFONTINDIRECTW emr; 
    29142990        OS.EnumEnhMetaFile(null, metaFile, &metaFileEnumProc, &emr, null); 
    2915         OS.DeleteEnhMetaFile(metaFile); 
     2991        res = OS.DeleteEnhMetaFile(metaFile); 
     2992        assert( res !is 0 ); 
    29162993 
    29172994        auto newFont = OS.CreateFontIndirectW(&emr.elfw.elfLogFont); 
     2995        assert( newFont !is null ); 
     2996 
    29182997        OS.SelectObject(hdc, newFont); 
    2919         if ((shapeSucceed = shape(hdc, run, wchars, buffer,  maxGlyphs, sp)) is true ) { 
     2998        if ((shapeSucceed = shape(hdc, run, wchars, buffer,  maxGlyphs, &sp)) is true ) { 
    29202999            run.fallbackFont = newFont; 
    29213000        } 
     
    29233002            if (!sp.fComplex) { 
    29243003                run.analysis.fNoGlyphIndex = true; 
    2925                 if ((shapeSucceed = shape(hdc, run, wchars, buffer,  maxGlyphs, sp)) is true ) { 
     3004                if ((shapeSucceed = shape(hdc, run, wchars, buffer,  maxGlyphs, &sp)) is true ) { 
    29263005                    run.fallbackFont = newFont; 
    29273006                } else { 
     
    29313010        } 
    29323011        if (!shapeSucceed) { 
    2933         if (mLangFontLink2 !is null) { 
    2934             HANDLE hNewFont; 
    2935             int dwCodePages, cchCodePages; 
     3012            if (mLangFontLink2 !is null) { 
     3013                HANDLE hNewFont; 
     3014                int dwCodePages, cchCodePages; 
    29363015                /* GetStrCodePages() */ 
    2937             OS.VtblCall(4, mLangFontLink2, cast(int)wchars.ptr, wchars.length, 0, cast(int)&dwCodePages, cast(int)&cchCodePages); 
     3016                OS.VtblCall(4, mLangFontLink2, cast(int)wchars.ptr, wchars.length, 0, cast(int)&dwCodePages, cast(int)&cchCodePages); 
    29383017                /* MapFont() */ 
    2939             if (OS.VtblCall(10, mLangFontLink2, cast(int)hdc, dwCodePages, cast(int)wchars[0], cast(int)&hNewFont) is OS.S_OK) { 
     3018                if (OS.VtblCall(10, mLangFontLink2, cast(int)hdc, dwCodePages, cast(int)wchars[0], cast(int)&hNewFont) is OS.S_OK) { 
    29403019                    LOGFONT logFont; 
    29413020                    OS.GetObject( hNewFont, LOGFONT.sizeof, &logFont ); 
     
    29443023                    auto mLangFont = OS.CreateFontIndirect(&logFont); 
    29453024                    auto oldFont = OS.SelectObject(hdc, mLangFont); 
    2946                     if ((shapeSucceed = shape(hdc, run, wchars, buffer,  maxGlyphs, sp)) is true ) { 
     3025                    if ((shapeSucceed = shape(hdc, run, wchars, buffer,  maxGlyphs, &sp)) is true ) { 
    29473026                        run.fallbackFont = mLangFont; 
    29483027                    } else { 
     
    29633042        * Missing glyphs typically will be represent as black boxes in the text. 
    29643043        */ 
    2965         auto wchars_ = StrToWCHARs(chars); 
    2966         OS.ScriptShape(hdc, run.psc, wchars_.ptr, wchars_.length, maxGlyphs, &run.analysis, run.glyphs, run.clusters, run.visAttrs, buffer.ptr); 
     3044        OS.ScriptShape(hdc, run.psc, wchars.ptr, wchars.length, maxGlyphs, &run.analysis, run.glyphs, run.clusters, run.visAttrs, buffer.ptr); 
    29673045        run.glyphCount = buffer[0]; 
    29683046    }