public static SCRIPT_TABDEF GetDefault() { var ret = new SCRIPT_TABDEF(); ret.cTabStops = 0; ret.iScale = 0; ret.pTabStops = IntPtr.Zero; ret.iTabOrigin = 4; return(ret); }
public static extern int ScriptStringAnalyse (IntPtr hdc, IntPtr pString, int cString, int cGlyphs, int iCharset, ScripStringAnalyseOptions dwFlags, int iReqWidth, IntPtr psControl, //SCRIPT_CONTROL* IntPtr psState, //SCRIPT_STATE* IntPtr piDx, // const int* ref SCRIPT_TABDEF pTabdef, IntPtr pbInClass, //const BYTE* ref IntPtr pssa //SCRIPT_STRING_ANALYSIS* );
public static IntPtr ScriptStringAnalyseCall (IntPtr hdc, IntPtr char_buffer, int max_char_len, int max_width, SCRIPT_TABDEF tab_def) { var ret = IntPtr.Zero; var actual_buf = char_buffer; var opts = ScripStringAnalyseOptions.BREAK | ScripStringAnalyseOptions.CLIP | //ScripStringAnalyseOptions.FALLBACK | -> это вызывает утечку, не освобождаются объекты gdi font ScripStringAnalyseOptions.GLYPHS | //ScripStringAnalyseOptions.LINK | ScripStringAnalyseOptions.TAB; var res0 = ScriptStringAnalyse (hdc, actual_buf, max_char_len, (int)((max_char_len * 1.5) + 16), -1, opts, max_width, IntPtr.Zero, IntPtr.Zero, IntPtr.Zero, ref tab_def, IntPtr.Zero, ref ret); if (res0 != S_OK) { Marshal.ThrowExceptionForHR(res0); } return(ret); }
public int FindPreviousLineStart(IDeviceContext dev) { //для обсчета строки будет нужен контекст IntPtr hdc = dev.GetHdc(); IntPtr font_ptr = Font.ToHfont(); IntPtr old_font = NativeGdi.SelectObject(hdc, font_ptr); uint old_align = NativeGdi.SetTextAlign(hdc, 0); int line_height = (int)Math.Ceiling(Font.GetHeight()); IntPtr char_buffer = IntPtr.Zero; bool EOF = false; int chars_filled = 0; int ret = 0; //получаем буфер символов начиная от -max_chars_in_line OnFetchCharsToScreen (-max_chars_in_line, false, out char_buffer, out chars_filled, out EOF); if (chars_filled <= 0) { //то есть и так находимся в начале ret = 0; } else { //получаем ssa_sctruct IntPtr ssa_scruct = NativeScript.ScriptStringAnalyseCall (hdc, char_buffer, chars_filled, SCRIPT_TABDEF.GetDefault()); //берем logical wodths int[] widths = NativeScript.GetLogicalWidths(ssa_scruct); //освобождаем ssa_scruct NativeScript.ScriptStringFree(ref ssa_scruct); //суммируем полученные ширины символов с конца, пока не превысим //максимальную ширину или не встретим второй hard break char current_char = '\0'; int current_width = 0; int finding_ind = -1; for (int i = chars_filled - 1; i >= 0; i--) { current_char = get_char_from_buffer(char_buffer, i); current_width = current_width + widths[i]; //проверяем ширину if (current_width > Bounds.Width) { finding_ind = i; break; } //проверяем hard break (\n \r \r\n) начиная со второго шага if (i != chars_filled - 1) { if (current_char == '\n') { if (((i - 1) >= 0) && (get_char_from_buffer(char_buffer, i - 1) == '\r')) { finding_ind = i; break; } finding_ind = i; break; } else if ((current_char == '\r') && (i < chars_filled - 2)) { finding_ind = i; break; } } } //finding_ind теперь соответствует концу предыщей строки ret = -(chars_filled - finding_ind - 1); } font_ptr = NativeGdi.SelectObject(hdc, old_font); NativeGdi.DeleteObject(font_ptr); NativeGdi.SetTextAlign(hdc, old_align); dev.ReleaseHdc(); return(ret); }