// Decompiled with JetBrains decompiler // Type: Microsoft.Iris.Drawing.RichText // Assembly: UIX, Version=4.8.0.0, Culture=neutral, PublicKeyToken=ddd0da4d3e678217 // MVID: A56C6C9D-B7F6-46A9-8BDE-B3D9B8D60B11 // Assembly location: C:\Program Files\Zune\UIX.dll using Microsoft.Iris.OS; using Microsoft.Iris.Render; using Microsoft.Iris.RenderAPI; using Microsoft.Iris.RenderAPI.Drawing; using Microsoft.Iris.Session; using Microsoft.Iris.ViewItems; using System; using System.Collections; using System.Runtime.InteropServices; using System.Text; namespace Microsoft.Iris.Drawing { internal sealed class RichText : IDisposable { public const float MaxWidthConstraint = 4095f; public const float MaxHeightConstraint = 8191f; private Win32Api.HANDLE _rtoHandle; private NativeApi.ReportRunCallback _rrcb; private string _currentlyMeasuringText; private bool _oversampled; private bool _hosted; private bool _inImeCompositionMode; private ArrayList _timers; private EventHandler _timerTickHandler; private object _lock; public RichText(bool richTextMode) : this(richTextMode, null) { } public unsafe RichText(bool richTextMode, IRichTextCallbacks callbacks) { Size sizeMaximumSurface = Size.Zero; if (UISession.Default != null) sizeMaximumSurface = UIImage.MaximumSurfaceSize(UISession.Default); if (callbacks != null) { _hosted = true; _timers = new ArrayList(6); _timerTickHandler = new EventHandler(OnTimerTick); } RendererApi.IFC(NativeApi.SpRichTextBuildObject(richTextMode, sizeMaximumSurface, callbacks, out _rtoHandle)); _oversampled = false; _lock = new object(); _rrcb = new NativeApi.ReportRunCallback(OnReportRun); } public void Dispose() => Dispose(true); private void Dispose(bool inDispose) { if (!inDispose) return; GC.SuppressFinalize(this); lock (_lock) { NativeApi.SpRichTextDestroyObject(_rtoHandle); _rtoHandle.h = IntPtr.Zero; } if (_timers == null) return; for (int index = 0; index < _timers.Count; ++index) DisposeTimer((DispatcherTimer)_timers[index]); _timers.Clear(); } ~RichText() => Dispose(false); public string Content { set { lock (_lock) RendererApi.IFC(NativeApi.SpRichTextSetContent(_rtoHandle, value)); } } public string SimpleContent { get { string str = null; int textLength = 0; lock (_lock) { RendererApi.IFC(NativeApi.SpRichTextGetSimpleContentLength(_rtoHandle, out textLength)); if (textLength != 0) { StringBuilder textBuffer = new StringBuilder(textLength); RendererApi.IFC(NativeApi.SpRichTextGetSimpleContent(_rtoHandle, textBuffer, textBuffer.Capacity)); str = textBuffer.ToString(); } } return str; } } public bool Oversample { set { if (_oversampled == value) return; lock (_lock) RendererApi.IFC(NativeApi.SpRichTextSetOversampleMode(_rtoHandle, value)); _oversampled = value; } get => _oversampled; } public int MaxLength { set { lock (_lock) RendererApi.IFC(NativeApi.SpRichTextSetMaximumLength(_rtoHandle, value)); } } public bool DetectUrls { set { lock (_lock) RendererApi.IFC(NativeApi.SpRichTextSetDetectUrls(_rtoHandle, value)); } } public bool HasCallbacks => _hosted; public bool ReadOnly { set { lock (_lock) RendererApi.IFC(NativeApi.SpRichTextSetReadOnly(_rtoHandle, value)); } } public void SetWordWrap(bool wordWrap) { lock (_lock) RendererApi.IFC(NativeApi.SpRichTextSetWordWrap(_rtoHandle, wordWrap)); } public Size GetNaturalBounds() { int cWidth; int cHeight; lock (_lock) RendererApi.IFC(NativeApi.SpRichTextGetNaturalBounds(_rtoHandle, out cWidth, out cHeight)); return new Size(cWidth, cHeight); } public void SetSelectionRange(int selectionStart, int selectionEnd) { lock (_lock) RendererApi.IFC(NativeApi.SpRichTextSetSelectionRange(_rtoHandle, selectionStart, selectionEnd)); } public unsafe TextFlow Measure(string content, ref TextMeasureParams measureParams) { TextFlow textFlow = new TextFlow(); GCHandle gcHandle = GCHandle.Alloc(textFlow); _currentlyMeasuringText = content != null ? content : string.Empty; fixed (char* content1 = _currentlyMeasuringText) fixed (char* chPtr = measureParams._textStyle.TruncatedFontFace) { var style = new TextStyle.MarshalledData(measureParams._textStyle) { _fontFace = chPtr }; measureParams.SetContent(content1); measureParams._data._pTextStyle = &style; fixed (TextMeasureParams.FormattedRange* formattedRangePtr = measureParams._formattedRanges) { measureParams._data._pFormattedRanges = formattedRangePtr; fixed (TextStyle.MarshalledData* marshalledDataPtr = measureParams._formattedRangeStyles) { measureParams._data._pFormattedRangeStyles = marshalledDataPtr; lock (_lock) RendererApi.IFC(NativeApi.SpRichTextMeasure(_rtoHandle, ref measureParams._data, _rrcb, GCHandle.ToIntPtr(gcHandle))); } } } gcHandle.Free(); _currentlyMeasuringText = null; return textFlow; } public void NotifyOfFocusChange(bool gainingFocus) { lock (_lock) { RendererApi.IFC(NativeApi.SpRichTextSetFocus(_rtoHandle, gainingFocus)); if (gainingFocus) return; _inImeCompositionMode = false; } } public void ScrollUp(ScrollbarType whichBar) { lock (_lock) RendererApi.IFC(NativeApi.SpRichTextScroll(_rtoHandle, (int)whichBar, 0)); } public void ScrollDown(ScrollbarType whichBar) { lock (_lock) RendererApi.IFC(NativeApi.SpRichTextScroll(_rtoHandle, (int)whichBar, 1)); } public void PageUp(ScrollbarType whichBar) { lock (_lock) RendererApi.IFC(NativeApi.SpRichTextScroll(_rtoHandle, (int)whichBar, 2)); } public void PageDown(ScrollbarType whichBar) { lock (_lock) RendererApi.IFC(NativeApi.SpRichTextScroll(_rtoHandle, (int)whichBar, 3)); } public void ScrollToPosition(ScrollbarType whichBar, int whereTo) { lock (_lock) RendererApi.IFC(NativeApi.SpRichTextScrollToPosition(_rtoHandle, (int)whichBar, whereTo)); } public void SetScrollbars(bool horizontalScrollbar, bool verticalScrollbar) { lock (_lock) RendererApi.IFC(NativeApi.SpRichTextSetScrollbars(_rtoHandle, horizontalScrollbar, verticalScrollbar)); } public bool ForwardKeyStateNotification( uint message, int virtualKey, int scanCode, int repeatCount, uint modifierState, ushort flags) { bool handled = true; lock (_lock) { if (!_inImeCompositionMode) RendererApi.IFC(NativeApi.SpRichTextForwardKeyState(_rtoHandle, message, virtualKey, scanCode, repeatCount, modifierState, flags, out handled)); } return handled; } public bool ForwardKeyCharacterNotification( uint message, int character, int scanCode, int repeatCount, uint modifierState, ushort flags) { bool handled = true; lock (_lock) { if (!_inImeCompositionMode) RendererApi.IFC(NativeApi.SpRichTextForwardKeyCharacter(_rtoHandle, message, character, scanCode, repeatCount, modifierState, flags, out handled)); } return handled; } public bool ForwardMouseInput( uint message, uint modifierState, int mouseButton, int x, int y, int mouseWheelDelta) { bool handled = true; lock (_lock) { if (!_inImeCompositionMode) RendererApi.IFC(NativeApi.SpRichTextForwardMouseInput(_rtoHandle, message, modifierState, mouseButton, x, y, mouseWheelDelta, out handled)); } return handled; } public HRESULT ForwardImeMessage(uint message, UIntPtr wParam, UIntPtr lParam) { lock (_lock) { switch (message) { case 269: _inImeCompositionMode = true; break; case 270: _inImeCompositionMode = false; break; } RendererApi.IFC(NativeApi.SpRichTextForwardImeMessage(_rtoHandle, message, wParam, lParam)); } return new HRESULT(0); } public bool CanUndo { get { bool canUndo; lock (_lock) RendererApi.IFC(NativeApi.SpRichTextCanUndo(_rtoHandle, out canUndo)); return canUndo; } } public void Undo() { lock (_lock) RendererApi.IFC(NativeApi.SpRichTextUndo(_rtoHandle)); } public void Cut() { lock (_lock) RendererApi.IFC(NativeApi.SpRichTextCut(_rtoHandle)); } public void Copy() { lock (_lock) RendererApi.IFC(NativeApi.SpRichTextCopy(_rtoHandle)); } public void Paste() { lock (_lock) RendererApi.IFC(NativeApi.SpRichTextPaste(_rtoHandle)); } public void Delete() { lock (_lock) RendererApi.IFC(NativeApi.SpRichTextDelete(_rtoHandle)); } public static LineAlignment ReverseAlignment( LineAlignment alignment, bool condition) { if (condition) { switch (alignment) { case LineAlignment.Near: alignment = LineAlignment.Far; break; case LineAlignment.Far: alignment = LineAlignment.Near; break; } } return alignment; } internal static Dib Rasterize( IntPtr hGlyphRunInfo, bool outlineMode, Color textColor, bool shadowMode) { IntPtr phTextBitmap = IntPtr.Zero; IntPtr ppvBits; Size psizeBitmap; RendererApi.IFC(NativeApi.SpRichTextRasterize(hGlyphRunInfo, outlineMode ? 1 : 0, textColor, shadowMode ? 1 : 0, out phTextBitmap, out ppvBits, out psizeBitmap)); return new Dib(phTextBitmap, ppvBits, psizeBitmap); } public void SetTimer(uint id, uint timeout) { DispatcherTimer dispatcherTimer = FindTimer(id); if (dispatcherTimer == null) { dispatcherTimer = new DispatcherTimer(); _timers.Add(dispatcherTimer); } dispatcherTimer.UserData = id; dispatcherTimer.Interval = (int)timeout; dispatcherTimer.Tick += _timerTickHandler; dispatcherTimer.Start(); } public void KillTimer(uint id) { DispatcherTimer timer = FindTimer(id); if (timer == null) return; DisposeTimer(timer); _timers.Remove(timer); } private DispatcherTimer FindTimer(uint id) { for (int index = 0; index < _timers.Count; ++index) { DispatcherTimer timer = (DispatcherTimer)_timers[index]; if ((int)(uint)timer.UserData == (int)id) return timer; } return null; } private void DisposeTimer(DispatcherTimer timer) { timer.Tick -= _timerTickHandler; timer.Stop(); } private void OnTimerTick(object sender, EventArgs ea) { DispatcherTimer dispatcherTimer = (DispatcherTimer)sender; lock (_lock) RendererApi.IFC(NativeApi.SpRichTextOnTimerTick(_rtoHandle, (uint)dispatcherTimer.UserData)); } private unsafe HRESULT OnReportRun( IntPtr hGlyphRunInfo, NativeApi.RasterizeRunPacket* runPacketPtr, IntPtr lpString, uint nChars, IntPtr dataPtr) { bool flag = false; if (_currentlyMeasuringText != null && _currentlyMeasuringText.Length == nChars) { flag = true; char* pointer = (char*)lpString.ToPointer(); for (int index = 0; index < nChars; ++index) { if (_currentlyMeasuringText[index] != pointer[index]) { flag = false; break; } } } string content = flag ? _currentlyMeasuringText : Marshal.PtrToStringUni(lpString, (int)nChars); TextRun run = TextRun.FromRunPacket(hGlyphRunInfo, runPacketPtr, content); if (run != null) ((TextFlow)GCHandle.FromIntPtr(dataPtr).Target).Add(run); return new HRESULT(0); } } }