Changeset 278:3f53ebb05b5b
- Timestamp:
- 08/04/08 19:07:44
(4 months ago)
- Author:
- Frank Benoit <benoit@tionex.de>
- Children:
279:e4b7af6b8e7e 280:4ec36c3a04a3
- branch:
- default
- Message:
Fix: make MARK copy work correctly mit multiple chars.
Fix: getLocation, getOffset (codepoint vs. chars)
Fix: itemize() translation of utf16 to utf8 indices
-
Files:
-
Legend:
- Unmodified
- Added
- Removed
- Modified
- Copied
- Moved
| r249 |
r278 |
|
| 34 | 34 | |
|---|
| 35 | 35 | import tango.text.convert.Format; |
|---|
| | 36 | import Utf = tango.text.convert.Utf; |
|---|
| 36 | 37 | import dwt.dwthelper.utils; |
|---|
| 37 | 38 | import dwt.dwthelper.System; |
|---|
| … | … | |
| 93 | 94 | void* mLangFontLink2; |
|---|
| 94 | 95 | |
|---|
| 95 | | static const wchar LTR_MARK = '\u200E', RTL_MARK = '\u200F'; |
|---|
| | 96 | static const dchar LTR_MARK = '\u200E', RTL_MARK = '\u200F'; |
|---|
| | 97 | static const String STR_LTR_MARK = "\u200E", STR_RTL_MARK = "\u200F"; |
|---|
| | 98 | static const int MARK_SIZE = 3; |
|---|
| 96 | 99 | static const int SCRIPT_VISATTR_SIZEOF = 2; |
|---|
| 97 | 100 | static const int GOFFSET_SIZEOF = 8; |
|---|
| … | … | |
| 120 | 123 | class StyleItem { |
|---|
| 121 | 124 | TextStyle style; |
|---|
| | 125 | // DWT: start, lenght relative to segmentsText |
|---|
| 122 | 126 | int start, length; |
|---|
| 123 | 127 | bool lineBreak, softBreak, tab; |
|---|
| … | … | |
| 1792 | 1796 | width = (trailing || (offset is length)) ? run.width : 0; |
|---|
| 1793 | 1797 | } else { |
|---|
| 1794 | | int runOffset = offset - run.start; |
|---|
| | 1798 | // DWT: runOffset now in codepoints |
|---|
| | 1799 | int runOffset = segmentsText[ run.start .. $ ].indexToCodepointIndex( offset - run.start ); |
|---|
| 1795 | 1800 | int cChars = run.length; |
|---|
| 1796 | 1801 | int gGlyphs = run.glyphCount; |
|---|
| … | … | |
| 1840 | 1845 | length = segmentsText.length; |
|---|
| 1841 | 1846 | offset = translateOffset(offset); |
|---|
| 1842 | | SCRIPT_LOGATTR* logAttr = new SCRIPT_LOGATTR(); |
|---|
| 1843 | | SCRIPT_PROPERTIES* properties = new SCRIPT_PROPERTIES(); |
|---|
| | 1847 | SCRIPT_LOGATTR* logAttr; |
|---|
| | 1848 | SCRIPT_PROPERTIES* properties; |
|---|
| 1844 | 1849 | int i = forward ? 0 : allRuns.length - 1; |
|---|
| 1845 | 1850 | offset = validadeOffset(offset, step); |
|---|
| … | … | |
| 1849 | 1854 | if (run.lineBreak && !run.softBreak) return untranslateOffset(run.start); |
|---|
| 1850 | 1855 | if (run.tab) return untranslateOffset(run.start); |
|---|
| 1851 | | OS.MoveMemory(properties, device.scripts[run.analysis.eScript], SCRIPT_PROPERTIES.sizeof); |
|---|
| | 1856 | properties = device.scripts[run.analysis.eScript]; |
|---|
| 1852 | 1857 | bool isComplex = properties.fNeedsCaretInfo || properties.fNeedsWordBreaking; |
|---|
| 1853 | 1858 | if (isComplex) breakRun(run); |
|---|
| 1854 | 1859 | while (run.start <= offset && offset < run.start + run.length) { |
|---|
| 1855 | 1860 | if (isComplex) { |
|---|
| 1856 | | OS.MoveMemory(logAttr, run.psla + (offset - run.start), SCRIPT_LOGATTR.sizeof); |
|---|
| | 1861 | logAttr = run.psla + (offset - run.start); |
|---|
| 1857 | 1862 | } |
|---|
| 1858 | 1863 | switch (movement) { |
|---|
| … | … | |
| 1958 | 1963 | computeRuns(null); |
|---|
| 1959 | 1964 | if (trailing !is null && trailing.length < 1) DWT.error(DWT.ERROR_INVALID_ARGUMENT); |
|---|
| | 1965 | |
|---|
| 1960 | 1966 | int line; |
|---|
| 1961 | 1967 | int lineCount = runs.length; |
|---|
| … | … | |
| 2003 | 2009 | OS.ScriptXtoCP(xRun, cChars, cGlyphs, run.clusters, run.visAttrs, advances, &run.analysis, &piCP, &piTrailing); |
|---|
| 2004 | 2010 | if (trailing !is null) trailing[0] = piTrailing; |
|---|
| 2005 | | return untranslateOffset(run.start + piCP); |
|---|
| | 2011 | |
|---|
| | 2012 | // DWT: back from codepoints to utf8 index |
|---|
| | 2013 | int offsetIndex = segmentsText[ run.start .. $ ].codepointIndexToIndex( piCP ); |
|---|
| | 2014 | return untranslateOffset(run.start + offsetIndex); |
|---|
| 2006 | 2015 | } |
|---|
| 2007 | 2016 | } |
|---|
| … | … | |
| 2105 | 2114 | char[] oldChars = new char[length_]; |
|---|
| 2106 | 2115 | text.getChars(0, length_, oldChars, 0); |
|---|
| 2107 | | char[] newChars = new char[length_ + nSegments]; |
|---|
| | 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]; |
|---|
| 2108 | 2120 | int charCount = 0, segmentCount = 0; |
|---|
| 2109 | | wchar separator = orientation is DWT.RIGHT_TO_LEFT ? RTL_MARK : LTR_MARK; |
|---|
| 2110 | 2121 | while (charCount < length_) { |
|---|
| 2111 | 2122 | if (segmentCount < nSegments && charCount is segments[segmentCount]) { |
|---|
| 2112 | | newChars[charCount + segmentCount++] = separator; |
|---|
| | 2123 | int start = charCount + (segmentCount*MARK_SIZE); |
|---|
| | 2124 | newChars[ start .. start + MARK_SIZE ] = separator; |
|---|
| | 2125 | segmentCount++; |
|---|
| 2113 | 2126 | } else { |
|---|
| 2114 | | newChars[charCount + segmentCount] = oldChars[charCount++]; |
|---|
| | 2127 | newChars[charCount + (segmentCount*MARK_SIZE)] = oldChars[charCount]; |
|---|
| | 2128 | charCount++; |
|---|
| 2115 | 2129 | } |
|---|
| 2116 | 2130 | } |
|---|
| 2117 | 2131 | if (segmentCount < nSegments) { |
|---|
| 2118 | 2132 | segments[segmentCount] = charCount; |
|---|
| 2119 | | newChars[charCount + segmentCount++] = separator; |
|---|
| 2120 | | } |
|---|
| 2121 | | return newChars[ 0 .. Math.min(charCount + segmentCount, newChars.length)].dup; |
|---|
| | 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; |
|---|
| 2122 | 2138 | } |
|---|
| 2123 | 2139 | |
|---|
| … | … | |
| 2253 | 2269 | */ |
|---|
| 2254 | 2270 | StyleItem[] itemize () { |
|---|
| | 2271 | // DWT: itemize is the process of finding changes in direction |
|---|
| 2255 | 2272 | segmentsText = getSegmentsText(); |
|---|
| 2256 | 2273 | int length = segmentsText.length; |
|---|
| … | … | |
| 2274 | 2291 | OS.ScriptItemize(chars.ptr, chars.length, MAX_ITEM, &scriptControl, &scriptState, pItems, &pcItems); |
|---|
| 2275 | 2292 | // if (hr is E_OUTOFMEMORY) //TODO handle it |
|---|
| | 2293 | // DWT pcItems is not inclusive the trailing item |
|---|
| 2276 | 2294 | |
|---|
| 2277 | 2295 | // Translate the utf16 indices to utf8 indices |
|---|
| 2278 | 2296 | int utf8idx = 0; |
|---|
| | 2297 | int utf16idx = 0; |
|---|
| | 2298 | int i = 0; |
|---|
| 2279 | 2299 | SCRIPT_ITEM* si = pItems; |
|---|
| 2280 | | foreach( uint utf16idx, char c; chars ){ |
|---|
| | 2300 | while( utf16idx < chars.length ){ |
|---|
| | 2301 | |
|---|
| 2281 | 2302 | if( si.iCharPos is utf16idx ){ |
|---|
| 2282 | 2303 | si.iCharPos = utf8idx; |
|---|
| | 2304 | i++; |
|---|
| 2283 | 2305 | si++; |
|---|
| 2284 | 2306 | } |
|---|
| 2285 | | utf8idx++; |
|---|
| 2286 | | } |
|---|
| | 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 ); |
|---|
| 2287 | 2322 | |
|---|
| 2288 | 2323 | StyleItem[] runs = merge(pItems, pcItems); |
|---|
| … | … | |
| 2302 | 2337 | int count = 0, start = 0, end = segmentsText.length, itemIndex = 0, styleIndex = 0; |
|---|
| 2303 | 2338 | StyleItem[] runs = new StyleItem[itemCount + stylesCount]; |
|---|
| 2304 | | SCRIPT_ITEM* scriptItem = new SCRIPT_ITEM(); |
|---|
| | 2339 | SCRIPT_ITEM* scriptItem; |
|---|
| 2305 | 2340 | bool linkBefore = false; |
|---|
| 2306 | 2341 | while (start < end) { |
|---|
| … | … | |
| 2309 | 2344 | item.style = styles[styleIndex].style; |
|---|
| 2310 | 2345 | runs[count++] = item; |
|---|
| 2311 | | OS.MoveMemory(scriptItem, (cast(void*)items) + itemIndex * SCRIPT_ITEM.sizeof, SCRIPT_ITEM.sizeof); |
|---|
| | 2346 | scriptItem = items + itemIndex; |
|---|
| 2312 | 2347 | item.analysis = scriptItem.a; |
|---|
| 2313 | 2348 | if (linkBefore) { |
|---|
| … | … | |
| 2316 | 2351 | } |
|---|
| 2317 | 2352 | //scriptItem.a = new SCRIPT_ANALYSIS(); |
|---|
| 2318 | | OS.MoveMemory(scriptItem, (cast(void*)items) + (itemIndex + 1) * SCRIPT_ITEM.sizeof, SCRIPT_ITEM.sizeof); |
|---|
| | 2353 | scriptItem = items + (itemIndex + 1); |
|---|
| 2319 | 2354 | int itemLimit = scriptItem.iCharPos; |
|---|
| 2320 | 2355 | int styleLimit = translateOffset(styles[styleIndex + 1].start); |
|---|
| … | … | |
| 2339 | 2374 | StyleItem item = new StyleItem(); |
|---|
| 2340 | 2375 | item.start = end; |
|---|
| 2341 | | OS.MoveMemory(scriptItem, (cast(void*)items) + itemCount * SCRIPT_ITEM.sizeof, SCRIPT_ITEM.sizeof); |
|---|
| | 2376 | scriptItem = items + itemCount; |
|---|
| 2342 | 2377 | item.analysis = scriptItem.a; |
|---|
| 2343 | 2378 | runs[count++] = item; |
|---|
| … | … | |
| 2834 | 2869 | */ |
|---|
| 2835 | 2870 | void shape (HDC hdc, StyleItem run) { |
|---|
| 2836 | | final int[] buffer = new int[1]; |
|---|
| 2837 | | final char[] chars = new char[run.length]; |
|---|
| | 2871 | int[1] buffer; |
|---|
| | 2872 | char[] chars = new char[run.length]; |
|---|
| 2838 | 2873 | segmentsText.getChars(run.start, run.start + run.length, chars, 0); |
|---|
| 2839 | 2874 | wchar[] wchars = StrToWCHARs( chars ); |
|---|
| … | … | |
| 2994 | 3029 | |
|---|
| 2995 | 3030 | int validadeOffset(int offset, int step) { |
|---|
| 2996 | | offset += step; |
|---|
| | 3031 | offset += segmentsText.getRelativeCodePointOffset( offset, step ); |
|---|
| 2997 | 3032 | if (segments !is null && segments.length > 2) { |
|---|
| 2998 | 3033 | for (int i = 0; i < segments.length; i++) { |
|---|
| … | … | |
| 3027 | 3062 | } |
|---|
| 3028 | 3063 | for (int i = 0; i < nSegments && offset - i >= segments[i]; i++) { |
|---|
| 3029 | | offset++; |
|---|
| | 3064 | offset+=MARK_SIZE; |
|---|
| 3030 | 3065 | } |
|---|
| 3031 | 3066 | return offset; |
|---|
| … | … | |
| 3042 | 3077 | } |
|---|
| 3043 | 3078 | for (int i = 0; i < nSegments && offset > segments[i]; i++) { |
|---|
| 3044 | | offset--; |
|---|
| | 3079 | offset-=MARK_SIZE; |
|---|
| 3045 | 3080 | } |
|---|
| 3046 | 3081 | return offset; |
|---|