private static void ScriptBreak(ScriptParagraph* scriptParagraph, char* chars, SCRIPT_ITEM* scriptItems, int scriptItemCount) { SCRIPT_ITEM* scriptItem = scriptItems; SCRIPT_ITEM* endScriptItem = scriptItems + scriptItemCount; SCRIPT_LOGATTR* logicalAttributes = scriptParagraph->CharLogicalAttributes; for (; scriptItem != endScriptItem; scriptItem++) { int scriptItemCharPos = scriptItem->iCharPos; int nextScriptItemCharPos = (scriptItem + 1)->iCharPos; int scriptItemCharCount = nextScriptItemCharPos - scriptItemCharPos; char* scriptItemChars = chars + scriptItemCharPos; int result = NativeMethods.ScriptBreak(scriptItemChars, scriptItemCharCount, &scriptItem->a, logicalAttributes); if (result != 0) Marshal.ThrowExceptionForHR(result); logicalAttributes += scriptItemCharCount; } }
private static void SplitScriptRuns(ScriptParagraph* scriptParagraph, Run* runs, int runCount, SCRIPT_ITEM* scriptItems, int scriptItemCount) { // Reserve space for the largest possible number of script runs. int maxScriptRuns = runCount + scriptItemCount; scriptParagraph->EnsureScriptRunCapacity(maxScriptRuns); // Merge Runs and SCRIPT_ITEMs to create ScriptRuns. Run* run = runs; int runStartCharIndex = 0; Run* endRun = runs + runCount; SCRIPT_ITEM* item = scriptItems; SCRIPT_ITEM* endItem = scriptItems + scriptItemCount; ScriptRun* startScriptRun = scriptParagraph->ScriptRuns; ScriptRun* scriptRun = startScriptRun; int currentCharIndex = 0; for (; ; scriptRun++) { int runEndCharIndex = runStartCharIndex + run->CharCount; int itemEndCharIndex = (item + 1)->iCharPos; if (itemEndCharIndex < runEndCharIndex) { scriptRun->Initialize(run, &item->a, currentCharIndex, itemEndCharIndex - currentCharIndex); currentCharIndex = itemEndCharIndex; item++; } else if (runEndCharIndex < itemEndCharIndex) { scriptRun->Initialize(run, &item->a, currentCharIndex, runEndCharIndex - currentCharIndex); runStartCharIndex = currentCharIndex = runEndCharIndex; run++; } else { scriptRun->Initialize(run, &item->a, currentCharIndex, runEndCharIndex - currentCharIndex); runStartCharIndex = currentCharIndex = runEndCharIndex; run++; item++; // All sequences of Runs and Items should always end on the same char so we only // need to check for termination here. if (run == endRun) { Debug.Assert(item == endItem, "Inconsistent Run and SCRIPT_ITEM sequences."); break; } } } scriptParagraph->ScriptRunCount = (int)(scriptRun - startScriptRun) + 1; }
private static void ScriptItemize(char* chars, int charCount, bool rightToLeft, UnmanagedBuffer tempScriptItemBuffer, out SCRIPT_ITEM* scriptItems, out int scriptItemCount) { var scriptControl = new SCRIPT_CONTROL(); var scriptState = new SCRIPT_STATE(); if (rightToLeft) { // Start in a RTL context. scriptState.uBidiLevel = 1; } for (; ; ) { scriptItems = (SCRIPT_ITEM*)tempScriptItemBuffer.GetPointer(); int result = NativeMethods.ScriptItemize(chars, charCount, tempScriptItemBuffer.Capacity - 1 /*itemize needs 1 extra item beyond capacity as a sentinel*/, &scriptControl, &scriptState, scriptItems, out scriptItemCount); if (result == NativeConstants.S_OK) return; if (result != NativeConstants.E_OUTOFMEMORY) Marshal.ThrowExceptionForHR(result); tempScriptItemBuffer.SetCapacity(tempScriptItemBuffer.Capacity * 2); } }